PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/cake/libs/controller/scaffold.php

https://github.com/hardsshah/bookmarks
PHP | 516 lines | 287 code | 31 blank | 198 comment | 75 complexity | 631764f6c463f96367ca01372eb365fe MD5 | raw file
  1. <?php
  2. /* SVN FILE: $Id$ */
  3. /**
  4. * Scaffold.
  5. *
  6. * Automatic forms and actions generation for rapid web application development.
  7. *
  8. * PHP versions 4 and 5
  9. *
  10. * CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
  11. * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
  12. *
  13. * Licensed under The MIT License
  14. * Redistributions of files must retain the above copyright notice.
  15. *
  16. * @filesource
  17. * @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
  18. * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
  19. * @package cake
  20. * @subpackage cake.cake.libs.controller
  21. * @since Cake v 0.10.0.1076
  22. * @version $Revision$
  23. * @modifiedby $LastChangedBy$
  24. * @lastmodified $Date$
  25. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  26. */
  27. /**
  28. * Scaffolding is a set of automatic views, forms and controllers for starting web development work faster.
  29. *
  30. * Scaffold inspects your database tables, and making educated guesses, sets up a
  31. * number of pages for each of your Models. These pages have data forms that work,
  32. * and afford the web developer an early look at the data, and the possibility to over-ride
  33. * scaffolded actions with custom-made ones.
  34. *
  35. * @package cake
  36. * @subpackage cake.cake.libs.controller
  37. */
  38. class Scaffold extends Object {
  39. /**
  40. * Controller object
  41. *
  42. * @var Controller
  43. * @access public
  44. */
  45. var $controller = null;
  46. /**
  47. * Name of the controller to scaffold
  48. *
  49. * @var string
  50. * @access public
  51. */
  52. var $name = null;
  53. /**
  54. * Action to be performed.
  55. *
  56. * @var string
  57. * @access public
  58. */
  59. var $action = null;
  60. /**
  61. * Name of current model this view context is attached to
  62. *
  63. * @var string
  64. * @access public
  65. */
  66. var $model = null;
  67. /**
  68. * Path to View.
  69. *
  70. * @var string
  71. * @access public
  72. */
  73. var $viewPath;
  74. /**
  75. * Path parts for creating links in views.
  76. *
  77. * @var string Base URL
  78. * @access public
  79. */
  80. var $base = null;
  81. /**
  82. * Name of layout to use with this View.
  83. *
  84. * @var string
  85. * @access public
  86. */
  87. var $layout = 'default';
  88. /**
  89. * Array of parameter data
  90. *
  91. * @var array
  92. * @access public
  93. */
  94. var $params;
  95. /**
  96. * File extension. Defaults to Cake's template ".ctp".
  97. *
  98. * @var array
  99. * @access public
  100. */
  101. var $ext = '.ctp';
  102. /**
  103. * Sub-directory for this view file.
  104. *
  105. * @var string
  106. * @access public
  107. */
  108. var $subDir = null;
  109. /**
  110. * Plugin name.
  111. *
  112. * @var string
  113. * @access public
  114. */
  115. var $plugin = null;
  116. /**
  117. * List of variables to collect from the associated controller
  118. *
  119. * @var array
  120. * @access private
  121. */
  122. var $__passedVars = array('action', 'base', 'webroot', 'layout', 'name', 'viewPath', 'ext', 'params', 'data', 'plugin', 'cacheAction');
  123. /**
  124. * Title HTML element for current scaffolded view
  125. *
  126. * @var string
  127. * @access public
  128. */
  129. var $scaffoldTitle = null;
  130. /**
  131. * Construct and set up given controller with given parameters.
  132. *
  133. * @param string $controller_class Name of controller
  134. * @param array $params Parameters for scaffolding
  135. */
  136. function __construct(&$controller, $params) {
  137. $this->controller =& $controller;
  138. $count = count($this->__passedVars);
  139. for ($j = 0; $j < $count; $j++) {
  140. $var = $this->__passedVars[$j];
  141. $this->{$var} = $controller->{$var};
  142. }
  143. $this->redirect = array('action'=> 'index');
  144. $this->modelClass = $controller->modelClass;
  145. $this->modelKey = $controller->modelKey;
  146. if (!is_object($this->controller->{$this->modelClass})) {
  147. return $this->cakeError('missingModel', array(array('className' => $this->modelClass, 'webroot' => '', 'base' => $controller->base)));
  148. }
  149. $this->ScaffoldModel =& $this->controller->{$this->modelClass};
  150. $this->scaffoldTitle = Inflector::humanize($this->viewPath);
  151. $this->scaffoldActions = $controller->scaffold;
  152. $this->controller->pageTitle = __('Scaffold :: ', true) . Inflector::humanize($this->action) . ' :: ' . $this->scaffoldTitle;
  153. $modelClass = $this->controller->modelClass;
  154. $primaryKey = $this->ScaffoldModel->primaryKey;
  155. $displayField = $this->ScaffoldModel->displayField;
  156. $singularVar = Inflector::variable($modelClass);
  157. $pluralVar = Inflector::variable($this->controller->name);
  158. $singularHumanName = Inflector::humanize($modelClass);
  159. $pluralHumanName = Inflector::humanize($this->controller->name);
  160. $scaffoldFields = array_keys($this->ScaffoldModel->schema());
  161. $associations = $this->__associations();
  162. $this->controller->set(compact('modelClass', 'primaryKey', 'displayField', 'singularVar', 'pluralVar',
  163. 'singularHumanName', 'pluralHumanName', 'scaffoldFields', 'associations'));
  164. if ($this->controller->view && $this->controller->view !== 'Theme') {
  165. $this->controller->view = 'scaffold';
  166. }
  167. $this->__scaffold($params);
  168. }
  169. /**
  170. * Outputs the content of a scaffold method passing it through the Controller::afterFilter()
  171. *
  172. * @return void
  173. * @access protected
  174. */
  175. function _output() {
  176. $this->controller->afterFilter();
  177. echo($this->controller->output);
  178. }
  179. /**
  180. * Renders a view action of scaffolded model.
  181. *
  182. * @param array $params Parameters for scaffolding
  183. * @return mixed A rendered view of a row from Models database table
  184. * @access private
  185. */
  186. function __scaffoldView($params) {
  187. if ($this->controller->_beforeScaffold('view')) {
  188. if (isset($params['pass'][0])) {
  189. $this->ScaffoldModel->id = $params['pass'][0];
  190. } elseif (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
  191. $this->controller->Session->setFlash(sprintf(__("No id set for %s::view()", true), Inflector::humanize($this->modelKey)));
  192. $this->controller->redirect($this->redirect);
  193. } else {
  194. return $this->controller->flash(sprintf(__("No id set for %s::view()", true), Inflector::humanize($this->modelKey)),
  195. '/' . Inflector::underscore($this->controller->viewPath));
  196. }
  197. $this->ScaffoldModel->recursive = 1;
  198. $this->controller->data = $this->ScaffoldModel->read();
  199. $this->controller->set(Inflector::variable($this->controller->modelClass), $this->controller->data);
  200. $this->controller->render($this->action, $this->layout);
  201. $this->_output();
  202. } elseif ($this->controller->_scaffoldError('view') === false) {
  203. return $this->__scaffoldError();
  204. }
  205. }
  206. /**
  207. * Renders index action of scaffolded model.
  208. *
  209. * @param array $params Parameters for scaffolding
  210. * @return mixed A rendered view listing rows from Models database table
  211. * @access private
  212. */
  213. function __scaffoldIndex($params) {
  214. if ($this->controller->_beforeScaffold('index')) {
  215. $this->ScaffoldModel->recursive = 0;
  216. $this->controller->set(Inflector::variable($this->controller->name), $this->controller->paginate());
  217. $this->controller->render($this->action, $this->layout);
  218. $this->_output();
  219. } elseif ($this->controller->_scaffoldError('index') === false) {
  220. return $this->__scaffoldError();
  221. }
  222. }
  223. /**
  224. * Renders an add or edit action for scaffolded model.
  225. *
  226. * @param string $action Action (add or edit)
  227. * @return mixed A rendered view with a form to edit or add a record in the Models database table
  228. * @access private
  229. */
  230. function __scaffoldForm($action = 'edit') {
  231. $this->controller->render($action, $this->layout);
  232. $this->_output();
  233. }
  234. /**
  235. * Saves or updates the scaffolded model.
  236. *
  237. * @param array $params Parameters for scaffolding
  238. * @param string $action add or edt
  239. * @return mixed Success on save/update, add/edit form if data is empty or error if save or update fails
  240. * @access private
  241. */
  242. function __scaffoldSave($params = array(), $action = 'edit') {
  243. $formAction = 'edit';
  244. $success = __('updated', true);
  245. if ($action === 'add') {
  246. $formAction = 'add';
  247. $success = __('saved', true);
  248. }
  249. if ($this->controller->_beforeScaffold($action)) {
  250. if ($action == 'edit') {
  251. if (isset($params['pass'][0])) {
  252. $this->ScaffoldModel->id = $params['pass'][0];
  253. }
  254. if (!$this->ScaffoldModel->exists()) {
  255. if (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
  256. $this->controller->Session->setFlash(sprintf(__("Invalid id for %s::edit()", true), Inflector::humanize($this->modelKey)));
  257. $this->controller->redirect($this->redirect);
  258. } else {
  259. return $this->controller->flash(sprintf(__("Invalid id for %s::edit()", true), Inflector::humanize($this->modelKey)), $this->redirect);
  260. }
  261. }
  262. }
  263. if (!empty($this->controller->data)) {
  264. if ($action == 'create') {
  265. $this->ScaffoldModel->create();
  266. }
  267. if ($this->ScaffoldModel->save($this->controller->data)) {
  268. if ($this->controller->_afterScaffoldSave($action)) {
  269. if (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
  270. $this->controller->Session->setFlash(sprintf(__('The %1$s has been %2$s', true), Inflector::humanize($this->modelClass), $success));
  271. $this->controller->redirect($this->redirect);
  272. } else {
  273. return $this->controller->flash(sprintf(__('The %1$s has been %2$s', true), Inflector::humanize($this->modelClass), $success), $this->redirect);
  274. }
  275. } else {
  276. return $this->controller->_afterScaffoldSaveError($action);
  277. }
  278. } else {
  279. if (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
  280. $this->controller->Session->setFlash(__('Please correct errors below.', true));
  281. }
  282. }
  283. }
  284. if (empty($this->controller->data)) {
  285. if ($this->ScaffoldModel->id) {
  286. $this->controller->data = $this->ScaffoldModel->read();
  287. } else {
  288. $this->controller->data = $this->ScaffoldModel->create();
  289. }
  290. }
  291. foreach ($this->ScaffoldModel->belongsTo as $assocName => $assocData) {
  292. $varName = Inflector::variable(Inflector::pluralize(preg_replace('/(?:_id)$/', '', $assocData['foreignKey'])));
  293. $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list'));
  294. }
  295. foreach ($this->ScaffoldModel->hasAndBelongsToMany as $assocName => $assocData) {
  296. $varName = Inflector::variable(Inflector::pluralize($assocName));
  297. $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list'));
  298. }
  299. return $this->__scaffoldForm($formAction);
  300. } elseif ($this->controller->_scaffoldError($action) === false) {
  301. return $this->__scaffoldError();
  302. }
  303. }
  304. /**
  305. * Performs a delete on given scaffolded Model.
  306. *
  307. * @param array $params Parameters for scaffolding
  308. * @return mixed Success on delete, error if delete fails
  309. * @access private
  310. */
  311. function __scaffoldDelete($params = array()) {
  312. if ($this->controller->_beforeScaffold('delete')) {
  313. if (isset($params['pass'][0])) {
  314. $id = $params['pass'][0];
  315. } elseif (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
  316. $this->controller->Session->setFlash(sprintf(__("No id set for %s::delete()", true), Inflector::humanize($this->modelKey)));
  317. $this->controller->redirect($this->redirect);
  318. } else {
  319. return $this->controller->flash(sprintf(__("No id set for %s::delete()", true), Inflector::humanize($this->modelKey)),
  320. '/' . Inflector::underscore($this->controller->viewPath));
  321. }
  322. if ($this->ScaffoldModel->del($id)) {
  323. if (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
  324. $this->controller->Session->setFlash(sprintf(__('The %1$s with id: %2$d has been deleted.', true), Inflector::humanize($this->modelClass), $id));
  325. $this->controller->redirect($this->redirect);
  326. } else {
  327. return $this->controller->flash(sprintf(__('The %1$s with id: %2$d has been deleted.', true), Inflector::humanize($this->modelClass), $id), '/' . $this->viewPath);
  328. }
  329. } else {
  330. if (isset($this->controller->Session) && $this->controller->Session->valid() != false) {
  331. $this->controller->Session->setFlash(sprintf(__('There was an error deleting the %1$s with id: %2$d', true), Inflector::humanize($this->modelClass), $id));
  332. $this->controller->redirect($this->redirect);
  333. } else {
  334. return $this->controller->flash(sprintf(__('There was an error deleting the %1$s with id: %2$d', true), Inflector::humanize($this->modelClass), $id), '/' . $this->viewPath);
  335. }
  336. }
  337. } elseif ($this->controller->_scaffoldError('delete') === false) {
  338. return $this->__scaffoldError();
  339. }
  340. }
  341. /**
  342. * Show a scaffold error
  343. *
  344. * @return mixed A rendered view showing the error
  345. * @access private
  346. */
  347. function __scaffoldError() {
  348. return $this->controller->render('error', $this->layout);
  349. $this->_output();
  350. }
  351. /**
  352. * When methods are now present in a controller
  353. * scaffoldView is used to call default Scaffold methods if:
  354. * <code>
  355. * var $scaffold;
  356. * </code>
  357. * is placed in the controller's class definition.
  358. *
  359. * @param array $params Parameters for scaffolding
  360. * @return mixed A rendered view of scaffold action, or showing the error
  361. * @access private
  362. */
  363. function __scaffold($params) {
  364. $db = &ConnectionManager::getDataSource($this->ScaffoldModel->useDbConfig);
  365. $admin = Configure::read('Routing.admin');
  366. if (isset($db)) {
  367. if (empty($this->scaffoldActions)) {
  368. $this->scaffoldActions = array('index', 'list', 'view', 'add', 'create', 'edit', 'update', 'delete');
  369. } elseif (!empty($admin) && $this->scaffoldActions === $admin) {
  370. $this->scaffoldActions = array($admin .'_index', $admin .'_list', $admin .'_view', $admin .'_add', $admin .'_create', $admin .'_edit', $admin .'_update', $admin .'_delete');
  371. }
  372. if (in_array($params['action'], $this->scaffoldActions)) {
  373. if (!empty($admin)) {
  374. $params['action'] = str_replace($admin . '_', '', $params['action']);
  375. }
  376. switch ($params['action']) {
  377. case 'index':
  378. $this->__scaffoldIndex($params);
  379. break;
  380. case 'view':
  381. $this->__scaffoldView($params);
  382. break;
  383. case 'list':
  384. $this->__scaffoldIndex($params);
  385. break;
  386. case 'add':
  387. $this->__scaffoldSave($params, 'add');
  388. break;
  389. case 'edit':
  390. $this->__scaffoldSave($params, 'edit');
  391. break;
  392. case 'create':
  393. $this->__scaffoldSave($params, 'add');
  394. break;
  395. case 'update':
  396. $this->__scaffoldSave($params, 'edit');
  397. break;
  398. case 'delete':
  399. $this->__scaffoldDelete($params);
  400. break;
  401. }
  402. } else {
  403. return $this->cakeError('missingAction', array(array('className' => $this->controller->name . "Controller",
  404. 'base' => $this->controller->base,
  405. 'action' => $this->action,
  406. 'webroot' => $this->controller->webroot)));
  407. }
  408. } else {
  409. return $this->cakeError('missingDatabase', array(array('webroot' => $this->controller->webroot)));
  410. }
  411. }
  412. /**
  413. * Returns associations for controllers models.
  414. *
  415. * @return array Associations for model
  416. * @access private
  417. */
  418. function __associations() {
  419. $keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany');
  420. $associations = array();
  421. foreach ($keys as $key => $type) {
  422. foreach ($this->ScaffoldModel->{$type} as $assocKey => $assocData) {
  423. $associations[$type][$assocKey]['primaryKey'] = $this->ScaffoldModel->{$assocKey}->primaryKey;
  424. $associations[$type][$assocKey]['displayField'] = $this->ScaffoldModel->{$assocKey}->displayField;
  425. $associations[$type][$assocKey]['foreignKey'] = $assocData['foreignKey'];
  426. $associations[$type][$assocKey]['controller'] = Inflector::pluralize(Inflector::underscore($assocData['className']));
  427. }
  428. }
  429. return $associations;
  430. }
  431. }
  432. /**
  433. * Scaffold View.
  434. *
  435. * @package cake
  436. * @subpackage cake.cake.libs.controller
  437. */
  438. if (!class_exists('ThemeView')) {
  439. App::import('View', 'Theme');
  440. }
  441. class ScaffoldView extends ThemeView {
  442. /**
  443. * Override _getViewFileName
  444. *
  445. * @return string action
  446. * @access protected
  447. */
  448. function _getViewFileName($name = null) {
  449. if ($name === null) {
  450. $name = $this->action;
  451. }
  452. $name = Inflector::underscore($name);
  453. $admin = Configure::read('Routing.admin');
  454. if (!empty($admin) && strpos($name, $admin . '_') !== false) {
  455. $name = substr($name, strlen($admin) + 1);
  456. }
  457. if ($name === 'add') {
  458. $name = 'edit';
  459. }
  460. $scaffoldAction = 'scaffold.' . $name;
  461. if (!is_null($this->subDir)) {
  462. $subDir = strtolower($this->subDir) . DS;
  463. } else {
  464. $subDir = null;
  465. }
  466. $names[] = $this->viewPath . DS . $subDir . $scaffoldAction;
  467. $names[] = 'scaffolds' . DS . $subDir . $name;
  468. $paths = $this->_paths($this->plugin);
  469. $exts = array($this->ext, '.ctp', '.thtml');
  470. foreach ($paths as $path) {
  471. foreach ($names as $name) {
  472. foreach ($exts as $ext) {
  473. if (file_exists($path . $name . $ext)) {
  474. return $path . $name . $ext;
  475. }
  476. }
  477. }
  478. }
  479. if ($name === 'scaffolds' . DS . $subDir . 'error') {
  480. return LIBS . 'view' . DS . 'errors' . DS . 'scaffold_error.ctp';
  481. }
  482. return $this->_missingView($paths[0] . $name . $this->ext, 'missingView');
  483. }
  484. }
  485. ?>