@@ -8,20 +8,147 @@ toc_depth: 2
88All notable changes to this project will be documented in this file.
99<!-- - END HEADER -->
1010
11- ## [ 0.10.0] ( https://github.com/romm/Valinor/compare/0.9.0...0.10.0 ) (2022-06-10)
11+ ## [ 0.11.0] ( https://github.com/CuyZ/Valinor/compare/0.10.0...0.11.0 ) (2022-06-23)
12+
13+ ### Notable changes
14+
15+ ** Strict mode**
16+
17+ The mapper is now more type-sensitive and will fail in the following situations:
18+
19+ - When a value does not match exactly the awaited scalar type, for instance a
20+ string ` "42" ` given to a node that awaits an integer.
21+
22+ - When unnecessary array keys are present, for instance mapping an array
23+ ` ['foo' => …, 'bar' => …, 'baz' => …] ` to an object that needs only ` foo ` and
24+ ` bar ` .
25+
26+ - When permissive types like ` mixed ` or ` object ` are encountered.
27+
28+ These limitations can be bypassed by enabling the flexible mode:
29+
30+ ``` php
31+ (new \CuyZ\Valinor\MapperBuilder())
32+ ->flexible()
33+ ->mapper();
34+ ->map('array{foo: int, bar: bool}', [
35+ 'foo' => '42', // Will be cast from `string` to `int`
36+ 'bar' => 'true', // Will be cast from `string` to `bool`
37+ 'baz' => '…', // Will be ignored
38+ ]);
39+ ```
40+
41+ When using this library for a provider application — for instance an API
42+ endpoint that can be called with a JSON payload — it is recommended to use the
43+ strict mode. This ensures that the consumers of the API provide the exact
44+ awaited data structure, and prevents unknown values to be passed.
45+
46+ When using this library as a consumer of an external source, it can make sense
47+ to enable the flexible mode. This allows for instance to convert string numeric
48+ values to integers or to ignore data that is present in the source but not
49+ needed in the application.
50+
51+ ** Interface inferring**
52+
53+ It is now mandatory to list all possible class-types that can be inferred by the
54+ mapper. This change is a step towards the library being able to deliver powerful
55+ new features such as compiling a mapper for better performance.
56+
57+ The existing calls to ` MapperBuilder::infer ` that could return several
58+ class-names must now add a signature to the callback. The callbacks that require
59+ no parameter and always return the same class-name can remain unchanged.
60+
61+ For instance:
62+
63+ ``` php
64+ $builder = (new \CuyZ\Valinor\MapperBuilder())
65+ // Can remain unchanged
66+ ->infer(SomeInterface::class, fn () => SomeImplementation::class);
67+ ```
68+
69+ ``` php
70+ $builder = (new \CuyZ\Valinor\MapperBuilder())
71+ ->infer(
72+ SomeInterface::class,
73+ fn (string $type) => match($type) {
74+ 'first' => ImplementationA::class,
75+ 'second' => ImplementationB::class,
76+ default => throw new DomainException("Unhandled `$type`.")
77+ }
78+ )
79+ // …should be modified with:
80+ ->infer(
81+ SomeInterface::class,
82+ /** @return class-string<ImplementationA |ImplementationB > */
83+ fn (string $type) => match($type) {
84+ 'first' => ImplementationA::class,
85+ 'second' => ImplementationB::class,
86+ default => throw new DomainException("Unhandled `$type`.")
87+ }
88+ );
89+ ```
90+
91+ ** Object constructors collision**
92+
93+ All these changes led to a new check that runs on all registered object
94+ constructors. If a collision is found between several constructors that have the
95+ same signature (the same parameter names), an exception will be thrown.
96+
97+ ``` php
98+ final class SomeClass
99+ {
100+ public static function constructorA(string $foo, string $bar): self
101+ {
102+ // …
103+ }
104+
105+ public static function constructorB(string $foo, string $bar): self
106+ {
107+ // …
108+ }
109+ }
110+
111+ (new \CuyZ\Valinor\MapperBuilder())
112+ ->registerConstructor(
113+ SomeClass::constructorA(...),
114+ SomeClass::constructorB(...),
115+ )
116+ ->mapper();
117+ ->map(SomeClass::class, [
118+ 'foo' => 'foo',
119+ 'bar' => 'bar',
120+ ]);
121+
122+ // Exception: A collision was detected […]
123+ ```
124+
125+ ### ⚠ BREAKING CHANGES
126+
127+ * Handle exhaustive list of interface inferring ([ 1b0ff3] ( https://github.com/CuyZ/Valinor/commit/1b0ff39af650f1c5902ee930f49049042842ec08 ) )
128+ * Make mapper more strict and allow flexible mode ([ 90dc58] ( https://github.com/CuyZ/Valinor/commit/90dc586018449b15f3b0296241d8cb2d1320d940 ) )
129+
130+ ### Features
131+
132+ * Improve cache warmup ([ 44c5f1] ( https://github.com/CuyZ/Valinor/commit/44c5f13b70a14cbe1cb2b917acd127d14b8c7d14 ) )
133+
134+ ---
135+
136+ ## [ 0.10.0] ( https://github.com/CuyZ/Valinor/compare/0.9.0...0.10.0 ) (2022-06-10)
12137
13138### Notable changes
14139
15140Documentation is now available at [ valinor.cuyz.io] ( https://valinor.cuyz.io ) .
16141
17142### Features
18143
19- * Support mapping to dates with no time ([ e0a529] ( https://github.com/romm /Valinor/commit/e0a529a7e546c2e3ffb929f819256b90a5f7859a ) )
144+ * Support mapping to dates with no time ([ e0a529] ( https://github.com/CuyZ /Valinor/commit/e0a529a7e546c2e3ffb929f819256b90a5f7859a ) )
20145
21146### Bug Fixes
22147
23- * Allow declaring promoted parameter type with ` @var ` annotation ([ d8eb4d] ( https://github.com/romm/Valinor/commit/d8eb4d830bd0817a5de2d61c8cfa81e7e025064a ) )
24- * Allow mapping iterable to shaped array ([ 628baf] ( https://github.com/romm/Valinor/commit/628baf1294aaf3ce65bc5af969073604e2005af8 ) )
148+ * Allow declaring promoted parameter type with ` @var ` annotation ([ d8eb4d] ( https://github.com/CuyZ/Valinor/commit/d8eb4d830bd0817a5de2d61c8cfa81e7e025064a ) )
149+ * Allow mapping iterable to shaped array ([ 628baf] ( https://github.com/CuyZ/Valinor/commit/628baf1294aaf3ce65bc5af969073604e2005af8 ) )
150+
151+ ---
25152
26153## [ 0.9.0] ( https://github.com/CuyZ/Valinor/compare/0.8.0...0.9.0 ) (2022-05-23)
27154
0 commit comments