Skip to content

Commit 4207405

Browse files
committed
Add a new HTMLElementEntry & related stuff
1 parent 709d414 commit 4207405

24 files changed

Lines changed: 546 additions & 52 deletions

File tree

rector.tests.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use Flow\ETL\FlowContext;
2828
use Flow\Types\Type\Logical\DateTimeType;
2929
use Flow\Types\Type\Logical\DateType;
30+
use Flow\Types\Type\Logical\HTMLElementType;
3031
use Flow\Types\Type\Logical\HTMLType;
3132
use Flow\Types\Type\Logical\JsonType;
3233
use Flow\Types\Type\Logical\ListType;
@@ -171,6 +172,7 @@
171172
new NewObjectToFunction(XMLElementType::class, 'Flow\ETL\DSL\type_xml_element'),
172173
new NewObjectToFunction(XMLType::class, 'Flow\ETL\DSL\type_xml'),
173174
new NewObjectToFunction(HTMLType::class, 'Flow\ETL\DSL\type_html'),
175+
new NewObjectToFunction(HTMLElementType::class, 'Flow\ETL\DSL\type_html_element'),
174176

175177
// Extractors
176178
new NewObjectToFunction(CacheExtractor::class, 'from_cache'),

src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/SchemaConverter.php

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,14 @@
66

77
use function Flow\Types\DSL\type_string;
88
use Doctrine\DBAL\Schema\{Column, Index, Table};
9-
use Doctrine\DBAL\Types\{DateImmutableType, DateTimeImmutableType, GuidType, TimeImmutableType};
109
use Doctrine\DBAL\Types\Type as DbalType;
1110
use Flow\ETL\Exception\InvalidArgumentException;
1211
use Flow\ETL\Schema;
1312
use Flow\ETL\Schema\{Definition, Metadata};
1413
use Flow\Types\Type;
15-
use Flow\Types\Type\Logical\{DateTimeType,
16-
DateType,
17-
JsonType,
18-
ListType,
19-
MapType,
20-
StructureType,
21-
TimeType,
22-
UuidType,
23-
XMLElementType,
24-
XMLType};
25-
use Flow\Types\Type\Native\{BooleanType, FloatType, IntegerType, StringType};
2614

