Skip to content
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
2 changes: 2 additions & 0 deletions rector.tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use Flow\ETL\FlowContext;
use Flow\Types\Type\Logical\DateTimeType;
use Flow\Types\Type\Logical\DateType;
use Flow\Types\Type\Logical\HTMLType;
use Flow\Types\Type\Logical\JsonType;
use Flow\Types\Type\Logical\ListType;
use Flow\Types\Type\Logical\MapType;
Expand Down Expand Up @@ -165,6 +166,7 @@
new NewObjectToFunction(UuidType::class, 'Flow\ETL\DSL\type_uuid'),
new NewObjectToFunction(XMLElementType::class, 'Flow\ETL\DSL\type_xml_element'),
new NewObjectToFunction(XMLType::class, 'Flow\ETL\DSL\type_xml'),
new NewObjectToFunction(HTMLType::class, 'Flow\ETL\DSL\type_html'),

// Extractors
new NewObjectToFunction(CacheExtractor::class, 'from_cache'),
Expand Down
10 changes: 10 additions & 0 deletions src/core/etl/src/Flow/ETL/DSL/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@
UnionType
};
use Flow\Types\Type\Types;
use Flow\Types\Value\HTMLDocument;
use UnitEnum;

/**
Expand Down Expand Up @@ -1957,6 +1958,15 @@ function json_schema(string $name, bool $nullable = false, ?Metadata $metadata =
return Definition::json($name, $nullable, $metadata);
}

/**
* @return Definition<HTMLDocument>
*/
#[DocumentationDSL(module: Module::CORE, type: DSLType::SCHEMA)]
function html_schema(string $name, bool $nullable = false, ?Metadata $metadata = null) : Definition
{
return Definition::html($name, $nullable, $metadata);
}

/**
* @return Definition<\DOMDocument>
*/
Expand Down
21 changes: 14 additions & 7 deletions src/core/etl/src/Flow/ETL/Row/EntryFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,16 @@ enum_entry,
uuid_entry,
xml_element_entry,
xml_entry};
use function Flow\Types\DSL\{type_date, type_datetime, type_json, type_optional, type_string, type_time, type_uuid, type_xml, type_xml_element};
use function Flow\Types\DSL\{type_date,
type_datetime,
type_html,
type_json,
type_optional,
type_string,
type_time,
type_uuid,
type_xml,
type_xml_element};
use Flow\ETL\Exception\{InvalidArgumentException,
RuntimeException,
SchemaDefinitionNotFoundException};
Expand Down Expand Up @@ -91,13 +100,11 @@ public function create(string $entryName, mixed $value, Schema|Definition|null $

if ($stringChecker->isJson()) {
$valueType = type_json();
}

if ($stringChecker->isUuid()) {
} elseif ($stringChecker->isUuid()) {
$valueType = type_uuid();
}

if ($stringChecker->isXML()) {
} elseif ($stringChecker->isHTML()) {
$valueType = type_html();
} elseif ($stringChecker->isXML()) {
$valueType = type_xml();
}
}
Expand Down
34 changes: 32 additions & 2 deletions src/core/etl/src/Flow/ETL/Schema/Definition.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,35 @@
namespace Flow\ETL\Schema;

use function Flow\ETL\DSL\is_nullable;
use function Flow\Types\DSL\{type_array, type_boolean, type_date, type_datetime, type_enum, type_equals, type_float, type_integer, type_is, type_is_any, type_json, type_list, type_map, type_mixed, type_optional, type_string, type_structure, type_time, type_uuid, type_xml, type_xml_element, types};
use function Flow\Types\DSL\{type_array,
type_boolean,
type_date,
type_datetime,
type_enum,
type_equals,
type_float,
type_html,
type_integer,
type_is,
type_is_any,
type_json,
type_list,
type_map,
type_mixed,
type_optional,
type_string,
type_structure,
type_time,
type_uuid,
type_xml,
type_xml_element,
types};
use Flow\ETL\Exception\{InvalidArgumentException, RuntimeException};
use Flow\ETL\Row\{Entry, EntryReference, Reference};
use Flow\Types\Type;
use Flow\Types\Type\Logical\{ListType, MapType, OptionalType, StructureType};
use Flow\Types\Type\{Native\FloatType, Native\IntegerType, Native\UnionType, TypeFactory};
use Flow\Types\Value\Uuid;
use Flow\Types\Value\{HTMLDocument, Uuid};

/**
* @template-covariant T
Expand Down Expand Up @@ -117,6 +139,14 @@ public static function fromArray(array $definition) : self
);
}

/**
* @return Definition<HTMLDocument>
*/
public static function html(string|Reference $entry, bool $nullable = false, ?Metadata $metadata = null) : self
{
return new self($entry, type_html(), $nullable, $metadata);
}

