From 47b759d993aa9a5953c317564aef9e86d4d51778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Tue, 7 Feb 2012 09:22:25 +0100 Subject: [PATCH] Loader::Find() Added a method to the loader which can find all sub-classes / implementations of a class / interface. The method must be called with at least one argument (the name of the class / interface to find subclasses / implementations of). By default Loader::Find() will look for 'extra' classes. However, it is possible to specify something else (e.g. 'ctrl' for controllers) as the second argument. Finally, by default, only packages which have already been loaded when the method is called are considered. Passing false as the 3rd argument will cause packages to be loaded. --- includes/loader.inc.php | 48 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/includes/loader.inc.php b/includes/loader.inc.php index c82a15c..387c89f 100644 --- a/includes/loader.inc.php +++ b/includes/loader.inc.php @@ -352,7 +352,11 @@ final class Loader if ( empty( $args ) ) { $instance = new $cName(); } else { - $reflection = new ReflectionClass( $cName ); + try { + $reflection = new ReflectionClass( $cName ); + } catch ( ReflectionException $e ) { + throw new LoaderException( "Class $cName from package $pName not found" ); + } $instance = $reflection->newInstanceArgs( $args ); } @@ -391,6 +395,42 @@ final class Loader return $instance; } + public function findClasses( $class , $type = 'extra' , $onlyLoadedPackages = true ) + { + $rType = $type . 's'; + if ( ! array_key_exists( $rType , $this->items ) ) { + throw new LoaderException( "Invalid type '$type'" ); + } + $convertName = ( $type !== 'extra' ); + + $result = array( ); + foreach ( $this->items[ $rType ] as $item => $pName ) { + $cName = $convertName ? Loader::convertName( $type , $item ) : $item; + if ( ! strcasecmp( $cName , $class ) ) { + continue; + } + + $package = $this->packages[ $pName ]; + if ( ! $package->loaded( ) ) { + if ( $onlyLoadedPackages ) { + continue; + } + $this->loadPackage( $pName ); + } + try { + $ref = new ReflectionClass( $cName ); + } catch ( ReflectionException $e ) { + throw new LoaderException( "Class $cName for $item of type $type and package $pName not found" ); + } + + if ( $ref->implementsInterface( $class ) || $ref->isSubclassOf( $class ) ) { + $result[] = $item; + } + } + + return $result; + } + private static function get( ) { @@ -409,6 +449,7 @@ final class Loader return $cName; } + public static function DirectCreate( $type , $convert , $args ) { $name = array_shift( $args ); @@ -488,4 +529,9 @@ final class Loader { return Loader::get( )->getDao( $name ); } + + public static function Find( $class , $type = 'extra' , $onlyLoadedPackages = true ) + { + return Loader::get( )->findClasses( $class , $type , $onlyLoadedPackages ); + } }