From 0148ec74fc22dd034b6f7dc302a48e6682fcb475 Mon Sep 17 00:00:00 2001 From: Brajk19 Date: Fri, 24 Nov 2023 20:35:48 +0100 Subject: [PATCH 01/14] [PropertyAccess] Add support for wildcard PropertyPath New property `$isWildcard` is added which denotes whether certain element is wildcard. Element is registered as wildcard if it's `[*]`. Method isWildcard should be added to PropertyPathInterface in next major release. --- .../ViolationMapper/ViolationPath.php | 5 ++++ .../Component/PropertyAccess/PropertyPath.php | 27 ++++++++++++++++++- .../PropertyAccess/Tests/PropertyPathTest.php | 12 +++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php index 0c2a130cc86bd..d408c999aa17d 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php @@ -161,6 +161,11 @@ public function isNullSafe(int $index): bool return false; } + public function isWildcard(int $index): bool + { + return false; + } + /** * Returns whether an element maps directly to a form. * diff --git a/src/Symfony/Component/PropertyAccess/PropertyPath.php b/src/Symfony/Component/PropertyAccess/PropertyPath.php index e797ab77be07c..d4724e5cc93de 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyPath.php +++ b/src/Symfony/Component/PropertyAccess/PropertyPath.php @@ -57,6 +57,14 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface */ private array $isNullSafe = []; + /** + * Contains a Boolean for each property in $elements denoting whether this + * element is wildcard or not. + * + * @var array + */ + private array $isWildcard = []; + /** * String representation of the path. */ @@ -78,6 +86,7 @@ public function __construct(self|string $propertyPath) $this->isIndex = $propertyPath->isIndex; $this->isNullSafe = $propertyPath->isNullSafe; $this->pathAsString = $propertyPath->pathAsString; + $this->isWildcard = $propertyPath->isWildcard; return; } @@ -97,9 +106,15 @@ public function __construct(self|string $propertyPath) if ('' !== $matches[2]) { $element = $matches[2]; $this->isIndex[] = false; + $this->isWildcard[] = false; + } elseif ('[*]' === $matches[1]) { + $element = '*'; + $this->isIndex[] = false; + $this->isWildcard[] = true; } else { $element = $matches[3]; $this->isIndex[] = true; + $this->isWildcard[] = false; } // Mark as optional when last character is "?". @@ -110,7 +125,7 @@ public function __construct(self|string $propertyPath) $this->isNullSafe[] = false; } - $element = preg_replace('/\\\([.[])/', '$1', $element); + $element = preg_replace('/\\\([.[*])/', '$1', $element); if (str_ends_with($element, '\\\\')) { $element = substr($element, 0, -1); } @@ -151,6 +166,7 @@ public function getParent(): ?PropertyPathInterface array_pop($parent->elements); array_pop($parent->isIndex); array_pop($parent->isNullSafe); + array_pop($parent->isWildcard); return $parent; } @@ -203,4 +219,13 @@ public function isNullSafe(int $index): bool return $this->isNullSafe[$index]; } + + public function isWildcard(int $index): bool + { + if (!isset($this->isWildcard[$index])) { + throw new OutOfBoundsException(sprintf('The index "%s" is not within the property path.', $index)); + } + + return $this->isWildcard[$index]; + } } diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php index 9257229c3aebf..051cb771519da 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php @@ -204,4 +204,16 @@ public function testIsIndexDoesNotAcceptNegativeIndices() $propertyPath->isIndex(-1); } + + public function testIsWildcard(): void + { + $propertyPath = new PropertyPath('[*][parent][child].name'); + + $this->assertTrue($propertyPath->isWildcard(0)); + $this->assertFalse($propertyPath->isIndex(0)); + + $this->assertFalse($propertyPath->isWildcard(1)); + $this->assertFalse($propertyPath->isWildcard(2)); + $this->assertFalse($propertyPath->isWildcard(3)); + } } From 85248a41934e84cae8065a9c4cc629cb0ce8fae1 Mon Sep 17 00:00:00 2001 From: Brajk19 Date: Fri, 24 Nov 2023 20:40:31 +0100 Subject: [PATCH 02/14] [PropertyAccess] Add logic for reading with wildcard Whenever wildcard is in property path, that wildcard is replaced with all possible values and same method `readPropertyUntil` is recursively called. All returned subpaths are then merged together. --- .../PropertyAccess/PropertyAccessor.php | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 3c98d41bab019..89ba5c10231b8 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -275,7 +275,7 @@ public function isWritable(object|array $objectOrArray, string|PropertyPathInter * @throws UnexpectedTypeException if a value within the path is neither object nor array * @throws NoSuchIndexException If a non-existing index is accessed */ - private function readPropertiesUntil(array $zval, PropertyPathInterface $propertyPath, int $lastIndex, bool $ignoreInvalidIndices = true): array + private function readPropertiesUntil(array $zval, PropertyPathInterface $propertyPath, int $lastIndex, bool $ignoreInvalidIndices = true, int $startIndex = 0): array { if (!\is_object($zval[self::VALUE]) && !\is_array($zval[self::VALUE])) { throw new UnexpectedTypeException($zval[self::VALUE], $propertyPath, 0); @@ -284,11 +284,19 @@ private function readPropertiesUntil(array $zval, PropertyPathInterface $propert // Add the root object to the list $propertyValues = [$zval]; - for ($i = 0; $i < $lastIndex; ++$i) { + for ($i = $startIndex; $i < $lastIndex; ++$i) { $property = $propertyPath->getElement($i); $isIndex = $propertyPath->isIndex($i); $isNullSafe = $propertyPath->isNullSafe($i); + $isWildcard = false; + if (method_exists($propertyPath, 'isWildcard')) { + // To be removed in symfony 8 once we are sure isNullSafe is always implemented. + $isWildcard = $propertyPath->isWildcard($i); + } else { + trigger_deprecation('symfony/property-access', '7.1', 'The "%s()" method in class "%s" needs to be implemented in version 8.0, not defining it is deprecated.', 'isWildcard', PropertyPathInterface::class); + } + if ($isIndex) { // Create missing nested arrays on demand if (($zval[self::VALUE] instanceof \ArrayAccess && !$zval[self::VALUE]->offsetExists($property)) @@ -317,6 +325,40 @@ private function readPropertiesUntil(array $zval, PropertyPathInterface $propert } $zval = $this->readIndex($zval, $property); + } elseif ($isWildcard) { + $newPropertyValues = []; + + // replace wildcard with all posible values + // e.g. [*][foo] becomes [0][foo], [1][foo], ... + foreach (array_keys($zval[self::VALUE]) as $index) { + $path = preg_replace('/\[\*\]/', "[$index]", (string) ($propertyPath), 1); + $subPath = $this->readPropertiesUntil($zval, $this->getPropertyPath($path), $lastIndex, $ignoreInvalidIndices, $i); + + // merge property values from all sub paths + // skip first because it's same for all paths and is already in $propertyValues + for($j = 1; $j < count($subPath); $j++) { + $newPropertyValues[$j][self::VALUE][] = $subPath[$j][self::VALUE]; + } + } + + foreach ($newPropertyValues as &$newValue) { + $shouldMerge = true; + + foreach ($newValue[self::VALUE] as $value) { + $shouldMerge = is_array($value) && array_is_list($value); + + if(!$shouldMerge) { + break; + } + } + + if($shouldMerge) { + $newValue[self::VALUE] = array_merge(...$newValue[self::VALUE]); + } + } + + array_push($propertyValues, ...$newPropertyValues); + break; } elseif ($isNullSafe && !\is_object($zval[self::VALUE])) { $zval[self::VALUE] = null; } else { From 85ca8cd6fe8fd3a813e3b5c850e236475e812ca1 Mon Sep 17 00:00:00 2001 From: Brajk19 Date: Fri, 24 Nov 2023 20:43:45 +0100 Subject: [PATCH 03/14] [PropertyAccess] Add test for PropertyAcessor with wildcard --- .../Tests/PropertyAccessorWildcardTest.php | 184 ++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorWildcardTest.php diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorWildcardTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorWildcardTest.php new file mode 100644 index 0000000000000..a746bd91c02e4 --- /dev/null +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorWildcardTest.php @@ -0,0 +1,184 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyAccess\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\PropertyAccess\PropertyAccessor; +use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass; + +class PropertyAccessorWildcardTest extends TestCase +{ + private PropertyAccessor $propertyAccessor; + + protected function setUp(): void + { + $this->propertyAccessor = new PropertyAccessor(); + } + + private const TEST_ARRAY = [ + [ + 'id' => 1, + 'name' => 'John', + 'languages' => ['EN'], + '*' => 'wildcard1', + 'jobs' => [ + [ + 'title' => 'chef', + 'info' => [ + 'experience' => 6, + 'salary' => 34 + ] + ], + [ + 'title' => 'waiter', + 'info' => [ + 'experience' => 3, + 'salary' => 30 + ] + ], + ], + 'info' => [ + 'age' => 32, + ], + ], + [ + 'id' => 2, + 'name' => 'Luke', + 'languages' => ['EN', 'FR'], + '*' => 'wildcard2', + 'jobs' => [ + [ + 'title' => 'chef', + 'info' => [ + 'experience' => 3, + 'salary' => 31 + ] + ], + [ + 'title' => 'bartender', + 'info' => [ + 'experience' => 6, + 'salary' => 30 + ] + ], + ], + 'info' => [ + 'age' => 28, + ] + ], + ]; + + public static function provideWildcardPaths(): iterable + { + yield [ + 'path' => '[*][id]', + 'expected' => [1, 2] + ]; + + yield [ + 'path' => '[*][name]', + 'expected' => ['John', 'Luke'] + ]; + + yield [ + 'path' => '[*][languages]', + 'expected' => ['EN', 'EN', 'FR'] + ]; + + yield [ + 'path' => '[*][info][age]', + 'expected' => [32, 28] + ]; + + yield [ + 'path' => '[0][jobs][*][title]', + 'expected' => ['chef', 'waiter'] + ]; + + yield [ + 'path' => '[0][jobs][*][info]', + 'expected' => [ + ['experience' => 6, 'salary' => 34], + ['experience' => 3, 'salary' => 30], + ] + ]; + + yield [ + 'path' => '[0][jobs][*][info][experience]', + 'expected' => [6, 3] + ]; + + yield [ + 'path' => '[*][jobs][0][title]', + 'expected' => ['chef', 'chef'] + ]; + + yield [ + 'path' => '[*][jobs][*][title]', + 'expected' => ['chef', 'waiter', 'chef', 'bartender'] + ]; + + yield [ + 'path' => '[*][jobs][*][info][*]', + 'expected' => [6, 34, 3, 30, 3, 31, 6, 30] + ]; + + yield [ + 'path' => '[*][jobs][*][info]', + 'expected' => [ + ['experience' => 6, 'salary' => 34], + ['experience' => 3, 'salary' => 30], + ['experience' => 3, 'salary' => 31], + ['experience' => 6, 'salary' => 30], + ] + ]; + + yield [ + 'path' => '[0][\*]', + 'expected' => 'wildcard1' + ]; + + yield [ + 'path' => '[*][\*]', + 'expected' => ['wildcard1', 'wildcard2'] + ]; + } + + /** + * @dataProvider provideWildcardPaths + */ + public function testAccessorWithWildcard(string $path, string|array $expected): void + { + self::assertSame($expected, $this->propertyAccessor->getValue(self::TEST_ARRAY, $path)); + } + + public function testAccessorWithWildcardAndObject(): void + { + $array = self::TEST_ARRAY; + + $array[0]['class'] = new TestClass('foo'); + $array[1]['class'] = new TestClass('bar'); + + self::assertSame(['foo', 'bar'], $this->propertyAccessor->getValue($array, '[*][class].publicAccessor')); + + $array[0]['classes'] = [ + new TestClass('foo'), + new TestClass('bar'), + ]; + $array[1]['classes'] = [ + new TestClass('baz'), + new TestClass('qux'), + ]; + + self::assertSame(['foo', 'bar', 'baz', 'qux'], $this->propertyAccessor->getValue($array, '[*][classes][*].publicAccessor')); + } +} From fc90fb3207a0ccfa9a32bfd90e90ed538ed6317c Mon Sep 17 00:00:00 2001 From: Brajk19 Date: Fri, 24 Nov 2023 20:44:10 +0100 Subject: [PATCH 04/14] [PropertyAccess] update CHANGELOG.md --- src/Symfony/Component/PropertyAccess/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Component/PropertyAccess/CHANGELOG.md b/src/Symfony/Component/PropertyAccess/CHANGELOG.md index 0dacd605277bf..9dd43aed4a651 100644 --- a/src/Symfony/Component/PropertyAccess/CHANGELOG.md +++ b/src/Symfony/Component/PropertyAccess/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +7.1 +--- + +* Allow wildcard `[*]` usage for reading multiple values + 7.0 --- From 02cdfe9cfbb00ad26e53d07b86969987225cff5b Mon Sep 17 00:00:00 2001 From: Brajk19 Date: Fri, 24 Nov 2023 20:54:22 +0100 Subject: [PATCH 05/14] revert change --- src/Symfony/Component/Translation/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index 622c7f75dd04a..a825342022ee8 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -33,6 +33,10 @@ CHANGELOG * Add `--as-tree` option to `translation:pull` command to write YAML messages as a tree-like structure * [BC BREAK] Add argument `$buildDir` to `DataCollectorTranslator::warmUp()` * Add `DataCollectorTranslatorPass` and `LoggingTranslatorPass` (moved from `FrameworkBundle`) + +6.3 +--- + * Add `PhraseTranslationProvider` 6.2.7 From fa6b440a75e8f9006364e8d427aa701b8b5bb38c Mon Sep 17 00:00:00 2001 From: Brajk19 Date: Fri, 24 Nov 2023 21:30:19 +0100 Subject: [PATCH 06/14] fabbot fixes --- .../PropertyAccess/Tests/PropertyAccessorWildcardTest.php | 4 ++-- .../Component/PropertyAccess/Tests/PropertyPathTest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorWildcardTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorWildcardTest.php index a746bd91c02e4..cd7be59b6a2b8 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorWildcardTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorWildcardTest.php @@ -156,12 +156,12 @@ public static function provideWildcardPaths(): iterable /** * @dataProvider provideWildcardPaths */ - public function testAccessorWithWildcard(string $path, string|array $expected): void + public function testAccessorWithWildcard(string $path, string|array $expected) { self::assertSame($expected, $this->propertyAccessor->getValue(self::TEST_ARRAY, $path)); } - public function testAccessorWithWildcardAndObject(): void + public function testAccessorWithWildcardAndObject() { $array = self::TEST_ARRAY; diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php index 051cb771519da..fee45f888677f 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php @@ -205,7 +205,7 @@ public function testIsIndexDoesNotAcceptNegativeIndices() $propertyPath->isIndex(-1); } - public function testIsWildcard(): void + public function testIsWildcard() { $propertyPath = new PropertyPath('[*][parent][child].name'); From a1ceaebf507b54ad703dde1d7ca3b3d1ae363502 Mon Sep 17 00:00:00 2001 From: Brajk19 Date: Fri, 24 Nov 2023 21:31:14 +0100 Subject: [PATCH 07/14] fabbot fixes --- .../PropertyAccess/PropertyAccessor.php | 10 ++--- .../Tests/PropertyAccessorWildcardTest.php | 44 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 89ba5c10231b8..38bf16f58b8ff 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -331,12 +331,12 @@ private function readPropertiesUntil(array $zval, PropertyPathInterface $propert // replace wildcard with all posible values // e.g. [*][foo] becomes [0][foo], [1][foo], ... foreach (array_keys($zval[self::VALUE]) as $index) { - $path = preg_replace('/\[\*\]/', "[$index]", (string) ($propertyPath), 1); + $path = preg_replace('/\[\*\]/', "[$index]", (string) $propertyPath, 1); $subPath = $this->readPropertiesUntil($zval, $this->getPropertyPath($path), $lastIndex, $ignoreInvalidIndices, $i); // merge property values from all sub paths // skip first because it's same for all paths and is already in $propertyValues - for($j = 1; $j < count($subPath); $j++) { + for ($j = 1; $j < \count($subPath); ++$j) { $newPropertyValues[$j][self::VALUE][] = $subPath[$j][self::VALUE]; } } @@ -345,14 +345,14 @@ private function readPropertiesUntil(array $zval, PropertyPathInterface $propert $shouldMerge = true; foreach ($newValue[self::VALUE] as $value) { - $shouldMerge = is_array($value) && array_is_list($value); + $shouldMerge = \is_array($value) && array_is_list($value); - if(!$shouldMerge) { + if (!$shouldMerge) { break; } } - if($shouldMerge) { + if ($shouldMerge) { $newValue[self::VALUE] = array_merge(...$newValue[self::VALUE]); } } diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorWildcardTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorWildcardTest.php index cd7be59b6a2b8..4d24a28a2ed25 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorWildcardTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorWildcardTest.php @@ -35,15 +35,15 @@ protected function setUp(): void 'title' => 'chef', 'info' => [ 'experience' => 6, - 'salary' => 34 - ] + 'salary' => 34, + ], ], [ 'title' => 'waiter', 'info' => [ 'experience' => 3, - 'salary' => 30 - ] + 'salary' => 30, + ], ], ], 'info' => [ @@ -60,20 +60,20 @@ protected function setUp(): void 'title' => 'chef', 'info' => [ 'experience' => 3, - 'salary' => 31 - ] + 'salary' => 31, + ], ], [ 'title' => 'bartender', 'info' => [ 'experience' => 6, - 'salary' => 30 - ] + 'salary' => 30, + ], ], ], 'info' => [ 'age' => 28, - ] + ], ], ]; @@ -81,27 +81,27 @@ public static function provideWildcardPaths(): iterable { yield [ 'path' => '[*][id]', - 'expected' => [1, 2] + 'expected' => [1, 2], ]; yield [ 'path' => '[*][name]', - 'expected' => ['John', 'Luke'] + 'expected' => ['John', 'Luke'], ]; yield [ 'path' => '[*][languages]', - 'expected' => ['EN', 'EN', 'FR'] + 'expected' => ['EN', 'EN', 'FR'], ]; yield [ 'path' => '[*][info][age]', - 'expected' => [32, 28] + 'expected' => [32, 28], ]; yield [ 'path' => '[0][jobs][*][title]', - 'expected' => ['chef', 'waiter'] + 'expected' => ['chef', 'waiter'], ]; yield [ @@ -109,27 +109,27 @@ public static function provideWildcardPaths(): iterable 'expected' => [ ['experience' => 6, 'salary' => 34], ['experience' => 3, 'salary' => 30], - ] + ], ]; yield [ 'path' => '[0][jobs][*][info][experience]', - 'expected' => [6, 3] + 'expected' => [6, 3], ]; yield [ 'path' => '[*][jobs][0][title]', - 'expected' => ['chef', 'chef'] + 'expected' => ['chef', 'chef'], ]; yield [ 'path' => '[*][jobs][*][title]', - 'expected' => ['chef', 'waiter', 'chef', 'bartender'] + 'expected' => ['chef', 'waiter', 'chef', 'bartender'], ]; yield [ 'path' => '[*][jobs][*][info][*]', - 'expected' => [6, 34, 3, 30, 3, 31, 6, 30] + 'expected' => [6, 34, 3, 30, 3, 31, 6, 30], ]; yield [ @@ -139,17 +139,17 @@ public static function provideWildcardPaths(): iterable ['experience' => 3, 'salary' => 30], ['experience' => 3, 'salary' => 31], ['experience' => 6, 'salary' => 30], - ] + ], ]; yield [ 'path' => '[0][\*]', - 'expected' => 'wildcard1' + 'expected' => 'wildcard1', ]; yield [ 'path' => '[*][\*]', - 'expected' => ['wildcard1', 'wildcard2'] + 'expected' => ['wildcard1', 'wildcard2'], ]; } From 570dd67b36356387f4a89812b5fbf54d865223f5 Mon Sep 17 00:00:00 2001 From: Adrian Brajkovic <80004828+Brajk19@users.noreply.github.com> Date: Sat, 25 Nov 2023 00:05:12 +0100 Subject: [PATCH 08/14] Update src/Symfony/Component/PropertyAccess/PropertyPath.php Co-authored-by: Oskar Stark --- src/Symfony/Component/PropertyAccess/PropertyPath.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyPath.php b/src/Symfony/Component/PropertyAccess/PropertyPath.php index d4724e5cc93de..0e0eeac846e99 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyPath.php +++ b/src/Symfony/Component/PropertyAccess/PropertyPath.php @@ -58,7 +58,7 @@ class PropertyPath implements \IteratorAggregate, PropertyPathInterface private array $isNullSafe = []; /** - * Contains a Boolean for each property in $elements denoting whether this + * Contains a boolean for each property in $elements denoting whether this * element is wildcard or not. * * @var array From f4f7d8f42f1768f695a29c078c3c225a3673c7d7 Mon Sep 17 00:00:00 2001 From: Adrian Brajkovic <80004828+Brajk19@users.noreply.github.com> Date: Sun, 26 Nov 2023 18:29:52 +0100 Subject: [PATCH 09/14] Update src/Symfony/Component/PropertyAccess/PropertyAccessor.php Co-authored-by: Oskar Stark --- src/Symfony/Component/PropertyAccess/PropertyAccessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 38bf16f58b8ff..9fa8eee9b539e 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -291,7 +291,7 @@ private function readPropertiesUntil(array $zval, PropertyPathInterface $propert $isWildcard = false; if (method_exists($propertyPath, 'isWildcard')) { - // To be removed in symfony 8 once we are sure isNullSafe is always implemented. + // To be removed in Symfony 8 once we are sure isWildcard is always implemented. $isWildcard = $propertyPath->isWildcard($i); } else { trigger_deprecation('symfony/property-access', '7.1', 'The "%s()" method in class "%s" needs to be implemented in version 8.0, not defining it is deprecated.', 'isWildcard', PropertyPathInterface::class); From d450f9ab2eb5a29f82c1c29d24cde20ac38e65d2 Mon Sep 17 00:00:00 2001 From: Brajk19 Date: Sun, 26 Nov 2023 18:35:55 +0100 Subject: [PATCH 10/14] [PropertyAccess] require symfony/deprecation-contracts --- src/Symfony/Component/PropertyAccess/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyAccess/composer.json b/src/Symfony/Component/PropertyAccess/composer.json index 376ee7e1afd0d..872501b32a99d 100644 --- a/src/Symfony/Component/PropertyAccess/composer.json +++ b/src/Symfony/Component/PropertyAccess/composer.json @@ -17,7 +17,8 @@ ], "require": { "php": ">=8.2", - "symfony/property-info": "^6.4|^7.0" + "symfony/property-info": "^6.4|^7.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "require-dev": { "symfony/cache": "^6.4|^7.0" From 885d1661bd3bce13efd684b3f9acda19e553c142 Mon Sep 17 00:00:00 2001 From: Brajk19 Date: Sun, 26 Nov 2023 18:41:44 +0100 Subject: [PATCH 11/14] [PropertyAccess] Add @method phpdoc tag for isWildcard --- src/Symfony/Component/PropertyAccess/PropertyPathInterface.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/PropertyAccess/PropertyPathInterface.php b/src/Symfony/Component/PropertyAccess/PropertyPathInterface.php index 729a1c8017a18..013ae5daa6217 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyPathInterface.php +++ b/src/Symfony/Component/PropertyAccess/PropertyPathInterface.php @@ -16,6 +16,8 @@ * * @author Bernhard Schussek * + * @method bool isWildcard(int $index) Returns whether the element at the given index is wildcard. Not implementing it is deprecated since Symfony 7.1 + * * @extends \Traversable */ interface PropertyPathInterface extends \Traversable, \Stringable From c5a05445b18d656d97dcd8be974f4db001786240 Mon Sep 17 00:00:00 2001 From: Adrian Brajkovic Date: Fri, 10 Jan 2025 12:05:25 +0100 Subject: [PATCH 12/14] update PR for 7.3 --- src/Symfony/Component/PropertyAccess/CHANGELOG.md | 2 +- src/Symfony/Component/PropertyAccess/PropertyAccessor.php | 2 +- src/Symfony/Component/PropertyAccess/PropertyPathInterface.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/CHANGELOG.md b/src/Symfony/Component/PropertyAccess/CHANGELOG.md index 9dd43aed4a651..df0f22c860678 100644 --- a/src/Symfony/Component/PropertyAccess/CHANGELOG.md +++ b/src/Symfony/Component/PropertyAccess/CHANGELOG.md @@ -1,7 +1,7 @@ CHANGELOG ========= -7.1 +7.3 --- * Allow wildcard `[*]` usage for reading multiple values diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 9fa8eee9b539e..fc3b4c3cafaec 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -294,7 +294,7 @@ private function readPropertiesUntil(array $zval, PropertyPathInterface $propert // To be removed in Symfony 8 once we are sure isWildcard is always implemented. $isWildcard = $propertyPath->isWildcard($i); } else { - trigger_deprecation('symfony/property-access', '7.1', 'The "%s()" method in class "%s" needs to be implemented in version 8.0, not defining it is deprecated.', 'isWildcard', PropertyPathInterface::class); + trigger_deprecation('symfony/property-access', '7.3', 'The "%s()" method in class "%s" needs to be implemented in version 8.0, not defining it is deprecated.', 'isWildcard', PropertyPathInterface::class); } if ($isIndex) { diff --git a/src/Symfony/Component/PropertyAccess/PropertyPathInterface.php b/src/Symfony/Component/PropertyAccess/PropertyPathInterface.php index 013ae5daa6217..96a69d40d35e3 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyPathInterface.php +++ b/src/Symfony/Component/PropertyAccess/PropertyPathInterface.php @@ -16,7 +16,7 @@ * * @author Bernhard Schussek * - * @method bool isWildcard(int $index) Returns whether the element at the given index is wildcard. Not implementing it is deprecated since Symfony 7.1 + * @method bool isWildcard(int $index) Returns whether the element at the given index is wildcard. Not implementing it is deprecated since Symfony 7.3 * * @extends \Traversable */ From 53203a06612d2ddc6af1c4efc85e9906a579c518 Mon Sep 17 00:00:00 2001 From: Adrian Brajkovic Date: Fri, 10 Jan 2025 12:11:04 +0100 Subject: [PATCH 13/14] cleanup --- src/Symfony/Component/Translation/CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index a825342022ee8..622c7f75dd04a 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -33,10 +33,6 @@ CHANGELOG * Add `--as-tree` option to `translation:pull` command to write YAML messages as a tree-like structure * [BC BREAK] Add argument `$buildDir` to `DataCollectorTranslator::warmUp()` * Add `DataCollectorTranslatorPass` and `LoggingTranslatorPass` (moved from `FrameworkBundle`) - -6.3 ---- - * Add `PhraseTranslationProvider` 6.2.7 From 77ec853fffda361c53f8c372238dfc834683a368 Mon Sep 17 00:00:00 2001 From: Adrian Brajkovic Date: Fri, 10 Jan 2025 12:16:26 +0100 Subject: [PATCH 14/14] lint --- src/Symfony/Component/PropertyAccess/PropertyPath.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyPath.php b/src/Symfony/Component/PropertyAccess/PropertyPath.php index 0e0eeac846e99..557dc6e239d21 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyPath.php +++ b/src/Symfony/Component/PropertyAccess/PropertyPath.php @@ -223,7 +223,7 @@ public function isNullSafe(int $index): bool public function isWildcard(int $index): bool { if (!isset($this->isWildcard[$index])) { - throw new OutOfBoundsException(sprintf('The index "%s" is not within the property path.', $index)); + throw new OutOfBoundsException(\sprintf('The index "%s" is not within the property path.', $index)); } return $this->isWildcard[$index];