Skip to content

Commit

Permalink
Allow to extract values from enum types at `AbstractPropertySourceIte…
Browse files Browse the repository at this point in the history
…rator::getValue()`
  • Loading branch information
phansys committed Oct 23, 2023
1 parent e3be944 commit 3b48cec
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 34 deletions.
15 changes: 14 additions & 1 deletion src/Source/AbstractPropertySourceIterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
};
Expand Down
5 changes: 3 additions & 2 deletions src/Source/DoctrineODMQuerySourceIterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ public function __construct(
Query $query,
array $fields,
string $dateTimeFormat = \DateTimeInterface::ATOM,
private int $batchSize = 100
private int $batchSize = 100,
bool $useBackedEnumValue = true
) {
$this->query = clone $query;

parent::__construct($fields, $dateTimeFormat);
parent::__construct($fields, $dateTimeFormat, $useBackedEnumValue);
}

/**
Expand Down
5 changes: 3 additions & 2 deletions src/Source/DoctrineORMQuerySourceIterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ 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());
foreach ($query->getHints() as $name => $value) {
$this->query->setHint($name, $value);
}

parent::__construct($fields, $dateTimeFormat);
parent::__construct($fields, $dateTimeFormat, $useBackedEnumValue);
}

/**
Expand Down
64 changes: 35 additions & 29 deletions tests/Source/AbstractPropertySourceIteratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -41,39 +43,43 @@ public function getValue(mixed $value): bool|int|float|string|null
}

/**
* @return iterable<array{0: mixed, 1: mixed, 2?: string}>
* @return iterable<array{0: mixed, 1: mixed, 2?: string, 3?: bool}>
*/
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];
}
}
22 changes: 22 additions & 0 deletions tests/Source/Fixtures/Element.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* 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;
}
22 changes: 22 additions & 0 deletions tests/Source/Fixtures/Suit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Sonata Project package.
*
* (c) Thomas Rabaix <[email protected]>
*
* 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';
}

0 comments on commit 3b48cec

Please sign in to comment.