Completed
Pull Request — master (#96)
by Roberto
24:38 queued 09:39
created

SortedSets::zRangeByScore()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
c 0
b 0
f 0
rs 9.7998
cc 3
nc 3
nop 4
1
<?php
2
3
namespace Webdcg\Redis\Traits;
4
5
use Webdcg\Redis\Exceptions\InvalidArgumentException;
6
use Webdcg\Redis\Exceptions\SetOperationException;
7
use Webdcg\Redis\Exceptions\UnsupportedOptionException;
8
9
trait SortedSets
10
{
11
    /*
12
     * Available Set Operations
13
     */
14
    protected $SET_OPERATIONS = ['SUM', 'MIN', 'MAX'];
15
16
    public function bzPop(): bool
17
    {
18
        return false;
19
    }
20
21
    /**
22
     * Add one or more members to a sorted set or update its score if it
23
     * already exists.
24
     *
25
     * See: https://redis.io/commands/zadd.
26
     *
27
     * @param  string $key
28
     * @param  float  $score
29
     * @param  mixed] $member
0 ignored issues
show
Documentation introduced by
The doc-type mixed] could not be parsed: Expected "|" or "end of type", but got "]" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
30
     *
31
     * @return int              1 if the element is added. 0 otherwise.
32
     */
33
    public function zAdd(string $key, float $score, $member): int
34
    {
35
        return $this->redis->zAdd($key, $score, $member);
0 ignored issues
show
Bug introduced by
The property redis does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
36
    }
37
38
    /**
39
     * Get the number of members in a sorted set.
40
     * See: https://redis.io/commands/zcard.
41
     *
42
     * @param  string $key
43
     *
44
     * @return int          The Set's cardinality
45
     */
46
    public function zCard(string $key): int
47
    {
48
        return $this->redis->zCard($key);
49
    }
50
51
    /**
52
     * Get the number of members in a sorted set.
53
     *
54
     * Note: zSize is an alias for zCard and will be removed in future
55
     * versions of phpredis.
56
     *
57
     * See: https://redis.io/commands/zcard.
58
     *
59
     * @param  string $key
60
     *
61
     * @return int          The Set's cardinality
62
     */
63
    public function zSize(string $key): int
64
    {
65
        return $this->redis->zCard($key);
66
    }
67
68
    /**
69
     * Returns the number of elements of the sorted set stored at the specified
70
     * key which have scores in the range [start, end]. Adding a parenthesis
71
     * before start or end excludes it from the range. +inf and -inf are also
72
     * valid limits.
73
     *
74
     * See: https://redis.io/commands/zcount.
75
     *
76
     * @param  string $key
77
     * @param  mixed|int|string $start
78
     * @param  mixed|int|string $end
79
     *
80
     * @return int                      the size of a corresponding zRangeByScore.
81
     */
82
    public function zCount(string $key, $start, $end): int
83
    {
84
        return $this->redis->zCount($key, $start, $end);
85
    }
86
87
    /**
88
     * Increments the score of a member from a sorted set by a given amount.
89
     *
90
     * See: https://redis.io/commands/zincrby.
91
     *
92
     * @param  string $key
93
     * @param  float  $value    (double) value that will be added to the
94
     *                          member's score).
95
     * @param  string $member
96
     *
97
     * @return float            the new value
98
     */
99
    public function zIncrBy(string $key, float $value, $member): float
100
    {
101
        return $this->redis->zIncrBy($key, $value, $member);
102
    }
103
104
    /**
105
     * Creates an intersection of sorted sets given in second argument.
106
     * The result of the union will be stored in the sorted set defined by the
107
     * first argument.
108
     *
109
     * The third optional argument defines weights to apply to the sorted sets
110
     * in input. In this case, the weights will be multiplied by the score of
111
     * each element in the sorted set before applying the aggregation. The
112
     * forth argument defines the AGGREGATE option which specify how the
113
     * results of the union are aggregated.
114
     *
115
     * See: https://redis.io/commands/zinterstore.
116
     *
117
     * @param  string $keyOutput
118
     * @param  array  $arrayZSetKeys
119
     * @param  array  $arrayWeights
120
     * @param  string $aggregateFunction    Either "SUM", "MIN", or "MAX":
121
     *                                      defines the behaviour to use on
122
     *                                      duplicate entries during the
123
     *                                      zInterStore.
124
     *
125
     * @return int                          The number of values in the new
126
     *                                      sorted set.
127
     */
128
    public function zInterStore(
129
        string $keyOutput,
130
        array $arrayZSetKeys,
131
        ?array $arrayWeights = null,
132
        ?string $aggregateFunction = null
133
    ): int {
134
        // Validate Aggregate Function
135
        if (!is_null($aggregateFunction) && !is_null($arrayWeights)) {
136
            $operation = strtoupper($aggregateFunction);
137
138
            if (!in_array($operation, $this->SET_OPERATIONS)) {
139
                throw new SetOperationException('Operation not supported', 1);
140
            }
141
142
            return $this->redis->zInterStore($keyOutput, $arrayZSetKeys, $arrayWeights, $operation);
143
        }
144
145
        // Call using Weights
146
        if (!is_null($arrayWeights)) {
147
            return $this->redis->zInterStore($keyOutput, $arrayZSetKeys, $arrayWeights);
148
        }
149
150
        // Make simplest call just with the required params
151
        return $this->redis->zInterStore($keyOutput, $arrayZSetKeys);
152
    }
153
154
    /**
155
     * Creates an intersection of sorted sets given in second argument.
156
     * The result of the union will be stored in the sorted set defined by the
157
     * first argument.
158
     *
159
     * The third optional argument defines weights to apply to the sorted sets
160
     * in input. In this case, the weights will be multiplied by the score of
161
     * each element in the sorted set before applying the aggregation. The
162
     * forth argument defines the AGGREGATE option which specify how the
163
     * results of the union are aggregated.
164
     *
165
     * Note: zInter is an alias for zinterstore and will be removed in future
166
     * versions of phpredis.
167
     *
168
     * See: https://redis.io/commands/zinterstore.
169
     *
170
     * @param  string $keyOutput
171
     * @param  array  $arrayZSetKeys
172
     * @param  array  $arrayWeights
173
     * @param  string $aggregateFunction    Either "SUM", "MIN", or "MAX":
174
     *                                      defines the behaviour to use on
175
     *                                      duplicate entries during the
176
     *                                      zInterStore.
177
     *
178
     * @return int                          The number of values in the new
179
     *                                      sorted set.
180
     */
181
    public function zInter(
182
        string $keyOutput,
183
        array $arrayZSetKeys,
184
        ?array $arrayWeights = null,
185
        ?string $aggregateFunction = null
186
    ): int {
187
        // Validate Aggregate Function
188
        if (!is_null($aggregateFunction) && !is_null($arrayWeights)) {
189
            $operation = strtoupper($aggregateFunction);
190
191
            if (!in_array($operation, $this->SET_OPERATIONS)) {
192
                throw new SetOperationException('Operation not supported', 1);
193
            }
194
195
            return $this->redis->zInterStore($keyOutput, $arrayZSetKeys, $arrayWeights, $operation);
196
        }
197
198
        // Call using Weights
199
        if (!is_null($arrayWeights)) {
200
            return $this->redis->zInterStore($keyOutput, $arrayZSetKeys, $arrayWeights);
201
        }
202
203
        // Make simplest call just with the required params
204
        return $this->redis->zInterStore($keyOutput, $arrayZSetKeys);
205
    }
206
207
    /**
208
     * Can pop the highest or lowest scoring members from one ZSETs.
209
     * There are two commands (ZPOPMIN and ZPOPMAX for popping the lowest and
210
     * highest scoring elements respectively.).
211
     *
212
     * See: https://redis.io/commands/zpopmin.
213
     * See: https://redis.io/commands/zpopmax.
214
     *
215
     * @param  string       $key
216
     * @param  int|integer  $count
217
     * @param  bool|boolean $max
218
     *
219
     * @return array                Either an array with the key member and
220
     *                              score of the highest or lowest element
221
     *                              or an empty array if there is no element
222
     *                              available.
223
     */
224
    public function zPop(string $key, int $count = 1, bool $max = true): array
225
    {
226
        return $max ? $this->redis->zPopMax($key, $count) : $this->redis->zPopMin($key, $count);
227
    }
228
229
    /**
230
     * Can pop the lowest scoring members from one ZSETs.
231
     *
232
     * See: https://redis.io/commands/zpopmin.
233
     *
234
     * @param  string      $key
235
     * @param  int|integer $count
236
     *
237
     * @return array                Either an array with the key member and
238
     *                              score of the highest or lowest element
239
     *                              or an empty array if there is no element
240
     *                              available.
241
     */
242
    public function zPopMin(string $key, int $count = 1): array
243
    {
244
        return $this->redis->zPopMin($key, $count);
245
    }
246
247
    /**
248
     * Can pop the highest scoring members from one ZSETs.
249
     *
250
     * See: https://redis.io/commands/zpopmax.
251
     *
252
     * @param  string      $key
253
     * @param  int|integer $count
254
     *
255
     * @return array                Either an array with the key member and
256
     *                              score of the highest or lowest element
257
     *                              or an empty array if there is no element
258
     *                              available.
259
     */
260
    public function zPopMax(string $key, int $count = 1): array
261
    {
262
        return $this->redis->zPopMax($key, $count);
263
    }
264
265
    /**
266
     * Returns a range of elements from the ordered set stored at the specified
267
     * key, with values in the range [start, end].
268
     *
269
     * Start and stop are interpreted as zero-based indices:
270
     *     0 the first element, 1 the second ...
271
     *     -1 the last element, -2 the penultimate ...
272
     *
273
     * See: https://redis.io/commands/zrange.
274
     *
275
     * @param  string       $key
276
     * @param  int|integer  $start
277
     * @param  int|integer  $end
278
     * @param  bool|boolean $withScores
279
     *
280
     * @return array                    Array containing the values in specified range.
281
     */
282
    public function zRange(string $key, int $start = 0, int $end = -1, bool $withScores = false): array
283
    {
284
        return $this->redis->zRange($key, $start, $end, $withScores);
285
    }
286
287
    /**
288
     * Returns the elements of the sorted set stored at the specified key which
289
     * have scores in the range [start,end]. Adding a parenthesis before start
290
     * or end excludes it from the range. +inf and -inf are also valid limits.
291
     *
292
     * See: https://redis.io/commands/zrangebyscore.
293
     *
294
     * @param  string     $key
295
     * @param  mixed|int|string     $start
296
     * @param  mixed|int|string     $end
297
     * @param  array|null           $options  Two options are available:
298
     *                                        - withscores => TRUE,
299
     *                                        and limit => [$offset, $count]
300
     *
301
     * @return array                        Array containing the values in
302
     *                                      specified range.
303
     */
304
    public function zRangeByScore(string $key, $start, $end, ?array $options = null): array
305
    {
306
        if (is_null($options)) {
307
            return $this->redis->zRangeByScore($key, $start, $end);
308
        }
309
310
        $rangeOptions = ['withscores', 'limit'];
311
312
        if (count(array_intersect(array_keys($options), $rangeOptions)) != count($options)) {
313
            throw new UnsupportedOptionException("Option Not Supported", 1);
314
        }
315
316
        return $this->redis->zRangeByScore($key, $start, $end, $options);
317
    }
318
319
    /**
320
     * Returns the elements of the sorted set stored at the specified key which
321
     * have scores in the range [start,end]. Adding a parenthesis before start
322
     * or end excludes it from the range. +inf and -inf are also valid limits.
323
     *
324
     * zRevRangeByScore returns the same items in reverse order, when the start
325
     * and end parameters are swapped.
326
     *
327
     * See: https://redis.io/commands/zrevrangebyscore.
328
     *
329
     * @param  string     $key
330
     * @param  mixed|int|string     $start
331
     * @param  mixed|int|string     $end
332
     * @param  array|null           $options  Two options are available:
333
     *                                        - withscores => TRUE,
334
     *                                        and limit => [$offset, $count]
335
     *
336
     * @return array                        Array containing the values in
337
     *                                      specified range.
338
     */
339
    public function zRevRangeByScore(string $key, $start, $end, ?array $options = null): array
340
    {
341
        if (is_null($options)) {
342
            return $this->redis->zRevRangeByScore($key, $start, $end);
343
        }
344
345
        $rangeOptions = ['withscores', 'limit'];
346
347
        if (count(array_intersect(array_keys($options), $rangeOptions)) != count($options)) {
348
            throw new UnsupportedOptionException("Option Not Supported", 1);
349
        }
350
351
        return $this->redis->zRevRangeByScore($key, $start, $end, $options);
352
    }
353
354
    /**
355
     * Returns a lexicographical range of members in a sorted set, assuming the
356
     * members have the same score. The min and max values are required to start
357
     * with '(' (exclusive), '[' (inclusive), or be exactly the values
358
     * '-' (negative inf) or '+' (positive inf).
359
     *
360
     * The command must be called with either three or five arguments or will
361
     * return FALSE.
362
     *
363
     * See: https://redis.io/commands/zrangebylex
364
     *
365
     * @param  string   $key        The ZSET you wish to run against
366
     * @param  mixed|string $min    The minimum alphanumeric value you wish to get
367
     * @param  mixed|string $max    The maximum alphanumeric value you wish to get
368
     * @param  int|null $offset     Optional argument if you wish to start
369
     *                              somewhere other than the first element.
370
     * @param  int|null $limit      Optional argument if you wish to limit the
371
     *                              number of elements returned.
372
     *
373
     * @return array                Array containing the values in the specified
374
     *                              range.
375
     */
376
    public function zRangeByLex(string $key, $min, $max, ?int $offset = null, ?int $limit = null): array
377
    {
378
        if (!$this->_validateLexParams($min, $max)) {
379
            throw new InvalidArgumentException("Redis::zRangeByLex(): min and max arguments must start with '[' or '('", 1);
380
        }
381
382
        if (is_null($offset) && is_null($limit)) {
383
            return $this->redis->zRangeByLex($key, $min, $max);
384
        }
385
386
        if (!is_null($offset) && !is_null($limit)) {
387
            return $this->redis->zRangeByLex($key, $min, $max, $offset, $limit);
388
        }
389
390
        throw new InvalidArgumentException("The provided parameters do not match the required.", 1);
391
    }
392
393
    /**
394
     * Returns the rank of a given member in the specified sorted set, starting
395
     * at 0 for the item with the smallest score.
396
     *
397
     * See: https://redis.io/commands/zrank.
398
     *
399
     * @param  string $key                      The ZSET you wish to run against
400
     * @param  mixed|string|int|float $member   The member to look for
401
     *
402
     * @return int                              The member's rank position
403
     */
404
    public function zRank(string $key, $member): int
405
    {
406
        return $this->redis->zRank($key, $member);
407
    }
408
409
    /**
410
     * Returns the rank of a given member in the specified sorted set, starting
411
     * at 0 for the item with the smallest score.
412
     *
413
     * zRevRank starts at 0 for the item with the largest score.
414
     *
415
     * See: https://redis.io/commands/zrevrank.
416
     *
417
     * @param  string $key                      The ZSET you wish to run against
418
     * @param  mixed|string|int|float $member   The member to look for
419
     *
420
     * @return int                              The member's rank position
421
     */
422
    public function zRevRank(string $key, $member): int
423
    {
424
        return $this->redis->zRevRank($key, $member);
425
    }
426
427
    /**
428
     * Delete one or more members from a sorted set.
429
     *
430
     * See: https://redis.io/commands/zrem.
431
     *
432
     * @param  string $key      The ZSET you wish to run against
433
     * @param  splay $members   Member(s) to be removed from the ZSET
434
     *
435
     * @return int              The number of members deleted.
436
     */
437
    public function zRem(string $key, ...$members): int
438
    {
439
        return $this->redis->zRem($key, ...$members);
440
    }
441
442
    /**
443
     * Delete one or more members from a sorted set.
444
     *
445
     * Note: zDelete and zRemove are an alias for zRem and will be removed
446
     * in future versions of phpredis.
447
     *
448
     * See: https://redis.io/commands/zrem.
449
     *
450
     * @param  string $key      The ZSET you wish to run against
451
     * @param  splay $members   Member(s) to be removed from the ZSET
452
     *
453
     * @return int              The number of members deleted.
454
     */
455
    public function zDelete(string $key, ...$members): int
456
    {
457
        return $this->redis->zRem($key, ...$members);
458
    }
459
460
    /**
461
     * Delete one or more members from a sorted set.
462
     *
463
     * Note: zDelete and zRemove are an alias for zRem and will be removed
464
     * in future versions of phpredis.
465
     *
466
     * See: https://redis.io/commands/zrem.
467
     *
468
     * @param  string $key      The ZSET you wish to run against
469
     * @param  splay $members   Member(s) to be removed from the ZSET
470
     *
471
     * @return int              The number of members deleted.
472
     */
473
    public function zRemove(string $key, ...$members): int
474
    {
475
        return $this->redis->zRem($key, ...$members);
476
    }
477
478
    /**
479
     * Deletes the elements of the sorted set stored at the specified key which
480
     * have rank in the range [start,end].
481
     *
482
     * See: https://redis.io/commands/zremrangebyrank.
483
     *
484
     * @param  string $key      The ZSET you wish to run against
485
     * @param  int    $start
486
     * @param  int    $end
487
     *
488
     * @return int              The number of values deleted from the sorted set
489
     */
490
    public function zRemRangeByRank(string $key, int $start, int $end): int
491
    {
492
        if ($end < $start) {
493
            throw new InvalidArgumentException("End should be greater than Start.", 1);
494
        }
495
496
        return $this->redis->zRemRangeByRank($key, $start, $end);
497
    }
498
499
    /**
500
     * Deletes the elements of the sorted set stored at the specified key which
501
     * have rank in the range [start,end].
502
     *
503
     * Note: zDeleteRangeByRank is an alias for zRemRangeByRank and will be
504
     * removed in future versions of phpredis.
505
     *
506
     * See: https://redis.io/commands/zremrangebyrank.
507
     *
508
     * @param  string $key      The ZSET you wish to run against
509
     * @param  int    $start
510
     * @param  int    $end
511
     *
512
     * @return int              The number of values deleted from the sorted set
513
     */
514
    public function zDeleteRangeByRank(string $key, int $start, int $end): int
515
    {
516
        if ($end < $start) {
517
            throw new InvalidArgumentException("End should be greater than Start.", 1);
518
        }
519
520
        return $this->redis->zRemRangeByRank($key, $start, $end);
521
    }
522
523
524
    /**
525
     * ========================================================================
526
     * H E L P E R   M E T H O D S
527
     * ========================================================================
528
     */
529
530
531
    /**
532
     * Validate Lex Params
533
     *
534
     * @param  splat $params
535
     *
536
     * @return bool
537
     */
538
    protected function _validateLexParams(...$params)
539
    {
540
        return count(preg_grep("/^(\+|\-)?(\({1}.)?(\[{1}.)?$/", $params)) == count($params);
541
    }
542
543
544
545
546
547
548
    public function zRemRangeByScore(): bool
549
    {
550
        return false;
551
    }
552
553
    public function zDeleteRangeByScore(): bool
554
    {
555
        return false;
556
    }
557
558
    public function zRemoveRangeByScore(): bool
559
    {
560
        return false;
561
    }
562
563
564
    public function zRevRange(): bool
565
    {
566
        return false;
567
    }
568
569
570
    public function zScore(): bool
571
    {
572
        return false;
573
    }
574
575
    public function zunionstore(): bool
576
    {
577
        return false;
578
    }
579
580
    public function zUnion(): bool
581
    {
582
        return false;
583
    }
584
585
586
    public function zScan(): bool
587
    {
588
        return false;
589
    }
590
}
591