Rather than display an "access denied" page, I want to over-ride the standard 403 with a panel page that contains several views which take the original node id as a contextual filter.

I can create a view which handles contextual filters easily. I can create a panel which over-rides the standard 403 with custom message.

However, there is no panels context that allows me to pass the original node id into the view, and the view doesn't get the "Content ID from URL" because the url passed to the view is "access-denied". PHP code in the panel confirms that when outputting $_GET['q'] and arg() using a custom content with PHP filter.

$_SERVER['REQUEST_URI'] DOES return the original path with the node ID, which I can parse, but I still don't know how I could pass that as a context to the view.

What is the best way to I pass the originally requested node id to the panel, and how do I pass that as context to the view? Alternatively, how can I directly pass it to the view, if doing through panels is not possible.


2 Answers 2


I found a solution that works.

I've just changed the default value of the view's contextual filter to PHP code and added this:

$node_path = explode('/', drupal_get_normal_path(trim($_SERVER['REQUEST_URI'], '/') ));
return $node_path[1];
  • Unfortunately, this doesn't cover the case I really wanted it to cover - that is, to have a custom access denied message for specific content types. It would be great if panels had a method of over-riding drupal core's access denied system, so that I can create variants for different content types. However, since the views take a node id, I can filter by node type on the view, to prevent views from being rendered (ie, view for content type A doesn't render for content type B, and vise-versa, and I can put both views on the panel, and which one renders is depends on the content type of the nid. Jun 12, 2015 at 15:59

The above solution ended up causing errors in some cases. I decided to implement a ctools plugin to provide a context for the panel.

$plugin = array( 'title' => t("Original Node"), 'description' => t('Provide token for original node on a 403 page.'), 'context' => 'ctools_plugin_originalnode_context', 'context name' => 'originalnode_context', 'keyword' => 'originalnode_context', // Provides a list of items which are exposed as keywords. 'convert list' => 'originalnode_context_convert_list', // Convert keywords into data. 'convert' => 'originalnode_context_convert', );

function ctools_plugin_originalnode_context($empty, $data = NULL, $conf = FALSE) {

$context = new ctools_context('originalnode_context'); $context->plugin = 'originalnode_context'; $context->data = $data; $context->title = 'Original node';

$path = drupal_get_normal_path(trim($_SERVER['REQUEST_URI'], '/'));

$router_item = menu_get_item($path);

$context->data['nid'] = $router_item['original_map'][1]; }

return $context;


function originalnode_context_convert_list() { return array( 'originalnode_nid' => t('Original node on 403 page'), ); }

function originalnode_context_convert($context, $type) { // switch is used in case of expansion (ctools plugin standard) switch ($type) { case 'originalnode_nid': return $context->data['nid']; } }

Works beautifully.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.