Advertisement
Guest User

Untitled

a guest
Jan 10th, 2015
351
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 100.34 KB | None | 0 0
  1. <?php
  2. /*
  3. * 2007-2014 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-2014 PrestaShop SA
  23. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  24. * International Registered Trademark & Property of PrestaShop SA
  25. */
  26.  
  27. class ToolsCore
  28. {
  29. protected static $file_exists_cache = array();
  30. protected static $_forceCompile;
  31. protected static $_caching;
  32. protected static $_user_plateform;
  33. protected static $_user_browser;
  34.  
  35. /**
  36. * Random password generator
  37. *
  38. * @param integer $length Desired length (optional)
  39. * @param string $flag Output type (NUMERIC, ALPHANUMERIC, NO_NUMERIC)
  40. * @return string Password
  41. */
  42. public static function passwdGen($length = 8, $flag = 'ALPHANUMERIC')
  43. {
  44. switch ($flag)
  45. {
  46. case 'NUMERIC':
  47. $str = '0123456789';
  48. break;
  49. case 'NO_NUMERIC':
  50. $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  51. break;
  52. default:
  53. $str = 'abcdefghijkmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  54. break;
  55. }
  56.  
  57. for ($i = 0, $passwd = ''; $i < $length; $i++)
  58. $passwd .= Tools::substr($str, mt_rand(0, Tools::strlen($str) - 1), 1);
  59. return $passwd;
  60. }
  61.  
  62. public static function strReplaceFirst($search, $replace, $subject, $cur = 0)
  63. {
  64. return (strpos($subject, $search, $cur))?substr_replace($subject, $replace, (int)strpos($subject, $search, $cur), strlen($search)):$subject;
  65. }
  66.  
  67. /**
  68. * Redirect user to another page
  69. *
  70. * @param string $url Desired URL
  71. * @param string $baseUri Base URI (optional)
  72. * @param Link $link
  73. * @param string|array $headers A list of headers to send before redirection
  74. */
  75. public static function redirect($url, $base_uri = __PS_BASE_URI__, Link $link = null, $headers = null)
  76. {
  77. if (!$link)
  78. $link = Context::getContext()->link;
  79.  
  80. if (strpos($url, 'http://') === false && strpos($url, 'https://') === false && $link)
  81. {
  82. if (strpos($url, $base_uri) === 0)
  83. $url = substr($url, strlen($base_uri));
  84. if (strpos($url, 'index.php?controller=') !== false && strpos($url, 'index.php/') == 0)
  85. {
  86. $url = substr($url, strlen('index.php?controller='));
  87. if (Configuration::get('PS_REWRITING_SETTINGS'))
  88. $url = Tools::strReplaceFirst('&', '?', $url);
  89. }
  90.  
  91. $explode = explode('?', $url);
  92. // don't use ssl if url is home page
  93. // used when logout for example
  94. $use_ssl = !empty($url);
  95. $url = $link->getPageLink($explode[0], $use_ssl);
  96. if (isset($explode[1]))
  97. $url .= '?'.$explode[1];
  98. }
  99.  
  100. // Send additional headers
  101. if ($headers)
  102. {
  103. if (!is_array($headers))
  104. $headers = array($headers);
  105.  
  106. foreach ($headers as $header)
  107. header($header);
  108. }
  109.  
  110. header('Location: '.$url);
  111. exit;
  112. }
  113.  
  114. /**
  115. * Redirect URLs already containing PS_BASE_URI
  116. *
  117. * @param string $url Desired URL
  118. */
  119. public static function redirectLink($url)
  120. {
  121. if (!preg_match('@^https?://@i', $url))
  122. {
  123. if (strpos($url, __PS_BASE_URI__) !== false && strpos($url, __PS_BASE_URI__) == 0)
  124. $url = substr($url, strlen(__PS_BASE_URI__));
  125. if (strpos($url, 'index.php?controller=') !== false && strpos($url, 'index.php/') == 0)
  126. $url = substr($url, strlen('index.php?controller='));
  127. $explode = explode('?', $url);
  128. $url = Context::getContext()->link->getPageLink($explode[0]);
  129. if (isset($explode[1]))
  130. $url .= '?'.$explode[1];
  131. }
  132. header('Location: '.$url);
  133. exit;
  134. }
  135.  
  136. /**
  137. * Redirect user to another admin page
  138. *
  139. * @param string $url Desired URL
  140. */
  141. public static function redirectAdmin($url)
  142. {
  143. header('Location: '.$url);
  144. exit;
  145. }
  146.  
  147. /**
  148. * getShopProtocol return the available protocol for the current shop in use
  149. * SSL if Configuration is set on and available for the server
  150. * @static
  151. * @return String
  152. */
  153. public static function getShopProtocol()
  154. {
  155. $protocol = (Configuration::get('PS_SSL_ENABLED') || (!empty($_SERVER['HTTPS'])
  156. && Tools::strtolower($_SERVER['HTTPS']) != 'off')) ? 'https://' : 'http://';
  157. return $protocol;
  158. }
  159.  
  160. /**
  161. * getProtocol return the set protocol according to configuration (http[s])
  162. * @param bool $use_ssl true if require ssl
  163. * @return String (http|https)
  164. */
  165. public static function getProtocol($use_ssl = null)
  166. {
  167. return (!is_null($use_ssl) && $use_ssl ? 'https://' : 'http://');
  168. }
  169.  
  170. /**
  171. * getHttpHost return the <b>current</b> host used, with the protocol (http or https) if $http is true
  172. * This function should not be used to choose http or https domain name.
  173. * Use Tools::getShopDomain() or Tools::getShopDomainSsl instead
  174. *
  175. * @param boolean $http
  176. * @param boolean $entities
  177. * @return string host
  178. */
  179. public static function getHttpHost($http = false, $entities = false, $ignore_port = false)
  180. {
  181. $host = (isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : $_SERVER['HTTP_HOST']);
  182. if ($ignore_port && $pos = strpos($host, ':'))
  183. $host = substr($host, 0, $pos);
  184. if ($entities)
  185. $host = htmlspecialchars($host, ENT_COMPAT, 'UTF-8');
  186. if ($http)
  187. $host = (Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$host;
  188. return $host;
  189. }
  190.  
  191. /**
  192. * getShopDomain returns domain name according to configuration and ignoring ssl
  193. *
  194. * @param boolean $http if true, return domain name with protocol
  195. * @param boolean $entities if true,
  196. * @return string domain
  197. */
  198. public static function getShopDomain($http = false, $entities = false)
  199. {
  200. if (!$domain = ShopUrl::getMainShopDomain())
  201. $domain = Tools::getHttpHost();
  202. if ($entities)
  203. $domain = htmlspecialchars($domain, ENT_COMPAT, 'UTF-8');
  204. if ($http)
  205. $domain = 'http://'.$domain;
  206. return $domain;
  207. }
  208.  
  209. /**
  210. * getShopDomainSsl returns domain name according to configuration and depending on ssl activation
  211. *
  212. * @param boolean $http if true, return domain name with protocol
  213. * @param boolean $entities if true,
  214. * @return string domain
  215. */
  216. public static function getShopDomainSsl($http = false, $entities = false)
  217. {
  218. if (!$domain = ShopUrl::getMainShopDomainSSL())
  219. $domain = Tools::getHttpHost();
  220. if ($entities)
  221. $domain = htmlspecialchars($domain, ENT_COMPAT, 'UTF-8');
  222. if ($http)
  223. $domain = (Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$domain;
  224. return $domain;
  225. }
  226.  
  227. /**
  228. * Get the server variable SERVER_NAME
  229. *
  230. * @return string server name
  231. */
  232. public static function getServerName()
  233. {
  234. if (isset($_SERVER['HTTP_X_FORWARDED_SERVER']) && $_SERVER['HTTP_X_FORWARDED_SERVER'])
  235. return $_SERVER['HTTP_X_FORWARDED_SERVER'];
  236. return $_SERVER['SERVER_NAME'];
  237. }
  238.  
  239. /**
  240. * Get the server variable REMOTE_ADDR, or the first ip of HTTP_X_FORWARDED_FOR (when using proxy)
  241. *
  242. * @return string $remote_addr ip of client
  243. */
  244. public static function getRemoteAddr()
  245. {
  246. // This condition is necessary when using CDN, don't remove it.
  247. if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] && (!isset($_SERVER['REMOTE_ADDR']) || preg_match('/^127\..*/i', trim($_SERVER['REMOTE_ADDR'])) || preg_match('/^172\.16.*/i', trim($_SERVER['REMOTE_ADDR'])) || preg_match('/^192\.168\.*/i', trim($_SERVER['REMOTE_ADDR'])) || preg_match('/^10\..*/i', trim($_SERVER['REMOTE_ADDR']))))
  248. {
  249. if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ','))
  250. {
  251. $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
  252. return $ips[0];
  253. }
  254. else
  255. return $_SERVER['HTTP_X_FORWARDED_FOR'];
  256. }
  257. return $_SERVER['REMOTE_ADDR'];
  258. }
  259.  
  260. /**
  261. * Check if the current page use SSL connection on not
  262. *
  263. * @return bool uses SSL
  264. */
  265. public static function usingSecureMode()
  266. {
  267. if (isset($_SERVER['HTTPS']))
  268. return in_array(Tools::strtolower($_SERVER['HTTPS']), array(1, 'on'));
  269. // $_SERVER['SSL'] exists only in some specific configuration
  270. if (isset($_SERVER['SSL']))
  271. return in_array(Tools::strtolower($_SERVER['SSL']), array(1, 'on'));
  272. // $_SERVER['REDIRECT_HTTPS'] exists only in some specific configuration
  273. if (isset($_SERVER['REDIRECT_HTTPS']))
  274. return in_array(Tools::strtolower($_SERVER['REDIRECT_HTTPS']), array(1, 'on'));
  275. if (isset($_SERVER['HTTP_SSL']))
  276. return in_array(Tools::strtolower($_SERVER['HTTP_SSL']), array(1, 'on'));
  277.  
  278. return false;
  279. }
  280.  
  281. /**
  282. * Get the current url prefix protocol (https/http)
  283. *
  284. * @return string protocol
  285. */
  286. public static function getCurrentUrlProtocolPrefix()
  287. {
  288. if (Tools::usingSecureMode())
  289. return 'https://';
  290. else
  291. return 'http://';
  292. }
  293.  
  294. /**
  295. * Secure an URL referrer
  296. *
  297. * @param string $referrer URL referrer
  298. * @return string secured referrer
  299. */
  300. public static function secureReferrer($referrer)
  301. {
  302. if (preg_match('/^http[s]?:\/\/'.Tools::getServerName().'(:'._PS_SSL_PORT_.')?\/.*$/Ui', $referrer))
  303. return $referrer;
  304. return __PS_BASE_URI__;
  305. }
  306.  
  307. /**
  308. * Get a value from $_POST / $_GET
  309. * if unavailable, take a default value
  310. *
  311. * @param string $key Value key
  312. * @param mixed $default_value (optional)
  313. * @return mixed Value
  314. */
  315. public static function getValue($key, $default_value = false)
  316. {
  317. if (!isset($key) || empty($key) || !is_string($key))
  318. return false;
  319. $ret = (isset($_POST[$key]) ? $_POST[$key] : (isset($_GET[$key]) ? $_GET[$key] : $default_value));
  320.  
  321. if (is_string($ret) === true)
  322. $ret = urldecode(preg_replace('/((\%5C0+)|(\%00+))/i', '', urlencode($ret)));
  323. return !is_string($ret)? $ret : stripslashes($ret);
  324. }
  325.  
  326. public static function getIsset($key)
  327. {
  328. if (!isset($key) || empty($key) || !is_string($key))
  329. return false;
  330. return isset($_POST[$key]) ? true : (isset($_GET[$key]) ? true : false);
  331. }
  332.  
  333. /**
  334. * Change language in cookie while clicking on a flag
  335. *
  336. * @return string iso code
  337. */
  338. public static function setCookieLanguage($cookie = null)
  339. {
  340. if (!$cookie)
  341. $cookie = Context::getContext()->cookie;
  342. /* If language does not exist or is disabled, erase it */
  343. if ($cookie->id_lang)
  344. {
  345. $lang = new Language((int)$cookie->id_lang);
  346. if (!Validate::isLoadedObject($lang) || !$lang->active || !$lang->isAssociatedToShop())
  347. $cookie->id_lang = null;
  348. }
  349.  
  350. if (!Configuration::get('PS_DETECT_LANG'))
  351. unset($cookie->detect_language);
  352.  
  353. /* Automatically detect language if not already defined, detect_language is set in Cookie::update */
  354. if ((!$cookie->id_lang || isset($cookie->detect_language)) && isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
  355. {
  356. $array = explode(',', Tools::strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));
  357. $string = $array[0];
  358.  
  359. if (Validate::isLanguageCode($string))
  360. {
  361. $lang = Language::getLanguageByIETFCode($string);
  362. if (Validate::isLoadedObject($lang) && $lang->active && $lang->isAssociatedToShop())
  363. {
  364. Context::getContext()->language = $lang;
  365. $cookie->id_lang = (int)$lang->id;
  366. }
  367. }
  368. }
  369.  
  370. if (isset($cookie->detect_language))
  371. unset($cookie->detect_language);
  372.  
  373. /* If language file not present, you must use default language file */
  374. if (!$cookie->id_lang || !Validate::isUnsignedId($cookie->id_lang))
  375. $cookie->id_lang = (int)Configuration::get('PS_LANG_DEFAULT');
  376.  
  377. $iso = Language::getIsoById((int)$cookie->id_lang);
  378. @include_once(_PS_THEME_DIR_.'lang/'.$iso.'.php');
  379.  
  380. return $iso;
  381. }
  382.  
  383. /**
  384. * Set cookie id_lang
  385. */
  386. public static function switchLanguage(Context $context = null)
  387. {
  388. if (!$context)
  389. $context = Context::getContext();
  390.  
  391. // Install call the dispatcher and so the switchLanguage
  392. // Stop this method by checking the cookie
  393. if (!isset($context->cookie))
  394. return;
  395.  
  396. if (($iso = Tools::getValue('isolang')) && Validate::isLanguageIsoCode($iso) && ($id_lang = (int)Language::getIdByIso($iso)))
  397. $_GET['id_lang'] = $id_lang;
  398.  
  399. // update language only if new id is different from old id
  400. // or if default language changed
  401. $cookie_id_lang = $context->cookie->id_lang;
  402. $configuration_id_lang = Configuration::get('PS_LANG_DEFAULT');
  403. if ((($id_lang = (int)Tools::getValue('id_lang')) && Validate::isUnsignedId($id_lang) && $cookie_id_lang != (int)$id_lang)
  404. || (($id_lang == $configuration_id_lang) && Validate::isUnsignedId($id_lang) && $id_lang != $cookie_id_lang))
  405. {
  406. $context->cookie->id_lang = $id_lang;
  407. $language = new Language($id_lang);
  408. if (Validate::isLoadedObject($language) && $language->active)
  409. $context->language = $language;
  410.  
  411. $params = $_GET;
  412. if (Configuration::get('PS_REWRITING_SETTINGS') || !Language::isMultiLanguageActivated())
  413. unset($params['id_lang']);
  414. }
  415. }
  416.  
  417. public static function getCountry($address = null)
  418. {
  419. if ($id_country = Tools::getValue('id_country'));
  420. elseif (isset($address) && isset($address->id_country) && $address->id_country)
  421. $id_country = $address->id_country;
  422. elseif (Configuration::get('PS_DETECT_COUNTRY') && isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
  423. {
  424. preg_match("#(?<=-)\w\w|\w\w(?!-)#", $_SERVER['HTTP_ACCEPT_LANGUAGE'], $array);
  425. if (is_array($array) && isset($array[0]) && Validate::isLanguageIsoCode($array[0]))
  426. $id_country = Country::getByIso($array[0], true);
  427. }
  428. if (!isset($id_country) || !$id_country)
  429. $id_country = Configuration::get('PS_COUNTRY_DEFAULT');
  430. return (int)$id_country;
  431. }
  432.  
  433. /**
  434. * Set cookie currency from POST or default currency
  435. *
  436. * @return Currency object
  437. */
  438. public static function setCurrency($cookie)
  439. {
  440. if (Tools::isSubmit('SubmitCurrency') && ($id_currency = Tools::getValue('id_currency')))
  441. {
  442. $currency = Currency::getCurrencyInstance((int)$id_currency);
  443. if (is_object($currency) && $currency->id && !$currency->deleted && $currency->isAssociatedToShop())
  444. $cookie->id_currency = (int)$currency->id;
  445. }
  446.  
  447. $currency = null;
  448. if ((int)$cookie->id_currency)
  449. $currency = Currency::getCurrencyInstance((int)$cookie->id_currency);
  450. if (!Validate::isLoadedObject($currency) || (bool)$currency->deleted || !(bool)$currency->active)
  451. $currency = Currency::getCurrencyInstance(Configuration::get('PS_CURRENCY_DEFAULT'));
  452.  
  453. $cookie->id_currency = (int)$currency->id;
  454. if ($currency->isAssociatedToShop())
  455. return $currency;
  456. else
  457. {
  458. // get currency from context
  459. $currency = Shop::getEntityIds('currency', Context::getContext()->shop->id, true, true);
  460. if (isset($currency[0]) && $currency[0]['id_currency'])
  461. {
  462. $cookie->id_currency = $currency[0]['id_currency'];
  463. return Currency::getCurrencyInstance((int)$cookie->id_currency);
  464. }
  465. }
  466.  
  467. return $currency;
  468. }
  469.  
  470. /**
  471. * Return price with currency sign for a given product
  472. *
  473. * @param float $price Product price
  474. * @param object|array $currency Current currency (object, id_currency, NULL => context currency)
  475. * @return string Price correctly formated (sign, decimal separator...)
  476. */
  477. public static function displayPrice($price, $currency = null, $no_utf8 = false, Context $context = null)
  478. {
  479. if (!is_numeric($price))
  480. return $price;
  481. if (!$context)
  482. $context = Context::getContext();
  483. if ($currency === null)
  484. $currency = $context->currency;
  485. // if you modified this function, don't forget to modify the Javascript function formatCurrency (in tools.js)
  486. elseif (is_int($currency))
  487. $currency = Currency::getCurrencyInstance((int)$currency);
  488.  
  489. if (is_array($currency))
  490. {
  491. $c_char = $currency['sign'];
  492. $c_format = $currency['format'];
  493. $c_decimals = (int)$currency['decimals'] * _PS_PRICE_DISPLAY_PRECISION_;
  494. $c_blank = $currency['blank'];
  495. }
  496. elseif (is_object($currency))
  497. {
  498. $c_char = $currency->sign;
  499. $c_format = $currency->format;
  500. $c_decimals = (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_;
  501. $c_blank = $currency->blank;
  502. }
  503. else
  504. return false;
  505.  
  506. $blank = ($c_blank ? ' ' : '');
  507. $ret = 0;
  508. if (($is_negative = ($price < 0)))
  509. $price *= -1;
  510. $price = Tools::ps_round($price, $c_decimals);
  511.  
  512. /*
  513. * If the language is RTL and the selected currency format contains spaces as thousands separator
  514. * then the number will be printed in reverse since the space is interpreted as separating words.
  515. * To avoid this we replace the currency format containing a space with the one containing a comma (,) as thousand
  516. * separator when the language is RTL.
  517. *
  518. * TODO: This is not ideal, a currency format should probably be tied to a language, not to a currency.
  519. */
  520. if(($c_format == 2) && ($context->language->is_rtl == 1))
  521. {
  522. $c_format = 4;
  523. }
  524.  
  525. switch ($c_format)
  526. {
  527. /* X 0,000.00 */
  528. case 1:
  529. $ret = $c_char.$blank.number_format($price, $c_decimals, '.', ',');
  530. break;
  531. /* 0 000,00 X*/
  532. case 2:
  533. $ret = number_format($price, $c_decimals, ',', ' ').$blank.$c_char;
  534. break;
  535. /* X 0.000,00 */
  536. case 3:
  537. $ret = $c_char.$blank.number_format($price, $c_decimals, ',', '.');
  538. break;
  539. /* 0,000.00 X */
  540. case 4:
  541. $ret = number_format($price, $c_decimals, '.', ',').$blank.$c_char;
  542. break;
  543. /* X 0'000.00 Added for the switzerland currency */
  544. case 5:
  545. $ret = $c_char.$blank.number_format($price, $c_decimals, '.', "'");
  546. break;
  547. }
  548. if ($is_negative)
  549. $ret = '-'.$ret;
  550. if ($no_utf8)
  551. return str_replace('€', chr(128), $ret);
  552. return $ret;
  553. }
  554.  
  555. // Just to fix a bug
  556. // Need real CLDR functions
  557. public static function displayNumber($number, $currency)
  558. {
  559. if (is_array($currency))
  560. $format = $currency['format'];
  561. elseif (is_object($currency))
  562. $format = $currency->format;
  563.  
  564. return number_format($number, 0, '.', in_array($format, array(1, 4)) ? ',': ' ');
  565. }
  566.  
  567. public static function displayPriceSmarty($params, &$smarty)
  568. {
  569. if (array_key_exists('currency', $params))
  570. {
  571. $currency = Currency::getCurrencyInstance((int)($params['currency']));
  572. if (Validate::isLoadedObject($currency))
  573. return Tools::displayPrice($params['price'], $currency, false);
  574. }
  575. return Tools::displayPrice($params['price']);
  576. }
  577.  
  578. /**
  579. * Return price converted
  580. *
  581. * @param float $price Product price
  582. * @param object|array $currency Current currency object
  583. * @param boolean $to_currency convert to currency or from currency to default currency
  584. * @param Context $context
  585. * @return float Price
  586. */
  587. public static function convertPrice($price, $currency = null, $to_currency = true, Context $context = null)
  588. {
  589. static $default_currency = null;
  590.  
  591. if ($default_currency === null)
  592. $default_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT');
  593.  
  594. if (!$context)
  595. $context = Context::getContext();
  596. if ($currency === null)
  597. $currency = $context->currency;
  598. elseif (is_numeric($currency))
  599. $currency = Currency::getCurrencyInstance($currency);
  600.  
  601. $c_id = (is_array($currency) ? $currency['id_currency'] : $currency->id);
  602. $c_rate = (is_array($currency) ? $currency['conversion_rate'] : $currency->conversion_rate);
  603.  
  604. if ($c_id != $default_currency)
  605. {
  606. if ($to_currency)
  607. $price *= $c_rate;
  608. else
  609. $price /= $c_rate;
  610. }
  611.  
  612. return $price;
  613. }
  614.  
  615. /**
  616. *
  617. * Convert amount from a currency to an other currency automatically
  618. * @param float $amount
  619. * @param Currency $currency_from if null we used the default currency
  620. * @param Currency $currency_to if null we used the default currency
  621. */
  622. public static function convertPriceFull($amount, Currency $currency_from = null, Currency $currency_to = null)
  623. {
  624. if ($currency_from === $currency_to)
  625. return $amount;
  626.  
  627. if ($currency_from === null)
  628. $currency_from = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
  629.  
  630. if ($currency_to === null)
  631. $currency_to = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
  632.  
  633. if ($currency_from->id == Configuration::get('PS_CURRENCY_DEFAULT'))
  634. $amount *= $currency_to->conversion_rate;
  635. else
  636. {
  637. $conversion_rate = ($currency_from->conversion_rate == 0 ? 1 : $currency_from->conversion_rate);
  638. // Convert amount to default currency (using the old currency rate)
  639. $amount = $amount / $conversion_rate;
  640. // Convert to new currency
  641. $amount *= $currency_to->conversion_rate;
  642. }
  643. return Tools::ps_round($amount, _PS_PRICE_DISPLAY_PRECISION_);
  644. }
  645.  
  646. /**
  647. * Display date regarding to language preferences
  648. *
  649. * @param array $params Date, format...
  650. * @param object $smarty Smarty object for language preferences
  651. * @return string Date
  652. */
  653. public static function dateFormat($params, &$smarty)
  654. {
  655. return Tools::displayDate($params['date'], null, (isset($params['full']) ? $params['full'] : false));
  656. }
  657.  
  658. /**
  659. * Display date regarding to language preferences
  660. *
  661. * @param string $date Date to display format UNIX
  662. * @param integer $id_lang Language id DEPRECATED
  663. * @param boolean $full With time or not (optional)
  664. * @param string $separator DEPRECATED
  665. * @return string Date
  666. */
  667. public static function displayDate($date, $id_lang = null, $full = false, $separator = null)
  668. {
  669. if ($id_lang !== null)
  670. Tools::displayParameterAsDeprecated('id_lang');
  671. if ($separator !== null)
  672. Tools::displayParameterAsDeprecated('separator');
  673.  
  674. if (!$date || !($time = strtotime($date)))
  675. return $date;
  676.  
  677. if ($date == '0000-00-00 00:00:00' || $date == '0000-00-00')
  678. return '';
  679.  
  680. if (!Validate::isDate($date) || !Validate::isBool($full))
  681. throw new PrestaShopException('Invalid date');
  682.  
  683. $context = Context::getContext();
  684. $date_format = ($full ? $context->language->date_format_full : $context->language->date_format_lite);
  685. return date($date_format, $time);
  686. }
  687.  
  688. /**
  689. * Sanitize a string
  690. *
  691. * @param string $string String to sanitize
  692. * @param boolean $full String contains HTML or not (optional)
  693. * @return string Sanitized string
  694. */
  695. public static function safeOutput($string, $html = false)
  696. {
  697. if (!$html)
  698. $string = strip_tags($string);
  699. return @Tools::htmlentitiesUTF8($string, ENT_QUOTES);
  700. }
  701.  
  702. public static function htmlentitiesUTF8($string, $type = ENT_QUOTES)
  703. {
  704. if (is_array($string))
  705. return array_map(array('Tools', 'htmlentitiesUTF8'), $string);
  706.  
  707. return htmlentities((string)$string, $type, 'utf-8');
  708. }
  709.  
  710. public static function htmlentitiesDecodeUTF8($string)
  711. {
  712. if (is_array($string))
  713. {
  714. $string = array_map(array('Tools', 'htmlentitiesDecodeUTF8'), $string);
  715. return (string)array_shift($string);
  716. }
  717. return html_entity_decode((string)$string, ENT_QUOTES, 'utf-8');
  718. }
  719.  
  720. public static function safePostVars()
  721. {
  722. if (!isset($_POST) || !is_array($_POST))
  723. $_POST = array();
  724. else
  725. $_POST = array_map(array('Tools', 'htmlentitiesUTF8'), $_POST);
  726. }
  727.  
  728. /**
  729. * Delete directory and subdirectories
  730. *
  731. * @param string $dirname Directory name
  732. */
  733. public static function deleteDirectory($dirname, $delete_self = true)
  734. {
  735. $dirname = rtrim($dirname, '/').'/';
  736. if (file_exists($dirname))
  737. if ($files = scandir($dirname))
  738. {
  739. foreach ($files as $file)
  740. if ($file != '.' && $file != '..' && $file != '.svn')
  741. {
  742. if (is_dir($dirname.$file))
  743. Tools::deleteDirectory($dirname.$file, true);
  744. elseif (file_exists($dirname.$file))
  745. {
  746. @chmod($dirname.$file, 0777); // NT ?
  747. unlink($dirname.$file);
  748. }
  749. }
  750. if ($delete_self && file_exists($dirname))
  751. if (!rmdir($dirname))
  752. {
  753. @chmod($dirname, 0777); // NT ?
  754. return false;
  755. }
  756. return true;
  757. }
  758. return false;
  759. }
  760.  
  761. /**
  762. * Delete file
  763. *
  764. * @param string File path
  765. * @param array Excluded files
  766. */
  767. public static function deleteFile($file, $exclude_files = array())
  768. {
  769. if (isset($exclude_files) && !is_array($exclude_files))
  770. $exclude_files = array($exclude_files);
  771.  
  772. if (file_exists($file) && is_file($file) && array_search(basename($file), $exclude_files) === FALSE)
  773. {
  774. @chmod($dirname.$file, 0777); // NT ?
  775. unlink($file);
  776. }
  777. }
  778.  
  779. /**
  780. * Clear XML cache folder
  781. */
  782. public static function clearXMLCache()
  783. {
  784. $themes = array();
  785. foreach (Theme::getThemes() as $theme)
  786. $themes[] = $theme->directory;
  787.  
  788. foreach (scandir(_PS_ROOT_DIR_.'/config/xml') as $file)
  789. {
  790. $path_info = pathinfo($file, PATHINFO_EXTENSION);
  791. if (($path_info == 'xml') && ($file != 'default.xml') && !in_array(basename($file, '.'.$path_info), $themes))
  792. self::deleteFile(_PS_ROOT_DIR_.'/config/xml/'.$file);
  793. }
  794. }
  795.  
  796. /**
  797. * Display an error according to an error code
  798. *
  799. * @param string $string Error message
  800. * @param boolean $htmlentities By default at true for parsing error message with htmlentities
  801. */
  802. public static function displayError($string = 'Fatal error', $htmlentities = true, Context $context = null)
  803. {
  804. global $_ERRORS;
  805.  
  806. if (is_null($context))
  807. $context = Context::getContext();
  808.  
  809. @include_once(_PS_TRANSLATIONS_DIR_.$context->language->iso_code.'/errors.php');
  810.  
  811. if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_ && $string == 'Fatal error')
  812. return ('<pre>'.print_r(debug_backtrace(), true).'</pre>');
  813. if (!is_array($_ERRORS))
  814. return $htmlentities ? Tools::htmlentitiesUTF8($string) : $string;
  815. $key = md5(str_replace('\'', '\\\'', $string));
  816. $str = (isset($_ERRORS) && is_array($_ERRORS) && array_key_exists($key, $_ERRORS)) ? $_ERRORS[$key] : $string;
  817. return $htmlentities ? Tools::htmlentitiesUTF8(stripslashes($str)) : $str;
  818. }
  819.  
  820. /**
  821. * Display an error with detailed object
  822. *
  823. * @param mixed $object
  824. * @param boolean $kill
  825. * @return $object if $kill = false;
  826. */
  827. public static function dieObject($object, $kill = true)
  828. {
  829. echo '<xmp style="text-align: left;">';
  830. print_r($object);
  831. echo '</xmp><br />';
  832.  
  833. if ($kill)
  834. die('END');
  835.  
  836. return $object;
  837. }
  838.  
  839. /**
  840. * Display a var dump in firebug console
  841. *
  842. * @param object $object Object to display
  843. */
  844. public static function fd($object, $type = 'log')
  845. {
  846. $types = array('log', 'debug', 'info', 'warn', 'error', 'assert');
  847.  
  848. if(!in_array($type, $types))
  849. $type = 'log';
  850.  
  851. echo '
  852. <script type="text/javascript">
  853. console.'.$type.'('.Tools::jsonEncode($object).');
  854. </script>
  855. ';
  856. }
  857.  
  858. /**
  859. * ALIAS OF dieObject() - Display an error with detailed object
  860. *
  861. * @param object $object Object to display
  862. */
  863. public static function d($object, $kill = true)
  864. {
  865. return (Tools::dieObject($object, $kill));
  866. }
  867.  
  868. public static function debug_backtrace($start = 0, $limit = null)
  869. {
  870. $backtrace = debug_backtrace();
  871. array_shift($backtrace);
  872. for ($i = 0; $i < $start; ++$i)
  873. array_shift($backtrace);
  874.  
  875. echo '
  876. <div style="margin:10px;padding:10px;border:1px solid #666666">
  877. <ul>';
  878. $i = 0;
  879. foreach ($backtrace as $id => $trace)
  880. {
  881. if ((int)$limit && (++$i > $limit ))
  882. break;
  883. $relative_file = (isset($trace['file'])) ? 'in /'.ltrim(str_replace(array(_PS_ROOT_DIR_, '\\'), array('', '/'), $trace['file']), '/') : '';
  884. $current_line = (isset($trace['line'])) ? ':'.$trace['line'] : '';
  885.  
  886. echo '<li>
  887. <b>'.((isset($trace['class'])) ? $trace['class'] : '').((isset($trace['type'])) ? $trace['type'] : '').$trace['function'].'</b>
  888. '.$relative_file.$current_line.'
  889. </li>';
  890. }
  891. echo '</ul>
  892. </div>';
  893. }
  894.  
  895. /**
  896. * ALIAS OF dieObject() - Display an error with detailed object but don't stop the execution
  897. *
  898. * @param object $object Object to display
  899. */
  900. public static function p($object)
  901. {
  902. return (Tools::dieObject($object, false));
  903. }
  904.  
  905. /**
  906. * Check if submit has been posted
  907. *
  908. * @param string $submit submit name
  909. */
  910. public static function isSubmit($submit)
  911. {
  912. return (
  913. isset($_POST[$submit]) || isset($_POST[$submit.'_x']) || isset($_POST[$submit.'_y'])
  914. || isset($_GET[$submit]) || isset($_GET[$submit.'_x']) || isset($_GET[$submit.'_y'])
  915. );
  916. }
  917.  
  918. /**
  919. * @deprecated 1.5.0
  920. */
  921. public static function getMetaTags($id_lang, $page_name, $title = '')
  922. {
  923. Tools::displayAsDeprecated();
  924. return Meta::getMetaTags($id_lang, $page_name, $title);
  925. }
  926.  
  927. /**
  928. * @deprecated 1.5.0
  929. */
  930. public static function getHomeMetaTags($id_lang, $page_name)
  931. {
  932. Tools::displayAsDeprecated();
  933. return Meta::getHomeMetas($id_lang, $page_name);
  934. }
  935.  
  936. /**
  937. * @deprecated 1.5.0
  938. */
  939. public static function completeMetaTags($meta_tags, $default_value, Context $context = null)
  940. {
  941. Tools::displayAsDeprecated();
  942. return Meta::completeMetaTags($meta_tags, $default_value, $context);
  943. }
  944.  
  945. /**
  946. * Encrypt password
  947. *
  948. * @param string $passwd String to encrypt
  949. */
  950. public static function encrypt($passwd)
  951. {
  952. return md5(_COOKIE_KEY_.$passwd);
  953. }
  954.  
  955. /**
  956. * Encrypt data string
  957. *
  958. * @param string $data String to encrypt
  959. */
  960. public static function encryptIV($data)
  961. {
  962. return md5(_COOKIE_IV_.$data);
  963. }
  964.  
  965. /**
  966. * Get token to prevent CSRF
  967. *
  968. * @param string $token token to encrypt
  969. */
  970. public static function getToken($page = true, Context $context = null)
  971. {
  972. if (!$context)
  973. $context = Context::getContext();
  974. if ($page === true)
  975. return (Tools::encrypt($context->customer->id.$context->customer->passwd.$_SERVER['SCRIPT_NAME']));
  976. else
  977. return (Tools::encrypt($context->customer->id.$context->customer->passwd.$page));
  978. }
  979.  
  980. /**
  981. * Tokenize a string
  982. *
  983. * @param string $string string to encript
  984. */
  985. public static function getAdminToken($string)
  986. {
  987. return !empty($string) ? Tools::encrypt($string) : false;
  988. }
  989.  
  990. public static function getAdminTokenLite($tab, Context $context = null)
  991. {
  992. if (!$context)
  993. $context = Context::getContext();
  994. return Tools::getAdminToken($tab.(int)Tab::getIdFromClassName($tab).(int)$context->employee->id);
  995. }
  996.  
  997. public static function getAdminTokenLiteSmarty($params, &$smarty)
  998. {
  999. $context = Context::getContext();
  1000. return Tools::getAdminToken($params['tab'].(int)Tab::getIdFromClassName($params['tab']).(int)$context->employee->id);
  1001. }
  1002.  
  1003. /**
  1004. * Get a valid URL to use from BackOffice
  1005. *
  1006. * @param string $url An URL to use in BackOffice
  1007. * @param boolean $entites Set to true to use htmlentities function on URL param
  1008. */
  1009. public static function getAdminUrl($url = null, $entities = false)
  1010. {
  1011. $link = Tools::getHttpHost(true).__PS_BASE_URI__;
  1012.  
  1013. if (isset($url))
  1014. $link .= ($entities ? Tools::htmlentitiesUTF8($url) : $url);
  1015.  
  1016. return $link;
  1017. }
  1018.  
  1019. /**
  1020. * Get a valid image URL to use from BackOffice
  1021. *
  1022. * @param string $image Image name
  1023. * @param boolean $entites Set to true to use htmlentities function on image param
  1024. */
  1025. public static function getAdminImageUrl($image = null, $entities = false)
  1026. {
  1027. return Tools::getAdminUrl(basename(_PS_IMG_DIR_).'/'.$image, $entities);
  1028. }
  1029.  
  1030. /**
  1031. * Get the user's journey
  1032. *
  1033. * @param integer $id_category Category ID
  1034. * @param string $path Path end
  1035. * @param boolean $linkOntheLastItem Put or not a link on the current category
  1036. * @param string [optionnal] $categoryType defined what type of categories is used (products or cms)
  1037. */
  1038. public static function getPath($id_category, $path = '', $link_on_the_item = false, $category_type = 'products', Context $context = null)
  1039. {
  1040. if (!$context)
  1041. $context = Context::getContext();
  1042.  
  1043. $id_category = (int)$id_category;
  1044. if ($id_category == 1)
  1045. return '<span class="navigation_end">'.$path.'</span>';
  1046.  
  1047. $pipe = Configuration::get('PS_NAVIGATION_PIPE');
  1048. if (empty($pipe))
  1049. $pipe = '>';
  1050.  
  1051. $full_path = '';
  1052. if ($category_type === 'products')
  1053. {
  1054. $interval = Category::getInterval($id_category);
  1055. $id_root_category = $context->shop->getCategory();
  1056. $interval_root = Category::getInterval($id_root_category);
  1057. if ($interval)
  1058. {
  1059. $sql = 'SELECT c.id_category, cl.name, cl.link_rewrite
  1060. FROM '._DB_PREFIX_.'category c
  1061. LEFT JOIN '._DB_PREFIX_.'category_lang cl ON (cl.id_category = c.id_category'.Shop::addSqlRestrictionOnLang('cl').')
  1062. '.Shop::addSqlAssociation('category', 'c').'
  1063. WHERE c.nleft <= '.$interval['nleft'].'
  1064. AND c.nright >= '.$interval['nright'].'
  1065. AND c.nleft >= '.$interval_root['nleft'].'
  1066. AND c.nright <= '.$interval_root['nright'].'
  1067. AND cl.id_lang = '.(int)$context->language->id.'
  1068. AND c.active = 1
  1069. AND c.level_depth > '.(int)$interval_root['level_depth'].'
  1070. ORDER BY c.level_depth ASC';
  1071. $categories = Db::getInstance()->executeS($sql);
  1072.  
  1073. $n = 1;
  1074. $n_categories = count($categories);
  1075. foreach ($categories as $category)
  1076. {
  1077. $full_path .=
  1078. (($n < $n_categories || $link_on_the_item) ? '<a href="'.Tools::safeOutput($context->link->getCategoryLink((int)$category['id_category'], $category['link_rewrite'])).'" title="'.htmlentities($category['name'], ENT_NOQUOTES, 'UTF-8').'">' : '').
  1079. htmlentities($category['name'], ENT_NOQUOTES, 'UTF-8').
  1080. (($n < $n_categories || $link_on_the_item) ? '</a>' : '').
  1081. (($n++ != $n_categories || !empty($path)) ? '<span class="navigation-pipe">'.$pipe.'</span>' : '');
  1082. }
  1083.  
  1084. return $full_path.$path;
  1085. }
  1086. }
  1087. else if ($category_type === 'CMS')
  1088. {
  1089. $category = new CMSCategory($id_category, $context->language->id);
  1090. if (!Validate::isLoadedObject($category))
  1091. die(Tools::displayError());
  1092. $category_link = $context->link->getCMSCategoryLink($category);
  1093.  
  1094. if ($path != $category->name)
  1095. $full_path .= '<a href="'.Tools::safeOutput($category_link).'">'.htmlentities($category->name, ENT_NOQUOTES, 'UTF-8').'</a><span class="navigation-pipe">'.$pipe.'</span>'.$path;
  1096. else
  1097. $full_path = ($link_on_the_item ? '<a href="'.Tools::safeOutput($category_link).'">' : '').htmlentities($path, ENT_NOQUOTES, 'UTF-8').($link_on_the_item ? '</a>' : '');
  1098.  
  1099. return Tools::getPath($category->id_parent, $full_path, $link_on_the_item, $category_type);
  1100. }
  1101. }
  1102.  
  1103. /**
  1104. * @param string [optionnal] $type_cat defined what type of categories is used (products or cms)
  1105. */
  1106. public static function getFullPath($id_category, $end, $type_cat = 'products', Context $context = null)
  1107. {
  1108. if (!$context)
  1109. $context = Context::getContext();
  1110.  
  1111. $id_category = (int)$id_category;
  1112. $pipe = (Configuration::get('PS_NAVIGATION_PIPE') ? Configuration::get('PS_NAVIGATION_PIPE') : '>');
  1113.  
  1114. $default_category = 1;
  1115. if ($type_cat === 'products')
  1116. {
  1117. $default_category = $context->shop->getCategory();
  1118. $category = new Category($id_category, $context->language->id);
  1119. }
  1120. else if ($type_cat === 'CMS')
  1121. $category = new CMSCategory($id_category, $context->language->id);
  1122.  
  1123. if (!Validate::isLoadedObject($category))
  1124. $id_category = $default_category;
  1125. if ($id_category == $default_category)
  1126. return htmlentities($end, ENT_NOQUOTES, 'UTF-8');
  1127.  
  1128. return Tools::getPath($id_category, $category->name, true, $type_cat).'<span class="navigation-pipe">'.$pipe.'</span> <span class="navigation_product">'.htmlentities($end, ENT_NOQUOTES, 'UTF-8').'</span>';
  1129. }
  1130.  
  1131. /**
  1132. * Return the friendly url from the provided string
  1133. *
  1134. * @param string $str
  1135. * @param bool $utf8_decode (deprecated)
  1136. * @return string
  1137. */
  1138. public static function link_rewrite($str, $utf8_decode = null)
  1139. {
  1140. if ($utf8_decode !== null)
  1141. Tools::displayParameterAsDeprecated('utf8_decode');
  1142. return Tools::str2url($str);
  1143. }
  1144.  
  1145. /**
  1146. * Return a friendly url made from the provided string
  1147. * If the mbstring library is available, the output is the same as the js function of the same name
  1148. *
  1149. * @param string $str
  1150. * @return string
  1151. */
  1152. public static function str2url($str)
  1153. {
  1154. static $allow_accented_chars = null;
  1155.  
  1156. if ($allow_accented_chars === null)
  1157. $allow_accented_chars = Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL');
  1158.  
  1159. if (!is_string($str))
  1160. return false;
  1161.  
  1162. $str = trim($str);
  1163.  
  1164. if (function_exists('mb_strtolower'))
  1165. $str = mb_strtolower($str, 'utf-8');
  1166. if (!$allow_accented_chars)
  1167. $str = Tools::replaceAccentedChars($str);
  1168.  
  1169. // Remove all non-whitelist chars.
  1170. if ($allow_accented_chars)
  1171. $str = preg_replace('/[^a-zA-Z0-9\s\'\:\/\[\]\-\pL]/u', '', $str);
  1172. else
  1173. $str = preg_replace('/[^a-zA-Z0-9\s\'\:\/\[\]\-]/','', $str);
  1174.  
  1175. $str = preg_replace('/[\s\'\:\/\[\]\-]+/', ' ', $str);
  1176. $str = str_replace(array(' ', '/'), '-', $str);
  1177.  
  1178. // If it was not possible to lowercase the string with mb_strtolower, we do it after the transformations.
  1179. // This way we lose fewer special chars.
  1180. if (!function_exists('mb_strtolower'))
  1181. $str = Tools::strtolower($str);
  1182.  
  1183. return $str;
  1184. }
  1185.  
  1186. /**
  1187. * Replace all accented chars by their equivalent non accented chars.
  1188. *
  1189. * @param string $str
  1190. * @return string
  1191. */
  1192. public static function replaceAccentedChars($str)
  1193. {
  1194. /* One source among others:
  1195. http://www.tachyonsoft.com/uc0000.htm
  1196. http://www.tachyonsoft.com/uc0001.htm
  1197. http://www.tachyonsoft.com/uc0004.htm
  1198. */
  1199. $patterns = array(
  1200.  
  1201. /* Lowercase */
  1202. /* a */ '/[\x{00E0}\x{00E1}\x{00E2}\x{00E3}\x{00E4}\x{00E5}\x{0101}\x{0103}\x{0105}\x{0430}]/u',
  1203. /* b */ '/[\x{0431}]/u',
  1204. /* c */ '/[\x{00E7}\x{0107}\x{0109}\x{010D}\x{0446}]/u',
  1205. /* d */ '/[\x{010F}\x{0111}\x{0434}]/u',
  1206. /* e */ '/[\x{00E8}\x{00E9}\x{00EA}\x{00EB}\x{0113}\x{0115}\x{0117}\x{0119}\x{011B}\x{0435}\x{044D}]/u',
  1207. /* f */ '/[\x{0444}]/u',
  1208. /* g */ '/[\x{011F}\x{0121}\x{0123}\x{0433}\x{0491}]/u',
  1209. /* h */ '/[\x{0125}\x{0127}]/u',
  1210. /* i */ '/[\x{00EC}\x{00ED}\x{00EE}\x{00EF}\x{0129}\x{012B}\x{012D}\x{012F}\x{0131}\x{0438}\x{0456}]/u',
  1211. /* j */ '/[\x{0135}\x{0439}]/u',
  1212. /* k */ '/[\x{0137}\x{0138}\x{043A}]/u',
  1213. /* l */ '/[\x{013A}\x{013C}\x{013E}\x{0140}\x{0142}\x{043B}]/u',
  1214. /* m */ '/[\x{043C}]/u',
  1215. /* n */ '/[\x{00F1}\x{0144}\x{0146}\x{0148}\x{0149}\x{014B}\x{043D}]/u',
  1216. /* o */ '/[\x{00F2}\x{00F3}\x{00F4}\x{00F5}\x{00F6}\x{00F8}\x{014D}\x{014F}\x{0151}\x{043E}]/u',
  1217. /* p */ '/[\x{043F}]/u',
  1218. /* r */ '/[\x{0155}\x{0157}\x{0159}\x{0440}]/u',
  1219. /* s */ '/[\x{015B}\x{015D}\x{015F}\x{0161}\x{0441}]/u',
  1220. /* ss */ '/[\x{00DF}]/u',
  1221. /* t */ '/[\x{0163}\x{0165}\x{0167}\x{0442}]/u',
  1222. /* u */ '/[\x{00F9}\x{00FA}\x{00FB}\x{00FC}\x{0169}\x{016B}\x{016D}\x{016F}\x{0171}\x{0173}\x{0443}]/u',
  1223. /* v */ '/[\x{0432}]/u',
  1224. /* w */ '/[\x{0175}]/u',
  1225. /* y */ '/[\x{00FF}\x{0177}\x{00FD}\x{044B}]/u',
  1226. /* z */ '/[\x{017A}\x{017C}\x{017E}\x{0437}]/u',
  1227. /* ae */ '/[\x{00E6}]/u',
  1228. /* ch */ '/[\x{0447}]/u',
  1229. /* kh */ '/[\x{0445}]/u',
  1230. /* oe */ '/[\x{0153}]/u',
  1231. /* sh */ '/[\x{0448}]/u',
  1232. /* shh*/ '/[\x{0449}]/u',
  1233. /* ya */ '/[\x{044F}]/u',
  1234. /* ye */ '/[\x{0454}]/u',
  1235. /* yi */ '/[\x{0457}]/u',
  1236. /* yo */ '/[\x{0451}]/u',
  1237. /* yu */ '/[\x{044E}]/u',
  1238. /* zh */ '/[\x{0436}]/u',
  1239.  
  1240. /* Uppercase */
  1241. /* A */ '/[\x{0100}\x{0102}\x{0104}\x{00C0}\x{00C1}\x{00C2}\x{00C3}\x{00C4}\x{00C5}\x{0410}]/u',
  1242. /* B */ '/[\x{0411}]]/u',
  1243. /* C */ '/[\x{00C7}\x{0106}\x{0108}\x{010A}\x{010C}\x{0426}]/u',
  1244. /* D */ '/[\x{010E}\x{0110}\x{0414}]/u',
  1245. /* E */ '/[\x{00C8}\x{00C9}\x{00CA}\x{00CB}\x{0112}\x{0114}\x{0116}\x{0118}\x{011A}\x{0415}\x{042D}]/u',
  1246. /* F */ '/[\x{0424}]/u',
  1247. /* G */ '/[\x{011C}\x{011E}\x{0120}\x{0122}\x{0413}\x{0490}]/u',
  1248. /* H */ '/[\x{0124}\x{0126}]/u',
  1249. /* I */ '/[\x{0128}\x{012A}\x{012C}\x{012E}\x{0130}\x{0418}\x{0406}]/u',
  1250. /* J */ '/[\x{0134}\x{0419}]/u',
  1251. /* K */ '/[\x{0136}\x{041A}]/u',
  1252. /* L */ '/[\x{0139}\x{013B}\x{013D}\x{0139}\x{0141}\x{041B}]/u',
  1253. /* M */ '/[\x{041C}]/u',
  1254. /* N */ '/[\x{00D1}\x{0143}\x{0145}\x{0147}\x{014A}\x{041D}]/u',
  1255. /* O */ '/[\x{00D3}\x{014C}\x{014E}\x{0150}\x{041E}]/u',
  1256. /* P */ '/[\x{041F}]/u',
  1257. /* R */ '/[\x{0154}\x{0156}\x{0158}\x{0420}]/u',
  1258. /* S */ '/[\x{015A}\x{015C}\x{015E}\x{0160}\x{0421}]/u',
  1259. /* T */ '/[\x{0162}\x{0164}\x{0166}\x{0422}]/u',
  1260. /* U */ '/[\x{00D9}\x{00DA}\x{00DB}\x{00DC}\x{0168}\x{016A}\x{016C}\x{016E}\x{0170}\x{0172}\x{0423}]/u',
  1261. /* V */ '/[\x{0412}]/u',
  1262. /* W */ '/[\x{0174}]/u',
  1263. /* Y */ '/[\x{0176}\x{042B}]/u',
  1264. /* Z */ '/[\x{0179}\x{017B}\x{017D}\x{0417}]/u',
  1265. /* AE */ '/[\x{00C6}]/u',
  1266. /* CH */ '/[\x{0427}]/u',
  1267. /* KH */ '/[\x{0425}]/u',
  1268. /* OE */ '/[\x{0152}]/u',
  1269. /* SH */ '/[\x{0428}]/u',
  1270. /* SHH*/ '/[\x{0429}]/u',
  1271. /* YA */ '/[\x{042F}]/u',
  1272. /* YE */ '/[\x{0404}]/u',
  1273. /* YI */ '/[\x{0407}]/u',
  1274. /* YO */ '/[\x{0401}]/u',
  1275. /* YU */ '/[\x{042E}]/u',
  1276. /* ZH */ '/[\x{0416}]/u');
  1277.  
  1278. // ö to oe
  1279. // å to aa
  1280. // ä to ae
  1281.  
  1282. $replacements = array(
  1283. 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 'ss', 't', 'u', 'v', 'w', 'y', 'z', 'ae', 'ch', 'kh', 'oe', 'sh', 'shh', 'ya', 'ye', 'yi', 'yo', 'yu', 'zh',
  1284. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'V', 'W', 'Y', 'Z', 'AE', 'CH', 'KH', 'OE', 'SH', 'SHH', 'YA', 'YE', 'YI', 'YO', 'YU', 'ZH'
  1285. );
  1286.  
  1287. return preg_replace($patterns, $replacements, $str);
  1288. }
  1289.  
  1290. /**
  1291. * Truncate strings
  1292. *
  1293. * @param string $str
  1294. * @param integer $max_length Max length
  1295. * @param string $suffix Suffix optional
  1296. * @return string $str truncated
  1297. */
  1298. /* CAUTION : Use it only on module hookEvents.
  1299. ** For other purposes use the smarty function instead */
  1300. public static function truncate($str, $max_length, $suffix = '...')
  1301. {
  1302. if (Tools::strlen($str) <= $max_length)
  1303. return $str;
  1304. $str = utf8_decode($str);
  1305. return (utf8_encode(substr($str, 0, $max_length - Tools::strlen($suffix)).$suffix));
  1306. }
  1307.  
  1308. /*Copied from CakePHP String utility file*/
  1309. public static function truncateString($text, $length = 120, $options = array())
  1310. {
  1311. $default = array(
  1312. 'ellipsis' => '...', 'exact' => true, 'html' => true
  1313. );
  1314.  
  1315. $options = array_merge($default, $options);
  1316. extract($options);
  1317.  
  1318. if ($html)
  1319. {
  1320. if (Tools::strlen(preg_replace('/<.*?>/', '', $text)) <= $length)
  1321. return $text;
  1322.  
  1323. $totalLength = Tools::strlen(strip_tags($ellipsis));
  1324. $openTags = array();
  1325. $truncate = '';
  1326. preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER);
  1327.  
  1328. foreach ($tags as $tag)
  1329. {
  1330. if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2]))
  1331. {
  1332. if (preg_match('/<[\w]+[^>]*>/s', $tag[0]))
  1333. array_unshift($openTags, $tag[2]);
  1334. elseif (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag))
  1335. {
  1336. $pos = array_search($closeTag[1], $openTags);
  1337. if ($pos !== false)
  1338. array_splice($openTags, $pos, 1);
  1339. }
  1340. }
  1341. $truncate .= $tag[1];
  1342. $contentLength = Tools::strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3]));
  1343.  
  1344. if ($contentLength + $totalLength > $length)
  1345. {
  1346. $left = $length - $totalLength;
  1347. $entitiesLength = 0;
  1348.  
  1349. if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $tag[3], $entities, PREG_OFFSET_CAPTURE))
  1350. {
  1351. foreach ($entities[0] as $entity)
  1352. {
  1353. if ($entity[1] + 1 - $entitiesLength <= $left)
  1354. {
  1355. $left--;
  1356. $entitiesLength += Tools::strlen($entity[0]);
  1357. }
  1358. else
  1359. break;
  1360. }
  1361. }
  1362.  
  1363. $truncate .= Tools::substr($tag[3], 0, $left + $entitiesLength);
  1364. break;
  1365. }
  1366. else
  1367. {
  1368. $truncate .= $tag[3];
  1369. $totalLength += $contentLength;
  1370. }
  1371.  
  1372. if ($totalLength >= $length)
  1373. break;
  1374. }
  1375. }
  1376. else
  1377. {
  1378. if (Tools::strlen($text) <= $length)
  1379. return $text;
  1380.  
  1381. $truncate = Tools::substr($text, 0, $length - Tools::strlen($ellipsis));
  1382. }
  1383.  
  1384. if (!$exact)
  1385. {
  1386. $spacepos = Tools::strrpos($truncate, ' ');
  1387. if ($html)
  1388. {
  1389. $truncateCheck = Tools::substr($truncate, 0, $spacepos);
  1390. $lastOpenTag = Tools::strrpos($truncateCheck, '<');
  1391. $lastCloseTag = Tools::strrpos($truncateCheck, '>');
  1392.  
  1393. if ($lastOpenTag > $lastCloseTag)
  1394. {
  1395. preg_match_all('/<[\w]+[^>]*>/s', $truncate, $lastTagMatches);
  1396. $lastTag = array_pop($lastTagMatches[0]);
  1397. $spacepos = Tools::strrpos($truncate, $lastTag) + Tools::strlen($lastTag);
  1398. }
  1399.  
  1400. $bits = Tools::substr($truncate, $spacepos);
  1401. preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER);
  1402.  
  1403. if (!empty($droppedTags))
  1404. {
  1405. if (!empty($openTags))
  1406. {
  1407. foreach ($droppedTags as $closingTag)
  1408. if (!in_array($closingTag[1], $openTags))
  1409. array_unshift($openTags, $closingTag[1]);
  1410. }
  1411. else
  1412. {
  1413. foreach ($droppedTags as $closingTag)
  1414. $openTags[] = $closingTag[1];
  1415. }
  1416. }
  1417. }
  1418.  
  1419. $truncate = Tools::substr($truncate, 0, $spacepos);
  1420. }
  1421.  
  1422. $truncate .= $ellipsis;
  1423.  
  1424. if ($html)
  1425. foreach ($openTags as $tag)
  1426. $truncate .= '</' . $tag . '>';
  1427.  
  1428. return $truncate;
  1429. }
  1430.  
  1431. public static function normalizeDirectory($directory)
  1432. {
  1433. $last = $directory[strlen($directory) - 1];
  1434.  
  1435. if (in_array($last, array('/', '\\')))
  1436. {
  1437. $directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR;
  1438. return $directory;
  1439. }
  1440.  
  1441. $directory .= DIRECTORY_SEPARATOR;
  1442. return $directory;
  1443. }
  1444.  
  1445. /**
  1446. * Generate date form
  1447. *
  1448. * @param integer $year Year to select
  1449. * @param integer $month Month to select
  1450. * @param integer $day Day to select
  1451. * @return array $tab html data with 3 cells :['days'], ['months'], ['years']
  1452. *
  1453. */
  1454. public static function dateYears()
  1455. {
  1456. $tab = array();
  1457. for ($i = date('Y'); $i >= 1900; $i--)
  1458. $tab[] = $i;
  1459. return $tab;
  1460. }
  1461.  
  1462. public static function dateDays()
  1463. {
  1464. $tab = array();
  1465. for ($i = 1; $i != 32; $i++)
  1466. $tab[] = $i;
  1467. return $tab;
  1468. }
  1469.  
  1470. public static function dateMonths()
  1471. {
  1472. $tab = array();
  1473. for ($i = 1; $i != 13; $i++)
  1474. $tab[$i] = date('F', mktime(0, 0, 0, $i, date('m'), date('Y')));
  1475. return $tab;
  1476. }
  1477.  
  1478. public static function hourGenerate($hours, $minutes, $seconds)
  1479. {
  1480. return implode(':', array($hours, $minutes, $seconds));
  1481. }
  1482.  
  1483. public static function dateFrom($date)
  1484. {
  1485. $tab = explode(' ', $date);
  1486. if (!isset($tab[1]))
  1487. $date .= ' '.Tools::hourGenerate(0, 0, 0);
  1488. return $date;
  1489. }
  1490.  
  1491. public static function dateTo($date)
  1492. {
  1493. $tab = explode(' ', $date);
  1494. if (!isset($tab[1]))
  1495. $date .= ' '.Tools::hourGenerate(23, 59, 59);
  1496. return $date;
  1497. }
  1498.  
  1499. public static function strtolower($str)
  1500. {
  1501. if (is_array($str))
  1502. return false;
  1503. if (function_exists('mb_strtolower'))
  1504. return mb_strtolower($str, 'utf-8');
  1505. return strtolower($str);
  1506. }
  1507.  
  1508. public static function strlen($str, $encoding = 'UTF-8')
  1509. {
  1510. if (is_array($str))
  1511. return false;
  1512. $str = html_entity_decode($str, ENT_COMPAT, 'UTF-8');
  1513. if (function_exists('mb_strlen'))
  1514. return mb_strlen($str, $encoding);
  1515. return strlen($str);
  1516. }
  1517.  
  1518. public static function stripslashes($string)
  1519. {
  1520. if (_PS_MAGIC_QUOTES_GPC_)
  1521. $string = stripslashes($string);
  1522. return $string;
  1523. }
  1524.  
  1525. public static function strtoupper($str)
  1526. {
  1527. if (is_array($str))
  1528. return false;
  1529. if (function_exists('mb_strtoupper'))
  1530. return mb_strtoupper($str, 'utf-8');
  1531. return strtoupper($str);
  1532. }
  1533.  
  1534. public static function substr($str, $start, $length = false, $encoding = 'utf-8')
  1535. {
  1536. if (is_array($str))
  1537. return false;
  1538. if (function_exists('mb_substr'))
  1539. return mb_substr($str, (int)$start, ($length === false ? Tools::strlen($str) : (int)$length), $encoding);
  1540. return substr($str, $start, ($length === false ? Tools::strlen($str) : (int)$length));
  1541. }
  1542.  
  1543. public static function strpos($str, $find, $offset = 0, $encoding = 'UTF-8')
  1544. {
  1545. if (function_exists('mb_strpos'))
  1546. return mb_strpos($str, $find, $offset, $encoding);
  1547. return strpos($str, $find, $offset);
  1548. }
  1549.  
  1550. public static function strrpos($str, $find, $offset = 0, $encoding = 'utf-8')
  1551. {
  1552. if (function_exists('mb_strrpos'))
  1553. return mb_strrpos($str, $find, $offset, $encoding);
  1554. return strrpos($str, $find, $offset);
  1555. }
  1556.  
  1557. public static function ucfirst($str)
  1558. {
  1559. return Tools::strtoupper(Tools::substr($str, 0, 1)).Tools::substr($str, 1);
  1560. }
  1561.  
  1562. public static function ucwords($str)
  1563. {
  1564. if (function_exists('mb_convert_case'))
  1565. return mb_convert_case($str, MB_CASE_TITLE);
  1566. return ucwords(Tools::strtolower($str));
  1567. }
  1568.  
  1569. public static function orderbyPrice(&$array, $order_way)
  1570. {
  1571. foreach ($array as &$row)
  1572. $row['price_tmp'] = Product::getPriceStatic($row['id_product'], true, ((isset($row['id_product_attribute']) && !empty($row['id_product_attribute'])) ? (int)$row['id_product_attribute'] : null), 2);
  1573.  
  1574. unset($row);
  1575.  
  1576. if (Tools::strtolower($order_way) == 'desc')
  1577. uasort($array, 'cmpPriceDesc');
  1578. else
  1579. uasort($array, 'cmpPriceAsc');
  1580. foreach ($array as &$row)
  1581. unset($row['price_tmp']);
  1582. }
  1583.  
  1584. public static function iconv($from, $to, $string)
  1585. {
  1586. if (function_exists('iconv'))
  1587. return iconv($from, $to.'//TRANSLIT', str_replace('¥', '&yen;', str_replace('£', '&pound;', str_replace('€', '&euro;', $string))));
  1588. return html_entity_decode(htmlentities($string, ENT_NOQUOTES, $from), ENT_NOQUOTES, $to);
  1589. }
  1590.  
  1591. public static function isEmpty($field)
  1592. {
  1593. return ($field === '' || $field === null);
  1594. }
  1595.  
  1596. /**
  1597. * returns the rounded value of $value to specified precision, according to your configuration;
  1598. *
  1599. * @note : PHP 5.3.0 introduce a 3rd parameter mode in round function
  1600. *
  1601. * @param float $value
  1602. * @param int $precision
  1603. * @return float
  1604. */
  1605. public static function ps_round($value, $precision = 0)
  1606. {
  1607. static $method = null;
  1608.  
  1609. if ($method == null)
  1610. $method = (int)Configuration::get('PS_PRICE_ROUND_MODE');
  1611.  
  1612. switch ($method)
  1613. {
  1614. case PS_ROUND_UP:
  1615. return Tools::ceilf($value, $precision);
  1616. case PS_ROUND_DOWN:
  1617. return Tools::floorf($value, $precision);
  1618. case PS_ROUND_HALF_DOWN:
  1619. case PS_ROUND_HALF_EVEN:
  1620. case PS_ROUND_HALF_ODD:
  1621. return Tools::math_round($value, $precision, $method);
  1622. case PS_ROUND_HALF_UP:
  1623. default:
  1624. return Tools::math_round($value, $precision, PS_ROUND_HALF_UP);
  1625. }
  1626. }
  1627.  
  1628. public static function math_round($value, $places, $mode = PS_ROUND_HALF_UP)
  1629. {
  1630. //If PHP_ROUND_HALF_UP exist (PHP 5.3) use it and pass correct mode value (PrestaShop define - 1)
  1631. if (defined('PHP_ROUND_HALF_UP'))
  1632. return round($value, $places, $mode-1);
  1633.  
  1634. $precision_places = 14 - floor(log10(abs($value)));
  1635. $f1 = pow(10.0, (double)abs($places));
  1636.  
  1637. /* If the decimal precision guaranteed by FP arithmetic is higher than
  1638. * the requested places BUT is small enough to make sure a non-zero value
  1639. * is returned, pre-round the result to the precision */
  1640. if ($precision_places > $places && $precision_places - $places < 15)
  1641. {
  1642. $f2 = pow(10.0, (double)abs($precision_places));
  1643.  
  1644. if ($precision_places >= 0)
  1645. $tmp_value = $value * $f2;
  1646. else
  1647. $tmp_value = $value / $f2;
  1648.  
  1649. /* preround the result (tmp_value will always be something * 1e14,
  1650. * thus never larger than 1e15 here) */
  1651. $tmp_value = Tools::round_helper($tmp_value, $mode);
  1652. /* now correctly move the decimal point */
  1653. $f2 = pow(10.0, (double)abs($places - $precision_places));
  1654. /* because places < precision_places */
  1655. $tmp_value = $tmp_value / $f2;
  1656. }
  1657. else
  1658. {
  1659. /* adjust the value */
  1660. if ($places >= 0)
  1661. $tmp_value = $value * $f1;
  1662. else
  1663. $tmp_value = $value / $f1;
  1664.  
  1665. /* This value is beyond our precision, so rounding it is pointless */
  1666. if (abs($tmp_value) >= 1e15)
  1667. return $value;
  1668. }
  1669.  
  1670. /* round the temp value */
  1671. $tmp_value = Tools::round_helper($tmp_value, $mode);
  1672.  
  1673. /* see if it makes sense to use simple division to round the value */
  1674. if (abs($places) < 23)
  1675. {
  1676. if ($places > 0)
  1677. $tmp_value /= $f1;
  1678. else
  1679. $tmp_value *= $f1;
  1680. }
  1681.  
  1682. return $tmp_value;
  1683. }
  1684.  
  1685. public static function round_helper($value, $mode)
  1686. {
  1687. if ($value >= 0.0)
  1688. {
  1689. $tmp_value = floor($value + 0.5);
  1690.  
  1691. if (($mode == PS_ROUND_HALF_DOWN && $value == (-0.5 + $tmp_value )) ||
  1692. ($mode == PS_ROUND_HALF_EVEN && $value == (0.5 + 2 * floor($tmp_value /2.0))) ||
  1693. ($mode == PS_ROUND_HALF_ODD && $value == (0.5 + 2 * floor($tmp_value /2.0) - 1.0)))
  1694. $tmp_value = $tmp_value - 1.0;
  1695. }
  1696. else
  1697. {
  1698. $tmp_value = ceil($value - 0.5);
  1699.  
  1700. if (($mode == PS_ROUND_HALF_DOWN && $value == (0.5 + $tmp_value )) ||
  1701. ($mode == PS_ROUND_HALF_EVEN && $value == (-0.5 + 2 * ceil($tmp_value /2.0))) ||
  1702. ($mode == PS_ROUND_HALF_ODD && $value == (-0.5 + 2 * ceil($tmp_value /2.0) + 1.0)))
  1703. $tmp_value = $tmp_value + 1.0;
  1704. }
  1705.  
  1706. return $tmp_value;
  1707. }
  1708.  
  1709. /**
  1710. * returns the rounded value down of $value to specified precision
  1711. *
  1712. * @param float $value
  1713. * @param int $precision
  1714. * @return float
  1715. */
  1716. public static function ceilf($value, $precision = 0)
  1717. {
  1718. $precision_factor = $precision == 0 ? 1 : pow(10, $precision);
  1719. $tmp = $value * $precision_factor;
  1720. $tmp2 = (string)$tmp;
  1721. // If the current value has already the desired precision
  1722. if (strpos($tmp2, '.') === false)
  1723. return ($value);
  1724. if ($tmp2[strlen($tmp2) - 1] == 0)
  1725. return $value;
  1726. return ceil($tmp) / $precision_factor;
  1727. }
  1728.  
  1729. /**
  1730. * returns the rounded value up of $value to specified precision
  1731. *
  1732. * @param float $value
  1733. * @param int $precision
  1734. * @return float
  1735. */
  1736. public static function floorf($value, $precision = 0)
  1737. {
  1738. $precision_factor = $precision == 0 ? 1 : pow(10, $precision);
  1739. $tmp = $value * $precision_factor;
  1740. $tmp2 = (string)$tmp;
  1741. // If the current value has already the desired precision
  1742. if (strpos($tmp2, '.') === false)
  1743. return ($value);
  1744. if ($tmp2[strlen($tmp2) - 1] == 0)
  1745. return $value;
  1746. return floor($tmp) / $precision_factor;
  1747. }
  1748.  
  1749. /**
  1750. * file_exists() wrapper with cache to speedup performance
  1751. *
  1752. * @param string $filename File name
  1753. * @return boolean Cached result of file_exists($filename)
  1754. */
  1755. public static function file_exists_cache($filename)
  1756. {
  1757. if (!isset(self::$file_exists_cache[$filename]))
  1758. self::$file_exists_cache[$filename] = file_exists($filename);
  1759. return self::$file_exists_cache[$filename];
  1760. }
  1761.  
  1762. /**
  1763. * file_exists() wrapper with a call to clearstatcache prior
  1764. *
  1765. * @param string $filename File name
  1766. * @return boolean Cached result of file_exists($filename)
  1767. */
  1768. public static function file_exists_no_cache($filename)
  1769. {
  1770. clearstatcache();
  1771. return file_exists($filename);
  1772. }
  1773.  
  1774. public static function file_get_contents($url, $use_include_path = false, $stream_context = null, $curl_timeout = 5)
  1775. {
  1776. if ($stream_context == null && preg_match('/^https?:\/\//', $url))
  1777. $stream_context = @stream_context_create(array('http' => array('timeout' => $curl_timeout)));
  1778. if (in_array(ini_get('allow_url_fopen'), array('On', 'on', '1')) || !preg_match('/^https?:\/\//', $url))
  1779. return @file_get_contents($url, $use_include_path, $stream_context);
  1780. elseif (function_exists('curl_init'))
  1781. {
  1782. $curl = curl_init();
  1783. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  1784. curl_setopt($curl, CURLOPT_URL, $url);
  1785. curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
  1786. curl_setopt($curl, CURLOPT_TIMEOUT, $curl_timeout);
  1787. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
  1788. if ($stream_context != null) {
  1789. $opts = stream_context_get_options($stream_context);
  1790. if (isset($opts['http']['method']) && Tools::strtolower($opts['http']['method']) == 'post')
  1791. {
  1792. curl_setopt($curl, CURLOPT_POST, true);
  1793. if (isset($opts['http']['content']))
  1794. {
  1795. parse_str($opts['http']['content'], $datas);
  1796. curl_setopt($curl, CURLOPT_POSTFIELDS, $datas);
  1797. }
  1798. }
  1799. }
  1800. $content = curl_exec($curl);
  1801. curl_close($curl);
  1802. return $content;
  1803. }
  1804. else
  1805. return false;
  1806. }
  1807.  
  1808. public static function simplexml_load_file($url, $class_name = null)
  1809. {
  1810. return @simplexml_load_string(Tools::file_get_contents($url), $class_name);
  1811. }
  1812.  
  1813. public static function copy($source, $destination, $stream_context = null)
  1814. {
  1815. if (is_null($stream_context) && !preg_match('/^https?:\/\//', $source))
  1816. return @copy($source, $destination);
  1817. return @file_put_contents($destination, Tools::file_get_contents($source, false, $stream_context));
  1818. }
  1819.  
  1820. /**
  1821. * @deprecated as of 1.5 use Media::minifyHTML()
  1822. */
  1823. public static function minifyHTML($html_content)
  1824. {
  1825. Tools::displayAsDeprecated();
  1826. return Media::minifyHTML($html_content);
  1827. }
  1828.  
  1829. /**
  1830. * Translates a string with underscores into camel case (e.g. first_name -> firstName)
  1831. * @prototype string public static function toCamelCase(string $str[, bool $capitalise_first_char = false])
  1832. */
  1833. public static function toCamelCase($str, $catapitalise_first_char = false)
  1834. {
  1835. $str = Tools::strtolower($str);
  1836. if ($catapitalise_first_char)
  1837. $str = Tools::ucfirst($str);
  1838. return preg_replace_callback('/_+([a-z])/', create_function('$c', 'return strtoupper($c[1]);'), $str);
  1839. }
  1840.  
  1841. /**
  1842. * Transform a CamelCase string to underscore_case string
  1843. *
  1844. * @param string $string
  1845. * @return string
  1846. */
  1847. public static function toUnderscoreCase($string)
  1848. {
  1849. // 'CMSCategories' => 'cms_categories'
  1850. // 'RangePrice' => 'range_price'
  1851. return Tools::strtolower(trim(preg_replace('/([A-Z][a-z])/', '_$1', $string), '_'));
  1852. }
  1853.  
  1854. public static function getBrightness($hex)
  1855. {
  1856. $hex = str_replace('#', '', $hex);
  1857. $r = hexdec(substr($hex, 0, 2));
  1858. $g = hexdec(substr($hex, 2, 2));
  1859. $b = hexdec(substr($hex, 4, 2));
  1860. return (($r * 299) + ($g * 587) + ($b * 114)) / 1000;
  1861. }
  1862.  
  1863. /**
  1864. * @deprecated as of 1.5 use Media::minifyHTMLpregCallback()
  1865. */
  1866. public static function minifyHTMLpregCallback($preg_matches)
  1867. {
  1868. Tools::displayAsDeprecated();
  1869. return Media::minifyHTMLpregCallback($preg_matches);
  1870. }
  1871.  
  1872. /**
  1873. * @deprecated as of 1.5 use Media::packJSinHTML()
  1874. */
  1875. public static function packJSinHTML($html_content)
  1876. {
  1877. Tools::displayAsDeprecated();
  1878. return Media::packJSinHTML($html_content);
  1879. }
  1880.  
  1881. /**
  1882. * @deprecated as of 1.5 use Media::packJSinHTMLpregCallback()
  1883. */
  1884. public static function packJSinHTMLpregCallback($preg_matches)
  1885. {
  1886. Tools::displayAsDeprecated();
  1887. return Media::packJSinHTMLpregCallback($preg_matches);
  1888. }
  1889.  
  1890. /**
  1891. * @deprecated as of 1.5 use Media::packJS()
  1892. */
  1893. public static function packJS($js_content)
  1894. {
  1895. Tools::displayAsDeprecated();
  1896. return Media::packJS($js_content);
  1897. }
  1898.  
  1899.  
  1900. public static function parserSQL($sql)
  1901. {
  1902. if (strlen($sql) > 0)
  1903. {
  1904. require_once(_PS_TOOL_DIR_.'parser_sql/PHPSQLParser.php');
  1905. $parser = new PHPSQLParser($sql);
  1906. return $parser->parsed;
  1907. }
  1908. return false;
  1909. }
  1910.  
  1911. /**
  1912. * @deprecated as of 1.5 use Media::minifyCSS()
  1913. */
  1914. public static function minifyCSS($css_content, $fileuri = false)
  1915. {
  1916. Tools::displayAsDeprecated();
  1917. return Media::minifyCSS($css_content, $fileuri);
  1918. }
  1919.  
  1920. public static function replaceByAbsoluteURL($matches)
  1921. {
  1922. global $current_css_file;
  1923. $protocol_link = Tools::getCurrentUrlProtocolPrefix();
  1924. if (array_key_exists(1, $matches) && array_key_exists(2, $matches))
  1925. {
  1926. if (!preg_match('/^(?:https?:)?\/\//iUs', $matches[2]))
  1927. {
  1928. $tmp = dirname($current_css_file).'/'.$matches[2];
  1929. return $matches[1].$protocol_link.Tools::getMediaServer($tmp).$tmp;
  1930. }
  1931. else
  1932. return $matches[0];
  1933. }
  1934. return false;
  1935. }
  1936.  
  1937. /**
  1938. * addJS load a javascript file in the header
  1939. *
  1940. * @deprecated as of 1.5 use FrontController->addJS()
  1941. * @param mixed $js_uri
  1942. * @return void
  1943. */
  1944. public static function addJS($js_uri)
  1945. {
  1946. Tools::displayAsDeprecated();
  1947. $context = Context::getContext();
  1948. $context->controller->addJs($js_uri);
  1949. }
  1950.  
  1951. /**
  1952. * @deprecated as of 1.5 use FrontController->addCSS()
  1953. */
  1954. public static function addCSS($css_uri, $css_media_type = 'all')
  1955. {
  1956. Tools::displayAsDeprecated();
  1957. $context = Context::getContext();
  1958. $context->controller->addCSS($css_uri, $css_media_type);
  1959. }
  1960.  
  1961. /**
  1962. * @deprecated as of 1.5 use Media::cccCss()
  1963. */
  1964. public static function cccCss($css_files)
  1965. {
  1966. Tools::displayAsDeprecated();
  1967. return Media::cccCss($css_files);
  1968. }
  1969.  
  1970.  
  1971. /**
  1972. * @deprecated as of 1.5 use Media::cccJS()
  1973. */
  1974. public static function cccJS($js_files)
  1975. {
  1976. Tools::displayAsDeprecated();
  1977. return Media::cccJS($js_files);
  1978. }
  1979.  
  1980. protected static $_cache_nb_media_servers = null;
  1981.  
  1982. public static function getMediaServer($filename)
  1983. {
  1984. if (self::$_cache_nb_media_servers === null && defined('_MEDIA_SERVER_1_') && defined('_MEDIA_SERVER_2_') && defined('_MEDIA_SERVER_3_'))
  1985. {
  1986. if (_MEDIA_SERVER_1_ == '')
  1987. self::$_cache_nb_media_servers = 0;
  1988. elseif (_MEDIA_SERVER_2_ == '')
  1989. self::$_cache_nb_media_servers = 1;
  1990. elseif (_MEDIA_SERVER_3_ == '')
  1991. self::$_cache_nb_media_servers = 2;
  1992. else
  1993. self::$_cache_nb_media_servers = 3;
  1994. }
  1995.  
  1996. if (self::$_cache_nb_media_servers && ($id_media_server = (abs(crc32($filename)) % self::$_cache_nb_media_servers + 1)))
  1997. return constant('_MEDIA_SERVER_'.$id_media_server.'_');
  1998.  
  1999. return Tools::usingSecureMode() ? Tools::getShopDomainSSL() : Tools::getShopDomain();
  2000. }
  2001.  
  2002. public static function generateHtaccess($path = null, $rewrite_settings = null, $cache_control = null, $specific = '', $disable_multiviews = null, $medias = false, $disable_modsec = null)
  2003. {
  2004. if (defined('PS_INSTALLATION_IN_PROGRESS') && $rewrite_settings === null)
  2005. return true;
  2006.  
  2007. // Default values for parameters
  2008. if (is_null($path))
  2009. $path = _PS_ROOT_DIR_.'/.htaccess';
  2010. if (is_null($cache_control))
  2011. $cache_control = (int)Configuration::get('PS_HTACCESS_CACHE_CONTROL');
  2012. if (is_null($disable_multiviews))
  2013. $disable_multiviews = (int)Configuration::get('PS_HTACCESS_DISABLE_MULTIVIEWS');
  2014.  
  2015. if ($disable_modsec === null)
  2016. $disable_modsec = (int)Configuration::get('PS_HTACCESS_DISABLE_MODSEC');
  2017.  
  2018. // Check current content of .htaccess and save all code outside of prestashop comments
  2019. $specific_before = $specific_after = '';
  2020. if (file_exists($path))
  2021. {
  2022. $content = file_get_contents($path);
  2023. if (preg_match('#^(.*)\# ~~start~~.*\# ~~end~~[^\n]*(.*)$#s', $content, $m))
  2024. {
  2025. $specific_before = $m[1];
  2026. $specific_after = $m[2];
  2027. }
  2028. else
  2029. {
  2030. // For retrocompatibility
  2031. if (preg_match('#\# http://www\.prestashop\.com - http://www\.prestashop\.com/forums\s*(.*)<IfModule mod_rewrite\.c>#si', $content, $m))
  2032. $specific_before = $m[1];
  2033. else
  2034. $specific_before = $content;
  2035. }
  2036. }
  2037.  
  2038. // Write .htaccess data
  2039. if (!$write_fd = fopen($path, 'w'))
  2040. return false;
  2041. if ($specific_before)
  2042. fwrite($write_fd, trim($specific_before)."\n\n");
  2043.  
  2044. $domains = array();
  2045. foreach (ShopUrl::getShopUrls() as $shop_url)
  2046. {
  2047. if (!isset($domains[$shop_url->domain]))
  2048. $domains[$shop_url->domain] = array();
  2049.  
  2050. $domains[$shop_url->domain][] = array(
  2051. 'physical' => $shop_url->physical_uri,
  2052. 'virtual' => $shop_url->virtual_uri,
  2053. 'id_shop' => $shop_url->id_shop
  2054. );
  2055.  
  2056. if ($shop_url->domain == $shop_url->domain_ssl)
  2057. continue;
  2058.  
  2059. if (!isset($domains[$shop_url->domain_ssl]))
  2060. $domains[$shop_url->domain_ssl] = array();
  2061.  
  2062. $domains[$shop_url->domain_ssl][] = array(
  2063. 'physical' => $shop_url->physical_uri,
  2064. 'virtual' => $shop_url->virtual_uri,
  2065. 'id_shop' => $shop_url->id_shop
  2066. );
  2067. }
  2068.  
  2069. // Write data in .htaccess file
  2070. fwrite($write_fd, "# ~~start~~ Do not remove this comment, Prestashop will keep automatically the code outside this comment when .htaccess will be generated again\n");
  2071. fwrite($write_fd, "# .htaccess automaticaly generated by PrestaShop e-commerce open-source solution\n");
  2072. fwrite($write_fd, "# http://www.prestashop.com - http://www.prestashop.com/forums\n\n");
  2073.  
  2074. if ($disable_modsec)
  2075. fwrite($write_fd, "<IfModule mod_security.c>\nSecFilterEngine Off\nSecFilterScanPOST Off\n</IfModule>\n\n");
  2076.  
  2077. // RewriteEngine
  2078. fwrite($write_fd, "<IfModule mod_rewrite.c>\n");
  2079.  
  2080. // Ensure HTTP_MOD_REWRITE variable is set in environment
  2081. fwrite($write_fd, "<IfModule mod_env.c>\n");
  2082. fwrite($write_fd, "SetEnv HTTP_MOD_REWRITE On\n");
  2083. fwrite($write_fd, "</IfModule>\n\n");
  2084.  
  2085. // Disable multiviews ?
  2086. if ($disable_multiviews)
  2087. fwrite($write_fd, "\n# Disable Multiviews\nOptions -Multiviews\n\n");
  2088.  
  2089. fwrite($write_fd, "RewriteEngine on\n");
  2090.  
  2091. if (!$medias && defined('_MEDIA_SERVER_1_') && defined('_MEDIA_SERVER_2_') && defined('_MEDIA_SERVER_3_'))
  2092. $medias = array(_MEDIA_SERVER_1_, _MEDIA_SERVER_2_, _MEDIA_SERVER_3_);
  2093.  
  2094. $media_domains = '';
  2095. if ($medias[0] != '')
  2096. $media_domains = 'RewriteCond %{HTTP_HOST} ^'.$medias[0].'$ [OR]'."\n";
  2097. if ($medias[1] != '')
  2098. $media_domains .= 'RewriteCond %{HTTP_HOST} ^'.$medias[1].'$ [OR]'."\n";
  2099. if ($medias[2] != '')
  2100. $media_domains .= 'RewriteCond %{HTTP_HOST} ^'.$medias[2].'$ [OR]'."\n";
  2101.  
  2102. if (Configuration::get('PS_WEBSERVICE_CGI_HOST'))
  2103. fwrite($write_fd, "RewriteCond %{HTTP:Authorization} ^(.*)\nRewriteRule . - [E=HTTP_AUTHORIZATION:%1]\n\n");
  2104.  
  2105. foreach ($domains as $domain => $list_uri)
  2106. {
  2107. $physicals = array();
  2108. foreach ($list_uri as $uri)
  2109. {
  2110. if (Shop::isFeatureActive())
  2111. fwrite($write_fd, 'RewriteCond %{HTTP_HOST} ^'.$domain.'$'."\n");
  2112. fwrite($write_fd, 'RewriteRule . - [E=REWRITEBASE:'.$uri['physical'].']'."\n");
  2113.  
  2114. // Webservice
  2115. fwrite($write_fd, 'RewriteRule ^api/?(.*)$ %{ENV:REWRITEBASE}webservice/dispatcher.php?url=$1 [QSA,L]'."\n\n");
  2116.  
  2117. if (!$rewrite_settings)
  2118. $rewrite_settings = (int)Configuration::get('PS_REWRITING_SETTINGS', null, null, (int)$uri['id_shop']);
  2119.  
  2120. $domain_rewrite_cond = 'RewriteCond %{HTTP_HOST} ^'.$domain.'$'."\n";
  2121. // Rewrite virtual multishop uri
  2122. if ($uri['virtual'])
  2123. {
  2124. if (!$rewrite_settings)
  2125. {
  2126. fwrite($write_fd, $media_domains);
  2127. if (Shop::isFeatureActive())
  2128. fwrite($write_fd, $domain_rewrite_cond);
  2129. fwrite($write_fd, 'RewriteRule ^'.trim($uri['virtual'], '/').'/?$ '.$uri['physical'].$uri['virtual']."index.php [L,R]\n");
  2130. }
  2131. else
  2132. {
  2133. fwrite($write_fd, $media_domains);
  2134. if (Shop::isFeatureActive())
  2135. fwrite($write_fd, $domain_rewrite_cond);
  2136. fwrite($write_fd, 'RewriteRule ^'.trim($uri['virtual'], '/').'$ '.$uri['physical'].$uri['virtual']." [L,R]\n");
  2137. }
  2138. fwrite($write_fd, $media_domains);
  2139. if (Shop::isFeatureActive())
  2140. fwrite($write_fd, $domain_rewrite_cond);
  2141. fwrite($write_fd, 'RewriteRule ^'.ltrim($uri['virtual'], '/').'(.*) '.$uri['physical']."$1 [L]\n\n");
  2142. }
  2143.  
  2144. if ($rewrite_settings)
  2145. {
  2146. // Compatibility with the old image filesystem
  2147. fwrite($write_fd, "# Images\n");
  2148. if (Configuration::get('PS_LEGACY_IMAGES'))
  2149. {
  2150. fwrite($write_fd, $media_domains);
  2151. if (Shop::isFeatureActive())
  2152. fwrite($write_fd, $domain_rewrite_cond);
  2153. fwrite($write_fd, 'RewriteRule ^([a-z0-9]+)\-([a-z0-9]+)(\-[_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1-$2$3$4.jpg [L]'."\n");
  2154. fwrite($write_fd, $media_domains);
  2155. if (Shop::isFeatureActive())
  2156. fwrite($write_fd, $domain_rewrite_cond);
  2157. fwrite($write_fd, 'RewriteRule ^([0-9]+)\-([0-9]+)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/$1-$2$3.jpg [L]'."\n");
  2158. }
  2159.  
  2160. // Rewrite product images < 100 millions
  2161. for ($i = 1; $i <= 8; $i++)
  2162. {
  2163. $img_path = $img_name = '';
  2164. for ($j = 1; $j <= $i; $j++)
  2165. {
  2166. $img_path .= '$'.$j.'/';
  2167. $img_name .= '$'.$j;
  2168. }
  2169. $img_name .= '$'.$j;
  2170. fwrite($write_fd, $media_domains);
  2171. if (Shop::isFeatureActive())
  2172. fwrite($write_fd, $domain_rewrite_cond);
  2173. fwrite($write_fd, 'RewriteRule ^'.str_repeat('([0-9])', $i).'(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/p/'.$img_path.$img_name.'$'.($j + 1).".jpg [L]\n");
  2174. }
  2175. fwrite($write_fd, $media_domains);
  2176. if (Shop::isFeatureActive())
  2177. fwrite($write_fd, $domain_rewrite_cond);
  2178. fwrite($write_fd, 'RewriteRule ^c/([0-9]+)(\-[\.*_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1$2$3.jpg [L]'."\n");
  2179. fwrite($write_fd, $media_domains);
  2180. if (Shop::isFeatureActive())
  2181. fwrite($write_fd, $domain_rewrite_cond);
  2182. fwrite($write_fd, 'RewriteRule ^c/([a-zA-Z_-]+)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1$2.jpg [L]'."\n");
  2183. }
  2184.  
  2185. fwrite($write_fd, "# AlphaImageLoader for IE and fancybox\n");
  2186. if (Shop::isFeatureActive())
  2187. fwrite($write_fd, $domain_rewrite_cond);
  2188. fwrite($write_fd, 'RewriteRule ^images_ie/?([^/]+)\.(jpe?g|png|gif)$ js/jquery/plugins/fancybox/images/$1.$2 [L]'."\n");
  2189. }
  2190. // Redirections to dispatcher
  2191. if ($rewrite_settings)
  2192. {
  2193. fwrite($write_fd, "\n# Dispatcher\n");
  2194. fwrite($write_fd, "RewriteCond %{REQUEST_FILENAME} -s [OR]\n");
  2195. fwrite($write_fd, "RewriteCond %{REQUEST_FILENAME} -l [OR]\n");
  2196. fwrite($write_fd, "RewriteCond %{REQUEST_FILENAME} -d\n");
  2197. if (Shop::isFeatureActive())
  2198. fwrite($write_fd, $domain_rewrite_cond);
  2199. fwrite($write_fd, "RewriteRule ^.*$ - [NC,L]\n");
  2200. if (Shop::isFeatureActive())
  2201. fwrite($write_fd, $domain_rewrite_cond);
  2202. fwrite($write_fd, "RewriteRule ^.*\$ %{ENV:REWRITEBASE}index.php [NC,L]\n");
  2203. }
  2204. }
  2205.  
  2206. fwrite($write_fd, "</IfModule>\n\n");
  2207.  
  2208. fwrite($write_fd, "AddType application/vnd.ms-fontobject .eot\n");
  2209. fwrite($write_fd, "AddType font/ttf .ttf\n");
  2210. fwrite($write_fd, "AddType font/otf .otf\n");
  2211. fwrite($write_fd, "AddType application/x-font-woff .woff\n\n");
  2212.  
  2213. // Cache control
  2214. if ($cache_control)
  2215. {
  2216. $cache_control = "<IfModule mod_expires.c>
  2217. ExpiresActive On
  2218. ExpiresByType image/gif \"access plus 1 month\"
  2219. ExpiresByType image/jpeg \"access plus 1 month\"
  2220. ExpiresByType image/png \"access plus 1 month\"
  2221. ExpiresByType text/css \"access plus 1 week\"
  2222. ExpiresByType text/javascript \"access plus 1 week\"
  2223. ExpiresByType application/javascript \"access plus 1 week\"
  2224. ExpiresByType application/x-javascript \"access plus 1 week\"
  2225. ExpiresByType image/x-icon \"access plus 1 year\"
  2226. ExpiresByType image/svg+xml \"access plus 1 year\"
  2227. ExpiresByType image/vnd.microsoft.icon \"access plus 1 year\"
  2228. ExpiresByType application/font-woff \"access plus 1 year\"
  2229. ExpiresByType application/x-font-woff \"access plus 1 year\"
  2230. ExpiresByType application/vnd.ms-fontobject \"access plus 1 year\"
  2231. ExpiresByType font/opentype \"access plus 1 year\"
  2232. ExpiresByType font/ttf \"access plus 1 year\"
  2233. ExpiresByType font/otf \"access plus 1 year\"
  2234. ExpiresByType application/x-font-ttf \"access plus 1 year\"
  2235. ExpiresByType application/x-font-otf \"access plus 1 year\"
  2236. </IfModule>
  2237.  
  2238. FileETag INode MTime Size
  2239. <IfModule mod_deflate.c>
  2240. <IfModule mod_filter.c>
  2241. AddOutputFilterByType DEFLATE text/html text/css text/javascript application/javascript application/x-javascript
  2242. </IfModule>
  2243. </IfModule>\n\n";
  2244. fwrite($write_fd, $cache_control);
  2245. }
  2246.  
  2247. // In case the user hasn't rewrite mod enabled
  2248. fwrite($write_fd, "#If rewrite mod isn't enabled\n");
  2249.  
  2250. // Do not remove ($domains is already iterated upper)
  2251. reset($domains);
  2252. $domain = current($domains);
  2253. fwrite($write_fd, 'ErrorDocument 404 '.$domain[0]['physical']."index.php?controller=404\n\n");
  2254.  
  2255. fwrite($write_fd, "# ~~end~~ Do not remove this comment, Prestashop will keep automatically the code outside this comment when .htaccess will be generated again");
  2256. if ($specific_after)
  2257. fwrite($write_fd, "\n\n".trim($specific_after));
  2258. fclose($write_fd);
  2259.  
  2260. if (!defined('PS_INSTALLATION_IN_PROGRESS'))
  2261. Hook::exec('actionHtaccessCreate');
  2262.  
  2263. return true;
  2264. }
  2265.  
  2266. public static function generateIndex()
  2267. {
  2268. if (defined('_DB_PREFIX_') && Configuration::get('PS_DISABLE_OVERRIDES'))
  2269. PrestaShopAutoload::getInstance()->_include_override_path = false;
  2270. PrestaShopAutoload::getInstance()->generateIndex();
  2271. }
  2272.  
  2273. public static function getDefaultIndexContent()
  2274. {
  2275. return '<?php
  2276. /*
  2277. * 2007-'.date('Y').' PrestaShop
  2278. *
  2279. * NOTICE OF LICENSE
  2280. *
  2281. * This source file is subject to the Open Software License (OSL 3.0)
  2282. * that is bundled with this package in the file LICENSE.txt.
  2283. * It is also available through the world-wide-web at this URL:
  2284. * http://opensource.org/licenses/osl-3.0.php
  2285. * If you did not receive a copy of the license and are unable to
  2286. * obtain it through the world-wide-web, please send an email
  2287. * to license@prestashop.com so we can send you a copy immediately.
  2288. *
  2289. * DISCLAIMER
  2290. *
  2291. * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
  2292. * versions in the future. If you wish to customize PrestaShop for your
  2293. * needs please refer to http://www.prestashop.com for more information.
  2294. *
  2295. * @author PrestaShop SA <contact@prestashop.com>
  2296. * @copyright 2007-'.date('Y').' PrestaShop SA
  2297. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  2298. * International Registered Trademark & Property of PrestaShop SA
  2299. */
  2300.  
  2301. header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  2302. header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
  2303.  
  2304. header("Cache-Control: no-store, no-cache, must-revalidate");
  2305. header("Cache-Control: post-check=0, pre-check=0", false);
  2306. header("Pragma: no-cache");
  2307.  
  2308. header("Location: ../");
  2309. exit;
  2310. ';
  2311. }
  2312.  
  2313. /**
  2314. * jsonDecode convert json string to php array / object
  2315. *
  2316. * @param string $json
  2317. * @param boolean $assoc (since 1.4.2.4) if true, convert to associativ array
  2318. * @return array
  2319. */
  2320. public static function jsonDecode($json, $assoc = false)
  2321. {
  2322. if (function_exists('json_decode'))
  2323. return json_decode($json, $assoc);
  2324. else
  2325. {
  2326. include_once(_PS_TOOL_DIR_.'json/json.php');
  2327. $pear_json = new Services_JSON(($assoc) ? SERVICES_JSON_LOOSE_TYPE : 0);
  2328. return $pear_json->decode($json);
  2329. }
  2330. }
  2331.  
  2332. /**
  2333. * Convert an array to json string
  2334. *
  2335. * @param array $data
  2336. * @return string json
  2337. */
  2338. public static function jsonEncode($data)
  2339. {
  2340. if (function_exists('json_encode'))
  2341. return json_encode($data);
  2342. else
  2343. {
  2344. include_once(_PS_TOOL_DIR_.'json/json.php');
  2345. $pear_json = new Services_JSON();
  2346. return $pear_json->encode($data);
  2347. }
  2348. }
  2349.  
  2350. /**
  2351. * Display a warning message indicating that the method is deprecated
  2352. */
  2353. public static function displayAsDeprecated($message = null)
  2354. {
  2355. $backtrace = debug_backtrace();
  2356. $callee = next($backtrace);
  2357. $class = isset($callee['class']) ? $callee['class'] : null;
  2358. if ($message === null)
  2359. $message = 'The function '.$callee['function'].' (Line '.$callee['line'].') is deprecated and will be removed in the next major version.';
  2360. $error = 'Function <b>'.$callee['function'].'()</b> is deprecated in <b>'.$callee['file'].'</b> on line <b>'.$callee['line'].'</b><br />';
  2361.  
  2362. Tools::throwDeprecated($error, $message, $class);
  2363. }
  2364.  
  2365. /**
  2366. * Display a warning message indicating that the parameter is deprecated
  2367. */
  2368. public static function displayParameterAsDeprecated($parameter)
  2369. {
  2370. $backtrace = debug_backtrace();
  2371. $callee = next($backtrace);
  2372. $error = 'Parameter <b>'.$parameter.'</b> in function <b>'.(isset($callee['function']) ? $callee['function'] : '').'()</b> is deprecated in <b>'.$callee['file'].'</b> on line <b>'.(isset($callee['line']) ? $callee['line'] : '(undefined)').'</b><br />';
  2373. $message = 'The parameter '.$parameter.' in function '.$callee['function'].' (Line '.(isset($callee['line']) ? $callee['line'] : 'undefined').') is deprecated and will be removed in the next major version.';
  2374. $class = isset($callee['class']) ? $callee['class'] : null;
  2375.  
  2376. Tools::throwDeprecated($error, $message, $class);
  2377. }
  2378.  
  2379. public static function displayFileAsDeprecated()
  2380. {
  2381. $backtrace = debug_backtrace();
  2382. $callee = current($backtrace);
  2383. $error = 'File <b>'.$callee['file'].'</b> is deprecated<br />';
  2384. $message = 'The file '.$callee['file'].' is deprecated and will be removed in the next major version.';
  2385. $class = isset($callee['class']) ? $callee['class'] : null;
  2386.  
  2387. Tools::throwDeprecated($error, $message, $class);
  2388. }
  2389.  
  2390. protected static function throwDeprecated($error, $message, $class)
  2391. {
  2392. if (_PS_DISPLAY_COMPATIBILITY_WARNING_)
  2393. {
  2394. trigger_error($error, E_USER_WARNING);
  2395. PrestaShopLogger::addLog($message, 3, $class);
  2396. }
  2397. }
  2398.  
  2399. public static function enableCache($level = 1, Context $context = null)
  2400. {
  2401. if (!$context)
  2402. $context = Context::getContext();
  2403. $smarty = $context->smarty;
  2404. if (!Configuration::get('PS_SMARTY_CACHE'))
  2405. return;
  2406. if ($smarty->force_compile == 0 && $smarty->caching == $level)
  2407. return;
  2408. self::$_forceCompile = (int)$smarty->force_compile;
  2409. self::$_caching = (int)$smarty->caching;
  2410. $smarty->force_compile = 0;
  2411. $smarty->caching = (int)$level;
  2412. $smarty->cache_lifetime = 31536000; // 1 Year
  2413. }
  2414.  
  2415. public static function restoreCacheSettings(Context $context = null)
  2416. {
  2417. if (!$context)
  2418. $context = Context::getContext();
  2419.  
  2420. if (isset(self::$_forceCompile))
  2421. $context->smarty->force_compile = (int)self::$_forceCompile;
  2422. if (isset(self::$_caching))
  2423. $context->smarty->caching = (int)self::$_caching;
  2424. }
  2425.  
  2426. public static function isCallable($function)
  2427. {
  2428. $disabled = explode(',', ini_get('disable_functions'));
  2429. return (!in_array($function, $disabled) && is_callable($function));
  2430. }
  2431.  
  2432. public static function pRegexp($s, $delim)
  2433. {
  2434. $s = str_replace($delim, '\\'.$delim, $s);
  2435. foreach (array('?', '[', ']', '(', ')', '{', '}', '-', '.', '+', '*', '^', '$', '`', '"', '%') as $char)
  2436. $s = str_replace($char, '\\'.$char, $s);
  2437. return $s;
  2438. }
  2439.  
  2440. public static function str_replace_once($needle, $replace, $haystack)
  2441. {
  2442. $pos = false;
  2443. if ($needle)
  2444. $pos = strpos($haystack, $needle);
  2445. if ($pos === false)
  2446. return $haystack;
  2447. return substr_replace($haystack, $replace, $pos, strlen($needle));
  2448. }
  2449.  
  2450. /**
  2451. * Function property_exists does not exist in PHP < 5.1
  2452. *
  2453. * @deprecated since 1.5.0 (PHP 5.1 required, so property_exists() is now natively supported)
  2454. * @param object or class $class
  2455. * @param string $property
  2456. * @return boolean
  2457. */
  2458. public static function property_exists($class, $property)
  2459. {
  2460. Tools::displayAsDeprecated();
  2461.  
  2462. if (function_exists('property_exists'))
  2463. return property_exists($class, $property);
  2464.  
  2465. if (is_object($class))
  2466. $vars = get_object_vars($class);
  2467. else
  2468. $vars = get_class_vars($class);
  2469.  
  2470. return array_key_exists($property, $vars);
  2471. }
  2472.  
  2473. /**
  2474. * @desc identify the version of php
  2475. * @return string
  2476. */
  2477. public static function checkPhpVersion()
  2478. {
  2479. $version = null;
  2480.  
  2481. if (defined('PHP_VERSION'))
  2482. $version = PHP_VERSION;
  2483. else
  2484. $version = phpversion('');
  2485.  
  2486. //Case management system of ubuntu, php version return 5.2.4-2ubuntu5.2
  2487. if (strpos($version, '-') !== false)
  2488. $version = substr($version, 0, strpos($version, '-'));
  2489.  
  2490. return $version;
  2491. }
  2492.  
  2493. /**
  2494. * @desc try to open a zip file in order to check if it's valid
  2495. * @return bool success
  2496. */
  2497. public static function ZipTest($from_file)
  2498. {
  2499. if (class_exists('ZipArchive', false))
  2500. {
  2501. $zip = new ZipArchive();
  2502. return ($zip->open($from_file, ZIPARCHIVE::CHECKCONS) === true);
  2503. }
  2504. else
  2505. {
  2506. require_once(_PS_ROOT_DIR_.'/tools/pclzip/pclzip.lib.php');
  2507. $zip = new PclZip($from_file);
  2508. return ($zip->privCheckFormat() === true);
  2509. }
  2510. }
  2511.  
  2512. public static function getSafeModeStatus()
  2513. {
  2514. if (!$safe_mode = @ini_get('safe_mode'))
  2515. $safe_mode = '';
  2516. return in_array(Tools::strtolower($safe_mode), array(1, 'on'));
  2517. }
  2518.  
  2519. /**
  2520. * @desc extract a zip file to the given directory
  2521. * @return bool success
  2522. */
  2523. public static function ZipExtract($from_file, $to_dir)
  2524. {
  2525. if (!file_exists($to_dir))
  2526. mkdir($to_dir, 0777);
  2527. if (class_exists('ZipArchive', false))
  2528. {
  2529. $zip = new ZipArchive();
  2530. if ($zip->open($from_file) === true && $zip->extractTo($to_dir) && $zip->close())
  2531. return true;
  2532. return false;
  2533. }
  2534. else
  2535. {
  2536. require_once(_PS_ROOT_DIR_.'/tools/pclzip/pclzip.lib.php');
  2537. $zip = new PclZip($from_file);
  2538. $list = $zip->extract(PCLZIP_OPT_PATH, $to_dir, PCLZIP_OPT_REPLACE_NEWER);
  2539. foreach ($list as $file)
  2540. if ($file['status'] != 'ok' && $file['status'] != 'already_a_directory')
  2541. return false;
  2542. return true;
  2543. }
  2544. }
  2545.  
  2546. public static function chmodr($path, $filemode)
  2547. {
  2548. if (!is_dir($path))
  2549. return @chmod($path, $filemode);
  2550. $dh = opendir($path);
  2551. while (($file = readdir($dh)) !== false)
  2552. {
  2553. if ($file != '.' && $file != '..')
  2554. {
  2555. $fullpath = $path.'/'.$file;
  2556. if (is_link($fullpath))
  2557. return false;
  2558. elseif (!is_dir($fullpath) && !@chmod($fullpath, $filemode))
  2559. return false;
  2560. elseif (!Tools::chmodr($fullpath, $filemode))
  2561. return false;
  2562. }
  2563. }
  2564. closedir($dh);
  2565. if (@chmod($path, $filemode))
  2566. return true;
  2567. else
  2568. return false;
  2569. }
  2570.  
  2571. /**
  2572. * Get products order field name for queries.
  2573. *
  2574. * @param string $type by|way
  2575. * @param string $value If no index given, use default order from admin -> pref -> products
  2576. * @param bool|\bool(false)|string $prefix
  2577. *
  2578. * @return string Order by sql clause
  2579. */
  2580. public static function getProductsOrder($type, $value = null, $prefix = false)
  2581. {
  2582. switch ($type)
  2583. {
  2584. case 'by' :
  2585. $list = array(0 => 'name', 1 => 'price', 2 => 'date_add', 3 => 'date_upd', 4 => 'position', 5 => 'manufacturer_name', 6 => 'quantity');
  2586. $value = (is_null($value) || $value === false || $value === '') ? (int)Configuration::get('PS_PRODUCTS_ORDER_BY') : $value;
  2587. $value = (isset($list[$value])) ? $list[$value] : ((in_array($value, $list)) ? $value : 'position');
  2588. $order_by_prefix = '';
  2589. if ($prefix)
  2590. {
  2591. if ($value == 'id_product' || $value == 'date_add' || $value == 'date_upd' || $value == 'price')
  2592. $order_by_prefix = 'p.';
  2593. elseif ($value == 'name')
  2594. $order_by_prefix = 'pl.';
  2595. elseif ($value == 'manufacturer_name' && $prefix)
  2596. {
  2597. $order_by_prefix = 'm.';
  2598. $value = 'name';
  2599. }
  2600. elseif ($value == 'position' || empty($value))
  2601. $order_by_prefix = 'cp.';
  2602. }
  2603.  
  2604. return $order_by_prefix.$value;
  2605. break;
  2606.  
  2607. case 'way' :
  2608. $value = (is_null($value) || $value === false || $value === '') ? (int)Configuration::get('PS_PRODUCTS_ORDER_WAY') : $value;
  2609. $list = array(0 => 'asc', 1 => 'desc');
  2610. return ((isset($list[$value])) ? $list[$value] : ((in_array($value, $list)) ? $value : 'asc'));
  2611. break;
  2612. }
  2613. }
  2614.  
  2615. /**
  2616. * Convert a shorthand byte value from a PHP configuration directive to an integer value
  2617. * @param string $value value to convert
  2618. * @return int
  2619. */
  2620. public static function convertBytes($value)
  2621. {
  2622. if (is_numeric($value))
  2623. return $value;
  2624. else
  2625. {
  2626. $value_length = strlen($value);
  2627. $qty = (int)substr($value, 0, $value_length - 1 );
  2628. $unit = Tools::strtolower(substr($value, $value_length - 1));
  2629. switch ($unit)
  2630. {
  2631. case 'k':
  2632. $qty *= 1024;
  2633. break;
  2634. case 'm':
  2635. $qty *= 1048576;
  2636. break;
  2637. case 'g':
  2638. $qty *= 1073741824;
  2639. break;
  2640. }
  2641. return $qty;
  2642. }
  2643. }
  2644.  
  2645. /**
  2646. * @deprecated as of 1.5 use Controller::getController('PageNotFoundController')->run();
  2647. */
  2648. public static function display404Error()
  2649. {
  2650. header('HTTP/1.1 404 Not Found');
  2651. header('Status: 404 Not Found');
  2652. include(dirname(__FILE__).'/../404.php');
  2653. die;
  2654. }
  2655.  
  2656. /**
  2657. * Concat $begin and $end, add ? or & between strings
  2658. *
  2659. * @since 1.5.0
  2660. * @param string $begin
  2661. * @param string $end
  2662. * @return string
  2663. */
  2664. public static function url($begin, $end)
  2665. {
  2666. return $begin.((strpos($begin, '?') !== false) ? '&' : '?').$end;
  2667. }
  2668.  
  2669. /**
  2670. * Display error and dies or silently log the error.
  2671. *
  2672. * @param string $msg
  2673. * @param bool $die
  2674. * @return bool success of logging
  2675. */
  2676. public static function dieOrLog($msg, $die = true)
  2677. {
  2678. if ($die || (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_))
  2679. die($msg);
  2680. return PrestaShopLogger::addLog($msg);
  2681. }
  2682.  
  2683. /**
  2684. * Convert \n and \r\n and \r to <br />
  2685. *
  2686. * @param string $string String to transform
  2687. * @return string New string
  2688. */
  2689. public static function nl2br($str)
  2690. {
  2691. return str_replace(array("\r\n", "\r", "\n"), '<br />', $str);
  2692. }
  2693.  
  2694. /**
  2695. * Clear cache for Smarty
  2696. *
  2697. * @param Smarty $smarty
  2698. */
  2699. public static function clearCache($smarty = null, $tpl = false, $cache_id = null, $compile_id = null)
  2700. {
  2701. if ($smarty === null)
  2702. $smarty = Context::getContext()->smarty;
  2703.  
  2704. if ($smarty === null)
  2705. return;
  2706.  
  2707. if (!$tpl && $cache_id === null && $compile_id === null)
  2708. return $smarty->clearAllCache();
  2709.  
  2710. return $smarty->clearCache($tpl, $cache_id, $compile_id);
  2711. }
  2712.  
  2713. /**
  2714. * Clear compile for Smarty
  2715. */
  2716. public static function clearCompile($smarty = null)
  2717. {
  2718. if ($smarty === null)
  2719. $smarty = Context::getContext()->smarty;
  2720.  
  2721. if ($smarty === null)
  2722. return;
  2723.  
  2724. return $smarty->clearCompiledTemplate();
  2725. }
  2726.  
  2727. /**
  2728. * Clear Smarty cache and compile folders
  2729. */
  2730. public static function clearSmartyCache()
  2731. {
  2732. $smarty = Context::getContext()->smarty;
  2733. Tools::clearCache($smarty);
  2734. Tools::clearCompile($smarty);
  2735. }
  2736.  
  2737. public static function clearColorListCache($id_product = false)
  2738. {
  2739.  
  2740. // Change template dir if called from the BackOffice
  2741. $current_template_dir = Context::getContext()->smarty->getTemplateDir();
  2742. Context::getContext()->smarty->setTemplateDir(_PS_THEME_DIR_);
  2743. Tools::clearCache(null, 'product-list-colors.tpl', ($id_product ? 'productlist_colors|'.(int)$id_product.'|'.(int)Context::getContext()->shop->id : 'productlist_colors'));
  2744. Context::getContext()->smarty->setTemplateDir($current_template_dir);
  2745. }
  2746.  
  2747. /**
  2748. * getMemoryLimit allow to get the memory limit in octet
  2749. *
  2750. * @since 1.4.5.0
  2751. * @return int the memory limit value in octet
  2752. */
  2753. public static function getMemoryLimit()
  2754. {
  2755. $memory_limit = @ini_get('memory_limit');
  2756.  
  2757. return Tools::getOctets($memory_limit);
  2758. }
  2759.  
  2760. /**
  2761. * getOctet allow to gets the value of a configuration option in octet
  2762. *
  2763. * @since 1.5.0
  2764. * @return int the value of a configuration option in octet
  2765. */
  2766. public static function getOctets($option)
  2767. {
  2768. if (preg_match('/[0-9]+k/i', $option))
  2769. return 1024 * (int)$option;
  2770.  
  2771. if (preg_match('/[0-9]+m/i', $option))
  2772. return 1024 * 1024 * (int)$option;
  2773.  
  2774. if (preg_match('/[0-9]+g/i', $option))
  2775. return 1024 * 1024 * 1024 * (int)$option;
  2776.  
  2777. return $option;
  2778. }
  2779.  
  2780. /**
  2781. *
  2782. * @return bool true if the server use 64bit arch
  2783. */
  2784. public static function isX86_64arch()
  2785. {
  2786. return (PHP_INT_MAX == '9223372036854775807');
  2787. }
  2788.  
  2789. /**
  2790. *
  2791. * @return bool true if php-cli is used
  2792. */
  2793. public static function isPHPCLI()
  2794. {
  2795. return (defined('STDIN') || (Tools::strtolower(php_sapi_name()) == 'cli' && (!isset($_SERVER['REMOTE_ADDR']) || empty($_SERVER['REMOTE_ADDR']))));
  2796. }
  2797.  
  2798. public static function argvToGET($argc, $argv)
  2799. {
  2800. if ($argc <= 1)
  2801. return;
  2802.  
  2803. // get the first argument and parse it like a query string
  2804. parse_str($argv[1], $args);
  2805. if (!is_array($args) || !count($args))
  2806. return;
  2807. $_GET = array_merge($args, $_GET);
  2808. $_SERVER['QUERY_STRING'] = $argv[1];
  2809. }
  2810.  
  2811. /**
  2812. * Get max file upload size considering server settings and optional max value
  2813. *
  2814. * @param int $max_size optional max file size
  2815. * @return int max file size in bytes
  2816. */
  2817. public static function getMaxUploadSize($max_size = 0)
  2818. {
  2819. $post_max_size = Tools::convertBytes(ini_get('post_max_size'));
  2820. $upload_max_filesize = Tools::convertBytes(ini_get('upload_max_filesize'));
  2821. if ($max_size > 0)
  2822. $result = min($post_max_size, $upload_max_filesize, $max_size);
  2823. else
  2824. $result = min($post_max_size, $upload_max_filesize);
  2825. return $result;
  2826. }
  2827.  
  2828. /**
  2829. * apacheModExists return true if the apache module $name is loaded
  2830. * @TODO move this method in class Information (when it will exist)
  2831. *
  2832. * Notes: This method requires either apache_get_modules or phpinfo()
  2833. * to be available. With CGI mod, we cannot get php modules
  2834. *
  2835. * @param string $name module name
  2836. * @return boolean true if exists
  2837. * @since 1.4.5.0
  2838. */
  2839. public static function apacheModExists($name)
  2840. {
  2841. if (function_exists('apache_get_modules'))
  2842. {
  2843. static $apache_module_list = null;
  2844.  
  2845. if (!is_array($apache_module_list))
  2846. $apache_module_list = apache_get_modules();
  2847.  
  2848. // we need strpos (example, evasive can be evasive20)
  2849. foreach ($apache_module_list as $module)
  2850. {
  2851. if (strpos($module, $name) !== false)
  2852. return true;
  2853. }
  2854. }
  2855. return false;
  2856. }
  2857.  
  2858. /**
  2859. * Copy the folder $src into $dst, $dst is created if it do not exist
  2860. * @param $src
  2861. * @param $dst
  2862. * @param bool $del if true, delete the file after copy
  2863. */
  2864. public static function recurseCopy($src, $dst, $del = false)
  2865. {
  2866. if (!Tools::file_exists_cache($src))
  2867. return false;
  2868. $dir = opendir($src);
  2869.  
  2870. if (!Tools::file_exists_cache($dst))
  2871. mkdir($dst);
  2872. while (false !== ($file = readdir($dir)))
  2873. {
  2874. if (($file != '.') && ($file != '..'))
  2875. {
  2876. if (is_dir($src.DIRECTORY_SEPARATOR.$file))
  2877. self::recurseCopy($src.DIRECTORY_SEPARATOR.$file, $dst.DIRECTORY_SEPARATOR.$file, $del);
  2878. else
  2879. {
  2880. copy($src.DIRECTORY_SEPARATOR.$file, $dst.DIRECTORY_SEPARATOR.$file);
  2881. if ($del && is_writable($src.DIRECTORY_SEPARATOR.$file))
  2882. unlink($src.DIRECTORY_SEPARATOR.$file);
  2883. }
  2884. }
  2885. }
  2886. closedir($dir);
  2887. if ($del && is_writable($src))
  2888. rmdir($src);
  2889. }
  2890.  
  2891. /**
  2892. * @params string $path Path to scan
  2893. * @params string $ext Extention to filter files
  2894. * @params string $dir Add this to prefix output for example /path/dir/*
  2895. *
  2896. * @return array List of file found
  2897. * @since 1.5.0
  2898. */
  2899. public static function scandir($path, $ext = 'php', $dir = '', $recursive = false)
  2900. {
  2901. $path = rtrim(rtrim($path, '\\'), '/').'/';
  2902. $real_path = rtrim(rtrim($path.$dir, '\\'), '/').'/';
  2903. $files = scandir($real_path);
  2904. if (!$files)
  2905. return array();
  2906.  
  2907. $filtered_files = array();
  2908.  
  2909. $real_ext = false;
  2910. if (!empty($ext))
  2911. $real_ext = '.'.$ext;
  2912. $real_ext_length = strlen($real_ext);
  2913.  
  2914. $subdir = ($dir) ? $dir.'/' : '';
  2915. foreach ($files as $file)
  2916. {
  2917. if (!$real_ext || (strpos($file, $real_ext) && strpos($file, $real_ext) == (strlen($file) - $real_ext_length)))
  2918. $filtered_files[] = $subdir.$file;
  2919.  
  2920. if ($recursive && $file[0] != '.' && is_dir($real_path.$file))
  2921. foreach (Tools::scandir($path, $ext, $subdir.$file, $recursive) as $subfile)
  2922. $filtered_files[] = $subfile;
  2923. }
  2924. return $filtered_files;
  2925. }
  2926.  
  2927.  
  2928. /**
  2929. * Align version sent and use internal function
  2930. *
  2931. * @static
  2932. * @param $v1
  2933. * @param $v2
  2934. * @param string $operator
  2935. * @return mixed
  2936. */
  2937. public static function version_compare($v1, $v2, $operator = '<')
  2938. {
  2939. Tools::alignVersionNumber($v1, $v2);
  2940. return version_compare($v1, $v2, $operator);
  2941. }
  2942.  
  2943. /**
  2944. * Align 2 version with the same number of sub version
  2945. * version_compare will work better for its comparison :)
  2946. * (Means: '1.8' to '1.9.3' will change '1.8' to '1.8.0')
  2947. * @static
  2948. * @param $v1
  2949. * @param $v2
  2950. */
  2951. public static function alignVersionNumber(&$v1, &$v2)
  2952. {
  2953. $len1 = count(explode('.', trim($v1, '.')));
  2954. $len2 = count(explode('.', trim($v2, '.')));
  2955. $len = 0;
  2956. $str = '';
  2957.  
  2958. if ($len1 > $len2)
  2959. {
  2960. $len = $len1 - $len2;
  2961. $str = &$v2;
  2962. }
  2963. else if ($len2 > $len1)
  2964. {
  2965. $len = $len2 - $len1;
  2966. $str = &$v1;
  2967. }
  2968.  
  2969. for ($len; $len > 0; $len--)
  2970. $str .= '.0';
  2971. }
  2972.  
  2973. public static function modRewriteActive()
  2974. {
  2975. if (Tools::apacheModExists('mod_rewrite'))
  2976. return true;
  2977. if ((isset($_SERVER['HTTP_MOD_REWRITE']) && Tools::strtolower($_SERVER['HTTP_MOD_REWRITE']) == 'on') || Tools::strtolower(getenv('HTTP_MOD_REWRITE')) == 'on')
  2978. return true;
  2979. return false;
  2980. }
  2981.  
  2982. public static function unSerialize($serialized, $object = false)
  2983. {
  2984. if (is_string($serialized) && (strpos($serialized, 'O:') === false || !preg_match('/(^|;|{|})O:[0-9]+:"/', $serialized)) && !$object || $object)
  2985. return @unserialize($serialized);
  2986.  
  2987. return false;
  2988. }
  2989.  
  2990. /**
  2991. * Reproduce array_unique working before php version 5.2.9
  2992. * @param array $array
  2993. * @return array
  2994. */
  2995. public static function arrayUnique($array)
  2996. {
  2997. if (version_compare(phpversion(), '5.2.9', '<'))
  2998. return array_unique($array);
  2999. else
  3000. return array_unique($array, SORT_REGULAR);
  3001. }
  3002.  
  3003. /**
  3004. * Delete unicode class from regular expression patterns
  3005. * @param string $pattern
  3006. * @return pattern
  3007. */
  3008. public static function cleanNonUnicodeSupport($pattern)
  3009. {
  3010. if (!defined('PREG_BAD_UTF8_OFFSET'))
  3011. return $pattern;
  3012. return preg_replace('/\\\[px]\{[a-z]{1,2}\}|(\/[a-z]*)u([a-z]*)$/i', "$1$2", $pattern);
  3013. }
  3014.  
  3015. protected static $is_addons_up = true;
  3016. public static function addonsRequest($request, $params = array())
  3017. {
  3018. if (!self::$is_addons_up)
  3019. return false;
  3020.  
  3021. $postData = http_build_query(array(
  3022. 'version' => isset($params['version']) ? $params['version'] : _PS_VERSION_,
  3023. 'iso_lang' => Tools::strtolower(isset($params['iso_lang']) ? $params['iso_lang'] : Context::getContext()->language->iso_code),
  3024. 'iso_code' => Tools::strtolower(isset($params['iso_country']) ? $params['iso_country'] : Country::getIsoById(Configuration::get('PS_COUNTRY_DEFAULT'))),
  3025. 'shop_url' => isset($params['shop_url']) ? $params['shop_url'] : Tools::getShopDomain(),
  3026. 'mail' => isset($params['email']) ? $params['email'] : Configuration::get('PS_SHOP_EMAIL')
  3027. ));
  3028.  
  3029. $protocols = array('https');
  3030. switch ($request)
  3031. {
  3032. case 'native':
  3033. $protocols[] = 'http';
  3034. $postData .= '&method=listing&action=native';
  3035. break;
  3036. case 'native_all':
  3037. $protocols[] = 'http';
  3038. $postData .= '&method=listing&action=native&iso_code=all';
  3039. break;
  3040. case 'must-have':
  3041. $protocols[] = 'http';
  3042. $postData .= '&method=listing&action=must-have';
  3043. break;
  3044. case 'must-have-themes':
  3045. $protocols[] = 'http';
  3046. $postData .= '&method=listing&action=must-have-themes';
  3047. break;
  3048. case 'customer':
  3049. $postData .= '&method=listing&action=customer&username='.urlencode(trim(Context::getContext()->cookie->username_addons)).'&password='.urlencode(trim(Context::getContext()->cookie->password_addons));
  3050. break;
  3051. case 'customer_themes':
  3052. $postData .= '&method=listing&action=customer-themes&username='.urlencode(trim(Context::getContext()->cookie->username_addons)).'&password='.urlencode(trim(Context::getContext()->cookie->password_addons));
  3053. break;
  3054. case 'check_customer':
  3055. $postData .= '&method=check_customer&username='.urlencode($params['username_addons']).'&password='.urlencode($params['password_addons']);
  3056. break;
  3057. case 'check_module':
  3058. $postData .= '&method=check&module_name='.urlencode($params['module_name']).'&module_key='.urlencode($params['module_key']);
  3059. break;
  3060. case 'module':
  3061. $postData .= '&method=module&id_module='.urlencode($params['id_module']);
  3062. if (isset($params['username_addons']) && isset($params['password_addons']))
  3063. $postData .= '&username='.urlencode($params['username_addons']).'&password='.urlencode($params['password_addons']);
  3064. else
  3065. $protocols[] = 'http';
  3066. break;
  3067. case 'install-modules':
  3068. $protocols[] = 'http';
  3069. $postData .= '&method=listing&action=install-modules';
  3070. break;
  3071. default:
  3072. return false;
  3073. }
  3074.  
  3075. $context = stream_context_create(array(
  3076. 'http' => array(
  3077. 'method'=> 'POST',
  3078. 'content' => $postData,
  3079. 'header' => 'Content-type: application/x-www-form-urlencoded',
  3080. 'timeout' => 5,
  3081. )
  3082. ));
  3083.  
  3084. foreach ($protocols as $protocol)
  3085. if ($content = Tools::file_get_contents($protocol.'://api.addons.prestashop.com', false, $context))
  3086. return $content;
  3087.  
  3088. self::$is_addons_up = false;
  3089. return false;
  3090. }
  3091.  
  3092. public static function fileAttachment($input = 'fileUpload')
  3093. {
  3094. $fileAttachment = null;
  3095. if (isset($_FILES[$input]['name']) && !empty($_FILES[$input]['name']) && !empty($_FILES[$input]['tmp_name']))
  3096. {
  3097. $fileAttachment['rename'] = uniqid(). Tools::strtolower(substr($_FILES[$input]['name'], -5));
  3098. $fileAttachment['content'] = file_get_contents($_FILES[$input]['tmp_name']);
  3099. $fileAttachment['tmp_name'] = $_FILES[$input]['tmp_name'];
  3100. $fileAttachment['name'] = $_FILES[$input]['name'];
  3101. $fileAttachment['mime'] = $_FILES[$input]['type'];
  3102. $fileAttachment['error'] = $_FILES[$input]['error'];
  3103. }
  3104. return $fileAttachment;
  3105. }
  3106.  
  3107. public static function changeFileMTime($file_name)
  3108. {
  3109. touch($file_name);
  3110. }
  3111.  
  3112. public static function waitUntilFileIsModified($file_name, $timeout = 180)
  3113. {
  3114. @ini_set('max_execution_time', $timeout);
  3115. if (($time_limit = ini_get('max_execution_time')) === null)
  3116. $time_limit = 30;
  3117.  
  3118. $time_limit -= 5;
  3119. $start_time = microtime(true);
  3120. $last_modified = @filemtime($file_name);
  3121.  
  3122. while(true)
  3123. {
  3124. if (((microtime(true) - $start_time) > $time_limit) || @filemtime($file_name) > $last_modified)
  3125. break;
  3126. clearstatcache();
  3127. usleep(300);
  3128. }
  3129. }
  3130.  
  3131. /**
  3132. * Delete a substring from another one starting from the right
  3133. * @param string $str
  3134. * @param string $str_search
  3135. * @return string
  3136. */
  3137. public static function rtrimString($str, $str_search)
  3138. {
  3139. $length_str = strlen($str_search);
  3140. if (strlen($str) >= $length_str && substr($str, -$length_str) == $str_search)
  3141. $str = substr($str, 0, -$length_str);
  3142. return $str;
  3143. }
  3144.  
  3145. /**
  3146. * Format a number into a human readable format
  3147. * e.g. 24962496 => 23.81M
  3148. * @param $size
  3149. * @param int $precision
  3150. *
  3151. * @return string
  3152. */
  3153. public static function formatBytes($size, $precision = 2)
  3154. {
  3155. if (!$size)
  3156. return '0';
  3157. $base = log($size) / log(1024);
  3158. $suffixes = array('', 'k', 'M', 'G', 'T');
  3159.  
  3160. return round(pow(1024, $base - floor($base)), $precision).$suffixes[floor($base)];
  3161. }
  3162.  
  3163. public static function boolVal($value)
  3164. {
  3165. if (empty($value))
  3166. $value = false;
  3167. return (bool)$value;
  3168. }
  3169.  
  3170. public static function getUserPlatform()
  3171. {
  3172. if (isset(self::$_user_plateform))
  3173. return self::$_user_plateform;
  3174.  
  3175. $user_agent = $_SERVER['HTTP_USER_AGENT'];
  3176. self::$_user_plateform = 'unknown';
  3177.  
  3178. if (preg_match('/linux/i', $user_agent))
  3179. self::$_user_plateform = 'Linux';
  3180. elseif (preg_match('/macintosh|mac os x/i', $user_agent))
  3181. self::$_user_plateform = 'Mac';
  3182. elseif (preg_match('/windows|win32/i', $user_agent))
  3183. self::$_user_plateform = 'Windows';
  3184.  
  3185. return self::$_user_plateform;
  3186. }
  3187.  
  3188. public static function getUserBrowser()
  3189. {
  3190. if (isset(self::$_user_browser))
  3191. return self::$_user_browser;
  3192.  
  3193. $user_agent = $_SERVER['HTTP_USER_AGENT'];
  3194. self::$_user_browser = 'unknown';
  3195.  
  3196. if(preg_match('/MSIE/i',$user_agent) && !preg_match('/Opera/i',$user_agent))
  3197. self::$_user_browser = 'Internet Explorer';
  3198. elseif(preg_match('/Firefox/i',$user_agent))
  3199. self::$_user_browser = 'Mozilla Firefox';
  3200. elseif(preg_match('/Chrome/i',$user_agent))
  3201. self::$_user_browser = 'Google Chrome';
  3202. elseif(preg_match('/Safari/i',$user_agent))
  3203. self::$_user_browser = 'Apple Safari';
  3204. elseif(preg_match('/Opera/i',$user_agent))
  3205. self::$_user_browser = 'Opera';
  3206. elseif(preg_match('/Netscape/i',$user_agent))
  3207. self::$_user_browser = 'Netscape';
  3208.  
  3209. return self::$_user_browser;
  3210. }
  3211.  
  3212. /**
  3213. * Allows to display the category description without HTML tags and slashes
  3214. *
  3215. * @return string
  3216. */
  3217. public static function getDescriptionClean($description)
  3218. {
  3219. return strip_tags(stripslashes($description));
  3220. }
  3221.  
  3222. public static function purifyHTML($html)
  3223. {
  3224. static $use_html_purifier = null;
  3225. static $purifier = null;
  3226.  
  3227. if (defined('PS_INSTALLATION_IN_PROGRESS') || !Configuration::configurationIsLoaded())
  3228. return $html;
  3229.  
  3230. if ($use_html_purifier === null)
  3231. $use_html_purifier = (bool)Configuration::get('PS_USE_HTMLPURIFIER');
  3232.  
  3233. if ($use_html_purifier)
  3234. {
  3235. if ($purifier === null)
  3236. {
  3237. $config = HTMLPurifier_Config::createDefault();
  3238. $config->set('Attr.EnableID', true);
  3239. $config->set('HTML.Trusted', true);
  3240. $config->set('Cache.SerializerPath', _PS_CACHE_DIR_.'purifier');
  3241. $config->set('Attr.AllowedFrameTargets', array('_blank', '_self', '_parent', '_top'));
  3242.  
  3243. if (Configuration::get('PS_ALLOW_HTML_IFRAME'))
  3244. {
  3245. $config->set('HTML.SafeIframe', true);
  3246. $config->set('HTML.SafeObject', true);
  3247. $config->set('URI.SafeIframeRegexp','/.*/');
  3248. }
  3249. $purifier = new HTMLPurifier($config);
  3250. }
  3251. if (_PS_MAGIC_QUOTES_GPC_)
  3252. $html = stripslashes($html);
  3253.  
  3254. $html = $purifier->purify($html);
  3255.  
  3256. if (_PS_MAGIC_QUOTES_GPC_)
  3257. $html = addslashes($html);
  3258. }
  3259.  
  3260. return $html;
  3261. }
  3262. }
  3263.  
  3264. /**
  3265. * Compare 2 prices to sort products
  3266. *
  3267. * @param float $a
  3268. * @param float $b
  3269. * @return integer
  3270. */
  3271. /* Externalized because of a bug in PHP 5.1.6 when inside an object */
  3272. function cmpPriceAsc($a, $b)
  3273. {
  3274. if ((float)$a['price_tmp'] < (float)$b['price_tmp'])
  3275. return (-1);
  3276. elseif ((float)$a['price_tmp'] > (float)$b['price_tmp'])
  3277. return (1);
  3278. return 0;
  3279. }
  3280.  
  3281. function cmpPriceDesc($a, $b)
  3282. {
  3283. if ((float)$a['price_tmp'] < (float)$b['price_tmp'])
  3284. return 1;
  3285. elseif ((float)$a['price_tmp'] > (float)$b['price_tmp'])
  3286. return -1;
  3287. return 0;
  3288. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement