Source of file ConfigListener.php
Size: 10,851 Bytes - Last Modified: 2014-03-12T23:21:18+01:00
/home/theseer/Downloads/ZendFramework-2.3.0/library/Zend/ModuleManager/Listener/ConfigListener.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 | <?php /** * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace Zend\ModuleManager\Listener; use Traversable; use Zend\Config\Config; use Zend\Config\Factory as ConfigFactory; use Zend\EventManager\EventManagerInterface; use Zend\EventManager\ListenerAggregateInterface; use Zend\ModuleManager\Feature\ConfigProviderInterface; use Zend\ModuleManager\ModuleEvent; use Zend\Stdlib\ArrayUtils; use Zend\Stdlib\Glob; /** * Config listener */ class ConfigListener extends AbstractListener implements ConfigMergerInterface, ListenerAggregateInterface { const STATIC_PATH = 'static_path'; const GLOB_PATH = 'glob_path'; /** * @var array */ protected $callbacks = array(); /** * @var array */ protected $configs = array(); /** * @var array */ protected $mergedConfig = array(); /** * @var Config */ protected $mergedConfigObject; /** * @var bool */ protected $skipConfig = false; /** * @var array */ protected $paths = array(); /** * __construct * * @param ListenerOptions $options */ public function __construct(ListenerOptions $options = null) { parent::__construct($options); if ($this->hasCachedConfig()) { $this->skipConfig = true; $this->setMergedConfig($this->getCachedConfig()); } else { $this->addConfigGlobPaths($this->getOptions()->getConfigGlobPaths()); $this->addConfigStaticPaths($this->getOptions()->getConfigStaticPaths()); } } /** * {@inheritDoc} */ public function attach(EventManagerInterface $events) { $this->callbacks[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULES, array($this, 'onloadModulesPre'), 1000); if ($this->skipConfig) { // We already have the config from cache, no need to collect or merge. return $this; } $this->callbacks[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULE, array($this, 'onLoadModule')); $this->callbacks[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULES, array($this, 'onLoadModules'), -1000); $this->callbacks[] = $events->attach(ModuleEvent::EVENT_MERGE_CONFIG, array($this, 'onMergeConfig'), 1000); return $this; } /** * Pass self to the ModuleEvent object early so everyone has access. * * @param ModuleEvent $e * @return ConfigListener */ public function onloadModulesPre(ModuleEvent $e) { $e->setConfigListener($this); return $this; } /** * Merge the config for each module * * @param ModuleEvent $e * @return ConfigListener */ public function onLoadModule(ModuleEvent $e) { $module = $e->getModule(); if (!$module instanceof ConfigProviderInterface && !is_callable(array($module, 'getConfig')) ) { return $this; } $config = $module->getConfig(); $this->addConfig($e->getModuleName(), $config); return $this; } /** * Merge all config files matched by the given glob()s * * This is only attached if config is not cached. * * @param ModuleEvent $e * @return ConfigListener */ public function onMergeConfig(ModuleEvent $e) { // Load the config files foreach ($this->paths as $path) { $this->addConfigByPath($path['path'], $path['type']); } // Merge all of the collected configs $this->mergedConfig = $this->getOptions()->getExtraConfig() ?: array(); foreach ($this->configs as $config) { $this->mergedConfig = ArrayUtils::merge($this->mergedConfig, $config); } return $this; } /** * Optionally cache merged config * * This is only attached if config is not cached. * * @param ModuleEvent $e * @return ConfigListener */ public function onLoadModules(ModuleEvent $e) { // Trigger MERGE_CONFIG event. This is a hook to allow the merged application config to be // modified before it is cached (In particular, allows the removal of config keys) $e->getTarget()->getEventManager()->trigger(ModuleEvent::EVENT_MERGE_CONFIG, $e->getTarget(), $e); // If enabled, update the config cache if ( $this->getOptions()->getConfigCacheEnabled() && false === $this->skipConfig ) { $configFile = $this->getOptions()->getConfigCacheFile(); $this->writeArrayToFile($configFile, $this->getMergedConfig(false)); } return $this; } /** * {@inheritDoc} */ public function detach(EventManagerInterface $events) { foreach ($this->callbacks as $index => $callback) { if ($events->detach($callback)) { unset($this->callbacks[$index]); } } } /** * getMergedConfig * * @param bool $returnConfigAsObject * @return mixed */ public function getMergedConfig($returnConfigAsObject = true) { if ($returnConfigAsObject === true) { if ($this->mergedConfigObject === null) { $this->mergedConfigObject = new Config($this->mergedConfig); } return $this->mergedConfigObject; } return $this->mergedConfig; } /** * setMergedConfig * * @param array $config * @return ConfigListener */ public function setMergedConfig(array $config) { $this->mergedConfig = $config; $this->mergedConfigObject = null; return $this; } /** * Add an array of glob paths of config files to merge after loading modules * * @param array|Traversable $globPaths * @return ConfigListener */ public function addConfigGlobPaths($globPaths) { $this->addConfigPaths($globPaths, self::GLOB_PATH); return $this; } /** * Add a glob path of config files to merge after loading modules * * @param string $globPath * @return ConfigListener */ public function addConfigGlobPath($globPath) { $this->addConfigPath($globPath, self::GLOB_PATH); return $this; } /** * Add an array of static paths of config files to merge after loading modules * * @param array|Traversable $staticPaths * @return ConfigListener */ public function addConfigStaticPaths($staticPaths) { $this->addConfigPaths($staticPaths, self::STATIC_PATH); return $this; } /** * Add a static path of config files to merge after loading modules * * @param string $staticPath * @return ConfigListener */ public function addConfigStaticPath($staticPath) { $this->addConfigPath($staticPath, self::STATIC_PATH); return $this; } /** * Add an array of paths of config files to merge after loading modules * * @param Traversable|array $paths * @param string $type * @throws Exception\InvalidArgumentException * @return ConfigListener */ protected function addConfigPaths($paths, $type) { if ($paths instanceof Traversable) { $paths = ArrayUtils::iteratorToArray($paths); } if (!is_array($paths)) { throw new Exception\InvalidArgumentException( sprintf('Argument passed to %::%s() must be an array, ' . 'implement the Traversable interface, or be an ' . 'instance of Zend\Config\Config. %s given.', __CLASS__, __METHOD__, gettype($paths)) ); } foreach ($paths as $path) { $this->addConfigPath($path, $type); } } /** * Add a path of config files to load and merge after loading modules * * @param string $path * @param string $type * @throws Exception\InvalidArgumentException * @return ConfigListener */ protected function addConfigPath($path, $type) { if (!is_string($path)) { throw new Exception\InvalidArgumentException( sprintf('Parameter to %s::%s() must be a string; %s given.', __CLASS__, __METHOD__, gettype($path)) ); } $this->paths[] = array('type' => $type, 'path' => $path); return $this; } /** * @param string $key * @param array|Traversable $config * @throws Exception\InvalidArgumentException * @return ConfigListener */ protected function addConfig($key, $config) { if ($config instanceof Traversable) { $config = ArrayUtils::iteratorToArray($config); } if (!is_array($config)) { throw new Exception\InvalidArgumentException( sprintf('Config being merged must be an array, ' . 'implement the Traversable interface, or be an ' . 'instance of Zend\Config\Config. %s given.', gettype($config)) ); } $this->configs[$key] = $config; return $this; } /** * Given a path (glob or static), fetch the config and add it to the array * of configs to merge. * * @param string $path * @param string $type * @return ConfigListener */ protected function addConfigByPath($path, $type) { switch ($type) { case self::STATIC_PATH: $this->addConfig($path, ConfigFactory::fromFile($path)); break; case self::GLOB_PATH: // We want to keep track of where each value came from so we don't // use ConfigFactory::fromFiles() since it does merging internally. foreach (Glob::glob($path, Glob::GLOB_BRACE) as $file) { $this->addConfig($file, ConfigFactory::fromFile($file)); } break; } return $this; } /** * @return bool */ protected function hasCachedConfig() { if (($this->getOptions()->getConfigCacheEnabled()) && (file_exists($this->getOptions()->getConfigCacheFile())) ) { return true; } return false; } /** * @return mixed */ protected function getCachedConfig() { return include $this->getOptions()->getConfigCacheFile(); } } |