Passed
Push — master ( ee6060...4c211f )
by Brent
02:40
created

CollectionAdapter::transformPage()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 43
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 27
nc 4
nop 2
dl 0
loc 43
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
namespace Brendt\Stitcher\Adapter;
4
5
use Brendt\Html\Meta\Meta;
6
use Brendt\Stitcher\Exception\ConfigurationException;
7
use Brendt\Stitcher\Exception\IdFieldNotFoundException;
8
use Brendt\Stitcher\Exception\VariableNotFoundException;
9
use Brendt\Stitcher\Factory\AdapterFactory;
10
use Brendt\Stitcher\factory\ParserFactory;
11
use Brendt\Stitcher\Site\Meta\MetaCompiler;
12
use Brendt\Stitcher\Site\Page;
13
14
/**
15
 * The CollectionAdapter takes a page with a collection of entries, and generates a detail page for each entry in the
16
 * collection.
17
 *
18
 * Sample configuration:
19
 *
20
 *  /examples/{id}:
21
 *      template: examples/detail
22
 *      data:
23
 *          variableName: collection.yml
24
 *      adapters:
25
 *          variableName:
26
 *              variable: example
27
 *              field: id
28
 */
29
class CollectionAdapter extends AbstractAdapter
30
{
31
    /**
32
     * @var MetaCompiler
33
     */
34
    private $metaCompiler;
35
36
    public function __construct(ParserFactory $parserFactory, MetaCompiler $metaCompiler) {
37
        parent::__construct($parserFactory);
38
39
        $this->metaCompiler = $metaCompiler;
40
    }
41
42
    /**
43
     * @param Page $page
44
     * @param null $filter
45
     *
46
     * @return Page[]
47
     */
48
    public function transformPage(Page $page, $filter = null) : array {
49
        $config = $page->getAdapterConfig(AdapterFactory::COLLECTION_ADAPTER);
50
51
        $this->validateConfig($config, $page);
52
53
        $variable = $config['variable'];
54
        $field = $config['field'];
55
        $entries = $this->getData($page->getVariable($variable));
56
        $pageId = $page->getId();
57
58
        reset($entries);
59
        $result = [];
60
        while ($entry = current($entries)) {
61
            if (!isset($entry[$field]) || ($filter && $entry[$field] !== $filter)) {
62
                next($entries);
63
64
                continue;
65
            }
66
67
            $fieldValue = $entry[$field];
68
69
            $url = str_replace('{' . $field . '}', $fieldValue, $pageId);
70
            $entryPage = clone $page;
71
            $entryPage->meta = new Meta();
72
73
            foreach ($entry as $entryVariableName => $entryVariableValue) {
74
                $this->metaCompiler->compilePageVariable($entryPage, $entryVariableName, $entryVariableValue);
75
            }
76
77
78
            $entryPage
79
                ->removeAdapter(AdapterFactory::COLLECTION_ADAPTER)
80
                ->setVariableValue($variable, $entry)
81
                ->setVariableIsParsed($variable)
82
                ->setId($url);
83
84
            $this->parseBrowseData($entryPage, $entries);
85
            
86
            $result[$url] = $entryPage;
87
        }
88
89
        return $result;
90
    }
91
92
    /**
93
     * @param Page  $entryPage
94
     * @param array $entries
95
     *
96
     * @return void
97
     */
98
    private function parseBrowseData(Page $entryPage, array &$entries) {
99
        if ($entryPage->getVariable('browse')) {
100
            return;
101
        }
102
103
        $prev = prev($entries);
104
105
        if (!$prev) {
106
            reset($entries);
107
        } else {
108
            next($entries);
109
        }
110
111
        $next = next($entries);
112
113
        $entryPage->setVariableValue('browse', [
114
            'prev' => $prev,
115
            'next' => $next,
116
        ])->setVariableIsParsed('browse');
117
    }
118
119
    /**
120
     * @param array $config
121
     * @param Page  $page
122
     *
123
     * @return void
124
     * @throws ConfigurationException
125
     * @throws IdFieldNotFoundException
126
     * @throws VariableNotFoundException
127
     */
128
    protected function validateConfig(array $config, Page $page) {
129
        if (!isset($config['field'], $config['variable'])) {
130
            throw new ConfigurationException('Both the configuration entry `field` and `variable` are required when using the Collection adapter.');
131
        }
132
133
        $variable = $config['variable'];
134
135
        if (!$page->getVariable($variable)) {
136
            throw new VariableNotFoundException("Variable \"{$variable}\" was not set as a data variable for page \"{$page->getId()}\"");
137
        }
138
139
        $field = $config['field'];
140
        $pageId = $page->getId();
141
142
        if (strpos($pageId, '{' . $field . '}') === false) {
143
            throw new IdFieldNotFoundException("The field \"{{$field}}\" was not found in the URL \"{$page->getId()}\"");
144
        }
145
    }
146
}
147