CheckFinalClassesCommand::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 10
cts 10
cp 1
rs 9.552
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Finalizer\Console;
4
5
use function count;
6
use Finalizer\Constraint\IsFinalizable;
7
use Finalizer\Scanner\DirectoryClassScanner;
8
use Finalizer\Scanner\DirectoryFileScanner;
9
use Symfony\Component\Console\Command\Command;
10
use Symfony\Component\Console\Helper\Table;
11
use Symfony\Component\Console\Input\InputArgument;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Output\OutputInterface;
14
15
class CheckFinalClassesCommand extends Command
16
{
17
    /**
18
     * {@inheritDoc}
19 4
     */
20
    public function __construct()
21 4
    {
22
        parent::__construct('finalizer:check-final-classes');
23
24 4
        $this
25 4
            ->setDescription(
26
                'Checks the given paths for classes that should or shouldn\'t be final'
27 4
            )
28 4
            ->setDefinition([new InputArgument(
29 4
                'directories',
30 4
                InputArgument::REQUIRED | InputArgument::IS_ARRAY,
31
                'Paths to be checked for existing classes'
32 4
            )]);
33 4
        $this->setHelp(<<<EOT
34
The <info>%command.name%</info> command generates a short report
35
of classes that should be final and classes that shouldn't be final.
36
37
You can use this command as following:
38
<info>%command.name% path/to/sources</info>
39
<info>%command.name% path/to/first/sources/dir path/to/second/sources/dir</info>
40
EOT
41 4
        );
42
    }
43
44
    /**
45
     * {@inheritDoc}
46 4
     */
47
    public function execute(InputInterface $input, OutputInterface $output) : int
48 4
    {
49 4
        $classScanner = new DirectoryClassScanner();
50 4
        $fileScanner  = new DirectoryFileScanner();
51
        $classes      = $classScanner($fileScanner($input->getArgument('directories')));
52 4
53 4
        $finalizeStatusCode = $this->renderClassesToFinalize($classes, $output);
54 4
        $deFinalizeStatusCode = $this->renderClassesToDeFinalize($classes, $output);
55
56
        return max($finalizeStatusCode, $deFinalizeStatusCode);
57
    }
58
59
    /**
60 4
     * @param \ReflectionClass[] $classes
61
     */
62 4
    private function renderClassesToFinalize(array $classes, OutputInterface $output) : int
63
    {
64 4
        $tableHelper = new Table($output);
65 3
66
        $toFinalize = $this->getClassesToFinalize($classes);
67 3
        if (count($toFinalize) > 0) {
68
            $output->writeln('<info>Following classes need to be made final:</info>');
69 3
70 3
            $tableHelper->addRows(array_map(
71 3
                function (\ReflectionClass $class) {
72
                    return [$class->getName()];
73
                },
74 3
                $toFinalize
75
            ));
76 4
77
            $tableHelper->render();
78
79
            return 1;
80
        }
81
82 4
        return 0;
83
    }
84 4
85
    /**
86 4
     * @param \ReflectionClass[] $classes
87 3
     */
88
    private function renderClassesToDeFinalize(array $classes, OutputInterface $output) : int
89 3
    {
90
        $tableHelper = new Table($output);
91 3
92 3
        $toDeFinalize = $this->getClassesToDeFinalize($classes);
93 3
        if (count($toDeFinalize) > 0) {
94
            $output->writeln('<error>Following classes are final and need to be made extensible again:</error>');
95
96 3
            $tableHelper->addRows(array_map(
97
                function (\ReflectionClass $class) {
98 4
                    return [$class->getName()];
99
                },
100
                $toDeFinalize
101
            ));
102
103
            $tableHelper->render();
104
105 4
            return 1;
106
        }
107 4
108 4
        return 0;
109
    }
110 4
111 4
    /**
112 4
     * @param \ReflectionClass[] $classes
113
     *
114
     * @return \ReflectionClass[]
115
     */
116 4
    private function getClassesToFinalize(array $classes)
117
    {
118
        $isFinalizable = new IsFinalizable();
119
        $toFinalize    = [];
120
121
        foreach ($classes as $class) {
122
            if ($isFinalizable($class, ...$classes) && ! $class->isFinal()) {
123
                $toFinalize[] = $class;
124 4
            }
125
        }
126 4
127 4
        return $toFinalize;
128
    }
129 4
130 4
    /**
131 4
     * @param \ReflectionClass[] $classes
132
     *
133
     * @return \ReflectionClass[]
134
     */
135 4
    private function getClassesToDeFinalize(array $classes)
136
    {
137
        $isFinalizable = new IsFinalizable();
138
        $toDeFinalize  = [];
139
140
        foreach ($classes as $class) {
141
            if ((! $isFinalizable($class, ...$classes)) && $class->isFinal()) {
142
                $toDeFinalize[] = $class;
143
            }
144
        }
145
146
        return $toDeFinalize;
147
    }
148
}
149