Index: apachesolr.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/apachesolr/apachesolr.module,v
retrieving revision 1.1.2.12.2.152
diff -u -p -r1.1.2.12.2.152 apachesolr.module
--- apachesolr.module	1 Jul 2009 22:57:55 -0000	1.1.2.12.2.152
+++ apachesolr.module	2 Jul 2009 03:44:45 -0000
@@ -575,35 +575,38 @@ function apachesolr_block($op = 'list', 
         $query = apachesolr_current_query();
         $sorts = $query->get_available_sorts();
 
-        $solrsorts = array();
-        $sort_parameter = $query->get_solrsort();
-        foreach (explode(',', $sort_parameter) as $solrsort) {
-          $parts = explode(' ', $solrsort);
-          if (!empty($parts[0]) && !empty($parts[1])) {
-            $solrsorts[$parts[0]] = $parts[1];
-          }
-        }
+        // Get the current sort as an array.
+        $solrsort = $query->get_solrsort(TRUE);
 
         $sort_links = array();
         $path = $query->get_path();
         $new_query = clone $query;
-        foreach ($sorts as $type => $sort) {
-          $new_sort = isset($solrsorts[$type]) ? $solrsorts[$type] == 'asc' ? 'desc' : 'asc' : $sort['default'];
-          $new_query->set_solrsort($type == "relevancy" ? '' : "{$type} {$new_sort}");
-          $active = isset($solrsorts[$type]) || ($type == "relevancy" && !$solrsorts);
-          $direction = isset($solrsorts[$type]) ? $solrsorts[$type] : '';
-          $sort_links[$type] = array(
-            'name' => $sort['name'],
+        $toggle = array('asc' => 'desc', 'desc' => 'asc');
+        foreach ($sorts as $name => $sort) {
+          $active = $solrsort['#name'] == $name;
+          $direction = '';
+          $new_direction = $sort['default'];
+          if ($name == 'score') {
+            // We only sort by ascending score.
+            $new_direction = 'asc';
+          }
+          elseif ($active) {
+            $direction = $solrsort['#direction'];
+            $new_direction = $toggle[$solrsort['#direction']];
+          }
+          $new_query->set_solrsort($name, $new_direction);
+          $sort_links[$name] = array(
+            'title' => $sort['title'],
             'path' => $path,
             'options' => array('query' => $new_query->get_url_querystring()),
             'active' => $active,
-            'direction' => $direction
+            'direction' => $direction,
           );
         }
         // Allow other modules to add or remove sorts.
         drupal_alter('apachesolr_sort_links', $sort_links);
-        foreach ($sort_links as $type => $link) {
-          $themed_links[$type] = theme('apachesolr_sort_link', $link['name'], $link['path'], $link['options'], $link['active'], $link['direction']);
+        foreach ($sort_links as $name => $link) {
+          $themed_links[$name] = theme('apachesolr_sort_link', $link['title'], $link['path'], $link['options'], $link['active'], $link['direction']);
         }
         return array('subject' => t('Sort by'),
                      'content' => theme('apachesolr_sort_list', $themed_links));
@@ -977,10 +980,15 @@ function apachesolr_modify_query(&$query
     $function_name = $module . '_apachesolr_modify_query';
     $function_name($query, $params, $caller);
   }
+  // TODO: The query object should hold all the params.
   // Add array of fq parameters.
   if ($query && ($fq = $query->get_fq())) {
     $params['fq'] = $fq;
   }
+  // Add sort if present.
+  if ($query && ($sort = $query->get_solrsort())) {
+    $params['sort'] = $sort;
+  }
 }
 
 /**
@@ -1481,14 +1489,19 @@ interface Drupal_Solr_Query_Interface {
   /**
    * Set the solrsort.
    *
-   * @param string raw string to set the sort to
+   * @param $sortstring
+   *  Raw string to set the sort to - optionally use aliased field names.
    */
-  function set_solrsort($sortstring);
+  function set_solrsort($field, $direction);
 
   /**
    * Get the solrsort.
+   *
+   * Returns the non-urlencode, non-aliased sort field and direction.
+   * Default return value is a string suitable to use as a param for Solr.
+   * If $as_array is TRUE, returns an array keyed with '#name' and '#direciton'.
    */
-  function get_solrsort();
+  function get_solrsort($as_array = FALSE);
 
   /**
    * Return an array of all filters.
Index: apachesolr_search.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/apachesolr/apachesolr_search.module,v
retrieving revision 1.1.2.6.2.108
diff -u -p -r1.1.2.6.2.108 apachesolr_search.module
--- apachesolr_search.module	1 Jul 2009 22:57:55 -0000	1.1.2.6.2.108
+++ apachesolr_search.module	2 Jul 2009 03:44:45 -0000
@@ -185,20 +185,14 @@ function apachesolr_search_view($type = 
  * @throws Exception
  */
 function apachesolr_search_execute($keys, $filters, $solrsort, $base_path = '', $page = 0, $caller = 'apachesolr_search') {
-  // Validate sort parameter
-  // TODO: move this to the query class.
-  if (strlen($solrsort) && preg_match('/^([a-z0-9_]+ (asc|desc)(,)?)+$/i', $solrsort)) {
-    $params['sort'] = $solrsort;
-  }
-  else {
-    $solrsort = '';
-    $params = array();
-  }
+
+  $params = array();
   // This is the object that knows about the query coming from the user.
   $query = apachesolr_drupal_query($keys, $filters, $solrsort, $base_path);
   if (empty($query)) {
     throw new Exception(t('Could not construct a Solr query in function apachesolr_search_search()'));
   }
+
   // This is the object that does the communication with the solr server.
   $solr = apachesolr_get_solr();
   $params += apachesolr_search_basic_params($query);
@@ -832,7 +826,7 @@ function apachesolr_search_form_search_s
     $keys = str_replace('+', '%2B', $keys);
   }
   if (!empty($fv['apachesolr_search']['retain-filters']) && $fv['apachesolr_search']['querystring']) {
-    $querystring = $fv['apachesolr_search']['querystring'] . '&retain-filters';
+    $querystring = $fv['apachesolr_search']['querystring'] . '&retain-filters=1';
   }
   $form_state['redirect'] = array($base . $keys, $querystring);
   if ($keys == '' && $querystring == '') {
Index: Solr_Base_Query.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/apachesolr/Solr_Base_Query.php,v
retrieving revision 1.1.4.38
diff -u -p -r1.1.4.38 Solr_Base_Query.php
--- Solr_Base_Query.php	30 Jun 2009 10:57:23 -0000	1.1.4.38
+++ Solr_Base_Query.php	2 Jul 2009 03:44:45 -0000
@@ -77,7 +77,7 @@ class Solr_Base_Query implements Drupal_
   /**
    * A mapping of field names from the URL to real index field names.
    */
-  protected $field_map = array();
+  protected $field_map = array('created' => 'date', 'type' => 'bigass', 'sort_name' => 'author');
 
   /**
    * An array of subqueries.
@@ -101,6 +101,9 @@ class Solr_Base_Query implements Drupal_
 
   protected $available_sorts;
 
+  // Makes sure we always have a valid sort.
+  protected $solrsort = array('#name' => 'score', '#direction' => 'asc');
+
   /**
    * @param $solr
    *   An instantiated Apache_Solr_Service Object.
@@ -123,11 +126,11 @@ class Solr_Base_Query implements Drupal_
     $this->solr = $solr;
     $this->keys = trim($keys);
     $this->filterstring = trim($filterstring);
-    $this->solrsort = trim($sortstring);
-    $this->base_path = $base_path;
-    $this->id = ++self::$idCount;
     $this->parse_filters();
     $this->available_sorts = $this->default_sorts();
+    $this->parse_sortstring($sortstring);
+    $this->base_path = $base_path;
+    $this->id = ++self::$idCount;
   }
 
   function __clone() {
@@ -233,32 +236,61 @@ class Solr_Base_Query implements Drupal_
     $this->subqueries = array();
   }
 
-  public function set_solrsort($sortstring) {
-    $this->solrsort = trim($sortstring);
+  protected function parse_sortstring($sortstring) {
+    // Validate and set sort parameter
+    $fields = implode('|', array_keys($this->available_sorts));
+    // Substitute any field aliases with real field names.
+    $sortstring = strtr(trim($sortstring), array_flip($this->field_map));
+    // Score is a special case - it's the default sort for Solr.
+    if ('' == $sortstring) {
+      $this->set_solrsort('score', 'asc');
+    }
+    elseif (preg_match('/^(?:('. $fields .') (asc|desc),?)+$/', $sortstring, $matches)) {
+      // We only use the last match.
+      $this->set_solrsort($matches[1], $matches[2]);
+    }
+  }
+
+  public function set_solrsort($name, $direction) {
+    if (isset($this->available_sorts[$name])) {
+      $this->solrsort = array('#name' => $name, '#direction' => $direction);
+    }
   }
 
-  public function get_solrsort() {
-    return $this->solrsort;
+  public function get_solrsort($as_array = FALSE) {
+    if ($as_array) {
+      return $this->solrsort;
+    }
+    else {
+      $sortstring = $this->solrsort['#name'] .' '. $this->solrsort['#direction'];
+      return $sortstring == 'score asc' ? '' : $sortstring;
+    }
   }
 
   public function get_available_sorts() {
     return $this->available_sorts;
   }
 
-  public function set_available_sort($field, $sort) {
-    $this->available_sorts[$field] = $sort;
+  public function set_available_sort($name, $data) {
+    // We expect non-aliased sorts to be added.
+    $this->available_sorts[$name] = $data;
+  }
+
+  public function remove_available_sort($name) {
+    unset($this->available_sorts[$name]);
   }
 
   /**
    * Returns a default list of sorts.
    */
   protected function default_sorts() {
+    // The array keys must always be real Solr index fields.
     return array(
-      'relevancy' => array('name' => t('Relevancy'), 'default' => 'asc'),
-      'sort_title' => array('name' => t('Title'), 'default' => 'asc'),
-      'type' => array('name' => t('Type'), 'default' => 'asc'),
-      'sort_name' => array('name' => t('Author'), 'default' => 'asc'),
-      'created' => array('name' => t('Date'), 'default' => 'desc'),
+      'score' => array('title' => t('Relevancy'), 'default' => 'asc'),
+      'sort_title' => array('title' => t('Title'), 'default' => 'asc'),
+      'type' => array('title' => t('Type'), 'default' => 'asc'),
+      'sort_name' => array('title' => t('Author'), 'default' => 'asc'),
+      'created' => array('title' => t('Date'), 'default' => 'desc'),
     );
   }
 
@@ -270,8 +302,12 @@ class Solr_Base_Query implements Drupal_
     if ($fq = $this->rebuild_fq(TRUE)) {
       $querystring = 'filters='. rawurlencode(implode(' ', $fq));
     }
-    if ($this->solrsort) {
-      $querystring .= ($querystring ? '&' : '') .'solrsort='. rawurlencode($this->solrsort);
+    $solrsort = $this->solrsort;
+    if ($solrsort && ($solrsort['#name'] != 'score' || $solrsort['#direction'] != 'asc')) {
+      if (isset($this->field_map[$solrsort['#name']])) {
+        $solrsort['#name'] = $this->field_map[$solrsort['#name']];
+      }
+      $querystring .= ($querystring ? '&' : '') .'solrsort='. rawurlencode($solrsort['#name'] .' '. $solrsort['#direction']);
     }
     return $querystring;
   }
