Open Monograph Press  1.1
 All Classes Namespaces Functions Variables Groups Pages
PKPPageRouter.inc.php
1 <?php
2 
16 define('ROUTER_DEFAULT_PAGE', './pages/index/index.php');
17 define('ROUTER_DEFAULT_OP', 'index');
18 
19 import('lib.pkp.classes.core.PKPRouter');
20 
21 class PKPPageRouter extends PKPRouter {
23  var $_installationPages = array('install', 'help', 'header', 'sidebar');
24 
25  //
26  // Internal state cache variables
27  // NB: Please do not access directly but
28  // only via their respective getters/setters
29  //
31  var $_page;
33  var $_op;
35  var $_indexUrl;
38 
42  function PKPPageRouter() {
43  parent::PKPRouter();
44  }
45 
50  function getInstallationPages() {
52  }
53 
58  function getCacheablePages() {
59  // Can be overridden by sub-classes.
60  return array();
61  }
62 
70  function isCacheable($request, $testOnly = false) {
71  if (defined('SESSION_DISABLE_INIT') && !$testOnly) return false;
72  if (!Config::getVar('general', 'installed')) return false;
73  if (!empty($_POST) || Validation::isLoggedIn()) return false;
74 
75  if ($request->isPathInfoEnabled()) {
76  if (!empty($_GET)) return false;
77  } else {
78  $application = $this->getApplication();
79  $ok = array_merge($application->getContextList(), array('page', 'op', 'path'));
80  if (!empty($_GET) && count(array_diff(array_keys($_GET), $ok)) != 0) {
81  return false;
82  }
83  }
84 
85  if (in_array($this->getRequestedPage($request), $this->getCacheablePages())) return true;
86 
87  return false;
88  }
89 
95  function getRequestedPage($request) {
96  if (!isset($this->_page)) {
97  $this->_page = $this->_getRequestedUrlParts(array('Core', 'getPage'), $request);
98  }
99  return $this->_page;
100  }
101 
107  function getRequestedOp($request) {
108  if (!isset($this->_op)) {
109  $this->_op = $this->_getRequestedUrlParts(array('Core', 'getOp'), $request);
110  }
111  return $this->_op;
112  }
113 
119  function getRequestedArgs($request) {
120  return $this->_getRequestedUrlParts(array('Core', 'getArgs'), $request);
121  }
123 
124  //
125  // Implement template methods from PKPRouter
126  //
130  function getCacheFilename($request) {
131  if (!isset($this->_cacheFilename)) {
132  if ($request->isPathInfoEnabled()) {
133  $id = isset($_SERVER['PATH_INFO'])?$_SERVER['PATH_INFO']:'index';
134  $id .= '-' . AppLocale::getLocale();
135  } else {
136  $id = '';
137  $application = $this->getApplication();
138  foreach($application->getContextList() as $contextName) {
139  $id .= $request->getUserVar($contextName) . '-';
140  }
141  $id .= $request->getUserVar('page') . '-' . $request->getUserVar('op') . '-' . $request->getUserVar('path') . '-' . AppLocale::getLocale();
142  }
143  $path = Core::getBaseDir();
144  $this->_cacheFilename = $path . '/cache/wc-' . md5($id) . '.html';
145  }
146  return $this->_cacheFilename;
147  }
148 
152  function route($request) {
153  // Determine the requested page and operation
154  $page = $this->getRequestedPage($request);
155  $op = $this->getRequestedOp($request);
156 
157  // If the application has not yet been installed we only
158  // allow installer pages to be displayed.
159  if (!Config::getVar('general', 'installed')) {
160  define('SESSION_DISABLE_INIT', 1);
161  if (!in_array($page, $this->getInstallationPages())) {
162  // A non-installation page was called although
163  // the system is not yet installed. Redirect to
164  // the installation page.
165  $redirectMethod = array($request, 'redirect');
166 
167  // The correct redirection for the installer page
168  // depends on the context depth of this application.
169  $application = $this->getApplication();
170  $contextDepth = $application->getContextDepth();
171  // The context will be filled with all nulls
172  $redirectArguments = array_pad(array('install'), - $contextDepth - 1, null);
173 
174  // Call request's redirect method
175  call_user_func_array($redirectMethod, $redirectArguments);
176  }
177  }
178 
179  // Determine the page index file. This file contains the
180  // logic to resolve a page to a specific handler class.
181  $sourceFile = sprintf('pages/%s/index.php', $page);
182 
183  // If a hook has been registered to handle this page, give it the
184  // opportunity to load required resources and set HANDLER_CLASS.
185  if (!HookRegistry::call('LoadHandler', array(&$page, &$op, &$sourceFile))) {
186  if (file_exists($sourceFile)) require('./'.$sourceFile);
187  elseif (file_exists(PKP_LIB_PATH . DIRECTORY_SEPARATOR . $sourceFile))
188  require('.' . DIRECTORY_SEPARATOR . PKP_LIB_PATH . DIRECTORY_SEPARATOR . $sourceFile);
189  elseif (empty($page)) require(ROUTER_DEFAULT_PAGE);
190  else {
191  $dispatcher = $this->getDispatcher();
192  $dispatcher->handle404();
193  }
194  }
195 
196  if (!defined('SESSION_DISABLE_INIT')) {
197  // Initialize session
199  }
200 
201  // Call the selected handler's index operation if
202  // no operation was defined in the request.
203  if (empty($op)) $op = ROUTER_DEFAULT_OP;
204 
205  // Redirect to 404 if the operation doesn't exist
206  // for the handler.
207  $methods = array();
208  if (defined('HANDLER_CLASS')) $methods = get_class_methods(HANDLER_CLASS);
209  if (!in_array($op, $methods)) {
210  $dispatcher = $this->getDispatcher();
211  $dispatcher->handle404();
212  }
213 
214  // Instantiate the handler class
215  $handlerClass = HANDLER_CLASS;
216  $handler = new $handlerClass($request);
217 
218  // Authorize and initialize the request but don't call the
219  // validate() method on page handlers.
220  // FIXME: We should call the validate() method for page
221  // requests also (last param = true in the below method
222  // call) once we've made sure that all validate() calls can
223  // be removed from handler operations without damage (i.e.
224  // they don't depend on actions being performed before the
225  // call to validate().
226  $args = $this->getRequestedArgs($request);
227  $serviceEndpoint = array($handler, $op);
228  $this->_authorizeInitializeAndCallRequest($serviceEndpoint, $request, $args, false);
229  }
230 
234  function url($request, $newContext = null, $page = null, $op = null, $path = null,
235  $params = null, $anchor = null, $escape = false) {
236  $pathInfoEnabled = $request->isPathInfoEnabled();
237 
238  //
239  // Base URL and Context
240  //
241  $newContext = $this->_urlCanonicalizeNewContext($newContext);
242  $baseUrlAndContext = $this->_urlGetBaseAndContext($request, $newContext);
243  $baseUrl = array_shift($baseUrlAndContext);
244  $context = $baseUrlAndContext;
245 
246  //
247  // Additional path info
248  //
249  if (empty($path)) {
250  $additionalPath = array();
251  } else {
252  if (is_array($path)) {
253  $additionalPath = array_map('rawurlencode', $path);
254  } else {
255  $additionalPath = array(rawurlencode($path));
256  }
257 
258  // If path info is disabled then we have to
259  // encode the path as query parameters.
260  if (!$pathInfoEnabled) {
261  $pathKey = $escape?'path%5B%5D=':'path[]=';
262  foreach($additionalPath as $key => $pathElement) {
263  $additionalPath[$key] = $pathKey.$pathElement;
264  }
265  }
266  }
267 
268  //
269  // Page and Operation
270  //
271 
272  // Are we in a page request?
273  $currentRequestIsAPageRequest = is_a($request->getRouter(), 'PKPPageRouter');
274 
275  // Determine the operation
276  if ($op) {
277  // If an operation has been explicitly set then use it.
278  $op = rawurlencode($op);
279  } else {
280  // No operation has been explicitly set so let's determine a sensible
281  // default operation.
282  if (empty($newContext) && empty($page) && $currentRequestIsAPageRequest) {
283  // If we remain in the existing context and on the existing page then
284  // we will default to the current operation. We can only determine a
285  // current operation if the current request is a page request.
286  $op = $this->getRequestedOp($request);
287  } else {
288  // If a new context (or page) has been set then we'll default to the
289  // index operation within the new context (or on the new page).
290  if (empty($additionalPath)) {
291  // If no additional path is set we can simply leave the operation
292  // undefined which automatically defaults to the index operation
293  // but gives shorter (=nicer) URLs.
294  $op = null;
295  } else {
296  // If an additional path is set then we have to explicitly set the
297  // index operation to disambiguate the path info.
298  $op = 'index';
299  }
300  }
301  }
302 
303  // Determine the page
304  if ($page) {
305  // If a page has been explicitly set then use it.
306  $page = rawurlencode($page);
307  } else {
308  // No page has been explicitly set so let's determine a sensible default page.
309  if (empty($newContext) && $currentRequestIsAPageRequest) {
310  // If we remain in the existing context then we will default to the current
311  // page. We can only determine a current page if the current request is a
312  // page request.
313  $page = $this->getRequestedPage($request);
314  } else {
315  // If a new context has been set then we'll default to the index page
316  // within the new context.
317  if (empty($op)) {
318  // If no explicit operation is set we can simply leave the page
319  // undefined which automatically defaults to the index page but gives
320  // shorter (=nicer) URLs.
321  $page = null;
322  } else {
323  // If an operation is set then we have to explicitly set the index
324  // page to disambiguate the path info.
325  $page = 'index';
326  }
327  }
328  }
329 
330  //
331  // Additional query parameters
332  //
333  $additionalParameters = $this->_urlGetAdditionalParameters($request, $params, $escape);
334 
335  //
336  // Anchor
337  //
338  $anchor = (empty($anchor) ? '' : '#'.rawurlencode($anchor));
339 
340  //
341  // Assemble URL
342  //
343  if ($pathInfoEnabled) {
344  // If path info is enabled then context, page,
345  // operation and additional path go into the
346  // path info.
347  $pathInfoArray = $context;
348  if (!empty($page)) {
349  $pathInfoArray[] = $page;
350  if (!empty($op)) {
351  $pathInfoArray[] = $op;
352  }
353  }
354  $pathInfoArray = array_merge($pathInfoArray, $additionalPath);
355 
356  // Query parameters
357  $queryParametersArray = $additionalParameters;
358  } else {
359  // If path info is disabled then context, page,
360  // operation and additional path are encoded as
361  // query parameters.
362  $pathInfoArray = array();
363 
364  // Query parameters
365  $queryParametersArray = $context;
366  if (!empty($page)) {
367  $queryParametersArray[] = "page=$page";
368  if (!empty($op)) {
369  $queryParametersArray[] = "op=$op";
370  }
371  }
372  $queryParametersArray = array_merge($queryParametersArray, $additionalPath, $additionalParameters);
373  }
374 
375  return $this->_urlFromParts($baseUrl, $pathInfoArray, $queryParametersArray, $anchor, $escape);
376  }
377 
381  function handleAuthorizationFailure($request, $authorizationMessage) {
382  // Redirect to the authorization denied page.
383  if (!$request->getUser()) Validation::redirectLogin();
384  $request->redirect(null, 'user', 'authorizationDenied', null, array('message' => $authorizationMessage));
385  }
386 
391  function redirectHome($request) {
392  $userGroupDao = DAORegistry::getDAO('UserGroupDAO');
393  $user = $request->getUser();
394  $userId = $user->getId();
395 
396  if ($context = $this->getContext($request, 1)) {
397  // The user is in the context, see if they have zero or one roles only
398  $userGroups = $userGroupDao->getByUserId($userId, $context->getId());
399  if($userGroups->getCount() <= 1) {
400  $userGroup = $userGroups->next();
401  if (!$userGroup || $userGroup->getRoleId() == ROLE_ID_READER) $request->redirect(null, 'index');
402  }
403  $request->redirect(null, 'dashboard');
404  } else {
405  // The user is at the site context, check to see if they are
406  // only registered in one place w/ one role
407  $userGroups = $userGroupDao->getByUserId($userId, CONTEXT_ID_NONE);
408 
409  if($userGroups->getCount() == 1) {
410  $contextDao = Application::getContextDAO();
411  $userGroup = $userGroups->next();
412  $context = $contextDao->getById($userGroup->getContextId());
413  if (!isset($context)) $request->redirect('index', 'index');
414  if ($userGroup->getRoleId() == ROLE_ID_READER) $request->redirect(null, 'index');
415  }
416  $request->redirect('index', 'index');
417  }
418  }
419 
420 
421  //
422  // Private helper methods.
423  //
432  private function _getRequestedUrlParts($callback, &$request) {
433  $url = null;
434  assert(is_a($request->getRouter(), 'PKPPageRouter'));
435  $isPathInfoEnabled = $request->isPathInfoEnabled();
436 
437  if ($isPathInfoEnabled) {
438  if (isset($_SERVER['PATH_INFO'])) {
439  $url = $_SERVER['PATH_INFO'];
440  }
441  } else {
442  $url = $request->getCompleteUrl();
443  }
444 
445  $userVars = $request->getUserVars();
446  return call_user_func_array($callback, array($url, $isPathInfoEnabled, $userVars));
447  }
448 }
449 
450 ?>
static & getDAO($name, $dbconn=null)
getRequestedArgs($request)
getRequestedPage($request)
& getContext($request, $requestedContextLevel=1)
getRequestedOp($request)
_urlCanonicalizeNewContext($newContext)
static getLocale()
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
_urlGetBaseAndContext($request, $newContext=array())
static redirectLogin($message=null)
_urlFromParts($baseUrl, $pathInfoArray=array(), $queryParametersArray=array(), $anchor= '', $escape=false)
_urlGetAdditionalParameters($request, $params=null, $escape=true)
static call($hookName, $args=null)
getCacheFilename($request)
handleAuthorizationFailure($request, $authorizationMessage)
url($request, $newContext=null, $page=null, $op=null, $path=null, $params=null, $anchor=null, $escape=false)
_authorizeInitializeAndCallRequest(&$serviceEndpoint, $request, &$args, $validate=true)
static getBaseDir()
Definition: Core.inc.php:37
isCacheable($request, $testOnly=false)
static getContextDAO()
Basic router class that has functionality common to all routers.
& getApplication()
Class mapping an HTTP request to a handler or context.
redirectHome($request)