Issues (6)

src/TemplateResolver/TemplatePathMatcher.php (1 issue)

Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Fabiang\ExceptionGenerator\TemplateResolver;
6
7
use Fabiang\ExceptionGenerator\Exception\RuntimeException;
8
9
use function array_values;
10
use function file_exists;
11
use function file_get_contents;
12
use function is_array;
13
use function is_readable;
14
use function json_decode;
15
use function json_last_error;
16
use function strlen;
17
use function strpos;
18
use function uksort;
19
20
use const JSON_ERROR_NONE;
21
22
class TemplatePathMatcher
23
{
24
    public const CONFIG_NAME = '.exception-generator.json';
25
26
    protected string $currentDir;
27
    protected string $configPath;
28
29
    /**
30
     * defines current dir and path for config
31
     */
32 3
    public function __construct(string $currentDir, string $configPath)
33
    {
34 3
        $this->currentDir = $currentDir;
35 3
        $this->configPath = $configPath . '/' . self::CONFIG_NAME;
36
    }
37
38
    /**
39
     * checks if config is valid and returns matching paths
40
     *
41
     * @throws RuntimeException
42
     */
43 5
    public function match(string $templateName): false|string
44
    {
45 5
        if (! is_readable($this->configPath)) {
46 1
            return false;
47
        }
48
49 4
        $jsonData = json_decode(file_get_contents($this->configPath), true);
50 4
        if (json_last_error() !== JSON_ERROR_NONE || ! is_array($jsonData)) {
51 2
            throw new RuntimeException("Could not parse json configuration \"$this->configPath\".");
52
        }
53
54 2
        return $this->getPaths($jsonData, $templateName);
55
    }
56
57
    /**
58
     * trys to get the most matching path or global from config
59
     */
60 4
    protected function getPaths(array $configData, string $templateName): false|string
61
    {
62 4
        if (! isset($configData['templatepath']) || ! is_array($configData['templatepath'])) {
63 1
            return false;
64
        }
65
66 3
        $templatePath = $configData['templatepath'];
67
68 3
        if (isset($templatePath['projects']) && is_array($templatePath['projects'])) {
69 3
            $filteredProjects = $this->filterMatchingPaths($templatePath['projects']);
70
71 3
            $matchingPath = $this->getMostRelatedPath($filteredProjects, $templateName);
72 3
            if (false !== $matchingPath) {
0 ignored issues
show
The condition false !== $matchingPath is always false.
Loading history...
73 1
                return $matchingPath;
74
            }
75
        }
76
77 2
        if (isset($templatePath['global'])) {
78 2
            $globalPath = $templatePath['global'];
79 2
            if (file_exists($globalPath . '/' . $templateName)) {
80 1
                return $globalPath;
81
            }
82
        }
83
84 1
        return false;
85
    }
86
87
    /**
88
     * filters paths matching to current directory
89
     */
90 1
    public function filterMatchingPaths(array $projects): array
91
    {
92 1
        $filteredProjects = [];
93 1
        foreach ($projects as $path => $projectTemplatePath) {
94
            // @todo Windows: case-insensitive match with stripos?
95 1
            if (false !== strpos($this->currentDir, $path)) {
96 1
                $filteredProjects[$path] = $projectTemplatePath;
97
            }
98
        }
99
100 1
        return $filteredProjects;
101
    }
102
103
    /**
104
     * trys to get the most related path where template was found
105
     */
106 2
    protected function getMostRelatedPath(array $filteredProjects, string $templateName): false|string
107
    {
108 2
        uksort($filteredProjects, function ($a, $b) {
109 2
            $strlenA = strlen($a);
110 2
            $strlenB = strlen($b);
111
112 2
            if ($strlenA < $strlenB) {
113 2
                return 1;
114
            }
115 2
            return -1;
116
        });
117
118 2
        $filteredProjects = array_values($filteredProjects);
119
120 2
        foreach ($filteredProjects as $templatePath) {
121 2
            if (file_exists($templatePath . '/' . $templateName)) {
122 1
                return $templatePath;
123
            }
124
        }
125 1
        return false;
126
    }
127
}
128