Collection::getCount()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * PHP: Nelson Martell Library file
5
 *
6
 * Copyright © 2015-2021 Nelson Martell (http://nelson6e65.github.io)
7
 *
8
 * Licensed under The MIT License (MIT)
9
 * For full copyright and license information, please see the LICENSE
10
 * Redistributions of files must retain the above copyright notice.
11
 *
12
 * @copyright 2015-2021 Nelson Martell
13
 * @link      http://nelson6e65.github.io/php_nml/
14
 * @since     0.4.0
15
 * @license   http://www.opensource.org/licenses/mit-license.php The MIT License (MIT)
16
 * */
17
18
namespace NelsonMartell\Collections;
19
20
use OutOfRangeException;
21
use NelsonMartell\Extensions\Text;
22
use NelsonMartell\StrictObject;
23
24
use function NelsonMartell\typeof;
25
26
/**
27
 * Clase base de una colección de objetos, que provee una implementación
28
 * predeterminada de la interfaz ICollection.
29
 *
30
 * @author Nelson Martell <[email protected]>
31
 * @since 0.4.0
32
 *
33
 * @property-read int $count Obtiene el número de elementos incluidos en la colección. Esta propiedad es de sólo
34
 *   lectura.
35
 * */
36
class Collection extends StrictObject implements ICollection
37
{
38
    // Implementación de la interfaz Iterator.
39
    use CollectionIterator;
40
41
    public function __construct()
42
    {
43
        parent::__construct();
44
    }
45
46
    final public function __invoke($index, $value = null)
47
    {
48
        if ($value == null) {
49
            return $this->items[$index];
50
        }
51
52
        $this->setItem($index, $value);
53
    }
54
55
    private $items = array();
56
57
58
    /**
59
     * Inserta un nuevo elemento a la colección, en el índice especificado.
60
     *
61
     * @param int     $index   Índice del elemento a insertar.
62
     * @param mixed   $newItem Nuevo elemento a insertar a la colección.
63
     *
64
     * @return void
65
     * */
66
    protected function insertItem($index, $newItem)
67
    {
68
        if ($index > $this->count || $index < 0) {
69
            throw new OutOfRangeException();
70
        }
71
72
        if ($index == $this->count) {
73
            $this->items[$index] = null;
74
            $this->count++;
75
        }
76
77
        $this->items[$index] = $newItem;
78
    }
79
80
    /**
81
     * Quita todos los elementos de la colección.
82
     *
83
     * @return void
84
     * */
85
    protected function clearItems()
86
    {
87
        $this->items = array();
88
        $this->count = 0;
0 ignored issues
show
Bug introduced by
The property count is declared read-only in NelsonMartell\Collections\Collection.
Loading history...
89
    }
90
91
    /**
92
     * Establece un elemento en el índice especificado.
93
     *
94
     * @param int $index   Índice del elemento a establecer.
95
     * @param mixed   $newItem Nuevo valor con el que se va a reemplazar.
96
     *
97
     * @return void
98
     * */
99
    protected function setItem($index, $newItem)
100
    {
101
        if ($index >= $this->count || $index < 0) {
102
            throw new OutOfRangeException();
103
        }
104
105
        $this->items[$index] = $newItem;
106
    }
107
108
    /**
109
     * Obtiene el elemento almacenado en el índice especificado.
110
     * Este método no lanza excepción en caso de indicar un índice fuera del
111
     * rango; en cambio, devuelve NULL.
112
     * El elemento obtenido es de sólo lectura. Para modificar el elemento
113
     * dentro de la colección, tendría que utilizarse el método
114
     * Collection::setItem una vez modificado.
115
     *
116
     * @param int $index Índice del elemento a obtener.
117
     *
118
     * @return mixed
119
     * */
120
    protected function getItem($index)
121
    {
122
        if ($index >= $this->count || $index < 0) {
123
            return null;
124
        }
125
126
        return $this->items[$index];
127
    }
128
129
    /**
130
     * Remove the item in specified index.
131
     *
132
     * @param int $index Index.
133
     *
134
     * @return void
135
     */
136
    protected function removeItem($index)
137
    {
138
        if ($index >= $this->count || $index < 0) {
139
            throw new OutOfRangeException();
140
        }
141
142
        for ($i = $index; $i < $this->count - 1; $i++) {
143
            $this->items[$i] = $this->items[$i + 1]; //Mueve los valores
144
        }
145
146
        unset($this->items[$this->count - 1]); //Des-asigna el último elemento
147
148
        $this->count--;
149
    }
150
151
    /**
152
     * Gets the string representation of this object collection.
153
     *
154
     * You can format the output, by setting $format param to one of this
155
     * options:
156
     * - `R` or `r`: All items, separated by comma and space (`, `).
157
     *   This is the default format.
158
     * - `L` or `l`: Same as `r` option, but enclosed in braces  (`{`, `}`).
159
     * - `g`: A full string, containing class name, items count and items
160
     *   list (this list, like `L` option).
161
     * - `G`: Same as `g`, but using a full class name (including namespace).
162
     *
163
     * You can also use a custom format instead, using this placeholders:
164
     * - `{class}`: Short class name (without namespace part);
165
     * - `{nsclass}`: Full class name (included namespace);
166
     * - `{count}`: Items count; and
167
     * - `{items}`: List of items, using comma and space (`, `) as separator.
168
     *
169
     * Example: For a instance with 10 elements (numbers: 1-10), using:
170
     * `Collection::ToString('My collection ({count} items): { {items} }');`
171
     * Result: 'My collection (10 items): { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }'
172
     *
173
     * @param string $format String format (optional). By default, `r`.
174
     *
175
     * @return string
176
     * @see    Text::format()
177
     * */
178
    public function toString($format = 'r')
179
    {
180
        static $defaultFormats = [
181
            'r' => '{items}',
182
            'l' => '{ {items} }',
183
            'g' => '{class} ({count} items): { {items} }',
184
            'G' => '{nsclass} ({count} items): { {items} }',
185
        ];
186
187
        if ($format == null || !is_string($format)) {
188
            $format = 'r'; //Override if is not an string
189
        }
190
191
        $str = '';
192
        switch ($format) {
193
            case 'r':
194
            case 'l':
195
            case 'g':
196
            case 'G':
197
                $str = $defaultFormats[$format];
198
                break;
199
200
            default:
201
                $str = $format;
202
        }
203
204
        $t = typeof($this);
205
206
        $items = implode(', ', $this->items);
207
208
        $placeHoldersValues = [
209
            'class'   => $t->shortName,
210
            'nsclass' => $t->name,
211
            'count'   => $this->count,
212
            'items'   => $items,
213
        ];
214
215
216
        $s = Text::format($str, $placeHoldersValues);
217
218
        return $s;
219
    }
220
221
    private $count = 0;
222
223
    /**
224
     * Getter for $count property.
225
     *
226
     * @return int
227
     * */
228
    public function getCount()
229
    {
230
        return $this->count;
231
    }
232
233
    /**
234
     * Agrega un nuevo elemento al final de la colección.
235
     * Nota para herederos: Para cambiar el comportamiento de este método,
236
     * reemplazar más bien el método protegido 'insertItem'.
237
     *
238
     * @param mixed $item Elemento que se va a agregar a la colección.
239
     *
240
     * @return void
241
     * */
242
    public function add($item)
243
    {
244
        $this->insertItem($this->count, $item);
245
    }
246
247
    /**
248
     * Quita todos los elementos de la colección.
249
     * Nota para herederos: Para cambiar el comportamiento de este método,
250
     * reemplazar más bien el método protegido `Collection::clearItems`.
251
     *
252
     * @return void
253
     * @see    Collection::clearItems()
254
     * */
255
    public function clear()
256
    {
257
        $this->clearItems();
258
    }
259
260
    /**
261
     * Determina si la colección contiene al elemento especificado.
262
     *
263
     * @param mixed $item Objeto que se va a buscar.
264
     *
265
     * @return bool `true` si $item se encuentra; en caso contrario, `false`.
266
     * */
267
    public function contains($item)
268
    {
269
        foreach ($this->items as $i) {
270
            if ($item === $i) {
271
                return true;
272
            }
273
        }
274
275
        return false;
276
    }
277
278
    /**
279
     * Quita, si existe, la primera aparición de un objeto específico de la
280
     * colección.
281
     *
282
     * @param mixed $item Objeto que se va a quitar.
283
     *
284
     * @return bool `true` si el elemento se ha quitado correctamente; en
285
     *   caso contrario, `false`. Este método también devuelve `false` si no
286
     *   se encontró.
287
     * */
288
    public function remove($item)
289
    {
290
        for ($i = 0; $i < $this->count; $i++) {
291
            if ($this->items[$i] === $item) {
292
                $this->removeItem($i);
293
            }
294
        }
295
296
        return false;
297
    }
298
}
299