From 78d60cb6b421d82b594fbb517ec7ebdfe0ebe3c1 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 |   97 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 94 insertions(+), 3 deletions(-)

diff --git a/includes/common.inc b/includes/common.inc
index d34c19d2c316852403debbd2e89d43416521ff26..221c2598bc18b0e63f481fb4da7902c16fca7662 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -306,6 +306,7 @@ function _drupal_default_html_head() {
   // Add default elements. Make sure the Content-Type comes first because the
   // IE browser may be vulnerable to XSS via encoding attacks from any content
   // that comes before this META tag, such as a TITLE tag.
+  $elements = array();
   $elements['system_meta_content_type'] = array(
     '#type' => 'html_tag',
     '#tag' => 'meta',
@@ -328,7 +329,14 @@ function _drupal_default_html_head() {
     ),
   );
   // Also send the generator in the HTTP header.
-  $elements['system_meta_generator']['#attached']['drupal_add_http_header'][] = array('X-Generator', $elements['system_meta_generator']['#attributes']['content']);
+  $elements['system_meta_generator']['#attached'] = array(
+    'drupal_add_http_header' => array(
+      array(
+        'X-Generator',
+        $elements['system_meta_generator']['#attributes']['content'],
+      )
+    )
+  );
   return $elements;
 }
 
@@ -2308,6 +2316,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,8 +2325,87 @@ 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($options['language']->language)) {
+    $path_key .= '?' . $options['language']->language;
+  }
+  if (!isset($active_paths[$path_key])) {
+    if ($text == $path) {
+      if (!empty($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']) && isset($language_url->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 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';
   }
 
@@ -2952,10 +3040,12 @@ function drupal_get_css($css = NULL, $skip_alter = FALSE) {
   $styles = array(
     '#type' => 'styles',
     '#items' => $css,
+    '#attached' => array('js' => array()),
   );
 
   // Provide the page with information about the individual CSS files used,
   // information not otherwise available when CSS aggregation is enabled.
+  $setting = array('ajaxPageState' => array());
   $setting['ajaxPageState']['css'] = array_fill_keys(array_keys($css), 1);
   $styles['#attached']['js'][] = array('type' => 'setting', 'data' => $setting);
 
@@ -4125,6 +4215,7 @@ function drupal_get_js($scope = 'header', $javascript = NULL, $skip_alter = FALS
 
   // Provide the page with information about the individual JavaScript files
   // used, information not otherwise available when aggregation is enabled.
+  $setting = array('ajaxPageState' => array());
   $setting['ajaxPageState']['js'] = array_fill_keys(array_keys($items), 1);
   unset($setting['ajaxPageState']['js']['settings']);
   drupal_add_js($setting, 'setting');
-- 
1.7.5.4

