Similar to its Drupal 7 version #1269608: Integrate Addressfield with Search API

The Address module stores country and state information in the database as abbreviations such as NY for New York and US for United States. Unfortunately, this is how the Search API indexes the information meaning that the an aggregated fulltext search filter will not return results for 'United States' and 'New York' but only for US and NY. The Search API faceted search blocks for the Addressfield's country field does show the full name of the country but only the abbreviated letters for the state.

The Search API does have an API hook to alter the values of the items being indexed, function hook_search_api_index_items_alter(array &$items, SearchApiIndex $index), however, I can not find a way to change the values of the country and state abbreviations to the full name using any Address module's functions.

CommentFileSizeAuthor
#81 search_api_facet_values.png23.36 KBrobpowell
#81 search_api_configure_processor.png55.8 KBrobpowell
#81 search_api_add_processor.png58.91 KBrobpowell
#81 search_api_add_field.png211.17 KBrobpowell
#77 address-integrate_address_searchapi-2812659-77.patch8.97 KBrecrit
#77 interdiff-2812659-74-77.txt1.95 KBrecrit
#74 interdiff-2812659-69-74.txt1.29 KBmanuel.adan
#74 address-integrate_address_searchapi-2812659-74.patch8.84 KBmanuel.adan
#73 interdiff-2812659-69-73.txt914 bytesmanuel.adan
#73 address-integrate_address_searchapi-2812659-73.patch8.82 KBmanuel.adan
#70 address-n2812659-37-fix.interdiff.txt1.09 KBdamienmckenna
#70 address-n2812659-37-fix.patch10.31 KBdamienmckenna
#69 address-integrate_address_searchapi-2812659-69-D8.patch9.02 KBgolddragon007
#68 address-field.jpg44.58 KBgolddragon007
#59 integrate-address-searchapi-2812659-58.patch8.64 KBghenov.andrei
#57 integrate-address-searchapi-2812659-57.patch8.62 KBdidierdemaeyer
#57 interdiff-56-57.txt8.07 KBdidierdemaeyer
#56 interdiff-53-56.txt1.03 KBoleksiy
#56 integrate-address-searchapi-2812659-56.patch6.72 KBoleksiy
#54 interdiff-52-53.txt877 bytesandrew answer
#53 integrate-address-searchapi-2812659-53.patch6.6 KBandrew answer
#52 interdiff-47-52.txt816 bytesvflirt
#52 integrate-address-searchapi-2812659-52.patch6.4 KBvflirt
#48 interdiff-46-47.txt317 bytesandrew answer
#48 integrate-address-searchapi-2812659-47.patch6.36 KBandrew answer
#47 interdiff-45-46.txt1.72 KBandrew answer
#47 integrate-address-searchapi-2812659-46.patch6.36 KBandrew answer
#46 interdiff-23-44.txt1.1 KBandrew answer
#45 interdiff-44-45.txt771 bytesandrew answer
#45 integrate-address-searchapi-2812659-45.patch6.19 KBandrew answer
#44 integrate-address-searchapi-2812659-44.patch6.16 KBandrew answer
#37 interdiff-2812659-28-37.txt1.5 KBrecrit
#37 address-search-api-full-name-properties-2812659-37.patch9.87 KBrecrit
#33 Screen Shot 2018-04-09 at 12.19.14 pm.png38.75 KBnickbits
#28 address-search-api-full-name-properties-2812659-28.patch9.92 KBrecrit
#23 interdiff-2812659-17-23.txt5.33 KBchriscalip
#23 integrate-address-searchapi-2812659-23.patch6.26 KBchriscalip
#23 abbrev2full-indexrecord.png176.72 KBchriscalip
#23 abbrev2full-noderecord.png144.86 KBchriscalip
#23 abbrev2full-processor-admin-config.png142.5 KBchriscalip
#18 screenshot-address-search-api-configuration.png141.77 KBchriscalip
#17 integrate-address-searchapi-2812659-17.patch7.11 KBchriscalip
#8 interdiff-2812659-5-8.txt4.64 KBchriscalip
#8 integrate-address-searchapi-2812659-8.patch5.6 KBchriscalip
#8 2812659-address-processor-US-MX.png190.75 KBchriscalip
#5 2812659-after-address-processor-indexed.png175.84 KBchriscalip
#5 2812659-address-processor-settings.png134.44 KBchriscalip
#5 2812659-before-address-processor-indexed.png175.42 KBchriscalip
#5 2812659-before-index-no-address-preprocessor.png152.09 KBchriscalip
#4 integrate-address-searchapi-2812659-4.patch5.13 KBchriscalip

Issue fork address-2812659

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

chriscalip created an issue. See original summary.

bojanz’s picture

AddressPlainFormatter is a good example of getting both the codes and the full names.

chriscalip’s picture

Assigned: Unassigned » chriscalip

@bojanz
Thanks for the info. Currently building patch.

chriscalip’s picture

