Completed
Push — master ( 0ffa26...ca3451 )
by Vladimir
02:21
created

PageManager::compilePageView()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5.3256

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 16
c 1
b 0
f 0
nc 8
nop 2
dl 0
loc 25
ccs 13
cts 17
cp 0.7647
crap 5.3256
rs 8.439
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\PageView;
10
use allejo\stakx\Object\RepeaterPageView;
11
use allejo\stakx\System\FileExplorer;
12
use allejo\stakx\System\Folder;
13
use Twig_Error_Syntax;
14
use Twig_Template;
15
16
/**
17
 * This class is responsible for handling all of the PageViews within a website.
18
 *
19
 * PageManager will parse all available dynamic and static PageViews. After, dynamic PageViews will be prepared by
20
 * setting the appropriate values for each ContentItem such as permalinks. Lastly, this class will compile all of the
21
 * PageViews and write them to the target directory.
22
 *
23
 * @package allejo\stakx\Manager
24
 */
25
class PageManager extends TrackingManager
26
{
27
    /**
28
     * The relative (to the stakx project) file path to the redirect template
29
     *
30
     * @var string|bool
31
     */
32
    private $redirectTemplate;
33
34
    /**
35
     * @var PageView[]
36
     */
37
    private $twigExtendsDeps;
38
39
    /**
40
     * @var ContentItem[][]
41
     */
42
    private $collections;
43
44
    /**
45
     * @var Folder
46
     */
47
    private $targetDir;
48
49
    /**
50
     * @var PageView[]
51
     */
52
    private $flatPages;
53
54
    private $siteMenu;
55
56
    private $twigOpts;
57
58
    /**
59
     * @var \Twig_Environment
60
     */
61
    private $twig;
62
63
    /**
64
     * PageManager constructor
65
     */
66 1
    public function __construct()
67
    {
68 1
        parent::__construct();
69
70 1
        $this->siteMenu = array();
71 1
    }
72
73
    public function setCollections (&$collections)
74
    {
75
        if (empty($collections)) { return; }
76
77
        $this->collections = &$collections;
78
    }
79
80
    public function setRedirectTemplate ($filePath)
81
    {
82
        $this->redirectTemplate = $filePath;
83
    }
84
85
    /**
86
     * @param Folder $folder The relative target directory as specified from the configuration file
87
     */
88 1
    public function setTargetFolder (&$folder)
89
    {
90 1
        $this->targetDir = &$folder;
91 1
    }
92
93 1
    public function configureTwig ($configuration, $options)
94
    {
95 1
        $this->twigOpts['configuration'] = $configuration;
96 1
        $this->twigOpts['options']       = $options;
97
98 1
        $this->createTwigManager();
99 1
    }
100
101 1
    public function createTwigManager ()
102
    {
103 1
        $twig = new TwigManager();
104 1
        $twig->configureTwig(
105 1
            $this->twigOpts['configuration'],
106 1
            $this->twigOpts['options']
107
        );
108
109 1
        $this->twig = TwigManager::getInstance();
110 1
    }
111
112
    public function getFlatPages ()
113
    {
114
        return $this->flatPages;
115
    }
116
117
    /**
118
     * An array representing the website's menu structure with children and grandchildren made from static PageViews
119
     *
120
     * @return array
121
     */
122
    public function getSiteMenu ()
123
    {
124
        static $jailedMenu = array();
125
126
        if (!empty($jailedMenu)) {
127
            return $jailedMenu;
128
        }
129
130
        foreach ($this->siteMenu as $key => $value)
131
        {
132
            // If it's an array, it means the parent is hidden from the site menu therefore its children should be too
133
            if (is_array($this->siteMenu[$key]))
134
            {
135
                continue;
136
            }
137
138
            $jailedMenu[$key] = $value->createJail();
139
        }
140
141
        return $jailedMenu;
142
    }
143
144
    /**
145
     * Go through all of the PageView directories and create a respective PageView for each and classify them as a
146
     * dynamic or static PageView.
147
     *
148
     * @param $pageViewFolders
149
     */
150 1
    public function parsePageViews ($pageViewFolders)
151
    {
152 1
        if (empty($pageViewFolders)) { return; }
153
154
        /**
155
         * The name of the folder where PageViews are located
156
         *
157
         * @var $pageViewFolder string
158
         */
159 1
        foreach ($pageViewFolders as $pageViewFolderName)
160
        {
161 1
            $pageViewFolder = $this->fs->absolutePath($pageViewFolderName);
162
163 1
            if (!$this->fs->exists($pageViewFolder))
164
            {
165
                continue;
166
            }
167
168
            // @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...
169 1
            $this->scanTrackableItems($pageViewFolder, array(
170 1
                'refresh' => false,
171
                'fileExplorer' => FileExplorer::INCLUDE_ONLY_FILES
172 1
            ), array('.html', '.twig'));
173 1
            $this->saveFolderDefinition($pageViewFolderName);
174
        }
175 1
    }
176
177
    /**
178
     * Compile dynamic and static PageViews
179
     */
180 1
    public function compileAll ()
181
    {
182 1
        foreach (array_keys($this->trackedItemsFlattened) as $filePath)
183
        {
184 1
            $this->compileFromFilePath($filePath);
185
        }
186 1
    }
187
188
    public function compileSome ($filter = array())
189
    {
190
        /** @var PageView $pageView */
191
        foreach ($this->trackedItemsFlattened as $pageView)
192
        {
193
            if ($pageView->hasTwigDependency($filter['namespace'], $filter['dependency']))
194
            {
195
                $this->compilePageView($pageView);
196
            }
197
        }
198
    }
199
200
    /**
201
     * @param ContentItem $contentItem
202
     */
203
    public function compileContentItem (&$contentItem)
204
    {
205
        $pageView = $contentItem->getPageView();
206
207
        // This ContentItem doesn't have an individual PageView dedicated to displaying this item
208
        if (is_null($pageView))
209
        {
210
            return;
211
        }
212
213
        $template = $this->createTemplate($pageView);
214
        $contentItem->evaluateFrontMatter(
215
            $pageView->getFrontMatter(false)
216
        );
217
218
        $output = $template->render(array(
219
            'this' => $contentItem
220
        ));
221
222
        $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
223
    }
224
225
    /**
226
     * Add a new ContentItem to the respective parent PageView of the ContentItem
227
     *
228
     * @param ContentItem $contentItem
229
     */
230
    public function updatePageView ($contentItem)
231
    {
232
        /** @var DynamicPageView $pageView */
233
        foreach ($this->trackedItems['dynamic'] as &$pageView)
234
        {
235
            $fm = $pageView->getFrontMatter(false);
236
237
            if ($fm['collection'] == $contentItem->getCollection())
238
            {
239
                $pageView->addContentItem($contentItem);
240
            }
241
        }
242
    }
243
244
    /**
245
     * Update an existing Twig variable that's injected globally
246
     *
247
     * @param string $variable
248
     * @param string $value
249
     */
250
    public function updateTwigVariable ($variable, $value)
251
    {
252
        $this->twig->addGlobal($variable, $value);
253
    }
254
255
    /**
256
     * {@inheritdoc}
257
     */
258 1
    public function isTracked($filePath)
259
    {
260 1
        return (parent::isTracked($filePath) || isset($this->twigExtendsDeps[$filePath]));
261
    }
262
263
    /**
264
     * {@inheritdoc}
265
     */
266
    public function refreshItem($filePath)
267
    {
268
        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...
269
        {
270
            $this->compileFromFilePath($filePath, true);
271
272
            return;
273
        }
274
275
        $this->createTwigManager();
276
277
        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...
278
        {
279
            $this->compilePageView($pageView);
280
        }
281
    }
282
283
    /**
284
     * {@inheritdoc}
285
     */
286 1
    protected function handleTrackableItem($filePath, $options = array())
287
    {
288 1
        $pageView  = PageView::create($filePath);
289 1
        $namespace = $pageView->getType();
290
291 1
        if ($namespace == PageView::DYNAMIC_TYPE)
292
        {
293
            $frontMatter = $pageView->getFrontMatter(false);
294
            $collection = $frontMatter['collection'];
295
296
            foreach ($this->collections[$collection] as &$item)
297
            {
298
                $item->evaluateFrontMatter($frontMatter);
299
                $pageView->addContentItem($item);
300
            }
301
        }
302
303 1
        $this->addObjectToTracker($pageView, $pageView->getRelativeFilePath(), $namespace);
304 1
        $this->saveTrackerOptions($pageView->getRelativeFilePath(), array(
305 1
            'viewType' => $namespace
306
        ));
307
308 1
        if ($namespace == PageView::STATIC_TYPE)
309
        {
310 1
            $this->addToSiteMenu($pageView);
311
312 1
            if (!empty($pageView->title)) {
0 ignored issues
show
Documentation introduced by
The property title does not exist on object<allejo\stakx\Object\PageView>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
313 1
                $this->flatPages[$pageView->title] = $pageView->createJail();
0 ignored issues
show
Documentation introduced by
The property title does not exist on object<allejo\stakx\Object\PageView>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
314
            }
315
        }
316 1
    }
317
318
    /**
319
     * Compile a given PageView
320
     *
321
     * @param string $filePath The file path to the PageView to compile
322
     * @param bool   $refresh  When set to true, the PageView will reread its contents
323
     *
324
     * @throws \Exception
325
     */
326 1
    private function compileFromFilePath ($filePath, $refresh = false)
327
    {
328 1
        if (!$this->isTracked($filePath))
329
        {
330
            throw new TrackedItemNotFoundException('PageView not found');
331
        }
332
333
        /** @var DynamicPageView|PageView|RepeaterPageView $pageView */
334 1
        $pageView = &$this->trackedItemsFlattened[$filePath];
335
336 1
        $this->compilePageView($pageView, $refresh);
337 1
    }
338
339
    /**
340
     * @param DynamicPageView|PageView|RepeaterPageView $pageView
341
     * @param bool                                      $refresh
342
     */
343 1
    private function compilePageView ($pageView, $refresh = false)
344
    {
345 1
        if ($refresh)
346
        {
347
            $pageView->refreshFileContent();
348
        }
349
350 1
        switch ($pageView->getType())
351
        {
352 1
            case PageView::REPEATER_TYPE:
353 1
                $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...
354 1
                $this->compileExpandedRedirects($pageView);
355 1
                break;
356
357 1
            case PageView::DYNAMIC_TYPE:
358
                $this->compileDynamicPageView($pageView);
359
                $this->compileNormalRedirects($pageView);
360
                break;
361
362 1
            case PageView::STATIC_TYPE:
363 1
                $this->compileStaticPageView($pageView);
364 1
                $this->compileNormalRedirects($pageView);
365 1
                break;
366
        }
367 1
    }
368
369
    /**
370
     * @param RepeaterPageView $pageView
371
     */
372 1
    private function compileRepeaterPageView (&$pageView)
373
    {
374 1
        $template = $this->createTemplate($pageView);
375 1
        $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...
376
377 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...
378
        {
379 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...
380 1
            $pageView->setFrontMatter(array(
381 1
                'permalink' => $permalink->getEvaluated(),
382 1
                'iterators' => $permalink->getIterators()
383
            ));
384
385 1
            $output = $template->render(array(
386 1
                'this' => $pageView->createJail()
387
            ));
388
389 1
            $this->output->notice("Writing repeater file: {file}", array('file' => $pageView->getTargetFile()));
390 1
            $this->targetDir->writeFile($pageView->getTargetFile(), $output);
391
        }
392 1
    }
393
394
    /**
395
     * @param PageView $pageView
396
     */
397
    private function compileDynamicPageView (&$pageView)
398
    {
399
        $template = $this->createTemplate($pageView);
400
401
        $pageViewFrontMatter = $pageView->getFrontMatter(false);
402
        $collection = $pageViewFrontMatter['collection'];
403
404
        /** @var ContentItem $contentItem */
405
        foreach ($this->collections[$collection] as &$contentItem)
406
        {
407
            $output = $template->render(array(
408
                'this' => $contentItem->createJail()
409
            ));
410
411
            $this->output->notice("Writing file: {file}", array('file' => $contentItem->getTargetFile()));
412
            $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
413
        }
414
    }
415
416
    /**
417
     * @param PageView $pageView
418
     */
419 1
    private function compileStaticPageView (&$pageView)
420
    {
421 1
        $this->twig->addGlobal('__currentTemplate', $pageView->getFilePath());
422
423 1
        $template = $this->createTemplate($pageView);
424 1
        $output = $template->render(array(
425 1
            'this' => $pageView->createJail()
426
        ));
427
428 1
        $this->output->notice("Writing file: {file}", array('file' => $pageView->getTargetFile()));
429 1
        $this->targetDir->writeFile($pageView->getTargetFile(), $output);
430 1
    }
431
432
    /**
433
     * @param DynamicPageView|PageView $pageView
434
     */
435 1
    private function compileNormalRedirects (&$pageView)
436
    {
437 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...
438
        {
439
            $redirectPageView = PageView::createRedirect(
440
                $redirect,
441
                $pageView->getPermalink(),
442
                $this->redirectTemplate
443
            );
444
445
            $this->compilePageView($redirectPageView);
446
        }
447 1
    }
448
449
    /**
450
     * @param RepeaterPageView $pageView
451
     */
452 1
    private function compileExpandedRedirects (&$pageView)
453
    {
454 1
        $permalinks = $pageView->getRepeaterPermalinks();
455
456
        /** @var ExpandedValue[] $repeaterRedirect */
457 1
        foreach ($pageView->getRepeaterRedirects() as $repeaterRedirect)
458
        {
459
            /**
460
             * @var int           $index
461
             * @var ExpandedValue $redirect
462
             */
463
            foreach ($repeaterRedirect as $index => $redirect)
464
            {
465
                $redirectPageView = PageView::createRedirect(
466
                    $redirect->getEvaluated(),
467
                    $permalinks[$index]->getEvaluated(),
468
                    $this->redirectTemplate
469
                );
470
471
                $this->compilePageView($redirectPageView);
472
            }
473
        }
474 1
    }
475
476
    /**
477
     * Add a static PageView to the menu array. Dynamic PageViews are not added to the menu
478
     *
479
     * @param PageView $pageView
480
     */
481 1
    private function addToSiteMenu (&$pageView)
482
    {
483 1
        $frontMatter = $pageView->getFrontMatter();
484
485 1
        if (isset($frontMatter['menu']) && !$frontMatter['menu'])
486
        {
487
            return;
488
        }
489
490 1
        $url = trim($pageView->getPermalink(), '/');
491
492 1
        if (empty($url))
493
        {
494
            return;
495
        }
496
497 1
        $root = &$this->siteMenu;
498 1
        $dirs = explode('/', $url);
499
500 1
        while (count($dirs) > 0)
501
        {
502 1
            $name = array_shift($dirs);
503 1
            $name = (!empty($name)) ? $name : '.';
504
505 1
            if (!is_null($name) && count($dirs) == 0)
506
            {
507 1
                if (isset($root[$name]) && is_array($root[$name]))
508
                {
509
                    $children = &$pageView->getChildren();
510
                    $children = $root[$name]['children'];
511
                }
512
513 1
                $root[$name] = &$pageView;
514
            }
515
            else
516
            {
517
                $root[$name]['children'] = array();
518
                $root = &$root[$name]['children'];
519
            }
520
        }
521 1
    }
522
523
    /**
524
     * @param PageView $pageView
525
     *
526
     * @return Twig_Template
527
     * @throws Twig_Error_Syntax
528
     */
529 1
    private function createTemplate (&$pageView)
530
    {
531
        try
532
        {
533 1
            $template = $this->twig->createTemplate($pageView->getContent());
534
535 1
            $this->trackParentTwigTemplate($template, $pageView);
536
537 1
            return $template;
538
        }
539
        catch (Twig_Error_Syntax $e)
540
        {
541
            $e->setTemplateLine($e->getTemplateLine() + $pageView->getLineOffset());
542
            $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...
543
544
            throw $e;
545
        }
546
    }
547
548
    /**
549
     * Find the parent Twig templates of the given template and keep a list of it
550
     *
551
     * @param Twig_Template $template The template created from the PageView's content
552
     * @param PageView      $pageView The PageView that has this content. Used to keep a reference of PageViews
553
     */
554 1
    private function trackParentTwigTemplate ($template, &$pageView)
555
    {
556 1
        if (!$this->tracking) { return; }
557
558
        /** @var Twig_Template $parent */
559
        $parent = $template->getParent(array());
560
561
        while ($parent !== false)
562
        {
563
            $filePath = $this->fs->getRelativePath($parent->getSourceContext()->getPath());
564
565
            $this->twigExtendsDeps[$filePath][(string)$pageView->getFilePath()] = &$pageView;
566
            $parent = $parent->getParent(array());
567
        }
568
    }
569
}