Ensure fieldsTo array are defined
[civicrm-core.git] / CRM / Core / DAO.php
index 70d248bfb010b57d07c198a15ea6b89a9f6035be..dbc886dbcf3556b87f90a059ec87ec42e5e2c657 100644 (file)
@@ -52,6 +52,13 @@ class CRM_Core_DAO extends DB_DataObject {
    */
   public static $_icon = NULL;
 
+  /**
+   * Field to show when displaying a record.
+   *
+   * @var string
+   */
+  public static $_labelField = NULL;
+
   /**
    * @var array
    * @deprecated
@@ -126,7 +133,7 @@ class CRM_Core_DAO extends DB_DataObject {
    */
   public static function getEntityTitle() {
     $className = static::class;
-    Civi::log()->warning("$className needs to be regenerated. Missing getEntityTitle method.", ['civi.tag' => 'deprecated']);
+    CRM_Core_Error::deprecatedWarning("$className needs to be regenerated. Missing getEntityTitle method.");
     return CRM_Core_DAO_AllCoreTables::getBriefName($className);
   }
 
@@ -186,16 +193,6 @@ class CRM_Core_DAO extends DB_DataObject {
     }
     $factory = new CRM_Contact_DAO_Factory();
     CRM_Core_DAO::setFactory($factory);
-    $currentModes = CRM_Utils_SQL::getSqlModes();
-    if (CRM_Utils_Constant::value('CIVICRM_MYSQL_STRICT', CRM_Utils_System::isDevelopment())) {
-      if (CRM_Utils_SQL::supportsFullGroupBy() && !in_array('ONLY_FULL_GROUP_BY', $currentModes) && CRM_Utils_SQL::isGroupByModeInDefault()) {
-        $currentModes[] = 'ONLY_FULL_GROUP_BY';
-      }
-      if (!in_array('STRICT_TRANS_TABLES', $currentModes)) {
-        $currentModes = array_merge(['STRICT_TRANS_TABLES'], $currentModes);
-      }
-      CRM_Core_DAO::executeQuery("SET SESSION sql_mode = %1", [1 => [implode(',', $currentModes), 'String']]);
-    }
     CRM_Core_DAO::executeQuery('SET NAMES utf8mb4');
     CRM_Core_DAO::executeQuery('SET @uniqueID = %1', [1 => [CRM_Utils_Request::id(), 'String']]);
   }
@@ -890,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') {
@@ -1780,11 +1778,9 @@ LIKE %1
       $newObject = new $daoName();
 
       $fields = $object->fields();
-      if (!is_array($fieldsFix)) {
-        $fieldsToPrefix = [];
-        $fieldsToSuffix = [];
-        $fieldsToReplace = [];
-      }
+      $fieldsToPrefix = [];
+      $fieldsToSuffix = [];
+      $fieldsToReplace = [];
       if (!empty($fieldsFix['prefix'])) {
         $fieldsToPrefix = $fieldsFix['prefix'];
       }
@@ -1795,6 +1791,7 @@ LIKE %1
         $fieldsToReplace = $fieldsFix['replace'];
       }
 
+      $localizableFields = FALSE;
       foreach ($fields as $name => $value) {
         if ($name == 'id' || $value['name'] == 'id') {
           // copy everything but the id!
@@ -1818,11 +1815,33 @@ LIKE %1
           $newObject->$dbName = CRM_Utils_Date::isoToMysql($newObject->$dbName);
         }
 
+        if (!empty($value['localizable'])) {
+          $localizableFields = TRUE;
+        }
+
         if ($newData) {
           $newObject->copyValues($newData);
         }
       }
       $newObject->save();
+
+      // ensure we copy all localized fields as well
+      if (CRM_Core_I18n::isMultilingual() && $localizableFields) {
+        global $dbLocale;
+        $locales = CRM_Core_I18n::getMultilingual();
+        $curLocale = CRM_Core_I18n::getLocale();
+        // loop on other locales
+        foreach ($locales as $locale) {
+          if ($locale != $curLocale) {
+            // setLocale doesn't seems to be reliable to set dbLocale and we only need to change the db locale
+            $dbLocale = '_' . $locale;
+            $newObject->copyLocalizable($object->id, $newObject->id, $fieldsToPrefix, $fieldsToSuffix, $fieldsToReplace);
+          }
+        }
+        // restore dbLocale to starting value
+        $dbLocale = '_' . $curLocale;
+      }
+
       if (!$blockCopyofCustomValues) {
         $newObject->copyCustomFields($object->id, $newObject->id);
       }
@@ -1832,6 +1851,67 @@ LIKE %1
     return $newObject;
   }
 
