Skip to content

Commit

Permalink
Use propertyAccessor
Browse files Browse the repository at this point in the history
  • Loading branch information
VincentLanglet committed Jan 22, 2021
1 parent be53d10 commit dbf9e0f
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 12 deletions.
66 changes: 59 additions & 7 deletions src/Admin/BaseFieldDescription.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
use Doctrine\Inflector\Inflector;
use Doctrine\Inflector\InflectorFactory;
use Sonata\AdminBundle\Exception\NoValueException;
use Symfony\Component\PropertyAccess\Exception\ExceptionInterface;
use Symfony\Component\PropertyAccess\PropertyAccess;

/**
* A FieldDescription hold the information about a field. A typical
Expand Down Expand Up @@ -416,25 +418,75 @@ public function getFieldValue($object, $fieldName)
return $this->getFieldValue($child, substr($fieldName, $dotPos + 1));
}

$getters = [];
$parameters = [];

// prefer method name given in the code option
if ($this->getOption('code')) {
$getters[] = $this->getOption('code');
$getter = $this->getOption('code');

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])) {
@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.',
\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}();
}
}
// parameters for the method given in the code option
if ($this->getOption('parameters')) {
$parameters = $this->getOption('parameters');

// NEXT_MAJOR: Remove the condition code and the else part
if (!$this->getOption('parameters')) {
$propertyAccesor = PropertyAccess::createPropertyAccessorBuilder()
->enableMagicCall()
->getPropertyAccessor();

try {
return $propertyAccesor->getValue($object, $fieldName);
} catch (ExceptionInterface $exception) {
throw new NoValueException(
sprintf('Cannot access property "%s" in class "%s".', $this->getName(), \get_class($object)),
$exception->getCode(),
$exception
);
}
}

@trigger_error(
'The option "parameters" is deprecated since sonata-project/admin-bundle 3.x and will be removed in 4.0.',
\E_USER_DEPRECATED
);

$getters = [];
$parameters = $this->getOption('parameters');

if (\is_string($fieldName) && '' !== $fieldName) {
if ($this->hasCachedFieldGetter($object, $fieldName)) {
return $this->callCachedGetter($object, $fieldName, $parameters);
}

$camelizedFieldName = InflectorFactory::create()->build()->classify($fieldName);

$getters[] = lcfirst($camelizedFieldName);
$getters[] = sprintf('get%s', $camelizedFieldName);
$getters[] = sprintf('is%s', $camelizedFieldName);
$getters[] = sprintf('has%s', $camelizedFieldName);
Expand Down
13 changes: 8 additions & 5 deletions tests/Admin/BaseFieldDescriptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
use Sonata\AdminBundle\Admin\BaseFieldDescription;
use Sonata\AdminBundle\Exception\NoValueException;
use Sonata\AdminBundle\Tests\Fixtures\Admin\FieldDescription;
use Sonata\AdminBundle\Tests\Fixtures\Entity\Foo;
use Sonata\AdminBundle\Tests\Fixtures\Entity\FooCall;
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;

Expand Down Expand Up @@ -195,6 +194,11 @@ public function testGetFieldValueWithCode(): void
$this->assertSame(42, $description->getFieldValue($mock, 'fake'));
}

/**
* NEXT_MAJOR: Remove this test.
*
* @group legacy
*/
public function testGetFieldValueWithParametersForGetter(): void
{
$arg1 = 38;
Expand All @@ -206,6 +210,7 @@ public function testGetFieldValueWithParametersForGetter(): void
$mock1 = $this->getMockBuilder(\stdClass::class)->addMethods(['getWithOneParameter'])->getMock();
$mock1->expects($this->once())->method('getWithOneParameter')->with($arg1)->willReturn($arg1 + 2);

$this->expectDeprecation('The option "parameters" is deprecated since sonata-project/admin-bundle 3.x and will be removed in 4.0.');
$this->assertSame(40, $description1->getFieldValue($mock1, 'fake'));

$arg2 = 4;
Expand All @@ -221,15 +226,13 @@ public function testGetFieldValueWithParametersForGetter(): void

public function testGetFieldValueWithMagicCall(): void
{
$parameters = ['foo', 'bar'];
$foo = new FooCall();

$description = new FieldDescription('name');
$description->setOption('parameters', $parameters);
$this->assertSame(['fake', $parameters], $description->getFieldValue($foo, 'fake'));
$this->assertSame(['getFake', []], $description->getFieldValue($foo, 'fake'));

// repeating to cover retrieving cached getter
$this->assertSame(['fake', $parameters], $description->getFieldValue($foo, 'fake'));
$this->assertSame(['getFake', []], $description->getFieldValue($foo, 'fake'));
}

/**
Expand Down

0 comments on commit dbf9e0f

Please sign in to comment.