mirror of
https://github.com/predis/predis.git
synced 2026-09-20 15:26:46 +00:00
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>
This commit is contained in:
committed by
GitHub
parent
bb65b31580
commit
b47aa7ad3a
@@ -185,6 +185,7 @@ use Predis\Command\CommandInterface;
|
||||
* @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>
|
||||
*/
|
||||
|
||||
@@ -203,6 +203,7 @@ use Predis\Response\Status;
|
||||
* @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>
|
||||
*/
|
||||
|
||||
@@ -14,6 +14,11 @@ namespace Predis\Command\Redis;
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
|
||||
/**
|
||||
* @deprecated As of Redis version 6.2.0, this command is regarded as deprecated.
|
||||
*
|
||||
* It can be replaced by GEOSEARCH and GEOSEARCHSTORE with the BYRADIUS argument
|
||||
* when migrating or writing new code.
|
||||
*
|
||||
* @link http://redis.io/commands/georadius
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
/**
|
||||
* @deprecated As of Redis version 6.2.0, this command is regarded as deprecated.
|
||||
*
|
||||
* It can be replaced by GEOSEARCH and GEOSEARCHSTORE with the FROMMEMBER arguments
|
||||
* when migrating or writing new code.
|
||||
*
|
||||
* @link http://redis.io/commands/georadiusbymember
|
||||
*
|
||||
* @author Daniele Alessandri <suppakilla@gmail.com>
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use Predis\Command\Traits\By\GeoBy;
|
||||
use Predis\Command\Traits\Count;
|
||||
use Predis\Command\Traits\From\GeoFrom;
|
||||
use Predis\Command\Traits\Sorting;
|
||||
use Predis\Command\Traits\Storedist;
|
||||
|
||||
/**
|
||||
* @link https://redis.io/commands/geosearchstore/
|
||||
*
|
||||
* This command is like GEOSEARCH, but stores the result in destination key.
|
||||
*/
|
||||
class GEOSEARCHSTORE extends RedisCommand
|
||||
{
|
||||
use GeoFrom {
|
||||
GeoFrom::setArguments as setFrom;
|
||||
}
|
||||
use GeoBy {
|
||||
GeoBy::setArguments as setBy;
|
||||
}
|
||||
use Sorting {
|
||||
Sorting::setArguments as setSorting;
|
||||
}
|
||||
use Count {
|
||||
Count::setArguments as setCount;
|
||||
}
|
||||
use Storedist {
|
||||
Storedist::setArguments as setStoreDist;
|
||||
}
|
||||
|
||||
protected static $sortArgumentPositionOffset = 4;
|
||||
protected static $countArgumentPositionOffset = 5;
|
||||
protected static $storeDistArgumentPositionOffset = 7;
|
||||
|
||||
public function getId()
|
||||
{
|
||||
return 'GEOSEARCHSTORE';
|
||||
}
|
||||
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$this->setStoreDist($arguments);
|
||||
$arguments = $this->getArguments();
|
||||
|
||||
$this->setCount($arguments, $arguments[6] ?? false);
|
||||
$arguments = $this->getArguments();
|
||||
|
||||
$this->setSorting($arguments);
|
||||
$arguments = $this->getArguments();
|
||||
|
||||
$this->setFrom($arguments);
|
||||
$arguments = $this->getArguments();
|
||||
|
||||
$this->setBy($arguments);
|
||||
$this->filterArguments();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Predis\Command\Traits;
|
||||
|
||||
use Predis\Command\Command;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* @mixin Command
|
||||
*/
|
||||
trait Storedist
|
||||
{
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
$argumentsLength = count($arguments);
|
||||
|
||||
if (
|
||||
static::$storeDistArgumentPositionOffset >= $argumentsLength
|
||||
|| false === $arguments[static::$storeDistArgumentPositionOffset]
|
||||
) {
|
||||
parent::setArguments($arguments);
|
||||
return;
|
||||
}
|
||||
|
||||
$argument = $arguments[static::$storeDistArgumentPositionOffset];
|
||||
|
||||
if (true === $argument) {
|
||||
$argument = 'STOREDIST';
|
||||
} else {
|
||||
throw new UnexpectedValueException("Wrong STOREDIST argument type");
|
||||
}
|
||||
|
||||
$argumentsBefore = array_slice($arguments, 0, static::$storeDistArgumentPositionOffset);
|
||||
$argumentsAfter = array_slice($arguments, static::$storeDistArgumentPositionOffset + 1);
|
||||
|
||||
parent::setArguments(array_merge($argumentsBefore, [$argument], $argumentsAfter));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,354 @@
|
||||
<?php
|
||||
|
||||
namespace Predis\Command\Redis;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Predis\Command\Argument\Geospatial\ByBox;
|
||||
use Predis\Command\Argument\Geospatial\ByInterface;
|
||||
use Predis\Command\Argument\Geospatial\ByRadius;
|
||||
use Predis\Command\Argument\Geospatial\FromInterface;
|
||||
use Predis\Command\Argument\Geospatial\FromLonLat;
|
||||
use Predis\Command\Argument\Geospatial\FromMember;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class GEOSEARCHSTORE_Test extends PredisCommandTestCase
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getExpectedCommand(): string
|
||||
{
|
||||
return GEOSEARCHSTORE::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getExpectedId(): string
|
||||
{
|
||||
return 'GEOSEARCHSTORE';
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
* @dataProvider argumentsProvider
|
||||
*/
|
||||
public function testFilterArguments(array $actualArguments, array $expectedArguments): void
|
||||
{
|
||||
$command = $this->getCommand();
|
||||
$command->setArguments($actualArguments);
|
||||
|
||||
$this->assertSameValues($expectedArguments, $command->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group disconnected
|
||||
*/
|
||||
public function testParseResponse(): void
|
||||
{
|
||||
$this->assertSame(1, $this->getCommand()->parseResponse(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @dataProvider coordinatesProvider
|
||||
* @param array $firstCoordinates
|
||||
* @param array $secondCoordinates
|
||||
* @param array $thirdCoordinates
|
||||
* @param string $destination
|
||||
* @param string $source
|
||||
* @param FromInterface $from
|
||||
* @param ByInterface $by
|
||||
* @param string|null $sorting
|
||||
* @param int $count
|
||||
* @param bool $any
|
||||
* @param int $expectedResultingElements
|
||||
* @param array $expectedResponse
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 6.2.0
|
||||
*/
|
||||
public function testStoresCorrectGivenGeospatialCoordinates(
|
||||
array $firstCoordinates,
|
||||
array $secondCoordinates,
|
||||
array $thirdCoordinates,
|
||||
string $destination,
|
||||
string $source,
|
||||
FromInterface $from,
|
||||
ByInterface $by,
|
||||
?string $sorting,
|
||||
int $count,
|
||||
bool $any,
|
||||
int $expectedResultingElements,
|
||||
array $expectedResponse
|
||||
): void {
|
||||
$redis = $this->getClient();
|
||||
|
||||
$redis->geoadd(...$firstCoordinates);
|
||||
$redis->geoadd(...$secondCoordinates);
|
||||
$redis->geoadd(...$thirdCoordinates);
|
||||
|
||||
$actualResultingElements = $redis->geosearchstore(
|
||||
$destination,
|
||||
$source,
|
||||
$from,
|
||||
$by,
|
||||
$sorting,
|
||||
$count,
|
||||
$any
|
||||
);
|
||||
|
||||
$this->assertSame($expectedResultingElements, $actualResultingElements);
|
||||
$this->assertSame($expectedResponse, $redis->geosearch($destination, $from, $by, $sorting, $count, $any));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 6.2.0
|
||||
*/
|
||||
public function testStoresInSortedSetWithStoreDistArgumentProvided(): void
|
||||
{
|
||||
$redis = $this->getClient();
|
||||
|
||||
$redis->geoadd('key', 1.1, 2, 'member1');
|
||||
$redis->geoadd('key', 2.1, 3, 'member2');
|
||||
$redis->geoadd('key', 3.1, 4, 'member3');
|
||||
|
||||
$actualResultingElements = $redis->geosearchstore(
|
||||
'destination',
|
||||
'key',
|
||||
new FromLonLat(1, 4),
|
||||
new ByRadius(9999, 'km'),
|
||||
null,
|
||||
2,
|
||||
false,
|
||||
true
|
||||
);
|
||||
|
||||
$this->assertSame(2, $actualResultingElements);
|
||||
$this->assertSame(['member2', 'member1'], $redis->zrange('destination', 0, -1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group connected
|
||||
* @dataProvider unexpectedValuesProvider
|
||||
* @param array $arguments
|
||||
* @param string $expectedException
|
||||
* @param string $expectedExceptionMessage
|
||||
* @return void
|
||||
* @requiresRedisVersion >= 6.2.0
|
||||
*/
|
||||
public function testThrowsExceptionOnUnexpectedValueProvided(
|
||||
array $arguments,
|
||||
string $expectedException,
|
||||
string $expectedExceptionMessage
|
||||
): void {
|
||||
$redis = $this->getClient();
|
||||
|
||||
$this->expectException($expectedException);
|
||||
$this->expectExceptionMessage($expectedExceptionMessage);
|
||||
|
||||
$redis->geosearchstore(...$arguments);
|
||||
}
|
||||
|
||||
public function argumentsProvider(): array
|
||||
{
|
||||
return [
|
||||
'with default arguments - FROMLONLAT, BYRADIUS' => [
|
||||
['destination', 'source', new FromLonLat(1.1, 2.2), new ByRadius(1, 'km')],
|
||||
['destination', 'source', 'FROMLONLAT', 1.1, 2.2, 'BYRADIUS', 1, 'km']
|
||||
],
|
||||
'with default arguments - FROMMEMBER, BYBOX' => [
|
||||
['destination', 'source', new FromMember('member'), new ByBox(1,1, 'km')],
|
||||
['destination', 'source', 'FROMMEMBER', 'member', 'BYBOX', 1, 1, 'km']
|
||||
],
|
||||
'with ASC sorting' => [
|
||||
['destination', 'source', new FromLonLat(1.1, 2.2), new ByRadius(1, 'km'), 'asc'],
|
||||
['destination', 'source', 'FROMLONLAT', 1.1, 2.2, 'BYRADIUS', 1, 'km', 'ASC']
|
||||
],
|
||||
'with DESC sorting' => [
|
||||
['destination', 'source', new FromLonLat(1.1, 2.2), new ByRadius(1, 'km'), 'desc'],
|
||||
['destination', 'source', 'FROMLONLAT', 1.1, 2.2, 'BYRADIUS', 1, 'km', 'DESC']
|
||||
],
|
||||
'with COUNT argument - without ANY option' => [
|
||||
['destination', 'source', new FromLonLat(1.1, 2.2), new ByRadius(1, 'km'), null, 20],
|
||||
['destination', 'source', 'FROMLONLAT', 1.1, 2.2, 'BYRADIUS', 1, 'km', 'COUNT', 20]
|
||||
],
|
||||
'with COUNT argument - with ANY option' => [
|
||||
['destination', 'source', new FromLonLat(1.1, 2.2), new ByRadius(1, 'km'), null, 20, true],
|
||||
['destination', 'source', 'FROMLONLAT', 1.1, 2.2, 'BYRADIUS', 1, 'km', 'COUNT', 20, 'ANY']
|
||||
],
|
||||
'with STOREDIST argument' => [
|
||||
['destination', 'source', new FromLonLat(1.1, 2.2), new ByRadius(1, 'km'), null, -1, false, true],
|
||||
['destination', 'source', 'FROMLONLAT', 1.1, 2.2, 'BYRADIUS', 1, 'km', 'STOREDIST']
|
||||
],
|
||||
'with all arguments' => [
|
||||
['destination', 'source', new FromLonLat(1.1, 2.2), new ByRadius(1, 'km'), 'asc', 20, true, true],
|
||||
['destination', 'source', 'FROMLONLAT', 1.1, 2.2, 'BYRADIUS', 1, 'km', 'ASC', 'COUNT', 20, 'ANY', 'STOREDIST']
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function coordinatesProvider(): array
|
||||
{
|
||||
return [
|
||||
'with default arguments - FROMLONLAT, BYRADIUS - all members' => [
|
||||
['key', 1.1, 2, 'member1'],
|
||||
['key', 2.1, 3, 'member2'],
|
||||
['key', 3.1, 4, 'member3'],
|
||||
'destination',
|
||||
'key',
|
||||
new FromLonLat(1, 4),
|
||||
new ByRadius(9999, 'km'),
|
||||
null,
|
||||
-1,
|
||||
false,
|
||||
3,
|
||||
['member1', 'member2', 'member3']
|
||||
],
|
||||
'with default arguments - FROMLONLAT, BYRADIUS - closest members' => [
|
||||
['key', 1.1, 2, 'member1'],
|
||||
['key', 2.1, 3, 'member2'],
|
||||
['key', 3.1, 4, 'member3'],
|
||||
'destination',
|
||||
'key',
|
||||
new FromLonLat(1, 3),
|
||||
new ByRadius(200, 'km'),
|
||||
null,
|
||||
-1,
|
||||
false,
|
||||
2,
|
||||
['member2', 'member1']
|
||||
],
|
||||
'with default arguments - FROMMEMBER, BYBOX - all members' => [
|
||||
['key', 1.1, 2, 'member1'],
|
||||
['key', 2.1, 3, 'member2'],
|
||||
['key', 3.1, 4, 'member3'],
|
||||
'destination',
|
||||
'key',
|
||||
new FromMember('member2'),
|
||||
new ByBox(999, 999, 'km'),
|
||||
null,
|
||||
-1,
|
||||
false,
|
||||
3,
|
||||
['member1', 'member2', 'member3']
|
||||
],
|
||||
'with default arguments - FROMMEMBER, BYBOX - closest members' => [
|
||||
['key', 1.1, 2, 'member1'],
|
||||
['key', 2.1, 3, 'member2'],
|
||||
['key', 3.1, 4, 'member3'],
|
||||
'destination',
|
||||
'key',
|
||||
new FromMember('member1'),
|
||||
new ByBox(300, 300, 'km'),
|
||||
null,
|
||||
-1,
|
||||
false,
|
||||
2,
|
||||
['member1', 'member2']
|
||||
],
|
||||
'with ASC modifier' => [
|
||||
['key', 1.1, 2, 'member1'],
|
||||
['key', 2.1, 3, 'member2'],
|
||||
['key', 3.1, 4, 'member3'],
|
||||
'destination',
|
||||
'key',
|
||||
new FromLonLat(1, 4),
|
||||
new ByRadius(9999, 'km'),
|
||||
'asc',
|
||||
-1,
|
||||
false,
|
||||
3,
|
||||
['member2', 'member1', 'member3']
|
||||
],
|
||||
'with DESC modifier' => [
|
||||
['key', 1.1, 2, 'member1'],
|
||||
['key', 2.1, 3, 'member2'],
|
||||
['key', 3.1, 4, 'member3'],
|
||||
'destination',
|
||||
'key',
|
||||
new FromLonLat(1, 4),
|
||||
new ByRadius(9999, 'km'),
|
||||
'desc',
|
||||
-1,
|
||||
false,
|
||||
3,
|
||||
['member3', 'member1', 'member2']
|
||||
],
|
||||
'with COUNT modifier - without ANY option' => [
|
||||
['key', 1.1, 2, 'member1'],
|
||||
['key', 2.1, 3, 'member2'],
|
||||
['key', 3.1, 4, 'member3'],
|
||||
'destination',
|
||||
'key',
|
||||
new FromLonLat(1, 4),
|
||||
new ByRadius(9999, 'km'),
|
||||
null,
|
||||
1,
|
||||
false,
|
||||
1,
|
||||
['member2']
|
||||
],
|
||||
'with COUNT modifier - with ANY option' => [
|
||||
['key', 1.1, 2, 'member1'],
|
||||
['key', 2.1, 3, 'member2'],
|
||||
['key', 3.1, 4, 'member3'],
|
||||
'destination',
|
||||
'key',
|
||||
new FromLonLat(1, 4),
|
||||
new ByRadius(9999, 'km'),
|
||||
null,
|
||||
2,
|
||||
true,
|
||||
2,
|
||||
['member1', 'member2']
|
||||
],
|
||||
'with all arguments' => [
|
||||
['key', 1.1, 2, 'member1'],
|
||||
['key', 2.1, 3, 'member2'],
|
||||
['key', 3.1, 4, 'member3'],
|
||||
'destination',
|
||||
'key',
|
||||
new FromLonLat(1, 4),
|
||||
new ByRadius(9999, 'km'),
|
||||
'asc',
|
||||
2,
|
||||
true,
|
||||
2,
|
||||
['member2', 'member1']
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function unexpectedValuesProvider(): array
|
||||
{
|
||||
return [
|
||||
'with wrong FROM argument' => [
|
||||
['destination', 'source', false, new ByRadius(9999, 'km'), null, -1, false, false],
|
||||
InvalidArgumentException::class,
|
||||
'Invalid FROM argument value given'
|
||||
],
|
||||
'with wrong BY argument' => [
|
||||
['destination', 'source', new FromLonLat(1, 4), false, null, -1, false, false],
|
||||
InvalidArgumentException::class,
|
||||
'Invalid BY argument value given'
|
||||
],
|
||||
'with wrong sorting argument' => [
|
||||
['destination', 'source', new FromLonLat(1, 4), new ByRadius(9999, 'km'), 'wrong', -1, false, false],
|
||||
UnexpectedValueException::class,
|
||||
'Sorting argument accepts only: asc, desc values'
|
||||
],
|
||||
'with wrong COUNT argument' => [
|
||||
['destination', 'source', new FromLonLat(1, 4), new ByRadius(9999, 'km'), null, 0, false, false],
|
||||
UnexpectedValueException::class,
|
||||
'Wrong count argument value or position offset'
|
||||
],
|
||||
'with wrong STOREDIST argument' => [
|
||||
['destination', 'source', new FromLonLat(1, 4), new ByRadius(9999, 'km'), null, 0, false, 'wrong'],
|
||||
UnexpectedValueException::class,
|
||||
'Wrong STOREDIST argument type'
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Predis\Command\Traits;
|
||||
|
||||
use Predis\Command\Command as RedisCommand;
|
||||
use PredisTestCase;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class StoredistTest extends PredisTestCase
|
||||
{
|
||||
private $testClass;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->testClass = new class extends RedisCommand {
|
||||
use Storedist;
|
||||
|
||||
public static $storeDistArgumentPositionOffset = 0;
|
||||
|
||||
public function getId()
|
||||
{
|
||||
return 'test';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider argumentsProvider
|
||||
* @param int $offset
|
||||
* @param array $actualArguments
|
||||
* @param array $expectedArguments
|
||||
* @return void
|
||||
*/
|
||||
public function testReturnsCorrectArguments(int $offset, array $actualArguments, array $expectedArguments): void
|
||||
{
|
||||
$this->testClass::$storeDistArgumentPositionOffset = $offset;
|
||||
|
||||
$this->testClass->setArguments($actualArguments);
|
||||
|
||||
$this->assertSame($expectedArguments, $this->testClass->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testThrowsExceptionOnUnexpectedValue(): void
|
||||
{
|
||||
$this->testClass::$storeDistArgumentPositionOffset = 0;
|
||||
|
||||
$this->expectException(UnexpectedValueException::class);
|
||||
$this->expectExceptionMessage("Wrong STOREDIST argument type");
|
||||
|
||||
$this->testClass->setArguments(['test']);
|
||||
}
|
||||
|
||||
public function argumentsProvider(): array
|
||||
{
|
||||
return [
|
||||
'STOREDIST false argument' => [
|
||||
0,
|
||||
[false, 'second argument', 'third argument'],
|
||||
[false, 'second argument', 'third argument']
|
||||
],
|
||||
'STOREDIST argument first and there is arguments after' => [
|
||||
0,
|
||||
[true, 'second argument', 'third argument'],
|
||||
['STOREDIST', 'second argument', 'third argument']
|
||||
],
|
||||
'STOREDIST argument last and there is arguments before' => [
|
||||
2,
|
||||
['first argument', 'second argument', true],
|
||||
['first argument', 'second argument', 'STOREDIST']
|
||||
],
|
||||
'STOREDIST argument not the first and not the last' => [
|
||||
1,
|
||||
['first argument', true, 'third argument'],
|
||||
['first argument', 'STOREDIST', 'third argument']
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user