Completed
Push — master ( a41cf5...7efa4f )
by Vladimir
02:55
created

Compiler::refreshParent()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 0
cts 4
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 1
crap 6
1
<?php
2
3
/**
4
 * @copyright 2017 Vladimir Jimenez
5
 * @license   https://github.com/allejo/stakx/blob/master/LICENSE.md MIT
6
 */
7
8
namespace allejo\stakx;
9
10
use allejo\stakx\Command\BuildableCommand;
11
use allejo\stakx\Document\BasePageView;
12
use allejo\stakx\Document\ContentItem;
13
use allejo\stakx\Document\DynamicPageView;
14
use allejo\stakx\Document\PermalinkDocument;
15
use allejo\stakx\Document\RepeaterPageView;
16
use allejo\stakx\Document\StaticPageView;
17
use allejo\stakx\Document\TemplateReadyDocument;
18
use allejo\stakx\Exception\FileAwareException;
19
use allejo\stakx\Filesystem\FilesystemLoader as fs;
20
use allejo\stakx\FrontMatter\ExpandedValue;
21
use allejo\stakx\Manager\BaseManager;
22
use allejo\stakx\Manager\PageManager;
23
use allejo\stakx\Manager\ThemeManager;
24
use allejo\stakx\Filesystem\Folder;
25
use allejo\stakx\System\FilePath;
26
use allejo\stakx\Templating\TemplateBridgeInterface;
27
use allejo\stakx\Templating\TemplateErrorInterface;
28
use allejo\stakx\Templating\TemplateInterface;
29
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
30
31
/**
32
 * This class takes care of rendering the Twig body of PageViews with the respective information and it also takes care
33
 * of writing the rendered Twig to the filesystem.
34
 *
35
 * @internal
36
 *
37
 * @since 0.1.1
38
 */
