Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions bench/src/Serializers/TypeLangAttributesBench.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@
use PhpBench\Attributes\Warmup;
use TypeLang\Mapper\Bench\Stub\ExampleRequestDTO;
use TypeLang\Mapper\Mapper;
use TypeLang\Mapper\Mapping\Driver\AttributeDriver;
use TypeLang\Mapper\Mapping\Driver\Psr16CachedDriver;
use TypeLang\Mapper\Mapping\Driver\ReflectionDriver;
use TypeLang\Mapper\Mapping\Provider\Psr16CacheProvider;
use TypeLang\Mapper\Mapping\Reader\AttributeReader;
use TypeLang\Mapper\Platform\StandardPlatform;

#[Revs(30), Warmup(3), Iterations(5), BeforeMethods('prepare')]
Expand All @@ -25,22 +24,20 @@ public function prepare(): void
{
parent::prepare();

$driver = new AttributeDriver(
delegate: new ReflectionDriver(),
);
$driver = new AttributeReader();

$this->cached = new Mapper(
platform: new StandardPlatform(
driver: new Psr16CachedDriver(
cache: $this->psr16,
meta: new Psr16CacheProvider(
psr16: $this->psr16,
delegate: $driver,
),
),
);

$this->raw = new Mapper(
platform: new StandardPlatform(
driver: $driver,
meta: $driver,
),
);
}
Expand Down
16 changes: 7 additions & 9 deletions bench/src/Serializers/TypeLangDocBlockBench.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
use PhpBench\Attributes\Warmup;
use TypeLang\Mapper\Bench\Stub\ExampleRequestDTO;
use TypeLang\Mapper\Mapper;
use TypeLang\Mapper\Mapping\Driver\DocBlockDriver;
use TypeLang\Mapper\Mapping\Driver\Psr16CachedDriver;
use TypeLang\Mapper\Mapping\Driver\ReflectionDriver;
use TypeLang\Mapper\Mapping\Provider\Psr16CacheProvider;
use TypeLang\Mapper\Mapping\Reader\PhpDocReader;
use TypeLang\Mapper\Mapping\Reader\ReflectionReader;
use TypeLang\Mapper\Platform\StandardPlatform;

#[Revs(30), Warmup(3), Iterations(5), BeforeMethods('prepare')]
Expand All @@ -25,22 +25,20 @@ public function prepare(): void
{
parent::prepare();

$driver = new DocBlockDriver(
delegate: new ReflectionDriver(),
);
$driver = new PhpDocReader();

$this->cached = new Mapper(
platform: new StandardPlatform(
driver: new Psr16CachedDriver(
cache: $this->psr16,
meta: new Psr16CacheProvider(
psr16: $this->psr16,
delegate: $driver,
),
),
);

$this->raw = new Mapper(
platform: new StandardPlatform(
driver: $driver,
meta: $driver,
),
);
}
Expand Down
10 changes: 8 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"require": {
"php": "^8.1",
"psr/clock": "^1.0",
"psr/log": "^1.0|^2.0|^3.0",
"psr/simple-cache": "^1.0|^2.0|^3.0",
"type-lang/parser": "^1.4",
Expand All @@ -33,6 +34,8 @@
"symfony/property-access": "^5.4|^6.0|^7.0",
"symfony/stopwatch": "^5.4|^6.0|^7.0",
"symfony/var-dumper": "^5.4|^6.0|^7.0",
"symfony/yaml": "^5.4|^6.0|^7.0",
"nette/neon": "^3.0",
"type-lang/phpdoc": "^1.0",
"type-lang/phpdoc-standard-tags": "^1.0"
},
Expand All @@ -42,8 +45,11 @@
}
},
"suggest": {
"type-lang/phpdoc-standard-tags": "(^1.0) Required for DocBlockDriver mapping driver support",
"justinrainbow/json-schema": "(^5.3|^6.0) Required for configuration drivers validation"
"ext-json": "Required for JSON mapping configuration files",
"nette/neon": "(^3.0) Required for NEON mapping configuration files",
"symfony/yaml": "(^5.4|^6.0|^7.0) Required for YAML mapping configuration files",
"type-lang/phpdoc-standard-tags": "(^1.0) Required for PhpDoc mapping configuration",
"justinrainbow/json-schema": "(^5.3|^6.0) Required for file-based configuration validation"
},
"extra": {
"branch-alias": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function __construct(

$result = $mapper->normalize($value);

dd($result);
var_dump($result);
//
// array:1 [
// "items" => array:3 [
Expand Down
24 changes: 12 additions & 12 deletions example/01.normalization/08.object-output-normalization.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ public function __construct(

var_dump($result);
//
// object{
// items: array:3 [
// "key1" => object{
// value: "first"
// }
// "key2" => object{
// value: "second"
// }
// 0 => object{
// value: "third"
// }
// array:1 [
// "items" => array:3 [
// "key1" => array:1 [
// "value" => "first"
// ]
// "key2" => array:1 [
// "value" => "second"
// ]
// 0 => array:1 [
// "value" => "third"
// ]
// ]
// }
// ]
//
12 changes: 4 additions & 8 deletions example/02.errors/01.custom-type-printer.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,15 @@ public function __construct(
]
], ExampleDTO::class);
} catch (RuntimeException $e) {
// Before
var_dump($e->getMessage());
// - Type: "list<ExampleDTO>"
// - Message: Passed value in "values" of {"values": 42} must be of type
// list<ExampleDTO>, but 42 given at $.values[1].values

// Replace all "expected type" definition to PHP-supported printer
// instead of PrettyPrinter
$e->template->types = new \TypeLang\Printer\NativeTypePrinter();

// After
// Before: Passed value in "values" of {"values": 42} must be of type
// list<ExampleDTO>, but 42 given at $.values[1].values
// After: Passed value in "values" of {"values": 42} must be of type
// array, but 42 given at $.values[1].values
var_dump($e->getMessage());
// - Type: "array"
// - Message: Passed value in "values" of {"values": 42} must be of type
// array, but 42 given at $.values[1].values
}
12 changes: 4 additions & 8 deletions example/02.errors/02.extended-type-printer.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,7 @@ public function __construct(
],
], ExampleDTO::class);
} catch (RuntimeException $e) {
// Before
var_dump($e->getMessage());
// - Type: "list<ExampleDTO>"
// - Message: Passed value in "values" of {"values": 42} must be of type
// list<ExampleDTO>, but 42 given at $.values[1].values

// Print all NamedTypeNode AST statements as "!!!MODIFIED!!!" string
$e->template->types = new class extends PrettyPrinter {
Expand All @@ -42,9 +38,9 @@ protected function printNamedTypeNode(NamedTypeNode $node): string
}
};

