%PDF- %PDF-
Direktori : /data/www_bck/varak.cloud_bck/tracker.varak.cloud/src/Legacy/ |
Current File : //data/www_bck/varak.cloud_bck/tracker.varak.cloud/src/Legacy/Template.php |
<?php /** * TorrentPier – Bull-powered BitTorrent tracker engine * * @copyright Copyright (c) 2005-2018 TorrentPier (https://torrentpier.com) * @link https://github.com/torrentpier/torrentpier for the canonical source repository * @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License */ namespace TorrentPier\Legacy; /** * Class Template * @package TorrentPier\Legacy */ class Template { /** * Variable that holds all the data we'll be substituting into the compiled templates. * This will end up being a multi-dimensional array like this: * $this->_tpldata[block.][iteration#][child.][iteration#][child2.][iteration#][variablename] == value * if it's a root-level variable, it'll be like this: * $this->vars[varname] == value or $this->_tpldata['.'][0][varname] == value * * @var array */ public $_tpldata = [ '.' => [ 0 => [] ] ]; /** @var array added for easier access to data */ public $vars; /** @var array hash of filenames for each template handle */ public $files = []; /** @var array cache files that exists */ public $files_cache = []; /** @var array cache files (exists or not exists) */ public $files_cache2 = []; /** @var string root template directory */ public $root = ''; /** @var string cache directory */ public $cachedir = CACHE_DIR . '/'; /** @var string template root directory */ public $tpldir = ''; /** @var string default template directory */ public $tpldef = 'default'; /** @var array this will hash handle names to the compiled code for that handle */ public $compiled_code = []; /** @var array this will hold the uncompiled code for that handle */ public $uncompiled_code = []; /** @var int cache settings */ public $use_cache = 1; public $cache_writable = 1; /** @var int auto-compile setting */ public $auto_compile = 1; /** @var string current template name */ public $tpl = ''; public $cur_tpl = ''; /** @var array list of replacements */ public $replace = []; /** @var int counter for include */ public $include_count = 0; /** @var string extension tpl-cache files */ public $cached_tpl_ext = 'php'; /** @var string these handles will be parsed if pparse() is executed */ public $preparse = ''; public $postparse = ''; /** @var bool subtemplates mod detection */ public $subtemplates = false; /** @var array style configuration */ public $style_config = []; public $lang = []; /** * Constructor. Installs XS mod on first run or updates it and sets the root dir. * * @param string $root */ public function __construct($root = '.') { global $bb_cfg, $lang; // setting pointer "vars" $this->vars = &$this->_tpldata['.'][0]; // load configuration $this->tpldir = TEMPLATES_DIR; $this->root = $root; $this->tpl = basename($root); $this->lang =& $lang; $this->use_cache = $bb_cfg['xs_use_cache']; } /** * Generates a full path+filename for the given filename, which can either * be an absolute name, or a name relative to the rootdir for this Template object. * * @param $filename * @param bool $xs_include * * @return mixed|string */ public function make_filename($filename, $xs_include = false) { // Check replacements list if (!$xs_include && isset($this->replace[$filename])) { $filename = $this->replace[$filename]; } // Check if it's an absolute or relative path. if (($filename[0] !== '/') && ($filename[1] !== ':')) { return $this->root . '/' . $filename; } return $filename; } /** * Converts template filename to cache filename. * Returns empty string if non-cachable (for tpl files outside of root dir). * $filename should be absolute filename * * @param $filename * * @return string */ public function make_filename_cache($filename) { $filename = clean_filename(str_replace(TEMPLATES_DIR, '', $filename)); return $this->cachedir . XS_TPL_PREFIX . $filename . '.' . $this->cached_tpl_ext; } /** * Sets the template filenames for handles. * $filename_array should be a hash of handle => filename pairs. * * @param $filenames */ public function set_filenames($filenames) { foreach ($filenames as $handle => $filename) { $this->set_filename($handle, $filename); } } /** * Assigns template filename for handle. * * @param $handle * @param $filename * @param bool $xs_include * @param bool $quiet * * @return bool */ public function set_filename($handle, $filename, $xs_include = false, $quiet = false) { $can_cache = $this->use_cache; $this->files[$handle] = $this->make_filename($filename, $xs_include); $this->files_cache[$handle] = ''; $this->files_cache2[$handle] = ''; // checking if we have valid filename if (!$this->files[$handle]) { if ($xs_include || $quiet) { return false; } die("Template->make_filename(): Error - invalid template $filename"); } // creating cache filename if ($can_cache) { $this->files_cache2[$handle] = $this->make_filename_cache($this->files[$handle]); if (@file_exists($this->files_cache2[$handle])) { $this->files_cache[$handle] = $this->files_cache2[$handle]; } } // checking if tpl and/or php file exists if (empty($this->files_cache[$handle]) && !@file_exists($this->files[$handle])) { if ($quiet) { return false; } die('Template->make_filename(): Error - template file not found: <br /><br />' . hide_bb_path($this->files[$handle])); } // checking if we should recompile cache if (!empty($this->files_cache[$handle])) { $cache_time = @filemtime($this->files_cache[$handle]); if (@filemtime($this->files[$handle]) > $cache_time) { // file was changed. don't use cache file (will be recompled if configuration allowes it) $this->files_cache[$handle] = ''; } } return true; } /** * includes file or executes code * * @param $filename * @param $code * @param $handle */ public function execute($filename, $code, $handle) { $this->cur_tpl = $filename; global $lang, $source_lang, $bb_cfg, $user; $L =& $lang; $V =& $this->vars; $SL =& $source_lang; if ($filename) { include $filename; } else { eval($code); } } /** * Load the file for the handle, compile the file and run the compiled code. * This will print out the results of executing the template. * * @param $handle * * @return bool */ public function pparse($handle) { // parsing header if there is one if ($this->preparse || $this->postparse) { $preparse = $this->preparse; $postparse = $this->postparse; $this->preparse = ''; $this->postparse = ''; if ($preparse) { $this->pparse($preparse); } if ($postparse) { $str = $handle; $handle = $postparse; $this->pparse($str); } } // checking if handle exists if (empty($this->files[$handle]) && empty($this->files_cache[$handle])) { die("Template->loadfile(): No files found for handle $handle"); } $this->xs_startup(); $force_recompile = empty($this->uncompiled_code[$handle]) ? false : true; // checking if php file exists. if (!empty($this->files_cache[$handle]) && !$force_recompile) { // php file exists - running it instead of tpl $this->execute($this->files_cache[$handle], '', $handle); return true; } if (!$this->loadfile($handle)) { die("Template->pparse(): Could not load template file for handle $handle"); } // actually compile the template now. if (empty($this->compiled_code[$handle])) { // Actually compile the code now. if (!empty($this->files_cache2[$handle]) && empty($this->files_cache[$handle]) && !$force_recompile) { $this->compiled_code[$handle] = $this->compile2($this->uncompiled_code[$handle], $handle, $this->files_cache2[$handle]); } else { $this->compiled_code[$handle] = $this->compile2($this->uncompiled_code[$handle], '', ''); } } // Run the compiled code. if (empty($this->files_cache[$handle]) || $force_recompile) { $this->execute('', $this->compiled_code[$handle], $handle); } else { $this->execute($this->files_cache[$handle], '', $handle); } return true; } /** * Block-level variable assignment. Adds a new block iteration with the given * variable assignments. Note that this should only be called once per block iteration. * * @param $blockname * @param $vararray * * @return bool */ public function assign_block_vars($blockname, $vararray) { if (false !== strpos($blockname, '.')) { // Nested block. $blocks = explode('.', $blockname); $blockcount = \count($blocks) - 1; $str = &$this->_tpldata; for ($i = 0; $i < $blockcount; $i++) { $str = &$str[$blocks[$i] . '.']; $str = &$str[\count($str) - 1]; } // Now we add the block that we're actually assigning to. // We're adding a new iteration to this block with the given // variable assignments. $str[$blocks[$blockcount] . '.'][] = $vararray; } else { // Top-level block. // Add a new iteration to this block with the variable assignments // we were given. $this->_tpldata[$blockname . '.'][] = $vararray; } return true; } /** * Root-level variable assignment. Adds to current assignments, overriding * any existing variable assignment with the same name. * * @param $vararray */ public function assign_vars($vararray) { foreach ($vararray as $key => $val) { $this->vars[$key] = $val; } } /** * Root-level variable assignment. Adds to current assignments, overriding * any existing variable assignment with the same name. * * @param $varname * @param bool $varval */ public function assign_var($varname, $varval = true) { $this->vars[$varname] = $varval; } /** * If not already done, load the file for the given handle and populate * the uncompiled_code[] hash with its code. Do not compile. * * @param $handle * * @return bool */ public function loadfile($handle) { // If cached file exists do nothing - it will be included via include() if (!empty($this->files_cache[$handle])) { return true; } // If the file for this handle is already loaded and compiled, do nothing. if (!empty($this->uncompiled_code[$handle])) { return true; } // If we don't have a file assigned to this handle, die. if (empty($this->files[$handle])) { die("Template->loadfile(): No file specified for handle $handle"); } $filename = $this->files[$handle]; if (($str = @file_get_contents($filename)) === false) { die("Template->loadfile(): File $filename for handle $handle is empty"); } $this->uncompiled_code[$handle] = $str; return true; } /** * Generates a reference to the given variable inside the given (possibly nested) * block namespace. This is a string of the form: * ' . $this->_tpldata['parent.'][$_parent_i]['$child1.'][$_child1_i]['$child2.'][$_child2_i]...['varname'] . ' * It's ready to be inserted into an "echo" line in one of the templates. * NOTE: expects a trailing "." on the namespace. * * @param $namespace * @param $varname * * @return string */ public function generate_block_varref($namespace, $varname) { // Strip the trailing period. $namespace = substr($namespace, 0, -1); // Get a reference to the data block for this namespace. $varref = $this->generate_block_data_ref($namespace, true); // Prepend the necessary code to stick this in an echo line. // Append the variable reference. $varref .= "['$varname']"; $varref = "<?php echo isset($varref) ? $varref : ''; ?>"; return $varref; } /** * Generates a reference to the array of data values for the given * (possibly nested) block namespace. This is a string of the form: * $this->_tpldata['parent.'][$_parent_i]['$child1.'][$_child1_i]['$child2.'][$_child2_i]...['$childN.'] * * If $include_last_iterator is true, then [$_childN_i] will be appended to the form shown above. * NOTE: does not expect a trailing "." on the blockname. * * @param $blockname * @param $include_last_iterator * * @return string */ public function generate_block_data_ref($blockname, $include_last_iterator) { // Get an array of the blocks involved. $blocks = explode('.', $blockname); $blockcount = \count($blocks) - 1; if ($include_last_iterator) { return '$' . $blocks[$blockcount] . '_item'; } return '$' . $blocks[$blockcount - 1] . '_item[\'' . $blocks[$blockcount] . '.\']'; } public function compile_code($filename, $code) { // $filename - file to load code from. used if $code is empty // $code - tpl code // load code from file if (!$code && !empty($filename)) { $code = file_get_contents($filename); } // Replace <!-- (END)PHP --> tags $search = array('<!-- PHP -->', '<!-- ENDPHP -->'); $replace = array('<' . '?php ', ' ?' . '>'); $code = str_replace($search, $replace, $code); // Break it up into lines and put " -->" back. $code_lines = explode(' -->', $code); $count = \count($code_lines); for ($i = 0; $i < ($count - 1); $i++) { $code_lines[$i] .= ' -->'; } $block_nesting_level = 0; $block_names = array(); $block_names[0] = '.'; $block_items = array(); $count_if = 0; // prepare array for compiled code $compiled = array(); // array of switches $sw = array(); // replace all short php tags $new_code = array(); $line_count = \count($code_lines); for ($i = 0; $i < $line_count; $i++) { $line = $code_lines[$i]; $pos = strpos($line, '<?'); if ($pos === false) { $new_code[] = $line; continue; } if (substr($line, $pos, 5) === '<?php') { // valid php tag. skip it $new_code[] = substr($line, 0, $pos + 5); $code_lines[$i] = substr($line, $pos + 5); $i--; continue; } // invalid php tag $new_code[] = substr($line, 0, $pos) . '<?php echo \'<?\'; ?>'; $code_lines[$i] = substr($line, $pos + 2); $i--; } $code_lines = $new_code; // main loop $line_count = \count($code_lines); for ($i = 0; $i < $line_count; $i++) { $line = $code_lines[$i]; // reset keyword type $keyword_type = XS_TAG_NONE; // check if we have valid keyword in current line $pos1 = strpos($line, '<!-- '); if ($pos1 === false) { // no keywords in this line $compiled[] = $this->_compile_text($line); continue; } // find end of html comment $pos2 = strpos($line, ' -->', $pos1); if ($pos2 !== false) { // find end of keyword in comment $pos3 = strpos($line, ' ', $pos1 + 5); if ($pos3 !== false && $pos3 <= $pos2) { $keyword = substr($line, $pos1 + 5, $pos3 - $pos1 - 5); // check keyword against list of supported keywords. case-sensitive if ($keyword === 'BEGIN') { $keyword_type = XS_TAG_BEGIN; } elseif ($keyword === 'END') { $keyword_type = XS_TAG_END; } elseif ($keyword === 'INCLUDE') { $keyword_type = XS_TAG_INCLUDE; } elseif ($keyword === 'IF') { $keyword_type = XS_TAG_IF; } elseif ($keyword === 'ELSE') { $keyword_type = XS_TAG_ELSE; } elseif ($keyword === 'ELSEIF') { $keyword_type = XS_TAG_ELSEIF; } elseif ($keyword === 'ENDIF') { $keyword_type = XS_TAG_ENDIF; } elseif ($keyword === 'BEGINELSE') { $keyword_type = XS_TAG_BEGINELSE; } } } if (!$keyword_type) { // not valid keyword. process the rest of line $compiled[] = $this->_compile_text(substr($line, 0, $pos1 + 4)); $code_lines[$i] = substr($line, $pos1 + 4); $i--; continue; } // remove code before keyword if ($pos1 > 0) { $compiled[] = $this->_compile_text(substr($line, 0, $pos1)); } // remove keyword $keyword_str = substr($line, $pos1, $pos2 - $pos1 + 4); $params_str = $pos2 == $pos3 ? '' : substr($line, $pos3 + 1, $pos2 - $pos3 - 1); $code_lines[$i] = substr($line, $pos2 + 4); $i--; // Check keywords /* * <!-- BEGIN --> */ if ($keyword_type == XS_TAG_BEGIN) { $params = explode(' ', $params_str); $num_params = \count($params); // get variable name if ($num_params == 1) { $var = $params[0]; } elseif ($num_params == 2) { if ($params[0] === '') { $var = $params[1]; } elseif ($params[1] === '') { $var = $params[0]; } else { // invalid tag $compiled[] = $keyword_str; continue; } } else { // invalid tag $compiled[] = $keyword_str; continue; } // adding code $block_nesting_level++; $block_names[$block_nesting_level] = $var; if (isset($block_items[$var])) { $block_items[$var]++; } else { $block_items[$var] = 1; } if ($block_nesting_level < 2) { // Block is not nested. $line = '<' . "?php\n\n"; $line .= '$' . $var . '_count = ( isset($this->_tpldata[\'' . $var . '.\']) ) ? sizeof($this->_tpldata[\'' . $var . '.\']) : 0;'; $line .= "\n" . 'for ($' . $var . '_i = 0; $' . $var . '_i < $' . $var . '_count; $' . $var . '_i++)'; $line .= "\n" . '{' . "\n"; $line .= ' $' . $var . '_item = &$this->_tpldata[\'' . $var . '.\'][$' . $var . '_i];' . "\n"; $line .= " \${$var}_item['S_ROW_COUNT'] = \${$var}_i;\n"; $line .= " \${$var}_item['S_NUM_ROWS'] = \${$var}_count;\n"; $line .= "\n?" . '>'; } else { // This block is nested. // Generate a namespace string for this block. $namespace = implode('.', $block_names); // strip leading period from root level.. $namespace = substr($namespace, 2); // Get a reference to the data array for this block that depends on the // current indices of all parent blocks. $varref = $this->generate_block_data_ref($namespace, false); // Create the for loop code to iterate over this block. $line = '<' . "?php\n\n"; $line .= '$' . $var . '_count = ( isset(' . $varref . ') ) ? sizeof(' . $varref . ') : 0;'; $line .= "\n" . 'for ($' . $var . '_i = 0; $' . $var . '_i < $' . $var . '_count; $' . $var . '_i++)'; $line .= "\n" . '{' . "\n"; $line .= ' $' . $var . '_item = &' . $varref . '[$' . $var . '_i];' . "\n"; $line .= " \${$var}_item['S_ROW_COUNT'] = \${$var}_i;\n"; $line .= " \${$var}_item['S_NUM_ROWS'] = \${$var}_count;\n"; $line .= "\n?" . '>'; } $compiled[] = $line; continue; } /* * <!-- END --> */ if ($keyword_type == XS_TAG_END) { $params = explode(' ', $params_str); $num_params = \count($params); if ($num_params == 1) { $var = $params[0]; } elseif ($num_params == 2 && $params[0] === '') { $var = $params[1]; } elseif ($num_params == 2 && $params[1] === '') { $var = $params[0]; } else { $compiled[] = $keyword_str; continue; } // We have the end of a block. $line = '<' . "?php\n\n"; $line .= '} // END ' . $var . "\n\n"; $line .= 'if(isset($' . $var . '_item)) { unset($' . $var . '_item); } '; $line .= "\n\n?" . '>'; if (isset($block_items[$var])) { $block_items[$var]--; } else { $block_items[$var] = -1; } unset($block_names[$block_nesting_level]); $block_nesting_level--; $compiled[] = $line; continue; } /* * <!-- BEGINELSE --> */ if ($keyword_type == XS_TAG_BEGINELSE) { if ($block_nesting_level) { $var = $block_names[$block_nesting_level]; $compiled[] = '<' . '?php } if(!$' . $var . '_count) { ?' . '>'; } else { $compiled[] = $keyword_str; continue; } } /* * <!-- INCLUDE --> */ if ($keyword_type == XS_TAG_INCLUDE) { $params = explode(' ', $params_str); $num_params = \count($params); if ($num_params != 1) { $compiled[] = $keyword_str; continue; } $line = '<' . '?php '; $filehash = md5($params_str . $this->include_count . TIMENOW); $line .= ' $this->set_filename(\'xs_include_' . $filehash . '\', \'' . $params_str . '\', true); '; $line .= ' $this->pparse(\'xs_include_' . $filehash . '\'); '; $line .= ' ?' . '>'; $this->include_count++; $compiled[] = $line; continue; } /* * <!-- IF --> */ if ($keyword_type == XS_TAG_IF || $keyword_type == XS_TAG_ELSEIF) { if (!$count_if) { $keyword_type = XS_TAG_IF; } $str = $this->compile_tag_if($params_str, $keyword_type != XS_TAG_IF); if ($str) { $compiled[] = '<?php ' . $str . ' ?>'; if ($keyword_type == XS_TAG_IF) { $count_if++; } } else { $compiled[] = $keyword_str; } continue; } /* * <!-- ELSE --> */ if ($keyword_type == XS_TAG_ELSE && $count_if > 0) { $compiled[] = '<?php } else { ?>'; continue; } /* * <!-- ENDIF --> */ if ($keyword_type == XS_TAG_ENDIF && $count_if > 0) { $compiled[] = '<?php } ?>'; $count_if--; continue; } } // bring it back into a single string. $code_header = ''; $code_footer = ''; return $code_header . implode('', $compiled) . $code_footer; } /** * Compile code between tags * * @param $code * * @return mixed */ public function _compile_text($code) { if (\strlen($code) < 3) { return $code; } // change template varrefs into PHP varrefs // This one will handle varrefs WITH namespaces $varrefs = array(); preg_match_all('#\{(([a-z0-9\-_]+?\.)+)([a-z0-9\-_]+?)\}#is', $code, $varrefs); $varcount = \count($varrefs[1]); $search = array(); $replace = array(); for ($i = 0; $i < $varcount; $i++) { $namespace = $varrefs[1][$i]; $varname = $varrefs[3][$i]; $new = $this->generate_block_varref($namespace, $varname); $search[] = $varrefs[0][$i]; $replace[] = $new; } if (\count($search) > 0) { $code = str_replace($search, $replace, $code); } // This will handle the remaining root-level varrefs $code = preg_replace('#\{(L_([a-z0-9\-_]+?))\}#i', '<?php echo isset($L[\'$2\']) ? $L[\'$2\'] : (isset($SL[\'$2\']) ? $SL[\'$2\'] : $V[\'$1\']); ?>', $code); $code = preg_replace('#\{(\$[a-z_][a-z0-9_$\->\'\"\.\[\]]*?)\}#i', '<?php echo isset($1) ? $1 : \'\'; ?>', $code); $code = preg_replace('#\{(\#([a-z_][a-z0-9_]*?))\}#i', '<?php echo defined(\'$2\') ? $2 : \'\'; ?>', $code); $code = preg_replace('#\{([a-z0-9\-_]+?)\}#i', '<?php echo isset($V[\'$1\']) ? $V[\'$1\'] : \'\'; ?>', $code); return $code; } /** * Compile IF tags - much of this is from Smarty with some adaptions for our block level methods * * @param $tag_args * @param $elseif * @return string */ public function compile_tag_if($tag_args, $elseif) { /* Tokenize args for 'if' tag. */ preg_match_all('/(?: "[^"\\\\]*(?:\\\\.[^"\\\\]*)*" | \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' | [(),] | [^\s(),]+)/x', $tag_args, $match); $tokens = $match[0]; $tokens_cnt = \count($tokens); $is_arg_stack = array(); for ($i = 0; $i < $tokens_cnt; $i++) { $token = &$tokens[$i]; switch ($token) { case 'eq': $token = '=='; break; case 'ne': case 'neq': $token = '!='; break; case 'lt': $token = '<'; break; case 'le': case 'lte': $token = '<='; break; case 'gt': $token = '>'; break; case 'ge': case 'gte': $token = '>='; break; case 'and': $token = '&&'; break; case 'or': $token = '||'; break; case 'not': $token = '!'; break; case 'mod': $token = '%'; break; case '(': $is_arg_stack[] = $i; break; case 'is': $is_arg_start = ($tokens[$i - 1] == ')') ? array_pop($is_arg_stack) : $i - 1; $is_arg = implode(' ', \array_slice($tokens, $is_arg_start, $i - $is_arg_start)); $new_tokens = $this->_parse_is_expr($is_arg, \array_slice($tokens, $i + 1)); array_splice($tokens, $is_arg_start, \count($tokens), $new_tokens); $i = $is_arg_start; break; default: $pattern = '@^ ( # 1 ([a-z0-9\-_]+?\.)+? # 2 block tpl vars (VAR1.VAR2.) but without last )? ( # 3 ([a-z_][a-z0-9\-_]*)? # 4 single tpl var or last block var (last in block) (\$[a-z_][a-z0-9_$\->\'\"\.\[\]]*)? # 5 php var (\#([a-z_][a-z0-9_]*))? # 7 php const ) $@ix'; if (preg_match($pattern, $token, $m)) { if (!empty($m[1])) { $token = $this->generate_block_data_ref(substr($m[1], 0, -1), true) . "['{$m[4]}']"; } elseif (!empty($m[4])) { $token = ($tokens_cnt == 1) ? "!empty(\$V['{$m[4]}'])" : "\$V['{$m[4]}']"; } elseif (!empty($m[5])) { $token = ($tokens_cnt == 1) ? "!empty({$m[5]})" : (string)($m[5]); } elseif (!empty($m[7])) { $token = ($tokens_cnt == 1) ? "defined('{$m[7]}') && {$m[7]}" : (string)($m[7]); } } break; } } if ($elseif) { $code = '} elseif (' . implode(' ', $tokens) . ') {'; } else { $code = 'if (' . implode(' ', $tokens) . ') {'; } return $code; } /** * This is from Smarty * * @param $is_arg * @param $tokens * * @return mixed */ public function _parse_is_expr($is_arg, $tokens) { $expr_end = 0; $negate_expr = false; if (($first_token = array_shift($tokens)) == 'not') { $negate_expr = true; $expr_type = array_shift($tokens); } else { $expr_type = $first_token; } switch ($expr_type) { case 'even': if (@$tokens[$expr_end] == 'by') { $expr_end++; $expr_arg = $tokens[$expr_end++]; $expr = "!(($is_arg / $expr_arg) % $expr_arg)"; } else { $expr = "!($is_arg % 2)"; } break; case 'odd': if (@$tokens[$expr_end] == 'by') { $expr_end++; $expr_arg = $tokens[$expr_end++]; $expr = "(($is_arg / $expr_arg) % $expr_arg)"; } else { $expr = "($is_arg % 2)"; } break; case 'div': if (@$tokens[$expr_end] == 'by') { $expr_end++; $expr_arg = $tokens[$expr_end++]; $expr = "!($is_arg % $expr_arg)"; } break; default: break; } if ($negate_expr) { $expr = "!($expr)"; } array_splice($tokens, 0, $expr_end, $expr); return $tokens; } /** * Compiles code and writes to cache if needed * * @param $code * @param $handle * @param $cache_file * * @return string */ public function compile2($code, $handle, $cache_file) { $code = $this->compile_code('', $code); if ($cache_file && !empty($this->use_cache) && !empty($this->auto_compile)) { $res = $this->write_cache($cache_file, $code); if ($handle && $res) { $this->files_cache[$handle] = $cache_file; } } $code = '?' . '>' . $code . '<' . "?php\n"; return $code; } /** * Write cache to disk * * @param $filename * @param $code */ public function write_cache($filename, $code) { file_write($code, $filename, false, true, true); } public function xs_startup() { global $bb_cfg; // adding language variable (eg: "english" or "german") // can be used to make truly multi-lingual templates $this->vars['LANG'] = $this->vars['LANG'] ?? $bb_cfg['default_lang']; // adding current template $tpl = $this->root . '/'; if (0 === strpos($tpl, './')) { $tpl = substr($tpl, 2, \strlen($tpl)); } $this->vars['TEMPLATE'] = $this->vars['TEMPLATE'] ?? $tpl; $this->vars['TEMPLATE_NAME'] = $this->vars['TEMPLATE_NAME'] ?? $this->tpl; } }