vendor/php-translation/symfony-bundle/Controller/WebUIController.php line 79

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