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

Resolver::isDependency()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
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