• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

chdemko / php-sorted-collections / 24611550585

18 Apr 2026 06:53PM UTC coverage: 99.355% (-0.5%) from 99.869%
24611550585

push

github

chdemko
🚨 Fix scrutinizer

28 of 32 new or added lines in 3 files covered. (87.5%)

770 of 775 relevant lines covered (99.35%)

114.09 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.05
/src/SortedCollection/SubSet.php
1
<?php
2

3
/**
4
 * chdemko\SortedCollection\SubSet class
5
 *
6
 * @author    Christophe Demko <chdemko@gmail.com>
7
 * @copyright Copyright (C) 2012-2024 Christophe Demko. All rights reserved.
8
 *
9
 * @license BSD 3-Clause License
10
 *
11
 * This file is part of the php-sorted-collections package https://github.com/chdemko/php-sorted-collections
12
 */
13

14
// Declare chdemko\SortedCollection namespace
15
namespace chdemko\SortedCollection;
16

17
/**
18
 * Sub set
19
 *
20
 * @package    SortedCollection
21
 * @subpackage Set
22
 *
23
 * @since 1.0.0
24
 *
25
 * @property      mixed      $from           The from element
26
 * @property      boolean    $fromInclusive  The from inclusive flag
27
 * @property      mixed      $to             The to element
28
 * @property      boolean    $toInclusive    The to inclusive flag
29
 * @property-read callable   $comparator     The element comparison function
30
 * @property-read mixed      $first          The first element of the set
31
 * @property-read mixed      $last           The last element of the set
32
 * @property-read integer    $count          The number of elements in the set
33
 * @property-read SortedSet  $set            The underlying set
34
 */
