Completed
Pull Request — master (#69)
by Vladimir
05:00
created

PageManager::parseAssetPageViews()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 17.8

Importance

Changes 0
Metric Value
dl 0
loc 35
ccs 4
cts 20
cp 0.2
rs 9.0488
c 0
b 0
f 0
cc 5
nc 6
nop 0
crap 17.8
1
<?php
2
3
/**
4
 * @copyright 2018 Vladimir Jimenez
5
 * @license   https://github.com/stakx-io/stakx/blob/master/LICENSE.md MIT
6
 */
7
8
namespace allejo\stakx\Manager;
9
10
use allejo\stakx\AssetEngine\AssetEngine;
11
use allejo\stakx\AssetEngine\AssetEngineManager;
12
use allejo\stakx\Configuration;
13
use allejo\stakx\Document\BasePageView;
14
use allejo\stakx\Document\ContentItem;
15
use allejo\stakx\Document\DataItem;
16
use allejo\stakx\Document\DynamicPageView;
17
use allejo\stakx\Document\JailedDocument;
18
use allejo\stakx\Document\RepeaterPageView;
19
use allejo\stakx\Document\StaticPageView;
20
use allejo\stakx\Event\PageViewAdded;
21
use allejo\stakx\Event\PageViewDefinitionAdded;
22
use allejo\stakx\Exception\CollectionNotFoundException;
23
use allejo\stakx\Filesystem\File;
24
use allejo\stakx\Filesystem\FileExplorer;
25
use allejo\stakx\Filesystem\FilesystemLoader as fs;
26
use Psr\Log\LoggerInterface;
27
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
28
29
/**
30
 * This class is responsible for handling all of the PageViews within a website.
31
 *
32
 * PageManager will parse all available dynamic and static PageViews. After, dynamic PageViews will be prepared by
33
 * setting the appropriate values for each ContentItem such as permalinks.
34
 */
35
class PageManager extends TrackingManager
36
{
37
    /** @var StaticPageView[] A place to store a reference to static PageViews with titles. */
38
    private $staticPages;
39
    private $configuration;
40
    private $assetEngineManager;
41
    private $collectionManager;
42
    private $dataManager;
43
    private $eventDispatcher;
44
    private $logger;
45
46
    /**
47
     * PageManager constructor.
48
     */
49 19
    public function __construct(
50
        Configuration $configuration,
51
        AssetEngineManager $assetEngineManager,
52
        CollectionManager $collectionManager,
53
        DataManager $dataManager,
54
        EventDispatcherInterface $eventDispatcher,
55
        LoggerInterface $logger
56
    ) {
57 19
        $this->trackedItems = [
58 19
            BasePageView::STATIC_TYPE => [],
59 19
            BasePageView::DYNAMIC_TYPE => [],
60 19
            BasePageView::REPEATER_TYPE => [],
61
        ];
62 19
        $this->staticPages = [];
63 19
        $this->configuration = $configuration;
64 19
        $this->assetEngineManager = $assetEngineManager;
65 19
        $this->collectionManager = $collectionManager;
66 19
        $this->dataManager = $dataManager;
67 19
        $this->eventDispatcher = $eventDispatcher;
68 19
        $this->logger = $logger;
69 19
    }
70
71
    /**
72
     * {@inheritdoc}
73
     */
74 7
    public function compileManager()
75
    {
76 7
        $this->parseAssetPageViews();
77 7
        $this->parsePageViews($this->configuration->getPageViewFolders());
78 6
    }
79
80 7
    public function parseAssetPageViews()
81
    {
82
        /**
83
         * @var string      $folder
84
         * @var AssetEngine $engine
85
         */
86 7
        foreach ($this->assetEngineManager->getFoldersToWatch() as $folder => $engine)
87
        {
88
            $assetFolder = fs::absolutePath($folder);
0 ignored issues
show
Documentation introduced by
$folder is of type integer|string, but the function expects a object<string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
89
90
            if (!fs::exists($assetFolder))
91
            {
92
                continue;
93
            }
94
95
            $extensions = [];
96
97
            foreach ($engine->getExtensions() as $extension)
98
            {
99
                $extensions[] = "/.{$extension}.twig$/";
100
            }
101
102
            $explorer = FileExplorer::create($assetFolder, [], $extensions, FileExplorer::IGNORE_DIRECTORIES);
103
104
            foreach ($explorer as $file)
105
            {
106
                $assetPageView = new StaticPageView($file);
107
                $compiled = $engine->parse($assetPageView->getContent());
108
                $assetPageView->setContent($compiled);
109
110
                $this->handleTrackableStaticPageView($assetPageView);
111
                $this->addObjectToTracker($assetPageView, $assetPageView->getType());
112
            }
113 7
        }
114 7
    }
115
116
    /**
117
     * Go through all of the PageView directories and create a respective PageView for each and classify them by type.
118
     *
119
     * @param string[] $pageViewFolders
120
     *
121
     * @since 0.1.0
122
     */
123 19
    public function parsePageViews(array $pageViewFolders)
124
    {
125 19
        foreach ($pageViewFolders as $pageViewFolderName)
126
        {
127 19
            $pageViewFolderPath = fs::absolutePath($pageViewFolderName);
0 ignored issues
show
Documentation introduced by
$pageViewFolderName is of type string, but the function expects a object<string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
128
129 19
            if (!fs::exists($pageViewFolderPath))
130 19
            {
131 1
                $this->logger->warning("The '$pageViewFolderName' folder could not be found");
132 1
                continue;
133
            }
134
135 18
            $event = new PageViewDefinitionAdded($pageViewFolderName);
136 18
            $this->eventDispatcher->dispatch(PageViewDefinitionAdded::NAME, $event);
137
138 18
            $this->scanTrackableItems($pageViewFolderPath, [
139 18
                'fileExplorer' => FileExplorer::INCLUDE_ONLY_FILES,
140 18
            ], ['/.html$/', '/.twig$/']);
141 18
        }
142 18
    }
143
144
    /**
145
     * Get all of the PageViews in an associative array with PageView types as the keys.
146
     *
147
     * @since  0.1.1
148
     *
149
     * @return BasePageView[][]
150
     */
151
    public function &getPageViews()
152
    {
153
        return $this->trackedItems;
154
    }
155
156
    /**
157
     * Get all of the PageViews in flat array.
158
     *
159
     * @since  0.1.1
160
     *
161
     * @return BasePageView[]
162
     */
163 17
    public function &getPageViewsFlattened()
164
    {
165 17
        return $this->trackedItemsFlattened;
166
    }
167
168
    /**
169
     * Get the static PageViews tracked by this manager indexed by their title.
170
     *
171
     * @since 0.1.0
172
     *
173
     * @return StaticPageView[]
174
     */
175 1
    public function getStaticPageViews()
176
    {
177 1
        return $this->staticPages;
178
    }
179
180
    /**
181
     * Get the jailed version of the static PageViews indexed by their title.
182
     *
183
     * @since 0.1.0
184
     *
185
     * @return JailedDocument[]
186
     */
187 13
    public function getJailedStaticPageViews()
188
    {
189 13
        $jailedObjects = [];
190
191 13
        foreach ($this->staticPages as $key => $value)
192
        {
193 1
            $jailedObjects[$key] = $value->createJail();
194 13
        }
195
196 13
        return $jailedObjects;
197
    }
198
199
    /**
200
     * Add a new ContentItem to the respective parent PageView of the ContentItem.
201
     *
202
     * @param ContentItem $contentItem
203
     *
204
     * @since 0.1.0
205
     */
206 1
    public function trackNewContentItem(&$contentItem)
207
    {
208 1
        $collection = $contentItem->getNamespace();
209 1
        $this->trackedItems[BasePageView::DYNAMIC_TYPE][$collection]->addCollectableItem($contentItem);
210 1
    }
211
212
    /**
213
     * {@inheritdoc}
214
     */
215 18
    protected function &handleTrackableItem(File $filePath, array $options = [])
216
    {
217 18
        $pageView = BasePageView::create($filePath, [
218 18
            'site' => $this->configuration->getConfiguration(),
219 18
        ]);
220 18
        $namespace = $pageView->getType();
221
222
        switch ($namespace)
223
        {
224 18
            case BasePageView::STATIC_TYPE:
225 11
                $this->handleTrackableStaticPageView($pageView);
0 ignored issues
show
Bug introduced by
It seems like $pageView defined by \allejo\stakx\Document\B...n->getConfiguration())) on line 217 can also be of type object<allejo\stakx\Document\DynamicPageView> or object<allejo\stakx\Document\RepeaterPageView>; however, allejo\stakx\Manager\Pag...ackableStaticPageView() does only seem to accept object<allejo\stakx\Document\StaticPageView>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
226 11
                break;
227
228 7
            case BasePageView::DYNAMIC_TYPE:
229 4
                $this->handleTrackableDynamicPageView($pageView);
0 ignored issues
show
Bug introduced by
It seems like $pageView defined by \allejo\stakx\Document\B...n->getConfiguration())) on line 217 can also be of type object<allejo\stakx\Document\RepeaterPageView> or object<allejo\stakx\Document\StaticPageView>; however, allejo\stakx\Manager\Pag...ckableDynamicPageView() does only seem to accept object<allejo\stakx\Document\DynamicPageView>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
230 3
                break;
