Merge pull request #14252 from jitendrapurohit/core-961
[civicrm-core.git] / Civi / API / Subscriber / I18nSubscriber.php
index c430928202ba17ce3ee49a709a0485c305d2b003..335bc823afa5bf0fc09362ccf4b4edc9f66e7089 100644 (file)
@@ -36,16 +36,26 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  */
 class I18nSubscriber implements EventSubscriberInterface {
 
+  /**
+   * Used for rolling back language to its original setting after the api call.
+   *
+   * @var array
+   */
+  public $originalLang = [];
+
   /**
    * @return array
    */
   public static function getSubscribedEvents() {
     return [
       Events::PREPARE => ['onApiPrepare', Events::W_MIDDLE],
+      Events::RESPOND => ['onApiRespond', Events::W_LATE],
     ];
   }
 
   /**
+   * Support multi-lingual requests
+   *
    * @param \Civi\API\Event\Event $event
    *   API preparation event.
    *
@@ -54,9 +64,33 @@ class I18nSubscriber implements EventSubscriberInterface {
   public function onApiPrepare(\Civi\API\Event\Event $event) {
     $apiRequest = $event->getApiRequest();
 
-    // support multi-lingual requests
-    if ($language = \CRM_Utils_Array::value('option.language', $apiRequest['params'])) {
-      $this->setLocale($language);
+    $params = $apiRequest['params'];
+    if ($apiRequest['version'] < 4) {
+      $language = !empty($params['options']['language']) ? $params['options']['language'] : \CRM_Utils_Array::value('option.language', $params);
+    }
+    else {
+      $language = \CRM_Utils_Array::value('language', $params);
+    }
+    if ($language) {
+      $this->setLocale($language, $apiRequest['id']);
+    }
+  }
+
+  /**
+   * Reset language to the default.
+   *
+   * @param \Civi\API\Event\Event $event
+   *
+   * @throws \API_Exception
+   */
+  public function onApiRespond(\Civi\API\Event\Event $event) {
+    $apiRequest = $event->getApiRequest();
+
+    if (!empty($this->originalLang[$apiRequest['id']])) {
+      global $tsLocale;
+      global $dbLocale;
+      $tsLocale = $this->originalLang[$apiRequest['id']]['tsLocale'];
+      $dbLocale = $this->originalLang[$apiRequest['id']]['dbLocale'];
     }
   }
 
@@ -64,44 +98,35 @@ class I18nSubscriber implements EventSubscriberInterface {
    * Sets the tsLocale and dbLocale for multi-lingual sites.
    * Some code duplication from CRM/Core/BAO/ConfigSetting.php retrieve()
    * to avoid regressions from refactoring.
-   * @param $lcMessagesRequest
+   * @param string $lcMessages
+   * @param int $requestId
    * @throws \API_Exception
    */
-  public function setLocale($lcMessagesRequest) {
-    // We must validate whether the locale is valid, otherwise setting a bad
-    // dbLocale could probably lead to sql-injection.
+  public function setLocale($lcMessages, $requestId) {
     $domain = new \CRM_Core_DAO_Domain();
     $domain->id = \CRM_Core_Config::domainID();
     $domain->find(TRUE);
 
-    // are we in a multi-language setup?
-    $multiLang = $domain->locales ? TRUE : FALSE;
-    $lcMessages = NULL;
-
-    // on multi-lang sites based on request and civicrm_uf_match
-    if ($multiLang) {
-      $config = \CRM_Core_Config::singleton();
-      $languageLimit = [];
-      if (isset($config->languageLimit) and $config->languageLimit) {
-        $languageLimit = $config->languageLimit;
+    // Check if the site is multi-lingual
+    if ($domain->locales && $lcMessages) {
+      // Validate language, otherwise a bad dbLocale could probably lead to sql-injection.
+      if (!array_key_exists($lcMessages, \Civi::settings()->get('languageLimit'))) {
+        throw new \API_Exception(ts('Language not enabled: %1', [1 => $lcMessages]));
       }
 
-      if (in_array($lcMessagesRequest, array_keys($languageLimit))) {
-        $lcMessages = $lcMessagesRequest;
-      }
-      else {
-        throw new \API_Exception(ts('Language not enabled: %1', [1 => $lcMessagesRequest]));
-      }
-    }
+      global $dbLocale;
+      global $tsLocale;
 
-    global $dbLocale;
+      // Store original value to be restored in $this->onApiRespond
+      $this->originalLang[$requestId] = [
+        'tsLocale' => $tsLocale,
+        'dbLocale' => $dbLocale,
+      ];
 
-    // set suffix for table names - use views if more than one language
-    if ($lcMessages) {
-      $dbLocale = $multiLang && $lcMessages ? "_{$lcMessages}" : '';
+      // Set suffix for table names - use views if more than one language
+      $dbLocale = "_{$lcMessages}";
 
-      // FIXME: an ugly hack to fix CRM-4041
-      global $tsLocale;
+      // Also set tsLocale - CRM-4041
       $tsLocale = $lcMessages;
     }
   }