ExceptionGeneratorCommand::configure()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 21
dl 0
loc 26
ccs 0
cts 7
cp 0
rs 9.584
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Fabiang\ExceptionGenerator\Cli\Command;
6
7
use Fabiang\ExceptionGenerator\Cli\Console\Application;
8
use Fabiang\ExceptionGenerator\Generator\CreateException;
9
use Fabiang\ExceptionGenerator\Generator\RecursiveNamespaceResolver;
10
use Fabiang\ExceptionGenerator\Generator\RecursiveParentExceptionResolver;
11
use Fabiang\ExceptionGenerator\Generator\TemplateRenderer;
12
use Fabiang\ExceptionGenerator\Listener\CreateExceptionListener;
13
use Fabiang\ExceptionGenerator\TemplateResolver\TemplatePathMatcher;
14
use Fabiang\ExceptionGenerator\TemplateResolver\TemplateResolver;
15
use Symfony\Component\Console\Command\Command;
16
use Symfony\Component\Console\Helper\QuestionHelper;
17
use Symfony\Component\Console\Input\InputArgument;
18
use Symfony\Component\Console\Input\InputInterface;
19
use Symfony\Component\Console\Input\InputOption;
20
use Symfony\Component\Console\Output\OutputInterface;
21
use Symfony\Component\Console\Question\Question;
22
use Symfony\Component\EventDispatcher\EventDispatcher;
23
24
use function array_reverse;
25
use function getcwd;
26
use function is_array;
27
use function is_string;
28
use function realpath;
29
use function substr;
30
31
class ExceptionGeneratorCommand extends Command
32
{
33
    /**
34
     * {@inheritDoc}
35
     */
36
    protected function configure(): void
37
    {
38
        $this->setName('exception-generator')
39
            ->setDescription('Generates Exception Classes for php files in current dir.')
40
            ->addArgument(
41
                'path',
42
                InputArgument::OPTIONAL,
43
                'Basepath for generating exception class.'
44
            )
45
            ->addOption(
46
                'overwrite',
47
                'o',
48
                InputOption::VALUE_NONE,
49
                'Force overwriting existing exception classes.'
50
            )
51
            ->addOption(
52
                'template-path',
53
                't',
54
                InputOption::VALUE_REQUIRED,
55
                'Set path for templates you want to use.'
56
            )
57
            ->addOption(
58
                'no-parents',
59
                'p',
60
                InputOption::VALUE_NONE,
61
                'Disable searching for parent exceptions.'
62
            );
63
    }
64
65
    /**
66
     * {@inheritDoc}
67
     */
68 2
    protected function execute(InputInterface $input, OutputInterface $output): int
69
    {
70 2
        if ($input->getArgument('path')) {
71 2
            $path = $this->realpath($input->getArgument('path'));
72
        } else {
73
            $path = getcwd();
74
        }
75
76 2
        if (! is_string($path)) {
0 ignored issues
show
introduced by
The condition is_string($path) is always true.
Loading history...
77
            $path = '';
78
        }
79
80
        /** @var QuestionHelper $questionHelper */
81 2
        $questionHelper = $this->getHelper('question');
82
83 2
        $eventDispatcher = new EventDispatcher();
84 2
        $eventDispatcher->addSubscriber(new CreateExceptionListener($output, $input, $questionHelper));
85 2
        $namespaceResolver = new RecursiveNamespaceResolver($eventDispatcher);
86
87 2
        $namespace = $namespaceResolver->resolveNamespace($path);
88
89
        /** @var Application $application */
90 2
        $application = $this->getApplication();
91
92 2
        $templatePathMatcher = new TemplatePathMatcher($path, $application->getHome() ?? '');
93
94 2
        $templatePath     = $this->realpath($input->getOption('template-path')) ?: '';
95 2
        $templateResolver = new TemplateResolver($templatePath, $templatePathMatcher);
96
97 2
        $exceptionTemplate = $templateResolver->resolve('exception.phtml');
98 2
        $interfaceTemplate = $templateResolver->resolve('interface.phtml');
99
100 2
        $useParents = $input->getOption('no-parents') ? false : true;
101
102 2
        $output->writeln('Using path for templates: "' . $templatePath . '"', OutputInterface::VERBOSITY_VERY_VERBOSE);
103 2
        $output->writeln('Exception-Path: "' . $exceptionTemplate . '"', OutputInterface::VERBOSITY_VERY_VERBOSE);
104 2
        $output->writeln('Interface-Path: "' . $interfaceTemplate . '"', OutputInterface::VERBOSITY_VERY_VERBOSE);
105
106 2
        $templateRenderer = new TemplateRenderer();
107 2
        $templateRenderer->addPath('exception', $exceptionTemplate);
108 2
        $templateRenderer->addPath('interface', $interfaceTemplate);
109
110 2
        $parentExceptionNamespace = null;
111
112 2
        if (false !== $useParents) {
113 1
            $parentExceptionResolver = new RecursiveParentExceptionResolver($eventDispatcher);
114 1
            $parentExceptionDirs     = $parentExceptionResolver->resolveExceptionDirs($path);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $parentExceptionDirs is correct as $parentExceptionResolver...lveExceptionDirs($path) targeting Fabiang\ExceptionGenerat...:resolveExceptionDirs() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
115
116 1
            if (is_array($parentExceptionDirs)) {
0 ignored issues
show
introduced by
The condition is_array($parentExceptionDirs) is always false.
Loading history...
117 1
                $parentExceptionDirs = array_reverse($parentExceptionDirs);
118 1
                foreach ($parentExceptionDirs as $parentExceptionDir) {
119 1
                    $prevParentNamespace      = $parentExceptionNamespace;
120 1
                    $parentExceptionNamespace = $namespaceResolver->resolveNamespace($parentExceptionDir);
121
122 1
                    if ($parentExceptionNamespace !== null) {
123 1
                        $output->writeln(
124 1
                            'BaseExceptionPath: "' . $parentExceptionDir . '"',
125
                            OutputInterface::VERBOSITY_VERY_VERBOSE
126
                        );
127 1
                        $output->writeln(
128 1
                            'BaseExceptionNamespace: "' . $parentExceptionNamespace . '"',
129
                            OutputInterface::VERBOSITY_VERY_VERBOSE
130
                        );
131
132 1
                        $parentExceptionCreator = new CreateException(
133
                            $eventDispatcher,
134
                            $templateRenderer,
135
                            false
136
                        );
137
138 1
                        $parentExceptionCreator->create(
139
                            $parentExceptionNamespace,
140
                            $parentExceptionDir,
141
                            $prevParentNamespace
142
                        );
143
                    }
144
                }
145
            }
146
        }
147
148 2
        $namespaceQuestion = new Question("Is this the correct namespace: [$namespace]?", $namespace);
149 2
        $inputNamespace    = $questionHelper->ask($input, $output, $namespaceQuestion);
150 2
        $output->writeln('Namespace set to "' . $inputNamespace . '"');
151
152 2
        $exceptionCreator = new CreateException(
153
            $eventDispatcher,
154
            $templateRenderer,
155 2
            $input->getOption('overwrite')
156
        );
157
158 2
        $exceptionCreator->create($inputNamespace, $path . '/Exception', $parentExceptionNamespace);
159
160 2
        return 0;
161
    }
162
163
    /**
164
     * Realpath.
165
     */
166 2
    private function realpath(?string $path): string|false
167
    {
168 2
        if (null === $path) {
169
            return '';
170
        }
171
172
        // extra check for virtual file system since vfsstream can't handle realpath()
173 2
        if (substr($path, 0, 6) === 'vfs://') {
174 2
            return $path;
175
        }
176
177
        return realpath($path);
178
    }
179
}
180