231
232 3
            case BasePageView::REPEATER_TYPE:
233 3
                $this->handleTrackableRepeaterPageView($pageView);
0 ignored issues
show
Bug introduced by
It seems like $pageView defined by \allejo\stakx\Document\B...n->getConfiguration())) on line 217 can also be of type object<allejo\stakx\Document\DynamicPageView> or object<allejo\stakx\Document\StaticPageView>; however, allejo\stakx\Manager\Pag...kableRepeaterPageView() does only seem to accept object<allejo\stakx\Document\RepeaterPageView>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
234 3
                break;
235
236
            default:
237
                break;
238
        }
239
240 17
        $event = new PageViewAdded($pageView);
241 17
        $this->eventDispatcher->dispatch(PageViewAdded::NAME, $event);
242
243 17
        $this->addObjectToTracker($pageView, $namespace);
244
245 17
        return $pageView;
246
    }
247
248
    /**
249
     * Handle special behavior and treatment for static PageViews while we're iterating through them.
250
     *
251
     * @param StaticPageView $pageView
252
     *
253
     * @since 0.1.0
254
     */
255 11
    private function handleTrackableStaticPageView(&$pageView)
256
    {
257 11
        $pageView->evaluateFrontMatter([], [
258 11
            'site' => $this->configuration->getConfiguration(),
259 11
        ]);
260
261 11
        if (empty($pageView['title']))
262 11
        {
263 11
            return;
264
        }
265
266 2
        $this->staticPages[$pageView['title']] = &$pageView;
267 2
    }
