Created
January 3, 2023 18:14
-
-
Save dersonsena/9dbb68aa58cd18aed288dee3cedfcfe9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace App\Shared\Adapter\Contracts; | |
/** | |
* Interface Dto | |
*/ | |
interface Dto | |
{ | |
/** | |
* Associative array such as `'property' => 'value'` with all boundary values | |
* @return array | |
*/ | |
public function values(): array; | |
/** | |
* Get a DTO value by property | |
* @param string $property | |
* @return mixed | |
*/ | |
public function get(string $property): mixed; | |
/** | |
* Rules to validate DTO | |
* @return array ['fieldName' => ValidatorFieldCollection] | |
*/ | |
public function rules(): array; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace App\Shared\Adapter; | |
use App\Shared\Adapter\Contracts\Dto; | |
use App\Shared\Adapter\Exception\InvalidDtoParam; | |
use JsonSerializable; | |
use ReflectionClass; | |
use ReflectionProperty; | |
/** | |
* Class DtoBase | |
*/ | |
abstract class DtoBase implements Dto, JsonSerializable | |
{ | |
private array $values = []; | |
private bool $strict; | |
/** | |
* Boundary constructor. | |
* @param array $values | |
* @param bool $strict | |
* @throws InvalidDtoParam | |
*/ | |
private function __construct(array $values, bool $strict) | |
{ | |
$this->strict = $strict; | |
$reflect = new ReflectionClass($this); | |
$dtoProps = $reflect->getProperties(ReflectionProperty::IS_PROTECTED); | |
$dtoProps = array_map(fn (ReflectionProperty $property) => $property->name, $dtoProps); | |
foreach ($dtoProps as $propertyName) { | |
$property = new ReflectionProperty($this, $propertyName); | |
$defaultValue = match ($property->getType()->getName()) { | |
'string' => '', | |
'array' => [], | |
'bool' => true, | |
'int', 'double', 'float' => 0, | |
default => null | |
}; | |
if ($property->getType()->allowsNull()) { | |
$defaultValue = null; | |
} | |
$this->{$propertyName} = $defaultValue; | |
$this->values[$propertyName] = $defaultValue; | |
} | |
foreach ($values as $key => $value) { | |
if (mb_strstr($key, '_') !== false) { | |
$key = lcfirst(str_replace('_', '', ucwords($key, '_'))); | |
} | |
if (!property_exists($this, $key)) { | |
if (!$this->strict) { | |
continue; | |
} | |
throw InvalidDtoParam::dynamicParam(get_class(), $key); | |
} | |
$this->{$key} = $value; | |
$this->values[$key] = $this->get($key); | |
} | |
} | |
/** | |
* Static method to create a Boundary (TextField or Output) | |
* @param array $values Associative array such as `'property' => 'value'` | |
* @throws InvalidDtoParam | |
*/ | |
public static function create(array $values, bool $strict = false): static | |
{ | |
return new static($values, $strict); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function values(): array | |
{ | |
return $this->values; | |
} | |
/** | |
* {@inheritdoc} | |
* @throws InvalidDtoParam | |
*/ | |
public function get(string $property): mixed | |
{ | |
$getter = "get" . ucfirst($property); | |
if (method_exists($this, $getter)) { | |
return $this->{$getter}(); | |
} | |
if (!property_exists($this, $property)) { | |
throw InvalidDtoParam::dynamicParam(get_class(), $property); | |
} | |
return $this->{$property}; | |
} | |
public function jsonSerialize() | |
{ | |
return $this->values(); | |
} | |
public function rules(): array | |
{ | |
return []; | |
} | |
/** | |
* Magic getter method to get a DTO property value | |
* @param string $name | |
* @return mixed | |
* @throws InvalidDtoParam | |
*/ | |
public function __get(string $name) | |
{ | |
return $this->get($name); | |
} | |
public function __set(string $name, mixed $value) | |
{ | |
throw InvalidDtoParam::readonlyProperty(get_class(), $name, $value); | |
} | |
public function __isset($name): bool | |
{ | |
return property_exists($this, $name); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment