152 lines
3.4 KiB
PHP
152 lines
3.4 KiB
PHP
<?php
|
|
|
|
namespace Kirby\Toolkit;
|
|
|
|
use Exception;
|
|
use ReflectionMethod;
|
|
|
|
/**
|
|
* Properties
|
|
* @deprecated 4.0.0 Will be remove in Kirby 5
|
|
* @codeCoverageIgnore
|
|
*
|
|
* @package Kirby Toolkit
|
|
* @author Bastian Allgeier <bastian@getkirby.com>
|
|
* @link https://getkirby.com
|
|
* @copyright Bastian Allgeier
|
|
* @license https://opensource.org/licenses/MIT
|
|
*/
|
|
trait Properties
|
|
{
|
|
protected $propertyData = [];
|
|
|
|
/**
|
|
* Creates an instance with the same
|
|
* initial properties.
|
|
*
|
|
* @param array $props
|
|
* @return static
|
|
*/
|
|
public function clone(array $props = [])
|
|
{
|
|
return new static(array_replace_recursive($this->propertyData, $props));
|
|
}
|
|
|
|
/**
|
|
* Creates a clone and fetches all
|
|
* lazy-loaded getters to get a full copy
|
|
*
|
|
* @return static
|
|
*/
|
|
public function hardcopy()
|
|
{
|
|
$clone = $this->clone();
|
|
$clone->propertiesToArray();
|
|
return $clone;
|
|
}
|
|
|
|
protected function isRequiredProperty(string $name): bool
|
|
{
|
|
$method = new ReflectionMethod($this, 'set' . $name);
|
|
return $method->getNumberOfRequiredParameters() > 0;
|
|
}
|
|
|
|
protected function propertiesToArray()
|
|
{
|
|
$array = [];
|
|
|
|
foreach (get_object_vars($this) as $name => $default) {
|
|
if ($name === 'propertyData') {
|
|
continue;
|
|
}
|
|
|
|
if (method_exists($this, 'convert' . $name . 'ToArray') === true) {
|
|
$array[$name] = $this->{'convert' . $name . 'ToArray'}();
|
|
continue;
|
|
}
|
|
|
|
if (method_exists($this, $name) === true) {
|
|
$method = new ReflectionMethod($this, $name);
|
|
|
|
if ($method->isPublic() === true) {
|
|
$value = $this->$name();
|
|
|
|
if (is_object($value) === false) {
|
|
$array[$name] = $value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ksort($array);
|
|
|
|
return $array;
|
|
}
|
|
|
|
protected function setOptionalProperties(array $props, array $optional)
|
|
{
|
|
$this->propertyData = array_merge($this->propertyData, $props);
|
|
|
|
foreach ($optional as $propertyName) {
|
|
if (isset($props[$propertyName]) === true) {
|
|
$this->{'set' . $propertyName}($props[$propertyName]);
|
|
} else {
|
|
$this->{'set' . $propertyName}();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected function setProperties($props, array|null $keys = null)
|
|
{
|
|
foreach (get_object_vars($this) as $name => $default) {
|
|
if ($name === 'propertyData') {
|
|
continue;
|
|
}
|
|
|
|
$this->setProperty($name, $props[$name] ?? $default);
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
protected function setProperty($name, $value, $required = null)
|
|
{
|
|
// use a setter if it exists
|
|
if (method_exists($this, 'set' . $name) === false) {
|
|
return $this;
|
|
}
|
|
|
|
// fetch the default value from the property
|
|
$value ??= $this->$name ?? null;
|
|
|
|
// store all original properties, to be able to clone them later
|
|
$this->propertyData[$name] = $value;
|
|
|
|
// handle empty values
|
|
if ($value === null) {
|
|
// replace null with a default value, if a default handler exists
|
|
if (method_exists($this, 'default' . $name) === true) {
|
|
$value = $this->{'default' . $name}();
|
|
}
|
|
|
|
// check for required properties
|
|
if ($value === null && ($required ?? $this->isRequiredProperty($name)) === true) {
|
|
throw new Exception(sprintf('The property "%s" is required', $name));
|
|
}
|
|
}
|
|
|
|
// call the setter with the final value
|
|
return $this->{'set' . $name}($value);
|
|
}
|
|
|
|
protected function setRequiredProperties(array $props, array $required)
|
|
{
|
|
foreach ($required as $propertyName) {
|
|
if (isset($props[$propertyName]) !== true) {
|
|
throw new Exception(sprintf('The property "%s" is required', $propertyName));
|
|
}
|
|
|
|
$this->{'set' . $propertyName}($props[$propertyName]);
|
|
}
|
|
}
|
|
}
|