* @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License * @author netico * */ class Template { private $blocks; private $vars; private $nb; private $template; /** * It requires the path to the template file. * You can refer to the TEMPLATES constant. * * @param string $template File path to template file. * @return void */ public function __construct($template) { $this->template = $template; $this->nb = array(); $this->blocks = array(); $this->vars = array(); } /** * The method adds a variable to the template. * This example describes how variables can be used within templates. * * PHP code: * * $t = new template("template.tpl"); * $t->add("foo", "Barletta"); * $t->output(); * * HTML code: * * I love {foo} * * Output: * * I love Barletta * * @param string $key * @param string $value * @return void */ public function add($key, $value) { $m = array(); if (preg_match("/" . preg_quote('.', '/') . "/s", $key, $m) > 0) { $a = preg_split("/" . preg_quote('.', '/') . "/s", $key); $c = $a[0]; $d = $a[1]; $iter = $this->iter; $this->nb["$c"][$iter]["$d"] = array("key" => "$d", "value" => "$value"); } if (preg_match("/" . preg_quote('.', '/') . "/s", $key, $m) < 1) { $this->vars["$key"]["key"] = $key; $this->vars["$key"]["value"] = $value; } } /** * This method provides support for repeating sections. * * PHP code: * * $t->section("planets"); * $t->add("planets.name", "Neptune"); * $t->add("planets.group", "Gas giant"); * $t->section("planets"); * $t->add("planets.name", "Saturn"); * $t->add("planets.group", "Gas giant"); * * HTML code * * ; *

Name: {name} - Group: {group}

* ; * * Output: * * Name: Neptune - Group: Gas giant * Name: Saturn - Group: Gas giant * * @param string $key * @return void */ public function section($key) { $c = $this->load(); $open = "/" . preg_quote('', '/') . "/si"; $close = "/" . preg_quote('', '/') . "/si"; $a = preg_split($open, $c); $c = $a[1]; $a = preg_split($close, $c); if (empty($this->blocks["$key"]) == true) { $iter = 0; } if (empty($this->blocks["$key"]) == false) { $iter = $this->iter; } $str = ''; $str = $a[0]; $str .= ''; $this->blocks["$key"]["content"] = $str; $this->iter = ($iter + 1); } /** * This method prints the HTML code. * Read https://stackoverflow.com/questions/6225351/how-to-minify-php-page-html-output, * that explains how to minify HTML code. * * @param string $mime * @return void */ public function output($mime) { switch ($mime) { // TODO: Does it work? case 'XML': header('Content-Type: text/xml'); break; case 'HTML': default: header('Content-Type: text/html'); break; } echo $this->sanitize($this->string()); } /** * This method also provides support for repeating sections. * The first parameter is an array constructed from the results of an SQL query. * The second parameter indicates the section with the name used in the template. * * PHP code: * * $db = new \netico\Bones\SQLite(); * $db->sql("SELECT [id], [title], [text] FROM pages ORDER BY [id] ASC;"); * $s->rs($db->data, "pages"); * * HTML code: * * *

{id}. {title}

*
{text}
* * * @param array $res * @param string $section * @return void */ public function rs($res, $section) { $columns = array(); foreach ($res as $r) { foreach ($r as $k => $v) { $columns[$k] = true; } } foreach ($res as $key => $v) { $this->section($section); foreach ($columns as $k => $v) { $this->add("$section.$k", $res["$key"]["$k"]); } } } private function load() { $t = $this->template; $fd = fopen("$t", "r"); $r = fread($fd, filesize("$t")); fclose($fd); return $r; } private function replace($key, $value, $content) { $pattern = '/{' . preg_quote($key, '/') . '}/'; return preg_replace($pattern, $value, $content); } private function string() { ksort($this->blocks); ksort($this->nb); $nca = array(); foreach ($this->nb as $k => $r) { $content = $this->blocks["$k"]["content"]; $nc = (string) ""; // Repetitions foreach ($r as $repetition => $ra) { $tmp = $content; // section foreach ($ra as $key => $ka) { $pcre = $ka["key"]; $value = $ka["value"]; if (empty($pcre) != true && empty($value) != true) { $tmp = $this->replace($pcre, $value, $tmp); } } unset($key); $nc .= $tmp; } unset($repetition); $nca["$k"]["content"] = $nc; } $text = $this->load(); foreach ($nca as $k => $v) { $content = $this->blocks["$k"]["content"]; $content = '/' . preg_quote($content, '/') . '/'; $nc = $v["content"]; $text = preg_replace($content, $nc, $text); } foreach ($this->vars as $k => $v) { $pcre = $v["key"]; $value = $v["value"]; $text = $this->replace($pcre, $value, $text); } return $text; } private function sanitize($buffer) { $search = array( '/\>[^\S ]+/s', // strip whitespaces after tags, except space '/[^\S ]+\/' // Remove HTML comments ); $replace = array( '>', '<', '\\1', '' ); $buffer = preg_replace($search, $replace, $buffer); return $buffer; } }