Add install and runtime status warnings if MySQL utf8mb4 is not supported.
authormark burdett <mfburdett@gmail.com>
Wed, 9 Jan 2019 01:13:27 +0000 (17:13 -0800)
committermark burdett <mfburdett@gmail.com>
Thu, 10 Jan 2019 00:52:43 +0000 (16:52 -0800)
This will allow CiviCRM to require utf8mb4 support at a future date.

See also dev/mail#37 dev/core#339 dev/core#392

CRM/Utils/Check/Component/Env.php
Civi/Install/Requirements.php
install/index.php

index 8e13d3e9a22b5820393deed95bca4e7fc45d7d3c..fdcbaa802ecec32aa501dd0551d7bf5f05ce70e1 100644 (file)
@@ -927,4 +927,60 @@ class CRM_Utils_Check_Component_Env extends CRM_Utils_Check_Component {
     return $messages;
   }
 
+  /**
+   * Check for utf8mb4 support by MySQL.
+   *
+   * @return array<CRM_Utils_Check_Message> an empty array, or a list of warnings
+   */
+  public function checkMysqlUtf8mb4() {
+    $messages = array();
+
+    if (CRM_Core_DAO::getConnection()->phptype != 'mysqli') {
+      return $messages;
+    }
+
+    try {
+      CRM_Core_DAO::executeQuery('CREATE TABLE civicrm_utf8mb4_test (id VARCHAR(255), PRIMARY KEY(id(255))) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC ENGINE=INNODB');
+      CRM_Core_DAO::executeQuery('DROP table civicrm_utf8mb4_test');
+    }
+    catch (Exception $e) {
+      $messages[] = new CRM_Utils_Check_Message(
+        __FUNCTION__,
+        ts('Future versions of CiviCRM may require MySQL utf8mb4 support. It is recommended, though not yet required, to configure your MySQL server for utf8mb4 support. You will need the following MySQL server configuration: innodb_large_prefix=true innodb_file_format=barracuda innodb_file_per_table=true'),
+        ts('MySQL utf8mb4 Support'),
+        \Psr\Log\LogLevel::WARNING,
+        'fa-database'
+      );
+    }
+    // Ensure that the MySQL driver supports utf8mb4 encoding.
+    $version = mysqli_get_client_info(CRM_Core_DAO::getConnection()->connection);
+    if (strpos($version, 'mysqlnd') !== FALSE) {
+      // The mysqlnd driver supports utf8mb4 starting at version 5.0.9.
+      $version = preg_replace('/^\D+([\d.]+).*/', '$1', $version);
+      if (version_compare($version, '5.0.9', '<')) {
+        $messages[] = new CRM_Utils_Check_Message(
+          __FUNCTION__,
+          ts('It is recommended, though not yet required, to upgrade your PHP MySQL driver (mysqlnd) to >= 5.0.9 for utf8mb4 support.'),
+          ts('PHP MySQL Driver (mysqlnd)'),
+          \Psr\Log\LogLevel::WARNING,
+          'fa-server'
+        );
+      }
+    }
+    else {
+      // The libmysqlclient driver supports utf8mb4 starting at version 5.5.3.
+      if (version_compare($version, '5.5.3', '<')) {
+        $messages[] = new CRM_Utils_Check_Message(
+          __FUNCTION__,
+          ts('It is recommended, though not yet required, to upgrade your PHP MySQL driver (libmysqlclient) to >= 5.0.9 for utf8mb4 support.'),
+          ts('PHP MySQL Driver (libmysqlclient)'),
+          \Psr\Log\LogLevel::WARNING,
+          'fa-server'
+        );
+      }
+    }
+
+    return $messages;
+  }
+
 }
index 13506a22b276cc2767e0e5a6c6f66d6762f45312..4d2d3f72d423a3af9ab9497d850b315185765123 100644 (file)
@@ -40,6 +40,7 @@ class Requirements {
     'checkMysqlTrigger',
     'checkMysqlThreadStack',
     'checkMysqlLockTables',
+    'checkMysqlUtf8mb4',
   );
 
   /**
@@ -582,4 +583,65 @@ class Requirements {
     return $results;
   }
 
+  /**
+   * @param $db_config
+   *
+   * @return array
+   */
+  public function checkMysqlUtf8mb4($db_config) {
+    $results = array(
+      'title' => 'CiviCRM MySQL utf8mb4 Support',
+      'severity' => $this::REQUIREMENT_OK,
+      'details' => 'Your system supports the MySQL utf8mb4 character set.',
+    );
+
+    $conn = $this->connect($db_config);
+    if (!$conn) {
+      $results['severity'] = $this::REQUIREMENT_ERROR;
+      $results['details'] = 'Could not connect to database';
+      return $results;
+    }
+
+    if (!@mysqli_select_db($conn, $db_config['database'])) {
+      $results['severity'] = $this::REQUIREMENT_ERROR;
+      $results['details'] = 'Could not select the database';
+      mysqli_close($conn);
+      return $results;
+    }
+
+    $r = mysqli_query($conn, 'CREATE TABLE civicrm_utf8mb4_test (id VARCHAR(255), PRIMARY KEY(id(255))) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC ENGINE=INNODB');
+    if (!$r) {
+      $results['severity'] = $this::REQUIREMENT_WARNING;
+      $results['details'] = 'It is recommended, though not yet required, to configure your MySQL server for utf8mb4 support. You will need the following MySQL server configuration: innodb_large_prefix=true innodb_file_format=barracuda innodb_file_per_table=true';
+      mysqli_close($conn);
+      return $results;
+    }
+    mysqli_query('DROP TABLE civicrm_utf8mb4_test');
+
+    // Ensure that the MySQL driver supports utf8mb4 encoding.
+    $version = mysqli_get_client_info($conn);
+    if (strpos($version, 'mysqlnd') !== FALSE) {
+      // The mysqlnd driver supports utf8mb4 starting at version 5.0.9.
+      $version = preg_replace('/^\D+([\d.]+).*/', '$1', $version);
+      if (version_compare($version, '5.0.9', '<')) {
+        $results['severity'] = $this::REQUIREMENT_WARNING;
+        $results['details'] = 'It is recommended, though not yet required, to upgrade your PHP MySQL driver (mysqlnd) to >= 5.0.9 for utf8mb4 support.';
+        mysqli_close($conn);
+        return $results;
+      }
+    }
+    else {
+      // The libmysqlclient driver supports utf8mb4 starting at version 5.5.3.
+      if (version_compare($version, '5.5.3', '<')) {
+        $results['severity'] = $this::REQUIREMENT_WARNING;
+        $results['details'] = 'It is recommended, though not yet required, to upgrade your PHP MySQL driver (libmysqlclient) to >= 5.5.3 for utf8mb4 support.';
+        mysqli_close($conn);
+        return $results;
+      }
+    }
+
+    mysqli_close($conn);
+    return $results;
+  }
+
 }
index 994786d193aaabf8c9dd562488855b39a2458fad..1bded4d2bb2f81d5bf34ed092c688897da034793 100644 (file)
@@ -557,6 +557,16 @@ class InstallRequirements {
             ts('Unable to create triggers. This MySQL user is missing the CREATE TRIGGERS  privilege.'),
           )
         );
+        $this->requireMySQLUtf8mb4($databaseConfig['server'],
+          $databaseConfig['username'],
+          $databaseConfig['password'],
+          $databaseConfig['database'],
+          array(
+            ts("MySQL %1 Configuration", array(1 => $dbName)),
+            ts('Is the <code>utf8mb4</code> character set supported?'),
+            ts('This MySQL server does not support the <code>utf8mb4</code> character set.'),
+          )
+        );
       }
     }
   }
@@ -1333,6 +1343,57 @@ class InstallRequirements {
     }
   }
 
+  /**
+   * @param $server
+   * @param string $username
+   * @param $password
+   * @param $database
+   * @param $testDetails
+   */
+  public function requireMysqlUtf8mb4($server, $username, $password, $database, $testDetails) {
+    $this->testing($testDetails);
+    $conn = $this->connect($server, $username, $password);
+    if (!$conn) {
+      $testDetails[2] = ts('Could not connect to the database server.');
+      $this->error($testDetails);
+      return;
+    }
+
+    if (!@mysqli_select_db($conn, $database)) {
+      $testDetails[2] = ts('Could not select the database.');
+      $this->error($testDetails);
+      return;
+    }
+
+    $result = mysqli_query($conn, 'CREATE TABLE civicrm_utf8mb4_test (id VARCHAR(255), PRIMARY KEY(id(255))) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC ENGINE=INNODB');
+    if (!$result) {
+      $testDetails[2] = ts('It is recommended, though not yet required, to configure your MySQL server for utf8mb4 support. You will need the following MySQL server configuration: innodb_large_prefix=true innodb_file_format=barracuda innodb_file_per_table=true');
+      $this->warning($testDetails);
+      return;
+    }
+    $result = mysqli_query($conn, 'DROP TABLE civicrm_utf8mb4_test');
+
+    // Ensure that the MySQL driver supports utf8mb4 encoding.
+    $version = mysqli_get_client_info($conn);
+    if (strpos($version, 'mysqlnd') !== FALSE) {
+      // The mysqlnd driver supports utf8mb4 starting at version 5.0.9.
+      $version = preg_replace('/^\D+([\d.]+).*/', '$1', $version);
+      if (version_compare($version, '5.0.9', '<')) {
+        $testDetails[2] = 'It is recommended, though not yet required, to upgrade your PHP MySQL driver (mysqlnd) to >= 5.0.9 for utf8mb4 support.';
+        $this->warning($testDetails);
+        return;
+      }
+    }
+    else {
+      // The libmysqlclient driver supports utf8mb4 starting at version 5.5.3.
+      if (version_compare($version, '5.5.3', '<')) {
+        $testDetails[2] = 'It is recommended, though not yet required, to upgrade your PHP MySQL driver (libmysqlclient) to >= 5.5.3 for utf8mb4 support.';
+        $this->warning($testDetails);
+        return;
+      }
+    }
+  }
+
   /**
    * @param $testDetails
    *