Passed
Push — master ( 7b7005...55ec05 )
by Brent
02:29
created

CollectionAdapter::validateConfig()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 4
nop 2
dl 0
loc 18
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
namespace Brendt\Stitcher\Adapter;
4
5
use Pageon\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
    private $metaCompiler;
32
    private $variable = null;
33
    private $field = null;
34
    private $entries = [];
35
36
    public function __construct(ParserFactory $parserFactory, MetaCompiler $metaCompiler) {
37
        parent::__construct($parserFactory);
38
39
        $this->metaCompiler = $metaCompiler;
40
    }
41
42
    public function transformPage(Page $page, $filter = null) : array {
43
        $this->loadConfig($page);
44
        $result = [];
45
46
        while ($entry = current($this->entries)) {
47
            if (isset($entry[$this->field]) && (!$filter || $entry[$this->field] === $filter)) {
48
                $entryPage = $this->createEntryPage($page, $entry);
49
                $result[$entryPage->getId()] = $entryPage;
50
            }
51
52
            next($this->entries);
53
        }
54
        return $result;
55
    }
56
57
    private function createEntryPage(Page $page, array $entry) : Page {
58
        $url = str_replace('{' . $this->field . '}', $entry[$this->field], $page->getId());
59
        $entryPage = Page::copy($page);
60
        $entryPageMeta = $entryPage->getMeta();
61
        $this->metaCompiler->setDefaultMeta($entryPageMeta);
62
63
        foreach ($entry as $entryVariableName => $entryVariableValue) {
64
            $this->metaCompiler->compilePageVariable($entryPage, $entryVariableName, $entryVariableValue);
65
        }
66
67
        $entryPage
68
            ->removeAdapter(AdapterFactory::COLLECTION_ADAPTER)
69
            ->setVariableValue($this->variable, $entry)
70
            ->setVariableIsParsed($this->variable)
71
            ->setId($url);
72
73
        $this->parseBrowseData($entryPage);
74
75
        return $entryPage;
76
    }
77
78
    private function parseBrowseData(Page $entryPage) {
79
        if ($entryPage->getVariable('browse')) {
80
            return;
81
        }
82
83
        $prev = prev($this->entries);
84
85
        if (!$prev) {
86
            reset($this->entries);
87
        } else {
88
            next($this->entries);
89
        }
90
91
        $next = next($this->entries);
92
93
        $entryPage->setVariableValue('browse', [
94
            'prev' => $prev,
95
            'next' => $next,
96
        ])->setVariableIsParsed('browse');
97
98
        prev($this->entries);
99
    }
100
101
    protected function loadConfig(Page $page) {
102
        $config = $page->getAdapterConfig(AdapterFactory::COLLECTION_ADAPTER);
103
104
        if (!isset($config['field'], $config['variable'])) {
105
            throw new ConfigurationException('Both the configuration entry `field` and `variable` are required when using the Collection adapter.');
106
        }
107
108
        $this->variable = $config['variable'];
109
110
        if (!$page->getVariable($this->variable)) {
111
            throw new VariableNotFoundException("Variable \"{$this->variable}\" was not set as a data variable for page \"{$page->getId()}\"");
112
        }
113
114
        $this->field = $config['field'];
115
116
        if (strpos($page->getId(), '{' . $this->field . '}') === false) {
117
            throw new IdFieldNotFoundException("The field \"{{$this->field}}\" was not found in the URL \"{$page->getId()}\"");
118
        }
119
120
        $this->entries = (array) $this->getData($page->getVariable($this->variable));
121
        reset($this->entries);
122
    }
123
}
124