From cec6583633dd1b8a746db81bc681b607989a434d Mon Sep 17 00:00:00 2001 From: Andreas Leathley Date: Sun, 10 May 2020 18:45:30 +0200 Subject: [PATCH] Improve flattened fields with types - Coerce values that can sensibly be coerced - Convert the functions into a trait so they can be shared between the three select classes - Adjust tests accordingly --- phpstan-baseline.neon | 40 ++++++ psalm-baseline.xml | 8 +- src/Action/FlattenedFieldsWithTypeTrait.php | 136 ++++++++++++++++++ src/Action/MultiSelectEntries.php | 4 +- src/Action/MultiSelectEntriesFreeform.php | 2 + src/Action/SelectEntries.php | 89 +----------- tests/RepositoryActions/SelectEntriesTest.php | 20 +-- 7 files changed, 194 insertions(+), 105 deletions(-) create mode 100644 src/Action/FlattenedFieldsWithTypeTrait.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 9f6a967..8dbcdb9 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,5 +1,45 @@ parameters: ignoreErrors: + - + message: "#^Method Squirrel\\\\Entities\\\\Action\\\\MultiSelectEntries\\:\\:getFlattenedIntegerFields\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: src/Action/MultiSelectEntries.php + + - + message: "#^Method Squirrel\\\\Entities\\\\Action\\\\MultiSelectEntries\\:\\:getFlattenedFloatFields\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: src/Action/MultiSelectEntries.php + + - + message: "#^Method Squirrel\\\\Entities\\\\Action\\\\MultiSelectEntries\\:\\:getFlattenedStringFields\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: src/Action/MultiSelectEntries.php + + - + message: "#^Method Squirrel\\\\Entities\\\\Action\\\\MultiSelectEntries\\:\\:getFlattenedBooleanFields\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: src/Action/MultiSelectEntries.php + + - + message: "#^Method Squirrel\\\\Entities\\\\Action\\\\MultiSelectEntriesFreeform\\:\\:getFlattenedIntegerFields\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: src/Action/MultiSelectEntriesFreeform.php + + - + message: "#^Method Squirrel\\\\Entities\\\\Action\\\\MultiSelectEntriesFreeform\\:\\:getFlattenedFloatFields\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: src/Action/MultiSelectEntriesFreeform.php + + - + message: "#^Method Squirrel\\\\Entities\\\\Action\\\\MultiSelectEntriesFreeform\\:\\:getFlattenedStringFields\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: src/Action/MultiSelectEntriesFreeform.php + + - + message: "#^Method Squirrel\\\\Entities\\\\Action\\\\MultiSelectEntriesFreeform\\:\\:getFlattenedBooleanFields\\(\\) should return array\\ but returns array\\\\.$#" + count: 1 + path: src/Action/MultiSelectEntriesFreeform.php + - message: "#^Method Squirrel\\\\Entities\\\\Action\\\\SelectEntries\\:\\:getFlattenedIntegerFields\\(\\) should return array\\ but returns array\\\\.$#" count: 1 diff --git a/psalm-baseline.xml b/psalm-baseline.xml index f3fdf40..b32bc5e 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,12 +1,6 @@ - - - $values - $values - $values - $values - + int[] float[] diff --git a/src/Action/FlattenedFieldsWithTypeTrait.php b/src/Action/FlattenedFieldsWithTypeTrait.php new file mode 100644 index 0000000..59bed01 --- /dev/null +++ b/src/Action/FlattenedFieldsWithTypeTrait.php @@ -0,0 +1,136 @@ +getFlattenedFields(); + + foreach ($values as $key => $value) { + // Convert non-int values which do not change when type casted + if ( + !\is_integer($value) + && \strval(\intval($value)) === \strval($value) + ) { + $values[$key] = \intval($value); + continue; + } + + if (!\is_int($value)) { + throw Debug::createException( + DBInvalidOptionException::class, + [ActionInterface::class], + 'Flattened integers requested, but not all values were integers' + ); + } + } + + return $values; + } + + /** + * @return float[] + */ + public function getFlattenedFloatFields(): array + { + $values = $this->getFlattenedFields(); + + foreach ($values as $key => $value) { + if (\is_int($value)) { + $values[$key] = \floatval($value); + continue; + } + + // Convert non-float values which do not change when type casted + if ( + !\is_float($value) + && \strval(\floatval($value)) === \strval($value) + ) { + $values[$key] = \floatval($value); + continue; + } + + if (!\is_float($value)) { + throw Debug::createException( + DBInvalidOptionException::class, + [ActionInterface::class], + 'Flattened floats requested, but not all values were floats' + ); + } + } + + return $values; + } + + /** + * @return string[] + */ + public function getFlattenedStringFields(): array + { + $values = $this->getFlattenedFields(); + + foreach ($values as $key => $value) { + // Integers and floats can be converted to strings without problems + if ( + \is_int($value) + || \is_float($value) + ) { + $values[$key] = \strval($value); + continue; + } + + if (!\is_string($value)) { + throw Debug::createException( + DBInvalidOptionException::class, + [ActionInterface::class], + 'Flattened strings requested, but not all values were strings' + ); + } + } + + return $values; + } + + /** + * @return bool[] + */ + public function getFlattenedBooleanFields(): array + { + $values = $this->getFlattenedFields(); + + foreach ($values as $key => $value) { + // Convert non-boolean values which can reasonably be converted to boolean + if ( + $value === 0 + || $value === '0' + ) { + $values[$key] = false; + continue; + } elseif ( + $value === 1 + || $value === '1' + ) { + $values[$key] = true; + continue; + } + + if (!\is_bool($value)) { + throw Debug::createException( + DBInvalidOptionException::class, + [ActionInterface::class], + 'Flattened booleans requested, but not all values were booleans' + ); + } + } + + return $values; + } +} diff --git a/src/Action/MultiSelectEntries.php b/src/Action/MultiSelectEntries.php index 3e52a53..4308d1b 100644 --- a/src/Action/MultiSelectEntries.php +++ b/src/Action/MultiSelectEntries.php @@ -13,6 +13,8 @@ */ class MultiSelectEntries implements ActionInterface, \IteratorAggregate { + use FlattenedFieldsWithTypeTrait; + private MultiRepositoryReadOnlyInterface $queryHandler; /** @@ -191,7 +193,7 @@ public function getOneEntry(): ?array /** * Execute SELECT query and return the fields as a list of values * - * @return array + * @return array */ public function getFlattenedFields(): array { diff --git a/src/Action/MultiSelectEntriesFreeform.php b/src/Action/MultiSelectEntriesFreeform.php index e52804c..1d32fa4 100644 --- a/src/Action/MultiSelectEntriesFreeform.php +++ b/src/Action/MultiSelectEntriesFreeform.php @@ -15,6 +15,8 @@ */ class MultiSelectEntriesFreeform implements ActionInterface, \IteratorAggregate { + use FlattenedFieldsWithTypeTrait; + private MultiRepositoryReadOnlyInterface $queryHandler; /** diff --git a/src/Action/SelectEntries.php b/src/Action/SelectEntries.php index 8ff8eac..c0aafa5 100644 --- a/src/Action/SelectEntries.php +++ b/src/Action/SelectEntries.php @@ -2,9 +2,7 @@ namespace Squirrel\Entities\Action; -use Squirrel\Debug\Debug; use Squirrel\Entities\RepositoryReadOnlyInterface; -use Squirrel\Queries\Exception\DBInvalidOptionException; /** * Select query builder as a fluent object - build query and return object(s) or flattened fields @@ -13,6 +11,8 @@ */ class SelectEntries implements ActionInterface, \IteratorAggregate { + use FlattenedFieldsWithTypeTrait; + private RepositoryReadOnlyInterface $repository; /** @@ -157,91 +157,6 @@ public function getFlattenedFields(): array ]); } - /** - * @return int[] - */ - public function getFlattenedIntegerFields(): array - { - $values = $this->getFlattenedFields(); - - foreach ($values as $value) { - if (!\is_int($value)) { - throw Debug::createException( - DBInvalidOptionException::class, - [ActionInterface::class], - 'Flattened integers requested, but not all values were integers' - ); - } - } - - return $values; - } - - /** - * @return float[] - */ - public function getFlattenedFloatFields(): array - { - $values = $this->getFlattenedFields(); - - foreach ($values as $key => $value) { - if (\is_int($value)) { - $values[$key] = \floatval($value); - continue; - } - - if (!\is_float($value)) { - throw Debug::createException( - DBInvalidOptionException::class, - [ActionInterface::class], - 'Flattened floats requested, but not all values were floats' - ); - } - } - - return $values; - } - - /** - * @return string[] - */ - public function getFlattenedStringFields(): array - { - $values = $this->getFlattenedFields(); - - foreach ($values as $value) { - if (!\is_string($value)) { - throw Debug::createException( - DBInvalidOptionException::class, - [ActionInterface::class], - 'Flattened strings requested, but not all values were strings' - ); - } - } - - return $values; - } - - /** - * @return bool[] - */ - public function getFlattenedBooleanFields(): array - { - $values = $this->getFlattenedFields(); - - foreach ($values as $value) { - if (!\is_bool($value)) { - throw Debug::createException( - DBInvalidOptionException::class, - [ActionInterface::class], - 'Flattened booleans requested, but not all values were booleans' - ); - } - } - - return $values; - } - public function getIterator(): SelectIterator { return new SelectIterator($this->repository, [ diff --git a/tests/RepositoryActions/SelectEntriesTest.php b/tests/RepositoryActions/SelectEntriesTest.php index 673d144..9865600 100644 --- a/tests/RepositoryActions/SelectEntriesTest.php +++ b/tests/RepositoryActions/SelectEntriesTest.php @@ -344,11 +344,11 @@ public function testGetFlattenedIntegerFields() 'offset' => 13, 'lock' => true, ]) - ->andReturn([5, 6, 8]); + ->andReturn([5, 6, 8, '33', '64']); $results = $this->selectBuilder->getFlattenedIntegerFields(); - $this->assertEquals([5, 6, 8], $results); + $this->assertEquals([5, 6, 8, 33, 64], $results); } public function testGetFlattenedFloatFields() @@ -388,11 +388,11 @@ public function testGetFlattenedFloatFields() 'offset' => 13, 'lock' => true, ]) - ->andReturn([5, 6, 8, 3.7]); + ->andReturn([5, '6', 8, 3.7, '4.6']); $results = $this->selectBuilder->getFlattenedFloatFields(); - $this->assertEquals([5.0, 6.0, 8.0, 3.7], $results); + $this->assertEquals([5.0, 6.0, 8.0, 3.7, 4.6], $results); } public function testGetFlattenedBooleanFields() @@ -432,11 +432,11 @@ public function testGetFlattenedBooleanFields() 'offset' => 13, 'lock' => true, ]) - ->andReturn([true, false, true, true, false]); + ->andReturn([true, false, true, true, false, 0, 1, '0', '1']); $results = $this->selectBuilder->getFlattenedBooleanFields(); - $this->assertEquals([true, false, true, true, false], $results); + $this->assertEquals([true, false, true, true, false, false, true, false, true], $results); } public function testGetFlattenedStringFields() @@ -476,7 +476,7 @@ public function testGetFlattenedStringFields() 'offset' => 13, 'lock' => true, ]) - ->andReturn(['dada', '5', 'rtew', '', '7777.3']); + ->andReturn(['dada', 5, 'rtew', '', 7777.3]); $results = $this->selectBuilder->getFlattenedStringFields(); @@ -522,7 +522,7 @@ public function testGetFlattenedIntegerFieldsWrongType() 'offset' => 13, 'lock' => true, ]) - ->andReturn([5, '7', 6, 8]); + ->andReturn([5, '5lada', 6, 8]); $this->selectBuilder->getFlattenedIntegerFields(); } @@ -566,7 +566,7 @@ public function testGetFlattenedFloatFieldsWrongType() 'offset' => 13, 'lock' => true, ]) - ->andReturn([5, 6, 8, '3.7']); + ->andReturn([5, 6, 8, '3.7nonnumber']); $this->selectBuilder->getFlattenedFloatFields(); } @@ -654,7 +654,7 @@ public function testGetFlattenedStringFieldsWrongType() 'offset' => 13, 'lock' => true, ]) - ->andReturn(['dada', '5', 'rtew', 5, '7777.3']); + ->andReturn(['dada', '5', 'rtew', false, '7777.3']); $this->selectBuilder->getFlattenedStringFields(); }