From fa7b65d7155ff164e16fd7d9bf50970c0298b0af Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Mon, 8 Feb 2021 17:28:32 +0100 Subject: [PATCH] Prefer property path instead of method name --- src/Admin/BaseFieldDescription.php | 56 +++++++++--------------- tests/Admin/BaseFieldDescriptionTest.php | 2 +- 2 files changed, 21 insertions(+), 37 deletions(-) diff --git a/src/Admin/BaseFieldDescription.php b/src/Admin/BaseFieldDescription.php index db509fd28c8..83c37a85602 100644 --- a/src/Admin/BaseFieldDescription.php +++ b/src/Admin/BaseFieldDescription.php @@ -18,6 +18,7 @@ use Sonata\AdminBundle\Exception\NoValueException; use Symfony\Component\PropertyAccess\Exception\ExceptionInterface; use Symfony\Component\PropertyAccess\PropertyAccess; +use Symfony\Component\PropertyAccess\PropertyPathInterface; /** * A FieldDescription hold the information about a field. A typical @@ -36,7 +37,7 @@ * - name (o) : the name used (label in the form, title in the list) * - link_parameters (o) : add link parameter to the related Admin class when * the Admin.generateUrl is called - * - accessor : the method or the method name to retrieve the related value + * - accessor : the method or the property path to retrieve the related value * - associated_tostring : (deprecated, use associated_property option) * the method to retrieve the "string" representation * of the collection element. @@ -425,47 +426,30 @@ public function getFieldValue($object, $fieldName) .' Use the "accessor" code instead', \E_USER_DEPRECATED ); - } - - // prefer method name given in the code option - // NEXT_MAJOR: Remove this line and uncomment the following - $getter = $this->getOption('accessor', $this->getOption('code')); -// $getter = $this->getOption('accessor'); - if ($getter) { - if (\is_callable($getter)) { - return $getter($object); - } - - if (!method_exists($object, $getter)) { - @trigger_error( - 'Passing a non-existing method in the "code" option is deprecated' - .' since sonata-project/admin-bundle 3.x and will throw an exception in 4.0.', - \E_USER_DEPRECATED - ); - // NEXT_MAJOR: Remove the deprecation and uncomment the next line. -// throw new \LogicException('The method "%s"() does not exist.', $getter); - } elseif (!\is_callable([$object, $getter])) { + $getter = $this->getOption('code'); + if ($this->getOption('parameters')) { @trigger_error( - 'Passing a non-callable method in the "code" option is deprecated' - .' since sonata-project/admin-bundle 3.x and will throw an exception in 4.0.', + 'The option "parameters" is deprecated since sonata-project/admin-bundle 3.x and will be removed in 4.0.', \E_USER_DEPRECATED ); - // NEXT_MAJOR: Remove the deprecation and uncomment the next line. -// throw new \LogicException('The method "%s"() does not have public access.', $getter); - } else { - if ($this->getOption('parameters')) { - @trigger_error( - 'The option "parameters" is deprecated since sonata-project/admin-bundle 3.x and will be removed in 4.0.', - \E_USER_DEPRECATED - ); + return $object->{$getter}(...$this->getOption('parameters')); + } - return $object->{$getter}(...$this->getOption('parameters')); - } + return $object->{$getter}(); + } - return $object->{$getter}(); - } + // prefer the method or the property path given in the code option + $accessor = $this->getOption('accessor', $fieldName); + if (\is_callable($accessor)) { + return $accessor($object); + } elseif (!\is_string($accessor)) { + throw new \TypeError(sprintf( + 'The option "accessor" must be a string, a callable or a %s, %s given.', + PropertyPathInterface::class, + \is_object($accessor) ? 'instance of '.\get_class($accessor) : \gettype($accessor) + )); } // NEXT_MAJOR: Remove the condition code and the else part @@ -475,7 +459,7 @@ public function getFieldValue($object, $fieldName) ->getPropertyAccessor(); try { - return $propertyAccesor->getValue($object, $fieldName); + return $propertyAccesor->getValue($object, $accessor); } catch (ExceptionInterface $exception) { throw new NoValueException( sprintf('Cannot access property "%s" in class "%s".', $this->getName(), \get_class($object)), diff --git a/tests/Admin/BaseFieldDescriptionTest.php b/tests/Admin/BaseFieldDescriptionTest.php index b9c26a2f676..2dfcfa5b900 100644 --- a/tests/Admin/BaseFieldDescriptionTest.php +++ b/tests/Admin/BaseFieldDescriptionTest.php @@ -188,7 +188,7 @@ public function testGetFieldValueWithNullObject(): void public function testGetFieldValueWithAccessor(): void { - $description = new FieldDescription('name', ['accessor' => 'getFoo']); + $description = new FieldDescription('name', ['accessor' => 'foo']); $mock = $this->getMockBuilder(\stdClass::class)->addMethods(['getFoo'])->getMock(); $mock->expects($this->once())->method('getFoo')->willReturn(42); $this->assertSame(42, $description->getFieldValue($mock, 'fake'));