pictcode / lib / Cake / Controller / Scaffold.php @ 635eef61
履歴 | 表示 | アノテート | ダウンロード (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 | } |