1

I have a Drupal 7 site that uses the Countries module. I would like to show the United States first in the list and the rest of the countries then in alphabetical order (by default, the module displays all countries in alphabetical order). This is a common feature on many sites so I'm hoping there's an easy way to do this.

  • is it just one form you want to change or is your country field shown on multiple forms? Also, I'm curious why you use the country field at all since addressfield has a complete list of countries – uwe May 24 '12 at 15:38
  • In this case, multiple forms. I have the Countries module installed because I'm using it for a "Nationality/Home Country" field. (And I was originally using the Location module, not Addressfield.) – Patrick Kenny May 24 '12 at 15:48
4
+50

It's a shame Sumeet didn't continue his answer, as he got so close, but here is the alter hook:

function HOOK_countries_alter(&$countries) {
  $US = $countries['US'];
  unset($countries['US']);
  array_unshift($countries, $US);
} 

It copies US, removes it from the list, and attaches the copy back to the top.

You don't say in what context you use the module. I verified that it does what it should on a country-field.

| improve this answer | |
  • I confirmed that this works for a country field. However, I also have the Addressfield module installed, and this breaks the feature where selecting a country automatically displays a drop-down list of states/provinces. Is there another way to do this, or would it be fair to report this as a bug of Addressfield? – Patrick Kenny May 24 '12 at 14:29
  • 1
    I looked some more at the code, and I can find no indication that addressfield and countries have direct integration. Since what we're doing with Countries seems completely "legit" in every way, I would say Addressfield is at fault, so, yesm it would be fair to report as a bug. How Addressfield could even be affected by this though, I do not understand. – Letharion May 24 '12 at 14:56
  • @Letharion Dont 'shame' me please ;) I could not give the final shuffle down because I had no time to look up the array structure then. Glad its a complete solution now :) – Sumeet Pareek May 25 '12 at 12:25
  • Yeah, I just felt silly for mostly re-iterating what you already had said. :) – Letharion May 25 '12 at 13:36
3

With the first solution, the country key is missing, so you can't save this country field because the country key doesn't match. I suggest that (similar to the second solution) :

function hook_countries_alter(&$countries) {
  $country_key = 'FR';//eg. your country key
  $country_data = $countries[$country_key];
  unset($countries[$country_key]);
  $countries = array_merge(array($country_key=>$country_data),$countries);
}
| improve this answer | |
2

I took a quick look under the hood of the countries module and found that the right place to do this change would be to use the hook - hook_countries_alter() in a custom module.

function countries_countries_alter(&$countries) {
  $enabled_countries = &drupal_static(__FUNCTION__, array());
  if (empty($enabled_countries)) {
    $enabled_countries = countries_get_countries('name', array('enabled' => COUNTRIES_ENABLED));
  }
  $countries = array_intersect_key($enabled_countries, $countries);
  $countries = array_merge($countries, array_diff_key($enabled_countries, $countries));
  uasort($countries, 'countries_sort');
}

The uasort towards the end does the alphabetical sort as shown below (in the same module)

/**
 * A helper uasort callback function to sort an array of countries or names.
 */
function countries_sort($a, $b) {
  $a = countries_transliterate(is_object($a) ? $a->name : $a);
  $b = countries_transliterate(is_object($b) ? $b->name : $b);
  return strnatcasecmp($a, $b);
}

I would suggest adding and enabling the devel module > then add a dsm($countries) at the end of countries_countries_alter() to check out the structure of the array > then write a small custom module where you implement the hook_countries_alter() and bring USA on top while the rest are sorted alphabetically.

| improve this answer | |
  • Thanks for this; unfortunately, I am not much of a coder. dsm() returns an array that is structured like this: 2-letter country code (e.g., "US") / ISO name of country (e.g., "United States"). I'm happy to provide a bounty for working sample code that shows how to do this. – Patrick Kenny May 24 '12 at 13:24
  • I could not give you the final piece of code without knowing the structure of the array. Crap. I only saw this now and missed the bounty :( – Sumeet Pareek May 25 '12 at 12:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.