Passed
Push — master ( 29e061...029172 )
by Satoshi
02:02
created

VerifyDependencyCommand::debugRules()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace DependencyAnalyzer\Commands;
5
6
use DependencyAnalyzer\Inspector\RuleViolationDetector;
7
use DependencyAnalyzer\Inspector\RuleViolationDetector\DependencyRule;
8
use DependencyAnalyzer\Inspector\RuleViolationDetector\DependencyRuleFactory;
9
use DependencyAnalyzer\DependencyGraph;
10
use DependencyAnalyzer\Exceptions\InvalidCommandArgumentException;
11
use LucidFrame\Console\ConsoleTable;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Input\InputOption;
14
use Symfony\Component\Console\Output\OutputInterface;
15
16
class VerifyDependencyCommand extends AnalyzeDependencyCommand
17
{
18
    protected $ruleDefinition;
19
20
    protected function getCommandName(): string
21
    {
22
        return 'verify';
23
    }
24
25
    protected function getCommandDescription(): string
26
    {
27
        return 'verify dependency map by rule';
28
    }
29
30
    protected function configure(): void
31
    {
32
        parent::configure();
33
        $this->addOption('rule', 'r', InputOption::VALUE_REQUIRED, 'Rule file');
34
    }
35
36
    protected function initialize(InputInterface $input, OutputInterface $output)
37
    {
38
        parent::initialize($input, $output);
39
40
        $ruleFile = $input->getOption('rule');
41
        if (is_null($ruleFile)) {
42
            $this->ruleDefinition = [];
43
        } else {
44
            if (!is_file($ruleFile)) {
0 ignored issues
show
Bug introduced by
It seems like $ruleFile can also be of type string[]; however, parameter $filename of is_file() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

44
            if (!is_file(/** @scrutinizer ignore-type */ $ruleFile)) {
Loading history...
45
                throw new InvalidCommandArgumentException(sprintf('rule is not file "%s".', $ruleFile));
0 ignored issues
show
Bug introduced by
It seems like $ruleFile can also be of type string[]; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

45
                throw new InvalidCommandArgumentException(sprintf('rule is not file "%s".', /** @scrutinizer ignore-type */ $ruleFile));
Loading history...
46
            }
47
            $this->ruleDefinition = require_once $ruleFile;
48
            if (!is_array($this->ruleDefinition)) {
49
                throw new InvalidCommandArgumentException(sprintf('rule is invalid file "%s".', $ruleFile));
50
            }
51
        }
52
    }
53
54
    protected function inspectDependencyGraph(DependencyGraph $graph, OutputInterface $output): int
55
    {
56
        $rules = (new DependencyRuleFactory())->create(array_merge(
57
            $this->ruleDefinition,
58
            $this->createRuleDefinitionFromPhpDoc($graph)
59
        ));
60
        $this->debugRules($rules, $output);
61
        $detector = new RuleViolationDetector($rules);
62
        $responses = $detector->inspect($graph);
63
64
        $errorCount = 0;
65
        foreach ($responses as $respons) {
66
            if ($respons->count() > 0) {
67
                $table = (new ConsoleTable())
68
                    ->addHeader('depender')
69
                    ->addHeader('component')
70
                    ->addHeader('')
71
                    ->addHeader('dependee')
72
                    ->addHeader('component');
73
74
                $errorCount += $respons->count();
75
                $output->writeln('');
76
                $output->writeln($respons->getRuleName());
77
                foreach ($respons->getViolations() as $violation) {
78
                    $table->addRow([
79
                        $violation['depender'],
80
                        $violation['dependerComponent'],
81
                        '->',
82
                        $violation['dependee'],
83
                        $violation['dependeeComponent']
84
                    ]);
85
                }
86
87
                $output->write($table->getTable());
88
            }
89
        }
90
91
        if ($errorCount === 0) {
0 ignored issues
show
introduced by
The condition $errorCount === 0 is always true.
Loading history...
92
            $output->write('rule violation is not found.');
93
        }
94
95
        return $errorCount > 0 ? 1 : 0;
96
    }
97
98
    protected function createRuleDefinitionFromPhpDoc(DependencyGraph $graph): array
99
    {
100
        $ruleDefinitions = [];
101
        foreach ($graph->getClassesHaveOnlyUsedTag() as $class => $classesInPhpDoc) {
102
            $ruleDefinitions['phpdoc in ' . $class] = [
103
                'phpdoc' => [
104
                    'define' => ["\\{$class}"],
105
                    'depender' => $classesInPhpDoc
106
                ],
107
                'other' => [
108
                    'define' => array_map(function (string $className) {
109
                        return "!{$className}";
110
                    }, $classesInPhpDoc),
111
                ]
112
            ];
113
        }
114
115
        return $ruleDefinitions;
116
    }
117
118
    /**
119
     * @param DependencyRule[] $rules
120
     * @param OutputInterface $output
121
     */
122
    protected function debugRules(array $rules, OutputInterface $output): void
123
    {
124
        if ($output->isVerbose()) {
125
            $output->writeln('');
126
            $output->writeln('Defined rules:');
127
            foreach ($rules as $rule) {
128
                $output->writeln(var_export($rule->toArray(), true));
129
            }
130
        }
131
    }
132
}
133