Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use propertyAccessor for BaseFieldDescription::getFieldValue #6798

Merged
merged 1 commit into from
Jan 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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'
phansys marked this conversation as resolved.
Show resolved Hide resolved
.' 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