1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
22:
23: App::uses('Scaffold', 'View');
24:
25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
35: class Scaffold {
36:
37: 38: 39: 40: 41:
42: public $controller = null;
43:
44: 45: 46: 47: 48:
49: public $name = null;
50:
51: 52: 53: 54: 55:
56: public $model = null;
57:
58: 59: 60: 61: 62:
63: public $viewPath;
64:
65: 66: 67: 68: 69:
70: public $layout = 'default';
71:
72: 73: 74: 75: 76:
77: public $request;
78:
79: 80: 81: 82: 83:
84: protected $_validSession = null;
85:
86: 87: 88: 89: 90:
91: protected $_passedVars = array(
92: 'layout', 'name', 'viewPath', 'request'
93: );
94:
95: 96: 97: 98: 99:
100: public $scaffoldTitle = null;
101:
102: 103: 104: 105: 106: 107: 108:
109: public function __construct(Controller $controller, CakeRequest $request) {
110: $this->controller = $controller;
111:
112: $count = count($this->_passedVars);
113: for ($j = 0; $j < $count; $j++) {
114: $var = $this->_passedVars[$j];
115: $this->{$var} = $controller->{$var};
116: }
117:
118: $this->redirect = array('action' => 'index');
119:
120: $this->modelClass = $controller->modelClass;
121: $this->modelKey = $controller->modelKey;
122:
123: if (!is_object($this->controller->{$this->modelClass})) {
124: throw new MissingModelException($this->modelClass);
125: }
126:
127: $this->ScaffoldModel = $this->controller->{$this->modelClass};
128: $this->scaffoldTitle = Inflector::humanize(Inflector::underscore($this->viewPath));
129: $this->scaffoldActions = $controller->scaffold;
130: $title = __d('cake', 'Scaffold :: ') . Inflector::humanize($request->action) . ' :: ' . $this->scaffoldTitle;
131: $modelClass = $this->controller->modelClass;
132: $primaryKey = $this->ScaffoldModel->primaryKey;
133: $displayField = $this->ScaffoldModel->displayField;
134: $singularVar = Inflector::variable($modelClass);
135: $pluralVar = Inflector::variable($this->controller->name);
136: $singularHumanName = Inflector::humanize(Inflector::underscore($modelClass));
137: $pluralHumanName = Inflector::humanize(Inflector::underscore($this->controller->name));
138: $scaffoldFields = array_keys($this->ScaffoldModel->schema());
139: $associations = $this->_associations();
140:
141: $this->controller->set(compact(
142: 'modelClass', 'primaryKey', 'displayField', 'singularVar', 'pluralVar',
143: 'singularHumanName', 'pluralHumanName', 'scaffoldFields', 'associations'
144: ));
145: $this->controller->set('title_for_layout', $title);
146:
147: if ($this->controller->viewClass) {
148: $this->controller->viewClass = 'Scaffold';
149: }
150: $this->_validSession = (
151: isset($this->controller->Session) && $this->controller->Session->valid()
152: );
153: $this->_scaffold($request);
154: }
155:
156: 157: 158: 159: 160: 161: 162:
163: protected function _scaffoldView(CakeRequest $request) {
164: if ($this->controller->beforeScaffold('view')) {
165: if (isset($request->params['pass'][0])) {
166: $this->ScaffoldModel->id = $request->params['pass'][0];
167: }
168: if (!$this->ScaffoldModel->exists()) {
169: throw new NotFoundException(__d('cake', 'Invalid %s', Inflector::humanize($this->modelKey)));
170: }
171: $this->ScaffoldModel->recursive = 1;
172: $this->controller->request->data = $this->ScaffoldModel->read();
173: $this->controller->set(
174: Inflector::variable($this->controller->modelClass), $this->request->data
175: );
176: $this->controller->render($this->request['action'], $this->layout);
177: } elseif ($this->controller->scaffoldError('view') === false) {
178: return $this->_scaffoldError();
179: }
180: }
181:
182: 183: 184: 185: 186: 187:
188: protected function _scaffoldIndex($params) {
189: if ($this->controller->beforeScaffold('index')) {
190: $this->ScaffoldModel->recursive = 0;
191: $this->controller->set(
192: Inflector::variable($this->controller->name), $this->controller->paginate()
193: );
194: $this->controller->render($this->request['action'], $this->layout);
195: } elseif ($this->controller->scaffoldError('index') === false) {
196: return $this->_scaffoldError();
197: }
198: }
199:
200: 201: 202: 203: 204: 205:
206: protected function _scaffoldForm($action = 'edit') {
207: $this->controller->viewVars['scaffoldFields'] = array_merge(
208: $this->controller->viewVars['scaffoldFields'],
209: array_keys($this->ScaffoldModel->hasAndBelongsToMany)
210: );
211: $this->controller->render($action, $this->layout);
212: }
213:
214: 215: 216: 217: 218: 219: 220: 221:
222: protected function _scaffoldSave(CakeRequest $request, $action = 'edit') {
223: $formAction = 'edit';
224: $success = __d('cake', 'updated');
225: if ($action === 'add') {
226: $formAction = 'add';
227: $success = __d('cake', 'saved');
228: }
229:
230: if ($this->controller->beforeScaffold($action)) {
231: if ($action === 'edit') {
232: if (isset($request->params['pass'][0])) {
233: $this->ScaffoldModel->id = $request['pass'][0];
234: }
235: if (!$this->ScaffoldModel->exists()) {
236: throw new NotFoundException(__d('cake', 'Invalid %s', Inflector::humanize($this->modelKey)));
237: }
238: }
239:
240: if (!empty($request->data)) {
241: if ($action === 'create') {
242: $this->ScaffoldModel->create();
243: }
244:
245: if ($this->ScaffoldModel->save($request->data)) {
246: if ($this->controller->afterScaffoldSave($action)) {
247: $message = __d('cake',
248: 'The %1$s has been %2$s',
249: Inflector::humanize($this->modelKey),
250: $success
251: );
252: return $this->_sendMessage($message);
253: }
254: return $this->controller->afterScaffoldSaveError($action);
255: }
256: if ($this->_validSession) {
257: $this->controller->Session->setFlash(__d('cake', 'Please correct errors below.'));
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: }
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: } elseif ($this->controller->scaffoldError('delete') === false) {
318: return $this->_scaffoldError();
319: }
320: }
321:
322: 323: 324: 325: 326: 327: 328:
329: protected function _sendMessage($message) {
330: if ($this->_validSession) {
331: $this->controller->Session->setFlash($message);
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' => $this->controller->name,
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: