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: 'title_for_layout', '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() != false
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: } else {
252: return $this->controller->afterScaffoldSaveError($action);
253: }
254: } else {
255: if ($this->_validSession) {
256: $this->controller->Session->setFlash(__d('cake', 'Please correct errors below.'));
257: }
258: }
259: }
260:
261: if (empty($request->data)) {
262: if ($this->ScaffoldModel->id) {
263: $this->controller->data = $request->data = $this->ScaffoldModel->read();
264: } else {
265: $this->controller->data = $request->data = $this->ScaffoldModel->create();
266: }
267: }
268:
269: foreach ($this->ScaffoldModel->belongsTo as $assocName => $assocData) {
270: $varName = Inflector::variable(Inflector::pluralize(
271: preg_replace('/(?:_id)$/', '', $assocData['foreignKey'])
272: ));
273: $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list'));
274: }
275: foreach ($this->ScaffoldModel->hasAndBelongsToMany as $assocName => $assocData) {
276: $varName = Inflector::variable(Inflector::pluralize($assocName));
277: $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list'));
278: }
279:
280: return $this->_scaffoldForm($formAction);
281: } elseif ($this->controller->scaffoldError($action) === false) {
282: return $this->_scaffoldError();
283: }
284: }
285:
286: 287: 288: 289: 290: 291: 292: 293:
294: protected function _scaffoldDelete(CakeRequest $request) {
295: if ($this->controller->beforeScaffold('delete')) {
296: if (!$request->is('post')) {
297: throw new MethodNotAllowedException();
298: }
299: $id = false;
300: if (isset($request->params['pass'][0])) {
301: $id = $request->params['pass'][0];
302: }
303: $this->ScaffoldModel->id = $id;
304: if (!$this->ScaffoldModel->exists()) {
305: throw new NotFoundException(__d('cake', 'Invalid %s', Inflector::humanize($this->modelClass)));
306: }
307: if ($this->ScaffoldModel->delete()) {
308: $message = __d('cake', 'The %1$s with id: %2$s has been deleted.', Inflector::humanize($this->modelClass), $id);
309: return $this->_sendMessage($message);
310: } else {
311: $message = __d('cake',
312: 'There was an error deleting the %1$s with id: %2$s',
313: Inflector::humanize($this->modelClass),
314: $id
315: );
316: return $this->_sendMessage($message);
317: }
318: } elseif ($this->controller->scaffoldError('delete') === false) {
319: return $this->_scaffoldError();
320: }
321: }
322:
323: 324: 325: 326: 327: 328: 329:
330: protected function _sendMessage($message) {
331: if ($this->_validSession) {
332: $this->controller->Session->setFlash($message);
333: $this->controller->redirect($this->redirect);
334: } else {
335: $this->controller->flash($message, $this->redirect);
336: }
337: }
338:
339: 340: 341: 342: 343:
344: protected function _scaffoldError() {
345: return $this->controller->render('error', $this->layout);
346: }
347:
348: 349: 350: 351: 352: 353: 354: 355: 356: 357:
358: protected function _scaffold(CakeRequest $request) {
359: $db = ConnectionManager::getDataSource($this->ScaffoldModel->useDbConfig);
360: $prefixes = Configure::read('Routing.prefixes');
361: $scaffoldPrefix = $this->scaffoldActions;
362:
363: if (isset($db)) {
364: if (empty($this->scaffoldActions)) {
365: $this->scaffoldActions = array(
366: 'index', 'list', 'view', 'add', 'create', 'edit', 'update', 'delete'
367: );
368: } elseif (!empty($prefixes) && in_array($scaffoldPrefix, $prefixes)) {
369: $this->scaffoldActions = array(
370: $scaffoldPrefix . '_index',
371: $scaffoldPrefix . '_list',
372: $scaffoldPrefix . '_view',
373: $scaffoldPrefix . '_add',
374: $scaffoldPrefix . '_create',
375: $scaffoldPrefix . '_edit',
376: $scaffoldPrefix . '_update',
377: $scaffoldPrefix . '_delete'
378: );
379: }
380:
381: if (in_array($request->params['action'], $this->scaffoldActions)) {
382: if (!empty($prefixes)) {
383: $request->params['action'] = str_replace($scaffoldPrefix . '_', '', $request->params['action']);
384: }
385: switch ($request->params['action']) {
386: case 'index':
387: case 'list':
388: $this->_scaffoldIndex($request);
389: break;
390: case 'view':
391: $this->_scaffoldView($request);
392: break;
393: case 'add':
394: case 'create':
395: $this->_scaffoldSave($request, 'add');
396: break;
397: case 'edit':
398: case 'update':
399: $this->_scaffoldSave($request, 'edit');
400: break;
401: case 'delete':
402: $this->_scaffoldDelete($request);
403: break;
404: }
405: } else {
406: throw new MissingActionException(array(
407: 'controller' => $this->controller->name,
408: 'action' => $request->action
409: ));
410: }
411: } else {
412: throw new MissingDatabaseException(array('connection' => $this->ScaffoldModel->useDbConfig));
413: }
414: }
415:
416: 417: 418: 419: 420:
421: protected function _associations() {
422: $keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
423: $associations = array();
424:
425: foreach ($keys as $key => $type) {
426: foreach ($this->ScaffoldModel->{$type} as $assocKey => $assocData) {
427: $associations[$type][$assocKey]['primaryKey'] =
428: $this->ScaffoldModel->{$assocKey}->primaryKey;
429:
430: $associations[$type][$assocKey]['displayField'] =
431: $this->ScaffoldModel->{$assocKey}->displayField;
432:
433: $associations[$type][$assocKey]['foreignKey'] =
434: $assocData['foreignKey'];
435:
436: list($plugin, $model) = pluginSplit($assocData['className']);
437: if ($plugin) {
438: $plugin = Inflector::underscore($plugin);
439: }
440: $associations[$type][$assocKey]['plugin'] = $plugin;
441:
442: $associations[$type][$assocKey]['controller'] =
443: Inflector::pluralize(Inflector::underscore($model));
444:
445: if ($type == 'hasAndBelongsToMany') {
446: $associations[$type][$assocKey]['with'] = $assocData['with'];
447: }
448: }
449: }
450: return $associations;
451: }
452:
453: }
454: