1. sfContext.class.php
  2. /** * sfContext provides information about the current application context, such as * the module and action names and the module directory. References to the * main symfony instances are also provided. * * @package symfony * @subpackage util * @author Fabien Potencier * @author Sean Kerr * @version SVN: $Id: sfContext.class.php 23922 2009-11-14 14:58:38Z fabien $ */
  3. class sfContext implements ArrayAccess
  4. {
  5. protected
  6. $dispatcher = null,
  7. $configuration = null,
  8. $mailerConfiguration = array(),
  9. $factories = array();
  10. protected static
  11. $instances = array(),
  12. $current = 'default';
  13. /**
  14. * Creates a new context instance.
  15. *
  16. * @param sfApplicationConfiguration $configuration An sfApplicationConfiguration instance
  17. * @param string $name A name for this context (application name by default)
  18. * @param string $class The context class to use (sfContext by default)
  19. *
  20. * @return sfContext An sfContext instance
  21. */
  22. static public function createInstance(sfApplicationConfiguration $configuration, $name = null, $class = __CLASS__)
  23. {
  24. if (null === $name)
  25. {
  26. $name = $configuration->getApplication();
  27. }
  28. self::$current = $name;
  29. self::$instances[$name] = new $class();
  30. if (!self::$instances[$name] instanceof sfContext)
  31. {
  32. throw new sfFactoryException(sprintf('Class "%s" is not of the type sfContext.', $class));
  33. }
  34. self::$instances[$name]->initialize($configuration);
  35. return self::$instances[$name];
  36. }
  37. /**
  38. * Initializes the current sfContext instance.
  39. *
  40. * @param sfApplicationConfiguration $configuration An sfApplicationConfiguration instance
  41. */
  42. public function initialize(sfApplicationConfiguration $configuration)
  43. {
  44. $this->configuration = $configuration;
  45. $this->dispatcher = $configuration->getEventDispatcher();
  46. try
  47. {
  48. $this->loadFactories();
  49. }
  50. catch (sfException $e)
  51. {
  52. $e->printStackTrace();
  53. }
  54. catch (Exception $e)
  55. {
  56. sfException::createFromException($e)->printStackTrace();
  57. }
  58. $this->dispatcher->connect('template.filter_parameters', array($this, 'filterTemplateParameters'));
  59. // register our shutdown function
  60. register_shutdown_function(array($this, 'shutdown'));
  61. }
  62. /**
  63. * Retrieves the singleton instance of this class.
  64. *
  65. * @param string $name The name of the sfContext to retrieve.
  66. * @param string $class The context class to use (sfContext by default)
  67. *
  68. * @return sfContext An sfContext implementation instance.
  69. */
  70. static public function getInstance($name = null, $class = __CLASS__)
  71. {
  72. if (null === $name)
  73. {
  74. $name = self::$current;
  75. }
  76. if (!isset(self::$instances[$name]))
  77. {
  78. throw new sfException(sprintf('The "%s" context does not exist.', $name));
  79. }
  80. return self::$instances[$name];
  81. }
  82. /**
  83. * Checks to see if there has been a context created
  84. *
  85. * @param string $name The name of the sfContext to check for
  86. *
  87. * @return bool true is instanced, otherwise false
  88. */
  89. public static function hasInstance($name = null)
  90. {
  91. if (null === $name)
  92. {
  93. $name = self::$current;
  94. }
  95. return isset(self::$instances[$name]);
  96. }
  97. /**
  98. * Loads the symfony factories.
  99. */
  100. public function loadFactories()
  101. {
  102. if (sfConfig::get('sf_use_database'))
  103. {
  104. // setup our database connections
  105. $this->factories['databaseManager'] = new sfDatabaseManager($this->configuration, array('auto_shutdown' => false));
  106. }
  107. // create a new action stack
  108. $this->factories['actionStack'] = new sfActionStack();
  109. if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled'))
  110. {
  111. $timer = sfTimerManager::getTimer('Factories');
  112. }
  113. // include the factories configuration
  114. require($this->configuration->getConfigCache()->checkConfig('config/factories.yml'));
  115. $this->dispatcher->notify(new sfEvent($this, 'context.load_factories'));
  116. if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled'))
  117. {
  118. $timer->addTime();
  119. }
  120. }
  121. /**
  122. * Dispatches the current request.
  123. */
  124. public function dispatch()
  125. {
  126. $this->getController()->dispatch();
  127. }
  128. /**
  129. * Sets the current context to something else
  130. *
  131. * @param string $name The name of the context to switch to
  132. *
  133. */
  134. public static function switchTo($name)
  135. {
  136. if (!isset(self::$instances[$name]))
  137. {
  138. $currentConfiguration = sfContext::getInstance()->getConfiguration();
  139. sfContext::createInstance(ProjectConfiguration::getApplicationConfiguration($name, $currentConfiguration->getEnvironment(), $currentConfiguration->isDebug()));
  140. }
  141. self::$current = $name;
  142. sfContext::getInstance()->getConfiguration()->activate();
  143. }
  144. /**
  145. * Returns the configuration instance.
  146. *
  147. * @return sfApplicationConfiguration The current application configuration instance
  148. */
  149. public function getConfiguration()
  150. {
  151. return $this->configuration;
  152. }
  153. /**
  154. * Retrieves the current event dispatcher.
  155. *
  156. * @return sfEventDispatcher An sfEventDispatcher instance
  157. */
  158. public function getEventDispatcher()
  159. {
  160. return $this->dispatcher;
  161. }
  162. /**
  163. * Retrieve the action name for this context.
  164. *
  165. * @return string The currently executing action name, if one is set,
  166. * otherwise null.
  167. */
  168. public function getActionName()
  169. {
  170. // get the last action stack entry
  171. if ($this->factories['actionStack'] && $lastEntry = $this->factories['actionStack']->getLastEntry())
  172. {
  173. return $lastEntry->getActionName();
  174. }
  175. }
  176. /**
  177. * Retrieve the ActionStack.
  178. *
  179. * @return sfActionStack the sfActionStack instance
  180. */
  181. public function getActionStack()
  182. {
  183. return $this->factories['actionStack'];
  184. }
  185. /**
  186. * Retrieve the controller.
  187. *
  188. * @return sfController The current sfController implementation instance.
  189. */
  190. public function getController()
  191. {
  192. return isset($this->factories['controller']) ? $this->factories['controller'] : null;
  193. }
  194. /**
  195. * Retrieves the mailer.
  196. *
  197. * @return sfMailer The current sfMailer implementation instance.
  198. */
  199. public function getMailer()
  200. {
  201. if (!isset($this->factories['mailer']))
  202. {
  203. $this->factories['mailer'] = new $this->mailerConfiguration['class']($this->dispatcher, $this->mailerConfiguration);
  204. }
  205. return $this->factories['mailer'];
  206. }
  207. public function setMailerConfiguration($configuration)
  208. {
  209. $this->mailerConfiguration = $configuration;
  210. }
  211. /**
  212. * Retrieve the logger.
  213. *
  214. * @return sfLogger The current sfLogger implementation instance.
  215. */
  216. public function getLogger()
  217. {
  218. if (!isset($this->factories['logger']))
  219. {
  220. $this->factories['logger'] = new sfNoLogger($this->dispatcher);
  221. }
  222. return $this->factories['logger'];
  223. }
  224. /**
  225. * Retrieve a database connection from the database manager.
  226. *
  227. * This is a shortcut to manually getting a connection from an existing
  228. * database implementation instance.
  229. *
  230. * If the [sf_use_database] setting is off, this will return null.
  231. *
  232. * @param name $name A database name.
  233. *
  234. * @return mixed A database instance.
  235. *
  236. * @throws sfDatabaseException if the requested database name does not exist.
  237. */
  238. public function getDatabaseConnection($name = 'default')
  239. {
  240. if (null !== $this->factories['databaseManager'])
  241. {
  242. return $this->factories['databaseManager']->getDatabase($name)->getConnection();
  243. }
  244. return null;
  245. }
  246. /**
  247. * Retrieve the database manager.
  248. *
  249. * @return sfDatabaseManager The current sfDatabaseManager instance.
  250. */
  251. public function getDatabaseManager()
  252. {
  253. return isset($this->factories['databaseManager']) ? $this->factories['databaseManager'] : null;
  254. }
  255. /**
  256. * Retrieve the module directory for this context.
  257. *
  258. * @return string An absolute filesystem path to the directory of the
  259. * currently executing module, if one is set, otherwise null.
  260. */
  261. public function getModuleDirectory()
  262. {
  263. // get the last action stack entry
  264. if (isset($this->factories['actionStack']) && $lastEntry = $this->factories['actionStack']->getLastEntry())
  265. {
  266. return sfConfig::get('sf_app_module_dir').'/'.$lastEntry->getModuleName();
  267. }
  268. }
  269. /**
  270. * Retrieve the module name for this context.
  271. *
  272. * @return string The currently executing module name, if one is set,
  273. * otherwise null.
  274. */
  275. public function getModuleName()
  276. {
  277. // get the last action stack entry
  278. if (isset($this->factories['actionStack']) && $lastEntry = $this->factories['actionStack']->getLastEntry())
  279. {
  280. return $lastEntry->getModuleName();
  281. }
  282. }
  283. /**
  284. * Retrieve the request.
  285. *
  286. * @return sfRequest The current sfRequest implementation instance.
  287. */
  288. public function getRequest()
  289. {
  290. return isset($this->factories['request']) ? $this->factories['request'] : null;
  291. }
  292. /**
  293. * Retrieve the response.
  294. *
  295. * @return sfResponse The current sfResponse implementation instance.
  296. */
  297. public function getResponse()
  298. {
  299. return isset($this->factories['response']) ? $this->factories['response'] : null;
  300. }
  301. /**
  302. * Set the response object.
  303. *
  304. * @param sfResponse $response An sfResponse instance.
  305. *
  306. * @return void
  307. */
  308. public function setResponse($response)
  309. {
  310. $this->factories['response'] = $response;
  311. }
  312. /**
  313. * Retrieve the storage.
  314. *
  315. * @return sfStorage The current sfStorage implementation instance.
  316. */
  317. public function getStorage()
  318. {
  319. return isset($this->factories['storage']) ? $this->factories['storage'] : null;
  320. }
  321. /**
  322. * Retrieve the view cache manager
  323. *
  324. * @return sfViewCacheManager The current sfViewCacheManager implementation instance.
  325. */
  326. public function getViewCacheManager()
  327. {
  328. return isset($this->factories['viewCacheManager']) ? $this->factories['viewCacheManager'] : null;
  329. }
  330. /**
  331. * Retrieve the i18n instance
  332. *
  333. * @return sfI18N The current sfI18N implementation instance.
  334. */
  335. public function getI18N()
  336. {
  337. if (!sfConfig::get('sf_i18n'))
  338. {
  339. throw new sfConfigurationException('You must enable i18n support in your settings.yml configuration file.');
  340. }
  341. return $this->factories['i18n'];
  342. }
  343. /**
  344. * Retrieve the routing instance.
  345. *
  346. * @return sfRouting The current sfRouting implementation instance.
  347. */
  348. public function getRouting()
  349. {
  350. return isset($this->factories['routing']) ? $this->factories['routing'] : null;
  351. }
  352. /**
  353. * Retrieve the user.
  354. *
  355. * @return sfUser The current sfUser implementation instance.
  356. */
  357. public function getUser()
  358. {
  359. return isset($this->factories['user']) ? $this->factories['user'] : null;
  360. }
  361. /**
  362. * Returns the configuration cache.
  363. *
  364. * @return sfConfigCache A sfConfigCache instance
  365. */
  366. public function getConfigCache()
  367. {
  368. return $this->configuration->getConfigCache();
  369. }
  370. /**
  371. * Returns true if the context object exists (implements the ArrayAccess interface).
  372. *
  373. * @param string $name The name of the context object
  374. *
  375. * @return Boolean true if the context object exists, false otherwise
  376. */
  377. public function offsetExists($name)
  378. {
  379. return $this->has($name);
  380. }
  381. /**
  382. * Returns the context object associated with the name (implements the ArrayAccess interface).
  383. *
  384. * @param string $name The offset of the value to get
  385. *
  386. * @return mixed The context object if exists, null otherwise
  387. */
  388. public function offsetGet($name)
  389. {
  390. return $this->get($name);
  391. }
  392. /**
  393. * Sets the context object associated with the offset (implements the ArrayAccess interface).
  394. *
  395. * @param string $offset The parameter name
  396. * @param string $value The parameter value
  397. */
  398. public function offsetSet($offset, $value)
  399. {
  400. $this->set($offset, $value);
  401. }
  402. /**
  403. * Unsets the context object associated with the offset (implements the ArrayAccess interface).
  404. *
  405. * @param string $offset The parameter name
  406. */
  407. public function offsetUnset($offset)
  408. {
  409. unset($this->factories[$offset]);
  410. }
  411. /**
  412. * Gets an object from the current context.
  413. *
  414. * @param string $name The name of the object to retrieve
  415. *
  416. * @return object The object associated with the given name
  417. */
  418. public function get($name)
  419. {
  420. if (!$this->has($name))
  421. {
  422. throw new sfException(sprintf('The "%s" object does not exist in the current context.', $name));
  423. }
  424. return $this->factories[$name];
  425. }
  426. /**
  427. * Puts an object in the current context.
  428. *
  429. * @param string $name The name of the object to store
  430. * @param object $object The object to store
  431. */
  432. public function set($name, $object)
  433. {
  434. $this->factories[$name] = $object;
  435. }
  436. /**
  437. * Returns true if an object is currently stored in the current context with the given name, false otherwise.
  438. *
  439. * @param string $name The object name
  440. *
  441. * @return bool true if the object is not null, false otherwise
  442. */
  443. public function has($name)
  444. {
  445. return isset($this->factories[$name]);
  446. }
  447. /**
  448. * Listens to the template.filter_parameters event.
  449. *
  450. * @param sfEvent $event An sfEvent instance
  451. * @param array $parameters An array of template parameters to filter
  452. *
  453. * @return array The filtered parameters array
  454. */
  455. public function filterTemplateParameters(sfEvent $event, $parameters)
  456. {
  457. $parameters['sf_context'] = $this;
  458. $parameters['sf_request'] = $this->factories['request'];
  459. $parameters['sf_params'] = $this->factories['request']->getParameterHolder();
  460. $parameters['sf_response'] = $this->factories['response'];
  461. $parameters['sf_user'] = $this->factories['user'];
  462. return $parameters;
  463. }
  464. /**
  465. * Calls methods defined via sfEventDispatcher.
  466. *
  467. * If a method cannot be found via sfEventDispatcher, the method name will
  468. * be parsed to magically handle getMyFactory() and setMyFactory() methods.
  469. *
  470. * @param string $method The method name
  471. * @param array $arguments The method arguments
  472. *
  473. * @return mixed The returned value of the called method
  474. *
  475. * @throws <b>sfException</b> if call fails
  476. */
  477. public function __call($method, $arguments)
  478. {
  479. $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'context.method_not_found', array('method' => $method, 'arguments' => $arguments)));
  480. if (!$event->isProcessed())
  481. {
  482. $verb = substr($method, 0, 3); // get | set
  483. $factory = strtolower(substr($method, 3)); // factory name
  484. if ('get' == $verb && $this->has($factory))
  485. {
  486. return $this->factories[$factory];
  487. }
  488. else if ('set' == $verb && isset($arguments[0]))
  489. {
  490. return $this->set($factory, $arguments[0]);
  491. }
  492. throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method));
  493. }
  494. return $event->getReturnValue();
  495. }
  496. /**
  497. * Execute the shutdown procedure.
  498. *
  499. * @return void
  500. */
  501. public function shutdown()
  502. {
  503. // shutdown all factories
  504. if($this->has('user'))
  505. {
  506. $this->getUser()->shutdown();
  507. $this->getStorage()->shutdown();
  508. }
  509. if ($this->has('routing'))
  510. {
  511. $this->getRouting()->shutdown();
  512. }
  513. if (sfConfig::get('sf_use_database'))
  514. {
  515. $this->getDatabaseManager()->shutdown();
  516. }
  517. if (sfConfig::get('sf_logging_enabled'))
  518. {
  519. $this->getLogger()->shutdown();
  520. }
  521. }
  522. }

Debug toolbar