Completed
Push — master ( 808f8c...952fde )
by Vladimir
11s
created

Compiler::writeToFilesystem()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 3
crap 1
1
<?php
2
3
/**
4
 * @copyright 2018 Vladimir Jimenez
5
 * @license   https://github.com/stakx-io/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\Event\CompileProcessPostRenderPageView;
19
use allejo\stakx\Event\CompileProcessPreRenderPageView;
20
use allejo\stakx\Event\CompileProcessTemplateCreation;
21
use allejo\stakx\Exception\FileAwareException;
22
use allejo\stakx\Filesystem\FilesystemLoader as fs;
23
use allejo\stakx\Filesystem\FilesystemPath;
24
use allejo\stakx\Filesystem\Folder;
25
use allejo\stakx\FrontMatter\ExpandedValue;
26
use allejo\stakx\Manager\PageManager;
27
use allejo\stakx\Manager\ThemeManager;
28
use allejo\stakx\Templating\TemplateBridgeInterface;
29
use allejo\stakx\Templating\TemplateErrorInterface;
30
use allejo\stakx\Templating\TemplateInterface;
31
use Psr\Log\LoggerInterface;
32
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
33
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
34
35
/**
36
 * This class takes care of rendering the Twig body of PageViews with the respective information and it also takes care
37
 * of writing the rendered Twig to the filesystem.
38
 *
39
 * @internal
40
 *
41
 * @since 0.1.1
42
 */
