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) && $this->controller->Session->valid()
149: );
150: $this->_scaffold($request);
151: }
152:
153: 154: 155: 156: 157: 158: 159:
160: protected function _scaffoldView(CakeRequest $request) {
161: if ($this->controller->beforeScaffold('view')) {
162: if (isset($request->params['pass'][0])) {
163: $this->ScaffoldModel->id = $request->params['pass'][0];
164: }
165: if (!$this->ScaffoldModel->exists()) {
166: throw new NotFoundException(__d('cake', 'Invalid %s', Inflector::humanize($this->modelKey)));
167: }
168: $this->ScaffoldModel->recursive = 1;
169: $this->controller->request->data = $this->ScaffoldModel->read();
170: $this->controller->set(
171: Inflector::variable($this->controller->modelClass), $this->request->data
172: );
173: $this->controller->render($this->request['action'], $this->layout);
174: } elseif ($this->controller->scaffoldError('view') === false) {
175: return $this->_scaffoldError();
176: }
177: }
178:
179: 180: 181: 182: 183: 184:
185: protected function _scaffoldIndex($params) {
186: if ($this->controller->beforeScaffold('index')) {
187: $this->ScaffoldModel->recursive = 0;
188: $this->controller->set(
189: Inflector::variable($this->controller->name), $this->controller->paginate()
190: );
191: $this->controller->render($this->request['action'], $this->layout);
192: } elseif ($this->controller->scaffoldError('index') === false) {
193: return $this->_scaffoldError();
194: }
195: }
196:
197: 198: 199: 200: 201: 202:
203: protected function _scaffoldForm($action = 'edit') {
204: $this->controller->viewVars['scaffoldFields'] = array_merge(
205: $this->controller->viewVars['scaffoldFields'],
206: array_keys($this->ScaffoldModel->hasAndBelongsToMany)
207: );
208: $this->controller->render($action, $this->layout);
209: }
210:
211: 212: 213: 214: 215: 216: 217: 218:
219: protected function _scaffoldSave(CakeRequest $request, $action = 'edit') {
220: $formAction = 'edit';
221: $success = __d('cake', 'updated');
222: if ($action === 'add') {
223: $formAction = 'add';
224: $success = __d('cake', 'saved');
225: }
226:
227: if ($this->controller->beforeScaffold($action)) {
228: if ($action === 'edit') {
229: if (isset($request->params['pass'][0])) {
230: $this->ScaffoldModel->id = $request['pass'][0];
231: }
232: if (!$this->ScaffoldModel->exists()) {
233: throw new NotFoundException(__d('cake', 'Invalid %s', Inflector::humanize($this->modelKey)));
234: }
235: }
236:
237: if (!empty($request->data)) {
238: if ($action === 'create') {
239: $this->ScaffoldModel->create();
240: }
241:
242: if ($this->ScaffoldModel->save($request->data)) {
243: if ($this->controller->afterScaffoldSave($action)) {
244: $message = __d('cake',
245: 'The %1$s has been %2$s',
246: Inflector::humanize($this->modelKey),
247: $success
248: );
249: return $this->_sendMessage($message);
250: }
251: return $this->controller->afterScaffoldSaveError($action);
252: }
253: if ($this->_validSession) {
254: $this->controller->Session->setFlash(__d('cake', 'Please correct errors below.'));
255: }
256: }
257:
258: if (empty($request->data)) {
259: if ($this->ScaffoldModel->id) {
260: $this->controller->data = $request->data = $this->ScaffoldModel->read();
261: } else {
262: $this->controller->data = $request->data = $this->ScaffoldModel->create();
263: }
264: }
265:
266: foreach ($this->ScaffoldModel->belongsTo as $assocName => $assocData) {
267: $varName = Inflector::variable(Inflector::pluralize(
268: preg_replace('/(?:_id)$/', '', $assocData['foreignKey'])
269: ));
270: $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list'));
271: }
272: foreach ($this->ScaffoldModel->hasAndBelongsToMany as $assocName => $assocData) {
273: $varName = Inflector::variable(Inflector::pluralize($assocName));
274: $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list'));
275: }
276:
277: return $this->_scaffoldForm($formAction);
278: } elseif ($this->controller->scaffoldError($action) === false) {
279: return $this->_scaffoldError();
280: }
281: }
282:
283: 284: 285: 286: 287: 288: 289: 290:
291: protected function _scaffoldDelete(CakeRequest $request) {
292: if ($this->controller->beforeScaffold('delete')) {
293: if (!$request->is('post')) {
294: throw new MethodNotAllowedException();
295: }
296: $id = false;
297: if (isset($request->params['pass'][0])) {
298: $id = $request->params['pass'][0];
299: }
300: $this->ScaffoldModel->id = $id;
301: if (!$this->ScaffoldModel->exists()) {
302: throw new NotFoundException(__d('cake', 'Invalid %s', Inflector::humanize($this->modelClass)));
303: }
304: if ($this->ScaffoldModel->delete()) {
305: $message = __d('cake', 'The %1$s with id: %2$s has been deleted.', Inflector::humanize($this->modelClass), $id);
306: return $this->_sendMessage($message);
307: }
308: $message = __d('cake',
309: 'There was an error deleting the %1$s with id: %2$s',
310: Inflector::humanize($this->modelClass),
311: $id
312: );
313: return $this->_sendMessage($message);
314: } elseif ($this->controller->scaffoldError('delete') === false) {
315: return $this->_scaffoldError();
316: }
317: }
318:
319: 320: 321: 322: 323: 324: 325:
326: protected function _sendMessage($message) {
327: if ($this->_validSession) {
328: $this->controller->Session->setFlash($message);
329: return $this->controller->redirect($this->redirect);
330: }
331: $this->controller->flash($message, $this->redirect);
332: }
333:
334: 335: 336: 337: 338:
339: protected function _scaffoldError() {
340: return $this->controller->render('error', $this->layout);
341: }
342:
343: 344: 345: 346: 347: 348: 349: 350: 351: 352:
353: protected function _scaffold(CakeRequest $request) {
354: $db = ConnectionManager::getDataSource($this->ScaffoldModel->useDbConfig);
355: $prefixes = Configure::read('Routing.prefixes');
356: $scaffoldPrefix = $this->scaffoldActions;
357:
358: if (isset($db)) {
359: if (empty($this->scaffoldActions)) {
360: $this->scaffoldActions = array(
361: 'index', 'list', 'view', 'add', 'create', 'edit', 'update', 'delete'
362: );
363: } elseif (!empty($prefixes) && in_array($scaffoldPrefix, $prefixes)) {
364: $this->scaffoldActions = array(
365: $scaffoldPrefix . '_index',
366: $scaffoldPrefix . '_list',
367: $scaffoldPrefix . '_view',
368: $scaffoldPrefix . '_add',
369: $scaffoldPrefix . '_create',
370: $scaffoldPrefix . '_edit',
371: $scaffoldPrefix . '_update',
372: $scaffoldPrefix . '_delete'
373: );
374: }
375:
376: if (in_array($request->params['action'], $this->scaffoldActions)) {
377: if (!empty($prefixes)) {
378: $request->params['action'] = str_replace($scaffoldPrefix . '_', '', $request->params['action']);
379: }
380: switch ($request->params['action']) {
381: case 'index':
382: case 'list':
383: $this->_scaffoldIndex($request);
384: break;
385: case 'view':
386: $this->_scaffoldView($request);
387: break;
388: case 'add':
389: case 'create':
390: $this->_scaffoldSave($request, 'add');
391: break;
392: case 'edit':
393: case 'update':
394: $this->_scaffoldSave($request, 'edit');
395: break;
396: case 'delete':
397: $this->_scaffoldDelete($request);
398: break;
399: }
400: } else {
401: throw new MissingActionException(array(
402: 'controller' => $this->controller->name,
403: 'action' => $request->action
404: ));
405: }
406: } else {
407: throw new MissingDatabaseException(array('connection' => $this->ScaffoldModel->useDbConfig));
408: }
409: }
410:
411: 412: 413: 414: 415:
416: protected function _associations() {
417: $keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
418: $associations = array();
419:
420: foreach ($keys as $type) {
421: foreach ($this->ScaffoldModel->{$type} as $assocKey => $assocData) {
422: $associations[$type][$assocKey]['primaryKey'] =
423: $this->ScaffoldModel->{$assocKey}->primaryKey;
424:
425: $associations[$type][$assocKey]['displayField'] =
426: $this->ScaffoldModel->{$assocKey}->displayField;
427:
428: $associations[$type][$assocKey]['foreignKey'] =
429: $assocData['foreignKey'];
430:
431: list($plugin, $model) = pluginSplit($assocData['className']);
432: if ($plugin) {
433: $plugin = Inflector::underscore($plugin);
434: }
435: $associations[$type][$assocKey]['plugin'] = $plugin;
436:
437: $associations[$type][$assocKey]['controller'] =
438: Inflector::pluralize(Inflector::underscore($model));
439:
440: if ($type === 'hasAndBelongsToMany') {
441: $associations[$type][$assocKey]['with'] = $assocData['with'];
442: }
443: }
444: }
445: return $associations;
446: }
447:
448: }
449: