Skip to content

Commit

Permalink
Extended core support by implementing SORT_RO command (#1044)
Browse files Browse the repository at this point in the history
* Added support for SORT_RO command

* Codestyle fixes

* Added command description

---------

Co-authored-by: Vladyslav Vildanov <vladyslavvildanov@Vladyslav-Vildanov-MacBook-Pro.local>
  • Loading branch information
vladvildanov and Vladyslav Vildanov committed Jan 29, 2023
1 parent 50e005b commit db65e5e
Show file tree
Hide file tree
Showing 18 changed files with 738 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/ClientContextInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

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;

Expand All @@ -39,6 +40,7 @@
* @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)
Expand Down
2 changes: 2 additions & 0 deletions src/ClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

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;
Expand Down Expand Up @@ -48,6 +49,7 @@
* @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)
Expand Down
19 changes: 19 additions & 0 deletions src/Command/Argument/Server/LimitInterface.php
Original file line number Diff line number Diff line change
@@ -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
{
}
42 changes: 42 additions & 0 deletions src/Command/Argument/Server/LimitOffsetCount.php
Original file line number Diff line number Diff line change
@@ -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];
}
}
2 changes: 1 addition & 1 deletion src/Command/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public static function normalizeVariadic(array $arguments)
public function filterArguments(): void
{
$this->arguments = array_filter($this->arguments, static function ($argument) {
return $argument !== false;
return $argument !== false && $argument !== null;
});
}
}
2 changes: 1 addition & 1 deletion src/Command/Redis/SINTERCARD.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\Keys;
use Predis\Command\Traits\Limit;
use Predis\Command\Traits\Limit\Limit;

class SINTERCARD extends RedisCommand
{
Expand Down
74 changes: 74 additions & 0 deletions src/Command/Redis/SORT_RO.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?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;

use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\By\ByArgument;
use Predis\Command\Traits\Get\Get;
use Predis\Command\Traits\Limit\LimitObject;
use Predis\Command\Traits\Sorting;

/**
* @see https://redis.io/commands/sort_ro/
*
* Read-only variant of the SORT command.
* It is exactly like the original SORT but refuses the STORE option
* and can safely be used in read-only replicas.
*/
class SORT_RO extends RedisCommand
{
use ByArgument {
ByArgument::setArguments as setBy;
}
use LimitObject {
LimitObject::setArguments as setLimit;
}
use Get {
Get::setArguments as setGetArgument;
}
use Sorting {
Sorting::setArguments as setSorting;
}

protected static $byArgumentPositionOffset = 1;
protected static $getArgumentPositionOffset = 3;
protected static $sortArgumentPositionOffset = 4;

public function getId()
{
return 'SORT_RO';
}

public function setArguments(array $arguments)
{
$alpha = array_pop($arguments);

if (is_bool($alpha) && $alpha) {
$arguments[] = 'ALPHA';
} elseif (!is_bool($alpha)) {
$arguments[] = $alpha;
}

$this->setSorting($arguments);
$arguments = $this->getArguments();

$this->setGetArgument($arguments);
$arguments = $this->getArguments();

$this->setLimit($arguments);
$arguments = $this->getArguments();

$this->setBy($arguments);
$this->filterArguments();
}
}
2 changes: 1 addition & 1 deletion src/Command/Redis/ZINTERCARD.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\Keys;
use Predis\Command\Traits\Limit;
use Predis\Command\Traits\Limit\Limit;

/**
* @see https://redis.io/commands/zintercard/
Expand Down
2 changes: 1 addition & 1 deletion src/Command/Redis/ZRANGESTORE.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

use Predis\Command\Command as RedisCommand;
use Predis\Command\Traits\By\ByLexByScore;
use Predis\Command\Traits\Limit;
use Predis\Command\Traits\Limit\Limit;
use Predis\Command\Traits\Rev;

/**
Expand Down
40 changes: 40 additions & 0 deletions src/Command/Traits/By/ByArgument.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?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\Traits\By;

use Predis\Command\Command;

/**
* @mixin Command
*/
trait ByArgument
{
private $byModifier = 'BY';

public function setArguments(array $arguments)
{
$argumentsLength = count($arguments);

if (static::$byArgumentPositionOffset >= $argumentsLength || null === $arguments[static::$byArgumentPositionOffset]) {
parent::setArguments($arguments);

return;
}

$argument = $arguments[static::$byArgumentPositionOffset];
$argumentsBefore = array_slice($arguments, 0, static::$byArgumentPositionOffset);
$argumentsAfter = array_slice($arguments, static::$byArgumentPositionOffset + 1);

parent::setArguments(array_merge($argumentsBefore, [$this->byModifier, $argument], $argumentsAfter));
}
}
47 changes: 47 additions & 0 deletions src/Command/Traits/Get/Get.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?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\Traits\Get;

use UnexpectedValueException;

trait Get
{
private static $getModifier = 'GET';

public function setArguments(array $arguments)
{
$argumentsLength = count($arguments);

if (static::$getArgumentPositionOffset >= $argumentsLength) {
parent::setArguments($arguments);

return;
}

if (!is_array($arguments[static::$getArgumentPositionOffset])) {
throw new UnexpectedValueException('Wrong get argument type');
}

$patterns = [];

foreach ($arguments[static::$getArgumentPositionOffset] as $pattern) {
$patterns[] = self::$getModifier;
$patterns[] = $pattern;
}

$argumentsBeforeKeys = array_slice($arguments, 0, static::$getArgumentPositionOffset);
$argumentsAfterKeys = array_slice($arguments, static::$getArgumentPositionOffset + 1);

parent::setArguments(array_merge($argumentsBeforeKeys, $patterns, $argumentsAfterKeys));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* file that was distributed with this source code.
*/

namespace Predis\Command\Traits;
namespace Predis\Command\Traits\Limit;

use Predis\Command\Command;
use UnexpectedValueException;
Expand Down
50 changes: 50 additions & 0 deletions src/Command/Traits/Limit/LimitObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?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\Traits\Limit;

use Predis\Command\Argument\Server\LimitInterface;

trait LimitObject
{
public function setArguments(array $arguments)
{
$argumentPositionOffset = $this->getLimitArgumentPositionOffset($arguments);

if (null === $argumentPositionOffset) {
parent::setArguments($arguments);

return;
}

$limitObject = $arguments[$argumentPositionOffset];
$argumentsBefore = array_slice($arguments, 0, $argumentPositionOffset);
$argumentsAfter = array_slice($arguments, $argumentPositionOffset + 1);

parent::setArguments(array_merge(
$argumentsBefore,
$limitObject->toArray(),
$argumentsAfter
));
}

private function getLimitArgumentPositionOffset(array $arguments): ?int
{
foreach ($arguments as $i => $value) {
if ($value instanceof LimitInterface) {
return $i;
}
}

return null;
}
}
Loading

0 comments on commit db65e5e

Please sign in to comment.