sfUser.class.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
  5. * (c) 2004-2006 Sean Kerr <sean@code-box.org>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. /**
  11. *
  12. * sfUser wraps a client session and provides accessor methods for user
  13. * attributes. It also makes storing and retrieving multiple page form data
  14. * rather easy by allowing user attributes to be stored in namespaces, which
  15. * help organize data.
  16. *
  17. * @package symfony
  18. * @subpackage user
  19. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  20. * @author Sean Kerr <sean@code-box.org>
  21. * @version SVN: $Id: sfUser.class.php 9060 2008-05-19 21:31:17Z FabianLange $
  22. */
  23. class sfUser
  24. {
  25. /**
  26. * The namespace under which attributes will be stored.
  27. */
  28. const ATTRIBUTE_NAMESPACE = 'symfony/user/sfUser/attributes';
  29. const CULTURE_NAMESPACE = 'symfony/user/sfUser/culture';
  30. protected
  31. $options = array(),
  32. $attributeHolder = null,
  33. $culture = null,
  34. $storage = null,
  35. $dispatcher = null;
  36. /**
  37. * Class constructor.
  38. *
  39. * @see initialize()
  40. */
  41. public function __construct(sfEventDispatcher $dispatcher, sfStorage $storage, $options = array())
  42. {
  43. $this->initialize($dispatcher, $storage, $options);
  44. if ($this->options['auto_shutdown'])
  45. {
  46. register_shutdown_function(array($this, 'shutdown'));
  47. }
  48. }
  49. /**
  50. * Initializes this sfUser.
  51. *
  52. * Available options:
  53. *
  54. * * auto_shutdown: Whether to automatically save the changes to the session (true by default)
  55. * * culture: The user culture
  56. * * default_culture: The default user culture (en by default)
  57. * * use_flash: Whether to enable flash usage (false by default)
  58. * * logging: Whether to enable logging (false by default)
  59. *
  60. * @param sfEventDispatcher $dispatcher An sfEventDispatcher instance.
  61. * @param sfStorage $storage An sfStorage instance.
  62. * @param array $options An associative array of options.
  63. *
  64. * @return Boolean true, if initialization completes successfully, otherwise false.
  65. */
  66. public function initialize(sfEventDispatcher $dispatcher, sfStorage $storage, $options = array())
  67. {
  68. $this->dispatcher = $dispatcher;
  69. $this->storage = $storage;
  70. $this->options = array_merge(array(
  71. 'auto_shutdown' => true,
  72. 'culture' => null,
  73. 'default_culture' => 'en',
  74. 'use_flash' => false,
  75. 'logging' => false,
  76. ), $options);
  77. $this->attributeHolder = new sfNamespacedParameterHolder(self::ATTRIBUTE_NAMESPACE);
  78. // read attributes from storage
  79. $attributes = $storage->read(self::ATTRIBUTE_NAMESPACE);
  80. if (is_array($attributes))
  81. {
  82. foreach ($attributes as $namespace => $values)
  83. {
  84. $this->attributeHolder->add($values, $namespace);
  85. }
  86. }
  87. // set the user culture to sf_culture parameter if present in the request
  88. // otherwise
  89. // - use the culture defined in the user session
  90. // - use the default culture set in settings.yml
  91. $currentCulture = $storage->read(self::CULTURE_NAMESPACE);
  92. $this->setCulture(!is_null($this->options['culture']) ? $this->options['culture'] : (!is_null($currentCulture) ? $currentCulture : $this->options['default_culture']));
  93. // flag current flash to be removed at shutdown
  94. if ($this->options['use_flash'] && $names = $this->attributeHolder->getNames('symfony/user/sfUser/flash'))
  95. {
  96. if ($this->options['logging'])
  97. {
  98. $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Flag old flash messages ("%s")', implode('", "', $names)))));
  99. }
  100. foreach ($names as $name)
  101. {
  102. $this->attributeHolder->set($name, true, 'symfony/user/sfUser/flash/remove');
  103. }
  104. }
  105. }
  106. /**
  107. * Returns the initialization options
  108. *
  109. * @return array The options used to initialize sfUser
  110. */
  111. public function getOptions()
  112. {
  113. return $this->options;
  114. }
  115. /**
  116. * Sets the user culture.
  117. *
  118. * @param string $culture
  119. */
  120. public function setCulture($culture)
  121. {
  122. if ($this->culture != $culture)
  123. {
  124. $this->culture = $culture;
  125. $this->dispatcher->notify(new sfEvent($this, 'user.change_culture', array('culture' => $culture)));
  126. }
  127. }
  128. /**
  129. * Sets a flash variable that will be passed to the very next action.
  130. *
  131. * @param string $name The name of the flash variable
  132. * @param string $value The value of the flash variable
  133. * @param bool $persist true if the flash have to persist for the following request (true by default)
  134. */
  135. public function setFlash($name, $value, $persist = true)
  136. {
  137. if (!$this->options['use_flash'])
  138. {
  139. return;
  140. }
  141. $this->setAttribute($name, $value, 'symfony/user/sfUser/flash');
  142. if ($persist)
  143. {
  144. // clear removal flag
  145. $this->attributeHolder->remove($name, null, 'symfony/user/sfUser/flash/remove');
  146. }
  147. else
  148. {
  149. $this->setAttribute($name, true, 'symfony/user/sfUser/flash/remove');
  150. }
  151. }
  152. /**
  153. * Gets a flash variable.
  154. *
  155. * @param string $name The name of the flash variable
  156. * @param string $default The default value returned when named variable does not exist.
  157. *
  158. * @return mixed The value of the flash variable
  159. */
  160. public function getFlash($name, $default = null)
  161. {
  162. if (!$this->options['use_flash'])
  163. {
  164. return $default;
  165. }
  166. return $this->getAttribute($name, $default, 'symfony/user/sfUser/flash');
  167. }
  168. /**
  169. * Returns true if a flash variable of the specified name exists.
  170. *
  171. * @param string $name The name of the flash variable
  172. *
  173. * @return bool true if the variable exists, false otherwise
  174. */
  175. public function hasFlash($name)
  176. {
  177. if (!$this->options['use_flash'])
  178. {
  179. return false;
  180. }
  181. return $this->hasAttribute($name, 'symfony/user/sfUser/flash');
  182. }
  183. /**
  184. * Gets culture.
  185. *
  186. * @return string
  187. */
  188. public function getCulture()
  189. {
  190. return $this->culture;
  191. }
  192. public function getAttributeHolder()
  193. {
  194. return $this->attributeHolder;
  195. }
  196. public function getAttribute($name, $default = null, $ns = null)
  197. {
  198. return $this->attributeHolder->get($name, $default, $ns);
  199. }
  200. public function hasAttribute($name, $ns = null)
  201. {
  202. return $this->attributeHolder->has($name, $ns);
  203. }
  204. public function setAttribute($name, $value, $ns = null)
  205. {
  206. return $this->attributeHolder->set($name, $value, $ns);
  207. }
  208. /**
  209. * Executes the shutdown procedure.
  210. */
  211. public function shutdown()
  212. {
  213. // remove flash that are tagged to be removed
  214. if ($this->options['use_flash'] && $names = $this->attributeHolder->getNames('symfony/user/sfUser/flash/remove'))
  215. {
  216. if ($this->options['logging'])
  217. {
  218. $this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Remove old flash messages ("%s")', implode('", "', $names)))));
  219. }
  220. foreach ($names as $name)
  221. {
  222. $this->attributeHolder->remove($name, null, 'symfony/user/sfUser/flash');
  223. $this->attributeHolder->remove($name, null, 'symfony/user/sfUser/flash/remove');
  224. }
  225. }
  226. $attributes = array();
  227. foreach ($this->attributeHolder->getNamespaces() as $namespace)
  228. {
  229. $attributes[$namespace] = $this->attributeHolder->getAll($namespace);
  230. }
  231. // write attributes to the storage
  232. $this->storage->write(self::ATTRIBUTE_NAMESPACE, $attributes);
  233. // write culture to the storage
  234. $this->storage->write(self::CULTURE_NAMESPACE, $this->culture);
  235. session_write_close();
  236. }
  237. /**
  238. * Calls methods defined via sfEventDispatcher.
  239. *
  240. * @param string $method The method name
  241. * @param array $arguments The method arguments
  242. *
  243. * @return mixed The returned value of the called method
  244. *
  245. * @throws sfException If the calls fails
  246. */
  247. public function __call($method, $arguments)
  248. {
  249. $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'user.method_not_found', array('method' => $method, 'arguments' => $arguments)));
  250. if (!$event->isProcessed())
  251. {
  252. throw new sfException(sprintf('Call to undefined method %s::%s.', get_class($this), $method));
  253. }
  254. return $event->getReturnValue();
  255. }
  256. }