Location: PHPKode > projects > GnomePHP > peec-GnomePHP-b5a360b/gnomephp/mvc/View.php
<?php
namespace gnomephp\mvc;

use gnomephp\cache\CatchedCacheException;

use gnomephp\Gnomephp;

use gnomephp\Configuration,
	gnomephp\Url,
	gnomephp\message\Message;
	
	
/**
 * This is the view helper.
 * It contains logic for the views.
 * 
 * You have convenience methods like form generation, extending other views, importing views
 * and so fourth.
 * 
 * You can assign variables and render one or more specific views.
 * 
 * @author peec
 *
 */
class View{
	/**
	 * 
	 * Variables assigned to view.
	 * @var array
	 */
	protected $variables=array();
	
	
	/**
	 * Global variables  ( gets added in all extends and implements )
	 * @var array
	 */
	static public $globalVariables = array();
	
	
	
	protected $viewname;
	
	/**
	 * 
	 * Instance of Url helper.
	 * @var gnomephp\Url
	 */
	public $url;
	
	
	/**
	 * Holds the input class.
	 * @var gnomephp\input\Input
	 */
	public $input;	
	
	
	/**
	 * Holds the input class.
	 * @var gnomephp\helper\lang\Lang
	 */
	public $lang;
	
	/**
	 * Holds the input class.
	 * @var gnomephp\Session
	 */
	public $session;
	
	
	/**
	 * This will contain the view name the current view is extending.
	 * If extend() method is used $extendingView is set.
	 * @var string
	 */
	protected $extendingView = null;
	protected $extendingViewAlias = null;
	protected $extendingVars = array();
	
	/**
	 * This will contain the implementation map if there are some view outputs
	 * that is currently implementing this specific view.
	 * @var array
	 */
	protected $implementsMap = array();
	
	
	/**
	 * View cache queue.
	 * 
	 * @var array Array of gnomephp\cache\ViewCache objects.
	 */
	protected $cacheQueue = array();
	
	
	/**
	 * Constructs the view.
	 * 
	 * @param unknown_type $input
	 * @param unknown_type $lang
	 * @param unknown_type $session
	 */
	public function __construct($input=null, $lang=null, $session=null){
		$this->url = new Url;
		$this->input = $input;
		$this->lang = $lang;
		$this->session = $session;
	}

	
	public function addImplementation($alias, $content){
		$this->implementsMap[$alias] = $content;
	}
	
	public function getExtend($alias){
		if (isset($this->implementsMap[$alias])){
			return $this->implementsMap[$alias];
		}else{
			return null;
		}
	}
	
	
	/**
	 * 
	 * Assigns a variable to the view.
	 * @param string $var Variable name
	 * @param mixed $value Value of the variable, can be array, object, string boolean, etc... all types of variables is accepted.
	 */
	public function assign($var, $value){
		$this->variables[$var] = $value;
	}
	/**
	 * 
	 * Assigns a GLOBAL variable to all views.
	 * @param string $var Variable name
	 * @param mixed $value Value of the variable, can be array, object, string boolean, etc... all types of variables is accepted.
	 */
	public function assignGlobal($var, $value){
		View::$globalVariables[$var] = $value;
	}
	

	
	/**
	 * 
	 * Imports a view and creates a separate view for the specific view. Useful to use inside templates like:
	 * <? $view->import('header'); ?>
	 * 
	 * @param string $view The view name, Can be in folder too, like template/header, . This will load view/template/header.php
	 * @param array $vars Array of variables to assign to this specific view. Key should be the variable name, Value can be anything.
	 * @param string $suffix The file extension of the view file. Default is .php.
	 */
	public function import($view, $vars=array(), $returnContent=false,  $suffix='.php'){
		$v = new View($this->input, $this->lang, $this->session);
		foreach($vars as $k => $va){
			$v->assign($k, $va);
		}

		
		$v->render($view, $returnContent, $suffix);
	}
	
	
	/**
	 * Let's you extend another view with alias and optional vars.
	 * 
	 * @param string $view View file path
	 * @param string $alias Alias of the extend.
	 * @param array $vars Additional vars to pass to the other view.
	 * @return gnomephp\mvc\View
	 */
	public function extend($view, $alias=false, $vars=array()){
		$this->extendingView = $view;
		$this->extendingViewAlias = $alias ? $alias : $view;
		$this->extendingVars = $vars;
		return $this;
	}
	
	
	
	public function getRuntime(){
		return \gnomephp\mvc\Dispatcher::getRuntime();
	}
	
	
	/**
	 * 
	 * Gets a configuration value from a specific configuration file.
	 * 
	 * @param string $file The configuration file inside the config folder. NOTICE! Do not include .yml extension, this will be added automatically.
	 * @param string $key The key to load, if not provided, it will load all configurations in an array in the config file.
	 * @param string $suffix The suffix of the config file. Default is .yml.
	 */
	public function getConfig($file, $key=null, $suffix='.yml'){
		return \gnomephp\Configuration::get($file, $key, $suffix);
	}
	
	/**
	 * Gets message objects.
	 * @return array Array of MessageItem, check for what type of message with instanceof operator.
	 */
	public function getMessages(){
		return Message::getMessages();
	}
	
	
	public function getViewPath(){
		return  GNOME_APP_PATH.DIRECTORY_SEPARATOR.'view'.DIRECTORY_SEPARATOR;
	}
	
