Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added: The smarty template overriding feature. #1195

Merged
merged 15 commits into from
Sep 17, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Added block wise override feature for the smarty template files
vishal-singh-webkul committed Aug 30, 2024
commit a62ed6d9f76c49ec29cfc78aac7cbea43b779d23
285 changes: 4 additions & 281 deletions classes/Smarty/SmartyCustom.php
Original file line number Diff line number Diff line change
@@ -24,297 +24,20 @@
* International Registered Trademark & Property of PrestaShop SA
*/

class SmartyCustomCore extends Smarty
class SmartyCustomCore extends SmartyDev
{
public $display_comments = false;
public function __construct()
{
parent::__construct();
$this->template_class = 'Smarty_Custom_Template';
}

/**
* 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;
} else {
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);
} else {
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 = array();
$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();
}
}

class Smarty_Custom_Template extends Smarty_Internal_Template
class Smarty_Custom_Template extends Smarty_Dev_Template
{
/** @var SmartyCustom|null */
public $smarty = null;
public $display_comments = false;

public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false)
{
if ($this->smarty->caching) {
$tpl = parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter);
if (property_exists($this, 'cached')) {
$filepath = str_replace($this->smarty->getCacheDir(), '', $this->cached->filepath);
if ($this->smarty->is_in_lazy_cache($this->template_resource, $this->cache_id, $this->compile_id) != $filepath) {
$this->smarty->update_filepath($filepath, $this->template_resource, $this->cache_id, $this->compile_id);
}
}
return $tpl;
} else {
return parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter);
}
}
}
35 changes: 29 additions & 6 deletions classes/Smarty/SmartyDev.php
Original file line number Diff line number Diff line change
@@ -37,9 +37,18 @@ public function __construct()
*/
public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false)
{
return "\n<!-- begin $template -->\n"
.parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter)
."\n<!-- end $template -->\n";
if (($overrideTemplate = Hook::exec('displayOverrideTemplate', array('default_template' => $template, 'controller' => Context::getContext()->controller)))
&& file_exists($overrideTemplate)
) {
$template = $overrideTemplate;
}

$response = parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter);
if (!isset($this->display_comments) || $this->display_comments) {
$response = "\n<!-- begin $template -->\n".$response."\n<!-- end $template -->\n";
}

return $response;
}
}

@@ -56,8 +65,22 @@ public function fetch($template = null, $cache_id = null, $compile_id = null, $p
$tpl = $this->template_resource;
}

return "\n<!-- begin $tpl -->\n"
.parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter)
."\n<!-- end $tpl -->\n";
if (($overrideTemplate = Hook::exec('displayOverrideTemplate', array('default_template' => $tpl, 'controller' => Context::getContext()->controller)))
&& file_exists($overrideTemplate)
) {
$tpl = $overrideTemplate;
if (!is_null($template)) {
$template = Context::getContext()->smarty->createTemplate($tpl);
} else {
$template = $tpl;
}
}

$response = parent::fetch($template, $cache_id, $compile_id, $parent, $display, $merge_tpl_vars, $no_output_filter);
if (!isset($this->display_comments) || $this->display_comments) {
$response = "\n<!-- begin $tpl -->\n".$response."\n<!-- end $tpl -->\n";
}

return $response;
}
}
20 changes: 1 addition & 19 deletions classes/controller/FrontController.php
Original file line number Diff line number Diff line change
@@ -1624,28 +1624,10 @@ public function setTemplate($default_template)
if ($this->useMobileTheme()) {
$this->setMobileTemplate($default_template);
} else {
$template = $this->getOverrideTemplate();
if ($template) {
parent::setTemplate($template);
} else {
parent::setTemplate($default_template);
}
parent::setTemplate($default_template);
}
}

/**
* Returns an overridden template path (if any) for this controller.
* If not overridden, will return false. This method can be easily overriden in a
* specific controller.
*
* @since 1.5.0.13
* @return string|bool
*/
public function getOverrideTemplate()
{
return Hook::exec('DisplayOverrideTemplate', array('controller' => $this));
}

/**
* Checks if mobile theme is active and in use.
*
2 changes: 1 addition & 1 deletion config/smarty.config.inc.php
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@
} elseif (_PS_MODE_DEV_ && !defined('_PS_ADMIN_DIR_')) {
$smarty = new SmartyDev();
} else {
$smarty = new Smarty();
$smarty = new SmartyCustom();
}

$smarty->setCompileDir(_PS_CACHE_DIR_.'smarty/compile');
Loading