Completed
Push — master ( 599098...2eed8d )
by Vladimir
03:27
created

PageManager::compileSingle()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 12
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 23
rs 9.0856
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
     * An array representing the website's menu structure with children and grandchildren made from static PageViews
61
     *
62
     * @return array
63
     */
64
    public function getSiteMenu ()
65
    {
66
        return $this->siteMenu;
67
    }
68
69
    /**
70
     * Go through all of the PageView directories and create a respective PageView for each and classify them as a
71
     * dynamic or static PageView.
72
     *
73
     * @param $pageViewFolders
74
     */
75
    public function parsePageViews ($pageViewFolders)
76
    {
77
        if (empty($pageViewFolders)) { return; }
78
79
        /**
80
         * The name of the folder where PageViews are located
81
         *
82
         * @var $pageViewFolder string
83
         */
84
        foreach ($pageViewFolders as $pageViewFolderName)
85
        {
86
            $pageViewFolder = $this->fs->absolutePath($pageViewFolderName);
87
88
            if (!$this->fs->exists($pageViewFolder))
89
            {
90
                continue;
91
            }
92
93
            $finder = new Finder();
94
            $finder->files()
95
                   ->name('/\.(html|twig)/')
96
                   ->ignoreDotFiles(true)
97
                   ->ignoreUnreadableDirs()
98
                   ->in($pageViewFolder);
99
100
            foreach ($finder as $viewFile)
101
            {
102
                $newPageView = new PageView($viewFile);
103
                $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...
104
105
                if ($newPageView->isDynamicPage())
106
                {
107
                    $this->dynamicPageViews[$file_id] = $newPageView;
108
                }
109
                else
110
                {
111
                    $this->addToSiteMenu($newPageView->getFrontMatter());
112
                    $this->staticPageViews[$file_id] = $newPageView;
113
                }
114
            }
115
        }
116
    }
117
118
    /**
119
     * Go through all of the dynamic PageViews and prepare the necessary information for each one.
120
     *
121
     * For example, permalinks are dynamic generated based on FrontMatter so this function sets the permalink for each
122
     * ContentItem in a collection. This is called before dynamic PageViews are compiled in order to allow access to
123
     * this information to Twig by the time it is compiled.
124
     *
125
     * @param ContentItem[] $collections
126
     */
127
    public function prepareDynamicPageViews ($collections)
128
    {
129
        if (empty($collections)) { return; }
130
131
        $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...
132
133
        foreach ($this->dynamicPageViews as $pageView)
134
        {
135
            $frontMatter = $pageView->getFrontMatter(false);
136
            $collection = $frontMatter['collection'];
137
138
            if (empty($collections[$collection]))
139
            {
140
                continue;
141
            }
142
143
            /** @var $item ContentItem */
144
            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...
145
            {
146
                $item->evaluateFrontMatter($frontMatter);
147
            }
148
        }
149
    }
150
151
    /**
152
     * Compile dynamic and static PageViews
153
     *
154
     * @param \Twig_Environment $twig        The Twig Environment configured with all of the appropriate extensions
155
     * @param ContentItem[][]   $collections The collections that will be used to compile dynamic PageViews
0 ignored issues
show
Bug introduced by
There is no parameter named $collections. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
156
     * @param Folder            $targetDir   The relative target directory as specified from the configuration file
157
     */
158
    public function compileAll (&$twig, &$targetDir)
159
    {
160
        $this->targetDir = $targetDir;
161
        $this->twig = &$twig;
162
163
        $this->compileDynamicPageViews();
164
        $this->compileStaticPageViews();
165
    }
166
167
    public function compileSingle ($filePath)
