Skip to content

Commit

Permalink
Allowed to use more advanced callbacks in call user function transfor…
Browse files Browse the repository at this point in the history
…mer (#251)
  • Loading branch information
norberttech committed Jun 5, 2022
1 parent f8f54c6 commit 84692d8
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 4 deletions.
30 changes: 28 additions & 2 deletions src/Flow/ETL/DSL/Transform.php
Expand Up @@ -447,6 +447,19 @@ final public static function prefix(string $entry, string $prefix) : Transformer
return new Transformer\StringFormatTransformer($entry, \str_replace('%', '%%', $prefix) . '%s');
}

/**
* @param string $entry
* @param array<string>|string $pattern
* @param array<string>|string $replacement
* @param int $limit
*
* @return Transformer
*/
final public static function preg_replace(string $entry, string|array $pattern, string|array $replacement, int $limit = -1) : Transformer
{
return self::user_function([$entry], 'preg_replace', ['pattern' => $pattern, 'replacement' => $replacement, 'limit' => $limit], 'subject');
}

final public static function remove(string ...$entries) : Transformer
{
return new Transformer\RemoveEntriesTransformer(...$entries);
Expand Down Expand Up @@ -486,6 +499,18 @@ final public static function str_pad(string $entry, int $length, string $pad_str
return self::user_function([$entry], 'str_pad', [$length, $pad_string, $type]);
}

/**
* @param string $entry
* @param array<string>|string $search
* @param array<string>|string $replace
*
* @return Transformer
*/
final public static function str_replace(string $entry, string|array $search, string|array $replace) : Transformer
{
return self::user_function([$entry], 'str_replace', ['search' => $search, 'replace' => $replace], 'subject');
}

/**
* @param string[] $string_columns
*/
Expand Down Expand Up @@ -674,11 +699,12 @@ final public static function trim(string $entry, string $characters = " \n\r\t\v
* @param array<string> $entries
* @param callable $callback
* @param array<mixed> $extra_arguments
* @param null|string $value_argument_name - when used, row value is passed to callback function under argument with given name
*
* @return Transformer
*/
final public static function user_function(array $entries, callable $callback, array $extra_arguments = []) : Transformer
final public static function user_function(array $entries, callable $callback, array $extra_arguments = [], string $value_argument_name = null) : Transformer
{
return new Transformer\CallUserFunctionTransformer($entries, $callback, $extra_arguments);
return new Transformer\CallUserFunctionTransformer($entries, $callback, $extra_arguments, $value_argument_name);
}
}
24 changes: 22 additions & 2 deletions src/Flow/ETL/Transformer/CallUserFunctionTransformer.php
Expand Up @@ -14,7 +14,13 @@
use Laravel\SerializableClosure\SerializableClosure;

/**
* @implements Transformer<array{entries: array<string>, callback: callable, extra_arguments: array<mixed>, entry_factory: EntryFactory}>
* @implements Transformer<array{
* entries: array<string>,
* callback: callable,
* extra_arguments: array<mixed>,
* value_argument_name: ?string,
* entry_factory: EntryFactory
* }>
* @psalm-immutable
*/
final class CallUserFunctionTransformer implements Transformer
Expand All @@ -27,12 +33,16 @@ final class CallUserFunctionTransformer implements Transformer

/**
* @param array<string> $entries
* @param callable $callback
* @param array<mixed> $extraArguments
* @param null|string $valueArgumentName
* @param EntryFactory $entryFactory
*/
public function __construct(
private readonly array $entries,
callable $callback,
private readonly array $extraArguments = [],
private readonly ?string $valueArgumentName = null,
private readonly EntryFactory $entryFactory = new NativeEntryFactory()
) {
$this->callback = $callback;
Expand All @@ -49,6 +59,7 @@ public function __serialize() : array
'callback' => $this->callback instanceof \Closure ? new SerializableClosure(\Closure::fromCallable($this->callback)) : $this->callback,
'extra_arguments' => $this->extraArguments,
'entry_factory' => $this->entryFactory,
'value_argument_name' => $this->valueArgumentName,
];
}

Expand All @@ -63,6 +74,7 @@ public function __unserialize(array $data) : void
$this->callback = $data['callback'] instanceof SerializableClosure ? $data['callback']->getClosure() : $data['callback'];
$this->extraArguments = $data['extra_arguments'];
$this->entryFactory = $data['entry_factory'];
$this->valueArgumentName = $data['value_argument_name'];
}

public function transform(Rows $rows) : Rows
Expand All @@ -77,7 +89,15 @@ public function transform(Rows $rows) : Rows
if (\in_array($entry->name(), $this->entries, true)) {
$entry = $this->entryFactory->create(
$entry->name(),
\call_user_func($this->callback, ...\array_merge([$entry->value()], $this->extraArguments))
\call_user_func(
$this->callback,
...\array_merge(
$this->valueArgumentName
? [$this->valueArgumentName => $entry->value()]
: [$entry->value()],
$this->extraArguments
)
)
);
}

Expand Down
Expand Up @@ -70,6 +70,25 @@ public function test_ltrim() : void
), $rows);
}

public function test_preg_replace_callback() : void
{
$callbackTransformer = Transform::preg_replace('string', '/^\[[0-9]+\][[0-9]+\]/', '');

$rows = $callbackTransformer->transform(
new Rows(
Row::create(
new Entry\StringEntry('string', '[90321][90346]/Frodo...')
)
)
);

$this->assertEquals(new Rows(
Row::create(
new Entry\StringEntry('string', '/Frodo...')
)
), $rows);
}

public function test_round() : void
{
$transformer = Transform::round('float', 2, \PHP_ROUND_HALF_DOWN);
Expand Down Expand Up @@ -132,6 +151,25 @@ public function test_str_pad() : void
), $rows);
}

public function test_str_replace_callback() : void
{
$callbackTransformer = Transform::str_replace('string', 'thing', '');

$rows = $callbackTransformer->transform(
new Rows(
Row::create(
new Entry\StringEntry('string', 'Something')
)
)
);

$this->assertEquals(new Rows(
Row::create(
new Entry\StringEntry('string', 'Some')
)
), $rows);
}

public function test_trim() : void
{
$callbackTransformer = Transform::trim('string');
Expand Down

0 comments on commit 84692d8

Please sign in to comment.