Completed
Push — master ( 505196...f680a5 )
by Vladimir
10s
created

PageManager::parsePageViews()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 38
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

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