Connector::setPagination()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 4
rs 10
ccs 3
cts 3
cp 1
crap 1
1
<?php
2
3
namespace kalanis\kw_connect\arrays;
4
5
6
use kalanis\kw_connect\core\AConnector;
7
use kalanis\kw_connect\core\ConnectException;
8
use kalanis\kw_connect\core\Interfaces\IFilterFactory;
9
use kalanis\kw_connect\core\Interfaces\IFilterSubs;
10
use kalanis\kw_connect\core\Interfaces\IIterableConnector;
11
use kalanis\kw_connect\core\Interfaces\IOrder;
12
use kalanis\kw_connect\core\Interfaces\IRow;
13
use kalanis\kw_connect\core\Rows\SimpleArrayRow;
14
15
16
/**
17
 * Class Connector
18
 * @package kalanis\kw_connect\arrays
19
 * For likes there is a column finder in search mapper.
20
 * So it's possible to map children for sorting and filtering.
21
 */
22
class Connector extends AConnector implements IIterableConnector
23
{
24
    /** @var string|int|null */
25
    protected $primaryKey = null;
26
    /** @var array<int|string, array<int|string, string|int|float|bool|null>> */
27
    protected array $dataSource = [];
28
    /** @var array<int, array<string>> */
29
    protected array $ordering = [];
30
    /** @var array<string|int|bool|SimpleArrayRow> */
31
    protected array $filteredData = [];
32
    protected string $sortDirection = IOrder::ORDER_ASC;
33
    /** @var array<string|int> */
34
    protected array $filtering = [];
35
    protected ?int $offset = null;
36
    protected ?int $limit = null;
37
38
    /**
39
     * @param array<int|string, array<int|string, string|int|float|bool|null>> $source
40
     * @param string|null $primaryKey
41
     */
42 5
    public function __construct(array $source, ?string $primaryKey = null)
43
    {
44 5
        $this->dataSource = $source;
45 5
        $this->primaryKey = $primaryKey;
46 5
    }
47
48
    /**
49
     * @param string $colName
50
     * @param string $filterType
51
     * @param string|int $value  cannot use array from range
52
     */
53 2
    public function setFiltering(string $colName, string $filterType, $value): void
54
    {
55 2
        $this->filtering[] = [$filterType, $colName, $value];
56 2
    }
57
58
    /**
59
     * @param array<IRow> $data
60
     * @return FilteringArrays
61
     */
62 4
    protected function getFiltered(&$data)
63
    {
64 4
        return new FilteringArrays($data);
65
    }
66
67
    /**
68
     * @param array<int|string, string|int|float|bool|null> $data
69
     * @return IRow
70
     */
71 4
    public function getTranslated($data): IRow
72
    {
73 4
        return new SimpleArrayRow($data);
74
    }
75
76 4
    public function setOrdering(string $colName, string $direction): void
77
    {
78 4
        $this->ordering[] = [$colName, $direction];
79 4
    }
80
81 1
    public function setPagination(?int $offset, ?int $limit): void
82
    {
83 1
        $this->offset = $offset;
84 1
        $this->limit = $limit;
85 1
    }
86
87 5
    public function getTotalCount(): int
88
    {
89 5
        if (empty($this->dataSource)) {
90 1
            return 0;
91
        }
92 4
        if (empty($this->filteredData)) {
93 1
            $this->fetchData();
94
        }
95 4
        return count($this->filteredData);
96
    }
97
98 4
    public function fetchData(): void
99
    {
100 4
        $this->parseData();
101 4
    }
102
103
    /**
104
     * @throws ConnectException
105
     */
106 4
    protected function parseData(): void
107
    {
108 4
        $translated = array_map([$this, 'getTranslated'], $this->dataSource);
109 4
        $filtered = $this->getFiltered($translated);
110 4
        foreach (array_reverse($this->filtering) as list($filterType, $columnName, $value)) {
111 2
            $type = $this->getFilterFactory()->getFilter($filterType);
112 2
            if ($type instanceof IFilterSubs) {
113 1
                $type->addFilterFactory($this->getFilterFactory());
114
            }
115 2
            $type->setDataSource($filtered);
116 2
            $type->setFiltering($columnName, $value);
117 2
            $filtered = $type->getDataSource();
118
        }
119
120 4
        foreach (array_reverse($this->ordering) as list($columnName, $direction)) {
121 4
            $toSort = $this->indexedArray($filtered, $columnName);
122 4
            if (IOrder::ORDER_ASC == $direction) {
123 2
                asort($toSort);
124
            } else {
125 2
                arsort($toSort);
126
            }
127 4
            $this->putItBack($filtered, $toSort);
128
        }
129
130 4
        $this->filteredData = $filtered->getArray();
131 4
        $this->translatedData = array_slice($filtered->getArray(), intval($this->offset), $this->limit);
132 4
        if (!empty($this->primaryKey)) {
133 1
            $translatedData = array_combine(array_map([$this, 'rowsPk'], $this->translatedData), $this->translatedData);
134 1
            if (false !== $translatedData) {
135 1
                $this->translatedData = $translatedData;
136
            }
137
        }
138 4
    }
139
140
    /**
141
     * @param IRow $row
142
     * @throws ConnectException
143
     * @return string
144
     */
145 1
    public function rowsPk(IRow $row): string
146
    {
147 1
        return strval($row->getValue($this->primaryKey));
148
    }
149
150
    /**
151
     * @param FilteringArrays $filtered
152
     * @param string $columnName
153
     * @throws ConnectException
154
     * @return array<string|int, int|string|float|bool|null>
155
     */
156 4
    protected function indexedArray(FilteringArrays $filtered, string $columnName): array
157
    {
158 4
        $result = [];
159 4
        foreach ($filtered->getArray() as $index => $item) {
160
            /** @var IRow $item */
161 4
            $result[$index] = $item->getValue($columnName);
162
        }
163 4
        return $result;
164
    }
165
166
    /**
167
     * @param FilteringArrays $filtered
168
     * @param array<string|int, int|string|float|bool|null> $sorted
169
     */
170 4
    protected function putItBack(FilteringArrays $filtered, array $sorted): void
171
    {
172 4
        $finalArray = [];
173 4
        foreach ($sorted as $key => $item) {
174 4
            $finalArray[$key] = $filtered->offsetGet($key);
175
        }
176 4
        $filtered->setArray($finalArray);
177 4
    }
178
179 2
    public function getFilterFactory(): IFilterFactory
180
    {
181 2
        return Filters\Factory::getInstance();
182
    }
183
}
184