PageRenderTime 62ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/classes/Tools.php

https://bitbucket.org/yhjohn/ayanapure.com
PHP | 2273 lines | 1472 code | 242 blank | 559 comment | 359 complexity | 7e73633bf266f3083485202bda52b7cf MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. * 2007-2012 PrestaShop
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@prestashop.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
  18. * versions in the future. If you wish to customize PrestaShop for your
  19. * needs please refer to http://www.prestashop.com for more information.
  20. *
  21. * @author PrestaShop SA <contact@prestashop.com>
  22. * @copyright 2007-2012 PrestaShop SA
  23. * @version Release: $Revision: 7521 $
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. * International Registered Trademark & Property of PrestaShop SA
  26. */
  27. class ToolsCore
  28. {
  29. protected static $file_exists_cache = array();
  30. protected static $_forceCompile;
  31. protected static $_caching;
  32. /**
  33. * Random password generator
  34. *
  35. * @param integer $length Desired length (optional)
  36. * @param string $flag Output type (NUMERIC, ALPHANUMERIC, NO_NUMERIC)
  37. * @return string Password
  38. */
  39. public static function passwdGen($length = 8, $flag = 'ALPHANUMERIC')
  40. {
  41. switch ($flag)
  42. {
  43. case 'NUMERIC':
  44. $str = '0123456789';
  45. break;
  46. case 'NO_NUMERIC':
  47. $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  48. break;
  49. default:
  50. $str = 'abcdefghijkmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  51. break;
  52. }
  53. for ($i = 0, $passwd = ''; $i < $length; $i++)
  54. $passwd .= Tools::substr($str, mt_rand(0, Tools::strlen($str) - 1), 1);
  55. return $passwd;
  56. }
  57. public static function strReplaceFirst($search, $replace, $subject, $cur = 0)
  58. {
  59. return (strpos($subject, $search, $cur))?substr_replace($subject, $replace, (int)strpos($subject, $search, $cur), strlen($search)):$subject;
  60. }
  61. /**
  62. * Redirect user to another page
  63. *
  64. * @param string $url Desired URL
  65. * @param string $baseUri Base URI (optional)
  66. * @param Link $link
  67. * @param string|array $headers A list of headers to send before redirection
  68. */
  69. public static function redirect($url, $base_uri = __PS_BASE_URI__, Link $link = null, $headers = null)
  70. {
  71. if (!$link)
  72. $link = Context::getContext()->link;
  73. if (strpos($url, 'http://') === false && strpos($url, 'https://') === false && $link)
  74. {
  75. if (strpos($url, $base_uri) === 0)
  76. $url = substr($url, strlen($base_uri));
  77. if (strpos($url, 'index.php?controller=') !== false && strpos($url, 'index.php/') == 0)
  78. {
  79. $url = substr($url, strlen('index.php?controller='));
  80. if (Configuration::get('PS_REWRITING_SETTINGS'))
  81. $url = Tools::strReplaceFirst('&', '?', $url);
  82. }
  83. $explode = explode('?', $url);
  84. // don't use ssl if url is home page
  85. // used when logout for example
  86. $use_ssl = !empty($url);
  87. $url = $link->getPageLink($explode[0], $use_ssl);
  88. if (isset($explode[1]))
  89. $url .= '?'.$explode[1];
  90. }
  91. // Send additional headers
  92. if ($headers)
  93. {
  94. if (!is_array($headers))
  95. $headers = array($headers);
  96. foreach ($headers as $header)
  97. header($header);
  98. }
  99. header('Location: '.$url);
  100. exit;
  101. }
  102. /**
  103. * Redirect url wich allready PS_BASE_URI
  104. *
  105. * @param string $url Desired URL
  106. */
  107. public static function redirectLink($url)
  108. {
  109. if (!preg_match('@^https?://@i', $url))
  110. {
  111. if (strpos($url, __PS_BASE_URI__) !== false && strpos($url, __PS_BASE_URI__) == 0)
  112. $url = substr($url, strlen(__PS_BASE_URI__));
  113. if (strpos($url, 'index.php?controller=') !== false && strpos($url, 'index.php/') == 0)
  114. $url = substr($url, strlen('index.php?controller='));
  115. $explode = explode('?', $url);
  116. $url = Context::getContext()->link->getPageLink($explode[0]);
  117. if (isset($explode[1]))
  118. $url .= '?'.$explode[1];
  119. }
  120. header('Location: '.$url);
  121. exit;
  122. }
  123. /**
  124. * Redirect user to another admin page
  125. *
  126. * @param string $url Desired URL
  127. */
  128. public static function redirectAdmin($url)
  129. {
  130. header('Location: '.$url);
  131. exit;
  132. }
  133. /**
  134. * getShopProtocol return the available protocol for the current shop in use
  135. * SSL if Configuration is set on and available for the server
  136. * @static
  137. * @return String
  138. */
  139. public static function getShopProtocol()
  140. {
  141. $protocol = (Configuration::get('PS_SSL_ENABLED') || (!empty($_SERVER['HTTPS'])
  142. && strtolower($_SERVER['HTTPS']) != 'off')) ? 'https://' : 'http://';
  143. return $protocol;
  144. }
  145. /**
  146. * getProtocol return the set protocol according to configuration (http[s])
  147. * @param bool $use_ssl true if require ssl
  148. * @return String (http|https)
  149. */
  150. public static function getProtocol($use_ssl = null)
  151. {
  152. return (!is_null($use_ssl) && $use_ssl ? 'https://' : 'http://');
  153. }
  154. /**
  155. * getHttpHost return the <b>current</b> host used, with the protocol (http or https) if $http is true
  156. * This function should not be used to choose http or https domain name.
  157. * Use Tools::getShopDomain() or Tools::getShopDomainSsl instead
  158. *
  159. * @param boolean $http
  160. * @param boolean $entities
  161. * @return string host
  162. */
  163. public static function getHttpHost($http = false, $entities = false, $ignore_port = false)
  164. {
  165. $host = (isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : $_SERVER['HTTP_HOST']);
  166. if ($ignore_port && $pos = strpos($host, ':'))
  167. $host = substr($host, 0, $pos);
  168. if ($entities)
  169. $host = htmlspecialchars($host, ENT_COMPAT, 'UTF-8');
  170. if ($http)
  171. $host = (Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$host;
  172. return $host;
  173. }
  174. /**
  175. * getShopDomain returns domain name according to configuration and ignoring ssl
  176. *
  177. * @param boolean $http if true, return domain name with protocol
  178. * @param boolean $entities if true,
  179. * @return string domain
  180. */
  181. public static function getShopDomain($http = false, $entities = false)
  182. {
  183. if (!$domain = ShopUrl::getMainShopDomain())
  184. $domain = Tools::getHttpHost();
  185. if ($entities)
  186. $domain = htmlspecialchars($domain, ENT_COMPAT, 'UTF-8');
  187. if ($http)
  188. $domain = 'http://'.$domain;
  189. return $domain;
  190. }
  191. /**
  192. * getShopDomainSsl returns domain name according to configuration and depending on ssl activation
  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 getShopDomainSsl($http = false, $entities = false)
  199. {
  200. if (!$domain = ShopUrl::getMainShopDomainSSL())
  201. $domain = Tools::getHttpHost();
  202. if ($entities)
  203. $domain = htmlspecialchars($domain, ENT_COMPAT, 'UTF-8');
  204. if ($http)
  205. $domain = (Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://').$domain;
  206. return $domain;
  207. }
  208. /**
  209. * Get the server variable SERVER_NAME
  210. *
  211. * @return string server name
  212. */
  213. public static function getServerName()
  214. {
  215. if (isset($_SERVER['HTTP_X_FORWARDED_SERVER']) && $_SERVER['HTTP_X_FORWARDED_SERVER'])
  216. return $_SERVER['HTTP_X_FORWARDED_SERVER'];
  217. return $_SERVER['SERVER_NAME'];
  218. }
  219. /**
  220. * Get the server variable REMOTE_ADDR, or the first ip of HTTP_X_FORWARDED_FOR (when using proxy)
  221. *
  222. * @return string $remote_addr ip of client
  223. */
  224. public static function getRemoteAddr()
  225. {
  226. // This condition is necessary when using CDN, don't remove it.
  227. 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']))))
  228. {
  229. if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ','))
  230. {
  231. $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
  232. return $ips[0];
  233. }
  234. else
  235. return $_SERVER['HTTP_X_FORWARDED_FOR'];
  236. }
  237. return $_SERVER['REMOTE_ADDR'];
  238. }
  239. /**
  240. * Check if the current page use SSL connection on not
  241. *
  242. * @return bool uses SSL
  243. */
  244. public static function usingSecureMode()
  245. {
  246. if (isset($_SERVER['HTTPS']))
  247. return ($_SERVER['HTTPS'] == 1 || strtolower($_SERVER['HTTPS']) == 'on');
  248. // $_SERVER['SSL'] exists only in some specific configuration
  249. if (isset($_SERVER['SSL']))
  250. return ($_SERVER['SSL'] == 1 || strtolower($_SERVER['SSL']) == 'on');
  251. return false;
  252. }
  253. /**
  254. * Get the current url prefix protocol (https/http)
  255. *
  256. * @return string protocol
  257. */
  258. public static function getCurrentUrlProtocolPrefix()
  259. {
  260. if (Tools::usingSecureMode())
  261. return 'https://';
  262. else
  263. return 'http://';
  264. }
  265. /**
  266. * Secure an URL referrer
  267. *
  268. * @param string $referrer URL referrer
  269. * @return string secured referrer
  270. */
  271. public static function secureReferrer($referrer)
  272. {
  273. if (preg_match('/^http[s]?:\/\/'.Tools::getServerName().'(:'._PS_SSL_PORT_.')?\/.*$/Ui', $referrer))
  274. return $referrer;
  275. return __PS_BASE_URI__;
  276. }
  277. /**
  278. * Get a value from $_POST / $_GET
  279. * if unavailable, take a default value
  280. *
  281. * @param string $key Value key
  282. * @param mixed $default_value (optional)
  283. * @return mixed Value
  284. */
  285. public static function getValue($key, $default_value = false)
  286. {
  287. if (!isset($key) || empty($key) || !is_string($key))
  288. return false;
  289. $ret = (isset($_POST[$key]) ? $_POST[$key] : (isset($_GET[$key]) ? $_GET[$key] : $default_value));
  290. if (is_string($ret) === true)
  291. $ret = urldecode(preg_replace('/((\%5C0+)|(\%00+))/i', '', urlencode($ret)));
  292. return !is_string($ret)? $ret : stripslashes($ret);
  293. }
  294. public static function getIsset($key)
  295. {
  296. if (!isset($key) || empty($key) || !is_string($key))
  297. return false;
  298. return isset($_POST[$key]) ? true : (isset($_GET[$key]) ? true : false);
  299. }
  300. /**
  301. * Change language in cookie while clicking on a flag
  302. *
  303. * @return string iso code
  304. */
  305. public static function setCookieLanguage($cookie = null)
  306. {
  307. if (!$cookie)
  308. $cookie = Context::getContext()->cookie;
  309. /* If language does not exist or is disabled, erase it */
  310. if ($cookie->id_lang)
  311. {
  312. //echo $cookie->id_lang;exit;
  313. $lang = new Language((int)$cookie->id_lang);
  314. if (!Validate::isLoadedObject($lang) || !$lang->active || !$lang->isAssociatedToShop())
  315. $cookie->id_lang = null;
  316. }
  317. /* Automatically detect language if not already defined */
  318. if (!$cookie->id_lang && isset($_SERVER['HTTP_ACCEPT_LANGUAGE']))
  319. {
  320. $array = explode(',', Tools::strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));
  321. if (Tools::strlen($array[0]) > 2)
  322. {
  323. $tab = explode('-', $array[0]);
  324. $string = $tab[0];
  325. }
  326. else
  327. $string = $array[0];
  328. if (Validate::isLanguageIsoCode($string))
  329. {
  330. $lang = new Language(Language::getIdByIso($string));
  331. if (Validate::isLoadedObject($lang) && $lang->active)
  332. $cookie->id_lang = (int)$lang->id;
  333. }
  334. }
  335. /* If language file not present, you must use default language file */
  336. if (!$cookie->id_lang || !Validate::isUnsignedId($cookie->id_lang))
  337. $cookie->id_lang = (int)Configuration::get('PS_LANG_DEFAULT');
  338. $iso = Language::getIsoById((int)$cookie->id_lang);
  339. @include_once(_PS_THEME_DIR_.'lang/'.$iso.'.php');
  340. return $iso;
  341. }
  342. /**
  343. * Set cookie id_lang
  344. */
  345. public static function switchLanguage(Context $context = null)
  346. {
  347. if (!$context)
  348. $context = Context::getContext();
  349. // Install call the dispatcher and so the switchLanguage
  350. // Stop this method by checking the cookie
  351. if (!isset($context->cookie))
  352. return;
  353. if (($iso = Tools::getValue('isolang')) && Validate::isLanguageIsoCode($iso) && ($id_lang = (int)Language::getIdByIso($iso)))
  354. $_GET['id_lang'] = $id_lang;
  355. // update language only if new id is different from old id
  356. // or if default language changed
  357. $cookie_id_lang = $context->cookie->id_lang;
  358. $configuration_id_lang = Configuration::get('PS_LANG_DEFAULT');
  359. if ((($id_lang = (int)Tools::getValue('id_lang')) && Validate::isUnsignedId($id_lang) && $cookie_id_lang != (int)$id_lang)
  360. || (($id_lang == $configuration_id_lang) && Validate::isUnsignedId($id_lang) && $id_lang != $cookie_id_lang))
  361. {
  362. $context->cookie->id_lang = $id_lang;
  363. $language = new Language($id_lang);
  364. if (Validate::isLoadedObject($language))
  365. $context->language = $language;
  366. $params = $_GET;
  367. if (Configuration::get('PS_REWRITING_SETTINGS') || !Language::isMultiLanguageActivated())
  368. unset($params['id_lang']);
  369. }
  370. }
  371. /**
  372. * Set cookie currency from POST or default currency
  373. *
  374. * @return Currency object
  375. */
  376. public static function setCurrency($cookie)
  377. {
  378. if (Tools::isSubmit('SubmitCurrency'))
  379. if (isset($_POST['id_currency']) && is_numeric($_POST['id_currency']))
  380. {
  381. $currency = Currency::getCurrencyInstance($_POST['id_currency']);
  382. if (is_object($currency) && $currency->id && !$currency->deleted && $currency->isAssociatedToShop())
  383. $cookie->id_currency = (int)$currency->id;
  384. }
  385. if ((int)$cookie->id_currency)
  386. {
  387. $currency = Currency::getCurrencyInstance((int)$cookie->id_currency);
  388. if (is_object($currency) && (int)$currency->id && (int)$currency->deleted != 1 && $currency->active)
  389. if ($currency->isAssociatedToShop())
  390. return $currency;
  391. else
  392. {
  393. // get currency from context
  394. $currency = Shop::getEntityIds('currency', Context::getContext()->shop->id);
  395. $cookie->id_currency = $currency[0]['id_currency'];
  396. return Currency::getCurrencyInstance((int)$cookie->id_currency);
  397. }
  398. }
  399. $currency = Currency::getCurrencyInstance(Configuration::get('PS_CURRENCY_DEFAULT'));
  400. if (is_object($currency) && $currency->id)
  401. $cookie->id_currency = (int)$currency->id;
  402. return $currency;
  403. }
  404. /**
  405. * Return price with currency sign for a given product
  406. *
  407. * @param float $price Product price
  408. * @param object $currency Current currency (object, id_currency, NULL => context currency)
  409. * @return string Price correctly formated (sign, decimal separator...)
  410. */
  411. public static function displayPrice($price, $currency = null, $no_utf8 = false, Context $context = null)
  412. {
  413. if (!is_numeric($price))
  414. return $price;
  415. if (!$context)
  416. $context = Context::getContext();
  417. if ($currency === null)
  418. $currency = $context->currency;
  419. // if you modified this function, don't forget to modify the Javascript function formatCurrency (in tools.js)
  420. elseif (is_int($currency))
  421. $currency = Currency::getCurrencyInstance((int)$currency);
  422. if (is_array($currency))
  423. {
  424. $c_char = $currency['sign'];
  425. $c_format = $currency['format'];
  426. $c_decimals = (int)$currency['decimals'] * _PS_PRICE_DISPLAY_PRECISION_;
  427. $c_blank = $currency['blank'];
  428. }
  429. elseif (is_object($currency))
  430. {
  431. $c_char = $currency->sign;
  432. $c_format = $currency->format;
  433. $c_decimals = (int)$currency->decimals * _PS_PRICE_DISPLAY_PRECISION_;
  434. $c_blank = $currency->blank;
  435. }
  436. else
  437. return false;
  438. $blank = ($c_blank ? ' ' : '');
  439. $ret = 0;
  440. if (($is_negative = ($price < 0)))
  441. $price *= -1;
  442. $price = Tools::ps_round($price, $c_decimals);
  443. switch ($c_format)
  444. {
  445. /* X 0,000.00 */
  446. case 1:
  447. $ret = $c_char.$blank.number_format($price, $c_decimals, '.', ',');
  448. break;
  449. /* 0 000,00 X*/
  450. case 2:
  451. $ret = number_format($price, $c_decimals, ',', ' ').$blank.$c_char;
  452. break;
  453. /* X 0.000,00 */
  454. case 3:
  455. $ret = $c_char.$blank.number_format($price, $c_decimals, ',', '.');
  456. break;
  457. /* 0,000.00 X */
  458. case 4:
  459. $ret = number_format($price, $c_decimals, '.', ',').$blank.$c_char;
  460. break;
  461. /* 0 000.00 X Added for the switzerland currency */
  462. case 5:
  463. $ret = number_format($price, $c_decimals, '.', ' ').$blank.$c_char;
  464. break;
  465. }
  466. if ($is_negative)
  467. $ret = '-'.$ret;
  468. if ($no_utf8)
  469. return str_replace('€', chr(128), $ret);
  470. return $ret;
  471. }
  472. public static function displayPriceSmarty($params, &$smarty)
  473. {
  474. if (array_key_exists('currency', $params))
  475. {
  476. $currency = Currency::getCurrencyInstance((int)($params['currency']));
  477. if (Validate::isLoadedObject($currency))
  478. return Tools::displayPrice($params['price'], $currency, false);
  479. }
  480. return Tools::displayPrice($params['price']);
  481. }
  482. /**
  483. * Return price converted
  484. *
  485. * @param float $price Product price
  486. * @param object $currency Current currency object
  487. * @param boolean $to_currency convert to currency or from currency to default currency
  488. */
  489. public static function convertPrice($price, $currency = null, $to_currency = true, Context $context = null)
  490. {
  491. static $default_currency = null;
  492. if ($default_currency === null)
  493. $default_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT');
  494. if (!$context)
  495. $context = Context::getContext();
  496. if ($currency === null)
  497. $currency = $context->currency;
  498. elseif (is_numeric($currency))
  499. $currency = Currency::getCurrencyInstance($currency);
  500. $c_id = (is_array($currency) ? $currency['id_currency'] : $currency->id);
  501. $c_rate = (is_array($currency) ? $currency['conversion_rate'] : $currency->conversion_rate);
  502. if ($c_id != $default_currency)
  503. {
  504. if ($to_currency)
  505. $price *= $c_rate;
  506. else
  507. $price /= $c_rate;
  508. }
  509. return $price;
  510. }
  511. /**
  512. *
  513. * Convert amount from a currency to an other currency automatically
  514. * @param float $amount
  515. * @param Currency $currency_from if null we used the default currency
  516. * @param Currency $currency_to if null we used the default currency
  517. */
  518. public static function convertPriceFull($amount, Currency $currency_from = null, Currency $currency_to = null)
  519. {
  520. if ($currency_from === $currency_to)
  521. return $amount;
  522. if ($currency_from === null)
  523. $currency_from = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
  524. if ($currency_to === null)
  525. $currency_to = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
  526. if ($currency_from->id == Configuration::get('PS_CURRENCY_DEFAULT'))
  527. $amount *= $currency_to->conversion_rate;
  528. else
  529. {
  530. $conversion_rate = ($currency_from->conversion_rate == 0 ? 1 : $currency_from->conversion_rate);
  531. // Convert amount to default currency (using the old currency rate)
  532. $amount = Tools::ps_round($amount / $conversion_rate, 2);
  533. // Convert to new currency
  534. $amount *= $currency_to->conversion_rate;
  535. }
  536. return Tools::ps_round($amount, 2);
  537. }
  538. /**
  539. * Display date regarding to language preferences
  540. *
  541. * @param array $params Date, format...
  542. * @param object $smarty Smarty object for language preferences
  543. * @return string Date
  544. */
  545. public static function dateFormat($params, &$smarty)
  546. {
  547. return Tools::displayDate($params['date'], Context::getContext()->language->id, (isset($params['full']) ? $params['full'] : false));
  548. }
  549. /**
  550. * Display date regarding to language preferences
  551. *
  552. * @param string $date Date to display format UNIX
  553. * @param integer $id_lang Language id
  554. * @param boolean $full With time or not (optional)
  555. * @param string $separator DEPRECATED
  556. * @return string Date
  557. */
  558. public static function displayDate($date, $id_lang, $full = false, $separator = '-')
  559. {
  560. if (!$date || !($time = strtotime($date)))
  561. return $date;
  562. if ($date == '0000-00-00 00:00:00' || $date == '0000-00-00')
  563. return '';
  564. if (!Validate::isDate($date) || !Validate::isBool($full))
  565. throw new PrestaShopException('Invalid date');
  566. $context = Context::getContext();
  567. $date_format = ($full ? $context->language->date_format_full : $context->language->date_format_lite);
  568. return date($date_format, $time);
  569. }
  570. /**
  571. * Sanitize a string
  572. *
  573. * @param string $string String to sanitize
  574. * @param boolean $full String contains HTML or not (optional)
  575. * @return string Sanitized string
  576. */
  577. public static function safeOutput($string, $html = false)
  578. {
  579. if (!$html)
  580. $string = strip_tags($string);
  581. return @Tools::htmlentitiesUTF8($string, ENT_QUOTES);
  582. }
  583. public static function htmlentitiesUTF8($string, $type = ENT_QUOTES)
  584. {
  585. if (is_array($string))
  586. return array_map(array('Tools', 'htmlentitiesUTF8'), $string);
  587. return htmlentities($string, $type, 'utf-8');
  588. }
  589. public static function htmlentitiesDecodeUTF8($string)
  590. {
  591. if (is_array($string))
  592. return array_map(array('Tools', 'htmlentitiesDecodeUTF8'), $string);
  593. return html_entity_decode($string, ENT_QUOTES, 'utf-8');
  594. }
  595. public static function safePostVars()
  596. {
  597. if (!is_array($_POST))
  598. return array();
  599. $_POST = array_map(array('Tools', 'htmlentitiesUTF8'), $_POST);
  600. }
  601. /**
  602. * Delete directory and subdirectories
  603. *
  604. * @param string $dirname Directory name
  605. */
  606. public static function deleteDirectory($dirname, $delete_self = true)
  607. {
  608. $dirname = rtrim($dirname, '/').'/';
  609. $files = scandir($dirname);
  610. if (is_dir($dirname))
  611. {
  612. foreach ($files as $file)
  613. if ($file != '.' && $file != '..' && $file != '.svn')
  614. {
  615. if (is_dir($dirname.$file))
  616. Tools::deleteDirectory($dirname.$file, true);
  617. elseif (file_exists($dirname.$file))
  618. unlink($dirname.$file);
  619. }
  620. if ($delete_self)
  621. rmdir($dirname);
  622. }
  623. }
  624. /**
  625. * Display an error according to an error code
  626. *
  627. * @param string $string Error message
  628. * @param boolean $htmlentities By default at true for parsing error message with htmlentities
  629. */
  630. public static function displayError($string = 'Fatal error', $htmlentities = true, Context $context = null)
  631. {
  632. global $_ERRORS;
  633. if (is_null($context))
  634. $context = Context::getContext();
  635. @include_once(_PS_TRANSLATIONS_DIR_.$context->language->iso_code.'/errors.php');
  636. if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_ && $string == 'Fatal error')
  637. return ('<pre>'.print_r(debug_backtrace(), true).'</pre>');
  638. if (!is_array($_ERRORS))
  639. return str_replace('"', '&quot;', $string);
  640. $key = md5(str_replace('\'', '\\\'', $string));
  641. $str = (isset($_ERRORS) && is_array($_ERRORS) && array_key_exists($key, $_ERRORS)) ? ($htmlentities ? htmlentities($_ERRORS[$key], ENT_COMPAT, 'UTF-8') : $_ERRORS[$key]) : $string;
  642. return str_replace('"', '&quot;', stripslashes($str));
  643. }
  644. /**
  645. * Display an error with detailed object
  646. *
  647. * @param mixed $object
  648. * @param boolean $kill
  649. * @return $object if $kill = false;
  650. */
  651. public static function dieObject($object, $kill = true)
  652. {
  653. echo '<xmp style="text-align: left;">';
  654. print_r($object);
  655. echo '</xmp><br />';
  656. if ($kill)
  657. die('END');
  658. return $object;
  659. }
  660. /**
  661. * Display a var dump in firebug console
  662. *
  663. * @param object $object Object to display
  664. */
  665. public static function fd($object)
  666. {
  667. echo '
  668. <script type="text/javascript">
  669. console.log('.json_encode($object).');
  670. </script>
  671. ';
  672. }
  673. /**
  674. * ALIAS OF dieObject() - Display an error with detailed object
  675. *
  676. * @param object $object Object to display
  677. */
  678. public static function d($object, $kill = true)
  679. {
  680. return (Tools::dieObject($object, $kill));
  681. }
  682. /**
  683. * ALIAS OF dieObject() - Display an error with detailed object but don't stop the execution
  684. *
  685. * @param object $object Object to display
  686. */
  687. public static function p($object)
  688. {
  689. return (Tools::dieObject($object, false));
  690. }
  691. /**
  692. * Check if submit has been posted
  693. *
  694. * @param string $submit submit name
  695. */
  696. public static function isSubmit($submit)
  697. {
  698. return (
  699. isset($_POST[$submit]) || isset($_POST[$submit.'_x']) || isset($_POST[$submit.'_y'])
  700. || isset($_GET[$submit]) || isset($_GET[$submit.'_x']) || isset($_GET[$submit.'_y'])
  701. );
  702. }
  703. /**
  704. * @deprecated 1.5.0
  705. */
  706. public static function getMetaTags($id_lang, $page_name, $title = '')
  707. {
  708. Tools::displayAsDeprecated();
  709. return Meta::getMetaTags($id_lang, $page_name, $title);
  710. }
  711. /**
  712. * @deprecated 1.5.0
  713. */
  714. public static function getHomeMetaTags($id_lang, $page_name)
  715. {
  716. Tools::displayAsDeprecated();
  717. return Meta::getHomeMetas($id_lang, $page_name);
  718. }
  719. /**
  720. * @deprecated 1.5.0
  721. */
  722. public static function completeMetaTags($meta_tags, $default_value, Context $context = null)
  723. {
  724. Tools::displayAsDeprecated();
  725. return Meta::completeMetaTags($meta_tags, $default_value, $context);
  726. }
  727. /**
  728. * Encrypt password
  729. *
  730. * @param string $passwd String to encrypt
  731. */
  732. public static function encrypt($passwd)
  733. {
  734. return md5(_COOKIE_KEY_.$passwd);
  735. }
  736. /**
  737. * Get token to prevent CSRF
  738. *
  739. * @param string $token token to encrypt
  740. */
  741. public static function getToken($page = true, Context $context = null)
  742. {
  743. if (!$context)
  744. $context = Context::getContext();
  745. if ($page === true)
  746. return (Tools::encrypt($context->customer->id.$context->customer->passwd.$_SERVER['SCRIPT_NAME']));
  747. else
  748. return (Tools::encrypt($context->customer->id.$context->customer->passwd.$page));
  749. }
  750. /**
  751. * Tokenize a string
  752. *
  753. * @param string $string string to encript
  754. */
  755. public static function getAdminToken($string)
  756. {
  757. return !empty($string) ? Tools::encrypt($string) : false;
  758. }
  759. public static function getAdminTokenLite($tab, Context $context = null)
  760. {
  761. if (!$context)
  762. $context = Context::getContext();
  763. return Tools::getAdminToken($tab.(int)Tab::getIdFromClassName($tab).(int)$context->employee->id);
  764. }
  765. public static function getAdminTokenLiteSmarty($params, &$smarty)
  766. {
  767. $context = Context::getContext();
  768. return Tools::getAdminToken($params['tab'].(int)Tab::getIdFromClassName($params['tab']).(int)$context->employee->id);
  769. }
  770. /**
  771. * Get the user's journey
  772. *
  773. * @param integer $id_category Category ID
  774. * @param string $path Path end
  775. * @param boolean $linkOntheLastItem Put or not a link on the current category
  776. * @param string [optionnal] $categoryType defined what type of categories is used (products or cms)
  777. */
  778. public static function getPath($id_category, $path = '', $link_on_the_item = false, $category_type = 'products', Context $context = null)
  779. {
  780. if (!$context)
  781. $context = Context::getContext();
  782. $id_category = (int)$id_category;
  783. if ($id_category == 1)
  784. return '<span class="navigation_end">'.$path.'</span>';
  785. $pipe = Configuration::get('PS_NAVIGATION_PIPE');
  786. if (empty($pipe))
  787. $pipe = '>';
  788. $full_path = '';
  789. if ($category_type === 'products')
  790. {
  791. $interval = Category::getInterval($id_category);
  792. $id_root_category = $context->shop->getCategory();
  793. $interval_root = Category::getInterval($id_root_category);
  794. if ($interval)
  795. {
  796. $sql = 'SELECT c.id_category, cl.name, cl.link_rewrite
  797. FROM '._DB_PREFIX_.'category c
  798. LEFT JOIN '._DB_PREFIX_.'category_lang cl ON (cl.id_category = c.id_category'.Shop::addSqlRestrictionOnLang('cl').')
  799. WHERE c.nleft <= '.$interval['nleft'].'
  800. AND c.nright >= '.$interval['nright'].'
  801. AND c.nleft >= '.$interval_root['nleft'].'
  802. AND c.nright <= '.$interval_root['nright'].'
  803. AND cl.id_lang = '.(int)$context->language->id.'
  804. AND c.active = 1
  805. AND c.level_depth > '.(int)$interval_root['level_depth'].'
  806. ORDER BY c.level_depth ASC';
  807. $categories = Db::getInstance()->executeS($sql);
  808. $n = 1;
  809. $n_categories = count($categories);
  810. foreach ($categories as $category)
  811. {
  812. $full_path .=
  813. (($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').'">' : '').
  814. htmlentities($category['name'], ENT_NOQUOTES, 'UTF-8').
  815. (($n < $n_categories || $link_on_the_item) ? '</a>' : '').
  816. (($n++ != $n_categories || !empty($path)) ? '<span class="navigation-pipe">'.$pipe.'</span>' : '');
  817. }
  818. return $full_path.$path;
  819. }
  820. }
  821. else if ($category_type === 'CMS')
  822. {
  823. $category = new CMSCategory($id_category, $context->language->id);
  824. if (!Validate::isLoadedObject($category))
  825. die(Tools::displayError());
  826. $category_link = $context->link->getCMSCategoryLink($category);
  827. if ($path != $category->name)
  828. $full_path .= '<a href="'.Tools::safeOutput($category_link).'">'.htmlentities($category->name, ENT_NOQUOTES, 'UTF-8').'</a><span class="navigation-pipe">'.$pipe.'</span>'.$path;
  829. else
  830. $full_path = ($link_on_the_item ? '<a href="'.Tools::safeOutput($category_link).'">' : '').htmlentities($path, ENT_NOQUOTES, 'UTF-8').($link_on_the_item ? '</a>' : '');
  831. return Tools::getPath($category->id_parent, $full_path, $link_on_the_item, $category_type);
  832. }
  833. }
  834. /**
  835. * @param string [optionnal] $type_cat defined what type of categories is used (products or cms)
  836. */
  837. public static function getFullPath($id_category, $end, $type_cat = 'products', Context $context = null)
  838. {
  839. if (!$context)
  840. $context = Context::getContext();
  841. $id_category = (int)$id_category;
  842. $pipe = (Configuration::get('PS_NAVIGATION_PIPE') ? Configuration::get('PS_NAVIGATION_PIPE') : '>');
  843. $default_category = 1;
  844. if ($type_cat === 'products')
  845. {
  846. $default_category = $context->shop->getCategory();
  847. $category = new Category($id_category, $context->language->id);
  848. }
  849. else if ($type_cat === 'CMS')
  850. $category = new CMSCategory($id_category, $context->language->id);
  851. if (!Validate::isLoadedObject($category))
  852. $id_category = $default_category;
  853. if ($id_category == $default_category)
  854. return htmlentities($end, ENT_NOQUOTES, 'UTF-8');
  855. 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>';
  856. }
  857. /**
  858. * Return the friendly url from the provided string
  859. *
  860. * @param string $str
  861. * @param bool $utf8_decode => needs to be marked as deprecated
  862. * @return string
  863. */
  864. public static function link_rewrite($str, $utf8_decode = false)
  865. {
  866. return Tools::str2url($str);
  867. }
  868. /**
  869. * Return a friendly url made from the provided string
  870. * If the mbstring library is available, the output is the same as the js function of the same name
  871. *
  872. * @param string $str
  873. * @return string
  874. */
  875. public static function str2url($str)
  876. {
  877. if (function_exists('mb_strtolower'))
  878. $str = mb_strtolower($str, 'utf-8');
  879. $str = trim($str);
  880. if (!function_exists('mb_strtolower'))
  881. $str = Tools::replaceAccentedChars($str);
  882. // Remove all non-whitelist chars.
  883. $str = preg_replace('/[^a-zA-Z0-9\s\'\:\/\[\]-\pL]/u', '', $str);
  884. $str = preg_replace('/[\s\'\:\/\[\]-]+/', ' ', $str);
  885. $str = str_replace(array(' ', '/'), '-', $str);
  886. // If it was not possible to lowercase the string with mb_strtolower, we do it after the transformations.
  887. // This way we lose fewer special chars.
  888. if (!function_exists('mb_strtolower'))
  889. $str = strtolower($str);
  890. return $str;
  891. }
  892. /**
  893. * Replace all accented chars by their equivalent non accented chars.
  894. *
  895. * @param string $str
  896. * @return string
  897. */
  898. public static function replaceAccentedChars($str)
  899. {
  900. $patterns = array(
  901. /* Lowercase */
  902. '/[\x{0105}\x{00E0}\x{00E1}\x{00E2}\x{00E3}\x{00E4}\x{00E5}]/u',
  903. '/[\x{00E7}\x{010D}\x{0107}]/u',
  904. '/[\x{010F}]/u',
  905. '/[\x{00E8}\x{00E9}\x{00EA}\x{00EB}\x{011B}\x{0119}]/u',
  906. '/[\x{00EC}\x{00ED}\x{00EE}\x{00EF}]/u',
  907. '/[\x{0142}\x{013E}\x{013A}]/u',
  908. '/[\x{00F1}\x{0148}]/u',
  909. '/[\x{00F2}\x{00F3}\x{00F4}\x{00F5}\x{00F6}\x{00F8}]/u',
  910. '/[\x{0159}\x{0155}]/u',
  911. '/[\x{015B}\x{0161}]/u',
  912. '/[\x{00DF}]/u',
  913. '/[\x{0165}]/u',
  914. '/[\x{00F9}\x{00FA}\x{00FB}\x{00FC}\x{016F}]/u',
  915. '/[\x{00FD}\x{00FF}]/u',
  916. '/[\x{017C}\x{017A}\x{017E}]/u',
  917. '/[\x{00E6}]/u',
  918. '/[\x{0153}]/u',
  919. /* Uppercase */
  920. '/[\x{0104}\x{00C0}\x{00C1}\x{00C2}\x{00C3}\x{00C4}\x{00C5}]/u',
  921. '/[\x{00C7}\x{010C}\x{0106}]/u',
  922. '/[\x{010E}]/u',
  923. '/[\x{00C8}\x{00C9}\x{00CA}\x{00CB}\x{011A}\x{0118}]/u',
  924. '/[\x{0141}\x{013D}\x{0139}]/u',
  925. '/[\x{00D1}\x{0147}]/u',
  926. '/[\x{00D3}]/u',
  927. '/[\x{0158}\x{0154}]/u',
  928. '/[\x{015A}\x{0160}]/u',
  929. '/[\x{0164}]/u',
  930. '/[\x{00D9}\x{00DA}\x{00DB}\x{00DC}\x{016E}]/u',
  931. '/[\x{017B}\x{0179}\x{017D}]/u',
  932. '/[\x{00C6}]/u',
  933. '/[\x{0152}]/u');
  934. $replacements = array(
  935. 'a', 'c', 'd', 'e', 'i', 'l', 'n', 'o', 'r', 's', 'ss', 't', 'u', 'y', 'z', 'ae', 'oe',
  936. 'A', 'C', 'D', 'E', 'L', 'N', 'O', 'R', 'S', 'T', 'U', 'Z', 'AE', 'OE'
  937. );
  938. return preg_replace($patterns, $replacements, $str);
  939. }
  940. /**
  941. * Truncate strings
  942. *
  943. * @param string $str
  944. * @param integer $max_length Max length
  945. * @param string $suffix Suffix optional
  946. * @return string $str truncated
  947. */
  948. /* CAUTION : Use it only on module hookEvents.
  949. ** For other purposes use the smarty function instead */
  950. public static function truncate($str, $max_length, $suffix = '...')
  951. {
  952. if (Tools::strlen($str) <= $max_length)
  953. return $str;
  954. $str = utf8_decode($str);
  955. return (utf8_encode(substr($str, 0, $max_length - Tools::strlen($suffix)).$suffix));
  956. }
  957. /**
  958. * Generate date form
  959. *
  960. * @param integer $year Year to select
  961. * @param integer $month Month to select
  962. * @param integer $day Day to select
  963. * @return array $tab html data with 3 cells :['days'], ['months'], ['years']
  964. *
  965. */
  966. public static function dateYears()
  967. {
  968. $tab = array();
  969. for ($i = date('Y'); $i >= 1900; $i--)
  970. $tab[] = $i;
  971. return $tab;
  972. }
  973. public static function dateDays()
  974. {
  975. $tab = array();
  976. for ($i = 1; $i != 32; $i++)
  977. $tab[] = $i;
  978. return $tab;
  979. }
  980. public static function dateMonths()
  981. {
  982. $tab = array();
  983. for ($i = 1; $i != 13; $i++)
  984. $tab[$i] = date('F', mktime(0, 0, 0, $i, date('m'), date('Y')));
  985. return $tab;
  986. }
  987. public static function hourGenerate($hours, $minutes, $seconds)
  988. {
  989. return implode(':', array($hours, $minutes, $seconds));
  990. }
  991. public static function dateFrom($date)
  992. {
  993. $tab = explode(' ', $date);
  994. if (!isset($tab[1]))
  995. $date .= ' '.Tools::hourGenerate(0, 0, 0);
  996. return $date;
  997. }
  998. public static function dateTo($date)
  999. {
  1000. $tab = explode(' ', $date);
  1001. if (!isset($tab[1]))
  1002. $date .= ' '.Tools::hourGenerate(23, 59, 59);
  1003. return $date;
  1004. }
  1005. public static function strtolower($str)
  1006. {
  1007. if (is_array($str))
  1008. return false;
  1009. if (function_exists('mb_strtolower'))
  1010. return mb_strtolower($str, 'utf-8');
  1011. return strtolower($str);
  1012. }
  1013. public static function strlen($str, $encoding = 'UTF-8')
  1014. {
  1015. if (is_array($str))
  1016. return false;
  1017. $str = html_entity_decode($str, ENT_COMPAT, 'UTF-8');
  1018. if (function_exists('mb_strlen'))
  1019. return mb_strlen($str, $encoding);
  1020. return strlen($str);
  1021. }
  1022. public static function stripslashes($string)
  1023. {
  1024. if (_PS_MAGIC_QUOTES_GPC_)
  1025. $string = stripslashes($string);
  1026. return $string;
  1027. }
  1028. public static function strtoupper($str)
  1029. {
  1030. if (is_array($str))
  1031. return false;
  1032. if (function_exists('mb_strtoupper'))
  1033. return mb_strtoupper($str, 'utf-8');
  1034. return strtoupper($str);
  1035. }
  1036. public static function substr($str, $start, $length = false, $encoding = 'utf-8')
  1037. {
  1038. if (is_array($str))
  1039. return false;
  1040. if (function_exists('mb_substr'))
  1041. return mb_substr($str, (int)$start, ($length === false ? Tools::strlen($str) : (int)$length), $encoding);
  1042. return substr($str, $start, ($length === false ? Tools::strlen($str) : (int)$length));
  1043. }
  1044. public static function ucfirst($str)
  1045. {
  1046. return Tools::strtoupper(Tools::substr($str, 0, 1)).Tools::substr($str, 1);
  1047. }
  1048. public static function orderbyPrice(&$array, $order_way)
  1049. {
  1050. foreach ($array as &$row)
  1051. $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);
  1052. if (strtolower($order_way) == 'desc')
  1053. uasort($array, 'cmpPriceDesc');
  1054. else
  1055. uasort($array, 'cmpPriceAsc');
  1056. foreach ($array as &$row)
  1057. unset($row['price_tmp']);
  1058. }
  1059. public static function iconv($from, $to, $string)
  1060. {
  1061. if (function_exists('iconv'))
  1062. return iconv($from, $to.'//TRANSLIT', str_replace('¥', '&yen;', str_replace('£', '&pound;', str_replace('€', '&euro;', $string))));
  1063. return html_entity_decode(htmlentities($string, ENT_NOQUOTES, $from), ENT_NOQUOTES, $to);
  1064. }
  1065. public static function isEmpty($field)
  1066. {
  1067. return ($field === '' || $field === null);
  1068. }
  1069. /**
  1070. * returns the rounded value of $value to specified precision, according to your configuration;
  1071. *
  1072. * @note : PHP 5.3.0 introduce a 3rd parameter mode in round function
  1073. *
  1074. * @param float $value
  1075. * @param int $precision
  1076. * @return float
  1077. */
  1078. public static function ps_round($value, $precision = 0)
  1079. {
  1080. static $method = null;
  1081. if ($method == null)
  1082. $method = (int)Configuration::get('PS_PRICE_ROUND_MODE');
  1083. if ($method == PS_ROUND_UP)
  1084. return Tools::ceilf($value, $precision);
  1085. elseif ($method == PS_ROUND_DOWN)
  1086. return Tools::floorf($value, $precision);
  1087. return round($value, $precision);
  1088. }
  1089. /**
  1090. * returns the rounded value down of $value to specified precision
  1091. *
  1092. * @param float $value
  1093. * @param int $precision
  1094. * @return float
  1095. */
  1096. public static function ceilf($value, $precision = 0)
  1097. {
  1098. $precision_factor = $precision == 0 ? 1 : pow(10, $precision);
  1099. $tmp = $value * $precision_factor;
  1100. $tmp2 = (string)$tmp;
  1101. // If the current value has already the desired precision
  1102. if (strpos($tmp2, '.') === false)
  1103. return ($value);
  1104. if ($tmp2[strlen($tmp2) - 1] == 0)
  1105. return $value;
  1106. return ceil($tmp) / $precision_factor;
  1107. }
  1108. /**
  1109. * returns the rounded value up of $value to specified precision
  1110. *
  1111. * @param float $value
  1112. * @param int $precision
  1113. * @return float
  1114. */
  1115. public static function floorf($value, $precision = 0)
  1116. {
  1117. $precision_factor = $precision == 0 ? 1 : pow(10, $precision);
  1118. $tmp = $value * $precision_factor;
  1119. $tmp2 = (string)$tmp;
  1120. // If the current value has already the desired precision
  1121. if (strpos($tmp2, '.') === false)
  1122. return ($value);
  1123. if ($tmp2[strlen($tmp2) - 1] == 0)
  1124. return $value;
  1125. return floor($tmp) / $precision_factor;
  1126. }
  1127. /**
  1128. * file_exists() wrapper with cache to speedup performance
  1129. *
  1130. * @param string $filename File name
  1131. * @return boolean Cached result of file_exists($filename)
  1132. */
  1133. public static function file_exists_cache($filename)
  1134. {
  1135. if (!isset(self::$file_exists_cache[$filename]))
  1136. self::$file_exists_cache[$filename] = file_exists($filename);
  1137. return self::$file_exists_cache[$filename];
  1138. }
  1139. public static function file_get_contents($url, $use_include_path = false, $stream_context = null, $curl_timeout = 5)
  1140. {
  1141. if ($stream_context == null)
  1142. $stream_context = @stream_context_create(array('http' => array('timeout' => 5)));
  1143. if (in_array(ini_get('allow_url_fopen'), array('On', 'on', '1')))
  1144. return @file_get_contents($url, $use_include_path, $stream_context);
  1145. elseif (function_exists('curl_init'))
  1146. {
  1147. $curl = curl_init();
  1148. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  1149. curl_setopt($curl, CURLOPT_URL, $url);
  1150. curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $curl_timeout);
  1151. curl_setopt($curl, CURLOPT_TIMEOUT, $curl_timeout);
  1152. $content = curl_exec($curl);
  1153. curl_close($curl);
  1154. return $content;
  1155. }
  1156. else
  1157. return false;
  1158. }
  1159. public static function simplexml_load_file($url, $class_name = null)
  1160. {
  1161. if (in_array(ini_get('allow_url_fopen'), array('On', 'on', '1')))
  1162. return @simplexml_load_string(Tools::file_get_contents($url), $class_name);
  1163. else
  1164. return false;
  1165. }
  1166. public static $a = 0;
  1167. /**
  1168. * @deprecated as of 1.5 use Media::minifyHTML()
  1169. */
  1170. public static function minifyHTML($html_content)
  1171. {
  1172. Tools::displayAsDeprecated();
  1173. return Media::minifyHTML($html_content);
  1174. }
  1175. /**
  1176. * Translates a string with underscores into camel case (e.g. first_name -> firstName)
  1177. * @prototype string public static function toCamelCase(string $str[, bool $catapitalise_first_char = false])
  1178. */
  1179. public static function toCamelCase($str, $catapitalise_first_char = false)
  1180. {
  1181. $str = strtolower($str);
  1182. if ($catapitalise_first_char)
  1183. $str = ucfirst($str);
  1184. return preg_replace_callback('/_+([a-z])/', create_function('$c', 'return strtoupper($c[1]);'), $str);
  1185. }
  1186. /**
  1187. * Transform a CamelCase string to underscore_case string
  1188. *
  1189. * @param string $string
  1190. * @return string
  1191. */
  1192. public static function toUnderscoreCase($string)
  1193. {
  1194. // 'CMSCategories' => 'cms_categories'
  1195. // 'RangePrice' => 'range_price'
  1196. return strtolower(trim(preg_replace('/([A-Z][a-z])/', '_$1', $string), '_'));
  1197. }
  1198. public static function getBrightness($hex)
  1199. {
  1200. $hex = str_replace('#', '', $hex);
  1201. $r = hexdec(substr($hex, 0, 2));
  1202. $g = hexdec(substr($hex, 2, 2));
  1203. $b = hexdec(substr($hex, 4, 2));
  1204. return (($r * 299) + ($g * 587) + ($b * 114)) / 1000;
  1205. }
  1206. /**
  1207. * @deprecated as of 1.5 use Media::minifyHTMLpregCallback()
  1208. */
  1209. public static function minifyHTMLpregCallback($preg_matches)
  1210. {
  1211. Tools::displayAsDeprecated();
  1212. return Media::minifyHTMLpregCallback($preg_matches);
  1213. }
  1214. /**
  1215. * @deprecated as of 1.5 use Media::packJSinHTML()
  1216. */
  1217. public static function packJSinHTML($html_content)
  1218. {
  1219. Tools::displayAsDeprecated();
  1220. return Media::packJSinHTML($html_content);
  1221. }
  1222. /**
  1223. * @deprecated as of 1.5 use Media::packJSinHTMLpregCallback()
  1224. */
  1225. public static function packJSinHTMLpregCallback($preg_matches)
  1226. {
  1227. Tools::displayAsDeprecated();
  1228. return Media::packJSinHTMLpregCallback($preg_matches);
  1229. }
  1230. /**
  1231. * @deprecated as of 1.5 use Media::packJS()
  1232. */
  1233. public static function packJS($js_content)
  1234. {
  1235. Tools::displayAsDeprecated();
  1236. return Media::packJS($js_content);
  1237. }
  1238. public static function parserSQL($sql)
  1239. {
  1240. if (strlen($sql) > 0)
  1241. {
  1242. require_once(_PS_TOOL_DIR_.'parser_sql/php-sql-parser.php');
  1243. $parser = new parserSql($sql);
  1244. return $parser->parsed;
  1245. }
  1246. return false;
  1247. }
  1248. /**
  1249. * @deprecated as of 1.5 use Media::minifyCSS()
  1250. */
  1251. public static function minifyCSS($css_content, $fileuri = false)
  1252. {
  1253. Tools::displayAsDeprecated();
  1254. return Media::minifyCSS($css_content, $fileuri);
  1255. }
  1256. public static function replaceByAbsoluteURL($matches)
  1257. {
  1258. global $current_css_file;
  1259. $protocol_link = Tools::getCurrentUrlProtocolPrefix();
  1260. if (array_key_exists(1, $matches))
  1261. {
  1262. $tmp = dirname($current_css_file).'/'.$matches[1];
  1263. return 'url(\''.$protocol_link.Tools::getMediaServer($tmp).$tmp.'\')';
  1264. }
  1265. return false;
  1266. }
  1267. /**
  1268. * addJS load a javascript file in the header
  1269. *
  1270. * @deprecated as of 1.5 use FrontController->addJS()
  1271. * @param mixed $js_uri
  1272. * @return void
  1273. */
  1274. public static function addJS($js_uri)
  1275. {
  1276. Tools::displayAsDeprecated();
  1277. $context = Context::getContext();
  1278. $context->controller->addJs($js_uri);
  1279. }
  1280. /**
  1281. * @deprecated as of 1.5 use FrontController->addCSS()
  1282. */
  1283. public static function addCSS($css_uri, $css_media_type = 'all')
  1284. {
  1285. Tools::displayAsDeprecated();
  1286. $context = Context::getContext();
  1287. $context->controller->addCSS($css_uri, $css_media_type);
  1288. }
  1289. /**
  1290. * @deprecated as of 1.5 use Media::cccCss()
  1291. */
  1292. public static function cccCss($css_files)
  1293. {
  1294. Tools::displayAsDeprecated();
  1295. return Media::cccCss($css_files);
  1296. }
  1297. /**
  1298. * @deprecated as of 1.5 use Media::cccJS()
  1299. */
  1300. public static function cccJS($js_files)
  1301. {
  1302. Tools::displayAsDeprecated();
  1303. return Media::cccJS($js_files);
  1304. }
  1305. protected static $_cache_nb_media_servers = null;
  1306. public static function getMediaServer($filename)
  1307. {
  1308. if (self::$_cache_nb_media_servers === null)
  1309. {
  1310. if (_MEDIA_SERVER_1_ == '')
  1311. self::$_cache_nb_media_servers = 0;
  1312. elseif (_MEDIA_SERVER_2_ == '')
  1313. self::$_cache_nb_media_servers = 1;
  1314. elseif (_MEDIA_SERVER_3_ == '')
  1315. self::$_cache_nb_media_servers = 2;
  1316. else
  1317. self::$_cache_nb_media_servers = 3;
  1318. }
  1319. if (self::$_cache_nb_media_servers && ($id_media_server = (abs(crc32($filename)) % self::$_cache_nb_media_servers + 1)))
  1320. return constant('_MEDIA_SERVER_'.$id_media_server.'_');
  1321. return Tools::getHttpHost();
  1322. }
  1323. public static function generateHtaccess($path = null, $rewrite_settings = null, $cache_control = null, $specific = '', $disable_multiviews = null, $medias = false)
  1324. {
  1325. if (defined('PS_INSTALLATION_IN_PROGRESS'))
  1326. return true;
  1327. // Default values for parameters
  1328. if (is_null($path))
  1329. $path = _PS_ROOT_DIR_.'/.htaccess';
  1330. if (is_null($cache_control))
  1331. $cache_control = (int)Configuration::get('PS_HTACCESS_CACHE_CONTROL');
  1332. if (is_null($disable_multiviews))
  1333. $disable_multiviews = (int)Configuration::get('PS_HTACCESS_DISABLE_MULTIVIEWS');
  1334. // Check current content of .htaccess and save all code outside of prestashop comments
  1335. $specific_before = $specific_after = '';
  1336. if (file_exists($path))
  1337. {
  1338. $content = file_get_contents($path);
  1339. if (preg_match('#^(.*)\# ~~start~~.*\# ~~end~~[^\n]*(.*)$#s', $content, $m))
  1340. {
  1341. $specific_before = $m[1];
  1342. $specific_after = $m[2];
  1343. }
  1344. else
  1345. {
  1346. // For retrocompatibility
  1347. if (preg_match('#\# http://www\.prestashop\.com - http://www\.prestashop\.com/forums\s*(.*)<IfModule mod_rewrite\.c>#si', $content, $m))
  1348. $specific_before = $m[1];
  1349. else
  1350. $specific_before = $content;
  1351. }
  1352. }
  1353. // Write .htaccess data
  1354. if (!$write_fd = @fopen($path, 'w'))
  1355. return false;
  1356. fwrite($write_fd, trim($specific_before)."\n\n");
  1357. $domains = array();
  1358. foreach (ShopUrl::getShopUrls() as $shop_url)
  1359. {
  1360. if (!isset($domains[$shop_url->domain]))
  1361. $domains[$shop_url->domain] = array();
  1362. $domains[$shop_url->domain][] = array(
  1363. 'physical' => $shop_url->physical_uri,
  1364. 'virtual' => $shop_url->virtual_uri,
  1365. 'id_shop' => $shop_url->id_shop
  1366. );
  1367. }
  1368. // Write data in .htaccess file
  1369. 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");
  1370. fwrite($write_fd, "# .htaccess automaticaly generated by PrestaShop e-commerce open-source solution\n");
  1371. fwrite($write_fd, "# http://www.prestashop.com - http://www.prestashop.com/forums\n\n");
  1372. // RewriteEngine
  1373. fwrite($write_fd, "<IfModule mod_rewrite.c>\n");
  1374. // Disable multiviews ?
  1375. if ($disable_multiviews)
  1376. fwrite($write_fd, "\n# Disable Multiviews\nOptions -Multiviews\n\n");
  1377. fwrite($write_fd, "RewriteEngine on\n");
  1378. if (!$medias)
  1379. $medias = array(_MEDIA_SERVER_1_, _MEDIA_SERVER_2_, _MEDIA_SERVER_3_);
  1380. $media_domains = '';
  1381. if ($medias[0] != '')
  1382. $media_domains = 'RewriteCond %{HTTP_HOST} ^'.$medias[0].'$ [OR]'."\n";
  1383. if ($medias[1] != '')
  1384. $media_domains .= 'RewriteCond %{HTTP_HOST} ^'.$medias[1].'$ [OR]'."\n";
  1385. if ($medias[2] != '')
  1386. $media_domains .= 'RewriteCond %{HTTP_HOST} ^'.$medias[2].'$ [OR]'."\n";
  1387. if (Configuration::get('PS_WEBSERVICE_CGI_HOST'))
  1388. fwrite($write_fd, "RewriteCond %{HTTP:Authorization} ^(.*)\nRewriteRule . - [E=HTTP_AUTHORIZATION:%1]\n\n");
  1389. foreach ($domains as $domain => $list_uri)
  1390. {
  1391. $physicals = array();
  1392. foreach ($list_uri as $uri)
  1393. {
  1394. fwrite($write_fd, 'RewriteCond %{HTTP_HOST} ^'.$domain.'$'."\n");
  1395. fwrite($write_fd, 'RewriteRule . - [E=REWRITEBASE:'.$uri['physical'].']'."\n");
  1396. // Webservice
  1397. fwrite($write_fd, 'RewriteRule ^api/?(.*)$ %{ENV:REWRITEBASE}webservice/dispatcher.php?url=$1 [QSA,L]'."\n\n");
  1398. $rewrite_settings = (int)Configuration::get('PS_REWRITING_SETTINGS', null, null, (int)$uri['id_shop']);
  1399. $domain_rewrite_cond = 'RewriteCond %{HTTP_HOST} ^'.$domain.'$'."\n";
  1400. // Rewrite virtual multishop uri
  1401. if ($uri['virtual'])
  1402. {
  1403. if (!$rewrite_settings)
  1404. {
  1405. fwrite($write_fd, $media_domains);
  1406. fwrite($write_fd, $domain_rewrite_cond);
  1407. fwrite($write_fd, 'RewriteRule ^'.trim($uri['virtual'], '/').'/?$ '.$uri['physical'].$uri['virtual']."index.php [L,R]\n");
  1408. }
  1409. else
  1410. {
  1411. fwrite($write_fd, $media_domains);
  1412. fwrite($write_fd, $domain_rewrite_cond);
  1413. fwrite($write_fd, 'RewriteRule ^'.trim($uri['virtual'], '/').'$ '.$uri['physical'].$uri['virtual']." [L,R]\n");
  1414. }
  1415. fwrite($write_fd, $media_domains);
  1416. fwrite($write_fd, $domain_rewrite_cond);
  1417. fwrite($write_fd, 'RewriteRule ^'.ltrim($uri['virtual'], '/').'(.*) '.$uri['physical']."$1 [L]\n\n");
  1418. }
  1419. if ($rewrite_settings)
  1420. {
  1421. // Compatibility with the old image filesystem
  1422. fwrite($write_fd, "# Images\n");
  1423. if (Configuration::get('PS_LEGACY_IMAGES'))
  1424. {
  1425. fwrite($write_fd, $media_domains);
  1426. fwrite($write_fd, $domain_rewrite_cond);
  1427. fwrite($write_fd, 'RewriteRule ^([a-z0-9]+)\-([a-z0-9]+)(\-[_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}'._PS_PROD_IMG_.'$1-$2$3$4.jpg [L]'."\n");
  1428. fwrite($write_fd, $media_domains);
  1429. fwrite($write_fd, $domain_rewrite_cond);
  1430. fwrite($write_fd, 'RewriteRule ^([0-9]+)\-([0-9]+)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}'._PS_PROD_IMG_.'$1-$2$3.jpg [L]'."\n");
  1431. }
  1432. // Rewrite product images < 100 millions
  1433. for ($i = 1; $i <= 8; $i++)
  1434. {
  1435. $img_path = $img_name = '';
  1436. for ($j = 1; $j <= $i; $j++)
  1437. {
  1438. $img_path .= '$'.$j.'/';
  1439. $img_name .= '$'.$j;
  1440. }
  1441. $img_name .= '$'.$j;
  1442. fwrite($write_fd, $media_domains);
  1443. fwrite($write_fd, $domain_rewrite_cond);
  1444. fwrite($write_fd, 'RewriteRule ^'.str_repeat('([0-9])', $i).'(\-[_a-zA-Z0-9-]*)?(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}'._PS_PROD_IMG_.$img_path.$img_name.'$'.($j + 1).".jpg [L]\n");
  1445. }
  1446. fwrite($write_fd, $media_domains);
  1447. fwrite($write_fd, $domain_rewrite_cond);
  1448. fwrite($write_fd, 'RewriteRule ^c/([0-9]+)(\-[\.*_a-zA-Z0-9-]*)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1$2$3.jpg [L]'."\n");
  1449. fwrite($write_fd, $media_domains);
  1450. fwrite($write_fd, $domain_rewrite_cond);
  1451. fwrite($write_fd, 'RewriteRule ^c/([a-zA-Z-]+)(-[0-9]+)?/.+\.jpg$ %{ENV:REWRITEBASE}img/c/$1$2.jpg [L]'."\n");
  1452. }
  1453. }
  1454. // Redirections to dispatcher
  1455. if ($rewrite_settings)
  1456. {
  1457. fwrite($write_fd, "\n# Dispatcher\n");
  1458. fwrite($write_fd, "RewriteCond %{REQUEST_FILENAME} -s [OR]\n");
  1459. fwrite($write_fd, "RewriteCond %{REQUEST_FILENAME} -l [OR]\n");
  1460. fwrite($write_fd, "RewriteCond %{REQUEST_FILENAME} -d\n");
  1461. fwrite($write_fd, $domain_rewrite_cond);
  1462. fwrite($write_fd, "RewriteRule ^.*$ - [NC,L]\n");
  1463. fwrite($write_fd, $domain_rewrite_cond);
  1464. fwrite($write_fd, "RewriteRule ^.*\$ %{ENV:REWRITEBASE}index.php [NC,L]\n");
  1465. }
  1466. }
  1467. fwrite($write_fd, "</IfModule>\n\n");
  1468. // Cache control
  1469. if ($cache_control)
  1470. {
  1471. $cache_control = "<IfModule mod_expires.c>
  1472. ExpiresActive On
  1473. ExpiresByType image/gif \"access plus 1 month\"
  1474. ExpiresByType image/jpeg \"access plus 1 month\"
  1475. ExpiresByType image/png \"access plus 1 month\"
  1476. ExpiresByType text/…

Large files files are truncated, but you can click here to view the full file