/library/Symfony/Components/sfServiceContainer.php

https://bitbucket.org/khuongduybui/openfisma · PHP · 367 lines · 149 code · 34 blank · 184 comment · 5 complexity · 7f3c7b374050a1909ca95a5554062d6d MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the symfony framework.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  6. *
  7. * This source file is subject to the MIT license that is bundled
  8. * with this source code in the file LICENSE.
  9. */
  10. /**
  11. * sfServiceContainer is a dependency injection container.
  12. *
  13. * It gives access to object instances (services), and parameters.
  14. *
  15. * Services and parameters are simple key/pair stores.
  16. *
  17. * Parameters keys are case insensitive.
  18. *
  19. * A service id can contain lowercased letters, digits, underscores, and dots.
  20. * Underscores are used to separate words, and dots to group services
  21. * under namespaces:
  22. *
  23. * <ul>
  24. * <li>request</li>
  25. * <li>mysql_session_storage</li>
  26. * <li>symfony.mysql_session_storage</li>
  27. * </ul>
  28. *
  29. * A service can also be defined by creating a method named
  30. * getXXXService(), where XXX is the camelized version of the id:
  31. *
  32. * <ul>
  33. * <li>request -> getRequestService()</li>
  34. * <li>mysql_session_storage -> getMysqlSessionStorageService()</li>
  35. * <li>symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()</li>
  36. * </ul>
  37. *
  38. * @package symfony
  39. * @subpackage dependency_injection
  40. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  41. * @version SVN: $Id$
  42. */
  43. class sfServiceContainer implements sfServiceContainerInterface, ArrayAccess, Iterator
  44. {
  45. protected
  46. $serviceIds = array(),
  47. $parameters = array(),
  48. $services = array(),
  49. $count = 0;
  50. /**
  51. * Constructor.
  52. *
  53. * @param array $parameters An array of parameters
  54. */
  55. public function __construct(array $parameters = array())
  56. {
  57. $this->setParameters($parameters);
  58. $this->setService('service_container', $this);
  59. }
  60. /**
  61. * Sets the service container parameters.
  62. *
  63. * @param array $parameters An array of parameters
  64. */
  65. public function setParameters(array $parameters)
  66. {
  67. $this->parameters = array();
  68. foreach ($parameters as $key => $value)
  69. {
  70. $this->parameters[strtolower($key)] = $value;
  71. }
  72. }
  73. /**
  74. * Adds parameters to the service container parameters.
  75. *
  76. * @param array $parameters An array of parameters
  77. */
  78. public function addParameters(array $parameters)
  79. {
  80. $this->setParameters(array_merge($this->parameters, $parameters));
  81. }
  82. /**
  83. * Gets the service container parameters.
  84. *
  85. * @return array An array of parameters
  86. */
  87. public function getParameters()
  88. {
  89. return $this->parameters;
  90. }
  91. /**
  92. * Gets a service container parameter.
  93. *
  94. * @param string $name The parameter name
  95. *
  96. * @return mixed The parameter value
  97. *
  98. * @throw InvalidArgumentException if the parameter is not defined
  99. */
  100. public function getParameter($name)
  101. {
  102. if (!$this->hasParameter($name))
  103. {
  104. throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
  105. }
  106. return $this->parameters[strtolower($name)];
  107. }
  108. /**
  109. * Sets a service container parameter.
  110. *
  111. * @param string $name The parameter name
  112. * @param mixed $parameters The parameter value
  113. */
  114. public function setParameter($name, $value)
  115. {
  116. $this->parameters[strtolower($name)] = $value;
  117. }
  118. /**
  119. * Returns true if a parameter name is defined.
  120. *
  121. * @param string $name The parameter name
  122. *
  123. * @return Boolean true if the parameter name is defined, false otherwise
  124. */
  125. public function hasParameter($name)
  126. {
  127. return array_key_exists(strtolower($name), $this->parameters);
  128. }
  129. /**
  130. * Sets a service.
  131. *
  132. * @param string $id The service identifier
  133. * @param object $service The service instance
  134. */
  135. public function setService($id, $service)
  136. {
  137. $this->services[$id] = $service;
  138. }
  139. /**
  140. * Returns true if the given service is defined.
  141. *
  142. * @param string $id The service identifier
  143. *
  144. * @return Boolean true if the service is defined, false otherwise
  145. */
  146. public function hasService($id)
  147. {
  148. return isset($this->services[$id]) || method_exists($this, 'get'.self::camelize($id).'Service');
  149. }
  150. /**
  151. * Gets a service.
  152. *
  153. * If a service is both defined through a setService() method and
  154. * with a set*Service() method, the former has always precedence.
  155. *
  156. * @param string $id The service identifier
  157. *
  158. * @return object The associated service
  159. *
  160. * @throw InvalidArgumentException if the service is not defined
  161. */
  162. public function getService($id)
  163. {
  164. if (isset($this->services[$id]))
  165. {
  166. return $this->services[$id];
  167. }
  168. if (method_exists($this, $method = 'get'.self::camelize($id).'Service'))
  169. {
  170. return $this->$method();
  171. }
  172. throw new InvalidArgumentException(sprintf('The service "%s" does not exist.', $id));
  173. }
  174. /**
  175. * Gets all service ids.
  176. *
  177. * @return array An array of all defined service ids
  178. */
  179. public function getServiceIds()
  180. {
  181. $ids = array();
  182. $r = new ReflectionClass($this);
  183. foreach ($r->getMethods() as $method)
  184. {
  185. if (preg_match('/^get(.+)Service$/', $name = $method->getName(), $match))
  186. {
  187. $ids[] = self::underscore($match[1]);
  188. }
  189. }
  190. return array_merge($ids, array_keys($this->services));
  191. }
  192. /**
  193. * Returns true if the parameter name is defined (implements the ArrayAccess interface).
  194. *
  195. * @param string The parameter name
  196. *
  197. * @return Boolean true if the parameter name is defined, false otherwise
  198. */
  199. public function offsetExists($name)
  200. {
  201. return $this->hasParameter($name);
  202. }
  203. /**
  204. * Gets a service container parameter (implements the ArrayAccess interface).
  205. *
  206. * @param string The parameter name
  207. *
  208. * @return mixed The parameter value
  209. */
  210. public function offsetGet($name)
  211. {
  212. return $this->getParameter($name);
  213. }
  214. /**
  215. * Sets a parameter (implements the ArrayAccess interface).
  216. *
  217. * @param string The parameter name
  218. * @param mixed The parameter value
  219. */
  220. public function offsetSet($name, $value)
  221. {
  222. $this->setParameter($name, $value);
  223. }
  224. /**
  225. * Removes a parameter (implements the ArrayAccess interface).
  226. *
  227. * @param string The parameter name
  228. */
  229. public function offsetUnset($name)
  230. {
  231. unset($this->parameters[$name]);
  232. }
  233. /**
  234. * Returns true if the container has a service with the given identifier.
  235. *
  236. * @param string The service identifier
  237. *
  238. * @return Boolean true if the container has a service with the given identifier, false otherwise
  239. */
  240. public function __isset($id)
  241. {
  242. return $this->hasService($id);
  243. }
  244. /**
  245. * Gets the service associated with the given identifier.
  246. *
  247. * @param string The service identifier
  248. *
  249. * @return mixed The service instance associated with the given identifier
  250. */
  251. public function __get($id)
  252. {
  253. return $this->getService($id);
  254. }
  255. /**
  256. * Sets a service.
  257. *
  258. * @param string The service identifier
  259. * @param mixed A service instance
  260. */
  261. public function __set($id, $service)
  262. {
  263. $this->setService($id, $service);
  264. }
  265. /**
  266. * Removes a service by identifier.
  267. *
  268. * @param string The service identifier
  269. */
  270. public function __unset($id)
  271. {
  272. throw new LogicException('You can\'t unset a service.');
  273. }
  274. /**
  275. * Resets the service identifiers array to the beginning (implements the Iterator interface).
  276. */
  277. public function rewind()
  278. {
  279. $this->serviceIds = $this->getServiceIds();
  280. $this->count = count($this->serviceIds);
  281. }
  282. /**
  283. * Gets the key associated with the current service (implements the Iterator interface).
  284. *
  285. * @return string The service identifier
  286. */
  287. public function key()
  288. {
  289. return current($this->serviceIds);
  290. }
  291. /**
  292. * Returns the current service (implements the Iterator interface).
  293. *
  294. * @return mixed The service
  295. */
  296. public function current()
  297. {
  298. return $this->getService(current($this->serviceIds));
  299. }
  300. /**
  301. * Moves to the next service (implements the Iterator interface).
  302. */
  303. public function next()
  304. {
  305. next($this->serviceIds);
  306. --$this->count;
  307. }
  308. /**
  309. * Returns true if the current service is valid (implements the Iterator interface).
  310. *
  311. * @return boolean The validity of the current service; true if it is valid
  312. */
  313. public function valid()
  314. {
  315. return $this->count > 0;
  316. }
  317. static public function camelize($id)
  318. {
  319. return preg_replace_callback(
  320. '/\.(.)/',
  321. function($matches) { return '_' . strtoupper($matches[1]); },
  322. preg_replace_callback(
  323. '/(^|_|-)+(.)/',
  324. function($matches) { return strtoupper($matches[2]); },
  325. $id
  326. )
  327. );
  328. }
  329. static public function underscore($id)
  330. {
  331. return strtolower(preg_replace(array('/_/', '/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('.', '\\1_\\2', '\\1_\\2'), $id));
  332. }
  333. }