diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 4a6e580..514bb8f 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -22,6 +22,7 @@ on: env: CONSUL_HTTP_ADDR: "127.0.0.1:8500" + CONSUL_VERSION: '1.16.1' jobs: tests: @@ -33,22 +34,32 @@ jobs: name: Tests - PHP ${{ matrix.php-version }} steps: - uses: actions/checkout@v3 + - uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} extensions: json ini-values: precision=14,serialize_precision=-1 - - run: | + + - name: 'Composer update' + # language=bash + run: | composer update \ --no-ansi \ --no-interaction \ --no-scripts \ --no-progress - - run: | - wget https://releases.hashicorp.com/consul/1.15.2/consul_1.15.2_linux_amd64.zip - unzip consul_1.15.2_linux_amd64.zip -d /usr/local/bin/ - rm consul_1.15.2_linux_amd64.zip + + - name: 'Install Consul' + # language=bash + run: | + wget https://releases.hashicorp.com/consul/${{ env.CONSUL_VERSION }}/consul_${{ env.CONSUL_VERSION }}_linux_amd64.zip + unzip consul_${{ env.CONSUL_VERSION }}_linux_amd64.zip -d /usr/local/bin/ + rm consul_${{ env.CONSUL_VERSION }}_linux_amd64.zip chmod +x /usr/local/bin/consul consul --version - - run: | + + - name: 'Execute tests' + # language=bash + run: | ./vendor/bin/phpunit -c phpunit.xml diff --git a/composer.lock b/composer.lock index b519421..f06ad9b 100644 --- a/composer.lock +++ b/composer.lock @@ -235,16 +235,16 @@ }, { "name": "guzzlehttp/promises", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6" + "reference": "111166291a0f8130081195ac4556a5587d7f1b5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6", - "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6", + "url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d", + "reference": "111166291a0f8130081195ac4556a5587d7f1b5d", "shasum": "" }, "require": { @@ -298,7 +298,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.0" + "source": "https://github.com/guzzle/promises/tree/2.0.1" }, "funding": [ { @@ -314,20 +314,20 @@ "type": "tidelift" } ], - "time": "2023-05-21T13:50:22+00:00" + "time": "2023-08-03T15:11:55+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.5.0", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "b635f279edd83fc275f822a1188157ffea568ff6" + "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6", - "reference": "b635f279edd83fc275f822a1188157ffea568ff6", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/8bd7c33a0734ae1c5d074360512beb716bef3f77", + "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77", "shasum": "" }, "require": { @@ -414,7 +414,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.5.0" + "source": "https://github.com/guzzle/psr7/tree/2.6.0" }, "funding": [ { @@ -430,7 +430,7 @@ "type": "tidelift" } ], - "time": "2023-04-17T16:11:26+00:00" + "time": "2023-08-03T15:06:02+00:00" }, { "name": "psr/http-client", @@ -638,16 +638,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e" + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", "shasum": "" }, "require": { @@ -656,7 +656,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -685,7 +685,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" }, "funding": [ { @@ -701,7 +701,7 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:25:55+00:00" + "time": "2023-05-23T14:45:45+00:00" } ], "packages-dev": [ @@ -766,16 +766,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.15.5", + "version": "v4.17.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e" + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "shasum": "" }, "require": { @@ -816,9 +816,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" }, - "time": "2023-05-19T20:20:00+00:00" + "time": "2023-08-13T19:53:39+00:00" }, { "name": "phar-io/manifest", @@ -933,16 +933,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "10.1.2", + "version": "10.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "db1497ec8dd382e82c962f7abbe0320e4882ee4e" + "reference": "be1fe461fdc917de2a29a452ccf2657d325b443d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/db1497ec8dd382e82c962f7abbe0320e4882ee4e", - "reference": "db1497ec8dd382e82c962f7abbe0320e4882ee4e", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/be1fe461fdc917de2a29a452ccf2657d325b443d", + "reference": "be1fe461fdc917de2a29a452ccf2657d325b443d", "shasum": "" }, "require": { @@ -999,7 +999,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.2" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.3" }, "funding": [ { @@ -1007,7 +1007,7 @@ "type": "github" } ], - "time": "2023-05-22T09:04:27+00:00" + "time": "2023-07-26T13:45:28+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1253,16 +1253,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.1.3", + "version": "10.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2379ebafc1737e71cdc84f402acb6b7f04198b9d" + "reference": "0dafb1175c366dd274eaa9a625e914451506bcd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2379ebafc1737e71cdc84f402acb6b7f04198b9d", - "reference": "2379ebafc1737e71cdc84f402acb6b7f04198b9d", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0dafb1175c366dd274eaa9a625e914451506bcd1", + "reference": "0dafb1175c366dd274eaa9a625e914451506bcd1", "shasum": "" }, "require": { @@ -1287,7 +1287,7 @@ "sebastian/diff": "^5.0", "sebastian/environment": "^6.0", "sebastian/exporter": "^5.0", - "sebastian/global-state": "^6.0", + "sebastian/global-state": "^6.0.1", "sebastian/object-enumerator": "^5.0", "sebastian/recursion-context": "^5.0", "sebastian/type": "^4.0", @@ -1302,7 +1302,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.1-dev" + "dev-main": "10.3-dev" } }, "autoload": { @@ -1334,7 +1334,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.1.3" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.2" }, "funding": [ { @@ -1350,7 +1350,7 @@ "type": "tidelift" } ], - "time": "2023-05-11T05:16:22+00:00" + "time": "2023-08-15T05:34:23+00:00" }, { "name": "sebastian/cli-parser", @@ -1521,16 +1521,16 @@ }, { "name": "sebastian/comparator", - "version": "5.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c" + "reference": "2db5010a484d53ebf536087a70b4a5423c102372" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/72f01e6586e0caf6af81297897bd112eb7e9627c", - "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372", "shasum": "" }, "require": { @@ -1541,7 +1541,7 @@ "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^10.3" }, "type": "library", "extra": { @@ -1585,7 +1585,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" }, "funding": [ { @@ -1593,7 +1594,7 @@ "type": "github" } ], - "time": "2023-02-03T07:07:16+00:00" + "time": "2023-08-14T13:18:12+00:00" }, { "name": "sebastian/complexity", @@ -1862,16 +1863,16 @@ }, { "name": "sebastian/global-state", - "version": "6.0.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "aab257c712de87b90194febd52e4d184551c2d44" + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/aab257c712de87b90194febd52e4d184551c2d44", - "reference": "aab257c712de87b90194febd52e4d184551c2d44", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4", + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4", "shasum": "" }, "require": { @@ -1911,7 +1912,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.0" + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1" }, "funding": [ { @@ -1919,7 +1921,7 @@ "type": "github" } ], - "time": "2023-02-03T07:07:38+00:00" + "time": "2023-07-19T07:19:23+00:00" }, { "name": "sebastian/lines-of-code", diff --git a/phpunit.xml b/phpunit.xml index ef5e278..623a0bb 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -43,5 +43,9 @@ ./tests/Usage/Session + + + ./tests/Usage/Random + diff --git a/src/AbstractModel.php b/src/AbstractModel.php index 53951b9..5aa296c 100644 --- a/src/AbstractModel.php +++ b/src/AbstractModel.php @@ -30,6 +30,12 @@ abstract class AbstractModel implements \JsonSerializable protected const FIELDS = []; + /** + * Stores dynamically assigned variables + * @var array + */ + private array $_dyn = []; + /** * AbstractModel constructor. * @@ -49,6 +55,16 @@ public function __construct(?array $data = []) } } + public function __set(string $field, $value): void + { + $this->_dyn[$field] = $value; + } + + public function __get(string $field) + { + return $this->_dyn[$field] ?? null; + } + /** * todo: this picks up non-public fields. externalize this at some point. * @@ -57,8 +73,19 @@ public function __construct(?array $data = []) public function jsonSerialize(): array { $out = []; + // marshal fields foreach ((array)$this as $field => $value) { - $this->marshalField($out, $field, $value); + // marshal dynamically defined fields + // todo: this is crap. + if (substr($field, -4) === '_dyn') { + if ([] !== $value) { + foreach ($value as $k => $v) { + $this->marshalField($out, $k, $v); + } + } + } else { + $this->marshalField($out, $field, $value); + } } return $out; } diff --git a/src/Unmarshaller.php b/src/Unmarshaller.php index 1202e55..76cd707 100644 --- a/src/Unmarshaller.php +++ b/src/Unmarshaller.php @@ -46,19 +46,22 @@ protected function unmarshalField(string $field, $value): void // if the field isn't explicitly defined on the implementing class, just set it to whatever the incoming // value is $this->{$field} = $value; - } /** @noinspection PhpStatementHasEmptyBodyInspection */ elseif (null === $value) { - // if the value is null at this point, ignore and move on. - // note: this is not checked prior to the property_exists call as if the field is not explicitly defined but - // is seen with a null value, we still want to define it as null on the implementing type. - } elseif (isset($this->{$field}) && is_scalar($this->{$field})) { - // if the property has a scalar default value, unmarshal it as such. - $this->unmarshalScalar($field, $value, false); - } else { - // if we fall down here, try to set the value as-is. if this barfs, it indicates we have a bug to be - // squished. - // todo: should this be an exception? - $this->{$field} = $value; + } elseif (null !== $value) { + // at this point, value must be non-null to be operable + if (isset($this->{$field}) && is_scalar($this->{$field})) { + // if the property has a scalar default value, unmarshal it as such. + $this->unmarshalScalar($field, $value, false); + } else { + // if we fall down here, try to set the value as-is. if this barfs, it indicates we have a bug to be + // squished. + // todo: should this be an exception? + $this->{$field} = $value; + } } + + // if the value is null at this point, ignore and move on. + // note: this is not checked prior to the property_exists call as if the field is not explicitly defined but + // is seen with a null value, we still want to define it as null on the implementing type. } /** @@ -333,7 +336,7 @@ private function unmarshalArray(string $field, $value, array $def): void } foreach ($value as $k => $v) { - // todo: causes double-checking for null if value isn't null, not great... + // short circuit to prevent additional func call if (null === $v) { $this->{$field}[$k] = null; } else { @@ -343,6 +346,7 @@ private function unmarshalArray(string $field, $value, array $def): void } else { // in all other cases, just set as-is foreach ($value as $k => $v) { + // short circuit to prevent additional func call if (null === $v) { $this->{$field}[$k] = null; } else { diff --git a/tests/Usage/Random/RandomWhateverTest.php b/tests/Usage/Random/RandomWhateverTest.php new file mode 100644 index 0000000..965022b --- /dev/null +++ b/tests/Usage/Random/RandomWhateverTest.php @@ -0,0 +1,46 @@ +assertIsObject($dec); + + $kvp = new KVPair((array)$dec, false); + + self::assertEquals($v, $kvp->{$k}); + } +}