Skip to content

Commit 52be2d7

Browse files
norberttechstloyd
andauthored
Added array related functions (#1391)
* Added array related functions * Commited missing files * Apply suggestions from code review Co-authored-by: Joseph Bielawski <[email protected]> --------- Co-authored-by: Joseph Bielawski <[email protected]>
1 parent 52b3d67 commit 52be2d7

File tree

9 files changed

+350
-0
lines changed

9 files changed

+350
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Function;
6+
7+
use Flow\ETL\Row;
8+
9+
final class ArrayFilter extends ScalarFunctionChain
10+
{
11+
public function __construct(private readonly ScalarFunction|array $array, private readonly mixed $value = null)
12+
{
13+
}
14+
15+
public function eval(Row $row) : mixed
16+
{
17+
$array = (new Parameter($this->array))->asArray($row);
18+
19+
if (null === $array) {
20+
return null;
21+
}
22+
23+
$value = (new Parameter($this->value))->eval($row);
24+
25+
return \array_filter($array, fn ($item) => $item !== $value);
26+
}
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Function;
6+
7+
use Flow\ETL\Row;
8+
9+
final class ArrayKeep extends ScalarFunctionChain
10+
{
11+
public function __construct(private readonly ScalarFunction|array $array, private readonly mixed $value = null)
12+
{
13+
}
14+
15+
public function eval(Row $row) : mixed
16+
{
17+
$array = (new Parameter($this->array))->asArray($row);
18+
19+
if (null === $array) {
20+
return null;
21+
}
22+
23+
$value = (new Parameter($this->value))->eval($row);
24+
25+
return \array_filter($array, fn ($item) => $item === $value);
26+
}
27+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Function;
6+
7+
use Flow\ETL\Row;
8+
9+
final class ArrayKeys extends ScalarFunctionChain
10+
{
11+
public function __construct(private readonly ScalarFunction|array $array)
12+
{
13+
}
14+
15+
public function eval(Row $row) : mixed
16+
{
17+
$array = (new Parameter($this->array))->asArray($row);
18+
19+
if (!\is_array($array)) {
20+
return null;
21+
}
22+
23+
return \array_keys($array);
24+
}
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Function;
6+
7+
use Flow\ETL\Row;
8+
9+
final class ArrayValues extends ScalarFunctionChain
10+
{
11+
public function __construct(private readonly ScalarFunction|array $array)
12+
{
13+
}
14+
15+
public function eval(Row $row) : mixed
16+
{
17+
$array = (new Parameter($this->array))->asArray($row);
18+
19+
if (!\is_array($array)) {
20+
return null;
21+
}
22+
23+
return \array_values($array);
24+
}
25+
}

src/core/etl/src/Flow/ETL/Function/ScalarFunctionChain.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@ public function andNot(ScalarFunction $function) : All
2525
return new All($this, new Not($function));
2626
}
2727

28+
/**
29+
* Filters an array by removing all elements that matches passed value.
30+
* Applicable to all data structures that can be converted to an array:
31+
* - json
32+
* - list
33+
* - map
34+
* - structure.
35+
*/
36+
public function arrayFilter(mixed $value) : self
37+
{
38+
return new ArrayFilter($this, $value);
39+
}
40+
2841
public function arrayGet(ScalarFunction|string $path) : self
2942
{
3043
return new ArrayGet($this, $path);
@@ -40,6 +53,32 @@ public function arrayGetCollectionFirst(string ...$keys) : self
4053
return ArrayGetCollection::fromFirst($this, $keys);
4154
}
4255

56+
/**
57+
* Filters an array by keeping only elements that matches passed value.
58+
* Applicable to all data structures that can be converted to an array:
59+
* - json
60+
* - list
61+
* - map
62+
* - structure.
63+
*/
64+
public function arrayKeep(mixed $value) : self
65+
{
66+
return new ArrayKeep($this, $value);
67+
}
68+
69+
/**
70+
* Returns all keys from an array, ignoring the values.
71+
* Applicable to all data structures that can be converted to an array:
72+
* - json
73+
* - list
74+
* - map
75+
* - structure.
76+
*/
77+
public function arrayKeys() : self
78+
{
79+
return new ArrayKeys($this);
80+
}
81+
4382
public function arrayMerge(ScalarFunction|array $ref) : self
4483
{
4584
return new ArrayMerge($this, $ref);
@@ -65,6 +104,19 @@ public function arraySort(ScalarFunction|Sort|null $sortFunction = null, ScalarF
65104
return new ArraySort($this, $sortFunction ?? Sort::sort, $flags, $recursive);
66105
}
67106

107+
/**
108+
* Returns all values from an array, ignoring the keys.
109+
* Applicable to all data structures that can be converted to an array:
110+
* - json
111+
* - list
112+
* - map
113+
* - structure.
114+
*/
115+
public function arrayValues() : self
116+
{
117+
return new ArrayValues($this);
118+
}
119+
68120
public function ascii() : self
69121
{
70122
return new Ascii($this);
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Tests\Unit\Function;
6+
7+
use function Flow\ETL\DSL\row;
8+
use function Flow\ETL\DSL\{int_entry, list_entry, lit, ref, string_entry, type_int, type_list};
9+
use Flow\ETL\Tests\FlowTestCase;
10+
11+
final class ArrayFilterTest extends FlowTestCase
12+
{
13+
public function test_array_filter() : void
14+
{
15+
self::assertSame(
16+
[1],
17+
ref('list')->arrayFilter(lit(2))
18+
->eval(
19+
row(list_entry('list', [1, 2], type_list(type_int()))),
20+
)
21+
);
22+
}
23+
24+
public function test_array_filter_by_entry_reference() : void
25+
{
26+
self::assertSame(
27+
[1],
28+
ref('list')->arrayFilter(ref('int'))
29+
->eval(
30+
row(
31+
list_entry('list', [1, 2], type_list(type_int())),
32+
int_entry('int', 2)
33+
),
34+
)
35+
);
36+
}
37+
38+
public function test_array_filter_not_existing_value() : void
39+
{
40+
self::assertSame(
41+
[1, 2],
42+
ref('list')->arrayFilter(lit(5))
43+
->eval(
44+
row(list_entry('list', [1, 2], type_list(type_int()))),
45+
)
46+
);
47+
}
48+
49+
public function test_array_filter_on_non_array() : void
50+
{
51+
self::assertNull(
52+
ref('map')->arrayFilter(lit(1))
53+
->eval(
54+
row(string_entry('map', 'test')),
55+
)
56+
);
57+
}
58+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Tests\Unit\Function;
6+
7+
use function Flow\ETL\DSL\row;
8+
use function Flow\ETL\DSL\{int_entry, list_entry, lit, ref, string_entry, type_int, type_list};
9+
use Flow\ETL\Tests\FlowTestCase;
10+
11+
final class ArrayKeepTest extends FlowTestCase
12+
{
13+
public function test_array_keep() : void
14+
{
15+
self::assertSame(
16+
[1 => 2],
17+
ref('list')->arrayKeep(lit(2))
18+
->eval(
19+
row(list_entry('list', [1, 2], type_list(type_int()))),
20+
)
21+
);
22+
}
23+
24+
public function test_array_keep_by_entry_reference() : void
25+
{
26+
self::assertSame(
27+
[1 => 2],
28+
ref('list')->arrayKeep(ref('int'))
29+
->eval(
30+
row(
31+
list_entry('list', [1, 2], type_list(type_int())),
32+
int_entry('int', 2)
33+
),
34+
)
35+
);
36+
}
37+
38+
public function test_array_keep_not_existing_value() : void
39+
{
40+
self::assertSame(
41+
[],
42+
ref('list')->arrayKeep(lit(5))
43+
->eval(
44+
row(list_entry('list', [1, 2], type_list(type_int()))),
45+
)
46+
);
47+
}
48+
49+
public function test_array_keep_on_non_array() : void
50+
{
51+
self::assertNull(
52+
ref('map')->arrayKeep(lit(1))
53+
->eval(
54+
row(string_entry('map', 'test')),
55+
)
56+
);
57+
}
58+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Tests\Unit\Function;
6+
7+
use function Flow\ETL\DSL\row;
8+
use function Flow\ETL\DSL\{
9+
map_entry,
10+
ref,
11+
string_entry,
12+
type_int,
13+
type_map,
14+
type_string};
15+
use Flow\ETL\Tests\FlowTestCase;
16+
17+
final class ArrayKeysTest extends FlowTestCase
18+
{
19+
public function test_array_keys() : void
20+
{
21+
self::assertSame(
22+
['a', 'b'],
23+
ref('map')->arrayKeys()
24+
->eval(
25+
row(map_entry('map', ['a' => 1, 'b' => 2], type_map(type_string(), type_int()))),
26+
)
27+
);
28+
}
29+
30+
public function test_array_keys_on_non_array() : void
31+
{
32+
self::assertNull(
33+
ref('map')->arrayKeys()
34+
->eval(
35+
row(string_entry('map', 'test')),
36+
)
37+
);
38+
}
39+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Tests\Unit\Function;
6+
7+
use function Flow\ETL\DSL\row;
8+
use function Flow\ETL\DSL\{
9+
map_entry,
10+
ref,
11+
string_entry,
12+
type_int,
13+
type_map,
14+
type_string};
15+
use Flow\ETL\Tests\FlowTestCase;
16+
17+
final class ArrayValuesTest extends FlowTestCase
18+
{
19+
public function test_array_values() : void
20+
{
21+
self::assertSame(
22+
[1, 2],
23+
ref('map')->arrayValues()
24+
->eval(
25+
row(map_entry('map', ['a' => 1, 'b' => 2], type_map(type_string(), type_int()))),
26+
)
27+
);
28+
}
29+
30+
public function test_array_values_on_non_array() : void
31+
{
32+
self::assertNull(
33+
ref('map')->arrayValues()
34+
->eval(
35+
row(string_entry('map', 'test')),
36+
)
37+
);
38+
}
39+
}

0 commit comments

Comments
 (0)