Completed
Push — master ( ecd0f8...3ad52b )
by ignace nyamagana
15:08
created

Statement::where()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * League.Csv (https://csv.thephpleague.com).
5
 *
6
 * @author  Ignace Nyamagana Butera <[email protected]>
7
 * @license https://github.com/thephpleague/csv/blob/master/LICENSE (MIT License)
8
 * @version 9.1.5
9
 * @link    https://github.com/thephpleague/csv
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
declare(strict_types=1);
16
17
namespace League\Csv;
18
19
use ArrayIterator;
20
use CallbackFilterIterator;
21
use Iterator;
22
use LimitIterator;
23
use function array_reduce;
24
use function iterator_to_array;
25
26
/**
27
 * A Prepared statement to be executed on a {@link Reader} object.
28
 *
29
 * @package League.csv
30
 * @since   9.0.0
31
 * @author  Ignace Nyamagana Butera <[email protected]>
32
 */
33
class Statement
34
{
35
    /**
36
     * Callables to filter the iterator.
37
     *
38
     * @var callable[]
39
     */
40
    protected $where = [];
41
42
    /**
43
     * Callables to sort the iterator.
44
     *
45
     * @var callable[]
46
     */
47
    protected $order_by = [];
48
49
    /**
50
     * iterator Offset.
51
     *
52
     * @var int
53
     */
54
    protected $offset = 0;
55
56
    /**
57
     * iterator maximum length.
58
     *
59
     * @var int
60
     */
61
    protected $limit = -1;
62
63
    /**
64
     * Set the Iterator filter method.
65
     */
66 10
    public function where(callable $callable): self
67
    {
68 10
        $clone = clone $this;
69 10
        $clone->where[] = $callable;
70
71 10
        return $clone;
72
    }
73
74
    /**
75
     * Set an Iterator sorting callable function.
76
     */
77
    public function orderBy(callable $callable): self
78
    {
79
        $clone = clone $this;
80
        $clone->order_by[] = $callable;
81 4
82
        return $clone;
83 4
    }
84 4
85
    /**
86 4
     * Set LimitIterator Offset.
87
     *
88
     * @throws Exception if the offset is lesser than 0
89
     */
90
    public function offset(int $offset): self
91
    {
92
        if (0 > $offset) {
93
            throw new Exception(sprintf('%s() expects the offset to be a positive integer or 0, %s given', __METHOD__, $offset));
94
        }
95
96
        if ($offset === $this->offset) {
97
            return $this;
98 12
        }
99
100 12
        $clone = clone $this;
101 2
        $clone->offset = $offset;
102
103
        return $clone;
104 10
    }
105 2
106
    /**
107
     * Set LimitIterator Count.
108 8
     *
109 8
     * @throws Exception if the limit is lesser than -1
110
     */
111 8
    public function limit(int $limit): self
112
    {
113
        if (-1 > $limit) {
114
            throw new Exception(sprintf('%s() expects the limit to be greater or equel to -1, %s given', __METHOD__, $limit));
115
        }
116
117
        if ($limit === $this->limit) {
118
            return $this;
119
        }
120
121
        $clone = clone $this;
122
        $clone->limit = $limit;
123 22
124
        return $clone;
125 22
    }
126 4
127
    /**
128
     * Execute the prepared Statement on the {@link Reader} object.
129 18
     *
130 2
     * @param string[] $header an optional header to use instead of the CSV document header
131
     */
132
    public function process(Reader $csv, array $header = []): ResultSet
133 16
    {
134 16
        if ([] === $header) {
135
            $header = $csv->getHeader();
136 16
        }
137
138
        $iterator = array_reduce($this->where, [$this, 'filter'], $csv->getRecords($header));
139
        $iterator = $this->buildOrderBy($iterator);
140
141
        return new ResultSet(new LimitIterator($iterator, $this->offset, $this->limit), $header);
142
    }
143
144
    /**
145
     * Filters elements of an Iterator using a callback function.
146
     */
147 16
    protected function filter(Iterator $iterator, callable $callable): CallbackFilterIterator
148
    {
149 16
        return new CallbackFilterIterator($iterator, $callable);
150 16
    }
151
152
    /**
153 16
     * Sort the Iterator.
154 16
     */
155
    protected function buildOrderBy(Iterator $iterator): Iterator
156 16
    {
157
        if ([] === $this->order_by) {
158
            return $iterator;
159
        }
160
161
        $compare = function (array $record_a, array $record_b): int {
162
            foreach ($this->order_by as $callable) {
163
                if (0 !== ($cmp = $callable($record_a, $record_b))) {
164
                    return $cmp;
165
                }
166
            }
167 6
168
            return $cmp ?? 0;
169 6
        };
170
171
        $iterator = new ArrayIterator(iterator_to_array($iterator));
172
        $iterator->uasort($compare);
173
174
        return $iterator;
175
    }
176
}
177