From a5248828b461cdaf3bc8782795a580b467679faf Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Wed, 19 Oct 2022 10:18:51 -0400 Subject: [PATCH] Ensure value for PriceSet.extends is correctly serialized --- CRM/Core/DAO.php | 7 +++ CRM/Price/BAO/PriceSet.php | 47 +++++++------------ .../Incremental/sql/5.56.alpha1.mysql.tpl | 2 +- .../Incremental/sql/5.62.alpha1.mysql.tpl | 4 ++ tests/phpunit/CiviTest/CiviUnitTestCase.php | 2 +- tests/phpunit/api/v3/PriceSetTest.php | 2 +- xml/templates/civicrm_data.tpl | 6 +-- xml/templates/civicrm_sample.tpl | 10 ++-- 8 files changed, 39 insertions(+), 41 deletions(-) diff --git a/CRM/Core/DAO.php b/CRM/Core/DAO.php index 46a9026eaf..ead9a4f451 100644 --- a/CRM/Core/DAO.php +++ b/CRM/Core/DAO.php @@ -783,6 +783,13 @@ class CRM_Core_DAO extends DB_DataObject { $this->$dbName = CRM_Core_DAO::serializeField($value, $field['serialize']); $allNull = FALSE; } + // When a single value was entered for a serialized field, it's probably due to sloppy coding. + // Folks, always use an array to pass in values for fields containing array data. + // Meanwhile, I'll convert it for you. You're welcome. + elseif (is_numeric($value) && !empty($field['serialize'])) { + $this->$dbName = CRM_Core_DAO::serializeField((array) $value, $field['serialize']); + $allNull = FALSE; + } else { $maxLength = $field['maxlength'] ?? NULL; if (!is_array($value) && $maxLength && mb_strlen($value ?? '') > $maxLength && empty($field['pseudoconstant'])) { diff --git a/CRM/Price/BAO/PriceSet.php b/CRM/Price/BAO/PriceSet.php index 15570a7787..e263fdf3de 100644 --- a/CRM/Price/BAO/PriceSet.php +++ b/CRM/Price/BAO/PriceSet.php @@ -19,7 +19,7 @@ * Business object for managing price sets. * */ -class CRM_Price_BAO_PriceSet extends CRM_Price_DAO_PriceSet { +class CRM_Price_BAO_PriceSet extends CRM_Price_DAO_PriceSet implements \Civi\Core\HookInterface { /** * Static field for default price set details. @@ -31,41 +31,28 @@ class CRM_Price_BAO_PriceSet extends CRM_Price_DAO_PriceSet { /** * Takes an associative array and creates a price set object. * + * @deprecated + * Use writeRecord + * * @param array $params - * (reference) an assoc array of name/value pairs. * - * @return CRM_Price_DAO_PriceSet + * @return CRM_Price_BAO_PriceSet */ - public static function create(&$params) { - $hook = empty($params['id']) ? 'create' : 'edit'; - CRM_Utils_Hook::pre($hook, 'PriceSet', CRM_Utils_Array::value('id', $params), $params); - - if (empty($params['id']) && empty($params['name'])) { - $params['name'] = CRM_Utils_String::munge($params['title'], '_', 242); - } - $priceSetID = NULL; - $validatePriceSet = TRUE; - if (!empty($params['extends']) && is_array($params['extends'])) { - if (!array_key_exists(CRM_Core_Component::getComponentID('CiviEvent'), $params['extends']) - || !array_key_exists(CRM_Core_Component::getComponentID('CiviMember'), $params['extends']) - ) { - $validatePriceSet = FALSE; + public static function create($params) { + return self::writeRecord($params); + } + + /** + * Event fired before an action is taken on an ACL record. + * @param \Civi\Core\Event\PreEvent $event + */ + public static function self_hook_civicrm_pre(\Civi\Core\Event\PreEvent $event) { + if ($event->action === 'create' || $event->action === 'edit') { + if (self::eventPriceSetDomainID()) { + $event->params['domain_id'] = CRM_Core_Config::domainID(); } - $params['extends'] = CRM_Utils_Array::implodePadded($params['extends']); - } - else { - $priceSetID = $params['id'] ?? NULL; } - $priceSetBAO = new CRM_Price_BAO_PriceSet(); - $priceSetBAO->copyValues($params); - if (self::eventPriceSetDomainID()) { - $priceSetBAO->domain_id = CRM_Core_Config::domainID(); - } - $priceSetBAO->save(); - - CRM_Utils_Hook::post($hook, 'PriceSet', $priceSetBAO->id, $priceSetBAO); unset(\Civi::$statics['CRM_Core_PseudoConstant']); - return $priceSetBAO; } /** diff --git a/CRM/Upgrade/Incremental/sql/5.56.alpha1.mysql.tpl b/CRM/Upgrade/Incremental/sql/5.56.alpha1.mysql.tpl index 4fc320d501..bb201441f6 100644 --- a/CRM/Upgrade/Incremental/sql/5.56.alpha1.mysql.tpl +++ b/CRM/Upgrade/Incremental/sql/5.56.alpha1.mysql.tpl @@ -46,4 +46,4 @@ UPDATE civicrm_preferences_date SET description = '{ts escape="sql"}Date for rel UPDATE civicrm_preferences_date SET description = '{ts escape="sql"}Used in search forms.{/ts}' WHERE civicrm_preferences_date.name = 'searchDate'; -- dev/core#3926 Need to increase data size for 'url' column on 'civicrm_website' table -ALTER TABLE civicrm_website CHANGE url url VARCHAR( 255 ); \ No newline at end of file +ALTER TABLE civicrm_website CHANGE url url VARCHAR( 255 ); diff --git a/CRM/Upgrade/Incremental/sql/5.62.alpha1.mysql.tpl b/CRM/Upgrade/Incremental/sql/5.62.alpha1.mysql.tpl index 97d48e8774..9981a2bae8 100644 --- a/CRM/Upgrade/Incremental/sql/5.62.alpha1.mysql.tpl +++ b/CRM/Upgrade/Incremental/sql/5.62.alpha1.mysql.tpl @@ -1,5 +1,9 @@ {* file to handle db changes in 5.62.alpha1 during upgrade *} +-- Ensure all PriceSet.extends values are properly serialized +UPDATE `civicrm_price_set` SET `extends` = CONCAT("", `extends`, "") +WHERE `extends` IS NOT NULL AND `extends` != '' AND `extends` NOT LIKE "%"; + {* https://github.com/civicrm/civicrm-core/pull/26055 *} UPDATE civicrm_mapping SET name = CONCAT('mapping_', id) WHERE name IS NULL; UPDATE civicrm_mapping m1, civicrm_mapping m2 diff --git a/tests/phpunit/CiviTest/CiviUnitTestCase.php b/tests/phpunit/CiviTest/CiviUnitTestCase.php index 134f358080..5166fb7d1e 100644 --- a/tests/phpunit/CiviTest/CiviUnitTestCase.php +++ b/tests/phpunit/CiviTest/CiviUnitTestCase.php @@ -1948,7 +1948,7 @@ class CiviUnitTestCase extends PHPUnit\Framework\TestCase { $value = date('Y-m-d H:i:s', strtotime($value)); $result[$keys[$key]] = date('Y-m-d H:i:s', strtotime(CRM_Utils_Array::value($keys[$key], $result, CRM_Utils_Array::value($key, $result)))); } - $this->assertEquals($value, $result[$keys[$key]], $key . " GetandCheck function determines that for key {$key} value: $value doesn't match " . print_r($result[$keys[$key]], TRUE) . $errorText); + $this->assertEquals($value, $result[$keys[$key]], $key . " GetandCheck function determines that for key {$key} value: " . print_r($value, TRUE) . " doesn't match " . print_r($result[$keys[$key]], TRUE) . $errorText); } } diff --git a/tests/phpunit/api/v3/PriceSetTest.php b/tests/phpunit/api/v3/PriceSetTest.php index 1eb8dd58ad..734fdcbb87 100644 --- a/tests/phpunit/api/v3/PriceSetTest.php +++ b/tests/phpunit/api/v3/PriceSetTest.php @@ -31,7 +31,7 @@ class api_v3_PriceSetTest extends CiviUnitTestCase { 'is_active' => 1, 'help_pre' => "Please describe your goat in detail", 'help_post' => "thank you for your time", - 'extends' => 2, + 'extends' => [2], 'financial_type_id' => 1, 'is_quick_config' => 1, 'is_reserved' => 1, diff --git a/xml/templates/civicrm_data.tpl b/xml/templates/civicrm_data.tpl index f9c0e0c2e1..a9020076ba 100644 --- a/xml/templates/civicrm_data.tpl +++ b/xml/templates/civicrm_data.tpl @@ -1755,10 +1755,10 @@ VALUES -- CRM-9714 INSERT INTO `civicrm_price_set` ( `name`, `title`, `is_active`, `extends`, `is_quick_config`, `financial_type_id`, `is_reserved` ) -VALUES ( 'default_contribution_amount', 'Contribution Amount', '1', '2', '1', NULL,1), -( 'default_membership_type_amount', 'Membership Amount', '1', '3', '1', @financial_type_id_md,1); +VALUES ( 'default_contribution_amount', 'Contribution Amount', '1', '2', '1', NULL, 1), +( 'default_membership_type_amount', 'Membership Amount', '1', '3', '1', @financial_type_id_md, 1); -SELECT @setID := max(id) FROM civicrm_price_set WHERE name = 'default_contribution_amount' AND extends = 2 AND is_quick_config = 1 ; +SELECT @setID := max(id) FROM civicrm_price_set WHERE name = 'default_contribution_amount' AND is_quick_config = 1; INSERT INTO `civicrm_price_field` (`price_set_id`, `name`, `label`, `html_type`,`weight`, `is_display_amounts`, `options_per_line`, `is_active`, `is_required`,`visibility_id` ) VALUES ( @setID, 'contribution_amount', 'Contribution Amount', 'Text', '1', '1', '1', '1', '1', '1' ); diff --git a/xml/templates/civicrm_sample.tpl b/xml/templates/civicrm_sample.tpl index a7d647bb99..266052884f 100644 --- a/xml/templates/civicrm_sample.tpl +++ b/xml/templates/civicrm_sample.tpl @@ -15,7 +15,7 @@ SELECT @domainID := id FROM civicrm_domain where name = 'Default Domain Name'; -- Sample Extended Property Group and Fields INSERT INTO `civicrm_price_set` (`name`,`title`,`is_active`,`extends`,`is_quick_config`, `financial_type_id`) -VALUES ('help_support_civicrm_amount', 'Help Support CiviCRM!', 1, 2, 0, 1); +VALUES ('help_support_civicrm_amount', 'Help Support CiviCRM!', 1, '2', 0, 1); SELECT @priceSetId := max(id) FROM `civicrm_price_set` WHERE name = 'help_support_civicrm_amount'; @@ -141,7 +141,7 @@ SELECT @priceFieldId, LOWER(name), name, description, minimum_fee, id as weight, INSERT INTO `civicrm_price_set` (`name`,`title`,`is_active`,`extends`, `financial_type_id`, `is_quick_config`) -VALUES ('member_signup_and_renewal', 'Member Signup and Renewal', 1, 3, @financial_type_id, 1), +VALUES ('member_signup_and_renewal', 'Member Signup and Renewal', 1, '3', @financial_type_id, 1), ('pledge_for_civicrm', 'Pledge for CiviCRM!',1,2,null,1); SELECT @priceSetId := max(id) FROM `civicrm_price_set` WHERE name = 'member_signup_and_renewal'; @@ -181,9 +181,9 @@ VALUES -- Insert sample data for event INSERT INTO `civicrm_price_set` (`name`,`title`,`is_active`,`extends`, `is_quick_config`, `financial_type_id`) -VALUES ('rain_forest_cup_youth_soccer_tournament', 'Rain-forest Cup Youth Soccer Tournament', 1, 1, 1,3), - ('fall_fundraiser_dinner', 'Fall Fundraiser Dinner', 1, 1, 1,3), - ('summer_solstice_festival_day_concert', 'Summer Solstice Festival Day Concert',1,1,0,3); +VALUES ('rain_forest_cup_youth_soccer_tournament', 'Rain-forest Cup Youth Soccer Tournament', 1, '1', 1, 3), + ('fall_fundraiser_dinner', 'Fall Fundraiser Dinner', 1, '1', 1, 3), + ('summer_solstice_festival_day_concert', 'Summer Solstice Festival Day Concert', 1, '1', 0, 3); SELECT @priceSetId := max(id) FROM `civicrm_price_set` WHERE `name` = 'rain_forest_cup_youth_soccer_tournament'; -- 2.25.1