Skip to content

Introducing Data Configuration #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
487 changes: 287 additions & 200 deletions clover.xml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/CloneableData.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ $todoWithDueDate = $todo->with(
);
```

> We are using the `empty` method
> **Note:** We are using the `empty` method
> from [Empty Data](https://github.com/nuxtifyts/php-dto/blob/main/docs/EmptyData.md)
> here

> `emptyTodo`, `todo` and `todoWithDueDate` are all different instances.
> **Important:** `emptyTodo`, `todo` and `todoWithDueDate` are all different instances.

Computed properties
-
Expand Down
43 changes: 43 additions & 0 deletions docs/DataConfiguration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
Data Configuration
=

The library uses a configuration based approach to define, load and save data.
It uses a `DataConfiguration` object to define many things:

```php
use Nuxtifyts\PhpDto\Configuration\DataConfiguration;

$config = DataConfiguration::getInstance();
```

The function's signature is:

| Argument | Type | Description |
|-------------|---------------|-------------------------------------------------------------------------------------------------|
| config | array \| null | The configuration array to load, by default it's `null`, which means switch to default configs. |
| forceCreate | bool | If `true`, it will create a new instance of `DataConfiguration` even if it's already created. |

If nothing is passed, it will be the equivalent of:

```php
DataConfiguration::getInstance([
'normalizers' => [
'baseNormalizers' => [
JsonStringNormalizer::class,
StdClassNormalizer::class,
ArrayAccessNormalizer::class,
ArrayNormalizer::class,
],
],

'serializers' => [
'baseSerializers' => [
ArraySerializer::class,
DataSerializer::class,
DateTimeSerializer::class,
BackedEnumSerializer::class,
ScalarTypeSerializer::class,
]
]
])
```
2 changes: 1 addition & 1 deletion docs/DefaultValues.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class UserConfigDataFallbackResolver implements FallbackResolver
}
```

>! When using `DefaultsTo` attribute, priority is given to the attribute instead of the parameter's default value.
> When using `DefaultsTo` attribute, priority is given to the attribute instead of the parameter's default value.

