scaffold.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: scaffold.php 8276 2009-08-03 17:38:40Z mark_story $ */
00003 /**
00004  * Scaffold.
00005  *
00006  * Automatic forms and actions generation for rapid web application development.
00007  *
00008  * PHP versions 4 and 5
00009  *
00010  * CakePHP(tm) :  Rapid Development Framework (http://www.cakephp.org)
00011  * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
00012  *
00013  * Licensed under The MIT License
00014  * Redistributions of files must retain the above copyright notice.
00015  *
00016  * @filesource
00017  * @copyright     Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
00018  * @link          http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00019  * @package       cake
00020  * @subpackage    cake.cake.libs.controller
00021  * @since         Cake v 0.10.0.1076
00022  * @version       $Revision: 8276 $
00023  * @modifiedby    $LastChangedBy: mark_story $
00024  * @lastmodified  $Date: 2009-08-03 13:38:40 -0400 (Mon, 03 Aug 2009) $
00025  * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
00026  */
00027 /**
00028  * Scaffolding is a set of automatic views, forms and controllers for starting web development work faster.
00029  *
00030  * Scaffold inspects your database tables, and making educated guesses, sets up a
00031  * number of pages for each of your Models. These pages have data forms that work,
00032  * and afford the web developer an early look at the data, and the possibility to over-ride
00033  * scaffolded actions with custom-made ones.
00034  *
00035  * @package       cake
00036  * @subpackage    cake.cake.libs.controller
00037  */
00038 class Scaffold extends Object {
00039 /**
00040  * Controller object
00041  *
00042  * @var Controller
00043  * @access public
00044  */
00045     var $controller = null;
00046 /**
00047  * Name of the controller to scaffold
00048  *
00049  * @var string
00050  * @access public
00051  */
00052     var $name = null;
00053 /**
00054  * Action to be performed.
00055  *
00056  * @var string
00057  * @access public
00058  */
00059     var $action = null;
00060 /**
00061  * Name of current model this view context is attached to
00062  *
00063  * @var string
00064  * @access public
00065  */
00066     var $model = null;
00067 /**
00068  * Path to View.
00069  *
00070  * @var string
00071  * @access public
00072  */
00073     var $viewPath;
00074 /**
00075  * Path parts for creating links in views.
00076  *
00077  * @var string Base URL
00078  * @access public
00079  */
00080     var $base = null;
00081 /**
00082  * Name of layout to use with this View.
00083  *
00084  * @var string
00085  * @access public
00086  */
00087     var $layout = 'default';
00088 /**
00089  * Array of parameter data
00090  *
00091  * @var array
00092  * @access public
00093  */
00094     var $params;
00095 /**
00096  * File extension. Defaults to Cake's template ".ctp".
00097  *
00098  * @var array
00099  * @access public
00100  */
00101     var $ext = '.ctp';
00102 /**
00103  * Sub-directory for this view file.
00104  *
00105  * @var string
00106  * @access public
00107  */
00108     var $subDir = null;
00109 /**
00110  * Plugin name.
00111  *
00112  * @var string
00113  * @access public
00114  */
00115     var $plugin = null;
00116 /**
00117  * List of variables to collect from the associated controller
00118  *
00119  * @var array
00120  * @access private
00121  */
00122     var $__passedVars = array('action', 'base', 'webroot', 'layout', 'name', 'viewPath', 'ext', 'params', 'data', 'plugin', 'cacheAction');
00123 /**
00124  * Title HTML element for current scaffolded view
00125  *
00126  * @var string
00127  * @access public
00128  */
00129     var $scaffoldTitle = null;
00130 /**
00131  * Construct and set up given controller with given parameters.
00132  *
00133  * @param string $controller_class Name of controller
00134  * @param array $params Parameters for scaffolding
00135  */
00136     function __construct(&$controller, $params) {
00137         $this->controller =& $controller;
00138 
00139         $count = count($this->__passedVars);
00140         for ($j = 0; $j < $count; $j++) {
00141             $var = $this->__passedVars[$j];
00142             $this->{$var} = $controller->{$var};
00143         }
00144 
00145         $this->redirect = array('action'=> 'index');
00146 
00147         $this->modelClass = $controller->modelClass;
00148         $this->modelKey = $controller->modelKey;
00149 
00150         if (!is_object($this->controller->{$this->modelClass})) {
00151             return $this->cakeError('missingModel', array(array('className' => $this->modelClass, 'webroot' => '', 'base' => $controller->base)));
00152         }
00153 
00154         $this->ScaffoldModel =& $this->controller->{$this->modelClass};
00155         $this->scaffoldTitle = Inflector::humanize($this->viewPath);
00156         $this->scaffoldActions = $controller->scaffold;
00157         $this->controller->pageTitle = __('Scaffold :: ', true) . Inflector::humanize($this->action) . ' :: ' . $this->scaffoldTitle;
00158 
00159         $modelClass = $this->controller->modelClass;
00160         $primaryKey = $this->ScaffoldModel->primaryKey;
00161         $displayField = $this->ScaffoldModel->displayField;
00162         $singularVar = Inflector::variable($modelClass);
00163         $pluralVar = Inflector::variable($this->controller->name);
00164         $singularHumanName = Inflector::humanize(Inflector::underscore($modelClass));
00165         $pluralHumanName = Inflector::humanize(Inflector::underscore($this->controller->name));
00166         $scaffoldFields = array_keys($this->ScaffoldModel->schema());
00167         $associations = $this->__associations();
00168 
00169         $this->controller->set(compact('modelClass', 'primaryKey', 'displayField', 'singularVar', 'pluralVar',
00170             'singularHumanName', 'pluralHumanName', 'scaffoldFields', 'associations'));
00171 
00172         if ($this->controller->view && $this->controller->view !== 'Theme') {
00173             $this->controller->view = 'scaffold';
00174         }
00175         $this->__scaffold($params);
00176     }
00177 /**
00178  * Outputs the content of a scaffold method passing it through the Controller::afterFilter()
00179  *
00180  * @return void
00181  * @access protected
00182  */
00183     function _output() {
00184         $this->controller->afterFilter();
00185         echo($this->controller->output);
00186     }
00187 /**
00188  * Renders a view action of scaffolded model.
00189  *
00190  * @param array $params Parameters for scaffolding
00191  * @return mixed A rendered view of a row from Models database table
00192  * @access private
00193  */
00194     function __scaffoldView($params) {
00195         if ($this->controller->_beforeScaffold('view')) {
00196 
00197             if (isset($params['pass'][0])) {
00198                 $this->ScaffoldModel->id = $params['pass'][0];
00199             } elseif (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
00200                 $this->controller->Session->setFlash(sprintf(__("No id set for %s::view()", true), Inflector::humanize($this->modelKey)));
00201                 $this->controller->redirect($this->redirect);
00202             } else {
00203                 return $this->controller->flash(sprintf(__("No id set for %s::view()", true), Inflector::humanize($this->modelKey)),
00204                                                                         '/' . Inflector::underscore($this->controller->viewPath));
00205             }
00206             $this->ScaffoldModel->recursive = 1;
00207             $this->controller->data = $this->ScaffoldModel->read();
00208             $this->controller->set(Inflector::variable($this->controller->modelClass), $this->controller->data);
00209             $this->controller->render($this->action, $this->layout);
00210             $this->_output();
00211         } elseif ($this->controller->_scaffoldError('view') === false) {
00212             return $this->__scaffoldError();
00213         }
00214     }
00215 /**
00216  * Renders index action of scaffolded model.
00217  *
00218  * @param array $params Parameters for scaffolding
00219  * @return mixed A rendered view listing rows from Models database table
00220  * @access private
00221  */
00222     function __scaffoldIndex($params) {
00223         if ($this->controller->_beforeScaffold('index')) {
00224             $this->ScaffoldModel->recursive = 0;
00225             $this->controller->set(Inflector::variable($this->controller->name), $this->controller->paginate());
00226             $this->controller->render($this->action, $this->layout);
00227             $this->_output();
00228         } elseif ($this->controller->_scaffoldError('index') === false) {
00229             return $this->__scaffoldError();
00230         }
00231     }
00232 /**
00233  * Renders an add or edit action for scaffolded model.
00234  *
00235  * @param string $action Action (add or edit)
00236  * @return mixed A rendered view with a form to edit or add a record in the Models database table
00237  * @access private
00238  */
00239     function __scaffoldForm($action = 'edit') {
00240         $this->controller->render($action, $this->layout);
00241         $this->_output();
00242     }
00243 /**
00244  * Saves or updates the scaffolded model.
00245  *
00246  * @param array $params Parameters for scaffolding
00247  * @param string $action add or edt
00248  * @return mixed Success on save/update, add/edit form if data is empty or error if save or update fails
00249  * @access private
00250  */
00251     function __scaffoldSave($params = array(), $action = 'edit') {
00252         $formAction = 'edit';
00253         $success = __('updated', true);
00254         if ($action === 'add') {
00255             $formAction = 'add';
00256             $success = __('saved', true);
00257         }
00258 
00259         if ($this->controller->_beforeScaffold($action)) {
00260             if ($action == 'edit') {
00261                 if (isset($params['pass'][0])) {
00262                     $this->ScaffoldModel->id = $params['pass'][0];
00263                 }
00264 
00265                 if (!$this->ScaffoldModel->exists()) {
00266                     if (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
00267                         $this->controller->Session->setFlash(sprintf(__("Invalid id for %s::edit()", true), Inflector::humanize($this->modelKey)));
00268                         $this->controller->redirect($this->redirect);
00269                     } else {
00270                         return $this->controller->flash(sprintf(__("Invalid id for %s::edit()", true), Inflector::humanize($this->modelKey)), $this->redirect);
00271                     }
00272                 }
00273             }
00274 
00275             if (!empty($this->controller->data)) {
00276                 if ($action == 'create') {
00277                     $this->ScaffoldModel->create();
00278                 }
00279 
00280                 if ($this->ScaffoldModel->save($this->controller->data)) {
00281                     if ($this->controller->_afterScaffoldSave($action)) {
00282                         if (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
00283                             $this->controller->Session->setFlash(sprintf(__('The %1$s has been %2$s', true), Inflector::humanize($this->modelClass), $success));
00284                             $this->controller->redirect($this->redirect);
00285                         } else {
00286                             return $this->controller->flash(sprintf(__('The %1$s has been %2$s', true), Inflector::humanize($this->modelClass), $success), $this->redirect);
00287                         }
00288                     } else {
00289                         return $this->controller->_afterScaffoldSaveError($action);
00290                     }
00291                 } else {
00292                     if (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
00293                         $this->controller->Session->setFlash(__('Please correct errors below.', true));
00294                     }
00295                 }
00296             }
00297 
00298             if (empty($this->controller->data)) {
00299                 if ($this->ScaffoldModel->id) {
00300                     $this->controller->data = $this->ScaffoldModel->read();
00301                 } else {
00302                     $this->controller->data = $this->ScaffoldModel->create();
00303                 }
00304             }
00305 
00306             foreach ($this->ScaffoldModel->belongsTo as $assocName => $assocData) {
00307                 $varName = Inflector::variable(Inflector::pluralize(preg_replace('/(?:_id)$/', '', $assocData['foreignKey'])));
00308                 $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list'));
00309             }
00310             foreach ($this->ScaffoldModel->hasAndBelongsToMany as $assocName => $assocData) {
00311                 $varName = Inflector::variable(Inflector::pluralize($assocName));
00312                 $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list'));
00313             }
00314 
00315             return $this->__scaffoldForm($formAction);
00316         } elseif ($this->controller->_scaffoldError($action) === false) {
00317             return $this->__scaffoldError();
00318         }
00319     }
00320 /**
00321  * Performs a delete on given scaffolded Model.
00322  *
00323  * @param array $params Parameters for scaffolding
00324  * @return mixed Success on delete, error if delete fails
00325  * @access private
00326  */
00327     function __scaffoldDelete($params = array()) {
00328         if ($this->controller->_beforeScaffold('delete')) {
00329             if (isset($params['pass'][0])) {
00330                 $id = $params['pass'][0];
00331             } elseif (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
00332                 $this->controller->Session->setFlash(sprintf(__("No id set for %s::delete()", true), Inflector::humanize($this->modelKey)));
00333                 $this->controller->redirect($this->redirect);
00334             } else {
00335                 return $this->controller->flash(sprintf(__("No id set for %s::delete()", true), Inflector::humanize($this->modelKey)),
00336                                                                     '/' . Inflector::underscore($this->controller->viewPath));
00337             }
00338 
00339             if ($this->ScaffoldModel->del($id)) {
00340                 if (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
00341                     $this->controller->Session->setFlash(sprintf(__('The %1$s with id: %2$d has been deleted.', true), Inflector::humanize($this->modelClass), $id));
00342                     $this->controller->redirect($this->redirect);
00343                 } else {
00344                     return $this->controller->flash(sprintf(__('The %1$s with id: %2$d has been deleted.', true), Inflector::humanize($this->modelClass), $id), '/' . $this->viewPath);
00345                 }
00346             } else {
00347                 if (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
00348                     $this->controller->Session->setFlash(sprintf(__('There was an error deleting the %1$s with id: %2$d', true), Inflector::humanize($this->modelClass), $id));
00349                     $this->controller->redirect($this->redirect);
00350                 } else {
00351                     return $this->controller->flash(sprintf(__('There was an error deleting the %1$s with id: %2$d', true), Inflector::humanize($this->modelClass), $id), '/' . $this->viewPath);
00352                 }
00353             }
00354         } elseif ($this->controller->_scaffoldError('delete') === false) {
00355             return $this->__scaffoldError();
00356         }
00357     }
00358 /**
00359  * Show a scaffold error
00360  *
00361  * @return mixed A rendered view showing the error
00362  * @access private
00363  */
00364     function __scaffoldError() {
00365         return $this->controller->render('error', $this->layout);
00366         $this->_output();
00367     }
00368 /**
00369  * When methods are now present in a controller
00370  * scaffoldView is used to call default Scaffold methods if:
00371  * <code>
00372  * var $scaffold;
00373  * </code>
00374  * is placed in the controller's class definition.
00375  *
00376  * @param array $params Parameters for scaffolding
00377  * @return mixed A rendered view of scaffold action, or showing the error
00378  * @access private
00379  */
00380     function __scaffold($params) {
00381         $db =& ConnectionManager::getDataSource($this->ScaffoldModel->useDbConfig);
00382         $admin = Configure::read('Routing.admin');
00383 
00384         if (isset($db)) {
00385             if (empty($this->scaffoldActions)) {
00386                 $this->scaffoldActions = array('index', 'list', 'view', 'add', 'create', 'edit', 'update', 'delete');
00387             } elseif (!empty($admin) && $this->scaffoldActions === $admin) {
00388                 $this->scaffoldActions = array($admin .'_index', $admin .'_list', $admin .'_view', $admin .'_add', $admin .'_create', $admin .'_edit', $admin .'_update', $admin .'_delete');
00389             }
00390 
00391             if (in_array($params['action'], $this->scaffoldActions)) {
00392                 if (!empty($admin)) {
00393                     $params['action'] = str_replace($admin . '_', '', $params['action']);
00394                 }
00395                 switch ($params['action']) {
00396                     case 'index':
00397                         $this->__scaffoldIndex($params);
00398                     break;
00399                     case 'view':
00400                         $this->__scaffoldView($params);
00401                     break;
00402                     case 'list':
00403                         $this->__scaffoldIndex($params);
00404                     break;
00405                     case 'add':
00406                         $this->__scaffoldSave($params, 'add');
00407                     break;
00408                     case 'edit':
00409                         $this->__scaffoldSave($params, 'edit');
00410                     break;
00411                     case 'create':
00412                         $this->__scaffoldSave($params, 'add');
00413                     break;
00414                     case 'update':
00415                         $this->__scaffoldSave($params, 'edit');
00416                     break;
00417                     case 'delete':
00418                         $this->__scaffoldDelete($params);
00419                     break;
00420                 }
00421             } else {
00422                 return $this->cakeError('missingAction', array(array('className' => $this->controller->name . "Controller",
00423                                                                                         'base' => $this->controller->base,
00424                                                                                         'action' => $this->action,
00425                                                                                         'webroot' => $this->controller->webroot)));
00426             }
00427         } else {
00428             return $this->cakeError('missingDatabase', array(array('webroot' => $this->controller->webroot)));
00429         }
00430     }
00431 /**
00432  * Returns associations for controllers models.
00433  *
00434  * @return array Associations for model
00435  * @access private
00436  */
00437     function __associations() {
00438         $keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
00439         $associations = array();
00440 
00441         foreach ($keys as $key => $type) {
00442             foreach ($this->ScaffoldModel->{$type} as $assocKey => $assocData) {
00443                 $associations[$type][$assocKey]['primaryKey'] = $this->ScaffoldModel->{$assocKey}->primaryKey;
00444                 $associations[$type][$assocKey]['displayField'] = $this->ScaffoldModel->{$assocKey}->displayField;
00445                 $associations[$type][$assocKey]['foreignKey'] = $assocData['foreignKey'];
00446                 $associations[$type][$assocKey]['controller'] = Inflector::pluralize(Inflector::underscore($assocData['className']));
00447             }
00448         }
00449         return $associations;
00450     }
00451 }
00452 
00453 /**
00454  * Scaffold View.
00455  *
00456  * @package       cake
00457  * @subpackage    cake.cake.libs.controller
00458 */
00459 if (!class_exists('ThemeView')) {
00460     App::import('View', 'Theme');
00461 }
00462 
00463 class ScaffoldView extends ThemeView {
00464 /**
00465  * Override _getViewFileName
00466  *
00467  * @return string action
00468  * @access protected
00469  */
00470     function _getViewFileName($name = null) {
00471         if ($name === null) {
00472             $name = $this->action;
00473         }
00474         $name = Inflector::underscore($name);
00475         $admin = Configure::read('Routing.admin');
00476 
00477         if (!empty($admin) && strpos($name, $admin . '_') !== false) {
00478             $name = substr($name, strlen($admin) + 1);
00479         }
00480 
00481         if ($name === 'add') {
00482             $name = 'edit';
00483         }
00484 
00485         $scaffoldAction = 'scaffold.' . $name;
00486 
00487         if (!is_null($this->subDir)) {
00488             $subDir = strtolower($this->subDir) . DS;
00489         } else {
00490             $subDir = null;
00491         }
00492 
00493         $names[] = $this->viewPath . DS . $subDir . $scaffoldAction;
00494         $names[] = 'scaffolds' . DS . $subDir . $name;
00495 
00496         $paths = $this->_paths($this->plugin);
00497 
00498         $exts = array($this->ext, '.ctp', '.thtml');
00499         foreach ($paths as $path) {
00500             foreach ($names as $name) {
00501                 foreach ($exts as $ext) {
00502                     if (file_exists($path . $name . $ext)) {
00503                         return $path . $name . $ext;
00504                     }
00505                 }
00506             }
00507         }
00508 
00509         if ($name === 'scaffolds' . DS . $subDir . 'error') {
00510             return LIBS . 'view' . DS . 'errors' . DS . 'scaffold_error.ctp';
00511         }
00512 
00513         return $this->_missingView($paths[0] . $name . $this->ext, 'missingView');
00514     }
00515 }
00516 ?>

Generated on Sun Nov 22 00:30:53 2009 for CakePHP 1.2.x.x (v1.2.4.8284) by doxygen 1.4.7