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