1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
20:
21: App::uses('Scaffold', 'View');
22:
23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
33: class Scaffold {
34:
35: 36: 37: 38: 39:
40: public $controller = null;
41:
42: 43: 44: 45: 46:
47: public $name = null;
48:
49: 50: 51: 52: 53:
54: public $model = null;
55:
56: 57: 58: 59: 60:
61: public $viewPath;
62:
63: 64: 65: 66: 67:
68: public $layout = 'default';
69:
70: 71: 72: 73: 74:
75: public $request;
76:
77: 78: 79: 80: 81:
82: protected $_validSession = null;
83:
84: 85: 86: 87: 88:
89: protected $_passedVars = array(
90: 'layout', 'name', 'viewPath', 'request'
91: );
92:
93: 94: 95: 96: 97:
98: public $scaffoldTitle = null;
99:
100: 101: 102: 103: 104: 105: 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: 156: 157: 158: 159: 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: 182: 183: 184: 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: 200: 201: 202: 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: 214: 215: 216: 217: 218: 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: 286: 287: 288: 289: 290: 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: 322: 323: 324: 325: 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: 337: 338: 339:
340: protected function _scaffoldError() {
341: return $this->controller->render('error', $this->layout);
342: }
343:
344: 345: 346: 347: 348: 349: 350: 351: 352: 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: 414: 415: 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: }
450: