GSoC Week #5: Creating views filter plugin for search api location (Second part)

If you find my week-3 post I had posted a brief description about creating views filter of search api location views. Here I explained some more details about the filter plugin. The module works great with raw plugin and does exactly  it says on the tin, however it created something of a head-scratcher as the same project, which was using Apache Solr via Search API, required this data to be searchable by the end user. Creating a view of the indexed data and then exposing the various filters to be included in the search was the obvious answer and initially it was felt that it should be pretty straightforward. In the previous post  I had emphasized on the views hook. For a number of the exposed filters, it was straightforward; although some required the use of hook_form_alter to make some alterations to the output of some exposed filters such as changing boolean filters from a True/False selection to Yes/No

In our case the table which we are interested in is search_api_index_IndexID. IndexID is different for each index. we need to implement hook_views_data_alter() to define a filter of our own and to alter the search_api_index_IndexID table. You should note search_api_index_  is a virtual table. You can not find it in Drupal database. For each search index, There is a base table with key "search_api_index_INDEX", which contains field, filter, argument and sort handlers for all indexed fields. (Field handlers too, to allow things like click-sorting.) . 

If you see the below code snippet, you will find there are 2 plugins. One is "search_api_location" and another is "search_api" . You can recognize them from their ids that are keyed as " $table[$field_id]['filter']['id'] " . 

 * Implements hook_views_data_alter().
function search_api_location_views_views_data_alter(&$data) {

  /** @var \Drupal\search_api\IndexInterface $index */
  foreach (Index::loadMultiple() as $index) {
    $table = &$data['search_api_index_' . $index->id()];
    /** @var \Drupal\search_api\Item\FieldInterface $field */
    foreach ($index->getFields() as $field_id => $field) {
      if ($field->getType() == 'location') {
        // Adding filter to location fields.
        $table[$field_id]['filter']['title'] = $field->getLabel();
        $table[$field_id]['filter']['id'] = 'search_api_location';
        $table[$field_id]['filter']['help'] = $field->getDescription();

        $location_field = $field_id . '__distance';
        $table[$location_field]['group'] = $table[$field_id]['group'];
        $table[$location_field]['group'] = t('@datasource datasource', array('@datasource' => $field->getDatasource()->label()));
        $table[$location_field]['title'] = t('@field (indexed field) - distance', array('@field' => $field->getLabel()));
        $table[$location_field]['help'] = t('Calculated distance to the %field field', array('%field' => $field->getLabel()));
        $table[$location_field]['field']['type'] = 'decimal';
        $table[$location_field]['field']['id'] = 'numeric';
        $table[$location_field]['field']['click sortable'] = TRUE;
        $table[$location_field]['field']['real field'] = $table[$field_id]['field']['real field'] . '__distance';
        $table[$location_field]['sort']['id'] = 'search_api';

SearchAPIFilterLocation is an extended class of FilterpluginBase with plugin id search_api_location. Basically it provides site admin to select the Location input plugins. Currently I implemented Raw plugin to configure Views Filter. Two more plugins to be implemented.  This week I went through some more details on search_api_location plugin.  Soon I will submit a patch for it. search_api plugin is not workable yet. So I have commented out those code snippet. The field key is the important item in that array and refers to the actual field, we want to be able to filter on.  Well I will post more about it on next week. Stay tuned.