PageRenderTime 43ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/code/ryzom/tools/server/www/webtt/cake/libs/controller/scaffold.php

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