2005-07-02 22:49:04 +00:00
|
|
|
<?php
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
2005-06-21 23:44:49 +00:00
|
|
|
// + $Id$
|
|
|
|
// +------------------------------------------------------------------+ //
|
|
|
|
// + Cake <https://developers.nextco.com/cake/> + //
|
|
|
|
// + Copyright: (c) 2005, Cake Authors/Developers + //
|
|
|
|
// + Author(s): Michal Tatarynowicz aka Pies <tatarynowicz@gmail.com> + //
|
|
|
|
// + Larry E. Masters aka PhpNut <nut@phpnut.com> + //
|
|
|
|
// + Kamil Dzielinski aka Brego <brego.dk@gmail.com> + //
|
|
|
|
// +------------------------------------------------------------------+ //
|
|
|
|
// + Licensed under The MIT License + //
|
|
|
|
// + Redistributions of files must retain the above copyright notice. + //
|
|
|
|
// + See: http://www.opensource.org/licenses/mit-license.php + //
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/**
|
2005-07-02 22:49:04 +00:00
|
|
|
* Purpose: View
|
|
|
|
*
|
2005-06-21 23:44:49 +00:00
|
|
|
*
|
|
|
|
* @filesource
|
|
|
|
* @author Cake Authors/Developers
|
|
|
|
* @copyright Copyright (c) 2005, Cake Authors/Developers
|
|
|
|
* @link https://developers.nextco.com/cake/wiki/Authors Authors/Developers
|
|
|
|
* @package cake
|
|
|
|
* @subpackage cake.libs
|
2005-07-02 22:49:04 +00:00
|
|
|
* @since Cake v 0.9.1
|
2005-06-21 23:44:49 +00:00
|
|
|
* @version $Revision$
|
|
|
|
* @modifiedby $LastChangedBy$
|
|
|
|
* @lastmodified $Date$
|
|
|
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
|
|
|
*/
|
|
|
|
|
2005-07-02 22:49:04 +00:00
|
|
|
uses('object');
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @package cake
|
|
|
|
* @subpackage cake.libs
|
|
|
|
* @since Cake v 0.9.1
|
|
|
|
*/
|
|
|
|
class View extends Object
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Name of the controller.
|
|
|
|
*
|
|
|
|
* @var unknown_type
|
|
|
|
* @access public
|
|
|
|
*/
|
|
|
|
var $name = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores the current URL (for links etc.)
|
|
|
|
*
|
|
|
|
* @var string Current URL
|
|
|
|
*/
|
|
|
|
var $here = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enter description here...
|
|
|
|
*
|
|
|
|
* @var unknown_type
|
|
|
|
* @access public
|
|
|
|
*/
|
|
|
|
var $parent = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Action to be performed.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
* @access public
|
|
|
|
*/
|
|
|
|
var $action = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An array of names of models the particular controller wants to use.
|
|
|
|
*
|
|
|
|
* @var mixed A single name as a string or a list of names as an array.
|
|
|
|
* @access protected
|
|
|
|
*/
|
|
|
|
var $uses = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An array of names of built-in helpers to include.
|
|
|
|
*
|
|
|
|
* @var mixed A single name as a string or a list of names as an array.
|
|
|
|
* @access protected
|
|
|
|
*/
|
|
|
|
var $helpers = array('html');
|
|
|
|
|
|
|
|
var $viewPath;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Variables for the view
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
* @access private
|
|
|
|
*/
|
|
|
|
var $_viewVars = array();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enter description here...
|
|
|
|
*
|
|
|
|
* @var boolean
|
|
|
|
* @access private
|
|
|
|
*/
|
|
|
|
var $pageTitle = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An array of model objects.
|
|
|
|
*
|
|
|
|
* @var array Array of model objects.
|
|
|
|
* @access public
|
|
|
|
*/
|
|
|
|
var $models = array();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enter description here...
|
|
|
|
*
|
|
|
|
* @var unknown_type
|
|
|
|
* @access public
|
|
|
|
*/
|
|
|
|
var $base = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enter description here...
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
* @access public
|
|
|
|
*/
|
|
|
|
var $layout = 'default';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enter description here...
|
|
|
|
*
|
|
|
|
* @var boolean
|
|
|
|
* @access public
|
|
|
|
*/
|
|
|
|
var $autoRender = true;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enter description here...
|
|
|
|
*
|
|
|
|
* @var boolean
|
|
|
|
* @access public
|
|
|
|
*/
|
|
|
|
var $autoLayout = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var $params;
|
|
|
|
var $hasRendered = null;
|
|
|
|
|
|
|
|
var $modelsLoaded = false;
|
2005-07-03 07:07:47 +00:00
|
|
|
|
|
|
|
function View(){
|
|
|
|
}
|
2005-07-02 22:49:04 +00:00
|
|
|
|
|
|
|
function getInstance()
|
|
|
|
{
|
|
|
|
static $instance;
|
|
|
|
if (!isset($instance))
|
|
|
|
{
|
2005-07-03 07:07:47 +00:00
|
|
|
$instance[0] =& new View();
|
2005-07-02 22:49:04 +00:00
|
|
|
}
|
|
|
|
return $instance[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Displays a flash message. A flash message is feedback to the user that displays after editing actions, among other things.
|
|
|
|
*
|
|
|
|
* @param string $message Text to display to the user
|
|
|
|
* @param string $url URL fragment
|
|
|
|
* @param int $time Display time, in seconds
|
|
|
|
*/
|
|
|
|
function flash($message, $url, $time=1)
|
|
|
|
{
|
|
|
|
$this->autoRender = false;
|
|
|
|
$this->autoLayout = false;
|
|
|
|
|
|
|
|
$this->set('url', $this->base.$url);
|
|
|
|
$this->set('message', $message);
|
|
|
|
$this->set('time', $time);
|
|
|
|
|
|
|
|
$this->render(null,false,VIEWS.'layouts'.DS.'flash.thtml');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Render view for given action and layout. If $file is given, that is used
|
|
|
|
* for a view filename (e.g. customFunkyView.thtml).
|
|
|
|
*
|
|
|
|
* @param string $action Name of action to render for
|
|
|
|
* @param string $layout
|
|
|
|
* @param string $file Custom filename for view
|
|
|
|
*/
|
|
|
|
function render($action=null, $layout=null, $file=null)
|
|
|
|
{
|
2005-07-03 07:07:47 +00:00
|
|
|
|
|
|
|
|
2005-07-02 22:49:04 +00:00
|
|
|
if ($this->modelsLoaded!==true)
|
|
|
|
{
|
|
|
|
foreach ($this->models as $modelName => $model)
|
|
|
|
{
|
|
|
|
$this->$modelName = $model;
|
|
|
|
}
|
|
|
|
}
|
2005-07-03 07:07:47 +00:00
|
|
|
// What is reason for these being the same?
|
2005-07-02 22:49:04 +00:00
|
|
|
if (isset($this->hasRendered) && $this->hasRendered)
|
|
|
|
{
|
2005-07-03 07:07:47 +00:00
|
|
|
//echo "<pre>";
|
|
|
|
//print_r($this);
|
|
|
|
//echo "</pre>";
|
2005-07-02 22:49:04 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$this->hasRendered = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->autoRender = false;
|
|
|
|
|
|
|
|
if (!$action)
|
|
|
|
{
|
|
|
|
$action = $this->action;
|
|
|
|
}
|
|
|
|
if ($layout)
|
|
|
|
{
|
|
|
|
$this->setLayout($layout);
|
|
|
|
}
|
|
|
|
|
|
|
|
$viewFileName = $file? $file: $this->_getViewFileName($action);
|
|
|
|
|
|
|
|
if (!is_file($viewFileName))
|
|
|
|
{
|
|
|
|
if (strtolower(get_class($this)) == 'template')
|
|
|
|
{
|
|
|
|
return array('action' => $action, 'layout' => $layout, 'viewFn' => $viewFileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// check to see if the missing view is due to a custom missingAction
|
|
|
|
if (strpos($action, 'missingAction') !== false)
|
|
|
|
{
|
|
|
|
$errorAction = 'missingAction';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$errorAction = 'missingView';
|
|
|
|
}
|
|
|
|
|
|
|
|
// check for controller-level view handler
|
|
|
|
foreach(array($this->name, 'errors') as $viewDir)
|
|
|
|
{
|
|
|
|
$missingViewFileName = VIEWS.$viewDir.DS.Inflector::underscore($errorAction).'.thtml';
|
|
|
|
$missingViewExists = is_file($missingViewFileName);
|
|
|
|
if ($missingViewExists)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strpos($action, 'missingView') === false)
|
|
|
|
{
|
|
|
|
$controller = $this;
|
|
|
|
$controller->missingView = $viewFileName;
|
|
|
|
$controller->action = $action;
|
|
|
|
call_user_func_array(array(&$controller, 'missingView'), empty($params['pass'])? null: $params['pass']);
|
|
|
|
$isFatal = isset($this->isFatal) ? $this->isFatal : false;
|
|
|
|
if (!$isFatal)
|
|
|
|
{
|
|
|
|
$viewFileName = $missingViewFileName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$missingViewExists = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$missingViewExists || $isFatal)
|
|
|
|
{
|
|
|
|
// app/view/errors/missing_view.thtml view is missing!
|
|
|
|
if (DEBUG)
|
|
|
|
{
|
|
|
|
trigger_error(sprintf(ERROR_NO_VIEW, $action, $viewFileName), E_USER_ERROR);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$this->error('404', 'Not found', sprintf(ERROR_404, '', "missing view \"{$action}\""));
|
|
|
|
}
|
|
|
|
|
|
|
|
die();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($viewFileName && !$this->hasRendered)
|
|
|
|
{
|
|
|
|
$out = $this->_render($viewFileName, $this->_viewVars, 0);
|
|
|
|
if ($out !== false)
|
|
|
|
{
|
|
|
|
if ($this->layout && $this->autoLayout)
|
|
|
|
{
|
|
|
|
$out = $this->renderLayout($out);
|
|
|
|
}
|
|
|
|
|
|
|
|
print $out;
|
|
|
|
$this->hasRendered = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$out = $this->_render($viewFileName, $this->_viewVars, false);
|
|
|
|
trigger_error(sprintf(ERROR_IN_VIEW, $viewFileName, $out), E_USER_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders a piece of PHP with provided parameters and returns HTML, XML, or any other string.
|
|
|
|
*
|
|
|
|
* @param string $name Name of template file
|
|
|
|
* @param array $params Array of data for rendered view
|
|
|
|
* @return string Rendered output
|
|
|
|
*/
|
|
|
|
function renderElement($name, $params=array())
|
|
|
|
{
|
|
|
|
$fn = ELEMENTS.$name.'.thtml';
|
|
|
|
|
|
|
|
if (!file_exists($fn))
|
|
|
|
{
|
|
|
|
return "(Error rendering {$name})";
|
|
|
|
}
|
|
|
|
return $this->_render($fn, array_merge($this->_viewVars, $params));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders a layout. Returns output from _render(). Returns false on error.
|
|
|
|
*
|
|
|
|
* @param string $content_for_layout Content to render in a view
|
|
|
|
* @return string Rendered output
|
|
|
|
*/
|
|
|
|
function renderLayout($content_for_layout)
|
|
|
|
{
|
|
|
|
$layout_fn = $this->_getLayoutFileName();
|
|
|
|
|
|
|
|
$data_for_layout = array_merge($this->_viewVars, array(
|
|
|
|
'title_for_layout'=>$this->pageTitle !== false? $this->pageTitle: Inflector::humanize($this->viewPath),
|
|
|
|
'content_for_layout'=>$content_for_layout));
|
|
|
|
|
|
|
|
if (is_file($layout_fn))
|
|
|
|
{
|
|
|
|
$out = $this->_render($layout_fn, $data_for_layout);
|
|
|
|
|
|
|
|
if ($out === false)
|
|
|
|
{
|
|
|
|
$out = $this->_render($layout_fn, $data_for_layout, false);
|
|
|
|
trigger_error(sprintf(ERROR_IN_LAYOUT, $layout_fn, $out), E_USER_ERROR);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return $out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
trigger_error(sprintf(ERROR_NO_LAYOUT, $this->layout, $layout_fn), E_USER_ERROR);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Choose the layout to be used when rendering.
|
|
|
|
*
|
|
|
|
* @param string $layout
|
|
|
|
*/
|
|
|
|
function setLayout($layout)
|
|
|
|
{
|
|
|
|
$this->layout = $layout;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Displays an error page to the user. Uses layouts/error.html to render the page.
|
|
|
|
*
|
|
|
|
* @param int $code Error code (for instance: 404)
|
|
|
|
* @param string $name Name of the error (for instance: Not Found)
|
|
|
|
* @param string $message Error message
|
|
|
|
*/
|
|
|
|
function error ($code, $name, $message)
|
|
|
|
{
|
|
|
|
header ("HTTP/1.0 {$code} {$name}");
|
|
|
|
print ($this->_render(VIEWS.'layouts/error.thtml', array('code'=>$code,'name'=>$name,'message'=>$message)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function missingController()
|
|
|
|
{
|
|
|
|
//We are simulating action call below, this is not a filename!
|
|
|
|
$this->render('../errors/missingController');
|
|
|
|
}
|
|
|
|
|
|
|
|
function missingAction()
|
|
|
|
{
|
|
|
|
//We are simulating action call below, this is not a filename!
|
|
|
|
$this->render('../errors/missingAction');
|
|
|
|
}
|
|
|
|
|
|
|
|
function missingView()
|
|
|
|
{
|
|
|
|
//We are simulating action call below, this is not a filename!
|
|
|
|
$this->render('../errors/missingView');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* Private methods.
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns filename of given action's template file (.thtml) as a string. CamelCased action names will be under_scored! This means that you can have LongActionNames that refer to long_action_names.thtml views.
|
|
|
|
*
|
|
|
|
* @param string $action Controller action to find template filename for
|
|
|
|
* @return string Template filename
|
|
|
|
*/
|
|
|
|
function _getViewFileName($action)
|
|
|
|
{
|
|
|
|
$action = Inflector::underscore($action);
|
|
|
|
$viewFileName = VIEWS.$this->viewPath.DS."{$action}.thtml";
|
|
|
|
$viewPath = explode(DS, $viewFileName);
|
|
|
|
|
|
|
|
$i = array_search('..', $viewPath);
|
|
|
|
|
|
|
|
unset($viewPath[$i-1]);
|
|
|
|
unset($viewPath[$i]);
|
|
|
|
|
|
|
|
return '/'.implode('/', $viewPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns layout filename for this template as a string.
|
|
|
|
*
|
|
|
|
* @return string Filename for layout file (.thtml).
|
|
|
|
*/
|
|
|
|
function _getLayoutFileName()
|
|
|
|
{
|
|
|
|
return VIEWS."layouts".DS."{$this->layout}.thtml";
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders and returns output for given view filename with its
|
|
|
|
* array of data.
|
|
|
|
*
|
|
|
|
* @param string $___viewFn Filename of the view
|
|
|
|
* @param array $___data_for_view Data to include in rendered view
|
|
|
|
* @param boolean $___play_safe If set to false, the include() of the $__viewFn is done without suppressing output of errors
|
|
|
|
* @return string Rendered output
|
|
|
|
*/
|
|
|
|
function _render($___viewFn, $___data_for_view, $___play_safe = true)
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Fetching helpers
|
|
|
|
*/
|
|
|
|
if ($this->helpers !== false)
|
|
|
|
{
|
|
|
|
foreach ($this->helpers as $helper)
|
|
|
|
{
|
|
|
|
$helperFn = LIBS.'helpers'.DS.Inflector::underscore($helper).'.php';
|
|
|
|
$helperCn = ucfirst($helper).'Helper';
|
|
|
|
if (is_file($helperFn))
|
|
|
|
{
|
|
|
|
require_once $helperFn;
|
|
|
|
if(class_exists($helperCn)===true);
|
|
|
|
{
|
|
|
|
${$helper} = new $helperCn;
|
|
|
|
${$helper}->base = $this->base;
|
|
|
|
${$helper}->here = $this->here;
|
|
|
|
${$helper}->params = $this->params;
|
|
|
|
${$helper}->action = $this->action;
|
|
|
|
${$helper}->data = $this->data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extract($___data_for_view, EXTR_SKIP); # load all view variables
|
|
|
|
/**
|
|
|
|
* Local template variables.
|
|
|
|
*/
|
|
|
|
$BASE = $this->base;
|
|
|
|
$params = &$this->params;
|
|
|
|
$page_title = $this->pageTitle;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Start caching output (eval outputs directly so we need to cache).
|
|
|
|
*/
|
|
|
|
ob_start();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Include the template.
|
|
|
|
*/
|
|
|
|
$___play_safe? @include($___viewFn): include($___viewFn);
|
|
|
|
|
|
|
|
$out = ob_get_clean();
|
|
|
|
|
|
|
|
return $out;
|
|
|
|
}
|
2005-06-21 23:44:49 +00:00
|
|
|
|
2005-07-02 22:49:04 +00:00
|
|
|
}
|
2005-06-21 23:44:49 +00:00
|
|
|
|
|
|
|
?>
|