39
class Compiler extends BaseManager
40
{
41
    /** @var string|false */
42
    private $redirectTemplate;
43
44
    /** @var BasePageView[][] */
45
    private $importDependencies;
46
47
    /**
48
     * Any time a PageView extends another template, that relationship is stored in this array. This is necessary so
49
     * when watching a website, we can rebuild the necessary PageViews when these base templates change.
50
     *
51
     * ```
52
     * array['_layouts/base.html.twig'] = &PageView;
53
     * ```
54
     *
55
     * @var TemplateInterface[]
56
     */
57
    private $templateDependencies;
58
59
    /**
60
     * All of the PageViews handled by this Compiler instance indexed by their file paths relative to the site root.
61
     *
62
     * ```
63
     * array['_pages/index.html.twig'] = &PageView;
64
     * ```
65
     *
66
     * @var BasePageView[]
67
     */
68
    private $pageViewsFlattened;
69
70
    /** @var string[] */
71
    private $templateMapping;
72
73
    /** @var BasePageView[][] */
74
    private $pageViews;
75
76
    /** @var Folder */
77
    private $folder;
78
79
    /** @var string */
80
    private $theme;
81
82
    /** @var TemplateBridgeInterface */
83
    private $templateBridge;
84
85 14
    public function __construct(TemplateBridgeInterface $templateBridge)
86
    {
87 14
        parent::__construct();
88
89 14
        $this->templateBridge = $templateBridge;
90 14
        $this->theme = '';
91 14
    }
92
93
    /**
94
     * @param string|false $template
95
     */
96
    public function setRedirectTemplate($template)
97
    {
98
        $this->redirectTemplate = $template;
99
    }
100
101
    /**
102
     * @param Folder $folder
103
     */
104 14
    public function setTargetFolder(Folder $folder)
105
    {
106 14
        $this->folder = $folder;
107 14
    }
108
109 12
    public function setPageManager(PageManager $manager)
110
    {
111 12
        $this->pageViews = &$manager->getPageViews();
112 12
        $this->pageViewsFlattened = &$manager->getPageViewsFlattened();
113 12
    }
114
115
    /**
116
     * @deprecated Use setPageManager()
117
     *
118
     * @param BasePageView[][] $pageViews
119
     * @param BasePageView[]   $pageViewsFlattened
120
     */
121
    public function setPageViews(array &$pageViews, array &$pageViewsFlattened)
122
    {
123
        $this->pageViews = &$pageViews;
124
        $this->pageViewsFlattened = &$pageViewsFlattened;
125
    }
126
127
    /**
128
     * @param string $themeName
129
     */
130
    public function setThemeName($themeName)
131
    {
132
        $this->theme = $themeName;
133
    }
134
135
    ///
136
    // Twig parent templates
137
    ///
138
139
    public function isImportDependency($filePath)
140
    {
141
        return isset($this->importDependencies[$filePath]);
142
    }
143
144
    /**
145
     * Check whether a given file path is used as a parent template by a PageView
146
     *
147
     * @param  string $filePath
148
     *
149
     * @return bool
150
     */
151
    public function isParentTemplate($filePath)
152
    {
153
        return isset($this->templateDependencies[$filePath]);
154
    }
155
156
    /**
157
     * Rebuild all of the PageViews that used a given template as a parent
158
     *
159
     * @param string $filePath The file path to the parent Twig template
160
     */
161
    public function refreshParent($filePath)
162
    {
163
        foreach ($this->templateDependencies[$filePath] as &$parentTemplate)
0 ignored issues
show
Bug introduced by
The expression $this->templateDependencies[$filePath] of type object<allejo\stakx\Templating\TemplateInterface> is not traversable.
Loading history...
164
        {
165
            $this->compilePageView($parentTemplate);
166
        }
167
    }
168
169
    public function getTemplateMappings()
170
    {
171
        return $this->templateMapping;
172
    }
173
174
    ///
175
    // IO Functionality
176
    ///
177
178
    /**
179
     * Compile all of the PageViews registered with the compiler.
180
     *
181
     * @since 0.1.0
182
     */
183 14
    public function compileAll()
184
    {
185 14
        foreach ($this->pageViewsFlattened as &$pageView)
186
        {
187 14
            $this->compilePageView($pageView);
188
        }
189 14
    }
190
191
    public function compileImportDependencies($filePath)
192
    {
193
        foreach ($this->importDependencies[$filePath] as &$dependent)
194
        {
195
            $this->compilePageView($dependent);
196
        }
197
    }
198
199
    public function compileSome(array $filter = array())
200
    {
201
        /** @var BasePageView $pageView */
202
        foreach ($this->pageViewsFlattened as &$pageView)
203
        {
204
            $ns = $filter['namespace'];
205
206
            if ($pageView->hasDependencyOnCollection($ns, $filter['dependency']) ||
207
                $pageView->hasDependencyOnCollection($ns, null)
208
            ) {
209
                $this->compilePageView($pageView);
210
            }
211
        }
212
    }
213
214
    /**
215
     * Compile an individual PageView from a given path.
216
     *
217
     * @param string $filePath
218
     *
219
     * @throws FileNotFoundException When the given file path isn't tracked by the Compiler.
220
     */
221
    public function compilePageViewFromPath($filePath)
222
    {
223
        if (!isset($this->pageViewsFlattened[$filePath]))
224
        {
225
            throw new FileNotFoundException(sprintf('The "%s" PageView is not being tracked by this compiler.', $filePath));
226
        }
227
228
        $this->compilePageView($this->pageViewsFlattened[$filePath]);
229
    }
230
231
    /**
232
     * Compile an individual PageView item.
233
     *
234
     * This function will take care of determining *how* to treat the PageView and write the compiled output to a the
235
     * respective target file.
236
     *
237
     * @param DynamicPageView|RepeaterPageView|StaticPageView $pageView The PageView that needs to be compiled
0 ignored issues
show
Documentation introduced by
Should the type for parameter $pageView not be BasePageView?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
238
     *
239
     * @since 0.1.1
240
     */
241 14
    public function compilePageView(BasePageView &$pageView)
242
    {
243 14
        $this->templateBridge->setGlobalVariable('__currentTemplate', $pageView->getAbsoluteFilePath());
244 14
        $this->output->debug('Compiling {type} PageView: {pageview}', array(
245 14
            'pageview' => $pageView->getRelativeFilePath(),
246 14
            'type' => $pageView->getType()
247
        ));
248
249
        try
250
        {
251 14
            switch ($pageView->getType())
252
            {
253 14
                case BasePageView::STATIC_TYPE:
254 10
                    $this->compileStaticPageView($pageView);
0 ignored issues
show
Compatibility introduced by
$pageView of type object<allejo\stakx\Document\BasePageView> is not a sub-type of object<allejo\stakx\Document\StaticPageView>. It seems like you assume a child class of the class allejo\stakx\Document\BasePageView 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...
255 10
                    $this->compileStandardRedirects($pageView);
256 10
                    break;
257
258 4
                case BasePageView::DYNAMIC_TYPE:
259 2
                    $this->compileDynamicPageViews($pageView);
0 ignored issues
show
Compatibility introduced by
$pageView of type object<allejo\stakx\Document\BasePageView> is not a sub-type of object<allejo\stakx\Document\DynamicPageView>. It seems like you assume a child class of the class allejo\stakx\Document\BasePageView 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...
260 2
                    $this->compileStandardRedirects($pageView);
261 2
                    break;
262
263 2
                case BasePageView::REPEATER_TYPE:
264 2
                    $this->compileRepeaterPageViews($pageView);
0 ignored issues
show
Compatibility introduced by
$pageView of type object<allejo\stakx\Document\BasePageView> is not a sub-type of object<allejo\stakx\Document\RepeaterPageView>. It seems like you assume a child class of the class allejo\stakx\Document\BasePageView 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...
265 2
                    $this->compileExpandedRedirects($pageView);
266 14
                    break;
267
            }
268
        }
269
        catch (TemplateErrorInterface $e)
270
        {
271
            throw new FileAwareException(
272
                $e->getMessage(),
273
                $e->getCode(),
274
                $e,
275
                $pageView->getRelativeFilePath(),
276
                $e->getTemplateLine() + $pageView->getLineOffset()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface allejo\stakx\Document\PermalinkDocument as the method getLineOffset() does only exist in the following implementations of said interface: allejo\stakx\Document\BasePageView, allejo\stakx\Document\ContentItem, allejo\stakx\Document\DynamicPageView, allejo\stakx\Document\PermalinkFrontMatterDocument, allejo\stakx\Document\RepeaterPageView, allejo\stakx\Document\StaticPageView.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
277
            );
278
        }
279 14
    }
280
281
    /**
282
     * Write the compiled output for a static PageView.
283
     *
284
     * @since 0.1.1
285
     *
286
     * @throws TemplateErrorInterface
287
     */
288 10
    private function compileStaticPageView(StaticPageView &$pageView)
289
    {
290 10
        $pageView->compile();
291
292 10
        $targetFile = $pageView->getTargetFile();
293 10
        $output = $this->renderStaticPageView($pageView);
294
295 10
        $this->output->notice('Writing file: {file}', array('file' => $targetFile));
296 10
        $this->folder->writeFile($targetFile, $output);
297 10
    }
298
299
    /**
300
     * Write the compiled output for a dynamic PageView.
301
     *
302
     * @param DynamicPageView $pageView
303
     *
304
     * @since 0.1.1
305
     *
306
     * @throws TemplateErrorInterface
307
     */
308 2
    private function compileDynamicPageViews(DynamicPageView &$pageView)
309
    {
310 2
        $contentItems = $pageView->getCollectableItems();
311 2
        $template = $this->createTwigTemplate($pageView);
312
313 2
        foreach ($contentItems as &$contentItem)
314
        {
315 2
            if ($contentItem->isDraft() && !Service::getParameter(BuildableCommand::USE_DRAFTS))
316
            {
317 1
                $this->output->debug('{file}: marked as a draft', array(
318 1
                    'file' => $contentItem->getRelativeFilePath()
319
                ));
320
321 1
                continue;
322
            }
323
324 2
            $targetFile = $contentItem->getTargetFile();
325 2
            $output = $this->renderDynamicPageView($template, $contentItem);
0 ignored issues
show
Documentation introduced by
$contentItem is of type object<allejo\stakx\Document\CollectableItem>, but the function expects a object<allejo\stakx\Docu...\TemplateReadyDocument>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
326
327 2
            $this->output->notice('Writing file: {file}', array('file' => $targetFile));
328 2
            $this->folder->writeFile($targetFile, $output);
329
330 2
            $this->compileStandardRedirects($contentItem);
0 ignored issues
show
Documentation introduced by
$contentItem is of type object<allejo\stakx\Docu...\TemplateReadyDocument>, but the function expects a object<allejo\stakx\Document\PermalinkDocument>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
331
        }
332 2
    }
333
334
    /**
335
     * Write the compiled output for a repeater PageView.
336
     *
337
     * @param RepeaterPageView $pageView
338
339
     * @since 0.1.1
340
     *
341
     * @throws TemplateErrorInterface
342
     */
343 2
    private function compileRepeaterPageViews(RepeaterPageView &$pageView)
344
    {
345 2
        $pageView->rewindPermalink();
346
347 2
        $template = $this->createTwigTemplate($pageView);
348 2
        $permalinks = $pageView->getRepeaterPermalinks();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class allejo\stakx\Document\BasePageView as the method getRepeaterPermalinks() does only exist in the following sub-classes of allejo\stakx\Document\BasePageView: allejo\stakx\Document\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...
349
350 2
        foreach ($permalinks as $permalink)
351
        {
352 2
            $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\Document\BasePageView as the method bumpPermalink() does only exist in the following sub-classes of allejo\stakx\Document\BasePageView: allejo\stakx\Document\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...
353 2
            $targetFile = $pageView->getTargetFile();
354 2
            $output = $this->renderRepeaterPageView($template, $pageView, $permalink);
0 ignored issues
show
Compatibility introduced by
$pageView of type object<allejo\stakx\Document\BasePageView> is not a sub-type of object<allejo\stakx\Document\RepeaterPageView>. It seems like you assume a child class of the class allejo\stakx\Document\BasePageView 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...
355
356 2
            $this->output->notice('Writing repeater file: {file}', ['file' => $targetFile]);
357 2
            $this->folder->writeFile($targetFile, $output);
358
        }
359 2
    }
360
361
    /**
362
     * @deprecated
363
     *
364
     * @todo This function needs to be rewritten or removed. Something
365
     *
366
     * @param ContentItem $contentItem
367
     */
368
    public function compileContentItem(ContentItem &$contentItem)
369
    {
370
        $pageView = &$contentItem->getPageView();
0 ignored issues
show
Bug introduced by
The method getPageView() does not seem to exist on object<allejo\stakx\Document\ContentItem>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
371
        $template = $this->createTwigTemplate($pageView);
372
373
        $this->templateBridge->setGlobalVariable('__currentTemplate', $pageView->getAbsoluteFilePath());
374
        $contentItem->evaluateFrontMatter($pageView->getFrontMatter(false));
375
376
        $targetFile = $contentItem->getTargetFile();
377
        $output = $this->renderDynamicPageView($template, $contentItem);
378
379
        $this->output->notice('Writing file: {file}', array('file' => $targetFile));
380
        $this->folder->writeFile($targetFile, $output);
381
    }
382
383
    ///
384
    // Redirect handling
385
    ///
386
387
    /**
388
     * Write redirects for standard redirects.
389
     *
390
     * @throws TemplateErrorInterface
391
     *
392
     * @since 0.1.1
393
     */
394 12
    private function compileStandardRedirects(PermalinkDocument &$pageView)
395
    {
396 12
        $redirects = $pageView->getRedirects();
397
398 12 View Code Duplication
        foreach ($redirects as $redirect)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
399
        {
400 4
            $redirectPageView = BasePageView::createRedirect(
401 4
                $redirect,
402 4
                $pageView->getPermalink(),
403 4
                $this->redirectTemplate
404
            );
405 4
            $redirectPageView->evaluateFrontMatter([], [
406 4
                'site' => $this->container->get(Configuration::class)->getConfiguration(),
407
            ]);
408
409 4
            $this->compileStaticPageView($redirectPageView);
410
        }
411 12
    }
412
413
    /**
414
     * Write redirects for expanded redirects.
415
     *
416
     * @param RepeaterPageView $pageView
417
     *
418
     * @since 0.1.1
419
     */
420 2
    private function compileExpandedRedirects(RepeaterPageView &$pageView)
421
    {
422 2
        $permalinks = $pageView->getRepeaterPermalinks();
423
424
        /** @var ExpandedValue[] $repeaterRedirect */
425 2
        foreach ($pageView->getRepeaterRedirects() as $repeaterRedirect)
426
        {
427
            /**
428
             * @var int           $index
429
             * @var ExpandedValue $redirect
430
             */
431 View Code Duplication
            foreach ($repeaterRedirect as $index => $redirect)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
432
            {
433
                $redirectPageView = BasePageView::createRedirect(
434
                    $redirect->getEvaluated(),
435
                    $permalinks[$index]->getEvaluated(),
436
                    $this->redirectTemplate
437
                );
438
                $redirectPageView->evaluateFrontMatter([], [
439
                    'site' => $this->container->get(Configuration::class)->getConfiguration(),
440
                ]);
441
442
                $this->compilePageView($redirectPageView);
443
            }
444
        }
445 2
    }
446
447
    ///
448
    // Twig Functionality
449
    ///
450
451
    /**
452
     * Get the compiled HTML for a specific iteration of a repeater PageView.
453
     *
454
     * @param TemplateInterface $template
455
     * @param RepeaterPageView  $pageView
456
     * @param ExpandedValue     $expandedValue
457
     *
458
     * @since  0.1.1
459
     *
460
     * @return string
461
     */
462 2
    private function renderRepeaterPageView(TemplateInterface &$template, RepeaterPageView &$pageView, ExpandedValue &$expandedValue)
463
    {
464 2
        $pageView->evaluateFrontMatter([
465 2
            'permalink' => $expandedValue->getEvaluated(),
466 2
            'iterators' => $expandedValue->getIterators(),
467
        ]);
468
469
        return $template
470 2
            ->render(array(
471 2
                'this' => $pageView->createJail(),
472
            ));
473
    }
474
475
    /**
476
     * Get the compiled HTML for a specific ContentItem.
477
     *
478
     * @since  0.1.1
479
     *
480
     * @return string
481
     */
482 2
    private function renderDynamicPageView(TemplateInterface &$template, TemplateReadyDocument &$twigItem)
483
    {
484
        return $template
485 2
            ->render(array(
486 2
                'this' => $twigItem->createJail(),
487
            ));
488
    }
489
490
    /**
491
     * Get the compiled HTML for a static PageView.
492
     *
493
     * @since  0.1.1
494
     *
495
     * @throws TemplateErrorInterface
496
     *
497
     * @return string
498
     */
499 10
    private function renderStaticPageView(StaticPageView &$pageView)
500
    {
501
        return $this
502 10
            ->createTwigTemplate($pageView)
503 10
            ->render(array(
504 10
                'this' => $pageView->createJail(),
0 ignored issues
show
Bug introduced by
The method createJail() does not exist on allejo\stakx\Document\BasePageView. Did you maybe mean create()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
505
            ));
506
    }
507
508
    /**
509
     * Create a Twig template that just needs an array to render.
510
     *
511
     * @since  0.1.1
512
     *
513
     * @throws TemplateErrorInterface
514
     *
515
     * @return TemplateInterface
516
     */
517 14
    private function createTwigTemplate(BasePageView &$pageView)
518
    {
519
        try
520
        {
521 14
            $template = $this->templateBridge->createTemplate($pageView->getContent());
522
523 14
            $this->templateMapping[$template->getTemplateName()] = $pageView->getRelativeFilePath();
524
525 14
            if (Service::getParameter(BuildableCommand::WATCHING))
526
            {
527
                // Keep track of import dependencies
528
                foreach ($pageView->getImportDependencies() as $dependency)
529
                {
530
                    $this->importDependencies[$dependency][$pageView->getBasename()] = &$pageView;
531
                }
532
533
                // Keep track of Twig extends'
534
                $parent = $template->getParentTemplate();
535
536
                while ($parent !== false)
537
                {
538
                    // Replace the '@theme' namespace in Twig with the path to the theme folder and create a UnixFilePath object from the given path
539
                    $path = str_replace('@theme', fs::appendPath(ThemeManager::THEME_FOLDER, $this->theme), $parent->getTemplateName());
540
                    $path = new FilePath($path);
541
542
                    $this->templateDependencies[(string)$path][$pageView->getBasename()] = &$pageView;
543
544
                    $parent = $parent->getParentTemplate();
545
                }
546
            }
547
548 14
            return $template;
549
        }
550
        catch (TemplateErrorInterface $e)
551
        {
552
            $e
553
                ->setTemplateLine($e->getTemplateLine() + $pageView->getLineOffset())
554
                ->setContent($pageView->getContent())
555
                ->setName($pageView->getRelativeFilePath())
556
                ->setRelativeFilePath($pageView->getRelativeFilePath())
557
                ->buildException()
558
            ;
559
560
            throw $e;
561
        }
562
    }
563
}
564