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; }