PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/config/sfProjectConfiguration.class.php

https://github.com/bheneka/gitta
PHP | 635 lines | 342 code | 79 blank | 214 comment | 24 complexity | ecd6d75cdf2ba8f5472575e612371984 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. /**
  10. * sfProjectConfiguration represents a configuration for a symfony project.
  11. *
  12. * @package symfony
  13. * @subpackage config
  14. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  15. * @version SVN: $Id$
  16. */
  17. class sfProjectConfiguration
  18. {
  19. protected
  20. $rootDir = null,
  21. $symfonyLibDir = null,
  22. $dispatcher = null,
  23. $plugins = array(),
  24. $pluginPaths = array(),
  25. $overriddenPluginPaths = array(),
  26. $pluginConfigurations = array(),
  27. $pluginsLoaded = false;
  28. static protected
  29. $active = null;
  30. /**
  31. * Constructor.
  32. *
  33. * @param string $rootDir The project root directory
  34. * @param sfEventDispatcher $dispatcher The event dispatcher
  35. */
  36. public function __construct($rootDir = null, sfEventDispatcher $dispatcher = null)
  37. {
  38. if (null === self::$active || $this instanceof sfApplicationConfiguration)
  39. {
  40. self::$active = $this;
  41. }
  42. $this->rootDir = null === $rootDir ? self::guessRootDir() : realpath($rootDir);
  43. $this->symfonyLibDir = realpath(dirname(__FILE__).'/..');
  44. $this->dispatcher = null === $dispatcher ? new sfEventDispatcher() : $dispatcher;
  45. ini_set('magic_quotes_runtime', 'off');
  46. sfConfig::set('sf_symfony_lib_dir', $this->symfonyLibDir);
  47. $this->setRootDir($this->rootDir);
  48. // provide forms the dispatcher
  49. sfFormSymfony::setEventDispatcher($this->dispatcher);
  50. $this->setup();
  51. $this->loadPlugins();
  52. $this->setupPlugins();
  53. }
  54. /**
  55. * Setups the current configuration.
  56. *
  57. * Override this method if you want to customize your project configuration.
  58. */
  59. public function setup()
  60. {
  61. }
  62. /**
  63. * Loads the project's plugin configurations.
  64. */
  65. public function loadPlugins()
  66. {
  67. foreach ($this->getPluginPaths() as $path)
  68. {
  69. if (false === $plugin = array_search($path, $this->overriddenPluginPaths))
  70. {
  71. $plugin = basename($path);
  72. }
  73. $class = $plugin.'Configuration';
  74. if (is_readable($file = sprintf('%s/config/%s.class.php', $path, $class)))
  75. {
  76. require_once $file;
  77. $configuration = new $class($this, $path, $plugin);
  78. }
  79. else
  80. {
  81. $configuration = new sfPluginConfigurationGeneric($this, $path, $plugin);
  82. }
  83. $this->pluginConfigurations[$plugin] = $configuration;
  84. }
  85. $this->pluginsLoaded = true;
  86. }
  87. /**
  88. * Sets up plugin configurations.
  89. *
  90. * Override this method if you want to customize plugin configurations.
  91. */
  92. public function setupPlugins()
  93. {
  94. }
  95. /**
  96. * Sets the project root directory.
  97. *
  98. * @param string $rootDir The project root directory
  99. */
  100. public function setRootDir($rootDir)
  101. {
  102. $this->rootDir = $rootDir;
  103. sfConfig::add(array(
  104. 'sf_root_dir' => $rootDir,
  105. // global directory structure
  106. 'sf_apps_dir' => $rootDir.DIRECTORY_SEPARATOR.'apps',
  107. 'sf_lib_dir' => $rootDir.DIRECTORY_SEPARATOR.'lib',
  108. 'sf_log_dir' => $rootDir.DIRECTORY_SEPARATOR.'log',
  109. 'sf_data_dir' => $rootDir.DIRECTORY_SEPARATOR.'data',
  110. 'sf_config_dir' => $rootDir.DIRECTORY_SEPARATOR.'config',
  111. 'sf_test_dir' => $rootDir.DIRECTORY_SEPARATOR.'test',
  112. 'sf_plugins_dir' => $rootDir.DIRECTORY_SEPARATOR.'plugins',
  113. ));
  114. $this->setWebDir($rootDir.DIRECTORY_SEPARATOR.'web');
  115. $this->setCacheDir($rootDir.DIRECTORY_SEPARATOR.'cache');
  116. }
  117. /**
  118. * Returns the project root directory.
  119. *
  120. * @return string The project root directory
  121. */
  122. public function getRootDir()
  123. {
  124. return $this->rootDir;
  125. }
  126. /**
  127. * Sets the cache root directory.
  128. *
  129. * @param string $cacheDir The absolute path to the cache dir.
  130. */
  131. public function setCacheDir($cacheDir)
  132. {
  133. sfConfig::set('sf_cache_dir', $cacheDir);
  134. }
  135. /**
  136. * Sets the log directory.
  137. *
  138. * @param string $logDir The absolute path to the log dir.
  139. */
  140. public function setLogDir($logDir)
  141. {
  142. sfConfig::set('sf_log_dir', $logDir);
  143. }
  144. /**
  145. * Sets the web root directory.
  146. *
  147. * @param string $webDir The absolute path to the web dir.
  148. */
  149. public function setWebDir($webDir)
  150. {
  151. sfConfig::add(array(
  152. 'sf_web_dir' => $webDir,
  153. 'sf_upload_dir' => $webDir.DIRECTORY_SEPARATOR.'uploads',
  154. ));
  155. }
  156. /**
  157. * Gets directories where model classes are stored. The order of returned paths is lowest precedence
  158. * to highest precedence.
  159. *
  160. * @return array An array of directories
  161. */
  162. public function getModelDirs()
  163. {
  164. return array_merge(
  165. $this->getPluginSubPaths('/lib/model'), // plugins
  166. array(sfConfig::get('sf_lib_dir').'/model') // project
  167. );
  168. }
  169. /**
  170. * Gets directories where template files are stored for a generator class and a specific theme.
  171. *
  172. * @param string $class The generator class name
  173. * @param string $theme The theme name
  174. *
  175. * @return array An array of directories
  176. */
  177. public function getGeneratorTemplateDirs($class, $theme)
  178. {
  179. return array_merge(
  180. array(sfConfig::get('sf_data_dir').'/generator/'.$class.'/'.$theme.'/template'), // project
  181. $this->getPluginSubPaths('/data/generator/'.$class.'/'.$theme.'/template'), // plugins
  182. array(sfConfig::get('sf_data_dir').'/generator/'.$class.'/default/template'), // project (default theme)
  183. $this->getPluginSubPaths('/data/generator/'.$class.'/default/template') // plugins (default theme)
  184. );
  185. }
  186. /**
  187. * Gets directories where the skeleton is stored for a generator class and a specific theme.
  188. *
  189. * @param string $class The generator class name
  190. * @param string $theme The theme name
  191. *
  192. * @return array An array of directories
  193. */
  194. public function getGeneratorSkeletonDirs($class, $theme)
  195. {
  196. return array_merge(
  197. array(sfConfig::get('sf_data_dir').'/generator/'.$class.'/'.$theme.'/skeleton'), // project
  198. $this->getPluginSubPaths('/data/generator/'.$class.'/'.$theme.'/skeleton'), // plugins
  199. array(sfConfig::get('sf_data_dir').'/generator/'.$class.'/default/skeleton'), // project (default theme)
  200. $this->getPluginSubPaths('/data/generator/'.$class.'/default/skeleton') // plugins (default theme)
  201. );
  202. }
  203. /**
  204. * Gets the template to use for a generator class.
  205. *
  206. * @param string $class The generator class name
  207. * @param string $theme The theme name
  208. * @param string $path The template path
  209. *
  210. * @return string A template path
  211. *
  212. * @throws sfException
  213. */
  214. public function getGeneratorTemplate($class, $theme, $path)
  215. {
  216. $dirs = $this->getGeneratorTemplateDirs($class, $theme);
  217. foreach ($dirs as $dir)
  218. {
  219. if (is_readable($dir.'/'.$path))
  220. {
  221. return $dir.'/'.$path;
  222. }
  223. }
  224. throw new sfException(sprintf('Unable to load "%s" generator template in: %s.', $path, implode(', ', $dirs)));
  225. }
  226. /**
  227. * Gets the configuration file paths for a given relative configuration path.
  228. *
  229. * @param string $configPath The configuration path
  230. *
  231. * @return array An array of paths
  232. */
  233. public function getConfigPaths($configPath)
  234. {
  235. $globalConfigPath = basename(dirname($configPath)).'/'.basename($configPath);
  236. $files = array(
  237. $this->getSymfonyLibDir().'/config/'.$globalConfigPath, // symfony
  238. );
  239. foreach ($this->getPluginPaths() as $path)
  240. {
  241. if (is_file($file = $path.'/'.$globalConfigPath))
  242. {
  243. $files[] = $file; // plugins
  244. }
  245. }
  246. $files = array_merge($files, array(
  247. $this->getRootDir().'/'.$globalConfigPath, // project
  248. $this->getRootDir().'/'.$configPath, // project
  249. ));
  250. foreach ($this->getPluginPaths() as $path)
  251. {
  252. if (is_file($file = $path.'/'.$configPath))
  253. {
  254. $files[] = $file; // plugins
  255. }
  256. }
  257. $configs = array();
  258. foreach (array_unique($files) as $file)
  259. {
  260. if (is_readable($file))
  261. {
  262. $configs[] = $file;
  263. }
  264. }
  265. return $configs;
  266. }
  267. /**
  268. * Sets the enabled plugins.
  269. *
  270. * @param array $plugins An array of plugin names
  271. *
  272. * @throws LogicException If plugins have already been loaded
  273. */
  274. public function setPlugins(array $plugins)
  275. {
  276. if ($this->pluginsLoaded)
  277. {
  278. throw new LogicException('Plugins have already been loaded.');
  279. }
  280. $this->plugins = $plugins;
  281. $this->pluginPaths = array();
  282. }
  283. /**
  284. * Enables a plugin or a list of plugins.
  285. *
  286. * @param array|string $plugins A plugin name or a plugin list
  287. */
  288. public function enablePlugins($plugins)
  289. {
  290. if (!is_array($plugins))
  291. {
  292. if (func_num_args() > 1)
  293. {
  294. $plugins = func_get_args();
  295. }
  296. else
  297. {
  298. $plugins = array($plugins);
  299. }
  300. }
  301. $this->setPlugins(array_merge($this->plugins, $plugins));
  302. }
  303. /**
  304. * Disables a plugin.
  305. *
  306. * @param array|string $plugins A plugin name or a plugin list
  307. *
  308. * @throws LogicException If plugins have already been loaded
  309. */
  310. public function disablePlugins($plugins)
  311. {
  312. if ($this->pluginsLoaded)
  313. {
  314. throw new LogicException('Plugins have already been loaded.');
  315. }
  316. if (!is_array($plugins))
  317. {
  318. $plugins = array($plugins);
  319. }
  320. foreach ($plugins as $plugin)
  321. {
  322. if (false !== $pos = array_search($plugin, $this->plugins))
  323. {
  324. unset($this->plugins[$pos]);
  325. }
  326. else
  327. {
  328. throw new InvalidArgumentException(sprintf('The plugin "%s" does not exist.', $plugin));
  329. }
  330. }
  331. $this->pluginPaths = array();
  332. }
  333. /**
  334. * Enabled all installed plugins except the one given as argument.
  335. *
  336. * @param array|string $plugins A plugin name or a plugin list
  337. *
  338. * @throws LogicException If plugins have already been loaded
  339. */
  340. public function enableAllPluginsExcept($plugins = array())
  341. {
  342. if ($this->pluginsLoaded)
  343. {
  344. throw new LogicException('Plugins have already been loaded.');
  345. }
  346. $this->plugins = array_keys($this->getAllPluginPaths());
  347. sort($this->plugins);
  348. $this->disablePlugins($plugins);
  349. }
  350. /**
  351. * Gets the list of enabled plugins.
  352. *
  353. * @return array An array of enabled plugins
  354. */
  355. public function getPlugins()
  356. {
  357. return $this->plugins;
  358. }
  359. /**
  360. * Gets the paths plugin sub-directories, minding overloaded plugins.
  361. *
  362. * @param string $subPath The subdirectory to look for
  363. *
  364. * @return array The plugin paths.
  365. */
  366. public function getPluginSubPaths($subPath = '')
  367. {
  368. if (array_key_exists($subPath, $this->pluginPaths))
  369. {
  370. return $this->pluginPaths[$subPath];
  371. }
  372. $this->pluginPaths[$subPath] = array();
  373. $pluginPaths = $this->getPluginPaths();
  374. foreach ($pluginPaths as $pluginPath)
  375. {
  376. if (is_dir($pluginPath.$subPath))
  377. {
  378. $this->pluginPaths[$subPath][] = $pluginPath.$subPath;
  379. }
  380. }
  381. return $this->pluginPaths[$subPath];
  382. }
  383. /**
  384. * Gets the paths to plugins root directories, minding overloaded plugins.
  385. *
  386. * @return array The plugin root paths.
  387. *
  388. * @throws InvalidArgumentException If an enabled plugin does not exist
  389. */
  390. public function getPluginPaths()
  391. {
  392. if (!isset($this->pluginPaths['']))
  393. {
  394. $pluginPaths = $this->getAllPluginPaths();
  395. $this->pluginPaths[''] = array();
  396. foreach ($this->getPlugins() as $plugin)
  397. {
  398. if (isset($pluginPaths[$plugin]))
  399. {
  400. $this->pluginPaths[''][] = $pluginPaths[$plugin];
  401. }
  402. else
  403. {
  404. throw new InvalidArgumentException(sprintf('The plugin "%s" does not exist.', $plugin));
  405. }
  406. }
  407. }
  408. return $this->pluginPaths[''];
  409. }
  410. /**
  411. * Returns an array of paths for all available plugins.
  412. *
  413. * @return array
  414. */
  415. public function getAllPluginPaths()
  416. {
  417. $pluginPaths = array();
  418. // search for *Plugin directories representing plugins
  419. // follow links and do not recurse. No need to exclude VC because they do not end with *Plugin
  420. $finder = sfFinder::type('dir')->maxdepth(0)->ignore_version_control(false)->follow_link()->name('*Plugin');
  421. $dirs = array(
  422. $this->getSymfonyLibDir().'/plugins',
  423. sfConfig::get('sf_plugins_dir'),
  424. );
  425. foreach ($finder->in($dirs) as $path)
  426. {
  427. $pluginPaths[basename($path)] = $path;
  428. }
  429. foreach ($this->overriddenPluginPaths as $plugin => $path)
  430. {
  431. $pluginPaths[$plugin] = $path;
  432. }
  433. return $pluginPaths;
  434. }
  435. /**
  436. * Manually sets the location of a particular plugin.
  437. *
  438. * This method can be used to ease functional testing of plugins. It is not
  439. * intended to support sharing plugins between projects, as many plugins
  440. * save project specific code (to /lib/form/base, for example).
  441. *
  442. * @param string $plugin
  443. * @param string $path
  444. */
  445. public function setPluginPath($plugin, $path)
  446. {
  447. $this->overriddenPluginPaths[$plugin] = realpath($path);
  448. }
  449. /**
  450. * Returns the configuration for the requested plugin.
  451. *
  452. * @param string $name
  453. *
  454. * @return sfPluginConfiguration
  455. */
  456. public function getPluginConfiguration($name)
  457. {
  458. if (!isset($this->pluginConfigurations[$name]))
  459. {
  460. throw new InvalidArgumentException(sprintf('There is no configuration object for the "%s" object.', $name));
  461. }
  462. return $this->pluginConfigurations[$name];
  463. }
  464. /**
  465. * Returns the event dispatcher.
  466. *
  467. * @return sfEventDispatcher A sfEventDispatcher instance
  468. */
  469. public function getEventDispatcher()
  470. {
  471. return $this->dispatcher;
  472. }
  473. /**
  474. * Returns the symfony lib directory.
  475. *
  476. * @return string The symfony lib directory
  477. */
  478. public function getSymfonyLibDir()
  479. {
  480. return $this->symfonyLibDir;
  481. }
  482. /**
  483. * Returns the active configuration.
  484. *
  485. * @return sfProjectConfiguration The current sfProjectConfiguration instance
  486. */
  487. static public function getActive()
  488. {
  489. if (!self::hasActive())
  490. {
  491. throw new RuntimeException('There is no active configuration.');
  492. }
  493. return self::$active;
  494. }
  495. /**
  496. * Returns true if these is an active configuration.
  497. *
  498. * @return boolean
  499. */
  500. static public function hasActive()
  501. {
  502. return null !== self::$active;
  503. }
  504. /**
  505. * Guesses the project root directory.
  506. *
  507. * @return string The project root directory
  508. */
  509. static public function guessRootDir()
  510. {
  511. $r = new ReflectionClass('ProjectConfiguration');
  512. return realpath(dirname($r->getFileName()).'/..');
  513. }
  514. /**
  515. * Returns a sfApplicationConfiguration configuration for a given application.
  516. *
  517. * @param string $application An application name
  518. * @param string $environment The environment name
  519. * @param Boolean $debug true to enable debug mode
  520. * @param string $rootDir The project root directory
  521. * @param sfEventDispatcher $dispatcher An event dispatcher
  522. *
  523. * @return sfApplicationConfiguration A sfApplicationConfiguration instance
  524. */
  525. static public function getApplicationConfiguration($application, $environment, $debug, $rootDir = null, sfEventDispatcher $dispatcher = null)
  526. {
  527. $class = $application.'Configuration';
  528. if (null === $rootDir)
  529. {
  530. $rootDir = self::guessRootDir();
  531. }
  532. if (!file_exists($file = $rootDir.'/apps/'.$application.'/config/'.$class.'.class.php'))
  533. {
  534. throw new InvalidArgumentException(sprintf('The application "%s" does not exist.', $application));
  535. }
  536. require_once $file;
  537. return new $class($environment, $debug, $rootDir, $dispatcher);
  538. }
  539. /**
  540. * Calls methods defined via sfEventDispatcher.
  541. *
  542. * @param string $method The method name
  543. * @param array $arguments The method arguments
  544. *
  545. * @return mixed The returned value of the called method
  546. */
  547. public function __call($method, $arguments)
  548. {
  549. $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'configuration.method_not_found', array('method' => $method, 'arguments' => $arguments)));
  550. if (!$event->isProcessed())
  551. {
  552. throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method));
  553. }
  554. return $event->getReturnValue();
  555. }
  556. }