Completed
Push — master ( 584355...1b1aa8 )
by René
03:05
created

FileViewFinder::flush()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace ReneDeKat\LaravelViewFileFinder;
4
5
use Illuminate\Filesystem\Filesystem;
6
use Illuminate\View\ViewFinderInterface;
7
8
class FileViewFinder implements ViewFinderInterface
9
{
10
    /**
11
     * The filesystem instance.
12
     *
13
     * @var \Illuminate\Filesystem\Filesystem
14
     */
15
    protected $files;
16
17
    /**
18
     * The array of active view paths.
19
     *
20
     * @var array
21
     */
22
    protected $paths;
23
24
    /**
25
     * The array of views that have been located.
26
     *
27
     * @var array
28
     */
29
    protected $views = [];
30
31
    /**
32
     * The namespace to file path hints.
33
     *
34
     * @var array
35
     */
36
    protected $hints = [];
37
38
    /**
39
     * Register a view extension with the finder.
40
     *
41
     * @var array
42
     */
43
    protected $extensions = ['blade.php', 'php', 'css'];
44
45
    /**
46
     * Create a new file view loader instance.
47
     *
48
     * @param  \Illuminate\Filesystem\Filesystem  $files
49
     * @param  array  $paths
50
     * @param  array  $extensions
51
     */
52
    public function __construct(Filesystem $files, array $paths, array $extensions = null)
53
    {
54
        $this->files = $files;
55
        $this->paths = $paths;
56
57
        if (isset($extensions)) {
58
            $this->extensions = $extensions;
59
        }
60
    }
61
62
    /**
63
     * Get the fully qualified location of the view.
64
     *
65
     * @param  string  $name
66
     * @return string
67
     */
68
    public function find($name)
69
    {
70
        if (isset($this->views[$name])) {
71
            return $this->views[$name];
72
        }
73
74
        if ($this->hasHintInformation($name = trim($name))) {
75
            return $this->views[$name] = $this->findNamespacedView($name);
76
        }
77
78
        return $this->views[$name] = $this->findInPaths($name, $this->paths);
79
    }
80
81
    /**
82
     * Get the path to a template with a named path.
83
     *
84
     * @param  string  $name
85
     * @return string
86
     */
87
    protected function findNamespacedView($name)
88
    {
89
        list($namespace, $view) = $this->parseNamespaceSegments($name);
90
91
        return $this->findInPaths($view, $this->hints[$namespace]);
92
    }
93
94
    /**
95
     * Get the segments of a template with a named path.
96
     *
97
     * @param  string  $name
98
     * @return array
99
     *
100
     * @throws \InvalidArgumentException
101
     */
102
    protected function parseNamespaceSegments($name)
103
    {
104
        $segments = explode(static::HINT_PATH_DELIMITER, $name);
105
106
        if (count($segments) != 2) {
107
            throw new \InvalidArgumentException("View [$name] has an invalid name.");
108
        }
109
110
        if (! isset($this->hints[$segments[0]])) {
111
            throw new \InvalidArgumentException("No hint path defined for [{$segments[0]}].");
112
        }
113
114
        return $segments;
115
    }
116
117
    /**
118
     * Find the given view in the list of paths.
119
     *
120
     * @param  string  $name
121
     * @param  array   $paths
122
     * @return string
123
     *
124
     * @throws \InvalidArgumentException
125
     */
126
    protected function findInPaths($name, $paths)
127
    {
128
        foreach ((array) $paths as $path) {
129
            foreach ($this->getPossibleViewFiles($name) as $file) {
130
                if ($this->files->exists($viewPath = $path.'/'.$file)) {
131
                    return $viewPath;
132
                }
133
            }
134
        }
135
136
        if (! isset($path)) {
137
            throw new \InvalidArgumentException("View [$name] not found.");
138
        }
139
140
        return $this->createMissingView($name, $paths, $path);
141
    }
142
143
    /**
144
     * Get an array of possible view files.
145
     *
146
     * @param  string  $name
147
     * @return array
148
     */
149
    protected function getPossibleViewFiles($name)
150
    {
151
        return array_map(function ($extension) use ($name) {
152
            return str_replace('.', '/', $name).'.'.$extension;
153
        }, $this->extensions);
154
    }
155
156
    /**
157
     * Add a location to the finder.
158
     *
159
     * @param  string  $location
160
     * @return void
161
     */
162
    public function addLocation($location)
163
    {
164
        $this->paths[] = $location;
165
    }
166
167
    /**
168
     * Prepend a location to the finder.
169
     *
170
     * @param  string  $location
171
     * @return void
172
     */
173
    public function prependLocation($location)
174
    {
175
        array_unshift($this->paths, $location);
176
    }
177
178
    /**
179
     * Add a namespace hint to the finder.
180
     *
181
     * @param  string  $namespace
182
     * @param  string|array  $hints
183
     * @return void
184
     */
185
    public function addNamespace($namespace, $hints)
186
    {
187
        $hints = (array) $hints;
188
189
        if (isset($this->hints[$namespace])) {
190
            $hints = array_merge($this->hints[$namespace], $hints);
191
        }
192
193
        $this->hints[$namespace] = $hints;
194
    }
195
196
    /**
197
     * Prepend a namespace hint to the finder.
198
     *
199
     * @param  string  $namespace
200
     * @param  string|array  $hints
201
     * @return void
202
     */
203
    public function prependNamespace($namespace, $hints)
204
    {
205
        $hints = (array) $hints;
206
207
        if (isset($this->hints[$namespace])) {
208
            $hints = array_merge($hints, $this->hints[$namespace]);
209
        }
210
211
        $this->hints[$namespace] = $hints;
212
    }
213
214
    /**
215
     * Replace the namespace hints for the given namespace.
216
     *
217
     * @param  string  $namespace
218
     * @param  string|array  $hints
219
     * @return void
220
     */
221
    public function replaceNamespace($namespace, $hints)
222
    {
223
        $this->hints[$namespace] = (array) $hints;
224
    }
225
226
    /**
227
     * Register an extension with the view finder.
228
     *
229
     * @param  string  $extension
230
     * @return void
231
     */
232
    public function addExtension($extension)
233
    {
234
        if (($index = array_search($extension, $this->extensions)) !== false) {
235
            unset($this->extensions[$index]);
236
        }
237
238
        array_unshift($this->extensions, $extension);
239
    }
240
241
    /**
242
     * Returns whether or not the view name has any hint information.
243
     *
244
     * @param  string  $name
245
     * @return bool
246
     */
247
    public function hasHintInformation($name)
248
    {
249
        return strpos($name, static::HINT_PATH_DELIMITER) > 0;
250
    }
251
252
    /**
253
     * Flush the cache of located views.
254
     *
255
     * @return void
256
     */
257
    public function flush()
258
    {
259
        $this->views = [];
260
    }
261
262
    /**
263
     * Get the filesystem instance.
264
     *
265
     * @return \Illuminate\Filesystem\Filesystem
266
     */
267
    public function getFilesystem()
268
    {
269
        return $this->files;
270
    }
271
272
    /**
273
     * Get the active view paths.
274
     *
275
     * @return array
276
     */
277
    public function getPaths()
278
    {
279
        return $this->paths;
280
    }
281
282
    /**
283
     * Get the namespace to file path hints.
284
     *
285
     * @return array
286
     */
287
    public function getHints()
288
    {
289
        return $this->hints;
290
    }
291
292
    /**
293
     * Get registered extensions.
294
     *
295
     * @return array
296
     */
297
    public function getExtensions()
298
    {
299
        return $this->extensions;
300
    }
301
302
    /**
303
     * @param string $name
304
     * @param array $paths
305
     * @param string $path
306
     * @return string
307
     */
308
    protected function createMissingView($name, $paths, $path): string
309
    {
310
        $fsName = str_replace('.', '/', $name);
311
        $viewFilename = "{$path}/{$fsName}.blade.php";
312
        $viewFileDirectory = dirname($viewFilename);
313
314
        if (! file_exists($viewFileDirectory)) {
315
            mkdir($viewFileDirectory, 0755, true);
316
        }
317
318
        \File::copy(resource_path('/assets/pages/missing.blade.php'), $viewFilename);
319
320
        return $this->findInPaths($name, $paths);
321
    }
322
}
323