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_for_layout = __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:
144: if ($this->controller->viewClass) {
145: $this->controller->viewClass = 'Scaffold';
146: }
147: $this->_validSession = (
148: isset($this->controller->Session) && $this->controller->Session->valid() != false
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: } else {
251: return $this->controller->afterScaffoldSaveError($action);
252: }
253: } else {
254: if ($this->_validSession) {
255: $this->controller->Session->setFlash(__d('cake', 'Please correct errors below.'));
256: }
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: 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$d has been deleted.', Inflector::humanize($this->modelClass), $id);
307: return $this->_sendMessage($message);
308: } else {
309: $message = __d('cake',
310: 'There was an error deleting the %1$s with id: %2$d',
311: Inflector::humanize($this->modelClass),
312: $id
313: );
314: return $this->_sendMessage($message);
315: }
316: } elseif ($this->controller->scaffoldError('delete') === false) {
317: return $this->_scaffoldError();
318: }
319: }
320:
321: 322: 323: 324: 325: 326: 327:
328: protected function _sendMessage($message) {
329: if ($this->_validSession) {
330: $this->controller->Session->setFlash($message);
331: $this->controller->redirect($this->redirect);
332: } else {
333: $this->controller->flash($message, $this->redirect);
334: }
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: protected function _scaffold(CakeRequest $request) {
356: $db = ConnectionManager::getDataSource($this->ScaffoldModel->useDbConfig);
357: $prefixes = Configure::read('Routing.prefixes');
358: $scaffoldPrefix = $this->scaffoldActions;
359:
360: if (isset($db)) {
361: if (empty($this->scaffoldActions)) {
362: $this->scaffoldActions = array(
363: 'index', 'list', 'view', 'add', 'create', 'edit', 'update', 'delete'
364: );
365: } elseif (!empty($prefixes) && in_array($scaffoldPrefix, $prefixes)) {
366: $this->scaffoldActions = array(
367: $scaffoldPrefix . '_index',
368: $scaffoldPrefix . '_list',
369: $scaffoldPrefix . '_view',
370: $scaffoldPrefix . '_add',
371: $scaffoldPrefix . '_create',
372: $scaffoldPrefix . '_edit',
373: $scaffoldPrefix . '_update',
374: $scaffoldPrefix . '_delete'
375: );
376: }
377:
378: if (in_array($request->params['action'], $this->scaffoldActions)) {
379: if (!empty($prefixes)) {
380: $request->params['action'] = str_replace($scaffoldPrefix . '_', '', $request->params['action']);
381: }
382: switch ($request->params['action']) {
383: case 'index':
384: case 'list':
385: $this->_scaffoldIndex($request);
386: break;
387: case 'view':
388: $this->_scaffoldView($request);
389: break;
390: case 'add':
391: case 'create':
392: $this->_scaffoldSave($request, 'add');
393: break;
394: case 'edit':
395: case 'update':
396: $this->_scaffoldSave($request, 'edit');
397: break;
398: case 'delete':
399: $this->_scaffoldDelete($request);
400: break;
401: }
402: } else {
403: throw new MissingActionException(array(
404: 'controller' => $this->controller->name,
405: 'action' => $request->action
406: ));
407: }
408: } else {
409: throw new MissingDatabaseException(array('connection' => $this->ScaffoldModel->useDbConfig));
410: }
411: }
412:
413: 414: 415: 416: 417:
418: protected function _associations() {
419: $keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
420: $associations = array();
421:
422: foreach ($keys as $key => $type) {
423: foreach ($this->ScaffoldModel->{$type} as $assocKey => $assocData) {
424: $associations[$type][$assocKey]['primaryKey'] =
425: $this->ScaffoldModel->{$assocKey}->primaryKey;
426:
427: $associations[$type][$assocKey]['displayField'] =
428: $this->ScaffoldModel->{$assocKey}->displayField;
429:
430: $associations[$type][$assocKey]['foreignKey'] =
431: $assocData['foreignKey'];
432:
433: $associations[$type][$assocKey]['controller'] =
434: Inflector::pluralize(Inflector::underscore($assocData['className']));
435:
436: if ($type == 'hasAndBelongsToMany') {
437: $associations[$type][$assocKey]['with'] = $assocData['with'];
438: }
439: }
440: }
441: return $associations;
442: }
443: }
444: