When using tokens, all of the address fields are available as tokens except for the country name.
The only token for country is "country_code".

Can support for a country name token be added?

CommentFileSizeAuthor
#31 interdiff-2915147-29-31-do-not-test.diff2.79 KBlisastreeter
#31 2915147-31-country-name-token.patch12.51 KBlisastreeter
#29 interdiff-2915147-20-29-do-not-test.diff2.99 KBlisastreeter
#29 2915147-29-country-name-token.patch14.22 KBlisastreeter
#28 interdiff-2915147-20-28-do-not-test.diff2.77 KBlisastreeter
#28 2915147-28-country-name-token.patch13.95 KBlisastreeter
#26 interdiff-2915147-20-26-do-not-test.diff2.64 KBlisastreeter
#26 2915147-26-country-name-token.patch13.64 KBlisastreeter
#24 interdiff-2915147-20-24-do-not-test.diff2.54 KBlisastreeter
#24 2915147-24-country-name-token.patch13.67 KBlisastreeter
#23 interdiff-2915147-20-23-do-not-test.diff2.34 KBlisastreeter
#23 2915147-23-country-name-token.patch13.66 KBlisastreeter
#22 interdiff-2915147-20-22-do-not-test.diff3.81 KBlisastreeter
#22 2915147-22-country-name-token.patch12.2 KBlisastreeter
#21 interdiff-2915147-20-21-do-not-test.diff3.21 KBlisastreeter
#21 2915147-21-country-name-token.patch12.04 KBlisastreeter
#20 2915147-20-country-name-token.patch13.07 KBbojanz
#19 interdiff-2915147-13-19-do-not-test.diff703 byteslisastreeter
#19 country-name-token-2915147-19.patch13.17 KBlisastreeter
#17 Country_name_token.png79.01 KBlisastreeter
#13 country-name-token-2915147-13.patch13.46 KBlisastreeter
#12 country-name-token-2915147-12.patch13.88 KBlisastreeter
#11 country-name-token-2915147-11.patch13.85 KBlisastreeter
#10 country-name-token-2915147-10.patch13.6 KBlisastreeter
#9 country-name-token-2915147-9.patch13.4 KBlisastreeter
#8 country-name-token-2915147-8.patch13.36 KBlisastreeter
#7 country-name-token-2915147-7.patch13.3 KBlisastreeter
#6 country-name-token-2915147-6.patch12.03 KBlisastreeter
#5 country-name-token-2915147-5.patch12.07 KBlisastreeter
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

weseze created an issue. See original summary.

rmcdahal’s picture

Any Updates ?

rmcdahal’s picture

Still No Solutions For This
I have opened another issue

weseze’s picture

Why did you open a new ticket for the exact same issue?

lisastreeter’s picture

First attempt at a country name token patch, with tests.

lisastreeter’s picture

Update to try to get tests to run.

lisastreeter’s picture

Continuing to work on test code.

lisastreeter’s picture

missing use statement fixed.

lisastreeter’s picture

explicitly enable token module

lisastreeter’s picture

lisastreeter’s picture

lisastreeter’s picture

Added to kernel test annotation:
* @requires module token

lisastreeter’s picture

lisastreeter’s picture

Status: Active » Needs review

Country name has been added as an option for any address field.

In order to get the address implementation of hook_tokens to execute after the hook_tokens function for the field module (in token.tokens.inc), I needed to implement hook_module_implements_alter.

bojanz’s picture

Great job on the tests!

Could we have used hook_token_info_alter() to avoid needing address_module_implements_alter()?

+      $types[$token_type . '-' . $field_name . '-country_name'] = [
+        'name' => 'Country name',
+        'description' => NULL,
+        'needs-data' => $token_type . '-' . $field_name . '-country_name',
+      ];

Why do we need a custom type? Shouldn't we be able to reuse an existing field token type, as defined in https://cgit.drupalcode.org/token/tree/token.tokens.inc#n1391?

lisastreeter’s picture

@bojanz Thank you. I did try using hook_token_info_alter() instead of hook_token_info(), but it didn't seem to make any difference. I can try again, though, if you think it might. I tried so many different things that it's quite possible I missed some simple combination.

As for the custom type, initially, I just created the country_name tokens as if country_name was just another property of the address field and for the token type, I just used:
\Drupal::service('token.entity_mapper')->getTokenTypeForEntityType($entity_type_id)

