first commit
This commit is contained in:
301
classes/Smarty/SmartyCustom.php
Normal file
301
classes/Smarty/SmartyCustom.php
Normal file
@@ -0,0 +1,301 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class SmartyCustomCore extends Smarty
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->template_class = 'SmartyCustomTemplate';
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete compiled template file (lazy delete if resource_name is not specified).
|
||||
*
|
||||
* @param string $resource_name template name
|
||||
* @param string $compile_id compile id
|
||||
* @param int $exp_time expiration time
|
||||
*
|
||||
* @return int number of template files deleted
|
||||
*/
|
||||
public function clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
|
||||
{
|
||||
if ($resource_name == null) {
|
||||
Db::getInstance()->execute('REPLACE INTO `' . _DB_PREFIX_ . 'smarty_last_flush` (`type`, `last_flush`) VALUES (\'compile\', FROM_UNIXTIME(' . time() . '))');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return parent::clearCompiledTemplate($resource_name, $compile_id, $exp_time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark all template files to be regenerated.
|
||||
*
|
||||
* @param int $exp_time expiration time
|
||||
* @param string $type resource type
|
||||
*
|
||||
* @return int number of cache files which needs to be updated
|
||||
*/
|
||||
public function clearAllCache($exp_time = null, $type = null)
|
||||
{
|
||||
Db::getInstance()->execute('REPLACE INTO `' . _DB_PREFIX_ . 'smarty_last_flush` (`type`, `last_flush`) VALUES (\'template\', FROM_UNIXTIME(' . time() . '))');
|
||||
|
||||
return $this->delete_from_lazy_cache(null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark file to be regenerated for a specific template.
|
||||
*
|
||||
* @param string $template_name template name
|
||||
* @param string $cache_id cache id
|
||||
* @param string $compile_id compile id
|
||||
* @param int $exp_time expiration time
|
||||
* @param string $type resource type
|
||||
*
|
||||
* @return int number of cache files which needs to be updated
|
||||
*/
|
||||
public function clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null)
|
||||
{
|
||||
return $this->delete_from_lazy_cache($template_name, $cache_id, $compile_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the compile cache needs to be invalidated (multi front + local cache compatible).
|
||||
*/
|
||||
public function check_compile_cache_invalidation()
|
||||
{
|
||||
static $last_flush = null;
|
||||
if (!file_exists($this->getCompileDir() . 'last_flush')) {
|
||||
@touch($this->getCompileDir() . 'last_flush', time());
|
||||
} elseif (defined('_DB_PREFIX_')) {
|
||||
if ($last_flush === null) {
|
||||
$sql = 'SELECT UNIX_TIMESTAMP(last_flush) as last_flush FROM `' . _DB_PREFIX_ . 'smarty_last_flush` WHERE type=\'compile\'';
|
||||
$last_flush = Db::getInstance()->getValue($sql, false);
|
||||
}
|
||||
if ((int) $last_flush && @filemtime($this->getCompileDir() . 'last_flush') < $last_flush) {
|
||||
@touch($this->getCompileDir() . 'last_flush', time());
|
||||
parent::clearCompiledTemplate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false)
|
||||
{
|
||||
$this->check_compile_cache_invalidation();
|
||||
|
||||
return parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true)
|
||||
{
|
||||
$this->check_compile_cache_invalidation();
|
||||
if ($this->caching) {
|
||||
$this->check_template_invalidation($template, $cache_id, $compile_id);
|
||||
}
|
||||
|
||||
return parent::createTemplate($template, $cache_id, $compile_id, $parent, $do_clone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the lazy template cache invalidation.
|
||||
*
|
||||
* @param string $template template name
|
||||
* @param string $cache_id cache id
|
||||
* @param string $compile_id compile id
|
||||
*/
|
||||
public function check_template_invalidation($template, $cache_id, $compile_id)
|
||||
{
|
||||
static $last_flush = null;
|
||||
if (!file_exists($this->getCacheDir() . 'last_template_flush')) {
|
||||
@touch($this->getCacheDir() . 'last_template_flush', time());
|
||||
} elseif (defined('_DB_PREFIX_')) {
|
||||
if ($last_flush === null) {
|
||||
$sql = 'SELECT UNIX_TIMESTAMP(last_flush) as last_flush FROM `' . _DB_PREFIX_ . 'smarty_last_flush` WHERE type=\'template\'';
|
||||
$last_flush = Db::getInstance()->getValue($sql, false);
|
||||
}
|
||||
|
||||
if ((int) $last_flush && @filemtime($this->getCacheDir() . 'last_template_flush') < $last_flush) {
|
||||
@touch($this->getCacheDir() . 'last_template_flush', time());
|
||||
parent::clearAllCache();
|
||||
} else {
|
||||
if ($cache_id !== null && (is_object($cache_id) || is_array($cache_id))) {
|
||||
$cache_id = null;
|
||||
}
|
||||
|
||||
if ($this->is_in_lazy_cache($template, $cache_id, $compile_id) === false) {
|
||||
// insert in cache before the effective cache creation to avoid nasty race condition
|
||||
$this->insert_in_lazy_cache($template, $cache_id, $compile_id);
|
||||
parent::clearCache($template, $cache_id, $compile_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the cache file path.
|
||||
*
|
||||
* @param string $filepath cache file path
|
||||
* @param string $template template name
|
||||
* @param string $cache_id cache id
|
||||
* @param string $compile_id compile id
|
||||
*/
|
||||
public function update_filepath($filepath, $template, $cache_id, $compile_id)
|
||||
{
|
||||
$template_md5 = md5($template);
|
||||
$sql = 'UPDATE `' . _DB_PREFIX_ . 'smarty_lazy_cache`
|
||||
SET filepath=\'' . pSQL($filepath) . '\'
|
||||
WHERE `template_hash`=\'' . pSQL($template_md5) . '\'';
|
||||
|
||||
$sql .= ' AND cache_id="' . pSQL((string) $cache_id) . '"';
|
||||
|
||||
if (strlen($compile_id) > 32) {
|
||||
$compile_id = md5($compile_id);
|
||||
}
|
||||
$sql .= ' AND compile_id="' . pSQL((string) $compile_id) . '"';
|
||||
Db::getInstance()->execute($sql, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current template is stored in the lazy cache
|
||||
* Entry in the lazy cache = no need to regenerate the template.
|
||||
*
|
||||
* @param string $template template name
|
||||
* @param string $cache_id cache id
|
||||
* @param string $compile_id compile id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_in_lazy_cache($template, $cache_id, $compile_id)
|
||||
{
|
||||
static $is_in_lazy_cache = [];
|
||||
$template_md5 = md5($template);
|
||||
|
||||
if (strlen($compile_id) > 32) {
|
||||
$compile_id = md5($compile_id);
|
||||
}
|
||||
|
||||
$key = md5($template_md5 . '-' . $cache_id . '-' . $compile_id);
|
||||
|
||||
if (isset($is_in_lazy_cache[$key])) {
|
||||
return $is_in_lazy_cache[$key];
|
||||
} else {
|
||||
$sql = 'SELECT UNIX_TIMESTAMP(last_update) as last_update, filepath FROM `' . _DB_PREFIX_ . 'smarty_lazy_cache`
|
||||
WHERE `template_hash`=\'' . pSQL($template_md5) . '\'';
|
||||
$sql .= ' AND cache_id="' . pSQL((string) $cache_id) . '"';
|
||||
$sql .= ' AND compile_id="' . pSQL((string) $compile_id) . '"';
|
||||
|
||||
$result = Db::getInstance()->getRow($sql, false);
|
||||
// If the filepath is not yet set, it means the cache update is in progress in another process.
|
||||
// In this case do not try to clear the cache again and tell to use the existing cache, if any
|
||||
if ($result !== false && $result['filepath'] == '') {
|
||||
// If the cache update is stalled for more than 1min, something should be wrong,
|
||||
// remove the entry from the lazy cache
|
||||
if ($result['last_update'] < time() - 60) {
|
||||
$this->delete_from_lazy_cache($template, $cache_id, $compile_id);
|
||||
}
|
||||
|
||||
$return = true;
|
||||
} else {
|
||||
if ($result === false
|
||||
|| @filemtime($this->getCacheDir() . $result['filepath']) < $result['last_update']) {
|
||||
$return = false;
|
||||
} else {
|
||||
$return = $result['filepath'];
|
||||
}
|
||||
}
|
||||
$is_in_lazy_cache[$key] = $return;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the current template in the lazy cache.
|
||||
*
|
||||
* @param string $template template name
|
||||
* @param string $cache_id cache id
|
||||
* @param string $compile_id compile id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function insert_in_lazy_cache($template, $cache_id, $compile_id)
|
||||
{
|
||||
$template_md5 = md5($template);
|
||||
$sql = 'INSERT IGNORE INTO `' . _DB_PREFIX_ . 'smarty_lazy_cache`
|
||||
(`template_hash`, `cache_id`, `compile_id`, `last_update`)
|
||||
VALUES (\'' . pSQL($template_md5) . '\'';
|
||||
|
||||
$sql .= ',"' . pSQL((string) $cache_id) . '"';
|
||||
|
||||
if (strlen($compile_id) > 32) {
|
||||
$compile_id = md5($compile_id);
|
||||
}
|
||||
$sql .= ',"' . pSQL((string) $compile_id) . '"';
|
||||
$sql .= ', FROM_UNIXTIME(' . time() . '))';
|
||||
|
||||
return Db::getInstance()->execute($sql, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the current template from the lazy cache or the whole cache if no template name is given.
|
||||
*
|
||||
* @param string $template template name
|
||||
* @param string $cache_id cache id
|
||||
* @param string $compile_id compile id
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete_from_lazy_cache($template, $cache_id, $compile_id)
|
||||
{
|
||||
if (!$template) {
|
||||
return Db::getInstance()->execute('TRUNCATE TABLE `' . _DB_PREFIX_ . 'smarty_lazy_cache`', false);
|
||||
}
|
||||
|
||||
$template_md5 = md5($template);
|
||||
$sql = 'DELETE FROM `' . _DB_PREFIX_ . 'smarty_lazy_cache`
|
||||
WHERE template_hash=\'' . pSQL($template_md5) . '\'';
|
||||
|
||||
if ($cache_id != null) {
|
||||
$sql .= ' AND cache_id LIKE "' . pSQL((string) $cache_id) . '%"';
|
||||
}
|
||||
|
||||
if ($compile_id != null) {
|
||||
if (strlen($compile_id) > 32) {
|
||||
$compile_id = md5($compile_id);
|
||||
}
|
||||
$sql .= ' AND compile_id="' . pSQL((string) $compile_id) . '"';
|
||||
}
|
||||
Db::getInstance()->execute($sql, false);
|
||||
|
||||
return Db::getInstance()->Affected_Rows();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user