Completed
Push — master ( d14277...a23ebb )
by Vladimir
06:29
created

PageManager::compileExpandedRedirects()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 23
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 6.4624

Importance

Changes 0
Metric Value
cc 3
eloc 9
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 23
ccs 3
cts 11
cp 0.2727
crap 6.4624
rs 9.0856
1
<?php
2
3
namespace allejo\stakx\Manager;
4
5
use allejo\stakx\Exception\TrackedItemNotFoundException;
6
use allejo\stakx\FrontMatter\ExpandedValue;
7
use allejo\stakx\Object\ContentItem;
8
use allejo\stakx\Object\DynamicPageView;
9
use allejo\stakx\Object\JailObject;
10
use allejo\stakx\Object\PageView;
11
use allejo\stakx\Object\RepeaterPageView;
12
use allejo\stakx\System\FileExplorer;
13
use allejo\stakx\System\Folder;
14
use Twig_Error_Syntax;
15
use Twig_Template;
16
17
/**
18
 * This class is responsible for handling all of the PageViews within a website.
19
 *
20
 * PageManager will parse all available dynamic and static PageViews. After, dynamic PageViews will be prepared by
21
 * setting the appropriate values for each ContentItem such as permalinks. Lastly, this class will compile all of the
22
 * PageViews and write them to the target directory.
23
 *
24
 * @package allejo\stakx\Manager
25
 */
