PageRenderTime 49ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/pkp/classes/handler/PKPHandler.inc.php

https://github.com/lib-uoguelph-ca/ocs
PHP | 281 lines | 123 code | 30 blank | 128 comment | 27 complexity | 8292efdacabb9c19b0b79c02c6d50687 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /**
  3. * @file classes/core/PKPHandler.inc.php
  4. *
  5. * Copyright (c) 2000-2012 John Willinsky
  6. * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
  7. *
  8. * @package core
  9. * @class PKPHandler
  10. *
  11. * Base request handler abstract class.
  12. *
  13. */
  14. import('handler.validation.HandlerValidator');
  15. import('handler.validation.HandlerValidatorCustom');
  16. class PKPHandler {
  17. /**
  18. * @var string identifier of the controller instance - must be unique
  19. * among all instances of a given controller type.
  20. */
  21. var $_id;
  22. /** @var Dispatcher, mainly needed for cross-router url construction */
  23. var $_dispatcher;
  24. /** @var array validation checks for this page*/
  25. var $_checks;
  26. /**
  27. * Constructor
  28. */
  29. function PKPHandler() {
  30. $this->_checks = array();
  31. // enforce SSL sitewide
  32. $this->addCheck(new HandlerValidatorCustom($this, null, null, null, create_function('$forceSSL, $protocol', 'if ($forceSSL && $protocol != \'https\') Request::redirectSSL(); else return true;'), array(Config::getVar('security', 'force_ssl'), Request::getProtocol())));
  33. }
  34. //
  35. // Setters and Getters
  36. //
  37. /**
  38. * Set the controller id
  39. * @param $id string
  40. */
  41. function setId($id) {
  42. $this->_id = $id;
  43. }
  44. /**
  45. * Get the controller id
  46. * @return string
  47. */
  48. function getId() {
  49. return $this->_id;
  50. }
  51. /**
  52. * Get the dispatcher
  53. *
  54. * NB: The dispatcher will only be set after
  55. * handler instantiation. Calling getDispatcher()
  56. * in the constructor will fail.
  57. *
  58. * @return Dispatcher
  59. */
  60. function &getDispatcher() {
  61. assert(!is_null($this->_dispatcher));
  62. return $this->_dispatcher;
  63. }
  64. /**
  65. * Set the dispatcher
  66. * @param $dispatcher PKPDispatcher
  67. */
  68. function setDispatcher(&$dispatcher) {
  69. $this->_dispatcher =& $dispatcher;
  70. }
  71. /**
  72. * Fallback method in case request handler does not implement index method.
  73. */
  74. function index() {
  75. $dispatcher =& $this->getDispatcher();
  76. if (isset($dispatcher)) $dispatcher->handle404();
  77. else Dispatcher::handle404(); // For old-style handlers
  78. }
  79. /**
  80. * Add a validation check to the handler.
  81. * @param $handlerValidator HandlerValidator
  82. */
  83. function addCheck($handlerValidator) {
  84. $this->_checks[] =& $handlerValidator;
  85. }
  86. /**
  87. * Perform request access validation based on security settings.
  88. *
  89. * This method will be called once for every request only.
  90. *
  91. * NB (non-page controllers only): The component router will call
  92. * this method automatically thereby enforcing validation. This
  93. * method will be call directly before the initialize() method.
  94. *
  95. * @param $requiredContexts array
  96. * @param $request Request
  97. */
  98. function validate($requiredContexts = null, $request = null) {
  99. // FIXME: for backwards compatibility only - remove when request/router refactoring complete
  100. if (!isset($request)) {
  101. if (Config::getVar('debug', 'deprecation_warnings')) trigger_error('Deprecated function call.');
  102. $request =& Registry::get('request');
  103. }
  104. foreach ($this->_checks as $check) {
  105. // WARNING: This line is for PHP4 compatibility when
  106. // instantiating handlers without reference. Should not
  107. // be removed or otherwise used.
  108. // See <http://pkp.sfu.ca/wiki/index.php/Information_for_Developers#Use_of_.24this_in_the_constructor>
  109. // for a similar proplem.
  110. $check->_setHandler($this);
  111. // check should redirect on fail and continue on pass
  112. // default action is to redirect to the index page on fail
  113. if ( !$check->isValid() ) {
  114. $router =& $request->getRouter();
  115. if (is_a($router, 'PKPPageRouter')) {
  116. if ( $check->redirectToLogin ) {
  117. Validation::redirectLogin();
  118. } else {
  119. // An unauthorized page request will be re-routed
  120. // to the index page.
  121. $request->redirect(null, 'index');
  122. }
  123. } else {
  124. // Sub-controller requests should always be sufficiently
  125. // authorized and valid when being called from a
  126. // page. Otherwise we either hit a development error
  127. // or somebody is trying to fake component calls.
  128. // In both cases raising a fatal error is appropriate.
  129. // NB: The check's redirection flag will be ignored
  130. // for sub-controller requests.
  131. if (!empty($check->message)) {
  132. fatalError($check->message);
  133. } else {
  134. fatalError('Unauthorized access!');
  135. }
  136. }
  137. }
  138. }
  139. return true;
  140. }
  141. /**
  142. * Subclasses can override this method to configure the
  143. * handler.
  144. *
  145. * NB: This method will be called after validation and
  146. * authorization.
  147. *
  148. * @param $request PKPRequest
  149. */
  150. function initialize(&$request) {
  151. // Set the controller id to the requested
  152. // page (page routing) or component name
  153. // (component routing) by default.
  154. $router =& $request->getRouter();
  155. if (is_a($router, 'PKPComponentRouter')) {
  156. $componentId = $router->getRequestedComponent($request);
  157. // Create a somewhat compressed but still globally unique
  158. // and human readable component id.
  159. // Example: "grid.citation.CitationGridHandler"
  160. // becomes "grid-citation-citationgrid"
  161. $componentId = str_replace('.', '-', String::strtolower(String::substr($componentId, 0, -7)));
  162. $this->setId($componentId);
  163. } else {
  164. assert(is_a($router, 'PKPPageRouter'));
  165. $this->setId($router->getRequestedPage($request));
  166. }
  167. }
  168. /**
  169. * Return the DBResultRange structure and misc. variables describing the current page of a set of pages.
  170. * @param $rangeName string Symbolic name of range of pages; must match the Smarty {page_list ...} name.
  171. * @param $contextData array If set, this should contain a set of data that are required to
  172. * define the context of this request (for maintaining page numbers across requests).
  173. * To disable persistent page contexts, set this variable to null.
  174. * @return array ($pageNum, $dbResultRange)
  175. */
  176. function &getRangeInfo($rangeName, $contextData = null) {
  177. //FIXME: is there any way to get around calling a Request (instead of a PKPRequest) here?
  178. $context =& Request::getContext();
  179. $pageNum = PKPRequest::getUserVar($rangeName . 'Page');
  180. if (empty($pageNum)) {
  181. $session =& PKPRequest::getSession();
  182. $pageNum = 1; // Default to page 1
  183. if ($session && $contextData !== null) {
  184. // See if we can get a page number from a prior request
  185. $contextHash = PKPHandler::hashPageContext($contextData);
  186. if (PKPRequest::getUserVar('clearPageContext')) {
  187. // Explicitly clear the old page context
  188. $session->unsetSessionVar("page-$contextHash");
  189. } else {
  190. $oldPage = $session->getSessionVar("page-$contextHash");
  191. if (is_numeric($oldPage)) $pageNum = $oldPage;
  192. }
  193. }
  194. } else {
  195. $session =& PKPRequest::getSession();
  196. if ($session && $contextData !== null) {
  197. // Store the page number
  198. $contextHash = PKPHandler::hashPageContext($contextData);
  199. $session->setSessionVar("page-$contextHash", $pageNum);
  200. }
  201. }
  202. if ($context) $count = $context->getSetting('itemsPerPage');
  203. if (!isset($count)) $count = Config::getVar('interface', 'items_per_page');
  204. import('db.DBResultRange');
  205. if (isset($count)) $returner = new DBResultRange($count, $pageNum);
  206. else $returner = new DBResultRange(-1, -1);
  207. return $returner;
  208. }
  209. function setupTemplate() {
  210. AppLocale::requireComponents(array(
  211. LOCALE_COMPONENT_PKP_COMMON,
  212. LOCALE_COMPONENT_PKP_USER
  213. ));
  214. if (defined('LOCALE_COMPONENT_APPLICATION_COMMON')) {
  215. AppLocale::requireComponents(array(LOCALE_COMPONENT_APPLICATION_COMMON));
  216. }
  217. }
  218. /**
  219. * Generate a unique-ish hash of the page's identity, including all
  220. * context that differentiates it from other similar pages (e.g. all
  221. * articles vs. all articles starting with "l").
  222. * @param $contextData array A set of information identifying the page
  223. * @return string hash
  224. */
  225. function hashPageContext($contextData = array()) {
  226. return md5(
  227. implode(',', Request::getRequestedContextPath()) . ',' .
  228. Request::getRequestedPage() . ',' .
  229. Request::getRequestedOp() . ',' .
  230. serialize($contextData)
  231. );
  232. }
  233. /**
  234. * Get a list of pages that don't require login, even if the system does
  235. * @return array
  236. */
  237. function getLoginExemptions() {
  238. return array('user', 'login', 'help');
  239. }
  240. /**
  241. * This method returns all operation names that can be called from remote.
  242. * FIXME: Currently only used for component handlers. Use this for page
  243. * handlers as well and remove the page-specific index.php whitelist.
  244. */
  245. function getRemoteOperations() {
  246. // Whitelist approach: by default we don't
  247. // allow any remote access at all.
  248. return array();
  249. }
  250. }
  251. ?>