← Back to team overview

kolibri-discuss team mailing list archive

[Merge] lp:~frode-danielsen/kolibri/config+interceptors into lp:kolibri

 

Frode Danielsen has proposed merging lp:~frode-danielsen/kolibri/config+interceptors into lp:kolibri.

Requested reviews:
    Kolibri Dev (kolibri-dev)

Provides some improvements to the configuration system. New interceptor classes can now be defined in application specific configuration files, in a section named 'interceptors.classes'. Mappings of interceptors for URIs are now also merged when cascading through production => development => test configuration files. This means you only need to define the difference in interceptors for a URI. I.e. production.ini defines '* = "defaultStack"' which adds all interceptors in the default stack to all URIs. In development.ini you can add or subtract more interceptors to this configuration by '* = "params,!session"'.
-- 
https://code.launchpad.net/~frode-danielsen/kolibri/config+interceptors/+merge/7187
Your team Kolibri Discuss is subscribed to branch lp:kolibri.
=== modified file 'src/core/Config.php'
--- src/core/Config.php	2009-04-15 22:00:10 +0000
+++ src/core/Config.php	2009-05-24 16:06:34 +0000
@@ -19,13 +19,13 @@
 	const PRODUCTION = 'production';
 	const DEVELOPMENT = 'development';
 	const TEST = 'test';
-	
+
 	/**
 	 * Current environment mode.
 	 * @var string
 	 */
 	private $mode;
-	
+
 	/**
 	 * General configuration settings.
 	 * @var array
@@ -38,7 +38,7 @@
 	 * @var array
 	 */
 	private $autoloadClasses;
-	
+
 	/**
 	 * Name of interceptors and interceptor stacks mapped to interceptor classes.
 	 * @var array
@@ -50,13 +50,13 @@
 	 * @var array
 	 */
 	private $interceptorSettings;
-	
+
 	/**
 	 * Prepared list of URIs to unique set of interceptors.
 	 * @var array
 	 */
 	private $interceptorMappings;
-	
+
 	/**
 	 * Defines the validation classes.
 	 * @var array
@@ -68,7 +68,7 @@
 	 * @var array
 	 */
 	private $validationMessages;
-	
+
 	/**
 	 * Singleton instance of this class.
 	 * @var Config
@@ -81,31 +81,35 @@
 	 */
 	private function __construct ($mode) {
 		$this->mode = $mode;
-		
+
 		require(ROOT . '/conf/autoload.php');
 		require(ROOT . '/conf/interceptors.php');
 		require(ROOT . '/conf/validation.php');
 		require(ROOT . '/core/ConfigHelper.php');
-		
+
 		// Cache the autoload class index
 		$this->autoloadClasses = $autoloadClasses;
-		
+
 		// Load relevant app configuration depending on current environment mode
 		$helper = new ConfigHelper($this->mode, $interceptors);
 		$this->config = $helper->loadApp();
-		
+
 		/*
 		 * Extract all interceptor configurations from the loaded application
 		 * configuration. These configurations are irrelevant as normal configuration
 		 * values. They are instead merged with the default configuration and compiled
 		 * internally for use with the Dispatcher.
 		 */
+		if (isset($this->config['interceptors.classes'])) {
+			$helper->addInterceptorClasses($this->config['interceptors.classes']);
+			unset($this->config['interceptors.classes']);
+		}
 		if (isset($this->config['interceptors.stacks'])) {
 			$appInterceptorStacks = $this->config['interceptors.stacks'];
 			unset($this->config['interceptors.stacks']);
 		}
 		else $appInterceptorStacks = array();
-		
+
 		if (isset($this->config['interceptors.settings'])) {
 			$appInterceptorSettings = $this->config['interceptors.settings'];
 			unset($this->config['interceptors.settings']);
@@ -117,7 +121,7 @@
 			unset($this->config['interceptors']);
 		}
 		else $appInterceptorMappings = array();
-		
+
 		// Compile single index of interceptor classes, default stacks and application stacks
 		$this->interceptorClasses = $helper->prepareInterceptors($interceptorStacks,
 				$appInterceptorStacks);
@@ -127,12 +131,12 @@
 		// Flatten stacks and filter down to a unique list of interceptors for each URI
 		$this->interceptorMappings =
 				$helper->prepareInterceptorMappings($appInterceptorMappings);
-		
+
 		// Store validation configuration from conf/validation.php
 		$this->validationClasses = $validators;
 		$this->validationMessages = $validationMessages;
 	}