Assigned: chriscalip » Unassigned
Status: Active » Needs review
StatusFileSize
new5.13 KB

Patched Attached.

chriscalip’s picture

Screenshots of successful test attached.

Screenshots before Address Field : Full Administrative Area got activated.
2812659-before-address-processor-indexed.png
2812659-before-index-no-address-preprocessor.png

Screenshots of processor Address Field : Full Administrative use.
2812659-address-processor-settings.png
2812659-after-address-processor-indexed.png

borisson_’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests
  1. +++ b/src/Plugin/search_api/processor/FullAdministrativeArea.php
    @@ -0,0 +1,143 @@
    +
    +
    

    Should be only one line.

  2. +++ b/src/Plugin/search_api/processor/FullAdministrativeArea.php
    @@ -0,0 +1,143 @@
    + *   id = "full_administrative_area",
    

    Not sure about this id, let's prefix this with address field as well.

  3. +++ b/src/Plugin/search_api/processor/FullAdministrativeArea.php
    @@ -0,0 +1,143 @@
    + *   label = @Translation("Address Field : Full Administrative Area"),
    + *   description = @Translation("Processor for appending address field full text value of administrative_area (state) to its abbreviation i.e., IL => IL Illinois."),
    

    Let's mention in the label or description that this is only useful for US states.

  4. +++ b/src/Plugin/search_api/processor/FullAdministrativeArea.php
    @@ -0,0 +1,143 @@
    +    $this->subdivisionRepository = \Drupal::service('address.subdivision_repository');
    

    We don't do this, we usually extend the contructor and implemt a create method to set those in.

  5. +++ b/src/Plugin/search_api/processor/FullAdministrativeArea.php
    @@ -0,0 +1,143 @@
    +        continue;
    +      }
    +      if ($this->testType($field->getType())) {
    

    I don't think we need to do it like that, can be refactored to be shorter.

    $admin_area_field = (strpos($field->getPropertyPath(), ':administrative_area') === FALSE)
    if ($this->testType($field->getType() && $admin_area_field) {
    

This will also need at least a unit test, maybe integration as well (even though that'd need to have address as a test-dependency - so not sure about that.

borisson_’s picture

Oh wait, this is in the address queue - not in search api.
The fourth issue I posted is probably not as relevant as for the search api queue.

This makes the integration test also a lot less viable, so that's probably not needed. Also not sure how strict @bojanz is about unit tests.

chriscalip’s picture

Ok here's the patch:
Also here are response point by point from comment # 6.

1. Fixed. Additional ran phpcs using drupal codesniffer standards.
2. This is directly related to comment # 7. To be clear I dont think it is necessary to prefix with address field because it already namespace for address.

✝ vagrant@multi-vlad ✝ ../www/site/vlad_aux/d8-dev
$ drupal plugin:debug search_api.processor
 -------------------------- -------------------------------------------------------------------
  Plugin ID                  Plugin class
 -------------------------- -------------------------------------------------------------------
  add_url                    Drupal\search_api\Plugin\search_api\processor\AddURL
  aggregated_field           Drupal\search_api\Plugin\search_api\processor\AggregatedFields
  content_access             Drupal\search_api\Plugin\search_api\processor\ContentAccess
  full_administrative_area   Drupal\address\Plugin\search_api\processor\FullAdministrativeArea
  highlight                  Drupal\search_api\Plugin\search_api\processor\Highlight
  html_filter                Drupal\search_api\Plugin\search_api\processor\HtmlFilter
  ignore_character           Drupal\search_api\Plugin\search_api\processor\IgnoreCharacters
  ignorecase                 Drupal\search_api\Plugin\search_api\processor\IgnoreCase
  node_status                Drupal\search_api\Plugin\search_api\processor\NodeStatus
  rendered_item              Drupal\search_api\Plugin\search_api\processor\RenderedItem
  role_filter                Drupal\search_api\Plugin\search_api\processor\RoleFilter
  stopwords                  Drupal\search_api\Plugin\search_api\processor\Stopwords
  tokenizer                  Drupal\search_api\Plugin\search_api\processor\Tokenizer
  transliteration            Drupal\search_api\Plugin\search_api\processor\Transliteration
 -------------------------- -------------------------------------------------------------------

3. This processor for address is meant for all of the countries. Here's a screenshot, 2812659-address-processor-US-MX.png, that this processor is working for Mexico and United States. For illustration purposes here's code at main algorithm compressed in a simple script. The addressing api means to have a subdvision code and subdivision full name. Admittedly Canada in this example is using subdivision code for its subdivision name. But I believe thats for another issue entirely.

✝ vagrant@multi-vlad ✝ ../www/site/vlad_aux/d8-dev
$ more test.php
<?php

use CommerceGuys\Addressing\AddressFormat\AddressFormatRepository;
use CommerceGuys\Addressing\Subdivision\SubdivisionRepository;

$addressFormatRepository = new AddressFormatRepository();
$subdivisionRepository = new SubdivisionRepository();

$countries = array(
  'CA' => 'Canada',
  'MX' => 'Mexico',
  'US' => 'United States',
);

foreach ($countries as $country_code => $country) {
  $addressFormat = $addressFormatRepository->get($country_code);
  $states = $subdivisionRepository->getAll([$country_code]);
  echo "$country_code for $country". PHP_EOL;
  foreach ($states as $state) {
    echo $state->getCode() . ' - ' . $state->getName() . ' | ';
  }
  echo 'end' . PHP_EOL;
}

✝ vagrant@multi-vlad ✝ ../www/site/vlad_aux/d8-dev
$ drush scr test.php
CA for Canada
AB - AB | BC - BC | MB - MB | NB - NB | NL - NL | NT - NT | NS - NS | NU - NU | ON - ON | PE - PE | QC - QC | SK - SK | YT - YT | end
MX for Mexico
MEX - México | AGS - Aguascalientes | BC - Baja California | BCS - Baja California Sur | CAMP - Campeche | CHIS - Chiapas | CHIH - Chihuahua | COAH - Coahuila | COL - Colima | D.F. - Distrito Federal | DGO - Durango | GTO - Guanajuato | GRO - Guerrero | HGO - Hidalgo | JAL - Jalisco | MICH - Michoacán | MOR - Morelos | NAY - Nayarit | NL - Nuevo León | OAX - Oaxaca | PUE - Puebla | QRO - Querétaro | QROO - Quintana Roo | SLP - San Luís Potosí | SIN - Sinalóa | SON - Sonora | TAB - Tabasco | TAMPS - Tamaulipas | TLAX - Tlaxcala | VER - Veracruz | YUC - Yucatán | ZAC - Zacatecas | end
US for United States
AL - Alabama | AK - Alaska | AS - American Samoa | AZ - Arizona | AR - Arkansas | AA - Armed Forces (AA) | AE - Armed Forces (AE) | AP - Armed Forces (AP) | CA - California | CO - Colorado | CT - Connecticut | DE - Delaware | DC - District of Columbia | FL - Florida | GA - Georgia | GU - Guam | HI - Hawaii | ID - Idaho | IL - Illinois | IN - Indiana | IA - Iowa | KS - Kansas | KY - Kentucky | LA - Louisiana | ME - Maine | MH - Marshall Islands | MD - Maryland | MA - Massachusetts | MI - Michigan | FM - Micronesia | MN - Minnesota | MS - Mississippi | MO - Missouri | MT - Montana | NE - Nebraska | NV - Nevada | NH - New Hampshire | NJ - New Jersey | NM - New Mexico | NY - New York | NC - North Carolina | ND - North Dakota | MP - Northern Mariana Islands | OH - Ohio | OK - Oklahoma | OR - Oregon | PW - Palau | PA - Pennsylvania | PR - Puerto Rico | RI - Rhode Island | SC - South Carolina | SD - South Dakota | TN - Tennessee | TX - Texas | UT - Utah | VT - Vermont | VI - Virgin Islands | VA - Virginia | WA - Washington | WV - West Virginia | WI - Wisconsin | WY - Wyoming | end

✝ vagrant@multi-vlad ✝ ../www/site/vlad_aux/d8-dev

4. This is directly related to comment # 7. I believe this approach is ok as it makes use of existing resources provided by address module.
5. Nice, updated per suggestion.
6. About integration test and unit test.. yeah i think thats overkill :) please help.

chriscalip’s picture

Status: Needs work » Needs review
borisson_’s picture

If no tests are needed, this looks rtbc to me.

chriscalip’s picture

Status: Needs review » Reviewed & tested by the community

Setting to conditional RTBC per previous comment. Up to address maintainers on go ahead.

bojanz’s picture

Status: Reviewed & tested by the community » Needs work
+  /**
+   * Stored Administrative Areas indexed by country_country.
+   *
+   * Used as a cache.
+   *
+   * @var array
+   */
+  protected $heapAdministrativeAreas = array();
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->addressFormatRepository = \Drupal::service('address.address_format_repository');
+    $this->subdivisionRepository = \Drupal::service('address.subdivision_repository');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+    $fields = $this->index->getFields();
+    $field_options = array();
+    $default_fields = array();

1) We never use array() in Drupal anymore, only short array syntax: [].
2) The address format and subdivision repositories can be injected, you don't need to use \Drupal::service()?
3) I've never seen the convention of using "heap" as a prefix for static caches? Probably unneeded?

