Completed
Pull Request — master (#78)
by Vladimir
04:42 queued 01:10
created

PageManager::getJailedRepeaterPageViews()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.032

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 4
cts 5
cp 0.8
rs 9.9
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2.032
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\Configuration;
11
use allejo\stakx\Document\BasePageView;
12
use allejo\stakx\Document\ContentItem;
13
use allejo\stakx\Document\DataItem;
14
use allejo\stakx\Document\DynamicPageView;
15
use allejo\stakx\Document\JailedDocument;
16
use allejo\stakx\Document\RepeaterPageView;
17
use allejo\stakx\Document\StaticPageView;
18
use allejo\stakx\Event\PageManagerPostProcess;
19
use allejo\stakx\Event\PageManagerPreProcess;
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
    /** @var RepeaterPageView[] A place to store a reference to repeater PageViews with titles. */
40
    private $repeaterPages;
41
    private $configuration;
42
    private $collectionManager;
43
    private $dataManager;
44
    private $eventDispatcher;
45
    private $logger;
46
47
    /**
48
     * PageManager constructor.
49
     */
50 20
    public function __construct(
51
        Configuration $configuration,
52
        CollectionManager $collectionManager,
53
        DataManager $dataManager,
54
        EventDispatcherInterface $eventDispatcher,
55
        LoggerInterface $logger
56
    ) {
57 20
        $this->trackedItems = [
58
            BasePageView::STATIC_TYPE => [],
59
            BasePageView::DYNAMIC_TYPE => [],
60
            BasePageView::REPEATER_TYPE => [],
61
        ];
62 20
        $this->staticPages = [];
63 20
        $this->repeaterPages = [];
64 20
        $this->configuration = $configuration;
65 20
        $this->collectionManager = $collectionManager;
66 20
        $this->dataManager = $dataManager;
67 20
        $this->eventDispatcher = $eventDispatcher;
68 20
        $this->logger = $logger;
69 20
    }
70
71
    /**
72
     * {@inheritdoc}
73
     */
74 7
    public function compileManager()
75
    {
76 7
        $this->parsePageViews($this->configuration->getPageViewFolders());
77 6
    }
78
79
    /**
80
     * Go through all of the PageView directories and create a respective PageView for each and classify them by type.
81
     *
82
     * @param string[] $pageViewFolders
83
     *
84
     * @since 0.1.0
85
     */
86 19
    public function parsePageViews(array $pageViewFolders)
87
    {
88 19
        $preEvent = new PageManagerPreProcess($this);
89 19
        $this->eventDispatcher->dispatch(PageManagerPreProcess::NAME, $preEvent);
90
91 19
        foreach ($pageViewFolders as $pageViewFolderName)
92
        {
93 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...
94
95 19
            if (!fs::exists($pageViewFolderPath))
96
            {
97 1
                $this->logger->warning("The '$pageViewFolderName' folder could not be found");
98 1
                continue;
99
            }
100
101 18
            $event = new PageViewDefinitionAdded($pageViewFolderName);
102 18
            $this->eventDispatcher->dispatch(PageViewDefinitionAdded::NAME, $event);
103
104 18
            $this->scanTrackableItems($pageViewFolderPath, [
105 18
                'fileExplorer' => FileExplorer::INCLUDE_ONLY_FILES,
106 18
            ], ['/.html$/', '/.twig$/']);
107
        }
108
109 18
        $postEvent = new PageManagerPostProcess($this);
110 18
        $this->eventDispatcher->dispatch(PageManagerPostProcess::NAME, $postEvent);
111 18
    }
112
113
    /**
114
     * Get all of the PageViews in an associative array with PageView types as the keys.
115
     *
116
     * @since  0.1.1
117
     *
118
     * @return BasePageView[][]
119
     */
120 1
    public function &getPageViews()
121
    {
122 1
        return $this->trackedItems;
123
    }
124
125
    /**
126
     * Get all of the PageViews in flat array.
127
     *
128
     * @since  0.1.1
129
     *
130
     * @return BasePageView[]
131
     */
132 17
    public function &getPageViewsFlattened()
133
    {
134 17
        return $this->trackedItemsFlattened;
135
    }
136
137
    /**
138
     * Get the static PageViews tracked by this manager indexed by their title.
139
     *
140
     * @since 0.1.0
141
     *
142
     * @return StaticPageView[]
143
     */
144 1
    public function getStaticPageViews()
145
    {
146 1
        return $this->staticPages;
147
    }
148
149
    /**
150
     * Get the jailed version of the static PageViews indexed by their title.
151
     *
152
     * @since 0.1.0
153
     *
154
     * @return JailedDocument[]
155
     */
156 13
    public function getJailedStaticPageViews()
157
    {
158 13
        $jailedObjects = [];
159
160 13
        foreach ($this->staticPages as $key => $value)
161
        {
162 1
            $jailedObjects[$key] = $value->createJail();
163
        }
164
165 13
        return $jailedObjects;
166
    }
167
168
    /**
169
     * Get the jailed version of repeater PageViews indexed by their title.
170
     */
171 12
    public function getJailedRepeaterPageViews()
172
    {
173 12
        $jailedObjects = [];
174
175 12
        foreach ($this->repeaterPages as $key => $value)
176
        {
177
            $jailedObjects[$key]= $value->createJail();
178
        }
179
180 12
        return $jailedObjects;
181
    }
182
183
    /**
184
     * Add a PageView for this PageManager to track.
185
     *
186
     * @param BasePageView|StaticPageView|DynamicPageView|RepeaterPageView $pageView
187
     *
188
     * @throws \LogicException             When a PageView is treated as the wrong type
189
     * @throws CollectionNotFoundException When the collection specified in a Dynamic PageView isn't found
190
     * @throws \Exception                  The permalink could not be built correctly
191
     *
192
     * @since 0.2.0
193
     */
194 19
    public function trackNewPageView(BasePageView $pageView)
195
    {
196 19
        $namespace = $pageView->getType();
197
198 19
        switch ($namespace)
199
        {
200
            case BasePageView::STATIC_TYPE:
201 12
                $this->handleTrackableStaticPageView($pageView);
0 ignored issues
show
Compatibility introduced by
$pageView of type object<allejo\stakx\Document\BasePageView> is not a sub-type of object<allejo\stakx\Document\StaticPageView>. It seems like you assume a child class of the class allejo\stakx\Document\BasePageView to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
202 12
                break;
203
204
            case BasePageView::DYNAMIC_TYPE:
205 4
                $this->handleTrackableDynamicPageView($pageView);
0 ignored issues
show
Compatibility introduced by
$pageView of type object<allejo\stakx\Document\BasePageView> is not a sub-type of object<allejo\stakx\Document\DynamicPageView>. It seems like you assume a child class of the class allejo\stakx\Document\BasePageView to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
206 3
                break;
207
208
            case BasePageView::REPEATER_TYPE:
209 3
                $this->handleTrackableRepeaterPageView($pageView);
0 ignored issues
show
Compatibility introduced by
$pageView of type object<allejo\stakx\Document\BasePageView> is not a sub-type of object<allejo\stakx\Document\RepeaterPageView>. It seems like you assume a child class of the class allejo\stakx\Document\BasePageView to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
210 3
                break;
211
212
            default:
213
                break;
214
        }
215
216 18
        $event = new PageViewAdded($pageView);
217 18
        $this->eventDispatcher->dispatch(PageViewAdded::NAME, $event);
218
219 18
        $this->addObjectToTracker($pageView, $namespace);
220 18
    }
221
222
    /**
223
     * Add a new ContentItem to the respective parent PageView of the ContentItem.
224
     *
225
     * @param ContentItem $contentItem
226
     *
227
     * @since 0.1.0
228
     */
229 1
    public function trackNewContentItem(&$contentItem)
230
    {
231 1
        $collection = $contentItem->getNamespace();
232 1
        $this->trackedItems[BasePageView::DYNAMIC_TYPE][$collection]->addCollectableItem($contentItem);
233 1
    }
234
235
    /**
236
     * {@inheritdoc}
237
     */
238 18
    protected function &handleTrackableItem(File $filePath, array $options = [])
239
    {
240 18
        $pageView = BasePageView::create($filePath, [
241 18
            'site' => $this->configuration->getConfiguration(),
242
        ]);
243
244 18
        $this->trackNewPageView($pageView);
245
246 17
        return $pageView;
247
    }
248
249
    /**
250
     * Handle special behavior and treatment for static PageViews while we're iterating through them.
251
     *
252
     * @param StaticPageView $pageView
253
     *
254
     * @since 0.1.0
255
     */
256 12 View Code Duplication
    private function handleTrackableStaticPageView(&$pageView)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
257
    {
258 12
        $pageView->evaluateFrontMatter([], [
259 12
            'site' => $this->configuration->getConfiguration(),
260
        ]);
261
262 12
        if (empty($pageView['title']))
263
        {
264 12
            return;
265
        }
266
267 2
        $this->staticPages[$pageView['title']] = &$pageView;
268 2
    }
269
270
    /**
271
     * Handle special behavior and treatment for dynamic PageViews while we're iterating through them.
272
     *
273
     * @param DynamicPageView $pageView
274
     *
275
     * @since 0.1.0
276
     *
277
     * @throws \LogicException             An invalid PageView has been given as a Dynamic PageView
278
     * @throws CollectionNotFoundException When a collection or dataset specified in a Dynamic PageView doesn't exist
279
     * @throws \Exception                  When the permalink for the given PageView hasn't been set
280
     */
281 4
    private function handleTrackableDynamicPageView(&$pageView)
282
    {
283 4
        $frontMatter = $pageView->getRawFrontMatter();
284 4
        $dataSource = null;
285 4
        $namespace = null;
286
287 4
        if (isset($frontMatter['collection']))
288
        {
289 4
            $dataSource = &$this->collectionManager->getCollections();
290 4
            $namespace = 'collection';
291
        }
292
        elseif (isset($frontMatter['dataset']))
293
        {
294
            $dataSource = &$this->dataManager->getDataItems();
295
            $namespace = 'dataset';
296
        }
297
298 4
        if ($dataSource === null)
299
        {
300
            throw new \LogicException('Invalid Dynamic PageView defined');
301
        }
302
303 4
        $collection = $frontMatter[$namespace];
304
305 4
        if (!isset($dataSource[$collection]))
306
        {
307 1
            throw new CollectionNotFoundException("The '$collection' $namespace is not defined");
308
        }
309
310
        /** @var ContentItem|DataItem $item */
311 3
        foreach ($dataSource[$collection] as &$item)
312
        {
313 3
            $item->evaluateFrontMatter($frontMatter, [
314 3
                'site' => $this->configuration->getConfiguration(),
315
            ]);
316 3
            $item->saveParentPageView($pageView);
317 3
            $item->buildPermalink(true);
318
319 3
            $pageView->addCollectableItem($item);
320
        }
321 3
    }
322
323
    /**
324
     * Handle special behavior and treatment for repeater PageViews while we're iterating through them.
325
     *
326
     * @param RepeaterPageView $pageView
327
     *
328
     * @since 0.2.0
329
     */
330 3 View Code Duplication
    private function handleTrackableRepeaterPageView(&$pageView)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
331
    {
332 3
        $pageView->evaluateFrontMatter([], [
333 3
            'site' => $this->configuration->getConfiguration(),
334
        ]);
335 3
        $pageView->configurePermalinks();
336
337 3
        if (empty($pageView['title']))
338
        {
339 3
            return;
340
        }
341
342
        $this->repeaterPages[$pageView['title']] = &$pageView;
343
    }
344
}
345