Page MenuHomeIn-Portal Phabricator

template_cache.php
No OneTemporary

File Metadata

Created
Sat, Feb 1, 5:35 AM

template_cache.php

<?php
/**
* @version $Id: template_cache.php 14241 2011-03-16 20:24:35Z alex $
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class TemplatesCache extends kHelper {
/**
* Base path for searching templates
*
* @var string
*/
var $BasePath;
/**
* Force templates cache to search templates on front-end:
* true - search for theme name in template name
* false - don't search anywhere
* name - theme name to prepend for each template name
*
* @var mixed
*/
var $forceThemeName = false;
/**
* Compile templates to database
*
* @var bool
*/
var $_compileToDatabase = false;
/**
* Compress compiled templates
*
* @var bool
*/
var $_compressOutput = false;
/**
* Template locations of each module
*
* @var Array
*/
var $_modulePaths = Array ();
function TemplatesCache()
{
parent::kHelper();
if ( !defined('T_DOC_COMMENT') ) {
// method "TemplatesCache::_compress" uses such constant, but it's only available since PHP 5.0.0
define('T_DOC_COMMENT', 366);
}
$this->BasePath = FULL_PATH . THEMES_PATH;
$this->_compileToDatabase = defined('SAFE_MODE') && SAFE_MODE;
$this->_compressOutput = $this->Application->ConfigValue('UseTemplateCompression');
if ($this->Application->isAdmin) {
// prepare module template paths for quick access
$module_paths = Array ();
foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
$module_paths[ mb_strtolower($module_name) ] = rtrim($module_info['Path'], '/');
}
$this->_modulePaths = $module_paths;
}
}
/**
* Based on template name gets it's location on disk and owner module
*
* @param string $filename
* @return Array 0 - path on disk, 1 - template name
*/
function GetTemplatePaths($filename)
{
if ($this->Application->isAdmin && array_key_exists($filename, $this->Application->ReplacementTemplates)) {
// process admin template replacement
$filename = $this->Application->ReplacementTemplates[$filename];
}
// allows to use non-replaced version of replaced template
$filename = preg_replace('/^original:(.*)/', '\\1', $filename);
if (preg_match('#^[\/]{0,1}([^\/]*)\/(.*)#', $filename, $regs)) {
$first_dir = $regs[1];
$module_filename = $regs[2];
}
else {
$first_dir = '';
$module_filename = $filename;
}
if (is_string($this->forceThemeName)) {
// when defined, then all templates are read from given theme name
$first_dir = 'theme:' . $this->forceThemeName . ($first_dir ? '/' . $first_dir : '');
}
if ($this->Application->isAdmin && array_key_exists($first_dir, $this->_modulePaths)) {
// template belongs to one of the modules
$path = FULL_PATH . '/' . $this->_modulePaths[$first_dir] . '/admin_templates';
}
elseif ($this->forceThemeName && preg_match('/^theme:(.*)/', $first_dir, $regs)) {
// ability to use Front-End templates in admin (only during mass compilation)
$path = FULL_PATH . '/themes/' . $regs[1];
}
else {
// template from "core" module
$path = $this->BasePath;
$module_filename = $first_dir . '/' . $module_filename;
}
return Array ($path, $module_filename);
}
/**
* Returns template filename by given template name
*
* @param string $filename
* @return string
*/
function GetRealFilename($filename)
{
list ($path, $module_filename) = $this->GetTemplatePaths($filename);
return $path.'/'.trim($module_filename, '/');
}
/**
* Checks, that given template exists on disk
*
* @param string $filename
* @return bool
*/
function TemplateExists($filename)
{
if ((strpos($filename, '../') !== false) || (trim($filename) !== $filename)) {
// when relative paths or special chars are found template names from url, then it's hacking attempt
return false;
}
$real_file = $this->GetRealFilename( strtolower($filename) );
if (substr($real_file, -4) != '.tpl') {
// add ".tpl" file extension, when not specified in template name
$real_file .= '.tpl';
}
return file_exists($real_file);
}
/**
* Returns information about template compilation status
*
* @param string $template
* @return Array
*/
function GetPreParsed($template)
{
$real_name = $this->GetRealFilename($template);
$fname = str_replace(FULL_PATH, WRITEABLE . '/cache', $real_name . '.php');
$tname = $real_name . '.tpl';
if (!file_exists($tname)) {
// given template doesn't exist
return false;
}
if ($this->_compileToDatabase) {
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'Cache
WHERE VarName = "' . $fname . '"';
$cached = $this->Conn->GetRow($sql);
if ($cached !== false && $cached['Cached'] > filemtime($tname)) {
return Array ('active' => 1, 'fname' => $fname, 'tname' => $tname, 'mode' => 'db', 'content' => $cached['Data']);
}
}
else {
if (file_exists($fname) && file_exists($tname) && filemtime($fname) > filemtime($tname)) {
return Array ('active' => 1, 'fname' => $fname, 'tname' => $tname, 'mode' => 'file');
}
if (!file_exists($fname)) {
// make sure to create directory if pre-parsed file does not exist
$this->CheckDir(dirname($fname), WRITEABLE . '/cache');
}
}
// when compiled template is expired or doesn't exist
return Array ('active' => 0, 'fname' => $fname, 'tname' => $tname, 'mode' => 'file');
}
/**
* Saves compiled template version to database or disk
*
* @param string $filename
* @param string $compiled_template
*/
function saveTemplate($filename, &$compiled_template)
{
if ($this->_compileToDatabase) {
$fields_hash = Array (
'VarName' => $filename,
'Data' => &$compiled_template,
'Cached' => adodb_mktime(),
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE');
}
else {
$fp = fopen($filename, 'w');
if ($this->_compressOutput) {
$compiled_template = $this->_compress($compiled_template);
}
if (!fwrite($fp, $compiled_template)) {
trigger_error('Saving compiled template failed', E_USER_ERROR);
}
fclose($fp);
}
}
/**
* Runs template and returns result (template already should be compiled by now)
*
* @param NParser $_parser
* @param Array $pre_parsed
* @return string
*/
function &runTemplate(&$_parser, &$pre_parsed)
{
ob_start();
if ($this->_compileToDatabase) {
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'Cache
WHERE VarName = "' . $pre_parsed['fname'] . '"';
$cached = $this->Conn->GetRow($sql);
if (($cached !== false) && ($cached['Cached'] > filemtime($pre_parsed['tname']))) {
eval('?' . '>' . $cached['Data']);
}
}
else {
if ($pre_parsed['mode'] == 'file') {
include($pre_parsed['fname']);
}
else {
eval('?' . '>' . $pre_parsed['content']);
}
}
$output = ob_get_clean();
return $output;
}
/**
* Compress given php code
*
* @param string $src
* @return string
*/
function _compress($src) {
// Whitespaces left and right from this signs can be ignored
static $IW = array(
T_CONCAT_EQUAL, // .=
T_DOUBLE_ARROW, // =>
T_BOOLEAN_AND, // &&
T_BOOLEAN_OR, // ||
T_IS_EQUAL, // ==
T_IS_NOT_EQUAL, // != or <>
T_IS_SMALLER_OR_EQUAL, // <=
T_IS_GREATER_OR_EQUAL, // >=
T_INC, // ++
T_DEC, // --
T_PLUS_EQUAL, // +=
T_MINUS_EQUAL, // -=
T_MUL_EQUAL, // *=
T_DIV_EQUAL, // /=
T_IS_IDENTICAL, // ===
T_IS_NOT_IDENTICAL, // !==
T_DOUBLE_COLON, // ::
T_PAAMAYIM_NEKUDOTAYIM, // ::
T_OBJECT_OPERATOR, // ->
T_DOLLAR_OPEN_CURLY_BRACES, // ${
T_AND_EQUAL, // &=
T_MOD_EQUAL, // %=
T_XOR_EQUAL, // ^=
T_OR_EQUAL, // |=
T_SL, // <<
T_SR, // >>
T_SL_EQUAL, // <<=
T_SR_EQUAL, // >>=
);
$tokens = token_get_all($src);
$new = "";
$c = sizeof($tokens);
$iw = false; // ignore whitespace
$ih = false; // in HEREDOC
$ls = ""; // last sign
$ot = null; // open tag
for ($i = 0; $i < $c; $i++) {
$token = $tokens[$i];
if (is_array($token)) {
list ($tn, $ts) = $token; // tokens: number, string, line
$tname = token_name($tn);
if ($tn == T_INLINE_HTML) {
$new .= $ts;
$iw = false;
} else {
if ($tn == T_OPEN_TAG) {
if (strpos($ts, " ") || strpos($ts, "\n") || strpos($ts, "\t") || strpos($ts, "\r")) {
$ts = rtrim($ts);
}
$ts .= " ";
$new .= $ts;
$ot = T_OPEN_TAG;
$iw = true;
} elseif ($tn == T_OPEN_TAG_WITH_ECHO) {
$new .= $ts;
$ot = T_OPEN_TAG_WITH_ECHO;
$iw = true;
} elseif ($tn == T_CLOSE_TAG) {
if ($ot == T_OPEN_TAG_WITH_ECHO) {
$new = rtrim($new, "; ");
} else {
$ts = " ".$ts;
}
$new .= $ts;
$ot = null;
$iw = false;
} elseif (in_array($tn, $IW)) {
$new .= $ts;
$iw = true;
} elseif ($tn == T_CONSTANT_ENCAPSED_STRING || $tn == T_ENCAPSED_AND_WHITESPACE) {
if ($ts[0] == '"') {
$ts = addcslashes($ts, "\n\t\r");
}
$new .= $ts;
$iw = true;
} elseif ($tn == T_WHITESPACE) {
$nt = @$tokens[$i+1];
if (!$iw && (!is_string($nt) || $nt == '$') && !in_array($nt[0], $IW)) {
$new .= " ";
}
$iw = false;
} elseif ($tn == T_START_HEREDOC) {
$new .= "<<<S\n";
$iw = false;
$ih = true; // in HEREDOC
} elseif ($tn == T_END_HEREDOC) {
$new .= "S;";
$iw = true;
$ih = false; // in HEREDOC
for ($j = $i + 1; $j < $c; $j++) {
if (is_string($tokens[$j]) && $tokens[$j] == ";") {
$i = $j;
break;
} else if ($tokens[$j][0] == T_CLOSE_TAG) {
break;
}
}
} elseif ($tn == T_COMMENT || $tn == T_DOC_COMMENT) {
$iw = true;
} else {
/*if (!$ih) {
// this also lowecases attribute names :(
$ts = strtolower($ts);
}*/
$new .= $ts;
$iw = false;
}
}
$ls = "";
} else {
if (($token != ";" && $token != ":") || $ls != $token) {
$new .= $token;
$ls = $token;
}
$iw = true;
}
}
return $new;
}
/**
* Recursive mkdir
*
* @param string $dir
* @param string $base_path base path to directory where folders should be created in
*/
function CheckDir($dir, $base_path = '')
{
if (file_exists($dir)) {
return;
}
else {
// remove $base_path from beggining because it is already created during install
$dir = preg_replace('/^'.preg_quote($base_path.'/', '/').'/', '', $dir, 1);
$segments = explode('/', $dir);
$cur_path = $base_path;
foreach ($segments as $segment) {
// do not add leading / for windows paths (c:\...)
$cur_path .= preg_match('/^[a-zA-Z]{1}:/', $segment) ? $segment : '/'.$segment;
if (!file_exists($cur_path)) {
mkdir($cur_path);
}
}
}
}
}

Event Timeline