diff --git a/CRM/Core/DAO/CustomField.php b/CRM/Core/DAO/CustomField.php index 137fbf81a247..6cae23bea076 100644 --- a/CRM/Core/DAO/CustomField.php +++ b/CRM/Core/DAO/CustomField.php @@ -6,7 +6,7 @@ * * Generated from xml/schema/CRM/Core/CustomField.xml * DO NOT EDIT. Generated by CRM_Core_CodeGen - * (GenCodeChecksum:200b28277fc9e025b42d3f3e45fde020) + * (GenCodeChecksum:1acb9b3538bd3005b99e6af6d9ec062f) */ /** @@ -227,7 +227,7 @@ class CRM_Core_DAO_CustomField extends CRM_Core_DAO { public $option_group_id; /** - * Serialization method - a non-null value indicates a multi-valued field. + * Serialization method - a non-zero value indicates a multi-valued field. * * @var int */ @@ -688,8 +688,10 @@ public static function &fields() { 'name' => 'serialize', 'type' => CRM_Utils_Type::T_INT, 'title' => ts('Serialize'), - 'description' => ts('Serialization method - a non-null value indicates a multi-valued field.'), + 'description' => ts('Serialization method - a non-zero value indicates a multi-valued field.'), + 'required' => TRUE, 'where' => 'civicrm_custom_field.serialize', + 'default' => '0', 'table_name' => 'civicrm_custom_field', 'entity' => 'CustomField', 'bao' => 'CRM_Core_BAO_CustomField', diff --git a/CRM/Dedupe/Merger.php b/CRM/Dedupe/Merger.php index d8fd267310cd..69827f16192f 100644 --- a/CRM/Dedupe/Merger.php +++ b/CRM/Dedupe/Merger.php @@ -541,6 +541,12 @@ public static function moveContactBelongings($mergeHandler, $tables, $tableOpera continue; } + if ($table === 'civicrm_dashboard_contact') { + $sqls[] = "UPDATE IGNORE civicrm_dashboard_contact SET contact_id = $mainId WHERE contact_id = $otherId"; + $sqls[] = "DELETE FROM civicrm_dashboard_contact WHERE contact_id = $otherId"; + continue; + } + if ($table === 'civicrm_dedupe_exception') { $sqls[] = "UPDATE IGNORE civicrm_dedupe_exception SET contact_id1 = $mainId WHERE contact_id1 = $otherId"; $sqls[] = "UPDATE IGNORE civicrm_dedupe_exception SET contact_id2 = $mainId WHERE contact_id2 = $otherId"; diff --git a/CRM/Upgrade/Incremental/sql/5.29.1.mysql.tpl b/CRM/Upgrade/Incremental/sql/5.29.1.mysql.tpl new file mode 100644 index 000000000000..f51e009f0dc4 --- /dev/null +++ b/CRM/Upgrade/Incremental/sql/5.29.1.mysql.tpl @@ -0,0 +1,7 @@ +{* file to handle db changes in 5.29.1 during upgrade *} + +UPDATE `civicrm_custom_field` SET `serialize` = 0 WHERE `serialize` IS NULL; + +ALTER TABLE `civicrm_custom_field` +CHANGE COLUMN `serialize` +`serialize` int unsigned NOT NULL DEFAULT 0 COMMENT 'Serialization method - a non-zero value indicates a multi-valued field.'; diff --git a/api/v3/CustomField.php b/api/v3/CustomField.php index 1667721744b7..a9b664b0b59a 100644 --- a/api/v3/CustomField.php +++ b/api/v3/CustomField.php @@ -122,18 +122,45 @@ function civicrm_api3_custom_field_delete($params) { * @return array */ function civicrm_api3_custom_field_get($params) { - if (CRM_Core_BAO_Domain::isDBVersionAtLeast('5.27.alpha1') && ($params['legacy_html_type'] ?? TRUE) && !empty($params['return'])) { - if (is_array($params['return'])) { + // Legacy handling for serialize property + $handleLegacy = (($params['legacy_html_type'] ?? !isset($params['serialize'])) && CRM_Core_BAO_Domain::isDBVersionAtLeast('5.27.alpha1')); + if ($handleLegacy && !empty($params['return'])) { + if (!is_array($params['return'])) { + $params['return'] = explode(',', str_replace(' ', '', $params['return'])); + } + if (!in_array('serialize', $params['return'])) { $params['return'][] = 'serialize'; } - elseif (is_string($params['return'])) { - $params['return'] .= ',serialize'; + } + if ($handleLegacy && !empty($params['html_type'])) { + $serializedTypes = ['CheckBox', 'Multi-Select', 'Multi-Select Country', 'Multi-Select State/Province']; + if (is_string($params['html_type'])) { + if (strpos($params['html_type'], 'Multi-Select') === 0) { + $params['html_type'] = str_replace('Multi-Select', 'Select', $params['html_type']); + $params['serialize'] = 1; + } + elseif (!in_array($params['html_type'], $serializedTypes)) { + $params['serialize'] = 0; + } + } + elseif (is_array($params['html_type']) && !empty($params['html_type']['IN'])) { + $excludeNonSerialized = !array_diff($params['html_type']['IN'], $serializedTypes); + $onlyNonSerialized = !array_intersect($params['html_type']['IN'], $serializedTypes); + $params['html_type']['IN'] = array_map(function($val) { + return str_replace('Multi-Select', 'Select', $val); + }, $params['html_type']['IN']); + if ($excludeNonSerialized) { + $params['serialize'] = 1; + } + if ($onlyNonSerialized) { + $params['serialize'] = 0; + } } } $results = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params); - if (($params['legacy_html_type'] ?? TRUE) && !empty($results['values']) && is_array($results['values'])) { + if ($handleLegacy && !empty($results['values']) && is_array($results['values']) && !isset($params['serialize'])) { foreach ($results['values'] as $id => $result) { if (!empty($result['serialize']) && !empty($result['html_type'])) { $results['values'][$id]['html_type'] = str_replace('Select', 'Multi-Select', $result['html_type']); diff --git a/tests/phpunit/CRM/Core/BAO/CustomFieldTest.php b/tests/phpunit/CRM/Core/BAO/CustomFieldTest.php index 42a74c202693..bf3cdf38c8f2 100644 --- a/tests/phpunit/CRM/Core/BAO/CustomFieldTest.php +++ b/tests/phpunit/CRM/Core/BAO/CustomFieldTest.php @@ -481,7 +481,7 @@ public function testGetFieldsForImport() { 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('country'), 'extends_table' => 'civicrm_contact', 'search_table' => 'contact_a', - 'serialize' => NULL, + 'serialize' => 0, 'pseudoconstant' => [ 'table' => 'civicrm_country', 'keyColumn' => 'id', @@ -559,7 +559,7 @@ public function testGetFieldsForImport() { 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.my_file_' . $this->getCustomFieldID('file'), 'extends_table' => 'civicrm_contact', 'search_table' => 'contact_a', - 'serialize' => NULL, + 'serialize' => 0, ], $this->getCustomFieldName('text') => [ 'name' => $this->getCustomFieldName('text'), @@ -593,7 +593,7 @@ public function testGetFieldsForImport() { 'extends_table' => 'civicrm_contact', 'search_table' => 'contact_a', 'maxlength' => 300, - 'serialize' => NULL, + 'serialize' => 0, ], $this->getCustomFieldName('select_string') => [ 'name' => $this->getCustomFieldName('select_string'), @@ -626,7 +626,7 @@ public function testGetFieldsForImport() { 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.pick_color_' . $this->getCustomFieldID('select_string'), 'extends_table' => 'civicrm_contact', 'search_table' => 'contact_a', - 'serialize' => NULL, + 'serialize' => 0, 'pseudoconstant' => [ 'optionGroupName' => $this->callAPISuccessGetValue('CustomField', ['id' => $this->getCustomFieldID('select_string'), 'return' => 'option_group_id.name']), 'optionEditPath' => 'civicrm/admin/options/' . $this->callAPISuccessGetValue('CustomField', ['id' => $this->getCustomFieldID('select_string'), 'return' => 'option_group_id.name']), @@ -663,7 +663,7 @@ public function testGetFieldsForImport() { 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.test_date_' . $this->getCustomFieldID('select_date'), 'extends_table' => 'civicrm_contact', 'search_table' => 'contact_a', - 'serialize' => NULL, + 'serialize' => 0, ], $this->getCustomFieldName('link') => [ 'name' => $this->getCustomFieldName('link'), @@ -696,7 +696,7 @@ public function testGetFieldsForImport() { 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.test_link_' . $this->getCustomFieldID('link'), 'extends_table' => 'civicrm_contact', 'search_table' => 'contact_a', - 'serialize' => NULL, + 'serialize' => 0, ], $this->getCustomFieldName('int') => [ 'name' => $this->getCustomFieldName('int'), @@ -729,7 +729,7 @@ public function testGetFieldsForImport() { 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('int'), 'extends_table' => 'civicrm_contact', 'search_table' => 'contact_a', - 'serialize' => NULL, + 'serialize' => 0, ], $this->getCustomFieldName('contact_reference') => [ 'name' => $this->getCustomFieldName('contact_reference'), @@ -762,7 +762,7 @@ public function testGetFieldsForImport() { 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('contact_reference'), 'extends_table' => 'civicrm_contact', 'search_table' => 'contact_a', - 'serialize' => NULL, + 'serialize' => 0, ], $this->getCustomFieldName('state') => [ 'name' => $this->getCustomFieldName('state'), @@ -788,7 +788,7 @@ public function testGetFieldsForImport() { 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('state'), 'extends_table' => 'civicrm_contact', 'search_table' => 'contact_a', - 'serialize' => NULL, + 'serialize' => 0, 'pseudoconstant' => [ 'table' => 'civicrm_state_province', 'keyColumn' => 'id', @@ -871,7 +871,7 @@ public function testGetFieldsForImport() { 'text_length' => NULL, 'options_per_line' => NULL, 'is_search_range' => '0', - 'serialize' => NULL, + 'serialize' => 0, 'pseudoconstant' => [ 'callback' => 'CRM_Core_SelectValues::boolean', ], diff --git a/tests/phpunit/CRM/Core/BAO/CustomQueryTest.php b/tests/phpunit/CRM/Core/BAO/CustomQueryTest.php index acca0de169bf..d1a103d53297 100644 --- a/tests/phpunit/CRM/Core/BAO/CustomQueryTest.php +++ b/tests/phpunit/CRM/Core/BAO/CustomQueryTest.php @@ -85,7 +85,7 @@ public function testSearchCustomDataDateRelative() { 'type' => 4, 'where' => 'civicrm_value_testsearchcus_' . $ids['custom_group_id'] . '.date_field_' . $dateCustomField['id'], 'import' => 1, - 'serialize' => NULL, + 'serialize' => 0, ], $queryObj->getFieldSpec('custom_' . $dateCustomField['id'])); } diff --git a/tests/phpunit/CRM/Utils/Migrate/fixtures/Activity-text.xml b/tests/phpunit/CRM/Utils/Migrate/fixtures/Activity-text.xml index b678d654d1ad..20a73caf24a8 100644 --- a/tests/phpunit/CRM/Utils/Migrate/fixtures/Activity-text.xml +++ b/tests/phpunit/CRM/Utils/Migrate/fixtures/Activity-text.xml @@ -31,6 +31,7 @@ 1 0 name1_1 + 0 0 example diff --git a/tests/phpunit/CRM/Utils/Migrate/fixtures/ActivityMeeting-text.xml b/tests/phpunit/CRM/Utils/Migrate/fixtures/ActivityMeeting-text.xml index fe8d93eea5e2..58a45e824bd2 100644 --- a/tests/phpunit/CRM/Utils/Migrate/fixtures/ActivityMeeting-text.xml +++ b/tests/phpunit/CRM/Utils/Migrate/fixtures/ActivityMeeting-text.xml @@ -33,6 +33,7 @@ 1 0 name1_1 + 0 0 example diff --git a/tests/phpunit/CRM/Utils/Migrate/fixtures/Contact-text.xml b/tests/phpunit/CRM/Utils/Migrate/fixtures/Contact-text.xml index c6fd51652288..22cb829ad871 100644 --- a/tests/phpunit/CRM/Utils/Migrate/fixtures/Contact-text.xml +++ b/tests/phpunit/CRM/Utils/Migrate/fixtures/Contact-text.xml @@ -31,6 +31,7 @@ 1 0 name1_1 + 0 0 example diff --git a/tests/phpunit/CRM/Utils/Migrate/fixtures/Individual-text.xml b/tests/phpunit/CRM/Utils/Migrate/fixtures/Individual-text.xml index 59768ede169a..ffdd76a9ef9f 100644 --- a/tests/phpunit/CRM/Utils/Migrate/fixtures/Individual-text.xml +++ b/tests/phpunit/CRM/Utils/Migrate/fixtures/Individual-text.xml @@ -31,6 +31,7 @@ 1 0 name1_1 + 0 0 example diff --git a/tests/phpunit/CRM/Utils/Migrate/fixtures/IndividualStudent-text.xml b/tests/phpunit/CRM/Utils/Migrate/fixtures/IndividualStudent-text.xml index 2a367d908e39..6c7e06e69214 100644 --- a/tests/phpunit/CRM/Utils/Migrate/fixtures/IndividualStudent-text.xml +++ b/tests/phpunit/CRM/Utils/Migrate/fixtures/IndividualStudent-text.xml @@ -33,6 +33,7 @@ 1 0 name1_1 + 0 0 example diff --git a/tests/phpunit/api/v3/CustomFieldTest.php b/tests/phpunit/api/v3/CustomFieldTest.php index 5d828378d203..8fc16468a1df 100644 --- a/tests/phpunit/api/v3/CustomFieldTest.php +++ b/tests/phpunit/api/v3/CustomFieldTest.php @@ -618,4 +618,64 @@ public function testDisableSearchableContactReferenceField() { $this->callAPISuccess('CustomField', 'create', $params); } + public function testLegacyHtmlType() { + $customGroup = $this->customGroupCreate([ + 'name' => 'testCustomGroup', + 'title' => 'testCustomGroup', + 'extends' => 'Individual', + ]); + $f1 = $this->callAPISuccess('CustomField', 'create', [ + 'label' => 'SingleSelect', + 'custom_group_id' => 'testCustomGroup', + 'data_type' => 'String', + 'html_type' => 'Select', + 'option_values' => [1 => 'One', 2 => 'Two'], + ]); + $f2 = $this->callAPISuccess('CustomField', 'create', [ + 'label' => 'CheckBoxes', + 'custom_group_id' => 'testCustomGroup', + 'data_type' => 'String', + 'html_type' => 'CheckBox', + 'option_values' => [1 => 'One', 2 => 'Two'], + ]); + $f3 = $this->callAPISuccess('CustomField', 'create', [ + 'label' => 'MultiSelect', + 'custom_group_id' => 'testCustomGroup', + 'data_type' => 'String', + 'html_type' => 'Multi-Select', + 'option_values' => [1 => 'One', 2 => 'Two'], + ]); + + $result = $this->callAPISuccess('CustomField', 'get', [ + 'custom_group_id' => 'testCustomGroup', + 'html_type' => 'Multi-Select', + 'sequential' => 1, + ]); + $this->assertCount(1, $result['values']); + $this->assertEquals('MultiSelect', $result['values'][0]['label']); + + $result = $this->callAPISuccess('CustomField', 'get', [ + 'custom_group_id' => 'testCustomGroup', + 'html_type' => ['IN' => ['Multi-Select', 'CheckBox']], + 'sequential' => 1, + ]); + $this->assertCount(2, $result['values']); + + $result = $this->callAPISuccess('CustomField', 'get', [ + 'custom_group_id' => 'testCustomGroup', + 'html_type' => 'Select', + 'sequential' => 1, + ]); + $this->assertCount(1, $result['values']); + $this->assertEquals('SingleSelect', $result['values'][0]['label']); + + $result = $this->callAPISuccess('CustomField', 'get', [ + 'custom_group_id' => 'testCustomGroup', + 'html_type' => ['IN' => ['Select']], + 'sequential' => 1, + ]); + $this->assertCount(1, $result['values']); + $this->assertEquals('SingleSelect', $result['values'][0]['label']); + } + } diff --git a/tests/phpunit/api/v4/Action/CustomValueTest.php b/tests/phpunit/api/v4/Action/CustomValueTest.php index 81edd46e2a7f..0b39e2617314 100644 --- a/tests/phpunit/api/v4/Action/CustomValueTest.php +++ b/tests/phpunit/api/v4/Action/CustomValueTest.php @@ -89,7 +89,7 @@ public function testCRUD() { 'entity' => "Custom_$group", 'data_type' => 'String', 'fk_entity' => NULL, - 'serialize' => NULL, + 'serialize' => 0, 'options' => $optionValues, ], [ @@ -109,7 +109,7 @@ public function testCRUD() { 'entity' => "Custom_$group", 'data_type' => 'String', 'fk_entity' => NULL, - 'serialize' => NULL, + 'serialize' => 0, ], [ 'name' => 'id', diff --git a/xml/schema/Core/CustomField.xml b/xml/schema/Core/CustomField.xml index 8d49adce76d0..44c632256010 100644 --- a/xml/schema/Core/CustomField.xml +++ b/xml/schema/Core/CustomField.xml @@ -278,11 +278,13 @@ int unsigned Serialize 255 - Serialization method - a non-null value indicates a multi-valued field. + Serialization method - a non-zero value indicates a multi-valued field. CRM_Core_SelectValues::fieldSerialization 5.27 + true + 0 filter