/library/Symfony/Components/sfServiceContainerDumperPhp.php

https://bitbucket.org/khuongduybui/openfisma · PHP · 359 lines · 271 code · 57 blank · 31 comment · 21 complexity · 92146fd4474293e7e3a6bf8da82998f2 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. * sfServiceContainerDumperPhp dumps a service container as a PHP class.
  12. *
  13. * @package symfony
  14. * @subpackage dependency_injection
  15. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  16. * @version SVN: $Id$
  17. */
  18. class sfServiceContainerDumperPhp extends sfServiceContainerDumper
  19. {
  20. /**
  21. * Dumps the service container as a PHP class.
  22. *
  23. * Available options:
  24. *
  25. * * class: The class name
  26. * * base_class: The base class name
  27. *
  28. * @param array $options An array of options
  29. *
  30. * @return string A PHP class representing of the service container
  31. */
  32. public function dump(array $options = array())
  33. {
  34. $options = array_merge(array(
  35. 'class' => 'ProjectServiceContainer',
  36. 'base_class' => 'sfServiceContainer',
  37. ), $options);
  38. return
  39. $this->startClass($options['class'], $options['base_class']).
  40. $this->addConstructor().
  41. $this->addServices().
  42. $this->addDefaultParametersMethod().
  43. $this->endClass()
  44. ;
  45. }
  46. protected function addServiceInclude($id, $definition)
  47. {
  48. if (null !== $definition->getFile())
  49. {
  50. return sprintf(" require_once %s;\n\n", $this->dumpValue($definition->getFile()));
  51. }
  52. }
  53. protected function addServiceShared($id, $definition)
  54. {
  55. if ($definition->isShared())
  56. {
  57. return <<<EOF
  58. if (isset(\$this->shared['$id'])) return \$this->shared['$id'];
  59. EOF;
  60. }
  61. }
  62. protected function addServiceReturn($id, $definition)
  63. {
  64. if ($definition->isShared())
  65. {
  66. return <<<EOF
  67. return \$this->shared['$id'] = \$instance;
  68. }
  69. EOF;
  70. }
  71. else
  72. {
  73. return <<<EOF
  74. return \$instance;
  75. }
  76. EOF;
  77. }
  78. }
  79. protected function addServiceInstance($id, $definition)
  80. {
  81. $class = $this->dumpValue($definition->getClass());
  82. $arguments = array();
  83. foreach ($definition->getArguments() as $value)
  84. {
  85. $arguments[] = $this->dumpValue($value);
  86. }
  87. if (null !== $definition->getConstructor())
  88. {
  89. return sprintf(" \$instance = call_user_func(array(%s, '%s')%s);\n", $class, $definition->getConstructor(), $arguments ? ', '.implode(', ', $arguments) : '');
  90. }
  91. else
  92. {
  93. if ($class != "'".$definition->getClass()."'")
  94. {
  95. return sprintf(" \$class = %s;\n \$instance = new \$class(%s);\n", $class, implode(', ', $arguments));
  96. }
  97. else
  98. {
  99. return sprintf(" \$instance = new %s(%s);\n", $definition->getClass(), implode(', ', $arguments));
  100. }
  101. }
  102. }
  103. protected function addServiceMethodCalls($id, $definition)
  104. {
  105. $calls = '';
  106. foreach ($definition->getMethodCalls() as $call)
  107. {
  108. $arguments = array();
  109. foreach ($call[1] as $value)
  110. {
  111. $arguments[] = $this->dumpValue($value);
  112. }
  113. $calls .= sprintf(" \$instance->%s(%s);\n", $call[0], implode(', ', $arguments));
  114. }
  115. return $calls;
  116. }
  117. protected function addServiceConfigurator($id, $definition)
  118. {
  119. if (!$callable = $definition->getConfigurator())
  120. {
  121. return '';
  122. }
  123. if (is_array($callable))
  124. {
  125. if (is_object($callable[0]) && $callable[0] instanceof sfServiceReference)
  126. {
  127. return sprintf(" %s->%s(\$instance);\n", $this->getServiceCall((string) $callable[0]), $callable[1]);
  128. }
  129. else
  130. {
  131. return sprintf(" call_user_func(array(%s, '%s'), \$instance);\n", $this->dumpValue($callable[0]), $callable[1]);
  132. }
  133. }
  134. else
  135. {
  136. return sprintf(" %s(\$instance);\n", $callable);
  137. }
  138. }
  139. protected function addService($id, $definition)
  140. {
  141. $name = sfServiceContainer::camelize($id);
  142. $code = <<<EOF
  143. protected function get{$name}Service()
  144. {
  145. EOF;
  146. $code .=
  147. $this->addServiceInclude($id, $definition).
  148. $this->addServiceShared($id, $definition).
  149. $this->addServiceInstance($id, $definition).
  150. $this->addServiceMethodCalls($id, $definition).
  151. $this->addServiceConfigurator($id, $definition).
  152. $this->addServiceReturn($id, $definition)
  153. ;
  154. return $code;
  155. }
  156. protected function addServiceAlias($alias, $id)
  157. {
  158. $name = sfServiceContainer::camelize($alias);
  159. return <<<EOF
  160. protected function get{$name}Service()
  161. {
  162. return {$this->getServiceCall($id)};
  163. }
  164. EOF;
  165. }
  166. protected function addServices()
  167. {
  168. $code = '';
  169. foreach ($this->container->getServiceDefinitions() as $id => $definition)
  170. {
  171. $code .= $this->addService($id, $definition);
  172. }
  173. foreach ($this->container->getAliases() as $alias => $id)
  174. {
  175. $code .= $this->addServiceAlias($alias, $id);
  176. }
  177. return $code;
  178. }
  179. protected function startClass($class, $baseClass)
  180. {
  181. return <<<EOF
  182. <?php
  183. class $class extends $baseClass
  184. {
  185. protected \$shared = array();
  186. EOF;
  187. }
  188. protected function addConstructor()
  189. {
  190. if (!$this->container->getParameters())
  191. {
  192. return '';
  193. }
  194. return <<<EOF
  195. public function __construct()
  196. {
  197. parent::__construct(\$this->getDefaultParameters());
  198. }
  199. EOF;
  200. }
  201. protected function addDefaultParametersMethod()
  202. {
  203. if (!$this->container->getParameters())
  204. {
  205. return '';
  206. }
  207. $parameters = $this->exportParameters($this->container->getParameters());
  208. return <<<EOF
  209. protected function getDefaultParameters()
  210. {
  211. return $parameters;
  212. }
  213. EOF;
  214. }
  215. protected function exportParameters($parameters, $indent = 6)
  216. {
  217. $php = array();
  218. foreach ($parameters as $key => $value)
  219. {
  220. if (is_array($value))
  221. {
  222. $value = $this->exportParameters($value, $indent + 2);
  223. }
  224. elseif ($value instanceof sfServiceReference)
  225. {
  226. $value = sprintf("new sfServiceReference('%s')", $value);
  227. }
  228. elseif ($value instanceof sfServiceParameter)
  229. {
  230. $value = sprintf("\$this->getParameter('%s')", $value);
  231. }
  232. else
  233. {
  234. $value = var_export($value, true);
  235. }
  236. $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), var_export($key, true), $value);
  237. }
  238. return sprintf("array(\n%s\n%s)", implode("\n", $php), str_repeat(' ', $indent - 2));
  239. }
  240. protected function endClass()
  241. {
  242. return <<<EOF
  243. }
  244. EOF;
  245. }
  246. protected function dumpValue($value)
  247. {
  248. if (is_array($value))
  249. {
  250. $code = array();
  251. foreach ($value as $k => $v)
  252. {
  253. $code[] = sprintf("%s => %s", $this->dumpValue($k), $this->dumpValue($v));
  254. }
  255. return sprintf("array(%s)", implode(', ', $code));
  256. }
  257. elseif (is_object($value) && $value instanceof sfServiceReference)
  258. {
  259. return $this->getServiceCall((string) $value);
  260. }
  261. elseif (is_object($value) && $value instanceof sfServiceParameter)
  262. {
  263. return sprintf("\$this->getParameter('%s')", strtolower($value));
  264. }
  265. elseif (is_string($value))
  266. {
  267. if (preg_match('/^%([^%]+)%$/', $value, $match))
  268. {
  269. // we do this to deal with non string values (boolean, integer, ...)
  270. // the preg_replace_callback converts them to strings
  271. return sprintf("\$this->getParameter('%s')", strtolower($match[1]));
  272. }
  273. else
  274. {
  275. $code = str_replace('%%', '%', preg_replace_callback('/(?<!%)(%)([^%]+)\1/', array($this, 'replaceParameter'), var_export($value, true)));
  276. // optimize string
  277. $code = preg_replace(array("/^''\./", "/\.''$/", "/\.''\./"), array('', '', '.'), $code);
  278. return $code;
  279. }
  280. }
  281. elseif (is_object($value) || is_resource($value))
  282. {
  283. throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
  284. }
  285. else
  286. {
  287. return var_export($value, true);
  288. }
  289. }
  290. public function replaceParameter($match)
  291. {
  292. return sprintf("'.\$this->getParameter('%s').'", strtolower($match[2]));
  293. }
  294. protected function getServiceCall($id)
  295. {
  296. if ('service_container' == $id)
  297. {
  298. return '$this';
  299. }
  300. return sprintf('$this->getService(\'%s\')', $id);
  301. }
  302. }