+  /**
+   * Method that copies localizable fields from an old entity to a new one.
+   *
+   * Fixes bug dev/core#2479,
+   * where non current locale fields are copied from current locale losing translation when copying
+   *
+   * @param int $entityID
+   * @param int $newEntityID
+   * @param array $fieldsToPrefix
+   * @param array $fieldsToSuffix
+   * @param array $fieldsToReplace
+   */
+  protected function copyLocalizable($entityID, $newEntityID, $fieldsToPrefix, $fieldsToSuffix, $fieldsToReplace) {
+    $entity = get_class($this);
+    $object = new $entity();
+    $object->id = $entityID;
+    $object->find();
+
+    $newObject = new $entity();
+    $newObject->id = $newEntityID;
+
+    $newObject->find();
+
+    if ($object->fetch() && $newObject->fetch()) {
+
+      $fields = $object->fields();
+      foreach ($fields as $name => $value) {
+
+        if ($name == 'id' || $value['name'] == 'id') {
+          // copy everything but the id!
+          continue;
+        }
+
+        // only copy localizable fields
+        if (!$value['localizable']) {
+          continue;
+        }
+
+        $dbName = $value['name'];
+        $type = CRM_Utils_Type::typeToString($value['type']);
+        $newObject->$dbName = $object->$dbName;
+        if (isset($fieldsToPrefix[$dbName])) {
+          $newObject->$dbName = $fieldsToPrefix[$dbName] . $newObject->$dbName;
+        }
+        if (isset($fieldsToSuffix[$dbName])) {
+          $newObject->$dbName .= $fieldsToSuffix[$dbName];
+        }
+        if (isset($fieldsToReplace[$dbName])) {
+          $newObject->$dbName = $fieldsToReplace[$dbName];
+        }
+
+        if ($type == 'Timestamp' || $type == 'Date') {
+          $newObject->$dbName = CRM_Utils_Date::isoToMysql($newObject->$dbName);
+        }
+
+      }
+      $newObject->save();
+
+    }
+  }
+
   /**
    * Method that copies custom fields values from an old entity to a new one.
    *
@@ -2286,40 +2366,21 @@ SELECT contact_id
     if (\Civi::settings()->get('logging_no_trigger_permission')) {
       return TRUE;
     }
-    // test for create view and trigger permissions and if allowed, add the option to go multilingual
-    // and logging
-    // I'm not sure why we use the getStaticProperty for an error, rather than checking for DB_Error
+    // test for create view and trigger permissions and if allowed, add the option to go multilingual and logging
     $dao = new CRM_Core_DAO();
-    if ($view) {
-      $result = $dao->query('CREATE OR REPLACE VIEW civicrm_domain_view AS SELECT * FROM civicrm_domain');
-      if (PEAR::getStaticProperty('DB_DataObject', 'lastError') || is_a($result, 'DB_Error')) {
-        return FALSE;
+    try {
+      if ($view) {
+        $dao->query('CREATE OR REPLACE VIEW civicrm_domain_view AS SELECT * FROM civicrm_domain');
+        $dao->query('DROP VIEW IF EXISTS civicrm_domain_view');
       }
-    }
 
-    if ($trigger) {
-      $result = $dao->query('CREATE TRIGGER civicrm_domain_trigger BEFORE INSERT ON civicrm_domain FOR EACH ROW BEGIN END');
-      if (PEAR::getStaticProperty('DB_DataObject', 'lastError') || is_a($result, 'DB_Error')) {
-        if ($view) {
-          $dao->query('DROP VIEW IF EXISTS civicrm_domain_view');
-        }
-        return FALSE;
-      }
-
-      $dao->query('DROP TRIGGER IF EXISTS civicrm_domain_trigger');
-      if (PEAR::getStaticProperty('DB_DataObject', 'lastError')) {
-        if ($view) {
-          $dao->query('DROP VIEW IF EXISTS civicrm_domain_view');
-        }
-        return FALSE;
+      if ($trigger) {
+        $dao->query('CREATE TRIGGER civicrm_domain_trigger BEFORE INSERT ON civicrm_domain FOR EACH ROW BEGIN END');
+        $dao->query('DROP TRIGGER IF EXISTS civicrm_domain_trigger');
       }
     }
-
-    if ($view) {
-      $dao->query('DROP VIEW IF EXISTS civicrm_domain_view');
-      if (PEAR::getStaticProperty('DB_DataObject', 'lastError')) {
-        return FALSE;
-      }
+    catch (Exception $e) {
+      return FALSE;
     }
 
     return TRUE;