CRM-16373 - Localization - Rearrange load/save logic
authorTim Otten <totten@civicrm.org>
Tue, 8 Sep 2015 21:23:42 +0000 (14:23 -0700)
committerTim Otten <totten@civicrm.org>
Thu, 17 Sep 2015 22:49:29 +0000 (15:49 -0700)
 * Declare missing setting `languageLimit`
 * Allow saving admin form -- even when using makeMultilingual, makeSinglelingual, addLanguage, and/or languageLimit
 * Move onChange logic for `lcMessages` from `ConfigSetting::add()` to `onChangeLcMessages()`
 * Move locale init from `ConfigSetting::retrieve()` to `applyLocale()`

CRM/Admin/Form/Setting/Localization.php
CRM/Core/BAO/ConfigSetting.php
CRM/Core/BAO/Setting.php
settings/Localization.setting.php

index d8e9e29cd274f9ee68013fd00c45fcdf17995c89..ead6d55efcf64c45fecd1cf2988a7b8bf667337a 100644 (file)
@@ -62,15 +62,15 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting {
     CRM_Utils_System::setTitle(ts('Settings - Localization'));
 
     $warningTitle = json_encode(ts("Warning"));
-    $lcMessages = CRM_Admin_Form_Setting_Localization::getDefaultLocaleOptions();
+    $defaultLocaleOptions = CRM_Admin_Form_Setting_Localization::getDefaultLocaleOptions();
 
     $domain = new CRM_Core_DAO_Domain();
     $domain->find(TRUE);
 
     if ($domain->locales) {
       // add language limiter and language adder
-      $this->addCheckBox('languageLimit', ts('Available Languages'), array_flip($lcMessages), NULL, NULL, NULL, NULL, ' &nbsp; ');
-      $this->addElement('select', 'addLanguage', ts('Add Language'), array_merge(array('' => ts('- select -')), array_diff(CRM_Core_I18n::languages(), $lcMessages)));
+      $this->addCheckBox('languageLimit', ts('Available Languages'), array_flip($defaultLocaleOptions), NULL, NULL, NULL, NULL, ' &nbsp; ');
+      $this->addElement('select', 'addLanguage', ts('Add Language'), array_merge(array('' => ts('- select -')), array_diff(CRM_Core_I18n::languages(), $defaultLocaleOptions)));
 
       // add the ability to return to single language
       $warning = ts('This will make your CiviCRM installation a single-language one again. THIS WILL DELETE ALL DATA RELATED TO LANGUAGES OTHER THAN THE DEFAULT ONE SELECTED ABOVE (and only that language will be preserved).');
@@ -167,6 +167,8 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting {
     // retrieve default values for currencyLimit
     $this->_defaults['currencyLimit'] = array_keys(CRM_Core_OptionGroup::values('currencies_enabled'));
 
+    $this->_defaults['languageLimit'] = Civi::settings()->get('languageLimit');
+
     // CRM-5111: unset these two unconditionally, we don’t want them to stick – ever
     unset($this->_defaults['makeMultilingual']);
     unset($this->_defaults['makeSinglelingual']);
@@ -248,8 +250,16 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting {
     // if we manipulated the language list, return to the localization admin screen
     $return = (bool) (CRM_Utils_Array::value('makeMultilingual', $values) or CRM_Utils_Array::value('addLanguage', $values));
 
+    $filteredValues = $values;
+    unset($filteredValues['makeMultilingual']);
+    unset($filteredValues['makeSinglelingual']);
+    unset($filteredValues['addLanguage']);
+    unset($filteredValues['languageLimit']);
+
+    Civi::settings()->set('languageLimit', CRM_Utils_Array::value('languageLimit', $values));
+
     // save all the settings
-    parent::commonProcess($values);
+    parent::commonProcess($filteredValues);
 
     if ($return) {
       CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/setting/localization', 'reset=1'));
@@ -277,17 +287,17 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting {
     $locales = CRM_Core_I18n::languages();
     if ($domain->locales) {
       // for multi-lingual sites, populate default language drop-down with available languages
-      $lcMessages = array();
+      $defaultLocaleOptions = array();
       foreach ($locales as $loc => $lang) {
         if (substr_count($domain->locales, $loc)) {
-          $lcMessages[$loc] = $lang;
+          $defaultLocaleOptions[$loc] = $lang;
         }
       }
     }
     else {
-      $lcMessages = $locales;
+      $defaultLocaleOptions = $locales;
     }
-    return $lcMessages;
+    return $defaultLocaleOptions;
   }
 
   /**
@@ -311,4 +321,21 @@ class CRM_Admin_Form_Setting_Localization extends CRM_Admin_Form_Setting {
     return $_currencySymbols;
   }
 
+  public static function onChangeLcMessages($oldLocale, $newLocale, $metadata, $domainID) {
+    if ($oldLocale == $newLocale) {
+      return;
+    }
+
+    $session = CRM_Core_Session::singleton();
+    if ($newLocale && $session->get('userID')) {
+      $ufm = new CRM_Core_DAO_UFMatch();
+      $ufm->contact_id = $session->get('userID');
+      if ($newLocale && $ufm->find(TRUE)) {
+        $ufm->language = $newLocale;
+        $ufm->save();
+        $session->set('lcMessages', $newLocale);
+      }
+    }
+  }
+
 }
index 051d7352a60ab768ad2584ffa043f10871b20404..de61ec0eee8bba10c4cc64ad35ce417356a71fe5 100644 (file)
@@ -75,27 +75,6 @@ class CRM_Core_BAO_ConfigSetting {
       }
     }
 
-    //keep user preferred language up to date, CRM-7746
-    $session = CRM_Core_Session::singleton();
-    $lcMessages = CRM_Utils_Array::value('lcMessages', $params);
-    if ($lcMessages && $session->get('userID')) {
-      $languageLimit = CRM_Utils_Array::value('languageLimit', $params);
-      if (is_array($languageLimit) &&
-        !in_array($lcMessages, array_keys($languageLimit))
-      ) {
-        $lcMessages = $session->get('lcMessages');
-      }
-
-      $ufm = new CRM_Core_DAO_UFMatch();
-      $ufm->contact_id = $session->get('userID');
-      if ($lcMessages && $ufm->find(TRUE)) {
-        $ufm->language = $lcMessages;
-        $ufm->save();
-        $session->set('lcMessages', $lcMessages);
-        $params['lcMessages'] = $lcMessages;
-      }
-    }
-
     $domain->config_backend = serialize($params);
     $domain->save();
   }
@@ -139,95 +118,106 @@ class CRM_Core_BAO_ConfigSetting {
         }
       }
 
-      // are we in a multi-language setup?
-      $multiLang = $domain->locales ? TRUE : FALSE;
+      CRM_Core_BAO_ConfigSetting::applyLocale(Civi::settings($domain->id), $domain->locales);
+    }
+  }
 
-      // set the current language
-      $lcMessages = NULL;
+  /**
+   * Evaluate locale preferences and activate a chosen locale by
+   * updating session+global variables.
+   *
+   * @param \Civi\Core\SettingsBag $settings
+   * @param string $activatedLocales
+   *   Imploded list of locales which are supported in the DB.
+   * @return array
+   */
+  public static function applyLocale($settings, $activatedLocales) {
+    // are we in a multi-language setup?
+    $multiLang = $activatedLocales ? TRUE : FALSE;
 
-      $session = CRM_Core_Session::singleton();
+    // set the current language
+    $chosenLocale = NULL;
 
-      // on multi-lang sites based on request and civicrm_uf_match
-      if ($multiLang) {
-        $lcMessagesRequest = CRM_Utils_Request::retrieve('lcMessages', 'String', $this);
-        $languageLimit = array();
-        if (array_key_exists('languageLimit', $defaults) && is_array($defaults['languageLimit'])) {
-          $languageLimit = $defaults['languageLimit'];
-        }
+    $session = CRM_Core_Session::singleton();
 
-        if (in_array($lcMessagesRequest, array_keys($languageLimit))) {
-          $lcMessages = $lcMessagesRequest;
+    // on multi-lang sites based on request and civicrm_uf_match
+    if ($multiLang) {
+      $languageLimit = array();
+      if (is_array($settings->get('languageLimit'))) {
+        $languageLimit = $settings->get('languageLimit');
+      }
 
-          //CRM-8559, cache navigation do not respect locale if it is changed, so reseting cache.
-          CRM_Core_BAO_Cache::deleteGroup('navigation');
-        }
-        else {
-          $lcMessagesRequest = NULL;
-        }
+      $requestLocale = CRM_Utils_Request::retrieve('lcMessages', 'String');
+      if (in_array($requestLocale, array_keys($languageLimit))) {
+        $chosenLocale = $requestLocale;
 
-        if (!$lcMessagesRequest) {
-          $lcMessagesSession = $session->get('lcMessages');
-          if (in_array($lcMessagesSession, array_keys($languageLimit))) {
-            $lcMessages = $lcMessagesSession;
-          }
-          else {
-            $lcMessagesSession = NULL;
-          }
-        }
+        //CRM-8559, cache navigation do not respect locale if it is changed, so reseting cache.
+        // Ed: This doesn't sound good.
+        CRM_Core_BAO_Cache::deleteGroup('navigation');
+      }
+      else {
+        $requestLocale = NULL;
+      }
 
-        if ($lcMessagesRequest) {
-          $ufm = new CRM_Core_DAO_UFMatch();
-          $ufm->contact_id = $session->get('userID');
-          if ($ufm->find(TRUE)) {
-            $ufm->language = $lcMessages;
-            $ufm->save();
-          }
-          $session->set('lcMessages', $lcMessages);
+      if (!$requestLocale) {
+        $sessionLocale = $session->get('lcMessages');
+        if (in_array($sessionLocale, array_keys($languageLimit))) {
+          $chosenLocale = $sessionLocale;
+        }
+        else {
+          $sessionLocale = NULL;
         }
+      }
 
-        if (!$lcMessages and $session->get('userID')) {
-          $ufm = new CRM_Core_DAO_UFMatch();
-          $ufm->contact_id = $session->get('userID');
-          if ($ufm->find(TRUE) &&
-            in_array($ufm->language, array_keys($languageLimit))
-          ) {
-            $lcMessages = $ufm->language;
-          }
-          $session->set('lcMessages', $lcMessages);
+      if ($requestLocale) {
+        $ufm = new CRM_Core_DAO_UFMatch();
+        $ufm->contact_id = $session->get('userID');
+        if ($ufm->find(TRUE)) {
+          $ufm->language = $chosenLocale;
+          $ufm->save();
         }
+        $session->set('lcMessages', $chosenLocale);
       }
-      global $dbLocale;
-
-      // try to inherit the language from the hosting CMS
-      if (!empty($defaults['inheritLocale'])) {
-        // FIXME: On multilanguage installs, CRM_Utils_System::getUFLocale() in many cases returns nothing if $dbLocale is not set
-        $dbLocale = $multiLang ? "_{$defaults['lcMessages']}" : '';
-        $lcMessages = CRM_Utils_System::getUFLocale();
-        if ($domain->locales and !in_array($lcMessages, explode(CRM_Core_DAO::VALUE_SEPARATOR,
-            $domain->locales
-          ))
+
+      if (!$chosenLocale and $session->get('userID')) {
+        $ufm = new CRM_Core_DAO_UFMatch();
+        $ufm->contact_id = $session->get('userID');
+        if ($ufm->find(TRUE) &&
+          in_array($ufm->language, array_keys($languageLimit))
         ) {
-          $lcMessages = NULL;
+          $chosenLocale = $ufm->language;
         }
+        $session->set('lcMessages', $chosenLocale);
       }
-
-      if (empty($lcMessages)) {
-        //CRM-11993 - if a single-lang site, use default
-        $lcMessages = CRM_Utils_Array::value('lcMessages', $defaults);
+    }
+    global $dbLocale;
+
+    // try to inherit the language from the hosting CMS
+    if ($settings->get('inheritLocale')) {
+      // FIXME: On multilanguage installs, CRM_Utils_System::getUFLocale() in many cases returns nothing if $dbLocale is not set
+      $dbLocale = $multiLang ? ("_" . $settings->get('lcMessages')) : '';
+      $chosenLocale = CRM_Utils_System::getUFLocale();
+      if ($activatedLocales and !in_array($chosenLocale, explode(CRM_Core_DAO::VALUE_SEPARATOR, $activatedLocales))) {
+        $chosenLocale = NULL;
       }
+    }
+
+    if (empty($chosenLocale)) {
+      //CRM-11993 - if a single-lang site, use default
+      $chosenLocale = $settings->get('lcMessages');
+    }
 
-      // set suffix for table names - use views if more than one language
-      $dbLocale = $multiLang ? "_{$lcMessages}" : '';
+    // set suffix for table names - use views if more than one language
+    $dbLocale = $multiLang ? "_{$chosenLocale}" : '';
 
-      // FIXME: an ugly hack to fix CRM-4041
-      global $tsLocale;
-      $tsLocale = $lcMessages;
+    // FIXME: an ugly hack to fix CRM-4041
+    global $tsLocale;
+    $tsLocale = $chosenLocale;
 
-      // FIXME: as bad aplace as any to fix CRM-5428
-      // (to be moved to a sane location along with the above)
-      if (function_exists('mb_internal_encoding')) {
-        mb_internal_encoding('UTF-8');
-      }
+    // FIXME: as bad aplace as any to fix CRM-5428
+    // (to be moved to a sane location along with the above)
+    if (function_exists('mb_internal_encoding')) {
+      mb_internal_encoding('UTF-8');
     }
   }
 
index d8eeadfc81e24744b764057b7810dffa5a4b958f..a9688fc9ac8b7ade03d59b4a69340e6cc720f3b4 100644 (file)
@@ -381,7 +381,8 @@ class CRM_Core_BAO_Setting extends CRM_Core_DAO_Setting {
           Civi\Core\Resolver::singleton()->get($callback),
           unserialize($dao->value),
           $value,
-          $metadata
+          $metadata,
+          $domainID
         );
       }
     }
index 52ff3ba29e2ffc63aa88bd31ba44b426b6f11289..4e57ffb6a45d7ca55f42e78c7452755d5bfe0753 100644 (file)
@@ -210,7 +210,7 @@ return array(
       'multiple' => 1,
       'class' => 'crm-select2',
     ),
-    'default' => 'null',
+    'default' => NULL,
     'add' => '4.3',
     'title' => 'Available Countries',
     'is_domain' => 1,
@@ -234,7 +234,7 @@ return array(
       'multiple' => 1,
       'class' => 'crm-select2',
     ),
-    'default' => 'null',
+    'default' => NULL,
     'add' => '4.3',
     'title' => 'Available States and Provinces',
     'is_domain' => 1,
@@ -407,14 +407,34 @@ return array(
     'title' => 'Fiscal Year Start',
     'description' => '',
   ),
+  'languageLimit' => array(
+    'group_name' => 'Localization Preferences',
+    'group' => 'localization',
+    'name' => 'languageLimit',
+    'type' => 'Array',
+    'quick_form_type' => 'Select',
+    'html_type' => 'Select',
+    'html_attributes' => array(
+      'multiple' => 1,
+      'class' => 'crm-select2',
+    ),
+    'default' => NULL,
+    'add' => '4.3',
+    'title' => 'Available Languages (Multi-lingual)',
+    'is_domain' => 1,
+    'is_contact' => 0,
+    'description' => '',
+    'help_text' => NULL,
+    'pseudoconstant' => array(
+      'callback' => 'CRM_Core_I18n::languages',
+    ),
+  ),
   'lcMessages' => array(
     'group_name' => 'Localization Preferences',
     'group' => 'localization',
     'name' => 'lcMessages',
     'prefetch' => 1,
     // prefetch causes it to be cached in config settings. Usually this is a transitional setting. Some things like urls are permanent. Remove this comment if you have assessed & it should be permanent
-    //'config_only' => 1,
-    //@todo - see https://wiki.civicrm.org/confluence/display/CRMDOC/Settings+Reference#SettingsReference-Convertingaconfigobjecttoasetting on removing this deprecated value
     'type' => 'String',
     'quick_form_type' => 'Select',
     'html_type' => 'Select',
@@ -431,6 +451,9 @@ return array(
     'pseudoconstant' => array(
       'callback' => 'CRM_Admin_Form_Setting_Localization::getDefaultLocaleOptions',
     ),
+    'on_change' => array(
+      'CRM_Admin_Form_Setting_Localization::onChangeLcMessages',
+    ),
   ),
   'legacyEncoding' => array(
     'add' => '4.7',