OwlCyberSecurity - MANAGER
Edit File: 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; } } }