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