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