Filters::guardAgainstInvalidFilter()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2.1481

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 4
ccs 2
cts 3
cp 0.6667
crap 2.1481
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace ReadModel\Filters;
5
6
use Assert\Assertion;
7
use ReadModel\InvalidArgumentException;
8
use ReadModel\Paginator;
9
10
final class Filters
11
{
12
    /** @var Filter[] */
13
    private $filters;
14
15
    /** @var string[] */
16
    private $unusedFilters;
17
18
    /** @var OrderBy[] */
19
    private $ordersBy;
20
21
    /** @var string[] */
22
    private $unusedOrdersBy;
23
24
    /** @var int */
25
    private $limit;
26
27
    /** @var int */
28
    private $offset;
29
30 3
    public function __construct(array $filters, array $ordersBy, int $limit = null, int $offset = 0)
31
    {
32 3
        Assertion::allIsInstanceOf($filters, Filter::class);
33 3
        Assertion::allIsInstanceOf($ordersBy, OrderBy::class);
34
35 3
        $this->limit = $limit;
36 3
        $this->offset = $offset;
37 3
        $this->setFilters($filters);
38 3
        $this->setOrdersBy($ordersBy);
39 3
    }
40
41
    public function limit(): ?int
42
    {
43
        return $this->limit;
44
    }
45
46
    public function offset(): int
47
    {
48
        return $this->offset;
49
    }
50
51 2
    public function useFilter(string $name)
52
    {
53 2
        $this->guardAgainstInvalidFilter($name);
54 2
        unset($this->unusedFilters[$name]);
55 2
        return $this->filters[$name]->transformedValue();
56
    }
57
58 2
    public function useOrderBy(string $name): ?OrderBy
59
    {
60 2
        unset($this->unusedOrdersBy[$name]);
61 2
        return $this->ordersBy[$name] ?? null;
62
    }
63
64
    /** @return Filter[] */
65 1
    public function unusedFilters(): \Generator
66
    {
67 1
        foreach ($this->unusedFilters as $filter) {
68
            $this->useFilter($filter);
69
            yield $this->filters[$filter];
70
        }
71 1
    }
72
73
    /** @return OrderBy[] */
74 1
    public function unusedOrdersBy(): \Generator
75
    {
76 1
        foreach ($this->unusedOrdersBy as $orderBy) {
77
            yield $this->useOrderBy($orderBy);
78
        }
79 1
    }
80
81
    public function addMetaToPaginator(Paginator $paginator): void
82
    {
83
        // callables are used, because filters and orders by might be used after calling that method
84
85 1
        $paginator->addMeta('query', function () {
86 1
            foreach ($this->filters as $filter) {
87 1
                if (!isset($this->unusedFilters[$filter->name()])) {
88
                    // only for used filters
89 1
                    $queries[$filter->name()] = $filter->simplifiedValue();
90
                }
91
            }
92
93 1
            return isset($queries) ? array_filter($queries) : [];
94 1
        });
95
96 1
        $paginator->addMeta('order', function () {
97 1
            foreach ($this->ordersBy as $orderBy) {
98 1
                if (!isset($this->unusedOrdersBy[$orderBy->field()])) {
99
                    // only for used orders by
100 1
                    $orders[] = (string) $orderBy;
101
                }
102
            }
103
104 1
            return isset($orders) ? implode(',', $orders) : null;
105 1
        });
106 1
    }
107
108 2
    private function guardAgainstInvalidFilter(string $name): void
109
    {
110 2
        if (!isset($this->filters[$name])) {
111
            throw InvalidArgumentException::filterDoesNotExist($name);
112
        }
113 2
    }
114
115
    private function setFilters(array $filters): void
116
    {
117 3
        $keys = array_map(function (Filter $filter) {
118 3
            return $filter->name();
119 3
        }, $filters);
120
121 3
        $this->filters = array_combine($keys, $filters);
122 3
        $this->unusedFilters = array_combine($keys, $keys);
123 3
    }
124
125
    private function setOrdersBy(array $ordersBy): void
126
    {
127 3
        $keys = array_map(function (OrderBy $orderBy) {
128 3
            return $orderBy->field();
129 3
        }, $ordersBy);
130
131 3
        $this->ordersBy = array_combine($keys, $ordersBy);
132 3
        $this->unusedOrdersBy = array_combine($keys, $keys);
133 3
    }
134
}
135