PageRenderTime 40ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/pdf/code/trunk/administrator/components/com_artofpdf/libraries/joomla/application/component/controllerform.php

https://bitbucket.org/eddieajau/the-art-of-joomla-archive
PHP | 516 lines | 225 code | 65 blank | 226 comment | 35 complexity | 036a6643231db3f56e0aebec3ff00a53 MD5 | raw file
  1. <?php
  2. /**
  3. * @version $Id: controllerform.php 278 2010-09-14 11:11:09Z eddieajau $
  4. * @copyright Copyright (C) 2005 - 2010 Open Source Matters, Inc. All rights reserved.
  5. * @license GNU General Public License version 2 or later; see LICENSE.txt
  6. */
  7. defined('_JEXEC') or die;
  8. juimport('joomla.application.component.controller');
  9. // @TODO Add ability to set redirect manually to better cope with frontend usage.
  10. /**
  11. * Controller tailored to suit most form-based admin operations.
  12. *
  13. * @package Joomla.Framework
  14. * @subpackage Application
  15. * @since 1.6
  16. */
  17. class JControllerForm extends JController
  18. {
  19. /**
  20. * @var string The context for storing internal data, eg record.
  21. * @since 1.6
  22. */
  23. protected $context;
  24. /**
  25. * @var string The URL option for the component.
  26. * @since 1.6
  27. */
  28. protected $option;
  29. /**
  30. * @var string The URL view item variable.
  31. * @since 1.6
  32. */
  33. protected $view_item;
  34. /**
  35. * @var string The URL view list variable.
  36. * @since 1.6
  37. */
  38. protected $view_list;
  39. /**
  40. * @var string The prefix to use with controller messages.
  41. * @since 1.6
  42. */
  43. protected $text_prefix;
  44. /**
  45. * Constructor.
  46. *
  47. * @param array An optional associative array of configuration settings.
  48. * @see JController
  49. */
  50. public function __construct($config = array())
  51. {
  52. parent::__construct($config);
  53. // Guess the option as com_NameOfController
  54. if (empty($this->option)) {
  55. $this->option = 'com_'.strtolower($this->getName());
  56. }
  57. // Guess the JText message prefix. Defaults to the option.
  58. if (empty($this->text_prefix)) {
  59. $this->text_prefix = strtoupper($this->option);
  60. }
  61. // Guess the context as the suffix, eg: OptionControllerContent.
  62. if (empty($this->context)) {
  63. $r = null;
  64. if (!preg_match('/(.*)Controller(.*)/i', get_class($this), $r)) {
  65. JError::raiseError(500, JText::_('JLIB_APPLICATION_ERROR_CONTROLLER_GET_NAME'));
  66. }
  67. $this->context = strtolower($r[2]);
  68. }
  69. // Guess the item view as the context.
  70. if (empty($this->view_item)) {
  71. $this->view_item = $this->context;
  72. }
  73. // Guess the list view as the plural of the item view.
  74. if (empty($this->view_list)) {
  75. // @TODO Probably worth moving to an inflector class based on http://kuwamoto.org/2007/12/17/improved-pluralizing-in-php-actionscript-and-ror/
  76. // Simple pluralisation based on public domain snippet by Paul Osman
  77. // For more complex types, just manually set the variable in your class.
  78. $plural = array(
  79. array( '/(x|ch|ss|sh)$/i', "$1es"),
  80. array( '/([^aeiouy]|qu)y$/i', "$1ies"),
  81. array( '/([^aeiouy]|qu)ies$/i', "$1y"),
  82. array( '/(bu)s$/i', "$1ses"),
  83. array( '/s$/i', "s"),
  84. array( '/$/', "s")
  85. );
  86. // check for matches using regular expressions
  87. foreach ($plural as $pattern) {
  88. if (preg_match($pattern[0], $this->view_item)) {
  89. $this->view_list = preg_replace( $pattern[0], $pattern[1], $this->view_item);
  90. break;
  91. }
  92. }
  93. }
  94. // Apply, Save & New, and Save As copy should be standard on forms.
  95. $this->registerTask('apply', 'save');
  96. $this->registerTask('save2new', 'save');
  97. $this->registerTask('save2copy', 'save');
  98. }
  99. /**
  100. * Method to add a new record.
  101. */
  102. public function add()
  103. {
  104. // Initialise variables.
  105. $app = JFactory::getApplication();
  106. $context = "$this->option.edit.$this->context";
  107. $tmpl = JRequest::getString('tmpl');
  108. $layout = JRequest::getString('layout', 'edit');
  109. $append = '';
  110. // Setup redirect info.
  111. if ($tmpl) {
  112. $append .= '&tmpl='.$tmpl;
  113. }
  114. if ($layout) {
  115. $append .= '&layout='.$layout;
  116. }
  117. // Access check.
  118. if (!$this->allowAdd()) {
  119. $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list, false));
  120. return JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_CREATE_RECORD_NOT_PERMITTED'));
  121. }
  122. // Clear the record edit information from the session.
  123. //$app->setUserState($context.'.id', null);
  124. //$app->setUserState($context.'.data', null);
  125. // Redirect to the edit screen.
  126. $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$append, false));
  127. }
  128. /**
  129. * Method to check if you can add a new record.
  130. *
  131. * Extended classes can override this if necessary.
  132. *
  133. * @param array An array of input data.
  134. *
  135. * @return boolean
  136. */
  137. protected function allowAdd($data = array())
  138. {
  139. //return JFactory::getUser()->authorise('core.create', $this->option);
  140. return true;
  141. }
  142. /**
  143. * Method to check if you can add a new record.
  144. *
  145. * Extended classes can override this if necessary.
  146. *
  147. * @param array An array of input data.
  148. * @param string The name of the key for the primary key.
  149. *
  150. * @return boolean
  151. */
  152. protected function allowEdit($data = array(), $key = 'id')
  153. {
  154. //return JFactory::getUser()->authorise('core.edit', $this->option);
  155. return true;
  156. }
  157. /**
  158. * Method to check if you can save a new or existing record.
  159. *
  160. * Extended classes can override this if necessary.
  161. *
  162. * @param array An array of input data.
  163. * @param string The name of the key for the primary key.
  164. *
  165. * @return boolean
  166. */
  167. protected function allowSave($data, $key = 'id')
  168. {
  169. // Initialise variables.
  170. $recordId = isset($data[$key]) ? $data[$key] : '0';
  171. if ($recordId) {
  172. return $this->allowEdit($data, $key);
  173. } else {
  174. return $this->allowAdd($data);
  175. }
  176. }
  177. /**
  178. * Method to cancel an edit
  179. */
  180. public function cancel()
  181. {
  182. JRequest::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
  183. // Initialise variables.
  184. $app = JFactory::getApplication();
  185. $model = $this->getModel();
  186. $table = $model->getTable();
  187. $checkin = property_exists($table, 'checked_out');
  188. $context = "$this->option.edit.$this->context";
  189. $tmpl = JRequest::getString('tmpl');
  190. $layout = JRequest::getString('layout', 'edit');
  191. $append = '';
  192. // Setup redirect info.
  193. if ($tmpl) {
  194. $append .= '&tmpl='.$tmpl;
  195. }
  196. if ($layout) {
  197. $append .= '&layout='.$layout;
  198. }
  199. // Get the record id.
  200. $recordId = (int) $app->getUserState($context.'.id');
  201. // Attempt to check-in the current record.
  202. if ($checkin && $recordId) {
  203. if(!$model->checkin($recordId)) {
  204. // Check-in failed, go back to the record and display a notice.
  205. $message = JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError());
  206. $this->setRedirect('index.php?option='.$this->option.'&view='.$this->view_item.$append, $message, 'error');
  207. return false;
  208. }
  209. }
  210. // Clean the session data and redirect.
  211. $app->setUserState($context.'.id', null);
  212. $app->setUserState($context.'.data', null);
  213. $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list, false));
  214. }
  215. /**
  216. * This controller does not have a display method. Redirect back to the list view of the component.
  217. *
  218. * @param boolean If true, the view output will be cached
  219. * @param array An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}.
  220. *
  221. * @return void
  222. * @since 1.5
  223. */
  224. public function display($cachable = false, $urlparams = false)
  225. {
  226. $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list, false));
  227. }
  228. /**
  229. * Method to edit an existing record.
  230. */
  231. public function edit()
  232. {
  233. // Initialise variables.
  234. $app = JFactory::getApplication();
  235. $model = $this->getModel();
  236. $table = $model->getTable();
  237. $cid = JRequest::getVar('cid', array(), 'post', 'array');
  238. $context = "$this->option.edit.$this->context";
  239. $tmpl = JRequest::getString('tmpl');
  240. $layout = JRequest::getString('layout', 'edit');
  241. $append = '';
  242. // Setup redirect info.
  243. if ($tmpl) {
  244. $append .= '&tmpl='.$tmpl;
  245. }
  246. if ($layout) {
  247. $append .= '&layout='.$layout;
  248. }
  249. // Get the previous record id (if any) and the current record id.
  250. //$previousId = (int) $app->getUserState($context.'.id');
  251. $recordId = (int) (count($cid) ? $cid[0] : JRequest::getInt('id'));
  252. $checkin = property_exists($table, 'checked_out');
  253. // Access check.
  254. $key = $table->getKeyName();
  255. if (!$this->allowEdit(array($key => $recordId), $key)) {
  256. $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list, false));
  257. return JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'));
  258. }
  259. // Compat support.
  260. $append .= '&'.$key.'='.$recordId;
  261. /*
  262. // If record ids do not match, checkin previous record.
  263. if ($checkin && ($previousId > 0) && ($recordId != $previousId)) {
  264. if (!$model->checkin($previousId)) {
  265. // Check-in failed, go back to the record and display a notice.
  266. $message = JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError());
  267. $this->setRedirect('index.php?option='.$this->option.'&view='.$this->view_item.$append, $message, 'error');
  268. return false;
  269. }
  270. }
  271. */
  272. // Attempt to check-out the new record for editing and redirect.
  273. if ($checkin && !$model->checkout($recordId)) {
  274. // Check-out failed, go back to the list and display a notice.
  275. $message = JText::sprintf('JLIB_APPLICATION_ERROR_CHECKOUT_FAILED', $model->getError());
  276. $this->setRedirect('index.php?option='.$this->option.'&view='.$this->view_item.$append.'&id='.$recordId, $message, 'error');
  277. return false;
  278. }
  279. else {
  280. // Check-out succeeded, push the new record id into the session.
  281. //$app->setUserState($context.'.id', $recordId);
  282. //$app->setUserState($context.'.data', null);
  283. $this->setRedirect('index.php?option='.$this->option.'&view='.$this->view_item.$append);
  284. return true;
  285. }
  286. }
  287. /**
  288. * Method to get a model object, loading it if required.
  289. *
  290. * @param string The model name. Optional.
  291. * @param string The class prefix. Optional.
  292. * @param array Configuration array for model. Optional.
  293. *
  294. * @return object The model.
  295. */
  296. public function getModel($name = '', $prefix = '', $config = array('ignore_request' => true))
  297. {
  298. if (empty($name)) {
  299. $name = $this->context;
  300. }
  301. return parent::getModel($name, $prefix, $config);
  302. }
  303. /**
  304. * Function that allows child controller access to model data after the data has been saved.
  305. *
  306. * @param JModel $model The data model object.
  307. *
  308. * @return void
  309. * @since 1.6
  310. */
  311. protected function postSaveHook(JModel16 &$model)
  312. {
  313. }
  314. /**
  315. * Method to save a record.
  316. *
  317. * @return boolean
  318. * @since 1.6
  319. */
  320. public function save()
  321. {
  322. // Check for request forgeries.
  323. JRequest::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
  324. // Initialise variables.
  325. $app = JFactory::getApplication();
  326. $lang = JFactory::getLanguage();
  327. $model = $this->getModel();
  328. $table = $model->getTable();
  329. $data = JRequest::getVar('jform', array(), 'post', 'array');
  330. $checkin = property_exists($table, 'checked_out');
  331. $context = "$this->option.edit.$this->context";
  332. $task = $this->getTask();
  333. //$recordId = (int) $app->getUserState($context.'.id');
  334. $tmpl = JRequest::getString('tmpl');
  335. $layout = JRequest::getString('layout', 'edit');
  336. $append = '';
  337. // Setup redirect info.
  338. if ($tmpl) {
  339. $append .= '&tmpl='.$tmpl;
  340. }
  341. if ($layout) {
  342. $append .= '&layout='.$layout;
  343. }
  344. // Populate the row id from the session.
  345. $key = $table->getKeyName();
  346. //$data[$key] = $recordId;
  347. // The save2copy task needs to be handled slightly differently.
  348. if ($task == 'save2copy') {
  349. // Check-in the original row.
  350. if ($checkin && !$model->checkin($data[$key])) {
  351. // Check-in failed, go back to the item and display a notice.
  352. $message = JText::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError());
  353. $this->setRedirect('index.php?option='.$this->option.'&view='.$this->view_item.$append, $message, 'error');
  354. return false;
  355. }
  356. // Reset the ID and then treat the request as for Apply.
  357. $data[$key] = 0;
  358. $task = 'apply';
  359. }
  360. // Compat support.
  361. $append .= '&'.$key.'='.$data[$key];
  362. // Access check.
  363. if (!$this->allowSave($data)) {
  364. $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list, false));
  365. return JError::raiseWarning(403, JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'));
  366. }
  367. /*
  368. // Validate the posted data.
  369. // Sometimes the form needs some posted data, such as for plugins and modules.
  370. $form = $model->getForm($data, false);
  371. if (!$form) {
  372. JError::raiseError(500, $model->getError());
  373. return false;
  374. }
  375. // Test if the data is valid.
  376. $validData = $model->validate($form, $data);
  377. // Check for validation errors.
  378. if ($validData === false) {
  379. // Get the validation messages.
  380. $errors = $model->getErrors();
  381. // Push up to three validation messages out to the user.
  382. for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++) {
  383. if (JError::isError($errors[$i])) {
  384. $app->enqueueMessage($errors[$i]->getMessage(), 'notice');
  385. } else {
  386. $app->enqueueMessage($errors[$i], 'notice');
  387. }
  388. }
  389. // Save the data in the session.
  390. $app->setUserState($context.'.data', $data);
  391. // Redirect back to the edit screen.
  392. $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$append, false));
  393. return false;
  394. }
  395. */
  396. // Compat support.
  397. $validData = $data;
  398. // Attempt to save the data.
  399. if (!$model->save($validData)) {
  400. // Save the data in the session.
  401. //$app->setUserState($context.'.data', $validData);
  402. // Redirect back to the edit screen.
  403. $this->setMessage(JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()), 'error');
  404. $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$append, false));
  405. return false;
  406. }
  407. // Save succeeded, check-in the record.
  408. if ($checkin && !$model->checkin($validData[$key])) {
  409. // Save the data in the session.
  410. $app->setUserState($context.'.data', $validData);
  411. // Check-in failed, go back to the record and display a notice.
  412. $message = JText::sprintf('JError_Checkin_saved', $model->getError());
  413. $this->setRedirect('index.php?option='.$this->option.'&view='.$this->view_item.$append, $message, 'error');
  414. return false;
  415. }
  416. $this->setMessage(JText::_(($lang->hasKey($this->text_prefix.'_SAVE_SUCCESS') ? $this->text_prefix : 'JLIB_APPLICATION') . '_SAVE_SUCCESS'));
  417. // Redirect the user and adjust session state based on the chosen task.
  418. switch ($task) {
  419. case 'apply':
  420. // Set the record data in the session.
  421. //$app->setUserState($context.'.id', $model->getState($this->context.'.id'));
  422. //$app->setUserState($context.'.data', null);
  423. // Redirect back to the edit screen.
  424. $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$append, false));
  425. break;
  426. case 'save2new':
  427. // Clear the record id and data from the session.
  428. //$app->setUserState($context.'.id', null);
  429. //$app->setUserState($context.'.data', null);
  430. // Redirect back to the edit screen.
  431. $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_item.$append, false));
  432. break;
  433. default:
  434. // Clear the record id and data from the session.
  435. //$app->setUserState($context.'.id', null);
  436. //$app->setUserState($context.'.data', null);
  437. // Redirect to the list screen.
  438. $this->setRedirect(JRoute::_('index.php?option='.$this->option.'&view='.$this->view_list, false));
  439. break;
  440. }
  441. // Invoke the postSave method to allow for the child class to access the model.
  442. $this->postSaveHook($model);
  443. return true;
  444. }
  445. }