-	
+
 	/**
 	 * Initializes PHP settings based on the current configuration. This is done separately
 	 * from the constructor to support initalization after loading a stored instance
@@ -144,7 +148,7 @@
 		 * conf/autoload.php
 		 */
 		ClassLoader::initialize($this->autoloadClasses);
-		
+
 		$incPath = ROOT . '/lib';
 		if (file_exists(APP_PATH . '/lib')) {
 			$incPath .= PATH_SEPARATOR . APP_PATH . '/lib';
@@ -154,7 +158,7 @@
 			$incPath .= PATH_SEPARATOR . implode(PATH_SEPARATOR, $paths);
 		}
 		ini_set('include_path', ini_get('include_path') . PATH_SEPARATOR . $incPath);
-		
+
 		/*
 		 * Sets the current locale for date formatting et cetera
 		 * XXX: We leave LC_NUMERIC at default, as locales with comma as decimal seperator
@@ -167,11 +171,11 @@
 			setlocale(LC_NUMERIC, $envLocale);
 		}
 	}
-	
+
 	/**
 	 * Returns an instance of this class. An existing instance is returned if one exists, else
 	 * a new instance is created.
-	 * 
+	 *
 	 * @return Config
 	 */
 	public static function getInstance () {
@@ -209,15 +213,15 @@
 
 			return self::DEVELOPMENT;
 		}
-		
+
 		$instance = Config::getInstance();
 		return $instance->mode;
 	}
-	
+
 	/**
 	 * Returns the value of the configuration setting with the specified key, or
 	 * <code>NULL</code> if not found. If no key is supplied, all settings are returned.
-	 * 
+	 *
 	 * @param string $key Key of the configuration value to return, or <code>NULL</code> to
 	 *                    retrieve all.
 	 * @return mixed Configuration variable, <code>NULL</code> og array of all variables.

=== modified file 'src/core/ConfigHelper.php'
--- src/core/ConfigHelper.php	2009-04-15 22:00:10 +0000
+++ src/core/ConfigHelper.php	2009-05-24 16:06:34 +0000
@@ -11,20 +11,20 @@
 	 * @var string
 	 */
 	private $runMode;
-	
+
 	/**
 	 * Pure mapping of interceptor names to classes.
 	 * @var array
 	 */
 	private $interceptorClasses;
-	
+
 	/**
 	 * Extended mapping of interceptors, prepared from core and application configurations
 	 * and including interceptor stacks.
 	 * @var array
 	 */
 	private $interceptors;
-	
+
 	/**
 	 * Creates a new ConfigHelper for a specific environment mode and list of
 	 * interceptors that exist.
@@ -37,10 +37,10 @@
 		$this->runMode = $mode;
 		$this->interceptorClasses = $interceptorClasses;
 	}
-	
+
 	/**
 	 * Loads and returns and array with all application configuration for the current
-	 * environment mode. Configuration files are loaded for each environment in a 
+	 * environment mode. Configuration files are loaded for each environment in a
 	 * cascading hierarchy:
 	 *   Production -> Development -> Test
 	 * The production configuration will always be loaded, but overridden where
@@ -56,16 +56,16 @@
 		$configStack = array(Config::PRODUCTION);
 		if ($this->runMode != Config::PRODUCTION) {
 			$configStack[] = Config::DEVELOPMENT;
-			
+
 			if ($this->runMode == Config::TEST) {
 				$configStack[] = Config::TEST;
 			}
 		}
-		
+
 		$config = array();
 		foreach ($configStack as $configMode) {
 			$modeConfig = $this->loadMode($configMode);
-			
+
 			/*
 			 * We want to prevent accidental use of the development or production database
 			 * in the test environment where all data is volatile.
@@ -76,11 +76,25 @@
 						. 'development database.');
 				}
 			}
-			
+
+			/*
+			 * Perform string concatenation of interceptor mappings before merging.
+			 * This enables ammending a stack of interceptors for a URI in development.ini
+			 * or test.ini, instead of just overriding the complete stack.
+			 */
+			if (isset($config['interceptors']) && isset($modeConfig['interceptors'])) {
+				foreach ($modeConfig['interceptors'] as $uri => $interceptors) {
+					if (isset($config['interceptors'][$uri])) {
+						$config['interceptors'][$uri] .= ",{$interceptors}";
+						unset($modeConfig['interceptors'][$uri]);
+					}
+				}
+			}
+
 			// Merge config for a specific mode with previously loaded configuration recursively
 			$config = array_merge_recursive_distinct($config, $modeConfig);
 		}
