Make Smarty search template in database first
If not, fallback to file template Implement normalizer to convert gettingstarted/../support/default.tpl to support/default.tpl
This commit is contained in:
parent
75c7e0fc6d
commit
1aee65859f
@ -30,6 +30,7 @@ if ($detect->isMobile() && $setting->getValue('website_mobile_theme')) {
|
||||
}
|
||||
define('THEME', $theme);
|
||||
|
||||
//Required for Smarty
|
||||
require_once(CLASS_DIR . '/template.class.php');
|
||||
// Load smarty now that we have our theme defined
|
||||
require_once(INCLUDE_DIR . '/smarty.inc.php');
|
||||
|
||||
@ -6,6 +6,17 @@ if (!defined('SECURITY'))
|
||||
|
||||
class Template extends Base {
|
||||
protected $table = 'templates';
|
||||
/**
|
||||
* Get filepath for template name based on current PAGE and ACTION
|
||||
*/
|
||||
public function getFullpath($name) {
|
||||
$chunks = array(PAGE);
|
||||
if( ACTION )
|
||||
$chunks[] = ACTION;
|
||||
$chunks[] = $name;
|
||||
|
||||
return join('/', $chunks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all available themes
|
||||
@ -23,6 +34,41 @@ class Template extends Base {
|
||||
return $aThemes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cached getActiveTemplates method
|
||||
*
|
||||
* @see getActiveTemplates
|
||||
*/
|
||||
private static $active_templates;
|
||||
public function cachedGetActiveTemplates() {
|
||||
if ( is_null(self::$active_templates) ) {
|
||||
self::$active_templates = $this->getActiveTemplates();
|
||||
}
|
||||
return self::$active_templates;
|
||||
}
|
||||
/**
|
||||
* Return the all active templates as hash,
|
||||
* where key is template and value is modified_at
|
||||
*
|
||||
* @return array - list of active templates
|
||||
*/
|
||||
public function getActiveTemplates() {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$stmt = $this->mysqli->prepare("SELECT template, modified_at FROM $this->table WHERE active = 1");
|
||||
if ($stmt && $stmt->execute() && $result = $stmt->get_result()) {
|
||||
$rows = $result->fetch_all(MYSQLI_ASSOC);
|
||||
$hash = array();
|
||||
foreach($rows as $row) {
|
||||
$hash[$row['template']] = strtotime($row['modified_at']);
|
||||
}
|
||||
return $hash;
|
||||
}
|
||||
|
||||
$this->setErrorMessage('Failed to get active templates');
|
||||
$this->debug->append('Template::getActiveTemplates failed: ' . $this->mysqli->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the content of specific template file
|
||||
*
|
||||
@ -57,15 +103,15 @@ class Template extends Base {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return specific template form database
|
||||
* Return specific template from database
|
||||
*
|
||||
* @param $template - name (filepath) of the template
|
||||
* @return array - result from database
|
||||
*/
|
||||
public function getEntry($template) {
|
||||
public function getEntry($template, $columns = "*") {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
|
||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE template = ?");
|
||||
$stmt = $this->mysqli->prepare("SELECT $columns FROM $this->table WHERE template = ?");
|
||||
if ($stmt && $stmt->bind_param('s', $template) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $result->fetch_assoc();
|
||||
|
||||
@ -74,6 +120,22 @@ class Template extends Base {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return last modified time of specific template from database
|
||||
*
|
||||
* @param $template - name (filepath) of the template
|
||||
* @return timestamp - last modified time of template
|
||||
*/
|
||||
public function getEntryMTime($template) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
|
||||
$entry = $this->getEntry($template, "modified_at, active");
|
||||
if ( $entry && $entry['active'])
|
||||
return strtotime($entry['modified_at']);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update template in database
|
||||
*
|
||||
|
||||
@ -10,6 +10,143 @@ define('SMARTY_DIR', INCLUDE_DIR . '/smarty/libs/');
|
||||
// Include the actual smarty class file
|
||||
include(SMARTY_DIR . 'Smarty.class.php');
|
||||
|
||||
/**
|
||||
* Custom Smarty Template Resource for Pages
|
||||
* Get templates from Database
|
||||
* Allow admin to manage his templates from Backoffice
|
||||
*/
|
||||
class Smarty_Resource_Database extends Smarty_Resource_Custom {
|
||||
protected $template;
|
||||
|
||||
public function __construct($template) {
|
||||
$this->template = $template;
|
||||
}
|
||||
/**
|
||||
* Fetch a template and its modification time from database
|
||||
*
|
||||
* @param string $name template name
|
||||
* @param string $source template source
|
||||
* @param integer $mtime template modification timestamp (epoch)
|
||||
* @return void
|
||||
*/
|
||||
protected function fetch($name, &$source, &$mtime) {
|
||||
$oTemplate = $this->template->getEntry($this->fullTemplateName($name));
|
||||
if ( $oTemplate && $oTemplate['active'] ) {
|
||||
$source = $oTemplate['content'];
|
||||
$mtime = strtotime($oTemplate['modified_at']);
|
||||
} else {
|
||||
$source = null;
|
||||
$mtime = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a template's modification time from database
|
||||
*
|
||||
* @note implementing this method is optional. Only implement it if modification times can be accessed faster than loading the comple template source.
|
||||
* @param string $name template name
|
||||
* @return integer timestamp (epoch) the template was modified
|
||||
*/
|
||||
protected function fetchTimestamp($name) {
|
||||
$templates = $this->template->cachedGetActiveTemplates();
|
||||
$mtime = @$templates[$this->fullTemplateName($name)];
|
||||
return $mtime ? $mtime : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend THEME name to template name to get valid DB primary key
|
||||
*
|
||||
* @param string $name template name
|
||||
*/
|
||||
protected function fullTemplateName($name) {
|
||||
return $this->normalisePath(THEME . "/" . $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalise a file path string so that it can be checked safely.
|
||||
*
|
||||
* Attempt to avoid invalid encoding bugs by transcoding the path. Then
|
||||
* remove any unnecessary path components including '.', '..' and ''.
|
||||
*
|
||||
* @param $path string
|
||||
* The path to normalise.
|
||||
* @return string
|
||||
* The path, normalised.
|
||||
* @see https://gist.github.com/thsutton/772287
|
||||
*/
|
||||
protected function normalisePath($path) {
|
||||
// Process the components
|
||||
$parts = explode('/', $path);
|
||||
$safe = array();
|
||||
foreach ($parts as $idx => $part) {
|
||||
if (empty($part) || ('.' == $part)) {
|
||||
continue;
|
||||
} elseif ('..' == $part) {
|
||||
array_pop($safe);
|
||||
continue;
|
||||
} else {
|
||||
$safe[] = $part;
|
||||
}
|
||||
}
|
||||
// Return the "clean" path
|
||||
$path = implode(DIRECTORY_SEPARATOR, $safe);
|
||||
return $path;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Smarty_Resource_Hybrid extends Smarty_Resource {
|
||||
|
||||
protected $databaseResource;
|
||||
|
||||
protected $fileResource;
|
||||
|
||||
public function __construct($dbResource, $fileResource) {
|
||||
$this->databaseResource = $dbResource;
|
||||
$this->fileResource = $fileResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* populate Source Object with meta data from Resource
|
||||
*
|
||||
* @param Smarty_Template_Source $source source object
|
||||
* @param Smarty_Internal_Template $_template template object
|
||||
*/
|
||||
public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template=null) {
|
||||
$this->databaseResource->populate($source, $_template);
|
||||
if ( !$source->exists ) {
|
||||
$source->type = 'file';
|
||||
return $this->fileResource->populate($source, $_template);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load template's source into current template object
|
||||
*
|
||||
* @param Smarty_Template_Source $source source object
|
||||
* @return string template source
|
||||
* @throws SmartyException if source cannot be loaded
|
||||
*/
|
||||
public function getContent(Smarty_Template_Source $source) {
|
||||
try {
|
||||
return $this->databaseResource->getContent($source);
|
||||
} catch(SmartyException $e) {
|
||||
return $this->fileResource->getContent($source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine basename for compiled filename
|
||||
*
|
||||
* @param Smarty_Template_Source $source source object
|
||||
* @return string resource's basename
|
||||
*/
|
||||
public function getBasename(Smarty_Template_Source $source) {
|
||||
return $this->fileResource->getBasename($source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We initialize smarty here
|
||||
$debug->append('Instantiating Smarty Object', 3);
|
||||
$smarty = new Smarty;
|
||||
@ -18,6 +155,11 @@ $smarty = new Smarty;
|
||||
$debug->append('Define Smarty Paths', 3);
|
||||
$smarty->template_dir = BASEPATH . 'templates/' . THEME . '/';
|
||||
$smarty->compile_dir = BASEPATH . 'templates/compile/';
|
||||
$smarty->registerResource('hybrid', new Smarty_Resource_Hybrid(
|
||||
new Smarty_Resource_Database($template),
|
||||
new Smarty_Internal_Resource_File()
|
||||
));
|
||||
$smarty->default_resource_type = "hybrid";
|
||||
$smarty_cache_key = md5(serialize($_REQUEST) . serialize(@$_SESSION['USERDATA']['id']));
|
||||
|
||||
// Optional smarty caching, check Smarty documentation for details
|
||||
|
||||
@ -80,6 +80,9 @@ if (!empty($action)) {
|
||||
require_once(PAGES_DIR . '/' . $arrPages[$page]);
|
||||
}
|
||||
|
||||
define('PAGE', $page);
|
||||
define('ACTION', $action);
|
||||
|
||||
// For our content inclusion
|
||||
$smarty->assign("PAGE", $page);
|
||||
$smarty->assign("ACTION", $action);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user