	/**
	 * Creates a new form object.
	 * You can create the form in the controller and assign it to a variable.
	 * If you choose to provide a callback closure as listener it should be defined as:
	 * function ($input){
	 * 		// Do something with the input of the form.
	 * }
	 * 
	 * 
	 * @param string $id Unique id for the form. Example: 'contact_form'
	 * @param string $action The action of where to post the variables.
	 * @param string $method The method to use for posting the form, default is 'post'
	 * @param closure $listener A callback function to use if form is posted. This is not obligatory, but it's a good way of checking if this specific form was posted.
	 */
	public function createForm($id, $action, $method='post', $listener=null){
		return new \gnomephp\form\Form($id, $this->url, $action, $method, $listener, $this->input);
	}
	
	
	/**
	 * Sends a specific view to the output.
	 * 
	 * Can also return the content if $returnContent is set to true.
	 * 
	 * 
	 * @param string $viewName The view name, Can be in folder too, like template/header, . This will load view/template/header.php
	 * @param boolean $returnContent If you want to return the rendered output instead of echoing it out, you may set this to true.
	 * @param string $suffix The file extension of the view file. Default is .php.
	 * @param boolean $skipViewPath If you want to skip the view directory of the application running, set this to true. Note that you then need to set absolute path in $viewName.
	 */
	public function render($viewName, $returnContent=false, $suffix='.php', $skipViewPath = false){
		
		
		// Assign variables to nice onces... 
		extract($this->variables);
		
		// Also extract global variables!
		extract(View::$globalVariables);
		
		
		$this->viewname = $viewName;
		if ($skipViewPath) $vpath = '';
		else $vpath = GNOME_APP_PATH.DIRECTORY_SEPARATOR.'view' . DIRECTORY_SEPARATOR;
		
		$view = $this;
		
		

		ob_start();
		
		// Include view.
		require $vpath.$viewName.($suffix ?: $suffix);
	
		$content = ob_get_contents();
		ob_end_clean();
		
		
		
		if ($this->extendingView !== null){
			$v = new View($this->input, $this->lang, $this->session);
			$v->addImplementation($this->extendingViewAlias, $content);
			foreach($this->extendingVars as $k => $va){
				$v->assign($k, $va);
			}
			$content =  $v->render($this->extendingView, true, $suffix, $skipViewPath);
		}
		// Ok Lets see if we want to generate some caches
		foreach($this->cacheQueue as $key => $viewcache){
			if ($viewcache->getSuffix() == $suffix && $viewcache->getViewName() == $viewName){
				// Write cache.
				$viewcache->put($content);
				unset($this->cacheQueue[$key]);
			}
		}
		
			
		
		
		
		if ($returnContent){
			return $content;
		}else{
			echo $content;
		}
		
		
				
	}	
	
	/**
	 * Tries to render a cached view.
	 * If the file was not cached, render() method will create a cached file.
	 * After next run cached file will be returned.
	 * 
	 * This method is usually the first call in the controllers method when you call render() in the portion of the method.
	 * 
	 * 
	 * @param string $viewFile Path to view file
	 * @param int $timeout Timeout, default is 3600 (1 hour cache) 
	 * @param boolean $returnContent If you want to return the content, notice if true - CatchedCacheException will not be thrown if got cache.
	 * @param string $suffix the suffix of the view file ( default : .php )
	 * @param boolean $skipViewPath If you want to skip the dir pattern of the application's view directory set this to true.
	 * @param mixed $salt If $salt === null the current activeRoute md5 hash will be used, this allows you to cache pages depending on the URL arguments and controller / method pattern. Default is null ( active router rule hash ). You can set this to your own salt if you want.
	 * @throws gnomephp\cache\CatchedCacheException if valid cache it throws Exception, this is automatically catched in the Dispatcher so you dont want to catch it.
	 */
	public function renderCache($viewFile, $timeout=3600, $returnContent=false, $suffix='.php', $skipViewPath = false, $salt = null){
		if ($salt===null){
			$salt = Dispatcher::getInstance()->activeRoute;
		}
		$obj = new \gnomephp\cache\ViewCache($viewFile, $suffix, GNOME_APP_PATH . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'view', $salt);
		
		$cachePath = $obj->getCacheFile();
		// Return cached content ? 
		if (file_exists($cachePath) && ($timeout == 0 || filemtime($cachePath) > time()-$timeout)){
			
			$c = $this->render($obj->getViewName(), $returnContent, $obj->getSuffix(), $skipViewPath);
			
			if (!$returnContent)throw new \gnomephp\cache\CatchedCacheException("Got cache");
			else return $c;
		}
		
		
		// Ok content is not cached, lets do some work.
		
		$path = dirname($cachePath);
		
		// try to make the dir
		if (!file_exists($path))mkdir($path);
		
		
		// Add it to the cache queue. $viewFile . $suffix
		$this->cacheQueue[] = $obj;
		
		
	}
	
	/**
	 * Returns a view cache object based on variables.
	 * 
	 * @param string $viewFile View file.
	 * @param string $salt Salt appendix, if null active router hash will be used.
	 * @param string $suffix Suffix 
	 * 
	 * @return gnomephp\cache\ViewCache
	 */
	public function getViewCache($viewFile, $salt = null, $suffix='.php'){
		if ($salt===null){
			$salt = Dispatcher::getInstance()->activeRoute;
		}
		$obj = new \gnomephp\cache\ViewCache($viewFile, $suffix, GNOME_APP_PATH . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'view', $salt);
		return $obj;
	}
	
	/**
	 * Deletes all the view cached files.
	 * 
	 * Notice, deletes all files in cache/view apps directory.
	 */
	public function deleteAllViewCache(){
    	$iterator = new \DirectoryIterator(GNOME_APP_PATH . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'view');
    	foreach ($iterator as $fileinfo) {
        	if ($fileinfo->isFile()) {
            	unlink($fileinfo->getPathname());
        	}
    	}
	}
	
}
Return current item: GnomePHP