1<?php
2
3/**
4 * Copyright since 2007 PrestaShop SA and Contributors
5 * PrestaShop is an International Registered Trademark & Property of PrestaShop SA
6 *
7 * NOTICE OF LICENSE
8 *
9 * This source file is subject to the Open Software License (OSL 3.0)
10 * that is bundled with this package in the file LICENSE.md.
11 * It is also available through the world-wide-web at this URL:
12 * https://opensource.org/licenses/OSL-3.0
13 * If you did not receive a copy of the license and are unable to
14 * obtain it through the world-wide-web, please send an email
15 * to license@prestashop.com so we can send you a copy immediately.
16 *
17 * DISCLAIMER
18 *
19 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
20 * versions in the future. If you wish to customize PrestaShop for your
21 * needs please refer to https://devdocs.prestashop.com/ for more information.
22 *
23 * @author    PrestaShop SA and Contributors <contact@prestashop.com>
24 * @copyright Since 2007 PrestaShop SA and Contributors
25 * @license   https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
26 */
27
28namespace PrestaShopBundle\Translation\Loader;
29
30use Doctrine\ORM\EntityManagerInterface;
31use Doctrine\ORM\EntityRepository;
32use Doctrine\ORM\QueryBuilder;
33use PrestaShopBundle\Entity\Lang;
34use PrestaShopBundle\Entity\Translation;
35use Symfony\Component\Translation\Loader\LoaderInterface;
36use Symfony\Component\Translation\MessageCatalogue;
37
38/**
39 * The user translated catalogue is stored in database.
40 * This class is a helper to build the query for retrieving the translations.
41 * They depend on parameters like locale, theme or domain.
42 */
43class DatabaseTranslationLoader implements LoaderInterface
44{
45    /** @var EntityManagerInterface */
46    protected $entityManager;
47
48    /**
49     * @param EntityManagerInterface $entityManager
50     */
51    public function __construct(EntityManagerInterface $entityManager)
52    {
53        $this->entityManager = $entityManager;
54    }
55
56    /**
57     * {@inheritdoc}
58     *
59     * @todo: this method doesn't match the interface
60     */
61    public function load($resource, $locale, $domain = 'messages', $theme = null)
62    {
63        static $langs = [];
64        $catalogue = new MessageCatalogue($locale);
65
66        // do not try and load translations for a locale that cannot be saved to DB anyway
67        if ($locale === 'default') {
68            return $catalogue;
69        }
70
71        if (!array_key_exists($locale, $langs)) {
72            $langs[$locale] = $this->entityManager->getRepository('PrestaShopBundle:Lang')->findOneBy(['locale' => $locale]);
73        }
74
75        /** @var EntityRepository $translationRepository */
76        $translationRepository = $this->entityManager->getRepository('PrestaShopBundle:Translation');
77
78        $queryBuilder = $translationRepository->createQueryBuilder('t');
79
80        $this->addLangConstraint($queryBuilder, $langs[$locale]);
81
82        $this->addThemeConstraint($queryBuilder, $theme);
83
84        $this->addDomainConstraint($queryBuilder, $domain);
85
86        $translations = $queryBuilder
87            ->getQuery()
88            ->getResult();
89
90        /** @var Translation $translation */
91        foreach ($translations as $translation) {
92            $catalogue->set($translation->getKey(), $translation->getTranslation(), $translation->getDomain());
93        }
94
95        return $catalogue;
96    }
97
98    /**
99     * @param QueryBuilder $queryBuilder
100     * @param Lang $currentLang
101     */
102    private function addLangConstraint(QueryBuilder $queryBuilder, Lang $currentLang)
103    {
104        $queryBuilder->andWhere('t.lang =:lang')
105            ->setParameter('lang', $currentLang);
106    }
107
108    /**
109     * @param QueryBuilder $queryBuilder
110     * @param string|null $theme
111     */
112    private function addThemeConstraint(QueryBuilder $queryBuilder, $theme)
113    {
114        if (null === $theme) {
115            $queryBuilder->andWhere('t.theme IS NULL');
116        } else {
117            $queryBuilder
118                ->andWhere('t.theme = :theme')
119                ->setParameter('theme', $theme);
120        }
121    }
122
123    /**
124     * @param QueryBuilder $queryBuilder
125     * @param string $domain
126     */
127    private function addDomainConstraint(QueryBuilder $queryBuilder, $domain)
128    {
129        if ($domain !== '*') {
130            $queryBuilder->andWhere('REGEXP(t.domain, :domain) = true')
131                ->setParameter('domain', $domain);
132        }
133    }
134}
135