*/ public static array $validation_rules = []; /** * @var array */ protected array $casts = []; /** * @var array> */ protected static array $errors = []; public function __construct( protected readonly string $pluginKey, ) { self::$errors[$pluginKey] = []; $class = static::class; $validation_rules = []; $casts = []; while ($class = get_parent_class($class)) { $validation_rules = [...$validation_rules, ...get_class_vars($class)['validation_rules']]; $casts = [...$casts, ...get_class_vars($class)['casts']]; } $this::$validation_rules = [...$validation_rules, ...$this::$validation_rules]; $this->casts = [...$casts, ...$this->casts]; } public function __get(string $name): mixed { if (property_exists($this, $name)) { // if a get method exists for this property, return that $method = 'get' . str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $name))); if (method_exists($this, $method)) { return $this->{$method}(); } return $this->{$name}; } throw new Exception('Undefined object property ' . static::class . '::' . $name); } public function __isset(string $property): bool { return property_exists($this, $property); } public function loadFromFile(string $manifestPath): void { $manifestContents = @file_get_contents($manifestPath); if (! $manifestContents) { $manifestContents = '{}'; $this->addError('manifest', lang('Plugins.errors.manifestMissing', [ 'manifestPath' => $manifestPath, ])); } /** @var array|null $manifestData */ $manifestData = json_decode($manifestContents, true); if ($manifestData === null) { $manifestData = []; $this->addError('manifest', lang('Plugins.errors.manifestJsonInvalid', [ 'manifestPath' => $manifestPath, ])); } $this->loadData($manifestData); } /** * @param array $data */ public function loadData(array $data): void { /** @var Validation $validation */ $validation = service('validation'); $validation->setRules($this::$validation_rules); if (! $validation->run($data)) { foreach ($validation->getErrors() as $key => $message) { $this->addError($key, $message); } $validation->reset(); } foreach ($validation->getValidated() as $key => $value) { $method = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key))); if (is_callable([$this, $method])) { $this->{$method}($value); continue; } if (array_key_exists($key, $this->casts)) { $cast = $this->casts[$key]; if (is_array($cast) && is_array($value)) { foreach ($value as $valueKey => $valueElement) { if (is_subclass_of($cast[0], self::class)) { $manifestClass = $cast[0] === Field::class ? $this->getFieldClass( $valueElement ) : $cast[0]; $value[$valueKey] = new $manifestClass($this->pluginKey); $value[$valueKey]->loadData($valueElement); } else { $value[$valueKey] = new $cast[0]($valueElement); } } } elseif (is_subclass_of($cast, self::class)) { $manifestClass = $cast === Field::class ? $this->getFieldClass($value) : $cast; $valueElement = $value; $value = new $manifestClass($this->pluginKey); $value->loadData($valueElement ?? []); } else { $value = new $cast($value ?? []); } } $this->{$key} = $value; } } /** * @return array */ public static function getPluginErrors(string $pluginKey): array { return self::$errors[$pluginKey]; } protected function addError(string $errorKey, string $errorMessage): void { self::$errors[$this->pluginKey][$errorKey] = $errorMessage; } /** * @param array $data */ private function getFieldClass(array $data): string { $fieldType = $data['type'] ?? 'text'; return rtrim(Field::class, "\Field") . '\\Fields\\' . str_replace( ' ', '', ucwords(str_replace('-', ' ', $fieldType)) ); } }