InlineServiceDefinitionsPass.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. <?php
  2. namespace Symfony\Component\DependencyInjection\Compiler;
  3. use Symfony\Component\DependencyInjection\Definition;
  4. use Symfony\Component\DependencyInjection\Reference;
  5. use Symfony\Component\DependencyInjection\ContainerBuilder;
  6. /*
  7. * This file is part of the Symfony framework.
  8. *
  9. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  10. *
  11. * This source file is subject to the MIT license that is bundled
  12. * with this source code in the file LICENSE.
  13. */
  14. /**
  15. * Inline service definitions where this is possible.
  16. *
  17. * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  18. */
  19. class InlineServiceDefinitionsPass implements CompilerPassInterface
  20. {
  21. protected $aliasMap;
  22. public function process(ContainerBuilder $container)
  23. {
  24. $this->aliasMap = array();
  25. foreach ($container->getAliases() as $id => $alias) {
  26. if (!$alias->isPublic()) {
  27. continue;
  28. }
  29. $this->aliasMap[$id] = (string) $alias;
  30. }
  31. foreach ($container->getDefinitions() as $id => $definition) {
  32. $definition->setArguments(
  33. $this->inlineArguments($container, $definition->getArguments())
  34. );
  35. $definition->setMethodCalls(
  36. $this->inlineArguments($container, $definition->getMethodCalls())
  37. );
  38. }
  39. }
  40. protected function inlineArguments(ContainerBuilder $container, array $arguments)
  41. {
  42. foreach ($arguments as $k => $argument) {
  43. if (is_array($argument)) {
  44. $arguments[$k] = $this->inlineArguments($container, $argument);
  45. } else if ($argument instanceof Reference) {
  46. if (!$container->hasDefinition($id = (string) $argument)) {
  47. continue;
  48. }
  49. if ($this->isInlinableDefinition($container, $id, $definition = $container->getDefinition($id))) {
  50. $arguments[$k] = $definition;
  51. }
  52. }
  53. }
  54. return $arguments;
  55. }
  56. protected function isInlinableDefinition(ContainerBuilder $container, $id, Definition $definition)
  57. {
  58. if (!$definition->isShared()) {
  59. return true;
  60. }
  61. if ($definition->isPublic()) {
  62. return false;
  63. }
  64. $references = count(array_keys($this->aliasMap, $id, true));
  65. foreach ($container->getDefinitions() as $cDefinition)
  66. {
  67. if ($references > 1) {
  68. break;
  69. }
  70. if ($this->isReferencedByArgument($id, $cDefinition->getArguments())) {
  71. $references += 1;
  72. continue;
  73. }
  74. foreach ($cDefinition->getMethodCalls() as $call) {
  75. if ($this->isReferencedByArgument($id, $call[1])) {
  76. $references += 1;
  77. continue 2;
  78. }
  79. }
  80. }
  81. return $references <= 1;
  82. }
  83. protected function isReferencedByArgument($id, $argument)
  84. {
  85. if (is_array($argument)) {
  86. foreach ($argument as $arg) {
  87. if ($this->isReferencedByArgument($id, $arg)) {
  88. return true;
  89. }
  90. }
  91. } else if ($argument instanceof Reference) {
  92. if ($id === (string) $argument) {
  93. return true;
  94. }
  95. }
  96. return false;
  97. }
  98. }