Skip to content
This repository
Browse code

ENHANCEMENT: Add back CountryDropdownField

We removed this because it depended on GeoIP, which was weird, and had its own dependancies.
But Zend_Locale is included in core, and can give us all the data we need for CountryDropdownField
  • Loading branch information...
commit 01062c70a1cd36f40a46a63b637b5bdc6f32a2a0 1 parent 77d7122
Hamish Friedlander authored

Showing 1 changed file with 71 additions and 0 deletions. Show diff stats Hide diff stats

  1. 71  forms/CountryDropdownField.php
71  forms/CountryDropdownField.php
... ...
@@ -0,0 +1,71 @@
  1
+<?php
  2
+
  3
+/**
  4
+ * A simple extension to dropdown field, pre-configured to list countries.
  5
+ * It will default to the country of the current visitor.
  6
+ *
  7
+ * @package forms
  8
+ * @subpackage fields-relational
  9
+ */
  10
+class CountryDropdownField extends DropdownField {
  11
+
  12
+	/**
  13
+	 * @var bool - Should we default the dropdown to the region determined from the user's locale?
  14
+	 */
  15
+	static $default_to_locale = true;
  16
+
  17
+	/**
  18
+	 * @var string - The region code to default to if default_to_locale is set to false, or we can't determine a region from a locale
  19
+	 */
  20
+	static $default_country = 'NZ';
  21
+
  22
+	/**
  23
+	 * Get the locale of the Member, or if we're not logged in or don't have a locale, use the default one
  24
+	 * @return string
  25
+	 */
  26
+	protected function locale() {
  27
+		if (($member = Member::currentUser()) && $member->Locale) return $member->Locale;
  28
+		return i18n::get_locale();
  29
+	}
  30
+
  31
+	function __construct($name, $title = null, $source = null, $value = "", $form=null) {
  32
+		if(!is_array($source)) {
  33
+			// Get a list of countries from Zend
  34
+			$source = Zend_Locale::getTranslationList('territory', $this->locale(), 2);
  35
+
  36
+			// We want them ordered by display name, not country code
  37
+
  38
+			// PHP 5.3 has an extension that sorts UTF-8 strings correctly
  39
+			if (class_exists('Collator') && ($collator = Collator::create($this->locale()))) {
  40
+				$collator->asort($source);
  41
+			}
  42
+			// Otherwise just put up with them being weirdly ordered for now
  43
+			else {
  44
+				asort($source);
  45
+			}
  46
+
  47
+			// We don't want "unknown country" as an option
  48
+			unset($source['ZZ']);
  49
+		}
  50
+
  51
+		parent::__construct($name, ($title===null) ? $name : $title, $source, $value, $form);
  52
+	}
  53
+
  54
+	function Field($properties = array()) {
  55
+		$source = $this->getSource();
  56
+
  57
+		if (!$this->value || !isset($source[$this->value])) {
  58
+			if ($this->config()->get('default_to_locale') && $this->locale()) {
  59
+				$locale = new Zend_Locale();
  60
+				$locale->setLocale($this->locale());
  61
+				$this->value = $locale->getRegion();
  62
+			}
  63
+		}
  64
+
  65
+		if (!$this->value || !isset($source[$this->value])) {
  66
+			$this->value = $this->config()->get('default_country');
  67
+		}
  68
+
  69
+		return parent::Field();
  70
+	}
  71
+}

6 notes on commit 01062c7

ARNHOE

Thanks for the addition, but the sort is not set well I think, since Åland Islands is the last country, probably due to special A.

Stig Lindqvist
Owner
stojg commented on 01062c7

'Å' happens to be third to last letter in the alphabet in Swedish and Finnish, the last in the Norwegian and Danish.

Sam Minnée
Owner

Internationalisation: it's hard.

ARNHOE

Thanks stojg, didnt realise that :)

Hamish Friedlander
Owner

If you have the 5.3 "intl" module installed, it'll sort according to the current locale. The module is part of core 5.3, but like a lot of other core modules, most distributions split it out into a separate package.

If you don't have it installed, it just naively sorts with asort, which as you noticed puts Åland Islands at the bottom. Getting this right ourselves is hard (for reasons such as the one @stojg mentioned), so I just don't attempt to.

I think this is a reasonable trade-off. We could potentially check specifically for the locale being en, and just replace "Åland Islands" with "Aland Islands" in that case, but that seems a bit inelegant.

Sam Minnée
Owner

It would also be wrong - according to our resident Scandinavian, Åland is supposed to appear near the bottom of the list.

As a low-priority enhancement I'd suggest recommending the intl module to people installing who don't currently have it. However, I'd prefer to move the installer to use something like https://github.com/silverstripe-labs/silverstripe-environmentcheck that is also executed as a part of dev/build, so that all of these tests are checked during development and deployment. It would make more of the installer stuff that core devs use every day.

I guess I could add an enhancement ticket, but I've been down that road before, and it just leads to a cluttered ticket list.

Please sign in to comment.
Something went wrong with that request. Please try again.