Skip to content

Commit

Permalink
castTo() is realized via transform()
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Oct 5, 2023
1 parent f016753 commit 5f677e9
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 25 deletions.
11 changes: 11 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,8 @@ $processor->process($schema, ['a', 'b', 'c']);
// Failed assertion "Even items in array" for item with value array.
```

The method can be called repeatedly to add multiple constraints. It can be intermixed with calls to `transform()` and `castTo()`.


Transformation: transform()
---------------------------
Expand All @@ -387,6 +389,15 @@ Successfully validated data can be modified using a custom function:
Expect::string()->transform(fn(string $s) => strtoupper($s));
```

The method can be called repeatedly to add multiple transformations. It can be intermixed with calls to `assert()` and `castTo()`. The operations will be executed in the order in which they are declared:

```php
Expect::type('string|int')
->castTo('string')
->assert('ctype_lower', 'All characters must be lowercased')
->transform(fn(string $s) => strtoupper($s)); // conversion to uppercase
```

The `transform()` method can both transform and validate the value simultaneously. This is often simpler and less redundant than chaining `transform()` and `assert()`. For this purpose, the function receives a [Nette\Schema\Context](https://api.nette.org/schema/master/Nette/Schema/Context.html) object with an `addError()` method, which can be used to add information about validation issues:

```php
Expand Down
18 changes: 1 addition & 17 deletions src/Schema/Elements/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ trait Base
/** @var callable[] */
private $transforms = [];

/** @var string|null */
private $castTo;

/** @var string|null */
private $deprecated;

Expand Down Expand Up @@ -61,8 +58,7 @@ public function before(callable $handler): self

public function castTo(string $type): self
{
$this->castTo = $type;
return $this;
return $this->transform(Helpers::getCastStrategy($type));
}


Expand Down Expand Up @@ -134,18 +130,6 @@ private function doDeprecation(Context $context): void

private function doTransform($value, Context $context)
{
if ($this->castTo) {
if (Nette\Utils\Reflection::isBuiltinType($this->castTo)) {
settype($value, $this->castTo);
} else {
$object = new $this->castTo;
foreach ($value as $k => $v) {
$object->$k = $v;
}
$value = $object;
}
}

$isOk = $context->createChecker();
foreach ($this->transforms as $handler) {
$value = $handler($value, $context);
Expand Down
2 changes: 1 addition & 1 deletion src/Schema/Elements/Structure.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function __construct(array $items)
{
(function (Schema ...$items) {})(...array_values($items));
$this->items = $items;
$this->castTo = 'object';
$this->castTo('object');
$this->required = true;
}

Expand Down
19 changes: 19 additions & 0 deletions src/Schema/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,23 @@ public static function validatePattern(string $value, string $pattern, Context $
);
}
}


public static function getCastStrategy(string $type): \Closure
{
if (Nette\Utils\Reflection::isBuiltinType($type)) {
return static function ($value) use ($type) {
settype($value, $type);
return $value;
};
} else {
return static function ($value) use ($type) {
$object = new $type;
foreach ($value as $k => $v) {
$object->$k = $v;
}
return $object;
};
}
}
}
5 changes: 3 additions & 2 deletions tests/Schema/Expect.from.php74.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ declare(strict_types=1);

use Nette\Schema\Elements\Structure;
use Nette\Schema\Expect;
use Nette\Schema\Processor;
use Tester\Assert;


require __DIR__ . '/../bootstrap.php';


Assert::with(Structure::class, function () {
$schema = Expect::from(new class {
$schema = Expect::from($obj = new class {
public string $dsn = 'mysql';
public ?string $user;
public ?string $password = null;
Expand All @@ -35,5 +36,5 @@ Assert::with(Structure::class, function () {
'mixed' => Expect::mixed(),
'arr' => Expect::type('array')->default([1]),
], $schema->items);
Assert::type('string', $schema->castTo);
Assert::type($obj, (new Processor)->process($schema, ['user' => '']));
});
5 changes: 3 additions & 2 deletions tests/Schema/Expect.from.php80.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ declare(strict_types=1);

use Nette\Schema\Elements\Structure;
use Nette\Schema\Expect;
use Nette\Schema\Processor;
use Tester\Assert;


require __DIR__ . '/../bootstrap.php';


Assert::with(Structure::class, function () {
$schema = Expect::from(new class {
$schema = Expect::from($obj = new class {
public string $dsn = 'mysql';
public ?string $user;
public ?string $password = null;
Expand All @@ -35,5 +36,5 @@ Assert::with(Structure::class, function () {
'mixed' => Expect::mixed()->required(),
'arr' => Expect::type('array')->default([1]),
], $schema->items);
Assert::type('string', $schema->castTo);
Assert::type($obj, (new Processor)->process($schema, ['user' => '', 'mixed' => '']));
});
7 changes: 4 additions & 3 deletions tests/Schema/Expect.from.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ declare(strict_types=1);

use Nette\Schema\Elements\Structure;
use Nette\Schema\Expect;
use Nette\Schema\Processor;
use Tester\Assert;


Expand All @@ -19,12 +20,12 @@ Assert::with(Structure::class, function () {

Assert::type(Structure::class, $schema);
Assert::same([], $schema->items);
Assert::same(stdClass::class, $schema->castTo);
Assert::type(stdClass::class, (new Processor)->process($schema, []));
});


Assert::with(Structure::class, function () {
$schema = Expect::from(new class {
$schema = Expect::from($obj = new class {
/** @var string */
public $dsn = 'mysql';

Expand Down Expand Up @@ -59,7 +60,7 @@ Assert::with(Structure::class, function () {
'arr' => Expect::type('array|null')->default(null),
'required' => Expect::type('string')->required(),
], $schema->items);
Assert::type('string', $schema->castTo);
Assert::type($obj, (new Processor)->process($schema, ['required' => '']));
});


Expand Down

0 comments on commit 5f677e9

Please sign in to comment.