/** 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}"); } }