Karsten Frohwein, Geschäftsführer
Geschäftsführer der comm-press GmbH und absoluter Drupal Evanglist.

Fehlerbehebung Drupal

403 und 404 Fehler mit einem Drupal Modul behandeln

Drupal hat die Möglichkeit unter "admin/config/system/site-information" 403 und 404 Fehlerseiten zu bestimmen.

Allerdings kann man auch mehr machen als eine einfache Seite oder ein Panel anzuzeigen. Das Modul Search 404 ist ein Beispiel, was man Tolles mit einer 404 Seite anfangen kann.

Will man diese Seiten aber mit einer komplexeren Logik versehen, wird es allerdings ein wenig schwierig. Unsere Aufgabe war, von einem nicht veröffentlichten Node an einen Term aus diesem Node weiter zu leiten. Nur leider kann man auf der 403 Seite nicht so ganz einfach sehen, was die eigentliche URL war, da Drupal den Pfad schon auf die eingetragene 403 Seite geändert hat.

Schauen wir dafür kurz in den Core:

drupal_deliver_html_page(), common.inc, Zeile 2558

<?php
$path
= drupal_get_normal_path(variable_get('site_403', ''));
if (
$path && $path != $_GET['q']) {
 
// Custom 403 handler. Set the active item in case there are tabs to
  // display or other dependencies on the path.
 
menu_set_active_item($path);
 
$return = menu_execute_active_handler($path, FALSE);
}
?>

"menu_set_active_item($path);" ist unser "Problem".

<?php
/**
* Set the active path, which determines which page is loaded.
*
* Note that this may not have the desired effect unless invoked very early
* in the page load, such as during hook_boot, or unless you call
* menu_execute_active_handler() to generate your page output.
*
* @param $path
*   A Drupal path - not a path alias.
*/
function menu_set_active_item($path) {
 
$_GET['q'] = $path;
 
// Since the active item has changed, the active menu trail may also be out
  // of date.
 
drupal_static_reset('menu_set_active_trail');
}
?>

Da wir hier sehr früh im Ablauf von Drupal sind gehen so gesehen alle Informationen was aufgerufen werden sollte verloren. Ein paar Zeilen weiter oben in der common.inc Zeile 2553 steht:

<?php
// Keep old path for reference, and to allow forms to redirect to it.
if (!isset($_GET['destination'])) {
 
$_GET['destination'] = $_GET['q'];
}
?>

Das hilft uns aber auch nicht immer. Wenn "destination" gesetzt war, haben wir keine Chance. Aber wirklich kompliziert ist es nicht den alten Pfad wieder zu bekommen:

<?php
$path
= drupal_get_normal_path(request_path());
?>

Danach kann man wieder mit arg() arbeiten:

<?php
if (arg(0, $path) === 'node' && is_numeric(arg(1, $path))) {
}
?>

Von hier an ist es ein leichtes die gewünschte Weiterleitung zu bauen. Aber nicht vergessen dann auch unseren Menu Callback als 403 unter der oben genannten URL einzutragen!

<?php
/**
* Implements hook_menu().
*/
function redirect_http_status_menu() {

 
$items['redirect403'] = array(
   
'title' => 'Access denied',
   
'page callback' => 'redirect_http_status_403_check',
   
'access arguments' => array('access content'),
   
'type' => MENU_CALLBACK,
  );

  return
$items;
}

function
redirect_http_status_403_check() {
 
$path = redirect_http_status_path();

  if (
arg(0, $path) === 'node' && is_numeric(arg(1, $path))) {
   
$node = node_load(arg(1, $path));
   
$ref_kategorie = field_get_items('node', $node, 'field_ref_kategorie');
    if (
$ref_kategorie) {
     
// Get "lowest" term.
     
$term = array_pop($ref_kategorie);
     
drupal_add_http_header('Location', url('taxonomy/term/' . $term['tid']));
     
drupal_add_http_header('Status', '307 Temporary Redirect');
     
drupal_exit();
    }
  }
  return
t('You are not authorized to access this page.');
}
?>