Passed
Pull Request — master (#216)
by Alexander
03:22
created

DebugContainerCommand::execute()   D

Complexity

Conditions 19
Paths 62

Size

Total Lines 111
Code Lines 69

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
eloc 69
c 0
b 0
f 0
nc 62
nop 2
dl 0
loc 111
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
                    //var_dump(array_keys($definitions));
58
                    if (array_key_exists($id, $definitions)) {
59
                        $definition = $definitions[$id];
60
                    }
61
                }
62
                if ($definition === null) {
63
                    $io->error(
64
                        sprintf(
65
                            'Service "%s" not found',
66
                            $id,
67
                        )
68
                    );
69
                    continue;
70
                }
71
                $io->title($id);
72
73
                $normalizedDefinition = DefinitionNormalizer::normalize($definition, $id);
74
                if ($normalizedDefinition instanceof ArrayDefinition) {
75
                    $definitionList = ['ID' => $id];
76
                    if (class_exists($normalizedDefinition->getClass())) {
77
                        $definitionList[] = ['Class' => $normalizedDefinition->getClass()];
78
                    }
79
                    if (!empty($normalizedDefinition->getConstructorArguments())) {
80
                        $definitionList[] = [
81
                            'Constructor' => $this->export(
82
                                $normalizedDefinition->getConstructorArguments()
83
                            ),
84
                        ];
85
                    }
86
                    if (!empty($normalizedDefinition->getMethodsAndProperties())) {
87
                        $definitionList[] = [
88
                            'Methods' => $this->export(
89
                                $normalizedDefinition->getMethodsAndProperties()
90
                            ),
91
                        ];
92
                    }
93
                    if (isset($definition['tags'])) {
94
                        $definitionList[] = ['Tags' => $this->export($definition['tags'])];
95
                    }
96
97
                    $io->definitionList(...$definitionList);
98
99
                    continue;
100
                }
101
                if ($normalizedDefinition instanceof CallableDefinition || $normalizedDefinition instanceof ValueDefinition) {
102
                    $io->text(
103
                        $this->export($definition)
104
                    );
105
                    continue;
106
                }
107
108
                $output->writeln([
109
                    $id,
110
                    VarDumper::create($normalizedDefinition)->asString(),
111
                ]);
112
            }
113
114
            return ExitCode::OK;
115
        }
116
117
        if ($input->hasOption('groups') && $input->getOption('groups')) {
118
            $build = $this->getConfigBuild($config);
119
            $groups = array_keys($build);
120
            ksort($groups);
121
122
            $io->table(['Group'], array_map(fn ($group) => [$group], $groups));
123
124
            return ExitCode::OK;
125
        }
126
        if ($input->hasOption('group') && !empty($group = $input->getOption('group'))) {
127
            $data = $config->get($group);
128
            ksort($data);
129
130
            $rows = $this->getGroupServices($data);
131
132
            $table = new Table($output);
133
            $table
134
                ->setHeaderTitle($group)
135
                ->setHeaders(['Service', 'Definition'])
136
                ->setRows($rows);
137
            $table->render();
138
139
            return ExitCode::OK;
140
        }
141
142
        $build = $this->getConfigBuild($config);
143
144
        foreach ($build as $group => $data) {
145
            $rows = $this->getGroupServices($data);
146
147
            $table = new Table($output);
148
            $table
149
                ->setHeaderTitle($group)
150
                ->setHeaders(['Group', 'Services'])
151
                ->setRows($rows);
152
            $table->render();
153
        }
154
155
        return ExitCode::OK;
156
    }
157
158
    private function getConfigBuild(mixed $config): array
159
    {
160
        $reflection = new \ReflectionClass($config);
161
        $buildReflection = $reflection->getProperty('build');
162
        $buildReflection->setAccessible(true);
163
        return $buildReflection->getValue($config);
164
    }
165
166
    protected function getGroupServices(array $data): array
167
    {
168
        $rows = [];
169
        foreach ($data as $id => $definition) {
170
            $class = '';
171
            if (is_string($definition)) {
172
                $class = $definition;
173
            }
174
            if (is_array($definition)) {
175
                $class = $definition['class'] ?? $id;
176
            }
177
            if (is_object($definition)) {
178
                $class = $definition::class;
179
            }
180
181
            $rows[] = [
182
                $id,
183
                $class,
184
            ];
185
        }
186
        return $rows;
187
    }
188
189
    protected function export(mixed $value): string
190
    {
191
        return VarDumper::create($value)->asString();
192
    }
193
}
194