I will post a patch for integration of the Countries field in Apache SolR.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

guillaumev’s picture

Status: Active » Needs review
FileSize
1.94 KB

This patch integrates the country field into Apache SolR...

Alan D.’s picture

looks ok, but I can not test this myself... feedback anyone?

The only thing that I can see from the patch is this

+     $iso2 = field_filter_xss($allowed_values[$facet]);
+     $ct = country_load($iso2);

which could be shortened to this

+     $ct = country_load($allowed_values[$facet]);

Reason, the iso2 value is only used to index the country array.

guillaumev’s picture

FileSize
1.81 KB

I was too lazy to make a patch, but attached is the code that works for the new version of apachesolr (beta6)

webflo’s picture

Status: Needs review » Fixed

Looks good. Committed with small changes to 7.x-2.x. Thanks!

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

Alan D.’s picture

Category: feature » bug
Priority: Normal » Major
Status: Closed (fixed) » Needs work

Right, I am in the middle of a major refactor, so sorry for the cut 'n paste.

There is a non-critical security issue (user needs "administrate site configuration" permission) here and also invalid use of t(). Can someone please test this code for me. This integrates with i18n_countries module, but I have no idea what the means to ApacheSolr???

So, does this still work?

And if you have time, un-comment the TODO and see if it breaks the search if you have a country name like '<span>test</span>text'.

/**
 * Implements hook_apachesolr_field_mappings().
 */
function countries_apachesolr_field_mappings() {
  $mappings = array(
    'country' => array(
      'display_callback' => 'countries_apachesolr_display_callback',
      'indexing_callback' => 'countries_apachesolr_indexing_callback',
      'map callback' => 'countries_apachesolr_map_callback',
      'index_type' => 'string',
      'facets' => TRUE
    )
  );
  return $mappings;
}

/**
 * Callback that converts countries module field into an array.
 */
function countries_apachesolr_indexing_callback($entity, $field_name, $index_key, $field_info) {
  $fields = array();
  if (!empty($entity->{$field_name})) {
    $field = $entity->$field_name;
    list($lang, $values) = each($field);
    foreach ($values as $fval) {
      $fields[] = array(
        'key' => $index_key,
        'value' => $fval['iso2'],
      );
    }
  }
  return $fields;
}

/**
 * Map callback.
 */
function countries_apachesolr_map_callback(array $values) {
  $map = array();
  foreach ($values as $value) {
    if ($country = country_load($value)) {
      $map[$value] = countries_t($country, 'name');
      // This may break the search.
      // $map[$value] = check_plain($map[$value]);
    }
  }
  return $map;
}

/**
 * Returns the country name to be used in the facet.
 *
 *  @param $facet string
 *    The indexed value
 *  @param $options
 *    An array of options including the hook_block $delta.
 */
function countries_apachesolr_display_callback($facet, $options) {
  $fields = field_info_fields();
  $field_name = $options['delta'];
  if (isset($fields[$field_name])) {
    $allowed_values = list_allowed_values($field);
    if (isset($allowed_values[$facet])) {
      $country = country_load($allowed_values[$facet]);
    }
  }
  else {
    $country = country_load($allowed_values[$facet]);
  }

  if ($country) {
    return check_plain(countries_t($country, 'name'));
  }
  return '';
}

# New wrapper function to hook into countries_i18n rather than repeating the conditional all of the time.
/**
 * Wrapper function to hook into the countries_i18n module.
 */
function countries_t($country, $property) {
  static $i18n = NULL;
  if (!isset($i18n)) {
    $i18n = module_exists('countries_i18n');
  }
  switch ($property) {
    case 'name':
      $value = $country->name;
      break;
    case 'official_name':
      $value = empty($country->official_name) ? '' : $country->official_name;
      break;

    default:
      return isset($country->$property) ? $country->$property : '';
  }

  return $i18n ? countries_i18n_translate($country->iso2, $property, $value) : $value;
}
Alan D.’s picture

Title: Apache Solr integration » Apache Solr integration help
Project: Countries » Apache Solr Search
Component: Code » Documentation
Assigned: guillaumev » Unassigned
Category: bug » support
Status: Needs work » Needs review

I'm just flicking issues queues to get an experienced eye on the code for 2 minutes. Without being able to set up to test, I am wondering how best to safely integrate with the module.

Do the results for hook_apachesolr_map_callback() / hook_apachesolr_display_callback() both need to be sanitized?

Also, should we be translating results in either?

Feel free to transfer back to the countries issue queue afterwards. Thanks in advance.

Status: Needs review » Needs work

The last submitted patch, solr_integration-1130506-1.patch, failed testing.

Nick_vh’s picture

Project: Apache Solr Search » Countries

I'd prefer if you would open a new issue in the apache solr issue queue with a clear issue summary what is requested. Are you ok with that?

Alan D.’s picture

Title: Apache Solr integration help » Apache Solr integration
Component: Documentation » Code
Category: support » bug
Priority: Major » Normal
Status: Needs work » Fixed

Response was no sanitation, so changes are valid and I'm also adding a check_plain() to the map callback just to be safe. There should never be HTML in these text fields, so this should not effect anything!

Committed.

Nick_vh’s picture

Status: Fixed » Closed (fixed)
Alan D.’s picture

Version: 7.x-1.x-dev » 7.x-2.0-beta2
Status: Closed (fixed) » Fixed

Fixed issues automatically close themselves after two weeks and provide a grace period for any new issues arising from the commit.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

guillaumev’s picture

Status: Closed (fixed) » Needs review
FileSize
471 bytes

I'd like to reopen this issue because I found out that the check_plain that you added is causing issues. I have a site configured with countries and facetapi, and facetapi does a check_plain (in facetapi.theme.inc) before displaying any text.

The result is that check_plain is called twice on a single string. For most countries, it does not matter, but for "Côte d'Ivoire", which has an apostrophe:

  • In the first check_plain, the apostrophe is converted to &#039;
  • In the second check_plain, the & is converted to &amp;

The result is that instead of displaying "Côte d'Ivoire", "Côte d&#039;Ivoire" is displayed...

My proposition to fix this is to remove the check_plain in hook_apachesolr_map_callback: let modules which need to actually output text directly (such as facetapi) handle the check_plain...

Status: Needs review » Needs work

The last submitted patch, 1130506-solr-14.patch, failed testing.

Alan D.’s picture

Excellent, some feedback from someone that has the module enabled!!!! I have been running blind, and the maintainer of Apache Solr stated that there was no sanitization and that forced my hand adding the check_plain() function as to plug a potential security hole (albeit a minor one).

Can you also let us know if the function countries_apachesolr_display_callback() is called or used? From the very original patch, this was functionally wrong.

I'm thinking:

function countries_apachesolr_display_callback($facet, $options) {
  if (!empty($facet) && $country = country_load($facet)) {
    return check_plain(countries_t($country, 'name'));
// Or
//    return countries_t($country, 'name');
  }
  return '';
}
guillaumev’s picture

Version: 7.x-2.0-beta2 » 7.x-2.x-dev
Status: Needs work » Needs review
FileSize
471 bytes

Attaching new patch for testing

guillaumev’s picture

@Alan D > That's interesting, I commented out the function countries_apachesolr_display_callback, cleared my caches and the facet still displays without any problem... So it seems like countries_apachesolr_display_callback is not called or used...

Alan D.’s picture

@guillaumev
Since I am not in a position to test, can you edit one country and insert a couple of test values for me please?

<em>Test</em>
<script>alert('test')</script>Test

Alan D.’s picture

Status: Needs review » Fixed

Pushed #17

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.