Completed
Push — master ( 61017a...a1590e )
by Vladimir
02:25
created

PageManager   D

Complexity

Total Complexity 70

Size/Duplication

Total Lines 577
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 14

Test Coverage

Coverage 71.43%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
dl 0
loc 577
ccs 190
cts 266
cp 0.7143
rs 4.1333
c 4
b 0
f 0
wmc 70
lcom 2
cbo 14

27 Methods

Rating   Name   Duplication   Size   Complexity  
A setCollections() 0 4 1
B parsePageViews() 0 26 4
A __construct() 0 10 1
A setTargetFolder() 0 4 1
A configureTwig() 0 7 1
A getFlatPages() 0 4 1
A setRedirectTemplate() 0 4 1
A getSiteMenu() 0 17 3
A compileAll() 0 7 2
A compileSome() 0 11 3
A compileContentItem() 0 21 2
A updatePageView() 0 13 3
A updateTwigVariable() 0 4 1
A isTracked() 0 4 2
A refreshItem() 0 16 3
B handleTrackableItem() 0 33 6
A createTwigManager() 0 10 1
A compileFromFilePath() 0 20 3
A compilePageView() 0 20 4
A compileRepeaterPageView() 0 21 2
A compileDynamicPageView() 0 23 3
A compileStaticPageView() 0 12 1
A compileNormalRedirects() 0 13 2
A compileExpandedRedirects() 0 23 3
C addToSiteMenu() 0 45 11
A createTemplate() 0 18 2
A trackParentTwigTemplate() 0 15 3

How to fix   Complexity   

Complex Class

Complex classes like PageManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PageManager, and based on these observations, apply Extract Interface, too.

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)
0 ignored issues
show
Unused Code introduced by
The parameter $refresh is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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
            $pageView->refreshFileContent();
362 3
            $this->compilePageView($pageView);
363
        }
364 3
        catch (\Exception $e)
365
        {
366
            throw FileAwareException::castException($e, $filePath);
367
        }
368 3
    }
369
370
    /**
371
     * @param DynamicPageView|RepeaterPageView|PageView $pageView
372
     */
373 3
    private function compilePageView ($pageView)
374
    {
375 3
        switch ($pageView->getType())
376
        {
377 3
            case PageView::REPEATER_TYPE:
378 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...
379 3
                $this->compileExpandedRedirects($pageView);
380 3
                break;
381
382 3
            case PageView::DYNAMIC_TYPE:
383 3
                $this->compileDynamicPageView($pageView);
384 3
                $this->compileNormalRedirects($pageView);
385 3
                break;
386
387 3
            case PageView::STATIC_TYPE:
388 3
                $this->compileStaticPageView($pageView);
389 3
                $this->compileNormalRedirects($pageView);
390 3
                break;
391 3
        }
392 3
    }
393
394
    /**
395
     * @param RepeaterPageView $pageView
396
     */
397 3
    private function compileRepeaterPageView (&$pageView)
398
    {
399 3
        $template = $this->createTemplate($pageView);
400 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...
401
402 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...
403
        {
404 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...
405 3
            $pageView->setFrontMatter(array(
406 3
                'permalink' => $permalink->getEvaluated(),
407 3
                'iterators' => $permalink->getIterators()
408 3
            ));
409
410 3
            $output = $template->render(array(
411 3
                'this' => $pageView->createJail()
412 3
            ));
413
414 3
            $this->output->notice("Writing repeater file: {file}", array('file' => $pageView->getTargetFile()));
415 3
            $this->targetDir->writeFile($pageView->getTargetFile(), $output);
416 3
        }
417 3
    }
418
419
    /**
420
     * @param PageView $pageView
421
     */
422 3
    private function compileDynamicPageView (&$pageView)
423
    {
424 3
        $template = $this->createTemplate($pageView);
425
426 3
        $pageViewFrontMatter = $pageView->getFrontMatter(false);
427 3
        $collection = $pageViewFrontMatter['collection'];
428
429 3
        if (!isset($this->collections[$collection]))
430 3
        {
431
            throw new \RuntimeException("The '$collection' collection is not defined");
432
        }
433
434
        /** @var ContentItem $contentItem */
435 3
        foreach ($this->collections[$collection] as &$contentItem)
436
        {
437 3
            $output = $template->render(array(
438 3
                'this' => $contentItem->createJail()
439 3
            ));
440
441 3
            $this->output->notice("Writing file: {file}", array('file' => $contentItem->getTargetFile()));
442 3
            $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
443 3
        }
444 3
    }
445
446
    /**
447
     * @param PageView $pageView
448
     */
449 3
    private function compileStaticPageView (&$pageView)
