? 933664-pathredirect-better-source-select.patch.save
? REMOVED.txt
? TODO.txt
? path_redirect.css
? path_redirect.import-export.inc
? path_redirect.migrate.inc
? screenshot.png
Index: path_redirect.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/path_redirect/path_redirect.module,v
retrieving revision 1.3.2.7.2.107
diff -u -p -r1.3.2.7.2.107 path_redirect.module
--- path_redirect.module	7 Oct 2010 15:28:33 -0000	1.3.2.7.2.107
+++ path_redirect.module	30 Nov 2010 23:40:39 -0000
@@ -378,8 +378,8 @@ function path_redirect_load($rid) {
  *   An optional query string to match.
  */
 function path_redirect_load_by_source($source, $language = '', $query = array()) {
-  $where = $query ? "(source = '%s' OR source LIKE '%s')" : "source = '%s'";
-  $args = $query ? array($source, $source . '?%%') : array($source);
+  $where = $query ? "(source = '%s' OR source LIKE '%s%%')" : "source = '%s'";
+  $args = $query ? array($source, $source . '?') : array($source);
   $args[] = $language;
   $rid_query = db_query("SELECT rid FROM {path_redirect} WHERE $where AND language IN ('%s', '') ORDER BY language DESC, source DESC, rid DESC", $args);
   $rids = array();
@@ -387,16 +387,32 @@ function path_redirect_load_by_source($s
     $rids[] = $rid;
   }
 
-  if ($query) {
-    $redirects = path_redirect_load_multiple($rids);
+  if ($rids && $redirects = path_redirect_load_multiple($rids)) {
+    // Narrow down the list of candidates.
     foreach ($redirects as $rid => $redirect) {
-      if (path_redirect_compare_array($redirect['source_query'], $query)) {
-        return $redirect;
+      if (!empty($redirect['source_query'])) {
+        if (empty($query) || !path_redirect_compare_array($redirect['source_query'], $query)) {
+          unset($redirects[$rid]);
+          continue;
+        }
+      }
+
+      // Add a case sensitive matches condition to be used in sorting.
+      if ($source !== $redirect['source']) {
+        $redirects[$rid]['weight'] = 1;
       }
     }
-  }
-  elseif ($rids) {
-    return path_redirect_load(current($rids));
+
+    if (!empty($redirects)) {
+      // Sort the redirects in the proper order.
+      uasort($redirects, '_path_redirect_uasort');
+
+      // Allow other modules to alter the redirect candidates before selecting the top one.
+      $context = array('language' => $language, 'query' => $query);
+      drupal_alter('path_redirect_load_by_source', $redirects, $source, $context);
+
+      return !empty($redirects) ? reset($redirects) : FALSE;
+    }
   }
 
   return FALSE;
@@ -427,6 +443,30 @@ function path_redirect_load_multiple($ri
   return $redirects;
 }
 
+/**
+ * uasort callback; Compare redirects based on language neutrality and rids.
+ */
+function _path_redirect_uasort($a, $b) {
+  $a_weight = isset($a['weight']) ? $a['weight'] : 0;
+  $b_weight = isset($b['weight']) ? $b['weight'] : 0;
+  if ($a_weight != $b_weight) {
+    // First sort by weight (case sensitivity).
+    return $a_weight > $b_weight;
+  }
+  elseif ($a['language'] != $b['language']) {
+    // Then sort by language specific over language neutral.
+    return $a['language'] == '';
+  }
+  elseif (empty($a['source_query']) != empty($b['source_query'])) {
+    // Then sort by redirects that do not have query strings over ones that do.
+    return empty($a['source_query']);
+  }
+  else {
+    // Lastly sort by the highest redirect ID.
+    return $a['rid'] < $b['rid'];
+  }
+}
+
 function _path_redirect_build_conditions(&$query, $rids, $conditions) {
   static $schema;
   if (!isset($schema)) {
Index: path_redirect.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/path_redirect/path_redirect.test,v
retrieving revision 1.1.2.24
diff -u -p -r1.1.2.24 path_redirect.test
--- path_redirect.test	30 Nov 2010 22:52:32 -0000	1.1.2.24
+++ path_redirect.test	30 Nov 2010 23:40:39 -0000
@@ -114,6 +114,31 @@ class PathRedirectUnitTest extends PathR
     $this->testRedirects();
     variable_set('clean_url', (int) $clean_url);
   }
+
+  /**
+   * Test the _path_redirect_uasort() callback used in
+   * path_redirect_load_by_source().
+   */
+  function testRedirectQuerySorting() {
+    $redirect1 = array('source' => 'test', 'redirect' => 'node');
+    $redirect2 = array('source' => 'test', 'source_query' => array('foo' => 'bar'), 'redirect' => 'node', 'query' => array('foo' => 'bar'));
+    $redirect3 = array('source' => 'test', 'source_query' => array('foo' => 'ferzle'), 'redirect' => 'node', 'query' => array('foo' => 'ferzle'));
+
+    $this->addRedirect('test', 'node', $redirect2);
+    $this->assertNoRedirect($redirect1);
+    $this->assertRedirect($redirect2);
+    $this->assertNoRedirect($redirect3);
+
+    $this->addRedirect('test', 'node');
+    $this->assertRedirect($redirect1);
+    $this->assertRedirect($redirect2);
+    $this->assertRedirect(array('query' => array()) + $redirect3);
+
+    $this->addRedirect('test', 'node', $redirect3);
+    $this->assertRedirect($redirect1);
+    $this->assertRedirect($redirect2);
+    $this->assertRedirect($redirect3);
+  }
 }
 
 /*class PathRedirectPathautoUnitTest extends PathRedirectTestHelper {
