5 * Contains \Drupal\Console\Command\ContainerDebugCommand.
8 namespace Drupal\Console\Command;
10 use Symfony\Component\Console\Input\InputInterface;
11 use Symfony\Component\Console\Output\OutputInterface;
12 use Symfony\Component\Console\Input\InputArgument;
13 use Symfony\Component\Console\Input\InputOption;
14 use Symfony\Component\Console\Command\Command;
15 use Symfony\Component\Yaml\Yaml;
16 use Drupal\Console\Core\Command\Shared\ContainerAwareCommandTrait;
17 use Drupal\Console\Core\Style\DrupalStyle;
20 * Class ContainerDebugCommand
22 * @package Drupal\Console\Command
24 class ContainerDebugCommand extends Command
26 use ContainerAwareCommandTrait;
31 protected function configure()
34 ->setName('container:debug')
35 ->setDescription($this->trans('commands.container.debug.description'))
39 InputOption::VALUE_NONE,
40 $this->trans('commands.container.debug.arguments.service')
44 InputArgument::OPTIONAL,
45 $this->trans('commands.container.debug.arguments.service')
48 InputArgument::OPTIONAL,
49 $this->trans('commands.container.debug.arguments.method')
52 InputArgument::OPTIONAL,
53 $this->trans('commands.container.debug.arguments.arguments')
60 protected function execute(InputInterface $input, OutputInterface $output)
62 $io = new DrupalStyle($input, $output);
63 $service = $input->getArgument('service');
64 $parameters = $input->getOption('parameters');
65 $method = $input->getArgument('method');
66 $args = $input->getArgument('arguments');
69 $parameterList = $this->getParameterList();
70 ksort($parameterList);
71 $io->write(Yaml::dump(['parameters' => $parameterList], 4, 2));
78 $callbackRow = $this->getCallbackReturnList($service, $method, $args);
79 $io->table($tableHeader, $callbackRow, 'compact');
85 $tableRows = $this->getServiceDetail($service);
86 $io->table($tableHeader, $tableRows, 'compact');
92 $this->trans('commands.container.debug.messages.service_id'),
93 $this->trans('commands.container.debug.messages.class_name')
96 $tableRows = $this->getServiceList();
97 $io->table($tableHeader, $tableRows, 'compact');
103 private function getCallbackReturnList($service, $method, $args)
106 $parsedArgs = json_decode($args, true);
107 if (!is_array($parsedArgs)) {
108 $parsedArgs = explode(",", $args);
113 $serviceInstance = \Drupal::service($service);
115 if (!method_exists($serviceInstance, $method)) {
116 throw new \Symfony\Component\DependencyInjection\Exception\BadMethodCallException($this->trans('commands.container.debug.errors.method_not_exists'));
118 return $serviceDetail;
121 '<fg=green>'.$this->trans('commands.container.debug.messages.service').'</>',
122 '<fg=yellow>'.$service.'</>'
125 '<fg=green>'.$this->trans('commands.container.debug.messages.class').'</>',
126 '<fg=yellow>'.get_class($serviceInstance).'</>'
128 $methods = [$method];
129 $this->extendArgumentList($serviceInstance, $methods);
131 '<fg=green>'.$this->trans('commands.container.debug.messages.method').'</>',
132 '<fg=yellow>'.$methods[0].'</>'
136 '<fg=green>'.$this->trans('commands.container.debug.messages.arguments').'</>',
137 json_encode($parsedArgs, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
140 $return = call_user_func_array([$serviceInstance,$method], $parsedArgs);
142 '<fg=green>'.$this->trans('commands.container.debug.messages.return').'</>',
143 json_encode($return, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
145 return $serviceDetail;
147 private function getServiceList()
150 $serviceDefinitions = $this->container
151 ->getParameter('console.service_definitions');
153 foreach ($serviceDefinitions as $serviceId => $serviceDefinition) {
154 $services[] = [$serviceId, $serviceDefinition->getClass()];
156 usort($services, [$this, 'compareService']);
159 private function compareService($a, $b)
161 return strcmp($a[0], $b[0]);
164 private function getServiceDetail($service)
166 $serviceInstance = $this->get($service);
169 if ($serviceInstance) {
171 '<fg=green>'.$this->trans('commands.container.debug.messages.service').'</>',
172 '<fg=yellow>'.$service.'</>'
175 '<fg=green>'.$this->trans('commands.container.debug.messages.class').'</>',
176 '<fg=yellow>'.get_class($serviceInstance).'</>'
178 $interface = str_replace("{ }", "", Yaml::dump(class_implements($serviceInstance)));
179 if (!empty($interface)) {
181 '<fg=green>'.$this->trans('commands.container.debug.messages.interface').'</>',
182 '<fg=yellow>'.$interface.'</>'
185 if ($parent = get_parent_class($serviceInstance)) {
187 '<fg=green>'.$this->trans('commands.container.debug.messages.parent').'</>',
188 '<fg=yellow>'.$parent.'</>'
191 if ($vars = get_class_vars($serviceInstance)) {
193 '<fg=green>'.$this->trans('commands.container.debug.messages.variables').'</>',
194 '<fg=yellow>'.Yaml::dump($vars).'</>'
197 if ($methods = get_class_methods($serviceInstance)) {
199 $this->extendArgumentList($serviceInstance, $methods);
201 '<fg=green>'.$this->trans('commands.container.debug.messages.methods').'</>',
202 '<fg=yellow>'.implode("\n", $methods).'</>'
206 throw new \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($service);
208 return $serviceDetail;
211 return $serviceDetail;
213 private function extendArgumentList($serviceInstance, &$methods)
215 foreach ($methods as $k => $m) {
216 $reflection = new \ReflectionMethod($serviceInstance, $m);
217 $params = $reflection->getParameters();
220 for ($i = 0; $i < count($params); $i++) {
221 if ($params[$i]->isDefaultValueAvailable()) {
222 $defaultVar = $params[$i]->getDefaultValue();
223 $defaultVar = " = <fg=magenta>".str_replace(["\n","array ("], ["", "array("], var_export($def, true)).'</>';
227 if (method_exists($params[$i], 'hasType') && method_exists($params[$i], 'getType')) {
228 if ($params[$i]->hasType()) {
229 $defaultType = '<fg=white>'.strval($params[$i]->getType()).'</> ';
236 if ($params[$i]->isPassedByReference()) {
237 $parameterReference = '<fg=yellow>&</>';
239 $parameterReference = '';
241 $p[] = $defaultType.$parameterReference.'<fg=red>'.'$</><fg=red>'.$params[$i]->getName().'</>'.$defaultVar;
243 if ($reflection->isPublic()) {
244 $methods[$k] = '<fg=cyan>'.$methods[$k]."</><fg=blue>(</>".implode(', ', $p)."<fg=blue>) </> ";
249 private function getParameterList()
251 $parameters = array_filter(
252 $this->container->getParameterBag()->all(), function ($name) {
253 if (preg_match('/^container\./', $name)) {
256 if (preg_match('/^drupal\./', $name)) {
259 if (preg_match('/^console\./', $name)) {
263 }, ARRAY_FILTER_USE_KEY