drupal_access_denied handler should know what page was requested

moshe weitzman - November 29, 2004 - 02:37
Project:Drupal
Version:x.y.z
Component:menu system
Category:feature request
Priority:minor
Assigned:Unassigned
Status:closed
Description

the ability to specify a path for handling 'access denied' pages is nice. it would be helpful if this handler could learn the path which was originally requested by the user. currently, $_GET['q'] is overwritten with the path of the handler and thus the handler is ignorant.

#1

moshe weitzman - November 29, 2004 - 03:51

for now, i work around this limitation by stashing the path in my own var using the following line of code which executes in hook_menu(!$may_cache)

$_GET['q_original'] = $_GET['q'];

#2

jsloan - February 24, 2005 - 16:05

This same situation occurs when a node is a member of a book. Via the _nodeapi hook in the book module eventually the function menu_set_active_item() will execute the following statement:

<?php

if (empty($path)) {
     
$path = $_GET['q'];
    }
    else {
     
$_GET['q'] = $path;
    }
?>

... which sets the superglobal $_GET to the callback path of the menu item.

Like Moshe, I had to store the original contents in another variable. I need to use the full value of the $path in a module that extends the node to accept "full directory paths" and this works fine when the node is just a node, it breaks only when it is part of a book.

I guess what I am asking is "can we find another approach to menu/callback $path setting. Perhaps declare a variable for menu in the bootstrap and then leave the $_GET alone. It would be much more intuitive for module/theme developers to depend on the content of $_GET as reflecting what they see in the URL.

#3

Richard Archer - November 27, 2005 - 11:28
Priority:normal» minor

I'm changing this to CVS because:

- I think it's worth looking into further
but
- any solution will not likely be back-ported.

#4

Dublin Drupaller - November 27, 2005 - 11:43

Worth noting that Kbahey has already posted a patch for common.inc that maybe useful in this situation.

http://drupal.org/node/35687

The patch was intended for his customerrror.module, but, I'm guessing that it maybe aapplied to common.inc across the board.

Dub

#5

kbahey - November 27, 2005 - 16:24
Status:active» needs review

Here is the patch to common.inc for HEAD.

It is one line, and just stores the destination in the session. Any other module or function can check if destination is set and act accordingly.

For example, customerror traps the user hook, checks if it is a login, unsets the destination in the session, and redirects to the original page the user tried to access

If we get this in, modules can act on this in many ways.

AttachmentSizeStatusTest resultOperations
common.inc.redirect.patch684 bytesIgnoredNoneNone

#6

moshe weitzman - November 28, 2005 - 15:51

session is for data that needs to persist across page views. $_GET[q] doesn't need this. i don't really like this solution.

#7

moshe weitzman - January 30, 2006 - 03:57
Status:needs review» needs work

#8

markus_petrux - February 7, 2006 - 23:52

I would say "won't fix" 'cause why would you preserve the original value of $_GET['q']? I believe the core doesn't need this and if it is need by a contrib module, the original value could be capture from the init or menu hooks.

Someone that could benefit from this approach would be the statistics module, when it saves the path in the log, instead of $_GET['q'], it could use $original_path. Say $original_path was saved in the menu hook like this:

<?php
 
...
  if (
$may_cache) {
    ...
  }
  else {
    global
$original_path;
   
$original_path = $_GET['q'];
    ...
  }
  ...
?>

In statistics_exit, after this:
<?php
  drupal_bootstrap
(DRUPAL_BOOTSTRAP_PATH);
?>

it could do this:
<?php
 
global $original_path;
  if (!isset(
$original_path)) {
   
$original_path = $_GET['q'];
  }
?>

And use $original_path instead of $_GET['q'] in the INSERT statement.

It works. ;-)

#9

moshe weitzman - February 8, 2006 - 00:34

the use case is to put a login form on the accedss denied page ()assuming anonymous user). that login form ought to know the destination where the user was headed.

#10

markus_petrux - February 8, 2006 - 01:02

so you could save the original init path by drupal core itself and provide a normalized method to get its value. Say drupal_init_path() is modified like this:

<?php
function drupal_init_path() {
  global
$drupal_init_path;
  if (!empty(
$_GET['q'])) {
   
$_GET['q'] = drupal_get_normal_path(trim($_GET['q'], '/'));
  }
  else {
   
$_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage', 'node'));
  }
 
$drupal_init_path = $_GET['q'];
}
?>

The normalized method to get the original path could like:
<?php
/**
* Get the original init path.
*/
function drupal_get_init_path() {
  global
$drupal_init_path;
  return
$drupal_init_path;
}
?>

So you could set destination based on drupal_get_init_path() for a login form (or anything else) defined inside the 403/404 handlers.

#11

markus_petrux - February 8, 2006 - 01:06

Then the example I posted above, related to the statistics module, would be much simpler. The exit hook could use drupal_get_init_path() rather than $_GET['q'] to save the path in the access_log table.

#12

moshe weitzman - February 26, 2006 - 21:34

yes, thats the right idea. perhaps we change to two functions get_initial_path and set_initial_path. the set_initial_path will be called by the menu system whenever it first figures out $_GET['q'] ... lets not abbreviate init instead of initial. dries no like that.

#13

moshe weitzman - February 26, 2006 - 21:42

forget my last comment. i didn't realized we already had that init_path function. markus' proposal looks good to me.

#14

markus_petrux - February 26, 2006 - 22:23
Status:needs work» needs review

Do you mean this? (see patch)

AttachmentSizeStatusTest resultOperations
drupal_get_init_path.patch1.51 KBIgnoredNoneNone

#15

markus_petrux - March 1, 2006 - 20:49

rerolled (affected line in statistics module was changed)

AttachmentSizeStatusTest resultOperations
drupal_get_init_path_0.patch1.48 KBIgnoredNoneNone

#16

markus_petrux - March 7, 2006 - 00:34
Status:needs review» reviewed & tested by the community

This is so simple that I believe it is RTC. Please, correct me if I'm wrong.

#17

moshe weitzman - March 29, 2006 - 05:47

I suspect that http://drupal.org/node/13621 is a bug that depends on the patch here

#18

moshe weitzman - March 29, 2006 - 06:53

#19

killes@www.drop.org - March 29, 2006 - 06:57
Status:reviewed & tested by the community» needs work

using a get_foo function with a global variable doesn't make much sense. There should be a set_foo function and a static var.

#20

Steven - April 1, 2006 - 16:53

This issue offers a much simpler solution to this (and another) issue:
http://drupal.org/node/55869

#21

moshe weitzman - April 5, 2006 - 02:56
Status:needs work» fixed

tentatively marking this as fixed based on the patch that steven points to. please reopen with some detail if that solution isn't workable. it persists the original path in the $_REQUEST['destination'] element

#22

Anonymous - April 19, 2006 - 03:00
Status:fixed» closed
 
 

Drupal is a registered trademark of Dries Buytaert.