26
class PageManager extends TrackingManager
27
{
28
    /**
29
     * The relative (to the stakx project) file path to the redirect template
30
     *
31
     * @var string|bool
32
     */
33
    private $redirectTemplate;
34
35
    /**
36
     * @var PageView[]
37
     */
38
    private $twigExtendsDeps;
39
40
    /**
41
     * @var ContentItem[][]
42
     */
43
    private $collections;
44
45
    /**
46
     * @var Folder
47
     */
48
    private $targetDir;
49
50
    /**
51
     * @var PageView[]
52
     */
53
    private $flatPages;
54
55
    private $siteMenu;
56
57
    private $twigOpts;
58
59
    /**
60
     * @var \Twig_Environment
61
     */
62
    private $twig;
63
64
    /**
65
     * PageManager constructor
66 1
     */
67 1
    public function __construct()
68 1
    {
69
        parent::__construct();
70 1
71 1
        $this->siteMenu = array();
72
    }
73 1
74
    public function setCollections (&$collections)
75
    {
76
        if (empty($collections)) { return; }
77
78 1
        $this->collections = &$collections;
79
    }
80
81
    public function setRedirectTemplate ($filePath)
82
    {
83
        $this->redirectTemplate = $filePath;
84
    }
85
86
    /**
87
     * @param Folder $folder The relative target directory as specified from the configuration file
88 1
     */
89
    public function setTargetFolder (&$folder)
90 1
    {
91 1
        $this->targetDir = &$folder;
92
    }
93 1
94
    public function configureTwig ($configuration, $options)
95 1
    {
96 1
        $this->twigOpts['configuration'] = $configuration;
97
        $this->twigOpts['options']       = $options;
98 1
99 1
        $this->createTwigManager();
100
    }
101 1
102
    public function createTwigManager ()
103 1
    {
104 1
        $twig = new TwigManager();
105 1
        $twig->configureTwig(
106 1
            $this->twigOpts['configuration'],
107 1
            $this->twigOpts['options']
108
        );
109 1
110 1
        $this->twig = TwigManager::getInstance();
111
    }
112
113
    public function getFlatPages ()
114
    {
115
        return $this->flatPages;
116
    }
117
118
    /**
119
     * An array representing the website's menu structure with children and grandchildren made from static PageViews
120
     *
121
     * @return JailObject[]
122
     */
123
    public function getSiteMenu ()
124
    {
125
        static $jailedMenu = array();
126
127
        if (!empty($jailedMenu)) {
128
            return $jailedMenu;
129
        }
130
131
        foreach ($this->siteMenu as $key => $value)
132
        {
133
            // If it's an array, it means the parent is hidden from the site menu therefore its children should be too
134
            if (is_array($this->siteMenu[$key]))
135
            {
136
                continue;
137
            }
138
139
            $jailedMenu[$key] = $value->createJail();
140
        }
141
142
        return $jailedMenu;
143
    }
144
145
    /**
146
     * Go through all of the PageView directories and create a respective PageView for each and classify them as a
147
     * dynamic or static PageView.
148
     *
149
     * @param $pageViewFolders
150 1
     */
151
    public function parsePageViews ($pageViewFolders)
152 1
    {
153
        if (empty($pageViewFolders)) { return; }
154
155
        /**
156
         * The name of the folder where PageViews are located
157
         *
158
         * @var $pageViewFolder string
159 1
         */
160
        foreach ($pageViewFolders as $pageViewFolderName)
161 1
        {
162
            $pageViewFolder = $this->fs->absolutePath($pageViewFolderName);
163 1
164 1
            if (!$this->fs->exists($pageViewFolder))
165
            {
166
                continue;
167
            }
168
169 1
            // @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...
170 1
            $this->scanTrackableItems($pageViewFolder, array(
171
                'refresh' => false,
172 1
                'fileExplorer' => FileExplorer::INCLUDE_ONLY_FILES
173 1
            ), array('.html', '.twig'));
174 1
            $this->saveFolderDefinition($pageViewFolderName);
175 1
        }
176
    }
177
178
    /**
179
     * Compile dynamic and static PageViews
180 1
     */
181
    public function compileAll ()
182 1
    {
183
        foreach (array_keys($this->trackedItemsFlattened) as $filePath)
184 1
        {
185 1
            $this->compileFromFilePath($filePath);
186 1
        }
187
    }
188
189
    public function compileSome ($filter = array())
190
    {
191
        /** @var PageView $pageView */
192
        foreach ($this->trackedItemsFlattened as $pageView)
193
        {
194
            if ($pageView->hasTwigDependency($filter['namespace'], $filter['dependency']))
195
            {
196
                $this->compilePageView($pageView);
197
            }
198
        }
199
    }
200
201
    /**
202
     * @param ContentItem $contentItem
203
     */
204
    public function compileContentItem (&$contentItem)
205
    {
206
        $pageView = $contentItem->getPageView();
207
208
        // This ContentItem doesn't have an individual PageView dedicated to displaying this item
209
        if (is_null($pageView))
210
        {
211
            return;
212
        }
213
214
        $template = $this->createTemplate($pageView);
215
        $contentItem->evaluateFrontMatter(
216
            $pageView->getFrontMatter(false)
217
        );
218
219
        $output = $template->render(array(
220
            'this' => $contentItem
221
        ));
222
223
        $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
224
    }
225
226
    /**
227
     * Add a new ContentItem to the respective parent PageView of the ContentItem
228
     *
229
     * @param ContentItem $contentItem
230
     */
231
    public function updatePageView ($contentItem)
232
    {
233
        /** @var DynamicPageView $pageView */
234
        foreach ($this->trackedItems['dynamic'] as &$pageView)
235
        {
236
            $fm = $pageView->getFrontMatter(false);
237
238
            if ($fm['collection'] == $contentItem->getCollection())
239
            {
240
                $pageView->addContentItem($contentItem);
241
            }
242
        }
243
    }
244
245
    /**
246
     * Update an existing Twig variable that's injected globally
247
     *
248
     * @param string $variable
249
     * @param string $value
250
     */
251
    public function updateTwigVariable ($variable, $value)
252
    {
253
        $this->twig->addGlobal($variable, $value);
254
    }
255
256
    /**
257
     * {@inheritdoc}
258 1
     */
259
    public function isTracked($filePath)
260 1
    {
261
        return (parent::isTracked($filePath) || isset($this->twigExtendsDeps[$filePath]));
262
    }
263
264
    /**
265
     * {@inheritdoc}
266
     */
267
    public function refreshItem($filePath)
268
    {
269
        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...
270
        {
271
            $this->compileFromFilePath($filePath, true);
272
273
            return;
274
        }
275
276
        $this->createTwigManager();
277
278
        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...
279
        {
280
            $this->compilePageView($pageView);
281
        }
282
    }
283
284
    /**
285
     * {@inheritdoc}
286 1
     */
287
    protected function handleTrackableItem($filePath, $options = array())
288 1
    {
289 1
        $pageView  = PageView::create($filePath);
290
        $namespace = $pageView->getType();
291 1
292 1
        if ($namespace == PageView::DYNAMIC_TYPE)
293
        {
294
            $frontMatter = $pageView->getFrontMatter(false);
295
            $collection = $frontMatter['collection'];
296
297
            foreach ($this->collections[$collection] as &$item)
298
            {
299
                $item->evaluateFrontMatter($frontMatter);
300
                $pageView->addContentItem($item);
301
            }
302
        }
303 1
304 1
        $this->addObjectToTracker($pageView, $pageView->getRelativeFilePath(), $namespace);
305
        $this->saveTrackerOptions($pageView->getRelativeFilePath(), array(
306 1
            'viewType' => $namespace
307
        ));
308 1
309 1
        if ($namespace == PageView::STATIC_TYPE && !empty($pageView['title']))
310 1
        {
311
            $this->addToSiteMenu($pageView);
312 1
            $this->flatPages[$pageView['title']] = $pageView->createJail();
313 1
        }
314 1
    }
315 1
316 1
    /**
317
     * Compile a given PageView
318
     *
319
     * @param string $filePath The file path to the PageView to compile
320
     * @param bool   $refresh  When set to true, the PageView will reread its contents
321
     *
322
     * @throws \Exception
323
     */
324
    private function compileFromFilePath ($filePath, $refresh = false)
325
    {
326 1
        if (!$this->isTracked($filePath))
327
        {
328 1
            throw new TrackedItemNotFoundException('PageView not found');
329 1
        }
330
331
        /** @var DynamicPageView|PageView|RepeaterPageView $pageView */
332
        $pageView = &$this->trackedItemsFlattened[$filePath];
333
334 1
        $this->compilePageView($pageView, $refresh);
335
    }
336 1
337 1
    /**
338
     * @param DynamicPageView|PageView|RepeaterPageView $pageView
339
     * @param bool                                      $refresh
340
     */
341
    private function compilePageView ($pageView, $refresh = false)
342
    {
343 1
        if ($refresh)
344
        {
345
            $pageView->refreshFileContent();
346 1
        }
347
348
        switch ($pageView->getType())
349
        {
350 1
            case PageView::REPEATER_TYPE:
351
                $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...
352 1
                $this->compileExpandedRedirects($pageView);
353 1
                break;
354 1
355 1
            case PageView::DYNAMIC_TYPE:
356
                $this->compileDynamicPageView($pageView);
357 1
                $this->compileNormalRedirects($pageView);
358
                break;
359
360
            case PageView::STATIC_TYPE:
361
                $this->compileStaticPageView($pageView);
362 1
                $this->compileNormalRedirects($pageView);
363 1
                break;
364 1
        }
365 1
    }
366 1
367 1
    /**
368
     * @param RepeaterPageView $pageView
369
     */
370
    private function compileRepeaterPageView (&$pageView)
371
    {
372 1
        $template = $this->createTemplate($pageView);
373
        $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...
374 1
375 1
        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...
376
        {
377 1
            $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...
378
            $pageView->setFrontMatter(array(
379 1
                'permalink' => $permalink->getEvaluated(),
380 1
                'iterators' => $permalink->getIterators()
381 1
            ));
382 1
383 1
            $output = $template->render(array(
384
                'this' => $pageView->createJail()
385 1
            ));
386 1
387 1
            $this->output->notice("Writing repeater file: {file}", array('file' => $pageView->getTargetFile()));
388
            $this->targetDir->writeFile($pageView->getTargetFile(), $output);
389 1
        }
390 1
    }
391 1
392 1
    /**
393
     * @param PageView $pageView
394
     */
395
    private function compileDynamicPageView (&$pageView)
396
    {
397
        $template = $this->createTemplate($pageView);
398
399
        $pageViewFrontMatter = $pageView->getFrontMatter(false);
400
        $collection = $pageViewFrontMatter['collection'];
401
402
        /** @var ContentItem $contentItem */
403
        foreach ($this->collections[$collection] as &$contentItem)
404
        {
405
            $output = $template->render(array(
406
                'this' => $contentItem->createJail()
407
            ));
408
409
            $this->output->notice("Writing file: {file}", array('file' => $contentItem->getTargetFile()));
410
            $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
411
        }
412
    }
413
414
    /**
415
     * @param PageView $pageView
416
     */
417
    private function compileStaticPageView (&$pageView)
418
    {
419 1
        $this->twig->addGlobal('__currentTemplate', $pageView->getFilePath());
420
421 1
        $template = $this->createTemplate($pageView);
422
        $output = $template->render(array(
423 1
            'this' => $pageView->createJail()
424 1
        ));
425 1
426 1
        $this->output->notice("Writing file: {file}", array('file' => $pageView->getTargetFile()));
427
        $this->targetDir->writeFile($pageView->getTargetFile(), $output);
428 1
    }
429 1
430 1
    /**
431
     * @param DynamicPageView|PageView $pageView
432
     */
433
    private function compileNormalRedirects (&$pageView)
434
    {
435 1
        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...
436
        {
437 1
            $redirectPageView = PageView::createRedirect(
438
                $redirect,
439
                $pageView->getPermalink(),
440
                $this->redirectTemplate
441
            );
442
443
            $this->compilePageView($redirectPageView);
444
        }
445
    }
446 1
447 1
    /**
448
     * @param RepeaterPageView $pageView
449
     */
450
    private function compileExpandedRedirects (&$pageView)
451
    {
452 1
        $permalinks = $pageView->getRepeaterPermalinks();
453
454 1
        /** @var ExpandedValue[] $repeaterRedirect */
455
        foreach ($pageView->getRepeaterRedirects() as $repeaterRedirect)
456
        {
457 1
            /**
458
             * @var int           $index
459
             * @var ExpandedValue $redirect
460
             */
461
            foreach ($repeaterRedirect as $index => $redirect)
462
            {
463
                $redirectPageView = PageView::createRedirect(
464
                    $redirect->getEvaluated(),
465
                    $permalinks[$index]->getEvaluated(),
466
                    $this->redirectTemplate
467
                );
468
469
                $this->compilePageView($redirectPageView);
470
            }
471
        }
472
    }
473 1
474 1
    /**
475
     * Add a static PageView to the menu array. Dynamic PageViews are not added to the menu
476
     *
477
     * @param PageView $pageView
478
     */
479
    private function addToSiteMenu (&$pageView)
480
    {
481 1
        $frontMatter = $pageView->getFrontMatter();
482
483 1
        if (isset($frontMatter['menu']) && !$frontMatter['menu'])
484
        {
485 1
            return;
486 1
        }
487
488
        $url = trim($pageView->getPermalink(), '/');
489
490 1
        if (empty($url))
491
        {
492 1
            return;
493 1
        }
494 1
495 1
        $root = &$this->siteMenu;
496
        $dirs = explode('/', $url);
497 1
498 1
        while (count($dirs) > 0)
499
        {
500 1
            $name = array_shift($dirs);
501
            $name = (!empty($name)) ? $name : '.';
502 1
503 1
            if (!is_null($name) && count($dirs) == 0)
504
            {
505 1
                if (isset($root[$name]) && is_array($root[$name]))
506 1
                {
507 1
                    $children = &$pageView->getChildren();
508 1
                    $children = $root[$name]['children'];
509
                }
510
511
                $root[$name] = &$pageView;
512
            }
513 1
            else
514 1
            {
515
                if (!isset($root[$name]['children']))
516
                {
517 1
                    $root[$name]['children'] = array();
518 1
                }
519
520 1
                $root = &$root[$name]['children'];
521 1
            }
522
        }
523
    }
524
525
    /**
526
     * @param PageView $pageView
527
     *
528
     * @return Twig_Template
529 1
     * @throws Twig_Error_Syntax
530
     */
531
    private function createTemplate (&$pageView)
532
    {
533 1
        try
534
        {
535 1
            $template = $this->twig->createTemplate($pageView->getContent());
536
537 1
            $this->trackParentTwigTemplate($template, $pageView);
538
539
            return $template;
540
        }
541
        catch (Twig_Error_Syntax $e)
542
        {
543
            $e->setTemplateLine($e->getTemplateLine() + $pageView->getLineOffset());
544
            $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...
545
546
            throw $e;
547
        }
548
    }
549
550
    /**
551
     * Find the parent Twig templates of the given template and keep a list of it
552
     *
553
     * @param Twig_Template $template The template created from the PageView's content
554 1
     * @param PageView      $pageView The PageView that has this content. Used to keep a reference of PageViews
555
     */
556 1
    private function trackParentTwigTemplate ($template, &$pageView)
557
    {
558
        if (!$this->tracking) { return; }
559
560
        /** @var Twig_Template $parent */
561
        $parent = $template->getParent(array());
562
563
        while ($parent !== false)
564
        {
565
            $filePath = $this->fs->getRelativePath($parent->getSourceContext()->getPath());
566
567
            $this->twigExtendsDeps[$filePath][(string)$pageView->getFilePath()] = &$pageView;
568
            $parent = $parent->getParent(array());
569
        }
570
    }
571
}