diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000000..5274d5cf1fb
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,15 @@
+CHANGELOG for 1.0.0-alpha3
+===================
+
+This changelog references the relevant changes (new features, changes and bugs) done in 1.0.0-alpha3 versions.
+
+* 1.0.0-alpha3 (2013-06-27)
+ * Placeholders
+ * Developer toolbar works with AJAX navigation requests
+ * Configuring hidden columns in a Grid
+ * Auto-complete form type
+ * Added Address Book
+ * Localized countries and regions
+ * Enhanced data change log with ability to save changes for collections
+ * Removed dependency on lib ICU
+
diff --git a/UPGRADE.md b/UPGRADE.md
new file mode 100644
index 00000000000..cdcd65fff46
--- /dev/null
+++ b/UPGRADE.md
@@ -0,0 +1,7 @@
+UPGRADE FROM 1.0.0-alpha2 to 1.0.0-alpha3
+=======================
+
+### General
+
+ * Upgrade to 1.0.0-alpha3 is not supported and full reinstall is required
+
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 2c3461e3867..b83fac5019f 100644
--- a/composer.json
+++ b/composer.json
@@ -22,8 +22,8 @@
"jms/serializer": "0.12.*@dev",
"jms/serializer-bundle": "0.12.*@dev",
"kriswallsmith/assetic": "1.1.*@dev",
- "knplabs/knp-menu": "dev-master",
- "knplabs/knp-menu-bundle": "dev-master",
+ "knplabs/knp-menu": "v2.0.0-alpha1",
+ "knplabs/knp-menu-bundle": "v2.0.0-alpha1",
"knplabs/knp-paginator-bundle": "dev-master",
"friendsofsymfony/rest-bundle": "0.11.*",
"friendsofsymfony/jsrouting-bundle": "1.1.*@dev",
@@ -39,10 +39,9 @@
"sonata-project/doctrine-orm-admin-bundle": "2.1.x-dev",
"liip/imagine-bundle": "dev-master",
"leafo/lessphp": "dev-master",
- "symfony/icu": "1.2.*@dev",
- "symfony/intl": "2.3.*@dev",
"willdurand/expose-translation-bundle": "0.2.*@dev",
- "apy/jsfv-bundle": "dev-master#a27847b4e0e52212277c4759826328b3cfaa15dc"
+ "apy/jsfv-bundle": "dev-master#a27847b4e0e52212277c4759826328b3cfaa15dc",
+ "genemu/form-bundle": "2.1.*"
},
"repositories": [
{
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 1b7745c7854..2f9ce8dca63 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -11,26 +11,10 @@
processIsolation = "false"
stopOnFailure = "false"
syntaxCheck = "false"
- bootstrap = "vendor/autoload.php">
-
+ bootstrap = "tests/bootstrap.php">
- src/Oro/Bundle/AddressBundle/Tests/Unit
- src/Oro/Bundle/ConfigBundle/Tests/Unit
- src/Oro/Bundle/DataAuditBundle/Tests/Unit
-
- src/Oro/Bundle/FilterBundle/Tests/Unit
-
- src/Oro/Bundle/GridBundle/Tests/Unit
- src/Oro/Bundle/MeasureBundle/Tests/Unit
- src/Oro/Bundle/NavigationBundle/Tests/Unit
- src/Oro/Bundle/SearchBundle/Tests/Unit
- src/Oro/Bundle/SegmentationTreeBundle/Tests/Unit
- src/Oro/Bundle/SoapBundle/Tests/Unit
- src/Oro/Bundle/TestFrameworkBundle/Tests/Unit
- src/Oro/Bundle/UIBundle/Tests/Unit
- src/Oro/Bundle/UserBundle/Tests/Unit
- src/Oro/Bundle/WindowsBundle/Tests/Unit
+ src/*/Bundle/*Bundle/Tests/Unit
diff --git a/src/Oro/Bundle/AddressBundle/Controller/Api/Rest/CountryRegionsController.php b/src/Oro/Bundle/AddressBundle/Controller/Api/Rest/CountryRegionsController.php
index b22436c880b..4568b8d1667 100644
--- a/src/Oro/Bundle/AddressBundle/Controller/Api/Rest/CountryRegionsController.php
+++ b/src/Oro/Bundle/AddressBundle/Controller/Api/Rest/CountryRegionsController.php
@@ -2,12 +2,16 @@
namespace Oro\Bundle\AddressBundle\Controller\Api\Rest;
+use Symfony\Component\HttpFoundation\Response;
+use Doctrine\ORM\Query;
use FOS\Rest\Util\Codes;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Controller\Annotations\NamePrefix;
use FOS\RestBundle\Controller\Annotations\RouteResource;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
-use Symfony\Component\HttpFoundation\Response;
+
+use Oro\Bundle\AddressBundle\Entity\Country;
+use Oro\Bundle\AddressBundle\Entity\Repository\RegionRepository;
/**
* @RouteResource("country/regions")
@@ -18,7 +22,7 @@ class CountryRegionsController extends FOSRestController
/**
* REST GET regions by country
*
- * @param string $id
+ * @param Country $country
*
* @ApiDoc(
* description="Get regions by country id",
@@ -26,13 +30,20 @@ class CountryRegionsController extends FOSRestController
* )
* @return Response
*/
- public function getAction($id)
+ public function getAction(Country $country = null)
{
- /** @var $item \Oro\Bundle\AddressBundle\Entity\Country */
- $item = $this->getDoctrine()->getRepository('OroAddressBundle:Country')->find($id);
+ if (!$country) {
+ return $this->handleView(
+ $this->view(null, Codes::HTTP_NOT_FOUND)
+ );
+ }
+
+ /** @var $regionRepository RegionRepository */
+ $regionRepository = $this->getDoctrine()->getRepository('OroAddressBundle:Region');
+ $regions = $regionRepository->getCountryRegions($country);
return $this->handleView(
- $this->view($item ? $item->getRegions() : null, $item ? Codes::HTTP_OK : Codes::HTTP_NOT_FOUND)
+ $this->view($regions, Codes::HTTP_OK)
);
}
}
diff --git a/src/Oro/Bundle/AddressBundle/DataFixtures/ORM/LoadCountryData.php b/src/Oro/Bundle/AddressBundle/DataFixtures/ORM/LoadCountryData.php
new file mode 100644
index 00000000000..0db0233b45a
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/DataFixtures/ORM/LoadCountryData.php
@@ -0,0 +1,231 @@
+translator = $this->container->get('translator');
+
+ $fileName = $this->getFileName();
+ $countries = $this->getDataFromFile($fileName);
+ $this->saveCountryData($manager, $countries);
+ }
+
+ public function setContainer(ContainerInterface $container = null)
+ {
+ $this->container = $container;
+ }
+
+ /**
+ * @return string
+ */
+ protected function getFileName()
+ {
+ return __DIR__ . '/../data/countries.yml';
+ }
+
+ /**
+ * @param string $fileName
+ * @return bool
+ */
+ protected function isFileAvailable($fileName)
+ {
+ return is_file($fileName) && is_readable($fileName);
+ }
+
+ /**
+ * @param string $fileName
+ * @return array
+ * @throws \LogicException
+ */
+ protected function getDataFromFile($fileName)
+ {
+ if (!$this->isFileAvailable($fileName)) {
+ throw new \LogicException('File ' . $fileName . 'is not available');
+ }
+
+ $fileName = realpath($fileName);
+
+ return Yaml::parse($fileName);
+ }
+
+ /**
+ * @return array
+ */
+ protected function getAvailableCountryLocales()
+ {
+ $translationDirectory = str_replace('/', DIRECTORY_SEPARATOR, $this->translationDirectory);
+ $translationDirectories = array();
+
+ foreach ($this->container->getParameter('kernel.bundles') as $bundle) {
+ $reflection = new \ReflectionClass($bundle);
+ $bundleTranslationDirectory = dirname($reflection->getFilename()) . $translationDirectory;
+ if (is_dir($bundleTranslationDirectory) && is_readable($bundleTranslationDirectory)) {
+ $translationDirectories[] = realpath($bundleTranslationDirectory);
+ }
+ }
+
+ $finder = new Finder();
+ $finder->in($translationDirectories)->name(self::COUNTRY_FILE_REGEXP);
+
+ $countryLocales = array();
+ /** @var $file \SplFileInfo */
+ foreach ($finder as $file) {
+ preg_match(self::COUNTRY_FILE_REGEXP, $file->getFilename(), $matches);
+ if ($matches) {
+ $countryLocales[] = $matches[1];
+ }
+ }
+
+ return $countryLocales;
+ }
+
+ /**
+ * @param string $locale
+ * @param array $countryData
+ * @return null|Country
+ */
+ protected function getCountry($locale, array $countryData)
+ {
+ if (empty($countryData['iso2Code']) || empty($countryData['iso3Code'])) {
+ return null;
+ }
+
+ /** @var $country Country */
+ $country = $this->countryRepository->findOneBy(array('iso2Code' => $countryData['iso2Code']));
+ if (!$country) {
+ $country = new Country($countryData['iso2Code']);
+ $country->setIso3Code($countryData['iso3Code']);
+ }
+
+ $countryName = $this->translator->trans(
+ $countryData['iso2Code'],
+ array(),
+ self::COUNTRY_DOMAIN,
+ $locale
+ );
+
+ $country->setLocale($locale)
+ ->setName($countryName);
+
+ return $country;
+ }
+
+ /**
+ * @param string $locale
+ * @param Country $country
+ * @param array $regionData
+ * @return null|Region
+ */
+ protected function getRegion($locale, Country $country, array $regionData)
+ {
+ if (empty($regionData['combinedCode']) || empty($regionData['code'])) {
+ return null;
+ }
+
+ /** @var $region Region */
+ $region = $this->regionRepository->findOneBy(array('combinedCode' => $regionData['combinedCode']));
+ if (!$region) {
+ $region = new Region($regionData['combinedCode']);
+ $region->setCode($regionData['code'])
+ ->setCountry($country);
+ }
+
+ $regionName = $this->translator->trans(
+ $regionData['combinedCode'],
+ array(),
+ self::COUNTRY_DOMAIN,
+ $locale
+ );
+
+ $region->setLocale($locale)
+ ->setName($regionName);
+
+ return $region;
+ }
+
+ /**
+ * Save countries and regions to DB
+ *
+ * @param ObjectManager $manager
+ * @param array $countries
+ */
+ protected function saveCountryData(ObjectManager $manager, array $countries)
+ {
+ $this->countryRepository = $manager->getRepository('OroAddressBundle:Country');
+ $this->regionRepository = $manager->getRepository('OroAddressBundle:Region');
+
+ $countryLocales = $this->getAvailableCountryLocales();
+
+ foreach ($countryLocales as $locale) {
+ foreach ($countries as $countryData) {
+ $country = $this->getCountry($locale, $countryData);
+ if (!$country) {
+ continue;
+ }
+
+ $manager->persist($country);
+
+ if (!empty($countryData['regions'])) {
+ foreach ($countryData['regions'] as $regionData) {
+ $region = $this->getRegion($locale, $country, $regionData);
+ if (!$region) {
+ continue;
+ }
+
+ $manager->persist($region);
+ }
+ }
+ }
+
+ $manager->flush();
+ $manager->clear();
+ }
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/DataFixtures/ORM/LoadCountryDictsData.php b/src/Oro/Bundle/AddressBundle/DataFixtures/ORM/LoadCountryDictsData.php
deleted file mode 100644
index 9749855e9be..00000000000
--- a/src/Oro/Bundle/AddressBundle/DataFixtures/ORM/LoadCountryDictsData.php
+++ /dev/null
@@ -1,58 +0,0 @@
-container = $container;
- }
-
- /**
- * Load address types
- *
- * @param \Doctrine\Common\Persistence\ObjectManager $manager
- */
- public function load(ObjectManager $manager)
- {
- /* sample for manual input
- $importManager = $this->container->get('oro_address.dict.import.manager');
- $data = array(
- new Country('Ukraine', 'UA', 'UKR'),
- new Country('United States of America', 'US', 'USA'),
- new Country('Russian Federation', 'RU', 'RUS'),
- );
- $importManager->sync($data);
- */
-
- /**
- * @var $importManager Manager
- */
- $importManager = $this->container->get('oro_address.dict.import.intl.manager');
- $importManager->sync();
- }
-
- /**
- * Get the order of this fixture
- *
- * @return integer
- */
- public function getOrder()
- {
- return 10;
- }
-}
diff --git a/src/Oro/Bundle/AddressBundle/DataFixtures/ORM/LoadRegionData.php b/src/Oro/Bundle/AddressBundle/DataFixtures/ORM/LoadRegionData.php
deleted file mode 100644
index 4cad9eaaeb7..00000000000
--- a/src/Oro/Bundle/AddressBundle/DataFixtures/ORM/LoadRegionData.php
+++ /dev/null
@@ -1,40 +0,0 @@
-getRepository('OroAddressBundle:Country')->find('US');
-
- $region = new Region();
- $region->setCode('AL')
- ->setCountry($country)
- ->setName('Alabama');
- $manager->persist($region);
- $manager->flush();
- }
-
- /**
- * Get the order of this fixture
- *
- * @return integer
- */
- public function getOrder()
- {
- return 20;
- }
-}
diff --git a/src/Oro/Bundle/AddressBundle/DataFixtures/countries.yml b/src/Oro/Bundle/AddressBundle/DataFixtures/countries.yml
deleted file mode 100644
index 0bd74902fbb..00000000000
--- a/src/Oro/Bundle/AddressBundle/DataFixtures/countries.yml
+++ /dev/null
@@ -1,5975 +0,0 @@
-
-- name: Afghanistan
- iso2: AF
- iso3: AFG
- phone: 93
- units:
- - "Badakhshan"
- - "Badghis"
- - "Baghlan"
- - "Balkh"
- - "Bamian"
- - "Farah"
- - "Faryab"
- - "Ghazni"
- - "Ghowr"
- - "Helmand"
- - "Herat"
- - "Jowzjan"
- - "Kabol"
- - "Kandahar"
- - "Kapisa"
- - "Konar"
- - "Kondoz"
- - "Laghman"
- - "Lowgar"
- - "Nangarhar"
- - "Nimruz"
- - "Oruzgan"
- - "Paktia"
- - "Paktika"
- - "Parvan"
- - "Samangan"
- - "Sar-e Pol"
- - "Takhar"
- - "Vardak"
- - "Zabol"
-
-- name: Aland Islands
- iso2: AX
- iso3: ALA
- phone:
- units:
- - "Aland Islands"
-
-- name: Albania
- iso2: AL
- iso3: ALB
- phone: 355
- units:
- - "Berat"
- - "Bulqize"
- - "Delvine"
- - "Devoll [Bilisht]"
- - "Diber [Peshkopi]"
- - "Durres"
- - "Elbasan"
- - "Fier"
- - "Gjirokaster"
- - "Gramsh"
- - "Has [Krume]"
- - "Kavaje"
- - "Kolonje [Erseke]"
- - "Korce"
- - "Kruje"
- - "Kucove"
- - "Kukes"
- - "Kurbin"
- - "Lezhe"
- - "Librazhd"
- - "Lushnje"
- - "Malesi e Madhe [Koplik]"
- - "Mallakaster [Ballsh]"
- - "Mat [Burrel]"
- - "Mirdite [Rreshen]"
- - "Peqin"
- - "Permet"
- - "Pogradec"
- - "Puke"
- - "Sarande"
- - "Shkoder"
- - "Skrapar [Corovode]"
- - "Tepelene"
- - "Tirane [Tirana]"
- - "Tirane [Tirana]"
- - "Tropoje [Bajram Curri]"
- - "Vlore"
-
-- name: Algeria
- iso2: DZ
- iso3: DZA
- phone: 213
- units:
- - "Adrar"
- - "Ain Defla"
- - "Ain Temouchent"
- - "Alger"
- - "Annaba"
- - "Batna"
- - "Bechar"
- - "Bejaia"
- - "Biskra"
- - "Blida"
- - "Bordj Bou Arreridj"
- - "Bouira"
- - "Boumerdes"
- - "Chlef"
- - "Constantine"
- - "Djelfa"
- - "El Bayadh"
- - "El Oued"
- - "El Tarf"
- - "Ghardaia"
- - "Guelma"
- - "Illizi"
- - "Jijel"
- - "Khenchela"
- - "Laghouat"
- - "M'Sila"
- - "Mascara"
- - "Medea"
- - "Mila"
- - "Mostaganem"
- - "Naama"
- - "Oran"
- - "Ouargla"
- - "Oum el Bouaghi"
- - "Relizane"
- - "Saida"
- - "Setif"
- - "Sidi Bel Abbes"
- - "Skikda"
- - "Souk Ahras"
- - "Tamanghasset"
- - "Tebessa"
- - "Tiaret"
- - "Tindouf"
- - "Tipaza"
- - "Tissemsilt"
- - "Tizi Ouzou"
- - "Tlemcen"
-
-- name: American Samoa
- iso2: AS
- iso3: ASM
- phone: 1 684
- units:
- - "Eastern"
- - "Manu'a"
- - "Rose Island"
- - "Swains Island"
- - "Western"
-
-- name: Andorra
- iso2: AD
- iso3: AND
- phone: 376
- units:
- - "Andorra"
-
-- name: Angola
- iso2: AO
- iso3: AGO
- phone: 244
- units:
- - "Andorra la Vella"
- - "Bengo"
- - "Benguela"
- - "Bie"
- - "Cabinda"
- - "Canillo"
- - "Cuando Cubango"
- - "Cuanza Norte"
- - "Cuanza Sul"
- - "Cunene"
- - "Encamp"
- - "Escaldes-Engordany"
- - "Huambo"
- - "Huila"
- - "La Massana"
- - "Luanda"
- - "Lunda Norte"
- - "Lunda Sul"
- - "Malanje"
- - "Moxico"
- - "Namibe"
- - "Ordino"
- - "Sant Julia de Loria"
- - "Uige"
- - "Zaire"
-
-- name: Anguilla
- iso2: AI
- iso3: AIA
- phone: 1 264
- units:
- - "Anguilla"
-
-- name: Antarctica
- iso2: AQ
- iso3: ATA
- phone: 672
- units:
- - "Antarctica"
-
-- name: Antigua and Barbuda
- iso2: AG
- iso3: ATG
- phone: 1 268
- units:
- - "Barbuda"
- - "Redonda"
- - "Saint George"
- - "Saint John"
- - "Saint Mary"
- - "Saint Paul"
- - "Saint Peter"
- - "Saint Philip"
-
-- name: Argentina
- iso2: AR
- iso3: ARG
- phone: 54
- units:
- - "Antartica e Islas del Atlantico Sur"
- - "Buenos Aires"
- - "Buenos Aires Capital Federal"
- - "Catamarca"
- - "Chaco"
- - "Chubut"
- - "Cordoba"
- - "Corrientes"
- - "Entre Rios"
- - "Formosa"
- - "Jujuy"
- - "La Pampa"
- - "La Rioja"
- - "Mendoza"
- - "Misiones"
- - "Neuquen"
- - "Rio Negro"
- - "Salta"
- - "San Juan"
- - "San Luis"
- - "Santa Cruz"
- - "Santa Fe"
- - "Santiago del Estero"
- - "Tierra del Fuego"
- - "Tucuman"
-
-- name: Armenia
- iso2: AM
- iso3: ARM
- phone: 374
- units:
- - "Aragatsotn"
- - "Ararat"
- - "Armavir"
- - "Geghark'unik'"
- - "Kotayk'"
- - "Lorri"
- - "Shirak"
- - "Syunik'"
- - "Tavush"
- - "Vayots' Dzor"
- - "Yerevan"
-
-- name: Aruba
- iso2: AW
- iso3: ABW
- phone: 297
- units:
- - "Aruba"
-
-- name: Australia
- iso2: AU
- iso3: AUS
- phone: 61
- units:
- - "Australian Capital Territory"
- - "New South Wales"
- - "Northern Territory"
- - "Queensland"
- - "South Australia"
- - "Tasmania"
- - "Victoria"
- - "Western Australia"
-
-- name: Austria
- iso2: AT
- iso3: AUT
- phone: 43
- units:
- - "Burgenland"
- - "Kaernten"
- - "Niederoesterreich"
- - "Oberoesterreich"
- - "Salzburg"
- - "Steiermark"
- - "Tirol"
- - "Vorarlberg"
- - "Wien"
-
-- name: Azerbaijan
- iso2: AZ
- iso3: AZE
- phone: 994
- units:
- - "Abseron Rayonu"
- - "Agcabadi Rayonu"
- - "Agdam Rayonu"
- - "Agdas Rayonu"
- - "Agstafa Rayonu"
- - "Agsu Rayonu"
- - "Ali Bayramli Sahari"
- - "Astara Rayonu"
- - "Baki Sahari"
- - "Balakan Rayonu"
- - "Barda Rayonu"
- - "Beylaqan Rayonu"
- - "Bilasuvar Rayonu"
- - "Cabrayil Rayonu"
- - "Calilabad Rayonu"
- - "Daskasan Rayonu"
- - "Davaci Rayonu"
- - "Fuzuli Rayonu"
- - "Gadabay Rayonu"
- - "Ganca Sahari"
- - "Goranboy Rayonu"
- - "Goycay Rayonu"
- - "Haciqabul Rayonu"
- - "Imisli Rayonu"
- - "Ismayilli Rayonu"
- - "Kalbacar Rayonu"
- - "Kurdamir Rayonu"
- - "Lacin Rayonu"
- - "Lankaran Rayonu"
- - "Lankaran Sahari"
- - "Lerik Rayonu"
- - "Masalli Rayonu"
- - "Mingacevir Sahari"
- - "Naftalan Sahari"
- - "Naxcivan Muxtar Respublikasi"
- - "Neftcala Rayonu"
- - "Oguz Rayonu"
- - "Qabala Rayonu"
- - "Qax Rayonu"
- - "Qazax Rayonu"
- - "Qobustan Rayonu"
- - "Quba Rayonu"
- - "Qubadli Rayonu"
- - "Qusar Rayonu"
- - "Saatli Rayonu"
- - "Sabirabad Rayonu"
- - "Saki Rayonu"
- - "Saki Sahari"
- - "Salyan Rayonu"
- - "Samaxi Rayonu"
- - "Samkir Rayonu"
- - "Samux Rayonu"
- - "Siyazan Rayonu"
- - "Sumqayit Sahari"
- - "Susa Rayonu"
- - "Susa Sahari"
- - "Tartar Rayonu"
- - "Tovuz Rayonu"
- - "Ucar Rayonu"
- - "Xacmaz Rayonu"
- - "Xankandi Sahari"
- - "Xanlar Rayonu"
- - "Xizi Rayonu"
- - "Xocali Rayonu"
- - "Xocavand Rayonu"
- - "Yardimli Rayonu"
- - "Yevlax Rayonu"
- - "Yevlax Sahari"
- - "Zangilan Rayonu"
- - "Zaqatala Rayonu"
- - "Zardab Rayonu"
-
-- name: Bahamas
- iso2: BS
- iso3: BHS
- phone: 1 242
- units:
- - "Acklins and Crooked Islands"
- - "Bimini"
- - "Cat Island"
- - "Exuma"
- - "Freeport"
- - "Fresh Creek"
- - "Governor's Harbour"
- - "Green Turtle Cay"
- - "Harbour Island"
- - "High Rock"
- - "Inagua"
- - "Kemps Bay"
- - "Long Island"
- - "Marsh Harbour"
- - "Mayaguana"
- - "New Providence"
- - "Nicholls Town and Berry Islands"
- - "Ragged Island"
- - "Rock Sound"
- - "San Salvador and Rum Cay"
- - "Sandy Point"
-
-- name: Bahrain
- iso2: BH
- iso3: BHR
- phone: 973
- units:
- - "Al Hadd"
- - "Al Manamah"
- - "Al Mintaqah al Gharbiyah"
- - "Al Mintaqah al Wusta"
- - "Al Mintaqah ash Shamaliyah"
- - "Al Muharraq"
- - "Ar Rifa' wa al Mintaqah al Janubiyah"
- - "Jidd Hafs"
- - "Juzur Hawar"
- - "Madinat 'Isa"
- - "Madinat Hamad"
- - "Sitrah"
-
-- name: Bangladesh
- iso2: BD
- iso3: BGD
- phone: 880
- units:
- - "Barguna"
- - "Barisal"
- - "Bhola"
- - "Jhalokati"
- - "Patuakhali"
- - "Pirojpur"
- - "Bandarban"
- - "Brahmanbaria"
- - "Chandpur"
- - "Chittagong"
- - "Comilla"
- - "Cox's Bazar"
- - "Feni"
- - "Khagrachari"
- - "Lakshmipur"
- - "Noakhali"
- - "Rangamati"
- - "Dhaka"
- - "Faridpur"
- - "Gazipur"
- - "Gopalganj"
- - "Jamalpur"
- - "Kishoreganj"
- - "Madaripur"
- - "Manikganj"
- - "Munshiganj"
- - "Mymensingh"
- - "Narayanganj"
- - "Narsingdi"
- - "Netrokona"
- - "Rajbari"
- - "Shariatpur"
- - "Sherpur"
- - "Tangail"
- - "Bagerhat"
- - "Chuadanga"
- - "Jessore"
- - "Jhenaidah"
- - "Khulna"
- - "Kushtia"
- - "Magura"
- - "Meherpur"
- - "Narail"
- - "Satkhira"
- - "Bogra"
- - "Dinajpur"
- - "Gaibandha"
- - "Jaipurhat"
- - "Kurigram"
- - "Lalmonirhat"
- - "Naogaon"
- - "Natore"
- - "Nawabganj"
- - "Nilphamari"
- - "Pabna"
- - "Panchagarh"
- - "Rajshahi"
- - "Rangpur"
- - "Sirajganj"
- - "Thakurgaon"
- - "Habiganj"
- - "Maulvi bazar"
- - "Sunamganj"
- - "Sylhet"
-
-- name: Barbados
- iso2: BB
- iso3: BRB
- phone: 1 246
- units:
- - "Bridgetown"
- - "Christ Church"
- - "Saint Andrew"
- - "Saint George"
- - "Saint James"
- - "Saint John"
- - "Saint Joseph"
- - "Saint Lucy"
- - "Saint Michael"
- - "Saint Peter"
- - "Saint Philip"
- - "Saint Thomas"
-
-- name: Belarus
- iso2: BY
- iso3: BLR
- phone: 375
- units:
- - "Brestskaya [Brest]"
- - "Homyel'skaya [Homyel']"
- - "Horad Minsk"
- - "Hrodzyenskaya [Hrodna]"
- - "Mahilyowskaya [Mahilyow]"
- - "Minskaya"
- - "Vitsyebskaya [Vitsyebsk]"
-
-- name: Belgium
- iso2: BE
- iso3: BEL
- phone: 32
- units:
- - "Antwerpen"
- - "Brabant Wallon"
- - "Brussels Capitol Region"
- - "Hainaut"
- - "Liege"
- - "Limburg"
- - "Luxembourg"
- - "Namur"
- - "Oost-Vlaanderen"
- - "Vlaams Brabant"
- - "West-Vlaanderen"
-
-- name: Belize
- iso2: BZ
- iso3: BLZ
- phone: 501
- units:
- - "Belize"
- - "Cayo"
- - "Corozal"
- - "Orange Walk"
- - "Stann Creek"
- - "Toledo"
-
-- name: Benin
- iso2: BJ
- iso3: BEN
- phone: 229
- units:
- - "Alibori"
- - "Atakora"
- - "Atlantique"
- - "Borgou"
- - "Collines"
- - "Couffo"
- - "Donga"
- - "Littoral"
- - "Mono"
- - "Oueme"
- - "Plateau"
- - "Zou"
-
-- name: Bermuda
- iso2: BM
- iso3: BMU
- phone: 1 441
- units:
- - "Devonshire"
- - "Hamilton"
- - "Hamilton"
- - "Paget"
- - "Pembroke"
- - "Saint George"
- - "Saint Georges"
- - "Sandys"
- - "Smiths"
- - "Southampton"
- - "Warwick"
-
-- name: Bhutan
- iso2: BT
- iso3: BTN
- phone: 975
- units:
- - "Bumthang"
- - "Chhukha"
- - "Chirang"
- - "Daga"
- - "Geylegphug"
- - "Ha"
- - "Lhuntshi"
- - "Mongar"
- - "Paro"
- - "Pemagatsel"
- - "Punakha"
- - "Samchi"
- - "Samdrup Jongkhar"
- - "Shemgang"
- - "Tashigang"
- - "Thimphu"
- - "Tongsa"
- - "Wangdi Phodrang"
-
-- name: Bolivia Plurinational State of
- iso2: BO
- iso3: BOL
- phone: 591
- units:
- - "Beni"
- - "Chuquisaca"
- - "Cochabamba"
- - "La Paz"
- - "Oruro"
- - "Pando"
- - "Potosi"
- - "Santa Cruz"
- - "Tarija"
-
-- name: Bonaire Sint Eustatius and Saba
- iso2: BQ
- iso3: BES
- phone:
- units:
- - "Bonaire"
-
-- name: Bosnia and Herzegovina
- iso2: BA
- iso3: BIH
- phone: 387
- units:
- - "Federation of Bosnia and Herzegovina"
- - "Republika Srpska"
-
-- name: Botswana
- iso2: BW
- iso3: BWA
- phone: 267
- units:
- - "Central"
- - "Chobe"
- - "Francistown"
- - "Gaborone"
- - "Ghanzi"
- - "Kgalagadi"
- - "Kgatleng"
- - "Kweneng"
- - "Lobatse"
- - "Ngamiland"
- - "North-East"
- - "Selebi-Pikwe"
- - "South-East"
- - "Southern"
-
-- name: Bouvet Island
- iso2: BV
- iso3: BVT
- phone:
- units:
- - "Bouvet Island"
-
-- name: Brazil
- iso2: BR
- iso3: BRA
- phone: 55
- units:
- - "Acre"
- - "Alagoas"
- - "Amapa"
- - "Amazonas"
- - "Bahia"
- - "Ceara"
- - "Distrito Federal"
- - "Espirito Santo"
- - "Goias"
- - "Maranhao"
- - "Mato Grosso"
- - "Mato Grosso do Sul"
- - "Minas Gerais"
- - "Para"
- - "Paraiba"
- - "Parana"
- - "Pernambuco"
- - "Piaui"
- - "Rio de Janeiro"
- - "Rio Grande do Norte"
- - "Rio Grande do Sul"
- - "Rondonia"
- - "Roraima"
- - "Santa Catarina"
- - "Sao Paulo"
- - "Sergipe"
- - "Tocantins"
-
-- name: British Indian Ocean Territory
- iso2: IO
- iso3: IOT
- phone:
- units:
- - "British Indian Ocean Territory"
-
-- name: Brunei Darussalam
- iso2: BN
- iso3: BRN
- phone: 673
- units:
- - "Belait"
- - "Brunei and Muara"
- - "Temburong"
- - "Tutong"
-
-- name: Bulgaria
- iso2: BG
- iso3: BGR
- phone: 359
- units:
- - "Blagoevgrad"
- - "Burgas"
- - "Dobrich"
- - "Gabrovo"
- - "Khaskovo"
- - "Kurdzhali"
- - "Kyustendil"
- - "Lovech"
- - "Montana"
- - "Pazardzhik"
- - "Pernik"
- - "Pleven"
- - "Plovdiv"
- - "Razgrad"
- - "Ruse"
- - "Shumen"
- - "Silistra"
- - "Sliven"
- - "Smolyan"
- - "Sofiya"
- - "Sofiya-Grad"
- - "Stara Zagora"
- - "Turgovishte"
- - "Varna"
- - "Veliko Turnovo"
- - "Vidin"
- - "Vratsa"
- - "Yambol"
-
-- name: Burkina Faso
- iso2: BF
- iso3: BFA
- phone: 226
- units:
- - "Bale"
- - "Bam"
- - "Banwa"
- - "Bazega"
- - "Bougouriba"
- - "Boulgou"
- - "Boulkiemde"
- - "Comoe"
- - "Ganzourgou"
- - "Gnagna"
- - "Gourma"
- - "Houet"
- - "Ioba"
- - "Kadiogo"
- - "Kenedougou"
- - "Komandjari"
- - "Kompienga"
- - "Kossi"
- - "Koupelogo"
- - "Kouritenga"
- - "Kourweogo"
- - "Leraba"
- - "Loroum"
- - "Mouhoun"
- - "Nahouri"
- - "Namentenga"
- - "Naumbiel"
- - "Nayala"
- - "Oubritenga"
- - "Oudalan"
- - "Passore"
- - "Poni"
- - "Samentenga"
- - "Sanguie"
- - "Seno"
- - "Sissili"
- - "Soum"
- - "Sourou"
- - "Tapoa"
- - "Tuy"
- - "Yagha"
- - "Yatenga"
- - "Ziro"
- - "Zondomo"
- - "Zoundweogo"
-
-- name: Burundi
- iso2: BI
- iso3: BDI
- phone: 257
- units:
- - "Bubanza"
- - "Bujumbura"
- - "Bururi"
- - "Cankuzo"
- - "Cibitoke"
- - "Gitega"
- - "Karuzi"
- - "Kayanza"
- - "Kirundo"
- - "Makamba"
- - "Muramvya"
- - "Muyinga"
- - "Mwaro"
- - "Ngozi"
- - "Rutana"
- - "Ruyigi"
-
-- name: Cambodia
- iso2: KH
- iso3: KHM
- phone: 855
- units:
- - "Banteay Mean Cheay"
- - "Batdambang"
- - "Kampong Cham"
- - "Kampong Chhnang"
- - "Kampong Spoe"
- - "Kampong Thum"
- - "Kampot"
- - "Kandal"
- - "Kaoh Kong"
- - "Keb"
- - "Kracheh"
- - "Mondol Kiri"
- - "Otdar Mean Cheay"
- - "Pailin"
- - "Phnum Penh"
- - "Pouthisat"
- - "Preah Seihanu [Sihanoukville]"
- - "Preah Vihear"
- - "Prey Veng"
- - "Rotanah Kiri"
- - "Siem Reab"
- - "Stoeng Treng"
- - "Svay Rieng"
- - "Takev"
-
-- name: Cameroon
- iso2: CM
- iso3: CMR
- phone: 237
- units:
- - "Adamaoua"
- - "Centre"
- - "Est"
- - "Extreme-Nord"
- - "Littoral"
- - "Nord"
- - "Nord-Ouest"
- - "Ouest"
- - "Sud"
- - "Sud-Ouest"
-
-- name: Canada
- iso2: CA
- iso3: CAN
- phone: 1
- units:
- - "Alberta"
- - "British Columbia"
- - "Manitoba"
- - "New Brunswick"
- - "Newfoundland"
- - "Northwest Territories"
- - "Nova Scotia"
- - "Nunavut"
- - "Ontario"
- - "Prince Edward Island"
- - "Quebec"
- - "Saskatchewan"
- - "Yukon"
-
-- name: Cape Verde
- iso2: CV
- iso3: CPV
- phone: 238
- units:
- - "Boa Vista"
- - "Brava"
- - "Maio"
- - "Mosteiros"
- - "Paul"
- - "Porto Novo"
- - "Praia"
- - "Ribeira Grande"
- - "Sal"
- - "Santa Catarina"
- - "Santa Cruz"
- - "Sao Domingos"
- - "Sao Filipe"
- - "Sao Nicolau"
- - "Sao Vicente"
- - "Tarrafal"
-
-- name: Cayman Islands
- iso2: KY
- iso3: CYM
- phone: 1 345
- units:
- - "Creek"
- - "Eastern"
- - "Midland"
- - "South Town"
- - "Spot Bay"
- - "Stake Bay"
- - "West End"
- - "Western"
-
-- name: Central African Republic
- iso2: CF
- iso3: CAF
- phone: 236
- units:
- - "Bamingui-Bangoran"
- - "Bangui"
- - "Basse-Kotto"
- - "Gribingui"
- - "Haut-Mbomou"
- - "Haute-Kotto"
- - "Haute-Sangha"
- - "Kemo-Gribingui"
- - "Lobaye"
- - "Mbomou"
- - "Nana-Mambere"
- - "Ombella-Mpoko"
- - "Ouaka"
- - "Ouham"
- - "Ouham-Pende"
- - "Sangha"
- - "Vakaga"
-
-- name: Chad
- iso2: TD
- iso3: TCD
- phone: 235
- units:
- - "Batha"
- - "Biltine"
- - "Borkou-Ennedi-Tibesti"
- - "Chari-Baguirmi"
- - "Guera"
- - "Kanem"
- - "Lac"
- - "Logone Occidental"
- - "Logone Oriental"
- - "Mayo-Kebbi"
- - "Moyen-Chari"
- - "Ouaddai"
- - "Salamat"
- - "Tandjile"
-
-- name: Chile
- iso2: CL
- iso3: CHL
- phone: 56
- units:
- - "Aisen del General Carlos Ibanez del Campo"
- - "Antofagasta"
- - "Araucania"
- - "Atacama"
- - "Bio-Bio"
- - "Coquimbo"
- - "Libertador General Bernardo O'Higgins"
- - "Los Lagos"
- - "Magallanes y de la Antartica Chilena"
- - "Maule"
- - "Region Metropolitana [Santiago]"
- - "Tarapaca"
- - "Valparaiso"
-
-- name: China
- iso2: CN
- iso3: CHN
- phone: 86
- units:
- - "Anhui"
- - "Beijing"
- - "Chongqing"
- - "Fujian"
- - "Gansu"
- - "Guangdong"
- - "Guangxi"
- - "Guizhou"
- - "Hainan"
- - "Hebei"
- - "Heilongjiang"
- - "Henan"
- - "Hubei"
- - "Hunan"
- - "Jiangsu"
- - "Jiangxi"
- - "Jilin"
- - "Liaoning"
- - "Nei Mongol"
- - "Ningxia"
- - "Qinghai"
- - "Shaanxi"
- - "Shandong"
- - "Shanghai"
- - "Shanxi"
- - "Sichuan"
- - "Tianjin"
- - "Xinjiang"
- - "Xizang [Tibet]"
- - "Yunnan"
- - "Zhejiang"
-
-- name: Christmas Island
- iso2: CX
- iso3: CXR
- phone: 61
- units:
- - "Christmas Island"
-
-- name: Cocos [Keeling, ] Islands
- iso2: CC
- iso3: CCK
- phone: 61
- units:
- - "Direction Island"
- - "Home Island"
- - "Horsburgh Island"
- - "North Keeling Island"
- - "South Island"
- - "West Island"
-
-- name: Colombia
- iso2: CO
- iso3: COL
- phone: 57
- units:
- - "Amazonas"
- - "Antioquia"
- - "Arauca"
- - "Atlantico"
- - "Bolivar"
- - "Boyaca"
- - "Caldas"
- - "Caqueta"
- - "Casanare"
- - "Cauca"
- - "Cesar"
- - "Choco"
- - "Cordoba"
- - "Cundinamarca"
- - "Distrito Capital de Santa Fe de Bogota"
- - "Guainia"
- - "Guaviare"
- - "Huila"
- - "La Guajira"
- - "Magdalena"
- - "Meta"
- - "Narino"
- - "Norte de Santander"
- - "Putumayo"
- - "Quindio"
- - "Risaralda"
- - "San Andres y Providencia"
- - "Santander"
- - "Sucre"
- - "Tolima"
- - "Valle del Cauca"
- - "Vaupes"
- - "Vichada"
-
-- name: Comoros
- iso2: KM
- iso3: COM
- phone: 269
- units:
- - "Anjouan [Nzwani]"
- - "Domoni"
- - "Fomboni"
- - "Grande Comore [Njazidja]"
- - "Moheli [Mwali]"
- - "Moroni"
- - "Moutsamoudou"
-
-- name: Congo
- iso2: CG
- iso3: COG
- phone: 242
- units:
- - "Bouenza"
- - "Brazzaville"
- - "Cuvette"
- - "Kouilou"
- - "Lekoumou"
- - "Likouala"
- - "Niari"
- - "Plateaux"
- - "Pool"
- - "Sangha"
-
-- name: Congo the Democratic Republic of the
- iso2: CD
- iso3: COD
- phone: 243
- units:
- - "Bandundu"
- - "Bas-Congo"
- - "Equateur"
- - "Kasai-Occidental"
- - "Kasai-Oriental"
- - "Katanga"
- - "Kinshasa"
- - "Maniema"
- - "Nord-Kivu"
- - "Orientale"
- - "Sud-Kivu"
-
-- name: Cook Islands
- iso2: CK
- iso3: COK
- phone: 682
- units:
- - "Aitutaki"
- - "Atiu"
- - "Avarua"
- - "Mangaia"
- - "Manihiki"
- - "Manuae"
- - "Mauke"
- - "Mitiaro"
- - "Nassau Island"
- - "Palmerston"
- - "Penrhyn"
- - "Pukapuka"
- - "Rakahanga"
- - "Rarotonga"
- - "Suwarrow"
- - "Takutea"
-
-- name: Costa Rica
- iso2: CR
- iso3: CRI
- phone: 506
- units:
- - "Alajuela"
- - "Cartago"
- - "Guanacaste"
- - "Heredia"
- - "Limon"
- - "Puntarenas"
- - "San Jose"
-
-- name: Cote d'Ivoire
- iso2: CI
- iso3: CIV
- phone: 225
- units:
- - "Abengourou"
- - "Abidjan"
- - "Aboisso"
- - "Adiake'"
- - "Adzope"
- - "Agboville"
- - "Agnibilekrou"
- - "Ale'pe'"
- - "Bangolo"
- - "Beoumi"
- - "Biankouma"
- - "Bocanda"
- - "Bondoukou"
- - "Bongouanou"
- - "Bouafle"
- - "Bouake"
- - "Bouna"
- - "Boundiali"
- - "Dabakala"
- - "Dabon"
- - "Daloa"
- - "Danane"
- - "Daoukro"
- - "Dimbokro"
- - "Divo"
- - "Duekoue"
- - "Ferkessedougou"
- - "Gagnoa"
- - "Grand Bassam"
- - "Grand-Lahou"
- - "Guiglo"
- - "Issia"
- - "Jacqueville"
- - "Katiola"
- - "Korhogo"
- - "Lakota"
- - "Man"
- - "Mankono"
- - "Mbahiakro"
- - "Odienne"
- - "Oume"
- - "Sakassou"
- - "San-Pedro"
- - "Sassandra"
- - "Seguela"
- - "Sinfra"
- - "Soubre"
- - "Tabou"
- - "Tanda"
- - "Tiassale"
- - "Tiebissou"
- - "Tingrela"
- - "Touba"
- - "Toulepleu"
- - "Toumodi"
- - "Vavoua"
- - "Yamoussoukro"
- - "Zuenoula"
-
-- name: Croatia
- iso2: HR
- iso3: HRV
- phone: 385
- units:
- - "Bjelovarsko-Bilogorska Zupanija"
- - "Brodsko-Posavska Zupanija"
- - "Dubrovacko-Neretvanska Zupanija"
- - "Istarska Zupanija"
- - "Karlovacka Zupanija"
- - "Koprivnicko-Krizevacka Zupanija"
- - "Krapinsko-Zagorska Zupanija"
- - "Licko-Senjska Zupanija"
- - "Medimurska Zupanija"
- - "Osjecko-Baranjska Zupanija"
- - "Pozesko-Slavonska Zupanija"
- - "Primorsko-Goranska Zupanija"
- - "Sibensko-Kninska Zupanija"
- - "Sisacko-Moslavacka Zupanija"
- - "Splitsko-Dalmatinska Zupanija"
- - "Varazdinska Zupanija"
- - "Viroviticko-Podravska Zupanija"
- - "Vukovarsko-Srijemska Zupanija"
- - "Zadarska Zupanija"
- - "Zagreb"
- - "Zagrebacka Zupanija"
-
-- name: Cuba
- iso2: CU
- iso3: CUB
- phone: 53
- units:
- - "Camaguey"
- - "Ciego de Avila"
- - "Cienfuegos"
- - "Ciudad de La Habana"
- - "Granma"
- - "Guantanamo"
- - "Holguin"
- - "Isla de la Juventud"
- - "La Habana"
- - "Las Tunas"
- - "Matanzas"
- - "Pinar del Rio"
- - "Sancti Spiritus"
- - "Santiago de Cuba"
- - "Villa Clara"
-
-- name: Curacao
- iso2: CW
- iso3: CUW
- phone:
- units:
- - "Curacao"
-
-- name: Cyprus
- iso2: CY
- iso3: CYP
- phone: 357
- units:
- - "Famagusta"
- - "Kyrenia"
- - "Larnaca"
- - "Limassol"
- - "Nicosia"
- - "Paphos"
-
-- name: Czech Republic
- iso2: CZ
- iso3: CZE
- phone: 420
- units:
- - "Brnensky"
- - "Budejovicky"
- - "Jihlavsky"
- - "Karlovarsky"
- - "Kralovehradecky"
- - "Liberecky"
- - "Olomoucky"
- - "Ostravsky"
- - "Pardubicky"
- - "Plzensky"
- - "Praha"
- - "Stredocesky"
- - "Ustecky"
- - "Zlinsky"
-
-- name: Denmark
- iso2: DK
- iso3: DNK
- phone: 45
- units:
- - "Arhus"
- - "Bornholm"
- - "Fredericksberg"
- - "Frederiksborg"
- - "Fyn"
- - "Kobenhavn"
- - "Kobenhavns"
- - "Nordjylland"
- - "Ribe"
- - "Ringkobing"
- - "Roskilde"
- - "Sonderjylland"
- - "Storstrom"
- - "Vejle"
- - "Vestsjalland"
- - "Viborg"
-
-- name: Djibouti
- iso2: DJ
- iso3: DJI
- phone: 253
- units:
- - "'Ali Sabih"
- - "Dikhil"
- - "Djibouti"
- - "Obock"
- - "Tadjoura"
-
-- name: Dominica
- iso2: DM
- iso3: DMA
- phone: 1 767
- units:
- - "Saint Andrew"
- - "Saint David"
- - "Saint George"
- - "Saint John"
- - "Saint Joseph"
- - "Saint Luke"
- - "Saint Mark"
- - "Saint Patrick"
- - "Saint Paul"
- - "Saint Peter"
-
-- name: Dominican Republic
- iso2: DO
- iso3: DOM
- phone: 1 809
- units:
- - "Azua"
- - "Baoruco"
- - "Barahona"
- - "Dajabon"
- - "Distrito Nacional"
- - "Duarte"
- - "El Seibo"
- - "Elias Pina"
- - "Espaillat"
- - "Hato Mayor"
- - "Independencia"
- - "La Altagracia"
- - "La Romana"
- - "La Vega"
- - "Maria Trinidad Sanchez"
- - "Monsenor Nouel"
- - "Monte Cristi"
- - "Monte Plata"
- - "Pedernales"
- - "Peravia"
- - "Puerto Plata"
- - "Salcedo"
- - "Samana"
- - "San Cristobal"
- - "San Juan"
- - "San Pedro de Macoris"
- - "Sanchez Ramirez"
- - "Santiago"
- - "Santiago Rodriguez"
- - "Valverde"
-
-- name: Ecuador
- iso2: EC
- iso3: ECU
- phone: 593
- units:
- - "Azuay"
- - "Bolivar"
- - "Canar"
- - "Carchi"
- - "Chimborazo"
- - "Cotopaxi"
- - "El Oro"
- - "Esmeraldas"
- - "Galapagos"
- - "Guayas"
- - "Imbabura"
- - "Loja"
- - "Los Rios"
- - "Manabi"
- - "Morona-Santiago"
- - "Napo"
- - "Orellana"
- - "Pastaza"
- - "Pichincha"
- - "Sucumbios"
- - "Tungurahua"
- - "Zamora-Chinchipe"
-
-- name: Egypt
- iso2: EG
- iso3: EGY
- phone: 20
- units:
- - "Ad Daqahliyah"
- - "Al Bahr al Ahmar"
- - "Al Buhayrah"
- - "Al Fayyum"
- - "Al Gharbiyah"
- - "Al Iskandariyah"
- - "Al Isma'iliyah"
- - "Al Jizah"
- - "Al Minufiyah"
- - "Al Minya"
- - "Al Qahirah"
- - "Al Qalyubiyah"
- - "Al Wadi al Jadid"
- - "As Suways"
- - "Ash Sharqiyah"
- - "Aswan"
- - "Asyut"
- - "Bani Suwayf"
- - "Bur Sa'id"
- - "Dumyat"
- - "Janub Sina'"
- - "Kafr ash Shaykh"
- - "Matruh"
- - "Qina"
- - "Shamal Sina'"
- - "Suhaj"
-
-- name: El Salvador
- iso2: SV
- iso3: SLV
- phone: 503
- units:
- - "Ahuachapan"
- - "Cabanas"
- - "Chalatenango"
- - "Cuscatlan"
- - "La Libertad"
- - "La Paz"
- - "La Union"
- - "Morazan"
- - "San Miguel"
- - "San Salvador"
- - "San Vicente"
- - "Santa Ana"
- - "Sonsonate"
- - "Usulutan"
-
-- name: Equatorial Guinea
- iso2: GQ
- iso3: GNQ
- phone: 240
- units:
- - "Annobon"
- - "Bioko Norte"
- - "Bioko Sur"
- - "Centro Sur"
- - "Kie-Ntem"
- - "Litoral"
- - "Wele-Nzas"
-
-- name: Eritrea
- iso2: ER
- iso3: ERI
- phone: 291
- units:
- - "Akale Guzay"
- - "Barka"
- - "Denkel"
- - "Hamasen"
- - "Sahil"
- - "Semhar"
- - "Senhit"
- - "Seraye"
-
-- name: Estonia
- iso2: EE
- iso3: EST
- phone: 372
- units:
- - "Harjumaa [Tallinn]"
- - "Hiiumaa [Kardla]"
- - "Ida-Virumaa [Johvi]"
- - "Jarvamaa [Paide]"
- - "Jogevamaa [Jogeva]"
- - "Laane-Virumaa [Rakvere]"
- - "Laanemaa [Haapsalu]"
- - "Parnumaa [Parnu]"
- - "Polvamaa [Polva]"
- - "Raplamaa [Rapla]"
- - "Saaremaa [Kuessaare]"
- - "Tartumaa [Tartu]"
- - "Valgamaa [Valga]"
- - "Viljandimaa [Viljandi]"
- - "Vorumaa [Voru]"
-
-- name: Ethiopia
- iso2: ET
- iso3: ETH
- phone: 251
- units:
- - "Adis Abeba [Addis Ababa]"
- - "Afar"
- - "Amara"
- - "Dire Dawa"
- - "Gambela Hizboch"
- - "Hareri Hizb"
- - "Oromiya"
- - "Sumale"
- - "Tigray"
- - "YeDebub Biheroch Bihereseboch na Hizboch"
-
-- name: Falkland Islands [Malvinas, ]
- iso2: FK
- iso3: FLK
- phone: 500
- units:
- - "Falkland Islands [Islas Malvinas]"
-
-- name: Faroe Islands
- iso2: FO
- iso3: FRO
- phone: 298
- units:
- - "Bordoy"
- - "Eysturoy"
- - "Mykines"
- - "Sandoy"
- - "Skuvoy"
- - "Streymoy"
- - "Suduroy"
- - "Tvoroyri"
- - "Vagar"
-
-- name: Fiji
- iso2: FJ
- iso3: FJI
- phone: 679
- units:
- - "Central"
- - "Eastern"
- - "Northern"
- - "Rotuma"
- - "Western"
-
-- name: Finland
- iso2: FI
- iso3: FIN
- phone: 358
- units:
- - "Aland"
- - "Etela-Suomen Laani"
- - "Ita-Suomen Laani"
- - "Lansi-Suomen Laani"
- - "Lappi"
- - "Oulun Laani"
-
-- name: France
- iso2: FR
- iso3: FRA
- phone: 33
- units:
- - "Alsace"
- - "Aquitaine"
- - "Auvergne"
- - "Basse-Normandie"
- - "Bourgogne"
- - "Bretagne"
- - "Centre"
- - "Champagne-Ardenne"
- - "Corse"
- - "Franche-Comte"
- - "Haute-Normandie"
- - "Ile-de-France"
- - "Languedoc-Roussillon"
- - "Limousin"
- - "Lorraine"
- - "Midi-Pyrenees"
- - "Nord-Pas-de-Calais"
- - "Pays de la Loire"
- - "Picardie"
- - "Poitou-Charentes"
- - "Provence-Alpes-Cote d'Azur"
- - "Rhone-Alpes"
-
-- name: French Guiana
- iso2: GF
- iso3: GUF
- phone:
- units:
- - "French Guiana"
-
-- name: French Polynesia
- iso2: PF
- iso3: PYF
- phone: 689
- units:
- - "Archipel des Marquises"
- - "Archipel des Tuamotu"
- - "Archipel des Tubuai"
- - "Iles du Vent"
- - "Iles Sous-le-Vent"
-
-- name: French Southern Territories
- iso2: TF
- iso3: ATF
- phone:
- units:
- - "Adelie Land"
- - "Ile Crozet"
- - "Iles Kerguelen"
- - "Iles Saint-Paul et Amsterdam"
-
-- name: Gabon
- iso2: GA
- iso3: GAB
- phone: 241
- units:
- - "Estuaire"
- - "Haut-Ogooue"
- - "Moyen-Ogooue"
- - "Ngounie"
- - "Nyanga"
- - "Ogooue-Ivindo"
- - "Ogooue-Lolo"
- - "Ogooue-Maritime"
- - "Woleu-Ntem"
-
-- name: Gambia
- iso2: GM
- iso3: GMB
- phone: 220
- units:
- - "Banjul"
- - "Central River"
- - "Lower River"
- - "North Bank"
- - "Upper River"
- - "Western"
-
-- name: Georgia
- iso2: GE
- iso3: GEO
- phone: 995
- units:
- - "Abashis"
- - "Abkhazia or Ap'khazet'is Avtonomiuri Respublika [Sokhumi]"
- - "Adigenis"
- - "Ajaria or Acharis Avtonomiuri Respublika [Bat'umi]"
- - "Akhalgoris"
- - "Akhalk'alak'is"
- - "Akhalts'ikhis"
- - "Akhmetis"
- - "Ambrolauris"
- - "Aspindzis"
- - "Baghdat'is"
- - "Bolnisis"
- - "Borjomis"
- - "Ch'khorotsqus"
- - "Ch'okhatauris"
- - "Chiat'ura"
- - "Dedop'listsqaros"
- - "Dmanisis"
- - "Dushet'is"
- - "Gardabanis"
- - "Gori"
- - "Goris"
- - "Gurjaanis"
- - "Javis"
- - "K'arelis"
- - "K'ut'aisi"
- - "Kaspis"
- - "Kharagaulis"
- - "Khashuris"
- - "Khobis"
- - "Khonis"
- - "Lagodekhis"
- - "Lanch'khut'is"
- - "Lentekhis"
- - "Marneulis"
- - "Martvilis"
- - "Mestiis"
- - "Mts'khet'is"
- - "Ninotsmindis"
- - "Onis"
- - "Ozurget'is"
- - "P'ot'i"
- - "Qazbegis"
- - "Qvarlis"
- - "Rust'avi"
- - "Sach'kheris"
- - "Sagarejos"
- - "Samtrediis"
- - "Senakis"
- - "Sighnaghis"
- - "T'bilisi"
- - "T'elavis"
- - "T'erjolis"
- - "T'et'ritsqaros"
- - "T'ianet'is"
- - "Tqibuli"
- - "Ts'ageris"
- - "Tsalenjikhis"
- - "Tsalkis"
- - "Tsqaltubo"
- - "Vanis"
- - "Zestap'onis"
- - "Zugdidi"
- - "Zugdidis"
-
-- name: Germany
- iso2: DE
- iso3: DEU
- phone: 49
- units:
- - "Brandenburg"
- - "Berlin"
- - "Baden-Württemberg"
- - "Bayern [Bavaria]"
- - "Bremen"
- - "Hessen"
- - "Hamburg"
- - "Mecklenburg-Vorpommern"
- - "Niedersachsen [Lower Saxony]"
- - "Nordrhein-Westfalen"
- - "Rheinland-Pfalz [Palatinate]"
- - "Schleswig-Holstein"
- - "Saarland"
- - "Sachsen [Saxony]"
- - "Sachsen-Anhalt [Saxony-Anhalt]"
- - "Thüringen [Thuringia]"
-
-- name: Ghana
- iso2: GH
- iso3: GHA
- phone: 233
- units:
- - "Ashanti"
- - "Brong-Ahafo"
- - "Central"
- - "Eastern"
- - "Greater Accra"
- - "Northern"
- - "Upper East"
- - "Upper West"
- - "Volta"
- - "Western"
-
-- name: Gibraltar
- iso2: GI
- iso3: GIB
- phone: 350
- units:
- - "Gibraltar"
-
-- name: Greece
- iso2: GR
- iso3: GRC
- phone: 30
- units:
- - "Achaea"
- - "Aetolia-Acarnania"
- - "Arcadia"
- - "Argolis"
- - "Arta"
- - "Athens"
- - "Boeotia"
- - "Chalcidice"
- - "Chania"
- - "Chios"
- - "Corfu"
- - "Corinthia"
- - "Cyclades"
- - "Dodecanese"
- - "Drama"
- - "East Attica"
- - "Elis"
- - "Euboea"
- - "Evros"
- - "Evrytania"
- - "Florina"
- - "Grevena"
- - "Heraklion"
- - "Imathia"
- - "Ioannina"
- - "Karditsa"
- - "Kastoria"
- - "Kavala"
- - "Kefalonia and Ithaka"
- - "Kilkis"
- - "Kozani"
- - "Laconia"
- - "Larissa"
- - "Lasithi"
- - "Lefkada"
- - "Lesbos"
- - "Magnesia"
- - "Messenia"
- - "Pella"
- - "Phocis"
- - "Phthiotis"
- - "Pieria"
- - "Piraeus"
- - "Preveza"
- - "Rethymno"
- - "Rhodope"
- - "Samos"
- - "Serres"
- - "Thesprotia"
- - "Thessaloniki"
- - "Trikala"
- - "West Attica"
- - "Xanthi"
- - "Zakynthos"
-
-- name: Greenland
- iso2: GL
- iso3: GRL
- phone: 299
- units:
- - "Avannaa [Nordgronland]"
- - "Kitaa [Vestgronland]"
- - "Tunu [Ostgronland]"
-
-- name: Grenada
- iso2: GD
- iso3: GRD
- phone: 1 473
- units:
- - "Carriacou and Petit Martinique"
- - "Saint Andrew"
- - "Saint David"
- - "Saint George"
- - "Saint John"
- - "Saint Mark"
- - "Saint Patrick"
-
-- name: Guadeloupe
- iso2: GP
- iso3: GLP
- phone:
- units:
- - "Basse-Terre"
- - "Grande-Terre"
- - "Iles de la Petite Terre"
- - "Iles des Saintes"
- - "Marie-Galante"
-
-- name: Guam
- iso2: GU
- iso3: GUM
- phone: 1 671
- units:
- - "Guam"
-
-- name: Guatemala
- iso2: GT
- iso3: GTM
- phone: 502
- units:
- - "Alta Verapaz"
- - "Baja Verapaz"
- - "Chimaltenango"
- - "Chiquimula"
- - "El Progreso"
- - "Escuintla"
- - "Guatemala"
- - "Huehuetenango"
- - "Izabal"
- - "Jalapa"
- - "Jutiapa"
- - "Peten"
- - "Quetzaltenango"
- - "Quiche"
- - "Retalhuleu"
- - "Sacatepequez"
- - "San Marcos"
- - "Santa Rosa"
- - "Solola"
- - "Suchitepequez"
- - "Totonicapan"
- - "Zacapa"
-
-- name: Guernsey
- iso2: GG
- iso3: GGY
- phone:
- units:
- - "Castel"
- - "Forest"
- - "St. Andrew"
- - "St. Martin"
- - "St. Peter Port"
- - "St. Pierre du Bois"
- - "St. Sampson"
- - "St. Saviour"
- - "Torteval"
- - "Vale"
-
-- name: Guinea
- iso2: GN
- iso3: GIN
- phone: 224
- units:
- - "Beyla"
- - "Boffa"
- - "Boke"
- - "Conakry"
- - "Coyah"
- - "Dabola"
- - "Dalaba"
- - "Dinguiraye"
- - "Dubreka"
- - "Faranah"
- - "Forecariah"
- - "Fria"
- - "Gaoual"
- - "Gueckedou"
- - "Kankan"
- - "Kerouane"
- - "Kindia"
- - "Kissidougou"
- - "Koubia"
- - "Koundara"
- - "Kouroussa"
- - "Labe"
- - "Lelouma"
- - "Lola"
- - "Macenta"
- - "Mali"
- - "Mamou"
- - "Mandiana"
- - "Nzerekore"
- - "Pita"
- - "Siguiri"
- - "Telimele"
- - "Tougue"
- - "Yomou"
-
-- name: Guinea-Bissau
- iso2: GW
- iso3: GNB
- phone: 245
- units:
- - "Bafata"
- - "Biombo"
- - "Bissau"
- - "Bolama-Bijagos"
- - "Cacheu"
- - "Gabu"
- - "Oio"
- - "Quinara"
- - "Tombali"
-
-- name: Guyana
- iso2: GY
- iso3: GUY
- phone: 592
- units:
- - "Barima-Waini"
- - "Cuyuni-Mazaruni"
- - "Demerara-Mahaica"
- - "East Berbice-Corentyne"
- - "Essequibo Islands-West Demerara"
- - "Mahaica-Berbice"
- - "Pomeroon-Supenaam"
- - "Potaro-Siparuni"
- - "Upper Demerara-Berbice"
- - "Upper Takutu-Upper Essequibo"
-
-- name: Haiti
- iso2: HT
- iso3: HTI
- phone: 509
- units:
- - "Artibonite"
- - "Centre"
- - "Grand'Anse"
- - "Nord"
- - "Nord-Est"
- - "Nord-Ouest"
- - "Ouest"
- - "Sud"
- - "Sud-Est"
-
-- name: Heard Island and McDonald Islands
- iso2: HM
- iso3: HMD
- phone:
- units:
- - "Heard Island and McDonald Islands"
-
-- name: Holy See, Vatican City State
- iso2: VA
- iso3: VAT
- phone: 39
- units:
- - "Holy See [Vatican City]"
-
-- name: Honduras
- iso2: HN
- iso3: HND
- phone: 504
- units:
- - "Atlantida"
- - "Choluteca"
- - "Colon"
- - "Comayagua"
- - "Copan"
- - "Cortes"
- - "El Paraiso"
- - "Francisco Morazan"
- - "Gracias a Dios"
- - "Intibuca"
- - "Islas de la Bahia"
- - "La Paz"
- - "Lempira"
- - "Ocotepeque"
- - "Olancho"
- - "Santa Barbara"
- - "Valle"
- - "Yoro"
-
-- name: Hong Kong
- iso2: HK
- iso3: HKG
- phone: 852
- units:
- - "Hong Kong"
-
-- name: Hungary
- iso2: HU
- iso3: HUN
- phone: 36
- units:
- - "Bacs-Kiskun"
- - "Baranya"
- - "Bekes"
- - "Bekescsaba"
- - "Borsod-Abauj-Zemplen"
- - "Budapest"
- - "Csongrad"
- - "Debrecen"
- - "Dunaujvaros"
- - "Eger"
- - "Fejer"
- - "Gyor"
- - "Gyor-Moson-Sopron"
- - "Hajdu-Bihar"
- - "Heves"
- - "Hodmezovasarhely"
- - "Jasz-Nagykun-Szolnok"
- - "Kaposvar"
- - "Kecskemet"
- - "Komarom-Esztergom"
- - "Miskolc"
- - "Nagykanizsa"
- - "Nograd"
- - "Nyiregyhaza"
- - "Pecs"
- - "Pest"
- - "Somogy"
- - "Sopron"
- - "Szabolcs-Szatmar-Bereg"
- - "Szeged"
- - "Szekesfehervar"
- - "Szolnok"
- - "Szombathely"
- - "Tatabanya"
- - "Tolna"
- - "Vas"
- - "Veszprem"
- - "Veszprem"
- - "Zala"
- - "Zalaegerszeg"
-
-- name: Iceland
- iso2: IS
- iso3: ISL
- phone: 354
- units:
- - "Akranes"
- - "Akureyri"
- - "Arnessysla"
- - "Austur-Bardhastrandarsysla"
- - "Austur-Hunavatnssysla"
- - "Austur-Skaftafellssysla"
- - "Borgarfjardharsysla"
- - "Dalasysla"
- - "Eyjafjardharsysla"
- - "Gullbringusysla"
- - "Hafnarfjordhur"
- - "Husavik"
- - "Isafjordhur"
- - "Keflavik"
- - "Kjosarsysla"
- - "Kopavogur"
- - "Myrasysla"
- - "Neskaupstadhur"
- - "Nordhur-Isafjardharsysla"
- - "Nordhur-Mulasys-la"
- - "Nordhur-Thingeyjarsysla"
- - "Olafsfjordhur"
- - "Rangarvallasysla"
- - "Reykjavik"
- - "Saudharkrokur"
- - "Seydhisfjordhur"
- - "Siglufjordhur"
- - "Skagafjardharsysla"
- - "Snaefellsnes-og Hnappadalssysla"
- - "Strandasysla"
- - "Sudhur-Mulasysla"
- - "Sudhur-Thingeyjarsysla"
- - "Vesttmannaeyjar"
- - "Vestur-Bardhastrandarsysla"
- - "Vestur-Hunavatnssysla"
- - "Vestur-Isafjardharsysla"
- - "Vestur-Skaftafellssysla"
-
-- name: India
- iso2: IN
- iso3: IND
- phone: 91
- units:
- - "Andaman and Nicobar Islands"
- - "Andhra Pradesh"
- - "Arunachal Pradesh"
- - "Assam"
- - "Bihar"
- - "Chandigarh"
- - "Chhattisgarh"
- - "Dadra and Nagar Haveli"
- - "Daman and Diu"
- - "Delhi"
- - "Goa"
- - "Gujarat"
- - "Haryana"
- - "Himachal Pradesh"
- - "Jammu and Kashmir"
- - "Jharkhand"
- - "Karnataka"
- - "Kerala"
- - "Lakshadweep"
- - "Madhya Pradesh"
- - "Maharashtra"
- - "Manipur"
- - "Meghalaya"
- - "Mizoram"
- - "Nagaland"
- - "Orissa"
- - "Pondicherry"
- - "Punjab"
- - "Rajasthan"
- - "Sikkim"
- - "Tamil Nadu"
- - "Tripura"
- - "Uttar Pradesh"
- - "Uttaranchal"
- - "West Bengal"
-
-- name: Indonesia
- iso2: ID
- iso3: IDN
- phone: 62
- units:
- - "Aceh"
- - "Bali"
- - "Banten"
- - "Bengkulu"
- - "East Timor"
- - "Gorontalo"
- - "Irian Jaya"
- - "Jakarta Raya"
- - "Jambi"
- - "Jawa Barat"
- - "Jawa Tengah"
- - "Jawa Timur"
- - "Kalimantan Barat"
- - "Kalimantan Selatan"
- - "Kalimantan Tengah"
- - "Kalimantan Timur"
- - "Kepulauan Bangka Belitung"
- - "Lampung"
- - "Maluku"
- - "Maluku Utara"
- - "Nusa Tenggara Barat"
- - "Nusa Tenggara Timur"
- - "Riau"
- - "Sulawesi Selatan"
- - "Sulawesi Tengah"
- - "Sulawesi Tenggara"
- - "Sulawesi Utara"
- - "Sumatera Barat"
- - "Sumatera Selatan"
- - "Sumatera Utara"
- - "Yogyakarta"
-
-- name: Iran Islamic Republic of
- iso2: IR
- iso3: IRN
- phone: 98
- units:
- - "Ardabil"
- - "Azarbayjan-e Gharbi"
- - "Azarbayjan-e Sharqi"
- - "Bushehr"
- - "Chahar Mahall va Bakhtiari"
- - "Esfahan"
- - "Fars"
- - "Gilan"
- - "Golestan"
- - "Hamadan"
- - "Hormozgan"
- - "Ilam"
- - "Kerman"
- - "Kermanshah"
- - "Khorasan"
- - "Khuzestan"
- - "Kohgiluyeh va Buyer Ahmad"
- - "Kordestan"
- - "Lorestan"
- - "Markazi"
- - "Mazandaran"
- - "Qazvin"
- - "Qom"
- - "Semnan"
- - "Sistan va Baluchestan"
- - "Tehran"
- - "Yazd"
- - "Zanjan"
-
-- name: Iraq
- iso2: IQ
- iso3: IRQ
- phone: 964
- units:
- - "Al Anbar"
- - "Al Basrah"
- - "Al Muthanna"
- - "Al Qadisiyah"
- - "An Najaf"
- - "Arbil"
- - "As Sulaymaniyah"
- - "At Ta'mim"
- - "Babil"
- - "Baghdad"
- - "Dahuk"
- - "Dhi Qar"
- - "Diyala"
- - "Karbala'"
- - "Maysan"
- - "Ninawa"
- - "Salah ad Din"
- - "Wasit"
-
-- name: Ireland
- iso2: IE
- iso3: IRL
- phone: 353
- units:
- - "Co. Carlow"
- - "Co. Cavan"
- - "Co. Clare"
- - "Co. Cork"
- - "Co. Donegal"
- - "Co. Dublin"
- - "Co. Galway"
- - "Co. Kerry"
- - "Co. Kildare"
- - "Co. Kilkenny"
- - "Co. Laois"
- - "Co. Leitrim"
- - "Co. Limerick"
- - "Co. Longford"
- - "Co. Louth"
- - "Co. Mayo"
- - "Co. Meath"
- - "Co. Monaghan"
- - "Co. Offaly"
- - "Co. Roscommon"
- - "Co. Sligo"
- - "Co. Tipperary"
- - "Co. Waterford"
- - "Co. Westmeath"
- - "Co. Wexford"
- - "Co. Wicklow"
-
-- name: Isle of Man
- iso2: IM
- iso3: IMN
- phone: 44
- units:
- - "Isle of Man"
-
-- name: Israel
- iso2: IL
- iso3: ISR
- phone: 972
- units:
- - "Central"
- - "Haifa"
- - "Jerusalem"
- - "Northern"
- - "Southern"
- - "Tel Aviv"
-
-- name: Italy
- iso2: IT
- iso3: ITA
- phone: 39
- units:
- - "Agrigento"
- - "Alessandria"
- - "Ancona"
- - "Aosta"
- - "Ascoli Piceno"
- - "L'Aquila"
- - "Arezzo"
- - "Asti"
- - "Avellino"
- - "Bari"
- - "Bergamo"
- - "Biella"
- - "Belluno"
- - "Benevento"
- - "Bologna"
- - "Brindisi"
- - "Brescia"
- - "Barletta-Andria-Trani"
- - "Bolzano-Bozen"
- - "Cagliari"
- - "Campobasso"
- - "Caserta"
- - "Chieti"
- - "Carbonia-Inglesias"
- - "Caltanissetta"
- - "Cuneo"
- - "Como"
- - "Cremona"
- - "Cosenza"
- - "Catania"
- - "Catanzaro"
- - "Enna"
- - "Forlì-Cesena"
- - "Ferrara"
- - "Foggia"
- - "Firenze"
- - "Fermo"
- - "Frosinone"
- - "Genova"
- - "Gorizia"
- - "Grosseto"
- - "Imperia"
- - "Isernia"
- - "Crotone"
- - "Lecco"
- - "Lecce"
- - "Livorno"
- - "Lodi"
- - "Latina"
- - "Lucca"
- - "Monza e Brianza"
- - "Macerata"
- - "Messina"
- - "Milano"
- - "Mantova"
- - "Modena"
- - "Massa-Carrara"
- - "Matera"
- - "Napoli"
- - "Novara"
- - "Nuoro"
- - "Ogliastra"
- - "Oristano"
- - "Olbia-Tempio"
- - "Palermo"
- - "Piacenza"
- - "Padova"
- - "Pescara"
- - "Perugia"
- - "Pisa"
- - "Pordenone"
- - "Prato"
- - "Parma"
- - "Pistoia"
- - "Pesaro e Urbino"
- - "Pavia"
- - "Potenza"
- - "Ravenna"
- - "Reggio Calabria"
- - "Reggio Elilia"
- - "Ragusa"
- - "Rieti"
- - "Roma"
- - "Rimini"
- - "Rovigo"
- - "Salerno"
- - "Siena"
- - "Sondrio"
- - "La Spezia"
- - "Siracusa"
- - "Sassari"
- - "Savona"
- - "Taranto"
- - "Teramo"
- - "Trento"
- - "Torino"
- - "Trapani"
- - "Terni"
- - "Trieste"
- - "Treviso"
- - "Udine"
- - "Varese"
- - "Verbano-Cusio-Ossola"
- - "Vercelli"
- - "Venezia"
- - "Vicenza"
- - "Verona"
- - "Medio Campidano"
- - "Viterbo"
- - "Vibo Valentia"
-
-- name: Jamaica
- iso2: JM
- iso3: JAM
- phone: 1 876
- units:
- - "Clarendon"
- - "Hanover"
- - "Kingston"
- - "Manchester"
- - "Portland"
- - "Saint Andrew"
- - "Saint Ann"
- - "Saint Catherine"
- - "Saint Elizabeth"
- - "Saint James"
- - "Saint Mary"
- - "Saint Thomas"
- - "Trelawny"
- - "Westmoreland"
-
-- name: Japan
- iso2: JP
- iso3: JPN
- phone: 81
- units:
- - "Aichi"
- - "Akita"
- - "Aomori"
- - "Chiba"
- - "Ehime"
- - "Fukui"
- - "Fukuoka"
- - "Fukushima"
- - "Gifu"
- - "Gunma"
- - "Hiroshima"
- - "Hokkaido"
- - "Hyogo"
- - "Ibaragi"
- - "Ishikawa"
- - "Iwate"
- - "Kagawa"
- - "Kagoshima"
- - "Kanagawa"
- - "Kochi"
- - "Kumamoto"
- - "Kyoto"
- - "Mie"
- - "Miyagi"
- - "Miyazaki"
- - "Nagano"
- - "Nagasaki"
- - "Nara"
- - "Niigata"
- - "Oita"
- - "Okayama"
- - "Okinawa"
- - "Osaka"
- - "Saga"
- - "Saitama"
- - "Shiga"
- - "Shimane"
- - "Shizuoka"
- - "Tochigi"
- - "Tokushima"
- - "Tokyo"
- - "Tottori"
- - "Toyama"
- - "Wakayama"
- - "Yamagata"
- - "Yamaguchi"
- - "Yamanashi"
-
-- name: Jersey
- iso2: JE
- iso3: JEY
- phone:
- units:
- - "Jersey"
-
-- name: Jordan
- iso2: JO
- iso3: JOR
- phone: 962
- units:
- - "'Amman"
- - "Ajlun"
- - "Al 'Aqabah"
- - "Al Balqa'"
- - "Al Karak"
- - "Al Mafraq"
- - "At Tafilah"
- - "Az Zarqa'"
- - "Irbid"
- - "Jarash"
- - "Ma'an"
- - "Madaba"
-
-- name: Kazakhstan
- iso2: KZ
- iso3: KAZ
- phone: 7
- units:
- - "Almaty"
- - "Aqmola"
- - "Aqtobe"
- - "Astana"
- - "Atyrau"
- - "Batys Qazaqstan"
- - "Bayqongyr"
- - "Mangghystau"
- - "Ongtustik Qazaqstan"
- - "Pavlodar"
- - "Qaraghandy"
- - "Qostanay"
- - "Qyzylorda"
- - "Shyghys Qazaqstan"
- - "Soltustik Qazaqstan"
- - "Zhambyl"
-
-- name: Kenya
- iso2: KE
- iso3: KEN
- phone: 254
- units:
- - "Central"
- - "Coast"
- - "Eastern"
- - "Nairobi Area"
- - "North Eastern"
- - "Nyanza"
- - "Rift Valley"
- - "Western"
-
-- name: Kiribati
- iso2: KI
- iso3: KIR
- phone: 686
- units:
- - "Abaiang"
- - "Abemama"
- - "Aranuka"
- - "Arorae"
- - "Banaba"
- - "Banaba"
- - "Beru"
- - "Butaritari"
- - "Central Gilberts"
- - "Gilbert Islands"
- - "Kanton"
- - "Kiritimati"
- - "Kuria"
- - "Line Islands"
- - "Line Islands"
- - "Maiana"
- - "Makin"
- - "Marakei"
- - "Nikunau"
- - "Nonouti"
- - "Northern Gilberts"
- - "Onotoa"
- - "Phoenix Islands"
- - "Southern Gilberts"
- - "Tabiteuea"
- - "Tabuaeran"
- - "Tamana"
- - "Tarawa"
- - "Tarawa"
- - "Teraina"
-
-- name: Korea, Democratic People's Republic of
- iso2: KP
- iso3: PRK
- phone: 850
- units:
- - "Chagang-do [Chagang Province]"
- - "Hamgyong-bukto [North Hamgyong Province]"
- - "Hamgyong-namdo [South Hamgyong Province]"
- - "Hwanghae-bukto [North Hwanghae Province]"
- - "Hwanghae-namdo [South Hwanghae Province]"
- - "Kaesong-si [Kaesong City]"
- - "Kangwon-do [Kangwon Province]"
- - "Namp'o-si [Namp'o City]"
- - "P'yongan-bukto [North P'yongan Province]"
- - "P'yongan-namdo [South P'yongan Province]"
- - "P'yongyang-si [P'yongyang City]"
- - "Yanggang-do [Yanggang Province]"
-
-- name: Korea, Republic of
- iso2: KR
- iso3: KOR
- phone: 82
- units:
- - "Ch'ungch'ong-bukto"
- - "Ch'ungch'ong-namdo"
- - "Cheju-do"
- - "Cholla-bukto"
- - "Cholla-namdo"
- - "Inch'on-gwangyoksi"
- - "Kangwon-do"
- - "Kwangju-gwangyoksi"
- - "Kyonggi-do"
- - "Kyongsang-bukto"
- - "Kyongsang-namdo"
- - "Pusan-gwangyoksi"
- - "Soul-t'ukpyolsi"
- - "Taegu-gwangyoksi"
- - "Taejon-gwangyoksi"
- - "Ulsan-gwangyoksi"
-
-- name: Kuwait
- iso2: KW
- iso3: KWT
- phone: 965
- units:
- - "Al 'Asimah"
- - "Al Ahmadi"
- - "Al Farwaniyah"
- - "Al Jahra'"
- - "Hawalli"
-
-- name: Kyrgyzstan
- iso2: KG
- iso3: KGZ
- phone: 996
- units:
- - "Batken Oblasty"
- - "Bishkek Shaary"
- - "Chuy Oblasty [Bishkek]"
- - "Jalal-Abad Oblasty"
- - "Naryn Oblasty"
- - "Osh Oblasty"
- - "Talas Oblasty"
- - "Ysyk-Kol Oblasty [Karakol]"
-
-- name: Lao People's Democratic Republic
- iso2: LA
- iso3: LAO
- phone: 856
- units:
- - "Attapu"
- - "Bokeo"
- - "Bolikhamxai"
- - "Champasak"
- - "Houaphan"
- - "Khammouan"
- - "Louangnamtha"
- - "Louangphabang"
- - "Oudomxai"
- - "Phongsali"
- - "Salavan"
- - "Savannakhet"
- - "Viangchan"
- - "Viangchan"
- - "Xaignabouli"
- - "Xaisomboun"
- - "Xekong"
- - "Xiangkhoang"
-
-- name: Latvia
- iso2: LV
- iso3: LVA
- phone: 371
- units:
- - "Aizkraukles Rajons"
- - "Aluksnes Rajons"
- - "Balvu Rajons"
- - "Bauskas Rajons"
- - "Cesu Rajons"
- - "Daugavpils"
- - "Daugavpils Rajons"
- - "Dobeles Rajons"
- - "Gulbenes Rajons"
- - "Jekabpils Rajons"
- - "Jelgava"
- - "Jelgavas Rajons"
- - "Jurmala"
- - "Kraslavas Rajons"
- - "Kuldigas Rajons"
- - "Leipaja"
- - "Liepajas Rajons"
- - "Limbazu Rajons"
- - "Ludzas Rajons"
- - "Madonas Rajons"
- - "Ogres Rajons"
- - "Preilu Rajons"
- - "Rezekne"
- - "Rezeknes Rajons"
- - "Riga"
- - "Rigas Rajons"
- - "Saldus Rajons"
- - "Talsu Rajons"
- - "Tukuma Rajons"
- - "Valkas Rajons"
- - "Valmieras Rajons"
- - "Ventspils"
- - "Ventspils Rajons"
-
-- name: Lebanon
- iso2: LB
- iso3: LBN
- phone: 961
- units:
- - "Beyrouth"
- - "Ech Chimal"
- - "Ej Jnoub"
- - "El Bekaa"
- - "Jabal Loubnane"
-
-- name: Lesotho
- iso2: LS
- iso3: LSO
- phone: 266
- units:
- - "Berea"
- - "Butha-Buthe"
- - "Leribe"
- - "Mafeteng"
- - "Maseru"
- - "Mohales Hoek"
- - "Mokhotlong"
- - "Qacha's Nek"
- - "Quthing"
- - "Thaba-Tseka"
-
-- name: Liberia
- iso2: LR
- iso3: LBR
- phone: 231
- units:
- - "Bomi"
- - "Bong"
- - "Grand Bassa"
- - "Grand Cape Mount"
- - "Grand Gedeh"
- - "Grand Kru"
- - "Lofa"
- - "Margibi"
- - "Maryland"
- - "Montserrado"
- - "Nimba"
- - "River Cess"
- - "Sinoe"
-
-- name: Libyan Arab Jamahiriya
- iso2: LY
- iso3: LBY
- phone: 218
- units:
- - "Ajdabiya"
- - "Al 'Aziziyah"
- - "Al Fatih"
- - "Al Jabal al Akhdar"
- - "Al Jufrah"
- - "Al Khums"
- - "Al Kufrah"
- - "An Nuqat al Khams"
- - "Ash Shati'"
- - "Awbari"
- - "Az Zawiyah"
- - "Banghazi"
- - "Darnah"
- - "Ghadamis"
- - "Gharyan"
- - "Misratah"
- - "Murzuq"
- - "Sabha"
- - "Sawfajjin"
- - "Surt"
- - "Tarabulus"
- - "Tarhunah"
- - "Tubruq"
- - "Yafran"
- - "Zlitan"
-
-- name: Liechtenstein
- iso2: LI
- iso3: LIE
- phone: 423
- units:
- - "Balzers"
- - "Eschen"
- - "Gamprin"
- - "Mauren"
- - "Planken"
- - "Ruggell"
- - "Schaan"
- - "Schellenberg"
- - "Triesen"
- - "Triesenberg"
- - "Vaduz"
-
-- name: Lithuania
- iso2: LT
- iso3: LTU
- phone: 370
- units:
- - "Akmenes Rajonas"
- - "Alytaus Rajonas"
- - "Alytus"
- - "Anyksciu Rajonas"
- - "Birstonas"
- - "Birzu Rajonas"
- - "Druskininkai"
- - "Ignalinos Rajonas"
- - "Jonavos Rajonas"
- - "Joniskio Rajonas"
- - "Jurbarko Rajonas"
- - "Kaisiadoriu Rajonas"
- - "Kaunas"
- - "Kauno Rajonas"
- - "Kedainiu Rajonas"
- - "Kelmes Rajonas"
- - "Klaipeda"
- - "Klaipedos Rajonas"
- - "Kretingos Rajonas"
- - "Kupiskio Rajonas"
- - "Lazdiju Rajonas"
- - "Marijampole"
- - "Marijampoles Rajonas"
- - "Mazeikiu Rajonas"
- - "Moletu Rajonas"
- - "Neringa Pakruojo Rajonas"
- - "Palanga"
- - "Panevezio Rajonas"
- - "Panevezys"
- - "Pasvalio Rajonas"
- - "Plunges Rajonas"
- - "Prienu Rajonas"
- - "Radviliskio Rajonas"
- - "Raseiniu Rajonas"
- - "Rokiskio Rajonas"
- - "Sakiu Rajonas"
- - "Salcininku Rajonas"
- - "Siauliai"
- - "Siauliu Rajonas"
- - "Silales Rajonas"
- - "Silutes Rajonas"
- - "Sirvintu Rajonas"
- - "Skuodo Rajonas"
- - "Svencioniu Rajonas"
- - "Taurages Rajonas"
- - "Telsiu Rajonas"
- - "Traku Rajonas"
- - "Ukmerges Rajonas"
- - "Utenos Rajonas"
- - "Varenos Rajonas"
- - "Vilkaviskio Rajonas"
- - "Vilniaus Rajonas"
- - "Vilnius"
- - "Zarasu Rajonas"
-
-- name: Luxembourg
- iso2: LU
- iso3: LUX
- phone: 352
- units:
- - "Diekirch"
- - "Grevenmacher"
- - "Luxembourg"
-
-- name: Macao
- iso2: MO
- iso3: MAC
- phone: 853
- units:
- - "Macao"
-
-- name: Macedonia
- iso2: MK
- iso3: MKD
- phone: 389
- units:
- - "Aracinovo"
- - "Bac"
- - "Belcista"
- - "Berovo"
- - "Bistrica"
- - "Bitola"
- - "Blatec"
- - "Bogdanci"
- - "Bogomila"
- - "Bogovinje"
- - "Bosilovo"
- - "Brvenica"
- - "Cair [Skopje]"
- - "Capari"
- - "Caska"
- - "Cegrane"
- - "Centar [Skopje]"
- - "Centar Zupa"
- - "Cesinovo"
- - "Cucer-Sandevo"
- - "Debar"
- - "Delcevo"
- - "Delogozdi"
- - "Demir Hisar"
- - "Demir Kapija"
- - "Dobrusevo"
- - "Dolna Banjica"
- - "Dolneni"
- - "Dorce Petrov [Skopje]"
- - "Drugovo"
- - "Dzepciste"
- - "Gazi Baba [Skopje]"
- - "Gevgelija"
- - "Gostivar"
- - "Gradsko"
- - "Ilinden"
- - "Izvor"
- - "Jegunovce"
- - "Kamenjane"
- - "Karbinci"
- - "Karpos [Skopje]"
- - "Kavadarci"
- - "Kicevo"
- - "Kisela Voda [Skopje]"
- - "Klecevce"
- - "Kocani"
- - "Konce"
- - "Kondovo"
- - "Konopiste"
- - "Kosel"
- - "Kratovo"
- - "Kriva Palanka"
- - "Krivogastani"
- - "Krusevo"
- - "Kuklis"
- - "Kukurecani"
- - "Kumanovo"
- - "Labunista"
- - "Lipkovo"
- - "Lozovo"
- - "Lukovo"
- - "Makedonska Kamenica"
- - "Makedonski Brod"
- - "Mavrovi Anovi"
- - "Meseista"
- - "Miravci"
- - "Mogila"
- - "Murtino"
- - "Negotino"
- - "Negotino-Poloska"
- - "Novaci"
- - "Novo Selo"
- - "Oblesevo"
- - "Ohrid"
- - "Orasac"
- - "Orizari"
- - "Oslomej"
- - "Pehcevo"
- - "Petrovec"
- - "Plasnia"
- - "Podares"
- - "Prilep"
- - "Probistip"
- - "Radovis"
- - "Rankovce"
- - "Resen"
- - "Rosoman"
- - "Rostusa"
- - "Samokov"
- - "Saraj"
- - "Sipkovica"
- - "Sopiste"
- - "Sopotnika"
- - "Srbinovo"
- - "Star Dojran"
- - "Staravina"
- - "Staro Nagoricane"
- - "Stip"
- - "Struga"
- - "Strumica"
- - "Studenicani"
- - "Suto Orizari [Skopje]"
- - "Sveti Nikole"
- - "Tearce"
- - "Tetovo"
- - "Topolcani"
- - "Valandovo"
- - "Vasilevo"
- - "Veles"
- - "Velesta"
- - "Vevcani"
- - "Vinica"
- - "Vitoliste"
- - "Vranestica"
- - "Vrapciste"
- - "Vratnica"
- - "Vrutok"
- - "Zajas"
- - "Zelenikovo"
- - "Zileno"
- - "Zitose"
- - "Zletovo"
- - "Zrnovci"
-
-- name: Madagascar
- iso2: MG
- iso3: MDG
- phone: 261
- units:
- - "Antananarivo"
- - "Antsiranana"
- - "Fianarantsoa"
- - "Mahajanga"
- - "Toamasina"
- - "Toliara"
-
-- name: Malawi
- iso2: MW
- iso3: MWI
- phone: 265
- units:
- - "Balaka"
- - "Blantyre"
- - "Chikwawa"
- - "Chiradzulu"
- - "Chitipa"
- - "Dedza"
- - "Dowa"
- - "Karonga"
- - "Kasungu"
- - "Likoma"
- - "Lilongwe"
- - "Machinga [Kasupe]"
- - "Mangochi"
- - "Mchinji"
- - "Mulanje"
- - "Mwanza"
- - "Mzimba"
- - "Nkhata Bay"
- - "Nkhotakota"
- - "Nsanje"
- - "Ntcheu"
- - "Ntchisi"
- - "Phalombe"
- - "Rumphi"
- - "Salima"
- - "Thyolo"
- - "Zomba"
-
-- name: Malaysia
- iso2: MY
- iso3: MYS
- phone: 60
- units:
- - "Johor"
- - "Kedah"
- - "Kelantan"
- - "Labuan"
- - "Melaka"
- - "Negeri Sembilan"
- - "Pahang"
- - "Perak"
- - "Perlis"
- - "Pulau Pinang"
- - "Sabah"
- - "Sarawak"
- - "Selangor"
- - "Terengganu"
- - "Wilayah Persekutuan"
-
-- name: Maldives
- iso2: MV
- iso3: MDV
- phone: 960
- units:
- - "Alifu"
- - "Baa"
- - "Dhaalu"
- - "Faafu"
- - "Gaafu Alifu"
- - "Gaafu Dhaalu"
- - "Gnaviyani"
- - "Haa Alifu"
- - "Haa Dhaalu"
- - "Kaafu"
- - "Laamu"
- - "Lhaviyani"
- - "Maale"
- - "Meemu"
- - "Noonu"
- - "Raa"
- - "Seenu"
- - "Shaviyani"
- - "Thaa"
- - "Vaavu"
-
-- name: Mali
- iso2: ML
- iso3: MLI
- phone: 223
- units:
- - "Gao"
- - "Kayes"
- - "Kidal"
- - "Koulikoro"
- - "Mopti"
- - "Segou"
- - "Sikasso"
- - "Tombouctou"
-
-- name: Malta
- iso2: MT
- iso3: MLT
- phone: 356
- units:
- - "Valletta"
-
-- name: Marshall Islands
- iso2: MH
- iso3: MHL
- phone: 692
- units:
- - "Ailinginae"
- - "Ailinglaplap"
- - "Ailuk"
- - "Arno"
- - "Aur"
- - "Bikar"
- - "Bikini"
- - "Bokak"
- - "Ebon"
- - "Enewetak"
- - "Erikub"
- - "Jabat"
- - "Jaluit"
- - "Jemo"
- - "Kili"
- - "Kwajalein"
- - "Lae"
- - "Lib"
- - "Likiep"
- - "Majuro"
- - "Maloelap"
- - "Mejit"
- - "Mili"
- - "Namorik"
- - "Namu"
- - "Rongelap"
- - "Rongrik"
- - "Toke"
- - "Ujae"
- - "Ujelang"
- - "Utirik"
- - "Wotho"
- - "Wotje"
-
-- name: Martinique
- iso2: MQ
- iso3: MTQ
- phone:
- units:
- - "Martinique"
-
-- name: Mauritania
- iso2: MR
- iso3: MRT
- phone: 222
- units:
- - "Adrar"
- - "Assaba"
- - "Brakna"
- - "Dakhlet Nouadhibou"
- - "Gorgol"
- - "Guidimaka"
- - "Hodh Ech Chargui"
- - "Hodh El Gharbi"
- - "Inchiri"
- - "Nouakchott"
- - "Tagant"
- - "Tiris Zemmour"
- - "Trarza"
-
-- name: Mauritius
- iso2: MU
- iso3: MUS
- phone: 230
- units:
- - "Agalega Islands"
- - "Black River"
- - "Cargados Carajos Shoals"
- - "Flacq"
- - "Grand Port"
- - "Moka"
- - "Pamplemousses"
- - "Plaines Wilhems"
- - "Port Louis"
- - "Riviere du Rempart"
- - "Rodrigues"
- - "Savanne"
-
-- name: Mayotte
- iso2: YT
- iso3: MYT
- phone: 262
- units:
- - "Mayotte"
-
-- name: Mexico
- iso2: MX
- iso3: MEX
- phone: 52
- units:
- - "Aguascalientes"
- - "Baja California"
- - "Baja California Sur"
- - "Campeche"
- - "Chiapas"
- - "Chihuahua"
- - "Coahuila de Zaragoza"
- - "Colima"
- - "Distrito Federal"
- - "Durango"
- - "Guanajuato"
- - "Guerrero"
- - "Hidalgo"
- - "Jalisco"
- - "Mexico"
- - "Michoacan de Ocampo"
- - "Morelos"
- - "Nayarit"
- - "Nuevo Leon"
- - "Oaxaca"
- - "Puebla"
- - "Queretaro de Arteaga"
- - "Quintana Roo"
- - "San Luis Potosi"
- - "Sinaloa"
- - "Sonora"
- - "Tabasco"
- - "Tamaulipas"
- - "Tlaxcala"
- - "Veracruz-Llave"
- - "Yucatan"
- - "Zacatecas"
-
-- name: Micronesia Federated States of
- iso2: FM
- iso3: FSM
- phone: 691
- units:
- - "Chuuk [Truk]"
- - "Kosrae"
- - "Pohnpei"
- - "Yap"
-
-- name: Moldova
- iso2: MD
- iso3: MDA
- phone: 373
- units:
- - "Balti"
- - "Cahul"
- - "Chisinau"
- - "Chisinau"
- - "Dubasari"
- - "Edinet"
- - "Gagauzia"
- - "Lapusna"
- - "Orhei"
- - "Soroca"
- - "Tighina"
- - "Ungheni"
-
-- name: Monaco
- iso2: MC
- iso3: MCO
- phone: 377
- units:
- - "Fontvieille"
- - "La Condamine"
- - "Monaco-Ville"
- - "Monte-Carlo"
-
-- name: Mongolia
- iso2: MN
- iso3: MNG
- phone: 976
- units:
- - "Arhangay"
- - "Bayan-Olgiy"
- - "Bayanhongor"
- - "Bulgan"
- - "Darhan"
- - "Dornod"
- - "Dornogovi"
- - "Dundgovi"
- - "Dzavhan"
- - "Erdenet"
- - "Govi-Altay"
- - "Hentiy"
- - "Hovd"
- - "Hovsgol"
- - "Omnogovi"
- - "Ovorhangay"
- - "Selenge"
- - "Suhbaatar"
- - "Tov"
- - "Ulaanbaatar"
- - "Uvs"
-
-- name: Montenegro
- iso2: ME
- iso3: MNE
- phone: 382
- units:
- - "Montenegro"
-
-- name: Montserrat
- iso2: MS
- iso3: MSR
- phone: 1 664
- units:
- - "Saint Anthony"
- - "Saint Georges"
- - "Saint Peter's"
-
-- name: Morocco
- iso2: MA
- iso3: MAR
- phone: 212
- units:
- - "Agadir"
- - "Al Hoceima"
- - "Azilal"
- - "Ben Slimane"
- - "Beni Mellal"
- - "Boulemane"
- - "Casablanca"
- - "Chaouen"
- - "El Jadida"
- - "El Kelaa des Srarhna"
- - "Er Rachidia"
- - "Essaouira"
- - "Fes"
- - "Figuig"
- - "Guelmim"
- - "Ifrane"
- - "Kenitra"
- - "Khemisset"
- - "Khenifra"
- - "Khouribga"
- - "Laayoune"
- - "Larache"
- - "Marrakech"
- - "Meknes"
- - "Nador"
- - "Ouarzazate"
- - "Oujda"
- - "Rabat-Sale"
- - "Safi"
- - "Settat"
- - "Sidi Kacem"
- - "Tan-Tan"
- - "Tanger"
- - "Taounate"
- - "Taroudannt"
- - "Tata"
- - "Taza"
- - "Tetouan"
- - "Tiznit"
-
-- name: Mozambique
- iso2: MZ
- iso3: MOZ
- phone: 258
- units:
- - "Cabo Delgado"
- - "Gaza"
- - "Inhambane"
- - "Manica"
- - "Maputo"
- - "Nampula"
- - "Niassa"
- - "Sofala"
- - "Tete"
- - "Zambezia"
-
-- name: Myanmar
- iso2: MM
- iso3: MMR
- phone: 95
- units:
- - "Ayeyarwady"
- - "Bago"
- - "Chin State"
- - "Kachin State"
- - "Kayah State"
- - "Kayin State"
- - "Magway"
- - "Mandalay"
- - "Mon State"
- - "Rakhine State"
- - "Sagaing"
- - "Shan State"
- - "Tanintharyi"
- - "Yangon"
-
-- name: Namibia
- iso2: NA
- iso3: NAM
- phone: 264
- units:
- - "Caprivi"
- - "Erongo"
- - "Hardap"
- - "Karas"
- - "Khomas"
- - "Kunene"
- - "Ohangwena"
- - "Okavango"
- - "Omaheke"
- - "Omusati"
- - "Oshana"
- - "Oshikoto"
- - "Otjozondjupa"
-
-- name: Nauru
- iso2: NR
- iso3: NRU
- phone: 674
- units:
- - "Aiwo"
- - "Anabar"
- - "Anetan"
- - "Anibare"
- - "Baiti"
- - "Boe"
- - "Buada"
- - "Denigomodu"
- - "Ewa"
- - "Ijuw"
- - "Meneng"
- - "Nibok"
- - "Uaboe"
- - "Yaren"
-
-- name: Nepal
- iso2: NP
- iso3: NPL
- phone: 977
- units:
- - "Bagmati"
- - "Bheri"
- - "Dhawalagiri"
- - "Gandaki"
- - "Janakpur"
- - "Karnali"
- - "Kosi"
- - "Lumbini"
- - "Mahakali"
- - "Mechi"
- - "Narayani"
- - "Rapti"
- - "Sagarmatha"
- - "Seti"
-
-- name: Netherlands
- iso2: NL
- iso3: NLD
- phone: 31
- units:
- - "Drenthe"
- - "Flevoland"
- - "Friesland"
- - "Gelderland"
- - "Groningen"
- - "Limburg"
- - "Noord-Brabant"
- - "Noord-Holland"
- - "Overijssel"
- - "Utrecht"
- - "Zeeland"
- - "Zuid-Holland"
-
-- name: New Caledonia
- iso2: NC
- iso3: NCL
- phone: 687
- units:
- - "Iles Loyaute"
- - "Nord"
- - "Sud"
-
-- name: New Zealand
- iso2: NZ
- iso3: NZL
- phone: 64
- units:
- - "Akaroa"
- - "Amuri"
- - "Ashburton"
- - "Bay of Islands"
- - "Bruce"
- - "Buller"
- - "Chatham Islands"
- - "Cheviot"
- - "Clifton"
- - "Clutha"
- - "Cook"
- - "Dannevirke"
- - "Egmont"
- - "Eketahuna"
- - "Ellesmere"
- - "Eltham"
- - "Eyre"
- - "Featherston"
- - "Franklin"
- - "Golden Bay"
- - "Great Barrier Island"
- - "Grey"
- - "Hauraki Plains"
- - "Hawera"
- - "Hawke's Bay"
- - "Heathcote"
- - "Hikurangi"
- - "Hobson"
- - "Hokianga"
- - "Horowhenua"
- - "Hurunui"
- - "Hutt"
- - "Inangahua"
- - "Inglewood"
- - "Kaikoura"
- - "Kairanga"
- - "Kiwitea"
- - "Lake"
- - "Mackenzie"
- - "Malvern"
- - "Manaia"
- - "Manawatu"
- - "Mangonui"
- - "Maniototo"
- - "Marlborough"
- - "Masterton"
- - "Matamata"
- - "Mount Herbert"
- - "Ohinemuri"
- - "Opotiki"
- - "Oroua"
- - "Otamatea"
- - "Otorohanga"
- - "Oxford"
- - "Pahiatua"
- - "Paparua"
- - "Patea"
- - "Piako"
- - "Pohangina"
- - "Raglan"
- - "Rangiora"
- - "Rangitikei"
- - "Rodney"
- - "Rotorua"
- - "Runanga"
- - "Saint Kilda"
- - "Silverpeaks"
- - "Southland"
- - "Stewart Island"
- - "Stratford"
- - "Strathallan"
- - "Taranaki"
- - "Taumarunui"
- - "Taupo"
- - "Tauranga"
- - "Thames-Coromandel"
- - "Tuapeka"
- - "Vincent"
- - "Waiapu"
- - "Waiheke"
- - "Waihemo"
- - "Waikato"
- - "Waikohu"
- - "Waimairi"
- - "Waimarino"
- - "Waimate"
- - "Waimate West"
- - "Waimea"
- - "Waipa"
- - "Waipawa"
- - "Waipukurau"
- - "Wairarapa South"
- - "Wairewa"
- - "Wairoa"
- - "Waitaki"
- - "Waitomo"
- - "Waitotara"
- - "Wallace"
- - "Wanganui"
- - "Waverley"
- - "Westland"
- - "Whakatane"
- - "Whangarei"
- - "Whangaroa"
- - "Woodville"
-
-- name: Nicaragua
- iso2: NI
- iso3: NIC
- phone: 505
- units:
- - "Atlantico Norte"
- - "Atlantico Sur"
- - "Boaco"
- - "Carazo"
- - "Chinandega"
- - "Chontales"
- - "Esteli"
- - "Granada"
- - "Jinotega"
- - "Leon"
- - "Madriz"
- - "Managua"
- - "Masaya"
- - "Matagalpa"
- - "Nueva Segovia"
- - "Rio San Juan"
- - "Rivas"
-
-- name: Niger
- iso2: NE
- iso3: NER
- phone: 227
- units:
- - "Agadez"
- - "Diffa"
- - "Dosso"
- - "Maradi"
- - "Niamey"
- - "Tahoua"
- - "Tillaberi"
- - "Zinder"
-
-- name: Nigeria
- iso2: NG
- iso3: NGA
- phone: 234
- units:
- - "Abia"
- - "Abuja Federal Capital Territory"
- - "Adamawa"
- - "Akwa Ibom"
- - "Anambra"
- - "Bauchi"
- - "Bayelsa"
- - "Benue"
- - "Borno"
- - "Cross River"
- - "Delta"
- - "Ebonyi"
- - "Edo"
- - "Ekiti"
- - "Enugu"
- - "Gombe"
- - "Imo"
- - "Jigawa"
- - "Kaduna"
- - "Kano"
- - "Katsina"
- - "Kebbi"
- - "Kogi"
- - "Kwara"
- - "Lagos"
- - "Nassarawa"
- - "Niger"
- - "Ogun"
- - "Ondo"
- - "Osun"
- - "Oyo"
- - "Plateau"
- - "Rivers"
- - "Sokoto"
- - "Taraba"
- - "Yobe"
- - "Zamfara"
-
-- name: Niue
- iso2: NU
- iso3: NIU
- phone: 683
- units:
- - "Niue"
-
-- name: Norfolk Island
- iso2: NF
- iso3: NFK
- phone:
- units:
- - "Norfolk Island"
-
-- name: Northern Mariana Islands
- iso2: MP
- iso3: MNP
- phone: 1 670
- units:
- - "Northern Islands"
- - "Rota"
- - "Saipan"
- - "Tinian"
-
-- name: Norway
- iso2: NO
- iso3: NOR
- phone: 47
- units:
- - "Akershus"
- - "Aust-Agder"
- - "Buskerud"
- - "Finnmark"
- - "Hedmark"
- - "Hordaland"
- - "More og Romsdal"
- - "Nord-Trondelag"
- - "Nordland"
- - "Oppland"
- - "Oslo"
- - "Ostfold"
- - "Rogaland"
- - "Sogn og Fjordane"
- - "Sor-Trondelag"
- - "Telemark"
- - "Troms"
- - "Vest-Agder"
- - "Vestfold"
-
-- name: Oman
- iso2: OM
- iso3: OMN
- phone: 968
- units:
- - "Ad Dakhiliyah"
- - "Al Batinah"
- - "Al Wusta"
- - "Ash Sharqiyah"
- - "Az Zahirah"
- - "Masqat"
- - "Musandam"
- - "Zufar"
-
-- name: Pakistan
- iso2: PK
- iso3: PAK
- phone: 92
- units:
- - "Balochistan"
- - "Federally Administered Tribal Areas"
- - "Islamabad Capital Territory"
- - "North-West Frontier Province"
- - "Punjab"
- - "Sindh"
-
-- name: Palau
- iso2: PW
- iso3: PLW
- phone: 680
- units:
- - "Aimeliik"
- - "Airai"
- - "Angaur"
- - "Hatobohei"
- - "Kayangel"
- - "Koror"
- - "Melekeok"
- - "Ngaraard"
- - "Ngarchelong"
- - "Ngardmau"
- - "Ngatpang"
- - "Ngchesar"
- - "Ngeremlengui"
- - "Ngiwal"
- - "Palau Island"
- - "Peleliu"
- - "Sonsoral"
- - "Tobi"
-
-- name: Palestinian Territory Occupied
- iso2: PS
- iso3: PSE
- phone:
- units:
- - "West Bank"
- - "Gaza Strip"
-
-- name: Panama
- iso2: PA
- iso3: PAN
- phone: 507
- units:
- - "Bocas del Toro"
- - "Chiriqui"
- - "Cocle"
- - "Colon"
- - "Darien"
- - "Herrera"
- - "Los Santos"
- - "Panama"
- - "San Blas"
- - "Veraguas"
-
-- name: Papua New Guinea
- iso2: PG
- iso3: PNG
- phone: 675
- units:
- - "Bougainville"
- - "Central"
- - "Chimbu"
- - "East New Britain"
- - "East Sepik"
- - "Eastern Highlands"
- - "Enga"
- - "Gulf"
- - "Madang"
- - "Manus"
- - "Milne Bay"
- - "Morobe"
- - "National Capital"
- - "New Ireland"
- - "Northern"
- - "Sandaun"
- - "Southern Highlands"
- - "West New Britain"
- - "Western"
- - "Western Highlands"
-
-- name: Paraguay
- iso2: PY
- iso3: PRY
- phone: 595
- units:
- - "Alto Paraguay"
- - "Alto Parana"
- - "Amambay"
- - "Asuncion [city]"
- - "Boqueron"
- - "Caaguazu"
- - "Caazapa"
- - "Canindeyu"
- - "Central"
- - "Concepcion"
- - "Cordillera"
- - "Guaira"
- - "Itapua"
- - "Misiones"
- - "Neembucu"
- - "Paraguari"
- - "Presidente Hayes"
- - "San Pedro"
-
-- name: Peru
- iso2: PE
- iso3: PER
- phone: 51
- units:
- - "Amazonas"
- - "Ancash"
- - "Apurimac"
- - "Arequipa"
- - "Ayacucho"
- - "Cajamarca"
- - "Callao"
- - "Cusco"
- - "Huancavelica"
- - "Huanuco"
- - "Ica"
- - "Junin"
- - "La Libertad"
- - "Lambayeque"
- - "Lima"
- - "Loreto"
- - "Madre de Dios"
- - "Moquegua"
- - "Pasco"
- - "Piura"
- - "Puno"
- - "San Martin"
- - "Tacna"
- - "Tumbes"
- - "Ucayali"
-
-- name: Philippines
- iso2: PH
- iso3: PHL
- phone: 63
- units:
- - "Abra"
- - "Agusan del Norte"
- - "Agusan del Sur"
- - "Aklan"
- - "Albay"
- - "Angeles"
- - "Antique"
- - "Aurora"
- - "Bacolod"
- - "Bago"
- - "Baguio"
- - "Bais"
- - "Basilan"
- - "Basilan City"
- - "Bataan"
- - "Batanes"
- - "Batangas"
- - "Batangas City"
- - "Benguet"
- - "Bohol"
- - "Bukidnon"
- - "Bulacan"
- - "Butuan"
- - "Cabanatuan"
- - "Cadiz"
- - "Cagayan"
- - "Cagayan de Oro"
- - "Calbayog"
- - "Caloocan"
- - "Camarines Norte"
- - "Camarines Sur"
- - "Camiguin"
- - "Canlaon"
- - "Capiz"
- - "Catanduanes"
- - "Cavite"
- - "Cavite City"
- - "Cebu"
- - "Cebu City"
- - "Cotabato"
- - "Dagupan"
- - "Danao"
- - "Dapitan"
- - "Davao City Davao"
- - "Davao del Sur"
- - "Davao Oriental"
- - "Dipolog"
- - "Dumaguete"
- - "Eastern Samar"
- - "General Santos"
- - "Gingoog"
- - "Ifugao"
- - "Iligan"
- - "Ilocos Norte"
- - "Ilocos Sur"
- - "Iloilo"
- - "Iloilo City"
- - "Iriga"
- - "Isabela"
- - "Kalinga-Apayao"
- - "La Carlota"
- - "La Union"
- - "Laguna"
- - "Lanao del Norte"
- - "Lanao del Sur"
- - "Laoag"
- - "Lapu-Lapu"
- - "Legaspi"
- - "Leyte"
- - "Lipa"
- - "Lucena"
- - "Maguindanao"
- - "Mandaue"
- - "Manila"
- - "Marawi"
- - "Marinduque"
- - "Masbate"
- - "Mindoro Occidental"
- - "Mindoro Oriental"
- - "Misamis Occidental"
- - "Misamis Oriental"
- - "Mountain"
- - "Naga"
- - "Negros Occidental"
- - "Negros Oriental"
- - "North Cotabato"
- - "Northern Samar"
- - "Nueva Ecija"
- - "Nueva Vizcaya"
- - "Olongapo"
- - "Ormoc"
- - "Oroquieta"
- - "Ozamis"
- - "Pagadian"
- - "Palawan"
- - "Palayan"
- - "Pampanga"
- - "Pangasinan"
- - "Pasay"
- - "Puerto Princesa"
- - "Quezon"
- - "Quezon City"
- - "Quirino"
- - "Rizal"
- - "Romblon"
- - "Roxas"
- - "Samar"
- - "San Carlos [in Negros Occidental]"
- - "San Carlos [in Pangasinan]"
- - "San Jose"
- - "San Pablo"
- - "Silay"
- - "Siquijor"
- - "Sorsogon"
- - "South Cotabato"
- - "Southern Leyte"
- - "Sultan Kudarat"
- - "Sulu"
- - "Surigao"
- - "Surigao del Norte"
- - "Surigao del Sur"
- - "Tacloban"
- - "Tagaytay"
- - "Tagbilaran"
- - "Tangub"
- - "Tarlac"
- - "Tawitawi"
- - "Toledo"
- - "Trece Martires"
- - "Zambales"
- - "Zamboanga"
- - "Zamboanga del Norte"
- - "Zamboanga del Sur"
-
-- name: Pitcairn
- iso2: PN
- iso3: PCN
- phone: 870
- units:
- - "Pitcarin Islands"
-
-- name: Poland
- iso2: PL
- iso3: POL
- phone: 48
- units:
- - "Dolnoslaskie"
- - "Kujawsko-Pomorskie"
- - "Lodzkie"
- - "Lubelskie"
- - "Lubuskie"
- - "Malopolskie"
- - "Mazowieckie"
- - "Opolskie"
- - "Podkarpackie"
- - "Podlaskie"
- - "Pomorskie"
- - "Slaskie"
- - "Swietokrzyskie"
- - "Warminsko-Mazurskie"
- - "Wielkopolskie"
- - "Zachodniopomorskie"
-
-- name: Portugal
- iso2: PT
- iso3: PRT
- phone: 351
- units:
- - "Acores [Azores]"
- - "Aveiro"
- - "Beja"
- - "Braga"
- - "Braganca"
- - "Castelo Branco"
- - "Coimbra"
- - "Evora"
- - "Faro"
- - "Guarda"
- - "Leiria"
- - "Lisboa"
- - "Madeira"
- - "Portalegre"
- - "Porto"
- - "Santarem"
- - "Setubal"
- - "Viana do Castelo"
- - "Vila Real"
- - "Viseu"
-
-- name: Puerto Rico
- iso2: PR
- iso3: PRI
- phone: 1
- units:
- - "Adjuntas"
- - "Aguada"
- - "Aguadilla"
- - "Aguas Buenas"
- - "Aibonito"
- - "Anasco"
- - "Arecibo"
- - "Arroyo"
- - "Barceloneta"
- - "Barranquitas"
- - "Bayamon"
- - "Cabo Rojo"
- - "Caguas"
- - "Camuy"
- - "Canovanas"
- - "Carolina"
- - "Catano"
- - "Cayey"
- - "Ceiba"
- - "Ciales"
- - "Cidra"
- - "Coamo"
- - "Comerio"
- - "Corozal"
- - "Culebra"
- - "Dorado"
- - "Fajardo"
- - "Florida"
- - "Guanica"
- - "Guayama"
- - "Guayanilla"
- - "Guaynabo"
- - "Gurabo"
- - "Hatillo"
- - "Hormigueros"
- - "Humacao"
- - "Isabela"
- - "Jayuya"
- - "Juana Diaz"
- - "Juncos"
- - "Lajas"
- - "Lares"
- - "Las Marias"
- - "Las Piedras"
- - "Loiza"
- - "Luquillo"
- - "Manati"
- - "Maricao"
- - "Maunabo"
- - "Mayaguez"
- - "Moca"
- - "Morovis"
- - "Naguabo"
- - "Naranjito"
- - "Orocovis"
- - "Patillas"
- - "Penuelas"
- - "Ponce"
- - "Quebradillas"
- - "Rincon"
- - "Rio Grande"
- - "Sabana Grande"
- - "Salinas"
- - "San German"
- - "San Juan"
- - "San Lorenzo"
- - "San Sebastian"
- - "Santa Isabel"
- - "Toa Alta"
- - "Toa Baja"
- - "Trujillo Alto"
- - "Utuado"
- - "Vega Alta"
- - "Vega Baja"
- - "Vieques"
- - "Villalba"
- - "Yabucoa"
- - "Yauco"
-
-- name: Qatar
- iso2: QA
- iso3: QAT
- phone: 974
- units:
- - "Ad Dawhah"
- - "Al Ghuwayriyah"
- - "Al Jumayliyah"
- - "Al Khawr"
- - "Al Wakrah"
- - "Ar Rayyan"
- - "Jarayan al Batinah"
- - "Madinat ash Shamal"
- - "Umm Salal"
-
-- name: Reunion
- iso2: RE
- iso3: REU
- phone:
- units:
- - "Reunion"
-
-- name: Romania
- iso2: RO
- iso3: ROU
- phone: 40
- units:
- - "Alba"
- - "Arad"
- - "Arges"
- - "Bacau"
- - "Bihor"
- - "Bistrita-Nasaud"
- - "Botosani"
- - "Braila"
- - "Brasov"
- - "Bucuresti"
- - "Buzau"
- - "Calarasi"
- - "Caras-Severin"
- - "Cluj"
- - "Constanta"
- - "Covasna"
- - "Dimbovita"
- - "Dolj"
- - "Galati"
- - "Giurgiu"
- - "Gorj"
- - "Harghita"
- - "Hunedoara"
- - "Ialomita"
- - "Iasi"
- - "Maramures"
- - "Mehedinti"
- - "Mures"
- - "Neamt"
- - "Olt"
- - "Prahova"
- - "Salaj"
- - "Satu Mare"
- - "Sibiu"
- - "Suceava"
- - "Teleorman"
- - "Timis"
- - "Tulcea"
- - "Vaslui"
- - "Vilcea"
- - "Vrancea"
-
-- name: Russian Federation
- iso2: RU
- iso3: RUS
- phone: 7
- units:
- - "Республика Адыгея"
- - "Республика Алтай"
- - "Амурская область"
- - "Архангельская область"
- - "Астраханская область"
- - "Республика Башкортостан"
- - "Белгородская область"
- - "Брянская область"
- - "Республика Бурятия"
- - "Чеченская Республика"
- - "Челябинская область"
- - "Чукотский АО"
- - "Чувашская Республика"
- - "Республика Дагестан"
- - "Республика Ингушетия"
- - "Иркутская область"
- - "Ивановская область"
- - "Камчатский край"
- - "Кабардино-Балкарская Республика"
- - "Карачаево-Черкесская Республика"
- - "Краснодарский край"
- - "Кемеровская область"
- - "Калининградская область"
- - "Курганская область"
- - "Хабаровский край"
- - "Ханты-Мансийский АО"
- - "Кировская область"
- - "Республика Хакасия"
- - "Республика Калмыкия"
- - "Калужская область"
- - "Республика Коми"
- - "Костромская область"
- - "Республика Карелия"
- - "Курская область"
- - "Красноярский край"
- - "Ленинградская область"
- - "Липецкая область"
- - "Алтайский край"
- - "Магаданская область"
- - "Республика Марий Эл"
- - "Республика Мордовия"
- - "Московская область"
- - "Москва"
- - "Мурманская область"
- - "Ненецкий АО"
- - "Новгородская область"
- - "Нижегородская область"
- - "Новосибирская область"
- - "Омская область"
- - "Оренбургская область"
- - "Орловская область"
- - "Пермский край"
- - "Пензенская область"
- - "Приморский край"
- - "Псковская область"
- - "Ростовская область"
- - "Рязанская область"
- - "Республика Саха [Якутия]"
- - "Сахалинская область"
- - "Самарская область"
- - "Саратовская область"
- - "Республика Сев. Осетия-Алания"
- - "Смоленская область"
- - "Санкт-Петербург"
- - "Ставропольский край"
- - "Свердловская область"
- - "Республика Татарстан"
- - "Тамбовская область"
- - "Томская область"
- - "Тульская область"
- - "Тверская область"
- - "Республика Тыва"
- - "Тюменская область"
- - "Удмуртская Республика"
- - "Ульяновская область"
- - "Волгоградская область"
- - "Владимирская область"
- - "Вологодская область"
- - "Воронежская область"
- - "Ямало-Ненецкий АО"
- - "Ярославская область"
- - "Еврейская АО"
- - "Забайкальский край"
-
-- name: Rwanda
- iso2: RW
- iso3: RWA
- phone: 250
- units:
- - "Butare"
- - "Byumba"
- - "Cyangugu"
- - "Gikongoro"
- - "Gisenyi"
- - "Gitarama"
- - "Kibungo"
- - "Kibuye"
- - "Kigali Rurale"
- - "Kigali-ville"
- - "Ruhengeri"
- - "Umutara"
-
-- name: Saint Barthelemy
- iso2: BL
- iso3: BLM
- phone: 590
- units:
- - "Saint Barthelemy"
-
-- name: Saint Helena Ascension and Tristan da Cunha
- iso2: SH
- iso3: SHN
- phone: 290
- units:
- - "Ascension"
- - "Saint Helena"
- - "Tristan da Cunha"
-
-- name: Saint Kitts and Nevis
- iso2: KN
- iso3: KNA
- phone: 1 869
- units:
- - "Christ Church Nichola Town"
- - "Saint Anne Sandy Point"
- - "Saint George Basseterre"
- - "Saint George Gingerland"
- - "Saint James Windward"
- - "Saint John Capisterre"
- - "Saint John Figtree"
- - "Saint Mary Cayon"
- - "Saint Paul Capisterre"
- - "Saint Paul Charlestown"
- - "Saint Peter Basseterre"
- - "Saint Thomas Lowland"
- - "Saint Thomas Middle Island"
- - "Trinity Palmetto Point"
-
-- name: Saint Lucia
- iso2: LC
- iso3: LCA
- phone: 1 758
- units:
- - "Anse-la-Raye"
- - "Castries"
- - "Choiseul"
- - "Dauphin"
- - "Dennery"
- - "Gros Islet"
- - "Laborie"
- - "Micoud"
- - "Praslin"
- - "Soufriere"
- - "Vieux Fort"
-
-- name: Saint Martin [French part]
- iso2: MF
- iso3: MAF
- phone: 1 599
- units:
- - "Saint Martin [French part]"
-
-- name: Saint Pierre and Miquelon
- iso2: PM
- iso3: SPM
- phone: 508
- units:
- - "Miquelon"
- - "Saint Pierre"
-
-- name: Saint Vincent and the Grenadines
- iso2: VC
- iso3: VCT
- phone: 1 784
- units:
- - "Charlotte"
- - "Grenadines"
- - "Saint Andrew"
- - "Saint David"
- - "Saint George"
- - "Saint Patrick"
-
-- name: Samoa
- iso2: WS
- iso3: WSM
- phone: 685
- units:
- - "A'ana"
- - "Aiga-i-le-Tai"
- - "Atua"
- - "Fa'asaleleaga"
- - "Gaga'emauga"
- - "Gagaifomauga"
- - "Palauli"
- - "Satupa'itea"
- - "Tuamasaga"
- - "Va'a-o-Fonoti"
- - "Vaisigano"
-
-- name: San Marino
- iso2: SM
- iso3: SMR
- phone: 378
- units:
- - "Acquaviva"
- - "Borgo Maggiore"
- - "Chiesanuova"
- - "Domagnano"
- - "Faetano"
- - "Fiorentino"
- - "Monte Giardino"
- - "San Marino"
- - "Serravalle"
-
-- name: Sao Tome and Principe
- iso2: ST
- iso3: STP
- phone: 239
- units:
- - "Principe"
- - "Sao Tome"
-
-- name: Saudi Arabia
- iso2: SA
- iso3: SAU
- phone: 966
- units:
- - "'Asir"
- - "Al Bahah"
- - "Al Hudud ash Shamaliyah"
- - "Al Jawf"
- - "Al Madinah"
- - "Al Qasim"
- - "Ar Riyad"
- - "Ash Sharqiyah [Eastern Province]"
- - "Ha'il"
- - "Jizan"
- - "Makkah"
- - "Najran"
- - "Tabuk"
-
-- name: Senegal
- iso2: SN
- iso3: SEN
- phone: 221
- units:
- - "Dakar"
- - "Diourbel"
- - "Fatick"
- - "Kaolack"
- - "Kolda"
- - "Louga"
- - "Saint-Louis"
- - "Tambacounda"
- - "Thies"
- - "Ziguinchor"
-
-- name: Serbia
- iso2: RS
- iso3: SRB
- phone: 381
- units:
- - "Serbia"
-
-- name: Seychelles
- iso2: SC
- iso3: SYC
- phone: 248
- units:
- - "Anse aux Pins"
- - "Anse Boileau"
- - "Anse Etoile"
- - "Anse Louis"
- - "Anse Royale"
- - "Baie Lazare"
- - "Baie Sainte Anne"
- - "Beau Vallon"
- - "Bel Air"
- - "Bel Ombre"
- - "Cascade"
- - "Glacis"
- - "Grand' Anse [on Mahe]"
- - "Grand' Anse [on Praslin]"
- - "La Digue"
- - "La Riviere Anglaise"
- - "Mont Buxton"
- - "Mont Fleuri"
- - "Plaisance"
- - "Pointe La Rue"
- - "Port Glaud"
- - "Saint Louis"
- - "Takamaka"
-
-- name: Sierra Leone
- iso2: SL
- iso3: SLE
- phone: 232
- units:
- - "Eastern"
- - "Northern"
- - "Southern"
- - "Western"
-
-- name: Singapore
- iso2: SG
- iso3: SGP
- phone: 65
- units:
- - "Singapore"
-
-- name: Sint Maarten [Dutch part]
- iso2: SX
- iso3: SXM
- phone:
- units:
- - "Sint Maarten [Dutch part]"
-
-- name: Slovakia
- iso2: SK
- iso3: SVK
- phone: 421
- units:
- - "Banskobystricky"
- - "Bratislavsky"
- - "Kosicky"
- - "Nitriansky"
- - "Presovsky"
- - "Trenciansky"
- - "Trnavsky"
- - "Zilinsky"
-
-- name: Slovenia
- iso2: SI
- iso3: SVN
- phone: 386
- units:
- - "Ajdovscina"
- - "Beltinci"
- - "Bled"
- - "Bohinj"
- - "Borovnica"
- - "Bovec"
- - "Brda"
- - "Brezice"
- - "Brezovica"
- - "Cankova-Tisina"
- - "Celje"
- - "Cerklje na Gorenjskem"
- - "Cerknica"
- - "Cerkno"
- - "Crensovci"
- - "Crna na Koroskem"
- - "Crnomelj"
- - "Destrnik-Trnovska Vas"
- - "Divaca"
- - "Dobrepolje"
- - "Dobrova-Horjul-Polhov Gradec"
- - "Dol pri Ljubljani"
- - "Domzale"
- - "Dornava"
- - "Dravograd"
- - "Duplek"
- - "Gorenja Vas-Poljane"
- - "Gorisnica"
- - "Gornja Radgona"
- - "Gornji Grad"
- - "Gornji Petrovci"
- - "Grosuplje"
- - "Hodos Salovci"
- - "Hrastnik"
- - "Hrpelje-Kozina"
- - "Idrija"
- - "Ig"
- - "Ilirska Bistrica"
- - "Ivancna Gorica"
- - "Izola"
- - "Jesenice"
- - "Jursinci"
- - "Kamnik"
- - "Kanal"
- - "Kidricevo"
- - "Kobarid"
- - "Kobilje"
- - "Kocevje"
- - "Komen"
- - "Koper"
- - "Kozje"
- - "Kranj"
- - "Kranjska Gora"
- - "Krsko"
- - "Kungota"
- - "Kuzma"
- - "Lasko"
- - "Lenart"
- - "Lendava"
- - "Litija"
- - "Ljubljana"
- - "Ljubno"
- - "Ljutomer"
- - "Logatec"
- - "Loska Dolina"
- - "Loski Potok"
- - "Luce"
- - "Lukovica"
- - "Majsperk"
- - "Maribor"
- - "Medvode"
- - "Menges"
- - "Metlika"
- - "Mezica"
- - "Miren-Kostanjevica"
- - "Mislinja"
- - "Moravce"
- - "Moravske Toplice"
- - "Mozirje"
- - "Murska Sobota"
- - "Muta"
- - "Naklo"
- - "Nazarje"
- - "Nova Gorica"
- - "Novo Mesto"
- - "Odranci"
- - "Ormoz"
- - "Osilnica"
- - "Pesnica"
- - "Piran"
- - "Pivka"
- - "Podcetrtek"
- - "Podvelka-Ribnica"
- - "Postojna"
- - "Preddvor"
- - "Ptuj"
- - "Puconci"
- - "Race-Fram"
- - "Radece"
- - "Radenci"
- - "Radlje ob Dravi"
- - "Radovljica"
- - "Ravne-Prevalje"
- - "Ribnica"
- - "Rogasevci"
- - "Rogaska Slatina"
- - "Rogatec"
- - "Ruse"
- - "Semic"
- - "Sencur"
- - "Sentilj"
- - "Sentjernej"
- - "Sentjur pri Celju"
- - "Sevnica"
- - "Sezana"
- - "Skocjan"
- - "Skofja Loka"
- - "Skofljica"
- - "Slovenj Gradec"
- - "Slovenska Bistrica"
- - "Slovenske Konjice"
- - "Smarje pri Jelsah"
- - "Smartno ob Paki"
- - "Sostanj"
- - "Starse"
- - "Store"
- - "Sveti Jurij"
- - "Tolmin"
- - "Trbovlje"
- - "Trebnje"
- - "Trzic"
- - "Turnisce"
- - "Velenje"
- - "Velike Lasce"
- - "Videm"
- - "Vipava"
- - "Vitanje"
- - "Vodice"
- - "Vojnik"
- - "Vrhnika"
- - "Vuzenica"
- - "Zagorje ob Savi"
- - "Zalec"
- - "Zavrc"
- - "Zelezniki"
- - "Ziri"
- - "Zrece"
-
-- name: Solomon Islands
- iso2: SB
- iso3: SLB
- phone: 677
- units:
- - "Bellona"
- - "Central"
- - "Choiseul [Lauru]"
- - "Guadalcanal"
- - "Honiara"
- - "Isabel"
- - "Makira"
- - "Malaita"
- - "Rennell"
- - "Temotu"
- - "Western"
-
-- name: Somalia
- iso2: SO
- iso3: SOM
- phone: 252
- units:
- - "Awdal"
- - "Bakool"
- - "Banaadir"
- - "Bari"
- - "Bay"
- - "Galguduud"
- - "Gedo"
- - "Hiiraan"
- - "Jubbada Dhexe"
- - "Jubbada Hoose"
- - "Mudug"
- - "Nugaal"
- - "Sanaag"
- - "Shabeellaha Dhexe"
- - "Shabeellaha Hoose"
- - "Sool"
- - "Togdheer"
- - "Woqooyi Galbeed"
-
-- name: South Africa
- iso2: ZA
- iso3: ZAF
- phone: 27
- units:
- - "Eastern Cape"
- - "Free State"
- - "Gauteng"
- - "KwaZulu-Natal"
- - "Limpopo"
- - "Mpumalanga"
- - "North West"
- - "Northern Cape"
- - "Western Cape"
-
-- name: South Georgia and the South Sandwich Islands
- iso2: GS
- iso3: SGS
- phone:
- units:
- - "Bird Island"
- - "Bristol Island"
- - "Clerke Rocks"
- - "Montagu Island"
- - "Saunders Island"
- - "South Georgia"
- - "Southern Thule"
- - "Traversay Islands"
-
-- name: South Sudan
- iso2: SS
- iso3: SSD
- phone:
- units:
- - "South Sudan"
-
-- name: Spain
- iso2: ES
- iso3: ESP
- phone: 34
- units:
- - "Albacete"
- - "Alicante"
- - "Almería"
- - "Asturias"
- - "Badajoz"
- - "Balearic Islands"
- - "Barcelona"
- - "Biscay"
- - "Burgos"
- - "Cantabria"
- - "Castellón"
- - "Ciudad Real"
- - "Cuenca"
- - "Cáceres"
- - "Cádiz"
- - "Córdoba"
- - "Gerona"
- - "Granada"
- - "Guadalajara"
- - "Guipúzcoa"
- - "Huelva"
- - "Huesca"
- - "Jaén"
- - "La Coruña"
- - "La Rioja"
- - "Las Palmas"
- - "León"
- - "Lugo"
- - "Lérida"
- - "Madrid"
- - "Murcia"
- - "Málaga"
- - "Navarre"
- - "Orense"
- - "Palencia"
- - "Pontevedra"
- - "Salamanca"
- - "Santa Cruz"
- - "Segovia"
- - "Sevilla"
- - "Soria"
- - "Tarragona"
- - "Teruel"
- - "Toledo"
- - "Valencia"
- - "Valladolid"
- - "Zamora"
- - "Zaragoza"
- - "Álava"
- - "Ávila"
-
-- name: Sri Lanka
- iso2: LK
- iso3: LKA
- phone: 94
- units:
- - "Central"
- - "Eastern"
- - "North Central"
- - "North Eastern"
- - "North Western"
- - "Northern"
- - "Sabaragamuwa"
- - "Southern"
- - "Uva"
- - "Western"
-
-- name: Sudan
- iso2: SD
- iso3: SDN
- phone: 249
- units:
- - "A'ali an Nil"
- - "Al Bahr al Ahmar"
- - "Al Buhayrat"
- - "Al Jazirah"
- - "Al Khartum"
- - "Al Qadarif"
- - "Al Wahdah"
- - "An Nil al Abyad"
- - "An Nil al Azraq"
- - "Ash Shamaliyah"
- - "Bahr al Jabal"
- - "Gharb al Istiwa'iyah"
- - "Gharb Bahr al Ghazal"
- - "Gharb Darfur"
- - "Gharb Kurdufan"
- - "Janub Darfur"
- - "Janub Kurdufan"
- - "Junqali"
- - "Kassala"
- - "Nahr an Nil"
- - "Shamal Bahr al Ghazal"
- - "Shamal Darfur"
- - "Shamal Kurdufan"
- - "Sharq al Istiwa'iyah"
- - "Sinnar"
- - "Warab"
-
-- name: Suriname
- iso2: SR
- iso3: SUR
- phone: 597
- units:
- - "Brokopondo"
- - "Commewijne"
- - "Coronie"
- - "Marowijne"
- - "Nickerie"
- - "Para"
- - "Paramaribo"
- - "Saramacca"
- - "Sipaliwini"
- - "Wanica"
-
-- name: Svalbard and Jan Mayen
- iso2: SJ
- iso3: SJM
- phone:
- units:
- - "Barentsoya"
- - "Bjornoya"
- - "Edgeoya"
- - "Hopen"
- - "Kvitoya"
- - "Nordaustandet"
- - "Prins Karls Forland"
- - "Spitsbergen"
-
-- name: Swaziland
- iso2: SZ
- iso3: SWZ
- phone: 268
- units:
- - "Hhohho"
- - "Lubombo"
- - "Manzini"
- - "Shiselweni"
-
-- name: Sweden
- iso2: SE
- iso3: SWE
- phone: 46
- units:
- - "Blekinge"
- - "Dalarnas"
- - "Gavleborgs"
- - "Gotlands"
- - "Hallands"
- - "Jamtlands"
- - "Jonkopings"
- - "Kalmar"
- - "Kronobergs"
- - "Norrbottens"
- - "Orebro"
- - "Ostergotlands"
- - "Skane"
- - "Sodermanlands"
- - "Stockholms"
- - "Uppsala"
- - "Varmlands"
- - "Vasterbottens"
- - "Vasternorrlands"
- - "Vastmanlands"
- - "Vastra Gotalands"
-
-- name: Switzerland
- iso2: CH
- iso3: CHE
- phone: 41
- units:
- - "Aargau"
- - "Ausser-Rhoden"
- - "Basel-Landschaft"
- - "Basel-Stadt"
- - "Bern"
- - "Fribourg"
- - "Geneve"
- - "Glarus"
- - "Graubunden"
- - "Inner-Rhoden"
- - "Jura"
- - "Luzern"
- - "Neuchatel"
- - "Nidwalden"
- - "Obwalden"
- - "Sankt Gallen"
- - "Schaffhausen"
- - "Schwyz"
- - "Solothurn"
- - "Thurgau"
- - "Ticino"
- - "Uri"
- - "Valais"
- - "Vaud"
- - "Zug"
- - "Zurich"
-
-- name: Syrian Arab Republic
- iso2: SY
- iso3: SYR
- phone: 963
- units:
- - "Al Hasakah"
- - "Al Ladhiqiyah"
- - "Al Qunaytirah"
- - "Ar Raqqah"
- - "As Suwayda'"
- - "Dar'a"
- - "Dayr az Zawr"
- - "Dimashq"
- - "Halab"
- - "Hamah"
- - "Hims"
- - "Idlib"
- - "Rif Dimashq"
- - "Tartus"
-
-- name: Taiwan
- iso2: TW
- iso3: TWN
- phone: 886
- units:
- - "Chang-hua"
- - "Chi-lung"
- - "Chia-i"
- - "Chia-i"
- - "Chung-hsing-hsin-ts'un"
- - "Hsin-chu"
- - "Hsin-chu"
- - "Hua-lien"
- - "I-lan"
- - "Kao-hsiung"
- - "Kao-hsiung"
- - "Miao-li"
- - "Nan-t'ou"
- - "P'eng-hu"
- - "P'ing-tung"
- - "T'ai-chung"
- - "T'ai-chung"
- - "T'ai-nan"
- - "T'ai-nan"
- - "T'ai-pei"
- - "T'ai-pei"
- - "T'ai-tung"
- - "T'ao-yuan"
- - "Yun-lin"
-
-- name: Tajikistan
- iso2: TJ
- iso3: TJK
- phone: 992
- units:
- - "Viloyati Khatlon"
- - "Viloyati Leninobod"
- - "Viloyati Mukhtori Kuhistoni Badakhshon"
-
-- name: Tanzania United Republic of
- iso2: TZ
- iso3: TZA
- phone: 255
- units:
- - "Arusha"
- - "Dar es Salaam"
- - "Dodoma"
- - "Iringa"
- - "Kagera"
- - "Kigoma"
- - "Kilimanjaro"
- - "Lindi"
- - "Mara"
- - "Mbeya"
- - "Morogoro"
- - "Mtwara"
- - "Mwanza"
- - "Pemba North"
- - "Pemba South"
- - "Pwani"
- - "Rukwa"
- - "Ruvuma"
- - "Shinyanga"
- - "Singida"
- - "Tabora"
- - "Tanga"
- - "Zanzibar Central/South"
- - "Zanzibar North"
- - "Zanzibar Urban/West"
-
-- name: Thailand
- iso2: TH
- iso3: THA
- phone: 66
- units:
- - "Amnat Charoen"
- - "Ang Thong"
- - "Buriram"
- - "Chachoengsao"
- - "Chai Nat"
- - "Chaiyaphum"
- - "Chanthaburi"
- - "Chiang Mai"
- - "Chiang Rai"
- - "Chon Buri"
- - "Chumphon"
- - "Kalasin"
- - "Kamphaeng Phet"
- - "Kanchanaburi"
- - "Khon Kaen"
- - "Krabi"
- - "Krung Thep Mahanakhon [Bangkok]"
- - "Lampang"
- - "Lamphun"
- - "Loei"
- - "Lop Buri"
- - "Mae Hong Son"
- - "Maha Sarakham"
- - "Mukdahan"
- - "Nakhon Nayok"
- - "Nakhon Pathom"
- - "Nakhon Phanom"
- - "Nakhon Ratchasima"
- - "Nakhon Sawan"
- - "Nakhon Si Thammarat"
- - "Nan"
- - "Narathiwat"
- - "Nong Bua Lamphu"
- - "Nong Khai"
- - "Nonthaburi"
- - "Pathum Thani"
- - "Pattani"
- - "Phangnga"
- - "Phatthalung"
- - "Phayao"
- - "Phetchabun"
- - "Phetchaburi"
- - "Phichit"
- - "Phitsanulok"
- - "Phra Nakhon Si Ayutthaya"
- - "Phrae"
- - "Phuket"
- - "Prachin Buri"
- - "Prachuap Khiri Khan"
- - "Ranong"
- - "Ratchaburi"
- - "Rayong"
- - "Roi Et"
- - "Sa Kaeo"
- - "Sakon Nakhon"
- - "Samut Prakan"
- - "Samut Sakhon"
- - "Samut Songkhram"
- - "Sara Buri"
- - "Satun"
- - "Sing Buri"
- - "Sisaket"
- - "Songkhla"
- - "Sukhothai"
- - "Suphan Buri"
- - "Surat Thani"
- - "Surin"
- - "Tak"
- - "Trang"
- - "Trat"
- - "Ubon Ratchathani"
- - "Udon Thani"
- - "Uthai Thani"
- - "Uttaradit"
- - "Yala"
- - "Yasothon"
-
-- name: Timor-Leste
- iso2: TL
- iso3: TLS
- phone: 670
- units:
- - "Timor-Leste"
-
-- name: Togo
- iso2: TG
- iso3: TGO
- phone: 228
- units:
- - "De La Kara"
- - "Des Plateaux"
- - "Des Savanes"
- - "Du Centre"
- - "Maritime"
-
-- name: Tokelau
- iso2: TK
- iso3: TKL
- phone: 690
- units:
- - "Atafu"
- - "Fakaofo"
- - "Nukunonu"
-
-- name: Tonga
- iso2: TO
- iso3: TON
- phone: 676
- units:
- - "Ha'apai"
- - "Tongatapu"
- - "Vava'u"
-
-- name: Trinidad and Tobago
- iso2: TT
- iso3: TTO
- phone: 1 868
- units:
- - "Arima"
- - "Caroni"
- - "Mayaro"
- - "Nariva"
- - "Port-of-Spain"
- - "Saint Andrew"
- - "Saint David"
- - "Saint George"
- - "Saint Patrick"
- - "San Fernando"
- - "Victoria"
- - "Tobago"
-
-- name: Tunisia
- iso2: TN
- iso3: TUN
- phone: 216
- units:
- - "Ariana"
- - "Beja"
- - "Ben Arous"
- - "Bizerte"
- - "El Kef"
- - "Gabes"
- - "Gafsa"
- - "Jendouba"
- - "Kairouan"
- - "Kasserine"
- - "Kebili"
- - "Mahdia"
- - "Medenine"
- - "Monastir"
- - "Nabeul"
- - "Sfax"
- - "Sidi Bou Zid"
- - "Siliana"
- - "Sousse"
- - "Tataouine"
- - "Tozeur"
- - "Tunis"
- - "Zaghouan"
-
-- name: Turkey
- iso2: TR
- iso3: TUR
- phone: 90
- units:
- - "Adana"
- - "Adiyaman"
- - "Afyon"
- - "Agri"
- - "Aksaray"
- - "Amasya"
- - "Ankara"
- - "Antalya"
- - "Ardahan"
- - "Artvin"
- - "Aydin"
- - "Balikesir"
- - "Bartin"
- - "Batman"
- - "Bayburt"
- - "Bilecik"
- - "Bingol"
- - "Bitlis"
- - "Bolu"
- - "Burdur"
- - "Bursa"
- - "Canakkale"
- - "Cankiri"
- - "Corum"
- - "Denizli"
- - "Diyarbakir"
- - "Duzce"
- - "Edirne"
- - "Elazig"
- - "Erzincan"
- - "Erzurum"
- - "Eskisehir"
- - "Gaziantep"
- - "Giresun"
- - "Gumushane"
- - "Hakkari"
- - "Hatay"
- - "Icel"
- - "Igdir"
- - "Isparta"
- - "Istanbul"
- - "Izmir"
- - "Kahramanmaras"
- - "Karabuk"
- - "Karaman"
- - "Kars"
- - "Kastamonu"
- - "Kayseri"
- - "Kilis"
- - "Kirikkale"
- - "Kirklareli"
- - "Kirsehir"
- - "Kocaeli"
- - "Konya"
- - "Kutahya"
- - "Malatya"
- - "Manisa"
- - "Mardin"
- - "Mugla"
- - "Mus"
- - "Nevsehir"
- - "Nigde"
- - "Ordu"
- - "Osmaniye"
- - "Rize"
- - "Sakarya"
- - "Samsun"
- - "Sanliurfa"
- - "Siirt"
- - "Sinop"
- - "Sirnak"
- - "Sivas"
- - "Tekirdag"
- - "Tokat"
- - "Trabzon"
- - "Tunceli"
- - "Usak"
- - "Van"
- - "Yalova"
- - "Yozgat"
- - "Zonguldak"
-
-- name: Turkmenistan
- iso2: TM
- iso3: TKM
- phone: 993
- units:
- - "Ahal Welayaty"
- - "Balkan Welayaty"
- - "Dashhowuz Welayaty"
- - "Lebap Welayaty"
- - "Mary Welayaty"
-
-- name: Turks and Caicos Islands
- iso2: TC
- iso3: TCA
- phone: 1 649
- units:
- - "Turks and Caicos Islands"
-
-- name: Tuvalu
- iso2: TV
- iso3: TUV
- phone: 688
- units:
- - "Tuvalu"
-
-- name: Uganda
- iso2: UG
- iso3: UGA
- phone: 256
- units:
- - "Adjumani"
- - "Apac"
- - "Arua"
- - "Bugiri"
- - "Bundibugyo"
- - "Bushenyi"
- - "Busia"
- - "Gulu"
- - "Hoima"
- - "Iganga"
- - "Jinja"
- - "Kabale"
- - "Kabarole"
- - "Kalangala"
- - "Kampala"
- - "Kamuli"
- - "Kapchorwa"
- - "Kasese"
- - "Katakwi"
- - "Kibale"
- - "Kiboga"
- - "Kisoro"
- - "Kitgum"
- - "Kotido"
- - "Kumi"
- - "Lira"
- - "Luwero"
- - "Masaka"
- - "Masindi"
- - "Mbale"
- - "Mbarara"
- - "Moroto"
- - "Moyo"
- - "Mpigi"
- - "Mubende"
- - "Mukono"
- - "Nakasongola"
- - "Nebbi"
- - "Ntungamo"
- - "Pallisa"
- - "Rakai"
- - "Rukungiri"
- - "Sembabule"
- - "Soroti"
- - "Tororo"
-
-- name: Ukraine
- iso2: UA
- iso3: UKR
- phone: 380
- units:
- - "Avtonomna Respublika Krym [Simferopol']"
- - "Cherkas'ka [Cherkasy]"
- - "Chernihivs'ka [Chernihiv]"
- - "Chernivets'ka [Chernivtsi]"
- - "Dnipropetrovs'ka [Dnipropetrovs'k]"
- - "Donets'ka [Donets'k]"
- - "Ivano-Frankivs'ka [Ivano-Frankivs'k]"
- - "Kharkivs'ka [Kharkiv]"
- - "Khersons'ka [Kherson]"
- - "Khmel'nyts'ka [Khmel'nyts'kyy]"
- - "Kirovohrads'ka [Kirovohrad]"
- - "Kyyiv"
- - "Kyyivs'ka [Kiev]"
- - "L'vivs'ka [L'viv]"
- - "Luhans'ka [Luhans'k]"
- - "Mykolayivs'ka [Mykolayiv]"
- - "Odes'ka [Odesa]"
- - "Poltavs'ka [Poltava]"
- - "Rivnens'ka [Rivne]"
- - "Sevastopol'"
- - "Sums'ka [Sumy]"
- - "Ternopil's'ka [Ternopil']"
- - "Vinnyts'ka [Vinnytsya]"
- - "Volyns'ka [Luts'k]"
- - "Zakarpats'ka [Uzhhorod]"
- - "Zaporiz'ka [Zaporizhzhya]"
- - "Zhytomyrs'ka [Zhytomyr]"
-
-- name: United Arab Emirates
- iso2: AE
- iso3: ARE
- phone: 971
- units:
- - "'Ajman"
- - "Abu Zaby [Abu Dhabi]"
- - "Al Fujayrah"
- - "Ash Shariqah [Sharjah]"
- - "Dubayy [Dubai]"
- - "Ra's al Khaymah"
- - "Umm al Qaywayn"
-
-- name: United Kingdom
- iso2: GB
- iso3: GBR
- phone: 44
- units:
- - "Aberdeenshire"
- - "Alderney"
- - "Angus"
- - "Antrim"
- - "Argyll"
- - "Armagh"
- - "Avon"
- - "Ayrshire"
- - "Banffshire"
- - "Bedfordshire"
- - "Berkshire"
- - "Berwickshire"
- - "Blaenau Gwent"
- - "Borders"
- - "Bridgend"
- - "Buckinghamshire"
- - "Bute"
- - "Caerphilly"
- - "Caithness"
- - "Cambridgeshire"
- - "Cardiff"
- - "Carmarthenshire"
- - "Central"
- - "Ceredigion"
- - "Cheshire"
- - "Clackmannanshire"
- - "Cleveland"
- - "Clwyd"
- - "Co. Antrim"
- - "Co. Armagh"
- - "Co. Derry"
- - "Co. Down"
- - "Co. Fermanagh"
- - "Co. Tyrone"
- - "Conwy"
- - "Cornwall"
- - "Cumberland"
- - "Cumbria"
- - "Denbighshire"
- - "Derbyshire"
- - "Derry"
- - "Devon"
- - "Dorset"
- - "Down"
- - "Dumfries & Galloway"
- - "Dumfriesshire"
- - "Dunbartonshire"
- - "Durham"
- - "Dyfed"
- - "East Lothian"
- - "East Sussex"
- - "Essex"
- - "Fermanagh"
- - "Fife"
- - "Flintshire"
- - "Gloucestershire"
- - "Grampian"
- - "Greater London"
- - "Greater Manchester"
- - "Guernsey"
- - "Gwent"
- - "Gwynedd"
- - "Hampshire"
- - "Hereford & Worcester"
- - "Herefordshire"
- - "Hertfordshire"
- - "Highland"
- - "Humberside"
- - "Huntingdonshire"
- - "Inverness"
- - "Isle Of Man"
- - "Isle of Anglesey"
- - "Isle of Wight"
- - "Jersey"
- - "Kent"
- - "Kincardineshire"
- - "Kinross-shire"
- - "Kirkcudbrightshire"
- - "Lanarkshire"
- - "Lancashire"
- - "Leicestershire"
- - "Lincolnshire"
- - "Lothian"
- - "Merseyside"
- - "Merthyr Tydfil"
- - "Mid Glamorgan"
- - "Middlesex"
- - "Midlothian"
- - "Monmouthshire"
- - "Moray"
- - "Nairnshire"
- - "Neath Port Talbot"
- - "Newport"
- - "Norfolk"
- - "North Yorkshire"
- - "Northamptonshire"
- - "Northumberland"
- - "Nottinghamshire"
- - "Orkney"
- - "Oxfordshire"
- - "Peebleshire"
- - "Pembrokeshire"
- - "Perthshire"
- - "Powys"
- - "Renfrewshire"
- - "Rhondda Cynon Taff"
- - "Ross & Cromarty"
- - "Roxburghshire"
- - "Rutland"
- - "Scotland"
- - "Selkirkshire"
- - "Shetland"
- - "Shropshire"
- - "Somerset"
- - "South Glamorgan"
- - "South Yorkshire"
- - "Staffordshire"
- - "Stirlingshire"
- - "Strathclyde"
- - "Suffolk"
- - "Surrey"
- - "Sussex"
- - "Sutherland"
- - "Swansea"
- - "Tayside"
- - "Torfaen"
- - "Tyne & Wear"
- - "Tyne and Wear"
- - "Tyrone"
- - "Vale of Glamorgan"
- - "Wales"
- - "Warwickshire"
- - "West Glamorgan"
- - "West Lothian"
- - "West Midlands"
- - "West Riding"
- - "West Sussex"
- - "West Yorkshire"
- - "Western Isles"
- - "Westmoorland"
- - "Westmorland"
- - "Wigtownshire"
- - "Wiltshire"
- - "Worcestershire"
- - "Wrexham"
- - "Yorkshire"
-
-- name: United States
- iso2: US
- iso3: USA
- phone: 1
- units:
- - "Alaska"
- - "Alabama"
- - "Arkansas"
- - "Arizona"
- - "California"
- - "Colorado"
- - "Connecticut"
- - "Washington, D.C."
- - "Delaware"
- - "Florida"
- - "Georgia"
- - "Hawaii"
- - "Iowa"
- - "Idaho"
- - "Illinois"
- - "Indiana"
- - "Kansas"
- - "Kentucky"
- - "Louisiana"
- - "Massachusetts"
- - "Maryland"
- - "Maine"
- - "Michigan"
- - "Minnesota"
- - "Missouri"
- - "Mississippi"
- - "Montana"
- - "North Carolina"
- - "North Dakota"
- - "Nebraska"
- - "New Hampshire"
- - "New Jersey"
- - "New Mexico"
- - "Nevada"
- - "New York"
- - "Ohio"
- - "Oklahoma"
- - "Oregon"
- - "Pennsylvania"
- - "Rhode Island"
- - "South Carolina"
- - "South Dakota"
- - "Tennessee"
- - "Texas"
- - "Utah"
- - "Virginia"
- - "Vermont"
- - "Washington"
- - "Wisconsin"
- - "West Virginia"
- - "Wyoming"
-
-- name: United States Minor Outlying Islands
- iso2: UM
- iso3: UMI
- phone:
- units: []
-
-- name: Uruguay
- iso2: UY
- iso3: URY
- phone: 598
- units:
- - "Artigas"
- - "Canelones"
- - "Cerro Largo"
- - "Colonia"
- - "Durazno"
- - "Flores"
- - "Florida"
- - "Lavalleja"
- - "Maldonado"
- - "Montevideo"
- - "Paysandu"
- - "Rio Negro"
- - "Rivera"
- - "Rocha"
- - "Salto"
- - "San Jose"
- - "Soriano"
- - "Tacuarembo"
- - "Treinta y Tres"
-
-- name: Uzbekistan
- iso2: UZ
- iso3: UZB
- phone: 998
- units:
- - "Andijon Wiloyati"
- - "Bukhoro Wiloyati"
- - "Farghona Wiloyati"
- - "Jizzakh Wiloyati"
- - "Khorazm Wiloyati [Urganch]"
- - "Namangan Wiloyati"
- - "Nawoiy Wiloyati"
- - "Qashqadaryo Wiloyati [Qarshi]"
- - "Qoraqalpoghiston [Nukus]"
- - "Samarqand Wiloyati"
- - "Sirdaryo Wiloyati [Guliston]"
- - "Surkhondaryo Wiloyati [Termiz]"
- - "Toshkent Shahri"
- - "Toshkent Wiloyati"
-
-- name: Vanuatu
- iso2: VU
- iso3: VUT
- phone: 678
- units:
- - "Malampa"
- - "Penama"
- - "Sanma"
- - "Shefa"
- - "Tafea"
- - "Torba"
-
-- name: Venezuela, Bolivarian Republic of
- iso2: VE
- iso3: VEN
- phone: 58
- units:
- - "Amazonas"
- - "Anzoategui"
- - "Apure"
- - "Aragua"
- - "Barinas"
- - "Bolivar"
- - "Carabobo"
- - "Cojedes"
- - "Delta Amacuro"
- - "Dependencias Federales"
- - "Distrito Federal"
- - "Falcon"
- - "Guarico"
- - "Lara"
- - "Merida"
- - "Miranda"
- - "Monagas"
- - "Nueva Esparta"
- - "Portuguesa"
- - "Sucre"
- - "Tachira"
- - "Trujillo"
- - "Vargas"
- - "Yaracuy"
- - "Zulia"
-
-- name: Viet Nam
- iso2: VN
- iso3: VNM
- phone: 84
- units:
- - "An Giang"
- - "Ba Ria-Vung Tau"
- - "Bac Giang"
- - "Bac Kan"
- - "Bac Lieu"
- - "Bac Ninh"
- - "Ben Tre"
- - "Binh Dinh"
- - "Binh Duong"
- - "Binh Phuoc"
- - "Binh Thuan"
- - "Ca Mau"
- - "Can Tho"
- - "Cao Bang"
- - "Da Nang"
- - "Dac Lak"
- - "Dong Nai"
- - "Dong Thap"
- - "Gia Lai"
- - "Ha Giang"
- - "Ha Nam"
- - "Ha Noi"
- - "Ha Tay"
- - "Ha Tinh"
- - "Hai Duong"
- - "Hai Phong"
- - "Ho Chi Minh"
- - "Hoa Binh"
- - "Hung Yen"
- - "Khanh Hoa"
- - "Kien Giang"
- - "Kon Tum"
- - "Lai Chau"
- - "Lam Dong"
- - "Lang Son"
- - "Lao Cai"
- - "Long An"
- - "Nam Dinh"
- - "Nghe An"
- - "Ninh Binh"
- - "Ninh Thuan"
- - "Phu Tho"
- - "Phu Yen"
- - "Quang Binh"
- - "Quang Nam"
- - "Quang Ngai"
- - "Quang Ninh"
- - "Quang Tri"
- - "Soc Trang"
- - "Son La"
- - "Tay Ninh"
- - "Thai Binh"
- - "Thai Nguyen"
- - "Thanh Hoa"
- - "Thua Thien-Hue"
- - "Tien Giang"
- - "Tra Vinh"
- - "Tuyen Quang"
- - "Vinh Long"
- - "Vinh Phuc"
- - "Yen Bai"
-
-- name: Virgin Islands British
- iso2: VG
- iso3: VGB
- phone: 1 284
- units:
- - "Anegada"
- - "Jost Van Dyke"
- - "Tortola"
- - "Virgin Gorda"
-
-- name: Virgin Islands U.S.
- iso2: VI
- iso3: VIR
- phone: 1 340
- units:
- - "Saint Croix"
- - "Saint John"
- - "Saint Thomas"
-
-- name: Wallis and Futuna
- iso2: WF
- iso3: WLF
- phone: 681
- units:
- - "Alo"
- - "Sigave"
- - "Wallis"
-
-- name: Western Sahara
- iso2: EH
- iso3: ESH
- phone:
- units:
- - "Western Sahara"
-
-- name: Yemen
- iso2: YE
- iso3: YEM
- phone: 967
- units:
- - "'Adan"
- - "'Ataq"
- - "Abyan"
- - "Al Bayda'"
- - "Al Hudaydah"
- - "Al Jawf"
- - "Al Mahrah"
- - "Al Mahwit"
- - "Dhamar"
- - "Hadhramawt"
- - "Hajjah"
- - "Ibb"
- - "Lahij"
- - "Ma'rib"
- - "Sa'dah"
- - "San'a'"
- - "Ta'izz"
-
-- name: Zambia
- iso2: ZM
- iso3: ZMB
- phone: 260
- units:
- - "Central"
- - "Copperbelt"
- - "Eastern"
- - "Luapula"
- - "Lusaka"
- - "North-Western"
- - "Northern"
- - "Southern"
- - "Western"
-
-- name: Zimbabwe
- iso2: ZW
- iso3: ZWE
- phone: 263
- units:
- - "Bulawayo"
- - "Harare"
- - "Manicaland"
- - "Mashonaland Central"
- - "Mashonaland East"
- - "Mashonaland West"
- - "Masvingo"
- - "Matabeleland North"
- - "Matabeleland South"
- - "Midlands"
diff --git a/src/Oro/Bundle/AddressBundle/DataFixtures/data/countries.yml b/src/Oro/Bundle/AddressBundle/DataFixtures/data/countries.yml
new file mode 100644
index 00000000000..5d5bff9b008
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/DataFixtures/data/countries.yml
@@ -0,0 +1,12630 @@
+AD:
+ iso2Code: AD
+ iso3Code: AND
+ regions:
+ AD.06:
+ combinedCode: AD.06
+ code: '06'
+ AD.05:
+ combinedCode: AD.05
+ code: '05'
+ AD.04:
+ combinedCode: AD.04
+ code: '04'
+ AD.03:
+ combinedCode: AD.03
+ code: '03'
+ AD.02:
+ combinedCode: AD.02
+ code: '02'
+ AD.07:
+ combinedCode: AD.07
+ code: '07'
+ AD.08:
+ combinedCode: AD.08
+ code: '08'
+AE:
+ iso2Code: AE
+ iso3Code: ARE
+ regions:
+ AE.07:
+ combinedCode: AE.07
+ code: '07'
+ AE.05:
+ combinedCode: AE.05
+ code: '05'
+ AE.03:
+ combinedCode: AE.03
+ code: '03'
+ AE.06:
+ combinedCode: AE.06
+ code: '06'
+ AE.04:
+ combinedCode: AE.04
+ code: '04'
+ AE.02:
+ combinedCode: AE.02
+ code: '02'
+ AE.01:
+ combinedCode: AE.01
+ code: '01'
+AF:
+ iso2Code: AF
+ iso3Code: AFG
+ regions:
+ AF.28:
+ combinedCode: AF.28
+ code: '28'
+ AF.27:
+ combinedCode: AF.27
+ code: '27'
+ AF.26:
+ combinedCode: AF.26
+ code: '26'
+ AF.33:
+ combinedCode: AF.33
+ code: '33'
+ AF.32:
+ combinedCode: AF.32
+ code: '32'
+ AF.40:
+ combinedCode: AF.40
+ code: '40'
+ AF.29:
+ combinedCode: AF.29
+ code: '29'
+ AF.36:
+ combinedCode: AF.36
+ code: '36'
+ AF.39:
+ combinedCode: AF.39
+ code: '39'
+ AF.19:
+ combinedCode: AF.19
+ code: '19'
+ AF.18:
+ combinedCode: AF.18
+ code: '18'
+ AF.17:
+ combinedCode: AF.17
+ code: '17'
+ AF.35:
+ combinedCode: AF.35
+ code: '35'
+ AF.24:
+ combinedCode: AF.24
+ code: '24'
+ AF.34:
+ combinedCode: AF.34
+ code: '34'
+ AF.14:
+ combinedCode: AF.14
+ code: '14'
+ AF.23:
+ combinedCode: AF.23
+ code: '23'
+ AF.13:
+ combinedCode: AF.13
+ code: '13'
+ AF.31:
+ combinedCode: AF.31
+ code: '31'
+ AF.11:
+ combinedCode: AF.11
+ code: '11'
+ AF.10:
+ combinedCode: AF.10
+ code: '10'
+ AF.09:
+ combinedCode: AF.09
+ code: '09'
+ AF.08:
+ combinedCode: AF.08
+ code: '08'
+ AF.07:
+ combinedCode: AF.07
+ code: '07'
+ AF.06:
+ combinedCode: AF.06
+ code: '06'
+ AF.05:
+ combinedCode: AF.05
+ code: '05'
+ AF.30:
+ combinedCode: AF.30
+ code: '30'
+ AF.03:
+ combinedCode: AF.03
+ code: '03'
+ AF.02:
+ combinedCode: AF.02
+ code: '02'
+ AF.01:
+ combinedCode: AF.01
+ code: '01'
+ AF.37:
+ combinedCode: AF.37
+ code: '37'
+ AF.38:
+ combinedCode: AF.38
+ code: '38'
+ AF.41:
+ combinedCode: AF.41
+ code: '41'
+ AF.42:
+ combinedCode: AF.42
+ code: '42'
+AG:
+ iso2Code: AG
+ iso3Code: ATG
+ regions:
+ AG.08:
+ combinedCode: AG.08
+ code: '08'
+ AG.07:
+ combinedCode: AG.07
+ code: '07'
+ AG.06:
+ combinedCode: AG.06
+ code: '06'
+ AG.05:
+ combinedCode: AG.05
+ code: '05'
+ AG.04:
+ combinedCode: AG.04
+ code: '04'
+ AG.03:
+ combinedCode: AG.03
+ code: '03'
+ AG.09:
+ combinedCode: AG.09
+ code: '09'
+ AG.01:
+ combinedCode: AG.01
+ code: '01'
+AI:
+ iso2Code: AI
+ iso3Code: AIA
+ regions: { }
+AL:
+ iso2Code: AL
+ iso3Code: ALB
+ regions:
+ AL.40:
+ combinedCode: AL.40
+ code: '40'
+ AL.41:
+ combinedCode: AL.41
+ code: '41'
+ AL.43:
+ combinedCode: AL.43
+ code: '43'
+ AL.45:
+ combinedCode: AL.45
+ code: '45'
+ AL.46:
+ combinedCode: AL.46
+ code: '46'
+ AL.47:
+ combinedCode: AL.47
+ code: '47'
+ AL.42:
+ combinedCode: AL.42
+ code: '42'
+ AL.44:
+ combinedCode: AL.44
+ code: '44'
+ AL.48:
+ combinedCode: AL.48
+ code: '48'
+ AL.49:
+ combinedCode: AL.49
+ code: '49'
+ AL.50:
+ combinedCode: AL.50
+ code: '50'
+ AL.51:
+ combinedCode: AL.51
+ code: '51'
+AM:
+ iso2Code: AM
+ iso3Code: ARM
+ regions:
+ AM.02:
+ combinedCode: AM.02
+ code: '02'
+ AM.08:
+ combinedCode: AM.08
+ code: '08'
+ AM.10:
+ combinedCode: AM.10
+ code: '10'
+ AM.11:
+ combinedCode: AM.11
+ code: '11'
+ AM.01:
+ combinedCode: AM.01
+ code: '01'
+ AM.03:
+ combinedCode: AM.03
+ code: '03'
+ AM.04:
+ combinedCode: AM.04
+ code: '04'
+ AM.05:
+ combinedCode: AM.05
+ code: '05'
+ AM.06:
+ combinedCode: AM.06
+ code: '06'
+ AM.07:
+ combinedCode: AM.07
+ code: '07'
+ AM.09:
+ combinedCode: AM.09
+ code: '09'
+AO:
+ iso2Code: AO
+ iso3Code: AGO
+ regions:
+ AO.18:
+ combinedCode: AO.18
+ code: '18'
+ AO.17:
+ combinedCode: AO.17
+ code: '17'
+ AO.14:
+ combinedCode: AO.14
+ code: '14'
+ AO.04:
+ combinedCode: AO.04
+ code: '04'
+ AO.16:
+ combinedCode: AO.16
+ code: '16'
+ AO.15:
+ combinedCode: AO.15
+ code: '15'
+ AO.12:
+ combinedCode: AO.12
+ code: '12'
+ AO.20:
+ combinedCode: AO.20
+ code: '20'
+ AO.05:
+ combinedCode: AO.05
+ code: '05'
+ AO.03:
+ combinedCode: AO.03
+ code: '03'
+ AO.19:
+ combinedCode: AO.19
+ code: '19'
+ AO.13:
+ combinedCode: AO.13
+ code: '13'
+ AO.09:
+ combinedCode: AO.09
+ code: '09'
+ AO.08:
+ combinedCode: AO.08
+ code: '08'
+ AO.07:
+ combinedCode: AO.07
+ code: '07'
+ AO.06:
+ combinedCode: AO.06
+ code: '06'
+ AO.02:
+ combinedCode: AO.02
+ code: '02'
+ AO.01:
+ combinedCode: AO.01
+ code: '01'
+AQ:
+ iso2Code: AQ
+ iso3Code: ATA
+ regions: { }
+AR:
+ iso2Code: AR
+ iso3Code: ARG
+ regions:
+ AR.14:
+ combinedCode: AR.14
+ code: '14'
+ AR.09:
+ combinedCode: AR.09
+ code: '09'
+ AR.07:
+ combinedCode: AR.07
+ code: '07'
+ AR.08:
+ combinedCode: AR.08
+ code: '08'
+ AR.06:
+ combinedCode: AR.06
+ code: '06'
+ AR.01:
+ combinedCode: AR.01
+ code: '01'
+ AR.24:
+ combinedCode: AR.24
+ code: '24'
+ AR.23:
+ combinedCode: AR.23
+ code: '23'
+ AR.22:
+ combinedCode: AR.22
+ code: '22'
+ AR.21:
+ combinedCode: AR.21
+ code: '21'
+ AR.20:
+ combinedCode: AR.20
+ code: '20'
+ AR.19:
+ combinedCode: AR.19
+ code: '19'
+ AR.18:
+ combinedCode: AR.18
+ code: '18'
+ AR.17:
+ combinedCode: AR.17
+ code: '17'
+ AR.16:
+ combinedCode: AR.16
+ code: '16'
+ AR.15:
+ combinedCode: AR.15
+ code: '15'
+ AR.13:
+ combinedCode: AR.13
+ code: '13'
+ AR.12:
+ combinedCode: AR.12
+ code: '12'
+ AR.11:
+ combinedCode: AR.11
+ code: '11'
+ AR.10:
+ combinedCode: AR.10
+ code: '10'
+ AR.05:
+ combinedCode: AR.05
+ code: '05'
+ AR.04:
+ combinedCode: AR.04
+ code: '04'
+ AR.03:
+ combinedCode: AR.03
+ code: '03'
+ AR.02:
+ combinedCode: AR.02
+ code: '02'
+AS:
+ iso2Code: AS
+ iso3Code: ASM
+ regions:
+ AS.050:
+ combinedCode: AS.050
+ code: '050'
+ AS.040:
+ combinedCode: AS.040
+ code: '040'
+ AS.010:
+ combinedCode: AS.010
+ code: '010'
+ AS.020:
+ combinedCode: AS.020
+ code: '020'
+ AS.030:
+ combinedCode: AS.030
+ code: '030'
+AT:
+ iso2Code: AT
+ iso3Code: AUT
+ regions:
+ AT.09:
+ combinedCode: AT.09
+ code: '09'
+ AT.08:
+ combinedCode: AT.08
+ code: '08'
+ AT.07:
+ combinedCode: AT.07
+ code: '07'
+ AT.06:
+ combinedCode: AT.06
+ code: '06'
+ AT.05:
+ combinedCode: AT.05
+ code: '05'
+ AT.04:
+ combinedCode: AT.04
+ code: '04'
+ AT.03:
+ combinedCode: AT.03
+ code: '03'
+ AT.02:
+ combinedCode: AT.02
+ code: '02'
+ AT.01:
+ combinedCode: AT.01
+ code: '01'
+AU:
+ iso2Code: AU
+ iso3Code: AUS
+ regions:
+ AU.08:
+ combinedCode: AU.08
+ code: '08'
+ AU.05:
+ combinedCode: AU.05
+ code: '05'
+ AU.03:
+ combinedCode: AU.03
+ code: '03'
+ AU.07:
+ combinedCode: AU.07
+ code: '07'
+ AU.06:
+ combinedCode: AU.06
+ code: '06'
+ AU.04:
+ combinedCode: AU.04
+ code: '04'
+ AU.02:
+ combinedCode: AU.02
+ code: '02'
+ AU.01:
+ combinedCode: AU.01
+ code: '01'
+AW:
+ iso2Code: AW
+ iso3Code: ABW
+ regions: { }
+AX:
+ iso2Code: AX
+ iso3Code: ALA
+ regions:
+ AX.941:
+ combinedCode: AX.941
+ code: '941'
+ AX.771:
+ combinedCode: AX.771
+ code: '771'
+ AX.766:
+ combinedCode: AX.766
+ code: '766'
+ AX.736:
+ combinedCode: AX.736
+ code: '736'
+ AX.438:
+ combinedCode: AX.438
+ code: '438'
+ AX.417:
+ combinedCode: AX.417
+ code: '417'
+ AX.295:
+ combinedCode: AX.295
+ code: '295'
+ AX.318:
+ combinedCode: AX.318
+ code: '318'
+ AX.062:
+ combinedCode: AX.062
+ code: '062'
+ AX.035:
+ combinedCode: AX.035
+ code: '035'
+ AX.478:
+ combinedCode: AX.478
+ code: '478'
+ AX.170:
+ combinedCode: AX.170
+ code: '170'
+ AX.076:
+ combinedCode: AX.076
+ code: '076'
+ AX.065:
+ combinedCode: AX.065
+ code: '065'
+ AX.060:
+ combinedCode: AX.060
+ code: '060'
+ AX.043:
+ combinedCode: AX.043
+ code: '043'
+AZ:
+ iso2Code: AZ
+ iso3Code: AZE
+ regions:
+ AZ.12:
+ combinedCode: AZ.12
+ code: '12'
+ AZ.69:
+ combinedCode: AZ.69
+ code: '69'
+ AZ.66:
+ combinedCode: AZ.66
+ code: '66'
+ AZ.55:
+ combinedCode: AZ.55
+ code: '55'
+ AZ.49:
+ combinedCode: AZ.49
+ code: '49'
+ AZ.46:
+ combinedCode: AZ.46
+ code: '46'
+ AZ.45:
+ combinedCode: AZ.45
+ code: '45'
+ AZ.13:
+ combinedCode: AZ.13
+ code: '13'
+ AZ.36:
+ combinedCode: AZ.36
+ code: '36'
+ AZ.35:
+ combinedCode: AZ.35
+ code: '35'
+ AZ.32:
+ combinedCode: AZ.32
+ code: '32'
+ AZ.31:
+ combinedCode: AZ.31
+ code: '31'
+ AZ.29:
+ combinedCode: AZ.29
+ code: '29'
+ AZ.28:
+ combinedCode: AZ.28
+ code: '28'
+ AZ.43:
+ combinedCode: AZ.43
+ code: '43'
+ AZ.24:
+ combinedCode: AZ.24
+ code: '24'
+ AZ.18:
+ combinedCode: AZ.18
+ code: '18'
+ AZ.14:
+ combinedCode: AZ.14
+ code: '14'
+ AZ.15:
+ combinedCode: AZ.15
+ code: '15'
+ AZ.08:
+ combinedCode: AZ.08
+ code: '08'
+ AZ.64:
+ combinedCode: AZ.64
+ code: '64'
+ AZ.02:
+ combinedCode: AZ.02
+ code: '02'
+ AZ.03:
+ combinedCode: AZ.03
+ code: '03'
+ AZ.07:
+ combinedCode: AZ.07
+ code: '07'
+ AZ.30:
+ combinedCode: AZ.30
+ code: '30'
+ AZ.56:
+ combinedCode: AZ.56
+ code: '56'
+ AZ.57:
+ combinedCode: AZ.57
+ code: '57'
+ AZ.61:
+ combinedCode: AZ.61
+ code: '61'
+ AZ.65:
+ combinedCode: AZ.65
+ code: '65'
+ AZ.71:
+ combinedCode: AZ.71
+ code: '71'
+ AZ.70:
+ combinedCode: AZ.70
+ code: '70'
+ AZ.67:
+ combinedCode: AZ.67
+ code: '67'
+ AZ.37:
+ combinedCode: AZ.37
+ code: '37'
+ AZ.59:
+ combinedCode: AZ.59
+ code: '59'
+ AZ.58:
+ combinedCode: AZ.58
+ code: '58'
+ AZ.50:
+ combinedCode: AZ.50
+ code: '50'
+ AZ.47:
+ combinedCode: AZ.47
+ code: '47'
+ AZ.51:
+ combinedCode: AZ.51
+ code: '51'
+ AZ.27:
+ combinedCode: AZ.27
+ code: '27'
+ AZ.38:
+ combinedCode: AZ.38
+ code: '38'
+ AZ.44:
+ combinedCode: AZ.44
+ code: '44'
+ AZ.42:
+ combinedCode: AZ.42
+ code: '42'
+ AZ.62:
+ combinedCode: AZ.62
+ code: '62'
+ AZ.60:
+ combinedCode: AZ.60
+ code: '60'
+ AZ.26:
+ combinedCode: AZ.26
+ code: '26'
+ AZ.40:
+ combinedCode: AZ.40
+ code: '40'
+ AZ.21:
+ combinedCode: AZ.21
+ code: '21'
+ AZ.39:
+ combinedCode: AZ.39
+ code: '39'
+ AZ.25:
+ combinedCode: AZ.25
+ code: '25'
+ AZ.22:
+ combinedCode: AZ.22
+ code: '22'
+ AZ.17:
+ combinedCode: AZ.17
+ code: '17'
+ AZ.16:
+ combinedCode: AZ.16
+ code: '16'
+ AZ.10:
+ combinedCode: AZ.10
+ code: '10'
+ AZ.11:
+ combinedCode: AZ.11
+ code: '11'
+ AZ.09:
+ combinedCode: AZ.09
+ code: '09'
+ AZ.01:
+ combinedCode: AZ.01
+ code: '01'
+ AZ.06:
+ combinedCode: AZ.06
+ code: '06'
+ AZ.04:
+ combinedCode: AZ.04
+ code: '04'
+ AZ.19:
+ combinedCode: AZ.19
+ code: '19'
+ AZ.05:
+ combinedCode: AZ.05
+ code: '05'
+ AZ.20:
+ combinedCode: AZ.20
+ code: '20'
+ AZ.33:
+ combinedCode: AZ.33
+ code: '33'
+ AZ.34:
+ combinedCode: AZ.34
+ code: '34'
+ AZ.41:
+ combinedCode: AZ.41
+ code: '41'
+ AZ.52:
+ combinedCode: AZ.52
+ code: '52'
+ AZ.48:
+ combinedCode: AZ.48
+ code: '48'
+ AZ.53:
+ combinedCode: AZ.53
+ code: '53'
+ AZ.54:
+ combinedCode: AZ.54
+ code: '54'
+ AZ.63:
+ combinedCode: AZ.63
+ code: '63'
+ AZ.68:
+ combinedCode: AZ.68
+ code: '68'
+ AZ.23:
+ combinedCode: AZ.23
+ code: '23'
+ AZ.75:
+ combinedCode: AZ.75
+ code: '75'
+BA:
+ iso2Code: BA
+ iso3Code: BIH
+ regions:
+ BA.01:
+ combinedCode: BA.01
+ code: '01'
+ BA.02:
+ combinedCode: BA.02
+ code: '02'
+ BA.BRC:
+ combinedCode: BA.BRC
+ code: BRC
+BB:
+ iso2Code: BB
+ iso3Code: BRB
+ regions:
+ BB.11:
+ combinedCode: BB.11
+ code: '11'
+ BB.10:
+ combinedCode: BB.10
+ code: '10'
+ BB.09:
+ combinedCode: BB.09
+ code: '09'
+ BB.08:
+ combinedCode: BB.08
+ code: '08'
+ BB.07:
+ combinedCode: BB.07
+ code: '07'
+ BB.06:
+ combinedCode: BB.06
+ code: '06'
+ BB.05:
+ combinedCode: BB.05
+ code: '05'
+ BB.04:
+ combinedCode: BB.04
+ code: '04'
+ BB.03:
+ combinedCode: BB.03
+ code: '03'
+ BB.02:
+ combinedCode: BB.02
+ code: '02'
+ BB.01:
+ combinedCode: BB.01
+ code: '01'
+BD:
+ iso2Code: BD
+ iso3Code: BGD
+ regions:
+ BD.83:
+ combinedCode: BD.83
+ code: '83'
+ BD.81:
+ combinedCode: BD.81
+ code: '81'
+ BD.84:
+ combinedCode: BD.84
+ code: '84'
+ BD.82:
+ combinedCode: BD.82
+ code: '82'
+ BD.85:
+ combinedCode: BD.85
+ code: '85'
+ BD.86:
+ combinedCode: BD.86
+ code: '86'
+ BD.87:
+ combinedCode: BD.87
+ code: '87'
+BE:
+ iso2Code: BE
+ iso3Code: BEL
+ regions:
+ BE.BRU:
+ combinedCode: BE.BRU
+ code: BRU
+ BE.WAL:
+ combinedCode: BE.WAL
+ code: WAL
+ BE.VLG:
+ combinedCode: BE.VLG
+ code: VLG
+BF:
+ iso2Code: BF
+ iso3Code: BFA
+ regions:
+ BF.01:
+ combinedCode: BF.01
+ code: '01'
+ BF.02:
+ combinedCode: BF.02
+ code: '02'
+ BF.03:
+ combinedCode: BF.03
+ code: '03'
+ BF.04:
+ combinedCode: BF.04
+ code: '04'
+ BF.05:
+ combinedCode: BF.05
+ code: '05'
+ BF.06:
+ combinedCode: BF.06
+ code: '06'
+ BF.07:
+ combinedCode: BF.07
+ code: '07'
+ BF.08:
+ combinedCode: BF.08
+ code: '08'
+ BF.09:
+ combinedCode: BF.09
+ code: '09'
+ BF.10:
+ combinedCode: BF.10
+ code: '10'
+ BF.11:
+ combinedCode: BF.11
+ code: '11'
+ BF.12:
+ combinedCode: BF.12
+ code: '12'
+ BF.13:
+ combinedCode: BF.13
+ code: '13'
+BG:
+ iso2Code: BG
+ iso3Code: BGR
+ regions:
+ BG.52:
+ combinedCode: BG.52
+ code: '52'
+ BG.47:
+ combinedCode: BG.47
+ code: '47'
+ BG.64:
+ combinedCode: BG.64
+ code: '64'
+ BG.61:
+ combinedCode: BG.61
+ code: '61'
+ BG.40:
+ combinedCode: BG.40
+ code: '40'
+ BG.58:
+ combinedCode: BG.58
+ code: '58'
+ BG.53:
+ combinedCode: BG.53
+ code: '53'
+ BG.51:
+ combinedCode: BG.51
+ code: '51'
+ BG.50:
+ combinedCode: BG.50
+ code: '50'
+ BG.49:
+ combinedCode: BG.49
+ code: '49'
+ BG.48:
+ combinedCode: BG.48
+ code: '48'
+ BG.46:
+ combinedCode: BG.46
+ code: '46'
+ BG.43:
+ combinedCode: BG.43
+ code: '43'
+ BG.42:
+ combinedCode: BG.42
+ code: '42'
+ BG.39:
+ combinedCode: BG.39
+ code: '39'
+ BG.38:
+ combinedCode: BG.38
+ code: '38'
+ BG.41:
+ combinedCode: BG.41
+ code: '41'
+ BG.44:
+ combinedCode: BG.44
+ code: '44'
+ BG.45:
+ combinedCode: BG.45
+ code: '45'
+ BG.54:
+ combinedCode: BG.54
+ code: '54'
+ BG.55:
+ combinedCode: BG.55
+ code: '55'
+ BG.56:
+ combinedCode: BG.56
+ code: '56'
+ BG.57:
+ combinedCode: BG.57
+ code: '57'
+ BG.59:
+ combinedCode: BG.59
+ code: '59'
+ BG.60:
+ combinedCode: BG.60
+ code: '60'
+ BG.62:
+ combinedCode: BG.62
+ code: '62'
+ BG.63:
+ combinedCode: BG.63
+ code: '63'
+ BG.65:
+ combinedCode: BG.65
+ code: '65'
+BH:
+ iso2Code: BH
+ iso3Code: BHR
+ regions:
+ BH.15:
+ combinedCode: BH.15
+ code: '15'
+ BH.16:
+ combinedCode: BH.16
+ code: '16'
+ BH.17:
+ combinedCode: BH.17
+ code: '17'
+ BH.18:
+ combinedCode: BH.18
+ code: '18'
+ BH.19:
+ combinedCode: BH.19
+ code: '19'
+BI:
+ iso2Code: BI
+ iso3Code: BDI
+ regions:
+ BI.17:
+ combinedCode: BI.17
+ code: '17'
+ BI.10:
+ combinedCode: BI.10
+ code: '10'
+ BI.22:
+ combinedCode: BI.22
+ code: '22'
+ BI.13:
+ combinedCode: BI.13
+ code: '13'
+ BI.21:
+ combinedCode: BI.21
+ code: '21'
+ BI.11:
+ combinedCode: BI.11
+ code: '11'
+ BI.14:
+ combinedCode: BI.14
+ code: '14'
+ BI.09:
+ combinedCode: BI.09
+ code: '09'
+ BI.12:
+ combinedCode: BI.12
+ code: '12'
+ BI.19:
+ combinedCode: BI.19
+ code: '19'
+ BI.15:
+ combinedCode: BI.15
+ code: '15'
+ BI.18:
+ combinedCode: BI.18
+ code: '18'
+ BI.16:
+ combinedCode: BI.16
+ code: '16'
+ BI.20:
+ combinedCode: BI.20
+ code: '20'
+ BI.23:
+ combinedCode: BI.23
+ code: '23'
+ BI.24:
+ combinedCode: BI.24
+ code: '24'
+ BI.25:
+ combinedCode: BI.25
+ code: '25'
+BJ:
+ iso2Code: BJ
+ iso3Code: BEN
+ regions:
+ BJ.18:
+ combinedCode: BJ.18
+ code: '18'
+ BJ.16:
+ combinedCode: BJ.16
+ code: '16'
+ BJ.15:
+ combinedCode: BJ.15
+ code: '15'
+ BJ.10:
+ combinedCode: BJ.10
+ code: '10'
+ BJ.09:
+ combinedCode: BJ.09
+ code: '09'
+ BJ.08:
+ combinedCode: BJ.08
+ code: '08'
+ BJ.07:
+ combinedCode: BJ.07
+ code: '07'
+ BJ.11:
+ combinedCode: BJ.11
+ code: '11'
+ BJ.12:
+ combinedCode: BJ.12
+ code: '12'
+ BJ.13:
+ combinedCode: BJ.13
+ code: '13'
+ BJ.14:
+ combinedCode: BJ.14
+ code: '14'
+ BJ.17:
+ combinedCode: BJ.17
+ code: '17'
+BL:
+ iso2Code: BL
+ iso3Code: BLM
+ regions: { }
+BM:
+ iso2Code: BM
+ iso3Code: BMU
+ regions:
+ BM.11:
+ combinedCode: BM.11
+ code: '11'
+ BM.10:
+ combinedCode: BM.10
+ code: '10'
+ BM.09:
+ combinedCode: BM.09
+ code: '09'
+ BM.08:
+ combinedCode: BM.08
+ code: '08'
+ BM.07:
+ combinedCode: BM.07
+ code: '07'
+ BM.06:
+ combinedCode: BM.06
+ code: '06'
+ BM.05:
+ combinedCode: BM.05
+ code: '05'
+ BM.04:
+ combinedCode: BM.04
+ code: '04'
+ BM.02:
+ combinedCode: BM.02
+ code: '02'
+ BM.03:
+ combinedCode: BM.03
+ code: '03'
+ BM.01:
+ combinedCode: BM.01
+ code: '01'
+BN:
+ iso2Code: BN
+ iso3Code: BRN
+ regions:
+ BN.04:
+ combinedCode: BN.04
+ code: '04'
+ BN.03:
+ combinedCode: BN.03
+ code: '03'
+ BN.02:
+ combinedCode: BN.02
+ code: '02'
+ BN.01:
+ combinedCode: BN.01
+ code: '01'
+BO:
+ iso2Code: BO
+ iso3Code: BOL
+ regions:
+ BO.09:
+ combinedCode: BO.09
+ code: '09'
+ BO.08:
+ combinedCode: BO.08
+ code: '08'
+ BO.07:
+ combinedCode: BO.07
+ code: '07'
+ BO.06:
+ combinedCode: BO.06
+ code: '06'
+ BO.05:
+ combinedCode: BO.05
+ code: '05'
+ BO.04:
+ combinedCode: BO.04
+ code: '04'
+ BO.02:
+ combinedCode: BO.02
+ code: '02'
+ BO.01:
+ combinedCode: BO.01
+ code: '01'
+ BO.03:
+ combinedCode: BO.03
+ code: '03'
+BQ:
+ iso2Code: BQ
+ iso3Code: BES
+ regions:
+ BQ.BO:
+ combinedCode: BQ.BO
+ code: BO
+ BQ.SB:
+ combinedCode: BQ.SB
+ code: SB
+ BQ.SE:
+ combinedCode: BQ.SE
+ code: SE
+BR:
+ iso2Code: BR
+ iso3Code: BRA
+ regions:
+ BR.22:
+ combinedCode: BR.22
+ code: '22'
+ BR.20:
+ combinedCode: BR.20
+ code: '20'
+ BR.30:
+ combinedCode: BR.30
+ code: '30'
+ BR.17:
+ combinedCode: BR.17
+ code: '17'
+ BR.16:
+ combinedCode: BR.16
+ code: '16'
+ BR.13:
+ combinedCode: BR.13
+ code: '13'
+ BR.06:
+ combinedCode: BR.06
+ code: '06'
+ BR.03:
+ combinedCode: BR.03
+ code: '03'
+ BR.02:
+ combinedCode: BR.02
+ code: '02'
+ BR.28:
+ combinedCode: BR.28
+ code: '28'
+ BR.27:
+ combinedCode: BR.27
+ code: '27'
+ BR.26:
+ combinedCode: BR.26
+ code: '26'
+ BR.23:
+ combinedCode: BR.23
+ code: '23'
+ BR.21:
+ combinedCode: BR.21
+ code: '21'
+ BR.18:
+ combinedCode: BR.18
+ code: '18'
+ BR.15:
+ combinedCode: BR.15
+ code: '15'
+ BR.11:
+ combinedCode: BR.11
+ code: '11'
+ BR.14:
+ combinedCode: BR.14
+ code: '14'
+ BR.29:
+ combinedCode: BR.29
+ code: '29'
+ BR.07:
+ combinedCode: BR.07
+ code: '07'
+ BR.08:
+ combinedCode: BR.08
+ code: '08'
+ BR.05:
+ combinedCode: BR.05
+ code: '05'
+ BR.31:
+ combinedCode: BR.31
+ code: '31'
+ BR.25:
+ combinedCode: BR.25
+ code: '25'
+ BR.04:
+ combinedCode: BR.04
+ code: '04'
+ BR.01:
+ combinedCode: BR.01
+ code: '01'
+ BR.24:
+ combinedCode: BR.24
+ code: '24'
+BS:
+ iso2Code: BS
+ iso3Code: BHS
+ regions:
+ BS.35:
+ combinedCode: BS.35
+ code: '35'
+ BS.34:
+ combinedCode: BS.34
+ code: '34'
+ BS.33:
+ combinedCode: BS.33
+ code: '33'
+ BS.18:
+ combinedCode: BS.18
+ code: '18'
+ BS.32:
+ combinedCode: BS.32
+ code: '32'
+ BS.23:
+ combinedCode: BS.23
+ code: '23'
+ BS.16:
+ combinedCode: BS.16
+ code: '16'
+ BS.31:
+ combinedCode: BS.31
+ code: '31'
+ BS.15:
+ combinedCode: BS.15
+ code: '15'
+ BS.30:
+ combinedCode: BS.30
+ code: '30'
+ BS.13:
+ combinedCode: BS.13
+ code: '13'
+ BS.29:
+ combinedCode: BS.29
+ code: '29'
+ BS.22:
+ combinedCode: BS.22
+ code: '22'
+ BS.28:
+ combinedCode: BS.28
+ code: '28'
+ BS.27:
+ combinedCode: BS.27
+ code: '27'
+ BS.26:
+ combinedCode: BS.26
+ code: '26'
+ BS.25:
+ combinedCode: BS.25
+ code: '25'
+ BS.10:
+ combinedCode: BS.10
+ code: '10'
+ BS.06:
+ combinedCode: BS.06
+ code: '06'
+ BS.05:
+ combinedCode: BS.05
+ code: '05'
+ BS.24:
+ combinedCode: BS.24
+ code: '24'
+ BS.36:
+ combinedCode: BS.36
+ code: '36'
+ BS.37:
+ combinedCode: BS.37
+ code: '37'
+ BS.38:
+ combinedCode: BS.38
+ code: '38'
+ BS.39:
+ combinedCode: BS.39
+ code: '39'
+ BS.40:
+ combinedCode: BS.40
+ code: '40'
+ BS.41:
+ combinedCode: BS.41
+ code: '41'
+ BS.42:
+ combinedCode: BS.42
+ code: '42'
+ BS.43:
+ combinedCode: BS.43
+ code: '43'
+ BS.44:
+ combinedCode: BS.44
+ code: '44'
+ BS.45:
+ combinedCode: BS.45
+ code: '45'
+ BS.46:
+ combinedCode: BS.46
+ code: '46'
+ BS.47:
+ combinedCode: BS.47
+ code: '47'
+ BS.48:
+ combinedCode: BS.48
+ code: '48'
+ BS.49:
+ combinedCode: BS.49
+ code: '49'
+ BS.50:
+ combinedCode: BS.50
+ code: '50'
+ BS.51:
+ combinedCode: BS.51
+ code: '51'
+ BS.52:
+ combinedCode: BS.52
+ code: '52'
+ BS.53:
+ combinedCode: BS.53
+ code: '53'
+ BS.54:
+ combinedCode: BS.54
+ code: '54'
+BT:
+ iso2Code: BT
+ iso3Code: BTN
+ regions:
+ BT.05:
+ combinedCode: BT.05
+ code: '05'
+ BT.06:
+ combinedCode: BT.06
+ code: '06'
+ BT.08:
+ combinedCode: BT.08
+ code: '08'
+ BT.07:
+ combinedCode: BT.07
+ code: '07'
+ BT.09:
+ combinedCode: BT.09
+ code: '09'
+ BT.10:
+ combinedCode: BT.10
+ code: '10'
+ BT.11:
+ combinedCode: BT.11
+ code: '11'
+ BT.12:
+ combinedCode: BT.12
+ code: '12'
+ BT.13:
+ combinedCode: BT.13
+ code: '13'
+ BT.14:
+ combinedCode: BT.14
+ code: '14'
+ BT.15:
+ combinedCode: BT.15
+ code: '15'
+ BT.16:
+ combinedCode: BT.16
+ code: '16'
+ BT.17:
+ combinedCode: BT.17
+ code: '17'
+ BT.18:
+ combinedCode: BT.18
+ code: '18'
+ BT.19:
+ combinedCode: BT.19
+ code: '19'
+ BT.20:
+ combinedCode: BT.20
+ code: '20'
+ BT.21:
+ combinedCode: BT.21
+ code: '21'
+ BT.22:
+ combinedCode: BT.22
+ code: '22'
+ BT.23:
+ combinedCode: BT.23
+ code: '23'
+ BT.24:
+ combinedCode: BT.24
+ code: '24'
+BV:
+ iso2Code: BV
+ iso3Code: BVT
+ regions: { }
+BW:
+ iso2Code: BW
+ iso3Code: BWA
+ regions:
+ BW.10:
+ combinedCode: BW.10
+ code: '10'
+ BW.09:
+ combinedCode: BW.09
+ code: '09'
+ BW.08:
+ combinedCode: BW.08
+ code: '08'
+ BW.11:
+ combinedCode: BW.11
+ code: '11'
+ BW.06:
+ combinedCode: BW.06
+ code: '06'
+ BW.05:
+ combinedCode: BW.05
+ code: '05'
+ BW.04:
+ combinedCode: BW.04
+ code: '04'
+ BW.03:
+ combinedCode: BW.03
+ code: '03'
+ BW.01:
+ combinedCode: BW.01
+ code: '01'
+BY:
+ iso2Code: BY
+ iso3Code: BLR
+ regions:
+ BY.07:
+ combinedCode: BY.07
+ code: '07'
+ BY.06:
+ combinedCode: BY.06
+ code: '06'
+ BY.05:
+ combinedCode: BY.05
+ code: '05'
+ BY.04:
+ combinedCode: BY.04
+ code: '04'
+ BY.03:
+ combinedCode: BY.03
+ code: '03'
+ BY.02:
+ combinedCode: BY.02
+ code: '02'
+ BY.01:
+ combinedCode: BY.01
+ code: '01'
+BZ:
+ iso2Code: BZ
+ iso3Code: BLZ
+ regions:
+ BZ.06:
+ combinedCode: BZ.06
+ code: '06'
+ BZ.05:
+ combinedCode: BZ.05
+ code: '05'
+ BZ.04:
+ combinedCode: BZ.04
+ code: '04'
+ BZ.03:
+ combinedCode: BZ.03
+ code: '03'
+ BZ.02:
+ combinedCode: BZ.02
+ code: '02'
+ BZ.01:
+ combinedCode: BZ.01
+ code: '01'
+CA:
+ iso2Code: CA
+ iso3Code: CAN
+ regions:
+ CA.01:
+ combinedCode: CA.01
+ code: '01'
+ CA.02:
+ combinedCode: CA.02
+ code: '02'
+ CA.03:
+ combinedCode: CA.03
+ code: '03'
+ CA.04:
+ combinedCode: CA.04
+ code: '04'
+ CA.13:
+ combinedCode: CA.13
+ code: '13'
+ CA.07:
+ combinedCode: CA.07
+ code: '07'
+ CA.14:
+ combinedCode: CA.14
+ code: '14'
+ CA.08:
+ combinedCode: CA.08
+ code: '08'
+ CA.09:
+ combinedCode: CA.09
+ code: '09'
+ CA.10:
+ combinedCode: CA.10
+ code: '10'
+ CA.11:
+ combinedCode: CA.11
+ code: '11'
+ CA.12:
+ combinedCode: CA.12
+ code: '12'
+ CA.05:
+ combinedCode: CA.05
+ code: '05'
+CC:
+ iso2Code: CC
+ iso3Code: CCK
+ regions: { }
+CD:
+ iso2Code: CD
+ iso3Code: COD
+ regions:
+ CD.12:
+ combinedCode: CD.12
+ code: '12'
+ CD.05:
+ combinedCode: CD.05
+ code: '05'
+ CD.11:
+ combinedCode: CD.11
+ code: '11'
+ CD.10:
+ combinedCode: CD.10
+ code: '10'
+ CD.04:
+ combinedCode: CD.04
+ code: '04'
+ CD.03:
+ combinedCode: CD.03
+ code: '03'
+ CD.09:
+ combinedCode: CD.09
+ code: '09'
+ CD.02:
+ combinedCode: CD.02
+ code: '02'
+ CD.06:
+ combinedCode: CD.06
+ code: '06'
+ CD.08:
+ combinedCode: CD.08
+ code: '08'
+ CD.01:
+ combinedCode: CD.01
+ code: '01'
+CF:
+ iso2Code: CF
+ iso3Code: CAF
+ regions:
+ CF.14:
+ combinedCode: CF.14
+ code: '14'
+ CF.11:
+ combinedCode: CF.11
+ code: '11'
+ CF.08:
+ combinedCode: CF.08
+ code: '08'
+ CF.05:
+ combinedCode: CF.05
+ code: '05'
+ CF.03:
+ combinedCode: CF.03
+ code: '03'
+ CF.02:
+ combinedCode: CF.02
+ code: '02'
+ CF.01:
+ combinedCode: CF.01
+ code: '01'
+ CF.16:
+ combinedCode: CF.16
+ code: '16'
+ CF.13:
+ combinedCode: CF.13
+ code: '13'
+ CF.12:
+ combinedCode: CF.12
+ code: '12'
+ CF.17:
+ combinedCode: CF.17
+ code: '17'
+ CF.09:
+ combinedCode: CF.09
+ code: '09'
+ CF.07:
+ combinedCode: CF.07
+ code: '07'
+ CF.06:
+ combinedCode: CF.06
+ code: '06'
+ CF.04:
+ combinedCode: CF.04
+ code: '04'
+ CF.15:
+ combinedCode: CF.15
+ code: '15'
+ CF.18:
+ combinedCode: CF.18
+ code: '18'
+CG:
+ iso2Code: CG
+ iso3Code: COG
+ regions:
+ CG.10:
+ combinedCode: CG.10
+ code: '10'
+ CG.11:
+ combinedCode: CG.11
+ code: '11'
+ CG.08:
+ combinedCode: CG.08
+ code: '08'
+ CG.07:
+ combinedCode: CG.07
+ code: '07'
+ CG.06:
+ combinedCode: CG.06
+ code: '06'
+ CG.05:
+ combinedCode: CG.05
+ code: '05'
+ CG.04:
+ combinedCode: CG.04
+ code: '04'
+ CG.13:
+ combinedCode: CG.13
+ code: '13'
+ CG.01:
+ combinedCode: CG.01
+ code: '01'
+ CG.12:
+ combinedCode: CG.12
+ code: '12'
+ CG.14:
+ combinedCode: CG.14
+ code: '14'
+ CG.7280295:
+ combinedCode: CG.7280295
+ code: '7280295'
+CH:
+ iso2Code: CH
+ iso3Code: CHE
+ regions:
+ CH.ZH:
+ combinedCode: CH.ZH
+ code: ZH
+ CH.ZG:
+ combinedCode: CH.ZG
+ code: ZG
+ CH.VD:
+ combinedCode: CH.VD
+ code: VD
+ CH.VS:
+ combinedCode: CH.VS
+ code: VS
+ CH.UR:
+ combinedCode: CH.UR
+ code: UR
+ CH.TI:
+ combinedCode: CH.TI
+ code: TI
+ CH.TG:
+ combinedCode: CH.TG
+ code: TG
+ CH.SO:
+ combinedCode: CH.SO
+ code: SO
+ CH.SZ:
+ combinedCode: CH.SZ
+ code: SZ
+ CH.SH:
+ combinedCode: CH.SH
+ code: SH
+ CH.SG:
+ combinedCode: CH.SG
+ code: SG
+ CH.OW:
+ combinedCode: CH.OW
+ code: OW
+ CH.NW:
+ combinedCode: CH.NW
+ code: NW
+ CH.NE:
+ combinedCode: CH.NE
+ code: NE
+ CH.LU:
+ combinedCode: CH.LU
+ code: LU
+ CH.JU:
+ combinedCode: CH.JU
+ code: JU
+ CH.GR:
+ combinedCode: CH.GR
+ code: GR
+ CH.GL:
+ combinedCode: CH.GL
+ code: GL
+ CH.GE:
+ combinedCode: CH.GE
+ code: GE
+ CH.FR:
+ combinedCode: CH.FR
+ code: FR
+ CH.BE:
+ combinedCode: CH.BE
+ code: BE
+ CH.BS:
+ combinedCode: CH.BS
+ code: BS
+ CH.BL:
+ combinedCode: CH.BL
+ code: BL
+ CH.AR:
+ combinedCode: CH.AR
+ code: AR
+ CH.AI:
+ combinedCode: CH.AI
+ code: AI
+ CH.AG:
+ combinedCode: CH.AG
+ code: AG
+CI:
+ iso2Code: CI
+ iso3Code: CIV
+ regions:
+ CI.82:
+ combinedCode: CI.82
+ code: '82'
+ CI.89:
+ combinedCode: CI.89
+ code: '89'
+ CI.74:
+ combinedCode: CI.74
+ code: '74'
+ CI.80:
+ combinedCode: CI.80
+ code: '80'
+ CI.87:
+ combinedCode: CI.87
+ code: '87'
+ CI.90:
+ combinedCode: CI.90
+ code: '90'
+ CI.85:
+ combinedCode: CI.85
+ code: '85'
+ CI.78:
+ combinedCode: CI.78
+ code: '78'
+ CI.81:
+ combinedCode: CI.81
+ code: '81'
+ CI.92:
+ combinedCode: CI.92
+ code: '92'
+ CI.76:
+ combinedCode: CI.76
+ code: '76'
+ CI.91:
+ combinedCode: CI.91
+ code: '91'
+ CI.77:
+ combinedCode: CI.77
+ code: '77'
+ CI.88:
+ combinedCode: CI.88
+ code: '88'
+ CI.79:
+ combinedCode: CI.79
+ code: '79'
+ CI.86:
+ combinedCode: CI.86
+ code: '86'
+ CI.83:
+ combinedCode: CI.83
+ code: '83'
+ CI.84:
+ combinedCode: CI.84
+ code: '84'
+ CI.75:
+ combinedCode: CI.75
+ code: '75'
+CK:
+ iso2Code: CK
+ iso3Code: COK
+ regions: { }
+CL:
+ iso2Code: CL
+ iso3Code: CHL
+ regions:
+ CL.01:
+ combinedCode: CL.01
+ code: '01'
+ CL.15:
+ combinedCode: CL.15
+ code: '15'
+ CL.12:
+ combinedCode: CL.12
+ code: '12'
+ CL.11:
+ combinedCode: CL.11
+ code: '11'
+ CL.14:
+ combinedCode: CL.14
+ code: '14'
+ CL.08:
+ combinedCode: CL.08
+ code: '08'
+ CL.07:
+ combinedCode: CL.07
+ code: '07'
+ CL.06:
+ combinedCode: CL.06
+ code: '06'
+ CL.05:
+ combinedCode: CL.05
+ code: '05'
+ CL.04:
+ combinedCode: CL.04
+ code: '04'
+ CL.03:
+ combinedCode: CL.03
+ code: '03'
+ CL.02:
+ combinedCode: CL.02
+ code: '02'
+ CL.10:
+ combinedCode: CL.10
+ code: '10'
+ CL.16:
+ combinedCode: CL.16
+ code: '16'
+ CL.17:
+ combinedCode: CL.17
+ code: '17'
+CM:
+ iso2Code: CM
+ iso3Code: CMR
+ regions:
+ CM.09:
+ combinedCode: CM.09
+ code: '09'
+ CM.14:
+ combinedCode: CM.14
+ code: '14'
+ CM.08:
+ combinedCode: CM.08
+ code: '08'
+ CM.07:
+ combinedCode: CM.07
+ code: '07'
+ CM.13:
+ combinedCode: CM.13
+ code: '13'
+ CM.05:
+ combinedCode: CM.05
+ code: '05'
+ CM.12:
+ combinedCode: CM.12
+ code: '12'
+ CM.04:
+ combinedCode: CM.04
+ code: '04'
+ CM.11:
+ combinedCode: CM.11
+ code: '11'
+ CM.10:
+ combinedCode: CM.10
+ code: '10'
+CN:
+ iso2Code: CN
+ iso3Code: CHN
+ regions:
+ CN.14:
+ combinedCode: CN.14
+ code: '14'
+ CN.06:
+ combinedCode: CN.06
+ code: '06'
+ CN.13:
+ combinedCode: CN.13
+ code: '13'
+ CN.02:
+ combinedCode: CN.02
+ code: '02'
+ CN.29:
+ combinedCode: CN.29
+ code: '29'
+ CN.28:
+ combinedCode: CN.28
+ code: '28'
+ CN.32:
+ combinedCode: CN.32
+ code: '32'
+ CN.24:
+ combinedCode: CN.24
+ code: '24'
+ CN.23:
+ combinedCode: CN.23
+ code: '23'
+ CN.25:
+ combinedCode: CN.25
+ code: '25'
+ CN.26:
+ combinedCode: CN.26
+ code: '26'
+ CN.21:
+ combinedCode: CN.21
+ code: '21'
+ CN.03:
+ combinedCode: CN.03
+ code: '03'
+ CN.04:
+ combinedCode: CN.04
+ code: '04'
+ CN.11:
+ combinedCode: CN.11
+ code: '11'
+ CN.12:
+ combinedCode: CN.12
+ code: '12'
+ CN.09:
+ combinedCode: CN.09
+ code: '09'
+ CN.10:
+ combinedCode: CN.10
+ code: '10'
+ CN.31:
+ combinedCode: CN.31
+ code: '31'
+ CN.18:
+ combinedCode: CN.18
+ code: '18'
+ CN.16:
+ combinedCode: CN.16
+ code: '16'
+ CN.30:
+ combinedCode: CN.30
+ code: '30'
+ CN.15:
+ combinedCode: CN.15
+ code: '15'
+ CN.07:
+ combinedCode: CN.07
+ code: '07'
+ CN.33:
+ combinedCode: CN.33
+ code: '33'
+ CN.01:
+ combinedCode: CN.01
+ code: '01'
+ CN.20:
+ combinedCode: CN.20
+ code: '20'
+ CN.19:
+ combinedCode: CN.19
+ code: '19'
+ CN.05:
+ combinedCode: CN.05
+ code: '05'
+ CN.08:
+ combinedCode: CN.08
+ code: '08'
+ CN.22:
+ combinedCode: CN.22
+ code: '22'
+CO:
+ iso2Code: CO
+ iso3Code: COL
+ regions:
+ CO.31:
+ combinedCode: CO.31
+ code: '31'
+ CO.30:
+ combinedCode: CO.30
+ code: '30'
+ CO.29:
+ combinedCode: CO.29
+ code: '29'
+ CO.28:
+ combinedCode: CO.28
+ code: '28'
+ CO.27:
+ combinedCode: CO.27
+ code: '27'
+ CO.26:
+ combinedCode: CO.26
+ code: '26'
+ CO.25:
+ combinedCode: CO.25
+ code: '25'
+ CO.24:
+ combinedCode: CO.24
+ code: '24'
+ CO.23:
+ combinedCode: CO.23
+ code: '23'
+ CO.22:
+ combinedCode: CO.22
+ code: '22'
+ CO.21:
+ combinedCode: CO.21
+ code: '21'
+ CO.20:
+ combinedCode: CO.20
+ code: '20'
+ CO.19:
+ combinedCode: CO.19
+ code: '19'
+ CO.38:
+ combinedCode: CO.38
+ code: '38'
+ CO.17:
+ combinedCode: CO.17
+ code: '17'
+ CO.16:
+ combinedCode: CO.16
+ code: '16'
+ CO.14:
+ combinedCode: CO.14
+ code: '14'
+ CO.15:
+ combinedCode: CO.15
+ code: '15'
+ CO.33:
+ combinedCode: CO.33
+ code: '33'
+ CO.12:
+ combinedCode: CO.12
+ code: '12'
+ CO.11:
+ combinedCode: CO.11
+ code: '11'
+ CO.10:
+ combinedCode: CO.10
+ code: '10'
+ CO.09:
+ combinedCode: CO.09
+ code: '09'
+ CO.32:
+ combinedCode: CO.32
+ code: '32'
+ CO.08:
+ combinedCode: CO.08
+ code: '08'
+ CO.37:
+ combinedCode: CO.37
+ code: '37'
+ CO.36:
+ combinedCode: CO.36
+ code: '36'
+ CO.35:
+ combinedCode: CO.35
+ code: '35'
+ CO.34:
+ combinedCode: CO.34
+ code: '34'
+ CO.04:
+ combinedCode: CO.04
+ code: '04'
+ CO.03:
+ combinedCode: CO.03
+ code: '03'
+ CO.02:
+ combinedCode: CO.02
+ code: '02'
+ CO.01:
+ combinedCode: CO.01
+ code: '01'
+CR:
+ iso2Code: CR
+ iso3Code: CRI
+ regions:
+ CR.08:
+ combinedCode: CR.08
+ code: '08'
+ CR.07:
+ combinedCode: CR.07
+ code: '07'
+ CR.06:
+ combinedCode: CR.06
+ code: '06'
+ CR.04:
+ combinedCode: CR.04
+ code: '04'
+ CR.03:
+ combinedCode: CR.03
+ code: '03'
+ CR.02:
+ combinedCode: CR.02
+ code: '02'
+ CR.01:
+ combinedCode: CR.01
+ code: '01'
+CU:
+ iso2Code: CU
+ iso3Code: CUB
+ regions:
+ CU.16:
+ combinedCode: CU.16
+ code: '16'
+ CU.15:
+ combinedCode: CU.15
+ code: '15'
+ CU.14:
+ combinedCode: CU.14
+ code: '14'
+ CU.01:
+ combinedCode: CU.01
+ code: '01'
+ CU.03:
+ combinedCode: CU.03
+ code: '03'
+ CU.13:
+ combinedCode: CU.13
+ code: '13'
+ CU.04:
+ combinedCode: CU.04
+ code: '04'
+ CU.12:
+ combinedCode: CU.12
+ code: '12'
+ CU.10:
+ combinedCode: CU.10
+ code: '10'
+ CU.09:
+ combinedCode: CU.09
+ code: '09'
+ CU.02:
+ combinedCode: CU.02
+ code: '02'
+ CU.08:
+ combinedCode: CU.08
+ code: '08'
+ CU.07:
+ combinedCode: CU.07
+ code: '07'
+ CU.05:
+ combinedCode: CU.05
+ code: '05'
+ CU.AR:
+ combinedCode: CU.AR
+ code: AR
+ CU.MA:
+ combinedCode: CU.MA
+ code: MA
+CV:
+ iso2Code: CV
+ iso3Code: CPV
+ regions:
+ CV.20:
+ combinedCode: CV.20
+ code: '20'
+ CV.11:
+ combinedCode: CV.11
+ code: '11'
+ CV.15:
+ combinedCode: CV.15
+ code: '15'
+ CV.08:
+ combinedCode: CV.08
+ code: '08'
+ CV.07:
+ combinedCode: CV.07
+ code: '07'
+ CV.14:
+ combinedCode: CV.14
+ code: '14'
+ CV.05:
+ combinedCode: CV.05
+ code: '05'
+ CV.04:
+ combinedCode: CV.04
+ code: '04'
+ CV.02:
+ combinedCode: CV.02
+ code: '02'
+ CV.01:
+ combinedCode: CV.01
+ code: '01'
+ CV.13:
+ combinedCode: CV.13
+ code: '13'
+ CV.16:
+ combinedCode: CV.16
+ code: '16'
+ CV.17:
+ combinedCode: CV.17
+ code: '17'
+ CV.18:
+ combinedCode: CV.18
+ code: '18'
+ CV.19:
+ combinedCode: CV.19
+ code: '19'
+ CV.21:
+ combinedCode: CV.21
+ code: '21'
+ CV.22:
+ combinedCode: CV.22
+ code: '22'
+ CV.24:
+ combinedCode: CV.24
+ code: '24'
+ CV.26:
+ combinedCode: CV.26
+ code: '26'
+ CV.27:
+ combinedCode: CV.27
+ code: '27'
+ CV.25:
+ combinedCode: CV.25
+ code: '25'
+ CV.23:
+ combinedCode: CV.23
+ code: '23'
+CW:
+ iso2Code: CW
+ iso3Code: CUW
+ regions: { }
+CX:
+ iso2Code: CX
+ iso3Code: CXR
+ regions: { }
+CY:
+ iso2Code: CY
+ iso3Code: CYP
+ regions:
+ CY.06:
+ combinedCode: CY.06
+ code: '06'
+ CY.04:
+ combinedCode: CY.04
+ code: '04'
+ CY.05:
+ combinedCode: CY.05
+ code: '05'
+ CY.03:
+ combinedCode: CY.03
+ code: '03'
+ CY.02:
+ combinedCode: CY.02
+ code: '02'
+ CY.01:
+ combinedCode: CY.01
+ code: '01'
+CZ:
+ iso2Code: CZ
+ iso3Code: CZE
+ regions:
+ CZ.52:
+ combinedCode: CZ.52
+ code: '52'
+ CZ.78:
+ combinedCode: CZ.78
+ code: '78'
+ CZ.79:
+ combinedCode: CZ.79
+ code: '79'
+ CZ.80:
+ combinedCode: CZ.80
+ code: '80'
+ CZ.81:
+ combinedCode: CZ.81
+ code: '81'
+ CZ.82:
+ combinedCode: CZ.82
+ code: '82'
+ CZ.83:
+ combinedCode: CZ.83
+ code: '83'
+ CZ.84:
+ combinedCode: CZ.84
+ code: '84'
+ CZ.85:
+ combinedCode: CZ.85
+ code: '85'
+ CZ.86:
+ combinedCode: CZ.86
+ code: '86'
+ CZ.87:
+ combinedCode: CZ.87
+ code: '87'
+ CZ.88:
+ combinedCode: CZ.88
+ code: '88'
+ CZ.89:
+ combinedCode: CZ.89
+ code: '89'
+ CZ.90:
+ combinedCode: CZ.90
+ code: '90'
+DE:
+ iso2Code: DE
+ iso3Code: DEU
+ regions:
+ DE.15:
+ combinedCode: DE.15
+ code: '15'
+ DE.10:
+ combinedCode: DE.10
+ code: '10'
+ DE.14:
+ combinedCode: DE.14
+ code: '14'
+ DE.13:
+ combinedCode: DE.13
+ code: '13'
+ DE.09:
+ combinedCode: DE.09
+ code: '09'
+ DE.08:
+ combinedCode: DE.08
+ code: '08'
+ DE.07:
+ combinedCode: DE.07
+ code: '07'
+ DE.06:
+ combinedCode: DE.06
+ code: '06'
+ DE.12:
+ combinedCode: DE.12
+ code: '12'
+ DE.05:
+ combinedCode: DE.05
+ code: '05'
+ DE.04:
+ combinedCode: DE.04
+ code: '04'
+ DE.03:
+ combinedCode: DE.03
+ code: '03'
+ DE.11:
+ combinedCode: DE.11
+ code: '11'
+ DE.16:
+ combinedCode: DE.16
+ code: '16'
+ DE.02:
+ combinedCode: DE.02
+ code: '02'
+ DE.01:
+ combinedCode: DE.01
+ code: '01'
+DJ:
+ iso2Code: DJ
+ iso3Code: DJI
+ regions:
+ DJ.05:
+ combinedCode: DJ.05
+ code: '05'
+ DJ.04:
+ combinedCode: DJ.04
+ code: '04'
+ DJ.07:
+ combinedCode: DJ.07
+ code: '07'
+ DJ.06:
+ combinedCode: DJ.06
+ code: '06'
+ DJ.01:
+ combinedCode: DJ.01
+ code: '01'
+ DJ.08:
+ combinedCode: DJ.08
+ code: '08'
+DK:
+ iso2Code: DK
+ iso3Code: DNK
+ regions:
+ DK.17:
+ combinedCode: DK.17
+ code: '17'
+ DK.18:
+ combinedCode: DK.18
+ code: '18'
+ DK.19:
+ combinedCode: DK.19
+ code: '19'
+ DK.20:
+ combinedCode: DK.20
+ code: '20'
+ DK.21:
+ combinedCode: DK.21
+ code: '21'
+DM:
+ iso2Code: DM
+ iso3Code: DMA
+ regions:
+ DM.11:
+ combinedCode: DM.11
+ code: '11'
+ DM.10:
+ combinedCode: DM.10
+ code: '10'
+ DM.09:
+ combinedCode: DM.09
+ code: '09'
+ DM.08:
+ combinedCode: DM.08
+ code: '08'
+ DM.07:
+ combinedCode: DM.07
+ code: '07'
+ DM.06:
+ combinedCode: DM.06
+ code: '06'
+ DM.05:
+ combinedCode: DM.05
+ code: '05'
+ DM.04:
+ combinedCode: DM.04
+ code: '04'
+ DM.03:
+ combinedCode: DM.03
+ code: '03'
+ DM.02:
+ combinedCode: DM.02
+ code: '02'
+DO:
+ iso2Code: DO
+ iso3Code: DOM
+ regions:
+ DO.27:
+ combinedCode: DO.27
+ code: '27'
+ DO.26:
+ combinedCode: DO.26
+ code: '26'
+ DO.25:
+ combinedCode: DO.25
+ code: '25'
+ DO.24:
+ combinedCode: DO.24
+ code: '24'
+ DO.23:
+ combinedCode: DO.23
+ code: '23'
+ DO.33:
+ combinedCode: DO.33
+ code: '33'
+ DO.21:
+ combinedCode: DO.21
+ code: '21'
+ DO.20:
+ combinedCode: DO.20
+ code: '20'
+ DO.19:
+ combinedCode: DO.19
+ code: '19'
+ DO.18:
+ combinedCode: DO.18
+ code: '18'
+ DO.35:
+ combinedCode: DO.35
+ code: '35'
+ DO.16:
+ combinedCode: DO.16
+ code: '16'
+ DO.34:
+ combinedCode: DO.34
+ code: '34'
+ DO.32:
+ combinedCode: DO.32
+ code: '32'
+ DO.15:
+ combinedCode: DO.15
+ code: '15'
+ DO.31:
+ combinedCode: DO.31
+ code: '31'
+ DO.14:
+ combinedCode: DO.14
+ code: '14'
+ DO.30:
+ combinedCode: DO.30
+ code: '30'
+ DO.12:
+ combinedCode: DO.12
+ code: '12'
+ DO.10:
+ combinedCode: DO.10
+ code: '10'
+ DO.09:
+ combinedCode: DO.09
+ code: '09'
+ DO.29:
+ combinedCode: DO.29
+ code: '29'
+ DO.08:
+ combinedCode: DO.08
+ code: '08'
+ DO.28:
+ combinedCode: DO.28
+ code: '28'
+ DO.11:
+ combinedCode: DO.11
+ code: '11'
+ DO.06:
+ combinedCode: DO.06
+ code: '06'
+ DO.04:
+ combinedCode: DO.04
+ code: '04'
+ DO.03:
+ combinedCode: DO.03
+ code: '03'
+ DO.02:
+ combinedCode: DO.02
+ code: '02'
+ DO.01:
+ combinedCode: DO.01
+ code: '01'
+ DO.36:
+ combinedCode: DO.36
+ code: '36'
+ DO.37:
+ combinedCode: DO.37
+ code: '37'
+DZ:
+ iso2Code: DZ
+ iso3Code: DZA
+ regions:
+ DZ.15:
+ combinedCode: DZ.15
+ code: '15'
+ DZ.14:
+ combinedCode: DZ.14
+ code: '14'
+ DZ.56:
+ combinedCode: DZ.56
+ code: '56'
+ DZ.55:
+ combinedCode: DZ.55
+ code: '55'
+ DZ.54:
+ combinedCode: DZ.54
+ code: '54'
+ DZ.13:
+ combinedCode: DZ.13
+ code: '13'
+ DZ.33:
+ combinedCode: DZ.33
+ code: '33'
+ DZ.53:
+ combinedCode: DZ.53
+ code: '53'
+ DZ.52:
+ combinedCode: DZ.52
+ code: '52'
+ DZ.31:
+ combinedCode: DZ.31
+ code: '31'
+ DZ.30:
+ combinedCode: DZ.30
+ code: '30'
+ DZ.12:
+ combinedCode: DZ.12
+ code: '12'
+ DZ.10:
+ combinedCode: DZ.10
+ code: '10'
+ DZ.51:
+ combinedCode: DZ.51
+ code: '51'
+ DZ.29:
+ combinedCode: DZ.29
+ code: '29'
+ DZ.50:
+ combinedCode: DZ.50
+ code: '50'
+ DZ.09:
+ combinedCode: DZ.09
+ code: '09'
+ DZ.49:
+ combinedCode: DZ.49
+ code: '49'
+ DZ.27:
+ combinedCode: DZ.27
+ code: '27'
+ DZ.07:
+ combinedCode: DZ.07
+ code: '07'
+ DZ.48:
+ combinedCode: DZ.48
+ code: '48'
+ DZ.06:
+ combinedCode: DZ.06
+ code: '06'
+ DZ.26:
+ combinedCode: DZ.26
+ code: '26'
+ DZ.25:
+ combinedCode: DZ.25
+ code: '25'
+ DZ.47:
+ combinedCode: DZ.47
+ code: '47'
+ DZ.24:
+ combinedCode: DZ.24
+ code: '24'
+ DZ.46:
+ combinedCode: DZ.46
+ code: '46'
+ DZ.23:
+ combinedCode: DZ.23
+ code: '23'
+ DZ.45:
+ combinedCode: DZ.45
+ code: '45'
+ DZ.44:
+ combinedCode: DZ.44
+ code: '44'
+ DZ.43:
+ combinedCode: DZ.43
+ code: '43'
+ DZ.42:
+ combinedCode: DZ.42
+ code: '42'
+ DZ.22:
+ combinedCode: DZ.22
+ code: '22'
+ DZ.04:
+ combinedCode: DZ.04
+ code: '04'
+ DZ.41:
+ combinedCode: DZ.41
+ code: '41'
+ DZ.40:
+ combinedCode: DZ.40
+ code: '40'
+ DZ.21:
+ combinedCode: DZ.21
+ code: '21'
+ DZ.39:
+ combinedCode: DZ.39
+ code: '39'
+ DZ.20:
+ combinedCode: DZ.20
+ code: '20'
+ DZ.19:
+ combinedCode: DZ.19
+ code: '19'
+ DZ.18:
+ combinedCode: DZ.18
+ code: '18'
+ DZ.38:
+ combinedCode: DZ.38
+ code: '38'
+ DZ.03:
+ combinedCode: DZ.03
+ code: '03'
+ DZ.37:
+ combinedCode: DZ.37
+ code: '37'
+ DZ.01:
+ combinedCode: DZ.01
+ code: '01'
+ DZ.36:
+ combinedCode: DZ.36
+ code: '36'
+ DZ.35:
+ combinedCode: DZ.35
+ code: '35'
+ DZ.34:
+ combinedCode: DZ.34
+ code: '34'
+EC:
+ iso2Code: EC
+ iso3Code: ECU
+ regions:
+ EC.20:
+ combinedCode: EC.20
+ code: '20'
+ EC.19:
+ combinedCode: EC.19
+ code: '19'
+ EC.18:
+ combinedCode: EC.18
+ code: '18'
+ EC.17:
+ combinedCode: EC.17
+ code: '17'
+ EC.23:
+ combinedCode: EC.23
+ code: '23'
+ EC.15:
+ combinedCode: EC.15
+ code: '15'
+ EC.14:
+ combinedCode: EC.14
+ code: '14'
+ EC.13:
+ combinedCode: EC.13
+ code: '13'
+ EC.12:
+ combinedCode: EC.12
+ code: '12'
+ EC.11:
+ combinedCode: EC.11
+ code: '11'
+ EC.10:
+ combinedCode: EC.10
+ code: '10'
+ EC.01:
+ combinedCode: EC.01
+ code: '01'
+ EC.09:
+ combinedCode: EC.09
+ code: '09'
+ EC.08:
+ combinedCode: EC.08
+ code: '08'
+ EC.07:
+ combinedCode: EC.07
+ code: '07'
+ EC.06:
+ combinedCode: EC.06
+ code: '06'
+ EC.05:
+ combinedCode: EC.05
+ code: '05'
+ EC.04:
+ combinedCode: EC.04
+ code: '04'
+ EC.03:
+ combinedCode: EC.03
+ code: '03'
+ EC.02:
+ combinedCode: EC.02
+ code: '02'
+ EC.22:
+ combinedCode: EC.22
+ code: '22'
+ EC.24:
+ combinedCode: EC.24
+ code: '24'
+ EC.26:
+ combinedCode: EC.26
+ code: '26'
+ EC.25:
+ combinedCode: EC.25
+ code: '25'
+EE:
+ iso2Code: EE
+ iso3Code: EST
+ regions:
+ EE.21:
+ combinedCode: EE.21
+ code: '21'
+ EE.20:
+ combinedCode: EE.20
+ code: '20'
+ EE.19:
+ combinedCode: EE.19
+ code: '19'
+ EE.18:
+ combinedCode: EE.18
+ code: '18'
+ EE.14:
+ combinedCode: EE.14
+ code: '14'
+ EE.13:
+ combinedCode: EE.13
+ code: '13'
+ EE.12:
+ combinedCode: EE.12
+ code: '12'
+ EE.11:
+ combinedCode: EE.11
+ code: '11'
+ EE.08:
+ combinedCode: EE.08
+ code: '08'
+ EE.07:
+ combinedCode: EE.07
+ code: '07'
+ EE.05:
+ combinedCode: EE.05
+ code: '05'
+ EE.04:
+ combinedCode: EE.04
+ code: '04'
+ EE.03:
+ combinedCode: EE.03
+ code: '03'
+ EE.02:
+ combinedCode: EE.02
+ code: '02'
+ EE.01:
+ combinedCode: EE.01
+ code: '01'
+EG:
+ iso2Code: EG
+ iso3Code: EGY
+ regions:
+ EG.24:
+ combinedCode: EG.24
+ code: '24'
+ EG.27:
+ combinedCode: EG.27
+ code: '27'
+ EG.23:
+ combinedCode: EG.23
+ code: '23'
+ EG.22:
+ combinedCode: EG.22
+ code: '22'
+ EG.21:
+ combinedCode: EG.21
+ code: '21'
+ EG.26:
+ combinedCode: EG.26
+ code: '26'
+ EG.20:
+ combinedCode: EG.20
+ code: '20'
+ EG.19:
+ combinedCode: EG.19
+ code: '19'
+ EG.18:
+ combinedCode: EG.18
+ code: '18'
+ EG.17:
+ combinedCode: EG.17
+ code: '17'
+ EG.16:
+ combinedCode: EG.16
+ code: '16'
+ EG.15:
+ combinedCode: EG.15
+ code: '15'
+ EG.14:
+ combinedCode: EG.14
+ code: '14'
+ EG.13:
+ combinedCode: EG.13
+ code: '13'
+ EG.12:
+ combinedCode: EG.12
+ code: '12'
+ EG.11:
+ combinedCode: EG.11
+ code: '11'
+ EG.10:
+ combinedCode: EG.10
+ code: '10'
+ EG.09:
+ combinedCode: EG.09
+ code: '09'
+ EG.08:
+ combinedCode: EG.08
+ code: '08'
+ EG.07:
+ combinedCode: EG.07
+ code: '07'
+ EG.06:
+ combinedCode: EG.06
+ code: '06'
+ EG.05:
+ combinedCode: EG.05
+ code: '05'
+ EG.04:
+ combinedCode: EG.04
+ code: '04'
+ EG.03:
+ combinedCode: EG.03
+ code: '03'
+ EG.02:
+ combinedCode: EG.02
+ code: '02'
+ EG.01:
+ combinedCode: EG.01
+ code: '01'
+ EG.28:
+ combinedCode: EG.28
+ code: '28'
+EH:
+ iso2Code: EH
+ iso3Code: ESH
+ regions:
+ EH.CE:
+ combinedCode: EH.CE
+ code: CE
+ER:
+ iso2Code: ER
+ iso3Code: ERI
+ regions:
+ ER.01:
+ combinedCode: ER.01
+ code: '01'
+ ER.02:
+ combinedCode: ER.02
+ code: '02'
+ ER.03:
+ combinedCode: ER.03
+ code: '03'
+ ER.04:
+ combinedCode: ER.04
+ code: '04'
+ ER.05:
+ combinedCode: ER.05
+ code: '05'
+ ER.06:
+ combinedCode: ER.06
+ code: '06'
+ES:
+ iso2Code: ES
+ iso3Code: ESP
+ regions:
+ ES.31:
+ combinedCode: ES.31
+ code: '31'
+ ES.CE:
+ combinedCode: ES.CE
+ code: CE
+ ES.07:
+ combinedCode: ES.07
+ code: '07'
+ ES.51:
+ combinedCode: ES.51
+ code: '51'
+ ES.53:
+ combinedCode: ES.53
+ code: '53'
+ ES.54:
+ combinedCode: ES.54
+ code: '54'
+ ES.57:
+ combinedCode: ES.57
+ code: '57'
+ ES.60:
+ combinedCode: ES.60
+ code: '60'
+ ES.34:
+ combinedCode: ES.34
+ code: '34'
+ ES.32:
+ combinedCode: ES.32
+ code: '32'
+ ES.29:
+ combinedCode: ES.29
+ code: '29'
+ ES.27:
+ combinedCode: ES.27
+ code: '27'
+ ES.39:
+ combinedCode: ES.39
+ code: '39'
+ ES.52:
+ combinedCode: ES.52
+ code: '52'
+ ES.55:
+ combinedCode: ES.55
+ code: '55'
+ ES.56:
+ combinedCode: ES.56
+ code: '56'
+ ES.58:
+ combinedCode: ES.58
+ code: '58'
+ ES.59:
+ combinedCode: ES.59
+ code: '59'
+ ES.ML:
+ combinedCode: ES.ML
+ code: ML
+ET:
+ iso2Code: ET
+ iso3Code: ETH
+ regions:
+ ET.44:
+ combinedCode: ET.44
+ code: '44'
+ ET.45:
+ combinedCode: ET.45
+ code: '45'
+ ET.46:
+ combinedCode: ET.46
+ code: '46'
+ ET.47:
+ combinedCode: ET.47
+ code: '47'
+ ET.48:
+ combinedCode: ET.48
+ code: '48'
+ ET.49:
+ combinedCode: ET.49
+ code: '49'
+ ET.50:
+ combinedCode: ET.50
+ code: '50'
+ ET.51:
+ combinedCode: ET.51
+ code: '51'
+ ET.52:
+ combinedCode: ET.52
+ code: '52'
+ ET.53:
+ combinedCode: ET.53
+ code: '53'
+ ET.54:
+ combinedCode: ET.54
+ code: '54'
+FI:
+ iso2Code: FI
+ iso3Code: FIN
+ regions:
+ FI.08:
+ combinedCode: FI.08
+ code: '08'
+ FI.06:
+ combinedCode: FI.06
+ code: '06'
+ FI.13:
+ combinedCode: FI.13
+ code: '13'
+ FI.14:
+ combinedCode: FI.14
+ code: '14'
+ FI.15:
+ combinedCode: FI.15
+ code: '15'
+FJ:
+ iso2Code: FJ
+ iso3Code: FJI
+ regions:
+ FJ.05:
+ combinedCode: FJ.05
+ code: '05'
+ FJ.03:
+ combinedCode: FJ.03
+ code: '03'
+ FJ.01:
+ combinedCode: FJ.01
+ code: '01'
+ FJ.02:
+ combinedCode: FJ.02
+ code: '02'
+ FJ.04:
+ combinedCode: FJ.04
+ code: '04'
+FK:
+ iso2Code: FK
+ iso3Code: FLK
+ regions: { }
+FM:
+ iso2Code: FM
+ iso3Code: FSM
+ regions:
+ FM.04:
+ combinedCode: FM.04
+ code: '04'
+ FM.02:
+ combinedCode: FM.02
+ code: '02'
+ FM.01:
+ combinedCode: FM.01
+ code: '01'
+ FM.03:
+ combinedCode: FM.03
+ code: '03'
+FO:
+ iso2Code: FO
+ iso3Code: FRO
+ regions:
+ FO.VG:
+ combinedCode: FO.VG
+ code: VG
+ FO.SU:
+ combinedCode: FO.SU
+ code: SU
+ FO.ST:
+ combinedCode: FO.ST
+ code: ST
+ FO.SA:
+ combinedCode: FO.SA
+ code: SA
+ FO.NO:
+ combinedCode: FO.NO
+ code: NO
+ FO.OS:
+ combinedCode: FO.OS
+ code: OS
+FR:
+ iso2Code: FR
+ iso3Code: FRA
+ regions:
+ FR.B9:
+ combinedCode: FR.B9
+ code: B9
+ FR.B8:
+ combinedCode: FR.B8
+ code: B8
+ FR.B7:
+ combinedCode: FR.B7
+ code: B7
+ FR.B6:
+ combinedCode: FR.B6
+ code: B6
+ FR.B5:
+ combinedCode: FR.B5
+ code: B5
+ FR.B4:
+ combinedCode: FR.B4
+ code: B4
+ FR.B3:
+ combinedCode: FR.B3
+ code: B3
+ FR.B2:
+ combinedCode: FR.B2
+ code: B2
+ FR.B1:
+ combinedCode: FR.B1
+ code: B1
+ FR.A9:
+ combinedCode: FR.A9
+ code: A9
+ FR.A8:
+ combinedCode: FR.A8
+ code: A8
+ FR.A7:
+ combinedCode: FR.A7
+ code: A7
+ FR.A6:
+ combinedCode: FR.A6
+ code: A6
+ FR.A5:
+ combinedCode: FR.A5
+ code: A5
+ FR.A4:
+ combinedCode: FR.A4
+ code: A4
+ FR.A3:
+ combinedCode: FR.A3
+ code: A3
+ FR.A2:
+ combinedCode: FR.A2
+ code: A2
+ FR.A1:
+ combinedCode: FR.A1
+ code: A1
+ FR.99:
+ combinedCode: FR.99
+ code: '99'
+ FR.98:
+ combinedCode: FR.98
+ code: '98'
+ FR.97:
+ combinedCode: FR.97
+ code: '97'
+ FR.C1:
+ combinedCode: FR.C1
+ code: C1
+GA:
+ iso2Code: GA
+ iso3Code: GAB
+ regions:
+ GA.09:
+ combinedCode: GA.09
+ code: '09'
+ GA.08:
+ combinedCode: GA.08
+ code: '08'
+ GA.07:
+ combinedCode: GA.07
+ code: '07'
+ GA.06:
+ combinedCode: GA.06
+ code: '06'
+ GA.05:
+ combinedCode: GA.05
+ code: '05'
+ GA.04:
+ combinedCode: GA.04
+ code: '04'
+ GA.03:
+ combinedCode: GA.03
+ code: '03'
+ GA.02:
+ combinedCode: GA.02
+ code: '02'
+ GA.01:
+ combinedCode: GA.01
+ code: '01'
+GB:
+ iso2Code: GB
+ iso3Code: GBR
+ regions:
+ GB.WLS:
+ combinedCode: GB.WLS
+ code: WLS
+ GB.SCT:
+ combinedCode: GB.SCT
+ code: SCT
+ GB.NIR:
+ combinedCode: GB.NIR
+ code: NIR
+ GB.ENG:
+ combinedCode: GB.ENG
+ code: ENG
+GD:
+ iso2Code: GD
+ iso3Code: GRD
+ regions:
+ GD.06:
+ combinedCode: GD.06
+ code: '06'
+ GD.05:
+ combinedCode: GD.05
+ code: '05'
+ GD.04:
+ combinedCode: GD.04
+ code: '04'
+ GD.03:
+ combinedCode: GD.03
+ code: '03'
+ GD.02:
+ combinedCode: GD.02
+ code: '02'
+ GD.01:
+ combinedCode: GD.01
+ code: '01'
+ GD.10:
+ combinedCode: GD.10
+ code: '10'
+GE:
+ iso2Code: GE
+ iso3Code: GEO
+ regions:
+ GE.51:
+ combinedCode: GE.51
+ code: '51'
+ GE.04:
+ combinedCode: GE.04
+ code: '04'
+ GE.68:
+ combinedCode: GE.68
+ code: '68'
+ GE.67:
+ combinedCode: GE.67
+ code: '67'
+ GE.65:
+ combinedCode: GE.65
+ code: '65'
+ GE.66:
+ combinedCode: GE.66
+ code: '66'
+ GE.73:
+ combinedCode: GE.73
+ code: '73'
+ GE.69:
+ combinedCode: GE.69
+ code: '69'
+ GE.70:
+ combinedCode: GE.70
+ code: '70'
+ GE.71:
+ combinedCode: GE.71
+ code: '71'
+ GE.72:
+ combinedCode: GE.72
+ code: '72'
+ GE.02:
+ combinedCode: GE.02
+ code: '02'
+GF:
+ iso2Code: GF
+ iso3Code: GUF
+ regions:
+ GF.GF:
+ combinedCode: GF.GF
+ code: GF
+GG:
+ iso2Code: GG
+ iso3Code: GGY
+ regions: { }
+GH:
+ iso2Code: GH
+ iso3Code: GHA
+ regions:
+ GH.09:
+ combinedCode: GH.09
+ code: '09'
+ GH.08:
+ combinedCode: GH.08
+ code: '08'
+ GH.11:
+ combinedCode: GH.11
+ code: '11'
+ GH.10:
+ combinedCode: GH.10
+ code: '10'
+ GH.06:
+ combinedCode: GH.06
+ code: '06'
+ GH.01:
+ combinedCode: GH.01
+ code: '01'
+ GH.05:
+ combinedCode: GH.05
+ code: '05'
+ GH.04:
+ combinedCode: GH.04
+ code: '04'
+ GH.03:
+ combinedCode: GH.03
+ code: '03'
+ GH.02:
+ combinedCode: GH.02
+ code: '02'
+GI:
+ iso2Code: GI
+ iso3Code: GIB
+ regions: { }
+GL:
+ iso2Code: GL
+ iso3Code: GRL
+ regions:
+ GL.05:
+ combinedCode: GL.05
+ code: '05'
+ GL.04:
+ combinedCode: GL.04
+ code: '04'
+ GL.06:
+ combinedCode: GL.06
+ code: '06'
+ GL.07:
+ combinedCode: GL.07
+ code: '07'
+GM:
+ iso2Code: GM
+ iso3Code: GMB
+ regions:
+ GM.05:
+ combinedCode: GM.05
+ code: '05'
+ GM.04:
+ combinedCode: GM.04
+ code: '04'
+ GM.07:
+ combinedCode: GM.07
+ code: '07'
+ GM.03:
+ combinedCode: GM.03
+ code: '03'
+ GM.02:
+ combinedCode: GM.02
+ code: '02'
+ GM.01:
+ combinedCode: GM.01
+ code: '01'
+GN:
+ iso2Code: GN
+ iso3Code: GIN
+ regions:
+ GN.04:
+ combinedCode: GN.04
+ code: '04'
+ GN.B:
+ combinedCode: GN.B
+ code: B
+ GN.F:
+ combinedCode: GN.F
+ code: F
+ GN.K:
+ combinedCode: GN.K
+ code: K
+ GN.D:
+ combinedCode: GN.D
+ code: D
+ GN.L:
+ combinedCode: GN.L
+ code: L
+ GN.M:
+ combinedCode: GN.M
+ code: M
+ GN.N:
+ combinedCode: GN.N
+ code: N
+GP:
+ iso2Code: GP
+ iso3Code: GLP
+ regions:
+ GP.GP:
+ combinedCode: GP.GP
+ code: GP
+GQ:
+ iso2Code: GQ
+ iso3Code: GNQ
+ regions:
+ GQ.03:
+ combinedCode: GQ.03
+ code: '03'
+ GQ.04:
+ combinedCode: GQ.04
+ code: '04'
+ GQ.05:
+ combinedCode: GQ.05
+ code: '05'
+ GQ.06:
+ combinedCode: GQ.06
+ code: '06'
+ GQ.07:
+ combinedCode: GQ.07
+ code: '07'
+ GQ.08:
+ combinedCode: GQ.08
+ code: '08'
+ GQ.09:
+ combinedCode: GQ.09
+ code: '09'
+GR:
+ iso2Code: GR
+ iso3Code: GRC
+ regions:
+ GR.736572:
+ combinedCode: GR.736572
+ code: '736572'
+ GR.ESYE31:
+ combinedCode: GR.ESYE31
+ code: ESYE31
+ GR.ESYE24:
+ combinedCode: GR.ESYE24
+ code: ESYE24
+ GR.ESYE12:
+ combinedCode: GR.ESYE12
+ code: ESYE12
+ GR.ESYE43:
+ combinedCode: GR.ESYE43
+ code: ESYE43
+ GR.ESYE11:
+ combinedCode: GR.ESYE11
+ code: ESYE11
+ GR.ESYE21:
+ combinedCode: GR.ESYE21
+ code: ESYE21
+ GR.ESYE22:
+ combinedCode: GR.ESYE22
+ code: ESYE22
+ GR.ESYE41:
+ combinedCode: GR.ESYE41
+ code: ESYE41
+ GR.ESYE25:
+ combinedCode: GR.ESYE25
+ code: ESYE25
+ GR.ESYE42:
+ combinedCode: GR.ESYE42
+ code: ESYE42
+ GR.ESYE14:
+ combinedCode: GR.ESYE14
+ code: ESYE14
+ GR.ESYE23:
+ combinedCode: GR.ESYE23
+ code: ESYE23
+ GR.ESYE13:
+ combinedCode: GR.ESYE13
+ code: ESYE13
+GS:
+ iso2Code: GS
+ iso3Code: SGS
+ regions: { }
+GT:
+ iso2Code: GT
+ iso3Code: GTM
+ regions:
+ GT.22:
+ combinedCode: GT.22
+ code: '22'
+ GT.21:
+ combinedCode: GT.21
+ code: '21'
+ GT.20:
+ combinedCode: GT.20
+ code: '20'
+ GT.19:
+ combinedCode: GT.19
+ code: '19'
+ GT.18:
+ combinedCode: GT.18
+ code: '18'
+ GT.17:
+ combinedCode: GT.17
+ code: '17'
+ GT.16:
+ combinedCode: GT.16
+ code: '16'
+ GT.15:
+ combinedCode: GT.15
+ code: '15'
+ GT.14:
+ combinedCode: GT.14
+ code: '14'
+ GT.13:
+ combinedCode: GT.13
+ code: '13'
+ GT.12:
+ combinedCode: GT.12
+ code: '12'
+ GT.11:
+ combinedCode: GT.11
+ code: '11'
+ GT.10:
+ combinedCode: GT.10
+ code: '10'
+ GT.09:
+ combinedCode: GT.09
+ code: '09'
+ GT.08:
+ combinedCode: GT.08
+ code: '08'
+ GT.07:
+ combinedCode: GT.07
+ code: '07'
+ GT.06:
+ combinedCode: GT.06
+ code: '06'
+ GT.05:
+ combinedCode: GT.05
+ code: '05'
+ GT.04:
+ combinedCode: GT.04
+ code: '04'
+ GT.03:
+ combinedCode: GT.03
+ code: '03'
+ GT.02:
+ combinedCode: GT.02
+ code: '02'
+ GT.01:
+ combinedCode: GT.01
+ code: '01'
+GU:
+ iso2Code: GU
+ iso3Code: GUM
+ regions:
+ GU.PI:
+ combinedCode: GU.PI
+ code: PI
+ GU.SR:
+ combinedCode: GU.SR
+ code: SR
+ GU.SJ:
+ combinedCode: GU.SJ
+ code: SJ
+ GU.TF:
+ combinedCode: GU.TF
+ code: TF
+ GU.TM:
+ combinedCode: GU.TM
+ code: TM
+ GU.UM:
+ combinedCode: GU.UM
+ code: UM
+ GU.YG:
+ combinedCode: GU.YG
+ code: YG
+ GU.YN:
+ combinedCode: GU.YN
+ code: YN
+ GU.ME:
+ combinedCode: GU.ME
+ code: ME
+ GU.MA:
+ combinedCode: GU.MA
+ code: MA
+ GU.AH:
+ combinedCode: GU.AH
+ code: AH
+ GU.CP:
+ combinedCode: GU.CP
+ code: CP
+ GU.AS:
+ combinedCode: GU.AS
+ code: AS
+ GU.AT:
+ combinedCode: GU.AT
+ code: AT
+ GU.DD:
+ combinedCode: GU.DD
+ code: DD
+ GU.BA:
+ combinedCode: GU.BA
+ code: BA
+ GU.AN:
+ combinedCode: GU.AN
+ code: AN
+ GU.IN:
+ combinedCode: GU.IN
+ code: IN
+ GU.MT:
+ combinedCode: GU.MT
+ code: MT
+GW:
+ iso2Code: GW
+ iso3Code: GNB
+ regions:
+ GW.07:
+ combinedCode: GW.07
+ code: '07'
+ GW.02:
+ combinedCode: GW.02
+ code: '02'
+ GW.04:
+ combinedCode: GW.04
+ code: '04'
+ GW.10:
+ combinedCode: GW.10
+ code: '10'
+ GW.06:
+ combinedCode: GW.06
+ code: '06'
+ GW.05:
+ combinedCode: GW.05
+ code: '05'
+ GW.11:
+ combinedCode: GW.11
+ code: '11'
+ GW.12:
+ combinedCode: GW.12
+ code: '12'
+ GW.01:
+ combinedCode: GW.01
+ code: '01'
+GY:
+ iso2Code: GY
+ iso3Code: GUY
+ regions:
+ GY.19:
+ combinedCode: GY.19
+ code: '19'
+ GY.18:
+ combinedCode: GY.18
+ code: '18'
+ GY.17:
+ combinedCode: GY.17
+ code: '17'
+ GY.16:
+ combinedCode: GY.16
+ code: '16'
+ GY.15:
+ combinedCode: GY.15
+ code: '15'
+ GY.14:
+ combinedCode: GY.14
+ code: '14'
+ GY.13:
+ combinedCode: GY.13
+ code: '13'
+ GY.12:
+ combinedCode: GY.12
+ code: '12'
+ GY.11:
+ combinedCode: GY.11
+ code: '11'
+ GY.10:
+ combinedCode: GY.10
+ code: '10'
+HK:
+ iso2Code: HK
+ iso3Code: HKG
+ regions:
+ HK.NYL:
+ combinedCode: HK.NYL
+ code: NYL
+ HK.NTW:
+ combinedCode: HK.NTW
+ code: NTW
+ HK.NTP:
+ combinedCode: HK.NTP
+ code: NTP
+ HK.NSK:
+ combinedCode: HK.NSK
+ code: NSK
+ HK.NIS:
+ combinedCode: HK.NIS
+ code: NIS
+ HK.HCW:
+ combinedCode: HK.HCW
+ code: HCW
+ HK.HWC:
+ combinedCode: HK.HWC
+ code: HWC
+ HK.HEA:
+ combinedCode: HK.HEA
+ code: HEA
+ HK.HSO:
+ combinedCode: HK.HSO
+ code: HSO
+ HK.KYT:
+ combinedCode: HK.KYT
+ code: KYT
+ HK.KSS:
+ combinedCode: HK.KSS
+ code: KSS
+ HK.KKC:
+ combinedCode: HK.KKC
+ code: KKC
+ HK.KWT:
+ combinedCode: HK.KWT
+ code: KWT
+ HK.KKT:
+ combinedCode: HK.KKT
+ code: KKT
+ HK.NKT:
+ combinedCode: HK.NKT
+ code: NKT
+ HK.NTM:
+ combinedCode: HK.NTM
+ code: NTM
+ HK.NNO:
+ combinedCode: HK.NNO
+ code: NNO
+ HK.NST:
+ combinedCode: HK.NST
+ code: NST
+HM:
+ iso2Code: HM
+ iso3Code: HMD
+ regions: { }
+HN:
+ iso2Code: HN
+ iso3Code: HND
+ regions:
+ HN.18:
+ combinedCode: HN.18
+ code: '18'
+ HN.17:
+ combinedCode: HN.17
+ code: '17'
+ HN.16:
+ combinedCode: HN.16
+ code: '16'
+ HN.15:
+ combinedCode: HN.15
+ code: '15'
+ HN.14:
+ combinedCode: HN.14
+ code: '14'
+ HN.13:
+ combinedCode: HN.13
+ code: '13'
+ HN.12:
+ combinedCode: HN.12
+ code: '12'
+ HN.11:
+ combinedCode: HN.11
+ code: '11'
+ HN.10:
+ combinedCode: HN.10
+ code: '10'
+ HN.09:
+ combinedCode: HN.09
+ code: '09'
+ HN.08:
+ combinedCode: HN.08
+ code: '08'
+ HN.07:
+ combinedCode: HN.07
+ code: '07'
+ HN.06:
+ combinedCode: HN.06
+ code: '06'
+ HN.05:
+ combinedCode: HN.05
+ code: '05'
+ HN.04:
+ combinedCode: HN.04
+ code: '04'
+ HN.03:
+ combinedCode: HN.03
+ code: '03'
+ HN.02:
+ combinedCode: HN.02
+ code: '02'
+ HN.01:
+ combinedCode: HN.01
+ code: '01'
+HR:
+ iso2Code: HR
+ iso3Code: HRV
+ regions:
+ HR.01:
+ combinedCode: HR.01
+ code: '01'
+ HR.02:
+ combinedCode: HR.02
+ code: '02'
+ HR.03:
+ combinedCode: HR.03
+ code: '03'
+ HR.04:
+ combinedCode: HR.04
+ code: '04'
+ HR.05:
+ combinedCode: HR.05
+ code: '05'
+ HR.06:
+ combinedCode: HR.06
+ code: '06'
+ HR.07:
+ combinedCode: HR.07
+ code: '07'
+ HR.08:
+ combinedCode: HR.08
+ code: '08'
+ HR.09:
+ combinedCode: HR.09
+ code: '09'
+ HR.10:
+ combinedCode: HR.10
+ code: '10'
+ HR.11:
+ combinedCode: HR.11
+ code: '11'
+ HR.12:
+ combinedCode: HR.12
+ code: '12'
+ HR.13:
+ combinedCode: HR.13
+ code: '13'
+ HR.14:
+ combinedCode: HR.14
+ code: '14'
+ HR.15:
+ combinedCode: HR.15
+ code: '15'
+ HR.16:
+ combinedCode: HR.16
+ code: '16'
+ HR.18:
+ combinedCode: HR.18
+ code: '18'
+ HR.19:
+ combinedCode: HR.19
+ code: '19'
+ HR.20:
+ combinedCode: HR.20
+ code: '20'
+ HR.21:
+ combinedCode: HR.21
+ code: '21'
+ HR.17:
+ combinedCode: HR.17
+ code: '17'
+HT:
+ iso2Code: HT
+ iso3Code: HTI
+ regions:
+ HT.13:
+ combinedCode: HT.13
+ code: '13'
+ HT.12:
+ combinedCode: HT.12
+ code: '12'
+ HT.11:
+ combinedCode: HT.11
+ code: '11'
+ HT.03:
+ combinedCode: HT.03
+ code: '03'
+ HT.10:
+ combinedCode: HT.10
+ code: '10'
+ HT.09:
+ combinedCode: HT.09
+ code: '09'
+ HT.14:
+ combinedCode: HT.14
+ code: '14'
+ HT.07:
+ combinedCode: HT.07
+ code: '07'
+ HT.06:
+ combinedCode: HT.06
+ code: '06'
+ HT.15:
+ combinedCode: HT.15
+ code: '15'
+HU:
+ iso2Code: HU
+ iso3Code: HUN
+ regions:
+ HU.18:
+ combinedCode: HU.18
+ code: '18'
+ HU.20:
+ combinedCode: HU.20
+ code: '20'
+ HU.11:
+ combinedCode: HU.11
+ code: '11'
+ HU.10:
+ combinedCode: HU.10
+ code: '10'
+ HU.06:
+ combinedCode: HU.06
+ code: '06'
+ HU.04:
+ combinedCode: HU.04
+ code: '04'
+ HU.03:
+ combinedCode: HU.03
+ code: '03'
+ HU.24:
+ combinedCode: HU.24
+ code: '24'
+ HU.23:
+ combinedCode: HU.23
+ code: '23'
+ HU.22:
+ combinedCode: HU.22
+ code: '22'
+ HU.21:
+ combinedCode: HU.21
+ code: '21'
+ HU.17:
+ combinedCode: HU.17
+ code: '17'
+ HU.16:
+ combinedCode: HU.16
+ code: '16'
+ HU.14:
+ combinedCode: HU.14
+ code: '14'
+ HU.12:
+ combinedCode: HU.12
+ code: '12'
+ HU.09:
+ combinedCode: HU.09
+ code: '09'
+ HU.08:
+ combinedCode: HU.08
+ code: '08'
+ HU.05:
+ combinedCode: HU.05
+ code: '05'
+ HU.02:
+ combinedCode: HU.02
+ code: '02'
+ HU.01:
+ combinedCode: HU.01
+ code: '01'
+ID:
+ iso2Code: ID
+ iso3Code: IDN
+ regions:
+ ID.26:
+ combinedCode: ID.26
+ code: '26'
+ ID.01:
+ combinedCode: ID.01
+ code: '01'
+ ID.10:
+ combinedCode: ID.10
+ code: '10'
+ ID.32:
+ combinedCode: ID.32
+ code: '32'
+ ID.24:
+ combinedCode: ID.24
+ code: '24'
+ ID.31:
+ combinedCode: ID.31
+ code: '31'
+ ID.22:
+ combinedCode: ID.22
+ code: '22'
+ ID.21:
+ combinedCode: ID.21
+ code: '21'
+ ID.38:
+ combinedCode: ID.38
+ code: '38'
+ ID.37:
+ combinedCode: ID.37
+ code: '37'
+ ID.18:
+ combinedCode: ID.18
+ code: '18'
+ ID.17:
+ combinedCode: ID.17
+ code: '17'
+ ID.28:
+ combinedCode: ID.28
+ code: '28'
+ ID.15:
+ combinedCode: ID.15
+ code: '15'
+ ID.14:
+ combinedCode: ID.14
+ code: '14'
+ ID.13:
+ combinedCode: ID.13
+ code: '13'
+ ID.12:
+ combinedCode: ID.12
+ code: '12'
+ ID.11:
+ combinedCode: ID.11
+ code: '11'
+ ID.08:
+ combinedCode: ID.08
+ code: '08'
+ ID.07:
+ combinedCode: ID.07
+ code: '07'
+ ID.30:
+ combinedCode: ID.30
+ code: '30'
+ ID.05:
+ combinedCode: ID.05
+ code: '05'
+ ID.04:
+ combinedCode: ID.04
+ code: '04'
+ ID.36:
+ combinedCode: ID.36
+ code: '36'
+ ID.03:
+ combinedCode: ID.03
+ code: '03'
+ ID.02:
+ combinedCode: ID.02
+ code: '02'
+ ID.33:
+ combinedCode: ID.33
+ code: '33'
+ ID.34:
+ combinedCode: ID.34
+ code: '34'
+ ID.35:
+ combinedCode: ID.35
+ code: '35'
+ ID.29:
+ combinedCode: ID.29
+ code: '29'
+ ID.39:
+ combinedCode: ID.39
+ code: '39'
+ ID.41:
+ combinedCode: ID.41
+ code: '41'
+ ID.40:
+ combinedCode: ID.40
+ code: '40'
+IE:
+ iso2Code: IE
+ iso3Code: IRL
+ regions:
+ IE.C:
+ combinedCode: IE.C
+ code: C
+ IE.L:
+ combinedCode: IE.L
+ code: L
+ IE.M:
+ combinedCode: IE.M
+ code: M
+ IE.U:
+ combinedCode: IE.U
+ code: U
+IL:
+ iso2Code: IL
+ iso3Code: ISR
+ regions:
+ IL.06:
+ combinedCode: IL.06
+ code: '06'
+ IL.05:
+ combinedCode: IL.05
+ code: '05'
+ IL.04:
+ combinedCode: IL.04
+ code: '04'
+ IL.03:
+ combinedCode: IL.03
+ code: '03'
+ IL.02:
+ combinedCode: IL.02
+ code: '02'
+ IL.01:
+ combinedCode: IL.01
+ code: '01'
+IM:
+ iso2Code: IM
+ iso3Code: IMN
+ regions: { }
+IN:
+ iso2Code: IN
+ iso3Code: IND
+ regions:
+ IN.28:
+ combinedCode: IN.28
+ code: '28'
+ IN.36:
+ combinedCode: IN.36
+ code: '36'
+ IN.26:
+ combinedCode: IN.26
+ code: '26'
+ IN.25:
+ combinedCode: IN.25
+ code: '25'
+ IN.29:
+ combinedCode: IN.29
+ code: '29'
+ IN.24:
+ combinedCode: IN.24
+ code: '24'
+ IN.23:
+ combinedCode: IN.23
+ code: '23'
+ IN.22:
+ combinedCode: IN.22
+ code: '22'
+ IN.21:
+ combinedCode: IN.21
+ code: '21'
+ IN.20:
+ combinedCode: IN.20
+ code: '20'
+ IN.31:
+ combinedCode: IN.31
+ code: '31'
+ IN.18:
+ combinedCode: IN.18
+ code: '18'
+ IN.17:
+ combinedCode: IN.17
+ code: '17'
+ IN.16:
+ combinedCode: IN.16
+ code: '16'
+ IN.35:
+ combinedCode: IN.35
+ code: '35'
+ IN.14:
+ combinedCode: IN.14
+ code: '14'
+ IN.13:
+ combinedCode: IN.13
+ code: '13'
+ IN.19:
+ combinedCode: IN.19
+ code: '19'
+ IN.12:
+ combinedCode: IN.12
+ code: '12'
+ IN.11:
+ combinedCode: IN.11
+ code: '11'
+ IN.10:
+ combinedCode: IN.10
+ code: '10'
+ IN.09:
+ combinedCode: IN.09
+ code: '09'
+ IN.32:
+ combinedCode: IN.32
+ code: '32'
+ IN.33:
+ combinedCode: IN.33
+ code: '33'
+ IN.07:
+ combinedCode: IN.07
+ code: '07'
+ IN.06:
+ combinedCode: IN.06
+ code: '06'
+ IN.05:
+ combinedCode: IN.05
+ code: '05'
+ IN.34:
+ combinedCode: IN.34
+ code: '34'
+ IN.03:
+ combinedCode: IN.03
+ code: '03'
+ IN.30:
+ combinedCode: IN.30
+ code: '30'
+ IN.02:
+ combinedCode: IN.02
+ code: '02'
+ IN.01:
+ combinedCode: IN.01
+ code: '01'
+ IN.37:
+ combinedCode: IN.37
+ code: '37'
+ IN.38:
+ combinedCode: IN.38
+ code: '38'
+ IN.39:
+ combinedCode: IN.39
+ code: '39'
+IO:
+ iso2Code: IO
+ iso3Code: IOT
+ regions: { }
+IQ:
+ iso2Code: IQ
+ iso3Code: IRQ
+ regions:
+ IQ.02:
+ combinedCode: IQ.02
+ code: '02'
+ IQ.16:
+ combinedCode: IQ.16
+ code: '16'
+ IQ.18:
+ combinedCode: IQ.18
+ code: '18'
+ IQ.15:
+ combinedCode: IQ.15
+ code: '15'
+ IQ.14:
+ combinedCode: IQ.14
+ code: '14'
+ IQ.12:
+ combinedCode: IQ.12
+ code: '12'
+ IQ.11:
+ combinedCode: IQ.11
+ code: '11'
+ IQ.10:
+ combinedCode: IQ.10
+ code: '10'
+ IQ.09:
+ combinedCode: IQ.09
+ code: '09'
+ IQ.08:
+ combinedCode: IQ.08
+ code: '08'
+ IQ.07:
+ combinedCode: IQ.07
+ code: '07'
+ IQ.06:
+ combinedCode: IQ.06
+ code: '06'
+ IQ.13:
+ combinedCode: IQ.13
+ code: '13'
+ IQ.05:
+ combinedCode: IQ.05
+ code: '05'
+ IQ.17:
+ combinedCode: IQ.17
+ code: '17'
+ IQ.04:
+ combinedCode: IQ.04
+ code: '04'
+ IQ.03:
+ combinedCode: IQ.03
+ code: '03'
+ IQ.01:
+ combinedCode: IQ.01
+ code: '01'
+IR:
+ iso2Code: IR
+ iso3Code: IRN
+ regions:
+ IR.26:
+ combinedCode: IR.26
+ code: '26'
+ IR.36:
+ combinedCode: IR.36
+ code: '36'
+ IR.40:
+ combinedCode: IR.40
+ code: '40'
+ IR.25:
+ combinedCode: IR.25
+ code: '25'
+ IR.35:
+ combinedCode: IR.35
+ code: '35'
+ IR.34:
+ combinedCode: IR.34
+ code: '34'
+ IR.23:
+ combinedCode: IR.23
+ code: '23'
+ IR.16:
+ combinedCode: IR.16
+ code: '16'
+ IR.05:
+ combinedCode: IR.05
+ code: '05'
+ IR.15:
+ combinedCode: IR.15
+ code: '15'
+ IR.13:
+ combinedCode: IR.13
+ code: '13'
+ IR.29:
+ combinedCode: IR.29
+ code: '29'
+ IR.10:
+ combinedCode: IR.10
+ code: '10'
+ IR.11:
+ combinedCode: IR.11
+ code: '11'
+ IR.09:
+ combinedCode: IR.09
+ code: '09'
+ IR.08:
+ combinedCode: IR.08
+ code: '08'
+ IR.07:
+ combinedCode: IR.07
+ code: '07'
+ IR.03:
+ combinedCode: IR.03
+ code: '03'
+ IR.22:
+ combinedCode: IR.22
+ code: '22'
+ IR.33:
+ combinedCode: IR.33
+ code: '33'
+ IR.01:
+ combinedCode: IR.01
+ code: '01'
+ IR.32:
+ combinedCode: IR.32
+ code: '32'
+ IR.28:
+ combinedCode: IR.28
+ code: '28'
+ IR.37:
+ combinedCode: IR.37
+ code: '37'
+ IR.38:
+ combinedCode: IR.38
+ code: '38'
+ IR.39:
+ combinedCode: IR.39
+ code: '39'
+ IR.04:
+ combinedCode: IR.04
+ code: '04'
+ IR.41:
+ combinedCode: IR.41
+ code: '41'
+ IR.42:
+ combinedCode: IR.42
+ code: '42'
+ IR.43:
+ combinedCode: IR.43
+ code: '43'
+ IR.44:
+ combinedCode: IR.44
+ code: '44'
+IS:
+ iso2Code: IS
+ iso3Code: ISL
+ regions:
+ IS.41:
+ combinedCode: IS.41
+ code: '41'
+ IS.40:
+ combinedCode: IS.40
+ code: '40'
+ IS.38:
+ combinedCode: IS.38
+ code: '38'
+ IS.42:
+ combinedCode: IS.42
+ code: '42'
+ IS.39:
+ combinedCode: IS.39
+ code: '39'
+ IS.43:
+ combinedCode: IS.43
+ code: '43'
+ IS.45:
+ combinedCode: IS.45
+ code: '45'
+ IS.44:
+ combinedCode: IS.44
+ code: '44'
+IT:
+ iso2Code: IT
+ iso3Code: ITA
+ regions:
+ IT.15:
+ combinedCode: IT.15
+ code: '15'
+ IT.14:
+ combinedCode: IT.14
+ code: '14'
+ IT.03:
+ combinedCode: IT.03
+ code: '03'
+ IT.20:
+ combinedCode: IT.20
+ code: '20'
+ IT.19:
+ combinedCode: IT.19
+ code: '19'
+ IT.18:
+ combinedCode: IT.18
+ code: '18'
+ IT.17:
+ combinedCode: IT.17
+ code: '17'
+ IT.16:
+ combinedCode: IT.16
+ code: '16'
+ IT.13:
+ combinedCode: IT.13
+ code: '13'
+ IT.12:
+ combinedCode: IT.12
+ code: '12'
+ IT.11:
+ combinedCode: IT.11
+ code: '11'
+ IT.10:
+ combinedCode: IT.10
+ code: '10'
+ IT.09:
+ combinedCode: IT.09
+ code: '09'
+ IT.08:
+ combinedCode: IT.08
+ code: '08'
+ IT.07:
+ combinedCode: IT.07
+ code: '07'
+ IT.06:
+ combinedCode: IT.06
+ code: '06'
+ IT.05:
+ combinedCode: IT.05
+ code: '05'
+ IT.04:
+ combinedCode: IT.04
+ code: '04'
+ IT.02:
+ combinedCode: IT.02
+ code: '02'
+ IT.01:
+ combinedCode: IT.01
+ code: '01'
+JE:
+ iso2Code: JE
+ iso3Code: JEY
+ regions: { }
+JM:
+ iso2Code: JM
+ iso3Code: JAM
+ regions:
+ JM.16:
+ combinedCode: JM.16
+ code: '16'
+ JM.15:
+ combinedCode: JM.15
+ code: '15'
+ JM.14:
+ combinedCode: JM.14
+ code: '14'
+ JM.13:
+ combinedCode: JM.13
+ code: '13'
+ JM.12:
+ combinedCode: JM.12
+ code: '12'
+ JM.11:
+ combinedCode: JM.11
+ code: '11'
+ JM.10:
+ combinedCode: JM.10
+ code: '10'
+ JM.09:
+ combinedCode: JM.09
+ code: '09'
+ JM.08:
+ combinedCode: JM.08
+ code: '08'
+ JM.07:
+ combinedCode: JM.07
+ code: '07'
+ JM.04:
+ combinedCode: JM.04
+ code: '04'
+ JM.17:
+ combinedCode: JM.17
+ code: '17'
+ JM.02:
+ combinedCode: JM.02
+ code: '02'
+ JM.01:
+ combinedCode: JM.01
+ code: '01'
+JO:
+ iso2Code: JO
+ iso3Code: JOR
+ regions:
+ JO.19:
+ combinedCode: JO.19
+ code: '19'
+ JO.18:
+ combinedCode: JO.18
+ code: '18'
+ JO.17:
+ combinedCode: JO.17
+ code: '17'
+ JO.12:
+ combinedCode: JO.12
+ code: '12'
+ JO.16:
+ combinedCode: JO.16
+ code: '16'
+ JO.15:
+ combinedCode: JO.15
+ code: '15'
+ JO.09:
+ combinedCode: JO.09
+ code: '09'
+ JO.02:
+ combinedCode: JO.02
+ code: '02'
+ JO.20:
+ combinedCode: JO.20
+ code: '20'
+ JO.22:
+ combinedCode: JO.22
+ code: '22'
+ JO.21:
+ combinedCode: JO.21
+ code: '21'
+ JO.23:
+ combinedCode: JO.23
+ code: '23'
+JP:
+ iso2Code: JP
+ iso3Code: JPN
+ regions:
+ JP.46:
+ combinedCode: JP.46
+ code: '46'
+ JP.45:
+ combinedCode: JP.45
+ code: '45'
+ JP.43:
+ combinedCode: JP.43
+ code: '43'
+ JP.42:
+ combinedCode: JP.42
+ code: '42'
+ JP.41:
+ combinedCode: JP.41
+ code: '41'
+ JP.40:
+ combinedCode: JP.40
+ code: '40'
+ JP.39:
+ combinedCode: JP.39
+ code: '39'
+ JP.38:
+ combinedCode: JP.38
+ code: '38'
+ JP.37:
+ combinedCode: JP.37
+ code: '37'
+ JP.36:
+ combinedCode: JP.36
+ code: '36'
+ JP.35:
+ combinedCode: JP.35
+ code: '35'
+ JP.34:
+ combinedCode: JP.34
+ code: '34'
+ JP.33:
+ combinedCode: JP.33
+ code: '33'
+ JP.32:
+ combinedCode: JP.32
+ code: '32'
+ JP.47:
+ combinedCode: JP.47
+ code: '47'
+ JP.31:
+ combinedCode: JP.31
+ code: '31'
+ JP.30:
+ combinedCode: JP.30
+ code: '30'
+ JP.29:
+ combinedCode: JP.29
+ code: '29'
+ JP.28:
+ combinedCode: JP.28
+ code: '28'
+ JP.27:
+ combinedCode: JP.27
+ code: '27'
+ JP.26:
+ combinedCode: JP.26
+ code: '26'
+ JP.25:
+ combinedCode: JP.25
+ code: '25'
+ JP.23:
+ combinedCode: JP.23
+ code: '23'
+ JP.22:
+ combinedCode: JP.22
+ code: '22'
+ JP.21:
+ combinedCode: JP.21
+ code: '21'
+ JP.20:
+ combinedCode: JP.20
+ code: '20'
+ JP.19:
+ combinedCode: JP.19
+ code: '19'
+ JP.18:
+ combinedCode: JP.18
+ code: '18'
+ JP.17:
+ combinedCode: JP.17
+ code: '17'
+ JP.15:
+ combinedCode: JP.15
+ code: '15'
+ JP.13:
+ combinedCode: JP.13
+ code: '13'
+ JP.11:
+ combinedCode: JP.11
+ code: '11'
+ JP.10:
+ combinedCode: JP.10
+ code: '10'
+ JP.09:
+ combinedCode: JP.09
+ code: '09'
+ JP.07:
+ combinedCode: JP.07
+ code: '07'
+ JP.06:
+ combinedCode: JP.06
+ code: '06'
+ JP.05:
+ combinedCode: JP.05
+ code: '05'
+ JP.01:
+ combinedCode: JP.01
+ code: '01'
+ JP.44:
+ combinedCode: JP.44
+ code: '44'
+ JP.24:
+ combinedCode: JP.24
+ code: '24'
+ JP.16:
+ combinedCode: JP.16
+ code: '16'
+ JP.14:
+ combinedCode: JP.14
+ code: '14'
+ JP.08:
+ combinedCode: JP.08
+ code: '08'
+ JP.04:
+ combinedCode: JP.04
+ code: '04'
+ JP.02:
+ combinedCode: JP.02
+ code: '02'
+ JP.12:
+ combinedCode: JP.12
+ code: '12'
+ JP.03:
+ combinedCode: JP.03
+ code: '03'
+KE:
+ iso2Code: KE
+ iso3Code: KEN
+ regions:
+ KE.55:
+ combinedCode: KE.55
+ code: '55'
+ KE.54:
+ combinedCode: KE.54
+ code: '54'
+ KE.52:
+ combinedCode: KE.52
+ code: '52'
+ KE.51:
+ combinedCode: KE.51
+ code: '51'
+ KE.50:
+ combinedCode: KE.50
+ code: '50'
+ KE.49:
+ combinedCode: KE.49
+ code: '49'
+ KE.48:
+ combinedCode: KE.48
+ code: '48'
+ KE.46:
+ combinedCode: KE.46
+ code: '46'
+ KE.45:
+ combinedCode: KE.45
+ code: '45'
+ KE.05:
+ combinedCode: KE.05
+ code: '05'
+ KE.38:
+ combinedCode: KE.38
+ code: '38'
+ KE.37:
+ combinedCode: KE.37
+ code: '37'
+ KE.35:
+ combinedCode: KE.35
+ code: '35'
+ KE.34:
+ combinedCode: KE.34
+ code: '34'
+ KE.33:
+ combinedCode: KE.33
+ code: '33'
+ KE.29:
+ combinedCode: KE.29
+ code: '29'
+ KE.28:
+ combinedCode: KE.28
+ code: '28'
+ KE.27:
+ combinedCode: KE.27
+ code: '27'
+ KE.26:
+ combinedCode: KE.26
+ code: '26'
+ KE.25:
+ combinedCode: KE.25
+ code: '25'
+ KE.24:
+ combinedCode: KE.24
+ code: '24'
+ KE.23:
+ combinedCode: KE.23
+ code: '23'
+ KE.22:
+ combinedCode: KE.22
+ code: '22'
+ KE.21:
+ combinedCode: KE.21
+ code: '21'
+ KE.20:
+ combinedCode: KE.20
+ code: '20'
+ KE.18:
+ combinedCode: KE.18
+ code: '18'
+ KE.16:
+ combinedCode: KE.16
+ code: '16'
+ KE.15:
+ combinedCode: KE.15
+ code: '15'
+ KE.13:
+ combinedCode: KE.13
+ code: '13'
+ KE.12:
+ combinedCode: KE.12
+ code: '12'
+ KE.10:
+ combinedCode: KE.10
+ code: '10'
+ KE.43:
+ combinedCode: KE.43
+ code: '43'
+ KE.53:
+ combinedCode: KE.53
+ code: '53'
+ KE.30:
+ combinedCode: KE.30
+ code: '30'
+ KE.31:
+ combinedCode: KE.31
+ code: '31'
+ KE.32:
+ combinedCode: KE.32
+ code: '32'
+ KE.14:
+ combinedCode: KE.14
+ code: '14'
+ KE.47:
+ combinedCode: KE.47
+ code: '47'
+ KE.19:
+ combinedCode: KE.19
+ code: '19'
+ KE.44:
+ combinedCode: KE.44
+ code: '44'
+ KE.17:
+ combinedCode: KE.17
+ code: '17'
+ KE.11:
+ combinedCode: KE.11
+ code: '11'
+ KE.36:
+ combinedCode: KE.36
+ code: '36'
+ KE.39:
+ combinedCode: KE.39
+ code: '39'
+ KE.41:
+ combinedCode: KE.41
+ code: '41'
+ KE.42:
+ combinedCode: KE.42
+ code: '42'
+ KE.40:
+ combinedCode: KE.40
+ code: '40'
+KG:
+ iso2Code: KG
+ iso3Code: KGZ
+ regions:
+ KG.08:
+ combinedCode: KG.08
+ code: '08'
+ KG.09:
+ combinedCode: KG.09
+ code: '09'
+ KG.06:
+ combinedCode: KG.06
+ code: '06'
+ KG.04:
+ combinedCode: KG.04
+ code: '04'
+ KG.07:
+ combinedCode: KG.07
+ code: '07'
+ KG.01:
+ combinedCode: KG.01
+ code: '01'
+ KG.03:
+ combinedCode: KG.03
+ code: '03'
+ KG.02:
+ combinedCode: KG.02
+ code: '02'
+KH:
+ iso2Code: KH
+ iso3Code: KHM
+ regions:
+ KH.12:
+ combinedCode: KH.12
+ code: '12'
+ KH.29:
+ combinedCode: KH.29
+ code: '29'
+ KH.19:
+ combinedCode: KH.19
+ code: '19'
+ KH.18:
+ combinedCode: KH.18
+ code: '18'
+ KH.17:
+ combinedCode: KH.17
+ code: '17'
+ KH.27:
+ combinedCode: KH.27
+ code: '27'
+ KH.24:
+ combinedCode: KH.24
+ code: '24'
+ KH.23:
+ combinedCode: KH.23
+ code: '23'
+ KH.14:
+ combinedCode: KH.14
+ code: '14'
+ KH.13:
+ combinedCode: KH.13
+ code: '13'
+ KH.22:
+ combinedCode: KH.22
+ code: '22'
+ KH.30:
+ combinedCode: KH.30
+ code: '30'
+ KH.10:
+ combinedCode: KH.10
+ code: '10'
+ KH.09:
+ combinedCode: KH.09
+ code: '09'
+ KH.26:
+ combinedCode: KH.26
+ code: '26'
+ KH.08:
+ combinedCode: KH.08
+ code: '08'
+ KH.07:
+ combinedCode: KH.07
+ code: '07'
+ KH.21:
+ combinedCode: KH.21
+ code: '21'
+ KH.05:
+ combinedCode: KH.05
+ code: '05'
+ KH.04:
+ combinedCode: KH.04
+ code: '04'
+ KH.03:
+ combinedCode: KH.03
+ code: '03'
+ KH.02:
+ combinedCode: KH.02
+ code: '02'
+ KH.28:
+ combinedCode: KH.28
+ code: '28'
+ KH.25:
+ combinedCode: KH.25
+ code: '25'
+KI:
+ iso2Code: KI
+ iso3Code: KIR
+ regions:
+ KI.01:
+ combinedCode: KI.01
+ code: '01'
+ KI.02:
+ combinedCode: KI.02
+ code: '02'
+ KI.03:
+ combinedCode: KI.03
+ code: '03'
+KM:
+ iso2Code: KM
+ iso3Code: COM
+ regions:
+ KM.03:
+ combinedCode: KM.03
+ code: '03'
+ KM.02:
+ combinedCode: KM.02
+ code: '02'
+ KM.01:
+ combinedCode: KM.01
+ code: '01'
+KN:
+ iso2Code: KN
+ iso3Code: KNA
+ regions:
+ KN.15:
+ combinedCode: KN.15
+ code: '15'
+ KN.13:
+ combinedCode: KN.13
+ code: '13'
+ KN.12:
+ combinedCode: KN.12
+ code: '12'
+ KN.11:
+ combinedCode: KN.11
+ code: '11'
+ KN.10:
+ combinedCode: KN.10
+ code: '10'
+ KN.09:
+ combinedCode: KN.09
+ code: '09'
+ KN.08:
+ combinedCode: KN.08
+ code: '08'
+ KN.07:
+ combinedCode: KN.07
+ code: '07'
+ KN.06:
+ combinedCode: KN.06
+ code: '06'
+ KN.05:
+ combinedCode: KN.05
+ code: '05'
+ KN.04:
+ combinedCode: KN.04
+ code: '04'
+ KN.03:
+ combinedCode: KN.03
+ code: '03'
+ KN.02:
+ combinedCode: KN.02
+ code: '02'
+ KN.01:
+ combinedCode: KN.01
+ code: '01'
+KP:
+ iso2Code: KP
+ iso3Code: PRK
+ regions:
+ KP.12:
+ combinedCode: KP.12
+ code: '12'
+ KP.15:
+ combinedCode: KP.15
+ code: '15'
+ KP.11:
+ combinedCode: KP.11
+ code: '11'
+ KP.09:
+ combinedCode: KP.09
+ code: '09'
+ KP.06:
+ combinedCode: KP.06
+ code: '06'
+ KP.07:
+ combinedCode: KP.07
+ code: '07'
+ KP.03:
+ combinedCode: KP.03
+ code: '03'
+ KP.13:
+ combinedCode: KP.13
+ code: '13'
+ KP.17:
+ combinedCode: KP.17
+ code: '17'
+ KP.01:
+ combinedCode: KP.01
+ code: '01'
+ KP.18:
+ combinedCode: KP.18
+ code: '18'
+KR:
+ iso2Code: KR
+ iso3Code: KOR
+ regions:
+ KR.21:
+ combinedCode: KR.21
+ code: '21'
+ KR.19:
+ combinedCode: KR.19
+ code: '19'
+ KR.15:
+ combinedCode: KR.15
+ code: '15'
+ KR.11:
+ combinedCode: KR.11
+ code: '11'
+ KR.10:
+ combinedCode: KR.10
+ code: '10'
+ KR.14:
+ combinedCode: KR.14
+ code: '14'
+ KR.13:
+ combinedCode: KR.13
+ code: '13'
+ KR.18:
+ combinedCode: KR.18
+ code: '18'
+ KR.06:
+ combinedCode: KR.06
+ code: '06'
+ KR.12:
+ combinedCode: KR.12
+ code: '12'
+ KR.17:
+ combinedCode: KR.17
+ code: '17'
+ KR.05:
+ combinedCode: KR.05
+ code: '05'
+ KR.16:
+ combinedCode: KR.16
+ code: '16'
+ KR.03:
+ combinedCode: KR.03
+ code: '03'
+ KR.01:
+ combinedCode: KR.01
+ code: '01'
+ KR.20:
+ combinedCode: KR.20
+ code: '20'
+ KR.22:
+ combinedCode: KR.22
+ code: '22'
+XK:
+ iso2Code: XK
+ iso3Code: XKX
+ regions:
+ XK.28:
+ combinedCode: XK.28
+ code: '28'
+ XK.27:
+ combinedCode: XK.27
+ code: '27'
+ XK.03:
+ combinedCode: XK.03
+ code: '03'
+ XK.15:
+ combinedCode: XK.15
+ code: '15'
+ XK.26:
+ combinedCode: XK.26
+ code: '26'
+ XK.25:
+ combinedCode: XK.25
+ code: '25'
+ XK.21:
+ combinedCode: XK.21
+ code: '21'
+ XK.20:
+ combinedCode: XK.20
+ code: '20'
+ XK.19:
+ combinedCode: XK.19
+ code: '19'
+ XK.18:
+ combinedCode: XK.18
+ code: '18'
+ XK.22:
+ combinedCode: XK.22
+ code: '22'
+ XK.13:
+ combinedCode: XK.13
+ code: '13'
+ XK.12:
+ combinedCode: XK.12
+ code: '12'
+ XK.10:
+ combinedCode: XK.10
+ code: '10'
+ XK.11:
+ combinedCode: XK.11
+ code: '11'
+ XK.09:
+ combinedCode: XK.09
+ code: '09'
+ XK.08:
+ combinedCode: XK.08
+ code: '08'
+ XK.06:
+ combinedCode: XK.06
+ code: '06'
+ XK.07:
+ combinedCode: XK.07
+ code: '07'
+ XK.02:
+ combinedCode: XK.02
+ code: '02'
+ XK.01:
+ combinedCode: XK.01
+ code: '01'
+ XK.05:
+ combinedCode: XK.05
+ code: '05'
+ XK.04:
+ combinedCode: XK.04
+ code: '04'
+ XK.23:
+ combinedCode: XK.23
+ code: '23'
+ XK.24:
+ combinedCode: XK.24
+ code: '24'
+ XK.16:
+ combinedCode: XK.16
+ code: '16'
+ XK.17:
+ combinedCode: XK.17
+ code: '17'
+ XK.14:
+ combinedCode: XK.14
+ code: '14'
+ XK.29:
+ combinedCode: XK.29
+ code: '29'
+ XK.30:
+ combinedCode: XK.30
+ code: '30'
+ XK.31:
+ combinedCode: XK.31
+ code: '31'
+ XK.32:
+ combinedCode: XK.32
+ code: '32'
+ XK.33:
+ combinedCode: XK.33
+ code: '33'
+ XK.34:
+ combinedCode: XK.34
+ code: '34'
+ XK.35:
+ combinedCode: XK.35
+ code: '35'
+ XK.36:
+ combinedCode: XK.36
+ code: '36'
+ XK.37:
+ combinedCode: XK.37
+ code: '37'
+KW:
+ iso2Code: KW
+ iso3Code: KWT
+ regions:
+ KW.08:
+ combinedCode: KW.08
+ code: '08'
+ KW.02:
+ combinedCode: KW.02
+ code: '02'
+ KW.05:
+ combinedCode: KW.05
+ code: '05'
+ KW.07:
+ combinedCode: KW.07
+ code: '07'
+ KW.04:
+ combinedCode: KW.04
+ code: '04'
+ KW.09:
+ combinedCode: KW.09
+ code: '09'
+KY:
+ iso2Code: KY
+ iso3Code: CYM
+ regions: { }
+KZ:
+ iso2Code: KZ
+ iso3Code: KAZ
+ regions:
+ KZ.07:
+ combinedCode: KZ.07
+ code: '07'
+ KZ.09:
+ combinedCode: KZ.09
+ code: '09'
+ KZ.06:
+ combinedCode: KZ.06
+ code: '06'
+ KZ.04:
+ combinedCode: KZ.04
+ code: '04'
+ KZ.15:
+ combinedCode: KZ.15
+ code: '15'
+ KZ.03:
+ combinedCode: KZ.03
+ code: '03'
+ KZ.16:
+ combinedCode: KZ.16
+ code: '16'
+ KZ.11:
+ combinedCode: KZ.11
+ code: '11'
+ KZ.14:
+ combinedCode: KZ.14
+ code: '14'
+ KZ.13:
+ combinedCode: KZ.13
+ code: '13'
+ KZ.12:
+ combinedCode: KZ.12
+ code: '12'
+ KZ.17:
+ combinedCode: KZ.17
+ code: '17'
+ KZ.10:
+ combinedCode: KZ.10
+ code: '10'
+ KZ.02:
+ combinedCode: KZ.02
+ code: '02'
+ KZ.01:
+ combinedCode: KZ.01
+ code: '01'
+ KZ.08:
+ combinedCode: KZ.08
+ code: '08'
+ KZ.05:
+ combinedCode: KZ.05
+ code: '05'
+LA:
+ iso2Code: LA
+ iso3Code: LAO
+ regions:
+ LA.14:
+ combinedCode: LA.14
+ code: '14'
+ LA.13:
+ combinedCode: LA.13
+ code: '13'
+ LA.27:
+ combinedCode: LA.27
+ code: '27'
+ LA.20:
+ combinedCode: LA.20
+ code: '20'
+ LA.19:
+ combinedCode: LA.19
+ code: '19'
+ LA.18:
+ combinedCode: LA.18
+ code: '18'
+ LA.07:
+ combinedCode: LA.07
+ code: '07'
+ LA.17:
+ combinedCode: LA.17
+ code: '17'
+ LA.16:
+ combinedCode: LA.16
+ code: '16'
+ LA.15:
+ combinedCode: LA.15
+ code: '15'
+ LA.03:
+ combinedCode: LA.03
+ code: '03'
+ LA.02:
+ combinedCode: LA.02
+ code: '02'
+ LA.01:
+ combinedCode: LA.01
+ code: '01'
+ LA.26:
+ combinedCode: LA.26
+ code: '26'
+ LA.22:
+ combinedCode: LA.22
+ code: '22'
+ LA.23:
+ combinedCode: LA.23
+ code: '23'
+ LA.24:
+ combinedCode: LA.24
+ code: '24'
+LB:
+ iso2Code: LB
+ iso3Code: LBN
+ regions:
+ LB.05:
+ combinedCode: LB.05
+ code: '05'
+ LB.04:
+ combinedCode: LB.04
+ code: '04'
+ LB.09:
+ combinedCode: LB.09
+ code: '09'
+ LB.06:
+ combinedCode: LB.06
+ code: '06'
+ LB.08:
+ combinedCode: LB.08
+ code: '08'
+ LB.07:
+ combinedCode: LB.07
+ code: '07'
+ LB.10:
+ combinedCode: LB.10
+ code: '10'
+ LB.11:
+ combinedCode: LB.11
+ code: '11'
+LC:
+ iso2Code: LC
+ iso3Code: LCA
+ regions:
+ LC.10:
+ combinedCode: LC.10
+ code: '10'
+ LC.09:
+ combinedCode: LC.09
+ code: '09'
+ LC.11:
+ combinedCode: LC.11
+ code: '11'
+ LC.08:
+ combinedCode: LC.08
+ code: '08'
+ LC.07:
+ combinedCode: LC.07
+ code: '07'
+ LC.06:
+ combinedCode: LC.06
+ code: '06'
+ LC.05:
+ combinedCode: LC.05
+ code: '05'
+ LC.02:
+ combinedCode: LC.02
+ code: '02'
+ LC.04:
+ combinedCode: LC.04
+ code: '04'
+ LC.03:
+ combinedCode: LC.03
+ code: '03'
+ LC.01:
+ combinedCode: LC.01
+ code: '01'
+LI:
+ iso2Code: LI
+ iso3Code: LIE
+ regions:
+ LI.11:
+ combinedCode: LI.11
+ code: '11'
+ LI.10:
+ combinedCode: LI.10
+ code: '10'
+ LI.09:
+ combinedCode: LI.09
+ code: '09'
+ LI.08:
+ combinedCode: LI.08
+ code: '08'
+ LI.07:
+ combinedCode: LI.07
+ code: '07'
+ LI.06:
+ combinedCode: LI.06
+ code: '06'
+ LI.05:
+ combinedCode: LI.05
+ code: '05'
+ LI.04:
+ combinedCode: LI.04
+ code: '04'
+ LI.03:
+ combinedCode: LI.03
+ code: '03'
+ LI.02:
+ combinedCode: LI.02
+ code: '02'
+ LI.01:
+ combinedCode: LI.01
+ code: '01'
+LK:
+ iso2Code: LK
+ iso3Code: LKA
+ regions:
+ LK.36:
+ combinedCode: LK.36
+ code: '36'
+ LK.35:
+ combinedCode: LK.35
+ code: '35'
+ LK.34:
+ combinedCode: LK.34
+ code: '34'
+ LK.33:
+ combinedCode: LK.33
+ code: '33'
+ LK.32:
+ combinedCode: LK.32
+ code: '32'
+ LK.30:
+ combinedCode: LK.30
+ code: '30'
+ LK.29:
+ combinedCode: LK.29
+ code: '29'
+ LK.38:
+ combinedCode: LK.38
+ code: '38'
+ LK.37:
+ combinedCode: LK.37
+ code: '37'
+LR:
+ iso2Code: LR
+ iso3Code: LBR
+ regions:
+ LR.10:
+ combinedCode: LR.10
+ code: '10'
+ LR.09:
+ combinedCode: LR.09
+ code: '09'
+ LR.14:
+ combinedCode: LR.14
+ code: '14'
+ LR.13:
+ combinedCode: LR.13
+ code: '13'
+ LR.20:
+ combinedCode: LR.20
+ code: '20'
+ LR.19:
+ combinedCode: LR.19
+ code: '19'
+ LR.12:
+ combinedCode: LR.12
+ code: '12'
+ LR.11:
+ combinedCode: LR.11
+ code: '11'
+ LR.01:
+ combinedCode: LR.01
+ code: '01'
+ LR.15:
+ combinedCode: LR.15
+ code: '15'
+ LR.16:
+ combinedCode: LR.16
+ code: '16'
+ LR.17:
+ combinedCode: LR.17
+ code: '17'
+ LR.18:
+ combinedCode: LR.18
+ code: '18'
+ LR.21:
+ combinedCode: LR.21
+ code: '21'
+ LR.22:
+ combinedCode: LR.22
+ code: '22'
+LS:
+ iso2Code: LS
+ iso3Code: LSO
+ regions:
+ LS.19:
+ combinedCode: LS.19
+ code: '19'
+ LS.18:
+ combinedCode: LS.18
+ code: '18'
+ LS.17:
+ combinedCode: LS.17
+ code: '17'
+ LS.16:
+ combinedCode: LS.16
+ code: '16'
+ LS.15:
+ combinedCode: LS.15
+ code: '15'
+ LS.14:
+ combinedCode: LS.14
+ code: '14'
+ LS.13:
+ combinedCode: LS.13
+ code: '13'
+ LS.12:
+ combinedCode: LS.12
+ code: '12'
+ LS.11:
+ combinedCode: LS.11
+ code: '11'
+ LS.10:
+ combinedCode: LS.10
+ code: '10'
+LT:
+ iso2Code: LT
+ iso3Code: LTU
+ regions:
+ LT.56:
+ combinedCode: LT.56
+ code: '56'
+ LT.57:
+ combinedCode: LT.57
+ code: '57'
+ LT.58:
+ combinedCode: LT.58
+ code: '58'
+ LT.59:
+ combinedCode: LT.59
+ code: '59'
+ LT.60:
+ combinedCode: LT.60
+ code: '60'
+ LT.61:
+ combinedCode: LT.61
+ code: '61'
+ LT.62:
+ combinedCode: LT.62
+ code: '62'
+ LT.63:
+ combinedCode: LT.63
+ code: '63'
+ LT.64:
+ combinedCode: LT.64
+ code: '64'
+ LT.65:
+ combinedCode: LT.65
+ code: '65'
+LU:
+ iso2Code: LU
+ iso3Code: LUX
+ regions:
+ LU.03:
+ combinedCode: LU.03
+ code: '03'
+ LU.02:
+ combinedCode: LU.02
+ code: '02'
+ LU.01:
+ combinedCode: LU.01
+ code: '01'
+LV:
+ iso2Code: LV
+ iso3Code: LVA
+ regions:
+ LV.33:
+ combinedCode: LV.33
+ code: '33'
+ LV.32:
+ combinedCode: LV.32
+ code: '32'
+ LV.31:
+ combinedCode: LV.31
+ code: '31'
+ LV.30:
+ combinedCode: LV.30
+ code: '30'
+ LV.29:
+ combinedCode: LV.29
+ code: '29'
+ LV.28:
+ combinedCode: LV.28
+ code: '28'
+ LV.27:
+ combinedCode: LV.27
+ code: '27'
+ LV.25:
+ combinedCode: LV.25
+ code: '25'
+ LV.24:
+ combinedCode: LV.24
+ code: '24'
+ LV.23:
+ combinedCode: LV.23
+ code: '23'
+ LV.22:
+ combinedCode: LV.22
+ code: '22'
+ LV.21:
+ combinedCode: LV.21
+ code: '21'
+ LV.20:
+ combinedCode: LV.20
+ code: '20'
+ LV.19:
+ combinedCode: LV.19
+ code: '19'
+ LV.18:
+ combinedCode: LV.18
+ code: '18'
+ LV.16:
+ combinedCode: LV.16
+ code: '16'
+ LV.15:
+ combinedCode: LV.15
+ code: '15'
+ LV.14:
+ combinedCode: LV.14
+ code: '14'
+ LV.13:
+ combinedCode: LV.13
+ code: '13'
+ LV.12:
+ combinedCode: LV.12
+ code: '12'
+ LV.11:
+ combinedCode: LV.11
+ code: '11'
+ LV.10:
+ combinedCode: LV.10
+ code: '10'
+ LV.09:
+ combinedCode: LV.09
+ code: '09'
+ LV.08:
+ combinedCode: LV.08
+ code: '08'
+ LV.07:
+ combinedCode: LV.07
+ code: '07'
+ LV.06:
+ combinedCode: LV.06
+ code: '06'
+ LV.05:
+ combinedCode: LV.05
+ code: '05'
+ LV.04:
+ combinedCode: LV.04
+ code: '04'
+ LV.03:
+ combinedCode: LV.03
+ code: '03'
+ LV.02:
+ combinedCode: LV.02
+ code: '02'
+ LV.01:
+ combinedCode: LV.01
+ code: '01'
+ LV.60:
+ combinedCode: LV.60
+ code: '60'
+ LV.40:
+ combinedCode: LV.40
+ code: '40'
+ LV.A5:
+ combinedCode: LV.A5
+ code: A5
+ LV.99:
+ combinedCode: LV.99
+ code: '99'
+ LV.B6:
+ combinedCode: LV.B6
+ code: B6
+ LV.65:
+ combinedCode: LV.65
+ code: '65'
+ LV.61:
+ combinedCode: LV.61
+ code: '61'
+ LV.37:
+ combinedCode: LV.37
+ code: '37'
+ LV.A8:
+ combinedCode: LV.A8
+ code: A8
+ LV.D7:
+ combinedCode: LV.D7
+ code: D7
+ LV.C9:
+ combinedCode: LV.C9
+ code: C9
+ LV.51:
+ combinedCode: LV.51
+ code: '51'
+ LV.B4:
+ combinedCode: LV.B4
+ code: B4
+ LV.77:
+ combinedCode: LV.77
+ code: '77'
+ LV.44:
+ combinedCode: LV.44
+ code: '44'
+ LV.73:
+ combinedCode: LV.73
+ code: '73'
+ LV.62:
+ combinedCode: LV.62
+ code: '62'
+ LV.D5:
+ combinedCode: LV.D5
+ code: D5
+ LV.A3:
+ combinedCode: LV.A3
+ code: A3
+ LV.B9:
+ combinedCode: LV.B9
+ code: B9
+ LV.45:
+ combinedCode: LV.45
+ code: '45'
+ LV.95:
+ combinedCode: LV.95
+ code: '95'
+ LV.A2:
+ combinedCode: LV.A2
+ code: A2
+ LV.67:
+ combinedCode: LV.67
+ code: '67'
+ LV.80:
+ combinedCode: LV.80
+ code: '80'
+ LV.C3:
+ combinedCode: LV.C3
+ code: C3
+ LV.46:
+ combinedCode: LV.46
+ code: '46'
+ LV.D2:
+ combinedCode: LV.D2
+ code: D2
+ LV.53:
+ combinedCode: LV.53
+ code: '53'
+ LV.34:
+ combinedCode: LV.34
+ code: '34'
+ LV.64:
+ combinedCode: LV.64
+ code: '64'
+ LV.E4:
+ combinedCode: LV.E4
+ code: E4
+ LV.79:
+ combinedCode: LV.79
+ code: '79'
+ LV.87:
+ combinedCode: LV.87
+ code: '87'
+ LV.C8:
+ combinedCode: LV.C8
+ code: C8
+ LV.71:
+ combinedCode: LV.71
+ code: '71'
+ LV.98:
+ combinedCode: LV.98
+ code: '98'
+ LV.E6:
+ combinedCode: LV.E6
+ code: E6
+ LV.C2:
+ combinedCode: LV.C2
+ code: C2
+ LV.74:
+ combinedCode: LV.74
+ code: '74'
+ LV.38:
+ combinedCode: LV.38
+ code: '38'
+ LV.69:
+ combinedCode: LV.69
+ code: '69'
+ LV.E2:
+ combinedCode: LV.E2
+ code: E2
+ LV.90:
+ combinedCode: LV.90
+ code: '90'
+ LV.E1:
+ combinedCode: LV.E1
+ code: E1
+ LV.E8:
+ combinedCode: LV.E8
+ code: E8
+ LV.B3:
+ combinedCode: LV.B3
+ code: B3
+ LV.35:
+ combinedCode: LV.35
+ code: '35'
+ LV.56:
+ combinedCode: LV.56
+ code: '56'
+ LV.E9:
+ combinedCode: LV.E9
+ code: E9
+ LV.E7:
+ combinedCode: LV.E7
+ code: E7
+ LV.47:
+ combinedCode: LV.47
+ code: '47'
+ LV.57:
+ combinedCode: LV.57
+ code: '57'
+ LV.78:
+ combinedCode: LV.78
+ code: '78'
+ LV.B7:
+ combinedCode: LV.B7
+ code: B7
+ LV.55:
+ combinedCode: LV.55
+ code: '55'
+ LV.91:
+ combinedCode: LV.91
+ code: '91'
+ LV.85:
+ combinedCode: LV.85
+ code: '85'
+ LV.A6:
+ combinedCode: LV.A6
+ code: A6
+ LV.82:
+ combinedCode: LV.82
+ code: '82'
+ LV.68:
+ combinedCode: LV.68
+ code: '68'
+ LV.B5:
+ combinedCode: LV.B5
+ code: B5
+ LV.70:
+ combinedCode: LV.70
+ code: '70'
+ LV.84:
+ combinedCode: LV.84
+ code: '84'
+ LV.C7:
+ combinedCode: LV.C7
+ code: C7
+ LV.88:
+ combinedCode: LV.88
+ code: '88'
+ LV.94:
+ combinedCode: LV.94
+ code: '94'
+ LV.C6:
+ combinedCode: LV.C6
+ code: C6
+ LV.C5:
+ combinedCode: LV.C5
+ code: C5
+ LV.C1:
+ combinedCode: LV.C1
+ code: C1
+ LV.39:
+ combinedCode: LV.39
+ code: '39'
+ LV.97:
+ combinedCode: LV.97
+ code: '97'
+ LV.B8:
+ combinedCode: LV.B8
+ code: B8
+ LV.96:
+ combinedCode: LV.96
+ code: '96'
+ LV.52:
+ combinedCode: LV.52
+ code: '52'
+ LV.A4:
+ combinedCode: LV.A4
+ code: A4
+ LV.81:
+ combinedCode: LV.81
+ code: '81'
+ LV.42:
+ combinedCode: LV.42
+ code: '42'
+ LV.A9:
+ combinedCode: LV.A9
+ code: A9
+ LV.B1:
+ combinedCode: LV.B1
+ code: B1
+ LV.D3:
+ combinedCode: LV.D3
+ code: D3
+ LV.50:
+ combinedCode: LV.50
+ code: '50'
+ LV.D1:
+ combinedCode: LV.D1
+ code: D1
+ LV.72:
+ combinedCode: LV.72
+ code: '72'
+ LV.63:
+ combinedCode: LV.63
+ code: '63'
+ LV.E3:
+ combinedCode: LV.E3
+ code: E3
+ LV.43:
+ combinedCode: LV.43
+ code: '43'
+ LV.F1:
+ combinedCode: LV.F1
+ code: F1
+LY:
+ iso2Code: LY
+ iso3Code: LBY
+ regions:
+ LY.70:
+ combinedCode: LY.70
+ code: '70'
+ LY.69:
+ combinedCode: LY.69
+ code: '69'
+ LY.66:
+ combinedCode: LY.66
+ code: '66'
+ LY.65:
+ combinedCode: LY.65
+ code: '65'
+ LY.63:
+ combinedCode: LY.63
+ code: '63'
+ LY.77:
+ combinedCode: LY.77
+ code: '77'
+ LY.76:
+ combinedCode: LY.76
+ code: '76'
+ LY.75:
+ combinedCode: LY.75
+ code: '75'
+ LY.74:
+ combinedCode: LY.74
+ code: '74'
+ LY.73:
+ combinedCode: LY.73
+ code: '73'
+ LY.72:
+ combinedCode: LY.72
+ code: '72'
+ LY.71:
+ combinedCode: LY.71
+ code: '71'
+ LY.68:
+ combinedCode: LY.68
+ code: '68'
+ LY.78:
+ combinedCode: LY.78
+ code: '78'
+ LY.64:
+ combinedCode: LY.64
+ code: '64'
+ LY.67:
+ combinedCode: LY.67
+ code: '67'
+ LY.79:
+ combinedCode: LY.79
+ code: '79'
+ LY.80:
+ combinedCode: LY.80
+ code: '80'
+ LY.81:
+ combinedCode: LY.81
+ code: '81'
+ LY.82:
+ combinedCode: LY.82
+ code: '82'
+ LY.83:
+ combinedCode: LY.83
+ code: '83'
+ LY.84:
+ combinedCode: LY.84
+ code: '84'
+MA:
+ iso2Code: MA
+ iso3Code: MAR
+ regions:
+ MA.49:
+ combinedCode: MA.49
+ code: '49'
+ MA.48:
+ combinedCode: MA.48
+ code: '48'
+ MA.47:
+ combinedCode: MA.47
+ code: '47'
+ MA.46:
+ combinedCode: MA.46
+ code: '46'
+ MA.45:
+ combinedCode: MA.45
+ code: '45'
+ MA.50:
+ combinedCode: MA.50
+ code: '50'
+ MA.51:
+ combinedCode: MA.51
+ code: '51'
+ MA.52:
+ combinedCode: MA.52
+ code: '52'
+ MA.53:
+ combinedCode: MA.53
+ code: '53'
+ MA.54:
+ combinedCode: MA.54
+ code: '54'
+ MA.55:
+ combinedCode: MA.55
+ code: '55'
+ MA.56:
+ combinedCode: MA.56
+ code: '56'
+ MA.57:
+ combinedCode: MA.57
+ code: '57'
+ MA.58:
+ combinedCode: MA.58
+ code: '58'
+ MA.59:
+ combinedCode: MA.59
+ code: '59'
+ MA.EH:
+ combinedCode: MA.EH
+ code: EH
+MC:
+ iso2Code: MC
+ iso3Code: MCO
+ regions:
+ MC.00:
+ combinedCode: MC.00
+ code: '00'
+MD:
+ iso2Code: MD
+ iso3Code: MDA
+ regions:
+ MD.73:
+ combinedCode: MD.73
+ code: '73'
+ MD.92:
+ combinedCode: MD.92
+ code: '92'
+ MD.91:
+ combinedCode: MD.91
+ code: '91'
+ MD.90:
+ combinedCode: MD.90
+ code: '90'
+ MD.88:
+ combinedCode: MD.88
+ code: '88'
+ MD.89:
+ combinedCode: MD.89
+ code: '89'
+ MD.87:
+ combinedCode: MD.87
+ code: '87'
+ MD.84:
+ combinedCode: MD.84
+ code: '84'
+ MD.83:
+ combinedCode: MD.83
+ code: '83'
+ MD.82:
+ combinedCode: MD.82
+ code: '82'
+ MD.81:
+ combinedCode: MD.81
+ code: '81'
+ MD.59:
+ combinedCode: MD.59
+ code: '59'
+ MD.80:
+ combinedCode: MD.80
+ code: '80'
+ MD.79:
+ combinedCode: MD.79
+ code: '79'
+ MD.85:
+ combinedCode: MD.85
+ code: '85'
+ MD.69:
+ combinedCode: MD.69
+ code: '69'
+ MD.78:
+ combinedCode: MD.78
+ code: '78'
+ MD.57:
+ combinedCode: MD.57
+ code: '57'
+ MD.67:
+ combinedCode: MD.67
+ code: '67'
+ MD.65:
+ combinedCode: MD.65
+ code: '65'
+ MD.66:
+ combinedCode: MD.66
+ code: '66'
+ MD.64:
+ combinedCode: MD.64
+ code: '64'
+ MD.76:
+ combinedCode: MD.76
+ code: '76'
+ MD.75:
+ combinedCode: MD.75
+ code: '75'
+ MD.74:
+ combinedCode: MD.74
+ code: '74'
+ MD.72:
+ combinedCode: MD.72
+ code: '72'
+ MD.71:
+ combinedCode: MD.71
+ code: '71'
+ MD.70:
+ combinedCode: MD.70
+ code: '70'
+ MD.68:
+ combinedCode: MD.68
+ code: '68'
+ MD.63:
+ combinedCode: MD.63
+ code: '63'
+ MD.61:
+ combinedCode: MD.61
+ code: '61'
+ MD.77:
+ combinedCode: MD.77
+ code: '77'
+ MD.86:
+ combinedCode: MD.86
+ code: '86'
+ MD.58:
+ combinedCode: MD.58
+ code: '58'
+ MD.51:
+ combinedCode: MD.51
+ code: '51'
+ MD.62:
+ combinedCode: MD.62
+ code: '62'
+ MD.60:
+ combinedCode: MD.60
+ code: '60'
+ME:
+ iso2Code: ME
+ iso3Code: MNE
+ regions:
+ ME.17:
+ combinedCode: ME.17
+ code: '17'
+ ME.21:
+ combinedCode: ME.21
+ code: '21'
+ ME.20:
+ combinedCode: ME.20
+ code: '20'
+ ME.19:
+ combinedCode: ME.19
+ code: '19'
+ ME.16:
+ combinedCode: ME.16
+ code: '16'
+ ME.18:
+ combinedCode: ME.18
+ code: '18'
+ ME.15:
+ combinedCode: ME.15
+ code: '15'
+ ME.14:
+ combinedCode: ME.14
+ code: '14'
+ ME.13:
+ combinedCode: ME.13
+ code: '13'
+ ME.12:
+ combinedCode: ME.12
+ code: '12'
+ ME.11:
+ combinedCode: ME.11
+ code: '11'
+ ME.10:
+ combinedCode: ME.10
+ code: '10'
+ ME.09:
+ combinedCode: ME.09
+ code: '09'
+ ME.03:
+ combinedCode: ME.03
+ code: '03'
+ ME.08:
+ combinedCode: ME.08
+ code: '08'
+ ME.07:
+ combinedCode: ME.07
+ code: '07'
+ ME.06:
+ combinedCode: ME.06
+ code: '06'
+ ME.05:
+ combinedCode: ME.05
+ code: '05'
+ ME.04:
+ combinedCode: ME.04
+ code: '04'
+ ME.02:
+ combinedCode: ME.02
+ code: '02'
+ ME.01:
+ combinedCode: ME.01
+ code: '01'
+MF:
+ iso2Code: MF
+ iso3Code: MAF
+ regions: { }
+MG:
+ iso2Code: MG
+ iso3Code: MDG
+ regions:
+ MG.7670842:
+ combinedCode: MG.7670842
+ code: '7670842'
+ MG.7670846:
+ combinedCode: MG.7670846
+ code: '7670846'
+ MG.7670847:
+ combinedCode: MG.7670847
+ code: '7670847'
+ MG.7670848:
+ combinedCode: MG.7670848
+ code: '7670848'
+ MG.7670849:
+ combinedCode: MG.7670849
+ code: '7670849'
+ MG.7670850:
+ combinedCode: MG.7670850
+ code: '7670850'
+ MG.7670851:
+ combinedCode: MG.7670851
+ code: '7670851'
+ MG.7670852:
+ combinedCode: MG.7670852
+ code: '7670852'
+ MG.7670853:
+ combinedCode: MG.7670853
+ code: '7670853'
+ MG.7670854:
+ combinedCode: MG.7670854
+ code: '7670854'
+ MG.7670855:
+ combinedCode: MG.7670855
+ code: '7670855'
+ MG.7670856:
+ combinedCode: MG.7670856
+ code: '7670856'
+ MG.7670857:
+ combinedCode: MG.7670857
+ code: '7670857'
+ MG.7670902:
+ combinedCode: MG.7670902
+ code: '7670902'
+ MG.7670904:
+ combinedCode: MG.7670904
+ code: '7670904'
+ MG.7670905:
+ combinedCode: MG.7670905
+ code: '7670905'
+ MG.7670906:
+ combinedCode: MG.7670906
+ code: '7670906'
+ MG.7670907:
+ combinedCode: MG.7670907
+ code: '7670907'
+ MG.7670908:
+ combinedCode: MG.7670908
+ code: '7670908'
+ MG.7670910:
+ combinedCode: MG.7670910
+ code: '7670910'
+ MG.7670911:
+ combinedCode: MG.7670911
+ code: '7670911'
+ MG.7670913:
+ combinedCode: MG.7670913
+ code: '7670913'
+MH:
+ iso2Code: MH
+ iso3Code: MHL
+ regions:
+ MH.007:
+ combinedCode: MH.007
+ code: '007'
+ MH.010:
+ combinedCode: MH.010
+ code: '010'
+ MH.030:
+ combinedCode: MH.030
+ code: '030'
+ MH.040:
+ combinedCode: MH.040
+ code: '040'
+ MH.050:
+ combinedCode: MH.050
+ code: '050'
+ MH.060:
+ combinedCode: MH.060
+ code: '060'
+ MH.070:
+ combinedCode: MH.070
+ code: '070'
+ MH.080:
+ combinedCode: MH.080
+ code: '080'
+ MH.090:
+ combinedCode: MH.090
+ code: '090'
+ MH.100:
+ combinedCode: MH.100
+ code: '100'
+ MH.120:
+ combinedCode: MH.120
+ code: '120'
+ MH.150:
+ combinedCode: MH.150
+ code: '150'
+ MH.160:
+ combinedCode: MH.160
+ code: '160'
+ MH.180:
+ combinedCode: MH.180
+ code: '180'
+ MH.190:
+ combinedCode: MH.190
+ code: '190'
+ MH.300:
+ combinedCode: MH.300
+ code: '300'
+ MH.320:
+ combinedCode: MH.320
+ code: '320'
+ MH.330:
+ combinedCode: MH.330
+ code: '330'
+ MH.340:
+ combinedCode: MH.340
+ code: '340'
+ MH.350:
+ combinedCode: MH.350
+ code: '350'
+ MH.360:
+ combinedCode: MH.360
+ code: '360'
+ MH.385:
+ combinedCode: MH.385
+ code: '385'
+ MH.073:
+ combinedCode: MH.073
+ code: '073'
+ MH.390:
+ combinedCode: MH.390
+ code: '390'
+ MH.400:
+ combinedCode: MH.400
+ code: '400'
+ MH.410:
+ combinedCode: MH.410
+ code: '410'
+ MH.420:
+ combinedCode: MH.420
+ code: '420'
+ MH.430:
+ combinedCode: MH.430
+ code: '430'
+ MH.110:
+ combinedCode: MH.110
+ code: '110'
+ MH.130:
+ combinedCode: MH.130
+ code: '130'
+ MH.140:
+ combinedCode: MH.140
+ code: '140'
+ MH.170:
+ combinedCode: MH.170
+ code: '170'
+ MH.310:
+ combinedCode: MH.310
+ code: '310'
+MK:
+ iso2Code: MK
+ iso3Code: MKD
+ regions:
+ MK.E9:
+ combinedCode: MK.E9
+ code: E9
+ MK.86:
+ combinedCode: MK.86
+ code: '86'
+ MK.51:
+ combinedCode: MK.51
+ code: '51'
+ MK.78:
+ combinedCode: MK.78
+ code: '78'
+ MK.72:
+ combinedCode: MK.72
+ code: '72'
+ MK.11:
+ combinedCode: MK.11
+ code: '11'
+ MK.A9:
+ combinedCode: MK.A9
+ code: A9
+ MK.E5:
+ combinedCode: MK.E5
+ code: E5
+ MK.08:
+ combinedCode: MK.08
+ code: '08'
+ MK.47:
+ combinedCode: MK.47
+ code: '47'
+ MK.62:
+ combinedCode: MK.62
+ code: '62'
+ MK.C6:
+ combinedCode: MK.C6
+ code: C6
+ MK.40:
+ combinedCode: MK.40
+ code: '40'
+ MK.25:
+ combinedCode: MK.25
+ code: '25'
+ MK.87:
+ combinedCode: MK.87
+ code: '87'
+ MK.35:
+ combinedCode: MK.35
+ code: '35'
+ MK.60:
+ combinedCode: MK.60
+ code: '60'
+ MK.19:
+ combinedCode: MK.19
+ code: '19'
+ MK.E1:
+ combinedCode: MK.E1
+ code: E1
+ MK.04:
+ combinedCode: MK.04
+ code: '04'
+ MK.06:
+ combinedCode: MK.06
+ code: '06'
+ MK.D9:
+ combinedCode: MK.D9
+ code: D9
+ MK.01:
+ combinedCode: MK.01
+ code: '01'
+ MK.C7:
+ combinedCode: MK.C7
+ code: C7
+ MK.12:
+ combinedCode: MK.12
+ code: '12'
+ MK.C8:
+ combinedCode: MK.C8
+ code: C8
+ MK.C9:
+ combinedCode: MK.C9
+ code: C9
+ MK.D1:
+ combinedCode: MK.D1
+ code: D1
+ MK.18:
+ combinedCode: MK.18
+ code: '18'
+ MK.20:
+ combinedCode: MK.20
+ code: '20'
+ MK.D2:
+ combinedCode: MK.D2
+ code: D2
+ MK.22:
+ combinedCode: MK.22
+ code: '22'
+ MK.D3:
+ combinedCode: MK.D3
+ code: D3
+ MK.28:
+ combinedCode: MK.28
+ code: '28'
+ MK.29:
+ combinedCode: MK.29
+ code: '29'
+ MK.30:
+ combinedCode: MK.30
+ code: '30'
+ MK.32:
+ combinedCode: MK.32
+ code: '32'
+ MK.33:
+ combinedCode: MK.33
+ code: '33'
+ MK.D4:
+ combinedCode: MK.D4
+ code: D4
+ MK.36:
+ combinedCode: MK.36
+ code: '36'
+ MK.D5:
+ combinedCode: MK.D5
+ code: D5
+ MK.41:
+ combinedCode: MK.41
+ code: '41'
+ MK.D6:
+ combinedCode: MK.D6
+ code: D6
+ MK.43:
+ combinedCode: MK.43
+ code: '43'
+ MK.44:
+ combinedCode: MK.44
+ code: '44'
+ MK.46:
+ combinedCode: MK.46
+ code: '46'
+ MK.52:
+ combinedCode: MK.52
+ code: '52'
+ MK.53:
+ combinedCode: MK.53
+ code: '53'
+ MK.54:
+ combinedCode: MK.54
+ code: '54'
+ MK.D7:
+ combinedCode: MK.D7
+ code: D7
+ MK.59:
+ combinedCode: MK.59
+ code: '59'
+ MK.D8:
+ combinedCode: MK.D8
+ code: D8
+ MK.69:
+ combinedCode: MK.69
+ code: '69'
+ MK.E2:
+ combinedCode: MK.E2
+ code: E2
+ MK.77:
+ combinedCode: MK.77
+ code: '77'
+ MK.79:
+ combinedCode: MK.79
+ code: '79'
+ MK.80:
+ combinedCode: MK.80
+ code: '80'
+ MK.E3:
+ combinedCode: MK.E3
+ code: E3
+ MK.83:
+ combinedCode: MK.83
+ code: '83'
+ MK.84:
+ combinedCode: MK.84
+ code: '84'
+ MK.85:
+ combinedCode: MK.85
+ code: '85'
+ MK.E4:
+ combinedCode: MK.E4
+ code: E4
+ MK.90:
+ combinedCode: MK.90
+ code: '90'
+ MK.92:
+ combinedCode: MK.92
+ code: '92'
+ MK.97:
+ combinedCode: MK.97
+ code: '97'
+ MK.98:
+ combinedCode: MK.98
+ code: '98'
+ MK.E6:
+ combinedCode: MK.E6
+ code: E6
+ MK.E7:
+ combinedCode: MK.E7
+ code: E7
+ MK.A2:
+ combinedCode: MK.A2
+ code: A2
+ MK.A3:
+ combinedCode: MK.A3
+ code: A3
+ MK.A4:
+ combinedCode: MK.A4
+ code: A4
+ MK.A5:
+ combinedCode: MK.A5
+ code: A5
+ MK.E8:
+ combinedCode: MK.E8
+ code: E8
+ MK.F1:
+ combinedCode: MK.F1
+ code: F1
+ MK.B3:
+ combinedCode: MK.B3
+ code: B3
+ MK.B4:
+ combinedCode: MK.B4
+ code: B4
+ MK.B6:
+ combinedCode: MK.B6
+ code: B6
+ MK.B7:
+ combinedCode: MK.B7
+ code: B7
+ MK.C1:
+ combinedCode: MK.C1
+ code: C1
+ MK.C2:
+ combinedCode: MK.C2
+ code: C2
+ MK.C3:
+ combinedCode: MK.C3
+ code: C3
+ MK.F3:
+ combinedCode: MK.F3
+ code: F3
+ MK.F4:
+ combinedCode: MK.F4
+ code: F4
+ MK.F5:
+ combinedCode: MK.F5
+ code: F5
+ML:
+ iso2Code: ML
+ iso3Code: MLI
+ regions:
+ ML.08:
+ combinedCode: ML.08
+ code: '08'
+ ML.06:
+ combinedCode: ML.06
+ code: '06'
+ ML.05:
+ combinedCode: ML.05
+ code: '05'
+ ML.04:
+ combinedCode: ML.04
+ code: '04'
+ ML.07:
+ combinedCode: ML.07
+ code: '07'
+ ML.03:
+ combinedCode: ML.03
+ code: '03'
+ ML.09:
+ combinedCode: ML.09
+ code: '09'
+ ML.01:
+ combinedCode: ML.01
+ code: '01'
+ ML.10:
+ combinedCode: ML.10
+ code: '10'
+MM:
+ iso2Code: MM
+ iso3Code: MMR
+ regions:
+ MM.12:
+ combinedCode: MM.12
+ code: '12'
+ MM.11:
+ combinedCode: MM.11
+ code: '11'
+ MM.10:
+ combinedCode: MM.10
+ code: '10'
+ MM.17:
+ combinedCode: MM.17
+ code: '17'
+ MM.01:
+ combinedCode: MM.01
+ code: '01'
+ MM.16:
+ combinedCode: MM.16
+ code: '16'
+ MM.13:
+ combinedCode: MM.13
+ code: '13'
+ MM.08:
+ combinedCode: MM.08
+ code: '08'
+ MM.15:
+ combinedCode: MM.15
+ code: '15'
+ MM.06:
+ combinedCode: MM.06
+ code: '06'
+ MM.05:
+ combinedCode: MM.05
+ code: '05'
+ MM.04:
+ combinedCode: MM.04
+ code: '04'
+ MM.03:
+ combinedCode: MM.03
+ code: '03'
+ MM.02:
+ combinedCode: MM.02
+ code: '02'
+MN:
+ iso2Code: MN
+ iso3Code: MNG
+ regions:
+ MN.19:
+ combinedCode: MN.19
+ code: '19'
+ MN.12:
+ combinedCode: MN.12
+ code: '12'
+ MN.10:
+ combinedCode: MN.10
+ code: '10'
+ MN.09:
+ combinedCode: MN.09
+ code: '09'
+ MN.03:
+ combinedCode: MN.03
+ code: '03'
+ MN.02:
+ combinedCode: MN.02
+ code: '02'
+ MN.20:
+ combinedCode: MN.20
+ code: '20'
+ MN.18:
+ combinedCode: MN.18
+ code: '18'
+ MN.17:
+ combinedCode: MN.17
+ code: '17'
+ MN.16:
+ combinedCode: MN.16
+ code: '16'
+ MN.15:
+ combinedCode: MN.15
+ code: '15'
+ MN.14:
+ combinedCode: MN.14
+ code: '14'
+ MN.13:
+ combinedCode: MN.13
+ code: '13'
+ MN.11:
+ combinedCode: MN.11
+ code: '11'
+ MN.08:
+ combinedCode: MN.08
+ code: '08'
+ MN.07:
+ combinedCode: MN.07
+ code: '07'
+ MN.06:
+ combinedCode: MN.06
+ code: '06'
+ MN.21:
+ combinedCode: MN.21
+ code: '21'
+ MN.01:
+ combinedCode: MN.01
+ code: '01'
+ MN.23:
+ combinedCode: MN.23
+ code: '23'
+ MN.24:
+ combinedCode: MN.24
+ code: '24'
+ MN.25:
+ combinedCode: MN.25
+ code: '25'
+MO:
+ iso2Code: MO
+ iso3Code: MAC
+ regions:
+ MO.02:
+ combinedCode: MO.02
+ code: '02'
+ MO.01:
+ combinedCode: MO.01
+ code: '01'
+MP:
+ iso2Code: MP
+ iso3Code: MNP
+ regions:
+ MP.100:
+ combinedCode: MP.100
+ code: '100'
+ MP.110:
+ combinedCode: MP.110
+ code: '110'
+ MP.120:
+ combinedCode: MP.120
+ code: '120'
+ MP.085:
+ combinedCode: MP.085
+ code: '085'
+MQ:
+ iso2Code: MQ
+ iso3Code: MTQ
+ regions:
+ MQ.MQ:
+ combinedCode: MQ.MQ
+ code: MQ
+MR:
+ iso2Code: MR
+ iso3Code: MRT
+ regions:
+ MR.06:
+ combinedCode: MR.06
+ code: '06'
+ MR.11:
+ combinedCode: MR.11
+ code: '11'
+ MR.09:
+ combinedCode: MR.09
+ code: '09'
+ MR.NKC:
+ combinedCode: MR.NKC
+ code: NKC
+ MR.12:
+ combinedCode: MR.12
+ code: '12'
+ MR.02:
+ combinedCode: MR.02
+ code: '02'
+ MR.01:
+ combinedCode: MR.01
+ code: '01'
+ MR.10:
+ combinedCode: MR.10
+ code: '10'
+ MR.04:
+ combinedCode: MR.04
+ code: '04'
+ MR.08:
+ combinedCode: MR.08
+ code: '08'
+ MR.05:
+ combinedCode: MR.05
+ code: '05'
+ MR.03:
+ combinedCode: MR.03
+ code: '03'
+ MR.07:
+ combinedCode: MR.07
+ code: '07'
+MS:
+ iso2Code: MS
+ iso3Code: MSR
+ regions:
+ MS.03:
+ combinedCode: MS.03
+ code: '03'
+ MS.02:
+ combinedCode: MS.02
+ code: '02'
+ MS.01:
+ combinedCode: MS.01
+ code: '01'
+MT:
+ iso2Code: MT
+ iso3Code: MLT
+ regions:
+ MT.01:
+ combinedCode: MT.01
+ code: '01'
+ MT.02:
+ combinedCode: MT.02
+ code: '02'
+ MT.03:
+ combinedCode: MT.03
+ code: '03'
+ MT.04:
+ combinedCode: MT.04
+ code: '04'
+ MT.05:
+ combinedCode: MT.05
+ code: '05'
+ MT.06:
+ combinedCode: MT.06
+ code: '06'
+ MT.07:
+ combinedCode: MT.07
+ code: '07'
+ MT.08:
+ combinedCode: MT.08
+ code: '08'
+ MT.09:
+ combinedCode: MT.09
+ code: '09'
+ MT.10:
+ combinedCode: MT.10
+ code: '10'
+ MT.11:
+ combinedCode: MT.11
+ code: '11'
+ MT.12:
+ combinedCode: MT.12
+ code: '12'
+ MT.13:
+ combinedCode: MT.13
+ code: '13'
+ MT.14:
+ combinedCode: MT.14
+ code: '14'
+ MT.15:
+ combinedCode: MT.15
+ code: '15'
+ MT.16:
+ combinedCode: MT.16
+ code: '16'
+ MT.17:
+ combinedCode: MT.17
+ code: '17'
+ MT.18:
+ combinedCode: MT.18
+ code: '18'
+ MT.19:
+ combinedCode: MT.19
+ code: '19'
+ MT.20:
+ combinedCode: MT.20
+ code: '20'
+ MT.21:
+ combinedCode: MT.21
+ code: '21'
+ MT.22:
+ combinedCode: MT.22
+ code: '22'
+ MT.23:
+ combinedCode: MT.23
+ code: '23'
+ MT.24:
+ combinedCode: MT.24
+ code: '24'
+ MT.25:
+ combinedCode: MT.25
+ code: '25'
+ MT.26:
+ combinedCode: MT.26
+ code: '26'
+ MT.27:
+ combinedCode: MT.27
+ code: '27'
+ MT.28:
+ combinedCode: MT.28
+ code: '28'
+ MT.29:
+ combinedCode: MT.29
+ code: '29'
+ MT.30:
+ combinedCode: MT.30
+ code: '30'
+ MT.31:
+ combinedCode: MT.31
+ code: '31'
+ MT.32:
+ combinedCode: MT.32
+ code: '32'
+ MT.33:
+ combinedCode: MT.33
+ code: '33'
+ MT.34:
+ combinedCode: MT.34
+ code: '34'
+ MT.35:
+ combinedCode: MT.35
+ code: '35'
+ MT.36:
+ combinedCode: MT.36
+ code: '36'
+ MT.37:
+ combinedCode: MT.37
+ code: '37'
+ MT.38:
+ combinedCode: MT.38
+ code: '38'
+ MT.39:
+ combinedCode: MT.39
+ code: '39'
+ MT.40:
+ combinedCode: MT.40
+ code: '40'
+ MT.41:
+ combinedCode: MT.41
+ code: '41'
+ MT.42:
+ combinedCode: MT.42
+ code: '42'
+ MT.43:
+ combinedCode: MT.43
+ code: '43'
+ MT.44:
+ combinedCode: MT.44
+ code: '44'
+ MT.46:
+ combinedCode: MT.46
+ code: '46'
+ MT.47:
+ combinedCode: MT.47
+ code: '47'
+ MT.48:
+ combinedCode: MT.48
+ code: '48'
+ MT.49:
+ combinedCode: MT.49
+ code: '49'
+ MT.50:
+ combinedCode: MT.50
+ code: '50'
+ MT.51:
+ combinedCode: MT.51
+ code: '51'
+ MT.52:
+ combinedCode: MT.52
+ code: '52'
+ MT.53:
+ combinedCode: MT.53
+ code: '53'
+ MT.54:
+ combinedCode: MT.54
+ code: '54'
+ MT.55:
+ combinedCode: MT.55
+ code: '55'
+ MT.56:
+ combinedCode: MT.56
+ code: '56'
+ MT.57:
+ combinedCode: MT.57
+ code: '57'
+ MT.58:
+ combinedCode: MT.58
+ code: '58'
+ MT.59:
+ combinedCode: MT.59
+ code: '59'
+ MT.61:
+ combinedCode: MT.61
+ code: '61'
+ MT.62:
+ combinedCode: MT.62
+ code: '62'
+ MT.63:
+ combinedCode: MT.63
+ code: '63'
+ MT.64:
+ combinedCode: MT.64
+ code: '64'
+ MT.65:
+ combinedCode: MT.65
+ code: '65'
+ MT.66:
+ combinedCode: MT.66
+ code: '66'
+ MT.67:
+ combinedCode: MT.67
+ code: '67'
+ MT.68:
+ combinedCode: MT.68
+ code: '68'
+ MT.60:
+ combinedCode: MT.60
+ code: '60'
+MU:
+ iso2Code: MU
+ iso3Code: MUS
+ regions:
+ MU.21:
+ combinedCode: MU.21
+ code: '21'
+ MU.20:
+ combinedCode: MU.20
+ code: '20'
+ MU.19:
+ combinedCode: MU.19
+ code: '19'
+ MU.18:
+ combinedCode: MU.18
+ code: '18'
+ MU.17:
+ combinedCode: MU.17
+ code: '17'
+ MU.16:
+ combinedCode: MU.16
+ code: '16'
+ MU.15:
+ combinedCode: MU.15
+ code: '15'
+ MU.14:
+ combinedCode: MU.14
+ code: '14'
+ MU.13:
+ combinedCode: MU.13
+ code: '13'
+ MU.12:
+ combinedCode: MU.12
+ code: '12'
+ MU.22:
+ combinedCode: MU.22
+ code: '22'
+ MU.23:
+ combinedCode: MU.23
+ code: '23'
+MV:
+ iso2Code: MV
+ iso3Code: MDV
+ regions:
+ MV.47:
+ combinedCode: MV.47
+ code: '47'
+ MV.46:
+ combinedCode: MV.46
+ code: '46'
+ MV.45:
+ combinedCode: MV.45
+ code: '45'
+ MV.01:
+ combinedCode: MV.01
+ code: '01'
+ MV.44:
+ combinedCode: MV.44
+ code: '44'
+ MV.43:
+ combinedCode: MV.43
+ code: '43'
+ MV.42:
+ combinedCode: MV.42
+ code: '42'
+ MV.41:
+ combinedCode: MV.41
+ code: '41'
+ MV.39:
+ combinedCode: MV.39
+ code: '39'
+ MV.05:
+ combinedCode: MV.05
+ code: '05'
+ MV.38:
+ combinedCode: MV.38
+ code: '38'
+ MV.37:
+ combinedCode: MV.37
+ code: '37'
+ MV.36:
+ combinedCode: MV.36
+ code: '36'
+ MV.35:
+ combinedCode: MV.35
+ code: '35'
+ MV.34:
+ combinedCode: MV.34
+ code: '34'
+ MV.33:
+ combinedCode: MV.33
+ code: '33'
+ MV.32:
+ combinedCode: MV.32
+ code: '32'
+ MV.31:
+ combinedCode: MV.31
+ code: '31'
+ MV.30:
+ combinedCode: MV.30
+ code: '30'
+ MV.40:
+ combinedCode: MV.40
+ code: '40'
+ MV.48:
+ combinedCode: MV.48
+ code: '48'
+ MV.49:
+ combinedCode: MV.49
+ code: '49'
+ MV.50:
+ combinedCode: MV.50
+ code: '50'
+ MV.51:
+ combinedCode: MV.51
+ code: '51'
+ MV.52:
+ combinedCode: MV.52
+ code: '52'
+ MV.53:
+ combinedCode: MV.53
+ code: '53'
+ MV.54:
+ combinedCode: MV.54
+ code: '54'
+MW:
+ iso2Code: MW
+ iso3Code: MWI
+ regions:
+ MW.S:
+ combinedCode: MW.S
+ code: S
+ MW.N:
+ combinedCode: MW.N
+ code: N
+ MW.C:
+ combinedCode: MW.C
+ code: C
+MX:
+ iso2Code: MX
+ iso3Code: MEX
+ regions:
+ MX.31:
+ combinedCode: MX.31
+ code: '31'
+ MX.30:
+ combinedCode: MX.30
+ code: '30'
+ MX.29:
+ combinedCode: MX.29
+ code: '29'
+ MX.28:
+ combinedCode: MX.28
+ code: '28'
+ MX.27:
+ combinedCode: MX.27
+ code: '27'
+ MX.23:
+ combinedCode: MX.23
+ code: '23'
+ MX.22:
+ combinedCode: MX.22
+ code: '22'
+ MX.21:
+ combinedCode: MX.21
+ code: '21'
+ MX.20:
+ combinedCode: MX.20
+ code: '20'
+ MX.19:
+ combinedCode: MX.19
+ code: '19'
+ MX.17:
+ combinedCode: MX.17
+ code: '17'
+ MX.15:
+ combinedCode: MX.15
+ code: '15'
+ MX.13:
+ combinedCode: MX.13
+ code: '13'
+ MX.12:
+ combinedCode: MX.12
+ code: '12'
+ MX.09:
+ combinedCode: MX.09
+ code: '09'
+ MX.05:
+ combinedCode: MX.05
+ code: '05'
+ MX.04:
+ combinedCode: MX.04
+ code: '04'
+ MX.32:
+ combinedCode: MX.32
+ code: '32'
+ MX.26:
+ combinedCode: MX.26
+ code: '26'
+ MX.25:
+ combinedCode: MX.25
+ code: '25'
+ MX.24:
+ combinedCode: MX.24
+ code: '24'
+ MX.18:
+ combinedCode: MX.18
+ code: '18'
+ MX.16:
+ combinedCode: MX.16
+ code: '16'
+ MX.14:
+ combinedCode: MX.14
+ code: '14'
+ MX.11:
+ combinedCode: MX.11
+ code: '11'
+ MX.10:
+ combinedCode: MX.10
+ code: '10'
+ MX.08:
+ combinedCode: MX.08
+ code: '08'
+ MX.07:
+ combinedCode: MX.07
+ code: '07'
+ MX.06:
+ combinedCode: MX.06
+ code: '06'
+ MX.03:
+ combinedCode: MX.03
+ code: '03'
+ MX.02:
+ combinedCode: MX.02
+ code: '02'
+ MX.01:
+ combinedCode: MX.01
+ code: '01'
+MY:
+ iso2Code: MY
+ iso3Code: MYS
+ regions:
+ MY.04:
+ combinedCode: MY.04
+ code: '04'
+ MY.13:
+ combinedCode: MY.13
+ code: '13'
+ MY.12:
+ combinedCode: MY.12
+ code: '12'
+ MY.11:
+ combinedCode: MY.11
+ code: '11'
+ MY.16:
+ combinedCode: MY.16
+ code: '16'
+ MY.08:
+ combinedCode: MY.08
+ code: '08'
+ MY.07:
+ combinedCode: MY.07
+ code: '07'
+ MY.06:
+ combinedCode: MY.06
+ code: '06'
+ MY.05:
+ combinedCode: MY.05
+ code: '05'
+ MY.03:
+ combinedCode: MY.03
+ code: '03'
+ MY.14:
+ combinedCode: MY.14
+ code: '14'
+ MY.09:
+ combinedCode: MY.09
+ code: '09'
+ MY.02:
+ combinedCode: MY.02
+ code: '02'
+ MY.01:
+ combinedCode: MY.01
+ code: '01'
+ MY.15:
+ combinedCode: MY.15
+ code: '15'
+ MY.17:
+ combinedCode: MY.17
+ code: '17'
+MZ:
+ iso2Code: MZ
+ iso3Code: MOZ
+ regions:
+ MZ.09:
+ combinedCode: MZ.09
+ code: '09'
+ MZ.08:
+ combinedCode: MZ.08
+ code: '08'
+ MZ.05:
+ combinedCode: MZ.05
+ code: '05'
+ MZ.07:
+ combinedCode: MZ.07
+ code: '07'
+ MZ.06:
+ combinedCode: MZ.06
+ code: '06'
+ MZ.04:
+ combinedCode: MZ.04
+ code: '04'
+ MZ.10:
+ combinedCode: MZ.10
+ code: '10'
+ MZ.03:
+ combinedCode: MZ.03
+ code: '03'
+ MZ.02:
+ combinedCode: MZ.02
+ code: '02'
+ MZ.01:
+ combinedCode: MZ.01
+ code: '01'
+ MZ.11:
+ combinedCode: MZ.11
+ code: '11'
+NA:
+ iso2Code: NA
+ iso3Code: NAM
+ regions:
+ NA.28:
+ combinedCode: NA.28
+ code: '28'
+ NA.21:
+ combinedCode: NA.21
+ code: '21'
+ NA.29:
+ combinedCode: NA.29
+ code: '29'
+ NA.30:
+ combinedCode: NA.30
+ code: '30'
+ NA.31:
+ combinedCode: NA.31
+ code: '31'
+ NA.32:
+ combinedCode: NA.32
+ code: '32'
+ NA.33:
+ combinedCode: NA.33
+ code: '33'
+ NA.34:
+ combinedCode: NA.34
+ code: '34'
+ NA.35:
+ combinedCode: NA.35
+ code: '35'
+ NA.36:
+ combinedCode: NA.36
+ code: '36'
+ NA.37:
+ combinedCode: NA.37
+ code: '37'
+ NA.38:
+ combinedCode: NA.38
+ code: '38'
+ NA.39:
+ combinedCode: NA.39
+ code: '39'
+NC:
+ iso2Code: NC
+ iso3Code: NCL
+ regions:
+ NC.02:
+ combinedCode: NC.02
+ code: '02'
+ NC.01:
+ combinedCode: NC.01
+ code: '01'
+ NC.03:
+ combinedCode: NC.03
+ code: '03'
+NE:
+ iso2Code: NE
+ iso3Code: NER
+ regions:
+ NE.07:
+ combinedCode: NE.07
+ code: '07'
+ NE.06:
+ combinedCode: NE.06
+ code: '06'
+ NE.04:
+ combinedCode: NE.04
+ code: '04'
+ NE.03:
+ combinedCode: NE.03
+ code: '03'
+ NE.02:
+ combinedCode: NE.02
+ code: '02'
+ NE.01:
+ combinedCode: NE.01
+ code: '01'
+ NE.09:
+ combinedCode: NE.09
+ code: '09'
+ NE.08:
+ combinedCode: NE.08
+ code: '08'
+NF:
+ iso2Code: NF
+ iso3Code: NFK
+ regions: { }
+NG:
+ iso2Code: NG
+ iso3Code: NGA
+ regions:
+ NG.51:
+ combinedCode: NG.51
+ code: '51'
+ NG.50:
+ combinedCode: NG.50
+ code: '50'
+ NG.49:
+ combinedCode: NG.49
+ code: '49'
+ NG.32:
+ combinedCode: NG.32
+ code: '32'
+ NG.48:
+ combinedCode: NG.48
+ code: '48'
+ NG.16:
+ combinedCode: NG.16
+ code: '16'
+ NG.31:
+ combinedCode: NG.31
+ code: '31'
+ NG.05:
+ combinedCode: NG.05
+ code: '05'
+ NG.30:
+ combinedCode: NG.30
+ code: '30'
+ NG.24:
+ combinedCode: NG.24
+ code: '24'
+ NG.29:
+ combinedCode: NG.29
+ code: '29'
+ NG.23:
+ combinedCode: NG.23
+ code: '23'
+ NG.28:
+ combinedCode: NG.28
+ code: '28'
+ NG.22:
+ combinedCode: NG.22
+ code: '22'
+ NG.27:
+ combinedCode: NG.27
+ code: '27'
+ NG.26:
+ combinedCode: NG.26
+ code: '26'
+ NG.46:
+ combinedCode: NG.46
+ code: '46'
+ NG.25:
+ combinedCode: NG.25
+ code: '25'
+ NG.21:
+ combinedCode: NG.21
+ code: '21'
+ NG.11:
+ combinedCode: NG.11
+ code: '11'
+ NG.45:
+ combinedCode: NG.45
+ code: '45'
+ NG.36:
+ combinedCode: NG.36
+ code: '36'
+ NG.35:
+ combinedCode: NG.35
+ code: '35'
+ NG.37:
+ combinedCode: NG.37
+ code: '37'
+ NG.47:
+ combinedCode: NG.47
+ code: '47'
+ NG.39:
+ combinedCode: NG.39
+ code: '39'
+ NG.52:
+ combinedCode: NG.52
+ code: '52'
+ NG.53:
+ combinedCode: NG.53
+ code: '53'
+ NG.54:
+ combinedCode: NG.54
+ code: '54'
+ NG.55:
+ combinedCode: NG.55
+ code: '55'
+ NG.56:
+ combinedCode: NG.56
+ code: '56'
+ NG.57:
+ combinedCode: NG.57
+ code: '57'
+ NG.40:
+ combinedCode: NG.40
+ code: '40'
+ NG.41:
+ combinedCode: NG.41
+ code: '41'
+ NG.42:
+ combinedCode: NG.42
+ code: '42'
+ NG.43:
+ combinedCode: NG.43
+ code: '43'
+ NG.44:
+ combinedCode: NG.44
+ code: '44'
+NI:
+ iso2Code: NI
+ iso3Code: NIC
+ regions:
+ NI.15:
+ combinedCode: NI.15
+ code: '15'
+ NI.14:
+ combinedCode: NI.14
+ code: '14'
+ NI.13:
+ combinedCode: NI.13
+ code: '13'
+ NI.12:
+ combinedCode: NI.12
+ code: '12'
+ NI.11:
+ combinedCode: NI.11
+ code: '11'
+ NI.10:
+ combinedCode: NI.10
+ code: '10'
+ NI.09:
+ combinedCode: NI.09
+ code: '09'
+ NI.08:
+ combinedCode: NI.08
+ code: '08'
+ NI.07:
+ combinedCode: NI.07
+ code: '07'
+ NI.06:
+ combinedCode: NI.06
+ code: '06'
+ NI.05:
+ combinedCode: NI.05
+ code: '05'
+ NI.04:
+ combinedCode: NI.04
+ code: '04'
+ NI.03:
+ combinedCode: NI.03
+ code: '03'
+ NI.02:
+ combinedCode: NI.02
+ code: '02'
+ NI.01:
+ combinedCode: NI.01
+ code: '01'
+ NI.17:
+ combinedCode: NI.17
+ code: '17'
+ NI.18:
+ combinedCode: NI.18
+ code: '18'
+NL:
+ iso2Code: NL
+ iso3Code: NLD
+ regions:
+ NL.11:
+ combinedCode: NL.11
+ code: '11'
+ NL.10:
+ combinedCode: NL.10
+ code: '10'
+ NL.09:
+ combinedCode: NL.09
+ code: '09'
+ NL.15:
+ combinedCode: NL.15
+ code: '15'
+ NL.07:
+ combinedCode: NL.07
+ code: '07'
+ NL.06:
+ combinedCode: NL.06
+ code: '06'
+ NL.05:
+ combinedCode: NL.05
+ code: '05'
+ NL.04:
+ combinedCode: NL.04
+ code: '04'
+ NL.03:
+ combinedCode: NL.03
+ code: '03'
+ NL.02:
+ combinedCode: NL.02
+ code: '02'
+ NL.01:
+ combinedCode: NL.01
+ code: '01'
+ NL.16:
+ combinedCode: NL.16
+ code: '16'
+NO:
+ iso2Code: NO
+ iso3Code: NOR
+ regions:
+ NO.05:
+ combinedCode: NO.05
+ code: '05'
+ NO.20:
+ combinedCode: NO.20
+ code: '20'
+ NO.19:
+ combinedCode: NO.19
+ code: '19'
+ NO.18:
+ combinedCode: NO.18
+ code: '18'
+ NO.17:
+ combinedCode: NO.17
+ code: '17'
+ NO.16:
+ combinedCode: NO.16
+ code: '16'
+ NO.15:
+ combinedCode: NO.15
+ code: '15'
+ NO.14:
+ combinedCode: NO.14
+ code: '14'
+ NO.13:
+ combinedCode: NO.13
+ code: '13'
+ NO.12:
+ combinedCode: NO.12
+ code: '12'
+ NO.11:
+ combinedCode: NO.11
+ code: '11'
+ NO.10:
+ combinedCode: NO.10
+ code: '10'
+ NO.09:
+ combinedCode: NO.09
+ code: '09'
+ NO.08:
+ combinedCode: NO.08
+ code: '08'
+ NO.07:
+ combinedCode: NO.07
+ code: '07'
+ NO.06:
+ combinedCode: NO.06
+ code: '06'
+ NO.04:
+ combinedCode: NO.04
+ code: '04'
+ NO.02:
+ combinedCode: NO.02
+ code: '02'
+ NO.01:
+ combinedCode: NO.01
+ code: '01'
+NP:
+ iso2Code: NP
+ iso3Code: NPL
+ regions:
+ NP.FR:
+ combinedCode: NP.FR
+ code: FR
+ NP.MR:
+ combinedCode: NP.MR
+ code: MR
+ NP.CR:
+ combinedCode: NP.CR
+ code: CR
+ NP.ER:
+ combinedCode: NP.ER
+ code: ER
+ NP.WR:
+ combinedCode: NP.WR
+ code: WR
+NR:
+ iso2Code: NR
+ iso3Code: NRU
+ regions:
+ NR.14:
+ combinedCode: NR.14
+ code: '14'
+ NR.13:
+ combinedCode: NR.13
+ code: '13'
+ NR.12:
+ combinedCode: NR.12
+ code: '12'
+ NR.11:
+ combinedCode: NR.11
+ code: '11'
+ NR.10:
+ combinedCode: NR.10
+ code: '10'
+ NR.09:
+ combinedCode: NR.09
+ code: '09'
+ NR.08:
+ combinedCode: NR.08
+ code: '08'
+ NR.07:
+ combinedCode: NR.07
+ code: '07'
+ NR.06:
+ combinedCode: NR.06
+ code: '06'
+ NR.05:
+ combinedCode: NR.05
+ code: '05'
+ NR.04:
+ combinedCode: NR.04
+ code: '04'
+ NR.03:
+ combinedCode: NR.03
+ code: '03'
+ NR.02:
+ combinedCode: NR.02
+ code: '02'
+ NR.01:
+ combinedCode: NR.01
+ code: '01'
+NU:
+ iso2Code: NU
+ iso3Code: NIU
+ regions: { }
+NZ:
+ iso2Code: NZ
+ iso3Code: NZL
+ regions:
+ NZ.G2:
+ combinedCode: NZ.G2
+ code: G2
+ NZ.F3:
+ combinedCode: NZ.F3
+ code: F3
+ NZ.G1:
+ combinedCode: NZ.G1
+ code: G1
+ NZ.TAS:
+ combinedCode: NZ.TAS
+ code: TAS
+ NZ.F9:
+ combinedCode: NZ.F9
+ code: F9
+ NZ.F8:
+ combinedCode: NZ.F8
+ code: F8
+ NZ.E8:
+ combinedCode: NZ.E8
+ code: E8
+ NZ.F6:
+ combinedCode: NZ.F6
+ code: F6
+ NZ.F4:
+ combinedCode: NZ.F4
+ code: F4
+ NZ.F2:
+ combinedCode: NZ.F2
+ code: F2
+ NZ.F1:
+ combinedCode: NZ.F1
+ code: F1
+ NZ.E9:
+ combinedCode: NZ.E9
+ code: E9
+ NZ.E7:
+ combinedCode: NZ.E7
+ code: E7
+ NZ.10:
+ combinedCode: NZ.10
+ code: '10'
+ NZ.F5:
+ combinedCode: NZ.F5
+ code: F5
+ NZ.F7:
+ combinedCode: NZ.F7
+ code: F7
+ NZ.G3:
+ combinedCode: NZ.G3
+ code: G3
+OM:
+ iso2Code: OM
+ iso3Code: OMN
+ regions:
+ OM.01:
+ combinedCode: OM.01
+ code: '01'
+ OM.02:
+ combinedCode: OM.02
+ code: '02'
+ OM.03:
+ combinedCode: OM.03
+ code: '03'
+ OM.04:
+ combinedCode: OM.04
+ code: '04'
+ OM.09:
+ combinedCode: OM.09
+ code: '09'
+ OM.06:
+ combinedCode: OM.06
+ code: '06'
+ OM.07:
+ combinedCode: OM.07
+ code: '07'
+ OM.08:
+ combinedCode: OM.08
+ code: '08'
+ OM.10:
+ combinedCode: OM.10
+ code: '10'
+ OM.12:
+ combinedCode: OM.12
+ code: '12'
+ OM.11:
+ combinedCode: OM.11
+ code: '11'
+PA:
+ iso2Code: PA
+ iso3Code: PAN
+ regions:
+ PA.10:
+ combinedCode: PA.10
+ code: '10'
+ PA.09:
+ combinedCode: PA.09
+ code: '09'
+ PA.08:
+ combinedCode: PA.08
+ code: '08'
+ PA.07:
+ combinedCode: PA.07
+ code: '07'
+ PA.06:
+ combinedCode: PA.06
+ code: '06'
+ PA.05:
+ combinedCode: PA.05
+ code: '05'
+ PA.04:
+ combinedCode: PA.04
+ code: '04'
+ PA.03:
+ combinedCode: PA.03
+ code: '03'
+ PA.02:
+ combinedCode: PA.02
+ code: '02'
+ PA.01:
+ combinedCode: PA.01
+ code: '01'
+ PA.11:
+ combinedCode: PA.11
+ code: '11'
+ PA.12:
+ combinedCode: PA.12
+ code: '12'
+PE:
+ iso2Code: PE
+ iso3Code: PER
+ regions:
+ PE.25:
+ combinedCode: PE.25
+ code: '25'
+ PE.24:
+ combinedCode: PE.24
+ code: '24'
+ PE.22:
+ combinedCode: PE.22
+ code: '22'
+ PE.20:
+ combinedCode: PE.20
+ code: '20'
+ PE.16:
+ combinedCode: PE.16
+ code: '16'
+ PE.14:
+ combinedCode: PE.14
+ code: '14'
+ PE.13:
+ combinedCode: PE.13
+ code: '13'
+ PE.10:
+ combinedCode: PE.10
+ code: '10'
+ PE.06:
+ combinedCode: PE.06
+ code: '06'
+ PE.02:
+ combinedCode: PE.02
+ code: '02'
+ PE.01:
+ combinedCode: PE.01
+ code: '01'
+ PE.23:
+ combinedCode: PE.23
+ code: '23'
+ PE.21:
+ combinedCode: PE.21
+ code: '21'
+ PE.19:
+ combinedCode: PE.19
+ code: '19'
+ PE.18:
+ combinedCode: PE.18
+ code: '18'
+ PE.17:
+ combinedCode: PE.17
+ code: '17'
+ PE.LMA:
+ combinedCode: PE.LMA
+ code: LMA
+ PE.15:
+ combinedCode: PE.15
+ code: '15'
+ PE.12:
+ combinedCode: PE.12
+ code: '12'
+ PE.11:
+ combinedCode: PE.11
+ code: '11'
+ PE.09:
+ combinedCode: PE.09
+ code: '09'
+ PE.08:
+ combinedCode: PE.08
+ code: '08'
+ PE.07:
+ combinedCode: PE.07
+ code: '07'
+ PE.05:
+ combinedCode: PE.05
+ code: '05'
+ PE.04:
+ combinedCode: PE.04
+ code: '04'
+ PE.03:
+ combinedCode: PE.03
+ code: '03'
+PF:
+ iso2Code: PF
+ iso3Code: PYF
+ regions:
+ PF.04:
+ combinedCode: PF.04
+ code: '04'
+ PF.03:
+ combinedCode: PF.03
+ code: '03'
+ PF.02:
+ combinedCode: PF.02
+ code: '02'
+ PF.01:
+ combinedCode: PF.01
+ code: '01'
+ PF.05:
+ combinedCode: PF.05
+ code: '05'
+PG:
+ iso2Code: PG
+ iso3Code: PNG
+ regions:
+ PG.17:
+ combinedCode: PG.17
+ code: '17'
+ PG.06:
+ combinedCode: PG.06
+ code: '06'
+ PG.16:
+ combinedCode: PG.16
+ code: '16'
+ PG.05:
+ combinedCode: PG.05
+ code: '05'
+ PG.18:
+ combinedCode: PG.18
+ code: '18'
+ PG.07:
+ combinedCode: PG.07
+ code: '07'
+ PG.04:
+ combinedCode: PG.04
+ code: '04'
+ PG.15:
+ combinedCode: PG.15
+ code: '15'
+ PG.20:
+ combinedCode: PG.20
+ code: '20'
+ PG.14:
+ combinedCode: PG.14
+ code: '14'
+ PG.13:
+ combinedCode: PG.13
+ code: '13'
+ PG.12:
+ combinedCode: PG.12
+ code: '12'
+ PG.02:
+ combinedCode: PG.02
+ code: '02'
+ PG.19:
+ combinedCode: PG.19
+ code: '19'
+ PG.11:
+ combinedCode: PG.11
+ code: '11'
+ PG.10:
+ combinedCode: PG.10
+ code: '10'
+ PG.09:
+ combinedCode: PG.09
+ code: '09'
+ PG.08:
+ combinedCode: PG.08
+ code: '08'
+ PG.03:
+ combinedCode: PG.03
+ code: '03'
+ PG.01:
+ combinedCode: PG.01
+ code: '01'
+ PG.21:
+ combinedCode: PG.21
+ code: '21'
+ PG.22:
+ combinedCode: PG.22
+ code: '22'
+PH:
+ iso2Code: PH
+ iso3Code: PHL
+ regions:
+ PH.14:
+ combinedCode: PH.14
+ code: '14'
+ PH.10:
+ combinedCode: PH.10
+ code: '10'
+ PH.41:
+ combinedCode: PH.41
+ code: '41'
+ PH.02:
+ combinedCode: PH.02
+ code: '02'
+ PH.12:
+ combinedCode: PH.12
+ code: '12'
+ PH.13:
+ combinedCode: PH.13
+ code: '13'
+ PH.15:
+ combinedCode: PH.15
+ code: '15'
+ PH.01:
+ combinedCode: PH.01
+ code: '01'
+ PH.40:
+ combinedCode: PH.40
+ code: '40'
+ PH.06:
+ combinedCode: PH.06
+ code: '06'
+ PH.03:
+ combinedCode: PH.03
+ code: '03'
+ PH.07:
+ combinedCode: PH.07
+ code: '07'
+ PH.08:
+ combinedCode: PH.08
+ code: '08'
+ PH.09:
+ combinedCode: PH.09
+ code: '09'
+ PH.11:
+ combinedCode: PH.11
+ code: '11'
+ PH.05:
+ combinedCode: PH.05
+ code: '05'
+ PH.NCR:
+ combinedCode: PH.NCR
+ code: NCR
+PK:
+ iso2Code: PK
+ iso3Code: PAK
+ regions:
+ PK.08:
+ combinedCode: PK.08
+ code: '08'
+ PK.05:
+ combinedCode: PK.05
+ code: '05'
+ PK.04:
+ combinedCode: PK.04
+ code: '04'
+ PK.03:
+ combinedCode: PK.03
+ code: '03'
+ PK.07:
+ combinedCode: PK.07
+ code: '07'
+ PK.01:
+ combinedCode: PK.01
+ code: '01'
+ PK.02:
+ combinedCode: PK.02
+ code: '02'
+ PK.06:
+ combinedCode: PK.06
+ code: '06'
+PL:
+ iso2Code: PL
+ iso3Code: POL
+ regions:
+ PL.75:
+ combinedCode: PL.75
+ code: '75'
+ PL.77:
+ combinedCode: PL.77
+ code: '77'
+ PL.78:
+ combinedCode: PL.78
+ code: '78'
+ PL.80:
+ combinedCode: PL.80
+ code: '80'
+ PL.81:
+ combinedCode: PL.81
+ code: '81'
+ PL.84:
+ combinedCode: PL.84
+ code: '84'
+ PL.85:
+ combinedCode: PL.85
+ code: '85'
+ PL.72:
+ combinedCode: PL.72
+ code: '72'
+ PL.74:
+ combinedCode: PL.74
+ code: '74'
+ PL.76:
+ combinedCode: PL.76
+ code: '76'
+ PL.79:
+ combinedCode: PL.79
+ code: '79'
+ PL.82:
+ combinedCode: PL.82
+ code: '82'
+ PL.83:
+ combinedCode: PL.83
+ code: '83'
+ PL.86:
+ combinedCode: PL.86
+ code: '86'
+ PL.87:
+ combinedCode: PL.87
+ code: '87'
+ PL.73:
+ combinedCode: PL.73
+ code: '73'
+PM:
+ iso2Code: PM
+ iso3Code: SPM
+ regions:
+ PM.97502:
+ combinedCode: PM.97502
+ code: '97502'
+ PM.97501:
+ combinedCode: PM.97501
+ code: '97501'
+PN:
+ iso2Code: PN
+ iso3Code: PCN
+ regions: { }
+PR:
+ iso2Code: PR
+ iso3Code: PRI
+ regions:
+ PR.001:
+ combinedCode: PR.001
+ code: '001'
+ PR.003:
+ combinedCode: PR.003
+ code: '003'
+ PR.005:
+ combinedCode: PR.005
+ code: '005'
+ PR.007:
+ combinedCode: PR.007
+ code: '007'
+ PR.009:
+ combinedCode: PR.009
+ code: '009'
+ PR.011:
+ combinedCode: PR.011
+ code: '011'
+ PR.013:
+ combinedCode: PR.013
+ code: '013'
+ PR.015:
+ combinedCode: PR.015
+ code: '015'
+ PR.017:
+ combinedCode: PR.017
+ code: '017'
+ PR.019:
+ combinedCode: PR.019
+ code: '019'
+ PR.021:
+ combinedCode: PR.021
+ code: '021'
+ PR.023:
+ combinedCode: PR.023
+ code: '023'
+ PR.025:
+ combinedCode: PR.025
+ code: '025'
+ PR.027:
+ combinedCode: PR.027
+ code: '027'
+ PR.029:
+ combinedCode: PR.029
+ code: '029'
+ PR.031:
+ combinedCode: PR.031
+ code: '031'
+ PR.033:
+ combinedCode: PR.033
+ code: '033'
+ PR.035:
+ combinedCode: PR.035
+ code: '035'
+ PR.037:
+ combinedCode: PR.037
+ code: '037'
+ PR.039:
+ combinedCode: PR.039
+ code: '039'
+ PR.041:
+ combinedCode: PR.041
+ code: '041'
+ PR.043:
+ combinedCode: PR.043
+ code: '043'
+ PR.045:
+ combinedCode: PR.045
+ code: '045'
+ PR.047:
+ combinedCode: PR.047
+ code: '047'
+ PR.049:
+ combinedCode: PR.049
+ code: '049'
+ PR.051:
+ combinedCode: PR.051
+ code: '051'
+ PR.053:
+ combinedCode: PR.053
+ code: '053'
+ PR.054:
+ combinedCode: PR.054
+ code: '054'
+ PR.055:
+ combinedCode: PR.055
+ code: '055'
+ PR.057:
+ combinedCode: PR.057
+ code: '057'
+ PR.059:
+ combinedCode: PR.059
+ code: '059'
+ PR.061:
+ combinedCode: PR.061
+ code: '061'
+ PR.063:
+ combinedCode: PR.063
+ code: '063'
+ PR.065:
+ combinedCode: PR.065
+ code: '065'
+ PR.067:
+ combinedCode: PR.067
+ code: '067'
+ PR.069:
+ combinedCode: PR.069
+ code: '069'
+ PR.071:
+ combinedCode: PR.071
+ code: '071'
+ PR.073:
+ combinedCode: PR.073
+ code: '073'
+ PR.075:
+ combinedCode: PR.075
+ code: '075'
+ PR.077:
+ combinedCode: PR.077
+ code: '077'
+ PR.079:
+ combinedCode: PR.079
+ code: '079'
+ PR.081:
+ combinedCode: PR.081
+ code: '081'
+ PR.083:
+ combinedCode: PR.083
+ code: '083'
+ PR.085:
+ combinedCode: PR.085
+ code: '085'
+ PR.087:
+ combinedCode: PR.087
+ code: '087'
+ PR.089:
+ combinedCode: PR.089
+ code: '089'
+ PR.091:
+ combinedCode: PR.091
+ code: '091'
+ PR.093:
+ combinedCode: PR.093
+ code: '093'
+ PR.095:
+ combinedCode: PR.095
+ code: '095'
+ PR.097:
+ combinedCode: PR.097
+ code: '097'
+ PR.099:
+ combinedCode: PR.099
+ code: '099'
+ PR.101:
+ combinedCode: PR.101
+ code: '101'
+ PR.103:
+ combinedCode: PR.103
+ code: '103'
+ PR.105:
+ combinedCode: PR.105
+ code: '105'
+ PR.107:
+ combinedCode: PR.107
+ code: '107'
+ PR.109:
+ combinedCode: PR.109
+ code: '109'
+ PR.111:
+ combinedCode: PR.111
+ code: '111'
+ PR.113:
+ combinedCode: PR.113
+ code: '113'
+ PR.117:
+ combinedCode: PR.117
+ code: '117'
+ PR.115:
+ combinedCode: PR.115
+ code: '115'
+ PR.119:
+ combinedCode: PR.119
+ code: '119'
+ PR.121:
+ combinedCode: PR.121
+ code: '121'
+ PR.123:
+ combinedCode: PR.123
+ code: '123'
+ PR.125:
+ combinedCode: PR.125
+ code: '125'
+ PR.127:
+ combinedCode: PR.127
+ code: '127'
+ PR.129:
+ combinedCode: PR.129
+ code: '129'
+ PR.131:
+ combinedCode: PR.131
+ code: '131'
+ PR.133:
+ combinedCode: PR.133
+ code: '133'
+ PR.135:
+ combinedCode: PR.135
+ code: '135'
+ PR.137:
+ combinedCode: PR.137
+ code: '137'
+ PR.139:
+ combinedCode: PR.139
+ code: '139'
+ PR.141:
+ combinedCode: PR.141
+ code: '141'
+ PR.143:
+ combinedCode: PR.143
+ code: '143'
+ PR.145:
+ combinedCode: PR.145
+ code: '145'
+ PR.149:
+ combinedCode: PR.149
+ code: '149'
+ PR.151:
+ combinedCode: PR.151
+ code: '151'
+ PR.153:
+ combinedCode: PR.153
+ code: '153'
+ PR.147:
+ combinedCode: PR.147
+ code: '147'
+PS:
+ iso2Code: PS
+ iso3Code: PSE
+ regions:
+ PS.GZ:
+ combinedCode: PS.GZ
+ code: GZ
+ PS.WE:
+ combinedCode: PS.WE
+ code: WE
+PT:
+ iso2Code: PT
+ iso3Code: PRT
+ regions:
+ PT.19:
+ combinedCode: PT.19
+ code: '19'
+ PT.18:
+ combinedCode: PT.18
+ code: '18'
+ PT.16:
+ combinedCode: PT.16
+ code: '16'
+ PT.14:
+ combinedCode: PT.14
+ code: '14'
+ PT.13:
+ combinedCode: PT.13
+ code: '13'
+ PT.09:
+ combinedCode: PT.09
+ code: '09'
+ PT.08:
+ combinedCode: PT.08
+ code: '08'
+ PT.06:
+ combinedCode: PT.06
+ code: '06'
+ PT.03:
+ combinedCode: PT.03
+ code: '03'
+ PT.10:
+ combinedCode: PT.10
+ code: '10'
+ PT.22:
+ combinedCode: PT.22
+ code: '22'
+ PT.21:
+ combinedCode: PT.21
+ code: '21'
+ PT.20:
+ combinedCode: PT.20
+ code: '20'
+ PT.17:
+ combinedCode: PT.17
+ code: '17'
+ PT.11:
+ combinedCode: PT.11
+ code: '11'
+ PT.07:
+ combinedCode: PT.07
+ code: '07'
+ PT.05:
+ combinedCode: PT.05
+ code: '05'
+ PT.04:
+ combinedCode: PT.04
+ code: '04'
+ PT.02:
+ combinedCode: PT.02
+ code: '02'
+ PT.23:
+ combinedCode: PT.23
+ code: '23'
+PW:
+ iso2Code: PW
+ iso3Code: PLW
+ regions:
+ PW.11:
+ combinedCode: PW.11
+ code: '11'
+ PW.16:
+ combinedCode: PW.16
+ code: '16'
+ PW.05:
+ combinedCode: PW.05
+ code: '05'
+ PW.04:
+ combinedCode: PW.04
+ code: '04'
+ PW.01:
+ combinedCode: PW.01
+ code: '01'
+ PW.02:
+ combinedCode: PW.02
+ code: '02'
+ PW.03:
+ combinedCode: PW.03
+ code: '03'
+ PW.06:
+ combinedCode: PW.06
+ code: '06'
+ PW.07:
+ combinedCode: PW.07
+ code: '07'
+ PW.08:
+ combinedCode: PW.08
+ code: '08'
+ PW.12:
+ combinedCode: PW.12
+ code: '12'
+ PW.09:
+ combinedCode: PW.09
+ code: '09'
+ PW.10:
+ combinedCode: PW.10
+ code: '10'
+ PW.13:
+ combinedCode: PW.13
+ code: '13'
+ PW.14:
+ combinedCode: PW.14
+ code: '14'
+ PW.15:
+ combinedCode: PW.15
+ code: '15'
+PY:
+ iso2Code: PY
+ iso3Code: PRY
+ regions:
+ PY.17:
+ combinedCode: PY.17
+ code: '17'
+ PY.16:
+ combinedCode: PY.16
+ code: '16'
+ PY.15:
+ combinedCode: PY.15
+ code: '15'
+ PY.13:
+ combinedCode: PY.13
+ code: '13'
+ PY.12:
+ combinedCode: PY.12
+ code: '12'
+ PY.11:
+ combinedCode: PY.11
+ code: '11'
+ PY.10:
+ combinedCode: PY.10
+ code: '10'
+ PY.08:
+ combinedCode: PY.08
+ code: '08'
+ PY.07:
+ combinedCode: PY.07
+ code: '07'
+ PY.06:
+ combinedCode: PY.06
+ code: '06'
+ PY.19:
+ combinedCode: PY.19
+ code: '19'
+ PY.05:
+ combinedCode: PY.05
+ code: '05'
+ PY.04:
+ combinedCode: PY.04
+ code: '04'
+ PY.02:
+ combinedCode: PY.02
+ code: '02'
+ PY.01:
+ combinedCode: PY.01
+ code: '01'
+ PY.23:
+ combinedCode: PY.23
+ code: '23'
+ PY.22:
+ combinedCode: PY.22
+ code: '22'
+ PY.24:
+ combinedCode: PY.24
+ code: '24'
+QA:
+ iso2Code: QA
+ iso3Code: QAT
+ regions:
+ QA.08:
+ combinedCode: QA.08
+ code: '08'
+ QA.02:
+ combinedCode: QA.02
+ code: '02'
+ QA.04:
+ combinedCode: QA.04
+ code: '04'
+ QA.09:
+ combinedCode: QA.09
+ code: '09'
+ QA.03:
+ combinedCode: QA.03
+ code: '03'
+ QA.06:
+ combinedCode: QA.06
+ code: '06'
+ QA.01:
+ combinedCode: QA.01
+ code: '01'
+ QA.10:
+ combinedCode: QA.10
+ code: '10'
+ QA.11:
+ combinedCode: QA.11
+ code: '11'
+ QA.12:
+ combinedCode: QA.12
+ code: '12'
+ QA.13:
+ combinedCode: QA.13
+ code: '13'
+RE:
+ iso2Code: RE
+ iso3Code: REU
+ regions:
+ RE.RE:
+ combinedCode: RE.RE
+ code: RE
+RO:
+ iso2Code: RO
+ iso3Code: ROU
+ regions:
+ RO.40:
+ combinedCode: RO.40
+ code: '40'
+ RO.39:
+ combinedCode: RO.39
+ code: '39'
+ RO.38:
+ combinedCode: RO.38
+ code: '38'
+ RO.37:
+ combinedCode: RO.37
+ code: '37'
+ RO.36:
+ combinedCode: RO.36
+ code: '36'
+ RO.35:
+ combinedCode: RO.35
+ code: '35'
+ RO.34:
+ combinedCode: RO.34
+ code: '34'
+ RO.33:
+ combinedCode: RO.33
+ code: '33'
+ RO.32:
+ combinedCode: RO.32
+ code: '32'
+ RO.31:
+ combinedCode: RO.31
+ code: '31'
+ RO.30:
+ combinedCode: RO.30
+ code: '30'
+ RO.29:
+ combinedCode: RO.29
+ code: '29'
+ RO.28:
+ combinedCode: RO.28
+ code: '28'
+ RO.27:
+ combinedCode: RO.27
+ code: '27'
+ RO.26:
+ combinedCode: RO.26
+ code: '26'
+ RO.25:
+ combinedCode: RO.25
+ code: '25'
+ RO.23:
+ combinedCode: RO.23
+ code: '23'
+ RO.22:
+ combinedCode: RO.22
+ code: '22'
+ RO.21:
+ combinedCode: RO.21
+ code: '21'
+ RO.20:
+ combinedCode: RO.20
+ code: '20'
+ RO.19:
+ combinedCode: RO.19
+ code: '19'
+ RO.42:
+ combinedCode: RO.42
+ code: '42'
+ RO.18:
+ combinedCode: RO.18
+ code: '18'
+ RO.17:
+ combinedCode: RO.17
+ code: '17'
+ RO.16:
+ combinedCode: RO.16
+ code: '16'
+ RO.15:
+ combinedCode: RO.15
+ code: '15'
+ RO.14:
+ combinedCode: RO.14
+ code: '14'
+ RO.13:
+ combinedCode: RO.13
+ code: '13'
+ RO.12:
+ combinedCode: RO.12
+ code: '12'
+ RO.41:
+ combinedCode: RO.41
+ code: '41'
+ RO.11:
+ combinedCode: RO.11
+ code: '11'
+ RO.10:
+ combinedCode: RO.10
+ code: '10'
+ RO.09:
+ combinedCode: RO.09
+ code: '09'
+ RO.08:
+ combinedCode: RO.08
+ code: '08'
+ RO.07:
+ combinedCode: RO.07
+ code: '07'
+ RO.06:
+ combinedCode: RO.06
+ code: '06'
+ RO.05:
+ combinedCode: RO.05
+ code: '05'
+ RO.04:
+ combinedCode: RO.04
+ code: '04'
+ RO.03:
+ combinedCode: RO.03
+ code: '03'
+ RO.02:
+ combinedCode: RO.02
+ code: '02'
+ RO.01:
+ combinedCode: RO.01
+ code: '01'
+ RO.43:
+ combinedCode: RO.43
+ code: '43'
+RS:
+ iso2Code: RS
+ iso3Code: SRB
+ regions:
+ RS.VO:
+ combinedCode: RS.VO
+ code: VO
+ RS.SE:
+ combinedCode: RS.SE
+ code: SE
+RU:
+ iso2Code: RU
+ iso3Code: RUS
+ regions:
+ RU.88:
+ combinedCode: RU.88
+ code: '88'
+ RU.86:
+ combinedCode: RU.86
+ code: '86'
+ RU.85:
+ combinedCode: RU.85
+ code: '85'
+ RU.84:
+ combinedCode: RU.84
+ code: '84'
+ RU.81:
+ combinedCode: RU.81
+ code: '81'
+ RU.80:
+ combinedCode: RU.80
+ code: '80'
+ RU.77:
+ combinedCode: RU.77
+ code: '77'
+ RU.76:
+ combinedCode: RU.76
+ code: '76'
+ RU.73:
+ combinedCode: RU.73
+ code: '73'
+ RU.72:
+ combinedCode: RU.72
+ code: '72'
+ RU.70:
+ combinedCode: RU.70
+ code: '70'
+ RU.69:
+ combinedCode: RU.69
+ code: '69'
+ RU.67:
+ combinedCode: RU.67
+ code: '67'
+ RU.65:
+ combinedCode: RU.65
+ code: '65'
+ RU.62:
+ combinedCode: RU.62
+ code: '62'
+ RU.61:
+ combinedCode: RU.61
+ code: '61'
+ RU.60:
+ combinedCode: RU.60
+ code: '60'
+ RU.90:
+ combinedCode: RU.90
+ code: '90'
+ RU.57:
+ combinedCode: RU.57
+ code: '57'
+ RU.56:
+ combinedCode: RU.56
+ code: '56'
+ RU.55:
+ combinedCode: RU.55
+ code: '55'
+ RU.52:
+ combinedCode: RU.52
+ code: '52'
+ RU.68:
+ combinedCode: RU.68
+ code: '68'
+ RU.50:
+ combinedCode: RU.50
+ code: '50'
+ RU.49:
+ combinedCode: RU.49
+ code: '49'
+ RU.48:
+ combinedCode: RU.48
+ code: '48'
+ RU.47:
+ combinedCode: RU.47
+ code: '47'
+ RU.46:
+ combinedCode: RU.46
+ code: '46'
+ RU.45:
+ combinedCode: RU.45
+ code: '45'
+ RU.43:
+ combinedCode: RU.43
+ code: '43'
+ RU.42:
+ combinedCode: RU.42
+ code: '42'
+ RU.66:
+ combinedCode: RU.66
+ code: '66'
+ RU.41:
+ combinedCode: RU.41
+ code: '41'
+ RU.38:
+ combinedCode: RU.38
+ code: '38'
+ RU.37:
+ combinedCode: RU.37
+ code: '37'
+ RU.34:
+ combinedCode: RU.34
+ code: '34'
+ RU.33:
+ combinedCode: RU.33
+ code: '33'
+ RU.28:
+ combinedCode: RU.28
+ code: '28'
+ RU.27:
+ combinedCode: RU.27
+ code: '27'
+ RU.25:
+ combinedCode: RU.25
+ code: '25'
+ RU.24:
+ combinedCode: RU.24
+ code: '24'
+ RU.23:
+ combinedCode: RU.23
+ code: '23'
+ RU.22:
+ combinedCode: RU.22
+ code: '22'
+ RU.21:
+ combinedCode: RU.21
+ code: '21'
+ RU.19:
+ combinedCode: RU.19
+ code: '19'
+ RU.51:
+ combinedCode: RU.51
+ code: '51'
+ RU.17:
+ combinedCode: RU.17
+ code: '17'
+ RU.16:
+ combinedCode: RU.16
+ code: '16'
+ RU.12:
+ combinedCode: RU.12
+ code: '12'
+ RU.10:
+ combinedCode: RU.10
+ code: '10'
+ RU.09:
+ combinedCode: RU.09
+ code: '09'
+ RU.08:
+ combinedCode: RU.08
+ code: '08'
+ RU.07:
+ combinedCode: RU.07
+ code: '07'
+ RU.06:
+ combinedCode: RU.06
+ code: '06'
+ RU.01:
+ combinedCode: RU.01
+ code: '01'
+ RU.83:
+ combinedCode: RU.83
+ code: '83'
+ RU.87:
+ combinedCode: RU.87
+ code: '87'
+ RU.78:
+ combinedCode: RU.78
+ code: '78'
+ RU.79:
+ combinedCode: RU.79
+ code: '79'
+ RU.75:
+ combinedCode: RU.75
+ code: '75'
+ RU.71:
+ combinedCode: RU.71
+ code: '71'
+ RU.54:
+ combinedCode: RU.54
+ code: '54'
+ RU.53:
+ combinedCode: RU.53
+ code: '53'
+ RU.40:
+ combinedCode: RU.40
+ code: '40'
+ RU.91:
+ combinedCode: RU.91
+ code: '91'
+ RU.32:
+ combinedCode: RU.32
+ code: '32'
+ RU.31:
+ combinedCode: RU.31
+ code: '31'
+ RU.29:
+ combinedCode: RU.29
+ code: '29'
+ RU.03:
+ combinedCode: RU.03
+ code: '03'
+ RU.13:
+ combinedCode: RU.13
+ code: '13'
+ RU.04:
+ combinedCode: RU.04
+ code: '04'
+ RU.63:
+ combinedCode: RU.63
+ code: '63'
+ RU.59:
+ combinedCode: RU.59
+ code: '59'
+ RU.30:
+ combinedCode: RU.30
+ code: '30'
+ RU.20:
+ combinedCode: RU.20
+ code: '20'
+ RU.89:
+ combinedCode: RU.89
+ code: '89'
+ RU.05:
+ combinedCode: RU.05
+ code: '05'
+ RU.11:
+ combinedCode: RU.11
+ code: '11'
+ RU.64:
+ combinedCode: RU.64
+ code: '64'
+ RU.44:
+ combinedCode: RU.44
+ code: '44'
+ RU.92:
+ combinedCode: RU.92
+ code: '92'
+ RU.15:
+ combinedCode: RU.15
+ code: '15'
+ RU.93:
+ combinedCode: RU.93
+ code: '93'
+RW:
+ iso2Code: RW
+ iso3Code: RWA
+ regions:
+ RW.11:
+ combinedCode: RW.11
+ code: '11'
+ RW.12:
+ combinedCode: RW.12
+ code: '12'
+ RW.13:
+ combinedCode: RW.13
+ code: '13'
+ RW.14:
+ combinedCode: RW.14
+ code: '14'
+ RW.15:
+ combinedCode: RW.15
+ code: '15'
+SA:
+ iso2Code: SA
+ iso3Code: SAU
+ regions:
+ SA.19:
+ combinedCode: SA.19
+ code: '19'
+ SA.16:
+ combinedCode: SA.16
+ code: '16'
+ SA.14:
+ combinedCode: SA.14
+ code: '14'
+ SA.17:
+ combinedCode: SA.17
+ code: '17'
+ SA.13:
+ combinedCode: SA.13
+ code: '13'
+ SA.11:
+ combinedCode: SA.11
+ code: '11'
+ SA.06:
+ combinedCode: SA.06
+ code: '06'
+ SA.10:
+ combinedCode: SA.10
+ code: '10'
+ SA.08:
+ combinedCode: SA.08
+ code: '08'
+ SA.05:
+ combinedCode: SA.05
+ code: '05'
+ SA.20:
+ combinedCode: SA.20
+ code: '20'
+ SA.15:
+ combinedCode: SA.15
+ code: '15'
+ SA.02:
+ combinedCode: SA.02
+ code: '02'
+SB:
+ iso2Code: SB
+ iso3Code: SLB
+ regions:
+ SB.11:
+ combinedCode: SB.11
+ code: '11'
+ SB.03:
+ combinedCode: SB.03
+ code: '03'
+ SB.07:
+ combinedCode: SB.07
+ code: '07'
+ SB.06:
+ combinedCode: SB.06
+ code: '06'
+ SB.10:
+ combinedCode: SB.10
+ code: '10'
+ SB.09:
+ combinedCode: SB.09
+ code: '09'
+ SB.08:
+ combinedCode: SB.08
+ code: '08'
+ SB.12:
+ combinedCode: SB.12
+ code: '12'
+ SB.13:
+ combinedCode: SB.13
+ code: '13'
+SC:
+ iso2Code: SC
+ iso3Code: SYC
+ regions:
+ SC.23:
+ combinedCode: SC.23
+ code: '23'
+ SC.22:
+ combinedCode: SC.22
+ code: '22'
+ SC.27:
+ combinedCode: SC.27
+ code: '27'
+ SC.20:
+ combinedCode: SC.20
+ code: '20'
+ SC.19:
+ combinedCode: SC.19
+ code: '19'
+ SC.18:
+ combinedCode: SC.18
+ code: '18'
+ SC.17:
+ combinedCode: SC.17
+ code: '17'
+ SC.26:
+ combinedCode: SC.26
+ code: '26'
+ SC.25:
+ combinedCode: SC.25
+ code: '25'
+ SC.24:
+ combinedCode: SC.24
+ code: '24'
+ SC.14:
+ combinedCode: SC.14
+ code: '14'
+ SC.12:
+ combinedCode: SC.12
+ code: '12'
+ SC.11:
+ combinedCode: SC.11
+ code: '11'
+ SC.10:
+ combinedCode: SC.10
+ code: '10'
+ SC.09:
+ combinedCode: SC.09
+ code: '09'
+ SC.08:
+ combinedCode: SC.08
+ code: '08'
+ SC.07:
+ combinedCode: SC.07
+ code: '07'
+ SC.06:
+ combinedCode: SC.06
+ code: '06'
+ SC.05:
+ combinedCode: SC.05
+ code: '05'
+ SC.03:
+ combinedCode: SC.03
+ code: '03'
+ SC.02:
+ combinedCode: SC.02
+ code: '02'
+ SC.01:
+ combinedCode: SC.01
+ code: '01'
+ SC.29:
+ combinedCode: SC.29
+ code: '29'
+ SC.30:
+ combinedCode: SC.30
+ code: '30'
+ SC.28:
+ combinedCode: SC.28
+ code: '28'
+SD:
+ iso2Code: SD
+ iso3Code: SDN
+ regions:
+ SD.43:
+ combinedCode: SD.43
+ code: '43'
+ SD.29:
+ combinedCode: SD.29
+ code: '29'
+ SD.36:
+ combinedCode: SD.36
+ code: '36'
+ SD.38:
+ combinedCode: SD.38
+ code: '38'
+ SD.39:
+ combinedCode: SD.39
+ code: '39'
+ SD.41:
+ combinedCode: SD.41
+ code: '41'
+ SD.42:
+ combinedCode: SD.42
+ code: '42'
+ SD.47:
+ combinedCode: SD.47
+ code: '47'
+ SD.49:
+ combinedCode: SD.49
+ code: '49'
+ SD.50:
+ combinedCode: SD.50
+ code: '50'
+ SD.52:
+ combinedCode: SD.52
+ code: '52'
+ SD.53:
+ combinedCode: SD.53
+ code: '53'
+ SD.55:
+ combinedCode: SD.55
+ code: '55'
+ SD.56:
+ combinedCode: SD.56
+ code: '56'
+ SD.58:
+ combinedCode: SD.58
+ code: '58'
+ SD.60:
+ combinedCode: SD.60
+ code: '60'
+ SD.61:
+ combinedCode: SD.61
+ code: '61'
+SS:
+ iso2Code: SS
+ iso3Code: SSD
+ regions:
+ SS.07:
+ combinedCode: SS.07
+ code: '07'
+ SS.04:
+ combinedCode: SS.04
+ code: '04'
+ SS.06:
+ combinedCode: SS.06
+ code: '06'
+ SS.01:
+ combinedCode: SS.01
+ code: '01'
+ SS.10:
+ combinedCode: SS.10
+ code: '10'
+ SS.09:
+ combinedCode: SS.09
+ code: '09'
+ SS.03:
+ combinedCode: SS.03
+ code: '03'
+ SS.05:
+ combinedCode: SS.05
+ code: '05'
+ SS.02:
+ combinedCode: SS.02
+ code: '02'
+ SS.08:
+ combinedCode: SS.08
+ code: '08'
+SE:
+ iso2Code: SE
+ iso3Code: SWE
+ regions:
+ SE.14:
+ combinedCode: SE.14
+ code: '14'
+ SE.25:
+ combinedCode: SE.25
+ code: '25'
+ SE.24:
+ combinedCode: SE.24
+ code: '24'
+ SE.23:
+ combinedCode: SE.23
+ code: '23'
+ SE.22:
+ combinedCode: SE.22
+ code: '22'
+ SE.21:
+ combinedCode: SE.21
+ code: '21'
+ SE.26:
+ combinedCode: SE.26
+ code: '26'
+ SE.18:
+ combinedCode: SE.18
+ code: '18'
+ SE.16:
+ combinedCode: SE.16
+ code: '16'
+ SE.15:
+ combinedCode: SE.15
+ code: '15'
+ SE.12:
+ combinedCode: SE.12
+ code: '12'
+ SE.10:
+ combinedCode: SE.10
+ code: '10'
+ SE.09:
+ combinedCode: SE.09
+ code: '09'
+ SE.08:
+ combinedCode: SE.08
+ code: '08'
+ SE.07:
+ combinedCode: SE.07
+ code: '07'
+ SE.06:
+ combinedCode: SE.06
+ code: '06'
+ SE.05:
+ combinedCode: SE.05
+ code: '05'
+ SE.03:
+ combinedCode: SE.03
+ code: '03'
+ SE.02:
+ combinedCode: SE.02
+ code: '02'
+ SE.27:
+ combinedCode: SE.27
+ code: '27'
+ SE.28:
+ combinedCode: SE.28
+ code: '28'
+SG:
+ iso2Code: SG
+ iso3Code: SGP
+ regions:
+ SG.01:
+ combinedCode: SG.01
+ code: '01'
+ SG.02:
+ combinedCode: SG.02
+ code: '02'
+ SG.04:
+ combinedCode: SG.04
+ code: '04'
+ SG.05:
+ combinedCode: SG.05
+ code: '05'
+ SG.03:
+ combinedCode: SG.03
+ code: '03'
+SH:
+ iso2Code: SH
+ iso3Code: SHN
+ regions:
+ SH.01:
+ combinedCode: SH.01
+ code: '01'
+ SH.03:
+ combinedCode: SH.03
+ code: '03'
+ SH.02:
+ combinedCode: SH.02
+ code: '02'
+SI:
+ iso2Code: SI
+ iso3Code: SVN
+ regions:
+ SI.N5:
+ combinedCode: SI.N5
+ code: N5
+ SI.E7:
+ combinedCode: SI.E7
+ code: E7
+ SI.E5:
+ combinedCode: SI.E5
+ code: E5
+ SI.D5:
+ combinedCode: SI.D5
+ code: D5
+ SI.D4:
+ combinedCode: SI.D4
+ code: D4
+ SI.D3:
+ combinedCode: SI.D3
+ code: D3
+ SI.D2:
+ combinedCode: SI.D2
+ code: D2
+ SI.D7:
+ combinedCode: SI.D7
+ code: D7
+ SI.C5:
+ combinedCode: SI.C5
+ code: C5
+ SI.C4:
+ combinedCode: SI.C4
+ code: C4
+ SI.L8:
+ combinedCode: SI.L8
+ code: L8
+ SI.C2:
+ combinedCode: SI.C2
+ code: C2
+ SI.B9:
+ combinedCode: SI.B9
+ code: B9
+ SI.B7:
+ combinedCode: SI.B7
+ code: B7
+ SI.B6:
+ combinedCode: SI.B6
+ code: B6
+ SI.L7:
+ combinedCode: SI.L7
+ code: L7
+ SI.L1:
+ combinedCode: SI.L1
+ code: L1
+ SI.A3:
+ combinedCode: SI.A3
+ code: A3
+ SI.A2:
+ combinedCode: SI.A2
+ code: A2
+ SI.K7:
+ combinedCode: SI.K7
+ code: K7
+ SI.94:
+ combinedCode: SI.94
+ code: '94'
+ SI.J9:
+ combinedCode: SI.J9
+ code: J9
+ SI.87:
+ combinedCode: SI.87
+ code: '87'
+ SI.J7:
+ combinedCode: SI.J7
+ code: J7
+ SI.84:
+ combinedCode: SI.84
+ code: '84'
+ SI.80:
+ combinedCode: SI.80
+ code: '80'
+ SI.79:
+ combinedCode: SI.79
+ code: '79'
+ SI.73:
+ combinedCode: SI.73
+ code: '73'
+ SI.J2:
+ combinedCode: SI.J2
+ code: J2
+ SI.64:
+ combinedCode: SI.64
+ code: '64'
+ SI.I6:
+ combinedCode: SI.I6
+ code: I6
+ SI.I5:
+ combinedCode: SI.I5
+ code: I5
+ SI.I3:
+ combinedCode: SI.I3
+ code: I3
+ SI.57:
+ combinedCode: SI.57
+ code: '57'
+ SI.54:
+ combinedCode: SI.54
+ code: '54'
+ SI.52:
+ combinedCode: SI.52
+ code: '52'
+ SI.50:
+ combinedCode: SI.50
+ code: '50'
+ SI.H7:
+ combinedCode: SI.H7
+ code: H7
+ SI.H6:
+ combinedCode: SI.H6
+ code: H6
+ SI.H4:
+ combinedCode: SI.H4
+ code: H4
+ SI.40:
+ combinedCode: SI.40
+ code: '40'
+ SI.38:
+ combinedCode: SI.38
+ code: '38'
+ SI.36:
+ combinedCode: SI.36
+ code: '36'
+ SI.34:
+ combinedCode: SI.34
+ code: '34'
+ SI.32:
+ combinedCode: SI.32
+ code: '32'
+ SI.29:
+ combinedCode: SI.29
+ code: '29'
+ SI.25:
+ combinedCode: SI.25
+ code: '25'
+ SI.G7:
+ combinedCode: SI.G7
+ code: G7
+ SI.17:
+ combinedCode: SI.17
+ code: '17'
+ SI.13:
+ combinedCode: SI.13
+ code: '13'
+ SI.11:
+ combinedCode: SI.11
+ code: '11'
+ SI.08:
+ combinedCode: SI.08
+ code: '08'
+ SI.01:
+ combinedCode: SI.01
+ code: '01'
+ SI.35:
+ combinedCode: SI.35
+ code: '35'
+ SI.19:
+ combinedCode: SI.19
+ code: '19'
+ SI.91:
+ combinedCode: SI.91
+ code: '91'
+ SI.I7:
+ combinedCode: SI.I7
+ code: I7
+ SI.66:
+ combinedCode: SI.66
+ code: '66'
+ SI.88:
+ combinedCode: SI.88
+ code: '88'
+ SI.D8:
+ combinedCode: SI.D8
+ code: D8
+ SI.C1:
+ combinedCode: SI.C1
+ code: C1
+ SI.37:
+ combinedCode: SI.37
+ code: '37'
+ SI.09:
+ combinedCode: SI.09
+ code: '09'
+ SI.05:
+ combinedCode: SI.05
+ code: '05'
+ SI.E1:
+ combinedCode: SI.E1
+ code: E1
+ SI.49:
+ combinedCode: SI.49
+ code: '49'
+ SI.J5:
+ combinedCode: SI.J5
+ code: J5
+ SI.07:
+ combinedCode: SI.07
+ code: '07'
+ SI.44:
+ combinedCode: SI.44
+ code: '44'
+ SI.F2:
+ combinedCode: SI.F2
+ code: F2
+ SI.14:
+ combinedCode: SI.14
+ code: '14'
+ SI.F1:
+ combinedCode: SI.F1
+ code: F1
+ SI.27:
+ combinedCode: SI.27
+ code: '27'
+ SI.G4:
+ combinedCode: SI.G4
+ code: G4
+ SI.46:
+ combinedCode: SI.46
+ code: '46'
+ SI.06:
+ combinedCode: SI.06
+ code: '06'
+ SI.04:
+ combinedCode: SI.04
+ code: '04'
+ SI.03:
+ combinedCode: SI.03
+ code: '03'
+ SI.82:
+ combinedCode: SI.82
+ code: '82'
+ SI.53:
+ combinedCode: SI.53
+ code: '53'
+ SI.K5:
+ combinedCode: SI.K5
+ code: K5
+ SI.12:
+ combinedCode: SI.12
+ code: '12'
+ SI.B2:
+ combinedCode: SI.B2
+ code: B2
+ SI.E3:
+ combinedCode: SI.E3
+ code: E3
+ SI.71:
+ combinedCode: SI.71
+ code: '71'
+ SI.72:
+ combinedCode: SI.72
+ code: '72'
+ SI.22:
+ combinedCode: SI.22
+ code: '22'
+ SI.77:
+ combinedCode: SI.77
+ code: '77'
+ SI.30:
+ combinedCode: SI.30
+ code: '30'
+ SI.I9:
+ combinedCode: SI.I9
+ code: I9
+ SI.K8:
+ combinedCode: SI.K8
+ code: K8
+ SI.74:
+ combinedCode: SI.74
+ code: '74'
+ SI.81:
+ combinedCode: SI.81
+ code: '81'
+ SI.E6:
+ combinedCode: SI.E6
+ code: E6
+ SI.16:
+ combinedCode: SI.16
+ code: '16'
+ SI.62:
+ combinedCode: SI.62
+ code: '62'
+ SI.C7:
+ combinedCode: SI.C7
+ code: C7
+ SI.C6:
+ combinedCode: SI.C6
+ code: C6
+ SI.68:
+ combinedCode: SI.68
+ code: '68'
+ SI.99:
+ combinedCode: SI.99
+ code: '99'
+ SI.39:
+ combinedCode: SI.39
+ code: '39'
+ SI.20:
+ combinedCode: SI.20
+ code: '20'
+ SI.B1:
+ combinedCode: SI.B1
+ code: B1
+ SI.B4:
+ combinedCode: SI.B4
+ code: B4
+ SI.B8:
+ combinedCode: SI.B8
+ code: B8
+ SI.C9:
+ combinedCode: SI.C9
+ code: C9
+ SI.N3:
+ combinedCode: SI.N3
+ code: N3
+ SI.E2:
+ combinedCode: SI.E2
+ code: E2
+ SI.F3:
+ combinedCode: SI.F3
+ code: F3
+ SI.76:
+ combinedCode: SI.76
+ code: '76'
+ SI.L3:
+ combinedCode: SI.L3
+ code: L3
+ SI.55:
+ combinedCode: SI.55
+ code: '55'
+ SI.B3:
+ combinedCode: SI.B3
+ code: B3
+ SI.89:
+ combinedCode: SI.89
+ code: '89'
+ SI.26:
+ combinedCode: SI.26
+ code: '26'
+ SI.98:
+ combinedCode: SI.98
+ code: '98'
+ SI.C8:
+ combinedCode: SI.C8
+ code: C8
+ SI.45:
+ combinedCode: SI.45
+ code: '45'
+ SI.J1:
+ combinedCode: SI.J1
+ code: J1
+ SI.N2:
+ combinedCode: SI.N2
+ code: N2
+ SI.A7:
+ combinedCode: SI.A7
+ code: A7
+ SI.A8:
+ combinedCode: SI.A8
+ code: A8
+ SI.92:
+ combinedCode: SI.92
+ code: '92'
+ SI.51:
+ combinedCode: SI.51
+ code: '51'
+ SI.28:
+ combinedCode: SI.28
+ code: '28'
+ SI.E9:
+ combinedCode: SI.E9
+ code: E9
+ SI.24:
+ combinedCode: SI.24
+ code: '24'
+ SI.42:
+ combinedCode: SI.42
+ code: '42'
+ SI.D1:
+ combinedCode: SI.D1
+ code: D1
+ SI.A1:
+ combinedCode: SI.A1
+ code: A1
+ SI.97:
+ combinedCode: SI.97
+ code: '97'
+ SI.A6:
+ combinedCode: SI.A6
+ code: A6
+ SI.I2:
+ combinedCode: SI.I2
+ code: I2
+ SI.31:
+ combinedCode: SI.31
+ code: '31'
+ SI.78:
+ combinedCode: SI.78
+ code: '78'
+ SI.47:
+ combinedCode: SI.47
+ code: '47'
+ SI.02:
+ combinedCode: SI.02
+ code: '02'
+ SI.D6:
+ combinedCode: SI.D6
+ code: D6
+ SI.86:
+ combinedCode: SI.86
+ code: '86'
+ SI.15:
+ combinedCode: SI.15
+ code: '15'
+ SI.83:
+ combinedCode: SI.83
+ code: '83'
+ SI.61:
+ combinedCode: SI.61
+ code: '61'
+ SI.N7:
+ combinedCode: SI.N7
+ code: N7
+ SI.H5:
+ combinedCode: SI.H5
+ code: H5
+ SI.M2:
+ combinedCode: SI.M2
+ code: M2
+ SI.H8:
+ combinedCode: SI.H8
+ code: H8
+ SI.H3:
+ combinedCode: SI.H3
+ code: H3
+ SI.L6:
+ combinedCode: SI.L6
+ code: L6
+ SI.F6:
+ combinedCode: SI.F6
+ code: F6
+ SI.M1:
+ combinedCode: SI.M1
+ code: M1
+ SI.M8:
+ combinedCode: SI.M8
+ code: M8
+ SI.K6:
+ combinedCode: SI.K6
+ code: K6
+ SI.N4:
+ combinedCode: SI.N4
+ code: N4
+ SI.M5:
+ combinedCode: SI.M5
+ code: M5
+ SI.F7:
+ combinedCode: SI.F7
+ code: F7
+ SI.K3:
+ combinedCode: SI.K3
+ code: K3
+ SI.K4:
+ combinedCode: SI.K4
+ code: K4
+ SI.H9:
+ combinedCode: SI.H9
+ code: H9
+ SI.N8:
+ combinedCode: SI.N8
+ code: N8
+ SI.G6:
+ combinedCode: SI.G6
+ code: G6
+ SI.J6:
+ combinedCode: SI.J6
+ code: J6
+ SI.F5:
+ combinedCode: SI.F5
+ code: F5
+ SI.G2:
+ combinedCode: SI.G2
+ code: G2
+ SI.G3:
+ combinedCode: SI.G3
+ code: G3
+ SI.J8:
+ combinedCode: SI.J8
+ code: J8
+ SI.K2:
+ combinedCode: SI.K2
+ code: K2
+ SI.L2:
+ combinedCode: SI.L2
+ code: L2
+ SI.I8:
+ combinedCode: SI.I8
+ code: I8
+ SI.L5:
+ combinedCode: SI.L5
+ code: L5
+ SI.H1:
+ combinedCode: SI.H1
+ code: H1
+ SI.J4:
+ combinedCode: SI.J4
+ code: J4
+ SI.G9:
+ combinedCode: SI.G9
+ code: G9
+ SI.N6:
+ combinedCode: SI.N6
+ code: N6
+ SI.K1:
+ combinedCode: SI.K1
+ code: K1
+ SI.J3:
+ combinedCode: SI.J3
+ code: J3
+ SI.G1:
+ combinedCode: SI.G1
+ code: G1
+ SI.M7:
+ combinedCode: SI.M7
+ code: M7
+ SI.M4:
+ combinedCode: SI.M4
+ code: M4
+ SI.F9:
+ combinedCode: SI.F9
+ code: F9
+ SI.F4:
+ combinedCode: SI.F4
+ code: F4
+ SI.M3:
+ combinedCode: SI.M3
+ code: M3
+ SI.I1:
+ combinedCode: SI.I1
+ code: I1
+ SI.N1:
+ combinedCode: SI.N1
+ code: N1
+ SI.M9:
+ combinedCode: SI.M9
+ code: M9
+ SI.I4:
+ combinedCode: SI.I4
+ code: I4
+ SI.G5:
+ combinedCode: SI.G5
+ code: G5
+ SI.M6:
+ combinedCode: SI.M6
+ code: M6
+ SI.F8:
+ combinedCode: SI.F8
+ code: F8
+ SI.G8:
+ combinedCode: SI.G8
+ code: G8
+ SI.H2:
+ combinedCode: SI.H2
+ code: H2
+ SI.K9:
+ combinedCode: SI.K9
+ code: K9
+ SI.L9:
+ combinedCode: SI.L9
+ code: L9
+ SI.L4:
+ combinedCode: SI.L4
+ code: L4
+ SI.N9:
+ combinedCode: SI.N9
+ code: N9
+ SI.O1:
+ combinedCode: SI.O1
+ code: O1
+ SI.O3:
+ combinedCode: SI.O3
+ code: O3
+ SI.O4:
+ combinedCode: SI.O4
+ code: O4
+ SI.O5:
+ combinedCode: SI.O5
+ code: O5
+ SI.O7:
+ combinedCode: SI.O7
+ code: O7
+ SI.O8:
+ combinedCode: SI.O8
+ code: O8
+ SI.O9:
+ combinedCode: SI.O9
+ code: O9
+ SI.P1:
+ combinedCode: SI.P1
+ code: P1
+ SI.P4:
+ combinedCode: SI.P4
+ code: P4
+ SI.P5:
+ combinedCode: SI.P5
+ code: P5
+ SI.P6:
+ combinedCode: SI.P6
+ code: P6
+ SI.P8:
+ combinedCode: SI.P8
+ code: P8
+ SI.P2:
+ combinedCode: SI.P2
+ code: P2
+ SI.P3:
+ combinedCode: SI.P3
+ code: P3
+ SI.P7:
+ combinedCode: SI.P7
+ code: P7
+SJ:
+ iso2Code: SJ
+ iso3Code: SJM
+ regions:
+ SJ.22:
+ combinedCode: SJ.22
+ code: '22'
+ SJ.21:
+ combinedCode: SJ.21
+ code: '21'
+SK:
+ iso2Code: SK
+ iso3Code: SVK
+ regions:
+ SK.03:
+ combinedCode: SK.03
+ code: '03'
+ SK.05:
+ combinedCode: SK.05
+ code: '05'
+ SK.08:
+ combinedCode: SK.08
+ code: '08'
+ SK.01:
+ combinedCode: SK.01
+ code: '01'
+ SK.02:
+ combinedCode: SK.02
+ code: '02'
+ SK.04:
+ combinedCode: SK.04
+ code: '04'
+ SK.06:
+ combinedCode: SK.06
+ code: '06'
+ SK.07:
+ combinedCode: SK.07
+ code: '07'
+SL:
+ iso2Code: SL
+ iso3Code: SLE
+ regions:
+ SL.04:
+ combinedCode: SL.04
+ code: '04'
+ SL.03:
+ combinedCode: SL.03
+ code: '03'
+ SL.02:
+ combinedCode: SL.02
+ code: '02'
+ SL.01:
+ combinedCode: SL.01
+ code: '01'
+SM:
+ iso2Code: SM
+ iso3Code: SMR
+ regions:
+ SM.09:
+ combinedCode: SM.09
+ code: '09'
+ SM.02:
+ combinedCode: SM.02
+ code: '02'
+ SM.07:
+ combinedCode: SM.07
+ code: '07'
+ SM.01:
+ combinedCode: SM.01
+ code: '01'
+ SM.06:
+ combinedCode: SM.06
+ code: '06'
+ SM.03:
+ combinedCode: SM.03
+ code: '03'
+ SM.04:
+ combinedCode: SM.04
+ code: '04'
+ SM.05:
+ combinedCode: SM.05
+ code: '05'
+ SM.08:
+ combinedCode: SM.08
+ code: '08'
+SN:
+ iso2Code: SN
+ iso3Code: SEN
+ regions:
+ SN.12:
+ combinedCode: SN.12
+ code: '12'
+ SN.07:
+ combinedCode: SN.07
+ code: '07'
+ SN.05:
+ combinedCode: SN.05
+ code: '05'
+ SN.14:
+ combinedCode: SN.14
+ code: '14'
+ SN.15:
+ combinedCode: SN.15
+ code: '15'
+ SN.13:
+ combinedCode: SN.13
+ code: '13'
+ SN.11:
+ combinedCode: SN.11
+ code: '11'
+ SN.10:
+ combinedCode: SN.10
+ code: '10'
+ SN.09:
+ combinedCode: SN.09
+ code: '09'
+ SN.03:
+ combinedCode: SN.03
+ code: '03'
+ SN.01:
+ combinedCode: SN.01
+ code: '01'
+ SN.16:
+ combinedCode: SN.16
+ code: '16'
+ SN.17:
+ combinedCode: SN.17
+ code: '17'
+ SN.18:
+ combinedCode: SN.18
+ code: '18'
+SO:
+ iso2Code: SO
+ iso3Code: SOM
+ regions:
+ SO.20:
+ combinedCode: SO.20
+ code: '20'
+ SO.19:
+ combinedCode: SO.19
+ code: '19'
+ SO.14:
+ combinedCode: SO.14
+ code: '14'
+ SO.13:
+ combinedCode: SO.13
+ code: '13'
+ SO.12:
+ combinedCode: SO.12
+ code: '12'
+ SO.18:
+ combinedCode: SO.18
+ code: '18'
+ SO.10:
+ combinedCode: SO.10
+ code: '10'
+ SO.09:
+ combinedCode: SO.09
+ code: '09'
+ SO.08:
+ combinedCode: SO.08
+ code: '08'
+ SO.07:
+ combinedCode: SO.07
+ code: '07'
+ SO.06:
+ combinedCode: SO.06
+ code: '06'
+ SO.05:
+ combinedCode: SO.05
+ code: '05'
+ SO.04:
+ combinedCode: SO.04
+ code: '04'
+ SO.03:
+ combinedCode: SO.03
+ code: '03'
+ SO.02:
+ combinedCode: SO.02
+ code: '02'
+ SO.01:
+ combinedCode: SO.01
+ code: '01'
+ SO.21:
+ combinedCode: SO.21
+ code: '21'
+ SO.22:
+ combinedCode: SO.22
+ code: '22'
+SR:
+ iso2Code: SR
+ iso3Code: SUR
+ regions:
+ SR.19:
+ combinedCode: SR.19
+ code: '19'
+ SR.18:
+ combinedCode: SR.18
+ code: '18'
+ SR.17:
+ combinedCode: SR.17
+ code: '17'
+ SR.16:
+ combinedCode: SR.16
+ code: '16'
+ SR.15:
+ combinedCode: SR.15
+ code: '15'
+ SR.14:
+ combinedCode: SR.14
+ code: '14'
+ SR.13:
+ combinedCode: SR.13
+ code: '13'
+ SR.12:
+ combinedCode: SR.12
+ code: '12'
+ SR.11:
+ combinedCode: SR.11
+ code: '11'
+ SR.10:
+ combinedCode: SR.10
+ code: '10'
+ST:
+ iso2Code: ST
+ iso3Code: STP
+ regions:
+ ST.02:
+ combinedCode: ST.02
+ code: '02'
+ ST.01:
+ combinedCode: ST.01
+ code: '01'
+SV:
+ iso2Code: SV
+ iso3Code: SLV
+ regions:
+ SV.14:
+ combinedCode: SV.14
+ code: '14'
+ SV.13:
+ combinedCode: SV.13
+ code: '13'
+ SV.12:
+ combinedCode: SV.12
+ code: '12'
+ SV.11:
+ combinedCode: SV.11
+ code: '11'
+ SV.10:
+ combinedCode: SV.10
+ code: '10'
+ SV.09:
+ combinedCode: SV.09
+ code: '09'
+ SV.08:
+ combinedCode: SV.08
+ code: '08'
+ SV.07:
+ combinedCode: SV.07
+ code: '07'
+ SV.06:
+ combinedCode: SV.06
+ code: '06'
+ SV.05:
+ combinedCode: SV.05
+ code: '05'
+ SV.04:
+ combinedCode: SV.04
+ code: '04'
+ SV.03:
+ combinedCode: SV.03
+ code: '03'
+ SV.02:
+ combinedCode: SV.02
+ code: '02'
+ SV.01:
+ combinedCode: SV.01
+ code: '01'
+SX:
+ iso2Code: SX
+ iso3Code: SXM
+ regions: { }
+SY:
+ iso2Code: SY
+ iso3Code: SYR
+ regions:
+ SY.14:
+ combinedCode: SY.14
+ code: '14'
+ SY.13:
+ combinedCode: SY.13
+ code: '13'
+ SY.12:
+ combinedCode: SY.12
+ code: '12'
+ SY.11:
+ combinedCode: SY.11
+ code: '11'
+ SY.10:
+ combinedCode: SY.10
+ code: '10'
+ SY.09:
+ combinedCode: SY.09
+ code: '09'
+ SY.08:
+ combinedCode: SY.08
+ code: '08'
+ SY.07:
+ combinedCode: SY.07
+ code: '07'
+ SY.06:
+ combinedCode: SY.06
+ code: '06'
+ SY.05:
+ combinedCode: SY.05
+ code: '05'
+ SY.04:
+ combinedCode: SY.04
+ code: '04'
+ SY.03:
+ combinedCode: SY.03
+ code: '03'
+ SY.02:
+ combinedCode: SY.02
+ code: '02'
+ SY.01:
+ combinedCode: SY.01
+ code: '01'
+SZ:
+ iso2Code: SZ
+ iso3Code: SWZ
+ regions:
+ SZ.04:
+ combinedCode: SZ.04
+ code: '04'
+ SZ.03:
+ combinedCode: SZ.03
+ code: '03'
+ SZ.02:
+ combinedCode: SZ.02
+ code: '02'
+ SZ.01:
+ combinedCode: SZ.01
+ code: '01'
+TC:
+ iso2Code: TC
+ iso3Code: TCA
+ regions: { }
+TD:
+ iso2Code: TD
+ iso3Code: TCD
+ regions:
+ TD.13:
+ combinedCode: TD.13
+ code: '13'
+ TD.12:
+ combinedCode: TD.12
+ code: '12'
+ TD.02:
+ combinedCode: TD.02
+ code: '02'
+ TD.14:
+ combinedCode: TD.14
+ code: '14'
+ TD.17:
+ combinedCode: TD.17
+ code: '17'
+ TD.16:
+ combinedCode: TD.16
+ code: '16'
+ TD.09:
+ combinedCode: TD.09
+ code: '09'
+ TD.08:
+ combinedCode: TD.08
+ code: '08'
+ TD.07:
+ combinedCode: TD.07
+ code: '07'
+ TD.06:
+ combinedCode: TD.06
+ code: '06'
+ TD.05:
+ combinedCode: TD.05
+ code: '05'
+ TD.15:
+ combinedCode: TD.15
+ code: '15'
+ TD.01:
+ combinedCode: TD.01
+ code: '01'
+ TD.23:
+ combinedCode: TD.23
+ code: '23'
+ TD.18:
+ combinedCode: TD.18
+ code: '18'
+ TD.19:
+ combinedCode: TD.19
+ code: '19'
+ TD.20:
+ combinedCode: TD.20
+ code: '20'
+ TD.21:
+ combinedCode: TD.21
+ code: '21'
+ TD.22:
+ combinedCode: TD.22
+ code: '22'
+ TD.24:
+ combinedCode: TD.24
+ code: '24'
+ TD.25:
+ combinedCode: TD.25
+ code: '25'
+ TD.26:
+ combinedCode: TD.26
+ code: '26'
+TF:
+ iso2Code: TF
+ iso3Code: ATF
+ regions:
+ TF.02:
+ combinedCode: TF.02
+ code: '02'
+ TF.03:
+ combinedCode: TF.03
+ code: '03'
+ TF.01:
+ combinedCode: TF.01
+ code: '01'
+ TF.05:
+ combinedCode: TF.05
+ code: '05'
+ TF.04:
+ combinedCode: TF.04
+ code: '04'
+TG:
+ iso2Code: TG
+ iso3Code: TGO
+ regions:
+ TG.26:
+ combinedCode: TG.26
+ code: '26'
+ TG.25:
+ combinedCode: TG.25
+ code: '25'
+ TG.24:
+ combinedCode: TG.24
+ code: '24'
+ TG.22:
+ combinedCode: TG.22
+ code: '22'
+ TG.23:
+ combinedCode: TG.23
+ code: '23'
+TH:
+ iso2Code: TH
+ iso3Code: THA
+ regions:
+ TH.15:
+ combinedCode: TH.15
+ code: '15'
+ TH.65:
+ combinedCode: TH.65
+ code: '65'
+ TH.08:
+ combinedCode: TH.08
+ code: '08'
+ TH.60:
+ combinedCode: TH.60
+ code: '60'
+ TH.09:
+ combinedCode: TH.09
+ code: '09'
+ TH.52:
+ combinedCode: TH.52
+ code: '52'
+ TH.59:
+ combinedCode: TH.59
+ code: '59'
+ TH.57:
+ combinedCode: TH.57
+ code: '57'
+ TH.62:
+ combinedCode: TH.62
+ code: '62'
+ TH.56:
+ combinedCode: TH.56
+ code: '56'
+ TH.61:
+ combinedCode: TH.61
+ code: '61'
+ TH.01:
+ combinedCode: TH.01
+ code: '01'
+ TH.05:
+ combinedCode: TH.05
+ code: '05'
+ TH.06:
+ combinedCode: TH.06
+ code: '06'
+ TH.63:
+ combinedCode: TH.63
+ code: '63'
+ TH.50:
+ combinedCode: TH.50
+ code: '50'
+ TH.11:
+ combinedCode: TH.11
+ code: '11'
+ TH.58:
+ combinedCode: TH.58
+ code: '58'
+ TH.03:
+ combinedCode: TH.03
+ code: '03'
+ TH.02:
+ combinedCode: TH.02
+ code: '02'
+ TH.72:
+ combinedCode: TH.72
+ code: '72'
+ TH.70:
+ combinedCode: TH.70
+ code: '70'
+ TH.10:
+ combinedCode: TH.10
+ code: '10'
+ TH.49:
+ combinedCode: TH.49
+ code: '49'
+ TH.29:
+ combinedCode: TH.29
+ code: '29'
+ TH.51:
+ combinedCode: TH.51
+ code: '51'
+ TH.68:
+ combinedCode: TH.68
+ code: '68'
+ TH.30:
+ combinedCode: TH.30
+ code: '30'
+ TH.33:
+ combinedCode: TH.33
+ code: '33'
+ TH.67:
+ combinedCode: TH.67
+ code: '67'
+ TH.37:
+ combinedCode: TH.37
+ code: '37'
+ TH.54:
+ combinedCode: TH.54
+ code: '54'
+ TH.55:
+ combinedCode: TH.55
+ code: '55'
+ TH.42:
+ combinedCode: TH.42
+ code: '42'
+ TH.20:
+ combinedCode: TH.20
+ code: '20'
+ TH.25:
+ combinedCode: TH.25
+ code: '25'
+ TH.47:
+ combinedCode: TH.47
+ code: '47'
+ TH.36:
+ combinedCode: TH.36
+ code: '36'
+ TH.07:
+ combinedCode: TH.07
+ code: '07'
+ TH.12:
+ combinedCode: TH.12
+ code: '12'
+ TH.13:
+ combinedCode: TH.13
+ code: '13'
+ TH.14:
+ combinedCode: TH.14
+ code: '14'
+ TH.41:
+ combinedCode: TH.41
+ code: '41'
+ TH.66:
+ combinedCode: TH.66
+ code: '66'
+ TH.69:
+ combinedCode: TH.69
+ code: '69'
+ TH.39:
+ combinedCode: TH.39
+ code: '39'
+ TH.38:
+ combinedCode: TH.38
+ code: '38'
+ TH.17:
+ combinedCode: TH.17
+ code: '17'
+ TH.31:
+ combinedCode: TH.31
+ code: '31'
+ TH.04:
+ combinedCode: TH.04
+ code: '04'
+ TH.64:
+ combinedCode: TH.64
+ code: '64'
+ TH.16:
+ combinedCode: TH.16
+ code: '16'
+ TH.27:
+ combinedCode: TH.27
+ code: '27'
+ TH.73:
+ combinedCode: TH.73
+ code: '73'
+ TH.53:
+ combinedCode: TH.53
+ code: '53'
+ TH.43:
+ combinedCode: TH.43
+ code: '43'
+ TH.78:
+ combinedCode: TH.78
+ code: '78'
+ TH.24:
+ combinedCode: TH.24
+ code: '24'
+ TH.34:
+ combinedCode: TH.34
+ code: '34'
+ TH.18:
+ combinedCode: TH.18
+ code: '18'
+ TH.40:
+ combinedCode: TH.40
+ code: '40'
+ TH.22:
+ combinedCode: TH.22
+ code: '22'
+ TH.23:
+ combinedCode: TH.23
+ code: '23'
+ TH.46:
+ combinedCode: TH.46
+ code: '46'
+ TH.48:
+ combinedCode: TH.48
+ code: '48'
+ TH.26:
+ combinedCode: TH.26
+ code: '26'
+ TH.32:
+ combinedCode: TH.32
+ code: '32'
+ TH.44:
+ combinedCode: TH.44
+ code: '44'
+ TH.28:
+ combinedCode: TH.28
+ code: '28'
+ TH.35:
+ combinedCode: TH.35
+ code: '35'
+ TH.76:
+ combinedCode: TH.76
+ code: '76'
+ TH.74:
+ combinedCode: TH.74
+ code: '74'
+ TH.75:
+ combinedCode: TH.75
+ code: '75'
+ TH.77:
+ combinedCode: TH.77
+ code: '77'
+ TH.79:
+ combinedCode: TH.79
+ code: '79'
+ TH.80:
+ combinedCode: TH.80
+ code: '80'
+ TH.81:
+ combinedCode: TH.81
+ code: '81'
+TJ:
+ iso2Code: TJ
+ iso3Code: TJK
+ regions:
+ TJ.03:
+ combinedCode: TJ.03
+ code: '03'
+ TJ.01:
+ combinedCode: TJ.01
+ code: '01'
+ TJ.02:
+ combinedCode: TJ.02
+ code: '02'
+ TJ.RR:
+ combinedCode: TJ.RR
+ code: RR
+ TJ.7280679:
+ combinedCode: TJ.7280679
+ code: '7280679'
+TK:
+ iso2Code: TK
+ iso3Code: TKL
+ regions:
+ TK.N:
+ combinedCode: TK.N
+ code: N
+ TK.F:
+ combinedCode: TK.F
+ code: F
+ TK.A:
+ combinedCode: TK.A
+ code: A
+TL:
+ iso2Code: TL
+ iso3Code: TLS
+ regions:
+ TL.VI:
+ combinedCode: TL.VI
+ code: VI
+ TL.MF:
+ combinedCode: TL.MF
+ code: MF
+ TL.MT:
+ combinedCode: TL.MT
+ code: MT
+ TL.LI:
+ combinedCode: TL.LI
+ code: LI
+ TL.LA:
+ combinedCode: TL.LA
+ code: LA
+ TL.CO:
+ combinedCode: TL.CO
+ code: CO
+ TL.ER:
+ combinedCode: TL.ER
+ code: ER
+ TL.DI:
+ combinedCode: TL.DI
+ code: DI
+ TL.BO:
+ combinedCode: TL.BO
+ code: BO
+ TL.BA:
+ combinedCode: TL.BA
+ code: BA
+ TL.OE:
+ combinedCode: TL.OE
+ code: OE
+ TL.AN:
+ combinedCode: TL.AN
+ code: AN
+ TL.AL:
+ combinedCode: TL.AL
+ code: AL
+TM:
+ iso2Code: TM
+ iso3Code: TKM
+ regions:
+ TM.02:
+ combinedCode: TM.02
+ code: '02'
+ TM.01:
+ combinedCode: TM.01
+ code: '01'
+ TM.03:
+ combinedCode: TM.03
+ code: '03'
+ TM.05:
+ combinedCode: TM.05
+ code: '05'
+ TM.04:
+ combinedCode: TM.04
+ code: '04'
+TN:
+ iso2Code: TN
+ iso3Code: TUN
+ regions:
+ TN.37:
+ combinedCode: TN.37
+ code: '37'
+ TN.36:
+ combinedCode: TN.36
+ code: '36'
+ TN.35:
+ combinedCode: TN.35
+ code: '35'
+ TN.34:
+ combinedCode: TN.34
+ code: '34'
+ TN.23:
+ combinedCode: TN.23
+ code: '23'
+ TN.22:
+ combinedCode: TN.22
+ code: '22'
+ TN.33:
+ combinedCode: TN.33
+ code: '33'
+ TN.32:
+ combinedCode: TN.32
+ code: '32'
+ TN.31:
+ combinedCode: TN.31
+ code: '31'
+ TN.30:
+ combinedCode: TN.30
+ code: '30'
+ TN.29:
+ combinedCode: TN.29
+ code: '29'
+ TN.19:
+ combinedCode: TN.19
+ code: '19'
+ TN.28:
+ combinedCode: TN.28
+ code: '28'
+ TN.06:
+ combinedCode: TN.06
+ code: '06'
+ TN.27:
+ combinedCode: TN.27
+ code: '27'
+ TN.18:
+ combinedCode: TN.18
+ code: '18'
+ TN.17:
+ combinedCode: TN.17
+ code: '17'
+ TN.38:
+ combinedCode: TN.38
+ code: '38'
+ TN.03:
+ combinedCode: TN.03
+ code: '03'
+ TN.02:
+ combinedCode: TN.02
+ code: '02'
+ TN.16:
+ combinedCode: TN.16
+ code: '16'
+ TN.15:
+ combinedCode: TN.15
+ code: '15'
+ TN.14:
+ combinedCode: TN.14
+ code: '14'
+ TN.39:
+ combinedCode: TN.39
+ code: '39'
+TO:
+ iso2Code: TO
+ iso3Code: TON
+ regions:
+ TO.03:
+ combinedCode: TO.03
+ code: '03'
+ TO.02:
+ combinedCode: TO.02
+ code: '02'
+ TO.01:
+ combinedCode: TO.01
+ code: '01'
+ TO.EU:
+ combinedCode: TO.EU
+ code: EU
+ TO.NI:
+ combinedCode: TO.NI
+ code: NI
+TR:
+ iso2Code: TR
+ iso3Code: TUR
+ regions:
+ TR.66:
+ combinedCode: TR.66
+ code: '66'
+ TR.65:
+ combinedCode: TR.65
+ code: '65'
+ TR.64:
+ combinedCode: TR.64
+ code: '64'
+ TR.63:
+ combinedCode: TR.63
+ code: '63'
+ TR.62:
+ combinedCode: TR.62
+ code: '62'
+ TR.58:
+ combinedCode: TR.58
+ code: '58'
+ TR.74:
+ combinedCode: TR.74
+ code: '74'
+ TR.73:
+ combinedCode: TR.73
+ code: '73'
+ TR.50:
+ combinedCode: TR.50
+ code: '50'
+ TR.49:
+ combinedCode: TR.49
+ code: '49'
+ TR.48:
+ combinedCode: TR.48
+ code: '48'
+ TR.72:
+ combinedCode: TR.72
+ code: '72'
+ TR.45:
+ combinedCode: TR.45
+ code: '45'
+ TR.44:
+ combinedCode: TR.44
+ code: '44'
+ TR.43:
+ combinedCode: TR.43
+ code: '43'
+ TR.71:
+ combinedCode: TR.71
+ code: '71'
+ TR.40:
+ combinedCode: TR.40
+ code: '40'
+ TR.38:
+ combinedCode: TR.38
+ code: '38'
+ TR.46:
+ combinedCode: TR.46
+ code: '46'
+ TR.35:
+ combinedCode: TR.35
+ code: '35'
+ TR.33:
+ combinedCode: TR.33
+ code: '33'
+ TR.32:
+ combinedCode: TR.32
+ code: '32'
+ TR.31:
+ combinedCode: TR.31
+ code: '31'
+ TR.70:
+ combinedCode: TR.70
+ code: '70'
+ TR.83:
+ combinedCode: TR.83
+ code: '83'
+ TR.26:
+ combinedCode: TR.26
+ code: '26'
+ TR.25:
+ combinedCode: TR.25
+ code: '25'
+ TR.24:
+ combinedCode: TR.24
+ code: '24'
+ TR.23:
+ combinedCode: TR.23
+ code: '23'
+ TR.21:
+ combinedCode: TR.21
+ code: '21'
+ TR.20:
+ combinedCode: TR.20
+ code: '20'
+ TR.15:
+ combinedCode: TR.15
+ code: '15'
+ TR.13:
+ combinedCode: TR.13
+ code: '13'
+ TR.12:
+ combinedCode: TR.12
+ code: '12'
+ TR.11:
+ combinedCode: TR.11
+ code: '11'
+ TR.10:
+ combinedCode: TR.10
+ code: '10'
+ TR.09:
+ combinedCode: TR.09
+ code: '09'
+ TR.07:
+ combinedCode: TR.07
+ code: '07'
+ TR.68:
+ combinedCode: TR.68
+ code: '68'
+ TR.04:
+ combinedCode: TR.04
+ code: '04'
+ TR.03:
+ combinedCode: TR.03
+ code: '03'
+ TR.02:
+ combinedCode: TR.02
+ code: '02'
+ TR.81:
+ combinedCode: TR.81
+ code: '81'
+ TR.91:
+ combinedCode: TR.91
+ code: '91'
+ TR.88:
+ combinedCode: TR.88
+ code: '88'
+ TR.75:
+ combinedCode: TR.75
+ code: '75'
+ TR.76:
+ combinedCode: TR.76
+ code: '76'
+ TR.78:
+ combinedCode: TR.78
+ code: '78'
+ TR.79:
+ combinedCode: TR.79
+ code: '79'
+ TR.80:
+ combinedCode: TR.80
+ code: '80'
+ TR.90:
+ combinedCode: TR.90
+ code: '90'
+ TR.85:
+ combinedCode: TR.85
+ code: '85'
+ TR.61:
+ combinedCode: TR.61
+ code: '61'
+ TR.60:
+ combinedCode: TR.60
+ code: '60'
+ TR.59:
+ combinedCode: TR.59
+ code: '59'
+ TR.57:
+ combinedCode: TR.57
+ code: '57'
+ TR.55:
+ combinedCode: TR.55
+ code: '55'
+ TR.54:
+ combinedCode: TR.54
+ code: '54'
+ TR.53:
+ combinedCode: TR.53
+ code: '53'
+ TR.52:
+ combinedCode: TR.52
+ code: '52'
+ TR.41:
+ combinedCode: TR.41
+ code: '41'
+ TR.39:
+ combinedCode: TR.39
+ code: '39'
+ TR.37:
+ combinedCode: TR.37
+ code: '37'
+ TR.84:
+ combinedCode: TR.84
+ code: '84'
+ TR.34:
+ combinedCode: TR.34
+ code: '34'
+ TR.69:
+ combinedCode: TR.69
+ code: '69'
+ TR.28:
+ combinedCode: TR.28
+ code: '28'
+ TR.22:
+ combinedCode: TR.22
+ code: '22'
+ TR.19:
+ combinedCode: TR.19
+ code: '19'
+ TR.82:
+ combinedCode: TR.82
+ code: '82'
+ TR.17:
+ combinedCode: TR.17
+ code: '17'
+ TR.16:
+ combinedCode: TR.16
+ code: '16'
+ TR.14:
+ combinedCode: TR.14
+ code: '14'
+ TR.08:
+ combinedCode: TR.08
+ code: '08'
+ TR.05:
+ combinedCode: TR.05
+ code: '05'
+ TR.87:
+ combinedCode: TR.87
+ code: '87'
+ TR.89:
+ combinedCode: TR.89
+ code: '89'
+ TR.92:
+ combinedCode: TR.92
+ code: '92'
+ TR.86:
+ combinedCode: TR.86
+ code: '86'
+ TR.77:
+ combinedCode: TR.77
+ code: '77'
+ TR.93:
+ combinedCode: TR.93
+ code: '93'
+TT:
+ iso2Code: TT
+ iso3Code: TTO
+ regions:
+ TT.11:
+ combinedCode: TT.11
+ code: '11'
+ TT.10:
+ combinedCode: TT.10
+ code: '10'
+ TT.05:
+ combinedCode: TT.05
+ code: '05'
+ TT.03:
+ combinedCode: TT.03
+ code: '03'
+ TT.01:
+ combinedCode: TT.01
+ code: '01'
+ TT.CHA:
+ combinedCode: TT.CHA
+ code: CHA
+ TT.CTT:
+ combinedCode: TT.CTT
+ code: CTT
+ TT.DMN:
+ combinedCode: TT.DMN
+ code: DMN
+ TT.ETO:
+ combinedCode: TT.ETO
+ code: ETO
+ TT.PED:
+ combinedCode: TT.PED
+ code: PED
+ TT.PRT:
+ combinedCode: TT.PRT
+ code: PRT
+ TT.PTF:
+ combinedCode: TT.PTF
+ code: PTF
+ TT.SGE:
+ combinedCode: TT.SGE
+ code: SGE
+ TT.SIP:
+ combinedCode: TT.SIP
+ code: SIP
+ TT.SJL:
+ combinedCode: TT.SJL
+ code: SJL
+ TT.TUP:
+ combinedCode: TT.TUP
+ code: TUP
+TV:
+ iso2Code: TV
+ iso3Code: TUV
+ regions:
+ TV.NUI:
+ combinedCode: TV.NUI
+ code: NUI
+ TV.NMA:
+ combinedCode: TV.NMA
+ code: NMA
+ TV.FUN:
+ combinedCode: TV.FUN
+ code: FUN
+ TV.NIT:
+ combinedCode: TV.NIT
+ code: NIT
+ TV.NMG:
+ combinedCode: TV.NMG
+ code: NMG
+ TV.VAI:
+ combinedCode: TV.VAI
+ code: VAI
+ TV.NKF:
+ combinedCode: TV.NKF
+ code: NKF
+ TV.NKL:
+ combinedCode: TV.NKL
+ code: NKL
+TW:
+ iso2Code: TW
+ iso3Code: TWN
+ regions:
+ TW.01:
+ combinedCode: TW.01
+ code: '01'
+ TW.02:
+ combinedCode: TW.02
+ code: '02'
+ TW.03:
+ combinedCode: TW.03
+ code: '03'
+ TW.04:
+ combinedCode: TW.04
+ code: '04'
+TZ:
+ iso2Code: TZ
+ iso3Code: TZA
+ regions:
+ TZ.19:
+ combinedCode: TZ.19
+ code: '19'
+ TZ.25:
+ combinedCode: TZ.25
+ code: '25'
+ TZ.22:
+ combinedCode: TZ.22
+ code: '22'
+ TZ.21:
+ combinedCode: TZ.21
+ code: '21'
+ TZ.18:
+ combinedCode: TZ.18
+ code: '18'
+ TZ.17:
+ combinedCode: TZ.17
+ code: '17'
+ TZ.16:
+ combinedCode: TZ.16
+ code: '16'
+ TZ.15:
+ combinedCode: TZ.15
+ code: '15'
+ TZ.24:
+ combinedCode: TZ.24
+ code: '24'
+ TZ.02:
+ combinedCode: TZ.02
+ code: '02'
+ TZ.20:
+ combinedCode: TZ.20
+ code: '20'
+ TZ.13:
+ combinedCode: TZ.13
+ code: '13'
+ TZ.12:
+ combinedCode: TZ.12
+ code: '12'
+ TZ.10:
+ combinedCode: TZ.10
+ code: '10'
+ TZ.09:
+ combinedCode: TZ.09
+ code: '09'
+ TZ.08:
+ combinedCode: TZ.08
+ code: '08'
+ TZ.07:
+ combinedCode: TZ.07
+ code: '07'
+ TZ.06:
+ combinedCode: TZ.06
+ code: '06'
+ TZ.05:
+ combinedCode: TZ.05
+ code: '05'
+ TZ.04:
+ combinedCode: TZ.04
+ code: '04'
+ TZ.03:
+ combinedCode: TZ.03
+ code: '03'
+ TZ.23:
+ combinedCode: TZ.23
+ code: '23'
+ TZ.26:
+ combinedCode: TZ.26
+ code: '26'
+ TZ.27:
+ combinedCode: TZ.27
+ code: '27'
+ TZ.14:
+ combinedCode: TZ.14
+ code: '14'
+ TZ.11:
+ combinedCode: TZ.11
+ code: '11'
+ TZ.31:
+ combinedCode: TZ.31
+ code: '31'
+ TZ.28:
+ combinedCode: TZ.28
+ code: '28'
+ TZ.29:
+ combinedCode: TZ.29
+ code: '29'
+ TZ.30:
+ combinedCode: TZ.30
+ code: '30'
+UA:
+ iso2Code: UA
+ iso3Code: UKR
+ regions:
+ UA.27:
+ combinedCode: UA.27
+ code: '27'
+ UA.26:
+ combinedCode: UA.26
+ code: '26'
+ UA.25:
+ combinedCode: UA.25
+ code: '25'
+ UA.24:
+ combinedCode: UA.24
+ code: '24'
+ UA.23:
+ combinedCode: UA.23
+ code: '23'
+ UA.22:
+ combinedCode: UA.22
+ code: '22'
+ UA.21:
+ combinedCode: UA.21
+ code: '21'
+ UA.20:
+ combinedCode: UA.20
+ code: '20'
+ UA.19:
+ combinedCode: UA.19
+ code: '19'
+ UA.18:
+ combinedCode: UA.18
+ code: '18'
+ UA.17:
+ combinedCode: UA.17
+ code: '17'
+ UA.16:
+ combinedCode: UA.16
+ code: '16'
+ UA.15:
+ combinedCode: UA.15
+ code: '15'
+ UA.14:
+ combinedCode: UA.14
+ code: '14'
+ UA.13:
+ combinedCode: UA.13
+ code: '13'
+ UA.12:
+ combinedCode: UA.12
+ code: '12'
+ UA.11:
+ combinedCode: UA.11
+ code: '11'
+ UA.10:
+ combinedCode: UA.10
+ code: '10'
+ UA.09:
+ combinedCode: UA.09
+ code: '09'
+ UA.08:
+ combinedCode: UA.08
+ code: '08'
+ UA.07:
+ combinedCode: UA.07
+ code: '07'
+ UA.06:
+ combinedCode: UA.06
+ code: '06'
+ UA.05:
+ combinedCode: UA.05
+ code: '05'
+ UA.04:
+ combinedCode: UA.04
+ code: '04'
+ UA.03:
+ combinedCode: UA.03
+ code: '03'
+ UA.02:
+ combinedCode: UA.02
+ code: '02'
+ UA.01:
+ combinedCode: UA.01
+ code: '01'
+UG:
+ iso2Code: UG
+ iso3Code: UGA
+ regions:
+ UG.C:
+ combinedCode: UG.C
+ code: C
+ UG.E:
+ combinedCode: UG.E
+ code: E
+ UG.N:
+ combinedCode: UG.N
+ code: N
+ UG.W:
+ combinedCode: UG.W
+ code: W
+UM:
+ iso2Code: UM
+ iso3Code: UMI
+ regions:
+ UM.450:
+ combinedCode: UM.450
+ code: '450'
+ UM.350:
+ combinedCode: UM.350
+ code: '350'
+ UM.050:
+ combinedCode: UM.050
+ code: '050'
+ UM.100:
+ combinedCode: UM.100
+ code: '100'
+ UM.150:
+ combinedCode: UM.150
+ code: '150'
+ UM.200:
+ combinedCode: UM.200
+ code: '200'
+ UM.250:
+ combinedCode: UM.250
+ code: '250'
+ UM.300:
+ combinedCode: UM.300
+ code: '300'
+ UM.400:
+ combinedCode: UM.400
+ code: '400'
+US:
+ iso2Code: US
+ iso3Code: USA
+ regions:
+ US.AR:
+ combinedCode: US.AR
+ code: AR
+ US.DC:
+ combinedCode: US.DC
+ code: DC
+ US.DE:
+ combinedCode: US.DE
+ code: DE
+ US.FL:
+ combinedCode: US.FL
+ code: FL
+ US.GA:
+ combinedCode: US.GA
+ code: GA
+ US.KS:
+ combinedCode: US.KS
+ code: KS
+ US.LA:
+ combinedCode: US.LA
+ code: LA
+ US.MD:
+ combinedCode: US.MD
+ code: MD
+ US.MO:
+ combinedCode: US.MO
+ code: MO
+ US.MS:
+ combinedCode: US.MS
+ code: MS
+ US.NC:
+ combinedCode: US.NC
+ code: NC
+ US.OK:
+ combinedCode: US.OK
+ code: OK
+ US.SC:
+ combinedCode: US.SC
+ code: SC
+ US.TN:
+ combinedCode: US.TN
+ code: TN
+ US.TX:
+ combinedCode: US.TX
+ code: TX
+ US.WV:
+ combinedCode: US.WV
+ code: WV
+ US.AL:
+ combinedCode: US.AL
+ code: AL
+ US.CT:
+ combinedCode: US.CT
+ code: CT
+ US.IA:
+ combinedCode: US.IA
+ code: IA
+ US.IL:
+ combinedCode: US.IL
+ code: IL
+ US.IN:
+ combinedCode: US.IN
+ code: IN
+ US.ME:
+ combinedCode: US.ME
+ code: ME
+ US.MI:
+ combinedCode: US.MI
+ code: MI
+ US.MN:
+ combinedCode: US.MN
+ code: MN
+ US.NE:
+ combinedCode: US.NE
+ code: NE
+ US.NH:
+ combinedCode: US.NH
+ code: NH
+ US.NJ:
+ combinedCode: US.NJ
+ code: NJ
+ US.NY:
+ combinedCode: US.NY
+ code: NY
+ US.OH:
+ combinedCode: US.OH
+ code: OH
+ US.RI:
+ combinedCode: US.RI
+ code: RI
+ US.VT:
+ combinedCode: US.VT
+ code: VT
+ US.WI:
+ combinedCode: US.WI
+ code: WI
+ US.CA:
+ combinedCode: US.CA
+ code: CA
+ US.CO:
+ combinedCode: US.CO
+ code: CO
+ US.NM:
+ combinedCode: US.NM
+ code: NM
+ US.NV:
+ combinedCode: US.NV
+ code: NV
+ US.UT:
+ combinedCode: US.UT
+ code: UT
+ US.AZ:
+ combinedCode: US.AZ
+ code: AZ
+ US.ID:
+ combinedCode: US.ID
+ code: ID
+ US.MT:
+ combinedCode: US.MT
+ code: MT
+ US.ND:
+ combinedCode: US.ND
+ code: ND
+ US.OR:
+ combinedCode: US.OR
+ code: OR
+ US.SD:
+ combinedCode: US.SD
+ code: SD
+ US.WA:
+ combinedCode: US.WA
+ code: WA
+ US.WY:
+ combinedCode: US.WY
+ code: WY
+ US.HI:
+ combinedCode: US.HI
+ code: HI
+ US.AK:
+ combinedCode: US.AK
+ code: AK
+ US.KY:
+ combinedCode: US.KY
+ code: KY
+ US.MA:
+ combinedCode: US.MA
+ code: MA
+ US.PA:
+ combinedCode: US.PA
+ code: PA
+ US.VA:
+ combinedCode: US.VA
+ code: VA
+UY:
+ iso2Code: UY
+ iso3Code: URY
+ regions:
+ UY.19:
+ combinedCode: UY.19
+ code: '19'
+ UY.18:
+ combinedCode: UY.18
+ code: '18'
+ UY.17:
+ combinedCode: UY.17
+ code: '17'
+ UY.16:
+ combinedCode: UY.16
+ code: '16'
+ UY.15:
+ combinedCode: UY.15
+ code: '15'
+ UY.14:
+ combinedCode: UY.14
+ code: '14'
+ UY.13:
+ combinedCode: UY.13
+ code: '13'
+ UY.12:
+ combinedCode: UY.12
+ code: '12'
+ UY.11:
+ combinedCode: UY.11
+ code: '11'
+ UY.10:
+ combinedCode: UY.10
+ code: '10'
+ UY.09:
+ combinedCode: UY.09
+ code: '09'
+ UY.08:
+ combinedCode: UY.08
+ code: '08'
+ UY.07:
+ combinedCode: UY.07
+ code: '07'
+ UY.06:
+ combinedCode: UY.06
+ code: '06'
+ UY.05:
+ combinedCode: UY.05
+ code: '05'
+ UY.04:
+ combinedCode: UY.04
+ code: '04'
+ UY.03:
+ combinedCode: UY.03
+ code: '03'
+ UY.02:
+ combinedCode: UY.02
+ code: '02'
+ UY.01:
+ combinedCode: UY.01
+ code: '01'
+UZ:
+ iso2Code: UZ
+ iso3Code: UZB
+ regions:
+ UZ.09:
+ combinedCode: UZ.09
+ code: '09'
+ UZ.12:
+ combinedCode: UZ.12
+ code: '12'
+ UZ.10:
+ combinedCode: UZ.10
+ code: '10'
+ UZ.08:
+ combinedCode: UZ.08
+ code: '08'
+ UZ.02:
+ combinedCode: UZ.02
+ code: '02'
+ UZ.14:
+ combinedCode: UZ.14
+ code: '14'
+ UZ.13:
+ combinedCode: UZ.13
+ code: '13'
+ UZ.16:
+ combinedCode: UZ.16
+ code: '16'
+ UZ.07:
+ combinedCode: UZ.07
+ code: '07'
+ UZ.06:
+ combinedCode: UZ.06
+ code: '06'
+ UZ.05:
+ combinedCode: UZ.05
+ code: '05'
+ UZ.15:
+ combinedCode: UZ.15
+ code: '15'
+ UZ.03:
+ combinedCode: UZ.03
+ code: '03'
+ UZ.01:
+ combinedCode: UZ.01
+ code: '01'
+VA:
+ iso2Code: VA
+ iso3Code: VAT
+ regions: { }
+VC:
+ iso2Code: VC
+ iso3Code: VCT
+ regions:
+ VC.05:
+ combinedCode: VC.05
+ code: '05'
+ VC.04:
+ combinedCode: VC.04
+ code: '04'
+ VC.03:
+ combinedCode: VC.03
+ code: '03'
+ VC.02:
+ combinedCode: VC.02
+ code: '02'
+ VC.06:
+ combinedCode: VC.06
+ code: '06'
+ VC.01:
+ combinedCode: VC.01
+ code: '01'
+VE:
+ iso2Code: VE
+ iso3Code: VEN
+ regions:
+ VE.23:
+ combinedCode: VE.23
+ code: '23'
+ VE.22:
+ combinedCode: VE.22
+ code: '22'
+ VE.21:
+ combinedCode: VE.21
+ code: '21'
+ VE.20:
+ combinedCode: VE.20
+ code: '20'
+ VE.19:
+ combinedCode: VE.19
+ code: '19'
+ VE.18:
+ combinedCode: VE.18
+ code: '18'
+ VE.17:
+ combinedCode: VE.17
+ code: '17'
+ VE.16:
+ combinedCode: VE.16
+ code: '16'
+ VE.15:
+ combinedCode: VE.15
+ code: '15'
+ VE.14:
+ combinedCode: VE.14
+ code: '14'
+ VE.13:
+ combinedCode: VE.13
+ code: '13'
+ VE.12:
+ combinedCode: VE.12
+ code: '12'
+ VE.24:
+ combinedCode: VE.24
+ code: '24'
+ VE.25:
+ combinedCode: VE.25
+ code: '25'
+ VE.11:
+ combinedCode: VE.11
+ code: '11'
+ VE.09:
+ combinedCode: VE.09
+ code: '09'
+ VE.08:
+ combinedCode: VE.08
+ code: '08'
+ VE.07:
+ combinedCode: VE.07
+ code: '07'
+ VE.06:
+ combinedCode: VE.06
+ code: '06'
+ VE.05:
+ combinedCode: VE.05
+ code: '05'
+ VE.04:
+ combinedCode: VE.04
+ code: '04'
+ VE.03:
+ combinedCode: VE.03
+ code: '03'
+ VE.02:
+ combinedCode: VE.02
+ code: '02'
+ VE.01:
+ combinedCode: VE.01
+ code: '01'
+ VE.26:
+ combinedCode: VE.26
+ code: '26'
+VG:
+ iso2Code: VG
+ iso3Code: VGB
+ regions: { }
+VI:
+ iso2Code: VI
+ iso3Code: VIR
+ regions:
+ VI.010:
+ combinedCode: VI.010
+ code: '010'
+ VI.020:
+ combinedCode: VI.020
+ code: '020'
+ VI.030:
+ combinedCode: VI.030
+ code: '030'
+VN:
+ iso2Code: VN
+ iso3Code: VNM
+ regions:
+ VN.58:
+ combinedCode: VN.58
+ code: '58'
+ VN.59:
+ combinedCode: VN.59
+ code: '59'
+ VN.60:
+ combinedCode: VN.60
+ code: '60'
+ VN.65:
+ combinedCode: VN.65
+ code: '65'
+ VN.67:
+ combinedCode: VN.67
+ code: '67'
+ VN.68:
+ combinedCode: VN.68
+ code: '68'
+ VN.69:
+ combinedCode: VN.69
+ code: '69'
+ VN.70:
+ combinedCode: VN.70
+ code: '70'
+ VN.90:
+ combinedCode: VN.90
+ code: '90'
+ VN.37:
+ combinedCode: VN.37
+ code: '37'
+ VN.66:
+ combinedCode: VN.66
+ code: '66'
+ VN.55:
+ combinedCode: VN.55
+ code: '55'
+ VN.34:
+ combinedCode: VN.34
+ code: '34'
+ VN.35:
+ combinedCode: VN.35
+ code: '35'
+ VN.33:
+ combinedCode: VN.33
+ code: '33'
+ VN.32:
+ combinedCode: VN.32
+ code: '32'
+ VN.64:
+ combinedCode: VN.64
+ code: '64'
+ VN.30:
+ combinedCode: VN.30
+ code: '30'
+ VN.63:
+ combinedCode: VN.63
+ code: '63'
+ VN.62:
+ combinedCode: VN.62
+ code: '62'
+ VN.61:
+ combinedCode: VN.61
+ code: '61'
+ VN.53:
+ combinedCode: VN.53
+ code: '53'
+ VN.24:
+ combinedCode: VN.24
+ code: '24'
+ VN.39:
+ combinedCode: VN.39
+ code: '39'
+ VN.23:
+ combinedCode: VN.23
+ code: '23'
+ VN.89:
+ combinedCode: VN.89
+ code: '89'
+ VN.21:
+ combinedCode: VN.21
+ code: '21'
+ VN.54:
+ combinedCode: VN.54
+ code: '54'
+ VN.20:
+ combinedCode: VN.20
+ code: '20'
+ VN.52:
+ combinedCode: VN.52
+ code: '52'
+ VN.51:
+ combinedCode: VN.51
+ code: '51'
+ VN.50:
+ combinedCode: VN.50
+ code: '50'
+ VN.49:
+ combinedCode: VN.49
+ code: '49'
+ VN.44:
+ combinedCode: VN.44
+ code: '44'
+ VN.87:
+ combinedCode: VN.87
+ code: '87'
+ VN.13:
+ combinedCode: VN.13
+ code: '13'
+ VN.47:
+ combinedCode: VN.47
+ code: '47'
+ VN.09:
+ combinedCode: VN.09
+ code: '09'
+ VN.43:
+ combinedCode: VN.43
+ code: '43'
+ VN.88:
+ combinedCode: VN.88
+ code: '88'
+ VN.45:
+ combinedCode: VN.45
+ code: '45'
+ VN.05:
+ combinedCode: VN.05
+ code: '05'
+ VN.46:
+ combinedCode: VN.46
+ code: '46'
+ VN.03:
+ combinedCode: VN.03
+ code: '03'
+ VN.01:
+ combinedCode: VN.01
+ code: '01'
+ VN.91:
+ combinedCode: VN.91
+ code: '91'
+ VN.92:
+ combinedCode: VN.92
+ code: '92'
+ VN.74:
+ combinedCode: VN.74
+ code: '74'
+ VN.71:
+ combinedCode: VN.71
+ code: '71'
+ VN.78:
+ combinedCode: VN.78
+ code: '78'
+ VN.75:
+ combinedCode: VN.75
+ code: '75'
+ VN.76:
+ combinedCode: VN.76
+ code: '76'
+ VN.85:
+ combinedCode: VN.85
+ code: '85'
+ VN.84:
+ combinedCode: VN.84
+ code: '84'
+ VN.83:
+ combinedCode: VN.83
+ code: '83'
+ VN.82:
+ combinedCode: VN.82
+ code: '82'
+ VN.80:
+ combinedCode: VN.80
+ code: '80'
+ VN.72:
+ combinedCode: VN.72
+ code: '72'
+ VN.73:
+ combinedCode: VN.73
+ code: '73'
+ VN.77:
+ combinedCode: VN.77
+ code: '77'
+ VN.79:
+ combinedCode: VN.79
+ code: '79'
+ VN.81:
+ combinedCode: VN.81
+ code: '81'
+ VN.86:
+ combinedCode: VN.86
+ code: '86'
+ VN.93:
+ combinedCode: VN.93
+ code: '93'
+VU:
+ iso2Code: VU
+ iso3Code: VUT
+ regions:
+ VU.15:
+ combinedCode: VU.15
+ code: '15'
+ VU.13:
+ combinedCode: VU.13
+ code: '13'
+ VU.07:
+ combinedCode: VU.07
+ code: '07'
+ VU.16:
+ combinedCode: VU.16
+ code: '16'
+ VU.17:
+ combinedCode: VU.17
+ code: '17'
+ VU.18:
+ combinedCode: VU.18
+ code: '18'
+WF:
+ iso2Code: WF
+ iso3Code: WLF
+ regions:
+ WF.98613:
+ combinedCode: WF.98613
+ code: '98613'
+ WF.98612:
+ combinedCode: WF.98612
+ code: '98612'
+ WF.98611:
+ combinedCode: WF.98611
+ code: '98611'
+WS:
+ iso2Code: WS
+ iso3Code: WSM
+ regions:
+ WS.11:
+ combinedCode: WS.11
+ code: '11'
+ WS.06:
+ combinedCode: WS.06
+ code: '06'
+ WS.10:
+ combinedCode: WS.10
+ code: '10'
+ WS.09:
+ combinedCode: WS.09
+ code: '09'
+ WS.08:
+ combinedCode: WS.08
+ code: '08'
+ WS.07:
+ combinedCode: WS.07
+ code: '07'
+ WS.05:
+ combinedCode: WS.05
+ code: '05'
+ WS.04:
+ combinedCode: WS.04
+ code: '04'
+ WS.03:
+ combinedCode: WS.03
+ code: '03'
+ WS.02:
+ combinedCode: WS.02
+ code: '02'
+ WS.01:
+ combinedCode: WS.01
+ code: '01'
+YE:
+ iso2Code: YE
+ iso3Code: YEM
+ regions:
+ YE.25:
+ combinedCode: YE.25
+ code: '25'
+ YE.05:
+ combinedCode: YE.05
+ code: '05'
+ YE.16:
+ combinedCode: YE.16
+ code: '16'
+ YE.15:
+ combinedCode: YE.15
+ code: '15'
+ YE.27:
+ combinedCode: YE.27
+ code: '27'
+ YE.14:
+ combinedCode: YE.14
+ code: '14'
+ YE.10:
+ combinedCode: YE.10
+ code: '10'
+ YE.21:
+ combinedCode: YE.21
+ code: '21'
+ YE.04:
+ combinedCode: YE.04
+ code: '04'
+ YE.11:
+ combinedCode: YE.11
+ code: '11'
+ YE.03:
+ combinedCode: YE.03
+ code: '03'
+ YE.08:
+ combinedCode: YE.08
+ code: '08'
+ YE.20:
+ combinedCode: YE.20
+ code: '20'
+ YE.02:
+ combinedCode: YE.02
+ code: '02'
+ YE.01:
+ combinedCode: YE.01
+ code: '01'
+ YE.18:
+ combinedCode: YE.18
+ code: '18'
+ YE.19:
+ combinedCode: YE.19
+ code: '19'
+ YE.22:
+ combinedCode: YE.22
+ code: '22'
+ YE.23:
+ combinedCode: YE.23
+ code: '23'
+ YE.24:
+ combinedCode: YE.24
+ code: '24'
+ YE.26:
+ combinedCode: YE.26
+ code: '26'
+YT:
+ iso2Code: YT
+ iso3Code: MYT
+ regions:
+ YT.97601:
+ combinedCode: YT.97601
+ code: '97601'
+ YT.97602:
+ combinedCode: YT.97602
+ code: '97602'
+ YT.97603:
+ combinedCode: YT.97603
+ code: '97603'
+ YT.97604:
+ combinedCode: YT.97604
+ code: '97604'
+ YT.97605:
+ combinedCode: YT.97605
+ code: '97605'
+ YT.97606:
+ combinedCode: YT.97606
+ code: '97606'
+ YT.97607:
+ combinedCode: YT.97607
+ code: '97607'
+ YT.97608:
+ combinedCode: YT.97608
+ code: '97608'
+ YT.97609:
+ combinedCode: YT.97609
+ code: '97609'
+ YT.97610:
+ combinedCode: YT.97610
+ code: '97610'
+ YT.97611:
+ combinedCode: YT.97611
+ code: '97611'
+ YT.97612:
+ combinedCode: YT.97612
+ code: '97612'
+ YT.97613:
+ combinedCode: YT.97613
+ code: '97613'
+ YT.97614:
+ combinedCode: YT.97614
+ code: '97614'
+ YT.97615:
+ combinedCode: YT.97615
+ code: '97615'
+ YT.97616:
+ combinedCode: YT.97616
+ code: '97616'
+ YT.97617:
+ combinedCode: YT.97617
+ code: '97617'
+ZA:
+ iso2Code: ZA
+ iso3Code: ZAF
+ regions:
+ ZA.03:
+ combinedCode: ZA.03
+ code: '03'
+ ZA.02:
+ combinedCode: ZA.02
+ code: '02'
+ ZA.05:
+ combinedCode: ZA.05
+ code: '05'
+ ZA.06:
+ combinedCode: ZA.06
+ code: '06'
+ ZA.07:
+ combinedCode: ZA.07
+ code: '07'
+ ZA.08:
+ combinedCode: ZA.08
+ code: '08'
+ ZA.09:
+ combinedCode: ZA.09
+ code: '09'
+ ZA.10:
+ combinedCode: ZA.10
+ code: '10'
+ ZA.11:
+ combinedCode: ZA.11
+ code: '11'
+ZM:
+ iso2Code: ZM
+ iso3Code: ZMB
+ regions:
+ ZM.01:
+ combinedCode: ZM.01
+ code: '01'
+ ZM.07:
+ combinedCode: ZM.07
+ code: '07'
+ ZM.06:
+ combinedCode: ZM.06
+ code: '06'
+ ZM.05:
+ combinedCode: ZM.05
+ code: '05'
+ ZM.09:
+ combinedCode: ZM.09
+ code: '09'
+ ZM.04:
+ combinedCode: ZM.04
+ code: '04'
+ ZM.03:
+ combinedCode: ZM.03
+ code: '03'
+ ZM.08:
+ combinedCode: ZM.08
+ code: '08'
+ ZM.02:
+ combinedCode: ZM.02
+ code: '02'
+ZW:
+ iso2Code: ZW
+ iso3Code: ZWE
+ regions:
+ ZW.02:
+ combinedCode: ZW.02
+ code: '02'
+ ZW.07:
+ combinedCode: ZW.07
+ code: '07'
+ ZW.06:
+ combinedCode: ZW.06
+ code: '06'
+ ZW.08:
+ combinedCode: ZW.08
+ code: '08'
+ ZW.05:
+ combinedCode: ZW.05
+ code: '05'
+ ZW.04:
+ combinedCode: ZW.04
+ code: '04'
+ ZW.03:
+ combinedCode: ZW.03
+ code: '03'
+ ZW.01:
+ combinedCode: ZW.01
+ code: '01'
+ ZW.09:
+ combinedCode: ZW.09
+ code: '09'
+ ZW.10:
+ combinedCode: ZW.10
+ code: '10'
+CS:
+ iso2Code: CS
+ iso3Code: SCG
+ regions: { }
+AN:
+ iso2Code: AN
+ iso3Code: ANT
+ regions: { }
diff --git a/src/Oro/Bundle/AddressBundle/Entity/AddressBase.php b/src/Oro/Bundle/AddressBundle/Entity/AddressBase.php
index d4ea7250643..8a5b7b6afe0 100644
--- a/src/Oro/Bundle/AddressBundle/Entity/AddressBase.php
+++ b/src/Oro/Bundle/AddressBundle/Entity/AddressBase.php
@@ -7,6 +7,7 @@
use BeSimple\SoapBundle\ServiceDefinition\Annotation as Soap;
use Oro\Bundle\FlexibleEntityBundle\Entity\Mapping\AbstractEntityFlexible;
+use Oro\Bundle\FlexibleEntityBundle\Model\FlexibleValueInterface;
use Symfony\Component\Validator\ExecutionContext;
/**
@@ -50,15 +51,6 @@ class AddressBase extends AbstractEntityFlexible
*/
protected $city;
- /**
- * @var string
- *
- * @ORM\ManyToOne(targetEntity="Oro\Bundle\AddressBundle\Entity\Region", cascade={"persist"})
- * @ORM\JoinColumn(name="region_id", referencedColumnName="id")
- * @Soap\ComplexType("string", nillable=true)
- */
- protected $state;
-
/**
* @var string
*
@@ -79,11 +71,20 @@ class AddressBase extends AbstractEntityFlexible
* @var string
*
* @ORM\ManyToOne(targetEntity="Oro\Bundle\AddressBundle\Entity\Country", cascade={"persist"})
- * @ORM\JoinColumn(name="country_id", referencedColumnName="iso2_code")
+ * @ORM\JoinColumn(name="country_code", referencedColumnName="iso2_code")
* @Soap\ComplexType("string", nillable=false)
*/
protected $country;
+ /**
+ * @var Region
+ *
+ * @ORM\ManyToOne(targetEntity="Oro\Bundle\AddressBundle\Entity\Region", cascade={"persist"})
+ * @ORM\JoinColumn(name="region_code", referencedColumnName="combined_code")
+ * @Soap\ComplexType("string", nillable=true)
+ */
+ protected $state;
+
/**
* @var string
*
@@ -103,7 +104,7 @@ class AddressBase extends AbstractEntityFlexible
/**
* Get id
*
- * @return integer
+ * @return integer
*/
public function getId()
{
@@ -113,20 +114,20 @@ public function getId()
/**
* Set street
*
- * @param string $street
+ * @param string $street
* @return AddressBase
*/
public function setStreet($street)
{
$this->street = $street;
-
+
return $this;
}
/**
* Get street
*
- * @return string
+ * @return string
*/
public function getStreet()
{
@@ -136,20 +137,20 @@ public function getStreet()
/**
* Set street2
*
- * @param string $street2
+ * @param string $street2
* @return AddressBase
*/
public function setStreet2($street2)
{
$this->street2 = $street2;
-
+
return $this;
}
/**
* Get street2
*
- * @return string
+ * @return string
*/
public function getStreet2()
{
@@ -159,20 +160,20 @@ public function getStreet2()
/**
* Set city
*
- * @param string $city
+ * @param string $city
* @return AddressBase
*/
public function setCity($city)
{
$this->city = $city;
-
+
return $this;
}
/**
* Get city
*
- * @return string
+ * @return string
*/
public function getCity()
{
@@ -188,7 +189,7 @@ public function getCity()
public function setState($state)
{
$this->state = $state;
-
+
return $this;
}
@@ -199,17 +200,13 @@ public function setState($state)
*/
public function getState()
{
- if (!empty($this->stateText)) {
- return $this->stateText;
- } else {
- return $this->state;
- }
+ return $this->state;
}
/**
* Set state text
*
- * @param Region $stateText
+ * @param string $stateText
* @return AddressBase
*/
public function setStateText($stateText)
@@ -222,30 +219,44 @@ public function setStateText($stateText)
/**
* Get state test
*
- * @return Region
+ * @return string
*/
public function getStateText()
{
return $this->stateText;
}
+ /**
+ * Get state
+ *
+ * @return Region|string
+ */
+ public function getUniversalState()
+ {
+ if (!empty($this->stateText)) {
+ return $this->stateText;
+ } else {
+ return $this->state;
+ }
+ }
+
/**
* Set postal_code
*
- * @param string $postalCode
+ * @param string $postalCode
* @return AddressBase
*/
public function setPostalCode($postalCode)
{
$this->postalCode = $postalCode;
-
+
return $this;
}
/**
* Get postal_code
*
- * @return string
+ * @return string
*/
public function getPostalCode()
{
@@ -255,13 +266,13 @@ public function getPostalCode()
/**
* Set country
*
- * @param Country $country
+ * @param Country $country
* @return AddressBase
*/
public function setCountry($country)
{
$this->country = $country;
-
+
return $this;
}
@@ -380,11 +391,38 @@ public function __toString()
$this->getStreet(),
$this->getStreet2(),
$this->getCity(),
- $this->getState(),
+ $this->getUniversalState(),
',',
$this->getCountry(),
$this->getPostalCode(),
);
- return implode(' ', $data);
+
+ $str = implode(' ', $data);
+ $check = trim(str_replace(',', '', $str));
+ return empty($check) ? '' : $str;
+ }
+
+ /**
+ * Check if entity is empty.
+ *
+ * @return bool
+ */
+ public function isEmpty()
+ {
+ $isEmpty = empty($this->firstName)
+ && empty($this->lastName)
+ && empty($this->street)
+ && empty($this->street2)
+ && empty($this->city)
+ && empty($this->state)
+ && empty($this->stateText)
+ && empty($this->country)
+ && empty($this->postalCode);
+ /** @var FlexibleValueInterface $value */
+ foreach ($this->values as $value) {
+ $flexibleValue = $value->getData();
+ $isEmpty = $isEmpty && empty($flexibleValue);
+ }
+ return $isEmpty;
}
}
diff --git a/src/Oro/Bundle/AddressBundle/Entity/AddressType.php b/src/Oro/Bundle/AddressBundle/Entity/AddressType.php
index c69b60616bb..11e368ec609 100644
--- a/src/Oro/Bundle/AddressBundle/Entity/AddressType.php
+++ b/src/Oro/Bundle/AddressBundle/Entity/AddressType.php
@@ -24,7 +24,7 @@ class AddressType
/**
* @var string
*
- * @ORM\Column(name="type", type="string", length=255)
+ * @ORM\Column(name="type", type="string", length=255, unique=true)
*/
private $type;
@@ -41,7 +41,7 @@ public function getId()
/**
* Set route
*
- * @param string $type
+ * @param string $type
* @return AddressType
*/
public function setType($type)
@@ -60,4 +60,12 @@ public function getType()
{
return $this->type;
}
+
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->type;
+ }
}
diff --git a/src/Oro/Bundle/AddressBundle/Entity/Country.php b/src/Oro/Bundle/AddressBundle/Entity/Country.php
index d8792afcd76..d9ac5e6ce33 100644
--- a/src/Oro/Bundle/AddressBundle/Entity/Country.php
+++ b/src/Oro/Bundle/AddressBundle/Entity/Country.php
@@ -3,8 +3,12 @@
namespace Oro\Bundle\AddressBundle\Entity;
use JMS\Serializer\Annotation\Exclude;
+
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
+use Gedmo\Mapping\Annotation as Gedmo;
+use Gedmo\Translatable\Translatable;
+
use BeSimple\SoapBundle\ServiceDefinition\Annotation as Soap;
/**
@@ -12,8 +16,9 @@
*
* @ORM\Table("oro_dictionary_country")
* @ORM\Entity
+ * @Gedmo\TranslationEntity(class="Oro\Bundle\AddressBundle\Entity\CountryTranslation")
*/
-class Country
+class Country implements Translatable
{
/**
* @var string
@@ -35,29 +40,47 @@ class Country
/**
* @var string
*
- * @ORM\Column(name="name", type="string", length=100)
+ * @ORM\Column(name="name", type="string", length=255)
* @Soap\ComplexType("string", nillable=true)
+ * @Gedmo\Translatable
*/
private $name;
/**
* @var ArrayCollection
*
- * @ORM\OneToMany(targetEntity="Region", mappedBy="country", cascade={"ALL"}, fetch="EXTRA_LAZY")
+ * @ORM\OneToMany(
+ * targetEntity="Oro\Bundle\AddressBundle\Entity\Region",
+ * mappedBy="country",
+ * cascade={"ALL"},
+ * fetch="EXTRA_LAZY"
+ * )
* @Exclude
*/
private $regions;
/**
- * @param null|string $name
- * @param null|string $iso2Code
- * @param null|string $iso3Code
+ * @Gedmo\Locale
*/
- public function __construct($name = null, $iso2Code = null, $iso3Code = null)
+ private $locale;
+
+ /**
+ * @param string $iso2Code ISO2 country code
+ */
+ public function __construct($iso2Code)
{
- $this->setName($name);
- $this->setIso2Code($iso2Code);
- $this->setIso3Code($iso3Code);
+ $this->iso2Code = $iso2Code;
+ $this->regions = new ArrayCollection();
+ }
+
+ /**
+ * Get iso2_code
+ *
+ * @return string
+ */
+ public function getIso2Code()
+ {
+ return $this->iso2Code;
}
/**
@@ -81,55 +104,60 @@ public function getRegions()
}
/**
- * Check if country contains regions
- *
- * @return bool
+ * @param Region $region
+ * @return Country
*/
- public function hasRegions()
+ public function addRegion(Region $region)
{
- return count($this->regions) > 0;
+ if (!$this->regions->contains($region)) {
+ $this->regions->add($region);
+ $region->setCountry($this);
+ }
+
+ return $this;
}
/**
- * Set iso2_code
- *
- * @param string $iso2Code
+ * @param Region $region
* @return Country
*/
- public function setIso2Code($iso2Code)
+ public function removeRegion(Region $region)
{
- $this->iso2Code = $iso2Code;
-
+ if ($this->regions->contains($region)) {
+ $this->regions->removeElement($region);
+ $region->setCountry(null);
+ }
+
return $this;
}
/**
- * Get iso2_code
+ * Check if country contains regions
*
- * @return string
+ * @return bool
*/
- public function getIso2Code()
+ public function hasRegions()
{
- return $this->iso2Code;
+ return count($this->regions) > 0;
}
/**
* Set iso3_code
*
- * @param string $iso3Code
+ * @param string $iso3Code
* @return Country
*/
public function setIso3Code($iso3Code)
{
$this->iso3Code = $iso3Code;
-
+
return $this;
}
/**
* Get iso3_code
*
- * @return string
+ * @return string
*/
public function getIso3Code()
{
@@ -139,26 +167,49 @@ public function getIso3Code()
/**
* Set country name
*
- * @param string $name
+ * @param string $name
* @return Country
*/
public function setName($name)
{
$this->name = $name;
-
+
return $this;
}
/**
* Get country name
*
- * @return string
+ * @return string
*/
public function getName()
{
return $this->name;
}
+ /**
+ * Set locale
+ *
+ * @param string $locale
+ * @return Country
+ */
+ public function setLocale($locale)
+ {
+ $this->locale = $locale;
+
+ return $this;
+ }
+
+ /**
+ * Returns locale code
+ *
+ * @return mixed
+ */
+ public function getLocale()
+ {
+ return $this->locale;
+ }
+
/**
* @return string
*/
diff --git a/src/Oro/Bundle/AddressBundle/Entity/CountryTranslation.php b/src/Oro/Bundle/AddressBundle/Entity/CountryTranslation.php
new file mode 100644
index 00000000000..2f7ec0427fd
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Entity/CountryTranslation.php
@@ -0,0 +1,24 @@
+fm->getFlexibleRepository();
+
return $repository->findByWithAttributesQB(array(), null, array('id' => 'ASC'), $limit, $offset);
}
/**
* Provide proxy method calls to flexible manager
*
- * @param string $name
- * @param array $args
+ * @param string $name
+ * @param array $args
* @return mixed
* @throws \RuntimeException
*/
diff --git a/src/Oro/Bundle/AddressBundle/Entity/Manager/AddressTypeManager.php b/src/Oro/Bundle/AddressBundle/Entity/Manager/AddressTypeManager.php
index 33098eaaa5d..8b38822f95d 100644
--- a/src/Oro/Bundle/AddressBundle/Entity/Manager/AddressTypeManager.php
+++ b/src/Oro/Bundle/AddressBundle/Entity/Manager/AddressTypeManager.php
@@ -25,8 +25,8 @@ class AddressTypeManager
/**
* Constructor
*
- * @param string $class Entity name
- * @param ObjectManager $om Object manager
+ * @param string $class Entity name
+ * @param ObjectManager $om Object manager
*/
public function __construct($class, ObjectManager $om)
{
@@ -76,7 +76,7 @@ public function deleteAddressType(AddressType $addressType)
/**
* Finds one address type by the given criteria
*
- * @param array $criteria
+ * @param array $criteria
* @return AddressType
*/
public function findAddressTypeBy(array $criteria)
diff --git a/src/Oro/Bundle/AddressBundle/Entity/Manager/StorageInterface.php b/src/Oro/Bundle/AddressBundle/Entity/Manager/StorageInterface.php
index 2b99a5f0efd..c0b8759ee3b 100644
--- a/src/Oro/Bundle/AddressBundle/Entity/Manager/StorageInterface.php
+++ b/src/Oro/Bundle/AddressBundle/Entity/Manager/StorageInterface.php
@@ -16,8 +16,8 @@ public function createAddress();
/**
* Updates an address
*
- * @param AddressBase $address
- * @param bool $flush Whether to flush the changes (default true)
+ * @param AddressBase $address
+ * @param bool $flush Whether to flush the changes (default true)
* @throws \RuntimeException
*/
public function updateAddress(AddressBase $address, $flush = true);
@@ -32,7 +32,7 @@ public function deleteAddress(AddressBase $address);
/**
* Finds one address by the given criteria
*
- * @param array $criteria
+ * @param array $criteria
* @return AddressBase
*/
public function findAddressBy(array $criteria);
diff --git a/src/Oro/Bundle/AddressBundle/Entity/Region.php b/src/Oro/Bundle/AddressBundle/Entity/Region.php
index 8252dee18ff..343ef60fb95 100644
--- a/src/Oro/Bundle/AddressBundle/Entity/Region.php
+++ b/src/Oro/Bundle/AddressBundle/Entity/Region.php
@@ -3,9 +3,11 @@
namespace Oro\Bundle\AddressBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
+use Doctrine\Common\Collections\ArrayCollection;
use JMS\Serializer\Annotation\Type;
use BeSimple\SoapBundle\ServiceDefinition\Annotation as Soap;
use Gedmo\Mapping\Annotation as Gedmo;
+use Gedmo\Translatable\Translatable;
use Oro\Bundle\AddressBundle\Entity\Country;
@@ -13,25 +15,25 @@
* Region
*
* @ORM\Table("oro_dictionary_region")
- * @ORM\Entity
- * @Gedmo\TranslationEntity(class="Oro\Bundle\AddressBundle\Entity\RegionLocalized")
+ * @ORM\Entity(repositoryClass="Oro\Bundle\AddressBundle\Entity\Repository\RegionRepository")
+ * @Gedmo\TranslationEntity(class="Oro\Bundle\AddressBundle\Entity\RegionTranslation")
*/
-class Region
+class Region implements Translatable
{
/**
- * @var integer
+ * @var string
*
- * @ORM\Column(name="id", type="integer")
* @ORM\Id
- * @ORM\GeneratedValue(strategy="AUTO")
+ * @ORM\Column(name="combined_code", type="string", length=16)
+ * @Soap\ComplexType("string", nillable=true)
*/
- private $id;
+ private $combinedCode;
/**
* @var string
*
* @ORM\ManyToOne(targetEntity="Country", inversedBy="regions",cascade={"persist"})
- * @ORM\JoinColumn(name="country_id", referencedColumnName="iso2_code")
+ * @ORM\JoinColumn(name="country_code", referencedColumnName="iso2_code")
* @Type("string")
* @Soap\ComplexType("string", nillable=true)
*/
@@ -59,26 +61,34 @@ class Region
*/
private $locale;
+ /**
+ * @param string $combinedCode
+ */
+ public function __construct($combinedCode)
+ {
+ $this->combinedCode = $combinedCode;
+ }
+
/**
* Get id
*
- * @return integer
+ * @return integer
*/
- public function getId()
+ public function getCombinedCode()
{
- return $this->id;
+ return $this->combinedCode;
}
/**
* Set country
*
- * @param Country $country
+ * @param Country $country
* @return Region
*/
public function setCountry($country)
{
$this->country = $country;
-
+
return $this;
}
@@ -95,20 +105,20 @@ public function getCountry()
/**
* Set code
*
- * @param string $code
+ * @param string $code
* @return Region
*/
public function setCode($code)
{
$this->code = $code;
-
+
return $this;
}
/**
* Get code
*
- * @return string
+ * @return string
*/
public function getCode()
{
@@ -118,20 +128,20 @@ public function getCode()
/**
* Set name
*
- * @param string $name
+ * @param string $name
* @return Region
*/
public function setName($name)
{
$this->name = $name;
-
+
return $this;
}
/**
* Get name
*
- * @return string
+ * @return string
*/
public function getName()
{
@@ -142,9 +152,9 @@ public function getName()
* Set locale
*
* @param string $locale
- * @return $this
+ * @return Region
*/
- public function setLocale($locale = 'en_US')
+ public function setLocale($locale)
{
$this->locale = $locale;
diff --git a/src/Oro/Bundle/AddressBundle/Entity/RegionLocalized.php b/src/Oro/Bundle/AddressBundle/Entity/RegionLocalized.php
deleted file mode 100644
index 483cfb84f86..00000000000
--- a/src/Oro/Bundle/AddressBundle/Entity/RegionLocalized.php
+++ /dev/null
@@ -1,19 +0,0 @@
-createQueryBuilder('r')
+ ->where('r.country = :country')
+ ->orderBy('r.name', 'ASC')
+ ->setParameter('country', $country);
+ }
+
+ /**
+ * @param Country $country
+ * @return Region[]
+ */
+ public function getCountryRegions(Country $country)
+ {
+ $query = $this->getCountryRegionsQueryBuilder($country)->getQuery();
+ $query->setHint(
+ Query::HINT_CUSTOM_OUTPUT_WALKER,
+ 'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
+ );
+
+ return $query->execute();
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Entity/TypedAddress.php b/src/Oro/Bundle/AddressBundle/Entity/TypedAddress.php
new file mode 100644
index 00000000000..41f16c85b83
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Entity/TypedAddress.php
@@ -0,0 +1,76 @@
+type = $type;
+
+ return $this;
+ }
+
+ /**
+ * @return AddressType
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @param bool $primary
+ */
+ public function setPrimary($primary)
+ {
+ $this->primary = $primary;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isPrimary()
+ {
+ return $this->primary;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isEmpty()
+ {
+ return parent::isEmpty()
+ && empty($this->type)
+ && empty($this->primary);
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Form/DataTransformer/AddressTypeToTypeTransformer.php b/src/Oro/Bundle/AddressBundle/Form/DataTransformer/AddressTypeToTypeTransformer.php
new file mode 100644
index 00000000000..642f5f2efa8
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Form/DataTransformer/AddressTypeToTypeTransformer.php
@@ -0,0 +1,68 @@
+om = $om;
+ }
+
+ /**
+ * Transforms an object to a string.
+ *
+ * @param AddressType|null $addressType
+ * @return string
+ */
+ public function transform($addressType)
+ {
+ if (null === $addressType) {
+ return "";
+ }
+
+ return $addressType->getType();
+ }
+
+ /**
+ * Transforms a string to an object.
+ *
+ * @param string $type
+ * @return int|null
+ * @throws TransformationFailedException
+ */
+ public function reverseTransform($type)
+ {
+ if (!$type) {
+ return null;
+ }
+
+ $addressType = $this->om
+ ->getRepository('OroAddressBundle:AddressType')
+ ->findOneBy(array('type' => $type));
+
+ if (null === $addressType) {
+ throw new TransformationFailedException(
+ sprintf(
+ 'An address type with type "%s" does not exist!',
+ $type
+ )
+ );
+ }
+
+ return $addressType;
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Form/EventListener/AddressCollectionTypeSubscriber.php b/src/Oro/Bundle/AddressBundle/Form/EventListener/AddressCollectionTypeSubscriber.php
new file mode 100644
index 00000000000..d9b5b0e26f9
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Form/EventListener/AddressCollectionTypeSubscriber.php
@@ -0,0 +1,150 @@
+property = $property;
+ $this->entityClass = $entityClass;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getSubscribedEvents()
+ {
+ return array(
+ FormEvents::POST_BIND => 'postBind',
+ FormEvents::PRE_SET_DATA => 'preSet',
+ FormEvents::PRE_BIND => 'preBind'
+ );
+ }
+
+ /**
+ * Pre set empty collection elements.
+ *
+ * @param FormEvent $event
+ */
+ public function preSet(FormEvent $event)
+ {
+ $data = $event->getData();
+
+ $method = $this->getMethodName();
+ if ($data && method_exists($data, $method)) {
+ /** @var Collection $addresses */
+ $addresses = $data->$method();
+ if ($addresses->isEmpty()) {
+ $addresses->add(new $this->entityClass());
+ }
+ }
+ }
+
+ /**
+ * Removes empty collection elements.
+ *
+ * @param FormEvent $event
+ */
+ public function postBind(FormEvent $event)
+ {
+ $data = $event->getData();
+
+ $method = $this->getMethodName();
+ if ($data && method_exists($data, $method)) {
+ /** @var Collection $addresses */
+ $addresses = $data->$method();
+ /** @var TypedAddress $item */
+ foreach ($addresses as $item) {
+ if ($item->isEmpty()) {
+ $addresses->removeElement($item);
+ }
+ }
+ }
+ }
+
+ /**
+ * Remove empty addresses to prevent validation.
+ *
+ * @param FormEvent $event
+ */
+ public function preBind(FormEvent $event)
+ {
+ $data = $event->getData();
+ if (!$data) {
+ return;
+ }
+
+ $addresses = array();
+ $hasPrimary = false;
+ if ($data && array_key_exists($this->property, $data)) {
+ foreach ($data[$this->property] as $addressRow) {
+ if (!$this->isArrayEmpty($addressRow)) {
+ $hasPrimary = $hasPrimary || (array_key_exists('primary', $addressRow) && $addressRow['primary']);
+ $addresses[] = $addressRow;
+ }
+ }
+ }
+
+ // Set first non empty address for new item as primary
+ if ($addresses) {
+ if ((!array_key_exists('id', $data) || !$data['id']) && !$hasPrimary) {
+ $first = array_shift($addresses);
+ $first['primary'] = true;
+ array_unshift($addresses, $first);
+ }
+ $data[$this->property] = $addresses;
+ $event->setData($data);
+ }
+ }
+
+ /**
+ * Check if array is empty
+ *
+ * @param array $array
+ * @return bool
+ */
+ protected function isArrayEmpty($array)
+ {
+ foreach ($array as $val) {
+ if (is_array($val)) {
+ if (!$this->isArrayEmpty($val)) {
+ return false;
+ }
+ } elseif (!empty($val)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Get getter method name.
+ *
+ * @return string
+ */
+ protected function getMethodName()
+ {
+ return 'get' . ucfirst($this->property);
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Form/EventListener/BuildAddressFormListener.php b/src/Oro/Bundle/AddressBundle/Form/EventListener/BuildAddressFormListener.php
index d9704c5e6ef..05f2398e1b1 100644
--- a/src/Oro/Bundle/AddressBundle/Form/EventListener/BuildAddressFormListener.php
+++ b/src/Oro/Bundle/AddressBundle/Form/EventListener/BuildAddressFormListener.php
@@ -1,13 +1,15 @@
has('state')) {
$config = $form->get('state')->getConfig()->getOptions();
unset($config['choice_list']);
+ unset($config['choices']);
} else {
$config = array();
}
+
$config['country'] = $country;
+ $config['query_builder'] = $this->getRegionClosure($country);
$form->add(
$this->factory->createNamed(
@@ -95,12 +100,16 @@ public function preBind(FormEvent $event)
$form = $event->getForm();
/** @var $country \Oro\Bundle\AddressBundle\Entity\Country */
- $country = $this->om->getRepository('OroAddressBundle:Country')->find(isset($data['country']) ? $data['country'] : false);
+ $country = $this->om->getRepository('OroAddressBundle:Country')
+ ->find(isset($data['country']) ? $data['country'] : false);
if ($country && $country->hasRegions()) {
$config = $form->get('state')->getConfig()->getOptions();
unset($config['choice_list']);
+ unset($config['choices']);
+
$config['country'] = $country;
+ $config['query_builder'] = $this->getRegionClosure($country);
$form->add(
$this->factory->createNamed(
@@ -112,4 +121,15 @@ public function preBind(FormEvent $event)
);
}
}
+
+ /**
+ * @param Country $country
+ * @return callable
+ */
+ protected function getRegionClosure(Country $country)
+ {
+ return function (RegionRepository $regionRepository) use ($country) {
+ return $regionRepository->getCountryRegionsQueryBuilder($country);
+ };
+ }
}
diff --git a/src/Oro/Bundle/AddressBundle/Form/Type/AddressCollectionType.php b/src/Oro/Bundle/AddressBundle/Form/Type/AddressCollectionType.php
new file mode 100644
index 00000000000..c1a9236ad44
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Form/Type/AddressCollectionType.php
@@ -0,0 +1,61 @@
+setDefaults(
+ array(
+ 'type' => 'oro_address_typed',
+ 'allow_add' => true,
+ 'allow_delete' => true,
+ 'by_reference' => false,
+ 'prototype' => true,
+ 'prototype_name' => '__name__',
+ 'label' => ' ',
+ 'validation_groups' => function (FormInterface $form) {
+ /** @var AddressBase[] $data */
+ $data = $form->getData();
+ $hasAddress = false;
+ foreach ($data as $item) {
+ if (!$item->isEmpty()) {
+ $hasAddress = true;
+ break;
+ }
+ }
+ if ($hasAddress) {
+ return array('Default');
+ } else {
+ return array();
+ }
+ },
+ )
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getParent()
+ {
+ return 'collection';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'oro_address_collection';
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Form/Type/AddressTypedType.php b/src/Oro/Bundle/AddressBundle/Form/Type/AddressTypedType.php
new file mode 100644
index 00000000000..289e994942c
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Form/Type/AddressTypedType.php
@@ -0,0 +1,42 @@
+add(
+ 'type',
+ 'entity',
+ array(
+ 'class' => 'OroAddressBundle:AddressType',
+ 'property' => 'type',
+ 'required' => false,
+ 'empty_value' => 'Choose type...'
+ )
+ );
+ $builder->add(
+ 'primary',
+ 'checkbox',
+ array(
+ 'label' => 'Primary',
+ 'required' => false
+ )
+ );
+ parent::addEntityFields($builder);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'oro_address_typed';
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Form/Type/CountryType.php b/src/Oro/Bundle/AddressBundle/Form/Type/CountryType.php
index 58cebad248b..8c39b5e0e47 100644
--- a/src/Oro/Bundle/AddressBundle/Form/Type/CountryType.php
+++ b/src/Oro/Bundle/AddressBundle/Form/Type/CountryType.php
@@ -16,7 +16,10 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
return $er->createQueryBuilder('c')
->orderBy('c.name', 'ASC');
},
- 'empty_value' => 'Choose a country...',
+ 'configs' => array(
+ 'placeholder' => 'oro.address.form.choose_country'
+ ),
+ 'empty_value' => '',
'empty_data' => null
)
);
@@ -24,7 +27,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
public function getParent()
{
- return 'entity';
+ return 'genemu_jqueryselect2_translatable_entity';
}
public function getName()
diff --git a/src/Oro/Bundle/AddressBundle/Form/Type/RegionType.php b/src/Oro/Bundle/AddressBundle/Form/Type/RegionType.php
index 27d0f29ea41..fb9e68111f1 100644
--- a/src/Oro/Bundle/AddressBundle/Form/Type/RegionType.php
+++ b/src/Oro/Bundle/AddressBundle/Form/Type/RegionType.php
@@ -3,12 +3,11 @@
namespace Oro\Bundle\AddressBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
-use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
-use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
+use Symfony\Component\OptionsResolver\Options;
class RegionType extends AbstractType
{
@@ -28,22 +27,29 @@ public function buildForm(FormBuilderInterface $builder, array $options)
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
- $list = function (Options $options) {
- if (null === $options['country']) {
- return new ObjectChoiceList(array());
+ $choices = function (Options $options) {
+ // show empty list if country is not selected
+ if (empty($options['country'])) {
+ return array();
}
- return new ObjectChoiceList($options['country']->getRegions(), null, array(), null, 'code');
+ return null;
};
$resolver
->setDefaults(
array(
- 'choice_list' => $list,
- 'country' => null,
+ 'class' => 'OroAddressBundle:Region',
+ 'property' => 'name',
+ 'query_builder' => null,
+ 'choices' => $choices,
+ 'country' => null,
'country_field' => null,
- 'empty_value' => 'Choose a state...',
- 'empty_data' => null,
+ 'configs' => array(
+ 'placeholder' => 'oro.address.form.choose_state',
+ ),
+ 'empty_value' => '',
+ 'empty_data' => null
)
);
}
@@ -53,7 +59,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
*/
public function finishView(FormView $view, FormInterface $form, array $options)
{
- $view->vars['country_field'] = $form->getAttribute(self::COUNTRY_OPTION_KEY);
+ $view->vars['country_field'] = $form->getConfig()->getAttribute(self::COUNTRY_OPTION_KEY);
}
/**
@@ -61,7 +67,7 @@ public function finishView(FormView $view, FormInterface $form, array $options)
*/
public function getParent()
{
- return 'choice';
+ return 'genemu_jqueryselect2_translatable_entity';
}
/**
diff --git a/src/Oro/Bundle/AddressBundle/Provider/ImportExport/DbReader.php b/src/Oro/Bundle/AddressBundle/Provider/ImportExport/DbReader.php
deleted file mode 100644
index a591e5b6eb8..00000000000
--- a/src/Oro/Bundle/AddressBundle/Provider/ImportExport/DbReader.php
+++ /dev/null
@@ -1,45 +0,0 @@
-getClassMetadata($class);
- $this->class = $metadata->getName();
- $this->om = $om;
-
- if (!is_null($batchSize)) {
- $this->batchSize = $batchSize;
- }
- }
-
- /**
- * @inheritdoc
- */
- public function readBatch()
- {
- $offset = $this->offset * $this->batchSize;
- $this->offset++;
-
- return $this->om->getRepository($this->class)->findBy(array(), array(), $this->batchSize, $offset);
- }
-}
diff --git a/src/Oro/Bundle/AddressBundle/Provider/ImportExport/DbWriter.php b/src/Oro/Bundle/AddressBundle/Provider/ImportExport/DbWriter.php
deleted file mode 100644
index 42659d0102c..00000000000
--- a/src/Oro/Bundle/AddressBundle/Provider/ImportExport/DbWriter.php
+++ /dev/null
@@ -1,40 +0,0 @@
-om = $om;
- }
-
- /**
- * @inheritdoc
- */
- public function writeBatch($data)
- {
- if (empty($data) || !is_array($data)) {
- return false;
- }
-
- foreach ($data as $entry) {
- if (is_object($entry)) {
- $this->om->persist($entry);
- } else {
- throw new \Exception("Entry passed to writer is not an object");
- }
- }
-
- $this->om->flush();
-
- return true;
- }
-}
diff --git a/src/Oro/Bundle/AddressBundle/Provider/ImportExport/IntlReader.php b/src/Oro/Bundle/AddressBundle/Provider/ImportExport/IntlReader.php
deleted file mode 100644
index ff83acb0dd8..00000000000
--- a/src/Oro/Bundle/AddressBundle/Provider/ImportExport/IntlReader.php
+++ /dev/null
@@ -1,74 +0,0 @@
-class = $class;
-
- if (!is_null($batchSize)) {
- $this->batchSize = $batchSize;
- }
- }
-
- /**
- * @inheritdoc
- */
- public function readBatch()
- {
- if (!extension_loaded('intl')) {
- return false;
- }
-
- $countries = Intl::getRegionBundle()->getCountryNames();
- $class = $this->class;
-
- $offset = $this->offset * $this->batchSize;
- $this->offset++;
-
- $isoCodes = $this->readFallbackData();
-
- $countries = array_slice($countries, $offset, $this->batchSize);
-
- if (!empty($countries)) {
- $result = array();
- foreach ($countries as $iso2code => $countryName) {
- $result[] = new $class($countryName, $iso2code, isset($isoCodes[$iso2code]) ? $isoCodes[$iso2code] : $iso2code);
- }
- return $result;
- }
-
- return false;
- }
-
- /**
- * Move it or delete when valid datasource will be found
- */
- public function readFallbackData()
- {
- $data = Yaml::parse(realpath(__DIR__ . '/../../' . self::FALLBACK_DATA));
- $isoCodes = array();
-
- foreach ($data as $country) {
- $isoCodes[ $country['iso2'] ] = $country['iso3'];
- }
-
- return $isoCodes;
- }
-}
diff --git a/src/Oro/Bundle/AddressBundle/Provider/ImportExport/Manager.php b/src/Oro/Bundle/AddressBundle/Provider/ImportExport/Manager.php
deleted file mode 100644
index 3c9d15c9914..00000000000
--- a/src/Oro/Bundle/AddressBundle/Provider/ImportExport/Manager.php
+++ /dev/null
@@ -1,45 +0,0 @@
-reader = $reader;
- $this->writer = $writer;
- }
-
- /**
- * Reading/Writing data in a batch and write/read it to destination
- * data can be passed through argument or read from reader
- *
- * @param $data
- * @throws \Exception
- * @return boolean true on success
- */
- public function sync($data = null)
- {
- if ($this->reader instanceof ReaderInterface) {
- while ($batchData = $this->reader->readBatch()) {
- $this->writer->writeBatch($batchData);
- }
- } elseif (!is_null($data)) {
- $this->writer->writeBatch($data);
- } else {
- throw new \Exception("Source is not defined");
- }
-
- return true;
- }
-}
diff --git a/src/Oro/Bundle/AddressBundle/Provider/ImportExport/Reader.php b/src/Oro/Bundle/AddressBundle/Provider/ImportExport/Reader.php
deleted file mode 100644
index 293a6710a9d..00000000000
--- a/src/Oro/Bundle/AddressBundle/Provider/ImportExport/Reader.php
+++ /dev/null
@@ -1,35 +0,0 @@
-offset = 0;
- }
-
- /**
- * Return batch size
- *
- * @return int
- */
- public function getBatchSize()
- {
- return $this->batchSize;
- }
-}
diff --git a/src/Oro/Bundle/AddressBundle/Provider/ImportExport/ReaderInterface.php b/src/Oro/Bundle/AddressBundle/Provider/ImportExport/ReaderInterface.php
deleted file mode 100644
index 732c9807c07..00000000000
--- a/src/Oro/Bundle/AddressBundle/Provider/ImportExport/ReaderInterface.php
+++ /dev/null
@@ -1,13 +0,0 @@
-
+
+### Address collection
+Address collection may be added to form with next three steps
+1) Add field with type oro_address_collection to form
+
+```php
+$builder->add(
+ 'multiAddress',
+ 'oro_address_collection',
+ array(
+ 'required' => false,
+ 'label' => ' '
+ )
+);
+```
+2) Add AddressCollectionTypeSubscriber. AddressCollectionTypeSubscriber must be initialized with address collection field name.
+
+```php
+$builder->addEventSubscriber(new AddressCollectionTypeSubscriber('multiAddress'));
+```
+
+3) In template add OroAddressBundle:Include:fields.html.twig to support address form field typed
+
+```php
+{% form_theme form with ['OroAddressBundle:Include:fields.html.twig']}
+```
diff --git a/src/Oro/Bundle/AddressBundle/Resources/config/flexibleentity.yml b/src/Oro/Bundle/AddressBundle/Resources/config/flexibleentity.yml
index ce1cb487c69..59f2dd35ddf 100644
--- a/src/Oro/Bundle/AddressBundle/Resources/config/flexibleentity.yml
+++ b/src/Oro/Bundle/AddressBundle/Resources/config/flexibleentity.yml
@@ -4,3 +4,9 @@ entities_config:
flexible_class: %oro_address.address.entity.class%
flexible_value_class: %oro_address.address.entity.value.class%
flexible_init_mode: all_attributes
+
+ Oro\Bundle\AddressBundle\Entity\TypedAddress:
+ flexible_manager: oro_address.typed_address.manager.flexible
+ flexible_class: %oro_address.typed_address.entity.class%
+ flexible_value_class: %oro_address.address.entity.value.class%
+ flexible_init_mode: all_attributes
\ No newline at end of file
diff --git a/src/Oro/Bundle/AddressBundle/Resources/config/services.yml b/src/Oro/Bundle/AddressBundle/Resources/config/services.yml
index 80f45580b43..66e43a63290 100644
--- a/src/Oro/Bundle/AddressBundle/Resources/config/services.yml
+++ b/src/Oro/Bundle/AddressBundle/Resources/config/services.yml
@@ -1,17 +1,21 @@
parameters:
oro_address.address.base.class: Oro\Bundle\AddressBundle\Entity\AddressBase
oro_address.address.entity.class: Oro\Bundle\AddressBundle\Entity\Address
+ oro_address.typed_address.entity.class: Oro\Bundle\AddressBundle\Entity\TypedAddress
oro_address.address.type.entity.class: Oro\Bundle\AddressBundle\Entity\AddressType
oro_address.address.manager.class: Oro\Bundle\AddressBundle\Entity\Manager\AddressManager
oro_address.address.manager.api.class: Oro\Bundle\SoapBundle\Entity\Manager\ApiFlexibleEntityManager
oro_address.address.manager.flexible.class: Oro\Bundle\FlexibleEntityBundle\Manager\FlexibleManager
+ oro_address.typed_address.manager.flexible.class: Oro\Bundle\FlexibleEntityBundle\Manager\FlexibleManager
oro_address.address.type.manager.class: Oro\Bundle\AddressBundle\Entity\Manager\AddressTypeManager
oro_address.address.entity.value.class: Oro\Bundle\AddressBundle\Entity\Value\AddressValue
oro_address.type.address.class: Oro\Bundle\AddressBundle\Form\Type\AddressType
oro_address.type.address_value.class: Oro\Bundle\AddressBundle\Form\Type\AddressValueType
+ oro_address.type.address_typed.class: Oro\Bundle\AddressBundle\Form\Type\AddressTypedType
+ oro_address.type.address_collection.class: Oro\Bundle\AddressBundle\Form\Type\AddressCollectionType
oro_address.type.address_api.class: Oro\Bundle\AddressBundle\Form\Type\AddressApiType
oro_address.type.address_api_value.class: Oro\Bundle\AddressBundle\Form\Type\AddressApiValueType
oro_address.handler.address.class: Oro\Bundle\AddressBundle\Form\Handler\AddressHandler
@@ -19,11 +23,6 @@ parameters:
oro_address.provider.address.class: Oro\Bundle\AddressBundle\Provider\AddressProvider
oro_address.entity.value.class: Oro\Bundle\FlexibleEntityBundle\Entity\Mapping\AbstractEntityFlexibleValue
- oro_address.dict.import.writer.class: Oro\Bundle\AddressBundle\Provider\ImportExport\DbWriter
- oro_address.dict.import.intlreader.class: Oro\Bundle\AddressBundle\Provider\ImportExport\IntlReader
- oro_address.dict.manager.class: Oro\Bundle\AddressBundle\Provider\ImportExport\Manager
- oro_address.dict.import.entity.class: Oro\Bundle\AddressBundle\Entity\Country
-
oro_address.type.country.class: Oro\Bundle\AddressBundle\Form\Type\CountryType
oro_address.type.region.class: Oro\Bundle\AddressBundle\Form\Type\RegionType
@@ -31,6 +30,10 @@ parameters:
oro_address.attribute.address.class: Oro\Bundle\AddressBundle\AttributeType\AddressType
+ oro_address.twig.hasAddress.extension.class: Oro\Bundle\AddressBundle\Twig\HasAddressExtension
+
+ oro_address.typed.transformer.class: Oro\Bundle\AddressBundle\Form\DataTransformer\AddressTypeToTypeTransformer
+
services:
oro_address.address.provider:
class: %oro_address.provider.address.class%
@@ -49,6 +52,19 @@ services:
calls:
- [ addAttributeType, ['oro_flexibleentity_text'] ]
+ oro_address.typed_address.manager.flexible:
+ class: %oro_address.typed_address.manager.flexible.class%
+ arguments:
+ - %oro_address.typed_address.entity.class%
+ - %oro_flexibleentity.flexible_config%
+ - @doctrine.orm.entity_manager
+ - @event_dispatcher
+ - @oro_flexibleentity.attributetype.factory
+ tags:
+ - { name: oro_flexibleentity_manager, entity: %oro_address.typed_address.entity.class%}
+ calls:
+ - [ addAttributeType, ['oro_flexibleentity_text'] ]
+
oro_address.address.manager:
class: %oro_address.address.manager.class%
arguments:
@@ -103,6 +119,20 @@ services:
tags:
- { name: form.type, alias: oro_address_value }
+ oro_address.type.address_typed:
+ class: %oro_address.type.address_typed.class%
+ arguments:
+ - @oro_address.typed_address.manager.flexible
+ - "oro_address_value"
+ - @oro_address.form.listener.address
+ tags:
+ - { name: form.type, alias: oro_address_typed }
+
+ oro_address.type.address_collection:
+ class: %oro_address.type.address_collection.class%
+ tags:
+ - { name: form.type, alias: oro_address_collection }
+
oro_address.form.type.address.api:
class: %oro_address.type.address_api.class%
arguments:
@@ -147,23 +177,6 @@ services:
tags:
- { name: form.type, alias: oro_region }
- # dictionary services
- oro_address.dict.import.dbwriter:
- class: %oro_address.dict.import.writer.class%
- arguments: ["@doctrine.orm.entity_manager"]
-
- oro_address.dict.import.intlreader:
- class: %oro_address.dict.import.intlreader.class%
- arguments: ["%oro_address.dict.import.entity.class%"]
-
- oro_address.dict.import.manager:
- class: %oro_address.dict.manager.class%
- arguments: ["@oro_address.dict.import.dbwriter", null]
-
- oro_address.dict.import.intl.manager:
- class: %oro_address.dict.manager.class%
- arguments: ["@oro_address.dict.import.dbwriter", "@oro_address.dict.import.intlreader"]
-
oro_address.form.type.region:
class: %oro_address.type.region.class%
tags:
@@ -181,5 +194,16 @@ services:
arguments:
- "address"
- "oro_address"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
+ tags:
+ - { name: oro_flexibleentity.attributetype, alias: oro_address }
+
+ oro_address.twig.hasAddress.extension:
+ class: %oro_address.twig.hasAddress.extension.class%
tags:
- - { name: oro_flexibleentity.attributetype, alias: oro_address }
\ No newline at end of file
+ - { name: twig.extension }
+
+ oro_address.typed.transformer:
+ class: %oro_address.typed.transformer.class%
+ arguments:
+ - @doctrine.orm.entity_manager
diff --git a/src/Oro/Bundle/AddressBundle/Resources/config/validation.yml b/src/Oro/Bundle/AddressBundle/Resources/config/validation.yml
index ca2b0fc5ae7..7045f024b2b 100644
--- a/src/Oro/Bundle/AddressBundle/Resources/config/validation.yml
+++ b/src/Oro/Bundle/AddressBundle/Resources/config/validation.yml
@@ -1,4 +1,4 @@
-Oro\Bundle\AddressBundle\Entity\Address:
+Oro\Bundle\AddressBundle\Entity\AddressBase:
properties:
street:
- NotBlank: ~
diff --git a/src/Oro/Bundle/AddressBundle/Resources/public/js/collections/region.updater.js b/src/Oro/Bundle/AddressBundle/Resources/public/js/collections/region.updater.js
index 38063c8417d..de37601d23d 100644
--- a/src/Oro/Bundle/AddressBundle/Resources/public/js/collections/region.updater.js
+++ b/src/Oro/Bundle/AddressBundle/Resources/public/js/collections/region.updater.js
@@ -19,6 +19,6 @@ Oro.RegionUpdater.Collection = Backbone.Collection.extend({
* @param id {String}
*/
setCountryId: function (id) {
- this.url = Routing.generate(this.route, {id: id});
+ this.url = Routing.generate(this.route, {country: id});
}
});
diff --git a/src/Oro/Bundle/AddressBundle/Resources/public/js/views/region.updater.js b/src/Oro/Bundle/AddressBundle/Resources/public/js/views/region.updater.js
index 049c3246d03..621cbbdbffd 100644
--- a/src/Oro/Bundle/AddressBundle/Resources/public/js/views/region.updater.js
+++ b/src/Oro/Bundle/AddressBundle/Resources/public/js/views/region.updater.js
@@ -18,11 +18,30 @@ Oro.RegionUpdater.View = Backbone.View.extend({
this.target.closest('.controls').append(this.$simpleEl);
this.$simpleEl.attr('type', 'text');
+ this.showSelect = options.showSelect;
+
this.template = $('#region-chooser-template').html();
+ this.target.on('select2-init', _.bind(function() {
+ this.displaySelect2(this.showSelect);
+ }, this));
+
this.listenTo(this.collection, 'reset', this.render);
},
+ /**
+ * Show/hide select 2 element
+ *
+ * @param {Boolean} display
+ */
+ displaySelect2: function(display) {
+ if (display) {
+ this.target.select2('container').show();
+ } else {
+ this.target.select2('container').hide();
+ }
+ },
+
/**
* Trigger change event
*/
@@ -46,6 +65,7 @@ Oro.RegionUpdater.View = Backbone.View.extend({
render: function() {
if (this.collection.models.length > 0) {
this.target.show();
+ this.displaySelect2(true);
$('#uniform-' + this.target[0].id).show();
this.target.val('').trigger('change');
@@ -56,6 +76,8 @@ Oro.RegionUpdater.View = Backbone.View.extend({
this.$simpleEl.val('');
} else {
this.target.hide();
+ this.target.val('');
+ this.displaySelect2(false);
$('#uniform-' + this.target[0].id).hide();
this.$simpleEl.show();
}
diff --git a/src/Oro/Bundle/AddressBundle/Resources/translations/countries.en.yml b/src/Oro/Bundle/AddressBundle/Resources/translations/countries.en.yml
new file mode 100644
index 00000000000..26bf2d17db7
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Resources/translations/countries.en.yml
@@ -0,0 +1,4126 @@
+AD: Andorra
+AE: 'United Arab Emirates'
+AF: Afghanistan
+AG: 'Antigua and Barbuda'
+AI: Anguilla
+AL: Albania
+AM: Armenia
+AO: Angola
+AQ: Antarctica
+AR: Argentina
+AS: 'American Samoa'
+AT: Austria
+AU: Australia
+AW: Aruba
+AX: 'Aland Islands'
+AZ: Azerbaijan
+BA: 'Bosnia and Herzegovina'
+BB: Barbados
+BD: Bangladesh
+BE: Belgium
+BF: 'Burkina Faso'
+BG: Bulgaria
+BH: Bahrain
+BI: Burundi
+BJ: Benin
+BL: 'Saint Barthelemy'
+BM: Bermuda
+BN: Brunei
+BO: Bolivia
+BQ: 'Bonaire, Saint Eustatius and Saba '
+BR: Brazil
+BS: Bahamas
+BT: Bhutan
+BV: 'Bouvet Island'
+BW: Botswana
+BY: Belarus
+BZ: Belize
+CA: Canada
+CC: 'Cocos Islands'
+CD: 'Democratic Republic of the Congo'
+CF: 'Central African Republic'
+CG: 'Republic of the Congo'
+CH: Switzerland
+CI: 'Ivory Coast'
+CK: 'Cook Islands'
+CL: Chile
+CM: Cameroon
+CN: China
+CO: Colombia
+CR: 'Costa Rica'
+CU: Cuba
+CV: 'Cape Verde'
+CW: Curacao
+CX: 'Christmas Island'
+CY: Cyprus
+CZ: 'Czech Republic'
+DE: Germany
+DJ: Djibouti
+DK: Denmark
+DM: Dominica
+DO: 'Dominican Republic'
+DZ: Algeria
+EC: Ecuador
+EE: Estonia
+EG: Egypt
+EH: 'Western Sahara'
+ER: Eritrea
+ES: Spain
+ET: Ethiopia
+FI: Finland
+FJ: Fiji
+FK: 'Falkland Islands'
+FM: Micronesia
+FO: 'Faroe Islands'
+FR: France
+GA: Gabon
+GB: 'United Kingdom'
+GD: Grenada
+GE: Georgia
+GF: 'French Guiana'
+GG: Guernsey
+GH: Ghana
+GI: Gibraltar
+GL: Greenland
+GM: Gambia
+GN: Guinea
+GP: Guadeloupe
+GQ: 'Equatorial Guinea'
+GR: Greece
+GS: 'South Georgia and the South Sandwich Islands'
+GT: Guatemala
+GU: Guam
+GW: Guinea-Bissau
+GY: Guyana
+HK: 'Hong Kong'
+HM: 'Heard Island and McDonald Islands'
+HN: Honduras
+HR: Croatia
+HT: Haiti
+HU: Hungary
+ID: Indonesia
+IE: Ireland
+IL: Israel
+IM: 'Isle of Man'
+IN: India
+IO: 'British Indian Ocean Territory'
+IQ: Iraq
+IR: Iran
+IS: Iceland
+IT: Italy
+JE: Jersey
+JM: Jamaica
+JO: Jordan
+JP: Japan
+KE: Kenya
+KG: Kyrgyzstan
+KH: Cambodia
+KI: Kiribati
+KM: Comoros
+KN: 'Saint Kitts and Nevis'
+KP: 'North Korea'
+KR: 'South Korea'
+XK: Kosovo
+KW: Kuwait
+KY: 'Cayman Islands'
+KZ: Kazakhstan
+LA: Laos
+LB: Lebanon
+LC: 'Saint Lucia'
+LI: Liechtenstein
+LK: 'Sri Lanka'
+LR: Liberia
+LS: Lesotho
+LT: Lithuania
+LU: Luxembourg
+LV: Latvia
+LY: Libya
+MA: Morocco
+MC: Monaco
+MD: Moldova
+ME: Montenegro
+MF: 'Saint Martin'
+MG: Madagascar
+MH: 'Marshall Islands'
+MK: Macedonia
+ML: Mali
+MM: Myanmar
+MN: Mongolia
+MO: Macao
+MP: 'Northern Mariana Islands'
+MQ: Martinique
+MR: Mauritania
+MS: Montserrat
+MT: Malta
+MU: Mauritius
+MV: Maldives
+MW: Malawi
+MX: Mexico
+MY: Malaysia
+MZ: Mozambique
+NA: Namibia
+NC: 'New Caledonia'
+NE: Niger
+NF: 'Norfolk Island'
+NG: Nigeria
+NI: Nicaragua
+NL: Netherlands
+NO: Norway
+NP: Nepal
+NR: Nauru
+NU: Niue
+NZ: 'New Zealand'
+OM: Oman
+PA: Panama
+PE: Peru
+PF: 'French Polynesia'
+PG: 'Papua New Guinea'
+PH: Philippines
+PK: Pakistan
+PL: Poland
+PM: 'Saint Pierre and Miquelon'
+PN: Pitcairn
+PR: 'Puerto Rico'
+PS: 'Palestinian Territory'
+PT: Portugal
+PW: Palau
+PY: Paraguay
+QA: Qatar
+RE: Reunion
+RO: Romania
+RS: Serbia
+RU: Russia
+RW: Rwanda
+SA: 'Saudi Arabia'
+SB: 'Solomon Islands'
+SC: Seychelles
+SD: Sudan
+SS: 'South Sudan'
+SE: Sweden
+SG: Singapore
+SH: 'Saint Helena'
+SI: Slovenia
+SJ: 'Svalbard and Jan Mayen'
+SK: Slovakia
+SL: 'Sierra Leone'
+SM: 'San Marino'
+SN: Senegal
+SO: Somalia
+SR: Suriname
+ST: 'Sao Tome and Principe'
+SV: 'El Salvador'
+SX: 'Sint Maarten'
+SY: Syria
+SZ: Swaziland
+TC: 'Turks and Caicos Islands'
+TD: Chad
+TF: 'French Southern Territories'
+TG: Togo
+TH: Thailand
+TJ: Tajikistan
+TK: Tokelau
+TL: 'East Timor'
+TM: Turkmenistan
+TN: Tunisia
+TO: Tonga
+TR: Turkey
+TT: 'Trinidad and Tobago'
+TV: Tuvalu
+TW: Taiwan
+TZ: Tanzania
+UA: Ukraine
+UG: Uganda
+UM: 'United States Minor Outlying Islands'
+US: 'United States'
+UY: Uruguay
+UZ: Uzbekistan
+VA: Vatican
+VC: 'Saint Vincent and the Grenadines'
+VE: Venezuela
+VG: 'British Virgin Islands'
+VI: 'U.S. Virgin Islands'
+VN: Vietnam
+VU: Vanuatu
+WF: 'Wallis and Futuna'
+WS: Samoa
+YE: Yemen
+YT: Mayotte
+ZA: 'South Africa'
+ZM: Zambia
+ZW: Zimbabwe
+CS: 'Serbia and Montenegro'
+AN: 'Netherlands Antilles'
+AD.06: 'Parròquia de Sant Julià de Lòria'
+AD.05: 'Parròquia d''Ordino'
+AD.04: 'Parròquia de la Massana'
+AD.03: 'Parròquia d''Encamp'
+AD.02: Canillo
+AD.07: 'Parròquia d''Andorra la Vella'
+AD.08: 'Parròquia d''Escaldes-Engordany'
+AE.07: 'Umm al Qaywayn'
+AE.05: 'Raʼs al Khaymah'
+AE.03: Dubai
+AE.06: 'Ash Shāriqah'
+AE.04: 'Al Fujayrah'
+AE.02: Ajman
+AE.01: 'Abu Dhabi'
+AF.28: Zabul
+AF.27: Vardak
+AF.26: Takhār
+AF.33: 'Sar-e Pol'
+AF.32: Samangān
+AF.40: Parvān
+AF.29: Paktīkā
+AF.36: Paktia
+AF.39: Orūzgān
+AF.19: Nīmrūz
+AF.18: Nangarhār
+AF.17: Lowgar
+AF.35: Laghmān
+AF.24: Kunduz
+AF.34: Konar
+AF.14: Kāpīsā
+AF.23: Kandahār
+AF.13: Kabul
+AF.31: Jowzjān
+AF.11: Herat
+AF.10: Helmand
+AF.09: Ghowr
+AF.08: Ghaznī
+AF.07: Faryab
+AF.06: Farah
+AF.05: Bāmīān
+AF.30: 'Balkh Province'
+AF.03: 'Wilāyat-e Baghlān'
+AF.02: Badghis
+AF.01: Badakhshan
+AF.37: Khowst
+AF.38: Nūrestān
+AF.41: 'Wilāyat-e Dāykundī'
+AF.42: Panjshir
+AG.08: 'Saint Philip'
+AG.07: 'Saint Peter'
+AG.06: 'Saint Paul'
+AG.05: 'Saint Mary'
+AG.04: 'Saint John'
+AG.03: 'Saint George'
+AG.09: Redonda
+AG.01: Barbuda
+AL.40: Berat
+AL.41: Dibër
+AL.43: Elbasan
+AL.45: Gjirokastër
+AL.46: Korçë
+AL.47: Kukës
+AL.42: Durrës
+AL.44: Fier
+AL.48: Lezhë
+AL.49: Shkodër
+AL.50: Tiranë
+AL.51: Vlorë
+AM.02: Ararat
+AM.08: Syunikʼ
+AM.10: 'Vayotsʼ Dzor'
+AM.11: Yerevan
+AM.01: Aragatsotn
+AM.03: Armavir
+AM.04: Gegharkʼunikʼ
+AM.05: Kotaykʼ
+AM.06: Lorri
+AM.07: Shirak
+AM.09: Tavush
+AO.18: 'Lunda Sul'
+AO.17: 'Lunda Norte'
+AO.14: Moxico
+AO.04: 'Cuando Cubango'
+AO.16: Zaire
+AO.15: Uíge
+AO.12: Malanje
+AO.20: Luanda
+AO.05: 'Cuanza Norte'
+AO.03: Cabinda
+AO.19: Bengo
+AO.13: Namibe
+AO.09: Huíla
+AO.08: Huambo
+AO.07: Cunene
+AO.06: 'Cuanza Sul'
+AO.02: Bié
+AO.01: Benguela
+AR.14: Misiones
+AR.09: Formosa
+AR.07: 'Buenos Aires F.D.'
+AR.08: 'Entre Ríos'
+AR.06: Corrientes
+AR.01: 'Buenos Aires'
+AR.24: Tucumán
+AR.23: 'Tierra del Fuego'
+AR.22: 'Santiago del Estero'
+AR.21: 'Santa Fe'
+AR.20: 'Santa Cruz'
+AR.19: 'San Luis'
+AR.18: 'San Juan'
+AR.17: Salta
+AR.16: 'Río Negro'
+AR.15: Neuquén
+AR.13: Mendoza
+AR.12: 'La Rioja'
+AR.11: 'La Pampa'
+AR.10: Jujuy
+AR.05: Córdoba
+AR.04: Chubut
+AR.03: Chaco
+AR.02: Catamarca
+AS.050: 'Western District'
+AS.040: 'Swains Island'
+AS.010: 'Eastern District'
+AS.020: 'Manu''a'
+AS.030: 'Rose Atoll'
+AT.09: Vienna
+AT.08: Vorarlberg
+AT.07: Tyrol
+AT.06: Styria
+AT.05: Salzburg
+AT.04: 'Upper Austria'
+AT.03: 'Lower Austria'
+AT.02: Carinthia
+AT.01: Burgenland
+AU.08: 'Western Australia'
+AU.05: 'South Australia'
+AU.03: 'Northern Territory'
+AU.07: Victoria
+AU.06: Tasmania
+AU.04: Queensland
+AU.02: 'New South Wales'
+AU.01: 'Australian Capital Territory'
+AX.941: Vårdö
+AX.771: Sund
+AX.766: Sottunga
+AX.736: Saltvik
+AX.438: Lumparland
+AX.417: Lemland
+AX.295: Kumlinge
+AX.318: Kökar
+AX.062: Föglö
+AX.035: Brändö
+AX.478: Mariehamn
+AX.170: Jomala
+AX.076: Hammarland
+AX.065: Geta
+AX.060: Finström
+AX.043: Eckerö
+AZ.12: Beyləqan
+AZ.69: Zǝngilan
+AZ.66: Yardımlı
+AZ.55: Şuşa
+AZ.49: Salyan
+AZ.46: Sabirabad
+AZ.45: Saatlı
+AZ.13: Bilǝsuvar
+AZ.36: Neftçala
+AZ.35: Nakhichevan
+AZ.32: Masallı
+AZ.31: Lerik
+AZ.29: Lənkəran
+AZ.28: Laçın
+AZ.43: Qubadlı
+AZ.24: İmişli
+AZ.18: Füzuli
+AZ.14: Cǝbrayıl
+AZ.15: Cəlilabad
+AZ.08: Astara
+AZ.64: Xocalı
+AZ.02: Ağcabǝdi
+AZ.03: Ağdam
+AZ.07: 'Əli Bayramli'
+AZ.30: 'Lənkəran Şəhəri'
+AZ.56: 'Şuşa Şəhəri'
+AZ.57: Tǝrtǝr
+AZ.61: Xankǝndi
+AZ.65: Xocavǝnd
+AZ.71: Zərdab
+AZ.70: Zaqatala
+AZ.67: Yevlax
+AZ.37: Oğuz
+AZ.59: Ucar
+AZ.58: Tovuz
+AZ.50: Şamaxı
+AZ.47: Şǝki
+AZ.51: Şǝmkir
+AZ.27: Kürdǝmir
+AZ.38: Qǝbǝlǝ
+AZ.44: Qusar
+AZ.42: Quba
+AZ.62: 'Goygol Rayon'
+AZ.60: Xaçmaz
+AZ.26: Kǝlbǝcǝr
+AZ.40: Qazax
+AZ.21: Goranboy
+AZ.39: Qǝx
+AZ.25: İsmayıllı
+AZ.22: Göyçay
+AZ.17: Dǝvǝçi
+AZ.16: Daşkǝsǝn
+AZ.10: Balakǝn
+AZ.11: Bǝrdǝ
+AZ.09: Baki
+AZ.01: Abşeron
+AZ.06: Ağsu
+AZ.04: Ağdaş
+AZ.19: Gǝdǝbǝy
+AZ.05: Ağstafa
+AZ.20: Gǝncǝ
+AZ.33: Mingǝcevir
+AZ.34: Naftalan
+AZ.41: Qobustan
+AZ.52: Samux
+AZ.48: 'Shaki City'
+AZ.53: Siyǝzǝn
+AZ.54: Sumqayit
+AZ.63: Xızı
+AZ.68: 'Yevlax City'
+AZ.23: Hacıqabul
+AZ.75: 'Naxçıvan Şəhəri'
+BA.01: 'Federation of Bosnia and Herzegovina'
+BA.02: 'Republika Srpska'
+BA.BRC: Brčko
+BB.11: 'Saint Thomas'
+BB.10: 'Saint Philip'
+BB.09: 'Saint Peter'
+BB.08: 'Saint Michael'
+BB.07: 'Saint Lucy'
+BB.06: 'Saint Joseph'
+BB.05: 'Saint John'
+BB.04: 'Saint James'
+BB.03: 'Saint George'
+BB.02: 'Saint Andrew'
+BB.01: 'Christ Church'
+BD.83: Rājshāhi
+BD.81: Dhaka
+BD.84: Chittagong
+BD.82: Khulna
+BD.85: Barisāl
+BD.86: Sylhet
+BD.87: 'Rangpur Division'
+BE.BRU: 'Brussels Capital Region'
+BE.WAL: 'Walloon Region'
+BE.VLG: Flanders
+BF.01: 'Boucle du Mouhoun Region'
+BF.02: 'Cascades Region'
+BF.03: Centre
+BF.04: Centre-Est
+BF.05: Centre-Nord
+BF.06: Centre-Ouest
+BF.07: Centre-Sud
+BF.08: Est
+BF.09: 'High-Basins Region'
+BF.10: Nord
+BF.11: Plateau-Central
+BF.12: Sahel
+BF.13: 'Southwest Region'
+BG.52: Razgrad
+BG.47: Montana
+BG.64: Vratsa
+BG.61: Varna
+BG.40: Dobrich
+BG.58: Sofiya
+BG.53: Ruse
+BG.51: Plovdiv
+BG.50: Pleven
+BG.49: Pernik
+BG.48: Pazardzhit
+BG.46: Lovech
+BG.43: Khaskovo
+BG.42: Sofia-Capital
+BG.39: Burgas
+BG.38: Blagoevgrad
+BG.41: 'Gabrovo Province'
+BG.44: Kŭrdzhali
+BG.45: Kyustendil
+BG.54: Shumen
+BG.55: Silistra
+BG.56: Sliven
+BG.57: Smolyan
+BG.59: 'Stara Zagora'
+BG.60: Tŭrgovishte
+BG.62: 'Veliko Tŭrnovo'
+BG.63: Vidin
+BG.65: Yambol
+BH.15: Muharraq
+BH.16: Capital
+BH.17: 'Southern Governorate'
+BH.18: 'Central Governorate'
+BH.19: Northern
+BI.17: Makamba
+BI.10: Bururi
+BI.22: Muramvya
+BI.13: Gitega
+BI.21: Ruyigi
+BI.11: Cankuzo
+BI.14: Karuzi
+BI.09: Bubanza
+BI.12: Cibitoke
+BI.19: Ngozi
+BI.15: Kayanza
+BI.18: Muyinga
+BI.16: Kirundo
+BI.20: Rutana
+BI.23: Mwaro
+BI.24: 'Bujumbura Mairie Province'
+BI.25: 'Bujumbura Rural Province'
+BJ.18: Zou
+BJ.16: Quémé
+BJ.15: Mono
+BJ.10: Borgou
+BJ.09: Atlantique
+BJ.08: Atakora
+BJ.07: Alibori
+BJ.11: Collines
+BJ.12: Kouffo
+BJ.13: Donga
+BJ.14: Littoral
+BJ.17: Plateau
+BM.11: Warwick
+BM.10: Southampton
+BM.09: Smithʼs
+BM.08: Sandys
+BM.07: 'Saint Georgeʼs'
+BM.06: 'Saint George'
+BM.05: Pembroke
+BM.04: Paget
+BM.02: 'Hamilton Parish'
+BM.03: 'Hamilton city'
+BM.01: Devonshire
+BN.04: Tutong
+BN.03: Temburong
+BN.02: 'Brunei and Muara'
+BN.01: Belait
+BO.09: Tarija
+BO.08: 'Santa Cruz'
+BO.07: Potosí
+BO.06: Pando
+BO.05: Oruro
+BO.04: 'La Paz'
+BO.02: Cochabamba
+BO.01: Chuquisaca
+BO.03: 'El Beni'
+BQ.BO: Bonaire
+BQ.SB: Saba
+BQ.SE: 'Sint Eustatius'
+BR.22: 'Rio Grande do Norte'
+BR.20: Piauí
+BR.30: Pernambuco
+BR.17: Paraíba
+BR.16: Pará
+BR.13: Maranhão
+BR.06: Ceará
+BR.03: Amapá
+BR.02: Alagoas
+BR.28: Sergipe
+BR.27: 'São Paulo'
+BR.26: 'Santa Catarina'
+BR.23: 'Rio Grande do Sul'
+BR.21: 'Rio de Janeiro'
+BR.18: Paraná
+BR.15: 'Minas Gerais'
+BR.11: 'Estado de Mato Grosso do Sul'
+BR.14: 'Mato Grosso'
+BR.29: Goiás
+BR.07: 'Federal District'
+BR.08: 'Espírito Santo'
+BR.05: 'Estado de Bahía'
+BR.31: Tocantins
+BR.25: Roraima
+BR.04: Amazonas
+BR.01: Acre
+BR.24: Rondônia
+BS.35: 'San Salvador'
+BS.34: 'Sandy Point'
+BS.33: 'Rock Sound'
+BS.18: 'Ragged Island'
+BS.32: 'Berry Islands District'
+BS.23: 'New Providence'
+BS.16: Mayaguana
+BS.31: 'Marsh Harbour'
+BS.15: 'Long Island'
+BS.30: 'Kemps Bay'
+BS.13: Inagua
+BS.29: 'High Rock'
+BS.22: 'Harbour Island'
+BS.28: 'Green Turtle Cay'
+BS.27: 'Governorʼs Harbour'
+BS.26: 'Fresh Creek'
+BS.25: Freeport
+BS.10: Exuma
+BS.06: 'Cat Island'
+BS.05: Bimini
+BS.24: 'Acklins and Crooked Islands'
+BS.36: 'Black Point'
+BS.37: 'Central Abaco'
+BS.38: 'Central Andros'
+BS.39: 'Central Eleuthera'
+BS.40: 'Crooked Island and Long Cay'
+BS.41: 'East Grand Bahama'
+BS.42: 'Grand Cay'
+BS.43: 'Hope Town'
+BS.44: 'Mangrove Cay'
+BS.45: 'Moore’s Island'
+BS.46: 'North Abaco'
+BS.47: 'North Andros'
+BS.48: 'North Eleuthera'
+BS.49: 'Rum Cay'
+BS.50: 'South Abaco'
+BS.51: 'South Andros'
+BS.52: 'South Eleuthera'
+BS.53: 'Spanish Wells'
+BS.54: 'West Grand Bahama'
+BT.05: Bumthang
+BT.06: Chhukha
+BT.08: Daga
+BT.07: Chirang
+BT.09: Geylegphug
+BT.10: Ha
+BT.11: Lhuntshi
+BT.12: Mongar
+BT.13: Paro
+BT.14: Pemagatsel
+BT.15: Punakha
+BT.16: Samchi
+BT.17: 'Samdrup Jongkhar'
+BT.18: Shemgang
+BT.19: Tashigang
+BT.20: Thimphu
+BT.21: Tongsa
+BT.22: 'Wangdi Phodrang'
+BT.23: Gasa
+BT.24: 'Trashi Yangste'
+BW.10: Southern
+BW.09: 'South East'
+BW.08: 'North East'
+BW.11: 'North West'
+BW.06: Kweneng
+BW.05: Kgatleng
+BW.04: Kgalagadi
+BW.03: Ghanzi
+BW.01: Central
+BY.07: 'Vitsyebskaya Voblastsʼ'
+BY.06: 'Mahilyowskaya Voblastsʼ'
+BY.05: 'Minskaya Voblastsʼ'
+BY.04: Minsk
+BY.03: 'Hrodzyenskaya Voblastsʼ'
+BY.02: 'Homyelʼskaya Voblastsʼ'
+BY.01: 'Brestskaya Voblastsʼ'
+BZ.06: Toledo
+BZ.05: 'Stann Creek'
+BZ.04: 'Orange Walk'
+BZ.03: Corozal
+BZ.02: Cayo
+BZ.01: Belize
+CA.01: Alberta
+CA.02: 'British Columbia'
+CA.03: Manitoba
+CA.04: 'New Brunswick'
+CA.13: 'Northwest Territories'
+CA.07: 'Nova Scotia'
+CA.14: Nunavut
+CA.08: Ontario
+CA.09: 'Prince Edward Island'
+CA.10: Quebec
+CA.11: Saskatchewan
+CA.12: Yukon
+CA.05: 'Newfoundland and Labrador'
+CD.12: 'South Kivu'
+CD.05: Katanga
+CD.11: 'Nord Kivu'
+CD.10: Maniema
+CD.04: Kasaï-Oriental
+CD.03: Kasaï-Occidental
+CD.09: 'Eastern Province'
+CD.02: Équateur
+CD.06: Kinshasa
+CD.08: Bas-Congo
+CD.01: Bandundu
+CF.14: Vakaga
+CF.11: Ouaka
+CF.08: Mbomou
+CF.05: Haut-Mbomou
+CF.03: Haute-Kotto
+CF.02: Basse-Kotto
+CF.01: Bamingui-Bangoran
+CF.16: Sangha-Mbaéré
+CF.13: Ouham-Pendé
+CF.12: Ouham
+CF.17: Ombella-Mpoko
+CF.09: Nana-Mambéré
+CF.07: Lobaye
+CF.06: Kémo
+CF.04: Mambéré-Kadéï
+CF.15: Nana-Grébizi
+CF.18: Bangui
+CG.10: Sangha
+CG.11: Pool
+CG.08: Plateaux
+CG.07: Niari
+CG.06: Likouala
+CG.05: Lékoumou
+CG.04: Kouilou
+CG.13: Cuvette
+CG.01: Bouenza
+CG.12: Brazzaville
+CG.14: Cuvette-Ouest
+CG.7280295: Pointe-Noire
+CH.ZH: Zurich
+CH.ZG: Zug
+CH.VD: Vaud
+CH.VS: Valais
+CH.UR: Uri
+CH.TI: Ticino
+CH.TG: Thurgau
+CH.SO: Solothurn
+CH.SZ: Schwyz
+CH.SH: Schaffhausen
+CH.SG: 'Saint Gallen'
+CH.OW: Obwalden
+CH.NW: Nidwalden
+CH.NE: Neuchâtel
+CH.LU: Lucerne
+CH.JU: Jura
+CH.GR: Grisons
+CH.GL: Glarus
+CH.GE: Geneva
+CH.FR: Fribourg
+CH.BE: Bern
+CH.BS: Basel-City
+CH.BL: Basel-Landschaft
+CH.AR: 'Appenzell Ausserrhoden'
+CH.AI: 'Canton d''Appenzell Rhoden-Intérieur'
+CH.AG: Aargau
+CI.82: Lagunes
+CI.89: Sud-Comoé
+CI.74: Agnéby
+CI.80: Haut-Sassandra
+CI.87: Savanes
+CI.90: 'Vallée du Bandama'
+CI.85: Moyen-Comoé
+CI.78: 'Dix-Huit Montagnes'
+CI.81: Lacs
+CI.92: Zanzan
+CI.76: Bas-Sassandra
+CI.91: Worodougou
+CI.77: Denguélé
+CI.88: Sud-Bandama
+CI.79: Fromager
+CI.86: Nʼzi-Comoé
+CI.83: Marahoué
+CI.84: Moyen-Cavally
+CI.75: Bafing
+CL.01: Valparaíso
+CL.15: 'Tarapacá Region'
+CL.12: Santiago
+CL.11: Maule
+CL.14: 'Los Lagos'
+CL.08: 'O''Higgins'
+CL.07: Coquimbo
+CL.06: Biobío
+CL.05: Atacama
+CL.04: Araucanía
+CL.03: Antofagasta
+CL.02: Aisén
+CL.10: Magallanes
+CL.16: 'Arica y Parinacota'
+CL.17: 'Los Ríos'
+CM.09: 'South-West Province'
+CM.14: 'South Province'
+CM.08: 'West Region'
+CM.07: 'North-West Province'
+CM.13: 'North Province'
+CM.05: 'Littoral Province'
+CM.12: 'Far North Region'
+CM.04: 'East Province'
+CM.11: 'Centre Region'
+CM.10: 'Adamaoua Province'
+CN.14: 'Tibet Autonomous Region'
+CN.06: 'Qinghai Sheng'
+CN.13: 'Xinjiang Uygur Zizhiqu'
+CN.02: 'Zhejiang Sheng'
+CN.29: Yunnan
+CN.28: 'Tianjin Shi'
+CN.32: Sichuan
+CN.24: 'Shanxi Sheng'
+CN.23: 'Shanghai Shi'
+CN.25: 'Shandong Sheng'
+CN.26: Shaanxi
+CN.21: 'Ningxia Huizu Zizhiqu'
+CN.03: 'Jiangxi Sheng'
+CN.04: 'Jiangsu Sheng'
+CN.11: Hunan
+CN.12: Hubei
+CN.09: 'Henan Sheng'
+CN.10: Hebei
+CN.31: Hainan
+CN.18: 'Guizhou Sheng'
+CN.16: 'Guangxi Zhuangzu Zizhiqu'
+CN.30: 'Guangdong Province'
+CN.15: 'Gansu Sheng'
+CN.07: Fujian
+CN.33: 'Chongqing Shi'
+CN.01: 'Anhui Sheng'
+CN.20: 'Inner Mongolia'
+CN.19: Liaoning
+CN.05: 'Jilin Sheng'
+CN.08: 'Heilongjiang Sheng'
+CN.22: Beijing
+CO.31: Vichada
+CO.30: Vaupés
+CO.29: 'Valle del Cauca'
+CO.28: Tolima
+CO.27: Sucre
+CO.26: Santander
+CO.25: 'Archipiélago de San Andrés, Providencia y Santa Catalina'
+CO.24: Risaralda
+CO.23: Quindío
+CO.22: Putumayo
+CO.21: 'Norte de Santander'
+CO.20: Nariño
+CO.19: Meta
+CO.38: Magdalena
+CO.17: 'La Guajira'
+CO.16: Huila
+CO.14: Guaviare
+CO.15: Guainía
+CO.33: Cundinamarca
+CO.12: Córdoba
+CO.11: Chocó
+CO.10: Cesar
+CO.09: Cauca
+CO.32: Casanare
+CO.08: Caquetá
+CO.37: Caldas
+CO.36: Boyacá
+CO.35: Bolívar
+CO.34: 'Bogota D.C.'
+CO.04: Atlántico
+CO.03: Arauca
+CO.02: 'Departamento de Antioquia'
+CO.01: Amazonas
+CR.08: 'San José'
+CR.07: Puntarenas
+CR.06: Limón
+CR.04: Heredia
+CR.03: Guanacaste
+CR.02: Cartago
+CR.01: Alajuela
+CU.16: 'Villa Clara'
+CU.15: 'Santiago de Cuba'
+CU.14: 'Sancti Spíritus'
+CU.01: 'Pinar del Río'
+CU.03: Matanzas
+CU.13: 'Las Tunas'
+CU.04: 'Isla de la Juventud'
+CU.12: Holguín
+CU.10: Guantánamo
+CU.09: Granma
+CU.02: 'Ciudad de La Habana'
+CU.08: Cienfuegos
+CU.07: 'Ciego de Ávila'
+CU.05: Camagüey
+CU.AR: 'Provincia Artemisa'
+CU.MA: 'Provincia Mayabeque'
+CV.20: Tarrafal
+CV.11: 'São Vicente'
+CV.15: 'Santa Catarina'
+CV.08: 'Sal Municipality'
+CV.07: 'Ribeira Grande'
+CV.14: Praia
+CV.05: Paul
+CV.04: Maio
+CV.02: Brava
+CV.01: 'Boa Vista'
+CV.13: Mosteiros
+CV.16: 'Santa Cruz'
+CV.17: 'São Domingos'
+CV.18: 'São Filipe'
+CV.19: 'São Miguel'
+CV.21: 'Porto Novo'
+CV.22: 'Ribeira Brava'
+CV.24: 'Santa Catarina do Fogo'
+CV.26: 'São Salvador do Mundo'
+CV.27: 'Tarrafal de São Nicolau'
+CV.25: 'Concelho de São Lourenço dos Órgãos'
+CV.23: 'Ribeira Grande de Santiago'
+CY.06: Pafos
+CY.04: Lefkosia
+CY.05: Lemesos
+CY.03: Larnaka
+CY.02: Keryneia
+CY.01: Ammochostos
+CZ.52: Praha
+CZ.78: 'South Moravian Region'
+CZ.79: Jihočeský
+CZ.80: Vysočina
+CZ.81: Karlovarský
+CZ.82: Královéhradecký
+CZ.83: Liberecký
+CZ.84: Olomoucký
+CZ.85: Moravskoslezský
+CZ.86: Pardubický
+CZ.87: Plzeňský
+CZ.88: Středočeský
+CZ.89: Ústecký
+CZ.90: Zlínský
+DE.15: Thuringia
+DE.10: Schleswig-Holstein
+DE.14: Saxony-Anhalt
+DE.13: Saxony
+DE.09: Saarland
+DE.08: Rheinland-Pfalz
+DE.07: 'North Rhine-Westphalia'
+DE.06: 'Lower Saxony'
+DE.12: Mecklenburg-Vorpommern
+DE.05: Hesse
+DE.04: 'Free and Hanseatic City of Hamburg'
+DE.03: Bremen
+DE.11: Brandenburg
+DE.16: Berlin
+DE.02: Bavaria
+DE.01: 'Baden-Württemberg Region'
+DJ.05: Tadjourah
+DJ.04: Obock
+DJ.07: Djibouti
+DJ.06: Dikhil
+DJ.01: 'Ali Sabieh'
+DJ.08: Arta
+DK.17: 'Capital Region'
+DK.18: 'Central Jutland'
+DK.19: 'North Denmark Region'
+DK.20: Zealand
+DK.21: 'South Denmark'
+DM.11: 'Saint Peter'
+DM.10: 'Saint Paul'
+DM.09: 'Saint Patrick'
+DM.08: 'Saint Mark'
+DM.07: 'Saint Luke'
+DM.06: 'Saint Joseph'
+DM.05: 'Saint John'
+DM.04: 'Saint George'
+DM.03: 'Saint David'
+DM.02: 'Saint Andrew'
+DO.27: Valverde
+DO.26: 'Santiago Rodríguez'
+DO.25: Santiago
+DO.24: 'San Pedro de Macorís'
+DO.23: 'San Juan'
+DO.33: 'San Cristóbal'
+DO.21: 'Sánchez Ramírez'
+DO.20: Samaná
+DO.19: 'Hermanas Mirabal'
+DO.18: 'Puerto Plata'
+DO.35: Peravia
+DO.16: Pedernales
+DO.34: 'Distrito Nacional'
+DO.32: 'Monte Plata'
+DO.15: 'Monte Cristi'
+DO.31: 'Monseñor Nouel'
+DO.14: 'María Trinidad Sánchez'
+DO.30: 'La Vega'
+DO.12: 'La Romana'
+DO.10: 'La Altagracia'
+DO.09: Independencia
+DO.29: 'Hato Mayor'
+DO.08: Espaillat
+DO.28: 'El Seíbo'
+DO.11: 'Elías Piña'
+DO.06: Duarte
+DO.04: Dajabón
+DO.03: Barahona
+DO.02: Baoruco
+DO.01: Azua
+DO.36: 'San José de Ocoa'
+DO.37: 'Santo Domingo'
+DZ.15: Tlemcen
+DZ.14: 'Tizi Ouzou'
+DZ.56: Tissemsilt
+DZ.55: Tipaza
+DZ.54: Tindouf
+DZ.13: Tiaret
+DZ.33: Tébessa
+DZ.53: Tamanghasset
+DZ.52: 'Souk Ahras'
+DZ.31: Skikda
+DZ.30: 'Sidi Bel Abbès'
+DZ.12: Sétif
+DZ.10: Saïda
+DZ.51: Relizane
+DZ.29: 'Oum el Bouaghi'
+DZ.50: Ouargla
+DZ.09: Oran
+DZ.49: 'Naama النعامة'
+DZ.27: Mʼsila
+DZ.07: Mostaganem
+DZ.48: Mila
+DZ.06: Médéa
+DZ.26: Mascara
+DZ.25: Laghouat
+DZ.47: Khenchela
+DZ.24: Jijel
+DZ.46: Illizi
+DZ.23: Guelma
+DZ.45: Ghardaïa
+DZ.44: 'El Tarf'
+DZ.43: 'El Oued'
+DZ.42: 'El Bayadh'
+DZ.22: Djelfa
+DZ.04: Constantine
+DZ.41: Chlef
+DZ.40: Boumerdes
+DZ.21: Bouira
+DZ.39: 'Bordj Bou Arréridj'
+DZ.20: Blida
+DZ.19: Biskra
+DZ.18: Bejaïa
+DZ.38: Béchar
+DZ.03: Batna
+DZ.37: Annaba
+DZ.01: Alger
+DZ.36: 'Aïn Temouchent'
+DZ.35: 'Aïn Defla'
+DZ.34: Adrar
+EC.20: Zamora-Chinchipe
+EC.19: Tungurahua
+EC.18: Pichincha
+EC.17: Pastaza
+EC.23: Napo
+EC.15: Morona-Santiago
+EC.14: Manabí
+EC.13: 'Los Ríos'
+EC.12: Loja
+EC.11: Imbabura
+EC.10: Guayas
+EC.01: Galápagos
+EC.09: Esmeraldas
+EC.08: 'El Oro'
+EC.07: Cotopaxi
+EC.06: Chimborazo
+EC.05: Carchi
+EC.04: Cañar
+EC.03: Bolívar
+EC.02: Azuay
+EC.22: Sucumbios
+EC.24: Orellana
+EC.26: 'Santo Domingo de los Tsáchilas'
+EC.25: 'Santa Elena'
+EE.21: Võrumaa
+EE.20: Viljandimaa
+EE.19: Valgamaa
+EE.18: 'Tartu County'
+EE.14: 'Saare County'
+EE.13: Raplamaa
+EE.12: Põlvamaa
+EE.11: Pärnumaa
+EE.08: Lääne-Virumaa
+EE.07: 'Lääne County'
+EE.05: Jõgevamaa
+EE.04: Järvamaa
+EE.03: Ida-Virumaa
+EE.02: Hiiumaa
+EE.01: 'Harju County'
+EG.24: Sūhāj
+EG.27: 'Shamāl Sīnāʼ'
+EG.23: Qinā
+EG.22: Maţrūḩ
+EG.21: 'Kafr ash Shaykh'
+EG.26: 'Janūb Sīnāʼ'
+EG.20: Dumyāţ
+EG.19: 'Būr Sa‘īd'
+EG.18: 'Banī Suwayf'
+EG.17: Asyūţ
+EG.16: Aswān
+EG.15: 'As Suways'
+EG.14: 'Eastern Province'
+EG.13: 'Al Wādī al Jadīd'
+EG.12: 'Al Qalyūbīyah'
+EG.11: 'Al Qāhirah'
+EG.10: 'Al Minyā'
+EG.09: 'Al Minūfīyah'
+EG.08: 'Al Jīzah'
+EG.07: 'Al Ismā‘īlīyah'
+EG.06: Alexandria
+EG.05: 'Al Gharbīyah'
+EG.04: 'Al Fayyūm'
+EG.03: 'Al Buḩayrah'
+EG.02: 'Al Baḩr al Aḩmar'
+EG.01: 'Ad Daqahlīyah'
+EG.28: 'Muḩāfaz̧at al Uqşur'
+EH.CE: 'Oued Ed-Dahab-Lagouira'
+ER.01: Ānseba
+ER.02: Debub
+ER.03: 'Debubawī Kʼeyih Bahrī'
+ER.04: 'Gash Barka'
+ER.05: Maʼākel
+ER.06: 'Semēnawī Kʼeyih Bahrī'
+ES.31: Murcia
+ES.CE: Ceuta
+ES.07: 'Balearic Islands'
+ES.51: Andalusia
+ES.53: 'Canary Islands'
+ES.54: 'Castille-La Mancha'
+ES.57: Extremadura
+ES.60: Valencia
+ES.34: Asturias
+ES.32: Navarre
+ES.29: Madrid
+ES.27: 'La Rioja'
+ES.39: Cantabria
+ES.52: Aragon
+ES.55: 'Castille and León'
+ES.56: Catalonia
+ES.58: Galicia
+ES.59: 'Basque Country'
+ES.ML: Melilla
+ET.44: 'Ādīs Ābeba'
+ET.45: 'Afar Region'
+ET.46: 'Amhara Region'
+ET.47: 'Benishangul-Gumuz Region'
+ET.48: 'Dire Dawa Region'
+ET.49: Gambela
+ET.50: 'Harari Region'
+ET.51: 'Oromiya Region'
+ET.52: 'Somali Region'
+ET.53: 'Tigray Region'
+ET.54: 'Southern Nations, Nationalities, and People''s Region'
+FI.08: Oulu
+FI.06: Lapponia
+FI.13: 'Southern Finland Province'
+FI.14: 'Eastern Finland Province'
+FI.15: 'Province of Western Finland'
+FJ.05: Western
+FJ.03: Northern
+FJ.01: Central
+FJ.02: Eastern
+FJ.04: Rotuma
+FM.04: Yap
+FM.02: Pohnpei
+FM.01: Kosrae
+FM.03: Chuuk
+FO.VG: Vágar
+FO.SU: Suðuroy
+FO.ST: Streymoy
+FO.SA: Sandoy
+FO.NO: Norðoyar
+FO.OS: Eysturoy
+FR.B9: Rhône-Alpes
+FR.B8: 'Provence-Alpes-Côte d''Azur'
+FR.B7: Poitou-Charentes
+FR.B6: Picardie
+FR.B5: 'Pays de la Loire'
+FR.B4: Nord-Pas-de-Calais
+FR.B3: Midi-Pyrénées
+FR.B2: Lorraine
+FR.B1: Limousin
+FR.A9: Languedoc-Roussillon
+FR.A8: Île-de-France
+FR.A7: 'Upper Normandy'
+FR.A6: Franche-Comté
+FR.A5: Corsica
+FR.A4: Champagne-Ardenne
+FR.A3: Centre
+FR.A2: Brittany
+FR.A1: Bourgogne
+FR.99: 'Lower Normandy'
+FR.98: Auvergne
+FR.97: Aquitaine
+FR.C1: Alsace
+GA.09: Woleu-Ntem
+GA.08: Ogooué-Maritime
+GA.07: Ogooué-Lolo
+GA.06: Ogooué-Ivindo
+GA.05: Nyanga
+GA.04: Ngounié
+GA.03: Moyen-Ogooué
+GA.02: Haut-Ogooué
+GA.01: Estuaire
+GB.WLS: Wales
+GB.SCT: Scotland
+GB.NIR: 'N Ireland'
+GB.ENG: England
+GD.06: 'Saint Patrick'
+GD.05: 'Saint Mark'
+GD.04: 'Saint John'
+GD.03: 'Saint George'
+GD.02: 'Saint David'
+GD.01: 'Saint Andrew'
+GD.10: 'Carriacou and Petite Martinique'
+GE.51: 'T''bilisi'
+GE.04: Ajaria
+GE.68: 'Kvemo Kartli'
+GE.67: Kakheti
+GE.65: Guria
+GE.66: Imereti
+GE.73: 'Shida Kartli'
+GE.69: Mtskheta-Mtianeti
+GE.70: 'Racha-Lechkhumi and Kvemo Svaneti'
+GE.71: 'Samegrelo and Zemo Svaneti'
+GE.72: Samtskhe-Javakheti
+GE.02: Abkhazia
+GF.GF: Guyane
+GH.09: Western
+GH.08: Volta
+GH.11: 'Upper West'
+GH.10: 'Upper East'
+GH.06: Northern
+GH.01: 'Greater Accra'
+GH.05: Eastern
+GH.04: Central
+GH.03: Brong-Ahafo
+GH.02: Ashanti
+GL.05: Qaasuitsup
+GL.04: Kujalleq
+GL.06: Qeqqata
+GL.07: Sermersooq
+GM.05: Western
+GM.04: 'Upper River'
+GM.07: 'North Bank'
+GM.03: 'Central River'
+GM.02: 'Lower River'
+GM.01: Banjul
+GN.04: Conakry
+GN.B: 'Boke Region'
+GN.F: 'Faranah Region'
+GN.K: 'Kankan Region'
+GN.D: 'Kindia Region'
+GN.L: 'Labé Region'
+GN.M: 'Mamou Region'
+GN.N: 'Nzerekore Region'
+GP.GP: Guadeloupe
+GQ.03: Annobón
+GQ.04: 'Bioko Norte'
+GQ.05: 'Bioko Sur'
+GQ.06: 'Centro Sur'
+GQ.07: Kié-Ntem
+GQ.08: Litoral
+GQ.09: Wele-Nzas
+GR.736572: 'Mount Athos'
+GR.ESYE31: Attica
+GR.ESYE24: 'Central Greece'
+GR.ESYE12: 'Central Macedonia'
+GR.ESYE43: Crete
+GR.ESYE11: 'East Macedonia and Thrace'
+GR.ESYE21: Epirus
+GR.ESYE22: 'Ionian Islands'
+GR.ESYE41: 'North Aegean'
+GR.ESYE25: Peloponnese
+GR.ESYE42: 'South Aegean'
+GR.ESYE14: Thessaly
+GR.ESYE23: 'West Greece'
+GR.ESYE13: 'West Macedonia'
+GT.22: Zacapa
+GT.21: Totonicapán
+GT.20: Suchitepéquez
+GT.19: Sololá
+GT.18: 'Santa Rosa'
+GT.17: 'San Marcos'
+GT.16: Sacatepéquez
+GT.15: Retalhuleu
+GT.14: Quiché
+GT.13: Quetzaltenango
+GT.12: Petén
+GT.11: Jutiapa
+GT.10: Jalapa
+GT.09: Izabal
+GT.08: Huehuetenango
+GT.07: Guatemala
+GT.06: Escuintla
+GT.05: 'El Progreso'
+GT.04: Chiquimula
+GT.03: Chimaltenango
+GT.02: 'Baja Verapaz'
+GT.01: 'Alta Verapaz'
+GU.PI: 'Piti Municipality'
+GU.SR: 'Santa Rita Municipality'
+GU.SJ: 'Sinajana Municipality'
+GU.TF: 'Talofofo Municipality'
+GU.TM: 'Tamuning-Tumon-Harmon Municipality'
+GU.UM: 'Umatac Municipality'
+GU.YG: 'Yigo Municipality'
+GU.YN: 'Yona Municipality'
+GU.ME: 'Merizo Municipality'
+GU.MA: 'Mangilao Municipality'
+GU.AH: 'Agana Heights Municipality'
+GU.CP: 'Chalan Pago-Ordot Municipality'
+GU.AS: 'Asan-Maina Municipality'
+GU.AT: 'Agat Municipality'
+GU.DD: 'Dededo Municipality'
+GU.BA: 'Barrigada Municipality'
+GU.AN: 'Hagåtña Municipality'
+GU.IN: 'Inarajan Municipality'
+GU.MT: 'Mongmong-Toto-Maite Municipality'
+GW.07: Tombali
+GW.02: Quinara
+GW.04: Oio
+GW.10: Gabú
+GW.06: Cacheu
+GW.05: 'Bolama and Bijagos'
+GW.11: 'Bissau Autonomous Region'
+GW.12: Biombo
+GW.01: Bafatá
+GY.19: 'Upper Takutu-Upper Essequibo'
+GY.18: 'Upper Demerara-Berbice'
+GY.17: Potaro-Siparuni
+GY.16: Pomeroon-Supenaam
+GY.15: Mahaica-Berbice
+GY.14: 'Essequibo Islands-West Demerara'
+GY.13: 'East Berbice-Corentyne'
+GY.12: Demerara-Mahaica
+GY.11: Cuyuni-Mazaruni
+GY.10: Barima-Waini
+HK.NYL: 'Yuen Long'
+HK.NTW: 'Tsuen Wan'
+HK.NTP: 'Tai Po'
+HK.NSK: 'Sai Kung'
+HK.NIS: Islands
+HK.HCW: 'Central and Western'
+HK.HWC: Wanchai
+HK.HEA: Eastern
+HK.HSO: Southern
+HK.KYT: 'Yau Tsim Mong'
+HK.KSS: 'Sham Shui Po'
+HK.KKC: 'Kowloon City'
+HK.KWT: 'Wong Tai Sin'
+HK.KKT: 'Kwon Tong'
+HK.NKT: 'Kwai Tsing'
+HK.NTM: 'Tuen Mun'
+HK.NNO: North
+HK.NST: 'Sha Tin'
+HN.18: Yoro
+HN.17: Valle
+HN.16: 'Santa Bárbara'
+HN.15: Olancho
+HN.14: Ocotepeque
+HN.13: Lempira
+HN.12: 'La Paz'
+HN.11: 'Bay Islands'
+HN.10: Intibucá
+HN.09: 'Gracias a Dios'
+HN.08: 'Francisco Morazán'
+HN.07: 'El Paraíso'
+HN.06: Cortés
+HN.05: Copán
+HN.04: Comayagua
+HN.03: Colón
+HN.02: Choluteca
+HN.01: Atlántida
+HR.01: Bjelovarsko-Bilogorska
+HR.02: Brodsko-Posavska
+HR.03: Dubrovačko-Neretvanska
+HR.04: Istarska
+HR.05: Karlovačka
+HR.06: Koprivničko-Križevačka
+HR.07: Krapinsko-Zagorska
+HR.08: Ličko-Senjska
+HR.09: Međimurska
+HR.10: Osječko-Baranjska
+HR.11: Požeško-Slavonska
+HR.12: Primorsko-Goranska
+HR.13: Šibensko-Kniniska
+HR.14: Sisačko-Moslavačka
+HR.15: Splitsko-Dalmatinska
+HR.16: Varaždinska
+HR.18: Vukovarsko-Srijemska
+HR.19: Zadarska
+HR.20: Zagrebačka
+HR.21: 'Grad Zagreb'
+HR.17: Virovitičk-Podravska
+HT.13: Sud-Est
+HT.12: Sud
+HT.11: Ouest
+HT.03: Nord-Ouest
+HT.10: Nord-Est
+HT.09: Nord
+HT.14: GrandʼAnse
+HT.07: Centre
+HT.06: Artibonite
+HT.15: Nippes
+HU.18: Szabolcs-Szatmár-Bereg
+HU.20: Jász-Nagykun-Szolnok
+HU.11: Heves
+HU.10: Hajdú-Bihar
+HU.06: Csongrád
+HU.04: Borsod-Abaúj-Zemplén
+HU.03: 'Bekes County'
+HU.24: Zala
+HU.23: Veszprém
+HU.22: Vas
+HU.21: Tolna
+HU.17: Somogy
+HU.16: Pest
+HU.14: Nógrád
+HU.12: Komárom-Esztergom
+HU.09: Győr-Moson-Sopron
+HU.08: Fejér
+HU.05: Budapest
+HU.02: 'Baranya county'
+HU.01: Bács-Kiskun
+ID.26: 'North Sumatra'
+ID.01: Aceh
+ID.10: 'Daerah Istimewa Yogyakarta'
+ID.32: 'South Sumatra'
+ID.24: 'West Sumatra'
+ID.31: 'North Sulawesi'
+ID.22: 'Sulawesi Tenggara'
+ID.21: 'Central Sulawesi'
+ID.38: 'South Sulawesi'
+ID.37: Riau
+ID.18: 'East Nusa Tenggara'
+ID.17: 'Nusa Tenggara Barat'
+ID.28: Maluku
+ID.15: Lampung
+ID.14: 'East Kalimantan'
+ID.13: 'Kalimantan Tengah'
+ID.12: 'South Kalimantan'
+ID.11: 'West Kalimantan'
+ID.08: 'East Java'
+ID.07: 'Central Java'
+ID.30: 'West Java'
+ID.05: Jambi
+ID.04: 'Jakarta Raya'
+ID.36: Papua
+ID.03: Bengkulu
+ID.02: Bali
+ID.33: Banten
+ID.34: Gorontalo
+ID.35: Bangka-Belitung
+ID.29: 'Maluku Utara'
+ID.39: 'West Papua'
+ID.41: 'Sulawesi Barat'
+ID.40: 'Riau Islands'
+IE.C: Connaught
+IE.L: Leinster
+IE.M: Munster
+IE.U: Ulster
+IL.06: 'Jerusalem District'
+IL.05: 'Tel Aviv'
+IL.04: 'Haifa District'
+IL.03: 'Northern District'
+IL.02: 'Central District'
+IL.01: 'Southern District'
+IN.28: Bengal
+IN.36: 'Uttar Pradesh'
+IN.26: Tripura
+IN.25: 'Tamil Nādu'
+IN.29: Sikkim
+IN.24: Rajasthan
+IN.23: Punjab
+IN.22: Pondicherry
+IN.21: Orissa
+IN.20: Nāgāland
+IN.31: Mizoram
+IN.18: Meghālaya
+IN.17: Manipur
+IN.16: Mahārāshtra
+IN.35: 'Madhya Pradesh'
+IN.14: Laccadives
+IN.13: Kerala
+IN.19: Karnātaka
+IN.12: Kashmir
+IN.11: 'Himachal Pradesh'
+IN.10: Haryana
+IN.09: Gujarāt
+IN.32: 'Daman and Diu'
+IN.33: Goa
+IN.07: NCT
+IN.06: 'Dādra and Nagar Haveli'
+IN.05: Chandīgarh
+IN.34: Bihār
+IN.03: Assam
+IN.30: 'Arunāchal Pradesh'
+IN.02: 'Andhra Pradesh'
+IN.01: 'Andaman and Nicobar Islands'
+IN.37: Chhattisgarh
+IN.38: Jharkhand
+IN.39: Uttarakhand
+IQ.02: 'Al Başrah'
+IQ.16: Wāsiţ
+IQ.18: 'Şalāḩ ad Dīn'
+IQ.15: Nīnawá
+IQ.14: Maysan
+IQ.12: Karbalāʼ
+IQ.11: Arbīl
+IQ.10: 'Diyala Province'
+IQ.09: 'Dhi Qar'
+IQ.08: Dahūk
+IQ.07: 'Mayorality of Baghdad'
+IQ.06: Bābil
+IQ.13: 'At Taʼmīm'
+IQ.05: 'As Sulaymānīyah'
+IQ.17: 'An Najaf'
+IQ.04: 'Al Qādisīyah'
+IQ.03: 'Al Muthanná'
+IQ.01: Anbar
+IR.26: Tehrān
+IR.36: Zanjan
+IR.40: Yazd
+IR.25: Semnān
+IR.35: Māzandarān
+IR.34: Markazi
+IR.23: Lorestān
+IR.16: Kordestān
+IR.05: 'Kohgīlūyeh va Būyer Aḩmad'
+IR.15: Khūzestān
+IR.13: Kermānshāh
+IR.29: Kermān
+IR.10: Īlām
+IR.11: Hormozgān
+IR.09: Hamadān
+IR.08: Gīlān
+IR.07: Fārs
+IR.03: 'Chahār Maḩāll va Bakhtīārī'
+IR.22: Bushehr
+IR.33: 'East Azarbaijan'
+IR.01: 'Āz̄ārbāyjān-e Gharbī'
+IR.32: Ardabīl
+IR.28: 'Ostān-e Eşfahān'
+IR.37: Golestān
+IR.38: Qazvīn
+IR.39: Qom
+IR.04: 'Sīstān va Balūchestān'
+IR.41: 'Khorāsān-e Jonūbī'
+IR.42: 'Razavi Khorasan'
+IR.43: 'Khorāsān-e Shomālī'
+IR.44: Alborz
+IS.41: Northwest
+IS.40: Northeast
+IS.38: East
+IS.42: South
+IS.39: 'Capital Region'
+IS.43: 'Southern Peninsula'
+IS.45: West
+IS.44: Westfjords
+IT.15: Sicily
+IT.14: Sardinia
+IT.03: Calabria
+IT.20: Veneto
+IT.19: 'Aosta Valley'
+IT.18: Umbria
+IT.17: 'Trentino-Alto Adige'
+IT.16: Tuscany
+IT.13: Apulia
+IT.12: Piedmont
+IT.11: Molise
+IT.10: 'The Marches'
+IT.09: Lombardy
+IT.08: Liguria
+IT.07: Latium
+IT.06: 'Friuli Venezia Giulia'
+IT.05: Emilia-Romagna
+IT.04: Campania
+IT.02: Basilicate
+IT.01: Abruzzo
+JM.16: Westmoreland
+JM.15: Trelawny
+JM.14: 'Saint Thomas'
+JM.13: 'Saint Mary'
+JM.12: 'Saint James'
+JM.11: 'St. Elizabeth'
+JM.10: 'Saint Catherine'
+JM.09: 'Saint Ann'
+JM.08: 'Saint Andrew'
+JM.07: Portland
+JM.04: Manchester
+JM.17: Kingston
+JM.02: 'Hanover Parish'
+JM.01: Clarendon
+JO.19: Ma’an
+JO.18: Irbid
+JO.17: Zarqa
+JO.12: Tafielah
+JO.16: Amman
+JO.15: Mafraq
+JO.09: Karak
+JO.02: Balqa
+JO.20: Ajlun
+JO.22: Jerash
+JO.21: Aqaba
+JO.23: Madaba
+JP.46: Yamanashi
+JP.45: Yamaguchi
+JP.43: Wakayama
+JP.42: Toyama
+JP.41: Tottori
+JP.40: Tōkyō
+JP.39: Tokushima
+JP.38: Tochigi
+JP.37: Shizuoka
+JP.36: 'Shimane Prefecture'
+JP.35: Shiga
+JP.34: Saitama
+JP.33: Saga
+JP.32: Ōsaka
+JP.47: Okinawa
+JP.31: Okayama
+JP.30: Ōita
+JP.29: Niigata
+JP.28: Nara
+JP.27: Nagasaki
+JP.26: Nagano
+JP.25: Miyazaki
+JP.23: Mie
+JP.22: Kyōto
+JP.21: 'Kumamoto Prefecture'
+JP.20: Kōchi
+JP.19: Kanagawa
+JP.18: Kagoshima
+JP.17: Kagawa
+JP.15: Ishikawa
+JP.13: Hyōgo
+JP.11: Hiroshima
+JP.10: 'Gunma Prefecture'
+JP.09: Gifu
+JP.07: Fukuoka
+JP.06: Fukui
+JP.05: Ehime
+JP.01: Aichi
+JP.44: Yamagata
+JP.24: Miyagi
+JP.16: Iwate
+JP.14: Ibaraki
+JP.08: Fukushima
+JP.04: Chiba
+JP.02: Akita
+JP.12: Hokkaidō
+JP.03: 'Aomori Prefecture'
+KE.55: 'West Pokot'
+KE.54: Wajir
+KE.52: 'Uasin Gishu'
+KE.51: Turkana
+KE.50: 'Trans Nzoia'
+KE.49: 'Tharaka - Nithi'
+KE.48: 'Tana River'
+KE.46: Siaya
+KE.45: Samburu
+KE.05: 'Nairobi Area'
+KE.38: 'Murang''A'
+KE.37: Mombasa
+KE.35: Meru
+KE.34: Marsabit
+KE.33: Mandera
+KE.29: 'Laikipia District'
+KE.28: Kwale
+KE.27: Kitui
+KE.26: Kisumu
+KE.25: Kisii
+KE.24: Kirinyaga
+KE.23: Kilifi
+KE.22: Kiambu
+KE.21: Kericho
+KE.20: Kakamega
+KE.18: Isiolo
+KE.16: Garissa
+KE.15: Embu
+KE.13: Busia
+KE.12: Bungoma
+KE.10: Baringo
+KE.43: Nyandarua
+KE.53: Vihiga
+KE.30: Lamu
+KE.31: Machakos
+KE.32: Makueni
+KE.14: Elegeyo-Marakwet
+KE.47: 'Taita Taveta'
+KE.19: Kajiado
+KE.44: Nyeri
+KE.17: 'Homa Bay'
+KE.11: Bomet
+KE.36: Migori
+KE.39: Nakuru
+KE.41: Narok
+KE.42: Nyamira
+KE.40: Nandi
+KG.08: Osh
+KG.09: 'Batken Oblasty'
+KG.06: Talas
+KG.04: Naryn
+KG.07: Ysyk-Köl
+KG.01: Bishkek
+KG.03: Jalal-Abad
+KG.02: Chüy
+KH.12: Poŭthĭsăt
+KH.29: 'Battambang Province'
+KH.19: Takeo
+KH.18: 'Svay Rieng'
+KH.17: 'Stung Treng'
+KH.27: 'Ŏtâr Méanchey'
+KH.24: 'Siem Reap'
+KH.23: Ratanakiri
+KH.14: 'Prey Veng'
+KH.13: 'Preah Vihear'
+KH.22: 'Phnom Penh'
+KH.30: Pailin
+KH.10: Mondolkiri
+KH.09: Kratie
+KH.26: Kep
+KH.08: 'Kaôh Kŏng'
+KH.07: Kandal
+KH.21: Kampot
+KH.05: 'Kampong Thom'
+KH.04: 'Kampong Speu'
+KH.03: 'Kampong Chhnang'
+KH.02: 'Kampong Cham'
+KH.28: 'Preah Sihanouk'
+KH.25: 'Banteay Meanchey Province'
+KI.01: 'Gilbert Islands'
+KI.02: 'Line Islands'
+KI.03: 'Phoenix Islands'
+KM.03: Mohéli
+KM.02: 'Grande Comore'
+KM.01: Anjouan
+KN.15: 'Trinity Palmetto Point'
+KN.13: 'Saint Thomas Middle Island'
+KN.12: 'Saint Thomas Lowland'
+KN.11: 'Saint Peter Basseterre'
+KN.10: 'Saint Paul Charlestown'
+KN.09: 'Saint Paul Capesterre'
+KN.08: 'Saint Mary Cayon'
+KN.07: 'Saint John Figtree'
+KN.06: 'Saint John Capesterre'
+KN.05: 'Saint James Windwa'
+KN.04: 'Saint George Gingerland'
+KN.03: 'Saint George Basseterre'
+KN.02: 'Saint Anne Sandy Point'
+KN.01: 'Christ Church Nichola Town'
+KP.12: 'P''yŏngyang-si'
+KP.15: 'P''yŏngan-namdo'
+KP.11: 'P''yŏngan-bukto'
+KP.09: Gangwon
+KP.06: Hwanghae-namdo
+KP.07: Hwanghae-bukto
+KP.03: Hamgyŏng-namdo
+KP.13: Yanggang-do
+KP.17: Hamgyŏng-bukto
+KP.01: Chagang-do
+KP.18: 'Najin Sŏnbong-si'
+KR.21: Ulsan
+KR.19: Daejeon
+KR.15: Daegu
+KR.11: Seoul
+KR.10: Busan
+KR.14: 'North Gyeongsang'
+KR.13: 'Gyeonggi Province'
+KR.18: Gwangju
+KR.06: Gangwon
+KR.12: Incheon
+KR.17: 'South Chungcheong'
+KR.05: 'North Chungcheong'
+KR.16: 'South Jeolla'
+KR.03: 'North Jeolla'
+KR.01: Jeju
+KR.20: 'South Gyeongsang'
+KR.22: Sejong
+KW.08: Ḩawallī
+KW.02: 'Al Asimah Governorate'
+KW.05: 'Al Jahrāʼ'
+KW.07: 'Al Farwaniyah'
+KW.04: 'Al Aḩmadī'
+KW.09: 'Muḩāfaz̧at Mubārak al Kabīr'
+KZ.07: 'Batys Qazaqstan'
+KZ.09: Mangghystaū
+KZ.06: Atyraū
+KZ.04: Aqtöbe
+KZ.15: 'East Kazakhstan'
+KZ.03: Aqmola
+KZ.16: 'Soltüstik Qazaqstan'
+KZ.11: Pavlodar
+KZ.14: Qyzylorda
+KZ.13: Qostanay
+KZ.12: Qaraghandy
+KZ.17: Zhambyl
+KZ.10: 'Ongtüstik Qazaqstan'
+KZ.02: 'Almaty Qalasy'
+KZ.01: Almaty
+KZ.08: 'Bayqongyr Qalasy'
+KZ.05: 'Astana Qalasy'
+LA.14: Xiangkhoang
+LA.13: Xiagnabouli
+LA.27: 'Vientiane Province'
+LA.20: Savannahkhét
+LA.19: Salavan
+LA.18: Phôngsali
+LA.07: Oudômxai
+LA.17: Louangphabang
+LA.16: Loungnamtha
+LA.15: Khammouan
+LA.03: Houaphan
+LA.02: Champasak
+LA.01: Attapu
+LA.26: Xékong
+LA.22: Bokèo
+LA.23: Bolikhamxai
+LA.24: 'Vientiane Prefecture'
+LB.05: Mont-Liban
+LB.04: Beyrouth
+LB.09: Liban-Nord
+LB.06: Liban-Sud
+LB.08: Béqaa
+LB.07: Nabatîyé
+LB.10: Aakkâr
+LB.11: Baalbek-Hermel
+LC.10: Vieux-Fort
+LC.09: Soufrière
+LC.11: Praslin
+LC.08: Micoud
+LC.07: Laborie
+LC.06: Gros-Islet
+LC.05: Dennery
+LC.02: Dauphin
+LC.04: Choiseul
+LC.03: Castries
+LC.01: Anse-la-Raye
+LI.11: Vaduz
+LI.10: Triesenberg
+LI.09: Triesen
+LI.08: Schellenberg
+LI.07: Schaan
+LI.06: Ruggell
+LI.05: Planken
+LI.04: Mauren
+LI.03: Gamprin
+LI.02: Eschen
+LI.01: Balzers
+LK.36: Western
+LK.35: Uva
+LK.34: Southern
+LK.33: Sabaragamuwa
+LK.32: 'North Western'
+LK.30: 'North Central'
+LK.29: Central
+LK.38: 'Northern Province'
+LK.37: 'Eastern Province'
+LR.10: Sinoe
+LR.09: Nimba
+LR.14: Montserrado
+LR.13: Maryland
+LR.20: Lofa
+LR.19: 'Grand Gedeh'
+LR.12: 'Grand Cape Mount'
+LR.11: 'Grand Bassa'
+LR.01: Bong
+LR.15: Bomi
+LR.16: 'Grand Kru'
+LR.17: Margibi
+LR.18: 'River Cess'
+LR.21: Gbarpolu
+LR.22: 'River Gee'
+LS.19: Thaba-Tseka
+LS.18: Quthing
+LS.17: 'Qachaʼs Nek'
+LS.16: Mokhotlong
+LS.15: 'Mohaleʼs Hoek'
+LS.14: Maseru
+LS.13: Mafeteng
+LS.12: Leribe
+LS.11: Butha-Buthe
+LS.10: Berea
+LT.56: 'Alytaus Apskritis'
+LT.57: 'Kauno Apskritis'
+LT.58: 'Klaipėdos Apskritis'
+LT.59: 'Marijampolės Apskritis'
+LT.60: 'Panevėžio Apskritis'
+LT.61: 'Šiaulių Apskritis'
+LT.62: 'Tauragės Apskritis'
+LT.63: 'Telšių Apskritis'
+LT.64: 'Utenos Apskritis'
+LT.65: 'Vilniaus Apskritis'
+LU.03: Luxembourg
+LU.02: Grevenmacher
+LU.01: Diekirch
+LV.33: 'Ventspils Rajons'
+LV.32: Ventspils
+LV.31: 'Valmieras Rajons'
+LV.30: 'Valkas Rajons'
+LV.29: 'Tukuma Rajons'
+LV.28: 'Talsu Rajons'
+LV.27: 'Saldus Rajons'
+LV.25: Rīga
+LV.24: 'Rēzeknes Rajons'
+LV.23: Rēzekne
+LV.22: 'Preiļu Rajons'
+LV.21: 'Ogres Rajons'
+LV.20: 'Madonas Rajons'
+LV.19: 'Ludzas Rajons'
+LV.18: 'Limbažu Rajons'
+LV.16: Liepāja
+LV.15: 'Kuldīgas Rajons'
+LV.14: 'Krāslavas Rajons'
+LV.13: Jūrmala
+LV.12: 'Jelgavas Rajons'
+LV.11: Jelgava
+LV.10: 'Jēkabpils Rajons'
+LV.09: 'Gulbenes Rajons'
+LV.08: 'Dobeles Rajons'
+LV.07: 'Daugavpils municipality'
+LV.06: Daugavpils
+LV.05: 'Cēsu Rajons'
+LV.04: 'Bauskas Rajons'
+LV.03: 'Balvu Rajons'
+LV.02: 'Alūksnes Rajons'
+LV.01: 'Aizkraukles Rajons'
+LV.60: 'Dundagas Novads'
+LV.40: 'Alsungas Novads'
+LV.A5: 'Pāvilostas Novads'
+LV.99: 'Nīcas Novads'
+LV.B6: 'Rucavas Novads'
+LV.65: 'Grobiņas Novads'
+LV.61: 'Durbes Novads'
+LV.37: 'Aizputes Novads'
+LV.A8: 'Priekules Novads'
+LV.D7: 'Vaiņodes Novads'
+LV.C9: 'Skrundas Novads'
+LV.51: 'Brocēnu Novads'
+LV.B4: 'Rojas Novads'
+LV.77: 'Kandavas Novads'
+LV.44: 'Auces Novads'
+LV.73: 'Jaunpils Novads'
+LV.62: 'Engures Novads'
+LV.D5: 'Tērvetes Novads'
+LV.A3: 'Ozolnieku Novads'
+LV.B9: 'Rundāles Novads'
+LV.45: 'Babītes Novads'
+LV.95: 'Mārupes Novads'
+LV.A2: 'Olaines Novads'
+LV.67: 'Iecavas Novads'
+LV.80: 'Ķekavas Novads'
+LV.C3: 'Salaspils Novads'
+LV.46: 'Baldones Novads'
+LV.D2: 'Stopiņu Novads'
+LV.53: 'Carnikavas Novads'
+LV.34: 'Ādažu Novads'
+LV.64: 'Garkalnes Novads'
+LV.E4: 'Vecumnieku Novads'
+LV.79: 'Ķeguma Novads'
+LV.87: 'Lielvārdes Novads'
+LV.C8: 'Skrīveru Novads'
+LV.71: 'Jaunjelgavas Novads'
+LV.98: 'Neretas Novads'
+LV.E6: 'Viesītes Novads'
+LV.C2: 'Salas Novads'
+LV.74: Jēkabpils
+LV.38: 'Aknīstes Novads'
+LV.69: 'Ilūkstes Novads'
+LV.E2: 'Vārkavas Novads'
+LV.90: 'Līvānu Novads'
+LV.E1: 'Varakļānu Novads'
+LV.E8: 'Viļānu Novads'
+LV.B3: 'Riebiņu Novads'
+LV.35: 'Aglonas Novads'
+LV.56: 'Ciblas Novads'
+LV.E9: 'Zilupes Novads'
+LV.E7: 'Viļakas Novads'
+LV.47: 'Baltinavas Novads'
+LV.57: 'Dagdas Novads'
+LV.78: 'Kārsavas Novads'
+LV.B7: 'Rugāju Novads'
+LV.55: 'Cesvaines Novads'
+LV.91: 'Lubānas Novads'
+LV.85: 'Krustpils Novads'
+LV.A6: 'Pļaviņu Novads'
+LV.82: 'Kokneses Novads'
+LV.68: 'Ikšķiles Novads'
+LV.B5: 'Ropažu Novads'
+LV.70: 'Inčukalna Novads'
+LV.84: 'Krimuldas Novads'
+LV.C7: 'Siguldas Novads'
+LV.88: 'Līgatnes Novads'
+LV.94: 'Mālpils Novads'
+LV.C6: 'Sējas Novads'
+LV.C5: 'Saulkrastu Novads'
+LV.C1: 'Salacgrīvas Novads'
+LV.39: 'Alojas Novads'
+LV.97: 'Naukšēnu Novads'
+LV.B8: 'Rūjienas Novads'
+LV.96: 'Mazsalacas Novads'
+LV.52: 'Burtnieku Novads'
+LV.A4: 'Pārgaujas Novads'
+LV.81: 'Kocēnu Novads'
+LV.42: 'Amatas Novads'
+LV.A9: 'Priekuļu Novads'
+LV.B1: 'Raunas Novads'
+LV.D3: 'Strenču Novads'
+LV.50: 'Beverīnas Novads'
+LV.D1: 'Smiltenes Novads'
+LV.72: 'Jaunpiebalgas Novads'
+LV.63: 'Ērgļu Novads'
+LV.E3: 'Vecpiebalgas Novads'
+LV.43: 'Apes Novads'
+LV.F1: 'Mērsraga Novads'
+LY.70: Darnah
+LY.69: Banghāzī
+LY.66: 'Al Marj'
+LY.65: 'Al Kufrah'
+LY.63: 'Al Jabal al Akhḑar'
+LY.77: Ţarābulus
+LY.76: Surt
+LY.75: Sabhā
+LY.74: 'Sha‘bīyat Nālūt'
+LY.73: Murzuq
+LY.72: Mişrātah
+LY.71: 'Sha‘bīyat Ghāt'
+LY.68: 'Az Zāwiyah'
+LY.78: 'Ash Shāţiʼ'
+LY.64: 'Al Jufrah'
+LY.67: 'An Nuqāţ al Khams'
+LY.79: 'Sha‘bīyat al Buţnān'
+LY.80: 'Sha‘bīyat al Jabal al Gharbī'
+LY.81: 'Sha‘bīyat al Jafārah'
+LY.82: 'Al Marqab'
+LY.83: 'Sha‘bīyat al Wāḩāt'
+LY.84: 'Sha‘bīyat Wādī al Ḩayāt'
+MA.49: Rabat-Salé-Zemmour-Zaër
+MA.48: Meknès-Tafilalet
+MA.47: 'Marrakech-Tensift-Al Haouz'
+MA.46: Fès-Boulemane
+MA.45: 'Grand Casablanca'
+MA.50: Chaouia-Ouardigha
+MA.51: Doukkala-Abda
+MA.52: 'Gharb-Chrarda-Beni Hssen'
+MA.53: 'Guelmim-Es Smara'
+MA.54: 'Oriental Region'
+MA.55: Souss-Massa-Drâa
+MA.56: Tadla-Azilal
+MA.57: Tanger-Tétouan
+MA.58: 'Taza-Al Hoceima-Taounate'
+MA.59: 'Laâyoune-Boujdour-Sakia El Hamra'
+MA.EH: 'Oued ed Dahab-Lagouira'
+MC.00: ''
+MD.73: 'Raionul Edineţ'
+MD.92: 'Ungheni District'
+MD.91: 'Raionul Teleneşti'
+MD.90: 'Raionul Taraclia'
+MD.88: Ştefan-Vodă
+MD.89: 'Strășeni District'
+MD.87: 'Raionul Soroca'
+MD.84: 'Raionul Rîşcani'
+MD.83: 'Raionul Rezina'
+MD.82: 'Raionul Orhei'
+MD.81: 'Raionul Ocniţa'
+MD.59: 'Raionul Anenii Noi'
+MD.80: 'Raionul Nisporeni'
+MD.79: 'Raionul Leova'
+MD.85: 'Raionul Sîngerei'
+MD.69: 'Raionul Criuleni'
+MD.78: 'Raionul Ialoveni'
+MD.57: Chişinău
+MD.67: Căuşeni
+MD.65: 'Raionul Cantemir'
+MD.66: Călăraşi
+MD.64: 'Cahul District'
+MD.76: 'Raionul Glodeni'
+MD.75: 'Raionul Floreşti'
+MD.74: 'Raionul Făleşti'
+MD.72: Dubăsari
+MD.71: 'Drochia District'
+MD.70: 'Raionul Donduşeni'
+MD.68: 'Raionul Cimişlia'
+MD.63: 'Raionul Briceni'
+MD.61: 'Raionul Basarabeasca'
+MD.77: 'Raionul Hînceşti'
+MD.86: 'Raionul Şoldăneşti'
+MD.58: 'Stînga Nistrului'
+MD.51: Găgăuzia
+MD.62: Bender
+MD.60: Bălţi
+ME.17: 'Opština Rožaje'
+ME.21: 'Opština Žabljak'
+ME.20: Ulcinj
+ME.19: Tivat
+ME.16: Podgorica
+ME.18: 'Opština Šavnik'
+ME.15: 'Opština Plužine'
+ME.14: Pljevlja
+ME.13: 'Opština Plav'
+ME.12: 'Opština Nikšić'
+ME.11: Mojkovac
+ME.10: Kotor
+ME.09: 'Opština Kolašin'
+ME.03: Berane
+ME.08: 'Herceg Novi'
+ME.07: Danilovgrad
+ME.06: Cetinje
+ME.05: Budva
+ME.04: 'Bijelo Polje'
+ME.02: Bar
+ME.01: Andrijevica
+MG.7670842: Diana
+MG.7670846: Sava
+MG.7670847: Sofia
+MG.7670848: Analanjirofo
+MG.7670849: Boeny
+MG.7670850: Betsiboka
+MG.7670851: 'Alaotra Mangoro'
+MG.7670852: Melaky
+MG.7670853: Bongolava
+MG.7670854: Vakinankaratra
+MG.7670855: Itasy
+MG.7670856: Analamanga
+MG.7670857: Atsinanana
+MG.7670902: Menabe
+MG.7670904: 'Amoron''i Mania'
+MG.7670905: 'Upper Matsiatra'
+MG.7670906: 'Vatovavy Fitovinany'
+MG.7670907: Ihorombe
+MG.7670908: 'Atsimo-Atsinanana Region'
+MG.7670910: Anosy
+MG.7670911: Androy
+MG.7670913: Atsimo-Andrefana
+MH.007: 'Ailinginae Atoll'
+MH.010: 'Ailinglaplap Atoll'
+MH.030: 'Ailuk Atoll'
+MH.040: 'Arno Atoll'
+MH.050: 'Aur Atoll'
+MH.060: 'Bikar Atoll'
+MH.070: 'Bikini Atoll'
+MH.080: 'Ebon Atoll'
+MH.090: 'Enewetak Atoll'
+MH.100: 'Erikub Atoll'
+MH.120: 'Jaluit Atoll'
+MH.150: 'Kwajalein Atoll'
+MH.160: 'Lae Atoll'
+MH.180: 'Likiep Atoll'
+MH.190: 'Majuro Atoll'
+MH.300: 'Maloelap Atoll'
+MH.320: 'Mili Atoll'
+MH.330: 'Namdrik Atoll'
+MH.340: 'Namu Atoll'
+MH.350: 'Rongelap Atoll'
+MH.360: 'Rongrik Atoll'
+MH.385: 'Taka Atoll'
+MH.073: 'Bokak Atoll'
+MH.390: 'Ujae Atoll'
+MH.400: Ujelang
+MH.410: 'Utrik Atoll'
+MH.420: 'Wotho Atoll'
+MH.430: 'Wotje Atoll'
+MH.110: 'Jabat Island'
+MH.130: 'Jemo Island'
+MH.140: 'Kili Island'
+MH.170: 'Lib Island'
+MH.310: 'Mejit Island'
+MK.E9: Valandovo
+MK.86: Resen
+MK.51: Kratovo
+MK.78: Pehčevo
+MK.72: 'Novo Selo'
+MK.11: Bosilovo
+MK.A9: Vasilevo
+MK.E5: Dojran
+MK.08: Bogdanci
+MK.47: Konče
+MK.62: 'Makedonska Kamenica'
+MK.C6: Zrnovci
+MK.40: Karbinci
+MK.25: 'Demir Kapija'
+MK.87: Rosoman
+MK.35: Gradsko
+MK.60: Lozovo
+MK.19: Češinovo
+MK.E1: Novaci
+MK.04: Berovo
+MK.06: Bitola
+MK.D9: Mogila
+MK.01: Aračinovo
+MK.C7: Bogovinje
+MK.12: Brvenica
+MK.C8: Čair
+MK.C9: Čaška
+MK.D1: Centar
+MK.18: 'Centar Župa'
+MK.20: Čučer-Sandevo
+MK.D2: Debar
+MK.22: Delčevo
+MK.D3: 'Demir Hisar'
+MK.28: Dolneni
+MK.29: 'Opstina Gjorce Petrov'
+MK.30: Drugovo
+MK.32: 'Gazi Baba'
+MK.33: Gevgelija
+MK.D4: Gostivar
+MK.36: Ilinden
+MK.D5: Jegunovce
+MK.41: Karpoš
+MK.D6: Kavadarci
+MK.43: Kičevo
+MK.44: 'Kisela Voda'
+MK.46: Kočani
+MK.52: 'Kriva Palanka'
+MK.53: Krivogaštani
+MK.54: Kruševo
+MK.D7: Kumanovo
+MK.59: 'Opstina Lipkovo'
+MK.D8: 'Makedonski Brod'
+MK.69: Negotino
+MK.E2: Ohrid
+MK.77: Oslomej
+MK.79: Petrovec
+MK.80: Plasnica
+MK.E3: Prilep
+MK.83: Probištip
+MK.84: Radoviš
+MK.85: 'Opstina Rankovce'
+MK.E4: 'Opština Rostuša'
+MK.90: Saraj
+MK.92: Sopište
+MK.97: 'Staro Nagoričane'
+MK.98: Štip
+MK.E6: Struga
+MK.E7: Strumica
+MK.A2: Studeničani
+MK.A3: 'Šuto Orizari'
+MK.A4: 'Sveti Nikole'
+MK.A5: Tearce
+MK.E8: Tetovo
+MK.F1: Veles
+MK.B3: Vevčani
+MK.B4: Vinica
+MK.B6: Vraneštica
+MK.B7: Vrapčište
+MK.C1: Zajas
+MK.C2: Zelenikovo
+MK.C3: Želino
+MK.F3: Aerodrom
+MK.F4: Butel
+MK.F5: Debarca
+ML.08: 'Tombouctou Region'
+ML.06: 'Sikasso Region'
+ML.05: 'Ségou Region'
+ML.04: 'Mopti Region'
+ML.07: 'Koulikoro Region'
+ML.03: 'Kayes Region'
+ML.09: 'Gao Region'
+ML.01: Bamako
+ML.10: 'Kidal Region'
+MM.12: Tanintharyi
+MM.11: Shan
+MM.10: Sagain
+MM.17: Yangon
+MM.01: Rakhine
+MM.16: Bago
+MM.13: Mon
+MM.08: Mandalay
+MM.15: Magway
+MM.06: Kayah
+MM.05: Kayin
+MM.04: Kachin
+MM.03: Ayeyarwady
+MM.02: Chin
+MN.19: Uvs
+MN.12: Hovd
+MN.10: Govĭ-Altay
+MN.09: Dzabkhan
+MN.03: Bayan-Ölgiy
+MN.02: Bayanhongor
+MN.20: Ulaanbaatar
+MN.18: 'Central Aimak'
+MN.17: Sühbaatar
+MN.16: Selenge
+MN.15: Övörhangay
+MN.14: 'Ömnögovi Province'
+MN.13: Hövsgöl
+MN.11: Hentiy
+MN.08: 'Middle Govĭ'
+MN.07: 'East Gobi Aymag'
+MN.06: 'East Aimak'
+MN.21: Bulgan
+MN.01: Arhangay
+MN.23: 'Darhan Uul'
+MN.24: Govĭ-Sumber
+MN.25: Orhon
+MO.02: Macau
+MO.01: Ilhas
+MP.100: 'Rota Municipality'
+MP.110: 'Saipan Municipality'
+MP.120: 'Tinian Municipality'
+MP.085: 'Northern Islands Municipality'
+MQ.MQ: Martinique
+MR.06: Trarza
+MR.11: 'Tiris Zemmour'
+MR.09: Tagant
+MR.NKC: Nouakchott
+MR.12: Inchiri
+MR.02: 'Hodh el Gharbi'
+MR.01: 'Hodh ech Chargui'
+MR.10: Guidimaka
+MR.04: Gorgol
+MR.08: 'Dakhlet Nouadhibou'
+MR.05: Brakna
+MR.03: Assaba
+MR.07: Adrar
+MS.03: 'Saint Peter'
+MS.02: 'Saint Georges'
+MS.01: 'Saint Anthony'
+MT.01: Attard
+MT.02: Balzan
+MT.03: Il-Birgu
+MT.04: Birkirkara
+MT.05: Birżebbuġa
+MT.06: Bormla
+MT.07: Dingli
+MT.08: Il-Fgura
+MT.09: Il-Furjana
+MT.10: Il-Fontana
+MT.11: Għajnsielem
+MT.12: L-Għarb
+MT.13: 'Ħal Għargħur'
+MT.14: L-Għasri
+MT.15: 'Ħal Għaxaq'
+MT.16: Il-Gudja
+MT.17: Il-Gżira
+MT.18: Il-Ħamrun
+MT.19: L-Iklin
+MT.20: L-Imdina
+MT.21: L-Imġarr
+MT.22: L-Imqabba
+MT.23: L-Imsida
+MT.24: L-Imtarfa
+MT.25: L-Isla
+MT.26: Il-Kalkara
+MT.27: 'Ta’ Kerċem'
+MT.28: Kirkop
+MT.29: Lija
+MT.30: Luqa
+MT.31: Il-Marsa
+MT.32: Marsaskala
+MT.33: Marsaxlokk
+MT.34: Il-Mellieħa
+MT.35: Il-Mosta
+MT.36: Il-Munxar
+MT.37: In-Nadur
+MT.38: In-Naxxar
+MT.39: Paola
+MT.40: Pembroke
+MT.41: Tal-Pietà
+MT.42: Il-Qala
+MT.43: Qormi
+MT.44: Il-Qrendi
+MT.46: Ir-Rabat
+MT.47: Safi
+MT.48: 'Saint John'
+MT.49: 'Saint Julian'
+MT.50: 'Saint Lawrence'
+MT.51: 'Saint Lucia'
+MT.52: 'Saint Paul’s Bay'
+MT.53: 'Saint Venera'
+MT.54: Sannat
+MT.55: Is-Siġġiewi
+MT.56: Tas-Sliema
+MT.57: Is-Swieqi
+MT.58: Tarxien
+MT.59: 'Ta’ Xbiex'
+MT.61: Ix-Xagħra
+MT.62: Ix-Xewkija
+MT.63: Ix-Xgħajra
+MT.64: Ħaż-Żabbar
+MT.65: Ħaż-Żebbuġ
+MT.66: Iż-Żebbuġ
+MT.67: Iż-Żejtun
+MT.68: Iż-Żurrieq
+MT.60: 'Il-Belt Valletta'
+MU.21: 'Agalega Islands'
+MU.20: Savanne
+MU.19: 'Rivière du Rempart'
+MU.18: 'Port Louis'
+MU.17: 'Plaines Wilhems'
+MU.16: Pamplemousses
+MU.15: Moka
+MU.14: 'Grand Port'
+MU.13: Flacq
+MU.12: 'Black River'
+MU.22: 'Cargados Carajos'
+MU.23: Rodrigues
+MV.47: 'Vaavu Atholhu'
+MV.46: 'Thaa Atholhu'
+MV.45: 'Shaviyani Atholhu'
+MV.01: Seenu
+MV.44: 'Raa Atholhu'
+MV.43: 'Noonu Atoll'
+MV.42: 'Gnyaviyani Atoll'
+MV.41: 'Meemu Atholhu'
+MV.39: 'Lhaviyani Atholhu'
+MV.05: Laamu
+MV.38: 'Kaafu Atoll'
+MV.37: 'Haa Dhaalu Atholhu'
+MV.36: 'Haa Alifu Atholhu'
+MV.35: 'Gaafu Dhaalu Atholhu'
+MV.34: 'Gaafu Alifu Atholhu'
+MV.33: 'Faafu Atholhu'
+MV.32: 'Dhaalu Atholhu'
+MV.31: 'Baa Atholhu'
+MV.30: 'Northern Ari Atoll'
+MV.40: Maale
+MV.48: 'South Province'
+MV.49: 'Upper South Province'
+MV.50: 'Upper North Province'
+MV.51: 'Central Province'
+MV.52: 'South Central Province'
+MV.53: 'North Central Province'
+MV.54: 'North Province'
+MW.S: 'Southern Region'
+MW.N: 'Northern Region'
+MW.C: 'Central Region'
+MX.31: Yucatán
+MX.30: Veracruz-Llave
+MX.29: Tlaxcala
+MX.28: Tamaulipas
+MX.27: Tabasco
+MX.23: 'Quintana Roo'
+MX.22: Querétaro
+MX.21: Puebla
+MX.20: Oaxaca
+MX.19: 'Nuevo León'
+MX.17: Morelos
+MX.15: México
+MX.13: Hidalgo
+MX.12: Guerrero
+MX.09: 'The Federal District'
+MX.05: Chiapas
+MX.04: Campeche
+MX.32: Zacatecas
+MX.26: Sonora
+MX.25: Sinaloa
+MX.24: 'San Luis Potosí'
+MX.18: Nayarit
+MX.16: Michoacán
+MX.14: Jalisco
+MX.11: Guanajuato
+MX.10: Durango
+MX.08: Colima
+MX.07: Coahuila
+MX.06: Chihuahua
+MX.03: 'Baja California Sur'
+MX.02: 'Baja California'
+MX.01: Aguascalientes
+MY.04: Melaka
+MY.13: Terengganu
+MY.12: Selangor
+MY.11: Sarawak
+MY.16: Sabah
+MY.08: Perlis
+MY.07: Perak
+MY.06: Pahang
+MY.05: 'Negeri Sembilan'
+MY.03: Kelantan
+MY.14: 'Kuala Lumpur'
+MY.09: 'Pulau Pinang'
+MY.02: Kedah
+MY.01: Johor
+MY.15: Labuan
+MY.17: Putrajaya
+MZ.09: Zambézia
+MZ.08: 'Province of Tete'
+MZ.05: Sofala
+MZ.07: Niassa
+MZ.06: Nampula
+MZ.04: Maputo
+MZ.10: Manica
+MZ.03: Inhambane
+MZ.02: Gaza
+MZ.01: 'Cabo Delgado'
+MZ.11: 'Maputo City'
+NA.28: Caprivi
+NA.21: Khomas
+NA.29: Erongo
+NA.30: Hardap
+NA.31: Karas
+NA.32: Kunene
+NA.33: Ohangwena
+NA.34: Okavango
+NA.35: Omaheke
+NA.36: Omusati
+NA.37: Oshana
+NA.38: Oshikoto
+NA.39: Otjozondjupa
+NC.02: 'Province Sud'
+NC.01: 'Province Nord'
+NC.03: 'Province des îles Loyauté'
+NE.07: Zinder
+NE.06: Tahoua
+NE.04: Maradi
+NE.03: Dosso
+NE.02: Diffa
+NE.01: 'Agadez Region'
+NE.09: Tillabéri
+NE.08: Niamey
+NG.51: Sokoto
+NG.50: Rivers
+NG.49: Plateau
+NG.32: Oyo
+NG.48: Ondo
+NG.16: Ogun
+NG.31: Niger
+NG.05: Lagos
+NG.30: Kwara
+NG.24: Katsina
+NG.29: Kano
+NG.23: Kaduna
+NG.28: 'Imo State'
+NG.22: 'Cross River'
+NG.27: Borno
+NG.26: 'Benue State'
+NG.46: 'Bauchi State'
+NG.25: 'Anambra State'
+NG.21: 'Akwa Ibom'
+NG.11: 'Abuja Federal Capital Territory'
+NG.45: Abia
+NG.36: 'Delta State'
+NG.35: 'Adamawa State'
+NG.37: Edo
+NG.47: 'Enugu State'
+NG.39: 'Jigawa State'
+NG.52: Bayelsa
+NG.53: Ebonyi
+NG.54: Ekiti
+NG.55: Gombe
+NG.56: Nassarawa
+NG.57: Zamfara
+NG.40: Kebbi
+NG.41: Kogi
+NG.42: Osun
+NG.43: 'Taraba State'
+NG.44: Yobe
+NI.15: Rivas
+NI.14: 'Río San Juan'
+NI.13: 'Nueva Segovia'
+NI.12: Matagalpa
+NI.11: Masaya
+NI.10: Managua
+NI.09: Madriz
+NI.08: León
+NI.07: Jinotega
+NI.06: Granada
+NI.05: Estelí
+NI.04: Chontales
+NI.03: Chinandega
+NI.02: Carazo
+NI.01: Boaco
+NI.17: 'Atlántico Norte'
+NI.18: 'Atlántico Sur'
+NL.11: 'South Holland'
+NL.10: Zeeland
+NL.09: Utrecht
+NL.15: Overijssel
+NL.07: 'North Holland'
+NL.06: 'North Brabant'
+NL.05: Limburg
+NL.04: Groningen
+NL.03: Gelderland
+NL.02: Friesland
+NL.01: Drenthe
+NL.16: Flevoland
+NO.05: Finnmark
+NO.20: 'Vestfold county'
+NO.19: Vest-Agder
+NO.18: Troms
+NO.17: 'Telemark county'
+NO.16: Sør-Trøndelag
+NO.15: 'Sogn og Fjordane'
+NO.14: Rogaland
+NO.13: Østfold
+NO.12: 'Oslo County'
+NO.11: 'Oppland county'
+NO.10: Nord-Trøndelag
+NO.09: Nordland
+NO.08: 'Møre og Romsdal'
+NO.07: Hordaland
+NO.06: 'Hedmark county'
+NO.04: 'Buskerud county'
+NO.02: 'Aust-Agder county'
+NO.01: 'Akershus county'
+NP.FR: 'Far Western Region'
+NP.MR: 'Mid Western Region'
+NP.CR: 'Central Region'
+NP.ER: 'Eastern Region'
+NP.WR: 'Western Region'
+NR.14: Yaren
+NR.13: Uaboe
+NR.12: Nibok
+NR.11: Meneng
+NR.10: Ijuw
+NR.09: Ewa
+NR.08: Denigomodu
+NR.07: Buada
+NR.06: Boe
+NR.05: Baiti
+NR.04: Anibare
+NR.03: Anetan
+NR.02: Anabar
+NR.01: Aiwo
+NZ.G2: Wellington
+NZ.F3: Manawatu-Wanganui
+NZ.G1: Waikato
+NZ.TAS: Tasman
+NZ.F9: Taranaki
+NZ.F8: 'Southland Region'
+NZ.E8: 'Bay of Plenty'
+NZ.F6: Northland
+NZ.F4: Marlborough
+NZ.F2: 'Hawke''s Bay'
+NZ.F1: 'Gisborne Region'
+NZ.E9: 'Canterbury Region'
+NZ.E7: Auckland
+NZ.10: 'Chatham Islands'
+NZ.F5: Nelson
+NZ.F7: 'Otago Region'
+NZ.G3: 'West Coast'
+OM.01: 'Ad Dākhilīyah'
+OM.02: 'Al Bāţinah'
+OM.03: 'Al Wusţá'
+OM.04: 'Ash Sharqīyah'
+OM.09: 'Az̧ Z̧āhirah'
+OM.06: Masqaţ
+OM.07: Musandam
+OM.08: Z̧ufār
+OM.10: 'Muḩāfaz̧at al Buraymī'
+OM.12: 'Muḩāfaz̧at Shamāl ash Sharqīyah'
+OM.11: 'Muḩāfaz̧at Shamāl al Bāţinah'
+PA.10: Veraguas
+PA.09: 'Kuna Yala'
+PA.08: Panamá
+PA.07: 'Los Santos'
+PA.06: Herrera
+PA.05: Darién
+PA.04: Colón
+PA.03: Coclé
+PA.02: Chiriquí
+PA.01: 'Bocas del Toro'
+PA.11: Emberá
+PA.12: Ngöbe-Buglé
+PE.25: 'Ucayali Region'
+PE.24: Tumbes
+PE.22: 'San Martín'
+PE.20: 'Piura Region'
+PE.16: 'Loreto Region'
+PE.14: 'Lambayeque Region'
+PE.13: 'La Libertad Region'
+PE.10: Huanuco
+PE.06: Cajamarca
+PE.02: 'Ancash Region'
+PE.01: 'Amazonas Region'
+PE.23: 'Tacna Region'
+PE.21: 'Puno Region'
+PE.19: Pasco
+PE.18: Moquegua
+PE.17: 'Madre de Dios'
+PE.LMA: 'Provincia de Lima'
+PE.15: 'Lima Region'
+PE.12: Junín
+PE.11: 'Ica Region'
+PE.09: 'Huancavelica Region'
+PE.08: Cusco
+PE.07: Callao
+PE.05: 'Ayacucho Region'
+PE.04: 'Arequipa Region'
+PE.03: Apurímac
+PF.04: 'Îles Marquises'
+PF.03: 'Îles Tuamotu-Gambier'
+PF.02: 'Îles Sous-le-Vent'
+PF.01: 'Îles du Vent'
+PF.05: 'Îles Australes'
+PG.17: 'West New Britain'
+PG.06: 'Western Province'
+PG.16: 'Western Highlands'
+PG.05: 'Southern Highlands'
+PG.18: Sandaun
+PG.07: Bougainville
+PG.04: 'Northern Province'
+PG.15: 'New Ireland'
+PG.20: 'National Capital District'
+PG.14: Morobe
+PG.13: Manus
+PG.12: Madang
+PG.02: Gulf
+PG.19: Enga
+PG.11: 'East Sepik'
+PG.10: 'East New Britain'
+PG.09: 'Eastern Highlands'
+PG.08: Chimbu
+PG.03: 'Milne Bay'
+PG.01: 'Central Province'
+PG.21: Hela
+PG.22: Jiwaka
+PH.14: 'Autonomous Region in Muslim Mindanao'
+PH.10: 'Northern Mindanao'
+PH.41: Mimaropa
+PH.02: 'Cagayan Valley'
+PH.12: Soccsksargen
+PH.13: Caraga
+PH.15: 'Cordillera Administrative Region'
+PH.01: 'Ilocos Region'
+PH.40: Calabarzon
+PH.06: 'Western Visayas'
+PH.03: 'Central Luzon'
+PH.07: 'Central Visayas'
+PH.08: 'Eastern Visayas'
+PH.09: 'Zamboanga Peninsula'
+PH.11: Davao
+PH.05: Bicol
+PH.NCR: 'National Capital Region'
+PK.08: Islāmābād
+PK.05: Sindh
+PK.04: Punjab
+PK.03: 'North-West Frontier Province'
+PK.07: Gilgit-Baltistan
+PK.01: 'Federally Administered Tribal Areas'
+PK.02: Balochistān
+PK.06: 'Azad Kashmir'
+PL.75: 'Lublin Voivodeship'
+PL.77: 'Lesser Poland Voivodeship'
+PL.78: 'Masovian Voivodeship'
+PL.80: 'Subcarpathian Voivodeship'
+PL.81: Podlasie
+PL.84: Świętokrzyskie
+PL.85: 'Warmian-Masurian Voivodeship'
+PL.72: 'Lower Silesian Voivodeship'
+PL.74: 'Łódź Voivodeship'
+PL.76: Lubusz
+PL.79: 'Opole Voivodeship'
+PL.82: 'Pomeranian Voivodeship'
+PL.83: 'Silesian Voivodeship'
+PL.86: 'Greater Poland Voivodeship'
+PL.87: 'West Pomeranian Voivodeship'
+PL.73: Kujawsko-Pomorskie
+PM.97502: Saint-Pierre
+PM.97501: Miquelon-Langlade
+PR.001: Adjuntas
+PR.003: Aguada
+PR.005: Aguadilla
+PR.007: 'Aguas Buenas'
+PR.009: Aibonito
+PR.011: Añasco
+PR.013: Arecibo
+PR.015: Arroyo
+PR.017: Barceloneta
+PR.019: Barranquitas
+PR.021: Bayamón
+PR.023: 'Cabo Rojo'
+PR.025: Caguas
+PR.027: Camuy
+PR.029: Canovanas
+PR.031: Carolina
+PR.033: Catano
+PR.035: Cayey
+PR.037: Ceiba
+PR.039: Ciales
+PR.041: Cidra
+PR.043: Coamo
+PR.045: Comerio
+PR.047: Corozal
+PR.049: Culebra
+PR.051: Dorado
+PR.053: Fajardo
+PR.054: Florida
+PR.055: Guanica
+PR.057: Guayama
+PR.059: Guayanilla
+PR.061: Guaynabo
+PR.063: Gurabo
+PR.065: Hatillo
+PR.067: Hormigueros
+PR.069: Humacao
+PR.071: Isabela
+PR.073: 'Municipio de Jayuya'
+PR.075: 'Juana Diaz'
+PR.077: 'Municipio de Juncos'
+PR.079: Lajas
+PR.081: Lares
+PR.083: 'Las Marias'
+PR.085: 'Las Piedras'
+PR.087: Loiza
+PR.089: Luquillo
+PR.091: Manati
+PR.093: Maricao
+PR.095: Maunabo
+PR.097: Mayaguez
+PR.099: Moca
+PR.101: Morovis
+PR.103: Naguabo
+PR.105: Naranjito
+PR.107: Orocovis
+PR.109: Patillas
+PR.111: Penuelas
+PR.113: Ponce
+PR.117: Rincon
+PR.115: Quebradillas
+PR.119: 'Rio Grande'
+PR.121: 'Sabana Grande'
+PR.123: Salinas
+PR.125: 'San German'
+PR.127: 'San Juan'
+PR.129: 'San Lorenzo'
+PR.131: 'San Sebastian'
+PR.133: 'Santa Isabel Municipio'
+PR.135: 'Toa Alta'
+PR.137: 'Toa Baja'
+PR.139: 'Trujillo Alto'
+PR.141: Utuado
+PR.143: 'Vega Alta'
+PR.145: 'Vega Baja'
+PR.149: Villalba
+PR.151: Yabucoa
+PR.153: Yauco
+PR.147: Vieques
+PS.GZ: 'Gaza Strip'
+PS.WE: 'West Bank'
+PT.19: Setúbal
+PT.18: Santarém
+PT.16: Portalegre
+PT.14: Lisbon
+PT.13: Leiria
+PT.09: Faro
+PT.08: Évora
+PT.06: 'Castelo Branco'
+PT.03: Beja
+PT.10: Madeira
+PT.22: Viseu
+PT.21: 'Vila Real'
+PT.20: 'Viana do Castelo'
+PT.17: Porto
+PT.11: Guarda
+PT.07: Coimbra
+PT.05: Bragança
+PT.04: Braga
+PT.02: Aveiro
+PT.23: Azores
+PW.11: Ngatpang
+PW.16: Sonsorol
+PW.05: Kayangel
+PW.04: 'State of Hatohobei'
+PW.01: Aimeliik
+PW.02: Airai
+PW.03: Angaur
+PW.06: Koror
+PW.07: Melekeok
+PW.08: Ngaraard
+PW.12: Ngchesar
+PW.09: Ngarchelong
+PW.10: Ngardmau
+PW.13: 'State of Ngeremlengui'
+PW.14: Ngiwal
+PW.15: Peleliu
+PY.17: 'San Pedro'
+PY.16: 'Presidente Hayes'
+PY.15: Paraguarí
+PY.13: Ñeembucú
+PY.12: Misiones
+PY.11: Itapúa
+PY.10: Guairá
+PY.08: Cordillera
+PY.07: Concepción
+PY.06: Central
+PY.19: Canindeyú
+PY.05: Caazapá
+PY.04: Caaguazú
+PY.02: Amambay
+PY.01: 'Alto Paraná'
+PY.23: 'Alto Paraguay'
+PY.22: Asunción
+PY.24: Boquerón
+QA.08: 'Madīnat ash Shamāl'
+QA.02: 'Al Ghuwayrīyah'
+QA.04: 'Al Khawr'
+QA.09: 'Umm Şalāl'
+QA.03: 'Al Jumaylīyah'
+QA.06: 'Ar Rayyān'
+QA.01: 'Ad Dawḩah'
+QA.10: 'Al Wakrah'
+QA.11: 'Jarayān al Bāţinah'
+QA.12: 'Baladīyat Umm Sa‘īd'
+QA.13: 'Baladīyat az̧ Z̧a‘āyin'
+RE.RE: Réunion
+RO.40: Vrancea
+RO.39: Vâlcea
+RO.38: Vaslui
+RO.37: Tulcea
+RO.36: Timiş
+RO.35: Teleorman
+RO.34: Suceava
+RO.33: Sibiu
+RO.32: 'Satu Mare'
+RO.31: Sălaj
+RO.30: 'Prahova County'
+RO.29: Olt
+RO.28: Neamţ
+RO.27: Mureş
+RO.26: Mehedinţi
+RO.25: Maramureş
+RO.23: Iaşi
+RO.22: Ialomiţa
+RO.21: Hunedoara
+RO.20: Harghita
+RO.19: Gorj
+RO.42: Giurgiu
+RO.18: Galaţi
+RO.17: Dolj
+RO.16: Dâmboviţa
+RO.15: Covasna
+RO.14: Constanţa
+RO.13: Cluj
+RO.12: Caraş-Severin
+RO.41: Călăraşi
+RO.11: Buzău
+RO.10: Bucureşti
+RO.09: Braşov
+RO.08: Brăila
+RO.07: Botoşani
+RO.06: Bistriţa-Năsăud
+RO.05: Bihor
+RO.04: Bacău
+RO.03: Argeş
+RO.02: Arad
+RO.01: Alba
+RO.43: 'Ilfov County'
+RS.VO: 'Autonomna Pokrajina Vojvodina'
+RS.SE: 'Central Serbia'
+RU.88: Jaroslavl
+RU.86: Voronezj
+RU.85: Vologda
+RU.84: Volgograd
+RU.81: Uljanovsk
+RU.80: Udmurtiya
+RU.77: Tverskaya
+RU.76: Tula
+RU.73: Tatarstan
+RU.72: Tambov
+RU.70: 'Stavropol''skiy'
+RU.69: Smolensk
+RU.67: Saratov
+RU.65: Samara
+RU.62: Rjazan
+RU.61: Rostov
+RU.60: Pskov
+RU.90: Perm
+RU.57: Penza
+RU.56: Orjol
+RU.55: Orenburg
+RU.52: Novgorod
+RU.68: 'North Ossetia'
+RU.50: 'Nenetskiy Avtonomnyy Okrug'
+RU.49: Murmansk
+RU.48: Moscow
+RU.47: Moskovskaya
+RU.46: Mordoviya
+RU.45: Mariy-El
+RU.43: Lipetsk
+RU.42: Leningrad
+RU.66: St.-Petersburg
+RU.41: Kursk
+RU.38: Krasnodarskiy
+RU.37: Kostroma
+RU.34: 'Komi Republic'
+RU.33: Kirov
+RU.28: Kareliya
+RU.27: Karachayevo-Cherkesiya
+RU.25: Kaluga
+RU.24: Kalmykiya
+RU.23: Kaliningrad
+RU.22: Kabardino-Balkariya
+RU.21: Ivanovo
+RU.19: Ingushetiya
+RU.51: 'Nizjnij Novgorod'
+RU.17: Dagestan
+RU.16: Chuvashia
+RU.12: Chechnya
+RU.10: Brjansk
+RU.09: Belgorod
+RU.08: Bashkortostan
+RU.07: Astrakhan
+RU.06: Arkhangelskaya
+RU.01: Adygeya
+RU.83: Vladimir
+RU.87: 'Yamalo-Nenetskiy Avtonomnyy Okrug'
+RU.78: Tjumen
+RU.79: Tyva
+RU.75: Tomsk
+RU.71: Sverdlovsk
+RU.54: Omsk
+RU.53: Novosibirsk
+RU.40: Kurgan
+RU.91: Krasnoyarskiy
+RU.32: 'Khanty-Mansiyskiy Avtonomnyy Okrug'
+RU.31: Khakasiya
+RU.29: Kemerovo
+RU.03: Altay
+RU.13: 'Chelyabinsk Oblast'
+RU.04: Altayskiy
+RU.63: Sakha
+RU.59: Primorskiy
+RU.30: 'Khabarovsk Krai'
+RU.20: Irkutsk
+RU.89: 'Jewish Autonomous Oblast'
+RU.05: Amur
+RU.11: Buryatiya
+RU.64: Sakhalin
+RU.44: Magadan
+RU.92: Kamtsjatka
+RU.15: 'Chukotskiy Avtonomnyy Okrug'
+RU.93: 'Zabaykal’skiy Kray'
+RW.11: 'Eastern Province'
+RW.12: 'Kigali Province'
+RW.13: 'Northern Province'
+RW.14: 'Western Province'
+RW.15: 'Southern Province'
+SA.19: Tabūk
+SA.16: Najrān
+SA.14: Makkah
+SA.17: Jīzān
+SA.13: Ḩāʼil
+SA.11: 'Minţaqat ‘Asīr'
+SA.06: 'Eastern Province'
+SA.10: 'Ar Riyāḑ'
+SA.08: 'Al-Qassim Province'
+SA.05: 'Al Madīnah'
+SA.20: 'Al Jawf'
+SA.15: 'Northern Borders Region'
+SA.02: 'Al Bāḩah'
+SB.11: 'Western Province'
+SB.03: Malaita
+SB.07: Isabel
+SB.06: Guadalcanal
+SB.10: 'Central Province'
+SB.09: Temotu
+SB.08: Makira
+SB.12: Choiseul
+SB.13: 'Rennell and Bellona'
+SC.23: Takamaka
+SC.22: 'Saint Louis'
+SC.27: 'Port Glaud'
+SC.20: 'Pointe Larue'
+SC.19: Plaisance
+SC.18: 'Mont Fleuri'
+SC.17: 'Mont Buxton'
+SC.26: 'English River'
+SC.25: 'Inner Islands'
+SC.24: 'Grand Anse Mahe'
+SC.14: 'Grand Anse Praslin'
+SC.12: Glacis
+SC.11: Cascade
+SC.10: 'Bel Ombre'
+SC.09: 'Bel Air'
+SC.08: 'Beau Vallon'
+SC.07: 'Baie Sainte Anne'
+SC.06: 'Baie Lazare'
+SC.05: 'Anse Royale'
+SC.03: 'Anse Etoile'
+SC.02: 'Anse Boileau'
+SC.01: 'Anse aux Pins'
+SC.29: 'Les Mamelles'
+SC.30: 'Roche Caiman'
+SC.28: 'Au Cap'
+SD.43: 'Northern State'
+SD.29: 'Khartoum State'
+SD.36: 'Red Sea'
+SD.38: 'Al Jazirah State'
+SD.39: 'Al Qadarif State'
+SD.41: 'White Nile State'
+SD.42: 'Blue Nile'
+SD.47: 'Western Darfur State'
+SD.49: 'Southern Darfur State'
+SD.50: 'Southern Kordofan State'
+SD.52: 'Kassala State'
+SD.53: 'River Nile'
+SD.55: 'Northern Darfur State'
+SD.56: 'Northern Kordofan State'
+SD.58: 'Sinnar State'
+SD.60: 'Eastern Darfur State'
+SD.61: 'Central Darfur State'
+SE.14: Norrbotten
+SE.25: Västmanland
+SE.24: Västernorrland
+SE.23: Västerbotten
+SE.22: Värmland
+SE.21: Uppsala
+SE.26: Stockholm
+SE.18: Södermanland
+SE.16: Östergötland
+SE.15: Örebro
+SE.12: Kronoberg
+SE.10: Dalarna
+SE.09: Kalmar
+SE.08: Jönköping
+SE.07: Jämtland
+SE.06: Halland
+SE.05: Gotland
+SE.03: Gävleborg
+SE.02: Blekinge
+SE.27: Skåne
+SE.28: 'Västra Götaland'
+SG.01: 'Central Singapore'
+SG.02: 'North East'
+SG.04: 'South East'
+SG.05: 'South West'
+SG.03: 'North West'
+SH.01: Ascension
+SH.03: 'Tristan da Cunha'
+SH.02: 'Saint Helena'
+SI.N5: Žalec
+SI.E7: 'Zagorje ob Savi'
+SI.E5: Vrhnika
+SI.D5: Tržič
+SI.D4: Trebnje
+SI.D3: Trbovlje
+SI.D2: Tolmin
+SI.D7: Velenje
+SI.C5: 'Šmarje pri Jelšah'
+SI.C4: 'Slovenska Konjice'
+SI.L8: 'Slovenska Bistrica'
+SI.C2: 'Slovenj Gradec'
+SI.B9: 'Škofja Loka'
+SI.B7: Sežana
+SI.B6: Sevnica
+SI.L7: 'Šentjur pri Celju'
+SI.L1: Ribnica
+SI.A3: Radovljica
+SI.A2: 'Radlje ob Dravi'
+SI.K7: Ptuj
+SI.94: Postojna
+SI.J9: Piran-Pirano
+SI.87: Ormož
+SI.J7: 'Novo Mesto'
+SI.84: 'Nova Gorica'
+SI.80: 'Murska Sobota'
+SI.79: Mozirje
+SI.73: Metlika
+SI.J2: Maribor
+SI.64: Logatec
+SI.I6: Ljutomer
+SI.I5: Litija
+SI.I3: Lenart
+SI.57: Laško
+SI.54: Krško
+SI.52: Kranj
+SI.50: Koper-Capodistria
+SI.H7: Kočevje
+SI.H6: Kamnik
+SI.H4: Jesenice
+SI.40: Izola-Isola
+SI.38: 'Ilirska Bistrica'
+SI.36: Idrija
+SI.34: Hrastnik
+SI.32: Grosuplje
+SI.29: 'Gornja Radgona'
+SI.25: Dravograd
+SI.G7: Domžale
+SI.17: Črnomelj
+SI.13: Cerknica
+SI.11: Celje
+SI.08: Brežice
+SI.01: Ajdovščina
+SI.35: Hrpelje-Kozina
+SI.19: Divača
+SI.91: Pivka
+SI.I7: 'Loška Dolina'
+SI.66: 'Loški Potok'
+SI.88: Osilnica
+SI.D8: 'Velike Lašče'
+SI.C1: Škofljica
+SI.37: Ig
+SI.09: Brezovica
+SI.05: Borovnica
+SI.E1: Vipava
+SI.49: Komen
+SI.J5: Miren-Kostanjevica
+SI.07: Brda
+SI.44: Kanal
+SI.F2: Žiri
+SI.14: Cerkno
+SI.F1: Železniki
+SI.27: 'Gorenja Vas-Poljane'
+SI.G4: 'Dobrova-Horjul-Polhov Gradec'
+SI.46: Kobarid
+SI.06: Bovec
+SI.04: Bohinj
+SI.03: Bled
+SI.82: Naklo
+SI.53: 'Kranjska Gora'
+SI.K5: Preddvor
+SI.12: 'Cerklje na Gorenjskem'
+SI.B2: Šenčur
+SI.E3: Vodice
+SI.71: Medvode
+SI.72: Mengeš
+SI.22: 'Dol pri Ljubljani'
+SI.77: Moravče
+SI.30: 'Gornji Grad'
+SI.I9: Luče
+SI.K8: 'Ravne na Koroškem'
+SI.74: Mežica
+SI.81: Muta
+SI.E6: Vuzenica
+SI.16: 'Črna na Koroškem'
+SI.62: Ljubno
+SI.C7: Šoštanj
+SI.C6: 'Šmartno ob Paki'
+SI.68: Lukovica
+SI.99: Radeče
+SI.39: 'Ivančna Gorica'
+SI.20: Dobrepolje
+SI.B1: Semič
+SI.B4: Šentjernej
+SI.B8: Škocjan
+SI.C9: Štore
+SI.N3: Vojnik
+SI.E2: Vitanje
+SI.F3: Zreče
+SI.76: Mislinja
+SI.L3: Ruše
+SI.55: Kungota
+SI.B3: Šentilj
+SI.89: Pesnica
+SI.26: Duplek
+SI.98: Rače-Fram
+SI.C8: Starše
+SI.45: Kidričevo
+SI.J1: Majšperk
+SI.N2: Videm
+SI.A7: 'Rogaška Slatina'
+SI.A8: Rogatec
+SI.92: Podčetrtek
+SI.51: Kozje
+SI.28: Gorišnica
+SI.E9: Zavrč
+SI.24: Dornava
+SI.42: Juršinci
+SI.D1: 'Sveti Jurij'
+SI.A1: Radenci
+SI.97: Puconci
+SI.A6: Rogašovci
+SI.I2: Kuzma
+SI.31: 'Gornji Petrovci'
+SI.78: 'Moravske Toplice'
+SI.47: Kobilje
+SI.02: Beltinci
+SI.D6: Turnišče
+SI.86: Odranci
+SI.15: Črenšovci
+SI.83: Nazarje
+SI.61: Ljubljana
+SI.N7: Žirovnica
+SI.H5: Jezersko
+SI.M2: Solčava
+SI.H8: Komenda
+SI.H3: Horjul
+SI.L6: Šempeter-Vrtojba
+SI.F6: Bloke
+SI.M1: Sodražica
+SI.M8: Trzin
+SI.K6: Prevalje
+SI.N4: Vransko
+SI.M5: Tabor
+SI.F7: Braslovče
+SI.K3: Polzela
+SI.K4: Prebold
+SI.H9: Kostel
+SI.N8: Žužemberk
+SI.G6: 'Dolenjske Toplice'
+SI.J6: 'Mirna Peč'
+SI.F5: 'Bistrica ob Sotli'
+SI.G2: Dobje
+SI.G3: Dobrna
+SI.J8: Oplotnica
+SI.K2: Podvelka
+SI.L2: 'Ribnica na Pohorju'
+SI.I8: 'Lovrenc na Pohorju'
+SI.L5: 'Selnica ob Dravi'
+SI.H1: Hoče-Slivnica
+SI.J4: 'Miklavž na Dravskem Polju'
+SI.G9: Hajdina
+SI.N6: Žetale
+SI.K1: Podlehnik
+SI.J3: Markovci
+SI.G1: Destrnik
+SI.M7: 'Trnovska Vas'
+SI.M4: 'Sveti Andraž v Slovenskih Goricah'
+SI.F9: Cerkvenjak
+SI.F4: Benedikt
+SI.M3: 'Sveta Ana'
+SI.I1: Križevci
+SI.N1: Veržej
+SI.M9: 'Velika Polana'
+SI.I4: Lendava-Lendva
+SI.G5: Dobrovnik-Dobronak
+SI.M6: Tišina
+SI.F8: Cankova
+SI.G8: Grad
+SI.H2: Hodoš-Hodos
+SI.K9: Razkrižje
+SI.L9: 'Šmartno pri Litiji'
+SI.L4: Šalovci
+SI.N9: 'Občina Apače'
+SI.O1: Cirkulane
+SI.O3: 'Kostanjevica na Krki'
+SI.O4: Log-Dragomer
+SI.O5: Makole
+SI.O7: Mokronog-Trebelno
+SI.O8: 'Občina Poljčane'
+SI.O9: 'Občina Rečica ob Savinji'
+SI.P1: 'Občina Renče-Vogrsko'
+SI.P4: 'Občina Središče ob Dravi'
+SI.P5: 'Občina Straža'
+SI.P6: 'Sveta Trojica v Slovenskih Goricah'
+SI.P8: 'Občina Sveti Tomaž'
+SI.P2: 'Občina Šentrupert'
+SI.P3: 'Občina Šmarješke Toplice'
+SI.P7: 'Sveti Jurij v Slovenskih Goricah'
+SJ.22: 'Jan Mayen'
+SJ.21: Svalbard
+SK.03: Košický
+SK.05: Prešovský
+SK.08: Žilinský
+SK.01: Banskobystrický
+SK.02: Bratislavský
+SK.04: Nitriansky
+SK.06: Trenčiansky
+SK.07: Trnavský
+SL.04: 'Western Area'
+SL.03: 'Southern Province'
+SL.02: 'Northern Province'
+SL.01: 'Eastern Province'
+SM.09: Serravalle
+SM.02: Chiesanuova
+SM.07: 'San Marino'
+SM.01: Acquaviva
+SM.06: 'Borgo Maggiore'
+SM.03: Domagnano
+SM.04: Faetano
+SM.05: Fiorentino
+SM.08: Montegiardino
+SN.12: Ziguinchor
+SN.07: Thiès
+SN.05: Tambacounda
+SN.14: Saint-Louis
+SN.15: Matam
+SN.13: Louga
+SN.11: Kolda
+SN.10: Kaolack
+SN.09: Fatick
+SN.03: Diourbel
+SN.01: Dakar
+SN.16: Kaffrine
+SN.17: Kédougou
+SN.18: Sédhiou
+SO.20: 'Waqooyi Galbeed Region'
+SO.19: 'Togdheer Region'
+SO.14: 'Shabeele Hoose Region'
+SO.13: 'Middle Shabele'
+SO.12: 'Sanaag Region'
+SO.18: 'Nugaal Region'
+SO.10: 'Mudug Region'
+SO.09: 'Lower Juba'
+SO.08: 'Middle Juba'
+SO.07: 'Hiiran Region'
+SO.06: 'Gedo Region'
+SO.05: 'Galgadud Region'
+SO.04: 'Bay Region'
+SO.03: 'Bari Region'
+SO.02: 'Banadir Region'
+SO.01: 'Bakool Region'
+SO.21: 'Awadal Region'
+SO.22: 'Sool Region'
+SR.19: Wanica
+SR.18: Sipaliwini
+SR.17: Saramacca
+SR.16: Paramaribo
+SR.15: Para
+SR.14: Nickerie
+SR.13: Marowijne
+SR.12: Coronie
+SR.11: Commewijne
+SR.10: Brokopondo
+SS.07: 'Upper Nile'
+SS.04: Lakes
+SS.06: Unity
+SS.01: 'Central Equatoria State'
+SS.10: 'Western Equatoria State'
+SS.09: 'Western Bahr al Ghazal'
+SS.03: 'Jonglei State'
+SS.05: 'Northern Bahr el Ghazal State'
+SS.02: 'Eastern Equatoria'
+SS.08: 'Warab State'
+ST.02: 'São Tomé Island'
+ST.01: Príncipe
+SV.14: Usulután
+SV.13: Sonsonate
+SV.12: 'San Vicente'
+SV.11: 'Santa Ana'
+SV.10: 'San Salvador'
+SV.09: 'San Miguel'
+SV.08: Morazán
+SV.07: 'La Unión'
+SV.06: 'La Paz'
+SV.05: 'La Libertad'
+SV.04: Cuscatlán
+SV.03: Chalatenango
+SV.02: Cabañas
+SV.01: Ahuachapán
+SY.14: Tartus
+SY.13: 'Damascus City'
+SY.12: Idlib
+SY.11: Homs
+SY.10: Hama
+SY.09: Aleppo
+SY.08: Rif-dimashq
+SY.07: 'Deir ez-Zor'
+SY.06: Daraa
+SY.05: As-Suwayda
+SY.04: Ar-Raqqah
+SY.03: Quneitra
+SY.02: Latakia
+SY.01: Al-Hasakah
+SZ.04: Shiselweni
+SZ.03: Manzini
+SZ.02: Lubombo
+SZ.01: Hhohho
+TD.13: Salamat
+TD.12: Ouaddaï
+TD.02: Biltine
+TD.14: Tandjilé
+TD.17: Moyen-Chari
+TD.16: 'Mayo-Kebbi East Region'
+TD.09: 'Logone Oriental'
+TD.08: 'Logone Occidental'
+TD.07: Lac
+TD.06: Kanem
+TD.05: Guéra
+TD.15: Chari-Baguirmi
+TD.01: Batha
+TD.23: 'Borkou Region'
+TD.18: Hadjer-Lamis
+TD.19: Mandoul
+TD.20: 'Mayo-Kebbi West Region'
+TD.21: 'Ville de N''Djaména'
+TD.22: 'Barh el Gazel'
+TD.24: 'Ennedi Region'
+TD.25: Sila
+TD.26: 'Tibesti Region'
+TF.02: Crozet
+TF.03: Kerguelen
+TF.01: Saint-Paul-et-Amsterdam
+TF.05: 'Îles Éparses'
+TF.04: Terre-Adélie
+TG.26: Savanes
+TG.25: Plateaux
+TG.24: Maritime
+TG.22: Centrale
+TG.23: Kara
+TH.15: 'Uthai Thani'
+TH.65: Trang
+TH.08: Tak
+TH.60: 'Surat Thani'
+TH.09: Sukhothai
+TH.52: Ratchaburi
+TH.59: Ranong
+TH.57: 'Prachuap Khiri Khan'
+TH.62: 'Phuket Province'
+TH.56: Phetchaburi
+TH.61: Phangnga
+TH.01: 'Mae Hong Son'
+TH.05: Lamphun
+TH.06: Lampang
+TH.63: Krabi
+TH.50: Kanchanaburi
+TH.11: 'Kamphaeng Phet'
+TH.58: Chumphon
+TH.03: 'Chiang Rai'
+TH.02: 'Chiang Mai'
+TH.72: Yasothon
+TH.70: Yala
+TH.10: Uttaradit
+TH.49: Trat
+TH.29: Surin
+TH.51: 'Suphan Buri'
+TH.68: Songkhla
+TH.30: Sisaket
+TH.33: 'Sing Buri'
+TH.67: Satun
+TH.37: 'Sara Buri'
+TH.54: 'Samut Songkhram'
+TH.55: 'Samut Sakhon'
+TH.42: 'Samut Prakan'
+TH.20: 'Sakon Nakhon'
+TH.25: 'Roi Et'
+TH.47: Rayong
+TH.36: 'Phra Nakhon Si Ayutthaya'
+TH.07: Phrae
+TH.12: Phitsanulok
+TH.13: Phichit
+TH.14: Phetchabun
+TH.41: Phayao
+TH.66: Phatthalung
+TH.69: Pattani
+TH.39: 'Pathum Thani'
+TH.38: Nonthaburi
+TH.17: 'Nong Khai'
+TH.31: Narathiwat
+TH.04: Nan
+TH.64: 'Nakhon Si Thammarat'
+TH.16: 'Nakhon Sawan'
+TH.27: 'Nakhon Ratchasima'
+TH.73: 'Nakhon Phanom'
+TH.53: 'Nakhon Pathom'
+TH.43: 'Nakhon Nayok'
+TH.78: Mukdahan
+TH.24: 'Maha Sarakham'
+TH.34: 'Lop Buri'
+TH.18: Loei
+TH.40: Bangkok
+TH.22: 'Khon Kaen'
+TH.23: Kalasin
+TH.46: 'Chon Buri'
+TH.48: Chanthaburi
+TH.26: Chaiyaphum
+TH.32: 'Chai Nat'
+TH.44: Chachoengsao
+TH.28: Buriram
+TH.35: 'Ang Thong'
+TH.76: 'Changwat Udon Thani'
+TH.74: 'Prachin Buri'
+TH.75: 'Changwat Ubon Ratchathani'
+TH.77: 'Amnat Charoen'
+TH.79: 'Changwat Nong Bua Lamphu'
+TH.80: 'Sa Kaeo'
+TH.81: 'Changwat Bueng Kan'
+TJ.03: 'Viloyati Sughd'
+TJ.01: Gorno-Badakhshan
+TJ.02: Khatlon
+TJ.RR: 'Region of Republican Subordination'
+TJ.7280679: Dushanbe
+TK.N: Nukunonu
+TK.F: Fakaofo
+TK.A: Atafu
+TL.VI: 'Distrito Viqueque'
+TL.MF: Manufahi
+TL.MT: 'Distrito Manatuto'
+TL.LI: 'Distrito Liquiçá'
+TL.LA: 'Distrito Lautém'
+TL.CO: 'Distrito Cova Lima'
+TL.ER: Ermera
+TL.DI: 'Distrito Díli'
+TL.BO: Bobonaro
+TL.BA: 'Distrito Bacau'
+TL.OE: 'Distrito Oecussi-Ambeno'
+TL.AN: 'Distrito Ainaro'
+TL.AL: 'Distrito Aileu'
+TM.02: Balkan
+TM.01: Ahal
+TM.03: Daşoguz
+TM.05: Mary
+TM.04: Lebap
+TN.37: Zaghwān
+TN.36: Tūnis
+TN.35: Tawzar
+TN.34: Taţāwīn
+TN.23: Sūsah
+TN.22: Silyānah
+TN.33: 'Sīdī Bū Zayd'
+TN.32: Şafāqis
+TN.31: Qibilī
+TN.30: Qafşah
+TN.29: Qābis
+TN.19: Nābul
+TN.28: Madanīn
+TN.06: Jundūbah
+TN.27: 'Bin ‘Arūs'
+TN.18: Banzart
+TN.17: Bājah
+TN.38: Ariana
+TN.03: 'Al Qayrawān'
+TN.02: 'Al Qaşrayn'
+TN.16: 'Al Munastīr'
+TN.15: 'Al Mahdīyah'
+TN.14: Kef
+TN.39: Manouba
+TO.03: Vava`u
+TO.02: Tongatapu
+TO.01: Ha`apai
+TO.EU: Eua
+TO.NI: Niuas
+TR.66: Yozgat
+TR.65: Van
+TR.64: Uşak
+TR.63: Şanlıurfa
+TR.62: Tunceli
+TR.58: Sivas
+TR.74: Siirt
+TR.73: Niğde
+TR.50: Nevşehir
+TR.49: Muş
+TR.48: Muğla
+TR.72: Mardin
+TR.45: Manisa
+TR.44: Malatya
+TR.43: Kütahya
+TR.71: Konya
+TR.40: Kırşehir
+TR.38: Kayseri
+TR.46: Kahramanmaraş
+TR.35: İzmir
+TR.33: Isparta
+TR.32: Mersin
+TR.31: Hatay
+TR.70: Hakkâri
+TR.83: Gaziantep
+TR.26: Eskişehir
+TR.25: Erzurum
+TR.24: Erzincan
+TR.23: Elazığ
+TR.21: Diyarbakır
+TR.20: Denizli
+TR.15: Burdur
+TR.13: Bitlis
+TR.12: Bingöl
+TR.11: Bilecik
+TR.10: Balıkesir
+TR.09: Aydın
+TR.07: Antalya
+TR.68: Ankara
+TR.04: Ağrı
+TR.03: Afyonkarahisar
+TR.02: Adıyaman
+TR.81: Adana
+TR.91: Osmaniye
+TR.88: Iğdır
+TR.75: Aksaray
+TR.76: Batman
+TR.78: Karaman
+TR.79: Kırıkkale
+TR.80: Şırnak
+TR.90: Kilis
+TR.85: Zonguldak
+TR.61: Trabzon
+TR.60: Tokat
+TR.59: Tekirdağ
+TR.57: Sinop
+TR.55: Samsun
+TR.54: Sakarya
+TR.53: Rize
+TR.52: Ordu
+TR.41: Kocaeli
+TR.39: Kırklareli
+TR.37: Kastamonu
+TR.84: Kars
+TR.34: Istanbul
+TR.69: Gümüşhane
+TR.28: Giresun
+TR.22: Edirne
+TR.19: Çorum
+TR.82: Çankırı
+TR.17: Çanakkale
+TR.16: Bursa
+TR.14: Bolu
+TR.08: Artvin
+TR.05: Amasya
+TR.87: Bartın
+TR.89: Karabük
+TR.92: Yalova
+TR.86: Ardahan
+TR.77: Bayburt
+TR.93: Düzce
+TT.11: Tobago
+TT.10: 'City of San Fernando'
+TT.05: 'City of Port of Spain'
+TT.03: Mayaro
+TT.01: 'Borough of Arima'
+TT.CHA: Chaguanas
+TT.CTT: Couva-Tabaquite-Talparo
+TT.DMN: 'Diego Martin'
+TT.ETO: 'Eastern Tobago'
+TT.PED: Penal/Debe
+TT.PRT: 'Princes Town'
+TT.PTF: 'Point Fortin'
+TT.SGE: 'Sangre Grande'
+TT.SIP: Siparia
+TT.SJL: 'San Juan/Laventille'
+TT.TUP: Tunapuna/Piarco
+TV.NUI: Nui
+TV.NMA: Nanumea
+TV.FUN: Funafuti
+TV.NIT: Niutao
+TV.NMG: Nanumanga
+TV.VAI: Vaitupu
+TV.NKF: Nukufetau
+TV.NKL: Nukulaelae
+TW.01: Fukien
+TW.02: Kaohsiung
+TW.03: Taipei
+TW.04: Taiwan
+TZ.19: Kagera
+TZ.25: 'Zanzibar Urban/West'
+TZ.22: 'Zanzibar North'
+TZ.21: 'Zanzibar Central/South'
+TZ.18: Tanga
+TZ.17: Tabora
+TZ.16: Singida
+TZ.15: Shinyanga
+TZ.24: 'Rukwa Region'
+TZ.02: Pwani
+TZ.20: 'Pemba South'
+TZ.13: 'Pemba North'
+TZ.12: Mwanza
+TZ.10: 'Morogoro Region'
+TZ.09: Mbeya
+TZ.08: Mara
+TZ.07: Lindi
+TZ.06: Kilimanjaro
+TZ.05: Kigoma
+TZ.04: Iringa
+TZ.03: Dodoma
+TZ.23: 'Dar es Salaam'
+TZ.26: Arusha
+TZ.27: Manyara
+TZ.14: Ruvuma
+TZ.11: Mtwara
+TZ.31: 'Simiyu Region'
+TZ.28: 'Geita Region'
+TZ.29: 'Katavi Region'
+TZ.30: 'Njombe Region'
+UA.27: 'Zhytomyrs’ka Oblast’'
+UA.26: 'Zaporiz’ka Oblast’'
+UA.25: 'Zakarpattia Oblast'
+UA.24: 'Volyns’ka Oblast’'
+UA.23: 'Vinnyts''ka'
+UA.22: 'Ternopil’s’ka Oblast’'
+UA.21: 'Sums’ka Oblast’'
+UA.20: 'Misto Sevastopol’'
+UA.19: 'Rivnens’ka Oblast’'
+UA.18: 'Poltavs’ka Oblast’'
+UA.17: 'Odes’ka Oblast’'
+UA.16: 'Mykolayivs’ka Oblast’'
+UA.15: 'L’vivs’ka Oblast’'
+UA.14: 'Luhans’ka Oblast’'
+UA.13: 'Kyyivs’ka Oblast’'
+UA.12: 'Kyiv City'
+UA.11: 'Avtonomna Respublika Krym'
+UA.10: 'Kirovohrads’ka Oblast’'
+UA.09: 'Khmel’nyts’ka Oblast’'
+UA.08: 'Khersons’ka Oblast’'
+UA.07: 'Kharkivs’ka Oblast’'
+UA.06: 'Ivano-Frankivs’ka Oblast’'
+UA.05: 'Donets’ka Oblast’'
+UA.04: 'Dnipropetrovs''ka Oblast'''
+UA.03: 'Chernivets''ka Oblast'''
+UA.02: 'Chernihivs’ka Oblast’'
+UA.01: 'Cherkas''ka Oblast'''
+UG.C: 'Central Region'
+UG.E: 'Eastern Region'
+UG.N: 'Northern Region'
+UG.W: 'Western Region'
+UM.450: 'Wake Island'
+UM.350: 'Navassa Island'
+UM.050: 'Baker Island'
+UM.100: 'Howland Island'
+UM.150: 'Jarvis Island'
+UM.200: 'Johnston Atoll'
+UM.250: 'Kingman Reef'
+UM.300: 'Midway Islands'
+UM.400: 'Palmyra Atoll'
+US.AR: Arkansas
+US.DC: 'Washington, D.C.'
+US.DE: Delaware
+US.FL: Florida
+US.GA: Georgia
+US.KS: Kansas
+US.LA: Louisiana
+US.MD: Maryland
+US.MO: Missouri
+US.MS: Mississippi
+US.NC: 'North Carolina'
+US.OK: Oklahoma
+US.SC: 'South Carolina'
+US.TN: Tennessee
+US.TX: Texas
+US.WV: 'West Virginia'
+US.AL: Alabama
+US.CT: Connecticut
+US.IA: Iowa
+US.IL: Illinois
+US.IN: Indiana
+US.ME: Maine
+US.MI: Michigan
+US.MN: Minnesota
+US.NE: Nebraska
+US.NH: 'New Hampshire'
+US.NJ: 'New Jersey'
+US.NY: 'New York'
+US.OH: Ohio
+US.RI: 'Rhode Island'
+US.VT: Vermont
+US.WI: Wisconsin
+US.CA: California
+US.CO: Colorado
+US.NM: 'New Mexico'
+US.NV: Nevada
+US.UT: Utah
+US.AZ: Arizona
+US.ID: Idaho
+US.MT: Montana
+US.ND: 'North Dakota'
+US.OR: Oregon
+US.SD: 'South Dakota'
+US.WA: Washington
+US.WY: Wyoming
+US.HI: Hawaii
+US.AK: Alaska
+US.KY: Kentucky
+US.MA: Massachusetts
+US.PA: Pennsylvania
+US.VA: Virginia
+UY.19: 'Treinta y Tres'
+UY.18: Tacuarembó
+UY.17: Soriano
+UY.16: 'San José'
+UY.15: Salto
+UY.14: Rocha
+UY.13: Rivera
+UY.12: 'Río Negro'
+UY.11: Paysandú
+UY.10: Montevideo
+UY.09: Maldonado
+UY.08: Lavalleja
+UY.07: Florida
+UY.06: Flores
+UY.05: Durazno
+UY.04: Colonia
+UY.03: 'Cerro Largo'
+UY.02: Canelones
+UY.01: Artigas
+UZ.09: Karakalpakstan
+UZ.12: Surxondaryo
+UZ.10: Samarqand
+UZ.08: 'Kashkadarya Province'
+UZ.02: Bukhara
+UZ.14: Toshkent
+UZ.13: 'Toshkent Shahri'
+UZ.16: Sirdaryo
+UZ.07: Navoiy
+UZ.06: 'Namangan Province'
+UZ.05: Xorazm
+UZ.15: Jizzax
+UZ.03: Fergana
+UZ.01: Andijon
+VC.05: 'Saint Patrick'
+VC.04: 'Saint George'
+VC.03: 'Saint David'
+VC.02: 'Saint Andrew'
+VC.06: Grenadines
+VC.01: Charlotte
+VE.23: 'Estado Zulia'
+VE.22: 'Estado Yaracuy'
+VE.21: Trujillo
+VE.20: 'Estado Táchira'
+VE.19: Sucre
+VE.18: 'Estado Portuguesa'
+VE.17: 'Estado Nueva Esparta'
+VE.16: 'Estado Monagas'
+VE.15: 'Estado Miranda'
+VE.14: 'Estado Mérida'
+VE.13: 'Estado Lara'
+VE.12: 'Estado Guárico'
+VE.24: 'Dependencias Federales'
+VE.25: 'Distrito Federal'
+VE.11: 'Estado Falcón'
+VE.09: 'Delta Amacuro'
+VE.08: 'Estado Cojedes'
+VE.07: 'Estado Carabobo'
+VE.06: 'Estado Bolívar'
+VE.05: 'Estado Barinas'
+VE.04: 'Estado Aragua'
+VE.03: 'Estado Apure'
+VE.02: 'Estado Anzoátegui'
+VE.01: 'Estado Amazonas'
+VE.26: Vargas
+VI.010: 'Saint Croix Island'
+VI.020: 'Saint John Island'
+VI.030: 'Saint Thomas Island'
+VN.58: 'Nghệ An'
+VN.59: 'Ninh Bình'
+VN.60: 'Ninh Thuận'
+VN.65: 'Sóc Trăng'
+VN.67: 'Trà Vinh'
+VN.68: 'Tuyên Quang'
+VN.69: 'Vĩnh Long'
+VN.70: 'Yên Bái'
+VN.90: 'Lào Cai'
+VN.37: 'Tiền Giang'
+VN.66: 'Thừa Thiên-Huế'
+VN.55: 'Kon Tum'
+VN.34: 'Thanh Hóa'
+VN.35: 'Thái Bình'
+VN.33: 'Tây Ninh'
+VN.32: 'Sơn La'
+VN.64: 'Quảng Trị'
+VN.30: 'Quảng Ninh'
+VN.63: 'Quảng Ngãi'
+VN.62: 'Quảng Bình'
+VN.61: 'Phú Yên'
+VN.53: 'Hòa Bình'
+VN.24: 'Long An'
+VN.39: 'Lạng Sơn'
+VN.23: 'Lâm Đồng'
+VN.89: 'Lai Châu'
+VN.21: 'Kiến Giang'
+VN.54: 'Khánh Hòa'
+VN.20: 'Hồ Chí Minh'
+VN.52: 'Hà Tĩnh'
+VN.51: 'Hà Tây'
+VN.50: 'Hà Giang'
+VN.49: 'Gia Lai'
+VN.44: 'Ha Nội'
+VN.87: 'Cần Thơ'
+VN.13: 'Hải Phòng'
+VN.47: 'Bình Thuận'
+VN.09: 'Đồng Tháp'
+VN.43: 'Đồng Nai'
+VN.88: 'Ðắc Lắk'
+VN.45: 'Bà Rịa-Vũng Tàu'
+VN.05: 'Cao Bằng'
+VN.46: 'Bình Định'
+VN.03: 'Bến Tre'
+VN.01: 'An Giang'
+VN.91: 'Ðắk Nông'
+VN.92: 'Huyện Ðiện Biên'
+VN.74: 'Bắc Ninh'
+VN.71: 'Bắc Giang'
+VN.78: 'Đà Nẵng'
+VN.75: 'Bình Dương'
+VN.76: 'Bình Phước'
+VN.85: 'Thái Nguyên'
+VN.84: 'Quảng Nam'
+VN.83: 'Phú Thọ'
+VN.82: 'Nam Ðịnh'
+VN.80: 'Hà Nam'
+VN.72: 'Bắc Kạn'
+VN.73: 'Bạc Liêu'
+VN.77: 'Cà Mau'
+VN.79: 'Hải Dương'
+VN.81: 'Hưng Yên'
+VN.86: 'Vĩnh Phúc'
+VN.93: 'Hau Giang'
+VU.15: Tafea
+VU.13: Sanma
+VU.07: Torba
+VU.16: Malampa
+VU.17: Penama
+VU.18: Shefa
+WF.98613: 'Circonscription d''Uvéa'
+WF.98612: 'Circonscription de Sigavé'
+WF.98611: 'Circonscription d''Alo'
+WS.11: Vaisigano
+WS.06: Va‘a-o-Fonoti
+WS.10: Tuamasaga
+WS.09: Satupa‘itea
+WS.08: Palauli
+WS.07: Gagaifomauga
+WS.05: Gaga‘emauga
+WS.04: Fa‘asaleleaga
+WS.03: Atua
+WS.02: Aiga-i-le-Tai
+WS.01: 'A''ana'
+XK.28: Vushtrri
+XK.27: 'Komuna e Vitisë'
+XK.03: 'Komuna e Ferizajt'
+XK.15: 'Komuna e Mitrovicës'
+XK.26: 'Komuna e Thërandës'
+XK.25: 'Komuna e Skenderajt'
+XK.21: Prizren
+XK.20: 'Komuna e Prishtinës'
+XK.19: Podujevo
+XK.18: 'Komuna e Pejës'
+XK.22: Orahovac
+XK.13: Lipjan
+XK.12: 'Komuna e Leposaviqit'
+XK.10: Kamenica
+XK.11: 'Komuna e Klines'
+XK.09: 'Komuna e Kaçanikut'
+XK.08: 'Komuna e Istogut'
+XK.06: 'Komuna e Gjilanit'
+XK.07: 'Komuna e Drenasit'
+XK.02: 'Komuna e Dragashit'
+XK.01: 'Komuna e Deçanit'
+XK.05: 'Komuna e Gjakovës'
+XK.04: 'Kosovo Polje'
+XK.23: 'Opština Štrpce'
+XK.24: 'Komuna e Shtimes'
+XK.16: 'Novo Brdo'
+XK.17: 'Komuna e Obiliqit'
+XK.14: 'Komuna e Malisheves'
+XK.29: 'Komuna e Zubin Potokut'
+XK.30: 'Opština Zvečan'
+XK.31: 'Komuna e Graçanicës'
+XK.32: 'Hani i Elezit'
+XK.33: 'Komuna e Junikut'
+XK.34: 'Komuna e Kllokotit'
+XK.35: 'Komuna e Mamushës'
+XK.36: 'Komuna e Parteshit'
+XK.37: 'Komuna e Ranillugut'
+YE.25: 'Muḩāfaz̧at Ta‘izz'
+YE.05: Shabwah
+YE.16: Sanaa
+YE.15: 'Muḩāfaz̧at Şa‘dah'
+YE.27: 'Muḩāfaz̧at Raymah'
+YE.14: 'Muḩāfaz̧at Ma’rib'
+YE.10: 'Al Maḩwīt'
+YE.21: 'Muḩāfaz̧at al Jawf'
+YE.04: Ḩaḑramawt
+YE.11: 'Muḩāfaz̧at Dhamār'
+YE.03: 'Al Mahrah'
+YE.08: 'Al Ḩudaydah'
+YE.20: 'Al Bayḑāʼ'
+YE.02: Aden
+YE.01: Abyan
+YE.18: 'Muḩāfaz̧at aḑ Ḑāli‘'
+YE.19: Omran
+YE.22: 'Muḩāfaz̧at Ḩajjah'
+YE.23: Ibb
+YE.24: 'Muḩāfaz̧at Laḩij'
+YE.26: 'Amanat Al Asimah'
+YT.97601: Acoua
+YT.97602: Bandraboua
+YT.97603: Bandrele
+YT.97604: Bouéni
+YT.97605: Chiconi
+YT.97606: Chirongui
+YT.97607: Dembeni
+YT.97608: Dzaoudzi
+YT.97609: Kani-Kéli
+YT.97610: Koungou
+YT.97611: Mamoudzou
+YT.97612: Mtsamboro
+YT.97613: 'M''Tsangamouji'
+YT.97614: Ouangani
+YT.97615: Pamandzi
+YT.97616: Sada
+YT.97617: Tsingoni
+ZA.03: 'Free State'
+ZA.02: KwaZulu-Natal
+ZA.05: 'Eastern Cape'
+ZA.06: Gauteng
+ZA.07: Mpumalanga
+ZA.08: 'Northern Cape'
+ZA.09: Limpopo
+ZA.10: North-West
+ZA.11: 'Western Cape'
+ZM.01: Western
+ZM.07: Southern
+ZM.06: North-Western
+ZM.05: Northern
+ZM.09: Lusaka
+ZM.04: Luapula
+ZM.03: Eastern
+ZM.08: Copperbelt
+ZM.02: Central
+ZW.02: Midlands
+ZW.07: 'Matabeleland South'
+ZW.06: 'Matabeleland North'
+ZW.08: Masvingo
+ZW.05: 'Mashonaland West Province'
+ZW.04: 'Mashonaland East'
+ZW.03: 'Mashonaland Central Province'
+ZW.01: Manicaland
+ZW.09: Bulawayo
+ZW.10: 'Harare Province'
diff --git a/src/Oro/Bundle/AddressBundle/Resources/translations/messages.en.yml b/src/Oro/Bundle/AddressBundle/Resources/translations/messages.en.yml
index d1f27f6412b..c255b431049 100644
--- a/src/Oro/Bundle/AddressBundle/Resources/translations/messages.en.yml
+++ b/src/Oro/Bundle/AddressBundle/Resources/translations/messages.en.yml
@@ -3,4 +3,6 @@
"View address": "View address"
"Edit address": "Edit address"
"Create address": "Create address"
-"Remove address": "Remove address"
\ No newline at end of file
+"Remove address": "Remove address"
+oro.address.form.choose_country: "Choose a country..."
+oro.address.form.choose_state: "Choose a state..."
diff --git a/src/Oro/Bundle/AddressBundle/Resources/views/Include/fields.html.twig b/src/Oro/Bundle/AddressBundle/Resources/views/Include/fields.html.twig
index 69a96c1af2b..96886bca127 100644
--- a/src/Oro/Bundle/AddressBundle/Resources/views/Include/fields.html.twig
+++ b/src/Oro/Bundle/AddressBundle/Resources/views/Include/fields.html.twig
@@ -22,11 +22,12 @@
$(function() {
var regions = new Oro.RegionUpdater.Collection();
- var regionView = new Oro.RegionUpdater.View ({
+ var regionView = new Oro.RegionUpdater.View({
el: $('{{ country_field }}'),
target: $('#{{ id }}'),
simpleEl: $('{{ state_text_field }}'),
- collection: regions
+ collection: regions,
+ showSelect: {{ (choices is not empty)|json_encode }}
});
});
@@ -63,3 +64,51 @@
{{ form_row(form.country) }}
{{ form_row(form.postalCode) }}
{% endblock oro_address_widget %}
+
+{% macro address_collection_prototype(widget) %}
+ {% if widget.get('prototype') %}
+ {% set form = widget.get('prototype') %}
+ {% set name = widget.get('prototype').get('name') %}
+ {% else %}
+ {% set form = widget %}
+ {% set name = widget.get('full_name') %}
+ {% endif %}
+
+
+ {{ form_errors(form) }}
+ {{ form_row(form.id) }}
+ {{ form_row(form.type) }}
+ {{ form_row(form.primary) }}
+ {{ block('oro_address_widget') }}
+
+
+
+{% endmacro %}
+
+{% block oro_address_collection_widget %}
+ {% spaceless %}
+
+
+ {% for field in form.children %}
+ {{ _self.address_collection_prototype(field) }}
+ {% endfor %}
+
+
{{ 'Add'|trans }}
+
+
+ {% endspaceless %}
+{% endblock oro_address_collection_widget %}
diff --git a/src/Oro/Bundle/AddressBundle/Resources/views/Include/javascript.html.twig b/src/Oro/Bundle/AddressBundle/Resources/views/Include/javascript.html.twig
index 1ec3b218323..16bad123d3e 100644
--- a/src/Oro/Bundle/AddressBundle/Resources/views/Include/javascript.html.twig
+++ b/src/Oro/Bundle/AddressBundle/Resources/views/Include/javascript.html.twig
@@ -1,7 +1,7 @@
{% block oro_region_updater_js %}
{% endblock oro_region_updater_js %}
diff --git a/src/Oro/Bundle/AddressBundle/Resources/views/Include/viewMacro.html.twig b/src/Oro/Bundle/AddressBundle/Resources/views/Include/viewMacro.html.twig
new file mode 100644
index 00000000000..14c5133de49
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Resources/views/Include/viewMacro.html.twig
@@ -0,0 +1,45 @@
+{% macro renderAddress(address) %}
+ {% import _self as __ %}
+
+ {% set fields = [
+ {label: "First name", data: "firstName"},
+ {label: "Last name", data: "lastName"},
+ {label: "Street", data: "street"},
+ {label: "Street 2", data: "street2"},
+ {label: "City", data: "city"},
+ {label: "State", data: "universalState"},
+ {label: "Country", data: "country"},
+ {label: "Zip/postal code", data: "postalCode"}
+ ] %}
+
+ {{ __.renderAddressView(address, fields) }}
+{% endmacro %}
+
+{% macro renderAddressView(address, fields, renderFlexibleAttributes) %}
+ {# Render flexible attributes by default #}
+ {% set renderFlexibleAttributes = renderFlexibleAttributes|default(true) %}
+
+ {# Render static attributes #}
+ {% for field in fields %}
+ {{ block('addressStaticAttribute') }}
+ {% endfor %}
+
+ {# Render flexible attributes #}
+ {% import 'OroUIBundle::macros.html.twig' as UI %}
+ {% for value in address|getAttributes() %}
+ {{ UI.flexibleAttributeRow(value) }}
+ {% endfor %}
+{% endmacro %}
+
+{% block addressStaticAttribute %}
+ {% set defaultValue = field.defaultValue|default('N/A') %}
+ {% set value = field.value is defined ? field.value : attribute(address, field.data) %}
+
+
+
+
+
{{ value|default(defaultValue) }}
+
+
+
+{% endblock addressStaticAttribute %}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Functional/API/RestApiTest.php b/src/Oro/Bundle/AddressBundle/Tests/Functional/API/RestApiTest.php
index f8f3c7548b2..104b36cbaf2 100644
--- a/src/Oro/Bundle/AddressBundle/Tests/Functional/API/RestApiTest.php
+++ b/src/Oro/Bundle/AddressBundle/Tests/Functional/API/RestApiTest.php
@@ -25,7 +25,7 @@ public function testPost()
array(
'street' => 'Some kind st.',
'city' => 'Old York',
- 'state' => 'AL',
+ 'state' => 'US.AL',
'country' => 'US',
'postalCode' => '32422',
)
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/AddressBaseTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/AddressBaseTest.php
new file mode 100644
index 00000000000..dd3e0422e7a
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/AddressBaseTest.php
@@ -0,0 +1,225 @@
+assertEquals($value, call_user_func_array(array($obj, 'get' . ucfirst($property)), array()));
+ }
+
+ /**
+ * Data provider with entity properties
+ *
+ * @return array
+ */
+ public function propertiesDataProvider()
+ {
+ $countryMock = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\Country')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $regionMock = $this->getMock('Oro\Bundle\AddressBundle\Entity\Region', array(), array('combinedCode'));
+ return array(
+ 'id' => array('id', 1),
+ 'lastName' => array('lastName', 'last name'),
+ 'firstName' => array('firstName', 'first_name'),
+ 'street' => array('street', 'street'),
+ 'street2' => array('street2', 'street2'),
+ 'city' => array('city', 'city'),
+ 'state' => array('state', $regionMock),
+ 'stateText' => array('stateText', 'test state'),
+ 'postalCode' => array('postalCode', '12345'),
+ 'country' => array('country', $countryMock),
+ 'created' => array('created', new \DateTime()),
+ 'updated' => array('updated', new \DateTime()),
+ );
+ }
+
+ public function testBeforeSave()
+ {
+ $obj = new AddressBase();
+ $obj->beforeSave();
+
+ $this->assertNotNull($obj->getCreatedAt());
+ $this->assertNotNull($obj->getUpdatedAt());
+
+ $this->assertEquals($obj->getCreatedAt(), $obj->getUpdatedAt());
+ }
+
+ public function testToString()
+ {
+ $obj = new AddressBase();
+ $country = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\Country')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $country->expects($this->once())
+ ->method('__toString')
+ ->will($this->returnValue('Ukraine'));
+
+ $regionMock = $this->getMock('Oro\Bundle\AddressBundle\Entity\Region', array(), array('combinedCode'));
+ $regionMock->expects($this->once())
+ ->method('__toString')
+ ->will($this->returnValue('Kharkivs\'ka oblast\''));
+
+ $obj->setFirstName('FirstName')
+ ->setLastName('LastName')
+ ->setStreet('Street')
+ ->setState($regionMock)
+ ->setPostalCode('12345')
+ ->setCountry($country);
+
+ $this->assertTrue(method_exists($obj, '__toString'));
+ $this->assertEquals('FirstName LastName , Street Kharkivs\'ka oblast\' , Ukraine 12345', $obj->__toString());
+ }
+
+ public function testStateText()
+ {
+ $obj = new AddressBase();
+ $region = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\Region')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $obj->setState($region);
+ $this->assertEquals($region, $obj->getState());
+ $obj->setStateText('text state');
+ $this->assertEquals('text state', $obj->getUniversalState());
+ }
+
+ public function testIsStateValidNoCountry()
+ {
+ $context = $this->getMockBuilder('Symfony\Component\Validator\ExecutionContext')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $context->expects($this->never())
+ ->method('addViolationAtPath');
+
+ $obj = new AddressBase();
+ $obj->isStateValid($context);
+ }
+
+ public function testIsStateValidNoRegion()
+ {
+ $country = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\Country')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $country->expects($this->once())
+ ->method('hasRegions')
+ ->will($this->returnValue(false));
+
+ $context = $this->getMockBuilder('Symfony\Component\Validator\ExecutionContext')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $context->expects($this->never())
+ ->method('addViolationAtPath');
+
+ $obj = new AddressBase();
+ $obj->setCountry($country);
+ $obj->isStateValid($context);
+ }
+
+ public function testIsStateValid()
+ {
+ $country = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\Country')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $country->expects($this->once())
+ ->method('hasRegions')
+ ->will($this->returnValue(true));
+ $country->expects($this->once())
+ ->method('getName')
+ ->will($this->returnValue('Country'));
+
+ $context = $this->getMockBuilder('Symfony\Component\Validator\ExecutionContext')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $context->expects($this->once())
+ ->method('getPropertyPath')
+ ->will($this->returnValue('test'));
+ $context->expects($this->once())
+ ->method('addViolationAtPath')
+ ->with(
+ 'test.state',
+ 'State is required for country %country%',
+ array('%country%' => 'Country')
+ );
+
+ $obj = new AddressBase();
+ $obj->setCountry($country);
+ $obj->isStateValid($context);
+ }
+
+ public function testIsEmpty()
+ {
+ $obj = new AddressBase();
+ $this->assertTrue($obj->isEmpty());
+ }
+
+ /**
+ * @dataProvider emptyCheckPropertiesDataProvider
+ * @param string $property
+ * @param mixed $value
+ */
+ public function testIsNotEmpty($property, $value)
+ {
+ $obj = new AddressBase();
+ call_user_func_array(array($obj, 'set' . ucfirst($property)), array($value));
+ $this->assertFalse($obj->isEmpty());
+ }
+
+ /**
+ * Data provider with entity properties
+ *
+ * @return array
+ */
+ public function emptyCheckPropertiesDataProvider()
+ {
+ $countryMock = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\Country')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $regionMock = $this->getMock('Oro\Bundle\AddressBundle\Entity\Region', array(), array('combinedCode'));
+ return array(
+ 'lastName' => array('lastName', 'last name'),
+ 'firstName' => array('firstName', 'first_name'),
+ 'street' => array('street', 'street'),
+ 'street2' => array('street2', 'street2'),
+ 'city' => array('city', 'city'),
+ 'state' => array('state', $regionMock),
+ 'stateText' => array('stateText', 'test state'),
+ 'postalCode' => array('postalCode', '12345'),
+ 'country' => array('country', $countryMock),
+ );
+ }
+
+ public function testIsNotEmptyFlexible()
+ {
+ $value = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Entity\Mapping\AbstractEntityFlexibleValue');
+ $value->expects($this->once())
+ ->method('getData')
+ ->will($this->returnValue('not empty'));
+
+ $obj = new AddressBase();
+ $obj->addValue($value);
+ $this->assertFalse($obj->isEmpty());
+ }
+
+ public function testIsEmptyFlexible()
+ {
+ $value = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Entity\Mapping\AbstractEntityFlexibleValue');
+ $value->expects($this->once())
+ ->method('getData');
+
+ $obj = new AddressBase();
+ $obj->addValue($value);
+ $this->assertTrue($obj->isEmpty());
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/AddressTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/AddressTest.php
deleted file mode 100644
index 6b6547b5e2a..00000000000
--- a/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/AddressTest.php
+++ /dev/null
@@ -1,80 +0,0 @@
-assertEquals($value, call_user_func_array(array($obj, 'get' . ucfirst($property)), array()));
- }
-
- public function testBeforeSave()
- {
- $obj = new Address();
- $obj->beforeSave();
-
- $this->assertNotNull($obj->getCreatedAt());
- $this->assertNotNull($obj->getUpdatedAt());
-
- $this->assertEquals($obj->getCreatedAt(), $obj->getUpdatedAt());
- }
-
- public function testToString()
- {
- $obj = new Address();
- $country = $this->getMock('Oro\Bundle\AddressBundle\Entity\Country');
- $country->expects($this->once())
- ->method('__toString')
- ->will($this->returnValue('Ukraine'));
-
- $regionMock = $this->getMock('Oro\Bundle\AddressBundle\Entity\Region');
- $regionMock->expects($this->once())
- ->method('__toString')
- ->will($this->returnValue('Kharkivs\'ka oblast\''));
-
- $obj->setFirstName('FirstName')
- ->setLastName('LastName')
- ->setStreet('Street')
- ->setState($regionMock)
- ->setPostalCode('12345')
- ->setCountry($country);
-
- $this->assertTrue(method_exists($obj, '__toString'));
- $this->assertEquals('FirstName LastName , Street Kharkivs\'ka oblast\' , Ukraine 12345', $obj->__toString());
- }
-
- /**
- * Data provider
- *
- * @return array
- */
- public function provider()
- {
- $countryMock = $this->getMock('Oro\Bundle\AddressBundle\Entity\Country');
- $regionMock = $this->getMock('Oro\Bundle\AddressBundle\Entity\Region');
- return array(
- array('id', 1),
- array('lastName', 'last name'),
- array('firstName', 'first_name'),
- array('street', 'street'),
- array('street2', 'street2'),
- array('city', 'city'),
- array('state', $regionMock),
- array('postalCode', '12345'),
- array('country', $countryMock),
- array('created', new \DateTime()),
- array('updated', new \DateTime()),
- );
- }
-}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/CountryTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/CountryTest.php
index 59d53ad9a93..768b4051177 100644
--- a/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/CountryTest.php
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/CountryTest.php
@@ -3,6 +3,7 @@
namespace Oro\Bundle\AddressBundle\Tests\Entity;
use Oro\Bundle\AddressBundle\Entity\Country;
+use Oro\Bundle\AddressBundle\Entity\Region;
class CountryTest extends \PHPUnit_Framework_TestCase
{
@@ -12,7 +13,7 @@ class CountryTest extends \PHPUnit_Framework_TestCase
*/
public function testSettersAndGetters($property)
{
- $obj = new Country();
+ $obj = new Country('iso2code');
$value = 'testValue';
call_user_func_array(array($obj, 'set' . ucfirst($property)), array($value));
@@ -21,11 +22,9 @@ public function testSettersAndGetters($property)
public function testConstructorData()
{
- $obj = new Country('name', 'iso2Code', 'iso3Code');
+ $obj = new Country('iso2Code');
- $this->assertEquals('name', $obj->getName());
$this->assertEquals('iso2Code', $obj->getIso2Code());
- $this->assertEquals('iso3Code', $obj->getIso3Code());
}
/**
@@ -37,15 +36,55 @@ public function provider()
{
return array(
array('name'),
- array('iso2code'),
array('iso3code'),
array('regions'),
+ array('locale'),
);
}
public function testToString()
{
- $obj = new Country('name', 'iso2Code', 'iso3Code');
+ $obj = new Country('iso2Code');
+ $obj->setName('name');
$this->assertEquals('name', $obj->__toString());
}
+
+ public function testAddRegion()
+ {
+ $country = new Country('iso2Code');
+ $region = new Region('combinedCode');
+
+ $this->assertEmpty($country->getRegions()->getValues());
+
+ $country->addRegion($region);
+
+ $this->assertEquals(array($region), $country->getRegions()->getValues());
+ $this->assertEquals($country, $region->getCountry());
+ }
+
+ public function testRemoveRegion()
+ {
+ $country = new Country('iso2Code');
+ $region = new Region('combinedCode');
+ $country->addRegion($region);
+
+ $this->assertNotEmpty($country->getRegions()->getValues());
+
+ $country->removeRegion($region);
+
+ $this->assertEmpty($country->getRegions()->getValues());
+ $this->assertNull($region->getCountry());
+ }
+
+ public function testHasRegions()
+ {
+ $country = new Country('iso2Code');
+ $region = new Region('combinedCode');
+
+ $this->assertFalse($country->hasRegions());
+
+ $country->addRegion($region);
+
+ $this->assertTrue($country->hasRegions());
+ }
}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/RegionTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/RegionTest.php
index 0d973dceb12..0da538d24ec 100644
--- a/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/RegionTest.php
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/RegionTest.php
@@ -8,10 +8,10 @@ class RegionTest extends \PHPUnit_Framework_TestCase
{
public function testConstructorData()
{
- $obj = new Region();
+ $combinedCode = 'combinedCode';
- $this->assertNull($obj->getId());
- $obj->setLocale();
+ $obj = new Region($combinedCode);
+ $this->assertEquals($combinedCode, $obj->getCombinedCode());
}
/**
@@ -19,13 +19,14 @@ public function testConstructorData()
*/
public function testCountrySetter()
{
- $countryMock = $this->getMock('Oro\Bundle\AddressBundle\Entity\Country');
+ $countryMock = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\Country')
+ ->disableOriginalConstructor()
+ ->getMock();
- $obj = new Region();
+ $obj = new Region('combinedCode');
$obj->setCountry($countryMock);
$this->assertEquals($countryMock, $obj->getCountry());
- $this->assertNull($obj->getId());
}
/**
@@ -34,7 +35,7 @@ public function testCountrySetter()
*/
public function testSettersAndGetters($property)
{
- $obj = new Region();
+ $obj = new Region('combinedCode');
$value = 'testValue';
call_user_func_array(array($obj, 'set' . ucfirst($property)), array($value));
@@ -54,4 +55,11 @@ public function provider()
array('locale'),
);
}
+
+ public function testToString()
+ {
+ $obj = new Region('combinedCode');
+ $obj->setName('name');
+ $this->assertEquals('name', $obj->__toString());
+ }
}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/Repository/RegionRepositoryTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/Repository/RegionRepositoryTest.php
new file mode 100644
index 00000000000..a71025082d4
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/Repository/RegionRepositoryTest.php
@@ -0,0 +1,89 @@
+entityManager = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+ ->disableOriginalConstructor()
+ ->setMethods(array('createQueryBuilder'))
+ ->getMock();
+
+ $this->repository = new RegionRepository($this->entityManager, new ClassMetadata(self::ENTITY_NAME));
+ }
+
+ protected function tearDown()
+ {
+ unset($this->repository);
+ }
+
+ /**
+ * Tests both getCountryRegionsQueryBuilder and getCountryRegions
+ */
+ public function testGetCountryRegions()
+ {
+ $entityAlias = 'r';
+ $country = new Country('iso2Code');
+
+ $query = $this->getMockBuilder('Doctrine\ORM\AbstractQuery')
+ ->disableOriginalConstructor()
+ ->setMethods(array('setHint', 'execute'))
+ ->getMockForAbstractClass();
+ $query->expects($this->once())->method('setHint')->with(
+ Query::HINT_CUSTOM_OUTPUT_WALKER,
+ 'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
+ );
+ $query->expects($this->once())->method('execute')
+ ->will($this->returnValue($this->testRegions));
+
+ $queryBuilder = $this->getMockBuilder('Doctrine\ORM\QueryBuilder')
+ ->disableOriginalConstructor()
+ ->setMethods(array('select', 'from', 'where', 'orderBy', 'setParameter', 'getQuery'))
+ ->getMock();
+ $queryBuilder->expects($this->once())->method('select')->with($entityAlias)
+ ->will($this->returnSelf());
+ $queryBuilder->expects($this->once())->method('from')->with(self::ENTITY_NAME, $entityAlias)
+ ->will($this->returnSelf());
+ $queryBuilder->expects($this->once())->method('where')->with('r.country = :country')
+ ->will($this->returnSelf());
+ $queryBuilder->expects($this->once())->method('orderBy')->with('r.name', 'ASC')
+ ->will($this->returnSelf());
+ $queryBuilder->expects($this->once())->method('setParameter')->with('country', $country)
+ ->will($this->returnSelf());
+ $queryBuilder->expects($this->once())->method('getQuery')
+ ->will($this->returnValue($query));
+
+ $this->entityManager->expects($this->once())
+ ->method('createQueryBuilder')
+ ->will($this->returnValue($queryBuilder));
+
+ $actualRegions = $this->repository->getCountryRegions($country);
+ $this->assertEquals($this->testRegions, $actualRegions);
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/TypedAddressTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/TypedAddressTest.php
new file mode 100644
index 00000000000..f7961f32e77
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Entity/TypedAddressTest.php
@@ -0,0 +1,15 @@
+setType('TEST');
+ $this->assertEquals('TEST', $obj->getType());
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/DataTransformer/AddressTypeToTypeTransformerTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/DataTransformer/AddressTypeToTypeTransformerTest.php
new file mode 100644
index 00000000000..cb7ac8c7b58
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/DataTransformer/AddressTypeToTypeTransformerTest.php
@@ -0,0 +1,102 @@
+om = $this->getMockBuilder('Doctrine\Common\Persistence\ObjectManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->transformer = new AddressTypeToTypeTransformer($this->om);
+ }
+
+ /**
+ * @dataProvider typesDataProvider
+ * @param null|AddressType $type
+ * @param string $expected
+ */
+ public function testTransform($type, $expected)
+ {
+ $this->assertEquals($expected, $this->transformer->transform($type));
+ }
+
+ /**
+ * @return array
+ */
+ public function typesDataProvider()
+ {
+ return array(
+ array(null, ''),
+ array($this->getAddressTypeMock('test'), 'test')
+ );
+ }
+
+ public function testReverseTransformEmpty()
+ {
+ $this->assertNull($this->transformer->reverseTransform(false));
+ }
+
+ /**
+ * @expectedException Symfony\Component\Form\Exception\TransformationFailedException
+ * @expectedExceptionMessage An address type with type "unknown" does not exist!
+ */
+ public function testReverseTransformException()
+ {
+ $type = 'unknown';
+ $this->assertRepositoryCall($type, null);
+ $this->transformer->reverseTransform($type);
+ }
+
+ public function testReverseTransform()
+ {
+ $type = 'test';
+ $addressType = $addressType = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\AddressType')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->assertRepositoryCall($type, $addressType);
+ $this->assertSame($addressType, $this->transformer->reverseTransform($type));
+ }
+
+ protected function assertRepositoryCall($type, $addressType)
+ {
+ $repository = $this->getMockBuilder('\Doctrine\Common\Persistence\ObjectRepository')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $repository->expects($this->once())
+ ->method('findOneBy')
+ ->with(array('type' => $type))
+ ->will($this->returnValue($addressType));
+
+ $this->om->expects($this->once())
+ ->method('getRepository')
+ ->with('OroAddressBundle:AddressType')
+ ->will($this->returnValue($repository));
+ }
+
+ protected function getAddressTypeMock($type)
+ {
+ $addressType = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\AddressType')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $addressType->expects($this->once())
+ ->method('getType')
+ ->will($this->returnValue($type));
+ return $addressType;
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/EventListener/AddressCollectionTypeSubscriberTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/EventListener/AddressCollectionTypeSubscriberTest.php
new file mode 100644
index 00000000000..60b32f34d42
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/EventListener/AddressCollectionTypeSubscriberTest.php
@@ -0,0 +1,206 @@
+subscriber = new AddressCollectionTypeSubscriber('test', '\Oro\Bundle\AddressBundle\Entity\TypedAddress');
+ }
+
+ public function testGetSubscribedEvents()
+ {
+ $result = $this->subscriber->getSubscribedEvents();
+
+ $this->assertInternalType('array', $result);
+ $this->assertArrayHasKey(FormEvents::PRE_SET_DATA, $result);
+ $this->assertArrayHasKey(FormEvents::PRE_BIND, $result);
+ $this->assertArrayHasKey(FormEvents::POST_BIND, $result);
+ }
+
+ public function testPreSetNotEmpty()
+ {
+ $addresses = $this->getMockBuilder('Doctrine\Common\Collections\Collection')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $addresses->expects($this->once())
+ ->method('isEmpty')
+ ->will($this->returnValue(false));
+ $addresses->expects($this->never())
+ ->method('add');
+ $this->subscriber->preSet($this->getEvent($addresses));
+ }
+
+ public function testPreSetEmpty()
+ {
+ $addresses = $this->getMockBuilder('Doctrine\Common\Collections\Collection')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $addresses->expects($this->once())
+ ->method('isEmpty')
+ ->will($this->returnValue(true));
+ $addresses->expects($this->once())
+ ->method('add')
+ ->with($this->isInstanceOf('Oro\Bundle\AddressBundle\Entity\TypedAddress'));
+ $this->subscriber->preSet($this->getEvent($addresses));
+ }
+
+ public function testPostBind()
+ {
+ $addressEmpty = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\TypedAddress')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $addressEmpty->expects($this->once())
+ ->method('isEmpty')
+ ->will($this->returnValue(true));
+ $addressNotEmpty = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\TypedAddress')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $addressNotEmpty->expects($this->once())
+ ->method('isEmpty')
+ ->will($this->returnValue(false));
+
+ $iterator = new \ArrayIterator(array($addressEmpty, $addressNotEmpty));
+ $addresses = $this->getMockBuilder('Doctrine\Common\Collections\Collection')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $addresses->expects($this->once())
+ ->method('getIterator')
+ ->will($this->returnValue($iterator));
+ $addresses->expects($this->once())
+ ->method('removeElement')
+ ->with($addressEmpty);
+ $this->subscriber->postBind($this->getEvent($addresses));
+ }
+
+ protected function getEvent($collection)
+ {
+ $data = $this->getMockBuilder('\stdClass')
+ ->setMethods(array('getTest'))
+ ->getMock();
+ $data->expects($this->once())
+ ->method('getTest')
+ ->will($this->returnValue($collection));
+
+ $event = $this->getMockBuilder('Symfony\Component\Form\FormEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $event->expects($this->once())
+ ->method('getData')
+ ->will($this->returnValue($data));
+ return $event;
+ }
+
+ /**
+ * @dataProvider noDataPreBindDataProvider
+ * @param array|null $data
+ */
+ public function testPreBindNoData($data)
+ {
+ $event = $this->getMockBuilder('Symfony\Component\Form\FormEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $event->expects($this->once())
+ ->method('getData')
+ ->will($this->returnValue($data));
+ $event->expects($this->never())
+ ->method('setData');
+ $this->subscriber->preBind($event);
+ }
+
+ /**
+ * @return array
+ */
+ public function noDataPreBindDataProvider()
+ {
+ return array(
+ array(
+ null, array()
+ ),
+ array(
+ array(), array()
+ )
+ );
+ }
+
+ /**
+ * @dataProvider preBindDataProvider
+ * @param array|null $data
+ * @param array $expected
+ */
+ public function testPreBind($data, $expected)
+ {
+ $event = $this->getMockBuilder('Symfony\Component\Form\FormEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $event->expects($this->once())
+ ->method('getData')
+ ->will($this->returnValue($data));
+ $event->expects($this->once())
+ ->method('setData')
+ ->with($expected);
+ $this->subscriber->preBind($event);
+ }
+
+ public function preBindDataProvider()
+ {
+ return array(
+ array(
+ array('key' => 'value', 'test' => array(array(), array('k' => 'v'))),
+ array('key' => 'value', 'test' => array(array('k' => 'v', 'primary' => true)))
+ ),
+ array(
+ array('key' => 'value', 'test' => array(array(array()), array('k' => 'v'))),
+ array('key' => 'value', 'test' => array(array('k' => 'v', 'primary' => true)))
+ ),
+ array(
+ array('key' => 'value', 'test' => array(array(array('k2' => 'v')), array('k' => 'v'))),
+ array('key' => 'value', 'test' => array(array(array('k2' => 'v'), 'primary' => true), array('k' => 'v')))
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider preBindNoResetDataProvider
+ * @param array $data
+ */
+ public function testPreBindNoReset($data)
+ {
+ $event = $this->getMockBuilder('Symfony\Component\Form\FormEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $event->expects($this->once())
+ ->method('getData')
+ ->will($this->returnValue($data));
+ $event->expects($this->never())
+ ->method('setData');
+ $this->subscriber->preBind($event);
+ }
+
+ /**
+ * @return array
+ */
+ public function preBindNoResetDataProvider()
+ {
+ return array(
+ array(
+ array('key' => 'value')
+ ),
+ array(
+ array('key' => 'value', 'test' => array())
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/EventListener/BuildAddressFormListenerTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/EventListener/BuildAddressFormListenerTest.php
index 6604a6f00b7..56183697c96 100644
--- a/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/EventListener/BuildAddressFormListenerTest.php
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/EventListener/BuildAddressFormListenerTest.php
@@ -79,7 +79,7 @@ public function testPreSetDataHasState()
->disableOriginalConstructor()
->getMock();
- $countryMock = $this->getMock('Oro\Bundle\AddressBundle\Entity\Country');
+ $countryMock = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\Country')->disableOriginalConstructor()->getMock();
$countryMock->expects($this->once())
->method('hasRegions')
->will($this->returnValue(true));
@@ -142,7 +142,7 @@ public function testPreSetDataNoState()
->disableOriginalConstructor()
->getMock();
- $countryMock = $this->getMock('Oro\Bundle\AddressBundle\Entity\Country');
+ $countryMock = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\Country')->disableOriginalConstructor()->getMock();
$countryMock->expects($this->once())
->method('hasRegions')
->will($this->returnValue(true));
@@ -190,7 +190,7 @@ public function testPreBindData()
->disableOriginalConstructor()
->getMock();
- $countryMock = $this->getMock('Oro\Bundle\AddressBundle\Entity\Country');
+ $countryMock = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\Country')->disableOriginalConstructor()->getMock();
$countryMock->expects($this->once())
->method('hasRegions')
->will($this->returnValue(true));
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/AddressCollectionTypeTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/AddressCollectionTypeTest.php
new file mode 100644
index 00000000000..776428744c1
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/AddressCollectionTypeTest.php
@@ -0,0 +1,42 @@
+type = new AddressCollectionType();
+ }
+
+ public function testSetDefaultOptions()
+ {
+ /** @var OptionsResolverInterface $resolver */
+ $resolver = $this->getMock('Symfony\Component\OptionsResolver\OptionsResolverInterface');
+ $resolver->expects($this->once())
+ ->method('setDefaults')
+ ->with($this->isType('array'));
+ $this->type->setDefaultOptions($resolver);
+ }
+
+ public function testGetParent()
+ {
+ $this->assertEquals('collection', $this->type->getParent());
+ }
+
+ public function testGetName()
+ {
+ $this->assertEquals('oro_address_collection', $this->type->getName());
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/AddressTypedTypeTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/AddressTypedTypeTest.php
new file mode 100644
index 00000000000..996aaad85fa
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/AddressTypedTypeTest.php
@@ -0,0 +1,55 @@
+getMockBuilder('Oro\Bundle\AddressBundle\Form\EventListener\BuildAddressFormListener')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $flexibleManager = $this->getMockBuilder('Oro\Bundle\FlexibleEntityBundle\Manager\FlexibleManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->type = new AddressTypedType(
+ $flexibleManager,
+ 'oro_address_value',
+ $buildAddressFormListener
+ );
+ }
+
+ public function testAddEntityFields()
+ {
+ $builder = $this->getMockBuilder('Symfony\Component\Form\FormBuilder')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $builder->expects($this->any())
+ ->method('add')
+ ->will($this->returnSelf());
+ $builder->expects($this->at(0))
+ ->method('add')
+ ->with(
+ 'type',
+ 'entity',
+ $this->isType('array')
+ );
+ $this->type->addEntityFields($builder);
+ }
+
+ public function testGetName()
+ {
+ $this->assertEquals('oro_address_typed', $this->type->getName());
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/CountryTypeTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/CountryTypeTest.php
index 75581c05c39..8c5c6b2a409 100644
--- a/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/CountryTypeTest.php
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/CountryTypeTest.php
@@ -35,7 +35,7 @@ public function testSetDefaultOptions()
public function testGetParent()
{
- $this->assertEquals('entity', $this->type->getParent());
+ $this->assertEquals('genemu_jqueryselect2_translatable_entity', $this->type->getParent());
}
public function testGetName()
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/RegionTypeTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/RegionTypeTest.php
index f53a853c2a4..ee8c608f41a 100644
--- a/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/RegionTypeTest.php
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Form/Type/RegionTypeTest.php
@@ -1,7 +1,8 @@
getMock('Symfony\Component\OptionsResolver\OptionsResolverInterface');
$resolver->expects($this->once())
->method('setDefaults')
@@ -35,7 +35,7 @@ public function testSetDefaultOptions()
public function testGetParent()
{
- $this->assertEquals('choice', $this->type->getParent());
+ $this->assertEquals('genemu_jqueryselect2_translatable_entity', $this->type->getParent());
}
public function testGetName()
@@ -58,15 +58,28 @@ public function testBuildForm()
public function testFinishView()
{
- $formViewMock = $this->getMock('Symfony\Component\Form\FormView');
+ $optionKey = 'countryFieldName';
+
+ $formConfigMock = $this->getMockBuilder('Symfony\Component\Form\FormConfigInterface')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getAttribute'))
+ ->getMockForAbstractClass();
+ $formConfigMock->expects($this->once())
+ ->method('getAttribute')
+ ->with($this->equalTo(RegionType::COUNTRY_OPTION_KEY))
+ ->will($this->returnValue($optionKey));
+
$formMock = $this->getMockBuilder('Symfony\Component\Form\Form')
->disableOriginalConstructor()
+ ->setMethods(array('getConfig'))
->getMock();
$formMock->expects($this->once())
- ->method('getAttribute')
- ->with($this->equalTo(RegionType::COUNTRY_OPTION_KEY))
- ->will($this->returnValue(''));
+ ->method('getConfig')
+ ->will($this->returnValue($formConfigMock));
- $this->type->finishView($formViewMock, $formMock, array());
+ $formView = new FormView();
+ $this->type->finishView($formView, $formMock, array());
+ $this->assertArrayHasKey('country_field', $formView->vars);
+ $this->assertEquals($optionKey, $formView->vars['country_field']);
}
}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Provider/ImportExport/DbReaderTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Provider/ImportExport/DbReaderTest.php
deleted file mode 100644
index 31197357576..00000000000
--- a/src/Oro/Bundle/AddressBundle/Tests/Unit/Provider/ImportExport/DbReaderTest.php
+++ /dev/null
@@ -1,102 +0,0 @@
-class = 'Oro\Bundle\AddressBundle\Entity\Country';
- $this->om = $this->getMock('Doctrine\Common\Persistence\ObjectManager');
-
- $classMetaData = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')
- ->disableOriginalConstructor()
- ->getMock();
-
- $classMetaData
- ->expects($this->once())
- ->method('getName')
- ->with()
- ->will($this->returnValue($this->class));
-
- $this->om
- ->expects($this->once())
- ->method('getClassMetadata')
- ->with($this->equalTo($this->class))
- ->will($this->returnValue($classMetaData));
-
-
- $this->reader = new ImportExport\DbReader($this->class, $this->om, $this->batchSize);
- }
-
- /**
- * Test setting limits
- */
- public function testSettingBatchLimit()
- {
- $this->assertEquals($this->batchSize, $this->reader->getBatchSize());
- }
-
- /**
- * Test read batch
- */
- public function testDbReader()
- {
- $repository = $this->getMock('Doctrine\Common\Persistence\ObjectRepository');
- $repository
- ->expects($this->exactly(3))
- ->method('findBy')
- ->with(
- $this->equalTo(array()),
- $this->equalTo(array()),
- $this->batchSize,
- $this->logicalOr(0, $this->batchSize)
- )
- ->will(
- $this->returnValue(
- array(
- new Country(),
- )
- )
- );
-
- $this->om
- ->expects($this->any())
- ->method('getRepository')
- ->with($this->equalTo($this->class))
- ->will($this->returnValue($repository));
-
- $this->reader->readBatch();
- $this->reader->readBatch();
-
- $this->reader->reset();
- $this->reader->readBatch();
- }
-}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Provider/ImportExport/DbWriterTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Provider/ImportExport/DbWriterTest.php
deleted file mode 100644
index 8246875c8b0..00000000000
--- a/src/Oro/Bundle/AddressBundle/Tests/Unit/Provider/ImportExport/DbWriterTest.php
+++ /dev/null
@@ -1,64 +0,0 @@
-om = $this->getMock('Doctrine\Common\Persistence\ObjectManager');
- $this->writer = new ImportExport\DbWriter($this->om);
- }
-
- /**
- * Test write batch
- */
- public function testWriter()
- {
- $data = array(
- new Country('Ukraine', 'UA', 'UKR'),
- new Country('United States of America', 'US', 'USA'),
- new Country('Russian Federation', 'RU', 'RUS'),
- );
-
- $this->om
- ->expects($this->exactly(count($data)))
- ->method('persist')
- ->with($this->containsOnlyInstancesOf('Country'));
-
- $this->om
- ->expects($this->once())
- ->method('flush');
-
- $this->writer->writeBatch($data);
- }
-
- /**
- * Test exception on not valid write
- *
- * @expectedException \Exception
- */
- public function testEmptyWrite()
- {
- $this->assertFalse($this->writer->writeBatch(array()));
-
- $this->writer->writeBatch(array(1));
- }
-}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Provider/ImportExport/IntlReaderTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Provider/ImportExport/IntlReaderTest.php
deleted file mode 100644
index fee5ea0a037..00000000000
--- a/src/Oro/Bundle/AddressBundle/Tests/Unit/Provider/ImportExport/IntlReaderTest.php
+++ /dev/null
@@ -1,61 +0,0 @@
-class = 'Oro\Bundle\AddressBundle\Entity\Country';
-
- $this->reader = new ImportExport\IntlReader($this->class, $this->batchSize);
- }
-
- /**
- * Test setting limits
- */
- public function testSettingBatchLimit()
- {
- $this->assertEquals($this->batchSize, $this->reader->getBatchSize());
- }
-
- /**
- * Test read batch
- */
- public function testReader()
- {
- $data = $this->reader->readBatch();
- $this->assertInternalType('array', $data);
- $this->assertCount($this->batchSize, $data);
-
- $this->reader->reset();
- $data2 = $this->reader->readBatch();
-
- $this->assertEquals($data, $data2);
-
- $this->reader->readBatch();
- $this->assertFalse($this->reader->readBatch());
- }
-}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Provider/ImportExport/ManagerTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Provider/ImportExport/ManagerTest.php
deleted file mode 100644
index 030c9dd8694..00000000000
--- a/src/Oro/Bundle/AddressBundle/Tests/Unit/Provider/ImportExport/ManagerTest.php
+++ /dev/null
@@ -1,92 +0,0 @@
-writer = $this->getMock('Oro\Bundle\AddressBundle\Provider\ImportExport\WriterInterface');
- $this->reader = $this->getMock('Oro\Bundle\AddressBundle\Provider\ImportExport\ReaderInterface');
- }
-
- /**
- * Test sync with reader and writer
- */
- public function testSync()
- {
- $countryMock = $this->getMock('Oro\Bundle\AddressBundle\Entity\Country');
-
- $this->reader
- ->expects($this->exactly(2))
- ->method('readBatch')
- ->will(
- $this->onConsecutiveCalls(
- $countryMock, // first batch return
- false // second batch return
- )
- );
-
- $this->writer
- ->expects($this->once())
- ->method('writeBatch')
- ->with($this->equalTo($countryMock))
- ->will($this->returnValue(true));
-
- /**
- * @var ImportExport\Manager
- */
- $manager = new ImportExport\Manager($this->writer, $this->reader);
- $manager->sync();
- }
-
- /**
- * Test sync for array data without reader
- */
- public function testArraySync()
- {
- $countryMock = $this->getMock('Oro\Bundle\AddressBundle\Entity\Country');
- $data = array($countryMock);
-
- $this->writer
- ->expects($this->once())
- ->method('writeBatch')
- ->with($this->equalTo($data))
- ->will($this->returnValue(true));
-
- /**
- * @var ImportExport\Manager
- */
- $manager = new ImportExport\Manager($this->writer);
- $manager->sync($data);
- }
-
- /**
- * Test exception
- *
- * @expectedException \Exception
- */
- public function testExceptionSync()
- {
- /**
- * @var ImportExport\Manager
- */
- $manager = new ImportExport\Manager($this->writer);
- $manager->sync();
- }
-}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Twig/HasAddressExtensionTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Twig/HasAddressExtensionTest.php
new file mode 100644
index 00000000000..b30a6db8d04
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Twig/HasAddressExtensionTest.php
@@ -0,0 +1,112 @@
+extension = new HasAddressExtension();
+ $this->entityMock = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Entity\Mapping\AbstractEntityFlexible');
+ $this->valuesMock = $this->getMock('Doctrine\Common\Collections\ArrayCollection');
+ $this->valueMock = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Model\FlexibleValueInterface');
+ }
+
+ public function testGetName()
+ {
+ $this->assertEquals('oro_address_hasAddress', $this->extension->getName());
+ }
+
+ public function testGetFilters()
+ {
+ $filters = $this->extension->getFilters();
+
+ $this->assertArrayHasKey('hasAddress', $filters);
+ $this->assertInstanceOf('\Twig_Filter_Method', $filters['hasAddress']);
+ }
+
+ public function testHasAddressPositiveScenario()
+ {
+ $this->valueMock->expects($this->once())
+ ->method('getData')
+ ->will($this->returnValue(true));
+
+ $this->entityMock->expects($this->once())
+ ->method('getValue')
+ ->with($this->equalTo('address'))
+ ->will($this->returnValue($this->valueMock));
+
+ $this->assertTrue($this->extension->hasAddress($this->entityMock, 'address'));
+ }
+
+ public function testHasAddressNegativeScenario()
+ {
+ $this->valueMock->expects($this->once())
+ ->method('getData')
+ ->will($this->returnValue(null));
+
+ $this->entityMock->expects($this->once())
+ ->method('getValue')
+ ->with($this->equalTo('address'))
+ ->will($this->returnValue($this->valueMock));
+
+ $this->assertFalse($this->extension->hasAddress($this->entityMock, 'address'));
+ }
+
+ public function testHasAddressPositiveScenarioWithoutCode()
+ {
+ $this->entityMock->expects($this->once())
+ ->method('getValues')
+ ->will($this->returnValue($this->valuesMock));
+
+ $this->valuesMock->expects($this->once())
+ ->method('filter')
+ ->will($this->returnValue($this->valuesMock));
+ $this->valuesMock->expects($this->once())
+ ->method('isEmpty')
+ ->will($this->returnValue(false));
+
+ $this->assertTrue($this->extension->hasAddress($this->entityMock));
+ }
+
+ public function testHasAddressNegativeScenarioWithoutCode()
+ {
+ $this->entityMock->expects($this->once())
+ ->method('getValues')
+ ->will($this->returnValue($this->valuesMock));
+
+ $this->valuesMock->expects($this->once())
+ ->method('filter')
+ ->will($this->returnValue($this->valuesMock));
+ $this->valuesMock->expects($this->once())
+ ->method('isEmpty')
+ ->will($this->returnValue(true));
+
+ $this->assertFalse($this->extension->hasAddress($this->entityMock));
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Tests/Unit/Validator/Constraints/ContainsPrimaryValidatorTest.php b/src/Oro/Bundle/AddressBundle/Tests/Unit/Validator/Constraints/ContainsPrimaryValidatorTest.php
new file mode 100644
index 00000000000..44214fb898f
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Tests/Unit/Validator/Constraints/ContainsPrimaryValidatorTest.php
@@ -0,0 +1,121 @@
+getMock('Symfony\Component\Validator\Constraint');
+ $validator = new ContainsPrimaryValidator();
+ $validator->validate(false, $constraint);
+ }
+
+ /**
+ * @dataProvider validAddressesDataProvider
+ * @param array $addresses
+ */
+ public function testValidateValid($addresses)
+ {
+ $context = $this->getMockBuilder('Symfony\Component\Validator\ExecutionContext')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $context->expects($this->never())
+ ->method('addViolation');
+
+ $constraint = $this->getMock('Oro\Bundle\AddressBundle\Validator\Constraints\ContainsPrimary');
+ $validator = new ContainsPrimaryValidator();
+ $validator->initialize($context);
+
+ $validator->validate($addresses, $constraint);
+ }
+
+ /**
+ * @return array
+ */
+ public function validAddressesDataProvider()
+ {
+ return array(
+ 'no addresses' => array(
+ array()
+ ),
+ 'one address primary' => array(
+ array($this->getTypedAddressMock(true))
+ ),
+ 'more than one address with primary' => array(
+ array($this->getTypedAddressMock(false), $this->getTypedAddressMock(true))
+ ),
+ 'empty address' => array(
+ array($this->getTypedAddressMock(false, true), $this->getTypedAddressMock(false, true))
+ ),
+ 'empty address and primary' => array(
+ array($this->getTypedAddressMock(false, true), $this->getTypedAddressMock(true), $this->getTypedAddressMock(false, true))
+ )
+ );
+ }
+
+ /**
+ * @dataProvider invalidAddressesDataProvider
+ * @param array $addresses
+ */
+ public function testValidateInvalid($addresses)
+ {
+ $context = $this->getMockBuilder('Symfony\Component\Validator\ExecutionContext')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $context->expects($this->once())
+ ->method('addViolation')
+ ->with('One of addresses must be set as primary.');
+
+ $constraint = $this->getMock('Oro\Bundle\AddressBundle\Validator\Constraints\ContainsPrimary');
+ $validator = new ContainsPrimaryValidator();
+ $validator->initialize($context);
+
+ $validator->validate($addresses, $constraint);
+ }
+
+ /**
+ * @return array
+ */
+ public function invalidAddressesDataProvider()
+ {
+ return array(
+ 'one address' => array(
+ array($this->getTypedAddressMock(false))
+ ),
+ 'more than one address no primary' => array(
+ array($this->getTypedAddressMock(false), $this->getTypedAddressMock(false))
+ ),
+ 'more than one address more than one primary' => array(
+ array($this->getTypedAddressMock(true), $this->getTypedAddressMock(true))
+ ),
+ );
+ }
+
+ /**
+ * Get address mock.
+ *
+ * @param bool $isPrimary
+ * @param bool $isEmpty
+ * @return \PHPUnit_Framework_MockObject_MockObject
+ */
+ protected function getTypedAddressMock($isPrimary, $isEmpty = false)
+ {
+ $address = $this->getMockBuilder('Oro\Bundle\AddressBundle\Entity\TypedAddress')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $address->expects($this->any())
+ ->method('isPrimary')
+ ->will($this->returnValue($isPrimary));
+ $address->expects($this->once())
+ ->method('isEmpty')
+ ->will($this->returnValue($isEmpty));
+ return $address;
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Twig/HasAddressExtension.php b/src/Oro/Bundle/AddressBundle/Twig/HasAddressExtension.php
new file mode 100644
index 00000000000..bdb44400038
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Twig/HasAddressExtension.php
@@ -0,0 +1,55 @@
+ new \Twig_Filter_Method($this, 'hasAddress')
+ );
+ }
+
+ /**
+ * Check whenever flexible entity contains not empty address attribute
+ *
+ * @param \Oro\Bundle\FlexibleEntityBundle\Entity\Mapping\AbstractEntityFlexible $entity
+ * @param null $addressCode
+ * @return bool
+ */
+ public function hasAddress(AbstractEntityFlexible $entity, $addressCode = null)
+ {
+ if ($addressCode !== null) {
+ $address = $entity->getValue($addressCode);
+
+ return $address->getData() != null;
+ }
+
+ /** @var \Doctrine\Common\Collections\ArrayCollection $values **/
+ $values = $entity->getValues();
+ $values = $values->filter(
+ function ($value) {
+ if (strpos($value->getAttribute()->getCode(), 'address') !== false) {
+ return $value->getData() != null;
+ }
+
+ return false;
+ }
+ );
+ return !$values->isEmpty();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'oro_address_hasAddress';
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/Validator/Constraints/ContainsPrimary.php b/src/Oro/Bundle/AddressBundle/Validator/Constraints/ContainsPrimary.php
new file mode 100644
index 00000000000..b69b3e8e904
--- /dev/null
+++ b/src/Oro/Bundle/AddressBundle/Validator/Constraints/ContainsPrimary.php
@@ -0,0 +1,13 @@
+isEmpty()) {
+ if ($item instanceof TypedAddress && $item->isPrimary()) {
+ $primaryItemsNumber++;
+ }
+ $totalItemsNumber++;
+ }
+ }
+
+ if ($totalItemsNumber > 0 && $primaryItemsNumber != 1) {
+ $this->context->addViolation($constraint->message);
+ }
+ }
+}
diff --git a/src/Oro/Bundle/AddressBundle/composer.json b/src/Oro/Bundle/AddressBundle/composer.json
index 1de58a3bc06..ea61775cf34 100644
--- a/src/Oro/Bundle/AddressBundle/composer.json
+++ b/src/Oro/Bundle/AddressBundle/composer.json
@@ -8,12 +8,11 @@
"require": {
"php": ">=5.3.3",
"symfony/symfony": "2.1.*",
- "symfony/icu": "1.2.*@dev",
- "symfony/intl": "2.3.*@dev",
"friendsofsymfony/rest-bundle": "0.11.*",
"friendsofsymfony/jsrouting-bundle": "1.1.*@dev",
"nelmio/api-doc-bundle": "dev-master",
"oro/flexible-entity-bundle": "dev-master",
+ "oro/form-bundle": "dev-master",
"besimple/soap-bundle": "dev-master"
},
"autoload": {
diff --git a/src/Oro/Bundle/ConfigBundle/DependencyInjection/Configuration.php b/src/Oro/Bundle/ConfigBundle/DependencyInjection/Configuration.php
index 4612d396be3..0f01cdf50a8 100644
--- a/src/Oro/Bundle/ConfigBundle/DependencyInjection/Configuration.php
+++ b/src/Oro/Bundle/ConfigBundle/DependencyInjection/Configuration.php
@@ -13,7 +13,18 @@ class Configuration implements ConfigurationInterface
public function getConfigTreeBuilder()
{
$builder = new TreeBuilder();
- $root = $builder->root('oro_config');
+ $root = $builder
+ ->root('oro_config')
+ ->children()
+ ->arrayNode('entity_output')
+ ->prototype('array')
+ ->children()
+ ->scalarNode('icon_class')->end()
+ ->scalarNode('name')->end()
+ ->scalarNode('description')->end()
+ ->end()
+ ->end()
+ ->end();
return $builder;
}
diff --git a/src/Oro/Bundle/ConfigBundle/DependencyInjection/OroConfigExtension.php b/src/Oro/Bundle/ConfigBundle/DependencyInjection/OroConfigExtension.php
index 236f2f6aed7..525c720a09e 100644
--- a/src/Oro/Bundle/ConfigBundle/DependencyInjection/OroConfigExtension.php
+++ b/src/Oro/Bundle/ConfigBundle/DependencyInjection/OroConfigExtension.php
@@ -3,9 +3,10 @@
namespace Oro\Bundle\ConfigBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
-use Symfony\Component\DependencyInjection\Loader;
+use Symfony\Component\Yaml\Yaml;
/**
* This is the class that loads and manages your bundle configuration
@@ -19,10 +20,25 @@ class OroConfigExtension extends Extension
*/
public function load(array $configs, ContainerBuilder $container)
{
+ $data = array();
+
+ foreach ($container->getParameter('kernel.bundles') as $bundle) {
+ $reflection = new \ReflectionClass($bundle);
+
+ if (file_exists($file = dirname($reflection->getFilename()) . '/Resources/config/entity_output.yml')) {
+ $data = array_merge($data, Yaml::parse(realpath($file)));
+ }
+ }
+
+ $configs[] = array('entity_output' => $data);
$configuration = new Configuration();
+
$config = $this->processConfiguration($configuration, $configs);
- $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
+ $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
+
$loader->load('services.yml');
+
+ $container->setParameter('oro_config.entities', $data);
}
}
diff --git a/src/Oro/Bundle/ConfigBundle/DependencyInjection/SettingsBuilder.php b/src/Oro/Bundle/ConfigBundle/DependencyInjection/SettingsBuilder.php
index 81ffbd0d360..f4f402df898 100644
--- a/src/Oro/Bundle/ConfigBundle/DependencyInjection/SettingsBuilder.php
+++ b/src/Oro/Bundle/ConfigBundle/DependencyInjection/SettingsBuilder.php
@@ -35,12 +35,10 @@ public static function append(ArrayNodeDefinition $root, $settings)
$child->scalarNode('value')->defaultValue($setting['value']);
break;
-
case 'boolean':
$child->booleanNode('value')->defaultValue((bool) $setting['value']);
break;
-
case 'array':
$child->arrayNode('value');
diff --git a/src/Oro/Bundle/ConfigBundle/README.md b/src/Oro/Bundle/ConfigBundle/README.md
index 05fd162cb10..c63b659bed9 100644
--- a/src/Oro/Bundle/ConfigBundle/README.md
+++ b/src/Oro/Bundle/ConfigBundle/README.md
@@ -40,7 +40,8 @@ $ phpunit --coverage-html=cov/
```
## Usage ##
-In your controllers you can access different Oro settings using different scopes.
+### Controller ###
+You can access different Oro settings using different scopes.
**Note:** Currently, only `oro_config.user` scope implemented.
@@ -85,4 +86,35 @@ public function getConfigTreeBuilder()
}
```
-`type` above could be `scalar` (which is default) or `boolean`.
\ No newline at end of file
+`type` above could be `scalar` (which is default) or `boolean`.
+
+### View ###
+
+```
+{% set format = oro_config_value('oro_anybundle.anysetting') %}
+```
+
+### Entity ###
+It is possible to configure entity output through the yaml config file named `entity_output.yml`. Sample syntax:
+
+``` yaml
+Acme\Bundle\MyBundle\Entity\MyEntity:
+ icon_class: icon-entity
+ name: entity.myentity.name
+ description: entity.myentity.description
+```
+
+To make name and description translatable, add `translations/config.{locale}.yml` file:
+
+``` yaml
+entity:
+ myentity:
+ name: My entity
+ description: My entity description
+```
+
+Then, you can use customized entity parameters in views:
+
+```
+{{ oro_config_entity('Acme\\Bundle\\MyBundle\\Entity\\MyEntity').name|trans({}, 'config') }}
+```
diff --git a/src/Oro/Bundle/ConfigBundle/Resources/config/services.yml b/src/Oro/Bundle/ConfigBundle/Resources/config/services.yml
index 7ceef9efdb9..ea40dd3b1d3 100644
--- a/src/Oro/Bundle/ConfigBundle/Resources/config/services.yml
+++ b/src/Oro/Bundle/ConfigBundle/Resources/config/services.yml
@@ -13,6 +13,6 @@ services:
oro_config.twig.config_extension:
class: %oro_config.twig_extension.class%
- arguments: ["@oro_config.user"]
+ arguments: ["@oro_config.user", %oro_config.entities%]
tags:
- { name: twig.extension }
diff --git a/src/Oro/Bundle/ConfigBundle/Tests/Unit/Config/UserConfigManagerTest.php b/src/Oro/Bundle/ConfigBundle/Tests/Unit/Config/UserConfigManagerTest.php
index 97546fb18e3..da21724617e 100644
--- a/src/Oro/Bundle/ConfigBundle/Tests/Unit/Config/UserConfigManagerTest.php
+++ b/src/Oro/Bundle/ConfigBundle/Tests/Unit/Config/UserConfigManagerTest.php
@@ -112,10 +112,8 @@ function ($param) use ($configUser, $configGroup) {
switch ($param['recordId']) {
case 1:
return $configUser;
-
case 2:
return $configGroup;
-
case 3:
return null;
}
diff --git a/src/Oro/Bundle/ConfigBundle/Tests/Unit/DependencyInjection/OroConfigExtensionTest.php b/src/Oro/Bundle/ConfigBundle/Tests/Unit/DependencyInjection/OroConfigExtensionTest.php
index 7d737af75b1..46b692deb95 100644
--- a/src/Oro/Bundle/ConfigBundle/Tests/Unit/DependencyInjection/OroConfigExtensionTest.php
+++ b/src/Oro/Bundle/ConfigBundle/Tests/Unit/DependencyInjection/OroConfigExtensionTest.php
@@ -28,6 +28,8 @@ protected function createEmptyConfiguration()
{
$this->configuration = new ContainerBuilder();
+ $this->configuration->setParameter('kernel.bundles', array());
+
$loader = new OroConfigExtension();
$config = $this->getEmptyConfig();
@@ -59,10 +61,10 @@ protected function assertParameter($value, $key)
protected function getContainer(array $config = array())
{
$container = new ContainerBuilder();
- $container->addCompilerPass(new Compiler\ConfigPass());
-
- $loader = new OroConfigExtension();
+ $loader = new OroConfigExtension();
+ $container->addCompilerPass(new Compiler\ConfigPass());
+ $container->setParameter('kernel.bundles', array());
$loader->load($config, $container);
$container->register('doctrine.orm.entity_manager', $this->getMockClass('Doctrine\Common\Persistence\ObjectManager'));
diff --git a/src/Oro/Bundle/ConfigBundle/Tests/Unit/DependencyInjection/SettingsBuilderTest.php b/src/Oro/Bundle/ConfigBundle/Tests/Unit/DependencyInjection/SettingsBuilderTest.php
index 4a6be1160b7..634dee05939 100644
--- a/src/Oro/Bundle/ConfigBundle/Tests/Unit/DependencyInjection/SettingsBuilderTest.php
+++ b/src/Oro/Bundle/ConfigBundle/Tests/Unit/DependencyInjection/SettingsBuilderTest.php
@@ -3,7 +3,6 @@
namespace Oro\Bundle\ConfigBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
-use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition;
class SettingsBuilderTest extends \PHPUnit_Framework_TestCase
{
diff --git a/src/Oro/Bundle/ConfigBundle/Twig/ConfigExtension.php b/src/Oro/Bundle/ConfigBundle/Twig/ConfigExtension.php
index c506955ae61..dffbb8ec8de 100644
--- a/src/Oro/Bundle/ConfigBundle/Twig/ConfigExtension.php
+++ b/src/Oro/Bundle/ConfigBundle/Twig/ConfigExtension.php
@@ -11,9 +11,15 @@ class ConfigExtension extends \Twig_Extension
*/
protected $userConfigManager;
- public function __construct(UserConfigManager $userConfigManager)
+ /**
+ * @var array
+ */
+ protected $entityOutput;
+
+ public function __construct(UserConfigManager $userConfigManager, $entityOutput = array())
{
$this->userConfigManager = $userConfigManager;
+ $this->entityOutput = $entityOutput;
}
/**
@@ -24,7 +30,8 @@ public function __construct(UserConfigManager $userConfigManager)
public function getFunctions()
{
return array(
- 'get_user_value' => new \Twig_Function_Method($this, 'getUserValue'),
+ 'oro_config_value' => new \Twig_Function_Method($this, 'getUserValue'),
+ 'oro_config_entity' => new \Twig_Function_Method($this, 'getEntityOutput'),
);
}
@@ -37,6 +44,28 @@ public function getUserValue($name)
return $this->userConfigManager->get($name);
}
+ /**
+ * Get entity output config (if any provided).
+ * Provided parameters:
+ * "icon_class" - CSS class name for icon element
+ * "name" - custom entity name
+ * "description" - entity description
+ *
+ * @param string $class FQCN of the entity
+ * @return array
+ */
+ public function getEntityOutput($class)
+ {
+ $default = explode('\\', $class);
+
+ return isset($this->entityOutput[$class])
+ ? $this->entityOutput[$class]
+ : array(
+ 'icon_class' => '',
+ 'name' => end($default),
+ 'description' => 'No description'
+ );
+ }
/**
* Returns the name of the extension.
diff --git a/src/Oro/Bundle/DataAuditBundle/Datagrid/AuditDatagridManager.php b/src/Oro/Bundle/DataAuditBundle/Datagrid/AuditDatagridManager.php
index fe7a3816fdc..da4f50788b4 100644
--- a/src/Oro/Bundle/DataAuditBundle/Datagrid/AuditDatagridManager.php
+++ b/src/Oro/Bundle/DataAuditBundle/Datagrid/AuditDatagridManager.php
@@ -4,7 +4,7 @@
use Doctrine\ORM\Query;
-use Gedmo\Loggable\LoggableListener;
+use Oro\Bundle\DataAuditBundle\Loggable\LoggableManager;
use Oro\Bundle\GridBundle\Datagrid\DatagridManager;
use Oro\Bundle\GridBundle\Field\FieldDescription;
@@ -35,6 +35,7 @@ class AuditDatagridManager extends DatagridManager
/**
* {@inheritDoc}
+ * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
protected function configureFields(FieldDescriptionCollection $fieldsCollection)
{
@@ -51,9 +52,9 @@ protected function configureFields(FieldDescriptionCollection $fieldsCollection)
'filterable' => true,
'show_filter' => true,
'choices' => array(
- LoggableListener::ACTION_UPDATE => 'Updated',
- LoggableListener::ACTION_CREATE => 'Created',
- LoggableListener::ACTION_REMOVE => 'Deleted',
+ LoggableManager::ACTION_UPDATE => 'Updated',
+ LoggableManager::ACTION_CREATE => 'Created',
+ LoggableManager::ACTION_REMOVE => 'Deleted',
),
'multiple' => true,
)
diff --git a/src/Oro/Bundle/DataAuditBundle/DependencyInjection/OroDataAuditExtension.php b/src/Oro/Bundle/DataAuditBundle/DependencyInjection/OroDataAuditExtension.php
index b60f3d24bbf..a5857c84ae7 100644
--- a/src/Oro/Bundle/DataAuditBundle/DependencyInjection/OroDataAuditExtension.php
+++ b/src/Oro/Bundle/DataAuditBundle/DependencyInjection/OroDataAuditExtension.php
@@ -16,5 +16,6 @@ public function load(array $configs, ContainerBuilder $container)
{
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('datagrid.yml');
+ $loader->load('services.yml');
}
}
diff --git a/src/Oro/Bundle/DataAuditBundle/Entity/Audit.php b/src/Oro/Bundle/DataAuditBundle/Entity/Audit.php
index d3bd395080b..e5900cad804 100644
--- a/src/Oro/Bundle/DataAuditBundle/Entity/Audit.php
+++ b/src/Oro/Bundle/DataAuditBundle/Entity/Audit.php
@@ -12,7 +12,7 @@
use Oro\Bundle\UserBundle\Entity\User;
/**
- * @ORM\Entity
+ * @ORM\Entity(repositoryClass="Gedmo\Loggable\Entity\Repository\LogEntryRepository")
* @ORM\Table(name="oro_audit")
*/
class Audit extends AbstractLogEntry
@@ -92,7 +92,7 @@ class Audit extends AbstractLogEntry
/**
* @var User $user
*
- * @ORM\ManyToOne(targetEntity="Oro\Bundle\UserBundle\Entity\User")
+ * @ORM\ManyToOne(targetEntity="Oro\Bundle\UserBundle\Entity\User", cascade={"persist"})
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
* @Type("string")
* @Soap\ComplexType("string", nillable=true)
diff --git a/src/Oro/Bundle/DataAuditBundle/Entity/AuditableInterface.php b/src/Oro/Bundle/DataAuditBundle/Entity/AuditableInterface.php
deleted file mode 100644
index 2467ae7fd7c..00000000000
--- a/src/Oro/Bundle/DataAuditBundle/Entity/AuditableInterface.php
+++ /dev/null
@@ -1,18 +0,0 @@
- "stringifiedValue"
- * ...
- * )
- */
- public function setAuditData();
-}
\ No newline at end of file
diff --git a/src/Oro/Bundle/DataAuditBundle/EventListener/EntitySubscriber.php b/src/Oro/Bundle/DataAuditBundle/EventListener/EntitySubscriber.php
new file mode 100644
index 00000000000..7ed761dfb3b
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/EventListener/EntitySubscriber.php
@@ -0,0 +1,73 @@
+metadataFactory = $metadataFactory;
+ $this->loggableManager = $loggableManager;
+ }
+
+ /**
+ * @return array
+ */
+ public function getSubscribedEvents()
+ {
+ return array(
+ 'onFlush',
+ 'loadClassMetadata',
+ 'postPersist',
+ );
+ }
+
+ /**
+ * @param OnFlushEventArgs $event
+ */
+ public function onFlush(OnFlushEventArgs $event)
+ {
+ $this->loggableManager->handleLoggable($event->getEntityManager());
+ }
+
+ /**
+ * @param LoadClassMetadataEventArgs $event
+ */
+ public function loadClassMetadata(LoadClassMetadataEventArgs $event)
+ {
+ if ($metadata = $this->metadataFactory->extendLoadMetadataForClass($event->getClassMetadata())) {
+ $this->loggableManager->addConfig($metadata);
+ }
+ }
+
+ /**
+ * @param LifecycleEventArgs $event
+ */
+ public function postPersist(LifecycleEventArgs $event)
+ {
+ $this->loggableManager->handlePostPersist($event->getEntity(), $event->getEntityManager());
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/EventListener/KernelListener.php b/src/Oro/Bundle/DataAuditBundle/EventListener/KernelListener.php
new file mode 100644
index 00000000000..4d834ab280c
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/EventListener/KernelListener.php
@@ -0,0 +1,58 @@
+loggableManager = $loggableManager;
+ $this->securityContext = $securityContext;
+ }
+
+ /**
+ * @param GetResponseEvent $event
+ */
+ public function onKernelRequest(GetResponseEvent $event)
+ {
+ if (null === $this->securityContext) {
+ return;
+ }
+
+ $token = $this->securityContext->getToken();
+ if (null !== $token && $this->securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
+ $this->loggableManager->setUsername($token);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::REQUEST => 'onKernelRequest',
+ );
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/EventListener/LoggableListener.php b/src/Oro/Bundle/DataAuditBundle/EventListener/LoggableListener.php
deleted file mode 100644
index 17397b2c6bf..00000000000
--- a/src/Oro/Bundle/DataAuditBundle/EventListener/LoggableListener.php
+++ /dev/null
@@ -1,242 +0,0 @@
-getEventAdapter($eventArgs)->getObjectManager();
-
- foreach ($this->loggedObjects as &$lo) {
- if ($lo['log']->getAction() == self::ACTION_UPDATE && !$lo['log']->getData()) {
- $om->remove($lo['log']);
- }
- }
- }
-
- /**
- * Create a new Audit instance
- *
- * @param string $action
- * @param object $object
- * @param LoggableAdapter $ea
- */
- protected function createLogEntry($action, $object, LoggableAdapter $ea)
- {
- $om = $ea->getObjectManager();
- $uow = $om->getUnitOfWork();
- $user = $om->getRepository('OroUserBundle:User')->findOneBy(array('username' => $this->username));
-
- if (!$user) {
- return;
- }
-
- $wrapped = AbstractWrapper::wrap($object, $om);
- $meta = $wrapped->getMetadata();
-
- if ($config = $this->getConfiguration($om, $meta->name)) {
- $logEntryClass = $this->getLogEntryClass($ea, $meta->name);
- $logEntryMeta = $om->getClassMetadata($logEntryClass);
- $logEntry = $logEntryMeta->newInstance();
-
- // do not store log entries for flexible attributes - add them to a parent entity instead
- if ($object instanceof AbstractEntityFlexibleValue) {
- if ($action !== self::ACTION_REMOVE && !$this->logFlexible($object, $ea)) {
- $objectMeta = $om->getClassMetadata(get_class($object));
-
- // if no "parent" object has been saved previously - get it from attribute and save it's log
- if ($objectMeta->reflFields['entity']->getValue($object) instanceof AbstractEntityFlexible) {
- $this->createLogEntry($action, $objectMeta->reflFields['entity']->getValue($object), $ea);
- }
-
- $this->logFlexible($object, $ea);
- }
-
- return;
- }
-
- $logEntry->setAction($action);
- $logEntry->setObjectClass($meta->name);
- $logEntry->setLoggedAt();
- $logEntry->setUser($user);
- $logEntry->setObjectName(method_exists($object, '__toString') ? $object->__toString() : $meta->name);
-
- // check for the availability of the primary key
- $objectId = $wrapped->getIdentifier();
-
- if (!$objectId && $action === self::ACTION_CREATE) {
- $this->pendingLogEntryInserts[spl_object_hash($object)] = $logEntry;
- }
-
- $logEntry->setObjectId($objectId);
-
- $newValues = array();
-
- if ($action !== self::ACTION_REMOVE && isset($config['versioned'])) {
- foreach ($ea->getObjectChangeSet($uow, $object) as $field => $changes) {
- if (!in_array($field, $config['versioned'])) {
- continue;
- }
-
- // fix issues with DateTime
- if ($changes[0] == $changes[1]) {
- continue;
- }
-
- $value = $changes[1];
-
- if ($meta->isSingleValuedAssociation($field) && $value) {
- $oid = spl_object_hash($value);
- $wrappedAssoc = AbstractWrapper::wrap($value, $om);
- $value = $wrappedAssoc->getIdentifier(false);
-
- if (!is_array($value) && !$value) {
- $this->pendingRelatedObjects[$oid][] = array(
- 'log' => $logEntry,
- 'field' => $field
- );
- }
- }
-
- $newValues[$field] = array(
- 'old' => $changes[0],
- 'new' => $value,
- );
- }
-
- $logEntry->setData($newValues);
- }
-
- if ($action === self::ACTION_UPDATE && 0 === count($newValues) && !($object instanceof AbstractEntityFlexible)) {
- return;
- }
-
- $version = 1;
-
- if ($action !== self::ACTION_CREATE) {
- $version = $ea->getNewVersion($logEntryMeta, $object);
-
- if (empty($version)) {
- // was versioned later
- $version = 1;
- }
- }
-
- $logEntry->setVersion($version);
-
- $this->prePersistLogEntry($logEntry, $object);
-
- $om->persist($logEntry);
- $uow->computeChangeSet($logEntryMeta, $logEntry);
-
- // save logged data for possible future handling of flexible attributes
- if ($object instanceof AbstractEntityFlexible) {
- $this->loggedObjects[] = array(
- 'object' => $object,
- 'log' => $logEntry,
- 'meta' => $logEntryMeta,
- );
- }
- }
- }
-
- /**
- * Add flexible attribute log to a parent entity's log entry
- *
- * @param AbstractEntityFlexibleValue $object
- * @param LoggableAdapter $ea
- * @return boolean True if value has been saved, false otherwise
- */
- protected function logFlexible(AbstractEntityFlexibleValue $object, LoggableAdapter $ea)
- {
- $om = $ea->getObjectManager();
- $uow = $om->getUnitOfWork();
-
- foreach ($this->loggedObjects as &$lo) {
- if ($lo['object']->getValues()->contains($object)) {
- $logEntry = $lo['log'];
- $changes = current($ea->getObjectChangeSet($uow, $object));
- $oldData = $changes[0];
- $newData = $object->getData();
-
- if ($oldData instanceof AbstractEntityAttributeOption) {
- $oldData = $oldData->getOptionValue()->getValue();
- }
-
- if ($newData instanceof AbstractEntityAttributeOption) {
- $newData = $newData->getOptionValue()->getValue();
- } elseif ($newData instanceof Collection) {
- $oldData = implode(
- ', ',
- array_map(
- function ($item) {
- return $item->getOptionValue()->getValue();
- },
- $newData->getSnapshot()
- )
- );
-
- $newData = implode(
- ', ',
- $newData->map(function ($item) {
- return $item->getOptionValue()->getValue();
- })->toArray()
- );
- }
-
- // special case for, as an example, decimal values
- // do not store changeset d:123 and s:3:"123"
- if ($oldData == $newData) {
- return true;
- }
-
- $data = array_merge(
- (array) $logEntry->getData(),
- array(
- $object->getAttribute()->getCode() => array(
- 'old' => $oldData,
- 'new' => $newData,
- )
- )
- );
-
- $logEntry->setData($data);
-
- $om->persist($logEntry);
- $uow->recomputeSingleEntityChangeSet($lo['meta'], $logEntry);
-
- return true;
- }
- }
-
- return false;
- }
-}
diff --git a/src/Oro/Bundle/DataAuditBundle/Form/EventListener/AuditableSubscriber.php b/src/Oro/Bundle/DataAuditBundle/Form/EventListener/AuditableSubscriber.php
deleted file mode 100644
index 494048328bc..00000000000
--- a/src/Oro/Bundle/DataAuditBundle/Form/EventListener/AuditableSubscriber.php
+++ /dev/null
@@ -1,34 +0,0 @@
- 'postBind',
- );
- }
-
- public function postBind(FormEvent $event)
- {
- /* @var $entity AuditableInterface */
- $entity = $event->getData();
-
- if (is_null($entity) || !$entity instanceof AuditableInterface) {
- return;
- }
-
- $entity->setAuditData();
- }
-}
diff --git a/src/Oro/Bundle/DataAuditBundle/Loggable/LoggableManager.php b/src/Oro/Bundle/DataAuditBundle/Loggable/LoggableManager.php
new file mode 100644
index 00000000000..9c6cccdda05
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Loggable/LoggableManager.php
@@ -0,0 +1,482 @@
+logEntityClass = $logEntityClass;
+ }
+
+ /**
+ * @param ClassMetadata $metadata
+ */
+ public function addConfig(ClassMetadata $metadata)
+ {
+ $this->configs[$metadata->name] = $metadata;
+ }
+
+ /**
+ * @param $name
+ * @return ClassMetadata
+ * @throws InvalidParameterException
+ */
+ public function getConfig($name)
+ {
+ if (!isset($this->configs[$name])) {
+ throw new InvalidParameterException(sprintf('invalid config name %s', $name));
+ }
+
+ return $this->configs[$name];
+ }
+
+ /**
+ * @param $name
+ * @return bool
+ */
+ public function hasConfig($name)
+ {
+ return isset($this->configs[$name]);
+ }
+
+ /**
+ * @param $username
+ * @throws \InvalidArgumentException
+ */
+ public function setUsername($username)
+ {
+ if (is_string($username)) {
+ $this->username = $username;
+ } elseif (is_object($username) && method_exists($username, 'getUsername')) {
+ $this->username = (string) $username->getUsername();
+ } else {
+ throw new \InvalidArgumentException("Username must be a string, or object should have method: getUsername");
+ }
+ }
+
+ /**
+ * @param EntityManager $em
+ */
+ public function handleLoggable(EntityManager $em)
+ {
+ $this->em = $em;
+ $uow = $em->getUnitOfWork();
+
+ $collections = array_merge($uow->getScheduledCollectionUpdates(), $uow->getScheduledCollectionDeletions());
+ foreach ($collections as $collection) {
+ $this->calculateCollectionData($collection);
+ }
+
+ foreach ($uow->getScheduledEntityInsertions() as $entity) {
+ $this->createLogEntity(self::ACTION_CREATE, $entity);
+ }
+ foreach ($uow->getScheduledEntityUpdates() as $entity) {
+ $this->createLogEntity(self::ACTION_UPDATE, $entity);
+ }
+ foreach ($uow->getScheduledEntityDeletions() as $entity) {
+ $this->createLogEntity(self::ACTION_REMOVE, $entity);
+ }
+ }
+
+ /**
+ * @param $entity
+ * @param EntityManager $em
+ */
+ public function handlePostPersist($entity, EntityManager $em)
+ {
+ $this->em = $em;
+ $uow = $em->getUnitOfWork();
+
+ $oid = spl_object_hash($entity);
+
+ if ($this->pendingLogEntityInserts && array_key_exists($oid, $this->pendingLogEntityInserts)) {
+ $logEntry = $this->pendingLogEntityInserts[$oid];
+ $logEntryMeta = $em->getClassMetadata(get_class($logEntry));
+
+ $id = $this->getIdentifier($entity);
+ $logEntryMeta->getReflectionProperty('objectId')->setValue($logEntry, $id);
+ $uow->scheduleExtraUpdate($logEntry, array(
+ 'objectId' => array(null, $id)
+ ));
+
+ $uow->setOriginalEntityProperty(spl_object_hash($logEntry), 'objectId', $id);
+
+ unset($this->pendingLogEntityInserts[$oid]);
+ }
+
+ if ($this->pendingRelatedEntities && array_key_exists($oid, $this->pendingRelatedEntities)) {
+ $identifiers = $uow->getEntityIdentifier($entity);
+
+ foreach ($this->pendingRelatedEntities[$oid] as $props) {
+ $logEntry = $props['log'];
+ $oldData = $data = $logEntry->getData();
+ $data[$props['field']] = $identifiers;
+ $logEntry->setData($data);
+
+ $uow->scheduleExtraUpdate($logEntry, array(
+ 'data' => array($oldData, $data)
+ ));
+ $uow->setOriginalEntityProperty(spl_object_hash($logEntry), 'objectId', $data);
+ }
+ unset($this->pendingRelatedEntities[$oid]);
+ }
+ }
+
+ /**
+ * @param PersistentCollection $collection
+ */
+ protected function calculateCollectionData(PersistentCollection $collection)
+ {
+ $ownerEntity = $collection->getOwner();
+
+ if ($this->hasConfig(get_class($ownerEntity))) {
+ $meta = $this->getConfig(get_class($ownerEntity));
+ $collectionMapping = $collection->getMapping();
+
+ if (isset($meta->propertyMetadata[$collectionMapping['fieldName']])) {
+ $method = $meta->propertyMetadata[$collectionMapping['fieldName']]->method;
+
+ $oldData = array_reduce(
+ $collection->getSnapshot(),
+ function ($result, $item) use ($method) {
+ return $result . ($result ? ', ' : '') . $item->{$method}();
+ }
+ );
+
+ $newData = array_reduce(
+ $collection->toArray(),
+ function ($result, $item) use ($method) {
+ return $result . ($result ? ', ' : '') . $item->{$method}();
+ }
+ );
+
+ $this->collectionLogData[$collectionMapping['fieldName']] = array(
+ 'old' => $oldData,
+ 'new' => $newData,
+ );
+ }
+ }
+ }
+
+ /**
+ * @param $action
+ * @param $entity
+ */
+ protected function createLogEntity($action, $entity)
+ {
+ if (!$this->username) {
+ return;
+ }
+
+ /** @var User $user */
+ $user = $this->em->getRepository('OroUserBundle:User')->findOneBy(array('username' => $this->username));
+
+ if (!$user) {
+ return;
+ }
+
+ $uow = $this->em->getUnitOfWork();
+
+ if ($this->hasConfig(get_class($entity))) {
+ $meta = $this->getConfig(get_class($entity));
+ $entityMeta = $this->em->getClassMetadata(get_class($entity));
+
+ $logEntryMeta = $this->em->getClassMetadata($this->getLogEntityClass());
+ /** @var Audit $logEntry */
+ $logEntry = $logEntryMeta->newInstance();
+
+ // do not store log entries for flexible attributes - add them to a parent entity instead
+ if ($entity instanceof AbstractEntityFlexibleValue) {
+ if ($action !== self::ACTION_REMOVE && !$this->logFlexible($entity)) {
+ $flexibleEntityMeta = $this->em->getClassMetadata(get_class($entity));
+
+ // if no "parent" object has been saved previously - get it from attribute and save it's log
+ if ($flexibleEntityMeta->reflFields['entity']->getValue($entity) instanceof AbstractEntityFlexible) {
+ $this->createLogEntity($action, $flexibleEntityMeta->reflFields['entity']->getValue($entity));
+ }
+
+ $this->logFlexible($entity);
+ }
+
+ return;
+ }
+
+ $logEntry->setAction($action);
+ $logEntry->setObjectClass($meta->name);
+ $logEntry->setLoggedAt();
+ $logEntry->setUser($user);
+ $logEntry->setObjectName(method_exists($entity, '__toString') ? $entity->__toString() : $meta->name);
+
+ $entityId = $this->getIdentifier($entity);
+
+ if (!$entityId && $action === self::ACTION_CREATE) {
+ $this->pendingLogEntityInserts[spl_object_hash($entity)] = $logEntry;
+ }
+
+ $logEntry->setObjectId($entityId);
+
+ $newValues = array();
+
+ if ($action !== self::ACTION_REMOVE && count($meta->propertyMetadata)) {
+ foreach ($uow->getEntityChangeSet($entity) as $field => $changes) {
+ if (!isset($meta->propertyMetadata[$field])) {
+ continue;
+ }
+
+ // fix issues with DateTime
+ if ($changes[0] == $changes[1]) {
+ continue;
+ }
+
+ $value = $changes[1];
+
+ if ($entityMeta->isSingleValuedAssociation($field) && $value) {
+ $oid = spl_object_hash($value);
+ $value = $this->getIdentifier($value);
+
+ if (!is_array($value) && !$value) {
+ $this->pendingRelatedEntities[$oid][] = array(
+ 'log' => $logEntry,
+ 'field' => $field
+ );
+ }
+ }
+
+ $newValues[$field] = array(
+ 'old' => $changes[0],
+ 'new' => $value,
+ );
+ }
+
+ $logEntry->setData(array_merge($newValues, $this->collectionLogData));
+ }
+
+
+ if ($action === self::ACTION_UPDATE && 0 === count($newValues) && !($entity instanceof AbstractEntityFlexible)) {
+ return;
+ }
+
+ $version = 1;
+
+ if ($action !== self::ACTION_CREATE) {
+ $version = $this->getNewVersion($logEntryMeta, $entity);
+
+ if (empty($version)) {
+ // was versioned later
+ $version = 1;
+ }
+ }
+
+ $logEntry->setVersion($version);
+
+ $this->em->persist($logEntry);
+ $uow->computeChangeSet($logEntryMeta, $logEntry);
+
+ // save logged data for possible future handling of flexible attributes
+ if ($entity instanceof AbstractEntityFlexible) {
+ $this->loggedObjects[] = array(
+ 'object' => $entity,
+ 'log' => $logEntry,
+ 'meta' => $logEntryMeta,
+ );
+ }
+ }
+ }
+
+ /**
+ * Get the LogEntry class
+ *
+ * @return string
+ */
+ protected function getLogEntityClass()
+ {
+ return $this->logEntityClass;
+ }
+
+ /**
+ * Add flexible attribute log to a parent entity's log entry
+ *
+ * @param AbstractEntityFlexibleValue $entity
+ * @return boolean True if value has been saved, false otherwise
+ */
+ protected function logFlexible(AbstractEntityFlexibleValue $entity)
+ {
+ $uow = $this->em->getUnitOfWork();
+
+ foreach ($this->loggedObjects as &$lo) {
+ if ($lo['object']->getValues()->contains($entity)) {
+ $logEntry = $lo['log'];
+ $changes = current($uow->getEntityChangeSet($entity));
+ $oldData = $changes[0];
+ $newData = $entity->getData();
+
+ if ($oldData instanceof AbstractEntityAttributeOption) {
+ $oldData = $oldData->getOptionValue()->getValue();
+ }
+
+ if ($newData instanceof AbstractEntityAttributeOption) {
+ $newData = $newData->getOptionValue()->getValue();
+ } elseif ($newData instanceof Collection) {
+ $oldData = implode(
+ ', ',
+ array_map(
+ function (AbstractEntityAttributeOption $item) {
+ return $item->getOptionValue()->getValue();
+ },
+ $newData->getSnapshot()
+ )
+ );
+
+ $newData = implode(
+ ', ',
+ $newData->map(function (AbstractEntityAttributeOption $item) {
+ return $item->getOptionValue()->getValue();
+ })->toArray()
+ );
+ }
+
+ // special case for, as an example, decimal values
+ // do not store changeset d:123 and s:3:"123"
+ if ($oldData == $newData) {
+ return true;
+ }
+
+ $data = array_merge(
+ (array) $logEntry->getData(),
+ array(
+ $entity->getAttribute()->getCode() => array(
+ 'old' => $oldData,
+ 'new' => $newData,
+ )
+ )
+ );
+
+ $logEntry->setData($data);
+
+ $this->em->persist($logEntry);
+ $uow->recomputeSingleEntityChangeSet($lo['meta'], $logEntry);
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @param $logEntityMeta
+ * @param $entity
+ * @return mixed
+ */
+ protected function getNewVersion($logEntityMeta, $entity)
+ {
+ $entityMeta = $this->em->getClassMetadata(get_class($entity));
+ $entityId = $this->getIdentifier($entity);
+
+ $dql = "SELECT MAX(log.version) FROM {$logEntityMeta->name} log";
+ $dql .= " WHERE log.objectId = :objectId";
+ $dql .= " AND log.objectClass = :objectClass";
+
+ $q = $this->em->createQuery($dql);
+ $q->setParameters(array(
+ 'objectId' => $entityId,
+ 'objectClass' => $entityMeta->name
+ ));
+
+ return $q->getSingleScalarResult() + 1;
+ }
+
+ /**
+ * @param $entity
+ * @param null $entityMeta
+ * @return mixed
+ */
+ protected function getIdentifier($entity, $entityMeta = null)
+ {
+ $entityMeta = $entityMeta ? $entityMeta : $this->em->getClassMetadata(get_class($entity));
+ $identifierField = $entityMeta->getSingleIdentifierFieldName($entityMeta);
+
+ return $entityMeta->getReflectionProperty($identifierField)->getValue($entity);
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Metadata/Annotation/Loggable.php b/src/Oro/Bundle/DataAuditBundle/Metadata/Annotation/Loggable.php
new file mode 100644
index 00000000000..67ec6a6a761
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Metadata/Annotation/Loggable.php
@@ -0,0 +1,13 @@
+method = $data['method'];
+ } elseif (isset($data['value'])) {
+ $this->method = $data['value'];
+ }
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Metadata/ClassMetadata.php b/src/Oro/Bundle/DataAuditBundle/Metadata/ClassMetadata.php
new file mode 100644
index 00000000000..0b044fa890f
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Metadata/ClassMetadata.php
@@ -0,0 +1,9 @@
+reader = $reader;
+ }
+
+ /**
+ * Merge DoctrineClassMetadata and DataAuditClassMetadata
+ * @param DoctrineClassMetadata $doctrineClassMetadata
+ * @return null|ClassMetadata
+ * @throws \InvalidArgumentException
+ */
+ public function extendLoadMetadataForClass(DoctrineClassMetadata $doctrineClassMetadata)
+ {
+ if ($doctrineClassMetadata->isMappedSuperclass
+ || !$classMetadata = $this->loadMetadataForClass($doctrineClassMetadata->getReflectionClass())
+ ) {
+ return null;
+ }
+
+ /** @var $property PropertyMetadata */
+ foreach ($classMetadata->propertyMetadata as $name => $property) {
+ if ($doctrineClassMetadata->isInheritedField($name) ||
+ isset($doctrineClassMetadata->associationMappings[$property->name]['inherited'])
+ ) {
+ unset($classMetadata->propertyMetadata[$name]);
+ continue;
+ }
+
+ if ($doctrineClassMetadata->isCollectionValuedAssociation($name)) {
+ $property->isCollection = true;
+
+ $targetMapping = $doctrineClassMetadata->getAssociationMapping($name);
+
+ if (!method_exists($targetMapping['targetEntity'], $property->method)) {
+ throw new \InvalidArgumentException(sprintf(
+ "Method %s in Class %s is not defined. Class must implement a method '__toString' or configure getMethod with Versioned annotation",
+ $property->method,
+ $targetMapping['targetEntity'])
+ );
+ }
+ }
+ }
+
+ return $classMetadata;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function loadMetadataForClass(\ReflectionClass $class)
+ {
+ $classMetadata = new ClassMetadata($class->getName());
+
+ /** @var Loggable $loggable */
+ $loggable = $this->reader->getClassAnnotation($class, self::LOGGABLE);
+
+ foreach ($class->getProperties() as $reflectionProperty) {
+ /** @var Versioned $versioned */
+ if ($versioned = $this->reader->getPropertyAnnotation($reflectionProperty, self::VERSIONED)) {
+ $propertyMetadata = new PropertyMetadata($class->getName(), $reflectionProperty->getName());
+ $propertyMetadata->method = $versioned->method ? $versioned->method : '__toString';
+
+ $classMetadata->addPropertyMetadata($propertyMetadata);
+ }
+ }
+
+ if (count($classMetadata->propertyMetadata) && !$loggable) {
+ throw new \InvalidArgumentException(sprintf(
+ "Class must be annoted with Loggable annotation in order to track versioned fields in class - %s",
+ $classMetadata->name)
+ );
+ }
+
+ if (count($classMetadata->propertyMetadata)) {
+ return $classMetadata;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Metadata/ExtendMetadataFactory.php b/src/Oro/Bundle/DataAuditBundle/Metadata/ExtendMetadataFactory.php
new file mode 100644
index 00000000000..6ea2dd33585
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Metadata/ExtendMetadataFactory.php
@@ -0,0 +1,32 @@
+driver = $driver;
+ }
+
+ /**
+ * @param DoctrineClassMetadata $metadata
+ * @return null|ClassMetadata
+ */
+ public function extendLoadMetadataForClass(DoctrineClassMetadata $metadata)
+ {
+ return $this->driver->extendLoadMetadataForClass($metadata);
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Metadata/PropertyMetadata.php b/src/Oro/Bundle/DataAuditBundle/Metadata/PropertyMetadata.php
new file mode 100644
index 00000000000..5a881e85de0
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Metadata/PropertyMetadata.php
@@ -0,0 +1,44 @@
+isCollection,
+ $this->method,
+ parent::serialize(),
+ ));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function unserialize($str)
+ {
+ list(
+ $this->isCollection,
+ $this->method,
+ $parentStr
+ ) = unserialize($str);
+
+ parent::unserialize($parentStr);
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/README.md b/src/Oro/Bundle/DataAuditBundle/README.md
index fe36215b33b..371f782db7b 100644
--- a/src/Oro/Bundle/DataAuditBundle/README.md
+++ b/src/Oro/Bundle/DataAuditBundle/README.md
@@ -35,18 +35,6 @@ public function registerBundles()
}
```
-Enable Loggable behavior in your `app/config/config.yml` file and customize `LoggableListener`:
-
-``` yaml
-stof_doctrine_extensions:
- orm:
- default:
- [...]
- loggable: true
- class:
- [...]
- loggable: Oro\Bundle\DataAuditBundle\EventListener\LoggableListener
-```
To enable log view and API calls, import routing rules in `app/config/routing.yml`
@@ -67,12 +55,12 @@ In your entity add special annotations to mark particular fields versioned.
``` php
{% block content %}
-
+
{% endblock %}
{% endblock %}
diff --git a/src/Oro/Bundle/DataAuditBundle/Resources/views/Audit/index.html.twig b/src/Oro/Bundle/DataAuditBundle/Resources/views/Audit/index.html.twig
index f44750d00f6..ee16d3ebf95 100644
--- a/src/Oro/Bundle/DataAuditBundle/Resources/views/Audit/index.html.twig
+++ b/src/Oro/Bundle/DataAuditBundle/Resources/views/Audit/index.html.twig
@@ -1,17 +1,7 @@
-{% extends bap.layout %}
-
-{% block head_script %}
+{% extends 'OroUIBundle:actions:index.html.twig' %}
+{% import 'OroUIBundle::macros.html.twig' as UI %}
+{% set gridId = 'audit-grid' %}
+{% block content %}
+ {% set pageTitle = 'Data Audit' %}
{{ parent() }}
-
- {% include 'OroGridBundle:Include:javascript.html.twig' with {'datagridView': datagrid, 'selector': '#audit-grid'} %}
- {% include 'OroGridBundle:Include:stylesheet.html.twig' %}
-{% endblock %}
-
-{% block page_container %}
-
- {% block content %}
-
{{ 'Data Audit'|trans }}
-
- {% endblock %}
-
{% endblock %}
diff --git a/src/Oro/Bundle/DataAuditBundle/Resources/views/change_history_link.html.twig b/src/Oro/Bundle/DataAuditBundle/Resources/views/change_history_link.html.twig
new file mode 100644
index 00000000000..bfb3cf326f5
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Resources/views/change_history_link.html.twig
@@ -0,0 +1,6 @@
+
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Functional/RestDataAuditApiTest.php b/src/Oro/Bundle/DataAuditBundle/Tests/Functional/RestDataAuditApiTest.php
new file mode 100644
index 00000000000..3f915b83e79
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Functional/RestDataAuditApiTest.php
@@ -0,0 +1,91 @@
+client = static::createClient(array(), ToolsAPI::generateWsseHeader());
+ }
+
+ /**
+ * @return array
+ */
+ public function testPreconditions()
+ {
+ //create users
+ $request = array(
+ "user" => array (
+ "username" => 'user_' . mt_rand(),
+ "email" => 'test_' . mt_rand() . '@test.com',
+ "enabled" => '1',
+ "plainPassword" => '1231231q',
+ "firstName" => "firstName",
+ "lastName" => "lastName",
+ "rolesCollection" => array("1")
+ )
+ );
+
+ $this->client->request('POST', 'http://localhost/api/rest/latest/user', $request);
+ $result = $this->client->getResponse();
+ ToolsAPI::assertJsonResponse($result, 201);
+
+ return $request;
+ }
+
+ /**
+ * @param $response
+ * @return array
+ * @depends testPreconditions
+ */
+ public function testGetAudits($response)
+ {
+ $this->client->request('GET', 'http://localhost/api/rest/latest/audits');
+ $result = $this->client->getResponse();
+ ToolsAPI::assertJsonResponse($result, 200);
+ $result = ToolsAPI::jsonToArray($result->getContent());
+
+ return $result;
+ }
+
+ /**
+ * @param array $response
+ * @return array
+ * @depends testGetAudits
+ */
+ public function testGetAudit($response)
+ {
+ $this->client->request('GET', 'http://localhost/api/rest/latest/audits/' . $response[0]['id']);
+ $result = $this->client->getResponse();
+ ToolsAPI::assertJsonResponse($result, 200);
+ $result = ToolsAPI::jsonToArray($result->getContent());
+
+ return $result;
+ }
+
+ /**
+ * @param array $response
+ * @depends testGetAudit
+ */
+ public function testDeleteAudit($response)
+ {
+ $this->client->request('DELETE', 'http://localhost/api/rest/latest/audits/' . $response['id']);
+ $result = $this->client->getResponse();
+ ToolsAPI::assertJsonResponse($result, 204);
+ $this->client->request('GET', 'http://localhost/api/rest/latest/audits/' . $response['id']);
+ $result = $this->client->getResponse();
+ ToolsAPI::assertJsonResponse($result, 404);
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Functional/SoapDataAuditApiTest.php b/src/Oro/Bundle/DataAuditBundle/Tests/Functional/SoapDataAuditApiTest.php
new file mode 100644
index 00000000000..f0929940220
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Functional/SoapDataAuditApiTest.php
@@ -0,0 +1,85 @@
+client = static::createClient(array(), ToolsAPI::generateWsseHeader());
+
+ $this->client->soap(
+ "http://localhost/api/soap",
+ array(
+ 'location' => 'http://localhost/api/soap',
+ 'soap_version' => SOAP_1_2
+ )
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function testPreconditions()
+ {
+ //create users
+ $request = array(
+ "username" => 'user_' . mt_rand(),
+ "email" => 'test_' . mt_rand() . '@test.com',
+ "enabled" => '1',
+ "plainPassword" => '1231231q',
+ "firstName" => "firstName",
+ "lastName" => "lastName",
+ "rolesCollection" => array("1")
+ );
+ $result = $this->client->soapClient->createUser($request);
+ $this->assertTrue($result, $this->client->soapClient->__getLastResponse());
+
+ return $request;
+ }
+
+ /**
+ * @param $response
+ * @return array
+ * @depends testPreconditions
+ */
+ public function testGetAudits($response)
+ {
+ $this->markTestSkipped('BAP-949');
+ $result = $this->client->soapClient->getAudits();
+
+ return $result;
+ }
+
+ /**
+ * @param array $response
+ * @return array
+ * @depends testGetAudits
+ */
+ public function testGetAudit($response)
+ {
+ $result = $this->client->soapClient->getAudit($response[0]['id']);
+
+ return $result;
+ }
+
+ /**
+ * @param array $response
+ * @depends testGetAudit
+ */
+ public function testDeleteAudit($response)
+ {
+ $this->client->soapClient->deleteAudit($response[0]['id']);
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/DependencyInjection/OroDataAuditExtensionTest.php b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/DependencyInjection/OroDataAuditExtensionTest.php
index 0979ee419db..e9240e7cc25 100644
--- a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/DependencyInjection/OroDataAuditExtensionTest.php
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/DependencyInjection/OroDataAuditExtensionTest.php
@@ -1,6 +1,6 @@
assertTrue($configuration instanceof ContainerBuilder);
$this->assertTrue($configuration->has('oro_dataaudit.datagrid.manager'));
+ $this->assertTrue($configuration->has('oro_dataaudit.loggable.loggable_manager'));
+ $this->assertTrue($configuration->has('oro_dataaudit.listener.kernel_listener'));
}
/**
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Entity/AuditDataTest.php b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Entity/AuditDataTest.php
new file mode 100644
index 00000000000..29cb5fc6857
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Entity/AuditDataTest.php
@@ -0,0 +1,18 @@
+assertInstanceOf('Oro\Bundle\DataAuditBundle\Entity\AuditData', $auditData);
+
+ $this->assertEquals('key', $auditData->getKey());
+ $this->assertEquals('value', $auditData->getValue());
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Entity/AuditTest.php b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Entity/AuditTest.php
index d755a2636cf..a463e35c726 100644
--- a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Entity/AuditTest.php
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Entity/AuditTest.php
@@ -1,6 +1,6 @@
id;
+ }
+
+ /**
+ * @param mixed $name
+ * @return $this
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * @param mixed $collection
+ * @return $this
+ */
+ public function setCollection($collection)
+ {
+ $this->collection = $collection;
+
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCollection()
+ {
+ return $this->collection;
+ }
+
+ /**
+ * @param LoggableCollectionClass[] $collectionWithMethodName
+ * @return $this
+ */
+ public function setCollectionWithMethodName($collectionWithMethodName)
+ {
+ $this->collectionWithMethodName = $collectionWithMethodName;
+
+ return $this;
+ }
+
+ /**
+ * @return LoggableCollectionClass[]
+ */
+ public function getCollectionWithMethodName()
+ {
+ return $this->collectionWithMethodName;
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Fixture/LoggableCollectionClass.php b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Fixture/LoggableCollectionClass.php
new file mode 100644
index 00000000000..82e553fd543
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Fixture/LoggableCollectionClass.php
@@ -0,0 +1,62 @@
+id;
+ }
+
+ /**
+ * @param mixed $name
+ * @return $this
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->name;
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Fixture/Repository/UserRepository.php b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Fixture/Repository/UserRepository.php
new file mode 100644
index 00000000000..ac6ad3d8f6f
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Fixture/Repository/UserRepository.php
@@ -0,0 +1,17 @@
+setUsername('testUser');
+
+ return $user;
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Loggable/LoggableManagerTest.php b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Loggable/LoggableManagerTest.php
new file mode 100644
index 00000000000..f3d510b7749
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Loggable/LoggableManagerTest.php
@@ -0,0 +1,99 @@
+em->getClassMetadata('Oro\Bundle\UserBundle\Entity\User');
+ $meta->setCustomRepositoryClass('Oro\Bundle\DataAuditBundle\Tests\Unit\Fixture\Repository\UserRepository');
+
+ $this->config = $this->loggableAnnotationDriver->extendLoadMetadataForClass(
+ $this->em->getClassMetadata('Oro\Bundle\DataAuditBundle\Tests\Unit\Fixture\LoggableClass')
+ );
+
+ $this->loggableManager = new LoggableManager('Oro\Bundle\DataAuditBundle\Entity\Audit');
+ $this->loggableManager->addConfig($this->config);
+
+ $this->loggableClass = new LoggableClass();
+ $this->loggableClass->setName('testName');
+ }
+
+ public function testHandleLoggable()
+ {
+ $loggableCollectionClass = new LoggableCollectionClass();
+ $loggableCollectionClass->setName('testCollectionName');
+
+ $collection = new PersistentCollection($this->em, get_class($loggableCollectionClass), array($loggableCollectionClass));
+ $collection->setDirty(true);
+ $this->loggableClass->setCollection($collection);
+
+ $this->em->persist($this->loggableClass);
+
+ //log with out user
+ $this->loggableManager->handleLoggable($this->em);
+
+ //log with user
+ $this->loggableManager->setUsername('testUser');
+ $this->loggableManager->handleLoggable($this->em);
+
+ //log delete
+ $this->em->remove($this->loggableClass);
+ $this->loggableManager->handleLoggable($this->em);
+ }
+
+ public function testHandlePostPersist()
+ {
+ $this->loggableManager->handlePostPersist($this->loggableClass, $this->em);
+ }
+
+ public function testSetUsername()
+ {
+ $user = new User();
+ $user->setUsername('testuser');
+
+ $this->loggableManager->setUsername($user);
+
+ $this->setExpectedException('InvalidArgumentException', 'Username must be a string, or object should have method: getUsername');
+ $wrongUser = new \stdClass();
+ $this->loggableManager->setUsername($wrongUser);
+ }
+
+ public function testGetConfig()
+ {
+ $this->setExpectedException('InvalidArgumentException', 'Oro\Bundle\DataAuditBundle\Tests\Unit\Fixture\LoggableClassWrong');
+ $this->loggableManager->getConfig('Oro\Bundle\DataAuditBundle\Tests\Unit\Fixture\LoggableClassWrong');
+
+ $resultConfig = $this->loggableManager->getConfig('Oro\Bundle\DataAuditBundle\Tests\Unit\Fixture\LoggableClass');
+
+ $this->assertEquals($this->config, $resultConfig);
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/AbstractMetadataTest.php b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/AbstractMetadataTest.php
new file mode 100644
index 00000000000..7bedf57bf1c
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/AbstractMetadataTest.php
@@ -0,0 +1,41 @@
+em = $this->_getTestEntityManager();
+ $this->em->getConfiguration()->setEntityNamespaces(array(
+ 'OroUserBundle' => 'Oro\\Bundle\\UserBundle\\Entity',
+ 'OroDataAuditBundle' => 'Oro\\Bundle\\DataAuditBundle\\Entity'
+ ));
+ $this->em->getConfiguration()->setMetadataDriverImpl($metadataDriver);
+
+ $this->loggableAnnotationDriver = new \Oro\Bundle\DataAuditBundle\Metadata\Driver\AnnotationDriver(new AnnotationReader());
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/Annotation/VersionedTest.php b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/Annotation/VersionedTest.php
new file mode 100644
index 00000000000..96e83e653bd
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/Annotation/VersionedTest.php
@@ -0,0 +1,17 @@
+ '__toString'));
+ $versioned2 = new Versioned(array('method' => '__toString'));
+
+ $this->assertAttributeEquals('__toString', 'method', $versioned);
+ $this->assertAttributeEquals('__toString', 'method', $versioned2);
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/Driver/AnnotationDriverTest.php b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/Driver/AnnotationDriverTest.php
new file mode 100644
index 00000000000..884d7693250
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/Driver/AnnotationDriverTest.php
@@ -0,0 +1,48 @@
+em->getClassMetadata('Oro\Bundle\DataAuditBundle\Tests\Unit\Fixture\LoggableClass');
+
+ $nameProperty = new PropertyMetadata('Oro\Bundle\DataAuditBundle\Tests\Unit\Fixture\LoggableClass', 'name');
+ $nameProperty->method = '__toString';
+
+ $collectionProperty = new PropertyMetadata('Oro\Bundle\DataAuditBundle\Tests\Unit\Fixture\LoggableClass', 'collection');
+ $collectionProperty->method = '__toString';
+ $collectionProperty->isCollection = true;
+
+ $collectionWithMethodNameProperty = new PropertyMetadata('Oro\Bundle\DataAuditBundle\Tests\Unit\Fixture\LoggableClass', 'collectionWithMethodName');
+ $collectionWithMethodNameProperty->isCollection = true;
+ $collectionWithMethodNameProperty->method = 'getName';
+
+ $metadata = new BaseClassMetadata('Oro\Bundle\DataAuditBundle\Tests\Unit\Fixture\LoggableClass');
+ $metadata->addPropertyMetadata($nameProperty);
+ $metadata->addPropertyMetadata($collectionProperty);
+ $metadata->addPropertyMetadata($collectionWithMethodNameProperty);
+
+ $annotationDriver = new AnnotationDriver(new AnnotationReader());
+
+ $resultMetadata = $annotationDriver->extendLoadMetadataForClass($doctrineClassMetadata);
+
+ $metadata->createdAt = $resultMetadata->createdAt;
+
+ $this->assertEquals($metadata, $resultMetadata);
+ }
+
+ public function testLoadMetadataForClass()
+ {
+ $this->assertEquals(true, true);
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/ExtendMetadataFactoryTest.php b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/ExtendMetadataFactoryTest.php
new file mode 100644
index 00000000000..71d3ec5b777
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/ExtendMetadataFactoryTest.php
@@ -0,0 +1,22 @@
+em->getClassMetadata('Oro\Bundle\DataAuditBundle\Tests\Unit\Fixture\LoggableClass');
+
+ $metadata = $this->loggableAnnotationDriver->extendLoadMetadataForClass($doctrineClassMetadata);
+
+ $metadataFactory = new ExtendMetadataFactory($this->loggableAnnotationDriver);
+ $resultMetadata = $metadataFactory->extendLoadMetadataForClass($doctrineClassMetadata);
+
+ $metadata->createdAt = $resultMetadata->createdAt;
+
+ $this->assertEquals($metadata, $resultMetadata);
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/PropertyMetadataTest.php b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/PropertyMetadataTest.php
new file mode 100644
index 00000000000..7b3eafbc48f
--- /dev/null
+++ b/src/Oro/Bundle/DataAuditBundle/Tests/Unit/Metadata/PropertyMetadataTest.php
@@ -0,0 +1,34 @@
+propertyMetadata = new PropertyMetadata(
+ 'Oro\Bundle\DataAuditBundle\Tests\Unit\Fixture\LoggableClass',
+ 'name'
+ );
+ }
+
+ public function testSerializeUnserialize()
+ {
+ $this->propertyMetadata->isCollection = true;
+ $this->propertyMetadata->method = 'getName';
+
+ $this->assertEquals($this->propertyMetadata, unserialize(serialize($this->propertyMetadata)));
+ }
+
+ public function tearDown()
+ {
+ $this->propertyMetadata = null;
+ }
+}
diff --git a/src/Oro/Bundle/DataAuditBundle/phpunit.xml.dist b/src/Oro/Bundle/DataAuditBundle/phpunit.xml.dist
index 03e301e89c0..829e44d12d0 100644
--- a/src/Oro/Bundle/DataAuditBundle/phpunit.xml.dist
+++ b/src/Oro/Bundle/DataAuditBundle/phpunit.xml.dist
@@ -10,7 +10,7 @@
stopOnFailure="false"
syntaxCheck="false"
bootstrap="Tests/bootstrap.php"
->
+ >
diff --git a/src/Oro/Bundle/FilterBundle/Form/Type/Filter/EntityFilterType.php b/src/Oro/Bundle/FilterBundle/Form/Type/Filter/EntityFilterType.php
new file mode 100644
index 00000000000..606313d9fd0
--- /dev/null
+++ b/src/Oro/Bundle/FilterBundle/Form/Type/Filter/EntityFilterType.php
@@ -0,0 +1,54 @@
+setDefaults(
+ array(
+ 'field_type' => 'entity',
+ 'field_options' => array(),
+ 'translatable' => false,
+ )
+ );
+
+ $resolver->setNormalizers(
+ array(
+ 'field_type' => function (Options $options, $value) {
+ if (!empty($options['translatable'])) {
+ $value = 'translatable_entity';
+ }
+ return $value;
+ }
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FilterBundle/Resources/config/form_types.yml b/src/Oro/Bundle/FilterBundle/Resources/config/form_types.yml
index 3148398587f..2089c4ea321 100644
--- a/src/Oro/Bundle/FilterBundle/Resources/config/form_types.yml
+++ b/src/Oro/Bundle/FilterBundle/Resources/config/form_types.yml
@@ -50,3 +50,9 @@ services:
arguments: ["@translator"]
tags:
- { name: form.type, alias: oro_type_boolean_filter }
+
+ oro_filter.form.type.filter.entity:
+ class: Oro\Bundle\FilterBundle\Form\Type\Filter\EntityFilterType
+ arguments: ["@translator"]
+ tags:
+ - { name: form.type, alias: oro_type_entity_filter }
diff --git a/src/Oro/Bundle/FilterBundle/Resources/doc/reference/filter_form_types.md b/src/Oro/Bundle/FilterBundle/Resources/doc/reference/filter_form_types.md
index 692d9200bca..40ea67488af 100644
--- a/src/Oro/Bundle/FilterBundle/Resources/doc/reference/filter_form_types.md
+++ b/src/Oro/Bundle/FilterBundle/Resources/doc/reference/filter_form_types.md
@@ -43,6 +43,11 @@ There are next filters form types:
oro_type_choice_filter |
Represents choice filter form |
+
+ EntityFilterType |
+ oro_type_entity_filter |
+ Represents entity filter form |
+
BooleanFilterType |
oro_type_boolean_filter |
@@ -222,6 +227,34 @@ _Oro\Bundle\FilterBundle\Form\Type\Filter\ChoiceFilterType_
_Oro.Filter.MultiSelectFilter_
_Oro.Filter.SelectFilter_
+### oro\_type\_entity\_filter Form Type
+
+**Inherit Options**
+
+* field\_type
+* field\_options
+* operator\_choices
+* operator\_type
+* operator\_options
+* show\_filter
+
+**Default Options**
+
+* field\_type = entity
+
+**Parent Type**
+
+oro\_type\_choice\_filter
+
+**Class**
+
+_Oro\Bundle\FilterBundle\Form\Type\Filter\EntityFilterType_
+
+**JS Classes**
+
+_Oro.Filter.MultiSelectFilter_
+_Oro.Filter.SelectFilter_
+
### oro\_type\_boolean\_filter Form Type
**Inherit Options**
diff --git a/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/abstractfilter.js b/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/abstractfilter.js
index d3e7af97fba..60872de9daa 100644
--- a/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/abstractfilter.js
+++ b/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/abstractfilter.js
@@ -355,5 +355,18 @@ Oro.Filter.AbstractFilter = Backbone.View.extend({
} else {
element.parent().removeClass(this.buttonActiveClass);
}
+ },
+
+ /**
+ * Prevent submit of parent form if any.
+ *
+ * @param {Event} e
+ * @private
+ */
+ _preventEnterProcessing: function(e) {
+ if (e.keyCode == 13) {
+ e.preventDefault()
+ e.stopPropagation();
+ }
}
});
diff --git a/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/choicefilter.js b/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/choicefilter.js
index f9d688a4001..12bd8108491 100644
--- a/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/choicefilter.js
+++ b/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/choicefilter.js
@@ -120,6 +120,7 @@ Oro.Filter.ChoiceFilter = Oro.Filter.TextFilter.extend({
*/
events: {
'keyup input': '_onReadCriteriaInputKey',
+ 'keydown [type="text"]': '_preventEnterProcessing',
'click .filter-update': '_onClickUpdateCriteria',
'click .filter-criteria-selector': '_onClickCriteriaSelector',
'click .filter-criteria .filter-criteria-hide': '_onClickCloseCriteria',
diff --git a/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/selectfilter.js b/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/selectfilter.js
index d5bead4a13c..09bd742b047 100644
--- a/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/selectfilter.js
+++ b/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/selectfilter.js
@@ -117,6 +117,7 @@ Oro.Filter.SelectFilter = Oro.Filter.AbstractFilter.extend({
* @property
*/
events: {
+ 'keydown select': '_preventEnterProcessing',
'click .filter-select': '_onClickFilterArea',
'click .disable-filter': '_onClickDisableFilter',
'change select': '_onSelectChange'
@@ -209,7 +210,7 @@ Oro.Filter.SelectFilter = Oro.Filter.AbstractFilter.extend({
*/
_setDropdownWidth: function() {
if (!this.minimumWidth) {
- this.minimumWidth = this.selectWidget.getMinimumDropdownWidth() + 12;
+ this.minimumWidth = this.selectWidget.getMinimumDropdownWidth() + 22;
}
var widget = this.selectWidget.getWidget();
var filterWidth = this.$(this.containerSelector).width();
diff --git a/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/textfilter.js b/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/textfilter.js
index c8dd47e439a..65b70965a6c 100644
--- a/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/textfilter.js
+++ b/src/Oro/Bundle/FilterBundle/Resources/public/js/app/filter/textfilter.js
@@ -94,6 +94,7 @@ Oro.Filter.TextFilter = Oro.Filter.AbstractFilter.extend({
*/
events: {
'keyup input': '_onReadCriteriaInputKey',
+ 'keydown [type="text"]': '_preventEnterProcessing',
'click .filter-update': '_onClickUpdateCriteria',
'click .filter-criteria-selector': '_onClickCriteriaSelector',
'click .filter-criteria .filter-criteria-hide': '_onClickCloseCriteria',
diff --git a/src/Oro/Bundle/FilterBundle/Resources/views/Filter/layout.js.twig b/src/Oro/Bundle/FilterBundle/Resources/views/Filter/layout.js.twig
index d7cdcbc45d3..6a49996517a 100644
--- a/src/Oro/Bundle/FilterBundle/Resources/views/Filter/layout.js.twig
+++ b/src/Oro/Bundle/FilterBundle/Resources/views/Filter/layout.js.twig
@@ -43,32 +43,36 @@
}))
{% endblock %}
-{% block oro_type_choice_filter_js %}
- {% if formView.children.value.vars.multiple %}
- {{ block('oro_type_multiselect_filter_js') }}
- {% else %}
- {{ block('oro_type_select_filter_js') }}
- {% endif %}
-{% endblock %}
-
{% block oro_type_select_filter_js %}
Oro.createInstanceFromConstructor(Oro.Filter.SelectFilter.extend({
- 'name': {{ formView.vars.name|json_encode|raw }},
- 'label': {{ formView.vars.label|json_encode|raw }},
- 'enabled': {{ formView.vars.show_filter|json_encode|raw }},
- 'options': {{ formView.children.value.vars.choices|oro_filter_choices|json_encode|raw }}
+ 'name': {{ formView.vars.name|json_encode|raw }},
+ 'label': {{ formView.vars.label|json_encode|raw }},
+ 'enabled': {{ formView.vars.show_filter|json_encode|raw }},
+ 'options': {{ formView.children.value.vars.choices|oro_filter_choices|json_encode|raw }}
}))
{% endblock %}
{% block oro_type_multiselect_filter_js %}
Oro.createInstanceFromConstructor(Oro.Filter.MultiSelectFilter.extend({
- 'name': {{ formView.vars.name|json_encode|raw }},
- 'label': {{ formView.vars.label|json_encode|raw }},
- 'enabled': {{ formView.vars.show_filter|json_encode|raw }},
- 'options': {{ formView.children.value.vars.choices|oro_filter_choices|json_encode|raw }}
+ 'name': {{ formView.vars.name|json_encode|raw }},
+ 'label': {{ formView.vars.label|json_encode|raw }},
+ 'enabled': {{ formView.vars.show_filter|json_encode|raw }},
+ 'options': {{ formView.children.value.vars.choices|oro_filter_choices|json_encode|raw }}
}))
{% endblock %}
+{% block oro_type_choice_filter_js %}
+ {% if formView.children.value.vars.multiple %}
+ {{ block('oro_type_multiselect_filter_js') }}
+ {% else %}
+ {{ block('oro_type_select_filter_js') }}
+ {% endif %}
+{% endblock %}
+
+{% block oro_type_entity_filter_js %}
+ {{ block('oro_type_choice_filter_js') }}
+{% endblock %}
+
{% block oro_type_boolean_filter_js %}
Oro.createInstanceFromConstructor(Oro.Filter.SelectFilter.extend({
'name': {{ formView.vars.name|json_encode|raw }},
diff --git a/src/Oro/Bundle/FilterBundle/Tests/Unit/DependencyInjection/OroFilterExtensionTest.php b/src/Oro/Bundle/FilterBundle/Tests/Unit/DependencyInjection/OroFilterExtensionTest.php
index 7d6ec4282a4..d58733d3279 100644
--- a/src/Oro/Bundle/FilterBundle/Tests/Unit/DependencyInjection/OroFilterExtensionTest.php
+++ b/src/Oro/Bundle/FilterBundle/Tests/Unit/DependencyInjection/OroFilterExtensionTest.php
@@ -6,7 +6,7 @@
use Symfony\Component\DependencyInjection\Definition;
use Oro\Bundle\FilterBundle\DependencyInjection\OroFilterExtension;
-class OroGridExtensionTest extends \PHPUnit_Framework_TestCase
+class OroFilterExtensionTest extends \PHPUnit_Framework_TestCase
{
/**
* @var array
diff --git a/src/Oro/Bundle/FilterBundle/Tests/Unit/Form/Type/Filter/EntityFilterTypeTest.php b/src/Oro/Bundle/FilterBundle/Tests/Unit/Form/Type/Filter/EntityFilterTypeTest.php
new file mode 100644
index 00000000000..85c5f3c6444
--- /dev/null
+++ b/src/Oro/Bundle/FilterBundle/Tests/Unit/Form/Type/Filter/EntityFilterTypeTest.php
@@ -0,0 +1,95 @@
+createMockTranslator();
+ $this->type = new EntityFilterType($translator);
+ $this->factory->addType(new FilterType($translator));
+ $this->factory->addType(new ChoiceFilterType($translator));
+
+ $registry = $this->getMockForAbstractClass('Doctrine\Common\Persistence\ManagerRegistry', array(), '', false);
+ $this->factory->addType(new EntityType($registry));
+ }
+
+ /**
+ * @return EntityFilterType
+ */
+ protected function getTestFormType()
+ {
+ return $this->type;
+ }
+
+ public function testGetName()
+ {
+ $this->assertEquals(EntityFilterType::NAME, $this->type->getName());
+ }
+
+ public function testGetParent()
+ {
+ $this->assertEquals(ChoiceFilterType::NAME, $this->type->getParent());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function setDefaultOptionsDataProvider()
+ {
+ return array(
+ array(
+ 'defaultOptions' => array(
+ 'field_type' => 'entity',
+ 'field_options' => array(),
+ 'translatable' => false,
+ )
+ )
+ );
+ }
+
+ /**
+ * @dataProvider bindDataProvider
+ * @param array $bindData
+ * @param array $formData
+ * @param array $viewData
+ * @param array $customOptions
+ */
+ public function testBindData(
+ array $bindData,
+ array $formData,
+ array $viewData,
+ array $customOptions = array()
+ ) {
+ // bind method should be tested in functional test
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function bindDataProvider()
+ {
+ return array(
+ 'empty' => array(
+ 'bindData' => array(),
+ 'formData' => array(),
+ 'viewData' => array(),
+ ),
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/AbstractAttributeType.php b/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/AbstractAttributeType.php
index bd0724efc06..d6b1eabfed0 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/AbstractAttributeType.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/AbstractAttributeType.php
@@ -6,6 +6,7 @@
use Oro\Bundle\FlexibleEntityBundle\AttributeType\AttributeTypeInterface;
use Oro\Bundle\FlexibleEntityBundle\Model\FlexibleValueInterface;
use Oro\Bundle\FlexibleEntityBundle\Model\AbstractAttribute;
+use Oro\Bundle\FlexibleEntityBundle\Form\Validator\ConstraintGuesserInterface;
/**
* Abstract attribute type
@@ -32,6 +33,7 @@ abstract class AbstractAttributeType implements AttributeTypeInterface
const BACKEND_TYPE_DATE = 'date';
const BACKEND_TYPE_DATETIME = 'datetime';
const BACKEND_TYPE_DECIMAL = 'decimal';
+ const BACKEND_TYPE_BOOLEAN = 'boolean';
const BACKEND_TYPE_INTEGER = 'integer';
const BACKEND_TYPE_OPTIONS = 'options';
const BACKEND_TYPE_OPTION = 'option';
@@ -59,13 +61,14 @@ abstract class AbstractAttributeType implements AttributeTypeInterface
/**
* Constructor
*
- * @param string $backendType the backend type
- * @param string $formType the form type
+ * @param string $backendType the backend type
+ * @param string $formType the form type
*/
- public function __construct($backendType, $formType)
+ public function __construct($backendType, $formType, ConstraintGuesserInterface $constraintGuesser)
{
- $this->backendType = $backendType;
- $this->formType = $formType;
+ $this->backendType = $backendType;
+ $this->formType = $formType;
+ $this->constraintGuesser = $constraintGuesser;
}
/**
@@ -95,11 +98,13 @@ public function buildValueFormType(FormFactoryInterface $factory, FlexibleValueI
{
$name = $this->prepareValueFormName($value);
$type = $this->prepareValueFormAlias($value);
- $options = $this->prepareValueFormOptions($value);
$data = $this->prepareValueFormData($value);
- $form = $factory->createNamed($name, $type, $data, $options);
+ $options = array_merge(
+ $this->prepareValueFormConstraints($value),
+ $this->prepareValueFormOptions($value)
+ );
- return $form;
+ return $factory->createNamed($name, $type, $data, $options);
}
/**
@@ -135,29 +140,24 @@ protected function prepareValueFormAlias(FlexibleValueInterface $value)
*/
protected function prepareValueFormOptions(FlexibleValueInterface $value)
{
- $options = array(
- 'label' => $value->getAttribute()->getLabel(),
- 'required' => $value->getAttribute()->getRequired(),
- 'constraints' => array()
+ return array(
+ 'label' => $value->getAttribute()->getLabel(),
+ 'required' => $value->getAttribute()->getRequired(),
);
+ }
- if ($options['required']) {
- $options['constraints'][] = new Constraints\NotBlank();
- }
-
- switch ($value->getAttribute()->getBackendType()) {
- case self::BACKEND_TYPE_DATE:
- $options['constraints'][] = new Constraints\Date();
- break;
- case self::BACKEND_TYPE_DATE:
- $options['constraints'][] = new Constraints\Date();
- break;
- case self::BACKEND_TYPE_DATETIME:
- $options['constraints'][] = new Constraints\DateTime();
- break;
+ /**
+ * Guess the constraints to apply on the form
+ */
+ protected function prepareValueFormConstraints(FlexibleValueInterface $value)
+ {
+ if ($this->constraintGuesser->supportAttribute($attribute = $value->getAttribute())) {
+ return array(
+ 'constraints' => $this->constraintGuesser->guessConstraints($attribute),
+ );
}
- return $options;
+ return array();
}
/**
@@ -175,10 +175,47 @@ protected function prepareValueFormData(FlexibleValueInterface $value)
/**
* {@inheritdoc}
*/
- public function buildAttributeFormType(FormFactoryInterface $factory, AbstractAttribute $attribute)
+ public function buildAttributeFormTypes(FormFactoryInterface $factory, AbstractAttribute $attribute)
{
- // TODO will be used to build attribute create / edit form for attribute management, cf BAP-650
+ $properties = $this->defineCustomAttributeProperties($attribute);
+
+ $types = array();
+
+ foreach ($properties as $property) {
+ $fieldType = 'text';
+ if (isset($property['fieldType'])) {
+ $fieldType = $property['fieldType'];
+ }
+ $data = null;
+ if (isset($property['data'])) {
+ $data = $property['data'];
+ }
+ $options = array();
+ if (isset($property['options'])) {
+ $options = $property['options'];
+ }
+ if (!isset($options['required'])) {
+ $options['required'] = false;
+ }
+
+ $types[] = $factory->createNamed($property['name'], $fieldType, $data, $options);
+ }
- return null;
+ return $types;
+ }
+
+ /**
+ * Define custom properties used in attribute form
+ *
+ * Each property must be an array with a 'name' key that matches the name of the property
+ * Optional 'fieldType', 'data' and 'options' keys can be provided for field customization
+ *
+ * @param AbstractAttribute $attribute Attribute entity
+ *
+ * @return array:array:multitype $properties an array of custom properties
+ */
+ protected function defineCustomAttributeProperties(AbstractAttribute $attribute)
+ {
+ return array();
}
}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/AttributeTypeInterface.php b/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/AttributeTypeInterface.php
index e83124005c5..a18bdb5197b 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/AttributeTypeInterface.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/AttributeTypeInterface.php
@@ -32,12 +32,12 @@ public function getName();
public function buildValueFormType(FormFactoryInterface $factory, FlexibleValueInterface $value);
/**
- * Build form type for attribute
+ * Build form types for custom properties of an attribute
*
* @param FormFactoryInterface $factory the form factory
* @param AbstractAttribute $attribute the attribute
*
* @return FormInterface the form
*/
- public function buildAttributeFormType(FormFactoryInterface $factory, AbstractAttribute $attribute);
+ public function buildAttributeFormTypes(FormFactoryInterface $factory, AbstractAttribute $attribute);
}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/MetricType.php b/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/MetricType.php
index f0716a4fa60..8ce9fa69106 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/MetricType.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/MetricType.php
@@ -4,6 +4,7 @@
use Oro\Bundle\FlexibleEntityBundle\AttributeType\AbstractAttributeType;
use Oro\Bundle\FlexibleEntityBundle\Model\FlexibleValueInterface;
use Oro\Bundle\MeasureBundle\Manager\MeasureManager;
+use Oro\Bundle\FlexibleEntityBundle\Form\Validator\ConstraintGuesserInterface;
/**
* Metric attribute type
@@ -23,9 +24,9 @@ class MetricType extends AbstractAttributeType
* @param string $formType the form type
* @param MeasureManager $manager The measure manager
*/
- public function __construct($backendType, $formType, MeasureManager $manager)
+ public function __construct($backendType, $formType, ConstraintGuesserInterface $constraintGuesser, MeasureManager $manager)
{
- parent::__construct($backendType, $formType);
+ parent::__construct($backendType, $formType, $constraintGuesser);
$this->manager = $manager;
}
@@ -43,13 +44,14 @@ public function getName()
*/
protected function prepareValueFormOptions(FlexibleValueInterface $value)
{
- return array(
- 'label' => $value->getAttribute()->getLabel(),
- 'required' => $value->getAttribute()->getRequired(),
- 'units' => $this->manager->getUnitSymbolsForFamily(
- $value->getAttribute()->getMetricFamily()
- ),
- 'default_unit' => $value->getAttribute()->getDefaultMetricUnit(),
+ return array_merge(
+ parent::prepareValueFormOptions($value),
+ array(
+ 'units' => $this->manager->getUnitSymbolsForFamily(
+ $value->getAttribute()->getMetricFamily()
+ ),
+ 'default_unit' => $value->getAttribute()->getDefaultMetricUnit(),
+ )
);
}
}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/OptionMultiCheckboxType.php b/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/OptionMultiCheckboxType.php
index 5a0c9f8d4d8..e43e65a83d2 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/OptionMultiCheckboxType.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/AttributeType/OptionMultiCheckboxType.php
@@ -1,7 +1,7 @@
array('=', '<', '<=', '>', '>='),
AbstractAttributeType::BACKEND_TYPE_DECIMAL => array('=', '<', '<=', '>', '>='),
AbstractAttributeType::BACKEND_TYPE_INTEGER => array('=', '<', '<=', '>', '>='),
+ AbstractAttributeType::BACKEND_TYPE_BOOLEAN => array('='),
AbstractAttributeType::BACKEND_TYPE_OPTION => array('IN', 'NOT IN'),
AbstractAttributeType::BACKEND_TYPE_OPTIONS => array('IN', 'NOT IN'),
AbstractAttributeType::BACKEND_TYPE_TEXT => array('=', 'NOT LIKE', 'LIKE'),
@@ -153,6 +154,9 @@ public function getAllowedOperators($backendType)
*
* @return string
* @throws FlexibleQueryException
+ *
+ * @SuppressWarnings(PHPMD)
+ * TODO: This method should be refactored (BAP-974).
*/
public function prepareCriteriaCondition($field, $operator, $value)
{
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Entity/Mapping/AbstractEntityFlexibleValue.php b/src/Oro/Bundle/FlexibleEntityBundle/Entity/Mapping/AbstractEntityFlexibleValue.php
index 1f2e4b5eeb5..25108c8f84f 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Entity/Mapping/AbstractEntityFlexibleValue.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Entity/Mapping/AbstractEntityFlexibleValue.php
@@ -84,6 +84,14 @@ abstract class AbstractEntityFlexibleValue extends AbstractFlexibleValue
*/
protected $decimal;
+ /**
+ * Store boolean value
+ * @var boolean $boolean
+ *
+ * @ORM\Column(name="value_boolean", type="boolean", nullable=true)
+ */
+ protected $boolean;
+
/**
* Store text value
* @var string $text
@@ -149,6 +157,16 @@ public function __construct()
$this->collection = new ArrayCollection();
}
+ /**
+ * Get entity
+ *
+ * @return AbstractFlexible $entity
+ */
+ public function getEntity()
+ {
+ return $this->entity;
+ }
+
/**
* Set entity
*
@@ -261,6 +279,30 @@ public function setDecimal($decimal)
return $this;
}
+ /**
+ * Get boolean data
+ *
+ * @return boolean
+ */
+ public function getBoolean()
+ {
+ return $this->boolean;
+ }
+
+ /**
+ * Set boolean data
+ *
+ * @param boolean $boolean
+ *
+ * @return EntityAttributeValue
+ */
+ public function setBoolean($boolean)
+ {
+ $this->boolean = $boolean;
+
+ return $this;
+ }
+
/**
* Get text data
*
@@ -340,7 +382,7 @@ public function setDatetime($datetime)
*
* @return AbstractEntityFlexibleValue
*/
- public function setOption(AbstractEntityAttributeOption $option)
+ public function setOption(AbstractEntityAttributeOption $option = null)
{
$this->option = $option;
@@ -421,7 +463,7 @@ public function getCollection()
* @param AbstractEntityFlexibleValue $value
* @return $this
*/
- public function setCollections(AbstractEntityFlexibleValue $value)
+ public function setCollections(AbstractEntityFlexibleValue $value = null)
{
$this->collection = $value->getCollections();
@@ -460,7 +502,7 @@ public function __toString()
return implode(', ', $items);
- } else if (is_object($data)) {
+ } elseif (is_object($data)) {
return $data->__toString();
}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Entity/Repository/FlexibleEntityRepository.php b/src/Oro/Bundle/FlexibleEntityBundle/Entity/Repository/FlexibleEntityRepository.php
index 75a53d9e80f..8c22dc395a0 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Entity/Repository/FlexibleEntityRepository.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Entity/Repository/FlexibleEntityRepository.php
@@ -214,11 +214,8 @@ public function createFlexibleQueryBuilder($alias, $attributeCodes = null)
$this->entityAlias = $alias;
$qb = new FlexibleQueryBuilder($this->_em);
- // TODO : grid integration, find a smart way to inject locale and scope in repo then qb
- $locale = ($this->getLocale() !== null) ? $this->getLocale() : 'en_US';
- $scope = ($this->getScope() !== null) ? $this->getScope() : 'ecommerce';
- $qb->setLocale($locale);
- $qb->setScope($scope);
+ $qb->setLocale($this->getLocale());
+ $qb->setScope($this->getScope());
$qb->select($alias, 'Value', 'Attribute', 'ValueOption', 'AttributeOptionValue')
->from($this->_entityName, $this->entityAlias);
@@ -374,24 +371,18 @@ public function findWithAttributes($id)
}
/**
- * Load a flexible entity with only localized values
+ * Load a flexible entity with its attributes sorted by sortOrder
*
* @param integer $id
*
- * @return AbstractFlexible
+ * @return AbstractFlexible|null
+ * @throws NonUniqueResultException
*/
- public function findWithLocalizedValuesAndSortedAttributes($id)
+ public function findWithSortedAttribute($id)
{
- $qb = $this->findByWithAttributesQB(array(), array('id' => $id));
-
- return $qb
- ->andWhere(
- $qb->expr()->orX(
- $qb->expr()->isNull('Value.locale'),
- $qb->expr()->eq('Value.locale', $qb->expr()->literal($this->getLocale()))
- )
- )
- ->orderBy('Attribute.sortOrder')
+ return $this
+ ->findByWithAttributesQB(array(), array('id' => $id))
+ ->addOrderBy('Attribute.sortOrder')
->getQuery()
->getOneOrNullResult();
}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/EventListener/TimestampableListener.php b/src/Oro/Bundle/FlexibleEntityBundle/EventListener/TimestampableListener.php
index a08e9081b73..5b45509f04c 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/EventListener/TimestampableListener.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/EventListener/TimestampableListener.php
@@ -2,8 +2,10 @@
namespace Oro\Bundle\FlexibleEntityBundle\EventListener;
use Doctrine\Common\EventSubscriber;
+use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Oro\Bundle\FlexibleEntityBundle\Model\Behavior\TimestampableInterface;
+use Oro\Bundle\FlexibleEntityBundle\Model\AbstractFlexible;
/**
* Aims to add timestambable behavior
@@ -47,8 +49,35 @@ public function prePersist(LifecycleEventArgs $args)
public function preUpdate(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
+
+ if ($entity instanceof \Oro\Bundle\FlexibleEntityBundle\Entity\Mapping\AbstractEntityFlexibleValue) {
+ $flexible = $entity->getEntity();
+ if ($flexible !== null) {
+ $this->updateFlexibleFields($args->getEntityManager(), $flexible, array('updated'));
+ }
+ }
+
if ($entity instanceof \Oro\Bundle\FlexibleEntityBundle\Model\Behavior\TimestampableInterface) {
$entity->setUpdated(new \DateTime('now', new \DateTimeZone('UTC')));
}
}
+
+ /**
+ * Update flexible fields when a value is updated
+ *
+ * @param ObjectManager $om
+ * @param Flexible $flexible
+ * @param array $fields
+ */
+ protected function updateFlexibleFields(ObjectManager $om, AbstractFlexible $flexible, $fields)
+ {
+ $meta = $om->getClassMetadata(get_class($flexible));
+ $uow = $om->getUnitOfWork();
+ $now = new \DateTime('now', new \DateTimeZone('UTC'));
+ $changes = array();
+ foreach ($fields as $field) {
+ $changes[$field]= array(null, $now);
+ }
+ $uow->scheduleExtraUpdate($flexible, $changes);
+ }
}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Form/Type/FlexibleType.php b/src/Oro/Bundle/FlexibleEntityBundle/Form/Type/FlexibleType.php
index 03c3cef1f01..dc6d0434be1 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Form/Type/FlexibleType.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Form/Type/FlexibleType.php
@@ -52,7 +52,7 @@ public function __construct(FlexibleManager $flexibleManager, $valueFormAlias)
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->addEntityFields($builder);
- $this->addDynamicAttributesFields($builder);
+ $this->addDynamicAttributesFields($builder, $options);
}
/**
@@ -70,7 +70,7 @@ public function addEntityFields(FormBuilderInterface $builder)
*
* @param FormBuilderInterface $builder
*/
- public function addDynamicAttributesFields(FormBuilderInterface $builder)
+ public function addDynamicAttributesFields(FormBuilderInterface $builder, array $options)
{
$builder->add(
'values',
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Form/Type/MetricType.php b/src/Oro/Bundle/FlexibleEntityBundle/Form/Type/MetricType.php
index ec4612b5439..2b21a6a0813 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Form/Type/MetricType.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Form/Type/MetricType.php
@@ -28,8 +28,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
$builder
->add('id', 'hidden')
->add('data', 'number')
- ->add('unit', 'choice', $unitOptions)
- ;
+ ->add('unit', 'choice', $unitOptions);
}
/**
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Form/Validator/AttributeConstraintGuesser.php b/src/Oro/Bundle/FlexibleEntityBundle/Form/Validator/AttributeConstraintGuesser.php
new file mode 100644
index 00000000000..c993ea69e20
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Form/Validator/AttributeConstraintGuesser.php
@@ -0,0 +1,46 @@
+
+ * @copyright 2013 Akeneo SAS (http://www.akeneo.com)
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
+ */
+class AttributeConstraintGuesser implements ConstraintGuesserInterface
+{
+ public function supportAttribute(AbstractAttribute $attribute)
+ {
+ return true;
+ }
+
+ public function guessConstraints(AbstractAttribute $attribute)
+ {
+ $constraints = array();
+
+ if ($attribute->getRequired()) {
+ $constraints[] = new Constraints\NotBlank();
+ }
+
+ switch ($attribute->getBackendType()) {
+ case AbstractAttributeType::BACKEND_TYPE_DATE:
+ $constraints[] = new Constraints\Date();
+ break;
+ case AbstractAttributeType::BACKEND_TYPE_DATETIME:
+ $constraints[] = new Constraints\DateTime();
+ break;
+ }
+
+ switch ($attribute->getAttributeType()) {
+ case 'oro_flexibleentity_email':
+ $constraints[] = new Constraints\Email();
+ break;
+ }
+
+ return $constraints;
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Form/Validator/ConstraintGuesserInterface.php b/src/Oro/Bundle/FlexibleEntityBundle/Form/Validator/ConstraintGuesserInterface.php
new file mode 100644
index 00000000000..269b48e7a07
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Form/Validator/ConstraintGuesserInterface.php
@@ -0,0 +1,31 @@
+
+ * @copyright 2013 Akeneo SAS (http://www.akeneo.com)
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
+ */
+interface ConstraintGuesserInterface
+{
+ /**
+ * Tells wether or not the constraint guesser supports the given attribute type
+ *
+ * @param AbstractAttribute $attribute
+ *
+ * @return bool
+ */
+ public function supportAttribute(AbstractAttribute $attribute);
+
+ /**
+ * Guess the constraints for the given attribute
+ *
+ * @param AbstractAttribute $attribute
+ *
+ * @return Symfony\Component\Validator\Constraint[]
+ */
+ public function guessConstraints(AbstractAttribute $attribute);
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Manager/FlexibleManager.php b/src/Oro/Bundle/FlexibleEntityBundle/Manager/FlexibleManager.php
index 0957c790f4a..0e73e361499 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Manager/FlexibleManager.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Manager/FlexibleManager.php
@@ -83,8 +83,13 @@ class FlexibleManager implements TranslatableInterface, ScopableInterface
* @param EventDispatcherInterface $eventDispatcher Event dispatcher
* @param AttributeTypeFactory $attributeTypeFactory Attribute type factory
*/
- public function __construct($flexibleName, $flexibleConfig, ObjectManager $storageManager, EventDispatcherInterface $eventDispatcher, AttributeTypeFactory $attributeTypeFactory)
- {
+ public function __construct(
+ $flexibleName,
+ $flexibleConfig,
+ ObjectManager $storageManager,
+ EventDispatcherInterface $eventDispatcher,
+ AttributeTypeFactory $attributeTypeFactory
+ ) {
$this->flexibleName = $flexibleName;
$this->flexibleConfig = $flexibleConfig['entities_config'][$flexibleName];
$this->storageManager = $storageManager;
@@ -368,21 +373,6 @@ public function createFlexibleValue()
return $value;
}
- /**
- * Return only localized values of flexible entity
- *
- * @param integer $id
- *
- * @return AbstractFlexible
- */
- public function localizedFind($id)
- {
- $fr = $this->getFlexibleRepository();
- $fr->setLocale($this->getLocale());
-
- return $fr->findWithLocalizedValuesAndSortedAttributes($id);
- }
-
/**
* Get attribute type factory
*
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Manager/FlexibleManagerRegistry.php b/src/Oro/Bundle/FlexibleEntityBundle/Manager/FlexibleManagerRegistry.php
index 2be18e41880..0c79b84dce4 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Manager/FlexibleManagerRegistry.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Manager/FlexibleManagerRegistry.php
@@ -1,7 +1,7 @@
entityToManager[$entityFQCN];
+ $realClassName = ClassUtils::getRealClass($entityFQCN);
+ return $this->entityToManager[$realClassName];
}
}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Resources/config/attribute_types.yml b/src/Oro/Bundle/FlexibleEntityBundle/Resources/config/attribute_types.yml
index 83103b84eb9..aede0e3c5fd 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Resources/config/attribute_types.yml
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Resources/config/attribute_types.yml
@@ -1,112 +1,199 @@
services:
oro_flexibleentity.attributetype.boolean:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\BooleanType
- arguments: ["integer", "option"]
+ arguments:
+ - "boolean"
+ - "checkbox"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_boolean }
+
oro_flexibleentity.attributetype.text:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\TextType
- arguments: ["varchar", "text"]
+ arguments:
+ - "varchar"
+ - "text"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_text }
+
oro_flexibleentity.attributetype.textarea:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\TextAreaType
- arguments: ["text", "textarea"]
+ arguments:
+ - "text"
+ - "textarea"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_textarea }
+
oro_flexibleentity.attributetype.date:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\DateType
- arguments: ["date", "oro_date"]
+ arguments:
+ - "date"
+ - "oro_date"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_date }
+
oro_flexibleentity.attributetype.datetime:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\DateTimeType
- arguments: ["datetime", "oro_datetime"]
+ arguments:
+ - "datetime"
+ - "oro_datetime"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_datetime }
+
oro_flexibleentity.attributetype.integer:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\IntegerType
- arguments: ["integer", "integer"]
+ arguments:
+ - "integer"
+ - "integer"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_integer }
+
oro_flexibleentity.attributetype.money:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\MoneyType
- arguments: ["decimal", "money"]
+ arguments:
+ - "decimal"
+ - "money"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_money }
+
oro_flexibleentity.attributetype.number:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\NumberType
- arguments: ["decimal", "number"]
+ arguments:
+ - "decimal"
+ - "number"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_number }
+
oro_flexibleentity.attributetype.multiselect:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\OptionMultiSelectType
- arguments: ["options", "entity"]
+ arguments:
+ - "options"
+ - "entity"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_multiselect }
+
oro_flexibleentity.attributetype.simpleselect:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\OptionSimpleSelectType
- arguments: ["option", "entity"]
+ arguments:
+ - "option"
+ - "entity"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_simpleselect }
+
oro_flexibleentity.attributetype.metric:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\MetricType
- arguments: ["metric", "oro_flexibleentity_metric", @oro_measure.manager]
+ arguments:
+ - "metric"
+ - "oro_flexibleentity_metric"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
+ - @oro_measure.manager
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_metric }
+
oro_flexibleentity.attributetype.file:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\FileType
- arguments: ["media", "oro_media"]
+ arguments:
+ - "media"
+ - "oro_media"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_file }
+
oro_flexibleentity.attributetype.image:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\ImageType
- arguments: ["media", "oro_media"]
+ arguments:
+ - "media"
+ - "oro_media"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_image }
+
oro_flexibleentity.attributetype.fileurl:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\FileUrlType
- arguments: ["media", "oro_media"]
+ arguments:
+ - "media"
+ - "oro_media"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_fileurl }
+
oro_flexibleentity.attributetype.imageurl:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\ImageUrlType
- arguments: ["media", "oro_media"]
+ arguments:
+ - "media"
+ - "oro_media"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_imageurl }
+
oro_flexibleentity.attributetype.email:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\EmailType
- arguments: ["varchar", "email"]
+ arguments:
+ - "varchar"
+ - "email"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_email }
+
oro_flexibleentity.attributetype.url:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\UrlType
- arguments: ["varchar", "url"]
+ arguments:
+ - "varchar"
+ - "url"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_url }
+
oro_flexibleentity.attributetype.multicheckbox:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\OptionMultiCheckboxType
- arguments: ["options", "entity"]
+ arguments:
+ - "options"
+ - "entity"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_multicheckbox }
+
oro_flexibleentity.attributetype.simpleradio:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\OptionSimpleRadioType
- arguments: ["option", "entity"]
+ arguments:
+ - "option"
+ - "entity"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_simpleradio }
+
oro_flexibleentity.attributetype.price:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\PriceType
- arguments: ["price", "oro_flexibleentity_price"]
+ arguments:
+ - "price"
+ - "oro_flexibleentity_price"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_price }
+
oro_flexibleentity.attributetype.email_collection:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\EmailCollectionType
- arguments: ["collections", "oro_flexibleentity_email_collection"]
+ arguments:
+ - "collections"
+ - "oro_flexibleentity_email_collection"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_email_collection }
+
oro_flexibleentity.attributetype.phone_collection:
class: Oro\Bundle\FlexibleEntityBundle\AttributeType\PhoneCollectionType
- arguments: ["collections", "oro_flexibleentity_phone_collection"]
+ arguments:
+ - "collections"
+ - "oro_flexibleentity_phone_collection"
+ - @oro_flexibleentity.validator.attribute_constraint_guesser
tags:
- { name: oro_flexibleentity.attributetype, alias: oro_flexibleentity_phone_collection }
-
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Resources/config/services.yml b/src/Oro/Bundle/FlexibleEntityBundle/Resources/config/services.yml
index 18b8a58ac24..9bbcba2a71f 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Resources/config/services.yml
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Resources/config/services.yml
@@ -1,8 +1,10 @@
parameters:
- oro_flexibleentity.flexible_config: ~
- oro_flexibleentity.registry.class: Oro\Bundle\FlexibleEntityBundle\Manager\FlexibleManagerRegistry
- oro_flexibleentity.attributetype.factory.class: Oro\Bundle\FlexibleEntityBundle\AttributeType\AttributeTypeFactory
- oro_flexibleentity.value_form.value_subscriber.class: Oro\Bundle\FlexibleEntityBundle\Form\EventListener\FlexibleValueSubscriber
+ oro_flexibleentity.flexible_config: ~
+ oro_flexibleentity.registry.class: Oro\Bundle\FlexibleEntityBundle\Manager\FlexibleManagerRegistry
+ oro_flexibleentity.attributetype.factory.class: Oro\Bundle\FlexibleEntityBundle\AttributeType\AttributeTypeFactory
+ oro_flexibleentity.value_form.value_subscriber.class: Oro\Bundle\FlexibleEntityBundle\Form\EventListener\FlexibleValueSubscriber
+ oro_flexibleentity.filterAttributes.twig.extension.class: Oro\Bundle\FlexibleEntityBundle\Twig\FilterAttributesExtension
+ oro_flexibleentity.validator.attribute_constraint_guesser.class: Oro\Bundle\FlexibleEntityBundle\Form\Validator\AttributeConstraintGuesser
services:
oro_flexibleentity.value_form.value_subscriber:
@@ -89,3 +91,12 @@ services:
class: Oro\Bundle\FlexibleEntityBundle\Form\Type\EmailCollectionType
tags:
- { name: form.type, alias: oro_flexibleentity_email_collection }
+
+ oro_flexibleentity.filterAttributes.twig.extension:
+ class: %oro_flexibleentity.filterAttributes.twig.extension.class%
+ tags:
+ - { name: twig.extension }
+
+ oro_flexibleentity.validator.attribute_constraint_guesser:
+ class: %oro_flexibleentity.validator.attribute_constraint_guesser.class%
+ public: false
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AbstractFlexibleEntityManagerTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AbstractFlexibleEntityManagerTest.php
index 744ae3e969b..9bb478bc505 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AbstractFlexibleEntityManagerTest.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AbstractFlexibleEntityManagerTest.php
@@ -107,7 +107,7 @@ public function setUp()
$this->container->setParameter('oro_flexibleentity.flexible_config', $this->flexibleConfig);
// prepare attribute type factory
- $attType = new TextType('varchar', 'text');
+ $attType = new TextType('varchar', 'text', $this->getMock('Oro\Bundle\FlexibleEntityBundle\Form\Validator\AttributeConstraintGuesser'));
$this->container->set('oro_flexibleentity.attributetype.text', $attType);
$attTypes = array('oro_flexibleentity_text' => 'oro_flexibleentity.attributetype.text');
$this->attributeTypeFactory = new AttributeTypeFactory($this->container, $attTypes);
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/AttributeTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/AttributeTypeTest.php
index 47082ba08db..1f82b888f58 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/AttributeTypeTest.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/AttributeTypeTest.php
@@ -1,46 +1,104 @@
- * @copyright 2012 Akeneo SAS (http://www.akeneo.com)
- * @license http://opensource.org/licenses/MIT MIT
- */
-class AttributeTypeTest extends \PHPUnit_Framework_TestCase
+ * @author Gildas Quemener
+ * @copyright 2013 Akeneo SAS (http://www.akeneo.com)
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
+ */
+abstract class AttributeTypeTest extends \PHPUnit_Framework_TestCase
{
- /**
- * Data provider
- *
- * @return array
- *
- * @static
- */
- public static function typesProvider()
+ protected $target;
+ protected $name;
+
+ public function setUp()
+ {
+ $this->guesser = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Form\Validator\AttributeConstraintGuesser');
+ $this->guesser->expects($this->any())
+ ->method('supportAttribute')
+ ->will($this->returnValue(true));
+ $this->guesser->expects($this->any())
+ ->method('guessConstraints')
+ ->will($this->returnValue(array('constraints')));
+ }
+
+ public function testGetName()
+ {
+ if (!$this->target) {
+ throw new \Exception(sprintf('You must override the setUp() method and provide a $target instance.'));
+ }
+
+ if (!$this->name) {
+ throw new \Exception(sprintf('You must override the $name property.'));
+ }
+ $this->assertEquals($this->name, $this->target->getName());
+ }
+
+ public function testAssertInstanceOfAbstractAttributeType()
+ {
+ if (!$this->target) {
+ throw new \Exception(sprintf('You must override the setUp() method and provide a $target instance.'));
+ }
+ $this->assertInstanceOf('Oro\Bundle\FlexibleEntityBundle\AttributeType\AbstractAttributeType', $this->target);
+ }
+
+ protected function getFormFactoryMock()
{
- return array(
- array('Oro\Bundle\FlexibleEntityBundle\AttributeType\BooleanType', 'integer', 'option', 'oro_flexibleentity_boolean'),
- array('Oro\Bundle\FlexibleEntityBundle\AttributeType\TextType', 'varchar', 'text', 'oro_flexibleentity_text'),
- array('Oro\Bundle\FlexibleEntityBundle\AttributeType\TextAreaType', 'text', 'textarea', 'oro_flexibleentity_textarea')
+ return $this
+ ->getMockBuilder('Symfony\Component\Form\FormFactory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ protected function getFlexibleValueMock(array $options)
+ {
+ $options = array_merge(
+ array(
+ 'data' => null,
+ 'defaultValue' => null,
+ 'backendType' => null,
+ ),
+ $options
);
+
+ $value = $this->getMock(
+ 'Oro\Bundle\FlexibleEntityBundle\Model\FlexibleValueInterface',
+ array(
+ 'getAttribute', 'getData'
+ )
+ );
+
+ $value->expects($this->any())
+ ->method('getAttribute')
+ ->will(
+ $this->returnValue(
+ $this->getAttributeMock(
+ $options['backendType'],
+ $options['defaultValue']
+ )
+ )
+ );
+
+ $value->expects($this->any())
+ ->method('getData')
+ ->will($this->returnValue($options['data']));
+
+ return $value;
}
- /**
- * Test related methods
- *
- * @param string $class
- * @param string $backend
- * @param string $form
- * @param string $name
- *
- * @dataProvider typesProvider
- */
- public function testConstructorAnGetters($class, $backend, $form, $name)
+ protected function getAttributeMock($backendType, $defaultValue)
{
- $attType = new $class($backend, $form);
- $this->assertEquals($attType->getName(), $name);
- $this->assertEquals($attType->getBackendType(), $backend);
- $this->assertEquals($attType->getFormType(), $form);
+ $attribute = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Model\AbstractAttribute');
+
+ $attribute->expects($this->any())
+ ->method('getBackendType')
+ ->will($this->returnValue($backendType));
+
+ $attribute->expects($this->any())
+ ->method('getDefaultValue')
+ ->will($this->returnValue($defaultValue));
+
+ return $attribute;
}
}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/BooleanTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/BooleanTypeTest.php
new file mode 100644
index 00000000000..3ff7d3083c3
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/BooleanTypeTest.php
@@ -0,0 +1,64 @@
+target = new BooleanType('text', 'email', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'email',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('text', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('email', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/DateTimeTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/DateTimeTypeTest.php
new file mode 100644
index 00000000000..92a20583102
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/DateTimeTypeTest.php
@@ -0,0 +1,71 @@
+
+ * @copyright 2013 Akeneo SAS (http://www.akeneo.com)
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
+ */
+class DateTimeTypeTest extends AttributeTypeTest
+{
+ protected $name = 'oro_flexibleentity_datetime';
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->target = new DateTimeType('integer', 'date', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'date',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ 'widget' => 'single_text',
+ 'input' => 'datetime',
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('integer', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('date', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/DateTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/DateTypeTest.php
new file mode 100644
index 00000000000..342a2cb01cf
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/DateTypeTest.php
@@ -0,0 +1,71 @@
+
+ * @copyright 2013 Akeneo SAS (http://www.akeneo.com)
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
+ */
+class DateTypeTest extends AttributeTypeTest
+{
+ protected $name = 'oro_flexibleentity_date';
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->target = new DateType('integer', 'date', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'date',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ 'widget' => 'single_text',
+ 'input' => 'datetime',
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('integer', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('date', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/EmailCollectionTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/EmailCollectionTypeTest.php
index fd63a1129f3..016b384bac7 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/EmailCollectionTypeTest.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/EmailCollectionTypeTest.php
@@ -3,37 +3,62 @@
use Oro\Bundle\FlexibleEntityBundle\AttributeType\EmailCollectionType;
-class EmailCollectionTypeTest extends \PHPUnit_Framework_TestCase
+class EmailCollectionTypeTest extends AttributeTypeTest
{
- /**
- * Data provider
- *
- * @return array
- *
- * @static
- */
- public static function typesProvider()
+ protected $name = 'oro_flexibleentity_email_collection';
+
+ public function setUp()
{
- return array(
- array('Oro\Bundle\FlexibleEntityBundle\AttributeType\EmailCollectionType', 'integer', 'option', 'oro_flexibleentity_email_collection'),
+ parent::setUp();
+
+ $this->target = new EmailCollectionType('collections', 'text', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $email = $this->getFlexibleValueMock(array());
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => $email,
+ 'backendType' => 'foo',
+ )
);
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'text',
+ $email,
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
}
- /**
- * Test related methods
- *
- * @param string $class
- * @param string $backend
- * @param string $form
- * @param string $name
- *
- * @dataProvider typesProvider
- */
- public function testConstructorAnGetters($class, $backend, $form, $name)
+ public function testGetBackendType()
{
- $attType = new $class($backend, $form);
- $this->assertEquals($attType->getName(), $name);
- $this->assertEquals($attType->getBackendType(), $backend);
- $this->assertEquals($attType->getFormType(), $form);
+ $this->assertEquals('collections', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('text', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
}
}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/EmailTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/EmailTypeTest.php
index 9b3235be8e6..425af8877e8 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/EmailTypeTest.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/EmailTypeTest.php
@@ -1,20 +1,64 @@
target = new EmailType('text', 'email', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'email',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('text', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('email', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
{
- $backend = 'varchar';
- $attType = new EmailType($backend, 'test');
- $this->assertEquals($attType->getName(), 'oro_flexibleentity_email');
- $this->assertEquals($attType->getBackendType(), $backend);
- $this->assertEquals($attType->getFormType(), 'test');
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
}
}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/FileTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/FileTypeTest.php
new file mode 100644
index 00000000000..5c2b78c164e
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/FileTypeTest.php
@@ -0,0 +1,64 @@
+target = new FileType('varchar', 'text', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'text',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('varchar', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('text', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/FileUrlTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/FileUrlTypeTest.php
new file mode 100644
index 00000000000..a4dbd543f80
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/FileUrlTypeTest.php
@@ -0,0 +1,64 @@
+target = new FileUrlType('varchar', 'text', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'text',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('varchar', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('text', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/ImageTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/ImageTypeTest.php
new file mode 100644
index 00000000000..70cf2cbd1e3
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/ImageTypeTest.php
@@ -0,0 +1,64 @@
+target = new ImageType('varchar', 'text', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'text',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('varchar', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('text', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/ImageUrlTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/ImageUrlTypeTest.php
new file mode 100644
index 00000000000..d8ee8604217
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/ImageUrlTypeTest.php
@@ -0,0 +1,64 @@
+target = new ImageUrlType('varchar', 'text', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'text',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('varchar', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('text', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/IntegerTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/IntegerTypeTest.php
new file mode 100644
index 00000000000..b661cf94f06
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/IntegerTypeTest.php
@@ -0,0 +1,64 @@
+target = new IntegerType('integer', 'text', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'text',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('integer', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('text', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/MoneyTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/MoneyTypeTest.php
new file mode 100644
index 00000000000..8133093d470
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/MoneyTypeTest.php
@@ -0,0 +1,64 @@
+target = new MoneyType('varchar', 'text', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'text',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('varchar', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('text', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/NumberTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/NumberTypeTest.php
new file mode 100644
index 00000000000..e2b712e981a
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/NumberTypeTest.php
@@ -0,0 +1,64 @@
+target = new NumberType('number', 'text', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'text',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('number', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('text', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/OptionMultiCheckboxTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/OptionMultiCheckboxTypeTest.php
new file mode 100644
index 00000000000..134e2991061
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/OptionMultiCheckboxTypeTest.php
@@ -0,0 +1,70 @@
+target = new OptionMultiCheckboxType('text', 'email', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'email',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ 'empty_value' => false,
+ 'class' => 'OroFlexibleEntityBundle:AttributeOption',
+ 'expanded' => true,
+ 'multiple' => true,
+ 'query_builder' => function () {
+ },
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('text', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('email', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/OptionMultiSelectTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/OptionMultiSelectTypeTest.php
new file mode 100644
index 00000000000..1338c876788
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/OptionMultiSelectTypeTest.php
@@ -0,0 +1,70 @@
+target = new OptionMultiSelectType('text', 'email', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'email',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ 'empty_value' => false,
+ 'class' => 'OroFlexibleEntityBundle:AttributeOption',
+ 'expanded' => false,
+ 'multiple' => true,
+ 'query_builder' => function () {
+ },
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('text', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('email', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/OptionSimpleRadioTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/OptionSimpleRadioTypeTest.php
new file mode 100644
index 00000000000..7b3f2119720
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/OptionSimpleRadioTypeTest.php
@@ -0,0 +1,70 @@
+target = new OptionSimpleRadioType('text', 'email', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'email',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ 'empty_value' => false,
+ 'class' => 'OroFlexibleEntityBundle:AttributeOption',
+ 'expanded' => true,
+ 'multiple' => false,
+ 'query_builder' => function () {
+ },
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('text', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('email', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/OptionSimpleSelectTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/OptionSimpleSelectTypeTest.php
new file mode 100644
index 00000000000..485dd9f044e
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/OptionSimpleSelectTypeTest.php
@@ -0,0 +1,70 @@
+target = new OptionSimpleSelectType('text', 'email', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'email',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ 'empty_value' => false,
+ 'class' => 'OroFlexibleEntityBundle:AttributeOption',
+ 'expanded' => false,
+ 'multiple' => false,
+ 'query_builder' => function () {
+ }
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('text', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('email', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/PhoneCollectionTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/PhoneCollectionTypeTest.php
index e722555c2d8..bbb4fdc3a0a 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/PhoneCollectionTypeTest.php
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/PhoneCollectionTypeTest.php
@@ -3,37 +3,62 @@
use Oro\Bundle\FlexibleEntityBundle\AttributeType\PhoneCollectionType;
-class PhoneCollectionTypeTest extends \PHPUnit_Framework_TestCase
+class PhoneCollectionTypeTest extends AttributeTypeTest
{
- /**
- * Data provider
- *
- * @return array
- *
- * @static
- */
- public static function typesProvider()
+ protected $name = 'oro_flexibleentity_phone_collection';
+
+ public function setUp()
{
- return array(
- array('Oro\Bundle\FlexibleEntityBundle\AttributeType\PhoneCollectionType', 'integer', 'option', 'oro_flexibleentity_phone_collection'),
+ parent::setUp();
+
+ $this->target = new PhoneCollectionType('collections', 'text', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $phone = $this->getFlexibleValueMock(array());
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => $phone,
+ 'backendType' => 'foo',
+ )
);
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'text',
+ $phone,
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
}
- /**
- * Test related methods
- *
- * @param string $class
- * @param string $backend
- * @param string $form
- * @param string $name
- *
- * @dataProvider typesProvider
- */
- public function testConstructorAnGetters($class, $backend, $form, $name)
+ public function testGetBackendType()
{
- $attType = new $class($backend, $form);
- $this->assertEquals($attType->getName(), $name);
- $this->assertEquals($attType->getBackendType(), $backend);
- $this->assertEquals($attType->getFormType(), $form);
+ $this->assertEquals('collections', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('text', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
}
}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/PriceTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/PriceTypeTest.php
new file mode 100644
index 00000000000..93559486b49
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/PriceTypeTest.php
@@ -0,0 +1,64 @@
+target = new TextAreaType('longtext', 'text', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'text',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('longtext', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('text', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/TextTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/TextTypeTest.php
new file mode 100644
index 00000000000..2c1da5b6bc4
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/TextTypeTest.php
@@ -0,0 +1,64 @@
+target = new TextType('longtext', 'text', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'text',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('longtext', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('text', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/UrlTypeTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/UrlTypeTest.php
new file mode 100644
index 00000000000..5a462ea240b
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/AttributeType/UrlTypeTest.php
@@ -0,0 +1,64 @@
+target = new UrlType('longtext', 'text', $this->guesser);
+ }
+
+ public function testBuildValueFormType()
+ {
+ $factory = $this->getFormFactoryMock();
+ $value = $this->getFlexibleValueMock(
+ array(
+ 'data' => 'bar',
+ 'backendType' => 'foo',
+ )
+ );
+
+ $factory->expects($this->once())
+ ->method('createNamed')
+ ->with(
+ 'foo',
+ 'text',
+ 'bar',
+ array(
+ 'constraints' => array('constraints'),
+ 'label' => null,
+ 'required' => null,
+ )
+ );
+
+ $this->target->buildValueFormType($factory, $value);
+ }
+
+ public function testGetBackendType()
+ {
+ $this->assertEquals('longtext', $this->target->getBackendType());
+ }
+
+ public function testGetFormType()
+ {
+ $this->assertEquals('text', $this->target->getFormType());
+ }
+
+ public function testBuildAttributeFormTypes()
+ {
+ $this->assertEquals(
+ array(),
+ $this->target->buildAttributeFormTypes(
+ $this->getFormFactoryMock(),
+ $this->getAttributeMock(null, null)
+ )
+ );
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/Form/Validator/AttributeConstraintGuesserTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/Form/Validator/AttributeConstraintGuesserTest.php
new file mode 100644
index 00000000000..40e06b3ffcc
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/Form/Validator/AttributeConstraintGuesserTest.php
@@ -0,0 +1,92 @@
+
+ * @copyright 2013 Akeneo SAS (http://www.akeneo.com)
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
+ */
+class ChainedConstraintGuesserTest extends \PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ $this->target = new AttributeConstraintGuesser;
+ }
+
+ public function testInstanceOfContraintGuesserInterface()
+ {
+ $this->assertInstanceOf(
+ 'Oro\Bundle\FlexibleEntityBundle\Form\Validator\ConstraintGuesserInterface',
+ $this->target
+ );
+ }
+
+ public function testGuessNotBlankConstraints()
+ {
+ $this->assertContainsInstanceOf(
+ 'Symfony\Component\Validator\Constraints\NotBlank',
+ $this->target->guessConstraints(
+ $this->getAttributeMock(array('required' => true))
+ )
+ );
+ }
+
+ public function testGuessDateConstraints()
+ {
+ $this->assertContainsInstanceOf(
+ 'Symfony\Component\Validator\Constraints\Date',
+ $this->target->guessConstraints(
+ $this->getAttributeMock(array('backendType' => AbstractAttributeType::BACKEND_TYPE_DATE))
+ )
+ );
+ }
+
+ public function testGuessDateTimeConstraints()
+ {
+ $this->assertContainsInstanceOf(
+ 'Symfony\Component\Validator\Constraints\DateTime',
+ $this->target->guessConstraints(
+ $this->getAttributeMock(array('backendType' => AbstractAttributeType::BACKEND_TYPE_DATETIME))
+ )
+ );
+ }
+
+ private function getAttributeMock(array $options)
+ {
+ $options = array_merge(
+ array(
+ 'required' => false,
+ 'backendType' => null,
+ ),
+ $options
+ );
+
+ $attribute = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Model\AbstractAttribute');
+
+ $attribute->expects($this->any())
+ ->method('getBackendType')
+ ->will($this->returnValue($options['backendType']));
+
+ $attribute->expects($this->any())
+ ->method('getRequired')
+ ->will($this->returnValue($options['required']));
+
+ return $attribute;
+ }
+
+ private function assertContainsInstanceOf($class, $constraints)
+ {
+ foreach ($constraints as $constraint) {
+ if ($constraint instanceof $class) {
+ return true;
+ }
+ }
+
+ throw new \Exception(sprintf('Expecting constraints to contain instance of "%s"', $class));
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/Twig/FilterAttributesExtensionTest.php b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/Twig/FilterAttributesExtensionTest.php
new file mode 100644
index 00000000000..09995427a19
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Tests/Unit/Twig/FilterAttributesExtensionTest.php
@@ -0,0 +1,176 @@
+extension = new FilterAttributesExtension();
+ $this->entityMock = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Entity\Mapping\AbstractEntityFlexible');
+ $this->valuesMock = $this->getMock('Doctrine\Common\Collections\ArrayCollection');
+ }
+
+ public function testGetName()
+ {
+ $this->assertEquals('oro_flexibleentity_getAttributes', $this->extension->getName());
+ }
+
+ public function testGetFilters()
+ {
+ $filters = $this->extension->getFilters();
+
+ $this->assertArrayHasKey('getAttributes', $filters);
+ $this->assertInstanceOf('\Twig_Filter_Method', $filters['getAttributes']);
+ }
+
+ public function testGetAttributesEmptyValuesScenario()
+ {
+ $this->entityMock->expects($this->exactly(2))
+ ->method('getValues')
+ ->will($this->returnValue($this->valuesMock));
+
+ $this->valuesMock->expects($this->exactly(2))
+ ->method('isEmpty')
+ ->will($this->returnValue(true));
+
+ $result = $this->extension->getAttributes($this->entityMock, 'test attribute');
+ $this->assertEquals($this->valuesMock, $result);
+
+ $result = $this->extension->getAttributes($this->entityMock, array('test'), true);
+ $this->assertInstanceOf('Doctrine\Common\Collections\ArrayCollection', $result);
+ }
+
+ public function testGetAttributesValuesScenario()
+ {
+ $this->entityMock->expects($this->once())
+ ->method('getValues')
+ ->will($this->returnValue($this->valuesMock));
+
+ $this->valuesMock->expects($this->once())
+ ->method('filter')
+ ->will($this->returnValue($this->valuesMock));
+
+ $this->valuesMock->expects($this->once())
+ ->method('isEmpty')
+ ->will($this->returnValue(false));
+
+ $result = $this->extension->getAttributes($this->entityMock, 'test attribute', true);
+ $this->assertInstanceOf('Doctrine\Common\Collections\ArrayCollection', $result);
+ $this->assertEquals($this->valuesMock, $result);
+ }
+
+ public function testGetAttributesEmptyAttributesScenario()
+ {
+ $this->entityMock->expects($this->exactly(2))
+ ->method('getValues')
+ ->will($this->returnValue($this->valuesMock));
+
+ $this->valuesMock->expects($this->exactly(2))
+ ->method('isEmpty')
+ ->will($this->returnValue(true));
+
+ $result = $this->extension->getAttributes($this->entityMock);
+ $this->assertInstanceOf('\PHPUnit_Framework_MockObject_MockObject', $result);
+
+ $result = $this->extension->getAttributes($this->entityMock, array(), true);
+ $this->assertInstanceOf('Doctrine\Common\Collections\ArrayCollection', $result);
+ }
+
+ public function testFilterScenario()
+ {
+ $valueMock1 = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Model\FlexibleValueInterface');
+ $attributeMock1 = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Model\AbstractAttribute');
+ $valueMock2 = clone $valueMock1;
+ $attributeMock2 = clone $attributeMock1;
+
+ $valueMock1->expects($this->once())
+ ->method('getAttribute')
+ ->will($this->returnValue($attributeMock1));
+
+ $valueMock2->expects($this->once())
+ ->method('getAttribute')
+ ->will($this->returnValue($attributeMock2));
+
+ $attributeMock1->expects($this->once())
+ ->method('getCode')
+ ->will($this->returnValue('codeNeeded'));
+
+ $attributeMock2->expects($this->once())
+ ->method('getCode')
+ ->will($this->returnValue('codeNotNeeded'));
+
+ $collection = new ArrayCollection(
+ array(
+ $valueMock1, $valueMock2
+ )
+ );
+
+ $this->entityMock->expects($this->once())
+ ->method('getValues')
+ ->will($this->returnValue($collection));
+
+ $result = $this->extension->getAttributes($this->entityMock, array('codeNeeded'));
+ $this->assertCount(1, $result);
+ $this->assertEquals($valueMock1, $result->first());
+ }
+
+ public function testFilterSkipScenario()
+ {
+ $valueMock1 = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Model\FlexibleValueInterface');
+ $attributeMock1 = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Model\AbstractAttribute');
+ $valueMock2 = clone $valueMock1;
+ $attributeMock2 = clone $attributeMock1;
+
+ $valueMock1->expects($this->once())
+ ->method('getAttribute')
+ ->will($this->returnValue($attributeMock1));
+
+ $valueMock2->expects($this->once())
+ ->method('getAttribute')
+ ->will($this->returnValue($attributeMock2));
+
+ $attributeMock1->expects($this->once())
+ ->method('getCode')
+ ->will($this->returnValue('codeNeeded'));
+
+ $attributeMock2->expects($this->once())
+ ->method('getCode')
+ ->will($this->returnValue('codeNotNeeded'));
+
+ $collection = new ArrayCollection(
+ array(
+ $valueMock1, $valueMock2
+ )
+ );
+
+ $this->entityMock->expects($this->once())
+ ->method('getValues')
+ ->will($this->returnValue($collection));
+
+ $result = $this->extension->getAttributes($this->entityMock, array('codeNotNeeded'), true);
+ $this->assertCount(1, $result);
+ $this->assertEquals($valueMock1, $result->first());
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/Twig/FilterAttributesExtension.php b/src/Oro/Bundle/FlexibleEntityBundle/Twig/FilterAttributesExtension.php
new file mode 100644
index 00000000000..7975c44f486
--- /dev/null
+++ b/src/Oro/Bundle/FlexibleEntityBundle/Twig/FilterAttributesExtension.php
@@ -0,0 +1,68 @@
+ new \Twig_Filter_Method($this, 'getAttributes')
+ );
+ }
+
+ /**
+ * Returns attribute values array and filter if attributes array filled
+ * |getAttributes() - will return all attributes
+ * |getAttributes('address') - will return attribute with code "address"
+ * |getAttributes(['firstName', 'lastName']) - will filter by few attribute codes
+ *
+ * If third parameter equals true method will return attributes that not in given array(or string)
+ *
+ * @param AbstractEntityFlexible $entity
+ * @param string|array $attributes attribute names
+ * @param bool $skip
+ * @return ArrayCollection
+ */
+ public function getAttributes(AbstractEntityFlexible $entity, $attributes = array(), $skip = false)
+ {
+ if (!empty($attributes) && !is_array($attributes)) {
+ $attributes = array($attributes);
+ }
+
+ /** @var ArrayCollection $values */
+ $values = $entity->getValues();
+
+ if ($values->isEmpty() || empty($attributes)) {
+ $values = $skip ? new ArrayCollection() : $values;
+ return $values;
+ }
+
+ $values = $values->filter(
+ function ($value) use ($attributes, $skip) {
+ if (in_array($value->getAttribute()->getCode(), $attributes)) {
+ return !$skip;
+ }
+
+ return $skip;
+ }
+ );
+
+ return $values;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'oro_flexibleentity_getAttributes';
+ }
+}
diff --git a/src/Oro/Bundle/FlexibleEntityBundle/composer.lock b/src/Oro/Bundle/FlexibleEntityBundle/composer.lock
index 6048a3b5538..16d2e72af9a 100644
--- a/src/Oro/Bundle/FlexibleEntityBundle/composer.lock
+++ b/src/Oro/Bundle/FlexibleEntityBundle/composer.lock
@@ -1,32 +1,248 @@
{
- "hash": "9929fae7cd616b247e68db5443bbe0be",
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
+ ],
+ "hash": "ad390ff8c7df168e5cf338dd719569ae",
"packages": [
+ {
+ "name": "doctrine/annotations",
+ "version": "v1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/annotations.git",
+ "reference": "v1.1.1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/annotations/zipball/v1.1.1",
+ "reference": "v1.1.1",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/lexer": "1.*",
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "doctrine/cache": "1.*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\Common\\Annotations\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com",
+ "homepage": "http://www.jwage.com/"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com",
+ "homepage": "http://www.instaclick.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com",
+ "homepage": "https://github.com/schmittjoh",
+ "role": "Developer of wrapped JMSSerializerBundle"
+ }
+ ],
+ "description": "Docblock Annotations Parser",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "annotations",
+ "docblock",
+ "parser"
+ ],
+ "time": "2013-04-20 08:30:17"
+ },
+ {
+ "name": "doctrine/cache",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/cache.git",
+ "reference": "89493d2c6e1362f581f9de1c1871cc52eb29c030"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/cache/zipball/89493d2c6e1362f581f9de1c1871cc52eb29c030",
+ "reference": "89493d2c6e1362f581f9de1c1871cc52eb29c030",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "conflict": {
+ "doctrine/common": ">2.2,<2.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\Common\\Cache\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com",
+ "homepage": "http://www.jwage.com/"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com",
+ "homepage": "http://www.instaclick.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com",
+ "homepage": "http://jmsyst.com",
+ "role": "Developer of wrapped JMSSerializerBundle"
+ }
+ ],
+ "description": "Caching library offering an object-oriented API for many cache backends",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "cache",
+ "caching"
+ ],
+ "time": "2013-06-07 14:54:47"
+ },
+ {
+ "name": "doctrine/collections",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/collections.git",
+ "reference": "3db3ab843ff76774bee4679d4cb3a10cffb0a935"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/collections/zipball/3db3ab843ff76774bee4679d4cb3a10cffb0a935",
+ "reference": "3db3ab843ff76774bee4679d4cb3a10cffb0a935",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\Common\\Collections\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com",
+ "homepage": "http://www.jwage.com/"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com",
+ "homepage": "http://www.instaclick.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com",
+ "homepage": "https://github.com/schmittjoh",
+ "role": "Developer of wrapped JMSSerializerBundle"
+ }
+ ],
+ "description": "Collections Abstraction library",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "array",
+ "collections",
+ "iterator"
+ ],
+ "time": "2013-05-26 05:21:22"
+ },
{
"name": "doctrine/common",
- "version": "2.3.x-dev",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/doctrine/common.git",
- "reference": "bb0aebbf234db52df476a2b473d434745b34221c"
+ "reference": "c4255b9fbd63ee1fe52697839318af5937fced9b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/common/zipball/bb0aebbf234db52df476a2b473d434745b34221c",
- "reference": "bb0aebbf234db52df476a2b473d434745b34221c",
+ "url": "https://api.github.com/repos/doctrine/common/zipball/c4255b9fbd63ee1fe52697839318af5937fced9b",
+ "reference": "c4255b9fbd63ee1fe52697839318af5937fced9b",
"shasum": ""
},
"require": {
+ "doctrine/annotations": "1.*",
+ "doctrine/cache": "1.*",
+ "doctrine/collections": "1.*",
+ "doctrine/inflector": "1.*",
+ "doctrine/lexer": "1.*",
"php": ">=5.3.2"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3.x-dev"
+ "dev-master": "2.4.x-dev"
}
},
"autoload": {
"psr-0": {
- "Doctrine\\Common": "lib/"
+ "Doctrine\\Common\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -55,7 +271,7 @@
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com",
- "homepage": "http://jmsyst.com",
+ "homepage": "https://github.com/schmittjoh",
"role": "Developer of wrapped JMSSerializerBundle"
}
],
@@ -68,24 +284,291 @@
"persistence",
"spl"
],
- "time": "2012-09-20 05:55:18"
+ "time": "2013-06-21 12:11:28"
+ },
+ {
+ "name": "doctrine/inflector",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/inflector.git",
+ "reference": "8b4b3ccec7aafc596e2fc1e593c9f2e78f939c8c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/inflector/zipball/8b4b3ccec7aafc596e2fc1e593c9f2e78f939c8c",
+ "reference": "8b4b3ccec7aafc596e2fc1e593c9f2e78f939c8c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\Common\\Inflector\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com",
+ "homepage": "http://www.jwage.com/"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com",
+ "homepage": "http://www.instaclick.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com",
+ "homepage": "https://github.com/schmittjoh",
+ "role": "Developer of wrapped JMSSerializerBundle"
+ }
+ ],
+ "description": "Common String Manipulations with regard to casing and singular/plural rules.",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "inflection",
+ "pluralize",
+ "singularize",
+ "string"
+ ],
+ "time": "2013-04-10 16:14:30"
+ },
+ {
+ "name": "doctrine/lexer",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/lexer.git",
+ "reference": "bc0e1f0cc285127a38c6c8ea88bc5dba2fd53e94"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/lexer/zipball/bc0e1f0cc285127a38c6c8ea88bc5dba2fd53e94",
+ "reference": "bc0e1f0cc285127a38c6c8ea88bc5dba2fd53e94",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\Common\\Lexer\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com",
+ "homepage": "http://www.instaclick.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com",
+ "homepage": "https://github.com/schmittjoh",
+ "role": "Developer of wrapped JMSSerializerBundle"
+ }
+ ],
+ "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "lexer",
+ "parser"
+ ],
+ "time": "2013-03-07 12:15:25"
+ },
+ {
+ "name": "gedmo/doctrine-extensions",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/l3pp4rd/DoctrineExtensions.git",
+ "reference": "10f5f83a3e20fb94566e9a103b45a40a817e6134"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/l3pp4rd/DoctrineExtensions/zipball/10f5f83a3e20fb94566e9a103b45a40a817e6134",
+ "reference": "10f5f83a3e20fb94566e9a103b45a40a817e6134",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/common": ">=2.2,<2.5-dev",
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "doctrine/common": ">=2.4.0-RC3",
+ "doctrine/dbal": ">=2.4.0-RC1",
+ "doctrine/mongodb": ">=1.0.3",
+ "doctrine/mongodb-odm": ">=1.0.0-BETA9",
+ "doctrine/orm": ">=2.4.0-RC1",
+ "symfony/yaml": "2.3.1"
+ },
+ "suggest": {
+ "doctrine/dbal": ">=2.3.2",
+ "doctrine/mongodb": ">=1.0.1",
+ "doctrine/mongodb-odm": ">=1.0.0-BETA7",
+ "doctrine/orm": ">=2.3.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Gedmo\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "David Buchmann",
+ "email": "david@liip.ch"
+ },
+ {
+ "name": "Gediminas Morkevicius",
+ "email": "gediminas.morkevicius@gmail.com"
+ },
+ {
+ "name": "Gustavo Falco",
+ "email": "comfortablynumb84@gmail.com"
+ }
+ ],
+ "description": "Doctrine2 behavioral extensions",
+ "homepage": "http://gediminasm.org/",
+ "keywords": [
+ "Blameable",
+ "behaviors",
+ "doctrine2",
+ "extensions",
+ "gedmo",
+ "loggable",
+ "nestedset",
+ "sluggable",
+ "sortable",
+ "timestampable",
+ "translatable",
+ "tree",
+ "uploadable"
+ ],
+ "time": "2013-06-24 12:42:19"
+ },
+ {
+ "name": "stof/doctrine-extensions-bundle",
+ "version": "dev-master",
+ "target-dir": "Stof/DoctrineExtensionsBundle",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/stof/StofDoctrineExtensionsBundle.git",
+ "reference": "6577f2388abeac4896aa0aef37fc1b6f2c6923e9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/stof/StofDoctrineExtensionsBundle/zipball/6577f2388abeac4896aa0aef37fc1b6f2c6923e9",
+ "reference": "6577f2388abeac4896aa0aef37fc1b6f2c6923e9",
+ "shasum": ""
+ },
+ "require": {
+ "gedmo/doctrine-extensions": "2.3.*",
+ "php": ">=5.3.2",
+ "symfony/framework-bundle": ">=2.1,<3.0"
+ },
+ "suggest": {
+ "doctrine/doctrine-bundle": "to use the ORM extensions",
+ "doctrine/mongodb-odm-bundle": "to use the MongoDB ODM extensions"
+ },
+ "type": "symfony-bundle",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Stof\\DoctrineExtensionsBundle": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Christophe Coevoet",
+ "email": "stof@notk.org"
+ }
+ ],
+ "description": "Integration of the gedmo/doctrine-extensions with Symfony2",
+ "homepage": "https://github.com/stof/StofDoctrineExtensionsBundle",
+ "keywords": [
+ "behaviors",
+ "doctrine2",
+ "extensions",
+ "gedmo",
+ "loggable",
+ "nestedset",
+ "sluggable",
+ "sortable",
+ "timestampable",
+ "translatable",
+ "tree"
+ ],
+ "time": "2013-06-25 08:05:01"
},
{
"name": "symfony/symfony",
- "version": "v2.1.7",
+ "version": "2.1.x-dev",
"source": {
"type": "git",
- "url": "git://github.com/symfony/symfony.git",
- "reference": "v2.1.7"
+ "url": "https://github.com/symfony/symfony.git",
+ "reference": "0c0a3e90e79b63215707ae7e92193f511cc0ec77"
},
"dist": {
"type": "zip",
- "url": "https://github.com/symfony/symfony/archive/v2.1.7.zip",
- "reference": "v2.1.7",
+ "url": "https://api.github.com/repos/symfony/symfony/zipball/0c0a3e90e79b63215707ae7e92193f511cc0ec77",
+ "reference": "0c0a3e90e79b63215707ae7e92193f511cc0ec77",
"shasum": ""
},
"require": {
- "doctrine/common": ">2.2,<2.4-dev",
+ "doctrine/common": ">=2.2,<3.0",
"php": ">=5.3.3",
"twig/twig": ">=1.9.1,<2.0-dev"
},
@@ -156,7 +639,7 @@
"keywords": [
"framework"
],
- "time": "2013-01-17 21:21:51"
+ "time": "2013-06-11 07:34:22"
},
{
"name": "twig/twig",
@@ -164,12 +647,12 @@
"source": {
"type": "git",
"url": "https://github.com/fabpot/Twig.git",
- "reference": "399916916533589c95dc04e1afd4aeefa34928ad"
+ "reference": "6f753205834b511269a97fe35108bbd5c8d245f5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/fabpot/Twig/zipball/399916916533589c95dc04e1afd4aeefa34928ad",
- "reference": "399916916533589c95dc04e1afd4aeefa34928ad",
+ "url": "https://api.github.com/repos/fabpot/Twig/zipball/6f753205834b511269a97fe35108bbd5c8d245f5",
+ "reference": "6f753205834b511269a97fe35108bbd5c8d245f5",
"shasum": ""
},
"require": {
@@ -178,7 +661,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.12-dev"
+ "dev-master": "1.13-dev"
}
},
"autoload": {
@@ -205,7 +688,7 @@
"keywords": [
"templating"
],
- "time": "2013-04-01 08:27:18"
+ "time": "2013-06-09 06:03:21"
}
],
"packages-dev": [
@@ -215,12 +698,12 @@
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
- "reference": "dd69835e0dcc44f7f0726b105e83ae5013622f5c"
+ "reference": "6a62fefefde6b2c0d8b3df70151d6a81fc028d28"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/dbal/zipball/dd69835e0dcc44f7f0726b105e83ae5013622f5c",
- "reference": "dd69835e0dcc44f7f0726b105e83ae5013622f5c",
+ "url": "https://api.github.com/repos/doctrine/dbal/zipball/6a62fefefde6b2c0d8b3df70151d6a81fc028d28",
+ "reference": "6a62fefefde6b2c0d8b3df70151d6a81fc028d28",
"shasum": ""
},
"require": {
@@ -270,7 +753,7 @@
"persistence",
"queryobject"
],
- "time": "2013-03-24 19:16:29"
+ "time": "2013-05-21 05:53:02"
},
{
"name": "doctrine/orm",
@@ -278,12 +761,12 @@
"source": {
"type": "git",
"url": "https://github.com/doctrine/doctrine2.git",
- "reference": "868bb68cc8f96485a5407d2b16f88037a69e96b8"
+ "reference": "9787b27518bf4e4da1523ced6bfca74e98397907"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/868bb68cc8f96485a5407d2b16f88037a69e96b8",
- "reference": "868bb68cc8f96485a5407d2b16f88037a69e96b8",
+ "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/9787b27518bf4e4da1523ced6bfca74e98397907",
+ "reference": "9787b27518bf4e4da1523ced6bfca74e98397907",
"shasum": ""
},
"require": {
@@ -340,16 +823,16 @@
"database",
"orm"
],
- "time": "2013-03-24 20:43:58"
+ "time": "2013-05-26 07:27:03"
}
],
"aliases": [
],
"minimum-stability": "dev",
- "stability-flags": [
-
- ],
+ "stability-flags": {
+ "stof/doctrine-extensions-bundle": 20
+ },
"platform": {
"php": ">=5.3.3"
},
diff --git a/src/Oro/Bundle/FormBundle/.gitignore b/src/Oro/Bundle/FormBundle/.gitignore
new file mode 100644
index 00000000000..dad62749d16
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/.gitignore
@@ -0,0 +1,4 @@
+/.settings
+/.buildpath
+/.project
+/.idea
diff --git a/src/Oro/Bundle/FormBundle/Autocomplete/ConverterInterface.php b/src/Oro/Bundle/FormBundle/Autocomplete/ConverterInterface.php
new file mode 100644
index 00000000000..e454e0dcc8a
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Autocomplete/ConverterInterface.php
@@ -0,0 +1,14 @@
+entityName = $entityName;
+ $this->properties = $properties;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getProperties()
+ {
+ return $this->properties;
+ }
+
+ /**
+ * @param Indexer $indexer
+ * @param array $config
+ * @throws \RuntimeException
+ */
+ public function initSearchIndexer(Indexer $indexer, array $config)
+ {
+ $this->indexer = $indexer;
+ if (empty($config[$this->entityName]['alias'])) {
+ throw new \RuntimeException("Cannot init entity search alias.");
+ }
+ $this->entitySearchAlias = $config[$this->entityName]['alias'];
+ }
+
+ /**
+ * @param ManagerRegistry $managerRegistry
+ * @throws \RuntimeException
+ */
+ public function initDoctrinePropertiesByManagerRegistry(ManagerRegistry $managerRegistry)
+ {
+ $objectManager = $managerRegistry->getManagerForClass($this->entityName);
+ if (!$objectManager instanceof EntityManager) {
+ throw new \RuntimeException(
+ 'Object manager for "%s" expected to be an instance of "%s".',
+ $this->entityName,
+ 'Doctrine\ORM\EntityManager'
+ );
+ }
+ $this->initDoctrinePropertiesByEntityManager($objectManager);
+ }
+
+ /**
+ * @param EntityManager $entityManager
+ */
+ public function initDoctrinePropertiesByEntityManager(EntityManager $entityManager)
+ {
+ $this->entityRepository = $entityManager->getRepository($this->entityName);
+ $this->idFieldName = $this->getEntityIdentifierFieldName($entityManager);
+ }
+
+ /**
+ * @param EntityManager $entityManager
+ * @return string
+ */
+ protected function getEntityIdentifierFieldName(EntityManager $entityManager)
+ {
+ /** @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
+ $metadata = $entityManager->getMetadataFactory()->getMetadataFor($this->entityName);
+ return $metadata->getSingleIdentifierFieldName();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function search($query, $page, $perPage)
+ {
+ $this->checkAllDependenciesInjected();
+
+ $page = (int)$page > 0 ? (int)$page : 1;
+ $perPage = (int)$perPage > 0 ? (int)$perPage : 10;
+ $perPage += 1;
+
+ $items = $this->searchEntities($query, ($page - 1) * $perPage, $perPage);
+
+ $this->hasMore = count($items) == $perPage;
+ if ($this->hasMore) {
+ $items = array_slice($items, 0, $perPage - 1);
+ }
+
+ return $this->formatResult($items);
+ }
+
+ /**
+ * @throws \RuntimeException
+ */
+ private function checkAllDependenciesInjected()
+ {
+ if (!$this->indexer || !$this->entitySearchAlias || !$this->entityRepository || !$this->idFieldName) {
+ throw new \RuntimeException('Search handler is not fully configured');
+ }
+ }
+
+ /**
+ * @param array $items
+ * @return array
+ */
+ protected function formatResult(array $items)
+ {
+ return array(
+ 'results' => $this->convertItems($items),
+ 'more' => $this->hasMore
+ );
+ }
+
+ /**
+ * Search and return entities
+ *
+ * @param string $search
+ * @param int $firstResult
+ * @param int $maxResults
+ * @return array
+ */
+ protected function searchEntities($search, $firstResult, $maxResults)
+ {
+ $entityIds = $this->searchIds($search, $firstResult, $maxResults);
+
+ $resultEntities = array();
+
+ if ($entityIds) {
+ /** @var QueryBuilder $queryBuilder */
+ $queryBuilder = $this->entityRepository->createQueryBuilder('e');
+ $queryBuilder->where($queryBuilder->expr()->in('e.' . $this->idFieldName, $entityIds));
+ $currentEntities = $queryBuilder->getQuery()->getResult();
+
+ foreach ($currentEntities as $entity) {
+ $resultEntities[] = $entity;
+ }
+ }
+
+ return $resultEntities;
+ }
+
+ /**
+ * @param string $search
+ * @param int $firstResult
+ * @param int $maxResults
+ * @return array
+ */
+ protected function searchIds($search, $firstResult, $maxResults)
+ {
+ $result = $this->indexer->simpleSearch($search, $firstResult, $maxResults, $this->entitySearchAlias);
+ $elements = $result->getElements();
+
+ $ids = array();
+ foreach ($elements as $element) {
+ $ids[] = $element->getRecordId();
+ }
+
+ return $ids;
+ }
+
+ /**
+ * @param array $items
+ * @return array
+ */
+ protected function convertItems(array $items)
+ {
+ $result = array();
+ foreach ($items as $item) {
+ $result[] = $this->convertItem($item);
+ }
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function convertItem($item)
+ {
+ $result = array();
+
+ $result[$this->idFieldName] = $this->getPropertyValue($this->idFieldName, $item);
+
+ foreach ($this->properties as $property) {
+ $result[$property] = $this->getPropertyValue($property, $item);
+ }
+
+ return $result;
+ }
+
+ /**
+ * @param string $name
+ * @param object|array $item
+ * @return mixed
+ */
+ protected function getPropertyValue($name, $item)
+ {
+ $result = null;
+
+ if (is_object($item)) {
+ $method = 'get' . str_replace(' ', '', str_replace('_', ' ', ucwords($name)));
+ if (method_exists($item, $method)) {
+ $result = $item->$method();
+ } elseif (isset($item->$name)) {
+ $result = $item->$name;
+ }
+ } elseif (is_array($item) && array_key_exists($name, $item)) {
+ $result = $item[$name];
+ }
+
+ if ($result instanceof FlexibleValueInterface) {
+ $result = $result->getData();
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getEntityName()
+ {
+ return $this->entityName;
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/Autocomplete/SearchHandlerInterface.php b/src/Oro/Bundle/FormBundle/Autocomplete/SearchHandlerInterface.php
new file mode 100644
index 00000000000..71e882ae2af
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Autocomplete/SearchHandlerInterface.php
@@ -0,0 +1,30 @@
+searchHandlers[$name] = $searchHandler;
+ }
+
+ /**
+ * @param string $name
+ * @return SearchHandlerInterface
+ * @throws \RuntimeException
+ */
+ public function getSearchHandler($name)
+ {
+ if (!isset($this->searchHandlers[$name])) {
+ throw new \RuntimeException(sprintf('Search handler "%s" is not registered', $name));
+ }
+
+ return $this->searchHandlers[$name];
+ }
+
+ /**
+ * @param string $name
+ * @return boolean
+ */
+ public function hasSearchHandler($name)
+ {
+ return isset($this->searchHandlers[$name]);
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/Autocomplete/Security.php b/src/Oro/Bundle/FormBundle/Autocomplete/Security.php
new file mode 100644
index 00000000000..69c3019353a
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Autocomplete/Security.php
@@ -0,0 +1,52 @@
+manager = $manager;
+ $this->autocompleteAclResources = array();
+ }
+
+ /**
+ * @param string $name
+ * @param string $aclResource
+ */
+ public function setAutocompleteAclResource($name, $aclResource)
+ {
+ $this->autocompleteAclResources[$name] = $aclResource;
+ }
+
+ /**
+ * @param string $name
+ * @return string|null
+ */
+ public function getAutocompleteAclResource($name)
+ {
+ return isset($this->autocompleteAclResources[$name]) ? $this->autocompleteAclResources[$name] : null;
+ }
+
+ /**
+ * @param $name
+ * @return boolean
+ */
+ public function isAutocompleteGranted($name)
+ {
+ $aclResource = $this->getAutocompleteAclResource($name);
+ return $aclResource && $this->manager->isResourceGranted($aclResource);
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/Controller/AutocompleteController.php b/src/Oro/Bundle/FormBundle/Controller/AutocompleteController.php
new file mode 100644
index 00000000000..43a91c161ea
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Controller/AutocompleteController.php
@@ -0,0 +1,68 @@
+get('name');
+ $query = $request->get('query');
+ $page = intval($request->get('page', 1));
+ $perPage = intval($request->get('per_page', 50));
+
+ if (!$name) {
+ throw new HttpException(400, 'Parameter "name" is required');
+ }
+
+ if ($page <= 0) {
+ throw new HttpException(400, 'Parameter "page" must be greater than 0');
+ }
+
+ if ($perPage <= 0) {
+ throw new HttpException(400, 'Parameter "per_page" must be greater than 0');
+ }
+
+ if (!$this->get('oro_form.autocomplete.security')->isAutocompleteGranted($name)) {
+ throw new AccessDeniedHttpException('Access denied.');
+ }
+
+ /** @var SearchHandlerInterface $searchHandler */
+ $searchHandler = $this->get('oro_form.autocomplete.search_registry')->getSearchHandler($name);
+
+ return new JsonResponse($searchHandler->search($query, $page, $perPage));
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/DependencyInjection/Compiler/AutocompleteCompilerPass.php b/src/Oro/Bundle/FormBundle/DependencyInjection/Compiler/AutocompleteCompilerPass.php
new file mode 100644
index 00000000000..57e1e84934c
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/DependencyInjection/Compiler/AutocompleteCompilerPass.php
@@ -0,0 +1,33 @@
+getDefinition('oro_form.autocomplete.search_registry');
+ $securityDefinition = $container->getDefinition('oro_form.autocomplete.security');
+
+ foreach ($container->findTaggedServiceIds('oro_form.autocomplete.search_handler') as $id => $attributes) {
+ foreach ($attributes as $eachTag) {
+ $name = !empty($eachTag['alias']) ? $eachTag['alias'] : $id;
+ $searchRegistryDefinition->addMethodCall('addSearchHandler', array($name, new Reference($id)));
+ if (!empty($eachTag['acl_resource'])) {
+ $securityDefinition->addMethodCall(
+ 'setAutocompleteAclResource',
+ array($name, $eachTag['acl_resource'])
+ );
+ }
+ }
+ }
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/DependencyInjection/Configuration.php b/src/Oro/Bundle/FormBundle/DependencyInjection/Configuration.php
new file mode 100644
index 00000000000..50d983926f2
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/DependencyInjection/Configuration.php
@@ -0,0 +1,20 @@
+root('oro_form');
+
+ return $treeBuilder;
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/DependencyInjection/OroFormExtension.php b/src/Oro/Bundle/FormBundle/DependencyInjection/OroFormExtension.php
new file mode 100644
index 00000000000..b0c7e7c78a2
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/DependencyInjection/OroFormExtension.php
@@ -0,0 +1,26 @@
+processConfiguration($configuration, $configs);
+
+ $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
+ $loader->load('autocomplete.yml');
+ $loader->load('form_type.yml');
+ }
+}
diff --git a/src/Oro/Bundle/UIBundle/Form/DataTransformer/ArrayToStringTransformer.php b/src/Oro/Bundle/FormBundle/Form/DataTransformer/ArrayToStringTransformer.php
similarity index 97%
rename from src/Oro/Bundle/UIBundle/Form/DataTransformer/ArrayToStringTransformer.php
rename to src/Oro/Bundle/FormBundle/Form/DataTransformer/ArrayToStringTransformer.php
index 7b438bc29d0..c81589f966c 100644
--- a/src/Oro/Bundle/UIBundle/Form/DataTransformer/ArrayToStringTransformer.php
+++ b/src/Oro/Bundle/FormBundle/Form/DataTransformer/ArrayToStringTransformer.php
@@ -1,6 +1,6 @@
propertyPath->getValue($entity);
+ $result[] = $id;
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reverseTransform($value)
+ {
+ if (!is_array($value)) {
+ throw new UnexpectedTypeException($value, 'array');
+ }
+
+ if (!$value) {
+ return array();
+ }
+
+ $entities = $this->loadEntitiesByIds($value);
+
+ if (count($entities) !== count($value)) {
+ throw new TransformationFailedException('Could not find all entities for the given IDs');
+ }
+
+ return $entities;
+ }
+
+ /**
+ * Load entities by array of ids
+ *
+ * @param array $ids
+ * @return array
+ * @throws UnexpectedTypeException if query builder callback returns invalid type
+ */
+ protected function loadEntitiesByIds(array $ids)
+ {
+ $repository = $this->em->getRepository($this->className);
+ if ($this->queryBuilderCallback) {
+ /** @var $qb QueryBuilder */
+ $qb = call_user_func($this->queryBuilderCallback, $repository, $ids);
+ if (!$qb instanceof QueryBuilder) {
+ throw new UnexpectedTypeException($qb, 'Doctrine\ORM\QueryBuilder');
+ }
+ } else {
+ $qb = $repository->createQueryBuilder('e');
+ $qb->where(sprintf('e.%s IN (:ids)', $this->propertyPath))
+ ->setParameter('ids', $ids);
+ }
+
+ return $qb->getQuery()->execute();
+ }
+}
diff --git a/src/Oro/Bundle/UIBundle/Form/DataTransformer/EntitiesToIdsTransformer.php b/src/Oro/Bundle/FormBundle/Form/DataTransformer/EntityToIdTransformer.php
similarity index 65%
rename from src/Oro/Bundle/UIBundle/Form/DataTransformer/EntitiesToIdsTransformer.php
rename to src/Oro/Bundle/FormBundle/Form/DataTransformer/EntityToIdTransformer.php
index 2877ce7315d..4a70b213aa2 100644
--- a/src/Oro/Bundle/UIBundle/Form/DataTransformer/EntitiesToIdsTransformer.php
+++ b/src/Oro/Bundle/FormBundle/Form/DataTransformer/EntityToIdTransformer.php
@@ -1,21 +1,20 @@
getSingleIdentifierFieldName();
} catch (MappingException $e) {
throw new FormException(
- "Cannot get id property path of entity. \"$this->className\" has composite primary key."
+ "Cannot get id property path of entity. \"$className\" has composite primary key."
);
}
}
@@ -84,21 +88,15 @@ protected function getIdPropertyPathFromEntityManager(EntityManager $em, $classN
*/
public function transform($value)
{
- if (null === $value || array() === $value) {
- return array();
- }
-
- if (!is_array($value)) {
- throw new UnexpectedTypeException($value, 'array');
+ if (null === $value) {
+ return null;
}
- $result = array();
- foreach ($value as $entity) {
- $id = $this->propertyPath->getValue($entity);
- $result[] = $id;
+ if (!is_object($value)) {
+ throw new UnexpectedTypeException($value, 'object');
}
- return $result;
+ return $this->propertyPath->getValue($value);
}
/**
@@ -106,45 +104,32 @@ public function transform($value)
*/
public function reverseTransform($value)
{
- if (!is_array($value)) {
- throw new UnexpectedTypeException($value, 'array');
- }
-
if (!$value) {
- return array();
+ return null;
}
- $entities = $this->loadEntitiesByIds($value);
-
- if (count($entities) !== count($value)) {
- throw new TransformationFailedException('Could not find all entities for the given IDs');
- }
-
- return $entities;
+ return $this->loadEntityById($value);
}
/**
- * Load entities by array of ids
+ * Load entity by id
*
- * @param array $ids
- * @return array
+ * @param mixed $id
+ * @return object
* @throws UnexpectedTypeException if query builder callback returns invalid type
*/
- protected function loadEntitiesByIds(array $ids)
+ protected function loadEntityById($id)
{
$repository = $this->em->getRepository($this->className);
if ($this->queryBuilderCallback) {
/** @var $qb QueryBuilder */
- $qb = call_user_func($this->queryBuilderCallback, $repository, $ids);
+ $qb = call_user_func($this->queryBuilderCallback, $repository, $id);
if (!$qb instanceof QueryBuilder) {
throw new UnexpectedTypeException($qb, 'Doctrine\ORM\QueryBuilder');
}
+ return $qb->getQuery()->execute();
} else {
- $qb = $repository->createQueryBuilder('e');
- $qb->where(sprintf('e.%s IN (:ids)', $this->propertyPath))
- ->setParameter('ids', $ids);
+ return $repository->find($id);
}
-
- return $qb->getQuery()->execute();
}
}
diff --git a/src/Oro/Bundle/UIBundle/Form/EventListener/FixArrayToStringListener.php b/src/Oro/Bundle/FormBundle/Form/EventListener/FixArrayToStringListener.php
similarity index 93%
rename from src/Oro/Bundle/UIBundle/Form/EventListener/FixArrayToStringListener.php
rename to src/Oro/Bundle/FormBundle/Form/EventListener/FixArrayToStringListener.php
index cb364220120..3e27a9d3e28 100644
--- a/src/Oro/Bundle/UIBundle/Form/EventListener/FixArrayToStringListener.php
+++ b/src/Oro/Bundle/FormBundle/Form/EventListener/FixArrayToStringListener.php
@@ -1,6 +1,6 @@
entityManager = $entityManager;
+ $this->searchRegistry = $registry;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setDefaultOptions(OptionsResolverInterface $resolver)
+ {
+ $defaultConfig = array(
+ 'placeholder' => 'oro.form.choose_value',
+ 'allowClear' => true,
+ 'minimumInputLength' => 1,
+ );
+
+ $searchRegistry = $this->searchRegistry;
+ $formType = $this;
+
+ $resolver
+ ->setDefaults(
+ array(
+ 'empty_value' => '',
+ 'empty_data' => null,
+ 'data_class' => null,
+ 'entity_class' => null,
+ 'configs' => $defaultConfig,
+ 'converter' => null,
+ 'autocomplete_alias' => null
+ )
+ );
+
+ $this->setConverterNormalizer($resolver);
+ $this->setConfigsNormalizer($resolver, $defaultConfig);
+
+ $resolver
+ ->setNormalizers(
+ array(
+ 'entity_class' => function (Options $options, $value) use ($searchRegistry) {
+ if (!$value && !empty($options['autocomplete_alias'])) {
+ $searchHandler = $searchRegistry->getSearchHandler($options['autocomplete_alias']);
+ $value = $searchHandler->getEntityName();
+ }
+
+ if (!$value) {
+ throw new FormException('The option "entity_class" must be set.');
+ }
+ return $value;
+ },
+ 'transformer' => function (Options $options, $value) use ($formType) {
+ if (!$value) {
+ $value = $formType->createDefaultTransformer($options['entity_class']);
+ } elseif (!$value instanceof DataTransformerInterface) {
+ throw new FormException(
+ sprintf(
+ 'The option "transformer" must be an instance of "%s".',
+ 'Symfony\Component\Form\DataTransformerInterface'
+ )
+ );
+ }
+ return $value;
+ }
+ )
+ );
+ }
+
+ /**
+ * @param OptionsResolverInterface $resolver
+ */
+ protected function setConverterNormalizer(OptionsResolverInterface $resolver)
+ {
+ $searchRegistry = $this->searchRegistry;
+ $resolver->setNormalizers(
+ array(
+ 'converter' => function (Options $options, $value) use ($searchRegistry) {
+ if (!$value && !empty($options['autocomplete_alias'])) {
+ $value = $searchRegistry->getSearchHandler($options['autocomplete_alias']);
+ } elseif (!$value) {
+ throw new FormException('The option "converter" must be set.');
+ }
+
+ if (!$value instanceof ConverterInterface) {
+ throw new FormException(
+ sprintf(
+ 'The option "converter" must be an instance of "%s".',
+ 'Oro\Bundle\FormBundle\Autocomplete\ConverterInterface'
+ )
+ );
+ }
+ return $value;
+ }
+ )
+ );
+ }
+
+ /**
+ * @param OptionsResolverInterface $resolver
+ * @param array $defaultConfig
+ */
+ protected function setConfigsNormalizer(OptionsResolverInterface $resolver, array $defaultConfig)
+ {
+ $searchRegistry = $this->searchRegistry;
+ $resolver->setNormalizers(
+ array(
+ 'configs' => function (Options $options, $configs) use ($searchRegistry, $defaultConfig) {
+ $result = array_replace_recursive($defaultConfig, $configs);
+
+ if (!empty($options['autocomplete_alias'])) {
+ $result['autocomplete_alias'] = $options['autocomplete_alias'];
+ if (empty($result['properties'])) {
+ $searchHandler = $searchRegistry->getSearchHandler($options['autocomplete_alias']);
+ $result['properties'] = $searchHandler->getProperties();
+ }
+ if (empty($result['route_name'])) {
+ $result['route_name'] = 'oro_form_autocomplete_search';
+ }
+ if (empty($result['extra_config'])) {
+ $result['extra_config'] = 'autocomplete';
+ }
+ }
+
+ if (empty($result['route_name']) && empty($result['ajax']['url'])) {
+ throw new FormException(
+ 'Either option "configs.route_name" or "configs.ajax.url" must be set.'
+ );
+ }
+
+ return $result;
+ }
+ )
+ );
+ }
+
+ /**
+ * @param string $entityClass
+ * @return EntityToIdTransformer
+ */
+ public function createDefaultTransformer($entityClass)
+ {
+ return $value = new EntityToIdTransformer($this->entityManager, $entityClass);
+ }
+
+ /**
+ * Set data-title attribute to element to show selected value
+ *
+ * @param FormView $view
+ * @param FormInterface $form
+ * @param array $options
+ */
+ public function buildView(FormView $view, FormInterface $form, array $options)
+ {
+ parent::buildView($view, $form, $options);
+
+ $vars = array('configs' => $options['configs']);
+ if ($form->getData()) {
+ $vars['attr'] = array(
+ 'data-entity' => json_encode($options['converter']->convertItem($form->getData()))
+ );
+ }
+
+ $view->vars = array_replace_recursive($view->vars, $vars);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getParent()
+ {
+ return 'genemu_jqueryselect2_hidden';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'oro_jqueryselect2_hidden';
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/Form/Type/TranslatableEntityType.php b/src/Oro/Bundle/FormBundle/Form/Type/TranslatableEntityType.php
new file mode 100644
index 00000000000..b912c741c81
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Form/Type/TranslatableEntityType.php
@@ -0,0 +1,123 @@
+registry = $registry;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName()
+ {
+ return self::NAME;
+ }
+
+ /**
+ * @return string
+ */
+ public function getParent()
+ {
+ return 'choice';
+ }
+
+ /**
+ * @param FormBuilderInterface $builder
+ * @param array $options
+ */
+ public function buildForm(FormBuilderInterface $builder, array $options)
+ {
+ // transformer must be only one in chain
+ $builder->resetViewTransformers();
+
+ /** @var $entityManager EntityManager */
+ $entityManager = $this->registry->getManager();
+ if (!empty($options['multiple'])) {
+ $builder->addViewTransformer(new EntitiesToIdsTransformer($entityManager, $options['class']));
+ } else {
+ $builder->addViewTransformer(new EntityToIdTransformer($entityManager, $options['class']));
+ }
+ }
+
+ /**
+ * @param OptionsResolverInterface $resolver
+ */
+ public function setDefaultOptions(OptionsResolverInterface $resolver)
+ {
+ $registry = $this->registry;
+
+ $choiceList = function (Options $options) use ($registry) {
+ $className = $options['class'];
+
+ /** @var $entityManager EntityManager */
+ $entityManager = $registry->getManager();
+ $idField = $entityManager->getClassMetadata($className)->getSingleIdentifierFieldName();
+
+ if (null !== $options['choices']) {
+ return new ObjectChoiceList($options['choices'], $options['property'], array(), null, $idField);
+ }
+
+ // get query builder
+ if (!empty($options['query_builder'])) {
+ $queryBuilder = $options['query_builder'];
+ if ($queryBuilder instanceof \Closure) {
+ $queryBuilder = $queryBuilder($registry->getRepository($className));
+ }
+ } else {
+ /** @var $repository EntityRepository */
+ $repository = $registry->getRepository($className);
+ $queryBuilder = $repository->createQueryBuilder('e');
+ }
+
+ // make entity translatable
+ /** @var $queryBuilder QueryBuilder */
+ $query = $queryBuilder->getQuery();
+ $query->setHint(
+ Query::HINT_CUSTOM_OUTPUT_WALKER,
+ 'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
+ );
+
+ return new ObjectChoiceList($query->execute(), $options['property'], array(), null, $idField);
+ };
+
+ $resolver->setDefaults(
+ array(
+ 'property' => null,
+ 'query_builder' => null,
+ 'choices' => null,
+ 'choice_list' => $choiceList
+ )
+ );
+
+ $resolver->setRequired(array('class'));
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/OroFormBundle.php b/src/Oro/Bundle/FormBundle/OroFormBundle.php
new file mode 100644
index 00000000000..978ea324277
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/OroFormBundle.php
@@ -0,0 +1,19 @@
+addCompilerPass(new AutocompleteCompilerPass());
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/README.md b/src/Oro/Bundle/FormBundle/README.md
new file mode 100644
index 00000000000..d594728b9c0
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/README.md
@@ -0,0 +1,6 @@
+OroFormBundle
+=============
+
+Provide additional form types and form components.
+
+Please see [documentation](./Resources/doc/index.md) for more details.
diff --git a/src/Oro/Bundle/FormBundle/Resources/config/assets.yml b/src/Oro/Bundle/FormBundle/Resources/config/assets.yml
new file mode 100644
index 00000000000..8310dca3f2c
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Resources/config/assets.yml
@@ -0,0 +1,2 @@
+js:
+ - '@OroFormBundle/Resources/public/js/oro.select2.config.js'
\ No newline at end of file
diff --git a/src/Oro/Bundle/FormBundle/Resources/config/autocomplete.yml b/src/Oro/Bundle/FormBundle/Resources/config/autocomplete.yml
new file mode 100644
index 00000000000..01f4672ce5f
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Resources/config/autocomplete.yml
@@ -0,0 +1,19 @@
+parameters:
+ oro_form.autocomplete.security.class: Oro\Bundle\FormBundle\Autocomplete\Security
+ oro_form.autocomplete.search_registry.class: Oro\Bundle\FormBundle\Autocomplete\SearchRegistry
+ oro_form.autocomplete.search_handler.class: Oro\Bundle\FormBundle\Autocomplete\SearchHandler
+
+services:
+ oro_form.autocomplete.security:
+ class: %oro_form.autocomplete.security.class%
+ arguments: [@oro_user.acl_manager]
+
+ oro_form.autocomplete.search_registry:
+ class: %oro_form.autocomplete.search_registry.class%
+
+ oro_form.autocomplete.search_handler:
+ class: %oro_form.autocomplete.search_handler.class%
+ abstract: true
+ calls:
+ - [initSearchIndexer, ["@oro_search.index", %oro_search.entities_config%]]
+ - [initDoctrinePropertiesByManagerRegistry, ["@doctrine"]]
diff --git a/src/Oro/Bundle/FormBundle/Resources/config/form_type.yml b/src/Oro/Bundle/FormBundle/Resources/config/form_type.yml
new file mode 100644
index 00000000000..678e5de4383
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Resources/config/form_type.yml
@@ -0,0 +1,45 @@
+parameters:
+ oro_form.type.date.class: Oro\Bundle\FormBundle\Form\Type\OroDateType
+ oro_form.type.datetime.class: Oro\Bundle\FormBundle\Form\Type\OroDateTimeType
+ oro_form.type.combobox_local.class: Oro\Bundle\FormBundle\Form\Type\OroComboboxLocalType
+ oro_form.type.entity_identifier.class: Oro\Bundle\FormBundle\Form\Type\EntityIdentifierType
+ oro_form.type.jqueryselect2_hidden.class: Oro\Bundle\FormBundle\Form\Type\OroJquerySelect2HiddenType
+ oro_form.type.translatable_entity.class: Oro\Bundle\FormBundle\Form\Type\TranslatableEntityType
+
+services:
+ # Form types
+ oro_form.type.date:
+ class: %oro_form.type.date.class%
+ tags:
+ - { name: form.type, alias: oro_date }
+
+ oro_form.type.datetime:
+ class: %oro_form.type.datetime.class%
+ tags:
+ - { name: form.type, alias: oro_datetime }
+
+ oro_form.type.entity_identifier:
+ class: %oro_form.type.entity_identifier.class%
+ arguments: ["@doctrine"]
+ tags:
+ - { name: form.type, alias: oro_entity_identifier }
+
+ oro_form.type.jqueryselect2_hidden:
+ class: %oro_form.type.jqueryselect2_hidden.class%
+ arguments:
+ - @doctrine.orm.entity_manager
+ - @oro_form.autocomplete.search_registry
+ tags:
+ - { name: form.type, alias: oro_jqueryselect2_hidden }
+
+ oro_form.type.translatable_entity:
+ class: %oro_form.type.translatable_entity.class%
+ arguments: ["@doctrine"]
+ tags:
+ - { name: form.type, alias: translatable_entity }
+
+ oro_form.type.jqueryselect2_translatable_entity:
+ parent: genemu.form.jquery.type.select2
+ arguments: ["translatable_entity"]
+ tags:
+ - { name: form.type, alias: genemu_jqueryselect2_translatable_entity }
diff --git a/src/Oro/Bundle/FormBundle/Resources/config/routing.yml b/src/Oro/Bundle/FormBundle/Resources/config/routing.yml
new file mode 100644
index 00000000000..ff2eaa3411c
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Resources/config/routing.yml
@@ -0,0 +1,3 @@
+oro_form_bundle:
+ resource: "@OroFormBundle/Controller"
+ type: annotation
diff --git a/src/Oro/Bundle/FormBundle/Resources/doc/index.md b/src/Oro/Bundle/FormBundle/Resources/doc/index.md
new file mode 100644
index 00000000000..65145cf3382
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Resources/doc/index.md
@@ -0,0 +1,5 @@
+OroFormBundle Documentation
+===========================
+
+- [Form Components Overview](./reference/form_components.md)
+- [Autocomplete Form Type](./reference/autocomplete_form_type.md)
diff --git a/src/Oro/Bundle/FormBundle/Resources/doc/reference/autocomplete_form_type.md b/src/Oro/Bundle/FormBundle/Resources/doc/reference/autocomplete_form_type.md
new file mode 100644
index 00000000000..c21a3392724
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Resources/doc/reference/autocomplete_form_type.md
@@ -0,0 +1,242 @@
+Autocomplete Form Type
+----------------------
+
+#### Overview
+
+Autocomplete element is based on [GenemuFormBundle](https://github.com/genemu/GenemuFormBundle) [Select2](http://ivaynberg.github.io/select2/)
+form type. In case when autocomplete functionality is required for static selects
+or for entity based selects generic genemu_jqueryselect2_* form types may be used. For example:
+
+- genemu_jqueryselect2_choice
+- genemu_jqueryselect2_country
+- genemu_jqueryselect2_entity
+
+oro_jqueryselect2_hidden was created to add more complex support of AJAX based data sources.
+Main differences from genemu_jqueryselect2_hidden are:
+
+- support of configuration based autocompletition
+- selected value text is shown on entity edit form
+- pre-configured ability to work with doctrine entities, flexible entities and grids
+
+#### Form Type Configuration
+
+Consider there is a form type that should have a field with support of autocomplete powered by Select2 jQuery plugin:
+
+```php
+class ProductType extends AbstractType
+{
+/**
+ * {@inheritdoc}
+ */
+ public function buildForm(FormBuilderInterface $builder, array $options)
+ {
+ $builder->add(
+ 'user',
+ 'oro_jqueryselect2_hidden',
+ array(
+ 'autocomplete_alias' => 'users',
+
+ // Default values
+ 'configs' => array(
+ 'extra_config' => 'autocomplete',
+ 'placeholder' => 'Choose a value...',
+ 'allowClear' => true,
+ 'minimumInputLength' => 1,
+ 'route_name' => 'oro_form_autocomplete_search'
+ )
+ )
+ );
+ }
+
+ // ...
+}
+```
+
+Minimum required configuration with use of "autocomplete_alias":
+
+```php
+class ProductType extends AbstractType
+{
+/**
+ * {@inheritdoc}
+ */
+ public function buildForm(FormBuilderInterface $builder, array $options)
+ {
+ $builder->add(
+ 'user',
+ 'oro_jqueryselect2_hidden',
+ array(
+ 'autocomplete_alias' => 'users'
+ )
+ );
+ }
+
+ // ...
+}
+```
+
+
+Configuration without "autocomplete_alias":
+
+```php
+class ProductType extends AbstractType
+{
+/**
+ * {@inheritdoc}
+ */
+ public function buildForm(FormBuilderInterface $builder, array $options)
+ {
+ $builder->add(
+ 'user',
+ 'oro_jqueryselect2_hidden',
+ array(
+ 'converter' => $this->converter,
+ 'configs' => array(
+ 'properties' => array(),
+ 'route' => 'some_route',
+ 'entity_class' => 'UserFullyQualifiedClassName'
+ )
+ )
+ );
+ }
+
+ // ...
+}
+```
+
+**autocomplete_alias**
+
+This option refers to a service configured with tag "oro_form.autocomplete.search_handler". Details of service configuration
+described [here](#search-handler-configuration). If this option is set next options will be inited if they are empty:
+*entity_class*, *configs.properties*, *converter*, *configs.extra_config* ("autocomplete")
+
+**entity_class**
+
+Entity class (optional if "autocomplete_alias" option is provided).
+
+**converter**
+
+Object that implements Oro\Bundle\FormBundle\Autocomplete\ConverterInterface that will be used to convert bind entity into array to use in select2 plugin.
+This option can be ommited if option "autocomplete_alias" provided.
+
+**configs.properties**
+
+List of properties that will be used in view to convert json object to string that will be displayed in select options
+(optional if "autocomplete_alias" option is provided).
+
+**configs.extra_config**
+
+This option changes the block name in twig template that will be used to add extra configuration to select2 jQuery plugin.
+Make sure that block with name "oro_combobox_dataconfig_%extra_config%" exists. There are two predefined values that can be used:
+"autocomplete" (block name "oro_combobox_dataconfig_autocomplete") and "grid" (block name "oro_combobox_dataconfig_grid").
+
+If you need to extend select2 logic you can add a block in twig template with name of your "extra_config" and do all customization there.
+
+**configs.selection_template_twig**
+
+A name of Twig template that contain [underscore.js](http://underscorejs.org/) template.
+This template will be used in dropdown list to render each result row.
+Example of template:
+```
+<%= highlight(firstName) %> <%= highlight(lastName) %> (<%= highlight(email) %>) %>)
+```
+
+**configs.result_template_twig**
+
+Difference from "selection_template_twig" is that it will be used to render value when it is selected.
+
+**configs.placeholder**
+
+A string that will be displayed when field doesn't have a value.
+
+**configs.allowClear**
+
+Controls possibility to make selected value empty.
+
+**configs.minimumInputLength**
+
+Count of characters that should be typed before request to remote server will be send.
+
+**configs.ajax**
+
+Custom options that are used by select2 jQuery plugin.
+
+**configs.ajax.url**
+
+Custom URL that will be used instead of route_name to send search requests.
+
+**configs.route_name**
+
+Url of this route will be used by select2 plugin to iteract with search handler.
+By default Oro\Bundle\FormBundle\Controller\AutocompleteController::searchAction is used
+but you can implement your own action and use it by referencing it via *route_name*.
+
+
+#### Search Handler Service
+
+This service has several responsibilities:
+* searching results that matches queries when user types characters in field on the web page
+* converting each found entities to associated array that will be used on side of view and particularly in js code that
+ renders search results
+* providing information about entity class name that is handled, this information is used in form type to transform
+ id to entity object using transformer
+
+Generic way to declare a search handler service and make possible to reference it using option "autocomplete_alias" is
+to add declaration like below:
+
+```yml
+services:
+ users_search_handler:
+ parent: oro_form.autocomplete.search_handler
+ arguments:
+ - %user_class% # pass class name of entity
+ - ["firstName", "lastName"] # pass properties that should be transported to the client
+ tags:
+ - { name: oro_form.autocomplete.search_handler, alias: users, acl_resource: user_acl_resource }
+
+```
+
+
+After this "oro_jqueryselect2_hidden" form type can receive option "autocomplete_alias" with value "users".
+
+This services receives a class name of entity that will be used by form type and during search requests. Also it
+receives properties names that control what data will be transported to select2 javascript widget.
+
+This services can be parent of abstract service "oro_form.autocomplete.search_handler" but if you need your
+own implementation of search handler you should implement Oro\Bundle\FormBundle\Autocomplete\SearchHandlerInterface.
+
+#### Security
+
+Each tag "oro_form.autocomplete.search_handler" can contain attribute "acl_resource" that references to an ACL resource
+that should be granted to user that performs autocomplete request. This feature works only if you use default implementation
+of autocomplete search action: Oro\Bundle\FormBundle\Controller\AutocompleteController::searchAction.
+
+If you use custom "configs.route_name" option it's on your own to check user permissions.
+
+#### Iteraction of Server and Javascript
+
+Server action receives next parameters from client:
+* **name** - alias of search handler that is specified using tag "oro_form.autocomplete.search_handler"
+* **query** - search string
+* **page** - number of page to return
+* **per_page** - how many records service should return
+
+Select2 plugin on client side expects response in next format:
+```
+{
+ "results": [{"id": 1, "firstName": "John", "lastName": "Doe"}, {...}, ...]
+ "more": true|false
+}
+```
+
+Properties "firstName" and "lastName" are configured in search handler service.
+
+
+#### Dependency on OroSearchBundle
+
+Default implementation of search handler is based on functionality of OroSearchBundle. If you use this implementation
+your entity should be properly configured in the way that OroSearchBundle allows.
+
+#### Dependency on OroUserBundle
+
+As each autocomplete could be protected using ACL-resource, there is a dependency on OroUserBundle, particularly on "oro_user.acl_manager" service.
diff --git a/src/Oro/Bundle/FormBundle/Resources/doc/reference/form_components.md b/src/Oro/Bundle/FormBundle/Resources/doc/reference/form_components.md
new file mode 100644
index 00000000000..b47f3a80ac4
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Resources/doc/reference/form_components.md
@@ -0,0 +1,61 @@
+Form Components Overview
+------------------------
+
+This article describes all form components that are stored in OroUIBundle.
+Form components are form types, data transformers and event listeners.
+
+### Form Types
+
+* **Form / Type / OroDateType** (name = oro_date) - encapsulates date element logic;
+* **Form / Type / OroDateTimeType** (name = oro_datetime) - encapsulates datetime element logic;
+* **Form / Type / EntityIdentifierType** (name = oro_entity_identifier) - converts string or array of entity IDs to existing entities of specified type.
+* **Form / Type / OroJquerySelect2HiddenType** (name = oro_jqueryselect2_hidden) - supports autocompletition ([more details](./autocomplete_form_type.md))
+
+### Data Transformers
+
+* **Form / DataTransformer / ArrayToStringTransformer** - converts array to string and back;
+* **Form / DataTransformer / EntitiesToIdsTransformer** - converts entity IDs to entities and back.
+* **Form / DataTransformer / EntityToIdTransformer** - converts entity ID to entity and back.
+
+
+### Event Subscribers
+
+* **Form / EventListener / FixArrayToStringListener** - converts array to string on form PRE_BIND event.
+
+
+### Configuration
+
+#### Form Types
+
+```
+parameters:
+ oro_form.type.date.class: Oro\Bundle\FormBundle\Form\Type\OroDateType
+ oro_form.type.datetime.class: Oro\Bundle\FormBundle\Form\Type\OroDateTimeType
+ oro_form.type.entity_identifier.class: Oro\Bundle\FormBundle\Form\Type\EntityIdentifierType
+ oro_form.type.jqueryselect2_hidden.class: Oro\Bundle\FormBundle\Form\Type\OroJquerySelect2HiddenType
+
+services:
+ oro_form.type.date:
+ class: %oro_form.type.date.class%
+ tags:
+ - { name: form.type, alias: oro_date }
+
+ oro_form.type.datetime:
+ class: %oro_form.type.datetime.class%
+ tags:
+ - { name: form.type, alias: oro_datetime }
+
+ oro_form.type.entity_identifier:
+ class: %oro_form.type.entity_identifier.class%
+ tags:
+ - { name: form.type, alias: oro_entity_identifier }
+ arguments: ["@doctrine"]
+
+ oro_form.type.jqueryselect2_hidden:
+ class: %oro_form.type.jqueryselect2_hidden.class%
+ arguments:
+ - @doctrine.orm.entity_manager
+ - @oro_form.autocomplete.configuration
+ tags:
+ - { name: form.type, alias: oro_jqueryselect2_hidden }
+```
diff --git a/src/Oro/Bundle/FormBundle/Resources/public/js/oro.select2.config.js b/src/Oro/Bundle/FormBundle/Resources/public/js/oro.select2.config.js
new file mode 100644
index 00000000000..94258d63bba
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Resources/public/js/oro.select2.config.js
@@ -0,0 +1,83 @@
+var OroSelect2Config = function (config, url, perPage) {
+ this.config = config;
+ this.url = url;
+ this.perPage = perPage;
+};
+
+OroSelect2Config.prototype.getConfig = function () {
+ var self = this;
+ if (this.config.formatResult === undefined) {
+ this.config.formatResult = this.format(this.config.result_template !== undefined ? this.config.result_template : false);
+ }
+ if (this.config.formatSelection === undefined) {
+ this.config.formatSelection = this.format(this.config.selection_template !== undefined ? this.config.selection_template : false);
+ }
+ if (this.config.initSelection === undefined) {
+ this.config.initSelection = this.initSelection;
+ }
+ if (this.config.ajax === undefined) {
+ this.config.ajax = {
+ 'url': this.url,
+ 'data': function (query, page) {
+ return {
+ 'page': page,
+ 'per_page': self.perPage,
+ 'query': query
+ };
+ },
+ 'results': function (data, page) {
+ return data;
+ }
+ };
+ }
+ if (this.config.ajax.quietMillis === undefined) {
+ this.config.ajax.quietMillis = 700;
+ }
+ if (this.config.escapeMarkup === undefined) {
+ this.config.escapeMarkup = function (m) { return m; };
+ }
+ return this.config;
+};
+
+OroSelect2Config.prototype.format = function (jsTemplate) {
+ var self = this;
+ return function (object, container, query) {
+ if ($.isEmptyObject(object)) {
+ return undefined;
+ }
+ var result = '';
+ var highlight = function (str) {
+ return self.highlightSelection(str, query);
+ };
+ if (object._html !== undefined) {
+ result = object._html;
+ } else if (jsTemplate) {
+ object.highlight = highlight;
+ var tpl = _.template(jsTemplate);
+ result = tpl(object);
+ } else {
+ result = highlight(self.getTitle(object, self.config.properties));
+ }
+ return result;
+ };
+};
+
+OroSelect2Config.prototype.initSelection = function (element, callback) {
+ callback(element.data('entity'));
+};
+
+OroSelect2Config.prototype.highlightSelection = function (str, selection) {
+ return str && selection && selection.term ? str.replace(new RegExp(selection.term, 'ig'), '$&') : str;
+};
+
+OroSelect2Config.prototype.getTitle = function (data, properties) {
+ var title = '';
+ if (data) {
+ var result = [];
+ for (var i = 0; i < properties.length; i++) {
+ result.push(data[properties[i]]);
+ }
+ title = result.join(' ');
+ }
+ return title;
+};
diff --git a/src/Oro/Bundle/FormBundle/Resources/translations/messages.en.yml b/src/Oro/Bundle/FormBundle/Resources/translations/messages.en.yml
new file mode 100644
index 00000000000..8f83e39dbfd
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Resources/translations/messages.en.yml
@@ -0,0 +1 @@
+oro.form.choose_value: Choose a value...
diff --git a/src/Oro/Bundle/FormBundle/Resources/views/Form/fields.html.twig b/src/Oro/Bundle/FormBundle/Resources/views/Form/fields.html.twig
new file mode 100644
index 00000000000..8c80e4ac9e7
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Resources/views/Form/fields.html.twig
@@ -0,0 +1,155 @@
+{% block oro_ticker_symbol_widget %}
+
+
+ {{ form_widget(form) }}
+{% endblock %}
+
+{% block genemu_jqueryselect2_country_row %}
+ {{ block('genemu_jqueryselect2_row') }}
+{% endblock %}
+
+{% block genemu_jqueryselect2_choice_row %}
+ {{ block('genemu_jqueryselect2_row') }}
+{% endblock %}
+
+{% block genemu_jqueryselect2_entity_row %}
+ {{ block('genemu_jqueryselect2_row') }}
+{% endblock %}
+
+{% block oro_jqueryselect2_hidden_row %}
+ {{ block('genemu_jqueryselect2_row') }}
+{% endblock %}
+
+{% block genemu_jqueryselect2_row %}
+ {{ form_row(form) }}
+ {{ form_javascript(form) }}
+{% endblock %}
+
+{% block genemu_jqueryselect2_javascript %}
+
+{% endblock %}
+
+{% block oro_combobox_dataconfig_autocomplete %}
+ {% set url = '' %}
+ {% if configs.ajax.url is defined and configs.ajax.url%}
+ {% set url = configs.ajax.url %}
+ {% elseif configs.route_name is defined and configs.route_name %}
+ {% set url = path(configs.route_name) %}
+ {% endif %}
+ select2Config.ajax = {
+ 'url': {{ url|json_encode|raw }},
+ 'data': function (query, page) {
+ return {
+ 'page': page,
+ 'per_page': {{ configs.per_page|default(10) }},
+ 'name': "{{ configs.autocomplete_alias }}",
+ 'query': query
+ };
+ },
+ 'results': function (data, page) {
+ return data;
+ }
+ };
+{% endblock %}
+
+{% block oro_combobox_dataconfig_grid %}
+ {% set url = configs.ajax.url is defined ? configs.ajax.url : path(configs.route, {'_format': 'json'}) %}
+ select2Config.ajax = {
+ 'url': {{ url|json_encode|raw }},
+ 'data': function (query, page) {
+ return {
+ '{{ configs.grid.name }}[_pager][_page]': page,
+ '{{ configs.grid.name }}[_pager][_per_page]': {{ configs.per_page|default(10) }},
+ '{{ configs.grid.name }}[_sort_by][{{ configs.grid.sort_by|default(configs.properties[0]) }}]': "{{ configs.grid.sort_order|default('ASC') }}",
+ '{{ configs.grid.name }}[_filter][{{ configs.properties[0] }}][type]': 1,
+ '{{ configs.grid.name }}[_filter][{{ configs.properties[0] }}][value]': query
+ };
+ },
+ 'results': function (data, page) {
+ return {
+ results: $.map(data.data, function(item) {
+ return {'id': item.id, 'text': item.{{- configs.properties[0] -}} };
+ }),
+ more: page*10 < data.options.totalRecords
+ };
+ }
+ };
+{% endblock %}
diff --git a/src/Oro/Bundle/FormBundle/Tests/Unit/Autocomplete/SearchHandlerTest.php b/src/Oro/Bundle/FormBundle/Tests/Unit/Autocomplete/SearchHandlerTest.php
new file mode 100644
index 00000000000..3b5e01591af
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Tests/Unit/Autocomplete/SearchHandlerTest.php
@@ -0,0 +1,426 @@
+ array('alias' => self::TEST_ENTITY_SEARCH_ALIAS));
+
+ /**
+ * @var Indexer|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $indexer;
+
+ /**
+ * @var ManagerRegistry|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $managerRegistry;
+
+ /**
+ * @var EntityManager|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityManager;
+
+ /**
+ * @var EntityRepository|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $entityRepository;
+
+ /**
+ * @var QueryBuilder|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $queryBuilder;
+
+ /**
+ * @var AbstractQuery|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $query;
+
+ /**
+ * @var Expr|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $expr;
+
+ /**
+ * @var Result|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $searchResult;
+
+ /**
+ * @var SearchHandler
+ */
+ protected $searchHandler;
+
+ protected function setUp()
+ {
+ $this->indexer = $this->getMockBuilder('Oro\Bundle\SearchBundle\Engine\Indexer')
+ ->setMethods(array('simpleSearch'))
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->entityRepository = $this->getMockBuilder('Doctrine\ORM\EntityRepository')
+ ->disableOriginalConstructor()
+ ->setMethods(array('createQueryBuilder'))
+ ->getMock();
+
+ $metadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')
+ ->setMethods(array('getSingleIdentifierFieldName'))
+ ->disableOriginalConstructor()
+ ->getMock();
+ $metadata->expects($this->once())
+ ->method('getSingleIdentifierFieldName')
+ ->will($this->returnValue(self::TEST_ID_FIELD));
+
+ $metadataFactory = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadataFactory')
+ ->setMethods(array('getMetadataFor'))
+ ->disableOriginalConstructor()
+ ->getMock();
+ $metadataFactory->expects($this->once())
+ ->method('getMetadataFor')
+ ->with(self::TEST_ENTITY_CLASS)
+ ->will($this->returnValue($metadata));
+
+ $this->entityManager = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getRepository', 'getMetadataFactory'))
+ ->getMock();
+ $this->entityManager->expects($this->once())
+ ->method('getRepository')
+ ->will($this->returnValue($this->entityRepository));
+ $this->entityManager->expects($this->once())
+ ->method('getMetadataFactory')
+ ->will($this->returnValue($metadataFactory));
+
+ $this->managerRegistry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
+ $this->managerRegistry->expects($this->once())
+ ->method('getManagerForClass')
+ ->with(self::TEST_ENTITY_CLASS)
+ ->will($this->returnValue($this->entityManager));
+
+ $this->queryBuilder = $this->getMockBuilder('Doctrine\ORM\QueryBuilder')
+ ->disableOriginalConstructor()
+ ->setMethods(array('expr', 'getQuery', 'where'))
+ ->getMock();
+
+ $this->query = $this->getMockBuilder('Doctrine\ORM\AbstractQuery')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getResult'))
+ ->getMockForAbstractClass();
+
+ $this->expr = $this->getMockBuilder('Doctrine\ORM\Query\Expr')
+ ->disableOriginalConstructor()
+ ->setMethods(array('in'))
+ ->getMock();
+
+ $this->searchResult = $this->getMockBuilder('Oro\Bundle\SearchBundle\Query\Result')
+ ->setMethods(array('getElements'))
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->searchHandler = new SearchHandler(
+ self::TEST_ENTITY_CLASS,
+ $this->testProperties
+ );
+
+ $this->searchHandler->initDoctrinePropertiesByManagerRegistry($this->managerRegistry);
+ $this->searchHandler->initSearchIndexer($this->indexer, $this->testSearchConfig);
+ }
+
+ public function testConstructorAndInitialize()
+ {
+ $this->assertAttributeSame(
+ $this->indexer,
+ 'indexer',
+ $this->searchHandler
+ );
+ $this->assertAttributeSame(
+ $this->entityRepository,
+ 'entityRepository',
+ $this->searchHandler
+ );
+ $this->assertAttributeEquals(
+ self::TEST_ENTITY_CLASS,
+ 'entityName',
+ $this->searchHandler
+ );
+ $this->assertAttributeEquals(
+ self::TEST_ID_FIELD,
+ 'idFieldName',
+ $this->searchHandler
+ );
+ $this->assertAttributeEquals(
+ $this->testProperties,
+ 'properties',
+ $this->searchHandler
+ );
+ }
+
+ public function testGetProperties()
+ {
+ $this->assertEquals($this->testProperties, $this->searchHandler->getProperties());
+ }
+
+ public function testGetEntitName()
+ {
+ $this->assertEquals(self::TEST_ENTITY_CLASS, $this->searchHandler->getEntityName());
+ }
+
+ /**
+ * @dataProvider searchDataProvider
+ * @param string $query
+ * @param array $expectedResult
+ * @param array $expectedIndexerCalls
+ * @param array $expectSearchResultCalls
+ * @param array $expectEntityRepositoryCalls
+ * @param array $expectQueryBuilderCalls
+ * @param array $expectExprCalls
+ * @param array $expectQueryCalls
+ */
+ public function testSearch(
+ $query,
+ $expectedResult,
+ $expectedIndexerCalls,
+ $expectSearchResultCalls,
+ $expectEntityRepositoryCalls,
+ $expectQueryBuilderCalls,
+ $expectExprCalls,
+ $expectQueryCalls
+ ) {
+ MockHelper::addMockExpectedCalls($this->indexer, $expectedIndexerCalls, $this);
+ MockHelper::addMockExpectedCalls($this->searchResult, $expectSearchResultCalls, $this);
+ MockHelper::addMockExpectedCalls($this->entityRepository, $expectEntityRepositoryCalls, $this);
+ MockHelper::addMockExpectedCalls($this->queryBuilder, $expectQueryBuilderCalls, $this);
+ MockHelper::addMockExpectedCalls($this->expr, $expectExprCalls, $this);
+ MockHelper::addMockExpectedCalls($this->query, $expectQueryCalls, $this);
+
+ $actualResult = $this->searchHandler->search($query['query'], $query['page'], $query['perPage']);
+ $this->assertEquals($expectedResult, $actualResult);
+ }
+
+ /**
+ * @return array
+ * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+ */
+ public function searchDataProvider()
+ {
+ return array(
+ 'default' => array(
+ 'query' => array('query' => 'search', 'page' => 1, 'perPage' => 100),
+ 'expectedResult' => array(
+ 'results' => array(
+ array(self::TEST_ID_FIELD => 1, 'name' => 'John', 'email' => 'john@example.com'),
+ array(self::TEST_ID_FIELD => 2, 'name' => 'Jane', 'email' => 'jane@example.com'),
+ array(self::TEST_ID_FIELD => 3, 'name' => 'Jack', 'email' => null),
+ array(self::TEST_ID_FIELD => 4, 'name' => 'Bill', 'email' => 'bill@example.com')
+ ),
+ 'more' => false
+ ),
+ 'expectIndexerCalls' => array(
+ array(
+ 'simpleSearch',
+ array('search', 0, 101, self::TEST_ENTITY_SEARCH_ALIAS), 'getMockSearchResult'
+ )
+ ),
+ 'expectSearchResultCalls' => array(
+ array('getElements', array(), $this->createMockSearchItems(array(1, 2, 3, 4)))
+ ),
+ 'expectEntityRepositoryCalls' => array(
+ array('createQueryBuilder', array('e'), 'getMockQueryBuilder')
+ ),
+ 'expectQueryBuilderCalls' => array(
+ array('expr', array(), 'getMockExpr'),
+ array('where', array('e.id IN (1, 2, 3, 4)'), 'getMockQueryBuilder'),
+ array('getQuery', array(), 'getMockQuery'),
+ ),
+ 'expectExprCalls' => array(
+ array('in', array('e.' . self::TEST_ID_FIELD, array(1, 2, 3, 4)), 'e.id IN (1, 2, 3, 4)')
+ ),
+ 'expectQueryCalls' => array(
+ array(
+ 'getResult',
+ array(),
+ array(
+ $this->createMockEntity(
+ array(self::TEST_ID_FIELD => 1, 'name' => 'John', 'email' => 'john@example.com')
+ ),
+ $this->createMockEntity(
+ array(self::TEST_ID_FIELD => 2, 'name' => 'Jane', 'email' => 'jane@example.com')
+ ),
+ array(self::TEST_ID_FIELD => 3,'name' => 'Jack'),
+ $this->createStubEntityWithProperties(
+ array(
+ self::TEST_ID_FIELD => 4,
+ 'name' => 'Bill',
+ 'email' => $this->createMockFlexibleValue('bill@example.com')
+ )
+ )
+ )
+ )
+ ),
+ ),
+ 'hasMore' => array(
+ 'query' => array('query' => 'search', 'page' => 1, 'perPage' => 1),
+ 'expectedResult' => array(
+ 'results' => array(
+ array(
+ self::TEST_ID_FIELD => 1, 'name' => 'John', 'email' => 'john@example.com'
+ )
+ ),
+ 'more' => true
+ ),
+ 'expectIndexerCalls' => array(
+ array(
+ 'simpleSearch', array('search', 0, 2, self::TEST_ENTITY_SEARCH_ALIAS), 'getMockSearchResult'
+ )
+ ),
+ 'expectSearchResultCalls' => array(
+ array('getElements', array(), $this->createMockSearchItems(array(1, 2)))
+ ),
+ 'expectEntityRepositoryCalls' => array(
+ array('createQueryBuilder', array('e'), 'getMockQueryBuilder')
+ ),
+ 'expectQueryBuilderCalls' => array(
+ array('expr', array(), 'getMockExpr'),
+ array('where', array('e.id IN (1, 2)'), 'getMockQueryBuilder'),
+ array('getQuery', array(), 'getMockQuery'),
+ ),
+ 'expectExprCalls' => array(
+ array('in', array('e.' . self::TEST_ID_FIELD, array(1, 2)), 'e.id IN (1, 2)')
+ ),
+ 'expectQueryCalls' => array(
+ array(
+ 'getResult',
+ array(),
+ array(
+ $this->createMockEntity(
+ array(self::TEST_ID_FIELD => 1, 'name' => 'John', 'email' => 'john@example.com')
+ ),
+ $this->createMockEntity(
+ array(self::TEST_ID_FIELD => 2, 'name' => 'Jane', 'email' => 'jane@example.com')
+ )
+ )
+ )
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @return Result|\PHPUnit_Framework_MockObject_MockObject
+ */
+ public function getMockSearchResult()
+ {
+ return $this->searchResult;
+ }
+
+ /**
+ * @return QueryBuilder|\PHPUnit_Framework_MockObject_MockObject
+ */
+ public function getMockQueryBuilder()
+ {
+ return $this->queryBuilder;
+ }
+
+ /**
+ * @return Expr|\PHPUnit_Framework_MockObject_MockObject
+ */
+ public function getMockExpr()
+ {
+ return $this->expr;
+ }
+
+ /**
+ * @return AbstractQuery|\PHPUnit_Framework_MockObject_MockObject
+ */
+ public function getMockQuery()
+ {
+ return $this->query;
+ }
+
+ /**
+ * @param array $ids
+ * @return Item[]
+ */
+ public function createMockSearchItems(array $ids)
+ {
+ $result = array();
+ foreach ($ids as $id) {
+ $item = $this->getMockBuilder('Oro\Bundle\SearchBundle\Query\Result\Item')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getRecordId'))
+ ->getMock();
+ $item->expects($this->once())
+ ->method('getRecordId')
+ ->will($this->returnValue($id));
+ $result[] = $item;
+ }
+ return $result;
+ }
+
+ public function createStubEntityWithProperties(array $data)
+ {
+ $result = new \stdClass();
+ foreach ($data as $name => $property) {
+ $result->$name = $property;
+ }
+ return $result;
+ }
+
+ public function createMockEntity(array $data)
+ {
+ $methods = array();
+ foreach (array_keys($data) as $name) {
+ $methods[$name] = 'get' .ucfirst($name);
+ }
+ $result = $this->getMock('stdClass', array_values($methods));
+ foreach ($data as $name => $property) {
+ $result->expects($this->any())
+ ->method($methods[$name])
+ ->will($this->returnValue($property));
+ }
+ return $result;
+ }
+
+ public function createMockFlexibleValue($data)
+ {
+ $result = $this->getMock('Oro\Bundle\FlexibleEntityBundle\Model\FlexibleValueInterface');
+ $result->expects($this->any())
+ ->method('getData')
+ ->will($this->returnValue($data));
+ return $result;
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/Tests/Unit/Autocomplete/SearchRegistryTest.php b/src/Oro/Bundle/FormBundle/Tests/Unit/Autocomplete/SearchRegistryTest.php
new file mode 100644
index 00000000000..c9f2dd0a8ca
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Tests/Unit/Autocomplete/SearchRegistryTest.php
@@ -0,0 +1,50 @@
+searchHandler = $this->getMock('Oro\Bundle\FormBundle\Autocomplete\SearchHandlerInterface');
+ $this->searchRegistry = new SearchRegistry();
+ }
+
+ public function testAddSearchHandler()
+ {
+ $this->searchRegistry->addSearchHandler('test', $this->searchHandler);
+ $this->assertAttributeSame(
+ array('test' => $this->searchHandler),
+ 'searchHandlers',
+ $this->searchRegistry
+ );
+ }
+
+ public function testGetSearchHandler()
+ {
+ $this->searchRegistry->addSearchHandler('test', $this->searchHandler);
+ $this->assertSame($this->searchHandler, $this->searchRegistry->getSearchHandler('test'));
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Search handler "test" is not registered
+ */
+ public function testGetSearchHandlerFails()
+ {
+ $this->searchRegistry->getSearchHandler('test');
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/Tests/Unit/Autocomplete/SecurityTest.php b/src/Oro/Bundle/FormBundle/Tests/Unit/Autocomplete/SecurityTest.php
new file mode 100644
index 00000000000..4858bb5c613
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Tests/Unit/Autocomplete/SecurityTest.php
@@ -0,0 +1,57 @@
+manager = $this->getMock('Oro\Bundle\UserBundle\Acl\ManagerInterface');
+ $this->security = new Security($this->manager);
+ }
+
+ public function testSetAutocompleteAclResource()
+ {
+ $this->security->setAutocompleteAclResource('test_search', 'test_acl_resource');
+ $this->assertAttributeEquals(
+ array('test_search' => 'test_acl_resource'),
+ 'autocompleteAclResources',
+ $this->security
+ );
+ }
+
+ public function testGetAutocompleteAclResource()
+ {
+ $this->assertNull($this->security->getAutocompleteAclResource('test'));
+
+ $this->security->setAutocompleteAclResource('test_search', 'test_acl_resource');
+ $this->assertEquals('test_acl_resource', $this->security->getAutocompleteAclResource('test_search'));
+ }
+
+ public function testIsAutocompleteGranted()
+ {
+ $this->assertFalse($this->security->isAutocompleteGranted('test_acl_resource'));
+
+ $this->security->setAutocompleteAclResource('test_search', 'test_acl_resource');
+
+ $this->manager->expects($this->once())
+ ->method('isResourceGranted')
+ ->with('test_acl_resource')
+ ->will($this->returnValue(true));
+
+ $this->assertTrue($this->security->isAutocompleteGranted('test_search'));
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/Tests/Unit/DependencyInjection/Compiler/AutocompleteCompilerPassTest.php b/src/Oro/Bundle/FormBundle/Tests/Unit/DependencyInjection/Compiler/AutocompleteCompilerPassTest.php
new file mode 100644
index 00000000000..b5a9f0e0e23
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Tests/Unit/DependencyInjection/Compiler/AutocompleteCompilerPassTest.php
@@ -0,0 +1,73 @@
+ array(
+ array('alias' => 'tag1'), array('alias' => 'tag2')
+ ),
+ 'testId2' => array(
+ array('alias' => 'tag1', 'acl_resource' => 'test_acl_resource')
+ ),
+ 'testId3' => array(
+ array('name' => 'not_matched')
+ )
+ );
+
+ $searchRegistryDefinition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $searchRegistryDefinition->expects($this->exactly(4))
+ ->method('addMethodCall');
+ $searchRegistryDefinition->expects($this->at(0))
+ ->method('addMethodCall')
+ ->with('addSearchHandler', array('tag1', new Reference('testId1')));
+ $searchRegistryDefinition->expects($this->at(1))
+ ->method('addMethodCall')
+ ->with('addSearchHandler', array('tag2', new Reference('testId1')));
+ $searchRegistryDefinition->expects($this->at(2))
+ ->method('addMethodCall')
+ ->with('addSearchHandler', array('tag1', new Reference('testId2')));
+ $searchRegistryDefinition->expects($this->at(3))
+ ->method('addMethodCall')
+ ->with('addSearchHandler', array('testId3', new Reference('testId3')));
+
+ $securityDefinition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $securityDefinition->expects($this->exactly(1))
+ ->method('addMethodCall');
+ $securityDefinition->expects($this->at(0))
+ ->method('addMethodCall')
+ ->with('setAutocompleteAclResource', array('tag1', 'test_acl_resource'));
+
+ $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $container->expects($this->at(0))
+ ->method('getDefinition')
+ ->with('oro_form.autocomplete.search_registry')
+ ->will($this->returnValue($searchRegistryDefinition));
+
+ $container->expects($this->at(1))
+ ->method('getDefinition')
+ ->with('oro_form.autocomplete.security')
+ ->will($this->returnValue($securityDefinition));
+
+ $container->expects($this->at(2))
+ ->method('findTaggedServiceIds')
+ ->with('oro_form.autocomplete.search_handler')
+ ->will($this->returnValue($attributes));
+
+ $pass = new AutocompleteCompilerPass();
+ $pass->process($container);
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/Tests/Unit/DependencyInjection/ConfigurationTest.php b/src/Oro/Bundle/FormBundle/Tests/Unit/DependencyInjection/ConfigurationTest.php
new file mode 100644
index 00000000000..51de5520e4f
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Tests/Unit/DependencyInjection/ConfigurationTest.php
@@ -0,0 +1,23 @@
+getConfigTreeBuilder();
+ $this->assertInstanceOf('Symfony\Component\Config\Definition\Builder\TreeBuilder', $builder);
+
+ /** @var $root ArrayNode */
+ $root = $builder->buildTree();
+ $this->assertInstanceOf('Symfony\Component\Config\Definition\ArrayNode', $root);
+ $this->assertEquals('oro_form', $root->getName());
+ }
+}
diff --git a/src/Oro/Bundle/UIBundle/Tests/Unit/Form/DataTransformer/ArrayToStringTransformerTest.php b/src/Oro/Bundle/FormBundle/Tests/Unit/Form/DataTransformer/ArrayToStringTransformerTest.php
similarity index 97%
rename from src/Oro/Bundle/UIBundle/Tests/Unit/Form/DataTransformer/ArrayToStringTransformerTest.php
rename to src/Oro/Bundle/FormBundle/Tests/Unit/Form/DataTransformer/ArrayToStringTransformerTest.php
index 4e18674cc80..f20f2f832ee 100644
--- a/src/Oro/Bundle/UIBundle/Tests/Unit/Form/DataTransformer/ArrayToStringTransformerTest.php
+++ b/src/Oro/Bundle/FormBundle/Tests/Unit/Form/DataTransformer/ArrayToStringTransformerTest.php
@@ -1,8 +1,8 @@
getMockEntityManager(), 'TestClass', $property, null);
+ $this->assertEquals($expectedValue, $transformer->transform($value));
+ }
+
+ /**
+ * @return array
+ */
+ public function transformDataProvider()
+ {
+ return array(
+ 'default' => array(
+ 'id',
+ $this->createMockEntity('id', 1),
+ 1
+ ),
+ 'empty' => array(
+ 'id',
+ null,
+ null
+ ),
+ );
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
+ * @expectedExceptionMessage Expected argument of type "object", "string" given
+ */
+ public function testTransformFailsWhenValueInNotAnArray()
+ {
+ $transformer = new EntityToIdTransformer($this->getMockEntityManager(), 'TestClass', 'id', null);
+ $transformer->transform('invalid value');
+ }
+
+ public function testReverseTransformEmpty()
+ {
+ $transformer = new EntityToIdTransformer($this->getMockEntityManager(), 'TestClass', 'id', null);
+ $this->assertNull($transformer->reverseTransform(''));
+ }
+
+ public function testReverseTransform()
+ {
+ $entity = $this->createMockEntity('id', 1);
+
+ $repository = $this->getMockBuilder('Doctrine\ORM\EntityRepository')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $repository->expects($this->once())
+ ->method('find')
+ ->with(1)
+ ->will($this->returnValue($entity));
+
+ $em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $em->expects($this->once())
+ ->method('getRepository')
+ ->with('TestClass')
+ ->will($this->returnValue($repository));
+
+ $transformer = new EntityToIdTransformer($em, 'TestClass', 'id', null);
+ $this->assertEquals($entity, $transformer->reverseTransform(1));
+ }
+
+ public function testReverseTransformQueryBuilder()
+ {
+ $entity = $this->createMockEntity('id', 1);
+
+ $repository = $this->getMockBuilder('Doctrine\ORM\EntityRepository')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $self= $this;
+ $callback = function ($pRepository, $pId) use ($self, $repository, $entity) {
+ $self->assertEquals($repository, $pRepository);
+ $self->assertEquals(1, $pId);
+
+ $query = $self->getMockBuilder('Doctrine\ORM\AbstractQuery')
+ ->disableOriginalConstructor()
+ ->setMethods(array('execute'))
+ ->getMockForAbstractClass();
+ $query->expects($self->once())
+ ->method('execute')
+ ->will($self->returnValue($entity));
+
+ $qb = $self->getMockBuilder('Doctrine\ORM\QueryBuilder')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $qb->expects($self->once())
+ ->method('getQuery')
+ ->will($self->returnValue($query));
+ return $qb;
+ };
+
+ $em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $em->expects($this->once())
+ ->method('getRepository')
+ ->with('TestClass')
+ ->will($this->returnValue($repository));
+
+ $transformer = new EntityToIdTransformer($em, 'TestClass', 'id', $callback);
+ $this->assertEquals($entity, $transformer->reverseTransform(1));
+ }
+
+ /**
+ * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
+ * @expectedExceptionMessage Expected argument of type "Doctrine\ORM\QueryBuilder", "NULL" given
+ */
+ public function testReverseTransformQueryBuilderException()
+ {
+ $entity = $this->createMockEntity('id', 1);
+
+ $repository = $this->getMockBuilder('Doctrine\ORM\EntityRepository')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $callback = function () {
+ return null;
+ };
+
+ $em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $em->expects($this->once())
+ ->method('getRepository')
+ ->with('TestClass')
+ ->will($this->returnValue($repository));
+
+ $transformer = new EntityToIdTransformer($em, 'TestClass', 'id', $callback);
+ $this->assertEquals($entity, $transformer->reverseTransform(1));
+ }
+
+ public function testPropertyConstruction()
+ {
+ $em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $metadata = $this->getMockBuilder('\Doctrine\ORM\Mapping\ClassMetadata')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $metadata->expects($this->once())
+ ->method('getSingleIdentifierFieldName')
+ ->will($this->returnValue('id'));
+ $em->expects($this->once())
+ ->method('getClassMetadata')
+ ->will($this->returnValue($metadata));
+
+ new EntityToIdTransformer($em, 'TestClass', null, null);
+ }
+
+ /**
+ * @expectedException Symfony\Component\Form\Exception\FormException
+ * @expectedExceptionMessage Cannot get id property path of entity. "TestClass" has composite primary key.
+ */
+ public function testPropertyConstructionException()
+ {
+ $em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $metadata = $this->getMockBuilder('\Doctrine\ORM\Mapping\ClassMetadata')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $metadata->expects($this->once())
+ ->method('getSingleIdentifierFieldName')
+ ->will(
+ $this->returnCallback(
+ function () {
+ throw new MappingException('Exception');
+ }
+ )
+ );
+ $em->expects($this->once())
+ ->method('getClassMetadata')
+ ->will($this->returnValue($metadata));
+
+ new EntityToIdTransformer($em, 'TestClass', null, null);
+ }
+
+ /**
+ * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
+ * @expectedExceptionMessage Expected argument of type "callable", "string" given
+ */
+ public function testCallbackException()
+ {
+ new EntityToIdTransformer($this->getMockEntityManager(), 'TestClass', 'id', 'uncallable');
+ }
+
+ /**
+ * @return EntityManager|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected function getMockEntityManager()
+ {
+ if (!$this->entityManager) {
+ $this->entityManager = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getClassMetadata', 'getRepository'))
+ ->getMockForAbstractClass();
+ }
+
+ return $this->entityManager;
+ }
+
+ /**
+ * Create mock entity by id property name and value
+ *
+ * @param string $property
+ * @param mixed $value
+ * @return \PHPUnit_Framework_MockObject_MockObject
+ */
+ private function createMockEntity($property, $value)
+ {
+ $getter = 'get' . ucfirst($property);
+ $result = $this->getMock('MockEntity', array($getter));
+ $result->expects($this->any())->method($getter)->will($this->returnValue($value));
+ return $result;
+ }
+}
diff --git a/src/Oro/Bundle/UIBundle/Tests/Unit/Form/EventListener/FixArrayToStringListenerTest.php b/src/Oro/Bundle/FormBundle/Tests/Unit/Form/EventListener/FixArrayToStringListenerTest.php
similarity index 91%
rename from src/Oro/Bundle/UIBundle/Tests/Unit/Form/EventListener/FixArrayToStringListenerTest.php
rename to src/Oro/Bundle/FormBundle/Tests/Unit/Form/EventListener/FixArrayToStringListenerTest.php
index a9a231ad0be..f2448d1cf0e 100644
--- a/src/Oro/Bundle/UIBundle/Tests/Unit/Form/EventListener/FixArrayToStringListenerTest.php
+++ b/src/Oro/Bundle/FormBundle/Tests/Unit/Form/EventListener/FixArrayToStringListenerTest.php
@@ -1,12 +1,12 @@
type = $this->getMockBuilder('Oro\Bundle\UIBundle\Form\Type\EntityIdentifierType')
+ $this->type = $this->getMockBuilder('Oro\Bundle\FormBundle\Form\Type\EntityIdentifierType')
->setMethods(array('createEntitiesToIdsTransformer'))
->setConstructorArgs(array($this->getMockManagerRegistry()))
->getMock();
@@ -282,7 +283,7 @@ public function testCreateEntitiesToIdsTransformer()
$this->callback(
function ($transformer) use ($options) {
\PHPUnit_Framework_TestCase::assertInstanceOf(
- 'Oro\Bundle\UIBundle\Form\DataTransformer\EntitiesToIdsTransformer',
+ 'Oro\Bundle\FormBundle\Form\DataTransformer\EntitiesToIdsTransformer',
$transformer
);
\PHPUnit_Framework_TestCase::assertAttributeEquals(
@@ -412,7 +413,7 @@ protected function getMockEntitiesToIdsTransformer()
{
if (!$this->entitiesToIdsTransformer) {
$this->entitiesToIdsTransformer =
- $this->getMockBuilder('Oro\Bundle\UIBundle\Form\DataTransformer\EntitiesToIdsTransformer')
+ $this->getMockBuilder('Oro\Bundle\FormBundle\Form\DataTransformer\EntitiesToIdsTransformer')
->disableOriginalConstructor()
->setMethods(array('transform', 'reverseTransform'))
->getMockForAbstractClass();
diff --git a/src/Oro/Bundle/FormBundle/Tests/Unit/Form/Type/OroJquerySelect2HiddenTypeTest.php b/src/Oro/Bundle/FormBundle/Tests/Unit/Form/Type/OroJquerySelect2HiddenTypeTest.php
new file mode 100644
index 00000000000..61fd28773d6
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Tests/Unit/Form/Type/OroJquerySelect2HiddenTypeTest.php
@@ -0,0 +1,404 @@
+type = $this->getMockBuilder('Oro\Bundle\FormBundle\Form\Type\OroJquerySelect2HiddenType')
+ ->setMethods(array('createDefaultTransformer'))
+ ->setConstructorArgs(array($this->getMockEntityManager(), $this->getMockSearchRegistry()))
+ ->getMock();
+ /*$this->type->expects($this->any())->method('createDefaultTransformer')
+ ->will($this->returnValue($this->getMockEntityToIdTransformer()));*/
+ }
+
+ protected function getExtensions()
+ {
+ return array_merge(parent::getExtensions(), array(new TestFormExtension()));
+ }
+
+ /**
+ * @dataProvider bindDataProvider
+ * @param mixed $bindData
+ * @param mixed $formData
+ * @param mixed $viewData
+ * @param array $options
+ * @param array $expectedCalls
+ * @param array $expectedVars
+ */
+ public function testBindData(
+ $bindData,
+ $formData,
+ $viewData,
+ array $options,
+ array $expectedCalls,
+ array $expectedVars
+ ) {
+ if (isset($options['converter'])
+ && is_string($options['converter'])
+ && method_exists($this, $options['converter'])
+ ) {
+ $options['converter'] = $this->$options['converter']();
+ }
+
+ foreach ($expectedCalls as $key => $calls) {
+ $mock = $this->{'getMock' . ucfirst($key)}();
+ MockHelper::addMockExpectedCalls($mock, $calls, $this);
+ }
+
+ $form = $this->factory->create($this->type, null, $options);
+
+ $form->bind($bindData);
+
+ $this->assertTrue($form->isSynchronized());
+ $this->assertEquals($formData, $form->getData());
+
+ $view = $form->createView();
+ $this->assertEquals($viewData, $view->vars['value']);
+
+ foreach ($expectedVars as $name => $expectedValue) {
+ $this->assertEquals($expectedValue, $view->vars[$name]);
+ }
+ }
+
+
+ /**
+ * Data provider for testBindData
+ *
+ * @return array
+ * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+ */
+ public function bindDataProvider()
+ {
+ $entityId1 = $this->createMockEntity('id', 1);
+ return array(
+ 'use autocomplete_alias' => array(
+ '1',
+ $entityId1,
+ '1',
+ array('autocomplete_alias' => 'foo'),
+ 'expectedCalls' => array(
+ 'searchRegistry' => array(
+ array('getSearchHandler', array('foo'), 'getMockSearchHandler'),
+ array('getSearchHandler', array('foo'), 'getMockSearchHandler'),
+ array('getSearchHandler', array('foo'), 'getMockSearchHandler')
+ ),
+ 'searchHandler' => array(
+ array('getProperties', array(), array('bar', 'baz')),
+ array('getEntityName', array(), 'TestEntityClass'),
+ array(
+ 'convertItem',
+ array($entityId1),
+ array('id' => 1, 'bar' => 'Bar value', 'baz' => 'Baz value')
+ ),
+ ),
+ 'formType' => array(
+ array('createDefaultTransformer', array('TestEntityClass'), 'getMockEntityToIdTransformer')
+ ),
+ 'entityToIdTransformer' => array(
+ array('transform', array(null), null),
+ array('reverseTransform', array('1'), $entityId1)
+ )
+ ),
+ 'expectedVars' => array(
+ 'configs' => array(
+ 'placeholder' => 'oro.form.choose_value',
+ 'allowClear' => 1,
+ 'minimumInputLength' => 1,
+ 'autocomplete_alias' => 'foo',
+ 'properties' => array('bar', 'baz'),
+ 'route_name' => 'oro_form_autocomplete_search',
+ 'extra_config' => 'autocomplete'
+ ),
+ 'attr' => array(
+ 'data-entity' => json_encode(array('id' => 1, 'bar' => 'Bar value', 'baz' => 'Baz value'))
+ )
+ )
+ ),
+ 'without autocomplete_alias' => array(
+ '1',
+ $entityId1,
+ '1',
+ array(
+ 'configs' => array(
+ 'route_name' => 'custom_route'
+ ),
+ 'converter' => 'getMockConverter',
+ 'entity_class' => 'TestEntityClass'
+ ),
+ 'expectedCalls' => array(
+ 'converter' => array(
+ array(
+ 'convertItem',
+ array($entityId1),
+ array('id' => 1, 'bar' => 'Bar value', 'baz' => 'Baz value')
+ ),
+ ),
+ 'formType' => array(
+ array('createDefaultTransformer', array('TestEntityClass'), 'getMockEntityToIdTransformer')
+ ),
+ 'entityToIdTransformer' => array(
+ array('transform', array(null), null),
+ array('reverseTransform', array('1'), $entityId1)
+ )
+ ),
+ 'expectedVars' => array(
+ 'configs' => array(
+ 'placeholder' => 'oro.form.choose_value',
+ 'allowClear' => 1,
+ 'minimumInputLength' => 1,
+ 'route_name' => 'custom_route'
+ ),
+ 'attr' => array(
+ 'data-entity' => json_encode(array('id' => 1, 'bar' => 'Bar value', 'baz' => 'Baz value'))
+ )
+ )
+ )
+ );
+ }
+
+ /**
+ * @dataProvider createErrorsDataProvider
+ * @param array $options
+ * @param array $expectedCalls
+ * @param string $expectedException
+ * @param string $expectedExceptionMessage
+ */
+ public function testCreateErrors(
+ array $options,
+ array $expectedCalls,
+ $expectedException,
+ $expectedExceptionMessage
+ ) {
+ if (isset($options['converter'])
+ && is_string($options['converter'])
+ && method_exists($this, $options['converter'])
+ ) {
+ $options['converter'] = $this->$options['converter']();
+ }
+
+ foreach ($expectedCalls as $key => $calls) {
+ $mock = $this->{'getMock' . ucfirst($key)}();
+ MockHelper::addMockExpectedCalls($mock, $calls, $this);
+ }
+
+ $this->setExpectedException($expectedException, $expectedExceptionMessage);
+ $this->factory->create($this->type, null, $options);
+ }
+
+ /**
+ * Data provider for testBindData
+ *
+ * @return array
+ */
+ public function createErrorsDataProvider()
+ {
+ return array(
+ 'configs.route_name or configs.ajax.url must be set' => array(
+ array(),
+ 'expectedCalls' => array(),
+ 'expectedException' => 'Symfony\Component\Form\Exception\FormException',
+ 'expectedExceptionMessage' => 'Either option "configs.route_name" or "configs.ajax.url" must be set.'
+ ),
+ 'converter must be set' => array(
+ array(
+ 'configs' => array(
+ 'route_name' => 'foo'
+ )
+ ),
+ 'expectedCalls' => array(),
+ 'expectedException' => 'Symfony\Component\Form\Exception\FormException',
+ 'expectedExceptionMessage' => 'The option "converter" must be set.'
+ ),
+ 'converter invalid' => array(
+ array(
+ 'converter' => 'bar',
+ 'configs' => array(
+ 'route_name' => 'foo'
+ )
+ ),
+ 'expectedCalls' => array(),
+ 'expectedException' => 'Symfony\Component\Form\Exception\FormException',
+ 'expectedExceptionMessage' =>
+ sprintf(
+ 'The option "converter" must be an instance of "%s".',
+ 'Oro\Bundle\FormBundle\Autocomplete\ConverterInterface'
+ )
+ ),
+ 'entity_class must be set' => array(
+ array(
+ 'converter' => 'getMockConverter',
+ 'configs' => array(
+ 'route_name' => 'foo'
+ )
+ ),
+ 'expectedCalls' => array(),
+ 'expectedException' => 'Symfony\Component\Form\Exception\FormException',
+ 'expectedExceptionMessage' => 'The option "entity_class" must be set.'
+ ),
+ 'entity_class must be set2' => array(
+ array(
+ 'converter' => 'getMockConverter',
+ 'entity_class' => 'bar',
+ 'configs' => array(
+ 'route_name' => 'foo'
+ ),
+ 'transformer' => 'invalid'
+ ),
+ 'expectedCalls' => array(),
+ 'expectedException' => 'Symfony\Component\Form\Exception\FormException',
+ 'expectedExceptionMessage' =>
+ sprintf(
+ 'The option "transformer" must be an instance of "%s".',
+ 'Symfony\Component\Form\DataTransformerInterface'
+ )
+ )
+ );
+ }
+
+ /**
+ * Create mock entity by id property name and value
+ *
+ * @param string $property
+ * @param mixed $value
+ * @return \PHPUnit_Framework_MockObject_MockObject
+ */
+ private function createMockEntity($property, $value)
+ {
+ $getter = 'get' . ucfirst($property);
+ $result = $this->getMock('MockEntity', array($getter));
+ $result->expects($this->any())->method($getter)->will($this->returnValue($value));
+ return $result;
+ }
+
+ /**
+ * @return EntityManager|\PHPUnit_Framework_MockObject_MockObject
+ */
+ public function getMockEntityManager()
+ {
+ if (!$this->entityManager) {
+ $this->entityManager = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getClassMetadata', 'getRepository'))
+ ->getMockForAbstractClass();
+ }
+
+ return $this->entityManager;
+ }
+
+ /**
+ * @return SearchRegistry|\PHPUnit_Framework_MockObject_MockObject
+ */
+ public function getMockSearchRegistry()
+ {
+ if (!$this->searchRegistry) {
+ $this->searchRegistry = $this->getMockBuilder('Oro\Bundle\FormBundle\Autocomplete\SearchRegistry')
+ ->disableOriginalConstructor()
+ ->setMethods(array('hasSearchHandler', 'getSearchHandler'))
+ ->getMock();
+ }
+
+ return $this->searchRegistry;
+ }
+
+ /**
+ * @return ConverterInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ public function getMockConverter()
+ {
+ if (!$this->converter) {
+ $this->converter = $this->getMock('Oro\Bundle\FormBundle\Autocomplete\ConverterInterface');
+ }
+
+ return $this->converter;
+ }
+
+ /**
+ * @return \PHPUnit_Framework_MockObject_MockObject
+ */
+ public function getMockFormType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @return SearchHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ public function getMockSearchHandler()
+ {
+ if (!$this->searchHandler) {
+ $this->searchHandler = $this->getMock('Oro\Bundle\FormBundle\Autocomplete\SearchHandlerInterface');
+ }
+
+ return $this->searchHandler;
+ }
+
+ /**
+ * @return EntityToIdTransformer|\PHPUnit_Framework_MockObject_MockObject
+ */
+ public function getMockEntityToIdTransformer()
+ {
+ if (!$this->entityToIdTransformer) {
+ $this->entityToIdTransformer =
+ $this->getMockBuilder('Oro\Bundle\FormBundle\Form\DataTransformer\EntityToIdTransformer')
+ ->disableOriginalConstructor()
+ ->setMethods(array('transform', 'reverseTransform'))
+ ->getMockForAbstractClass();
+ }
+ return $this->entityToIdTransformer;
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/Tests/Unit/Form/Type/Stub/TestEntity.php b/src/Oro/Bundle/FormBundle/Tests/Unit/Form/Type/Stub/TestEntity.php
new file mode 100644
index 00000000000..3d47c582164
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Tests/Unit/Form/Type/Stub/TestEntity.php
@@ -0,0 +1,26 @@
+testId = $id;
+ $this->testProperty = $property;
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/Tests/Unit/Form/Type/TestFormExtension.php b/src/Oro/Bundle/FormBundle/Tests/Unit/Form/Type/TestFormExtension.php
new file mode 100644
index 00000000000..860ac541093
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Tests/Unit/Form/Type/TestFormExtension.php
@@ -0,0 +1,17 @@
+classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadataInfo')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getSingleIdentifierFieldName'))
+ ->getMock();
+ $this->classMetadata->expects($this->any())
+ ->method('getSingleIdentifierFieldName')
+ ->will($this->returnValue(self::TEST_IDENTIFIER));
+
+ $this->entityManager = $this->getMockBuilder('Doctrine\ORM\EntityManager')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getClassMetadata'))
+ ->getMock();
+ $this->entityManager->expects($this->any())
+ ->method('getClassMetadata')
+ ->with(self::TEST_CLASS)
+ ->will($this->returnValue($this->classMetadata));
+
+ $this->registry = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry')
+ ->disableOriginalConstructor()
+ ->setMethods('getManager', 'getRepository')
+ ->getMockForAbstractClass();
+ $this->registry->expects($this->any())
+ ->method('getManager')
+ ->will($this->returnValue($this->entityManager));
+ $this->registry->expects($this->any())
+ ->method('getRepository')
+ ->with(self::TEST_CLASS)
+ ->will($this->returnValue($this->getEntityRepository()));
+
+ $this->type = new TranslatableEntityType($this->registry);
+ }
+
+ protected function tearDown()
+ {
+ unset($this->classMetadata);
+ unset($this->entityManager);
+ unset($this->registry);
+ unset($this->entityRepository);
+ unset($this->queryBuilder);
+ unset($this->type);
+ }
+
+ public function testGetName()
+ {
+ $this->assertEquals(TranslatableEntityType::NAME, $this->type->getName());
+ }
+
+ public function testGetParent()
+ {
+ $this->assertEquals('choice', $this->type->getParent());
+ }
+
+ /**
+ * @return QueryBuilder
+ */
+ public function getQueryBuilder()
+ {
+ $testChoiceEntities = $this->getTestChoiceEntities($this->testChoices);
+
+ if (!$this->queryBuilder) {
+ $query = $this->getMockBuilder('Doctrine\ORM\AbstractQuery')
+ ->disableOriginalConstructor()
+ ->setMethods(array('execute', 'setHint'))
+ ->getMockForAbstractClass();
+ $query->expects($this->any())
+ ->method('execute')
+ ->will($this->returnValue($testChoiceEntities));
+
+ $this->queryBuilder = $this->getMockBuilder('Doctrine\ORM\QueryBuilder')
+ ->disableOriginalConstructor()
+ ->setMethods(array('getQuery'))
+ ->getMock();
+ $this->queryBuilder->expects($this->any())
+ ->method('getQuery')
+ ->will($this->returnValue($query));
+ }
+
+ return $this->queryBuilder;
+ }
+
+ /**
+ * @return EntityRepository
+ */
+ public function getEntityRepository()
+ {
+ if (!$this->entityRepository) {
+ $this->entityRepository = $this->getMockBuilder('Doctrine\ORM\EntityRepository')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->entityRepository->expects($this->any())
+ ->method('createQueryBuilder')
+ ->with('e')
+ ->will($this->returnValue($this->getQueryBuilder()));
+ }
+
+ return $this->entityRepository;
+ }
+
+ /**
+ * @param array $choices
+ * @return array
+ */
+ protected function getTestChoiceEntities($choices)
+ {
+ foreach ($choices as $key => $value) {
+ $entity = new TestEntity($key, $value);
+ $choices[$key] = $entity;
+ }
+
+ return $choices;
+ }
+
+ /**
+ * @param array $options
+ * @param string $transformerClass
+ *
+ * @dataProvider buildFormDataProvider
+ */
+ public function testBuildForm($options, $transformerClass)
+ {
+ // mock
+ $formBuilder = $this->getMockBuilder('Symfony\Component\Form\FormBuilder')
+ ->disableOriginalConstructor()
+ ->setMethods(array('resetViewTransformers'))
+ ->getMock();
+ $formBuilder->expects($this->at(0))
+ ->method('resetViewTransformers');
+
+ // test
+ $this->type->buildForm($formBuilder, $options);
+
+ // assertions
+ /** @var $formBuilder FormBuilderInterface */
+ $transformers = $formBuilder->getViewTransformers();
+ $this->assertCount(1, $transformers);
+
+ $transformer = current($transformers);
+ $this->assertInstanceOf($transformerClass, $transformer);
+
+ $this->assertAttributeEquals($this->entityManager, 'em', $transformer);
+ $this->assertAttributeEquals(self::TEST_CLASS, 'className', $transformer);
+ $this->assertAttributeEquals(self::TEST_IDENTIFIER, 'property', $transformer);
+ }
+
+ /**
+ * @return array
+ */
+ public function buildFormDataProvider()
+ {
+ return array(
+ 'single' => array(
+ 'options' => array('class' => self::TEST_CLASS),
+ 'transformerClass' => 'Oro\Bundle\FormBundle\Form\DataTransformer\EntityToIdTransformer'
+ ),
+ 'multiple' => array(
+ 'options' => array('class' => self::TEST_CLASS, 'multiple' => true),
+ 'transformerClass' => 'Oro\Bundle\FormBundle\Form\DataTransformer\EntitiesToIdsTransformer'
+ ),
+ );
+ }
+
+ /**
+ * @param array $choiceListOptions
+ * @param array $expectedChoices
+ * @param boolean $expectSetHint
+ *
+ * @dataProvider setDefaultOptionsDataProvider
+ */
+ public function testSetDefaultOptions(array $choiceListOptions, array $expectedChoices, $expectSetHint = false)
+ {
+ $test = $this;
+
+ // prepare query builder option
+ if (isset($choiceListOptions['query_builder'])) {
+ $choiceListOptions['query_builder'] = $this->getQueryBuilderOption($choiceListOptions);
+ }
+
+ // expectations for option resolver
+ $expectedRequiredOptions = array('class');
+
+ $optionsResolver = $this->getMockBuilder('Symfony\Component\OptionsResolver\OptionsResolverInterface')
+ ->disableOriginalConstructor()
+ ->setMethods(array('setRequired', 'setDefaults'))
+ ->getMockForAbstractClass();
+ $optionsResolver->expects($this->once())
+ ->method('setRequired')
+ ->with($expectedRequiredOptions);
+ $optionsResolver->expects($this->once())
+ ->method('setDefaults')
+ ->will(
+ $this->returnCallback(
+ function ($options) use ($test, $choiceListOptions, $expectedChoices) {
+ $test->assertNull($options['property']);
+ $test->assertNull($options['query_builder']);
+ $test->assertNull($options['choices']);
+ $test->assertInstanceOf('\Closure', $options['choice_list']);
+
+ $test->assertChoiceList($options['choice_list'], $choiceListOptions, $expectedChoices);
+ }
+ )
+ );
+
+ // expectation for translation walker hint
+ if ($expectSetHint) {
+ /** @var $query \PHPUnit_Framework_MockObject_MockObject */
+ $query = $this->getQueryBuilder()->getQuery();
+ $query->expects($this->once())
+ ->method('setHint')
+ ->with(
+ Query::HINT_CUSTOM_OUTPUT_WALKER,
+ 'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
+ );
+ }
+
+ // test
+ $this->type->setDefaultOptions($optionsResolver);
+ }
+
+ /**
+ * @param array $options
+ * @return callable|QueryBuilder
+ */
+ protected function getQueryBuilderOption(array $options)
+ {
+ if (empty($options['query_builder'])) {
+ return null;
+ }
+
+ $test = $this;
+
+ switch ($options['query_builder']) {
+ case 'closure':
+ return function (EntityRepository $entityRepository) use ($test) {
+ $test->assertEquals($test->getEntityRepository(), $entityRepository);
+ return $test->getQueryBuilder();
+ };
+ case 'object':
+ default:
+ return $this->getQueryBuilder();
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function setDefaultOptionsDataProvider()
+ {
+ $testChoiceEntities = $this->getTestChoiceEntities($this->testChoices);
+
+ return array(
+ 'predefined_choices' => array(
+ 'choiceListOptions' => array(
+ 'class' => self::TEST_CLASS,
+ 'property' => self::TEST_PROPERTY,
+ 'choices' => $testChoiceEntities
+ ),
+ 'expectedChoices' => $testChoiceEntities
+ ),
+ 'all_choices' => array(
+ 'choiceListOptions' => array(
+ 'class' => self::TEST_CLASS,
+ 'property' => self::TEST_PROPERTY,
+ 'choices' => null
+ ),
+ 'expectedChoices' => $testChoiceEntities,
+ 'expectSetHint' => true,
+ ),
+ 'query_builder' => array(
+ 'choiceListOptions' => array(
+ 'class' => self::TEST_CLASS,
+ 'property' => self::TEST_PROPERTY,
+ 'choices' => null,
+ 'query_builder' => 'object'
+ ),
+ 'expectedChoices' => $testChoiceEntities,
+ 'expectSetHint' => true,
+ ),
+ 'query_builder_callback' => array(
+ 'choiceListOptions' => array(
+ 'class' => self::TEST_CLASS,
+ 'property' => self::TEST_PROPERTY,
+ 'choices' => null,
+ 'query_builder' => 'closure'
+ ),
+ 'expectedChoices' => $testChoiceEntities,
+ 'expectSetHint' => true,
+ ),
+ );
+ }
+
+ /**
+ * @param callback $choiceList
+ * @param array $options
+ * @param array $expectedChoices
+ */
+ public function assertChoiceList($choiceList, $options, $expectedChoices)
+ {
+ /** @var $objectChoiceList ObjectChoiceList */
+ $objectChoiceList = $choiceList($this->getResolverOptions($options));
+
+ $this->assertInstanceOf('Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList', $objectChoiceList);
+ $this->assertEquals($expectedChoices, $objectChoiceList->getChoices());
+ }
+
+ /**
+ * @param array $options
+ * @return Options
+ */
+ protected function getResolverOptions($options)
+ {
+ $resolverOptions = new Options();
+ foreach ($options as $key => $value) {
+ $resolverOptions->set($key, $value);
+ }
+
+ return $resolverOptions;
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/Tests/Unit/MockHelper.php b/src/Oro/Bundle/FormBundle/Tests/Unit/MockHelper.php
new file mode 100644
index 00000000000..10d84153780
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/Tests/Unit/MockHelper.php
@@ -0,0 +1,33 @@
+expects(\PHPUnit_Framework_TestCase::at($index++))->method($method);
+ $methodExpectation = call_user_func_array(array($methodExpectation, 'with'), $arguments);
+ if (is_string($result) && $callbacksContext && method_exists($callbacksContext, $result)) {
+ $result = $callbacksContext->$result();
+ }
+ $methodExpectation->will(\PHPUnit_Framework_TestCase::returnValue($result));
+ }
+ } else {
+ $mock->expects(\PHPUnit_Framework_TestCase::never())->method(\PHPUnit_Framework_TestCase::anything());
+ }
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/bootstrap.php b/src/Oro/Bundle/FormBundle/bootstrap.php
new file mode 100644
index 00000000000..fd52fe63a9a
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/bootstrap.php
@@ -0,0 +1,14 @@
+=5.3.3",
+ "symfony/symfony": ">=2.1",
+ "genemu/form-bundle": "2.1.*",
+ "oro/search-bundle": "dev-master",
+ "oro/user-bundle": "dev-master"
+ },
+ "autoload": {
+ "psr-0": { "Oro\\Bundle\\FormBundle": "" }
+ },
+ "target-dir": "Oro/Bundle/FormBundle",
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ }
+}
diff --git a/src/Oro/Bundle/FormBundle/phpunit.xml.dist b/src/Oro/Bundle/FormBundle/phpunit.xml.dist
new file mode 100644
index 00000000000..ed8987c8a21
--- /dev/null
+++ b/src/Oro/Bundle/FormBundle/phpunit.xml.dist
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+ ./Tests
+
+
+
+
+
+
+ ./
+
+ ./Resources
+ ./Tests
+ ./vendor
+
+
+
+
diff --git a/src/Oro/Bundle/GridBundle/Datagrid/Datagrid.php b/src/Oro/Bundle/GridBundle/Datagrid/Datagrid.php
index 4eb43e01489..587edac3870 100644
--- a/src/Oro/Bundle/GridBundle/Datagrid/Datagrid.php
+++ b/src/Oro/Bundle/GridBundle/Datagrid/Datagrid.php
@@ -52,6 +52,13 @@ class Datagrid implements DatagridInterface
*/
protected $parametersApplied = false;
+ /**
+ * Pager applied flag
+ *
+ * @var bool
+ */
+ protected $pagerApplied = false;
+
/**
* @var RouteGeneratorInterface
*/
@@ -320,10 +327,16 @@ protected function applySorters()
*/
protected function applyPager()
{
+ if ($this->pagerApplied) {
+ return;
+ }
+
$pagerParameters = $this->parameters->get(ParametersInterface::PAGER_PARAMETERS);
$this->pager->setPage(isset($pagerParameters['_page']) ? $pagerParameters['_page'] : 1);
$this->pager->setMaxPerPage(!empty($pagerParameters['_per_page']) ? $pagerParameters['_per_page'] : 10);
$this->pager->init();
+
+ $this->pagerApplied = true;
}
/**
diff --git a/src/Oro/Bundle/GridBundle/Datagrid/DatagridManager.php b/src/Oro/Bundle/GridBundle/Datagrid/DatagridManager.php
index 010d4371142..60c80471d13 100644
--- a/src/Oro/Bundle/GridBundle/Datagrid/DatagridManager.php
+++ b/src/Oro/Bundle/GridBundle/Datagrid/DatagridManager.php
@@ -37,6 +37,11 @@ abstract class DatagridManager implements DatagridManagerInterface
*/
protected $translator;
+ /**
+ * @var string
+ */
+ protected $translationDomain;
+
/**
* @var ValidatorInterface
*/
@@ -104,6 +109,14 @@ public function setTranslator(TranslatorInterface $translator)
$this->translator = $translator;
}
+ /**
+ * {@inheritDoc}
+ */
+ public function setTranslationDomain($translationDomain)
+ {
+ $this->translationDomain = $translationDomain;
+ }
+
/**
* {@inheritDoc}
*/
@@ -217,7 +230,16 @@ public function getDatagrid()
*/
protected function createQuery()
{
- return $this->queryFactory->createQuery();
+ $query = $this->queryFactory->createQuery();
+ $this->prepareQuery($query);
+ return $query;
+ }
+
+ /**
+ * @param ProxyQueryInterface $query
+ */
+ protected function prepareQuery(ProxyQueryInterface $query)
+ {
}
/**
@@ -259,7 +281,6 @@ protected function getFieldDescriptionCollection()
*/
protected function configureFields(FieldDescriptionCollection $fieldCollection)
{
-
}
/**
@@ -385,4 +406,19 @@ protected function getDefaultPager()
{
return array();
}
+
+ /**
+ * @param string $id
+ * @param array $parameters
+ * @param string $domain
+ * @return string
+ */
+ protected function translate($id, array $parameters = array(), $domain = null)
+ {
+ if (!$domain) {
+ $domain = $this->translationDomain;
+ }
+
+ return $this->translator->trans($id, $parameters, $domain);
+ }
}
diff --git a/src/Oro/Bundle/GridBundle/Datagrid/DatagridManagerInterface.php b/src/Oro/Bundle/GridBundle/Datagrid/DatagridManagerInterface.php
index 194eadede72..98a2e17efde 100644
--- a/src/Oro/Bundle/GridBundle/Datagrid/DatagridManagerInterface.php
+++ b/src/Oro/Bundle/GridBundle/Datagrid/DatagridManagerInterface.php
@@ -59,6 +59,12 @@ public function setQueryFactory(QueryFactoryInterface $queryManager);
*/
public function setTranslator(TranslatorInterface $translator);
+ /**
+ * @param string $translationDomain
+ * @return void
+ */
+ public function setTranslationDomain($translationDomain);
+
/**
* @param ValidatorInterface $validator
* @return void
diff --git a/src/Oro/Bundle/GridBundle/Datagrid/FlexibleDatagridManager.php b/src/Oro/Bundle/GridBundle/Datagrid/FlexibleDatagridManager.php
index 06db3e24295..374f6a4881d 100644
--- a/src/Oro/Bundle/GridBundle/Datagrid/FlexibleDatagridManager.php
+++ b/src/Oro/Bundle/GridBundle/Datagrid/FlexibleDatagridManager.php
@@ -39,6 +39,10 @@ abstract class FlexibleDatagridManager extends DatagridManager
'field' => FieldDescriptionInterface::TYPE_DECIMAL,
'filter' => FilterInterface::TYPE_FLEXIBLE_NUMBER,
),
+ AbstractAttributeType::BACKEND_TYPE_BOOLEAN => array(
+ 'field' => FieldDescriptionInterface::TYPE_BOOLEAN,
+ 'filter' => FilterInterface::TYPE_FLEXIBLE_BOOLEAN,
+ ),
AbstractAttributeType::BACKEND_TYPE_INTEGER => array(
'field' => FieldDescriptionInterface::TYPE_INTEGER,
'filter' => FilterInterface::TYPE_FLEXIBLE_NUMBER,
@@ -76,9 +80,8 @@ public function setFlexibleManager(FlexibleManager $flexibleManager)
{
$this->flexibleManager = $flexibleManager;
- // TODO: somehow get locale and scope from parameters interface
- $this->flexibleManager->setLocale('en_US');
- $this->flexibleManager->setScope('ecommerce');
+ $this->flexibleManager->setLocale($this->parameters->getLocale());
+ $this->flexibleManager->setScope($this->parameters->getScope());
}
/**
@@ -112,12 +115,14 @@ protected function configureFlexibleField(
$attributeCode,
array $options = array()
) {
- $fieldsCollection->add(
- $this->createFlexibleField(
- $this->getFlexibleAttribute($attributeCode),
- $options
- )
- );
+ if ($this->hasFlexibleAttribute($attributeCode)) {
+ $fieldsCollection->add(
+ $this->createFlexibleField(
+ $this->getFlexibleAttribute($attributeCode),
+ $options
+ )
+ );
+ }
}
/**
@@ -192,7 +197,7 @@ protected function getFlexibleAttributes()
}
/**
- * @param $code
+ * @param string $code
* @return AbstractAttribute
* @throws \LogicException
*/
@@ -206,6 +211,17 @@ protected function getFlexibleAttribute($code)
return $attributes[$code];
}
+ /**
+ * @param string $code
+ * @return boolean
+ */
+ protected function hasFlexibleAttribute($code)
+ {
+ $attributes = $this->getFlexibleAttributes();
+
+ return isset($attributes[$code]);
+ }
+
/**
* @param $flexibleFieldType
* @return string
diff --git a/src/Oro/Bundle/GridBundle/Datagrid/ORM/ProxyQuery.php b/src/Oro/Bundle/GridBundle/Datagrid/ORM/ProxyQuery.php
index ad2d46bbfd2..b79be51cbef 100644
--- a/src/Oro/Bundle/GridBundle/Datagrid/ORM/ProxyQuery.php
+++ b/src/Oro/Bundle/GridBundle/Datagrid/ORM/ProxyQuery.php
@@ -4,11 +4,16 @@
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Query;
+use Doctrine\ORM\AbstractQuery;
use Sonata\DoctrineORMAdminBundle\Datagrid\ProxyQuery as BaseProxyQuery;
use Oro\Bundle\GridBundle\Datagrid\ProxyQueryInterface;
+/**
+ * @SuppressWarnings(PHPMD)
+ * TODO: This class should be refactored (BAP-969).
+ */
class ProxyQuery extends BaseProxyQuery implements ProxyQueryInterface
{
/**
@@ -36,6 +41,11 @@ class ProxyQuery extends BaseProxyQuery implements ProxyQueryInterface
*/
protected $selectWhitelist = array();
+ /**
+ * @var array
+ */
+ protected $queryHints = array();
+
/**
* Get query builder
*
@@ -58,7 +68,9 @@ public function getTotalCount()
$qb->setMaxResults(null);
$qb->resetDQLPart('orderBy');
- $ids = $qb->getQuery()->execute();
+ $query = $qb->getQuery();
+ $this->applyQueryHints($query);
+ $ids = $query->execute();
return count($ids);
}
@@ -69,6 +81,7 @@ public function getTotalCount()
public function execute(array $params = array(), $hydrationMode = null)
{
$query = $this->getResultQueryBuilder()->getQuery();
+ $this->applyQueryHints($query);
return $query->execute($params, $hydrationMode);
}
@@ -202,6 +215,7 @@ protected function getResultIds()
$idx = array();
$query = $this->getResultIdsQueryBuilder()->getQuery();
+ $this->applyQueryHints($query);
$results = $query->execute(array(), Query::HYDRATE_ARRAY);
$connection = $this->getQueryBuilder()->getEntityManager()->getConnection();
@@ -306,7 +320,7 @@ public function entityJoin(array $associationMappings)
*
* @return string
*/
- protected function getRootAlias()
+ public function getRootAlias()
{
if (!$this->rootAlias) {
$this->rootAlias = current($this->getQueryBuilder()->getRootAliases());
@@ -408,9 +422,36 @@ public function addSelect($select = null, $addToWhitelist = false)
*
* @param string $name
* @param mixed $value
+ * @return ProxyQuery
*/
public function setParameter($name, $value)
{
$this->getQueryBuilder()->setParameter($name, $value);
+
+ return $this;
+ }
+
+ /**
+ * Sets a query hint
+ *
+ * @param string $name
+ * @param mixed $value
+ * @return ProxyQuery
+ */
+ public function setQueryHint($name, $value)
+ {
+ $this->queryHints[$name] = $value;
+
+ return $this;
+ }
+
+ /**
+ * @param AbstractQuery $query
+ */
+ protected function applyQueryHints(AbstractQuery $query)
+ {
+ foreach ($this->queryHints as $name => $value) {
+ $query->setHint($name, $value);
+ }
}
}
diff --git a/src/Oro/Bundle/GridBundle/Datagrid/ORM/QueryFactory/AbstractQueryFactory.php b/src/Oro/Bundle/GridBundle/Datagrid/ORM/QueryFactory/AbstractQueryFactory.php
index 493f957fad9..9d1b8d5cd9c 100644
--- a/src/Oro/Bundle/GridBundle/Datagrid/ORM/QueryFactory/AbstractQueryFactory.php
+++ b/src/Oro/Bundle/GridBundle/Datagrid/ORM/QueryFactory/AbstractQueryFactory.php
@@ -14,9 +14,9 @@ abstract class AbstractQueryFactory implements QueryFactoryInterface
*/
protected $queryBuilder;
-
/**
* @return ProxyQueryInterface
+ * @throws \LogicException
*/
public function createQuery()
{
diff --git a/src/Oro/Bundle/GridBundle/Datagrid/ParametersInterface.php b/src/Oro/Bundle/GridBundle/Datagrid/ParametersInterface.php
index 0f25cb2f61c..9c7028fb9db 100644
--- a/src/Oro/Bundle/GridBundle/Datagrid/ParametersInterface.php
+++ b/src/Oro/Bundle/GridBundle/Datagrid/ParametersInterface.php
@@ -8,6 +8,7 @@ interface ParametersInterface
const SORT_PARAMETERS = '_sort_by';
const PAGER_PARAMETERS = '_pager';
const ADDITIONAL_PARAMETERS = '_parameters';
+ const SCOPE_PARAMETER = '_scope';
/**
* Get parameter value from parameters container
@@ -29,4 +30,14 @@ public function set($type, $value);
* @return array
*/
public function toArray();
+
+ /**
+ * @return string
+ */
+ public function getLocale();
+
+ /**
+ * @return string
+ */
+ public function getScope();
}
diff --git a/src/Oro/Bundle/GridBundle/Datagrid/ProxyQueryInterface.php b/src/Oro/Bundle/GridBundle/Datagrid/ProxyQueryInterface.php
index c9506137e00..41dd3f0f5d9 100644
--- a/src/Oro/Bundle/GridBundle/Datagrid/ProxyQueryInterface.php
+++ b/src/Oro/Bundle/GridBundle/Datagrid/ProxyQueryInterface.php
@@ -39,6 +39,23 @@ public function addSelect($select = null, $addToWhitelist = false);
*
* @param string $name
* @param mixed $value
+ * @return ProxyQueryInterface
*/
public function setParameter($name, $value);
+
+ /**
+ * Gets the root alias of the query
+ *
+ * @return string
+ */
+ public function getRootAlias();
+
+ /**
+ * Sets a query hint
+ *
+ * @param string $name
+ * @param mixed $value
+ * @return ProxyQueryInterface
+ */
+ public function setQueryHint($name, $value);
}
diff --git a/src/Oro/Bundle/GridBundle/Datagrid/RequestParameters.php b/src/Oro/Bundle/GridBundle/Datagrid/RequestParameters.php
index 3ce83805b0e..048779e5ce1 100644
--- a/src/Oro/Bundle/GridBundle/Datagrid/RequestParameters.php
+++ b/src/Oro/Bundle/GridBundle/Datagrid/RequestParameters.php
@@ -109,4 +109,21 @@ public function toArray()
return $result;
}
+
+ /**
+ * @return string
+ */
+ public function getLocale()
+ {
+ return $this->getRequest()->getLocale();
+ }
+
+ /**
+ * @return string
+ */
+ public function getScope()
+ {
+ $rootValue = $this->getRootParameterValue();
+ return isset($rootValue[self::SCOPE_PARAMETER]) ? $rootValue[self::SCOPE_PARAMETER] : null;
+ }
}
diff --git a/src/Oro/Bundle/GridBundle/DependencyInjection/Compiler/AddDependencyCallsCompilerPass.php b/src/Oro/Bundle/GridBundle/DependencyInjection/Compiler/AddDependencyCallsCompilerPass.php
index c223969a8a1..bee9166b5b6 100644
--- a/src/Oro/Bundle/GridBundle/DependencyInjection/Compiler/AddDependencyCallsCompilerPass.php
+++ b/src/Oro/Bundle/GridBundle/DependencyInjection/Compiler/AddDependencyCallsCompilerPass.php
@@ -5,20 +5,25 @@
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
+use Oro\Bundle\GridBundle\DependencyInjection\OroGridExtension;
+
class AddDependencyCallsCompilerPass extends AbstractDatagridManagerCompilerPass
{
- const QUERY_FACTORY_ATTRIBUTE = 'query_factory';
- const ROUTE_GENERATOR_ATTRIBUTE = 'route_generator';
- const DATAGRID_BUILDER_ATTRIBUTE = 'datagrid_builder';
- const LIST_BUILDER_ATTRIBUTE = 'list_builder';
- const PARAMETERS_ATTRIBUTE = 'parameters';
- const TRANSLATOR_ATTRIBUTE = 'translator';
- const VALIDATOR_ATTRIBUTE = 'validator';
- const ROUTER_ATTRIBUTE = 'router';
+ const QUERY_FACTORY_ATTRIBUTE = 'query_factory';
+ const ROUTE_GENERATOR_ATTRIBUTE = 'route_generator';
+ const DATAGRID_BUILDER_ATTRIBUTE = 'datagrid_builder';
+ const LIST_BUILDER_ATTRIBUTE = 'list_builder';
+ const PARAMETERS_ATTRIBUTE = 'parameters';
+ const TRANSLATOR_ATTRIBUTE = 'translator';
+ const TRANSLATION_DOMAIN_ATTRIBUTE = 'translation_domain';
+ const VALIDATOR_ATTRIBUTE = 'validator';
+ const ROUTER_ATTRIBUTE = 'router';
+ const ENTITY_HINT_ATTRIBUTE = 'entity_hint';
/**
* {@inheritDoc}
@@ -34,7 +39,10 @@ public function processDatagrid()
*/
protected function applyConfigurationFromAttributes()
{
- $keys = array(
+ $this->definition->addMethodCall('setName', array($this->getMandatoryAttribute('datagrid_name')));
+
+ // add services
+ $serviceKeys = array(
self::QUERY_FACTORY_ATTRIBUTE,
self::ROUTE_GENERATOR_ATTRIBUTE,
self::DATAGRID_BUILDER_ATTRIBUTE,
@@ -45,7 +53,7 @@ protected function applyConfigurationFromAttributes()
self::ROUTER_ATTRIBUTE,
);
- foreach ($keys as $key) {
+ foreach ($serviceKeys as $key) {
$method = 'set' . $this->camelize($key);
if (!$this->hasAttribute($key) || $this->definition->hasMethodCall($method)) {
continue;
@@ -54,10 +62,19 @@ protected function applyConfigurationFromAttributes()
$this->definition->addMethodCall($method, array(new Reference($this->getAttribute($key))));
}
- $this->definition->addMethodCall('setName', array($this->getMandatoryAttribute('datagrid_name')));
+ // add other attributes
+ $attributeKeys = array(
+ self::ENTITY_HINT_ATTRIBUTE,
+ self::TRANSLATION_DOMAIN_ATTRIBUTE
+ );
+
+ foreach ($attributeKeys as $key) {
+ $method = 'set' . $this->camelize($key);
+ if (!$this->hasAttribute($key) || $this->definition->hasMethodCall($method)) {
+ continue;
+ }
- if ($this->hasAttribute('entity_hint')) {
- $this->definition->addMethodCall('setEntityHint', array($this->getAttribute('entity_hint')));
+ $this->definition->addMethodCall($method, array($this->getAttribute($key)));
}
}
@@ -68,6 +85,7 @@ protected function applyDefaults()
{
$this->definition->setScope(ContainerInterface::SCOPE_PROTOTYPE);
+ // add default services
$defaultAddServices = array(
self::QUERY_FACTORY_ATTRIBUTE => array($this, 'getDefaultQueryFactoryServiceId'),
self::ROUTE_GENERATOR_ATTRIBUTE => array($this, 'getDefaultRouteGeneratorServiceId'),
@@ -89,6 +107,19 @@ protected function applyDefaults()
$this->definition->addMethodCall($method, array(new Reference($serviceId)));
}
}
+
+ // add default parameters
+ $defaultAddParameters = array(
+ self::TRANSLATION_DOMAIN_ATTRIBUTE => OroGridExtension::PARAMETER_TRANSLATION_DOMAIN
+ );
+
+ foreach ($defaultAddParameters as $attribute => $parameterId) {
+ $method = 'set' . $this->camelize($attribute);
+
+ if (!$this->definition->hasMethodCall($method)) {
+ $this->definition->addMethodCall($method, array(new Parameter($parameterId)));
+ }
+ }
}
/**
diff --git a/src/Oro/Bundle/GridBundle/DependencyInjection/Configuration.php b/src/Oro/Bundle/GridBundle/DependencyInjection/Configuration.php
index 848cc1c6d68..e0b0e417db4 100644
--- a/src/Oro/Bundle/GridBundle/DependencyInjection/Configuration.php
+++ b/src/Oro/Bundle/GridBundle/DependencyInjection/Configuration.php
@@ -7,13 +7,23 @@
class Configuration implements ConfigurationInterface
{
+ const TRANSLATION_DOMAIN_NODE = 'translation_domain';
+ const DEFAULT_TRANSLATION_DOMAIN = 'datagrid';
+
/**
* {@inheritDoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
- $treeBuilder->root('oro_grid');
+ $rootNode = $treeBuilder->root('oro_grid');
+
+ $rootNode
+ ->children()
+ ->scalarNode(self::TRANSLATION_DOMAIN_NODE)
+ ->cannotBeEmpty()
+ ->defaultValue(self::DEFAULT_TRANSLATION_DOMAIN)
+ ->end();
return $treeBuilder;
}
diff --git a/src/Oro/Bundle/GridBundle/DependencyInjection/OroGridExtension.php b/src/Oro/Bundle/GridBundle/DependencyInjection/OroGridExtension.php
index 81291eb232c..6be455fe818 100644
--- a/src/Oro/Bundle/GridBundle/DependencyInjection/OroGridExtension.php
+++ b/src/Oro/Bundle/GridBundle/DependencyInjection/OroGridExtension.php
@@ -10,6 +10,8 @@
class OroGridExtension extends Extension
{
+ const PARAMETER_TRANSLATION_DOMAIN = 'oro_grid.translation.translation_domain';
+
/**
* {@inheritdoc}
*/
@@ -18,6 +20,8 @@ public function load(array $configs, ContainerBuilder $container)
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
+ $container->setParameter(self::PARAMETER_TRANSLATION_DOMAIN, $config[Configuration::TRANSLATION_DOMAIN_NODE]);
+
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
$loader->load('orm_filter_types.yml');
diff --git a/src/Oro/Bundle/GridBundle/Field/FieldDescription.php b/src/Oro/Bundle/GridBundle/Field/FieldDescription.php
index f125d9628da..5ac826dd3bb 100644
--- a/src/Oro/Bundle/GridBundle/Field/FieldDescription.php
+++ b/src/Oro/Bundle/GridBundle/Field/FieldDescription.php
@@ -138,8 +138,6 @@ public function setOptions(array $options)
// set the field_name if provided
if (isset($options['field_name'])) {
$this->setFieldName($options['field_name']);
- // TODO Cannot unset option because it is used by filter!
- //unset($options['field_name']);
}
// remove property value
@@ -153,7 +151,7 @@ public function setOptions(array $options)
$this->setFieldMapping($options['field_mapping']);
} else {
$fieldMapping = array(
- 'fieldName' => $this->getFieldName()
+ 'fieldName' => $this->getFieldName(),
);
if (isset($options['entity_alias'])) {
$fieldMapping['entityAlias'] = $options['entity_alias'];
@@ -161,6 +159,12 @@ public function setOptions(array $options)
if (isset($options['expression'])) {
$fieldMapping['fieldExpression'] = $options['expression'];
}
+ if (isset($options['filter_by_where'])) {
+ $fieldMapping['filterByWhere'] = $options['filter_by_where'];
+ }
+ if (isset($options['filter_by_having'])) {
+ $fieldMapping['filterByHaving'] = $options['filter_by_having'];
+ }
$this->setFieldMapping($fieldMapping);
$options['field_mapping'] = $fieldMapping;
}
diff --git a/src/Oro/Bundle/GridBundle/Filter/FilterInterface.php b/src/Oro/Bundle/GridBundle/Filter/FilterInterface.php
index 5d38ff3615d..c2cc47f9d28 100644
--- a/src/Oro/Bundle/GridBundle/Filter/FilterInterface.php
+++ b/src/Oro/Bundle/GridBundle/Filter/FilterInterface.php
@@ -15,9 +15,11 @@ interface FilterInterface extends BaseFilterInterface
const TYPE_STRING = 'oro_grid_orm_string';
const TYPE_CHOICE = 'oro_grid_orm_choice';
const TYPE_BOOLEAN = 'oro_grid_orm_boolean';
+ const TYPE_ENTITY = 'oro_grid_orm_entity';
const TYPE_FLEXIBLE_DATE = 'oro_grid_orm_flexible_date_range';
const TYPE_FLEXIBLE_DATETIME = 'oro_grid_orm_flexible_datetime_range';
const TYPE_FLEXIBLE_NUMBER = 'oro_grid_orm_flexible_number';
+ const TYPE_FLEXIBLE_BOOLEAN = 'oro_grid_orm_flexible_boolean';
const TYPE_FLEXIBLE_STRING = 'oro_grid_orm_flexible_string';
const TYPE_FLEXIBLE_OPTIONS = 'oro_grid_orm_flexible_options';
diff --git a/src/Oro/Bundle/GridBundle/Filter/ORM/AbstractFilter.php b/src/Oro/Bundle/GridBundle/Filter/ORM/AbstractFilter.php
index 04d52f29956..8ee35c43abf 100644
--- a/src/Oro/Bundle/GridBundle/Filter/ORM/AbstractFilter.php
+++ b/src/Oro/Bundle/GridBundle/Filter/ORM/AbstractFilter.php
@@ -76,7 +76,13 @@ protected function applyFilterToClause(ProxyQueryInterface $queryBuilder, $expre
protected function isApplyFilterToHavingClause()
{
$fieldMapping = $this->getFieldMapping();
- return !empty($fieldMapping['fieldExpression']);
+ if (!empty($fieldMapping['filterByHaving'])) {
+ return true;
+ } elseif (!empty($fieldMapping['filterByWhere'])) {
+ return false;
+ } else {
+ return !empty($fieldMapping['fieldExpression']);
+ }
}
/**
diff --git a/src/Oro/Bundle/GridBundle/Filter/ORM/ChoiceFilter.php b/src/Oro/Bundle/GridBundle/Filter/ORM/ChoiceFilter.php
index 75776a6b84f..5d992f75a8f 100644
--- a/src/Oro/Bundle/GridBundle/Filter/ORM/ChoiceFilter.php
+++ b/src/Oro/Bundle/GridBundle/Filter/ORM/ChoiceFilter.php
@@ -3,6 +3,8 @@
namespace Oro\Bundle\GridBundle\Filter\ORM;
use Doctrine\DBAL\Query\QueryBuilder;
+use Doctrine\Common\Collections\Collection;
+
use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
use Oro\Bundle\FilterBundle\Form\Type\Filter\ChoiceFilterType;
@@ -18,20 +20,24 @@ public function filter(ProxyQueryInterface $queryBuilder, $alias, $field, $data)
return;
}
- $operator = $this->getOperator($data['type']);
+ $operator = $this->getOperator($data['type']);
+ $parameter = $this->getName() . '_choices';
if ('IN' == $operator) {
$expression = $this->getExpressionFactory()->in(
$this->createFieldExpression($field, $alias),
- $data['value']
+ ':' . $parameter
);
} else {
$expression = $this->getExpressionFactory()->notIn(
$this->createFieldExpression($field, $alias),
- $data['value']
+ ':' . $parameter
);
}
+
$this->applyFilterToClause($queryBuilder, $expression);
+ /** @var $queryBuilder QueryBuilder */
+ $queryBuilder->setParameter($parameter, $data['value']);
}
/**
@@ -44,16 +50,22 @@ public function parseData($data)
|| !array_key_exists('value', $data)
|| $data['value'] === ''
|| is_null($data['value'])
- || (is_array($data['value']) && !count($data['value']))
+ || ((is_array($data['value']) || $data['value'] instanceof Collection) && !count($data['value']))
) {
return false;
}
- if (!is_array($data['value'])) {
- $data['value'] = array($data['value']);
+ $value = $data['value'];
+
+ if ($value instanceof Collection) {
+ $value = $value->getValues();
+ }
+ if (!is_array($value)) {
+ $value = array($value);
}
- $data['type'] = isset($data['type']) ? $data['type'] : null;
+ $data['type'] = isset($data['type']) ? $data['type'] : null;
+ $data['value'] = $value;
return $data;
}
diff --git a/src/Oro/Bundle/GridBundle/Filter/ORM/EntityFilter.php b/src/Oro/Bundle/GridBundle/Filter/ORM/EntityFilter.php
new file mode 100644
index 00000000000..3ee95c08f7f
--- /dev/null
+++ b/src/Oro/Bundle/GridBundle/Filter/ORM/EntityFilter.php
@@ -0,0 +1,41 @@
+ EntityFilterType::NAME
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRenderSettings()
+ {
+ list($formType, $formOptions) = parent::getRenderSettings();
+
+ // proxy for entity form type options
+ foreach (array('class', 'property', 'query_builder') as $option) {
+ $optionValue = $this->getOption($option);
+ if ($optionValue) {
+ $formOptions['field_options'][$option] = $optionValue;
+ }
+ }
+
+ $translatable = $this->getOption('translatable');
+ if ($translatable) {
+ $formOptions['translatable'] = $translatable;
+ }
+
+ return array($formType, $formOptions);
+ }
+}
diff --git a/src/Oro/Bundle/GridBundle/Filter/ORM/Flexible/FlexibleBooleanFilter.php b/src/Oro/Bundle/GridBundle/Filter/ORM/Flexible/FlexibleBooleanFilter.php
new file mode 100644
index 00000000000..761b0fa1461
--- /dev/null
+++ b/src/Oro/Bundle/GridBundle/Filter/ORM/Flexible/FlexibleBooleanFilter.php
@@ -0,0 +1,33 @@
+parentFilter->parseData($data);
+ if (!$data) {
+ return;
+ }
+
+ $value = ($data['value'] == BooleanFilterType::TYPE_YES) ? 1 : 0;
+
+ $this->applyFlexibleFilter($proxyQuery, $field, $value, '=');
+ }
+}
diff --git a/src/Oro/Bundle/GridBundle/Property/UrlProperty.php b/src/Oro/Bundle/GridBundle/Property/UrlProperty.php
index d342bc03c4c..b4f98cfd10c 100644
--- a/src/Oro/Bundle/GridBundle/Property/UrlProperty.php
+++ b/src/Oro/Bundle/GridBundle/Property/UrlProperty.php
@@ -32,6 +32,11 @@ class UrlProperty extends AbstractProperty
*/
protected $isAbsolute;
+ /**
+ * @var string
+ */
+ protected $anchor;
+
/**
* @param string $name
* @param Router $router
@@ -39,13 +44,14 @@ class UrlProperty extends AbstractProperty
* @param array $placeholders
* @param bool $isAbsolute
*/
- public function __construct($name, Router $router, $routeName, array $placeholders = array(), $isAbsolute = false)
+ public function __construct($name, Router $router, $routeName, array $placeholders = array(), $isAbsolute = false, $anchor = null)
{
$this->name = $name;
$this->router = $router;
$this->routeName = $routeName;
$this->placeholders = $placeholders;
$this->isAbsolute = $isAbsolute;
+ $this->anchor = $anchor;
}
/**
@@ -53,7 +59,8 @@ public function __construct($name, Router $router, $routeName, array $placeholde
*/
public function getValue(ResultRecordInterface $record)
{
- return $this->router->generate($this->routeName, $this->getParameters($record), $this->isAbsolute);
+ $route = $this->router->generate($this->routeName, $this->getParameters($record), $this->isAbsolute);
+ return $route . $this->anchor;
}
/**
diff --git a/src/Oro/Bundle/GridBundle/Resources/config/orm_filter_types.yml b/src/Oro/Bundle/GridBundle/Resources/config/orm_filter_types.yml
index ba9120d8b89..d3d514f2030 100644
--- a/src/Oro/Bundle/GridBundle/Resources/config/orm_filter_types.yml
+++ b/src/Oro/Bundle/GridBundle/Resources/config/orm_filter_types.yml
@@ -35,12 +35,24 @@ services:
tags:
- { name: oro_grid.filter.type, alias: oro_grid_orm_boolean }
+ oro_grid.orm.filter.type.entity:
+ class: Oro\Bundle\GridBundle\Filter\ORM\EntityFilter
+ arguments: ["@translator"]
+ tags:
+ - { name: oro_grid.filter.type, alias: oro_grid_orm_entity }
+
oro_grid.orm.filter.type.flexible_number:
class: Oro\Bundle\GridBundle\Filter\ORM\Flexible\FlexibleNumberFilter
arguments: ["@oro_flexibleentity.registry", "@oro_grid.orm.filter.type.number"]
tags:
- { name: oro_grid.filter.type, alias: oro_grid_orm_flexible_number }
+ oro_grid.orm.filter.type.flexible_boolean:
+ class: Oro\Bundle\GridBundle\Filter\ORM\Flexible\FlexibleBooleanFilter
+ arguments: ["@oro_flexibleentity.registry", "@oro_grid.orm.filter.type.boolean"]
+ tags:
+ - { name: oro_grid.filter.type, alias: oro_grid_orm_flexible_boolean }
+
oro_grid.orm.filter.type.flexible_string:
class: Oro\Bundle\GridBundle\Filter\ORM\Flexible\FlexibleStringFilter
arguments: ["@oro_flexibleentity.registry", "@oro_grid.orm.filter.type.string"]
diff --git a/src/Oro/Bundle/GridBundle/Resources/config/placeholders.yml b/src/Oro/Bundle/GridBundle/Resources/config/placeholders.yml
new file mode 100644
index 00000000000..4a96a1d01e1
--- /dev/null
+++ b/src/Oro/Bundle/GridBundle/Resources/config/placeholders.yml
@@ -0,0 +1,9 @@
+placeholders:
+ prepare_grid:
+ label: Prepare grid tempaltes
+ items:
+ datagrid:
+ order: 100
+items:
+ datagrid:
+ template: OroGridBundle:Include:datagrid.html.twig
diff --git a/src/Oro/Bundle/GridBundle/Resources/doc/index.md b/src/Oro/Bundle/GridBundle/Resources/doc/index.md
index 96462ab2add..c11e32a1df0 100644
--- a/src/Oro/Bundle/GridBundle/Resources/doc/index.md
+++ b/src/Oro/Bundle/GridBundle/Resources/doc/index.md
@@ -22,6 +22,7 @@ OroGridBundle Documentation
- [Route Generator](./reference/backend/route-generator.md)
- [Grid Rendering](./reference/backend/grid-rendering.md)
- [Events](./reference/backend/events.md)
+ - [Translations](./reference/backend/translations.md)
- **Frontend Architecture**
- [Overview](./reference/frontend/overview.md)
- [Backbone Developer Introduction](./reference/frontend/backbone-developer-introduction.md)
diff --git a/src/Oro/Bundle/GridBundle/Resources/doc/reference/backend/filters.md b/src/Oro/Bundle/GridBundle/Resources/doc/reference/backend/filters.md
index 56ede129388..c8223605fd1 100644
--- a/src/Oro/Bundle/GridBundle/Resources/doc/reference/backend/filters.md
+++ b/src/Oro/Bundle/GridBundle/Resources/doc/reference/backend/filters.md
@@ -17,6 +17,8 @@ Flexible filters are used to apply filters to flexible attributes in flexible en
* **Filter \ ORM \ NumberFilter** - ORM filter for number values;
* **Filter \ ORM \ StringFilter** - ORM filter for string values;
* **Filter \ ORM \ ChoiceFilter** - ORM filter which allows to use choices (single or multiple);
+* **Filter \ ORM \ EntityFilter** - ORM choices filter based on Symfony entity field type and allows to use
+entity repository or query builder as choices data source;
* **Filter \ ORM \ BooleanFilter** - ORM filter which allows to filter data as boolean value;
* **Filter \ ORM \ AbstractDateFilter** - abstract filter implementation to work with date/datetime values;
* **Filter \ ORM \ DateRangeFilter** - ORM filter for date and date range values;
@@ -86,6 +88,12 @@ services:
tags:
- { name: oro_grid.filter.type, alias: oro_grid_orm_boolean }
+ oro_grid.orm.filter.type.entity:
+ class: Oro\Bundle\GridBundle\Filter\ORM\EntityFilter
+ arguments: ["@translator"]
+ tags:
+ - { name: oro_grid.filter.type, alias: oro_grid_orm_entity }
+
oro_grid.orm.filter.type.flexible_number:
class: Oro\Bundle\GridBundle\Filter\ORM\Flexible\FlexibleNumberFilter
arguments: ["@oro_flexibleentity.registry", "@oro_grid.orm.filter.type.number"]
diff --git a/src/Oro/Bundle/GridBundle/Resources/doc/reference/backend/translations.md b/src/Oro/Bundle/GridBundle/Resources/doc/reference/backend/translations.md
new file mode 100644
index 00000000000..0697616c5db
--- /dev/null
+++ b/src/Oro/Bundle/GridBundle/Resources/doc/reference/backend/translations.md
@@ -0,0 +1,40 @@
+Translations
+------------
+
+OroGridBundle provides translation mechanism which can translate localized information (column and row action labels).
+
+DatagridManager contains translator object and translation domain and provides method _translate_
+which use translator object to perform translation. Default translation domain is "datagrid".
+
+#### Configuration
+
+**Translator and translation domain configuration**
+
+Datagrid manager can customize translator service and translation domain.
+
+```
+services:
+ orocrm_contact.contact.datagrid_manager:
+ class: %orocrm_contact.contact.datagrid_manager.class%
+ tags:
+ - name: oro_grid.datagrid.manager
+ ...
+ translator: acme_demobundle.custom_translator
+ translation_domain: acme_datagrid
+```
+
+**Default translation domain configuration**
+
+Default translation domain can be customized in main configuration.
+
+```
+oro_grid:
+ translation_domain: acme_datagrid
+```
+
+Another way to customize default translation domain is to set it as parameter in some specific bundle configuration.
+
+```
+parameters:
+ oro_grid.translation.translation_domain: acme_datagrid
+```
diff --git a/src/Oro/Bundle/GridBundle/Resources/public/js/app/datagrid/action/deleteaction.js b/src/Oro/Bundle/GridBundle/Resources/public/js/app/datagrid/action/deleteaction.js
index 9ef550eda95..765ee77cfc7 100644
--- a/src/Oro/Bundle/GridBundle/Resources/public/js/app/datagrid/action/deleteaction.js
+++ b/src/Oro/Bundle/GridBundle/Resources/public/js/app/datagrid/action/deleteaction.js
@@ -35,9 +35,9 @@ Oro.Datagrid.Action.DeleteAction = Oro.Datagrid.Action.ModelAction.extend({
self.getErrorDialog().open();
},
success: function() {
- var messageText = 'Item was deleted';
- if (!_.isUndefined(Oro.Messages)) {
- Oro.Messages.showMessage('success', messageText);
+ var messageText = Translator.get('Item was deleted');
+ if (!_.isUndefined(Oro.NotificationFlashMessage)) {
+ Oro.NotificationFlashMessage('success', messageText);
} else {
alert(messageText);
}
@@ -53,8 +53,8 @@ Oro.Datagrid.Action.DeleteAction = Oro.Datagrid.Action.ModelAction.extend({
getConfirmDialog: function() {
if (!this.confirmModal) {
this.confirmModal = new Oro.BootstrapModal({
- title: 'Delete Confirmation',
- content: 'Are you sure you want to delete this item?',
+ title: Translator.get('Delete Confirmation'),
+ content: Translator.get('Are you sure you want to delete this item?'),
okText: 'Yes, Delete',
allowCancel: 'false'
});
diff --git a/src/Oro/Bundle/GridBundle/Resources/public/js/app/datagrid/action/launcher.js b/src/Oro/Bundle/GridBundle/Resources/public/js/app/datagrid/action/launcher.js
index e096a478f7c..a6d69ddc1db 100644
--- a/src/Oro/Bundle/GridBundle/Resources/public/js/app/datagrid/action/launcher.js
+++ b/src/Oro/Bundle/GridBundle/Resources/public/js/app/datagrid/action/launcher.js
@@ -166,6 +166,9 @@ Oro.Datagrid.Action.Launcher = Backbone.View.extend({
this.trigger('click', this);
if (this.runAction) {
this.action.run();
+
+ // skip launcher functionality, if action was executed
+ return false;
}
return this.onClickReturnValue;
},
diff --git a/src/Oro/Bundle/GridBundle/Resources/public/js/app/datagrid/action/navigateaction.js b/src/Oro/Bundle/GridBundle/Resources/public/js/app/datagrid/action/navigateaction.js
index ade409877f1..c73a2456cf4 100644
--- a/src/Oro/Bundle/GridBundle/Resources/public/js/app/datagrid/action/navigateaction.js
+++ b/src/Oro/Bundle/GridBundle/Resources/public/js/app/datagrid/action/navigateaction.js
@@ -31,6 +31,8 @@ Oro.Datagrid.Action.NavigateAction = Oro.Datagrid.Action.ModelAction.extend({
this.useDirectLauncherLink = options.useDirectLauncherLink;
}
+ this.on('preExecute', _.bind(this._preExecuteSubscriber, this));
+
if (this.useDirectLauncherLink) {
this.launcherOptions = _.extend({
link: this.getLink(),
@@ -43,10 +45,15 @@ Oro.Datagrid.Action.NavigateAction = Oro.Datagrid.Action.ModelAction.extend({
* Execute redirect
*/
execute: function() {
- if (Oro.hashNavigationEnabled()) {
- Oro.Navigation.prototype.setLocation(this.getLink());
- } else {
- window.location.href = this.getLink();
- }
+ window.location.href = this.getLink();
+ },
+
+ /**
+ * Trigger global event
+ *
+ * @private
+ */
+ _preExecuteSubscriber: function(action, options) {
+ Oro.Events.trigger('grid_action:navigateAction:preExecute', action, options);
}
});
diff --git a/src/Oro/Bundle/GridBundle/Resources/translations/OroGridBundle.en.xliff b/src/Oro/Bundle/GridBundle/Resources/translations/OroGridBundle.en.xliff
index 113d2a1fe77..5024b1ee64c 100644
--- a/src/Oro/Bundle/GridBundle/Resources/translations/OroGridBundle.en.xliff
+++ b/src/Oro/Bundle/GridBundle/Resources/translations/OroGridBundle.en.xliff
@@ -2,42 +2,6 @@
-
-
- Filter
-
-
-
- Reset
-
-
-
- Sort descending
-
-
-
- Sort ascending
-
-
-
- 1 result|%count% results
-
-
-
- Per page
-
-
-
- All elements
-
-
-
- Download
-
-
-
- OK
-
No %entityHint% were found to match your search.
diff --git a/src/Oro/Bundle/GridBundle/Resources/views/Include/datagrid.html.twig b/src/Oro/Bundle/GridBundle/Resources/views/Include/datagrid.html.twig
new file mode 100644
index 00000000000..b68d1c41623
--- /dev/null
+++ b/src/Oro/Bundle/GridBundle/Resources/views/Include/datagrid.html.twig
@@ -0,0 +1,5 @@
+{% include 'OroGridBundle:Include:javascript.html.twig' with {'datagridView': datagrid, 'selector': selector} %}
+{% include 'OroGridBundle:Include:stylesheet.html.twig' %}
+{% if parameters is defined and parameters|length %}
+ {% include 'OroGridBundle:Include:Listener/column_form.html.twig' with {'datagridView': datagrid, 'parameters': parameters} %}
+{% endif %}
diff --git a/src/Oro/Bundle/GridBundle/Resources/views/Include/javascript.html.twig b/src/Oro/Bundle/GridBundle/Resources/views/Include/javascript.html.twig
index ef2fae5e912..89c8f90dbca 100644
--- a/src/Oro/Bundle/GridBundle/Resources/views/Include/javascript.html.twig
+++ b/src/Oro/Bundle/GridBundle/Resources/views/Include/javascript.html.twig
@@ -4,7 +4,7 @@
{% set form = datagridView.formView %}
+{% endoro_js %}
diff --git a/src/Oro/Bundle/NavigationBundle/Resources/views/HashNav/hashNavAjax.html.twig b/src/Oro/Bundle/NavigationBundle/Resources/views/HashNav/hashNavAjax.html.twig
index c66574ccedb..da25244e89f 100644
--- a/src/Oro/Bundle/NavigationBundle/Resources/views/HashNav/hashNavAjax.html.twig
+++ b/src/Oro/Bundle/NavigationBundle/Resources/views/HashNav/hashNavAjax.html.twig
@@ -1,23 +1,14 @@
-
-
{{ oro_title_render() }}
-
{{ oro_title_render_serialized()|raw }}
- {{ script|raw }}
-
-
- {{ menu|raw }}
-
-
- {{ messages|raw }}
-
-
- {{ oro_menu_render('history') }}
-
-
- {{ oro_menu_render('mostviewed') }}
-
-
- {{ content|raw }}
-
-
- {% if app.request.attributes.get('_route') == bap.start_route %}false{% else %}true{% endif %}
-
+{% spaceless %}
+{% set data = {
+ 'title': oro_title_render(),
+ 'titleSerialized': oro_title_render_serialized(),
+ 'scripts': script,
+ 'mainMenu': menu,
+ 'flashMessages': app.session.flashbag.all,
+ 'history': oro_menu_render('history'),
+ 'mostviewed': oro_menu_render('mostviewed'),
+ 'content': content,
+ 'showPinButton': (app.request.attributes.get('_route') != bap.start_route)
+} %}
+{{ data|json_encode|raw }}
+{% endspaceless %}
\ No newline at end of file
diff --git a/src/Oro/Bundle/NavigationBundle/Resources/views/HashNav/redirect.html.twig b/src/Oro/Bundle/NavigationBundle/Resources/views/HashNav/redirect.html.twig
index 967c49204f6..a8c000750f6 100644
--- a/src/Oro/Bundle/NavigationBundle/Resources/views/HashNav/redirect.html.twig
+++ b/src/Oro/Bundle/NavigationBundle/Resources/views/HashNav/redirect.html.twig
@@ -1 +1,6 @@
-{{ location }}
\ No newline at end of file
+{% set data = {
+ 'redirect': true,
+ 'fullRedirect': full_redirect,
+ 'location': location
+} %}
+{{ data|json_encode|raw }}
\ No newline at end of file
diff --git a/src/Oro/Bundle/NavigationBundle/Resources/views/HashNav/script.js.twig b/src/Oro/Bundle/NavigationBundle/Resources/views/HashNav/script.js.twig
new file mode 100644
index 00000000000..04bfe833335
--- /dev/null
+++ b/src/Oro/Bundle/NavigationBundle/Resources/views/HashNav/script.js.twig
@@ -0,0 +1,10 @@
+
diff --git a/src/Oro/Bundle/NavigationBundle/Resources/views/Js/navigationItem.html.twig b/src/Oro/Bundle/NavigationBundle/Resources/views/Js/navigationItem.html.twig
new file mode 100644
index 00000000000..e2cb57efa2e
--- /dev/null
+++ b/src/Oro/Bundle/NavigationBundle/Resources/views/Js/navigationItem.html.twig
@@ -0,0 +1,3 @@
+
diff --git a/src/Oro/Bundle/UIBundle/Resources/views/Menu/application_menu.html.twig b/src/Oro/Bundle/NavigationBundle/Resources/views/Menu/application_menu.html.twig
similarity index 100%
rename from src/Oro/Bundle/UIBundle/Resources/views/Menu/application_menu.html.twig
rename to src/Oro/Bundle/NavigationBundle/Resources/views/Menu/application_menu.html.twig
diff --git a/src/Oro/Bundle/UIBundle/Resources/views/Menu/dots_menu.html.twig b/src/Oro/Bundle/NavigationBundle/Resources/views/Menu/dots_menu.html.twig
similarity index 100%
rename from src/Oro/Bundle/UIBundle/Resources/views/Menu/dots_menu.html.twig
rename to src/Oro/Bundle/NavigationBundle/Resources/views/Menu/dots_menu.html.twig
diff --git a/src/Oro/Bundle/NavigationBundle/Resources/views/Menu/menuProfile.html.twig b/src/Oro/Bundle/NavigationBundle/Resources/views/Menu/menuProfile.html.twig
new file mode 100644
index 00000000000..a2060171c88
--- /dev/null
+++ b/src/Oro/Bundle/NavigationBundle/Resources/views/Menu/menuProfile.html.twig
@@ -0,0 +1,8 @@
+{% if app.user %}
+
+ {{ app.user.fullname(oro_config_value('oro_user.name_format')) }}
+ {{ oro_menu_render('usermenu') }}
+
+{% else %}
+ Login
+{% endif %}
diff --git a/src/Oro/Bundle/UIBundle/Resources/views/Menu/shortcuts.html.twig b/src/Oro/Bundle/NavigationBundle/Resources/views/Menu/shortcuts.html.twig
similarity index 75%
rename from src/Oro/Bundle/UIBundle/Resources/views/Menu/shortcuts.html.twig
rename to src/Oro/Bundle/NavigationBundle/Resources/views/Menu/shortcuts.html.twig
index af15e6a1cad..d8cf132c458 100644
--- a/src/Oro/Bundle/UIBundle/Resources/views/Menu/shortcuts.html.twig
+++ b/src/Oro/Bundle/NavigationBundle/Resources/views/Menu/shortcuts.html.twig
@@ -14,23 +14,23 @@