Skip to content

Commit e396e81

Browse files
committed
Add metadata readers and meta configuration pages
1 parent 4d004ac commit e396e81

24 files changed

+2335
-30
lines changed

Writerside/tl.tree

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,41 @@
6262
<toc-element topic="custom-type-coercer.md" />
6363
</toc-element>
6464
<toc-element topic="type-metadata.md">
65-
<toc-element topic="meta-reader.md" />
66-
<toc-element topic="meta-provider.md" />
65+
<toc-element topic="meta-configuration.md"
66+
toc-title="Writing Metadata"/>
67+
<toc-element topic="meta-reader.md">
68+
<toc-element topic="meta-reader-reflection.md"
69+
toc-title="Reflection" />
70+
<toc-element topic="meta-reader-attribute.md"
71+
toc-title="Attributes" />
72+
<toc-element topic="meta-reader-phpdoc.md"
73+
toc-title="PHPDoc" />
74+
<toc-element topic="meta-reader-array.md"
75+
toc-title="PHP Array" />
76+
<toc-element topic="meta-reader-php-config.md"
77+
toc-title="PHP Config Files" />
78+
<toc-element topic="meta-reader-json-config.md"
79+
toc-title="JSON Config Files" />
80+
<toc-element topic="meta-reader-neon-config.md"
81+
toc-title="NEON Config Files" />
82+
<toc-element topic="meta-reader-yaml-config.md"
83+
toc-title="YAML Config Files"/>
84+
<toc-element topic="meta-reader-null.md"
85+
toc-title="Null" />
86+
</toc-element>
87+
<toc-element topic="meta-provider.md">
88+
<toc-element topic="meta-provider-in-memory.md"
89+
toc-title="InMemory" />
90+
<toc-element topic="meta-provider-psr6-cache.md"
91+
toc-title="PSR-6 Cache" />
92+
<toc-element topic="meta-provider-psr16-cache.md"
93+
toc-title="PSR-16 Cache" />
94+
<toc-element topic="meta-provider-null.md"
95+
toc-title="Null" />
96+
</toc-element>
97+
<toc-element topic="meta-expressions.md" />
98+
<toc-element topic="meta-clock.md" />
99+
<toc-element topic="meta-references.md" />
67100
</toc-element>
68101
<toc-element topic="type-extractors.md">
69102
<toc-element topic="native-type-extractor.md" />
@@ -77,6 +110,9 @@
77110
toc-title="Feature toggling"/>
78111
<toc-element topic="tolerant-mode.md"
79112
toc-title="Tolerant mode"/>
113+
<toc-element toc-title="AST">
114+
<toc-element topic="ast-type-statements.md" />
115+
</toc-element>
80116
<toc-element topic="visitors.md">
81117
<toc-element topic="class-name-matcher-visitor.md"/>
82118
<toc-element topic="stream-dumper-visitor.md"/>

Writerside/topics/mapper/builders/custom-type-builder.md

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ requires the implementation of two methods:
1515
- `build()` - Creates [a `TypeInterface` instance](types.md)
1616

1717
```php
18+
use TypeLang\Mapper\Type\Builder\TypeBuilderInterface;
1819
use TypeLang\Mapper\Type\Parser\TypeParserInterface;
1920
use TypeLang\Mapper\Type\Repository\TypeRepositoryInterface;
2021
use TypeLang\Mapper\Type\TypeInterface;
@@ -51,7 +52,83 @@ final readonly class JsonTypeBuilder implements TypeBuilderInterface
5152
}
5253
```
5354

54-
<warning>
55-
This is just an example, it is not necessary to pass the container
56-
to each type builder.
57-
</warning>
55+
## Matching
56+
57+
First, for the builder to work and construct the type, a checking method
58+
`isSupported()` must be implemented.
59+
60+
For example, if we want to check that the type is called `json`, the code
61+
will look like this:
62+
63+
```php
64+
use TypeLang\Parser\Node\Stmt\NamedTypeNode;
65+
66+
// ...
67+
68+
public function isSupported(TypeStatement $statement): bool
69+
{
70+
return $statement instanceof NamedTypeNode
71+
&& $statement->name->toLowerString() === 'json';
72+
}
73+
```
74+
75+
Each named type is implemented using
76+
[the `NamedTypeNode` instance](ast-type-statements.md#named-types).
77+
78+
<tip>
79+
A more detailed description of some of the available nodes in
80+
<a href="ast-type-statements.md">the <code>TypeStatement</code> documentation pages</a>
81+
</tip>
82+
83+
84+
### Building
85+
86+
Next, we need to implement the type creation method. If the type doesn't
87+
have any external dependencies, then creating the type will be quite simple.
88+
89+
```php
90+
public function build(
91+
TypeStatement $statement,
92+
TypeRepositoryInterface $types,
93+
TypeParserInterface $parser,
94+
): JsonType {
95+
return new JsonType();
96+
}
97+
```
98+
99+
However, in this case the same `JsonType` instance will be returned,
100+
**no matter** how you write the type definition:
101+
- `json`
102+
- `json<T>`
103+
- `json{key: val}`
104+
- `json{key: val, ...<T>}`
105+
- etc.
106+
107+
You can add appropriate checks to exclude template arguments and shape fields.
108+
109+
```php
110+
use TypeLang\Mapper\Exception\Definition\{
111+
Shape\ShapeFieldsNotSupportedException,
112+
Template\TemplateArgumentsNotSupportedException
113+
};
114+
115+
// ...
116+
117+
public function build(
118+
TypeStatement $statement,
119+
TypeRepositoryInterface $types,
120+
TypeParserInterface $parser,
121+
): JsonType {
122+
if ($statement->fields !== null) {
123+
throw ShapeFieldsNotSupportedException
124+
::becauseShapeFieldsNotSupported($statement);
125+
}
126+
127+
if ($statement->arguments !== null) {
128+
throw TemplateArgumentsNotSupportedException
129+
::becauseTemplateArgumentsNotSupported($statement);
130+
}
131+
132+
return new JsonType();
133+
}
134+
```

Writerside/topics/mapper/mapper-configuration.md

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ $mapper = new TypeLang\Mapper\Mapper(
6666
This option is responsible for converting user defined objects
6767
PHP into associative arrays.
6868

69+
<note>
70+
This configuration option is enabled by default
71+
</note>
72+
6973
<note>
7074
This option is only applicable if the output can be an array or an object.
7175
For example, in the <a href="standard-platform.md">standard platform</a>.
@@ -129,29 +133,15 @@ $result = new Mapper(config: $config)
129133
This option is responsible for disabling the strict comparison
130134
mode and attempts to coerce (cast) the values.
131135

136+
<note>
137+
This configuration option is disabled by default
138+
</note>
139+
132140
<tip>
133141
When this option is enabled, the corresponding cast rules
134142
defined in the <a href="type-coercers.md">type coercers</a> are enabled.
135143
</tip>
136144

137-
<warning>
138-
If the configuration value is not set, the option will
139-
be will depend on which direction is used:
140-
<list>
141-
<li>
142-
<b>Normalization</b>:
143-
144-
<code>strictTypes: false</code>
145-
</li>
146-
<li>
147-
<b>Denormalization</b>:
148-
149-
<code>strictTypes: true</code>
150-
</li>
151-
</list>
152-
</warning>
153-
154-
155145
<tabs>
156146
<tab title="default (null)">
157147
<code-block lang="php">
@@ -168,9 +158,9 @@ $result = new Mapper(config: $config)
168158
$result = new Mapper(config: $config)
169159
->denormalize(['k' => 42], 'list<string>');
170160

171-
// TypeLang\Mapper\Exception\Mapping\InvalidValueException:
172-
// Passed value {"k": 42} is invalid
173-
//
161+
// array:1 [
162+
// 0 => "42"
163+
// ]
174164
]]>
175165
</code-block>
176166
</tab>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Date/Time (Clock)
2+
3+
After metadata building, each DTO stores a datetime snapshot with the DTO
4+
build time to prevent reading stale data (this can be used, for example,
5+
in cache implementations).
6+
7+
To ensure testing, the time generator can be passed explicitly using
8+
any [PSR-20 library](https://www.php-fig.org/psr/psr-20/).
9+
10+
Here are the [most popular](https://packagist.org/providers/psr/clock-implementation)
11+
implementations:
12+
- [nesbot/carbon](https://packagist.org/packages/nesbot/carbon)
13+
- [symfony/clock](https://packagist.org/packages/symfony/clock)
14+
- [lcobucci/clock](https://packagist.org/packages/lcobucci/clock)
15+
- [beste/clock](https://packagist.org/packages/beste/clock)
16+
- [cakephp/chronos](https://packagist.org/packages/cakephp/chronos)
17+
- ...and [many other](https://packagist.org/providers/psr/clock-implementation)
18+
19+
To create a time provider, you can install any implementation, for example:
20+
```shell
21+
composer require symfony/clock
22+
```
23+
24+
Or write your own:
25+
```php
26+
final MySimpleClock implements [[[Psr\Clock\ClockInterface|https://www.php-fig.org/psr/psr-20/]]]
27+
{
28+
public function now(): \DateTimeImmutable
29+
{
30+
return new \DateTimeImmutable();
31+
}
32+
}
33+
```
34+
35+
Next, in case for the datetime to be "applied" to the metadata, the
36+
implementation must be passed to the
37+
[`MetadataBuilder` metadata provider](meta-provider.md).
38+
39+
```php
40+
use TypeLang\Mapper\Mapping\Provider\MetadataBuilder;
41+
42+
$provider = [[[new MetadataBuilder(|meta-provider.md]]]
43+
clock: new MySimpleClock(),
44+
);
45+
```

0 commit comments

Comments
 (0)