From 221772f614a45519f3a7f434e13e8e94fb456ffd Mon Sep 17 00:00:00 2001 From: Javier Spagnoletti Date: Sat, 21 Oct 2023 20:40:57 -0300 Subject: [PATCH] Allow to extract values from enum types at `AbstractPropertySourceIterator::getValue()` --- src/Source/AbstractPropertySourceIterator.php | 15 ++++- src/Source/DoctrineORMQuerySourceIterator.php | 5 +- .../AbstractPropertySourceIteratorTest.php | 62 ++++++++++--------- tests/Source/Fixtures/Element.php | 22 +++++++ tests/Source/Fixtures/Suit.php | 22 +++++++ 5 files changed, 95 insertions(+), 31 deletions(-) create mode 100644 tests/Source/Fixtures/Element.php create mode 100644 tests/Source/Fixtures/Suit.php diff --git a/src/Source/AbstractPropertySourceIterator.php b/src/Source/AbstractPropertySourceIterator.php index 21b0de0a..830be23e 100644 --- a/src/Source/AbstractPropertySourceIterator.php +++ b/src/Source/AbstractPropertySourceIterator.php @@ -43,7 +43,8 @@ abstract class AbstractPropertySourceIterator implements \Iterator */ public function __construct( protected array $fields, - protected string $dateTimeFormat = 'r' + protected string $dateTimeFormat = 'r', + protected bool $useBackedEnumValue = true ) { $this->propertyAccessor = PropertyAccess::createPropertyAccessor(); } @@ -85,6 +86,16 @@ public function getDateTimeFormat(): string return $this->dateTimeFormat; } + public function useBackedEnumValue(bool $useBackedEnumValue): void + { + $this->useBackedEnumValue = $useBackedEnumValue; + } + + public function isBackedEnumValueInUse(): bool + { + return $this->useBackedEnumValue; + } + protected function getIterator(): \Iterator { if (null === $this->iterator) { @@ -126,6 +137,8 @@ protected function getValue(mixed $value): bool|int|float|string|null $value instanceof \Traversable => '['.implode(', ', array_map([$this, 'getValue'], iterator_to_array($value))).']', $value instanceof \DateTimeInterface => $value->format($this->dateTimeFormat), $value instanceof \DateInterval => $this->getDuration($value), + $value instanceof \BackedEnum && $this->useBackedEnumValue => $value->value, + $value instanceof \UnitEnum => $value->name, \is_object($value) => method_exists($value, '__toString') ? (string) $value : null, default => $value, }; diff --git a/src/Source/DoctrineORMQuerySourceIterator.php b/src/Source/DoctrineORMQuerySourceIterator.php index eca43b94..47fe2cf0 100644 --- a/src/Source/DoctrineORMQuerySourceIterator.php +++ b/src/Source/DoctrineORMQuerySourceIterator.php @@ -26,7 +26,8 @@ public function __construct( Query $query, array $fields, string $dateTimeFormat = 'r', - private int $batchSize = 100 + private int $batchSize = 100, + bool $useBackedEnumValue = true, ) { $this->query = clone $query; $this->query->setParameters($query->getParameters()); @@ -34,7 +35,7 @@ public function __construct( $this->query->setHint($name, $value); } - parent::__construct($fields, $dateTimeFormat); + parent::__construct($fields, $dateTimeFormat, $useBackedEnumValue); } /** diff --git a/tests/Source/AbstractPropertySourceIteratorTest.php b/tests/Source/AbstractPropertySourceIteratorTest.php index 620cc8dc..bb267c84 100644 --- a/tests/Source/AbstractPropertySourceIteratorTest.php +++ b/tests/Source/AbstractPropertySourceIteratorTest.php @@ -15,16 +15,18 @@ use PHPUnit\Framework\TestCase; use Sonata\Exporter\Source\AbstractPropertySourceIterator; +use Sonata\Exporter\Tests\Source\Fixtures\Element; use Sonata\Exporter\Tests\Source\Fixtures\ObjectWithToString; +use Sonata\Exporter\Tests\Source\Fixtures\Suit; final class AbstractPropertySourceIteratorTest extends TestCase { /** * @dataProvider provideGetValueCases */ - public function testGetValue(mixed $value, mixed $expected, string $dateFormat = 'r'): void + public function testGetValue(mixed $value, mixed $expected, string $dateFormat = 'r', bool $useBackedEnumValue = true): void { - $iterator = new class([], $dateFormat) extends AbstractPropertySourceIterator { + $iterator = new class([], $dateFormat, $useBackedEnumValue) extends AbstractPropertySourceIterator { public function rewind(): void { $this->iterator = new \ArrayIterator(); @@ -48,32 +50,36 @@ public function provideGetValueCases(): iterable $datetime = new \DateTime(); $dateTimeImmutable = new \DateTimeImmutable(); - $data = [ - [[1, 2, 3], '[1, 2, 3]'], - [new \ArrayIterator([1, 2, 3]), '[1, 2, 3]'], - [(static function (): \Generator { yield from [1, 2, 3]; })(), '[1, 2, 3]'], - [$datetime, $datetime->format('r')], - [$datetime, $datetime->format('Y-m-d H:i:s'), 'Y-m-d H:i:s'], - [123, 123], - ['123', '123'], - [new ObjectWithToString('object with to string'), 'object with to string'], - [$dateTimeImmutable, $dateTimeImmutable->format('r')], - [$dateTimeImmutable, $dateTimeImmutable->format('Y-m-d H:i:s'), 'Y-m-d H:i:s'], - [new \DateInterval('P1Y'), 'P1Y'], - [new \DateInterval('P1M'), 'P1M'], - [new \DateInterval('P1D'), 'P1D'], - [new \DateInterval('PT1H'), 'PT1H'], - [new \DateInterval('PT1M'), 'PT1M'], - [new \DateInterval('PT1S'), 'PT1S'], - [new \DateInterval('P1Y1M'), 'P1Y1M'], - [new \DateInterval('P1Y1M1D'), 'P1Y1M1D'], - [new \DateInterval('P1Y1M1DT1H'), 'P1Y1M1DT1H'], - [new \DateInterval('P1Y1M1DT1H1M'), 'P1Y1M1DT1H1M'], - [new \DateInterval('P1Y1M1DT1H1M1S'), 'P1Y1M1DT1H1M1S'], - [new \DateInterval('P0Y'), 'P0Y'], - [new \DateInterval('PT0S'), 'P0Y'], - ]; + yield [[1, 2, 3], '[1, 2, 3]']; + yield [new \ArrayIterator([1, 2, 3]), '[1, 2, 3]']; + yield [(static function (): \Generator { yield from [1, 2, 3]; })(), '[1, 2, 3]']; + yield [$datetime, $datetime->format('r')]; + yield [$datetime, $datetime->format('Y-m-d H:i:s'), 'Y-m-d H:i:s']; + yield [123, 123]; + yield ['123', '123']; + yield [new ObjectWithToString('object with to string'), 'object with to string']; + yield [$dateTimeImmutable, $dateTimeImmutable->format('r')]; + yield [$dateTimeImmutable, $dateTimeImmutable->format('Y-m-d H:i:s'), 'Y-m-d H:i:s']; + yield [new \DateInterval('P1Y'), 'P1Y']; + yield [new \DateInterval('P1M'), 'P1M']; + yield [new \DateInterval('P1D'), 'P1D']; + yield [new \DateInterval('PT1H'), 'PT1H']; + yield [new \DateInterval('PT1M'), 'PT1M']; + yield [new \DateInterval('PT1S'), 'PT1S']; + yield [new \DateInterval('P1Y1M'), 'P1Y1M']; + yield [new \DateInterval('P1Y1M1D'), 'P1Y1M1D']; + yield [new \DateInterval('P1Y1M1DT1H'), 'P1Y1M1DT1H']; + yield [new \DateInterval('P1Y1M1DT1H1M'), 'P1Y1M1DT1H1M']; + yield [new \DateInterval('P1Y1M1DT1H1M1S'), 'P1Y1M1DT1H1M1S']; + yield [new \DateInterval('P0Y'), 'P0Y']; + yield [new \DateInterval('PT0S'), 'P0Y']; - return $data; + if (\PHP_VERSION_ID < 80100) { + return; + } + + yield [Element::Hydrogen, 'Hydrogen']; + yield [Suit::Diamonds, 'D']; + yield [Suit::Diamonds, 'Diamonds', 'r', false]; } } diff --git a/tests/Source/Fixtures/Element.php b/tests/Source/Fixtures/Element.php new file mode 100644 index 00000000..d3cb35da --- /dev/null +++ b/tests/Source/Fixtures/Element.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\Exporter\Tests\Source\Fixtures; + +enum Element +{ + case Carbon; + case Helium; + case Hydrogen; + case Lithium; +} diff --git a/tests/Source/Fixtures/Suit.php b/tests/Source/Fixtures/Suit.php new file mode 100644 index 00000000..fa5bc3aa --- /dev/null +++ b/tests/Source/Fixtures/Suit.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Sonata\Exporter\Tests\Source\Fixtures; + +enum Suit: string +{ + case Clubs = 'C'; + case Diamonds = 'D'; + case Hearts = 'H'; + case Spades = 'S'; +}