Completed
Push — master ( 73a623...61017a )
by Vladimir
02:34
created

PageManager::refreshItem()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 7.608

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
nc 3
nop 1
dl 0
loc 16
ccs 2
cts 10
cp 0.2
crap 7.608
rs 9.4285
c 1
b 0
f 0
1
<?php
2
3
namespace allejo\stakx\Manager;
4
5
use allejo\stakx\Exception\FileAwareException;
6
use allejo\stakx\Exception\TrackedItemNotFoundException;
7
use allejo\stakx\FrontMatter\ExpandedValue;
8
use allejo\stakx\Object\ContentItem;
9
use allejo\stakx\Object\DynamicPageView;
10
use allejo\stakx\Object\JailObject;
11
use allejo\stakx\Object\PageView;
12
use allejo\stakx\Object\RepeaterPageView;
13
use allejo\stakx\System\FileExplorer;
14
use allejo\stakx\System\Folder;
15
use Twig_Error_Syntax;
16
use Twig_Template;
17
18
/**
19
 * This class is responsible for handling all of the PageViews within a website.
20
 *
21
 * PageManager will parse all available dynamic and static PageViews. After, dynamic PageViews will be prepared by
22
 * setting the appropriate values for each ContentItem such as permalinks. Lastly, this class will compile all of the
23
 * PageViews and write them to the target directory.
24
 *
25
 * @package allejo\stakx\Manager
26
 */
