Completed
Pull Request — master (#5)
by James Ekow Abaka
02:42
created

TemplateFileResolver::getPathHierarchy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
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 37
    public function appendToPathHierarchy($path)
33
    {
34 37
        $this->pathHierarchy[] = $path;
35 37
    }
36
37
    /**
38
     * Prepend a directory to the beginning of the template path heirachy.
39
     *
40
     * @param string $path
41
     */
42 2
    public function prependToPathHierarchy($path)
43
    {
44 2
        array_unshift($this->pathHierarchy, $path);
45 2
    }
46
47 30
    private function testTemplateFile($testTemplate, $paths, $extension)
48
    {
49 30
        $templateFile = '';
50 30
        foreach ($paths as $path) {
51 30
            $newTemplateFile = "$path/$testTemplate.$extension";
52 30
            if (file_exists($newTemplateFile)) {
53 29
                $templateFile = $newTemplateFile;
54 29
                break;
55
            }
56
        }
57 30
        return $templateFile;
58
    }
59
60 15
    private function testNoEngineTemplateFile($testTemplate, $paths)
61
    {
62 15
        $templateFile = '';
63 15
        foreach ($paths as $path) {
64 15
            $newTemplateFile = "$testTemplate.*";
65 15
            $files = array_filter(
66 15
                iterator_to_array(Filesystem::directory($path)->getFiles(false)),
67
                function($file) use($newTemplateFile) {
68 15
                    return fnmatch($newTemplateFile, basename($file));
69 15
                });
70
            $files = array_map(function($file) { return basename($file);}, $files);
71 15
            if (count($files) == 1) {
72 15
                $templateFile = $path . "/" . reset($files);
73 15
                break;
74 5
            } 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 15
        return $templateFile;
80
    }
81
82 31
    private function searchTemplateDirectory($template, $ignoreEngine = false)
83
    {
84 31
        $templateFile = '';
85 31
        $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 31
        if ($ignoreEngine) {
93 15
            $breakDown = explode('_', $template);
94
        } else {
95 30
            $splitOnDots = explode('.', $template);
96 30
            $breakDown = explode('_', array_shift($splitOnDots));
97 30
            $extension = implode(".", $splitOnDots);
98
        }
99
100 31
        $parts = count($breakDown);
101
102 31
        for ($i = 0; $i < $parts; $i++) {
103 31
            $testTemplate = implode("_", array_slice($breakDown, $i, count($breakDown) - $i));
104
105 31
            if ($ignoreEngine) {
106 15
                $templateFile = $this->testNoEngineTemplateFile($testTemplate, $this->pathHierarchy);
107
            } else {
108 30
                $templateFile = $this->testTemplateFile($testTemplate, $this->pathHierarchy, $extension);
109
            }
110
111 31
            if ($templateFile != '') {
112 30
                break;
113
            }
114
        }
115
116 31
        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 31
    public function resolveTemplateFile($template)
128
    {
129 31
        if ($template == '') {
130
            throw new TemplateResolutionException("Empty template file requested");
131
        }
132
133 31
        $templateFile = $this->searchTemplateDirectory($template, pathinfo($template, PATHINFO_EXTENSION) === '');
134
135 31
        if ($templateFile == null) {
136 1
            $pathString = "[" . implode('; ', $this->pathHierarchy) . "]";
137 1
            throw new TemplateResolutionException(
138 1
                "Could not find a suitable template file for the current request '{$template}'. Current template path $pathString"
139
            );
140
        }
141
142 30
        return $templateFile;
143
    }
144
}
145