Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.91% covered (success)
90.91%
30 / 33
94.44% covered (success)
94.44%
17 / 18
CRAP
0.00% covered (danger)
0.00%
0 / 1
AbstractRecordCollection
90.91% covered (success)
90.91%
30 / 33
94.44% covered (success)
94.44%
17 / 18
24.43
0.00% covered (danger)
0.00%
0 / 1
 getRecords
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getErrors
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 shuffle
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 slice
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 first
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getOffset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setSourceIdentifier
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 setSourceIdentifiers
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 getSourceIdentifier
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 add
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 has
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 replace
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 valid
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 current
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 rewind
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 next
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 key
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 count
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3/**
4 * Abstract record collection (implements some shared low-level functionality).
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2010.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2,
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 * @category VuFind
24 * @package  Search
25 * @author   David Maus <maus@hab.de>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org
28 */
29
30namespace VuFindSearch\Response;
31
32use function array_slice;
33use function count;
34use function in_array;
35
36/**
37 * Abstract record collection (implements some shared low-level functionality).
38 *
39 * @category VuFind
40 * @package  Search
41 * @author   David Maus <maus@hab.de>
42 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
43 * @link     https://vufind.org
44 */
45abstract class AbstractRecordCollection implements RecordCollectionInterface
46{
47    /**
48     * Response records.
49     *
50     * @var array
51     */
52    protected $records = [];
53
54    /**
55     * Source identifier
56     *
57     * @var string
58     */
59    protected $source;
60
61    /**
62     * Array pointer
63     *
64     * @var int
65     */
66    protected $pointer = 0;
67
68    /**
69     * Zero-based offset in complete search result.
70     *
71     * @var int
72     */
73    protected $offset = 0;
74
75    /**
76     * Return records.
77     *
78     * @return array
79     */
80    public function getRecords()
81    {
82        return $this->records;
83    }
84
85    /**
86     * Return any errors.
87     *
88     * Each error can be a translatable string or an array that the Flashmessages
89     * view helper understands.
90     *
91     * @return array
92     */
93    public function getErrors()
94    {
95        return [];
96    }
97
98    /**
99     * Shuffles records.
100     *
101     * @return bool
102     */
103    public function shuffle()
104    {
105        return shuffle($this->records);
106    }
107
108    /**
109     * Slice the record list.
110     *
111     * @param int $offset Offset
112     * @param int $limit  Limit
113     *
114     * @return void
115     */
116    public function slice(int $offset, int $limit): void
117    {
118        $this->records = array_slice(
119            $this->records,
120            $offset,
121            $limit
122        );
123    }
124
125    /**
126     * Return first record in response.
127     *
128     * @return RecordInterface|null
129     */
130    public function first()
131    {
132        return $this->records[0] ?? null;
133    }
134
135    /**
136     * Return offset in the total search result set.
137     *
138     * @return int
139     */
140    public function getOffset()
141    {
142        return $this->offset;
143    }
144
145    /**
146     * Set the source backend identifier.
147     *
148     * @param string $identifier Backend identifier
149     *
150     * @return void
151     *
152     * @deprecated Use setSourceIdentifiers instead
153     */
154    public function setSourceIdentifier($identifier)
155    {
156        $this->source = $identifier;
157        foreach ($this->records as $record) {
158            $record->setSourceIdentifier($identifier);
159        }
160    }
161
162    /**
163     * Set the source backend identifiers.
164     *
165     * @param string $recordSourceId  Record source identifier
166     * @param string $searchBackendId Search backend identifier (if different from
167     * $recordSourceId)
168     *
169     * @return void
170     */
171    public function setSourceIdentifiers($recordSourceId, $searchBackendId = '')
172    {
173        $this->source = $searchBackendId ?: $recordSourceId;
174        foreach ($this->records as $record) {
175            $record->setSourceIdentifiers(
176                $recordSourceId,
177                $this->source
178            );
179        }
180    }
181
182    /**
183     * Return the source backend identifier.
184     *
185     * @return string
186     */
187    public function getSourceIdentifier()
188    {
189        return $this->source;
190    }
191
192    /**
193     * Add a record to the collection.
194     *
195     * @param RecordInterface $record        Record to add
196     * @param bool            $checkExisting Whether to check for existing record in
197     * the collection (slower, but makes sure there are no duplicates)
198     *
199     * @return void
200     */
201    public function add(RecordInterface $record, $checkExisting = true)
202    {
203        if (!$checkExisting || !$this->has($record)) {
204            $this->records[$this->pointer] = $record;
205            $this->next();
206        }
207    }
208
209    /**
210     * Check if the collection contains the given record
211     *
212     * @param RecordInterface $record Record to check
213     *
214     * @return bool
215     */
216    public function has(RecordInterface $record)
217    {
218        return in_array($record, $this->records, true);
219    }
220
221    /**
222     * Replace a record in the collection.
223     *
224     * @param RecordInterface $record      Record to be replaced
225     * @param RecordInterface $replacement Replacement record
226     *
227     * @return void
228     */
229    public function replace(RecordInterface $record, RecordInterface $replacement)
230    {
231        $key = array_search($record, $this->records, true);
232        if ($key !== false) {
233            $this->records[$key] = $replacement;
234        }
235    }
236
237    /// Iterator interface
238
239    /**
240     * Return true if current collection index is valid.
241     *
242     * @return bool
243     */
244    public function valid(): bool
245    {
246        return isset($this->records[$this->pointer]);
247    }
248
249    /**
250     * Return record at current collection index.
251     *
252     * @return RecordInterface
253     */
254    #[\ReturnTypeWillChange]
255    public function current()
256    {
257        return $this->records[$this->pointer];
258    }
259
260    /**
261     * Rewind collection index.
262     *
263     * @return void
264     */
265    public function rewind(): void
266    {
267        $this->pointer = 0;
268    }
269
270    /**
271     * Move to next collection index.
272     *
273     * @return void
274     */
275    public function next(): void
276    {
277        $this->pointer++;
278    }
279
280    /**
281     * Return current collection index.
282     *
283     * @return integer
284     */
285    #[\ReturnTypeWillChange]
286    public function key()
287    {
288        return $this->pointer + $this->getOffset();
289    }
290
291    /// Countable interface
292
293    /**
294     * Return number of records in collection.
295     *
296     * @return integer
297     */
298    public function count(): int
299    {
300        return count($this->records);
301    }
302}