// After
// Before: Passed value in "values" of {"values": 42} must be of type
// list<ExampleDTO>, but 42 given at $.values[1].values
// After: Passed value in "values" of {"values": 42} must be of type
// !!!MODIFIED!!!, but 42 given at $.values[1].values
var_dump($e->getMessage());
// - Type: "!!!MODIFIED!!!"
// - Message: Passed value in "values" of {"values": 42} must be of type
// !!!MODIFIED!!!, but 42 given at $.values[1].values
}
29 changes: 11 additions & 18 deletions example/02.errors/03.custom-value-printer.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,30 @@ public function __construct(
],
], ExampleDTO::class);
} catch (RuntimeException $e) {
// Before
var_dump($e->getMessage());
// - Value#1: "of {"values": 42}"
// - Value#2: "but 42 given"
// - Message: Passed value in "values" of {"values": 42} must be of type
// list<ExampleDTO>, but 42 given at $.values[1].values

// Print all values using PHP-compatible types
$e->template->values = new PHPValuePrinter();

// After#1
// Before: Passed value in "values" of {"values": 42} must be of type
// list<ExampleDTO>, but 42 given at $.values[1].values
// After#1: Passed value in string of stdClass must be of type
// list<ExampleDTO>, but int given at $.values[1].values
var_dump($e->getMessage());
// - Value#1: "of array"
// - Value#2: "but int given"
// - Message: Passed value in "values" of array must be of type
// list<ExampleDTO>, but int given at $.values[1].values


// In case of symfony/var-dumper is installed, we can use it
if (\Composer\InstalledVersions::isInstalled('symfony/var-dumper')) {
// Print all values using SymfonyValuePrinter
$e->template->values = new SymfonyValuePrinter();

// After#2
// Before: Passed value in "values" of {"values": 42} must be of type
// list<ExampleDTO>, but 42 given at $.values[1].values
// After#1: Passed value in string of stdClass must be of type
// list<ExampleDTO>, but int given at $.values[1].values
// After#2: Passed value in "values" of {#394
// +"values": 42
// } must be of type list<ExampleDTO>, but 42 given at $.values[1].values
var_dump($e->getMessage());
// - Value#1: "of array:1 [
// "values" => 42
// ]"
// - Value#2: "but 42 given"
// - Message: Passed value in "values" of array:1 [
// "values" => 42
// ] must be of type list<ExampleDTO>, but 42 given at $.values[1].values
}
}
11 changes: 5 additions & 6 deletions example/02.errors/04.custom-path-printer.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ public function __construct(
],
], ExampleDTO::class);
} catch (RuntimeException $e) {
// Before: "at $.values[1].values"
var_dump($e->getMessage());
// Passed value of field "values" must be of type list<ExampleDTO>,
// but 42 given at $.values[1].values

// Print full path using ">" delimiter
$e->template->paths = new class implements PathPrinterInterface {
Expand All @@ -41,8 +38,10 @@ public function print(PathInterface $path): string
}
};

