Problem/Motivation

This code in Geocoder::geocode() is looping through an array of the form [$plugin_id => plugin_label:

   public function geocode($data, array $plugins, array $options = []) {
    foreach ($plugins as $plugin_id) {

on systems that are case-sensitive, this results in $plugin_id being set, for instance, to GoogleMaps, resulting in this error:

Drupal\Component\Plugin\Exception\PluginNotFoundException: The "GoogleMaps" plugin does not exist.

Proposed resolution

Use array_keys for the loop to get the actual plugin ID.

Remaining tasks

User interface changes

API changes

Data model changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jhedstrom created an issue. See original summary.

jhedstrom’s picture

Status: Active » Needs review
FileSize
521 bytes
Pol’s picture

Assigned: Unassigned » Pol
jhedstrom’s picture

Hmm, it isn't quite this simple of a fix. I think some code is calling Geocode:geocoder() with a simple numericly keyed array of plugin IDs, so with this patch, the result is

The "0" plugin does not exist.
jhedstrom’s picture

FileSize
820 bytes
1.31 KB

The interface docs for this method state:

   * @param array $options
   *   (optional) An associative array with plugin options, keyed plugin by the
   *   plugin id. Defaults to an empty array.

so ones that are just calling it with the plugin ID should be fixed. Thus far I've found that geocoder_field_entity_presave was calling the method with a simple array of plugin IDs.

This isn't the most elegant fix, but it gets the code working again...

jhedstrom’s picture

And this is the code that was calling with the full array (plugin_id => definition) in AddressGeocodeFormatter:

         if ($addressCollection = $this->geocoder->geocode(implode(',', array_filter($address)), $this->getEnabledProviderPlugins())) {

  • Pol committed f192975 on 8.x-2.x authored by jhedstrom
    Issue #2841914 by jhedstrom: Geocoder::geocode() is looping through...
Pol’s picture

Status: Needs review » Fixed

Thanks!

GlenAware’s picture

While following the following example:
https://github.com/drupol/geocoder/blob/8.x-2.x/README.md

I get the following error:
The "0" plugin does not exist.

The following patch was applied.
modules/gecoder/src/Geocoder.php
From

  public function geocode($data, array $plugins, array $options = []) {
    foreach ($plugins as $plugin_id) {
      $options += [$plugin_id => []];
      $provider = $this->providerPluginManager->createInstance($plugin_id, $options[$plugin_id]);

To

  public function geocode($data, array $plugins, array $options = []) {
    foreach (array_keys($plugins) as $plugin_id) {
      $options += [$plugin_id => []];
      $provider = $this->providerPluginManager->createInstance($plugin_id, $options[$plugin_id]);



The problem was resolved when I reverted the patch.


Output $options with patch:

array(4) {
  ["geonames"]=>
  array(0) {
  }
  ["googlemaps"]=>
  array(0) {
  }
  ["bingmaps"]=>
  array(0) {
  }
  [0]=>
  array(0) {
  }
}

Output $options without patch:

array(3) {
  ["geonames"]=>
  array(0) {
  }
  ["googlemaps"]=>
  array(0) {
  }
  ["bingmaps"]=>
  array(0) {
  }
}

$options being supplied to geocode:

array(3) {
  ["geonames"]=>
  array(0) {
  }
  ["googlemaps"]=>
  array(0) {
  }
  ["bingmaps"]=>
  array(0) {
  }
}



Tldr; Problem was resolved when reverting patch

ArnaudDabouis’s picture

Is this the final API ? Because it breaks the latest dev of search_api_location for example. Should I provide a patch for that module to match the changes applied here ?

If so, I think the documentation of the GeocoderInterface, which mentions, about $plugins, "A list of plugin identifiers to use.", should be updated.

/**
   * Geocodes a string.
   *
   * @param string $data
   *   The string to geocoded.
   * @param string[] $plugins
   *   A list of plugin identifiers to use.
   * @param array $options
   *   (optional) An associative array with plugin options, keyed plugin by the
   *   plugin id. Defaults to an empty array.
   *
   * @return \Geocoder\Model\AddressCollection|null
   *   An address collection or NULL on gecoding failure.
   */
  public function geocode($data, array $plugins, array $options = []);

I'm personally reverting to previous commit for now.

Status: Fixed » Closed (fixed)

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

robertshell22’s picture

Here's a patch that applies to the latest 2.x-dev.

Pol’s picture

Thanks !

itamair’s picture

The #12 patch introduces a great regression and everything breaks.
The committed #12 patch should be reverted immediately as not needed, and indeed harmful.
To verify just enable a Geocode operation on a field with just a Plugin.
The Drupal\geocoder\Geocoder geocode function will fail, as the $plugins already is an array of plugins machine names,
and array_keys($plugins) will return a list of not existing plugins.
So ... IMO we should really immediately revert the just committed #12 patch ...

itamair’s picture

Status: Closed (fixed) » Active
itamair’s picture

Once the committed #12 patch has been reverted this issue might be closed anyway, because this sounds to me as an old-outdated issue.
(fixed by the last beta versions of the module)

  • itamair committed b45eee9 on 8.x-2.x
    Revert "Issue #2841914 by jhedstrom, robertshell22: Geocoder::geocode()...
itamair’s picture

reverted the previously committed #12 patch.
Closing this one ...

itamair’s picture

Status: Active » Fixed

Status: Fixed » Closed (fixed)

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