168
    {
169
        if (array_key_exists($filePath, $this->staticPageViews))
170
        {
171
            $this->output->notice("Compiling static page: {file}", array('file' => $filePath));
172
173
            $this->staticPageViews[$filePath]->refreshFileContent();
174
            $this->compileStaticPageView($this->staticPageViews[$filePath]);
175
176
            return true;
177
        }
178
        else if (array_key_exists($filePath, $this->dynamicPageViews))
179
        {
180
            $this->output->notice("Compiling dynamic page: {file}", array('file' => $filePath));
181
182
            $this->dynamicPageViews[$filePath]->refreshFileContent();
183
            $this->compileDynamicPageView($this->dynamicPageViews[$filePath]);
184
185
            return true;
186
        }
187
188
        return false;
189
    }
190
191
    /**
192
     * A dynamic PageView is one that is built from a collection and each collection item deserves its own page. This
193
     * function goes through all of the dynamic PageViews and compiles each page
194
     */
195
    private function compileDynamicPageViews ()
196
    {
197
        foreach ($this->dynamicPageViews as $pageView)
198
        {
199
            $this->compileDynamicPageView($pageView);
200
        }
201
    }
202
203
    /**
204
     * A static PageView is built from a single Twig file and is not automatically rendered based on a collection's
205
     * content. This function goes through all of the static PageViews and compiles them.
206
     *
207
     * @throws \Exception
208
     */
209
    private function compileStaticPageViews ()
210
    {
211
        foreach ($this->staticPageViews as $pageView)
212
        {
213
            $this->compileStaticPageView($pageView);
214
        }
215
    }
216
217
    /**
218
     * @param ContentItem $pageView
219
     *
220
     * @throws \Exception
221
     * @throws \Throwable
222
     */
223
    private function compileDynamicPageView ($pageView)
224
    {
225
        $template = $this->twig->createTemplate($pageView->getContent());
226
227
        $pageViewFrontMatter = $pageView->getFrontMatter(false);
228
        $collection = $pageViewFrontMatter['collection'];
229
230
        /** @var $contentItem ContentItem */
231
        foreach ($this->collections[$collection] as $contentItem)
232
        {
233
            $output = $template->render(array(
234
                'this' => $contentItem
235
            ));
236
237
            $this->targetDir->writeFile($contentItem->getTargetFile(), $output);
238
        }
239
    }
240
241
    /**
242
     * @param ContentItem $pageView
243
     */
244
    private function compileStaticPageView ($pageView)
245
    {
246
        $this->twig->addGlobal('__currentTemplate', $pageView->getFilePath());
247
248
        $template = $this->twig->createTemplate($pageView->getContent());
249
        $output = $template->render(array(
250
            'this' => $pageView->getFrontMatter()
251
        ));
252
253
        $this->targetDir->writeFile($pageView->getTargetFile(), $output);
254
    }
255
256
    /**
257
     * Add a static PageView to the menu array. Dynamic PageViews are not added to the menu
258
     *
259
     * @param array $frontMatter
260
     */
261
    private function addToSiteMenu ($frontMatter)
262
    {
263
        if (!array_key_exists('permalink', $frontMatter) ||
264
            (array_key_exists('menu', $frontMatter) && !$frontMatter['menu']))
265
        {
266
            return;
267
        }
268
269
        $url = $frontMatter['permalink'];
270
        $root = &$this->siteMenu;
271
        $permalink = trim($url, DIRECTORY_SEPARATOR);
272
        $dirs = explode(DIRECTORY_SEPARATOR, $permalink);
273
274
        while (count($dirs) > 0)
275
        {
276
            $name = array_shift($dirs);
277
            $name = (!empty($name)) ? $name : '.';
278
279
            if (!isset($root[$name]) && !is_null($name) && count($dirs) == 0)
280
            {
281
                $link = (pathinfo($url, PATHINFO_EXTENSION) !== "") ? $url : $permalink . DIRECTORY_SEPARATOR;
282
283
                $root[$name] = array_merge($frontMatter, array(
284
                    "url"  => '/' . $link,
285
                    "children" => array()
286
                ));
287
            }
288
289
            $root = &$root[$name]['children'];
290
        }
291
    }
292
}