+    // Get the subdivisions for country.
+    $states = $this->subdivisionRepository->getAll([$country_code]);
+    foreach ($states as $state) {
+      $state_code = $state->getCode();
+      $administrative_areas[$state_code] = $state_code . ' - ' . $state->getName();
+    }

In the same block of code you use subdivisions, administrative areas, states. Only the first one is precise (state is just one label that an administrative area could have).

Architectural issues:
1) I don't see this code accounting for a country not having any subdivisions defined? In which case the static cache will always be empty and you will call subdivisionRepository->getAll() for each item? The library optimizes this away, but for clarity's sake it would make sense to acknowledge in the code that it's a possibility.

2) Some countries (Russia, China, Japan, etc) also have a local code and a local name (cyrlic, chinese version, etc). You would want to add those as well. The local code and the local name could be identical, in which case you'd only add the local code.

3) We would ideally register this handler for the locality and dependent_locality fields as well, load the right values using the parents. Brazil has predefined localities, China has both predefined levels. On those two levels the name could be the same as the code (cause there's no actual abbreviation to use), in which case you could skip adding it.

yoran scholiers’s picture

This patch does not work correctly for me but I might be misunderstanding the desired functionality.
Instead of displaying the full country name (instead of the code) it displays the administrative subdivision.
So in this case the result is:
Country = wv - West Vlaanderen
subdevision = wv

EDIT
Never mind, I did misunderstand the purpose..
I was able to make it work for the country name as well.

Anyway, out of the box search_api integration would be a very nice to have.

chriscalip’s picture

Well changes from 8.x-1.0-beta3 to 8.x-1.0-beta4 broke api again.. and I don't want to deal doing constant corresponding changes to the API for this plugin patch. Maybe this plugin is safe from the api changes brought about by destructive patch https://www.drupal.org/node/2656052 I don't know, and I don't want to spend time and effort to something that will probably again change.
I'll revisit patch build once search_api gets to 1.x stable.

chriscalip’s picture

Looks like d8 search_api getting in a stable place. Going back to work on this patch.

drunken monkey’s picture

I won't comment on general code style issues, etc., just on the Search API side of things:

+        $field->setValues($new_data);
+        if ($this->testField($name, $field)) {
+          $this->processField($field);
+        }

Largest problem: you mustn't use setValues() to set unprocessed values on a field, as the documentation notes. Use addValue() instead. (Cf. #2764385: Aggregated text plugin setting field value without datatype.)

Also, if you don't override/implement process() (or any of the other process*() methods) anyways, there's no need to call processField() from here.

Finally, I agree with Joris, the plugin ID should definitely be prefixed with the module name – as everywhere in Drupal. Only the module defining the plugin type (the Search API, in this case) can be exempt, as that sets the standard, which more or less guarantees there won't be any clashes (provided we're careful with new plugins now that 1.0 is out). For other modules, this can't be guaranteed, so the prefix is needed.
Again, it's the same for all other plugin types in Drupal.

