Merging changes from Kamil's sandbox.

Beginning refactoring to bring current trunk to a usable release.


git-svn-id: https://svn.cakephp.org/repo/trunk/cake@301 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
phpnut 2005-07-02 22:49:04 +00:00
parent 4089572c5f
commit 75cce3f107
3 changed files with 658 additions and 1221 deletions

View file

@ -37,7 +37,7 @@
/**
* Enter description here...
*/
uses('model', 'template', 'inflector', 'folder');
uses('model', 'inflector', 'folder', 'view');
/**
* Enter description here...
@ -47,7 +47,7 @@ uses('model', 'template', 'inflector', 'folder');
* @since Cake v 0.2.9
*
*/
class Controller extends Template
class Controller extends Object
{
/**
* Name of the controller.
@ -96,6 +96,66 @@ class Controller extends Template
*/
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;
/**
* Constructor.
*
@ -113,7 +173,7 @@ class Controller extends Template
}
$this->name = strtolower($r[1]);
$this->viewpath = Inflector::underscore($r[1]);
$this->viewPath = Inflector::underscore($r[1]);
$model_class = Inflector::singularize($this->name);
@ -122,7 +182,7 @@ class Controller extends Template
if (class_exists($model_class) && ($this->uses === false))
{
$this->$model_class = new $model_class();
$this->models[$model_class] = new $model_class();
}
elseif ($this->uses)
{
@ -139,7 +199,7 @@ class Controller extends Template
if (class_exists($model_class))
{
$this->$model_name = new $model_class (false);
$this->models[$model_name] = new $model_class(false);
}
else
{
@ -149,6 +209,97 @@ class Controller extends Template
}
}
/**
* Redirects to given $url, after turning off $this->autoRender.
*
* @param unknown_type $url
*/
function redirect ($url)
{
$this->autoRender = false;
header ('Location: '.$this->base.$url);
}
/**
* Saves a variable to use inside a template.
*
* @param mixed $one A string or an array of data.
* @param string $two Value in case $one is a string (which then works as the key), otherwise unused.
* @return unknown
*/
function set($one, $two=null)
{
return $this->_setArray(is_array($one)? $one: array($one=>$two));
}
/**
* Enter description here...
*
* @param unknown_type $action
*/
function setAction ($action)
{
$this->action = $action;
$args = func_get_args();
call_user_func_array(array(&$this, $action), $args);
}
/**
* Returns number of errors in a submitted FORM.
*
* @return int Number of errors
*/
function validate ()
{
$args = func_get_args();
$errors = call_user_func_array(array(&$this, 'validateErrors'), $args);
return count($errors);
}
/**
* Validates a FORM according to the rules set up in the Model.
*
* @return int Number of errors
*/
function validateErrors ()
{
$objects = func_get_args();
if (!count($objects)) return false;
$errors = array();
foreach ($objects as $object)
{
$errors = array_merge($errors, $object->invalidFields($object->data));
}
return $this->validationErrors = (count($errors)? $errors: false);
}
function render($action=null, $layout=null, $file=null)
{
$v = new View();
$v->_viewVars = $this->_viewVars;
$v->action = $this->action;
$v->autoLayout = $this->autoLayout;
$v->autoRender = $this->autoRender;
$v->base = $this->base;
$v->helpers = $this->helpers;
$v->here = $this->here;
$v->layout = $this->layout;
$v->models = $this->models;
$v->name = $this->name;
$v->pageTitle = $this->pageTitle;
$v->parent = $this->parent;
$v->viewPath = $this->viewPath;
$v->params = $this->params;
$v->data = $this->data;
//$this->view = $v;
return $v->render($action, $layout, $file);
}
function missingController()
{
//We are simulating action call below, this is not a filename!
@ -167,41 +318,43 @@ class Controller extends Template
$this->render('../errors/missingView');
}
// /**
// * 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)));
// }
/**
* Redirects to given $url, after turning off $this->autoRender.
* Sets data for this view. Will set title if the key "title" is in given $data array.
*
* @param unknown_type $url
* @param array $data Array of
*/
function redirect ($url)
function _setArray($data)
{
$this->autoRender = false;
header ('Location: '.$this->base.$url);
foreach ($data as $name => $value)
{
if ($name == 'title')
$this->_setTitle($value);
else
$this->_viewVars[$name] = $value;
}
}
/**
* Enter description here...
* Set the title element of the page.
*
* @param unknown_type $action
* @param string $pageTitle Text for the title
*/
function setAction ($action)
function _setTitle($pageTitle)
{
$this->action = $action;
$args = func_get_args();
call_user_func_array(array(&$this, $action), $args);
}
/**
* 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)));
$this->pageTitle = $pageTitle;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,5 @@
<?php//////////////////////////////////////////////////////////////////////////
<?php
//////////////////////////////////////////////////////////////////////////
// + $Id$
// +------------------------------------------------------------------+ //
// + Cake <https://developers.nextco.com/cake/> + //
@ -13,8 +14,8 @@
//////////////////////////////////////////////////////////////////////////
/**
* Purpose: Dispatcher
* Dispatches the request, creating aproppriate models and controllers.
* Purpose: View
*
*
* @filesource
* @author Cake Authors/Developers
@ -22,13 +23,483 @@
* @link https://developers.nextco.com/cake/wiki/Authors Authors/Developers
* @package cake
* @subpackage cake.libs
* @since Cake v 0.2.9
* @since Cake v 0.9.1
* @version $Revision$
* @modifiedby $LastChangedBy$
* @lastmodified $Date$
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*/
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;
function getInstance()
{
static $instance;
if (!isset($instance))
{
$instance = array(new View());
}
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)
{
if ($this->modelsLoaded!==true)
{
foreach ($this->models as $modelName => $model)
{
$this->$modelName = $model;
}
}
if (isset($this->hasRendered) && $this->hasRendered)
{
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;
}
}
?>