Completed
Push — master ( 6af8c9...1b8281 )
by Vladimir
02:30
created

PageManager::createTemplate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 6
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 13
rs 9.4285
1
<?php
2
3
namespace allejo\stakx\Manager;
4
5
use allejo\stakx\Object\ContentItem;
6
use allejo\stakx\Object\PageView;
7
use allejo\stakx\System\Folder;
8
use Symfony\Component\Finder\Finder;
9
use Twig_Error_Syntax;
10
use Twig_Template;
11
12
/**
13
 * This class is responsible for handling all of the PageViews within a website.
14
 *
15
 * PageManager will parse all available dynamic and static PageViews. After, dynamic PageViews will be prepared by
16
 * setting the appropriate values for each ContentItem such as permalinks. Lastly, this class will compile all of the
17
 * PageViews and write them to the target directory.
18
 *
19
 * @package allejo\stakx\Manager
20
 */
21
class PageManager extends BaseManager
22
{
23
    /**
24
     * @var PageView[]
25
     */
26
    private $dynamicPageViews;
27
28
    /**
29
     * @var PageView[]
30
     */
31
    private $staticPageViews;
32
33
    /**
34
     * @var ContentItem[][]
35
     */
36
    private $collections;
37
38
    /**
39
     * @var Folder
40
     */
41
    private $targetDir;
42
43
    private $siteMenu;
44
45
    /**
46
     * @var \Twig_Environment
47
     */
48
    private $twig;
49
50
    /**
51
     * PageManager constructor
52
     */
53
    public function __construct()
54
    {
55
        parent::__construct();
56
57
        $this->dynamicPageViews = array();
58
        $this->staticPageViews  = array();
59
    }
60
61
    public function configureTwig ($configuration, $options)
62
    {
63
        $twig = new TwigManager();
64
        $twig->configureTwig($configuration, $options);
65
66
        $this->twig = TwigManager::getInstance();
67
    }
68
69
    /**
70
     * An array representing the website's menu structure with children and grandchildren made from static PageViews
71
     *
72
     * @return array
73
     */
74
    public function getSiteMenu ()
75
    {
76
        return $this->siteMenu;
77
    }
78
79
    /**
80
     * Go through all of the PageView directories and create a respective PageView for each and classify them as a
81
     * dynamic or static PageView.
82
     *
83
     * @param $pageViewFolders
84
     */
85
    public function parsePageViews ($pageViewFolders)
86
    {
87
        if (empty($pageViewFolders)) { return; }
88
89
        /**
90
         * The name of the folder where PageViews are located
91
         *
92
         * @var $pageViewFolder string
93
         */
94
        foreach ($pageViewFolders as $pageViewFolderName)
95
        {
96
            $pageViewFolder = $this->fs->absolutePath($pageViewFolderName);
97
98
            if (!$this->fs->exists($pageViewFolder))
99
            {
100
                continue;
101
            }
102
103
            $finder = new Finder();
104
            $finder->files()
105
                   ->name('/\.(html|twig)/')
106
                   ->ignoreDotFiles(true)
107
                   ->ignoreUnreadableDirs()
108
                   ->in($pageViewFolder);
109
110
            foreach ($finder as $viewFile)
111
            {
112
                $newPageView = new PageView($viewFile);
113
                $file_id = $this->fs->getRelativePath($newPageView->getFilePath()->getPathName());
0 ignored issues
show
Bug introduced by
The method getPathName cannot be called on $newPageView->getFilePath() (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
114
115
                if ($newPageView->isDynamicPage())
116
                {
117
                    $this->dynamicPageViews[$file_id] = $newPageView;
118
                }
119
                else
120
                {
121
                    $this->addToSiteMenu($newPageView->getFrontMatter());
122
                    $this->staticPageViews[$file_id] = $newPageView;
123
                }
124
            }
125
        }
126
    }
127
128
    /**
129
     * Go through all of the dynamic PageViews and prepare the necessary information for each one.
130
     *
131
     * For example, permalinks are dynamic generated based on FrontMatter so this function sets the permalink for each
132
     * ContentItem in a collection. This is called before dynamic PageViews are compiled in order to allow access to
133
     * this information to Twig by the time it is compiled.
134
     *
135
     * @param ContentItem[] $collections
136
     */
137
    public function prepareDynamicPageViews ($collections)
138
    {
139
        if (empty($collections)) { return; }
140
141
        $this->collections = $collections;
0 ignored issues
show
Documentation Bug introduced by
It seems like $collections of type array<integer,object<all...kx\Object\ContentItem>> is incompatible with the declared type array<integer,array<inte...x\Object\ContentItem>>> of property $collections.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
142
143
        foreach ($this->dynamicPageViews as &$pageView)
144
        {
145
            $frontMatter = $pageView->getFrontMatter(false);
146
            $collection = $frontMatter['collection'];
147
148
            /** @var $item ContentItem */
149
            foreach ($collections[$collection] as &$item)
0 ignored issues
show
Bug introduced by
The expression $collections[$collection] of type object<allejo\stakx\Object\ContentItem> is not traversable.
Loading history...
150
            {
151
                $item->evaluateFrontMatter($frontMatter);
152
                $pageView->addContentItem($item);
153
            }
154
        }
155
    }
156
157
    /**
158
     * Compile dynamic and static PageViews
159
     *
160
     * @param Folder $targetDir The relative target directory as specified from the configuration file
161
     */
162
    public function compileAll (&$targetDir)
163
    {
164
        $this->targetDir = $targetDir;
165
166
        $this->compileDynamicPageViews();
167
        $this->compileStaticPageViews();
168
    }
169
170
    /**
171
     * Compile a single PageView into the appropriate output path
172
     *
173
     * @param string $filePath
174
     */
175
    public function compileSingle ($filePath)
176
    {
177
        if (array_key_exists($filePath, $this->staticPageViews))
178
        {
179
            $this->output->notice("Compiling static page: {file}", array('file' => $filePath));
180
181
            $this->staticPageViews[$filePath]->refreshFileContent();
182
            $this->compileStaticPageView($this->staticPageViews[$filePath]);
183
184
            return;
185
        }
186
        else if (array_key_exists($filePath, $this->dynamicPageViews))
187
        {
188
            $this->output->notice("Compiling dynamic page: {file}", array('file' => $filePath));
189
190
            $this->dynamicPageViews[$filePath]->refreshFileContent();
191
            $this->compileDynamicPageView($this->dynamicPageViews[$filePath]);
192
193
            return;
194
        }
195
196
        throw new \InvalidArgumentException('The given file path to compile is not a Page View');
197
    }
198
199
    /**
200
     * @param ContentItem $contentItem
201
     */
202
    public function compileContentItem (&$contentItem)
203
    {
204
        $pageView = $contentItem->getPageView();
205
        $template = $this->twig->createTemplate($pageView);
0 ignored issues
show
Documentation introduced by
$pageView is of type object<allejo\stakx\Object\PageView>, but the function expects a string.

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...
206
207
        $contentItem->evaluateFrontMatter(
208
            $pageView->getFrontMatter(false)
209
        );
210
211
        $output = $template->render(array(
212
            'this' => $contentItem
213
        ));
214
215
        $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
216
    }
217
218
    /**
219
     * Check whether or not a given file path is Page View
220
     *
221
     * @param  string $filePath
222
     *
223
     * @return bool True if the file path given is to a Page View
224
     */
225
    public function isPageView ($filePath)
226
    {
227
        return (array_key_exists($filePath, $this->staticPageViews) || array_key_exists($filePath, $this->dynamicPageViews));
228
    }
229
230
    /**
231
     * A dynamic PageView is one that is built from a collection and each collection item deserves its own page. This
232
     * function goes through all of the dynamic PageViews and compiles each page
233
     */
234
    private function compileDynamicPageViews ()
235
    {
236
        foreach ($this->dynamicPageViews as $pageView)
237
        {
238
            $this->compileDynamicPageView($pageView);
239
        }
240
    }
241
242
    /**
243
     * A static PageView is built from a single Twig file and is not automatically rendered based on a collection's
244
     * content. This function goes through all of the static PageViews and compiles them.
245
     *
246
     * @throws \Exception
247
     */
248
    private function compileStaticPageViews ()
249
    {
250
        foreach ($this->staticPageViews as $pageView)
251
        {
252
            $this->compileStaticPageView($pageView);
253
        }
254
    }
255
256
    /**
257
     * @param PageView $pageView
258
     */
259
    private function compileDynamicPageView ($pageView)
260
    {
261
        $template = $this->createTemplate($pageView);
262
263
        $pageViewFrontMatter = $pageView->getFrontMatter(false);
264
        $collection = $pageViewFrontMatter['collection'];
265
266
        /** @var $contentItem ContentItem */
267
        foreach ($this->collections[$collection] as $contentItem)
268
        {
269
            $output = $template->render(array(
270
                'this' => $contentItem
271
            ));
272
273
            $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
274
        }
275
    }
276
277
    /**
278
     * @param PageView $pageView
279
     */
280
    private function compileStaticPageView ($pageView)
281
    {
282
        $this->twig->addGlobal('__currentTemplate', $pageView->getFilePath());
283
284
        $template = $this->createTemplate($pageView);
285
        $output = $template->render(array(
286
            'this' => $pageView->getFrontMatter()
287
        ));
288
289
        $this->targetDir->writeFile($pageView->getTargetFile(), $output);
290
    }
291
292
    /**
293
     * Add a static PageView to the menu array. Dynamic PageViews are not added to the menu
294
     *
295
     * @param array $frontMatter
296
     */
297
    private function addToSiteMenu ($frontMatter)
298
    {
299
        if (!array_key_exists('permalink', $frontMatter) ||
300
            (array_key_exists('menu', $frontMatter) && !$frontMatter['menu']))
301
        {
302
            return;
303
        }
304
305
        $url = $frontMatter['permalink'];
306
        $root = &$this->siteMenu;
307
        $permalink = trim($url, DIRECTORY_SEPARATOR);
308
        $dirs = explode(DIRECTORY_SEPARATOR, $permalink);
309
310
        while (count($dirs) > 0)
311
        {
312
            $name = array_shift($dirs);
313
            $name = (!empty($name)) ? $name : '.';
314
315
            if (!isset($root[$name]) && !is_null($name) && count($dirs) == 0)
316
            {
317
                $link = (pathinfo($url, PATHINFO_EXTENSION) !== "") ? $url : $permalink . DIRECTORY_SEPARATOR;
318
319
                $root[$name] = array_merge($frontMatter, array(
320
                    "url"  => '/' . $link,
321
                    "children" => array()
322
                ));
323
            }
324
325
            $root = &$root[$name]['children'];
326
        }
327
    }
328
329
    /**
330
     * @param PageView $pageView
331
     *
332
     * @return Twig_Template
333
     * @throws Twig_Error_Syntax
334
     */
335
    private function createTemplate ($pageView)
336
    {
337
        try
338
        {
339
            return $this->twig->createTemplate($pageView->getContent());
340
        }
341
        catch (Twig_Error_Syntax $e)
342
        {
343
            $e->setTemplateFile($pageView->getRelativeFilePath());
344
345
            throw $e;
346
        }
347
    }
348
}