Template.php
<?php
namespace PHN\View
{
class Template {
protected $controller;
public $vars=array(); /// Holds all the template variables
public $themeDir;
public $cacheDir;
function __construct(&$cfg,$controller) {
$this->themeDir = $cfg['theme_dir'];
$this->cacheDir = $cfg['theme_cache_dir'];
$this->controller=$controller;
$this->setTheme( isset($cfg['theme_default']) ? $cfg['theme_default'] : 'default');
$this->setGZip(isset($cfg['theme_gzip'])?$cfg['theme_gzip']:false);
}
function setTheme($theme){
$this->themeDefault =$theme;
$this->controller->cfg['theme_active_url']=$this->controller->cfg['theme_url'].'/'.$this->themeDefault ;
$this->activeThemeDir = $this->themeDir . '/' . $this->themeDefault . '/' . 'tpl';
chdir($this->activeThemeDir);
}
function setGZip($flag){
$this->gzipOutput = $flag;
}
/**
* Set a template variable.
*/
function assign($name, $value=null) {
if (is_string($name)) $this->vars[$name] = $value;
else{
$this->vars = array_merge($this->vars,$name);
}
}
function assignRef($name, &$value) {
$this->vars[$name] = &$value;
}
/**
* Open, parse, and return the template file.
* @param type $name as the partial path of file
* @param type $vars nếu không muốn dùng var từ assign thì truyền vào còn không để null
* @param type $cache
* @return type
*/
function fetch($name, $vars = null, $cache = null) {
$file = $this->activeThemeDir . '/' . $name;
if ($vars)
$_vars = &$vars;
else
$_vars = &$this->vars;
extract($_vars); // Extract the vars to local namespace
ob_start(); // Start output buffering
include($file); // Include the file
return ob_get_clean() ;//return buffer and clean up
}
/**
*
* @param type $name
* @param type $vars nếu không muốn dùng var từ assign thì truyền vào còn không để null
* @param type $cache
*/
function display($name, $vars = null, $cache = null ) {
$file = $this->activeThemeDir . '/' . $name;
if ($vars)
$_vars = &$vars;
else
$_vars = &$this->vars;
extract($_vars); // Extract the vars to local namespace
$GLOBALS['tpl'] =&$this;//for accessing inside template file
$GLOBALS['tpl_vars'] =&$_vars;
$GLOBALS['tpl_vars_cache'] =array();
include($file); // Include the file
//
//if ($gzip || $this->gzipOutput) ob_end_clean(); //flush the buffer to prevent error message caused stop to display
}
}
/**
* An extension to Template that provides automatic caching of
* template contents.
*/
class CachedTemplate extends Template {
var $cache_id;
var $expire;
var $cached;
/**
* Constructor.
*
* @param $cache_id string unique cache identifier
* @param $expire int number of seconds the cache will live
*/
function CachedTemplate($cache_id = null, $expire = 900) {
$this->Template();
$this->cache_id = $cache_id ? 'cache/' . md5($cache_id) : $cache_id;
$this->expire = $expire;
}
/**
* Test to see whether the currently loaded cache_id has a valid
* corrosponding cache file.
*/
function is_cached() {
if ($this->cached)
return true;
// Passed a cache_id?
if (!$this->cache_id)
return false;
// Cache file exists?
if (!file_exists($this->cache_id))
return false;
// Can get the time of the file?
if (!($mtime = filemtime($this->cache_id)))
return false;
// Cache expired?
if (($mtime + $this->expire) < time()) {
@unlink($this->cache_id);
return false;
} else {
/**
* Cache the results of this is_cached() call. Why? So
* we don't have to double the overhead for each template.
* If we didn't cache, it would be hitting the file system
* twice as much (file_exists() & filemtime() [twice each]).
*/
$this->cached = true;
return true;
}
}
/**
* This function returns a cached copy of a template (if it exists),
* otherwise, it parses it as normal and caches the content.
*
* @param $file string the template file
*/
function fetch_cache($file) {
if ($this->is_cached()) {
$fp = @fopen($this->cache_id, 'r');
$contents = fread($fp, filesize($this->cache_id));
fclose($fp);
return $contents;
} else {
$contents = $this->fetch($file);
// Write the cache
if ($fp = @fopen($this->cache_id, 'w')) {
fwrite($fp, $contents);
fclose($fp);
} else {
die('Unable to write cache.');
}
return $contents;
}
}
}
}//end namespace
// <editor-fold defaultstate="collapsed" desc="GLOBAL ROOT LOCALE FUNCTION ">
namespace {
/**
* change textdomain
* @param string $domain
*/
function _dom($domain=null){
global $App;
//set the default if no param
if (!$domain) textdomain($App->cfg['textdomain']);
else textdomain($App->cfg['textdomain'][$domain]);
}
function _t($msg) {
echo _($msg);
}
//
/**
* Echo plural translated string
* @example: _n('%d item','%d items',$n)
* @param type $msg1 case N=1
* @param type $msg2 case N=2
* @param type $n
*/
function _n($msg1, $msg2, $n) {
printf(ngettext($msg1, $msg2, $n),$n);
}
/**
* Return plural translated string
* @example: __n('%d item','%d items',$n)
* @param type $msg1 case N=1
* @param type $msg2 case N=2
* @param type $n
*/
function __n($msg1, $msg2, $n) {
return sprintf(ngettext($msg1, $msg2, $n),$n);
}
/**
* echo translated string with format % parameter
* maximum 4 args
* @example: _f('%d item has %d' subitem,$n,$m)
* @example: _f('%d ... %d ... %d',$n,$m,$l)
* @param string $msg with % place holder inside
* @param type $s1
* @param type $s2
* @param type $s3
* @param type $s4
*/
function _f($msg,$s1=null,$s2=null,$s3=null,$s4=null){
printf(_($msg),$s1,$s2,$s3,$s4);
}
/**
* return translated string with format % parameter
* @param type $msg
* @param type $s1
* @param type $s2
* @param type $s3
* @param type $s4
* @return type
*/
function __f($msg,$s1=null,$s2=null,$s3=null,$s4=null){
return sprintf(_($msg),$s1,$s2,$s3,$s4);
}
/**
* return locale datetime
* @param int $time
* @param str $type ='l' long, 'm' medium, 's' short ( number only )
*/
function __date($value='now',$locale='local', $datetype='s',$timezone=null) {
if ($datetype == 'l') $datetype = IntlDateFormatter::LONG;
elseif ($datetype == 'm') $datetype = IntlDateFormatter::MEDIUM;
elseif ($datetype == 's') $datetype = IntlDateFormatter::SHORT;
if (!$timezone) $timezone = date_default_timezone_get ();
$d = new IntlDateFormatter($locale, $datetype, $timetype, $timezone);
if ($value == 'now') $value = time();
return $d->format($value);
}
/**
* echo locale datetime
* @param int $time
* @param str $type ='l' long, 'm' medium, 's' short ( number only )
*/
function _date($value='now',$locale='local', $datetype='s',$timezone=null) {
echo __date($value,$locale, $datetype,$timezone);
}
/**
* echo locale time format
* @param type $time
*/
function _time($value,$locale='local' ,$long = false) {
echo __time($value,$long);
}
/**
* return locale time
* @param type $time
* @param type $long
*/
function __time($value, $locale='local' ,$long = false){
$number = new NumberFormatter($locale, NumberFormatter::DURATION);
if ($long) $number->setTextAttribute (NumberFormatter::DEFAULT_RULESET, '%with-words');
return $number->format($value);
}
/**
* echo locale number
* @param type $value
* @param type $loc
* @param type $dec
* @param type $speak
*/
function _num($value,$loc='local' ,$dec=2) {
echo __num($value,$loc,$dec);
}
/**
* return locale number
* @staticvar type $cache
* @param type $value
* @param type $loc
* @param type $dec
* @return type
*/
function __num($value,$loc='local' ,$dec=2) {
static $cache;
if (isset($cache) && isset($cache[$loc.$dec])) $number = &$cache[$loc.$dec];
else {
$number = new \NumberFormatter ($loc, \NumberFormatter::DECIMAL);
$number->setAttribute(\NumberFormatter::FRACTION_DIGITS, $dec);
$cache[$loc.$dec]=&$number;
}
return $number->format($value);
}
/**
* echo locale spellout number
* @param type $value
* @param type $loc
*/
function _numspell($value,$loc='local'){
echo __numspell($value,$loc);
}
/**
* return locale spellout number
* @param type $value
* @param type $loc
* @return type
*/
function __numspell($value,$loc='local'){
$number = new NumberFormatter($loc, NumberFormatter::SPELLOUT);
$number->setTextAttribute(NumberFormatter::DEFAULT_RULESET, '%financial');
return $number->format($value);
}
/**
* echo format locale money
* @param type $value
* @param type $loc
* @param type $dec
* @param type $speak
*/
function _money($value,$loc='local' ,$dec=2,$speak = false) {
echo __money($value,$loc,$dec,$speak);
}
/**
* return format locale money
* @staticvar type $cache
* @param type $value
* @param type $loc
* @param type $dec
* @param type $default_currency
* @param type $speak
* @return type
*/
function __money($value,$loc='local' ,$dec=0,$default_currency='USD',$speak = false) {
static $cache;
if (isset($cache) && isset($cache[$loc.$dec])) $number = &$cache[$loc.$dec];
else {
$number = new \NumberFormatter ($loc, \NumberFormatter::CURRENCY);
$number->setAttribute(\NumberFormatter::FRACTION_DIGITS, $dec);
$cache[$loc.$dec]=&$number;
}
return $number->formatCurrency($value,$default_currency);
}
/**
* return locale percent
* @staticvar type $cache
* @param type $value
* @param type $loc
* @param type $pattern
* @return type
*/
function __percent($value,$loc='local',$pattern='@@'){
static $cache;
if (isset($cache) && isset($cache[$loc.$pattern])) $number = &$cache[$loc.$pattern];
else {
$number = new \NumberFormatter ($loc, \NumberFormatter::PERCENT);
$number->setPattern($pattern);
$cache[$loc.$pattern]=&$number;
}
return $number->format($value);
}
/**
* return locale percent
* @staticvar type $cache
* @param type $value
* @param type $loc
* @param type $pattern
* @return type
*/
function _percent($value,$loc='local',$pattern='@@'){
echo _gpercent($value,$loc,$pattern);
}
/**
* echo variable thru its assigned name
* @global type $tpl
* @global type $tpl_vars
* @param type $name
* @param type $def
*/
function _v($name,$def=null){
global $tpl,$tpl_vars,$tpl_vars_cache;
if (isset($tpl_vars[$name]) ) echo $tpl_vars[$name];
elseif ($def !== null) echo $def;
}
/**
* return variable thru its assigned name
* @global type $tpl
* @global type $tpl_vars
* @param type $name
* @param type $def
* @return type
*/
function __v($name,$def=null){
global $tpl,$tpl_vars;
if (isset($tpl_vars[$name]) ) return $tpl_vars[$name];
elseif ($def !== null) return $def;
}
/**
* return object/array's member variable
* dành cho $name có dạng obj.x , obj.x.y value tùy loại có thể là array hoac object
* nếu $name chỉ thuần túy là obj thì dùng _v để nhanh hơn
* Get mixed type variable
* return var/array/obj
*/
function __x($name,$def=null){
global $tpl,$tpl_vars,$tpl_vars_cache;
if (isset($tpl_vars_cache[$name])) return $tpl_vars_cache[$name];
$names = explode('.',$name);
if (count($names) ==1) {
if (isset($tpl_vars[$name])) return $tpl_vars_cache[$name]=&$tpl_vars[$name];
}
elseif (isset($tpl_vars[$names[0]]) )
{
if (is_array($tpl_vars[$names[0]]) && isset($tpl_vars[$names[0]][$names[1]]))
{
if (count($names) == 2) return $tpl_vars_cache[$name]=&$tpl_vars[$names[0]][$names[1]];
else {
$v = &$tpl_vars[$names[0]][$names[1]];
for ($i = 2; $i < count($names) ; $i++ )
if (isset($v[$names[$i]])) $v = &$v[$names[$i]];
else {
if ($def !== null) return $tpl_vars_cache[$name]=$def;
return null;
}
return $tpl_vars_cache[$name]=&$v;
}
}
elseif (is_object($tpl_vars[$names[0]]) && isset($tpl_vars[$names[0]]->$names[1]))
{
if (count($names) == 2) return $tpl_vars_cache[$name]=&$tpl_vars[$names[0]]->$names[1];
else {
$v = &$tpl_vars[$names[0]]->$names[1];
for ($i = 2; $i < count($names) ; $i++ )
if (isset($v->$names[$i])) $v = &$v->$names[$i];
else {
if ($def !== null) return $tpl_vars_cache[$name]=$def;
return null;
}
return $tpl_vars_cache[$name]=&$v;
}
}
elseif ($def !== null) return $tpl_vars_cache[$name]=$def;
}
elseif ($def !== null) return $tpl_vars_cache[$name]=$def;
}
/**
* echo mixed type variable
* echo x=obj/array/obj
* @param type $name
* @param type $def
*/
function _x($name,$def=null){
echo __x($name,$def);
}
// <editor-fold desc="###For Page Infomation ( title, meta , url... )">
/**
* echo title from param $title or from CFG['title']
* @global type $App
* @param type $title
*/
function _title($title=null){
global $App;
$cfg = &$App->cfg;
if (empty($title)) $title = $cfg['title'];
if (!empty($title)) echo urlencode ($title);
}
function _html($key=null){
global $App;
if (!$key || !isset($App->cfg['html'])) return;
$cfg = &$App->cfg['html'];
echo isset($cfg[$key] ) ? $cfg[$key] : '';
}
function _url($key=null){
global $App;
if (!$key) {
//echo current url
$url = ( !isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] != 'on' ) ? 'http://' . $_SERVER["SERVER_NAME"] : 'https://' . $_SERVER["SERVER_NAME"];
$url .= ( $_SERVER["SERVER_PORT"] !== '80' ) ? ":" . $_SERVER["SERVER_PORT"] : "";
$url .= $_SERVER["REQUEST_URI"];
echo $url;
return;
}
echo isset($App->cfg[$key . '_url'] ) ? $App->cfg[$key . '_url'] : '';
}
// </editor-fold>
/**
* echo css from param or form config['cfg']
* @global type $App
* @param type $css
* @return type
*/
function _css($css=null){
global $App;
if (!$css && !isset($App->cfg['html'])) return;
if (empty($css) && isset($App->cfg['html'])) $css = &$App->cfg['html']['css'];
if (empty($css)) return;
if (!is_array($css)) echo '<link href="'.$css.'"'." rel=\"stylesheet\" type=\"text/css\" />\r\n";
else{
foreach ($css as $key => $value ){
$acss = &$value;
if (!is_array($acss)) echo '<link href="'.$acss.'"'." rel=\"stylesheet\" type=\"text/css\" />\r\n";
else{ //as key=>value
$id="";
$src="";
if (isset($acss['id'])) $id= ' id="'.$acss['id'].'"';
if (isset($acss['src'])) $src= ' href="'.$acss['src'].'"';
if (isset($acss['code'])) echo "<style$id>\r\n".$acss['code'] . "\r\n</style>\r\n";
else {
echo "<link$id$src rel=\"stylesheet\" type=\"text/css\" />\r\n";
}
}
}
}
}
function _css_unset($key)
{
global $App;
if (!isset($App->cfg['html']) && !$App->cfg['html']['css']) return;
//$css = &$App->cfg['html']['css'];
unset($App->cfg['html']['css'][$key]);
}
function _css_append($css)
{
global $App;
if (!isset($App->cfg['html']) ) return;
if (!isset($App->cfg['html']['css'])) $App->cfg['html']['css']=array();
$App->cfg['html']['css'] = array_merge($App->cfg['html']['css'],$css);
}
function _css_prepend($css)
{
global $App;
if (!isset($App->cfg['html']) ) return;
if (!isset($App->cfg['html']['css'])) $App->cfg['html']['css']=array();
$App->cfg['html']['css'] = array_merge($css,$App->cfg['html']['css']);
}
function _js_unset($js)
{
global $App;
if (!isset($App->cfg['html']) && !$App->cfg['html']['js']) return;
//$css = &$App->cfg['html']['css'];
unset($App->cfg['html']['js'][$js]);
}
function _js_append($js)
{
global $App;
if (!isset($App->cfg['html']) ) return;
if (!isset($App->cfg['html']['js'])) $App->cfg['html']['js']=array();
$App->cfg['html']['js'] = array_merge($App->cfg['html']['js'],$js);
}
function _js_prepend($js)
{
global $App;
if (!isset($App->cfg['html']) ) return;
if (!isset($App->cfg['html']['js'])) $App->cfg['html']['js']=array();
$App->cfg['html']['js'] = array_merge($js,$App->cfg['html']['js']);
}
/**
* echo _js array
* @global type $App
* @param type $js
* @param type $foot=null , neu $foot=true thi chi chon js co thuoc tinh $foot=true
* @return no
*/
function _js($js=null,$foot=null){
global $App;
if (!$js && !isset($App->cfg['html'])) return;
if (empty($js) && isset($App->cfg['html'])) $js = &$App->cfg['html']['js'];
if (empty($js)) return;
if (!is_array($js) && !$foot) echo '<script src="'.$js.'"'." ></script>\r\n";
else{
foreach ($js as $key => $value ){
$ajs = &$value;
if (!is_array($ajs) && !$foot) echo '<script src="'.$ajs.'"'." ></script>\r\n";
else{ //as key=>value
if ( (!$foot && isset($ajs['foot'])) || ($foot && !isset($ajs['foot'])) ) continue;
$id="";
$src="";
if (isset($ajs['id'])) $id= ' id="'.$ajs['id'].'"';
if (isset($ajs['src'])) $src= ' src="'.$ajs['src'].'"';
echo "<script$id$src>";
if (isset($ajs['code'])) echo $ajs['code'] . "\r\n</script>\r\n";
else echo "</script>\r\n";
}
}
}
}
/**
* ex: var = <?php _json(); ?>
* @param mixed $var
*/
function _json($var){
echo '"' . json_encode($var). '"';
}
/**
*
* @global type $App
*/
function _isbot(){
global $App;
return ($App->controller->getUA() == \PHN\Core\Controller::UA_BOT);
}
/**
*
* @global type $App
*/
function _istablet(){
global $App;
return ($App->controller->getUA() == \PHN\Core\Controller::UA_TABLET);
}
/**
*
* @global type $App
*/
function _ismobile(){
global $App;
return ($App->controller->getUA() == \PHN\Core\Controller::UA_MOBILE);
}
function _user($key){
global $App;
$user = &$App->controller->user;
echo isset($user[$key]) ? $user[$key] : '';
}
function _acl($key){
global $App;
//under construction
//return true/false
}
}
// </editor-fold>