VerifyDependencyCommand::debugRules()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 7
rs 10
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 $response) {
66
            if ($response->count() > 0) {
67
                $table = (new ConsoleTable())
68
                    ->addHeader('depender')
69
                    ->addHeader('component')
70
                    ->addHeader('')
71
                    ->addHeader('dependee')
72
                    ->addHeader('component');
73
74
                $errorCount += $response->count();
75
                $output->writeln('');
76
                $output->writeln($response->getRuleName());
77
                foreach ($response->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
102
        foreach ($graph->getClasses() as $class) {
103
            if (!empty($depsInternals = $class->getDepsInternalTag())) {
104
                $definePattern = [];
105
                $extraPatterns = [];
106
                foreach ($depsInternals as $depsInternal) {
107
                    $calleeName = $depsInternal->getFqsen()->toString();
108
                    if (!in_array($calleeName, $definePattern)) {
109
                        $definePattern[] = $calleeName;
110
                    }
111
                    $extraPatterns[$calleeName] = $depsInternal->getTargets();
112
                }
113
                $ruleDefinitions['phpdoc in ' . $class->getName()] = [
114
                    'phpdoc' => [
115
                        'define' => $definePattern,
116
                        'depender' => ['!\\'],
117
                        'extra' => $extraPatterns
118
                    ],
119
                    'other' => [
120
                        'define' => ['!' . $class->getName()],
121
                    ]
122
                ];
123
            }
124
        }
125
126
        return $ruleDefinitions;
127
    }
128
129
    /**
130
     * @param DependencyRule[] $rules
131
     * @param OutputInterface $output
132
     */
133
    protected function debugRules(array $rules, OutputInterface $output): void
134
    {
135
        if ($output->isVerbose()) {
136
            $output->writeln('');
137
            $output->writeln('Defined rules:');
138
            foreach ($rules as $rule) {
139
                $output->writeln(var_export($rule->toArray(), true));
140
            }
141
        }
142
    }
143
}
144