27
class PageManager extends TrackingManager
28
{
29
    /**
30
     * The relative (to the stakx project) file path to the redirect template
31
     *
32
     * @var string|bool
33
     */
34
    private $redirectTemplate;
35
36
    /**
37
     * @var PageView[]
38
     */
39
    private $twigExtendsDeps;
40
41
    /**
42
     * @var ContentItem[][]
43
     */
44
    private $collections;
45
46
    /**
47
     * @var Folder
48
     */
49
    private $targetDir;
50
51
    /**
52
     * @var PageView[]
53
     */
54
    private $flatPages;
55
56
    /**
57
     * @var PageView[]
58
     */
59
    private $siteMenu;
60
61
    /**
62
     * @var array
63
     */
64
    private $twigOpts;
65
66
    /**
67
     * @var \Twig_Environment
68
     */
69
    private $twig;
70
71
    /**
72
     * PageManager constructor
73
     */
74 3
    public function __construct()
75
    {
76 3
        parent::__construct();
77
78 3
        $this->redirectTemplate = false;
79 3
        $this->twigExtendsDeps = array();
80 3
        $this->collections = array();
81 3
        $this->flatPages = array();
82 3
        $this->siteMenu = array();
83 3
    }
84
85
    /**
86
     * Give this manager the collections we'll be using for dynamic PageViews
87
     *
88
     * @param ContentItem[][] $collections
89
     */
90 3
    public function setCollections (&$collections)
91
    {
92 3
        $this->collections = &$collections;
93 3
    }
94
95
    /**
96
     * Set the template used for redirects
97
     *
98
     * @param false|string $filePath The path to the redirect template
99
     */
100
    public function setRedirectTemplate ($filePath)
101
    {
102
        $this->redirectTemplate = $filePath;
103
    }
104
105
    /**
106
     * The location where the compiled website will be written to
107
     *
108
     * @param Folder $folder The relative target directory as specified from the configuration file
109
     */
110 3
    public function setTargetFolder (&$folder)
111
    {
112 3
        $this->targetDir = &$folder;
113 3
    }
114
115 3
    public function configureTwig ($configuration, $options)
116
    {
117 3
        $this->twigOpts['configuration'] = $configuration;
118 3
        $this->twigOpts['options']       = $options;
119
120 3
        $this->createTwigManager();
121 3
    }
122
123 1
    public function getFlatPages ()
124
    {
125 1
        return $this->flatPages;
126
    }
127
128
    /**
129
     * An array representing the website's menu structure with children and grandchildren made from static PageViews
130
     *
131
     * @return JailObject[]
132
     */
133 1
    public function getSiteMenu ()
134
    {
135 1
        $jailedMenu = array();
136
137 1
        foreach ($this->siteMenu as $key => $value)
138
        {
139
            // If it's an array, it means the parent is hidden from the site menu therefore its children should be too
140 1
            if (is_array($this->siteMenu[$key]))
141 1
            {
142
                continue;
143
            }
144
145 1
            $jailedMenu[$key] = $value->createJail();
146 1
        }
147
148 1
        return $jailedMenu;
149 1
    }
150
151
    /**
152
     * Go through all of the PageView directories and create a respective PageView for each and classify them as a
153
     * dynamic or static PageView.
154
     *
155
     * @param $pageViewFolders
156
     */
157 3
    public function parsePageViews ($pageViewFolders)
158
    {
159 3
        if (empty($pageViewFolders)) { return; }
160
161
        /**
162
         * The name of the folder where PageViews are located
163
         *
164
         * @var $pageViewFolder string
165
         */
166 3
        foreach ($pageViewFolders as $pageViewFolderName)
167
        {
168 3
            $pageViewFolder = $this->fs->absolutePath($pageViewFolderName);
169
170 3
            if (!$this->fs->exists($pageViewFolder))
171 3
            {
172
                continue;
173
            }
174
175
            // @TODO Replace this with a regular expression or have wildcard support
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
176 3
            $this->scanTrackableItems($pageViewFolder, array(
177 3
                'refresh' => false,
178
                'fileExplorer' => FileExplorer::INCLUDE_ONLY_FILES
179 3
            ), array('.html', '.twig'));
180 3
            $this->saveFolderDefinition($pageViewFolderName);
181 3
        }
182 3
    }
183
184
    /**
185
     * Compile dynamic and static PageViews
186
     */
187 3
    public function compileAll ()
188
    {
189 3
        foreach (array_keys($this->trackedItemsFlattened) as $filePath)
190
        {
191 3
            $this->compileFromFilePath($filePath);
192 3
        }
193 3
    }
194
195
    public function compileSome ($filter = array())
196
    {
197
        /** @var PageView $pageView */
198
        foreach ($this->trackedItemsFlattened as $pageView)
199
        {
200
            if ($pageView->hasTwigDependency($filter['namespace'], $filter['dependency']))
201
            {
202
                $this->compilePageView($pageView);
203
            }
204
        }
205
    }
206
207
    /**
208
     * @param ContentItem $contentItem
209
     */
210
    public function compileContentItem (&$contentItem)
211
    {
212
        $pageView = $contentItem->getPageView();
213
214
        // This ContentItem doesn't have an individual PageView dedicated to displaying this item
215
        if (is_null($pageView))
216
        {
217
            return;
218
        }
219
220
        $template = $this->createTemplate($pageView);
221
        $contentItem->evaluateFrontMatter(
222
            $pageView->getFrontMatter(false)
223
        );
224
225
        $output = $template->render(array(
226
            'this' => $contentItem
227
        ));
228
229
        $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
230
    }
231
232
    /**
233
     * Add a new ContentItem to the respective parent PageView of the ContentItem
234
     *
235
     * @param ContentItem $contentItem
236
     */
237
    public function updatePageView ($contentItem)
238
    {
239
        /** @var DynamicPageView $pageView */
240
        foreach ($this->trackedItems['dynamic'] as &$pageView)
241
        {
242
            $fm = $pageView->getFrontMatter(false);
243
244
            if ($fm['collection'] == $contentItem->getCollection())
245
            {
246
                $pageView->addContentItem($contentItem);
247
            }
248
        }
249
    }
250
251
    /**
252
     * Update an existing Twig variable that's injected globally
253
     *
254
     * @param string $variable
255
     * @param string $value
256
     */
257
    public function updateTwigVariable ($variable, $value)
258
    {
259
        $this->twig->addGlobal($variable, $value);
260
    }
261
262
    /**
263
     * {@inheritdoc}
264
     */
265 3
    public function isTracked($filePath)
266
    {
267 3
        return (parent::isTracked($filePath) || isset($this->twigExtendsDeps[$filePath]));
268
    }
269
270
    /**
271
     * {@inheritdoc}
272
     */
273 3
    public function refreshItem($filePath)
274
    {
275
        if (parent::isTracked($filePath))
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (isTracked() instead of refreshItem()). Are you sure this is correct? If so, you might want to change this to $this->isTracked().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
276 3
        {
277
            $this->compileFromFilePath($filePath, true);
278
279
            return;
280
        }
281
282
        $this->createTwigManager();
283
284
        foreach ($this->twigExtendsDeps[$filePath] as $pageView)
0 ignored issues
show
Bug introduced by
The expression $this->twigExtendsDeps[$filePath] of type object<allejo\stakx\Object\PageView> is not traversable.
Loading history...
285
        {
286
            $this->compilePageView($pageView);
287
        }
288
    }
289
290
    /**
291
     * {@inheritdoc}
292
     */
293 3
    protected function handleTrackableItem($filePath, $options = array())
294
    {
295 3
        $pageView  = PageView::create($filePath);
296 3
        $namespace = $pageView->getType();
297
298 3
        if ($namespace == PageView::DYNAMIC_TYPE)
299 3
        {
300 3
            $frontMatter = $pageView->getFrontMatter(false);
301 3
            $collection = $frontMatter['collection'];
302
303 3
            if (!isset($this->collections[$collection]))
304 3
            {
305
                throw new \RuntimeException("The '$collection' collection is not defined");
306
            }
307
308 3
            foreach ($this->collections[$collection] as &$item)
309
            {
310 3
                $item->evaluateFrontMatter($frontMatter);
311 3
                $pageView->addContentItem($item);
312 3
            }
313 3
        }
314
315 3
        $this->addObjectToTracker($pageView, $pageView->getRelativeFilePath(), $namespace);
316 3
        $this->saveTrackerOptions($pageView->getRelativeFilePath(), array(
317
            'viewType' => $namespace
318 3
        ));
319
320 3
        if ($namespace == PageView::STATIC_TYPE && !empty($pageView['title']))
321 3
        {
322 3
            $this->addToSiteMenu($pageView);
323 3
            $this->flatPages[$pageView['title']] = $pageView->createJail();
324 3
        }
325 3
    }
326
327
    /**
328
     * Create a Twig environment
329
     */
330 3
    private function createTwigManager ()
331
    {
332 3
        $twig = new TwigManager();
333 3
        $twig->configureTwig(
334 3
            $this->twigOpts['configuration'],
335 3
            $this->twigOpts['options']
336 3
        );
337
338 3
        $this->twig = TwigManager::getInstance();
339 3
    }
340
341
    /**
342
     * Compile a given PageView
343
     *
344
     * @param string $filePath The file path to the PageView to compile
345
     * @param bool   $refresh  When set to true, the PageView will reread its contents
346
     *
347
     * @throws \Exception
348
     */
349 3
    private function compileFromFilePath ($filePath, $refresh = false)
350
    {
351 3
        if (!$this->isTracked($filePath))
352 3
        {
353
            throw new TrackedItemNotFoundException('PageView not found');
354
        }
355
356
        /** @var DynamicPageView|PageView|RepeaterPageView $pageView */
357 3
        $pageView = &$this->trackedItemsFlattened[$filePath];
358
359
        try
360
        {
361 3
            $this->compilePageView($pageView, $refresh);
362
        }
363 3
        catch (\Exception $e)
364
        {
365
            throw FileAwareException::castException($e, $filePath);
366
        }
367 3
    }
368
369
    /**
370
     * @param DynamicPageView|PageView|RepeaterPageView $pageView
371
     * @param bool                                      $refresh
372
     */
373 3
    private function compilePageView ($pageView, $refresh = false)
374
    {
375
        if ($refresh)
376 3
        {
377
            $pageView->refreshFileContent();
378
        }
379
380 3
        switch ($pageView->getType())
381
        {
382 3
            case PageView::REPEATER_TYPE:
383 3
                $this->compileRepeaterPageView($pageView);
0 ignored issues
show
Compatibility introduced by
$pageView of type object<allejo\stakx\Object\PageView> is not a sub-type of object<allejo\stakx\Object\RepeaterPageView>. It seems like you assume a child class of the class allejo\stakx\Object\PageView to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
384 3
                $this->compileExpandedRedirects($pageView);
385 3
                break;
386
387 3
            case PageView::DYNAMIC_TYPE:
388 3
                $this->compileDynamicPageView($pageView);
389 3
                $this->compileNormalRedirects($pageView);
390 3
                break;
391
392 3
            case PageView::STATIC_TYPE:
393 3
                $this->compileStaticPageView($pageView);
394 3
                $this->compileNormalRedirects($pageView);
395 3
                break;
396 3
        }
397 3
    }
398
399
    /**
400
     * @param RepeaterPageView $pageView
401
     */
402 3
    private function compileRepeaterPageView (&$pageView)
403
    {
404 3
        $template = $this->createTemplate($pageView);
405 3
        $pageView->rewindPermalink();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class allejo\stakx\Object\PageView as the method rewindPermalink() does only exist in the following sub-classes of allejo\stakx\Object\PageView: allejo\stakx\Object\RepeaterPageView. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
406
407 3
        foreach ($pageView->getRepeaterPermalinks() as $permalink)
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class allejo\stakx\Object\PageView as the method getRepeaterPermalinks() does only exist in the following sub-classes of allejo\stakx\Object\PageView: allejo\stakx\Object\RepeaterPageView. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
408
        {
409 3
            $pageView->bumpPermalink();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class allejo\stakx\Object\PageView as the method bumpPermalink() does only exist in the following sub-classes of allejo\stakx\Object\PageView: allejo\stakx\Object\RepeaterPageView. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
410 3
            $pageView->setFrontMatter(array(
411 3
                'permalink' => $permalink->getEvaluated(),
412 3
                'iterators' => $permalink->getIterators()
413 3
            ));
414
415 3
            $output = $template->render(array(
416 3
                'this' => $pageView->createJail()
417 3
            ));
418
419 3
            $this->output->notice("Writing repeater file: {file}", array('file' => $pageView->getTargetFile()));
420 3
            $this->targetDir->writeFile($pageView->getTargetFile(), $output);
421 3
        }
422 3
    }
423
424
    /**
425
     * @param PageView $pageView
426
     */
427 3
    private function compileDynamicPageView (&$pageView)
428
    {
429 3
        $template = $this->createTemplate($pageView);
430
431 3
        $pageViewFrontMatter = $pageView->getFrontMatter(false);
432 3
        $collection = $pageViewFrontMatter['collection'];
433
434 3
        if (!isset($this->collections[$collection]))
435 3
        {
436
            throw new \RuntimeException("The '$collection' collection is not defined");
437
        }
438
439
        /** @var ContentItem $contentItem */
440 3
        foreach ($this->collections[$collection] as &$contentItem)
441
        {
442 3
            $output = $template->render(array(
443 3
                'this' => $contentItem->createJail()
444 3
            ));
445
446 3
            $this->output->notice("Writing file: {file}", array('file' => $contentItem->getTargetFile()));
447 3
            $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
448 3
        }
449 3
    }
450
451
    /**
452
     * @param PageView $pageView
453
     */
454 3
    private function compileStaticPageView (&$pageView)
455
    {
456 3
        $this->twig->addGlobal('__currentTemplate', $pageView->getFilePath());
457
458 3
        $template = $this->createTemplate($pageView);
459 3
        $output = $template->render(array(
460 3
            'this' => $pageView->createJail()
461 3
        ));
462
463 3
        $this->output->notice("Writing file: {file}", array('file' => $pageView->getTargetFile()));
464 3
        $this->targetDir->writeFile($pageView->getTargetFile(), $output);
465 3
    }
466
467
    /**
468
     * @param DynamicPageView|PageView $pageView
469
     */
470 3
    private function compileNormalRedirects (&$pageView)
471
    {
472 3
        foreach ($pageView->getRedirects() as $redirect)
0 ignored issues
show
Bug introduced by
The expression $pageView->getRedirects() of type null|array<integer,string> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
473
        {
474
            $redirectPageView = PageView::createRedirect(
475
                $redirect,
476
                $pageView->getPermalink(),
477
                $this->redirectTemplate
478
            );
479
480
            $this->compilePageView($redirectPageView);
481 3
        }
482 3
    }
483
484
    /**
485
     * @param RepeaterPageView $pageView
486
     */
487 3
    private function compileExpandedRedirects (&$pageView)
488
    {
489 3
        $permalinks = $pageView->getRepeaterPermalinks();
490
491
        /** @var ExpandedValue[] $repeaterRedirect */
492 3
        foreach ($pageView->getRepeaterRedirects() as $repeaterRedirect)
493
        {
494
            /**
495
             * @var int           $index
496
             * @var ExpandedValue $redirect
497
             */
498
            foreach ($repeaterRedirect as $index => $redirect)
499
            {
500
                $redirectPageView = PageView::createRedirect(
501
                    $redirect->getEvaluated(),
502
                    $permalinks[$index]->getEvaluated(),
503
                    $this->redirectTemplate
504
                );
505
506
                $this->compilePageView($redirectPageView);
507
            }
508 3
        }
509 3
    }
510
511
    /**
512
     * Add a static PageView to the menu array. Dynamic PageViews are not added to the menu
513
     *
514
     * @param PageView $pageView
515
     */
516 3
    private function addToSiteMenu (&$pageView)
517
    {
518 3
        $frontMatter = $pageView->getFrontMatter();
519
520 3
        if (isset($frontMatter['menu']) && !$frontMatter['menu'])
521 3
        {
522
            return;
523
        }
524
525 3
        $url = trim($pageView->getPermalink(), '/');
526
527 3
        if (empty($url))
528 3
        {
529
            return;
530
        }
531
532 3
        $root = &$this->siteMenu;
533 3
        $dirs = explode('/', $url);
534
535 3
        while (count($dirs) > 0)
536
        {
537 3
            $name = array_shift($dirs);
538 3
            $name = (!empty($name)) ? $name : '.';
539
540 3
            if (!is_null($name) && count($dirs) == 0)
541 3
            {
542 3
                if (isset($root[$name]) && is_array($root[$name]))
543 3
                {
544 3
                    $children = &$pageView->getChildren();
545 3
                    $children = $root[$name]['children'];
546 3
                }
547
548 3
                $root[$name] = &$pageView;
549 3
            }
550
            else
551
            {
552 3
                if (!isset($root[$name]['children']))
553 3
                {
554 3
                    $root[$name]['children'] = array();
555 3
                }
556
557 3
                $root = &$root[$name]['children'];
558
            }
559 3
        }
560 3
    }
561
562
    /**
563
     * @param PageView $pageView
564
     *
565
     * @return Twig_Template
566
     * @throws Twig_Error_Syntax
567
     */
568 3
    private function createTemplate (&$pageView)
569
    {
570
        try
571
        {
572 3
            $template = $this->twig->createTemplate($pageView->getContent());
573
574 3
            $this->trackParentTwigTemplate($template, $pageView);
575
576 3
            return $template;
577
        }
578
        catch (Twig_Error_Syntax $e)
579
        {
580
            $e->setTemplateLine($e->getTemplateLine() + $pageView->getLineOffset());
581
            $e->setTemplateName($pageView->getRelativeFilePath());
0 ignored issues
show
Deprecated Code introduced by
The method Twig_Error::setTemplateName() has been deprecated with message: since 1.29 (to be removed in 2.0). Use setSourceContext() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
582
583
            throw $e;
584
        }
585
    }
586
587
    /**
588
     * Find the parent Twig templates of the given template and keep a list of it
589
     *
590
     * @param Twig_Template $template The template created from the PageView's content
591
     * @param PageView      $pageView The PageView that has this content. Used to keep a reference of PageViews
592
     */
593 3
    private function trackParentTwigTemplate ($template, &$pageView)
594
    {
595 3
        if (!$this->tracking) { return; }
596
597
        /** @var Twig_Template $parent */
598
        $parent = $template->getParent(array());
599
600
        while ($parent !== false)
601
        {
602
            $filePath = $this->fs->getRelativePath($parent->getSourceContext()->getPath());
603
604
            $this->twigExtendsDeps[$filePath][(string)$pageView->getFilePath()] = &$pageView;
605
            $parent = $parent->getParent(array());
606
        }
607
    }
608
}