chriscalip’s picture

This patch is based on suggestions found in comment #12 by bojanz, and comment #16 by drunken monkey, and my own project needs.

A) comment#12 item 3) We would ideally register this handler for the locality and dependent_locality fields as well, load the right values using the parents. Brazil has predefined localities, China has both predefined levels. On those two levels the name could be the same as the code (cause there's no actual abbreviation to use), in which case you could skip adding it.

Great idea, I also need this on my projects. Hence plugin processor scope increased from just dealing administrative_area to targeted $this->supportedComponents = ['country_code', 'administrative_area', 'locality', 'dependent_locality'];

B) The plugin is now id = "address_abbreviations_to_full_form", class AddressAbbreviationsToFullForm per increased scope and comment#16.

C) configuration per field_name and component. So far we have configuration 'concat' in play.
Potentially doing :
country_code : US - United States
country_code : United States
administrative_areas: IL - Illinois
administrative_areas: Illinois

D) Point by point addressing comment #12 by bojanz
1) We never use array() in Drupal anymore, only short array syntax: [].
-- done. code changed to short array syntax
2. The address format and subdivision repositories can be injected, you don't need to use \Drupal::service()?
-- I was only using existing examples in address module codebase. What's the alternative way to inject these repos?
3) I've never seen the convention of using "heap" as a prefix for static caches? Probably unneeded?
-- done. code changed.. static caches removed, triangulation is derived strictly from api.
Architectural issues:
1) I don't see this code accounting for a country not having any subdivisions defined? In which case the static cache will always be empty and you will call subdivisionRepository->getAll() for each item? The library optimizes this away, but for clarity's sake it would make sense to acknowledge in the code that it's a possibility.
-- N/A because of code change.
2) Some countries (Russia, China, Japan, etc) also have a local code and a local name (cyrlic, chinese version, etc). You would want to add those as well. The local code and the local name could be identical, in which case you'd only add the local code.
-- cool, code changed.

E) comment#16

Also, if you don't override/implement process() (or any of the other process*() methods) anyways, there's no need to call processField() from here.
-- done. code updated.

