function compile($code, $no_echo = false, $echo_var = '') { // Remove any "loose" php ... we want to give admins the ability // to switch on/off PHP for a given template. Allowing unchecked // php is a no-no. There is a potential issue here in that non-php // content may be removed ... however designers should use entities // if they wish to display < and > $match_php_tags = array('#\\<\\?php .*?\\?\\>#is', '#\\<\\script language="php"\\>.*?\\<\\/script\\>#is', '#\\<\\?.*?\\?\\>#s', '#\\<%.*?%\\>#s'); $code = preg_replace($match_php_tags, '', $code); // Pull out all block/statement level elements and seperate plain text preg_match_all('#<!-- PHP -->(.*?)<!-- ENDPHP -->#s', $code, $matches); $php_blocks = $matches[1]; $code = preg_replace('#<!-- PHP -->(.*?)<!-- ENDPHP -->#s', '<!-- PHP -->', $code); preg_match_all('#<!-- INCLUDE ([a-zA-Z0-9\\_\\-\\+\\.\\/]+?) -->#', $code, $matches); $include_blocks = $matches[1]; $code = preg_replace('#<!-- INCLUDE ([a-zA-Z0-9\\_\\-\\+\\.\\/]+?) -->#', '<!-- INCLUDE -->', $code); preg_match_all('#<!-- INCLUDEPHP ([a-zA-Z0-9\\_\\-\\+\\.\\\\\\/]+?) -->#', $code, $matches); $includephp_blocks = $matches[1]; $code = preg_replace('#<!-- INCLUDEPHP ([a-zA-Z0-9\\_\\-\\+\\.\\/]+?) -->#', '<!-- INCLUDEPHP -->', $code); preg_match_all('#<!-- (.*?) (.*?)?[ ]?-->#s', $code, $blocks); $text_blocks = preg_split('#<!-- (.*?) (.*?)?[ ]?-->#s', $code); if ($text_blocks[count($text_blocks) - 1] == '') { unset($text_blocks[count($text_blocks) - 1]); } for ($i = 0; $i < count($text_blocks); $i++) { RosterTplEncode::compile_var_tags($text_blocks[$i]); } $compile_blocks = array(); $block_else_level = array(); $this->block_names = array(); for ($curr_tb = 0; $curr_tb < count($text_blocks); $curr_tb++) { if (isset($blocks[1][$curr_tb])) { switch ($blocks[1][$curr_tb]) { case 'BEGIN': $block_else_level[] = false; $compile_blocks[] = '<?php ' . RosterTplEncode::compile_tag_block($blocks[2][$curr_tb]) . ' ?>'; break; case 'BEGINELSE': $block_else_level[count($block_else_level) - 1] = true; $compile_blocks[] = '<?php }} else { ?>'; break; case 'END': array_pop($this->block_names); $compile_blocks[] = '<?php ' . (array_pop($block_else_level) ? '}' : '}}') . ' ?>'; break; case 'IF': $compile_blocks[] = '<?php ' . RosterTplEncode::compile_tag_if($blocks[2][$curr_tb], false) . ' ?>'; break; case 'ELSE': $compile_blocks[] = '<?php } else { ?>'; break; case 'ELSEIF': $compile_blocks[] = '<?php ' . RosterTplEncode::compile_tag_if($blocks[2][$curr_tb], true) . ' ?>'; break; case 'ENDIF': $compile_blocks[] = '<?php } ?>'; break; case 'DEFINE': $compile_blocks[] = '<?php ' . RosterTplEncode::compile_tag_define($blocks[2][$curr_tb], true) . ' ?>'; break; case 'UNDEFINE': $compile_blocks[] = '<?php ' . RosterTplEncode::compile_tag_define($blocks[2][$curr_tb], false) . ' ?>'; break; case 'INCLUDE': $temp = array_shift($include_blocks); $compile_blocks[] = '<?php $this->_tpl_include(\'' . $temp . "'); ?>"; $this->_tpl_include($temp, false); break; case 'INCLUDEPHP': /* $compile_blocks[] = "<?php include('" . $this->root . '/' . array_shift($includephp_blocks) . "'); ?>"; */ break; case 'PHP': $compile_blocks[] = '<?php ' . array_shift($php_blocks) . ' ?>'; break; case 'TRANSLATE': $params = explode(' ', $blocks[2][$curr_tb]); $key = $params[0]; $compile_blocks[] = '<?php if( isset($roster->locale->act[\'' . $key . '\']) ) { echo $roster->locale->act[\'' . $key . '\']; ' . '} else { echo \'{ TRANSLATE ' . $key . ' }\'; trigger_error(\'Missing translation { ' . $key . ' }\', E_USER_NOTICE); } ?>'; break; case 'TRANSLATE_F': $params = explode(' ', $blocks[2][$curr_tb]); $key = array_shift($params); $args = ''; $extra = ''; foreach ($params as $param) { if (preg_match('#^(([a-z0-9\\-_]+?\\.)+?)(\\$)?([A-Z0-9\\-_]+?)$#', $param, $varref)) { $namespace = $varref[1]; $varname = $varref[4]; $isdefine = $varref[3]; $args .= ',' . RosterTplEncode::generate_block_varref($namespace, $varname, false, $isdefine); } else { $args .= ',( isset($roster->locale->act[\'' . $param . '\']) ? $roster->locale->act[\'' . $param . '\'] : ( isset($this->_tpldata[\'.\'][0][\'' . $param . '\']) ? $this->_tpldata[\'.\'][0][\'' . $param . '\'] : \'{ TRANSLATE ' . $param . ' }\' ))'; } } $compile_blocks[] = '<?php if( isset($roster->locale->act[\'' . $key . '\']) ) { echo sprintf( $roster->locale->act[\'' . $key . '\']' . $args . '); ' . '} else { echo \'{ TRANSLATE_F ' . $key . ' }\'; trigger_error(\'Missing translation { ' . $key . ' }\', E_USER_NOTICE); } ?>'; break; default: RosterTplEncode::compile_var_tags($blocks[0][$curr_tb]); $trim_check = trim($blocks[0][$curr_tb]); $compile_blocks[] = !$no_echo ? !empty($trim_check) ? $blocks[0][$curr_tb] : '' : (!empty($trim_check) ? $blocks[0][$curr_tb] : ''); break; } } } $template_php = '<?php global $roster; ?>'; for ($i = 0; $i < count($text_blocks); $i++) { $trim_check_text = trim($text_blocks[$i]); $trim_check_block = isset($compile_blocks[$i]) ? trim($compile_blocks[$i]) : ''; $template_php .= !$no_echo ? (!empty($trim_check_text) ? $text_blocks[$i] : '') . (!empty($compile_blocks[$i]) ? $compile_blocks[$i] : '') : (!empty($trim_check_text) ? $text_blocks[$i] : '') . (!empty($compile_blocks[$i]) ? $compile_blocks[$i] : ''); } // There will be a number of occassions where we switch into and out of // PHP mode instantaneously. Rather than "burden" the parser with this // we'll strip out such occurences, minimising such switching $template_php = str_replace(' ?><?php ', '', $template_php); return !$no_echo ? $template_php : "\${$echo_var} .= '" . $template_php . "'"; }