/** Datei: library/ARUNOX/API/PHP/Attributes/Attribute.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes; abstract class Attribute { /* ################################################################ # */ /* ### ATTRIBUTE CONFIG ######################################### # */ /* ################################################################ # */ /* ### VARIABLES ################################################ # */ protected static null|string $__NAME = NULL; protected static null|string $__DEFAULT = NULL; /* ### PUBLIC FUNCTIONS ######################################### # */ public function getName() : string { if( static::$__NAME ) return static::$__NAME; $name = explode( "\\", static::class ); $name = end( $name ); $name = strtolower( $name ); return $name; } public function get() : mixed { if( static::$__DEFAULT ) return static::{static::$__DEFAULT}(); return NULL; } /* ################################################################ # */ /* ### CACHE SUPPORT ########################################### # */ /* ################################################################ # */ /* ### VARIABLES ################################################ # */ protected static array $__CACHE = []; protected mixed $CONFIG = NULL; /* ### PROTECTED FUNCTIONS ###################################### # */ protected function getCache() { return static::$__CACHE[ static::class ][ $this->PARENT ]; } protected function getCacheAll() { return static::$__CACHE[ static::class ]; } protected function addCache( mixed $config ) { static::$__CACHE[ static::class ][ $this->PARENT ] = $config; } /* ################################################################ # */ /* ### PARENT SUPPORT ########################################### # */ /* ################################################################ # */ /* ### VARIABLES ################################################ # */ protected null|string $PARENT = NULL; /* ### PUBLIC FUNCTIONS ######################################### # */ public function setParentClass( string $class ){ $this->PARENT = $class; $this->addCache( $this->CONFIG ); } /* ### PROTECTED FUNCTIONS ###################################### # */ protected function getParentClass() : string { return $this->PARENT; } /* ################################################################ # */ /* ### NAMESPACE SUPPORT ######################################## # */ /* ################################################################ # */ /* ### VARIABLES ################################################ # */ protected null|string $NAMESPACE = NULL; /* ### PUBLIC FUNCTIONS ######################################### # */ public function setNamespace( string $namespace ){ $this->NAMESPACE = $namespace; } /* ### PROTECTED FUNCTIONS ###################################### # */ protected function getNamespace() : string { return $this->NAMESPACE; } /* ################################################################ # */ /* ### MAGIC FUNCTIONS ########################################## # */ /* ################################################################ # */ public function __construct( mixed $config ) { $this->CONFIG = $config; } } /** Datei: library/ARUNOX/API/PHP/Attributes/Magic/Get/Exceptions/PatternFailed.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Magic\Get\Exceptions; use Exception; class PatternFailed extends Exception {} /** Datei: library/ARUNOX/API/PHP/Attributes/Magic/Get/Exceptions/FallbackFailed.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Magic\Get\Exceptions; use Exception; class FallbackFailed extends Exception {} /** Datei: library/ARUNOX/API/PHP/Attributes/Magic/Get/Get.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Magic; use Attribute; use ARUNOX\API\PHP; #[Attribute( Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE )] class Get { use PHP\Attributes\Magic\Get\Helper; /* ### VARIABLES ################################################ # */ /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( protected null|string $match = NULL, protected bool $fallback = FALSE, protected int $priority = 10 ){} } /** Datei: library/ARUNOX/API/PHP/Attributes/Magic/Get/Helper.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Magic\Get; use ARUNOX\API\PHP; use ReflectionClass; use ReflectionMethod; trait Helper { /* ### VARIABLES ################################################ # */ protected static array $__CACHED_GETTER = []; /* ### PUBLIC STATIC FUNCTIONS ################################## # */ public static function getMagicGetter() : array { $class = static::class; if( !isset( static::$__CACHED_GETTER[ $class ] ) ) { static::$__CACHED_GETTER[ $class ] = static::resolveMagicGettersFromClass(); } return static::$__CACHED_GETTER[ $class ]; } /* ### PRIVATE STATIC FUNCTIONS ################################# # */ private static function resolveMagicGettersFromClass() : array { $ref = new ReflectionClass( static::class ); $result = [ "exact" => [], "pattern" => [], "fallback" => [], ]; foreach( $ref->getMethods(ReflectionMethod::IS_PUBLIC ) as $method ) { foreach( $method->getAttributes(PHP\Attributes\Magic\Get::class ) as $attr ) { $meta = $attr->newInstance(); $target = $method->getName(); if( $meta->fallback || $meta->match === NULL || $meta->match === "*" ) { $result["fallback"][ $meta->priority ][] = $target; continue; } if( @preg_match("/^{$meta->match}$/", "" ) !== FALSE ) { $result["pattern"][ $meta->priority ][] = [ "/^{$meta->match}$/", $target ]; continue; } $result["exact"][ $meta->priority ][ $meta->match ] = $target; } } foreach( $result as &$type ) { ksort( $type ); $type = array_reduce_recursive( $type ); $type = array_values( $type ); } return $result; } /* ### MAGIC FUNCTIONS ########################################## # */ public function __get( string $name ) : mixed { $map = self::getMagicGetter(); // 1. exact if( isset( $map["exact"][ $name ] ) ) { return $this->{$map["exact"][ $name ]}(); } // 2. pattern foreach( $map["pattern"] as [ $regex, $method ]) { if( preg_match( $regex, $name ) ) { try { return $this->{$method}( $name ); } catch( Exceptions\PatternFailed $e ) {} } } // 3. fallback foreach( $map["fallback"] as $method ) { try { return $this->{$method}( $name ); } catch( Exceptions\FallbackFailed $e ) {} } // 4. method getXyz() if( method_exists( $this, "get{$name}" ) ) { return $this->{"get{$name}"}(); } // 5. property access if( property_exists( $this, $name ) ) { return $this->{$name}; } throw new \BadMethodCallException("Unbekannte dynamische Eigenschaft: {$name}"); } } /** Datei: library/ARUNOX/API/PHP/Attributes/Magic/Call/Exceptions/PatternFailed.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Magic\Call\Exceptions; use Exception; class PatternFailed extends Exception {} /** Datei: library/ARUNOX/API/PHP/Attributes/Magic/Call/Exceptions/FallbackFailed.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Magic\Call\Exceptions; use Exception; class FallbackFailed extends Exception {} /** Datei: library/ARUNOX/API/PHP/Attributes/Magic/Call/Call.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Magic; use Attribute; use ARUNOX\API\PHP; #[Attribute( Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE )] class Call { use PHP\Attributes\Magic\Get\Helper; /* ### VARIABLES ################################################ # */ /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( protected null|string $match = NULL, protected bool $fallback = FALSE ){} } /** Datei: library/ARUNOX/API/PHP/Attributes/Magic/Call/Helper.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Magic\Call; use ARUNOX\API\PHP; use ReflectionClass; use ReflectionMethod; trait Helper { /* ### VARIABLES ################################################ # */ protected static array $__CACHED_CALLER = []; /* ### PUBLIC STATIC FUNCTIONS ################################## # */ public static function getMagicCaller( bool $static = FALSE ) : array { $class = static::class; $type = $static ? "static" : "normal"; if( !isset( static::$__CACHED_CALLER[ $class ] ) ) { static::$__CACHED_CALLER[ $class ] = static::resolveMagicCallerFromClass(); } return static::$__CACHED_CALLER[ $class ][ $type ]; } /* ### PRIVATE STATIC FUNCTIONS ################################# # */ private static function resolveMagicCallerFromClass() : array { $ref = new ReflectionClass( static::class ); $result = [ "exact" => [], "pattern" => [], "fallback" => [], ]; $result = [ "static" => $result, "normal" => $result, ]; foreach( $ref->getMethods(ReflectionMethod::IS_PUBLIC ) as $method ) { foreach( $method->getAttributes(PHP\Attributes\Magic\Call::class ) as $attr ) { $meta = $attr->newInstance(); $target = $method->getName(); $type = $method->isStatic() ? "static" : "normal"; // show( $meta, $method, $type, $target ); if( $meta->fallback || $meta->match === NULL || $meta->match === "*" ) { $result[ $type ]["fallback"][] = $target; continue; } if( @preg_match("/^{$meta->match}$/", "" ) !== FALSE ) { $result[ $type ]["pattern"][] = [ "/^{$meta->match}$/", $target ]; continue; } $result[ $type ]["exact"][ $meta->match ] = $target; } } return $result; } /* ### MAGIC FUNCTIONS ########################################## # */ public function __call( string $name, array $args ) : mixed { $map = self::getMagicCaller(); // if( $name == "getIcon" ) show( $name, $args, $map, FALSE ); // 1. exact if( isset( $map["exact"][ $name ] ) ) { return $this->{$map["exact"][ $name ]}( ...$args ); } // 2. pattern foreach( $map["pattern"] as [ $regex, $method ]) { if( preg_match( $regex, $name, $matches ) ) { try { return $this->{$method}( $matches, ...$args ); } catch( Exceptions\PatternFailed $e ) {} } } // 3. fallback foreach( $map["fallback"] as $method ) { try { return $this->{$method}( $name, ...$args ); } catch( Exceptions\FallbackFailed $e ) {} } return NULL; // throw new \BadMethodCallException("Unbekannte dynamische Methode: {$name}"); } public static function __callStatic( string $name, array $args ) : mixed { $map = self::getMagicCaller( TRUE ); // show( static::class, FALSE ); // 1. exact if( isset( $map["exact"][ $name ] ) ) { return static::{$map["exact"][ $name ]}( ...$args ); } // 2. pattern foreach( $map["pattern"] as [ $regex, $method ]) { if( preg_match( $regex, $name, $matches ) ) { try { return static::{$method}( $matches, ...$args ); } catch( Exceptions\PatternFailed $e ) {} } } // 3. fallback foreach( $map["fallback"] as $method ) { try { return static::{$method}( $name, ...$args ); } catch( Exceptions\FallbackFailed $e ) {} } return NULL; // throw new \BadMethodCallException("Unbekannte dynamische Methode: {$name}"); } } /** Datei: library/ARUNOX/API/PHP/Attributes/Magic/Set/Set.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Magic; use Attribute; use ARUNOX\API\PHP; #[Attribute( Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE )] class Set { use PHP\Attributes\Magic\Get\Helper; /* ### VARIABLES ################################################ # */ /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( protected null|string $match = NULL, protected bool $fallback = FALSE ){} } /** Datei: library/ARUNOX/API/PHP/Attributes/Magic/Set/Helper.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Magic\Set; use ARUNOX\API\PHP; use ReflectionClass; use ReflectionMethod; trait Helper { /* ### VARIABLES ################################################ # */ protected static array $__CACHED_SETTER = []; /* ### PUBLIC STATIC FUNCTIONS ################################## # */ public static function getMagicSetter() : array { $class = static::class; if( !isset( static::$__CACHED_SETTER[ $class ] ) ) { static::$__CACHED_SETTER[ $class ] = static::resolveMagicSettersFromClass(); } return static::$__CACHED_SETTER[ $class ]; } /* ### PRIVATE STATIC FUNCTIONS ################################# # */ private static function resolveMagicSettersFromClass() : array { $ref = new ReflectionClass( static::class ); $result = [ "exact" => [], "pattern" => [], "fallback" => [], ]; foreach( $ref->getMethods(ReflectionMethod::IS_PUBLIC ) as $method ) { foreach( $method->getAttributes(PHP\Attributes\Magic\Set::class ) as $attr ) { $meta = $attr->newInstance(); $target = $method->getName(); if( $meta->fallback || $meta->match === NULL || $meta->match === "*" ) { $result["fallback"][] = $target; continue; } if( @preg_match("/^{$meta->match}$/", "" ) !== FALSE ) { $result["pattern"][] = [ "/^{$meta->match}$/", $target ]; continue; } $result["exact"][ $meta->match ] = $target; } } return $result; } /* ### MAGIC FUNCTIONS ########################################## # */ public function __set( string $name, mixed $value ) : void { $map = self::getMagicSetter(); // 1. exact if( isset( $map["exact"][ $name ] ) ) { // show( "Case 1", $map["exact"], $name, $value, FALSE ); $this->{$map["exact"][ $name ]}( $value ); return; } // 2. pattern foreach( $map["pattern"] as [ $regex, $method ]) { if( preg_match( $regex, $name ) ) { // show( "Case 2", $method, $name, $value, FALSE ); $this->{$method}( $name, $value ); return; } } // 3. fallback foreach( $map["fallback"] as $method ) { // show( "Case 3", $method, $name, $value, FALSE ); $this->{$method}( $name, $value ); return; } // 4. method getXyz() if( method_exists( $this, "set{$name}" ) ) { // show( "Case 4", "set{$name}", $value, FALSE ); $this->{"set{$name}"}( $value ); return; } // 5. property access if( property_exists( $this, $name ) ) { // show( "Case 5", $name, $value, FALSE ); $this->{$name} = $value; return; } throw new \BadMethodCallException("Unbekannte dynamische Eigenschaft: {$name}"); } } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Attributes/Attributes.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database; use Attribute; use ARUNOX\API\PHP; use ARUNOX\Database; #[Attribute( Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE )] class Attributes { use PHP\Attributes\Magic\Get\Helper; /* ### VARIABLES ################################################ # */ protected static array $ATTRIBUTES = [ "status" => Database\Attribute\Status::class, "date_create" => Database\Attribute\DateTime::class, "date_edit" => Database\Attribute\DateTime::class, ]; /* ### PROTECTED FUNCTIONS ###################################### # */ protected function getClass() { return $this->class ?? ( static::$ATTRIBUTES[ $this->column ] ?? NULL ); } /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( protected string $column, protected null|string $class = NULL ){ if( !$class ) $this->class = $this->getClass( $this->column ); } } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Attributes/Resolve/Helper.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database\Attributes\Resolve; use ARUNOX\API\PHP; use ReflectionClass; use ARUNOX\Interfaces\Supports; trait Helper { /* ### VARIABLES ################################################ # */ protected static array $__CACHED_RESOLVES = []; /* ### PUBLIC FUNCTIONS ######################################### # */ #[PHP\Attributes\Magic\Get( fallback: TRUE, priority: 5 )] public function handleGetResolve( string $column ) { if( static::existsResolve( $column ) ) { $resolves = static::getResolve( $column ); $result = NULL; foreach( $resolves as $resolve ) { if( preg_match( '/\$\{[a-z]+\}/', $resolve ) ) { $result = preg_replace_callback( '/\$\{([a-z]+)\}/', fn( $m ) => $this->attributes[ $m[1] ], $resolve ); } else if( is_string( $resolve ) ) $result = $this->attributes[ $resolve ]; if( preg_replace( "/\s+/", "", $result ) != NULL ) return $result; } return ""; } throw new PHP\Attributes\Magic\Get\Exceptions\FallbackFailed(); } /* ### PUBLIC STATIC FUNCTIONS ################################## # */ public static function existsResolve( string $column ) : bool { $resolves = static::getResolves(); return isset( $resolves[ $column ] ); } public static function getResolve( string $column ) : array { return static::resolveResolvesFromClass( $column ); } public static function getResolves() : array { return static::resolveResolvesFromClass(); } /* ### PRIVATE STATIC FUNCTIONS ################################# # */ private static function resolveResolvesFromClass( null|string $column = NULL ) : string|array { $reflection = new ReflectionClass( static::class ); $attributes = []; if( !isset( static::$__CACHED_RESOLVES[ static::class ] ) ) { do { foreach( $reflection->getAttributes( PHP\Attributes\Database\Attributes\Resolve::class ) as $attribute ) { $instance = $attribute->newInstance(); if( !empty( $attributes ) ) break 2; $attributes[ $instance->column ] = $instance->resolves; } $reflection = $reflection->getParentClass(); } while ($reflection); static::$__CACHED_RESOLVES[ static::class ] = $attributes; } if( $column ) { return static::$__CACHED_RESOLVES[ static::class ][ $column ] ?? ""; } return static::$__CACHED_RESOLVES[ static::class ] ?? ""; } } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Attributes/Resolve/Resolve.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database\Attributes; use Attribute; use ARUNOX\API\PHP; #[Attribute( Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE )] class Resolve { use PHP\Attributes\Magic\Get\Helper; /* ### VARIABLES ################################################ # */ protected array $resolves = []; /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( protected string $column, ...$resolves ){ $this->resolves = (array)$resolves; } } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Attributes/Helper.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database\Attributes; use ARUNOX\API\PHP; use ReflectionClass; use ARUNOX\Interfaces\Supports; trait Helper { /* ### VARIABLES ################################################ # */ protected static array $ATTRIBUTES = []; protected static array $__CACHED_ATTRS = []; protected static array $__CALLABLE_ATTRS = [ "toggle" => Supports\Toggle::class, ]; /* ### PUBLIC FUNCTIONS ######################################### # */ #[PHP\Attributes\Magic\Call( fallback: TRUE )] public function handleAttributesCall( string $name, ...$args ) { $name = preg_split('/([[:upper:]][[:lower:]]+)/', $name, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); if( is_array( $name ) ) { $name = array_map( "strtolower", $name ); if( key_exists( $name[0], static::$__CALLABLE_ATTRS ) ) { $class = static::$__CALLABLE_ATTRS[ $name[0] ]; if( isset( $this->{$name[1]} ) ) { if( $this->{$name[1]} instanceof $class ) { if( method_exists( $this->{$name[1]}, "setParent" ) ) { $this->{$name[1]}->setParent( $this ); } return $this->{$name[1]}->{$name[0]}( ...$args ); } } } } throw new PHP\Attributes\Magic\Call\Exceptions\FallbackFailed(); } /* ### PUBLIC STATIC FUNCTIONS ################################## # */ public static function existsAttribute( string $name ) : bool { $attrs = static::getAttributes(); return isset( $attrs[ $name ] ); } public static function getAttribute( string $name ) : mixed { $attrs = static::getAttributes(); return $attrs[ $name ] ?? NULL; } public static function getAttributes() : array { $class = static::class; if( !isset( static::$__CACHED_ATTRS[ $class ] ) ) { $attrs = static::resolveAttributesFromClass(); $attrs = static::getMergedAttributes( $attrs ); static::$__CACHED_ATTRS[ $class ] = $attrs; } return static::$__CACHED_ATTRS[ $class ]; } /* ### PRIVATE STATIC FUNCTIONS ################################# # */ private static function getMergedAttributes( null|array $defaults = []) : array { $result = $defaults; $class = static::class; do { if( property_exists( $class, "ATTRIBUTES" ) ) { $ref = new ReflectionClass( $class ); if( $ref->hasProperty("ATTRIBUTES") ) { $prop = $ref->getProperty("ATTRIBUTES"); if( $prop->isStatic() ) { $prop->setAccessible( TRUE ); $attrs = $prop->getValue(); if( is_array( $attrs ) ) { $result = array_merge( $attrs, $result ); } } } } } while( $class = get_parent_class( $class ) ); return $result; } private static function resolveAttributesFromClass() : array { $ref = new ReflectionClass( static::class ); $result = []; foreach( $ref->getAttributes( PHP\Attributes\Database\Attributes::class ) as $attr ) { $inst = $attr->newInstance(); $result[ $inst->column ] = $inst->class; } return $result; } } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Definitions/Model.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database\Definitions; use Attribute; use ARUNOX\API\PHP; #[Attribute( Attribute::TARGET_CLASS )] class Model extends PHP\Attributes\Attribute { /* ### VARIABLES ################################################ # */ /* ### PUBLIC STATIC FUNCTIONS ################################## # */ public function getModelClass() : string|bool { return $this->class; } public function callModelClass( string $method, ...$args ) { return $this->getModelClass()::{$method}( ...$args ); } /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( protected string $class ){ parent::__construct( $class ); } } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Definitions/HashID.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database\Definitions; use Attribute; use ARUNOX\API\PHP; use Hashids\Hashids; use ARUNOX\Core\Hooks; #[Attribute( Attribute::TARGET_CLASS )] class HashID extends PHP\Attributes\Attribute { /* ### VARIABLES ################################################ # */ /* ### PUBLIC FUNCTIONS ######################################### # */ public function getHashIDPrefix() : string { return $this->prefix; } public function getHashID( int $primary ) : string { $prefix = $this->getHashIDPrefix() ?? $this->getTable(); $hashids = new Hashids( $this->getTable(), 16 ); $numbers = [ $primary ]; $numbers = Hooks::filterWithNames( "model::hashids", $this->getTable(), $numbers, $this->getTable() ); $encoded = $hashids->encode( $numbers ); $hashid = "{$this->prefix}_{$encoded}"; return $hashid; } public function resolveHashID( string $hashid, null|int $index = 0 ) : int|bool|array { $prefix = $this->getHashIDPrefix() ?? $this->getTable(); $hashid = explode( "_", $hashid ); if( $hashid[0] !== $prefix ) return FALSE; $sqids = new Hashids( $this->getTable(), 16 ); $decoded = $sqids->decode( $hashid[1] ); if( !$decoded ) return FALSE; return $index === NULL ? $decoded : $decoded[ $index ]; } public function resolveHashIDPrefix( string $hashid, null|string $column = NULL ) { $split = explode( "_", $hashid ); $class = array_search( $split[0], $this->getCacheAll() ); if( !$class ) return NULL; $data = $class::get( $hashid ); if( $column ) return $data->{$column} ?? NULL; return $data; } /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### PRIVATE FUNCTIONS ######################################## # */ private function getTable() : string { return $this->getParentClass()::getTable(); } /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( protected string $prefix ){ parent::__construct( $prefix ); } } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Definitions/Table.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database\Definitions; use Attribute; use ARUNOX\API\PHP; #[Attribute( Attribute::TARGET_CLASS )] class Table extends PHP\Attributes\Attribute { /* ### VARIABLES ################################################ # */ /* ### PUBLIC FUNCTIONS ######################################### # */ public function getTable( null|string $suffix = NULL ) { return implode( "_", array_filter( [ $this->table, $suffix ] ) ); } public function resolveTable( string $table ) { $class = array_search( $table, $this->getCacheAll() ); if( !$class ) return NULL; return $class; } /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( protected string $table, ){ parent::__construct( $table ); } } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Definitions/Entity.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database\Definitions; use Attribute; use ARUNOX\API\PHP; #[Attribute( Attribute::TARGET_CLASS )] class Entity extends PHP\Attributes\Attribute { /* ### VARIABLES ################################################ # */ /* ### PUBLIC STATIC FUNCTIONS ################################## # */ public function getEntityClass() : string|bool { return $this->class; } public function callEntityClass( string $method, ...$args ) { return $this->getEntityClass()::{$method}( ...$args ); } /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( protected string $class ){ parent::__construct( $class ); } } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Definitions/Origin.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database\Definitions; use Attribute; use ARUNOX\API\PHP; use ARUNOX\Autoloader; #[Attribute( Attribute::TARGET_CLASS )] class Origin extends PHP\Attributes\Attribute { /* ### VARIABLES ################################################ # */ /* ### PUBLIC STATIC FUNCTIONS ################################## # */ public function getOriginClass() : string|bool { return $this->class; } public function callOriginClass( string $method, ...$args ) { return $this->getOriginClass()::{$method}( ...$args ); } public function getControllerClass() { return Autoloader::find( $this->getNamespace(), "controller" ); } public function callControllerClass( string $method, ...$args ) { return $this->getControllerClass()::{$method}( ...$args ); } /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( protected string $class ){ parent::__construct( $class ); } } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Options/Label.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database\Options; use Attribute; use ARUNOX\API\PHP; #[Attribute( Attribute::TARGET_CLASS | Attribute::TARGET_CLASS_CONSTANT )] class Label extends PHP\Attributes\Attribute { /* ### VARIABLES ################################################ # */ protected static null|string $__DEFAULT = "getSingular"; /* ### PUNLIC FUNCTIONS ######################################### # */ public function getLabel() : array { return [ "singular" => $this->singular, "plural" => $this->plural, "group" => $this->group, ]; } public function getSingular( null|string $label = NULL, ...$tokens ) : string { return $this->getLabelSingular( $label, ...$tokens ); } public function getLabelSingular( null|string $label = NULL, ...$tokens ) : string { return $this->resolveLabel( "singular", $label, "Entry", ...$tokens ); } public function getPlural( null|string $label = NULL, ...$tokens ) : string { return $this->getLabelPlural( $label, ...$tokens ); } public function getLabelPlural( null|string $label = NULL, ...$tokens ) : string { return $this->resolveLabel( "plural", $label, "Entries", ...$tokens ); } public function getLabelGroup( null|string $label = NULL, ...$tokens ) : string { return $this->resolveLabel( "group", $label, "Overview", ...$tokens ); } /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### PRIVATE FUNCTIONS ######################################## # */ private function resolveLabel( null|string $column = NULL, null|string $label = NULL, null|string $fallback = NULL, ...$tokens ) : string|array { if( $column ) { if( !$label ) return __( $this->getLabel()[ $column ] ?? $fallback ); return __( $label, $this->getLabel()[ $column ] ?? $fallback, ...$tokens ); } else return $this->getLabel() ?? []; } /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( protected string $singular, protected null|string $plural = NULL, protected null|string $group = NULL ){ if( !$plural ) $this->plural = $singular; if( !$group ) $this->group = $this->plural; } } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Options/Color.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database\Options; use Attribute; use ARUNOX\API\PHP; use ARUNOX\Plugins\REST; #[Attribute( Attribute::TARGET_CLASS | Attribute::TARGET_CLASS_CONSTANT )] class Color extends PHP\Attributes\Attribute { /* ### VARIABLES ################################################ # */ protected static null|string $__DEFAULT = "getColor"; /* ### PUBLIC FUNCTIONS ######################################### # */ public function getColor() { return $this->CONFIG; } /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### MAGIC FUNCTIONS ########################################## # */ } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Options/Toggle.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database\Options; use Attribute; use ARUNOX\API\PHP; use ARUNOX\Plugins\REST; #[Attribute( Attribute::TARGET_CLASS_CONSTANT )] class Toggle extends PHP\Attributes\Attribute { /* ### VARIABLES ################################################ # */ protected static null|string $__DEFAULT = "getToggle"; /* ### PUBLIC FUNCTIONS ######################################### # */ public function getToggle() { return $this->CONFIG; } /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### MAGIC FUNCTIONS ########################################## # */ } /** Datei: library/ARUNOX/API/PHP/Attributes/Database/Options/Icon.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Database\Options; use Attribute; use ARUNOX\API\PHP; use ARUNOX\Plugins\REST; #[Attribute( Attribute::TARGET_CLASS | Attribute::TARGET_CLASS_CONSTANT )] class Icon extends PHP\Attributes\Attribute { /* ### VARIABLES ################################################ # */ protected static null|string $__DEFAULT = "getIcon"; /* ### PUBLIC FUNCTIONS ######################################### # */ public function getIcon() { return $this->CONFIG; } /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### MAGIC FUNCTIONS ########################################## # */ } /** Datei: library/ARUNOX/API/PHP/Attributes/Helper.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes; use Attribute; use ARUNOX\API\PHP; use ReflectionClass; use ReflectionAttribute; use ReflectionClassConstant; trait Helper { /* ### VARIABLES ################################################ # */ protected static array $__CACHED_ATTRIBUTES = []; protected static array $__CACHED_CONSTANTS = []; /* ### PUBLIC FUNCTIONS ######################################### # */ #[PHP\Attributes\Magic\Call( fallback: TRUE )] public static function handleDynamicAttributesCallStatic( string $name, ...$args ) { $objects = static::getDynamicAttributes(); // if( $name == "getIcon" ) show( $name, $args, get_called_class(), get_class(), static::class, $objects, FALSE ); foreach( $objects as $object ) { if( method_exists( $object, $name ) ) { return $object->{$name}( ...$args ); } } // show( $name, $args, $objects, FALSE ); throw new PHP\Attributes\Magic\Call\Exceptions\FallbackFailed(); } #[PHP\Attributes\Magic\Call( fallback: TRUE )] public function handleDynamicAttributesCall( string $name, ...$args ) { return static::handleDynamicAttributesCallStatic( $name, ...$args ); } /* ### PUBLIC STATIC FUNCTIONS ################################## # */ public static function getDynamicAttributes() : array { return static::resolveDynamicAttributesFromClass(); } /* ### PRIVATE STATIC FUNCTIONS ################################# # */ private static function resolveDynamicAttributesFromReflection( $reflection ) : array { $attributes = []; do { foreach( $reflection->getAttributes( PHP\Attributes\Attribute::class, ReflectionAttribute::IS_INSTANCEOF ) as $attribute ) { $attrName = $attribute->getName(); $attrInstance = $attribute->newInstance(); $attrArguments = $attribute->getArguments(); $attrReflection = new ReflectionClass( $attribute->getName() ); $attrAttributes = $attrReflection->getAttributes( Attribute::class ); $attrRepeatable = Attribute::IS_REPEATABLE & $attrAttributes[0]->getArguments()[0]; if( method_exists( $reflection, "getNamespaceName" ) ) { $attrInstance->setNamespace( $reflection->getNamespaceName() ); } $attrInstance->setParentClass( static::class ); if( !key_exists( $attrName, $attributes ) ) { $attributes[ $attrName ] = $attrInstance; } if( !$attrRepeatable ) continue; $attributes[ $attrName ]->add( ...$attrArguments ); } if( !method_exists( $reflection, "getParentClass" ) ) break; $reflection = $reflection->getParentClass(); } while( $reflection ); return array_filter( $attributes ); } private static function resolveDynamicAttributesFromClass() : array { $reflection = new ReflectionClass( static::class ); if( !isset( static::$__CACHED_ATTRIBUTES[ static::class ] ) ) { static::$__CACHED_ATTRIBUTES[ static::class ] = static::resolveDynamicAttributesFromReflection( $reflection ); } return static::$__CACHED_ATTRIBUTES[ static::class ] ?? []; } private static function resolveDynamicAttributesFromConstants() : array { $reflection = new ReflectionClass( static::class ); $constants = []; if( !isset( static::$__CACHED_CONSTANTS[ static::class ] ) ) { foreach( $reflection->getReflectionConstants( ReflectionClassConstant::IS_PUBLIC ) as $constant ) { $attributes = static::resolveDynamicAttributesFromReflection( $constant ); if( key_exists( $constant->getValue(), $constants ) ) continue; $constants[ $constant->getValue() ] = [ "name" => $constant->getName(), "value" => $constant->getValue(), "attributes" => $attributes, ]; } static::$__CACHED_CONSTANTS[ static::class ] = array_filter( $constants ); // if( static::class == \ARUNOX\Plugins\Calendars\Entries\Participants\Status::class ) { // show( static::class, $constants, $reflection->getReflectionConstants( ReflectionClassConstant::IS_PUBLIC ) ); // } } return static::$__CACHED_CONSTANTS[ static::class ] ?? []; } } /** Datei: library/ARUNOX/API/PHP/Attributes/Controller/Label.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Controller; use Attribute; use ARUNOX\API\PHP; #[Attribute( Attribute::TARGET_CLASS )] class Label extends PHP\Attributes\Database\Options\Label {} /** Datei: library/ARUNOX/API/PHP/Attributes/Controller/Notifications/Helper.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Controller\Notifications; use Attribute; use ARUNOX\API\PHP; use ReflectionClass; trait Helper { /* ### VARIABLES ################################################ # */ protected static array $__CACHED_NOTIFIES = []; /* ### PUBLIC STATIC FUNCTIONS ################################## # */ public static function getNotify( string|array $type, null|string $label = NULL ) : string|bool { return static::getNotification( $type, $label ); } public static function getNotification( string|array $type, null|string|array $label = NULL ) : string|bool { $notify = static::resolveNotificationsFromClass( ...(array)$type ); if( $label ) { $label = new Label( ...(array)$label ); $label = $label->getLabel() ?? NULL; } if( $label == NULL ) { $label = static::getLabel(); } if( $label ) { $notify = preg_replace_callback( '/\{\$LABEL\.([a-z]+)\}/', fn( $match ) => $label[ $match[1] ], $notify ); } return $notify; } public static function getNotifications() : array { return static::resolveNotificationsFromClass(); } /* ### PRIVATE STATIC FUNCTIONS ################################# # */ private static function resolveNotificationsFromClass( ...$type ) : string|array { $reflection = new ReflectionClass( static::class ); $attributes = []; $type = implode( ".", $type ); if( !isset( static::$__CACHED_NOTIFIES[ static::class ] ) ) { do { foreach( $reflection->getAttributes( PHP\Attributes\Controller\Notifications::class ) as $attribute ) { $instance = $attribute->newInstance(); if( key_exists( $instance->type, $attributes ) ) continue; $attributes[ $instance->type ] = $instance->message; } $reflection = $reflection->getParentClass(); } while ($reflection); static::$__CACHED_NOTIFIES[ static::class ] = $attributes; } if( $type ) return static::$__CACHED_NOTIFIES[ static::class ][ $type ] ?? "Unbekannter Fehler!"; else return static::$__CACHED_NOTIFIES[ static::class ] ?? []; } } /** Datei: library/ARUNOX/API/PHP/Attributes/Controller/Notifications/Notifications.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Controller; use Attribute; use ARUNOX\API\PHP; #[Attribute( Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE )] class Notifications { use PHP\Attributes\Magic\Get\Helper; /* ### VARIABLES ################################################ # */ /* ### PROTECTED FUNCTIONS ###################################### # */ /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( protected string $type, protected string $message, protected bool $default = FALSE ){} } /** Datei: library/ARUNOX/API/PHP/Attributes/Controller/Icon.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Controller; use Attribute; use ARUNOX\API\PHP; #[Attribute( Attribute::TARGET_CLASS )] class Icon extends PHP\Attributes\Database\Options\Icon {} /** Datei: library/ARUNOX/API/PHP/Attributes/Controller/Route/Route.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Controller; use Attribute; use ARUNOX\API\PHP; use ARUNOX\API\BaseController; #[Attribute( Attribute::TARGET_CLASS )] class Route { use PHP\Attributes\Magic\Get\Helper; /* ### VARIABLES ################################################ # */ protected string $route = "/"; /* ### PUNLIC FUNCTIONS ######################################### # */ public function get() { return $this->route; } /* ### MAGIC FUNCTIONS ########################################## # */ public function __construct( ... $route ){ $segments = []; foreach( $route as $item ) { if( class_exists( $item ) ) { if( method_exists( $item, "getRoute" ) ) { array_unshift( $segments, $item::getRoute() ?? NULL ); } continue; } if( is_string( $item ) ) array_unshift( $segments, $item ); } $segments = array_filter( $segments ); $segments = implode( "/", $segments ); $segments = preg_replace( "/\/+/", "/", $segments ); $segments = strtolower( $segments ); $this->route = $segments; } } /** Datei: library/ARUNOX/API/PHP/Attributes/Controller/Route/Helper.php **/ * @copyright 2025 ARUNOX * @version 1.1.0 * * @since 1.0.0 File is created */ namespace ARUNOX\API\PHP\Attributes\Controller\Route; use ARUNOX\API\PHP; use ReflectionClass; trait Helper { /* ### VARIABLES ################################################ # */ protected static array $__CACHED_ROUTES = []; /* ### PUBLIC STATIC FUNCTIONS ################################## # */ public static function getRoute( ...$suffixes ) : string { $route = static::resolveRouteFromClass(); $route = preg_replace( "/\\/+/", "/", $route ); $route = preg_replace( "/\\/#/", "#", $route ); $route = explode( "/", $route ); $route = array_filter( $route ); foreach( $suffixes as $suffix ) { if( preg_match( "/([0-9]+):(.*)/", $suffix, $matches ) ) { $pos = $matches[1] * -1; $prev = array_slice( $route, 0, $pos ); $next = array_slice( $route, $pos ); $route = [ ...$prev, $matches[2], ...$next ]; continue; } $route[] = $suffix; } $route = array_filter( $route ); $route = implode( "/", $route ); $route = "/{$route}"; return $route; } /* ### PRIVATE STATIC FUNCTIONS ################################# # */ private static function resolveRouteFromClass() : string { $reflection = new ReflectionClass( static::class ); $attributes = ""; if( !isset( static::$__CACHED_ROUTES[ static::class ] ) ) { do { foreach( $reflection->getAttributes( PHP\Attributes\Controller\Route::class ) as $attribute ) { $instance = $attribute->newInstance(); if( !empty( $attributes ) ) break 2; $attributes = $instance->get(); } $reflection = $reflection->getParentClass(); } while ($reflection); static::$__CACHED_ROUTES[ static::class ] = $attributes; } return static::$__CACHED_ROUTES[ static::class ] ?? ""; } }