Initial Version
This commit is contained in:
129
shared/lib/Resource/Selector/SelectorAbstract.php
Normal file
129
shared/lib/Resource/Selector/SelectorAbstract.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: Sebastian Krupinski <krupinski01@gmail.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace KTXF\Resource\Selector;
|
||||
|
||||
use JsonSerializable;
|
||||
use KTXF\Json\JsonDeserializable;
|
||||
|
||||
/**
|
||||
* Abstract base class for all selector types
|
||||
* Provides common functionality for hierarchical selectors
|
||||
*/
|
||||
abstract class SelectorAbstract extends \ArrayObject implements JsonSerializable, JsonDeserializable {
|
||||
|
||||
protected const TYPE_STRING = 'string';
|
||||
protected const TYPE_INT = 'int';
|
||||
protected const TYPE_BOOL = 'bool';
|
||||
|
||||
/** @var array<mixed> Allowed key types: 'string', 'int' */
|
||||
protected array $keyTypes = [];
|
||||
|
||||
/** @var array<mixed> Allowed scalar value types: 'string', 'int', 'bool' */
|
||||
protected array $valueTypes = [];
|
||||
|
||||
/** @var class-string selector class for nested structures */
|
||||
protected string $nestedSelector = SelectorAbstract::class;
|
||||
|
||||
/** @var string Human-readable name for this selector type */
|
||||
protected string $selectorName = 'Selector';
|
||||
|
||||
/**
|
||||
* Serialize to JSON-compatible array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function jsonSerialize(): array {
|
||||
$result = [];
|
||||
foreach ($this as $key => $value) {
|
||||
if ($value instanceof JsonSerializable) {
|
||||
$result[$key] = $value->jsonSerialize();
|
||||
} else {
|
||||
$result[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize from JSON-compatible array
|
||||
* @param array $data
|
||||
* @return void
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function jsonDeserialize(array|string $data): static {
|
||||
if (is_string($data)) {
|
||||
$data = json_decode($data, true);
|
||||
}
|
||||
foreach ($data as $key => $value) {
|
||||
if ($this->nestedSelector !== null && is_array($value)) {
|
||||
$selector = new $this->nestedSelector();
|
||||
$selector->jsonDeserialize($value);
|
||||
$this->offsetSet($key, $selector);
|
||||
} else {
|
||||
$this->offsetSet($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if a key is of the correct type for this selector
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateKey(mixed $key): bool {
|
||||
return in_array(gettype($key), $this->keyTypes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if a value is of the correct type for this selector
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateValue(mixed $value): bool {
|
||||
if ($this->nestedSelector !== null && $value instanceof $this->nestedSelector) {
|
||||
return true;
|
||||
}
|
||||
return in_array(gettype($value), $this->valueTypes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override offsetSet to enforce type checking
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
#[\Override]
|
||||
public function offsetSet($key, $value): void {
|
||||
if (!$this->validateKey($key)) {
|
||||
throw new \InvalidArgumentException("{$this->selectorName} keys must be one of [" . implode(', ', $this->keyTypes) . "], got " . gettype($key));
|
||||
}
|
||||
|
||||
if (!$this->validateValue($value)) {
|
||||
throw new \InvalidArgumentException("{$this->selectorName} values must be one of [" . implode(', ', $this->valueTypes) . "], got " . gettype($value));
|
||||
}
|
||||
parent::offsetSet($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all identifiers (keys or values depending on selector type)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function identifiers(): array {
|
||||
return array_keys($this->getArrayCopy());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user