統計
| ブランチ: | リビジョン:

pictcode_admin / lib / Cake / Controller / Scaffold.php @ 5ad38a95

履歴 | 表示 | アノテート | ダウンロード (13.584 KB)

1
<?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
}