From d5893e02c3f1f4fe9ca74ae2728bc491e6ce3461 Mon Sep 17 00:00:00 2001 From: codeliner Date: Sat, 7 Mar 2020 18:50:03 +0100 Subject: [PATCH 01/11] Enable cs checks on travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bbaf530..003ea9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,8 +23,8 @@ before_script: script: - if [[ $TEST_COVERAGE == 'true' ]]; then php -dzend_extension=xdebug.so ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml; else ./vendor/bin/phpunit; fi -# - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/php-cs-fixer fix -v --diff --dry-run; fi -# - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/docheader check examples/ src/ tests/; fi + - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/php-cs-fixer fix -v --diff --dry-run; fi + - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/docheader check examples/ src/ tests/; fi after_success: - if [[ $TEST_COVERAGE == 'true' ]]; then php vendor/bin/coveralls -v; fi From cdfdf124ab28a6afa5b953f585b977594f00a4a4 Mon Sep 17 00:00:00 2001 From: codeliner Date: Sat, 7 Mar 2020 19:15:26 +0100 Subject: [PATCH 02/11] Fix cs check command in travis config --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 003ea9d..baaf2fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ before_script: script: - if [[ $TEST_COVERAGE == 'true' ]]; then php -dzend_extension=xdebug.so ./vendor/bin/phpunit --coverage-text --coverage-clover ./build/logs/clover.xml; else ./vendor/bin/phpunit; fi - - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/php-cs-fixer fix -v --diff --dry-run; fi + - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/php-cs-fixer fix src -v --diff --dry-run; fi - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/docheader check examples/ src/ tests/; fi after_success: From 1e3ca706920cd7389b55da4affce7d30133d14b2 Mon Sep 17 00:00:00 2001 From: codeliner Date: Sat, 7 Mar 2020 20:32:29 +0100 Subject: [PATCH 03/11] Add tests for ImmutableRecordDataConverter --- tests/ImmutableRecordDataConverterTest.php | 96 ++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 tests/ImmutableRecordDataConverterTest.php diff --git a/tests/ImmutableRecordDataConverterTest.php b/tests/ImmutableRecordDataConverterTest.php new file mode 100644 index 0000000..2756d26 --- /dev/null +++ b/tests/ImmutableRecordDataConverterTest.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +declare(strict_types=1); + +namespace EventEngineTest\Data; + +use EventEngine\Data\ImmutableRecordDataConverter; +use EventEngineTest\Data\Stub\TypeHintedImmutableRecordWithValueObjects; +use PHPUnit\Framework\TestCase; +use stdClass; + +final class ImmutableRecordDataConverterTest extends TestCase +{ + private $data = []; + + protected function setUp() + { + parent::setUp(); + + $this->data = [ + 'name' => 'test', + 'version' => 1, + 'itemList' => [['name' => 'one']], + 'access' => true, + ]; + } + + /** + * @test + */ + public function it_converts_immutable_record_to_array() + { + $valueObjects = TypeHintedImmutableRecordWithValueObjects::fromArray($this->data); + + $dataConverter = new ImmutableRecordDataConverter(); + + $this->data['type'] = null; + $this->data['percentage'] = 0.5; + + + $this->assertEquals( + $this->data, + $dataConverter->convertDataToArray( + TypeHintedImmutableRecordWithValueObjects::class, + $valueObjects + ) + ); + } + + /** + * @test + */ + public function it_converts_stdClass_to_array() + { + $obj = new stdClass(); + + $obj->test = "This is a test"; + $obj->msg = "With a message"; + + $this->assertEquals([ + 'test' => "This is a test", + 'msg' => "With a message", + ], + (new ImmutableRecordDataConverter())->convertDataToArray(stdClass::class, $obj) + ); + } + + /** + * @test + */ + public function it_converts_array_to_immutable_record() + { + $dataConverter = new ImmutableRecordDataConverter(); + + $this->assertTrue($dataConverter->canConvertTypeToData(TypeHintedImmutableRecordWithValueObjects::class)); + + $valueObjects = $dataConverter->convertArrayToData( + TypeHintedImmutableRecordWithValueObjects::class, + $this->data + ); + + $this->data['type'] = null; + $this->data['percentage'] = 0.5; + + $this->assertEquals( + $this->data, + $valueObjects->toArray() + ); + } +} From 1ecda749b232fae6a4442eeabe738061a076fbfa Mon Sep 17 00:00:00 2001 From: codeliner Date: Sat, 7 Mar 2020 21:31:27 +0100 Subject: [PATCH 04/11] Fix coveralls path --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index baaf2fb..9dd7095 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ script: - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/docheader check examples/ src/ tests/; fi after_success: - - if [[ $TEST_COVERAGE == 'true' ]]; then php vendor/bin/coveralls -v; fi + - if [[ $TEST_COVERAGE == 'true' ]]; then php ./vendor/bin/coveralls -v; fi notifications: webhooks: From ad3710ad79acd6784897bd3481a6cc335df90e4c Mon Sep 17 00:00:00 2001 From: codeliner Date: Sat, 7 Mar 2020 23:31:43 +0100 Subject: [PATCH 05/11] Install correct php-coveralls package --- .travis.yml | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9dd7095..0adef60 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ script: - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/docheader check examples/ src/ tests/; fi after_success: - - if [[ $TEST_COVERAGE == 'true' ]]; then php ./vendor/bin/coveralls -v; fi + - if [[ $TEST_COVERAGE == 'true' ]]; then php ./vendor/bin/php-coveralls -v; fi notifications: webhooks: diff --git a/composer.json b/composer.json index ee729b4..97adaf2 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "require-dev": { "phpunit/phpunit": "^7.0", "prooph/php-cs-fixer-config": "^0.3", - "satooshi/php-coveralls": "^2.2", + "php-coveralls/php-coveralls": "^2.2", "malukenho/docheader": "^0.1.4" }, "autoload": { From c48b0ecb5505aa154ae484d10b24a56350b5d0ec Mon Sep 17 00:00:00 2001 From: codeliner Date: Sun, 8 Mar 2020 15:51:40 +0100 Subject: [PATCH 06/11] More tests --- tests/ImmutableRecordDataConverterTest.php | 25 +++++ tests/ImmutableRecordLogicTest.php | 108 +++++++++++++++++++++ tests/Stub/RecordWithStringList.php | 34 +++++++ 3 files changed, 167 insertions(+) create mode 100644 tests/Stub/RecordWithStringList.php diff --git a/tests/ImmutableRecordDataConverterTest.php b/tests/ImmutableRecordDataConverterTest.php index 2756d26..cf0f5bb 100644 --- a/tests/ImmutableRecordDataConverterTest.php +++ b/tests/ImmutableRecordDataConverterTest.php @@ -11,6 +11,7 @@ namespace EventEngineTest\Data; use EventEngine\Data\ImmutableRecordDataConverter; +use EventEngineTest\Data\Stub\ImmutableItem; use EventEngineTest\Data\Stub\TypeHintedImmutableRecordWithValueObjects; use PHPUnit\Framework\TestCase; use stdClass; @@ -53,6 +54,30 @@ public function it_converts_immutable_record_to_array() ); } + /** + * @test + */ + public function it_returns_array_if_passed_as_input() + { + $input = ["a" => "test"]; + + $dataConverter = new ImmutableRecordDataConverter(); + + $output = $dataConverter->convertDataToArray('data', $input); + + $this->assertEquals($input, $output); + } + + /** + * @test + */ + public function it_returns_false_if_unknown_class_is_passed() + { + $dataConverter = new ImmutableRecordDataConverter(); + + $this->assertFalse($dataConverter->canConvertTypeToData(ImmutableItem::class . 'Unknown')); + } + /** * @test */ diff --git a/tests/ImmutableRecordLogicTest.php b/tests/ImmutableRecordLogicTest.php index 210ef1f..aa62013 100644 --- a/tests/ImmutableRecordLogicTest.php +++ b/tests/ImmutableRecordLogicTest.php @@ -13,6 +13,7 @@ use EventEngineTest\Data\Stub\ImmutableItem; use EventEngineTest\Data\Stub\ImmutableRecordWithNoTypes; use EventEngineTest\Data\Stub\ImmutableRecordWithTypedGetters; +use EventEngineTest\Data\Stub\RecordWithStringList; use EventEngineTest\Data\Stub\TypeHintedImmutableRecord; use EventEngineTest\Data\Stub\TypeHintedImmutableRecordWithValueObjects; use EventEngineTest\Data\Stub\ValueObject\Access; @@ -22,6 +23,7 @@ use EventEngineTest\Data\Stub\ValueObject\Type; use EventEngineTest\Data\Stub\ValueObject\Version; use PHPUnit\Framework\TestCase; +use function sprintf; final class ImmutableRecordLogicTest extends TestCase { @@ -110,6 +112,112 @@ public function it_takes_value_object_as_initialization_params() ); } + /** + * @test + */ + public function it_returns_new_record_with_changed_properties() + { + $valueObjects = TypeHintedImmutableRecordWithValueObjects::fromArray($this->data); + + $changedValueObjects = $valueObjects->with([ + 'version' => Version::fromInt(2), + 'percentage' => Percentage::fromFloat(0.9) + ]); + + $this->data['type'] = null; + $this->data['percentage'] = 0.5; + + $this->assertEquals( + $this->data, + $valueObjects->toArray() + ); + + $this->data['percentage'] = 0.9; + $this->data['version'] = 2; + + $this->assertEquals( + $this->data, + $changedValueObjects->toArray() + ); + } + + /** + * @test + */ + public function it_equals_other_record_with_same_values() + { + $valueObjects = TypeHintedImmutableRecordWithValueObjects::fromArray($this->data); + $other = TypeHintedImmutableRecordWithValueObjects::fromArray($this->data); + + $this->assertTrue($valueObjects->equals($other)); + } + + /** + * @test + */ + public function it_throws_exception_if_unkown_property_provided() + { + $this->data['unknown'] = 'value'; + + $this->expectExceptionMessage('Invalid property passed to Record ' . TypeHintedImmutableRecordWithValueObjects::class . '. Got property with key unknown'); + + TypeHintedImmutableRecordWithValueObjects::fromArray($this->data); + } + + /** + * @test + */ + public function it_throws_exception_if_non_nullable_prop_is_missing() + { + unset($this->data['version']); + + $this->expectExceptionMessage('Missing record data for key version of record ' . TypeHintedImmutableRecord::class); + + TypeHintedImmutableRecord::fromArray($this->data); + } + + /** + * @test + */ + public function it_throws_exception_if_non_nullable_prop_should_be_set_to_null() + { + $this->data['version'] = null; + + $this->expectExceptionMessage("Got null for non nullable property version of Record " . TypeHintedImmutableRecord::class); + + TypeHintedImmutableRecord::fromArray($this->data); + } + + /** + * @test + */ + public function it_throws_exception_if_property_value_has_wrong_type() + { + $this->data['version'] = 'v1'; + + $this->expectExceptionMessage(sprintf( + "Record %s data contains invalid value for property version. Expected type is int. Got type string.", + TypeHintedImmutableRecord::class + )); + + TypeHintedImmutableRecord::fromArray($this->data); + } + + /** + * @test + */ + public function it_throws_exception_if_array_property_contains_invalid_value() + { + $stringList = ["abc", 123, "def"]; + + $this->expectExceptionMessage(sprintf( + "Record %s data contains invalid value for property stringList. Value should be an array of string, but at least one item of the array has the wrong type.", + RecordWithStringList::class + )); + + RecordWithStringList::fromArray(['stringList' => $stringList]); + } + /** * @test */ diff --git a/tests/Stub/RecordWithStringList.php b/tests/Stub/RecordWithStringList.php new file mode 100644 index 0000000..333371e --- /dev/null +++ b/tests/Stub/RecordWithStringList.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +declare(strict_types=1); + +namespace EventEngineTest\Data\Stub; + +use EventEngine\Data\ImmutableRecord; +use EventEngine\Data\ImmutableRecordLogic; + +final class RecordWithStringList implements ImmutableRecord +{ + use ImmutableRecordLogic; + + private array $stringList; + + private static function arrayPropItemTypeMap(): array + { + return ['stringList' => ImmutableRecord::PHP_TYPE_STRING]; + } + + /** + * @return array + */ + public function stringList(): array + { + return $this->stringList; + } +} From 97ed424cb797a71b14a5ee7e5cb42fde8733b9e1 Mon Sep 17 00:00:00 2001 From: Sandro Keil Date: Wed, 1 Jul 2020 23:14:17 +0200 Subject: [PATCH 07/11] Add special key support e. g. snake_case --- src/ImmutableRecordLogic.php | 42 ++++++++++---- src/SpecialKeySupport.php | 36 ++++++++++++ tests/ImmutableRecordLogicTest.php | 39 ++++++++++--- tests/Stub/RecordWithSpecialKey.php | 90 +++++++++++++++++++++++++++++ 4 files changed, 187 insertions(+), 20 deletions(-) create mode 100644 src/SpecialKeySupport.php create mode 100644 tests/Stub/RecordWithSpecialKey.php diff --git a/src/ImmutableRecordLogic.php b/src/ImmutableRecordLogic.php index 717647b..854573f 100644 --- a/src/ImmutableRecordLogic.php +++ b/src/ImmutableRecordLogic.php @@ -93,6 +93,12 @@ public function toArray(): array $arrayPropItemTypeMap = self::getArrayPropItemTypeMapFromMethodOrCache(); foreach (self::$__propTypeMap as $key => [$type, $isNative, $isNullable]) { + $specialKey = $key; + + if ($this instanceof SpecialKeySupport) { + $specialKey = $this->convertKeyForArray($key); + } + switch ($type) { case ImmutableRecord::PHP_TYPE_STRING: case ImmutableRecord::PHP_TYPE_INT: @@ -101,23 +107,23 @@ public function toArray(): array case ImmutableRecord::PHP_TYPE_ARRAY: if (\array_key_exists($key, $arrayPropItemTypeMap) && ! self::isScalarType($arrayPropItemTypeMap[$key])) { if ($isNullable && $this->{$key} === null) { - $nativeData[$key] = null; + $nativeData[$specialKey] = null; continue 2; } - $nativeData[$key] = \array_map(function ($item) use ($key, &$arrayPropItemTypeMap) { + $nativeData[$specialKey] = \array_map(function ($item) use ($key, &$arrayPropItemTypeMap) { return $this->voTypeToNative($item, $key, $arrayPropItemTypeMap[$key]); }, $this->{$key}); } else { - $nativeData[$key] = $this->{$key}; + $nativeData[$specialKey] = $this->{$key}; } break; default: if ($isNullable && (! isset($this->{$key}))) { - $nativeData[$key] = null; + $nativeData[$specialKey] = null; continue 2; } - $nativeData[$key] = $this->voTypeToNative($this->{$key}, $key, $type); + $nativeData[$specialKey] = $this->voTypeToNative($this->{$key}, $key, $type); } } @@ -126,7 +132,7 @@ public function toArray(): array public function equals(ImmutableRecord $other): bool { - if (get_class($this) !== get_class($other)) { + if (\get_class($this) !== \get_class($other)) { return false; } @@ -136,8 +142,14 @@ public function equals(ImmutableRecord $other): bool private function setRecordData(array $recordData): void { foreach ($recordData as $key => $value) { - $this->assertType($key, $value); - $this->{$key} = $value; + $specialKey = $key; + + if ($this instanceof SpecialKeySupport) { + $specialKey = $this->convertKeyForRecord($key); + } + + $this->assertType($specialKey, $value); + $this->{$specialKey} = $value; } } @@ -147,17 +159,23 @@ private function setNativeData(array $nativeData): void $arrayPropItemTypeMap = self::getArrayPropItemTypeMapFromMethodOrCache(); foreach ($nativeData as $key => $val) { - if (! isset(self::$__propTypeMap[$key])) { + $specialKey = $key; + + if ($this instanceof SpecialKeySupport) { + $specialKey = $this->convertKeyForRecord($key); + } + + if (! isset(self::$__propTypeMap[$specialKey])) { throw new \InvalidArgumentException(\sprintf( - 'Invalid property passed to Record %s. Got property with key ' . $key, + 'Invalid property passed to Record %s. Got property with key ' . $specialKey, \get_called_class() )); } - [$type, $isNative, $isNullable] = self::$__propTypeMap[$key]; + [$type, $isNative, $isNullable] = self::$__propTypeMap[$specialKey]; if ($val === null) { if (! $isNullable) { - throw new \RuntimeException("Got null for non nullable property $key of Record " . \get_called_class()); + throw new \RuntimeException("Got null for non nullable property $specialKey of Record " . \get_called_class()); } $recordData[$key] = null; diff --git a/src/SpecialKeySupport.php b/src/SpecialKeySupport.php new file mode 100644 index 0000000..b527515 --- /dev/null +++ b/src/SpecialKeySupport.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace EventEngine\Data; + +/** + * Implement this interface in your ImmutableRecord class if you have special keys like snake_case. + */ +interface SpecialKeySupport +{ + /** + * Converts the given key to key name for the record. For example if the key is first_name and you have a class + * property firstName then you have to convert it to camel case. + * + * @param string $key + * @return string + */ + public function convertKeyForRecord(string $key): string; + + /** + * Converts the given key to key name for the array data. For example if you have a class property firstName + * and want to have snake case array keys then you have to convert it to first_name. + * + * @param string $key + * @return string + */ + public function convertKeyForArray(string $key): string; +} diff --git a/tests/ImmutableRecordLogicTest.php b/tests/ImmutableRecordLogicTest.php index aa62013..a69b3aa 100644 --- a/tests/ImmutableRecordLogicTest.php +++ b/tests/ImmutableRecordLogicTest.php @@ -6,6 +6,7 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ + declare(strict_types=1); namespace EventEngineTest\Data; @@ -13,6 +14,7 @@ use EventEngineTest\Data\Stub\ImmutableItem; use EventEngineTest\Data\Stub\ImmutableRecordWithNoTypes; use EventEngineTest\Data\Stub\ImmutableRecordWithTypedGetters; +use EventEngineTest\Data\Stub\RecordWithSpecialKey; use EventEngineTest\Data\Stub\RecordWithStringList; use EventEngineTest\Data\Stub\TypeHintedImmutableRecord; use EventEngineTest\Data\Stub\TypeHintedImmutableRecordWithValueObjects; @@ -23,7 +25,6 @@ use EventEngineTest\Data\Stub\ValueObject\Type; use EventEngineTest\Data\Stub\ValueObject\Version; use PHPUnit\Framework\TestCase; -use function sprintf; final class ImmutableRecordLogicTest extends TestCase { @@ -121,7 +122,7 @@ public function it_returns_new_record_with_changed_properties() $changedValueObjects = $valueObjects->with([ 'version' => Version::fromInt(2), - 'percentage' => Percentage::fromFloat(0.9) + 'percentage' => Percentage::fromFloat(0.9), ]); $this->data['type'] = null; @@ -152,6 +153,28 @@ public function it_equals_other_record_with_same_values() $this->assertTrue($valueObjects->equals($other)); } + /** + * @test + */ + public function it_supports_special_keys(): void + { + // emulates snake_case + $recordArray = [ + RecordWithSpecialKey::BANK_ACCOUNT => '12324434', + RecordWithSpecialKey::SUCCESS_RATE => 33.33, + RecordWithSpecialKey::ITEM_LIST => [['name' => 'Awesome tester'], ['name' => 'John Smith']], + ]; + $specialKey = RecordWithSpecialKey::fromArray($recordArray); + $this->assertSame($recordArray, $specialKey->toArray()); + + $specialKey = RecordWithSpecialKey::fromRecordData([ + RecordWithSpecialKey::BANK_ACCOUNT => $recordArray[RecordWithSpecialKey::BANK_ACCOUNT], + RecordWithSpecialKey::SUCCESS_RATE => Percentage::fromFloat($recordArray[RecordWithSpecialKey::SUCCESS_RATE]), + RecordWithSpecialKey::ITEM_LIST => ItemList::fromArray($recordArray[RecordWithSpecialKey::ITEM_LIST]), + ]); + $this->assertSame($recordArray, $specialKey->toArray()); + } + /** * @test */ @@ -183,7 +206,7 @@ public function it_throws_exception_if_non_nullable_prop_should_be_set_to_null() { $this->data['version'] = null; - $this->expectExceptionMessage("Got null for non nullable property version of Record " . TypeHintedImmutableRecord::class); + $this->expectExceptionMessage('Got null for non nullable property version of Record ' . TypeHintedImmutableRecord::class); TypeHintedImmutableRecord::fromArray($this->data); } @@ -195,8 +218,8 @@ public function it_throws_exception_if_property_value_has_wrong_type() { $this->data['version'] = 'v1'; - $this->expectExceptionMessage(sprintf( - "Record %s data contains invalid value for property version. Expected type is int. Got type string.", + $this->expectExceptionMessage(\sprintf( + 'Record %s data contains invalid value for property version. Expected type is int. Got type string.', TypeHintedImmutableRecord::class )); @@ -208,10 +231,10 @@ public function it_throws_exception_if_property_value_has_wrong_type() */ public function it_throws_exception_if_array_property_contains_invalid_value() { - $stringList = ["abc", 123, "def"]; + $stringList = ['abc', 123, 'def']; - $this->expectExceptionMessage(sprintf( - "Record %s data contains invalid value for property stringList. Value should be an array of string, but at least one item of the array has the wrong type.", + $this->expectExceptionMessage(\sprintf( + 'Record %s data contains invalid value for property stringList. Value should be an array of string, but at least one item of the array has the wrong type.', RecordWithStringList::class )); diff --git a/tests/Stub/RecordWithSpecialKey.php b/tests/Stub/RecordWithSpecialKey.php new file mode 100644 index 0000000..3bd81b3 --- /dev/null +++ b/tests/Stub/RecordWithSpecialKey.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace EventEngineTest\Data\Stub; + +use EventEngine\Data\ImmutableRecord; +use EventEngine\Data\ImmutableRecordLogic; +use EventEngine\Data\SpecialKeySupport; +use EventEngineTest\Data\Stub\ValueObject\ItemList; +use EventEngineTest\Data\Stub\ValueObject\Percentage; + +final class RecordWithSpecialKey implements ImmutableRecord, SpecialKeySupport +{ + use ImmutableRecordLogic; + + public const BANK_ACCOUNT = 'bank_account'; + public const SUCCESS_RATE = 'success_rate'; + public const ITEM_LIST = 'item_list'; + + /** + * @var string + */ + private $bankAccount; + + /** + * @var Percentage + */ + private $successRate; + + /** + * @var ItemList + */ + private $itemList; + + /** + * @return mixed + */ + public function bankAccount(): string + { + return $this->bankAccount; + } + + /** + * @return Percentage + */ + public function successRate(): Percentage + { + return $this->successRate; + } + + /** + * @return ItemList + */ + public function itemList(): ItemList + { + return $this->itemList; + } + + public function convertKeyForRecord(string $key): string + { + switch ($key) { + case self::SUCCESS_RATE: + return 'successRate'; + case self::ITEM_LIST: + return 'itemList'; + default: + return 'bankAccount'; + } + } + + public function convertKeyForArray(string $key): string + { + switch ($key) { + case 'successRate': + return self::SUCCESS_RATE; + case 'itemList': + return self::ITEM_LIST; + default: + return self::BANK_ACCOUNT; + } + } +} From 1c41211bfd501557ab63ae0d94393f4f06aa8c37 Mon Sep 17 00:00:00 2001 From: Zacharias Luiten Date: Sat, 30 Jan 2021 14:04:48 +0100 Subject: [PATCH 08/11] - Allow PHP 8 - Updated (dev) dependencies - Updated doc header with copyright year --- .travis.yml | 5 +++++ composer.json | 6 +++--- src/DataConverter.php | 2 +- src/ImmutableRecord.php | 2 +- src/ImmutableRecordDataConverter.php | 2 +- src/ImmutableRecordLogic.php | 2 +- src/SpecialKeySupport.php | 2 +- tests/ImmutableRecordDataConverterTest.php | 4 ++-- tests/ImmutableRecordLogicTest.php | 4 ++-- tests/Stub/ImmutableItem.php | 2 +- tests/Stub/ImmutableRecordWithNoTypes.php | 2 +- tests/Stub/ImmutableRecordWithTypedGetters.php | 2 +- tests/Stub/RecordWithSpecialKey.php | 2 +- tests/Stub/RecordWithStringList.php | 2 +- tests/Stub/TypeHintedImmutableRecord.php | 2 +- tests/Stub/TypeHintedImmutableRecordWithValueObjects.php | 2 +- tests/Stub/ValueObject/Access.php | 2 +- tests/Stub/ValueObject/ItemList.php | 2 +- tests/Stub/ValueObject/Name.php | 2 +- tests/Stub/ValueObject/Percentage.php | 2 +- tests/Stub/ValueObject/Type.php | 2 +- tests/Stub/ValueObject/Version.php | 2 +- 22 files changed, 30 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0adef60..209b70c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,11 @@ matrix: - DEPENDENCIES="" - EXECUTE_CS_CHECK=true - TEST_COVERAGE=true + - php: 8.0 + env: + - DEPENDENCIES="" + - EXECUTE_CS_CHECK=true + - TEST_COVERAGE=true cache: directories: diff --git a/composer.json b/composer.json index 97adaf2..6376d90 100644 --- a/composer.json +++ b/composer.json @@ -16,12 +16,12 @@ } ], "require": { - "php": "^7.4", + "php": "^7.4 || ^8.0", "roave/security-advisories": "dev-master" }, "require-dev": { - "phpunit/phpunit": "^7.0", - "prooph/php-cs-fixer-config": "^0.3", + "phpunit/phpunit": "^8.0 || ^9.0", + "prooph/php-cs-fixer-config": "^0.4", "php-coveralls/php-coveralls": "^2.2", "malukenho/docheader": "^0.1.4" }, diff --git a/src/DataConverter.php b/src/DataConverter.php index 6b5c229..7ef87ba 100644 --- a/src/DataConverter.php +++ b/src/DataConverter.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/ImmutableRecord.php b/src/ImmutableRecord.php index 0abe53e..a705147 100644 --- a/src/ImmutableRecord.php +++ b/src/ImmutableRecord.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/ImmutableRecordDataConverter.php b/src/ImmutableRecordDataConverter.php index 73526aa..5029cde 100644 --- a/src/ImmutableRecordDataConverter.php +++ b/src/ImmutableRecordDataConverter.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/ImmutableRecordLogic.php b/src/ImmutableRecordLogic.php index 854573f..19c6478 100644 --- a/src/ImmutableRecordLogic.php +++ b/src/ImmutableRecordLogic.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/src/SpecialKeySupport.php b/src/SpecialKeySupport.php index b527515..158c0d0 100644 --- a/src/SpecialKeySupport.php +++ b/src/SpecialKeySupport.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/ImmutableRecordDataConverterTest.php b/tests/ImmutableRecordDataConverterTest.php index cf0f5bb..77c6e5c 100644 --- a/tests/ImmutableRecordDataConverterTest.php +++ b/tests/ImmutableRecordDataConverterTest.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -20,7 +20,7 @@ final class ImmutableRecordDataConverterTest extends TestCase { private $data = []; - protected function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/ImmutableRecordLogicTest.php b/tests/ImmutableRecordLogicTest.php index a69b3aa..c3343ff 100644 --- a/tests/ImmutableRecordLogicTest.php +++ b/tests/ImmutableRecordLogicTest.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -30,7 +30,7 @@ final class ImmutableRecordLogicTest extends TestCase { private $data = []; - protected function setUp() + protected function setUp(): void { parent::setUp(); diff --git a/tests/Stub/ImmutableItem.php b/tests/Stub/ImmutableItem.php index 32cdbfb..92df681 100644 --- a/tests/Stub/ImmutableItem.php +++ b/tests/Stub/ImmutableItem.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Stub/ImmutableRecordWithNoTypes.php b/tests/Stub/ImmutableRecordWithNoTypes.php index 3a30282..8ac85ef 100644 --- a/tests/Stub/ImmutableRecordWithNoTypes.php +++ b/tests/Stub/ImmutableRecordWithNoTypes.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Stub/ImmutableRecordWithTypedGetters.php b/tests/Stub/ImmutableRecordWithTypedGetters.php index d7260f4..85ea424 100644 --- a/tests/Stub/ImmutableRecordWithTypedGetters.php +++ b/tests/Stub/ImmutableRecordWithTypedGetters.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Stub/RecordWithSpecialKey.php b/tests/Stub/RecordWithSpecialKey.php index 3bd81b3..8ab80cb 100644 --- a/tests/Stub/RecordWithSpecialKey.php +++ b/tests/Stub/RecordWithSpecialKey.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Stub/RecordWithStringList.php b/tests/Stub/RecordWithStringList.php index 333371e..059d359 100644 --- a/tests/Stub/RecordWithStringList.php +++ b/tests/Stub/RecordWithStringList.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Stub/TypeHintedImmutableRecord.php b/tests/Stub/TypeHintedImmutableRecord.php index 5496e80..5ae44d5 100644 --- a/tests/Stub/TypeHintedImmutableRecord.php +++ b/tests/Stub/TypeHintedImmutableRecord.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Stub/TypeHintedImmutableRecordWithValueObjects.php b/tests/Stub/TypeHintedImmutableRecordWithValueObjects.php index 7385553..07909ce 100644 --- a/tests/Stub/TypeHintedImmutableRecordWithValueObjects.php +++ b/tests/Stub/TypeHintedImmutableRecordWithValueObjects.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Stub/ValueObject/Access.php b/tests/Stub/ValueObject/Access.php index 7e09d31..cf7382b 100644 --- a/tests/Stub/ValueObject/Access.php +++ b/tests/Stub/ValueObject/Access.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Stub/ValueObject/ItemList.php b/tests/Stub/ValueObject/ItemList.php index 70f3d97..0bfc0a1 100644 --- a/tests/Stub/ValueObject/ItemList.php +++ b/tests/Stub/ValueObject/ItemList.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Stub/ValueObject/Name.php b/tests/Stub/ValueObject/Name.php index fffa4b7..342b3c0 100644 --- a/tests/Stub/ValueObject/Name.php +++ b/tests/Stub/ValueObject/Name.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Stub/ValueObject/Percentage.php b/tests/Stub/ValueObject/Percentage.php index b5283dd..145b3ac 100644 --- a/tests/Stub/ValueObject/Percentage.php +++ b/tests/Stub/ValueObject/Percentage.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Stub/ValueObject/Type.php b/tests/Stub/ValueObject/Type.php index bfe3e32..ff8c2ae 100644 --- a/tests/Stub/ValueObject/Type.php +++ b/tests/Stub/ValueObject/Type.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. diff --git a/tests/Stub/ValueObject/Version.php b/tests/Stub/ValueObject/Version.php index 70c2fc1..971f970 100644 --- a/tests/Stub/ValueObject/Version.php +++ b/tests/Stub/ValueObject/Version.php @@ -1,7 +1,7 @@ + * (c) 2018-2021 prooph software GmbH * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. From 522667ded5793ce4c7c64aabcbba0875c50dd0e3 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Wed, 17 Nov 2021 18:52:49 +0100 Subject: [PATCH 09/11] move roave/security-advisories to require-dev --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 6376d90..be3fa40 100644 --- a/composer.json +++ b/composer.json @@ -16,14 +16,14 @@ } ], "require": { - "php": "^7.4 || ^8.0", - "roave/security-advisories": "dev-master" + "php": "^7.4 || ^8.0" }, "require-dev": { "phpunit/phpunit": "^8.0 || ^9.0", "prooph/php-cs-fixer-config": "^0.4", "php-coveralls/php-coveralls": "^2.2", - "malukenho/docheader": "^0.1.4" + "malukenho/docheader": "^0.1.4", + "roave/security-advisories": "dev-latest" }, "autoload": { "psr-4": { From 2ec9e9199c3a4ab71dd2c7758d3cbd2920a0cea3 Mon Sep 17 00:00:00 2001 From: Arne De Smedt Date: Wed, 27 Apr 2022 10:57:09 +0200 Subject: [PATCH 10/11] arrayPropItemTypeMap should be indexed with a specialKey --- src/ImmutableRecordLogic.php | 6 +++--- tests/ImmutableRecordLogicTest.php | 8 ++++++++ tests/Stub/RecordWithSpecialKey.php | 25 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/ImmutableRecordLogic.php b/src/ImmutableRecordLogic.php index 19c6478..32d5581 100644 --- a/src/ImmutableRecordLogic.php +++ b/src/ImmutableRecordLogic.php @@ -190,9 +190,9 @@ private function setNativeData(array $nativeData): void $recordData[$key] = $val; break; case ImmutableRecord::PHP_TYPE_ARRAY: - if (\array_key_exists($key, $arrayPropItemTypeMap) && ! self::isScalarType($arrayPropItemTypeMap[$key])) { - $recordData[$key] = \array_map(function ($item) use ($key, &$arrayPropItemTypeMap) { - return $this->fromType($item, $arrayPropItemTypeMap[$key]); + if (\array_key_exists($specialKey, $arrayPropItemTypeMap) && ! self::isScalarType($arrayPropItemTypeMap[$specialKey])) { + $recordData[$key] = \array_map(function ($item) use ($specialKey, &$arrayPropItemTypeMap) { + return $this->fromType($item, $arrayPropItemTypeMap[$specialKey]); }, $val); } else { $recordData[$key] = $val; diff --git a/tests/ImmutableRecordLogicTest.php b/tests/ImmutableRecordLogicTest.php index c3343ff..e8f9ab5 100644 --- a/tests/ImmutableRecordLogicTest.php +++ b/tests/ImmutableRecordLogicTest.php @@ -163,6 +163,8 @@ public function it_supports_special_keys(): void RecordWithSpecialKey::BANK_ACCOUNT => '12324434', RecordWithSpecialKey::SUCCESS_RATE => 33.33, RecordWithSpecialKey::ITEM_LIST => [['name' => 'Awesome tester'], ['name' => 'John Smith']], + RecordWithSpecialKey::ITEM_ARRAY => [['name' => 'Awesome tester array'], ['name' => 'John Smith array']], + ]; $specialKey = RecordWithSpecialKey::fromArray($recordArray); $this->assertSame($recordArray, $specialKey->toArray()); @@ -171,6 +173,12 @@ public function it_supports_special_keys(): void RecordWithSpecialKey::BANK_ACCOUNT => $recordArray[RecordWithSpecialKey::BANK_ACCOUNT], RecordWithSpecialKey::SUCCESS_RATE => Percentage::fromFloat($recordArray[RecordWithSpecialKey::SUCCESS_RATE]), RecordWithSpecialKey::ITEM_LIST => ItemList::fromArray($recordArray[RecordWithSpecialKey::ITEM_LIST]), + RecordWithSpecialKey::ITEM_ARRAY => array_map( + static function (array $item) { + return ImmutableItem::fromArray($item); + }, + $recordArray[RecordWithSpecialKey::ITEM_ARRAY] + ), ]); $this->assertSame($recordArray, $specialKey->toArray()); } diff --git a/tests/Stub/RecordWithSpecialKey.php b/tests/Stub/RecordWithSpecialKey.php index 8ab80cb..a7b7249 100644 --- a/tests/Stub/RecordWithSpecialKey.php +++ b/tests/Stub/RecordWithSpecialKey.php @@ -24,6 +24,7 @@ final class RecordWithSpecialKey implements ImmutableRecord, SpecialKeySupport public const BANK_ACCOUNT = 'bank_account'; public const SUCCESS_RATE = 'success_rate'; public const ITEM_LIST = 'item_list'; + public const ITEM_ARRAY = 'item_array'; /** * @var string @@ -40,6 +41,11 @@ final class RecordWithSpecialKey implements ImmutableRecord, SpecialKeySupport */ private $itemList; + /** + * @var array + */ + private $itemArray; + /** * @return mixed */ @@ -64,6 +70,14 @@ public function itemList(): ItemList return $this->itemList; } + /** + * @return array + */ + public function itemArray(): array + { + return $this->itemArray; + } + public function convertKeyForRecord(string $key): string { switch ($key) { @@ -71,6 +85,8 @@ public function convertKeyForRecord(string $key): string return 'successRate'; case self::ITEM_LIST: return 'itemList'; + case self::ITEM_ARRAY: + return 'itemArray'; default: return 'bankAccount'; } @@ -83,8 +99,17 @@ public function convertKeyForArray(string $key): string return self::SUCCESS_RATE; case 'itemList': return self::ITEM_LIST; + case 'itemArray': + return self::ITEM_ARRAY; default: return self::BANK_ACCOUNT; } } + + private static function arrayPropItemTypeMap(): array + { + return [ + 'itemArray' => ImmutableItem::class, + ]; + } } From 5285ec033241de39faaed8975ed931e6e0e72626 Mon Sep 17 00:00:00 2001 From: Arne De Smedt Date: Thu, 16 Jan 2025 13:09:03 +0100 Subject: [PATCH 11/11] Explicit nullable types --- src/ImmutableRecordLogic.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImmutableRecordLogic.php b/src/ImmutableRecordLogic.php index 32d5581..5516f05 100644 --- a/src/ImmutableRecordLogic.php +++ b/src/ImmutableRecordLogic.php @@ -56,7 +56,7 @@ public static function fromArray(array $nativeData): self return new self(null, $nativeData); } - private function __construct(array $recordData = null, array $nativeData = null) + private function __construct(array|null $recordData = null, array|null $nativeData = null) { if (null === self::$__propTypeMap) { self::$__propTypeMap = self::buildPropTypeMap();