PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/monica/vendor/zendframework/zendframework/library/Zend/ModuleManager/Listener/ConfigListener.php

https://bitbucket.org/alexandretaz/maniac_divers
PHP | 383 lines | 195 code | 45 blank | 143 comment | 17 complexity | eeb6af34bd72b2ca55588dda23cdd4ef MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\ModuleManager\Listener;
  10. use Traversable;
  11. use Zend\Config\Config;
  12. use Zend\Config\Factory as ConfigFactory;
  13. use Zend\EventManager\EventManagerInterface;
  14. use Zend\EventManager\ListenerAggregateInterface;
  15. use Zend\ModuleManager\Feature\ConfigProviderInterface;
  16. use Zend\ModuleManager\ModuleEvent;
  17. use Zend\Stdlib\ArrayUtils;
  18. use Zend\Stdlib\Glob;
  19. /**
  20. * Config listener
  21. */
  22. class ConfigListener extends AbstractListener implements
  23. ConfigMergerInterface,
  24. ListenerAggregateInterface
  25. {
  26. const STATIC_PATH = 'static_path';
  27. const GLOB_PATH = 'glob_path';
  28. /**
  29. * @var array
  30. */
  31. protected $listeners = array();
  32. /**
  33. * @var array
  34. */
  35. protected $configs = array();
  36. /**
  37. * @var array
  38. */
  39. protected $mergedConfig = array();
  40. /**
  41. * @var Config
  42. */
  43. protected $mergedConfigObject;
  44. /**
  45. * @var bool
  46. */
  47. protected $skipConfig = false;
  48. /**
  49. * @var array
  50. */
  51. protected $paths = array();
  52. /**
  53. * __construct
  54. *
  55. * @param ListenerOptions $options
  56. */
  57. public function __construct(ListenerOptions $options = null)
  58. {
  59. parent::__construct($options);
  60. if ($this->hasCachedConfig()) {
  61. $this->skipConfig = true;
  62. $this->setMergedConfig($this->getCachedConfig());
  63. } else {
  64. $this->addConfigGlobPaths($this->getOptions()->getConfigGlobPaths());
  65. $this->addConfigStaticPaths($this->getOptions()->getConfigStaticPaths());
  66. }
  67. }
  68. /**
  69. * Attach one or more listeners
  70. *
  71. * @param EventManagerInterface $events
  72. * @return ConfigListener
  73. */
  74. public function attach(EventManagerInterface $events)
  75. {
  76. $this->listeners[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULES, array($this, 'onloadModulesPre'), 1000);
  77. if ($this->skipConfig) {
  78. // We already have the config from cache, no need to collect or merge.
  79. return $this;
  80. }
  81. $this->listeners[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULE, array($this, 'onLoadModule'));
  82. $this->listeners[] = $events->attach(ModuleEvent::EVENT_LOAD_MODULES, array($this, 'onLoadModulesPost'), -1000);
  83. return $this;
  84. }
  85. /**
  86. * Pass self to the ModuleEvent object early so everyone has access.
  87. *
  88. * @param ModuleEvent $e
  89. * @return ConfigListener
  90. */
  91. public function onloadModulesPre(ModuleEvent $e)
  92. {
  93. $e->setConfigListener($this);
  94. return $this;
  95. }
  96. /**
  97. * Merge the config for each module
  98. *
  99. * @param ModuleEvent $e
  100. * @return ConfigListener
  101. */
  102. public function onLoadModule(ModuleEvent $e)
  103. {
  104. $module = $e->getModule();
  105. if (!$module instanceof ConfigProviderInterface
  106. && !is_callable(array($module, 'getConfig'))
  107. ) {
  108. return $this;
  109. }
  110. $config = $module->getConfig();
  111. $this->addConfig($e->getModuleName(), $config);
  112. return $this;
  113. }
  114. /**
  115. * Merge all config files matched by the given glob()s
  116. *
  117. * This is only attached if config is not cached.
  118. *
  119. * @param ModuleEvent $e
  120. * @return ConfigListener
  121. */
  122. public function onLoadModulesPost(ModuleEvent $e)
  123. {
  124. // Load the config files
  125. foreach ($this->paths as $path) {
  126. $this->addConfigByPath($path['path'], $path['type']);
  127. }
  128. // Merge all of the collected configs
  129. $this->mergedConfig = $this->getOptions()->getExtraConfig() ?: array();
  130. foreach ($this->configs as $config) {
  131. $this->mergedConfig = ArrayUtils::merge($this->mergedConfig, $config);
  132. }
  133. // If enabled, update the config cache
  134. if (
  135. $this->getOptions()->getConfigCacheEnabled()
  136. && false === $this->skipConfig
  137. ) {
  138. $configFile = $this->getOptions()->getConfigCacheFile();
  139. $this->writeArrayToFile($configFile, $this->getMergedConfig(false));
  140. }
  141. return $this;
  142. }
  143. /**
  144. * Detach all previously attached listeners
  145. *
  146. * @param EventManagerInterface $events
  147. * @return ConfigListener
  148. */
  149. public function detach(EventManagerInterface $events)
  150. {
  151. foreach ($this->listeners as $key => $listener) {
  152. $events->detach($listener);
  153. unset($this->listeners[$key]);
  154. }
  155. $this->listeners = array();
  156. return $this;
  157. }
  158. /**
  159. * getMergedConfig
  160. *
  161. * @param bool $returnConfigAsObject
  162. * @return mixed
  163. */
  164. public function getMergedConfig($returnConfigAsObject = true)
  165. {
  166. if ($returnConfigAsObject === true) {
  167. if ($this->mergedConfigObject === null) {
  168. $this->mergedConfigObject = new Config($this->mergedConfig);
  169. }
  170. return $this->mergedConfigObject;
  171. }
  172. return $this->mergedConfig;
  173. }
  174. /**
  175. * setMergedConfig
  176. *
  177. * @param array $config
  178. * @return ConfigListener
  179. */
  180. public function setMergedConfig(array $config)
  181. {
  182. $this->mergedConfig = $config;
  183. $this->mergedConfigObject = null;
  184. return $this;
  185. }
  186. /**
  187. * Add an array of glob paths of config files to merge after loading modules
  188. *
  189. * @param array|Traversable $globPaths
  190. * @return ConfigListener
  191. */
  192. public function addConfigGlobPaths($globPaths)
  193. {
  194. $this->addConfigPaths($globPaths, self::GLOB_PATH);
  195. return $this;
  196. }
  197. /**
  198. * Add a glob path of config files to merge after loading modules
  199. *
  200. * @param string $globPath
  201. * @return ConfigListener
  202. */
  203. public function addConfigGlobPath($globPath)
  204. {
  205. $this->addConfigPath($globPath, self::GLOB_PATH);
  206. return $this;
  207. }
  208. /**
  209. * Add an array of static paths of config files to merge after loading modules
  210. *
  211. * @param array|Traversable $staticPaths
  212. * @return ConfigListener
  213. */
  214. public function addConfigStaticPaths($staticPaths)
  215. {
  216. $this->addConfigPaths($staticPaths, self::STATIC_PATH);
  217. return $this;
  218. }
  219. /**
  220. * Add a static path of config files to merge after loading modules
  221. *
  222. * @param string $staticPath
  223. * @return ConfigListener
  224. */
  225. public function addConfigStaticPath($staticPath)
  226. {
  227. $this->addConfigPath($staticPath, self::STATIC_PATH);
  228. return $this;
  229. }
  230. /**
  231. * Add an array of paths of config files to merge after loading modules
  232. *
  233. * @param Traversable|array $paths
  234. * @param string $type
  235. * @throws Exception\InvalidArgumentException
  236. * @return ConfigListener
  237. */
  238. protected function addConfigPaths($paths, $type)
  239. {
  240. if ($paths instanceof Traversable) {
  241. $paths = ArrayUtils::iteratorToArray($paths);
  242. }
  243. if (!is_array($paths)) {
  244. throw new Exception\InvalidArgumentException(
  245. sprintf('Argument passed to %::%s() must be an array, '
  246. . 'implement the \Traversable interface, or be an '
  247. . 'instance of Zend\Config\Config. %s given.',
  248. __CLASS__, __METHOD__, gettype($paths))
  249. );
  250. }
  251. foreach ($paths as $path) {
  252. $this->addConfigPath($path, $type);
  253. }
  254. }
  255. /**
  256. * Add a path of config files to load and merge after loading modules
  257. *
  258. * @param string $path
  259. * @param string $type
  260. * @throws Exception\InvalidArgumentException
  261. * @return ConfigListener
  262. */
  263. protected function addConfigPath($path, $type)
  264. {
  265. if (!is_string($path)) {
  266. throw new Exception\InvalidArgumentException(
  267. sprintf('Parameter to %s::%s() must be a string; %s given.',
  268. __CLASS__, __METHOD__, gettype($path))
  269. );
  270. }
  271. $this->paths[] = array('type' => $type, 'path' => $path);
  272. return $this;
  273. }
  274. /**
  275. * @param string $key
  276. * @param array|Traversable $config
  277. * @throws Exception\InvalidArgumentException
  278. * @return ConfigListener
  279. */
  280. protected function addConfig($key, $config)
  281. {
  282. if ($config instanceof Traversable) {
  283. $config = ArrayUtils::iteratorToArray($config);
  284. }
  285. if (!is_array($config)) {
  286. throw new Exception\InvalidArgumentException(
  287. sprintf('Config being merged must be an array, '
  288. . 'implement the \Traversable interface, or be an '
  289. . 'instance of Zend\Config\Config. %s given.', gettype($config))
  290. );
  291. }
  292. $this->configs[$key] = $config;
  293. return $this;
  294. }
  295. /**
  296. * Given a path (glob or static), fetch the config and add it to the array
  297. * of configs to merge.
  298. *
  299. * @param string $path
  300. * @param string $type
  301. * @return ConfigListener
  302. */
  303. protected function addConfigByPath($path, $type)
  304. {
  305. switch ($type) {
  306. case self::STATIC_PATH:
  307. $this->addConfig($path, ConfigFactory::fromFile($path));
  308. break;
  309. case self::GLOB_PATH:
  310. // We want to keep track of where each value came from so we don't
  311. // use ConfigFactory::fromFiles() since it does merging internally.
  312. foreach (Glob::glob($path, Glob::GLOB_BRACE) as $file) {
  313. $this->addConfig($file, ConfigFactory::fromFile($file));
  314. }
  315. break;
  316. }
  317. return $this;
  318. }
  319. /**
  320. * @return bool
  321. */
  322. protected function hasCachedConfig()
  323. {
  324. if (($this->getOptions()->getConfigCacheEnabled())
  325. && (file_exists($this->getOptions()->getConfigCacheFile()))
  326. ) {
  327. return true;
  328. }
  329. return false;
  330. }
  331. /**
  332. * @return mixed
  333. */
  334. protected function getCachedConfig()
  335. {
  336. return include $this->getOptions()->getConfigCacheFile();
  337. }
  338. }