43
class Compiler
44
{
45
    /** @var string|false */
46
    private $redirectTemplate;
47
48
    /** @var BasePageView[][] */
49
    private $importDependencies;
50
51
    /**
52
     * Any time a PageView extends another template, that relationship is stored in this array. This is necessary so
53
     * when watching a website, we can rebuild the necessary PageViews when these base templates change.
54
     *
55
     * ```
56
     * array['_layouts/base.html.twig'] = &PageView;
57
     * ```
58
     *
59
     * @var TemplateInterface[]
60
     */
61
    private $templateDependencies;
62
63
    /**
64
     * All of the PageViews handled by this Compiler instance indexed by their file paths relative to the site root.
65
     *
66
     * ```
67
     * array['_pages/index.html.twig'] = &PageView;
68
     * ```
69
     *
70
     * @var BasePageView[]
71
     */
72
    private $pageViewsFlattened;
73
74
    /** @var string[] */
75
    private $templateMapping;
76
77
    /** @var Folder */
78
    private $folder;
79
80
    /** @var string */
81
    private $theme;
82
83
    private $templateBridge;
84
    private $pageManager;
85
    private $eventDispatcher;
86
    private $configuration;
87
88 12
    public function __construct(TemplateBridgeInterface $templateBridge, Configuration $configuration, PageManager $pageManager, EventDispatcherInterface $eventDispatcher, LoggerInterface $logger)
89
    {
90 12
        $this->templateBridge = $templateBridge;
91 12
        $this->theme = '';
92 12
        $this->pageManager = $pageManager;
93 12
        $this->eventDispatcher = $eventDispatcher;
94 12
        $this->logger = $logger;
0 ignored issues
show
Bug introduced by
The property logger does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
95 12
        $this->configuration = $configuration;
96
97 12
        $this->pageViewsFlattened = &$pageManager->getPageViewsFlattened();
98 12
        $this->redirectTemplate = $this->configuration->getRedirectTemplate();
99 12
    }
100
101
    /**
102
     * @param Folder $folder
103
     */
104 12
    public function setTargetFolder(Folder $folder)
105
    {
106 12
        $this->folder = $folder;
107 12
    }
108
109
    /**
110
     * @param string $themeName
111
     */
112
    public function setThemeName($themeName)
113
    {
114
        $this->theme = $themeName;
115
    }
116
117
    ///
118
    // Twig parent templates
119
    ///
120
121
    public function isImportDependency($filePath)
122
    {
123
        return isset($this->importDependencies[$filePath]);
124
    }
125
126
    /**
127
     * Check whether a given file path is used as a parent template by a PageView.
128
     *
129
     * @param string $filePath
130
     *
131
     * @return bool
132
     */
133
    public function isParentTemplate($filePath)
134
    {
135
        return isset($this->templateDependencies[$filePath]);
136
    }
137
138
    /**
139
     * Rebuild all of the PageViews that used a given template as a parent.
140
     *
141
     * @param string $filePath The file path to the parent Twig template
142
     */
143
    public function refreshParent($filePath)
144
    {
145
        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...
146
        {
147
            $this->compilePageView($parentTemplate);
148
        }
149
    }
150
151
    public function getTemplateMappings()
152
    {
153
        return $this->templateMapping;
154
    }
155
156
    ///
157
    // IO Functionality
158
    ///
159
160
    /**
161
     * Compile all of the PageViews registered with the compiler.
162
     *
163
     * @since 0.1.0
164
     */
165 12
    public function compileAll()
166
    {
167 12
        foreach ($this->pageViewsFlattened as &$pageView)
168
        {
169 12
            $this->compilePageView($pageView);
170
        }
171 12
    }
172
173
    public function compileImportDependencies($filePath)
174
    {
175
        foreach ($this->importDependencies[$filePath] as &$dependent)
176
        {
177
            $this->compilePageView($dependent);
178
        }
179
    }
180
181
    public function compileSome(array $filter = [])
182
    {
183
        /** @var BasePageView $pageView */
184
        foreach ($this->pageViewsFlattened as &$pageView)
185
        {
186
            $ns = $filter['namespace'];
187
188
            if ($pageView->hasDependencyOnCollection($ns, $filter['dependency']) ||
189
                $pageView->hasDependencyOnCollection($ns, null)
190
            ) {
191
                $this->compilePageView($pageView);
192
            }
193
        }
194
    }
195
196
    /**
197
     * Compile an individual PageView item.
198
     *
199
     * This function will take care of determining *how* to treat the PageView and write the compiled output to a the
200
     * respective target file.
201
     *
202
     * @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...
203
     *
204
     * @since 0.1.1
205
     */
206 12
    public function compilePageView(BasePageView &$pageView)
207
    {
208 12
        $this->templateBridge->setGlobalVariable('__currentTemplate', $pageView->getAbsoluteFilePath());
209 12
        $this->logger->debug('Compiling {type} PageView: {pageview}', [
210 12
            'pageview' => $pageView->getRelativeFilePath(),
211 12
            'type' => $pageView->getType(),
212
        ]);
213
214
        try
215
        {
216 12
            switch ($pageView->getType())
217
            {
218
                case BasePageView::STATIC_TYPE:
219 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...
220 10
                    $this->compileStandardRedirects($pageView);
221 10
                    break;
222
223
                case BasePageView::DYNAMIC_TYPE:
224
                    $this->compileDynamicPageView($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...
225
                    $this->compileStandardRedirects($pageView);
226
                    break;
227
228
                case BasePageView::REPEATER_TYPE:
229 3
                    $this->compileRepeaterPageView($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...
230 3
                    $this->compileExpandedRedirects($pageView);
231 12
                    break;
232
            }
233
        }
234
        catch (TemplateErrorInterface $e)
235
        {
236
            throw new FileAwareException(
237
                $e->getMessage(),
238
                $e->getCode(),
239
                $e,
240
                $pageView->getRelativeFilePath(),
241
                $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...
242
            );
243
        }
244 12
    }
245
246
    /**
247
     * Write the compiled output for a static PageView.
248
     *
249
     * @since 0.1.1
250
     *
251
     * @throws TemplateErrorInterface
252
     */
253 10
    private function compileStaticPageView(StaticPageView &$pageView)
254
    {
255 10
        $pageView->compile();
256
257 10
        $this->writeToFilesystem(
258 10
            $pageView->getTargetFile(),
259 10
            $this->renderStaticPageView($pageView),
260 10
            BasePageView::STATIC_TYPE
261
        );
262 10
    }
263
264
    /**
265
     * Write the compiled output for a dynamic PageView.
266
     *
267
     * @param DynamicPageView $pageView
268
     *
269
     * @since 0.1.1
270
     *
271
     * @throws TemplateErrorInterface
272
     */
273
    private function compileDynamicPageView(DynamicPageView &$pageView)
274
    {
275
        $contentItems = $pageView->getCollectableItems();
276
        $template = $this->createTwigTemplate($pageView);
277
278
        foreach ($contentItems as &$contentItem)
279
        {
280
            if ($contentItem->isDraft() && !Service::getParameter(BuildableCommand::USE_DRAFTS))
281
            {
282
                $this->logger->debug('{file}: marked as a draft', [
283
                    'file' => $contentItem->getRelativeFilePath(),
284
                ]);
285
286
                continue;
287
            }
288
289
            $this->writeToFilesystem(
290
                $contentItem->getTargetFile(),
291
                $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...
292
                BasePageView::DYNAMIC_TYPE
293
            );
294
295
            $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...
296
        }
297
    }
298
299
    /**
300
     * Write the compiled output for a repeater PageView.
301
     *
302
     * @param RepeaterPageView $pageView
303
     *
304
     * @since 0.1.1
305
     *
306
     * @throws TemplateErrorInterface
307
     */
308 3
    private function compileRepeaterPageView(RepeaterPageView &$pageView)
309
    {
310 3
        $pageView->rewindPermalink();
311
312 3
        $template = $this->createTwigTemplate($pageView);
313 3
        $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...
314
315 3
        foreach ($permalinks as $permalink)
316
        {
317 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\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...
318
319 3
            $this->writeToFilesystem(
320 3
                $pageView->getTargetFile(),
321 3
                $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...
322 3
                BasePageView::REPEATER_TYPE
323
            );
324
        }
325 3
    }
326
327
    /**
328
     * Write the given $output to the $targetFile as a $fileType PageView.
329
     *
330
     * @param string $targetFile
331
     * @param string $output
332
     * @param string $fileType
333
     */
334 12
    private function writeToFilesystem($targetFile, $output, $fileType)
335
    {
336 12
        $this->logger->notice('Writing {type} PageView file: {file}', [
337 12
            'type' => $fileType,
338 12
            'file' => $targetFile,
339
        ]);
340 12
        $this->folder->writeFile($targetFile, $output);
341 12
    }
342
343
    /**
344
     * @deprecated
345
     *
346
     * @todo This function needs to be rewritten or removed. Something
347
     *
348
     * @param ContentItem $contentItem
349
     */
350
    public function compileContentItem(ContentItem &$contentItem)
351
    {
352
        $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...
353
        $template = $this->createTwigTemplate($pageView);
354
355
        $this->templateBridge->setGlobalVariable('__currentTemplate', $pageView->getAbsoluteFilePath());
356
        $contentItem->evaluateFrontMatter($pageView->getFrontMatter(false));
357
358
        $targetFile = $contentItem->getTargetFile();
359
        $output = $this->renderDynamicPageView($template, $contentItem);
360
361
        $this->logger->notice('Writing file: {file}', ['file' => $targetFile]);
362
        $this->folder->writeFile($targetFile, $output);
363
    }
364
365
    ///
366
    // Redirect handling
367
    ///
368
369
    /**
370
     * Write redirects for standard redirects.
371
     *
372
     * @throws TemplateErrorInterface
373
     *
374
     * @since 0.1.1
375
     */
376 10
    private function compileStandardRedirects(PermalinkDocument &$pageView)
377
    {
378 10
        $redirects = $pageView->getRedirects();
379
380 10 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...
381
        {
382 1
            $redirectPageView = BasePageView::createRedirect(
383 1
                $redirect,
384 1
                $pageView->getPermalink(),
385 1
                $this->redirectTemplate
386
            );
387 1
            $redirectPageView->evaluateFrontMatter([], [
388 1
                'site' => $this->configuration->getConfiguration(),
389
            ]);
390
391 1
            $this->compileStaticPageView($redirectPageView);
392
        }
393 10
    }
394
395
    /**
396
     * Write redirects for expanded redirects.
397
     *
398
     * @param RepeaterPageView $pageView
399
     *
400
     * @since 0.1.1
401
     */
402 3
    private function compileExpandedRedirects(RepeaterPageView &$pageView)
403
    {
404 3
        $permalinks = $pageView->getRepeaterPermalinks();
405
406
        /** @var ExpandedValue[] $repeaterRedirect */
407 3
        foreach ($pageView->getRepeaterRedirects() as $repeaterRedirect)
408
        {
409
            /**
410
             * @var int
411
             * @var ExpandedValue $redirect
412
             */
413 1 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...
414
            {
415 1
                $redirectPageView = BasePageView::createRedirect(
416 1
                    $redirect->getEvaluated(),
417 1
                    $permalinks[$index]->getEvaluated(),
418 1
                    $this->redirectTemplate
419
                );
420 1
                $redirectPageView->evaluateFrontMatter([], [
421 1
                    'site' => $this->configuration->getConfiguration(),
422
                ]);
423
424 1
                $this->compilePageView($redirectPageView);
425
            }
426
        }
427 3
    }
428
429
    ///
430
    // Twig Functionality
431
    ///
432
433
    /**
434
     * Get the compiled HTML for a specific iteration of a repeater PageView.
435
     *
436
     * @param TemplateInterface $template
437
     * @param RepeaterPageView  $pageView
438
     * @param ExpandedValue     $expandedValue
439
     *
440
     * @since  0.1.1
441
     *
442
     * @return string
443
     */
444 3
    private function renderRepeaterPageView(TemplateInterface &$template, RepeaterPageView &$pageView, ExpandedValue &$expandedValue)
445
    {
446
        $defaultContext = [
447 3
            'this' => $pageView->createJail(),
448
        ];
449
450 3
        $pageView->evaluateFrontMatter([
451 3
            'permalink' => $expandedValue->getEvaluated(),
452 3
            'iterators' => $expandedValue->getIterators(),
453
        ]);
454
455 3
        $preEvent = new CompileProcessPreRenderPageView(BasePageView::REPEATER_TYPE);
456 3
        $this->eventDispatcher->dispatch(CompileProcessPreRenderPageView::NAME, $preEvent);
457
458 3
        $context = array_merge($preEvent->getCustomVariables(), $defaultContext);
459
        $output = $template
460 3
            ->render($context)
461
        ;
462
463 3
        $postEvent = new CompileProcessPostRenderPageView(BasePageView::REPEATER_TYPE, $output);
464 3
        $this->eventDispatcher->dispatch(CompileProcessPostRenderPageView::NAME, $postEvent);
465
466 3
        return $postEvent->getCompiledOutput();
467
    }
468
469
    /**
470
     * Get the compiled HTML for a specific ContentItem.
471
     *
472
     * @since  0.1.1
473
     *
474
     * @return string
475
     */
476 View Code Duplication
    private function renderDynamicPageView(TemplateInterface &$template, TemplateReadyDocument &$twigItem)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
477
    {
478
        $defaultContext = [
479
            'this' => $twigItem->createJail(),
480
        ];
481
482
        $preEvent = new CompileProcessPreRenderPageView(BasePageView::DYNAMIC_TYPE);
483
        $this->eventDispatcher->dispatch(CompileProcessPreRenderPageView::NAME, $preEvent);
484
485
        $content = array_merge($preEvent->getCustomVariables(), $defaultContext);
486
        $output = $template
487
            ->render($content)
488
        ;
489
490
        $postEvent = new CompileProcessPostRenderPageView(BasePageView::DYNAMIC_TYPE, $output);
491
        $this->eventDispatcher->dispatch(CompileProcessPostRenderPageView::NAME, $postEvent);
492
493
        return $postEvent->getCompiledOutput();
494
    }
495
496
    /**
497
     * Get the compiled HTML for a static PageView.
498
     *
499
     * @since  0.1.1
500
     *
501
     * @throws TemplateErrorInterface
502
     *
503
     * @return string
504
     */
505 10 View Code Duplication
    private function renderStaticPageView(StaticPageView &$pageView)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
506
    {
507
        $defaultContext = [
508 10
            'this' => $pageView->createJail(),
509
        ];
510
511 10
        $preEvent = new CompileProcessPreRenderPageView(BasePageView::STATIC_TYPE);
512 10
        $this->eventDispatcher->dispatch(CompileProcessPreRenderPageView::NAME, $preEvent);
513
514 10
        $context = array_merge($preEvent->getCustomVariables(), $defaultContext);
515
        $output = $this
516 10
            ->createTwigTemplate($pageView)
517 10
            ->render($context)
518
        ;
519
520 10
        $postEvent = new CompileProcessPostRenderPageView(BasePageView::STATIC_TYPE, $output);
521 10
        $this->eventDispatcher->dispatch(CompileProcessPostRenderPageView::NAME, $postEvent);
522
523 10
        return $postEvent->getCompiledOutput();
524
    }
525
526
    /**
527
     * Create a Twig template that just needs an array to render.
528
     *
529
     * @since  0.1.1
530
     *
531
     * @throws TemplateErrorInterface
532
     *
533
     * @return TemplateInterface
534
     */
535 12
    private function createTwigTemplate(BasePageView &$pageView)
536
    {
537
        try
538
        {
539 12
            $template = $this->templateBridge->createTemplate($pageView->getContent());
540
541 12
            $this->templateMapping[$template->getTemplateName()] = $pageView->getRelativeFilePath();
542
543 12
            $event = new CompileProcessTemplateCreation($pageView, $template, $this->theme);
544 12
            $this->eventDispatcher->dispatch(CompileProcessTemplateCreation::NAME, $event);
545
546 12
            return $template;
547
        }
548
        catch (TemplateErrorInterface $e)
549
        {
550
            $e
551
                ->setTemplateLine($e->getTemplateLine() + $pageView->getLineOffset())
552
                ->setContent($pageView->getContent())
553
                ->setName($pageView->getRelativeFilePath())
554
                ->setRelativeFilePath($pageView->getRelativeFilePath())
555
                ->buildException()
556
            ;
557
558
            throw $e;
559
        }
560
    }
561
}
562