PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/classes/Language.php

https://bitbucket.org/marcenuc/prestashop
PHP | 786 lines | 565 code | 99 blank | 122 comment | 134 complexity | c636a1414256f7c4ed02c239c08938f6 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0
  1. <?php
  2. /*
  3. * 2007-2012 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. * http://opensource.org/licenses/osl-3.0.php
  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-2012 PrestaShop SA
  23. * @version Release: $Revision: 7040 $
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. * International Registered Trademark & Property of PrestaShop SA
  26. */
  27. class LanguageCore extends ObjectModel
  28. {
  29. public $id;
  30. /** @var string Name */
  31. public $name;
  32. /** @var string 2-letter iso code */
  33. public $iso_code;
  34. /** @var string 5-letter iso code */
  35. public $language_code;
  36. /** @var string date format http://http://php.net/manual/en/function.date.php with the date only */
  37. public $date_format_lite = 'Y-m-d';
  38. /** @var string date format http://http://php.net/manual/en/function.date.php with hours and minutes */
  39. public $date_format_full = 'Y-m-d H:i:s';
  40. /** @var bool true if this language is right to left language */
  41. public $is_rtl = false;
  42. /** @var boolean Status */
  43. public $active = true;
  44. /**
  45. * @see ObjectModel::$definition
  46. */
  47. public static $definition = array(
  48. 'table' => 'lang',
  49. 'primary' => 'id_lang',
  50. 'fields' => array(
  51. 'name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true, 'size' => 32),
  52. 'iso_code' => array('type' => self::TYPE_STRING, 'validate' => 'isLanguageIsoCode', 'required' => true, 'size' => 2),
  53. 'language_code' => array('type' => self::TYPE_STRING, 'validate' => 'isLanguageCode', 'size' => 5),
  54. 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
  55. 'is_rtl' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
  56. 'date_format_lite' => array('type' => self::TYPE_STRING, 'validate' => 'isPhpDateFormat', 'required' => true, 'size' => 32),
  57. 'date_format_full' => array('type' => self::TYPE_STRING, 'validate' => 'isPhpDateFormat', 'required' => true, 'size' => 32),
  58. ),
  59. );
  60. /** @var array Languages cache */
  61. protected static $_checkedLangs;
  62. protected static $_LANGUAGES;
  63. protected static $countActiveLanguages;
  64. protected $webserviceParameters = array(
  65. 'objectNodeName' => 'language',
  66. 'objectsNodeName' => 'languages',
  67. );
  68. protected $translationsFilesAndVars = array(
  69. 'fields' => '_FIELDS',
  70. 'errors' => '_ERRORS',
  71. 'admin' => '_LANGADM',
  72. 'pdf' => '_LANGPDF',
  73. 'tabs' => 'tabs',
  74. );
  75. public function __construct($id = null, $id_lang = null)
  76. {
  77. parent::__construct($id);
  78. }
  79. /**
  80. * @see ObjectModel::getFields()
  81. * @return array
  82. */
  83. public function getFields()
  84. {
  85. if (empty($this->language_code))
  86. $this->language_code = $this->iso_code;
  87. return parent::getFields();
  88. }
  89. /**
  90. * Generate translations files
  91. *
  92. */
  93. protected function _generateFiles($newIso = null)
  94. {
  95. $iso_code = $newIso ? $newIso : $this->iso_code;
  96. if (!file_exists(_PS_TRANSLATIONS_DIR_.$iso_code))
  97. mkdir(_PS_TRANSLATIONS_DIR_.$iso_code);
  98. foreach ($this->translationsFilesAndVars as $file => $var)
  99. {
  100. $path_file = _PS_TRANSLATIONS_DIR_.$iso_code.'/'.$file.'.php';
  101. if (!file_exists($path_file))
  102. if ($file != 'tabs')
  103. file_put_contents($path_file, '<?php
  104. global $'.$var.';
  105. $'.$var.' = array();
  106. ?>');
  107. else
  108. file_put_contents($path_file, '<?php
  109. $'.$var.' = array();
  110. return $'.$var.';
  111. ?>');
  112. @chmod($path_file, 0777);
  113. }
  114. }
  115. /**
  116. * Move translations files after editiing language iso code
  117. */
  118. public function moveToIso($newIso)
  119. {
  120. if ($newIso == $this->iso_code)
  121. return true;
  122. if (file_exists(_PS_TRANSLATIONS_DIR_.$this->iso_code))
  123. rename(_PS_TRANSLATIONS_DIR_.$this->iso_code, _PS_TRANSLATIONS_DIR_.$newIso);
  124. if (file_exists(_PS_MAIL_DIR_.$this->iso_code))
  125. rename(_PS_MAIL_DIR_.$this->iso_code, _PS_MAIL_DIR_.$newIso);
  126. $modulesList = Module::getModulesDirOnDisk();
  127. foreach ($modulesList as $moduleDir)
  128. {
  129. if (file_exists(_PS_MODULE_DIR_.$moduleDir.'/mails/'.$this->iso_code))
  130. rename(_PS_MODULE_DIR_.$moduleDir.'/mails/'.$this->iso_code, _PS_MODULE_DIR_.$moduleDir.'/mails/'.$newIso);
  131. if (file_exists(_PS_MODULE_DIR_.$moduleDir.'/'.$this->iso_code.'.php'))
  132. rename(_PS_MODULE_DIR_.$moduleDir.'/'.$this->iso_code.'.php', _PS_MODULE_DIR_.$moduleDir.'/'.$newIso.'.php');
  133. }
  134. foreach (Theme::getThemes() as $theme)
  135. {
  136. $theme_dir = $theme->directory;
  137. if (file_exists(_PS_ALL_THEMES_DIR_.$theme_dir.'/lang/'.$this->iso_code.'.php'))
  138. rename(_PS_ALL_THEMES_DIR_.$theme_dir.'/lang/'.$this->iso_code.'.php', _PS_ALL_THEMES_DIR_.$theme_dir.'/lang/'.$newIso.'.php');
  139. if (file_exists(_PS_ALL_THEMES_DIR_.$theme_dir.'/mails/'.$this->iso_code))
  140. rename(_PS_ALL_THEMES_DIR_.$theme_dir.'/mails/'.$this->iso_code, _PS_ALL_THEMES_DIR_.$theme_dir.'/mails/'.$newIso);
  141. foreach ($modulesList as $module)
  142. if (file_exists(_PS_ALL_THEMES_DIR_.$theme_dir.'/modules/'.$module.'/'.$this->iso_code.'.php'))
  143. rename(_PS_ALL_THEMES_DIR_.$theme_dir.'/modules/'.$module.'/'.$this->iso_code.'.php', _PS_ALL_THEMES_DIR_.$theme_dir.'/modules/'.$module.'/'.$newIso.'.php');
  144. }
  145. }
  146. /**
  147. * Return an array of theme
  148. *
  149. * @return array([theme dir] => array('name' => [theme name]))
  150. * @deprecated will be removed in 1.6
  151. */
  152. protected function _getThemesList()
  153. {
  154. Tools::displayAsDeprecated();
  155. static $themes = array();
  156. if (empty($themes))
  157. {
  158. $installed_themes = Theme::getThemes();
  159. foreach ($installed_themes as $theme)
  160. $themes[$theme->directory] = array('name' => $theme->name);
  161. }
  162. return $themes;
  163. }
  164. public function add($autodate = true, $nullValues = false)
  165. {
  166. if (!parent::add($autodate))
  167. return false;
  168. // create empty files if they not exists
  169. $this->_generateFiles();
  170. // @todo Since a lot of modules are not in right format with their primary keys name, just get true ...
  171. $resUpdateSQL = $this->loadUpdateSQL();
  172. $resUpdateSQL = true;
  173. return $resUpdateSQL && Tools::generateHtaccess();
  174. }
  175. public function toggleStatus()
  176. {
  177. if (!parent::toggleStatus())
  178. return false;
  179. return Tools::generateHtaccess();
  180. }
  181. public function checkFiles()
  182. {
  183. return Language::checkFilesWithIsoCode($this->iso_code);
  184. }
  185. /**
  186. * This functions checks if every files exists for the language $iso_code.
  187. * Concerned files are those located in translations/$iso_code/
  188. * and translations/mails/$iso_code .
  189. *
  190. * @param mixed $iso_code
  191. * @returntrue if all files exists
  192. */
  193. public static function checkFilesWithIsoCode($iso_code)
  194. {
  195. if (isset(self::$_checkedLangs[$iso_code]) && self::$_checkedLangs[$iso_code])
  196. return true;
  197. foreach (array_keys(Language::getFilesList($iso_code, _THEME_NAME_, false, false, false, true)) as $key)
  198. if (!file_exists($key))
  199. return false;
  200. self::$_checkedLangs[$iso_code] = true;
  201. return true;
  202. }
  203. public static function getFilesList($iso_from, $theme_from, $iso_to = false, $theme_to = false, $select = false, $check = false, $modules = false)
  204. {
  205. if (empty($iso_from))
  206. die(Tools::displayError());
  207. $copy = ($iso_to && $theme_to) ? true : false;
  208. $lPath_from = _PS_TRANSLATIONS_DIR_.(string)$iso_from.'/';
  209. $tPath_from = _PS_ROOT_DIR_.'/themes/'.(string)$theme_from.'/';
  210. $pPath_from = _PS_ROOT_DIR_.'/themes/'.(string)$theme_from.'/pdf/';
  211. $mPath_from = _PS_MAIL_DIR_.(string)$iso_from.'/';
  212. if ($copy)
  213. {
  214. $lPath_to = _PS_TRANSLATIONS_DIR_.(string)$iso_to.'/';
  215. $tPath_to = _PS_ROOT_DIR_.'/themes/'.(string)$theme_to.'/';
  216. $pPath_to = _PS_ROOT_DIR_.'/themes/'.(string)$theme_to.'/pdf/';
  217. $mPath_to = _PS_MAIL_DIR_.(string)$iso_to.'/';
  218. }
  219. $lFiles = array('admin.php', 'errors.php', 'fields.php', 'pdf.php', 'tabs.php', 'index.php');
  220. // Added natives mails files
  221. $mFiles = array(
  222. 'account.html', 'account.txt',
  223. 'backoffice_order.html', 'backoffice_order.txt',
  224. 'bankwire.html', 'bankwire.txt',
  225. 'cheque.html', 'cheque.txt',
  226. 'contact.html', 'contact.txt',
  227. 'contact_form.html', 'contact_form.txt',
  228. 'credit_slip.html', 'credit_slip.txt',
  229. 'download_product.html', 'download_product.txt', 'download-product.tpl',
  230. 'employee_password.html', 'employee_password.txt',
  231. 'forward_msg.html', 'forward_msg.txt',
  232. 'guest_to_customer.html', 'guest_to_customer.txt',
  233. 'in_transit.html', 'in_transit.txt',
  234. 'log_alert.html', 'log_alert.txt',
  235. 'newsletter.html', 'newsletter.txt',
  236. 'order_canceled.html', 'order_canceled.txt',
  237. 'order_conf.html', 'order_conf.txt',
  238. 'order_customer_comment.html', 'order_customer_comment.txt',
  239. 'order_merchant_comment.html', 'order_merchant_comment.txt',
  240. 'order_return_state.html', 'order_return_state.txt',
  241. 'outofstock.html', 'outofstock.txt',
  242. 'password.html', 'password.txt',
  243. 'password_query.html', 'password_query.txt',
  244. 'payment.html', 'payment.txt',
  245. 'payment_error.html', 'payment_error.txt',
  246. 'preparation.html', 'preparation.txt',
  247. 'refund.html', 'refund.txt',
  248. 'reply_msg.html', 'reply_msg.txt',
  249. 'shipped.html', 'shipped.txt',
  250. 'test.html', 'test.txt',
  251. 'voucher.html', 'voucher.txt',
  252. 'voucher_new.html', 'voucher_new.txt',
  253. 'order_changed.html', 'order_changed.txt', 'index.php'
  254. );
  255. $number = -1;
  256. $files = array();
  257. $files_tr = array();
  258. $files_theme = array();
  259. $files_mail = array();
  260. $files_modules = array();
  261. // When a copy is made from a theme in specific language
  262. // to an other theme for the same language,
  263. // it's avoid to copy Translations, Mails files
  264. // and modules files which are not override by theme.
  265. if (!$copy || $iso_from != $iso_to)
  266. {
  267. // Translations files
  268. if (!$check || ($check && (string)$iso_from != 'en'))
  269. foreach ($lFiles as $file)
  270. $files_tr[$lPath_from.$file] = ($copy ? $lPath_to.$file : ++$number);
  271. if ($select == 'tr')
  272. return $files_tr;
  273. $files = array_merge($files, $files_tr);
  274. // Mail files
  275. if (!$check || ($check && (string)$iso_from != 'en'))
  276. $files_mail[$mPath_from.'lang.php'] = ($copy ? $mPath_to.'lang.php' : ++$number);
  277. foreach ($mFiles as $file)
  278. $files_mail[$mPath_from.$file] = ($copy ? $mPath_to.$file : ++$number);
  279. if ($select == 'mail')
  280. return $files_mail;
  281. $files = array_merge($files, $files_mail);
  282. // Modules
  283. if ($modules)
  284. {
  285. $modList = Module::getModulesDirOnDisk();
  286. foreach ($modList as $mod)
  287. {
  288. $modDir = _PS_MODULE_DIR_.$mod;
  289. // Lang file
  290. if (file_exists($modDir.'/translations/'.(string)$iso_from.'.php'))
  291. $files_modules[$modDir.'/translations/'.(string)$iso_from.'.php'] = ($copy ? $modDir.'/translations/'.(string)$iso_to.'.php' : ++$number);
  292. else if (file_exists($modDir.'/'.(string)$iso_from.'.php'))
  293. $files_modules[$modDir.'/'.(string)$iso_from.'.php'] = ($copy ? $modDir.'/'.(string)$iso_to.'.php' : ++$number);
  294. // Mails files
  295. $modMailDirFrom = $modDir.'/mails/'.(string)$iso_from;
  296. $modMailDirTo = $modDir.'/mails/'.(string)$iso_to;
  297. if (file_exists($modMailDirFrom))
  298. {
  299. $dirFiles = scandir($modMailDirFrom);
  300. foreach ($dirFiles as $file)
  301. if (file_exists($modMailDirFrom.'/'.$file) && $file != '.' && $file != '..' && $file != '.svn')
  302. $files_modules[$modMailDirFrom.'/'.$file] = ($copy ? $modMailDirTo.'/'.$file : ++$number);
  303. }
  304. }
  305. if ($select == 'modules')
  306. return $files_modules;
  307. $files = array_merge($files, $files_modules);
  308. }
  309. }
  310. else if ($select == 'mail' || $select == 'tr')
  311. return $files;
  312. // Theme files
  313. if (!$check || ($check && (string)$iso_from != 'en'))
  314. {
  315. $files_theme[$tPath_from.'lang/'.(string)$iso_from.'.php'] = ($copy ? $tPath_to.'lang/'.(string)$iso_to.'.php' : ++$number);
  316. // Override for pdf files in the theme
  317. if (file_exists($pPath_from.'lang/'.(string)$iso_from.'.php'))
  318. $files_theme[$pPath_from.'lang/'.(string)$iso_from.'.php'] = ($copy ? $pPath_to.'lang/'.(string)$iso_to.'.php' : ++$number);
  319. $module_theme_files = (file_exists($tPath_from.'modules/') ? scandir($tPath_from.'modules/') : array());
  320. foreach ($module_theme_files as $module)
  321. if ($module !== '.' && $module != '..' && $module !== '.svn' && file_exists($tPath_from.'modules/'.$module.'/'.(string)$iso_from.'.php'))
  322. $files_theme[$tPath_from.'modules/'.$module.'/'.(string)$iso_from.'.php'] = ($copy ? $tPath_to.'modules/'.$module.'/'.(string)$iso_to.'.php' : ++$number);
  323. }
  324. if ($select == 'theme')
  325. return $files_theme;
  326. $files = array_merge($files, $files_theme);
  327. // Return
  328. return $files;
  329. }
  330. /**
  331. * loadUpdateSQL will create default lang values when you create a new lang, based on default id lang
  332. *
  333. * @return boolean true if succeed
  334. */
  335. public function loadUpdateSQL()
  336. {
  337. $tables = Db::getInstance()->executeS('SHOW TABLES LIKE \''.str_replace('_', '\\_', _DB_PREFIX_).'%\_lang\' ');
  338. $langTables = array();
  339. foreach ($tables as $table)
  340. foreach ($table as $t)
  341. if ($t != _DB_PREFIX_.'configuration_lang')
  342. $langTables[] = $t;
  343. $return = true;
  344. $shops = Shop::getShopsCollection(false);
  345. foreach ($shops as $shop)
  346. {
  347. $id_lang_default = Configuration::get('PS_LANG_DEFAULT', null, $shop->id_shop_group, $shop->id);
  348. foreach ($langTables as $name)
  349. {
  350. $fields = '';
  351. // We will check if the table contains a column "id_shop"
  352. // If yes, we will add "id_shop" as a WHERE condition in queries copying data from default language
  353. $shop_field_exists = false;
  354. $columns = Db::getInstance()->executeS('SHOW COLUMNS FROM `'.$name.'`');
  355. foreach ($columns as $column)
  356. {
  357. $fields .= $column['Field'].', ';
  358. if ($column['Field'] == 'id_shop')
  359. $shop_field_exists = true;
  360. }
  361. $fields = rtrim($fields, ', ');
  362. preg_match('#^'.preg_quote(_DB_PREFIX_).'(.+)_lang$#i', $name, $m);
  363. $identifier = 'id_'.$m[1];
  364. $sql = 'INSERT IGNORE INTO `'.$name.'` ('.$fields.') (SELECT ';
  365. // For each column, copy data from default language
  366. foreach ($columns as $column)
  367. {
  368. if ($identifier != $column['Field'] && $column['Field'] != 'id_lang')
  369. {
  370. $sql .= '(SELECT `'.$column['Field'].'` FROM `'.$name.'` tl WHERE tl.`id_lang` = '.(int)$id_lang_default
  371. .($shop_field_exists ? ' AND tl.`id_shop` = '.(int)$shop->id : '')
  372. .' AND tl.`'.$identifier.'` = `'.str_replace('_lang', '', $name).'`.`'.$identifier.'`), ';
  373. }
  374. else
  375. $sql .= '`'.$column['Field'].'`, ';
  376. }
  377. $sql = rtrim($sql, ', ');
  378. $sql .= ' FROM `'._DB_PREFIX_.'lang` CROSS JOIN `'.str_replace('_lang', '', $name).'`) ;';
  379. $return &= Db::getInstance()->execute(pSQL($sql));
  380. }
  381. }
  382. return $return;
  383. }
  384. public static function recurseDeleteDir($dir)
  385. {
  386. if (!is_dir($dir))
  387. return false;
  388. if ($handle = @opendir($dir))
  389. {
  390. while (false !== ($file = readdir($handle)))
  391. if ($file != '.' && $file != '..')
  392. {
  393. if (is_dir($dir.'/'.$file))
  394. Language::recurseDeleteDir($dir.'/'.$file);
  395. elseif (file_exists($dir.'/'.$file))
  396. @unlink($dir.'/'.$file);
  397. }
  398. closedir($handle);
  399. }
  400. rmdir($dir);
  401. }
  402. public function delete()
  403. {
  404. if (!$this->hasMultishopEntries())
  405. {
  406. if (empty($this->iso_code))
  407. $this->iso_code = Language::getIsoById($this->id);
  408. // Database translations deletion
  409. $result = Db::getInstance()->executeS('SHOW TABLES FROM `'._DB_NAME_.'`');
  410. foreach ($result as $row)
  411. if (isset($row['Tables_in_'._DB_NAME_]) && !empty($row['Tables_in_'._DB_NAME_]) && preg_match('/_lang/', $row['Tables_in_'._DB_NAME_]))
  412. if (!Db::getInstance()->execute('DELETE FROM `'.$row['Tables_in_'._DB_NAME_].'` WHERE `id_lang` = '.(int)$this->id))
  413. return false;
  414. // Delete tags
  415. Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'tag WHERE id_lang = '.(int)$this->id);
  416. // Delete search words
  417. Db::getInstance()->execute('DELETE FROM '._DB_PREFIX_.'search_word WHERE id_lang = '.(int)$this->id);
  418. // Files deletion
  419. foreach (Language::getFilesList($this->iso_code, _THEME_NAME_, false, false, false, true, true) as $key => $file)
  420. if (file_exists($key))
  421. unlink($key);
  422. $modList = scandir(_PS_MODULE_DIR_);
  423. foreach ($modList as $mod)
  424. {
  425. Language::recurseDeleteDir(_PS_MODULE_DIR_.$mod.'/mails/'.$this->iso_code);
  426. $files = @scandir(_PS_MODULE_DIR_.$mod.'/mails/');
  427. if (count($files) <= 2)
  428. Language::recurseDeleteDir(_PS_MODULE_DIR_.$mod.'/mails/');
  429. if (file_exists(_PS_MODULE_DIR_.$mod.'/'.$this->iso_code.'.php'))
  430. {
  431. unlink(_PS_MODULE_DIR_.$mod.'/'.$this->iso_code.'.php');
  432. $files = @scandir(_PS_MODULE_DIR_.$mod);
  433. if (count($files) <= 2)
  434. Language::recurseDeleteDir(_PS_MODULE_DIR_.$mod);
  435. }
  436. }
  437. if (file_exists(_PS_MAIL_DIR_.$this->iso_code))
  438. Language::recurseDeleteDir(_PS_MAIL_DIR_.$this->iso_code);
  439. if (file_exists(_PS_TRANSLATIONS_DIR_.$this->iso_code))
  440. Language::recurseDeleteDir(_PS_TRANSLATIONS_DIR_.$this->iso_code);
  441. }
  442. if (!parent::delete())
  443. return false;
  444. if (!$this->hasMultishopEntries())
  445. {
  446. // delete images
  447. $files_copy = array(
  448. '/en.jpg',
  449. '/en-default-thickbox_default.jpg',
  450. '/en-default-home_default.jpg',
  451. '/en-default-large_default.jpg',
  452. '/en-default-medium_default.jpg',
  453. '/en-default-small_default.jpg'
  454. );
  455. $tos = array(_PS_CAT_IMG_DIR_, _PS_MANU_IMG_DIR_, _PS_PROD_IMG_DIR_, _PS_SUPP_IMG_DIR_);
  456. foreach ($tos as $to)
  457. foreach ($files_copy as $file)
  458. {
  459. $name = str_replace('/en', ''.$this->iso_code, $file);
  460. if (file_exists($to.$name))
  461. unlink($to.$name);
  462. if (file_exists(dirname(__FILE__).'/../img/l/'.$this->id.'.jpg'))
  463. unlink(dirname(__FILE__).'/../img/l/'.$this->id.'.jpg');
  464. }
  465. }
  466. return Tools::generateHtaccess();
  467. }
  468. public function deleteSelection($selection)
  469. {
  470. if (!is_array($selection))
  471. die(Tools::displayError());
  472. $result = true;
  473. foreach ($selection as $id)
  474. {
  475. $this->id = (int)($id);
  476. $result = $result && $this->delete();
  477. }
  478. Tools::generateHtaccess();
  479. return $result;
  480. }
  481. /**
  482. * Return available languages
  483. *
  484. * @param boolean $active Select only active languages
  485. * @return array Languages
  486. */
  487. public static function getLanguages($active = true, $id_shop = false)
  488. {
  489. if (!self::$_LANGUAGES)
  490. Language::loadLanguages();
  491. $languages = array();
  492. foreach (self::$_LANGUAGES as $language)
  493. {
  494. if ($active && !$language['active'] || ($id_shop && !isset($language['shops'][(int)$id_shop])))
  495. continue;
  496. $languages[] = $language;
  497. }
  498. return $languages;
  499. }
  500. public static function getLanguage($id_lang)
  501. {
  502. if (!array_key_exists((int)($id_lang), self::$_LANGUAGES))
  503. return false;
  504. return self::$_LANGUAGES[(int)($id_lang)];
  505. }
  506. /**
  507. * Return iso code from id
  508. *
  509. * @param integer $id_lang Language ID
  510. * @return string Iso code
  511. */
  512. public static function getIsoById($id_lang)
  513. {
  514. if (isset(self::$_LANGUAGES[(int)$id_lang]['iso_code']))
  515. return self::$_LANGUAGES[(int)$id_lang]['iso_code'];
  516. return false;
  517. }
  518. /**
  519. * Return id from iso code
  520. *
  521. * @param string $iso_code Iso code
  522. * @return integer Language ID
  523. */
  524. public static function getIdByIso($iso_code)
  525. {
  526. if (!Validate::isLanguageIsoCode($iso_code))
  527. die(Tools::displayError('Fatal error: ISO code is not correct').' '.$iso_code);
  528. return Db::getInstance()->getValue('SELECT `id_lang` FROM `'._DB_PREFIX_.'lang` WHERE `iso_code` = \''.pSQL(strtolower($iso_code)).'\'');
  529. }
  530. public static function getLanguageCodeByIso($iso_code)
  531. {
  532. if (!Validate::isLanguageIsoCode($iso_code))
  533. die(Tools::displayError('Fatal error: ISO code is not correct').' '.$iso_code);
  534. return Db::getInstance()->getValue('SELECT `language_code` FROM `'._DB_PREFIX_.'lang` WHERE `iso_code` = \''.pSQL(strtolower($iso_code)).'\'');
  535. }
  536. /**
  537. * Return array (id_lang, iso_code)
  538. *
  539. * @param string $iso_code Iso code
  540. * @return array Language (id_lang, iso_code)
  541. */
  542. public static function getIsoIds($active = true)
  543. {
  544. return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('SELECT `id_lang`, `iso_code` FROM `'._DB_PREFIX_.'lang` '.($active ? 'WHERE active = 1' : ''));
  545. }
  546. public static function copyLanguageData($from, $to)
  547. {
  548. $result = Db::getInstance()->executeS('SHOW TABLES FROM `'._DB_NAME_.'`');
  549. foreach ($result as $row)
  550. if (preg_match('/_lang/', $row['Tables_in_'._DB_NAME_]) && $row['Tables_in_'._DB_NAME_] != _DB_PREFIX_.'lang')
  551. {
  552. $result2 = Db::getInstance()->executeS('SELECT * FROM `'.$row['Tables_in_'._DB_NAME_].'` WHERE `id_lang` = '.(int)$from);
  553. if (!count($result2))
  554. continue;
  555. Db::getInstance()->execute('DELETE FROM `'.$row['Tables_in_'._DB_NAME_].'` WHERE `id_lang` = '.(int)$to);
  556. $query = 'INSERT INTO `'.$row['Tables_in_'._DB_NAME_].'` VALUES ';
  557. foreach ($result2 as $row2)
  558. {
  559. $query .= '(';
  560. $row2['id_lang'] = $to;
  561. foreach ($row2 as $field)
  562. $query .= '\''.pSQL($field, true).'\',';
  563. $query = rtrim($query, ',').'),';
  564. }
  565. $query = rtrim($query, ',');
  566. Db::getInstance()->execute($query);
  567. }
  568. return true;
  569. }
  570. /**
  571. * Load all languages in memory for caching
  572. */
  573. public static function loadLanguages()
  574. {
  575. self::$_LANGUAGES = array();
  576. $sql = 'SELECT l.*, ls.`id_shop`
  577. FROM `'._DB_PREFIX_.'lang` l
  578. LEFT JOIN `'._DB_PREFIX_.'lang_shop` ls ON (l.id_lang = ls.id_lang)';
  579. $result = Db::getInstance()->executeS($sql);
  580. foreach ($result as $row)
  581. {
  582. if (!isset(self::$_LANGUAGES[(int)$row['id_lang']]))
  583. self::$_LANGUAGES[(int)$row['id_lang']] = $row;
  584. self::$_LANGUAGES[(int)$row['id_lang']]['shops'][(int)$row['id_shop']] = true;
  585. }
  586. }
  587. public function update($nullValues = false)
  588. {
  589. if (!parent::update($nullValues))
  590. return false;
  591. return Tools::generateHtaccess();
  592. }
  593. public static function checkAndAddLanguage($iso_code)
  594. {
  595. if (Language::getIdByIso($iso_code))
  596. return true;
  597. else
  598. {
  599. if (@fsockopen('www.prestashop.com', 80))
  600. {
  601. $lang = new Language();
  602. $lang->iso_code = $iso_code;
  603. $lang->active = true;
  604. if ($lang_pack = Tools::jsonDecode(Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/get_language_pack.php?version='._PS_VERSION_.'&iso_lang='.$iso_code)))
  605. {
  606. if (isset($lang_pack->name)
  607. && isset($lang_pack->version)
  608. && isset($lang_pack->iso_code))
  609. $lang->name = $lang_pack->name;
  610. }
  611. if (!$lang->name || !$lang->add())
  612. return false;
  613. $insert_id = (int)$lang->id;
  614. if ($lang_pack)
  615. {
  616. $flag = Tools::file_get_contents('http://www.prestashop.com/download/lang_packs/flags/jpeg/'.$iso_code.'.jpg');
  617. if ($flag != null && !preg_match('/<body>/', $flag))
  618. {
  619. $file = fopen(dirname(__FILE__).'/../img/l/'.$insert_id.'.jpg', 'w');
  620. if ($file)
  621. {
  622. fwrite($file, $flag);
  623. fclose($file);
  624. }
  625. else
  626. Language::_copyNoneFlag($insert_id);
  627. }
  628. else
  629. Language::_copyNoneFlag($insert_id);
  630. }
  631. else
  632. Language::_copyNoneFlag($insert_id);
  633. $files_copy = array(
  634. '/en.jpg',
  635. '/en-default-thickbox_default.jpg',
  636. '/en-default-home_default.jpg',
  637. '/en-default-large_default.jpg',
  638. '/en-default-medium_default.jpg',
  639. '/en-default-small_default.jpg',
  640. '/en-default-scene_default.jpg'
  641. );
  642. foreach (array(_PS_CAT_IMG_DIR_, _PS_MANU_IMG_DIR_, _PS_PROD_IMG_DIR_, _PS_SUPP_IMG_DIR_) as $to)
  643. foreach ($files_copy as $file)
  644. @copy(dirname(__FILE__).'/../img/l'.$file, $to.str_replace('/en', '/'.$iso_code, $file));
  645. return true;
  646. }
  647. else
  648. return false;
  649. }
  650. }
  651. protected static function _copyNoneFlag($id)
  652. {
  653. return copy(dirname(__FILE__).'/../img/l/none.jpg', dirname(__FILE__).'/../img/l/'.$id.'.jpg');
  654. }
  655. protected static $_cache_language_installation = null;
  656. public static function isInstalled($iso_code)
  657. {
  658. if (self::$_cache_language_installation === null)
  659. {
  660. self::$_cache_language_installation = array();
  661. $result = Db::getInstance()->executeS('SELECT `id_lang`, `iso_code` FROM `'._DB_PREFIX_.'lang`');
  662. foreach ($result as $row)
  663. self::$_cache_language_installation[$row['iso_code']] = $row['id_lang'];
  664. }
  665. return (isset(self::$_cache_language_installation[$iso_code]) ? self::$_cache_language_installation[$iso_code] : false);
  666. }
  667. public static function countActiveLanguages()
  668. {
  669. if (!self::$countActiveLanguages)
  670. self::$countActiveLanguages = Db::getInstance()->getValue('
  671. SELECT COUNT(DISTINCT l.id_lang) FROM `'._DB_PREFIX_.'lang` l
  672. '.Shop::addSqlAssociation('lang', 'l').'
  673. WHERE l.`active` = 1
  674. ');
  675. return self::$countActiveLanguages;
  676. }
  677. /**
  678. * Check if more on than one language is activated
  679. *
  680. * @since 1.5.0
  681. * @return bool
  682. */
  683. public static function isMultiLanguageActivated()
  684. {
  685. return (Language::countActiveLanguages() > 1);
  686. }
  687. }