Passed
Push — develop ( d317a1...403463 )
by Brent
03:24
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\VariableNotFoundException;
6
use Brendt\Stitcher\Factory\AdapterFactory;
7
use Brendt\Stitcher\Site\Page;
8
9
/**
10
 * The PaginationAdapter takes a page with a collection of entries and generates pagination for that collection.
11
 *
12
 * Sample configuration:
13
 *
14
 *  /examples:
15
 *      template: examples/overview
16
 *      data:
17
 *          collection: collection.yml
18
 *      adapters:
19
 *      pagination:
20
 *          variable: collection
21
 *          entriesPerPage: 4
22
 */
23
class PaginationAdapter extends AbstractAdapter
24
{
25
    private $pageCount = null;
26
    private $variable = null;
27
    private $entries = [];
28
29
    public function transformPage(Page $page, $filter = null) : array {
30
        $config = $page->getAdapterConfig(AdapterFactory::PAGINATION_ADAPTER);
31
32
        if (!isset($config['variable'])) {
33
            return [$page];
34
        }
35
36
        $this->variable = $config['variable'];
37
38
        if (!$source = $page->getVariable($this->variable)) {
39
            throw new VariableNotFoundException("Variable \"{$this->variable}\" was not set as a data variable for page \"{$page->getId()}\"");
40
        }
41
42
        $pageId = rtrim($page->getId(), '/');
43
        $this->entries = $this->getData($source);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getData($source) of type * is incompatible with the declared type array of property $entries.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
44
        $entriesPerPage = (int) $config['entriesPerPage'] ?? 10;
45
        $this->pageCount = (int) ceil(count($this->entries) / $entriesPerPage);
46
47
        $index = 0;
48
        $result = [];
49
50
        while ($index < $this->pageCount) {
51
            $pageEntries = array_splice($this->entries, 0, $entriesPerPage);
52
            $pageIndex = $index + 1;
53
54
            if (!$filter || $pageIndex === (int) $filter) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $filter of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
55
                $paginatedPage = $this->createPage($page, $pageIndex, $pageEntries);
56
                $result[$paginatedPage->getId()] = $paginatedPage;
57
            }
58
59
            $index += 1;
60
        }
61
62
        $this->createMainPage($pageId, $result);
63
64
        return $result;
65
    }
66
67
    private function createPage(Page $page, int $pageIndex, array $pageEntries) : Page {
68
        $url = "{$page->getId()}/page-{$pageIndex}";
69
        $pagination = $this->createPagination($page->getId(), $pageIndex);
70
        $paginatedPage = clone $page;
71
72
        $paginatedPage
73
            ->removeAdapter(AdapterFactory::PAGINATION_ADAPTER)
74
            ->setVariableValue($this->variable, $pageEntries)
75
            ->setVariableIsParsed($this->variable)
76
            ->setVariableValue('pagination', $pagination)
77
            ->setVariableIsParsed('pagination')
78
            ->setId($url);
79
80
        return $paginatedPage;
81
    }
82
83
    private function createMainPage(string $pageId, array &$result) {
84
        $firstPage = reset($result);
85
86
        if (!$firstPage) {
87
            return;
88
        }
89
90
        $mainPage = clone $firstPage;
91
        $mainPage->setId($pageId);
92
        $result[$pageId] = $mainPage;
93
    }
94
95
    private function createPagination($pageId, $pageIndex) {
96
        $next = count($this->entries) ? $pageIndex + 1 : null;
97
        $nextUrl = $next ? "{$pageId}/page-{$next}" : null;
98
        $previous = $pageIndex > 1 ? $pageIndex - 1 : null;
99
        $previousUrl = $previous ? "{$pageId}/page-{$previous}" : null;
100
101
        return [
102
            'current'  => $pageIndex,
103
            'previous' => $previous ? [
104
                'url'   => $previousUrl,
105
                'index' => $previous,
106
            ] : null,
107
            'next'     => $next ? [
108
                'url'   => $nextUrl,
109
                'index' => $next,
110
            ] : null,
111
            'pages'    => $this->pageCount,
112
        ];
113
    }
114
}
115