From b03e1de0a9402501a5485b105b9bd468a5e202db Mon Sep 17 00:00:00 2001 From: Dmitriy Simushev Date: Fri, 17 Jan 2014 09:25:31 +0000 Subject: [PATCH] Replace expand* function with TemplateEngine class --- src/mibew/client.php | 13 +- .../libs/classes/Mibew/Style/ChatStyle.php | 30 ++- .../TemplateEngine/ChatTemplateEngine.php | 251 ++++++++++++++++++ src/mibew/libs/expand.php | 126 --------- src/mibew/mail.php | 7 +- src/mibew/operator/agent.php | 25 +- src/mibew/operator/invitationthemes.php | 1 - src/mibew/operator/redirect.php | 7 +- src/mibew/operator/themes.php | 1 - 9 files changed, 305 insertions(+), 156 deletions(-) create mode 100644 src/mibew/libs/classes/Mibew/TemplateEngine/ChatTemplateEngine.php delete mode 100644 src/mibew/libs/expand.php diff --git a/src/mibew/client.php b/src/mibew/client.php index 0c47ffb7..b2b1a0e6 100644 --- a/src/mibew/client.php +++ b/src/mibew/client.php @@ -25,7 +25,6 @@ require_once(dirname(__FILE__).'/libs/init.php'); require_once(MIBEW_FS_ROOT.'/libs/chat.php'); require_once(MIBEW_FS_ROOT.'/libs/operator.php'); require_once(MIBEW_FS_ROOT.'/libs/groups.php'); -require_once(MIBEW_FS_ROOT.'/libs/expand.php'); require_once(MIBEW_FS_ROOT.'/libs/captcha.php'); require_once(MIBEW_FS_ROOT.'/libs/invitation.php'); require_once(MIBEW_FS_ROOT.'/libs/track.php'); @@ -51,7 +50,7 @@ if (get_remote_level($_SERVER['HTTP_USER_AGENT']) == 'old') { $page = array_merge_recursive( setup_logo() ); - $chat_style->render('nochat'); + $chat_style->render('nochat', $page); exit; } @@ -70,7 +69,7 @@ if (verifyparam("act", "/^(invitation)$/", "default") == 'invitation' // Build js application options $page['invitationOptions'] = json_encode($page['invitation']); // Expand page - $chat_style->render('chat'); + $chat_style->render('chat', $page); exit; } } @@ -136,7 +135,7 @@ if( !isset($_GET['token']) || !isset($_GET['thread']) ) { ) ); $page['leaveMessageOptions'] = json_encode($page['leaveMessage']); - $chat_style->render('chat'); + $chat_style->render('chat', $page); exit; } @@ -165,7 +164,7 @@ if( !isset($_GET['token']) || !isset($_GET['thread']) ) { setup_survey($visitor['name'], $email, $groupid, $info, $referrer) ); $page['surveyOptions'] = json_encode($page['survey']); - $chat_style->render('chat'); + $chat_style->render('chat', $page); exit; } @@ -191,12 +190,12 @@ $page = setup_chatview_for_user($thread); $pparam = verifyparam( "act", "/^(mailthread)$/", "default"); if( $pparam == "mailthread" ) { - $chat_style->render('mail'); + $chat_style->render('mail', $page); } else { // Build js application options $page['chatOptions'] = json_encode($page['chat']); // Expand page - $chat_style->render('chat'); + $chat_style->render('chat', $page); } ?> \ No newline at end of file diff --git a/src/mibew/libs/classes/Mibew/Style/ChatStyle.php b/src/mibew/libs/classes/Mibew/Style/ChatStyle.php index db7186e3..570f7623 100644 --- a/src/mibew/libs/classes/Mibew/Style/ChatStyle.php +++ b/src/mibew/libs/classes/Mibew/Style/ChatStyle.php @@ -19,11 +19,34 @@ namespace Mibew\Style; // Import namespaces and classes of the core use Mibew\Settings; +use Mibew\TemplateEngine\ChatTemplateEngine; /** * Represents a chat style */ class ChatStyle extends Style implements StyleInterface { + + /** + * Template engine for chat templates. + * @var \Mibew\TemplateEngine\ChatTemplateEngine + */ + protected $templateEngine; + + /** + * Object constructor + * + * @param string $style_name Name of the style + */ + public function __construct($style_name) { + parent::__construct($style_name); + + $this->templateEngine = new ChatTemplateEngine( + $this->filesPath(), + $this->name() + ); + } + + /** * Builds base path for style files. This path is relative Mibew root and * does not contain neither leading nor trailing slash. @@ -43,11 +66,8 @@ class ChatStyle extends Style implements StyleInterface { * substitutions in a template. */ public function render($template_name, $data = array()) { - $templates_root = MIBEW_FS_ROOT . - '/' . $this->filesPath() . '/templates/'; - $full_template_name = $template_name . '.tpl'; - - expand($this, $templates_root, $full_template_name); + start_html_output(); + echo($this->templateEngine->render($template_name, $data)); } /** diff --git a/src/mibew/libs/classes/Mibew/TemplateEngine/ChatTemplateEngine.php b/src/mibew/libs/classes/Mibew/TemplateEngine/ChatTemplateEngine.php new file mode 100644 index 00000000..7fc8ec58 --- /dev/null +++ b/src/mibew/libs/classes/Mibew/TemplateEngine/ChatTemplateEngine.php @@ -0,0 +1,251 @@ +stylePath = $style_path; + $this->styleName = $style_name; + } + + /** + * Renders template and returns HTML for it. + * + * @param string $template_name Name of a template with neither path nor + * extension. + * @param array $data Data for substitutions. + * @return string Rendered HTML markup. + */ + public function render($template_name, $data) { + $this->flattenTemplateData = array_flatten_recursive($data); + $this->templateData = $data; + $contents = $this->getTemplateFileContent($template_name); + return $this->expandText($contents); + } + + /** + * Check if condition form conditional construction is true. + * + * @param string $condition Condition name. Can be any element name of the + * template data array. + */ + public function checkCondition($condition) { + if ($condition == 'errors') { + return !empty($this->templateData['errors']) + && is_array($this->templateData['errors']); + } + return !empty($this->flattenTemplateData[$condition]); + } + + /** + * Process conditional construction. This function is a callback for + * "preg_replace_callback" function. + * + * @param array $matches matches passed from "preg_replace_callback" + * function. + * @return string One of conditional blocks depending of conditional value. + */ + public function expandCondition($matches) { + $value = $this->checkCondition($matches[2]) ^ ($matches[1] != 'if'); + + if ($value) { + return preg_replace_callback( + self::IF_REGEXP, + array($this, "expandCondition"), + $matches[3] + ); + } else if (isset($matches[4])) { + return preg_replace_callback( + self::IF_REGEXP, + array($this, "expandCondition"), + substr($matches[4], strpos($matches[4], "}") + 1) + ); + } + + return ""; + } + + /** + * Replace variables in template with its values. This function is a + * callback for "preg_replace_callback" function. + * + * @param array $matches matches passed from "preg_replace_callback" + * function. + * @return string Value of the variable or empty string if the value was not + * passed in with template data. + */ + public function expandVar($matches) { + $prefix = $matches[1]; + $var = $matches[2]; + + if (!$prefix) { + if ($var == 'mibewroot') { + return MIBEW_WEB_ROOT; + } elseif ($var == 'tplroot') { + return MIBEW_WEB_ROOT . "/" . $this->stylePath; + } elseif ($var == 'styleid') { + return $this->styleName; + } elseif ($var == 'pagination') { + return generate_pagination($this->templateData['pagination']); + } elseif ($var == 'errors' || $var == 'harderrors') { + if ( + !empty($this->templateData['errors']) + && is_array($this->templateData['errors']) + ) { + $result = getlocal("$var.header"); + foreach ($this->templateData['errors'] as $e) { + $result .= getlocal("errors.prefix") + . $e + . getlocal("errors.suffix"); + } + $result .= getlocal("errors.footer"); + return $result; + } + } + + } elseif ($prefix == 'msg:' || $prefix == 'msgjs:' || $prefix == 'url:') { + $message = ''; + if (strpos($var, ",") !== false) { + $pos = strpos($var, ","); + $param = substr($var, $pos + 1); + $var = substr($var, 0, $pos); + $message = getlocal2($var, array($this->flattenTemplateData[$param])); + } else { + $message = getlocal($var); + } + if ($prefix == 'msgjs:') { + return json_encode($message); + } + return $message; + } else if ($prefix == 'form:') { + return form_value($this->templateData, $var); + } else if ($prefix == 'page:' || $prefix == 'pagejs:') { + $message = isset($this->flattenTemplateData[$var]) + ? $this->flattenTemplateData[$var] + : ""; + return ($prefix == 'pagejs:') ? json_encode($message) : $message; + } else if ($prefix == 'if:' || $prefix == 'else:' || $prefix == 'endif:' || $prefix == 'ifnot:') { + return ""; + } + + return ""; + } + + /** + * Process "include" control structure. This function is a callback for + * "preg_replace_callback" function. + * + * @param array $matches matches passed from "preg_replace_callback" + * function. + * @return string Contents of including file + */ + public function expandInclude($matches) { + $template_name = $matches[1]; + return $this->getTemplateFileContent($template_name); + } + + /** + * Converts all control structures to markup. + * + * @param string $text Source text + * @return string Markup with no control structures + */ + public function expandText($text) { + $text = preg_replace_callback( + "/\\\${include:([\w\.]+)}/", + array($this, "expandInclude"), + $text + ); + + $text = preg_replace_callback( + self::IF_REGEXP, + array($this, "expandCondition"), + $text + ); + + return preg_replace_callback( + "/\\\${(\w+:)?([\w\.,]+)}/", + array($this, "expandVar"), + $text + ); + } + + /** + * Loads content of a template file. + * + * @param string $template_name Name of a template file to load. + * @return string Template file's content. + * + * @throws \RuntimeException If there is no such template file or the file + * is not readable. + */ + protected function getTemplateFileContent($template_name) { + $full_file_path = MIBEW_FS_ROOT . '/' . $this->stylePath . + '/templates/' . $template_name . '.tpl'; + + if (!is_readable($full_file_path)) { + throw new \RuntimeException( + 'Cannot load template file: "' . $full_file_path . '"' + ); + } + + return file_get_contents($full_file_path); + } +} + +?> \ No newline at end of file diff --git a/src/mibew/libs/expand.php b/src/mibew/libs/expand.php deleted file mode 100644 index f45f6c5a..00000000 --- a/src/mibew/libs/expand.php +++ /dev/null @@ -1,126 +0,0 @@ - 0; - } - return isset($flatten_page[$condition]) && $flatten_page[$condition]; -} - -function expand_condition($matches) -{ - global $page, $ifregexp; - $value = check_condition($matches[2]) ^ ($matches[1] != 'if'); - if ($value) { - return preg_replace_callback($ifregexp, "expand_condition", $matches[3]); - } else if (isset($matches[4])) { - return preg_replace_callback($ifregexp, "expand_condition", substr($matches[4], strpos($matches[4], "}") + 1)); - } - return ""; -} - -function expand_var($matches) -{ - global $page, $errors, $current_style, $flatten_page; - - $prefix = $matches[1]; - $var = $matches[2]; - if (!$prefix) { - if ($var == 'mibewroot') { - return MIBEW_WEB_ROOT; - } else if ($var == 'tplroot') { - return MIBEW_WEB_ROOT . "/" . $current_style->filesPath(); - } else if ($var == 'styleid') { - return $current_style->name(); - } else if ($var == 'pagination') { - return generate_pagination($page['pagination']); - } else if ($var == 'errors' || $var == 'harderrors') { - if (isset($errors) && count($errors) > 0) { - $result = getlocal("$var.header"); - foreach ($errors as $e) { - $result .= getlocal("errors.prefix") . $e . getlocal("errors.suffix"); - } - $result .= getlocal("errors.footer"); - return $result; - } - } - - } else if ($prefix == 'msg:' || $prefix == 'msgjs:' || $prefix == 'url:') { - $message = ''; - if (strpos($var, ",") !== false) { - $pos = strpos($var, ","); - $param = substr($var, $pos + 1); - $var = substr($var, 0, $pos); - $message = getlocal2($var, array($flatten_page[$param])); - } else { - $message = getlocal($var); - } - if ($prefix == 'msgjs:') { - return json_encode($message); - } - return $message; - } else if ($prefix == 'form:') { - return form_value($page, $var); - } else if ($prefix == 'page:' || $prefix == 'pagejs:') { - $message = isset($flatten_page[$var]) ? $flatten_page[$var] : ""; - return ($prefix == 'pagejs:') ? json_encode($message) : $message; - } else if ($prefix == 'if:' || $prefix == 'else:' || $prefix == 'endif:' || $prefix == 'ifnot:') { - return ""; - } - - return ""; -} - -function expand_include($matches) -{ - global $expand_include_path; - $name = $matches[1]; - $contents = @file_get_contents($expand_include_path . $name) or die("cannot load template"); - return $contents; -} - -function expandtext($text) -{ - global $ifregexp; - $text = preg_replace_callback("/\\\${include:([\w\.]+)}/", "expand_include", $text); - $text = preg_replace_callback($ifregexp, "expand_condition", $text); - return preg_replace_callback("/\\\${(\w+:)?([\w\.,]+)}/", "expand_var", $text); -} - -function expand(\Mibew\Style\StyleInterface $style, $templates_root, $filename) -{ - global $page, $expand_include_path, $current_style, $flatten_page; - - $flatten_page = array_flatten_recursive($page); - - start_html_output(); - $expand_include_path = $templates_root; - $current_style = $style; - $contents = @file_get_contents($expand_include_path . $filename); - echo expandtext($contents); -} - -?> \ No newline at end of file diff --git a/src/mibew/mail.php b/src/mibew/mail.php index ad37d6fb..3b78f4d3 100644 --- a/src/mibew/mail.php +++ b/src/mibew/mail.php @@ -23,7 +23,6 @@ use Mibew\Style\ChatStyle; // Initialize libraries require_once(dirname(__FILE__).'/libs/init.php'); require_once(MIBEW_FS_ROOT.'/libs/chat.php'); -require_once(MIBEW_FS_ROOT.'/libs/expand.php'); require_once(MIBEW_FS_ROOT.'/libs/groups.php'); require_once(MIBEW_FS_ROOT.'/libs/notify.php'); @@ -59,7 +58,8 @@ if( count($errors) > 0 ) { $page, setup_logo($group) ); - $chat_style->render('mail'); + $page['errors'] = $errors; + $chat_style->render('mail', $page); exit; } @@ -82,6 +82,7 @@ $page = array_merge_recursive( $page, setup_logo($group) ); -$chat_style->render('mailsent'); +$page['errors'] = $errors; +$chat_style->render('mailsent', $page); exit; ?> \ No newline at end of file diff --git a/src/mibew/operator/agent.php b/src/mibew/operator/agent.php index 6b84aaa5..aa595b03 100644 --- a/src/mibew/operator/agent.php +++ b/src/mibew/operator/agent.php @@ -28,7 +28,6 @@ require_once(MIBEW_FS_ROOT.'/libs/chat.php'); require_once(MIBEW_FS_ROOT.'/libs/groups.php'); require_once(MIBEW_FS_ROOT.'/libs/operator.php'); require_once(MIBEW_FS_ROOT.'/libs/pagination.php'); -require_once(MIBEW_FS_ROOT.'/libs/expand.php'); $operator = check_login(); @@ -57,14 +56,16 @@ if (!isset($_GET['token'])) { $remote_level = get_remote_level($_SERVER['HTTP_USER_AGENT']); if ($remote_level != "ajaxed") { $errors = array(getlocal("thread.error.old_browser")); - $chat_style->render('error'); + $page['errors'] = $errors; + $chat_style->render('error', $page); exit; } $thread = Thread::load($threadid); if (!$thread || !isset($thread->lastToken)) { $errors = array(getlocal("thread.error.wrong_thread")); - $chat_style->render('error'); + $page['errors'] = $errors; + $chat_style->render('error', $page); exit; } @@ -75,7 +76,8 @@ if (!isset($_GET['token'])) { if (!is_capable(CAN_TAKEOVER, $operator)) { $errors = array(getlocal("thread.error.cannot_take_over")); - $chat_style->render('error'); + $page['errors'] = $errors; + $chat_style->render('error', $page); exit; } @@ -94,12 +96,14 @@ if (!isset($_GET['token'])) { if (!$viewonly) { if(! $thread->take($operator)){ $errors = array(getlocal("thread.error.cannot_take")); - $chat_style->render('error'); + $page['errors'] = $errors; + $chat_style->render('error', $page); exit; } } else if (!is_capable(CAN_VIEWTHREADS, $operator)) { $errors = array(getlocal("thread.error.cannot_view")); - $chat_style->render('error'); + $page['errors'] = $errors; + $chat_style->render('error', $page); exit; } @@ -117,7 +121,8 @@ if (!$thread) { if ($thread->agentId != $operator['operatorid'] && !is_capable(CAN_VIEWTHREADS, $operator)) { $errors = array("Cannot view threads"); - $chat_style->render('error'); + $page['errors'] = $errors; + $chat_style->render('error', $page); exit; } @@ -131,12 +136,12 @@ start_html_output(); $pparam = verifyparam("act", "/^(redirect)$/", "default"); if ($pparam == "redirect") { setup_redirect_links($threadid, $operator, $token); - $chat_style->render('redirect'); + $chat_style->render('redirect', $page); } else { // Build js application options $page['chatOptions'] = json_encode($page['chat']); - // Expand page - $chat_style->render('chat'); + // Render the page + $chat_style->render('chat', $page); } ?> \ No newline at end of file diff --git a/src/mibew/operator/invitationthemes.php b/src/mibew/operator/invitationthemes.php index 9c3ab2df..d331ccf3 100644 --- a/src/mibew/operator/invitationthemes.php +++ b/src/mibew/operator/invitationthemes.php @@ -24,7 +24,6 @@ require_once(dirname(dirname(__FILE__)).'/libs/init.php'); require_once(MIBEW_FS_ROOT.'/libs/pagination.php'); require_once(MIBEW_FS_ROOT.'/libs/operator.php'); require_once(MIBEW_FS_ROOT.'/libs/groups.php'); -require_once(MIBEW_FS_ROOT.'/libs/expand.php'); require_once(MIBEW_FS_ROOT.'/libs/settings.php'); $operator = check_login(); diff --git a/src/mibew/operator/redirect.php b/src/mibew/operator/redirect.php index 20ac5b92..929711c2 100644 --- a/src/mibew/operator/redirect.php +++ b/src/mibew/operator/redirect.php @@ -24,7 +24,6 @@ use Mibew\Style\ChatStyle; require_once(dirname(dirname(__FILE__)).'/libs/init.php'); require_once(MIBEW_FS_ROOT.'/libs/operator.php'); require_once(MIBEW_FS_ROOT.'/libs/chat.php'); -require_once(MIBEW_FS_ROOT.'/libs/expand.php'); require_once(MIBEW_FS_ROOT.'/libs/groups.php'); $operator = check_login(); @@ -118,11 +117,13 @@ $page = array_merge_recursive( $page, setup_logo() ); +$page['errors'] = $errors; + if (count($errors) > 0) { - $chat_style->render('error'); + $chat_style->render('error', $page); } else { - $chat_style->render('redirected'); + $chat_style->render('redirected', $page); } ?> \ No newline at end of file diff --git a/src/mibew/operator/themes.php b/src/mibew/operator/themes.php index bfe93b3e..2197e456 100644 --- a/src/mibew/operator/themes.php +++ b/src/mibew/operator/themes.php @@ -25,7 +25,6 @@ require_once(MIBEW_FS_ROOT.'/libs/chat.php'); require_once(MIBEW_FS_ROOT.'/libs/pagination.php'); require_once(MIBEW_FS_ROOT.'/libs/operator.php'); require_once(MIBEW_FS_ROOT.'/libs/groups.php'); -require_once(MIBEW_FS_ROOT.'/libs/expand.php'); require_once(MIBEW_FS_ROOT.'/libs/settings.php'); $operator = check_login();