Passed
Push — master ( f5390f...ff2936 )
by Alexander
02:09
created

Resolver   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 84
Duplicated Lines 0 %

Test Coverage

Coverage 71.43%

Importance

Changes 0
Metric Value
wmc 19
eloc 37
c 0
b 0
f 0
dl 0
loc 84
ccs 30
cts 42
cp 0.7143
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A parseDependencyName() 0 3 1
A resolveDependencies() 0 11 3
A get() 0 8 2
A isDependency() 0 3 1
A followDependencies() 0 16 5
A collectDependencies() 0 10 5
A __construct() 0 7 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Composer\Config\Util;
6
7
use Yiisoft\Composer\Config\Builder;
8
use Yiisoft\Composer\Config\Exception\CircularDependencyException;
9
10
/**
11
 * Resolver class.
12
 * Reorders files according to their cross dependencies
13
 * and resolves `$name` paths.
14
 */
15
class Resolver
16
{
17
    private array $dependenciesOrder = [];
18
19
    private array $dependencies = [];
20
21
    private array $following = [];
22
23
    private array $files;
24
25 1
    public function __construct(array $files)
26
    {
27 1
        $this->files = $files;
28
29 1
        $this->collectDependencies($files);
30 1
        foreach (array_keys($files) as $name) {
31 1
            $this->followDependencies($name);
32
        }
33 1
    }
34
35 1
    public function get(): array
36
    {
37 1
        $result = [];
38 1
        foreach ($this->dependenciesOrder as $name) {
39 1
            $result[$name] = $this->resolveDependencies($this->files[$name]);
40
        }
41
42 1
        return $result;
43
    }
44
45 1
    private function resolveDependencies(array $paths): array
46
    {
47 1
        foreach ($paths as &$path) {
48 1
            if ($this->isDependency($path)) {
49
                $dependency = $this->parseDependencyName($path);
50
51
                $path = Builder::path($dependency);
52
            }
53
        }
54
55 1
        return $paths;
56
    }
57
58 1
    private function followDependencies(string $name): void
59
    {
60 1
        if (array_key_exists($name, $this->dependenciesOrder)) {
61
            return;
62
        }
63 1
        if (array_key_exists($name, $this->following)) {
64
            throw new CircularDependencyException($name . ' ' . implode(',', $this->following));
65
        }
66 1
        $this->following[$name] = $name;
67 1
        if (array_key_exists($name, $this->dependencies)) {
68
            foreach ($this->dependencies[$name] as $dependency) {
69
                $this->followDependencies($dependency);
70
            }
71
        }
72 1
        $this->dependenciesOrder[$name] = $name;
73 1
        unset($this->following[$name]);
74 1
    }
75
76 1
    private function collectDependencies(array $files): void
77
    {
78 1
        foreach ($files as $name => $paths) {
79 1
            foreach ($paths as $path) {
80 1
                if ($this->isDependency($path)) {
81
                    $dependencyName = $this->parseDependencyName($path);
82
                    if (!array_key_exists($name, $this->dependencies)) {
83
                        $this->dependencies[$name] = [];
84
                    }
85
                    $this->dependencies[$name][$dependencyName] = $dependencyName;
86
                }
87
            }
88
        }
89 1
    }
90
91 1
    private function isDependency(string $path): bool
92
    {
93 1
        return 0 === strncmp($path, '$', 1);
94
    }
95
96
    private function parseDependencyName(string $path): string
97
    {
98
        return substr($path, 1);
99
    }
100
}
101