That worked fine, but I thought that maybe creating a custom type would somehow differentiate country_name from the actual address field properties, to help with my hook_tokens not getting overridden by logic in the token.tokens.inc field_tokens() method. Also, it seemed like everything I read about, "how to create custom tokens", started by explaining how to create a custom type. So I thought perhaps my code would be somehow incomplete if I didn't. (Even though it worked without it.) I'll happily remove the custom type to simplify the code.

As for getting rid of address_module_implements_alter(), my issues that field_tokens() (in token.tokens.inc) treats 'country_name' as if it's just another address field property and does this to my tokens (line 1695):

$replacements[$original] = $field_item->$property_name;

Since $field_name->country_name doesn't exist, and since field_tokens() executes after address_tokens(), my country_name replacement values are overwritten.

Essentially, I think my issue is that I want country_name tokens to behave as if they're address field properties so that they'll show up nicely in the tokens UI as part of address fields. But then when it comes time to replace the tokens with the actual values, I'd like for field_tokens() to just leave them alone and not try to set a replacement value for a field property that doesn't actually exist.

lisastreeter’s picture

FileSize
79.01 KB

I did some experimenting. If I change the field type to an existing type like this:

'type' => $token_type . '-' . $field_name,

Then a weird little drop-down triangle appears next to the country name token (with nothing underneath it when clicked.)
Image of Tokens UI

For normal field properties, the 'type' is omitted from the definition:

          $info['tokens'][$field_token_name][$property] = [
            'name' => $property_definition->getLabel(),
            'description' => $property_definition->getDescription(),
            'module' => 'token',
          ];

If I omit type from the token definition for the country_name, everything seems to work fine, and the funny triangle does not appear. So I think I can either 1) get rid of the custom type and the 'type' part of the country_name tokens definition. Or 2) leave it as it is with the custom type.

bojanz’s picture

Less code is always a good idea.

lisastreeter’s picture

Removed the custom token type.

bojanz’s picture

Status: Needs review » Needs work
FileSize
13.07 KB
+    if (!$entity_type->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface')) {

isSubclassOf() is deprecated.
String references to classes/interfaces should be replaced by class references (ContentEntityInterface::class) in this case.

The test is not passing, the build is green here because it was skipped (probably due to the optional dependency.)

$this->installEntitySchema('address');

There is no "address" entity type.

    $this->installEntitySchema('node');
    $this->installEntitySchema('taxonomy_term');

This crashes without the "text" and "filter" modules listed in $modules.

$this->enableModules(['token']);

I get "2x: KernelTestBase::enableModules() should not be called from setUp(). Use the $modules property instead."

$entity = Node::create([

The test has no use statement for Node.

I fixed the above, but the test is still crashing, so setting to "needs work". Uploading updated patch.

lisastreeter’s picture

Fixed various errors in the Kernel test including an incorrect use statement, missing setUp items, and a token name typo.

lisastreeter’s picture

Kernel test was passing locally but failed here. Trying a changed base class.

lisastreeter’s picture

Kernel test doesn't seem happy with including any test base code from token module. Removed it in this patch.

lisastreeter’s picture

A little coding standards cleanup now that testbot is happy with test.

EDIT: actually...just looked more carefully: the test was skipped.

lisastreeter’s picture

Status: Needs review » Needs work
lisastreeter’s picture

Removed from the annotation: @requires module token

lisastreeter’s picture

Patch #24 has in its class annotation:
@requires module token

Patch #26 does not have that in its annotation.

Patch #24 does not run the CountryNameTokenTest kernel tests.
Patch #26 fails because the token module is unavailable (and says the test class needs to be annotated with '@requires module token')

So I'm not sure what I can do at this point.

lisastreeter’s picture

I don't think this is the intended usage for the test_dependencies property in the info.yml file, but perhaps it will encourage testbot to include the token dependency.

lisastreeter’s picture

I just learned that test_dependencies will work but only if it's committed first.

The alternative is to add token to require-dev in the module's composer.json file, which I've done here.

Documentation for this was just added here: Managing dependencies for a contributed project

lisastreeter’s picture

Status: Needs work » Needs review
lisastreeter’s picture

Changed base class to reduce code by reusing token module test code.

  • bojanz committed 45c2d9a on 8.x-1.x authored by lisastreeter
    Issue #2915147 by lisastreeter, bojanz: Add support for a country token
    
bojanz’s picture

Status: Needs review » Fixed

Thank you, Lisa.

I've removed the require-dev, now that test_dependencies should be recognized post-commit.

Status: Fixed » Closed (fixed)

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