Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\View;
4
 
5
use Illuminate\Contracts\Container\Container;
6
use Illuminate\Contracts\Events\Dispatcher;
7
use Illuminate\Contracts\Support\Arrayable;
8
use Illuminate\Contracts\View\Factory as FactoryContract;
9
use Illuminate\Support\Arr;
10
use Illuminate\Support\Traits\Macroable;
11
use Illuminate\View\Engines\EngineResolver;
12
use InvalidArgumentException;
13
 
14
class Factory implements FactoryContract
15
{
16
    use Macroable,
17
        Concerns\ManagesComponents,
18
        Concerns\ManagesEvents,
19
        Concerns\ManagesFragments,
20
        Concerns\ManagesLayouts,
21
        Concerns\ManagesLoops,
22
        Concerns\ManagesStacks,
23
        Concerns\ManagesTranslations;
24
 
25
    /**
26
     * The engine implementation.
27
     *
28
     * @var \Illuminate\View\Engines\EngineResolver
29
     */
30
    protected $engines;
31
 
32
    /**
33
     * The view finder implementation.
34
     *
35
     * @var \Illuminate\View\ViewFinderInterface
36
     */
37
    protected $finder;
38
 
39
    /**
40
     * The event dispatcher instance.
41
     *
42
     * @var \Illuminate\Contracts\Events\Dispatcher
43
     */
44
    protected $events;
45
 
46
    /**
47
     * The IoC container instance.
48
     *
49
     * @var \Illuminate\Contracts\Container\Container
50
     */
51
    protected $container;
52
 
53
    /**
54
     * Data that should be available to all templates.
55
     *
56
     * @var array
57
     */
58
    protected $shared = [];
59
 
60
    /**
61
     * The extension to engine bindings.
62
     *
63
     * @var array
64
     */
65
    protected $extensions = [
66
        'blade.php' => 'blade',
67
        'php' => 'php',
68
        'css' => 'file',
69
        'html' => 'file',
70
    ];
71
 
72
    /**
73
     * The view composer events.
74
     *
75
     * @var array
76
     */
77
    protected $composers = [];
78
 
79
    /**
80
     * The number of active rendering operations.
81
     *
82
     * @var int
83
     */
84
    protected $renderCount = 0;
85
 
86
    /**
87
     * The "once" block IDs that have been rendered.
88
     *
89
     * @var array
90
     */
91
    protected $renderedOnce = [];
92
 
93
    /**
94
     * Create a new view factory instance.
95
     *
96
     * @param  \Illuminate\View\Engines\EngineResolver  $engines
97
     * @param  \Illuminate\View\ViewFinderInterface  $finder
98
     * @param  \Illuminate\Contracts\Events\Dispatcher  $events
99
     * @return void
100
     */
101
    public function __construct(EngineResolver $engines, ViewFinderInterface $finder, Dispatcher $events)
102
    {
103
        $this->finder = $finder;
104
        $this->events = $events;
105
        $this->engines = $engines;
106
 
107
        $this->share('__env', $this);
108
    }
109
 
110
    /**
111
     * Get the evaluated view contents for the given view.
112
     *
113
     * @param  string  $path
114
     * @param  \Illuminate\Contracts\Support\Arrayable|array  $data
115
     * @param  array  $mergeData
116
     * @return \Illuminate\Contracts\View\View
117
     */
118
    public function file($path, $data = [], $mergeData = [])
119
    {
120
        $data = array_merge($mergeData, $this->parseData($data));
121
 
122
        return tap($this->viewInstance($path, $path, $data), function ($view) {
123
            $this->callCreator($view);
124
        });
125
    }
126
 
127
    /**
128
     * Get the evaluated view contents for the given view.
129
     *
130
     * @param  string  $view
131
     * @param  \Illuminate\Contracts\Support\Arrayable|array  $data
132
     * @param  array  $mergeData
133
     * @return \Illuminate\Contracts\View\View
134
     */
135
    public function make($view, $data = [], $mergeData = [])
136
    {
137
        $path = $this->finder->find(
138
            $view = $this->normalizeName($view)
139
        );
140
 
141
        // Next, we will create the view instance and call the view creator for the view
142
        // which can set any data, etc. Then we will return the view instance back to
143
        // the caller for rendering or performing other view manipulations on this.
144
        $data = array_merge($mergeData, $this->parseData($data));
145
 
146
        return tap($this->viewInstance($view, $path, $data), function ($view) {
147
            $this->callCreator($view);
148
        });
149
    }
150
 
151
    /**
152
     * Get the first view that actually exists from the given list.
153
     *
154
     * @param  array  $views
155
     * @param  \Illuminate\Contracts\Support\Arrayable|array  $data
156
     * @param  array  $mergeData
157
     * @return \Illuminate\Contracts\View\View
158
     *
159
     * @throws \InvalidArgumentException
160
     */
161
    public function first(array $views, $data = [], $mergeData = [])
162
    {
163
        $view = Arr::first($views, function ($view) {
164
            return $this->exists($view);
165
        });
166
 
167
        if (! $view) {
168
            throw new InvalidArgumentException('None of the views in the given array exist.');
169
        }
170
 
171
        return $this->make($view, $data, $mergeData);
172
    }
173
 
174
    /**
175
     * Get the rendered content of the view based on a given condition.
176
     *
177
     * @param  bool  $condition
178
     * @param  string  $view
179
     * @param  \Illuminate\Contracts\Support\Arrayable|array  $data
180
     * @param  array  $mergeData
181
     * @return string
182
     */
183
    public function renderWhen($condition, $view, $data = [], $mergeData = [])
184
    {
185
        if (! $condition) {
186
            return '';
187
        }
188
 
189
        return $this->make($view, $this->parseData($data), $mergeData)->render();
190
    }
191
 
192
    /**
193
     * Get the rendered content of the view based on the negation of a given condition.
194
     *
195
     * @param  bool  $condition
196
     * @param  string  $view
197
     * @param  \Illuminate\Contracts\Support\Arrayable|array  $data
198
     * @param  array  $mergeData
199
     * @return string
200
     */
201
    public function renderUnless($condition, $view, $data = [], $mergeData = [])
202
    {
203
        return $this->renderWhen(! $condition, $view, $data, $mergeData);
204
    }
205
 
206
    /**
207
     * Get the rendered contents of a partial from a loop.
208
     *
209
     * @param  string  $view
210
     * @param  array  $data
211
     * @param  string  $iterator
212
     * @param  string  $empty
213
     * @return string
214
     */
215
    public function renderEach($view, $data, $iterator, $empty = 'raw|')
216
    {
217
        $result = '';
218
 
219
        // If is actually data in the array, we will loop through the data and append
220
        // an instance of the partial view to the final result HTML passing in the
221
        // iterated value of this data array, allowing the views to access them.
222
        if (count($data) > 0) {
223
            foreach ($data as $key => $value) {
224
                $result .= $this->make(
225
                    $view, ['key' => $key, $iterator => $value]
226
                )->render();
227
            }
228
        }
229
 
230
        // If there is no data in the array, we will render the contents of the empty
231
        // view. Alternatively, the "empty view" could be a raw string that begins
232
        // with "raw|" for convenience and to let this know that it is a string.
233
        else {
234
            $result = str_starts_with($empty, 'raw|')
235
                        ? substr($empty, 4)
236
                        : $this->make($empty)->render();
237
        }
238
 
239
        return $result;
240
    }
241
 
242
    /**
243
     * Normalize a view name.
244
     *
245
     * @param  string  $name
246
     * @return string
247
     */
248
    protected function normalizeName($name)
249
    {
250
        return ViewName::normalize($name);
251
    }
252
 
253
    /**
254
     * Parse the given data into a raw array.
255
     *
256
     * @param  mixed  $data
257
     * @return array
258
     */
259
    protected function parseData($data)
260
    {
261
        return $data instanceof Arrayable ? $data->toArray() : $data;
262
    }
263
 
264
    /**
265
     * Create a new view instance from the given arguments.
266
     *
267
     * @param  string  $view
268
     * @param  string  $path
269
     * @param  \Illuminate\Contracts\Support\Arrayable|array  $data
270
     * @return \Illuminate\Contracts\View\View
271
     */
272
    protected function viewInstance($view, $path, $data)
273
    {
274
        return new View($this, $this->getEngineFromPath($path), $view, $path, $data);
275
    }
276
 
277
    /**
278
     * Determine if a given view exists.
279
     *
280
     * @param  string  $view
281
     * @return bool
282
     */
283
    public function exists($view)
284
    {
285
        try {
286
            $this->finder->find($view);
287
        } catch (InvalidArgumentException $e) {
288
            return false;
289
        }
290
 
291
        return true;
292
    }
293
 
294
    /**
295
     * Get the appropriate view engine for the given path.
296
     *
297
     * @param  string  $path
298
     * @return \Illuminate\Contracts\View\Engine
299
     *
300
     * @throws \InvalidArgumentException
301
     */
302
    public function getEngineFromPath($path)
303
    {
304
        if (! $extension = $this->getExtension($path)) {
305
            throw new InvalidArgumentException("Unrecognized extension in file: {$path}.");
306
        }
307
 
308
        $engine = $this->extensions[$extension];
309
 
310
        return $this->engines->resolve($engine);
311
    }
312
 
313
    /**
314
     * Get the extension used by the view file.
315
     *
316
     * @param  string  $path
317
     * @return string|null
318
     */
319
    protected function getExtension($path)
320
    {
321
        $extensions = array_keys($this->extensions);
322
 
323
        return Arr::first($extensions, function ($value) use ($path) {
324
            return str_ends_with($path, '.'.$value);
325
        });
326
    }
327
 
328
    /**
329
     * Add a piece of shared data to the environment.
330
     *
331
     * @param  array|string  $key
332
     * @param  mixed|null  $value
333
     * @return mixed
334
     */
335
    public function share($key, $value = null)
336
    {
337
        $keys = is_array($key) ? $key : [$key => $value];
338
 
339
        foreach ($keys as $key => $value) {
340
            $this->shared[$key] = $value;
341
        }
342
 
343
        return $value;
344
    }
345
 
346
    /**
347
     * Increment the rendering counter.
348
     *
349
     * @return void
350
     */
351
    public function incrementRender()
352
    {
353
        $this->renderCount++;
354
    }
355
 
356
    /**
357
     * Decrement the rendering counter.
358
     *
359
     * @return void
360
     */
361
    public function decrementRender()
362
    {
363
        $this->renderCount--;
364
    }
365
 
366
    /**
367
     * Check if there are no active render operations.
368
     *
369
     * @return bool
370
     */
371
    public function doneRendering()
372
    {
373
        return $this->renderCount == 0;
374
    }
375
 
376
    /**
377
     * Determine if the given once token has been rendered.
378
     *
379
     * @param  string  $id
380
     * @return bool
381
     */
382
    public function hasRenderedOnce(string $id)
383
    {
384
        return isset($this->renderedOnce[$id]);
385
    }
386
 
387
    /**
388
     * Mark the given once token as having been rendered.
389
     *
390
     * @param  string  $id
391
     * @return void
392
     */
393
    public function markAsRenderedOnce(string $id)
394
    {
395
        $this->renderedOnce[$id] = true;
396
    }
397
 
398
    /**
399
     * Add a location to the array of view locations.
400
     *
401
     * @param  string  $location
402
     * @return void
403
     */
404
    public function addLocation($location)
405
    {
406
        $this->finder->addLocation($location);
407
    }
408
 
409
    /**
410
     * Add a new namespace to the loader.
411
     *
412
     * @param  string  $namespace
413
     * @param  string|array  $hints
414
     * @return $this
415
     */
416
    public function addNamespace($namespace, $hints)
417
    {
418
        $this->finder->addNamespace($namespace, $hints);
419
 
420
        return $this;
421
    }
422
 
423
    /**
424
     * Prepend a new namespace to the loader.
425
     *
426
     * @param  string  $namespace
427
     * @param  string|array  $hints
428
     * @return $this
429
     */
430
    public function prependNamespace($namespace, $hints)
431
    {
432
        $this->finder->prependNamespace($namespace, $hints);
433
 
434
        return $this;
435
    }
436
 
437
    /**
438
     * Replace the namespace hints for the given namespace.
439
     *
440
     * @param  string  $namespace
441
     * @param  string|array  $hints
442
     * @return $this
443
     */
444
    public function replaceNamespace($namespace, $hints)
445
    {
446
        $this->finder->replaceNamespace($namespace, $hints);
447
 
448
        return $this;
449
    }
450
 
451
    /**
452
     * Register a valid view extension and its engine.
453
     *
454
     * @param  string  $extension
455
     * @param  string  $engine
456
     * @param  \Closure|null  $resolver
457
     * @return void
458
     */
459
    public function addExtension($extension, $engine, $resolver = null)
460
    {
461
        $this->finder->addExtension($extension);
462
 
463
        if (isset($resolver)) {
464
            $this->engines->register($engine, $resolver);
465
        }
466
 
467
        unset($this->extensions[$extension]);
468
 
469
        $this->extensions = array_merge([$extension => $engine], $this->extensions);
470
    }
471
 
472
    /**
473
     * Flush all of the factory state like sections and stacks.
474
     *
475
     * @return void
476
     */
477
    public function flushState()
478
    {
479
        $this->renderCount = 0;
480
        $this->renderedOnce = [];
481
 
482
        $this->flushSections();
483
        $this->flushStacks();
484
        $this->flushComponents();
485
        $this->flushFragments();
486
    }
487
 
488
    /**
489
     * Flush all of the section contents if done rendering.
490
     *
491
     * @return void
492
     */
493
    public function flushStateIfDoneRendering()
494
    {
495
        if ($this->doneRendering()) {
496
            $this->flushState();
497
        }
498
    }
499
 
500
    /**
501
     * Get the extension to engine bindings.
502
     *
503
     * @return array
504
     */
505
    public function getExtensions()
506
    {
507
        return $this->extensions;
508
    }
509
 
510
    /**
511
     * Get the engine resolver instance.
512
     *
513
     * @return \Illuminate\View\Engines\EngineResolver
514
     */
515
    public function getEngineResolver()
516
    {
517
        return $this->engines;
518
    }
519
 
520
    /**
521
     * Get the view finder instance.
522
     *
523
     * @return \Illuminate\View\ViewFinderInterface
524
     */
525
    public function getFinder()
526
    {
527
        return $this->finder;
528
    }
529
 
530
    /**
531
     * Set the view finder instance.
532
     *
533
     * @param  \Illuminate\View\ViewFinderInterface  $finder
534
     * @return void
535
     */
536
    public function setFinder(ViewFinderInterface $finder)
537
    {
538
        $this->finder = $finder;
539
    }
540
 
541
    /**
542
     * Flush the cache of views located by the finder.
543
     *
544
     * @return void
545
     */
546
    public function flushFinderCache()
547
    {
548
        $this->getFinder()->flush();
549
    }
550
 
551
    /**
552
     * Get the event dispatcher instance.
553
     *
554
     * @return \Illuminate\Contracts\Events\Dispatcher
555
     */
556
    public function getDispatcher()
557
    {
558
        return $this->events;
559
    }
560
 
561
    /**
562
     * Set the event dispatcher instance.
563
     *
564
     * @param  \Illuminate\Contracts\Events\Dispatcher  $events
565
     * @return void
566
     */
567
    public function setDispatcher(Dispatcher $events)
568
    {
569
        $this->events = $events;
570
    }
571
 
572
    /**
573
     * Get the IoC container instance.
574
     *
575
     * @return \Illuminate\Contracts\Container\Container
576
     */
577
    public function getContainer()
578
    {
579
        return $this->container;
580
    }
581
 
582
    /**
583
     * Set the IoC container instance.
584
     *
585
     * @param  \Illuminate\Contracts\Container\Container  $container
586
     * @return void
587
     */
588
    public function setContainer(Container $container)
589
    {
590
        $this->container = $container;
591
    }
592
 
593
    /**
594
     * Get an item from the shared data.
595
     *
596
     * @param  string  $key
597
     * @param  mixed  $default
598
     * @return mixed
599
     */
600
    public function shared($key, $default = null)
601
    {
602
        return Arr::get($this->shared, $key, $default);
603
    }
604
 
605
    /**
606
     * Get all of the shared data for the environment.
607
     *
608
     * @return array
609
     */
610
    public function getShared()
611
    {
612
        return $this->shared;
613
    }
614
}