From ea9ba5a4f5fdae0f8ccef5b955afb7e4815379da Mon Sep 17 00:00:00 2001
From: Bob Vincent <bobvin@pillars.net>
Date: Sat, 15 Oct 2011 15:44:06 -0400
Subject: [PATCH] Issue 41595: Correctly identify active paths.

---
 includes/common.inc |   82 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/includes/common.inc b/includes/common.inc
index d34c19d2c316852403debbd2e89d43416521ff26..dfed1c58ad8b27e7b120ceab55766675fd8a8939 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -2308,6 +2308,7 @@ function drupal_attributes(array $attributes = array()) {
 function l($text, $path, array $options = array()) {
   global $language_url;
   static $use_theme = NULL;
+  static $active_paths = array();
 
   // Merge in defaults.
   $options += array(
@@ -2316,11 +2317,86 @@ function l($text, $path, array $options = array()) {
   );
 
   // Append active class.
-  if (($path == $_GET['q'] || ($path == '<front>' && drupal_is_front_page())) &&
-      (empty($options['language']) || $options['language']->language == $language_url->language)) {
+  // Compare the link to the current page's path, but don't modify $path or
+  // $options, as they are sent to url() below.
+
+  // If Clean URLs is enabled and there is an alias for the node, then $path
+  // is equal to $text. Test for that condition and set the working variable
+  // to the actual path.
+  $path_key = $path;
+  if (isset($options['query'])) {
+    $path_key .= '?' . serialize($options['query']);
+  }
+  if (!isset($active_paths[$path_key])) {
+    if ($text == $path) {
+      if (isset($options['language']->language)) {
+        $real_path = drupal_get_normal_path($path, $options['language']->language;
+      }
+      else {
+        $real_path = drupal_get_normal_path($path);
+      }
+    }
+    else {
+      $real_path = $path;
+    }
+    $query = '';
+    $current_page = $_GET['q'];
+
+    // If the paths are not the same, don't even bother doing anything else.
+    if ($real_path == $current_page) {
+      // Check to see if there is a query key in $options.
+      if (!empty($options['query'])) {
+        // Parse the $options['query'] array and reconstruct the query for
+        // testing.
+        foreach($options['query'] as $key => $value) {
+          $query .= $key . '=' . $value . '&';
+        }
+
+        // Complete the query and remove the final '&'.
+        if (variable_get('clean_url')) {
+          // With Clean URLs enabled.
+          $query = '?' . drupal_substr($query, 0, drupal_strlen($query) - 1);
+        }
+        else {
+          // With Clean URLs disabled.
+          $query = '?q=node&' . drupal_substr($query, 0, drupal_strlen($query) - 1);
+        }
+      }
+
+      // Check to see if the URL contains a query part.
+      if (!empty($_SERVER['QUERY_STRING'])) {
+        // Sometimes, there is a query in $_SERVER['QUERY_STRING'] that is
+        // simply either the path or alias of the current page. We need to
+        // verify that in order to accurately test.
+        $raw_query = drupal_substr($_SERVER['QUERY_STRING'], 2, drupal_strlen($_SERVER['QUERY_STRING']) - 2);
+        if ($raw_query != drupal_get_path_alias($real_path) && $raw_query != $real_path) {
+          // Add the query part to our test variable. We need both parts for
+          // accurate and complete testing.
+          $current_page .= '?' . $_SERVER['QUERY_STRING'];
+        }
+      }
+    }
+
+    // The path is not active if its language differs from the current page.
+    if (isset($options['language']) && $options['language']->language != $language_url->language)) {
+      $active_paths[$path_key] = FALSE;
+    }
+    // The path is active if it matches the current page.
+    elseif ($current_page == $real_path . $query) {
+      $active_paths[$path_key] = TRUE;
+    }
+    // A path of '<front>' is active for the the front page.
+    elseif ($path == '<front>' && drupal_is_front_page()) {
+      $active_paths[$path_key] = TRUE;
+    }
+    // All other paths are not active.
+    else {
+      $active_paths[$path_key] = FALSE;
+    }
+  }
+  if ($active_paths[$path_key]) {
     $options['attributes']['class'][] = 'active';
   }
-
   // Remove all HTML and PHP tags from a tooltip. For best performance, we act only
   // if a quick strpos() pre-check gave a suspicion (because strip_tags() is expensive).
   if (isset($options['attributes']['title']) && strpos($options['attributes']['title'], '<') !== FALSE) {
-- 
1.7.5.4

