diff --git a/.gitignore b/.gitignore index 5032e1e..0b526b4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ vendor composer.lock phpunit.xml .env +.phpunit.cache .phpunit.result.cache .php-cs-fixer.cache node_modules \ No newline at end of file diff --git a/README.md b/README.md index fe60653..e1df302 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ $transformers = [ ]; ``` +### Specify Value Argument Order By default, the first argument passed to your function will be the value being formatted, followed by the arguments specified in the order provided. If your function does not accept the value as the first argument, you can use the `:value:` placeholder to specify the order. For example: @@ -88,6 +89,58 @@ $transformers = [ $transformer = new DataTransformer($input, $transformers); $transformer->transform(); ``` + +### Casting Arguments + +You may find that when passing arguments to the transforming functions, you may hit run time errors due to typehints on arguments for basic types. Since arguments are being specified as a string here, you may come across a scenario like this: + + +```php +"1"]; + +$transformers = [ + 'example'=>'example_function:1', +]; + +``` + +The above would throw an error because the `1` argument being passed in is a string and the function expects a integer. In these cases, you can use the following convention to cast the argument to specific native type, by suffixing `@` to the value. For example to cast the `1` to an integer: + + +```php +"1"]; + +$transformers = [ + 'example'=>'example_function:1@int', // "1" will be casted to an int. +]; + +``` + +#### Available Casting Types: + +The following basic casting types are available + +- int +- str +- float +- bool +- array +- object + +**Note** For more complex type or casting needs, use a Closure or `Surgiie\Transformer\Contracts\Transformable` class as documented below. + ## Optional Transformation If you only want to transform a value if it is not null or "blank", you can use the `?` character in the chain of functions to specify when to break out of processing. This is often placed at the start of the chain: @@ -212,17 +265,34 @@ It is possible to delegate a function call to an object if the value has been co use Closure; -// example available functions at runtime: -function to_carbon($value) +class Example { - return new Carbon\Carbon($value); + + protected $value; + + public function __construct($value) + { + $this->value = $value; + } + + public function concat($string) + { + return $this->value . $string; + } + } +function example($value) +{ + return new Example($value); +} + + $input = [ - 'some_date'=>"1991-05-01", + 'string'=>"Foo", ]; $transformers = [ - 'some_date'=>'to_carbon|->addDay:1|->format:m/d/y', + 'string'=>'example|->concat:Bar', ]; ``` You can also use class constants that accept a single value as its constructor, for example: @@ -232,10 +302,10 @@ You can also use class constants that accept a single value as its constructor, "1991-05-01", + 'string'=>"Foo", ]; $transformers = [ - 'some_date'=>[Carbon\Carbon::class, '->addDay:1', '->format:m/d/y'], + 'string'=>[Example::class, '->concat:Bar'], ]; ``` diff --git a/composer.json b/composer.json index 6a33681..db1e35c 100644 --- a/composer.json +++ b/composer.json @@ -18,14 +18,14 @@ ], "require": { "php": "^8.0.2", - "illuminate/http": "^9.0|^10.0", - "illuminate/support": "^9.0|^10.0", - "illuminate/validation": "^9.0|^10.0" + "illuminate/http": "^9.0|^10.0|^11.0", + "illuminate/support": "^9.0|^10.0|^11.0", + "illuminate/validation": "^9.0|^10.0|^11.0" }, "require-dev": { - "pestphp/pest": "^1.22", - "laravel/pint": "^1.0", - "symfony/var-dumper": "^6.2" + "pestphp/pest": "^2.34", + "laravel/pint": "^1.16", + "symfony/var-dumper": "^7.0" }, "autoload": { "psr-4": { diff --git a/phpunit.dist.xml b/phpunit.dist.xml index 33b1270..5afe4f5 100644 --- a/phpunit.dist.xml +++ b/phpunit.dist.xml @@ -1,26 +1,8 @@ - - - - tests - - - \ No newline at end of file + + + + tests + + + diff --git a/src/Transformer.php b/src/Transformer.php index 757ce49..e12e2a4 100644 --- a/src/Transformer.php +++ b/src/Transformer.php @@ -201,13 +201,31 @@ protected function prepareArguments($value, $function, array $args = []) $parameters = array_merge($defaults, $args); foreach ($parameters as $index => $param) { - if (is_string($param) && trim($param) === ':value:') { + if(!is_string($param)){ + continue; + } + + if (trim($param) === ':value:') { $parameters[$index] = $value; array_shift($parameters); break; } - } + // allow params to be to be casted to a specific type + if(preg_match('/.+@(int|str|float|bool|array|object)/', $param, $matches)){ + $type = $matches[1]; + $param = rtrim($param, "@$type"); + $parameters[$index] = match($type){ + 'int' => (int) $param, + 'str' => (string) $param, + 'float' => (float) $param, + 'bool' => filter_var($param, FILTER_VALIDATE_BOOL), + 'array' => (array) $param, + 'object' => (object) $param, + }; + } + + } return $parameters; } diff --git a/tests/Feature/DataTransformerTest.php b/tests/Feature/DataTransformerTest.php index 9ec5efa..94db4b7 100644 --- a/tests/Feature/DataTransformerTest.php +++ b/tests/Feature/DataTransformerTest.php @@ -128,13 +128,13 @@ public function transform($value, Closure $exit) it('can delegate to underlying objects', function () { $formatter = (new DataTransformer($this->data, [ - 'date_of_birth' => 'trim|Carbon\Carbon|->addDays:1|->format:m/d/Y', + 'date_of_birth' => 'trim|Carbon\Carbon|->format:m/d/Y', ])); $formattedData = $formatter->transform(); expect($formattedData['date_of_birth'])->not->toBe($this->data['date_of_birth']); - expect($formattedData['date_of_birth'])->toBe('05/25/2020'); + expect($formattedData['date_of_birth'])->toBe('05/24/2020'); }); it('can process wildcards on data', function () { diff --git a/tests/Feature/RequestMacroTest.php b/tests/Feature/RequestMacroTest.php index 4bfdfc9..acfd37f 100644 --- a/tests/Feature/RequestMacroTest.php +++ b/tests/Feature/RequestMacroTest.php @@ -74,7 +74,7 @@ function to_carbon($value) return new \Carbon\Carbon($value); } $formattedData = $this->request->transform([ - 'date_of_birth' => 'to_carbon|->addDay:1|->format:m/d/Y', + 'date_of_birth' => 'to_carbon|->addDay:1@int|->format:m/d/Y', ]); expect($formattedData['date_of_birth'])->toBe('05/25/2020'); diff --git a/tests/Unit/TransformerTest.php b/tests/Unit/TransformerTest.php index fa5d169..600af33 100644 --- a/tests/Unit/TransformerTest.php +++ b/tests/Unit/TransformerTest.php @@ -62,14 +62,50 @@ function ($value) { }); it('can delegate to underlying value instances', function () { - $formatter = (new Transformer(' 2020-05-24 ', [ + + class Example + { + protected $value; + public function __construct($value) + { + $this->value = $value; + } + + public function concat($string) + { + return $this->value . $string; + } + + } + + function example($value) + { + return new Example($value); + } + + $formatter = (new Transformer(' foo ', [ 'trim', - Carbon::class, - '->addDays:1', - '->format:m/d/Y', + Example::class, + '->concat:bar', + ])); + + expect($formatter->transform())->toBe('foobar'); +}); + + +it('can cast arguments', function () { + + function example_two(int $value) + { + return $value + 1; + } + + $formatter = (new Transformer(1, [ + 'trim', + 'example_two:1@int' ])); - expect($formatter->transform())->toBe('05/25/2020'); + expect($formatter->transform())->toBe(2); }); it('throws exception when guarded', function () {