/** Datei: plugins/rest/library/ARUNOX/Plugins/REST/Generator/Base/BaseGenerator.php **/ * @copyright 2025 ARUNOX * @version 1.0.0 * @since 1.0.0 File is created */ namespace ARUNOX\Plugins\REST\Generator\Base; use UnitEnum; use JsonSerializable; use ARUNOX\Plugins\REST\Generator; use ARUNOX\Plugins\REST\Generator\Config; abstract class BaseGenerator implements JsonSerializable { /* ### VARIABLES ################################################ # */ protected static string $TYPE = "generator"; protected static ?string $PRIMARYKEY = NULL; protected ?string $GENERATOR = NULL; protected string $RETURN_OBJECT = "self"; // e.g. self, content protected bool $INCLUDE_ALLOWED_CONTENT = TRUE; protected bool $INCLUDE_ALLOWED_CONFIG = TRUE; protected bool $INCLUDE_ALLOWED_DATA = TRUE; protected array $ALLOWED_CONTENT = []; protected array $ALLOWED_CONFIG = []; protected array $ALLOWED_DATA = []; protected string $CHILDREN_NAME = "content"; protected ?object $parent_node = NULL; protected ?self $lastelement = NULL; protected array $data = []; protected array $config = []; protected array $content = []; /* ### PUBLIC STATIC FUNCTIONS ################################## # */ public static function create( ...$args ) : ?BaseGenerator { return Generator::create( ...$args ); } public static function hasGenerator() : bool { return !!static::$GENERATOR; } public static function getGenerator() : ?string { return static::$GENERATOR; } /* ### PUBLIC FUNCTIONS ######################################### # */ public function getReturnObject() { return match( $this->RETURN_OBJECT ) { "self" => $this, "content" => end( $this->content ), }; } public function getType() { return static::$TYPE; } public function getPrimaryKey() { return $this->get( static::$PRIMARYKEY ); } public function setParentNode( object $parentNode ) : self { $this->parent_node = $parentNode; return $this; } public function parent( int $steps = 1 ) : ?self { $parent = $this->parent_node; for( $x = 1; $x < $steps; $x++ ) { if( !$parent->parent() ) break; $parent = $parent->parent(); } return $parent; } public function top() : self { $parent = $this; while( $parent->parent() ) { $parent = $parent->parent(); } return $parent; } public function addCallable( string|array $callable, ...$arguments ) { if( is_callable( $callable ) ) { return call_user_func( $callable, $this, ...$arguments ) ?? $this; } return $this; } /* ### JSON FUNCTIONS ########################################### # */ public function jsonSerialize() : array { $config = $this->config; foreach( $config as &$value ) { if( $value instanceof \UnitEnum ) { $value = $value->value; } } $config["content"] = $this->content; if( $this->GENERATOR ) { $config = [ "type" => $this->TYPE, "generator" => $this->GENERATOR, "config" => $config, ]; if( $this->TYPE == "wrapper" && $this->HISTORY ) { $config["history"] = $this->HISTORY; } foreach( $this->data as $name => $data ) { $config[ $name ] = $data; } } return $config; } /* ### PROTECTED FUNCTIONS ###################################### # */ protected function set( $name, ...$args ) { if( FALSE !== $this->checkAllowedData( $name, ...$args ) ) { $this->data[ $name ] = current( $args ); return $this; } if( FALSE !== $this->checkAllowedConfig( $name, ...$args ) ) { // $this->config[ $name ] = is_multi( $args ) ? $args : current( $args ); $this->config[ $name ] = current( $args ); return $this; } // if( FALSE !== $addClass = $this->checkAllowedContent( $name, ...$args ) ) { // $lastkey = array_key_last( $this->content ); // unset( $this->content[ $lastkey ] ); // show( $this->content ); // return $this->addToAllowed( $name, $addClass, "content", $args ); // } show( "SET", $name, $args ); } protected function get( ?string $name = NULL, ...$args ) { // show( $name, $args, FALSE ); if( in_array( $name, [ "content", NULL ] ) ) { if( isset( $args[0] ) ) return $this->content[ $args[0] ]; if( $this->lastelement ) return $this->lastelement; } if( in_array( $name, [ "children" ] ) ) { return $this->{$this->CHILDREN_NAME}; } if( in_array( $name, [ "config", "content" ] ) ) { $value = $this->{$name}; foreach( $args as $arg ) { $value = $value[ $arg ]; } return $value; } if( FALSE !== $class = $this->getAllowedConfig( $name ) ) { if( !is_array( $this->config[ $name ] ) ) { return $this->config[ $name ]; } if( isset( $args[0] ) ) return $this->config[ $name ][ $args[0] ]; return end( $this->config[ $name ] ); } if( FALSE !== $class = $this->checkAllowedContent( $name ) ) { foreach( $this->content as $content ) { show( $class, false ); if( is_a( $content, $class ) ) { $origin = $content->getPrimaryKey(); $origin = strtolower( $origin ); $needle = strtolower( $args[0] ); if( $needle === $origin ) { return $content; } } } } show( "GET", [ "name" => $name, "args" => $args, "config" => $this->config ] ); } /* ### PROTECTED ADD FUNCTIONS ################################## # */ protected function add( string $addName, ...$args ) { // if( $addName == "children" ) show( $addName, $args, FALSE ); foreach( $args as &$arg ) { if( $arg instanceof BaseGenerator ) { $arg = $arg->top(); } } if( $addName == "children" ) { if( !is_array( $args[0] ) ) $args[0] = [ $args[0] ]; foreach( $args[0] as $child ) { if( FALSE !== $addClass = $this->checkAllowedContent( "content", $child ) ) { $last = $this->addToAllowed( "content", $addClass, "content", [$child] ); } } return $last ?? NULL; } if( FALSE !== $addClass = $this->checkAllowedConfig( $addName ) ) { return $this->addToAllowed( $addName, $addClass, "config", $args ); } if( FALSE !== $addClass = $this->checkAllowedContent( $addName, ...$args ) ) { return $this->addToAllowed( $addName, $addClass, "content", $args ); } show( "ADD", $addName, $addClass, $args, $this->ALLOWED_CONTENT, get_called_class() ); } protected function insert( string $insertPosition, int $insertIndex, string $insertName, ...$args ) { if( FALSE !== $insertClass = $this->checkAllowedConfig( $insertName, ...$args ) ) { return $this->{"insert{$insertPosition}Config"}( $this->config[ $insertName ][ $insertIndex ], $insertName, $insertClass, $args ); } if( FALSE !== $insertClass = $this->checkAllowedContent( $insertName, ...$args ) ) { return $this->{"insert{$insertPosition}Content"}( $this->content[ $insertIndex ], $insertName, $insertClass, $args ); } show( "INSERT", $insertPosition, $insertName, $insertClass, $args, $this->ALLOWED_CONTENT, get_called_class() ); } protected function before( string $addName, ...$args ) { $parent = $this->parent(); foreach( $args as &$arg ) { if( $arg instanceof BaseGenerator ) { $arg = $arg->top(); } } if( FALSE !== $addClass = $parent->checkAllowedConfig( $addName, ...$args ) ) { return $parent->insertBeforeConfig( $this, $addName, $addClass, $args ); } if( FALSE !== $addClass = $parent->checkAllowedContent( $addName, ...$args ) ) { return $parent->insertBeforeContent( $this, $addName, $addClass, $args ); } show( "before", $addName, $addClass, $args, $parent->ALLOWED_CONTENT, get_called_class() ); } protected function after( string $addName, ...$args ) { $parent = $this->parent(); foreach( $args as &$arg ) { if( $arg instanceof BaseGenerator ) { $arg = $arg->top(); } } if( FALSE !== $addClass = $parent->checkAllowedConfig( $addName, ...$args ) ) { return $parent->insertAfterConfig( $this, $addName, $addClass, $args ); } if( FALSE !== $addClass = $parent->checkAllowedContent( $addName, ...$args ) ) { return $parent->insertAfterContent( $this, $addName, $addClass, $args ); } show( "AFTER", $addName, $addClass, $args, $parent->ALLOWED_CONTENT, get_called_class() ); } /* ### PROTECTED REMOVE FUNCTIONS ############################### # */ protected function remove( ?string $removeName = NULL ) { $parent = $this->parent(); // show( $removeName, FALSE ); if( FALSE !== $parent->checkAllowedConfig( $removeName ) ) { // show( 1 ); return $parent->removeConfig( $this, $removeName ); } if( FALSE !== $parent->checkAllowedContent( $removeName ) ) { // show( 2 ); return $parent->removeContent( $this ); } show( "remove", $removeName, $parent->ALLOWED_CONTENT, get_called_class() ); } /* ### PROTECTED REMPLACE FUNCTIONS ############################### # */ protected function replace( ?string $addName = NULL, ...$args ) { // show( $addName ); $child = $this->get( $addName ); // show( $addName, $child, $this->{$addName}, "X"); if( FALSE !== $addClass = $this->checkAllowedConfig( $addName, ...$args ) ) { $child->before( $addName, $addClass, ...$args ); return $this->removeConfig( $child, $addName ); } // show($child, "X"); if( FALSE !== $addClass = $this->checkAllowedContent( $addName, ...$args ) ) { $child->before( $addName, $addClass, ...$args ); return $this->removeContent( $child ); } show( "replace", $addName, $this->ALLOWED_CONTENT, get_called_class() ); } /* ### ALLOWED DATA FUNCTIONS ################################### # */ protected function isAllowedData( $name ) : bool { return key_exists( $name, $this->ALLOWED_DATA ); } protected function getAllowedData( ?string $name = NULL ) : mixed { if( !$name ) return $this->ALLOWED_DATA; if( !$this->isAllowedData( $name ) ) return FALSE; return $this->ALLOWED_DATA[ $name ]; } protected function addAllowedData( string $name, string|array|UnitEnum $types ) : void { $this->ALLOWED_DATA[ $name ] = $this->parseAllowedTypes( $types ); } protected function checkAllowedData( $name, ...$args ) : null|bool|string { if( !$this->isAllowedData( $name ) ) return FALSE; $types = $this->getAllowedData( $name ); return $this->checkAllowedTypes( $name, $types, ...$args ); } /* ### ALLOWED CONFIG FUNCTIONS ################################# # */ protected function isAllowedConfig( $name ) : bool { return key_exists( $name, $this->ALLOWED_CONFIG ); } protected function getAllowedConfig( ?string $name = NULL ) : mixed { if( !$name ) return $this->ALLOWED_CONFIG; if( !$this->isAllowedConfig( $name ) ) return FALSE; return $this->ALLOWED_CONFIG[ $name ]; } protected function addAllowedConfig( string $name, string|array|UnitEnum $types ) : void { $this->ALLOWED_CONFIG[ $name ] = $this->parseAllowedTypes( $types ); } protected function checkAllowedConfig( ?string $name = NULL , ...$args ) : null|bool|string { if( !$this->isAllowedConfig( $name ) ) return FALSE; $types = $this->getAllowedConfig( $name ); return $this->checkAllowedTypes( $name, $types, ...$args ); } protected function removeConfig( self $remove, string $name ) { $index = array_search( $remove, $this->config[ $name ] ); $before = array_slice( $this->config[ $name ],0, $index ); $after = array_slice( $this->config[ $name ], $index + 1 ); // show( $index, $remove, $before, $after, $this->config[ $name ] ); $this->config[ $name ] = array_merge( $before, $after ); return $this; } protected function insertBeforeConfig( self $before, string $name, $class, $args ) { $this->addToAllowed( $name, $class, "config", $args ); $index = array_search( $before, $this->config[ $name ] ); $before = array_slice( $this->config[ $name ],0, $index ); $insert = array_slice( $this->config[ $name ], -1 ); $after = array_slice( $this->config[ $name ], $index, -1 ); $this->config[ $name ] = array_merge( $before, $insert, $after ); return $this; } protected function insertAfterConfig( self $after, string $name, $class, $args ) { $this->addToAllowed( $name, $class, "config", $args ); $index = array_search( $after, $this->config[ $name ] ); $before = array_slice( $this->config[ $name ],0, $index + 1 ); $insert = array_slice( $this->config[ $name ], -1 ); $after = array_slice( $this->config[ $name ], $index + 1, -1 ); $this->config[ $name ] = array_merge( $before, $insert, $after ); return $this; } /* ### ALLOWED CONTENT FUNCTIONS ################################ # */ protected function isAllowedContent( $name ) : bool { return key_exists( $name, $this->ALLOWED_CONTENT ); } protected function getAllowedContent( ?string $name = NULL ) : mixed { if( !$name ) return $this->ALLOWED_CONTENT; if( !$this->isAllowedContent( $name ) ) return FALSE; return $this->ALLOWED_CONTENT[ $name ]; } protected function addAllowedContent( string $name, string|array|UnitEnum $types ) : void { $this->ALLOWED_CONTENT[ $name ] = $this->parseAllowedTypes( $types ); } protected function checkAllowedContent( ?string $name = NULL, ...$args ) : null|bool|string { if( !$this->isAllowedContent( $name ) ) { if( !$this->isAllowedContent( $name = "*" ) ) return FALSE; } $types = $this->getAllowedContent( $name ); return $this->checkAllowedTypes( $name, $types, ...$args ); } protected function removeContent( self $remove ) { $index = array_search( $remove, $this->content ); $before = array_slice( $this->content,0, $index ); $after = array_slice( $this->content, $index, -1 ); $this->content = array_merge( $before, $after ); return $this; } protected function insertBeforeContent( self $before, string $name, $class, $args ) { $this->addToAllowed( $name, $class, "content", $args ); $index = array_search( $before, $this->content ); $before = array_slice( $this->content,0, $index ); $insert = array_slice( $this->content, -1 ); $after = array_slice( $this->content, $index, -1 ); $this->content = array_merge( $before, $insert, $after ); return $this; } protected function insertAfterContent( self $after, string $name, $class, $args ) { $this->addToAllowed( $name, $class, "content", $args ); $index = array_search( $after, $this->content ); $before = array_slice( $this->content,0, $index + 1 ); $insert = array_slice( $this->content, -1 ); $after = array_slice( $this->content, $index + 1, -1 ); $this->content = array_merge( $before, $insert, $after ); return $this; } /* ### PRIVATE FUNCTIONS ######################################## # */ private function addToAllowed( string $name, $class, $type, $args ) { // if( $name == "dropdowns" ) show( $name, $class, $type, $args, FALSE ); if( !isset( $args[0] ) || ! $args[0] instanceof BaseGenerator ) { if( $name == $type ) { $class = array_shift( $args ); } // if( $name == "dropdowns" ) show( $name, FALSE ); if( $class ) $generator = Generator::create( $class, ...$args ); // if( $name == "dropdowns" ) show( $generator, FALSE ); } else $generator = $args[0]; if( $class ) $generator->setParentNode( $this ); else $generator = $args[0]; // if( $name == "dropdowns" ) show( $this, $generator, FALSE ); if( $type === 'config' ) { $this->{$type}[ $name ][] = $this->lastelement = $generator; } else $this->{$type}[] = $this->lastelement = $generator; return $this; } private function loadAllowedTypes() : bool { $class = get_class( $this ); foreach( $this->getAllowedData() as $name => $types ) { $this->addAllowedData( $name, $types ); } foreach( $this->getAllowedConfig() as $name => $types ) { $this->addAllowedConfig( $name, $types ); } foreach( $this->getAllowedContent() as $name => $types ) { $this->addAllowedContent( $name, $types ); } while( $class ) { $vars = get_class_vars( $class ); if( key_exists( "ALLOWED_DATA", $vars ) ) { foreach( $vars["ALLOWED_DATA"] as $name => $types ) { $this->addAllowedData( $name, $types ); } } if( key_exists( "ALLOWED_CONFIG", $vars ) ) { foreach( $vars["ALLOWED_CONFIG"] as $name => $types ) { $this->addAllowedConfig( $name, $types ); } } if( key_exists( "ALLOWED_CONTENT", $vars ) ) { foreach( $vars["ALLOWED_CONTENT"] as $name => $types ) { $this->addAllowedContent( $name, $types ); } } $class = get_parent_class( $class ); } return TRUE; } private function parseAllowedTypes( string|array|UnitEnum $types ) : array { if( key_exists( "generator", (array)$types ) ) { $generator = $types["generator"]; } if( key_exists( "args", (array)$types ) ) { $types = $types["args"]; } if( !is_array( $types ) ) $types = [ $types ]; if( !is_multi( $types ) ) $types = [ $types ]; $types = [ "generator" => $generator ?? NULL, "args" => $types, ]; return $types; } private function checkAllowedTypes( string $name, array $types, ...$args ) : null|bool|string { $class = $types["generator"]; $types = $types["args"] ?? $types; $last = end( $types ); $last = $last instanceof UnitEnum ? $last->value : $last; $index = 0; // show( $name, $types, $args, FALSE ); foreach( $args as $arg ) { $index++; if( $index + 1 >= count( $types ) && $last == Config\Type::Traversable->value ) { $index = count( $types ) - 2; } if( !key_exists( $index, $types ) ) return $class; foreach( $types[ $index ] as $type ) { if( $type instanceof UnitEnum ) { $type = $type->value; } if( is_a( $arg, $type ) ) continue 2; if( function_exists( "is_{$type}" ) ) { $func = "is_{$type}"; if( $func( $arg ) ) continue 2; } } return FALSE; } return $class; } private function loadTraits() { if( class_uses( $this ) ) { $traits = get_declared_traits(); $traits = array_intersect( class_uses($this), $traits ); $traits = array_values( $traits ); foreach( $traits as $trait ) { $trait = explode( "\\", $trait ); $trait = end( $trait ); if( method_exists( $this, "{$trait}Init" ) ) { $this->{"{$trait}Init"}(); } } } } /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( ...$args ) { // if( get_called_class() == "ARUNOX\Plugins\REST\Generator\Components\Button" ) show( get_called_class(), $args, FALSE ); $this->loadAllowedTypes(); $this->loadTraits(); foreach( $args as $name => $arg ) { $this->{"set{$name}"}( $arg ); } } public function __get( $name ) { if( method_exists( $this, "get{$name}" ) ) { return $this->{"get{$name}"}(); } return NULL; } public function __call( $name, $args ) { if( preg_match( "/^(insert)(.+)(before|after)$/", strtolower( $name ), $matches ) ) { $insertIndex = array_shift( $args ); return $this->insert( $matches[3], $insertIndex, $matches[2], ...$args ); } if( preg_match( "/^(add|set|get|remove|replace|insert|before|after)(.*)$/", strtolower( $name ), $matches ) ) { if( !$matches[2] ) $matches[2] = NULL; array_unshift( $args, $matches[2] ); return $this->{$matches[1]}( ...$args ); } } } /** Datei: plugins/rest/library/ARUNOX/Plugins/REST/Generator/Base/BaseWrapper.php **/ * @copyright 2025 ARUNOX * @version 1.0.0 * @since 1.0.0 File is created */ namespace ARUNOX\Plugins\REST\Generator\Base; use ARUNOX\Plugins\REST\Response; use ARUNOX\Plugins\REST\Generator\Config; class BaseWrapper extends BaseGenerator { /* ### VARIABLES ################################################ # */ protected static ?string $PRIMARYKEY = "title"; protected ?string $HISTORY = REQUEST_ROUTE; protected ?string $GENERATOR = "dynamic"; protected array $ALLOWED_CONTENT = [ "*" => [ BaseGenerator::class, Config\Type::String ], ]; protected array $ALLOWED_CONFIG = [ "title" => Config\Type::String, ]; /* ### PUBLIC FUNCTIONS ######################################### # */ public function setHistory( null|string $history = NULL ) { $this->HISTORY = $history; return $this; } /* ### PUBLIC STATIC FUNCTIONS ################################# # */ public static function create( ...$args ) : ?BaseGenerator { return parent::create( get_called_class(), ...$args ); } /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( ?string $title = NULL, ...$args ) { parent::__construct(); if( $title ) $this->setTitle( $title ); foreach( $args as $arg ) { $content = $this->addContent( $arg ); if( $title ) $content->get()->setTitle( $title ); } } }