2018-08-08 10:12:45 -04:00
|
|
|
<?php declare(strict_types=1);
|
|
|
|
/**
|
|
|
|
* Hummingbird Anime List Client
|
|
|
|
*
|
2018-08-22 13:48:27 -04:00
|
|
|
* An API client for Kitsu to manage anime and manga watch lists
|
2018-08-08 10:12:45 -04:00
|
|
|
*
|
2021-02-04 11:57:01 -05:00
|
|
|
* PHP version 8
|
2018-08-08 10:12:45 -04:00
|
|
|
*
|
|
|
|
* @package HummingbirdAnimeClient
|
|
|
|
* @author Timothy J. Warren <tim@timshomepage.net>
|
2021-01-13 01:52:03 -05:00
|
|
|
* @copyright 2015 - 2021 Timothy J. Warren
|
2018-08-08 10:12:45 -04:00
|
|
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
2020-12-10 17:06:50 -05:00
|
|
|
* @version 5.2
|
2018-08-08 10:12:45 -04:00
|
|
|
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace Aviat\AnimeClient\Types;
|
|
|
|
|
|
|
|
use ArrayAccess;
|
2019-10-07 20:10:27 -04:00
|
|
|
use Countable;
|
2018-08-08 10:12:45 -04:00
|
|
|
|
2022-03-03 13:25:10 -05:00
|
|
|
abstract class AbstractType implements ArrayAccess, Countable, \Stringable {
|
2018-08-08 13:05:38 -04:00
|
|
|
/**
|
2018-10-05 14:32:05 -04:00
|
|
|
* Populate values for un-serializing data
|
2018-08-08 13:05:38 -04:00
|
|
|
*/
|
2021-02-10 17:17:51 -05:00
|
|
|
public static function __set_state(mixed $properties): self
|
2018-08-08 13:05:38 -04:00
|
|
|
{
|
|
|
|
return new static($properties);
|
|
|
|
}
|
|
|
|
|
2020-04-21 19:22:56 -04:00
|
|
|
/**
|
|
|
|
* Check the shape of the object, and return the array equivalent
|
|
|
|
*/
|
2021-12-02 17:08:11 -05:00
|
|
|
final public static function check(array $data = []): ?array
|
2020-04-21 19:22:56 -04:00
|
|
|
{
|
|
|
|
$currentClass = static::class;
|
|
|
|
|
|
|
|
if (get_parent_class($currentClass) !== FALSE)
|
|
|
|
{
|
2021-02-10 17:31:20 -05:00
|
|
|
return static::class::from($data)->toArray();
|
2020-04-21 19:22:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-04-22 07:53:52 -04:00
|
|
|
/**
|
|
|
|
* Static constructor
|
|
|
|
*/
|
2021-02-10 17:17:51 -05:00
|
|
|
final public static function from(mixed $data): static
|
2020-04-22 07:53:52 -04:00
|
|
|
{
|
|
|
|
return new static($data);
|
|
|
|
}
|
|
|
|
|
2018-08-08 10:12:45 -04:00
|
|
|
/**
|
|
|
|
* Sets the properties by using the constructor
|
|
|
|
*/
|
2021-02-10 17:17:51 -05:00
|
|
|
final private function __construct(mixed $data = [])
|
2018-08-08 10:12:45 -04:00
|
|
|
{
|
2018-08-09 11:34:02 -04:00
|
|
|
$typeKeys = array_keys((array)$this);
|
|
|
|
$dataKeys = array_keys((array)$data);
|
|
|
|
|
|
|
|
$unsetKeys = array_diff($typeKeys, $dataKeys);
|
|
|
|
|
|
|
|
foreach ($data as $key => $value)
|
|
|
|
{
|
|
|
|
$this->__set($key, $value);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove unset keys so that they aren't serialized
|
|
|
|
foreach ($unsetKeys as $k)
|
|
|
|
{
|
|
|
|
unset($this->$k);
|
2018-08-08 10:12:45 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* See if a property is set
|
|
|
|
*/
|
2021-02-10 17:17:51 -05:00
|
|
|
final public function __isset(string $name): bool
|
2018-08-08 10:12:45 -04:00
|
|
|
{
|
2020-01-15 15:22:38 -05:00
|
|
|
return property_exists($this, $name) && isset($this->$name);
|
2018-08-08 10:12:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set a property on the type object
|
|
|
|
*/
|
2021-02-10 17:17:51 -05:00
|
|
|
final public function __set(string $name, mixed $value): void
|
2018-08-08 10:12:45 -04:00
|
|
|
{
|
2018-08-09 11:34:02 -04:00
|
|
|
$setterMethod = 'set' . ucfirst($name);
|
|
|
|
|
|
|
|
if (method_exists($this, $setterMethod))
|
|
|
|
{
|
|
|
|
$this->$setterMethod($value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-24 14:23:01 -04:00
|
|
|
if ( ! property_exists($this, $name))
|
2018-08-09 11:34:02 -04:00
|
|
|
{
|
2022-03-03 13:25:10 -05:00
|
|
|
$existing = json_encode($this, JSON_THROW_ON_ERROR);
|
2018-08-08 10:12:45 -04:00
|
|
|
|
2022-03-03 13:25:10 -05:00
|
|
|
throw new UndefinedPropertyException("Trying to set undefined property: '{$name}'. Existing properties: {$existing}");
|
2018-08-08 10:12:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
$this->$name = $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a property from the type object
|
|
|
|
*/
|
2021-02-10 17:17:51 -05:00
|
|
|
final public function __get(string $name): mixed
|
2018-08-08 10:12:45 -04:00
|
|
|
{
|
2020-01-15 12:35:37 -05:00
|
|
|
// Be a bit more lenient here, so that you can easily typecast missing
|
|
|
|
// values to reasonable defaults, and not have to resort to array indexes
|
|
|
|
return ($this->__isset($name)) ? $this->$name : NULL;
|
2018-08-08 10:12:45 -04:00
|
|
|
}
|
|
|
|
|
2019-08-10 10:09:07 -04:00
|
|
|
/**
|
|
|
|
* Create a string representation of the object for debugging
|
|
|
|
*/
|
|
|
|
public function __toString(): string
|
|
|
|
{
|
|
|
|
return print_r($this, TRUE);
|
|
|
|
}
|
|
|
|
|
2018-08-08 10:12:45 -04:00
|
|
|
/**
|
|
|
|
* Implementing ArrayAccess
|
|
|
|
*/
|
2021-02-10 17:17:51 -05:00
|
|
|
final public function offsetExists(mixed $offset): bool
|
2018-08-08 10:12:45 -04:00
|
|
|
{
|
2021-02-10 17:17:51 -05:00
|
|
|
return $this->__isset((string)$offset);
|
2018-08-08 10:12:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implementing ArrayAccess
|
|
|
|
*/
|
2021-02-10 17:17:51 -05:00
|
|
|
final public function offsetGet(mixed $offset): mixed
|
2018-08-08 10:12:45 -04:00
|
|
|
{
|
2021-02-10 17:17:51 -05:00
|
|
|
return $this->__get((string)$offset);
|
2018-08-08 10:12:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implementing ArrayAccess
|
|
|
|
*/
|
2021-02-10 17:17:51 -05:00
|
|
|
final public function offsetSet(mixed $offset, mixed $value): void
|
2018-08-08 10:12:45 -04:00
|
|
|
{
|
2021-02-10 17:17:51 -05:00
|
|
|
$this->__set((string)$offset, $value);
|
2018-08-08 10:12:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implementing ArrayAccess
|
|
|
|
*/
|
2021-02-10 17:17:51 -05:00
|
|
|
final public function offsetUnset(mixed $offset): void
|
2018-08-08 10:12:45 -04:00
|
|
|
{
|
2018-08-09 11:34:02 -04:00
|
|
|
if ($this->offsetExists($offset))
|
|
|
|
{
|
2021-02-10 17:17:51 -05:00
|
|
|
$strOffset = (string)$offset;
|
|
|
|
unset($this->$strOffset);
|
2018-08-09 11:34:02 -04:00
|
|
|
}
|
2018-08-08 10:12:45 -04:00
|
|
|
}
|
2018-08-24 14:23:01 -04:00
|
|
|
|
2019-10-07 20:10:27 -04:00
|
|
|
/**
|
|
|
|
* Implementing Countable
|
|
|
|
*/
|
2020-04-21 19:22:56 -04:00
|
|
|
final public function count(): int
|
2019-10-07 20:10:27 -04:00
|
|
|
{
|
2021-12-02 17:08:11 -05:00
|
|
|
$keys = array_keys($this->toArray());
|
2019-10-07 20:10:27 -04:00
|
|
|
return count($keys);
|
|
|
|
}
|
|
|
|
|
2018-08-24 14:23:01 -04:00
|
|
|
/**
|
|
|
|
* Recursively cast properties to an array
|
|
|
|
*
|
2021-02-10 17:17:51 -05:00
|
|
|
* Returns early on primitive values to work recursively.
|
|
|
|
*
|
2019-12-09 16:17:25 -05:00
|
|
|
* @param mixed $parent
|
2018-08-24 14:23:01 -04:00
|
|
|
*/
|
2021-02-10 17:31:20 -05:00
|
|
|
final public function toArray(mixed $parent = null): array
|
2018-08-24 14:23:01 -04:00
|
|
|
{
|
2021-02-10 17:31:20 -05:00
|
|
|
$fromObject = $this->fromObject($parent);
|
|
|
|
return (is_array($fromObject)) ? $fromObject : [];
|
2018-08-24 14:23:01 -04:00
|
|
|
}
|
2019-08-10 10:09:07 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine whether the type has any properties set
|
|
|
|
*/
|
2020-04-21 19:22:56 -04:00
|
|
|
final public function isEmpty(): bool
|
2019-08-10 10:09:07 -04:00
|
|
|
{
|
2021-12-02 17:08:11 -05:00
|
|
|
$self = $this->toArray();
|
2021-02-10 17:17:51 -05:00
|
|
|
foreach ($self as $value)
|
2019-08-10 10:09:07 -04:00
|
|
|
{
|
|
|
|
if ( ! empty($value))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
2021-02-10 17:31:20 -05:00
|
|
|
|
2021-02-23 15:38:29 -05:00
|
|
|
/**
|
|
|
|
* @codeCoverageIgnore
|
|
|
|
*/
|
2021-02-10 17:31:20 -05:00
|
|
|
final protected function fromObject(mixed $parent = null): float|null|bool|int|array|string
|
|
|
|
{
|
|
|
|
$object = $parent ?? $this;
|
|
|
|
|
|
|
|
if (is_scalar($object) || $object === NULL)
|
|
|
|
{
|
|
|
|
return $object;
|
|
|
|
}
|
|
|
|
|
|
|
|
$output = [];
|
|
|
|
|
|
|
|
foreach ($object as $key => $value)
|
|
|
|
{
|
|
|
|
$output[$key] = (is_scalar($value) || empty($value))
|
|
|
|
? $value
|
|
|
|
: $this->fromObject((array) $value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
}
|
2019-08-10 10:09:07 -04:00
|
|
|
}
|