From 84692d810aa195479ad65fca03f4a456524e0fc1 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz <1921950+norberttech@users.noreply.github.com> Date: Sun, 5 Jun 2022 11:53:22 +0200 Subject: [PATCH] Allowed to use more advanced callbacks in call user function transformer (#251) --- src/Flow/ETL/DSL/Transform.php | 30 ++++++++++++++- .../CallUserFunctionTransformer.php | 24 +++++++++++- .../CallUserFunctionTransformerTest.php | 38 +++++++++++++++++++ 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/Flow/ETL/DSL/Transform.php b/src/Flow/ETL/DSL/Transform.php index 3c9f127dc..f846179a1 100644 --- a/src/Flow/ETL/DSL/Transform.php +++ b/src/Flow/ETL/DSL/Transform.php @@ -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 $pattern + * @param array|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); @@ -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 $search + * @param array|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 */ @@ -674,11 +699,12 @@ final public static function trim(string $entry, string $characters = " \n\r\t\v * @param array $entries * @param callable $callback * @param array $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); } } diff --git a/src/Flow/ETL/Transformer/CallUserFunctionTransformer.php b/src/Flow/ETL/Transformer/CallUserFunctionTransformer.php index 179877c38..590f1fc63 100755 --- a/src/Flow/ETL/Transformer/CallUserFunctionTransformer.php +++ b/src/Flow/ETL/Transformer/CallUserFunctionTransformer.php @@ -14,7 +14,13 @@ use Laravel\SerializableClosure\SerializableClosure; /** - * @implements Transformer, callback: callable, extra_arguments: array, entry_factory: EntryFactory}> + * @implements Transformer, + * callback: callable, + * extra_arguments: array, + * value_argument_name: ?string, + * entry_factory: EntryFactory + * }> * @psalm-immutable */ final class CallUserFunctionTransformer implements Transformer @@ -27,12 +33,16 @@ final class CallUserFunctionTransformer implements Transformer /** * @param array $entries + * @param callable $callback * @param array $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; @@ -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, ]; } @@ -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 @@ -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 + ) + ) ); } diff --git a/tests/Flow/ETL/Tests/Unit/Transformer/CallUserFunctionTransformerTest.php b/tests/Flow/ETL/Tests/Unit/Transformer/CallUserFunctionTransformerTest.php index 19b0ac3ba..e14cc0cad 100755 --- a/tests/Flow/ETL/Tests/Unit/Transformer/CallUserFunctionTransformerTest.php +++ b/tests/Flow/ETL/Tests/Unit/Transformer/CallUserFunctionTransformerTest.php @@ -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); @@ -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');