If ever needed to create a new instance of a DTO with complex default value,
using the constructor is no longer possible, instead, you can make use of the
Expand Down
2 changes: 1 addition & 1 deletion docs/EmptyData.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ By calling the `empty()` method, we can create a new instance of the `TodoData`
$emptyTodo = TodoData::empty();
```

> This is really useful with [Cloneable Data](https://github.com/nuxtifyts/php-dto/blob/main/docs/CloneableData.md)
> **Note:** This is really useful with [Cloneable Data](https://github.com/nuxtifyts/php-dto/blob/main/docs/CloneableData.md)

The `$emptyTodo` variable will contain the following data:

Expand Down
7 changes: 6 additions & 1 deletion docs/Normalizers.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ data into (preferable) an `array`/`ArrayAccess`.
By default, there are 4 normalizers:

- **JsonStringNormalizer** will cast json string.
- **StrClassNormalizer** will cast stdObject.
- **StdClassNormalizer** will cast stdObject.
- **ArrayAccessNormalizer** will cast ArrayAccess.
- **ArrayNormalizer** will cast array.

> **Note:** In order to adjust there default normalizers, for example, you don't need
> to use the `StdClassNormalizer` and you want to simply remove it, you need
> to [configure](https://github.com/nuxtifyts/php-dto/blob/main/docs/DataConfiguration.md)
> the `DataConfiguration` object.

Custom normalizers:
=

Expand Down
1 change: 1 addition & 0 deletions docs/Quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,4 @@ can be found here:
- [Data Refiners](https://github.com/nuxtifyts/php-dto/blob/main/docs/DataRefiners.md)
- [Empty Data](https://github.com/nuxtifyts/php-dto/blob/main/docs/EmptyData.md)
- [Cloneable Data](https://github.com/nuxtifyts/php-dto/blob/main/docs/CloneableData.md)
- [Data Configuration](https://github.com/nuxtifyts/php-dto/blob/main/docs/DataConfiguration.md)
2 changes: 1 addition & 1 deletion src/Concerns/BaseData.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
use Nuxtifyts\PhpDto\Exceptions\DataCreationException;
use Nuxtifyts\PhpDto\Exceptions\DeserializeException;
use Nuxtifyts\PhpDto\Exceptions\SerializeException;
use Nuxtifyts\PhpDto\Normalizers\Concerns\HasNormalizers;
use Nuxtifyts\PhpDto\Pipelines\DeserializePipeline\DeserializePipeline;
use Nuxtifyts\PhpDto\Pipelines\DeserializePipeline\DeserializePipelinePassable;
use Nuxtifyts\PhpDto\Support\Traits\HasNormalizers;
use ReflectionClass;
use Throwable;

Expand Down
4 changes: 2 additions & 2 deletions src/Concerns/CloneableData.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Nuxtifyts\PhpDto\Contexts\ClassContext;
use Nuxtifyts\PhpDto\Exceptions\DataCreationException;
use Nuxtifyts\PhpDto\Support\Traits\HasNormalizers;
use Nuxtifyts\PhpDto\Normalizers\Concerns\HasNormalizers;
use ReflectionClass;
use Throwable;

Expand Down Expand Up @@ -36,7 +36,7 @@ public function with(mixed ...$args): static
? $this->cloneInstanceWithConstructorCall($context, $value)
: $this->cloneInstanceWithoutConstructorCall($context, $value);
} catch (Throwable $t) {
throw DataCreationException::unableToCloneInstanceWithNewData($t);
throw DataCreationException::unableToCloneInstanceWithNewData(static::class, $t);
}
}

Expand Down
18 changes: 18 additions & 0 deletions src/Configuration/Configuration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Nuxtifyts\PhpDto\Configuration;

use Nuxtifyts\PhpDto\Exceptions\DataConfigurationException;

interface Configuration
{
/**
* @param ?array<string, mixed> $config
*
* @throws DataConfigurationException
*/
public static function getInstance(
?array $config = null,
bool $forceCreate = false
): self;
}
42 changes: 42 additions & 0 deletions src/Configuration/DataConfiguration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Nuxtifyts\PhpDto\Configuration;

use Nuxtifyts\PhpDto\Exceptions\DataConfigurationException;
use Nuxtifyts\PhpDto\Support\Arr;

class DataConfiguration implements Configuration
{
protected static ?self $instance = null;

protected function __construct(
protected(set) NormalizersConfiguration $normalizers,
protected(set) SerializersConfiguration $serializers,
) {
}

/**
* @param array<array-key, mixed> $config
*
* @throws DataConfigurationException
*/
public static function getInstance(
?array $config = null,
bool $forceCreate = false
): self {
if (self::$instance && !$forceCreate) {
return self::$instance;
}

return self::$instance = new self(
normalizers: NormalizersConfiguration::getInstance(
Arr::getArray($config ?? [], 'normalizers'),
$forceCreate
),
serializers: SerializersConfiguration::getInstance(
Arr::getArray($config ?? [], 'serializers'),
$forceCreate
)
);
}
}
57 changes: 57 additions & 0 deletions src/Configuration/NormalizersConfiguration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Nuxtifyts\PhpDto\Configuration;

use Nuxtifyts\PhpDto\Exceptions\DataConfigurationException;
use Nuxtifyts\PhpDto\Normalizers\ArrayAccessNormalizer;
use Nuxtifyts\PhpDto\Normalizers\ArrayNormalizer;
use Nuxtifyts\PhpDto\Normalizers\JsonStringNormalizer;
use Nuxtifyts\PhpDto\Normalizers\Normalizer;
use Nuxtifyts\PhpDto\Normalizers\StdClassNormalizer;
use Nuxtifyts\PhpDto\Support\Arr;

class NormalizersConfiguration implements Configuration
{
protected static ?self $instance = null;

/**
* @param array<array-key, class-string<Normalizer>> $baseNormalizers
*/
protected function __construct(
protected(set) array $baseNormalizers
) {
}

/**
* @param ?array<array-key, mixed> $config
*
* @throws DataConfigurationException
*/
public static function getInstance(
?array $config = null,
bool $forceCreate = false
): self {
if (self::$instance && !$forceCreate) {
return self::$instance;
}

$baseNormalizers = $config['baseNormalizers'] ?? [
JsonStringNormalizer::class,
StdClassNormalizer::class,
ArrayAccessNormalizer::class,
ArrayNormalizer::class,
];

if (
!is_array($baseNormalizers)
|| !Arr::isArrayOfClassStrings($baseNormalizers, Normalizer::class)
) {
throw DataConfigurationException::invalidBaseNormalizers();
}
/** @var array<array-key, class-string<Normalizer>> $baseNormalizers */

return self::$instance = new self(
baseNormalizers: $baseNormalizers
);
}
}
59 changes: 59 additions & 0 deletions src/Configuration/SerializersConfiguration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace Nuxtifyts\PhpDto\Configuration;

use Nuxtifyts\PhpDto\Exceptions\DataConfigurationException;
use Nuxtifyts\PhpDto\Serializers\ArraySerializer;
use Nuxtifyts\PhpDto\Serializers\BackedEnumSerializer;
use Nuxtifyts\PhpDto\Serializers\DataSerializer;
use Nuxtifyts\PhpDto\Serializers\DateTimeSerializer;
use Nuxtifyts\PhpDto\Serializers\ScalarTypeSerializer;
use Nuxtifyts\PhpDto\Serializers\Serializer;
use Nuxtifyts\PhpDto\Support\Arr;

class SerializersConfiguration implements Configuration
{
protected static ?self $instance = null;

/**
* @param array<array-key, class-string<Serializer>> $baseSerializers
*/
protected function __construct(
protected(set) array $baseSerializers,
) {
}

/**
* @param ?array<array-key, mixed> $config
*
* @throws DataConfigurationException
*/
public static function getInstance(
?array $config = null,
bool $forceCreate = false
): self {
if (self::$instance && !$forceCreate) {
return self::$instance;
}

$baseSerializers = $config['baseSerializers'] ?? [
ArraySerializer::class,
DataSerializer::class,
DateTimeSerializer::class,
BackedEnumSerializer::class,
ScalarTypeSerializer::class,
];

if (
!is_array($baseSerializers)
|| !Arr::isArrayOfClassStrings($baseSerializers, Serializer::class)
) {
throw DataConfigurationException::invalidBaseSerializers();
}
/** @var array<array-key, class-string<Serializer>> $baseSerializers */

return self::$instance = new self(
baseSerializers: $baseSerializers
);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Nuxtifyts\PhpDto\Support\Traits;
namespace Nuxtifyts\PhpDto\Contexts\Concerns;

use Nuxtifyts\PhpDto\Contexts\TypeContext;
use Nuxtifyts\PhpDto\Enums\Property\Type;
Expand Down
19 changes: 11 additions & 8 deletions src/Contexts/PropertyContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,33 @@
namespace Nuxtifyts\PhpDto\Contexts;

use BackedEnum;
use Nuxtifyts\PhpDto\Exceptions\DataCreationException;
use UnitEnum;
use DateTimeInterface;
use Exception;
use Nuxtifyts\PhpDto\Attributes\Property\Aliases;
use Nuxtifyts\PhpDto\Attributes\Property\CipherTarget;
use Nuxtifyts\PhpDto\Attributes\Property\Computed;
use Nuxtifyts\PhpDto\Attributes\Property\DefaultsTo;
use Nuxtifyts\PhpDto\Attributes\Property\WithRefiner;
use Nuxtifyts\PhpDto\Contexts\Concerns\HasTypes;
use Nuxtifyts\PhpDto\Data;
use Nuxtifyts\PhpDto\DataCiphers\CipherConfig;
use Nuxtifyts\PhpDto\DataRefiners\DataRefiner;
use Nuxtifyts\PhpDto\Enums\Property\Type;
use Nuxtifyts\PhpDto\Exceptions\DataConfigurationException;
use Nuxtifyts\PhpDto\Exceptions\DataCreationException;
use Nuxtifyts\PhpDto\Exceptions\DeserializeException;
use Nuxtifyts\PhpDto\Exceptions\SerializeException;
use Nuxtifyts\PhpDto\Exceptions\UnknownTypeException;
use Nuxtifyts\PhpDto\Exceptions\UnsupportedTypeException;
use Nuxtifyts\PhpDto\FallbackResolver\FallbackConfig;
use Nuxtifyts\PhpDto\Serializers\Concerns\HasSerializers;
use Nuxtifyts\PhpDto\Serializers\Serializer;
use Nuxtifyts\PhpDto\Support\Traits\HasSerializers;
use Nuxtifyts\PhpDto\Support\Traits\HasTypes;
use DateTimeInterface;
use ReflectionAttribute;
use ReflectionClass;
use ReflectionEnum;
use ReflectionException;
use ReflectionProperty;
use ReflectionAttribute;
use ReflectionClass;
use Exception;
use UnitEnum;

class PropertyContext
{
Expand Down Expand Up @@ -173,6 +174,7 @@ public function getFilteredSubTypeContexts(Type $type, Type ...$additionalTypes)
* @return list<Serializer>
*
* @throws UnknownTypeException
* @throws DataConfigurationException
*/
protected function resolveSerializers(): array
{
Expand All @@ -184,6 +186,7 @@ protected function resolveSerializers(): array
*
* @throws DeserializeException
* @throws UnknownTypeException
* @throws DataConfigurationException
*/
public function deserializeFrom(array $value): mixed
{
Expand Down
Loading
Loading