blob: 85b0fa4807190e9eb8751a9ea8231109130af8ee [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\Translation\DependencyInjection;
13
14use Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass;
15use Symfony\Component\DependencyInjection\ContainerBuilder;
16use Symfony\Component\DependencyInjection\Definition;
17use Symfony\Component\DependencyInjection\Reference;
18use Symfony\Component\DependencyInjection\ServiceLocator;
19
20/**
21 * @author Yonel Ceruto <yonelceruto@gmail.com>
22 */
23class TranslatorPathsPass extends AbstractRecursivePass
24{
25 private $translatorServiceId;
26 private $debugCommandServiceId;
27 private $updateCommandServiceId;
28 private $resolverServiceId;
29 private $level = 0;
30 private $paths = [];
31 private $definitions = [];
32 private $controllers = [];
33
34 public function __construct(string $translatorServiceId = 'translator', string $debugCommandServiceId = 'console.command.translation_debug', string $updateCommandServiceId = 'console.command.translation_update', string $resolverServiceId = 'argument_resolver.service')
35 {
36 if (0 < \func_num_args()) {
37 trigger_deprecation('symfony/translation', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
38 }
39
40 $this->translatorServiceId = $translatorServiceId;
41 $this->debugCommandServiceId = $debugCommandServiceId;
42 $this->updateCommandServiceId = $updateCommandServiceId;
43 $this->resolverServiceId = $resolverServiceId;
44 }
45
46 public function process(ContainerBuilder $container)
47 {
48 if (!$container->hasDefinition($this->translatorServiceId)) {
49 return;
50 }
51
52 foreach ($this->findControllerArguments($container) as $controller => $argument) {
53 $id = substr($controller, 0, strpos($controller, ':') ?: \strlen($controller));
54 if ($container->hasDefinition($id)) {
55 [$locatorRef] = $argument->getValues();
56 $this->controllers[(string) $locatorRef][$container->getDefinition($id)->getClass()] = true;
57 }
58 }
59
60 try {
61 parent::process($container);
62
63 $paths = [];
64 foreach ($this->paths as $class => $_) {
65 if (($r = $container->getReflectionClass($class)) && !$r->isInterface()) {
66 $paths[] = $r->getFileName();
67 foreach ($r->getTraits() as $trait) {
68 $paths[] = $trait->getFileName();
69 }
70 }
71 }
72 if ($paths) {
73 if ($container->hasDefinition($this->debugCommandServiceId)) {
74 $definition = $container->getDefinition($this->debugCommandServiceId);
75 $definition->replaceArgument(6, array_merge($definition->getArgument(6), $paths));
76 }
77 if ($container->hasDefinition($this->updateCommandServiceId)) {
78 $definition = $container->getDefinition($this->updateCommandServiceId);
79 $definition->replaceArgument(7, array_merge($definition->getArgument(7), $paths));
80 }
81 }
82 } finally {
83 $this->level = 0;
84 $this->paths = [];
85 $this->definitions = [];
86 }
87 }
88
89 protected function processValue($value, bool $isRoot = false)
90 {
91 if ($value instanceof Reference) {
92 if ((string) $value === $this->translatorServiceId) {
93 for ($i = $this->level - 1; $i >= 0; --$i) {
94 $class = $this->definitions[$i]->getClass();
95
96 if (ServiceLocator::class === $class) {
97 if (!isset($this->controllers[$this->currentId])) {
98 continue;
99 }
100 foreach ($this->controllers[$this->currentId] as $class => $_) {
101 $this->paths[$class] = true;
102 }
103 } else {
104 $this->paths[$class] = true;
105 }
106
107 break;
108 }
109 }
110
111 return $value;
112 }
113
114 if ($value instanceof Definition) {
115 $this->definitions[$this->level++] = $value;
116 $value = parent::processValue($value, $isRoot);
117 unset($this->definitions[--$this->level]);
118
119 return $value;
120 }
121
122 return parent::processValue($value, $isRoot);
123 }
124
125 private function findControllerArguments(ContainerBuilder $container): array
126 {
127 if ($container->hasDefinition($this->resolverServiceId)) {
128 $argument = $container->getDefinition($this->resolverServiceId)->getArgument(0);
129 if ($argument instanceof Reference) {
130 $argument = $container->getDefinition($argument);
131 }
132
133 return $argument->getArgument(0);
134 }
135
136 if ($container->hasDefinition('debug.'.$this->resolverServiceId)) {
137 $argument = $container->getDefinition('debug.'.$this->resolverServiceId)->getArgument(0);
138 if ($argument instanceof Reference) {
139 $argument = $container->getDefinition($argument);
140 }
141 $argument = $argument->getArgument(0);
142 if ($argument instanceof Reference) {
143 $argument = $container->getDefinition($argument);
144 }
145
146 return $argument->getArgument(0);
147 }
148
149 return [];
150 }
151}