PageRenderTime 43ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/www/libs/Zend/ModuleManager/Listener/ConfigListener.php

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