From 85e906aa9fbdda32d13afd098e4c22ff0a30963d Mon Sep 17 00:00:00 2001 From: Gunnar Wrobel Date: Mon, 6 Sep 2010 10:04:39 +0200 Subject: [PATCH] Start using dependency injection. --- components/lib/Components.php | 14 +- components/lib/Components/Dependencies.php | 38 +++++ .../lib/Components/Dependencies/Injector.php | 54 +++++++ components/lib/Components/Module.php | 23 ++- components/lib/Components/Module/Base.php | 49 +++++++ components/lib/Components/Module/Installer.php | 132 +++-------------- components/lib/Components/Modules.php | 16 ++- components/lib/Components/Runner/Installer.php | 159 +++++++++++++++++++++ components/package.xml | 102 +++++++------ 9 files changed, 430 insertions(+), 157 deletions(-) create mode 100644 components/lib/Components/Dependencies.php create mode 100644 components/lib/Components/Dependencies/Injector.php create mode 100644 components/lib/Components/Module/Base.php create mode 100644 components/lib/Components/Runner/Installer.php diff --git a/components/lib/Components.php b/components/lib/Components.php index e96b5b21c..9071c58a0 100644 --- a/components/lib/Components.php +++ b/components/lib/Components.php @@ -43,7 +43,15 @@ class Components { $parser = self::_prepareParser($parameters); $config = self::_prepareConfig($parser); - $modules = self::_prepareModules(); + if (isset($parameters['dependencies']) + && $parameters['dependencies'] instanceOf Components_Dependencies) { + $dependencies = $parameters['dependencies']; + } else { + $dependencies = new Components_Dependencies_Injector( + $config + ); + } + $modules = self::_prepareModules($dependencies); $config->handleModules($modules); try { self::_validateArguments($config); @@ -81,9 +89,9 @@ class Components return $config; } - static private function _prepareModules() + static private function _prepareModules(Components_Dependencies $dependencies) { - $modules = new Components_Modules(); + $modules = new Components_Modules($dependencies); $modules->addModulesFromDirectory(dirname(__FILE__) . '/Components/Module'); return $modules; } diff --git a/components/lib/Components/Dependencies.php b/components/lib/Components/Dependencies.php new file mode 100644 index 000000000..a5f3f0091 --- /dev/null +++ b/components/lib/Components/Dependencies.php @@ -0,0 +1,38 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Components + */ + +/** + * The Components_Dependencies:: interface is a central broker for + * providing the dependencies to the different application parts. + * + * Copyright 2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Horde + * @package Components + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Components + */ +interface Components_Dependencies +{ + /** + * Returns the installer for a package. + * + * @return Components_Runner_Installer The installer. + */ + public function getRunnerInstaller(); +} \ No newline at end of file diff --git a/components/lib/Components/Dependencies/Injector.php b/components/lib/Components/Dependencies/Injector.php new file mode 100644 index 000000000..86470188e --- /dev/null +++ b/components/lib/Components/Dependencies/Injector.php @@ -0,0 +1,54 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Components + */ + +/** + * The Components_Dependencies_Injector:: class provides the + * Components dependencies based on the Horde injector. + * + * Copyright 2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Horde + * @package Components + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Components + */ +class Components_Dependencies_Injector +extends Horde_Injector +implements Components_Dependencies +{ + /** + * Constructor. + * + * @param Components_Config $config The configuration. + */ + public function __construct(Components_Config $config) + { + parent::__construct(new Horde_Injector_TopLevel()); + $this->setInstance('Components_Config', $config); + } + + /** + * Returns the installer for a package. + * + * @return Components_Runner_Installer The installer. + */ + public function getRunnerInstaller() + { + return $this->getInstance('Components_Runner_Installer'); + } +} \ No newline at end of file diff --git a/components/lib/Components/Module.php b/components/lib/Components/Module.php index b9ab72802..1f76896a5 100644 --- a/components/lib/Components/Module.php +++ b/components/lib/Components/Module.php @@ -27,13 +27,32 @@ */ interface Components_Module { + /** + * Return the title for the option group representing this module. + * + * @return string The group title. + */ public function getOptionGroupTitle(); + /** + * Return the description for the option group representing this module. + * + * @return string The group description. + */ public function getOptionGroupDescription(); + /** + * Return the options for this module. + * + * @return array The group options. + */ public function getOptionGroupOptions(); + /** + * Determine if this module should act. Run all required actions if it has + * been instructed to do so. + * + * @return NULL + */ public function handle(Components_Config $config); - - public function run(Components_Config $config); } \ No newline at end of file diff --git a/components/lib/Components/Module/Base.php b/components/lib/Components/Module/Base.php new file mode 100644 index 000000000..2c37f4581 --- /dev/null +++ b/components/lib/Components/Module/Base.php @@ -0,0 +1,49 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Components + */ + +/** + * Components_Module_Base:: provides core functionality for the + * different modules. + * + * Copyright 2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Horde + * @package Components + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Components + */ +abstract class Components_Module_Base +implements Components_Module +{ + /** + * The dependency provider. + * + * @var Components_Dependencies + */ + protected $_dependencies; + + /** + * Constructor. + * + * @param Components_Dependencies $dependencies The dependency provider. + */ + public function __construct(Components_Dependencies $dependencies) + { + $this->_dependencies = $dependencies; + } +} \ No newline at end of file diff --git a/components/lib/Components/Module/Installer.php b/components/lib/Components/Module/Installer.php index b7f48a23d..1550f68b4 100644 --- a/components/lib/Components/Module/Installer.php +++ b/components/lib/Components/Module/Installer.php @@ -28,20 +28,33 @@ * @link http://pear.horde.org/index.php?package=Components */ class Components_Module_Installer -implements Components_Module +extends Components_Module_Base { - private $_run; - + /** + * Return the title for the option group representing this module. + * + * @return string The group title. + */ public function getOptionGroupTitle() { return 'Installer'; } + /** + * Return the description for the option group representing this module. + * + * @return string The group description. + */ public function getOptionGroupDescription() { return 'This module installs a Horde element including its dependencies.'; } + /** + * Return the options for this module. + * + * @return array The group options. + */ public function getOptionGroupOptions() { return array( @@ -56,116 +69,17 @@ implements Components_Module ); } + /** + * Determine if this module should act. Run all required actions if it has + * been instructed to do so. + * + * @return NULL + */ public function handle(Components_Config $config) { $options = $config->getOptions(); if (!empty($options['install'])) { - $this->run($config); - } - } - - public function run(Components_Config $config) - { - $options = $config->getOptions(); - $pear = new PEAR(); - $pear->setErrorHandling(PEAR_ERROR_DIE); - - $pearrc = $options['install'] . DIRECTORY_SEPARATOR . '.pearrc'; - $command_config = new PEAR_Command_Config(new PEAR_Frontend_CLI(), new stdClass); - $command_config->doConfigCreate( - 'config-create', array(), array($options['install'], $pearrc) - ); - - $pear_config = new PEAR_Config($pearrc); - $GLOBALS['_PEAR_Config_instance'] = $pear_config; - - $channel = new PEAR_Command_Channels( - new PEAR_Frontend_CLI(), - $pear_config - ); - $channel->doDiscover('channel-discover', array(), array('pear.horde.org')); - $channel->doDiscover('channel-discover', array(), array('pear.phpunit.de')); - - $installer = new PEAR_Command_Install( - new PEAR_Frontend_CLI(), - $pear_config - ); - - $arguments = $config->getArguments(); - $element = basename(realpath($arguments[0])); - $root_path = dirname(realpath($arguments[0])); - - $this->_run = array(); - - $this->_installHordeDependency( - $installer, - $pear_config, - $root_path, - $element - ); - } - - /** - * Install a Horde dependency from the current tree (the framework). - * - * @param PEAR_Command_Install $installer Installs the dependency. - * @param PEAR_Config $pear_config The configuration of the PEAR - * environment in which the - * dependency will be installed. - * @param string $root_path Root path to the Horde framework. - * @param string $dependency Package name of the dependency. - */ - private function _installHordeDependency( - PEAR_Command_Install $installer, - PEAR_Config $pear_config, - $root_path, - $dependency - ) { - $package_file = $root_path . DIRECTORY_SEPARATOR - . $dependency . DIRECTORY_SEPARATOR . 'package.xml'; - - $parser = new PEAR_PackageFile_Parser_v2(); - $parser->setConfig($pear_config); - $pkg = $parser->parse(file_get_contents($package_file), $package_file); - - $dependencies = $pkg->getDeps(); - foreach ($dependencies as $dependency) { - if (isset($dependency['channel']) && $dependency['channel'] != 'pear.horde.org') { - $key = $dependency['channel'] . '/' . $dependency['name']; - if (in_array($key, $this->_run)) { - continue; - } - $installer->doInstall( - 'install', - array( - 'force' => true, - 'channel' => $dependency['channel'], - ), - array($dependency['name']) - ); - $this->_run[] = $key; - } else if (isset($dependency['channel'])) { - $key = $dependency['channel'] . '/' . $dependency['name']; - if (in_array($key, $this->_run)) { - continue; - } - $this->_run[] = $key; - $this->_installHordeDependency( - $installer, - $pear_config, - $root_path, - $dependency['name'] - ); - } + $this->_dependencies->getRunnerInstaller()->run(); } - if (in_array($package_file, $this->_run)) { - return; - } - $installer->doInstall( - 'install', - array('nodeps' => true), - array($package_file) - ); - $this->_run[] = $package_file; } } diff --git a/components/lib/Components/Modules.php b/components/lib/Components/Modules.php index 023446d14..6af57078d 100644 --- a/components/lib/Components/Modules.php +++ b/components/lib/Components/Modules.php @@ -36,10 +36,20 @@ implements Iterator, Countable private $_modules; /** + * The dependency provider. + * + * @var Components_Dependencies + */ + private $_dependencies; + + /** * Constructor. + * + * @param Components_Dependencies $dependencies The dependency provider. */ - public function __construct() + public function __construct(Components_Dependencies $dependencies) { + $this->_dependencies = $dependencies; $this->_modules = array(); } @@ -57,7 +67,9 @@ implements Iterator, Countable foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($module_directory)) as $file) { if ($file->isFile() && preg_match('/.php$/', $file->getFilename())) { $class = $base . preg_replace("/^(.*)\.php/", '\\1', $file->getFilename()); - $this->_modules[$class] = new $class(); + if ($class != 'Components_Module_Base') { + $this->_modules[$class] = new $class($this->_dependencies); + } } } } diff --git a/components/lib/Components/Runner/Installer.php b/components/lib/Components/Runner/Installer.php new file mode 100644 index 000000000..ffcd60ac9 --- /dev/null +++ b/components/lib/Components/Runner/Installer.php @@ -0,0 +1,159 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Components + */ + +/** + * Components_Runner_Installer:: installs a Horde component including its + * dependencies. + * + * Copyright 2010 The Horde Project (http://www.horde.org/) + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * @category Horde + * @package Components + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Components + */ +class Components_Runner_Installer +{ + private $_run; + + /** + * The configuration for the current job. + * + * @param Components_Config + */ + private $_config; + + /** + * Constructor. + * + * @param Components_Config $config The configuration for the current job. + */ + public function __construct(Components_Config $config) + { + $this->_config = $config; + } + + public function run() + { + $options = $this->_config->getOptions(); + $pear = new PEAR(); + $pear->setErrorHandling(PEAR_ERROR_DIE); + + $pearrc = $options['install'] . DIRECTORY_SEPARATOR . '.pearrc'; + $command_config = new PEAR_Command_Config(new PEAR_Frontend_CLI(), new stdClass); + $command_config->doConfigCreate( + 'config-create', array(), array($options['install'], $pearrc) + ); + + $pear_config = new PEAR_Config($pearrc); + $GLOBALS['_PEAR_Config_instance'] = $pear_config; + + $channel = new PEAR_Command_Channels( + new PEAR_Frontend_CLI(), + $pear_config + ); + $channel->doDiscover('channel-discover', array(), array('pear.horde.org')); + $channel->doDiscover('channel-discover', array(), array('pear.phpunit.de')); + + $installer = new PEAR_Command_Install( + new PEAR_Frontend_CLI(), + $pear_config + ); + + $arguments = $this->_config->getArguments(); + $element = basename(realpath($arguments[0])); + $root_path = dirname(realpath($arguments[0])); + + $this->_run = array(); + + $this->_installHordeDependency( + $installer, + $pear_config, + $root_path, + $element + ); + } + + /** + * Install a Horde dependency from the current tree (the framework). + * + * @param PEAR_Command_Install $installer Installs the dependency. + * @param PEAR_Config $pear_config The configuration of the PEAR + * environment in which the + * dependency will be installed. + * @param string $root_path Root path to the Horde framework. + * @param string $dependency Package name of the dependency. + */ + private function _installHordeDependency( + PEAR_Command_Install $installer, + PEAR_Config $pear_config, + $root_path, + $dependency + ) { + $package_file = $root_path . DIRECTORY_SEPARATOR + . $dependency . DIRECTORY_SEPARATOR . 'package.xml'; + if (!file_exists($package_file)) { + $package_file = $root_path . DIRECTORY_SEPARATOR . 'framework' . DIRECTORY_SEPARATOR + . $dependency . DIRECTORY_SEPARATOR . 'package.xml'; + } + + $parser = new PEAR_PackageFile_Parser_v2(); + $parser->setConfig($pear_config); + $pkg = $parser->parse(file_get_contents($package_file), $package_file); + + $dependencies = $pkg->getDeps(); + foreach ($dependencies as $dependency) { + if (isset($dependency['channel']) && $dependency['channel'] != 'pear.horde.org') { + $key = $dependency['channel'] . '/' . $dependency['name']; + if (in_array($key, $this->_run)) { + continue; + } + $installer->doInstall( + 'install', + array( + 'force' => true, + 'channel' => $dependency['channel'], + ), + array($dependency['name']) + ); + $this->_run[] = $key; + } else if (isset($dependency['channel'])) { + $key = $dependency['channel'] . '/' . $dependency['name']; + if (in_array($key, $this->_run)) { + continue; + } + $this->_run[] = $key; + $this->_installHordeDependency( + $installer, + $pear_config, + $root_path, + $dependency['name'] + ); + } + } + if (in_array($package_file, $this->_run)) { + return; + } + $installer->doInstall( + 'install', + array('nodeps' => true), + array($package_file) + ); + $this->_run[] = $package_file; + } +} diff --git a/components/package.xml b/components/package.xml index ad5ebb76b..ab941a051 100644 --- a/components/package.xml +++ b/components/package.xml @@ -24,8 +24,8 @@ jan@horde.org yes - 2010-08-25 - + 2010-09-06 + 0.0.1 0.0.1 @@ -47,50 +47,63 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + @@ -136,19 +149,26 @@ + + + + + + + @@ -165,7 +185,7 @@ alpha alpha - 2010-08-25 + 2010-09-06 LGPL * Initial release -- 2.11.0