mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-22 04:46:04 +03:00
Fix: allow MixedStore to accept true, false, null and floats as keys + related tests
This commit is contained in:
parent
f668300cd8
commit
bc6a7a3d1d
@ -16,7 +16,12 @@ class MixedStore implements \ArrayAccess
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $scalarStore;
|
||||
private $standardStore;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $floatStore;
|
||||
|
||||
/**
|
||||
* @var \SplObjectStorage
|
||||
@ -43,15 +48,49 @@ class MixedStore implements \ArrayAccess
|
||||
*/
|
||||
private $lastArrayValue;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
private $nullValue;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $nullValueIsSet;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
private $trueValue;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $trueValueIsSet;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
private $falseValue;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $falseValueIsSet;
|
||||
|
||||
/**
|
||||
* MixedStore constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->scalarStore = [];
|
||||
$this->standardStore = [];
|
||||
$this->floatStore = [];
|
||||
$this->objectStore = new \SplObjectStorage();
|
||||
$this->arrayKeys = [];
|
||||
$this->arrayValues = [];
|
||||
$this->nullValueIsSet = false;
|
||||
$this->trueValueIsSet = false;
|
||||
$this->falseValueIsSet = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,8 +107,17 @@ class MixedStore implements \ArrayAccess
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
if (is_scalar($offset)) {
|
||||
return array_key_exists($offset, $this->scalarStore);
|
||||
if (false === $offset) {
|
||||
return $this->falseValueIsSet;
|
||||
}
|
||||
if (true === $offset) {
|
||||
return $this->trueValueIsSet;
|
||||
}
|
||||
if (is_int($offset) || is_string($offset)) {
|
||||
return array_key_exists($offset, $this->standardStore);
|
||||
}
|
||||
if (is_float($offset)) {
|
||||
return array_key_exists((string) $offset, $this->floatStore);
|
||||
}
|
||||
if (is_object($offset)) {
|
||||
return $this->objectStore->offsetExists($offset);
|
||||
@ -83,6 +131,9 @@ class MixedStore implements \ArrayAccess
|
||||
}
|
||||
}
|
||||
}
|
||||
if (null === $offset) {
|
||||
return $this->nullValueIsSet;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -97,8 +148,17 @@ class MixedStore implements \ArrayAccess
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if (is_scalar($offset)) {
|
||||
return $this->scalarStore[$offset];
|
||||
if (true === $offset) {
|
||||
return $this->trueValue;
|
||||
}
|
||||
if (false === $offset) {
|
||||
return $this->falseValue;
|
||||
}
|
||||
if (is_int($offset) || is_string($offset)) {
|
||||
return $this->standardStore[$offset];
|
||||
}
|
||||
if (is_float($offset)) {
|
||||
return $this->floatStore[(string)$offset];
|
||||
}
|
||||
if (is_object($offset)) {
|
||||
return $this->objectStore->offsetGet($offset);
|
||||
@ -114,6 +174,9 @@ class MixedStore implements \ArrayAccess
|
||||
}
|
||||
}
|
||||
}
|
||||
if (null === $offset) {
|
||||
return $this->nullValue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -131,13 +194,24 @@ class MixedStore implements \ArrayAccess
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if (is_scalar($offset)) {
|
||||
$this->scalarStore[$offset] = $value;
|
||||
if (false === $offset) {
|
||||
$this->falseValue = $value;
|
||||
$this->falseValueIsSet = true;
|
||||
} else if (true === $offset) {
|
||||
$this->trueValue = $value;
|
||||
$this->trueValueIsSet = true;
|
||||
} else if (is_int($offset) || is_string($offset)) {
|
||||
$this->standardStore[$offset] = $value;
|
||||
} else if (is_float($offset)) {
|
||||
$this->floatStore[(string)$offset] = $value;
|
||||
} else if (is_object($offset)) {
|
||||
$this->objectStore[$offset] = $value;
|
||||
} else if (is_array($offset)) {
|
||||
$this->arrayKeys[] = $offset;
|
||||
$this->arrayValues[] = $value;
|
||||
} else if (null === $offset) {
|
||||
$this->nullValue = $value;
|
||||
$this->nullValueIsSet = true;
|
||||
} else {
|
||||
throw new \InvalidArgumentException("Unexpected offset type: " . Utils::printSafe($offset));
|
||||
}
|
||||
@ -154,8 +228,16 @@ class MixedStore implements \ArrayAccess
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
if (is_scalar($offset)) {
|
||||
unset($this->scalarStore[$offset]);
|
||||
if (true === $offset) {
|
||||
$this->trueValue = null;
|
||||
$this->trueValueIsSet = false;
|
||||
} else if (false === $offset) {
|
||||
$this->falseValue = null;
|
||||
$this->falseValueIsSet = false;
|
||||
} else if (is_int($offset) || is_string($offset)) {
|
||||
unset($this->standardStore[$offset]);
|
||||
} else if (is_float($offset)) {
|
||||
unset($this->floatStore[(string)$offset]);
|
||||
} else if (is_object($offset)) {
|
||||
$this->objectStore->offsetUnset($offset);
|
||||
} else if (is_array($offset)) {
|
||||
@ -165,6 +247,9 @@ class MixedStore implements \ArrayAccess
|
||||
array_splice($this->arrayKeys, $index, 1);
|
||||
array_splice($this->arrayValues, $index, 1);
|
||||
}
|
||||
} else if (null === $offset) {
|
||||
$this->nullValue = null;
|
||||
$this->nullValueIsSet = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
126
tests/Utils/MixedStoreTest.php
Normal file
126
tests/Utils/MixedStoreTest.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
namespace GraphQL\Tests\Utils;
|
||||
|
||||
|
||||
use GraphQL\Utils;
|
||||
use GraphQL\Utils\MixedStore;
|
||||
|
||||
class MixedStoreTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var MixedStore
|
||||
*/
|
||||
private $mixedStore;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->mixedStore = new MixedStore();
|
||||
}
|
||||
|
||||
public function getPossibleValues()
|
||||
{
|
||||
return [
|
||||
null,
|
||||
false,
|
||||
true,
|
||||
'',
|
||||
'0',
|
||||
'1',
|
||||
'a',
|
||||
[],
|
||||
new \stdClass(),
|
||||
function() {},
|
||||
new MixedStore()
|
||||
];
|
||||
}
|
||||
|
||||
public function testAcceptsNullKeys()
|
||||
{
|
||||
foreach ($this->getPossibleValues() as $value) {
|
||||
$this->assertAcceptsKeyValue(null, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAcceptsBoolKeys()
|
||||
{
|
||||
foreach ($this->getPossibleValues() as $value) {
|
||||
$this->assertAcceptsKeyValue(false, $value);
|
||||
}
|
||||
foreach ($this->getPossibleValues() as $value) {
|
||||
$this->assertAcceptsKeyValue(true, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAcceptsIntKeys()
|
||||
{
|
||||
foreach ($this->getPossibleValues() as $value) {
|
||||
$this->assertAcceptsKeyValue(-100000, $value);
|
||||
$this->assertAcceptsKeyValue(-1, $value);
|
||||
$this->assertAcceptsKeyValue(0, $value);
|
||||
$this->assertAcceptsKeyValue(1, $value);
|
||||
$this->assertAcceptsKeyValue(1000000, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAcceptsFloatKeys()
|
||||
{
|
||||
foreach ($this->getPossibleValues() as $value) {
|
||||
$this->assertAcceptsKeyValue(-100000.5, $value);
|
||||
$this->assertAcceptsKeyValue(-1.6, $value);
|
||||
$this->assertAcceptsKeyValue(-0.0001, $value);
|
||||
$this->assertAcceptsKeyValue(0.0000, $value);
|
||||
$this->assertAcceptsKeyValue(0.0001, $value);
|
||||
$this->assertAcceptsKeyValue(1.6, $value);
|
||||
$this->assertAcceptsKeyValue(1000000.5, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAcceptsArrayKeys()
|
||||
{
|
||||
foreach ($this->getPossibleValues() as $value) {
|
||||
$this->assertAcceptsKeyValue([], $value);
|
||||
$this->assertAcceptsKeyValue([null], $value);
|
||||
$this->assertAcceptsKeyValue([[]], $value);
|
||||
$this->assertAcceptsKeyValue([new \stdClass()], $value);
|
||||
$this->assertAcceptsKeyValue(['a', 'b'], $value);
|
||||
$this->assertAcceptsKeyValue(['a' => 'b'], $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAcceptsObjectKeys()
|
||||
{
|
||||
foreach ($this->getPossibleValues() as $value) {
|
||||
$this->assertAcceptsKeyValue(new \stdClass(), $value);
|
||||
$this->assertAcceptsKeyValue(new MixedStore(), $value);
|
||||
$this->assertAcceptsKeyValue(function() {}, $value);
|
||||
}
|
||||
}
|
||||
|
||||
private function assertAcceptsKeyValue($key, $value)
|
||||
{
|
||||
$err = 'Failed assertion that MixedStore accepts key ' .
|
||||
Utils::printSafe($key) . ' with value ' . Utils::printSafe($value);
|
||||
|
||||
$this->assertFalse($this->mixedStore->offsetExists($key), $err);
|
||||
$this->mixedStore->offsetSet($key, $value);
|
||||
$this->assertTrue($this->mixedStore->offsetExists($key), $err);
|
||||
$this->assertSame($value, $this->mixedStore->offsetGet($key), $err);
|
||||
$this->mixedStore->offsetUnset($key);
|
||||
$this->assertFalse($this->mixedStore->offsetExists($key), $err);
|
||||
$this->assertProvidesArrayAccess($key, $value);
|
||||
}
|
||||
|
||||
private function assertProvidesArrayAccess($key, $value)
|
||||
{
|
||||
$err = 'Failed assertion that MixedStore provides array access for key ' .
|
||||
Utils::printSafe($key) . ' with value ' . Utils::printSafe($value);
|
||||
|
||||
$this->assertFalse(isset($this->mixedStore[$key]), $err);
|
||||
$this->mixedStore[$key] = $value;
|
||||
$this->assertTrue(isset($this->mixedStore[$key]), $err);
|
||||
$this->assertEquals(!empty($value), !empty($this->mixedStore[$key]), $err);
|
||||
$this->assertSame($value, $this->mixedStore[$key], $err);
|
||||
unset($this->mixedStore[$key]);
|
||||
$this->assertFalse(isset($this->mixedStore[$key]), $err);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user