Completed
Push — master ( 22c257...e714e6 )
by Gabriel
13:14 queued 10:09
created

ViewFinder::find()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 2
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
namespace Nip\View\ViewFinder;
4
5
use InvalidArgumentException;
6
use Nip\View\Utilities\Backtrace;
7
8
/**
9
 * Class ViewFinder
10
 * @package Nip\View\ViewFinder
11
 */
12
class ViewFinder implements ViewFinderInterface
13
{
14
    /**
15
     * The array of active view paths.
16
     *
17
     * @var array
18
     */
19
    protected $paths = [];
20
21
    /**
22
     * @var string
23
     */
24
    protected $rootPath;
25
26
27
    /**
28
     * Get the fully qualified location of the view.
29
     *
30
     * @param  string $name
31
     * @return string
32
     */
33 4
    public function find($name)
34
    {
35 4
        list($namespace, $view) = $this->parseName($name);
36
37 4
        if ($this->isRelativeView($view)) {
38 4
            return $this->findRelativePathView($view);
39
        }
40
41 4
        return $this->findNamespacedView($view, $namespace);
42
    }
43
44
    /**
45
     * Get the path to a template with a relative path.
46
     *
47
     * @param  string $name
48
     * @return string
49
     */
50 4
    protected function findRelativePathView($name)
51
    {
52 4
        $caller = Backtrace::getViewOrigin();
53 4
        return $this->findInPaths($name, [dirname($caller)]);
54
    }
55
56
    /**
57
     * Get the path to a template with a named path.
58
     *
59
     * @param  string $name
60
     * @param $namespace
61
     * @return string
62
     */
63 4
    protected function findNamespacedView($name, $namespace)
64
    {
65 4
        return $this->findInPaths($name, $this->paths[$namespace]);
66
    }
67
68
    /**
69
     * @param $name
70
     * @param string $namespace
71
     * @return array
72
     */
73 4
    public function parseName($name, $namespace = self::MAIN_NAMESPACE)
74
    {
75 4
        if ($this->hasNamespaceInformation($name = trim($name))) {
76 1
            return $this->parseNamespacedName($name);
77
        }
78 4
        return [$namespace, $name];
79
    }
80
81
    /**
82
     * Get the segments of a template with a named path.
83
     *
84
     * @param  string $name
85
     * @return array
86
     *
87
     * @throws \InvalidArgumentException
88
     */
89 1
    protected function parseNamespacedName($name)
90
    {
91 1
        $segments = explode(static::HINT_PATH_DELIMITER, $name);
92 1
        if (count($segments) != 2) {
93
            throw new InvalidArgumentException("View [$name] has an invalid name.");
94
        }
95 1
        if (!isset($this->paths[$segments[0]]) || count($this->paths[$segments[0]]) < 1) {
96
            throw new InvalidArgumentException("No path defined for namespace [{$segments[0]}].");
97
        }
98 1
        return $segments;
99
    }
100
101
    /**
102
     * @param $name
103
     * @return bool
104
     */
105 4
    public function isRelativeView($name)
106
    {
107 4
        return $name[0] !== '/';
108
    }
109
110
    /**
111
     * Find the given view in the list of paths.
112
     *
113
     * @param  string $name
114
     * @param  array $paths
115
     * @return string
116
     *
117
     * @throws \InvalidArgumentException
118
     */
119 4
    protected function findInPaths($name, $paths)
120
    {
121 4
        foreach ((array)$paths as $path) {
122 4
            $file = $this->getViewFilename($name);
123 4
            if (file_exists($viewPath = $path . '/' . $file)) {
124 4
                return $viewPath;
125
            }
126
        }
127 1
        throw new InvalidArgumentException(
128 1
            'View [' . $name . '] not found in paths [' . implode(', ', $paths) . '].'
129
        );
130
    }
131
132
    /**
133
     * Get an view file name with extension.
134
     *
135
     * @param  string $name
136
     * @return string
137
     */
138 4
    protected function getViewFilename($name)
139
    {
140 4
        return $name . '.php';
141
    }
142
143
    /**
144
     * Adds a path where templates are stored.
145
     *
146
     * @param string $path A path where to look for templates
147
     * @param string $namespace A path namespace
148
     *
149
     * @return void
150
     */
151 6
    public function addPath($path, $namespace = self::MAIN_NAMESPACE)
152
    {
153 6
        $this->paths[$namespace][] = rtrim($path, '/\\');
154 6
    }
155
156
    /**
157
     * Prepends a path where templates are stored.
158
     *
159
     * @param string $path A path where to look for templates
160
     * @param string $namespace A path namespace
161
     * @return void
162
     */
163 1
    public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
164
    {
165 1
        $path = rtrim($path, '/\\');
166
167 1
        if (!isset($this->paths[$namespace])) {
168
            $this->paths[$namespace][] = $path;
169
        } else {
170 1
            array_unshift($this->paths[$namespace], $path);
171
        }
172 1
    }
173
174
    /**
175
     * Sets the paths where templates are stored.
176
     *
177
     * @param string|array $paths A path or an array of paths where to look for templates
178
     * @param string $namespace A path namespace
179
     */
180 6
    public function setPaths($paths, $namespace = self::MAIN_NAMESPACE)
181
    {
182 6
        if (!is_array($paths)) {
183 6
            $paths = [$paths];
184
        }
185 6
        $this->paths[$namespace] = [];
186 6
        foreach ($paths as $path) {
187 6
            $this->addPath($path, $namespace);
188
        }
189 6
    }
190
191
    /**
192
     * Returns whether or not the view name has any hint information.
193
     *
194
     * @param  string $name
195
     * @return bool
196
     */
197 4
    public function hasNamespaceInformation($name)
198
    {
199 4
        return strpos($name, static::HINT_PATH_DELIMITER) > 0;
200
    }
201
202
    /**
203
     * Get the active view paths.
204
     *
205
     * @return array
206
     */
207
    public function getPaths()
208
    {
209
        return $this->paths;
210
    }
211
}
212