-		
+
 		/*
 		 * The 'app' section in configuration files are automatically flattened to global
 		 * configuration values for convenience.
@@ -91,10 +105,10 @@
 			}
 			unset($config['app']);
 		}
-		
+
 		return $config;
 	}
-	
+
 	/**
 	 * Loads and returns an array with application configuration for a specific environment
 	 * mode.
@@ -110,18 +124,27 @@
 			throw new Exception("Application configuration file missing for "
 				. "{$mode} environment: $file");
 		}
-		
+
 		$config = @parse_ini_file($file, true);
 		if ($config === false) {
 			// Raise the PHP warning from syntax errors in configuration file to an Exception
 			$error = error_get_last();
 			throw new Exception($error['message']);
 		}
-		
+
 		return $config;
 	}
 
 	/**
+	 * Adds custom interceptor classes to Kolibri's core interceptors.
+	 *
+	 * @param array $classes Array with interceptor class names, indexed on their shortname.
+	 */
+	public function addInterceptorClasses (array $classes) {
+		$this->interceptorClasses = array_merge($this->interceptorClasses, $classes);
+	}
+
+	/**
 	 * Merges default interceptor stacks with the application's stacks. Then loops through
 	 * all interceptor stacks, adding each stack to the regular interceptor list with the
 	 * correct interceptors attached. This makes it possible to use a stack just as a single
@@ -135,12 +158,12 @@
 	 */
 	public function prepareInterceptors (array $defaultStacks, array $applicationStacks) {
 		$this->interceptors = $this->interceptorClasses;
-		
+
 		// Parse stacks defined in application ini files
 		foreach ($applicationStacks as $name => $stack) {
 			$applicationStacks[$name] = preg_split('/,\s*/', $stack);
 		}
-		
+
 		$stacks = array_merge($defaultStacks, $applicationStacks);
 		foreach ($stacks as $name => $stack) {
 			/*
@@ -163,10 +186,10 @@
 				}
 			}
 		}
-		
+
 		return $this->interceptors;
 	}
-	
+
 	/**
 	 * Parses and validates application specific interceptor settings, and merges them with
 	 * the default interceptor settings. Each application specific setting must have a name
@@ -183,7 +206,7 @@
 	 */
 	public function prepareInterceptorSettings (array $defaultSettings, array $appSettings) {
 		$parsedAppSettings = array();
-		
+
 		foreach ($appSettings as $setting => $value) {
 			/*
 			 * Make sure setting name contains one, and only one, period. We depend on the
@@ -204,7 +227,7 @@
 				throw new Exception("Invalid key '$setting' in interceptor settings ($file)");
 			}
 		}
-		
+
 		/*
 		 * Both the default settings and parsed application settings are arrays indexed
 		 * on interceptor names with sub-arrays containing settings for each interceptor.
@@ -213,7 +236,7 @@
 		 */
 		return array_merge_recursive_distinct($defaultSettings, $parsedAppSettings);
 	}
-	
+
 	/**
 	 * Prepares interceptor mappings by flattening interceptor stacks and translating
 	 * interceptor names to class names. Must be run after prepareInterceptors() for stacks
@@ -241,7 +264,7 @@
 					$name = substr($name, 1);
 				}
 				$prefix = ($exclude ? '!' : '');
-				
+
 				/*
 				 * An array represents a stack of interceptors which we optimize by
 				 * flattening to simple interceptor class names.
@@ -255,7 +278,7 @@
 					$classes[$name] = $prefix . $this->interceptors[$name];
 				}
 			}
-			
+
 			/*
 			 * Replace string from application config with optimized array of
 			 * interceptor class names.

=== modified file 'src/response/FileResponse.php'
--- src/response/FileResponse.php	2009-04-27 13:27:48 +0000
+++ src/response/FileResponse.php	2009-05-24 15:55:47 +0000
@@ -27,7 +27,7 @@
 
 		if ($isFile) {
 			if (!file_exists($data)) {
-				throw new Exeption("File $data to return to user does not exist.");
+				throw new Exception("File $data to return to user does not exist.");
 			}
 		}
 


Follow ups