ModuleReader::generateDependenciesGraph()   B
last analyzed

Complexity

Conditions 7
Paths 10

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
c 0
b 0
f 0
rs 7.551
cc 7
eloc 11
nc 10
nop 1
1
<?php
2
/**
3
 * @copyright 2018 Aleksander Stelmaczonek <[email protected]>
4
 * @license   MIT License, see license file distributed with this source code
5
 */
6
7
namespace Koriit\PHPDeps\Modules;
8
9
use Koriit\PHPDeps\Graph\DirectedGraph;
10
use Koriit\PHPDeps\Graph\Vertex;
11
use Koriit\PHPDeps\Modules\Exceptions\ModuleNotFound;
12
use Koriit\PHPDeps\Tokenizer\DependenciesReader;
13
use Koriit\PHPDeps\Tokenizer\Exceptions\MalformedFile;
14
use RecursiveDirectoryIterator;
15
use RecursiveIteratorIterator;
16
17
class ModuleReader
18
{
19
    /** @var DependenciesReader */
20
    private $fileReader;
21
22
    public function __construct(DependenciesReader $fileReader)
23
    {
24
        $this->fileReader = $fileReader;
25
    }
26
27
    /**
28
     * @param Module[] $modules
29
     *
30
     * @throws MalformedFile
31
     * @throws ModuleNotFound
32
     *
33
     * @return DirectedGraph Graph describing dependencies between modules
34
     */
35
    public function generateDependenciesGraph(array $modules)
36
    {
37
        /** @var Vertex[] $vertices */
38
        $vertices = [];
39
        foreach ($modules as $module) {
40
            $vertices[] = new Vertex($module);
41
        }
42
43
        foreach ($vertices as $vertex) {
44
            $dependencies = $this->findModuleDependencies($vertex->getValue()->getPath());
45
            foreach ($dependencies as $dependency) {
46
                foreach ($vertices as $neighbour) {
47
                    if ($vertex !== $neighbour && \preg_match($neighbour->getValue()->getPattern(), $dependency)) {
48
                        $vertex->addNeighbour($neighbour);
49
                    }
50
                }
51
            }
52
        }
53
54
        return new DirectedGraph($vertices);
55
    }
56
57
    /**
58
     * @param string $modulePath Path to module, either file or directory
59
     *
60
     * @throws MalformedFile
61
     * @throws ModuleNotFound
62
     *
63
     * @return string[] List of module's dependencies
64
     */
65
    public function findModuleDependencies($modulePath)
66
    {
67
        $dependencies = [];
68
        $files = $this->findPHPFiles($modulePath);
69
        foreach ($files as $file) {
70
            $dependencies = \array_merge($dependencies, $this->fileReader->findFileDependencies($file));
71
        }
72
73
        // remove duplicates
74
        $dependencies = \array_unique($dependencies);
75
76
        // reindex array
77
        return \array_values($dependencies);
78
    }
79
80
    /**
81
     * @param string $modulePath
82
     *
83
     * @throws ModuleNotFound
84
     *
85
     * @return string[] Paths to PHP files in the module
86
     */
87
    private function findPHPFiles($modulePath)
88
    {
89
        $files = [];
90
91
        if (\is_dir($modulePath)) {
92
            $dirIterator = new RecursiveDirectoryIterator($modulePath);
93
            $iterator = new RecursiveIteratorIterator($dirIterator);
94
            foreach ($iterator as $file) {
95
                if (\preg_match("/\.php$/i", $file)) {
96
                    $files[] = (string) $file;
97
                }
98
            }
99
        } elseif (\is_file($modulePath)) {
100
            $files[] = $modulePath;
101
        } else {
102
            throw new ModuleNotFound($modulePath);
103
        }
104
105
        return $files;
106
    }
107
}
108