Merge pull request #15962 from seamuslee001/dev_core_1422
[civicrm-core.git] / CRM / Logging / Schema.php
index 9c13df4bd2efe1a7217aece6e04868b7e57a43b4..647edcfbf49cadba49181f57e910f27692461692 100644 (file)
@@ -446,6 +446,17 @@ AND    (TABLE_NAME LIKE 'log_civicrm_%' $nonStandardTableNameString )
       $cols = $this->columnsWithDiffSpecs($table, "log_$table");
     }
 
+    // If a column that already exists on logging table is being added, we
+    // should treat it as a modification.
+    $this->resetSchemaCacheForTable("log_$table");
+    $logTableSchema = $this->columnSpecsOf("log_$table");
+    foreach ($cols['ADD'] as $colKey => $col) {
+      if (array_key_exists($col, $logTableSchema)) {
+        $cols['MODIFY'][] = $col;
+        unset($cols['ADD'][$colKey]);
+      }
+    }
+
     // use the relevant lines from CREATE TABLE to add colums to the log table
     $create = $this->_getCreateQuery($table);
     foreach ((['ADD', 'MODIFY']) as $alterType) {
@@ -467,9 +478,21 @@ AND    (TABLE_NAME LIKE 'log_civicrm_%' $nonStandardTableNameString )
       }
     }
 
+    $this->resetSchemaCacheForTable("log_$table");
+
     return TRUE;
   }
 
+  /**
+   * Resets schema cache for the given table.
+   *
+   * @param string $table
+   *   Name of the table.
+   */
+  private function resetSchemaCacheForTable($table) {
+    unset(\Civi::$statics[__CLASS__]['columnSpecs'][$table]);
+  }
+
   /**
    * Get query table.
    *
@@ -507,6 +530,8 @@ AND    (TABLE_NAME LIKE 'log_civicrm_%' $nonStandardTableNameString )
    */
   public function fixSchemaDifferencesForAll($rebuildTrigger = FALSE) {
     $diffs = [];
+    $this->resetTableColumnsCache();
+
     foreach ($this->tables as $table) {
       if (empty($this->logs[$table])) {
         $this->createLogTableFor($table);
@@ -525,6 +550,17 @@ AND    (TABLE_NAME LIKE 'log_civicrm_%' $nonStandardTableNameString )
     }
   }
 
+  /**
+   * Resets columnSpecs.
+   *
+   * Resets columnSpecs static array in Civi's $statics to make sure we use the
+   * real state of the schema to perform sync operations between core and
+   * logging tables.
+   */
+  private function resetTableColumnsCache() {
+    unset(\Civi::$statics[__CLASS__]['columnSpecs']);
+  }
+
   /**
    * Fix timestamp.
    *
@@ -597,7 +633,7 @@ AND    (TABLE_NAME LIKE 'log_civicrm_%' $nonStandardTableNameString )
       }
       \Civi::$statics[__CLASS__]['columnsOf'][$table] = [];
       while ($dao->fetch()) {
-        \Civi::$statics[__CLASS__]['columnsOf'][$table][] = CRM_Utils_type::escape($dao->Field, 'MysqlColumnNameOrAlias');
+        \Civi::$statics[__CLASS__]['columnsOf'][$table][] = CRM_Utils_Type::escape($dao->Field, 'MysqlColumnNameOrAlias');
       }
     }
     return \Civi::$statics[__CLASS__]['columnsOf'][$table];
@@ -913,6 +949,13 @@ COLS;
 
     // logging is enabled, so now lets create the trigger info tables
     foreach ($tableNames as $table) {
+      if (!isset($this->logTableSpec[$table])) {
+        // Per testIgnoreCustomTableByHook this would be unset if a hook had
+        // intervened to prevent logging / triggers on this table.
+        // This could go to the extent of blocking the updates to 'modified_date'
+        // which makes sense, in particular, for calculated fields.
+        continue;
+      }
       $columns = $this->columnsOf($table, $force);
 
       // only do the change if any data has changed