Skip to content

Commit

Permalink
Merge pull request #21001 from seamuslee001/fix_utf8mb4_test
Browse files Browse the repository at this point in the history
[REF] Fix utf8mb4 test in APIv4 and re-enable the altering of databas…
  • Loading branch information
seamuslee001 authored Aug 7, 2021
2 parents 1f9a5b0 + 9787e1b commit 586db1c
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 18 deletions.
5 changes: 4 additions & 1 deletion CRM/Contact/BAO/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -5668,7 +5668,10 @@ public static function buildClause($field, $op, $value = NULL, $dataType = NULL)
}
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') {
Expand Down
17 changes: 3 additions & 14 deletions CRM/Core/DAO.php
Original file line number Diff line number Diff line change
Expand Up @@ -2881,20 +2881,9 @@ public function getFieldSpec($fieldName) {
*/
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)) {
Expand Down
26 changes: 26 additions & 0 deletions CRM/Utils/SQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,4 +203,30 @@ public static function autoSwitchDSN($dsn) {
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;
}
}

}
18 changes: 17 additions & 1 deletion tests/phpunit/api/v3/ContactTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5196,11 +5196,27 @@ protected function doMerge(bool $isReverse = FALSE) {
* 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'] = [];
}
}

/**
Expand Down
5 changes: 3 additions & 2 deletions tests/phpunit/api/v4/Action/ContactGetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ public function testEmoji(): void {
\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()
Expand All @@ -129,7 +130,7 @@ public function testEmoji(): void {
\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
");
}
}
Expand Down

0 comments on commit 586db1c

Please sign in to comment.