From cf1809f55ffa2c061cf94879a67af23927e2b867 Mon Sep 17 00:00:00 2001 From: Theo D Date: Fri, 1 Mar 2024 21:31:31 +0100 Subject: [PATCH] feat: Use PropertyAccess Component syntax for nested variables access --- .gitignore | 1 + CHANGELOG.md | 1 + composer.json | 1 + composer.lock | 164 +++++++++++++++++- doc/getting-started/context.md | 14 +- examples/context.php | 4 + src/ContextRegistry.php | 8 +- .../ContextContextDynamicTest.php.output.txt | 1 + ...ContextContextMyDefaultTest.php.output.txt | 1 + .../ContextContextPathTest.php.output.txt | 1 + ...ontextContextProductionTest.php.output.txt | 1 + .../ContextContextRunTest.php.output.txt | 1 + .../ContextContextTest.php.output.txt | 1 + .../ContextContextWithTest.php.output.txt | 3 +- 14 files changed, 190 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 5a685f78..f527b7c1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ /my-app.* /var/ /vendor/ +.idea/ diff --git a/CHANGELOG.md b/CHANGELOG.md index c6649c7d..9129db86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Add a `yaml_dump()` function to dump any PHP value to a YAML string * Add a `yaml_parse()` function to parse a YAML string to a PHP value * Remove the default timeout of 60 seconds from the Context +* Add possibility to use [Property Access Component](https://symfony.com/doc/current/components/property_access.html) syntax for getting variable from context. ## 0.13.1 (2024-02-27) diff --git a/composer.json b/composer.json index 9196fa27..943b7942 100644 --- a/composer.json +++ b/composer.json @@ -43,6 +43,7 @@ "symfony/http-client": "^6.4.3", "symfony/monolog-bridge": "^6.4.3", "symfony/process": "^6.4.3", + "symfony/property-access": "^6.4", "symfony/string": "^6.4.3", "symfony/translation-contracts": "^3.4.1", "symfony/var-dumper": "^6.4.3", diff --git a/composer.lock b/composer.lock index 612ecc71..d23b0612 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "16e5f7934a962f8c5ad979ca1c6cc176", + "content-hash": "a08187a40ca9c74303089d9e6d917d6b", "packages": [ { "name": "jolicode/jolinotif", @@ -2342,6 +2342,166 @@ ], "time": "2024-01-23T14:51:35+00:00" }, + { + "name": "symfony/property-access", + "version": "v6.4.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-access.git", + "reference": "c0664db266024013e31446dd690b6bfcf218ad93" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-access/zipball/c0664db266024013e31446dd690b6bfcf218ad93", + "reference": "c0664db266024013e31446dd690b6bfcf218ad93", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/property-info": "^5.4|^6.0|^7.0" + }, + "require-dev": { + "symfony/cache": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides functions to read and write from/to an object or array using a simple string notation", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property-path", + "reflection" + ], + "support": { + "source": "https://github.com/symfony/property-access/tree/v6.4.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-02-16T13:31:43+00:00" + }, + { + "name": "symfony/property-info", + "version": "v6.4.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-info.git", + "reference": "e96d740ab5ac39aa530c8eaa0720ea8169118e26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-info/zipball/e96d740ab5ac39aa530c8eaa0720ea8169118e26", + "reference": "e96d740ab5ac39aa530c8eaa0720ea8169118e26", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/string": "^5.4|^6.0|^7.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<5.2", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/dependency-injection": "<5.4", + "symfony/serializer": "<6.4" + }, + "require-dev": { + "phpdocumentor/reflection-docblock": "^5.2", + "phpstan/phpdoc-parser": "^1.0", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts information about PHP class' properties using metadata of popular sources", + "homepage": "https://symfony.com", + "keywords": [ + "doctrine", + "phpdoc", + "property", + "symfony", + "type", + "validator" + ], + "support": { + "source": "https://github.com/symfony/property-info/tree/v6.4.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T14:51:35+00:00" + }, { "name": "symfony/service-contracts", "version": "v3.4.1", @@ -3448,5 +3608,5 @@ "platform-overrides": { "php": "8.1.19" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.2.0" } diff --git a/doc/getting-started/context.md b/doc/getting-started/context.md index 687e003d..2b4f2e95 100644 --- a/doc/getting-started/context.md +++ b/doc/getting-started/context.md @@ -53,13 +53,15 @@ function foo(): void { $foobar = variable('foobar', 'default value'); - // Same as: $context = context(); - try { - $foobar = $context['foobar']; - } catch (\OutOfBoundsException) { - $foobar = 'default value; - } + // Same as: + $foobar = $context['foobar'] ?? 'default value'; + + // Getting nested values + $foobar = variable('[foo][bar][baz]', 'default value'); + + // Same as: + $foobar = $context['foo']['bar']['baz'] ?? 'default value'; } ``` diff --git a/examples/context.php b/examples/context.php index 27154bc0..8a7e3c48 100644 --- a/examples/context.php +++ b/examples/context.php @@ -21,6 +21,9 @@ function defaultContext(): Context 'name' => 'my_default', 'production' => false, 'foo' => 'bar', + 'nested' => [ + 'key' => 'nested_value', + ], ]); } @@ -83,6 +86,7 @@ function contextInfo(): void echo 'Production? ' . (variable('production', false) ? 'yes' : 'no') . "\n"; echo "verbosity: {$context->verbosityLevel->value}\n"; echo 'context: ' . variable('foo', 'N/A') . "\n"; + echo 'nested key: ' . variable('[nested][key]', 'N/A') . "\n"; } /** diff --git a/src/ContextRegistry.php b/src/ContextRegistry.php index faa79ca7..cd75f097 100644 --- a/src/ContextRegistry.php +++ b/src/ContextRegistry.php @@ -2,6 +2,8 @@ namespace Castor; +use Symfony\Component\PropertyAccess\PropertyAccess; + /** @internal */ class ContextRegistry { @@ -113,11 +115,11 @@ public function getVariable(string $key, mixed $default = null): mixed { $context = $this->getCurrentContext(); - if (!isset($context[$key])) { - return $default; + if (str_starts_with($key, '[')) { + return PropertyAccess::createPropertyAccessor()->getValue($context, $key) ?? $default; } - return $context[$key]; + return $context[$key] ?? $default; } /** diff --git a/tests/Examples/Generated/ContextContextDynamicTest.php.output.txt b/tests/Examples/Generated/ContextContextDynamicTest.php.output.txt index b5e52a95..9d8204e0 100644 --- a/tests/Examples/Generated/ContextContextDynamicTest.php.output.txt +++ b/tests/Examples/Generated/ContextContextDynamicTest.php.output.txt @@ -2,3 +2,4 @@ context name: dynamic Production? no verbosity: 1 context: baz +nested key: N/A diff --git a/tests/Examples/Generated/ContextContextMyDefaultTest.php.output.txt b/tests/Examples/Generated/ContextContextMyDefaultTest.php.output.txt index d9f99d5a..18ee1071 100644 --- a/tests/Examples/Generated/ContextContextMyDefaultTest.php.output.txt +++ b/tests/Examples/Generated/ContextContextMyDefaultTest.php.output.txt @@ -2,3 +2,4 @@ context name: my_default Production? no verbosity: 2 context: bar +nested key: nested_value diff --git a/tests/Examples/Generated/ContextContextPathTest.php.output.txt b/tests/Examples/Generated/ContextContextPathTest.php.output.txt index bf1dfcde..94c61039 100644 --- a/tests/Examples/Generated/ContextContextPathTest.php.output.txt +++ b/tests/Examples/Generated/ContextContextPathTest.php.output.txt @@ -2,3 +2,4 @@ context name: path Production? yes verbosity: 1 context: bar +nested key: N/A diff --git a/tests/Examples/Generated/ContextContextProductionTest.php.output.txt b/tests/Examples/Generated/ContextContextProductionTest.php.output.txt index e30eb5ba..15c9bbd9 100644 --- a/tests/Examples/Generated/ContextContextProductionTest.php.output.txt +++ b/tests/Examples/Generated/ContextContextProductionTest.php.output.txt @@ -2,3 +2,4 @@ context name: production Production? yes verbosity: 1 context: bar +nested key: nested_value diff --git a/tests/Examples/Generated/ContextContextRunTest.php.output.txt b/tests/Examples/Generated/ContextContextRunTest.php.output.txt index b371862f..91a81c7b 100644 --- a/tests/Examples/Generated/ContextContextRunTest.php.output.txt +++ b/tests/Examples/Generated/ContextContextRunTest.php.output.txt @@ -2,3 +2,4 @@ context name: run Production? no verbosity: 1 context: no defined +nested key: N/A diff --git a/tests/Examples/Generated/ContextContextTest.php.output.txt b/tests/Examples/Generated/ContextContextTest.php.output.txt index 0d2e5e60..96dd0762 100644 --- a/tests/Examples/Generated/ContextContextTest.php.output.txt +++ b/tests/Examples/Generated/ContextContextTest.php.output.txt @@ -2,3 +2,4 @@ context name: my_default Production? no verbosity: 1 context: bar +nested key: nested_value diff --git a/tests/Examples/Generated/ContextContextWithTest.php.output.txt b/tests/Examples/Generated/ContextContextWithTest.php.output.txt index 280f111d..88408218 100644 --- a/tests/Examples/Generated/ContextContextWithTest.php.output.txt +++ b/tests/Examples/Generated/ContextContextWithTest.php.output.txt @@ -2,4 +2,5 @@ context name: dynamic Production? no verbosity: -1 context: bar -bar \ No newline at end of file +nested key: N/A +bar