From 3b91a6fc8cf315838f9a508308a5952c35d32dfc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
Date: Sun, 5 Feb 2012 13:58:55 +0100
Subject: [PATCH] Multiple paths for configuration and packages

Added Loader::AddPath() which allows additional paths to be added to
the list in which the loader tries to find both configuration files
and components.
---
 includes/loader.inc.php | 61 ++++++++++++++++++++++++++++++++---------
 1 file changed, 48 insertions(+), 13 deletions(-)

diff --git a/includes/loader.inc.php b/includes/loader.inc.php
index ead5830..ce3b866 100644
--- a/includes/loader.inc.php
+++ b/includes/loader.inc.php
@@ -42,6 +42,7 @@ final class ConfigGetter
 final class Package
 {
 	private $name;
+	private $source;
 
 	private $files;
 	private $requires;
@@ -57,9 +58,10 @@ final class Package
 	private $loaded = false;
 	private $config;
 
-	public function __construct( $name , $description , $config )
+	public function __construct( $name , $description , $config , $source )
 	{
 		$this->name = $name;
+		$this->source = $source;
 
 		$fields = array( 'files' , 'requires' , 'daos' , 'views' , 'ctrls' , 'extras' , 'singletons' , 'pages' , 'hooks' );
 		foreach ( $fields as $field ) {
@@ -103,6 +105,11 @@ final class Package
 		return $this->name;
 	}
 
+	public function source( )
+	{
+		return $this->source;
+	}
+
 	public function files( )
 	{
 		return $this->files;
@@ -188,7 +195,7 @@ final class Loader
 {
 	private static $loader = null;
 
-	private $baseDir;
+	private static $paths = array();
 	private $config;
 	private $packages = array( );
 	private $items = array(
@@ -206,21 +213,38 @@ final class Loader
 
 	private function __construct( )
 	{
-		$this->baseDir = dirname( __FILE__ );
+		if ( empty( Loader::$paths ) ) {
+			array_push( Loader::$paths , dirname( __FILE__ ) );
+		}
 		$this->loadConfig( );
 		$this->loadPackageDescriptions( );
 	}
 
 	private function loadConfig( )
 	{
-		$config = array( );
-		@include( $this->baseDir . '/config.inc.php' );
-		$this->config = $config;
+		$mergedConfig = array( );
+		foreach ( Loader::$paths as $directory ) {
+			if ( ! file_exists( $directory . '/config.inc.php' ) ) {
+				continue;
+			}
+
+			$config = array( );
+			@include( $directory . '/config.inc.php' );
+			$mergedConfig = array_merge_recursive( $mergedConfig , $config );
+		}
+		$this->config = $mergedConfig;
 	}
 
 	private function loadPackageDescriptions( )
 	{
-		if ( !( $dh = opendir( $this->baseDir ) ) ) {
+		foreach ( Loader::$paths as $source ) {
+			$this->loadPackageDescriptionsFrom( $source );
+		}
+	}
+
+	private function loadPackageDescriptionsFrom( $source )
+	{
+		if ( !( $dh = opendir( $source ) ) ) {
 			throw new LoaderException( "unable to access directory" );
 		}
 
@@ -229,9 +253,9 @@ final class Loader
 				continue;
 			}
 
-			$path = "{$this->baseDir}/$entry";
+			$path = "$source/$entry";
 			if ( is_dir( $path ) && is_file( "$path/package.inc.php" ) ) {
-				$this->loadDescription( $entry );
+				$this->loadDescription( $entry , $source );
 			}
 		}
 
@@ -239,10 +263,10 @@ final class Loader
 	}
 
 
-	private function loadDescription( $name )
+	private function loadDescription( $name , $source )
 	{
 		$package = array( );
-		require( $this->baseDir . '/' . $name . '/package.inc.php' );
+		require( $source . '/' . $name . '/package.inc.php' );
 		if ( empty( $package ) ) {
 			throw new LoaderException( "package '$name': no information" );
 		}
@@ -251,7 +275,7 @@ final class Loader
 			$this->config[ $name ] = array( );
 		}
 
-		$package = new Package( $name , $package , $this->config[ $name ] );
+		$package = new Package( $name , $package , $this->config[ $name ] , $source );
 		$this->packages[ $name ] = $package;
 		$this->config[ $name ] = null;
 
@@ -289,7 +313,7 @@ final class Loader
 			$this->loadPackage( $dependency );
 		}
 
-		$dir = $this->baseDir . '/' . $name;
+		$dir = $package->source() . '/' . $name;
 		foreach ( $package->files( ) as $file ) {
 			require_once( "$dir/$file.inc.php" );
 		}
@@ -393,6 +417,17 @@ final class Loader
 	}
 
 
+	public static function AddPath( $path )
+	{
+		if ( empty( Loader::$paths ) ) {
+			array_push( Loader::$paths , dirname( __FILE__ ) );
+		}
+		if ( is_dir( $path ) ) {
+			array_push( Loader::$paths , $path );
+		}
+	}
+
+
 	public static function PackageConfig( $name )
 	{
 		$loader = Loader::get( );