Passed
Push — develop ( 89bad3...3f9e31 )
by Brent
04:47 queued 01:28
created

PaginationAdapter::createPagination()   B

Complexity

Conditions 7
Paths 64

Size

Total Lines 19
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 16
nc 64
nop 2
dl 0
loc 19
rs 8.2222
c 0
b 0
f 0
1
<?php
2
3
namespace Brendt\Stitcher\Adapter;
4
5
use Brendt\Stitcher\Exception\ConfigurationException;
6
use Brendt\Stitcher\Exception\VariableNotFoundException;
7
use Brendt\Stitcher\Factory\AdapterFactory;
8
use Brendt\Stitcher\Site\Page;
9
10
/**
11
 * The PaginationAdapter takes a page with a collection of entries and generates pagination for that collection.
12
 *
13
 * Sample configuration:
14
 *
15
 *  /examples:
16
 *      template: examples/overview
17
 *      data:
18
 *          collection: collection.yml
19
 *      adapters:
20
 *      pagination:
21
 *          variable: collection
22
 *          entriesPerPage: 4
23
 */
24
class PaginationAdapter extends AbstractAdapter
25
{
26
    private $pageCount = null;
27
    private $variable = null;
28
    private $entries = [];
29
30
    public function transformPage(Page $page, $filter = null) : array {
31
        $config = $page->getAdapterConfig(AdapterFactory::PAGINATION_ADAPTER);
32
        $this->variable = $config['variable'] ?? null;
33
34
        $this->validateConfig($config, $page);
35
36
        $pageId = rtrim($page->getId(), '/');
37
        $this->entries = (array) $this->getData($page->getVariable($this->variable));
38
        $entriesPerPage = (int) $config['entriesPerPage'] ?? 10;
39
        $this->pageCount = (int) ceil(count($this->entries) / $entriesPerPage);
40
41
        $index = 0;
42
        $result = [];
43
44
        while ($index < $this->pageCount) {
45
            $pageEntries = array_splice($this->entries, 0, $entriesPerPage);
46
            $pageIndex = $index + 1;
47
48
            if ($filter === null || $pageIndex === (int) $filter) {
49
                $paginatedPage = $this->createPaginatedPage($page, $pageIndex, $pageEntries);
50
                $result[$paginatedPage->getId()] = $paginatedPage;
51
            }
52
53
            $index += 1;
54
        }
55
56
        $this->createMainPage($pageId, $result);
57
58
        return $result;
59
    }
60
61
    private function createPaginatedPage(Page $page, int $pageIndex, array $pageEntries) : Page {
62
        $url = "{$page->getId()}/page-{$pageIndex}";
63
        $pagination = $this->createPagination($page->getId(), $pageIndex);
64
        $paginatedPage = clone $page;
65
66
        $paginatedPage
67
            ->removeAdapter(AdapterFactory::PAGINATION_ADAPTER)
68
            ->setVariableValue($this->variable, $pageEntries)
69
            ->setVariableIsParsed($this->variable)
70
            ->setVariableValue('pagination', $pagination)
71
            ->setVariableIsParsed('pagination')
72
            ->setId($url);
73
74
        return $paginatedPage;
75
    }
76
77
    private function createMainPage(string $pageId, array &$result) {
78
        $firstPage = reset($result);
79
80
        if (!$firstPage) {
81
            return;
82
        }
83
84
        $mainPage = clone $firstPage;
85
        $mainPage->setId($pageId);
86
        $result[$pageId] = $mainPage;
87
    }
88
89
    private function createPagination($pageId, $pageIndex) {
90
        $next = count($this->entries) ? $pageIndex + 1 : null;
91
        $nextUrl = $next ? "{$pageId}/page-{$next}" : null;
92
        $previous = $pageIndex > 1 ? $pageIndex - 1 : null;
93
        $previousUrl = $previous ? "{$pageId}/page-{$previous}" : null;
94
95
        return [
96
            'current'  => $pageIndex,
97
            'previous' => $previous ? [
98
                'url'   => $previousUrl,
99
                'index' => $previous,
100
            ] : null,
101
            'next'     => $next ? [
102
                'url'   => $nextUrl,
103
                'index' => $next,
104
            ] : null,
105
            'pages'    => $this->pageCount,
106
        ];
107
    }
108
109
    private function validateConfig(array $config, Page $page) {
110
        if (!isset($config['variable'])) {
111
            throw new ConfigurationException('The configuration entry `variable` is required when using the Pagination adapter');
112
        }
113
114
        if (!$page->getVariable($this->variable)) {
115
            throw new VariableNotFoundException("Variable \"{$this->variable}\" was not set as a data variable for page \"{$page->getId()}\"");
116
        }
117
    }
118
}
119