From f7d0daed2ed61981c3630d390ca6acde4b1e0ebe 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 |   79 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 76 insertions(+), 3 deletions(-)

diff --git a/includes/common.inc b/includes/common.inc
index d34c19d2c316852403debbd2e89d43416521ff26..5bd42a470d830c0e928ecb0f32c611830f00d455 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -2316,11 +2316,84 @@ 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.
+  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 = FALSE;
+  }
+  // The path is active if it matches the current page.
+  elseif ($current_page == $real_path . $query) {
+    $active_paths[$path_key] = TRUE;
+  }
+  // The path is active if it exactly matches the request path.
+  elseif ($path == $_GET['q']) {
+    $active = TRUE;
+  }
+  // A path of '<front>' is active for the front page.
+  elseif ($path == '<front>' && drupal_is_front_page()) {
+    $active = TRUE;
+  }
+  // All other paths are not active.
+  else {
+    $active = FALSE;
+  }
+  if ($active) {
     $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

