TemplateFileResolver::getPathHierarchy()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace ntentan\honam;
4
5
use ntentan\honam\exceptions\TemplateResolutionException;
6
use ntentan\utils\Filesystem;
7
8
class TemplateFileResolver
9
{
10
    /**
11
     * The array which holds the template path heirachy.
12
     *
13
     * @var array<string>
14
     */
15
    private $pathHierarchy = array();
16
17
    public function getPathHierarchy() : array
18
    {
19
        return $this->pathHierarchy;
20
    }
21
22
    public function setPathHierarchy(array $pathHierarchy) : void
23
    {
24
        $this->pathHierarchy = $pathHierarchy;
25
    }
26
27
    /**
28
     * Append a directory to the end of the template path heirachy.
29
     *
30
     * @param string $path
31
     */
32
    public function appendToPathHierarchy($path)
33
    {
34
        $this->pathHierarchy[] = $path;
35
    }
36
37
    /**
38
     * Prepend a directory to the beginning of the template path heirachy.
39
     *
40
     * @param string $path
41
     */
42
    public function prependToPathHierarchy($path)
43
    {
44
        array_unshift($this->pathHierarchy, $path);
45
    }
46
47
    private function testTemplateFile($testTemplate, $paths, $extension)
48
    {
49
        $templateFile = '';
50
        foreach ($paths as $path) {
51
            $newTemplateFile = "$path/$testTemplate.$extension";
52
            if (file_exists($newTemplateFile)) {
53
                $templateFile = $newTemplateFile;
54
                break;
55
            }
56
        }
57
        return $templateFile;
58
    }
59
60
    private function testNoEngineTemplateFile($testTemplate, $paths)
61
    {
62
        $templateFile = '';
63
        foreach ($paths as $path) {
64
            $newTemplateFile = "$testTemplate.*";
65
            $files = array_filter(
66
                iterator_to_array(Filesystem::directory($path)->getFiles(false)),
67
                function($file) use($newTemplateFile) {
68
                    return fnmatch($newTemplateFile, basename($file));
69
                });
70
            $files = array_map(function($file) { return basename($file);}, $files);
71
            if (count($files) == 1) {
72
                $templateFile = $path . "/" . reset($files);
73
                break;
74
            } else if (count($files) > 1) {
75
                $templates = implode(", ", $files);
76
                throw new TemplateResolutionException("Multiple templates were resolved for the request '$testTemplate'. Please ensure that only one supported template type of the name '$testTemplate' exists in the path '$path'. Files found: $templates");
77
            }
78
        }
79
        return $templateFile;
80
    }
81
82
    private function searchTemplateDirectory($template, $ignoreEngine = false)
83
    {
84
        $templateFile = '';
85
        $extension = '';
86
87
        // Split the filename on the dots. The first part before the first dot
88
        // would be used to implement the file breakdown. The other parts are
89
        // fused together again and appended during the evaluation of the
90
        // breakdown.
91
92
        if ($ignoreEngine) {
93
            $breakDown = explode('_', $template);
94
        } else {
95
            $splitOnDots = explode('.', $template);
96
            $breakDown = explode('_', array_shift($splitOnDots));
97
            $extension = implode(".", $splitOnDots);
98
        }
99
100
        $parts = count($breakDown);
101
102
        for ($i = 0; $i < $parts; $i++) {
103
            $testTemplate = implode("_", array_slice($breakDown, $i, count($breakDown) - $i));
104
105
            if ($ignoreEngine) {
106
                $templateFile = $this->testNoEngineTemplateFile($testTemplate, $this->pathHierarchy);
107
            } else {
108
                $templateFile = $this->testTemplateFile($testTemplate, $this->pathHierarchy, $extension);
109
            }
110
111
            if ($templateFile != '') {
112
                break;
113
            }
114
        }
115
116
        return $templateFile;
117
    }
118
119
    /**
120
     * Resolve a template file by running through all the directories in the
121
     * template heirachy till a file that matches the template is found.
122
     *
123
     * @param string $template
124
     * @return string
125
     * @throws TemplateResolutionException
126
     */
127
    public function resolveTemplateFile($template)
128
    {
129
        if ($template == '') {
130
            throw new TemplateResolutionException("Empty template file requested");
131
        }
132
133
        if(file_exists($template)) {
134
            return $template;
135
        }
136
137
        $templateFile = $this->searchTemplateDirectory($template, pathinfo($template, PATHINFO_EXTENSION) === '');
138
139
        if ($templateFile == null) {
140
            $pathString = "[" . implode('; ', $this->pathHierarchy) . "]";
141
            throw new TemplateResolutionException(
142
                "Could not find a suitable template file for the current request '{$template}'. Current template path $pathString"
143
            );
144
        }
145
146
        return $templateFile;
147
    }
148
}
149