Completed
Push — master ( 827100...0aed89 )
by Vladimir
02:24
created

PageManager::compileFromFilePath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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