Skip to content

Commit

Permalink
splitting object definition onto interface as per daft-object
Browse files Browse the repository at this point in the history
  • Loading branch information
SignpostMarv committed Aug 5, 2019
1 parent 3c01fed commit f9bfa4b
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 126 deletions.
4 changes: 2 additions & 2 deletions Tests/DaftTypedObjectTest.php
Expand Up @@ -22,11 +22,11 @@ public function testPropertyValueToScalarOrNullFailsWithDateTimeImmutable(
'Unsupported value object given:' .
' %s::%s() only supports scalar and NULL'
),
DaftTypedObject::class,
AbstractDaftTypedObject::class,
'PropertyValueToScalarOrNull'
));

DaftTypedObject::PropertyValueToScalarOrNull(
AbstractDaftTypedObject::PropertyValueToScalarOrNull(
'foo',
new DateTimeImmutable()
);
Expand Down
2 changes: 1 addition & 1 deletion Tests/Fixtures/Mutable.php
Expand Up @@ -6,7 +6,7 @@

namespace SignpostMarv\DaftTypedObject\Fixtures;

use SignpostMarv\DaftTypedObject\DaftTypedObject as Base;
use SignpostMarv\DaftTypedObject\AbstractDaftTypedObject as Base;

/**
* @psalm-type DATA = array{id:int, name:string}
Expand Down
2 changes: 1 addition & 1 deletion Tests/Fixtures/MutableWithNullables.php
Expand Up @@ -7,7 +7,7 @@
namespace SignpostMarv\DaftTypedObject\Fixtures;

use DateTimeImmutable;
use SignpostMarv\DaftTypedObject\DaftTypedObject as Base;
use SignpostMarv\DaftTypedObject\AbstractDaftTypedObject as Base;

/**
* @template T as array{id:int, name:string, date:DateTimeImmutable|null}
Expand Down
197 changes: 197 additions & 0 deletions src/AbstractDaftTypedObject.php
@@ -0,0 +1,197 @@
<?php
/**
* @author SignpostMarv
*/
declare(strict_types=1);

namespace SignpostMarv\DaftTypedObject;

use InvalidArgumentException;

/**
* @template T as array<string, scalar|array|object|null>
* @template S as array<string, scalar|null>
*
* @template-implements DaftTypedObject<T, S>
*/
abstract class AbstractDaftTypedObject implements DaftTypedObject
{
/**
* @var array<int, key-of<T>>
*/
const TYPED_PROPERTIES = [];

/**
* @var array<int, key-of<T>>
*/
const TYPED_NULLABLE_PROPERTIES = [];

/**
* @param T $data
*/
public function __construct(array $data)
{
foreach ($data as $property => $value) {
$this->$property = $value;
}
}

/**
* @template K as key-of<T>
*
* @param K $property
*
* @return T[K]
*/
public function __get(string $property)
{
/**
* @var T[K]
*/
return $this->$property;
}

/**
* @template K as key-of<T>
*
* @param K $property
* @param T[K] $value
*/
public function __set(string $property, $value) : void
{
$this->$property = $value;
}

/**
* @template K as key-of<T>
*
* @param K $property
*/
public function __isset(string $property) : bool
{
return isset($this->$property);
}

/**
* @template K as key-of<T>
*
* @param K $property
*/
public function __unset(string $property) : void
{
/**
* @var array<int, key-of<T>>
*/
$nullables = static::TYPED_NULLABLE_PROPERTIES;

if ( ! in_array(
$property,
$nullables,
true
)) {
throw new InvalidArgumentException(sprintf(
'%s::$%s is not nullable!',
static::class,
$property
));
}

$this->$property = null;
}

/**
* @template K as key-of<T>
*
* @return S
*/
public function jsonSerialize() : array
{
/**
* @var array<int, K>
*/
$properties = static::TYPED_PROPERTIES;

/**
* @var S
*/
return array_combine($properties, array_map(
[$this, 'PropertyMapperToScalarOrNull'],
$properties
));
}

/**
* @template K as key-of<T>
*
* @param K $_property
* @param T[K] $value
*
* @return S[K]
*/
public static function PropertyValueToScalarOrNull(
string $_property,
$value
) {
/**
* @var scalar|array|object|null
*/
$value = $value;

if ( ! is_scalar($value) && ! is_null($value)) {
throw new InvalidArgumentException(sprintf(
(
'Unsupported value %s given:' .
' %s() only supports scalar and NULL'
),
gettype($value),
__METHOD__
));
}

/**
* @var S[K]
*/
return $value;
}

/**
* @template K as key-of<T>
*
* @param K $_property
* @param S[K] $value
*
* @return T[K]
*/
public static function PropertyScalarOrNullToValue(
string $_property,
$value
) {
/**
* @var T[K]
*/
return $value;
}

/**
* @template K as key-of<T>
*
* @param K $property
*
* @return S[K]
*/
protected function PropertyMapperToScalarOrNull(string $property)
{
/**
* @var T[K]
*/
$value = $this->$property;

/**
* @var S[K]
*/
return static::PropertyValueToScalarOrNull(
(string) $property,
$value
);
}
}

0 comments on commit f9bfa4b

Please sign in to comment.