alcohol/iso3166

Aliases

Closed this issue · 5 comments

If I may suggest, I would consider the use of Aliases for the most common countries.

A few examples:

  • United States vs United States Of America
  • Britain vs Great Britain

I ran into an issue where I was not getting a ISO 2 letter code for US orders. Upon investigation I found out the reason was because the ordering system we use writes it as "United States" and not "United States Of America" which is what the library expects. While I can understand not wanting to add bloat by allowing any/all country alias I do feel the most common ones would be a great way to add some graceful wiggle room. I know of very few systems that use the full name for the US.

I prefer to let the end-user implement their specific use-case modifications.

Quick (and oversimplified) example:

test.php

<?php

require_once 'vendor/autoload.php';

use League\ISO3166\ISO3166;
use League\ISO3166\ISO3166DataProvider;

class ISO3166WithAliases implements ISO3166DataProvider
{
    private ISO3166DataProvider $source;

    public function __construct(ISO3166DataProvider $iso3166)
    {
        $this->source = $iso3166;
    }

    public function name($name): array
    {
        $aliases = [
            'United States' => 'United States of America'
        ];

        return $this->source->name(array_key_exists($name, $aliases) ? $aliases[$name] : $name);
    }

    public function alpha2($alpha2): array
    {
        return $this->source->alpha2($alpha2);
    }

    public function alpha3($alpha3): array
    {
        return $this->source->alpha3($alpha3);
    }

    public function numeric($numeric): array
    {
        return $this->source->numeric($numeric);
    }
}

var_dump((new ISO3166WithAliases(new ISO3166))->name('United States'));

output

array(5) {
  ["name"]=>
  string(24) "United States of America"
  ["alpha2"]=>
  string(2) "US"
  ["alpha3"]=>
  string(3) "USA"
  ["numeric"]=>
  string(3) "840"
  ["currency"]=>
  array(1) {
    [0]=>
    string(3) "USD"
  }
}

I do feel the most common ones would be a great

Agree. Otherwise tons of ppl will do the same work independently.
Im for most common ones.

Alright, if you submit a PR I'm OK with merging it (along the lines of my proposed solution - so a new class that wraps the original).

Though I would like to point out that it is rather uncommon to use the "name" as a key. And adding aliases does not change the returned data, only the way you lookup said data.

Just some quick notes:

  1. We COULD add the alias feature into the same|main class ISO3166.
  2. We SHOULD implement an alias setter setAliases($aliases) (overwrite) and addAliases($aliases) accepting one string or array of alias.
    Everybody can set up the model with a config.
    2.1. We SHOULD add a 2nd parameter $aliases on __construct (default empty array).
    2.2. We SHOULD add a method getAliases().
  3. Aliases SHOULD be set on a property (array).
    3.1. Alias keys COULD be lowercase {lowercase(alias)} => {actual name} to prevent duplicates ("Austria" <> "austria").
  4. The method lookup() SHOULD get a parameter (something like) $allowAliases or $includeAliases.
    4.1. Every method that is using lookup() (name(),alpha2(), ...) SHOULD get this parameter too.
    4.2. For backwards compatibility (keep previous behavior) this parameter should be default false.
  5. The method lookup() SHOULD get a check AFTER the existing lookup-loop for an alias match.

Note: another way to implement aliases would be

  • change property $countries to have the (lowercase) name as key for quick search via array_key_exists or isset.
    (but ofc keep the name offset each array it self)
  • add offset aliases (self::KEY_ALIASES) to each country array (default empty)
  • aliases gets added to each country array
  • aliases array is value only (no keys need - we are in the related array)
  • setAlias() and addAlias() can directly point to $this->countries[$name]['aliases'] (if isset ofc).
  • lookup() method can be easy extended using the same check for aliases
    for each $country[self::KEY_ALIASES]) as alias ... and strcasecmp using the alias.

This way we could benefit of getting a complete set of data on f.e. all() ect.