268
269
    /**
270
     * Handle special behavior and treatment for dynamic PageViews while we're iterating through them.
271
     *
272
     * @param DynamicPageView $pageView
273
     *
274
     * @since 0.1.0
275
     *
276
     * @throws \Exception
277
     */
278 4
    private function handleTrackableDynamicPageView(&$pageView)
279
    {
280 4
        $frontMatter = $pageView->getRawFrontMatter();
281 4
        $dataSource = null;
282 4
        $namespace = null;
283
284 4
        if (isset($frontMatter['collection']))
285 4
        {
286 4
            $dataSource = &$this->collectionManager->getCollections();
287 4
            $namespace = 'collection';
288 4
        }
289
        elseif (isset($frontMatter['dataset']))
290
        {
291
            $dataSource = &$this->dataManager->getDataItems();
292
            $namespace = 'dataset';
293
        }
294
295 4
        if ($dataSource === null)
296 4
        {
297
            throw new \Exception('Invalid Dynamic PageView defined');
298
        }
299
300 4
        $collection = $frontMatter[$namespace];
301
302 4
        if (!isset($dataSource[$collection]))
303 4
        {
304 1
            throw new CollectionNotFoundException("The '$collection' $namespace is not defined");
305
        }
306
307
        /** @var ContentItem|DataItem $item */
308 3
        foreach ($dataSource[$collection] as &$item)
309
        {
310 3
            $item->evaluateFrontMatter($frontMatter, [
311 3
                'site' => $this->configuration->getConfiguration(),
312 3
            ]);
313 3
            $item->saveParentPageView($pageView);
314 3
            $item->buildPermalink(true);
315
316 3
            $pageView->addCollectableItem($item);
317 3
        }
318 3
    }
319
320
    /**
321
     * Handle special behavior and treatment for repeater PageViews while we're iterating through them.
322
     *
323
     * @param RepeaterPageView $pageView
324
     *
325
     * @since 0.2.0
326
     */
327 3
    private function handleTrackableRepeaterPageView(&$pageView)
328
    {
329 3
        $pageView->evaluateFrontMatter([], [
330 3
            'site' => $this->configuration->getConfiguration(),
331 3
        ]);
332 3
        $pageView->configurePermalinks();
333 3
    }
334
}
335