Passed
Push — master ( 376d34...7bf0e1 )
by Alexander
04:51 queued 02:18
created

DebugContainerCommand::execute()   D

Complexity

Conditions 19
Paths 62

Size

Total Lines 110
Code Lines 69

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 19
eloc 69
c 1
b 0
f 0
nc 62
nop 2
dl 0
loc 110
rs 4.5166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Debug\Command;
6
7
use Psr\Container\ContainerInterface;
8
use Symfony\Component\Console\Command\Command;
9
use Symfony\Component\Console\Helper\Table;
10
use Symfony\Component\Console\Input\InputArgument;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Input\InputOption;
13
use Symfony\Component\Console\Output\OutputInterface;
14
use Symfony\Component\Console\Style\SymfonyStyle;
15
use Yiisoft\Config\ConfigInterface;
16
use Yiisoft\Definitions\ArrayDefinition;
17
use Yiisoft\Definitions\CallableDefinition;
18
use Yiisoft\Definitions\ValueDefinition;
19
use Yiisoft\Di\Helpers\DefinitionNormalizer;
20
use Yiisoft\VarDumper\VarDumper;
21
use Yiisoft\Yii\Console\ExitCode;
22
use Yiisoft\Yii\Debug\Debugger;
23
24
final class DebugContainerCommand extends Command
25
{
26
    public const COMMAND_NAME = 'debug:container';
27
    protected static $defaultName = self::COMMAND_NAME;
28
29
    public function __construct(
30
        private ContainerInterface $container,
31
        private Debugger $debugger,
32
    ) {
33
        parent::__construct();
34
    }
35
36
    protected function configure(): void
37
    {
38
        $this
39
            ->setDescription('Show information about container')
40
            ->addArgument('id', InputArgument::IS_ARRAY, 'Service ID')
41
            ->addOption('groups', null, InputOption::VALUE_NONE, 'Show groups')
42
            ->addOption('group', 'g', InputOption::VALUE_REQUIRED, 'Show group');
43
    }
44
45
    protected function execute(InputInterface $input, OutputInterface $output): int
46
    {
47
        $this->debugger->stop();
48
        $config = $this->container->get(ConfigInterface::class);
49
50
        $io = new SymfonyStyle($input, $output);
51
52
        if ($input->hasArgument('id') && !empty($ids = $input->getArgument('id'))) {
53
            $build = $this->getConfigBuild($config);
54
            foreach ($ids as $id) {
55
                $definition = null;
56
                foreach ($build as $definitions) {
57
                    if (array_key_exists($id, $definitions)) {
58
                        $definition = $definitions[$id];
59
                    }
60
                }
61
                if ($definition === null) {
62
                    $io->error(
63
                        sprintf(
64
                            'Service "%s" not found.',
65
                            $id,
66
                        )
67
                    );
68
                    continue;
69
                }
70
                $io->title($id);
71
72
                $normalizedDefinition = DefinitionNormalizer::normalize($definition, $id);
73
                if ($normalizedDefinition instanceof ArrayDefinition) {
74
                    $definitionList = ['ID' => $id];
75
                    if (class_exists($normalizedDefinition->getClass())) {
76
                        $definitionList[] = ['Class' => $normalizedDefinition->getClass()];
77
                    }
78
                    if (!empty($normalizedDefinition->getConstructorArguments())) {
79
                        $definitionList[] = [
80
                            'Constructor' => $this->export(
81
                                $normalizedDefinition->getConstructorArguments()
82
                            ),
83
                        ];
84
                    }
85
                    if (!empty($normalizedDefinition->getMethodsAndProperties())) {
86
                        $definitionList[] = [
87
                            'Methods' => $this->export(
88
                                $normalizedDefinition->getMethodsAndProperties()
89
                            ),
90
                        ];
91
                    }
92
                    if (isset($definition['tags'])) {
93
                        $definitionList[] = ['Tags' => $this->export($definition['tags'])];
94
                    }
95
96
                    $io->definitionList(...$definitionList);
97
98
                    continue;
99
                }
100
                if ($normalizedDefinition instanceof CallableDefinition || $normalizedDefinition instanceof ValueDefinition) {
101
                    $io->text(
102
                        $this->export($definition)
103
                    );
104
                    continue;
105
                }
106
107
                $output->writeln([
108
                    $id,
109
                    VarDumper::create($normalizedDefinition)->asString(),
110
                ]);
111
            }
112
113
            return ExitCode::OK;
114
        }
115
116
        if ($input->hasOption('groups') && $input->getOption('groups')) {
117
            $build = $this->getConfigBuild($config);
118
            $groups = array_keys($build);
119
            ksort($groups);
120
121
            $io->table(['Group'], array_map(fn ($group) => [$group], $groups));
122
123
            return ExitCode::OK;
124
        }
125
        if ($input->hasOption('group') && !empty($group = $input->getOption('group'))) {
126
            $data = $config->get($group);
127
            ksort($data);
128
129
            $rows = $this->getGroupServices($data);
130
131
            $table = new Table($output);
132
            $table
133
                ->setHeaderTitle($group)
134
                ->setHeaders(['Service', 'Definition'])
135
                ->setRows($rows);
136
            $table->render();
137
138
            return ExitCode::OK;
139
        }
140
141
        $build = $this->getConfigBuild($config);
142
143
        foreach ($build as $group => $data) {
144
            $rows = $this->getGroupServices($data);
145
146
            $table = new Table($output);
147
            $table
148
                ->setHeaderTitle($group)
149
                ->setHeaders(['Group', 'Services'])
150
                ->setRows($rows);
151
            $table->render();
152
        }
153
154
        return ExitCode::OK;
155
    }
156
157
    private function getConfigBuild(mixed $config): array
158
    {
159
        $reflection = new \ReflectionClass($config);
160
        $buildReflection = $reflection->getProperty('build');
161
        $buildReflection->setAccessible(true);
162
        return $buildReflection->getValue($config);
163
    }
164
165
    protected function getGroupServices(array $data): array
166
    {
167
        $rows = [];
168
        foreach ($data as $id => $definition) {
169
            $class = '';
170
            if (is_string($definition)) {
171
                $class = $definition;
172
            }
173
            if (is_array($definition)) {
174
                $class = $definition['class'] ?? $id;
175
            }
176
            if (is_object($definition)) {
177
                $class = $definition::class;
178
            }
179
180
            $rows[] = [
181
                $id,
182
                $class,
183
            ];
184
        }
185
        return $rows;
186
    }
187
188
    protected function export(mixed $value): string
189
    {
190
        return VarDumper::create($value)->asString();
191
    }
192
}
193