450
    {
451 3
        $this->twig->addGlobal('__currentTemplate', $pageView->getFilePath());
452
453 3
        $template = $this->createTemplate($pageView);
454 3
        $output = $template->render(array(
455 3
            'this' => $pageView->createJail()
456 3
        ));
457
458 3
        $this->output->notice("Writing file: {file}", array('file' => $pageView->getTargetFile()));
459 3
        $this->targetDir->writeFile($pageView->getTargetFile(), $output);
460 3
    }
461
462
    /**
463
     * @param DynamicPageView|PageView $pageView
464
     */
465 3
    private function compileNormalRedirects (&$pageView)
466
    {
467 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...
468
        {
469
            $redirectPageView = PageView::createRedirect(
470
                $redirect,
471
                $pageView->getPermalink(),
472
                $this->redirectTemplate
473
            );
474
475
            $this->compilePageView($redirectPageView);
476 3
        }
477 3
    }
478
479
    /**
480
     * @param RepeaterPageView $pageView
481
     */
482 3
    private function compileExpandedRedirects (&$pageView)
483
    {
484 3
        $permalinks = $pageView->getRepeaterPermalinks();
485
486
        /** @var ExpandedValue[] $repeaterRedirect */
487 3
        foreach ($pageView->getRepeaterRedirects() as $repeaterRedirect)
488
        {
489
            /**
490
             * @var int           $index
491
             * @var ExpandedValue $redirect
492
             */
493
            foreach ($repeaterRedirect as $index => $redirect)
494 1
            {
495 1
                $redirectPageView = PageView::createRedirect(
496
                    $redirect->getEvaluated(),
497
                    $permalinks[$index]->getEvaluated(),
498
                    $this->redirectTemplate
499
                );
500
501
                $this->compilePageView($redirectPageView);
502
            }
503 3
        }
504 3
    }
505
506
    /**
507
     * Add a static PageView to the menu array. Dynamic PageViews are not added to the menu
508
     *
509
     * @param PageView $pageView
510
     */
511 3
    private function addToSiteMenu (&$pageView)
512
    {
513 3
        $frontMatter = $pageView->getFrontMatter();
514
515 3
        if (isset($frontMatter['menu']) && !$frontMatter['menu'])
516 3
        {
517
            return;
518
        }
519
520 3
        $url = trim($pageView->getPermalink(), '/');
521
522 3
        if (empty($url))
523 3
        {
524
            return;
525
        }
526
527 3
        $root = &$this->siteMenu;
528 3
        $dirs = explode('/', $url);
529
530 3
        while (count($dirs) > 0)
531
        {
532 3
            $name = array_shift($dirs);
533 3
            $name = (!empty($name)) ? $name : '.';
534
535 3
            if (!is_null($name) && count($dirs) == 0)
536 3
            {
537 3
                if (isset($root[$name]) && is_array($root[$name]))
538 3
                {
539 3
                    $children = &$pageView->getChildren();
540 3
                    $children = $root[$name]['children'];
541 3
                }
542
543 3
                $root[$name] = &$pageView;
544 3
            }
545
            else
546
            {
547 3
                if (!isset($root[$name]['children']))
548 3
                {
549 3
                    $root[$name]['children'] = array();
550 3
                }
551
552 3
                $root = &$root[$name]['children'];
553
            }
554 3
        }
555 3
    }
556
557
    /**
558
     * @param PageView $pageView
559
     *
560
     * @return Twig_Template
561
     * @throws Twig_Error_Syntax
562
     */
563 3
    private function createTemplate (&$pageView)
564
    {
565
        try
566
        {
567 3
            $template = $this->twig->createTemplate($pageView->getContent());
568
569 3
            $this->trackParentTwigTemplate($template, $pageView);
570
571 3
            return $template;
572
        }
573
        catch (Twig_Error_Syntax $e)
574
        {
575
            $e->setTemplateLine($e->getTemplateLine() + $pageView->getLineOffset());
576
            $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...
577
578
            throw $e;
579
        }
580
    }
581
582
    /**
583
     * Find the parent Twig templates of the given template and keep a list of it
584
     *
585
     * @param Twig_Template $template The template created from the PageView's content
586
     * @param PageView      $pageView The PageView that has this content. Used to keep a reference of PageViews
587
     */
588 3
    private function trackParentTwigTemplate ($template, &$pageView)
589
    {
590 3
        if (!$this->tracking) { return; }
591
592
        /** @var Twig_Template $parent */
593
        $parent = $template->getParent(array());
594
595
        while ($parent !== false)
596
        {
597
            $filePath = $this->fs->getRelativePath($parent->getSourceContext()->getPath());
598
599
            $this->twigExtendsDeps[$filePath][(string)$pageView->getFilePath()] = &$pageView;
600
            $parent = $parent->getParent(array());
601
        }
602
    }
603
}