Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

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