Largest problem: you mustn't use setValues() to set unprocessed values on a field, as the documentation notes. Use addValue() instead.
-- I am unable to comply with suggestion as the processor plugin requires update of address component code value to full text value. I am unable to make use of $field->addValue()
Reference: search_api/src/Item/Field.php

  /**
   * {@inheritdoc}
   */
  public function addValue($value) {
    // The data type has to be able to alter the given value before it is
    // included.
    $data_type_plugin = $this->getDataTypePlugin();
    if ($data_type_plugin) {
      $value = $data_type_plugin->getValue($value);
    }

    $this->values[] = $value;
    return $this;
  }

This appends the full text value to a random delta on value.. its pretty unreliable and unusable for this situation. Please update patch if there is a way.

chriscalip’s picture

Screenshot of configuration of processor plugin at search_api dashboard.

chriscalip’s picture

Status: Needs work » Needs review
chriscalip’s picture

Patch #17 is not enough. Sadly patch #17 does not hit 100% when used in live production situations. This patch fails to handle situations where same field and component is used n times. It clearly needs attributes from "field_name,component" to "field_name,component,machine_name". Patch needs work.

chriscalip’s picture

Status: Needs review » Needs work
chriscalip’s picture

Assigned: Unassigned » chriscalip
chriscalip’s picture

This patch, integrate-address-searchapi-2812659-23.patch, fixes concerns by comment #20.

a.) Processor is now centered around the search_api index fields instead of entity fields and its components.
b.) run through of codebase on phpcs per drupal.org/project/coder 8.x styleguide.
c.) Screenshot abbrev2full-processor-admin-config.png shows processor configuration per search_api index field.
d.) Screenshot abbrev2full-noderecord.png shows node records with multiple address field values.
e.) Screenshot abbrev2full-indexrecord.png shows delta alignment. Delta alignment is why I think $field->addValue() does not apply for this situation.
f.) interdiff-2812659-17-23.txt :)

chriscalip’s picture

Assigned: chriscalip » Unassigned
Status: Needs work » Needs review

Patch needs review.

gnuget’s picture

Hi!

Thanks for all the work on this patch.

I tried this today and I got an error when the data is re-indexing if I set the type as "full text" in the fields page.

Fatal error: Call to a member function getTokens() on string in /vagrant/web/modules/contrib/search_api/modules/search_api_db/src/Plugin/search_api/backend/Database.php on line 1387

drunken monkey’s picture

I tried this today and I got an error when the data is re-indexing if I set the type as "full text" in the fields page.

Yes, that's exactly what will happen if setValues() is used instead of addValue().

gnuget’s picture

Status: Needs review » Needs work

So, this needs work, yes?

Thanks!

recrit’s picture

Status: Needs work » Needs review
StatusFileSize
new9.92 KB

This can implemented cleaner by extending the property definitions of the address field items with computed fields for the full names of the sub-properties.
With the full names as field item properties:
* Search API automatically finds them.
* They can be added to the Search API index fields as needed.
* Concatenation can be accomplished with Search API's "Aggregated fields" with the code property and the equivalent new full name property.

The attached patch adds:

  • Plugin/Field/FieldType/AddressItem: Added full name computed properties added for: country_code, administrative_area, locality, dependent_locality.
  • Plugin/Field/FieldType/CountryItem: Added full name computed properties added for: value.
  • Created TypedData classes for SubdivisionName and CountryName that act similar to the views field handlers.
chriscalip’s picture

Heads up, I'll stop participating on this issue for the time being because most of my current and immediate projects are rest-api based which is mostly laravel.

vaccinemedia’s picture

@recrit I can't add the address fields using the patch above to facets unfortunately... I get this:
Error: Call to undefined method Drupal\Core\TypedData\DataDefinition::getPropertyDefinitions() in Drupal\facets\Plugin\facets\processor\BooleanItemProcessor->supportsFacet() (line 92 of /var/www/vhosts/example.dev/web/modules/contrib/facets/src/Plugin/facets/processor/BooleanItemProcessor.php) #0

borisson_’s picture

#30 is a bug in facets, see #2917323: Critical error thrown when editing a facet based on an aggregated field - please confirm if the patch there fixes your problem.

vaccinemedia’s picture

@borisson_ thanks for the link. This did indeed fix the issue. Just to clarify - I have a content type with an address field and search api installed using database (for now may up to using solar before the project is finished). Instead of using the patch by chriscalip which appears to add a processor option to the index I went for the latest patch by recrit which adds the full country name to the list of fields I can add to the index.

I have created a view based on the index and added 4 of the required fields into a table display.

I then added some facets for taxonomy terms which worked great. Then I got the error mentioned above for country name but the patch you referenced has enabled me to fully configure the facet and place all the blocks required for testing. So for that - thanks very much!

Quick question though as I prefer to make sure I'm doing things correctly: In your opinion, which patch should I be using here? The one by chriscalip which adds a processor plugin specifically for address fields or recrit which allows you to add the country field with nothing extra turned on?

nickbits’s picture

StatusFileSize
new38.75 KB

Hi,

I applied the patch in #28 thinking it would fix my issue. Sadly doesn't seem to be working for me. I may have missed the point totally here. Here is what I have - a content type with an address field. Got Search API installed using database for the index.

