Skip to content

Commit

Permalink
release: version 1.12.0
Browse files Browse the repository at this point in the history
  • Loading branch information
romm committed Apr 4, 2024
1 parent cd5df97 commit 3bc4079
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/pages/project/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Below are listed the changelogs for all released versions of the library.

## Version 1

- [`1.12.0` — 4th of April 2024](changelog/version-1.12.0.md)
- [`1.11.0` — 27th of March 2024](changelog/version-1.11.0.md)
- [`1.10.0` — 12th of March 2024](changelog/version-1.10.0.md)
- [`1.9.0` — 2nd of February 2024](changelog/version-1.9.0.md)
Expand Down
176 changes: 176 additions & 0 deletions docs/pages/project/changelog/version-1.12.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# Changelog 1.12.0 — 4th of April 2024

!!! info inline end "[See release on GitHub]"
[See release on GitHub]: https://github.com/CuyZ/Valinor/releases/tag/1.12.0

## Notable changes

**Introduce unsealed shaped array syntax**

This syntax enables an extension of the shaped array type by allowing additional
values that must respect a certain type.

```php
$mapper = (new \CuyZ\Valinor\MapperBuilder())->mapper();

// Default syntax can be used like this:
$mapper->map(
'array{foo: string, ...array<string>}',
[
'foo' => 'foo',
'bar' => 'bar', // ✅ valid additional value
]
);

$mapper->map(
'array{foo: string, ...array<string>}',
[
'foo' => 'foo',
'bar' => 1337, // ❌ invalid value 1337
]
);

// Key type can be added as well:
$mapper->map(
'array{foo: string, ...array<int, string>}',
[
'foo' => 'foo',
42 => 'bar', // ✅ valid additional key
]
);

$mapper->map(
'array{foo: string, ...array<int, string>}',
[
'foo' => 'foo',
'bar' => 'bar' // ❌ invalid key
]
);

// Advanced types can be used:
$mapper->map(
"array{
'en_US': non-empty-string,
...array<non-empty-string, non-empty-string>
}",
[
'en_US' => 'Hello',
'fr_FR' => 'Salut', // ✅ valid additional value
]
);

$mapper->map(
"array{
'en_US': non-empty-string,
...array<non-empty-string, non-empty-string>
}",
[
'en_US' => 'Hello',
'fr_FR' => '', // ❌ invalid value
]
);

// If the permissive type is enabled, the following will work:
(new \CuyZ\Valinor\MapperBuilder())
->allowPermissiveTypes()
->mapper()
->map(
'array{foo: string, ...}',
['foo' => 'foo', 'bar' => 'bar', 42 => 1337]
); // ✅
```

**Interface constructor registration**

By default, the mapper cannot instantiate an interface, as it does not know
which implementation to use. To do so, the `MapperBuilder::infer()` method can
be used, but it is cumbersome in most cases.

It is now also possible to register a constructor for an interface, in the same
way as for a class.

Because the mapper cannot automatically guess which implementation can be used
for an interface, it is not possible to use the `Constructor` attribute, the
`MapperBuilder::registerConstructor()` method must be used instead.

In the example below, the mapper is taught how to instantiate an implementation
of `UuidInterface` from package `ramsey/uuid`:

```php
(new \CuyZ\Valinor\MapperBuilder())
->registerConstructor(
// The static method below has return type `UuidInterface`;
// therefore, the mapper will build an instance of `Uuid` when
// it needs to instantiate an implementation of `UuidInterface`.
Ramsey\Uuid\Uuid::fromString(...)
)
->mapper()
->map(
Ramsey\Uuid\UuidInterface::class,
'663bafbf-c3b5-4336-b27f-1796be8554e0'
);
```

**JSON normalizer formatting options**

By default, the JSON normalizer will only use `JSON_THROW_ON_ERROR` to encode
non-boolean scalar values. There might be use-cases where projects will need
flags like `JSON_JSON_PRESERVE_ZERO_FRACTION`.

This can be achieved by passing these flags to the new
`JsonNormalizer::withOptions()` method:

```php
namespace My\App;

$normalizer = (new \CuyZ\Valinor\MapperBuilder())
->normalizer(\CuyZ\Valinor\Normalizer\Format::json())
->withOptions(\JSON_PRESERVE_ZERO_FRACTION);

$lowerManhattanAsJson = $normalizer->normalize(
new \My\App\Coordinates(
longitude: 40.7128,
latitude: -74.0000
)
);

// `$lowerManhattanAsJson` is a valid JSON string representing the data:
// {"longitude":40.7128,"latitude":-74.0000}
```

The method accepts an int-mask of the following `JSON_*` constant
representations:

- `JSON_HEX_QUOT`
- `JSON_HEX_TAG`
- `JSON_HEX_AMP`
- `JSON_HEX_APOS`
- `JSON_INVALID_UTF8_IGNORE`
- `JSON_INVALID_UTF8_SUBSTITUTE`
- `JSON_NUMERIC_CHECK`
- `JSON_PRESERVE_ZERO_FRACTION`
- `JSON_UNESCAPED_LINE_TERMINATORS`
- `JSON_UNESCAPED_SLASHES`
- `JSON_UNESCAPED_UNICODE`

`JSON_THROW_ON_ERROR` is always enforced and thus is not accepted.

See official doc for more information:
https://www.php.net/manual/en/json.constants.php

### Features

* Allow JSON normalizer to set JSON formatting options ([cd5df9](https://github.com/CuyZ/Valinor/commit/cd5df97d45b2687b4a79bf01e4b03d7deee28dfa))
* Allow mapping to `array-key` type ([5020d6](https://github.com/CuyZ/Valinor/commit/5020d62e00e00fdb74ac26e83dd36b313e0a5ee1))
* Handle interface constructor registration ([13f69a](https://github.com/CuyZ/Valinor/commit/13f69a9e1b5ce7f7a2305933764a928adf08c7df))
* Handle type importation from interface ([3af22d](https://github.com/CuyZ/Valinor/commit/3af22d16f6a4034611859a5998e6d0317d61dc4f))
* Introduce unsealed shaped array syntax ([fa8bb0](https://github.com/CuyZ/Valinor/commit/fa8bb0020c8792a17eadc9df0559d44f908b5397))

### Bug Fixes

* Handle class tokens only when needed during lexing ([c4be75](https://github.com/CuyZ/Valinor/commit/c4be75844bc71912fdbf34fac2523ca184d3c15f))
* Load needed information only during interface inferring ([c8e204](https://github.com/CuyZ/Valinor/commit/c8e204a4a3cdfc681e99f80e0c1632e663a32161))

### Other

* Rename internal class ([4c62d8](https://github.com/CuyZ/Valinor/commit/4c62d87a68a7de4e60d070cb7298a19fd7ebad5a))

0 comments on commit 3bc4079

Please sign in to comment.