8detect
7/3/2013 - 11:09 PM

Template.php

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>