Skip to content

Commit

Permalink
v1.14.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrii Savluk committed Apr 4, 2023
1 parent 427ad80 commit 61ebcdd
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 11 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,33 @@ use Savks\Negotiator\Support\DTO\{

new Intersection(
new UserMapper($this->user),
new ObjectValue( $this->user, fn (Factory $factory) => [
new ObjectValue($this->user, fn (Factory $factory) => [
'otherField' => $factory->string('other_field')
]),
);
```

* `oneOfConst` — дозволяє вказати, що значення може набувати одного з типів-констант. Приклад:

```php
<?php

use App\Models\User;

use Savks\Negotiator\Support\DTO\{
Utils\Factory,
ObjectValue
};

new ObjectValue($this->source, fn (Factory $factory) => [
'field' => $factory->oneOfConst([
$factory->constNumber(1),
$factory->constNumber(2),
$factory->constNumber(3),
]),
]);
```

## Генерація типів

Для генерації типів пакет містить клас генератора `Savks\Negotiator\Support\TypeGeneration\Generator`. Для роботи якого достатньо вказання для яких маперів і з якими просторами імен потрібно згенерувати код. Приклад використання:
Expand Down
8 changes: 8 additions & 0 deletions src/Support/DTO/Castable.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,12 @@ public function null(): NullValue
{
return new NullValue();
}

/**
* @param list<ConstBooleanValue|ConstEnumValue|ConstNumberValue|ConstStringValue> $values
*/
public function oneOfConst(array $values, string|Closure|null $accessor = null): OneOfConstValue
{
return new OneOfConstValue($this->source, $values, $accessor);
}
}
10 changes: 9 additions & 1 deletion src/Support/DTO/ConstBooleanValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,22 @@
ConstBooleanType
};

class ConstBooleanValue extends Value
/**
* @extends ConstValue<bool>
*/
class ConstBooleanValue extends ConstValue
{
public function __construct(
protected readonly bool $value,
protected readonly bool $asAnyBool
) {
}

public function originalValue(): bool
{
return $this->value;
}

protected function finalize(): bool
{
return $this->value;
Expand Down
24 changes: 17 additions & 7 deletions src/Support/DTO/ConstEnumValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,47 @@
namespace Savks\Negotiator\Support\DTO;

use BackedEnum;
use ReflectionEnum;
use ReflectionNamedType;
use Savks\Negotiator\Contexts\TypeGenerationContext;
use Savks\PhpContexts\Context;
use StringBackedEnum;

use Savks\Negotiator\Support\Types\{
AliasType,
NumberType,
StringType
};

class ConstEnumValue extends NullableValue
class ConstEnumValue extends ConstValue
{
public function __construct(protected BackedEnum $case)
public function __construct(protected readonly BackedEnum $case)
{
}

public function originalValue(): BackedEnum
{
return $this->case;
}

protected function finalize(): string|int|null
{
return $this->case->value;
}

protected function types(): AliasType|StringType|NumberType
{
$enumRef = Context::use(TypeGenerationContext::class)->resolveEnumRef(
$this->case::class
);
/** @var TypeGenerationContext $typeGenerationContext */
$typeGenerationContext = Context::use(TypeGenerationContext::class);

$enumRef = $typeGenerationContext->resolveEnumRef($this->case::class);

if ($enumRef) {
return new AliasType("{$enumRef}.{$this->case->name}");
}

return $this->case instanceof StringBackedEnum ? new StringType() : new NumberType();
/** @var ReflectionNamedType $type */
$type = (new ReflectionEnum($this->case))->getBackingType();

return $type->getName() === 'string' ? new StringType() : new NumberType();
}
}
7 changes: 6 additions & 1 deletion src/Support/DTO/ConstNumberValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@
NumberType
};

class ConstNumberValue extends Value
class ConstNumberValue extends ConstValue
{
public function __construct(
protected readonly int|float $value,
protected readonly bool $asAnyNumber
) {
}

public function originalValue(): int|float
{
return $this->value;
}

protected function finalize(): int|float
{
return $this->value;
Expand Down
7 changes: 6 additions & 1 deletion src/Support/DTO/ConstStringValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@
StringType
};

class ConstStringValue extends Value
class ConstStringValue extends ConstValue
{
public function __construct(
protected readonly string $value,
protected readonly bool $asAnyString
) {
}

public function originalValue(): string
{
return $this->value;
}

protected function finalize(): string
{
return $this->value;
Expand Down
14 changes: 14 additions & 0 deletions src/Support/DTO/ConstValue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Savks\Negotiator\Support\DTO;

/**
* @template TOriginalValueType
*/
abstract class ConstValue extends Value
{
/**
* @return TOriginalValueType
*/
abstract public function originalValue(): mixed;
}
101 changes: 101 additions & 0 deletions src/Support/DTO/OneOfConstValue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

namespace Savks\Negotiator\Support\DTO;

use BackedEnum;
use Closure;
use RuntimeException;
use Savks\Negotiator\Exceptions\UnexpectedValue;

use Savks\Negotiator\Support\Types\{
BooleanType,
ConstBooleanType,
ConstNumberType,
ConstStringType,
NumberType,
StringType,
Types
};

class OneOfConstValue extends NullableValue
{
/**
* @param ConstValue[] $values
*/
public function __construct(
protected readonly mixed $source,
protected readonly array $values,
protected readonly string|Closure|null $accessor = null
) {
}

protected function finalize(): string|int|float|bool|null
{
$value = $this->resolveValueFromAccessor(
$this->accessor,
$this->source,
$this->sourcesTrace
);

if ($this->accessor && last($this->sourcesTrace) !== $this->source) {
$this->sourcesTrace[] = $this->source;
}

if ($value === null) {
return null;
}

$isMatched = null;

foreach ($this->values as $constValue) {
$isMatched = $constValue->originalValue() === $value;

if ($isMatched) {
break;
}
}

if (! $isMatched) {
$types = [];

foreach ($this->values as $constValue) {
if ($constValue instanceof ConstEnumValue) {
$types[] = 'BackedEnum<' . $constValue->originalValue()::class . '>';
} else {
foreach ($constValue->compileTypes()->types as $type) {
$types[] = match (true) {
$type instanceof ConstBooleanType => $type->value ? 'true' : 'false',

$type instanceof ConstNumberType, $type instanceof ConstStringType => $type->value,

$type instanceof BooleanType => 'bool',
$type instanceof NumberType => 'numeric',
$type instanceof StringType => 'string',

default => throw new RuntimeException(
\sprintf('Unprocessed type "%s".', $type::class)
)
};
}
}
}

throw new UnexpectedValue($types, $value);
}

return $value instanceof BackedEnum ? $value->value : $value;
}

protected function types(): Types
{
$types = [];

foreach ($this->values as $value) {
$types[] = $value->compileTypes()->types;
}

return new Types(
\array_merge(...$types)
);
}
}

0 comments on commit 61ebcdd

Please sign in to comment.