Can add the address field to the agregated content.

For the field I can add additional_name, locality_name, address_line1 and so on. However it does report one field skipped, field_item:address (see attached screenshot).

Ignoring this I add the fields, perform a re-index, and do a search for something I know is in one of the fields. Location name, postcodes, etc. It does find most of them. The only one that doesn't seem to work is "Company" which is what I assume is Organization.

andriy khomych’s picture

Hi Bojan Živanović, Michael Vanetta.

Why wasn't https://www.drupal.org/files/issues/address-search-api-full-name-properties-2812659-28.patch added to the module? Except for comment https://www.drupal.org/project/address/issues/2812659#comment-12563243, it works clear and I think is the best suggestion. However, it requires some views filter for the Search API like Drupal\address\Plugin\views\filter\AdministrativeArea. Can you check this issue again and maybe update main issue goals? E.g. if somebody wants to finish this issue.

andriy khomych’s picture

Status: Needs review » Needs work
radiumhe’s picture

Version: 8.x-1.x-dev » 8.x-1.4

address 8.x-1.4 "require": "commerceguys/addressing": "^1.0.0" , Addressing\LocaleHelper -> Addressing\Locale

addressing-1.0.0-beta5 is LocaleHelper.php

revise

use CommerceGuys\Addressing\Locale;

$use_local_name = Locale::match($parent->getLocale(), $subdivision->getLocale());
recrit’s picture

Version: 8.x-1.4 » 8.x-1.x-dev
StatusFileSize
new9.87 KB
new1.5 KB

@radiumhe Thanks for locale change!
Patch re-rolled for the latest 8.x-1.x as of #a29a522.

recrit’s picture

Status: Needs work » Needs review

updated status

kyuubi’s picture

Hi guys,
Patch seems to be working for me.
When can we make this RTBC?

rbosscher’s picture

Status: Needs review » Reviewed & tested by the community

I have used #37 successfully for a while now, I believe when multiple users has tested the patch with success we can mark this RTBC.

bojanz’s picture

Status: Reviewed & tested by the community » Needs work

#28 and later are "won't fix" as far as I'm concerned. We are not going to modify the field type itself to support a contrib module, especially since the original approach seemed to be valid (adding search-api specific plugins).

Rewriting the patch mid-issue after it has already been reviewed is a good way to ensure an issue never lands.

chriscalip’s picture

To my future self or anyone wanting to move this issue forward.

Notes to move forward #23 patch. Approach via search-api specific plugins

a.) Instead of method preprocessIndexItems use addFieldValues; this will make patch compliant to comment #16
For an example see search_api/src/Plugin/search_api/processor/AddUrl.php
Also see https://www.drupal.org/docs/8/modules/search-api/developer-documentation...
Check into #36 tidbit.

b.) Please create unit tests.

I know its tedious but it saves the contrib maintainer(s) future time and effort by having unit test. Yes --> address module has reached that complexity threshold needing unit-tests. Unit test(s) helps software maintainers be able to safely add-in new features/new fixes/new changes. For example on upcoming address 8.2.x a unit-test gives visibility IF these plugins breaks with a new major version.
Breaking changes happens on major versions. address 8.1.x -> address 8.2.x

For patch to have a unit-test regimen I suggest a split of responsibilities per class.
Country to full text as Drupal\address\Plugin\search_api\processor\AddressTextCountry, Drupal\address\Plugin\search_api\processor\AddressCodeTextCountry
processor\AddressTextCountry strictly does country to full text and processor\AddressCodeTextCountry doing country code with full text of country.
Administrative Area as Drupal\address\Plugin\search_api\processor\AddressTextAdminArea, Drupal\address\Plugin\search_api\processor\AddressTextCodeAdminArea, etc..
ie. https://en.wikipedia.org/wiki/Single_responsibility_principle

For an example of unit-testing see search_api/tests/src/Unit/Plugin/Processor/AddURLTest.php

maskedjellybean’s picture

Is there any way to use the entire address as a single field to build a facet? For example, I'd like a facet block of checkboxes with the entire address as the checkbox label.

Edit: I've realized what I'm asking for would not be practical for usability anyways. Nevermind!

andrew answer’s picture

Hello,

I modified patch #23 to use addValue(). Now I can use full text search field and it works. I also tried to use Search API Autocomplete with Address field, but it doesn't work. I created another issue for this: #3126474: Integrate Address with Search API Autocomplete.

andrew answer’s picture

StatusFileSize
new6.19 KB
new771 bytes

Also, I see notice "Notice: Undefined offset: 1 in Drupal\address\Plugin\search_api\processor\AddressAbbreviationsToFullForm->buildConfigurationForm() (line 69 of modules/contrib/address/src/Plugin/search_api/processor/AddressAbbreviationsToFullForm.php)." in some cases. I fixed it.

andrew answer’s picture

