File: /var/www/html/wpmuhibbah/wp-content/plugins/give/src/Framework/Blocks/BlockType.php
<?php
namespace Give\Framework\Blocks;
use Exception;
use Give\Framework\Blocks\Contracts\BlockTypeInterface;
use Give\Framework\Exceptions\Primitives\InvalidArgumentException;
use Give\Framework\Support\Contracts\Arrayable;
use RuntimeException;
/**
* @since 3.8.0
*/
abstract class BlockType implements BlockTypeInterface, Arrayable
{
/**
* @var string[]
*/
protected $properties = [];
/**
* @var BlockModel
*/
protected $block;
/**
* @since 3.8.0
*/
abstract public static function name(): string;
/**
* @throws Exception
*/
public function __construct(BlockModel $block)
{
$this->block = $block;
if ($this->block->name !== $this::name()) {
throw new RuntimeException(
sprintf(
'BlockModel name "%s" does not match the BlockType name "%s".',
$this->block->name,
$this::name()
)
);
}
$this->fillDefaultProperties();
}
/**
* Dynamically retrieve attributes.
*
* @since 3.8.0
*
* @return mixed
*/
public function __get(string $key)
{
$value = $this->getAttribute($key);
return $this->castAttributeType($key, $value);
}
/**
* Dynamically set attributes.
*
* @since 3.8.0
*
* @param mixed $value
*
* @return void
*/
public function __set(string $key, $value)
{
$this->validateAttributeType($key, $value);
$this->setAttribute($key, $value);
}
/**
* Determine if an attribute exists.
*
* @since 3.8.0
*
* @return bool
*/
public function __isset(string $key)
{
return !is_null($this->getAttribute($key));
}
/**
* @since 3.8.0
*/
protected function getAttribute($name)
{
return $this->block->getAttribute($name);
}
/**
* @since 3.8.0
*/
protected function hasAttribute($name): bool
{
return $this->block->hasAttribute($name);
}
/**
* @since 3.8.0
*/
protected function setAttribute(string $name, $value): self
{
$this->block->setAttribute($name, $value);
return $this;
}
/**
* Validates that the given value is a valid type for the given attribute.
*
* @since 3.8.0
*
* @throws InvalidArgumentException
*/
protected function validateAttributeType(string $key, $value): void
{
if (!$this->isAttributeTypeValid($key, $value)) {
$type = $this->getPropertyType($key);
throw new InvalidArgumentException("Invalid attribute assignment. '$key' should be of type: '$type'");
}
}
/**
* Validate an attribute to a PHP type.
*
* @since 3.8.0
*/
public function isAttributeTypeValid(string $key, $value): bool
{
if (is_null($value)) {
return true;
}
$type = $this->getPropertyType($key);
switch ($type) {
case 'int':
return is_int($value);
case 'string':
return is_string($value);
case 'bool':
return is_bool($value);
case 'array':
return is_array($value);
case 'float':
return is_float($value);
default:
return $value instanceof $type;
}
}
/**
* @since 3.21.0 updated to always cast value even if null
* @since 3.8.0
*/
public function castAttributeType(string $key, $value)
{
$type = $this->getPropertyType($key);
switch ($type) {
case 'int':
return (int)($value);
case 'string':
return (string)($value);
case 'bool':
return (bool)filter_var($value, FILTER_VALIDATE_BOOLEAN);
case 'array':
return (array)($value);
case 'float':
return (float)filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT,FILTER_FLAG_ALLOW_FRACTION);
default:
return $value;
}
}
/**
* @since 3.8.0
*/
protected function getPropertyType(string $key): string
{
$type = is_array($this->properties[$key]) ? $this->properties[$key][0] : $this->properties[$key];
return strtolower(trim($type));
}
/**
* @since 3.8.0
*/
public function toArray(): array
{
$attributes = [];
foreach($this->properties as $key => $type) {
$attributes[$key] = $this->{$key};
}
return [
'name' => $this::name(),
'attributes' => $attributes
];
}
/**
* @since 3.8.0
*/
protected function setDefaultProperties(): array
{
return [];
}
/**
* @since 3.21.0 updated to always set default properties
* @since 3.8.0
*/
private function fillDefaultProperties(): void
{
foreach ($this->setDefaultProperties() as $key => $type) {
$this->properties[$key] = $type;
}
}
}