Merge pull request #19800 from eileenmcnaughton/gettypes
authorcolemanw <coleman@civicrm.org>
Tue, 23 Mar 2021 18:40:52 +0000 (14:40 -0400)
committerGitHub <noreply@github.com>
Tue, 23 Mar 2021 18:40:52 +0000 (14:40 -0400)
[REF] Remove setting of unused variables

186 files changed:
CRM/ACL/BAO/ACL.php
CRM/Activity/BAO/ActivityContact.php
CRM/Activity/Form/Search.php
CRM/Admin/Form/Setting.php
CRM/Admin/Form/Setting/Path.php
CRM/Admin/Form/Setting/Url.php
CRM/Campaign/Form/Task.php
CRM/Contact/BAO/DashboardContact.php
CRM/Contact/BAO/Query.php
CRM/Contact/Form/Task/EmailTrait.php
CRM/Contact/Import/Form/Preview.php
CRM/Contact/Import/Parser/Contact.php
CRM/Contribute/Export/Form/Select.php
CRM/Contribute/Form/Contribution/Confirm.php
CRM/Contribute/Form/Task.php
CRM/Contribute/Form/Task/TaskTrait.php [new file with mode: 0644]
CRM/Core/BAO/ActionSchedule.php
CRM/Core/BAO/CustomField.php
CRM/Core/DAO.php
CRM/Core/Error.php
CRM/Core/JobManager.php
CRM/Core/Payment.php
CRM/Core/Permission.php
CRM/Core/Permission/Base.php
CRM/Core/Permission/Drupal6.php
CRM/Core/Permission/Drupal8.php
CRM/Dedupe/Merger.php
CRM/Event/BAO/Participant.php
CRM/Export/BAO/ExportProcessor.php
CRM/Member/BAO/Membership.php
CRM/Member/Form.php
CRM/Member/Form/Membership.php
CRM/Upgrade/Incremental/sql/5.37.alpha1.mysql.tpl
CRM/Utils/Cache/Redis.php
CRM/Utils/Hook.php
CRM/Utils/Money.php
CRM/Utils/Rule.php
CRM/Utils/System.php
CRM/Utils/System/Joomla.php
Civi/Api4/Action/Permission/Get.php
Civi/Api4/Generic/DAOGetAction.php
Civi/Api4/Permission.php
Civi/Api4/Query/Api4SelectQuery.php
Civi/Api4/Route.php
Civi/Api4/Service/Schema/Joinable/CustomGroupJoinable.php
Civi/Api4/Service/Spec/SpecFormatter.php
Civi/Api4/Service/Spec/SpecGatherer.php
ang/api4Explorer/Explorer.html
ang/api4Explorer/Explorer.js
api/v3/Membership.php
composer.json
composer.lock
css/api4-explorer.css
css/civicrm.css
distmaker/utils/joomlaxml.php
ext/afform/admin/ang/afGuiEditor/config-form.html
ext/afform/core/CRM/Afform/AfformScanner.php
ext/afform/core/Civi/Afform/StatusChecks.php [new file with mode: 0644]
ext/afform/core/Civi/Afform/Tokens.php [new file with mode: 0644]
ext/afform/core/Civi/Api4/Action/Afform/Get.php
ext/afform/core/Civi/Api4/Afform.php
ext/afform/core/afform.php
ext/afform/core/phpunit.xml.dist
ext/afform/core/tests/phpunit/CRM/Afform/UtilTest.php
ext/afform/core/tests/phpunit/Civi/Afform/FilterTest.php
ext/afform/core/tests/phpunit/Civi/Afform/FormDataModelTest.php
ext/afform/core/tests/phpunit/Civi/Afform/SymbolsTest.php
ext/afform/core/tests/phpunit/bootstrap.php
ext/afform/docs/crud.md
ext/afform/html/ang/afHtmlEditor.aff.html
ext/afform/mock/ang/mockPublicForm.aff.json
ext/afform/mock/ang/mockPublicForm.test.php
ext/afform/mock/tests/phpunit/api/v4/AfformRoutingTest.php
ext/afform/mock/tests/phpunit/api/v4/AfformTest.php
ext/afform/mock/tests/phpunit/api/v4/AfformUsageTest.php
ext/afform/mock/tests/phpunit/bootstrap.php
ext/authx/Civi/Authx/Authenticator.php
ext/authx/Civi/Authx/Meta.php
ext/authx/authx.php
ext/authx/settings/authx.setting.php
ext/authx/tests/phpunit/Civi/Authx/AllFlowsTest.php
ext/authx/tests/phpunit/bootstrap.php
ext/contributioncancelactions/tests/phpunit/bootstrap.php
ext/ewaysingle/tests/phpunit/CRM/Core/Payment/EwayTest.php
ext/ewaysingle/tests/phpunit/bootstrap.php
ext/financialacls/tests/phpunit/Civi/Financialacls/BuildAmountHookTest.php
ext/financialacls/tests/phpunit/Civi/Financialacls/LineItemTest.php
ext/financialacls/tests/phpunit/Civi/Financialacls/MembershipTypesTest.php
ext/financialacls/tests/phpunit/Civi/Financialacls/OptionsTest.php
ext/financialacls/tests/phpunit/bootstrap.php
ext/flexmailer/tests/phpunit/Civi/FlexMailer/ClickTracker/HtmlClickTrackerTest.php
ext/flexmailer/tests/phpunit/Civi/FlexMailer/ClickTracker/TextClickTrackerTest.php
ext/flexmailer/tests/phpunit/Civi/FlexMailer/ClickTrackerTest.php
ext/flexmailer/tests/phpunit/Civi/FlexMailer/ConcurrentDeliveryTest.php
ext/flexmailer/tests/phpunit/Civi/FlexMailer/FlexMailerSystemTest.php
ext/flexmailer/tests/phpunit/Civi/FlexMailer/Listener/SimpleFilterTest.php
ext/flexmailer/tests/phpunit/Civi/FlexMailer/MailingPreviewTest.php
ext/flexmailer/tests/phpunit/Civi/FlexMailer/ValidatorTest.php
ext/flexmailer/tests/phpunit/bootstrap.php
ext/oauth-client/tests/phpunit/CRM/OAuth/MailSetupTest.php
ext/oauth-client/tests/phpunit/api/v4/OAuthClientGrantTest.php
ext/oauth-client/tests/phpunit/api/v4/OAuthClientTest.php
ext/oauth-client/tests/phpunit/api/v4/OAuthProviderTest.php
ext/oauth-client/tests/phpunit/api/v4/OAuthSysTokenTest.php
ext/oauth-client/tests/phpunit/bootstrap.php
ext/search/CRM/Search/Upgrader.php
ext/search/Civi/Api4/Action/SearchDisplay/Run.php
ext/search/Civi/Search/Admin.php
ext/search/ang/crmSearchActions/crmSearchActionUpdate.ctrl.js
ext/search/ang/crmSearchAdmin/compose/criteria.html
ext/search/ang/crmSearchAdmin/crmSearchAdmin.component.js
ext/search/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js
ext/search/ang/crmSearchAdmin/crmSearchAdminLinkGroup.component.js
ext/search/ang/crmSearchAdmin/crmSearchAdminLinkGroup.html
ext/search/ang/crmSearchAdmin/crmSearchAdminLinkSelect.component.js
ext/search/ang/crmSearchAdmin/crmSearchAdminLinkSelect.html
ext/search/ang/crmSearchAdmin/displays/colType/field.html
ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.html
ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.html
ext/search/ang/crmSearchDisplay.module.js
ext/search/ang/crmSearchDisplay/colType/buttons.html
ext/search/ang/crmSearchDisplay/colType/field.html
ext/search/ang/crmSearchDisplay/colType/links.html
ext/search/ang/crmSearchDisplay/colType/menu.html
ext/search/ang/crmSearchDisplay/crmSearchDisplayEditable.component.js [new file with mode: 0644]
ext/search/ang/crmSearchDisplay/crmSearchDisplayEditable.html [new file with mode: 0644]
ext/search/ang/crmSearchDisplayList/crmSearchDisplayList.component.js
ext/search/ang/crmSearchDisplayList/crmSearchDisplayList.html
ext/search/ang/crmSearchDisplayList/crmSearchDisplayListItems.html
ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.component.js
ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.html
ext/search/css/crmSearchActions.css
ext/search/css/crmSearchAdmin.css
ext/sequentialcreditnotes/phpunit.xml.dist
ext/sequentialcreditnotes/tests/phpunit/SequentialcreditnotesTest.php
ext/sequentialcreditnotes/tests/phpunit/bootstrap.php
js/Common.js
js/crm.menubar.js
release-notes.md
release-notes/5.35.1.md [new file with mode: 0644]
sql/GenerateData.php
sql/GenerateGroups.php
sql/GenerateMailing.php
sql/GenerateReportData.php
sql/civicrm_generated.mysql
templates/CRM/Activity/Import/Form/MapTable.tpl
templates/CRM/Admin/Page/ExtensionDetails.tpl
templates/CRM/Admin/Page/Extensions/Main.tpl
templates/CRM/Contact/Import/Form/MapTable.tpl
templates/CRM/Contribute/Form/Contribution.tpl
templates/CRM/Contribute/Import/Form/MapTable.tpl
templates/CRM/Event/Import/Form/MapTable.tpl
templates/CRM/Financial/Form/Export.tpl
templates/CRM/Member/Import/Form/MapTable.tpl
templates/CRM/PCP/Page/PCPInfo.tpl
templates/CRM/common/SocialNetwork.tpl
tests/phpunit/CRM/Activity/Form/ActivityViewTest.php
tests/phpunit/CRM/Activity/Form/Task/PDFLetterCommonTest.php
tests/phpunit/CRM/Contact/SelectorTest.php
tests/phpunit/CRM/Contribute/Form/Contribution/ConfirmTest.php
tests/phpunit/CRM/Contribute/Form/Contribution/ThankYouTest.php
tests/phpunit/CRM/Core/BAO/ActionScheduleTest.php
tests/phpunit/CRM/Core/BAO/CustomFieldTest.php
tests/phpunit/CRM/Core/InvokeTest.php [new file with mode: 0644]
tests/phpunit/CRM/Core/Permission/BaseTest.php
tests/phpunit/CRM/Core/ResourcesTest.php
tests/phpunit/CRM/Dedupe/MergerTest.php
tests/phpunit/CRM/Event/Form/ParticipantTest.php
tests/phpunit/CRM/Export/BAO/ExportTest.php
tests/phpunit/CRM/Logging/LoggingTest.php
tests/phpunit/CRM/Logging/SchemaTest.php
tests/phpunit/CRM/Member/Form/MembershipTest.php
tests/phpunit/CRM/Utils/RuleTest.php
tests/phpunit/CRM/Utils/TypeTest.php
tests/phpunit/Civi/API/Subscriber/DynamicFKAuthorizationTest.php
tests/phpunit/CiviTest/bootstrap.php
tests/phpunit/HelloTest.php
tests/phpunit/api/v3/ContactTest.php
tests/phpunit/api/v3/MembershipTypeTest.php
tests/phpunit/api/v4/Action/FkJoinTest.php
tests/phpunit/api/v4/Spec/SpecFormatterTest.php
tools/bin/scripts/NormalizePhone.php
tools/bin/scripts/ckeditorConfigScraper.php
tools/bin/scripts/set-version.php
tools/bin/scripts/testProcess.php
xml/templates/civicrm_state_province.tpl

index f1f8cb0df8a1c67f51fb2bc348cde8620f1d7dad..5927b87753378868dc8b5afb4e5a2650eabd9033 100644 (file)
@@ -88,17 +88,12 @@ class CRM_ACL_BAO_ACL extends CRM_ACL_DAO_ACL {
    */
   protected static function getACLs(int $contact_id) {
     $results = [];
-
-    $rule = new CRM_ACL_BAO_ACL();
-
-    $contact = CRM_Contact_BAO_Contact::getTableName();
-
     $query = " SELECT acl.*
       FROM civicrm_acl acl
-      WHERE   acl.entity_table   = '$contact'
+      WHERE   acl.entity_table   = 'civicrm_contact'
       AND acl.entity_id      = $contact_id";
 
-    $rule->query($query);
+    $rule = CRM_Core_DAO::executeQuery($query);
 
     while ($rule->fetch()) {
       $results[$rule->id] = $rule->toArray();
@@ -123,20 +118,16 @@ class CRM_ACL_BAO_ACL extends CRM_ACL_DAO_ACL {
   protected static function getACLRoles($contact_id = NULL) {
     $contact_id = CRM_Utils_Type::escape($contact_id, 'Integer');
 
-    $rule = new CRM_ACL_BAO_ACL();
-
-    $contact = CRM_Contact_BAO_Contact::getTableName();
-
     $query = 'SELECT acl.* FROM civicrm_acl acl';
     $where = ['acl.entity_table = "civicrm_acl_role" AND acl.entity_id IN (' . implode(',', array_keys(CRM_Core_OptionGroup::values('acl_role'))) . ')'];
 
     if (!empty($contact_id)) {
-      $where[] = " acl.entity_table  = '$contact' AND acl.is_active = 1 AND acl.entity_id = $contact_id";
+      return [];
     }
 
     $results = [];
 
-    $rule->query($query . ' WHERE ' . implode(' AND ', $where));
+    $rule = CRM_Core_DAO::executeQuery($query . ' WHERE ' . implode(' AND ', $where));
 
     while ($rule->fetch()) {
       $results[$rule->id] = $rule->toArray();
@@ -160,23 +151,19 @@ class CRM_ACL_BAO_ACL extends CRM_ACL_DAO_ACL {
   protected static function getGroupACLs($contact_id, $aclRoles = FALSE) {
     $contact_id = CRM_Utils_Type::escape($contact_id, 'Integer');
 
-    $rule = new CRM_ACL_BAO_ACL();
-
-    $c2g = CRM_Contact_BAO_GroupContact::getTableName();
-    $group = CRM_Contact_BAO_Group::getTableName();
     $results = [];
 
     if ($contact_id) {
       $query = "
 SELECT      acl.*
   FROM      civicrm_acl acl
- INNER JOIN  $c2g group_contact
+ INNER JOIN  civicrm_group_contact group_contact
         ON  acl.entity_id      = group_contact.group_id
-     WHERE  acl.entity_table   = '$group'
+     WHERE  acl.entity_table   = 'civicrm_group'
        AND  group_contact.contact_id     = $contact_id
        AND  group_contact.status         = 'Added'";
 
-      $rule->query($query);
+      $rule = CRM_Core_DAO::executeQuery($query);
 
       while ($rule->fetch()) {
         $results[$rule->id] = $rule->toArray();
index 4ac6652f7c251374212e77590f01f1aa0fdf544d..b68260e1be64ca52a9be049e75f4ce439c5997da 100644 (file)
  */
 class CRM_Activity_BAO_ActivityContact extends CRM_Activity_DAO_ActivityContact {
 
-  /**
-   * Class constructor.
-   */
-  public function __construct() {
-    parent::__construct();
-  }
-
   /**
    * Function to add activity contact.
    *
    * @param array $params
    *   The values for this table: activity id, contact id, record type.
    *
-   * @return object
+   * @return CRM_Activity_DAO_ActivityContact
    *   activity_contact object
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \PEAR_Exception
    */
-  public static function create($params) {
-    $activityContact = new CRM_Activity_DAO_ActivityContact();
-    $activityContact->copyValues($params);
+  public static function create(array $params): CRM_Activity_DAO_ActivityContact {
     try {
-      return $activityContact->save();
+      return self::writeRecord($params);
     }
     catch (PEAR_Exception $e) {
       // This check used to be done first, creating an extra query before each insert.
       // However, in none of the core tests was this ever called with values that already
       // existed, meaning that this line would never or almost never be hit.
       // hence it's better to save the select query here.
+      $activityContact = new CRM_Activity_DAO_ActivityContact();
+      $activityContact->copyValues($params);
       if ($activityContact->find(TRUE)) {
         return $activityContact;
       }
index 3c2b792f428faca6b23b6c282d8be949242d3921..6b3e467266e7bd7aca8d6e83ec4f6417718ad488 100644 (file)
@@ -62,7 +62,7 @@ class CRM_Activity_Form_Search extends CRM_Core_Form_Search {
   /**
    * @return string
    */
-  public function getDefaultEntity() {
+  public function getDefaultEntity(): string {
     return 'Activity';
   }
 
@@ -72,7 +72,7 @@ class CRM_Activity_Form_Search extends CRM_Core_Form_Search {
    * @throws \CRM_Core_Exception
    * @throws \CiviCRM_API3_Exception
    */
-  public function preProcess() {
+  public function preProcess(): void {
     $this->set('searchFormName', 'Search');
 
     // set the button names
@@ -83,10 +83,8 @@ class CRM_Activity_Form_Search extends CRM_Core_Form_Search {
 
     parent::preProcess();
 
-    if (empty($this->_formValues)) {
-      if (isset($this->_ssID)) {
-        $this->_formValues = CRM_Contact_BAO_SavedSearch::getFormValues($this->_ssID);
-      }
+    if (empty($this->_formValues) && isset($this->_ssID)) {
+      $this->_formValues = CRM_Contact_BAO_SavedSearch::getFormValues($this->_ssID);
     }
 
     $this->_queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_formValues);
@@ -98,7 +96,7 @@ class CRM_Activity_Form_Search extends CRM_Core_Form_Search {
       $this->_context
     );
     $prefix = NULL;
-    if ($this->_context == 'user') {
+    if ($this->_context === 'user') {
       $prefix = $this->_prefix;
     }
 
@@ -125,7 +123,7 @@ class CRM_Activity_Form_Search extends CRM_Core_Form_Search {
    * @throws \CRM_Core_Exception
    * @throws \CiviCRM_API3_Exception
    */
-  public function buildQuickForm() {
+  public function buildQuickForm(): void {
     parent::buildQuickForm();
     $this->addSortNameField();
 
@@ -155,9 +153,9 @@ class CRM_Activity_Form_Search extends CRM_Core_Form_Search {
    * The processing consists of using a Selector / Controller framework for getting the
    * search results.
    *
-   * @throws \CRM_Core_Exception
+   * @throws \CRM_Core_Exception|\CiviCRM_API3_Exception
    */
-  public function postProcess() {
+  public function postProcess(): void {
     if ($this->_done) {
       return;
     }
@@ -184,7 +182,7 @@ class CRM_Activity_Form_Search extends CRM_Core_Form_Search {
 
     // We don't show test records in summaries or dashboards
     if (empty($this->_formValues['activity_test']) && $this->_force) {
-      $this->_formValues["activity_test"] = 0;
+      $this->_formValues['activity_test'] = 0;
     }
 
     $this->_queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_formValues);
@@ -286,7 +284,7 @@ class CRM_Activity_Form_Search extends CRM_Core_Form_Search {
     // use getEntity Defaults
     $requestParams = CRM_Utils_Request::exportValues();
     foreach (array_keys($requestParams) as $key) {
-      if (substr($key, 0, 7) != 'custom_') {
+      if (substr($key, 0, 7) !== 'custom_') {
         continue;
       }
       elseif (empty($requestParams[$key])) {
index 41585c821389b9b75ac740cb9941c95b15eca446..57e2c9fff52f6b18b7f451c0554f88bf20d9a7cc 100644 (file)
@@ -117,6 +117,7 @@ class CRM_Admin_Form_Setting extends CRM_Core_Form {
     Civi::cache('session')->clear();
     CRM_Utils_System::flushCache();
     CRM_Core_Resources::singleton()->resetCacheCode();
+    $this->rebuildMenu();
 
     CRM_Core_Session::setStatus(" ", ts('Changes Saved'), "success");
   }
index d882f37fd9c805db7abd32e09129875c9ee286ae..aa17363a29141ec19db4856b2014b9318cf53e46 100644 (file)
@@ -31,6 +31,8 @@ class CRM_Admin_Form_Setting_Path extends CRM_Admin_Form_Setting {
 
   /**
    * Build the form object.
+   *
+   * @throws \CRM_Core_Exception
    */
   public function buildQuickForm() {
     CRM_Utils_System::setTitle(ts('Settings - Upload Directories'));
@@ -56,10 +58,4 @@ class CRM_Admin_Form_Setting_Path extends CRM_Admin_Form_Setting {
 
   }
 
-  public function postProcess() {
-    parent::postProcess();
-
-    parent::rebuildMenu();
-  }
-
 }
index fa854247eaf4243b053c5c79cd4d964d65e11c77..a81c1e5313e04d8a83dc19745b410b9e88e13f45 100644 (file)
@@ -81,8 +81,6 @@ class CRM_Admin_Form_Setting_Url extends CRM_Admin_Form_Setting {
     $session->getStatus(TRUE);
 
     parent::postProcess();
-
-    parent::rebuildMenu();
   }
 
 }
index 8765bdcdc4c9e316eae854e89306daf6b133f11a..924e49ed4f29b6d772ff7c4dee7d476521b3e09e 100644 (file)
@@ -35,7 +35,7 @@ class CRM_Campaign_Form_Task extends CRM_Core_Form_Task {
 
     $this->_task = $values['task'];
 
-    $ids = $form->getSelectedIDs($values);
+    $ids = $this->getSelectedIDs($values);
 
     if (!$ids) {
       $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', $this);
index c6ff99f6891a9cfd33421c01eab9a20843b64da6..145494860b58e8a8f0fcba5666da31a149cdc117 100644 (file)
@@ -17,10 +17,11 @@ class CRM_Contact_BAO_DashboardContact extends CRM_Contact_DAO_DashboardContact
 
   /**
    * @param array $record
+   *
    * @return CRM_Contact_DAO_DashboardContact
-   * @throws CRM_Core_Exception
+   * @throws \CRM_Core_Exception
    */
-  public static function writeRecord(array $record) {
+  public static function writeRecord(array $record): CRM_Core_DAO {
     self::checkEditPermission($record);
     return parent::writeRecord($record);
   }
index baa41722cd9e9275814e0a82fdffee7f07ce8d16..b53ebface16000a5342e5ceb772267774864e701 100644 (file)
@@ -396,6 +396,7 @@ class CRM_Contact_BAO_Query {
     'im',
     'address_name',
     'master_id',
+    'location_type',
   ];
 
   /**
@@ -1281,6 +1282,14 @@ class CRM_Contact_BAO_Query {
                   }
                   break;
 
+                case 'civicrm_location_type':
+                  $this->_tables[$tName] = "\nLEFT JOIN $tableName `$tName` ON `$tName`.id = $aName.location_type_id";
+
+                  if ($addWhere) {
+                    $this->_whereTables["{$name}-address"] = $addressJoin;
+                  }
+                  break;
+
                 case 'civicrm_country':
                   $this->_pseudoConstantsSelect["{$name}-{$elementFullName}"]['table'] = $newName;
                   $this->_pseudoConstantsSelect["{$name}-{$elementFullName}"]['join']
index 67c06172d8e10aa63031a919ff74cb2bfd971037..bd5c205996e230092af2d295bff47ea694075d01 100644 (file)
@@ -447,20 +447,6 @@ trait CRM_Contact_Form_Task_EmailTrait {
         'plural' => '%count Messages Not Sent',
       ]), 'info');
     }
-
-    if (isset($this->_caseId)) {
-      // if case-id is found in the url, create case activity record
-      $cases = explode(',', $this->_caseId);
-      foreach ($cases as $key => $val) {
-        if (is_numeric($val)) {
-          $caseParams = [
-            'activity_id' => $activityId,
-            'case_id' => $val,
-          ];
-          CRM_Case_BAO_Case::processCaseActivity($caseParams);
-        }
-      }
-    }
   }
 
   /**
index 77ddd7afa22a1ed5f3a20663920baf8c103c39cf..d25cd4f58eced0cc559949abd431ca8153708aa8 100644 (file)
@@ -423,7 +423,7 @@ class CRM_Contact_Import_Form_Preview extends CRM_Import_Form_Preview {
     );
 
     // add the new contacts to selected groups
-    $contactIds = &$parser->getImportedContacts();
+    $contactIds = $parser->getImportedContacts();
 
     // add the new related contacts to selected groups
     $relatedContactIds = &$parser->getRelatedImportedContacts();
index b35004675b33dc566f62b81028d986ddf5b68d18..75bbb421d3a96e169797708909ddc5fd29909025 100644 (file)
@@ -979,7 +979,7 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser {
    *
    * @return array
    */
-  public function &getImportedContacts() {
+  public function getImportedContacts() {
     return $this->_newContacts;
   }
 
index 9ad30badd631521ec3e5ad89264893618ce7b849..4e57be122f48c5ddd241895e0eeb359ac4c577e0 100644 (file)
  */
 class CRM_Contribute_Export_Form_Select extends CRM_Export_Form_Select {
 
+  use CRM_Contribute_Form_Task_TaskTrait;
+
   /**
    * Call the pre-processing function.
+   *
+   * @throws \CRM_Core_Exception
    */
   protected function callPreProcessing(): void {
     CRM_Contribute_Form_Task::preProcessCommon($this);
index 549b8ec985c736aeeb05def96b438bb5076173af..9e20a3015b1f38036862d81164946cb98fcc108e 100644 (file)
@@ -2770,10 +2770,6 @@ class CRM_Contribute_Form_Contribution_Confirm extends CRM_Contribute_Form_Contr
       if (!empty($form->_paymentProcessor)) {
         $contributionParams['payment_instrument_id'] = $paymentParams['payment_instrument_id'] = $form->_paymentProcessor['payment_instrument_id'];
       }
-
-      // @todo this is the wrong place for this - it should be done as close to form submission
-      // as possible
-      $paymentParams['amount'] = CRM_Utils_Rule::cleanMoney($paymentParams['amount']);
       $contribution = CRM_Contribute_Form_Contribution_Confirm::processFormContribution(
         $form,
         $paymentParams,
index 60cc441184cf6533cd8ee7a2e26da8f600a520fa..1cef21bc6cc8bbaf6ffe52820bca164d0fcc1c02 100644 (file)
@@ -21,6 +21,8 @@
  */
 class CRM_Contribute_Form_Task extends CRM_Core_Form_Task {
 
+  use CRM_Contribute_Form_Task_TaskTrait;
+
   /**
    * The array that holds all the contribution ids.
    *
@@ -50,11 +52,11 @@ class CRM_Contribute_Form_Task extends CRM_Core_Form_Task {
   }
 
   /**
-   * @param \CRM_Core_Form_Task $form
+   * @param \CRM_Contribute_Form_Task $form
    *
    * @throws \CRM_Core_Exception
    */
-  public static function preProcessCommon(&$form) {
+  public static function preProcessCommon(&$form): void {
     $form->_contributionIds = [];
 
     $values = $form->getSearchFormValues();
@@ -63,50 +65,8 @@ class CRM_Contribute_Form_Task extends CRM_Core_Form_Task {
 
     $ids = $form->getSelectedIDs($values);
     if (!$ids) {
-      $queryParams = $form->get('queryParams');
-      $isTest = FALSE;
-      if (is_array($queryParams)) {
-        foreach ($queryParams as $fields) {
-          if ($fields[0] === 'contribution_test') {
-            $isTest = TRUE;
-            break;
-          }
-        }
-      }
-      if (!$isTest) {
-        $queryParams[] = [
-          'contribution_test',
-          '=',
-          0,
-          0,
-          0,
-        ];
-      }
-      $returnProperties = ['contribution_id' => 1];
-      $sortOrder = $sortCol = NULL;
-      if ($form->get(CRM_Utils_Sort::SORT_ORDER)) {
-        $sortOrder = $form->get(CRM_Utils_Sort::SORT_ORDER);
-        //Include sort column in select clause.
-        $sortCol = trim(str_replace(['`', 'asc', 'desc'], '', $sortOrder));
-        $returnProperties[$sortCol] = 1;
-      }
-
-      $form->_includesSoftCredits = CRM_Contribute_BAO_Query::isSoftCreditOptionEnabled($queryParams);
-      $query = new CRM_Contact_BAO_Query($queryParams, $returnProperties, NULL, FALSE, FALSE,
-        CRM_Contact_BAO_Query::MODE_CONTRIBUTE
-      );
-      // @todo the function CRM_Contribute_BAO_Query::isSoftCreditOptionEnabled should handle this
-      // can we remove? if not why not?
-      if ($form->_includesSoftCredits) {
-        $contactIds = $contributionContactIds = [];
-        $query->_rowCountClause = " count(civicrm_contribution.id)";
-        $query->_groupByComponentClause = " GROUP BY contribution_search_scredit_combined.id, contribution_search_scredit_combined.contact_id, contribution_search_scredit_combined.scredit_id ";
-      }
-      else {
-        $query->_distinctComponentClause = ' civicrm_contribution.id';
-        $query->_groupByComponentClause = ' GROUP BY civicrm_contribution.id ';
-      }
-      $result = $query->searchQuery(0, 0, $sortOrder);
+      $result = $form->getSearchQueryResults();
+      $contributionContactIds = $contactIds = [];
       while ($result->fetch()) {
         $ids[] = $result->contribution_id;
         if ($form->_includesSoftCredits) {
diff --git a/CRM/Contribute/Form/Task/TaskTrait.php b/CRM/Contribute/Form/Task/TaskTrait.php
new file mode 100644 (file)
index 0000000..85d17ff
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ *
+ * @package CRM
+ * @copyright CiviCRM LLC https://civicrm.org/licensing
+ */
+
+/**
+ * This class provides shared contribution task functionality.
+ */
+trait CRM_Contribute_Form_Task_TaskTrait {
+
+  /**
+   * Get the results from the BAO_Query object based search.
+   *
+   * @return CRM_Core_DAO
+   *
+   * @throws \CRM_Core_Exception
+   */
+  public function getSearchQueryResults(): CRM_Core_DAO {
+    $form = $this;
+    $queryParams = $this->getQueryParams();
+    $returnProperties = ['contribution_id' => 1];
+    $sortOrder = $sortCol = NULL;
+    if ($form->get(CRM_Utils_Sort::SORT_ORDER)) {
+      $sortOrder = $form->get(CRM_Utils_Sort::SORT_ORDER);
+      //Include sort column in select clause.
+      $sortCol = trim(str_replace(['`', 'asc', 'desc'], '', $sortOrder));
+      $returnProperties[$sortCol] = 1;
+    }
+
+    $form->_includesSoftCredits = CRM_Contribute_BAO_Query::isSoftCreditOptionEnabled($queryParams);
+    $query = new CRM_Contact_BAO_Query($queryParams, $returnProperties, NULL, FALSE, FALSE,
+      CRM_Contact_BAO_Query::MODE_CONTRIBUTE
+    );
+    // @todo the function CRM_Contribute_BAO_Query::isSoftCreditOptionEnabled should handle this
+    // can we remove? if not why not?
+    if ($form->_includesSoftCredits) {
+      $query->_rowCountClause = " count(civicrm_contribution.id)";
+      $query->_groupByComponentClause = " GROUP BY contribution_search_scredit_combined.id, contribution_search_scredit_combined.contact_id, contribution_search_scredit_combined.scredit_id ";
+    }
+    else {
+      $query->_distinctComponentClause = ' civicrm_contribution.id';
+      $query->_groupByComponentClause = ' GROUP BY civicrm_contribution.id ';
+    }
+    return $query->searchQuery(0, 0, $sortOrder);
+  }
+
+  /**
+   * Get the query parameters, adding test = FALSE if needed.
+   *
+   * @return array|null
+   */
+  protected function getQueryParams(): ?array {
+    $queryParams = $this->get('queryParams');
+    if (!is_array($queryParams)) {
+      return NULL;
+    }
+    foreach ($queryParams as $fields) {
+      if ($fields[0] === 'contribution_test') {
+        return $queryParams;
+      }
+    }
+    $queryParams[] = [
+      'contribution_test',
+      '=',
+      0,
+      0,
+      0,
+    ];
+    return $queryParams;
+  }
+
+}
index 47fdd617ca17d8a5331c6339464548dd40fc1568..b724780662aa9e4a2fe56cea4559f0fba992d4a8 100644 (file)
@@ -588,7 +588,7 @@ FROM civicrm_action_schedule cas
     $domainValues = CRM_Core_BAO_Domain::getNameAndEmail();
     $fromEmailAddress = "$domainValues[0] <$domainValues[1]>";
     if ($actionSchedule->from_email) {
-      $fromEmailAddress = "$actionSchedule->from_name <$actionSchedule->from_email>";
+      $fromEmailAddress = "\"$actionSchedule->from_name\" <$actionSchedule->from_email>";
       return $fromEmailAddress;
     }
     return $fromEmailAddress;
index b27bad0c39b37a8b71f9d7d2864dfe338edb3c63..f45707ca96b906c872d19a8cc83f1caeecad1ffd 100644 (file)
@@ -1994,6 +1994,11 @@ WHERE  id IN ( %1, %2 )
       }
     }
 
+    // Remove option group IDs from fields changed to Text html_type.
+    if ($htmlType == 'Text') {
+      $params['option_group_id'] = '';
+    }
+
     // check for orphan option groups
     if (!empty($params['option_group_id'])) {
       if (!empty($params['id'])) {
index b80bc54575bad121f81d6e3b332e4ce10d9db28e..506a971ba72ada0069624873e40614d202ab14eb 100644 (file)
@@ -887,10 +887,11 @@ class CRM_Core_DAO extends DB_DataObject {
    * Otherwise a new record will be created.
    *
    * @param array $record
-   * @return CRM_Core_DAO
-   * @throws CRM_Core_Exception
+   *
+   * @return $this
+   * @throws \CRM_Core_Exception
    */
-  public static function writeRecord(array $record) {
+  public static function writeRecord(array $record): CRM_Core_DAO {
     $hook = empty($record['id']) ? 'create' : 'edit';
     $className = CRM_Core_DAO_AllCoreTables::getCanonicalClassName(static::class);
     if ($className === 'CRM_Core_DAO') {
index 0d15f3006ee94b283981b80e2d0761598ce2f6ee..6c44df6261a3d2dbdf8153874f2fa1140524464f 100644 (file)
@@ -829,7 +829,7 @@ class CRM_Core_Error extends PEAR_ErrorStack {
     // Exception backtrace
     if ($e instanceof PEAR_Exception) {
       $ei = $e;
-      while (is_callable([$ei, 'getCause'])) {
+      if (is_callable([$ei, 'getCause'])) {
         // DB_ERROR doesn't have a getCause but does have a __call function which tricks is_callable.
         if (!$ei instanceof DB_Error) {
           if ($ei->getCause() instanceof PEAR_Error) {
index 604d3ee150ddfeb45e8d2b5d6e0dc51bb4ae015a..d30646262e9f2f9dc99086c8d1c05187cee49a1d 100644 (file)
@@ -40,9 +40,6 @@ class CRM_Core_JobManager {
    * Class constructor.
    */
   public function __construct() {
-    $config = CRM_Core_Config::singleton();
-    $config->fatalErrorHandler = 'CRM_Core_JobManager_scheduledJobFatalErrorHandler';
-
     $this->jobs = $this->_getJobs();
   }
 
@@ -276,12 +273,3 @@ class CRM_Core_JobManager {
   }
 
 }
-
-/**
- * @param $message
- *
- * @throws Exception
- */
-function CRM_Core_JobManager_scheduledJobFatalErrorHandler($message) {
-  throw new Exception("{$message['message']}: {$message['code']}");
-}
index 74892574f8dece8a9209fc73e0ab5e90223a26fe..8064029670ca052daecd2106bf2e6f279ed6a799 100644 (file)
@@ -584,20 +584,10 @@ abstract class CRM_Core_Payment {
     // not documented clearly above.
     switch ($context) {
       case 'contributionPageRecurringHelp':
-        // require exactly two parameters
-        if (array_keys($params) == [
-          'is_recur_installments',
-          'is_email_receipt',
-        ]) {
-          $gotText = ts('Your recurring contribution will be processed automatically.');
-          if ($params['is_recur_installments']) {
-            $gotText .= ' ' . ts('You can specify the number of installments, or you can leave the number of installments blank if you want to make an open-ended commitment. In either case, you can choose to cancel at any time.');
-          }
-          if ($params['is_email_receipt']) {
-            $gotText .= ' ' . ts('You will receive an email receipt for each recurring contribution.');
-          }
+        if ($params['is_recur_installments']) {
+          return ts('You can specify the number of installments, or you can leave the number of installments blank if you want to make an open-ended commitment. In either case, you can choose to cancel at any time.');
         }
-        return $gotText;
+        return '';
 
       case 'contributionPageContinueText':
         return ts('Click the <strong>Continue</strong> button to proceed with the payment.');
index cd21819d18e6bd6ff5b49bbaf72efa1ef67e58f6..37c14b04148db6ffeb0776ce1deea891067a93d8 100644 (file)
@@ -585,48 +585,19 @@ class CRM_Core_Permission {
    *   whether to return descriptions
    *
    * @return array
+   * @throws \CRM_Core_Exception
    */
-  public static function assembleBasicPermissions($all = FALSE, $descriptions = FALSE) {
-    $config = CRM_Core_Config::singleton();
-    $permissions = self::getCorePermissions();
+  public static function assembleBasicPermissions($all = FALSE, $descriptions = FALSE): array {
+    $permissions = self::getCoreAndComponentPermissions($all);
 
+    // Add any permissions defined in hook_civicrm_permission implementations.
+    $module_permissions = CRM_Core_Config::singleton()->userPermissionClass->getAllModulePermissions(TRUE, $permissions);
+    $permissions = array_merge($permissions, $module_permissions);
     if (!$descriptions) {
       foreach ($permissions as $name => $attr) {
         $permissions[$name] = array_shift($attr);
       }
     }
-    if (!$all) {
-      $components = CRM_Core_Component::getEnabledComponents();
-    }
-    else {
-      $components = CRM_Core_Component::getComponents();
-    }
-
-    foreach ($components as $comp) {
-      $perm = $comp->getPermissions($all, $descriptions);
-      if ($perm) {
-        $info = $comp->getInfo();
-        foreach ($perm as $p => $attr) {
-
-          if (!is_array($attr)) {
-            $attr = [$attr];
-          }
-
-          $attr[0] = $info['translatedName'] . ': ' . $attr[0];
-
-          if ($descriptions) {
-            $permissions[$p] = $attr;
-          }
-          else {
-            $permissions[$p] = $attr[0];
-          }
-        }
-      }
-    }
-
-    // Add any permissions defined in hook_civicrm_permission implementations.
-    $module_permissions = $config->userPermissionClass->getAllModulePermissions($descriptions);
-    $permissions = array_merge($permissions, $module_permissions);
     return $permissions;
   }
 
@@ -903,6 +874,10 @@ class CRM_Core_Permission {
         'label' => $prefix . ts('administer CiviCRM Data'),
         'description' => ts('Permit altering all restricted data options'),
       ],
+      'all CiviCRM permissions and ACLs' => [
+        'label' => $prefix . ts('all CiviCRM permissions and ACLs'),
+        'description' => ts('Administer and use CiviCRM bypassing any other permission or ACL checks and enabling the creation of displays and forms that allow others to bypass checks. This permission should be given out with care'),
+      ],
     ];
     if (self::isMultisiteEnabled()) {
       // This could arguably be moved to the multisite extension but
@@ -912,11 +887,6 @@ class CRM_Core_Permission {
         'description' => ts('Administer multiple organizations. In practice this allows editing the group organization link'),
       ];
     }
-    foreach (self::getImpliedPermissions() as $name => $includes) {
-      foreach ($includes as $permission) {
-        $permissions[$name][] = $permissions[$permission];
-      }
-    }
     return $permissions;
   }
 
@@ -925,11 +895,11 @@ class CRM_Core_Permission {
    *
    * @return array
    */
-  public static function getImpliedPermissions() {
+  public static function getImpliedAdminPermissions(): array {
     return [
-      'administer CiviCRM' => ['administer CiviCRM system', 'administer CiviCRM data'],
-      'administer CiviCRM data' => ['edit message templates', 'administer dedupe rules'],
-      'administer CiviCRM system' => ['edit system workflow message templates'],
+      'administer CiviCRM' => ['implied_permissions' => ['administer CiviCRM system', 'administer CiviCRM data']],
+      'administer CiviCRM data' => ['implied_permissions' => ['edit message templates', 'administer dedupe rules']],
+      'administer CiviCRM system' => ['implied_permissions' => ['edit system workflow message templates']],
     ];
   }
 
@@ -940,14 +910,24 @@ class CRM_Core_Permission {
    *
    * @return array
    */
-  public static function getImpliedPermissionsFor(string $permission) {
-    $return = [];
-    foreach (self::getImpliedPermissions() as $superPermission => $components) {
-      if (in_array($permission, $components, TRUE)) {
-        $return[$superPermission] = $superPermission;
+  public static function getImpliedPermissionsFor(string $permission): array {
+    if (in_array($permission[0], ['@', '*'], TRUE)) {
+      // Special permissions like '*always deny*' - see DynamicFKAuthorizationTest.
+      // Also '@afform - see AfformUsageTest.
+      return [];
+    }
+    $implied = Civi::cache('metadata')->get('implied_permissions', []);
+    if (isset($implied[$permission])) {
+      return $implied[$permission];
+    }
+    $implied[$permission] = ['all CiviCRM permissions and ACLs'];
+    foreach (self::getImpliedAdminPermissions() as $key => $details) {
+      if (in_array($permission, $details['implied_permissions'] ?? [], TRUE)) {
+        $implied[$permission][] = $key;
       }
     }
-    return $return;
+    Civi::cache('metadata')->set('implied_permissions', $implied);
+    return $implied[$permission];
   }
 
   /**
@@ -1711,4 +1691,54 @@ class CRM_Core_Permission {
     return FALSE;
   }
 
+  /**
+   * Get permissions for components.
+   *
+   * @param bool $includeDisabled
+   *
+   * @return array
+   * @throws \CRM_Core_Exception
+   */
+  protected static function getComponentPermissions(bool $includeDisabled): array {
+    if (!$includeDisabled) {
+      $components = CRM_Core_Component::getEnabledComponents();
+    }
+    else {
+      $components = CRM_Core_Component::getComponents();
+    }
+
+    $permissions = [];
+    foreach ($components as $comp) {
+      $perm = $comp->getPermissions($includeDisabled, TRUE);
+      if ($perm) {
+        $info = $comp->getInfo();
+        foreach ($perm as $p => $attr) {
+
+          if (!is_array($attr)) {
+            $attr = [$attr];
+          }
+
+          $attr[0] = $info['translatedName'] . ': ' . $attr[0];
+          $permissions[$p] = $attr;
+        }
+      }
+    }
+    return $permissions;
+  }
+
+  /**
+   * Get permissions for core functionality and for that of core components.
+   *
+   * @param bool $all
+   *
+   * @return array
+   * @throws \CRM_Core_Exception
+   */
+  protected static function getCoreAndComponentPermissions(bool $all): array {
+    $permissions = self::getCorePermissions();
+    $permissions = array_merge($permissions, self::getComponentPermissions($all));
+    $permissions['all CiviCRM permissions and ACLs']['implied_permissions'] = array_keys($permissions);
+    return $permissions;
+  }
+
 }
index 1ceae88d7e98afe46e9e66fd25152c2e6a9291ab..60ffbe3c9ed6adc129811e0efbe3627e121560d2 100644 (file)
@@ -57,7 +57,7 @@ class CRM_Core_Permission_Base {
    *   a permission name
    */
   public function translatePermission($perm, $nativePrefix, $map) {
-    list ($civiPrefix, $name) = CRM_Utils_String::parsePrefix(':', $perm, NULL);
+    [$civiPrefix, $name] = CRM_Utils_String::parsePrefix(':', $perm, NULL);
     switch ($civiPrefix) {
       case $nativePrefix:
         return $name;
@@ -272,9 +272,12 @@ class CRM_Core_Permission_Base {
    *   The permission to check.
    * @param int $userId
    *
+   * @return bool;
+   *
    */
   public function check($str, $userId = NULL) {
     //no default behaviour
+    return FALSE;
   }
 
   /**
@@ -374,7 +377,7 @@ class CRM_Core_Permission_Base {
    *   Array of permissions, in the same format as CRM_Core_Permission::getCorePermissions().
    * @see CRM_Core_Permission::getCorePermissions
    */
-  public static function getModulePermissions($module) {
+  public function getModulePermissions($module): array {
     $return_permissions = [];
     $fn_name = "{$module}_civicrm_permission";
     if (function_exists($fn_name)) {
@@ -390,13 +393,15 @@ class CRM_Core_Permission_Base {
    * in all enabled CiviCRM module extensions.
    *
    * @param bool $descriptions
+   * @param array $permissions
    *
    * @return array
    *   Array of permissions, in the same format as CRM_Core_Permission::getCorePermissions().
    */
-  public function getAllModulePermissions($descriptions = FALSE) {
-    $permissions = [];
-    CRM_Utils_Hook::permission($permissions);
+  public function getAllModulePermissions($descriptions = FALSE, &$permissions): array {
+    $newPermissions = [];
+    CRM_Utils_Hook::permission($newPermissions, $permissions);
+    $permissions = array_merge($permissions, $newPermissions);
 
     if ($descriptions) {
       foreach ($permissions as $permission => $label) {
@@ -404,6 +409,7 @@ class CRM_Core_Permission_Base {
       }
     }
     else {
+      // Passing in false here is to be deprecated.
       foreach ($permissions as $permission => $label) {
         $permissions[$permission] = (is_array($label)) ? array_shift($label) : $label;
       }
index 2ff671fb09bcedc3a65909151ef3b9f3979bd905..d478f09b5dbc9754534fb3c5757652a720986aa2 100644 (file)
@@ -192,7 +192,7 @@ class CRM_Core_Permission_Drupal6 extends CRM_Core_Permission_DrupalBase {
    * @return array
    *   Array of permissions, in the same format as CRM_Core_Permission::getCorePermissions().
    */
-  public static function getModulePermissions($module) {
+  public function getModulePermissions($module):array {
     $return_permissions = [];
     $fn_name = "{$module}_civicrm_permission";
     if (function_exists($fn_name)) {
index 65112da464650424e1ba2cb7fdf8c2377d5ab9b3..add83a00f3378e093099787d68dbb90e3279af55 100644 (file)
@@ -109,6 +109,7 @@ class CRM_Core_Permission_Drupal8 extends CRM_Core_Permission_DrupalBase {
    * @inheritDoc
    */
   public function upgradePermissions($permissions) {
+    // @todo - this should probably call getCoreAndComponentPermissions.
     $civicrm_perms = array_keys(CRM_Core_Permission::getCorePermissions());
     if (empty($civicrm_perms)) {
       throw new CRM_Core_Exception("Cannot upgrade permissions: permission list missing");
index 90c6a675882464e97a9a7921714be77e0ee6ee2a..59bc053582bdac69c8bb83fe71689c110dee74f7 100644 (file)
@@ -1176,7 +1176,6 @@ INNER JOIN  civicrm_membership membership2 ON membership1.membership_type_id = m
    *
    * @throws \CRM_Core_Exception
    * @throws \CiviCRM_API3_Exception
-   * @throws \Exception
    */
   public static function getRowsElementsAndInfo($mainId, $otherId, $checkPermissions = TRUE) {
     $qfZeroBug = 'e8cddb72-a257-11dc-b9cc-0016d3330ee9';
index d287f8fb9d97b2118780eceee1f3729c91fe79ec..5c719c7964cd384e217f1477985de507113a8c7c 100644 (file)
@@ -80,10 +80,6 @@ class CRM_Event_BAO_Participant extends CRM_Event_DAO_Participant {
       $params['participant_fee_amount'] = CRM_Utils_Rule::cleanMoney($params['participant_fee_amount']);
     }
 
-    if (!empty($params['fee_amount'])) {
-      $params['fee_amount'] = CRM_Utils_Rule::cleanMoney($params['fee_amount']);
-    }
-
     // ensure that role ids are encoded as a string
     if (isset($params['role_id']) && is_array($params['role_id'])) {
       if (in_array(key($params['role_id']), CRM_Core_DAO::acceptedSQLOperators(), TRUE)) {
index 3ba681e456482c60bb721f2631ba505bd38a345a..c3b0dd24bf6c4e428039ba1e66ec544d9e6f9b50 100644 (file)
@@ -1120,6 +1120,11 @@ class CRM_Export_BAO_ExportProcessor {
           return $result['values'][$result['id']]['url'];
         }
 
+        // Do not export HTML markup for links
+        if ($html_type === 'Link' && $fieldValue) {
+          return $fieldValue;
+        }
+
         return CRM_Core_BAO_CustomField::displayValue($fieldValue, $cfID);
       }
       elseif (in_array($field, [
index 471a15e39416b86d7a100c94c145ffa92f07502e..a3f77a558e886c88575d7fd993128e1e98d0f2a0 100644 (file)
@@ -246,6 +246,11 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership {
    * @throws CRM_Core_Exception
    */
   public static function create(&$params, $ids = []) {
+    $isLifeTime = FALSE;
+    if (!empty($params['membership_type_id'])) {
+      $memTypeDetails = CRM_Member_BAO_MembershipType::getMembershipType($params['membership_type_id']);
+      $isLifeTime = $memTypeDetails['duration_unit'] === 'lifetime' ? TRUE : FALSE;
+    }
     // always calculate status if is_override/skipStatusCal is not true.
     // giving respect to is_override during import.  CRM-4012
 
@@ -260,7 +265,7 @@ class CRM_Member_BAO_Membership extends CRM_Member_DAO_Membership {
           // @todo enable this once core is using the api.
           // CRM_Core_Error::deprecatedWarning('Relying on the BAO to clean up dates is deprecated. Call membership create via the api');
         }
-        if (!empty($params['id']) && empty($params[$dateField])) {
+        if (!empty($params['id']) && empty($params[$dateField]) && !($isLifeTime && $dateField == 'end_date')) {
           $fieldsToLoad[] = $dateField;
         }
       }
index 1c9313c16b0f879074cac02796826bc68a3fbb7f..5b65b75372109b9e056ee880d9a3cd02117be327 100644 (file)
@@ -497,7 +497,7 @@ class CRM_Member_Form extends CRM_Contribute_Form_AbstractEditPayment {
   public function testSubmit(array $formValues): void {
     $this->exportedValues = $formValues;
     $this->setContextVariables($formValues);
-    $this->_memType = $formValues['membership_type_id'][1];
+    $this->_memType = !empty($formValues['membership_type_id']) ? $formValues['membership_type_id'][1] : NULL;
     $this->_params = $formValues;
     $this->submit();
   }
index 7829965eb575bdc2bddcb9f4f458f96cc137d5b8..99923a136a686bd6ee4706fa6be049162109e680 100644 (file)
@@ -1020,9 +1020,7 @@ DESC limit 1");
     }
 
     //take the required membership recur values.
-    if ($this->_mode && !empty($formValues['auto_renew'])) {
-      $params['is_recur'] = $formValues['is_recur'] = TRUE;
-
+    if ($this->isCreateRecurringContribution()) {
       $count = 0;
       foreach ($this->_memTypeSelected as $memType) {
         $recurMembershipTypeValues = CRM_Utils_Array::value($memType,
@@ -1065,24 +1063,7 @@ DESC limit 1");
 
     $params['contact_id'] = $this->_contactID;
 
-    $fields = [
-      'status_id',
-      'source',
-      'is_override',
-      'status_override_end_date',
-      'campaign_id',
-    ];
-
-    foreach ($fields as $f) {
-      $params[$f] = $formValues[$f] ?? NULL;
-    }
-
-    // fix for CRM-3724
-    // when is_override false ignore is_admin statuses during membership
-    // status calculation. similarly we did fix for import in CRM-3570.
-    if (empty($params['is_override'])) {
-      $params['exclude_is_admin'] = TRUE;
-    }
+    $params = array_merge($params, $this->getFormMembershipParams());
 
     $joinDate = $formValues['join_date'];
     $startDate = $formValues['start_date'];
@@ -1117,10 +1098,6 @@ DESC limit 1");
         // max related memberships - take from form or inherit from membership type
         $membershipTypeValues[$memType]['max_related'] = $formValues['max_related'] ?? NULL;
       }
-      $membershipTypeValues[$memType]['custom'] = CRM_Core_BAO_CustomField::postProcess($formValues,
-        $this->_id,
-        'Membership'
-      );
     }
 
     // Retrieve the name and email of the current user - this will be the FROM for the receipt email
@@ -1233,21 +1210,21 @@ DESC limit 1");
       // CRM-7137 -for recurring membership,
       // we do need contribution and recurring records.
       $result = NULL;
-      if (!empty($paymentParams['is_recur'])) {
+      if ($this->isCreateRecurringContribution()) {
         $this->_params = $formValues;
 
         $contribution = $this->processContribution(
           $paymentParams,
           [
             'contact_id' => $this->_contributorContactID,
-            'line_item' => $lineItem,
+            'line_item' => [$this->order->getPriceSetID() => $this->order->getLineItems()],
             'is_test' => $this->isTest(),
             'campaign_id' => $paymentParams['campaign_id'] ?? NULL,
             'source' => CRM_Utils_Array::value('source', $paymentParams, CRM_Utils_Array::value('description', $paymentParams)),
             'payment_instrument_id' => $this->getPaymentInstrumentID(),
             'financial_type_id' => $this->getFinancialTypeID(),
             'receive_date' => CRM_Utils_Time::date('YmdHis'),
-            'tax_amount' => $params['tax_amount'] ?? NULL,
+            'tax_amount' => $this->order->getTotalTaxAmount(),
             'total_amount' => $this->order->getTotalAmount(),
             'invoice_id' => $this->getInvoiceID(),
             'currency' => $this->getCurrency(),
@@ -1261,7 +1238,7 @@ DESC limit 1");
         //create new soft-credit record, CRM-13981
         if ($softParams) {
           $softParams['contribution_id'] = $contribution->id;
-          $softParams['currency'] = $contribution->currency;
+          $softParams['currency'] = $this->getCurrency();
           $softParams['amount'] = $contribution->total_amount;
           CRM_Contribute_BAO_ContributionSoft::add($softParams);
         }
@@ -1269,6 +1246,7 @@ DESC limit 1");
         $paymentParams['contactID'] = $this->_contactID;
         $paymentParams['contributionID'] = $contribution->id;
         $paymentParams['contributionRecurID'] = $contribution->contribution_recur_id;
+        $paymentParams['is_recur'] = $this->isCreateRecurringContribution();
         $params['contribution_id'] = $paymentParams['contributionID'];
         $params['contribution_recur_id'] = $paymentParams['contributionRecurID'];
       }
@@ -1347,7 +1325,7 @@ DESC limit 1");
 
         $membershipParams = array_merge($membershipTypeValues[$memType], $params);
         //CRM-15366
-        if (!empty($softParams) && empty($paymentParams['is_recur'])) {
+        if (!empty($softParams) && !$this->isCreateRecurringContribution()) {
           $membershipParams['soft_credit'] = $softParams;
         }
         if (isset($result['fee_amount'])) {
@@ -1360,7 +1338,7 @@ DESC limit 1");
         // process -
         // @see http://wiki.civicrm.org/confluence/pages/viewpage.action?pageId=261062657#Payments&AccountsRoadmap-Movetowardsalwaysusinga2-steppaymentprocess
         $membershipParams['contribution_status_id'] = $result['payment_status_id'] ?? NULL;
-        if (!empty($paymentParams['is_recur'])) {
+        if ($this->isCreateRecurringContribution()) {
           // The earlier process created the line items (although we want to get rid of the earlier one in favour
           // of a single path!
           unset($membershipParams['lineItems']);
@@ -1408,13 +1386,12 @@ DESC limit 1");
         CRM_Member_BAO_Membership::recordMembershipContribution($params);
       }
     }
-    $isRecur = $params['is_recur'] ?? NULL;
     if (($this->_action & CRM_Core_Action::UPDATE)) {
       $this->addStatusMessage($this->getStatusMessageForUpdate($membership, $endDate));
     }
     elseif (($this->_action & CRM_Core_Action::ADD)) {
       $this->addStatusMessage($this->getStatusMessageForCreate($endDate, $createdMemberships,
-        $isRecur, $calcDates));
+        $this->isCreateRecurringContribution(), $calcDates));
     }
 
     // This would always be true as we always add price set id into both
@@ -1518,7 +1495,7 @@ DESC limit 1");
     // if selected membership doesn't match with earlier membership
       !in_array($this->_memType, $this->_memTypeSelected)
     ) {
-      if (!empty($inputParams['is_recur'])) {
+      if ($this->isCreateRecurringContribution()) {
         CRM_Core_Session::setStatus(ts('Associated recurring contribution cannot be updated on membership type change.', ts('Error'), 'error'));
         return;
       }
@@ -1817,41 +1794,34 @@ DESC limit 1");
     $contributionParams
   ) {
     $contactID = $contributionParams['contact_id'];
-
-    // add these values for the recurringContrib function ,CRM-10188
-    $params['financial_type_id'] = $this->getFinancialTypeID();
-    $params['is_recur'] = TRUE;
-    $recurringContributionID = $this->legacyProcessRecurringContribution($params, $contactID);
-
-    if ($recurringContributionID) {
-      $contributionParams['contribution_recur_id'] = $recurringContributionID;
-    }
-
+    $contributionParams['contribution_recur_id'] = $this->legacyProcessRecurringContribution($params, $contactID);
     return CRM_Contribute_BAO_Contribution::add($contributionParams);
   }
 
   /**
-   * Create the recurring contribution record.
+   * Create the recurring contribution record if the form submission requires it.
    *
    * This function was copied from another form & needs cleanup.
    *
    * @param array $params
    * @param int $contactID
    *
-   * @return int
+   * @return int|null
+   * @throws \CiviCRM_API3_Exception
    */
-  protected function legacyProcessRecurringContribution(array $params, $contactID): int {
-
+  protected function legacyProcessRecurringContribution(array $params, $contactID): ?int {
+    if (!$this->isCreateRecurringContribution()) {
+      return NULL;
+    }
     $recurParams = ['contact_id' => $contactID];
-    $recurParams['amount'] = $params['amount'] ?? NULL;
+    $recurParams['amount'] = $this->order->getTotalAmount();
     $recurParams['auto_renew'] = $params['auto_renew'] ?? NULL;
     $recurParams['frequency_unit'] = $params['frequency_unit'] ?? NULL;
     $recurParams['frequency_interval'] = $params['frequency_interval'] ?? NULL;
     $recurParams['installments'] = $params['installments'] ?? NULL;
     $recurParams['financial_type_id'] = $this->getFinancialTypeID();
-    $recurParams['currency'] = $params['currency'] ?? NULL;
+    $recurParams['currency'] = $this->getCurrency();
     $recurParams['payment_instrument_id'] = $this->getPaymentInstrumentID();
-
     $recurParams['is_test'] = $this->isTest();
 
     $recurParams['start_date'] = $recurParams['create_date'] = $recurParams['modified_date'] = CRM_Utils_Time::date('YmdHis');
@@ -1876,7 +1846,7 @@ DESC limit 1");
    *
    * @return bool
    */
-  protected function isTest(): int {
+  protected function isTest(): bool {
     return ($this->_mode === 'test') ? TRUE : FALSE;
   }
 
@@ -1892,4 +1862,45 @@ DESC limit 1");
     return (int) $this->getSubmittedValue('financial_type_id') ?: $this->order->getFinancialTypeID();
   }
 
+  /**
+   * Get values that should be passed to all membership create actions.
+   *
+   * These parameters are generic to all memberships created from the form,
+   * whether a single membership or multiple by price set (although
+   * the form will not expose all in the latter case.
+   *
+   * By referencing the submitted values directly we can call this
+   * from anywhere in postProcess and get the same result (protects
+   * against breakage if code is moved around).
+   *
+   * @return array
+   */
+  protected function getFormMembershipParams(): array {
+    $submittedValues = $this->controller->exportValues($this->_name);
+    return [
+      'status_id' => $this->getSubmittedValue('status_id'),
+      'source' => $this->getSubmittedValue('source'),
+      'is_override' => $this->getSubmittedValue('is_override'),
+      'status_override_end_date' => $this->getSubmittedValue('status_override_end_date'),
+      'campaign_id' => $this->getSubmittedValue('campaign_id'),
+      'custom' => CRM_Core_BAO_CustomField::postProcess($submittedValues,
+        $this->_id,
+        'Membership'
+      ),
+      // fix for CRM-3724
+      // when is_override false ignore is_admin statuses during membership
+      // status calculation. similarly we did fix for import in CRM-3570.
+      'exclude_is_admin' => !$this->getSubmittedValue('is_override'),
+    ];
+  }
+
+  /**
+   * Is it necessary to create a recurring contribution.
+   *
+   * @return bool
+   */
+  protected function isCreateRecurringContribution(): bool {
+    return $this->_mode && $this->getSubmittedValue('auto_renew');
+  }
+
 }
index e5eec4889d7d5c08cbd82369b15adb4298613b65..773d4db9622d50b85072cdc84a6914857bb6d3f0 100644 (file)
@@ -2,3 +2,8 @@
 
 DROP VIEW IF EXISTS civicrm_view_case_activity_upcoming;
 DROP VIEW IF EXISTS civicrm_view_case_activity_recent;
+
+UPDATE civicrm_state_province s
+ INNER JOIN civicrm_country c
+   on c.id = s.country_id AND c.name = 'United Kingdom' AND s.name = 'Carmarthenshire' AND s.abbreviation = 'CRF'
+ SET s.abbreviation = 'CMN';
index d56427d86745f224519cdd5ba3d9427f30e66326..87c7361139c8039412b4c407c638980096a5b0c8 100644 (file)
@@ -145,7 +145,7 @@ class CRM_Utils_Cache_Redis implements CRM_Utils_Cache_Interface {
    */
   public function delete($key) {
     CRM_Utils_Cache::assertValidKey($key);
-    $this->_cache->delete($this->_prefix . $key);
+    $this->_cache->del($this->_prefix . $key);
     return TRUE;
   }
 
index 2c0d1958626fe36ea2832017361b5b3ba72fee3e..dc54996f1423eb42e4e474d5821cdae4d8689f1d 100644 (file)
@@ -2023,16 +2023,19 @@ abstract class CRM_Utils_Hook {
    * This hook is called when exporting Civi's permission to the CMS. Use this hook to modify
    * the array of system permissions for CiviCRM.
    *
+   * @param array $newPermissions
+   *   Array to be filled with permissions.
    * @param array $permissions
-   *   Array of permissions. See CRM_Core_Permission::getCorePermissions() for
-   *   the format of this array.
+   *   Already calculated permissions. These can be altered. Notably an
+   *   extension might want to add it's permissions to 'implied' or to
+   *   remove some permissions.
    *
    * @return null
    *   The return value is ignored
    */
-  public static function permission(&$permissions) {
-    return self::singleton()->invoke(['permissions'], $permissions,
-      self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject,
+  public static function permission(&$newPermissions, &$permissions) {
+    return self::singleton()->invoke(['permissions', 'all_permissions'], $newPermissions, $permissions,
+      self::$_nullObject, self::$_nullObject, self::$_nullObject, self::$_nullObject,
       'civicrm_permission'
     );
   }
index c6a39f03cc62e9f46efe2b65d06d4a13d919d973..acf785d201157d3de15fc3a980c61628cdbe66b9 100644 (file)
@@ -85,8 +85,7 @@ class CRM_Utils_Money {
     if ($currency === ' ') {
       CRM_Core_Error::deprecatedWarning('Passing empty currency to CRM_Utils_Money::format is deprecated if you need it for display without currency call CRM_Utils_Money::formatLocaleNumericRounded');
     }
-
-    $amount = self::formatNumericByFormat($amount);
+    $amount = self::formatUSLocaleNumericRounded($amount, 2);
     // If it contains tags, means that HTML was passed and the
     // amount is already converted properly,
     // so don't mess with it again.
@@ -184,17 +183,19 @@ class CRM_Utils_Money {
    *
    * It's not totally clear when it changes the $amount value but has historical usage.
    *
-   * @param string $amount
+   * @param string|float $amount
    * @param int $numberOfPlaces
    *
    * @return string
    */
-  protected static function formatLocaleNumericRounded($amount, $numberOfPlaces) {
-    if (!extension_loaded('intl')) {
+  protected static function formatUSLocaleNumericRounded($amount, int $numberOfPlaces): string {
+    if (!extension_loaded('intl') || !is_numeric($amount)) {
+      // @todo - we should not attempt to format non-numeric strings. For now
+      // these will not fail but will give notices on php 7.4
       self::missingIntlNotice();
       return self::formatNumericByFormat($amount, '%!.' . $numberOfPlaces . 'i');
     }
-    $money = Money::of($amount, CRM_Core_Config::singleton()->defaultCurrency, new CustomContext($numberOfPlaces), RoundingMode::CEILING);
+    $money = Money::of($amount, CRM_Core_Config::singleton()->defaultCurrency, new CustomContext($numberOfPlaces), RoundingMode::HALF_UP);
     // @todo - we specify en_US here because we don't want this function to do
     // currency replacement at the moment because
     // formatLocaleNumericRoundedByPrecision is doing it and if it
@@ -234,7 +235,7 @@ class CRM_Utils_Money {
    *   Formatted amount.
    */
   public static function formatLocaleNumericRoundedByPrecision($amount, $precision) {
-    $amount = self::formatLocaleNumericRounded($amount, $precision);
+    $amount = self::formatUSLocaleNumericRounded($amount, $precision);
     return self::replaceCurrencySeparators($amount);
   }
 
@@ -253,8 +254,8 @@ class CRM_Utils_Money {
    *   Formatted amount.
    */
   public static function formatLocaleNumericRoundedByOptionalPrecision($amount, $precision) {
-    $decimalPlaces = strlen(substr($amount, strpos($amount, '.') + 1));
-    $amount = self::formatLocaleNumericRounded($amount, $precision > $decimalPlaces ? $decimalPlaces : $precision);
+    $decimalPlaces = self::getDecimalPlacesForAmount((string) $amount);
+    $amount = self::formatUSLocaleNumericRounded($amount, $precision > $decimalPlaces ? $decimalPlaces : $precision);
     return self::replaceCurrencySeparators($amount);
   }
 
@@ -316,4 +317,16 @@ class CRM_Utils_Money {
     CRM_Core_Session::singleton()->setStatus(ts('As this system does not include the PHP intl extension, CiviCRM has fallen back onto a slightly less accurate and deprecated method to format money'), ts('Missing PHP INTL extension'));
   }
 
+  /**
+   * Get the number of characters after the decimal point.
+   *
+   * @param string $amount
+   *
+   * @return int
+   */
+  protected static function getDecimalPlacesForAmount(string $amount): int {
+    $decimalPlaces = strlen(substr($amount, strpos($amount, '.') + 1));
+    return $decimalPlaces;
+  }
+
 }
index 9341e173f9225563edb2fac410c70bfa2dcf5e2c..9c5707925cb1648c056ed64661dda82cfaa9b258 100644 (file)
@@ -625,6 +625,10 @@ class CRM_Utils_Rule {
    * @return bool
    */
   public static function boolean($value) {
+    if ($value === TRUE || $value === FALSE) {
+      return TRUE;
+    }
+    // This is intentionally not using === comparison - but will fail on FALSE.
     return preg_match(
       '/(^(1|0)$)|(^(Y(es)?|N(o)?)$)|(^(T(rue)?|F(alse)?)$)/i', $value
     ) ? TRUE : FALSE;
index 5c27f998d451fb88c75aaf7b1cb3e8b67a14932f..4be0a9588857a8696948b2b4a2d60432b4167959 100644 (file)
@@ -629,7 +629,7 @@ class CRM_Utils_System {
       );
     }
 
-    if ($key !== $siteKey) {
+    if (!hash_equals($siteKey, $key)) {
       return self::authenticateAbort(
         "ERROR: Invalid key value sent. " . $docAdd . "\n",
         $abort
index 7651aeb82392fc4d6f81bdfa3cc0a5dc4a450fd8..18637f3c1c41ed94b03bf919b6b82cb0d0a20705 100644 (file)
@@ -105,9 +105,8 @@ class CRM_Utils_System_Joomla extends CRM_Utils_System_Base {
   public function checkUserNameEmailExists(&$params, &$errors, $emailName = 'email') {
     $config = CRM_Core_Config::singleton();
 
-    $dao = new CRM_Core_DAO();
-    $name = $dao->escape(CRM_Utils_Array::value('name', $params));
-    $email = $dao->escape(CRM_Utils_Array::value('mail', $params));
+    $name = CRM_Utils_Array::value('name', $params);
+    $email = CRM_Utils_Array::value('mail', $params);
     //don't allow the special characters and min. username length is two
     //regex \\ to match a single backslash would become '/\\\\/'
     $isNotValid = (bool) preg_match('/[\<|\>|\"|\'|\%|\;|\(|\)|\&|\\\\|\/]/im', $name);
@@ -123,7 +122,7 @@ class CRM_Utils_System_Joomla extends CRM_Utils_System_Base {
     $query->from($JUserTable->getTableName());
 
     // LOWER in query below roughly translates to 'hurt my database without deriving any benefit' See CRM-19811.
-    $query->where('(LOWER(username) = LOWER(\'' . $name . '\')) OR (LOWER(email) = LOWER(\'' . $email . '\'))');
+    $query->where('(LOWER(username) = LOWER(' . $db->quote($name) . ')) OR (LOWER(email) = LOWER(' . $db->quote($email) . '))');
     $db->setQuery($query, 0, 10);
     $users = $db->loadAssocList();
 
@@ -343,7 +342,7 @@ class CRM_Utils_System_Joomla extends CRM_Utils_System_Base {
     $query = $db->getQuery(TRUE);
     $query->select('id, name, username, email, password');
     $query->from($JUserTable->getTableName());
-    $query->where('(LOWER(username) = LOWER(\'' . $name . '\')) AND (block = 0)');
+    $query->where('(LOWER(username) = LOWER(' . $db->quote($name) . ')) AND (block = 0)');
     $db->setQuery($query, 0, 0);
     $users = $db->loadObjectList();
 
index 7bb0afbe724dd7cbf1b845ce5f975c610640f180..8dd4e4bb32c53f814c2347020d5a165415ec1ff0 100644 (file)
@@ -21,27 +21,29 @@ use Civi\Api4\Generic\BasicGetAction;
  * It may be poorly suited to recursive usage (e.g. permissions defined dynamically
  * on top of permissions!) or during install/uninstall processes.
  *
- * The list of permissions is generated via hook, and there is a standard/default
- * listener.
+ * The list of permissions is generated via hook, and there is a standard/default listener.
  *
  * @see CRM_Core_Permission_List
  * @see \CRM_Utils_Hook::permissionList
  */
 class Get extends BasicGetAction {
 
-  public function getRecords() {
+  /**
+   * @return array[]
+   */
+  protected function getRecords() {
     $cacheKey = 'list_' . $GLOBALS['tsLocale'];
     if (!isset(\Civi::$statics[__CLASS__][$cacheKey])) {
       $perms = [];
       \CRM_Utils_Hook::permissionList($perms);
-      foreach (array_keys($perms) as $permName) {
+      foreach ($perms as $permName => $permission) {
         $defaults = [
           'name' => $permName,
           'group' => 'unknown',
           'is_synthetic' => ($permName[0] === '@'),
           'is_active' => TRUE,
         ];
-        $perms[$permName] = array_merge($defaults, $perms[$permName]);
+        $perms[$permName] = array_merge($defaults, $permission);
       }
       \Civi::$statics[__CLASS__][$cacheKey] = $perms;
     }
index 055eb72370715efab6280adaa71535b4ac731e2a..778cc3de40b71bbaa387febff1ee0edb95fd66d3 100644 (file)
@@ -164,16 +164,16 @@ class DAOGetAction extends AbstractGetAction {
 
   /**
    * @param string $entity
-   * @param bool $required
+   * @param string|bool $type
    * @param string $bridge
    * @param array ...$conditions
    * @return DAOGetAction
    */
-  public function addJoin(string $entity, bool $required = FALSE, $bridge = NULL, ...$conditions): DAOGetAction {
+  public function addJoin(string $entity, $type = 'LEFT', $bridge = NULL, ...$conditions): DAOGetAction {
     if ($bridge) {
       array_unshift($conditions, $bridge);
     }
-    array_unshift($conditions, $entity, $required);
+    array_unshift($conditions, $entity, $type);
     $this->join[] = $conditions;
     return $this;
   }
index 8f5f3e5fdd730d1aa89f473f53aefa991fbaacae..95a63bc9ea24af3080a629083f66c537e0b00b1a 100644 (file)
@@ -32,10 +32,11 @@ class Permission extends Generic\AbstractEntity {
 
   /**
    * @param bool $checkPermissions
-   * @return \Civi\Api4\Generic\BasicGetAction
+   * @return Action\Permission\Get
    */
   public static function get($checkPermissions = TRUE) {
-    return (new \Civi\Api4\Action\Permission\Get(__CLASS__, __FUNCTION__))->setCheckPermissions($checkPermissions);
+    return (new Action\Permission\Get(__CLASS__, __FUNCTION__))
+      ->setCheckPermissions($checkPermissions);
   }
 
   /**
@@ -48,31 +49,26 @@ class Permission extends Generic\AbstractEntity {
         [
           'name' => 'group',
           'title' => 'Group',
-          'required' => TRUE,
           'data_type' => 'String',
         ],
         [
           'name' => 'name',
           'title' => 'Name',
-          'required' => TRUE,
           'data_type' => 'String',
         ],
         [
           'name' => 'title',
           'title' => 'Title',
-          'required' => TRUE,
           'data_type' => 'String',
         ],
         [
           'name' => 'description',
           'title' => 'Description',
-          'required' => FALSE,
           'data_type' => 'String',
         ],
         [
           'name' => 'is_synthetic',
           'title' => 'Is Synthetic',
-          'required' => FALSE,
           'data_type' => 'Boolean',
         ],
         [
@@ -80,7 +76,6 @@ class Permission extends Generic\AbstractEntity {
           'title' => 'Is Active',
           'description' => '',
           'default' => TRUE,
-          'required' => FALSE,
           'data_type' => 'Boolean',
         ],
       ];
index 411802b91a069280809d3de437214926baa45e5b..efaba5c29645878f93b87fc652f01e1e9d9dbb54 100644 (file)
@@ -595,7 +595,18 @@ class Api4SelectQuery {
       $alias = $alias ? \CRM_Utils_String::munge($alias, '_', 256) : strtolower($entity);
       // First item in the array is a boolean indicating if the join is required (aka INNER or LEFT).
       // The rest are join conditions.
-      $side = array_shift($join) ? 'INNER' : 'LEFT';
+      $side = array_shift($join);
+      // If omitted, supply default (LEFT); and legacy support for boolean values
+      if (!is_string($side)) {
+        $side = $side ? 'INNER' : 'LEFT';
+      }
+      if (!in_array($side, ['INNER', 'LEFT', 'EXCLUDE'])) {
+        throw new \API_Exception("Illegal value for join side: '$side'.");
+      }
+      if ($side === 'EXCLUDE') {
+        $side = 'LEFT';
+        $this->api->addWhere("$alias.id", 'IS NULL');
+      }
       // Add all fields from joined entity to spec
       $joinEntityGet = \Civi\API\Request::create($entity, 'get', ['version' => 4, 'checkPermissions' => $this->getCheckPermissions()]);
       $joinEntityFields = $joinEntityGet->entityFields();
@@ -613,15 +624,15 @@ class Api4SelectQuery {
       // If the first condition is a string, it's the name of a bridge entity
       if (!empty($join[0]) && is_string($join[0]) && \CRM_Utils_Rule::alphanumeric($join[0])) {
         $this->explicitJoins[$alias]['bridge'] = $join[0];
-        $conditions = $this->getBridgeJoin($join, $entity, $alias);
+        $this->addBridgeJoin($join, $entity, $alias, $side);
       }
       else {
         $conditions = $this->getJoinConditions($join, $entity, $alias, $joinEntityFields);
+        foreach (array_filter($join) as $clause) {
+          $conditions[] = $this->treeWalkClauses($clause, 'ON');
+        }
+        $this->join($side, $tableName, $alias, $conditions);
       }
-      foreach (array_filter($join) as $clause) {
-        $conditions[] = $this->treeWalkClauses($clause, 'ON');
-      }
-      $this->join($side, $tableName, $alias, $conditions);
     }
   }
 
@@ -680,17 +691,67 @@ class Api4SelectQuery {
    *
    * This creates a double-join in sql that appears to the API user like a single join.
    *
+   * LEFT joins use a subquery so that the bridge + joined-entity can be treated like a single table.
+   *
    * @param array $joinTree
    * @param string $joinEntity
    * @param string $alias
-   * @return array
+   * @param string $side
    * @throws \API_Exception
    */
-  protected function getBridgeJoin(&$joinTree, $joinEntity, $alias) {
+  protected function addBridgeJoin($joinTree, $joinEntity, $alias, $side) {
     $bridgeEntity = array_shift($joinTree);
+
+    // INNER joins require unique aliases, whereas left joins will be inside a subquery and short aliases are more readable
+    $bridgeAlias = $side === 'INNER' ? $alias . '_via_' . strtolower($bridgeEntity) : 'b';
+    $joinAlias = $side === 'INNER' ? $alias : 'c';
+
+    $joinTable = CoreUtil::getTableName($joinEntity);
+    [$bridgeTable, $baseRef, $joinRef] = $this->getBridgeRefs($bridgeEntity, $joinEntity);
+
+    $bridgeFields = $this->registerBridgeJoinFields($bridgeEntity, $joinRef, $baseRef, $alias, $bridgeAlias, $side);
+
+    $linkConditions = $this->getBridgeLinkConditions($bridgeAlias, $joinAlias, $joinTable, $joinRef);
+
+    $bridgeConditions = $this->getBridgeJoinConditions($joinTree, $baseRef, $alias, $bridgeAlias, $bridgeEntity, $side);
+
+    $acls = array_values($this->getAclClause($joinAlias, CoreUtil::getBAOFromApiName($joinEntity), [NULL, NULL]));
+
+    $joinConditions = [];
+    foreach (array_filter($joinTree) as $clause) {
+      $joinConditions[] = $this->treeWalkClauses($clause, 'ON');
+    }
+
+    // INNER joins are done with 2 joins
+    if ($side === 'INNER') {
+      $this->join('INNER', $bridgeTable, $bridgeAlias, $bridgeConditions);
+      $this->join('INNER', $joinTable, $alias, array_merge($linkConditions, $acls, $joinConditions));
+    }
+    // For LEFT joins, construct a subquery to link the bridge & join tables as one
+    else {
+      $joinEntityClass = '\Civi\Api4\\' . $joinEntity;
+      foreach ($joinEntityClass::get($this->getCheckPermissions())->entityFields() as $name => $field) {
+        $bridgeFields[$field['column_name']] = '`' . $joinAlias . '`.`' . $field['column_name'] . '`';
+      }
+      $select = implode(',', $bridgeFields);
+      $joinConditions = array_merge($joinConditions, $bridgeConditions);
+      $innerConditions = array_merge($linkConditions, $acls);
+      $subquery = "SELECT $select FROM `$bridgeTable` `$bridgeAlias`, `$joinTable` `$joinAlias` WHERE " . implode(' AND ', $innerConditions);
+      $this->query->join($alias, "$side JOIN ($subquery) `$alias` ON " . implode(' AND ', $joinConditions));
+    }
+  }
+
+  /**
+   * Get the table name and 2 reference columns from a bridge entity
+   *
+   * @param string $bridgeEntity
+   * @param string $joinEntity
+   * @return array
+   * @throws \API_Exception
+   */
+  private function getBridgeRefs(string $bridgeEntity, string $joinEntity): array {
     /* @var \Civi\Api4\Generic\DAOEntity $bridgeEntityClass */
     $bridgeEntityClass = '\Civi\Api4\\' . $bridgeEntity;
-    $bridgeAlias = $alias . '_via_' . strtolower($bridgeEntity);
     $bridgeInfo = $bridgeEntityClass::getInfo();
     $bridgeFields = $bridgeInfo['bridge'] ?? [];
     // Sanity check - bridge entity should declare exactly 2 FK fields
@@ -701,8 +762,6 @@ class Api4SelectQuery {
     $bridgeDAO = $bridgeInfo['dao'];
     $bridgeTable = $bridgeDAO::getTableName();
 
-    $joinTable = CoreUtil::getTableName($joinEntity);
-    $bridgeEntityGet = $bridgeEntityClass::get($this->getCheckPermissions());
     // Get the 2 bridge reference columns as CRM_Core_Reference_* objects
     $joinRef = $baseRef = NULL;
     foreach ($bridgeDAO::getReferenceColumns() as $ref) {
@@ -718,29 +777,74 @@ class Api4SelectQuery {
     if (!$joinRef || !$baseRef) {
       throw new \API_Exception("Unable to join $bridgeEntity to $joinEntity");
     }
-    // Create link between bridge entity and join entity
-    $joinConditions = [
-      "`$bridgeAlias`.`{$joinRef->getReferenceKey()}` = `$alias`.`{$joinRef->getTargetKey()}`",
+    return [$bridgeTable, $baseRef, $joinRef];
+  }
+
+  /**
+   * Get the clause to link bridge entity with join entity
+   *
+   * @param string $bridgeAlias
+   * @param string $joinAlias
+   * @param string $joinTable
+   * @param $joinRef
+   * @return array
+   */
+  private function getBridgeLinkConditions(string $bridgeAlias, string $joinAlias, string $joinTable, $joinRef): array {
+    $linkConditions = [
+      "`$bridgeAlias`.`{$joinRef->getReferenceKey()}` = `$joinAlias`.`{$joinRef->getTargetKey()}`",
     ];
     // For dynamic references, also add the type column (e.g. `entity_table`)
     if ($joinRef->getTypeColumn()) {
-      $joinConditions[] = "`$bridgeAlias`.`{$joinRef->getTypeColumn()}` = '$joinTable'";
+      $linkConditions[] = "`$bridgeAlias`.`{$joinRef->getTypeColumn()}` = '$joinTable'";
     }
-    // Register fields (other than bridge FK fields) from the bridge entity as if they belong to the join entity
+    return $linkConditions;
+  }
+
+  /**
+   * Register fields (other than bridge FK fields) from the bridge entity as if they belong to the join entity
+   *
+   * @param $bridgeEntity
+   * @param $joinRef
+   * @param $baseRef
+   * @param string $alias
+   * @param string $bridgeAlias
+   * @param string $side
+   * @return array
+   */
+  private function registerBridgeJoinFields($bridgeEntity, $joinRef, $baseRef, string $alias, string $bridgeAlias, string $side): array {
     $fakeFields = [];
-    foreach ($bridgeEntityGet->entityFields() as $name => $field) {
-      if ($name === 'id' || $name === $joinRef->getReferenceKey() || $name === $joinRef->getTypeColumn() || $name === $baseRef->getReferenceKey() || $name === $baseRef->getTypeColumn()) {
+    $bridgeFkFields = [$joinRef->getReferenceKey(), $joinRef->getTypeColumn(), $baseRef->getReferenceKey(), $baseRef->getTypeColumn()];
+    $bridgeEntityClass = '\Civi\Api4\\' . $bridgeEntity;
+    foreach ($bridgeEntityClass::get($this->getCheckPermissions())->entityFields() as $name => $field) {
+      if ($name === 'id' || ($side === 'INNER' && in_array($name, $bridgeFkFields, TRUE))) {
         continue;
       }
-      // Note these fields get a sql alias pointing to the bridge entity, but an api alias pretending they belong to the join entity
-      $field['sql_name'] = '`' . $bridgeAlias . '`.`' . $field['column_name'] . '`';
-      $this->addSpecField($alias . '.' . $field['name'], $field);
-      $fakeFields[] = $alias . '.' . $field['name'];
+      // For INNER joins, these fields get a sql alias pointing to the bridge entity,
+      // but an api alias pretending they belong to the join entity.
+      $field['sql_name'] = '`' . ($side === 'LEFT' ? $alias : $bridgeAlias) . '`.`' . $field['column_name'] . '`';
+      $this->addSpecField($alias . '.' . $name, $field);
+      $fakeFields[$field['column_name']] = '`' . $bridgeAlias . '`.`' . $field['column_name'] . '`';
     }
-    // Move conditions for the bridge join out of the joinTree
+    return $fakeFields;
+  }
+
+  /**
+   * Extract bridge join conditions from the joinTree if any, else supply default conditions for join to base entity
+   *
+   * @param array $joinTree
+   * @param $baseRef
+   * @param string $alias
+   * @param string $bridgeAlias
+   * @param string $bridgeEntity
+   * @param string $side
+   * @return string[]
+   * @throws \API_Exception
+   */
+  private function getBridgeJoinConditions(array &$joinTree, $baseRef, string $alias, string $bridgeAlias, string $bridgeEntity, string $side): array {
     $bridgeConditions = [];
-    $isExplicit = FALSE;
-    $joinTree = array_filter($joinTree, function($clause) use ($baseRef, $alias, $bridgeAlias, $fakeFields, &$bridgeConditions, &$isExplicit) {
+    $bridgeAlias = $side === 'INNER' ? $bridgeAlias : $alias;
+    // Find explicit bridge join conditions and move them out of the joinTree
+    $joinTree = array_filter($joinTree, function ($clause) use ($baseRef, $alias, $bridgeAlias, &$bridgeConditions) {
       list($sideA, $op, $sideB) = array_pad((array) $clause, 3, NULL);
       // Skip AND/OR/NOT branches
       if (!$sideB) {
@@ -750,27 +854,18 @@ class Api4SelectQuery {
       if ($op === '=' && $sideB && ($sideA === "$alias.{$baseRef->getReferenceKey()}" || $sideB === "$alias.{$baseRef->getReferenceKey()}")) {
         $expr = $sideA === "$alias.{$baseRef->getReferenceKey()}" ? $sideB : $sideA;
         $bridgeConditions[] = "`$bridgeAlias`.`{$baseRef->getReferenceKey()}` = " . $this->getExpression($expr)->render($this->apiFieldSpec);
-        $isExplicit = TRUE;
         return FALSE;
       }
       // Explicit link with dynamic "entity_table" column
       elseif ($op === '=' && $baseRef->getTypeColumn() && ($sideA === "$alias.{$baseRef->getTypeColumn()}" || $sideB === "$alias.{$baseRef->getTypeColumn()}")) {
         $expr = $sideA === "$alias.{$baseRef->getTypeColumn()}" ? $sideB : $sideA;
         $bridgeConditions[] = "`$bridgeAlias`.`{$baseRef->getTypeColumn()}` = " . $this->getExpression($expr)->render($this->apiFieldSpec);
-        $isExplicit = TRUE;
         return FALSE;
       }
-      // Other conditions that apply only to the bridge table should be
-      foreach ([$sideA, $sideB] as $expr) {
-        if (is_string($expr) && in_array(explode(':', $expr)[0], $fakeFields)) {
-          $bridgeConditions[] = $this->composeClause($clause, 'ON');
-          return FALSE;
-        }
-      }
       return TRUE;
     });
     // If no bridge conditions were specified, link it to the base entity
-    if (!$isExplicit) {
+    if (!$bridgeConditions) {
       if (!in_array($this->getEntity(), $baseRef->getTargetEntities())) {
         throw new \API_Exception("Unable to join $bridgeEntity to " . $this->getEntity());
       }
@@ -779,12 +874,7 @@ class Api4SelectQuery {
         $bridgeConditions[] = "`$bridgeAlias`.`{$baseRef->getTypeColumn()}` = '" . $this->getFrom() . "'";
       }
     }
-
-    $this->join('LEFT', $bridgeTable, $bridgeAlias, $bridgeConditions);
-
-    $baoName = CoreUtil::getBAOFromApiName($joinEntity);
-    $acls = array_values($this->getAclClause($alias, $baoName, [NULL, NULL]));
-    return array_merge($acls, $joinConditions);
+    return $bridgeConditions;
   }
 
   /**
index 6681b645ecfb6294485ddfc40fb948f20a71cb2c..b6b095bf10914e9bea0dae878956d08e16467736 100644 (file)
@@ -33,14 +33,13 @@ class Route extends \Civi\Api4\Generic\AbstractEntity {
 
   /**
    * @param bool $checkPermissions
-   * @return \Civi\Api4\Generic\BasicGetAction
+   * @return Generic\BasicGetAction
    */
   public static function get($checkPermissions = TRUE) {
-    return (new \Civi\Api4\Generic\BasicGetAction(__CLASS__, __FUNCTION__, function ($get) {
-      // Pulling from ::items() rather than DB -- because it provides the final/live/altered data.
-      $items = \CRM_Core_Menu::items();
+    return (new Generic\BasicGetAction(__CLASS__, __FUNCTION__, function ($get) {
       $result = [];
-      foreach ($items as $path => $item) {
+      // Pulling from ::items() rather than DB -- because it provides the final/live/altered data.
+      foreach (\CRM_Core_Menu::items() as $path => $item) {
         $result[] = ['path' => $path] + $item;
       }
       return $result;
@@ -57,37 +56,31 @@ class Route extends \Civi\Api4\Generic\AbstractEntity {
         [
           'name' => 'path',
           'title' => 'Relative Path',
-          'required' => TRUE,
           'data_type' => 'String',
         ],
         [
           'name' => 'title',
           'title' => 'Page Title',
-          'required' => TRUE,
           'data_type' => 'String',
         ],
         [
           'name' => 'page_callback',
           'title' => 'Page Callback',
-          'required' => TRUE,
           'data_type' => 'String',
         ],
         [
           'name' => 'page_arguments',
           'title' => 'Page Arguments',
-          'required' => FALSE,
           'data_type' => 'String',
         ],
         [
           'name' => 'path_arguments',
           'title' => 'Path Arguments',
-          'required' => FALSE,
           'data_type' => 'String',
         ],
         [
           'name' => 'access_arguments',
           'title' => 'Access Arguments',
-          'required' => FALSE,
           'data_type' => 'Array',
         ],
       ];
index 510ff78826c662b13252afb11472199af178a53d..d77de0ed1d4797227fdd3b513a62cf3ab001e716 100644 (file)
@@ -60,7 +60,7 @@ class CustomGroupJoinable extends Joinable {
     $entityFields = (array) \Civi::cache('metadata')->get($cacheKey);
     if (!$entityFields) {
       $fields = CustomField::get(FALSE)
-        ->setSelect(['custom_group.name', 'custom_group.extends', 'custom_group.table_name', '*'])
+        ->setSelect(['custom_group.name', 'custom_group.extends', 'custom_group.table_name', 'custom_group.title', '*'])
         ->addWhere('custom_group.table_name', '=', $this->getTargetTable())
         ->execute();
       foreach ($fields as $field) {
index dad0c20caaad7493f1eccb8281babcbd1c94382a..341ab2bbd16ce8dba54a325281533740e5f59cfa 100644 (file)
@@ -63,7 +63,8 @@ class SpecFormatter {
       $field->setColumnName($data['column_name']);
       $field->setCustomFieldId($data['id'] ?? NULL);
       $field->setCustomGroupName($data['custom_group.name']);
-      $field->setTitle($data['label'] ?? NULL);
+      $field->setTitle($data['label']);
+      $field->setLabel($data['custom_group.title'] . ': ' . $data['label']);
       $field->setHelpPre($data['help_pre'] ?? NULL);
       $field->setHelpPost($data['help_post'] ?? NULL);
       $field->setOptions(self::customFieldHasOptions($data));
index 5eda054230d9614e358d65ba44c0af336c6dd6d4..ef9954f20c305ce455618aebf16a1bfb9999ecde 100644 (file)
@@ -132,7 +132,7 @@ class SpecGatherer {
     $customFields = CustomField::get(FALSE)
       ->addWhere('custom_group.extends', 'IN', $extends)
       ->addWhere('custom_group.is_multiple', '=', '0')
-      ->setSelect(['custom_group.name', '*'])
+      ->setSelect(['custom_group.name', 'custom_group.title', '*'])
       ->execute();
 
     foreach ($customFields as $fieldArray) {
@@ -148,7 +148,7 @@ class SpecGatherer {
   private function getCustomGroupFields($customGroup, RequestSpec $specification) {
     $customFields = CustomField::get(FALSE)
       ->addWhere('custom_group.name', '=', $customGroup)
-      ->setSelect(['custom_group.name', 'custom_group.table_name', '*'])
+      ->setSelect(['custom_group.name', 'custom_group.table_name', 'custom_group.title', '*'])
       ->execute();
 
     foreach ($customFields as $fieldArray) {
index 2f7ad0eb148dbd77ce2e62fce46c166af1f6cddf..f28cec6dbe9bc5d297f0bc494cacf38b6a6af003 100644 (file)
@@ -5,8 +5,8 @@
     {{:: ts('CiviCRM APIv4') }}{{ entity ? (' (' + entity + '::' + action + ')') : '' }}
   </h1>
 
-  <div class="api4-explorer-row">
-      <form name="api4-explorer" class="panel panel-default explorer-params-panel">
+  <div class="api4-explorer-row crm-flex-box">
+      <form name="api4-explorer" class="panel panel-default explorer-params-panel crm-flex-2">
         <div class="panel-heading">
           <div class="form-inline">
             <span ng-mouseenter="help('entity', paramDoc('$entity'))" ng-mouseleave="help()">
         </div>
       </div>
   </div>
-  <div class="api4-explorer-row">
+  <div class="api4-explorer-row crm-flex-box">
       <div class="panel panel-info explorer-code-panel">
         <ul class="panel-heading nav nav-tabs">
           <li role="presentation" ng-repeat="lang in ::langs" ng-class="{active: selectedTab.code === lang}">
index 7def6e386f46d516b366f647dd8e797e9cf35a14..f1918b7e40c8df2c8dd82978f8b90616f45ff277 100644 (file)
@@ -56,7 +56,7 @@
     $scope.loading = false;
     $scope.controls = {};
     $scope.langs = ['php', 'js', 'ang', 'cli'];
-    $scope.joinTypes = [{k: false, v: 'FALSE (LEFT JOIN)'}, {k: true, v: 'TRUE (INNER JOIN)'}];
+    $scope.joinTypes = [{k: 'LEFT', v: 'LEFT JOIN'}, {k: 'INNER', v: 'INNER JOIN'}, {k: 'EXCLUDE', v: 'EXCLUDE'}];
     $scope.bridgeEntities = _.filter(schema, function(entity) {return _.includes(entity.type, 'EntityBridge');});
     $scope.code = {
       php: [
       $scope.helpContent = helpContent = formatHelp(content);
     }
 
-    // Convert plain-text help to markdown; replace variables and format links
+    // Format help text with markdown; replace variables and format links
     function formatHelp(rawContent) {
       function formatRefs(see) {
         _.each(see, function(ref, idx) {
-          var match = ref.match(/^\\Civi\\Api4\\([a-zA-Z]+)$/);
+          var match = ref.match(/^(\\Civi\\Api4\\)?([a-zA-Z]+)$/);
           if (match) {
-            ref = '#/explorer/' + match[1];
+            ref = '#/explorer/' + match[2];
           }
-          if (ref[0] === '\\') {
-            ref = 'https://github.com/civicrm/civicrm-core/blob/master' + ref.replace(/\\/i, '/') + '.php';
+          // Link to php classes on GitHub.
+          // Fixme: Only works for files in the core repo
+          if (ref[0] === '\\' || ref.indexOf('Civi\\') === 0 || ref.indexOf('CRM_') === 0) {
+            var classFunction = _.trim(ref, '\\').split('::'),
+              replacement = new RegExp(classFunction[0].indexOf('CRM_') === 0 ? '_' : '\\\\', 'g');
+            ref = 'https://github.com/civicrm/civicrm-core/blob/master/' + classFunction[0].replace(replacement, '/') + '.php';
           }
           see[idx] = '<a target="' + (ref[0] === '#' ? '_self' : '_blank') + '" href="' + ref + '">' + see[idx] + '</a>';
         });
               $timeout(function() {
                 if (field) {
                   if (name === 'join') {
-                    $scope.params[name].push([field + ' AS ' + _.snakeCase(field), false]);
+                    $scope.params[name].push([field + ' AS ' + _.snakeCase(field), 'LEFT']);
                     ctrl.buildFieldList();
                   }
                   else if (typeof objectParams[name] === 'undefined') {
       }
       _.each($scope.code, function(vals) {
         _.each(vals, function(style) {
-          style.code = code[style.name] ? prettyPrintOne(code[style.name]) : '';
+          style.code = code[style.name] ? prettyPrintOne(_.escape(code[style.name])) : '';
         });
       });
     }
index 6232fd202853b464d4a21a4d2dbd308c60ed6db7..c7a3b1d5e478cba39c8a0fc6575f83f75a370d92 100644 (file)
@@ -281,12 +281,14 @@ function _civicrm_api3_membership_relationsship_get_customv2behaviour(&$params,
   $relationships = [];
   foreach ($membershipValues as $membershipId => $values) {
     // populate the membership type name for the membership type id
-    $membershipType = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($values['membership_type_id']);
+    $membershipType = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($values['membership_type_id']) ?? [];
 
-    $membershipValues[$membershipId]['membership_name'] = $membershipType['name'];
+    if (!empty($membershipType)) {
+      $membershipValues[$membershipId]['membership_name'] = $membershipType['name'];
 
-    if (!empty($membershipType['relationship_type_id'])) {
-      $relationships[$membershipType['relationship_type_id']] = $membershipId;
+      if (!empty($membershipType['relationship_type_id'])) {
+        $relationships[$membershipType['relationship_type_id']] = $membershipId;
+      }
     }
 
     // populating relationship type name.
index cd21534faa05b0e840410a025ba079fa67f6aeee..604bf273ce73e85cb20d3ae17f694154168cbab8 100644 (file)
@@ -84,7 +84,8 @@
     "ext-intl": "*",
     "pear/mail_mime": "~1.10",
     "pear/db": "1.10",
-    "civicrm/composer-compile-lib": "~0.3 || ~1.0"
+    "civicrm/composer-compile-lib": "~0.3 || ~1.0",
+    "ext-json": "*"
   },
   "scripts": {
     "post-install-cmd": [
         "path": "bower_components/{$id}"
       },
       "angular": {
-        "url": "https://github.com/angular/bower-angular/archive/v1.8.0.zip"
+        "url": "https://github.com/angular/bower-angular/archive/v1.8.2.zip"
       },
       "angular-bootstrap": {
         "url": "https://github.com/angular-ui/bootstrap-bower/archive/2.5.0.zip"
index b8e248fbf55f227dd74db227a01bbbef1a6711b9..46df527f7d80c8de97115938d297b2a89c7a9532 100644 (file)
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "2d1dfc8bddd169a9064a89c693bb5218",
+    "content-hash": "ec5c7533d5c9d49d54530eb94958e55b",
     "packages": [
         {
             "name": "adrienrn/php-mimetyper",
         },
         {
             "name": "brick/math",
-            "version": "0.8.15",
+            "version": "0.9.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/brick/math.git",
-                "reference": "9b08d412b9da9455b210459ff71414de7e6241cd"
+                "reference": "dff976c2f3487d42c1db75a3b180e2b9f0e72ce0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/brick/math/zipball/9b08d412b9da9455b210459ff71414de7e6241cd",
-                "reference": "9b08d412b9da9455b210459ff71414de7e6241cd",
+                "url": "https://api.github.com/repos/brick/math/zipball/dff976c2f3487d42c1db75a3b180e2b9f0e72ce0",
+                "reference": "dff976c2f3487d42c1db75a3b180e2b9f0e72ce0",
                 "shasum": ""
             },
             "require": {
                 "ext-json": "*",
-                "php": "^7.1|^8.0"
+                "php": "^7.1 || ^8.0"
             },
             "require-dev": {
                 "php-coveralls/php-coveralls": "^2.2",
-                "phpunit/phpunit": "^7.5.15|^8.5",
-                "vimeo/psalm": "^3.5"
+                "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.0",
+                "vimeo/psalm": "4.3.2"
             },
             "type": "library",
             "autoload": {
                 "brick",
                 "math"
             ],
-            "time": "2020-04-15T15:59:35+00:00"
+            "funding": [
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/brick/math",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2021-01-20T22:51:39+00:00"
         },
         {
             "name": "brick/money",
-            "version": "0.4.5",
+            "version": "0.5.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/brick/money.git",
-                "reference": "91f2b5bc35646f172b038e46bb496ad18db59c3c"
+                "reference": "c6f2883c8a759bf7f77c79aaa6004af6d6c0afaf"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/brick/money/zipball/91f2b5bc35646f172b038e46bb496ad18db59c3c",
-                "reference": "91f2b5bc35646f172b038e46bb496ad18db59c3c",
+                "url": "https://api.github.com/repos/brick/money/zipball/c6f2883c8a759bf7f77c79aaa6004af6d6c0afaf",
+                "reference": "c6f2883c8a759bf7f77c79aaa6004af6d6c0afaf",
                 "shasum": ""
             },
             "require": {
-                "brick/math": "~0.7.3 || ~0.8.0",
-                "php": "^7.1|^8.0"
+                "brick/math": "~0.7.3 || ~0.8.0 || ~0.9.0",
+                "php": "^7.1 || ^8.0"
             },
             "require-dev": {
                 "brick/varexporter": "~0.2.1",
                 "ext-dom": "*",
                 "ext-pdo": "*",
                 "php-coveralls/php-coveralls": "^2.2",
-                "phpunit/phpunit": "^7.5.15"
+                "phpunit/phpunit": "^7.5.15 || ^8.0 || ^9.0",
+                "vimeo/psalm": "4.3.2"
             },
             "suggest": {
                 "ext-intl": "Required to format Money objects"
                 "currency",
                 "money"
             ],
-            "time": "2020-05-31T14:17:02+00:00"
+            "funding": [
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/brick/money",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2021-02-10T14:14:29+00:00"
         },
         {
             "name": "cache/integration-tests",
                 "portable",
                 "shim"
             ],
-            "funding": [
-                {
-                    "url": "https://symfony.com/sponsor",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/fabpot",
-                    "type": "github"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
-                    "type": "tidelift"
-                }
-            ],
             "time": "2020-05-12T16:47:27+00:00"
         },
         {
index 092f6215d36bc9217c74bc00fa3266e80fcd3a03..d2bd35064775f4d933863347e2a025e97f421539 100644 (file)
 #bootstrap-theme .explorer-params-panel .panel-heading .form-inline > .select2-container {
   max-width: 25% !important;
 }
-#bootstrap-theme.api4-explorer-page .api4-explorer-row {
-  display: flex;
-}
-#bootstrap-theme.api4-explorer-page > div > .panel {
-  flex: 1;
+#bootstrap-theme .api4-explorer-row > .panel {
   margin: 10px;
   min-height: 500px;
 }
-#bootstrap-theme.api4-explorer-page > div > form.panel {
-  flex: 2;
-}
 /* Fix weird shorditch style */
 #bootstrap-theme.api4-explorer-page .api4-explorer-row .panel .panel-heading {
   border-bottom-right-radius: 0;
index 9a4ae97a4e6c79e57ac5cb80dd760a422baa118f..0114b041321b0d8045c6725a35b81d400ade7960 100644 (file)
   flex-wrap: wrap;
   box-sizing: border-box;
 }
-.crm-container .crm-flex-box > * {
+.crm-flex-box > * {
   flex: 1;
   box-sizing: border-box;
   min-width: 0; /* prevents getting squashed by whitespace:nowrap content */
 }
-.crm-container .crm-flex-box > .crm-flex-2 {
+.crm-container .crm-flex-1 {
+  flex: 1;
+}
+.crm-container .crm-flex-2 {
   flex: 2;
 }
-.crm-container .crm-flex-box > .crm-flex-3 {
+.crm-container .crm-flex-3 {
   flex: 3;
 }
-.crm-container .crm-flex-box > .crm-flex-4 {
+.crm-container .crm-flex-4 {
   flex: 4;
 }
-.crm-container .crm-flex-box > .crm-flex-5 {
+.crm-container .crm-flex-5 {
   flex: 5;
 }
 
@@ -3358,6 +3361,9 @@ span.crm-select-item-color {
 }
 .crm-container span.crm-editable-enabled {
   display: inline-block !important;
+  padding-right: 2px;
+  min-height: 1em;
+  min-width: 3em;
 }
 
 .crm-container .crm-editable-enabled .crm-i {
index 5367d1cbc44bebb43dd25260ced0bf38c0b50f82..5a77a2f1ba260dd7876f9c729d4eb3e0ca497614 100644 (file)
@@ -65,6 +65,8 @@ function generateJoomlaConfig($version) {
 
   $crmFolderDir = $sourceCheckoutDir . DIRECTORY_SEPARATOR . 'CRM';
 
+  // @todo call getCoreAndComponentPermissions instead and let that
+  // do the work of these next 15-20 lines.
   require_once 'CRM/Core/Component.php';
   $components = CRM_Core_Component::getComponentsFromFile($crmFolderDir);
   foreach ($components as $comp) {
index 46acccdc8ff4272867cc47bb8e5153f7c3c289b0..4b834f5c7436f4866ca6ba0598f34149cb612644 100644 (file)
   <p class="help-block">{{ts('The general look/feel should match the frontend')}}</p>
 </div>
 
+<div class="form-group" ng-if="!!afform.server_route">
+  <label for="af_config_form_is_token">
+    <input type="checkbox" id="af_config_form_is_token" ng-model="afform.is_token">
+    {{:: ts('Enable email token') }}
+  </label>
+  <p class="help-block">{{ts('Allow email authors to easily link to this form')}}</p>
+</div>
+
 <div class="form-group">
   <label for="af_config_form_is_dashlet">
     <input type="checkbox" id="af_config_form_is_dashlet" ng-model="afform.is_dashlet">
index e524a3f1f9146667d563aba7ded5c30c181822a1..f4e4bd86340411b605156da3980ba9115997b07e 100644 (file)
@@ -134,6 +134,7 @@ class CRM_Afform_AfformScanner {
       'description' => '',
       'is_dashlet' => FALSE,
       'is_public' => FALSE,
+      'is_token' => FALSE,
       'permission' => 'access CiviCRM',
       'type' => 'system',
     ];
diff --git a/ext/afform/core/Civi/Afform/StatusChecks.php b/ext/afform/core/Civi/Afform/StatusChecks.php
new file mode 100644 (file)
index 0000000..c1a7d7c
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+namespace Civi\Afform;
+
+use CRM_Afform_ExtensionUtil as E;
+
+class StatusChecks {
+
+  /**
+   * Afform has a soft dependency on Authx, which is used to generate authenticated email links.
+   *
+   * @param \Civi\Core\Event\GenericHookEvent $e
+   * @see CRM_Utils_Hook::check()
+   */
+  public static function hook_civicrm_check($e) {
+    $hasAuthx = \CRM_Extension_System::singleton()->getMapper()->isActiveModule('authx');
+    $tokenFormCount = count(Tokens::getTokenForms());
+    if (!$hasAuthx) {
+      if ($tokenFormCount) {
+        $e->messages[] = new \CRM_Utils_Check_Message(
+          'afform_token_authx',
+          E::ts('Email token support has been configured for %2 form(s), which requires extended authentication services. Please enable "AuthX" in <a href="%1">Manage Extensions</a>.', [
+            1 => \CRM_Utils_System::url('civicrm/admin/extensions', 'reset=1'),
+            2 => $tokenFormCount,
+          ]),
+          E::ts('AuthX Required'),
+          \Psr\Log\LogLevel::ERROR,
+          'fa-chain-broken'
+        );
+      }
+      else {
+        $e->messages[] = new \CRM_Utils_Check_Message(
+          'afform_token_authx',
+          E::ts('To generate authenticated email links for custom forms, enable extended authentication services (AuthX) in <a href="%1">Manage Extensions</a>.', [
+            1 => \CRM_Utils_System::url('civicrm/admin/extensions', 'reset=1'),
+          ]),
+          E::ts('AuthX Suggested'),
+          \Psr\Log\LogLevel::INFO,
+          'fa-lightbulb-o'
+        );
+      }
+    }
+
+    if ($hasAuthx && $tokenFormCount > 0 && !in_array('jwt', \Civi::settings()->get('authx_auto_cred'))) {
+      $e->messages[] = new \CRM_Utils_Check_Message(
+        'afform_token_authx',
+        E::ts('Email token support has been configured for %1 form(s). This requires JWT authentication, <code>authx_auto_cred</code> does not include JWT. ', [
+          1 => $tokenFormCount,
+        ]),
+        E::ts('AuthX Configuration'),
+        \Psr\Log\LogLevel::ERROR,
+        'fa-chain-broken'
+      );
+
+    }
+  }
+
+}
diff --git a/ext/afform/core/Civi/Afform/Tokens.php b/ext/afform/core/Civi/Afform/Tokens.php
new file mode 100644 (file)
index 0000000..bc12d84
--- /dev/null
@@ -0,0 +1,204 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+namespace Civi\Afform;
+
+use Civi\Core\Event\GenericHookEvent;
+use Civi\Crypto\Exception\CryptoException;
+use CRM_Afform_ExtensionUtil as E;
+
+/**
+ * Every afform with the property `is_token=true` should have a corresponding
+ * set of tokens, `{afform.myFormUrl}` and `{afform.myFormLink}`.
+ *
+ * @see MockPublicFormTest
+ * @package Civi\Afform
+ */
+class Tokens {
+
+  /**
+   * CKEditor makes it hard to set an `href` to a token, so we often get
+   * this munged `'http://{token}` data.
+   *
+   * @see CRM_Utils_Hook::alterMailContent
+   */
+  public static function applyCkeditorWorkaround(GenericHookEvent $e) {
+    foreach (array_keys($e->content) as $field) {
+      $e->content[$field] = preg_replace(';https?://(\{afform.*Url\});', '$1', $e->content[$field]);
+    }
+  }
+
+  /**
+   * Expose tokens for use in UI.
+   *
+   * @param \Civi\Core\Event\GenericHookEvent $e
+   * @see \CRM_Utils_Hook::tokens()
+   */
+  public static function hook_civicrm_tokens(GenericHookEvent $e) {
+    $tokenForms = static::getTokenForms();
+    foreach ($tokenForms as $tokenName => $afform) {
+      $e->tokens['afform']["afform.{$tokenName}Url"] = E::ts('%1 (URL)', [1 => $afform['title'] ?? $afform['name']]);
+      $e->tokens['afform']["afform.{$tokenName}Link"] = E::ts('%1 (Full Hyperlink)', [1 => $afform['title'] ?? $afform['name']]);
+    }
+  }
+
+  /**
+   * Substitute any tokens of the form `{afform.myFormUrl}` or `{afform.myFormLink}` with actual values.
+   *
+   * @param \Civi\Core\Event\GenericHookEvent $e
+   * @see \CRM_Utils_Hook::tokenValues()
+   */
+  public static function hook_civicrm_tokenValues(GenericHookEvent $e) {
+    try {
+      // Depending on the caller, $tokens['afform'] might be ['fooUrl'] or ['fooUrl'=>1]. Because... why not!
+      $activeAfformTokens = array_merge(array_keys($e->tokens['afform'] ?? []), array_values($e->tokens['afform'] ?? []));
+
+      $tokenForms = static::getTokenForms();
+      foreach ($tokenForms as $formName => $afform) {
+        if (!array_intersect($activeAfformTokens, ["{$formName}Url", "{$formName}Link"])) {
+          continue;
+        }
+
+        if (empty($afform['server_route'])) {
+          continue;
+        }
+
+        if (!is_array($e->contactIDs)) {
+          $url = self::createUrl($afform, $e->contactIDs);
+          $e->details["afform.{$formName}Url"] = $url;
+          $e->details["afform.{$formName}Link"] = sprintf('<a href="%s">%s</a>', htmlentities($url), htmlentities($afform['title'] ?? $afform['name']));
+        }
+        else {
+          foreach ($e->contactIDs as $cid) {
+            $url = self::createUrl($afform, $cid);
+            $e->details[$cid]["afform.{$formName}Url"] = $url;
+            $e->details[$cid]["afform.{$formName}Link"] = sprintf('<a href="%s">%s</a>', htmlentities($url), htmlentities($afform['title'] ?? $afform['name']));
+          }
+        }
+      }
+    }
+    catch (CryptoException $ex) {
+      \Civi::log()->warning('Civi\Afform\LegacyTokens cannot generate tokens due to crypto exception.', ['exception' => $ex]);
+    }
+  }
+
+  ///**
+  // * Expose tokens for use in UI.
+  // *
+  // * @param \Civi\Token\Event\TokenRegisterEvent $e
+  // */
+  //public static function onRegister(\Civi\Token\Event\TokenRegisterEvent $e) {
+  //  $tokenForms = static::getTokenForms();
+  //  foreach ($tokenForms as $tokenName => $afform) {
+  //    $e->register([
+  //      'entity' => 'afform',
+  //      'field' => $tokenName . 'Url',
+  //      'label' => E::ts('View Form: %1 (URL)', [1 => $afform['title'] ?? $afform['name']]),
+  //    ]);
+  //    $e->register([
+  //      'entity' => 'afform',
+  //      'field' => $tokenName . 'Link',
+  //      'label' => E::ts('View Form: %1 (Full Hyperlink)', [1 => $afform['title'] ?? $afform['name']]),
+  //    ]);
+  //  }
+  //}
+
+  ///**
+  // * Substitute any tokens of the form `{afform.myFormUrl}` or `{afform.myFormLink}` with actual values.
+  // *
+  // * @param \Civi\Token\Event\TokenValueEvent $e
+  // */
+  //public static function onEvaluate(\Civi\Token\Event\TokenValueEvent $e) {
+  //  $activeTokens = $e->getTokenProcessor()->getMessageTokens();
+  //  if (empty($activeTokens['afform'])) {
+  //    return;
+  //  }
+  //
+  //  $tokenForms = static::getTokenForms();
+  //  foreach ($tokenForms as $formName => $afform) {
+  //    if (!array_intersect($activeTokens['afform'], ["{$formName}Url", "{$formName}Link"])) {
+  //      continue;
+  //    }
+  //
+  //    if (empty($afform['server_route'])) {
+  //      \Civi::log()
+  //        ->warning('Civi\Afform\Tokens: Cannot generate link for {formName} -- missing server_route', [
+  //          'formName' => $formName,
+  //        ]);
+  //      continue;
+  //    }
+  //
+  //    foreach ($e->getRows() as $row) {
+  //      /** @var \Civi\Token\TokenRow $row */
+  //      try {
+  //        $url = self::createUrl($afform, $row->context['contactId']);
+  //        $row->format('text/plain')->tokens('afform', "{$formName}Url", $url);
+  //        $row->format('text/html')->tokens('afform', "{$formName}Link",
+  //          sprintf('<a href="%s">%s</a>', htmlentities($url), htmlentities($afform['title'] ?? $afform['name'])));
+  //      }
+  //      catch (CryptoException $e) {
+  //        \Civi::log()->warning('Civi\Afform\Tokens cannot generate tokens due to crypto exception.', ['exception' => $e]);
+  //      }
+  //    }
+  //  }
+  //}
+
+  /**
+   * Get a list of forms that have token support enabled.
+   *
+   * @return array
+   *   $result[$formName] = ['name' => $formName, 'title' => $formTitle, 'server_route' => $route];
+   */
+  public static function getTokenForms() {
+    if (!isset(\Civi::$statics[__CLASS__]['tokenForms'])) {
+      $tokenForms = (array) \Civi\Api4\Afform::get(0)
+        ->addWhere('is_token', '=', TRUE)
+        ->addSelect('name', 'title', 'server_route', 'is_public')
+        ->execute()
+        ->indexBy('name');
+      \Civi::$statics[__CLASS__]['tokenForms'] = $tokenForms;
+    }
+    return \Civi::$statics[__CLASS__]['tokenForms'];
+  }
+
+  /**
+   * Generate an authenticated URL for viewing this form.
+   *
+   * @param array $afform
+   * @param int $contactId
+   *
+   * @return string
+   * @throws \Civi\Crypto\Exception\CryptoException
+   */
+  public static function createUrl($afform, $contactId): string {
+    $expires = \CRM_Utils_Time::time() +
+      (\Civi::settings()->get('checksum_timeout') * 24 * 60 * 60);
+
+    /** @var \Civi\Crypto\CryptoJwt $jwt */
+    $jwt = \Civi::service('crypto.jwt');
+
+    $bearerToken = "Bearer " . $jwt->encode([
+      'exp' => $expires,
+      'sub' => "cid:" . $contactId,
+      'scope' => 'authx',
+    ]);
+
+    $url = \CRM_Utils_System::url($afform['server_route'],
+      ['_authx' => $bearerToken, '_authxSes' => 1],
+      TRUE,
+      NULL,
+      FALSE,
+      $afform['is_public'] ?? TRUE
+    );
+    return $url;
+  }
+
+}
index 368baa43045c8b4988203e536269eb9c2444b04a..8e32e56fe086a874158325d01a074bed1f0cdd91 100644 (file)
@@ -132,6 +132,7 @@ class Get extends \Civi\Api4\Generic\BasicGetAction {
         'description' => '',
         'is_dashlet' => FALSE,
         'is_public' => FALSE,
+        'is_token' => FALSE,
         'permission' => 'access CiviCRM',
         'join' => 'Custom_' . $custom['name'],
         'block' => $custom['extends'],
index 23c7c02189b7e06043db91f28179c9ffbc9a3117..31a3c387d46337d53850302e0d7715924b8036af 100644 (file)
@@ -153,6 +153,10 @@ class Afform extends Generic\AbstractEntity {
           'name' => 'is_public',
           'data_type' => 'Boolean',
         ],
+        [
+          'name' => 'is_token',
+          'data_type' => 'Boolean',
+        ],
         [
           'name' => 'repeat',
           'data_type' => 'Mixed',
index 4018b779df891f1d4058277e212a16b0608df102..2e70d5de67deddc7e606df30452d48abd65b4c1e 100644 (file)
@@ -49,10 +49,19 @@ function afform_civicrm_config(&$config) {
   }
   Civi::$statics[__FUNCTION__] = 1;
 
-  Civi::dispatcher()->addListener(Submit::EVENT_NAME, [Submit::class, 'processContacts'], 500);
-  Civi::dispatcher()->addListener(Submit::EVENT_NAME, [Submit::class, 'processGenericEntity'], -1000);
-  Civi::dispatcher()->addListener('hook_civicrm_angularModules', ['\Civi\Afform\AngularDependencyMapper', 'autoReq'], -1000);
-  Civi::dispatcher()->addListener('hook_civicrm_alterAngular', ['\Civi\Afform\AfformMetadataInjector', 'preprocess']);
+  $dispatcher = Civi::dispatcher();
+  $dispatcher->addListener(Submit::EVENT_NAME, [Submit::class, 'processContacts'], 500);
+  $dispatcher->addListener(Submit::EVENT_NAME, [Submit::class, 'processGenericEntity'], -1000);
+  $dispatcher->addListener('hook_civicrm_angularModules', ['\Civi\Afform\AngularDependencyMapper', 'autoReq'], -1000);
+  $dispatcher->addListener('hook_civicrm_alterAngular', ['\Civi\Afform\AfformMetadataInjector', 'preprocess']);
+  $dispatcher->addListener('hook_civicrm_check', ['\Civi\Afform\StatusChecks', 'hook_civicrm_check']);
+
+  // Register support for email tokens
+  if (CRM_Extension_System::singleton()->getMapper()->isActiveModule('authx')) {
+    $dispatcher->addListener('hook_civicrm_alterMailContent', ['\Civi\Afform\Tokens', 'applyCkeditorWorkaround']);
+    $dispatcher->addListener('hook_civicrm_tokens', ['\Civi\Afform\Tokens', 'hook_civicrm_tokens']);
+    $dispatcher->addListener('hook_civicrm_tokenValues', ['\Civi\Afform\Tokens', 'hook_civicrm_tokenValues']);
+  }
 }
 
 /**
index 0f9f25d307a9cd62aa26edb1928ddf2de81d249a..fc8f870b723b86a3cdf77609656b6ce38d0288ce 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<phpunit backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" syntaxCheck="false" bootstrap="tests/phpunit/bootstrap.php">
+<phpunit backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" bootstrap="tests/phpunit/bootstrap.php">
   <testsuites>
     <testsuite name="My Test Suite">
       <directory>./tests/phpunit</directory>
index e3884febf7c48befba7c97f3d002636ce62e8819..c759c16ee6a78008b05f3021e71c193f02a1d288 100644 (file)
@@ -56,7 +56,7 @@ class CRM_Afform_UtilTest extends \PHPUnit\Framework\TestCase implements Headles
    * @dataProvider getNameExamples
    * @throws \Exception
    */
-  public function testNameConversion($inputFileName, $toFormat, $expected) {
+  public function testNameConversion($inputFileName, $toFormat, $expected): void {
     $actual = _afform_angular_module_name($inputFileName, $toFormat);
     $this->assertEquals($expected, $actual);
   }
index 4e84b5592d37c7c197bba8aab2d1b235ffc2d6ae..012c4c2727c8ddca882ebe9ae24b2f0099b48022 100644 (file)
@@ -34,7 +34,7 @@ class FilterTest extends \PHPUnit\Framework\TestCase implements HeadlessInterfac
     return $htmls[$fileName];
   }
 
-  public function testDefnInjection() {
+  public function testDefnInjection(): void {
     $inputHtml = sprintf(self::PERSON_TPL,
       '<div af-fieldset="person"><af-field name="first_name" /></div>');
     $filteredHtml = $this->htmlFilter('~/afform/MyForm.aff.html', $inputHtml);
@@ -46,7 +46,7 @@ class FilterTest extends \PHPUnit\Framework\TestCase implements HeadlessInterfac
     $this->assertEquals('First Name', $myField['defn']['label']);
   }
 
-  public function testDefnInjectionNested() {
+  public function testDefnInjectionNested(): void {
     $inputHtml = sprintf(self::PERSON_TPL,
       '<span><div af-fieldset="person"><foo><af-field name="first_name" /></foo></div></span>');
     $filteredHtml = $this->htmlFilter('~/afform/MyForm.aff.html', $inputHtml);
@@ -58,7 +58,7 @@ class FilterTest extends \PHPUnit\Framework\TestCase implements HeadlessInterfac
     $this->assertEquals('First Name', $myField['defn']['label']);
   }
 
-  public function testDefnOverrideTitle() {
+  public function testDefnOverrideTitle(): void {
     $inputHtml = sprintf(self::PERSON_TPL,
       '<div af-fieldset="person"><af-field name="first_name" defn="{label: \'Given name\'}" /></div>');
     $filteredHtml = $this->htmlFilter('~/afform/MyForm.aff.html', $inputHtml);
index 00513dd3ee00b83c87f0a7d1c154e97333bbfdac..0e6d7812ee42dab230398f4d5c4e8921fce38b41 100644 (file)
@@ -99,7 +99,7 @@ class FormDataModelTest extends \PHPUnit\Framework\TestCase implements HeadlessI
    * @param $expectEntities
    * @dataProvider getEntityExamples
    */
-  public function testGetEntities($html, $expectEntities) {
+  public function testGetEntities($html, $expectEntities): void {
     $parser = new \CRM_Afform_ArrayHtml();
     $fdm = new FormDataModel($parser->convertHtmlToArray($html));
     $this->assertEquals($expectEntities, $fdm->getEntities());
index 8074fc41f9ca53eacfc2bcdcb53b699e95e6cc0d..e2560aa6d71546a4e53d9a9a86f85e943bcce7cc 100644 (file)
@@ -90,7 +90,7 @@ class SymbolsTest extends \PHPUnit\Framework\TestCase implements HeadlessInterfa
    *   Types are (e)lement, (a)ttribute, (c)lass
    * @dataProvider getExamples
    */
-  public function testSymbols($html, $expect) {
+  public function testSymbols($html, $expect): void {
     $expectDefaults = ['e' => [], 'a' => [], 'c' => []];
     $expect = array_merge($expectDefaults, $expect);
     $actual = Symbols::scan($html);
index a5b49253c819c5ab65947070e7ee67d0cac48ea1..5133778c819133e6d0a8d558055d5aa1a48b1ec3 100644 (file)
@@ -1,7 +1,6 @@
 <?php
 
 ini_set('memory_limit', '2G');
-ini_set('safe_mode', 0);
 // phpcs:disable
 eval(cv('php:boot --level=classloader', 'phpcode'));
 // phpcs:enable
index c51e70f09a3a5c96671b3b9eb47c3fcb66ed0085..83a87e05f34b8d86d28f0a69f4a77d2e06d0b742 100644 (file)
@@ -15,6 +15,7 @@ $ cv api4 afform.get +w name=helloWorld
         "description": "",
         "is_dashlet": false,
         "is_public": false,
+        "is_token": false,
         "server_route": "civicrm/hello-world",
         "layout": {
             "#tag": "div",
index 782ea3a256c11b57f0f40b43ba5cd506cf4f111e..1caefb11a4026f56d8f481ff55296d3df8c498ca 100644 (file)
               </label>
               <p class="help-block">{{ts('The general look/feel should match the frontend')}}</p>
             </div>
+            <div class="form-group" ng-if="!!resultForm.server_route">
+              <label for="af_config_form_is_token">
+                <input type="checkbox" id="af_config_form_is_token" ng-model="resultForm.is_token">
+                {{ ts('Enable email token') }}
+              </label>
+              <p class="help-block">{{ts('Allow email authors to easily link to this form')}}</p>
+            </div>
             <div class="form-group">
               <label for="af_config_form_is_dashlet">
                 <input type="checkbox" id="af_config_form_is_dashlet" ng-model="resultForm.is_dashlet">
index e97ef09b11c018d92a0c37402894bd96fcde478e..eb221305eeec01a787ae46d3b1ad794cab6a93e2 100644 (file)
@@ -2,5 +2,6 @@
   "type": "form",
   "title": "My public form",
   "server_route": "civicrm/mock-public-form",
-  "permission": "*always allow*"
+  "permission": "*always allow*",
+  "is_token": true
 }
index d4f7bf4f0c84d763c545a0fab86e01d5e58ca73a..70feb1f6a2e112cbca9738955366898b45464675 100644 (file)
@@ -63,4 +63,117 @@ class MockPublicFormTest extends \Civi\AfformMock\FormTestCase {
     $this->assertEquals(0, CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_contact WHERE first_name=%1', [1 => ["Firsty{$r}", 'String']]));
   }
 
+  /**
+   * The email token `{afform.mockPublicFormUrl}` should evaluate to an authenticated URL.
+   */
+  public function testAuthenticatedUrlToken_Plain() {
+    if (!function_exists('authx_civicrm_config')) {
+      $this->fail('Cannot test without authx');
+    }
+
+    $lebowski = $this->getLebowskiCID();
+    $text = $this->renderTokens($lebowski, 'Please go to {afform.mockPublicFormUrl}', 'text/plain');
+    if (!preg_match(';Please go to ([^\s]+);', $text, $m)) {
+      $this->fail('Plain text message did not have URL in expected place: ' . $text);
+    }
+    $url = $m[1];
+    $this->assertRegExp(';^https?:.*civicrm/mock-public-form.*;', $url, "URL should look plausible");
+
+    // Going to this page will cause us to authenticate as the target contact
+    $http = $this->createGuzzle(['http_errors' => FALSE, 'cookies' => new \GuzzleHttp\Cookie\CookieJar()]);
+    $response = $http->get($url);
+    $r = (string) $response->getBody();
+    $this->assertStatusCode(200, $response);
+    $response = $http->get('civicrm/authx/id');
+    $this->assertContactJson($lebowski, $response);
+  }
+
+  /**
+   * The email token `{afform.mockPublicFormUrl}` should evaluate to an authenticated URL.
+   */
+  public function testAuthenticatedUrlToken_Html() {
+    if (!function_exists('authx_civicrm_config')) {
+      $this->fail('Cannot test without authx');
+    }
+
+    $lebowski = $this->getLebowskiCID();
+    $html = $this->renderTokens($lebowski, 'Please go to <a href="{afform.mockPublicFormUrl}">my form</a>', 'text/html');
+
+    if (!preg_match(';a href="([^"]+)";', $html, $m)) {
+      $this->fail('HTML message did not have URL in expected place: ' . $html);
+    }
+    $url = html_entity_decode($m[1]);
+    $this->assertRegExp(';^https?:.*civicrm/mock-public-form.*;', $url, "URL should look plausible");
+
+    // Going to this page will cause us to authenticate as the target contact
+    $http = $this->createGuzzle(['cookies' => new \GuzzleHttp\Cookie\CookieJar()]);
+    $response = $http->get($url);
+    $this->assertStatusCode(200, $response);
+    $response = $http->get('civicrm/authx/id');
+    $this->assertContactJson($lebowski, $response);
+  }
+
+  /**
+   * The email token `{afform.mockPublicFormLink}` should evaluate to an authenticated URL.
+   */
+  public function testAuthenticatedLinkToken_Html() {
+    if (!function_exists('authx_civicrm_config')) {
+      $this->fail('Cannot test without authx');
+    }
+
+    $lebowski = $this->getLebowskiCID();
+    $html = $this->renderTokens($lebowski, 'Please go to {afform.mockPublicFormLink}', 'text/html');
+    $doc = \phpQuery::newDocument($html, 'text/html');
+    $this->assertEquals(1, $doc->find('a')->count(), 'Document should have hyperlink');
+    foreach ($doc->find('a') as $item) {
+      /** @var \DOMElement $item */
+      $this->assertRegExp(';^https?:.*civicrm/mock-public-form.*;', $item->getAttribute('href'));
+      $this->assertEquals('My public form', $item->firstChild->data);
+      $url = $item->getAttribute('href');
+    }
+
+    // Going to this page will cause us to authenticate as the target contact
+    $http = $this->createGuzzle(['cookies' => new \GuzzleHttp\Cookie\CookieJar()]);
+    $response = $http->get($url);
+    $this->assertStatusCode(200, $response);
+    $response = $http->get('civicrm/authx/id');
+    $this->assertContactJson($lebowski, $response);
+  }
+
+  protected function renderTokens($cid, $body, $format) {
+    $tp = new \Civi\Token\TokenProcessor(\Civi::dispatcher(), []);
+    $tp->addRow()->context('contactId', $cid);
+    $tp->addMessage('example', $body, $format);
+    $tp->evaluate();
+    return $tp->getRow(0)->render('example');
+  }
+
+  protected function getLebowskiCID() {
+    $contact = \civicrm_api3('Contact', 'create', [
+      'contact_type' => 'Individual',
+      'first_name' => 'Jeffrey',
+      'last_name' => 'Lebowski',
+      'external_identifier' => __CLASS__,
+      'options' => [
+        'match' => 'external_identifier',
+      ],
+    ]);
+    return $contact['id'];
+  }
+
+  /**
+   * Assert the AJAX request provided the expected contact.
+   *
+   * @param int $cid
+   *   The expected contact ID
+   * @param \Psr\Http\Message\ResponseInterface $response
+   */
+  public function assertContactJson($cid, $response) {
+    $this->assertContentType('application/json', $response);
+    $this->assertStatusCode(200, $response);
+    $j = json_decode((string) $response->getBody(), 1);
+    $formattedFailure = $this->formatFailure($response);
+    $this->assertEquals($cid, $j['contact_id'], "Response did not give expected contact ID\n" . $formattedFailure);
+  }
+
 }
index d7406c754d9e5e68b0f99c9218e559031889b6b9..5d310b7c2f2dd501f561a7c168f9b94c1c976863 100644 (file)
@@ -14,7 +14,7 @@ class api_v4_AfformRoutingTest extends \PHPUnit\Framework\TestCase implements \C
       ->apply();
   }
 
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
     Civi\Api4\Afform::revert()
       ->setCheckPermissions(FALSE)
@@ -22,7 +22,7 @@ class api_v4_AfformRoutingTest extends \PHPUnit\Framework\TestCase implements \C
       ->execute();
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     parent::tearDown();
     Civi\Api4\Afform::revert()
       ->setCheckPermissions(FALSE)
@@ -30,7 +30,7 @@ class api_v4_AfformRoutingTest extends \PHPUnit\Framework\TestCase implements \C
       ->execute();
   }
 
-  public function testChangingPermissions() {
+  public function testChangingPermissions(): void {
     $http = new \GuzzleHttp\Client(['http_errors' => FALSE]);
     $url = function ($path, $query = NULL) {
       return CRM_Utils_System::url($path, $query, TRUE, NULL, FALSE);
@@ -49,7 +49,7 @@ class api_v4_AfformRoutingTest extends \PHPUnit\Framework\TestCase implements \C
     $this->assertOpensPage($result, 'mock-page');
   }
 
-  public function testChangingPath() {
+  public function testChangingPath(): void {
     $http = new \GuzzleHttp\Client(['http_errors' => FALSE]);
     $url = function ($path, $query = NULL) {
       return CRM_Utils_System::url($path, $query, TRUE, NULL, FALSE);
index 9f5132a31a48efb42f83b53c84591d11e86a7d79..3d57c90bb0c1c6e51bce222fcad32182f5ea077d 100644 (file)
@@ -45,7 +45,7 @@ class api_v4_AfformTest extends api_v4_AfformTestCase {
    * @param array $originalMetadata
    * @dataProvider getBasicDirectives
    */
-  public function testGetUpdateRevert($formName, $originalMetadata) {
+  public function testGetUpdateRevert($formName, $originalMetadata): void {
     $get = function($arr, $key) {
       return isset($arr[$key]) ? $arr[$key] : NULL;
     };
@@ -134,7 +134,7 @@ class api_v4_AfformTest extends api_v4_AfformTestCase {
    *   (For debug messages) A symbolic name of the example data-set being tested.
    * @dataProvider getFormatExamples
    */
-  public function testBasicConvert($formName, $updateFormat, $updateLayout, $readFormat, $readLayout, $exampleName) {
+  public function testBasicConvert($formName, $updateFormat, $updateLayout, $readFormat, $readLayout, $exampleName): void {
     $actual = Civi\Api4\Afform::convert()->setLayout($updateLayout)
       ->setFrom($updateFormat)
       ->setTo($readFormat)
@@ -177,7 +177,7 @@ class api_v4_AfformTest extends api_v4_AfformTestCase {
    *   (For debug messages) A symbolic name of the example data-set being tested.
    * @dataProvider getFormatExamples
    */
-  public function testUpdateAndGetFormat($formName, $updateFormat, $updateLayout, $readFormat, $readLayout, $exampleName) {
+  public function testUpdateAndGetFormat($formName, $updateFormat, $updateLayout, $readFormat, $readLayout, $exampleName): void {
     Civi\Api4\Afform::revert()->addWhere('name', '=', $formName)->execute();
 
     Civi\Api4\Afform::update()
@@ -213,7 +213,7 @@ class api_v4_AfformTest extends api_v4_AfformTestCase {
    *
    * @dataProvider getWhitespaceExamples
    */
-  public function testWhitespaceFormat($directiveName, $example, $exampleName) {
+  public function testWhitespaceFormat($directiveName, $example, $exampleName): void {
     Civi\Api4\Afform::save()
       ->addRecord(['name' => $directiveName, 'layout' => $example['html']])
       ->setLayoutFormat('html')
@@ -243,7 +243,7 @@ class api_v4_AfformTest extends api_v4_AfformTestCase {
     $this->assertEquals($example['pretty'], $this->fudgeMarkup($result['layout']));
   }
 
-  public function testAutoRequires() {
+  public function testAutoRequires(): void {
     $formName = 'mockPage';
     $this->createLoggedInUser();
 
index 152e55c96bb0ea2efb2d51a52a7933e9e1589359..f13d6fa55d10fec893cc8d59bddb31e63b0bad8b 100644 (file)
@@ -13,7 +13,7 @@ class api_v4_AfformUsageTest extends api_v4_AfformTestCase {
 
   protected $formName;
 
-  public static function setUpBeforeClass() {
+  public static function setUpBeforeClass(): void {
     parent::setUpBeforeClass();
     self::$layouts['aboutMe'] = <<<EOHTML
 <af-form ctrl="modelListCtrl">
@@ -26,12 +26,12 @@ class api_v4_AfformUsageTest extends api_v4_AfformTestCase {
 EOHTML;
   }
 
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
     $this->formName = 'mock' . rand(0, 100000);
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     Civi\Api4\Afform::revert()
       ->setCheckPermissions(FALSE)
       ->addWhere('name', '=', $this->formName)
@@ -39,7 +39,7 @@ EOHTML;
     parent::tearDown();
   }
 
-  public function testAboutMeAllowed() {
+  public function testAboutMeAllowed(): void {
     $this->useValues([
       'layout' => self::$layouts['aboutMe'],
       'permission' => CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION,
@@ -71,7 +71,7 @@ EOHTML;
     $this->assertEquals('Lasty', $contact['last_name']);
   }
 
-  public function testAboutMeForbidden() {
+  public function testAboutMeForbidden(): void {
     $this->useValues([
       'layout' => self::$layouts['aboutMe'],
       'permission' => CRM_Core_Permission::ALWAYS_DENY_PERMISSION,
index bc7558e582fc97c1b0452df38a15250076af5e5f..bac7c1f2973b3424a5d4e46490eae391e9d00418 100644 (file)
@@ -1,7 +1,6 @@
 <?php
 
 ini_set('memory_limit', '2G');
-ini_set('safe_mode', 0);
 // phpcs:disable
 eval(cv('php:boot --level=classloader', 'phpcode'));
 // phpcs:enable
index c83ac1d6474118d7ab323eec6f090240cb08a8b4..e7559dbbb1932766ac6f042678019f503b3d04ff 100644 (file)
@@ -60,6 +60,7 @@ class Authenticator {
     $tgt = AuthenticatorTarget::create([
       'flow' => $details['flow'],
       'cred' => $details['cred'],
+      'siteKey' => $details['siteKey'] ?? NULL,
       'useSession' => $details['useSession'] ?? FALSE,
     ]);
     if ($principal = $this->checkCredential($tgt)) {
@@ -148,6 +149,23 @@ class Authenticator {
         }
         break;
     }
+
+    $useGuards = \Civi::settings()->get('authx_guards');
+    if (!empty($useGuards)) {
+      // array(string $credType => string $requiredPermissionToUseThisCred)
+      $perms['pass'] = 'authenticate with password';
+      $perms['api_key'] = 'authenticate with api key';
+
+      // If any one of these passes, then we allow the authentication.
+      $passGuard = [];
+      $passGuard[] = in_array('site_key', $useGuards) && defined('CIVICRM_SITE_KEY') && hash_equals(CIVICRM_SITE_KEY, $tgt->siteKey);
+      $passGuard[] = in_array('perm', $useGuards) && isset($perms[$tgt->credType]) && \CRM_Core_Permission::check($perms[$tgt->credType], $tgt->contactId);
+      // JWTs are signed by us. We don't need user to prove that they're allowed to use them.
+      $passGuard[] = ($tgt->credType === 'jwt');
+      if (!max($passGuard)) {
+        $this->reject(sprintf('Login not permitted. Must satisfy guard (%s).', implode(', ', $useGuards)));
+      }
+    }
   }
 
   /**
@@ -209,6 +227,7 @@ class Authenticator {
    * @param string $message
    */
   protected function reject($message = 'Authentication failed') {
+    \CRM_Core_Session::useFakeSession();
     $r = new Response(401, ['Content-Type' => 'text/plain'], "HTTP 401 $message");
     \CRM_Utils_System::sendResponse($r);
   }
@@ -238,6 +257,12 @@ class AuthenticatorTarget {
    */
   public $cred;
 
+  /**
+   * The raw site-key as submitted (if applicable).
+   * @var string
+   */
+  public $siteKey;
+
   /**
    * (Authenticated) The type of credential.
    *
index 9e5915cec9c89cc69eb368d21000338ba89546d8..fa4a1e6181cdc65b54d6cc1101007e4ecc7a3ef7 100644 (file)
@@ -28,6 +28,16 @@ class Meta {
     ];
   }
 
+  /**
+   * @return array
+   */
+  public static function getGuardTypes() {
+    return [
+      'perm' => E::ts('User Permission'),
+      'site_key' => E::ts('Site Key'),
+    ];
+  }
+
   /**
    * @return array
    */
index c01aaf328977bb64cca9fb998784c9a0d82e0b0d..95fd219557b8a725f4f1d7367051701f05f2b720 100644 (file)
@@ -6,22 +6,24 @@ use CRM_Authx_ExtensionUtil as E;
 // phpcs:enable
 
 Civi::dispatcher()->addListener('civi.invoke.auth', function($e) {
+  $params = ($_SERVER['REQUEST_METHOD'] === 'GET') ? $_GET : $_POST;
+  $siteKey = $_SERVER['HTTP_X_CIVI_KEY'] ?? $params['_authxSiteKey'] ?? NULL;
+
   if (!empty($_SERVER['HTTP_X_CIVI_AUTH'])) {
-    return (new \Civi\Authx\Authenticator())->auth($e, ['flow' => 'xheader', 'cred' => $_SERVER['HTTP_X_CIVI_AUTH']]);
+    return (new \Civi\Authx\Authenticator())->auth($e, ['flow' => 'xheader', 'cred' => $_SERVER['HTTP_X_CIVI_AUTH'], 'siteKey' => $siteKey]);
   }
 
   if (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
-    return (new \Civi\Authx\Authenticator())->auth($e, ['flow' => 'header', 'cred' => $_SERVER['HTTP_AUTHORIZATION']]);
+    return (new \Civi\Authx\Authenticator())->auth($e, ['flow' => 'header', 'cred' => $_SERVER['HTTP_AUTHORIZATION'], 'siteKey' => $siteKey]);
   }
 
-  $params = ($_SERVER['REQUEST_METHOD'] === 'GET') ? $_GET : $_POST;
   if (!empty($params['_authx'])) {
     if ((implode('/', $e->args) === 'civicrm/authx/login')) {
-      (new \Civi\Authx\Authenticator())->auth($e, ['flow' => 'login', 'cred' => $params['_authx'], 'useSession' => TRUE]);
+      (new \Civi\Authx\Authenticator())->auth($e, ['flow' => 'login', 'cred' => $params['_authx'], 'useSession' => TRUE, 'siteKey' => $siteKey]);
       _authx_redact(['_authx']);
     }
     elseif (!empty($params['_authxSes'])) {
-      (new \Civi\Authx\Authenticator())->auth($e, ['flow' => 'auto', 'cred' => $params['_authx'], 'useSession' => TRUE]);
+      (new \Civi\Authx\Authenticator())->auth($e, ['flow' => 'auto', 'cred' => $params['_authx'], 'useSession' => TRUE, 'siteKey' => $siteKey]);
       if ($_SERVER['REQUEST_METHOD'] === 'GET') {
         _authx_reload(implode('/', $e->args), $_SERVER['QUERY_STRING']);
       }
@@ -30,7 +32,7 @@ Civi::dispatcher()->addListener('civi.invoke.auth', function($e) {
       }
     }
     else {
-      (new \Civi\Authx\Authenticator())->auth($e, ['flow' => 'param', 'cred' => $params['_authx']]);
+      (new \Civi\Authx\Authenticator())->auth($e, ['flow' => 'param', 'cred' => $params['_authx'], 'siteKey' => $siteKey]);
       _authx_redact(['_authx']);
     }
   }
@@ -212,6 +214,16 @@ function authx_civicrm_themes(&$themes) {
   _authx_civix_civicrm_themes($themes);
 }
 
+/**
+ * Implements hook_civicrm_permission().
+ *
+ * @see CRM_Utils_Hook::permission()
+ */
+function authx_civicrm_permission(&$permissions) {
+  $permissions['authenticate with password'] = E::ts('AuthX: Authenticate to services with password');
+  $permissions['authenticate with api key'] = E::ts('AuthX: Authenticate to services with API key');
+}
+
 // --- Functions below this ship commented out. Uncomment as required. ---
 
 /**
index e40bfc8233242e874e3b9b05907aecdef2c9fe0e..5613bb2f06b9701b51d49a4086b2b35a17438572 100644 (file)
@@ -27,6 +27,22 @@ $_authx_settings = function() {
   ];
 
   $s = [];
+  $s["authx_guards"] = $basic + [
+    'name' => 'authx_guards',
+    'type' => 'Array',
+    'quick_form_type' => 'Select',
+    'html_type' => 'Select',
+    'html_attributes' => [
+      'multiple' => 1,
+      'class' => 'crm-select2',
+    ],
+    'default' => ['site_key', 'perm'],
+    'title' => ts('Authentication guard'),
+    'help_text' => ts('Enable an authentication guard if you want to limit which users may authenticate via authx. The permission-based guard is satisfied by checking user permissions. The key-based guard is satisfied by checking the secret site-key. The JWT guard is satisfied if the user presents a signed token. If there are no guards, then any user can authenticate.'),
+    'pseudoconstant' => [
+      'callback' => ['\Civi\Authx\Meta', 'getGuardTypes'],
+    ],
+  ];
   foreach ($flows as $flow) {
     $s["authx_{$flow}_cred"] = $basic + [
       'name' => "authx_{$flow}_cred",
index eb6eff39b77bd8614f92780c201da1a80947ff31..0db6f7d44b0c31eba497dd60ada0d48500522a81 100644 (file)
@@ -34,7 +34,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
    */
   protected $quirks = [];
 
-  public static function setUpBeforeClass() {
+  public static function setUpBeforeClass(): void {
     \Civi\Test::e2e()
       ->installMe(__DIR__)
       ->callback(
@@ -46,7 +46,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
       ->apply();
   }
 
-  public function setUp() {
+  public function setUp(): void {
     $quirks = [
       'Joomla' => ['sendsExcessCookies', 'authErrorShowsForm'],
       'WordPress' => ['sendsExcessCookies'],
@@ -56,13 +56,15 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
     parent::setUp();
     $this->settingsBackup = [];
     foreach (\Civi\Authx\Meta::getFlowTypes() as $flowType) {
-      foreach (["authx_{$flowType}_cred", "authx_{$flowType}_user"] as $setting) {
+      foreach (["authx_{$flowType}_cred", "authx_{$flowType}_user", "authx_guards"] as $setting) {
         $this->settingsBackup[$setting] = \Civi::settings()->get($setting);
       }
     }
+
+    \Civi::settings()->set('authx_guards', []);
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     foreach ($this->settingsBackup as $setting => $value) {
       \Civi::settings()->set($setting, $value);
     }
@@ -91,7 +93,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
     return $exs;
   }
 
-  public function testAnonymous() {
+  public function testAnonymous(): void {
     $http = $this->createGuzzle(['http_errors' => FALSE]);
 
     /** @var \Psr\Http\Message\RequestInterface $request */
@@ -111,7 +113,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
    * @throws \GuzzleHttp\Exception\GuzzleException
    * @dataProvider getStatelessExamples
    */
-  public function testStatelessContactOnly($credType, $flowType) {
+  public function testStatelessContactOnly($credType, $flowType): void {
     if ($credType === 'pass') {
       $this->assertTrue(TRUE, 'No need to test password credentials with non-user contacts');
       return;
@@ -146,7 +148,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
    * @throws \GuzzleHttp\Exception\GuzzleException
    * @dataProvider getStatelessExamples
    */
-  public function testStatelessUserContact($credType, $flowType) {
+  public function testStatelessUserContact($credType, $flowType): void {
     $http = $this->createGuzzle(['http_errors' => FALSE]);
 
     /** @var \Psr\Http\Message\RequestInterface $request */
@@ -166,6 +168,52 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
     }
   }
 
+  /**
+   * The setting "authx_guard" may be used to require (or not require) the site_key.
+   *
+   * @throws \CiviCRM_API3_Exception
+   * @throws \GuzzleHttp\Exception\GuzzleException
+   */
+  public function testStatelessGuardSiteKey() {
+    if (!defined('CIVICRM_SITE_KEY')) {
+      $this->markTestIncomplete("Cannot run test without CIVICRM_SITE_KEY");
+    }
+
+    $addParam = function($request, $key, $value) {
+      $query = $request->getUri()->getQuery();
+      return $request->withUri(
+        $request->getUri()->withQuery($query . '&' . urlencode($key) . '=' . urlencode($value))
+      );
+    };
+
+    [$credType, $flowType] = ['pass', 'header'];
+    $http = $this->createGuzzle(['http_errors' => FALSE]);
+    \Civi::settings()->set("authx_{$flowType}_cred", [$credType]);
+
+    /** @var \Psr\Http\Message\RequestInterface $request */
+    $request = $this->applyAuth($this->requestMyContact(), $credType, $flowType, $this->getDemoCID());
+
+    // Request OK. Policy requires site_key, and we have one.
+    \Civi::settings()->set("authx_guards", ['site_key']);
+    $response = $http->send($request->withHeader('X-Civi-Key', CIVICRM_SITE_KEY));
+    $this->assertMyContact($this->getDemoCID(), $this->getDemoUID(), $response);
+
+    // Request OK. Policy does not require site_key, and we do not have one
+    \Civi::settings()->set("authx_guards", []);
+    $response = $http->send($request);
+    $this->assertMyContact($this->getDemoCID(), $this->getDemoUID(), $response);
+
+    // Request fails. Policy requires site_key, but we don't have the wrong value.
+    \Civi::settings()->set("authx_guards", ['site_key']);
+    $response = $http->send($request->withHeader('X-Civi-Key', 'not-the-site-key'));
+    $this->assertFailedDueToProhibition($response);
+
+    // Request fails. Policy requires site_key, but we don't have one.
+    \Civi::settings()->set("authx_guards", ['site_key']);
+    $response = $http->send($request);
+    $this->assertFailedDueToProhibition($response);
+  }
+
   /**
    * The login flow allows you use 'civicrm/authx/login' and 'civicrm/authx/logout'
    * to setup/teardown a session.
@@ -176,7 +224,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
    * @throws \GuzzleHttp\Exception\GuzzleException
    * @dataProvider getCredTypes
    */
-  public function testStatefulLoginAllowed($credType) {
+  public function testStatefulLoginAllowed($credType): void {
     $flowType = 'login';
     $credFunc = 'cred' . ucfirst(preg_replace(';[^a-zA-Z0-9];', '', $credType));
 
@@ -222,7 +270,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
    * @throws \GuzzleHttp\Exception\GuzzleException
    * @dataProvider getCredTypes
    */
-  public function testStatefulLoginProhibited($credType) {
+  public function testStatefulLoginProhibited($credType): void {
     $flowType = 'login';
     $http = $this->createGuzzle(['http_errors' => FALSE]);
     $credFunc = 'cred' . ucfirst(preg_replace(';[^a-zA-Z0-9];', '', $credType));
@@ -244,7 +292,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
    * @throws \GuzzleHttp\Exception\GuzzleException
    * @dataProvider getCredTypes
    */
-  public function testStatefulAutoAllowed($credType) {
+  public function testStatefulAutoAllowed($credType): void {
     $flowType = 'auto';
     $cookieJar = new CookieJar();
     $http = $this->createGuzzle(['http_errors' => FALSE, 'cookies' => $cookieJar]);
@@ -271,7 +319,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
    * @throws \GuzzleHttp\Exception\GuzzleException
    * @dataProvider getCredTypes
    */
-  public function testStatefulAutoProhibited($credType) {
+  public function testStatefulAutoProhibited($credType): void {
     $flowType = 'auto';
     $cookieJar = new CookieJar();
     $http = $this->createGuzzle(['http_errors' => FALSE, 'cookies' => $cookieJar]);
@@ -291,7 +339,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
    * @throws \CiviCRM_API3_Exception
    * @throws \GuzzleHttp\Exception\GuzzleException
    */
-  public function testStatefulStatelessOverlap() {
+  public function testStatefulStatelessOverlap(): void {
     \Civi::settings()->set("authx_login_cred", ['api_key']);
     \Civi::settings()->set("authx_header_cred", ['api_key']);
 
@@ -329,7 +377,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
    * @throws \CiviCRM_API3_Exception
    * @throws \GuzzleHttp\Exception\GuzzleException
    */
-  public function testMultipleStateless() {
+  public function testMultipleStateless(): void {
     \Civi::settings()->set("authx_header_cred", ['api_key']);
     $cookieJar = new CookieJar();
     $http = $this->createGuzzle(['http_errors' => FALSE, 'cookies' => $cookieJar]);
@@ -417,7 +465,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
    *   The expected user ID
    * @param \Psr\Http\Message\ResponseInterface $response
    */
-  public function assertMyContact($cid, $uid, ResponseInterface $response) {
+  public function assertMyContact($cid, $uid, ResponseInterface $response): void {
     $this->assertContentType('application/json', $response);
     $this->assertStatusCode(200, $response);
     $j = json_decode((string) $response->getBody(), 1);
@@ -431,7 +479,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
    *
    * @param \Psr\Http\Message\ResponseInterface $response
    */
-  public function assertAnonymousContact(ResponseInterface $response) {
+  public function assertAnonymousContact(ResponseInterface $response): void {
     $formattedFailure = $this->formatFailure($response);
     $this->assertContentType('application/json', $response);
     $this->assertStatusCode(200, $response);
@@ -448,7 +496,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
    *
    * @param \Psr\Http\Message\ResponseInterface $response
    */
-  public function assertDashboardUnauthorized($response = NULL) {
+  public function assertDashboardUnauthorized($response = NULL): void {
     $response = $this->resolveResponse($response);
     if (!in_array('authErrorShowsForm', $this->quirks)) {
       $this->assertStatusCode(403, $response);
@@ -459,7 +507,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
     );
   }
 
-  public function assertDashboardOk($response = NULL) {
+  public function assertDashboardOk($response = NULL): void {
     $response = $this->resolveResponse($response);
     $this->assertStatusCode(200, $response);
     $this->assertContentType('text/html', $response);
@@ -569,7 +617,7 @@ class AllFlowsTest extends \PHPUnit\Framework\TestCase implements EndToEndInterf
   /**
    * @param \Psr\Http\Message\ResponseInterface $response
    */
-  private function assertFailedDueToProhibition($response) {
+  private function assertFailedDueToProhibition($response): void {
     $this->assertBodyRegexp(';HTTP 401;', $response);
     $this->assertContentType('text/plain', $response);
     if (!in_array('sendsExcessCookies', $this->quirks)) {
index a5b49253c819c5ab65947070e7ee67d0cac48ea1..5133778c819133e6d0a8d558055d5aa1a48b1ec3 100644 (file)
@@ -1,7 +1,6 @@
 <?php
 
 ini_set('memory_limit', '2G');
-ini_set('safe_mode', 0);
 // phpcs:disable
 eval(cv('php:boot --level=classloader', 'phpcode'));
 // phpcs:enable
index a5b49253c819c5ab65947070e7ee67d0cac48ea1..5133778c819133e6d0a8d558055d5aa1a48b1ec3 100644 (file)
@@ -1,7 +1,6 @@
 <?php
 
 ini_set('memory_limit', '2G');
-ini_set('safe_mode', 0);
 // phpcs:disable
 eval(cv('php:boot --level=classloader', 'phpcode'));
 // phpcs:enable
index 6591c5bb16766a14576ff07e30193f4df1079d82..de4ef3511c525fc0e21f701e3d42693bbbaf8010 100644 (file)
@@ -31,13 +31,13 @@ class CRM_Core_Payment_EwayTest extends \PHPUnit\Framework\TestCase implements H
       ->apply();
   }
 
-  public function setUp() {
+  public function setUp(): void {
     $this->setUpEwayProcessor();
     $this->processor = \Civi\Payment\System::singleton()->getById($this->ids['PaymentProcessor']['eWAY']);
     parent::setUp();
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     $this->callAPISuccess('PaymentProcessor', 'delete', ['id' => $this->ids['PaymentProcessor']['eWAY']]);
     parent::tearDown();
   }
@@ -45,7 +45,7 @@ class CRM_Core_Payment_EwayTest extends \PHPUnit\Framework\TestCase implements H
   /**
    * Test making a once off payment
    */
-  public function testSinglePayment() {
+  public function testSinglePayment(): void {
     $this->setupMockHandler();
     $params = $this->getBillingParams();
     $params['amount'] = 10.00;
@@ -69,7 +69,7 @@ class CRM_Core_Payment_EwayTest extends \PHPUnit\Framework\TestCase implements H
   /**
    * Test making a failed once off payment
    */
-  public function testErrorSinglePayment() {
+  public function testErrorSinglePayment(): void {
     $this->setupMockHandler(NULL, TRUE);
     $params = $this->getBillingParams();
     $params['amount'] = 5.24;
@@ -125,7 +125,7 @@ class CRM_Core_Payment_EwayTest extends \PHPUnit\Framework\TestCase implements H
     ];
   }
 
-  public function setUpEwayProcessor() {
+  public function setUpEwayProcessor(): void {
     $params = [
       'name' => 'demo',
       'domain_id' => CRM_Core_Config::domainID(),
@@ -164,7 +164,7 @@ class CRM_Core_Payment_EwayTest extends \PHPUnit\Framework\TestCase implements H
    *
    * @throws \CiviCRM_API3_Exception
    */
-  protected function setupMockHandler($id = NULL, $error = FALSE) {
+  protected function setupMockHandler($id = NULL, $error = FALSE): void {
     if ($id) {
       $this->processor = Civi\Payment\System::singleton()->getById($id);
     }
@@ -181,7 +181,7 @@ class CRM_Core_Payment_EwayTest extends \PHPUnit\Framework\TestCase implements H
    *
    * @return array
    */
-  public function getExpectedSinglePaymentResponses() {
+  public function getExpectedSinglePaymentResponses(): array {
     return [
       '<ewayResponse><ewayTrxnStatus>True</ewayTrxnStatus><ewayTrxnNumber>10002</ewayTrxnNumber><ewayTrxnReference>xyz</ewayTrxnReference><ewayTrxnOption1/><ewayTrxnOption2/><ewayTrxnOption3/><ewayAuthCode>123456</ewayAuthCode><ewayReturnAmount>1000</ewayReturnAmount><ewayTrxnError>00,Transaction Approved(Test Gateway)</ewayTrxnError></ewayResponse>',
     ];
@@ -192,7 +192,7 @@ class CRM_Core_Payment_EwayTest extends \PHPUnit\Framework\TestCase implements H
    *
    * @return array
    */
-  public function getExpectedSinglePaymentRequests() {
+  public function getExpectedSinglePaymentRequests(): array {
     return [
       '<ewaygateway><ewayCustomerID>87654321</ewayCustomerID><ewayTotalAmount>1000</ewayTotalAmount><ewayCardHoldersName>John O&apos;Connor</ewayCardHoldersName><ewayCardNumber>4444333322221111</ewayCardNumber><ewayCardExpiryMonth>10</ewayCardExpiryMonth><ewayCardExpiryYear>22</ewayCardExpiryYear><ewayTrxnNumber>xyz</ewayTrxnNumber><ewayCustomerInvoiceDescription>Test Contribution</ewayCustomerInvoiceDescription><ewayCustomerFirstName>John</ewayCustomerFirstName><ewayCustomerLastName>O&apos;Connor</ewayCustomerLastName><ewayCustomerEmail>unittesteway@civicrm.org</ewayCustomerEmail><ewayCustomerAddress>8 Hobbitton Road, The Shire, NSW.</ewayCustomerAddress><ewayCustomerPostcode>5010</ewayCustomerPostcode><ewayCustomerInvoiceRef>xyz</ewayCustomerInvoiceRef><ewayCVN>123</ewayCVN><ewayOption1></ewayOption1><ewayOption2></ewayOption2><ewayOption3></ewayOption3><ewayCustomerIPAddress>127.0.0.1</ewayCustomerIPAddress><ewayCustomerBillingCountry>AUS</ewayCustomerBillingCountry></ewaygateway>',
     ];
@@ -203,7 +203,7 @@ class CRM_Core_Payment_EwayTest extends \PHPUnit\Framework\TestCase implements H
    *
    * @return array
    */
-  public function getExpectedSinglePaymentErrorResponses() {
+  public function getExpectedSinglePaymentErrorResponses(): array {
     return [
       '<ewayResponse><ewayTrxnStatus>False</ewayTrxnStatus><ewayTrxnNumber>10003</ewayTrxnNumber><ewayTrxnReference>xyz</ewayTrxnReference><ewayTrxnOption1/><ewayTrxnOption2/><ewayTrxnOption3/><ewayAuthCode>123456</ewayAuthCode><ewayReturnAmount>524</ewayReturnAmount><ewayTrxnError>24,Do Not Honour(Test Gateway)</ewayTrxnError></ewayResponse>',
     ];
index a5b49253c819c5ab65947070e7ee67d0cac48ea1..5133778c819133e6d0a8d558055d5aa1a48b1ec3 100644 (file)
@@ -1,7 +1,6 @@
 <?php
 
 ini_set('memory_limit', '2G');
-ini_set('safe_mode', 0);
 // phpcs:disable
 eval(cv('php:boot --level=classloader', 'phpcode'));
 // phpcs:enable
index 1ef9435ff1bda5b324008f393dcc41ca6772998d..0c24979bc2072cf1f222cf4e4516ec1dac036915 100644 (file)
@@ -19,7 +19,7 @@ class BuildAmountHookTest extends BaseTestClass {
   /**
    * Test api applies permissions on line item actions (delete & get).
    */
-  public function testBuildAmount() {
+  public function testBuildAmount(): void {
     $priceSet = PriceSet::create()->setValues(['name' => 'test', 'title' => 'test', 'extends' => 'CiviMember'])->execute()->first();
     PriceField::create()->setValues([
       'financial_type_id:name' => 'Donation',
index 33db7de3424cf4b5e70fa0f504d3310991052b9c..3f15b7ec0d795c103bfb89c00134ff06ffb34d03 100644 (file)
@@ -28,7 +28,7 @@ class LineItemTest extends BaseTestClass {
    *
    * @dataProvider versionThreeAndFour
    */
-  public function testLineItemApiPermissions($version) {
+  public function testLineItemApiPermissions($version): void {
     $contact1 = $this->individualCreate();
     $defaultPriceFieldID = $this->getDefaultPriceFieldID();
     $order = $this->callAPISuccess('Order', 'create', [
index 8e63eeeaa2c3a6afe70a6676bd51a36b09a65e26..df71a02e35532a05e4520d3aedfeca0808b4db95 100644 (file)
@@ -15,7 +15,7 @@ class MembershipTypesTest extends BaseTestClass {
   /**
    * Test buildMembershipTypes.
    */
-  public function testMembershipTypesHook() {
+  public function testMembershipTypesHook(): void {
     $types = MembershipType::save(FALSE)->setRecords([
       ['name' => 'Forbidden', 'financial_type_id:name' => 'Member Dues'],
       ['name' => 'Go for it', 'financial_type_id:name' => 'Donation'],
index 1f9ab60309a97a3c3a2992df698455149c2f3c15..2141178bc8b29d06b485dca1f79f9a7b55b1752f 100644 (file)
@@ -13,7 +13,7 @@ class OptionsTest extends BaseTestClass {
   /**
    * Test buildMembershipTypes.
    */
-  public function testBuildOptions() {
+  public function testBuildOptions(): void {
     $this->setupLoggedInUserWithLimitedFinancialTypeAccess();
     $options = \CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes();
     $this->assertEquals(['Donation'], array_merge($options));
index a5b49253c819c5ab65947070e7ee67d0cac48ea1..5133778c819133e6d0a8d558055d5aa1a48b1ec3 100644 (file)
@@ -1,7 +1,6 @@
 <?php
 
 ini_set('memory_limit', '2G');
-ini_set('safe_mode', 0);
 // phpcs:disable
 eval(cv('php:boot --level=classloader', 'phpcode'));
 // phpcs:enable
index a486daed2e2a482162a77c13b5e7a781749a1052..082e2c0f76aca0b3e88f7b85c33316856d6ca979 100644 (file)
@@ -19,7 +19,7 @@ use Civi\FlexMailer\ClickTracker\HtmlClickTracker;
  */
 class HtmlClickTrackerTest extends \CiviUnitTestCase {
 
-  public function setUp() {
+  public function setUp(): void {
     // Activate before transactions are setup.
     $manager = \CRM_Extension_System::singleton()->getManager();
     if ($manager->getStatus('org.civicrm.flexmailer') !== \CRM_Extension_Manager::STATUS_INSTALLED) {
@@ -79,7 +79,7 @@ class HtmlClickTrackerTest extends \CiviUnitTestCase {
    * @param $expectHtml
    * @dataProvider getHrefExamples
    */
-  public function testReplaceHref($inputHtml, $expectHtml) {
+  public function testReplaceHref($inputHtml, $expectHtml): void {
     $actual = HtmlClickTracker::replaceHrefUrls($inputHtml, function($url) {
       return "tracking($url)";
     });
index a99ac5473e987fc3eb018b743198e693f34df08c..64f8b7f8c08d7398e354ee0ba9a61172bd0202cf 100644 (file)
@@ -19,7 +19,7 @@ use Civi\FlexMailer\ClickTracker\TextClickTracker;
  */
 class TextClickTrackerTest extends \CiviUnitTestCase {
 
-  public function setUp() {
+  public function setUp(): void {
     // Activate before transactions are setup.
     $manager = \CRM_Extension_System::singleton()->getManager();
     if ($manager->getStatus('org.civicrm.flexmailer') !== \CRM_Extension_Manager::STATUS_INSTALLED) {
@@ -79,7 +79,7 @@ class TextClickTrackerTest extends \CiviUnitTestCase {
    * @param $expectHtml
    * @dataProvider getHrefExamples
    */
-  public function testReplaceTextUrls($inputHtml, $expectHtml) {
+  public function testReplaceTextUrls($inputHtml, $expectHtml): void {
     $inputText = \CRM_Utils_String::htmlToText($inputHtml);
     $expectText = \CRM_Utils_String::htmlToText($expectHtml);
     $expectText = str_replace('/tracking', 'tracking', $expectText);
index 1f723c5557c000151152a90da6ea33667029969c..91a7af91e272994f493824bf378f6d92d783ed84 100644 (file)
@@ -25,7 +25,7 @@ class ClickTrackerTest extends \PHPUnit\Framework\TestCase implements HeadlessIn
       ->apply();
   }
 
-  public function setUp() {
+  public function setUp(): void {
     // Mock the getTrackerURL call; we don't need to test creating a row in a table.
     // If you want this to work without runkit, then either (a) make the dummy rows or (b) switch this to a hook/event that is runtime-configurable.
     require_once 'CRM/Mailing/BAO/TrackableURL.php';
@@ -34,7 +34,7 @@ class ClickTrackerTest extends \PHPUnit\Framework\TestCase implements HeadlessIn
     parent::setUp();
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     // Reset the class.
     runkit7_method_remove('\CRM_Mailing_BAO_TrackableURL', 'getBasicTrackerURL');
     runkit7_method_rename('\CRM_Mailing_BAO_TrackableURL', 'orig_getBasicTrackerURL', 'getBasicTrackerURL');
@@ -44,7 +44,7 @@ class ClickTrackerTest extends \PHPUnit\Framework\TestCase implements HeadlessIn
   /**
    * Example: Test that a link without any tokens works.
    */
-  public function testLinkWithoutTokens() {
+  public function testLinkWithoutTokens(): void {
     $filter = new TextClickTracker();
     $msg = 'See this: https://example.com/foo/bar?a=b&c=d#frag';
     $result = $filter->filterContent($msg, 1, 1);
@@ -54,7 +54,7 @@ class ClickTrackerTest extends \PHPUnit\Framework\TestCase implements HeadlessIn
   /**
    * Example: Test that a link with tokens in the query works.
    */
-  public function testLinkWithTokensInQueryWithStaticParams() {
+  public function testLinkWithTokensInQueryWithStaticParams(): void {
     $filter = new TextClickTracker();
     $msg = 'See this: https://example.com/foo/bar?a=b&cid={contact.id}';
     $result = $filter->filterContent($msg, 1, 1);
@@ -64,7 +64,7 @@ class ClickTrackerTest extends \PHPUnit\Framework\TestCase implements HeadlessIn
   /**
    * Example: Test that a link with tokens in the query works.
    */
-  public function testLinkWithTokensInQueryWithMultipleStaticParams() {
+  public function testLinkWithTokensInQueryWithMultipleStaticParams(): void {
     $filter = new TextClickTracker();
     $msg = 'See this: https://example.com/foo/bar?cs={contact.checksum}&a=b&cid={contact.id}';
     $result = $filter->filterContent($msg, 1, 1);
@@ -74,7 +74,7 @@ class ClickTrackerTest extends \PHPUnit\Framework\TestCase implements HeadlessIn
   /**
    * Example: Test that a link with tokens in the query works.
    */
-  public function testLinkWithTokensInQueryWithMultipleStaticParamsHtml() {
+  public function testLinkWithTokensInQueryWithMultipleStaticParamsHtml(): void {
     $filter = new HtmlClickTracker();
     $msg = '<a href="https://example.com/foo/bar?cs={contact.checksum}&amp;a=b&amp;cid={contact.id}">See this</a>';
     $result = $filter->filterContent($msg, 1, 1);
@@ -84,7 +84,7 @@ class ClickTrackerTest extends \PHPUnit\Framework\TestCase implements HeadlessIn
   /**
    * Example: Test that a link with tokens in the query works.
    */
-  public function testLinkWithTokensInQueryWithoutStaticParams() {
+  public function testLinkWithTokensInQueryWithoutStaticParams(): void {
     $filter = new TextClickTracker();
     $msg = 'See this: https://example.com/foo/bar?cid={contact.id}';
     $result = $filter->filterContent($msg, 1, 1);
@@ -97,7 +97,7 @@ class ClickTrackerTest extends \PHPUnit\Framework\TestCase implements HeadlessIn
    * Seems browsers maintain the fragment when they receive a redirect, so a
    * token here might still work.
    */
-  public function testLinkWithTokensInFragment() {
+  public function testLinkWithTokensInFragment(): void {
     $filter = new TextClickTracker();
     $msg = 'See this: https://example.com/foo/bar?a=b#cid={contact.id}';
     $result = $filter->filterContent($msg, 1, 1);
@@ -110,7 +110,7 @@ class ClickTrackerTest extends \PHPUnit\Framework\TestCase implements HeadlessIn
    * Seems browsers maintain the fragment when they receive a redirect, so a
    * token here might still work.
    */
-  public function testLinkWithTokensInQueryAndFragment() {
+  public function testLinkWithTokensInQueryAndFragment(): void {
     $filter = new TextClickTracker();
     $msg = 'See this: https://example.com/foo/bar?a=b&cid={contact.id}#cid={contact.id}';
     $result = $filter->filterContent($msg, 1, 1);
@@ -120,7 +120,7 @@ class ClickTrackerTest extends \PHPUnit\Framework\TestCase implements HeadlessIn
   /**
    * We can't handle tokens in the domain so it should not be tracked.
    */
-  public function testLinkWithTokensInDomainFails() {
+  public function testLinkWithTokensInDomainFails(): void {
     $filter = new TextClickTracker();
     $msg = 'See this: https://{some.domain}.com/foo/bar';
     $result = $filter->filterContent($msg, 1, 1);
@@ -130,7 +130,7 @@ class ClickTrackerTest extends \PHPUnit\Framework\TestCase implements HeadlessIn
   /**
    * We can't handle tokens in the path so it should not be tracked.
    */
-  public function testLinkWithTokensInPathFails() {
+  public function testLinkWithTokensInPathFails(): void {
     $filter = new TextClickTracker();
     $msg = 'See this: https://example.com/{some.path}';
     $result = $filter->filterContent($msg, 1, 1);
index b68047122537ebfe50f8975dd38321a78ff1fc4d..69a496fa6abf5ae2bfb4e3afede3ff7de7ca9671 100644 (file)
@@ -33,7 +33,7 @@ require_once 'tests/phpunit/api/v3/JobProcessMailingTest.php';
  */
 class ConcurrentDeliveryTest extends \api_v3_JobProcessMailingTest {
 
-  public function setUp() {
+  public function setUp(): void {
     // Activate before transactions are setup.
     $manager = \CRM_Extension_System::singleton()->getManager();
     if ($manager->getStatus('org.civicrm.flexmailer') !== \CRM_Extension_Manager::STATUS_INSTALLED) {
@@ -45,7 +45,7 @@ class ConcurrentDeliveryTest extends \api_v3_JobProcessMailingTest {
     \Civi::settings()->set('flexmailer_traditional', 'flexmailer');
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     // We're building on someone else's test and don't fully trust them to
     // protect our settings. Make sure they did.
     $ok = ('flexmailer' == \Civi::settings()->get('flexmailer_traditional'))
@@ -65,11 +65,11 @@ class ConcurrentDeliveryTest extends \api_v3_JobProcessMailingTest {
    * @dataProvider concurrencyExamples
    * @see          _testConcurrencyCommon
    */
-  public function testConcurrency($settings, $expectedTallies, $expectedTotal) {
+  public function testConcurrency($settings, $expectedTallies, $expectedTotal): void {
     parent::testConcurrency($settings, $expectedTallies, $expectedTotal);
   }
 
-  public function testBasic() {
+  public function testBasic(): void {
     parent::testBasic();
   }
 
index a5b7d5c2b20f587f47c776558ba905df8f4d394b..12e8d5e69a08467d039bf231101d71b909686081 100644 (file)
@@ -39,7 +39,7 @@ class FlexMailerSystemTest extends \CRM_Mailing_BaseMailingSystemTest {
 
   private $counts;
 
-  public function setUp() {
+  public function setUp(): void {
     // Activate before transactions are setup.
     $manager = \CRM_Extension_System::singleton()->getManager();
     if ($manager->getStatus('org.civicrm.flexmailer') !== \CRM_Extension_Manager::STATUS_INSTALLED) {
@@ -80,7 +80,7 @@ class FlexMailerSystemTest extends \CRM_Mailing_BaseMailingSystemTest {
     $this->assertEquals('flexmailer', $context);
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     parent::tearDown();
     $this->assertNotEmpty($this->counts['hook_alterMailParams']);
     foreach (FlexMailer::getEventTypes() as $event => $class) {
@@ -106,7 +106,7 @@ class FlexMailerSystemTest extends \CRM_Mailing_BaseMailingSystemTest {
     $htmlUrlRegex,
     $textUrlRegex,
     $params
-  ) {
+  ): void {
     parent::testUrlTracking($inputHtml, $htmlUrlRegex, $textUrlRegex, $params);
   }
 
@@ -132,19 +132,19 @@ class FlexMailerSystemTest extends \CRM_Mailing_BaseMailingSystemTest {
     return $cases;
   }
 
-  public function testBasicHeaders() {
+  public function testBasicHeaders(): void {
     parent::testBasicHeaders();
   }
 
-  public function testText() {
+  public function testText(): void {
     parent::testText();
   }
 
-  public function testHtmlWithOpenTracking() {
+  public function testHtmlWithOpenTracking(): void {
     parent::testHtmlWithOpenTracking();
   }
 
-  public function testHtmlWithOpenAndUrlTracking() {
+  public function testHtmlWithOpenAndUrlTracking(): void {
     parent::testHtmlWithOpenAndUrlTracking();
   }
 
index 8a0eba86356a460df95cc03ca1a00efe7c3b5dd6..b7d4d7904f1d73048c07b0ccabb21e2f6ff46c19 100644 (file)
@@ -29,7 +29,7 @@ use Civi\FlexMailer\FlexMailerTask;
  */
 class SimpleFilterTest extends \CiviUnitTestCase {
 
-  public function setUp() {
+  public function setUp(): void {
     // Activate before transactions are setup.
     $manager = \CRM_Extension_System::singleton()->getManager();
     if ($manager->getStatus('org.civicrm.flexmailer') !== \CRM_Extension_Manager::STATUS_INSTALLED) {
@@ -42,7 +42,7 @@ class SimpleFilterTest extends \CiviUnitTestCase {
   /**
    * Ensure that the utility `SimpleFilter::byValue()` correctly filters.
    */
-  public function testByValue() {
+  public function testByValue(): void {
     $test = $this;
     list($tasks, $e) = $this->createExampleBatch();
 
@@ -63,7 +63,7 @@ class SimpleFilterTest extends \CiviUnitTestCase {
   /**
    * Ensure that the utility `SimpleFilter::byColumn()` correctly filters.
    */
-  public function testByColumn() {
+  public function testByColumn(): void {
     $test = $this;
     list($tasks, $e) = $this->createExampleBatch();
 
index 32cdd17597843159893dfba361a1d00ca5937260..a6fadbdc8c1452b2ac539c2dc830418ed874f114 100644 (file)
@@ -21,7 +21,7 @@ class MailingPreviewTest extends \CiviUnitTestCase {
    */
   protected $footer;
 
-  public function setUp() {
+  public function setUp(): void {
     // Activate before transactions are setup.
     $manager = \CRM_Extension_System::singleton()->getManager();
     if ($manager->getStatus('org.civicrm.flexmailer') !== \CRM_Extension_Manager::STATUS_INSTALLED) {
@@ -56,13 +56,13 @@ class MailingPreviewTest extends \CiviUnitTestCase {
     ));
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     // DGW
     \CRM_Mailing_BAO_MailingJob::$mailsProcessed = 0;
     parent::tearDown();
   }
 
-  public function testMailerPreview() {
+  public function testMailerPreview(): void {
     // BEGIN SAMPLE DATA
     $contactID = $this->individualCreate();
     $displayName = $this->callAPISuccess('contact', 'get',
@@ -99,7 +99,7 @@ class MailingPreviewTest extends \CiviUnitTestCase {
     $this->assertEquals('flexmailer', $previewResult['values']['_rendered_by_']);
   }
 
-  public function testMailerPreviewWithoutId() {
+  public function testMailerPreviewWithoutId(): void {
     // BEGIN SAMPLE DATA
     $contactID = $this->createLoggedInUser();
     $displayName = $this->callAPISuccess('contact', 'get', ['id' => $contactID]);
@@ -147,7 +147,7 @@ class MailingPreviewTest extends \CiviUnitTestCase {
    * @param array $expectMaxIds
    *   Array(string $table => int $maxId).
    */
-  protected function assertMaxIds($expectMaxIds) {
+  protected function assertMaxIds($expectMaxIds): void {
     foreach ($expectMaxIds as $table => $maxId) {
       $this->assertDBQuery($expectMaxIds[$table], 'SELECT MAX(id) FROM ' . $table, [], "Table $table should have a maximum ID of $maxId");
     }
index 3b5d9993488f37c80ed76bc4639c20a1e709225e..35541e5e6739370caeb81a45e03746c2914c1d5b 100644 (file)
@@ -17,7 +17,7 @@ namespace Civi\FlexMailer;
  */
 class ValidatorTest extends \CiviUnitTestCase {
 
-  public function setUp() {
+  public function setUp(): void {
     // Activate before transactions are setup.
     $manager = \CRM_Extension_System::singleton()->getManager();
     if ($manager->getStatus('org.civicrm.flexmailer') !== \CRM_Extension_Manager::STATUS_INSTALLED) {
@@ -85,7 +85,7 @@ class ValidatorTest extends \CiviUnitTestCase {
    * @param array $expectedErrors
    * @dataProvider getExamples
    */
-  public function testExamples($mailingData, $expectedErrors) {
+  public function testExamples($mailingData, $expectedErrors): void {
     $mailing = new \CRM_Mailing_DAO_Mailing();
     $mailing->copyValues($mailingData);
     $actualErrors = Validator::createAndRun($mailing);
index 048cc4b260e28fd1689f1fc108062ac5584dd139..ed4f208fece2c9be5c3dee642bd664b8137b4e26 100644 (file)
@@ -3,7 +3,6 @@
 require_once dirname(dirname(__DIR__)) . '/flexmailer.php';
 
 ini_set('memory_limit', '2G');
-ini_set('safe_mode', 0);
 
 // We need to allow CiviUnitTestCase... but may break E2E support....
 
index 06ee4b8c20a4659c12d8f18d4166b013b0adba0a..d5f8e9a858e5bf1aa692f0d5eb85a6c527098fdc 100644 (file)
@@ -18,15 +18,15 @@ class CRM_OAuth_MailSetupTest extends \PHPUnit\Framework\TestCase implements Hea
     return \Civi\Test::headless()->install('oauth-client')->apply();
   }
 
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     parent::tearDown();
   }
 
-  public function testEvalArrayTemplate() {
+  public function testEvalArrayTemplate(): void {
     $vars = array(
       'token' => [
         'client_id' => 10,
index 9cc4a1fe8269bbffcd658aad25e9681a56d639d1..a678726d491b367455d645a9e93583d15acbbd5b 100644 (file)
@@ -18,19 +18,19 @@ class api_v4_OAuthClientGrantTest extends \PHPUnit\Framework\TestCase implements
     return \Civi\Test::headless()->install('oauth-client')->apply();
   }
 
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
     $this->assertEquals(0, CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_oauth_client'));
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     parent::tearDown();
   }
 
   /**
    * Basic sanity check - create, read, and delete a client.
    */
-  public function testAuthorizationCode() {
+  public function testAuthorizationCode(): void {
     $usePerms = function($ps) {
       $base = ['access CiviCRM'];
       \CRM_Core_Config::singleton()->userPermissionClass->permissions = array_merge($base, $ps);
index d4107ea386e0e3015b194277071ca5f8003c0684..34ec0a09730e6f8f25468189bce318c2d9435def 100644 (file)
@@ -18,19 +18,19 @@ class api_v4_OAuthClientTest extends \PHPUnit\Framework\TestCase implements Head
     return \Civi\Test::headless()->install('oauth-client')->apply();
   }
 
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
     $this->assertEquals(0, CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_oauth_client'));
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     parent::tearDown();
   }
 
   /**
    * Basic sanity check - create, read, and delete a client.
    */
-  public function testBasic() {
+  public function testBasic(): void {
     $random = CRM_Utils_String::createRandom(16, CRM_Utils_String::ALPHANUMERIC);
     $usePerms = function($ps) {
       $base = ['access CiviCRM'];
@@ -83,7 +83,7 @@ class api_v4_OAuthClientTest extends \PHPUnit\Framework\TestCase implements Head
     }
   }
 
-  public function testUpdateBadProvider() {
+  public function testUpdateBadProvider(): void {
     $random = CRM_Utils_String::createRandom(16, CRM_Utils_String::ALPHANUMERIC);
     $usePerms = function($ps) {
       $base = ['access CiviCRM'];
index a7f54e880e433e8c58bc154a607ab90a92682c67..2643fc9284d546319f133f4f3814595ebc0ff676 100644 (file)
@@ -17,18 +17,18 @@ class api_v4_OAuthProviderTest extends \PHPUnit\Framework\TestCase implements He
     return \Civi\Test::headless()->install('oauth-client')->apply();
   }
 
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     parent::tearDown();
   }
 
   /**
    * Create, read, and destroy token - with full access to secrets.
    */
-  public function testGet() {
+  public function testGet(): void {
     \CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM'];
 
     $examples = Civi\Api4\OAuthProvider::get()
index 43b20790bba212fd0ebbb75a1a973cacf1c4062f..bcd061413854be7bdf048f15c3f3f83145e3ffa1 100644 (file)
@@ -18,20 +18,20 @@ class api_v4_OAuthSysTokenTest extends \PHPUnit\Framework\TestCase implements He
     return \Civi\Test::headless()->install('oauth-client')->apply();
   }
 
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
     $this->assertEquals(0, CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_oauth_client'));
     $this->assertEquals(0, CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_oauth_systoken'));
   }
 
-  public function tearDown() {
+  public function tearDown(): void {
     parent::tearDown();
   }
 
   /**
    * Create, read, and destroy token - with full access to secrets.
    */
-  public function testFullApiAccess() {
+  public function testFullApiAccess(): void {
     $random = CRM_Utils_String::createRandom(16, CRM_Utils_String::ALPHANUMERIC);
     $usePerms = function($ps) {
       $base = ['access CiviCRM'];
@@ -86,7 +86,7 @@ class api_v4_OAuthSysTokenTest extends \PHPUnit\Framework\TestCase implements He
   /**
    * Create, read, and destroy a token - with limited API access (cannot access token secrets).
    */
-  public function testLimitedApiAccess() {
+  public function testLimitedApiAccess(): void {
     $random = CRM_Utils_String::createRandom(16, CRM_Utils_String::ALPHANUMERIC);
     $usePerms = function($ps) {
       $base = ['access CiviCRM'];
@@ -159,7 +159,7 @@ class api_v4_OAuthSysTokenTest extends \PHPUnit\Framework\TestCase implements He
     $this->assertEquals("example-refresh-token-$random", $token['refresh_token']);
   }
 
-  public function testGetByScope() {
+  public function testGetByScope(): void {
     $random = CRM_Utils_String::createRandom(16, CRM_Utils_String::ALPHANUMERIC);
     $usePerms = function($ps) {
       $base = ['access CiviCRM'];
index 41c0800198e4f59066440a60cb0b2000e9caba3b..4d64ac46f20b72b7cf18a3502637c88da3ed3302 100644 (file)
@@ -1,7 +1,6 @@
 <?php
 
 ini_set('memory_limit', '2G');
-ini_set('safe_mode', 0);
 define('CIVICRM_TEST', 1);
 // phpcs:disable
 eval(cv('php:boot --level=classloader', 'phpcode'));
index 670d3ca54594c147efd8b4e3a1109e4451326d27..3f6de4d5eea7139877b9977cdb41c362a4e6298c 100644 (file)
@@ -84,4 +84,53 @@ class CRM_Search_Upgrader extends CRM_Search_Upgrader_Base {
     return TRUE;
   }
 
+  /**
+   * Upgrade 1002 - embellish search display link data
+   * @return bool
+   */
+  public function upgrade_1002() {
+    $this->ctx->log->info('Applying update 1002 - embellish search display link data.');
+    $displays = \Civi\Api4\SearchDisplay::get(FALSE)
+      ->setSelect(['id', 'settings'])
+      ->execute();
+    foreach ($displays as $display) {
+      $update = FALSE;
+      foreach ($display['settings']['columns'] ?? [] as $c => $column) {
+        if (!empty($column['link'])) {
+          $display['settings']['columns'][$c]['link'] = ['path' => $column['link']];
+          $update = TRUE;
+        }
+      }
+      if ($update) {
+        \Civi\Api4\SearchDisplay::update(FALSE)
+          ->setValues($display)
+          ->execute();
+      }
+    }
+    return TRUE;
+  }
+
+  /**
+   * Upgrade 1003 - update APIv4 join syntax in saved searches
+   * @return bool
+   */
+  public function upgrade_1003() {
+    $this->ctx->log->info('Applying 1003 - update APIv4 join syntax in saved searches.');
+    $savedSearches = \Civi\Api4\SavedSearch::get(FALSE)
+      ->addSelect('id', 'api_params')
+      ->addWhere('api_params', 'IS NOT NULL')
+      ->execute();
+    foreach ($savedSearches as $savedSearch) {
+      foreach ($savedSearch['api_params']['join'] ?? [] as $i => $join) {
+        $savedSearch['api_params']['join'][$i][1] = empty($join[1]) ? 'LEFT' : 'INNER';
+      }
+      if (!empty($savedSearch['api_params']['join'])) {
+        \Civi\Api4\SavedSearch::update(FALSE)
+          ->setValues($savedSearch)
+          ->execute();
+      }
+    }
+    return TRUE;
+  }
+
 }
index 9a890b6aa882655b196b8146525372d070e6b737..7ad2c72c9c1f69848639b5f897c0adbd84d221ab 100644 (file)
@@ -134,6 +134,12 @@ class Run extends \Civi\Api4\Generic\AbstractAction {
             $apiParams['select'][] = $idField;
           }
         }
+        // Select value fields for in-place editing
+        foreach ($settings['columns'] ?? [] as $column) {
+          if (isset($column['editable']['value']) && !in_array($column['editable']['value'], $apiParams['select'])) {
+            $apiParams['select'][] = $column['editable']['value'];
+          }
+        }
     }
 
     $this->applyFilters();
index bcb73ca433297b0b697aa2f2f5bad9d28bd08daa..5b77712b89887fd971bf350a6a29031287241713 100644 (file)
@@ -87,7 +87,7 @@ class Admin {
       ->setChain([
         'get' => ['$name', 'getActions', ['where' => [['name', '=', 'get']]], ['params']],
       ])->execute();
-    $getFields = ['name', 'title', 'label', 'description', 'options', 'input_type', 'input_attrs', 'data_type', 'serialize', 'entity', 'fk_entity'];
+    $getFields = ['name', 'title', 'label', 'description', 'options', 'input_type', 'input_attrs', 'data_type', 'serialize', 'entity', 'fk_entity', 'readonly'];
     foreach ($entities as $entity) {
       // Skip if entity doesn't have a 'get' action or the user doesn't have permission to use get
       if ($entity['get']) {
index 2297be29502f1476b889bd2888048d70fcf6a534..55f704e0b3759c37dea5a4c32c0c054071a7ad02 100644 (file)
@@ -13,6 +13,7 @@
 
     crmApi4(model.entity, 'getFields', {
       action: 'update',
+      select: ['name', 'label', 'description', 'data_type', 'serialize', 'options'],
       loadOptions: ['id', 'name', 'label', 'description', 'color', 'icon'],
       where: [["readonly", "=", false]],
     }).then(function(fields) {
index 3185d4cb8613734a75a69603d997f60f02e14a4e..7eb92ef116171e3f4ff83adfdfeb523b98478a26 100644 (file)
@@ -3,9 +3,8 @@
     <div ng-if=":: $ctrl.paramExists('join')">
       <fieldset ng-repeat="join in $ctrl.savedSearch.api_params.join">
         <div class="form-inline">
-          <label for="crm-search-join-{{ $index }}">{{:: ts('With') }}</label>
+          <select class="form-control" ng-model="join[1]" ng-change="$ctrl.changeJoinType(join)" ng-options="o.k as o.v for o in ::joinTypes" ></select>
           <input id="crm-search-join-{{ $index }}" class="form-control huge" ng-model="join[0]" crm-ui-select="{placeholder: ' ', data: getJoinEntities}" disabled >
-          <select class="form-control" ng-model="join[1]" ng-options="o.k as o.v for o in ::joinTypes" ></select>
           <button type="button" class="btn btn-xs btn-danger-outline" ng-click="$ctrl.removeJoin($index)" title="{{:: ts('Remove join') }}">
             <i class="crm-i fa-trash" aria-hidden="true"></i>
           </button>
@@ -16,7 +15,8 @@
       </fieldset>
       <fieldset>
         <div class="form-inline">
-          <input id="crm-search-add-join" class="form-control crm-action-menu fa-plus huge" ng-model="controls.join" crm-ui-select="{placeholder: ts('With'), data: getJoinEntities}" ng-change="addJoin()"/>
+          <select class="form-control" ng-model="controls.joinType" ng-options="o.k as o.v for o in ::joinTypes" ></select>
+          <input id="crm-search-add-join" class="form-control crm-action-menu fa-plus huge" ng-model="controls.join" crm-ui-select="{placeholder: ts('Entity'), data: getJoinEntities}" ng-change="addJoin()"/>
         </div>
       </fieldset>
     </div>
index a26a5b4066ab309e8e6b61791818b0cd56050396..feac4a41e15dd2db18b16c4cc530e1c975e049a1 100644 (file)
       // Have the filters (WHERE, HAVING, GROUP BY, JOIN) changed?
       this.stale = true;
 
-      $scope.controls = {tab: 'compose'};
-      $scope.joinTypes = [{k: false, v: ts('Optional')}, {k: true, v: ts('Required')}];
+      $scope.controls = {tab: 'compose', joinType: 'LEFT'};
+      $scope.joinTypes = [
+        {k: 'LEFT', v: ts('With (optional)')},
+        {k: 'INNER', v: ts('With (required)')},
+        {k: 'EXCLUDE', v: ts('Without')},
+      ];
       // Try to create a sensible list of entities one might want to search for,
       // excluding those whos primary purpose is to provide joins or option lists to other entities
       var primaryEntities = _.filter(CRM.crmSearchAdmin.schema, function(entity) {
             ctrl.savedSearch.api_params.join = ctrl.savedSearch.api_params.join || [];
             var join = searchMeta.getJoin($scope.controls.join),
               entity = searchMeta.getEntity(join.entity),
-              params = [$scope.controls.join, false];
+              params = [$scope.controls.join, $scope.controls.joinType || 'LEFT'];
             _.each(_.cloneDeep(join.conditions), function(condition) {
               params.push(condition);
             });
               params.push(condition);
             });
             ctrl.savedSearch.api_params.join.push(params);
-            if (entity.label_field) {
+            if (entity.label_field && $scope.controls.joinType !== 'EXCLUDE') {
               ctrl.savedSearch.api_params.select.push(join.alias + '.' + entity.label_field);
             }
             loadFieldOptions();
       this.removeJoin = function(index) {
         var alias = searchMeta.getJoin(ctrl.savedSearch.api_params.join[index][0]).alias;
         ctrl.clearParam('join', index);
+        removeJoinStuff(alias);
+      };
+
+      function removeJoinStuff(alias) {
         _.remove(ctrl.savedSearch.api_params.select, function(item) {
           var pattern = new RegExp('\\b' + alias + '\\.');
           return pattern.test(item.split(' AS ')[0]);
           return clauseUsesJoin(clause, alias);
         });
         _.eachRight(ctrl.savedSearch.api_params.join, function(item, i) {
-          if (searchMeta.getJoin(item[0]).alias.indexOf(alias) === 0) {
+          var joinAlias = searchMeta.getJoin(item[0]).alias;
+          if (joinAlias !== alias && joinAlias.indexOf(alias) === 0) {
             ctrl.removeJoin(i);
           }
         });
+      }
+
+      this.changeJoinType = function(join) {
+        if (join[1] === 'EXCLUDE') {
+          removeJoinStuff(searchMeta.getJoin(join[0]).alias);
+        }
       };
 
       $scope.changeGroupBy = function(idx) {
index 2e1e07654c7bb9b140a459d2d49a53b7bda2729e..f5806fcf4010751be54f7f0488c476b12a2c4c28 100644 (file)
         return ctrl.colTypes[col.type].label;
       };
 
+      this.toggleRewrite = function(col) {
+        if (col.rewrite) {
+          col.rewrite = '';
+        } else {
+          col.rewrite = '[' + col.key + ']';
+          delete col.editable;
+        }
+      };
+
+      this.toggleEditable = function(col) {
+        if (col.editable) {
+          delete col.editable;
+          return;
+        }
+
+        var info = searchMeta.parseExpr(col.key),
+          value = col.key.split(':')[0];
+        // If field is an implicit join, use the original fk field
+        if (info.field.entity !== info.field.baseEntity) {
+          value = value.substr(0, value.indexOf('.')) + '_id';
+          info = searchMeta.parseExpr(value);
+        }
+        col.editable = {
+          entity: info.field.baseEntity,
+          options: !!info.field.options,
+          serialize: !!info.field.serialize,
+          fk_entity: info.field.fk_entity,
+          id: info.prefix + 'id',
+          name: info.field.name,
+          value: value
+        };
+      };
+
+      this.isEditable = function(col) {
+        var expr = ctrl.getExprFromSelect(col.key),
+          info = searchMeta.parseExpr(expr);
+        return !col.rewrite && !col.link && !info.fn && info.field && !info.field.readonly;
+      };
+
       function fieldToColumn(fieldExpr, defaults) {
         var info = searchMeta.parseExpr(fieldExpr),
           values = _.cloneDeep(defaults);
         return values;
       }
 
+      this.toggleLink = function(column) {
+        if (column.link) {
+          ctrl.onChangeLink(column, column.link.path, '');
+        } else {
+          var defaultLink = ctrl.getLinks()[0];
+          column.link = {path: defaultLink ? defaultLink.path : 'civicrm/'};
+          ctrl.onChangeLink(column, null, column.link.path);
+        }
+      };
+
+      this.onChangeLink = function(column, before, after) {
+        var beforeLink = before && _.findWhere(ctrl.getLinks(), {path: before}),
+          afterLink = after && _.findWhere(ctrl.getLinks(), {path: after});
+        if (!after) {
+          if (beforeLink && column.title === beforeLink.title) {
+            delete column.title;
+          }
+          delete column.link;
+        } else if (afterLink && ((!column.title && !before) || (beforeLink && beforeLink.title === column.title))) {
+          column.title = afterLink.title;
+        } else if (!afterLink && (beforeLink && beforeLink.title === column.title)) {
+          delete column.title;
+        }
+      };
+
       this.getLinks = function() {
         if (!ctrl.links) {
           ctrl.links = buildLinks();
               var idField = info.field.fk_entity ? fieldName : fieldName.substr(0, fieldName.lastIndexOf('.')) + '_id';
               if (!ctrl.crmSearchAdmin.canAggregate(idField)) {
                 var joinEntity = searchMeta.getEntity(info.field.fk_entity || info.field.entity);
-                _.each(joinEntity.paths, function(path) {
+                _.each((joinEntity || {}).paths, function(path) {
                   var link = _.cloneDeep(path);
                   link.path = link.path.replace(/\[id/g, '[' + idField);
                   links.push(link);
index b528ad0ba614ee43f6ac05bd3d89a8dd8ca70e9f..3ff0962ecbd730bd718f0f47fe2abea446e7b0a5 100644 (file)
 
       this.styles = CRM.crmSearchAdmin.styles;
 
-      this.setValue = function(val, index) {
-        var link = ctrl.getLink(val),
-          item = ctrl.group[index];
-        if (item.path === val) {
-          return;
-        }
-        item.path = val;
-        item.icon = link ? defaultIcons[link.action] : 'fa-external-link';
-        if (val === 'civicrm/') {
-          $timeout(function () {
-            $('tr:eq(' + index + ') input[type=text]', $element).focus();
-          });
-        }
+      this.getStyle = function(item) {
+        return _.findWhere(this.styles, {key: item.style});
       };
 
       this.sortableOptions = {
             ctrl.addItem('civicrm/');
           }
         }
-        $element.on('change', 'select.crm-search-admin-select-path', function() {
+        $element.on('change', 'select.crm-search-admin-add-link', function() {
           var $select = $(this);
           $scope.$apply(function() {
-            if ($select.closest('tfoot').length) {
-              ctrl.addItem($select.val());
-              $select.val('');
-            } else {
-              ctrl.setValue($select.val(), $select.closest('tr').index());
-            }
+            ctrl.addItem($select.val());
+            $select.val('');
           });
         });
       };
index 2846b600739632d0d2df03891a5e4ef549542620..87a236ce7fff912c60fd54d2db04cab11c2c8b61 100644 (file)
@@ -3,6 +3,7 @@
     <tr>
       <th class="crm-search-admin-icon-col"></th>
       <th class="crm-search-admin-icon-col">{{:: ts('Icon') }}</th>
+      <th>{{:: ts('Open') }}</th>
       <th>{{:: ts('Text') }}</th>
       <th>{{:: ts('Link') }}</th>
       <th>{{:: ts('Style') }}</th>
     </tr>
   </thead>
   <tbody ui-sortable="$ctrl.sortableOptions" ng-model="$ctrl.group">
-    <tr ng-repeat="item in $ctrl.group" class="bg-{{ item.style }}">
+    <tr ng-repeat="item in $ctrl.group" class="crm-draggable">
       <td class="crm-search-admin-icon-col">
-        <i class="crm-i fa-arrows disabled"></i>
+        <i class="crm-i fa-arrows crm-search-move-icon"></i>
       </td>
       <td class="crm-search-admin-icon-col">
         <span class="crm-editable-enabled" ng-click="pickIcon($index)">
-          <i class="{{ item.icon ? 'crm-i ' + item.icon : '' }}"></i>
+          <i class="{{ item.icon ? 'crm-i ' + item.icon : '' }}" style="opacity: 1"></i>
         </span>
       </td>
+      <td>
+        <select class="form-control" ng-model="item.target">
+          <option value>{{:: ts('Normal') }}</option>
+          <option value="_blank">{{:: ts('New tab') }}</option>
+          <option value="crm-popup">{{:: ts('Popup dialog') }}</option>
+        </select>
+      </td>
       <td>
         <input type="text" class="form-control" ng-model="item.text">
       </td>
       <td class="form-inline">
-        <select class="form-control crm-search-admin-select-path" ng-show="$ctrl.links.length">
-          <option ng-repeat="link in $ctrl.links" value="{{ link.path }}" ng-selected="item.path === link.path">
-            {{ link.title }}
-          </option>
-          <option value="civicrm/" ng-selected="item.path && !$ctrl.getLink(item.path)">
-            {{ ts('Other...') }}
-          </option>
-        </select>
-        <input class="form-control" type="text" ng-if="item.path && !$ctrl.getLink(item.path)" ng-model="item.path" ng-model-options="{updateOn: 'blur'}" />
-        <crm-search-admin-token-select ng-if="item.path && !$ctrl.getLink(item.path)" api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" model="item" field="path"></crm-search-admin-token-select>
+        <crm-search-admin-link-select api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" link="item" links="$ctrl.links"></crm-search-admin-link-select>
       </td>
-      <td class="form-inline">
-        <select class="form-control" ng-model="item.style">
-          <option ng-repeat="opt in $ctrl.styles" value="{{ opt.key }}">{{ opt.value }}</option>
-        </select>
+      <td>
+        <div class="btn-group">
+          <button type="button" style="min-width: 85px" class="btn btn-{{ item.style }} dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+            {{ $ctrl.getStyle(item).value }} <span class="caret"></span>
+          </button>
+          <ul class="dropdown-menu dropdown-menu-right">
+            <li ng-repeat="opt in $ctrl.styles">
+              <a href class="bg-{{:: opt.key }}" ng-click="item.style = opt.key">{{:: opt.value }}</a>
+            </li>
+          </ul>
+        </div>
       </td>
       <td class="crm-search-admin-icon-col">
         <button ng-if="$ctrl.group.length > 1" type="button" class="btn btn-xs btn-danger-outline" ng-click="$ctrl.group.splice($index, 1)">
@@ -49,7 +55,7 @@
   <tfoot>
     <tr>
       <td colspan="6" class="form-inline">
-        <select class="form-control crm-search-admin-select-path" ng-show="$ctrl.links.length">
+        <select class="form-control crm-search-admin-add-link" ng-show="$ctrl.links.length">
           <option value="">
             + {{:: ts('Add...') }}
           </option>
index 394f8158e4783e6fc9c89e769d6329a762e48ce3..6d39b945c8dca698d94ad2b887a728640afcae6e 100644 (file)
@@ -3,10 +3,11 @@
 
   angular.module('crmSearchAdmin').component('crmSearchAdminLinkSelect', {
     bindings: {
-      column: '<',
+      link: '<',
       apiEntity: '<',
       apiParams: '<',
-      links: '<'
+      links: '<',
+      onChange: '&'
     },
     templateUrl: '~/crmSearchAdmin/crmSearchAdminLinkSelect.html',
     controller: function ($scope, $element, $timeout) {
         ctrl = this;
 
       this.setValue = function(val) {
+        ctrl.link  = ctrl.link  || {};
         var link = ctrl.getLink(val),
-          oldLink = ctrl.getLink(ctrl.column.link);
-        if (link) {
-          ctrl.column.link = link.path;
-          ctrl.column.title = link.title;
-        } else {
-          if (val === 'civicrm/') {
-            ctrl.column.link = val;
-            $timeout(function () {
-              $('input[type=text]', $element).focus();
-            });
-          } else {
-            ctrl.column.link = '';
-          }
-          if (oldLink && ctrl.column.title === oldLink.title) {
-            ctrl.column.title = '';
-          }
+          oldVal = ctrl.link.path;
+        ctrl.link.path = val;
+        if (!link) {
+          $timeout(function () {
+            $('input[type=text]', $element).focus();
+          });
         }
-      };
-
-      function onChange() {
-        var val = $('select', $element).val();
-        if (val !== ctrl.column.link) {
-          ctrl.setValue(val);
-        }
-      }
-
-      this.$onInit = function() {
-        $('select', $element).on('change', function() {
-          $scope.$apply(onChange);
-        });
+        ctrl.onChange({before: oldVal, after: val});
       };
 
       this.getLink = function(path) {
index 855f9fdb71e8aeab285eb1bf2029b6af906fc080..9cd67a5a6c33ef3101aeff726ffb60f080603529 100644 (file)
@@ -1,14 +1,20 @@
-<label title="{{ ts('Display as clickable link') }}" >
-  <input type="checkbox" ng-checked="$ctrl.column.link" ng-click="$ctrl.setValue($ctrl.column.link ? '' : ($ctrl.links[0] && $ctrl.links[0].path || 'civicrm/'))" >
-  {{ $ctrl.column.link ? ts('Link:') : ts('Link') }}
-</label>
-<select class="form-control" ng-show="$ctrl.links.length && $ctrl.column.link">
-  <option ng-repeat="link in $ctrl.links" value="{{ link.path }}" ng-selected="$ctrl.column.link === link.path">
-    {{ link.title }}
-  </option>
-  <option value="civicrm/" ng-selected="$ctrl.column.link && !$ctrl.getLink($ctrl.column.link)">
-    {{ ts('Other...') }}
-  </option>
-</select>
-<input class="form-control" type="text" ng-if="$ctrl.column.link && !$ctrl.getLink($ctrl.column.link)" ng-model="$ctrl.column.link" ng-model-options="{updateOn: 'blur'}" />
-<crm-search-admin-token-select ng-if="$ctrl.column.link && !$ctrl.getLink($ctrl.column.link)" api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" model="$ctrl.column" field="link"></crm-search-admin-token-select>
+<div class="crm-flex-1 input-group" >
+  <input type="text" class="form-control" ng-if="!$ctrl.getLink($ctrl.link.path)" ng-model="$ctrl.link.path" ng-model-options="{updateOn: 'blur'}" ng-change="$ctrl.onChange({before: 'civicrm/', after: $ctrl.link.path})">
+  <div class="input-group-btn" style="{{ $ctrl.getLink($ctrl.link.path) ? '' : 'width:27px' }}">
+    <button type="button" class="btn btn-default-outline dropdown-toggle" style="min-width: 200px; text-align: left;" ng-if="$ctrl.getLink($ctrl.link.path)" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+      {{ $ctrl.getLink($ctrl.link.path).title }}
+    </button>
+    <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+      <span class="caret"></span>
+    </button>
+    <ul class="dropdown-menu {{ $ctrl.getLink($ctrl.link.path) ? '' : 'dropdown-menu-right' }}" style="min-width: 223px;">
+      <li ng-repeat="link in $ctrl.links" ng-class="{disabled: $ctrl.link.path === link.path}">
+        <a href ng-click="$ctrl.setValue(link.path)">{{:: link.title }}</a>
+      </li>
+      <li ng-class="{disabled: !$ctrl.getLink($ctrl.link.path)}">
+        <a href ng-click="$ctrl.setValue('civicrm/')">{{:: ts('Other...') }}</a>
+      </li>
+    </ul>
+  </div>
+</div>
+<crm-search-admin-token-select ng-if="!$ctrl.getLink($ctrl.link.path)" api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" model="$ctrl.link" field="path"></crm-search-admin-token-select>
index 20e1976e79a0e1d649c45c3a22a8d86b63ee54d7..7b0969cbd27e8620c4d4c6f6c955b0579912d758 100644 (file)
@@ -1,17 +1,39 @@
-<crm-search-admin-link-select class="form-inline crm-search-admin-flex-row" column="col" api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" links=":: $ctrl.parent.getLinks()"></crm-search-admin-link-select>
+<div class="form-inline crm-search-admin-flex-row">
+  <label title="{{ ts('Display as clickable link') }}" >
+    <input type="checkbox" ng-checked="col.link" ng-click="$ctrl.parent.toggleLink(col)" >
+    {{ col.link ? ts('Link:') : ts('Link') }}
+  </label>
+  <select class="form-control" ng-model="$ctrl.link.target" ng-if="col.link">
+    <option value>{{:: ts('Open normally') }}</option>
+    <option value="_blank">{{:: ts('New tab') }}</option>
+    <option value="crm-popup">{{:: ts('Popup dialog') }}</option>
+  </select>
+  <crm-search-admin-link-select ng-if="col.link" link="col.link" on-change="$ctrl.parent.onChangeLink(col, before, after)" api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" links=":: $ctrl.parent.getLinks()">
+  </crm-search-admin-link-select>
+</div>
 <div class="form-inline crm-search-admin-flex-row">
   <label>
     <input type="checkbox" ng-checked="col.title" ng-click="col.title = col.title ? null : $ctrl.parent.getFieldLabel(col.key)" >
     {{ col.title ? ts('Tooltip:') : ts('Tooltip') }}
   </label>
-  <input class="form-control" type="text" ng-model="col.title" ng-if="col.title" ng-model-options="{updateOn: 'blur'}" />
+  <input class="form-control crm-flex-1" type="text" ng-model="col.title" ng-if="col.title" ng-model-options="{updateOn: 'blur'}" />
   <crm-search-admin-token-select ng-if="col.title" api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" model="col" field="title"></crm-search-admin-token-select>
 </div>
 <div class="form-inline crm-search-admin-flex-row">
   <label title="{{ ts('Change the contents of this field, or combine multiple field values.') }}">
-    <input type="checkbox" ng-checked="col.rewrite" ng-click="col.rewrite = col.rewrite ? null : '['+col.key+']'" >
+    <input type="checkbox" ng-checked="col.rewrite" ng-click="$ctrl.parent.toggleRewrite(col)" >
     {{ col.rewrite ? ts('Rewrite:') : ts('Rewrite') }}
   </label>
-  <input type="text" class="form-control" ng-if="col.rewrite" ng-model="col.rewrite" ng-model-options="{updateOn: 'blur'}">
+  <input type="text" class="form-control crm-flex-1" ng-if="col.rewrite" ng-model="col.rewrite" ng-model-options="{updateOn: 'blur'}">
   <crm-search-admin-token-select ng-if="col.rewrite" api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" model="col" field="rewrite"></crm-search-admin-token-select>
 </div>
+<div class="form-inline">
+  <label ng-if="$ctrl.parent.isEditable(col)" title="{{:: ts('Users will be able to click to edit this field.') }}">
+    <input type="checkbox" ng-checked="col.editable" ng-click="$ctrl.parent.toggleEditable(col)">
+    {{:: ts('In-place edit') }}
+  </label>
+  <label ng-if="!$ctrl.parent.isEditable(col)" class="disabled" title="{{:: ts('Read-only or rewritten fields cannot be editable.') }}">
+    <input type="checkbox" disabled>
+    {{:: ts('In-place edit') }}
+  </label>
+</div>
index 382c808751973b28675d3f3ae2b32bf355409509..362cde215a3e9249770d8d16eac9c718878733c8 100644 (file)
@@ -28,7 +28,7 @@
   </legend>
   <div class="crm-search-admin-edit-columns" ng-model="$ctrl.display.settings.columns" ui-sortable="$ctrl.parent.sortableOptions">
     <fieldset ng-repeat="col in $ctrl.display.settings.columns" class="crm-draggable">
-      <legend>{{ $ctrl.parent.getColLabel(col) }}</legend>
+      <legend><i class="crm-i fa-arrows crm-search-move-icon"></i> {{ $ctrl.parent.getColLabel(col) }}</legend>
       <div class="form-inline" title="{{ ts('Should this item display on its own line or inline with other items?') }}">
         <label><input type="checkbox" ng-model="col.break"> {{:: ts('Display on new line') }}</label>
         <button type="button" class="btn-xs pull-right" ng-click="$ctrl.parent.removeCol($index)" title="{{:: ts('Remove') }}">
@@ -40,7 +40,7 @@
           <input type="checkbox" ng-checked="col.label" ng-click="col.label = col.label ? null : $ctrl.parent.getColLabel(col)" >
           {{ col.label ? ts('Label:') : ts('Label') }}
         </label>
-        <input ng-if="col.label" class="form-control" type="text" ng-model="col.label" ng-model-options="{updateOn: 'blur'}">
+        <input ng-if="col.label" class="form-control crm-flex-1" type="text" ng-model="col.label" ng-model-options="{updateOn: 'blur'}">
         <crm-search-admin-token-select ng-if="col.label" api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" model="col" field="label"></crm-search-admin-token-select>
       </div>
       <div class="form-inline" ng-if="col.label">
index 7aa5d91f68044c736fd45bea5d527ab4544e31d6..5264ceb1cb6575f2d70db707b12e00794bfb0623 100644 (file)
   </legend>
   <div class="crm-search-admin-edit-columns" ng-model="$ctrl.display.settings.columns" ui-sortable="$ctrl.parent.sortableOptions">
     <fieldset ng-repeat="col in $ctrl.display.settings.columns" class="crm-draggable">
-      <legend>{{ $ctrl.parent.getColLabel(col) }}</legend>
+      <legend><i class="crm-i fa-arrows crm-search-move-icon"></i> {{ $ctrl.parent.getColLabel(col) }}</legend>
       <div class="form-inline crm-search-admin-flex-row">
         <label for="crm-search-admin-edit-col-{{ $index }}">{{:: ts('Header:') }}</label>
-        <input id="crm-search-admin-edit-col-{{ $index }}" class="form-control" type="text" ng-model="col.label" >
+        <input id="crm-search-admin-edit-col-{{ $index }}" class="form-control crm-flex-1" type="text" ng-model="col.label" >
         <button type="button" class="btn-xs" ng-click="$ctrl.parent.removeCol($index)" title="{{:: ts('Remove') }}">
           <i class="crm-i fa-ban"></i>
         </button>
index 7c134b9f4741f9a6a76cd82f55c00fd55b3b99a1..1a27992c4a5edc767bdb64fc03a0d828c6aef62b 100644 (file)
           displayValue = column.rewrite ? replaceTokens(column.rewrite, rowData, rowMeta) : formatRawValue(column, rowData[key]),
           result = _.escape(displayValue);
         if (column.link) {
-          result = '<a href="' + _.escape(getUrl(column.link, rowData)) + '">' + result + '</a>';
+          var target = '';
+          if (column.link.target) {
+            target = column.link.target === 'crm-popup' ? 'class="crm-popup" ' : 'target="' + column.link.target + '" ';
+          }
+          result = '<a ' + target + 'href="' + _.escape(getUrl(column.link.path, rowData)) + '">' + result + '</a>';
         }
         return result;
       }
@@ -74,9 +78,9 @@
       }
 
       function getResults(ctrl) {
-        var params = getApiParams(ctrl);
-        crmApi4('SearchDisplay', 'run', params).then(function(results) {
+        return crmApi4('SearchDisplay', 'run', getApiParams(ctrl)).then(function(results) {
           ctrl.results = results;
+          ctrl.editing = false;
           if (ctrl.settings.pager && !ctrl.rowCount) {
             if (results.length < ctrl.settings.limit) {
               ctrl.rowCount = results.length;
index f18030cf3c2a47403b59a65b8b67a758128ed465..7630a9b86352490fe47c207eb2bcdb63ebd51cb7 100644 (file)
@@ -1,5 +1,5 @@
 <span ng-repeat="item in col.links">
-  <a class="btn {{:: col.size }} btn-{{:: item.style }}" href="{{:: displayUtils.getUrl(item.path, row) }}">
+  <a class="btn {{:: col.size }} btn-{{:: item.style }} {{:: item.target }}" target="{{:: item.target }}" href="{{:: displayUtils.getUrl(item.path, row) }}">
     <i ng-if=":: item.icon" class="crm-i {{:: item.icon }}"></i>
     {{:: item.text }}
   </a>
index 1c6106010025ccc5336ee02dfa89700fd92f35ca..4f21543abf02a38e9f307be2f40565087b8ef815 100644 (file)
@@ -1 +1,2 @@
-<span ng-bind-html="$ctrl.formatFieldValue(row, col)"></span>
+<crm-search-display-editable row="row" col="col" on-success="$ctrl.refresh(row)" cancel="$ctrl.editing = null;" ng-if="col.editable && $ctrl.editing && $ctrl.editing[0] === rowIndex && $ctrl.editing[1] === col.key"></crm-search-display-editable>
+<span ng-bind-html=":: $ctrl.formatFieldValue(row, col)" ng-class="{'crm-editable-enabled': col.editable && !$ctrl.editing && row[col.editable.id]}" ng-click="col.editable && !$ctrl.editing && ($ctrl.editing = [rowIndex, col.key])"></span>
index d0a248047338a2f9bb67515167077b903bff0b73..d84651693d176a988cafbff775c081c3ee24625b 100644 (file)
@@ -1,5 +1,5 @@
 <span ng-repeat="item in col.links">
-  <a class="text-{{:: item.style }}" href="{{:: displayUtils.getUrl(item.path, row) }}">
+  <a class="text-{{:: item.style }} {{:: item.target }}" target="{{:: item.target }}" href="{{:: displayUtils.getUrl(item.path, row) }}">
     <i ng-if=":: item.icon" class="crm-i {{:: item.icon }}"></i>
     {{:: item.text }}
   </a>
index a11b5319be60994e72560a83d4d0919d09ec6704..213f81442425dd185246a33635b8df5dd92d3a7e 100644 (file)
@@ -5,7 +5,7 @@
   </button>
   <ul class="dropdown-menu {{ col.alignment === 'text-right' ? 'dropdown-menu-right' : '' }}" ng-if=":: col.open">
     <li ng-repeat="item in col.links" class="bg-{{:: item.style }}">
-      <a href="{{:: displayUtils.getUrl(item.path, row) }}">
+      <a href="{{:: displayUtils.getUrl(item.path, row) }}" class="{{:: item.target }}" target="{{:: item.target }}">
         <i ng-if=":: item.icon" class="crm-i {{:: item.icon }}"></i>
         {{:: item.text }}
       </a>
diff --git a/ext/search/ang/crmSearchDisplay/crmSearchDisplayEditable.component.js b/ext/search/ang/crmSearchDisplay/crmSearchDisplayEditable.component.js
new file mode 100644 (file)
index 0000000..181c0d2
--- /dev/null
@@ -0,0 +1,83 @@
+// https://civicrm.org/licensing
+(function(angular, $, _) {
+  "use strict";
+
+  var optionsCache = {};
+
+  angular.module('crmSearchDisplay').component('crmSearchDisplayEditable', {
+    bindings: {
+      row: '<',
+      col: '<',
+      cancel: '&',
+      onSuccess: '&'
+    },
+    templateUrl: '~/crmSearchDisplay/crmSearchDisplayEditable.html',
+    controller: function($scope, $element, crmApi4, crmStatus) {
+      var ctrl = this,
+        initialValue,
+        col;
+
+      this.$onInit = function() {
+        col = this.col;
+        this.value = _.cloneDeep(this.row[col.editable.value]);
+        initialValue = _.cloneDeep(this.row[col.editable.value]);
+
+        this.field = {
+          data_type: col.dataType,
+          name: col.editable.name,
+          options: col.editable.options,
+          fk_entity: col.editable.fk_entity,
+          serialize: col.editable.serialize,
+        };
+
+        $(document).on('keydown.crmSearchDisplayEditable', function(e) {
+          if (e.key === 'Escape') {
+            $scope.$apply(function() {
+              ctrl.cancel();
+            });
+          } else if (e.key === 'Enter') {
+            $scope.$apply(ctrl.save);
+          }
+        });
+
+        if (this.field.options === true) {
+          loadOptions();
+        }
+      };
+
+      this.$onDestroy = function() {
+        $(document).off('.crmSearchDisplayEditable');
+      };
+
+      this.save = function() {
+        if (ctrl.value === initialValue) {
+          ctrl.cancel();
+          return;
+        }
+        var values = {id: ctrl.row[col.editable.id]};
+        values[col.editable.name] = ctrl.value;
+        $('input', $element).attr('disabled', true);
+        crmStatus({}, crmApi4(col.editable.entity, 'update', {
+          values: values
+        })).then(ctrl.onSuccess);
+      };
+
+      function loadOptions() {
+        var cacheKey = col.editable.entity + ' ' + ctrl.field.name;
+        if (optionsCache[cacheKey]) {
+          ctrl.field.options = optionsCache[cacheKey];
+          return;
+        }
+        crmApi4(col.editable.entity, 'getFields', {
+          action: 'update',
+          select: ['options'],
+          loadOptions: ['id', 'name', 'label', 'description', 'color', 'icon'],
+          where: [['name', '=', ctrl.field.name]],
+        }, 0).then(function(field) {
+          ctrl.field.options = optionsCache[cacheKey] = field.options;
+        });
+      }
+    }
+  });
+
+})(angular, CRM.$, CRM._);
diff --git a/ext/search/ang/crmSearchDisplay/crmSearchDisplayEditable.html b/ext/search/ang/crmSearchDisplay/crmSearchDisplayEditable.html
new file mode 100644 (file)
index 0000000..d0d8eca
--- /dev/null
@@ -0,0 +1,9 @@
+<crm-search-input class="form-inline" field="$ctrl.field" ng-model="$ctrl.value"></crm-search-input>
+<div class="form-inline crm-search-display-editable-buttons">
+  <button type="button" ng-click="$ctrl.save()" class="btn btn-xs btn-success">
+    <i class="crm-i fa-check"></i>
+  </button>
+  <button type="button" ng-click="$ctrl.cancel()" class="btn btn-xs btn-danger">
+    <i class="crm-i fa-times"></i>
+  </button>
+</div>
index 3245db91c2803fb59dc1514b7d4db1559c0a302a..2153e6dc1e920caa8ce802c28a0983f50c321173 100644 (file)
         $scope.displayUtils = searchDisplayUtils;
 
         if (this.afFieldset) {
-          $scope.$watch(this.afFieldset.getFieldData, refresh, true);
+          $scope.$watch(this.afFieldset.getFieldData, onChangeFilters, true);
         }
-        $scope.$watch('$ctrl.filters', refresh, true);
+        $scope.$watch('$ctrl.filters', onChangeFilters, true);
       };
 
       this.getResults = _.debounce(function() {
         searchDisplayUtils.getResults(ctrl);
       }, 100);
 
-      function refresh() {
+      // Refresh current page
+      this.refresh = function(row) {
+        searchDisplayUtils.getResults(ctrl);
+      };
+
+      function onChangeFilters() {
         ctrl.page = 1;
         ctrl.rowCount = null;
         ctrl.getResults();
index 00c0f55e47a958555503e6a93ef5687c006522b8..9d039ba19cc8f6c0619da6ecdc0c22a1c1c40e4e 100644 (file)
@@ -1,3 +1,5 @@
-<ol ng-if=":: $ctrl.settings.style === 'ol'" ng-include="'~/crmSearchDisplayList/crmSearchDisplayListItems.html'" ng-style="{'list-style': $ctrl.settings.symbol}"></ol>
-<ul ng-if=":: $ctrl.settings.style !== 'ol'" ng-include="'~/crmSearchDisplayList/crmSearchDisplayListItems.html'" ng-style="{'list-style': $ctrl.settings.symbol}"></ul>
-<div ng-include="'~/crmSearchDisplay/Pager.html'"></div>
+<div class="crm-search-display crm-search-display-list">
+  <ol ng-if=":: $ctrl.settings.style === 'ol'" ng-include="'~/crmSearchDisplayList/crmSearchDisplayListItems.html'" ng-style="{'list-style': $ctrl.settings.symbol}"></ol>
+  <ul ng-if=":: $ctrl.settings.style !== 'ol'" ng-include="'~/crmSearchDisplayList/crmSearchDisplayListItems.html'" ng-style="{'list-style': $ctrl.settings.symbol}"></ul>
+  <div ng-include="'~/crmSearchDisplay/Pager.html'"></div>
+</div>
index e99f04b04f09cb74798984863a9c346c5671b83f..59bae1aab8db509f4b62ddc58006b56863f788d1 100644 (file)
@@ -1,4 +1,4 @@
-<li ng-repeat="row in $ctrl.results">
+<li ng-repeat="(rowIndex, row) in $ctrl.results">
   <div ng-repeat="col in $ctrl.settings.columns" title="{{:: displayUtils.replaceTokens(col.title, row, $ctrl.settings.columns) }}" class="{{:: col.break ? '' : 'crm-inline-block' }}">
     <label ng-if=":: col.label && (col.type !== 'field' || col.forceLabel || row[col.key])">
       {{:: displayUtils.replaceTokens(col.label, row, $ctrl.settings.columns) }}
index 27a8aa11c8d9aaf6845cef816488c80901c29667..dfc029ab5f63cd09f1e7a40cbd4908699e26bfb2 100644 (file)
         $scope.displayUtils = searchDisplayUtils;
 
         if (this.afFieldset) {
-          $scope.$watch(this.afFieldset.getFieldData, refresh, true);
+          $scope.$watch(this.afFieldset.getFieldData, onChangeFilters, true);
         }
-        $scope.$watch('$ctrl.filters', refresh, true);
+        $scope.$watch('$ctrl.filters', onChangeFilters, true);
       };
 
       this.getResults = _.debounce(function() {
         searchDisplayUtils.getResults(ctrl);
       }, 100);
 
-      function refresh() {
+      // Refresh page after inline-editing a row
+      this.refresh = function(row) {
+        var rowId = row.id;
+        searchDisplayUtils.getResults(ctrl)
+          .then(function() {
+            // If edited row disappears (because edits cause it to not meet search criteria), deselect it
+            var index = ctrl.selectedRows.indexOf(rowId);
+            if (index > -1 && !_.findWhere(ctrl.results, {id: rowId})) {
+              ctrl.selectedRows.splice(index, 1);
+            }
+          });
+      };
+
+      function onChangeFilters() {
         ctrl.page = 1;
         ctrl.rowCount = null;
+        ctrl.selectedRows.legth = 0;
+        ctrl.allRowsSelected = false;
         ctrl.getResults();
       }
 
index 3c408c3b885da0ac72d5e4e8458eaea43e59e4bc..e867270f728f1ae5e6b27748950011ddd4a5a6c8 100644 (file)
@@ -1,27 +1,29 @@
-<div class="form-inline" ng-if="$ctrl.settings.actions">
-  <crm-search-actions entity="$ctrl.apiEntity" ids="$ctrl.selectedRows" refresh="$ctrl.getResults()"></crm-search-actions>
+<div class="crm-search-display crm-search-display-table">
+  <div class="form-inline" ng-if="$ctrl.settings.actions">
+    <crm-search-actions entity="$ctrl.apiEntity" ids="$ctrl.selectedRows" refresh="$ctrl.getResults()"></crm-search-actions>
+  </div>
+  <table>
+    <thead>
+      <tr>
+        <th class="crm-search-result-select" ng-if=":: $ctrl.settings.actions">
+          <input type="checkbox" ng-checked="$ctrl.allRowsSelected" ng-click="selectAllRows()" >
+        </th>
+        <th ng-repeat="col in $ctrl.settings.columns" ng-click="setSort(col, $event)" title="{{:: ts('Click to sort results (shift-click to sort by multiple).') }}">
+          <i ng-if="col.type === 'field'" class="crm-i {{ getSort(col) }}"></i>
+          <span>{{ col.label }}</span>
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr ng-repeat="(rowIndex, row) in $ctrl.results">
+        <td ng-if=":: $ctrl.settings.actions">
+          <input type="checkbox" ng-checked="isRowSelected(row)" ng-click="selectRow(row)" ng-disabled="!(!loadingAllRows && row.id)">
+        </td>
+        <td ng-repeat="col in $ctrl.settings.columns" ng-include="'~/crmSearchDisplay/colType/' + col.type + '.html'" title="{{:: displayUtils.replaceTokens(col.title, row, $ctrl.settings.columns) }}" class="{{:: col.alignment }}">
+        </td>
+        <td></td>
+      </tr>
+    </tbody>
+  </table>
+  <div ng-include="'~/crmSearchDisplay/Pager.html'"></div>
 </div>
-<table>
-  <thead>
-    <tr>
-      <th class="crm-search-result-select" ng-if="$ctrl.settings.actions">
-        <input type="checkbox" ng-checked="$ctrl.allRowsSelected" ng-click="selectAllRows()" >
-      </th>
-      <th ng-repeat="col in $ctrl.settings.columns" ng-click="setSort(col, $event)" title="{{:: ts('Click to sort results (shift-click to sort by multiple).') }}">
-        <i ng-if="col.type === 'field'" class="crm-i {{ getSort(col) }}"></i>
-        <span>{{ col.label }}</span>
-      </th>
-    </tr>
-  </thead>
-  <tbody>
-    <tr ng-repeat="row in $ctrl.results">
-      <td ng-if="$ctrl.settings.actions">
-        <input type="checkbox" ng-checked="isRowSelected(row)" ng-click="selectRow(row)" ng-disabled="!(!loadingAllRows && row.id)">
-      </td>
-      <td ng-repeat="col in $ctrl.settings.columns" ng-include="'~/crmSearchDisplay/colType/' + col.type + '.html'" title="{{:: displayUtils.replaceTokens(col.title, row, $ctrl.settings.columns) }}" class="{{:: col.alignment }}">
-      </td>
-      <td></td>
-    </tr>
-  </tbody>
-</table>
-<div ng-include="'~/crmSearchDisplay/Pager.html'"></div>
index 877e7ddaaaa4bf0682d2a3da374e723a3ffccdfc..aab0e8c9dca1ff3487d870acb3a5f64e5e6a430c 100644 (file)
@@ -3,3 +3,22 @@
   margin-top: 10px;
   border: 1px solid lightgrey;
 }
+
+.crm-search-display.crm-search-display-table td > crm-search-display-editable,
+.crm-search-display.crm-search-display-table td > .crm-editable-enabled {
+  display: block !important;
+}
+
+.crm-search-display crm-search-display-editable {
+  position: relative;
+}
+
+.crm-search-display crm-search-display-editable + span {
+  display: none !important;
+}
+
+.crm-search-display .crm-search-display-editable-buttons {
+  position: absolute;
+  bottom: -22px;
+  left: 0;
+}
index aaf1c5bc2681e7cd9a5dfcc124c7a6a99ae75f44..0bad2c7879e977d2b0e9f72697683cb584a52b14 100644 (file)
   display: inline-block;
 }
 
-#bootstrap-theme.crm-search i.fa-arrows {
-  cursor: move;
+#bootstrap-theme.crm-search i.crm-search-move-icon {
+  opacity: .5;
+}
+#bootstrap-theme.crm-search .crm-draggable:hover > * > i.crm-search-move-icon {
+  opacity: 1;
 }
 
 #bootstrap-theme.crm-search .api4-clause-badge {
 #bootstrap-theme.crm-search .api4-clause-badge .caret {
   margin: 0;
 }
+/* Icon only shown while dragging */
 #bootstrap-theme.crm-search .api4-clause-badge .crm-i {
   display: none;
   padding: 0 6px;
   background-color: rgba(255, 255, 255, .8);
 }
 
+/* A flex-row arranges elements inline, with the 'crm-flex-*' item(s) taking up all remaining space */
 #bootstrap-theme .crm-search-admin-flex-row {
   display: flex;
   align-items: center;
 #bootstrap-theme .crm-search-admin-flex-row > *:not(:first-child) {
   margin-left: 6px;
 }
-#bootstrap-theme .crm-search-admin-flex-row > input[type=text] {
-  flex: 1;
-}
 
 #bootstrap-theme .crm-search-admin-unused-columns fieldset {
   min-height: 60px;
index 0f9f25d307a9cd62aa26edb1928ddf2de81d249a..fc8f870b723b86a3cdf77609656b6ce38d0288ce 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<phpunit backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" syntaxCheck="false" bootstrap="tests/phpunit/bootstrap.php">
+<phpunit backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" bootstrap="tests/phpunit/bootstrap.php">
   <testsuites>
     <testsuite name="My Test Suite">
       <directory>./tests/phpunit</directory>
index 507b39a92182a1c04e6cf69a7a0c24c92a55dc53..58bda954fdbc3bb39a6a47cbc8b1e23967621c9d 100644 (file)
@@ -45,7 +45,7 @@ class SequentialcreditnotesTest extends \PHPUnit\Framework\TestCase implements H
    * @throws \CRM_Core_Exception
    * @throws \CiviCRM_API3_Exception
    */
-  public function testCreateCreditNoteId() {
+  public function testCreateCreditNoteId(): void {
     $this->_apiversion = 4;
     $contactId = $this->callAPISuccess('Contact', 'create', ['contact_type' => 'Individual', 'email' => 'b@example.com'])['id'];
 
index 352e007050f2a100faafc6c95b15e38820286699..f530038c3ff7920ba511b0f168f21a7127410f3f 100644 (file)
@@ -1,7 +1,6 @@
 <?php
 
 ini_set('memory_limit', '2G');
-ini_set('safe_mode', 0);
 // phpcs:ignore
 eval(cv('php:boot --level=classloader', 'phpcode'));
 
@@ -20,16 +19,16 @@ $loader->register();
  *   The rest of the command to send.
  * @param string $decode
  *   Ex: 'json' or 'phpcode'.
+ *
  * @return string
  *   Response output (if the command executed normally).
- * @throws \RuntimeException
- *   If the command terminates abnormally.
+ * @throws \RuntimeException If the command terminates abnormally.
  */
-function cv($cmd, $decode = 'json') {
+function cv(string $cmd, $decode = 'json'): string {
   $cmd = 'cv ' . $cmd;
-  $descriptorSpec = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => STDERR);
+  $descriptorSpec = [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => STDERR];
   $oldOutput = getenv('CV_OUTPUT');
-  putenv("CV_OUTPUT=json");
+  putenv('CV_OUTPUT=json');
 
   // Execute `cv` in the original folder. This is a work-around for
   // phpunit/codeception, which seem to manipulate PWD.
@@ -49,7 +48,7 @@ function cv($cmd, $decode = 'json') {
 
     case 'phpcode':
       // If the last output is /*PHPCODE*/, then we managed to complete execution.
-      if (substr(trim($result), 0, 12) !== "/*BEGINPHP*/" || substr(trim($result), -10) !== "/*ENDPHP*/") {
+      if (strpos(trim($result), '/*BEGINPHP*/') !== 0 || substr(trim($result), -10) !== '/*ENDPHP*/') {
         throw new \RuntimeException("Command failed ($cmd):\n$result");
       }
       return $result;
index 63db35419386429c233873a266a33656c1ca280a..1db1f25885f7f037af559efa45f3b0a83e223579 100644 (file)
@@ -436,11 +436,26 @@ if (!CRM.vars) CRM.vars = {};
           formatResult: formatCrmSelect2,
           formatSelection: formatCrmSelect2
         };
+
       // quickform doesn't support optgroups so here's a hack :(
+      // Instead of using wrapAll or similar that repeatedly appends options to the group and redraw the page (=> very slow on large lists),
+      // build bulk HTML and insert in single shot
+      var optGroups = {};
       $('option[value^=crm_optgroup]', this).each(function () {
-        $(this).nextUntil('option[value^=crm_optgroup]').wrapAll('<optgroup label="' + $(this).text() + '" />');
+        var groupHtml = '';
+          $(this).nextUntil('option[value^=crm_optgroup]').each(function () {
+          groupHtml += this.outerHTML;
+        });
+        optGroups[$(this).text()] = groupHtml;
         $(this).remove();
       });
+      var replacedHtml = '';
+      for (var groupLabel in optGroups) {
+        replacedHtml += '<optgroup label="' + groupLabel + '">' + optGroups[groupLabel] + '</optgroup>';
+      }
+      if (replacedHtml) {
+        $el.html(replacedHtml);
+      }
 
       // quickform does not support disabled option, so yet another hack to
       // add disabled property for option values
index d28f0983498f6a908f41c5b3839575871977f3ba..a9177bb5b2ced16a5bcff09953e02aa41d9acc2c 100644 (file)
               CRM.menubar.open('QuickSearch');
             }
           }
-        });
+        })
+        .autocomplete( "instance" )._renderItem = function( ul, item ) {
+          var uiMenuItemWrapper = $("<div class='ui-menu-item-uiMenuItemWrapper'>");
+          if (item.value == 0) {
+            uiMenuItemWrapper.text(item.label);
+          }
+          else {
+            uiMenuItemWrapper.append($('<a>')
+              .attr('href', CRM.url('civicrm/contact/view', {reset: 1, cid: item.value}))
+              .css({ display: 'block' })
+              .text(item.label)
+              .click(function(e) {
+                if (e.ctrlKey || e.shiftKey || e.altKey) {
+                  // Special-clicking lets you open several tabs.
+                  e.stopPropagation();
+                }
+                else {
+                  // Fall back to original behaviour.
+                  e.preventDefault();
+                }
+              }));
+          }
+
+          return $( "<li class='ui-menu-item'>" )
+            .append(uiMenuItemWrapper)
+            .appendTo( ul );
+        };
       $('#crm-qsearch > a').keyup(function(e) {
         if ($(e.target).is(this)) {
           $('#crm-qsearch-input').focus();
index 220e60bd81b25fa6252d69f60ac8828d76305bbb..9a38911cf9e9cd5a20a17ab595ebb3f09dc10532 100644 (file)
@@ -15,6 +15,16 @@ Other resources for identifying changes are:
     * https://github.com/civicrm/civicrm-joomla
     * https://github.com/civicrm/civicrm-wordpress
 
+## CiviCRM 5.35.1
+
+Released March 17, 2021
+
+- **[Synopsis](release-notes/5.35.1.md#synopsis)**
+- **[Security advisories](release-notes/5.35.1.md#security)**
+- **[Bugs resolved](release-notes/5.35.1.md#bugs)**
+- **[Credits](release-notes/5.35.1.md#credits)**
+- **[Feedback](release-notes/5.35.1.md#feedback)**
+
 ## CiviCRM 5.35.0
 
 Released March 3, 2021
diff --git a/release-notes/5.35.1.md b/release-notes/5.35.1.md
new file mode 100644 (file)
index 0000000..f539638
--- /dev/null
@@ -0,0 +1,58 @@
+# CiviCRM 5.35.1
+
+Released March 17, 2021
+
+- **[Synopsis](#synopsis)**
+- **[Bugs resolved](#bugs)**
+- **[Credits](#credits)**
+- **[Feedback](#feedback)**
+
+## <a name="synopsis"></a>Synopsis
+
+| *Does this version...?*                                         |          |
+| --------------------------------------------------------------- | -------- |
+| Change the database schema?                                     | no       |
+| Alter the API?                                                  | no       |
+| Require attention to configuration options?                     | no       |
+| **Fix problems installing or upgrading to a previous version?** | **yes**  |
+| Introduce features?                                             | no       |
+| **Fix bugs?**                                                   | **yes**  |
+
+## <a name="security"></a>Security advisories
+
+- **[CIVI-SA-2021-01](https://civicrm.org/advisory/civi-sa-2021-01-reflected-cross-site-scripting-uploaded-csvs)**: Reflected Cross Site Scripting via Uploaded CSVs
+- **[CIVI-SA-2021-02](https://civicrm.org/advisory/civi-sa-2021-02-web-executable-utility-scripts)**: Web Executable Utility Scripts
+- **[CIVI-SA-2021-03](https://civicrm.org/advisory/civi-sa-2021-03-cross-site-scripting-manage-extensions)**: Cross Site Scripting in "Manage Extensions"
+- **[CIVI-SA-2021-04](https://civicrm.org/advisory/civi-sa-2021-04-cross-site-scripting-apiv4-explorer)**: Cross Site Scripting in the APIv4 Explorer
+- **[CIVI-SA-2021-05](https://civicrm.org/advisory/civi-sa-2021-05-reflected-cross-site-scripting-personal-campaign-pages)**: Reflected Cross Site Scripting in Personal Campaign Pages
+- **[CIVI-SA-2021-06](https://civicrm.org/advisory/civi-sa-2021-06-timing-attacks-against-site-key)**: Timing Attacks Against the Site Key
+- **[CIVI-SA-2021-07](https://civicrm.org/advisory/civi-sa-2021-07-sql-injection-joomla-user-integration)**: SQL injection in Joomla user integration
+
+## <a name="bugs"></a>Bugs resolved
+
+* **_CiviCampaign_: Fix error when reserving respondents for a survey ([#19811](https://github.com/civicrm/civicrm-core/pull/19811))**
+* **_Upgrader_: Fix handling of "group_title" in certain upgrade-paths ([dev/translation#58](https://lab.civicrm.org/dev/translation/-/issues/58): [#19740](https://github.com/civicrm/civicrm-core/pull/19740))**
+* **_D8 / Asset Builder_: Fail gracefully when certain resources cannot be generted ([dev/core#2137](https://lab.civicrm.org/dev/core/-/issues/2137): [#18830](https://github.com/civicrm/civicrm-core/pull/18830))**
+
+  A common misconfiguration on Drupal 8+ is to omit `enable-patching`. This currently manifests as an error about `crm-menubar.css`. The change does not fix the misconfiguration, but it makes the error more manageable.
+
+## <a name="credits"></a>Credits
+
+Special support from Deutsche Gesellschaft für Internationale Zusammenarbeit
+GmbH contributed significantly to this release and other contemporaneous
+security improvements.
+
+This release was developed by the following authors and reviewers:
+
+Wikimedia Foundation - Eileen McNaughton; Stephen Palmstrom; Semper IT - Karin
+Gerritsen; Progressive Technology Project - Jamie McClelland; Megaphone Technology
+Consulting - Jon Goldberg; MJW Consulting - Matthew Wire; MJCO - Mikey O'Toole; JMA
+Consulting - Seamus Lee, Monish Deb; Fuzion - Luke Stewart; Dmitry Smirnov; Dave D;
+CiviCRM - Tim Otten, Coleman Watts; Circle Interactive - Pradeep Nayak; Blackfly
+Solutions - Alan Dixon; Artful Robot - Rich Lott; AGH Strategies - Andrew Hunt
+
+## <a name="feedback"></a>Feedback
+
+These release notes are edited by Tim Otten and Andrew Hunt.  If you'd like to
+provide feedback on them, please login to https://chat.civicrm.org/civicrm and
+contact `@agh1`.
index 63c2b30b23a861ab2fae3e8f1c9dfca1d36a8409..40dca615a15c95dd4be554118078f8350b5b619d 100644 (file)
  *
  */
 
+if (!(php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0))) {
+  header("HTTP/1.0 404 Not Found");
+  return;
+}
 
 require_once '../civicrm.config.php';
 CRM_Core_Config::singleton();
index 205b73d518952bc4ed2550ebe8f9548dbfe850f7..18381428ea9132eaab2d375abdca02dde137c171 100644 (file)
  * @package CRM
  * @copyright CiviCRM LLC https://civicrm.org/licensing
  */
+if (!(php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0))) {
+  header("HTTP/1.0 404 Not Found");
+  return;
+}
 
 require_once '../civicrm.config.php';
 
index d9af5ca112712e418c80b8122e58d52f5a568acf..1ea8e744e8d04b977eb6631dc3343d4a004f7217 100644 (file)
  * @package CRM
  * @copyright CiviCRM LLC https://civicrm.org/licensing
  */
+if (!(php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0))) {
+  header("HTTP/1.0 404 Not Found");
+
+  return;
+}
 
 require_once '../civicrm.config.php';
 
index f415959c6a009eec56ec0a50a6e71d3d59522e4a..bfb77ad0b35447e09aa7491965126f0c06f68bcc 100644 (file)
  * php versions.
  * @todo look to remove this file completely.
  */
-
+if (!(php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0))) {
+  header("HTTP/1.0 404 Not Found");
+  return;
+}
 
 require_once '../civicrm.config.php';
 
index 27063d65d492481162b3bd0dce7a22e2cdea0ad3..b1eb494497daa4ed62e05c9853d44e996925f2e5 100644 (file)
@@ -1328,7 +1328,7 @@ UNLOCK TABLES;
 
 LOCK TABLES `civicrm_state_province` WRITE;
 /*!40000 ALTER TABLE `civicrm_state_province` DISABLE KEYS */;
-INSERT INTO `civicrm_state_province` (`id`, `name`, `abbreviation`, `country_id`) VALUES (1000,'Alabama','AL',1228),(1001,'Alaska','AK',1228),(1002,'Arizona','AZ',1228),(1003,'Arkansas','AR',1228),(1004,'California','CA',1228),(1005,'Colorado','CO',1228),(1006,'Connecticut','CT',1228),(1007,'Delaware','DE',1228),(1008,'Florida','FL',1228),(1009,'Georgia','GA',1228),(1010,'Hawaii','HI',1228),(1011,'Idaho','ID',1228),(1012,'Illinois','IL',1228),(1013,'Indiana','IN',1228),(1014,'Iowa','IA',1228),(1015,'Kansas','KS',1228),(1016,'Kentucky','KY',1228),(1017,'Louisiana','LA',1228),(1018,'Maine','ME',1228),(1019,'Maryland','MD',1228),(1020,'Massachusetts','MA',1228),(1021,'Michigan','MI',1228),(1022,'Minnesota','MN',1228),(1023,'Mississippi','MS',1228),(1024,'Missouri','MO',1228),(1025,'Montana','MT',1228),(1026,'Nebraska','NE',1228),(1027,'Nevada','NV',1228),(1028,'New Hampshire','NH',1228),(1029,'New Jersey','NJ',1228),(1030,'New Mexico','NM',1228),(1031,'New York','NY',1228),(1032,'North Carolina','NC',1228),(1033,'North Dakota','ND',1228),(1034,'Ohio','OH',1228),(1035,'Oklahoma','OK',1228),(1036,'Oregon','OR',1228),(1037,'Pennsylvania','PA',1228),(1038,'Rhode Island','RI',1228),(1039,'South Carolina','SC',1228),(1040,'South Dakota','SD',1228),(1041,'Tennessee','TN',1228),(1042,'Texas','TX',1228),(1043,'Utah','UT',1228),(1044,'Vermont','VT',1228),(1045,'Virginia','VA',1228),(1046,'Washington','WA',1228),(1047,'West Virginia','WV',1228),(1048,'Wisconsin','WI',1228),(1049,'Wyoming','WY',1228),(1050,'District of Columbia','DC',1228),(1052,'American Samoa','AS',1228),(1053,'Guam','GU',1228),(1055,'Northern Mariana Islands','MP',1228),(1056,'Puerto Rico','PR',1228),(1057,'Virgin Islands','VI',1228),(1058,'United States Minor Outlying Islands','UM',1228),(1059,'Armed Forces Europe','AE',1228),(1060,'Armed Forces Americas','AA',1228),(1061,'Armed Forces Pacific','AP',1228),(1100,'Alberta','AB',1039),(1101,'British Columbia','BC',1039),(1102,'Manitoba','MB',1039),(1103,'New Brunswick','NB',1039),(1104,'Newfoundland and Labrador','NL',1039),(1105,'Northwest Territories','NT',1039),(1106,'Nova Scotia','NS',1039),(1107,'Nunavut','NU',1039),(1108,'Ontario','ON',1039),(1109,'Prince Edward Island','PE',1039),(1110,'Quebec','QC',1039),(1111,'Saskatchewan','SK',1039),(1112,'Yukon Territory','YT',1039),(1200,'Maharashtra','MM',1101),(1201,'Karnataka','KA',1101),(1202,'Andhra Pradesh','AP',1101),(1203,'Arunachal Pradesh','AR',1101),(1204,'Assam','AS',1101),(1205,'Bihar','BR',1101),(1206,'Chhattisgarh','CH',1101),(1207,'Goa','GA',1101),(1208,'Gujarat','GJ',1101),(1209,'Haryana','HR',1101),(1210,'Himachal Pradesh','HP',1101),(1211,'Jammu and Kashmir','JK',1101),(1212,'Jharkhand','JH',1101),(1213,'Kerala','KL',1101),(1214,'Madhya Pradesh','MP',1101),(1215,'Manipur','MN',1101),(1216,'Meghalaya','ML',1101),(1217,'Mizoram','MZ',1101),(1218,'Nagaland','NL',1101),(1219,'Orissa','OR',1101),(1220,'Punjab','PB',1101),(1221,'Rajasthan','RJ',1101),(1222,'Sikkim','SK',1101),(1223,'Tamil Nadu','TN',1101),(1224,'Tripura','TR',1101),(1225,'Uttarakhand','UT',1101),(1226,'Uttar Pradesh','UP',1101),(1227,'West Bengal','WB',1101),(1228,'Andaman and Nicobar Islands','AN',1101),(1229,'Dadra and Nagar Haveli','DN',1101),(1230,'Daman and Diu','DD',1101),(1231,'Delhi','DL',1101),(1232,'Lakshadweep','LD',1101),(1233,'Pondicherry','PY',1101),(1300,'mazowieckie','MZ',1172),(1301,'pomorskie','PM',1172),(1302,'dolnośląskie','DS',1172),(1303,'kujawsko-pomorskie','KP',1172),(1304,'lubelskie','LU',1172),(1305,'lubuskie','LB',1172),(1306,'łódzkie','LD',1172),(1307,'małopolskie','MA',1172),(1308,'opolskie','OP',1172),(1309,'podkarpackie','PK',1172),(1310,'podlaskie','PD',1172),(1311,'śląskie','SL',1172),(1312,'świętokrzyskie','SK',1172),(1313,'warmińsko-mazurskie','WN',1172),(1314,'wielkopolskie','WP',1172),(1315,'zachodniopomorskie','ZP',1172),(1500,'Abu Zaby','AZ',1225),(1501,'\'Ajman','AJ',1225),(1502,'Al Fujayrah','FU',1225),(1503,'Ash Shariqah','SH',1225),(1504,'Dubayy','DU',1225),(1505,'Ra\'s al Khaymah','RK',1225),(1506,'Dac Lac','33',1233),(1507,'Umm al Qaywayn','UQ',1225),(1508,'Badakhshan','BDS',1001),(1509,'Badghis','BDG',1001),(1510,'Baghlan','BGL',1001),(1511,'Balkh','BAL',1001),(1512,'Bamian','BAM',1001),(1513,'Farah','FRA',1001),(1514,'Faryab','FYB',1001),(1515,'Ghazni','GHA',1001),(1516,'Ghowr','GHO',1001),(1517,'Helmand','HEL',1001),(1518,'Herat','HER',1001),(1519,'Jowzjan','JOW',1001),(1520,'Kabul','KAB',1001),(1521,'Kandahar','KAN',1001),(1522,'Kapisa','KAP',1001),(1523,'Khowst','KHO',1001),(1524,'Konar','KNR',1001),(1525,'Kondoz','KDZ',1001),(1526,'Laghman','LAG',1001),(1527,'Lowgar','LOW',1001),(1528,'Nangrahar','NAN',1001),(1529,'Nimruz','NIM',1001),(1530,'Nurestan','NUR',1001),(1531,'Oruzgan','ORU',1001),(1532,'Paktia','PIA',1001),(1533,'Paktika','PKA',1001),(1534,'Parwan','PAR',1001),(1535,'Samangan','SAM',1001),(1536,'Sar-e Pol','SAR',1001),(1537,'Takhar','TAK',1001),(1538,'Wardak','WAR',1001),(1539,'Zabol','ZAB',1001),(1540,'Berat','BR',1002),(1541,'Bulqizë','BU',1002),(1542,'Delvinë','DL',1002),(1543,'Devoll','DV',1002),(1544,'Dibër','DI',1002),(1545,'Durrës','DR',1002),(1546,'Elbasan','EL',1002),(1547,'Fier','FR',1002),(1548,'Gramsh','GR',1002),(1549,'Gjirokastër','GJ',1002),(1550,'Has','HA',1002),(1551,'Kavajë','KA',1002),(1552,'Kolonjë','ER',1002),(1553,'Korçë','KO',1002),(1554,'Krujë','KR',1002),(1555,'Kuçovë','KC',1002),(1556,'Kukës','KU',1002),(1557,'Kurbin','KB',1002),(1558,'Lezhë','LE',1002),(1559,'Librazhd','LB',1002),(1560,'Lushnjë','LU',1002),(1561,'Malësi e Madhe','MM',1002),(1562,'Mallakastër','MK',1002),(1563,'Mat','MT',1002),(1564,'Mirditë','MR',1002),(1565,'Peqin','PQ',1002),(1566,'Përmet','PR',1002),(1567,'Pogradec','PG',1002),(1568,'Pukë','PU',1002),(1569,'Sarandë','SR',1002),(1570,'Skrapar','SK',1002),(1571,'Shkodër','SH',1002),(1572,'Tepelenë','TE',1002),(1573,'Tiranë','TR',1002),(1574,'Tropojë','TP',1002),(1575,'Vlorë','VL',1002),(1576,'Erevan','ER',1011),(1577,'Aragacotn','AG',1011),(1578,'Ararat','AR',1011),(1579,'Armavir','AV',1011),(1580,'Gegarkunik\'','GR',1011),(1581,'Kotayk\'','KT',1011),(1582,'Lory','LO',1011),(1583,'Sirak','SH',1011),(1584,'Syunik\'','SU',1011),(1585,'Tavus','TV',1011),(1586,'Vayoc Jor','VD',1011),(1587,'Bengo','BGO',1006),(1588,'Benguela','BGU',1006),(1589,'Bie','BIE',1006),(1590,'Cabinda','CAB',1006),(1591,'Cuando-Cubango','CCU',1006),(1592,'Cuanza Norte','CNO',1006),(1593,'Cuanza Sul','CUS',1006),(1594,'Cunene','CNN',1006),(1595,'Huambo','HUA',1006),(1596,'Huila','HUI',1006),(1597,'Luanda','LUA',1006),(1598,'Lunda Norte','LNO',1006),(1599,'Lunda Sul','LSU',1006),(1600,'Malange','MAL',1006),(1601,'Moxico','MOX',1006),(1602,'Namibe','NAM',1006),(1603,'Uige','UIG',1006),(1604,'Zaire','ZAI',1006),(1605,'Capital federal','C',1010),(1606,'Buenos Aires','B',1010),(1607,'Catamarca','K',1010),(1608,'Cordoba','X',1010),(1609,'Corrientes','W',1010),(1610,'Chaco','H',1010),(1611,'Chubut','U',1010),(1612,'Entre Rios','E',1010),(1613,'Formosa','P',1010),(1614,'Jujuy','Y',1010),(1615,'La Pampa','L',1010),(1616,'Mendoza','M',1010),(1617,'Misiones','N',1010),(1618,'Neuquen','Q',1010),(1619,'Rio Negro','R',1010),(1620,'Salta','A',1010),(1621,'San Juan','J',1010),(1622,'San Luis','D',1010),(1623,'Santa Cruz','Z',1010),(1624,'Santa Fe','S',1010),(1625,'Santiago del Estero','G',1010),(1626,'Tierra del Fuego','V',1010),(1627,'Tucuman','T',1010),(1628,'Burgenland','1',1014),(1629,'Kärnten','2',1014),(1630,'Niederösterreich','3',1014),(1631,'Oberösterreich','4',1014),(1632,'Salzburg','5',1014),(1633,'Steiermark','6',1014),(1634,'Tirol','7',1014),(1635,'Vorarlberg','8',1014),(1636,'Wien','9',1014),(1637,'Australian Antarctic Territory','AAT',1008),(1638,'Australian Capital Territory','ACT',1013),(1639,'Northern Territory','NT',1013),(1640,'New South Wales','NSW',1013),(1641,'Queensland','QLD',1013),(1642,'South Australia','SA',1013),(1643,'Tasmania','TAS',1013),(1644,'Victoria','VIC',1013),(1645,'Western Australia','WA',1013),(1646,'Naxcivan','NX',1015),(1647,'Ali Bayramli','AB',1015),(1648,'Baki','BA',1015),(1649,'Ganca','GA',1015),(1650,'Lankaran','LA',1015),(1651,'Mingacevir','MI',1015),(1652,'Naftalan','NA',1015),(1653,'Saki','SA',1015),(1654,'Sumqayit','SM',1015),(1655,'Susa','SS',1015),(1656,'Xankandi','XA',1015),(1657,'Yevlax','YE',1015),(1658,'Abseron','ABS',1015),(1659,'Agcabadi','AGC',1015),(1660,'Agdam','AGM',1015),(1661,'Agdas','AGS',1015),(1662,'Agstafa','AGA',1015),(1663,'Agsu','AGU',1015),(1664,'Astara','AST',1015),(1665,'Babak','BAB',1015),(1666,'Balakan','BAL',1015),(1667,'Barda','BAR',1015),(1668,'Beylagan','BEY',1015),(1669,'Bilasuvar','BIL',1015),(1670,'Cabrayll','CAB',1015),(1671,'Calilabad','CAL',1015),(1672,'Culfa','CUL',1015),(1673,'Daskasan','DAS',1015),(1674,'Davaci','DAV',1015),(1675,'Fuzuli','FUZ',1015),(1676,'Gadabay','GAD',1015),(1677,'Goranboy','GOR',1015),(1678,'Goycay','GOY',1015),(1679,'Haciqabul','HAC',1015),(1680,'Imisli','IMI',1015),(1681,'Ismayilli','ISM',1015),(1682,'Kalbacar','KAL',1015),(1683,'Kurdamir','KUR',1015),(1684,'Lacin','LAC',1015),(1685,'Lerik','LER',1015),(1686,'Masalli','MAS',1015),(1687,'Neftcala','NEF',1015),(1688,'Oguz','OGU',1015),(1689,'Ordubad','ORD',1015),(1690,'Qabala','QAB',1015),(1691,'Qax','QAX',1015),(1692,'Qazax','QAZ',1015),(1693,'Qobustan','QOB',1015),(1694,'Quba','QBA',1015),(1695,'Qubadli','QBI',1015),(1696,'Qusar','QUS',1015),(1697,'Saatli','SAT',1015),(1698,'Sabirabad','SAB',1015),(1699,'Sadarak','SAD',1015),(1700,'Sahbuz','SAH',1015),(1701,'Salyan','SAL',1015),(1702,'Samaxi','SMI',1015),(1703,'Samkir','SKR',1015),(1704,'Samux','SMX',1015),(1705,'Sarur','SAR',1015),(1706,'Siyazan','SIY',1015),(1707,'Tartar','TAR',1015),(1708,'Tovuz','TOV',1015),(1709,'Ucar','UCA',1015),(1710,'Xacmaz','XAC',1015),(1711,'Xanlar','XAN',1015),(1712,'Xizi','XIZ',1015),(1713,'Xocali','XCI',1015),(1714,'Xocavand','XVD',1015),(1715,'Yardimli','YAR',1015),(1716,'Zangilan','ZAN',1015),(1717,'Zaqatala','ZAQ',1015),(1718,'Zardab','ZAR',1015),(1719,'Federacija Bosna i Hercegovina','BIH',1026),(1720,'Republika Srpska','SRP',1026),(1721,'Bagerhat zila','05',1017),(1722,'Bandarban zila','01',1017),(1723,'Barguna zila','02',1017),(1724,'Barisal zila','06',1017),(1725,'Bhola zila','07',1017),(1726,'Bogra zila','03',1017),(1727,'Brahmanbaria zila','04',1017),(1728,'Chandpur zila','09',1017),(1729,'Chittagong zila','10',1017),(1730,'Chuadanga zila','12',1017),(1731,'Comilla zila','08',1017),(1732,'Cox\'s Bazar zila','11',1017),(1733,'Dhaka zila','13',1017),(1734,'Dinajpur zila','14',1017),(1735,'Faridpur zila','15',1017),(1736,'Feni zila','16',1017),(1737,'Gaibandha zila','19',1017),(1738,'Gazipur zila','18',1017),(1739,'Gopalganj zila','17',1017),(1740,'Habiganj zila','20',1017),(1741,'Jaipurhat zila','24',1017),(1742,'Jamalpur zila','21',1017),(1743,'Jessore zila','22',1017),(1744,'Jhalakati zila','25',1017),(1745,'Jhenaidah zila','23',1017),(1746,'Khagrachari zila','29',1017),(1747,'Khulna zila','27',1017),(1748,'Kishorganj zila','26',1017),(1749,'Kurigram zila','28',1017),(1750,'Kushtia zila','30',1017),(1751,'Lakshmipur zila','31',1017),(1752,'Lalmonirhat zila','32',1017),(1753,'Madaripur zila','36',1017),(1754,'Magura zila','37',1017),(1755,'Manikganj zila','33',1017),(1756,'Meherpur zila','39',1017),(1757,'Moulvibazar zila','38',1017),(1758,'Munshiganj zila','35',1017),(1759,'Mymensingh zila','34',1017),(1760,'Naogaon zila','48',1017),(1761,'Narail zila','43',1017),(1762,'Narayanganj zila','40',1017),(1763,'Narsingdi zila','42',1017),(1764,'Natore zila','44',1017),(1765,'Nawabganj zila','45',1017),(1766,'Netrakona zila','41',1017),(1767,'Nilphamari zila','46',1017),(1768,'Noakhali zila','47',1017),(1769,'Pabna zila','49',1017),(1770,'Panchagarh zila','52',1017),(1771,'Patuakhali zila','51',1017),(1772,'Pirojpur zila','50',1017),(1773,'Rajbari zila','53',1017),(1774,'Rajshahi zila','54',1017),(1775,'Rangamati zila','56',1017),(1776,'Rangpur zila','55',1017),(1777,'Satkhira zila','58',1017),(1778,'Shariatpur zila','62',1017),(1779,'Sherpur zila','57',1017),(1780,'Sirajganj zila','59',1017),(1781,'Sunamganj zila','61',1017),(1782,'Sylhet zila','60',1017),(1783,'Tangail zila','63',1017),(1784,'Thakurgaon zila','64',1017),(1785,'Antwerpen','VAN',1020),(1786,'Brabant Wallon','WBR',1020),(1787,'Hainaut','WHT',1020),(1788,'Liege','WLG',1020),(1789,'Limburg','VLI',1020),(1790,'Luxembourg','WLX',1020),(1791,'Namur','WNA',1020),(1792,'Oost-Vlaanderen','VOV',1020),(1793,'Vlaams-Brabant','VBR',1020),(1794,'West-Vlaanderen','VWV',1020),(1795,'Bale','BAL',1034),(1796,'Bam','BAM',1034),(1797,'Banwa','BAN',1034),(1798,'Bazega','BAZ',1034),(1799,'Bougouriba','BGR',1034),(1800,'Boulgou','BLG',1034),(1801,'Boulkiemde','BLK',1034),(1802,'Comoe','COM',1034),(1803,'Ganzourgou','GAN',1034),(1804,'Gnagna','GNA',1034),(1805,'Gourma','GOU',1034),(1806,'Houet','HOU',1034),(1807,'Ioba','IOB',1034),(1808,'Kadiogo','KAD',1034),(1809,'Kenedougou','KEN',1034),(1810,'Komondjari','KMD',1034),(1811,'Kompienga','KMP',1034),(1812,'Kossi','KOS',1034),(1813,'Koulpulogo','KOP',1034),(1814,'Kouritenga','KOT',1034),(1815,'Kourweogo','KOW',1034),(1816,'Leraba','LER',1034),(1817,'Loroum','LOR',1034),(1818,'Mouhoun','MOU',1034),(1819,'Nahouri','NAO',1034),(1820,'Namentenga','NAM',1034),(1821,'Nayala','NAY',1034),(1822,'Noumbiel','NOU',1034),(1823,'Oubritenga','OUB',1034),(1824,'Oudalan','OUD',1034),(1825,'Passore','PAS',1034),(1826,'Poni','PON',1034),(1827,'Sanguie','SNG',1034),(1828,'Sanmatenga','SMT',1034),(1829,'Seno','SEN',1034),(1830,'Siasili','SIS',1034),(1831,'Soum','SOM',1034),(1832,'Sourou','SOR',1034),(1833,'Tapoa','TAP',1034),(1834,'Tui','TUI',1034),(1835,'Yagha','YAG',1034),(1836,'Yatenga','YAT',1034),(1837,'Ziro','ZIR',1034),(1838,'Zondoma','ZON',1034),(1839,'Zoundweogo','ZOU',1034),(1840,'Blagoevgrad','01',1033),(1841,'Burgas','02',1033),(1842,'Dobrich','08',1033),(1843,'Gabrovo','07',1033),(1844,'Haskovo','26',1033),(1845,'Yambol','28',1033),(1846,'Kardzhali','09',1033),(1847,'Kyustendil','10',1033),(1848,'Lovech','11',1033),(1849,'Montana','12',1033),(1850,'Pazardzhik','13',1033),(1851,'Pernik','14',1033),(1852,'Pleven','15',1033),(1853,'Plovdiv','16',1033),(1854,'Razgrad','17',1033),(1855,'Ruse','18',1033),(1856,'Silistra','19',1033),(1857,'Sliven','20',1033),(1858,'Smolyan','21',1033),(1859,'Sofia','23',1033),(1860,'Stara Zagora','24',1033),(1861,'Shumen','27',1033),(1862,'Targovishte','25',1033),(1863,'Varna','03',1033),(1864,'Veliko Tarnovo','04',1033),(1865,'Vidin','05',1033),(1866,'Vratsa','06',1033),(1867,'Al Hadd','01',1016),(1868,'Al Manamah','03',1016),(1869,'Al Mintaqah al Gharbiyah','10',1016),(1870,'Al Mintagah al Wusta','07',1016),(1871,'Al Mintaqah ash Shamaliyah','05',1016),(1872,'Al Muharraq','02',1016),(1873,'Ar Rifa','09',1016),(1874,'Jidd Hafs','04',1016),(1875,'Madluat Jamad','12',1016),(1876,'Madluat Isa','08',1016),(1877,'Mintaqat Juzur tawar','11',1016),(1878,'Sitrah','06',1016),(1879,'Bubanza','BB',1036),(1880,'Bujumbura','BJ',1036),(1881,'Bururi','BR',1036),(1882,'Cankuzo','CA',1036),(1883,'Cibitoke','CI',1036),(1884,'Gitega','GI',1036),(1885,'Karuzi','KR',1036),(1886,'Kayanza','KY',1036),(1887,'Makamba','MA',1036),(1888,'Muramvya','MU',1036),(1889,'Mwaro','MW',1036),(1890,'Ngozi','NG',1036),(1891,'Rutana','RT',1036),(1892,'Ruyigi','RY',1036),(1893,'Alibori','AL',1022),(1894,'Atakora','AK',1022),(1895,'Atlantique','AQ',1022),(1896,'Borgou','BO',1022),(1897,'Collines','CO',1022),(1898,'Donga','DO',1022),(1899,'Kouffo','KO',1022),(1900,'Littoral','LI',1022),(1901,'Mono','MO',1022),(1902,'Oueme','OU',1022),(1903,'Plateau','PL',1022),(1904,'Zou','ZO',1022),(1905,'Belait','BE',1032),(1906,'Brunei-Muara','BM',1032),(1907,'Temburong','TE',1032),(1908,'Tutong','TU',1032),(1909,'Cochabamba','C',1025),(1910,'Chuquisaca','H',1025),(1911,'El Beni','B',1025),(1912,'La Paz','L',1025),(1913,'Oruro','O',1025),(1914,'Pando','N',1025),(1915,'Potosi','P',1025),(1916,'Tarija','T',1025),(1917,'Acre','AC',1029),(1918,'Alagoas','AL',1029),(1919,'Amazonas','AM',1029),(1920,'Amapa','AP',1029),(1921,'Bahia','BA',1029),(1922,'Ceara','CE',1029),(1923,'Distrito Federal','DF',1029),(1924,'Espirito Santo','ES',1029),(1926,'Goias','GO',1029),(1927,'Maranhao','MA',1029),(1928,'Minas Gerais','MG',1029),(1929,'Mato Grosso do Sul','MS',1029),(1930,'Mato Grosso','MT',1029),(1931,'Para','PA',1029),(1932,'Paraiba','PB',1029),(1933,'Pernambuco','PE',1029),(1934,'Piaui','PI',1029),(1935,'Parana','PR',1029),(1936,'Rio de Janeiro','RJ',1029),(1937,'Rio Grande do Norte','RN',1029),(1938,'Rondonia','RO',1029),(1939,'Roraima','RR',1029),(1940,'Rio Grande do Sul','RS',1029),(1941,'Santa Catarina','SC',1029),(1942,'Sergipe','SE',1029),(1943,'Sao Paulo','SP',1029),(1944,'Tocantins','TO',1029),(1945,'Acklins and Crooked Islands','AC',1212),(1946,'Bimini','BI',1212),(1947,'Cat Island','CI',1212),(1948,'Exuma','EX',1212),(1955,'Inagua','IN',1212),(1957,'Long Island','LI',1212),(1959,'Mayaguana','MG',1212),(1960,'New Providence','NP',1212),(1962,'Ragged Island','RI',1212),(1966,'Bumthang','33',1024),(1967,'Chhukha','12',1024),(1968,'Dagana','22',1024),(1969,'Gasa','GA',1024),(1970,'Ha','13',1024),(1971,'Lhuentse','44',1024),(1972,'Monggar','42',1024),(1973,'Paro','11',1024),(1974,'Pemagatshel','43',1024),(1975,'Punakha','23',1024),(1976,'Samdrup Jongkha','45',1024),(1977,'Samtee','14',1024),(1978,'Sarpang','31',1024),(1979,'Thimphu','15',1024),(1980,'Trashigang','41',1024),(1981,'Trashi Yangtse','TY',1024),(1982,'Trongsa','32',1024),(1983,'Tsirang','21',1024),(1984,'Wangdue Phodrang','24',1024),(1985,'Zhemgang','34',1024),(1986,'Central','CE',1027),(1987,'Ghanzi','GH',1027),(1988,'Kgalagadi','KG',1027),(1989,'Kgatleng','KL',1027),(1990,'Kweneng','KW',1027),(1991,'Ngamiland','NG',1027),(1992,'North-East','NE',1027),(1993,'North-West','NW',1027),(1994,'South-East','SE',1027),(1995,'Southern','SO',1027),(1996,'Brèsckaja voblasc\'','BR',1019),(1997,'Homel\'skaja voblasc\'','HO',1019),(1998,'Hrodzenskaja voblasc\'','HR',1019),(1999,'Mahilëuskaja voblasc\'','MA',1019),(2000,'Minskaja voblasc\'','MI',1019),(2001,'Vicebskaja voblasc\'','VI',1019),(2002,'Belize','BZ',1021),(2003,'Cayo','CY',1021),(2004,'Corozal','CZL',1021),(2005,'Orange Walk','OW',1021),(2006,'Stann Creek','SC',1021),(2007,'Toledo','TOL',1021),(2008,'Kinshasa','KN',1050),(2011,'Equateur','EQ',1050),(2014,'Kasai-Oriental','KE',1050),(2016,'Maniema','MA',1050),(2017,'Nord-Kivu','NK',1050),(2019,'Sud-Kivu','SK',1050),(2020,'Bangui','BGF',1042),(2021,'Bamingui-Bangoran','BB',1042),(2022,'Basse-Kotto','BK',1042),(2023,'Haute-Kotto','HK',1042),(2024,'Haut-Mbomou','HM',1042),(2025,'Kemo','KG',1042),(2026,'Lobaye','LB',1042),(2027,'Mambere-Kadei','HS',1042),(2028,'Mbomou','MB',1042),(2029,'Nana-Grebizi','KB',1042),(2030,'Nana-Mambere','NM',1042),(2031,'Ombella-Mpoko','MP',1042),(2032,'Ouaka','UK',1042),(2033,'Ouham','AC',1042),(2034,'Ouham-Pende','OP',1042),(2035,'Sangha-Mbaere','SE',1042),(2036,'Vakaga','VR',1042),(2037,'Brazzaville','BZV',1051),(2038,'Bouenza','11',1051),(2039,'Cuvette','8',1051),(2040,'Cuvette-Ouest','15',1051),(2041,'Kouilou','5',1051),(2042,'Lekoumou','2',1051),(2043,'Likouala','7',1051),(2044,'Niari','9',1051),(2045,'Plateaux','14',1051),(2046,'Pool','12',1051),(2047,'Sangha','13',1051),(2048,'Aargau','AG',1205),(2049,'Appenzell Innerrhoden','AI',1205),(2050,'Appenzell Ausserrhoden','AR',1205),(2051,'Bern','BE',1205),(2052,'Basel-Landschaft','BL',1205),(2053,'Basel-Stadt','BS',1205),(2054,'Fribourg','FR',1205),(2055,'Geneva','GE',1205),(2056,'Glarus','GL',1205),(2057,'Graubunden','GR',1205),(2058,'Jura','JU',1205),(2059,'Luzern','LU',1205),(2060,'Neuchatel','NE',1205),(2061,'Nidwalden','NW',1205),(2062,'Obwalden','OW',1205),(2063,'Sankt Gallen','SG',1205),(2064,'Schaffhausen','SH',1205),(2065,'Solothurn','SO',1205),(2066,'Schwyz','SZ',1205),(2067,'Thurgau','TG',1205),(2068,'Ticino','TI',1205),(2069,'Uri','UR',1205),(2070,'Vaud','VD',1205),(2071,'Valais','VS',1205),(2072,'Zug','ZG',1205),(2073,'Zurich','ZH',1205),(2074,'18 Montagnes','06',1054),(2075,'Agnebi','16',1054),(2076,'Bas-Sassandra','09',1054),(2077,'Denguele','10',1054),(2078,'Haut-Sassandra','02',1054),(2079,'Lacs','07',1054),(2080,'Lagunes','01',1054),(2081,'Marahoue','12',1054),(2082,'Moyen-Comoe','05',1054),(2083,'Nzi-Comoe','11',1054),(2084,'Savanes','03',1054),(2085,'Sud-Bandama','15',1054),(2086,'Sud-Comoe','13',1054),(2087,'Vallee du Bandama','04',1054),(2088,'Worodouqou','14',1054),(2089,'Zanzan','08',1054),(2090,'Aisen del General Carlos Ibanez del Campo','AI',1044),(2091,'Antofagasta','AN',1044),(2092,'Araucania','AR',1044),(2093,'Atacama','AT',1044),(2094,'Bio-Bio','BI',1044),(2095,'Coquimbo','CO',1044),(2096,'Libertador General Bernardo O\'Higgins','LI',1044),(2097,'Los Lagos','LL',1044),(2098,'Magallanes','MA',1044),(2099,'Maule','ML',1044),(2100,'Santiago Metropolitan','SM',1044),(2101,'Tarapaca','TA',1044),(2102,'Valparaiso','VS',1044),(2103,'Adamaoua','AD',1038),(2104,'Centre','CE',1038),(2105,'East','ES',1038),(2106,'Far North','EN',1038),(2107,'North','NO',1038),(2108,'South','SW',1038),(2109,'South-West','SW',1038),(2110,'West','OU',1038),(2111,'Beijing','11',1045),(2112,'Chongqing','50',1045),(2113,'Shanghai','31',1045),(2114,'Tianjin','12',1045),(2115,'Anhui','34',1045),(2116,'Fujian','35',1045),(2117,'Gansu','62',1045),(2118,'Guangdong','44',1045),(2119,'Guizhou','52',1045),(2120,'Hainan','46',1045),(2121,'Hebei','13',1045),(2122,'Heilongjiang','23',1045),(2123,'Henan','41',1045),(2124,'Hubei','42',1045),(2125,'Hunan','43',1045),(2126,'Jiangsu','32',1045),(2127,'Jiangxi','36',1045),(2128,'Jilin','22',1045),(2129,'Liaoning','21',1045),(2130,'Qinghai','63',1045),(2131,'Shaanxi','61',1045),(2132,'Shandong','37',1045),(2133,'Shanxi','14',1045),(2134,'Sichuan','51',1045),(2135,'Taiwan','71',1045),(2136,'Yunnan','53',1045),(2137,'Zhejiang','33',1045),(2138,'Guangxi','45',1045),(2139,'Neia Mongol (mn)','15',1045),(2140,'Xinjiang','65',1045),(2141,'Xizang','54',1045),(2142,'Hong Kong','91',1045),(2143,'Macau','92',1045),(2144,'Distrito Capital de Bogotá','DC',1048),(2145,'Amazonea','AMA',1048),(2146,'Antioquia','ANT',1048),(2147,'Arauca','ARA',1048),(2148,'Atlántico','ATL',1048),(2149,'Bolívar','BOL',1048),(2150,'Boyacá','BOY',1048),(2151,'Caldea','CAL',1048),(2152,'Caquetá','CAQ',1048),(2153,'Casanare','CAS',1048),(2154,'Cauca','CAU',1048),(2155,'Cesar','CES',1048),(2156,'Córdoba','COR',1048),(2157,'Cundinamarca','CUN',1048),(2158,'Chocó','CHO',1048),(2159,'Guainía','GUA',1048),(2160,'Guaviare','GUV',1048),(2161,'La Guajira','LAG',1048),(2162,'Magdalena','MAG',1048),(2163,'Meta','MET',1048),(2164,'Nariño','NAR',1048),(2165,'Norte de Santander','NSA',1048),(2166,'Putumayo','PUT',1048),(2167,'Quindio','QUI',1048),(2168,'Risaralda','RIS',1048),(2169,'San Andrés, Providencia y Santa Catalina','SAP',1048),(2170,'Santander','SAN',1048),(2171,'Sucre','SUC',1048),(2172,'Tolima','TOL',1048),(2173,'Valle del Cauca','VAC',1048),(2174,'Vaupés','VAU',1048),(2175,'Vichada','VID',1048),(2176,'Alajuela','A',1053),(2177,'Cartago','C',1053),(2178,'Guanacaste','G',1053),(2179,'Heredia','H',1053),(2180,'Limon','L',1053),(2181,'Puntarenas','P',1053),(2182,'San Jose','SJ',1053),(2183,'Camagey','09',1056),(2184,'Ciego de `vila','08',1056),(2185,'Cienfuegos','06',1056),(2186,'Ciudad de La Habana','03',1056),(2187,'Granma','12',1056),(2188,'Guantanamo','14',1056),(2189,'Holquin','11',1056),(2190,'La Habana','02',1056),(2191,'Las Tunas','10',1056),(2192,'Matanzas','04',1056),(2193,'Pinar del Rio','01',1056),(2194,'Sancti Spiritus','07',1056),(2195,'Santiago de Cuba','13',1056),(2196,'Villa Clara','05',1056),(2197,'Isla de la Juventud','99',1056),(2198,'Pinar del Roo','PR',1056),(2199,'Ciego de Avila','CA',1056),(2200,'Camagoey','CG',1056),(2201,'Holgun','HO',1056),(2202,'Sancti Spritus','SS',1056),(2203,'Municipio Especial Isla de la Juventud','IJ',1056),(2204,'Boa Vista','BV',1040),(2205,'Brava','BR',1040),(2206,'Calheta de Sao Miguel','CS',1040),(2207,'Fogo','FO',1040),(2208,'Maio','MA',1040),(2209,'Mosteiros','MO',1040),(2210,'Paul','PA',1040),(2211,'Porto Novo','PN',1040),(2212,'Praia','PR',1040),(2213,'Ribeira Grande','RG',1040),(2214,'Sal','SL',1040),(2215,'Sao Domingos','SD',1040),(2216,'Sao Filipe','SF',1040),(2217,'Sao Nicolau','SN',1040),(2218,'Sao Vicente','SV',1040),(2219,'Tarrafal','TA',1040),(2220,'Ammochostos Magusa','04',1057),(2221,'Keryneia','06',1057),(2222,'Larnaka','03',1057),(2223,'Lefkosia','01',1057),(2224,'Lemesos','02',1057),(2225,'Pafos','05',1057),(2226,'Jihočeský kraj','JC',1058),(2227,'Jihomoravský kraj','JM',1058),(2228,'Karlovarský kraj','KA',1058),(2229,'Královéhradecký kraj','KR',1058),(2230,'Liberecký kraj','LI',1058),(2231,'Moravskoslezský kraj','MO',1058),(2232,'Olomoucký kraj','OL',1058),(2233,'Pardubický kraj','PA',1058),(2234,'Plzeňský kraj','PL',1058),(2235,'Praha, hlavní město','PR',1058),(2236,'Středočeský kraj','ST',1058),(2237,'Ústecký kraj','US',1058),(2238,'Vysočina','VY',1058),(2239,'Zlínský kraj','ZL',1058),(2240,'Baden-Württemberg','BW',1082),(2241,'Bayern','BY',1082),(2242,'Bremen','HB',1082),(2243,'Hamburg','HH',1082),(2244,'Hessen','HE',1082),(2245,'Niedersachsen','NI',1082),(2246,'Nordrhein-Westfalen','NW',1082),(2247,'Rheinland-Pfalz','RP',1082),(2248,'Saarland','SL',1082),(2249,'Schleswig-Holstein','SH',1082),(2250,'Berlin','BE',1082),(2251,'Brandenburg','BB',1082),(2252,'Mecklenburg-Vorpommern','MV',1082),(2253,'Sachsen','SN',1082),(2254,'Sachsen-Anhalt','ST',1082),(2255,'Thüringen','TH',1082),(2256,'Ali Sabiah','AS',1060),(2257,'Dikhil','DI',1060),(2258,'Djibouti','DJ',1060),(2259,'Obock','OB',1060),(2260,'Tadjoura','TA',1060),(2261,'Frederiksberg','147',1059),(2262,'Copenhagen City','101',1059),(2263,'Copenhagen','015',1059),(2264,'Frederiksborg','020',1059),(2265,'Roskilde','025',1059),(2266,'Vestsjælland','030',1059),(2267,'Storstrøm','035',1059),(2268,'Bornholm','040',1059),(2269,'Fyn','042',1059),(2270,'South Jutland','050',1059),(2271,'Ribe','055',1059),(2272,'Vejle','060',1059),(2273,'Ringkjøbing','065',1059),(2274,'Århus','070',1059),(2275,'Viborg','076',1059),(2276,'North Jutland','080',1059),(2277,'Distrito Nacional (Santo Domingo)','01',1062),(2278,'Azua','02',1062),(2279,'Bahoruco','03',1062),(2280,'Barahona','04',1062),(2281,'Dajabón','05',1062),(2282,'Duarte','06',1062),(2283,'El Seybo [El Seibo]','08',1062),(2284,'Espaillat','09',1062),(2285,'Hato Mayor','30',1062),(2286,'Independencia','10',1062),(2287,'La Altagracia','11',1062),(2288,'La Estrelleta [Elias Pina]','07',1062),(2289,'La Romana','12',1062),(2290,'La Vega','13',1062),(2291,'Maroia Trinidad Sánchez','14',1062),(2292,'Monseñor Nouel','28',1062),(2293,'Monte Cristi','15',1062),(2294,'Monte Plata','29',1062),(2295,'Pedernales','16',1062),(2296,'Peravia','17',1062),(2297,'Puerto Plata','18',1062),(2298,'Salcedo','19',1062),(2299,'Samaná','20',1062),(2300,'San Cristóbal','21',1062),(2301,'San Pedro de Macorís','23',1062),(2302,'Sánchez Ramírez','24',1062),(2303,'Santiago','25',1062),(2304,'Santiago Rodríguez','26',1062),(2305,'Valverde','27',1062),(2306,'Adrar','01',1003),(2307,'Ain Defla','44',1003),(2308,'Ain Tmouchent','46',1003),(2309,'Alger','16',1003),(2310,'Annaba','23',1003),(2311,'Batna','05',1003),(2312,'Bechar','08',1003),(2313,'Bejaia','06',1003),(2314,'Biskra','07',1003),(2315,'Blida','09',1003),(2316,'Bordj Bou Arreridj','34',1003),(2317,'Bouira','10',1003),(2318,'Boumerdes','35',1003),(2319,'Chlef','02',1003),(2320,'Constantine','25',1003),(2321,'Djelfa','17',1003),(2322,'El Bayadh','32',1003),(2323,'El Oued','39',1003),(2324,'El Tarf','36',1003),(2325,'Ghardaia','47',1003),(2326,'Guelma','24',1003),(2327,'Illizi','33',1003),(2328,'Jijel','18',1003),(2329,'Khenchela','40',1003),(2330,'Laghouat','03',1003),(2331,'Mascara','29',1003),(2332,'Medea','26',1003),(2333,'Mila','43',1003),(2334,'Mostaganem','27',1003),(2335,'Msila','28',1003),(2336,'Naama','45',1003),(2337,'Oran','31',1003),(2338,'Ouargla','30',1003),(2339,'Oum el Bouaghi','04',1003),(2340,'Relizane','48',1003),(2341,'Saida','20',1003),(2342,'Setif','19',1003),(2343,'Sidi Bel Abbes','22',1003),(2344,'Skikda','21',1003),(2345,'Souk Ahras','41',1003),(2346,'Tamanghasset','11',1003),(2347,'Tebessa','12',1003),(2348,'Tiaret','14',1003),(2349,'Tindouf','37',1003),(2350,'Tipaza','42',1003),(2351,'Tissemsilt','38',1003),(2352,'Tizi Ouzou','15',1003),(2353,'Tlemcen','13',1003),(2354,'Azuay','A',1064),(2355,'Bolivar','B',1064),(2356,'Canar','F',1064),(2357,'Carchi','C',1064),(2358,'Cotopaxi','X',1064),(2359,'Chimborazo','H',1064),(2360,'El Oro','O',1064),(2361,'Esmeraldas','E',1064),(2362,'Galapagos','W',1064),(2363,'Guayas','G',1064),(2364,'Imbabura','I',1064),(2365,'Loja','L',1064),(2366,'Los Rios','R',1064),(2367,'Manabi','M',1064),(2368,'Morona-Santiago','S',1064),(2369,'Napo','N',1064),(2370,'Orellana','D',1064),(2371,'Pastaza','Y',1064),(2372,'Pichincha','P',1064),(2373,'Sucumbios','U',1064),(2374,'Tungurahua','T',1064),(2375,'Zamora-Chinchipe','Z',1064),(2376,'Harjumaa','37',1069),(2377,'Hiiumaa','39',1069),(2378,'Ida-Virumaa','44',1069),(2379,'Jõgevamaa','49',1069),(2380,'Järvamaa','51',1069),(2381,'Läänemaa','57',1069),(2382,'Lääne-Virumaa','59',1069),(2383,'Põlvamaa','65',1069),(2384,'Pärnumaa','67',1069),(2385,'Raplamaa','70',1069),(2386,'Saaremaa','74',1069),(2387,'Tartumaa','7B',1069),(2388,'Valgamaa','82',1069),(2389,'Viljandimaa','84',1069),(2390,'Võrumaa','86',1069),(2391,'Ad Daqahllyah','DK',1065),(2392,'Al Bahr al Ahmar','BA',1065),(2393,'Al Buhayrah','BH',1065),(2394,'Al Fayym','FYM',1065),(2395,'Al Gharbiyah','GH',1065),(2396,'Al Iskandarlyah','ALX',1065),(2397,'Al Isma illyah','IS',1065),(2398,'Al Jizah','GZ',1065),(2399,'Al Minuflyah','MNF',1065),(2400,'Al Minya','MN',1065),(2401,'Al Qahirah','C',1065),(2402,'Al Qalyublyah','KB',1065),(2403,'Al Wadi al Jadid','WAD',1065),(2404,'Ash Sharqiyah','SHR',1065),(2405,'As Suways','SUZ',1065),(2406,'Aswan','ASN',1065),(2407,'Asyut','AST',1065),(2408,'Bani Suwayf','BNS',1065),(2409,'Bur Sa\'id','PTS',1065),(2410,'Dumyat','DT',1065),(2411,'Janub Sina\'','JS',1065),(2412,'Kafr ash Shaykh','KFS',1065),(2413,'Matruh','MT',1065),(2414,'Qina','KN',1065),(2415,'Shamal Sina\'','SIN',1065),(2416,'Suhaj','SHG',1065),(2417,'Anseba','AN',1068),(2418,'Debub','DU',1068),(2419,'Debubawi Keyih Bahri [Debub-Keih-Bahri]','DK',1068),(2420,'Gash-Barka','GB',1068),(2421,'Maakel [Maekel]','MA',1068),(2422,'Semenawi Keyih Bahri [Semien-Keih-Bahri]','SK',1068),(2423,'Álava','VI',1198),(2424,'Albacete','AB',1198),(2425,'Alicante','A',1198),(2426,'Almería','AL',1198),(2427,'Asturias','O',1198),(2428,'Ávila','AV',1198),(2429,'Badajoz','BA',1198),(2430,'Baleares','PM',1198),(2431,'Barcelona','B',1198),(2432,'Burgos','BU',1198),(2433,'Cáceres','CC',1198),(2434,'Cádiz','CA',1198),(2435,'Cantabria','S',1198),(2436,'Castellón','CS',1198),(2437,'Ciudad Real','CR',1198),(2438,'Cuenca','CU',1198),(2439,'Girona [Gerona]','GE',1198),(2440,'Granada','GR',1198),(2441,'Guadalajara','GU',1198),(2442,'Guipúzcoa','SS',1198),(2443,'Huelva','H',1198),(2444,'Huesca','HU',1198),(2445,'Jaén','J',1198),(2446,'La Coruña','C',1198),(2447,'La Rioja','LO',1198),(2448,'Las Palmas','GC',1198),(2449,'León','LE',1198),(2450,'Lleida [Lérida]','L',1198),(2451,'Lugo','LU',1198),(2452,'Madrid','M',1198),(2453,'Málaga','MA',1198),(2454,'Murcia','MU',1198),(2455,'Navarra','NA',1198),(2456,'Ourense','OR',1198),(2457,'Palencia','P',1198),(2458,'Pontevedra','PO',1198),(2459,'Salamanca','SA',1198),(2460,'Santa Cruz de Tenerife','TF',1198),(2461,'Segovia','SG',1198),(2462,'Sevilla','SE',1198),(2463,'Soria','SO',1198),(2464,'Tarragona','T',1198),(2465,'Teruel','TE',1198),(2466,'Valencia','V',1198),(2467,'Valladolid','VA',1198),(2468,'Vizcaya','BI',1198),(2469,'Zamora','ZA',1198),(2470,'Zaragoza','Z',1198),(2471,'Ceuta','CE',1198),(2472,'Melilla','ML',1198),(2473,'Addis Ababa','AA',1070),(2474,'Dire Dawa','DD',1070),(2475,'Afar','AF',1070),(2476,'Amara','AM',1070),(2477,'Benshangul-Gumaz','BE',1070),(2478,'Gambela Peoples','GA',1070),(2479,'Harari People','HA',1070),(2480,'Oromia','OR',1070),(2481,'Somali','SO',1070),(2482,'Southern Nations, Nationalities and Peoples','SN',1070),(2483,'Tigrai','TI',1070),(2490,'Eastern','E',1074),(2491,'Northern','N',1074),(2492,'Western','W',1074),(2493,'Rotuma','R',1074),(2494,'Chuuk','TRK',1141),(2495,'Kosrae','KSA',1141),(2496,'Pohnpei','PNI',1141),(2497,'Yap','YAP',1141),(2498,'Ain','01',1076),(2499,'Aisne','02',1076),(2500,'Allier','03',1076),(2501,'Alpes-de-Haute-Provence','04',1076),(2502,'Alpes-Maritimes','06',1076),(2503,'Ardèche','07',1076),(2504,'Ardennes','08',1076),(2505,'Ariège','09',1076),(2506,'Aube','10',1076),(2507,'Aude','11',1076),(2508,'Aveyron','12',1076),(2509,'Bas-Rhin','67',1076),(2510,'Bouches-du-Rhône','13',1076),(2511,'Calvados','14',1076),(2512,'Cantal','15',1076),(2513,'Charente','16',1076),(2514,'Charente-Maritime','17',1076),(2515,'Cher','18',1076),(2516,'Corrèze','19',1076),(2517,'Corse-du-Sud','20A',1076),(2518,'Côte-d\'Or','21',1076),(2519,'Côtes-d\'Armor','22',1076),(2520,'Creuse','23',1076),(2521,'Deux-Sèvres','79',1076),(2522,'Dordogne','24',1076),(2523,'Doubs','25',1076),(2524,'Drôme','26',1076),(2525,'Essonne','91',1076),(2526,'Eure','27',1076),(2527,'Eure-et-Loir','28',1076),(2528,'Finistère','29',1076),(2529,'Gard','30',1076),(2530,'Gers','32',1076),(2531,'Gironde','33',1076),(2532,'Haut-Rhin','68',1076),(2533,'Haute-Corse','20B',1076),(2534,'Haute-Garonne','31',1076),(2535,'Haute-Loire','43',1076),(2536,'Haute-Saône','70',1076),(2537,'Haute-Savoie','74',1076),(2538,'Haute-Vienne','87',1076),(2539,'Hautes-Alpes','05',1076),(2540,'Hautes-Pyrénées','65',1076),(2541,'Hauts-de-Seine','92',1076),(2542,'Hérault','34',1076),(2543,'Indre','36',1076),(2544,'Ille-et-Vilaine','35',1076),(2545,'Indre-et-Loire','37',1076),(2546,'Isère','38',1076),(2547,'Landes','40',1076),(2548,'Loir-et-Cher','41',1076),(2549,'Loire','42',1076),(2550,'Loire-Atlantique','44',1076),(2551,'Loiret','45',1076),(2552,'Lot','46',1076),(2553,'Lot-et-Garonne','47',1076),(2554,'Lozère','48',1076),(2555,'Maine-et-Loire','49',1076),(2556,'Manche','50',1076),(2557,'Marne','51',1076),(2558,'Mayenne','53',1076),(2559,'Meurthe-et-Moselle','54',1076),(2560,'Meuse','55',1076),(2561,'Morbihan','56',1076),(2562,'Moselle','57',1076),(2563,'Nièvre','58',1076),(2564,'Nord','59',1076),(2565,'Oise','60',1076),(2566,'Orne','61',1076),(2567,'Paris','75',1076),(2568,'Pas-de-Calais','62',1076),(2569,'Puy-de-Dôme','63',1076),(2570,'Pyrénées-Atlantiques','64',1076),(2571,'Pyrénées-Orientales','66',1076),(2572,'Rhône','69',1076),(2573,'Saône-et-Loire','71',1076),(2574,'Sarthe','72',1076),(2575,'Savoie','73',1076),(2576,'Seine-et-Marne','77',1076),(2577,'Seine-Maritime','76',1076),(2578,'Seine-Saint-Denis','93',1076),(2579,'Somme','80',1076),(2580,'Tarn','81',1076),(2581,'Tarn-et-Garonne','82',1076),(2582,'Val d\'Oise','95',1076),(2583,'Territoire de Belfort','90',1076),(2584,'Val-de-Marne','94',1076),(2585,'Var','83',1076),(2586,'Vaucluse','84',1076),(2587,'Vendée','85',1076),(2588,'Vienne','86',1076),(2589,'Vosges','88',1076),(2590,'Yonne','89',1076),(2591,'Yvelines','78',1076),(2592,'Aberdeen City','ABE',1226),(2593,'Aberdeenshire','ABD',1226),(2594,'Angus','ANS',1226),(2595,'Co Antrim','ANT',1226),(2597,'Argyll and Bute','AGB',1226),(2598,'Co Armagh','ARM',1226),(2606,'Bedfordshire','BDF',1226),(2612,'Blaenau Gwent','BGW',1226),(2620,'Bristol, City of','BST',1226),(2622,'Buckinghamshire','BKM',1226),(2626,'Cambridgeshire','CAM',1226),(2634,'Cheshire','CHS',1226),(2635,'Clackmannanshire','CLK',1226),(2639,'Cornwall','CON',1226),(2643,'Cumbria','CMA',1226),(2647,'Derbyshire','DBY',1226),(2648,'Co Londonderry','DRY',1226),(2649,'Devon','DEV',1226),(2651,'Dorset','DOR',1226),(2652,'Co Down','DOW',1226),(2654,'Dumfries and Galloway','DGY',1226),(2655,'Dundee City','DND',1226),(2657,'County Durham','DUR',1226),(2659,'East Ayrshire','EAY',1226),(2660,'East Dunbartonshire','EDU',1226),(2661,'East Lothian','ELN',1226),(2662,'East Renfrewshire','ERW',1226),(2663,'East Riding of Yorkshire','ERY',1226),(2664,'East Sussex','ESX',1226),(2665,'Edinburgh, City of','EDH',1226),(2666,'Na h-Eileanan Siar','ELS',1226),(2668,'Essex','ESS',1226),(2669,'Falkirk','FAL',1226),(2670,'Co Fermanagh','FER',1226),(2671,'Fife','FIF',1226),(2674,'Glasgow City','GLG',1226),(2675,'Gloucestershire','GLS',1226),(2678,'Gwynedd','GWN',1226),(2682,'Hampshire','HAM',1226),(2687,'Herefordshire','HEF',1226),(2688,'Hertfordshire','HRT',1226),(2689,'Highland','HED',1226),(2692,'Inverclyde','IVC',1226),(2694,'Isle of Wight','IOW',1226),(2699,'Kent','KEN',1226),(2705,'Lancashire','LAN',1226),(2709,'Leicestershire','LEC',1226),(2712,'Lincolnshire','LIN',1226),(2723,'Midlothian','MLN',1226),(2726,'Moray','MRY',1226),(2734,'Norfolk','NFK',1226),(2735,'North Ayrshire','NAY',1226),(2738,'North Lanarkshire','NLK',1226),(2742,'North Yorkshire','NYK',1226),(2743,'Northamptonshire','NTH',1226),(2744,'Northumberland','NBL',1226),(2746,'Nottinghamshire','NTT',1226),(2747,'Oldham','OLD',1226),(2748,'Omagh','OMH',1226),(2749,'Orkney Islands','ORR',1226),(2750,'Oxfordshire','OXF',1226),(2752,'Perth and Kinross','PKN',1226),(2757,'Powys','POW',1226),(2761,'Renfrewshire','RFW',1226),(2766,'Rutland','RUT',1226),(2770,'Scottish Borders','SCB',1226),(2773,'Shetland Islands','ZET',1226),(2774,'Shropshire','SHR',1226),(2777,'Somerset','SOM',1226),(2778,'South Ayrshire','SAY',1226),(2779,'South Gloucestershire','SGC',1226),(2780,'South Lanarkshire','SLK',1226),(2785,'Staffordshire','STS',1226),(2786,'Stirling','STG',1226),(2791,'Suffolk','SFK',1226),(2793,'Surrey','SRY',1226),(2804,'Vale of Glamorgan, The','VGL',1226),(2811,'Warwickshire','WAR',1226),(2813,'West Dunbartonshire','WDU',1226),(2814,'West Lothian','WLN',1226),(2815,'West Sussex','WSX',1226),(2818,'Wiltshire','WIL',1226),(2823,'Worcestershire','WOR',1226),(2826,'Ashanti','AH',1083),(2827,'Brong-Ahafo','BA',1083),(2828,'Greater Accra','AA',1083),(2829,'Upper East','UE',1083),(2830,'Upper West','UW',1083),(2831,'Volta','TV',1083),(2832,'Banjul','B',1213),(2833,'Lower River','L',1213),(2834,'MacCarthy Island','M',1213),(2835,'North Bank','N',1213),(2836,'Upper River','U',1213),(2837,'Beyla','BE',1091),(2838,'Boffa','BF',1091),(2839,'Boke','BK',1091),(2840,'Coyah','CO',1091),(2841,'Dabola','DB',1091),(2842,'Dalaba','DL',1091),(2843,'Dinguiraye','DI',1091),(2844,'Dubreka','DU',1091),(2845,'Faranah','FA',1091),(2846,'Forecariah','FO',1091),(2847,'Fria','FR',1091),(2848,'Gaoual','GA',1091),(2849,'Guekedou','GU',1091),(2850,'Kankan','KA',1091),(2851,'Kerouane','KE',1091),(2852,'Kindia','KD',1091),(2853,'Kissidougou','KS',1091),(2854,'Koubia','KB',1091),(2855,'Koundara','KN',1091),(2856,'Kouroussa','KO',1091),(2857,'Labe','LA',1091),(2858,'Lelouma','LE',1091),(2859,'Lola','LO',1091),(2860,'Macenta','MC',1091),(2861,'Mali','ML',1091),(2862,'Mamou','MM',1091),(2863,'Mandiana','MD',1091),(2864,'Nzerekore','NZ',1091),(2865,'Pita','PI',1091),(2866,'Siguiri','SI',1091),(2867,'Telimele','TE',1091),(2868,'Tougue','TO',1091),(2869,'Yomou','YO',1091),(2870,'Region Continental','C',1067),(2871,'Region Insular','I',1067),(2872,'Annobon','AN',1067),(2873,'Bioko Norte','BN',1067),(2874,'Bioko Sur','BS',1067),(2875,'Centro Sur','CS',1067),(2876,'Kie-Ntem','KN',1067),(2877,'Litoral','LI',1067),(2878,'Wele-Nzas','WN',1067),(2879,'Achaïa','13',1085),(2880,'Aitolia-Akarnania','01',1085),(2881,'Argolis','11',1085),(2882,'Arkadia','12',1085),(2883,'Arta','31',1085),(2884,'Attiki','A1',1085),(2885,'Chalkidiki','64',1085),(2886,'Chania','94',1085),(2887,'Chios','85',1085),(2888,'Dodekanisos','81',1085),(2889,'Drama','52',1085),(2890,'Evros','71',1085),(2891,'Evrytania','05',1085),(2892,'Evvoia','04',1085),(2893,'Florina','63',1085),(2894,'Fokis','07',1085),(2895,'Fthiotis','06',1085),(2896,'Grevena','51',1085),(2897,'Ileia','14',1085),(2898,'Imathia','53',1085),(2899,'Ioannina','33',1085),(2900,'Irakleion','91',1085),(2901,'Karditsa','41',1085),(2902,'Kastoria','56',1085),(2903,'Kavalla','55',1085),(2904,'Kefallinia','23',1085),(2905,'Kerkyra','22',1085),(2906,'Kilkis','57',1085),(2907,'Korinthia','15',1085),(2908,'Kozani','58',1085),(2909,'Kyklades','82',1085),(2910,'Lakonia','16',1085),(2911,'Larisa','42',1085),(2912,'Lasithion','92',1085),(2913,'Lefkas','24',1085),(2914,'Lesvos','83',1085),(2915,'Magnisia','43',1085),(2916,'Messinia','17',1085),(2917,'Pella','59',1085),(2918,'Preveza','34',1085),(2919,'Rethymnon','93',1085),(2920,'Rodopi','73',1085),(2921,'Samos','84',1085),(2922,'Serrai','62',1085),(2923,'Thesprotia','32',1085),(2924,'Thessaloniki','54',1085),(2925,'Trikala','44',1085),(2926,'Voiotia','03',1085),(2927,'Xanthi','72',1085),(2928,'Zakynthos','21',1085),(2929,'Agio Oros','69',1085),(2930,'Alta Verapaz','AV',1090),(2931,'Baja Verapaz','BV',1090),(2932,'Chimaltenango','CM',1090),(2933,'Chiquimula','CQ',1090),(2934,'El Progreso','PR',1090),(2935,'Escuintla','ES',1090),(2936,'Guatemala','GU',1090),(2937,'Huehuetenango','HU',1090),(2938,'Izabal','IZ',1090),(2939,'Jalapa','JA',1090),(2940,'Jutiapa','JU',1090),(2941,'Peten','PE',1090),(2942,'Quetzaltenango','QZ',1090),(2943,'Quiche','QC',1090),(2944,'Retalhuleu','RE',1090),(2945,'Sacatepequez','SA',1090),(2946,'San Marcos','SM',1090),(2947,'Santa Rosa','SR',1090),(2948,'Sololá','SO',1090),(2949,'Suchitepequez','SU',1090),(2950,'Totonicapan','TO',1090),(2951,'Zacapa','ZA',1090),(2952,'Bissau','BS',1092),(2953,'Bafata','BA',1092),(2954,'Biombo','BM',1092),(2955,'Bolama','BL',1092),(2956,'Cacheu','CA',1092),(2957,'Gabu','GA',1092),(2958,'Oio','OI',1092),(2959,'Quloara','QU',1092),(2960,'Tombali S','TO',1092),(2961,'Barima-Waini','BA',1093),(2962,'Cuyuni-Mazaruni','CU',1093),(2963,'Demerara-Mahaica','DE',1093),(2964,'East Berbice-Corentyne','EB',1093),(2965,'Essequibo Islands-West Demerara','ES',1093),(2966,'Mahaica-Berbice','MA',1093),(2967,'Pomeroon-Supenaam','PM',1093),(2968,'Potaro-Siparuni','PT',1093),(2969,'Upper Demerara-Berbice','UD',1093),(2970,'Upper Takutu-Upper Essequibo','UT',1093),(2971,'Atlantida','AT',1097),(2972,'Colon','CL',1097),(2973,'Comayagua','CM',1097),(2974,'Copan','CP',1097),(2975,'Cortes','CR',1097),(2976,'Choluteca','CH',1097),(2977,'El Paraiso','EP',1097),(2978,'Francisco Morazan','FM',1097),(2979,'Gracias a Dios','GD',1097),(2980,'Intibuca','IN',1097),(2981,'Islas de la Bahia','IB',1097),(2982,'Lempira','LE',1097),(2983,'Ocotepeque','OC',1097),(2984,'Olancho','OL',1097),(2985,'Santa Barbara','SB',1097),(2986,'Valle','VA',1097),(2987,'Yoro','YO',1097),(2988,'Bjelovarsko-bilogorska zupanija','07',1055),(2989,'Brodsko-posavska zupanija','12',1055),(2990,'Dubrovacko-neretvanska zupanija','19',1055),(2991,'Istarska zupanija','18',1055),(2992,'Karlovacka zupanija','04',1055),(2993,'Koprivnickco-krizevacka zupanija','06',1055),(2994,'Krapinako-zagorska zupanija','02',1055),(2995,'Licko-senjska zupanija','09',1055),(2996,'Medimurska zupanija','20',1055),(2997,'Osjecko-baranjska zupanija','14',1055),(2998,'Pozesko-slavonska zupanija','11',1055),(2999,'Primorsko-goranska zupanija','08',1055),(3000,'Sisacko-moelavacka Iupanija','03',1055),(3001,'Splitako-dalmatinska zupanija','17',1055),(3002,'Sibenako-kninska zupanija','15',1055),(3003,'Varaidinska zupanija','05',1055),(3004,'VirovitiEko-podravska zupanija','10',1055),(3005,'VuRovarako-srijemska zupanija','16',1055),(3006,'Zadaraka','13',1055),(3007,'Zagrebacka zupanija','01',1055),(3008,'Grande-Anse','GA',1094),(3009,'Nord-Est','NE',1094),(3010,'Nord-Ouest','NO',1094),(3011,'Ouest','OU',1094),(3012,'Sud','SD',1094),(3013,'Sud-Est','SE',1094),(3014,'Budapest','BU',1099),(3015,'Bács-Kiskun','BK',1099),(3016,'Baranya','BA',1099),(3017,'Békés','BE',1099),(3018,'Borsod-Abaúj-Zemplén','BZ',1099),(3019,'Csongrád','CS',1099),(3020,'Fejér','FE',1099),(3021,'Győr-Moson-Sopron','GS',1099),(3022,'Hajdu-Bihar','HB',1099),(3023,'Heves','HE',1099),(3024,'Jász-Nagykun-Szolnok','JN',1099),(3025,'Komárom-Esztergom','KE',1099),(3026,'Nográd','NO',1099),(3027,'Pest','PE',1099),(3028,'Somogy','SO',1099),(3029,'Szabolcs-Szatmár-Bereg','SZ',1099),(3030,'Tolna','TO',1099),(3031,'Vas','VA',1099),(3032,'Veszprém','VE',1099),(3033,'Zala','ZA',1099),(3034,'Békéscsaba','BC',1099),(3035,'Debrecen','DE',1099),(3036,'Dunaújváros','DU',1099),(3037,'Eger','EG',1099),(3038,'Győr','GY',1099),(3039,'Hódmezővásárhely','HV',1099),(3040,'Kaposvár','KV',1099),(3041,'Kecskemét','KM',1099),(3042,'Miskolc','MI',1099),(3043,'Nagykanizsa','NK',1099),(3044,'Nyiregyháza','NY',1099),(3045,'Pécs','PS',1099),(3046,'Salgótarján','ST',1099),(3047,'Sopron','SN',1099),(3048,'Szeged','SD',1099),(3049,'Székesfehérvár','SF',1099),(3050,'Szekszárd','SS',1099),(3051,'Szolnok','SK',1099),(3052,'Szombathely','SH',1099),(3053,'Tatabánya','TB',1099),(3054,'Zalaegerszeg','ZE',1099),(3055,'Bali','BA',1102),(3056,'Kepulauan Bangka Belitung','BB',1102),(3057,'Banten','BT',1102),(3058,'Bengkulu','BE',1102),(3059,'Gorontalo','GO',1102),(3060,'Papua Barat','PB',1102),(3061,'Jambi','JA',1102),(3062,'Jawa Barat','JB',1102),(3063,'Jawa Tengah','JT',1102),(3064,'Jawa Timur','JI',1102),(3065,'Kalimantan Barat','KB',1102),(3066,'Kalimantan Timur','KI',1102),(3067,'Kalimantan Selatan','KS',1102),(3068,'Kepulauan Riau','KR',1102),(3069,'Lampung','LA',1102),(3070,'Maluku','MA',1102),(3071,'Maluku Utara','MU',1102),(3072,'Nusa Tenggara Barat','NB',1102),(3073,'Nusa Tenggara Timur','NT',1102),(3074,'Papua','PA',1102),(3075,'Riau','RI',1102),(3076,'Sulawesi Selatan','SN',1102),(3077,'Sulawesi Tengah','ST',1102),(3078,'Sulawesi Tenggara','SG',1102),(3079,'Sulawesi Utara','SA',1102),(3080,'Sumatra Barat','SB',1102),(3081,'Sumatra Selatan','SS',1102),(3082,'Sumatera Utara','SU',1102),(3083,'DKI Jakarta','JK',1102),(3084,'Aceh','AC',1102),(3085,'DI Yogyakarta','YO',1102),(3086,'Cork','C',1105),(3087,'Clare','CE',1105),(3088,'Cavan','CN',1105),(3089,'Carlow','CW',1105),(3090,'Dublin','D',1105),(3091,'Donegal','DL',1105),(3092,'Galway','G',1105),(3093,'Kildare','KE',1105),(3094,'Kilkenny','KK',1105),(3095,'Kerry','KY',1105),(3096,'Longford','LD',1105),(3097,'Louth','LH',1105),(3098,'Limerick','LK',1105),(3099,'Leitrim','LM',1105),(3100,'Laois','LS',1105),(3101,'Meath','MH',1105),(3102,'Monaghan','MN',1105),(3103,'Mayo','MO',1105),(3104,'Offaly','OY',1105),(3105,'Roscommon','RN',1105),(3106,'Sligo','SO',1105),(3107,'Tipperary','TA',1105),(3108,'Waterford','WD',1105),(3109,'Westmeath','WH',1105),(3110,'Wicklow','WW',1105),(3111,'Wexford','WX',1105),(3112,'HaDarom','D',1106),(3113,'HaMerkaz','M',1106),(3114,'HaZafon','Z',1106),(3115,'Haifa','HA',1106),(3116,'Tel-Aviv','TA',1106),(3117,'Jerusalem','JM',1106),(3118,'Al Anbar','AN',1104),(3119,'Al Ba,rah','BA',1104),(3120,'Al Muthanna','MU',1104),(3121,'Al Qadisiyah','QA',1104),(3122,'An Najef','NA',1104),(3123,'Arbil','AR',1104),(3124,'As Sulaymaniyah','SW',1104),(3125,'At Ta\'mim','TS',1104),(3126,'Babil','BB',1104),(3127,'Baghdad','BG',1104),(3128,'Dahuk','DA',1104),(3129,'Dhi Qar','DQ',1104),(3130,'Diyala','DI',1104),(3131,'Karbala\'','KA',1104),(3132,'Maysan','MA',1104),(3133,'Ninawa','NI',1104),(3134,'Salah ad Din','SD',1104),(3135,'Wasit','WA',1104),(3136,'Ardabil','03',1103),(3137,'Azarbayjan-e Gharbi','02',1103),(3138,'Azarbayjan-e Sharqi','01',1103),(3139,'Bushehr','06',1103),(3140,'Chahar Mahall va Bakhtiari','08',1103),(3141,'Esfahan','04',1103),(3142,'Fars','14',1103),(3143,'Gilan','19',1103),(3144,'Golestan','27',1103),(3145,'Hamadan','24',1103),(3146,'Hormozgan','23',1103),(3147,'Iiam','05',1103),(3148,'Kerman','15',1103),(3149,'Kermanshah','17',1103),(3150,'Khorasan','09',1103),(3151,'Khuzestan','10',1103),(3152,'Kohjiluyeh va Buyer Ahmad','18',1103),(3153,'Kordestan','16',1103),(3154,'Lorestan','20',1103),(3155,'Markazi','22',1103),(3156,'Mazandaran','21',1103),(3157,'Qazvin','28',1103),(3158,'Qom','26',1103),(3159,'Semnan','12',1103),(3160,'Sistan va Baluchestan','13',1103),(3161,'Tehran','07',1103),(3162,'Yazd','25',1103),(3163,'Zanjan','11',1103),(3164,'Austurland','7',1100),(3165,'Hofuoborgarsvaeoi utan Reykjavikur','1',1100),(3166,'Norourland eystra','6',1100),(3167,'Norourland vestra','5',1100),(3168,'Reykjavik','0',1100),(3169,'Suourland','8',1100),(3170,'Suournes','2',1100),(3171,'Vestfirolr','4',1100),(3172,'Vesturland','3',1100),(3173,'Agrigento','AG',1107),(3174,'Alessandria','AL',1107),(3175,'Ancona','AN',1107),(3176,'Aosta','AO',1107),(3177,'Arezzo','AR',1107),(3178,'Ascoli Piceno','AP',1107),(3179,'Asti','AT',1107),(3180,'Avellino','AV',1107),(3181,'Bari','BA',1107),(3182,'Belluno','BL',1107),(3183,'Benevento','BN',1107),(3184,'Bergamo','BG',1107),(3185,'Biella','BI',1107),(3186,'Bologna','BO',1107),(3187,'Bolzano','BZ',1107),(3188,'Brescia','BS',1107),(3189,'Brindisi','BR',1107),(3190,'Cagliari','CA',1107),(3191,'Caltanissetta','CL',1107),(3192,'Campobasso','CB',1107),(3193,'Caserta','CE',1107),(3194,'Catania','CT',1107),(3195,'Catanzaro','CZ',1107),(3196,'Chieti','CH',1107),(3197,'Como','CO',1107),(3198,'Cosenza','CS',1107),(3199,'Cremona','CR',1107),(3200,'Crotone','KR',1107),(3201,'Cuneo','CN',1107),(3202,'Enna','EN',1107),(3203,'Ferrara','FE',1107),(3204,'Firenze','FI',1107),(3205,'Foggia','FG',1107),(3206,'Forlì-Cesena','FC',1107),(3207,'Frosinone','FR',1107),(3208,'Genova','GE',1107),(3209,'Gorizia','GO',1107),(3210,'Grosseto','GR',1107),(3211,'Imperia','IM',1107),(3212,'Isernia','IS',1107),(3213,'L\'Aquila','AQ',1107),(3214,'La Spezia','SP',1107),(3215,'Latina','LT',1107),(3216,'Lecce','LE',1107),(3217,'Lecco','LC',1107),(3218,'Livorno','LI',1107),(3219,'Lodi','LO',1107),(3220,'Lucca','LU',1107),(3221,'Macerata','MC',1107),(3222,'Mantova','MN',1107),(3223,'Massa-Carrara','MS',1107),(3224,'Matera','MT',1107),(3225,'Messina','ME',1107),(3226,'Milano','MI',1107),(3227,'Modena','MO',1107),(3228,'Napoli','NA',1107),(3229,'Novara','NO',1107),(3230,'Nuoro','NU',1107),(3231,'Oristano','OR',1107),(3232,'Padova','PD',1107),(3233,'Palermo','PA',1107),(3234,'Parma','PR',1107),(3235,'Pavia','PV',1107),(3236,'Perugia','PG',1107),(3237,'Pesaro e Urbino','PU',1107),(3238,'Pescara','PE',1107),(3239,'Piacenza','PC',1107),(3240,'Pisa','PI',1107),(3241,'Pistoia','PT',1107),(3242,'Pordenone','PN',1107),(3243,'Potenza','PZ',1107),(3244,'Prato','PO',1107),(3245,'Ragusa','RG',1107),(3246,'Ravenna','RA',1107),(3247,'Reggio Calabria','RC',1107),(3248,'Reggio Emilia','RE',1107),(3249,'Rieti','RI',1107),(3250,'Rimini','RN',1107),(3251,'Roma','RM',1107),(3252,'Rovigo','RO',1107),(3253,'Salerno','SA',1107),(3254,'Sassari','SS',1107),(3255,'Savona','SV',1107),(3256,'Siena','SI',1107),(3257,'Siracusa','SR',1107),(3258,'Sondrio','SO',1107),(3259,'Taranto','TA',1107),(3260,'Teramo','TE',1107),(3261,'Terni','TR',1107),(3262,'Torino','TO',1107),(3263,'Trapani','TP',1107),(3264,'Trento','TN',1107),(3265,'Treviso','TV',1107),(3266,'Trieste','TS',1107),(3267,'Udine','UD',1107),(3268,'Varese','VA',1107),(3269,'Venezia','VE',1107),(3270,'Verbano-Cusio-Ossola','VB',1107),(3271,'Vercelli','VC',1107),(3272,'Verona','VR',1107),(3273,'Vibo Valentia','VV',1107),(3274,'Vicenza','VI',1107),(3275,'Viterbo','VT',1107),(3276,'Aichi','23',1109),(3277,'Akita','05',1109),(3278,'Aomori','02',1109),(3279,'Chiba','12',1109),(3280,'Ehime','38',1109),(3281,'Fukui','18',1109),(3282,'Fukuoka','40',1109),(3283,'Fukusima','07',1109),(3284,'Gifu','21',1109),(3285,'Gunma','10',1109),(3286,'Hiroshima','34',1109),(3287,'Hokkaido','01',1109),(3288,'Hyogo','28',1109),(3289,'Ibaraki','08',1109),(3290,'Ishikawa','17',1109),(3291,'Iwate','03',1109),(3292,'Kagawa','37',1109),(3293,'Kagoshima','46',1109),(3294,'Kanagawa','14',1109),(3295,'Kochi','39',1109),(3296,'Kumamoto','43',1109),(3297,'Kyoto','26',1109),(3298,'Mie','24',1109),(3299,'Miyagi','04',1109),(3300,'Miyazaki','45',1109),(3301,'Nagano','20',1109),(3302,'Nagasaki','42',1109),(3303,'Nara','29',1109),(3304,'Niigata','15',1109),(3305,'Oita','44',1109),(3306,'Okayama','33',1109),(3307,'Okinawa','47',1109),(3308,'Osaka','27',1109),(3309,'Saga','41',1109),(3310,'Saitama','11',1109),(3311,'Shiga','25',1109),(3312,'Shimane','32',1109),(3313,'Shizuoka','22',1109),(3314,'Tochigi','09',1109),(3315,'Tokushima','36',1109),(3316,'Tokyo','13',1109),(3317,'Tottori','31',1109),(3318,'Toyama','16',1109),(3319,'Wakayama','30',1109),(3320,'Yamagata','06',1109),(3321,'Yamaguchi','35',1109),(3322,'Yamanashi','19',1109),(3323,'Clarendon','CN',1108),(3324,'Hanover','HR',1108),(3325,'Kingston','KN',1108),(3326,'Portland','PD',1108),(3327,'Saint Andrew','AW',1108),(3328,'Saint Ann','AN',1108),(3329,'Saint Catherine','CE',1108),(3330,'Saint Elizabeth','EH',1108),(3331,'Saint James','JS',1108),(3332,'Saint Mary','MY',1108),(3333,'Saint Thomas','TS',1108),(3334,'Trelawny','TY',1108),(3335,'Westmoreland','WD',1108),(3336,'Ajln','AJ',1110),(3337,'Al \'Aqaba','AQ',1110),(3338,'Al Balqa\'','BA',1110),(3339,'Al Karak','KA',1110),(3340,'Al Mafraq','MA',1110),(3341,'Amman','AM',1110),(3342,'At Tafilah','AT',1110),(3343,'Az Zarga','AZ',1110),(3344,'Irbid','JR',1110),(3345,'Jarash','JA',1110),(3346,'Ma\'an','MN',1110),(3347,'Madaba','MD',1110),(3353,'Bishkek','GB',1117),(3354,'Batken','B',1117),(3355,'Chu','C',1117),(3356,'Jalal-Abad','J',1117),(3357,'Naryn','N',1117),(3358,'Osh','O',1117),(3359,'Talas','T',1117),(3360,'Ysyk-Kol','Y',1117),(3361,'Krong Kaeb','23',1037),(3362,'Krong Pailin','24',1037),(3363,'Xrong Preah Sihanouk','18',1037),(3364,'Phnom Penh','12',1037),(3365,'Baat Dambang','2',1037),(3366,'Banteay Mean Chey','1',1037),(3367,'Rampong Chaam','3',1037),(3368,'Kampong Chhnang','4',1037),(3369,'Kampong Spueu','5',1037),(3370,'Kampong Thum','6',1037),(3371,'Kampot','7',1037),(3372,'Kandaal','8',1037),(3373,'Kach Kong','9',1037),(3374,'Krachoh','10',1037),(3375,'Mondol Kiri','11',1037),(3376,'Otdar Mean Chey','22',1037),(3377,'Pousaat','15',1037),(3378,'Preah Vihear','13',1037),(3379,'Prey Veaeng','14',1037),(3380,'Rotanak Kiri','16',1037),(3381,'Siem Reab','17',1037),(3382,'Stueng Traeng','19',1037),(3383,'Svaay Rieng','20',1037),(3384,'Taakaev','21',1037),(3385,'Gilbert Islands','G',1113),(3386,'Line Islands','L',1113),(3387,'Phoenix Islands','P',1113),(3388,'Anjouan Ndzouani','A',1049),(3389,'Grande Comore Ngazidja','G',1049),(3390,'Moheli Moili','M',1049),(3391,'Kaesong-si','KAE',1114),(3392,'Nampo-si','NAM',1114),(3393,'Pyongyang-ai','PYO',1114),(3394,'Chagang-do','CHA',1114),(3395,'Hamgyongbuk-do','HAB',1114),(3396,'Hamgyongnam-do','HAN',1114),(3397,'Hwanghaebuk-do','HWB',1114),(3398,'Hwanghaenam-do','HWN',1114),(3399,'Kangwon-do','KAN',1114),(3400,'Pyonganbuk-do','PYB',1114),(3401,'Pyongannam-do','PYN',1114),(3402,'Yanggang-do','YAN',1114),(3403,'Najin Sonbong-si','NAJ',1114),(3404,'Seoul Teugbyeolsi','11',1115),(3405,'Busan Gwang\'yeogsi','26',1115),(3406,'Daegu Gwang\'yeogsi','27',1115),(3407,'Daejeon Gwang\'yeogsi','30',1115),(3408,'Gwangju Gwang\'yeogsi','29',1115),(3409,'Incheon Gwang\'yeogsi','28',1115),(3410,'Ulsan Gwang\'yeogsi','31',1115),(3411,'Chungcheongbugdo','43',1115),(3412,'Chungcheongnamdo','44',1115),(3413,'Gang\'weondo','42',1115),(3414,'Gyeonggido','41',1115),(3415,'Gyeongsangbugdo','47',1115),(3416,'Gyeongsangnamdo','48',1115),(3417,'Jejudo','49',1115),(3418,'Jeonrabugdo','45',1115),(3419,'Jeonranamdo','46',1115),(3420,'Al Ahmadi','AH',1116),(3421,'Al Farwanlyah','FA',1116),(3422,'Al Jahrah','JA',1116),(3423,'Al Kuwayt','KU',1116),(3424,'Hawalli','HA',1116),(3425,'Almaty','ALA',1111),(3426,'Astana','AST',1111),(3427,'Almaty oblysy','ALM',1111),(3428,'Aqmola oblysy','AKM',1111),(3429,'Aqtobe oblysy','AKT',1111),(3430,'Atyrau oblyfiy','ATY',1111),(3431,'Batys Quzaqstan oblysy','ZAP',1111),(3432,'Mangghystau oblysy','MAN',1111),(3433,'Ongtustik Quzaqstan oblysy','YUZ',1111),(3434,'Pavlodar oblysy','PAV',1111),(3435,'Qaraghandy oblysy','KAR',1111),(3436,'Qostanay oblysy','KUS',1111),(3437,'Qyzylorda oblysy','KZY',1111),(3438,'Shyghys Quzaqstan oblysy','VOS',1111),(3439,'Soltustik Quzaqstan oblysy','SEV',1111),(3440,'Zhambyl oblysy Zhambylskaya oblast\'','ZHA',1111),(3441,'Vientiane','VT',1118),(3442,'Attapu','AT',1118),(3443,'Bokeo','BK',1118),(3444,'Bolikhamxai','BL',1118),(3445,'Champasak','CH',1118),(3446,'Houaphan','HO',1118),(3447,'Khammouan','KH',1118),(3448,'Louang Namtha','LM',1118),(3449,'Louangphabang','LP',1118),(3450,'Oudomxai','OU',1118),(3451,'Phongsali','PH',1118),(3452,'Salavan','SL',1118),(3453,'Savannakhet','SV',1118),(3454,'Xaignabouli','XA',1118),(3455,'Xiasomboun','XN',1118),(3456,'Xekong','XE',1118),(3457,'Xiangkhoang','XI',1118),(3458,'Beirut','BA',1120),(3459,'Beqaa','BI',1120),(3460,'Mount Lebanon','JL',1120),(3461,'North Lebanon','AS',1120),(3462,'South Lebanon','JA',1120),(3463,'Nabatieh','NA',1120),(3464,'Ampara','52',1199),(3465,'Anuradhapura','71',1199),(3466,'Badulla','81',1199),(3467,'Batticaloa','51',1199),(3468,'Colombo','11',1199),(3469,'Galle','31',1199),(3470,'Gampaha','12',1199),(3471,'Hambantota','33',1199),(3472,'Jaffna','41',1199),(3473,'Kalutara','13',1199),(3474,'Kandy','21',1199),(3475,'Kegalla','92',1199),(3476,'Kilinochchi','42',1199),(3477,'Kurunegala','61',1199),(3478,'Mannar','43',1199),(3479,'Matale','22',1199),(3480,'Matara','32',1199),(3481,'Monaragala','82',1199),(3482,'Mullaittivu','45',1199),(3483,'Nuwara Eliya','23',1199),(3484,'Polonnaruwa','72',1199),(3485,'Puttalum','62',1199),(3486,'Ratnapura','91',1199),(3487,'Trincomalee','53',1199),(3488,'VavunLya','44',1199),(3489,'Bomi','BM',1122),(3490,'Bong','BG',1122),(3491,'Grand Basaa','GB',1122),(3492,'Grand Cape Mount','CM',1122),(3493,'Grand Gedeh','GG',1122),(3494,'Grand Kru','GK',1122),(3495,'Lofa','LO',1122),(3496,'Margibi','MG',1122),(3497,'Maryland','MY',1122),(3498,'Montserrado','MO',1122),(3499,'Nimba','NI',1122),(3500,'Rivercess','RI',1122),(3501,'Sinoe','SI',1122),(3502,'Berea','D',1121),(3503,'Butha-Buthe','B',1121),(3504,'Leribe','C',1121),(3505,'Mafeteng','E',1121),(3506,'Maseru','A',1121),(3507,'Mohale\'s Hoek','F',1121),(3508,'Mokhotlong','J',1121),(3509,'Qacha\'s Nek','H',1121),(3510,'Quthing','G',1121),(3511,'Thaba-Tseka','K',1121),(3512,'Alytaus Apskritis','AL',1125),(3513,'Kauno Apskritis','KU',1125),(3514,'Klaipėdos Apskritis','KL',1125),(3515,'Marijampolės Apskritis','MR',1125),(3516,'Panevėžio Apskritis','PN',1125),(3517,'Šiaulių Apskritis','SA',1125),(3518,'Tauragės Apskritis','TA',1125),(3519,'Telšių Apskritis','TE',1125),(3520,'Utenos Apskritis','UT',1125),(3521,'Vilniaus Apskritis','VL',1125),(3522,'Diekirch','D',1126),(3523,'GreveNmacher','G',1126),(3550,'Daugavpils','DGV',1119),(3551,'Jelgava','JEL',1119),(3552,'Jūrmala','JUR',1119),(3553,'Liepāja','LPX',1119),(3554,'Rēzekne','REZ',1119),(3555,'Rīga','RIX',1119),(3556,'Ventspils','VEN',1119),(3557,'Ajdābiyā','AJ',1123),(3558,'Al Buţnān','BU',1123),(3559,'Al Hizām al Akhdar','HZ',1123),(3560,'Al Jabal al Akhdar','JA',1123),(3561,'Al Jifārah','JI',1123),(3562,'Al Jufrah','JU',1123),(3563,'Al Kufrah','KF',1123),(3564,'Al Marj','MJ',1123),(3565,'Al Marqab','MB',1123),(3566,'Al Qaţrūn','QT',1123),(3567,'Al Qubbah','QB',1123),(3568,'Al Wāhah','WA',1123),(3569,'An Nuqaţ al Khams','NQ',1123),(3570,'Ash Shāţi\'','SH',1123),(3571,'Az Zāwiyah','ZA',1123),(3572,'Banghāzī','BA',1123),(3573,'Banī Walīd','BW',1123),(3574,'Darnah','DR',1123),(3575,'Ghadāmis','GD',1123),(3576,'Gharyān','GR',1123),(3577,'Ghāt','GT',1123),(3578,'Jaghbūb','JB',1123),(3579,'Mişrātah','MI',1123),(3580,'Mizdah','MZ',1123),(3581,'Murzuq','MQ',1123),(3582,'Nālūt','NL',1123),(3583,'Sabhā','SB',1123),(3584,'Şabrātah Şurmān','SS',1123),(3585,'Surt','SR',1123),(3586,'Tājūrā\' wa an Nawāhī al Arbāh','TN',1123),(3587,'Ţarābulus','TB',1123),(3588,'Tarhūnah-Masallātah','TM',1123),(3589,'Wādī al hayāt','WD',1123),(3590,'Yafran-Jādū','YJ',1123),(3591,'Agadir','AGD',1146),(3592,'Aït Baha','BAH',1146),(3593,'Aït Melloul','MEL',1146),(3594,'Al Haouz','HAO',1146),(3595,'Al Hoceïma','HOC',1146),(3596,'Assa-Zag','ASZ',1146),(3597,'Azilal','AZI',1146),(3598,'Beni Mellal','BEM',1146),(3599,'Ben Sllmane','BES',1146),(3600,'Berkane','BER',1146),(3601,'Boujdour','BOD',1146),(3602,'Boulemane','BOM',1146),(3603,'Casablanca  [Dar el Beïda]','CAS',1146),(3604,'Chefchaouene','CHE',1146),(3605,'Chichaoua','CHI',1146),(3606,'El Hajeb','HAJ',1146),(3607,'El Jadida','JDI',1146),(3608,'Errachidia','ERR',1146),(3609,'Essaouira','ESI',1146),(3610,'Es Smara','ESM',1146),(3611,'Fès','FES',1146),(3612,'Figuig','FIG',1146),(3613,'Guelmim','GUE',1146),(3614,'Ifrane','IFR',1146),(3615,'Jerada','JRA',1146),(3616,'Kelaat Sraghna','KES',1146),(3617,'Kénitra','KEN',1146),(3618,'Khemisaet','KHE',1146),(3619,'Khenifra','KHN',1146),(3620,'Khouribga','KHO',1146),(3621,'Laâyoune (EH)','LAA',1146),(3622,'Larache','LAP',1146),(3623,'Marrakech','MAR',1146),(3624,'Meknsès','MEK',1146),(3625,'Nador','NAD',1146),(3626,'Ouarzazate','OUA',1146),(3627,'Oued ed Dahab (EH)','OUD',1146),(3628,'Oujda','OUJ',1146),(3629,'Rabat-Salé','RBA',1146),(3630,'Safi','SAF',1146),(3631,'Sefrou','SEF',1146),(3632,'Settat','SET',1146),(3633,'Sidl Kacem','SIK',1146),(3634,'Tanger','TNG',1146),(3635,'Tan-Tan','TNT',1146),(3636,'Taounate','TAO',1146),(3637,'Taroudannt','TAR',1146),(3638,'Tata','TAT',1146),(3639,'Taza','TAZ',1146),(3640,'Tétouan','TET',1146),(3641,'Tiznit','TIZ',1146),(3642,'Gagauzia, Unitate Teritoriala Autonoma','GA',1142),(3643,'Chisinau','CU',1142),(3644,'Stinga Nistrului, unitatea teritoriala din','SN',1142),(3645,'Balti','BA',1142),(3646,'Cahul','CA',1142),(3647,'Edinet','ED',1142),(3648,'Lapusna','LA',1142),(3649,'Orhei','OR',1142),(3650,'Soroca','SO',1142),(3651,'Taraclia','TA',1142),(3652,'Tighina [Bender]','TI',1142),(3653,'Ungheni','UN',1142),(3654,'Antananarivo','T',1129),(3655,'Antsiranana','D',1129),(3656,'Fianarantsoa','F',1129),(3657,'Mahajanga','M',1129),(3658,'Toamasina','A',1129),(3659,'Toliara','U',1129),(3660,'Ailinglapalap','ALL',1135),(3661,'Ailuk','ALK',1135),(3662,'Arno','ARN',1135),(3663,'Aur','AUR',1135),(3664,'Ebon','EBO',1135),(3665,'Eniwetok','ENI',1135),(3666,'Jaluit','JAL',1135),(3667,'Kili','KIL',1135),(3668,'Kwajalein','KWA',1135),(3669,'Lae','LAE',1135),(3670,'Lib','LIB',1135),(3671,'Likiep','LIK',1135),(3672,'Majuro','MAJ',1135),(3673,'Maloelap','MAL',1135),(3674,'Mejit','MEJ',1135),(3675,'Mili','MIL',1135),(3676,'Namorik','NMK',1135),(3677,'Namu','NMU',1135),(3678,'Rongelap','RON',1135),(3679,'Ujae','UJA',1135),(3680,'Ujelang','UJL',1135),(3681,'Utirik','UTI',1135),(3682,'Wotho','WTN',1135),(3683,'Wotje','WTJ',1135),(3684,'Bamako','BK0',1133),(3685,'Gao','7',1133),(3686,'Kayes','1',1133),(3687,'Kidal','8',1133),(3688,'Xoulikoro','2',1133),(3689,'Mopti','5',1133),(3690,'S69ou','4',1133),(3691,'Sikasso','3',1133),(3692,'Tombouctou','6',1133),(3693,'Ayeyarwady','07',1035),(3694,'Bago','02',1035),(3695,'Magway','03',1035),(3696,'Mandalay','04',1035),(3697,'Sagaing','01',1035),(3698,'Tanintharyi','05',1035),(3699,'Yangon','06',1035),(3700,'Chin','14',1035),(3701,'Kachin','11',1035),(3702,'Kayah','12',1035),(3703,'Kayin','13',1035),(3704,'Mon','15',1035),(3705,'Rakhine','16',1035),(3706,'Shan','17',1035),(3707,'Ulaanbaatar','1',1144),(3708,'Arhangay','073',1144),(3709,'Bayanhongor','069',1144),(3710,'Bayan-Olgiy','071',1144),(3711,'Bulgan','067',1144),(3712,'Darhan uul','037',1144),(3713,'Dornod','061',1144),(3714,'Dornogov,','063',1144),(3715,'DundgovL','059',1144),(3716,'Dzavhan','057',1144),(3717,'Govi-Altay','065',1144),(3718,'Govi-Smber','064',1144),(3719,'Hentiy','039',1144),(3720,'Hovd','043',1144),(3721,'Hovsgol','041',1144),(3722,'Omnogovi','053',1144),(3723,'Orhon','035',1144),(3724,'Ovorhangay','055',1144),(3725,'Selenge','049',1144),(3726,'Shbaatar','051',1144),(3727,'Tov','047',1144),(3728,'Uvs','046',1144),(3729,'Nouakchott','NKC',1137),(3730,'Assaba','03',1137),(3731,'Brakna','05',1137),(3732,'Dakhlet Nouadhibou','08',1137),(3733,'Gorgol','04',1137),(3734,'Guidimaka','10',1137),(3735,'Hodh ech Chargui','01',1137),(3736,'Hodh el Charbi','02',1137),(3737,'Inchiri','12',1137),(3738,'Tagant','09',1137),(3739,'Tiris Zemmour','11',1137),(3740,'Trarza','06',1137),(3741,'Beau Bassin-Rose Hill','BR',1138),(3742,'Curepipe','CU',1138),(3743,'Port Louis','PU',1138),(3744,'Quatre Bornes','QB',1138),(3745,'Vacosa-Phoenix','VP',1138),(3746,'Black River','BL',1138),(3747,'Flacq','FL',1138),(3748,'Grand Port','GP',1138),(3749,'Moka','MO',1138),(3750,'Pamplemousses','PA',1138),(3751,'Plaines Wilhems','PW',1138),(3752,'Riviere du Rempart','RP',1138),(3753,'Savanne','SA',1138),(3754,'Agalega Islands','AG',1138),(3755,'Cargados Carajos Shoals','CC',1138),(3756,'Rodrigues Island','RO',1138),(3757,'Male','MLE',1132),(3758,'Alif','02',1132),(3759,'Baa','20',1132),(3760,'Dhaalu','17',1132),(3761,'Faafu','14',1132),(3762,'Gaaf Alif','27',1132),(3763,'Gaefu Dhaalu','28',1132),(3764,'Gnaviyani','29',1132),(3765,'Haa Alif','07',1132),(3766,'Haa Dhaalu','23',1132),(3767,'Kaafu','26',1132),(3768,'Laamu','05',1132),(3769,'Lhaviyani','03',1132),(3770,'Meemu','12',1132),(3771,'Noonu','25',1132),(3772,'Raa','13',1132),(3773,'Seenu','01',1132),(3774,'Shaviyani','24',1132),(3775,'Thaa','08',1132),(3776,'Vaavu','04',1132),(3777,'Balaka','BA',1130),(3778,'Blantyre','BL',1130),(3779,'Chikwawa','CK',1130),(3780,'Chiradzulu','CR',1130),(3781,'Chitipa','CT',1130),(3782,'Dedza','DE',1130),(3783,'Dowa','DO',1130),(3784,'Karonga','KR',1130),(3785,'Kasungu','KS',1130),(3786,'Likoma Island','LK',1130),(3787,'Lilongwe','LI',1130),(3788,'Machinga','MH',1130),(3789,'Mangochi','MG',1130),(3790,'Mchinji','MC',1130),(3791,'Mulanje','MU',1130),(3792,'Mwanza','MW',1130),(3793,'Mzimba','MZ',1130),(3794,'Nkhata Bay','NB',1130),(3795,'Nkhotakota','NK',1130),(3796,'Nsanje','NS',1130),(3797,'Ntcheu','NU',1130),(3798,'Ntchisi','NI',1130),(3799,'Phalomba','PH',1130),(3800,'Rumphi','RU',1130),(3801,'Salima','SA',1130),(3802,'Thyolo','TH',1130),(3803,'Zomba','ZO',1130),(3804,'Aguascalientes','AGU',1140),(3805,'Baja California','BCN',1140),(3806,'Baja California Sur','BCS',1140),(3807,'Campeche','CAM',1140),(3808,'Coahuila','COA',1140),(3809,'Colima','COL',1140),(3810,'Chiapas','CHP',1140),(3811,'Chihuahua','CHH',1140),(3812,'Durango','DUR',1140),(3813,'Guanajuato','GUA',1140),(3814,'Guerrero','GRO',1140),(3815,'Hidalgo','HID',1140),(3816,'Jalisco','JAL',1140),(3817,'Mexico','MEX',1140),(3818,'Michoacin','MIC',1140),(3819,'Morelos','MOR',1140),(3820,'Nayarit','NAY',1140),(3821,'Nuevo Leon','NLE',1140),(3822,'Oaxaca','OAX',1140),(3823,'Puebla','PUE',1140),(3824,'Queretaro','QUE',1140),(3825,'Quintana Roo','ROO',1140),(3826,'San Luis Potosi','SLP',1140),(3827,'Sinaloa','SIN',1140),(3828,'Sonora','SON',1140),(3829,'Tabasco','TAB',1140),(3830,'Tamaulipas','TAM',1140),(3831,'Tlaxcala','TLA',1140),(3832,'Veracruz','VER',1140),(3833,'Yucatan','YUC',1140),(3834,'Zacatecas','ZAC',1140),(3835,'Wilayah Persekutuan Kuala Lumpur','14',1131),(3836,'Wilayah Persekutuan Labuan','15',1131),(3837,'Wilayah Persekutuan Putrajaya','16',1131),(3838,'Johor','01',1131),(3839,'Kedah','02',1131),(3840,'Kelantan','03',1131),(3841,'Melaka','04',1131),(3842,'Negeri Sembilan','05',1131),(3843,'Pahang','06',1131),(3844,'Perak','08',1131),(3845,'Perlis','09',1131),(3846,'Pulau Pinang','07',1131),(3847,'Sabah','12',1131),(3848,'Sarawak','13',1131),(3849,'Selangor','10',1131),(3850,'Terengganu','11',1131),(3851,'Maputo','MPM',1147),(3852,'Cabo Delgado','P',1147),(3853,'Gaza','G',1147),(3854,'Inhambane','I',1147),(3855,'Manica','B',1147),(3856,'Numpula','N',1147),(3857,'Niaaea','A',1147),(3858,'Sofala','S',1147),(3859,'Tete','T',1147),(3860,'Zambezia','Q',1147),(3861,'Caprivi','CA',1148),(3862,'Erongo','ER',1148),(3863,'Hardap','HA',1148),(3864,'Karas','KA',1148),(3865,'Khomas','KH',1148),(3866,'Kunene','KU',1148),(3867,'Ohangwena','OW',1148),(3868,'Okavango','OK',1148),(3869,'Omaheke','OH',1148),(3870,'Omusati','OS',1148),(3871,'Oshana','ON',1148),(3872,'Oshikoto','OT',1148),(3873,'Otjozondjupa','OD',1148),(3874,'Niamey','8',1156),(3875,'Agadez','1',1156),(3876,'Diffa','2',1156),(3877,'Dosso','3',1156),(3878,'Maradi','4',1156),(3879,'Tahoua','S',1156),(3880,'Tillaberi','6',1156),(3881,'Zinder','7',1156),(3882,'Abuja Federal Capital Territory','FC',1157),(3883,'Abia','AB',1157),(3884,'Adamawa','AD',1157),(3885,'Akwa Ibom','AK',1157),(3886,'Anambra','AN',1157),(3887,'Bauchi','BA',1157),(3888,'Bayelsa','BY',1157),(3889,'Benue','BE',1157),(3890,'Borno','BO',1157),(3891,'Cross River','CR',1157),(3892,'Delta','DE',1157),(3893,'Ebonyi','EB',1157),(3894,'Edo','ED',1157),(3895,'Ekiti','EK',1157),(3896,'Enugu','EN',1157),(3897,'Gombe','GO',1157),(3898,'Imo','IM',1157),(3899,'Jigawa','JI',1157),(3900,'Kaduna','KD',1157),(3901,'Kano','KN',1157),(3902,'Katsina','KT',1157),(3903,'Kebbi','KE',1157),(3904,'Kogi','KO',1157),(3905,'Kwara','KW',1157),(3906,'Lagos','LA',1157),(3907,'Nassarawa','NA',1157),(3908,'Niger','NI',1157),(3909,'Ogun','OG',1157),(3910,'Ondo','ON',1157),(3911,'Osun','OS',1157),(3912,'Oyo','OY',1157),(3913,'Rivers','RI',1157),(3914,'Sokoto','SO',1157),(3915,'Taraba','TA',1157),(3916,'Yobe','YO',1157),(3917,'Zamfara','ZA',1157),(3918,'Boaco','BO',1155),(3919,'Carazo','CA',1155),(3920,'Chinandega','CI',1155),(3921,'Chontales','CO',1155),(3922,'Esteli','ES',1155),(3923,'Jinotega','JI',1155),(3924,'Leon','LE',1155),(3925,'Madriz','MD',1155),(3926,'Managua','MN',1155),(3927,'Masaya','MS',1155),(3928,'Matagalpa','MT',1155),(3929,'Nueva Segovia','NS',1155),(3930,'Rio San Juan','SJ',1155),(3931,'Rivas','RI',1155),(3932,'Atlantico Norte','AN',1155),(3933,'Atlantico Sur','AS',1155),(3934,'Drente','DR',1152),(3935,'Flevoland','FL',1152),(3936,'Friesland','FR',1152),(3937,'Gelderland','GL',1152),(3938,'Groningen','GR',1152),(3939,'Noord-Brabant','NB',1152),(3940,'Noord-Holland','NH',1152),(3941,'Overijssel','OV',1152),(3942,'Utrecht','UT',1152),(3943,'Zuid-Holland','ZH',1152),(3944,'Zeeland','ZL',1152),(3945,'Akershus','02',1161),(3946,'Aust-Agder','09',1161),(3947,'Buskerud','06',1161),(3948,'Finnmark','20',1161),(3949,'Hedmark','04',1161),(3950,'Hordaland','12',1161),(3951,'Møre og Romsdal','15',1161),(3952,'Nordland','18',1161),(3953,'Nord-Trøndelag','17',1161),(3954,'Oppland','05',1161),(3955,'Oslo','03',1161),(3956,'Rogaland','11',1161),(3957,'Sogn og Fjordane','14',1161),(3958,'Sør-Trøndelag','16',1161),(3959,'Telemark','06',1161),(3960,'Troms','19',1161),(3961,'Vest-Agder','10',1161),(3962,'Vestfold','07',1161),(3963,'Østfold','01',1161),(3964,'Jan Mayen','22',1161),(3965,'Svalbard','21',1161),(3966,'Auckland','AUK',1154),(3967,'Bay of Plenty','BOP',1154),(3968,'Canterbury','CAN',1154),(3969,'Gisborne','GIS',1154),(3970,'Hawkes Bay','HKB',1154),(3971,'Manawatu-Wanganui','MWT',1154),(3972,'Marlborough','MBH',1154),(3973,'Nelson','NSN',1154),(3974,'Northland','NTL',1154),(3975,'Otago','OTA',1154),(3976,'Southland','STL',1154),(3977,'Taranaki','TKI',1154),(3978,'Tasman','TAS',1154),(3979,'Waikato','WKO',1154),(3980,'Wellington','WGN',1154),(3981,'West Coast','WTC',1154),(3982,'Ad Dakhillyah','DA',1162),(3983,'Al Batinah','BA',1162),(3984,'Al Janblyah','JA',1162),(3985,'Al Wusta','WU',1162),(3986,'Ash Sharqlyah','SH',1162),(3987,'Az Zahirah','ZA',1162),(3988,'Masqat','MA',1162),(3989,'Musandam','MU',1162),(3990,'Bocas del Toro','1',1166),(3991,'Cocle','2',1166),(3992,'Chiriqui','4',1166),(3993,'Darien','5',1166),(3994,'Herrera','6',1166),(3995,'Loa Santoa','7',1166),(3996,'Panama','8',1166),(3997,'Veraguas','9',1166),(3998,'Comarca de San Blas','Q',1166),(3999,'El Callao','CAL',1169),(4000,'Ancash','ANC',1169),(4001,'Apurimac','APU',1169),(4002,'Arequipa','ARE',1169),(4003,'Ayacucho','AYA',1169),(4004,'Cajamarca','CAJ',1169),(4005,'Cuzco','CUS',1169),(4006,'Huancavelica','HUV',1169),(4007,'Huanuco','HUC',1169),(4008,'Ica','ICA',1169),(4009,'Junin','JUN',1169),(4010,'La Libertad','LAL',1169),(4011,'Lambayeque','LAM',1169),(4012,'Lima','LIM',1169),(4013,'Loreto','LOR',1169),(4014,'Madre de Dios','MDD',1169),(4015,'Moquegua','MOQ',1169),(4016,'Pasco','PAS',1169),(4017,'Piura','PIU',1169),(4018,'Puno','PUN',1169),(4019,'San Martin','SAM',1169),(4020,'Tacna','TAC',1169),(4021,'Tumbes','TUM',1169),(4022,'Ucayali','UCA',1169),(4023,'National Capital District (Port Moresby)','NCD',1167),(4024,'Chimbu','CPK',1167),(4025,'Eastern Highlands','EHG',1167),(4026,'East New Britain','EBR',1167),(4027,'East Sepik','ESW',1167),(4028,'Enga','EPW',1167),(4029,'Gulf','GPK',1167),(4030,'Madang','MPM',1167),(4031,'Manus','MRL',1167),(4032,'Milne Bay','MBA',1167),(4033,'Morobe','MPL',1167),(4034,'New Ireland','NIK',1167),(4035,'North Solomons','NSA',1167),(4036,'Santaun','SAN',1167),(4037,'Southern Highlands','SHM',1167),(4038,'Western Highlands','WHM',1167),(4039,'West New Britain','WBK',1167),(4040,'Abra','ABR',1170),(4041,'Agusan del Norte','AGN',1170),(4042,'Agusan del Sur','AGS',1170),(4043,'Aklan','AKL',1170),(4044,'Albay','ALB',1170),(4045,'Antique','ANT',1170),(4046,'Apayao','APA',1170),(4047,'Aurora','AUR',1170),(4048,'Basilan','BAS',1170),(4049,'Bataan','BAN',1170),(4050,'Batanes','BTN',1170),(4051,'Batangas','BTG',1170),(4052,'Benguet','BEN',1170),(4053,'Biliran','BIL',1170),(4054,'Bohol','BOH',1170),(4055,'Bukidnon','BUK',1170),(4056,'Bulacan','BUL',1170),(4057,'Cagayan','CAG',1170),(4058,'Camarines Norte','CAN',1170),(4059,'Camarines Sur','CAS',1170),(4060,'Camiguin','CAM',1170),(4061,'Capiz','CAP',1170),(4062,'Catanduanes','CAT',1170),(4063,'Cavite','CAV',1170),(4064,'Cebu','CEB',1170),(4065,'Compostela Valley','COM',1170),(4066,'Davao','DAV',1170),(4067,'Davao del Sur','DAS',1170),(4068,'Davao Oriental','DAO',1170),(4069,'Eastern Samar','EAS',1170),(4070,'Guimaras','GUI',1170),(4071,'Ifugao','IFU',1170),(4072,'Ilocos Norte','ILN',1170),(4073,'Ilocos Sur','ILS',1170),(4074,'Iloilo','ILI',1170),(4075,'Isabela','ISA',1170),(4076,'Kalinga-Apayso','KAL',1170),(4077,'Laguna','LAG',1170),(4078,'Lanao del Norte','LAN',1170),(4079,'Lanao del Sur','LAS',1170),(4080,'La Union','LUN',1170),(4081,'Leyte','LEY',1170),(4082,'Maguindanao','MAG',1170),(4083,'Marinduque','MAD',1170),(4084,'Masbate','MAS',1170),(4085,'Mindoro Occidental','MDC',1170),(4086,'Mindoro Oriental','MDR',1170),(4087,'Misamis Occidental','MSC',1170),(4088,'Misamis Oriental','MSR',1170),(4089,'Mountain Province','MOU',1170),(4090,'Negroe Occidental','NEC',1170),(4091,'Negros Oriental','NER',1170),(4092,'North Cotabato','NCO',1170),(4093,'Northern Samar','NSA',1170),(4094,'Nueva Ecija','NUE',1170),(4095,'Nueva Vizcaya','NUV',1170),(4096,'Palawan','PLW',1170),(4097,'Pampanga','PAM',1170),(4098,'Pangasinan','PAN',1170),(4099,'Quezon','QUE',1170),(4100,'Quirino','QUI',1170),(4101,'Rizal','RIZ',1170),(4102,'Romblon','ROM',1170),(4103,'Sarangani','SAR',1170),(4104,'Siquijor','SIG',1170),(4105,'Sorsogon','SOR',1170),(4106,'South Cotabato','SCO',1170),(4107,'Southern Leyte','SLE',1170),(4108,'Sultan Kudarat','SUK',1170),(4109,'Sulu','SLU',1170),(4110,'Surigao del Norte','SUN',1170),(4111,'Surigao del Sur','SUR',1170),(4112,'Tarlac','TAR',1170),(4113,'Tawi-Tawi','TAW',1170),(4114,'Western Samar','WSA',1170),(4115,'Zambales','ZMB',1170),(4116,'Zamboanga del Norte','ZAN',1170),(4117,'Zamboanga del Sur','ZAS',1170),(4118,'Zamboanga Sibiguey','ZSI',1170),(4119,'Islamabad Federal Capital Area','IS',1163),(4120,'Baluchistan','BA',1163),(4121,'Khyber Pakhtun Khawa','NW',1163),(4122,'Sindh','SD',1163),(4123,'Federally Administered Tribal Areas','TA',1163),(4124,'Azad Kashmir','JK',1163),(4125,'Gilgit-Baltistan','NA',1163),(4126,'Aveiro','01',1173),(4127,'Beja','02',1173),(4128,'Braga','03',1173),(4129,'Bragança','04',1173),(4130,'Castelo Branco','05',1173),(4131,'Coimbra','06',1173),(4132,'Évora','07',1173),(4133,'Faro','08',1173),(4134,'Guarda','09',1173),(4135,'Leiria','10',1173),(4136,'Lisboa','11',1173),(4137,'Portalegre','12',1173),(4138,'Porto','13',1173),(4139,'Santarém','14',1173),(4140,'Setúbal','15',1173),(4141,'Viana do Castelo','16',1173),(4142,'Vila Real','17',1173),(4143,'Viseu','18',1173),(4144,'Região Autónoma dos Açores','20',1173),(4145,'Região Autónoma da Madeira','30',1173),(4146,'Asuncion','ASU',1168),(4147,'Alto Paraguay','16',1168),(4148,'Alto Parana','10',1168),(4149,'Amambay','13',1168),(4150,'Boqueron','19',1168),(4151,'Caeguazu','5',1168),(4152,'Caazapl','6',1168),(4153,'Canindeyu','14',1168),(4154,'Concepcion','1',1168),(4155,'Cordillera','3',1168),(4156,'Guaira','4',1168),(4157,'Itapua','7',1168),(4158,'Miaiones','8',1168),(4159,'Neembucu','12',1168),(4160,'Paraguari','9',1168),(4161,'Presidente Hayes','15',1168),(4162,'San Pedro','2',1168),(4163,'Ad Dawhah','DA',1175),(4164,'Al Ghuwayriyah','GH',1175),(4165,'Al Jumayliyah','JU',1175),(4166,'Al Khawr','KH',1175),(4167,'Al Wakrah','WA',1175),(4168,'Ar Rayyan','RA',1175),(4169,'Jariyan al Batnah','JB',1175),(4170,'Madinat ash Shamal','MS',1175),(4171,'Umm Salal','US',1175),(4172,'Bucuresti','B',1176),(4173,'Alba','AB',1176),(4174,'Arad','AR',1176),(4175,'Argeș','AG',1176),(4176,'Bacău','BC',1176),(4177,'Bihor','BH',1176),(4178,'Bistrița-Năsăud','BN',1176),(4179,'Botoșani','BT',1176),(4180,'Brașov','BV',1176),(4181,'Brăila','BR',1176),(4182,'Buzău','BZ',1176),(4183,'Caraș-Severin','CS',1176),(4184,'Călărași','CL',1176),(4185,'Cluj','CJ',1176),(4186,'Constanța','CT',1176),(4187,'Covasna','CV',1176),(4188,'Dâmbovița','DB',1176),(4189,'Dolj','DJ',1176),(4190,'Galați','GL',1176),(4191,'Giurgiu','GR',1176),(4192,'Gorj','GJ',1176),(4193,'Harghita','HR',1176),(4194,'Hunedoara','HD',1176),(4195,'Ialomița','IL',1176),(4196,'Iași','IS',1176),(4197,'Ilfov','IF',1176),(4198,'Maramureș','MM',1176),(4199,'Mehedinți','MH',1176),(4200,'Mureș','MS',1176),(4201,'Neamț','NT',1176),(4202,'Olt','OT',1176),(4203,'Prahova','PH',1176),(4204,'Satu Mare','SM',1176),(4205,'Sălaj','SJ',1176),(4206,'Sibiu','SB',1176),(4207,'Suceava','SV',1176),(4208,'Teleorman','TR',1176),(4209,'Timiș','TM',1176),(4210,'Tulcea','TL',1176),(4211,'Vaslui','VS',1176),(4212,'Vâlcea','VL',1176),(4213,'Vrancea','VN',1176),(4214,'Adygeya, Respublika','AD',1177),(4215,'Altay, Respublika','AL',1177),(4216,'Bashkortostan, Respublika','BA',1177),(4217,'Buryatiya, Respublika','BU',1177),(4218,'Chechenskaya Respublika','CE',1177),(4219,'Chuvashskaya Respublika','CU',1177),(4220,'Dagestan, Respublika','DA',1177),(4221,'Ingushskaya Respublika','IN',1177),(4222,'Kabardino-Balkarskaya','KB',1177),(4223,'Kalmykiya, Respublika','KL',1177),(4224,'Karachayevo-Cherkesskaya Respublika','KC',1177),(4225,'Kareliya, Respublika','KR',1177),(4226,'Khakasiya, Respublika','KK',1177),(4227,'Komi, Respublika','KO',1177),(4228,'Mariy El, Respublika','ME',1177),(4229,'Mordoviya, Respublika','MO',1177),(4230,'Sakha, Respublika [Yakutiya]','SA',1177),(4231,'Severnaya Osetiya, Respublika','SE',1177),(4232,'Tatarstan, Respublika','TA',1177),(4233,'Tyva, Respublika [Tuva]','TY',1177),(4234,'Udmurtskaya Respublika','UD',1177),(4235,'Altayskiy kray','ALT',1177),(4236,'Khabarovskiy kray','KHA',1177),(4237,'Krasnodarskiy kray','KDA',1177),(4238,'Krasnoyarskiy kray','KYA',1177),(4239,'Primorskiy kray','PRI',1177),(4240,'Stavropol\'skiy kray','STA',1177),(4241,'Amurskaya oblast\'','AMU',1177),(4242,'Arkhangel\'skaya oblast\'','ARK',1177),(4243,'Astrakhanskaya oblast\'','AST',1177),(4244,'Belgorodskaya oblast\'','BEL',1177),(4245,'Bryanskaya oblast\'','BRY',1177),(4246,'Chelyabinskaya oblast\'','CHE',1177),(4247,'Zabaykalsky Krai\'','ZSK',1177),(4248,'Irkutskaya oblast\'','IRK',1177),(4249,'Ivanovskaya oblast\'','IVA',1177),(4250,'Kaliningradskaya oblast\'','KGD',1177),(4251,'Kaluzhskaya oblast\'','KLU',1177),(4252,'Kamchatka Krai\'','KAM',1177),(4253,'Kemerovskaya oblast\'','KEM',1177),(4254,'Kirovskaya oblast\'','KIR',1177),(4255,'Kostromskaya oblast\'','KOS',1177),(4256,'Kurganskaya oblast\'','KGN',1177),(4257,'Kurskaya oblast\'','KRS',1177),(4258,'Leningradskaya oblast\'','LEN',1177),(4259,'Lipetskaya oblast\'','LIP',1177),(4260,'Magadanskaya oblast\'','MAG',1177),(4261,'Moskovskaya oblast\'','MOS',1177),(4262,'Murmanskaya oblast\'','MUR',1177),(4263,'Nizhegorodskaya oblast\'','NIZ',1177),(4264,'Novgorodskaya oblast\'','NGR',1177),(4265,'Novosibirskaya oblast\'','NVS',1177),(4266,'Omskaya oblast\'','OMS',1177),(4267,'Orenburgskaya oblast\'','ORE',1177),(4268,'Orlovskaya oblast\'','ORL',1177),(4269,'Penzenskaya oblast\'','PNZ',1177),(4270,'Perm krai\'','PEK',1177),(4271,'Pskovskaya oblast\'','PSK',1177),(4272,'Rostovskaya oblast\'','ROS',1177),(4273,'Ryazanskaya oblast\'','RYA',1177),(4274,'Sakhalinskaya oblast\'','SAK',1177),(4275,'Samarskaya oblast\'','SAM',1177),(4276,'Saratovskaya oblast\'','SAR',1177),(4277,'Smolenskaya oblast\'','SMO',1177),(4278,'Sverdlovskaya oblast\'','SVE',1177),(4279,'Tambovskaya oblast\'','TAM',1177),(4280,'Tomskaya oblast\'','TOM',1177),(4281,'Tul\'skaya oblast\'','TUL',1177),(4282,'Tverskaya oblast\'','TVE',1177),(4283,'Tyumenskaya oblast\'','TYU',1177),(4284,'Ul\'yanovskaya oblast\'','ULY',1177),(4285,'Vladimirskaya oblast\'','VLA',1177),(4286,'Volgogradskaya oblast\'','VGG',1177),(4287,'Vologodskaya oblast\'','VLG',1177),(4288,'Voronezhskaya oblast\'','VOR',1177),(4289,'Yaroslavskaya oblast\'','YAR',1177),(4290,'Moskva','MOW',1177),(4291,'Sankt-Peterburg','SPE',1177),(4292,'Yevreyskaya avtonomnaya oblast\'','YEV',1177),(4294,'Chukotskiy avtonomnyy okrug','CHU',1177),(4296,'Khanty-Mansiyskiy avtonomnyy okrug','KHM',1177),(4299,'Nenetskiy avtonomnyy okrug','NEN',1177),(4302,'Yamalo-Nenetskiy avtonomnyy okrug','YAN',1177),(4303,'Butare','C',1178),(4304,'Byumba','I',1178),(4305,'Cyangugu','E',1178),(4306,'Gikongoro','D',1178),(4307,'Gisenyi','G',1178),(4308,'Gitarama','B',1178),(4309,'Kibungo','J',1178),(4310,'Kibuye','F',1178),(4311,'Kigali-Rural Kigali y\' Icyaro','K',1178),(4312,'Kigali-Ville Kigali Ngari','L',1178),(4313,'Mutara','M',1178),(4314,'Ruhengeri','H',1178),(4315,'Al Bahah','11',1187),(4316,'Al Hudud Ash Shamaliyah','08',1187),(4317,'Al Jawf','12',1187),(4318,'Al Madinah','03',1187),(4319,'Al Qasim','05',1187),(4320,'Ar Riyad','01',1187),(4321,'Asir','14',1187),(4322,'Ha\'il','06',1187),(4323,'Jlzan','09',1187),(4324,'Makkah','02',1187),(4325,'Najran','10',1187),(4326,'Tabuk','07',1187),(4327,'Capital Territory (Honiara)','CT',1194),(4328,'Guadalcanal','GU',1194),(4329,'Isabel','IS',1194),(4330,'Makira','MK',1194),(4331,'Malaita','ML',1194),(4332,'Temotu','TE',1194),(4333,'A\'ali an Nil','23',1200),(4334,'Al Bah al Ahmar','26',1200),(4335,'Al Buhayrat','18',1200),(4336,'Al Jazirah','07',1200),(4337,'Al Khartum','03',1200),(4338,'Al Qadarif','06',1200),(4339,'Al Wahdah','22',1200),(4340,'An Nil','04',1200),(4341,'An Nil al Abyaq','08',1200),(4342,'An Nil al Azraq','24',1200),(4343,'Ash Shamallyah','01',1200),(4344,'Bahr al Jabal','17',1200),(4345,'Gharb al Istiwa\'iyah','16',1200),(4346,'Gharb Ba~r al Ghazal','14',1200),(4347,'Gharb Darfur','12',1200),(4348,'Gharb Kurdufan','10',1200),(4349,'Janub Darfur','11',1200),(4350,'Janub Rurdufan','13',1200),(4351,'Jnqall','20',1200),(4352,'Kassala','05',1200),(4353,'Shamal Batr al Ghazal','15',1200),(4354,'Shamal Darfur','02',1200),(4355,'Shamal Kurdufan','09',1200),(4356,'Sharq al Istiwa\'iyah','19',1200),(4357,'Sinnar','25',1200),(4358,'Warab','21',1200),(4359,'Blekinge län','K',1204),(4360,'Dalarnas län','W',1204),(4361,'Gotlands län','I',1204),(4362,'Gävleborgs län','X',1204),(4363,'Hallands län','N',1204),(4364,'Jämtlands län','Z',1204),(4365,'Jönkopings län','F',1204),(4366,'Kalmar län','H',1204),(4367,'Kronobergs län','G',1204),(4368,'Norrbottens län','BD',1204),(4369,'Skåne län','M',1204),(4370,'Stockholms län','AB',1204),(4371,'Södermanlands län','D',1204),(4372,'Uppsala län','C',1204),(4373,'Värmlands län','S',1204),(4374,'Västerbottens län','AC',1204),(4375,'Västernorrlands län','Y',1204),(4376,'Västmanlands län','U',1204),(4377,'Västra Götalands län','Q',1204),(4378,'Örebro län','T',1204),(4379,'Östergötlands län','E',1204),(4380,'Saint Helena','SH',1180),(4381,'Ascension','AC',1180),(4382,'Tristan da Cunha','TA',1180),(4383,'Ajdovščina','001',1193),(4384,'Beltinci','002',1193),(4385,'Benedikt','148',1193),(4386,'Bistrica ob Sotli','149',1193),(4387,'Bled','003',1193),(4388,'Bloke','150',1193),(4389,'Bohinj','004',1193),(4390,'Borovnica','005',1193),(4391,'Bovec','006',1193),(4392,'Braslovče','151',1193),(4393,'Brda','007',1193),(4394,'Brezovica','008',1193),(4395,'Brežice','009',1193),(4396,'Cankova','152',1193),(4397,'Celje','011',1193),(4398,'Cerklje na Gorenjskem','012',1193),(4399,'Cerknica','013',1193),(4400,'Cerkno','014',1193),(4401,'Cerkvenjak','153',1193),(4402,'Črenšovci','015',1193),(4403,'Črna na Koroškem','016',1193),(4404,'Črnomelj','017',1193),(4405,'Destrnik','018',1193),(4406,'Divača','019',1193),(4407,'Dobje','154',1193),(4408,'Dobrepolje','020',1193),(4409,'Dobrna','155',1193),(4410,'Dobrova-Polhov Gradec','021',1193),(4411,'Dobrovnik','156',1193),(4412,'Dol pri Ljubljani','022',1193),(4413,'Dolenjske Toplice','157',1193),(4414,'Domžale','023',1193),(4415,'Dornava','024',1193),(4416,'Dravograd','025',1193),(4417,'Duplek','026',1193),(4418,'Gorenja vas-Poljane','027',1193),(4419,'Gorišnica','028',1193),(4420,'Gornja Radgona','029',1193),(4421,'Gornji Grad','030',1193),(4422,'Gornji Petrovci','031',1193),(4423,'Grad','158',1193),(4424,'Grosuplje','032',1193),(4425,'Hajdina','159',1193),(4426,'Hoče-Slivnica','160',1193),(4427,'Hodoš','161',1193),(4428,'Horjul','162',1193),(4429,'Hrastnik','034',1193),(4430,'Hrpelje-Kozina','035',1193),(4431,'Idrija','036',1193),(4432,'Ig','037',1193),(4433,'Ilirska Bistrica','038',1193),(4434,'Ivančna Gorica','039',1193),(4435,'Izola','040',1193),(4436,'Jesenice','041',1193),(4437,'Jezersko','163',1193),(4438,'Juršinci','042',1193),(4439,'Kamnik','043',1193),(4440,'Kanal','044',1193),(4441,'Kidričevo','045',1193),(4442,'Kobarid','046',1193),(4443,'Kobilje','047',1193),(4444,'Kočevje','048',1193),(4445,'Komen','049',1193),(4446,'Komenda','164',1193),(4447,'Koper','050',1193),(4448,'Kostel','165',1193),(4449,'Kozje','051',1193),(4450,'Kranj','052',1193),(4451,'Kranjska Gora','053',1193),(4452,'Križevci','166',1193),(4453,'Krško','054',1193),(4454,'Kungota','055',1193),(4455,'Kuzma','056',1193),(4456,'Laško','057',1193),(4457,'Lenart','058',1193),(4458,'Lendava','059',1193),(4459,'Litija','060',1193),(4460,'Ljubljana','061',1193),(4461,'Ljubno','062',1193),(4462,'Ljutomer','063',1193),(4463,'Logatec','064',1193),(4464,'Loška dolina','065',1193),(4465,'Loški Potok','066',1193),(4466,'Lovrenc na Pohorju','167',1193),(4467,'Luče','067',1193),(4468,'Lukovica','068',1193),(4469,'Majšperk','069',1193),(4470,'Maribor','070',1193),(4471,'Markovci','168',1193),(4472,'Medvode','071',1193),(4473,'Mengeš','072',1193),(4474,'Metlika','073',1193),(4475,'Mežica','074',1193),(4476,'Miklavž na Dravskem polju','169',1193),(4477,'Miren-Kostanjevica','075',1193),(4478,'Mirna Peč','170',1193),(4479,'Mislinja','076',1193),(4480,'Moravče','077',1193),(4481,'Moravske Toplice','078',1193),(4482,'Mozirje','079',1193),(4483,'Murska Sobota','080',1193),(4484,'Muta','081',1193),(4485,'Naklo','082',1193),(4486,'Nazarje','083',1193),(4487,'Nova Gorica','084',1193),(4488,'Novo mesto','085',1193),(4489,'Sveta Ana','181',1193),(4490,'Sveti Andraž v Slovenskih goricah','182',1193),(4491,'Sveti Jurij','116',1193),(4492,'Šalovci','033',1193),(4493,'Šempeter-Vrtojba','183',1193),(4494,'Šenčur','117',1193),(4495,'Šentilj','118',1193),(4496,'Šentjernej','119',1193),(4497,'Šentjur','120',1193),(4498,'Škocjan','121',1193),(4499,'Škofja Loka','122',1193),(4500,'Škofljica','123',1193),(4501,'Šmarje pri Jelšah','124',1193),(4502,'Šmartno ob Paki','125',1193),(4503,'Šmartno pri Litiji','194',1193),(4504,'Šoštanj','126',1193),(4505,'Štore','127',1193),(4506,'Tabor','184',1193),(4507,'Tišina','010',1193),(4508,'Tolmin','128',1193),(4509,'Trbovlje','129',1193),(4510,'Trebnje','130',1193),(4511,'Trnovska vas','185',1193),(4512,'Tržič','131',1193),(4513,'Trzin','186',1193),(4514,'Turnišče','132',1193),(4515,'Velenje','133',1193),(4516,'Velika Polana','187',1193),(4517,'Velike Lašče','134',1193),(4518,'Veržej','188',1193),(4519,'Videm','135',1193),(4520,'Vipava','136',1193),(4521,'Vitanje','137',1193),(4522,'Vojnik','138',1193),(4523,'Vransko','189',1193),(4524,'Vrhnika','140',1193),(4525,'Vuzenica','141',1193),(4526,'Zagorje ob Savi','142',1193),(4527,'Zavrč','143',1193),(4528,'Zreče','144',1193),(4529,'Žalec','190',1193),(4530,'Železniki','146',1193),(4531,'Žetale','191',1193),(4532,'Žiri','147',1193),(4533,'Žirovnica','192',1193),(4534,'Žužemberk','193',1193),(4535,'Banskobystrický kraj','BC',1192),(4536,'Bratislavský kraj','BL',1192),(4537,'Košický kraj','KI',1192),(4538,'Nitriansky kraj','NJ',1192),(4539,'Prešovský kraj','PV',1192),(4540,'Trenčiansky kraj','TC',1192),(4541,'Trnavský kraj','TA',1192),(4542,'Žilinský kraj','ZI',1192),(4543,'Western Area (Freetown)','W',1190),(4544,'Dakar','DK',1188),(4545,'Diourbel','DB',1188),(4546,'Fatick','FK',1188),(4547,'Kaolack','KL',1188),(4548,'Kolda','KD',1188),(4549,'Louga','LG',1188),(4550,'Matam','MT',1188),(4551,'Saint-Louis','SL',1188),(4552,'Tambacounda','TC',1188),(4553,'Thies','TH',1188),(4554,'Ziguinchor','ZG',1188),(4555,'Awdal','AW',1195),(4556,'Bakool','BK',1195),(4557,'Banaadir','BN',1195),(4558,'Bay','BY',1195),(4559,'Galguduud','GA',1195),(4560,'Gedo','GE',1195),(4561,'Hiirsan','HI',1195),(4562,'Jubbada Dhexe','JD',1195),(4563,'Jubbada Hoose','JH',1195),(4564,'Mudug','MU',1195),(4565,'Nugaal','NU',1195),(4566,'Saneag','SA',1195),(4567,'Shabeellaha Dhexe','SD',1195),(4568,'Shabeellaha Hoose','SH',1195),(4569,'Sool','SO',1195),(4570,'Togdheer','TO',1195),(4571,'Woqooyi Galbeed','WO',1195),(4572,'Brokopondo','BR',1201),(4573,'Commewijne','CM',1201),(4574,'Coronie','CR',1201),(4575,'Marowijne','MA',1201),(4576,'Nickerie','NI',1201),(4577,'Paramaribo','PM',1201),(4578,'Saramacca','SA',1201),(4579,'Sipaliwini','SI',1201),(4580,'Wanica','WA',1201),(4581,'Principe','P',1207),(4582,'Sao Tome','S',1207),(4583,'Ahuachapan','AH',1066),(4584,'Cabanas','CA',1066),(4585,'Cuscatlan','CU',1066),(4586,'Chalatenango','CH',1066),(4587,'Morazan','MO',1066),(4588,'San Miguel','SM',1066),(4589,'San Salvador','SS',1066),(4590,'Santa Ana','SA',1066),(4591,'San Vicente','SV',1066),(4592,'Sonsonate','SO',1066),(4593,'Usulutan','US',1066),(4594,'Al Hasakah','HA',1206),(4595,'Al Ladhiqiyah','LA',1206),(4596,'Al Qunaytirah','QU',1206),(4597,'Ar Raqqah','RA',1206),(4598,'As Suwayda\'','SU',1206),(4599,'Dar\'a','DR',1206),(4600,'Dayr az Zawr','DY',1206),(4601,'Dimashq','DI',1206),(4602,'Halab','HL',1206),(4603,'Hamah','HM',1206),(4604,'Jim\'','HI',1206),(4605,'Idlib','ID',1206),(4606,'Rif Dimashq','RD',1206),(4607,'Tarts','TA',1206),(4608,'Hhohho','HH',1203),(4609,'Lubombo','LU',1203),(4610,'Manzini','MA',1203),(4611,'Shiselweni','SH',1203),(4612,'Batha','BA',1043),(4613,'Biltine','BI',1043),(4614,'Borkou-Ennedi-Tibesti','BET',1043),(4615,'Chari-Baguirmi','CB',1043),(4616,'Guera','GR',1043),(4617,'Kanem','KA',1043),(4618,'Lac','LC',1043),(4619,'Logone-Occidental','LO',1043),(4620,'Logone-Oriental','LR',1043),(4621,'Mayo-Kebbi','MK',1043),(4622,'Moyen-Chari','MC',1043),(4623,'Ouaddai','OD',1043),(4624,'Salamat','SA',1043),(4625,'Tandjile','TA',1043),(4626,'Kara','K',1214),(4627,'Maritime (Region)','M',1214),(4628,'Savannes','S',1214),(4629,'Krung Thep Maha Nakhon Bangkok','10',1211),(4630,'Phatthaya','S',1211),(4631,'Amnat Charoen','37',1211),(4632,'Ang Thong','15',1211),(4633,'Buri Ram','31',1211),(4634,'Chachoengsao','24',1211),(4635,'Chai Nat','18',1211),(4636,'Chaiyaphum','36',1211),(4637,'Chanthaburi','22',1211),(4638,'Chiang Mai','50',1211),(4639,'Chiang Rai','57',1211),(4640,'Chon Buri','20',1211),(4641,'Chumphon','86',1211),(4642,'Kalasin','46',1211),(4643,'Kamphasng Phet','62',1211),(4644,'Kanchanaburi','71',1211),(4645,'Khon Kaen','40',1211),(4646,'Krabi','81',1211),(4647,'Lampang','52',1211),(4648,'Lamphun','51',1211),(4649,'Loei','42',1211),(4650,'Lop Buri','16',1211),(4651,'Mae Hong Son','58',1211),(4652,'Maha Sarakham','44',1211),(4653,'Mukdahan','49',1211),(4654,'Nakhon Nayok','26',1211),(4655,'Nakhon Pathom','73',1211),(4656,'Nakhon Phanom','48',1211),(4657,'Nakhon Ratchasima','30',1211),(4658,'Nakhon Sawan','60',1211),(4659,'Nakhon Si Thammarat','80',1211),(4660,'Nan','55',1211),(4661,'Narathiwat','96',1211),(4662,'Nong Bua Lam Phu','39',1211),(4663,'Nong Khai','43',1211),(4664,'Nonthaburi','12',1211),(4665,'Pathum Thani','13',1211),(4666,'Pattani','94',1211),(4667,'Phangnga','82',1211),(4668,'Phatthalung','93',1211),(4669,'Phayao','56',1211),(4670,'Phetchabun','67',1211),(4671,'Phetchaburi','76',1211),(4672,'Phichit','66',1211),(4673,'Phitsanulok','65',1211),(4674,'Phrae','54',1211),(4675,'Phra Nakhon Si Ayutthaya','14',1211),(4676,'Phuket','83',1211),(4677,'Prachin Buri','25',1211),(4678,'Prachuap Khiri Khan','77',1211),(4679,'Ranong','85',1211),(4680,'Ratchaburi','70',1211),(4681,'Rayong','21',1211),(4682,'Roi Et','45',1211),(4683,'Sa Kaeo','27',1211),(4684,'Sakon Nakhon','47',1211),(4685,'Samut Prakan','11',1211),(4686,'Samut Sakhon','74',1211),(4687,'Samut Songkhram','75',1211),(4688,'Saraburi','19',1211),(4689,'Satun','91',1211),(4690,'Sing Buri','17',1211),(4691,'Si Sa Ket','33',1211),(4692,'Songkhla','90',1211),(4693,'Sukhothai','64',1211),(4694,'Suphan Buri','72',1211),(4695,'Surat Thani','84',1211),(4696,'Surin','32',1211),(4697,'Tak','63',1211),(4698,'Trang','92',1211),(4699,'Trat','23',1211),(4700,'Ubon Ratchathani','34',1211),(4701,'Udon Thani','41',1211),(4702,'Uthai Thani','61',1211),(4703,'Uttaradit','53',1211),(4704,'Yala','95',1211),(4705,'Yasothon','35',1211),(4706,'Sughd','SU',1209),(4707,'Khatlon','KT',1209),(4708,'Gorno-Badakhshan','GB',1209),(4709,'Ahal','A',1220),(4710,'Balkan','B',1220),(4711,'Dasoguz','D',1220),(4712,'Lebap','L',1220),(4713,'Mary','M',1220),(4714,'Béja','31',1218),(4715,'Ben Arous','13',1218),(4716,'Bizerte','23',1218),(4717,'Gabès','81',1218),(4718,'Gafsa','71',1218),(4719,'Jendouba','32',1218),(4720,'Kairouan','41',1218),(4721,'Rasserine','42',1218),(4722,'Kebili','73',1218),(4723,'L\'Ariana','12',1218),(4724,'Le Ref','33',1218),(4725,'Mahdia','53',1218),(4726,'La Manouba','14',1218),(4727,'Medenine','82',1218),(4728,'Moneatir','52',1218),(4729,'Naboul','21',1218),(4730,'Sfax','61',1218),(4731,'Sidi Bouxid','43',1218),(4732,'Siliana','34',1218),(4733,'Sousse','51',1218),(4734,'Tataouine','83',1218),(4735,'Tozeur','72',1218),(4736,'Tunis','11',1218),(4737,'Zaghouan','22',1218),(4738,'Adana','01',1219),(4739,'Ad yaman','02',1219),(4740,'Afyon','03',1219),(4741,'Ag r','04',1219),(4742,'Aksaray','68',1219),(4743,'Amasya','05',1219),(4744,'Ankara','06',1219),(4745,'Antalya','07',1219),(4746,'Ardahan','75',1219),(4747,'Artvin','08',1219),(4748,'Aydin','09',1219),(4749,'Bal kesir','10',1219),(4750,'Bartin','74',1219),(4751,'Batman','72',1219),(4752,'Bayburt','69',1219),(4753,'Bilecik','11',1219),(4754,'Bingol','12',1219),(4755,'Bitlis','13',1219),(4756,'Bolu','14',1219),(4757,'Burdur','15',1219),(4758,'Bursa','16',1219),(4759,'Canakkale','17',1219),(4760,'Cankir','18',1219),(4761,'Corum','19',1219),(4762,'Denizli','20',1219),(4763,'Diyarbakir','21',1219),(4764,'Duzce','81',1219),(4765,'Edirne','22',1219),(4766,'Elazig','23',1219),(4767,'Erzincan','24',1219),(4768,'Erzurum','25',1219),(4769,'Eskis\'ehir','26',1219),(4770,'Gaziantep','27',1219),(4771,'Giresun','28',1219),(4772,'Gms\'hane','29',1219),(4773,'Hakkari','30',1219),(4774,'Hatay','31',1219),(4775,'Igidir','76',1219),(4776,'Isparta','32',1219),(4777,'Icel','33',1219),(4778,'Istanbul','34',1219),(4779,'Izmir','35',1219),(4780,'Kahramanmaras','46',1219),(4781,'Karabk','78',1219),(4782,'Karaman','70',1219),(4783,'Kars','36',1219),(4784,'Kastamonu','37',1219),(4785,'Kayseri','38',1219),(4786,'Kirikkale','71',1219),(4787,'Kirklareli','39',1219),(4788,'Kirs\'ehir','40',1219),(4789,'Kilis','79',1219),(4790,'Kocaeli','41',1219),(4791,'Konya','42',1219),(4792,'Ktahya','43',1219),(4793,'Malatya','44',1219),(4794,'Manisa','45',1219),(4795,'Mardin','47',1219),(4796,'Mugila','48',1219),(4797,'Mus','49',1219),(4798,'Nevs\'ehir','50',1219),(4799,'Nigide','51',1219),(4800,'Ordu','52',1219),(4801,'Osmaniye','80',1219),(4802,'Rize','53',1219),(4803,'Sakarya','54',1219),(4804,'Samsun','55',1219),(4805,'Siirt','56',1219),(4806,'Sinop','57',1219),(4807,'Sivas','58',1219),(4808,'S\'anliurfa','63',1219),(4809,'S\'rnak','73',1219),(4810,'Tekirdag','59',1219),(4811,'Tokat','60',1219),(4812,'Trabzon','61',1219),(4813,'Tunceli','62',1219),(4814,'Us\'ak','64',1219),(4815,'Van','65',1219),(4816,'Yalova','77',1219),(4817,'Yozgat','66',1219),(4818,'Zonguldak','67',1219),(4819,'Couva-Tabaquite-Talparo','CTT',1217),(4820,'Diego Martin','DMN',1217),(4821,'Eastern Tobago','ETO',1217),(4822,'Penal-Debe','PED',1217),(4823,'Princes Town','PRT',1217),(4824,'Rio Claro-Mayaro','RCM',1217),(4825,'Sangre Grande','SGE',1217),(4826,'San Juan-Laventille','SJL',1217),(4827,'Siparia','SIP',1217),(4828,'Tunapuna-Piarco','TUP',1217),(4829,'Western Tobago','WTO',1217),(4830,'Arima','ARI',1217),(4831,'Chaguanas','CHA',1217),(4832,'Point Fortin','PTF',1217),(4833,'Port of Spain','POS',1217),(4834,'San Fernando','SFO',1217),(4835,'Aileu','AL',1063),(4836,'Ainaro','AN',1063),(4837,'Bacucau','BA',1063),(4838,'Bobonaro','BO',1063),(4839,'Cova Lima','CO',1063),(4840,'Dili','DI',1063),(4841,'Ermera','ER',1063),(4842,'Laulem','LA',1063),(4843,'Liquica','LI',1063),(4844,'Manatuto','MT',1063),(4845,'Manafahi','MF',1063),(4846,'Oecussi','OE',1063),(4847,'Viqueque','VI',1063),(4848,'Changhua County','CHA',1208),(4849,'Chiayi County','CYQ',1208),(4850,'Hsinchu County','HSQ',1208),(4851,'Hualien County','HUA',1208),(4852,'Ilan County','ILA',1208),(4853,'Kaohsiung County','KHQ',1208),(4854,'Miaoli County','MIA',1208),(4855,'Nantou County','NAN',1208),(4856,'Penghu County','PEN',1208),(4857,'Pingtung County','PIF',1208),(4858,'Taichung County','TXQ',1208),(4859,'Tainan County','TNQ',1208),(4860,'Taipei County','TPQ',1208),(4861,'Taitung County','TTT',1208),(4862,'Taoyuan County','TAO',1208),(4863,'Yunlin County','YUN',1208),(4864,'Keelung City','KEE',1208),(4865,'Arusha','01',1210),(4866,'Dar-es-Salaam','02',1210),(4867,'Dodoma','03',1210),(4868,'Iringa','04',1210),(4869,'Kagera','05',1210),(4870,'Kaskazini Pemba','06',1210),(4871,'Kaskazini Unguja','07',1210),(4872,'Xigoma','08',1210),(4873,'Kilimanjaro','09',1210),(4874,'Rusini Pemba','10',1210),(4875,'Kusini Unguja','11',1210),(4876,'Lindi','12',1210),(4877,'Manyara','26',1210),(4878,'Mara','13',1210),(4879,'Mbeya','14',1210),(4880,'Mjini Magharibi','15',1210),(4881,'Morogoro','16',1210),(4882,'Mtwara','17',1210),(4883,'Pwani','19',1210),(4884,'Rukwa','20',1210),(4885,'Ruvuma','21',1210),(4886,'Shinyanga','22',1210),(4887,'Singida','23',1210),(4888,'Tabora','24',1210),(4889,'Tanga','25',1210),(4890,'Cherkas\'ka Oblast\'','71',1224),(4891,'Chernihivs\'ka Oblast\'','74',1224),(4892,'Chernivets\'ka Oblast\'','77',1224),(4893,'Dnipropetrovs\'ka Oblast\'','12',1224),(4894,'Donets\'ka Oblast\'','14',1224),(4895,'Ivano-Frankivs\'ka Oblast\'','26',1224),(4896,'Kharkivs\'ka Oblast\'','63',1224),(4897,'Khersons\'ka Oblast\'','65',1224),(4898,'Khmel\'nyts\'ka Oblast\'','68',1224),(4899,'Kirovohrads\'ka Oblast\'','35',1224),(4900,'Kyivs\'ka Oblast\'','32',1224),(4901,'Luhans\'ka Oblast\'','09',1224),(4902,'L\'vivs\'ka Oblast\'','46',1224),(4903,'Mykolaivs\'ka Oblast\'','48',1224),(4904,'Odes \'ka Oblast\'','51',1224),(4905,'Poltavs\'ka Oblast\'','53',1224),(4906,'Rivnens\'ka Oblast\'','56',1224),(4907,'Sums \'ka Oblast\'','59',1224),(4908,'Ternopil\'s\'ka Oblast\'','61',1224),(4909,'Vinnyts\'ka Oblast\'','05',1224),(4910,'Volyos\'ka Oblast\'','07',1224),(4911,'Zakarpats\'ka Oblast\'','21',1224),(4912,'Zaporiz\'ka Oblast\'','23',1224),(4913,'Zhytomyrs\'ka Oblast\'','18',1224),(4914,'Respublika Krym','43',1224),(4915,'Kyiv','30',1224),(4916,'Sevastopol','40',1224),(4917,'Adjumani','301',1223),(4918,'Apac','302',1223),(4919,'Arua','303',1223),(4920,'Bugiri','201',1223),(4921,'Bundibugyo','401',1223),(4922,'Bushenyi','402',1223),(4923,'Busia','202',1223),(4924,'Gulu','304',1223),(4925,'Hoima','403',1223),(4926,'Iganga','203',1223),(4927,'Jinja','204',1223),(4928,'Kabale','404',1223),(4929,'Kabarole','405',1223),(4930,'Kaberamaido','213',1223),(4931,'Kalangala','101',1223),(4932,'Kampala','102',1223),(4933,'Kamuli','205',1223),(4934,'Kamwenge','413',1223),(4935,'Kanungu','414',1223),(4936,'Kapchorwa','206',1223),(4937,'Kasese','406',1223),(4938,'Katakwi','207',1223),(4939,'Kayunga','112',1223),(4940,'Kibaale','407',1223),(4941,'Kiboga','103',1223),(4942,'Kisoro','408',1223),(4943,'Kitgum','305',1223),(4944,'Kotido','306',1223),(4945,'Kumi','208',1223),(4946,'Kyenjojo','415',1223),(4947,'Lira','307',1223),(4948,'Luwero','104',1223),(4949,'Masaka','105',1223),(4950,'Masindi','409',1223),(4951,'Mayuge','214',1223),(4952,'Mbale','209',1223),(4953,'Mbarara','410',1223),(4954,'Moroto','308',1223),(4955,'Moyo','309',1223),(4956,'Mpigi','106',1223),(4957,'Mubende','107',1223),(4958,'Mukono','108',1223),(4959,'Nakapiripirit','311',1223),(4960,'Nakasongola','109',1223),(4961,'Nebbi','310',1223),(4962,'Ntungamo','411',1223),(4963,'Pader','312',1223),(4964,'Pallisa','210',1223),(4965,'Rakai','110',1223),(4966,'Rukungiri','412',1223),(4967,'Sembabule','111',1223),(4968,'Sironko','215',1223),(4969,'Soroti','211',1223),(4970,'Tororo','212',1223),(4971,'Wakiso','113',1223),(4972,'Yumbe','313',1223),(4973,'Baker Island','81',1227),(4974,'Howland Island','84',1227),(4975,'Jarvis Island','86',1227),(4976,'Johnston Atoll','67',1227),(4977,'Kingman Reef','89',1227),(4978,'Midway Islands','71',1227),(4979,'Navassa Island','76',1227),(4980,'Palmyra Atoll','95',1227),(4981,'Wake Island','79',1227),(4982,'Artigsa','AR',1229),(4983,'Canelones','CA',1229),(4984,'Cerro Largo','CL',1229),(4985,'Colonia','CO',1229),(4986,'Durazno','DU',1229),(4987,'Flores','FS',1229),(4988,'Lavalleja','LA',1229),(4989,'Maldonado','MA',1229),(4990,'Montevideo','MO',1229),(4991,'Paysandu','PA',1229),(4992,'Rivera','RV',1229),(4993,'Rocha','RO',1229),(4994,'Salto','SA',1229),(4995,'Soriano','SO',1229),(4996,'Tacuarembo','TA',1229),(4997,'Treinta y Tres','TT',1229),(4998,'Toshkent (city)','TK',1230),(4999,'Qoraqalpogiston Respublikasi','QR',1230),(5000,'Andijon','AN',1230),(5001,'Buxoro','BU',1230),(5002,'Farg\'ona','FA',1230),(5003,'Jizzax','JI',1230),(5004,'Khorazm','KH',1230),(5005,'Namangan','NG',1230),(5006,'Navoiy','NW',1230),(5007,'Qashqadaryo','QA',1230),(5008,'Samarqand','SA',1230),(5009,'Sirdaryo','SI',1230),(5010,'Surxondaryo','SU',1230),(5011,'Toshkent','TO',1230),(5012,'Xorazm','XO',1230),(5013,'Distrito Federal','A',1232),(5014,'Anzoategui','B',1232),(5015,'Apure','C',1232),(5016,'Aragua','D',1232),(5017,'Barinas','E',1232),(5018,'Carabobo','G',1232),(5019,'Cojedes','H',1232),(5020,'Falcon','I',1232),(5021,'Guarico','J',1232),(5022,'Lara','K',1232),(5023,'Merida','L',1232),(5024,'Miranda','M',1232),(5025,'Monagas','N',1232),(5026,'Nueva Esparta','O',1232),(5027,'Portuguesa','P',1232),(5028,'Tachira','S',1232),(5029,'Trujillo','T',1232),(5030,'Vargas','X',1232),(5031,'Yaracuy','U',1232),(5032,'Zulia','V',1232),(5033,'Delta Amacuro','Y',1232),(5034,'Dependencias Federales','W',1232),(5035,'An Giang','44',1233),(5036,'Ba Ria - Vung Tau','43',1233),(5037,'Bac Can','53',1233),(5038,'Bac Giang','54',1233),(5039,'Bac Lieu','55',1233),(5040,'Bac Ninh','56',1233),(5041,'Ben Tre','50',1233),(5042,'Binh Dinh','31',1233),(5043,'Binh Duong','57',1233),(5044,'Binh Phuoc','58',1233),(5045,'Binh Thuan','40',1233),(5046,'Ca Mau','59',1233),(5047,'Can Tho','48',1233),(5048,'Cao Bang','04',1233),(5049,'Da Nang, thanh pho','60',1233),(5050,'Dong Nai','39',1233),(5051,'Dong Thap','45',1233),(5052,'Gia Lai','30',1233),(5053,'Ha Giang','03',1233),(5054,'Ha Nam','63',1233),(5055,'Ha Noi, thu do','64',1233),(5056,'Ha Tay','15',1233),(5057,'Ha Tinh','23',1233),(5058,'Hai Duong','61',1233),(5059,'Hai Phong, thanh pho','62',1233),(5060,'Hoa Binh','14',1233),(5061,'Ho Chi Minh, thanh pho [Sai Gon]','65',1233),(5062,'Hung Yen','66',1233),(5063,'Khanh Hoa','34',1233),(5064,'Kien Giang','47',1233),(5065,'Kon Tum','28',1233),(5066,'Lai Chau','01',1233),(5067,'Lam Dong','35',1233),(5068,'Lang Son','09',1233),(5069,'Lao Cai','02',1233),(5070,'Long An','41',1233),(5071,'Nam Dinh','67',1233),(5072,'Nghe An','22',1233),(5073,'Ninh Binh','18',1233),(5074,'Ninh Thuan','36',1233),(5075,'Phu Tho','68',1233),(5076,'Phu Yen','32',1233),(5077,'Quang Binh','24',1233),(5078,'Quang Nam','27',1233),(5079,'Quang Ngai','29',1233),(5080,'Quang Ninh','13',1233),(5081,'Quang Tri','25',1233),(5082,'Soc Trang','52',1233),(5083,'Son La','05',1233),(5084,'Tay Ninh','37',1233),(5085,'Thai Binh','20',1233),(5086,'Thai Nguyen','69',1233),(5087,'Thanh Hoa','21',1233),(5088,'Thua Thien-Hue','26',1233),(5089,'Tien Giang','46',1233),(5090,'Tra Vinh','51',1233),(5091,'Tuyen Quang','07',1233),(5092,'Vinh Long','49',1233),(5093,'Vinh Phuc','70',1233),(5094,'Yen Bai','06',1233),(5095,'Malampa','MAP',1231),(5096,'Penama','PAM',1231),(5097,'Sanma','SAM',1231),(5098,'Shefa','SEE',1231),(5099,'Tafea','TAE',1231),(5100,'Torba','TOB',1231),(5101,'A\'ana','AA',1185),(5102,'Aiga-i-le-Tai','AL',1185),(5103,'Atua','AT',1185),(5104,'Fa\'aaaleleaga','FA',1185),(5105,'Gaga\'emauga','GE',1185),(5106,'Gagaifomauga','GI',1185),(5107,'Palauli','PA',1185),(5108,'Satupa\'itea','SA',1185),(5109,'Tuamasaga','TU',1185),(5110,'Va\'a-o-Fonoti','VF',1185),(5111,'Vaisigano','VS',1185),(5112,'Crna Gora','CG',1243),(5113,'Srbija','SR',1242),(5114,'Kosovo-Metohija','KM',1242),(5115,'Vojvodina','VO',1242),(5116,'Abyan','AB',1237),(5117,'Adan','AD',1237),(5118,'Ad Dali','DA',1237),(5119,'Al Bayda\'','BA',1237),(5120,'Al Hudaydah','MU',1237),(5121,'Al Mahrah','MR',1237),(5122,'Al Mahwit','MW',1237),(5123,'Amran','AM',1237),(5124,'Dhamar','DH',1237),(5125,'Hadramawt','HD',1237),(5126,'Hajjah','HJ',1237),(5127,'Ibb','IB',1237),(5128,'Lahij','LA',1237),(5129,'Ma\'rib','MA',1237),(5130,'Sa\'dah','SD',1237),(5131,'San\'a\'','SN',1237),(5132,'Shabwah','SH',1237),(5133,'Ta\'izz','TA',1237),(5134,'Eastern Cape','EC',1196),(5135,'Free State','FS',1196),(5136,'Gauteng','GT',1196),(5137,'Kwazulu-Natal','NL',1196),(5138,'Mpumalanga','MP',1196),(5139,'Northern Cape','NC',1196),(5140,'Limpopo','NP',1196),(5141,'Western Cape','WC',1196),(5142,'Copperbelt','08',1239),(5143,'Luapula','04',1239),(5144,'Lusaka','09',1239),(5145,'North-Western','06',1239),(5146,'Bulawayo','BU',1240),(5147,'Harare','HA',1240),(5148,'Manicaland','MA',1240),(5149,'Mashonaland Central','MC',1240),(5150,'Mashonaland East','ME',1240),(5151,'Mashonaland West','MW',1240),(5152,'Masvingo','MV',1240),(5153,'Matabeleland North','MN',1240),(5154,'Matabeleland South','MS',1240),(5155,'Midlands','MI',1240),(5156,'South Karelia','SK',1075),(5157,'South Ostrobothnia','SO',1075),(5158,'Etelä-Savo','ES',1075),(5159,'Häme','HH',1075),(5160,'Itä-Uusimaa','IU',1075),(5161,'Kainuu','KA',1075),(5162,'Central Ostrobothnia','CO',1075),(5163,'Central Finland','CF',1075),(5164,'Kymenlaakso','KY',1075),(5165,'Lapland','LA',1075),(5166,'Tampere Region','TR',1075),(5167,'Ostrobothnia','OB',1075),(5168,'North Karelia','NK',1075),(5169,'Northern Ostrobothnia','NO',1075),(5170,'Northern Savo','NS',1075),(5171,'Päijät-Häme','PH',1075),(5172,'Satakunta','SK',1075),(5173,'Uusimaa','UM',1075),(5174,'South-West Finland','SW',1075),(5175,'Åland','AL',1075),(5176,'Limburg','LI',1152),(5177,'Central and Western','CW',1098),(5178,'Eastern','EA',1098),(5179,'Southern','SO',1098),(5180,'Wan Chai','WC',1098),(5181,'Kowloon City','KC',1098),(5182,'Kwun Tong','KU',1098),(5183,'Sham Shui Po','SS',1098),(5184,'Wong Tai Sin','WT',1098),(5185,'Yau Tsim Mong','YT',1098),(5186,'Islands','IS',1098),(5187,'Kwai Tsing','KI',1098),(5188,'North','NO',1098),(5189,'Sai Kung','SK',1098),(5190,'Sha Tin','ST',1098),(5191,'Tai Po','TP',1098),(5192,'Tsuen Wan','TW',1098),(5193,'Tuen Mun','TM',1098),(5194,'Yuen Long','YL',1098),(5195,'Manchester','MR',1108),(5196,'Al Manāmah (Al ‘Āşimah)','13',1016),(5197,'Al Janūbīyah','14',1016),(5199,'Al Wusţá','16',1016),(5200,'Ash Shamālīyah','17',1016),(5201,'Jenin','_A',1165),(5202,'Tubas','_B',1165),(5203,'Tulkarm','_C',1165),(5204,'Nablus','_D',1165),(5205,'Qalqilya','_E',1165),(5206,'Salfit','_F',1165),(5207,'Ramallah and Al-Bireh','_G',1165),(5208,'Jericho','_H',1165),(5209,'Jerusalem','_I',1165),(5210,'Bethlehem','_J',1165),(5211,'Hebron','_K',1165),(5212,'North Gaza','_L',1165),(5213,'Gaza','_M',1165),(5214,'Deir el-Balah','_N',1165),(5215,'Khan Yunis','_O',1165),(5216,'Rafah','_P',1165),(5217,'Brussels','BRU',1020),(5218,'Distrito Federal','DIF',1140),(5219,'Taichung City','TXG',1208),(5220,'Kaohsiung City','KHH',1208),(5221,'Taipei City','TPE',1208),(5222,'Chiayi City','CYI',1208),(5223,'Hsinchu City','HSZ',1208),(5224,'Tainan City','TNN',1208),(9000,'North West','NW',1196),(9986,'Tyne and Wear','TWR',1226),(9988,'Greater Manchester','GTM',1226),(9989,'Co Tyrone','TYR',1226),(9990,'West Yorkshire','WYK',1226),(9991,'South Yorkshire','SYK',1226),(9992,'Merseyside','MSY',1226),(9993,'Berkshire','BRK',1226),(9994,'West Midlands','WMD',1226),(9998,'West Glamorgan','WGM',1226),(9999,'London','LON',1226),(10000,'Carbonia-Iglesias','CI',1107),(10001,'Olbia-Tempio','OT',1107),(10002,'Medio Campidano','VS',1107),(10003,'Ogliastra','OG',1107),(10009,'Jura','39',1076),(10010,'Barletta-Andria-Trani','BT',1107),(10011,'Fermo','FM',1107),(10012,'Monza e Brianza','MB',1107),(10013,'Clwyd','CWD',1226),(10015,'South Glamorgan','SGM',1226),(10016,'Artibonite','AR',1094),(10017,'Centre','CE',1094),(10018,'Nippes','NI',1094),(10019,'Nord','ND',1094),(10020,'La Rioja','F',1010),(10021,'Andorra la Vella','07',1005),(10022,'Canillo','02',1005),(10023,'Encamp','03',1005),(10024,'Escaldes-Engordany','08',1005),(10025,'La Massana','04',1005),(10026,'Ordino','05',1005),(10027,'Sant Julia de Loria','06',1005),(10028,'Abaco Islands','AB',1212),(10029,'Andros Island','AN',1212),(10030,'Berry Islands','BR',1212),(10031,'Eleuthera','EL',1212),(10032,'Grand Bahama','GB',1212),(10033,'Rum Cay','RC',1212),(10034,'San Salvador Island','SS',1212),(10035,'Kongo central','01',1050),(10036,'Kwango','02',1050),(10037,'Kwilu','03',1050),(10038,'Mai-Ndombe','04',1050),(10039,'Kasai','05',1050),(10040,'Lulua','06',1050),(10041,'Lomami','07',1050),(10042,'Sankuru','08',1050),(10043,'Ituri','09',1050),(10044,'Haut-Uele','10',1050),(10045,'Tshopo','11',1050),(10046,'Bas-Uele','12',1050),(10047,'Nord-Ubangi','13',1050),(10048,'Mongala','14',1050),(10049,'Sud-Ubangi','15',1050),(10050,'Tshuapa','16',1050),(10051,'Haut-Lomami','17',1050),(10052,'Lualaba','18',1050),(10053,'Haut-Katanga','19',1050),(10054,'Tanganyika','20',1050),(10055,'Toledo','TO',1198),(10056,'Córdoba','CO',1198),(10057,'Metropolitan Manila','MNL',1170),(10058,'La Paz','LP',1097),(10059,'Yinchuan','YN',1045),(10060,'Shizuishan','SZ',1045),(10061,'Wuzhong','WZ',1045),(10062,'Guyuan','GY',1045),(10063,'Zhongwei','ZW',1045),(10064,'Luxembourg','L',1126),(10065,'Aizkraukles novads','002',1119),(10066,'Jaunjelgavas novads','038',1119),(10067,'Pļaviņu novads','072',1119),(10068,'Kokneses novads','046',1119),(10069,'Neretas novads','065',1119),(10070,'Skrīveru novads','092',1119),(10071,'Alūksnes novads','007',1119),(10072,'Apes novads','009',1119),(10073,'Balvu novads','015',1119),(10074,'Viļakas novads','108',1119),(10075,'Baltinavas novads','014',1119),(10076,'Rugāju novads','082',1119),(10077,'Bauskas novads','016',1119),(10078,'Iecavas novads','034',1119),(10079,'Rundāles novads','083',1119),(10080,'Vecumnieku novads','105',1119),(10081,'Cēsu novads','022',1119),(10082,'Līgatnes novads','055',1119),(10083,'Amatas novads','008',1119),(10084,'Jaunpiebalgas novads','039',1119),(10085,'Priekuļu novads','075',1119),(10086,'Pārgaujas novads','070',1119),(10087,'Raunas novads','076',1119),(10088,'Vecpiebalgas novads','104',1119),(10089,'Daugavpils novads','025',1119),(10090,'Ilūkstes novads','036',1119),(10091,'Dobeles novads','026',1119),(10092,'Auces novads','010',1119),(10093,'Tērvetes novads','098',1119),(10094,'Gulbenes novads','033',1119),(10095,'Jelgavas novads','041',1119),(10096,'Ozolnieku novads','069',1119),(10097,'Jēkabpils novads','042',1119),(10098,'Aknīstes novads','004',1119),(10099,'Viesītes novads','107',1119),(10100,'Krustpils novads','049',1119),(10101,'Salas novads','085',1119),(10102,'Krāslavas novads','047',1119),(10103,'Dagdas novads','024',1119),(10104,'Aglonas novads','001',1119),(10105,'Kuldīgas novads','050',1119),(10106,'Skrundas novads','093',1119),(10107,'Alsungas novads','006',1119),(10108,'Aizputes novads','003',1119),(10109,'Durbes novads','028',1119),(10110,'Grobiņas novads','032',1119),(10111,'Pāvilostas novads','071',1119),(10112,'Priekules novads','074',1119),(10113,'Nīcas novads','066',1119),(10114,'Rucavas novads','081',1119),(10115,'Vaiņodes novads','100',1119),(10116,'Limbažu novads','054',1119),(10117,'Alojas novads','005',1119),(10118,'Salacgrīvas novads','086',1119),(10119,'Ludzas novads','058',1119),(10120,'Kārsavas novads','044',1119),(10121,'Zilupes novads','110',1119),(10122,'Ciblas novads','023',1119),(10123,'Madonas novads','059',1119),(10124,'Cesvaines novads','021',1119),(10125,'Lubānas novads','057',1119),(10126,'Varakļānu novads','102',1119),(10127,'Ērgļu novads','030',1119),(10128,'Ogres novads','067',1119),(10129,'Ikšķiles novads','035',1119),(10130,'Ķeguma novads','051',1119),(10131,'Lielvārdes novads','053',1119),(10132,'Preiļu novads','073',1119),(10133,'Līvānu novads','056',1119),(10134,'Riebiņu novads','078',1119),(10135,'Vārkavas novads','103',1119),(10136,'Rēzeknes novads','077',1119),(10137,'Viļānu novads','109',1119),(10138,'Baldones novads','013',1119),(10139,'Ķekavas novads','052',1119),(10140,'Olaines novads','068',1119),(10141,'Salaspils novads','087',1119),(10142,'Saulkrastu novads','089',1119),(10143,'Siguldas novads','091',1119),(10144,'Inčukalna novads','037',1119),(10145,'Ādažu novads','011',1119),(10146,'Babītes novads','012',1119),(10147,'Carnikavas novads','020',1119),(10148,'Garkalnes novads','031',1119),(10149,'Krimuldas novads','048',1119),(10150,'Mālpils novads','061',1119),(10151,'Mārupes novads','062',1119),(10152,'Ropažu novads','080',1119),(10153,'Sējas novads','090',1119),(10154,'Stopiņu novads','095',1119),(10155,'Saldus novads','088',1119),(10156,'Brocēnu novads','018',1119),(10157,'Talsu novads','097',1119),(10158,'Dundagas novads','027',1119),(10159,'Mērsraga novads','063',1119),(10160,'Rojas novads','079',1119),(10161,'Tukuma novads','099',1119),(10162,'Kandavas novads','043',1119),(10163,'Engures novads','029',1119),(10164,'Jaunpils novads','040',1119),(10165,'Valkas novads','101',1119),(10166,'Smiltenes novads','094',1119),(10167,'Strenču novads','096',1119),(10168,'Kocēnu novads','045',1119),(10169,'Mazsalacas novads','060',1119),(10170,'Rūjienas novads','084',1119),(10171,'Beverīnas novads','017',1119),(10172,'Burtnieku novads','019',1119),(10173,'Naukšēnu novads','064',1119),(10174,'Ventspils novads','106',1119),(10175,'Jēkabpils','JKB',1119),(10176,'Valmiera','VMR',1119),(10177,'Florida','FL',1229),(10178,'Rio Negro','RN',1229),(10179,'San Jose','SJ',1229),(10180,'Plateau','PL',1157),(10181,'Pieria','61',1085),(10182,'Los Rios','LR',1044),(10183,'Arica y Parinacota','AP',1044),(10184,'Amazonas','AMA',1169),(10185,'Kalimantan Tengah','KT',1102),(10186,'Sulawesi Barat','SR',1102),(10187,'Kalimantan Utara','KU',1102),(10188,'Ankaran','86',1193),(10189,'Apače','87',1193),(10190,'Cirkulane','88',1193),(10191,'Gorje','89',1193),(10192,'Kostanjevica na Krki','90',1193),(10193,'Log-Dragomer','91',1193),(10194,'Makole','92',1193),(10195,'Mirna','93',1193),(10196,'Mokronog-Trebelno','94',1193),(10197,'Odranci','95',1193),(10198,'Oplotnica','96',1193),(10199,'Ormož','97',1193),(10200,'Osilnica','98',1193),(10201,'Pesnica','99',1193),(10202,'Piran','100',1193),(10203,'Pivka','101',1193),(10204,'Podčetrtek','102',1193),(10205,'Podlehnik','103',1193),(10206,'Podvelka','104',1193),(10207,'Poljčane','105',1193),(10208,'Polzela','106',1193),(10209,'Postojna','107',1193),(10210,'Prebold','108',1193),(10211,'Preddvor','109',1193),(10212,'Prevalje','110',1193),(10213,'Ptuj','111',1193),(10214,'Puconci','112',1193),(10215,'Rače-Fram','113',1193),(10216,'Radeče','114',1193),(10217,'Radenci','115',1193),(10218,'Radlje ob Dravi','139',1193),(10219,'Radovljica','145',1193),(10220,'Ravne na Koroškem','171',1193),(10221,'Razkrižje','172',1193),(10222,'Rečica ob Savinji','173',1193),(10223,'Renče-Vogrsko','174',1193),(10224,'Ribnica','175',1193),(10225,'Ribnica na Pohorju','176',1193),(10226,'Rogaška Slatina','177',1193),(10227,'Rogašovci','178',1193),(10228,'Rogatec','179',1193),(10229,'Ruše','180',1193),(10230,'Selnica ob Dravi','195',1193),(10231,'Semič','196',1193),(10232,'Šentrupert','197',1193),(10233,'Sevnica','198',1193),(10234,'Sežana','199',1193),(10235,'Slovenj Gradec','200',1193),(10236,'Slovenska Bistrica','201',1193),(10237,'Slovenske Konjice','202',1193),(10238,'Šmarješke Toplice','203',1193),(10239,'Sodražica','204',1193),(10240,'Solčava','205',1193),(10241,'Središče ob Dravi','206',1193),(10242,'Starše','207',1193),(10243,'Straža','208',1193),(10244,'Sveta Trojica v Slovenskih goricah','209',1193),(10245,'Sveti Jurij v Slovenskih goricah','210',1193),(10246,'Sveti Tomaž','211',1193),(10247,'Vodice','212',1193),(10248,'Abkhazia','AB',1081),(10249,'Adjara','AJ',1081),(10250,'Tbilisi','TB',1081),(10251,'Guria','GU',1081),(10252,'Imereti','IM',1081),(10253,'Kakheti','KA',1081),(10254,'Kvemo Kartli','KK',1081),(10255,'Mtskheta-Mtianeti','MM',1081),(10256,'Racha-Lechkhumi and Kvemo Svaneti','RL',1081),(10257,'Samegrelo-Zemo Svaneti','SZ',1081),(10258,'Samtskhe-Javakheti','SJ',1081),(10259,'Shida Kartli','SK',1081),(10260,'Central','C',1074),(10261,'Punjab','PB',1163),(10262,'La Libertad','LI',1066),(10263,'La Paz','PA',1066),(10264,'La Union','UN',1066),(10265,'Littoral','LT',1038),(10266,'Nord-Ouest','NW',1038),(10267,'Telangana','TG',1101),(10268,'Ash Sharqiyah','04',1187),(10269,'Guadeloupe','GP',1076),(10270,'Martinique','MQ',1076),(10271,'Guyane','GF',1076),(10272,'La Réunion','RE',1076),(10273,'Mayotte','YT',1076),(10274,'Baringo','01',1112),(10275,'Bomet','02',1112),(10276,'Bungoma','03',1112),(10277,'Busia','04',1112),(10278,'Elgeyo/Marakwet','05',1112),(10279,'Embu','06',1112),(10280,'Garissa','07',1112),(10281,'Homa Bay','08',1112),(10282,'Isiolo','09',1112),(10283,'Kajiado','10',1112),(10284,'Kakamega','11',1112),(10285,'Kericho','12',1112),(10286,'Kiambu','13',1112),(10287,'Kilifi','14',1112),(10288,'Kirinyaga','15',1112),(10289,'Kisii','16',1112),(10290,'Kisumu','17',1112),(10291,'Kitui','18',1112),(10292,'Kwale','19',1112),(10293,'Laikipia','20',1112),(10294,'Lamu','21',1112),(10295,'Machakos','22',1112),(10296,'Makueni','23',1112),(10297,'Mandera','24',1112),(10298,'Marsabit','25',1112),(10299,'Meru','26',1112),(10300,'Migori','27',1112),(10301,'Mombasa','28',1112),(10302,'Murang\'a','29',1112),(10303,'Nairobi City','30',1112),(10304,'Nakuru','31',1112),(10305,'Nandi','32',1112),(10306,'Narok','33',1112),(10307,'Nyamira','34',1112),(10308,'Nyandarua','35',1112),(10309,'Nyeri','36',1112),(10310,'Samburu','37',1112),(10311,'Siaya','38',1112),(10312,'Taita/Taveta','39',1112),(10313,'Tana River','40',1112),(10314,'Tharaka-Nithi','41',1112),(10315,'Trans Nzoia','42',1112),(10316,'Turkana','43',1112),(10317,'Uasin Gishu','44',1112),(10318,'Vihiga','45',1112),(10319,'Wajir','46',1112),(10320,'West Pokot','47',1112),(10321,'Chandigarh','CH',1101),(10322,'Central','CP',1083),(10323,'Eastern','EP',1083),(10324,'Northern','NP',1083),(10325,'Western','WP',1083),(10326,'Saint Kitts','K',1181),(10327,'Nevis','N',1181),(10328,'Eastern','E',1190),(10329,'Northern','N',1190),(10330,'Southern','S',1190),(10331,'Dushanbe','DU',1209),(10332,'Nohiyahoi Tobei Jumhurí','RA',1209),(10333,'Wallis-et-Futuna','WF',1076),(10334,'Nouvelle-Calédonie','NC',1076),(10335,'Haute-Marne','52',1076),(10336,'Saint George','03',1009),(10337,'Saint John','04',1009),(10338,'Saint Mary','05',1009),(10339,'Saint Paul','06',1009),(10340,'Saint Peter','07',1009),(10341,'Saint Philip','08',1009),(10342,'Barbuda','10',1009),(10343,'Redonda','11',1009),(10344,'Christ Church','01',1018),(10345,'Saint Andrew','02',1018),(10346,'Saint George','03',1018),(10347,'Saint James','04',1018),(10348,'Saint John','05',1018),(10349,'Saint Joseph','06',1018),(10350,'Saint Lucy','07',1018),(10351,'Saint Michael','08',1018),(10352,'Saint Peter','09',1018),(10353,'Saint Philip','10',1018),(10354,'Saint Thomas','11',1018),(10355,'Estuaire','01',1080),(10356,'Haut-Ogooué','02',1080),(10357,'Moyen-Ogooué','03',1080),(10358,'Ngounié','04',1080),(10359,'Nyanga','05',1080),(10360,'Ogooué-Ivindo','06',1080),(10361,'Ogooué-Lolo','07',1080),(10362,'Ogooué-Maritime','08',1080),(10363,'Woleu-Ntem','09',1080),(10364,'Monmouthshire','MON',1226),(10365,'Antrim and Newtownabbey','ANN',1226),(10366,'Ards and North Down','AND',1226),(10367,'Armagh City, Banbridge and Craigavon','ABC',1226),(10368,'Belfast','BFS',1226),(10369,'Causeway Coast and Glens','CCG',1226),(10370,'Derry City and Strabane','DRS',1226),(10371,'Fermanagh and Omagh','FMO',1226),(10372,'Lisburn and Castlereagh','LBC',1226),(10373,'Mid and East Antrim','MEA',1226),(10374,'Mid Ulster','MUL',1226),(10375,'Newry, Mourne and Down','NMD',1226),(10376,'Bridgend','BGE',1226),(10377,'Caerphilly','CAY',1226),(10378,'Cardiff','CRF',1226),(10379,'Carmarthenshire','CRF',1226),(10380,'Ceredigion','CGN',1226),(10381,'Conwy','CWY',1226),(10382,'Denbighshire','DEN',1226),(10383,'Flintshire','FLN',1226),(10384,'Isle of Anglesey','AGY',1226),(10385,'Merthyr Tydfil','MTY',1226),(10386,'Neath Port Talbot','NTL',1226),(10387,'Newport','NWP',1226),(10388,'Pembrokeshire','PEM',1226),(10389,'Rhondda, Cynon, Taff','RCT',1226),(10390,'Swansea','SWA',1226),(10391,'Torfaen','TOF',1226),(10392,'Wrexham','WRX',1226),(10393,'Sejong','50',1115);
+INSERT INTO `civicrm_state_province` (`id`, `name`, `abbreviation`, `country_id`) VALUES (1000,'Alabama','AL',1228),(1001,'Alaska','AK',1228),(1002,'Arizona','AZ',1228),(1003,'Arkansas','AR',1228),(1004,'California','CA',1228),(1005,'Colorado','CO',1228),(1006,'Connecticut','CT',1228),(1007,'Delaware','DE',1228),(1008,'Florida','FL',1228),(1009,'Georgia','GA',1228),(1010,'Hawaii','HI',1228),(1011,'Idaho','ID',1228),(1012,'Illinois','IL',1228),(1013,'Indiana','IN',1228),(1014,'Iowa','IA',1228),(1015,'Kansas','KS',1228),(1016,'Kentucky','KY',1228),(1017,'Louisiana','LA',1228),(1018,'Maine','ME',1228),(1019,'Maryland','MD',1228),(1020,'Massachusetts','MA',1228),(1021,'Michigan','MI',1228),(1022,'Minnesota','MN',1228),(1023,'Mississippi','MS',1228),(1024,'Missouri','MO',1228),(1025,'Montana','MT',1228),(1026,'Nebraska','NE',1228),(1027,'Nevada','NV',1228),(1028,'New Hampshire','NH',1228),(1029,'New Jersey','NJ',1228),(1030,'New Mexico','NM',1228),(1031,'New York','NY',1228),(1032,'North Carolina','NC',1228),(1033,'North Dakota','ND',1228),(1034,'Ohio','OH',1228),(1035,'Oklahoma','OK',1228),(1036,'Oregon','OR',1228),(1037,'Pennsylvania','PA',1228),(1038,'Rhode Island','RI',1228),(1039,'South Carolina','SC',1228),(1040,'South Dakota','SD',1228),(1041,'Tennessee','TN',1228),(1042,'Texas','TX',1228),(1043,'Utah','UT',1228),(1044,'Vermont','VT',1228),(1045,'Virginia','VA',1228),(1046,'Washington','WA',1228),(1047,'West Virginia','WV',1228),(1048,'Wisconsin','WI',1228),(1049,'Wyoming','WY',1228),(1050,'District of Columbia','DC',1228),(1052,'American Samoa','AS',1228),(1053,'Guam','GU',1228),(1055,'Northern Mariana Islands','MP',1228),(1056,'Puerto Rico','PR',1228),(1057,'Virgin Islands','VI',1228),(1058,'United States Minor Outlying Islands','UM',1228),(1059,'Armed Forces Europe','AE',1228),(1060,'Armed Forces Americas','AA',1228),(1061,'Armed Forces Pacific','AP',1228),(1100,'Alberta','AB',1039),(1101,'British Columbia','BC',1039),(1102,'Manitoba','MB',1039),(1103,'New Brunswick','NB',1039),(1104,'Newfoundland and Labrador','NL',1039),(1105,'Northwest Territories','NT',1039),(1106,'Nova Scotia','NS',1039),(1107,'Nunavut','NU',1039),(1108,'Ontario','ON',1039),(1109,'Prince Edward Island','PE',1039),(1110,'Quebec','QC',1039),(1111,'Saskatchewan','SK',1039),(1112,'Yukon Territory','YT',1039),(1200,'Maharashtra','MM',1101),(1201,'Karnataka','KA',1101),(1202,'Andhra Pradesh','AP',1101),(1203,'Arunachal Pradesh','AR',1101),(1204,'Assam','AS',1101),(1205,'Bihar','BR',1101),(1206,'Chhattisgarh','CH',1101),(1207,'Goa','GA',1101),(1208,'Gujarat','GJ',1101),(1209,'Haryana','HR',1101),(1210,'Himachal Pradesh','HP',1101),(1211,'Jammu and Kashmir','JK',1101),(1212,'Jharkhand','JH',1101),(1213,'Kerala','KL',1101),(1214,'Madhya Pradesh','MP',1101),(1215,'Manipur','MN',1101),(1216,'Meghalaya','ML',1101),(1217,'Mizoram','MZ',1101),(1218,'Nagaland','NL',1101),(1219,'Orissa','OR',1101),(1220,'Punjab','PB',1101),(1221,'Rajasthan','RJ',1101),(1222,'Sikkim','SK',1101),(1223,'Tamil Nadu','TN',1101),(1224,'Tripura','TR',1101),(1225,'Uttarakhand','UT',1101),(1226,'Uttar Pradesh','UP',1101),(1227,'West Bengal','WB',1101),(1228,'Andaman and Nicobar Islands','AN',1101),(1229,'Dadra and Nagar Haveli','DN',1101),(1230,'Daman and Diu','DD',1101),(1231,'Delhi','DL',1101),(1232,'Lakshadweep','LD',1101),(1233,'Pondicherry','PY',1101),(1300,'mazowieckie','MZ',1172),(1301,'pomorskie','PM',1172),(1302,'dolnośląskie','DS',1172),(1303,'kujawsko-pomorskie','KP',1172),(1304,'lubelskie','LU',1172),(1305,'lubuskie','LB',1172),(1306,'łódzkie','LD',1172),(1307,'małopolskie','MA',1172),(1308,'opolskie','OP',1172),(1309,'podkarpackie','PK',1172),(1310,'podlaskie','PD',1172),(1311,'śląskie','SL',1172),(1312,'świętokrzyskie','SK',1172),(1313,'warmińsko-mazurskie','WN',1172),(1314,'wielkopolskie','WP',1172),(1315,'zachodniopomorskie','ZP',1172),(1500,'Abu Zaby','AZ',1225),(1501,'\'Ajman','AJ',1225),(1502,'Al Fujayrah','FU',1225),(1503,'Ash Shariqah','SH',1225),(1504,'Dubayy','DU',1225),(1505,'Ra\'s al Khaymah','RK',1225),(1506,'Dac Lac','33',1233),(1507,'Umm al Qaywayn','UQ',1225),(1508,'Badakhshan','BDS',1001),(1509,'Badghis','BDG',1001),(1510,'Baghlan','BGL',1001),(1511,'Balkh','BAL',1001),(1512,'Bamian','BAM',1001),(1513,'Farah','FRA',1001),(1514,'Faryab','FYB',1001),(1515,'Ghazni','GHA',1001),(1516,'Ghowr','GHO',1001),(1517,'Helmand','HEL',1001),(1518,'Herat','HER',1001),(1519,'Jowzjan','JOW',1001),(1520,'Kabul','KAB',1001),(1521,'Kandahar','KAN',1001),(1522,'Kapisa','KAP',1001),(1523,'Khowst','KHO',1001),(1524,'Konar','KNR',1001),(1525,'Kondoz','KDZ',1001),(1526,'Laghman','LAG',1001),(1527,'Lowgar','LOW',1001),(1528,'Nangrahar','NAN',1001),(1529,'Nimruz','NIM',1001),(1530,'Nurestan','NUR',1001),(1531,'Oruzgan','ORU',1001),(1532,'Paktia','PIA',1001),(1533,'Paktika','PKA',1001),(1534,'Parwan','PAR',1001),(1535,'Samangan','SAM',1001),(1536,'Sar-e Pol','SAR',1001),(1537,'Takhar','TAK',1001),(1538,'Wardak','WAR',1001),(1539,'Zabol','ZAB',1001),(1540,'Berat','BR',1002),(1541,'Bulqizë','BU',1002),(1542,'Delvinë','DL',1002),(1543,'Devoll','DV',1002),(1544,'Dibër','DI',1002),(1545,'Durrës','DR',1002),(1546,'Elbasan','EL',1002),(1547,'Fier','FR',1002),(1548,'Gramsh','GR',1002),(1549,'Gjirokastër','GJ',1002),(1550,'Has','HA',1002),(1551,'Kavajë','KA',1002),(1552,'Kolonjë','ER',1002),(1553,'Korçë','KO',1002),(1554,'Krujë','KR',1002),(1555,'Kuçovë','KC',1002),(1556,'Kukës','KU',1002),(1557,'Kurbin','KB',1002),(1558,'Lezhë','LE',1002),(1559,'Librazhd','LB',1002),(1560,'Lushnjë','LU',1002),(1561,'Malësi e Madhe','MM',1002),(1562,'Mallakastër','MK',1002),(1563,'Mat','MT',1002),(1564,'Mirditë','MR',1002),(1565,'Peqin','PQ',1002),(1566,'Përmet','PR',1002),(1567,'Pogradec','PG',1002),(1568,'Pukë','PU',1002),(1569,'Sarandë','SR',1002),(1570,'Skrapar','SK',1002),(1571,'Shkodër','SH',1002),(1572,'Tepelenë','TE',1002),(1573,'Tiranë','TR',1002),(1574,'Tropojë','TP',1002),(1575,'Vlorë','VL',1002),(1576,'Erevan','ER',1011),(1577,'Aragacotn','AG',1011),(1578,'Ararat','AR',1011),(1579,'Armavir','AV',1011),(1580,'Gegarkunik\'','GR',1011),(1581,'Kotayk\'','KT',1011),(1582,'Lory','LO',1011),(1583,'Sirak','SH',1011),(1584,'Syunik\'','SU',1011),(1585,'Tavus','TV',1011),(1586,'Vayoc Jor','VD',1011),(1587,'Bengo','BGO',1006),(1588,'Benguela','BGU',1006),(1589,'Bie','BIE',1006),(1590,'Cabinda','CAB',1006),(1591,'Cuando-Cubango','CCU',1006),(1592,'Cuanza Norte','CNO',1006),(1593,'Cuanza Sul','CUS',1006),(1594,'Cunene','CNN',1006),(1595,'Huambo','HUA',1006),(1596,'Huila','HUI',1006),(1597,'Luanda','LUA',1006),(1598,'Lunda Norte','LNO',1006),(1599,'Lunda Sul','LSU',1006),(1600,'Malange','MAL',1006),(1601,'Moxico','MOX',1006),(1602,'Namibe','NAM',1006),(1603,'Uige','UIG',1006),(1604,'Zaire','ZAI',1006),(1605,'Capital federal','C',1010),(1606,'Buenos Aires','B',1010),(1607,'Catamarca','K',1010),(1608,'Cordoba','X',1010),(1609,'Corrientes','W',1010),(1610,'Chaco','H',1010),(1611,'Chubut','U',1010),(1612,'Entre Rios','E',1010),(1613,'Formosa','P',1010),(1614,'Jujuy','Y',1010),(1615,'La Pampa','L',1010),(1616,'Mendoza','M',1010),(1617,'Misiones','N',1010),(1618,'Neuquen','Q',1010),(1619,'Rio Negro','R',1010),(1620,'Salta','A',1010),(1621,'San Juan','J',1010),(1622,'San Luis','D',1010),(1623,'Santa Cruz','Z',1010),(1624,'Santa Fe','S',1010),(1625,'Santiago del Estero','G',1010),(1626,'Tierra del Fuego','V',1010),(1627,'Tucuman','T',1010),(1628,'Burgenland','1',1014),(1629,'Kärnten','2',1014),(1630,'Niederösterreich','3',1014),(1631,'Oberösterreich','4',1014),(1632,'Salzburg','5',1014),(1633,'Steiermark','6',1014),(1634,'Tirol','7',1014),(1635,'Vorarlberg','8',1014),(1636,'Wien','9',1014),(1637,'Australian Antarctic Territory','AAT',1008),(1638,'Australian Capital Territory','ACT',1013),(1639,'Northern Territory','NT',1013),(1640,'New South Wales','NSW',1013),(1641,'Queensland','QLD',1013),(1642,'South Australia','SA',1013),(1643,'Tasmania','TAS',1013),(1644,'Victoria','VIC',1013),(1645,'Western Australia','WA',1013),(1646,'Naxcivan','NX',1015),(1647,'Ali Bayramli','AB',1015),(1648,'Baki','BA',1015),(1649,'Ganca','GA',1015),(1650,'Lankaran','LA',1015),(1651,'Mingacevir','MI',1015),(1652,'Naftalan','NA',1015),(1653,'Saki','SA',1015),(1654,'Sumqayit','SM',1015),(1655,'Susa','SS',1015),(1656,'Xankandi','XA',1015),(1657,'Yevlax','YE',1015),(1658,'Abseron','ABS',1015),(1659,'Agcabadi','AGC',1015),(1660,'Agdam','AGM',1015),(1661,'Agdas','AGS',1015),(1662,'Agstafa','AGA',1015),(1663,'Agsu','AGU',1015),(1664,'Astara','AST',1015),(1665,'Babak','BAB',1015),(1666,'Balakan','BAL',1015),(1667,'Barda','BAR',1015),(1668,'Beylagan','BEY',1015),(1669,'Bilasuvar','BIL',1015),(1670,'Cabrayll','CAB',1015),(1671,'Calilabad','CAL',1015),(1672,'Culfa','CUL',1015),(1673,'Daskasan','DAS',1015),(1674,'Davaci','DAV',1015),(1675,'Fuzuli','FUZ',1015),(1676,'Gadabay','GAD',1015),(1677,'Goranboy','GOR',1015),(1678,'Goycay','GOY',1015),(1679,'Haciqabul','HAC',1015),(1680,'Imisli','IMI',1015),(1681,'Ismayilli','ISM',1015),(1682,'Kalbacar','KAL',1015),(1683,'Kurdamir','KUR',1015),(1684,'Lacin','LAC',1015),(1685,'Lerik','LER',1015),(1686,'Masalli','MAS',1015),(1687,'Neftcala','NEF',1015),(1688,'Oguz','OGU',1015),(1689,'Ordubad','ORD',1015),(1690,'Qabala','QAB',1015),(1691,'Qax','QAX',1015),(1692,'Qazax','QAZ',1015),(1693,'Qobustan','QOB',1015),(1694,'Quba','QBA',1015),(1695,'Qubadli','QBI',1015),(1696,'Qusar','QUS',1015),(1697,'Saatli','SAT',1015),(1698,'Sabirabad','SAB',1015),(1699,'Sadarak','SAD',1015),(1700,'Sahbuz','SAH',1015),(1701,'Salyan','SAL',1015),(1702,'Samaxi','SMI',1015),(1703,'Samkir','SKR',1015),(1704,'Samux','SMX',1015),(1705,'Sarur','SAR',1015),(1706,'Siyazan','SIY',1015),(1707,'Tartar','TAR',1015),(1708,'Tovuz','TOV',1015),(1709,'Ucar','UCA',1015),(1710,'Xacmaz','XAC',1015),(1711,'Xanlar','XAN',1015),(1712,'Xizi','XIZ',1015),(1713,'Xocali','XCI',1015),(1714,'Xocavand','XVD',1015),(1715,'Yardimli','YAR',1015),(1716,'Zangilan','ZAN',1015),(1717,'Zaqatala','ZAQ',1015),(1718,'Zardab','ZAR',1015),(1719,'Federacija Bosna i Hercegovina','BIH',1026),(1720,'Republika Srpska','SRP',1026),(1721,'Bagerhat zila','05',1017),(1722,'Bandarban zila','01',1017),(1723,'Barguna zila','02',1017),(1724,'Barisal zila','06',1017),(1725,'Bhola zila','07',1017),(1726,'Bogra zila','03',1017),(1727,'Brahmanbaria zila','04',1017),(1728,'Chandpur zila','09',1017),(1729,'Chittagong zila','10',1017),(1730,'Chuadanga zila','12',1017),(1731,'Comilla zila','08',1017),(1732,'Cox\'s Bazar zila','11',1017),(1733,'Dhaka zila','13',1017),(1734,'Dinajpur zila','14',1017),(1735,'Faridpur zila','15',1017),(1736,'Feni zila','16',1017),(1737,'Gaibandha zila','19',1017),(1738,'Gazipur zila','18',1017),(1739,'Gopalganj zila','17',1017),(1740,'Habiganj zila','20',1017),(1741,'Jaipurhat zila','24',1017),(1742,'Jamalpur zila','21',1017),(1743,'Jessore zila','22',1017),(1744,'Jhalakati zila','25',1017),(1745,'Jhenaidah zila','23',1017),(1746,'Khagrachari zila','29',1017),(1747,'Khulna zila','27',1017),(1748,'Kishorganj zila','26',1017),(1749,'Kurigram zila','28',1017),(1750,'Kushtia zila','30',1017),(1751,'Lakshmipur zila','31',1017),(1752,'Lalmonirhat zila','32',1017),(1753,'Madaripur zila','36',1017),(1754,'Magura zila','37',1017),(1755,'Manikganj zila','33',1017),(1756,'Meherpur zila','39',1017),(1757,'Moulvibazar zila','38',1017),(1758,'Munshiganj zila','35',1017),(1759,'Mymensingh zila','34',1017),(1760,'Naogaon zila','48',1017),(1761,'Narail zila','43',1017),(1762,'Narayanganj zila','40',1017),(1763,'Narsingdi zila','42',1017),(1764,'Natore zila','44',1017),(1765,'Nawabganj zila','45',1017),(1766,'Netrakona zila','41',1017),(1767,'Nilphamari zila','46',1017),(1768,'Noakhali zila','47',1017),(1769,'Pabna zila','49',1017),(1770,'Panchagarh zila','52',1017),(1771,'Patuakhali zila','51',1017),(1772,'Pirojpur zila','50',1017),(1773,'Rajbari zila','53',1017),(1774,'Rajshahi zila','54',1017),(1775,'Rangamati zila','56',1017),(1776,'Rangpur zila','55',1017),(1777,'Satkhira zila','58',1017),(1778,'Shariatpur zila','62',1017),(1779,'Sherpur zila','57',1017),(1780,'Sirajganj zila','59',1017),(1781,'Sunamganj zila','61',1017),(1782,'Sylhet zila','60',1017),(1783,'Tangail zila','63',1017),(1784,'Thakurgaon zila','64',1017),(1785,'Antwerpen','VAN',1020),(1786,'Brabant Wallon','WBR',1020),(1787,'Hainaut','WHT',1020),(1788,'Liege','WLG',1020),(1789,'Limburg','VLI',1020),(1790,'Luxembourg','WLX',1020),(1791,'Namur','WNA',1020),(1792,'Oost-Vlaanderen','VOV',1020),(1793,'Vlaams-Brabant','VBR',1020),(1794,'West-Vlaanderen','VWV',1020),(1795,'Bale','BAL',1034),(1796,'Bam','BAM',1034),(1797,'Banwa','BAN',1034),(1798,'Bazega','BAZ',1034),(1799,'Bougouriba','BGR',1034),(1800,'Boulgou','BLG',1034),(1801,'Boulkiemde','BLK',1034),(1802,'Comoe','COM',1034),(1803,'Ganzourgou','GAN',1034),(1804,'Gnagna','GNA',1034),(1805,'Gourma','GOU',1034),(1806,'Houet','HOU',1034),(1807,'Ioba','IOB',1034),(1808,'Kadiogo','KAD',1034),(1809,'Kenedougou','KEN',1034),(1810,'Komondjari','KMD',1034),(1811,'Kompienga','KMP',1034),(1812,'Kossi','KOS',1034),(1813,'Koulpulogo','KOP',1034),(1814,'Kouritenga','KOT',1034),(1815,'Kourweogo','KOW',1034),(1816,'Leraba','LER',1034),(1817,'Loroum','LOR',1034),(1818,'Mouhoun','MOU',1034),(1819,'Nahouri','NAO',1034),(1820,'Namentenga','NAM',1034),(1821,'Nayala','NAY',1034),(1822,'Noumbiel','NOU',1034),(1823,'Oubritenga','OUB',1034),(1824,'Oudalan','OUD',1034),(1825,'Passore','PAS',1034),(1826,'Poni','PON',1034),(1827,'Sanguie','SNG',1034),(1828,'Sanmatenga','SMT',1034),(1829,'Seno','SEN',1034),(1830,'Siasili','SIS',1034),(1831,'Soum','SOM',1034),(1832,'Sourou','SOR',1034),(1833,'Tapoa','TAP',1034),(1834,'Tui','TUI',1034),(1835,'Yagha','YAG',1034),(1836,'Yatenga','YAT',1034),(1837,'Ziro','ZIR',1034),(1838,'Zondoma','ZON',1034),(1839,'Zoundweogo','ZOU',1034),(1840,'Blagoevgrad','01',1033),(1841,'Burgas','02',1033),(1842,'Dobrich','08',1033),(1843,'Gabrovo','07',1033),(1844,'Haskovo','26',1033),(1845,'Yambol','28',1033),(1846,'Kardzhali','09',1033),(1847,'Kyustendil','10',1033),(1848,'Lovech','11',1033),(1849,'Montana','12',1033),(1850,'Pazardzhik','13',1033),(1851,'Pernik','14',1033),(1852,'Pleven','15',1033),(1853,'Plovdiv','16',1033),(1854,'Razgrad','17',1033),(1855,'Ruse','18',1033),(1856,'Silistra','19',1033),(1857,'Sliven','20',1033),(1858,'Smolyan','21',1033),(1859,'Sofia','23',1033),(1860,'Stara Zagora','24',1033),(1861,'Shumen','27',1033),(1862,'Targovishte','25',1033),(1863,'Varna','03',1033),(1864,'Veliko Tarnovo','04',1033),(1865,'Vidin','05',1033),(1866,'Vratsa','06',1033),(1867,'Al Hadd','01',1016),(1868,'Al Manamah','03',1016),(1869,'Al Mintaqah al Gharbiyah','10',1016),(1870,'Al Mintagah al Wusta','07',1016),(1871,'Al Mintaqah ash Shamaliyah','05',1016),(1872,'Al Muharraq','02',1016),(1873,'Ar Rifa','09',1016),(1874,'Jidd Hafs','04',1016),(1875,'Madluat Jamad','12',1016),(1876,'Madluat Isa','08',1016),(1877,'Mintaqat Juzur tawar','11',1016),(1878,'Sitrah','06',1016),(1879,'Bubanza','BB',1036),(1880,'Bujumbura','BJ',1036),(1881,'Bururi','BR',1036),(1882,'Cankuzo','CA',1036),(1883,'Cibitoke','CI',1036),(1884,'Gitega','GI',1036),(1885,'Karuzi','KR',1036),(1886,'Kayanza','KY',1036),(1887,'Makamba','MA',1036),(1888,'Muramvya','MU',1036),(1889,'Mwaro','MW',1036),(1890,'Ngozi','NG',1036),(1891,'Rutana','RT',1036),(1892,'Ruyigi','RY',1036),(1893,'Alibori','AL',1022),(1894,'Atakora','AK',1022),(1895,'Atlantique','AQ',1022),(1896,'Borgou','BO',1022),(1897,'Collines','CO',1022),(1898,'Donga','DO',1022),(1899,'Kouffo','KO',1022),(1900,'Littoral','LI',1022),(1901,'Mono','MO',1022),(1902,'Oueme','OU',1022),(1903,'Plateau','PL',1022),(1904,'Zou','ZO',1022),(1905,'Belait','BE',1032),(1906,'Brunei-Muara','BM',1032),(1907,'Temburong','TE',1032),(1908,'Tutong','TU',1032),(1909,'Cochabamba','C',1025),(1910,'Chuquisaca','H',1025),(1911,'El Beni','B',1025),(1912,'La Paz','L',1025),(1913,'Oruro','O',1025),(1914,'Pando','N',1025),(1915,'Potosi','P',1025),(1916,'Tarija','T',1025),(1917,'Acre','AC',1029),(1918,'Alagoas','AL',1029),(1919,'Amazonas','AM',1029),(1920,'Amapa','AP',1029),(1921,'Bahia','BA',1029),(1922,'Ceara','CE',1029),(1923,'Distrito Federal','DF',1029),(1924,'Espirito Santo','ES',1029),(1926,'Goias','GO',1029),(1927,'Maranhao','MA',1029),(1928,'Minas Gerais','MG',1029),(1929,'Mato Grosso do Sul','MS',1029),(1930,'Mato Grosso','MT',1029),(1931,'Para','PA',1029),(1932,'Paraiba','PB',1029),(1933,'Pernambuco','PE',1029),(1934,'Piaui','PI',1029),(1935,'Parana','PR',1029),(1936,'Rio de Janeiro','RJ',1029),(1937,'Rio Grande do Norte','RN',1029),(1938,'Rondonia','RO',1029),(1939,'Roraima','RR',1029),(1940,'Rio Grande do Sul','RS',1029),(1941,'Santa Catarina','SC',1029),(1942,'Sergipe','SE',1029),(1943,'Sao Paulo','SP',1029),(1944,'Tocantins','TO',1029),(1945,'Acklins and Crooked Islands','AC',1212),(1946,'Bimini','BI',1212),(1947,'Cat Island','CI',1212),(1948,'Exuma','EX',1212),(1955,'Inagua','IN',1212),(1957,'Long Island','LI',1212),(1959,'Mayaguana','MG',1212),(1960,'New Providence','NP',1212),(1962,'Ragged Island','RI',1212),(1966,'Bumthang','33',1024),(1967,'Chhukha','12',1024),(1968,'Dagana','22',1024),(1969,'Gasa','GA',1024),(1970,'Ha','13',1024),(1971,'Lhuentse','44',1024),(1972,'Monggar','42',1024),(1973,'Paro','11',1024),(1974,'Pemagatshel','43',1024),(1975,'Punakha','23',1024),(1976,'Samdrup Jongkha','45',1024),(1977,'Samtee','14',1024),(1978,'Sarpang','31',1024),(1979,'Thimphu','15',1024),(1980,'Trashigang','41',1024),(1981,'Trashi Yangtse','TY',1024),(1982,'Trongsa','32',1024),(1983,'Tsirang','21',1024),(1984,'Wangdue Phodrang','24',1024),(1985,'Zhemgang','34',1024),(1986,'Central','CE',1027),(1987,'Ghanzi','GH',1027),(1988,'Kgalagadi','KG',1027),(1989,'Kgatleng','KL',1027),(1990,'Kweneng','KW',1027),(1991,'Ngamiland','NG',1027),(1992,'North-East','NE',1027),(1993,'North-West','NW',1027),(1994,'South-East','SE',1027),(1995,'Southern','SO',1027),(1996,'Brèsckaja voblasc\'','BR',1019),(1997,'Homel\'skaja voblasc\'','HO',1019),(1998,'Hrodzenskaja voblasc\'','HR',1019),(1999,'Mahilëuskaja voblasc\'','MA',1019),(2000,'Minskaja voblasc\'','MI',1019),(2001,'Vicebskaja voblasc\'','VI',1019),(2002,'Belize','BZ',1021),(2003,'Cayo','CY',1021),(2004,'Corozal','CZL',1021),(2005,'Orange Walk','OW',1021),(2006,'Stann Creek','SC',1021),(2007,'Toledo','TOL',1021),(2008,'Kinshasa','KN',1050),(2011,'Equateur','EQ',1050),(2014,'Kasai-Oriental','KE',1050),(2016,'Maniema','MA',1050),(2017,'Nord-Kivu','NK',1050),(2019,'Sud-Kivu','SK',1050),(2020,'Bangui','BGF',1042),(2021,'Bamingui-Bangoran','BB',1042),(2022,'Basse-Kotto','BK',1042),(2023,'Haute-Kotto','HK',1042),(2024,'Haut-Mbomou','HM',1042),(2025,'Kemo','KG',1042),(2026,'Lobaye','LB',1042),(2027,'Mambere-Kadei','HS',1042),(2028,'Mbomou','MB',1042),(2029,'Nana-Grebizi','KB',1042),(2030,'Nana-Mambere','NM',1042),(2031,'Ombella-Mpoko','MP',1042),(2032,'Ouaka','UK',1042),(2033,'Ouham','AC',1042),(2034,'Ouham-Pende','OP',1042),(2035,'Sangha-Mbaere','SE',1042),(2036,'Vakaga','VR',1042),(2037,'Brazzaville','BZV',1051),(2038,'Bouenza','11',1051),(2039,'Cuvette','8',1051),(2040,'Cuvette-Ouest','15',1051),(2041,'Kouilou','5',1051),(2042,'Lekoumou','2',1051),(2043,'Likouala','7',1051),(2044,'Niari','9',1051),(2045,'Plateaux','14',1051),(2046,'Pool','12',1051),(2047,'Sangha','13',1051),(2048,'Aargau','AG',1205),(2049,'Appenzell Innerrhoden','AI',1205),(2050,'Appenzell Ausserrhoden','AR',1205),(2051,'Bern','BE',1205),(2052,'Basel-Landschaft','BL',1205),(2053,'Basel-Stadt','BS',1205),(2054,'Fribourg','FR',1205),(2055,'Geneva','GE',1205),(2056,'Glarus','GL',1205),(2057,'Graubunden','GR',1205),(2058,'Jura','JU',1205),(2059,'Luzern','LU',1205),(2060,'Neuchatel','NE',1205),(2061,'Nidwalden','NW',1205),(2062,'Obwalden','OW',1205),(2063,'Sankt Gallen','SG',1205),(2064,'Schaffhausen','SH',1205),(2065,'Solothurn','SO',1205),(2066,'Schwyz','SZ',1205),(2067,'Thurgau','TG',1205),(2068,'Ticino','TI',1205),(2069,'Uri','UR',1205),(2070,'Vaud','VD',1205),(2071,'Valais','VS',1205),(2072,'Zug','ZG',1205),(2073,'Zurich','ZH',1205),(2074,'18 Montagnes','06',1054),(2075,'Agnebi','16',1054),(2076,'Bas-Sassandra','09',1054),(2077,'Denguele','10',1054),(2078,'Haut-Sassandra','02',1054),(2079,'Lacs','07',1054),(2080,'Lagunes','01',1054),(2081,'Marahoue','12',1054),(2082,'Moyen-Comoe','05',1054),(2083,'Nzi-Comoe','11',1054),(2084,'Savanes','03',1054),(2085,'Sud-Bandama','15',1054),(2086,'Sud-Comoe','13',1054),(2087,'Vallee du Bandama','04',1054),(2088,'Worodouqou','14',1054),(2089,'Zanzan','08',1054),(2090,'Aisen del General Carlos Ibanez del Campo','AI',1044),(2091,'Antofagasta','AN',1044),(2092,'Araucania','AR',1044),(2093,'Atacama','AT',1044),(2094,'Bio-Bio','BI',1044),(2095,'Coquimbo','CO',1044),(2096,'Libertador General Bernardo O\'Higgins','LI',1044),(2097,'Los Lagos','LL',1044),(2098,'Magallanes','MA',1044),(2099,'Maule','ML',1044),(2100,'Santiago Metropolitan','SM',1044),(2101,'Tarapaca','TA',1044),(2102,'Valparaiso','VS',1044),(2103,'Adamaoua','AD',1038),(2104,'Centre','CE',1038),(2105,'East','ES',1038),(2106,'Far North','EN',1038),(2107,'North','NO',1038),(2108,'South','SW',1038),(2109,'South-West','SW',1038),(2110,'West','OU',1038),(2111,'Beijing','11',1045),(2112,'Chongqing','50',1045),(2113,'Shanghai','31',1045),(2114,'Tianjin','12',1045),(2115,'Anhui','34',1045),(2116,'Fujian','35',1045),(2117,'Gansu','62',1045),(2118,'Guangdong','44',1045),(2119,'Guizhou','52',1045),(2120,'Hainan','46',1045),(2121,'Hebei','13',1045),(2122,'Heilongjiang','23',1045),(2123,'Henan','41',1045),(2124,'Hubei','42',1045),(2125,'Hunan','43',1045),(2126,'Jiangsu','32',1045),(2127,'Jiangxi','36',1045),(2128,'Jilin','22',1045),(2129,'Liaoning','21',1045),(2130,'Qinghai','63',1045),(2131,'Shaanxi','61',1045),(2132,'Shandong','37',1045),(2133,'Shanxi','14',1045),(2134,'Sichuan','51',1045),(2135,'Taiwan','71',1045),(2136,'Yunnan','53',1045),(2137,'Zhejiang','33',1045),(2138,'Guangxi','45',1045),(2139,'Neia Mongol (mn)','15',1045),(2140,'Xinjiang','65',1045),(2141,'Xizang','54',1045),(2142,'Hong Kong','91',1045),(2143,'Macau','92',1045),(2144,'Distrito Capital de Bogotá','DC',1048),(2145,'Amazonea','AMA',1048),(2146,'Antioquia','ANT',1048),(2147,'Arauca','ARA',1048),(2148,'Atlántico','ATL',1048),(2149,'Bolívar','BOL',1048),(2150,'Boyacá','BOY',1048),(2151,'Caldea','CAL',1048),(2152,'Caquetá','CAQ',1048),(2153,'Casanare','CAS',1048),(2154,'Cauca','CAU',1048),(2155,'Cesar','CES',1048),(2156,'Córdoba','COR',1048),(2157,'Cundinamarca','CUN',1048),(2158,'Chocó','CHO',1048),(2159,'Guainía','GUA',1048),(2160,'Guaviare','GUV',1048),(2161,'La Guajira','LAG',1048),(2162,'Magdalena','MAG',1048),(2163,'Meta','MET',1048),(2164,'Nariño','NAR',1048),(2165,'Norte de Santander','NSA',1048),(2166,'Putumayo','PUT',1048),(2167,'Quindio','QUI',1048),(2168,'Risaralda','RIS',1048),(2169,'San Andrés, Providencia y Santa Catalina','SAP',1048),(2170,'Santander','SAN',1048),(2171,'Sucre','SUC',1048),(2172,'Tolima','TOL',1048),(2173,'Valle del Cauca','VAC',1048),(2174,'Vaupés','VAU',1048),(2175,'Vichada','VID',1048),(2176,'Alajuela','A',1053),(2177,'Cartago','C',1053),(2178,'Guanacaste','G',1053),(2179,'Heredia','H',1053),(2180,'Limon','L',1053),(2181,'Puntarenas','P',1053),(2182,'San Jose','SJ',1053),(2183,'Camagey','09',1056),(2184,'Ciego de `vila','08',1056),(2185,'Cienfuegos','06',1056),(2186,'Ciudad de La Habana','03',1056),(2187,'Granma','12',1056),(2188,'Guantanamo','14',1056),(2189,'Holquin','11',1056),(2190,'La Habana','02',1056),(2191,'Las Tunas','10',1056),(2192,'Matanzas','04',1056),(2193,'Pinar del Rio','01',1056),(2194,'Sancti Spiritus','07',1056),(2195,'Santiago de Cuba','13',1056),(2196,'Villa Clara','05',1056),(2197,'Isla de la Juventud','99',1056),(2198,'Pinar del Roo','PR',1056),(2199,'Ciego de Avila','CA',1056),(2200,'Camagoey','CG',1056),(2201,'Holgun','HO',1056),(2202,'Sancti Spritus','SS',1056),(2203,'Municipio Especial Isla de la Juventud','IJ',1056),(2204,'Boa Vista','BV',1040),(2205,'Brava','BR',1040),(2206,'Calheta de Sao Miguel','CS',1040),(2207,'Fogo','FO',1040),(2208,'Maio','MA',1040),(2209,'Mosteiros','MO',1040),(2210,'Paul','PA',1040),(2211,'Porto Novo','PN',1040),(2212,'Praia','PR',1040),(2213,'Ribeira Grande','RG',1040),(2214,'Sal','SL',1040),(2215,'Sao Domingos','SD',1040),(2216,'Sao Filipe','SF',1040),(2217,'Sao Nicolau','SN',1040),(2218,'Sao Vicente','SV',1040),(2219,'Tarrafal','TA',1040),(2220,'Ammochostos Magusa','04',1057),(2221,'Keryneia','06',1057),(2222,'Larnaka','03',1057),(2223,'Lefkosia','01',1057),(2224,'Lemesos','02',1057),(2225,'Pafos','05',1057),(2226,'Jihočeský kraj','JC',1058),(2227,'Jihomoravský kraj','JM',1058),(2228,'Karlovarský kraj','KA',1058),(2229,'Královéhradecký kraj','KR',1058),(2230,'Liberecký kraj','LI',1058),(2231,'Moravskoslezský kraj','MO',1058),(2232,'Olomoucký kraj','OL',1058),(2233,'Pardubický kraj','PA',1058),(2234,'Plzeňský kraj','PL',1058),(2235,'Praha, hlavní město','PR',1058),(2236,'Středočeský kraj','ST',1058),(2237,'Ústecký kraj','US',1058),(2238,'Vysočina','VY',1058),(2239,'Zlínský kraj','ZL',1058),(2240,'Baden-Württemberg','BW',1082),(2241,'Bayern','BY',1082),(2242,'Bremen','HB',1082),(2243,'Hamburg','HH',1082),(2244,'Hessen','HE',1082),(2245,'Niedersachsen','NI',1082),(2246,'Nordrhein-Westfalen','NW',1082),(2247,'Rheinland-Pfalz','RP',1082),(2248,'Saarland','SL',1082),(2249,'Schleswig-Holstein','SH',1082),(2250,'Berlin','BE',1082),(2251,'Brandenburg','BB',1082),(2252,'Mecklenburg-Vorpommern','MV',1082),(2253,'Sachsen','SN',1082),(2254,'Sachsen-Anhalt','ST',1082),(2255,'Thüringen','TH',1082),(2256,'Ali Sabiah','AS',1060),(2257,'Dikhil','DI',1060),(2258,'Djibouti','DJ',1060),(2259,'Obock','OB',1060),(2260,'Tadjoura','TA',1060),(2261,'Frederiksberg','147',1059),(2262,'Copenhagen City','101',1059),(2263,'Copenhagen','015',1059),(2264,'Frederiksborg','020',1059),(2265,'Roskilde','025',1059),(2266,'Vestsjælland','030',1059),(2267,'Storstrøm','035',1059),(2268,'Bornholm','040',1059),(2269,'Fyn','042',1059),(2270,'South Jutland','050',1059),(2271,'Ribe','055',1059),(2272,'Vejle','060',1059),(2273,'Ringkjøbing','065',1059),(2274,'Århus','070',1059),(2275,'Viborg','076',1059),(2276,'North Jutland','080',1059),(2277,'Distrito Nacional (Santo Domingo)','01',1062),(2278,'Azua','02',1062),(2279,'Bahoruco','03',1062),(2280,'Barahona','04',1062),(2281,'Dajabón','05',1062),(2282,'Duarte','06',1062),(2283,'El Seybo [El Seibo]','08',1062),(2284,'Espaillat','09',1062),(2285,'Hato Mayor','30',1062),(2286,'Independencia','10',1062),(2287,'La Altagracia','11',1062),(2288,'La Estrelleta [Elias Pina]','07',1062),(2289,'La Romana','12',1062),(2290,'La Vega','13',1062),(2291,'Maroia Trinidad Sánchez','14',1062),(2292,'Monseñor Nouel','28',1062),(2293,'Monte Cristi','15',1062),(2294,'Monte Plata','29',1062),(2295,'Pedernales','16',1062),(2296,'Peravia','17',1062),(2297,'Puerto Plata','18',1062),(2298,'Salcedo','19',1062),(2299,'Samaná','20',1062),(2300,'San Cristóbal','21',1062),(2301,'San Pedro de Macorís','23',1062),(2302,'Sánchez Ramírez','24',1062),(2303,'Santiago','25',1062),(2304,'Santiago Rodríguez','26',1062),(2305,'Valverde','27',1062),(2306,'Adrar','01',1003),(2307,'Ain Defla','44',1003),(2308,'Ain Tmouchent','46',1003),(2309,'Alger','16',1003),(2310,'Annaba','23',1003),(2311,'Batna','05',1003),(2312,'Bechar','08',1003),(2313,'Bejaia','06',1003),(2314,'Biskra','07',1003),(2315,'Blida','09',1003),(2316,'Bordj Bou Arreridj','34',1003),(2317,'Bouira','10',1003),(2318,'Boumerdes','35',1003),(2319,'Chlef','02',1003),(2320,'Constantine','25',1003),(2321,'Djelfa','17',1003),(2322,'El Bayadh','32',1003),(2323,'El Oued','39',1003),(2324,'El Tarf','36',1003),(2325,'Ghardaia','47',1003),(2326,'Guelma','24',1003),(2327,'Illizi','33',1003),(2328,'Jijel','18',1003),(2329,'Khenchela','40',1003),(2330,'Laghouat','03',1003),(2331,'Mascara','29',1003),(2332,'Medea','26',1003),(2333,'Mila','43',1003),(2334,'Mostaganem','27',1003),(2335,'Msila','28',1003),(2336,'Naama','45',1003),(2337,'Oran','31',1003),(2338,'Ouargla','30',1003),(2339,'Oum el Bouaghi','04',1003),(2340,'Relizane','48',1003),(2341,'Saida','20',1003),(2342,'Setif','19',1003),(2343,'Sidi Bel Abbes','22',1003),(2344,'Skikda','21',1003),(2345,'Souk Ahras','41',1003),(2346,'Tamanghasset','11',1003),(2347,'Tebessa','12',1003),(2348,'Tiaret','14',1003),(2349,'Tindouf','37',1003),(2350,'Tipaza','42',1003),(2351,'Tissemsilt','38',1003),(2352,'Tizi Ouzou','15',1003),(2353,'Tlemcen','13',1003),(2354,'Azuay','A',1064),(2355,'Bolivar','B',1064),(2356,'Canar','F',1064),(2357,'Carchi','C',1064),(2358,'Cotopaxi','X',1064),(2359,'Chimborazo','H',1064),(2360,'El Oro','O',1064),(2361,'Esmeraldas','E',1064),(2362,'Galapagos','W',1064),(2363,'Guayas','G',1064),(2364,'Imbabura','I',1064),(2365,'Loja','L',1064),(2366,'Los Rios','R',1064),(2367,'Manabi','M',1064),(2368,'Morona-Santiago','S',1064),(2369,'Napo','N',1064),(2370,'Orellana','D',1064),(2371,'Pastaza','Y',1064),(2372,'Pichincha','P',1064),(2373,'Sucumbios','U',1064),(2374,'Tungurahua','T',1064),(2375,'Zamora-Chinchipe','Z',1064),(2376,'Harjumaa','37',1069),(2377,'Hiiumaa','39',1069),(2378,'Ida-Virumaa','44',1069),(2379,'Jõgevamaa','49',1069),(2380,'Järvamaa','51',1069),(2381,'Läänemaa','57',1069),(2382,'Lääne-Virumaa','59',1069),(2383,'Põlvamaa','65',1069),(2384,'Pärnumaa','67',1069),(2385,'Raplamaa','70',1069),(2386,'Saaremaa','74',1069),(2387,'Tartumaa','7B',1069),(2388,'Valgamaa','82',1069),(2389,'Viljandimaa','84',1069),(2390,'Võrumaa','86',1069),(2391,'Ad Daqahllyah','DK',1065),(2392,'Al Bahr al Ahmar','BA',1065),(2393,'Al Buhayrah','BH',1065),(2394,'Al Fayym','FYM',1065),(2395,'Al Gharbiyah','GH',1065),(2396,'Al Iskandarlyah','ALX',1065),(2397,'Al Isma illyah','IS',1065),(2398,'Al Jizah','GZ',1065),(2399,'Al Minuflyah','MNF',1065),(2400,'Al Minya','MN',1065),(2401,'Al Qahirah','C',1065),(2402,'Al Qalyublyah','KB',1065),(2403,'Al Wadi al Jadid','WAD',1065),(2404,'Ash Sharqiyah','SHR',1065),(2405,'As Suways','SUZ',1065),(2406,'Aswan','ASN',1065),(2407,'Asyut','AST',1065),(2408,'Bani Suwayf','BNS',1065),(2409,'Bur Sa\'id','PTS',1065),(2410,'Dumyat','DT',1065),(2411,'Janub Sina\'','JS',1065),(2412,'Kafr ash Shaykh','KFS',1065),(2413,'Matruh','MT',1065),(2414,'Qina','KN',1065),(2415,'Shamal Sina\'','SIN',1065),(2416,'Suhaj','SHG',1065),(2417,'Anseba','AN',1068),(2418,'Debub','DU',1068),(2419,'Debubawi Keyih Bahri [Debub-Keih-Bahri]','DK',1068),(2420,'Gash-Barka','GB',1068),(2421,'Maakel [Maekel]','MA',1068),(2422,'Semenawi Keyih Bahri [Semien-Keih-Bahri]','SK',1068),(2423,'Álava','VI',1198),(2424,'Albacete','AB',1198),(2425,'Alicante','A',1198),(2426,'Almería','AL',1198),(2427,'Asturias','O',1198),(2428,'Ávila','AV',1198),(2429,'Badajoz','BA',1198),(2430,'Baleares','PM',1198),(2431,'Barcelona','B',1198),(2432,'Burgos','BU',1198),(2433,'Cáceres','CC',1198),(2434,'Cádiz','CA',1198),(2435,'Cantabria','S',1198),(2436,'Castellón','CS',1198),(2437,'Ciudad Real','CR',1198),(2438,'Cuenca','CU',1198),(2439,'Girona [Gerona]','GE',1198),(2440,'Granada','GR',1198),(2441,'Guadalajara','GU',1198),(2442,'Guipúzcoa','SS',1198),(2443,'Huelva','H',1198),(2444,'Huesca','HU',1198),(2445,'Jaén','J',1198),(2446,'La Coruña','C',1198),(2447,'La Rioja','LO',1198),(2448,'Las Palmas','GC',1198),(2449,'León','LE',1198),(2450,'Lleida [Lérida]','L',1198),(2451,'Lugo','LU',1198),(2452,'Madrid','M',1198),(2453,'Málaga','MA',1198),(2454,'Murcia','MU',1198),(2455,'Navarra','NA',1198),(2456,'Ourense','OR',1198),(2457,'Palencia','P',1198),(2458,'Pontevedra','PO',1198),(2459,'Salamanca','SA',1198),(2460,'Santa Cruz de Tenerife','TF',1198),(2461,'Segovia','SG',1198),(2462,'Sevilla','SE',1198),(2463,'Soria','SO',1198),(2464,'Tarragona','T',1198),(2465,'Teruel','TE',1198),(2466,'Valencia','V',1198),(2467,'Valladolid','VA',1198),(2468,'Vizcaya','BI',1198),(2469,'Zamora','ZA',1198),(2470,'Zaragoza','Z',1198),(2471,'Ceuta','CE',1198),(2472,'Melilla','ML',1198),(2473,'Addis Ababa','AA',1070),(2474,'Dire Dawa','DD',1070),(2475,'Afar','AF',1070),(2476,'Amara','AM',1070),(2477,'Benshangul-Gumaz','BE',1070),(2478,'Gambela Peoples','GA',1070),(2479,'Harari People','HA',1070),(2480,'Oromia','OR',1070),(2481,'Somali','SO',1070),(2482,'Southern Nations, Nationalities and Peoples','SN',1070),(2483,'Tigrai','TI',1070),(2490,'Eastern','E',1074),(2491,'Northern','N',1074),(2492,'Western','W',1074),(2493,'Rotuma','R',1074),(2494,'Chuuk','TRK',1141),(2495,'Kosrae','KSA',1141),(2496,'Pohnpei','PNI',1141),(2497,'Yap','YAP',1141),(2498,'Ain','01',1076),(2499,'Aisne','02',1076),(2500,'Allier','03',1076),(2501,'Alpes-de-Haute-Provence','04',1076),(2502,'Alpes-Maritimes','06',1076),(2503,'Ardèche','07',1076),(2504,'Ardennes','08',1076),(2505,'Ariège','09',1076),(2506,'Aube','10',1076),(2507,'Aude','11',1076),(2508,'Aveyron','12',1076),(2509,'Bas-Rhin','67',1076),(2510,'Bouches-du-Rhône','13',1076),(2511,'Calvados','14',1076),(2512,'Cantal','15',1076),(2513,'Charente','16',1076),(2514,'Charente-Maritime','17',1076),(2515,'Cher','18',1076),(2516,'Corrèze','19',1076),(2517,'Corse-du-Sud','20A',1076),(2518,'Côte-d\'Or','21',1076),(2519,'Côtes-d\'Armor','22',1076),(2520,'Creuse','23',1076),(2521,'Deux-Sèvres','79',1076),(2522,'Dordogne','24',1076),(2523,'Doubs','25',1076),(2524,'Drôme','26',1076),(2525,'Essonne','91',1076),(2526,'Eure','27',1076),(2527,'Eure-et-Loir','28',1076),(2528,'Finistère','29',1076),(2529,'Gard','30',1076),(2530,'Gers','32',1076),(2531,'Gironde','33',1076),(2532,'Haut-Rhin','68',1076),(2533,'Haute-Corse','20B',1076),(2534,'Haute-Garonne','31',1076),(2535,'Haute-Loire','43',1076),(2536,'Haute-Saône','70',1076),(2537,'Haute-Savoie','74',1076),(2538,'Haute-Vienne','87',1076),(2539,'Hautes-Alpes','05',1076),(2540,'Hautes-Pyrénées','65',1076),(2541,'Hauts-de-Seine','92',1076),(2542,'Hérault','34',1076),(2543,'Indre','36',1076),(2544,'Ille-et-Vilaine','35',1076),(2545,'Indre-et-Loire','37',1076),(2546,'Isère','38',1076),(2547,'Landes','40',1076),(2548,'Loir-et-Cher','41',1076),(2549,'Loire','42',1076),(2550,'Loire-Atlantique','44',1076),(2551,'Loiret','45',1076),(2552,'Lot','46',1076),(2553,'Lot-et-Garonne','47',1076),(2554,'Lozère','48',1076),(2555,'Maine-et-Loire','49',1076),(2556,'Manche','50',1076),(2557,'Marne','51',1076),(2558,'Mayenne','53',1076),(2559,'Meurthe-et-Moselle','54',1076),(2560,'Meuse','55',1076),(2561,'Morbihan','56',1076),(2562,'Moselle','57',1076),(2563,'Nièvre','58',1076),(2564,'Nord','59',1076),(2565,'Oise','60',1076),(2566,'Orne','61',1076),(2567,'Paris','75',1076),(2568,'Pas-de-Calais','62',1076),(2569,'Puy-de-Dôme','63',1076),(2570,'Pyrénées-Atlantiques','64',1076),(2571,'Pyrénées-Orientales','66',1076),(2572,'Rhône','69',1076),(2573,'Saône-et-Loire','71',1076),(2574,'Sarthe','72',1076),(2575,'Savoie','73',1076),(2576,'Seine-et-Marne','77',1076),(2577,'Seine-Maritime','76',1076),(2578,'Seine-Saint-Denis','93',1076),(2579,'Somme','80',1076),(2580,'Tarn','81',1076),(2581,'Tarn-et-Garonne','82',1076),(2582,'Val d\'Oise','95',1076),(2583,'Territoire de Belfort','90',1076),(2584,'Val-de-Marne','94',1076),(2585,'Var','83',1076),(2586,'Vaucluse','84',1076),(2587,'Vendée','85',1076),(2588,'Vienne','86',1076),(2589,'Vosges','88',1076),(2590,'Yonne','89',1076),(2591,'Yvelines','78',1076),(2592,'Aberdeen City','ABE',1226),(2593,'Aberdeenshire','ABD',1226),(2594,'Angus','ANS',1226),(2595,'Co Antrim','ANT',1226),(2597,'Argyll and Bute','AGB',1226),(2598,'Co Armagh','ARM',1226),(2606,'Bedfordshire','BDF',1226),(2612,'Blaenau Gwent','BGW',1226),(2620,'Bristol, City of','BST',1226),(2622,'Buckinghamshire','BKM',1226),(2626,'Cambridgeshire','CAM',1226),(2634,'Cheshire','CHS',1226),(2635,'Clackmannanshire','CLK',1226),(2639,'Cornwall','CON',1226),(2643,'Cumbria','CMA',1226),(2647,'Derbyshire','DBY',1226),(2648,'Co Londonderry','DRY',1226),(2649,'Devon','DEV',1226),(2651,'Dorset','DOR',1226),(2652,'Co Down','DOW',1226),(2654,'Dumfries and Galloway','DGY',1226),(2655,'Dundee City','DND',1226),(2657,'County Durham','DUR',1226),(2659,'East Ayrshire','EAY',1226),(2660,'East Dunbartonshire','EDU',1226),(2661,'East Lothian','ELN',1226),(2662,'East Renfrewshire','ERW',1226),(2663,'East Riding of Yorkshire','ERY',1226),(2664,'East Sussex','ESX',1226),(2665,'Edinburgh, City of','EDH',1226),(2666,'Na h-Eileanan Siar','ELS',1226),(2668,'Essex','ESS',1226),(2669,'Falkirk','FAL',1226),(2670,'Co Fermanagh','FER',1226),(2671,'Fife','FIF',1226),(2674,'Glasgow City','GLG',1226),(2675,'Gloucestershire','GLS',1226),(2678,'Gwynedd','GWN',1226),(2682,'Hampshire','HAM',1226),(2687,'Herefordshire','HEF',1226),(2688,'Hertfordshire','HRT',1226),(2689,'Highland','HED',1226),(2692,'Inverclyde','IVC',1226),(2694,'Isle of Wight','IOW',1226),(2699,'Kent','KEN',1226),(2705,'Lancashire','LAN',1226),(2709,'Leicestershire','LEC',1226),(2712,'Lincolnshire','LIN',1226),(2723,'Midlothian','MLN',1226),(2726,'Moray','MRY',1226),(2734,'Norfolk','NFK',1226),(2735,'North Ayrshire','NAY',1226),(2738,'North Lanarkshire','NLK',1226),(2742,'North Yorkshire','NYK',1226),(2743,'Northamptonshire','NTH',1226),(2744,'Northumberland','NBL',1226),(2746,'Nottinghamshire','NTT',1226),(2747,'Oldham','OLD',1226),(2748,'Omagh','OMH',1226),(2749,'Orkney Islands','ORR',1226),(2750,'Oxfordshire','OXF',1226),(2752,'Perth and Kinross','PKN',1226),(2757,'Powys','POW',1226),(2761,'Renfrewshire','RFW',1226),(2766,'Rutland','RUT',1226),(2770,'Scottish Borders','SCB',1226),(2773,'Shetland Islands','ZET',1226),(2774,'Shropshire','SHR',1226),(2777,'Somerset','SOM',1226),(2778,'South Ayrshire','SAY',1226),(2779,'South Gloucestershire','SGC',1226),(2780,'South Lanarkshire','SLK',1226),(2785,'Staffordshire','STS',1226),(2786,'Stirling','STG',1226),(2791,'Suffolk','SFK',1226),(2793,'Surrey','SRY',1226),(2804,'Vale of Glamorgan, The','VGL',1226),(2811,'Warwickshire','WAR',1226),(2813,'West Dunbartonshire','WDU',1226),(2814,'West Lothian','WLN',1226),(2815,'West Sussex','WSX',1226),(2818,'Wiltshire','WIL',1226),(2823,'Worcestershire','WOR',1226),(2826,'Ashanti','AH',1083),(2827,'Brong-Ahafo','BA',1083),(2828,'Greater Accra','AA',1083),(2829,'Upper East','UE',1083),(2830,'Upper West','UW',1083),(2831,'Volta','TV',1083),(2832,'Banjul','B',1213),(2833,'Lower River','L',1213),(2834,'MacCarthy Island','M',1213),(2835,'North Bank','N',1213),(2836,'Upper River','U',1213),(2837,'Beyla','BE',1091),(2838,'Boffa','BF',1091),(2839,'Boke','BK',1091),(2840,'Coyah','CO',1091),(2841,'Dabola','DB',1091),(2842,'Dalaba','DL',1091),(2843,'Dinguiraye','DI',1091),(2844,'Dubreka','DU',1091),(2845,'Faranah','FA',1091),(2846,'Forecariah','FO',1091),(2847,'Fria','FR',1091),(2848,'Gaoual','GA',1091),(2849,'Guekedou','GU',1091),(2850,'Kankan','KA',1091),(2851,'Kerouane','KE',1091),(2852,'Kindia','KD',1091),(2853,'Kissidougou','KS',1091),(2854,'Koubia','KB',1091),(2855,'Koundara','KN',1091),(2856,'Kouroussa','KO',1091),(2857,'Labe','LA',1091),(2858,'Lelouma','LE',1091),(2859,'Lola','LO',1091),(2860,'Macenta','MC',1091),(2861,'Mali','ML',1091),(2862,'Mamou','MM',1091),(2863,'Mandiana','MD',1091),(2864,'Nzerekore','NZ',1091),(2865,'Pita','PI',1091),(2866,'Siguiri','SI',1091),(2867,'Telimele','TE',1091),(2868,'Tougue','TO',1091),(2869,'Yomou','YO',1091),(2870,'Region Continental','C',1067),(2871,'Region Insular','I',1067),(2872,'Annobon','AN',1067),(2873,'Bioko Norte','BN',1067),(2874,'Bioko Sur','BS',1067),(2875,'Centro Sur','CS',1067),(2876,'Kie-Ntem','KN',1067),(2877,'Litoral','LI',1067),(2878,'Wele-Nzas','WN',1067),(2879,'Achaïa','13',1085),(2880,'Aitolia-Akarnania','01',1085),(2881,'Argolis','11',1085),(2882,'Arkadia','12',1085),(2883,'Arta','31',1085),(2884,'Attiki','A1',1085),(2885,'Chalkidiki','64',1085),(2886,'Chania','94',1085),(2887,'Chios','85',1085),(2888,'Dodekanisos','81',1085),(2889,'Drama','52',1085),(2890,'Evros','71',1085),(2891,'Evrytania','05',1085),(2892,'Evvoia','04',1085),(2893,'Florina','63',1085),(2894,'Fokis','07',1085),(2895,'Fthiotis','06',1085),(2896,'Grevena','51',1085),(2897,'Ileia','14',1085),(2898,'Imathia','53',1085),(2899,'Ioannina','33',1085),(2900,'Irakleion','91',1085),(2901,'Karditsa','41',1085),(2902,'Kastoria','56',1085),(2903,'Kavalla','55',1085),(2904,'Kefallinia','23',1085),(2905,'Kerkyra','22',1085),(2906,'Kilkis','57',1085),(2907,'Korinthia','15',1085),(2908,'Kozani','58',1085),(2909,'Kyklades','82',1085),(2910,'Lakonia','16',1085),(2911,'Larisa','42',1085),(2912,'Lasithion','92',1085),(2913,'Lefkas','24',1085),(2914,'Lesvos','83',1085),(2915,'Magnisia','43',1085),(2916,'Messinia','17',1085),(2917,'Pella','59',1085),(2918,'Preveza','34',1085),(2919,'Rethymnon','93',1085),(2920,'Rodopi','73',1085),(2921,'Samos','84',1085),(2922,'Serrai','62',1085),(2923,'Thesprotia','32',1085),(2924,'Thessaloniki','54',1085),(2925,'Trikala','44',1085),(2926,'Voiotia','03',1085),(2927,'Xanthi','72',1085),(2928,'Zakynthos','21',1085),(2929,'Agio Oros','69',1085),(2930,'Alta Verapaz','AV',1090),(2931,'Baja Verapaz','BV',1090),(2932,'Chimaltenango','CM',1090),(2933,'Chiquimula','CQ',1090),(2934,'El Progreso','PR',1090),(2935,'Escuintla','ES',1090),(2936,'Guatemala','GU',1090),(2937,'Huehuetenango','HU',1090),(2938,'Izabal','IZ',1090),(2939,'Jalapa','JA',1090),(2940,'Jutiapa','JU',1090),(2941,'Peten','PE',1090),(2942,'Quetzaltenango','QZ',1090),(2943,'Quiche','QC',1090),(2944,'Retalhuleu','RE',1090),(2945,'Sacatepequez','SA',1090),(2946,'San Marcos','SM',1090),(2947,'Santa Rosa','SR',1090),(2948,'Sololá','SO',1090),(2949,'Suchitepequez','SU',1090),(2950,'Totonicapan','TO',1090),(2951,'Zacapa','ZA',1090),(2952,'Bissau','BS',1092),(2953,'Bafata','BA',1092),(2954,'Biombo','BM',1092),(2955,'Bolama','BL',1092),(2956,'Cacheu','CA',1092),(2957,'Gabu','GA',1092),(2958,'Oio','OI',1092),(2959,'Quloara','QU',1092),(2960,'Tombali S','TO',1092),(2961,'Barima-Waini','BA',1093),(2962,'Cuyuni-Mazaruni','CU',1093),(2963,'Demerara-Mahaica','DE',1093),(2964,'East Berbice-Corentyne','EB',1093),(2965,'Essequibo Islands-West Demerara','ES',1093),(2966,'Mahaica-Berbice','MA',1093),(2967,'Pomeroon-Supenaam','PM',1093),(2968,'Potaro-Siparuni','PT',1093),(2969,'Upper Demerara-Berbice','UD',1093),(2970,'Upper Takutu-Upper Essequibo','UT',1093),(2971,'Atlantida','AT',1097),(2972,'Colon','CL',1097),(2973,'Comayagua','CM',1097),(2974,'Copan','CP',1097),(2975,'Cortes','CR',1097),(2976,'Choluteca','CH',1097),(2977,'El Paraiso','EP',1097),(2978,'Francisco Morazan','FM',1097),(2979,'Gracias a Dios','GD',1097),(2980,'Intibuca','IN',1097),(2981,'Islas de la Bahia','IB',1097),(2982,'Lempira','LE',1097),(2983,'Ocotepeque','OC',1097),(2984,'Olancho','OL',1097),(2985,'Santa Barbara','SB',1097),(2986,'Valle','VA',1097),(2987,'Yoro','YO',1097),(2988,'Bjelovarsko-bilogorska zupanija','07',1055),(2989,'Brodsko-posavska zupanija','12',1055),(2990,'Dubrovacko-neretvanska zupanija','19',1055),(2991,'Istarska zupanija','18',1055),(2992,'Karlovacka zupanija','04',1055),(2993,'Koprivnickco-krizevacka zupanija','06',1055),(2994,'Krapinako-zagorska zupanija','02',1055),(2995,'Licko-senjska zupanija','09',1055),(2996,'Medimurska zupanija','20',1055),(2997,'Osjecko-baranjska zupanija','14',1055),(2998,'Pozesko-slavonska zupanija','11',1055),(2999,'Primorsko-goranska zupanija','08',1055),(3000,'Sisacko-moelavacka Iupanija','03',1055),(3001,'Splitako-dalmatinska zupanija','17',1055),(3002,'Sibenako-kninska zupanija','15',1055),(3003,'Varaidinska zupanija','05',1055),(3004,'VirovitiEko-podravska zupanija','10',1055),(3005,'VuRovarako-srijemska zupanija','16',1055),(3006,'Zadaraka','13',1055),(3007,'Zagrebacka zupanija','01',1055),(3008,'Grande-Anse','GA',1094),(3009,'Nord-Est','NE',1094),(3010,'Nord-Ouest','NO',1094),(3011,'Ouest','OU',1094),(3012,'Sud','SD',1094),(3013,'Sud-Est','SE',1094),(3014,'Budapest','BU',1099),(3015,'Bács-Kiskun','BK',1099),(3016,'Baranya','BA',1099),(3017,'Békés','BE',1099),(3018,'Borsod-Abaúj-Zemplén','BZ',1099),(3019,'Csongrád','CS',1099),(3020,'Fejér','FE',1099),(3021,'Győr-Moson-Sopron','GS',1099),(3022,'Hajdu-Bihar','HB',1099),(3023,'Heves','HE',1099),(3024,'Jász-Nagykun-Szolnok','JN',1099),(3025,'Komárom-Esztergom','KE',1099),(3026,'Nográd','NO',1099),(3027,'Pest','PE',1099),(3028,'Somogy','SO',1099),(3029,'Szabolcs-Szatmár-Bereg','SZ',1099),(3030,'Tolna','TO',1099),(3031,'Vas','VA',1099),(3032,'Veszprém','VE',1099),(3033,'Zala','ZA',1099),(3034,'Békéscsaba','BC',1099),(3035,'Debrecen','DE',1099),(3036,'Dunaújváros','DU',1099),(3037,'Eger','EG',1099),(3038,'Győr','GY',1099),(3039,'Hódmezővásárhely','HV',1099),(3040,'Kaposvár','KV',1099),(3041,'Kecskemét','KM',1099),(3042,'Miskolc','MI',1099),(3043,'Nagykanizsa','NK',1099),(3044,'Nyiregyháza','NY',1099),(3045,'Pécs','PS',1099),(3046,'Salgótarján','ST',1099),(3047,'Sopron','SN',1099),(3048,'Szeged','SD',1099),(3049,'Székesfehérvár','SF',1099),(3050,'Szekszárd','SS',1099),(3051,'Szolnok','SK',1099),(3052,'Szombathely','SH',1099),(3053,'Tatabánya','TB',1099),(3054,'Zalaegerszeg','ZE',1099),(3055,'Bali','BA',1102),(3056,'Kepulauan Bangka Belitung','BB',1102),(3057,'Banten','BT',1102),(3058,'Bengkulu','BE',1102),(3059,'Gorontalo','GO',1102),(3060,'Papua Barat','PB',1102),(3061,'Jambi','JA',1102),(3062,'Jawa Barat','JB',1102),(3063,'Jawa Tengah','JT',1102),(3064,'Jawa Timur','JI',1102),(3065,'Kalimantan Barat','KB',1102),(3066,'Kalimantan Timur','KI',1102),(3067,'Kalimantan Selatan','KS',1102),(3068,'Kepulauan Riau','KR',1102),(3069,'Lampung','LA',1102),(3070,'Maluku','MA',1102),(3071,'Maluku Utara','MU',1102),(3072,'Nusa Tenggara Barat','NB',1102),(3073,'Nusa Tenggara Timur','NT',1102),(3074,'Papua','PA',1102),(3075,'Riau','RI',1102),(3076,'Sulawesi Selatan','SN',1102),(3077,'Sulawesi Tengah','ST',1102),(3078,'Sulawesi Tenggara','SG',1102),(3079,'Sulawesi Utara','SA',1102),(3080,'Sumatra Barat','SB',1102),(3081,'Sumatra Selatan','SS',1102),(3082,'Sumatera Utara','SU',1102),(3083,'DKI Jakarta','JK',1102),(3084,'Aceh','AC',1102),(3085,'DI Yogyakarta','YO',1102),(3086,'Cork','C',1105),(3087,'Clare','CE',1105),(3088,'Cavan','CN',1105),(3089,'Carlow','CW',1105),(3090,'Dublin','D',1105),(3091,'Donegal','DL',1105),(3092,'Galway','G',1105),(3093,'Kildare','KE',1105),(3094,'Kilkenny','KK',1105),(3095,'Kerry','KY',1105),(3096,'Longford','LD',1105),(3097,'Louth','LH',1105),(3098,'Limerick','LK',1105),(3099,'Leitrim','LM',1105),(3100,'Laois','LS',1105),(3101,'Meath','MH',1105),(3102,'Monaghan','MN',1105),(3103,'Mayo','MO',1105),(3104,'Offaly','OY',1105),(3105,'Roscommon','RN',1105),(3106,'Sligo','SO',1105),(3107,'Tipperary','TA',1105),(3108,'Waterford','WD',1105),(3109,'Westmeath','WH',1105),(3110,'Wicklow','WW',1105),(3111,'Wexford','WX',1105),(3112,'HaDarom','D',1106),(3113,'HaMerkaz','M',1106),(3114,'HaZafon','Z',1106),(3115,'Haifa','HA',1106),(3116,'Tel-Aviv','TA',1106),(3117,'Jerusalem','JM',1106),(3118,'Al Anbar','AN',1104),(3119,'Al Ba,rah','BA',1104),(3120,'Al Muthanna','MU',1104),(3121,'Al Qadisiyah','QA',1104),(3122,'An Najef','NA',1104),(3123,'Arbil','AR',1104),(3124,'As Sulaymaniyah','SW',1104),(3125,'At Ta\'mim','TS',1104),(3126,'Babil','BB',1104),(3127,'Baghdad','BG',1104),(3128,'Dahuk','DA',1104),(3129,'Dhi Qar','DQ',1104),(3130,'Diyala','DI',1104),(3131,'Karbala\'','KA',1104),(3132,'Maysan','MA',1104),(3133,'Ninawa','NI',1104),(3134,'Salah ad Din','SD',1104),(3135,'Wasit','WA',1104),(3136,'Ardabil','03',1103),(3137,'Azarbayjan-e Gharbi','02',1103),(3138,'Azarbayjan-e Sharqi','01',1103),(3139,'Bushehr','06',1103),(3140,'Chahar Mahall va Bakhtiari','08',1103),(3141,'Esfahan','04',1103),(3142,'Fars','14',1103),(3143,'Gilan','19',1103),(3144,'Golestan','27',1103),(3145,'Hamadan','24',1103),(3146,'Hormozgan','23',1103),(3147,'Iiam','05',1103),(3148,'Kerman','15',1103),(3149,'Kermanshah','17',1103),(3150,'Khorasan','09',1103),(3151,'Khuzestan','10',1103),(3152,'Kohjiluyeh va Buyer Ahmad','18',1103),(3153,'Kordestan','16',1103),(3154,'Lorestan','20',1103),(3155,'Markazi','22',1103),(3156,'Mazandaran','21',1103),(3157,'Qazvin','28',1103),(3158,'Qom','26',1103),(3159,'Semnan','12',1103),(3160,'Sistan va Baluchestan','13',1103),(3161,'Tehran','07',1103),(3162,'Yazd','25',1103),(3163,'Zanjan','11',1103),(3164,'Austurland','7',1100),(3165,'Hofuoborgarsvaeoi utan Reykjavikur','1',1100),(3166,'Norourland eystra','6',1100),(3167,'Norourland vestra','5',1100),(3168,'Reykjavik','0',1100),(3169,'Suourland','8',1100),(3170,'Suournes','2',1100),(3171,'Vestfirolr','4',1100),(3172,'Vesturland','3',1100),(3173,'Agrigento','AG',1107),(3174,'Alessandria','AL',1107),(3175,'Ancona','AN',1107),(3176,'Aosta','AO',1107),(3177,'Arezzo','AR',1107),(3178,'Ascoli Piceno','AP',1107),(3179,'Asti','AT',1107),(3180,'Avellino','AV',1107),(3181,'Bari','BA',1107),(3182,'Belluno','BL',1107),(3183,'Benevento','BN',1107),(3184,'Bergamo','BG',1107),(3185,'Biella','BI',1107),(3186,'Bologna','BO',1107),(3187,'Bolzano','BZ',1107),(3188,'Brescia','BS',1107),(3189,'Brindisi','BR',1107),(3190,'Cagliari','CA',1107),(3191,'Caltanissetta','CL',1107),(3192,'Campobasso','CB',1107),(3193,'Caserta','CE',1107),(3194,'Catania','CT',1107),(3195,'Catanzaro','CZ',1107),(3196,'Chieti','CH',1107),(3197,'Como','CO',1107),(3198,'Cosenza','CS',1107),(3199,'Cremona','CR',1107),(3200,'Crotone','KR',1107),(3201,'Cuneo','CN',1107),(3202,'Enna','EN',1107),(3203,'Ferrara','FE',1107),(3204,'Firenze','FI',1107),(3205,'Foggia','FG',1107),(3206,'Forlì-Cesena','FC',1107),(3207,'Frosinone','FR',1107),(3208,'Genova','GE',1107),(3209,'Gorizia','GO',1107),(3210,'Grosseto','GR',1107),(3211,'Imperia','IM',1107),(3212,'Isernia','IS',1107),(3213,'L\'Aquila','AQ',1107),(3214,'La Spezia','SP',1107),(3215,'Latina','LT',1107),(3216,'Lecce','LE',1107),(3217,'Lecco','LC',1107),(3218,'Livorno','LI',1107),(3219,'Lodi','LO',1107),(3220,'Lucca','LU',1107),(3221,'Macerata','MC',1107),(3222,'Mantova','MN',1107),(3223,'Massa-Carrara','MS',1107),(3224,'Matera','MT',1107),(3225,'Messina','ME',1107),(3226,'Milano','MI',1107),(3227,'Modena','MO',1107),(3228,'Napoli','NA',1107),(3229,'Novara','NO',1107),(3230,'Nuoro','NU',1107),(3231,'Oristano','OR',1107),(3232,'Padova','PD',1107),(3233,'Palermo','PA',1107),(3234,'Parma','PR',1107),(3235,'Pavia','PV',1107),(3236,'Perugia','PG',1107),(3237,'Pesaro e Urbino','PU',1107),(3238,'Pescara','PE',1107),(3239,'Piacenza','PC',1107),(3240,'Pisa','PI',1107),(3241,'Pistoia','PT',1107),(3242,'Pordenone','PN',1107),(3243,'Potenza','PZ',1107),(3244,'Prato','PO',1107),(3245,'Ragusa','RG',1107),(3246,'Ravenna','RA',1107),(3247,'Reggio Calabria','RC',1107),(3248,'Reggio Emilia','RE',1107),(3249,'Rieti','RI',1107),(3250,'Rimini','RN',1107),(3251,'Roma','RM',1107),(3252,'Rovigo','RO',1107),(3253,'Salerno','SA',1107),(3254,'Sassari','SS',1107),(3255,'Savona','SV',1107),(3256,'Siena','SI',1107),(3257,'Siracusa','SR',1107),(3258,'Sondrio','SO',1107),(3259,'Taranto','TA',1107),(3260,'Teramo','TE',1107),(3261,'Terni','TR',1107),(3262,'Torino','TO',1107),(3263,'Trapani','TP',1107),(3264,'Trento','TN',1107),(3265,'Treviso','TV',1107),(3266,'Trieste','TS',1107),(3267,'Udine','UD',1107),(3268,'Varese','VA',1107),(3269,'Venezia','VE',1107),(3270,'Verbano-Cusio-Ossola','VB',1107),(3271,'Vercelli','VC',1107),(3272,'Verona','VR',1107),(3273,'Vibo Valentia','VV',1107),(3274,'Vicenza','VI',1107),(3275,'Viterbo','VT',1107),(3276,'Aichi','23',1109),(3277,'Akita','05',1109),(3278,'Aomori','02',1109),(3279,'Chiba','12',1109),(3280,'Ehime','38',1109),(3281,'Fukui','18',1109),(3282,'Fukuoka','40',1109),(3283,'Fukusima','07',1109),(3284,'Gifu','21',1109),(3285,'Gunma','10',1109),(3286,'Hiroshima','34',1109),(3287,'Hokkaido','01',1109),(3288,'Hyogo','28',1109),(3289,'Ibaraki','08',1109),(3290,'Ishikawa','17',1109),(3291,'Iwate','03',1109),(3292,'Kagawa','37',1109),(3293,'Kagoshima','46',1109),(3294,'Kanagawa','14',1109),(3295,'Kochi','39',1109),(3296,'Kumamoto','43',1109),(3297,'Kyoto','26',1109),(3298,'Mie','24',1109),(3299,'Miyagi','04',1109),(3300,'Miyazaki','45',1109),(3301,'Nagano','20',1109),(3302,'Nagasaki','42',1109),(3303,'Nara','29',1109),(3304,'Niigata','15',1109),(3305,'Oita','44',1109),(3306,'Okayama','33',1109),(3307,'Okinawa','47',1109),(3308,'Osaka','27',1109),(3309,'Saga','41',1109),(3310,'Saitama','11',1109),(3311,'Shiga','25',1109),(3312,'Shimane','32',1109),(3313,'Shizuoka','22',1109),(3314,'Tochigi','09',1109),(3315,'Tokushima','36',1109),(3316,'Tokyo','13',1109),(3317,'Tottori','31',1109),(3318,'Toyama','16',1109),(3319,'Wakayama','30',1109),(3320,'Yamagata','06',1109),(3321,'Yamaguchi','35',1109),(3322,'Yamanashi','19',1109),(3323,'Clarendon','CN',1108),(3324,'Hanover','HR',1108),(3325,'Kingston','KN',1108),(3326,'Portland','PD',1108),(3327,'Saint Andrew','AW',1108),(3328,'Saint Ann','AN',1108),(3329,'Saint Catherine','CE',1108),(3330,'Saint Elizabeth','EH',1108),(3331,'Saint James','JS',1108),(3332,'Saint Mary','MY',1108),(3333,'Saint Thomas','TS',1108),(3334,'Trelawny','TY',1108),(3335,'Westmoreland','WD',1108),(3336,'Ajln','AJ',1110),(3337,'Al \'Aqaba','AQ',1110),(3338,'Al Balqa\'','BA',1110),(3339,'Al Karak','KA',1110),(3340,'Al Mafraq','MA',1110),(3341,'Amman','AM',1110),(3342,'At Tafilah','AT',1110),(3343,'Az Zarga','AZ',1110),(3344,'Irbid','JR',1110),(3345,'Jarash','JA',1110),(3346,'Ma\'an','MN',1110),(3347,'Madaba','MD',1110),(3353,'Bishkek','GB',1117),(3354,'Batken','B',1117),(3355,'Chu','C',1117),(3356,'Jalal-Abad','J',1117),(3357,'Naryn','N',1117),(3358,'Osh','O',1117),(3359,'Talas','T',1117),(3360,'Ysyk-Kol','Y',1117),(3361,'Krong Kaeb','23',1037),(3362,'Krong Pailin','24',1037),(3363,'Xrong Preah Sihanouk','18',1037),(3364,'Phnom Penh','12',1037),(3365,'Baat Dambang','2',1037),(3366,'Banteay Mean Chey','1',1037),(3367,'Rampong Chaam','3',1037),(3368,'Kampong Chhnang','4',1037),(3369,'Kampong Spueu','5',1037),(3370,'Kampong Thum','6',1037),(3371,'Kampot','7',1037),(3372,'Kandaal','8',1037),(3373,'Kach Kong','9',1037),(3374,'Krachoh','10',1037),(3375,'Mondol Kiri','11',1037),(3376,'Otdar Mean Chey','22',1037),(3377,'Pousaat','15',1037),(3378,'Preah Vihear','13',1037),(3379,'Prey Veaeng','14',1037),(3380,'Rotanak Kiri','16',1037),(3381,'Siem Reab','17',1037),(3382,'Stueng Traeng','19',1037),(3383,'Svaay Rieng','20',1037),(3384,'Taakaev','21',1037),(3385,'Gilbert Islands','G',1113),(3386,'Line Islands','L',1113),(3387,'Phoenix Islands','P',1113),(3388,'Anjouan Ndzouani','A',1049),(3389,'Grande Comore Ngazidja','G',1049),(3390,'Moheli Moili','M',1049),(3391,'Kaesong-si','KAE',1114),(3392,'Nampo-si','NAM',1114),(3393,'Pyongyang-ai','PYO',1114),(3394,'Chagang-do','CHA',1114),(3395,'Hamgyongbuk-do','HAB',1114),(3396,'Hamgyongnam-do','HAN',1114),(3397,'Hwanghaebuk-do','HWB',1114),(3398,'Hwanghaenam-do','HWN',1114),(3399,'Kangwon-do','KAN',1114),(3400,'Pyonganbuk-do','PYB',1114),(3401,'Pyongannam-do','PYN',1114),(3402,'Yanggang-do','YAN',1114),(3403,'Najin Sonbong-si','NAJ',1114),(3404,'Seoul Teugbyeolsi','11',1115),(3405,'Busan Gwang\'yeogsi','26',1115),(3406,'Daegu Gwang\'yeogsi','27',1115),(3407,'Daejeon Gwang\'yeogsi','30',1115),(3408,'Gwangju Gwang\'yeogsi','29',1115),(3409,'Incheon Gwang\'yeogsi','28',1115),(3410,'Ulsan Gwang\'yeogsi','31',1115),(3411,'Chungcheongbugdo','43',1115),(3412,'Chungcheongnamdo','44',1115),(3413,'Gang\'weondo','42',1115),(3414,'Gyeonggido','41',1115),(3415,'Gyeongsangbugdo','47',1115),(3416,'Gyeongsangnamdo','48',1115),(3417,'Jejudo','49',1115),(3418,'Jeonrabugdo','45',1115),(3419,'Jeonranamdo','46',1115),(3420,'Al Ahmadi','AH',1116),(3421,'Al Farwanlyah','FA',1116),(3422,'Al Jahrah','JA',1116),(3423,'Al Kuwayt','KU',1116),(3424,'Hawalli','HA',1116),(3425,'Almaty','ALA',1111),(3426,'Astana','AST',1111),(3427,'Almaty oblysy','ALM',1111),(3428,'Aqmola oblysy','AKM',1111),(3429,'Aqtobe oblysy','AKT',1111),(3430,'Atyrau oblyfiy','ATY',1111),(3431,'Batys Quzaqstan oblysy','ZAP',1111),(3432,'Mangghystau oblysy','MAN',1111),(3433,'Ongtustik Quzaqstan oblysy','YUZ',1111),(3434,'Pavlodar oblysy','PAV',1111),(3435,'Qaraghandy oblysy','KAR',1111),(3436,'Qostanay oblysy','KUS',1111),(3437,'Qyzylorda oblysy','KZY',1111),(3438,'Shyghys Quzaqstan oblysy','VOS',1111),(3439,'Soltustik Quzaqstan oblysy','SEV',1111),(3440,'Zhambyl oblysy Zhambylskaya oblast\'','ZHA',1111),(3441,'Vientiane','VT',1118),(3442,'Attapu','AT',1118),(3443,'Bokeo','BK',1118),(3444,'Bolikhamxai','BL',1118),(3445,'Champasak','CH',1118),(3446,'Houaphan','HO',1118),(3447,'Khammouan','KH',1118),(3448,'Louang Namtha','LM',1118),(3449,'Louangphabang','LP',1118),(3450,'Oudomxai','OU',1118),(3451,'Phongsali','PH',1118),(3452,'Salavan','SL',1118),(3453,'Savannakhet','SV',1118),(3454,'Xaignabouli','XA',1118),(3455,'Xiasomboun','XN',1118),(3456,'Xekong','XE',1118),(3457,'Xiangkhoang','XI',1118),(3458,'Beirut','BA',1120),(3459,'Beqaa','BI',1120),(3460,'Mount Lebanon','JL',1120),(3461,'North Lebanon','AS',1120),(3462,'South Lebanon','JA',1120),(3463,'Nabatieh','NA',1120),(3464,'Ampara','52',1199),(3465,'Anuradhapura','71',1199),(3466,'Badulla','81',1199),(3467,'Batticaloa','51',1199),(3468,'Colombo','11',1199),(3469,'Galle','31',1199),(3470,'Gampaha','12',1199),(3471,'Hambantota','33',1199),(3472,'Jaffna','41',1199),(3473,'Kalutara','13',1199),(3474,'Kandy','21',1199),(3475,'Kegalla','92',1199),(3476,'Kilinochchi','42',1199),(3477,'Kurunegala','61',1199),(3478,'Mannar','43',1199),(3479,'Matale','22',1199),(3480,'Matara','32',1199),(3481,'Monaragala','82',1199),(3482,'Mullaittivu','45',1199),(3483,'Nuwara Eliya','23',1199),(3484,'Polonnaruwa','72',1199),(3485,'Puttalum','62',1199),(3486,'Ratnapura','91',1199),(3487,'Trincomalee','53',1199),(3488,'VavunLya','44',1199),(3489,'Bomi','BM',1122),(3490,'Bong','BG',1122),(3491,'Grand Basaa','GB',1122),(3492,'Grand Cape Mount','CM',1122),(3493,'Grand Gedeh','GG',1122),(3494,'Grand Kru','GK',1122),(3495,'Lofa','LO',1122),(3496,'Margibi','MG',1122),(3497,'Maryland','MY',1122),(3498,'Montserrado','MO',1122),(3499,'Nimba','NI',1122),(3500,'Rivercess','RI',1122),(3501,'Sinoe','SI',1122),(3502,'Berea','D',1121),(3503,'Butha-Buthe','B',1121),(3504,'Leribe','C',1121),(3505,'Mafeteng','E',1121),(3506,'Maseru','A',1121),(3507,'Mohale\'s Hoek','F',1121),(3508,'Mokhotlong','J',1121),(3509,'Qacha\'s Nek','H',1121),(3510,'Quthing','G',1121),(3511,'Thaba-Tseka','K',1121),(3512,'Alytaus Apskritis','AL',1125),(3513,'Kauno Apskritis','KU',1125),(3514,'Klaipėdos Apskritis','KL',1125),(3515,'Marijampolės Apskritis','MR',1125),(3516,'Panevėžio Apskritis','PN',1125),(3517,'Šiaulių Apskritis','SA',1125),(3518,'Tauragės Apskritis','TA',1125),(3519,'Telšių Apskritis','TE',1125),(3520,'Utenos Apskritis','UT',1125),(3521,'Vilniaus Apskritis','VL',1125),(3522,'Diekirch','D',1126),(3523,'GreveNmacher','G',1126),(3550,'Daugavpils','DGV',1119),(3551,'Jelgava','JEL',1119),(3552,'Jūrmala','JUR',1119),(3553,'Liepāja','LPX',1119),(3554,'Rēzekne','REZ',1119),(3555,'Rīga','RIX',1119),(3556,'Ventspils','VEN',1119),(3557,'Ajdābiyā','AJ',1123),(3558,'Al Buţnān','BU',1123),(3559,'Al Hizām al Akhdar','HZ',1123),(3560,'Al Jabal al Akhdar','JA',1123),(3561,'Al Jifārah','JI',1123),(3562,'Al Jufrah','JU',1123),(3563,'Al Kufrah','KF',1123),(3564,'Al Marj','MJ',1123),(3565,'Al Marqab','MB',1123),(3566,'Al Qaţrūn','QT',1123),(3567,'Al Qubbah','QB',1123),(3568,'Al Wāhah','WA',1123),(3569,'An Nuqaţ al Khams','NQ',1123),(3570,'Ash Shāţi\'','SH',1123),(3571,'Az Zāwiyah','ZA',1123),(3572,'Banghāzī','BA',1123),(3573,'Banī Walīd','BW',1123),(3574,'Darnah','DR',1123),(3575,'Ghadāmis','GD',1123),(3576,'Gharyān','GR',1123),(3577,'Ghāt','GT',1123),(3578,'Jaghbūb','JB',1123),(3579,'Mişrātah','MI',1123),(3580,'Mizdah','MZ',1123),(3581,'Murzuq','MQ',1123),(3582,'Nālūt','NL',1123),(3583,'Sabhā','SB',1123),(3584,'Şabrātah Şurmān','SS',1123),(3585,'Surt','SR',1123),(3586,'Tājūrā\' wa an Nawāhī al Arbāh','TN',1123),(3587,'Ţarābulus','TB',1123),(3588,'Tarhūnah-Masallātah','TM',1123),(3589,'Wādī al hayāt','WD',1123),(3590,'Yafran-Jādū','YJ',1123),(3591,'Agadir','AGD',1146),(3592,'Aït Baha','BAH',1146),(3593,'Aït Melloul','MEL',1146),(3594,'Al Haouz','HAO',1146),(3595,'Al Hoceïma','HOC',1146),(3596,'Assa-Zag','ASZ',1146),(3597,'Azilal','AZI',1146),(3598,'Beni Mellal','BEM',1146),(3599,'Ben Sllmane','BES',1146),(3600,'Berkane','BER',1146),(3601,'Boujdour','BOD',1146),(3602,'Boulemane','BOM',1146),(3603,'Casablanca  [Dar el Beïda]','CAS',1146),(3604,'Chefchaouene','CHE',1146),(3605,'Chichaoua','CHI',1146),(3606,'El Hajeb','HAJ',1146),(3607,'El Jadida','JDI',1146),(3608,'Errachidia','ERR',1146),(3609,'Essaouira','ESI',1146),(3610,'Es Smara','ESM',1146),(3611,'Fès','FES',1146),(3612,'Figuig','FIG',1146),(3613,'Guelmim','GUE',1146),(3614,'Ifrane','IFR',1146),(3615,'Jerada','JRA',1146),(3616,'Kelaat Sraghna','KES',1146),(3617,'Kénitra','KEN',1146),(3618,'Khemisaet','KHE',1146),(3619,'Khenifra','KHN',1146),(3620,'Khouribga','KHO',1146),(3621,'Laâyoune (EH)','LAA',1146),(3622,'Larache','LAP',1146),(3623,'Marrakech','MAR',1146),(3624,'Meknsès','MEK',1146),(3625,'Nador','NAD',1146),(3626,'Ouarzazate','OUA',1146),(3627,'Oued ed Dahab (EH)','OUD',1146),(3628,'Oujda','OUJ',1146),(3629,'Rabat-Salé','RBA',1146),(3630,'Safi','SAF',1146),(3631,'Sefrou','SEF',1146),(3632,'Settat','SET',1146),(3633,'Sidl Kacem','SIK',1146),(3634,'Tanger','TNG',1146),(3635,'Tan-Tan','TNT',1146),(3636,'Taounate','TAO',1146),(3637,'Taroudannt','TAR',1146),(3638,'Tata','TAT',1146),(3639,'Taza','TAZ',1146),(3640,'Tétouan','TET',1146),(3641,'Tiznit','TIZ',1146),(3642,'Gagauzia, Unitate Teritoriala Autonoma','GA',1142),(3643,'Chisinau','CU',1142),(3644,'Stinga Nistrului, unitatea teritoriala din','SN',1142),(3645,'Balti','BA',1142),(3646,'Cahul','CA',1142),(3647,'Edinet','ED',1142),(3648,'Lapusna','LA',1142),(3649,'Orhei','OR',1142),(3650,'Soroca','SO',1142),(3651,'Taraclia','TA',1142),(3652,'Tighina [Bender]','TI',1142),(3653,'Ungheni','UN',1142),(3654,'Antananarivo','T',1129),(3655,'Antsiranana','D',1129),(3656,'Fianarantsoa','F',1129),(3657,'Mahajanga','M',1129),(3658,'Toamasina','A',1129),(3659,'Toliara','U',1129),(3660,'Ailinglapalap','ALL',1135),(3661,'Ailuk','ALK',1135),(3662,'Arno','ARN',1135),(3663,'Aur','AUR',1135),(3664,'Ebon','EBO',1135),(3665,'Eniwetok','ENI',1135),(3666,'Jaluit','JAL',1135),(3667,'Kili','KIL',1135),(3668,'Kwajalein','KWA',1135),(3669,'Lae','LAE',1135),(3670,'Lib','LIB',1135),(3671,'Likiep','LIK',1135),(3672,'Majuro','MAJ',1135),(3673,'Maloelap','MAL',1135),(3674,'Mejit','MEJ',1135),(3675,'Mili','MIL',1135),(3676,'Namorik','NMK',1135),(3677,'Namu','NMU',1135),(3678,'Rongelap','RON',1135),(3679,'Ujae','UJA',1135),(3680,'Ujelang','UJL',1135),(3681,'Utirik','UTI',1135),(3682,'Wotho','WTN',1135),(3683,'Wotje','WTJ',1135),(3684,'Bamako','BK0',1133),(3685,'Gao','7',1133),(3686,'Kayes','1',1133),(3687,'Kidal','8',1133),(3688,'Xoulikoro','2',1133),(3689,'Mopti','5',1133),(3690,'S69ou','4',1133),(3691,'Sikasso','3',1133),(3692,'Tombouctou','6',1133),(3693,'Ayeyarwady','07',1035),(3694,'Bago','02',1035),(3695,'Magway','03',1035),(3696,'Mandalay','04',1035),(3697,'Sagaing','01',1035),(3698,'Tanintharyi','05',1035),(3699,'Yangon','06',1035),(3700,'Chin','14',1035),(3701,'Kachin','11',1035),(3702,'Kayah','12',1035),(3703,'Kayin','13',1035),(3704,'Mon','15',1035),(3705,'Rakhine','16',1035),(3706,'Shan','17',1035),(3707,'Ulaanbaatar','1',1144),(3708,'Arhangay','073',1144),(3709,'Bayanhongor','069',1144),(3710,'Bayan-Olgiy','071',1144),(3711,'Bulgan','067',1144),(3712,'Darhan uul','037',1144),(3713,'Dornod','061',1144),(3714,'Dornogov,','063',1144),(3715,'DundgovL','059',1144),(3716,'Dzavhan','057',1144),(3717,'Govi-Altay','065',1144),(3718,'Govi-Smber','064',1144),(3719,'Hentiy','039',1144),(3720,'Hovd','043',1144),(3721,'Hovsgol','041',1144),(3722,'Omnogovi','053',1144),(3723,'Orhon','035',1144),(3724,'Ovorhangay','055',1144),(3725,'Selenge','049',1144),(3726,'Shbaatar','051',1144),(3727,'Tov','047',1144),(3728,'Uvs','046',1144),(3729,'Nouakchott','NKC',1137),(3730,'Assaba','03',1137),(3731,'Brakna','05',1137),(3732,'Dakhlet Nouadhibou','08',1137),(3733,'Gorgol','04',1137),(3734,'Guidimaka','10',1137),(3735,'Hodh ech Chargui','01',1137),(3736,'Hodh el Charbi','02',1137),(3737,'Inchiri','12',1137),(3738,'Tagant','09',1137),(3739,'Tiris Zemmour','11',1137),(3740,'Trarza','06',1137),(3741,'Beau Bassin-Rose Hill','BR',1138),(3742,'Curepipe','CU',1138),(3743,'Port Louis','PU',1138),(3744,'Quatre Bornes','QB',1138),(3745,'Vacosa-Phoenix','VP',1138),(3746,'Black River','BL',1138),(3747,'Flacq','FL',1138),(3748,'Grand Port','GP',1138),(3749,'Moka','MO',1138),(3750,'Pamplemousses','PA',1138),(3751,'Plaines Wilhems','PW',1138),(3752,'Riviere du Rempart','RP',1138),(3753,'Savanne','SA',1138),(3754,'Agalega Islands','AG',1138),(3755,'Cargados Carajos Shoals','CC',1138),(3756,'Rodrigues Island','RO',1138),(3757,'Male','MLE',1132),(3758,'Alif','02',1132),(3759,'Baa','20',1132),(3760,'Dhaalu','17',1132),(3761,'Faafu','14',1132),(3762,'Gaaf Alif','27',1132),(3763,'Gaefu Dhaalu','28',1132),(3764,'Gnaviyani','29',1132),(3765,'Haa Alif','07',1132),(3766,'Haa Dhaalu','23',1132),(3767,'Kaafu','26',1132),(3768,'Laamu','05',1132),(3769,'Lhaviyani','03',1132),(3770,'Meemu','12',1132),(3771,'Noonu','25',1132),(3772,'Raa','13',1132),(3773,'Seenu','01',1132),(3774,'Shaviyani','24',1132),(3775,'Thaa','08',1132),(3776,'Vaavu','04',1132),(3777,'Balaka','BA',1130),(3778,'Blantyre','BL',1130),(3779,'Chikwawa','CK',1130),(3780,'Chiradzulu','CR',1130),(3781,'Chitipa','CT',1130),(3782,'Dedza','DE',1130),(3783,'Dowa','DO',1130),(3784,'Karonga','KR',1130),(3785,'Kasungu','KS',1130),(3786,'Likoma Island','LK',1130),(3787,'Lilongwe','LI',1130),(3788,'Machinga','MH',1130),(3789,'Mangochi','MG',1130),(3790,'Mchinji','MC',1130),(3791,'Mulanje','MU',1130),(3792,'Mwanza','MW',1130),(3793,'Mzimba','MZ',1130),(3794,'Nkhata Bay','NB',1130),(3795,'Nkhotakota','NK',1130),(3796,'Nsanje','NS',1130),(3797,'Ntcheu','NU',1130),(3798,'Ntchisi','NI',1130),(3799,'Phalomba','PH',1130),(3800,'Rumphi','RU',1130),(3801,'Salima','SA',1130),(3802,'Thyolo','TH',1130),(3803,'Zomba','ZO',1130),(3804,'Aguascalientes','AGU',1140),(3805,'Baja California','BCN',1140),(3806,'Baja California Sur','BCS',1140),(3807,'Campeche','CAM',1140),(3808,'Coahuila','COA',1140),(3809,'Colima','COL',1140),(3810,'Chiapas','CHP',1140),(3811,'Chihuahua','CHH',1140),(3812,'Durango','DUR',1140),(3813,'Guanajuato','GUA',1140),(3814,'Guerrero','GRO',1140),(3815,'Hidalgo','HID',1140),(3816,'Jalisco','JAL',1140),(3817,'Mexico','MEX',1140),(3818,'Michoacin','MIC',1140),(3819,'Morelos','MOR',1140),(3820,'Nayarit','NAY',1140),(3821,'Nuevo Leon','NLE',1140),(3822,'Oaxaca','OAX',1140),(3823,'Puebla','PUE',1140),(3824,'Queretaro','QUE',1140),(3825,'Quintana Roo','ROO',1140),(3826,'San Luis Potosi','SLP',1140),(3827,'Sinaloa','SIN',1140),(3828,'Sonora','SON',1140),(3829,'Tabasco','TAB',1140),(3830,'Tamaulipas','TAM',1140),(3831,'Tlaxcala','TLA',1140),(3832,'Veracruz','VER',1140),(3833,'Yucatan','YUC',1140),(3834,'Zacatecas','ZAC',1140),(3835,'Wilayah Persekutuan Kuala Lumpur','14',1131),(3836,'Wilayah Persekutuan Labuan','15',1131),(3837,'Wilayah Persekutuan Putrajaya','16',1131),(3838,'Johor','01',1131),(3839,'Kedah','02',1131),(3840,'Kelantan','03',1131),(3841,'Melaka','04',1131),(3842,'Negeri Sembilan','05',1131),(3843,'Pahang','06',1131),(3844,'Perak','08',1131),(3845,'Perlis','09',1131),(3846,'Pulau Pinang','07',1131),(3847,'Sabah','12',1131),(3848,'Sarawak','13',1131),(3849,'Selangor','10',1131),(3850,'Terengganu','11',1131),(3851,'Maputo','MPM',1147),(3852,'Cabo Delgado','P',1147),(3853,'Gaza','G',1147),(3854,'Inhambane','I',1147),(3855,'Manica','B',1147),(3856,'Numpula','N',1147),(3857,'Niaaea','A',1147),(3858,'Sofala','S',1147),(3859,'Tete','T',1147),(3860,'Zambezia','Q',1147),(3861,'Caprivi','CA',1148),(3862,'Erongo','ER',1148),(3863,'Hardap','HA',1148),(3864,'Karas','KA',1148),(3865,'Khomas','KH',1148),(3866,'Kunene','KU',1148),(3867,'Ohangwena','OW',1148),(3868,'Okavango','OK',1148),(3869,'Omaheke','OH',1148),(3870,'Omusati','OS',1148),(3871,'Oshana','ON',1148),(3872,'Oshikoto','OT',1148),(3873,'Otjozondjupa','OD',1148),(3874,'Niamey','8',1156),(3875,'Agadez','1',1156),(3876,'Diffa','2',1156),(3877,'Dosso','3',1156),(3878,'Maradi','4',1156),(3879,'Tahoua','S',1156),(3880,'Tillaberi','6',1156),(3881,'Zinder','7',1156),(3882,'Abuja Federal Capital Territory','FC',1157),(3883,'Abia','AB',1157),(3884,'Adamawa','AD',1157),(3885,'Akwa Ibom','AK',1157),(3886,'Anambra','AN',1157),(3887,'Bauchi','BA',1157),(3888,'Bayelsa','BY',1157),(3889,'Benue','BE',1157),(3890,'Borno','BO',1157),(3891,'Cross River','CR',1157),(3892,'Delta','DE',1157),(3893,'Ebonyi','EB',1157),(3894,'Edo','ED',1157),(3895,'Ekiti','EK',1157),(3896,'Enugu','EN',1157),(3897,'Gombe','GO',1157),(3898,'Imo','IM',1157),(3899,'Jigawa','JI',1157),(3900,'Kaduna','KD',1157),(3901,'Kano','KN',1157),(3902,'Katsina','KT',1157),(3903,'Kebbi','KE',1157),(3904,'Kogi','KO',1157),(3905,'Kwara','KW',1157),(3906,'Lagos','LA',1157),(3907,'Nassarawa','NA',1157),(3908,'Niger','NI',1157),(3909,'Ogun','OG',1157),(3910,'Ondo','ON',1157),(3911,'Osun','OS',1157),(3912,'Oyo','OY',1157),(3913,'Rivers','RI',1157),(3914,'Sokoto','SO',1157),(3915,'Taraba','TA',1157),(3916,'Yobe','YO',1157),(3917,'Zamfara','ZA',1157),(3918,'Boaco','BO',1155),(3919,'Carazo','CA',1155),(3920,'Chinandega','CI',1155),(3921,'Chontales','CO',1155),(3922,'Esteli','ES',1155),(3923,'Jinotega','JI',1155),(3924,'Leon','LE',1155),(3925,'Madriz','MD',1155),(3926,'Managua','MN',1155),(3927,'Masaya','MS',1155),(3928,'Matagalpa','MT',1155),(3929,'Nueva Segovia','NS',1155),(3930,'Rio San Juan','SJ',1155),(3931,'Rivas','RI',1155),(3932,'Atlantico Norte','AN',1155),(3933,'Atlantico Sur','AS',1155),(3934,'Drente','DR',1152),(3935,'Flevoland','FL',1152),(3936,'Friesland','FR',1152),(3937,'Gelderland','GL',1152),(3938,'Groningen','GR',1152),(3939,'Noord-Brabant','NB',1152),(3940,'Noord-Holland','NH',1152),(3941,'Overijssel','OV',1152),(3942,'Utrecht','UT',1152),(3943,'Zuid-Holland','ZH',1152),(3944,'Zeeland','ZL',1152),(3945,'Akershus','02',1161),(3946,'Aust-Agder','09',1161),(3947,'Buskerud','06',1161),(3948,'Finnmark','20',1161),(3949,'Hedmark','04',1161),(3950,'Hordaland','12',1161),(3951,'Møre og Romsdal','15',1161),(3952,'Nordland','18',1161),(3953,'Nord-Trøndelag','17',1161),(3954,'Oppland','05',1161),(3955,'Oslo','03',1161),(3956,'Rogaland','11',1161),(3957,'Sogn og Fjordane','14',1161),(3958,'Sør-Trøndelag','16',1161),(3959,'Telemark','06',1161),(3960,'Troms','19',1161),(3961,'Vest-Agder','10',1161),(3962,'Vestfold','07',1161),(3963,'Østfold','01',1161),(3964,'Jan Mayen','22',1161),(3965,'Svalbard','21',1161),(3966,'Auckland','AUK',1154),(3967,'Bay of Plenty','BOP',1154),(3968,'Canterbury','CAN',1154),(3969,'Gisborne','GIS',1154),(3970,'Hawkes Bay','HKB',1154),(3971,'Manawatu-Wanganui','MWT',1154),(3972,'Marlborough','MBH',1154),(3973,'Nelson','NSN',1154),(3974,'Northland','NTL',1154),(3975,'Otago','OTA',1154),(3976,'Southland','STL',1154),(3977,'Taranaki','TKI',1154),(3978,'Tasman','TAS',1154),(3979,'Waikato','WKO',1154),(3980,'Wellington','WGN',1154),(3981,'West Coast','WTC',1154),(3982,'Ad Dakhillyah','DA',1162),(3983,'Al Batinah','BA',1162),(3984,'Al Janblyah','JA',1162),(3985,'Al Wusta','WU',1162),(3986,'Ash Sharqlyah','SH',1162),(3987,'Az Zahirah','ZA',1162),(3988,'Masqat','MA',1162),(3989,'Musandam','MU',1162),(3990,'Bocas del Toro','1',1166),(3991,'Cocle','2',1166),(3992,'Chiriqui','4',1166),(3993,'Darien','5',1166),(3994,'Herrera','6',1166),(3995,'Loa Santoa','7',1166),(3996,'Panama','8',1166),(3997,'Veraguas','9',1166),(3998,'Comarca de San Blas','Q',1166),(3999,'El Callao','CAL',1169),(4000,'Ancash','ANC',1169),(4001,'Apurimac','APU',1169),(4002,'Arequipa','ARE',1169),(4003,'Ayacucho','AYA',1169),(4004,'Cajamarca','CAJ',1169),(4005,'Cuzco','CUS',1169),(4006,'Huancavelica','HUV',1169),(4007,'Huanuco','HUC',1169),(4008,'Ica','ICA',1169),(4009,'Junin','JUN',1169),(4010,'La Libertad','LAL',1169),(4011,'Lambayeque','LAM',1169),(4012,'Lima','LIM',1169),(4013,'Loreto','LOR',1169),(4014,'Madre de Dios','MDD',1169),(4015,'Moquegua','MOQ',1169),(4016,'Pasco','PAS',1169),(4017,'Piura','PIU',1169),(4018,'Puno','PUN',1169),(4019,'San Martin','SAM',1169),(4020,'Tacna','TAC',1169),(4021,'Tumbes','TUM',1169),(4022,'Ucayali','UCA',1169),(4023,'National Capital District (Port Moresby)','NCD',1167),(4024,'Chimbu','CPK',1167),(4025,'Eastern Highlands','EHG',1167),(4026,'East New Britain','EBR',1167),(4027,'East Sepik','ESW',1167),(4028,'Enga','EPW',1167),(4029,'Gulf','GPK',1167),(4030,'Madang','MPM',1167),(4031,'Manus','MRL',1167),(4032,'Milne Bay','MBA',1167),(4033,'Morobe','MPL',1167),(4034,'New Ireland','NIK',1167),(4035,'North Solomons','NSA',1167),(4036,'Santaun','SAN',1167),(4037,'Southern Highlands','SHM',1167),(4038,'Western Highlands','WHM',1167),(4039,'West New Britain','WBK',1167),(4040,'Abra','ABR',1170),(4041,'Agusan del Norte','AGN',1170),(4042,'Agusan del Sur','AGS',1170),(4043,'Aklan','AKL',1170),(4044,'Albay','ALB',1170),(4045,'Antique','ANT',1170),(4046,'Apayao','APA',1170),(4047,'Aurora','AUR',1170),(4048,'Basilan','BAS',1170),(4049,'Bataan','BAN',1170),(4050,'Batanes','BTN',1170),(4051,'Batangas','BTG',1170),(4052,'Benguet','BEN',1170),(4053,'Biliran','BIL',1170),(4054,'Bohol','BOH',1170),(4055,'Bukidnon','BUK',1170),(4056,'Bulacan','BUL',1170),(4057,'Cagayan','CAG',1170),(4058,'Camarines Norte','CAN',1170),(4059,'Camarines Sur','CAS',1170),(4060,'Camiguin','CAM',1170),(4061,'Capiz','CAP',1170),(4062,'Catanduanes','CAT',1170),(4063,'Cavite','CAV',1170),(4064,'Cebu','CEB',1170),(4065,'Compostela Valley','COM',1170),(4066,'Davao','DAV',1170),(4067,'Davao del Sur','DAS',1170),(4068,'Davao Oriental','DAO',1170),(4069,'Eastern Samar','EAS',1170),(4070,'Guimaras','GUI',1170),(4071,'Ifugao','IFU',1170),(4072,'Ilocos Norte','ILN',1170),(4073,'Ilocos Sur','ILS',1170),(4074,'Iloilo','ILI',1170),(4075,'Isabela','ISA',1170),(4076,'Kalinga-Apayso','KAL',1170),(4077,'Laguna','LAG',1170),(4078,'Lanao del Norte','LAN',1170),(4079,'Lanao del Sur','LAS',1170),(4080,'La Union','LUN',1170),(4081,'Leyte','LEY',1170),(4082,'Maguindanao','MAG',1170),(4083,'Marinduque','MAD',1170),(4084,'Masbate','MAS',1170),(4085,'Mindoro Occidental','MDC',1170),(4086,'Mindoro Oriental','MDR',1170),(4087,'Misamis Occidental','MSC',1170),(4088,'Misamis Oriental','MSR',1170),(4089,'Mountain Province','MOU',1170),(4090,'Negroe Occidental','NEC',1170),(4091,'Negros Oriental','NER',1170),(4092,'North Cotabato','NCO',1170),(4093,'Northern Samar','NSA',1170),(4094,'Nueva Ecija','NUE',1170),(4095,'Nueva Vizcaya','NUV',1170),(4096,'Palawan','PLW',1170),(4097,'Pampanga','PAM',1170),(4098,'Pangasinan','PAN',1170),(4099,'Quezon','QUE',1170),(4100,'Quirino','QUI',1170),(4101,'Rizal','RIZ',1170),(4102,'Romblon','ROM',1170),(4103,'Sarangani','SAR',1170),(4104,'Siquijor','SIG',1170),(4105,'Sorsogon','SOR',1170),(4106,'South Cotabato','SCO',1170),(4107,'Southern Leyte','SLE',1170),(4108,'Sultan Kudarat','SUK',1170),(4109,'Sulu','SLU',1170),(4110,'Surigao del Norte','SUN',1170),(4111,'Surigao del Sur','SUR',1170),(4112,'Tarlac','TAR',1170),(4113,'Tawi-Tawi','TAW',1170),(4114,'Western Samar','WSA',1170),(4115,'Zambales','ZMB',1170),(4116,'Zamboanga del Norte','ZAN',1170),(4117,'Zamboanga del Sur','ZAS',1170),(4118,'Zamboanga Sibiguey','ZSI',1170),(4119,'Islamabad Federal Capital Area','IS',1163),(4120,'Baluchistan','BA',1163),(4121,'Khyber Pakhtun Khawa','NW',1163),(4122,'Sindh','SD',1163),(4123,'Federally Administered Tribal Areas','TA',1163),(4124,'Azad Kashmir','JK',1163),(4125,'Gilgit-Baltistan','NA',1163),(4126,'Aveiro','01',1173),(4127,'Beja','02',1173),(4128,'Braga','03',1173),(4129,'Bragança','04',1173),(4130,'Castelo Branco','05',1173),(4131,'Coimbra','06',1173),(4132,'Évora','07',1173),(4133,'Faro','08',1173),(4134,'Guarda','09',1173),(4135,'Leiria','10',1173),(4136,'Lisboa','11',1173),(4137,'Portalegre','12',1173),(4138,'Porto','13',1173),(4139,'Santarém','14',1173),(4140,'Setúbal','15',1173),(4141,'Viana do Castelo','16',1173),(4142,'Vila Real','17',1173),(4143,'Viseu','18',1173),(4144,'Região Autónoma dos Açores','20',1173),(4145,'Região Autónoma da Madeira','30',1173),(4146,'Asuncion','ASU',1168),(4147,'Alto Paraguay','16',1168),(4148,'Alto Parana','10',1168),(4149,'Amambay','13',1168),(4150,'Boqueron','19',1168),(4151,'Caeguazu','5',1168),(4152,'Caazapl','6',1168),(4153,'Canindeyu','14',1168),(4154,'Concepcion','1',1168),(4155,'Cordillera','3',1168),(4156,'Guaira','4',1168),(4157,'Itapua','7',1168),(4158,'Miaiones','8',1168),(4159,'Neembucu','12',1168),(4160,'Paraguari','9',1168),(4161,'Presidente Hayes','15',1168),(4162,'San Pedro','2',1168),(4163,'Ad Dawhah','DA',1175),(4164,'Al Ghuwayriyah','GH',1175),(4165,'Al Jumayliyah','JU',1175),(4166,'Al Khawr','KH',1175),(4167,'Al Wakrah','WA',1175),(4168,'Ar Rayyan','RA',1175),(4169,'Jariyan al Batnah','JB',1175),(4170,'Madinat ash Shamal','MS',1175),(4171,'Umm Salal','US',1175),(4172,'Bucuresti','B',1176),(4173,'Alba','AB',1176),(4174,'Arad','AR',1176),(4175,'Argeș','AG',1176),(4176,'Bacău','BC',1176),(4177,'Bihor','BH',1176),(4178,'Bistrița-Năsăud','BN',1176),(4179,'Botoșani','BT',1176),(4180,'Brașov','BV',1176),(4181,'Brăila','BR',1176),(4182,'Buzău','BZ',1176),(4183,'Caraș-Severin','CS',1176),(4184,'Călărași','CL',1176),(4185,'Cluj','CJ',1176),(4186,'Constanța','CT',1176),(4187,'Covasna','CV',1176),(4188,'Dâmbovița','DB',1176),(4189,'Dolj','DJ',1176),(4190,'Galați','GL',1176),(4191,'Giurgiu','GR',1176),(4192,'Gorj','GJ',1176),(4193,'Harghita','HR',1176),(4194,'Hunedoara','HD',1176),(4195,'Ialomița','IL',1176),(4196,'Iași','IS',1176),(4197,'Ilfov','IF',1176),(4198,'Maramureș','MM',1176),(4199,'Mehedinți','MH',1176),(4200,'Mureș','MS',1176),(4201,'Neamț','NT',1176),(4202,'Olt','OT',1176),(4203,'Prahova','PH',1176),(4204,'Satu Mare','SM',1176),(4205,'Sălaj','SJ',1176),(4206,'Sibiu','SB',1176),(4207,'Suceava','SV',1176),(4208,'Teleorman','TR',1176),(4209,'Timiș','TM',1176),(4210,'Tulcea','TL',1176),(4211,'Vaslui','VS',1176),(4212,'Vâlcea','VL',1176),(4213,'Vrancea','VN',1176),(4214,'Adygeya, Respublika','AD',1177),(4215,'Altay, Respublika','AL',1177),(4216,'Bashkortostan, Respublika','BA',1177),(4217,'Buryatiya, Respublika','BU',1177),(4218,'Chechenskaya Respublika','CE',1177),(4219,'Chuvashskaya Respublika','CU',1177),(4220,'Dagestan, Respublika','DA',1177),(4221,'Ingushskaya Respublika','IN',1177),(4222,'Kabardino-Balkarskaya','KB',1177),(4223,'Kalmykiya, Respublika','KL',1177),(4224,'Karachayevo-Cherkesskaya Respublika','KC',1177),(4225,'Kareliya, Respublika','KR',1177),(4226,'Khakasiya, Respublika','KK',1177),(4227,'Komi, Respublika','KO',1177),(4228,'Mariy El, Respublika','ME',1177),(4229,'Mordoviya, Respublika','MO',1177),(4230,'Sakha, Respublika [Yakutiya]','SA',1177),(4231,'Severnaya Osetiya, Respublika','SE',1177),(4232,'Tatarstan, Respublika','TA',1177),(4233,'Tyva, Respublika [Tuva]','TY',1177),(4234,'Udmurtskaya Respublika','UD',1177),(4235,'Altayskiy kray','ALT',1177),(4236,'Khabarovskiy kray','KHA',1177),(4237,'Krasnodarskiy kray','KDA',1177),(4238,'Krasnoyarskiy kray','KYA',1177),(4239,'Primorskiy kray','PRI',1177),(4240,'Stavropol\'skiy kray','STA',1177),(4241,'Amurskaya oblast\'','AMU',1177),(4242,'Arkhangel\'skaya oblast\'','ARK',1177),(4243,'Astrakhanskaya oblast\'','AST',1177),(4244,'Belgorodskaya oblast\'','BEL',1177),(4245,'Bryanskaya oblast\'','BRY',1177),(4246,'Chelyabinskaya oblast\'','CHE',1177),(4247,'Zabaykalsky Krai\'','ZSK',1177),(4248,'Irkutskaya oblast\'','IRK',1177),(4249,'Ivanovskaya oblast\'','IVA',1177),(4250,'Kaliningradskaya oblast\'','KGD',1177),(4251,'Kaluzhskaya oblast\'','KLU',1177),(4252,'Kamchatka Krai\'','KAM',1177),(4253,'Kemerovskaya oblast\'','KEM',1177),(4254,'Kirovskaya oblast\'','KIR',1177),(4255,'Kostromskaya oblast\'','KOS',1177),(4256,'Kurganskaya oblast\'','KGN',1177),(4257,'Kurskaya oblast\'','KRS',1177),(4258,'Leningradskaya oblast\'','LEN',1177),(4259,'Lipetskaya oblast\'','LIP',1177),(4260,'Magadanskaya oblast\'','MAG',1177),(4261,'Moskovskaya oblast\'','MOS',1177),(4262,'Murmanskaya oblast\'','MUR',1177),(4263,'Nizhegorodskaya oblast\'','NIZ',1177),(4264,'Novgorodskaya oblast\'','NGR',1177),(4265,'Novosibirskaya oblast\'','NVS',1177),(4266,'Omskaya oblast\'','OMS',1177),(4267,'Orenburgskaya oblast\'','ORE',1177),(4268,'Orlovskaya oblast\'','ORL',1177),(4269,'Penzenskaya oblast\'','PNZ',1177),(4270,'Perm krai\'','PEK',1177),(4271,'Pskovskaya oblast\'','PSK',1177),(4272,'Rostovskaya oblast\'','ROS',1177),(4273,'Ryazanskaya oblast\'','RYA',1177),(4274,'Sakhalinskaya oblast\'','SAK',1177),(4275,'Samarskaya oblast\'','SAM',1177),(4276,'Saratovskaya oblast\'','SAR',1177),(4277,'Smolenskaya oblast\'','SMO',1177),(4278,'Sverdlovskaya oblast\'','SVE',1177),(4279,'Tambovskaya oblast\'','TAM',1177),(4280,'Tomskaya oblast\'','TOM',1177),(4281,'Tul\'skaya oblast\'','TUL',1177),(4282,'Tverskaya oblast\'','TVE',1177),(4283,'Tyumenskaya oblast\'','TYU',1177),(4284,'Ul\'yanovskaya oblast\'','ULY',1177),(4285,'Vladimirskaya oblast\'','VLA',1177),(4286,'Volgogradskaya oblast\'','VGG',1177),(4287,'Vologodskaya oblast\'','VLG',1177),(4288,'Voronezhskaya oblast\'','VOR',1177),(4289,'Yaroslavskaya oblast\'','YAR',1177),(4290,'Moskva','MOW',1177),(4291,'Sankt-Peterburg','SPE',1177),(4292,'Yevreyskaya avtonomnaya oblast\'','YEV',1177),(4294,'Chukotskiy avtonomnyy okrug','CHU',1177),(4296,'Khanty-Mansiyskiy avtonomnyy okrug','KHM',1177),(4299,'Nenetskiy avtonomnyy okrug','NEN',1177),(4302,'Yamalo-Nenetskiy avtonomnyy okrug','YAN',1177),(4303,'Butare','C',1178),(4304,'Byumba','I',1178),(4305,'Cyangugu','E',1178),(4306,'Gikongoro','D',1178),(4307,'Gisenyi','G',1178),(4308,'Gitarama','B',1178),(4309,'Kibungo','J',1178),(4310,'Kibuye','F',1178),(4311,'Kigali-Rural Kigali y\' Icyaro','K',1178),(4312,'Kigali-Ville Kigali Ngari','L',1178),(4313,'Mutara','M',1178),(4314,'Ruhengeri','H',1178),(4315,'Al Bahah','11',1187),(4316,'Al Hudud Ash Shamaliyah','08',1187),(4317,'Al Jawf','12',1187),(4318,'Al Madinah','03',1187),(4319,'Al Qasim','05',1187),(4320,'Ar Riyad','01',1187),(4321,'Asir','14',1187),(4322,'Ha\'il','06',1187),(4323,'Jlzan','09',1187),(4324,'Makkah','02',1187),(4325,'Najran','10',1187),(4326,'Tabuk','07',1187),(4327,'Capital Territory (Honiara)','CT',1194),(4328,'Guadalcanal','GU',1194),(4329,'Isabel','IS',1194),(4330,'Makira','MK',1194),(4331,'Malaita','ML',1194),(4332,'Temotu','TE',1194),(4333,'A\'ali an Nil','23',1200),(4334,'Al Bah al Ahmar','26',1200),(4335,'Al Buhayrat','18',1200),(4336,'Al Jazirah','07',1200),(4337,'Al Khartum','03',1200),(4338,'Al Qadarif','06',1200),(4339,'Al Wahdah','22',1200),(4340,'An Nil','04',1200),(4341,'An Nil al Abyaq','08',1200),(4342,'An Nil al Azraq','24',1200),(4343,'Ash Shamallyah','01',1200),(4344,'Bahr al Jabal','17',1200),(4345,'Gharb al Istiwa\'iyah','16',1200),(4346,'Gharb Ba~r al Ghazal','14',1200),(4347,'Gharb Darfur','12',1200),(4348,'Gharb Kurdufan','10',1200),(4349,'Janub Darfur','11',1200),(4350,'Janub Rurdufan','13',1200),(4351,'Jnqall','20',1200),(4352,'Kassala','05',1200),(4353,'Shamal Batr al Ghazal','15',1200),(4354,'Shamal Darfur','02',1200),(4355,'Shamal Kurdufan','09',1200),(4356,'Sharq al Istiwa\'iyah','19',1200),(4357,'Sinnar','25',1200),(4358,'Warab','21',1200),(4359,'Blekinge län','K',1204),(4360,'Dalarnas län','W',1204),(4361,'Gotlands län','I',1204),(4362,'Gävleborgs län','X',1204),(4363,'Hallands län','N',1204),(4364,'Jämtlands län','Z',1204),(4365,'Jönkopings län','F',1204),(4366,'Kalmar län','H',1204),(4367,'Kronobergs län','G',1204),(4368,'Norrbottens län','BD',1204),(4369,'Skåne län','M',1204),(4370,'Stockholms län','AB',1204),(4371,'Södermanlands län','D',1204),(4372,'Uppsala län','C',1204),(4373,'Värmlands län','S',1204),(4374,'Västerbottens län','AC',1204),(4375,'Västernorrlands län','Y',1204),(4376,'Västmanlands län','U',1204),(4377,'Västra Götalands län','Q',1204),(4378,'Örebro län','T',1204),(4379,'Östergötlands län','E',1204),(4380,'Saint Helena','SH',1180),(4381,'Ascension','AC',1180),(4382,'Tristan da Cunha','TA',1180),(4383,'Ajdovščina','001',1193),(4384,'Beltinci','002',1193),(4385,'Benedikt','148',1193),(4386,'Bistrica ob Sotli','149',1193),(4387,'Bled','003',1193),(4388,'Bloke','150',1193),(4389,'Bohinj','004',1193),(4390,'Borovnica','005',1193),(4391,'Bovec','006',1193),(4392,'Braslovče','151',1193),(4393,'Brda','007',1193),(4394,'Brezovica','008',1193),(4395,'Brežice','009',1193),(4396,'Cankova','152',1193),(4397,'Celje','011',1193),(4398,'Cerklje na Gorenjskem','012',1193),(4399,'Cerknica','013',1193),(4400,'Cerkno','014',1193),(4401,'Cerkvenjak','153',1193),(4402,'Črenšovci','015',1193),(4403,'Črna na Koroškem','016',1193),(4404,'Črnomelj','017',1193),(4405,'Destrnik','018',1193),(4406,'Divača','019',1193),(4407,'Dobje','154',1193),(4408,'Dobrepolje','020',1193),(4409,'Dobrna','155',1193),(4410,'Dobrova-Polhov Gradec','021',1193),(4411,'Dobrovnik','156',1193),(4412,'Dol pri Ljubljani','022',1193),(4413,'Dolenjske Toplice','157',1193),(4414,'Domžale','023',1193),(4415,'Dornava','024',1193),(4416,'Dravograd','025',1193),(4417,'Duplek','026',1193),(4418,'Gorenja vas-Poljane','027',1193),(4419,'Gorišnica','028',1193),(4420,'Gornja Radgona','029',1193),(4421,'Gornji Grad','030',1193),(4422,'Gornji Petrovci','031',1193),(4423,'Grad','158',1193),(4424,'Grosuplje','032',1193),(4425,'Hajdina','159',1193),(4426,'Hoče-Slivnica','160',1193),(4427,'Hodoš','161',1193),(4428,'Horjul','162',1193),(4429,'Hrastnik','034',1193),(4430,'Hrpelje-Kozina','035',1193),(4431,'Idrija','036',1193),(4432,'Ig','037',1193),(4433,'Ilirska Bistrica','038',1193),(4434,'Ivančna Gorica','039',1193),(4435,'Izola','040',1193),(4436,'Jesenice','041',1193),(4437,'Jezersko','163',1193),(4438,'Juršinci','042',1193),(4439,'Kamnik','043',1193),(4440,'Kanal','044',1193),(4441,'Kidričevo','045',1193),(4442,'Kobarid','046',1193),(4443,'Kobilje','047',1193),(4444,'Kočevje','048',1193),(4445,'Komen','049',1193),(4446,'Komenda','164',1193),(4447,'Koper','050',1193),(4448,'Kostel','165',1193),(4449,'Kozje','051',1193),(4450,'Kranj','052',1193),(4451,'Kranjska Gora','053',1193),(4452,'Križevci','166',1193),(4453,'Krško','054',1193),(4454,'Kungota','055',1193),(4455,'Kuzma','056',1193),(4456,'Laško','057',1193),(4457,'Lenart','058',1193),(4458,'Lendava','059',1193),(4459,'Litija','060',1193),(4460,'Ljubljana','061',1193),(4461,'Ljubno','062',1193),(4462,'Ljutomer','063',1193),(4463,'Logatec','064',1193),(4464,'Loška dolina','065',1193),(4465,'Loški Potok','066',1193),(4466,'Lovrenc na Pohorju','167',1193),(4467,'Luče','067',1193),(4468,'Lukovica','068',1193),(4469,'Majšperk','069',1193),(4470,'Maribor','070',1193),(4471,'Markovci','168',1193),(4472,'Medvode','071',1193),(4473,'Mengeš','072',1193),(4474,'Metlika','073',1193),(4475,'Mežica','074',1193),(4476,'Miklavž na Dravskem polju','169',1193),(4477,'Miren-Kostanjevica','075',1193),(4478,'Mirna Peč','170',1193),(4479,'Mislinja','076',1193),(4480,'Moravče','077',1193),(4481,'Moravske Toplice','078',1193),(4482,'Mozirje','079',1193),(4483,'Murska Sobota','080',1193),(4484,'Muta','081',1193),(4485,'Naklo','082',1193),(4486,'Nazarje','083',1193),(4487,'Nova Gorica','084',1193),(4488,'Novo mesto','085',1193),(4489,'Sveta Ana','181',1193),(4490,'Sveti Andraž v Slovenskih goricah','182',1193),(4491,'Sveti Jurij','116',1193),(4492,'Šalovci','033',1193),(4493,'Šempeter-Vrtojba','183',1193),(4494,'Šenčur','117',1193),(4495,'Šentilj','118',1193),(4496,'Šentjernej','119',1193),(4497,'Šentjur','120',1193),(4498,'Škocjan','121',1193),(4499,'Škofja Loka','122',1193),(4500,'Škofljica','123',1193),(4501,'Šmarje pri Jelšah','124',1193),(4502,'Šmartno ob Paki','125',1193),(4503,'Šmartno pri Litiji','194',1193),(4504,'Šoštanj','126',1193),(4505,'Štore','127',1193),(4506,'Tabor','184',1193),(4507,'Tišina','010',1193),(4508,'Tolmin','128',1193),(4509,'Trbovlje','129',1193),(4510,'Trebnje','130',1193),(4511,'Trnovska vas','185',1193),(4512,'Tržič','131',1193),(4513,'Trzin','186',1193),(4514,'Turnišče','132',1193),(4515,'Velenje','133',1193),(4516,'Velika Polana','187',1193),(4517,'Velike Lašče','134',1193),(4518,'Veržej','188',1193),(4519,'Videm','135',1193),(4520,'Vipava','136',1193),(4521,'Vitanje','137',1193),(4522,'Vojnik','138',1193),(4523,'Vransko','189',1193),(4524,'Vrhnika','140',1193),(4525,'Vuzenica','141',1193),(4526,'Zagorje ob Savi','142',1193),(4527,'Zavrč','143',1193),(4528,'Zreče','144',1193),(4529,'Žalec','190',1193),(4530,'Železniki','146',1193),(4531,'Žetale','191',1193),(4532,'Žiri','147',1193),(4533,'Žirovnica','192',1193),(4534,'Žužemberk','193',1193),(4535,'Banskobystrický kraj','BC',1192),(4536,'Bratislavský kraj','BL',1192),(4537,'Košický kraj','KI',1192),(4538,'Nitriansky kraj','NJ',1192),(4539,'Prešovský kraj','PV',1192),(4540,'Trenčiansky kraj','TC',1192),(4541,'Trnavský kraj','TA',1192),(4542,'Žilinský kraj','ZI',1192),(4543,'Western Area (Freetown)','W',1190),(4544,'Dakar','DK',1188),(4545,'Diourbel','DB',1188),(4546,'Fatick','FK',1188),(4547,'Kaolack','KL',1188),(4548,'Kolda','KD',1188),(4549,'Louga','LG',1188),(4550,'Matam','MT',1188),(4551,'Saint-Louis','SL',1188),(4552,'Tambacounda','TC',1188),(4553,'Thies','TH',1188),(4554,'Ziguinchor','ZG',1188),(4555,'Awdal','AW',1195),(4556,'Bakool','BK',1195),(4557,'Banaadir','BN',1195),(4558,'Bay','BY',1195),(4559,'Galguduud','GA',1195),(4560,'Gedo','GE',1195),(4561,'Hiirsan','HI',1195),(4562,'Jubbada Dhexe','JD',1195),(4563,'Jubbada Hoose','JH',1195),(4564,'Mudug','MU',1195),(4565,'Nugaal','NU',1195),(4566,'Saneag','SA',1195),(4567,'Shabeellaha Dhexe','SD',1195),(4568,'Shabeellaha Hoose','SH',1195),(4569,'Sool','SO',1195),(4570,'Togdheer','TO',1195),(4571,'Woqooyi Galbeed','WO',1195),(4572,'Brokopondo','BR',1201),(4573,'Commewijne','CM',1201),(4574,'Coronie','CR',1201),(4575,'Marowijne','MA',1201),(4576,'Nickerie','NI',1201),(4577,'Paramaribo','PM',1201),(4578,'Saramacca','SA',1201),(4579,'Sipaliwini','SI',1201),(4580,'Wanica','WA',1201),(4581,'Principe','P',1207),(4582,'Sao Tome','S',1207),(4583,'Ahuachapan','AH',1066),(4584,'Cabanas','CA',1066),(4585,'Cuscatlan','CU',1066),(4586,'Chalatenango','CH',1066),(4587,'Morazan','MO',1066),(4588,'San Miguel','SM',1066),(4589,'San Salvador','SS',1066),(4590,'Santa Ana','SA',1066),(4591,'San Vicente','SV',1066),(4592,'Sonsonate','SO',1066),(4593,'Usulutan','US',1066),(4594,'Al Hasakah','HA',1206),(4595,'Al Ladhiqiyah','LA',1206),(4596,'Al Qunaytirah','QU',1206),(4597,'Ar Raqqah','RA',1206),(4598,'As Suwayda\'','SU',1206),(4599,'Dar\'a','DR',1206),(4600,'Dayr az Zawr','DY',1206),(4601,'Dimashq','DI',1206),(4602,'Halab','HL',1206),(4603,'Hamah','HM',1206),(4604,'Jim\'','HI',1206),(4605,'Idlib','ID',1206),(4606,'Rif Dimashq','RD',1206),(4607,'Tarts','TA',1206),(4608,'Hhohho','HH',1203),(4609,'Lubombo','LU',1203),(4610,'Manzini','MA',1203),(4611,'Shiselweni','SH',1203),(4612,'Batha','BA',1043),(4613,'Biltine','BI',1043),(4614,'Borkou-Ennedi-Tibesti','BET',1043),(4615,'Chari-Baguirmi','CB',1043),(4616,'Guera','GR',1043),(4617,'Kanem','KA',1043),(4618,'Lac','LC',1043),(4619,'Logone-Occidental','LO',1043),(4620,'Logone-Oriental','LR',1043),(4621,'Mayo-Kebbi','MK',1043),(4622,'Moyen-Chari','MC',1043),(4623,'Ouaddai','OD',1043),(4624,'Salamat','SA',1043),(4625,'Tandjile','TA',1043),(4626,'Kara','K',1214),(4627,'Maritime (Region)','M',1214),(4628,'Savannes','S',1214),(4629,'Krung Thep Maha Nakhon Bangkok','10',1211),(4630,'Phatthaya','S',1211),(4631,'Amnat Charoen','37',1211),(4632,'Ang Thong','15',1211),(4633,'Buri Ram','31',1211),(4634,'Chachoengsao','24',1211),(4635,'Chai Nat','18',1211),(4636,'Chaiyaphum','36',1211),(4637,'Chanthaburi','22',1211),(4638,'Chiang Mai','50',1211),(4639,'Chiang Rai','57',1211),(4640,'Chon Buri','20',1211),(4641,'Chumphon','86',1211),(4642,'Kalasin','46',1211),(4643,'Kamphasng Phet','62',1211),(4644,'Kanchanaburi','71',1211),(4645,'Khon Kaen','40',1211),(4646,'Krabi','81',1211),(4647,'Lampang','52',1211),(4648,'Lamphun','51',1211),(4649,'Loei','42',1211),(4650,'Lop Buri','16',1211),(4651,'Mae Hong Son','58',1211),(4652,'Maha Sarakham','44',1211),(4653,'Mukdahan','49',1211),(4654,'Nakhon Nayok','26',1211),(4655,'Nakhon Pathom','73',1211),(4656,'Nakhon Phanom','48',1211),(4657,'Nakhon Ratchasima','30',1211),(4658,'Nakhon Sawan','60',1211),(4659,'Nakhon Si Thammarat','80',1211),(4660,'Nan','55',1211),(4661,'Narathiwat','96',1211),(4662,'Nong Bua Lam Phu','39',1211),(4663,'Nong Khai','43',1211),(4664,'Nonthaburi','12',1211),(4665,'Pathum Thani','13',1211),(4666,'Pattani','94',1211),(4667,'Phangnga','82',1211),(4668,'Phatthalung','93',1211),(4669,'Phayao','56',1211),(4670,'Phetchabun','67',1211),(4671,'Phetchaburi','76',1211),(4672,'Phichit','66',1211),(4673,'Phitsanulok','65',1211),(4674,'Phrae','54',1211),(4675,'Phra Nakhon Si Ayutthaya','14',1211),(4676,'Phuket','83',1211),(4677,'Prachin Buri','25',1211),(4678,'Prachuap Khiri Khan','77',1211),(4679,'Ranong','85',1211),(4680,'Ratchaburi','70',1211),(4681,'Rayong','21',1211),(4682,'Roi Et','45',1211),(4683,'Sa Kaeo','27',1211),(4684,'Sakon Nakhon','47',1211),(4685,'Samut Prakan','11',1211),(4686,'Samut Sakhon','74',1211),(4687,'Samut Songkhram','75',1211),(4688,'Saraburi','19',1211),(4689,'Satun','91',1211),(4690,'Sing Buri','17',1211),(4691,'Si Sa Ket','33',1211),(4692,'Songkhla','90',1211),(4693,'Sukhothai','64',1211),(4694,'Suphan Buri','72',1211),(4695,'Surat Thani','84',1211),(4696,'Surin','32',1211),(4697,'Tak','63',1211),(4698,'Trang','92',1211),(4699,'Trat','23',1211),(4700,'Ubon Ratchathani','34',1211),(4701,'Udon Thani','41',1211),(4702,'Uthai Thani','61',1211),(4703,'Uttaradit','53',1211),(4704,'Yala','95',1211),(4705,'Yasothon','35',1211),(4706,'Sughd','SU',1209),(4707,'Khatlon','KT',1209),(4708,'Gorno-Badakhshan','GB',1209),(4709,'Ahal','A',1220),(4710,'Balkan','B',1220),(4711,'Dasoguz','D',1220),(4712,'Lebap','L',1220),(4713,'Mary','M',1220),(4714,'Béja','31',1218),(4715,'Ben Arous','13',1218),(4716,'Bizerte','23',1218),(4717,'Gabès','81',1218),(4718,'Gafsa','71',1218),(4719,'Jendouba','32',1218),(4720,'Kairouan','41',1218),(4721,'Rasserine','42',1218),(4722,'Kebili','73',1218),(4723,'L\'Ariana','12',1218),(4724,'Le Ref','33',1218),(4725,'Mahdia','53',1218),(4726,'La Manouba','14',1218),(4727,'Medenine','82',1218),(4728,'Moneatir','52',1218),(4729,'Naboul','21',1218),(4730,'Sfax','61',1218),(4731,'Sidi Bouxid','43',1218),(4732,'Siliana','34',1218),(4733,'Sousse','51',1218),(4734,'Tataouine','83',1218),(4735,'Tozeur','72',1218),(4736,'Tunis','11',1218),(4737,'Zaghouan','22',1218),(4738,'Adana','01',1219),(4739,'Ad yaman','02',1219),(4740,'Afyon','03',1219),(4741,'Ag r','04',1219),(4742,'Aksaray','68',1219),(4743,'Amasya','05',1219),(4744,'Ankara','06',1219),(4745,'Antalya','07',1219),(4746,'Ardahan','75',1219),(4747,'Artvin','08',1219),(4748,'Aydin','09',1219),(4749,'Bal kesir','10',1219),(4750,'Bartin','74',1219),(4751,'Batman','72',1219),(4752,'Bayburt','69',1219),(4753,'Bilecik','11',1219),(4754,'Bingol','12',1219),(4755,'Bitlis','13',1219),(4756,'Bolu','14',1219),(4757,'Burdur','15',1219),(4758,'Bursa','16',1219),(4759,'Canakkale','17',1219),(4760,'Cankir','18',1219),(4761,'Corum','19',1219),(4762,'Denizli','20',1219),(4763,'Diyarbakir','21',1219),(4764,'Duzce','81',1219),(4765,'Edirne','22',1219),(4766,'Elazig','23',1219),(4767,'Erzincan','24',1219),(4768,'Erzurum','25',1219),(4769,'Eskis\'ehir','26',1219),(4770,'Gaziantep','27',1219),(4771,'Giresun','28',1219),(4772,'Gms\'hane','29',1219),(4773,'Hakkari','30',1219),(4774,'Hatay','31',1219),(4775,'Igidir','76',1219),(4776,'Isparta','32',1219),(4777,'Icel','33',1219),(4778,'Istanbul','34',1219),(4779,'Izmir','35',1219),(4780,'Kahramanmaras','46',1219),(4781,'Karabk','78',1219),(4782,'Karaman','70',1219),(4783,'Kars','36',1219),(4784,'Kastamonu','37',1219),(4785,'Kayseri','38',1219),(4786,'Kirikkale','71',1219),(4787,'Kirklareli','39',1219),(4788,'Kirs\'ehir','40',1219),(4789,'Kilis','79',1219),(4790,'Kocaeli','41',1219),(4791,'Konya','42',1219),(4792,'Ktahya','43',1219),(4793,'Malatya','44',1219),(4794,'Manisa','45',1219),(4795,'Mardin','47',1219),(4796,'Mugila','48',1219),(4797,'Mus','49',1219),(4798,'Nevs\'ehir','50',1219),(4799,'Nigide','51',1219),(4800,'Ordu','52',1219),(4801,'Osmaniye','80',1219),(4802,'Rize','53',1219),(4803,'Sakarya','54',1219),(4804,'Samsun','55',1219),(4805,'Siirt','56',1219),(4806,'Sinop','57',1219),(4807,'Sivas','58',1219),(4808,'S\'anliurfa','63',1219),(4809,'S\'rnak','73',1219),(4810,'Tekirdag','59',1219),(4811,'Tokat','60',1219),(4812,'Trabzon','61',1219),(4813,'Tunceli','62',1219),(4814,'Us\'ak','64',1219),(4815,'Van','65',1219),(4816,'Yalova','77',1219),(4817,'Yozgat','66',1219),(4818,'Zonguldak','67',1219),(4819,'Couva-Tabaquite-Talparo','CTT',1217),(4820,'Diego Martin','DMN',1217),(4821,'Eastern Tobago','ETO',1217),(4822,'Penal-Debe','PED',1217),(4823,'Princes Town','PRT',1217),(4824,'Rio Claro-Mayaro','RCM',1217),(4825,'Sangre Grande','SGE',1217),(4826,'San Juan-Laventille','SJL',1217),(4827,'Siparia','SIP',1217),(4828,'Tunapuna-Piarco','TUP',1217),(4829,'Western Tobago','WTO',1217),(4830,'Arima','ARI',1217),(4831,'Chaguanas','CHA',1217),(4832,'Point Fortin','PTF',1217),(4833,'Port of Spain','POS',1217),(4834,'San Fernando','SFO',1217),(4835,'Aileu','AL',1063),(4836,'Ainaro','AN',1063),(4837,'Bacucau','BA',1063),(4838,'Bobonaro','BO',1063),(4839,'Cova Lima','CO',1063),(4840,'Dili','DI',1063),(4841,'Ermera','ER',1063),(4842,'Laulem','LA',1063),(4843,'Liquica','LI',1063),(4844,'Manatuto','MT',1063),(4845,'Manafahi','MF',1063),(4846,'Oecussi','OE',1063),(4847,'Viqueque','VI',1063),(4848,'Changhua County','CHA',1208),(4849,'Chiayi County','CYQ',1208),(4850,'Hsinchu County','HSQ',1208),(4851,'Hualien County','HUA',1208),(4852,'Ilan County','ILA',1208),(4853,'Kaohsiung County','KHQ',1208),(4854,'Miaoli County','MIA',1208),(4855,'Nantou County','NAN',1208),(4856,'Penghu County','PEN',1208),(4857,'Pingtung County','PIF',1208),(4858,'Taichung County','TXQ',1208),(4859,'Tainan County','TNQ',1208),(4860,'Taipei County','TPQ',1208),(4861,'Taitung County','TTT',1208),(4862,'Taoyuan County','TAO',1208),(4863,'Yunlin County','YUN',1208),(4864,'Keelung City','KEE',1208),(4865,'Arusha','01',1210),(4866,'Dar-es-Salaam','02',1210),(4867,'Dodoma','03',1210),(4868,'Iringa','04',1210),(4869,'Kagera','05',1210),(4870,'Kaskazini Pemba','06',1210),(4871,'Kaskazini Unguja','07',1210),(4872,'Xigoma','08',1210),(4873,'Kilimanjaro','09',1210),(4874,'Rusini Pemba','10',1210),(4875,'Kusini Unguja','11',1210),(4876,'Lindi','12',1210),(4877,'Manyara','26',1210),(4878,'Mara','13',1210),(4879,'Mbeya','14',1210),(4880,'Mjini Magharibi','15',1210),(4881,'Morogoro','16',1210),(4882,'Mtwara','17',1210),(4883,'Pwani','19',1210),(4884,'Rukwa','20',1210),(4885,'Ruvuma','21',1210),(4886,'Shinyanga','22',1210),(4887,'Singida','23',1210),(4888,'Tabora','24',1210),(4889,'Tanga','25',1210),(4890,'Cherkas\'ka Oblast\'','71',1224),(4891,'Chernihivs\'ka Oblast\'','74',1224),(4892,'Chernivets\'ka Oblast\'','77',1224),(4893,'Dnipropetrovs\'ka Oblast\'','12',1224),(4894,'Donets\'ka Oblast\'','14',1224),(4895,'Ivano-Frankivs\'ka Oblast\'','26',1224),(4896,'Kharkivs\'ka Oblast\'','63',1224),(4897,'Khersons\'ka Oblast\'','65',1224),(4898,'Khmel\'nyts\'ka Oblast\'','68',1224),(4899,'Kirovohrads\'ka Oblast\'','35',1224),(4900,'Kyivs\'ka Oblast\'','32',1224),(4901,'Luhans\'ka Oblast\'','09',1224),(4902,'L\'vivs\'ka Oblast\'','46',1224),(4903,'Mykolaivs\'ka Oblast\'','48',1224),(4904,'Odes \'ka Oblast\'','51',1224),(4905,'Poltavs\'ka Oblast\'','53',1224),(4906,'Rivnens\'ka Oblast\'','56',1224),(4907,'Sums \'ka Oblast\'','59',1224),(4908,'Ternopil\'s\'ka Oblast\'','61',1224),(4909,'Vinnyts\'ka Oblast\'','05',1224),(4910,'Volyos\'ka Oblast\'','07',1224),(4911,'Zakarpats\'ka Oblast\'','21',1224),(4912,'Zaporiz\'ka Oblast\'','23',1224),(4913,'Zhytomyrs\'ka Oblast\'','18',1224),(4914,'Respublika Krym','43',1224),(4915,'Kyiv','30',1224),(4916,'Sevastopol','40',1224),(4917,'Adjumani','301',1223),(4918,'Apac','302',1223),(4919,'Arua','303',1223),(4920,'Bugiri','201',1223),(4921,'Bundibugyo','401',1223),(4922,'Bushenyi','402',1223),(4923,'Busia','202',1223),(4924,'Gulu','304',1223),(4925,'Hoima','403',1223),(4926,'Iganga','203',1223),(4927,'Jinja','204',1223),(4928,'Kabale','404',1223),(4929,'Kabarole','405',1223),(4930,'Kaberamaido','213',1223),(4931,'Kalangala','101',1223),(4932,'Kampala','102',1223),(4933,'Kamuli','205',1223),(4934,'Kamwenge','413',1223),(4935,'Kanungu','414',1223),(4936,'Kapchorwa','206',1223),(4937,'Kasese','406',1223),(4938,'Katakwi','207',1223),(4939,'Kayunga','112',1223),(4940,'Kibaale','407',1223),(4941,'Kiboga','103',1223),(4942,'Kisoro','408',1223),(4943,'Kitgum','305',1223),(4944,'Kotido','306',1223),(4945,'Kumi','208',1223),(4946,'Kyenjojo','415',1223),(4947,'Lira','307',1223),(4948,'Luwero','104',1223),(4949,'Masaka','105',1223),(4950,'Masindi','409',1223),(4951,'Mayuge','214',1223),(4952,'Mbale','209',1223),(4953,'Mbarara','410',1223),(4954,'Moroto','308',1223),(4955,'Moyo','309',1223),(4956,'Mpigi','106',1223),(4957,'Mubende','107',1223),(4958,'Mukono','108',1223),(4959,'Nakapiripirit','311',1223),(4960,'Nakasongola','109',1223),(4961,'Nebbi','310',1223),(4962,'Ntungamo','411',1223),(4963,'Pader','312',1223),(4964,'Pallisa','210',1223),(4965,'Rakai','110',1223),(4966,'Rukungiri','412',1223),(4967,'Sembabule','111',1223),(4968,'Sironko','215',1223),(4969,'Soroti','211',1223),(4970,'Tororo','212',1223),(4971,'Wakiso','113',1223),(4972,'Yumbe','313',1223),(4973,'Baker Island','81',1227),(4974,'Howland Island','84',1227),(4975,'Jarvis Island','86',1227),(4976,'Johnston Atoll','67',1227),(4977,'Kingman Reef','89',1227),(4978,'Midway Islands','71',1227),(4979,'Navassa Island','76',1227),(4980,'Palmyra Atoll','95',1227),(4981,'Wake Island','79',1227),(4982,'Artigsa','AR',1229),(4983,'Canelones','CA',1229),(4984,'Cerro Largo','CL',1229),(4985,'Colonia','CO',1229),(4986,'Durazno','DU',1229),(4987,'Flores','FS',1229),(4988,'Lavalleja','LA',1229),(4989,'Maldonado','MA',1229),(4990,'Montevideo','MO',1229),(4991,'Paysandu','PA',1229),(4992,'Rivera','RV',1229),(4993,'Rocha','RO',1229),(4994,'Salto','SA',1229),(4995,'Soriano','SO',1229),(4996,'Tacuarembo','TA',1229),(4997,'Treinta y Tres','TT',1229),(4998,'Toshkent (city)','TK',1230),(4999,'Qoraqalpogiston Respublikasi','QR',1230),(5000,'Andijon','AN',1230),(5001,'Buxoro','BU',1230),(5002,'Farg\'ona','FA',1230),(5003,'Jizzax','JI',1230),(5004,'Khorazm','KH',1230),(5005,'Namangan','NG',1230),(5006,'Navoiy','NW',1230),(5007,'Qashqadaryo','QA',1230),(5008,'Samarqand','SA',1230),(5009,'Sirdaryo','SI',1230),(5010,'Surxondaryo','SU',1230),(5011,'Toshkent','TO',1230),(5012,'Xorazm','XO',1230),(5013,'Distrito Federal','A',1232),(5014,'Anzoategui','B',1232),(5015,'Apure','C',1232),(5016,'Aragua','D',1232),(5017,'Barinas','E',1232),(5018,'Carabobo','G',1232),(5019,'Cojedes','H',1232),(5020,'Falcon','I',1232),(5021,'Guarico','J',1232),(5022,'Lara','K',1232),(5023,'Merida','L',1232),(5024,'Miranda','M',1232),(5025,'Monagas','N',1232),(5026,'Nueva Esparta','O',1232),(5027,'Portuguesa','P',1232),(5028,'Tachira','S',1232),(5029,'Trujillo','T',1232),(5030,'Vargas','X',1232),(5031,'Yaracuy','U',1232),(5032,'Zulia','V',1232),(5033,'Delta Amacuro','Y',1232),(5034,'Dependencias Federales','W',1232),(5035,'An Giang','44',1233),(5036,'Ba Ria - Vung Tau','43',1233),(5037,'Bac Can','53',1233),(5038,'Bac Giang','54',1233),(5039,'Bac Lieu','55',1233),(5040,'Bac Ninh','56',1233),(5041,'Ben Tre','50',1233),(5042,'Binh Dinh','31',1233),(5043,'Binh Duong','57',1233),(5044,'Binh Phuoc','58',1233),(5045,'Binh Thuan','40',1233),(5046,'Ca Mau','59',1233),(5047,'Can Tho','48',1233),(5048,'Cao Bang','04',1233),(5049,'Da Nang, thanh pho','60',1233),(5050,'Dong Nai','39',1233),(5051,'Dong Thap','45',1233),(5052,'Gia Lai','30',1233),(5053,'Ha Giang','03',1233),(5054,'Ha Nam','63',1233),(5055,'Ha Noi, thu do','64',1233),(5056,'Ha Tay','15',1233),(5057,'Ha Tinh','23',1233),(5058,'Hai Duong','61',1233),(5059,'Hai Phong, thanh pho','62',1233),(5060,'Hoa Binh','14',1233),(5061,'Ho Chi Minh, thanh pho [Sai Gon]','65',1233),(5062,'Hung Yen','66',1233),(5063,'Khanh Hoa','34',1233),(5064,'Kien Giang','47',1233),(5065,'Kon Tum','28',1233),(5066,'Lai Chau','01',1233),(5067,'Lam Dong','35',1233),(5068,'Lang Son','09',1233),(5069,'Lao Cai','02',1233),(5070,'Long An','41',1233),(5071,'Nam Dinh','67',1233),(5072,'Nghe An','22',1233),(5073,'Ninh Binh','18',1233),(5074,'Ninh Thuan','36',1233),(5075,'Phu Tho','68',1233),(5076,'Phu Yen','32',1233),(5077,'Quang Binh','24',1233),(5078,'Quang Nam','27',1233),(5079,'Quang Ngai','29',1233),(5080,'Quang Ninh','13',1233),(5081,'Quang Tri','25',1233),(5082,'Soc Trang','52',1233),(5083,'Son La','05',1233),(5084,'Tay Ninh','37',1233),(5085,'Thai Binh','20',1233),(5086,'Thai Nguyen','69',1233),(5087,'Thanh Hoa','21',1233),(5088,'Thua Thien-Hue','26',1233),(5089,'Tien Giang','46',1233),(5090,'Tra Vinh','51',1233),(5091,'Tuyen Quang','07',1233),(5092,'Vinh Long','49',1233),(5093,'Vinh Phuc','70',1233),(5094,'Yen Bai','06',1233),(5095,'Malampa','MAP',1231),(5096,'Penama','PAM',1231),(5097,'Sanma','SAM',1231),(5098,'Shefa','SEE',1231),(5099,'Tafea','TAE',1231),(5100,'Torba','TOB',1231),(5101,'A\'ana','AA',1185),(5102,'Aiga-i-le-Tai','AL',1185),(5103,'Atua','AT',1185),(5104,'Fa\'aaaleleaga','FA',1185),(5105,'Gaga\'emauga','GE',1185),(5106,'Gagaifomauga','GI',1185),(5107,'Palauli','PA',1185),(5108,'Satupa\'itea','SA',1185),(5109,'Tuamasaga','TU',1185),(5110,'Va\'a-o-Fonoti','VF',1185),(5111,'Vaisigano','VS',1185),(5112,'Crna Gora','CG',1243),(5113,'Srbija','SR',1242),(5114,'Kosovo-Metohija','KM',1242),(5115,'Vojvodina','VO',1242),(5116,'Abyan','AB',1237),(5117,'Adan','AD',1237),(5118,'Ad Dali','DA',1237),(5119,'Al Bayda\'','BA',1237),(5120,'Al Hudaydah','MU',1237),(5121,'Al Mahrah','MR',1237),(5122,'Al Mahwit','MW',1237),(5123,'Amran','AM',1237),(5124,'Dhamar','DH',1237),(5125,'Hadramawt','HD',1237),(5126,'Hajjah','HJ',1237),(5127,'Ibb','IB',1237),(5128,'Lahij','LA',1237),(5129,'Ma\'rib','MA',1237),(5130,'Sa\'dah','SD',1237),(5131,'San\'a\'','SN',1237),(5132,'Shabwah','SH',1237),(5133,'Ta\'izz','TA',1237),(5134,'Eastern Cape','EC',1196),(5135,'Free State','FS',1196),(5136,'Gauteng','GT',1196),(5137,'Kwazulu-Natal','NL',1196),(5138,'Mpumalanga','MP',1196),(5139,'Northern Cape','NC',1196),(5140,'Limpopo','NP',1196),(5141,'Western Cape','WC',1196),(5142,'Copperbelt','08',1239),(5143,'Luapula','04',1239),(5144,'Lusaka','09',1239),(5145,'North-Western','06',1239),(5146,'Bulawayo','BU',1240),(5147,'Harare','HA',1240),(5148,'Manicaland','MA',1240),(5149,'Mashonaland Central','MC',1240),(5150,'Mashonaland East','ME',1240),(5151,'Mashonaland West','MW',1240),(5152,'Masvingo','MV',1240),(5153,'Matabeleland North','MN',1240),(5154,'Matabeleland South','MS',1240),(5155,'Midlands','MI',1240),(5156,'South Karelia','SK',1075),(5157,'South Ostrobothnia','SO',1075),(5158,'Etelä-Savo','ES',1075),(5159,'Häme','HH',1075),(5160,'Itä-Uusimaa','IU',1075),(5161,'Kainuu','KA',1075),(5162,'Central Ostrobothnia','CO',1075),(5163,'Central Finland','CF',1075),(5164,'Kymenlaakso','KY',1075),(5165,'Lapland','LA',1075),(5166,'Tampere Region','TR',1075),(5167,'Ostrobothnia','OB',1075),(5168,'North Karelia','NK',1075),(5169,'Northern Ostrobothnia','NO',1075),(5170,'Northern Savo','NS',1075),(5171,'Päijät-Häme','PH',1075),(5172,'Satakunta','SK',1075),(5173,'Uusimaa','UM',1075),(5174,'South-West Finland','SW',1075),(5175,'Åland','AL',1075),(5176,'Limburg','LI',1152),(5177,'Central and Western','CW',1098),(5178,'Eastern','EA',1098),(5179,'Southern','SO',1098),(5180,'Wan Chai','WC',1098),(5181,'Kowloon City','KC',1098),(5182,'Kwun Tong','KU',1098),(5183,'Sham Shui Po','SS',1098),(5184,'Wong Tai Sin','WT',1098),(5185,'Yau Tsim Mong','YT',1098),(5186,'Islands','IS',1098),(5187,'Kwai Tsing','KI',1098),(5188,'North','NO',1098),(5189,'Sai Kung','SK',1098),(5190,'Sha Tin','ST',1098),(5191,'Tai Po','TP',1098),(5192,'Tsuen Wan','TW',1098),(5193,'Tuen Mun','TM',1098),(5194,'Yuen Long','YL',1098),(5195,'Manchester','MR',1108),(5196,'Al Manāmah (Al ‘Āşimah)','13',1016),(5197,'Al Janūbīyah','14',1016),(5199,'Al Wusţá','16',1016),(5200,'Ash Shamālīyah','17',1016),(5201,'Jenin','_A',1165),(5202,'Tubas','_B',1165),(5203,'Tulkarm','_C',1165),(5204,'Nablus','_D',1165),(5205,'Qalqilya','_E',1165),(5206,'Salfit','_F',1165),(5207,'Ramallah and Al-Bireh','_G',1165),(5208,'Jericho','_H',1165),(5209,'Jerusalem','_I',1165),(5210,'Bethlehem','_J',1165),(5211,'Hebron','_K',1165),(5212,'North Gaza','_L',1165),(5213,'Gaza','_M',1165),(5214,'Deir el-Balah','_N',1165),(5215,'Khan Yunis','_O',1165),(5216,'Rafah','_P',1165),(5217,'Brussels','BRU',1020),(5218,'Distrito Federal','DIF',1140),(5219,'Taichung City','TXG',1208),(5220,'Kaohsiung City','KHH',1208),(5221,'Taipei City','TPE',1208),(5222,'Chiayi City','CYI',1208),(5223,'Hsinchu City','HSZ',1208),(5224,'Tainan City','TNN',1208),(9000,'North West','NW',1196),(9986,'Tyne and Wear','TWR',1226),(9988,'Greater Manchester','GTM',1226),(9989,'Co Tyrone','TYR',1226),(9990,'West Yorkshire','WYK',1226),(9991,'South Yorkshire','SYK',1226),(9992,'Merseyside','MSY',1226),(9993,'Berkshire','BRK',1226),(9994,'West Midlands','WMD',1226),(9998,'West Glamorgan','WGM',1226),(9999,'London','LON',1226),(10000,'Carbonia-Iglesias','CI',1107),(10001,'Olbia-Tempio','OT',1107),(10002,'Medio Campidano','VS',1107),(10003,'Ogliastra','OG',1107),(10009,'Jura','39',1076),(10010,'Barletta-Andria-Trani','BT',1107),(10011,'Fermo','FM',1107),(10012,'Monza e Brianza','MB',1107),(10013,'Clwyd','CWD',1226),(10015,'South Glamorgan','SGM',1226),(10016,'Artibonite','AR',1094),(10017,'Centre','CE',1094),(10018,'Nippes','NI',1094),(10019,'Nord','ND',1094),(10020,'La Rioja','F',1010),(10021,'Andorra la Vella','07',1005),(10022,'Canillo','02',1005),(10023,'Encamp','03',1005),(10024,'Escaldes-Engordany','08',1005),(10025,'La Massana','04',1005),(10026,'Ordino','05',1005),(10027,'Sant Julia de Loria','06',1005),(10028,'Abaco Islands','AB',1212),(10029,'Andros Island','AN',1212),(10030,'Berry Islands','BR',1212),(10031,'Eleuthera','EL',1212),(10032,'Grand Bahama','GB',1212),(10033,'Rum Cay','RC',1212),(10034,'San Salvador Island','SS',1212),(10035,'Kongo central','01',1050),(10036,'Kwango','02',1050),(10037,'Kwilu','03',1050),(10038,'Mai-Ndombe','04',1050),(10039,'Kasai','05',1050),(10040,'Lulua','06',1050),(10041,'Lomami','07',1050),(10042,'Sankuru','08',1050),(10043,'Ituri','09',1050),(10044,'Haut-Uele','10',1050),(10045,'Tshopo','11',1050),(10046,'Bas-Uele','12',1050),(10047,'Nord-Ubangi','13',1050),(10048,'Mongala','14',1050),(10049,'Sud-Ubangi','15',1050),(10050,'Tshuapa','16',1050),(10051,'Haut-Lomami','17',1050),(10052,'Lualaba','18',1050),(10053,'Haut-Katanga','19',1050),(10054,'Tanganyika','20',1050),(10055,'Toledo','TO',1198),(10056,'Córdoba','CO',1198),(10057,'Metropolitan Manila','MNL',1170),(10058,'La Paz','LP',1097),(10059,'Yinchuan','YN',1045),(10060,'Shizuishan','SZ',1045),(10061,'Wuzhong','WZ',1045),(10062,'Guyuan','GY',1045),(10063,'Zhongwei','ZW',1045),(10064,'Luxembourg','L',1126),(10065,'Aizkraukles novads','002',1119),(10066,'Jaunjelgavas novads','038',1119),(10067,'Pļaviņu novads','072',1119),(10068,'Kokneses novads','046',1119),(10069,'Neretas novads','065',1119),(10070,'Skrīveru novads','092',1119),(10071,'Alūksnes novads','007',1119),(10072,'Apes novads','009',1119),(10073,'Balvu novads','015',1119),(10074,'Viļakas novads','108',1119),(10075,'Baltinavas novads','014',1119),(10076,'Rugāju novads','082',1119),(10077,'Bauskas novads','016',1119),(10078,'Iecavas novads','034',1119),(10079,'Rundāles novads','083',1119),(10080,'Vecumnieku novads','105',1119),(10081,'Cēsu novads','022',1119),(10082,'Līgatnes novads','055',1119),(10083,'Amatas novads','008',1119),(10084,'Jaunpiebalgas novads','039',1119),(10085,'Priekuļu novads','075',1119),(10086,'Pārgaujas novads','070',1119),(10087,'Raunas novads','076',1119),(10088,'Vecpiebalgas novads','104',1119),(10089,'Daugavpils novads','025',1119),(10090,'Ilūkstes novads','036',1119),(10091,'Dobeles novads','026',1119),(10092,'Auces novads','010',1119),(10093,'Tērvetes novads','098',1119),(10094,'Gulbenes novads','033',1119),(10095,'Jelgavas novads','041',1119),(10096,'Ozolnieku novads','069',1119),(10097,'Jēkabpils novads','042',1119),(10098,'Aknīstes novads','004',1119),(10099,'Viesītes novads','107',1119),(10100,'Krustpils novads','049',1119),(10101,'Salas novads','085',1119),(10102,'Krāslavas novads','047',1119),(10103,'Dagdas novads','024',1119),(10104,'Aglonas novads','001',1119),(10105,'Kuldīgas novads','050',1119),(10106,'Skrundas novads','093',1119),(10107,'Alsungas novads','006',1119),(10108,'Aizputes novads','003',1119),(10109,'Durbes novads','028',1119),(10110,'Grobiņas novads','032',1119),(10111,'Pāvilostas novads','071',1119),(10112,'Priekules novads','074',1119),(10113,'Nīcas novads','066',1119),(10114,'Rucavas novads','081',1119),(10115,'Vaiņodes novads','100',1119),(10116,'Limbažu novads','054',1119),(10117,'Alojas novads','005',1119),(10118,'Salacgrīvas novads','086',1119),(10119,'Ludzas novads','058',1119),(10120,'Kārsavas novads','044',1119),(10121,'Zilupes novads','110',1119),(10122,'Ciblas novads','023',1119),(10123,'Madonas novads','059',1119),(10124,'Cesvaines novads','021',1119),(10125,'Lubānas novads','057',1119),(10126,'Varakļānu novads','102',1119),(10127,'Ērgļu novads','030',1119),(10128,'Ogres novads','067',1119),(10129,'Ikšķiles novads','035',1119),(10130,'Ķeguma novads','051',1119),(10131,'Lielvārdes novads','053',1119),(10132,'Preiļu novads','073',1119),(10133,'Līvānu novads','056',1119),(10134,'Riebiņu novads','078',1119),(10135,'Vārkavas novads','103',1119),(10136,'Rēzeknes novads','077',1119),(10137,'Viļānu novads','109',1119),(10138,'Baldones novads','013',1119),(10139,'Ķekavas novads','052',1119),(10140,'Olaines novads','068',1119),(10141,'Salaspils novads','087',1119),(10142,'Saulkrastu novads','089',1119),(10143,'Siguldas novads','091',1119),(10144,'Inčukalna novads','037',1119),(10145,'Ādažu novads','011',1119),(10146,'Babītes novads','012',1119),(10147,'Carnikavas novads','020',1119),(10148,'Garkalnes novads','031',1119),(10149,'Krimuldas novads','048',1119),(10150,'Mālpils novads','061',1119),(10151,'Mārupes novads','062',1119),(10152,'Ropažu novads','080',1119),(10153,'Sējas novads','090',1119),(10154,'Stopiņu novads','095',1119),(10155,'Saldus novads','088',1119),(10156,'Brocēnu novads','018',1119),(10157,'Talsu novads','097',1119),(10158,'Dundagas novads','027',1119),(10159,'Mērsraga novads','063',1119),(10160,'Rojas novads','079',1119),(10161,'Tukuma novads','099',1119),(10162,'Kandavas novads','043',1119),(10163,'Engures novads','029',1119),(10164,'Jaunpils novads','040',1119),(10165,'Valkas novads','101',1119),(10166,'Smiltenes novads','094',1119),(10167,'Strenču novads','096',1119),(10168,'Kocēnu novads','045',1119),(10169,'Mazsalacas novads','060',1119),(10170,'Rūjienas novads','084',1119),(10171,'Beverīnas novads','017',1119),(10172,'Burtnieku novads','019',1119),(10173,'Naukšēnu novads','064',1119),(10174,'Ventspils novads','106',1119),(10175,'Jēkabpils','JKB',1119),(10176,'Valmiera','VMR',1119),(10177,'Florida','FL',1229),(10178,'Rio Negro','RN',1229),(10179,'San Jose','SJ',1229),(10180,'Plateau','PL',1157),(10181,'Pieria','61',1085),(10182,'Los Rios','LR',1044),(10183,'Arica y Parinacota','AP',1044),(10184,'Amazonas','AMA',1169),(10185,'Kalimantan Tengah','KT',1102),(10186,'Sulawesi Barat','SR',1102),(10187,'Kalimantan Utara','KU',1102),(10188,'Ankaran','86',1193),(10189,'Apače','87',1193),(10190,'Cirkulane','88',1193),(10191,'Gorje','89',1193),(10192,'Kostanjevica na Krki','90',1193),(10193,'Log-Dragomer','91',1193),(10194,'Makole','92',1193),(10195,'Mirna','93',1193),(10196,'Mokronog-Trebelno','94',1193),(10197,'Odranci','95',1193),(10198,'Oplotnica','96',1193),(10199,'Ormož','97',1193),(10200,'Osilnica','98',1193),(10201,'Pesnica','99',1193),(10202,'Piran','100',1193),(10203,'Pivka','101',1193),(10204,'Podčetrtek','102',1193),(10205,'Podlehnik','103',1193),(10206,'Podvelka','104',1193),(10207,'Poljčane','105',1193),(10208,'Polzela','106',1193),(10209,'Postojna','107',1193),(10210,'Prebold','108',1193),(10211,'Preddvor','109',1193),(10212,'Prevalje','110',1193),(10213,'Ptuj','111',1193),(10214,'Puconci','112',1193),(10215,'Rače-Fram','113',1193),(10216,'Radeče','114',1193),(10217,'Radenci','115',1193),(10218,'Radlje ob Dravi','139',1193),(10219,'Radovljica','145',1193),(10220,'Ravne na Koroškem','171',1193),(10221,'Razkrižje','172',1193),(10222,'Rečica ob Savinji','173',1193),(10223,'Renče-Vogrsko','174',1193),(10224,'Ribnica','175',1193),(10225,'Ribnica na Pohorju','176',1193),(10226,'Rogaška Slatina','177',1193),(10227,'Rogašovci','178',1193),(10228,'Rogatec','179',1193),(10229,'Ruše','180',1193),(10230,'Selnica ob Dravi','195',1193),(10231,'Semič','196',1193),(10232,'Šentrupert','197',1193),(10233,'Sevnica','198',1193),(10234,'Sežana','199',1193),(10235,'Slovenj Gradec','200',1193),(10236,'Slovenska Bistrica','201',1193),(10237,'Slovenske Konjice','202',1193),(10238,'Šmarješke Toplice','203',1193),(10239,'Sodražica','204',1193),(10240,'Solčava','205',1193),(10241,'Središče ob Dravi','206',1193),(10242,'Starše','207',1193),(10243,'Straža','208',1193),(10244,'Sveta Trojica v Slovenskih goricah','209',1193),(10245,'Sveti Jurij v Slovenskih goricah','210',1193),(10246,'Sveti Tomaž','211',1193),(10247,'Vodice','212',1193),(10248,'Abkhazia','AB',1081),(10249,'Adjara','AJ',1081),(10250,'Tbilisi','TB',1081),(10251,'Guria','GU',1081),(10252,'Imereti','IM',1081),(10253,'Kakheti','KA',1081),(10254,'Kvemo Kartli','KK',1081),(10255,'Mtskheta-Mtianeti','MM',1081),(10256,'Racha-Lechkhumi and Kvemo Svaneti','RL',1081),(10257,'Samegrelo-Zemo Svaneti','SZ',1081),(10258,'Samtskhe-Javakheti','SJ',1081),(10259,'Shida Kartli','SK',1081),(10260,'Central','C',1074),(10261,'Punjab','PB',1163),(10262,'La Libertad','LI',1066),(10263,'La Paz','PA',1066),(10264,'La Union','UN',1066),(10265,'Littoral','LT',1038),(10266,'Nord-Ouest','NW',1038),(10267,'Telangana','TG',1101),(10268,'Ash Sharqiyah','04',1187),(10269,'Guadeloupe','GP',1076),(10270,'Martinique','MQ',1076),(10271,'Guyane','GF',1076),(10272,'La Réunion','RE',1076),(10273,'Mayotte','YT',1076),(10274,'Baringo','01',1112),(10275,'Bomet','02',1112),(10276,'Bungoma','03',1112),(10277,'Busia','04',1112),(10278,'Elgeyo/Marakwet','05',1112),(10279,'Embu','06',1112),(10280,'Garissa','07',1112),(10281,'Homa Bay','08',1112),(10282,'Isiolo','09',1112),(10283,'Kajiado','10',1112),(10284,'Kakamega','11',1112),(10285,'Kericho','12',1112),(10286,'Kiambu','13',1112),(10287,'Kilifi','14',1112),(10288,'Kirinyaga','15',1112),(10289,'Kisii','16',1112),(10290,'Kisumu','17',1112),(10291,'Kitui','18',1112),(10292,'Kwale','19',1112),(10293,'Laikipia','20',1112),(10294,'Lamu','21',1112),(10295,'Machakos','22',1112),(10296,'Makueni','23',1112),(10297,'Mandera','24',1112),(10298,'Marsabit','25',1112),(10299,'Meru','26',1112),(10300,'Migori','27',1112),(10301,'Mombasa','28',1112),(10302,'Murang\'a','29',1112),(10303,'Nairobi City','30',1112),(10304,'Nakuru','31',1112),(10305,'Nandi','32',1112),(10306,'Narok','33',1112),(10307,'Nyamira','34',1112),(10308,'Nyandarua','35',1112),(10309,'Nyeri','36',1112),(10310,'Samburu','37',1112),(10311,'Siaya','38',1112),(10312,'Taita/Taveta','39',1112),(10313,'Tana River','40',1112),(10314,'Tharaka-Nithi','41',1112),(10315,'Trans Nzoia','42',1112),(10316,'Turkana','43',1112),(10317,'Uasin Gishu','44',1112),(10318,'Vihiga','45',1112),(10319,'Wajir','46',1112),(10320,'West Pokot','47',1112),(10321,'Chandigarh','CH',1101),(10322,'Central','CP',1083),(10323,'Eastern','EP',1083),(10324,'Northern','NP',1083),(10325,'Western','WP',1083),(10326,'Saint Kitts','K',1181),(10327,'Nevis','N',1181),(10328,'Eastern','E',1190),(10329,'Northern','N',1190),(10330,'Southern','S',1190),(10331,'Dushanbe','DU',1209),(10332,'Nohiyahoi Tobei Jumhurí','RA',1209),(10333,'Wallis-et-Futuna','WF',1076),(10334,'Nouvelle-Calédonie','NC',1076),(10335,'Haute-Marne','52',1076),(10336,'Saint George','03',1009),(10337,'Saint John','04',1009),(10338,'Saint Mary','05',1009),(10339,'Saint Paul','06',1009),(10340,'Saint Peter','07',1009),(10341,'Saint Philip','08',1009),(10342,'Barbuda','10',1009),(10343,'Redonda','11',1009),(10344,'Christ Church','01',1018),(10345,'Saint Andrew','02',1018),(10346,'Saint George','03',1018),(10347,'Saint James','04',1018),(10348,'Saint John','05',1018),(10349,'Saint Joseph','06',1018),(10350,'Saint Lucy','07',1018),(10351,'Saint Michael','08',1018),(10352,'Saint Peter','09',1018),(10353,'Saint Philip','10',1018),(10354,'Saint Thomas','11',1018),(10355,'Estuaire','01',1080),(10356,'Haut-Ogooué','02',1080),(10357,'Moyen-Ogooué','03',1080),(10358,'Ngounié','04',1080),(10359,'Nyanga','05',1080),(10360,'Ogooué-Ivindo','06',1080),(10361,'Ogooué-Lolo','07',1080),(10362,'Ogooué-Maritime','08',1080),(10363,'Woleu-Ntem','09',1080),(10364,'Monmouthshire','MON',1226),(10365,'Antrim and Newtownabbey','ANN',1226),(10366,'Ards and North Down','AND',1226),(10367,'Armagh City, Banbridge and Craigavon','ABC',1226),(10368,'Belfast','BFS',1226),(10369,'Causeway Coast and Glens','CCG',1226),(10370,'Derry City and Strabane','DRS',1226),(10371,'Fermanagh and Omagh','FMO',1226),(10372,'Lisburn and Castlereagh','LBC',1226),(10373,'Mid and East Antrim','MEA',1226),(10374,'Mid Ulster','MUL',1226),(10375,'Newry, Mourne and Down','NMD',1226),(10376,'Bridgend','BGE',1226),(10377,'Caerphilly','CAY',1226),(10378,'Cardiff','CRF',1226),(10379,'Carmarthenshire','CMN',1226),(10380,'Ceredigion','CGN',1226),(10381,'Conwy','CWY',1226),(10382,'Denbighshire','DEN',1226),(10383,'Flintshire','FLN',1226),(10384,'Isle of Anglesey','AGY',1226),(10385,'Merthyr Tydfil','MTY',1226),(10386,'Neath Port Talbot','NTL',1226),(10387,'Newport','NWP',1226),(10388,'Pembrokeshire','PEM',1226),(10389,'Rhondda, Cynon, Taff','RCT',1226),(10390,'Swansea','SWA',1226),(10391,'Torfaen','TOF',1226),(10392,'Wrexham','WRX',1226),(10393,'Sejong','50',1115);
 /*!40000 ALTER TABLE `civicrm_state_province` ENABLE KEYS */;
 UNLOCK TABLES;
 
index 626a37948fc0f40d208a61097273cf952249b144..6ecd9c181db092e5b394f6c83f98a176d1b3aafe 100644 (file)
@@ -39,7 +39,7 @@
 
                 {section name=rows loop=$rowDisplayCount}
                     {assign var="j" value=$smarty.section.rows.index}
-                    <td class="{if $skipColumnHeader AND $smarty.section.rows.iteration == 1}even-row labels{else}odd-row{/if}">{$dataValues[$j][$i]}</td>
+                    <td class="{if $skipColumnHeader AND $smarty.section.rows.iteration == 1}even-row labels{else}odd-row{/if}">{$dataValues[$j][$i]|escape}</td>
                 {/section}
 
                 {* Display mapper <select> field for 'Map Fields', and mapper value for 'Preview' *}
index bab021bf148428e822ba55ab098f08e6fbfda7e4..a769842de6a358d0c9249512baac92e0be4b3ded 100644 (file)
@@ -1,6 +1,6 @@
 <table class="crm-info-panel">
         {foreach from=$extension.urls key=label item=url}
-            <tr><td class="label">{$label}</td><td><a href="{$url}">{$url}</a></td></tr>
+            <tr><td class="label">{$label|escape}</td><td><a href="{$url|escape}">{$url|escape}</a></td></tr>
         {/foreach}
     <tr>
         <td class="label">{ts}Author{/ts}</td>
         </td>
     </tr>
     <tr>
-      <td class="label">{ts}Comments{/ts}</td><td>{$extension.comments}</td>
+      <td class="label">{ts}Comments{/ts}</td><td>{$extension.comments|escape}</td>
     </tr>
     <tr>
-        <td class="label">{ts}Version{/ts}</td><td>{$extension.version}</td>
+        <td class="label">{ts}Version{/ts}</td><td>{$extension.version|escape}</td>
     </tr>
     <tr>
-        <td class="label">{ts}Released on{/ts}</td><td>{$extension.releaseDate}</td>
+        <td class="label">{ts}Released on{/ts}</td><td>{$extension.releaseDate|escape}</td>
     </tr>
     <tr>
-        <td class="label">{ts}License{/ts}</td><td>{$extension.license}</td>
+        <td class="label">{ts}License{/ts}</td><td>{$extension.license|escape}</td>
     </tr>
     <tr>
-        <td class="label">{ts}Development stage{/ts}</td><td>{$extension.develStage}</td>
+        <td class="label">{ts}Development stage{/ts}</td><td>{$extension.develStage|escape}</td>
     </tr>
     <tr>
         <td class="label">{ts}Requires{/ts}</td>
         <td class="label">{ts}Compatible with{/ts}</td>
         <td>
             {foreach from=$extension.compatibility.ver item=ver}
-                {$ver} &nbsp;
+                {$ver|escape} &nbsp;
             {/foreach}
         </td>
     </tr>
     <tr>
-      <td class="label">{ts}Local path{/ts}</td><td>{$extension.path}</td>
+      <td class="label">{ts}Local path{/ts}</td><td>{$extension.path|escape}</td>
     </tr>
     <tr>
-      <td class="label">{ts}Download location{/ts}</td><td>{$extension.downloadUrl}</td>
+      <td class="label">{ts}Download location{/ts}</td><td>{$extension.downloadUrl|escape}</td>
     </tr>
     <tr>
-      <td class="label">{ts}Key{/ts}</td><td>{$extension.key}</td>
+      <td class="label">{ts}Key{/ts}</td><td>{$extension.key|escape}</td>
     </tr>
 </table>
index 881d1a4d0ce90e53e06d99825a22752c063f7a29..e7598bab0442470957c1a2362d973a12bf0ac823 100644 (file)
@@ -19,19 +19,19 @@ Depends: CRM/common/enableDisableApi.tpl and CRM/common/jsortable.tpl
       </thead>
       <tbody>
         {foreach from=$localExtensionRows key=extKey item=row}
-        <tr id="extension-{$row.file}" class="crm-entity crm-extension-{$row.file}{if $row.status eq 'disabled'} disabled{/if}{if $row.status eq 'installed-missing' or $row.status eq 'disabled-missing'} extension-missing{/if}{if $row.upgradable} extension-upgradable{elseif $row.status eq 'installed'} extension-installed{/if}">
+        <tr id="extension-{$row.file|escape}" class="crm-entity crm-extension-{$row.file|escape}{if $row.status eq 'disabled'} disabled{/if}{if $row.status eq 'installed-missing' or $row.status eq 'disabled-missing'} extension-missing{/if}{if $row.upgradable} extension-upgradable{elseif $row.status eq 'installed'} extension-installed{/if}">
           <td class="crm-extensions-label">
-              <a class="collapsed" href="#"></a>&nbsp;<strong>{$row.label}</strong><br/>{$row.description}
+              <a class="collapsed" href="#"></a>&nbsp;<strong>{$row.label|escape}</strong><br/>{$row.description|escape}
               {if $extAddNewEnabled && $remoteExtensionRows[$extKey] && $remoteExtensionRows[$extKey].upgradelink}
                 <div class="crm-extensions-upgrade">{$remoteExtensionRows[$extKey].upgradelink}</div>
               {/if}
           </td>
           <td class="crm-extensions-label">{$row.statusLabel} {if $row.upgradable}<br/>({ts}Outdated{/ts}){/if}</td>
-          <td class="crm-extensions-label">{$row.version} {if $row.upgradable}<br/>({$row.upgradeVersion}){/if}</td>
-          <td class="crm-extensions-description">{$row.type|capitalize}</td>
+          <td class="crm-extensions-label">{$row.version|escape} {if $row.upgradable}<br/>({$row.upgradeVersion}){/if}</td>
+          <td class="crm-extensions-description">{$row.type|escape|capitalize}</td>
           <td>{$row.action|replace:'xx':$row.id}</td>
         </tr>
-        <tr class="hiddenElement" id="crm-extensions-details-{$row.file}">
+        <tr class="hiddenElement" id="crm-extensions-details-{$row.file|escape}">
             <td>
                 {include file="CRM/Admin/Page/ExtensionDetails.tpl" extension=$row localExtensionRows=$localExtensionRows remoteExtensionRows=$remoteExtensionRows}
             </td>
index 21966b6aa5c7c6cbe1bf27e4a7e3ff4a2c82c05b..6eb7c65346118859e45b50f130ab72728bb61c2f 100644 (file)
@@ -46,7 +46,7 @@
 
                 {section name=rows loop=$rowDisplayCount}
                     {assign var="j" value=$smarty.section.rows.index}
-                    <td class="odd-row">{$dataValues[$j][$i]}</td>
+                    <td class="odd-row">{$dataValues[$j][$i]|escape}</td>
                 {/section}
 
                 {* Display mapper <select> field for 'Map Fields', and mapper value for 'Preview' *}
index d138524d16aca1c3a565c082768c3841727010bd..185d5970d11bbfaed4654980030bc4474320b494 100644 (file)
                 </strong>
                 <br />
                 <span class="description">
-            {ts}Your recurring contribution will be processed automatically for the number of installments you specify. You can leave the number of installments blank if you want to make an open-ended commitment. In either case, you can choose to cancel at any time. You will receive an email receipt for each recurring contribution. The receipts will include a link you can use if you decide to modify or cancel your future contributions.{/ts}
+            {ts}You can leave the number of installments blank if you want to make an open-ended commitment. In either case, you can choose to cancel at any time.{/ts}
           </span>
               </td>
             </tr>
index ad14bd8ae12be4c17c4146b52738d48a5d8c8c4c..4c6909d271af2246ba39ffae96b5b820b400cf6a 100644 (file)
@@ -38,7 +38,7 @@
 
                 {section name=rows loop=$rowDisplayCount}
                     {assign var="j" value=$smarty.section.rows.index}
-                    <td class="{if $skipColumnHeader AND $smarty.section.rows.iteration == 1}even-row labels{else}odd-row{/if}">{$dataValues[$j][$i]}</td>
+                    <td class="{if $skipColumnHeader AND $smarty.section.rows.iteration == 1}even-row labels{else}odd-row{/if}">{$dataValues[$j][$i]|escape}</td>
                 {/section}
 
                 {* Display mapper <select> field for 'Map Fields', and mapper value for 'Preview' *}
index 2f602b38b9d6bd74f41a6354da6cac7764252800..00d7072721c9ea1ae6223076c9191c95fd9ac059 100644 (file)
@@ -38,7 +38,7 @@
 
                 {section name=rows loop=$rowDisplayCount}
                     {assign var="j" value=$smarty.section.rows.index}
-                    <td class="{if $skipColumnHeader AND $smarty.section.rows.iteration == 1}even-row labels{else}odd-row{/if}">{$dataValues[$j][$i]}</td>
+                    <td class="{if $skipColumnHeader AND $smarty.section.rows.iteration == 1}even-row labels{else}odd-row{/if}">{$dataValues[$j][$i]|escape}</td>
                 {/section}
 
                 {* Display mapper <select> field for 'Map Fields', and mapper value for 'Preview' *}
index 4b1bf47f1d5c1e62323bd5fd8428a0de6af04499..1bd38a56bf84d6b197889d2ade0f3ca48b04ea51 100644 (file)
@@ -40,7 +40,8 @@
     $('input[name="export_format"]').filter('[value=IIF]').prop('checked', true);
     $('#_qf_Export_next').click(function(){
       $(this).hide();
-      $('#_qf_Export_cancel').val('{/literal}{ts}Done{/ts}{literal}');
+      {/literal}{capture assign=tsdone}{ts}Done{/ts}{/capture}{literal}
+      $('#_qf_Export_cancel').html('<i aria-hidden="true" class="crm-i fa-check"></i> {/literal}{$tsdone|escape}{literal}');
     });
   });
 </script>
index 927ba7ceea89b928b7c82fcb32441f21ca01ebb3..0a3dfec5ae28811f506ab057f538d23fd052180b 100644 (file)
@@ -38,7 +38,7 @@
 
                 {section name=rows loop=$rowDisplayCount}
                     {assign var="j" value=$smarty.section.rows.index}
-                    <td class="{if $skipColumnHeader AND $smarty.section.rows.iteration == 1}even-row labels{else}odd-row{/if}">{$dataValues[$j][$i]}</td>
+                    <td class="{if $skipColumnHeader AND $smarty.section.rows.iteration == 1}even-row labels{else}odd-row{/if}">{$dataValues[$j][$i]|escape}</td>
                 {/section}
 
                 {* Display mapper <select> field for 'Map Fields', and mapper value for 'Preview' *}
index 866402fbfdb3fceda47cf7fa2a7e70d2cb40b8cd..28857297827529106bfd5471f448a67c45203ea1 100644 (file)
@@ -38,7 +38,7 @@
 <div class="campaign">
 {crmRegion name="pcp-page-pcpinfo"}
     <div class="pcp-intro-text">
-      {$pcp.intro_text}
+      {$pcp.intro_text|purify}
   </div>
     {if $image}
     <div class="pcp-image">
index 374123bdfba466c30702a46d7335ead67e89d105..57f91076de10c9b59407ec3b5af96faca923ecb1 100644 (file)
         <a href="https://facebook.com/sharer/sharer.php?u={$url|escape:'url'}" target="_blank" class="btn btn-default" role="button">{ts}Share on Facebook{/ts}</a>
         <a href="ttps://www.linkedin.com/shareArticle?mini=true&amp;url={$url|escape:'url'}&amp;title={$title}" target="_blank" rel="noopener" class="btn btn-default">{ts}Share on LinkedIn{/ts}</a>
     {else}
-       <button onclick="window.open('https://twitter.com/intent/tweet?url={$url|escape:'url'}&amp;text={$title}','_blank')" type="button" class="btn btn-default crm-button" id="crm-tw"><i aria-hidden="true" class="crm-i fa-twitter"></i>&nbsp;&nbsp;{ts}Tweet{/ts}</button>
+        <button onclick="window.open('https://twitter.com/intent/tweet?url={$url|escape:'url'}&amp;text={$title}','_blank')" type="button" class="btn btn-default crm-button" id="crm-tw"><i aria-hidden="true" class="crm-i fa-twitter"></i>&nbsp;&nbsp;{ts}Tweet{/ts}</button>
         <button onclick="window.open('https://facebook.com/sharer/sharer.php?u={$url|escape:'url'}','_blank')" type="button" class="btn btn-default crm-button" role="button" id="crm-fb"><i aria-hidden="true" class="crm-i fa-facebook"></i>&nbsp;&nbsp;{ts}Share on Facebook{/ts}</button>
         <button onclick="window.open('https://www.linkedin.com/shareArticle?mini=true&amp;url={$url|escape:'url'}&amp;title={$title}','_blank')" type="button" rel="noopener" class="btn btn-default crm-button" id="crm-li"><i aria-hidden="true" class="crm-i fa-linkedin"></i>&nbsp;&nbsp;{ts}Share on LinkedIn{/ts}</button>
         <button onclick="window.open('mailto:?subject={$title}&amp;body={$url|escape:'url'}','_self')" type="button" rel="noopener" class="btn btn-default crm-button" id="crm-email"><i aria-hidden="true" class="crm-i fa-envelope"></i>&nbsp;&nbsp;{ts}Email{/ts}</button>
-        {/if}
+    {/if}
     {if $pageURL}
-       {if $emailMode neq true}
-        <br/>
-               {/if}
-    <br/>
-    <p><strong>{ts}You can also share the below link in an email or on your website:{/ts}</strong><br />
+    <p class="clear">
+    <br/><strong>{ts}You can also share the below link in an email or on your website:{/ts}</strong><br />
     <a href="{$pageURL}">{$pageURL}</a></p>
     {else}
+    <div class="clear"></div>
     {/if}
 </div>
index 757e1851ba36b230179367778b099a64cb5195ed..4982cd59cd95a3ca96b15287ac016e102f85c02b 100644 (file)
@@ -5,11 +5,12 @@
  */
 class CRM_Activity_Form_ActivityViewTest extends CiviUnitTestCase {
 
-  public function setUp() {
-    parent::setUp();
-  }
-
-  public function tearDown() {
+  /**
+   * Cleanup after class.
+   *
+   * @throws \CRM_Core_Exception
+   */
+  public function tearDown(): void {
     $tablesToTruncate = [
       'civicrm_activity',
       'civicrm_activity_contact',
@@ -20,8 +21,11 @@ class CRM_Activity_Form_ActivityViewTest extends CiviUnitTestCase {
   /**
    * Test that the smarty template for ActivityView contains what we expect
    * after preProcess().
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testActivityViewPreProcess() {
+  public function testActivityViewPreProcess(): void {
     // create activity
     $activity = $this->activityCreate();
 
@@ -38,7 +42,7 @@ class CRM_Activity_Form_ActivityViewTest extends CiviUnitTestCase {
 
     // check one of the smarty template vars
     // not checking EVERYTHING
-    $templateVar = $activityViewForm->getTemplate()->get_template_vars('values');
+    $templateVar = CRM_Activity_Form_ActivityView::getTemplate()->get_template_vars('values');
     $expected = [
       'assignee_contact' => [0 => $activity['target_contact_id']],
       // it's always Julia
index 361fc0585bce53abd5491960e077380265b15f0a..c52fc647405b5ca7f6e597d5193403a95d96034a 100644 (file)
@@ -6,26 +6,25 @@
  */
 class CRM_Activity_Form_Task_PDFLetterCommonTest extends CiviUnitTestCase {
 
-  public function setUp() {
-    $this->useTransaction(TRUE);
+  /**
+   * Set up for tests.
+   */
+  public function setUp(): void {
+    $this->useTransaction();
     parent::setUp();
   }
 
-  public function tearDown() {
-    parent::tearDown();
-  }
-
   /**
    * Test create a document with basic tokens.
    *
    * @throws \CRM_Core_Exception
    * @throws \CiviCRM_API3_Exception
    */
-  public function testCreateDocumentBasicTokens() {
+  public function testCreateDocumentBasicTokens(): void {
     $activity = $this->activityCreate();
     $data = [
       ['Subject: {activity.subject}', 'Subject: Discussion on warm beer'],
-      ['Date: {activity.activity_date_time}', 'Date: ' . \CRM_Utils_Date::customFormat(date('Ymd')) . ' 12:00 AM'],
+      ['Date: {activity.activity_date_time}', 'Date: ' . CRM_Utils_Date::customFormat(date('Ymd')) . ' 12:00 AM'],
       ['Duration: {activity.duration}', 'Duration: 90'],
       ['Location: {activity.location}', 'Location: Baker Street'],
       ['Details: {activity.details}', 'Details: Lets schedule a meeting'],
@@ -61,29 +60,33 @@ class CRM_Activity_Form_Task_PDFLetterCommonTest extends CiviUnitTestCase {
     $activityIds = CRM_Utils_Array::collect('id', $activities);
     $output = CRM_Activity_Form_Task_PDFLetterCommon::createDocument($activityIds, $html_message, ['is_unit_test' => TRUE]);
     // Should have one row of output per activity
-    $this->assertEquals(count($activities), count($output));
+    $this->assertCount(count($activities), $output);
 
     // Check each line has the correct substitution
     foreach ($output as $key => $line) {
-      $this->assertEquals($line, "Custom: " . $cg['custom_field_group_options'][$activities[$key]['option']]);
+      $this->assertEquals($line, 'Custom: ' . $cg['custom_field_group_options'][$activities[$key]['option']]);
     }
   }
 
-  public function testCreateDocumentSpecialTokens() {
+  /**
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
+   */
+  public function testCreateDocumentSpecialTokens(): void {
     $this->markTestIncomplete('special tokens not yet merged - see https://github.com/civicrm/civicrm-core/pull/12012');
     $activity = $this->activityCreate();
     $data = [
-      ["Source First Name: {activity.source_first_name}", "Source First Name: Anthony"],
-      ["Target N First Name: {activity.target_N_first_name}", "Target N First Name: Julia"],
-      ["Target 0 First Name: {activity.target_0_first_name}", "Target 0 First Name: Julia"],
-      ["Target 1 First Name: {activity.target_1_first_name}", "Target 1 First Name: Julia"],
-      ["Target 2 First Name: {activity.target_2_first_name}", "Target 2 First Name: "],
-      ["Assignee N First Name: {activity.target_N_first_name}", "Assignee N First Name: Julia"],
-      ["Assignee 0 First Name: {activity.target_0_first_name}", "Assignee 0 First Name: Julia"],
-      ["Assignee 1 First Name: {activity.target_1_first_name}", "Assignee 1 First Name: Julia"],
-      ["Assignee 2 First Name: {activity.target_2_first_name}", "Assignee 2 First Name: "],
-      ["Assignee Count: {activity.assignees_count}", "Assignee Count: 1"],
-      ["Target Count: {activity.targets_count}", "Target Count: 1"],
+      ['Source First Name: {activity.source_first_name}', "Source First Name: Anthony"],
+      ['Target N First Name: {activity.target_N_first_name}', "Target N First Name: Julia"],
+      ['Target 0 First Name: {activity.target_0_first_name}', "Target 0 First Name: Julia"],
+      ['Target 1 First Name: {activity.target_1_first_name}', "Target 1 First Name: Julia"],
+      ['Target 2 First Name: {activity.target_2_first_name}', "Target 2 First Name: "],
+      ['Assignee N First Name: {activity.target_N_first_name}', "Assignee N First Name: Julia"],
+      ['Assignee 0 First Name: {activity.target_0_first_name}', "Assignee 0 First Name: Julia"],
+      ['Assignee 1 First Name: {activity.target_1_first_name}', "Assignee 1 First Name: Julia"],
+      ['Assignee 2 First Name: {activity.target_2_first_name}', "Assignee 2 First Name: "],
+      ['Assignee Count: {activity.assignees_count}', "Assignee Count: 1"],
+      ['Target Count: {activity.targets_count}', "Target Count: 1"],
     ];
     $html_message = "\n" . implode("\n", CRM_Utils_Array::collect('0', $data)) . "\n";
     $output = CRM_Activity_Form_Task_PDFLetterCommon::createDocument([$activity['id']], $html_message, ['is_unit_test' => TRUE]);
@@ -93,12 +96,16 @@ class CRM_Activity_Form_Task_PDFLetterCommonTest extends CiviUnitTestCase {
     }
   }
 
-  public function testCreateDocumentUnknownTokens() {
+  /**
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
+   */
+  public function testCreateDocumentUnknownTokens(): void {
     $activity = $this->activityCreate();
-    $html_message = "Unknown token: {activity.something_unknown}";
+    $html_message = 'Unknown token: {activity.something_unknown}';
     $output = CRM_Activity_Form_Task_PDFLetterCommon::createDocument([$activity['id']], $html_message, ['is_unit_test' => TRUE]);
     // Unknown tokens should be left alone
-    $this->assertEquals($output[0], $html_message);
+    $this->assertEquals($html_message, $output[0]);
   }
 
 }
index 04a9e968f8ace82f9c21b45d9fef4e8d68864c1b..b1486aab5cc239b7ff5d7013eee7b5d2c4fbee3b 100644 (file)
@@ -517,7 +517,7 @@ AND ( 1 ) AND (contact_a.is_deleted = 0)',
     $sql = $selector->getQueryObject()->query();
 
     $expectedQuery = [
-      0 => "SELECT contact_a.id as contact_id, contact_a.contact_type as `contact_type`, contact_a.contact_sub_type as `contact_sub_type`, contact_a.sort_name as `sort_name`, `Non_ASCII_Location_Type-location_type`.id as `Non_ASCII_Location_Type-location_type_id`, `Non_ASCII_Location_Type-location_type`.name as `Non_ASCII_Location_Type-location_type`, `Non_ASCII_Location_Type-email`.id as `Non_ASCII_Location_Type-email_id`, `Non_ASCII_Location_Type-email`.email as `Non_ASCII_Location_Type-email`",
+      0 => "SELECT contact_a.id as contact_id, contact_a.contact_type as `contact_type`, contact_a.contact_sub_type as `contact_sub_type`, contact_a.sort_name as `sort_name`, `Non_ASCII_Location_Type-location_type`.id as `Non_ASCII_Location_Type-location_type_id`, `Non_ASCII_Location_Type-location_type`.name as `Non_ASCII_Location_Type-location_type`, `Non_ASCII_Location_Type-address`.id as `Non_ASCII_Location_Type-address_id`, `Non_ASCII_Location_Type-email`.id as `Non_ASCII_Location_Type-email_id`, `Non_ASCII_Location_Type-email`.email as `Non_ASCII_Location_Type-email`",
       // @TODO these FROM clause doesn't matches due to extra spaces or special character
       2 => "WHERE  (  ( `Non_ASCII_Location_Type-email`.email IS NOT NULL )  )  AND ( 1 ) AND (contact_a.is_deleted = 0)",
     ];
index 84f42bad60a8a3740e2950ad34b0bffec251093e..1ab47a0d783a128c93e331a90d520634c633efd9 100644 (file)
@@ -65,6 +65,9 @@ class CRM_Contribute_Form_Contribution_ConfirmTest extends CiviUnitTestCase {
       'is_recur' => FALSE,
       'payment_instrument_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Credit card'),
     ];
+    $form->_values = [
+      'id' => $contributionPageID2,
+    ];
     $form->_params = [
       'contribution_id' => $contribution['id'],
       'credit_card_number' => 4111111111111111,
index 5c32de65f46911c74e39f55e5fabcbd4f7e38c29..aba8e8fa251bd481ff139f422553c787edd890b7 100644 (file)
@@ -77,6 +77,10 @@ class CRM_Contribute_Form_Contribution_ThankYouTest extends CiviUnitTestCase {
     if ($isTestContribution) {
       $form->_mode = 'test';
     }
+    $form->_values = [
+      'custom_pre_id' => NULL,
+      'custom_post_id' => NULL,
+    ];
 
     return $form;
   }
index e46626e3467ee30c0982d6743c8cd8c02af2b549..21d96074e50ac734c53364487a3ac09962320c97 100644 (file)
@@ -9,6 +9,7 @@
  +--------------------------------------------------------------------+
  */
 
+use Civi\Api4\Activity;
 use Civi\Api4\ActivityContact;
 
 /**
@@ -22,6 +23,8 @@ use Civi\Api4\ActivityContact;
  */
 class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
 
+  use CRMTraits_Custom_CustomDataTrait;
+
   /**
    * @var CiviMailUtils
    */
@@ -39,7 +42,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws CRM_Core_Exception
    */
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
 
     $this->mut = new CiviMailUtils($this, TRUE);
@@ -92,7 +95,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'status_id' => '8',
     ];
 
-    $this->fixtures['phonecall'] = [
+    $this->fixtures['phone_call'] = [
       'status_id' => 1,
       'activity_type_id' => 2,
       'activity_date_time' => '20120615100000',
@@ -112,13 +115,13 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'contact_type' => 'Individual',
       'email' => 'test-contact-2@example.com',
       'gender_id' => 'Male',
-      'first_name' => 'Fabble',
+      'first_name' => 'Fabio',
       'last_name' => 'Fi',
     ];
     $this->fixtures['contact_birthdate'] = [
       'is_deceased' => 0,
       'contact_type' => 'Individual',
-      'email' => 'test-bday@example.com',
+      'email' => 'test-birth_day@example.com',
       'birth_date' => '20050707',
     ];
     $this->fixtures['sched_activity_1day'] = [
@@ -211,13 +214,13 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'start_action_unit' => '',
       'subject' => '1-Day (repeating) (about {activity.activity_type})',
     ];
-    $this->fixtures['sched_eventname_1day_on_abs_date'] = [
-      'name' => 'sched_eventname_1day_on_abs_date',
-      'title' => 'sched_eventname_1day_on_abs_date',
+    $this->fixtures['sched_event_name_1day_on_abs_date'] = [
+      'name' => 'sched_event_name_1day_on_abs_date',
+      'title' => 'sched_event_name_1day_on_abs_date',
       'limit_to' => 1,
       'absolute_date' => CRM_Utils_Date::processDate('20120614100000'),
-      'body_html' => '<p>sched_eventname_1day_on_abs_date</p>',
-      'body_text' => 'sched_eventname_1day_on_abs_date',
+      'body_html' => '<p>sched_event_name_1day_on_abs_date</p>',
+      'body_text' => 'sched_event_name_1day_on_abs_date',
       'entity_status' => '1',
       'entity_value' => '2',
       'group_id' => NULL,
@@ -239,7 +242,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'start_action_date' => NULL,
       'start_action_offset' => NULL,
       'start_action_unit' => NULL,
-      'subject' => 'sched_eventname_1day_on_abs_date',
+      'subject' => 'sched_event_name_1day_on_abs_date',
     ];
     $this->fixtures['sched_membership_join_2week'] = [
       'name' => 'sched_membership_join_2week',
@@ -417,9 +420,9 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'subject' => 'subject sched_membership_absolute_date',
     ];
 
-    $this->fixtures['sched_contact_bday_yesterday'] = [
-      'name' => 'sched_contact_bday_yesterday',
-      'title' => 'sched_contact_bday_yesterday',
+    $this->fixtures['sched_contact_birth_day_yesterday'] = [
+      'name' => 'sched_contact_birth_day_yesterday',
+      'title' => 'sched_contact_birth_day_yesterday',
       'absolute_date' => '',
       'body_html' => '<p>you look like you were born yesterday!</p>',
       'body_text' => 'you look like you were born yesterday!',
@@ -444,12 +447,12 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'start_action_date' => 'date_field',
       'start_action_offset' => '1',
       'start_action_unit' => 'day',
-      'subject' => 'subject sched_contact_bday_yesterday',
+      'subject' => 'subject sched_contact_birth_day_yesterday',
     ];
 
-    $this->fixtures['sched_contact_bday_anniv'] = [
-      'name' => 'sched_contact_bday_anniv',
-      'title' => 'sched_contact_bday_anniv',
+    $this->fixtures['sched_contact_birth_day_anniversary'] = [
+      'name' => 'sched_contact_birth_day_anniversary',
+      'title' => 'sched_contact_birth_day_anniversary',
       'absolute_date' => '',
       'body_html' => '<p>happy birthday!</p>',
       'body_text' => 'happy birthday!',
@@ -474,7 +477,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'start_action_date' => 'date_field',
       'start_action_offset' => '1',
       'start_action_unit' => 'day',
-      'subject' => 'subject sched_contact_bday_anniv',
+      'subject' => 'subject sched_contact_birth_day_anniversary',
     ];
 
     $this->fixtures['sched_contact_grad_tomorrow'] = [
@@ -506,9 +509,9 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'subject' => 'subject sched_contact_grad_tomorrow',
     ];
 
-    $this->fixtures['sched_contact_grad_anniv'] = [
-      'name' => 'sched_contact_grad_anniv',
-      'title' => 'sched_contact_grad_anniv',
+    $this->fixtures['sched_contact_grad_anniversary'] = [
+      'name' => 'sched_contact_grad_anniversary',
+      'title' => 'sched_contact_grad_anniversary',
       'absolute_date' => '',
       'body_html' => '<p>dear alum, please send us money.</p>',
       'body_text' => 'dear alum, please send us money.',
@@ -532,7 +535,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'start_action_date' => 'date_field',
       'start_action_offset' => '1',
       'start_action_unit' => 'week',
-      'subject' => 'subject sched_contact_grad_anniv',
+      'subject' => 'subject sched_contact_grad_anniversary',
     ];
 
     $this->fixtures['sched_contact_created_yesterday'] = [
@@ -565,9 +568,9 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'subject' => 'subject sched_contact_created_yesterday',
     ];
 
-    $this->fixtures['sched_contact_mod_anniv'] = [
-      'name' => 'sched_contact_mod_anniv',
-      'title' => 'sched_contact_mod_anniv',
+    $this->fixtures['sched_contact_mod_anniversary'] = [
+      'name' => 'sched_contact_mod_anniversary',
+      'title' => 'sched_contact_mod_anniversary',
       'absolute_date' => '',
       'body_html' => '<p>You last updated your data last year</p>',
       'body_text' => 'Go update your stuff!',
@@ -592,15 +595,15 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'start_action_date' => 'date_field',
       'start_action_offset' => '1',
       'start_action_unit' => 'day',
-      'subject' => 'subject sched_contact_mod_anniv',
+      'subject' => 'subject sched_contact_mod_anniversary',
     ];
 
-    $this->fixtures['sched_eventtype_start_1week_before'] = [
-      'name' => 'sched_eventtype_start_1week_before',
-      'title' => 'sched_eventtype_start_1week_before',
+    $this->fixtures['sched_event_type_start_1week_before'] = [
+      'name' => 'sched_event_type_start_1week_before',
+      'title' => 'sched_event_type_start_1week_before',
       'absolute_date' => '',
-      'body_html' => '<p>body sched_eventtype_start_1week_before ({event.title})</p>',
-      'body_text' => 'body sched_eventtype_start_1week_before ({event.title})',
+      'body_html' => '<p>body sched_event_type_start_1week_before ({event.title})</p>',
+      'body_text' => 'body sched_event_type_start_1week_before ({event.title})',
       'end_action' => '',
       'end_date' => '',
       'end_frequency_interval' => '',
@@ -625,14 +628,14 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'start_action_date' => 'event_start_date',
       'start_action_offset' => '1',
       'start_action_unit' => 'week',
-      'subject' => 'subject sched_eventtype_start_1week_before ({event.title})',
+      'subject' => 'subject sched_event_type_start_1week_before ({event.title})',
     ];
-    $this->fixtures['sched_eventtype_end_2month_repeat_twice_2_weeks'] = [
-      'name' => 'sched_eventtype_end_2month_repeat_twice_2_weeks',
-      'title' => 'sched_eventtype_end_2month_repeat_twice_2_weeks',
+    $this->fixtures['sched_event_type_end_2month_repeat_twice_2_weeks'] = [
+      'name' => 'sched_event_type_end_2month_repeat_twice_2_weeks',
+      'title' => 'sched_event_type_end_2month_repeat_twice_2_weeks',
       'absolute_date' => '',
-      'body_html' => '<p>body sched_eventtype_end_2month_repeat_twice_2_weeks {event.title}</p>',
-      'body_text' => 'body sched_eventtype_end_2month_repeat_twice_2_weeks {event.title}',
+      'body_html' => '<p>body sched_event_type_end_2month_repeat_twice_2_weeks {event.title}</p>',
+      'body_text' => 'body sched_event_type_end_2month_repeat_twice_2_weeks {event.title}',
       'end_action' => 'after',
       'end_date' => 'event_end_date',
       'end_frequency_interval' => '3',
@@ -657,7 +660,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'start_action_date' => 'event_end_date',
       'start_action_offset' => '2',
       'start_action_unit' => 'month',
-      'subject' => 'subject sched_eventtype_end_2month_repeat_twice_2_weeks {event.title}',
+      'subject' => 'subject sched_event_type_end_2month_repeat_twice_2_weeks {event.title}',
     ];
 
     $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'] = [
@@ -756,7 +759,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'id' => $customField['id'],
       'token' => sprintf('{contact.custom_%s}', $customField['id']),
       'name' => sprintf('custom_%s', $customField['id']),
-      'value' => 'text ' . substr(sha1(rand()), 0, 7),
+      'value' => 'text ' . substr(sha1(mt_rand()), 0, 7),
     ];
 
     $this->_setUp();
@@ -769,7 +772,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function tearDown() {
+  public function tearDown(): void {
     parent::tearDown();
     $this->mut->clearMessages();
     $this->mut->stop();
@@ -778,14 +781,11 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'civicrm_action_schedule',
       'civicrm_action_log',
       'civicrm_membership',
+      'civicrm_line_item',
       'civicrm_participant',
       'civicrm_event',
       'civicrm_email',
-    ]);
-    $this->callAPISuccess('CustomField', 'delete', ['id' => $this->fixtures['contact_custom_token']['id']]);
-    $this->callAPISuccess('CustomGroup', 'delete', [
-      'id' => CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', 'test_contact_cg', 'id', 'name'),
-    ]);
+    ], TRUE);
     $this->_tearDown();
   }
 
@@ -794,7 +794,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @return array
    */
-  public function mailerExamples() {
+  public function mailerExamples(): array {
     $cases = [];
 
     // Some tokens - short as subject has 128char limit in DB.
@@ -853,7 +853,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       ],
     ];
 
-    // In this example, we autoconvert HTML to text
+    // In this example, we auto-convert HTML to text
     $cases[2] = [
       // Schedule definition.
       [
@@ -901,17 +901,11 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    * @throws \API_Exception
    * @throws \CRM_Core_Exception
    * @throws \Civi\API\Exception\UnauthorizedException
-   *
    * @dataProvider mailerExamples
-   *
    */
-  public function testMailer($schedule, $patterns) {
-    $actionSchedule = array_merge($this->fixtures['sched_activity_1day'], $schedule);
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertInternalType('numeric', $actionScheduleDao->id);
-
-    $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
-    $this->assertInternalType('numeric', $activity->id);
+  public function testMailer(array $schedule, array $patterns): void {
+    $this->createScheduleFromFixtures('sched_activity_1day', $schedule);
+    $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phone_call']);
     $contact = $this->callAPISuccess('contact', 'create', array_merge(
       $this->fixtures['contact'],
       [
@@ -960,15 +954,15 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
   /**
    * Test calculated activity schedule.
    *
+   * @throws \API_Exception
    * @throws \CRM_Core_Exception
    */
-  public function testActivityDateTimeMatchNonRepeatableSchedule() {
+  public function testActivityDateTimeMatchNonRepeatableSchedule(): void {
     $this->createScheduleFromFixtures('sched_activity_1day');
 
-    $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
-    $this->assertInternalType('numeric', $activity->id);
+    $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phone_call']);
     $contact = $this->callAPISuccess('contact', 'create', $this->fixtures['contact']);
-    $activity->subject = 'Test subject for Phonecall';
+    $activity->subject = 'Test subject for phone_call';
     $activity->save();
 
     $source['contact_id'] = $contact['id'];
@@ -996,13 +990,13 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
         'recipients' => [],
       ],
     ]);
-    $activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, FALSE, FALSE, 'name');
-    $activityDAO = new CRM_Activity_DAO_Activity();
-    $activityDAO->source_record_id = $activity->id;
-    $activityDAO->activity_type_id = array_search('Reminder Sent', $activityTypes);
-    $activityDAO->find();
-    while ($activityDAO->fetch()) {
-      $this->assertContains($activity->subject, $activityDAO->details);
+    $activities = Activity::get(FALSE)
+      ->setSelect(['details'])
+      ->addWhere('activity_type_id:name', '=', 'Reminder Sent')
+      ->addWhere('source_record_id', '=', $activity->id)
+      ->execute();
+    foreach ($activities as $activityDetails) {
+      $this->assertContains($activity->subject, $activityDetails['details']);
     }
   }
 
@@ -1011,24 +1005,14 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testActivityDateTimeMatchRepeatableSchedule() {
+  public function testActivityDateTimeMatchRepeatableSchedule(): void {
     $this->createScheduleFromFixtures('sched_activity_1day_r');
-
-    $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
-    $this->assertTrue(is_numeric($activity->id));
-    $contact = $this->callAPISuccess('contact', 'create', $this->fixtures['contact']);
-    $activity->save();
-
-    $source['contact_id'] = $contact['id'];
-    $source['activity_id'] = $activity->id;
-    $source['record_type_id'] = 2;
-    $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
-    $activityContact->save();
+    $this->createActivityAndContactFromFixtures();
 
     $this->assertCronRuns([
       [
         // Before the 24-hour mark, no email
-        'time' => '012-06-14 04:00:00',
+        'time' => '2012-06-14 04:00:00',
         'recipients' => [],
         'subjects' => [],
       ],
@@ -1056,19 +1040,9 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
   /**
    * @throws \CRM_Core_Exception
    */
-  public function testActivityDateTimeMatchRepeatableScheduleOnAbsDate() {
+  public function testActivityDateTimeMatchRepeatableScheduleOnAbsDate(): void {
     $this->createScheduleFromFixtures('sched_activity_1day_r_on_abs_date');
-
-    $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
-    $this->assertInternalType('numeric', $activity->id);
-    $contact = $this->callAPISuccess('contact', 'create', $this->fixtures['contact']);
-    $activity->save();
-
-    $source['contact_id'] = $contact['id'];
-    $source['activity_id'] = $activity->id;
-    $source['record_type_id'] = 2;
-    $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
-    $activityContact->save();
+    $this->createActivityAndContactFromFixtures();
 
     $this->assertCronRuns([
       [
@@ -1103,7 +1077,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testEventNameWithAbsoluteDateAndNothingElse() {
+  public function testEventNameWithAbsoluteDateAndNothingElse(): void {
     $participant = $this->createTestObject('CRM_Event_DAO_Participant', array_merge($this->fixtures['participant'], ['status_id' => 1]));
     $this->callAPISuccess('Email', 'create', [
       'contact_id' => $participant->contact_id,
@@ -1111,7 +1085,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     ]);
     $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $participant->contact_id]));
 
-    $actionSchedule = $this->fixtures['sched_eventname_1day_on_abs_date'];
+    $actionSchedule = $this->fixtures['sched_event_name_1day_on_abs_date'];
     $actionSchedule['entity_value'] = $participant->event_id;
     $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
 
@@ -1126,7 +1100,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
         // On absolute date set on 2012-06-14
         'time' => '2012-06-14 00:00:00',
         'recipients' => [['test-event@example.com']],
-        'subjects' => ['sched_eventname_1day_on_abs_date'],
+        'subjects' => ['sched_event_name_1day_on_abs_date'],
       ],
       [
         // Run cron 4 hours later; first message already sent
@@ -1137,21 +1111,14 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     ]);
   }
 
-  /**
-   * For contacts/activities which don't match the schedule filter,
-   * an email should *not* be sent.
-   */
-  // TODO // function testActivityDateTime_NonMatch() { }
-
   /**
    * For contacts/members which match schedule based on join/start date,
    * an email should be sent.
    *
    * @throws \CRM_Core_Exception
    */
-  public function testMembershipDateMatch() {
+  public function testMembershipDateMatch(): void {
     $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], ['status_id' => 1]));
-    $this->assertInternalType('numeric', $membership->id);
     $this->callAPISuccess('Email', 'create', [
       'contact_id' => $membership->contact_id,
       'email' => 'test-member@example.com',
@@ -1160,10 +1127,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     ]);
 
     $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
-    $actionSchedule = $this->fixtures['sched_membership_join_2week'];
-    $actionSchedule['entity_value'] = $membership->membership_type_id;
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertInternalType('numeric', $actionScheduleDao->id);
+    $this->createScheduleFromFixtures('sched_membership_join_2week', ['entity_value' => $membership->membership_type_id]);
 
     // start_date=2012-03-15 ; schedule is 2 weeks after join_date
     $this->assertCronRuns([
@@ -1181,10 +1145,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       ],
     ]);
 
-    $actionSchedule = $this->fixtures['sched_membership_start_1week'];
-    $actionSchedule['entity_value'] = $membership->membership_type_id;
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertInternalType('numeric', $actionScheduleDao->id);
+    $this->createScheduleFromFixtures('sched_membership_start_1week', ['entity_value' => $membership->membership_type_id]);
 
     // start_date=2012-03-15 ; schedule is 1 weeks after start_date
     $this->assertCronRuns([
@@ -1207,8 +1168,9 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    * CRM-21675: Support parent and smart group in 'Limit to' field
    *
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testScheduleReminderWithParentGroup() {
+  public function testScheduleReminderWithParentGroup(): void {
     // Contact A with birth-date at '07-07-2005' and gender - Male, later got added in smart group
     $this->individualCreate(['birth_date' => '20050707', 'gender_id' => 1, 'email' => 'abc@test.com']);
     // Contact B with birth-date at '07-07-2005', later got added in regular group
@@ -1235,8 +1197,8 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     );
 
     $actionScheduleParams = [
-      'name' => 'sched_contact_bday_yesterday',
-      'title' => 'sched_contact_bday_yesterday',
+      'name' => 'sched_contact_birth_day_yesterday',
+      'title' => 'sched_contact_birth_day_yesterday',
       'absolute_date' => '',
       'body_html' => '<p>you look like you were born yesterday!</p>',
       'body_text' => 'you look like you were born yesterday!',
@@ -1262,13 +1224,12 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'start_action_date' => 'date_field',
       'start_action_offset' => '1',
       'start_action_unit' => 'day',
-      'subject' => 'subject sched_contact_bday_yesterday',
+      'subject' => 'subject sched_contact_birth_day_yesterday',
     ];
 
-    // Create schedule reminder where parent group ($groupID) is selectd to limit recipients,
+    // Create schedule reminder where parent group ($groupID) is selected to limit recipients,
     // which contain a individual contact - $contactID2 and is parent to smart group.
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionScheduleParams);
-    $this->assertTrue(is_numeric($actionScheduleDao->id));
+    $this->callAPISuccess('ActionSchedule', 'create', $actionScheduleParams);
     $this->assertCronRuns([
       [
         // On the birthday, no email.
@@ -1299,17 +1260,13 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    * an email should be sent.
    *
    * @throws \API_Exception
-   * @throws \Civi\API\Exception\UnauthorizedException
+   * @throws \CRM_Core_Exception
    */
-  public function testMembershipJoinDateNonMatch() {
+  public function testMembershipJoinDateNonMatch(): void {
     $this->createMembershipFromFixture('rolling_membership', '', ['email' => 'test-member@example.com']);
     // Add an alternative membership type, and only send messages for that type
     $extraMembershipType = $this->createTestObject('CRM_Member_DAO_MembershipType', []);
-    $this->assertInternalType('numeric', $extraMembershipType->id);
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($this->fixtures['sched_membership_join_2week']);
-    $this->assertInternalType('numeric', $actionScheduleDao->id);
-    $actionScheduleDao->entity_value = $extraMembershipType->id;
-    $actionScheduleDao->save();
+    $this->createScheduleFromFixtures('sched_membership_join_2week', ['entity_value' => $extraMembershipType->id]);
 
     // start_date=2012-03-15 ; schedule is 2 weeks after start_date
     $this->assertCronRuns([
@@ -1324,9 +1281,10 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
   /**
    * Test that the first and SECOND notifications are sent out.
    *
+   * @throws \API_Exception
    * @throws \CRM_Core_Exception
    */
-  public function testMembershipEndDateRepeat() {
+  public function testMembershipEndDateRepeat(): void {
     // creates membership with end_date = 20120615
     $membership = $this->createMembershipFromFixture('rolling_membership', 'Current');
     $this->callAPISuccess('Email', 'create', [
@@ -1335,9 +1293,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     ]);
     $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
 
-    $actionSchedule = $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'];
-    $actionSchedule['entity_value'] = $membership->membership_type_id;
-    $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
+    $this->createScheduleFromFixtures('sched_membership_end_2month_repeat_twice_4_weeks', ['entity_value' => $membership->membership_type_id]);
 
     // end_date=2012-06-15 ; schedule is 2 weeks before end_date
     $this->assertCronRuns([
@@ -1389,9 +1345,10 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    * between
    *  see CRM-15376
    *
+   * @throws \API_Exception
    * @throws \CRM_Core_Exception
    */
-  public function testMembershipEndDateRepeatChangedEndDate_CRM_15376() {
+  public function testMembershipEndDateRepeatChangedEndDate_CRM_15376(): void {
     // creates membership with end_date = 20120615
     $membership = $this->createMembershipFromFixture('rolling_membership', 'Current');
     $this->callAPISuccess('Email', 'create', [
@@ -1400,9 +1357,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     ]);
     $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
 
-    $actionSchedule = $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'];
-    $actionSchedule['entity_value'] = $membership->membership_type_id;
-    $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
+    $this->createScheduleFromFixtures('sched_membership_end_2month_repeat_twice_4_weeks', ['entity_value' => $membership->membership_type_id]);
     // end_date=2012-06-15 ; schedule is 2 weeks before end_date
     $this->assertCronRuns([
       [
@@ -1431,9 +1386,8 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws \API_Exception
    * @throws \CRM_Core_Exception
-   * @throws \Civi\API\Exception\UnauthorizedException
    */
-  public function testMembershipEndDateMatch() {
+  public function testMembershipEndDateMatch(): void {
     // creates membership with end_date = 20120615
     $membership = $this->createMembershipFromFixture('rolling_membership', 'Current');
     $this->callAPISuccess('Email', 'create', [
@@ -1442,10 +1396,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     ]);
     $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
 
-    $actionSchedule = $this->fixtures['sched_membership_end_2week'];
-    $actionSchedule['entity_value'] = $membership->membership_type_id;
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertTrue(is_numeric($actionScheduleDao->id));
+    $this->createScheduleFromFixtures('sched_membership_end_2week', ['entity_value' => $membership->membership_type_id]);
 
     // end_date=2012-06-15 ; schedule is 2 weeks before end_date
     $this->assertCronRuns([
@@ -1529,7 +1480,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    * @return array|NULL|object
    * @throws \CRM_Core_Exception
    */
-  public function createMembershipAndContact($contactFixture, $membershipTypeId) {
+  public function createMembershipAndContact(array $contactFixture, int $membershipTypeId) {
     $result = $this->callAPISuccess('contact', 'create', $contactFixture);
     $contact = $result['values'][$result['id']];
     $params = [
@@ -1539,9 +1490,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'owner_membership_id' => 'NULL',
     ];
     $params = array_merge($this->fixtures['rolling_membership'], $params);
-    $membership = $this->createTestObject('CRM_Member_DAO_Membership', $params);
-    $this->assertInternalType('numeric', $membership->id);
-    return $membership;
+    return $this->createTestObject('CRM_Member_DAO_Membership', $params);
   }
 
   /**
@@ -1553,14 +1502,11 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testMultipleMembershipEndDateMatch() {
+  public function testMultipleMembershipEndDateMatch(): void {
     $membershipTypeId = $this->membershipTypeCreate($this->fixtures['rolling_membership']['membership_type_id']);
     $membershipOne = $this->createMembershipAndContact($this->fixtures['contact'], $membershipTypeId);
     $membershipTwo = $this->createMembershipAndContact($this->fixtures['contact_2'], $membershipTypeId);
-    $actionSchedule = $this->fixtures['sched_membership_end_2week'];
-    $actionSchedule['entity_value'] = $membershipTypeId;
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertTrue(is_numeric($actionScheduleDao->id));
+    $this->createScheduleFromFixtures('sched_membership_end_2week', ['entity_value' => $membershipTypeId]);
 
     // end_date=2012-06-15 ; schedule is 2 weeks before end_date
     $this->assertCronRuns([
@@ -1620,9 +1566,10 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    * For contacts/members which match schedule based on end date,
    * an email should be sent.
    *
+   * @throws \API_Exception
    * @throws \CRM_Core_Exception
    */
-  public function testMembershipEndDateNoMatch() {
+  public function testMembershipEndDateNoMatch(): void {
     // creates membership with end_date = 20120615
     $membership = $this->createMembershipFromFixture('rolling_membership', 'Grace');
     $this->callAPISuccess('Email', 'create', [
@@ -1630,11 +1577,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       'email' => 'test-member@example.com',
     ]);
     $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
-
-    $actionSchedule = $this->fixtures['sched_membership_end_2month'];
-    $actionSchedule['entity_value'] = $membership->membership_type_id;
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertTrue(is_numeric($actionScheduleDao->id));
+    $this->createScheduleFromFixtures('sched_membership_end_2month', ['entity_value' => $membership->membership_type_id]);
 
     // end_date=2012-06-15 ; schedule is 2 weeks before end_date
     $this->assertCronRuns([
@@ -1654,12 +1597,10 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
   /**
    * @throws \CRM_Core_Exception
    */
-  public function testContactBirthDateNoAnniv() {
+  public function testContactBirthDateNoAnniversary(): void {
     $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
     $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
-    $actionSchedule = $this->fixtures['sched_contact_bday_yesterday'];
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertInternalType('numeric', $actionScheduleDao->id);
+    $this->createScheduleFromFixtures('sched_contact_birth_day_yesterday');
     $this->assertCronRuns([
       [
         // On the birthday, no email.
@@ -1669,7 +1610,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       [
         // The next day, send an email.
         'time' => '2005-07-08 20:00:00',
-        'recipients' => [['test-bday@example.com']],
+        'recipients' => [['test-birth_day@example.com']],
       ],
     ]);
   }
@@ -1677,12 +1618,10 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
   /**
    * @throws \CRM_Core_Exception
    */
-  public function testContactBirthDateAnniversary() {
+  public function testContactBirthDateAnniversary(): void {
     $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
     $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
-    $actionSchedule = $this->fixtures['sched_contact_bday_anniv'];
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertTrue(is_numeric($actionScheduleDao->id));
+    $this->createScheduleFromFixtures('sched_contact_birth_day_anniversary');
     $this->assertCronRuns([
       [
         // On some random day, no email.
@@ -1692,7 +1631,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       [
         // On the eve of their 9th birthday, send an email.
         'time' => '2014-07-06 20:00:00',
-        'recipients' => [['test-bday@example.com']],
+        'recipients' => [['test-birth_day@example.com']],
       ],
     ]);
   }
@@ -1700,7 +1639,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
   /**
    * @throws \CRM_Core_Exception
    */
-  public function testContactCustomDateNoAnniversary() {
+  public function testContactCustomDateNoAnniversary(): void {
     $group = [
       'title' => 'Test_Group',
       'name' => 'test_group',
@@ -1721,10 +1660,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     $contactParams["custom_{$createField['id']}"] = '2013-12-16';
     $contact = $this->callAPISuccess('Contact', 'create', $contactParams);
     $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
-    $actionSchedule = $this->fixtures['sched_contact_grad_tomorrow'];
-    $actionSchedule['entity_value'] = "custom_{$createField['id']}";
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertTrue(is_numeric($actionScheduleDao->id));
+    $this->createScheduleFromFixtures('sched_contact_grad_tomorrow', ['entity_value' => "custom_{$createField['id']}"]);
     $this->assertCronRuns([
       [
         // On some random day, no email.
@@ -1743,7 +1679,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
   /**
    * @throws \CRM_Core_Exception
    */
-  public function testContactCreatedNoAnniversary() {
+  public function testContactCreatedNoAnniversary(): void {
     $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
     $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
     $this->createScheduleFromFixtures('sched_contact_created_yesterday');
@@ -1756,7 +1692,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       [
         // The next day, send an email.
         'time' => date('Y-m-d H:i:s', strtotime($contact['values'][$contact['id']]['created_date'] . ' +1 day')),
-        'recipients' => [['test-bday@example.com']],
+        'recipients' => [['test-birth_day@example.com']],
       ],
     ]);
   }
@@ -1766,13 +1702,11 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testContactModifiedAnniversary() {
+  public function testContactModifiedAnniversary(): void {
     $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
     $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
     $modifiedDate = $this->callAPISuccess('Contact', 'getvalue', ['id' => $contact['id'], 'return' => 'modified_date']);
-    $actionSchedule = $this->fixtures['sched_contact_mod_anniv'];
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertInternalType('numeric', $actionScheduleDao->id);
+    $this->createScheduleFromFixtures('sched_contact_mod_anniversary');
     $this->assertCronRuns([
       [
         // On some random day, no email.
@@ -1782,7 +1716,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       [
         // On the eve of 3 years after they were modified, send an email.
         'time' => date('Y-m-d H:i:s', strtotime($modifiedDate . ' +3 years -1 day')),
-        'recipients' => [['test-bday@example.com']],
+        'recipients' => [['test-birth_day@example.com']],
       ],
     ]);
   }
@@ -1792,9 +1726,8 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws \API_Exception
    * @throws \CRM_Core_Exception
-   * @throws \Civi\API\Exception\UnauthorizedException
    */
-  public function testMembershipLimitToNone() {
+  public function testMembershipLimitToNone(): void {
     // creates membership with end_date = 20120615
     $membership = $this->createMembershipFromFixture('rolling_membership', 'Current');
     $result = $this->callAPISuccess('Email', 'create', [
@@ -1806,17 +1739,13 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
 
     $this->assertAPISuccess($result);
 
-    $actionSchedule = $this->fixtures['sched_membership_end_limit_to_none'];
-    $actionSchedule['entity_value'] = $membership->membership_type_id;
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertTrue(is_numeric($actionScheduleDao->id));
+    $this->createScheduleFromFixtures('sched_membership_end_limit_to_none', ['entity_value' => $membership->membership_type_id]);
 
     // end_date=2012-06-15 ; schedule is 2 weeks before end_date
     $this->assertCronRuns([
       [
         // Before the 2-week mark, no email.
         'time' => '2012-05-31 01:00:00',
-        // 'time' => '2012-06-01 01:00:00', // FIXME: Is this the right boundary?
         'recipients' => [],
       ],
     ]);
@@ -1827,16 +1756,12 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws \API_Exception
    * @throws \CRM_Core_Exception
-   * @throws \Civi\API\Exception\UnauthorizedException
    */
-  public function testMembershipWithReferenceDate() {
+  public function testMembershipWithReferenceDate(): void {
     $membership = $this->createMembershipFromFixture('rolling_membership', 'Current', ['email' => 'member@example.com']);
     $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
 
-    $actionSchedule = $this->fixtures['sched_membership_join_2week'];
-    $actionSchedule['entity_value'] = $membership->membership_type_id;
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertInternalType('numeric', $actionScheduleDao->id);
+    $this->createScheduleFromFixtures('sched_membership_join_2week', ['entity_value' => $membership->membership_type_id]);
 
     // start_date=2012-03-15 ; schedule is 2 weeks after start_date
     $this->assertCronRuns([
@@ -1888,9 +1813,8 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws \API_Exception
    * @throws \CRM_Core_Exception
-   * @throws \Civi\API\Exception\UnauthorizedException
    */
-  public function testMembershipOnMultipleReminder() {
+  public function testMembershipOnMultipleReminder(): void {
     $membership = $this->createMembershipFromFixture('rolling_membership', 'Current', ['email' => 'member@example.com']);
     $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
 
@@ -1903,7 +1827,6 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     $actionScheduleBefore['entity_value'] = $actionScheduleOn['entity_value'] = $actionScheduleAfter['entity_value'] = $membership->membership_type_id;
     foreach (['actionScheduleBefore', 'actionScheduleOn', 'actionScheduleAfter'] as $value) {
       $$value = CRM_Core_BAO_ActionSchedule::add($$value);
-      $this->assertInternalType('numeric', $$value->id);
     }
 
     $this->assertCronRuns(
@@ -2006,34 +1929,18 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
   /**
    * Test reminders sent on custom data anniversary.
    *
+   * @throws \API_Exception
    * @throws \CRM_Core_Exception
    */
-  public function testContactCustomDate_Anniversary() {
-    $group = [
-      'title' => 'Test_Group now',
-      'name' => 'test_group_now',
-      'extends' => ['Individual'],
-      'style' => 'Inline',
-      'is_multiple' => FALSE,
-      'is_active' => 1,
-    ];
-    $createGroup = $this->callAPISuccess('custom_group', 'create', $group);
-    $field = [
-      'label' => 'Graduation',
-      'data_type' => 'Date',
-      'html_type' => 'Select Date',
-      'custom_group_id' => $createGroup['id'],
-    ];
-    $createField = $this->callAPISuccess('custom_field', 'create', $field);
-
+  public function testContactCustomDate_Anniversary(): void {
+    $this->createCustomGroupWithFieldOfType([], 'date');
     $contactParams = $this->fixtures['contact'];
-    $contactParams["custom_{$createField['id']}"] = '2013-12-16';
+    $contactParams[$this->getCustomFieldName('date')] = '2013-12-16';
     $contact = $this->callAPISuccess('Contact', 'create', $contactParams);
     $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
-    $actionSchedule = $this->fixtures['sched_contact_grad_anniv'];
-    $actionSchedule['entity_value'] = "custom_{$createField['id']}";
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertTrue(is_numeric($actionScheduleDao->id));
+    $this->fixtures['sched_contact_grad_anniversary']['entity_value'] = $this->getCustomFieldName('date');
+    $this->createScheduleFromFixtures('sched_contact_grad_anniversary');
+
     $this->assertCronRuns([
       [
         // On some random day, no email.
@@ -2046,15 +1953,15 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
         'recipients' => [['test-member@example.com']],
       ],
     ]);
-    $this->callAPISuccess('custom_group', 'delete', ['id' => $createGroup['id']]);
   }
 
   /**
    * Test sched reminder set via registration date.
    *
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testEventTypeRegistrationDate() {
+  public function testEventTypeRegistrationDate(): void {
     $contact = $this->individualCreate(['email' => 'test-event@example.com']);
     //Add it as a participant to an event ending registration - 7 days from now.
     $params = [
@@ -2067,7 +1974,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     $this->participantCreate(['contact_id' => $contact, 'event_id' => $event['id']]);
 
     //Create a scheduled reminder to send email 7 days before registration date.
-    $actionSchedule = $this->fixtures['sched_eventtype_start_1week_before'];
+    $actionSchedule = $this->fixtures['sched_event_type_start_1week_before'];
     $actionSchedule['start_action_offset'] = 7;
     $actionSchedule['start_action_unit'] = 'day';
     $actionSchedule['start_action_date'] = 'registration_end_date';
@@ -2125,7 +2032,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testEventTypeStartDate() {
+  public function testEventTypeStartDate(): void {
     // Create event+participant with start_date = 20120315, end_date = 20120615.
     $participant = $this->createTestObject('CRM_Event_DAO_Participant', array_merge($this->fixtures['participant'], ['status_id' => 2]));
     $this->callAPISuccess('Email', 'create', [
@@ -2134,7 +2041,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     ]);
     $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $participant->contact_id]));
 
-    $actionSchedule = $this->fixtures['sched_eventtype_start_1week_before'];
+    $actionSchedule = $this->fixtures['sched_event_type_start_1week_before'];
     $actionSchedule['entity_value'] = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $participant->event_id, 'event_type_id');
     $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
 
@@ -2165,7 +2072,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testEventTypeEndDateRepeat() {
+  public function testEventTypeEndDateRepeat(): void {
     // Create event+participant with start_date = 20120315, end_date = 20120615.
     $participant = $this->createTestObject('CRM_Event_DAO_Participant', array_merge($this->fixtures['participant'], ['status_id' => 2]));
     $this->callAPISuccess('Email', 'create', [
@@ -2174,7 +2081,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     ]);
     $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $participant->contact_id]));
 
-    $actionSchedule = $this->fixtures['sched_eventtype_end_2month_repeat_twice_2_weeks'];
+    $actionSchedule = $this->fixtures['sched_event_type_end_2month_repeat_twice_2_weeks'];
     $actionSchedule['entity_value'] = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $participant->event_id, 'event_type_id');
     $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
 
@@ -2212,12 +2119,6 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     ]);
   }
 
-  // TODO // function testMembershipEndDate_NonMatch() { }
-  // TODO // function testEventTypeStartDate_Match() { }
-  // TODO // function testEventTypeEndDate_Match() { }
-  // TODO // function testEventNameStartDate_Match() { }
-  // TODO // function testEventNameEndDate_Match() { }
-
   /**
    * Run a series of cron jobs and make an assertion about email deliveries.
    *
@@ -2227,8 +2128,9 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *   - recipients: array(array(string)), list of email addresses which should receive messages
    *
    * @throws \CRM_Core_Exception
+   * @noinspection DisconnectedForeachInstructionInspection
    */
-  public function assertCronRuns($cronRuns) {
+  public function assertCronRuns(array $cronRuns): void {
     foreach ($cronRuns as $cronRun) {
       CRM_Utils_Time::setTime($cronRun['time']);
       $this->callAPISuccess('job', 'send_reminder', []);
@@ -2242,6 +2144,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
 
   /**
    * @var array
+   *
    * (DAO_Name => array(int)) List of items to garbage-collect during tearDown
    */
   private $_testObjects;
@@ -2251,7 +2154,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * This method is called before a test is executed.
    */
-  protected function _setUp() {
+  protected function _setUp(): void {
     $this->_testObjects = [];
   }
 
@@ -2260,7 +2163,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * This method is called after a test is executed.
    */
-  protected function _tearDown() {
+  protected function _tearDown(): void {
     parent::tearDown();
     $this->deleteTestObjects();
   }
@@ -2293,17 +2196,17 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    * @param array $objects
    *   DAO or BAO objects.
    */
-  public function registerTestObjects($objects) {
+  public function registerTestObjects(array $objects): void {
     //if (is_object($objects)) {
     //  $objects = array($objects);
     //}
     foreach ($objects as $object) {
-      $daoName = preg_replace('/_BAO_/', '_DAO_', get_class($object));
+      $daoName = str_replace('_BAO_', '_DAO_', get_class($object));
       $this->_testObjects[$daoName][] = $object->id;
     }
   }
 
-  public function deleteTestObjects() {
+  public function deleteTestObjects(): void {
     // Note: You might argue that the FK relations between test
     // objects could make this problematic; however, it should
     // behave intuitively as long as we mentally split our
@@ -2319,9 +2222,11 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
 
   /**
    * Test that the various repetition units work correctly.
+   *
    * @see https://issues.civicrm.org/jira/browse/CRM-17028
+   * @throws \CRM_Core_Exception
    */
-  public function testRepetitionFrequencyUnit() {
+  public function testRepetitionFrequencyUnit(): void {
     $membershipTypeParams = [
       'duration_interval' => '1',
       'duration_unit' => 'year',
@@ -2331,7 +2236,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
     $membershipType = $this->createTestObject('CRM_Member_DAO_MembershipType', $membershipTypeParams);
     $interval_units = ['hour', 'day', 'week', 'month', 'year'];
     foreach ($interval_units as $interval_unit) {
-      $membershipEndDate = DateTime::createFromFormat('Y-m-d H:i:s', "2013-03-15 00:00:00");
+      $membershipEndDate = DateTime::createFromFormat('Y-m-d H:i:s', '2013-03-15 00:00:00');
       $contactParams = [
         'contact_type' => 'Individual',
         'first_name' => 'Test',
@@ -2339,15 +2244,13 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
         'is_deceased' => 0,
       ];
       $contact = $this->createTestObject('CRM_Contact_DAO_Contact', $contactParams);
-      $this->assertTrue(is_numeric($contact->id));
       $emailParams = [
         'contact_id' => $contact->id,
         'is_primary' => 1,
         'email' => "test-member-{$interval_unit}@example.com",
         'location_type_id' => 1,
       ];
-      $email = $this->createTestObject('CRM_Core_DAO_Email', $emailParams);
-      $this->assertTrue(is_numeric($email->id));
+      $this->createTestObject('CRM_Core_DAO_Email', $emailParams);
       $membershipParams = [
         'membership_type_id' => $membershipType->id,
         'contact_id' => $contact->id,
@@ -2364,7 +2267,6 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
       $actionScheduleParams['repetition_frequency_unit'] = $interval_unit;
       $actionScheduleParams['repetition_frequency_interval'] = 2;
       $actionSchedule = CRM_Core_BAO_ActionSchedule::add($actionScheduleParams);
-      $this->assertTrue(is_numeric($actionSchedule->id));
       $beforeEndDate = $this->createModifiedDateTime($membershipEndDate, '-1 day');
       $beforeFirstUnit = $this->createModifiedDateTime($membershipEndDate, "+1 $interval_unit");
       $afterFirstUnit = $this->createModifiedDateTime($membershipEndDate, "+2 $interval_unit");
@@ -2403,7 +2305,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testInheritedMembershipPermissions() {
+  public function testInheritedMembershipPermissions(): void {
     // Set up common parameters for memberships.
     $membershipParams = $this->fixtures['rolling_membership'];
     $membershipParams['status_id'] = 1;
@@ -2476,10 +2378,8 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
 
     // Test a reminder for the first membership type - that should exclude Black
     // Sheep.
-    $actionSchedule = $this->fixtures['sched_membership_join_2week'];
-    $actionSchedule['entity_value'] = $membershipType1->id;
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertTrue(is_numeric($actionScheduleDao->id));
+    $this->fixtures['sched_membership_join_2week']['entity_value'] = $membershipType1->id;
+    $this->createScheduleFromFixtures('sched_membership_join_2week');
 
     $this->assertCronRuns([
       [
@@ -2494,10 +2394,8 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
 
     // Test a reminder for the second membership type - that should include
     // Black Sheep.
-    $actionSchedule = $this->fixtures['sched_membership_start_1week'];
-    $actionSchedule['entity_value'] = $membershipType2->id;
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertInternalType('numeric', $actionScheduleDao->id);
+    $this->fixtures['sched_membership_start_1week']['entity_value'] = $membershipType2->id;
+    $this->createScheduleFromFixtures('sched_membership_start_1week');
 
     $this->assertCronRuns([
       [
@@ -2519,7 +2417,7 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @return DateTime
    */
-  public function createModifiedDateTime($origDateTime, $modifyRule) {
+  public function createModifiedDateTime(DateTime $origDateTime, string $modifyRule): DateTime {
     $newDateTime = clone($origDateTime);
     $newDateTime->modify($modifyRule);
     return $newDateTime;
@@ -2528,19 +2426,18 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
   /**
    * Test absolute date handling for membership.
    *
+   * @throws \API_Exception
    * @throws \CRM_Core_Exception
    */
-  public function testMembershipScheduleWithAbsoluteDate() {
+  public function testMembershipScheduleWithAbsoluteDate(): void {
     $membership = $this->createMembershipFromFixture('rolling_membership', 'New', [
       'email' => 'test-member@example.com',
       'location_type_id' => 1,
     ]);
 
     $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
-    $actionSchedule = $this->fixtures['sched_membership_absolute_date'];
-    $actionSchedule['entity_value'] = $membership->membership_type_id;
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
-    $this->assertInternalType('numeric', $actionScheduleDao->id);
+    $this->fixtures['sched_membership_absolute_date']['entity_value'] = $membership->membership_type_id;
+    $this->createScheduleFromFixtures('sched_membership_absolute_date');
 
     $this->assertCronRuns([
       [
@@ -2573,15 +2470,13 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    *
    * @return \CRM_Member_DAO_Membership
    * @throws \API_Exception
-   * @throws \Civi\API\Exception\UnauthorizedException
    */
-  protected function createMembershipFromFixture($fixture, $status, $emailParams = []) {
+  protected function createMembershipFromFixture(string $fixture, string $status, $emailParams = []): CRM_Member_DAO_Membership {
     /* @var CRM_Member_DAO_Membership $membership */
     $membership = $this->createTestObject(
       'CRM_Member_DAO_Membership',
       array_merge($this->fixtures[$fixture], ['status_id' => CRM_Core_PseudoConstant::getKey('CRM_Member_BAO_Membership', 'status_id', $status)])
     );
-    $this->assertInternalType('numeric', $membership->id);
     if ($emailParams) {
       Civi\Api4\Email::create(FALSE)->setValues(array_merge([
         'contact_id' => $membership->contact_id,
@@ -2595,10 +2490,32 @@ class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
    * Create action schedule from defined fixtures.
    *
    * @param string $fixture
+   * @param array $extraParams
+   *
+   * @throws \CRM_Core_Exception
+   */
+  protected function createScheduleFromFixtures(string $fixture, $extraParams = []): void {
+    $id = $this->callAPISuccess('ActionSchedule', 'create', array_merge($this->fixtures[$fixture], $extraParams))['id'];
+    $this->fixtures[$fixture]['action_schedule_id'] = (int) $id;
+  }
+
+  /**
+   * @param string $activityKey
+   * @param string $contactKey
+   *
+   * @throws \CRM_Core_Exception
    */
-  protected function createScheduleFromFixtures($fixture) {
-    $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($this->fixtures[$fixture]);
-    $this->assertInternalType('numeric', $actionScheduleDao->id);
+  protected function createActivityAndContactFromFixtures(string $activityKey = 'phone_call', string $contactKey = 'contact'): void {
+    $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures[$activityKey]);
+    $contact = $this->callAPISuccess('contact', 'create', $this->fixtures[$contactKey]);
+    $activity->save();
+
+    $source = [];
+    $source['contact_id'] = $contact['id'];
+    $source['activity_id'] = $activity->id;
+    $source['record_type_id'] = 2;
+    $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
+    $activityContact->save();
   }
 
 }
index 92742dc796690ec9d719a2db8218daa4c38d28fd..70678998fd0022bf8c43c2f79d826bcad5b76f18 100644 (file)
@@ -50,6 +50,34 @@ class CRM_Core_BAO_CustomFieldTest extends CiviUnitTestCase {
     $this->customGroupDelete($customGroup['id']);
   }
 
+  /**
+   * Test changing a data type from multiple-choice to Text.
+   */
+  public function testChangeDataType() {
+    $customGroup = $this->createCustomField();
+    $fields = [
+      'label' => 'Radio to Text',
+      'is_active' => 1,
+      'data_type' => 'String',
+      'html_type' => 'Radio',
+      'custom_group_id' => $customGroup['id'],
+      'option_type' => 1,
+      'option_label' => ["One", "Two"],
+      'option_value' => [1, 2],
+      'option_weight' => [1, 2],
+      'option_status' => [1, 1],
+    ];
+    $customField = CRM_Core_BAO_CustomField::create($fields);
+    $this->assertNotNull($customField->option_group_id);
+    $fieldsNew = [
+      'id' => $customField->id,
+      'html_type' => 'Text',
+      'custom_group_id' => $customGroup['id'],
+    ];
+    $customFieldModified = CRM_Core_BAO_CustomField::create($fieldsNew);
+    $this->assertFalse($customFieldModified->option_group_id ?? FALSE);
+  }
+
   /**
    * Test custom field create accepts passed column name.
    */
diff --git a/tests/phpunit/CRM/Core/InvokeTest.php b/tests/phpunit/CRM/Core/InvokeTest.php
new file mode 100644 (file)
index 0000000..a78add4
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved.                        |
+ |                                                                    |
+ | This work is published under the GNU AGPLv3 license with some      |
+ | permitted exceptions and without any warranty. For full license    |
+ | and copyright information, see https://civicrm.org/licensing       |
+ +--------------------------------------------------------------------+
+ */
+
+/**
+ * @group headless
+ */
+class CRM_Core_InvokeTest extends CiviUnitTestCase {
+
+  /**
+   * Test that no php errors come up invoking dashboard url for non-admins
+   * Motivation: This currently fails on php 7.4 because of IDS and magicquotes.
+   */
+  public function testInvokeDashboardForNonAdmin(): void {
+    CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM'];
+
+    $_SERVER['REQUEST_URI'] = 'civicrm/dashboard?reset=1';
+    $_GET['q'] = 'civicrm/dashboard';
+
+    $item = CRM_Core_Invoke::getItem(['civicrm/dashboard?reset=1']);
+    ob_start();
+    CRM_Core_Invoke::runItem($item);
+    ob_end_clean();
+  }
+
+}
index 2095aba6861ac09b9fd3edd2ef4b8476f1dda1a1..08d930defad4ed37286bc2a8a7e8ae97d8d8dede 100644 (file)
@@ -12,7 +12,7 @@ class CRM_Core_Permission_BaseTest extends CiviUnitTestCase {
    * @return array
    *   (0 => input to translatePermission, 1 => expected output from translatePermission)
    */
-  public function translateData() {
+  public function translateData(): array {
     $cases = [];
 
     $cases[] = ['administer CiviCRM', 'administer CiviCRM'];
@@ -35,7 +35,7 @@ class CRM_Core_Permission_BaseTest extends CiviUnitTestCase {
    * @param string $expected
    *   The name of an actual permission (based on translation matrix for "runtime").
    */
-  public function testTranslate($input, $expected) {
+  public function testTranslate(string $input, string $expected): void {
     $perm = new CRM_Core_Permission_Base();
     $actual = $perm->translatePermission($input, 'myruntime', [
       'universal name' => 'local name',
@@ -48,7 +48,7 @@ class CRM_Core_Permission_BaseTest extends CiviUnitTestCase {
   /**
    * Test that the user has the implied permission of administer CiviCRM data by virtue of having administer CiviCRM.
    */
-  public function testImpliedPermission() {
+  public function testImpliedPermission(): void {
     $this->createLoggedInUser();
     CRM_Core_Config::singleton()->userPermissionClass->permissions = [
       'administer CiviCRM',
@@ -56,4 +56,15 @@ class CRM_Core_Permission_BaseTest extends CiviUnitTestCase {
     $this->assertTrue(CRM_Core_Permission::check('administer CiviCRM data'));
   }
 
+  /**
+   * Test that the super permission gives the implied permission of the whole shebang.
+   */
+  public function testImpliedPermissionSuperDuper(): void {
+    $this->createLoggedInUser();
+    CRM_Core_Config::singleton()->userPermissionClass->permissions = [
+      'all CiviCRM permissions and ACLs',
+    ];
+    $this->assertTrue(CRM_Core_Permission::check('view all contacts'));
+  }
+
 }
index 4adb1aa1ab411c559e9f7a919691761593262ffc..f6d00a1c92ca0d689467871475bbb37fb76d4cee 100644 (file)
@@ -35,7 +35,7 @@ class CRM_Core_ResourcesTest extends CiviUnitTestCase {
   protected $originalRequest;
   protected $originalGet;
 
-  public function setUp() {
+  public function setUp(): void {
     parent::setUp();
 
     list ($this->basedir, $this->container, $this->mapper) = $this->_createMapper();
@@ -55,9 +55,10 @@ class CRM_Core_ResourcesTest extends CiviUnitTestCase {
   /**
    * Restore globals so this test doesn't interfere with others.
    */
-  public function tearDown() {
+  public function tearDown(): void {
     $_REQUEST = $this->originalRequest;
     $_GET = $this->originalGet;
+    parent::tearDown();
   }
 
   public function testCreateBasicBundle() {
index 2029614645c496703292b5a7deb03a229085b3f1..525c539d05cd84c69e9fea152252343c86ceeb85 100644 (file)
@@ -23,9 +23,9 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
   /**
    * Tear down.
    *
-   * @throws \Exception
+   * @throws \CRM_Core_Exception
    */
-  public function tearDown() {
+  public function tearDown(): void {
     $this->quickCleanup([
       'civicrm_contact',
       'civicrm_group_contact',
@@ -38,7 +38,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
   /**
    * @throws \CRM_Core_Exception
    */
-  public function createDupeContacts() {
+  public function createDupeContacts(): void {
     // create a group to hold contacts, so that dupe checks don't consider any other contacts in the DB
     $params = [
       'name' => 'Test Dupe Merger Group',
@@ -140,7 +140,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
   /**
    * Delete all created contacts.
    */
-  public function deleteDupeContacts() {
+  public function deleteDupeContacts(): void {
     foreach ($this->_contactIds as $contactId) {
       $this->contactDelete($contactId);
     }
@@ -150,9 +150,11 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
   /**
    * Test the batch merge.
    *
+   * @throws \API_Exception
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testBatchMergeSelectedDuplicates() {
+  public function testBatchMergeSelectedDuplicates(): void {
     $this->createDupeContacts();
 
     // verify that all contacts have been created separately
@@ -198,8 +200,8 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
     CRM_Core_DAO::singleValueQuery("UPDATE civicrm_prevnext_cache SET is_selected = 1 WHERE id IN ({$pnDupePairs[0]['prevnext_id']}, {$pnDupePairs[1]['prevnext_id']})");
 
     $pnDupePairs = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, NULL, NULL, 0, 0, $select);
-    $this->assertEquals($pnDupePairs[0]['is_selected'], 1, 'Check if first record in dupe pairs is marked as selected.');
-    $this->assertEquals($pnDupePairs[0]['is_selected'], 1, 'Check if second record in dupe pairs is marked as selected.');
+    $this->assertEquals(1, $pnDupePairs[0]['is_selected'], 'Check if first record in dupe pairs is marked as selected.');
+    $this->assertEquals(1, $pnDupePairs[0]['is_selected'], 'Check if second record in dupe pairs is marked as selected.');
 
     // batch merge selected dupes
     $result = CRM_Dedupe_Merger::batchMerge($dao->id, $this->_groupId, 'safe', 5, 1);
@@ -313,7 +315,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testGetMatches() {
+  public function testGetMatches(): void {
     $this->setupMatchData();
 
     $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
@@ -351,7 +353,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testGetMatchesExcludeDeleted($isReverse) {
+  public function testGetMatchesExcludeDeleted(bool $isReverse): void {
     $this->setupMatchData();
     $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
       'rule_group_id' => 1,
@@ -372,8 +374,9 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
    * Test that location type is ignored when deduping by postal address.
    *
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testGetMatchesIgnoreLocationType() {
+  public function testGetMatchesIgnoreLocationType(): void {
     $contact1 = $this->individualCreate();
     $contact2 = $this->individualCreate();
     $this->callAPISuccess('address', 'create', [
@@ -396,15 +399,16 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
     $dupeCount = $this->callAPISuccess('Dedupe', 'getduplicates', [
       'rule_group_id' => $ruleGroup['id'],
     ])['count'];
-    $this->assertEquals($dupeCount, 1);
+    $this->assertEquals(1, $dupeCount);
   }
 
   /**
    * Test results are returned when criteria are passed in.
    *
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testGetMatchesCriteriaMatched() {
+  public function testGetMatchesCriteriaMatched(): void {
     $this->setupMatchData();
     $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
       'rule_group_id' => 1,
@@ -417,8 +421,9 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
    * Test results are returned when criteria are passed in & limit is  respected.
    *
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testGetMatchesCriteriaMatchedWithLimit() {
+  public function testGetMatchesCriteriaMatchedWithLimit(): void {
     $this->setupMatchData();
     $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
       'rule_group_id' => 1,
@@ -429,11 +434,13 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
   }
 
   /**
-   * Test results are returned when criteria are passed in & limit is  respected.
+   * Test results are returned when criteria are passed in & limit is
+   * respected.
    *
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testGetMatchesCriteriaMatchedWithSearchLimit() {
+  public function testGetMatchesCriteriaMatchedWithSearchLimit(): void {
     $this->setupMatchData();
     $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
       'rule_group_id' => 1,
@@ -447,8 +454,9 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
    * Test getting matches where there are  no criteria.
    *
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testGetMatchesNoCriteria() {
+  public function testGetMatchesNoCriteria(): void {
     $this->setupMatchData();
     $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
       'rule_group_id' => 1,
@@ -460,8 +468,9 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
    * Test getting matches with a limit in play.
    *
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testGetMatchesNoCriteriaButLimit() {
+  public function testGetMatchesNoCriteriaButLimit(): void {
     $this->setupMatchData();
     $pairs = $this->callAPISuccess('Dedupe', 'getduplicates', [
       'rule_group_id' => 1,
@@ -490,7 +499,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
    *
    * @throws \Exception
    */
-  public function testGetOrganizationMatches() {
+  public function testGetOrganizationMatches(): void {
     $this->setupMatchData();
     $ruleGroups = $this->callAPISuccessGetSingle('RuleGroup', [
       'contact_type' => 'Organization',
@@ -778,7 +787,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
   }
 
   /**
-   * CRM-19653 : Test that custom field data should/shouldn't be overriden on
+   * CRM-19653 : Test that custom field data should/shouldn't be overridden on
    *   selecting/not selecting option to migrate data respectively
    *
    * @throws \CRM_Core_Exception
@@ -787,7 +796,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
     // Create Custom Field
     $createGroup = $this->setupCustomGroupForIndividual();
     $createField = $this->setupCustomField('Graduation', $createGroup);
-    $customFieldName = "custom_" . $createField['id'];
+    $customFieldName = 'custom_' . $createField['id'];
 
     // Contacts setup
     $this->setupMatchData();
@@ -801,7 +810,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
     // update the text custom field for original contact with value 'abc'
     $this->callAPISuccess('Contact', 'create', [
       'id' => $originalContactID,
-      "{$customFieldName}" => 'abc',
+      $customFieldName => 'abc',
     ]);
     $this->assertCustomFieldValue($originalContactID, 'abc', $customFieldName);
 
@@ -868,7 +877,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
       'id' => $this->contacts[0]['id'],
       'return' => ['created_date'],
     ])['created_date'];
-    // Assume contats have been flipped in the UL so merging into the higher id
+    // Assume contacts have been flipped in the UL so merging into the higher id
     $this->mergeContacts($this->contacts[$keepContactKey]['id'], $this->contacts[$duplicateContactKey]['id'], []);
     $this->assertEquals($lowerContactCreatedDate, $this->callAPISuccess('Contact', 'getsingle', ['id' => $this->contacts[$keepContactKey]['id'], 'return' => ['created_date']])['created_date']);
   }
@@ -928,6 +937,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
    * no records on the custom group table.
    *
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
   public function testMigrationOfSomeCustomDataOnEmptyCustomRecord() {
     // Create Custom Fields
@@ -1057,9 +1067,8 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
    * @throws \API_Exception
    * @throws \CRM_Core_Exception
    * @throws \CiviCRM_API3_Exception
-   * @throws \Civi\API\Exception\UnauthorizedException
    */
-  private function mergeContacts($originalContactID, $duplicateContactID, $params) {
+  private function mergeContacts($originalContactID, $duplicateContactID, $params): void {
     $rowsElementsAndInfo = CRM_Dedupe_Merger::getRowsElementsAndInfo($originalContactID, $duplicateContactID);
 
     $migrationData = [
@@ -1081,7 +1090,7 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  private function assertCustomFieldValue($contactID, $expectedValue, $customFieldName) {
+  private function assertCustomFieldValue($contactID, $expectedValue, $customFieldName): void {
     $this->assertEntityCustomFieldValue('Contact', $contactID, $expectedValue, $customFieldName);
   }
 
@@ -1156,9 +1165,9 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
   /**
    * Set up some contacts for our matching.
    *
-   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function setupMatchData() {
+  public function setupMatchData(): void {
     $fixtures = [
       [
         'first_name' => 'Mickey',
@@ -1420,8 +1429,8 @@ class CRM_Dedupe_MergerTest extends CiviUnitTestCase {
     $cidRefs = [];
     $sql = "
 SELECT
-    table_name,
-    column_name
+    table_name AS table_name,
+    column_name AS column_name
 FROM information_schema.key_column_usage
 WHERE
     referenced_table_schema = database() AND
index cdb0ae133c6782d223b7b93dfe0b3ceb0c767134..be2c61ffca0eabb9ec400ac168dc0b258465287e 100644 (file)
@@ -351,6 +351,7 @@ class CRM_Event_Form_ParticipantTest extends CiviUnitTestCase {
       $form->_bltID = 5;
       $form->_isPaidEvent = TRUE;
       CRM_Event_Form_EventFees::preProcess($form);
+      $form->assignProcessors();
       $form->buildEventFeeForm($form);
     }
     else {
index 99d699ca6cb718ebc454e16c29ee00ac31810c35..c35ce4bebe49da0de2fa9f0da54ce41d9e09408b 100644 (file)
@@ -734,6 +734,7 @@ class CRM_Export_BAO_ExportTest extends CiviUnitTestCase {
       $longString .= 'Blah';
     }
     $this->addOptionToCustomField('select_string', ['label' => $longString, 'name' => 'blah']);
+    $longUrl = 'https://stage.example.org/system/files/webform/way_too_long_url_that_still_fits_in_a_link_custom_field_but_would_fail_to_export_with_html.jpg';
 
     $this->callAPISuccess('Contact', 'create', [
       'id' => $this->contactIDs[1],
@@ -741,12 +742,14 @@ class CRM_Export_BAO_ExportTest extends CiviUnitTestCase {
       $this->getCustomFieldName('country') => 'LA',
       $this->getCustomFieldName('select_string') => 'blah',
       'api.Address.create' => ['location_type_id' => 'Billing', 'city' => 'Waipu'],
+      $this->getCustomFieldName('link') => $longUrl,
     ]);
     $selectedFields = [
       ['name' => 'city', 'location_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Core_BAO_Address', 'location_type_id', 'Billing')],
       ['name' => $this->getCustomFieldName('text')],
       ['name' => $this->getCustomFieldName('country')],
       ['name' => $this->getCustomFieldName('select_string')],
+      ['name' => $this->getCustomFieldName('link')],
     ];
 
     $this->doExportTest([
@@ -758,6 +761,7 @@ class CRM_Export_BAO_ExportTest extends CiviUnitTestCase {
     $this->assertEquals('Waipu', $row['Billing-City']);
     $this->assertEquals("Lao People's Democratic Republic", $row['Country']);
     $this->assertEquals($longString, $row['Pick Color']);
+    $this->assertEquals($longUrl, $row['test_link']);
   }
 
   /**
index acce7ee0fac9f27c9f4f040b97006fa5849e2c17..562450aaa4d96dfcbe5539ea3428422f2bc6e638 100644 (file)
@@ -52,6 +52,8 @@ class CRM_Logging_LoggingTest extends CiviUnitTestCase {
     $this->assertTrue(
       in_array("  `logging_test` int(11) DEFAULT '0'", $create)
       || in_array("  `logging_test` int(11) DEFAULT 0", $create)
+      || in_array("  `logging_test` int DEFAULT '0'", $create)
+      || in_array("  `logging_test` int DEFAULT 0", $create)
     );
     CRM_Core_DAO::executeQuery("ALTER TABLE `civicrm_option_value` DROP COLUMN `logging_test`", [], FALSE, NULL, FALSE, FALSE);
     $query = CRM_Core_DAO::executeQuery("SHOW CREATE TABLE `log_civicrm_option_value`", [], TRUE, NULL, FALSE, FALSE);
@@ -65,7 +67,10 @@ class CRM_Logging_LoggingTest extends CiviUnitTestCase {
     Civi::service('sql_triggers')->rebuild('civicrm_option_value');
     $this->assertTrue(
       in_array("  `logging_test` int(11) DEFAULT '0'", $create)
-      || in_array("  `logging_test` int(11) DEFAULT 0", $create));
+      || in_array("  `logging_test` int(11) DEFAULT 0", $create)
+      || in_array("  `logging_test` int DEFAULT '0'", $create)
+      || in_array("  `logging_test` int DEFAULT 0", $create)
+    );
     $logging->disableLogging();
   }
 
index 5356c14e6d0160107cc3c0c3995199a05f6d68ef..5b4c3ebe4cdf76ccb45265ee52d2e6d93b1b64af 100644 (file)
@@ -415,8 +415,8 @@ class CRM_Logging_SchemaTest extends CiviUnitTestCase {
     $dao = CRM_Core_DAO::executeQuery("SHOW CREATE TABLE civicrm_test_table");
     $dao->fetch();
     // using regex since not sure it's always int(10), so accept int(10), int(11), integer, etc...
-    $this->assertRegExp('/`id` int(.+) unsigned NOT NULL AUTO_INCREMENT/', $dao->Create_Table);
-    $this->assertRegExp('/`activity_id` int(.+) unsigned NOT NULL/', $dao->Create_Table);
+    $this->assertRegExp('/`id` int(.*) unsigned NOT NULL AUTO_INCREMENT/', $dao->Create_Table);
+    $this->assertRegExp('/`activity_id` int(.*) unsigned NOT NULL/', $dao->Create_Table);
     $this->assertStringContainsString('`texty` varchar(255)', $dao->Create_Table);
     $this->assertStringContainsString('ENGINE=InnoDB', $dao->Create_Table);
     $this->assertStringContainsString('FOREIGN KEY (`activity_id`) REFERENCES `civicrm_activity` (`id`) ON DELETE CASCADE', $dao->Create_Table);
@@ -426,8 +426,8 @@ class CRM_Logging_SchemaTest extends CiviUnitTestCase {
     $dao->fetch();
     $this->assertStringNotContainsString('AUTO_INCREMENT', $dao->Create_Table);
     // This seems debatable whether `id` should lose its NOT NULL status
-    $this->assertRegExp('/`id` int(.+) unsigned DEFAULT NULL/', $dao->Create_Table);
-    $this->assertRegExp('/`activity_id` int(.+) unsigned DEFAULT NULL/', $dao->Create_Table);
+    $this->assertRegExp('/`id` int(.*) unsigned DEFAULT NULL/', $dao->Create_Table);
+    $this->assertRegExp('/`activity_id` int(.*) unsigned DEFAULT NULL/', $dao->Create_Table);
     $this->assertStringContainsString('`texty` varchar(255)', $dao->Create_Table);
     $this->assertStringContainsString('ENGINE=InnoDB', $dao->Create_Table);
     $this->assertStringNotContainsString('FOREIGN KEY', $dao->Create_Table);
index 86bc054486dc98232c8140da02c294f284653f9c..29cfe5057baa97890bc149c2394f526cf01a808e 100644 (file)
@@ -674,6 +674,13 @@ class CRM_Member_Form_MembershipTest extends CiviUnitTestCase {
     $this->assertEquals(50, $payment['paid']);
     // balance remaining
     $this->assertEquals(-25, $payment['balance']);
+
+    //Update to lifetime membership.
+    $params['membership_type_id'] = [$this->ids['contact']['organization'], $this->ids['membership_type']['lifetime']];
+    $form->testSubmit($params);
+    $membership = $this->callAPISuccessGetSingle('Membership', ['contact_id' => $this->_individualId]);
+    $this->assertEquals($this->ids['membership_type']['lifetime'], $membership['membership_type_id']);
+    $this->assertTrue(empty($membership['end_date']), 'Lifetime Membership on the individual has an End date.');
   }
 
   /**
@@ -1221,9 +1228,7 @@ Expires: ',
     if (isset($_REQUEST['cid'])) {
       unset($_REQUEST['cid']);
     }
-    $form = new CRM_Member_Form_Membership();
-    $_SERVER['REQUEST_METHOD'] = 'GET';
-    $form->controller = new CRM_Core_Controller();
+    $form = $this->getFormObject('CRM_Member_Form_Membership');
     $form->preProcess();
     return $form;
   }
index 52b5253ce4cbfa7baac9b445946ce85c44944615..afa6a753cc228718653e8cb263fc9994d90e42ed 100644 (file)
@@ -79,6 +79,28 @@ class CRM_Utils_RuleTest extends CiviUnitTestCase {
     ];
   }
 
+  /**
+   * @dataProvider booleanDataProvider
+   * @param $inputData
+   * @param $expectedResult
+   */
+  public function testBoolean($inputData, $expectedResult) {
+    $this->assertEquals($expectedResult, CRM_Utils_Rule::boolean($inputData));
+  }
+
+  /**
+   * @return array
+   */
+  public function booleanDataProvider() {
+    return [
+      [TRUE, TRUE],
+      ['TRUE', TRUE],
+      [FALSE, TRUE],
+      ['false', TRUE],
+      ['banana', FALSE],
+    ];
+  }
+
   /**
    * @dataProvider moneyDataProvider
    * @param $inputData
index 21a47fa35b330e7a713afd9fb5ff0bf85871533e..48fd76ee4df714ca200543dd885a5b28807bcd4e 100644 (file)
@@ -131,6 +131,11 @@ class CRM_Utils_TypeTest extends CiviUnitTestCase {
       ['field(contribution_status_id,4,5,6) asc, contact_id asc', 'MysqlOrderBy', 'field(`contribution_status_id`,4,5,6) asc, `contact_id` asc'],
       ['table.civicrm_column_name desc,other_column,another_column desc', 'MysqlOrderBy', '`table`.`civicrm_column_name` desc, `other_column`, `another_column` desc'],
       ['table.`Home-street_address` asc, `table-alias`.`Home-street_address` desc,`table-alias`.column', 'MysqlOrderBy', '`table`.`Home-street_address` asc, `table-alias`.`Home-street_address` desc, `table-alias`.`column`'],
+      [TRUE, 'Boolean', TRUE],
+      [FALSE, 'Boolean', FALSE],
+      ['TRUE', 'Boolean', 'TRUE'],
+      ['false', 'Boolean', 'false'],
+      ['banana', 'Boolean', NULL],
     ];
   }
 
index 0934a626d2f8f5de63cd342c95473ecbbc043d00..c69c3e4fb26725a87a9be50d00eec9df3cadb1f2 100644 (file)
@@ -2,6 +2,7 @@
 namespace Civi\API\Subscriber;
 
 use Civi\API\Kernel;
+use Civi\API\Provider\StaticProvider;
 use Symfony\Component\EventDispatcher\EventDispatcher;
 
 /**
@@ -27,12 +28,12 @@ class DynamicFKAuthorizationTest extends \CiviUnitTestCase {
    */
   public $kernel;
 
-  protected function setUp() {
+  protected function setUp(): void {
     parent::setUp();
     \CRM_Core_DAO_AllCoreTables::init(TRUE);
 
     \CRM_Core_DAO_AllCoreTables::registerEntityType('FakeFile', 'CRM_Fake_DAO_FakeFile', 'fake_file');
-    $fileProvider = new \Civi\API\Provider\StaticProvider(
+    $fileProvider = new StaticProvider(
       3,
       'FakeFile',
       ['id', 'entity_table', 'entity_id'],
@@ -44,7 +45,7 @@ class DynamicFKAuthorizationTest extends \CiviUnitTestCase {
     );
 
     \CRM_Core_DAO_AllCoreTables::registerEntityType('Widget', 'CRM_Fake_DAO_Widget', 'fake_widget');
-    $widgetProvider = new \Civi\API\Provider\StaticProvider(3, 'Widget',
+    $widgetProvider = new StaticProvider(3, 'Widget',
       ['id', 'title'],
       [],
       [
@@ -53,7 +54,7 @@ class DynamicFKAuthorizationTest extends \CiviUnitTestCase {
     );
 
     \CRM_Core_DAO_AllCoreTables::registerEntityType('Forbidden', 'CRM_Fake_DAO_Forbidden', 'fake_forbidden');
-    $forbiddenProvider = new \Civi\API\Provider\StaticProvider(
+    $forbiddenProvider = new StaticProvider(
       3,
       'Forbidden',
       ['id', 'label'],
@@ -90,18 +91,18 @@ class DynamicFKAuthorizationTest extends \CiviUnitTestCase {
         else null
       end as entity_table,
       case %1
-        when " . self::FILE_WIDGET_ID . " then " . self::WIDGET_ID . "
-        when " . self::FILE_FORBIDDEN_ID . " then " . self::FORBIDDEN_ID . "
+        when " . self::FILE_WIDGET_ID . ' then ' . self::WIDGET_ID . '
+        when ' . self::FILE_FORBIDDEN_ID . ' then ' . self::FORBIDDEN_ID . '
         else null
       end as entity_id
-      ",
+      ',
       // Get a list of custom fields (field_name,table_name,extends)
-      "select",
+      'select',
       ['fake_widget', 'fake_forbidden']
     ));
   }
 
-  protected function tearDown() {
+  protected function tearDown(): void {
     parent::tearDown();
     \CRM_Core_DAO_AllCoreTables::init(TRUE);
   }
@@ -196,10 +197,10 @@ class DynamicFKAuthorizationTest extends \CiviUnitTestCase {
   }
 
   /**
-   * @param $entity
-   * @param $action
+   * @param string $entity
+   * @param int $action
    * @param array $params
-   * @param $expectedError
+   * @param array $expectedError
    * @dataProvider badDataProvider
    */
   public function testBad($entity, $action, $params, $expectedError) {
index 4c1fff3cd2570d698567df26adf1e7bb6dbe4e77..4c458f17bb4a7d38ed41245429eb2d163e53e6c1 100644 (file)
@@ -1,7 +1,6 @@
 <?php
 // ADAPTED FROM tools/scripts/phpunit
 
-ini_set('safe_mode', 0);
 ini_set('include_path', dirname(__DIR__) . PATH_SEPARATOR . ini_get('include_path'));
 
 #  Relying on system timezone setting produces a warning,
index 3c6f4ab655f724e3e577e58e4740c151d63310c5..172d62f358375b650f5c2cb01f16f7e6afbf99f2 100644 (file)
@@ -33,13 +33,6 @@ class HelloTest extends PHPUnit\Framework\TestCase {
    */
   public $abc;
 
-  /**
-   * @param string|null $name
-   */
-  public function __construct($name = NULL) {
-    parent::__construct($name);
-  }
-
   /**
    * Called before the test functions will be executed.
    * this function is defined in PHPUnit_TestCase and overwritten
@@ -48,7 +41,7 @@ class HelloTest extends PHPUnit\Framework\TestCase {
   public function setUp() {
     // create a new instance of String with the
     // string 'abc'
-    $this->abc = "hello";
+    $this->abc = 'hello';
   }
 
   /**
@@ -56,7 +49,7 @@ class HelloTest extends PHPUnit\Framework\TestCase {
    * this function is defined in PHPUnit_TestCase and overwritten
    * here.
    */
-  public function tearDown() {
+  public function tearDown(): void {
     // delete your instance
     unset($this->abc);
   }
@@ -64,10 +57,9 @@ class HelloTest extends PHPUnit\Framework\TestCase {
   /**
    * test the toString function.
    */
-  public function testHello() {
+  public function testHello(): void {
     $result = $this->abc;
-    $expected = 'hello';
-    $this->assertEquals($result, $expected);
+    $this->assertEquals('hello', $result);
   }
 
 }
index 846f10785e93f2e361567e221c5bca1561baf972..43942a9342527cb82fa9a5a63beea6edddfae4e1 100644 (file)
@@ -42,8 +42,6 @@ class api_v3_ContactTest extends CiviUnitTestCase {
 
   public $DBResetRequired = FALSE;
 
-  protected $_apiversion;
-
   protected $_entity;
 
   protected $_params;
@@ -65,7 +63,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    * Connect to the database, truncate the tables that will be used
    * and redirect stdin to a temporary file
    */
-  public function setUp() {
+  public function setUp(): void {
     // Connect to the database.
     parent::setUp();
     $this->_entity = 'contact';
@@ -81,7 +79,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @throws \Exception
    */
-  public function tearDown() {
+  public function tearDown(): void {
     $this->_apiversion = 3;
     $this->callAPISuccess('Setting', 'create', ['includeOrderByClause' => TRUE]);
     // truncate a few tables
@@ -99,8 +97,8 @@ class api_v3_ContactTest extends CiviUnitTestCase {
       'civicrm_activity',
       'civicrm_group',
       'civicrm_group_contact',
-      'civicrm_saved_search',
       'civicrm_group_contact_cache',
+      'civicrm_saved_search',
       'civicrm_prevnext_cache',
     ];
 
@@ -116,11 +114,11 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
+   * @throws \CRM_Core_Exception
    * @dataProvider versionThreeAndFour
    *
-   * @throws \CRM_Core_Exception
    */
-  public function testAddCreateIndividual($version) {
+  public function testAddCreateIndividual(int $version): void {
     $this->_apiversion = $version;
     $oldCount = CRM_Core_DAO::singleValueQuery('select count(*) from civicrm_contact');
     $params = [
@@ -130,7 +128,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
     ];
 
     $contact = $this->callAPISuccess('contact', 'create', $params);
-    $this->assertTrue(is_numeric($contact['id']));
+    $this->assertIsNumeric($contact['id']);
     $this->assertTrue($contact['id'] > 0);
     $newCount = CRM_Core_DAO::singleValueQuery('select count(*) from civicrm_contact');
     $this->assertEquals($oldCount + 1, $newCount);
@@ -148,7 +146,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testCreateIndividualNoCacheClear() {
+  public function testCreateIndividualNoCacheClear(): void {
 
     $contact = $this->callAPISuccess('contact', 'create', $this->_params);
     $groupID = $this->groupCreate();
@@ -156,13 +154,13 @@ class api_v3_ContactTest extends CiviUnitTestCase {
     $this->putGroupContactCacheInClearableState($groupID, $contact);
 
     $this->callAPISuccess('contact', 'create', ['id' => $contact['id']]);
-    $this->assertEquals(0, CRM_Core_DAO::singleValueQuery("SELECT count(*) FROM civicrm_group_contact_cache"));
+    $this->assertEquals(0, CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_group_contact_cache'));
 
     // Rinse & repeat, but with the option.
     $this->putGroupContactCacheInClearableState($groupID, $contact);
     CRM_Core_Config::setPermitCacheFlushMode(FALSE);
     $this->callAPISuccess('contact', 'create', ['id' => $contact['id']]);
-    $this->assertEquals(1, CRM_Core_DAO::singleValueQuery("SELECT count(*) FROM civicrm_group_contact_cache"));
+    $this->assertEquals(1, CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_group_contact_cache'));
     CRM_Core_Config::setPermitCacheFlushMode(TRUE);
   }
 
@@ -179,7 +177,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testInternationalStrings($string) {
+  public function testInternationalStrings(string $string): void {
     $this->callAPISuccess('Contact', 'create', array_merge(
       $this->_params,
       ['first_name' => $string]
@@ -201,7 +199,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
   /**
    * Get international string data for testing against api calls.
    */
-  public function getInternationalStrings() {
+  public function getInternationalStrings(): array {
     $invocations = [];
     $invocations[] = ['Scarabée'];
     $invocations[] = ['Iñtërnâtiônàlizætiøn'];
@@ -217,10 +215,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
-   * @dataProvider versionThreeAndFour
    * @throws \CRM_Core_Exception
+   * @dataProvider versionThreeAndFour
    */
-  public function testAddCreateIndividualWithPreferredLanguage($version) {
+  public function testAddCreateIndividualWithPreferredLanguage(int $version): void {
     $this->_apiversion = $version;
     $params = [
       'first_name' => 'abc1',
@@ -240,10 +238,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
-   * @dataProvider versionThreeAndFour
    * @throws \CRM_Core_Exception
+   * @dataProvider versionThreeAndFour
    */
-  public function testIndividualSubType($version) {
+  public function testIndividualSubType(int $version): void {
     $this->_apiversion = $version;
     $params = [
       'first_name' => 'test abc',
@@ -270,20 +268,19 @@ class api_v3_ContactTest extends CiviUnitTestCase {
     ]);
 
     $contact = $this->callAPISuccess('contact', 'get', ['id' => $cid]);
-    $this->assertTrue(empty($contact['values'][$cid]['contact_sub_type']));
+    $this->assertEmpty($contact['values'][$cid]['contact_sub_type']);
   }
 
   /**
-   * Verify that we can retreive contacts of different sub types
+   * Verify that we can retrieve contacts of different sub types
    *
    * @param int $version
    *
    * @throws \CRM_Core_Exception
    * @throws \CiviCRM_API3_Exception
-   *
    * @dataProvider versionThreeAndFour
    */
-  public function testGetMultipleContactSubTypes($version) {
+  public function testGetMultipleContactSubTypes(int $version): void {
     $this->_apiversion = $version;
 
     // This test presumes that there are no parents or students in the dataset
@@ -322,14 +319,14 @@ class api_v3_ContactTest extends CiviUnitTestCase {
   /**
    * Verify that attempt to create contact with empty params fails.
    */
-  public function testCreateEmptyContact() {
+  public function testCreateEmptyContact(): void {
     $this->callAPIFailure('contact', 'create', []);
   }
 
   /**
    * Verify that attempt to create contact with bad contact type fails.
    */
-  public function testCreateBadTypeContact() {
+  public function testCreateBadTypeContact(): void {
     $params = [
       'email' => 'man1@yahoo.com',
       'contact_type' => 'Does not Exist',
@@ -340,7 +337,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
   /**
    * Verify that attempt to create individual contact without required fields fails.
    */
-  public function testCreateBadRequiredFieldsIndividual() {
+  public function testCreateBadRequiredFieldsIndividual(): void {
     $params = [
       'middle_name' => 'This field is not required',
       'contact_type' => 'Individual',
@@ -351,7 +348,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
   /**
    * Verify that attempt to create household contact without required fields fails.
    */
-  public function testCreateBadRequiredFieldsHousehold() {
+  public function testCreateBadRequiredFieldsHousehold(): void {
     $params = [
       'middle_name' => 'This field is not required',
       'contact_type' => 'Household',
@@ -364,7 +361,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * Verify that attempt to create organization contact without required fields fails.
    */
-  public function testCreateBadRequiredFieldsOrganization() {
+  public function testCreateBadRequiredFieldsOrganization(): void {
     $params = [
       'middle_name' => 'This field is not required',
       'contact_type' => 'Organization',
@@ -378,7 +375,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testCreateEmailIndividual() {
+  public function testCreateEmailIndividual(): void {
     $primaryEmail = 'man3@yahoo.com';
     $notPrimaryEmail = 'man4@yahoo.com';
     $params = [
@@ -397,11 +394,11 @@ class api_v3_ContactTest extends CiviUnitTestCase {
     $this->callAPISuccess('email', 'create', ['contact_id' => $contact1['id'], 'is_primary' => 0, 'email' => $notPrimaryEmail]);
 
     // Case 1: Check with criteria primary 'email' => array('IS NOT NULL' => 1)
-    $result = $this->callAPISuccess('contact', 'get', ['email' => ['IS NOT NULL' => 1]]);
+    $this->callAPISuccess('contact', 'get', ['email' => ['IS NOT NULL' => 1]]);
     $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
 
     // Case 2: Check with criteria primary 'email' => array('<>' => '')
-    $result = $this->callAPISuccess('contact', 'get', ['email' => ['<>' => '']]);
+    $this->callAPISuccess('contact', 'get', ['email' => ['<>' => '']]);
     $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
 
     // Case 3: Check with email_id='primary email id'
@@ -421,10 +418,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
-   * @dataProvider versionThreeAndFour
    * @throws \CRM_Core_Exception
+   * @dataProvider versionThreeAndFour
    */
-  public function testCreateNameIndividual($version) {
+  public function testCreateNameIndividual(int $version): void {
     $this->_apiversion = $version;
     $params = [
       'first_name' => 'abc1',
@@ -442,10 +439,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
-   * @dataProvider versionThreeAndFour
    * @throws \CRM_Core_Exception
+   * @dataProvider versionThreeAndFour
    */
-  public function testCreateDisplayNameIndividual($version) {
+  public function testCreateDisplayNameIndividual(int $version): void {
     $this->_apiversion = $version;
     $params = [
       'display_name' => 'abc1',
@@ -462,10 +459,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
-   * @dataProvider versionThreeAndFour
    * @throws \CRM_Core_Exception
+   * @dataProvider versionThreeAndFour
    */
-  public function testGetNameVariantsCaseInsensitive($version) {
+  public function testGetNameVariantsCaseInsensitive(int $version): void {
     $this->_apiversion = $version;
     $this->callAPISuccess('contact', 'create', [
       'display_name' => 'Abc1',
@@ -487,7 +484,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testCreateNameIndividualOldKeys() {
+  public function testCreateNameIndividualOldKeys(): void {
     $params = [
       'individual_prefix' => 'Dr.',
       'first_name' => 'abc1',
@@ -511,8 +508,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * Verify that attempt to create individual contact with
    * first and last names and old key values works
+   *
+   * @throws \CRM_Core_Exception
    */
-  public function testCreateNameIndividualRecommendedKeys2() {
+  public function testCreateNameIndividualRecommendedKeys2(): void {
     $params = [
       'prefix_id' => 'Dr.',
       'first_name' => 'abc1',
@@ -540,10 +539,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
-   * @dataProvider versionThreeAndFour
    * @throws \CRM_Core_Exception
+   * @dataProvider versionThreeAndFour
    */
-  public function testCreateNameHousehold($version) {
+  public function testCreateNameHousehold(int $version): void {
     $this->_apiversion = $version;
     $params = [
       'household_name' => 'The abc Household',
@@ -560,9 +559,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
+   * @throws \CRM_Core_Exception
    * @dataProvider versionThreeAndFour
    */
-  public function testCreateNameOrganization($version) {
+  public function testCreateNameOrganization(int $version): void {
     $this->_apiversion = $version;
     $params = [
       'organization_name' => 'The abc Organization',
@@ -574,7 +574,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
   /**
    * Verify that attempt to create organization contact without organization name fails.
    */
-  public function testCreateNoNameOrganization() {
+  public function testCreateNoNameOrganization(): void {
     $params = [
       'first_name' => 'The abc Organization',
       'contact_type' => 'Organization',
@@ -587,9 +587,11 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    * @dataProvider versionThreeAndFour
    */
-  public function testCreateApiKey($version) {
+  public function testCreateApiKey(int $version): void {
     $this->_apiversion = $version;
     $config = CRM_Core_Config::singleton();
     $contactId = $this->individualCreate([
@@ -681,15 +683,15 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
-   * @dataProvider versionThreeAndFour
    * @throws \CRM_Core_Exception
+   * @dataProvider versionThreeAndFour
    */
-  public function testCreateWithCustom($version) {
+  public function testCreateWithCustom(int $version): void {
     $this->_apiversion = $version;
     $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
 
     $params = $this->_params;
-    $params['custom_' . $ids['custom_field_id']] = "custom string";
+    $params['custom_' . $ids['custom_field_id']] = 'custom string';
     $description = 'This demonstrates setting a custom field through the API.';
     $result = $this->callAPIAndDocument($this->_entity, 'create', $params, __FUNCTION__, __FILE__, $description);
 
@@ -697,7 +699,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
       'return.custom_' . $ids['custom_field_id'] => 1,
       'id' => $result['id'],
     ]);
-    $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
+    $this->assertEquals('custom string', $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
 
     $this->customFieldDelete($ids['custom_field_id']);
     $this->customGroupDelete($ids['custom_group_id']);
@@ -708,7 +710,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testCreateWithNULLCustomCRM12773() {
+  public function testCreateWithNULLCustomCRM12773(): void {
     $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
     $params = $this->_params;
     $params['custom_' . $ids['custom_field_id']] = NULL;
@@ -722,11 +724,11 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
+   * @throws \CRM_Core_Exception
    * @dataProvider versionThreeAndFour
    *
-   * @throws \CRM_Core_Exception
    */
-  public function testCreatePreferredLanguageUnset($version) {
+  public function testCreatePreferredLanguageUnset(int $version): void {
     $this->_apiversion = $version;
     $this->callAPISuccess('Contact', 'create', [
       'first_name' => 'Snoop',
@@ -742,11 +744,11 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
+   * @throws \CRM_Core_Exception
    * @dataProvider versionThreeAndFour
    *
-   * @throws \CRM_Core_Exception
    */
-  public function testCreatePreferredLanguageSet($version) {
+  public function testCreatePreferredLanguageSet(int $version): void {
     $this->_apiversion = $version;
     $this->callAPISuccess('Setting', 'create', ['contact_default_language' => 'fr_FR']);
     $this->callAPISuccess('Contact', 'create', [
@@ -764,7 +766,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testCreatePreferredLanguageNull() {
+  public function testCreatePreferredLanguageNull(): void {
     $this->callAPISuccess('Setting', 'create', ['contact_default_language' => 'null']);
     $this->callAPISuccess('Contact', 'create', [
       'first_name' => 'Snoop',
@@ -780,10 +782,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
-   * @dataProvider versionThreeAndFour
    * @throws \CRM_Core_Exception
+   * @dataProvider versionThreeAndFour
    */
-  public function testCreatePreferredLanguagePassed($version) {
+  public function testCreatePreferredLanguagePassed(int $version): void {
     $this->_apiversion = $version;
     $this->callAPISuccess('Setting', 'create', ['contact_default_language' => 'null']);
     $this->callAPISuccess('Contact', 'create', [
@@ -801,7 +803,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testCreateContactCustomFldDateTime() {
+  public function testCreateContactCustomFldDateTime(): void {
     $customGroup = $this->customGroupCreate(['extends' => 'Individual', 'title' => 'datetime_test_group']);
     $dateTime = CRM_Utils_Date::currentDBDate();
     //check date custom field is saved along with time when time_format is set
@@ -837,7 +839,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
 
     $result = $this->callAPISuccess('Contact', 'create', $params);
     $this->assertNotNull($result['id']);
-    $customFldDate = date("YmdHis", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
+    $customFldDate = date('YmdHis', strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
     $this->assertNotNull($customFldDate);
     $this->assertEquals($dateTime, $customFldDate);
     $customValueId = $result['values'][$result['id']]['api.CustomValue.get']['values'][0]['id'];
@@ -860,8 +862,8 @@ class api_v3_ContactTest extends CiviUnitTestCase {
     ];
     $result = $this->callAPISuccess('Contact', 'create', $params);
     $this->assertNotNull($result['id']);
-    $customFldDate = date("Ymd", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
-    $customFldTime = date("His", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
+    $customFldDate = date('Ymd', strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
+    $customFldTime = date('His', strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
     $this->assertNotNull($customFldDate);
     $this->assertEquals($dateTime, $customFldDate);
     $this->assertEquals(000000, $customFldTime);
@@ -870,8 +872,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
 
   /**
    * Test creating a current employer through API.
+   *
+   * @throws \CRM_Core_Exception
    */
-  public function testContactCreateCurrentEmployer() {
+  public function testContactCreateCurrentEmployer(): void {
     // Here we will just do the get for set-up purposes.
     $count = $this->callAPISuccess('contact', 'getcount', [
       'organization_name' => 'new employer org',
@@ -904,8 +908,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    * Test creating a current employer through API.
    *
    * Check it will re-activate a de-activated employer
+   *
+   * @throws \CRM_Core_Exception
    */
-  public function testContactCreateDuplicateCurrentEmployerEnables() {
+  public function testContactCreateDuplicateCurrentEmployerEnables(): void {
     // Set up  - create employer relationship.
     $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, ['current_employer' => 'new employer org']));
     $relationship = $this->callAPISuccess('relationship', 'get', [
@@ -936,11 +942,11 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
+   * @throws \CRM_Core_Exception
    * @dataProvider versionThreeAndFour
    *
-   * @throws \CRM_Core_Exception
    */
-  public function testGetDeceasedRetrieved($version) {
+  public function testGetDeceasedRetrieved(int $version): void {
     $this->_apiversion = $version;
     $this->callAPISuccess($this->_entity, 'create', $this->_params);
     $c2 = $this->callAPISuccess($this->_entity, 'create', [
@@ -950,7 +956,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
       'is_deceased' => 1,
     ]);
     $result = $this->callAPISuccess($this->_entity, 'get', ['is_deceased' => 0]);
-    $this->assertFalse(array_key_exists($c2['id'], $result['values']));
+    $this->assertArrayNotHasKey($c2['id'], $result['values']);
   }
 
   /**
@@ -958,7 +964,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testGetSort() {
+  public function testGetSort(): void {
     $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
     $c2 = $this->callAPISuccess($this->_entity, 'create', [
       'first_name' => 'bb',
@@ -990,8 +996,9 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    * Test the like operator works for Contact.get
    *
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testGetEmailLike() {
+  public function testGetEmailLike(): void {
     $this->individualCreate();
     $this->callAPISuccessGetCount('Contact', ['email' => ['LIKE' => 'an%']], 1);
     $this->callAPISuccessGetCount('Contact', ['email' => ['LIKE' => 'ab%']], 0);
@@ -1004,11 +1011,11 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
+   * @throws \CRM_Core_Exception
    * @dataProvider versionThreeAndFour
    *
-   * @throws \CRM_Core_Exception
    */
-  public function testGetINIDArray($version) {
+  public function testGetINIDArray(int $version): void {
     $this->_apiversion = $version;
     $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
     $c2 = $this->callAPISuccess($this->_entity, 'create', [
@@ -1034,7 +1041,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @throws \CRM_Core_Exception
    */
-  public function testGetDeleted() {
+  public function testGetDeleted(): void {
     $params = $this->_params;
     $contact1 = $this->callAPISuccess('contact', 'create', $params);
     $params['is_deleted'] = 1;
@@ -1070,9 +1077,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
+   * @throws \CRM_Core_Exception
    * @dataProvider versionThreeAndFour
    */
-  public function testGetSortNewSyntax($version) {
+  public function testGetSortNewSyntax(int $version): void {
     $this->_apiversion = $version;
     $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
     $c2 = $this->callAPISuccess($this->_entity, 'create', [
@@ -1110,10 +1118,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    * https://issues.civicrm.org/jira/browse/CRM-15983
    * @param int $version
    *
-   * @dataProvider versionThreeAndFour
    * @throws \CRM_Core_Exception
+   * @dataProvider versionThreeAndFour
    */
-  public function testSortLimitChainedRelationshipGetCRM15983($version) {
+  public function testSortLimitChainedRelationshipGetCRM15983(int $version): void {
     $this->_apiversion = $version;
     // Some contact
     $create_result_1 = $this->callAPISuccess('contact', 'create', [
@@ -1179,9 +1187,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
+   * @throws \CRM_Core_Exception
    * @dataProvider versionThreeAndFour
    */
-  public function testGetApostropheCRM10857($version) {
+  public function testGetApostropheCRM10857(int $version): void {
     $this->_apiversion = $version;
     $params = array_merge($this->_params, ['last_name' => "O'Connor"]);
     $this->callAPISuccess($this->_entity, 'create', $params);
@@ -1199,9 +1208,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * @param int $version
    *
+   * @throws \CRM_Core_Exception
    * @dataProvider versionThreeAndFour
    */
-  public function testGetBetweenZeroWorks($version) {
+  public function testGetBetweenZeroWorks(int $version): void {
     $this->_apiversion = $version;
     $this->callAPISuccess($this->_entity, 'get', [
       'contact_id' => ['BETWEEN' => [0, 9]],
@@ -1219,8 +1229,11 @@ class api_v3_ContactTest extends CiviUnitTestCase {
   /**
    * Test retrieval by addressee id.
    * V3 only - the "skip_greeting_processing" param is not currently in v4
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testGetByAddresseeID() {
+  public function testGetByAddresseeID(): void {
     $individual1ID = $this->individualCreate([
       'skip_greeting_processing' => 1,
       'addressee_id' => 'null',
@@ -1248,26 +1261,28 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    * Check with complete array + custom field.
    *
    * Note that the test is written on purpose without any
-   * variables specific to participant so it can be replicated into other entities
-   * and / or moved to the automated test suite
+   * variables specific to participant so it can be replicated into other
+   * entities and / or moved to the automated test suite
+   *
+   * @throws \CRM_Core_Exception
    */
-  public function testGetWithCustom() {
+  public function testGetWithCustom(): void {
     $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
 
     $params = $this->_params;
-    $params['custom_' . $ids['custom_field_id']] = "custom string";
-    $description = "This demonstrates setting a custom field through the API.";
-    $subfile = "CustomFieldGet";
+    $params['custom_' . $ids['custom_field_id']] = 'custom string';
+    $description = 'This demonstrates setting a custom field through the API.';
+    $subFile = 'CustomFieldGet';
     $result = $this->callAPISuccess($this->_entity, 'create', $params);
 
     $check = $this->callAPIAndDocument($this->_entity, 'get', [
       'return.custom_' . $ids['custom_field_id'] => 1,
       'id' => $result['id'],
-    ], __FUNCTION__, __FILE__, $description, $subfile);
+    ], __FUNCTION__, __FILE__, $description, $subFile);
 
-    $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
+    $this->assertEquals('custom string', $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
     $fields = ($this->callAPISuccess('contact', 'getfields', $params));
-    $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
+    $this->assertIsArray($fields['values']['custom_' . $ids['custom_field_id']]);
     $this->customFieldDelete($ids['custom_field_id']);
     $this->customGroupDelete($ids['custom_group_id']);
   }
@@ -1277,9 +1292,11 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    *
    * https://lab.civicrm.org/dev/core/issues/1025
    *
+   * @throws \API_Exception
    * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testGetWithCustomOfActivityType() {
+  public function testGetWithCustomOfActivityType(): void {
     $this->createCustomGroupWithFieldOfType(['extends' => 'Activity']);
     $this->createCustomGroupWithFieldOfType(['extends' => 'Contact'], 'text', 'contact_');
     $contactID = $this->individualCreate();
@@ -1290,29 +1307,34 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    * Check with complete array + custom field.
    *
    * Note that the test is written on purpose without any
-   * variables specific to participant so it can be replicated into other entities
-   * and / or moved to the automated test suite
+   * variables specific to participant so it can be replicated into other
+   * entities and / or moved to the automated test suite
+   *
+   * @throws \CRM_Core_Exception
    */
-  public function testGetWithCustomReturnSyntax() {
+  public function testGetWithCustomReturnSyntax(): void {
     $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
 
     $params = $this->_params;
-    $params['custom_' . $ids['custom_field_id']] = "custom string";
-    $description = "This demonstrates setting a custom field through the API.";
-    $subfile = "CustomFieldGetReturnSyntaxVariation";
+    $params['custom_' . $ids['custom_field_id']] = 'custom string';
+    $description = 'This demonstrates setting a custom field through the API.';
+    $subFile = 'CustomFieldGetReturnSyntaxVariation';
     $result = $this->callAPISuccess($this->_entity, 'create', $params);
     $params = ['return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']];
-    $check = $this->callAPIAndDocument($this->_entity, 'get', $params, __FUNCTION__, __FILE__, $description, $subfile);
+    $check = $this->callAPIAndDocument($this->_entity, 'get', $params, __FUNCTION__, __FILE__, $description, $subFile);
 
-    $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
+    $this->assertEquals('custom string', $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
     $this->customFieldDelete($ids['custom_field_id']);
     $this->customGroupDelete($ids['custom_group_id']);
   }
 
   /**
    * Check that address name, ID is returned if required.
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
-  public function testGetReturnAddress() {
+  public function testGetReturnAddress(): void {
     $contactID = $this->individualCreate();
     $result = $this->callAPISuccess('address', 'create', [
       'contact_id' => $contactID,
@@ -1333,9 +1355,11 @@ class api_v3_ContactTest extends CiviUnitTestCase {
   }
 
   /**
-   * Test group filter syntaxes.
+   * Test group filter syntax.
+   *
+   * @throws \CRM_Core_Exception
    */
-  public function testGetGroupIDFromContact() {
+  public function testGetGroupIDFromContact(): void {
     $groupId = $this->groupCreate();
     $params = [
       'email' => 'man2@yahoo.com',
@@ -1366,7 +1390,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
     $result = $this->callAPISuccess('contact', 'get', $params);
     $this->assertEquals(1, $result['count']);
     $params = [
-      'filter.group_id' => "26,27",
+      'filter.group_id' => '26,27',
       'contact_type' => 'Individual',
     ];
     $this->callAPISuccess('contact', 'get', $params);
@@ -1394,11 +1418,14 @@ class api_v3_ContactTest extends CiviUnitTestCase {
   }
 
   /**
-   * Verify that attempt to create individual contact with two chained websites succeeds.
+   * Verify that attempt to create individual contact with two chained websites
+   * succeeds.
+   *
+   * @throws \CRM_Core_Exception
    */
-  public function testCreateIndividualWithContributionDottedSyntax() {
-    $description = "This demonstrates the syntax to create 2 chained entities.";
-    $subFile = "ChainTwoWebsites";
+  public function testCreateIndividualWithContributionDottedSyntax(): void {
+    $description = 'This demonstrates the syntax to create 2 chained entities.';
+    $subFile = 'ChainTwoWebsites';
     $params = [
       'first_name' => 'abc3',
       'last_name' => 'xyz3',
@@ -1419,10 +1446,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
         'skipCleanMoney' => 1,
       ],
       'api.website.create' => [
-        'url' => "http://civicrm.org",
+        'url' => 'http://civicrm.org',
       ],
       'api.website.create.2' => [
-        'url' => "http://chained.org",
+        'url' => 'http://chained.org',
       ],
     ];
 
@@ -1430,17 +1457,20 @@ class api_v3_ContactTest extends CiviUnitTestCase {
 
     // checking child function result not covered in callAPIAndDocument
     $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
-    $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url']);
-    $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url']);
+    $this->assertEquals('http://chained.org', $result['values'][$result['id']]['api.website.create.2']['values'][0]['url']);
+    $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.create']['values'][0]['url']);
 
     // delete the contact
     $this->callAPISuccess('contact', 'delete', $result);
   }
 
   /**
-   * Verify that attempt to create individual contact with chained contribution and website succeeds.
+   * Verify that attempt to create individual contact with chained contribution
+   * and website succeeds.
+   *
+   * @throws \CRM_Core_Exception
    */
-  public function testCreateIndividualWithContributionChainedArrays() {
+  public function testCreateIndividualWithContributionChainedArrays(): void {
     $params = [
       'first_name' => 'abc3',
       'last_name' => 'xyz3',
@@ -1462,23 +1492,23 @@ class api_v3_ContactTest extends CiviUnitTestCase {
       ],
       'api.website.create' => [
         [
-          'url' => "http://civicrm.org",
+          'url' => 'http://civicrm.org',
         ],
         [
-          'url' => "http://chained.org",
+          'url' => 'http://chained.org',
           'website_type_id' => 2,
         ],
       ],
     ];
 
-    $description = "Demonstrates creating two websites as an array.";
-    $subfile = "ChainTwoWebsitesSyntax2";
-    $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__, $description, $subfile);
+    $description = 'Demonstrates creating two websites as an array.';
+    $subFile = 'ChainTwoWebsitesSyntax2';
+    $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__, $description, $subFile);
 
     // the callAndDocument doesn't check the chained call
     $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error']);
-    $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url']);
-    $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url']);
+    $this->assertEquals('http://chained.org', $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url']);
+    $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url']);
 
     $this->callAPISuccess('contact', 'delete', $result);
   }
@@ -1489,9 +1519,10 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    * https://issues.civicrm.org/jira/browse/CRM-16084
    * @param int $version
    *
+   * @throws \CRM_Core_Exception
    * @dataProvider versionThreeAndFour
    */
-  public function testDirectionChainingRelationshipsCRM16084($version) {
+  public function testDirectionChainingRelationshipsCRM16084(int $version): void {
     $this->_apiversion = $version;
     // Some contact, called Jules.
     $create_result_1 = $this->callAPISuccess('contact', 'create', [
@@ -1557,9 +1588,13 @@ class api_v3_ContactTest extends CiviUnitTestCase {
   }
 
   /**
-   * Verify that attempt to create individual contact with first, and last names and email succeeds.
+   * Verify that attempt to create individual contact with first, and last
+   * names and email succeeds.
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CRM_Core_Exception
    */
-  public function testCreateIndividualWithNameEmail() {
+  public function testCreateIndividualWithNameEmail(): void {
     $params = [
       'first_name' => 'abc3',
       'last_name' => 'xyz3',
@@ -1575,7 +1610,7 @@ class api_v3_ContactTest extends CiviUnitTestCase {
   /**
    * Verify that attempt to create individual contact with no data fails.
    */
-  public function testCreateIndividualWithOutNameEmail() {
+  public function testCreateIndividualWithOutNameEmail(): void {
     $params = [
       'contact_type' => 'Individual',
     ];
@@ -1583,9 +1618,13 @@ class api_v3_ContactTest extends CiviUnitTestCase {
   }
 
   /**
-   * Test create individual contact with first &last names, email and location type succeeds.
+   * Test create individual contact with first &last names, email and location
+   * type succeeds.
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CRM_Core_Exception
    */
-  public function testCreateIndividualWithNameEmailLocationType() {
+  public function testCreateIndividualWithNameEmailLocationType(): void {
     $params = [
       'first_name' => 'abc4',
       'last_name' => 'xyz4',
index cb25518fc8c4df490c505eebb66a4ac899f25ef8..170cee5ccdc3c84be78c4e6dfd6a0c819003de7a 100644 (file)
@@ -323,7 +323,7 @@ class api_v3_MembershipTypeTest extends CiviUnitTestCase {
     ];
     foreach ($memType as $rowCount => $type) {
       $membetype = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($type);
-      $fieldParams['option_id'] = [1 => $priceFieldValue['id']];
+      $fieldParams['option_id'] = [1 => $priceFieldValue];
       $fieldParams['option_label'][$rowCount] = $membetype['name'] ?? NULL;
       $fieldParams['option_amount'][$rowCount] = $membetype['minimum_fee'] ?? 0;
       $fieldParams['option_weight'][$rowCount] = $membetype['weight'] ?? NULL;
index faed114075b0a7ba9fe2649fab001018862c8f50..fe5f4e8363642f66b87a57d51f96eac561be2086 100644 (file)
@@ -113,6 +113,14 @@ class FkJoinTest extends UnitTestCase {
     $this->assertEquals('US', $contacts[0]['address.country.iso_code']);
   }
 
+  public function testExcludeJoin() {
+    $contacts = Contact::get(FALSE)
+      ->addJoin('Address AS address', 'EXCLUDE', ['id', '=', 'address.contact_id'], ['address.location_type_id', '=', 1])
+      ->addSelect('id')
+      ->execute()->column('id');
+    $this->assertNotContains($this->getReference('test_contact_1')['id'], $contacts);
+  }
+
   public function testJoinToTheSameTableTwice() {
     $cid1 = Contact::create(FALSE)
       ->addValue('first_name', 'Aaa')
@@ -137,8 +145,8 @@ class FkJoinTest extends UnitTestCase {
     $contacts = Contact::get(FALSE)
       ->addSelect('id', 'first_name', 'any_email.email', 'any_email.location_type_id:name', 'any_email.is_primary', 'primary_email.email')
       ->setJoin([
-        ['Email AS any_email', TRUE, NULL],
-        ['Email AS primary_email', FALSE, ['primary_email.is_primary', '=', TRUE]],
+        ['Email AS any_email', 'INNER', NULL],
+        ['Email AS primary_email', 'LEFT', ['primary_email.is_primary', '=', TRUE]],
       ])
       ->addWhere('id', 'IN', [$cid1, $cid2, $cid3])
       ->addOrderBy('any_email.id')
index 59302b8f60ba824a81e2345e093c1d7d4f31cdec..b0d805ea311c67e28df00108154d67f0821fad53 100644 (file)
@@ -62,8 +62,10 @@ class SpecFormatterTest extends UnitTestCase {
     $data = [
       'custom_group_id' => $customGroupId,
       'custom_group.name' => 'my_group',
+      'custom_group.title' => 'My Group',
       'id' => $customFieldId,
       'name' => $name,
+      'label' => $name,
       'data_type' => 'String',
       'html_type' => 'Select',
       'column_name' => $name,
index 795f1296292d1c9411e296c3634620b8888941e6..18e4e9d87292d2a2a8c449930209bc3227627029 100644 (file)
  * issues
  *
  */
-
+if (!(php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0))) {
+  header("HTTP/1.0 404 Not Found");
+  return;
+}
 define('THROTTLE_REQUESTS', 0);
 function run() {
   session_start();
index ba95cfb4a152366d879d2079fcb49fb9b2f859b5..348620023887da6bb3cec622c6671245e2378eb5 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+if (!(php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0))) {
+  header("HTTP/1.0 404 Not Found");
+  return;
+}
 /**
  * Scrape all config options from the CKEditor documentation site.
  */
index 1918e4e4bb2ff9950ac42bd49645e2ac29e1d653..10220baf2a6dd2f54cbd77998c321af18f7c72d7 100755 (executable)
 
 /* *********************************************************************** */
 /* Boot */
-
+if (!(php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0))) {
+  header("HTTP/1.0 404 Not Found");
+  return;
+}
 $civicrm_root = dirname(dirname(dirname(__DIR__)));
 chdir($civicrm_root);
 
index 8d2668c5260d4dd745d8196dd707e4d2ff92ecce..a9238fc9a8a64b62ccf56229757b3f5d9fa2191b 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+if (!(php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0))) {
+  header("HTTP/1.0 404 Not Found");
+  return;
+}
 require_once '../civicrm.config.php';
 require_once 'CRM/Core/Config.php';
 require_once 'CRM/Core/Error.php';
index ad35bf236bd0a60fd30e8bf640514852d6971107..4ba9fd530f126c14f9ad9a4c62cce9b3062ae067 100644 (file)
@@ -4125,7 +4125,7 @@ INSERT INTO civicrm_state_province (id, country_id, abbreviation, name) VALUES
 (NULL, 1226, "BGE", "Bridgend"),
 (NULL, 1226, "CAY", "Caerphilly"),
 (NULL, 1226, "CRF", "Cardiff"),
-(NULL, 1226, "CRF", "Carmarthenshire"),
+(NULL, 1226, "CMN", "Carmarthenshire"),
 (NULL, 1226, "CGN", "Ceredigion"),
 (NULL, 1226, "CWY", "Conwy"),
 (NULL, 1226, "DEN", "Denbighshire"),