1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the PHP Translation package. |
||
5 | * |
||
6 | * (c) PHP Translation team <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | namespace Translation\Bundle\Controller; |
||
13 | |||
14 | use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
||
15 | use Symfony\Component\HttpFoundation\Request; |
||
16 | use Symfony\Component\HttpFoundation\Response; |
||
17 | use Symfony\Component\HttpKernel\Profiler\Profiler; |
||
18 | use Symfony\Component\Translation\DataCollector\TranslationDataCollector; |
||
19 | use Symfony\Component\Translation\DataCollectorTranslator; |
||
20 | use Symfony\Component\VarDumper\Cloner\Data; |
||
21 | use Translation\Bundle\Model\SfProfilerMessage; |
||
22 | use Translation\Bundle\Service\StorageService; |
||
23 | use Translation\Common\Model\MessageInterface; |
||
24 | |||
25 | /** |
||
26 | * @author Tobias Nyholm <[email protected]> |
||
27 | */ |
||
28 | class SymfonyProfilerController extends AbstractController |
||
29 | { |
||
30 | private $storage; |
||
31 | private $profiler; |
||
32 | private $isToolbarAllowEdit; |
||
33 | |||
34 | public function __construct(StorageService $storage, Profiler $profiler, bool $isToolbarAllowEdit) |
||
35 | { |
||
36 | $this->storage = $storage; |
||
37 | $this->profiler = $profiler; |
||
38 | $this->isToolbarAllowEdit = $isToolbarAllowEdit; |
||
39 | } |
||
40 | |||
41 | public function editAction(Request $request, string $token): Response |
||
42 | { |
||
43 | if (!$this->isToolbarAllowEdit) { |
||
44 | return new Response('You are not allowed to edit the translations.'); |
||
45 | } |
||
46 | |||
47 | if (!$request->isXmlHttpRequest()) { |
||
48 | return $this->redirectToRoute('_profiler', ['token' => $token]); |
||
49 | } |
||
50 | |||
51 | $message = $this->getMessage($request, $token); |
||
52 | |||
53 | if ($request->isMethod('GET')) { |
||
54 | $translation = $this->storage->syncAndFetchMessage($message->getLocale(), $message->getDomain(), $message->getKey()); |
||
55 | |||
56 | return $this->render('@Translation/SymfonyProfiler/edit.html.twig', [ |
||
57 | 'message' => $translation, |
||
58 | 'key' => $request->query->get('message_id'), |
||
59 | ]); |
||
60 | } |
||
61 | |||
62 | //Assert: This is a POST request |
||
63 | $message->setTranslation($request->request->get('translation')); |
||
64 | $this->storage->update($message->convertToMessage()); |
||
65 | |||
66 | return new Response($message->getTranslation()); |
||
67 | } |
||
68 | |||
69 | public function syncAction(Request $request, string $token): Response |
||
70 | { |
||
71 | if (!$request->isXmlHttpRequest()) { |
||
72 | return $this->redirectToRoute('_profiler', ['token' => $token]); |
||
73 | } |
||
74 | |||
75 | $sfMessage = $this->getMessage($request, $token); |
||
76 | $message = $this->storage->syncAndFetchMessage($sfMessage->getLocale(), $sfMessage->getDomain(), $sfMessage->getKey()); |
||
77 | |||
78 | if (null !== $message) { |
||
79 | return new Response($message->getTranslation()); |
||
80 | } |
||
81 | |||
82 | return new Response('Asset not found', 404); |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response |
||
87 | */ |
||
88 | public function syncAllAction(Request $request, string $token): Response |
||
89 | { |
||
90 | if (!$request->isXmlHttpRequest()) { |
||
91 | return $this->redirectToRoute('_profiler', ['token' => $token]); |
||
92 | } |
||
93 | |||
94 | $this->storage->sync(); |
||
95 | |||
96 | return new Response('Started synchronization of all translations'); |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * Save the selected translation to resources. |
||
101 | * |
||
102 | * @author Damien Alexandre (damienalexandre) |
||
103 | */ |
||
104 | public function createAssetsAction(Request $request, string $token): Response |
||
105 | { |
||
106 | if (!$request->isXmlHttpRequest()) { |
||
107 | return $this->redirectToRoute('_profiler', ['token' => $token]); |
||
108 | } |
||
109 | |||
110 | $messages = $this->getSelectedMessages($request, $token); |
||
111 | if (empty($messages)) { |
||
112 | return new Response('No translations selected.'); |
||
113 | } |
||
114 | |||
115 | $uploaded = []; |
||
116 | foreach ($messages as $message) { |
||
117 | $this->storage->create($message); |
||
118 | $uploaded[] = $message; |
||
119 | } |
||
120 | |||
121 | return new Response(\sprintf('%s new assets created!', \count($uploaded))); |
||
122 | } |
||
123 | |||
124 | private function getMessage(Request $request, string $token): SfProfilerMessage |
||
125 | { |
||
126 | $this->profiler->disable(); |
||
127 | |||
128 | $messageId = $request->request->get('message_id', $request->query->get('message_id')); |
||
129 | |||
130 | $collectorMessages = $this->getMessages($token); |
||
131 | |||
132 | if (!isset($collectorMessages[$messageId])) { |
||
133 | throw $this->createNotFoundException(\sprintf('No message with key "%s" was found.', $messageId)); |
||
134 | } |
||
135 | $message = SfProfilerMessage::create($collectorMessages[$messageId]); |
||
136 | |||
137 | if (DataCollectorTranslator::MESSAGE_EQUALS_FALLBACK === $message->getState()) { |
||
138 | /** @var \Symfony\Component\HttpKernel\DataCollector\RequestDataCollector */ |
||
139 | $requestCollector = $this->profiler->loadProfile($token)->getCollector('request'); |
||
140 | |||
141 | $message |
||
142 | ->setLocale($requestCollector->getLocale()) |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
143 | ->setTranslation(\sprintf('[%s]', $message->getTranslation())) |
||
144 | ; |
||
145 | } |
||
146 | |||
147 | return $message; |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * @return MessageInterface[] |
||
152 | */ |
||
153 | protected function getSelectedMessages(Request $request, string $token): array |
||
154 | { |
||
155 | $this->profiler->disable(); |
||
156 | |||
157 | $selected = $request->request->get('selected'); |
||
158 | if (!$selected || 0 == \count($selected)) { |
||
159 | return []; |
||
160 | } |
||
161 | |||
162 | $toSave = \array_intersect_key($this->getMessages($token), \array_flip($selected)); |
||
163 | |||
164 | $messages = []; |
||
165 | foreach ($toSave as $data) { |
||
166 | $messages[] = SfProfilerMessage::create($data)->convertToMessage(); |
||
167 | } |
||
168 | |||
169 | return $messages; |
||
170 | } |
||
171 | |||
172 | private function getMessages(string $token, string $profileName = 'translation'): array |
||
173 | { |
||
174 | $profile = $this->profiler->loadProfile($token); |
||
175 | |||
176 | if (null === $dataCollector = $profile->getCollector($profileName)) { |
||
177 | throw $this->createNotFoundException("No collector with name \"$profileName\" was found."); |
||
178 | } |
||
179 | if (!$dataCollector instanceof TranslationDataCollector) { |
||
180 | throw $this->createNotFoundException("Collector with name \"$profileName\" is not an instance of TranslationDataCollector."); |
||
181 | } |
||
182 | |||
183 | $messages = $dataCollector->getMessages(); |
||
184 | |||
185 | if (\class_exists(Data::class) && $messages instanceof Data) { |
||
0 ignored issues
–
show
|
|||
186 | return $messages->getValue(true); |
||
187 | } |
||
188 | |||
189 | return $messages; |
||
0 ignored issues
–
show
|
|||
190 | } |
||
191 | } |
||
192 |