pictcode / lib / Cake / Controller / Scaffold.php @ 2df93201
履歴 | 表示 | アノテート | ダウンロード (13.584 KB)
| 1 | 635eef61 | spyder1211 | <?php
|
|---|---|---|---|
| 2 | /**
|
||
| 3 | * Scaffold.
|
||
| 4 | *
|
||
| 5 | * Automatic forms and actions generation for rapid web application development.
|
||
| 6 | *
|
||
| 7 | * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
|
||
| 8 | * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||
| 9 | *
|
||
| 10 | * Licensed under The MIT License
|
||
| 11 | * For full copyright and license information, please see the LICENSE.txt
|
||
| 12 | * Redistributions of files must retain the above copyright notice.
|
||
| 13 | *
|
||
| 14 | * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
|
||
| 15 | * @link http://cakephp.org CakePHP(tm) Project
|
||
| 16 | * @package Cake.Controller
|
||
| 17 | * @since Cake v 0.10.0.1076
|
||
| 18 | * @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||
| 19 | */
|
||
| 20 | |||
| 21 | /**
|
||
| 22 | * Scaffolding is a set of automatic actions for starting web development work faster.
|
||
| 23 | *
|
||
| 24 | * Scaffold inspects your database tables, and making educated guesses, sets up a
|
||
| 25 | * number of pages for each of your Models. These pages have data forms that work,
|
||
| 26 | * and afford the web developer an early look at the data, and the possibility to over-ride
|
||
| 27 | * scaffolded actions with custom-made ones.
|
||
| 28 | *
|
||
| 29 | * @package Cake.Controller
|
||
| 30 | * @deprecated 3.0.0 Dynamic scaffolding will be removed and replaced in 3.0
|
||
| 31 | */
|
||
| 32 | class Scaffold { |
||
| 33 | |||
| 34 | /**
|
||
| 35 | * Controller object
|
||
| 36 | *
|
||
| 37 | * @var Controller
|
||
| 38 | */
|
||
| 39 | public $controller = null; |
||
| 40 | |||
| 41 | /**
|
||
| 42 | * Name of the controller to scaffold
|
||
| 43 | *
|
||
| 44 | * @var string
|
||
| 45 | */
|
||
| 46 | public $name = null; |
||
| 47 | |||
| 48 | /**
|
||
| 49 | * Name of current model this view context is attached to
|
||
| 50 | *
|
||
| 51 | * @var string
|
||
| 52 | */
|
||
| 53 | public $model = null; |
||
| 54 | |||
| 55 | /**
|
||
| 56 | * Path to View.
|
||
| 57 | *
|
||
| 58 | * @var string
|
||
| 59 | */
|
||
| 60 | public $viewPath; |
||
| 61 | |||
| 62 | /**
|
||
| 63 | * Name of layout to use with this View.
|
||
| 64 | *
|
||
| 65 | * @var string
|
||
| 66 | */
|
||
| 67 | public $layout = 'default'; |
||
| 68 | |||
| 69 | /**
|
||
| 70 | * Request object
|
||
| 71 | *
|
||
| 72 | * @var CakeRequest
|
||
| 73 | */
|
||
| 74 | public $request; |
||
| 75 | |||
| 76 | /**
|
||
| 77 | * Valid session.
|
||
| 78 | *
|
||
| 79 | * @var bool
|
||
| 80 | */
|
||
| 81 | protected $_validSession = null; |
||
| 82 | |||
| 83 | /**
|
||
| 84 | * List of variables to collect from the associated controller
|
||
| 85 | *
|
||
| 86 | * @var array
|
||
| 87 | */
|
||
| 88 | protected $_passedVars = array( |
||
| 89 | 'layout', 'name', 'viewPath', 'request' |
||
| 90 | ); |
||
| 91 | |||
| 92 | /**
|
||
| 93 | * Title HTML element for current scaffolded view
|
||
| 94 | *
|
||
| 95 | * @var string
|
||
| 96 | */
|
||
| 97 | public $scaffoldTitle = null; |
||
| 98 | |||
| 99 | /**
|
||
| 100 | * Construct and set up given controller with given parameters.
|
||
| 101 | *
|
||
| 102 | * @param Controller $controller Controller to scaffold
|
||
| 103 | * @param CakeRequest $request Request parameters.
|
||
| 104 | * @throws MissingModelException
|
||
| 105 | */
|
||
| 106 | public function __construct(Controller $controller, CakeRequest $request) { |
||
| 107 | $this->controller = $controller; |
||
| 108 | |||
| 109 | $count = count($this->_passedVars); |
||
| 110 | for ($j = 0; $j < $count; $j++) { |
||
| 111 | $var = $this->_passedVars[$j]; |
||
| 112 | $this->{$var} = $controller->{$var}; |
||
| 113 | } |
||
| 114 | |||
| 115 | $this->redirect = array('action' => 'index'); |
||
| 116 | |||
| 117 | $this->modelClass = $controller->modelClass; |
||
| 118 | $this->modelKey = $controller->modelKey; |
||
| 119 | |||
| 120 | if (!is_object($this->controller->{$this->modelClass})) { |
||
| 121 | throw new MissingModelException($this->modelClass); |
||
| 122 | } |
||
| 123 | |||
| 124 | $this->ScaffoldModel = $this->controller->{$this->modelClass}; |
||
| 125 | $this->scaffoldTitle = Inflector::humanize(Inflector::underscore($this->viewPath)); |
||
| 126 | $this->scaffoldActions = $controller->scaffold; |
||
| 127 | $title = __d('cake', 'Scaffold :: ') . Inflector::humanize($request->action) . ' :: ' . $this->scaffoldTitle; |
||
| 128 | $modelClass = $this->controller->modelClass; |
||
| 129 | $primaryKey = $this->ScaffoldModel->primaryKey; |
||
| 130 | $displayField = $this->ScaffoldModel->displayField; |
||
| 131 | $singularVar = Inflector::variable($modelClass); |
||
| 132 | $pluralVar = Inflector::variable($this->controller->name); |
||
| 133 | $singularHumanName = Inflector::humanize(Inflector::underscore($modelClass)); |
||
| 134 | $pluralHumanName = Inflector::humanize(Inflector::underscore($this->controller->name)); |
||
| 135 | $scaffoldFields = array_keys($this->ScaffoldModel->schema()); |
||
| 136 | $associations = $this->_associations(); |
||
| 137 | |||
| 138 | $this->controller->set(compact( |
||
| 139 | 'modelClass', 'primaryKey', 'displayField', 'singularVar', 'pluralVar', |
||
| 140 | 'singularHumanName', 'pluralHumanName', 'scaffoldFields', 'associations' |
||
| 141 | )); |
||
| 142 | $this->controller->set('title_for_layout', $title); |
||
| 143 | |||
| 144 | if ($this->controller->viewClass) { |
||
| 145 | $this->controller->viewClass = 'Scaffold'; |
||
| 146 | } |
||
| 147 | $this->_validSession = (
|
||
| 148 | isset($this->controller->Session) && |
||
| 149 | $this->controller->Session->valid() && |
||
| 150 | isset($this->controller->Flash) |
||
| 151 | ); |
||
| 152 | $this->_scaffold($request); |
||
| 153 | } |
||
| 154 | |||
| 155 | /**
|
||
| 156 | * Renders a view action of scaffolded model.
|
||
| 157 | *
|
||
| 158 | * @param CakeRequest $request Request Object for scaffolding
|
||
| 159 | * @return mixed A rendered view of a row from Models database table
|
||
| 160 | * @throws NotFoundException
|
||
| 161 | */
|
||
| 162 | protected function _scaffoldView(CakeRequest $request) { |
||
| 163 | if ($this->controller->beforeScaffold('view')) { |
||
| 164 | if (isset($request->params['pass'][0])) { |
||
| 165 | $this->ScaffoldModel->id = $request->params['pass'][0]; |
||
| 166 | } |
||
| 167 | if (!$this->ScaffoldModel->exists()) { |
||
| 168 | throw new NotFoundException(__d('cake', 'Invalid %s', Inflector::humanize($this->modelKey))); |
||
| 169 | } |
||
| 170 | $this->ScaffoldModel->recursive = 1; |
||
| 171 | $this->controller->request->data = $this->ScaffoldModel->read(); |
||
| 172 | $this->controller->set(
|
||
| 173 | Inflector::variable($this->controller->modelClass), $this->request->data |
||
| 174 | ); |
||
| 175 | $this->controller->render($this->request['action'], $this->layout); |
||
| 176 | } elseif ($this->controller->scaffoldError('view') === false) { |
||
| 177 | return $this->_scaffoldError(); |
||
| 178 | } |
||
| 179 | } |
||
| 180 | |||
| 181 | /**
|
||
| 182 | * Renders index action of scaffolded model.
|
||
| 183 | *
|
||
| 184 | * @param array $params Parameters for scaffolding
|
||
| 185 | * @return mixed A rendered view listing rows from Models database table
|
||
| 186 | */
|
||
| 187 | protected function _scaffoldIndex($params) { |
||
| 188 | if ($this->controller->beforeScaffold('index')) { |
||
| 189 | $this->ScaffoldModel->recursive = 0; |
||
| 190 | $this->controller->set(
|
||
| 191 | Inflector::variable($this->controller->name), $this->controller->paginate() |
||
| 192 | ); |
||
| 193 | $this->controller->render($this->request['action'], $this->layout); |
||
| 194 | } elseif ($this->controller->scaffoldError('index') === false) { |
||
| 195 | return $this->_scaffoldError(); |
||
| 196 | } |
||
| 197 | } |
||
| 198 | |||
| 199 | /**
|
||
| 200 | * Renders an add or edit action for scaffolded model.
|
||
| 201 | *
|
||
| 202 | * @param string $action Action (add or edit)
|
||
| 203 | * @return void
|
||
| 204 | */
|
||
| 205 | protected function _scaffoldForm($action = 'edit') { |
||
| 206 | $this->controller->viewVars['scaffoldFields'] = array_merge( |
||
| 207 | $this->controller->viewVars['scaffoldFields'], |
||
| 208 | array_keys($this->ScaffoldModel->hasAndBelongsToMany) |
||
| 209 | ); |
||
| 210 | $this->controller->render($action, $this->layout); |
||
| 211 | } |
||
| 212 | |||
| 213 | /**
|
||
| 214 | * Saves or updates the scaffolded model.
|
||
| 215 | *
|
||
| 216 | * @param CakeRequest $request Request Object for scaffolding
|
||
| 217 | * @param string $action add or edit
|
||
| 218 | * @return mixed Success on save/update, add/edit form if data is empty or error if save or update fails
|
||
| 219 | * @throws NotFoundException
|
||
| 220 | */
|
||
| 221 | protected function _scaffoldSave(CakeRequest $request, $action = 'edit') { |
||
| 222 | $formAction = 'edit'; |
||
| 223 | $success = __d('cake', 'updated'); |
||
| 224 | if ($action === 'add') { |
||
| 225 | $formAction = 'add'; |
||
| 226 | $success = __d('cake', 'saved'); |
||
| 227 | } |
||
| 228 | |||
| 229 | if ($this->controller->beforeScaffold($action)) { |
||
| 230 | if ($action === 'edit') { |
||
| 231 | if (isset($request->params['pass'][0])) { |
||
| 232 | $this->ScaffoldModel->id = $request['pass'][0]; |
||
| 233 | } |
||
| 234 | if (!$this->ScaffoldModel->exists()) { |
||
| 235 | throw new NotFoundException(__d('cake', 'Invalid %s', Inflector::humanize($this->modelKey))); |
||
| 236 | } |
||
| 237 | } |
||
| 238 | |||
| 239 | if (!empty($request->data)) { |
||
| 240 | if ($action === 'create') { |
||
| 241 | $this->ScaffoldModel->create(); |
||
| 242 | } |
||
| 243 | |||
| 244 | if ($this->ScaffoldModel->save($request->data)) { |
||
| 245 | if ($this->controller->afterScaffoldSave($action)) { |
||
| 246 | $message = __d('cake', |
||
| 247 | 'The %1$s has been %2$s',
|
||
| 248 | Inflector::humanize($this->modelKey), |
||
| 249 | $success
|
||
| 250 | ); |
||
| 251 | return $this->_sendMessage($message, 'success'); |
||
| 252 | } |
||
| 253 | return $this->controller->afterScaffoldSaveError($action); |
||
| 254 | } |
||
| 255 | if ($this->_validSession) { |
||
| 256 | $this->controller->Flash->set(__d('cake', 'Please correct errors below.')); |
||
| 257 | } |
||
| 258 | } |
||
| 259 | |||
| 260 | if (empty($request->data)) { |
||
| 261 | if ($this->ScaffoldModel->id) { |
||
| 262 | $this->controller->data = $request->data = $this->ScaffoldModel->read(); |
||
| 263 | } else {
|
||
| 264 | $this->controller->data = $request->data = $this->ScaffoldModel->create(); |
||
| 265 | } |
||
| 266 | } |
||
| 267 | |||
| 268 | foreach ($this->ScaffoldModel->belongsTo as $assocName => $assocData) { |
||
| 269 | $varName = Inflector::variable(Inflector::pluralize( |
||
| 270 | preg_replace('/(?:_id)$/', '', $assocData['foreignKey']) |
||
| 271 | )); |
||
| 272 | $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list')); |
||
| 273 | } |
||
| 274 | foreach ($this->ScaffoldModel->hasAndBelongsToMany as $assocName => $assocData) { |
||
| 275 | $varName = Inflector::variable(Inflector::pluralize($assocName)); |
||
| 276 | $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list')); |
||
| 277 | } |
||
| 278 | |||
| 279 | return $this->_scaffoldForm($formAction); |
||
| 280 | } elseif ($this->controller->scaffoldError($action) === false) { |
||
| 281 | return $this->_scaffoldError(); |
||
| 282 | } |
||
| 283 | } |
||
| 284 | |||
| 285 | /**
|
||
| 286 | * Performs a delete on given scaffolded Model.
|
||
| 287 | *
|
||
| 288 | * @param CakeRequest $request Request for scaffolding
|
||
| 289 | * @return mixed Success on delete, error if delete fails
|
||
| 290 | * @throws MethodNotAllowedException When HTTP method is not a DELETE
|
||
| 291 | * @throws NotFoundException When id being deleted does not exist.
|
||
| 292 | */
|
||
| 293 | protected function _scaffoldDelete(CakeRequest $request) { |
||
| 294 | if ($this->controller->beforeScaffold('delete')) { |
||
| 295 | if (!$request->is('post')) { |
||
| 296 | throw new MethodNotAllowedException(); |
||
| 297 | } |
||
| 298 | $id = false; |
||
| 299 | if (isset($request->params['pass'][0])) { |
||
| 300 | $id = $request->params['pass'][0]; |
||
| 301 | } |
||
| 302 | $this->ScaffoldModel->id = $id; |
||
| 303 | if (!$this->ScaffoldModel->exists()) { |
||
| 304 | throw new NotFoundException(__d('cake', 'Invalid %s', Inflector::humanize($this->modelClass))); |
||
| 305 | } |
||
| 306 | if ($this->ScaffoldModel->delete()) { |
||
| 307 | $message = __d('cake', 'The %1$s with id: %2$s has been deleted.', Inflector::humanize($this->modelClass), $id); |
||
| 308 | return $this->_sendMessage($message, 'success'); |
||
| 309 | } |
||
| 310 | $message = __d('cake', |
||
| 311 | 'There was an error deleting the %1$s with id: %2$s',
|
||
| 312 | Inflector::humanize($this->modelClass), |
||
| 313 | $id
|
||
| 314 | ); |
||
| 315 | return $this->_sendMessage($message); |
||
| 316 | } elseif ($this->controller->scaffoldError('delete') === false) { |
||
| 317 | return $this->_scaffoldError(); |
||
| 318 | } |
||
| 319 | } |
||
| 320 | |||
| 321 | /**
|
||
| 322 | * Sends a message to the user. Either uses Sessions or flash messages depending
|
||
| 323 | * on the availability of a session
|
||
| 324 | *
|
||
| 325 | * @param string $message Message to display
|
||
| 326 | * @param string $element Flash template to use
|
||
| 327 | * @return void
|
||
| 328 | */
|
||
| 329 | protected function _sendMessage($message, $element = 'default') { |
||
| 330 | if ($this->_validSession) { |
||
| 331 | $this->controller->Flash->set($message, compact('element')); |
||
| 332 | return $this->controller->redirect($this->redirect); |
||
| 333 | } |
||
| 334 | $this->controller->flash($message, $this->redirect); |
||
| 335 | } |
||
| 336 | |||
| 337 | /**
|
||
| 338 | * Show a scaffold error
|
||
| 339 | *
|
||
| 340 | * @return mixed A rendered view showing the error
|
||
| 341 | */
|
||
| 342 | protected function _scaffoldError() { |
||
| 343 | return $this->controller->render('error', $this->layout); |
||
| 344 | } |
||
| 345 | |||
| 346 | /**
|
||
| 347 | * When methods are now present in a controller
|
||
| 348 | * scaffoldView is used to call default Scaffold methods if:
|
||
| 349 | * `public $scaffold;` is placed in the controller's class definition.
|
||
| 350 | *
|
||
| 351 | * @param CakeRequest $request Request object for scaffolding
|
||
| 352 | * @return void
|
||
| 353 | * @throws MissingActionException When methods are not scaffolded.
|
||
| 354 | * @throws MissingDatabaseException When the database connection is undefined.
|
||
| 355 | */
|
||
| 356 | protected function _scaffold(CakeRequest $request) { |
||
| 357 | $db = ConnectionManager::getDataSource($this->ScaffoldModel->useDbConfig); |
||
| 358 | $prefixes = Configure::read('Routing.prefixes'); |
||
| 359 | $scaffoldPrefix = $this->scaffoldActions; |
||
| 360 | |||
| 361 | if (isset($db)) { |
||
| 362 | if (empty($this->scaffoldActions)) { |
||
| 363 | $this->scaffoldActions = array( |
||
| 364 | 'index', 'list', 'view', 'add', 'create', 'edit', 'update', 'delete' |
||
| 365 | ); |
||
| 366 | } elseif (!empty($prefixes) && in_array($scaffoldPrefix, $prefixes)) { |
||
| 367 | $this->scaffoldActions = array( |
||
| 368 | $scaffoldPrefix . '_index', |
||
| 369 | $scaffoldPrefix . '_list', |
||
| 370 | $scaffoldPrefix . '_view', |
||
| 371 | $scaffoldPrefix . '_add', |
||
| 372 | $scaffoldPrefix . '_create', |
||
| 373 | $scaffoldPrefix . '_edit', |
||
| 374 | $scaffoldPrefix . '_update', |
||
| 375 | $scaffoldPrefix . '_delete' |
||
| 376 | ); |
||
| 377 | } |
||
| 378 | |||
| 379 | if (in_array($request->params['action'], $this->scaffoldActions)) { |
||
| 380 | if (!empty($prefixes)) { |
||
| 381 | $request->params['action'] = str_replace($scaffoldPrefix . '_', '', $request->params['action']); |
||
| 382 | } |
||
| 383 | switch ($request->params['action']) { |
||
| 384 | case 'index': |
||
| 385 | case 'list': |
||
| 386 | $this->_scaffoldIndex($request); |
||
| 387 | break;
|
||
| 388 | case 'view': |
||
| 389 | $this->_scaffoldView($request); |
||
| 390 | break;
|
||
| 391 | case 'add': |
||
| 392 | case 'create': |
||
| 393 | $this->_scaffoldSave($request, 'add'); |
||
| 394 | break;
|
||
| 395 | case 'edit': |
||
| 396 | case 'update': |
||
| 397 | $this->_scaffoldSave($request, 'edit'); |
||
| 398 | break;
|
||
| 399 | case 'delete': |
||
| 400 | $this->_scaffoldDelete($request); |
||
| 401 | break;
|
||
| 402 | } |
||
| 403 | } else {
|
||
| 404 | throw new MissingActionException(array( |
||
| 405 | 'controller' => get_class($this->controller), |
||
| 406 | 'action' => $request->action |
||
| 407 | )); |
||
| 408 | } |
||
| 409 | } else {
|
||
| 410 | throw new MissingDatabaseException(array('connection' => $this->ScaffoldModel->useDbConfig)); |
||
| 411 | } |
||
| 412 | } |
||
| 413 | |||
| 414 | /**
|
||
| 415 | * Returns associations for controllers models.
|
||
| 416 | *
|
||
| 417 | * @return array Associations for model
|
||
| 418 | */
|
||
| 419 | protected function _associations() { |
||
| 420 | $keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'); |
||
| 421 | $associations = array(); |
||
| 422 | |||
| 423 | foreach ($keys as $type) { |
||
| 424 | foreach ($this->ScaffoldModel->{$type} as $assocKey => $assocData) { |
||
| 425 | $associations[$type][$assocKey]['primaryKey'] = |
||
| 426 | $this->ScaffoldModel->{$assocKey}->primaryKey; |
||
| 427 | |||
| 428 | $associations[$type][$assocKey]['displayField'] = |
||
| 429 | $this->ScaffoldModel->{$assocKey}->displayField; |
||
| 430 | |||
| 431 | $associations[$type][$assocKey]['foreignKey'] = |
||
| 432 | $assocData['foreignKey']; |
||
| 433 | |||
| 434 | list($plugin, $model) = pluginSplit($assocData['className']); |
||
| 435 | if ($plugin) { |
||
| 436 | $plugin = Inflector::underscore($plugin); |
||
| 437 | } |
||
| 438 | $associations[$type][$assocKey]['plugin'] = $plugin; |
||
| 439 | |||
| 440 | $associations[$type][$assocKey]['controller'] = |
||
| 441 | Inflector::pluralize(Inflector::underscore($model)); |
||
| 442 | |||
| 443 | if ($type === 'hasAndBelongsToMany') { |
||
| 444 | $associations[$type][$assocKey]['with'] = $assocData['with']; |
||
| 445 | } |
||
| 446 | } |
||
| 447 | } |
||
| 448 | return $associations; |
||
| 449 | } |
||
| 450 | |||
| 451 | } |