PageRenderTime 57ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/library/INEX/Controller/FrontEnd.php

https://github.com/slampt/IXP-Manager
PHP | 458 lines | 308 code | 46 blank | 104 comment | 29 complexity | 39600d45fcbe01d2c8cb7d0d3794e73a MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /*
  3. * Copyright (C) 2009-2011 Internet Neutral Exchange Association Limited.
  4. * All Rights Reserved.
  5. *
  6. * This file is part of IXP Manager.
  7. *
  8. * IXP Manager is free software: you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the Free
  10. * Software Foundation, version v2.0 of the License.
  11. *
  12. * IXP Manager is distributed in the hope that it will be useful, but WITHOUT
  13. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  15. * more details.
  16. *
  17. * You should have received a copy of the GNU General Public License v2.0
  18. * along with IXP Manager. If not, see:
  19. *
  20. * http://www.gnu.org/licenses/gpl-2.0.html
  21. */
  22. /**
  23. * INEX's version of Zend's Zend_Controller_Action implemented custom
  24. * functionality.
  25. *
  26. * All application controlers subclass this rather than Zend's version directly.
  27. *
  28. * @package INEX_Controller
  29. */
  30. class INEX_Controller_FrontEnd extends INEX_Controller_Action
  31. {
  32. /**
  33. * Do the user need to be authenticated to access the component?
  34. *
  35. * @var array Is an authenticated user required to access this?
  36. */
  37. protected $feAuthLevelRequired = User::AUTH_SUPERUSER;
  38. /**
  39. * Contains the configuration for the front end
  40. *
  41. * @var array Configuration for the front end
  42. */
  43. protected $frontend = null;
  44. /**
  45. * A dedicated namespace for this front end manager for storing information
  46. * between user actions.
  47. *
  48. * @var object Dedicated namespace for this controller
  49. */
  50. protected $feSession = null;
  51. /**
  52. * Override the INEX_Controller_Action's constructor (which is called
  53. * at the very beginning of this function anyway).
  54. *
  55. * @param object $request See Parent class constructer
  56. * @param object $response See Parent class constructer
  57. * @param object $invokeArgs See Parent class constructer
  58. */
  59. public function __construct(
  60. Zend_Controller_Request_Abstract $request,
  61. Zend_Controller_Response_Abstract $response,
  62. array $invokeArgs = null )
  63. {
  64. // call the parent's version where all the Zend majic happens
  65. parent::__construct( $request, $response, $invokeArgs );
  66. }
  67. /**
  68. * Preflight checks - authenticated users, etc
  69. */
  70. public function preDispatch()
  71. {
  72. // is this controller enabled?
  73. if( isset( $this->config['controller'][$this->getRequest()->getParam( 'controller' )]['enabled'] )
  74. && !$this->config['controller'][$this->getRequest()->getParam( 'controller' )]['enabled'] )
  75. {
  76. return( $this->_forward( 'controller-disabled', 'index' ) );
  77. }
  78. if( $this->feAuthLevelRequired != User::AUTH_PUBLIC )
  79. {
  80. if( isset( $this->frontend['authLevels'][$this->getRequest()->getActionName()] )
  81. && $this->frontend['authLevels'][$this->getRequest()->getActionName()] == User::AUTH_PUBLIC
  82. )
  83. {
  84. // do nothing -> action has public access
  85. }
  86. else if( !$this->auth->hasIdentity() )
  87. {
  88. // record the page we wanted
  89. $this->session->postAuthRedirect = $this->_request->getPathInfo();
  90. $this->_redirect( 'auth/login' );
  91. }
  92. else
  93. {
  94. if( isset( $this->frontend['authLevels'][$this->getRequest()->getActionName()] ) )
  95. $authRequired = $this->frontend['authLevels'][$this->getRequest()->getActionName()];
  96. else
  97. $authRequired = $this->feAuthLevelRequired;
  98. if( $this->identity['user']['privs'] < $authRequired )
  99. {
  100. $this->getLogger()->alert( "User {$this->identity['username']} was denied access to {$this->frontend['name']}" );
  101. $this->view->message = new INEX_Message( "You are not authorised to view the requested page!", "alert" );
  102. return( $this->_forward( 'index', 'index' ) );
  103. }
  104. }
  105. }
  106. }
  107. /**
  108. * Validation function that is called as part of the subclasses set up.
  109. *
  110. * This should check that all necessary variables are set.
  111. */
  112. final protected function feInit()
  113. {
  114. if( $this->frontend['name'] == null )
  115. throw new Exception( "You must set a name for the controller in the init() method." );
  116. if( $this->frontend['model'] == null )
  117. throw new Exception( "You must set the model in the init() method for the {$this->feName} controller." );
  118. if( $this->frontend['columns'] == null )
  119. throw new Exception( "You must set the view's column configuration in the init() method for the {$this->feName} controller." );
  120. $this->frontend['controller'] = $this->getRequest()->getParam( 'controller' );
  121. $this->feSession = $this->_bootstrap->getResource( 'namespace' );
  122. $this->view->frontend = $this->frontend;
  123. }
  124. public function indexAction()
  125. {
  126. $this->_forward( 'list' );
  127. }
  128. public function addAction()
  129. {
  130. // is this an attempt to edit?
  131. if( $this->getRequest()->getParam( 'id' ) !== NULL && is_numeric( $this->getRequest()->getParam( 'id' ) ) )
  132. {
  133. $isEdit = true;
  134. // is the ID valid?
  135. if( !( $object = Doctrine::getTable( $this->frontend['model'] )->find( $this->getRequest()->getParam( 'id' ) ) ) )
  136. {
  137. $this->view->message = new INEX_Message( 'No entry with ID: ' . $this->getRequest()->getParam( 'id' ) . " exists.", "failure" );
  138. return( $this->_forward( 'list' ) );
  139. }
  140. $this->view->object = $object;
  141. $form = $this->getForm( null, $isEdit );
  142. $form->assignModelToForm( $object, $this );
  143. $form->setAction( Zend_Controller_Front::getInstance()->getBaseUrl() . '/' . $this->getRequest()->getParam( 'controller' ) . '/edit/id/' . $this->getRequest()->getParam( 'id' ) );
  144. $form->getElement( 'commit' )->setLabel( 'Save Changes' );
  145. }
  146. else
  147. {
  148. $isEdit = false;
  149. $form = $this->getForm( null, $isEdit );
  150. $form->setAction( Zend_Controller_Front::getInstance()->getBaseUrl() . '/' . $this->getRequest()->getParam( 'controller' ) . "/add" );
  151. $object = new $this->frontend['model'];
  152. }
  153. $this->view->isEdit = $isEdit;
  154. if( $this->getRequest()->getParam( 'return' ) !== null )
  155. $form->addElement( $form->createElement( 'hidden', 'return' )->setValue( $this->getRequest()->getParam( 'return' ) ) );
  156. // optional extra pre-validation code
  157. if( method_exists( $this, 'formPrevalidate' ) )
  158. $this->formPrevalidate( $form, $isEdit, $object );
  159. if( $this->inexGetPost( 'commit' ) !== null && $form->isValid( $_POST ) )
  160. {
  161. do
  162. {
  163. try
  164. {
  165. // non-standard validation checks
  166. if( !$isEdit )
  167. {
  168. if( method_exists( $this, 'formValidateForAdd' ) )
  169. if( $this->formValidateForAdd( $form ) === false )
  170. break;
  171. }
  172. $form->assignFormToModel( $object, $this, $isEdit );
  173. if( method_exists( $this, 'addEditPreSave' ) )
  174. $this->addEditPreSave( $object, $isEdit, $form );
  175. $object->save();
  176. if( method_exists( $this, 'addEditPostSave' ) )
  177. $this->addEditPostSave( $object, $isEdit, $form );
  178. if( $isEdit )
  179. {
  180. $this->getLogger()->notice( $this->getName() . ' edited' );
  181. $this->session->message = new INEX_Message( $this->getName() . ' edited', "success" );
  182. }
  183. else
  184. {
  185. $this->getLogger()->notice( 'New ' . $this->getName() . ' created' );
  186. $this->session->message = new INEX_Message( $this->getName() . ' added', "success" );
  187. }
  188. if( $this->getRequest()->getParam( 'return' ) !== null )
  189. $this->_redirect( $this->getRequest()->getParam( 'return' ) . '/objectid/' . $object['id'] );
  190. else if( method_exists( $this, '_addEditSetReturnOnSuccess' ) )
  191. $this->_redirect( $this->_addEditSetReturnOnSuccess( $form, $object ) );
  192. else
  193. $this->_redirect( $this->getRequest()->getParam( 'controller' ) );
  194. }
  195. catch( Exception $e )
  196. {
  197. Zend_Registry::set( 'exception', $e );
  198. return( $this->_forward( 'error', 'error' ) );
  199. }
  200. }while( false );
  201. }
  202. if( method_exists( $this, 'addEditPreDisplay' ) )
  203. $this->addEditPreDisplay( $form, $object );
  204. $this->view->form = $form->render( $this->view );
  205. $this->view->object = $object;
  206. if( $this->view->templateExists( $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'addEdit-preamble.tpl' ) )
  207. $this->view->hasPreContent = $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'addEdit-preamble.tpl';
  208. if( $this->view->templateExists( $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'addEdit-postamble.tpl' ) )
  209. $this->view->hasPostContent = $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'addEdit-postamble.tpl';
  210. if( $this->view->templateExists( $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'addEdit.tpl' ) )
  211. $this->view->display( $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'addEdit.tpl' );
  212. else
  213. $this->view->display( 'frontend' . DIRECTORY_SEPARATOR . 'addEdit.tpl' );
  214. }
  215. public function editAction()
  216. {
  217. $this->_forward( 'add' );
  218. }
  219. public function viewAction()
  220. {
  221. $this->view->perspective = $this->getRequest()->getParam( 'perspective' );
  222. if( $this->getRequest()->getParam( 'id' ) !== NULL && is_numeric( $this->getRequest()->getParam( 'id' ) ) )
  223. {
  224. // is the ID valid?
  225. if( !( $object = Doctrine::getTable( $this->frontend['model'] )->find( $this->getRequest()->getParam( 'id' ) ) ) )
  226. {
  227. $view = '<h1>Error</h1><p>No entry with ID: ' . $this->getRequest()->getParam( 'id' ) . ' exists.</p>';
  228. }
  229. else
  230. {
  231. $this->view->object = $object;
  232. }
  233. }
  234. $this->view->display( 'frontend' . DIRECTORY_SEPARATOR . 'view.tpl' );
  235. }
  236. /**
  237. * A generic action to delete an element of a database (as represented
  238. * by a Doctrine model) via Smarty templates.
  239. *
  240. * This method calls preDelete before the deletion.
  241. *
  242. * It then calls postDelete() after the deletion (assuming it succeeds).
  243. *
  244. * To capture errors, pre and postDelete() should throw an exception.
  245. *
  246. */
  247. public function deleteAction()
  248. {
  249. // is the ID valid?
  250. if( !( $object = Doctrine::getTable( $this->getModelName() )->find( $this->getRequest()->getParam( 'id' ) ) ) )
  251. {
  252. $this->view->message = new INEX_Message( 'No such object with ID: ' . $this->getRequest()->getParam( 'id' ), "error" );
  253. return( $this->_forward( 'list' ) );
  254. }
  255. $this->preDelete( $object );
  256. if( $object->delete() )
  257. {
  258. $this->getLogger()->notice( 'Object with ID: ' . $this->getRequest()->getParam( 'id' ) . " deleted from {$this->frontend['model']}" );
  259. $this->view->message = new INEX_Message( "Object with ID " . $this->getRequest()->getParam( 'id' ) . " deleted", "success" );
  260. $this->postDelete();
  261. }
  262. else
  263. {
  264. $this->getLogger()->error( "Object could not be deleted" );
  265. $this->view->message = new INEX_Message( "Error deleting object", "error" );
  266. }
  267. if( $this->getRequest()->getParam( 'return' ) !== null )
  268. $this->_redirect( 'http' . ( isset( $_SERVER['HTTPS'] ) ? 's' : '' ) . '://' . $_SERVER['SERVER_NAME'] . $this->getRequest()->getParam( 'return' ) );
  269. else if( method_exists( $this, '_deleteSetReturnOnSuccess' ) )
  270. $this->_redirect( $this->_deleteSetReturnOnSuccess() );
  271. else
  272. return( $this->_forward( 'list' ) );
  273. }
  274. /**
  275. * A generic action to list the elements of a database (as represented
  276. * by a Doctrine model) via Smarty templates.
  277. */
  278. public function listAction()
  279. {
  280. if( !( $this->view->rows = $this->_customList() ) )
  281. {
  282. $dataQuery = Doctrine_Query::create()
  283. ->from( $this->frontend['model'] . ' x' );
  284. if( isset( $this->frontend['columns']['sortDefaults'] ) )
  285. {
  286. $order = '';
  287. if( isset( $this->frontend['columns']['sortDefaults']['order'] ) )
  288. $order = strtoupper( $this->frontend['columns']['sortDefaults']['order'] );
  289. $dataQuery->orderBy( "{$this->frontend['columns']['sortDefaults']['column']} $order" );
  290. }
  291. $dataQuery = $this->_preList( $dataQuery );
  292. $this->view->rows = $dataQuery->execute();
  293. }
  294. $this->view->feSession = $this->feSession;
  295. $this->view->frontend = $this->frontend;
  296. if( $this->view->templateExists( $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'customContextMenu.html.tpl' ) )
  297. $this->view->hasCustomContextMenu = $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'customContextMenu';
  298. if( $this->view->templateExists( $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'list-pretable.tpl' ) )
  299. $this->view->hasPreContent = $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'list-pretable.tpl';
  300. if( $this->view->templateExists( $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'postContent.tpl' ) )
  301. $this->view->hasPostContent = $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'postContent.tpl';
  302. if( $this->view->templateExists( $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'list.tpl' ) )
  303. $this->view->display( $this->getRequest()->getParam( 'controller' ) . DIRECTORY_SEPARATOR . 'list.tpl' );
  304. else
  305. $this->view->display( 'frontend' . DIRECTORY_SEPARATOR . 'list.tpl' );
  306. }
  307. protected function _customList()
  308. {
  309. return false;
  310. }
  311. /**
  312. * A function executed before the list action queries the database.
  313. *
  314. * You can add clauses to the query or perform other queries and assign data to the
  315. * view.
  316. *
  317. * @param Doctrine_Query $dataQuery The query being formed to which you can add clauses. Just be sure to return it irregardless!
  318. * @return You *must* return the $dataQuery object.
  319. */
  320. protected function _preList( $dataQuery )
  321. {
  322. return $dataQuery;
  323. }
  324. protected function getForm( $options = null, $isEdit = false )
  325. {
  326. $formName = "INEX_Form_{$this->frontend['name']}";
  327. if( $this->getRequest()->getParam( 'return' ) !== null )
  328. $cancelLocation = 'http' . ( isset( $_SERVER['HTTPS'] ) ? 's' : '' ) . '://' . $_SERVER['SERVER_NAME'] . $this->getRequest()->getParam( 'return' );
  329. else
  330. $cancelLocation = 'http' . ( isset( $_SERVER['HTTPS'] ) ? 's' : '' ) . '://' . $_SERVER['SERVER_NAME'] . Zend_Controller_Front::getInstance()->getBaseUrl() . '/' . $this->getRequest()->getParam( 'controller' ) . '/list';
  331. return new $formName( $options, $isEdit, $cancelLocation );
  332. }
  333. /**
  334. * Returns the model name.
  335. *
  336. * Each controller extending the FrontEnd class represents a Doctrine model. This returns the name of that model.
  337. *
  338. * @return string the model name
  339. */
  340. public function getModelName()
  341. {
  342. return $this->frontend['model'];
  343. }
  344. /**
  345. * Returns the controller name.
  346. *
  347. * Each controller extending the FrontEnd class represents a Doctrine model. This returns the name that we use for the frontend to describe the model.
  348. *
  349. * @return string the name
  350. */
  351. public function getName()
  352. {
  353. return $this->frontend['name'];
  354. }
  355. /**
  356. * Base method to allow for pre-deletion hooks.
  357. */
  358. protected function preDelete()
  359. {}
  360. /**
  361. * Base method to allow for post-deletion hooks.
  362. */
  363. protected function postDelete()
  364. {}
  365. /**
  366. * Base method to allow for pre-add/edit save hooks.
  367. *
  368. * @param Doctrine_Record $object The object being built for adding or edited
  369. * @param bool $isEdit True if this is an edit, false if it's an add
  370. * @param Zend_Form $form The submitted add / edit form
  371. */
  372. protected function addEditPreSave( $object, $isEdit, $form )
  373. {}
  374. }