Completed
Push — master ( 2eed8d...2bc4b2 )
by Vladimir
02:25
created

PageManager::setTwig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 4
rs 10
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
10
/**
11
 * This class is responsible for handling all of the PageViews within a website.
12
 *
13
 * PageManager will parse all available dynamic and static PageViews. After, dynamic PageViews will be prepared by
14
 * setting the appropriate values for each ContentItem such as permalinks. Lastly, this class will compile all of the
15
 * PageViews and write them to the target directory.
16
 *
17
 * @package allejo\stakx\Manager
18
 */
19
class PageManager extends ItemManager
20
{
21
    /**
22
     * @var PageView[]
23
     */
24
    private $dynamicPageViews;
25
26
    /**
27
     * @var PageView[]
28
     */
29
    private $staticPageViews;
30
31
    /**
32
     * @var ContentItem[][]
33
     */
34
    private $collections;
35
36
    /**
37
     * @var Folder
38
     */
39
    private $targetDir;
40
41
    private $siteMenu;
42
43
    /**
44
     * @var \Twig_Environment
45
     */
46
    private $twig;
47
48
    /**
49
     * PageManager constructor
50
     */
51
    public function __construct()
52
    {
53
        parent::__construct();
54
55
        $this->dynamicPageViews = array();
56
        $this->staticPageViews  = array();
57
    }
58
59
    /**
60
     * Set the Twig environment used by Stakx for all Twig templates
61
     *
62
     * @param \Twig_Environment $twig
63
     */
64
    public function setTwig (&$twig)
65
    {
66
        $this->twig = &$twig;
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
            if (empty($collections[$collection]))
149
            {
150
                continue;
151
            }
152
153
            /** @var $item ContentItem */
154
            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...
155
            {
156
                $item->evaluateFrontMatter($frontMatter);
157
            }
158
        }
159
    }
160
161
    /**
162
     * Compile dynamic and static PageViews
163
     *
164
     * @param Folder $targetDir The relative target directory as specified from the configuration file
165
     */
166
    public function compileAll (&$targetDir)
167
    {
168
        $this->targetDir = $targetDir;
169
170
        $this->compileDynamicPageViews();
171
        $this->compileStaticPageViews();
172
    }
173
174
    /**
175
     * Compile a single PageView into the appropriate output path
176
     *
177
     * @param $filePath
178
     *
179
     * @return bool
180
     */
181
    public function compileSingle ($filePath)
182
    {
183
        if (array_key_exists($filePath, $this->staticPageViews))
184
        {
185
            $this->output->notice("Compiling static page: {file}", array('file' => $filePath));
186
187
            $this->staticPageViews[$filePath]->refreshFileContent();
188
            $this->compileStaticPageView($this->staticPageViews[$filePath]);
189
190
            return true;
191
        }
192
        else if (array_key_exists($filePath, $this->dynamicPageViews))
193
        {
194
            $this->output->notice("Compiling dynamic page: {file}", array('file' => $filePath));
195
196
            $this->dynamicPageViews[$filePath]->refreshFileContent();
197
            $this->compileDynamicPageView($this->dynamicPageViews[$filePath]);
198
199
            return true;
200
        }
201
202
        return false;
203
    }
204
205
    /**
206
     * A dynamic PageView is one that is built from a collection and each collection item deserves its own page. This
207
     * function goes through all of the dynamic PageViews and compiles each page
208
     */
209
    private function compileDynamicPageViews ()
210
    {
211
        foreach ($this->dynamicPageViews as $pageView)
212
        {
213
            $this->compileDynamicPageView($pageView);
214
        }
215
    }
216
217
    /**
218
     * A static PageView is built from a single Twig file and is not automatically rendered based on a collection's
219
     * content. This function goes through all of the static PageViews and compiles them.
220
     *
221
     * @throws \Exception
222
     */
223
    private function compileStaticPageViews ()
224
    {
225
        foreach ($this->staticPageViews as $pageView)
226
        {
227
            $this->compileStaticPageView($pageView);
228
        }
229
    }
230
231
    /**
232
     * @param ContentItem $pageView
233
     *
234
     * @throws \Exception
235
     * @throws \Throwable
236
     */
237
    private function compileDynamicPageView ($pageView)
238
    {
239
        $template = $this->twig->createTemplate($pageView->getContent());
240
241
        $pageViewFrontMatter = $pageView->getFrontMatter(false);
242
        $collection = $pageViewFrontMatter['collection'];
243
244
        /** @var $contentItem ContentItem */
245
        foreach ($this->collections[$collection] as $contentItem)
246
        {
247
            $output = $template->render(array(
248
                'this' => $contentItem
249
            ));
250
251
            $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
252
        }
253
    }
254
255
    /**
256
     * @param ContentItem $pageView
257
     */
258
    private function compileStaticPageView ($pageView)
259
    {
260
        $this->twig->addGlobal('__currentTemplate', $pageView->getFilePath());
261
262
        $template = $this->twig->createTemplate($pageView->getContent());
263
        $output = $template->render(array(
264
            'this' => $pageView->getFrontMatter()
265
        ));
266
267
        $this->targetDir->writeFile($pageView->getTargetFile(), $output);
268
    }
269
270
    /**
271
     * Add a static PageView to the menu array. Dynamic PageViews are not added to the menu
272
     *
273
     * @param array $frontMatter
274
     */
275
    private function addToSiteMenu ($frontMatter)
276
    {
277
        if (!array_key_exists('permalink', $frontMatter) ||
278
            (array_key_exists('menu', $frontMatter) && !$frontMatter['menu']))
279
        {
280
            return;
281
        }
282
283
        $url = $frontMatter['permalink'];
284
        $root = &$this->siteMenu;
285
        $permalink = trim($url, DIRECTORY_SEPARATOR);
286
        $dirs = explode(DIRECTORY_SEPARATOR, $permalink);
287
288
        while (count($dirs) > 0)
289
        {
290
            $name = array_shift($dirs);
291
            $name = (!empty($name)) ? $name : '.';
292
293
            if (!isset($root[$name]) && !is_null($name) && count($dirs) == 0)
294
            {
295
                $link = (pathinfo($url, PATHINFO_EXTENSION) !== "") ? $url : $permalink . DIRECTORY_SEPARATOR;
296
297
                $root[$name] = array_merge($frontMatter, array(
298
                    "url"  => '/' . $link,
299
                    "children" => array()
300
                ));
301
            }
302
303
            $root = &$root[$name]['children'];
304
        }
305
    }
306
}