kolibri-discuss team mailing list archive
-
kolibri-discuss team
-
Mailing list archive
-
Message #00050
[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