Completed
Push — master ( ceccbd...e1228d )
by Tobias
08:59
created

WebUIController::indexAction()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 44

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
dl 0
loc 44
ccs 0
cts 37
cp 0
rs 8.2826
c 0
b 0
f 0
cc 7
nc 8
nop 1
crap 56
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\Exception\BadRequestHttpException;
18
use Symfony\Component\Intl\Intl;
19
use Symfony\Component\Intl\Locales;
20
use Symfony\Component\Translation\MessageCatalogue;
21
use Symfony\Component\Validator\Validator\ValidatorInterface;
22
use Translation\Bundle\Catalogue\CatalogueFetcher;
23
use Translation\Bundle\Catalogue\CatalogueManager;
24
use Translation\Bundle\Exception\MessageValidationException;
25
use Translation\Bundle\Model\CatalogueMessage;
26
use Translation\Bundle\Service\ConfigurationManager;
27
use Translation\Bundle\Service\StorageManager;
28
use Translation\Bundle\Service\StorageService;
29
use Translation\Common\Exception\StorageException;
30
use Translation\Common\Model\Message;
31
use Translation\Common\Model\MessageInterface;
32
33
/**
34
 * @author Tobias Nyholm <[email protected]>
35
 */
36
class WebUIController extends AbstractController
37
{
38
    private $configurationManager;
39
    private $catalogueFetcher;
40
    private $catalogueManager;
41
    private $storageManager;
42
    private $validator;
43
    private $locales;
44
    private $isWebUIEnabled;
45
    private $isWebUIAllowCreate;
46
    private $isWebUIAllowDelete;
47
    private $fileBasePath;
48
49
    public function __construct(
50
        ConfigurationManager $configurationManager,
51
        CatalogueFetcher $catalogueFetcher,
52
        CatalogueManager $catalogueManager,
53
        StorageManager $storageManager,
54
        ValidatorInterface $validator,
55
        array $locales,
56
        bool $isWebUIEnabled,
57
        bool $isWebUIAllowCreate,
58
        bool $isWebUIAllowDelete,
59
        string $fileBasePath
60
    ) {
61
        $this->configurationManager = $configurationManager;
62
        $this->catalogueFetcher = $catalogueFetcher;
63
        $this->catalogueManager = $catalogueManager;
64
        $this->storageManager = $storageManager;
65
        $this->validator = $validator;
66
        $this->locales = $locales;
67
        $this->isWebUIEnabled = $isWebUIEnabled;
68
        $this->isWebUIAllowCreate = $isWebUIAllowCreate;
69
        $this->isWebUIAllowDelete = $isWebUIAllowDelete;
70
        $this->fileBasePath = $fileBasePath;
71
    }
72
73
    /**
74
     * Show a dashboard for the configuration.
75
     */
76
    public function indexAction(?string $configName = null): Response
77
    {
78
        if (!$this->isWebUIEnabled) {
79
            return new Response('You are not allowed here. Check you config. ', 400);
80
        }
81
82
        $config = $this->configurationManager->getConfiguration($configName);
83
        $localeMap = $this->getLocale2LanguageMap();
84
        $catalogues = $this->catalogueFetcher->getCatalogues($config);
85
86
        $catalogueSize = [];
87
        $maxDomainSize = [];
88
        $maxCatalogueSize = 1;
89
90
        // For each catalogue (or locale)
91
        /** @var MessageCatalogue $catalogue */
92
        foreach ($catalogues as $catalogue) {
93
            $locale = $catalogue->getLocale();
94
            $domains = $catalogue->all();
95
            \ksort($domains);
96
            $catalogueSize[$locale] = 0;
97
            foreach ($domains as $domain => $messages) {
98
                $count = \count($messages);
99
                $catalogueSize[$locale] += $count;
100
                if (!isset($maxDomainSize[$domain]) || $count > $maxDomainSize[$domain]) {
101
                    $maxDomainSize[$domain] = $count;
102
                }
103
            }
104
105
            if ($catalogueSize[$locale] > $maxCatalogueSize) {
106
                $maxCatalogueSize = $catalogueSize[$locale];
107
            }
108
        }
109
110
        return $this->render('@Translation/WebUI/index.html.twig', [
111
            'catalogues' => $catalogues,
112
            'catalogueSize' => $catalogueSize,
113
            'maxDomainSize' => $maxDomainSize,
114
            'maxCatalogueSize' => $maxCatalogueSize,
115
            'localeMap' => $localeMap,
116
            'configName' => $config->getName(),
117
            'configNames' => $this->configurationManager->getNames(),
118
        ]);
119
    }
120
121
    /**
122
     * Show a catalogue.
123
     */
124
    public function showAction(string $configName, string $locale, string $domain): Response
125
    {
126
        if (!$this->isWebUIEnabled) {
127
            return new Response('You are not allowed here. Check you config. ', 400);
128
        }
129
        $config = $this->configurationManager->getConfiguration($configName);
130
131
        // Get a catalogue manager and load it with all the catalogues
132
        $this->catalogueManager->load($this->catalogueFetcher->getCatalogues($config));
133
134
        /** @var CatalogueMessage[] $messages */
135
        $messages = $this->catalogueManager->getMessages($locale, $domain);
136
        \usort($messages, function (CatalogueMessage $a, CatalogueMessage $b) {
137
            return \strcmp($a->getKey(), $b->getKey());
138
        });
139
140
        return $this->render('@Translation/WebUI/show.html.twig', [
141
            'messages' => $messages,
142
            'domains' => $this->catalogueManager->getDomains(),
143
            'currentDomain' => $domain,
144
            'locales' => $this->locales,
145
            'currentLocale' => $locale,
146
            'configName' => $config->getName(),
147
            'configNames' => $this->configurationManager->getNames(),
148
            'allow_create' => $this->isWebUIAllowCreate,
149
            'allow_delete' => $this->isWebUIAllowDelete,
150
            'file_base_path' => $this->fileBasePath,
151
        ]);
152
    }
153
154
    public function createAction(Request $request, string $configName, string $locale, string $domain): Response
155
    {
156
        if (!$this->isWebUIEnabled || !$this->isWebUIAllowCreate) {
157
            return new Response('You are not allowed to create. Check you config. ', 400);
158
        }
159
160
        /** @var StorageService $storage */
161
        $storage = $this->storageManager->getStorage($configName);
162
163
        try {
164
            $message = $this->getMessageFromRequest($request);
165
            $message = $message->withDomain($domain);
166
            $message = $message->withLocale($locale);
167
            $this->validateMessage($message, ['Create']);
168
        } catch (MessageValidationException $e) {
169
            return new Response($e->getMessage(), 400);
170
        }
171
172
        try {
173
            $storage->create($message);
174
        } catch (StorageException $e) {
175
            throw new BadRequestHttpException(\sprintf('Key "%s" does already exist for "%s" on domain "%s".', $message->getKey(), $locale, $domain), $e);
176
        }
177
178
        return $this->render('@Translation/WebUI/create.html.twig', [
179
            'message' => $message,
180
        ]);
181
    }
182
183
    public function editAction(Request $request, string $configName, string $locale, string $domain): Response
184
    {
185
        if (!$this->isWebUIEnabled) {
186
            return new Response('You are not allowed here. Check you config. ', 400);
187
        }
188
189
        try {
190
            $message = $this->getMessageFromRequest($request);
191
            $message = $message->withDomain($domain);
192
            $message = $message->withLocale($locale);
193
            $this->validateMessage($message, ['Edit']);
194
        } catch (MessageValidationException $e) {
195
            return new Response($e->getMessage(), 400);
196
        }
197
198
        /** @var StorageService $storage */
199
        $storage = $this->storageManager->getStorage($configName);
200
        $storage->update($message);
201
202
        return new Response('Translation updated');
203
    }
204
205
    public function deleteAction(Request $request, string $configName, string $locale, string $domain): Response
206
    {
207
        if (!$this->isWebUIEnabled || !$this->isWebUIAllowDelete) {
208
            return new Response('You are not allowed to create. Check you config. ', 400);
209
        }
210
211
        try {
212
            $message = $this->getMessageFromRequest($request);
213
            $message = $message->withLocale($locale);
214
            $message = $message->withDomain($domain);
215
            $this->validateMessage($message, ['Delete']);
216
        } catch (MessageValidationException $e) {
217
            return new Response($e->getMessage(), 400);
218
        }
219
220
        /** @var StorageService $storage */
221
        $storage = $this->storageManager->getStorage($configName);
222
        $storage->delete($locale, $domain, $message->getKey());
223
224
        return new Response('Message was deleted');
225
    }
226
227
    private function getMessageFromRequest(Request $request): Message
228
    {
229
        $json = $request->getContent();
230
        $data = \json_decode($json, true);
231
        $message = new Message($data['key']);
232
        if (isset($data['message'])) {
233
            $message = $message->withTranslation($data['message']);
234
        }
235
236
        return $message;
237
    }
238
239
    /**
240
     * This will return a map of our configured locales and their language name.
241
     *
242
     * @return array locale => language
243
     */
244
    private function getLocale2LanguageMap(): array
245
    {
246
        $names = \class_exists(Locales::class)
247
            ? Locales::getNames('en')
248
            : Intl::getLocaleBundle()->getLocaleNames('en');
0 ignored issues
show
Bug introduced by
The method getLocaleBundle() does not seem to exist on object<Symfony\Component\Intl\Intl>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
249
        $map = [];
250
        foreach ($this->locales as $l) {
251
            $map[$l] = $names[$l] ?? $l;
252
        }
253
254
        return $map;
255
    }
256
257
    /**
258
     * @throws MessageValidationException
259
     */
260
    private function validateMessage(MessageInterface $message, array $validationGroups): void
261
    {
262
        $errors = $this->validator->validate($message, null, $validationGroups);
263
        if (\count($errors) > 0) {
264
            throw  MessageValidationException::create();
265
        }
266
    }
267
}
268