HummingBirdAnimeClient/src/AnimeClient/Types/AbstractType.php

250 lines
4.5 KiB
PHP
Raw Normal View History

<?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
*
* PHP version 7.4
*
* @package HummingbirdAnimeClient
* @author Timothy J. Warren <tim@timshomepage.net>
2020-01-08 15:39:49 -05:00
* @copyright 2015 - 2020 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
2020-08-04 09:30:21 -04:00
* @version 5.1
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\Types;
use ArrayAccess;
use Countable;
abstract class AbstractType implements ArrayAccess, Countable {
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
*
* @param $properties
* @return self
2018-08-08 13:05:38 -04:00
*/
2018-09-27 16:45:12 -04:00
public static function __set_state($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
*
* @param array $data
* @return array|null
*/
final public static function check($data = []): ?array
{
$currentClass = static::class;
if (get_parent_class($currentClass) !== FALSE)
{
return (new $currentClass($data))->toArray();
}
return NULL;
}
/**
* Static constructor
*
* @param mixed $data
* @return static
*/
final public static function from($data): self
{
return new static($data);
}
/**
* Sets the properties by using the constructor
*
* @param mixed $data
*/
final private function __construct($data = [])
{
$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);
}
}
/**
* See if a property is set
*
* @param $name
* @return bool
*/
2020-04-21 19:22:56 -04:00
final public function __isset($name): bool
{
2020-01-15 15:22:38 -05:00
return property_exists($this, $name) && isset($this->$name);
}
/**
* Set a property on the type object
*
* @param string $name
* @param mixed $value
* @return void
*/
2020-04-21 19:22:56 -04:00
final public function __set($name, $value): void
{
$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))
{
$existing = json_encode($this);
2018-10-05 14:32:05 -04:00
throw new UndefinedPropertyException("Trying to set undefined property: '$name'. Existing properties: $existing");
}
$this->$name = $value;
}
/**
* Get a property from the type object
*
* @param string $name
* @return mixed
*/
2020-04-21 19:22:56 -04:00
final public function __get($name)
{
// 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;
}
2019-08-10 10:09:07 -04:00
/**
* Create a string representation of the object for debugging
*
* @return string
*/
public function __toString(): string
{
return print_r($this, TRUE);
}
/**
* Implementing ArrayAccess
*
* @param $offset
* @return bool
*/
2020-04-21 19:22:56 -04:00
final public function offsetExists($offset): bool
{
return $this->__isset($offset);
}
/**
* Implementing ArrayAccess
*
* @param $offset
* @return mixed
*/
2020-04-21 19:22:56 -04:00
final public function offsetGet($offset)
{
return $this->__get($offset);
}
/**
* Implementing ArrayAccess
*
* @param $offset
* @param $value
*/
2020-04-21 19:22:56 -04:00
final public function offsetSet($offset, $value): void
{
$this->__set($offset, $value);
}
/**
* Implementing ArrayAccess
*
* @param $offset
*/
2020-04-21 19:22:56 -04:00
final public function offsetUnset($offset): void
{
if ($this->offsetExists($offset))
{
unset($this->$offset);
}
}
2018-08-24 14:23:01 -04:00
/**
* Implementing Countable
*
* @return int
*/
2020-04-21 19:22:56 -04:00
final public function count(): int
{
$keys = array_keys($this->toArray());
return count($keys);
}
2018-08-24 14:23:01 -04:00
/**
* Recursively cast properties to an array
*
2019-12-09 16:17:25 -05:00
* @param mixed $parent
2018-08-24 14:23:01 -04:00
* @return mixed
*/
2020-04-21 19:22:56 -04:00
final public function toArray($parent = null)
2018-08-24 14:23:01 -04:00
{
$object = $parent ?? $this;
2019-12-06 15:46:56 -05:00
if (is_scalar($object) || $object === NULL)
2018-08-24 14:23:01 -04:00
{
return $object;
}
$output = [];
foreach ($object as $key => $value)
{
2018-09-27 16:45:12 -04:00
$output[$key] = (is_scalar($value) || empty($value))
2018-08-24 14:23:01 -04:00
? $value
: $this->toArray((array) $value);
}
return $output;
}
2019-08-10 10:09:07 -04:00
/**
* Determine whether the type has any properties set
*
* @return bool
*/
2020-04-21 19:22:56 -04:00
final public function isEmpty(): bool
2019-08-10 10:09:07 -04:00
{
foreach ($this as $value)
2019-08-10 10:09:07 -04:00
{
if ( ! empty($value))
{
return FALSE;
}
}
return TRUE;
}
}