[REF] Fix utf8mb4 test in APIv4 and re-enable the altering of database in the v3...
authorSeamus Lee <seamuslee001@gmail.com>
Mon, 2 Aug 2021 22:34:47 +0000 (08:34 +1000)
committerSeamus Lee <seamuslee001@gmail.com>
Sat, 7 Aug 2021 02:48:02 +0000 (12:48 +1000)
CRM/Contact/BAO/Query.php
CRM/Core/DAO.php
CRM/Utils/SQL.php
tests/phpunit/api/v3/ContactTest.php
tests/phpunit/api/v4/Action/ContactGetTest.php

index 58b54ca1dfe941bab79df43037b11a354f34fa3c..cbe7debf28a06ac4cb131785994ffe8c30ad6dfc 100644 (file)
@@ -5668,7 +5668,10 @@ civicrm_relationship.start_date > {$today}
           }
           throw new CRM_Core_Exception(ts('Failed to interpret input for search'));
         }
-
+        $emojiWhere = CRM_Utils_SQL::handleEmojiInQuery($value);
+        if ($emojiWhere === '0 = 1') {
+          $value = $emojiWhere;
+        }
         $value = CRM_Utils_Type::escape($value, $dataType);
         // if we don't have a dataType we should assume
         if ($dataType == 'String' || $dataType == 'Text') {
index 7ac51a518f715c4e4d9fae150d7f58560ba657b9..5bb34367c713f0f0d8045ec04c2e7a186fed7db7 100644 (file)
@@ -2881,20 +2881,9 @@ SELECT contact_id
    */
   public static function createSQLFilter($fieldName, $filter, $type = NULL, $alias = NULL, $returnSanitisedArray = FALSE) {
     foreach ($filter as $operator => $criteria) {
-      if (!CRM_Core_BAO_SchemaHandler::databaseSupportsUTF8MB4()) {
-        foreach ((array) $criteria as $criterion) {
-          if (!empty($criterion) && !is_numeric($criterion)
-            // The first 2 criteria are redundant but are added as they
-            // seem like they would
-            // be quicker than this 3rd check.
-            && max(array_map('ord', str_split($criterion))) >= 240) {
-            // String contains unsupported emojis.
-            // We return a clause that resolves to false as an emoji string by definition cannot be saved.
-            // note that if we return just 0 for false if gets lost in empty checks.
-            // https://stackoverflow.com/questions/16496554/can-php-detect-4-byte-encoded-utf8-chars
-            return '0 = 1';
-          }
-        }
+      $emojiFilter = CRM_Utils_SQL::handleEmojiInQuery($criteria);
+      if ($emojiFilter === '0 = 1') {
+        return $emojiFilter;
       }
 
       if (in_array($operator, self::acceptedSQLOperators(), TRUE)) {
index 3b9167e6265f5301a81023024ff084d4134dbce2..1ca298e96ad37d881c25c64cde4aeed53709bb33 100644 (file)
@@ -203,4 +203,30 @@ class CRM_Utils_SQL {
     return $dsn;
   }
 
+  /**
+   * Filter out Emojis in where clause if the database (determined by checking the create table for civicrm_contact)
+   * cannot support emojis
+   * @param mixed $criteria - filter criteria to check
+   *
+   * @return bool|string
+   */
+  public static function handleEmojiInQuery($criteria) {
+    if (!CRM_Core_BAO_SchemaHandler::databaseSupportsUTF8MB4()) {
+      foreach ((array) $criteria as $criterion) {
+        if (!empty($criterion) && !is_numeric($criterion)
+          // The first 2 criteria are redundant but are added as they
+          // seem like they would
+          // be quicker than this 3rd check.
+          && max(array_map('ord', str_split($criterion))) >= 240) {
+          // String contains unsupported emojis.
+          // We return a clause that resolves to false as an emoji string by definition cannot be saved.
+          // note that if we return just 0 for false if gets lost in empty checks.
+          // https://stackoverflow.com/questions/16496554/can-php-detect-4-byte-encoded-utf8-chars
+          return '0 = 1';
+        }
+      }
+      return TRUE;
+    }
+  }
+
 }
index 79b3e54caf4c4809b26ec9c36064e627d42662dc..6eb0b086247ff0f5932463e130e0bac46ea36ee3 100644 (file)
@@ -5196,11 +5196,27 @@ class api_v3_ContactTest extends CiviUnitTestCase {
    * out when we are.
    */
   public function testEmojiInWhereClause(): void {
+    $schemaNeedsAlter = \CRM_Core_BAO_SchemaHandler::databaseSupportsUTF8MB4();
+    if ($schemaNeedsAlter) {
+      CRM_Core_DAO::executeQuery("
+        ALTER TABLE civicrm_contact MODIFY COLUMN
+        `first_name` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'First Name.',
+        CHARSET utf8 COLLATE utf8_unicode_ci
+      ");
+      Civi::$statics['CRM_Core_BAO_SchemaHandler'] = [];
+    }
     $this->callAPISuccess('Contact', 'get', [
       'debug' => 1,
       'first_name' => '🦉Claire',
-      'version' => 4,
     ]);
+    if ($schemaNeedsAlter) {
+      CRM_Core_DAO::executeQuery("
+        ALTER TABLE civicrm_contact MODIFY COLUMN
+        `first_name` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'First Name.',
+        CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci
+      ");
+      Civi::$statics['CRM_Core_BAO_SchemaHandler'] = [];
+    }
   }
 
   /**
index 8754771ca382140e72fe4b311a4265e4804a4067..2e5075ea03258b8fe1761c44ce011c3cf079c88c 100644 (file)
@@ -117,8 +117,9 @@ class ContactGetTest extends \api\v4\UnitTestCase {
       \CRM_Core_DAO::executeQuery("
         ALTER TABLE civicrm_contact MODIFY COLUMN
         `first_name` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'First Name.',
-        CHARSET utf8
+        CHARSET utf8 COLLATE utf8_unicode_ci
       ");
+      \Civi::$statics['CRM_Core_BAO_SchemaHandler'] = [];
     }
     \Civi::$statics['CRM_Core_BAO_SchemaHandler'] = [];
     Contact::get()
@@ -129,7 +130,7 @@ class ContactGetTest extends \api\v4\UnitTestCase {
       \CRM_Core_DAO::executeQuery("
         ALTER TABLE civicrm_contact MODIFY COLUMN
         `first_name` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'First Name.',
-        CHARSET utf8mb4
+        CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci
       ");
     }
   }