35
class SubSet extends AbstractSet
36
{
37
    /**
38
     * When the from or to value is unused
39
     *
40
     * @since 1.0.0
41
     */
42
    private const UNUSED = 0;
43

44
    /**
45
     * When the from or to value is inclusive
46
     *
47
     * @since 1.0.0
48
     */
49
    private const INCLUSIVE = 1;
50

51
    /**
52
     * When the from or to value is exclusive
53
     *
54
     * @since 1.0.0
55
     */
56
    private const EXCLUSIVE = 2;
57

58
    /**
59
     * @var SortedSet  Internal set
60
     *
61
     * @since 1.0.0
62
     */
63
    private $set;
64

65
    /**
66
     * Get the underlying map as a SubMap
67
     *
68
     * @throws RuntimeException If the underlying map is not a SubMap
69
     *
70
     * @return SubMap The underlying sub map
71
     *
72
     * @since 1.0.0
73
     */
74
    private function getSubMap()
75
    {
76
        $map = $this->getMap();
11✔
77

78
        if (!$map instanceof SubMap) {
11✔
NEW
79
            throw new \RuntimeException('Unexpected map type');
×
80
        }
81

82
        return $map;
11✔
83
    }
84

85
    /**
86
     * Magic get method
87
     *
88
     * @param string $property The property
89
     *
90
     * @return mixed The value associated to the property
91
     *
92
     * @since 1.0.0
93
     */
94
    public function __get($property)
95
    {
96
        $map = $this->getSubMap();
9✔
97

98
        switch ($property) {
99
            case 'from':
9✔
100
                return $map->fromKey;
8✔
101
            case 'to':
9✔
102
                return $map->toKey;
8✔
103
            case 'fromInclusive':
9✔
104
                return $map->fromInclusive;
8✔
105
            case 'toInclusive':
8✔
106
                return $map->toInclusive;
8✔
107
            case 'set':
1✔
108
                return $this->set;
1✔
109
            default:
110
                return parent::__get($property);
1✔
111
        }
112
    }
113

114
    /**
115
     * Magic set method
116
     *
117
     * @param string $property The property
118
     * @param mixed  $value    The new value
119
     *
120
     * @throws RuntimeException If the property does not exist
121
     *
122
     * @return void
123
     *
124
     * @since 1.0.0
125
     */
126
    public function __set($property, $value)
127
    {
128
        $map = $this->getSubMap();
1✔
129

130
        switch ($property) {
131
            case 'from':
1✔
132
                $map->fromKey = $value;
1✔
133
                break;
1✔
134
            case 'to':
1✔
135
                $map->toKey = $value;
1✔
136
                break;
1✔
137
            case 'fromInclusive':
1✔
138
                $map->fromInclusive = $value;
1✔
139
                break;
1✔
140
            case 'toInclusive':
1✔
141
                $map->toInclusive = $value;
1✔
142
                break;
1✔
143
            default:
144
                throw new \RuntimeException('Undefined property');
1✔
145
        }
146
    }
147

148
    /**
149
     * Magic unset method
150
     *
151
     * @param string $property The property
152
     *
153
     * @throws RuntimeException If the property does not exist
154
     *
155
     * @return void
156
     *
157
     * @since 1.0.0
158
     */
159
    public function __unset($property)
160
    {
161
        $map = $this->getSubMap();
1✔
162

163
        switch ($property) {
164
            case 'from':
1✔
165
                unset($map->fromKey);
1✔
166
                break;
1✔
167
            case 'to':
1✔
168
                unset($map->toKey);
1✔
169
                break;
1✔
170
            case 'fromInclusive':
1✔
171
                unset($map->fromInclusive);
1✔
172
                break;
1✔
173
            case 'toInclusive':
1✔
174
                unset($map->toInclusive);
1✔
175
                break;
1✔
176
            default:
177
                throw new \RuntimeException('Undefined property');
1✔
178
        }
179
    }
180

181
    /**
182
     * Magic isset method
183
     *
184
     * @param string $property The property
185
     *
186
     * @return boolean
187
     *
188
     * @since 1.0.0
189
     */
190
    public function __isset($property)
191
    {
192
        $map = $this->getSubMap();
9✔
193

194
        switch ($property) {
195
            case 'from':
9✔
196
                return isset($map->fromKey);
9✔
197
            case 'to':
9✔
198
                return isset($map->toKey);
9✔
199
            case 'fromInclusive':
1✔
200
                return isset($map->fromInclusive);
1✔
201
            case 'toInclusive':
1✔
202
                return isset($map->toInclusive);
1✔
203
            default:
204
                return false;
1✔
205
        }
206
    }
207

208
    /**
209
     * Constructor
210
     *
211
     * @param SortedSet $set        Internal set
212
     * @param mixed     $from       The from element
213
     * @param integer   $fromOption The option for from (SubSet::UNUSED, SubSet::INCLUSIVE or SubSet::EXCLUSIVE)
214
     * @param mixed     $to         The to element
215
     * @param integer   $toOption   The option for to (SubSet::UNUSED, SubSet::INCLUSIVE or SubSet::EXCLUSIVE)
216
     *
217
     * @since 1.0.0
218
     */
219
    protected function __construct(SortedSet $set, $from, $fromOption, $to, $toOption)
220
    {
221
        if ($fromOption == self::UNUSED) {
20✔
222
            if ($toOption == self::UNUSED) {
5✔
223
                $this->setMap(SubMap::view($set->getMap()));
2✔
224
            } else {
225
                $this->setMap(SubMap::head($set->getMap(), $to, $toOption == self::INCLUSIVE));
3✔
226
            }
227
        } elseif ($toOption == self::UNUSED) {
15✔
228
            $this->setMap(SubMap::tail($set->getMap(), $from, $fromOption == self::INCLUSIVE));
3✔
229
        } else {
230
            $this->setMap(
12✔
231
                SubMap::create($set->getMap(), $from, $to, $fromOption == self::INCLUSIVE, $toOption == self::INCLUSIVE)
12✔
232
            );
12✔
233
        }
234

235
        $this->set = $set;
20✔
236
    }
237

238
    /**
239
     * Create
240
     *
241
     * @param SortedSet $set           Internal set
242
     * @param mixed     $from          The from element
243
     * @param mixed     $to            The to element
244
     * @param boolean   $fromInclusive The inclusive flag for from
245
     * @param boolean   $toInclusive   The inclusive flag for to
246
     *
247
     * @return SubSet A new sub set
248
     *
249
     * @since 1.0.0
250
     */
251
    public static function create(SortedSet $set, $from, $to, $fromInclusive = true, $toInclusive = false)
252
    {
253
        return new static(
12✔
254
            $set,
12✔
255
            $from,
12✔
256
            $fromInclusive ? self::INCLUSIVE : self::EXCLUSIVE,
12✔
257
            $to,
12✔
258
            $toInclusive ? self::INCLUSIVE : self::EXCLUSIVE
12✔
259
        );
12✔
260
    }
261

262
    /**
263
     * Head
264
     *
265
     * @param SortedSet $set         Internal set
266
     * @param mixed     $to          The to element
267
     * @param boolean   $toInclusive The inclusive flag for to
268
     *
269
     * @return SubSet A new head set
270
     *
271
     * @since 1.0.0
272
     */
273
    public static function head(SortedSet $set, $to, $toInclusive = false)
274
    {
275
        return new static($set, null, self::UNUSED, $to, $toInclusive ? self::INCLUSIVE : self::EXCLUSIVE);
3✔
276
    }
277

278
    /**
279
     * Tail
280
     *
281
     * @param SortedSet $set           Internal set
282
     * @param mixed     $from          The from element
283
     * @param boolean   $fromInclusive The inclusive flag for from
284
     *
285
     * @return SubSet A new tail set
286
     *
287
     * @since 1.0.0
288
     */
289
    public static function tail(SortedSet $set, $from, $fromInclusive = true)
290
    {
291
        return new static($set, $from, $fromInclusive ? self::INCLUSIVE : self::EXCLUSIVE, null, self::UNUSED);
3✔
292
    }
293

294
    /**
295
     * View
296
     *
297
     * @param SortedSet $set Internal set
298
     *
299
     * @return SubSet A new sub set
300
     *
301
     * @since 1.0.0
302
     */
303
    public static function view(SortedSet $set)
304
    {
305
        return new static($set, null, self::UNUSED, null, self::UNUSED);
2✔
306
    }
307

308
    /**
309
     * Serialize the object
310
     *
311
     * @return array Array of values
312
     *
313
     * @since 1.0.0
314
     */
315
    public function jsonSerialize(): array
316
    {
317
        if (isset($this->from)) {
8✔
318
            if (isset($this->to)) {
6✔
319
                return array(
5✔
320
                    'SubSet' => array(
5✔
321
                        'set' => $this->set->jsonSerialize(),
5✔
322
                        'from' => $this->from,
5✔
323
                        'fromInclusive' => $this->fromInclusive,
5✔
324
                        'to' => $this->to,
5✔
325
                        'toInclusive' => $this->toInclusive,
5✔
326
                    )
5✔
327
                );
5✔
328
            } else {
329
                return array(
1✔
330
                    'TailSet' => array(
1✔
331
                        'set' => $this->set->jsonSerialize(),
1✔
332
                        'from' => $this->from,
1✔
333
                        'fromInclusive' => $this->fromInclusive,
1✔
334
                    )
1✔
335
                );
1✔
336
            }
337
        } else {
338
            if (isset($this->to)) {
2✔
339
                return array(
1✔
340
                    'HeadSet' => array(
1✔
341
                        'set' => $this->set->jsonSerialize(),
1✔
342
                        'to' => $this->to,
1✔
343
                        'toInclusive' => $this->toInclusive,
1✔
344
                    )
1✔
345
                );
1✔
346
            } else {
347
                return array(
1✔
348
                    'ViewSet' => array(
1✔
349
                        'set' => $this->set->jsonSerialize(),
1✔
350
                    )
1✔
351
                );
1✔
352
            }
353
        }
354
    }
355
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc