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: