comment fixes
[civicrm-core.git] / CRM / Logging / Schema.php
index 1fbb0dc5e5c05a5a883f27c1d46cc4b7f7445a36..b36635eef5c20cc87db0ca3b8240a7dd043971f2 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /*
  +--------------------------------------------------------------------+
- | CiviCRM version 4.6                                                |
+ | CiviCRM version 4.7                                                |
  +--------------------------------------------------------------------+
  | Copyright CiviCRM LLC (c) 2004-2015                                |
  +--------------------------------------------------------------------+
@@ -52,6 +52,49 @@ class CRM_Logging_Schema {
     'civicrm_group' => array('cache_date', 'refresh_date'),
   );
 
+  /**
+   * (Setting Callback - Validate)
+   *
+   * @param mixed $value
+   * @param array $fieldSpec
+   * @return bool
+   * @throws API_Exception
+   */
+  public static function checkLoggingSupport(&$value, $fieldSpec) {
+    $domain = new CRM_Core_DAO_Domain();
+    $domain->find(TRUE);
+    if (!(CRM_Core_DAO::checkTriggerViewPermission(FALSE)) && $value) {
+      throw new API_Exception("In order to use this functionality, the installation's database user must have privileges to create triggers (in MySQL 5.0 – and in MySQL 5.1 if binary logging is enabled – this means the SUPER privilege). This install either does not seem to have the required privilege enabled.");
+    }
+    return TRUE;
+  }
+
+  /**
+   * (Setting Callback - On Change)
+   * Respond to changes in the "logging" setting. Set up or destroy
+   * triggers, etal.
+   *
+   * @param array $oldValue
+   *   List of component names.
+   * @param array $newValue
+   *   List of component names.
+   * @param array $metadata
+   *   Specification of the setting (per *.settings.php).
+   */
+  public static function onToggle($oldValue, $newValue, $metadata) {
+    if ($oldValue == $newValue) {
+      return;
+    }
+
+    $logging = new CRM_Logging_Schema();
+    if ($newValue) {
+      $logging->enableLogging();
+    }
+    else {
+      $logging->disableLogging();
+    }
+  }
+
   /**
    * Populate $this->tables and $this->logs with current db state.
    */
@@ -144,6 +187,8 @@ AND    TABLE_NAME LIKE 'log_civicrm_%'
 
   /**
    * Drop triggers for all logged tables.
+   *
+   * @param string $tableName
    */
   public function dropTriggers($tableName = NULL) {
     $dao = new CRM_Core_DAO();
@@ -372,7 +417,7 @@ AND    TABLE_NAME LIKE 'log_civicrm_%'
 
     if (!isset($columnsOf[$table]) || $force) {
       $errorScope = CRM_Core_TemporaryErrorScope::ignoreException();
-      $dao = CRM_Core_DAO::executeQuery("SHOW COLUMNS FROM $from");
+      $dao = CRM_Core_DAO::executeQuery("SHOW COLUMNS FROM $from", CRM_Core_DAO::$_nullArray, TRUE, NULL, FALSE, FALSE);
       if (is_a($dao, 'DB_Error')) {
         return array();
       }
@@ -396,11 +441,11 @@ AND    TABLE_NAME LIKE 'log_civicrm_%'
         $dao = new CRM_Contact_DAO_Contact();
         $civiDB = $dao->_database;
       }
-      $errorScope = CRM_Core_TemporaryErrorScope::ignoreException();
+      CRM_Core_TemporaryErrorScope::ignoreException();
       // NOTE: W.r.t Performance using one query to find all details and storing in static array is much faster
       // than firing query for every given table.
       $query = "
-SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT
+SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_TYPE
 FROM   INFORMATION_SCHEMA.COLUMNS
 WHERE  table_schema IN ('{$this->db}', '{$civiDB}')";
       $dao = CRM_Core_DAO::executeQuery($query);
@@ -417,6 +462,9 @@ WHERE  table_schema IN ('{$this->db}', '{$civiDB}')";
           'IS_NULLABLE' => $dao->IS_NULLABLE,
           'COLUMN_DEFAULT' => $dao->COLUMN_DEFAULT,
         );
+        if (($first = strpos($dao->COLUMN_TYPE, '(')) != 0) {
+          $columnSpecs[$dao->TABLE_NAME][$dao->COLUMN_NAME]['LENGTH'] = substr($dao->COLUMN_TYPE, $first, strpos($dao->COLUMN_TYPE, ')'));
+        }
       }
     }
     return $columnSpecs[$table];
@@ -448,7 +496,10 @@ WHERE  table_schema IN ('{$this->db}', '{$civiDB}')";
       $specDiff = array_diff($civiTableSpecs[$col], $logTableSpecs[$col]);
       if (!empty($specDiff) && $col != 'id' && !array_key_exists($col, $diff['ADD'])) {
         // ignore 'id' column for any spec changes, to avoid any auto-increment mysql errors
-        if ($civiTableSpecs[$col]['DATA_TYPE'] != CRM_Utils_Array::value('DATA_TYPE', $logTableSpecs[$col])) {
+        if ($civiTableSpecs[$col]['DATA_TYPE'] != CRM_Utils_Array::value('DATA_TYPE', $logTableSpecs[$col])
+        // We won't alter the log if the length is decreased in case some of the existing data won't fit.
+        || CRM_Utils_Array::value('LENGTH', $civiTableSpecs[$col]) > CRM_Utils_Array::value('LENGTH', $logTableSpecs[$col])
+        ) {
           // if data-type is different, surely consider the column
           $diff['MODIFY'][] = $col;
         }
@@ -485,7 +536,7 @@ WHERE  table_schema IN ('{$this->db}', '{$civiDB}')";
    * Create a log table with schema mirroring the given table’s structure and seeding it with the given table’s contents.
    */
   private function createLogTableFor($table) {
-    $dao = CRM_Core_DAO::executeQuery("SHOW CREATE TABLE $table");
+    $dao = CRM_Core_DAO::executeQuery("SHOW CREATE TABLE $table", CRM_Core_DAO::$_nullArray, TRUE, NULL, FALSE, FALSE);
     $dao->fetch();
     $query = $dao->Create_Table;
 
@@ -513,10 +564,10 @@ COLS;
     $query = self::fixTimeStampAndNotNullSQL($query);
     $query = preg_replace("/^\) /m", "$cols\n) ", $query);
 
-    CRM_Core_DAO::executeQuery($query);
+    CRM_Core_DAO::executeQuery($query, CRM_Core_DAO::$_nullArray, TRUE, NULL, FALSE, FALSE);
 
     $columns = implode(', ', $this->columnsOf($table));
-    CRM_Core_DAO::executeQuery("INSERT INTO `{$this->db}`.log_$table ($columns, log_conn_id, log_user_id, log_action) SELECT $columns, CONNECTION_ID(), @civicrm_user_id, 'Initialization' FROM {$table}");
+    CRM_Core_DAO::executeQuery("INSERT INTO `{$this->db}`.log_$table ($columns, log_conn_id, log_user_id, log_action) SELECT $columns, CONNECTION_ID(), @civicrm_user_id, 'Initialization' FROM {$table}", CRM_Core_DAO::$_nullArray, TRUE, NULL, FALSE, FALSE);
 
     $this->tables[] = $table;
     $this->logs[$table] = "log_$table";