Skip to content

Commit

Permalink
feat: add casting for arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
surgiie committed May 27, 2024
1 parent 009d195 commit 448a1f6
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 48 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ vendor
composer.lock
phpunit.xml
.env
.phpunit.cache
.phpunit.result.cache
.php-cs-fixer.cache
node_modules
84 changes: 77 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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
<?php
function example_function(int $value){
return $value + 1;
}
$input = ['example'=>"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 `@<type>` to the value. For example to cast the `1` to an integer:


```php
<?php
function example_function(int $value){
return $value + 1;
}
$input = ['example'=>"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:
Expand Down Expand Up @@ -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:
Expand All @@ -232,10 +302,10 @@ You can also use class constants that accept a single value as its constructor,
<?php
$input = [
'some_date'=>"1991-05-01",
'string'=>"Foo",
];
$transformers = [
'some_date'=>[Carbon\Carbon::class, '->addDay:1', '->format:m/d/y'],
'string'=>[Example::class, '->concat:Bar'],
];
```
Expand Down
12 changes: 6 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
32 changes: 7 additions & 25 deletions phpunit.dist.xml
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
executionOrder="random"
failOnWarning="true"
failOnRisky="true"
failOnEmptyTestSuite="true"
beStrictAboutOutputDuringTests="true"
verbose="true"
>
<testsuites>
<testsuite name="Transformer Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" backupGlobals="false" bootstrap="vendor/autoload.php" colors="true" processIsolation="false" stopOnFailure="false" executionOrder="random" failOnWarning="true" failOnRisky="true" failOnEmptyTestSuite="true" beStrictAboutOutputDuringTests="true" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
<testsuites>
<testsuite name="Transformer Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
22 changes: 20 additions & 2 deletions src/Transformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
4 changes: 2 additions & 2 deletions tests/Feature/DataTransformerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand Down
2 changes: 1 addition & 1 deletion tests/Feature/RequestMacroTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
46 changes: 41 additions & 5 deletions tests/Unit/TransformerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand Down

0 comments on commit 448a1f6

Please sign in to comment.