Completed
Push — master ( 54fa46...73d26f )
by Vladimir
02:25
created

PageManager::parsePageViews()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 26
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 10
nc 4
nop 1
dl 0
loc 26
rs 8.5806
c 2
b 0
f 0
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 Twig_Error_Syntax;
9
use Twig_Template;
10
11
/**
12
 * This class is responsible for handling all of the PageViews within a website.
13
 *
14
 * PageManager will parse all available dynamic and static PageViews. After, dynamic PageViews will be prepared by
15
 * setting the appropriate values for each ContentItem such as permalinks. Lastly, this class will compile all of the
16
 * PageViews and write them to the target directory.
17
 *
18
 * @package allejo\stakx\Manager
19
 */
20
class PageManager extends TrackingManager
21
{
22
    /**
23
     * @var ContentItem[][]
24
     */
25
    private $collections;
26
27
    /**
28
     * @var Folder
29
     */
30
    private $targetDir;
31
32
    private $siteMenu;
33
34
    /**
35
     * @var \Twig_Environment
36
     */
37
    private $twig;
38
39
    /**
40
     * PageManager constructor
41
     */
42
    public function __construct()
43
    {
44
        parent::__construct();
45
    }
46
47
    public function setCollections ($collections)
48
    {
49
        if (empty($collections)) { return; }
50
51
        $this->collections = $collections;
52
    }
53
54
    /**
55
     * @param Folder $folder The relative target directory as specified from the configuration file
56
     */
57
    public function setTargetFolder (&$folder)
58
    {
59
        $this->targetDir = &$folder;
60
    }
61
62
    public function configureTwig ($configuration, $options)
63
    {
64
        $twig = new TwigManager();
65
        $twig->configureTwig($configuration, $options);
66
67
        $this->twig = TwigManager::getInstance();
68
    }
69
70
    /**
71
     * An array representing the website's menu structure with children and grandchildren made from static PageViews
72
     *
73
     * @return array
74
     */
75
    public function getSiteMenu ()
76
    {
77
        return $this->siteMenu;
78
    }
79
80
    /**
81
     * Go through all of the PageView directories and create a respective PageView for each and classify them as a
82
     * dynamic or static PageView.
83
     *
84
     * @param $pageViewFolders
85
     */
86
    public function parsePageViews ($pageViewFolders)
87
    {
88
        if (empty($pageViewFolders)) { return; }
89
90
        /**
91
         * The name of the folder where PageViews are located
92
         *
93
         * @var $pageViewFolder string
94
         */
95
        foreach ($pageViewFolders as $pageViewFolderName)
96
        {
97
            $pageViewFolder = $this->fs->absolutePath($pageViewFolderName);
98
99
            if (!$this->fs->exists($pageViewFolder))
100
            {
101
                continue;
102
            }
103
104
            $finder = $this->fs->getFinder(array(), array(), $pageViewFolder);
105
            $finder->name('/\.(html|twig)/');
106
107
            $this->scanTrackableItems($finder, array(
108
                'refresh' => false
109
            ));
110
        }
111
    }
112
113
    /**
114
     * Compile dynamic and static PageViews
115
     */
116
    public function compileAll ()
117
    {
118
        foreach (array_keys($this->trackedItemsFlattened) as $filePath)
119
        {
120
            $this->compilePageView($filePath);
121
        }
122
    }
123
124
    /**
125
     * @param ContentItem $contentItem
126
     */
127
    public function compileContentItem (&$contentItem)
128
    {
129
        $pageView = $contentItem->getPageView();
130
        $template = $this->createTemplate($pageView);
131
132
        $contentItem->evaluateFrontMatter(
133
            $pageView->getFrontMatter(false)
134
        );
135
136
        $output = $template->render(array(
137
            'this' => $contentItem
138
        ));
139
140
        $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
141
    }
142
143
    /**
144
     * Update an existing Twig variable that's injected globally
145
     *
146
     * @param string $variable
147
     * @param string $value
148
     */
149
    public function updateTwigVariable ($variable, $value)
150
    {
151
        $this->twig->addGlobal($variable, $value);
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157
    public function refreshItem($filePath)
158
    {
159
        $this->compilePageView($filePath, true);
160
    }
161
162
    /**
163
     * {@inheritdoc}
164
     */
165
    protected function handleTrackableItem($filePath, $options = array())
166
    {
167
        $pageView = new PageView($filePath);
168
        $namespace = 'static';
169
170
        if ($pageView->isDynamicPage())
171
        {
172
            $namespace = 'dynamic';
173
            $frontMatter = $pageView->getFrontMatter(false);
174
            $collection = $frontMatter['collection'];
175
176
            foreach ($this->collections[$collection] as &$item)
177
            {
178
                $item->evaluateFrontMatter($frontMatter);
179
                $pageView->addContentItem($item);
180
            }
181
        }
182
183
        $this->addObjectToTracker($pageView, $pageView->getRelativeFilePath(), $namespace);
184
        $this->saveTrackerOptions($pageView->getRelativeFilePath(), array(
185
            'viewType' => $namespace
186
        ));
187
188
        if ($namespace === 'static')
189
        {
190
            $this->addToSiteMenu($pageView->getFrontMatter());
191
        }
192
    }
193
194
    /**
195
     * Compile a given PageView
196
     *
197
     * @param string $filePath The file path to the PageView to compile
198
     * @param bool   $refresh  When set to true, the PageView will reread its contents
199
     *
200
     * @throws \Exception
201
     */
202
    private function compilePageView ($filePath, $refresh = false)
203
    {
204
        if (!$this->isTracked($filePath))
205
        {
206
            throw new \Exception('PageView not found');
207
        }
208
209
        /** @var PageView $pageView */
210
        $pageView = &$this->trackedItemsFlattened[$filePath];
211
        $viewType = $this->trackedItemsOptions[$filePath]['viewType'];
212
213
        if ($refresh)
214
        {
215
            $pageView->refreshFileContent();
216
        }
217
218
        if ($viewType === 'static')
219
        {
220
            $this->compileStaticPageView($pageView);
221
        }
222
        else if ($viewType === 'dynamic')
223
        {
224
            $this->compileDynamicPageView($pageView);
225
        }
226
    }
227
228
    /**
229
     * @param PageView $pageView
230
     */
231
    private function compileDynamicPageView (&$pageView)
232
    {
233
        $template = $this->createTemplate($pageView);
234
235
        $pageViewFrontMatter = $pageView->getFrontMatter(false);
236
        $collection = $pageViewFrontMatter['collection'];
237
238
        /** @var $contentItem ContentItem */
239
        foreach ($this->collections[$collection] as $contentItem)
240
        {
241
            $output = $template->render(array(
242
                'this' => $contentItem
243
            ));
244
245
            $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
246
        }
247
    }
248
249
    /**
250
     * @param PageView $pageView
251
     */
252
    private function compileStaticPageView (&$pageView)
253
    {
254
        $this->twig->addGlobal('__currentTemplate', $pageView->getFilePath());
255
256
        $template = $this->createTemplate($pageView);
257
        $output = $template->render(array(
258
            'this' => $pageView->getFrontMatter()
259
        ));
260
261
        $this->targetDir->writeFile($pageView->getTargetFile(), $output);
262
    }
263
264
    /**
265
     * Add a static PageView to the menu array. Dynamic PageViews are not added to the menu
266
     *
267
     * @param array $frontMatter
268
     */
269
    private function addToSiteMenu ($frontMatter)
270
    {
271
        if (!array_key_exists('permalink', $frontMatter) ||
272
            (array_key_exists('menu', $frontMatter) && !$frontMatter['menu']))
273
        {
274
            return;
275
        }
276
277
        $url = $frontMatter['permalink'];
278
        $root = &$this->siteMenu;
279
        $permalink = trim($url, DIRECTORY_SEPARATOR);
280
        $dirs = explode(DIRECTORY_SEPARATOR, $permalink);
281
282
        while (count($dirs) > 0)
283
        {
284
            $name = array_shift($dirs);
285
            $name = (!empty($name)) ? $name : '.';
286
287
            if (!isset($root[$name]) && !is_null($name) && count($dirs) == 0)
288
            {
289
                $link = (pathinfo($url, PATHINFO_EXTENSION) !== "") ? $url : $permalink . DIRECTORY_SEPARATOR;
290
291
                $root[$name] = array_merge($frontMatter, array(
292
                    "url"  => '/' . $link,
293
                    "children" => array()
294
                ));
295
            }
296
297
            $root = &$root[$name]['children'];
298
        }
299
    }
300
301
    /**
302
     * @param PageView $pageView
303
     *
304
     * @return Twig_Template
305
     * @throws Twig_Error_Syntax
306
     */
307
    private function createTemplate ($pageView)
308
    {
309
        try
310
        {
311
            return $this->twig->createTemplate($pageView->getContent());
312
        }
313
        catch (Twig_Error_Syntax $e)
314
        {
315
            $e->setTemplateFile($pageView->getRelativeFilePath());
316
317
            throw $e;
318
        }
319
    }
320
}