Yaffs site version 1.1
[yaffs-website] / vendor / drupal / console / src / Command / ContainerDebugCommand.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\Console\Command\ContainerDebugCommand.
6  */
7
8 namespace Drupal\Console\Command;
9
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;
18
19 /**
20  * Class ContainerDebugCommand
21  *
22  * @package Drupal\Console\Command
23  */
24 class ContainerDebugCommand extends Command
25 {
26     use ContainerAwareCommandTrait;
27
28     /**
29      * {@inheritdoc}
30      */
31     protected function configure()
32     {
33         $this
34             ->setName('container:debug')
35             ->setDescription($this->trans('commands.container.debug.description'))
36             ->addOption(
37                 'parameters',
38                 null,
39                 InputOption::VALUE_NONE,
40                 $this->trans('commands.container.debug.arguments.service')
41             )
42             ->addArgument(
43                 'service',
44                 InputArgument::OPTIONAL,
45                 $this->trans('commands.container.debug.arguments.service')
46             )->addArgument(
47                 'method',
48                 InputArgument::OPTIONAL,
49                 $this->trans('commands.container.debug.arguments.method')
50             )->addArgument(
51                 'arguments',
52                 InputArgument::OPTIONAL,
53                 $this->trans('commands.container.debug.arguments.arguments')
54             );
55     }
56
57     /**
58      * {@inheritdoc}
59      */
60     protected function execute(InputInterface $input, OutputInterface $output)
61     {
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');
67
68         if ($parameters) {
69             $parameterList = $this->getParameterList();
70             ksort($parameterList);
71             $io->write(Yaml::dump(['parameters' => $parameterList], 4, 2));
72
73             return 0;
74         }
75
76         if ($method) {
77             $tableHeader = [];
78             $callbackRow = $this->getCallbackReturnList($service, $method, $args);
79             $io->table($tableHeader, $callbackRow, 'compact');
80
81             return 0;
82         } else {
83             $tableHeader = [];
84             if ($service) {
85                 $tableRows = $this->getServiceDetail($service);
86                 $io->table($tableHeader, $tableRows, 'compact');
87
88                 return 0;
89             }
90
91             $tableHeader = [
92                 $this->trans('commands.container.debug.messages.service_id'),
93                 $this->trans('commands.container.debug.messages.class_name')
94             ];
95
96             $tableRows = $this->getServiceList();
97             $io->table($tableHeader, $tableRows, 'compact');
98         }
99
100         return 0;
101     }
102
103     private function getCallbackReturnList($service, $method, $args)
104     {
105         if ($args != null) {
106             $parsedArgs = json_decode($args, true);
107             if (!is_array($parsedArgs)) {
108                 $parsedArgs = explode(",", $args);
109             }
110         } else {
111             $parsedArgs = null;
112         }
113         $serviceInstance = \Drupal::service($service);
114
115         if (!method_exists($serviceInstance, $method)) {
116             throw new \Symfony\Component\DependencyInjection\Exception\BadMethodCallException($this->trans('commands.container.debug.errors.method_not_exists'));
117
118             return $serviceDetail;
119         }
120         $serviceDetail[] = [
121             '<fg=green>'.$this->trans('commands.container.debug.messages.service').'</>',
122             '<fg=yellow>'.$service.'</>'
123         ];
124         $serviceDetail[] = [
125             '<fg=green>'.$this->trans('commands.container.debug.messages.class').'</>',
126             '<fg=yellow>'.get_class($serviceInstance).'</>'
127         ];
128         $methods = [$method];
129         $this->extendArgumentList($serviceInstance, $methods);
130         $serviceDetail[] = [
131             '<fg=green>'.$this->trans('commands.container.debug.messages.method').'</>',
132             '<fg=yellow>'.$methods[0].'</>'
133         ];
134         if ($parsedArgs) {
135             $serviceDetail[] = [
136                 '<fg=green>'.$this->trans('commands.container.debug.messages.arguments').'</>',
137                 json_encode($parsedArgs, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
138             ];
139         }
140         $return = call_user_func_array([$serviceInstance,$method], $parsedArgs);
141         $serviceDetail[] = [
142             '<fg=green>'.$this->trans('commands.container.debug.messages.return').'</>',
143             json_encode($return, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
144         ];
145         return $serviceDetail;
146     }
147     private function getServiceList()
148     {
149         $services = [];
150         $serviceDefinitions = $this->container
151             ->getParameter('console.service_definitions');
152
153         foreach ($serviceDefinitions as $serviceId => $serviceDefinition) {
154             $services[] = [$serviceId, $serviceDefinition->getClass()];
155         }
156         usort($services, [$this, 'compareService']);
157         return $services;
158     }
159     private function compareService($a, $b)
160     {
161         return strcmp($a[0], $b[0]);
162     }
163
164     private function getServiceDetail($service)
165     {
166         $serviceInstance = $this->get($service);
167         $serviceDetail = [];
168
169         if ($serviceInstance) {
170             $serviceDetail[] = [
171                 '<fg=green>'.$this->trans('commands.container.debug.messages.service').'</>',
172                 '<fg=yellow>'.$service.'</>'
173             ];
174             $serviceDetail[] = [
175                 '<fg=green>'.$this->trans('commands.container.debug.messages.class').'</>',
176                 '<fg=yellow>'.get_class($serviceInstance).'</>'
177             ];
178             $interface = str_replace("{  }", "", Yaml::dump(class_implements($serviceInstance)));
179             if (!empty($interface)) {
180                 $serviceDetail[] = [
181                     '<fg=green>'.$this->trans('commands.container.debug.messages.interface').'</>',
182                     '<fg=yellow>'.$interface.'</>'
183                 ];
184             }
185             if ($parent = get_parent_class($serviceInstance)) {
186                 $serviceDetail[] = [
187                     '<fg=green>'.$this->trans('commands.container.debug.messages.parent').'</>',
188                     '<fg=yellow>'.$parent.'</>'
189                 ];
190             }
191             if ($vars = get_class_vars($serviceInstance)) {
192                 $serviceDetail[] = [
193                     '<fg=green>'.$this->trans('commands.container.debug.messages.variables').'</>',
194                     '<fg=yellow>'.Yaml::dump($vars).'</>'
195                 ];
196             }
197             if ($methods = get_class_methods($serviceInstance)) {
198                 sort($methods);
199                 $this->extendArgumentList($serviceInstance, $methods);
200                 $serviceDetail[] = [
201                     '<fg=green>'.$this->trans('commands.container.debug.messages.methods').'</>',
202                     '<fg=yellow>'.implode("\n", $methods).'</>'
203                 ];
204             }
205         } else {
206             throw new \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($service);
207
208             return $serviceDetail;
209         }
210
211         return $serviceDetail;
212     }
213     private function extendArgumentList($serviceInstance, &$methods)
214     {
215         foreach ($methods as $k => $m) {
216             $reflection = new \ReflectionMethod($serviceInstance, $m);
217             $params = $reflection->getParameters();
218             $p = [];
219
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)).'</>';
224                 } else {
225                     $defaultVar = '';
226                 }
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()).'</> ';
230                     } else {
231                         $defaultType = '';
232                     }
233                 } else {
234                     $defaultType = '';
235                 }
236                 if ($params[$i]->isPassedByReference()) {
237                     $parameterReference = '<fg=yellow>&</>';
238                 } else {
239                     $parameterReference = '';
240                 }
241                 $p[] = $defaultType.$parameterReference.'<fg=red>'.'$</><fg=red>'.$params[$i]->getName().'</>'.$defaultVar;
242             }
243             if ($reflection->isPublic()) {
244                 $methods[$k] = '<fg=cyan>'.$methods[$k]."</><fg=blue>(</>".implode(', ', $p)."<fg=blue>) </> ";
245             }
246         }
247     }
248
249     private function getParameterList()
250     {
251         $parameters = array_filter(
252             $this->container->getParameterBag()->all(), function ($name) {
253                 if (preg_match('/^container\./', $name)) {
254                     return false;
255                 }
256                 if (preg_match('/^drupal\./', $name)) {
257                     return false;
258                 }
259                 if (preg_match('/^console\./', $name)) {
260                     return false;
261                 }
262                 return true;
263             }, ARRAY_FILTER_USE_KEY
264         );
265
266         return $parameters;
267     }
268 }