StatusFileSize
new1.1 KB
andrew answer’s picture

Checked on working site and fixed several other errors.

andrew answer’s picture

StatusFileSize
new6.36 KB
new317 bytes

Fixed the typo.

andrew answer’s picture

Status: Needs work » Needs review
langelhc’s picture

Status: Needs review » Needs work

Hello,
After Applying patch #48:

1. In Facets: I get duplicated items (Country code and Country name)

PE (1)
Peru (1)
United States (1)
US (1)

2. Views using Content indexed: When 'Content datasource: address » The two-letter country code (indexed field)' field is added Country code is displayed.

clemens.tolboom’s picture

Issue summary: View changes
vflirt’s picture

Minor fix for when the address is empty.

andrew answer’s picture

This patch replaces the field value instead of adding it, so @langelhc it can probably fix your problem (but the facet case hasn't been tested by me yet).

andrew answer’s picture

StatusFileSize
new877 bytes
oleksiy’s picture

The patch gives me the following error:

ResponseText: Error: Call to a member function setText() on string in Drupal\address\Plugin\search_api\processor\AddressAbbreviationsToFullForm->preprocessIndexItems() (line 167 of /modules/contrib/address/src/Plugin/search_api/processor/AddressAbbreviationsToFullForm.php).

It works only if "Fulltext" field type selected.

And another error I got when tried to apply the previous patch (#52):
Drupal\search_api_solr\SearchApiSolrException while indexing item entity:node/6:en: Solr endpoint http://solr:8983/ bad request (400). ERROR: [doc=674e8e-search_api_solr_index-entity:node/6:en] multiple values encountered for non multiValued field ss_country_code: [UA, Ukraine] in Drupal\search_api_solr\SolrConnector\SolrConnectorPluginBase->handleHttpException() (line 997 of /modules/contrib/search_api_solr/src/SolrConnector/SolrConnectorPluginBase.php).

oleksiy’s picture

StatusFileSize
new6.72 KB
new1.03 KB

Added fix for scalar values.

didierdemaeyer’s picture

Added support for fields on referenced entities.

For example, when you want to use the processor on fields from a user profile (https://www.drupal.org/project/profile).
Then the property path is something like this user_profiles:entity:field_address:country_code

ghenov.andrei made their first commit to this issue’s fork.

ghenov.andrei’s picture

Fixed - warnings about undefined offset.

ghenov.andrei’s picture

// [$field_name, $component, $reference_field_name, $reference_component] = explode(':', $field->getPropertyPath());
[$field_name, $component, $reference_field_name, $reference_component] = array_pad(explode(':', $field->getPropertyPath()), 4, '');

// $target = $reference_component ?? $component;
$target = $reference_component ?: $component;

recrit’s picture

All of the "fixes" for the Search API approach patch - facet support, any index field type, any level of nesting of entity references - were already handled by just adding the computed properties to the address field type in the patch #37.
The Search API Processor Plugin that is post processing an existing indexed field is going to have these issues since you are trying to reproduce what Drupal Core already provides to you with the Field API system. The admin UX also will have the issue where the admin / developer must know that the index type selected on the Search API "Fields" page must be acceptable by the new Search API Processor plugin selected on the Search API "Processors" page.

Adding the computed properties to the field type solves all of these issues for the Search API indexing while exposing the properties for any non Search API usage.
Example: Get the administrative area name.

  // With new computed properties:
  $admin_area_name = $node->field_address->first()->administrative_area_name;

  // vs without computed properties.
  $admin_area_code = $node->field_address->first()->administrative_area;
  $country_code = $node->field_address->first()->country_code;
  if ($admin_area_code && $country_code) {
    $subdivision = \Drupal::service('address.subdivision_repository')->get($admin_area_code, [$country_code]);
    if ($subdivision) {
      $admin_area_name = $subdivision->getName();
    }
  }
damienmckenna’s picture

Maintainers - any feedback on @recrit's comment #61?

damienmckenna’s picture

Status: Needs work » Needs review

Quick reminder - please set the status to "needs review" after you upload a patch so we can see what the testbot thinks of it.

rszrama’s picture

Copying some thoughts over from Slack, let's start by attempting to make the Search API field processor plugin work. If that system was designed to do what this issue desires, I'd second bojanz's earlier desire to make use of it vs. working around it with a pattern unique to this module. (In other words, I'd rather we do what other modules do, if that's the case with the processor, vs. present our own workaround for Address.)

I believe the latest patch to work from is #59, but I haven't tested it myself.

pyxio’s picture

i am getting the following error in drupal 9.3.7

PHP Fatal error: Cannot declare class Drupal\address\Plugin\search_api\processor\AddressAbbreviationsToFullForm, because the name is already in use in /var/www/html/*/web/modules/contrib/search_api/src/Plugin/search_api/processor/AddressAbbreviationsToFullForm.php on line 29

is there a fix? cheers kevin

drunken monkey’s picture

@ pyxio: Seems like you maybe applied the patch to both the Search API and the Address modules, leading to two copies of the same class in your installation? The patch should only be applied to Address, not to Search API.
Please delete the one in web/modules/contrib/search_api/src/Plugin/search_api/processor and make sure there is also one in web/modules/contrib/address/src/Plugin/search_api/processor.

pyxio’s picture

@drunken monkey thanks for the reply. I do not believe I tried to patch search api but I can't confirm that now as I have updated the code base.

Now I have applied the patch successfully and there are no errors. I now have the processor Address Field : Convert Abbreviations into Full Text Form. available and have enabled it. Unfortunately, views field and facet still show abbreviation. I have tried both fulltext and string in the search api fields config. I can't find any other settings.

What else is needed to configure other than enable the processor and reindex? many thanks.

golddragon007’s picture

Status: Needs review » Needs work
StatusFileSize
new44.58 KB

Something does not seem correct to me, I can't select the country code for indexing and therefore I can't apply this preprocess to my address field. To get the country code in the facet list, I need to use the bare field, without any additional "target" or subpath.

Address field

golddragon007’s picture

Status: Needs work » Needs review
StatusFileSize
new9.02 KB

Because the county_code is actually the main property of this field, it can't be referred to as a component like others. So it was needed to adjust the logic.

damienmckenna’s picture

For sites that might be using it, this provides a fix for patch #37 due to changes in the addressing library.

socialnicheguru’s picture

so is #69 or #70 the correct patch?

damienmckenna’s picture

#69 is the preferred path forward, #70 was a fix of #37 necessary for a site that was built using the previous approach where we didn't have time to switch (we'll work on the switch shortly).

manuel.adan’s picture

Added support for country field type.

manuel.adan’s picture

StatusFileSize
new8.84 KB
new1.29 KB

Country field stores the country code in the default 'value' property instead of 'country_code'.

dxvargas’s picture

Patch #74 works well (as did patch #69) with an address field.
I've also tested with a Country field type and the preprocessor worked as expected.

I vote for this to be RTBC.

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

This looks great, I'm not sure how viable it is to add integration tests for this and a unit test doesn't add much value, because it's only the integration with search api that matters.

RTBC based on that.

recrit’s picture

After applying patch address-integrate_address_searchapi-2812659-74.patch, I started to notice the logs being littered with the following warning:

Warning: Undefined array key "value" in Drupal\address\Plugin\search_api\processor\AddressAbbreviationsToFullForm->triangulateCodeToFulltext() (line 198...

Cause:
This is caused by the new code in patch 74 to account for the country field:

$current = $result = $field_value[$target] ?? $field_value['value'];

An address field can have optional properties so $field_value[$target] may actually be NULL for an address field (not a country field).

Fix:
The attached patch changes the line to the following to account for NULL values.

$current = $result = $field_value[$target] ?? ($field_value['value'] ?? NULL);
if (!isset($result)) {
  return $result;
 }

The patch also updates the "preprocessIndexField" method to account for NULL to avoid string operations on a NULL value which causes deprecation notices in PHP 8.1

maxilein’s picture

Does 2.0 work with search api?

bojanz’s picture

Version: 8.x-1.x-dev » 2.x-dev

Changing version to 2.x-dev, this will have to go into the 2.1.0 release, 8.x-1.x is now closed.

proweb.ua’s picture

address 2.0.1
#77 works

robpowell’s picture

Steps to test

  1. Go to your search index's field form admin/config/search/search-api/index/{index_name}/fields
  2. Click "add fields"
  3. Go to your address field and click "expand"
  4. Select one of the supported abbreviation --> to label fields (e.g. country_code, administrative_area, locality, and dependent_locality)
  5. Click "Done" in the modal
  6. Click "save changes"
  7. Go to your search index's processor form, /admin/config/search/search-api/index/{index_name}/processors
  8. Check "Address Field : Convert Abbreviations into Full Text Form"
  9. Scroll to the bottom to the process settings sections
  10. Select "Enable" for your given fields
  11. Click "save"
  12. All items should be queued for index. Now you have to reindex them /admin/config/search/search-api/index/{index_name}
  13. Add the necessary facet(s) to your search api view
  14. you should now see the field labels

I tested on
"drupal/search_api": "1.40.0",
"drupal/address": "2.0.4",
"drupal/facets": "3.0.2",

This works! See screenshots.

search api field form
search api processor form
search api processor configure form
search api view facet results

steinmb’s picture

Issue tags: -Needs tests

Based on #76, remove the need for tests tag. I would help to get this in if the patch would be converted to a MR.

kevinquillen’s picture

Country code is missing for some reason.

kevinquillen’s picture

Actually 'country_code' is represented as 'address' which is quite misleading. It also would index the code and not the country name (I suspect most would want that option) which I could only get with a Custom Value index item and token.

tbkot made their first commit to this issue’s fork.

tbkot’s picture

MR is created based on patch #77