PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/PrestaShopBundle/Service/TranslationService.php

https://bitbucket.org/fanch1/testlb
PHP | 344 lines | 199 code | 52 blank | 93 comment | 31 complexity | bb01284ebd4b893694dd3733045cdbb8 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, BSD-2-Clause, GPL-2.0, GPL-3.0
  1. <?php
  2. /**
  3. * 2007-2017 PrestaShop
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * https://opensource.org/licenses/OSL-3.0
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@prestashop.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
  18. * versions in the future. If you wish to customize PrestaShop for your
  19. * needs please refer to http://www.prestashop.com for more information.
  20. *
  21. * @author PrestaShop SA <contact@prestashop.com>
  22. * @copyright 2007-2017 PrestaShop SA
  23. * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
  24. * International Registered Trademark & Property of PrestaShop SA
  25. */
  26. namespace PrestaShopBundle\Service;
  27. use PrestaShopBundle\Entity\Translation;
  28. use PrestaShopBundle\Translation\Constraints\PassVsprintf;
  29. use Symfony\Component\DependencyInjection\Container;
  30. use Symfony\Component\Validator\Validation;
  31. class TranslationService {
  32. /**
  33. * @var Container
  34. */
  35. public $container;
  36. /**
  37. * @param $lang
  38. * @return mixed
  39. */
  40. public function langToLocale($lang)
  41. {
  42. $legacyToStandardLocales = $this->getLangToLocalesMapping();
  43. return $legacyToStandardLocales[$lang];
  44. }
  45. /**
  46. * @param $locale
  47. * @return mixed
  48. * @throws \Exception
  49. */
  50. public function findLanguageByLocale($locale)
  51. {
  52. $doctrine = $this->container->get('doctrine');
  53. $lang = $doctrine->getManager()->getRepository('PrestaShopBundle:Lang')->findOneByLocale($locale);
  54. if (!$lang) {
  55. throw new \Exception('The language for this locale is not available');
  56. }
  57. return $lang;
  58. }
  59. /**
  60. * @return mixed
  61. * @throws \Exception
  62. */
  63. private function getLangToLocalesMapping()
  64. {
  65. $translationsDirectory = $this->getResourcesDirectory();
  66. $legacyToStandardLocalesJson = file_get_contents($translationsDirectory . '/legacy-to-standard-locales.json');
  67. $legacyToStandardLocales = json_decode($legacyToStandardLocalesJson, true);
  68. $jsonLastErrorCode = json_last_error();
  69. if (JSON_ERROR_NONE !== $jsonLastErrorCode) {
  70. throw new \Exception('The legacy to standard locales JSON could not be decoded', $jsonLastErrorCode);
  71. }
  72. return $legacyToStandardLocales;
  73. }
  74. /**
  75. * @return string
  76. */
  77. private function getResourcesDirectory()
  78. {
  79. return $this->container->getParameter('kernel.root_dir') . '/Resources';
  80. }
  81. /**
  82. * @param $lang
  83. * @param $type
  84. * @param $selected
  85. * @param null $search
  86. *
  87. * @return array|mixed
  88. */
  89. public function getTranslationsCatalogue($lang, $type, $selected, $search = null)
  90. {
  91. $factory = $this->container->get('ps.translations_factory');
  92. if ($selected !== 'classic' && $this->requiresThemeTranslationsFactory($selected, $type)) {
  93. $factory = $this->container->get('ps.theme_translations_factory');
  94. }
  95. $locale = $this->langToLocale($lang);
  96. if ($this->requiresThemeTranslationsFactory($selected, $type)) {
  97. if ('classic' === $selected) {
  98. $type = 'front';
  99. } else {
  100. $type = $selected;
  101. }
  102. }
  103. return $factory->createTranslationsArray($type, $locale, $selected, $search);
  104. }
  105. /**
  106. * @param $theme
  107. * @param $type
  108. *
  109. * @return bool
  110. */
  111. private function requiresThemeTranslationsFactory($theme, $type)
  112. {
  113. return $type === 'themes' && !is_null($theme);
  114. }
  115. /**
  116. * List translation for domain
  117. *
  118. * @param $locale
  119. * @param $domain
  120. * @param null $theme
  121. * @param null $search
  122. * @return array
  123. */
  124. public function listDomainTranslation($locale, $domain, $theme = null, $search = null){
  125. if (!empty($theme) && 'classic' !== $theme) {
  126. $translationProvider = $this->container->get('prestashop.translation.theme_provider');
  127. $translationProvider->setThemeName($theme);
  128. } else {
  129. $translationProvider = $this->container->get('prestashop.translation.search_provider');
  130. }
  131. if ('Messages' === $domain){
  132. $domain = 'messages';
  133. }
  134. $translationProvider->setDomain($domain);
  135. $translationProvider->setLocale($locale);
  136. $router = $this->container->get('router');
  137. $domains = array(
  138. 'info' => array(
  139. 'edit_url' => $router->generate('api_translation_value_edit'),
  140. 'reset_url' => $router->generate('api_translation_value_reset'),
  141. ),
  142. 'data' => array(),
  143. );
  144. $treeDomain = preg_split('/(?=[A-Z])/', $domain, -1, PREG_SPLIT_NO_EMPTY);
  145. if (!empty($theme) && 'classic' !== $theme) {
  146. $defaultCatalog = current($translationProvider->getThemeCatalogue()->all());
  147. } else {
  148. $defaultCatalog = current($translationProvider->getDefaultCatalogue()->all());
  149. }
  150. $xliffCatalog = current($translationProvider->getXliffCatalogue()->all());
  151. if ('EmailsSubject' === $domain) {
  152. $theme = 'subject';
  153. }
  154. $dbCatalog = current($translationProvider->getDatabaseCatalogue($theme)->all());
  155. foreach ($defaultCatalog as $key => $message) {
  156. $data = array(
  157. 'default' => $key,
  158. 'xliff' => (array_key_exists($key, (array)$xliffCatalog) ? $xliffCatalog[$key] : null),
  159. 'database' => (array_key_exists($key, (array)$dbCatalog) ? $dbCatalog[$key] : null),
  160. 'tree_domain' => $treeDomain,
  161. );
  162. // if search is empty or is in catalog default|xlf|database
  163. if (empty($search) || $this->dataContainsSearchWord($search, $data)) {
  164. if (empty($data['xliff']) && empty($data['database'])) {
  165. array_unshift($domains['data'], $data);
  166. } else {
  167. array_push($domains['data'], $data);
  168. }
  169. }
  170. }
  171. return $domains;
  172. }
  173. /**
  174. * Check if data contains search word
  175. *
  176. * @param $search
  177. * @param $data
  178. * @return bool
  179. */
  180. private function dataContainsSearchWord($search, $data) {
  181. if (is_string($search)) {
  182. $search = strtolower($search);
  183. return false !== strpos(strtolower($data['default']), $search) ||
  184. false !== strpos(strtolower($data['xliff']), $search) ||
  185. false !== strpos(strtolower($data['database']), $search);
  186. }
  187. if (is_array($search)) {
  188. $contains = true;
  189. foreach ($search as $s) {
  190. $s = strtolower($s);
  191. $contains &= false !== strpos(strtolower($data['default']), $s) ||
  192. false !== strpos(strtolower($data['xliff']), $s) ||
  193. false !== strpos(strtolower($data['database']), $s);
  194. }
  195. return $contains;
  196. }
  197. return false;
  198. }
  199. /**
  200. * Save a translation in database
  201. *
  202. * @param $lang
  203. * @param $domain
  204. * @param $key
  205. * @param $translationValue
  206. * @param null $theme
  207. * @return bool
  208. */
  209. public function saveTranslationMessage($lang, $domain, $key, $translationValue, $theme = null)
  210. {
  211. $doctrine = $this->container->get('doctrine');
  212. $entityManager = $doctrine->getManager();
  213. $logger = $this->container->get('logger');
  214. if (empty($theme)) {
  215. $theme = null;
  216. }
  217. $translation = $entityManager->getRepository('PrestaShopBundle:Translation')
  218. ->findOneBy(array(
  219. 'lang' => $lang,
  220. 'domain' => $domain,
  221. 'key' => $key,
  222. 'theme' => $theme
  223. ));
  224. if (is_null($translation)) {
  225. $translation = new Translation();
  226. $translation->setDomain($domain);
  227. $translation->setLang($lang);
  228. $translation->setKey(htmlspecialchars_decode($key, ENT_QUOTES));
  229. $translation->setTranslation($translationValue);
  230. if (!empty($theme)) {
  231. $translation->setTheme($theme);
  232. }
  233. } else {
  234. if (!empty($theme)) {
  235. $translation->setTheme($theme);
  236. }
  237. $translation->setTranslation($translationValue);
  238. }
  239. $validator = Validation::createValidator();
  240. $violations = $validator->validate($translation, new PassVsprintf());
  241. if (0 !== count($violations)) {
  242. foreach ($violations as $violation) {
  243. $logger->error($violation->getMessage());
  244. }
  245. return false;
  246. }
  247. $updatedTranslationSuccessfully = false;
  248. try {
  249. $entityManager->persist($translation);
  250. $entityManager->flush();
  251. $updatedTranslationSuccessfully = true;
  252. } catch (\Exception $exception) {
  253. $logger->error($exception->getMessage());
  254. }
  255. return $updatedTranslationSuccessfully;
  256. }
  257. /**
  258. * Reset translation from database
  259. *
  260. * @param $lang
  261. * @param $domain
  262. * @param $key
  263. * @param null $theme
  264. * @return bool
  265. */
  266. public function resetTranslationMessage($lang, $domain, $key, $theme = null)
  267. {
  268. $doctrine = $this->container->get('doctrine');
  269. $entityManager = $doctrine->getManager();
  270. $searchTranslation = array(
  271. 'lang' => $lang,
  272. 'domain' => $domain,
  273. 'key' => $key,
  274. );
  275. if (!empty($theme)) {
  276. $searchTranslation['theme'] = $theme;
  277. }
  278. $translation = $entityManager->getRepository('PrestaShopBundle:Translation')->findOneBy($searchTranslation);
  279. $resetTranslationSuccessfully = false;
  280. if (is_null($translation)) {
  281. $resetTranslationSuccessfully = true;
  282. }
  283. try {
  284. $entityManager->remove($translation);
  285. $entityManager->flush();
  286. $resetTranslationSuccessfully = true;
  287. } catch (\Exception $exception) {
  288. $this->container->get('logger')->error($exception->getMessage());
  289. }
  290. return $resetTranslationSuccessfully;
  291. }
  292. }