// After: "at ExampleDTO > values > 1 > ExampleDTO > values"
// Before: Passed value in "values" of {"values": 42} must be of type
// list<ExampleDTO>, but 42 given at $.values[1].values
// After: Passed value in "values" of {"values": 42} must be of type
// list<ExampleDTO>, but 42 given at ExampleDTO > values >
// 1 > ExampleDTO > values
var_dump($e->getMessage());
// Passed value of field "values" must be of type list<ExampleDTO>,
// but 42 given at ExampleDTO > values > 1 > ExampleDTO > values
}
19 changes: 15 additions & 4 deletions example/03.types/03.custom-type-template-arguments.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,30 @@ public function cast(mixed $value, Context $context): mixed
// ]
//

var_dump($mapper->normalize([], 'non-empty<string>'));
try {
var_dump($mapper->normalize([], 'non-empty<string>'));
} catch (\Throwable $e) {
echo $e->getMessage() . "\n";
}
//
// InvalidValueException: Passed value [] is invalid
//


var_dump($mapper->normalize('example', 'non-empty'));
try {
var_dump($mapper->normalize('example', 'non-empty'));
} catch (\Throwable $e) {
echo $e->getMessage() . "\n";
}
//
// MissingTemplateArgumentsException: Type "non-empty" expects at least 1
// template argument(s), but 0 were passed
//

var_dump($mapper->normalize('', 'non-empty<string>'));
try {
var_dump($mapper->normalize('', 'non-empty<string>'));
} catch (\Throwable $e) {
echo $e->getMessage() . "\n";
}
//
// InvalidValueException: Passed value "" is invalid
//
15 changes: 12 additions & 3 deletions example/03.types/04.custom-platform.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,22 @@ public function __construct(

$mapper = new Mapper(new SimplePlatform());

var_dump($mapper->normalize(new ExampleDTO()));
try {
var_dump($mapper->normalize(new ExampleDTO()));
} catch (\Throwable $e) {
echo $e->getMessage() . "\n";
}
//
// TypeRequiredException: Type "int" for property ExampleDTO::$value
// is not defined
//

var_dump($mapper->normalize([new ExampleDTO()], 'array<ExampleDTO>'));
try {
var_dump($mapper->normalize([new ExampleDTO()], 'array<ExampleDTO>'));
} catch (\Throwable $e) {
echo $e->getMessage() . "\n";
}
//
// ParseException: Template arguments not allowed in "array<ExampleDTO>" at column 6
// ParseException: Template arguments not allowed in "array<ExampleDTO>"
// at column 6
//
1 change: 0 additions & 1 deletion example/03.types/06.custom-type-psr-container.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use TypeLang\Mapper\Platform\DelegatePlatform;
use TypeLang\Mapper\Platform\StandardPlatform;
use TypeLang\Mapper\Runtime\Context;
use TypeLang\Mapper\Type\Builder\CallableTypeBuilder;
use TypeLang\Mapper\Type\Builder\PsrContainerTypeBuilder;
use TypeLang\Mapper\Type\TypeInterface;

Expand Down
38 changes: 38 additions & 0 deletions example/04.mapping-readers/01.reflection-mapping.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

use TypeLang\Mapper\Mapper;

require __DIR__ . '/../../vendor/autoload.php';

class ExampleDTO
{
public function __construct(
public readonly array $value = [],
) {}
}

// Create standard platform with REFLECTION READER
$platform = new \TypeLang\Mapper\Platform\StandardPlatform(
meta: new \TypeLang\Mapper\Mapping\Reader\ReflectionReader(),
);

$mapper = new Mapper($platform);

var_dump($mapper->denormalize([
'value' => ['string', 'string 2'],
], ExampleDTO::class));

//
// Because NATIVE type hint is "array" that infers to "array<array-key, mixed>"
//
// object(ExampleDTO)#345 (1) {
// ["value"] => array(2) {
// [0] => string(6) "string"
// [1] => string(8) "string 2"
// }
// }
//


Loading
Loading