2715
final readonly class SchemaConverter
2816
{
29-
public const DEFAULT_TYPES = [
30-
StringType::class => \Doctrine\DBAL\Types\StringType::class,
31-
IntegerType::class => \Doctrine\DBAL\Types\IntegerType::class,
32-
FloatType::class => \Doctrine\DBAL\Types\FloatType::class,
33-
BooleanType::class => \Doctrine\DBAL\Types\BooleanType::class,
34-
DateType::class => DateImmutableType::class,
35-
TimeType::class => TimeImmutableType::class,
36-
DateTimeType::class => DateTimeImmutableType::class,
37-
UuidType::class => GuidType::class,
38-
JsonType::class => \Doctrine\DBAL\Types\JsonType::class,
39-
XMLType::class => \Doctrine\DBAL\Types\StringType::class,
40-
XMLElementType::class => \Doctrine\DBAL\Types\StringType::class,
41-
ListType::class => \Doctrine\DBAL\Types\JsonType::class,
42-
MapType::class => \Doctrine\DBAL\Types\JsonType::class,
43-
StructureType::class => \Doctrine\DBAL\Types\JsonType::class,
44-
];
45-
4617
private TypesMap $typesMap;
4718

4819
/**

src/adapter/etl-adapter-doctrine/src/Flow/ETL/Adapter/Doctrine/TypesMap.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use Flow\Types\Type as FlowType;
1111
use Flow\Types\Type\Logical\{DateTimeType,
1212
DateType,
13+
HTMLElementType,
14+
HTMLType,
1315
JsonType,
1416
ListType,
1517
MapType,
@@ -63,6 +65,8 @@ final class TypesMap
6365
JsonType::class => \Doctrine\DBAL\Types\JsonType::class,
6466
XMLType::class => \Doctrine\DBAL\Types\StringType::class,
6567
XMLElementType::class => \Doctrine\DBAL\Types\StringType::class,
68+
HTMLType::class => \Doctrine\DBAL\Types\StringType::class,
69+
HTMLElementType::class => \Doctrine\DBAL\Types\StringType::class,
6670
ListType::class => \Doctrine\DBAL\Types\JsonType::class,
6771
MapType::class => \Doctrine\DBAL\Types\JsonType::class,
6872
StructureType::class => \Doctrine\DBAL\Types\JsonType::class,

src/adapter/etl-adapter-doctrine/tests/Flow/ETL/Adapter/Doctrine/Tests/Unit/TypesMapTest.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,18 @@
88
use Doctrine\DBAL\Types\DateTimeTzType;
99
use Flow\ETL\Adapter\Doctrine\TypesMap;
1010
use Flow\ETL\Exception\InvalidArgumentException;
11-
use Flow\Types\Type\Logical\{DateTimeType, DateType, JsonType, ListType, MapType, StructureType, TimeType, UuidType, XMLElementType, XMLType};
11+
use Flow\Types\Type\Logical\{DateTimeType,
12+
DateType,
13+
HTMLElementType,
14+
HTMLType,
15+
JsonType,
16+
ListType,
17+
MapType,
18+
StructureType,
19+
TimeType,
20+
UuidType,
21+
XMLElementType,
22+
XMLType};
1223
use Flow\Types\Type\Native\{BooleanType, FloatType, IntegerType, StringType};
1324
use PHPUnit\Framework\TestCase;
1425

@@ -175,6 +186,8 @@ public function test_default_flow_types_constant_mapping() : void
175186
JsonType::class => DbalJsonType::class,
176187
XMLType::class => \Doctrine\DBAL\Types\StringType::class,
177188
XMLElementType::class => \Doctrine\DBAL\Types\StringType::class,
189+
HTMLType::class => \Doctrine\DBAL\Types\StringType::class,
190+
HTMLElementType::class => \Doctrine\DBAL\Types\StringType::class,
178191
ListType::class => DbalJsonType::class,
179192
MapType::class => DbalJsonType::class,
180193
StructureType::class => DbalJsonType::class,

src/adapter/etl-adapter-parquet/src/Flow/ETL/Adapter/Parquet/SchemaConverter.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use Flow\Types\Type;
2626
use Flow\Types\Type\Logical\{DateTimeType,
2727
DateType,
28+
HTMLType,
2829
JsonType,
2930
ListType,
3031
MapType,
@@ -34,6 +35,7 @@
3435
UuidType,
3536
XMLElementType,
3637
XMLType};
38+
use Flow\Types\Type\Logical\HTMLElementType;
3739
use Flow\Types\Type\Native\{BooleanType, FloatType, IntegerType, StringType};
3840

3941
final class SchemaConverter
@@ -77,6 +79,10 @@ private function flowToParquet(string $name, Type $type, bool $nullable) : Colum
7779
return FlatColumn::float($name, $nullable ? ParquetSchema\Repetition::OPTIONAL : ParquetSchema\Repetition::REQUIRED);
7880
case IntegerType::class:
7981
return FlatColumn::int64($name, $nullable ? ParquetSchema\Repetition::OPTIONAL : ParquetSchema\Repetition::REQUIRED);
82+
case HTMLType::class:
83+
case HTMLElementType::class:
84+
case XMLElementType::class:
85+
case XMLType::class:
8086
case StringType::class:
8187
return FlatColumn::string($name, $nullable ? ParquetSchema\Repetition::OPTIONAL : ParquetSchema\Repetition::REQUIRED);
8288
case BooleanType::class:
@@ -91,9 +97,6 @@ private function flowToParquet(string $name, Type $type, bool $nullable) : Colum
9197
return FlatColumn::uuid($name, $nullable ? ParquetSchema\Repetition::OPTIONAL : ParquetSchema\Repetition::REQUIRED);
9298
case JsonType::class:
9399
return FlatColumn::json($name, $nullable ? ParquetSchema\Repetition::OPTIONAL : ParquetSchema\Repetition::REQUIRED);
94-
case XMLType::class:
95-
case XMLElementType::class:
96-
return FlatColumn::string($name, $nullable ? ParquetSchema\Repetition::OPTIONAL : ParquetSchema\Repetition::REQUIRED);
97100
case ListType::class:
98101
$elementType = $type->element();
99102
$elementOptional = $elementType instanceof OptionalType;

src/bridge/openapi/specification/src/Flow/Bridge/OpenAPI/Specification/OpenAPIConverter.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,13 +423,15 @@ private function convertTypeToOpenAPI(Type $type) : array
423423
BooleanType::class => ['type' => 'boolean'],
424424
IntegerType::class => ['type' => 'integer'],
425425
FloatType::class => ['type' => 'number'],
426-
StringType::class => ['type' => 'string'],
426+
StringType::class,
427+
Type\Logical\HTMLType::class,
428+
Type\Logical\HTMLElementType::class => ['type' => 'string'],
427429
DateType::class => ['type' => 'string', 'format' => 'date'],
428430
DateTimeType::class => ['type' => 'string', 'format' => 'date-time'],
429431
TimeType::class => ['type' => 'string', 'format' => 'time'],
430432
UuidType::class => ['type' => 'string', 'format' => 'uuid'],
431433
JsonType::class => ['type' => 'string', 'format' => 'json'],
432-
XMLType::class => ['type' => 'string', 'format' => 'xml'],
434+
XMLType::class,
433435
XMLElementType::class => ['type' => 'string', 'format' => 'xml'],
434436
EnumType::class => $this->convertEnumToOpenAPI($type),
435437
ArrayType::class => $this->convertArrayToOpenAPI($type),

src/core/etl/src/Flow/ETL/DSL/functions.php

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
type_xml_element as type_xml_element_new,
3838
types as types_new
3939
};
40-
use Dom\HTMLDocument;
40+
use Dom\{HTMLDocument, HTMLElement};
4141
use Flow\Calculator\Rounding;
4242
use Flow\ETL\{Analyze,
4343
Attribute\DocumentationDSL,
@@ -165,7 +165,22 @@
165165
use Flow\ETL\Retry\DelayFactory\{Fixed, Fixed\FixedMilliseconds};
166166
use Flow\ETL\Retry\RetryStrategy\{AnyThrowable, OnExceptionTypes};
167167
use Flow\ETL\Row\{Entries, EntryFactory, SortOrder};
168-
use Flow\ETL\Row\Entry\{BooleanEntry, DateEntry, DateTimeEntry, EnumEntry, FloatEntry, IntegerEntry, JsonEntry, ListEntry, MapEntry, StringEntry, StructureEntry, TimeEntry, UuidEntry, XMLElementEntry, XMLEntry};
168+
use Flow\ETL\Row\Entry\{BooleanEntry,
169+
DateEntry,
170+
DateTimeEntry,
171+
EnumEntry,
172+
FloatEntry,
173+
HTMLElementEntry,
174+
IntegerEntry,
175+
JsonEntry,
176+
ListEntry,
177+
MapEntry,
178+
StringEntry,
179+
StructureEntry,
180+
TimeEntry,
181+
UuidEntry,
182+
XMLElementEntry,
183+
XMLEntry};
169184
use Flow\ETL\Row\Entry\HTMLEntry;
170185
use Flow\ETL\Row\{Entry, EntryReference, Reference, References};
171186
use Flow\ETL\Row\Formatter\ASCIISchemaFormatter;
@@ -637,6 +652,15 @@ function html_entry(string $name, HTMLDocument|string|null $value, ?Metadata $me
637652
return new HTMLEntry($name, $value, $metadata);
638653
}
639654

655+
/**
656+
* @return Entry<?HTMLElement>
657+
*/
658+
#[DocumentationDSL(module: Module::CORE, type: DSLType::ENTRY)]
659+
function html_element_entry(string $name, HTMLElement|string|null $value, ?Metadata $metadata = null) : Entry // @phpstan-ignore class.notFound,class.notFound
660+
{
661+
return new HTMLElementEntry($name, $value, $metadata);
662+
}
663+
640664
/**
641665
* @param Entry<mixed> ...$entries
642666
*/
@@ -1978,6 +2002,15 @@ function html_schema(string $name, bool $nullable = false, ?Metadata $metadata =
19782002
return Definition::html($name, $nullable, $metadata);
19792003
}
19802004

2005+
/**
2006+
* @return Definition<HTMLElement>
2007+
*/
2008+
#[DocumentationDSL(module: Module::CORE, type: DSLType::SCHEMA)]
2009+
function html_element_schema(string $name, bool $nullable = false, ?Metadata $metadata = null) : Definition // @phpstan-ignore class.notFound
2010+
{
2011+
return Definition::html_element($name, $nullable, $metadata);
2012+
}
2013+
19812014
/**
19822015
* @return Definition<\DOMDocument>
19832016
*/
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Row\Entry;
6+
7+
use function Flow\Types\DSL\{type_equals, type_html_element, type_instance_of, type_optional};
8+
use Dom\{HTMLDocument, HTMLElement};
9+
use Flow\ETL\Row\{Entry, Reference};
10+
use Flow\ETL\Schema\{Definition, Metadata};
11+
use Flow\Types\Type;
12+
13+
/**
14+
* @implements Entry<?HTMLElement>
15+
*/
16+
final class HTMLElementEntry implements Entry
17+
{
18+
use EntryRef;
19+
20+
private Metadata $metadata;
21+
22+
/**
23+
* @var Type<HTMLElement>
24+
*/
25+
private readonly Type $type;
26+
27+
private readonly ?HTMLElement $value;
28+
29+
public function __construct(
30+
private readonly string $name,
31+
HTMLElement|string|null $value,
32+
?Metadata $metadata = null,
33+
) {
34+
if (\is_string($value)) {
35+
$document = HTMLDocument::createFromString($value, \LIBXML_HTML_NOIMPLIED | \LIBXML_NOERROR);
36+
37+
$value = $document->documentElement;
38+
}
39+
40+
$this->metadata = $metadata ?: Metadata::empty();
41+
$this->value = $value;
42+
$this->type = type_html_element();
43+
}
44+
45+
public function __toString() : string
46+
{
47+
if ($this->value === null) {
48+
return '';
49+
}
50+
51+
return $this->toString();
52+
}
53+
54+
public function definition() : Definition
55+
{
56+
return new Definition($this->name, $this->type, $this->value === null, $this->metadata);
57+
}
58+
59+
public function duplicate() : self
60+
{
61+
return new self($this->name, type_optional(type_instance_of(HTMLElement::class))->assert($this->value ? $this->value->cloneNode(true) : null), $this->metadata);
62+
}
63+
64+
public function is(Reference|string $name) : bool
65+
{
66+
if ($name instanceof Reference) {
67+
return $this->name === $name->name();
68+
}
69+
70+
return $this->name === $name;
71+
}
72+
73+
public function isEqual(Entry $entry) : bool
74+
{
75+
if (!$entry instanceof self || !$this->is($entry->name())) {
76+
return false;
77+
}
78+
79+
if (!type_equals($this->type, $entry->type)) {
80+
return false;
81+
}
82+
83+
return $this->value?->C14N() === $entry->value?->C14N();
84+
}
85+
86+
public function map(callable $mapper) : self
87+
{
88+
$mappedValue = $mapper($this->value());
89+
$mappedValue = type_optional(type_instance_of(HTMLElement::class))->assert($mappedValue);
90+
91+
return new self($this->name, $mappedValue);
92+
}
93+
94+
public function name() : string
95+
{
96+
return $this->name;
97+
}
98+
99+
public function rename(string $name) : self
100+
{
101+
return new self($name, $this->value);
102+
}
103+
104+
public function toString() : string
105+
{
106+
if ($this->value === null) {
107+
return '';
108+
}
109+
110+
/* @phpstan-ignore-next-line */
111+
return $this->value->innerHTML;
112+
}
113+
114+
public function type() : Type
115+
{
116+
return $this->type;
117+
}
118+
119+
public function value() : ?HTMLElement
120+
{
121+
return $this->value;
122+
}
123+
124+
public function withValue(mixed $value) : self
125+
{
126+
return new self($this->name, type_optional($this->type())->assert($value), $this->metadata);
127+
}
128+
}

src/core/etl/src/Flow/ETL/Row/EntryFactory.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
datetime_entry,
1010
enum_entry,
1111
float_entry,
12+
html_element_entry,
1213
html_entry,
1314
int_entry,
1415
json_entry,
@@ -30,6 +31,7 @@ enum_entry,
3031
use Flow\Types\Type;
3132
use Flow\Types\Type\Logical\{DateTimeType,
3233
DateType,
34+
HTMLElementType,
3335
HTMLType,
3436
InstanceOfType,
3537
JsonType,
@@ -192,6 +194,10 @@ public function createAs(string $entryName, mixed $value, Definition|Type $defin
192194
return html_entry($entryName, type_optional($type)->cast($value), $metadata);
193195
}
194196

197+
if ($type instanceof HTMLElementType) {
198+
return html_element_entry($entryName, type_optional($type)->cast($value), $metadata);
199+
}
200+
195201
if ($type instanceof XMLType) {
196202
return xml_entry($entryName, type_optional($type)->cast($value), $metadata);
197203
}

0 commit comments

Comments
 (0)