/**
* @return Definition<int>
*/
Expand Down
23 changes: 13 additions & 10 deletions src/core/etl/src/Flow/ETL/Schema/Formatter/PHPSchemaFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
UuidType,
XMLElementType,
XMLType};
use Flow\Types\Type\Logical\HTMLType;
use Flow\Types\Type\Native\{BooleanType, EnumType, FloatType, IntegerType, StringType};

final readonly class PHPSchemaFormatter implements SchemaFormatter
Expand Down Expand Up @@ -114,6 +115,7 @@ private function formatSchema(Schema $schema, int $level = 1) : string
TimeType::class,
JsonType::class,
UuidType::class,
HTMLType::class,
XMLType::class,
XMLElementType::class,
DateTimeType::class => $this->simpleType($definition),
Expand Down Expand Up @@ -174,16 +176,17 @@ private function mapType(Definition $definition) : string
private function simpleType(Definition $definition) : string
{
$reflection = match ($definition->type()::class) {
StringType::class => new \ReflectionFunction("\Flow\ETL\DSL\string_schema"),
IntegerType::class => new \ReflectionFunction("\Flow\ETL\DSL\integer_schema"),
BooleanType::class => new \ReflectionFunction("\Flow\ETL\DSL\bool_schema"),
DateType::class => new \ReflectionFunction("\Flow\ETL\DSL\date_schema"),
DateTimeType::class => new \ReflectionFunction("\Flow\ETL\DSL\datetime_schema"),
TimeType::class => new \ReflectionFunction("\Flow\ETL\DSL\\time_schema"),
JsonType::class => new \ReflectionFunction("\Flow\ETL\DSL\\json_schema"),
UuidType::class => new \ReflectionFunction("\Flow\ETL\DSL\\uuid_schema"),
XMLType::class => new \ReflectionFunction("\Flow\ETL\DSL\\xml_schema"),
XMLElementType::class => new \ReflectionFunction("\Flow\ETL\DSL\\xml_element_schema"),
StringType::class => new \ReflectionFunction('\Flow\ETL\DSL\string_schema'),
IntegerType::class => new \ReflectionFunction('\Flow\ETL\DSL\integer_schema'),
BooleanType::class => new \ReflectionFunction('\Flow\ETL\DSL\bool_schema'),
DateType::class => new \ReflectionFunction('\Flow\ETL\DSL\date_schema'),
DateTimeType::class => new \ReflectionFunction('\Flow\ETL\DSL\datetime_schema'),
TimeType::class => new \ReflectionFunction('\Flow\ETL\DSL\time_schema'),
JsonType::class => new \ReflectionFunction('\Flow\ETL\DSL\json_schema'),
UuidType::class => new \ReflectionFunction('\Flow\ETL\DSL\uuid_schema'),
XMLType::class => new \ReflectionFunction('\Flow\ETL\DSL\xml_schema'),
XMLElementType::class => new \ReflectionFunction('\Flow\ETL\DSL\xml_element_schema'),
HTMLType::class => new \ReflectionFunction('\Flow\ETL\DSL\html_schema'),
default => throw new RuntimeException('Type ' . $definition->type()->toString() . ' is not a simple definition'),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public static function cast_provider() : array
'xml_to_array' => [$xml, 'array', ['root' => ['foo' => ['@attributes' => ['baz' => 'buz'], '@value' => 'bar']]]],
'string_to_xml' => [$xmlString, 'xml', $xml],
'xml_to_string' => [$xml, 'string', '<root><foo baz="buz">bar</foo></root>'],
'full_xml_to_string' => [$fullXMLString, 'string', '<root><foo baz="buz">bar</foo></root>'],
'datetime' => [new \DateTimeImmutable('2023-01-01 00:00:00 UTC'), 'string', '2023-01-01T00:00:00+00:00'],
'datetime_to_date' => [new \DateTimeImmutable('2023-01-01 00:01:00 UTC'), 'date', new \DateTimeImmutable('2023-01-01T00:00:00+00:00')],
'string_to_timezone' => ['UTC', 'timezone', new \DateTimeZone('UTC')],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ enum_schema,
use function Flow\Types\DSL\{type_datetime, type_float, type_integer, type_list, type_map, type_string, type_structure, type_time_zone};
use Flow\ETL\Exception\{InvalidArgumentException, SchemaDefinitionNotFoundException};
use Flow\ETL\Row\Entry\TimeEntry;
use Flow\ETL\Row\EntryFactory;
use Flow\ETL\Row\{Entry, EntryFactory};
use Flow\ETL\Schema\Metadata;
use Flow\ETL\Tests\Fixtures\Enum\BackedIntEnum;
use PHPUnit\Framework\Attributes\DataProvider;
Expand All @@ -47,6 +47,24 @@ final class EntryFactoryTest extends TestCase
{
private EntryFactory $entryFactory;

public static function provide_recognized_data() : \Generator
{
yield 'json' => [
$json = '{"id":1}',
json_entry('e', $json),
];

yield 'xml' => [
$xml = '<root><foo>1</foo><bar>2</bar><baz>3</baz></root>',
xml_entry('e', $xml),
];

yield 'uuid' => [
$uuid = '00000000-0000-0000-0000-000000000000',
uuid_entry('e', $uuid),
];
}

public static function provide_unrecognized_data() : \Generator
{
yield 'json alike' => [
Expand Down Expand Up @@ -369,6 +387,18 @@ public function test_object() : void
$this->entryFactory->create('e', new \ArrayIterator([1, 2]));
}

/**
* @param Entry<mixed> $entry
*/
#[DataProvider('provide_recognized_data')]
public function test_recognized_data_set_same_as_provided(string $input, Entry $entry) : void
{
self::assertEquals(
$entry,
$this->entryFactory->create('e', $input)
);
}

public function test_string() : void
{
self::assertEquals(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
datetime_schema,
enum_schema,
float_schema,
html_schema,
int_schema,
json_schema,
list_schema,
Expand Down Expand Up @@ -107,6 +108,7 @@ public function test_formatting_simple_schema() : void
\\Flow\\ETL\\DSL\\uuid_schema("uuid", nullable: true, metadata: \\Flow\\ETL\\DSL\\schema_metadata()),
\\Flow\\ETL\\DSL\\xml_schema("xml", nullable: true, metadata: \\Flow\\ETL\\DSL\\schema_metadata()),
\\Flow\\ETL\\DSL\\xml_element_schema("xml_element", nullable: true, metadata: \\Flow\\ETL\\DSL\\schema_metadata()),
\\Flow\\ETL\\DSL\\html_schema("html", nullable: true, metadata: \\Flow\\ETL\\DSL\\schema_metadata()),
);
PHP,
(new PHPSchemaFormatter())->format(schema(
Expand All @@ -120,6 +122,7 @@ public function test_formatting_simple_schema() : void
uuid_schema('uuid', nullable: true),
xml_schema('xml', nullable: true),
xml_element_schema('xml_element', nullable: true),
html_schema('html', nullable: true),
))
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
namespace Flow\ETL\Tests\Unit\Transformer;

use function Flow\ETL\DSL\{array_to_rows, config, flow_context};
use Flow\ETL\Tests\FlowTestCase;
use Flow\ETL\Transformer\AutoCastTransformer;
use Flow\Types\Type\AutoCaster;
use PHPUnit\Framework\TestCase;

final class AutoCastTransformerTest extends FlowTestCase
final class AutoCastTransformerTest extends TestCase
{
public function test_transforming_row() : void
{
Expand Down
12 changes: 11 additions & 1 deletion src/lib/types/src/Flow/Types/DSL/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
UuidType,
XMLElementType,
XMLType};
use Flow\Types\Type\Logical\HTMLType;
use Flow\Types\Type\Native\{ArrayType,
BooleanType,
CallableType,
Expand All @@ -39,7 +40,7 @@
ResourceType,
StringType,
UnionType};
use Flow\Types\Value\Uuid;
use Flow\Types\Value\{HTMLDocument, Uuid};
use UnitEnum;

/**
Expand Down Expand Up @@ -435,6 +436,15 @@ function type_literal(bool|float|int|string $value) : LiteralType
return new LiteralType($value);
}

/**
* @return Type<HTMLDocument>
*/
#[DocumentationDSL(module: Module::TYPES, type: DSLType::TYPE)]
function type_html() : Type
Comment thread
stloyd marked this conversation as resolved.
{
return new HTMLType();
}

/**
* @template T
*
Expand Down
62 changes: 62 additions & 0 deletions src/lib/types/src/Flow/Types/Type/Logical/HTMLType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

namespace Flow\Types\Type\Logical;

use Flow\Types\Exception\{CastingException, InvalidTypeException};
use Flow\Types\Type;
use Flow\Types\Value\HTMLDocument;

/**
* @implements Type<HTMLDocument>
*/
final readonly class HTMLType implements Type
{
public function assert(mixed $value) : HTMLDocument
{
if ($this->isValid($value)) {
return $value;
}

throw InvalidTypeException::value($value, $this);
}

public function cast(mixed $value) : HTMLDocument
{
if ($this->isValid($value)) {
return $value;
}

if (\is_string($value)) {
return new HTMLDocument($value);
}

if ($value instanceof \DOMDocument) {
return new HTMLDocument($value);
}

if (\is_object($value) && \is_a($value, 'Dom\HTMLDocument')) {
return new HTMLDocument($value);
}

throw new CastingException($value, $this);
}

public function isValid(mixed $value) : bool
{
return $value instanceof HTMLDocument;
}

public function normalize() : array
{
return [
'type' => 'html',
];
}

public function toString() : string
{
return 'html';
}
}
Loading