First, please see Better Integration with Apache Solr Autocomplete.

As summarized in that issue, I would like to control what fields are queried via the Solr QF parameter in the Solr Panels pane settings form.

If interested in the following approach, I would be happy to submit a patch.

The basic idea of my approach was to utilize the unused jquey-autocomplete configuration point 'extraParams'. And so that this wasn't just limited to Apache Solr Panels, I was thinking something like this:

Drupal.behaviors.apachesolr_autocomplete = function(context) {
  $(".apachesolr-autocomplete.unprocessed", context).autocomplete(Drupal.settings.apachesolr_autocomplete.path,
  {
    // Classnames for the widget.
    inputClass: "",
   
  ......

    extraParams: {
       apachesolr_autocomplete_overrides: function() { return $("#apachesolr-autocomplete-overrides").val(); },
    },

And, the value of #apachesolr-autocomplete-overrides would be a json-encoded PHP object/array of values that would could be documented and used by any module and added as part of a hook_form_alter(), like so:

/**
 * Implementation of hook_form_FORM_ID_alter().
 */
function apachesolr_panels_form_apachesolr_panels_search_form_alter(&$form, &$form_state) {

  ...

    $apachesolr_autocomplete_overrides_value = array();
    $apachesolr_autocomplete_overrides_value['fq'] = explode(' ', $form_state['apachesolr_autocomplete_fq']);
    $apachesolr_autocomplete_overrides_value['facet_field'] = explode(' ', $form_state['apachesolr_autocomplete_facet_field']);
    $apachesolr_autocomplete_overrides_value['qf'] = explode(' ', $form_state['apachesolr_autocomplete_qf']);
    $form['basic']['apachesolr_panels_search']['apachesolr_autocomplete_overrides'] = array(
      '#type' => 'hidden',
      '#id' => 'apachesolr-autocomplete-overrides',
      // We use JSON encoding instead of PHP serialize, since otherwise we be
      // at risk of user input being injected into the hidden string and
      // unserialized.
      '#default_value' => json_encode($apachesolr_autocomplete_overrides_value),
    );
  }
}

Then, apachesolr_autocomplete.module would be modified to utilize those additional Solr overrides. Another example:

function apachesolr_autocomplete_suggest_word_completion($keys, $suggestions_to_return = 5) {
  $apachesolr_autocomplete_overrides = json_decode($_GET['apachesolr_autocomplete_overrides']);

  ...

  // Ask Solr to return facets that begin with $last_part; these will be the suggestions.
  $facet_field = array('spell');
  if (!empty($apachesolr_autocomplete_overrides->facet_field)) {
    $facet_field = $apachesolr_autocomplete_overrides->facet_field;
  }
  $params = array(
    'facet' => 'true',
    'facet.field' => $facet_field,
    'facet.prefix' => $last_part,
    'facet.limit' => $suggestions_to_return * 5,
    'facet.mincount' => 1,
    'start' => 0,
    'rows' => 0,
  );
  if (!empty($apachesolr_autocomplete_overrides->fq)) {
    $add_filters_array = $apachesolr_autocomplete_overrides->fq;
  }
  if (!empty($apachesolr_autocomplete_overrides->qf)) {
    $params['qf'] = $apachesolr_autocomplete_overrides->qf;
  }

  ...

}

Finally:

function apachesolr_autocomplete_suggest($keys, $params, $theme_callback, $orig_keys, $suggestions_to_return = 5, $add_filters_array = NULL) {
  
  ...

  // Query Solr for $keys so that suggestions will always return results.
  $query = apachesolr_drupal_query($keys);
  //add additional filters if any and have both key and value
  if ($add_filters_array) {
    foreach ($add_filters_array as $add_filter) {
      $filter_array = explode(':', $add_filter);
      if (!empty($filter_array[0]) && !empty($filter_array[1])) {
        $query->add_filter($filter_array[0], $filter_array[1]);
      }
    }
  }

  ...

}

And this give you the basic idea.

Comments

janusman’s picture

Thanks for opening up the issue. This along with other issues would pull the module towards a more API-like way of handling things:

  • specify field to use for suggestions
  • specify a set of active filters to use when running the autocomplete

I won't consider your changes unless some issues are addressed first: Placing the filters as JSON is a nice hack, but again, imagining a more API-like setting think that we should be able to handle different simultaneous widgets on the same page. Also, settings should really be in the main javascript Drupal object, and also passed on to the module PHP functions as arguments and not have the functions read from $_GET (again, thinking of an API).

So, for now I'll leave this issue opened, but maybe we need to take care of an API-ifying meta-issue first. I think at the end of that issue it would be relatively painless to work in Solr Panels and tackle other feature requests. I'll post the link to that issue when I open it.

janusman’s picture

kmadel’s picture

janusman - I completely agree with you about a 'more API-like way of handling things.' But until there is more major work done around that, my approach seems to be inline with apachesolr_autocomplete_callback function:

function apachesolr_autocomplete_callback($keys = '') {
  if (apachesolr_autocomplete_variable_get_widget() == 'custom') {
    // Keys for custom widget come from $_GET.
    $keys = $_GET['query'];
  }

Also using the $_GET object. Am I missing something there?

Finally, I would like to reiterate that I am using core functionality of the jquery-autocomplete library in using the extraParams configuration point:

    extraParams: {
       apachesolr_autocomplete_overrides: function() { return $("#apachesolr-autocomplete-overrides").val(); },
    },

One thing that I could and wouldn't mind doing in the short term, was to covert the somewhat unstructured PHP array that gets passed to extraParams into a well documented PHP class - perhaps even just use Drupal_Solr_Query_Interface from the apachesolr module itself.

Thoughts?

And thanks for taking a look.

janusman’s picture

kmadel: yeah, for this feature to make it thru I'm not asking for great things =) I was not suggesting that #1062818: APIfy ApacheSolr Autocomplete to tackle more use cases is a blocking issue for this one.

I guess I would be content to have settings in JS settings instead of stuffed into $form['basic']['apachesolr_panels_search']['apachesolr_autocomplete_overrides'] inside apachesolr_panels_form_apachesolr_panels_search_form_alter() ...

Anonymous’s picture

Hi - I have a requirement for this too as I have facets for things like 'keywords' which could grow to hundreds and the checkbox facets just won't be sensible to use so I'd like to use autocomplete instead but just on one facet, e.g. keywords.

I'm going to work through the examples of code you've supplied above and in the other related issues but before I dive in I was just wondering whether anyone had successfully done this already - i.e. I'm fishing for code examples ;)

GaëlG’s picture

@stevepurkiss & kmadel :
It looks like you've already done it for a site. Any patch or detailed code changes ?
Thanks in advance !

GaëlG’s picture

I tried to understand and make work the instructions from kmadel. But at the end I figured out that the data like $form_state['apachesolr_autocomplete_...'] in apachesolr_panels_form_apachesolr_panels_search_form_alter are not actually available, so we're supposed to populate them.
But the problem is the way apachesolr_panels is done. Search form and search results are two panes with their own configuration. And the special filters added by ApacheSolr Panels are in the configuration for the search results pane. So this is not directly available from the search form pane in which we do the autocomplete.
Anyway, if we just want to add support for basic autocompletion in the ApacheSolr Panels search form, we just have to add this little function in apachesolr_autocomplete.module:

/*
 * Implementation of hook_form_FORM_ID_alter().
 * apachesolr_panels compatibility
 */
function apachesolr_autocomplete_form_apachesolr_panels_search_form_alter(&$form, $form_state) {
  $element = &$form['basic']['inline']['keys'];
  apachesolr_autocomplete_do_alter($element);
}

With this, the suggestions will be the same as for the default apachesolr search form.

GaëlG’s picture

Status: Active » Needs review

I change to "needs review", as this could be committed easily.

GaëlG’s picture

And this one too :

/**
 * Implementation of hook_form_FORM_ID_alter().
 * apachesolr_panels compatibility
 */
function apachesolr_autocomplete_form_apachesolr_panels_search_block_alter(&$form, $form_state) {
  $element = &$form['apachesolr_panels_search_block_form'];
  apachesolr_autocomplete_do_alter($element);
}
tsmith512’s picture

Both snippets from #7 and #9 are part of a patch suggested for 7.x-1.x; it looks like the code would be the same. #1491860: Add support for apachesolr_panels

janusman’s picture

So #1444038: Autocomplete for custom search pages has a patch that includes panelized search pages:

function apachesolr_autocomplete_form_apachesolr_panels_search_form_alter()...

however it does not have anything around the block form, which is on #9 above.

I think we should track panels integration on this issue, and the other issue ( #1444038: Autocomplete for custom search pages ) should be about the general support for different forms/environments.