Compare commits

..

100 Commits

Author SHA1 Message Date
Till Krüss a77a43913a tag v2.1.2 2023-03-02 10:32:04 -08:00
Till Krüss fea402743f Deprecate webdis and phpiredis (#1179)
* Deprecate webdis and phpiredis

* remove space
2023-02-28 13:09:56 -08:00
Vladyslav Vildanov 84844acb93 Added CODEOWNERS file (#1181)
* Added CODEOWNERS file

* Update CODEOWNERS

* Applied whole Redis commands path as @vladvildanov codeowner

* Set @predis/team as Redis commands codeowners

* Update CODEOWNERS

---------

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-02-28 13:07:06 -08:00
Till Krüss 26c625230f match MasterSlaveReplication (#1175)
* match `MasterSlaveReplication`

also the name of this method 😬

* Update SentinelReplication.php
2023-02-21 08:30:43 -08:00
David Bomba 8ef75ba6b2 Add option for disabling reads to slaves in replication topologies (#1168)
* Add option for disabling reads to slaves in replication topologies

(cherry picked from commit e132c312a9)

* remove empty line

---------

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-02-21 08:15:58 -08:00
Stephan 8a5ced5251 Fix return type of ReplicationInterface::getSlaves (#1111) 2023-02-08 07:26:27 -08:00
Vladyslav Vildanov 29350952d0 Added stream commands to KeyPrefixProcessor (#1051)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2023-01-31 08:50:14 -08:00
Vladyslav Vildanov 98222f47b0 Added support for container commands (#1049)
* Added support for container commands FUNCTION LOAD, FUNCTION DELETE and FCALL

* Changed ContainerInterface and AbstractContainer

* Re-implement logic of abstract methods

---------

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2023-01-31 08:48:48 -08:00
Till Krüss 38e955bc26 fix deprecated call 2023-01-29 11:58:46 -08:00
Vladyslav Vildanov db65e5ebd3 Extended core support by implementing SORT_RO command (#1044)
* Added support for SORT_RO command

* Codestyle fixes

* Added command description

---------

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2023-01-29 11:38:30 -08:00
Vladyslav Vildanov 50e005bfe3 Added support for new arguments for EXPIRE, EXPIREAT commands (#1046) 2023-01-25 08:00:23 -08:00
Vladyslav Vildanov c541617333 Added support for new arguments for BITPOS, BITCOUNT commands (#1045) 2023-01-25 07:59:44 -08:00
Till Krüss 0a8e0c2f96 remove CONTRIBUTING file 2023-01-21 17:20:25 -08:00
Till Krüss 793de36822 Update README.md 2023-01-21 17:17:25 -08:00
Till Krüss fa13640ddd try another format 2023-01-21 17:05:13 -08:00
Viktor Szépe 5331d943fe Upgrade static analysis to PHPStan level 2 (#1043)
* Upgrade static analysis to PHPStan level 2

* Fix CS and CI

* Fix coverage path

* Start debugging

* Stop debugging
2023-01-21 17:03:53 -08:00
Viktor Szépe 74d5ad22dd Add Coverage badge to README (#1042) 2023-01-21 15:59:53 -08:00
Till Krüss a04bcb94fc try different license format 2023-01-21 14:10:06 -08:00
Till Krüss 9f77e5178f fix license header 2023-01-21 14:08:25 -08:00
Viktor Szépe ac259bdb6f Add complete CI (#1036)
* Add complete CI

* Fix CI

* Fix spelling

* Fix indentation

* Fix CI

* Fix CI

* Revert disabling unit tests

* Add coverage driver to CI

* Start coverage debugging

* Fix debugging
ignored, and an empty message aborts the commit.

* Stop debugging

* Move TODO-s from source to GitHub issues

* Ignore too long lines in certain files

* Revert requiring php-parallel-lint/php-parallel-lint

* formatting

* try shorter formatting

* formatting

* fix syntax

* try two paths?

* Update .editorconfig

Co-authored-by: Viktor Szépe <viktor@szepe.net>

* indentation

* make it a group

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-01-21 13:22:13 -08:00
Till Krüss 6e45ca5154 Create README.md 2023-01-21 13:17:31 -08:00
Viktor Szépe c201af5ad3 Fix PHPStan level 2 problems (#1025)
* Fix almost all PHPStan level 2 problems

* Fix master loop and remove empty line

* Fix variadic functions

* Fix CS

* Disable xdebug in CI and improve a condition

* Fix CI fix
2023-01-20 14:20:53 -08:00
Vladyslav Vildanov 1c6c5feb3a Extended core support by implementing EVALSHA_RO command (#1034) 2023-01-20 11:15:39 -08:00
Vladyslav Vildanov a8c5794b8a Added support for LCS command (#1035) 2023-01-20 11:14:50 -08:00
Vladyslav Vildanov ccc2860ad2 Added support for EVAL_RO command (#1032) 2023-01-20 11:13:46 -08:00
Till Krüss 1cd78095e6 drop phpcs version to 3.3 for php 7.2 support 2023-01-19 09:49:27 -08:00
Till Krüss f6f4830b3c tweak composer config 2023-01-19 09:28:33 -08:00
Vladyslav Vildanov e3ad353125 Extended Sets support by implementing SINTERCARD command (#1027)
* Added support for SINTERCARD command

* Codestyle fixes, added support for php-cs-fixer

* Moved php-cs-fixer dependency to dev

* Removed trailed comma

* Added support for php 7.2

* update scripts

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-01-19 09:17:15 -08:00
Vladyslav Vildanov e00d1a0bd3 Added support for EXPIRETIME command (#1029)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2023-01-19 09:15:20 -08:00
Vladyslav Vildanov 64604de751 Added support for PEXPIRETIME command (#1031)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2023-01-19 09:14:55 -08:00
Viktor Szépe 20dcb4bb73 Fix LICENSE file (#1026)
GitHub has problems with it
`curl "https://api.github.com/repos/predis/predis" -H "Accept: application/vnd.github.drax-preview+json" -s | jq '.license'`
2023-01-18 16:03:08 -08:00
Fran Moreno 3daf75508d Add phpstan level 0 (#1022)
* Remove unused arguments

* Fix return types

* Removed unused parameter and argument

* Add phpstan job

* merge files

* Delete phpstan-baseline.neon

* Delete static-analysis.yml

* merge workflows

* Update composer.json

* format yaml

* install composer reps

* fix yaml

Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-01-18 13:33:51 -08:00
Till Krüss 7a4b3d1d0f Update .editorconfig 2023-01-18 13:27:04 -08:00
Till Krüss 3cf958580a Update .editorconfig 2023-01-18 13:26:53 -08:00
Fran Moreno d6dc6e51e1 Add CS job (#1024)
* Add CS job

* Apply PHP71Migration ruleset
2023-01-18 10:02:26 -08:00
Till Krüss 113145f306 more code formatting 2023-01-17 15:08:18 -08:00
Till Krüss 47a7cbc862 unify code formatting 2023-01-17 15:08:18 -08:00
Till Krüss 3c8a811ca3 update examples 2023-01-17 15:08:18 -08:00
Till Krüss f4bd6d44b1 update cs-fixer config 2023-01-17 15:08:18 -08:00
Till Krüss 6b6179ee44 don’t run tests twice 2023-01-17 15:08:18 -08:00
Till Krüss 82791e55e1 format tests 2023-01-17 15:08:18 -08:00
Till Krüss ea7698e12f use single quotes 2023-01-17 15:08:18 -08:00
Till Krüss af2e5cc553 order imports 2023-01-17 15:08:18 -08:00
Till Krüss b1009f46ac unify spacing 2023-01-17 15:08:18 -08:00
Till Krüss a09da4f3b0 trailing multiline commas 2023-01-17 15:08:18 -08:00
Till Krüss 06c00ac43f import global namespace 2023-01-17 15:08:18 -08:00
Till Krüss f3deda22cd no @link tags 2023-01-17 15:08:18 -08:00
Till Krüss c412594217 align phpdoc vertically 2023-01-17 15:08:18 -08:00
Till Krüss cc40219268 use short array syntax 2023-01-17 15:08:18 -08:00
Till Krüss 31b65f614b Remove @author tags 2023-01-17 13:41:35 -08:00
Till Krüss c9babb1984 update copyright comments 2023-01-17 13:41:35 -08:00
Till Krüss c2af9427c5 update MIT license template 2023-01-17 13:41:35 -08:00
Till Krüss c5b60884e8 tag v2.1.1 2023-01-17 12:57:35 -08:00
Till Krüss 836ab07d40 Fix support options array in ZINTERSTORE and ZUNIONSTORE (#1018)
* support old options array

* fix zinterstore as well

* single override
2023-01-17 12:50:15 -08:00
Fran Moreno 2bfc8a9316 Fix Client template (#1017) 2023-01-17 12:48:39 -08:00
Till Krüss d21576669d remove phpiredis suggestion 2023-01-17 09:42:23 -08:00
Till Krüss 65fe24e346 bump version 2023-01-17 09:42:15 -08:00
Till Krüss fbf270156f tweak workflow formatting 2023-01-16 15:33:05 -08:00
Till Krüss 24630fbd5b tag 2.1.0 2023-01-16 15:21:30 -08:00
Till Krüss bded73f516 tweak release draft template [skip ci] 2023-01-16 15:21:19 -08:00
Till Krüss 6a3f4a4c08 Update release-drafter-config.yml 2023-01-16 15:12:32 -08:00
Vladyslav Vildanov 47896f1be7 Extended core support by implementing BLMPOP command (#1015)
* Added support for LMPOP command

* Added support for BLMPOP command

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2023-01-16 08:46:59 -08:00
erikn69 586b039289 Fix builds badge (#1014) 2023-01-16 08:45:19 -08:00
Vladyslav Vildanov d1acca607e Added support for LMPOP command (#1013)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2023-01-16 08:45:04 -08:00
Vladyslav Vildanov 721c829042 Extended server functionality by implementing FAILOVER command (#875)
* Added arrayable arguments classes

* Updated count trait to accept additional modifier argument

* Added new With traits, moved into separate directory

* Added traits for geo command arguments resolving

* Remove BaseWith trait, not working with traits nesting

* Added AscDesc trait

* Rename AscDesc traint into Sorting

* Fixed trait keyword

* Removed unnecessary traits

* Updated count trait to handle default argument value

* Fixed With traits offset check condition

* Added GeoFrom, GeoBy traits

* Fixes for Count and Sorting traits

* Fixed variable names in with traits

* [WIP] Added GEOSEARCH command support, without test coverage

* Changed functionality to support only lower case units (Redis 6.0 support)

* Changed namespace for WITHSCORES trait

* Added more test coverage, added response parsing

* Added test coverage for tratis

* Added support for FAILOVER command

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-29 12:19:17 -08:00
Vladyslav Vildanov b8cc7c643a Extended Key Space support by implementing COPY command (#866)
* Added support for COPY command

* Revert getCLient signature changes, used createClient instead

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-29 12:18:08 -08:00
Vladyslav Vildanov b47aa7ad3a Extended Geospatial support by implementing GEOSEARCHSTORE command (#873)
* Added arrayable arguments classes

* Updated count trait to accept additional modifier argument

* Added new With traits, moved into separate directory

* Added traits for geo command arguments resolving

* Remove BaseWith trait, not working with traits nesting

* Added AscDesc trait

* Rename AscDesc traint into Sorting

* Fixed trait keyword

* Removed unnecessary traits

* Updated count trait to handle default argument value

* Fixed With traits offset check condition

* Added GeoFrom, GeoBy traits

* Fixes for Count and Sorting traits

* Fixed variable names in with traits

* [WIP] Added GEOSEARCH command support, without test coverage

* Changed functionality to support only lower case units (Redis 6.0 support)

* Changed namespace for WITHSCORES trait

* Added more test coverage, added response parsing

* Added support for GEOSEARCHSTORE command

* Added test coverage for tratis

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Chayim <chayim@users.noreply.github.com>
2022-12-29 12:16:51 -08:00
Vladyslav Vildanov bb65b31580 Extend Geospatial support by implementing GEOSEARCH command (#867)
* Added arrayable arguments classes

* Updated count trait to accept additional modifier argument

* Added new With traits, moved into separate directory

* Added traits for geo command arguments resolving

* Remove BaseWith trait, not working with traits nesting

* Added AscDesc trait

* Rename AscDesc traint into Sorting

* Fixed trait keyword

* Removed unnecessary traits

* Updated count trait to handle default argument value

* Fixed With traits offset check condition

* Added GeoFrom, GeoBy traits

* Fixes for Count and Sorting traits

* Fixed variable names in with traits

* [WIP] Added GEOSEARCH command support, without test coverage

* Changed functionality to support only lower case units (Redis 6.0 support)

* Changed namespace for WITHSCORES trait

* Added more test coverage, added response parsing

* Added test coverage for tratis

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Chayim <chayim@users.noreply.github.com>
2022-12-28 09:10:03 -08:00
Vladyslav Vildanov e540ca062b Added support for SISMEMBER command (#871)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-23 11:18:50 -08:00
Vladyslav Vildanov 9c543ef5b1 Added support for HRANDFIELD command (#870)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-23 11:18:33 -08:00
Vladyslav Vildanov 83fb0020a1 Added support for GETEX command (#872)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-23 11:17:24 -08:00
Vladyslav Vildanov 4a77aea9ef Added support for GETDEL command (#869)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-20 09:32:58 -08:00
Vladyslav Vildanov 72bc11eb63 Extended Sorted Set support by adding ZINTER command (#859)
* Refactored zinterstore, zunionstore commands and command traits

* Merge conflicts resolve, update cluster strategy test with new arguments

* Updated assertion in case if command executed faster then duration minimal threshold

* Added support for ZINTER command

* Added command link and description

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-14 08:54:30 -08:00
Vladyslav Vildanov f26fd899f9 Extend Sorted Set support by implementing BZPOPMAX command (#864)
* Refactored zinterstore, zunionstore commands and command traits

* Merge conflicts resolve, update cluster strategy test with new arguments

* Updated assertion in case if command executed faster then duration minimal threshold

* Updated Keys trait to handle cases when no numkeys modifier needed

* Added support for BZPOPMIN command

* Added command link and description

* Added support for BZPOPMAX command

* Added absract command to fix inheritance chain

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-13 10:26:47 -08:00
Vladyslav Vildanov 65447807ed Extended Sorted Set support by adding ZUNION command (#860)
* Refactored zinterstore, zunionstore commands and command traits

* Merge conflicts resolve, update cluster strategy test with new arguments

* Updated assertion in case if command executed faster then duration minimal threshold

* Added support for ZUNION command

* Added command link and description

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-13 08:41:56 -08:00
Vladyslav Vildanov 5418cd5813 Extended Sorted Set support by adding BLMOVE command (#865)
* Added support for LMOVE command

* Added support for BLMOVE command

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-13 08:38:35 -08:00
Vladyslav Vildanov bc5892e260 Extended Sorted Set support by adding BZPOPMIN command (#862)
* Refactored zinterstore, zunionstore commands and command traits

* Merge conflicts resolve, update cluster strategy test with new arguments

* Updated assertion in case if command executed faster then duration minimal threshold

* Updated Keys trait to handle cases when no numkeys modifier needed

* Added support for BZPOPMIN command

* Added command link and description

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-12 08:38:26 -08:00
Vladyslav Vildanov 7c0cc7bdbe Extended Sorted Set support by adding ZINTERCARD command (#861)
* Refactored zinterstore, zunionstore commands and command traits

* Merge conflicts resolve, update cluster strategy test with new arguments

* Updated assertion in case if command executed faster then duration minimal threshold

* Updated Limit trait to handle integer values

* Updated Limit trait to return previous arguments if limit argument isn't set

* Added support for ZINTERCARD command

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-12 08:38:06 -08:00
Vladyslav Vildanov 87ecd7bde2 Added support for LMOVE command (#863)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-12 08:37:28 -08:00
Vladyslav Vildanov f9e77a0562 Refactored ZUNIONSTORE, ZINTERSTORE, removed Numkeys trait, improved Withscores response parsing (#858) 2022-12-09 07:37:22 -08:00
Vladyslav Vildanov d2b05ff58a Added mixin annotations for traits (#835)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-07 09:19:04 -08:00
Chayim e24ecbbf90 Fixing the release drafter, to honour the main branch (#857) 2022-12-07 12:08:16 +02:00
Vladyslav Vildanov 9f3bdd5616 Extend Sorted Set support by implementing ZRANGESTORE command (#829)
* Added support for ZRANGESTORE command

* Added missing test coverage, added new filter method

* Added test coverage for new traits

* Updated offset for unexpected value tests

* Added missing offset

* Removed version annotation for inconsistency

* Update ZDIFF.php

* Update ZRANGESTORE.php

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-12-06 08:40:06 -08:00
Chayim 57a24413c2 Adding the release drafter for release management (#811) 2022-12-05 09:25:47 -08:00
Vladyslav Vildanov 0e6126ba9d Added support for BZMPOP command (#833) 2022-12-05 08:33:43 -08:00
Vladyslav Vildanov 7904fed6da Added support for ZMPOP command (#831)
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-12-01 12:10:20 -08:00
Vladyslav Vildanov cfd6f030bc Extend Sorted Set support by implementing ZDIFFSTORE command (#828)
* Added support for ZDIFF, added new WITHSCORE trait

* Added trait to resolve numkeys argument

* Added trait for unpacking keys array

* Added static binding for Numkeys trait

* Added ZDIFFSTORE command support

* Changed access modifier type to more strict

* Removed version annotation for inconsistency

* Update ZDIFFSTORE.php

Co-authored-by: Vladislav <vladislav@Admins-MacBook-Pro.local>
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-11-30 13:23:08 -08:00
Vladyslav Vildanov 35d18d739a Added response parser for WithScore trait (#830)
* Added response parser for WithScore trait

* Added test coverage for new method

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-11-30 13:20:56 -08:00
Vladyslav Vildanov 573c54ac4c Extend Sorted Set support by implementing ZDIFF command (#826)
* Added support for ZDIFF, added new WITHSCORE trait

* Added trait to resolve numkeys argument

* Added trait for unpacking keys array

* Added static binding for Numkeys trait

* Changed access modifier type to more strict

Co-authored-by: Vladislav <vladislav@Admins-MacBook-Pro.local>
Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
2022-11-28 13:16:30 -08:00
Vladyslav Vildanov 169604bf74 Extend Sorted Set support by implementing ZRANDMEMBER command (#825)
* Added support for ZRANDMEMBER, added test coverage

* Changed key to more specific on exception testing

Co-authored-by: Vladislav <vladislav@Admins-MacBook-Pro.local>
2022-11-21 08:37:04 -08:00
vladvildanov 94bd54b2af Extend Sorted Set support by implementing ZMSCORE (#823) 2022-11-17 07:48:16 -08:00
Josh England bdebad7d62 added annotations to suppress PHP 8.1 return type deprecation warning… (#810)
* added annotations to suppress PHP 8.1 return type deprecation warning for `IteratorAggregate::toIterator()`

* move import

Co-authored-by: Josh England <joshua.england@trinet.com>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-11-02 17:07:32 -07:00
Till Krüss 1a411d2ad7 back to dev version 2022-10-11 09:57:28 -07:00
Till Krüss 1400689df8 switch to actions/checkout@v3 [skip ci] 2022-10-11 09:56:57 -07:00
Till Krüss ff59f74581 bump version 2022-10-11 09:52:29 -07:00
Mehmet Tolga Avcioglu 1a0eb7ee85 sentinel default to no password when replica authentication is used (#807)
* set default nopass if password is not provided

* remove debug output

* added tests for noauth sentinel

* Update SentinelReplication.php

Co-authored-by: Mehmet Tolga Avcioglu <mehmet.avcioglu@pusula.net.tr>
Co-authored-by: Till Krüss <tillkruss@users.noreply.github.com>
2022-10-06 08:14:47 -07:00
Tobias Bengtsson bb6c1a7b6d Add partial support for Stream commands (#804)
Adds support for the following commands not related to groups/consumers:
XADD, XDEL, XLEN, XRANGE, XREVRANGE, XTRIM.
2022-09-27 09:39:17 -07:00
streamingsystems 42c33a406f Check if socket is resource before reading (#802) 2022-09-18 15:01:02 -07:00
Stefano Borghi 7ad74217c2 check resource before writing, w/ test (#800) 2022-09-16 17:03:13 -07:00
Alexandru Pătrănescu 72d7675563 improve PHP 8.2 support (#797)
* use static::class . '::<method>' instead of 'static::method'

* extract concatenation so it can be improved easier at a later point

one improvement at some point could be to replace static::class . '::<method>' with static::<method>(...) in PHP 8.1+

Co-authored-by: Alexandru Patranescu <alexandru.patranescu@payu.com>
2022-09-08 11:25:37 -07:00
709 changed files with 20040 additions and 6121 deletions
+6
View File
@@ -0,0 +1,6 @@
[codespell]
skip=./.git
check-hidden=
check-filenames=
builtin=clear,rare,informal,usage,code,names
ignore-words-list=master,masters,slave,slaves,whitelist,cas,exat,smove
+12 -5
View File
@@ -1,5 +1,3 @@
# http://editorconfig.org
root = true
[*]
@@ -8,10 +6,19 @@ indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
block_comment_start = /*
block_comment = *
block_comment_end = */
[*.php]
trim_trailing_whitespace = true
max_line_length = 120
max_line_length = 150
[*.{md,yml}]
[*.{md,yml,yaml,neon}]
indent_size = 2
[tests/**.php]
max_line_length = unset
[{src/ClientInterface.php,src/ClientContextInterface.php}]
max_line_length = unset
+11 -3
View File
@@ -1,9 +1,17 @@
* text=auto
/tests export-ignore
/.github export-ignore
/.github/ export-ignore
/examples/ export-ignore
/tests/ export-ignore
/.codespellrc export-ignore linguist-language=INI
/.editorconfig export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.php_cs.dist export-ignore
/.php-cs-fixer.dist.php export-ignore
/CHANGELOG.md export-ignore linguist-documentation
/CONTRIBUTING.md export-ignore linguist-documentation
/FAQ.md export-ignore linguist-documentation
/VERSION export-ignore
/phpunit.xml.dist export-ignore
/phpstan.dist.neon export-ignore
/phpstan-tests.dist.neon export-ignore
+14
View File
@@ -0,0 +1,14 @@
# Default
* @tillkruss
# Redis commands
src/Command/Redis/* @predis/team @tillkruss
# Redis Stack
src/Command/Redis/Json/* @predis/team
src/Command/Redis/Search/* @predis/team
src/Command/Redis/TopK/* @predis/team
src/Command/Redis/TDigest/* @predis/team
src/Command/Redis/BloomFilter/* @predis/team
src/Command/Redis/CuckooFilter/* @predis/team
src/Command/Redis/CountMinSketch/* @predis/team
+4 -4
View File
@@ -19,10 +19,10 @@ Steps to reproduce the behavior:
A clear and concise description of what you expected to happen.
**Versions (please complete the following information):**
- Predis: [e.g. 1.1.2]
- PHP [e.g. 8.0.0]
- Redis Server [e.g. 6.0.0]
- OS [e.g. Ubuntu 20.10]
- Predis: [e.g. 1.1.2]
- PHP [e.g. 8.0.0]
- Redis Server [e.g. 6.0.0]
- OS [e.g. Ubuntu 20.10]
**Code sample**
If applicable, a small snippet of code that reproduces the issue.
+49
View File
@@ -0,0 +1,49 @@
name-template: 'v$NEXT_MINOR_VERSION'
tag-template: 'v$NEXT_MINOR_VERSION'
change-template: '- $TITLE (#$NUMBER)'
autolabeler:
- label: 'maintenance'
files:
- '*.md'
- '.github/*'
- label: 'bug'
branch:
- '/bug-.+'
- label: 'maintenance'
branch:
- '/maintenance-.+'
- label: 'feature'
branch:
- '/feature-.+'
categories:
- title: 'Breaking Changes'
labels:
- 'breakingchange'
- title: 'Experimental Features'
labels:
- 'experimental'
- title: 'New Features'
labels:
- 'feature'
- 'enhancement'
- title: 'Bug Fixes'
labels:
- 'fix'
- 'bugfix'
- 'bug'
- 'BUG'
- title: 'Maintenance'
label: 'maintenance'
exclude-labels:
- 'skip-changelog'
template: |
$CHANGES
## Contributors
We'd like to thank all the contributors who worked on this release!
$CONTRIBUTORS
+9
View File
@@ -0,0 +1,9 @@
# Workflows
## Delete runs by workflow name
```bash
gh run list --workflow 'redis-server-tests.yml' --limit 1000 --json databaseId \
| jq '.[].databaseId' \
| xargs -I % gh api --silent -X DELETE /repos/predis/predis/actions/runs/%
```
+167
View File
@@ -0,0 +1,167 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow
name: Linters
on:
push:
branches:
- main
- v2.**
pull_request: null
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
byte_level:
name: Byte-level
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Check file permissions
run: test "$(find . -type f -not -path './.git/*' -executable)" = "./bin/create-command-test"
- name: "Find non-printable ASCII characters"
run: |
! LC_ALL=C.UTF-8 find . -type f -name '*.php' -print0 \
| xargs --null -- grep --perl-regexp --with-filename --line-number '[^ -~ü]'
syntax_errors:
name: Syntax errors
runs-on: ubuntu-latest
steps:
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.1"
coverage: none
tools: parallel-lint
- name: Checkout repository
uses: actions/checkout@v3
- name: Check source code for syntax errors
run: composer exec -- parallel-lint bin/ examples/ src/ tests/
static_analysis:
name: Static Analysis
needs:
- byte_level
- syntax_errors
runs-on: ubuntu-latest
steps:
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.2"
coverage: none
- name: Checkout repository
uses: actions/checkout@v3
- name: Validate Composer configuration
run: composer validate --no-interaction --strict
- name: Install dependencies
uses: ramsey/composer-install@v2
with:
dependency-versions: highest
- name: Check PSR-4 mapping
run: composer dump-autoload --no-interaction --optimize --strict-psr
- name: Perform static analysis
run: composer run phpstan
- name: Perform static analysis on tests
run: composer run phpstan -- --configuration=phpstan-tests.dist.neon
coding_standards:
name: Coding Standards
needs:
- byte_level
- syntax_errors
runs-on: ubuntu-latest
steps:
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.1"
coverage: none
- name: Checkout repository
uses: actions/checkout@v3
- name: Check EditorConfig configuration
run: test -f .editorconfig
- name: Check adherence to EditorConfig
uses: greut/eclint-action@v0
- name: Install dependencies
uses: ramsey/composer-install@v2
with:
dependency-versions: highest
- name: Check coding style
run: composer exec -- php-cs-fixer fix --diff --dry-run --allow-risky=yes --using-cache=no
- name: Search for TODO-s and FIXME-s
run: |
! git grep --extended-regexp --ignore-case '\b(TODO|FIXME)\b' -- ':/' ':!tests/*' ':!*/linters\.yml'
exported_files:
name: Exported files
needs:
- byte_level
- syntax_errors
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Check exported files
run: |
EXPECTED="LICENSE,README.md,autoload.php,composer.json"
CURRENT="$(
git archive HEAD \
| tar --list --exclude="src" --exclude="src/*" --exclude="bin" --exclude="bin/*" \
| paste --serial --delimiters=","
)"
echo "CURRENT =${CURRENT}"
echo "EXPECTED=${EXPECTED}"
test "${CURRENT}" = "${EXPECTED}"
spelling:
name: Spelling
needs:
- byte_level
- syntax_errors
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Cache pip
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-codespell
- name: Install codespell
run: pip install --user 'codespell>=2.2'
- name: Search for misspellings
run: $(python -m site --user-base)/bin/codespell
+25
View File
@@ -0,0 +1,25 @@
name: Release Drafter
on:
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
update_release_draft:
name: Update release draft
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v5
with:
config-name: release-drafter-config.yml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+56 -33
View File
@@ -1,52 +1,75 @@
name: Tests
on:
- push
- pull_request
push:
branches:
- main
- v2.**
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
predis:
name: PHP ${{ matrix.php-versions }} (Redis ${{ matrix.redis-versions }})
name: PHP ${{ matrix.php }} Redis ${{ matrix.redis }}
runs-on: ubuntu-latest
services:
redis:
image: redis:${{ matrix.redis-versions }}
ports:
- 6379:6379
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
strategy:
fail-fast: false
matrix:
php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2']
redis-versions: ['3', '4', '5', '6', '7']
php:
- '7.2'
- '7.3'
- '7.4'
- '8.0'
- '8.1'
- '8.2'
redis:
- '3'
- '4'
- '5'
- '6'
- '7'
services:
redis:
image: redis:${{ matrix.redis }}
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
ports:
- 6379:6379
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP with Composer and extensions
with:
php-version: ${{ matrix.php-versions }}
uses: shivammathur/setup-php@v2
- name: Checkout repository
uses: actions/checkout@v3
- name: Get Composer cache directory
id: composercache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Setup PHP with Composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: ${{ (matrix.php == '8.1' && matrix.redis == '7') && 'xdebug' || 'none' }}
- name: Cache Composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composercache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install Composer dependencies
uses: ramsey/composer-install@v2
with:
dependency-versions: highest
composer-options: ${{ matrix.php == '8.0' && '--ignore-platform-reqs' || '' }}
- name: Install Composer dependencies
env:
PHP_VERSION: ${{ matrix.php-versions }}
run: composer install --no-progress --prefer-dist --optimize-autoloader $(if [ "$PHP_VERSION" == "8.0" ]; then echo "--ignore-platform-reqs"; fi;)
- name: Run PHPUnit tests
if: ${{ matrix.php != '8.1' || matrix.redis != '7' }}
run: vendor/bin/phpunit --verbose
- name: Test with PHPUnit
run: vendor/bin/phpunit
- name: Run PHPUnit tests with coverage
if: ${{ matrix.php == '8.1' && matrix.redis == '7' }}
run: vendor/bin/phpunit --verbose --coverage-clover build/logs/clover.xml --coverage-filter ./src
- name: Send coverage to Coveralls
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: ${{ env.COVERALLS_REPO_TOKEN && matrix.php == '8.1' && matrix.redis == '7' }}
run: |
wget "https://github.com/php-coveralls/php-coveralls/releases/download/v2.5.3/php-coveralls.phar"
php ./php-coveralls.phar -v
+2
View File
@@ -1,6 +1,8 @@
/build
/vendor
.php-version
.php_cs.cache
.phpunit.result.cache
.php-cs-fixer.cache
composer.lock
phpunit.xml
+34
View File
@@ -0,0 +1,34 @@
<?php
$PREDIS_HEADER = <<<EOS
This file is part of the Predis package.
(c) 2009-2020 Daniele Alessandri
(c) 2021-2023 Till Krüss
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
EOS;
return (new PhpCsFixer\Config)
->setRules([
'@PHP71Migration' => true,
'header_comment' => ['header' => $PREDIS_HEADER],
'@Symfony' => true,
'phpdoc_separation' => false,
'phpdoc_annotation_without_dot' => false,
'no_superfluous_phpdoc_tags' => false,
'no_unneeded_curly_braces' => false,
'global_namespace_import' => true,
'yoda_style' => false,
'single_line_throw' => false,
'concat_space' => ['spacing' => 'one'],
'increment_style' => false,
])
->setFinder(
PhpCsFixer\Finder::create()
->in(__DIR__ . '/bin')
->in(__DIR__ . '/examples')
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests')
);
-33
View File
@@ -1,33 +0,0 @@
<?php
$PREDIS_HEADER = <<<EOS
This file is part of the Predis package.
(c) Daniele Alessandri <suppakilla@gmail.com>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
EOS;
return PhpCsFixer\Config::create()
->setUsingCache(true)
->setRules(array(
'@Symfony' => true,
'header_comment' => array(
'header' => $PREDIS_HEADER,
),
'ordered_imports' => true,
'phpdoc_order' => true,
'binary_operator_spaces' => array(
'align_double_arrow' => false,
'align_equals' => false,
),
'array_syntax' => array('syntax' => 'long'),
))
->setFinder(
PhpCsFixer\Finder::create()
->in(__DIR__.'/bin')
->in(__DIR__.'/src')
->in(__DIR__.'/tests')
->in(__DIR__.'/examples')
);
+81 -5
View File
@@ -1,5 +1,81 @@
## Changelog
## v2.1.2 (2023-03-02)
## Added
- Added stream commands to `KeyPrefixProcessor` (#1051)
- Added `ReplicationStrategy::$loadBalancing` option to disable replica reads (#1168)
- Added support for `FCALL` and `FUNCTIONS` commands (#1049)
- Added support for `PEXPIRETIME` command (#1031)
- Added support for `EXPIRETIME` command (#1029)
- Added support for `EVAL_RO` command (#1032)
- Added support for `LCS` command (#1035)
- Added support for `SORT_RO` command (#1044)
- Added support for `SINTERCARD` command (#1027)
- Added support for `EVALSHA_RO` command (#1034)
- Added support for new arguments for `BITPOS` and `BITCOUNT` commands (#1045)
- Added support for new arguments for `EXPIRE` and `EXPIREAT` commands (#1046)
## Bug Fixes
- Fixed deprecated function call syntax
## Deprecated
- Further deprecated phpiredis and webdis integration (#1179)
## Maintenance
- Applied coding standards
- Pass PHPStan level 2
## v2.1.1 (2023-01-17)
## Bug Fixes
- Fix `@template` in `Predis\Client` (#1017)
- Fix support options array in `ZINTERSTORE` and `ZUNIONSTORE` (#1018)
## Deprecated
- Deprecated phpiredis and webdis connections
## v2.1.0 (2023-01-16)
## New Features
- Implemented `GETEX` command (#872)
- Implemented `GETDEL` command (#869)
- Implemented `COPY` command (#866)
- Implemented `FAILOVER` command (#875)
- Implemented `LMOVE` command (#863)
- Implemented `LMPOP` command (#1013)
- Implemented `HRANDFIELD` command (#870)
- Implemented `SMISMEMBER` command (#871)
- Implemented `ZMPOP` command (#831)
- Implemented `BLMOVE` command (#865)
- Implemented `BLMPOP` command (#1015)
- Implemented `BZMPOP` command (#833)
- Implemented `BZPOPMIN` command (#862)
- Implemented `BZPOPMAX` command (#864)
- Implemented `ZUNION` command (#860)
- Implemented `ZINTER` command (#859)
- Implemented `ZINTERCARD` command (#861)
- Implemented `ZRANGESTORE` command (#829)
- Implemented `ZDIFFSTORE` command (#828)
- Implemented `ZDIFF` command (#826)
- Implemented `ZRANDMEMBER` command (#825)
- Implemented `ZMSCORE` (#823)
- Implemented `GEOSEARCH` command (#867)
- Implemented `GEOSEARCHSTORE` command (#873)
## Bug Fixes
- Added annotations to suppress PHP 8.1 return type deprecation warning (#810)
## Maintenance
- Added mixin annotations for traits (#835)
## v2.0.3 (2022-10-11)
- Improved PHP 8.2 support
- Call `is_resource()` before reading/writing
- Added partial support for Redis Stream commands
- Fixed Sentinel authentication issue
## v2.0.2 (2022-09-06)
- Fixed PHP 8.2 deprecation notice: Use of "static" in callables
@@ -21,7 +97,7 @@
- `cluster`: string value (`predis`, `redis`), callable returning an aggregate
connection.
- `replication`: string value (`predis`, `sentinel`), callable returning an
aggregate connection.
aggregate connection.
- `commands`: command factory, named array mapping command IDs to PHP classes,
callable returning a command factory or a named array.
- `connections`: connection factory, callable object returning a connection
@@ -34,7 +110,7 @@
acting as initializer instead of an aggregate connection instance.
- The `connections` client option now accepts certain string values identifying
certain combinations of configurations for the connection factory. Currenlty
certain combinations of configurations for the connection factory. Currently
this is used to provide a short way to configure Predis to load our phpiredis
based connection backends simply, accepted values are:
@@ -59,7 +135,7 @@
supported by the redis-sentinel backend due to its dynamic nature (connections
are retrieved and initialized at runtime from sentinels) but it is possible to
get a single connection from the pool by using its ID. It is also possible to
retrive a connection by role using the method getConnectionByRole().
retrieve a connection by role using the method getConnectionByRole().
- The concept of connection ID (ip:port pair) and connection alias (the `alias`
parameter) in `Predis\Connection\Cluster\PredisCluster` has been separated.
@@ -119,7 +195,7 @@
- Support Pub/Sub and Pipelines when using replication
- The class `Predis\Transaction\AbortedMultiExecException` now uses the correct
- The class `Predis\Transaction\AbortedMultiExecException` now uses the correct
default types for the `$code` (integer) parameter.
- __FIX__: using `strval` in `getScanOptions()` method, part of
@@ -127,7 +203,7 @@
string value of `$this->match` and not passing `null` to `strlen()` function.
- __FIX__: the value returned from `getArgument()` in `isReadOperation()` method,
part of `Predis\Replication\ReplicationStrategy` class, is checked to not pass
part of `Predis\Replication\ReplicationStrategy` class, is checked to not pass
`null` to `sha1` function.
- __FIX__: the value returned from `getArgument()` in `parseResponse()`method,
-44
View File
@@ -1,44 +0,0 @@
## Filing bug reports ##
Bugs or feature requests can be posted on the [GitHub issues](http://github.com/predis/predis/issues)
section of the project.
When reporting bugs, in addition to the obvious description of your issue you __must__ always provide
some essential information about your environment such as:
1. version of Predis (check the `VERSION` file or the `Predis\Client::VERSION` constant).
2. version of Redis (check `redis_version` returned by [`INFO`](http://redis.io/commands/info)).
3. version of PHP.
4. name and version of the operating system.
5. when possible, a small snippet of code that reproduces the issue.
__Think about it__: we do not have a crystal ball and cannot predict things or peer into the unknown
so please provide as much details as possible to help us isolating issues and fix them.
__Never__ use GitHub issues to post generic questions about Predis! When you have questions about
how Predis works or how it can be used, please just hop me an email and I will get back to you as
soon as possible.
## Contributing code ##
If you want to work on Predis, it is highly recommended that you first run the test suite in order
to check that everything is OK and report strange behaviours or bugs. When modifying Predis please
make sure that no warnings or notices are emitted by PHP running the interpreter in your development
environment with the `error_reporting` variable set to `E_ALL | E_STRICT`.
The recommended way to contribute to Predis is to fork the project on GitHub, create topic branches
on your newly created repository to fix bugs or add new features (possibly with tests covering your
modifications) and then open a pull request with a description of the applied changes. Obviously you
can use any other Git hosting provider of your preference.
We always aim for consistency in our code base so you should follow basic coding rules as defined by
[PSR-1](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md)
and [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
and stick with the conventions used in Predis to name classes and interfaces. Indentation should be
done with 4 spaces and code should be wrapped at 100 columns (please try to stay within this limit
even if the above mentioned official coding guidelines set the soft limit to 120 columns).
Please follow these [commit guidelines](http://git-scm.com/book/ch5-2.html#Commit-Guidelines) when
committing your code to Git and always write a meaningful (not necessarily extended) description of
your changes before opening pull requests.
+1 -1
View File
@@ -4,7 +4,7 @@ ________________________________________________
### What is the point of Predis? ###
The main point of Predis is about offering a highly customizable and extensible client for Redis,
that can be easily extended by developers while still being reasonabily fast. With Predis you can
that can be easily extended by developers while still being reasonably fast. With Predis you can
swap almost any class with your own custom implementation: you can have custom connection classes,
new distribution strategies for client-side sharding, or handlers to replace or add Redis commands.
All of this can be achieved without messing with the source code of the library and directly in your
+19 -19
View File
@@ -1,22 +1,22 @@
Copyright (c) 2009-2021 Daniele Alessandri
MIT License
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
Copyright (c) 2009-2020 Daniele Alessandri (original work)
Copyright (c) 2021-2023 Till Krüss (modified work)
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+11 -36
View File
@@ -1,10 +1,11 @@
# Predis #
[![Software license][ico-license]](LICENSE)
[![Latest stable][ico-version-stable]][link-packagist]
[![Latest development][ico-version-dev]][link-packagist]
[![Latest stable][ico-version-stable]][link-releases]
[![Latest development][ico-version-dev]][link-releases]
[![Monthly installs][ico-downloads-monthly]][link-downloads]
[![Build status][ico-build]][link-actions]
[![Coverage Status][ico-coverage]][link-coverage]
A flexible and feature-complete [Redis](http://redis.io) client for PHP 7.2 and newer.
@@ -24,7 +25,6 @@ More details about this project can be found on the [frequently asked questions]
- Abstraction for `SCAN`, `SSCAN`, `ZSCAN` and `HSCAN` (Redis >= 2.8) based on PHP iterators.
- Connections are established lazily by the client upon the first command and can be persisted.
- Connections can be established via TCP/IP (also TLS/SSL-encrypted) or UNIX domain sockets.
- Support for [Webdis](http://webd.is) (requires both `ext-curl` and `ext-phpiredis`).
- Support for custom connection classes for providing different network or protocol backends.
- Flexible system for defining custom commands and override the default ones.
@@ -396,31 +396,6 @@ $response = $client->lpushrand('random_values', $seed = mt_rand());
### Customizable connection backends ###
Predis can use different connection backends to connect to Redis. Two of them leverage a third party
extension such as [phpiredis](https://github.com/nrk/phpiredis) resulting in major performance gains
especially when dealing with big multibulk responses. While one is based on PHP streams, the other
is based on socket resources provided by `ext-socket`. Both support TCP/IP and UNIX domain sockets:
```php
$client = new Predis\Client('tcp://127.0.0.1', [
'connections' => [
'tcp' => 'Predis\Connection\PhpiredisStreamConnection', // PHP stream resources
'unix' => 'Predis\Connection\PhpiredisSocketConnection', // ext-socket resources
],
]);
```
The client can also be configured to rely on a [phpiredis](https://github.com/nrk/phpiredis)-backend
by specifying a descriptive string for the `connections` client option. Supported string values are:
- `phpiredis-stream` maps `tcp`, `redis` and `unix` to `Predis\Connection\PhpiredisStreamConnection`
- `phpiredis-socket` maps `tcp`, `redis` and `unix` to `Predis\Connection\PhpiredisSocketConnection`
- `phpiredis` is simply an alias of `phpiredis-stream`
```php
$client = new Predis\Client('tcp://127.0.0.1', ['connections' => 'phpiredis']);
```
Developers can create their own connection classes to support whole new network backends, extend
existing classes or provide completely different implementations. Connection classes must implement
`Predis\Connection\NodeConnectionInterface` or extend `Predis\Connection\AbstractConnection`:
@@ -447,9 +422,7 @@ implementation of the standard connection classes available in the `Predis\Conne
### Reporting bugs and contributing code ###
Contributions to Predis are highly appreciated either in the form of pull requests for new features,
bug fixes, or just bug reports. We only ask you to adhere to a [basic set of rules](CONTRIBUTING.md)
before submitting your changes or filing bugs on the issue tracker to make it easier for everyone to
stay consistent while working on the project.
bug fixes, or just bug reports. We only ask you to adhere to issue and pull request templates.
### Test suite ###
@@ -479,8 +452,8 @@ found [on its actions page](https://github.com/predis/predis/actions).
### Author ###
- [Daniele Alessandri](mailto:suppakilla@gmail.com) ([twitter](http://twitter.com/JoL1hAHN))
- [Till Krüss](https://till.im) ([Twitter](http://twitter.com/tillkruss))
- [Daniele Alessandri](mailto:suppakilla@gmail.com) ([twitter](http://twitter.com/JoL1hAHN))
### License ###
@@ -488,11 +461,13 @@ found [on its actions page](https://github.com/predis/predis/actions).
The code for Predis is distributed under the terms of the MIT license (see [LICENSE](LICENSE)).
[ico-license]: https://img.shields.io/github/license/predis/predis.svg?style=flat-square
[ico-version-stable]: https://img.shields.io/packagist/v/predis/predis.svg?style=flat-square
[ico-version-dev]: https://img.shields.io/packagist/vpre/predis/predis.svg?style=flat-square
[ico-version-stable]: https://img.shields.io/github/v/tag/predis/predis?label=stable&style=flat-square
[ico-version-dev]: https://img.shields.io/github/v/tag/predis/predis?include_prereleases&label=pre-release&style=flat-square
[ico-downloads-monthly]: https://img.shields.io/packagist/dm/predis/predis.svg?style=flat-square
[ico-build]: https://img.shields.io/github/workflow/status/predis/predis/Tests/main?style=flat-square
[ico-build]: https://img.shields.io/github/actions/workflow/status/predis/predis/tests.yml?branch=main&style=flat-square
[ico-coverage]: https://img.shields.io/coverallsCoverage/github/predis/predis?style=flat-square
[link-packagist]: https://packagist.org/packages/predis/predis
[link-releases]: https://github.com/predis/predis/releases
[link-actions]: https://github.com/predis/predis/actions
[link-downloads]: https://packagist.org/packages/predis/predis/stats
[link-coverage]: https://coveralls.io/github/predis/predis
+1 -1
View File
@@ -1 +1 @@
2.0.2
2.1.2
-2
View File
@@ -3,8 +3,6 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
+1 -5
View File
@@ -4,8 +4,6 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
@@ -119,7 +117,7 @@ class CommandTestCaseGenerator
protected function getTestRealm()
{
if (empty($this->options['realm'])) {
throw new RuntimeException('Invalid value for realm has been sepcified (empty).');
throw new RuntimeException('Invalid value for realm has been specified (empty).');
}
return $this->options['realm'];
@@ -170,8 +168,6 @@ class CommandTestCaseGenerator
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
+12 -14
View File
@@ -9,12 +9,6 @@
"issues": "https://github.com/predis/predis/issues"
},
"authors": [
{
"name": "Daniele Alessandri",
"email": "suppakilla@gmail.com",
"homepage": "http://clorophilla.net",
"role": "Creator & Maintainer"
},
{
"name": "Till Krüss",
"homepage": "https://till.im",
@@ -31,20 +25,24 @@
"php": "^7.2 || ^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.3",
"phpstan/phpstan": "^1.9",
"phpunit/phpunit": "^8.0 || ~9.4.4"
},
"suggest": {
"ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol",
"ext-curl": "Allows access to Webdis when paired with phpiredis"
"scripts": {
"phpstan": "phpstan analyse",
"style": "php-cs-fixer fix --diff --dry-run",
"style:fix": "php-cs-fixer fix"
},
"autoload": {
"psr-4": {
"Predis\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-main": "2.0-dev"
}
}
"config": {
"sort-packages": true,
"preferred-install": "dist"
},
"minimum-stability": "dev",
"prefer-stable": true
}
+7 -6
View File
@@ -3,13 +3,14 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// Developers can implement Predis\Distribution\DistributorInterface to create
// their own distributors used by the client to distribute keys among a cluster
@@ -27,7 +28,7 @@ class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
public function __construct()
{
$this->nodes = array();
$this->nodes = [];
$this->nodesCount = 0;
}
@@ -53,7 +54,7 @@ class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
public function getBySlot($slot)
{
return isset($this->nodes[$slot]) ? $this->nodes[$slot] : null;
return $this->nodes[$slot] ?? null;
}
public function getByHash($hash)
@@ -87,7 +88,7 @@ class NaiveDistributor implements DistributorInterface, HashGeneratorInterface
}
}
$options = array(
$options = [
'cluster' => function () {
$distributor = new NaiveDistributor();
$strategy = new PredisStrategy($distributor);
@@ -95,7 +96,7 @@ $options = array(
return $cluster;
},
);
];
$client = new Predis\Client($multiple_servers, $options);
+17 -16
View File
@@ -3,17 +3,18 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// This is an example of how you can easily extend an existing connection class
// and trace the execution of commands for debugging purposes. This can be quite
// useful as a starting poing to understand how your application interacts with
// useful as a starting point to understand how your application interacts with
// Redis.
use Predis\Command\CommandInterface;
@@ -22,7 +23,7 @@ use Predis\Connection\StreamConnection;
class SimpleDebuggableConnection extends StreamConnection
{
private $tstart = 0;
private $debugBuffer = array();
private $debugBuffer = [];
public function connect()
{
@@ -65,11 +66,11 @@ class SimpleDebuggableConnection extends StreamConnection
}
}
$options = array(
'connections' => array(
$options = [
'connections' => [
'tcp' => 'SimpleDebuggableConnection',
),
);
],
];
$client = new Predis\Client($single_server, $options);
$client->set('foo', 'bar');
@@ -80,13 +81,13 @@ var_export($client->getConnection()->getDebugBuffer());
/* OUTPUT:
array (
0 => 'SELECT 15 -> 127.0.0.1:6379 [0.0008s]',
1 => 'SELECT 15 <- 127.0.0.1:6379 [0.001s]',
2 => 'SET foo -> 127.0.0.1:6379 [0.001s]',
3 => 'SET foo <- 127.0.0.1:6379 [0.0011s]',
4 => 'GET foo -> 127.0.0.1:6379 [0.0013s]',
5 => 'GET foo <- 127.0.0.1:6379 [0.0015s]',
6 => 'INFO -> 127.0.0.1:6379 [0.0019s]',
7 => 'INFO <- 127.0.0.1:6379 [0.0022s]',
0 => 'SELECT 15 -> 127.0.0.1:6379 [0.0008s]',
1 => 'SELECT 15 <- 127.0.0.1:6379 [0.001s]',
2 => 'SET foo -> 127.0.0.1:6379 [0.001s]',
3 => 'SET foo <- 127.0.0.1:6379 [0.0011s]',
4 => 'GET foo -> 127.0.0.1:6379 [0.0013s]',
5 => 'GET foo <- 127.0.0.1:6379 [0.0015s]',
6 => 'INFO -> 127.0.0.1:6379 [0.0019s]',
7 => 'INFO <- 127.0.0.1:6379 [0.0022s]',
)
*/
+6 -5
View File
@@ -3,13 +3,14 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// This is a basic example on how to use the Predis\DispatcherLoop class.
//
@@ -23,7 +24,7 @@ require __DIR__.'/shared.php';
// PUBLISH control terminate_dispatcher
// Create a client and disable r/w timeout on the socket
$client = new Predis\Client($single_server + array('read_write_timeout' => 0));
$client = new Predis\Client($single_server + ['read_write_timeout' => 0]);
// Return an initialized PubSub consumer instance from the client.
$pubsub = $client->pubSubLoop();
@@ -38,7 +39,7 @@ class EventsListener implements Countable
public function __construct()
{
$this->events = array();
$this->events = [];
}
public function count()
@@ -58,7 +59,7 @@ class EventsListener implements Countable
}
// Attach our callable class to the dispatcher.
$dispatcher->attachCallback('events', ($events = new EventsListener()));
$dispatcher->attachCallback('events', $events = new EventsListener());
// Attach a function to control the dispatcher loop termination with a message.
$dispatcher->attachCallback('control', function ($payload, $dispatcher) {
+23 -17
View File
@@ -3,13 +3,14 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
$client = new Predis\Client($single_server);
@@ -17,41 +18,46 @@ $client = new Predis\Client($single_server);
$client->set('library', 'predis');
$response = $client->get('library');
var_export($response); echo PHP_EOL;
var_export($response);
echo PHP_EOL;
/* OUTPUT: 'predis' */
// Redis has the MSET and MGET commands to set or get multiple keys in one go,
// cases like this Predis accepts arguments for variadic commands both as a list
// of arguments or an array containing all of the keys and/or values.
$mkv = array(
$mkv = [
'uid:0001' => '1st user',
'uid:0002' => '2nd user',
'uid:0003' => '3rd user',
);
];
$client->mset($mkv);
$response = $client->mget(array_keys($mkv));
var_export($response); echo PHP_EOL;
var_export($response);
echo PHP_EOL;
/* OUTPUT:
array (
0 => '1st user',
1 => '2nd user',
2 => '3rd user',
) */
0 => '1st user',
1 => '2nd user',
2 => '3rd user',
)
*/
// Predis can also send "raw" commands to Redis. The difference between sending
// commands to Redis the usual way and the "raw" way is that in the latter case
// their arguments are not filtered nor responses coming from Redis are parsed.
$response = $client->executeRaw(array(
$response = $client->executeRaw([
'MGET', 'uid:0001', 'uid:0002', 'uid:0003',
));
]);
var_export($response); echo PHP_EOL;
var_export($response);
echo PHP_EOL;
/* OUTPUT:
array (
0 => '1st user',
1 => '2nd user',
2 => '3rd user',
) */
0 => '1st user',
1 => '2nd user',
2 => '3rd user',
)
*/
+9 -8
View File
@@ -3,34 +3,35 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// Predis can prefix keys found in commands arguments before sending commands to
// Redis, even for complex commands such as SORT, ZUNIONSTORE and ZINTERSTORE.
// Prefixing keys can be useful to create user-level namespaces for you keyspace
// thus reducing the need for separate logical databases in certain scenarios.
$client = new Predis\Client($single_server, array('prefix' => 'nrk:'));
$client = new Predis\Client($single_server, ['prefix' => 'nrk:']);
$client->mset(array('foo' => 'bar', 'lol' => 'wut'));
$client->mset(['foo' => 'bar', 'lol' => 'wut']);
var_export($client->mget('foo', 'lol'));
/*
array (
0 => 'bar',
1 => 'wut',
0 => 'bar',
1 => 'wut',
)
*/
var_export($client->keys('*'));
/*
array (
0 => 'nrk:foo',
1 => 'nrk:lol',
0 => 'nrk:foo',
1 => 'nrk:lol',
)
*/
+15 -14
View File
@@ -3,13 +3,14 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// This example will not work with versions of Redis < 2.6.
//
@@ -36,11 +37,11 @@ local cmd, insert = redis.call, table.insert
local increment, results = ARGV[1], { }
for idx, key in ipairs(KEYS) do
if cmd('exists', key) == 1 then
insert(results, idx, cmd('incrby', key, increment))
else
insert(results, idx, false)
end
if cmd('exists', key) == 1 then
insert(results, idx, cmd('incrby', key, increment))
else
insert(results, idx, false)
end
end
return results
@@ -48,11 +49,11 @@ LUA;
}
}
$client = new Predis\Client($single_server, array(
'commands' => array(
$client = new Predis\Client($single_server, [
'commands' => [
'increxby' => 'IncrementExistingKeysBy',
),
));
],
]);
$client->mset('foo', 10, 'foobar', 100);
@@ -60,8 +61,8 @@ var_export($client->increxby('foo', 'foofoo', 'foobar', 50));
/*
array (
0 => 60,
1 => NULL,
2 => 150,
0 => 60,
1 => NULL,
2 => 150,
)
*/
+4 -3
View File
@@ -3,13 +3,14 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// This is a basic example on how to use the Predis\Monitor\Consumer class. You
// can use redis-cli to send commands to the same Redis instance your client is
@@ -17,7 +18,7 @@ require __DIR__.'/shared.php';
// exit the monitor loop and terminate this script in a graceful way.
// Create a client and disable r/w timeout on the socket.
$client = new Predis\Client($single_server + array('read_write_timeout' => 0));
$client = new Predis\Client($single_server + ['read_write_timeout' => 0]);
// Use only one instance of DateTime, we will update the timestamp later.
$timestamp = new DateTime();
+14 -13
View File
@@ -3,13 +3,14 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// When you have a whole set of consecutive commands to send to a redis server,
// you can use a pipeline to dramatically improve performances. Pipelines can
@@ -30,16 +31,16 @@ var_export($responses);
/* OUTPUT:
array (
0 => Predis\Response\Status::__set_state(array(
'payload' => 'OK',
)),
1 => 10,
2 => 40,
3 => true,
4 => '40',
5 => array (
0 => NULL,
1 => '40',
),
0 => Predis\Response\Status::__set_state(array(
'payload' => 'OK',
)),
1 => 10,
2 => 40,
3 => true,
4 => '40',
5 => array (
0 => NULL,
1 => '40',
),
)
*/
+5 -4
View File
@@ -3,19 +3,20 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// Starting from Redis 2.0 clients can subscribe and listen for events published
// on certain channels using a Publish/Subscribe (PUB/SUB) approach.
// Create a client and disable r/w timeout on the socket
$client = new Predis\Client($single_server + array('read_write_timeout' => 0));
$client = new Predis\Client($single_server + ['read_write_timeout' => 0]);
// Initialize a new pubsub consumer.
$pubsub = $client->pubSubLoop();
@@ -43,7 +44,7 @@ foreach ($pubsub as $message) {
}
} else {
echo "Received the following message from {$message->channel}:",
PHP_EOL, " {$message->payload}", PHP_EOL, PHP_EOL;
PHP_EOL, " {$message->payload}", PHP_EOL, PHP_EOL;
}
break;
}
+21 -20
View File
@@ -3,13 +3,14 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
use Predis\Collection\Iterator;
@@ -47,9 +48,9 @@ foreach (new Iterator\Keyspace($client, 'predis:*') as $key) {
/* OUTPUT
Scan the keyspace matching only our prefixed keys:
- predis:zset
- predis:set
- predis:hash
- predis:zset
- predis:set
- predis:hash
*/
// === Set iterator based on SSCAN ===
@@ -60,11 +61,11 @@ foreach (new Iterator\SetKey($client, 'predis:set') as $member) {
/* OUTPUT
Scan members of `predis:set`:
- member:1
- member:4
- member:0
- member:3
- member:2
- member:1
- member:4
- member:0
- member:3
- member:2
*/
// === Sorted set iterator based on ZSCAN ===
@@ -75,11 +76,11 @@ foreach (new Iterator\SortedSetKey($client, 'predis:zset') as $member => $rank)
/* OUTPUT
Scan members and ranks of `predis:zset`:
- member:4 [rank: -4]
- member:3 [rank: -3]
- member:2 [rank: -2]
- member:1 [rank: -1]
- member:0 [rank: 0]
- member:4 [rank: -4]
- member:3 [rank: -3]
- member:2 [rank: -2]
- member:1 [rank: -1]
- member:0 [rank: 0]
*/
// === Hash iterator based on HSCAN ===
@@ -90,9 +91,9 @@ foreach (new Iterator\HashKey($client, 'predis:hash') as $field => $value) {
/* OUTPUT
Scan fields and values of `predis:hash`:
- field:0 => value:0
- field:1 => value:1
- field:2 => value:2
- field:3 => value:3
- field:4 => value:4
- field:0 => value:0
- field:1 => value:1
- field:2 => value:2
- field:3 => value:3
- field:4 => value:4
*/
+10 -9
View File
@@ -3,13 +3,14 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// Predis allows to set Lua scripts as read-only operations for replication.
// This works for both EVAL and EVALSHA and also for the client-side abstraction
@@ -29,7 +30,7 @@ use Predis\Replication\ReplicationStrategy;
class HashMultipleGetAll extends ScriptCommand
{
const BODY = <<<LUA
public const BODY = <<<LUA
local hashes = {}
for _, key in pairs(KEYS) do
table.insert(hashes, key)
@@ -46,15 +47,15 @@ LUA;
// ------------------------------------------------------------------------- //
$parameters = array(
$parameters = [
'tcp://127.0.0.1:6381?role=master&database=15',
'tcp://127.0.0.1:6382?role=slave&alias=slave-01&database=15',
);
];
$options = array(
'commands' => array(
$options = [
'commands' => [
'hmgetall' => 'HashMultipleGetAll',
),
],
'replication' => function () {
$strategy = new ReplicationStrategy();
$strategy->setScriptReadOnly(HashMultipleGetAll::BODY);
@@ -63,7 +64,7 @@ $options = array(
return $replication;
},
);
];
// ------------------------------------------------------------------------- //
+7 -6
View File
@@ -3,13 +3,14 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// Predis supports redis-sentinel to provide high availability in master / slave
// scenarios. The only but relevant difference with a basic replication scenario
@@ -25,16 +26,16 @@ require __DIR__.'/shared.php';
// without an explicit timeout value.
//
// NOTE: in real-world scenarios sentinels should be running on different hosts!
$sentinels = array(
$sentinels = [
'tcp://127.0.0.1:5380?timeout=0.100',
'tcp://127.0.0.1:5381?timeout=0.100',
'tcp://127.0.0.1:5382?timeout=0.100',
);
];
$client = new Predis\Client($sentinels, array(
$client = new Predis\Client($sentinels, [
'replication' => 'sentinel',
'service' => 'mymaster',
));
]);
// Read operation.
$exists = $client->exists('foo') ? 'yes' : 'no';
+6 -5
View File
@@ -3,13 +3,14 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// Predis supports master / slave replication scenarios where write operations
// are performed on the master server and read operations are executed against
@@ -21,12 +22,12 @@ require __DIR__.'/shared.php';
// slave of the first one (see the "SLAVEOF" command).
//
$parameters = array(
$parameters = [
'tcp://127.0.0.1:6381?role=master&database=15',
'tcp://127.0.0.1:6382?role=slave&database=15',
);
];
$options = array('replication' => 'predis');
$options = ['replication' => 'predis'];
$client = new Predis\Client($parameters, $options);
+6 -5
View File
@@ -3,13 +3,14 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// This example demonstrates how to use Predis to save PHP sessions on Redis.
//
@@ -25,16 +26,16 @@ require __DIR__.'/shared.php';
//
if (!interface_exists('SessionHandlerInterface')) {
die('ATTENTION: the session handler implemented by Predis requires PHP >= 5.4.0 '.
exit('ATTENTION: the session handler implemented by Predis requires PHP >= 5.4.0 ' .
"or a polyfill for SessionHandlerInterface provided by an external package.\n");
}
// Instantiate a new client just like you would normally do. Using a prefix for
// keys will effectively prefix all session keys with the specified string.
$client = new Predis\Client($single_server, array('prefix' => 'sessions:'));
$client = new Predis\Client($single_server, ['prefix' => 'sessions:']);
// Set `gc_maxlifetime` to specify a time-to-live of 5 seconds for session keys.
$handler = new Predis\Session\Handler($client, array('gc_maxlifetime' => 5));
$handler = new Predis\Session\Handler($client, ['gc_maxlifetime' => 5]);
// Register the session handler.
$handler->register();
+20 -19
View File
@@ -3,17 +3,18 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
if (PHP_SAPI !== 'cli') {
die("Example scripts are meant to be executed locally via CLI.");
exit('Example scripts are meant to be executed locally via CLI.');
}
require __DIR__.'/../autoload.php';
require __DIR__ . '/../autoload.php';
function redis_version($info)
{
@@ -26,23 +27,23 @@ function redis_version($info)
}
}
$single_server = array(
$single_server = [
'host' => '127.0.0.1',
'port' => 6379,
'database' => 15,
);
];
$multiple_servers = array(
array(
'host' => '127.0.0.1',
'port' => 6379,
'database' => 15,
'alias' => 'first',
),
array(
'host' => '127.0.0.1',
'port' => 6380,
'database' => 15,
'alias' => 'second',
),
);
$multiple_servers = [
[
'host' => '127.0.0.1',
'port' => 6379,
'database' => 15,
'alias' => 'first',
],
[
'host' => '127.0.0.1',
'port' => 6380,
'database' => 15,
'alias' => 'second',
],
];
+6 -5
View File
@@ -3,13 +3,14 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
require __DIR__.'/shared.php';
require __DIR__ . '/shared.php';
// This is an implementation of an atomic client-side ZPOP using the support for
// check-and-set (CAS) operations with MULTI/EXEC transactions, as described in
@@ -27,15 +28,15 @@ require __DIR__.'/shared.php';
function zpop($client, $key)
{
$element = null;
$options = array(
$options = [
'cas' => true, // Initialize with support for CAS operations
'watch' => $key, // Key that needs to be WATCHed to detect changes
'retry' => 3, // Number of retries on aborted transactions, after
// which the client bails out with an exception.
);
];
$client->transaction($options, function ($tx) use ($key, &$element) {
@list($element) = $tx->zrange($key, 0, 0);
@[$element] = $tx->zrange($key, 0, 0);
if (isset($element)) {
$tx->multi(); // With CAS, MULTI *must* be explicitly invoked.
+15
View File
@@ -0,0 +1,15 @@
parameters:
level: 0
paths:
- tests/
ignoreErrors:
# Uses func_get_args()
- message: "#^Static method Predis\\\\Command\\\\RawCommand\\:\\:create\\(\\) invoked with 0 parameters, at least 1 required\\.$#"
count: 1
path: tests/Predis/Command/RawCommandTest.php
# Mockery
- message: "#^Call to an undefined method Predis\\\\Configuration\\\\Option\\\\AggregateTest\\:\\:getMockConnectionClass\\(\\)\\.$#"
count: 2
path: tests/Predis/Configuration/Option/AggregateTest.php
+56
View File
@@ -0,0 +1,56 @@
parameters:
level: 2
paths:
- src/
ignoreErrors:
# Tricky ones
- message: "#^Cannot cast Predis\\\\Response\\\\ResponseInterface to string\\.$#"
count: 1
path: src/Client.php
- message: "#^Cannot cast Predis\\\\Connection\\\\ConnectionInterface to string\\.$#"
count: 1
path: src/Client.php
# phpiredis extension is not installed
- "#^Function phpiredis_\\w+ not found\\.$#"
- "#^Constant PHPIREDIS_#"
# "new static" in non-final classes
- message: "#^Unsafe usage of new static\\(\\)\\.$#"
count: 3
path: src/Client.php
- message: "#^Unsafe usage of new static\\(\\)\\.$#"
count: 1
path: src/Connection/Parameters.php
# Using an interface as concrete type
- message: "#^Call to an undefined method Predis\\\\Command\\\\FactoryInterface\\:\\:define\\(\\)\\.$#"
count: 1
path: src/Configuration/Option/Commands.php
- message: "#^Call to an undefined method Predis\\\\Command\\\\FactoryInterface\\:\\:undefine\\(\\)\\.$#"
count: 1
path: src/Configuration/Option/Commands.php
- message: "#^Access to an undefined property Predis\\\\Configuration\\\\OptionsInterface\\:\\:\\$parameters\\.$#"
count: 1
path: src/Configuration/Option/Connections.php
- message: "#^Access to an undefined property Predis\\\\Connection\\\\ParametersInterface\\:\\:\\$weight\\.$#"
count: 1
path: src/Connection/Cluster/PredisCluster.php
- message: "#^Variable \\$response might not be defined\\.$#"
count: 2
path: src/Connection/Cluster/RedisCluster.php
- message: "#^Access to an undefined property Predis\\\\Connection\\\\ParametersInterface\\:\\:\\$role\\.$#"
count: 1
path: src/Connection/Replication/MasterSlaveReplication.php
- message: "#^Access to an undefined property Predis\\\\Connection\\\\ParametersInterface\\:\\:\\$role\\.$#"
count: 1
path: src/Connection/Replication/SentinelReplication.php
# try/catch problems
- message: "#^Variable \\$connection might not be defined\\.$#"
count: 1
path: src/Connection/Replication/MasterSlaveReplication.php
- message: "#^Variable \\$response might not be defined\\.$#"
count: 1
path: src/Connection/Replication/MasterSlaveReplication.php
- message: "#^Variable \\$response might not be defined\\.$#"
count: 1
path: src/Connection/Replication/SentinelReplication.php
+20 -10
View File
@@ -1,14 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
beStrictAboutTestsThatDoNotTestAnything="true">
<phpunit
bootstrap="tests/bootstrap.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
beStrictAboutTestsThatDoNotTestAnything="true"
>
<testsuites>
<testsuite name="Predis Test Suite">
@@ -16,6 +17,15 @@
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./src</directory>
</include>
<report>
<clover outputFile="build/logs/clover.xml"/>
</report>
</coverage>
<groups>
<exclude>
<group>ext-phpiredis</group>
+5 -4
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -30,7 +31,7 @@ class Autoloader
public function __construct($baseDirectory = __DIR__)
{
$this->directory = $baseDirectory;
$this->prefix = __NAMESPACE__.'\\';
$this->prefix = __NAMESPACE__ . '\\';
$this->prefixLength = strlen($this->prefix);
}
@@ -41,7 +42,7 @@ class Autoloader
*/
public static function register($prepend = false)
{
spl_autoload_register(array(new self(), 'autoload'), true, $prepend);
spl_autoload_register([new self(), 'autoload'], true, $prepend);
}
/**
@@ -53,7 +54,7 @@ class Autoloader
{
if (0 === strpos($className, $this->prefix)) {
$parts = explode('\\', substr($className, $this->prefixLength));
$filepath = $this->directory.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts).'.php';
$filepath = $this->directory . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $parts) . '.php';
if (is_file($filepath)) {
require $filepath;
+73 -41
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -11,8 +12,13 @@
namespace Predis;
use ArrayIterator;
use InvalidArgumentException;
use IteratorAggregate;
use Predis\Command\CommandInterface;
use Predis\Command\RawCommand;
use Predis\Command\Redis\Container\ContainerFactory;
use Predis\Command\Redis\Container\ContainerInterface;
use Predis\Command\ScriptCommand;
use Predis\Configuration\Options;
use Predis\Configuration\OptionsInterface;
@@ -26,6 +32,9 @@ use Predis\Response\ErrorInterface as ErrorResponseInterface;
use Predis\Response\ResponseInterface;
use Predis\Response\ServerException;
use Predis\Transaction\MultiExec as MultiExecTransaction;
use ReturnTypeWillChange;
use RuntimeException;
use Traversable;
/**
* Client class used for connecting and executing commands on Redis.
@@ -34,13 +43,11 @@ use Predis\Transaction\MultiExec as MultiExecTransaction;
* abstractions are built. Internally it aggregates various other classes each
* one with its own responsibility and scope.
*
* {@inheritdoc}
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @template-implements \IteratorAggregate<string, static>
*/
class Client implements ClientInterface, \IteratorAggregate
class Client implements ClientInterface, IteratorAggregate
{
const VERSION = '2.0.2';
public const VERSION = '2.1.2';
/** @var OptionsInterface */
private $options;
@@ -57,8 +64,8 @@ class Client implements ClientInterface, \IteratorAggregate
*/
public function __construct($parameters = null, $options = null)
{
$this->options = static::createOptions($options ?? new Options);
$this->connection = static::createConnection($this->options, $parameters ?? new Parameters);
$this->options = static::createOptions($options ?? new Options());
$this->connection = static::createConnection($this->options, $parameters ?? new Parameters());
$this->commands = $this->options->commands;
}
@@ -67,9 +74,8 @@ class Client implements ClientInterface, \IteratorAggregate
*
* @param array|OptionsInterface $options Set of client options
*
* @throws \InvalidArgumentException
*
* @return OptionsInterface
* @throws InvalidArgumentException
*/
protected static function createOptions($options)
{
@@ -78,7 +84,7 @@ class Client implements ClientInterface, \IteratorAggregate
} elseif ($options instanceof OptionsInterface) {
return $options;
} else {
throw new \InvalidArgumentException('Invalid type for client options');
throw new InvalidArgumentException('Invalid type for client options');
}
}
@@ -103,9 +109,8 @@ class Client implements ClientInterface, \IteratorAggregate
* @param OptionsInterface $options Client options container
* @param mixed $parameters Connection parameters
*
* @throws \InvalidArgumentException
*
* @return ConnectionInterface
* @throws InvalidArgumentException
*/
protected static function createConnection(OptionsInterface $options, $parameters)
{
@@ -127,7 +132,7 @@ class Client implements ClientInterface, \IteratorAggregate
} elseif ($options->defined('aggregate') && $initializer = $options->aggregate) {
return $initializer($parameters, false);
} else {
throw new \InvalidArgumentException(
throw new InvalidArgumentException(
'Array of connection parameters requires `cluster`, `replication` or `aggregate` client option'
);
}
@@ -137,13 +142,13 @@ class Client implements ClientInterface, \IteratorAggregate
$connection = call_user_func($parameters, $options);
if (!$connection instanceof ConnectionInterface) {
throw new \InvalidArgumentException('Callable parameters must return a valid connection');
throw new InvalidArgumentException('Callable parameters must return a valid connection');
}
return $connection;
}
throw new \InvalidArgumentException('Invalid type for connection parameters');
throw new InvalidArgumentException('Invalid type for connection parameters');
}
/**
@@ -196,17 +201,17 @@ class Client implements ClientInterface, \IteratorAggregate
{
$selector = strtolower($selector);
if (!in_array($selector, array('id', 'key', 'slot', 'role', 'alias', 'command'))) {
throw new \InvalidArgumentException("Invalid selector type: `$selector`");
if (!in_array($selector, ['id', 'key', 'slot', 'role', 'alias', 'command'])) {
throw new InvalidArgumentException("Invalid selector type: `$selector`");
}
if (!method_exists($this->connection, $method = "getConnectionBy$selector")) {
$class = get_class($this->connection);
throw new \InvalidArgumentException("Selecting connection by $selector is not supported by $class");
throw new InvalidArgumentException("Selecting connection by $selector is not supported by $class");
}
if (!$connection = $this->connection->$method($value)) {
throw new \InvalidArgumentException("Cannot find a connection by $selector matching `$value`");
throw new InvalidArgumentException("Cannot find a connection by $selector matching `$value`");
}
return new static($connection, $this->getOptions());
@@ -303,11 +308,39 @@ class Client implements ClientInterface, \IteratorAggregate
/**
* {@inheritdoc}
*/
public function createCommand($commandID, $arguments = array())
public function createCommand($commandID, $arguments = [])
{
return $this->commands->create($commandID, $arguments);
}
/**
* @param $name
* @return ContainerInterface
*/
public function __get($name)
{
return ContainerFactory::create($this, $name);
}
/**
* @param $name
* @param $value
* @return mixed
*/
public function __set($name, $value)
{
throw new RuntimeException('Not allowed');
}
/**
* @param $name
* @return mixed
*/
public function __isset($name)
{
throw new RuntimeException('Not allowed');
}
/**
* {@inheritdoc}
*/
@@ -332,9 +365,8 @@ class Client implements ClientInterface, \IteratorAggregate
* @param CommandInterface $command Redis command that generated the error.
* @param ErrorResponseInterface $response Instance of the error response.
*
* @throws ServerException
*
* @return mixed
* @throws ServerException
*/
protected function onErrorResponse(CommandInterface $command, ErrorResponseInterface $response)
{
@@ -357,7 +389,7 @@ class Client implements ClientInterface, \IteratorAggregate
/**
* Executes the specified initializer method on `$this` by adjusting the
* actual invokation depending on the arity (0, 1 or 2 arguments). This is
* actual invocation depending on the arity (0, 1 or 2 arguments). This is
* simply an utility method to create Redis contexts instances since they
* follow a common initialization path.
*
@@ -378,26 +410,24 @@ class Client implements ClientInterface, \IteratorAggregate
: $this->$initializer(null, $argv[0]);
case 2:
list($arg0, $arg1) = $argv;
[$arg0, $arg1] = $argv;
return $this->$initializer($arg0, $arg1);
// @codeCoverageIgnoreStart
default:
return $this->$initializer($this, $argv);
}
// @codeCoverageIgnoreEnd
}
/**
* Creates a new pipeline context and returns it, or returns the results of
* a pipeline executed inside the optionally provided callable object.
*
* @param mixed ... Array of options, a callable for execution, or both.
* @param mixed ...$arguments Array of options, a callable for execution, or both.
*
* @return Pipeline|array
*/
public function pipeline(/* arguments */)
public function pipeline(...$arguments)
{
return $this->sharedContextFactory('createPipeline', func_get_args());
}
@@ -436,11 +466,11 @@ class Client implements ClientInterface, \IteratorAggregate
* Creates a new transaction context and returns it, or returns the results
* of a transaction executed inside the optionally provided callable object.
*
* @param mixed ... Array of options, a callable for execution, or both.
* @param mixed ...$arguments Array of options, a callable for execution, or both.
*
* @return MultiExecTransaction|array
*/
public function transaction(/* arguments */)
public function transaction(...$arguments)
{
return $this->sharedContextFactory('createTransaction', func_get_args());
}
@@ -468,11 +498,11 @@ class Client implements ClientInterface, \IteratorAggregate
* Creates a new publish/subscribe context and returns it, or starts its loop
* inside the optionally provided callable object.
*
* @param mixed ... Array of options, a callable for execution, or both.
* @param mixed ...$arguments Array of options, a callable for execution, or both.
*
* @return PubSubConsumer|null
*/
public function pubSubLoop(/* arguments */)
public function pubSubLoop(...$arguments)
{
return $this->sharedContextFactory('createPubSub', func_get_args());
}
@@ -498,6 +528,8 @@ class Client implements ClientInterface, \IteratorAggregate
$pubsub->stop();
}
}
return null;
}
/**
@@ -511,24 +543,24 @@ class Client implements ClientInterface, \IteratorAggregate
}
/**
* {@inheritdoc}
* @return Traversable<string, static>
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function getIterator()
{
$clients = array();
$clients = [];
$connection = $this->getConnection();
if (!$connection instanceof \Traversable) {
return new \ArrayIterator(array(
(string) $connection => new static($connection, $this->getOptions())
));
if (!$connection instanceof Traversable) {
return new ArrayIterator([
(string) $connection => new static($connection, $this->getOptions()),
]);
}
foreach ($connection as $node) {
$clients[(string) $node] = new static($node, $this->getOptions());
}
return new \ArrayIterator($clients);
return new ArrayIterator($clients);
}
}
+47 -8
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -11,16 +12,23 @@
namespace Predis;
use Predis\Command\Argument\Geospatial\ByInterface;
use Predis\Command\Argument\Geospatial\FromInterface;
use Predis\Command\Argument\Server\LimitOffsetCount;
use Predis\Command\Argument\Server\To;
use Predis\Command\CommandInterface;
use Predis\Command\Redis\Container\FunctionContainer;
/**
* Interface defining a client-side context such as a pipeline or transaction.
*
* @method $this copy(string $source, string $destination, int $db = -1, bool $replace = false)
* @method $this del(array|string $keys)
* @method $this dump($key)
* @method $this exists($key)
* @method $this expire($key, $seconds)
* @method $this expireat($key, $timestamp)
* @method $this expire($key, $seconds, string $expireOption = '')
* @method $this expireat($key, $timestamp, string $expireOption = '')
* @method $this expiretime(string $key)
* @method $this keys($pattern)
* @method $this move($key, $db)
* @method $this object($subcommand, $key)
@@ -33,18 +41,27 @@ use Predis\Command\CommandInterface;
* @method $this renamenx($key, $target)
* @method $this scan($cursor, array $options = null)
* @method $this sort($key, array $options = null)
* @method $this sort_ro(string $key, ?string $byPattern = null, ?LimitOffsetCount $limit = null, array $getPatterns = [], ?string $sorting = null, bool $alpha = false)
* @method $this ttl($key)
* @method $this type($key)
* @method $this append($key, $value)
* @method $this bitcount($key, $start = null, $end = null)
* @method $this bitcount($key, $start = null, $end = null, string $index = 'byte')
* @method $this bitop($operation, $destkey, $key)
* @method $this bitfield($key, $subcommand, ...$subcommandArg)
* @method $this bitpos($key, $bit, $start = null, $end = null)
* @method $this bitpos($key, $bit, $start = null, $end = null, string $index = 'byte')
* @method $this blmpop(int $timeout, array $keys, string $modifier = 'left', int $count = 1)
* @method $this bzpopmax(array $keys, int $timeout)
* @method $this bzpopmin(array $keys, int $timeout)
* @method $this bzmpop(int $timeout, array $keys, string $modifier = 'min', int $count = 1)
* @method $this decr($key)
* @method $this decrby($key, $decrement)
* @method $this failover(?To $to = null, bool $abort = false, int $timeout = -1)
* @method $this fcall(string $function, array $keys, ...$args)
* @method $this get($key)
* @method $this getbit($key, $offset)
* @method $this getex(string $key, $modifier = '', $value = false)
* @method $this getrange($key, $start, $end)
* @method $this getdel(string $key)
* @method $this getset($key, $value)
* @method $this incr($key)
* @method $this incrby($key, $increment)
@@ -69,17 +86,22 @@ use Predis\Command\CommandInterface;
* @method $this hlen($key)
* @method $this hmget($key, array $fields)
* @method $this hmset($key, array $dictionary)
* @method $this hrandfield(string $key, int $count = 1, bool $withValues = false)
* @method $this hscan($key, $cursor, array $options = null)
* @method $this hset($key, $field, $value)
* @method $this hsetnx($key, $field, $value)
* @method $this hvals($key)
* @method $this hstrlen($key, $field)
* @method $this blmove(string $source, string $destination, string $where, string $to, int $timeout)
* @method $this blpop(array|string $keys, $timeout)
* @method $this brpop(array|string $keys, $timeout)
* @method $this brpoplpush($source, $destination, $timeout)
* @method $this lcs(string $key1, string $key2, bool $len = false, bool $idx = false, int $minMatchLen = 0, bool $withMatchLen = false)
* @method $this lindex($key, $index)
* @method $this linsert($key, $whence, $pivot, $value)
* @method $this llen($key)
* @method $this lmove(string $source, string $destination, string $where, string $to)
* @method $this lmpop(array $keys, string $modifier = 'left', int $count = 1)
* @method $this lpop($key)
* @method $this lpush($key, array $values)
* @method $this lpushx($key, array $values)
@@ -96,9 +118,11 @@ use Predis\Command\CommandInterface;
* @method $this sdiff(array|string $keys)
* @method $this sdiffstore($destination, array|string $keys)
* @method $this sinter(array|string $keys)
* @method $this sintercard(array $keys, int $limit = 0)
* @method $this sinterstore($destination, array|string $keys)
* @method $this sismember($key, $member)
* @method $this smembers($key)
* @method $this smismember(string $key, string ...$members)
* @method $this smove($source, $destination, $member)
* @method $this spop($key, $count = null)
* @method $this srandmember($key, $count = null)
@@ -109,10 +133,18 @@ use Predis\Command\CommandInterface;
* @method $this zadd($key, array $membersAndScoresDictionary)
* @method $this zcard($key)
* @method $this zcount($key, $min, $max)
* @method $this zdiff(array $keys, bool $withScores = false)
* @method $this zdiffstore(string $destination, array $keys)
* @method $this zincrby($key, $increment, $member)
* @method $this zinterstore($destination, array|string $keys, array $options = null)
* @method $this zintercard(array $keys, int $limit = 0)
* @method $this zinterstore(string $destination, array $keys, int[] $weights = [], string $aggregate = 'sum')
* @method $this zinter(array $keys, int[] $weights = [], string $aggregate = 'sum', bool $withScores = false)
* @method $this zmpop(array $keys, string $modifier = 'min', int $count = 1)
* @method $this zmscore(string $key, string ...$member)
* @method $this zrandmember(string $key, int $count = 1, bool $withScores = false)
* @method $this zrange($key, $start, $stop, array $options = null)
* @method $this zrangebyscore($key, $min, $max, array $options = null)
* @method $this zrangestore(string $destination, string $source, int|string $min, string|int $max, string|bool $by = false, bool $reversed = false, bool $limit = false, int $offset = 0, int $count = 0)
* @method $this zrank($key, $member)
* @method $this zrem($key, $member)
* @method $this zremrangebyrank($key, $start, $stop)
@@ -120,13 +152,15 @@ use Predis\Command\CommandInterface;
* @method $this zrevrange($key, $start, $stop, array $options = null)
* @method $this zrevrangebyscore($key, $max, $min, array $options = null)
* @method $this zrevrank($key, $member)
* @method $this zunionstore($destination, array|string $keys, array $options = null)
* @method $this zunion(array $keys, int[] $weights = [], string $aggregate = 'sum', bool $withScores = false)
* @method $this zunionstore(string $destination, array $keys, int[] $weights = [], string $aggregate = 'sum')
* @method $this zscore($key, $member)
* @method $this zscan($key, $cursor, array $options = null)
* @method $this zrangebylex($key, $start, $stop, array $options = null)
* @method $this zrevrangebylex($key, $start, $stop, array $options = null)
* @method $this zremrangebylex($key, $min, $max)
* @method $this zlexcount($key, $min, $max)
* @method $this pexpiretime(string $key)
* @method $this pfadd($key, array $elements)
* @method $this pfmerge($destinationKey, array|string $sourceKeys)
* @method $this pfcount(array|string $keys)
@@ -138,7 +172,9 @@ use Predis\Command\CommandInterface;
* @method $this unwatch()
* @method $this watch($key)
* @method $this eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method $this eval_ro(string $script, array $keys, ...$argument)
* @method $this evalsha($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
* @method $this evalsha_ro(string $sha1, array $keys, ...$argument)
* @method $this script($subcommand, $argument = null)
* @method $this auth($password)
* @method $this echo($message)
@@ -164,8 +200,11 @@ use Predis\Command\CommandInterface;
* @method $this geodist($key, $member1, $member2, $unit = null)
* @method $this georadius($key, $longitude, $latitude, $radius, $unit, array $options = null)
* @method $this georadiusbymember($key, $member, $radius, $unit, array $options = null)
* @method $this geosearch(string $key, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $withCoord = false, bool $withDist = false, bool $withHash = false)
* @method $this geosearchstore(string $destination, string $source, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $storeDist = false)
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* Container commands
* @property FunctionContainer $function
*/
interface ClientContextInterface
{
+2 -3
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -13,8 +14,6 @@ namespace Predis;
/**
* Exception class that identifies client-side errors.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ClientException extends PredisException
{
+54 -9
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -11,8 +12,13 @@
namespace Predis;
use Predis\Command\Argument\Geospatial\ByInterface;
use Predis\Command\Argument\Geospatial\FromInterface;
use Predis\Command\Argument\Server\LimitOffsetCount;
use Predis\Command\Argument\Server\To;
use Predis\Command\CommandInterface;
use Predis\Command\FactoryInterface;
use Predis\Command\Redis\Container\FunctionContainer;
use Predis\Configuration\OptionsInterface;
use Predis\Connection\ConnectionInterface;
use Predis\Response\Status;
@@ -25,11 +31,13 @@ use Predis\Response\Status;
* and more friendly interface to ease programming which is described in the
* following list of methods:
*
* @method int copy(string $source, string $destination, int $db = -1, bool $replace = false)
* @method int del(string[]|string $keyOrKeys, string ...$keys = null)
* @method string|null dump(string $key)
* @method int exists(string $key)
* @method int expire(string $key, int $seconds)
* @method int expireat(string $key, int $timestamp)
* @method int expire(string $key, int $seconds, string $expireOption = '')
* @method int expireat(string $key, int $timestamp, string $expireOption = '')
* @method int expiretime(string $key)
* @method array keys(string $pattern)
* @method int move(string $key, int $db)
* @method mixed object($subcommand, string $key)
@@ -42,18 +50,27 @@ use Predis\Response\Status;
* @method int renamenx(string $key, string $target)
* @method array scan($cursor, array $options = null)
* @method array sort(string $key, array $options = null)
* @method array sort_ro(string $key, ?string $byPattern = null, ?LimitOffsetCount $limit = null, array $getPatterns = [], ?string $sorting = null, bool $alpha = false)
* @method int ttl(string $key)
* @method mixed type(string $key)
* @method int append(string $key, $value)
* @method int bitcount(string $key, $start = null, $end = null)
* @method int bitcount(string $key, $start = null, $end = null, string $index = 'byte')
* @method int bitop($operation, $destkey, $key)
* @method array|null bitfield(string $key, $subcommand, ...$subcommandArg)
* @method int bitpos(string $key, $bit, $start = null, $end = null)
* @method int bitpos(string $key, $bit, $start = null, $end = null, string $index = 'byte')
* @method array blmpop(int $timeout, array $keys, string $modifier = 'left', int $count = 1)
* @method array bzpopmax(array $keys, int $timeout)
* @method array bzpopmin(array $keys, int $timeout)
* @method array bzmpop(int $timeout, array $keys, string $modifier = 'min', int $count = 1)
* @method int decr(string $key)
* @method int decrby(string $key, int $decrement)
* @method Status failover(?To $to = null, bool $abort = false, int $timeout = -1)
* @method mixed fcall(string $function, array $keys, ...$args)
* @method string|null get(string $key)
* @method int getbit(string $key, $offset)
* @method int|null getex(string $key, $modifier = '', $value = false)
* @method string getrange(string $key, $start, $end)
* @method string getdel(string $key)
* @method string|null getset(string $key, $value)
* @method int incr(string $key)
* @method int incrby(string $key, int $increment)
@@ -78,17 +95,22 @@ use Predis\Response\Status;
* @method int hlen(string $key)
* @method array hmget(string $key, array $fields)
* @method mixed hmset(string $key, array $dictionary)
* @method array hrandfield(string $key, int $count = 1, bool $withValues = false)
* @method array hscan(string $key, $cursor, array $options = null)
* @method int hset(string $key, string $field, string $value)
* @method int hsetnx(string $key, string $field, string $value)
* @method array hvals(string $key)
* @method int hstrlen(string $key, string $field)
* @method string blmove(string $source, string $destination, string $where, string $to, int $timeout)
* @method array|null blpop(array|string $keys, int|float $timeout)
* @method array|null brpop(array|string $keys, int|float $timeout)
* @method string|null brpoplpush(string $source, string $destination, int|float $timeout)
* @method mixed lcs(string $key1, string $key2, bool $len = false, bool $idx = false, int $minMatchLen = 0, bool $withMatchLen = false)
* @method string|null lindex(string $key, int $index)
* @method int linsert(string $key, $whence, $pivot, $value)
* @method int llen(string $key)
* @method string lmove(string $source, string $destination, string $where, string $to)
* @method array|null lmpop(array $keys, string $modifier = 'left', int $count = 1)
* @method string|null lpop(string $key)
* @method int lpush(string $key, array $values)
* @method int lpushx(string $key, array $values)
@@ -105,9 +127,11 @@ use Predis\Response\Status;
* @method string[] sdiff(array|string $keys)
* @method int sdiffstore(string $destination, array|string $keys)
* @method string[] sinter(array|string $keys)
* @method int sintercard(array $keys, int $limit = 0)
* @method int sinterstore(string $destination, array|string $keys)
* @method int sismember(string $key, string $member)
* @method string[] smembers(string $key)
* @method array smismember(string $key, string ...$members)
* @method int smove(string $source, string $destination, string $member)
* @method string|array|null spop(string $key, int $count = null)
* @method string|null srandmember(string $key, int $count = null)
@@ -116,15 +140,29 @@ use Predis\Response\Status;
* @method string[] sunion(array|string $keys)
* @method int sunionstore(string $destination, array|string $keys)
* @method int touch(string[]|string $keyOrKeys, string ...$keys = null)
* @method string xadd(string $key, array $dictionary, string $id = '*', array $options = null)
* @method int xdel(string $key, string ...$id)
* @method int xlen(string $key)
* @method array xrevrange(string $key, string $end, string $start, ?int $count = null)
* @method array xrange(string $key, string $start, string $end, ?int $count = null)
* @method string xtrim(string $key, array|string $strategy, string $threshold, array $options = null)
* @method int zadd(string $key, array $membersAndScoresDictionary)
* @method int zcard(string $key)
* @method string zcount(string $key, int|string $min, int|string $max)
* @method array zdiff(array $keys, bool $withScores = false)
* @method int zdiffstore(string $destination, array $keys)
* @method string zincrby(string $key, int $increment, string $member)
* @method int zinterstore(string $destination, array|string $keys, array $options = null)
* @method int zintercard(array $keys, int $limit = 0)
* @method int zinterstore(string $destination, array $keys, int[] $weights = [], string $aggregate = 'sum')
* @method array zinter(array $keys, int[] $weights = [], string $aggregate = 'sum', bool $withScores = false)
* @method array zmpop(array $keys, string $modifier = 'min', int $count = 1)
* @method array zmscore(string $key, string ...$member)
* @method array zpopmin(string $key, int $count = 1)
* @method array zpopmax(string $key, int $count = 1)
* @method mixed zrandmember(string $key, int $count = 1, bool $withScores = false)
* @method array zrange(string $key, int|string $start, int|string $stop, array $options = null)
* @method array zrangebyscore(string $key, int|string $min, int|string $max, array $options = null)
* @method int zrangestore(string $destination, string $source, int|string $min, int|string $max, string|bool $by = false, bool $reversed = false, bool $limit = false, int $offset = 0, int $count = 0)
* @method int|null zrank(string $key, string $member)
* @method int zrem(string $key, string ...$member)
* @method int zremrangebyrank(string $key, int|string $start, int|string $stop)
@@ -132,13 +170,15 @@ use Predis\Response\Status;
* @method array zrevrange(string $key, int|string $start, int|string $stop, array $options = null)
* @method array zrevrangebyscore(string $key, int|string $max, int|string $min, array $options = null)
* @method int|null zrevrank(string $key, string $member)
* @method int zunionstore(string $destination, array|string $keys, array $options = null)
* @method array zunion(array $keys, int[] $weights = [], string $aggregate = 'sum', bool $withScores = false)
* @method int zunionstore(string $destination, array $keys, int[] $weights = [], string $aggregate = 'sum')
* @method string|null zscore(string $key, string $member)
* @method array zscan(string $key, int $cursor, array $options = null)
* @method array zrangebylex(string $key, string $start, string $stop, array $options = null)
* @method array zrevrangebylex(string $key, string $start, string $stop, array $options = null)
* @method int zremrangebylex(string $key, string $min, string $max)
* @method int zlexcount(string $key, string $min, string $max)
* @method int pexpiretime(string $key)
* @method int pfadd(string $key, array $elements)
* @method mixed pfmerge(string $destinationKey, array|string $sourceKeys)
* @method int pfcount(string[]|string $keyOrKeys, string ...$keys = null)
@@ -150,7 +190,9 @@ use Predis\Response\Status;
* @method mixed unwatch()
* @method mixed watch(string $key)
* @method mixed eval(string $script, int $numkeys, string ...$keyOrArg = null)
* @method mixed eval_ro(string $script, array $keys, ...$argument)
* @method mixed evalsha(string $script, int $numkeys, string ...$keyOrArg = null)
* @method mixed evalsha_ro(string $sha1, array $keys, ...$argument)
* @method mixed script($subcommand, $argument = null)
* @method mixed auth(string $password)
* @method string echo(string $message)
@@ -176,8 +218,11 @@ use Predis\Response\Status;
* @method string|null geodist(string $key, $member1, $member2, $unit = null)
* @method array georadius(string $key, $longitude, $latitude, $radius, $unit, array $options = null)
* @method array georadiusbymember(string $key, $member, $radius, $unit, array $options = null)
* @method array geosearch(string $key, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $withCoord = false, bool $withDist = false, bool $withHash = false)
* @method int geosearchstore(string $destination, string $source, FromInterface $from, ByInterface $by, ?string $sorting = null, int $count = -1, bool $any = false, bool $storeDist = false)
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* Container commands
* @property FunctionContainer $function
*/
interface ClientInterface
{
@@ -220,7 +265,7 @@ interface ClientInterface
*
* @return CommandInterface
*/
public function createCommand($method, $arguments = array());
public function createCommand($method, $arguments = []);
/**
* Executes the specified Redis command.
+59 -52
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -11,21 +12,17 @@
namespace Predis\Cluster;
use InvalidArgumentException;
use Predis\Command\CommandInterface;
use Predis\Command\ScriptCommand;
/**
* Common class implementing the logic needed to support clustering strategies.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
abstract class ClusterStrategy implements StrategyInterface
{
protected $commands;
/**
*
*/
public function __construct()
{
$this->commands = $this->getDefaultCommands();
@@ -38,10 +35,10 @@ abstract class ClusterStrategy implements StrategyInterface
*/
protected function getDefaultCommands()
{
$getKeyFromFirstArgument = array($this, 'getKeyFromFirstArgument');
$getKeyFromAllArguments = array($this, 'getKeyFromAllArguments');
$getKeyFromFirstArgument = [$this, 'getKeyFromFirstArgument'];
$getKeyFromAllArguments = [$this, 'getKeyFromAllArguments'];
return array(
return [
/* commands operating on the key space */
'EXISTS' => $getKeyFromAllArguments,
'DEL' => $getKeyFromAllArguments,
@@ -53,7 +50,7 @@ abstract class ClusterStrategy implements StrategyInterface
'PEXPIREAT' => $getKeyFromFirstArgument,
'TTL' => $getKeyFromFirstArgument,
'PTTL' => $getKeyFromFirstArgument,
'SORT' => array($this, 'getKeyFromSortCommand'),
'SORT' => [$this, 'getKeyFromSortCommand'],
'DUMP' => $getKeyFromFirstArgument,
'RESTORE' => $getKeyFromFirstArgument,
@@ -72,13 +69,13 @@ abstract class ClusterStrategy implements StrategyInterface
'INCRBYFLOAT' => $getKeyFromFirstArgument,
'SETBIT' => $getKeyFromFirstArgument,
'SETEX' => $getKeyFromFirstArgument,
'MSET' => array($this, 'getKeyFromInterleavedArguments'),
'MSETNX' => array($this, 'getKeyFromInterleavedArguments'),
'MSET' => [$this, 'getKeyFromInterleavedArguments'],
'MSETNX' => [$this, 'getKeyFromInterleavedArguments'],
'SETNX' => $getKeyFromFirstArgument,
'SETRANGE' => $getKeyFromFirstArgument,
'STRLEN' => $getKeyFromFirstArgument,
'SUBSTR' => $getKeyFromFirstArgument,
'BITOP' => array($this, 'getKeyFromBitOp'),
'BITOP' => [$this, 'getKeyFromBitOp'],
'BITCOUNT' => $getKeyFromFirstArgument,
'BITFIELD' => $getKeyFromFirstArgument,
@@ -89,9 +86,9 @@ abstract class ClusterStrategy implements StrategyInterface
'LPOP' => $getKeyFromFirstArgument,
'RPOP' => $getKeyFromFirstArgument,
'RPOPLPUSH' => $getKeyFromAllArguments,
'BLPOP' => array($this, 'getKeyFromBlockingListCommands'),
'BRPOP' => array($this, 'getKeyFromBlockingListCommands'),
'BRPOPLPUSH' => array($this, 'getKeyFromBlockingListCommands'),
'BLPOP' => [$this, 'getKeyFromBlockingListCommands'],
'BRPOP' => [$this, 'getKeyFromBlockingListCommands'],
'BRPOPLPUSH' => [$this, 'getKeyFromBlockingListCommands'],
'LPUSH' => $getKeyFromFirstArgument,
'LPUSHX' => $getKeyFromFirstArgument,
'RPUSH' => $getKeyFromFirstArgument,
@@ -122,7 +119,7 @@ abstract class ClusterStrategy implements StrategyInterface
'ZCARD' => $getKeyFromFirstArgument,
'ZCOUNT' => $getKeyFromFirstArgument,
'ZINCRBY' => $getKeyFromFirstArgument,
'ZINTERSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
'ZINTERSTORE' => [$this, 'getKeyFromZsetAggregationCommands'],
'ZRANGE' => $getKeyFromFirstArgument,
'ZRANGEBYSCORE' => $getKeyFromFirstArgument,
'ZRANK' => $getKeyFromFirstArgument,
@@ -133,7 +130,7 @@ abstract class ClusterStrategy implements StrategyInterface
'ZREVRANGEBYSCORE' => $getKeyFromFirstArgument,
'ZREVRANK' => $getKeyFromFirstArgument,
'ZSCORE' => $getKeyFromFirstArgument,
'ZUNIONSTORE' => array($this, 'getKeyFromZsetAggregationCommands'),
'ZUNIONSTORE' => [$this, 'getKeyFromZsetAggregationCommands'],
'ZSCAN' => $getKeyFromFirstArgument,
'ZLEXCOUNT' => $getKeyFromFirstArgument,
'ZRANGEBYLEX' => $getKeyFromFirstArgument,
@@ -163,17 +160,17 @@ abstract class ClusterStrategy implements StrategyInterface
'PFMERGE' => $getKeyFromAllArguments,
/* scripting */
'EVAL' => array($this, 'getKeyFromScriptingCommands'),
'EVALSHA' => array($this, 'getKeyFromScriptingCommands'),
'EVAL' => [$this, 'getKeyFromScriptingCommands'],
'EVALSHA' => [$this, 'getKeyFromScriptingCommands'],
/* commands performing geospatial operations */
'GEOADD' => $getKeyFromFirstArgument,
'GEOHASH' => $getKeyFromFirstArgument,
'GEOPOS' => $getKeyFromFirstArgument,
'GEODIST' => $getKeyFromFirstArgument,
'GEORADIUS' => array($this, 'getKeyFromGeoradiusCommands'),
'GEORADIUSBYMEMBER' => array($this, 'getKeyFromGeoradiusCommands'),
);
'GEORADIUS' => [$this, 'getKeyFromGeoradiusCommands'],
'GEORADIUSBYMEMBER' => [$this, 'getKeyFromGeoradiusCommands'],
];
}
/**
@@ -198,7 +195,7 @@ abstract class ClusterStrategy implements StrategyInterface
* @param string $commandID Command ID.
* @param mixed $callback A valid callable object, or NULL to unset the handler.
*
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
*/
public function setCommandHandler($commandID, $callback = null)
{
@@ -211,7 +208,7 @@ abstract class ClusterStrategy implements StrategyInterface
}
if (!is_callable($callback)) {
throw new \InvalidArgumentException(
throw new InvalidArgumentException(
'The argument must be a callable object or NULL.'
);
}
@@ -243,9 +240,11 @@ abstract class ClusterStrategy implements StrategyInterface
{
$arguments = $command->getArguments();
if ($this->checkSameSlotForKeys($arguments)) {
return $arguments[0];
if (!$this->checkSameSlotForKeys($arguments)) {
return null;
}
return $arguments[0];
}
/**
@@ -259,15 +258,17 @@ abstract class ClusterStrategy implements StrategyInterface
protected function getKeyFromInterleavedArguments(CommandInterface $command)
{
$arguments = $command->getArguments();
$keys = array();
$keys = [];
for ($i = 0; $i < count($arguments); $i += 2) {
$keys[] = $arguments[$i];
}
if ($this->checkSameSlotForKeys($keys)) {
return $arguments[0];
if (!$this->checkSameSlotForKeys($keys)) {
return null;
}
return $arguments[0];
}
/**
@@ -286,7 +287,7 @@ abstract class ClusterStrategy implements StrategyInterface
return $firstKey;
}
$keys = array($firstKey);
$keys = [$firstKey];
for ($i = 1; $i < $argc; ++$i) {
if (strtoupper($arguments[$i]) === 'STORE') {
@@ -294,9 +295,11 @@ abstract class ClusterStrategy implements StrategyInterface
}
}
if ($this->checkSameSlotForKeys($keys)) {
return $firstKey;
if (!$this->checkSameSlotForKeys($keys)) {
return null;
}
return $firstKey;
}
/**
@@ -310,9 +313,11 @@ abstract class ClusterStrategy implements StrategyInterface
{
$arguments = $command->getArguments();
if ($this->checkSameSlotForKeys(array_slice($arguments, 0, count($arguments) - 1))) {
return $arguments[0];
if (!$this->checkSameSlotForKeys(array_slice($arguments, 0, count($arguments) - 1))) {
return null;
}
return $arguments[0];
}
/**
@@ -326,9 +331,11 @@ abstract class ClusterStrategy implements StrategyInterface
{
$arguments = $command->getArguments();
if ($this->checkSameSlotForKeys(array_slice($arguments, 1, count($arguments)))) {
return $arguments[1];
if (!$this->checkSameSlotForKeys(array_slice($arguments, 1, count($arguments)))) {
return null;
}
return $arguments[1];
}
/**
@@ -345,7 +352,7 @@ abstract class ClusterStrategy implements StrategyInterface
$startIndex = $command->getId() === 'GEORADIUS' ? 5 : 4;
if ($argc > $startIndex) {
$keys = array($arguments[0]);
$keys = [$arguments[0]];
for ($i = $startIndex; $i < $argc; ++$i) {
$argument = strtoupper($arguments[$i]);
@@ -354,10 +361,8 @@ abstract class ClusterStrategy implements StrategyInterface
}
}
if ($this->checkSameSlotForKeys($keys)) {
return $arguments[0];
} else {
return;
if (!$this->checkSameSlotForKeys($keys)) {
return null;
}
}
@@ -374,11 +379,13 @@ abstract class ClusterStrategy implements StrategyInterface
protected function getKeyFromZsetAggregationCommands(CommandInterface $command)
{
$arguments = $command->getArguments();
$keys = array_merge(array($arguments[0]), array_slice($arguments, 2, $arguments[1]));
$keys = array_merge([$arguments[0]], array_slice($arguments, 2, $arguments[1]));
if ($this->checkSameSlotForKeys($keys)) {
return $arguments[0];
if (!$this->checkSameSlotForKeys($keys)) {
return null;
}
return $arguments[0];
}
/**
@@ -390,15 +397,15 @@ abstract class ClusterStrategy implements StrategyInterface
*/
protected function getKeyFromScriptingCommands(CommandInterface $command)
{
if ($command instanceof ScriptCommand) {
$keys = $command->getKeys();
} else {
$keys = array_slice($args = $command->getArguments(), 2, $args[1]);
$keys = $command instanceof ScriptCommand
? $command->getKeys()
: array_slice($args = $command->getArguments(), 2, $args[1]);
if (!$keys || !$this->checkSameSlotForKeys($keys)) {
return null;
}
if ($keys && $this->checkSameSlotForKeys($keys)) {
return $keys[0];
}
return $keys[0];
}
/**
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -16,8 +17,6 @@ use Predis\Cluster\Hash\HashGeneratorInterface;
/**
* A distributor implements the logic to automatically distribute keys among
* several nodes for client-side sharding.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface DistributorInterface
{
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -11,11 +12,11 @@
namespace Predis\Cluster\Distributor;
use Exception;
/**
* Exception class that identifies empty rings.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class EmptyRingException extends \Exception
class EmptyRingException extends Exception
{
}
+8 -9
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -17,21 +18,19 @@ use Predis\Cluster\Hash\HashGeneratorInterface;
* This class implements an hashring-based distributor that uses the same
* algorithm of memcache to distribute keys in a cluster using client-side
* sharding.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @author Lorenzo Castelli <lcastelli@gmail.com>
*/
class HashRing implements DistributorInterface, HashGeneratorInterface
{
const DEFAULT_REPLICAS = 128;
const DEFAULT_WEIGHT = 100;
public const DEFAULT_REPLICAS = 128;
public const DEFAULT_WEIGHT = 100;
private $ring;
private $ringKeys;
private $ringKeysCount;
private $replicas;
private $nodeHashCallback;
private $nodes = array();
private $nodes = [];
/**
* @param int $replicas Number of replicas in the ring.
@@ -53,10 +52,10 @@ class HashRing implements DistributorInterface, HashGeneratorInterface
{
// In case of collisions in the hashes of the nodes, the node added
// last wins, thus the order in which nodes are added is significant.
$this->nodes[] = array(
$this->nodes[] = [
'object' => $node,
'weight' => (int) $weight ?: $this::DEFAULT_WEIGHT,
);
];
$this->reset();
}
@@ -131,7 +130,7 @@ class HashRing implements DistributorInterface, HashGeneratorInterface
throw new EmptyRingException('Cannot initialize an empty hashring.');
}
$this->ring = array();
$this->ring = [];
$totalWeight = $this->computeTotalWeight();
$nodesCount = count($this->nodes);
+3 -4
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -15,13 +16,11 @@ namespace Predis\Cluster\Distributor;
* This class implements an hashring-based distributor that uses the same
* algorithm of libketama to distribute keys in a cluster using client-side
* sharding.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @author Lorenzo Castelli <lcastelli@gmail.com>
*/
class KetamaRing extends HashRing
{
const DEFAULT_REPLICAS = 160;
public const DEFAULT_REPLICAS = 160;
/**
* @param mixed $nodeHashCallback Callback returning a string used to calculate the hash of nodes.
+4 -5
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -13,12 +14,10 @@ namespace Predis\Cluster\Hash;
/**
* Hash generator implementing the CRC-CCITT-16 algorithm used by redis-cluster.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class CRC16 implements HashGeneratorInterface
{
private static $CCITT_16 = array(
private static $CCITT_16 = [
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
@@ -51,7 +50,7 @@ class CRC16 implements HashGeneratorInterface
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0,
);
];
/**
* {@inheritdoc}
+2 -3
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -14,8 +15,6 @@ namespace Predis\Cluster\Hash;
/**
* An hash generator implements the logic used to calculate the hash of a key to
* distribute operations among Redis nodes.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface HashGeneratorInterface
{
+3 -5
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -16,13 +17,10 @@ use Predis\NotSupportedException;
/**
* Hash generator implementing the CRC-CCITT-16 algorithm used by redis-cluster.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @deprecated 2.1.2
*/
class PhpiredisCRC16 implements HashGeneratorInterface
{
/**
*
*/
public function __construct()
{
if (!function_exists('phpiredis_utils_crc16')) {
+2 -3
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -16,8 +17,6 @@ use Predis\Cluster\Distributor\HashRing;
/**
* Default cluster strategy used by Predis to handle client-side sharding.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class PredisStrategy extends ClusterStrategy
{
+2 -3
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -18,8 +19,6 @@ use Predis\NotSupportedException;
/**
* Default class used by Predis to calculate hashes out of keys of
* commands supported by redis-cluster.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class RedisStrategy extends ClusterStrategy
{
+30 -23
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -11,17 +12,25 @@
namespace Predis\Cluster;
use ArrayAccess;
use ArrayIterator;
use Countable;
use IteratorAggregate;
use OutOfBoundsException;
use Predis\Connection\NodeConnectionInterface;
use ReturnTypeWillChange;
/**
* Slot map for redis-cluster.
*/
class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
class SlotMap implements ArrayAccess, IteratorAggregate, Countable
{
private $slots = array();
private $slots = [];
/**
* Checks if the given slot is valid.
*
* @param int $first Slot index.
* @param int $slot Slot index.
*
* @return bool
*/
@@ -48,7 +57,7 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
*/
public function reset()
{
$this->slots = array();
$this->slots = [];
}
/**
@@ -90,12 +99,12 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
* @param int $last Last slot of the range.
* @param NodeConnectionInterface|string $connection ID or connection instance.
*
* @throws \OutOfBoundsException
* @throws OutOfBoundsException
*/
public function setSlots($first, $last, $connection)
{
if (!static::isValidRange($first, $last)) {
throw new \OutOfBoundsException("Invalid slot range $first-$last for `$connection`");
throw new OutOfBoundsException("Invalid slot range $first-$last for `$connection`");
}
$this->slots += array_fill($first, $last - $first + 1, (string) $connection);
@@ -112,7 +121,7 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
public function getSlots($first, $last)
{
if (!static::isValidRange($first, $last)) {
throw new \OutOfBoundsException("Invalid slot range $first-$last");
throw new OutOfBoundsException("Invalid slot range $first-$last");
}
return array_intersect_key($this->slots, array_fill($first, $last - $first + 1, null));
@@ -125,7 +134,7 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
*
* @return bool
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function offsetExists($slot)
{
return isset($this->slots[$slot]);
@@ -136,14 +145,12 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
*
* @param int $slot Slot index.
*
* @return string
* @return string|null
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function offsetGet($slot)
{
if (isset($this->slots[$slot])) {
return $this->slots[$slot];
}
return $this->slots[$slot] ?? null;
}
/**
@@ -152,13 +159,13 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
* @param int $slot Slot index.
* @param NodeConnectionInterface|string $connection ID or connection instance.
*
* @return string
* @return void
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function offsetSet($slot, $connection)
{
if (!static::isValid($slot)) {
throw new \OutOfBoundsException("Invalid slot $slot for `$connection`");
throw new OutOfBoundsException("Invalid slot $slot for `$connection`");
}
$this->slots[(int) $slot] = (string) $connection;
@@ -169,9 +176,9 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
*
* @param int $slot Slot index.
*
* @return string
* @return void
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function offsetUnset($slot)
{
unset($this->slots[$slot]);
@@ -182,7 +189,7 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
*
* @return int
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function count()
{
return count($this->slots);
@@ -191,11 +198,11 @@ class SlotMap implements \ArrayAccess, \IteratorAggregate, \Countable
/**
* Returns an iterator over the slot map.
*
* @return \ArrayIterator
* @return ArrayIterator
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function getIterator()
{
return new \ArrayIterator($this->slots);
return new ArrayIterator($this->slots);
}
}
+4 -5
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -19,8 +20,6 @@ use Predis\Command\CommandInterface;
* keys extracted from supported commands.
*
* This is mostly useful to support clustering via client-side sharding.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface StrategyInterface
{
@@ -30,7 +29,7 @@ interface StrategyInterface
*
* @param CommandInterface $command Command instance.
*
* @return int
* @return int|null
*/
public function getSlot(CommandInterface $command);
@@ -40,7 +39,7 @@ interface StrategyInterface
*
* @param string $key Key string.
*
* @return int
* @return int|null
*/
public function getSlotByKey($key);
+14 -14
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -11,8 +12,10 @@
namespace Predis\Collection\Iterator;
use Iterator;
use Predis\ClientInterface;
use Predis\NotSupportedException;
use ReturnTypeWillChange;
/**
* Provides the base implementation for a fully-rewindable PHP iterator that can
@@ -24,10 +27,8 @@ use Predis\NotSupportedException;
* can change several times during the iteration process.
*
* @see http://redis.io/commands/scan
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
abstract class CursorBasedIterator implements \Iterator
abstract class CursorBasedIterator implements Iterator
{
protected $client;
protected $match;
@@ -77,7 +78,7 @@ abstract class CursorBasedIterator implements \Iterator
{
$this->valid = true;
$this->fetchmore = true;
$this->elements = array();
$this->elements = [];
$this->cursor = 0;
$this->position = -1;
$this->current = null;
@@ -90,7 +91,7 @@ abstract class CursorBasedIterator implements \Iterator
*/
protected function getScanOptions()
{
$options = array();
$options = [];
if (strlen(strval($this->match)) > 0) {
$options['MATCH'] = $this->match;
@@ -117,7 +118,7 @@ abstract class CursorBasedIterator implements \Iterator
*/
protected function fetch()
{
list($cursor, $elements) = $this->executeCommand();
[$cursor, $elements] = $this->executeCommand();
if (!$cursor) {
$this->fetchmore = false;
@@ -139,7 +140,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function rewind()
{
$this->reset();
@@ -149,7 +150,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function current()
{
return $this->current;
@@ -158,7 +159,7 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function key()
{
return $this->position;
@@ -167,10 +168,10 @@ abstract class CursorBasedIterator implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function next()
{
tryFetch: {
tryFetch:
if (!$this->elements && $this->fetchmore) {
$this->fetch();
}
@@ -182,13 +183,12 @@ abstract class CursorBasedIterator implements \Iterator
} else {
$this->valid = false;
}
}
}
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function valid()
{
return $this->valid;
+3 -4
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -17,9 +18,7 @@ use Predis\ClientInterface;
* Abstracts the iteration of fields and values of an hash by leveraging the
* HSCAN command (Redis >= 2.8) wrapped in a fully-rewindable PHP iterator.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*
* @link http://redis.io/commands/scan
* @see http://redis.io/commands/scan
*/
class HashKey extends CursorBasedIterator
{
+3 -4
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -17,9 +18,7 @@ use Predis\ClientInterface;
* Abstracts the iteration of the keyspace on a Redis instance by leveraging the
* SCAN command (Redis >= 2.8) wrapped in a fully-rewindable PHP iterator.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*
* @link http://redis.io/commands/scan
* @see http://redis.io/commands/scan
*/
class Keyspace extends CursorBasedIterator
{
+15 -13
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -11,8 +12,11 @@
namespace Predis\Collection\Iterator;
use InvalidArgumentException;
use Iterator;
use Predis\ClientInterface;
use Predis\NotSupportedException;
use ReturnTypeWillChange;
/**
* Abstracts the iteration of items stored in a list by leveraging the LRANGE
@@ -24,11 +28,9 @@ use Predis\NotSupportedException;
* guarantees on the returned elements because the collection can change several
* times (trimmed, deleted, overwritten) during the iteration process.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*
* @link http://redis.io/commands/lrange
* @see http://redis.io/commands/lrange
*/
class ListKey implements \Iterator
class ListKey implements Iterator
{
protected $client;
protected $count;
@@ -45,14 +47,14 @@ class ListKey implements \Iterator
* @param string $key Redis list key.
* @param int $count Number of items retrieved on each fetch operation.
*
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
*/
public function __construct(ClientInterface $client, $key, $count = 10)
{
$this->requiredCommand($client, 'LRANGE');
if ((false === $count = filter_var($count, FILTER_VALIDATE_INT)) || $count < 0) {
throw new \InvalidArgumentException('The $count argument must be a positive integer.');
throw new InvalidArgumentException('The $count argument must be a positive integer.');
}
$this->client = $client;
@@ -85,7 +87,7 @@ class ListKey implements \Iterator
{
$this->valid = true;
$this->fetchmore = true;
$this->elements = array();
$this->elements = [];
$this->position = -1;
$this->current = null;
}
@@ -128,7 +130,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function rewind()
{
$this->reset();
@@ -138,7 +140,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function current()
{
return $this->current;
@@ -147,7 +149,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function key()
{
return $this->position;
@@ -156,7 +158,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function next()
{
if (!$this->elements && $this->fetchmore) {
@@ -173,7 +175,7 @@ class ListKey implements \Iterator
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function valid()
{
return $this->valid;
+3 -4
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -17,9 +18,7 @@ use Predis\ClientInterface;
* Abstracts the iteration of members stored in a set by leveraging the SSCAN
* command (Redis >= 2.8) wrapped in a fully-rewindable PHP iterator.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*
* @link http://redis.io/commands/scan
* @see http://redis.io/commands/scan
*/
class SetKey extends CursorBasedIterator
{
+3 -4
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -17,9 +18,7 @@ use Predis\ClientInterface;
* Abstracts the iteration of members stored in a sorted set by leveraging the
* ZSCAN command (Redis >= 2.8) wrapped in a fully-rewindable PHP iterator.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*
* @link http://redis.io/commands/scan
* @see http://redis.io/commands/scan
*/
class SortedSetKey extends CursorBasedIterator
{
@@ -0,0 +1,26 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Argument;
/**
* Allows to use object-oriented approach to handle complex conditional arguments.
*/
interface ArrayableArgument
{
/**
* Get the instance as an array.
*
* @return array
*/
public function toArray(): array;
}
@@ -0,0 +1,46 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Argument\Geospatial;
use UnexpectedValueException;
abstract class AbstractBy implements ByInterface
{
/**
* @var string[]
*/
private static $unitEnum = ['m', 'km', 'ft', 'mi'];
/**
* @var string
*/
protected $unit;
/**
* {@inheritDoc}
*/
abstract public function toArray(): array;
/**
* @param string $unit
* @return void
*/
protected function setUnit(string $unit): void
{
if (!in_array($unit, self::$unitEnum, true)) {
throw new UnexpectedValueException('Wrong value given for unit');
}
$this->unit = $unit;
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Argument\Geospatial;
class ByBox extends AbstractBy
{
private const KEYWORD = 'BYBOX';
/**
* @var int
*/
private $width;
/**
* @var int
*/
private $height;
public function __construct(int $width, int $height, string $unit)
{
$this->width = $width;
$this->height = $height;
$this->setUnit($unit);
}
/**
* {@inheritDoc}
*/
public function toArray(): array
{
return [self::KEYWORD, $this->width, $this->height, $this->unit];
}
}
@@ -0,0 +1,19 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Argument\Geospatial;
use Predis\Command\Argument\ArrayableArgument;
interface ByInterface extends ArrayableArgument
{
}
@@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Argument\Geospatial;
class ByRadius extends AbstractBy
{
private const KEYWORD = 'BYRADIUS';
/**
* @var int
*/
private $radius;
public function __construct(int $radius, string $unit)
{
$this->radius = $radius;
$this->setUnit($unit);
}
/**
* {@inheritDoc}
*/
public function toArray(): array
{
return [self::KEYWORD, $this->radius, $this->unit];
}
}
@@ -0,0 +1,19 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Argument\Geospatial;
use Predis\Command\Argument\ArrayableArgument;
interface FromInterface extends ArrayableArgument
{
}
@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Argument\Geospatial;
class FromLonLat implements FromInterface
{
private const KEYWORD = 'FROMLONLAT';
/**
* @var float
*/
private $longitude;
/**
* @var float
*/
private $latitude;
public function __construct(float $longitude, float $latitude)
{
$this->longitude = $longitude;
$this->latitude = $latitude;
}
/**
* {@inheritDoc}
*/
public function toArray(): array
{
return [self::KEYWORD, $this->longitude, $this->latitude];
}
}
@@ -0,0 +1,36 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Argument\Geospatial;
class FromMember implements FromInterface
{
private const KEYWORD = 'FROMMEMBER';
/**
* @var string
*/
private $member;
public function __construct(string $member)
{
$this->member = $member;
}
/**
* {@inheritDoc}
*/
public function toArray(): array
{
return [self::KEYWORD, $this->member];
}
}
@@ -0,0 +1,19 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Argument\Server;
use Predis\Command\Argument\ArrayableArgument;
interface LimitInterface extends ArrayableArgument
{
}
@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Argument\Server;
class LimitOffsetCount implements LimitInterface
{
private const KEYWORD = 'LIMIT';
/**
* @var int
*/
private $offset;
/**
* @var int
*/
private $count;
public function __construct(int $offset, int $count)
{
$this->offset = $offset;
$this->count = $count;
}
/**
* {@inheritDoc}
*/
public function toArray(): array
{
return [self::KEYWORD, $this->offset, $this->count];
}
}
+57
View File
@@ -0,0 +1,57 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Argument\Server;
use Predis\Command\Argument\ArrayableArgument;
class To implements ArrayableArgument
{
private const KEYWORD = 'TO';
private const FORCE_KEYWORD = 'FORCE';
/**
* @var string
*/
private $host;
/**
* @var int
*/
private $port;
/**
* @var bool
*/
private $isForce;
public function __construct(string $host, int $port, bool $isForce = false)
{
$this->host = $host;
$this->port = $port;
$this->isForce = $isForce;
}
/**
* {@inheritDoc}
*/
public function toArray(): array
{
$arguments = [self::KEYWORD, $this->host, $this->port];
if ($this->isForce) {
$arguments[] = self::FORCE_KEYWORD;
}
return $arguments;
}
}
+17 -8
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -13,13 +14,11 @@ namespace Predis\Command;
/**
* Base class for Redis commands.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
abstract class Command implements CommandInterface
{
private $slot;
private $arguments = array();
private $arguments = [];
/**
* {@inheritdoc}
@@ -70,9 +69,7 @@ abstract class Command implements CommandInterface
*/
public function getSlot()
{
if (isset($this->slot)) {
return $this->slot;
}
return $this->slot ?? null;
}
/**
@@ -109,9 +106,21 @@ abstract class Command implements CommandInterface
public static function normalizeVariadic(array $arguments)
{
if (count($arguments) === 2 && is_array($arguments[1])) {
return array_merge(array($arguments[0]), $arguments[1]);
return array_merge([$arguments[0]], $arguments[1]);
}
return $arguments;
}
/**
* Remove all false values from arguments.
*
* @return void
*/
public function filterArguments(): void
{
$this->arguments = array_filter($this->arguments, static function ($argument) {
return $argument !== false && $argument !== null;
});
}
}
+2 -3
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -13,8 +14,6 @@ namespace Predis\Command;
/**
* Defines an abstraction representing a Redis command.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface CommandInterface
{
+8 -10
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -11,6 +12,7 @@
namespace Predis\Command;
use InvalidArgumentException;
use Predis\ClientException;
use Predis\Command\Processor\ProcessorInterface;
@@ -20,8 +22,6 @@ use Predis\Command\Processor\ProcessorInterface;
* This class provides all of the common functionalities required for a command
* factory to create new instances of Redis commands objects. It also allows to
* define or undefine command handler classes for each command ID.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
abstract class Factory implements FactoryInterface
{
@@ -49,13 +49,11 @@ abstract class Factory implements FactoryInterface
*
* @param string $commandID Command ID
*
* @return ?string
* @return string|null
*/
public function getCommandClass(string $commandID): ?string
{
if (isset($this->commands[$commandID = strtoupper($commandID)])) {
return $this->commands[$commandID];
}
return $this->commands[strtoupper($commandID)] ?? null;
}
/**
@@ -89,12 +87,12 @@ abstract class Factory implements FactoryInterface
* @param string $commandID Command ID
* @param string $commandClass FQCN of a class implementing Predis\Command\CommandInterface
*
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
*/
public function define(string $commandID, string $commandClass): void
{
if (!is_a($commandClass, 'Predis\Command\CommandInterface', true)) {
throw new \InvalidArgumentException(
throw new InvalidArgumentException(
"Class $commandClass must implement Predis\Command\CommandInterface"
);
}
@@ -136,7 +134,7 @@ abstract class Factory implements FactoryInterface
/**
* Returns the current command processor.
*
* @return ?ProcessorInterface
* @return ProcessorInterface|null
*/
public function getProcessor(): ?ProcessorInterface
{
+4 -5
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -17,15 +18,13 @@ namespace Predis\Command;
* A command factory is used through the library to create instances of commands
* classes implementing Predis\Command\CommandInterface mapped to Redis commands
* by their command ID string (SET, GET, etc...).
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface FactoryInterface
{
/**
* Checks if the command factory supports the specified list of commands.
*
* @param array $commandIDs List of command IDs
* @param string ...$commandIDs List of command IDs
*
* @return bool
*/
@@ -39,5 +38,5 @@ interface FactoryInterface
*
* @return CommandInterface
*/
public function create(string $commandID, array $arguments = array()): CommandInterface;
public function create(string $commandID, array $arguments = []): CommandInterface;
}
+2 -3
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -13,8 +14,6 @@ namespace Predis\Command;
/**
* Defines a command whose keys can be prefixed.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface PrefixableCommandInterface extends CommandInterface
{
+155 -145
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -11,14 +12,13 @@
namespace Predis\Command\Processor;
use InvalidArgumentException;
use Predis\Command\CommandInterface;
use Predis\Command\PrefixableCommandInterface;
/**
* Command processor capable of prefixing keys stored in the arguments of Redis
* commands supported.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class KeyPrefixProcessor implements ProcessorInterface
{
@@ -31,142 +31,160 @@ class KeyPrefixProcessor implements ProcessorInterface
public function __construct($prefix)
{
$this->prefix = $prefix;
$this->commands = array(
$prefixFirst = static::class . '::first';
$prefixAll = static::class . '::all';
$prefixInterleaved = static::class . '::interleaved';
$prefixSkipFirst = static::class . '::skipFirst';
$prefixSkipLast = static::class . '::skipLast';
$prefixSort = static::class . '::sort';
$prefixEvalKeys = static::class . '::evalKeys';
$prefixZsetStore = static::class . '::zsetStore';
$prefixMigrate = static::class . '::migrate';
$prefixGeoradius = static::class . '::georadius';
$this->commands = [
/* ---------------- Redis 1.2 ---------------- */
'EXISTS' => 'static::all',
'DEL' => 'static::all',
'TYPE' => 'static::first',
'KEYS' => 'static::first',
'RENAME' => 'static::all',
'RENAMENX' => 'static::all',
'EXPIRE' => 'static::first',
'EXPIREAT' => 'static::first',
'TTL' => 'static::first',
'MOVE' => 'static::first',
'SORT' => 'static::sort',
'DUMP' => 'static::first',
'RESTORE' => 'static::first',
'SET' => 'static::first',
'SETNX' => 'static::first',
'MSET' => 'static::interleaved',
'MSETNX' => 'static::interleaved',
'GET' => 'static::first',
'MGET' => 'static::all',
'GETSET' => 'static::first',
'INCR' => 'static::first',
'INCRBY' => 'static::first',
'DECR' => 'static::first',
'DECRBY' => 'static::first',
'RPUSH' => 'static::first',
'LPUSH' => 'static::first',
'LLEN' => 'static::first',
'LRANGE' => 'static::first',
'LTRIM' => 'static::first',
'LINDEX' => 'static::first',
'LSET' => 'static::first',
'LREM' => 'static::first',
'LPOP' => 'static::first',
'RPOP' => 'static::first',
'RPOPLPUSH' => 'static::all',
'SADD' => 'static::first',
'SREM' => 'static::first',
'SPOP' => 'static::first',
'SMOVE' => 'static::skipLast',
'SCARD' => 'static::first',
'SISMEMBER' => 'static::first',
'SINTER' => 'static::all',
'SINTERSTORE' => 'static::all',
'SUNION' => 'static::all',
'SUNIONSTORE' => 'static::all',
'SDIFF' => 'static::all',
'SDIFFSTORE' => 'static::all',
'SMEMBERS' => 'static::first',
'SRANDMEMBER' => 'static::first',
'ZADD' => 'static::first',
'ZINCRBY' => 'static::first',
'ZREM' => 'static::first',
'ZRANGE' => 'static::first',
'ZREVRANGE' => 'static::first',
'ZRANGEBYSCORE' => 'static::first',
'ZCARD' => 'static::first',
'ZSCORE' => 'static::first',
'ZREMRANGEBYSCORE' => 'static::first',
'EXISTS' => $prefixAll,
'DEL' => $prefixAll,
'TYPE' => $prefixFirst,
'KEYS' => $prefixFirst,
'RENAME' => $prefixAll,
'RENAMENX' => $prefixAll,
'EXPIRE' => $prefixFirst,
'EXPIREAT' => $prefixFirst,
'TTL' => $prefixFirst,
'MOVE' => $prefixFirst,
'SORT' => $prefixSort,
'DUMP' => $prefixFirst,
'RESTORE' => $prefixFirst,
'SET' => $prefixFirst,
'SETNX' => $prefixFirst,
'MSET' => $prefixInterleaved,
'MSETNX' => $prefixInterleaved,
'GET' => $prefixFirst,
'MGET' => $prefixAll,
'GETSET' => $prefixFirst,
'INCR' => $prefixFirst,
'INCRBY' => $prefixFirst,
'DECR' => $prefixFirst,
'DECRBY' => $prefixFirst,
'RPUSH' => $prefixFirst,
'LPUSH' => $prefixFirst,
'LLEN' => $prefixFirst,
'LRANGE' => $prefixFirst,
'LTRIM' => $prefixFirst,
'LINDEX' => $prefixFirst,
'LSET' => $prefixFirst,
'LREM' => $prefixFirst,
'LPOP' => $prefixFirst,
'RPOP' => $prefixFirst,
'RPOPLPUSH' => $prefixAll,
'SADD' => $prefixFirst,
'SREM' => $prefixFirst,
'SPOP' => $prefixFirst,
'SMOVE' => $prefixSkipLast,
'SCARD' => $prefixFirst,
'SISMEMBER' => $prefixFirst,
'SINTER' => $prefixAll,
'SINTERSTORE' => $prefixAll,
'SUNION' => $prefixAll,
'SUNIONSTORE' => $prefixAll,
'SDIFF' => $prefixAll,
'SDIFFSTORE' => $prefixAll,
'SMEMBERS' => $prefixFirst,
'SRANDMEMBER' => $prefixFirst,
'ZADD' => $prefixFirst,
'ZINCRBY' => $prefixFirst,
'ZREM' => $prefixFirst,
'ZRANGE' => $prefixFirst,
'ZREVRANGE' => $prefixFirst,
'ZRANGEBYSCORE' => $prefixFirst,
'ZCARD' => $prefixFirst,
'ZSCORE' => $prefixFirst,
'ZREMRANGEBYSCORE' => $prefixFirst,
/* ---------------- Redis 2.0 ---------------- */
'SETEX' => 'static::first',
'APPEND' => 'static::first',
'SUBSTR' => 'static::first',
'BLPOP' => 'static::skipLast',
'BRPOP' => 'static::skipLast',
'ZUNIONSTORE' => 'static::zsetStore',
'ZINTERSTORE' => 'static::zsetStore',
'ZCOUNT' => 'static::first',
'ZRANK' => 'static::first',
'ZREVRANK' => 'static::first',
'ZREMRANGEBYRANK' => 'static::first',
'HSET' => 'static::first',
'HSETNX' => 'static::first',
'HMSET' => 'static::first',
'HINCRBY' => 'static::first',
'HGET' => 'static::first',
'HMGET' => 'static::first',
'HDEL' => 'static::first',
'HEXISTS' => 'static::first',
'HLEN' => 'static::first',
'HKEYS' => 'static::first',
'HVALS' => 'static::first',
'HGETALL' => 'static::first',
'SUBSCRIBE' => 'static::all',
'UNSUBSCRIBE' => 'static::all',
'PSUBSCRIBE' => 'static::all',
'PUNSUBSCRIBE' => 'static::all',
'PUBLISH' => 'static::first',
'SETEX' => $prefixFirst,
'APPEND' => $prefixFirst,
'SUBSTR' => $prefixFirst,
'BLPOP' => $prefixSkipLast,
'BRPOP' => $prefixSkipLast,
'ZUNIONSTORE' => $prefixZsetStore,
'ZINTERSTORE' => $prefixZsetStore,
'ZCOUNT' => $prefixFirst,
'ZRANK' => $prefixFirst,
'ZREVRANK' => $prefixFirst,
'ZREMRANGEBYRANK' => $prefixFirst,
'HSET' => $prefixFirst,
'HSETNX' => $prefixFirst,
'HMSET' => $prefixFirst,
'HINCRBY' => $prefixFirst,
'HGET' => $prefixFirst,
'HMGET' => $prefixFirst,
'HDEL' => $prefixFirst,
'HEXISTS' => $prefixFirst,
'HLEN' => $prefixFirst,
'HKEYS' => $prefixFirst,
'HVALS' => $prefixFirst,
'HGETALL' => $prefixFirst,
'SUBSCRIBE' => $prefixAll,
'UNSUBSCRIBE' => $prefixAll,
'PSUBSCRIBE' => $prefixAll,
'PUNSUBSCRIBE' => $prefixAll,
'PUBLISH' => $prefixFirst,
/* ---------------- Redis 2.2 ---------------- */
'PERSIST' => 'static::first',
'STRLEN' => 'static::first',
'SETRANGE' => 'static::first',
'GETRANGE' => 'static::first',
'SETBIT' => 'static::first',
'GETBIT' => 'static::first',
'RPUSHX' => 'static::first',
'LPUSHX' => 'static::first',
'LINSERT' => 'static::first',
'BRPOPLPUSH' => 'static::skipLast',
'ZREVRANGEBYSCORE' => 'static::first',
'WATCH' => 'static::all',
'PERSIST' => $prefixFirst,
'STRLEN' => $prefixFirst,
'SETRANGE' => $prefixFirst,
'GETRANGE' => $prefixFirst,
'SETBIT' => $prefixFirst,
'GETBIT' => $prefixFirst,
'RPUSHX' => $prefixFirst,
'LPUSHX' => $prefixFirst,
'LINSERT' => $prefixFirst,
'BRPOPLPUSH' => $prefixSkipLast,
'ZREVRANGEBYSCORE' => $prefixFirst,
'WATCH' => $prefixAll,
/* ---------------- Redis 2.6 ---------------- */
'PTTL' => 'static::first',
'PEXPIRE' => 'static::first',
'PEXPIREAT' => 'static::first',
'PSETEX' => 'static::first',
'INCRBYFLOAT' => 'static::first',
'BITOP' => 'static::skipFirst',
'BITCOUNT' => 'static::first',
'HINCRBYFLOAT' => 'static::first',
'EVAL' => 'static::evalKeys',
'EVALSHA' => 'static::evalKeys',
'MIGRATE' => 'static::migrate',
'PTTL' => $prefixFirst,
'PEXPIRE' => $prefixFirst,
'PEXPIREAT' => $prefixFirst,
'PSETEX' => $prefixFirst,
'INCRBYFLOAT' => $prefixFirst,
'BITOP' => $prefixSkipFirst,
'BITCOUNT' => $prefixFirst,
'HINCRBYFLOAT' => $prefixFirst,
'EVAL' => $prefixEvalKeys,
'EVALSHA' => $prefixEvalKeys,
'MIGRATE' => $prefixMigrate,
/* ---------------- Redis 2.8 ---------------- */
'SSCAN' => 'static::first',
'ZSCAN' => 'static::first',
'HSCAN' => 'static::first',
'PFADD' => 'static::first',
'PFCOUNT' => 'static::all',
'PFMERGE' => 'static::all',
'ZLEXCOUNT' => 'static::first',
'ZRANGEBYLEX' => 'static::first',
'ZREMRANGEBYLEX' => 'static::first',
'ZREVRANGEBYLEX' => 'static::first',
'BITPOS' => 'static::first',
'SSCAN' => $prefixFirst,
'ZSCAN' => $prefixFirst,
'HSCAN' => $prefixFirst,
'PFADD' => $prefixFirst,
'PFCOUNT' => $prefixAll,
'PFMERGE' => $prefixAll,
'ZLEXCOUNT' => $prefixFirst,
'ZRANGEBYLEX' => $prefixFirst,
'ZREMRANGEBYLEX' => $prefixFirst,
'ZREVRANGEBYLEX' => $prefixFirst,
'BITPOS' => $prefixFirst,
/* ---------------- Redis 3.2 ---------------- */
'HSTRLEN' => 'static::first',
'BITFIELD' => 'static::first',
'GEOADD' => 'static::first',
'GEOHASH' => 'static::first',
'GEOPOS' => 'static::first',
'GEODIST' => 'static::first',
'GEORADIUS' => 'static::georadius',
'GEORADIUSBYMEMBER' => 'static::georadius',
);
'HSTRLEN' => $prefixFirst,
'BITFIELD' => $prefixFirst,
'GEOADD' => $prefixFirst,
'GEOHASH' => $prefixFirst,
'GEOPOS' => $prefixFirst,
'GEODIST' => $prefixFirst,
'GEORADIUS' => $prefixGeoradius,
'GEORADIUSBYMEMBER' => $prefixGeoradius,
/* ---------------- Redis 5.0 ---------------- */
'XADD' => $prefixFirst,
'XRANGE' => $prefixFirst,
'XDEL' => $prefixFirst,
'XLEN' => $prefixFirst,
'XACK' => $prefixFirst,
];
}
/**
@@ -197,14 +215,7 @@ class KeyPrefixProcessor implements ProcessorInterface
if ($command instanceof PrefixableCommandInterface) {
$command->prefixKeys($this->prefix);
} elseif (isset($this->commands[$commandID = strtoupper($command->getId())])) {
$callable = $this->commands[$commandID];
if (is_string($callable) && strpos($callable, 'static::') === 0) {
$callable = explode('::', $this->commands[$commandID]);
$callable[0] = $this;
}
call_user_func($callable, $command, $this->prefix);
$this->commands[$commandID]($command, $this->prefix);
}
}
@@ -222,7 +233,7 @@ class KeyPrefixProcessor implements ProcessorInterface
* @param string $commandID The ID of the command to be handled.
* @param mixed $callback A valid callable object or NULL.
*
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
*/
public function setCommandHandler($commandID, $callback = null)
{
@@ -235,7 +246,7 @@ class KeyPrefixProcessor implements ProcessorInterface
}
if (!is_callable($callback)) {
throw new \InvalidArgumentException(
throw new InvalidArgumentException(
'Callback must be a valid callable object or NULL'
);
}
@@ -365,7 +376,7 @@ class KeyPrefixProcessor implements ProcessorInterface
}
break;
case 'LIMIT';
case 'LIMIT':
$i += 2;
break;
}
@@ -446,7 +457,6 @@ class KeyPrefixProcessor implements ProcessorInterface
case 'STOREDIST':
$arguments[$i] = "$prefix{$arguments[++$i]}";
break;
}
}
}
+17 -13
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -11,21 +12,24 @@
namespace Predis\Command\Processor;
use ArrayAccess;
use ArrayIterator;
use InvalidArgumentException;
use Predis\Command\CommandInterface;
use ReturnTypeWillChange;
use Traversable;
/**
* Default implementation of a command processors chain.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ProcessorChain implements \ArrayAccess, ProcessorInterface
class ProcessorChain implements ArrayAccess, ProcessorInterface
{
private $processors = array();
private $processors = [];
/**
* @param array $processors List of instances of ProcessorInterface.
*/
public function __construct($processors = array())
public function __construct($processors = [])
{
foreach ($processors as $processor) {
$this->add($processor);
@@ -71,11 +75,11 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* Returns an iterator over the list of command processor in the chain.
*
* @return \Traversable<int, ProcessorInterface>
* @return Traversable<int, ProcessorInterface>
*/
public function getIterator()
{
return new \ArrayIterator($this->processors);
return new ArrayIterator($this->processors);
}
/**
@@ -91,7 +95,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function offsetExists($index)
{
return isset($this->processors[$index]);
@@ -100,7 +104,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function offsetGet($index)
{
return $this->processors[$index];
@@ -109,11 +113,11 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function offsetSet($index, $processor)
{
if (!$processor instanceof ProcessorInterface) {
throw new \InvalidArgumentException(
throw new InvalidArgumentException(
'Processor chain accepts only instances of `Predis\Command\Processor\ProcessorInterface`'
);
}
@@ -124,7 +128,7 @@ class ProcessorChain implements \ArrayAccess, ProcessorInterface
/**
* {@inheritdoc}
*/
#[\ReturnTypeWillChange]
#[ReturnTypeWillChange]
public function offsetUnset($index)
{
unset($this->processors[$index]);
+2 -3
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -15,8 +16,6 @@ use Predis\Command\CommandInterface;
/**
* A command processor processes Redis commands before they are sent to Redis.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
interface ProcessorInterface
{
+6 -9
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -21,8 +22,6 @@ namespace Predis\Command;
* of Predis\Client or managing internals like Redis Sentinel or Cluster as they
* are not potentially subject to hijacking from third party libraries when they
* override command handlers for standard Redis commands.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
final class RawCommand implements CommandInterface
{
@@ -34,7 +33,7 @@ final class RawCommand implements CommandInterface
* @param string $commandID Command ID
* @param array $arguments Command arguments
*/
public function __construct($commandID, array $arguments = array())
public function __construct($commandID, array $arguments = [])
{
$this->commandID = strtoupper($commandID);
$this->setArguments($arguments);
@@ -44,11 +43,11 @@ final class RawCommand implements CommandInterface
* Creates a new raw command using a variadic method.
*
* @param string $commandID Redis command ID
* @param string ... Arguments list for the command
* @param string ...$args Arguments list for the command
*
* @return CommandInterface
*/
public static function create($commandID /* [ $arg, ... */)
public static function create($commandID, ...$args)
{
$arguments = func_get_args();
@@ -111,9 +110,7 @@ final class RawCommand implements CommandInterface
*/
public function getSlot()
{
if (isset($this->slot)) {
return $this->slot;
}
return $this->slot ?? null;
}
/**
+2 -3
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -21,8 +22,6 @@ namespace Predis\Command;
* When using this factory the client does not process arguments before sending
* commands to Redis and server responses are not further processed before being
* returned to the caller.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class RawFactory implements FactoryInterface
{
+3 -4
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -14,9 +15,7 @@ namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* @link http://redis.io/commands/append
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @see http://redis.io/commands/append
*/
class APPEND extends RedisCommand
{
+3 -4
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -14,9 +15,7 @@ namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* @link http://redis.io/commands/auth
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @see http://redis.io/commands/auth
*/
class AUTH extends RedisCommand
{
@@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis\AbstractCommand;
use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\Keys;
abstract class BZPOPBase extends RedisCommand
{
use Keys {
Keys::setArguments as setKeys;
}
protected static $keysArgumentPositionOffset = 0;
abstract public function getId(): string;
public function setArguments(array $arguments)
{
$this->setKeys($arguments, false);
}
public function parseResponse($data)
{
$key = array_shift($data);
if (null === $key) {
return [$key];
}
return array_combine([$key], [[$data[0] => $data[1]]]);
}
}
+3 -4
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -14,9 +15,7 @@ namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* @link http://redis.io/commands/bgrewriteaof
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @see http://redis.io/commands/bgrewriteaof
*/
class BGREWRITEAOF extends RedisCommand
{
+3 -4
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -14,9 +15,7 @@ namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* @link http://redis.io/commands/bgsave
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @see http://redis.io/commands/bgsave
*/
class BGSAVE extends RedisCommand
{
+7 -3
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -12,14 +13,17 @@
namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\BitByte;
/**
* @link http://redis.io/commands/bitcount
* @see http://redis.io/commands/bitcount
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* Count the number of set bits (population counting) in a string.
*/
class BITCOUNT extends RedisCommand
{
use BitByte;
/**
* {@inheritdoc}
*/
+3 -4
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -14,9 +15,7 @@ namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* @link http://redis.io/commands/bitfield
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @see http://redis.io/commands/bitfield
*/
class BITFIELD extends RedisCommand
{
+4 -5
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -14,9 +15,7 @@ namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* @link http://redis.io/commands/bitop
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @see http://redis.io/commands/bitop
*/
class BITOP extends RedisCommand
{
@@ -34,7 +33,7 @@ class BITOP extends RedisCommand
public function setArguments(array $arguments)
{
if (count($arguments) === 3 && is_array($arguments[2])) {
list($operation, $destination) = $arguments;
[$operation, $destination] = $arguments;
$arguments = $arguments[2];
array_unshift($arguments, $operation, $destination);
}
+7 -3
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -12,14 +13,17 @@
namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\BitByte;
/**
* @link http://redis.io/commands/bitpos
* @see http://redis.io/commands/bitpos
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* Return the position of the first bit set to 1 or 0 in a string.
*/
class BITPOS extends RedisCommand
{
use BitByte;
/**
* {@inheritdoc}
*/
+21
View File
@@ -0,0 +1,21 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
class BLMOVE extends LMOVE
{
public function getId()
{
return 'BLMOVE';
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
class BLMPOP extends LMPOP
{
protected static $keysArgumentPositionOffset = 1;
protected static $leftRightArgumentPositionOffset = 2;
protected static $countArgumentPositionOffset = 3;
public function getId()
{
return 'BLMPOP';
}
}
+4 -5
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -14,9 +15,7 @@ namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* @link http://redis.io/commands/blpop
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @see http://redis.io/commands/blpop
*/
class BLPOP extends RedisCommand
{
@@ -34,7 +33,7 @@ class BLPOP extends RedisCommand
public function setArguments(array $arguments)
{
if (count($arguments) === 2 && is_array($arguments[0])) {
list($arguments, $timeout) = $arguments;
[$arguments, $timeout] = $arguments;
array_push($arguments, $timeout);
}
+4 -5
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -14,9 +15,7 @@ namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* @link http://redis.io/commands/brpop
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @see http://redis.io/commands/brpop
*/
class BRPOP extends RedisCommand
{
@@ -34,7 +33,7 @@ class BRPOP extends RedisCommand
public function setArguments(array $arguments)
{
if (count($arguments) === 2 && is_array($arguments[0])) {
list($arguments, $timeout) = $arguments;
[$arguments, $timeout] = $arguments;
array_push($arguments, $timeout);
}
+3 -4
View File
@@ -3,7 +3,8 @@
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -14,9 +15,7 @@ namespace Predis\Command\Redis;
use Predis\Command\Command as RedisCommand;
/**
* @link http://redis.io/commands/brpoplpush
*
* @author Daniele Alessandri <suppakilla@gmail.com>
* @see http://redis.io/commands/brpoplpush
*/
class BRPOPLPUSH extends RedisCommand
{
+30
View File
@@ -0,0 +1,30 @@
<?php
/*
* This file is part of the Predis package.
*
* (c) 2009-2020 Daniele Alessandri
* (c) 2021-2023 Till Krüss
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\Command\Redis;
/**
* @see https://redis.io/commands/bzmpop/
*
* BZMPOP is the blocking variant of ZMPOP.
*/
class BZMPOP extends ZMPOP
{
protected static $keysArgumentPositionOffset = 1;
protected static $countArgumentPositionOffset = 3;
protected static $modifierArgumentPositionOffset = 2;
public function getId()
{
return 'BZMPOP';
}
}

Some files were not shown because too many files have changed in this diff Show More