diff --git a/src/core/etl/src/Flow/ETL/Row/Entry/Type/Uuid.php b/src/core/etl/src/Flow/ETL/Row/Entry/Type/Uuid.php index 9dd364d7a..52c8e2413 100644 --- a/src/core/etl/src/Flow/ETL/Row/Entry/Type/Uuid.php +++ b/src/core/etl/src/Flow/ETL/Row/Entry/Type/Uuid.php @@ -5,7 +5,7 @@ use Flow\ETL\Exception\InvalidArgumentException; use Flow\ETL\Exception\RuntimeException; -final class Uuid +final class Uuid implements \Stringable { /** * This regexp is a port of the Uuid library, @@ -44,6 +44,11 @@ public static function fromString(string $value) : self return new self($value); } + public function __toString() : string + { + return $this->toString(); + } + public function isEqual(self $type) : bool { return $this->toString() === $type->toString(); diff --git a/src/core/etl/src/Flow/ETL/Row/Reference/Expression/Cast.php b/src/core/etl/src/Flow/ETL/Row/Reference/Expression/Cast.php index c42934e61..13412db7f 100644 --- a/src/core/etl/src/Flow/ETL/Row/Reference/Expression/Cast.php +++ b/src/core/etl/src/Flow/ETL/Row/Reference/Expression/Cast.php @@ -44,11 +44,7 @@ public function eval(Row $row) : mixed 'int', 'integer' => (int) $value, /** @phpstan-ignore-next-line */ 'float', 'double', 'real' => (float) $value, - 'string' => match (\gettype($value)) { - 'object', 'array' => \json_encode($value, JSON_THROW_ON_ERROR), - /** @phpstan-ignore-next-line */ - default => (string) $value - }, + 'string' => $this->toString($value), 'bool', 'boolean' => (bool) $value, 'array' => $this->toArray($value), 'object' => (object) $value, @@ -68,6 +64,40 @@ private function toArray(mixed $data) : array return (array) $data; } + private function toString(mixed $value) : ?string + { + if ($value === null) { + return null; + } + + if (\is_string($value)) { + return $value; + } + + if (\is_bool($value)) { + return $value ? 'true' : 'false'; + } + + if (\is_array($value)) { + return \json_encode($value, JSON_THROW_ON_ERROR); + } + + if ($value instanceof \DateTimeInterface) { + return $value->format(\DateTimeInterface::RFC3339); + } + + if ($value instanceof \Stringable) { + return (string) $value; + } + + if ($value instanceof \DOMDocument) { + return $value->saveXML() ?: null; + } + + /** @phpstan-ignore-next-line */ + return (string) $value; + } + private function toXML(mixed $value) : null|\DOMDocument { if (\is_string($value)) { diff --git a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Reference/Expression/CastTest.php b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Reference/Expression/CastTest.php index 3219e4a24..ea22f4c70 100644 --- a/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Reference/Expression/CastTest.php +++ b/src/core/etl/tests/Flow/ETL/Tests/Unit/Row/Reference/Expression/CastTest.php @@ -7,6 +7,7 @@ use function Flow\ETL\DSL\cast; use function Flow\ETL\DSL\ref; use Flow\ETL\Row; +use Flow\ETL\Row\Entry\Type\Uuid; use Flow\ETL\Row\Factory\NativeEntryFactory; use PHPUnit\Framework\TestCase; @@ -17,6 +18,12 @@ public static function cast_provider() : array $xml = new \DOMDocument(); $xml->loadXML($xmlString = 'bar'); + $fullXMLString = <<<'XML' + +bar + +XML; + return [ 'invalid' => [null, 'int', null], 'int' => ['1', 'int', 1], @@ -34,6 +41,10 @@ public static function cast_provider() : array 'json_pretty' => [[1], 'json_pretty', "[\n 1\n]"], 'xml_to_array' => [$xml, 'array', ['root' => ['foo' => ['@attributes' => ['baz' => 'buz'], '@value' => 'bar']]]], 'string_to_xml' => [$xmlString, 'xml', $xml], + 'xml_to_string' => [$xml, 'string', $fullXMLString], + 'datetime' => [new \DateTimeImmutable('2023-01-01 00:00:00 UTC'), 'string', '2023-01-01T00:00:00+00:00'], + 'uuid' => [Uuid::fromString('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'), 'string', 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'], + 'bool_to_string' => [true, 'string', 'true'], ]; }