Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dev/core#2164 Exporting in localized civicrm crashes due to long translations in columns T_Boolean #19957

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
8fccc8a
Expose mapping search task to Search Kit
seamuslee001 Feb 8, 2021
53480c5
[REF] [Towards membership api] more consistent handling on amount
eileenmcnaughton Mar 26, 2021
633d512
dev/wordpress#82 Add support for creating WordPress accounts from the…
mlutfy Nov 16, 2020
9e582c5
[REF] Extract getMembershipTypeValues
eileenmcnaughton Mar 26, 2021
fc2e199
dev/core#527 use public title for on behalf profile and confirm/thank…
samuelsov Mar 29, 2021
7652b05
trigger an error if non-numeric
demeritcowboy Mar 29, 2021
e908d4a
[REF] Minor cleanup
eileenmcnaughton Mar 31, 2021
a9ade36
dev/core#2498 Fix regression on saving dedupe rules
eileenmcnaughton Mar 31, 2021
c64b189
Donot over-ride total amount incase contribution has more than one li…
pradpnayak Mar 31, 2021
df43ca0
Adding test to support fix
pradpnayak Mar 31, 2021
a5e9dbe
[REF] Move function from static class to OO class
eileenmcnaughton Mar 31, 2021
8fbbfea
Merge pull request #19952 from eileenmcnaughton/5.36
monishdeb Mar 31, 2021
31c5844
extending the @wannesderoy patch from https://github.com/civicrm/civi…
bjendres Mar 31, 2021
df7cc14
adjusting unit tests
bjendres Mar 31, 2021
8e88fa0
Merge pull request #19956 from civicrm/5.36
eileenmcnaughton Mar 31, 2021
f0cf4ce
Merge pull request #19924 from eileenmcnaughton/mem_ex
monishdeb Mar 31, 2021
db43311
integers are affected as well
bjendres Mar 31, 2021
0f608ae
adjusting unit tests
bjendres Mar 31, 2021
f9044d4
don't try to money_format html
demeritcowboy Mar 31, 2021
da4aa95
Merge pull request #19955 from eileenmcnaughton/merge_locations
colemanw Mar 31, 2021
6b04b7e
dev/core#527 simpler solution
samuelsov Mar 31, 2021
88ecb42
Merge pull request #19561 from seamuslee001/search_task_map
eileenmcnaughton Mar 31, 2021
c6d5e7a
Merge pull request #19958 from demeritcowboy/htmlmoney
eileenmcnaughton Mar 31, 2021
d67ca01
Merge pull request #19951 from pradpnayak/fixgetlineitem
eileenmcnaughton Mar 31, 2021
0278c62
Merge pull request #19937 from samuelsov/core#527
eileenmcnaughton Mar 31, 2021
9e81577
Merge pull request #19938 from demeritcowboy/php74-money
seamuslee001 Mar 31, 2021
788b304
Merge pull request #19911 from eileenmcnaughton/new
monishdeb Apr 1, 2021
aaaabd3
Merge pull request #19949 from eileenmcnaughton/dedupe
seamuslee001 Apr 1, 2021
74cdcad
adjusting unit tests
bjendres Apr 1, 2021
55bf40f
Fix for dev/core#2503
jaapjansma Apr 1, 2021
6517979
Merge pull request #19962 from jaapjansma/dev_2503
eileenmcnaughton Apr 1, 2021
78ed520
Merge pull request #18982 from mlutfy/wp82
mlutfy Apr 2, 2021
4ade2ea
extending the @wannesderoy patch from https://github.com/civicrm/civi…
bjendres Mar 31, 2021
7138889
Merge remote-tracking branch 'origin/issue/2164' into issue/2164
bjendres Apr 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CRM/Contact/Form/DedupeRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,11 @@ public static function formRule($fields, $files, $self) {
for ($count = 0; $count < self::RULES_COUNT; $count++) {
if (!empty($fields["where_$count"]) || (isset($self->_defaults['is_reserved']) && !empty($self->_defaults["where_$count"]))) {
$fieldSelected = TRUE;
if (!empty($fields["weight_$count"])) {
$actualThreshold += $fields["weight_$count"];
}
break;
}
if (!empty($self->_defaults["weight_$count"])) {
$actualThreshold += $self->_defaults["weight_$count"];
}
}
if (empty($fields['threshold'])) {
// CRM-20607 - Don't validate the threshold of hard-coded rules
Expand Down
2 changes: 1 addition & 1 deletion CRM/Contact/Form/Task.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public static function preProcessCommon(&$form) {
$form->_contactIds = [];
$form->_contactTypes = [];

$isStandAlone = in_array('task', $form->urlPath) || in_array('standalone', $form->urlPath);
$isStandAlone = in_array('task', $form->urlPath) || in_array('standalone', $form->urlPath) || in_array('map', $form->urlPath);
if ($isStandAlone) {
[$form->_task, $title] = CRM_Contact_Task::getTaskAndTitleByClass(get_class($form));
if (!array_key_exists($form->_task, CRM_Contact_Task::permissionedTaskTitles(CRM_Core_Permission::getPermission()))) {
Expand Down
14 changes: 10 additions & 4 deletions CRM/Contact/Form/Task/Useradd.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,20 @@ public function setDefaultValues() {
* Build the form object.
*/
public function buildQuickForm() {
$config = CRM_Core_Config::singleton();

$element = $this->add('text', 'name', ts('Full Name'), ['class' => 'huge']);
$element->freeze();
$this->add('text', 'cms_name', ts('Username'), ['class' => 'huge']);
$this->addRule('cms_name', 'Username is required', 'required');
$this->add('password', 'cms_pass', ts('Password'), ['class' => 'huge']);
$this->add('password', 'cms_confirm_pass', ts('Confirm Password'), ['class' => 'huge']);
$this->addRule('cms_pass', 'Password is required', 'required');
$this->addRule(['cms_pass', 'cms_confirm_pass'], 'ERROR: Password mismatch', 'compare');

if (!$config->userSystem->isUserRegistrationPermitted()) {
$this->add('password', 'cms_pass', ts('Password'), ['class' => 'huge']);
$this->add('password', 'cms_confirm_pass', ts('Confirm Password'), ['class' => 'huge']);
$this->addRule('cms_pass', 'Password is required', 'required');
$this->addRule(['cms_pass', 'cms_confirm_pass'], 'ERROR: Password mismatch', 'compare');
}

$this->add('text', 'email', ts('Email:'), ['class' => 'huge'])->freeze();
$this->addRule('email', 'Email is required', 'required');
$this->add('hidden', 'contactID');
Expand Down
2 changes: 2 additions & 0 deletions CRM/Contact/Task.php
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ public static function tasks() {
'title' => ts('Map contacts'),
'class' => 'CRM_Contact_Form_Task_Map',
'result' => FALSE,
'url' => 'civicrm/contact/map',
'icon' => 'fa-map',
);
}

Expand Down
2 changes: 1 addition & 1 deletion CRM/Contribute/BAO/ContributionPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ protected static function getProfileNameAndFields($gid, $cid, $params, $fieldTyp
$fields = CRM_Core_BAO_UFGroup::getFields($gid, FALSE, CRM_Core_Action::VIEW, NULL, NULL, FALSE, NULL, FALSE, NULL, CRM_Core_Permission::CREATE, NULL);
foreach ($fields as $k => $v) {
if (!$groupTitle) {
$groupTitle = $v['groupTitle'];
$groupTitle = $v['groupDisplayTitle'];
}
// suppress all file fields from display and formatting fields
if (
Expand Down
109 changes: 109 additions & 0 deletions CRM/Dedupe/MergeHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -359,4 +359,113 @@ protected function getSelectedType($entity, $blockIndex) {
return $this->getMigrationInfo()['location_blocks'][$entity][$blockIndex]['typeTypeId'] ?? NULL;
}

/**
* Merge location.
*
* Based on the data in the $locationMigrationInfo merge the locations for 2 contacts.
*
* The data is in the format received from the merge form (which is a fairly confusing format).
*
* It is converted into an array of DAOs which is passed to the alterLocationMergeData hook
* before saving or deleting the DAOs. A new hook is added to allow these to be altered after they have
* been calculated and before saving because
* - the existing format & hook combo is so confusing it is hard for developers to change & inherently fragile
* - passing to a hook right before save means calculations only have to be done once
* - the existing pattern of passing dissimilar data to the same (merge) hook with a different 'type' is just
* ugly.
*
* The use of the new hook is tested, including the fact it is called before contributions are merged, as this
* is likely to be significant data in merge hooks.
*
* @throws \CRM_Core_Exception
*/
public function mergeLocations(): void {
$mergeHandler = $this;
$locBlocks = $mergeHandler->getLocationBlocksToMerge();
$blocksDAO = [];
$migrationInfo = $mergeHandler->getMigrationInfo();

// @todo Handle OpenID (not currently in API).
if (!empty($locBlocks)) {
$locationBlocks = CRM_Dedupe_Merger::getLocationBlockInfo();

$primaryBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($mergeHandler->getToKeepID(), ['is_primary' => 1]);
$billingBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($mergeHandler->getToKeepID(), ['is_billing' => 1]);

foreach ($locBlocks as $name => $block) {
$blocksDAO[$name] = ['delete' => [], 'update' => []];
$daoName = 'CRM_Core_DAO_' . $locationBlocks[$name]['label'];
$changePrimary = FALSE;
$primaryDAOId = (array_key_exists($name, $primaryBlockIds)) ? array_pop($primaryBlockIds[$name]) : NULL;
$billingDAOId = (array_key_exists($name, $billingBlockIds)) ? array_pop($billingBlockIds[$name]) : NULL;

foreach ($block as $blkCount => $values) {
$otherBlockId = $migrationInfo['other_details']['location_blocks'][$name][$blkCount]['id'] ?? NULL;
$mainBlockId = CRM_Utils_Array::value('mainContactBlockId', $migrationInfo['location_blocks'][$name][$blkCount], 0);
if (!$otherBlockId) {
continue;
}
$otherBlockDAO = $mergeHandler->copyDataToNewBlockDAO($otherBlockId, $name, $blkCount);

// If we're deliberately setting this as primary then add the flag
// and remove it from the current primary location (if there is one).
// But only once for each entity.
$set_primary = $migrationInfo['location_blocks'][$name][$blkCount]['set_other_primary'] ?? NULL;
if (!$changePrimary && $set_primary == "1") {
$otherBlockDAO->is_primary = 1;
if ($primaryDAOId) {
$removePrimaryDAO = $mergeHandler->getDAOForLocationEntity($name);
$removePrimaryDAO->id = $primaryDAOId;
$removePrimaryDAO->is_primary = 0;
$blocksDAO[$name]['update'][$primaryDAOId] = $removePrimaryDAO;
}
$changePrimary = TRUE;
}
// Otherwise, if main contact already has primary, set it to 0.
elseif ($primaryDAOId) {
$otherBlockDAO->is_primary = 0;
}

// If the main contact already has a billing location, set this to 0.
if ($billingDAOId) {
$otherBlockDAO->is_billing = 0;
}

// overwrite - need to delete block which belongs to main-contact.
if (!empty($mainBlockId) && $values['is_replace']) {
$deleteDAO = $mergeHandler->getDAOForLocationEntity($name);
$deleteDAO->id = $mainBlockId;
$deleteDAO->find(TRUE);

// if we about to delete a primary / billing block, set the flags for new block
// that we going to assign to main-contact
if ($primaryDAOId && ($primaryDAOId == $deleteDAO->id)) {
$otherBlockDAO->is_primary = 1;
}
if ($billingDAOId && ($billingDAOId == $deleteDAO->id)) {
$otherBlockDAO->is_billing = 1;
}
$blocksDAO[$name]['delete'][$deleteDAO->id] = $deleteDAO;
}
$blocksDAO[$name]['update'][$otherBlockDAO->id] = $otherBlockDAO;
}
$blocksDAO[$name]['update'] += $mergeHandler->getBlocksToUpdateForDeletedContact($name);
}
}

CRM_Utils_Hook::alterLocationMergeData($blocksDAO, $mergeHandler->getToKeepID(), $mergeHandler->getToRemoveID(), $migrationInfo);
foreach ($blocksDAO as $blockDAOs) {
if (!empty($blockDAOs['update'])) {
foreach ($blockDAOs['update'] as $blockDAO) {
$blockDAO->save();
}
}
if (!empty($blockDAOs['delete'])) {
foreach ($blockDAOs['delete'] as $blockDAO) {
$blockDAO->delete();
}
}
}
}

}
124 changes: 8 additions & 116 deletions CRM/Dedupe/Merger.php
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ protected static function createContact($contactID, $params) {
// This parameter causes blank fields to be be emptied out.
// We can probably remove.
$params['updateBlankLocInfo'] = TRUE;
list($data) = CRM_Contact_BAO_Contact::formatProfileContactParams($params, [], $contactID);
[$data] = CRM_Contact_BAO_Contact::formatProfileContactParams($params, [], $contactID);
CRM_Contact_BAO_Contact::create($data);
}

Expand Down Expand Up @@ -994,7 +994,7 @@ public static function merge($dupePairs = [], $cacheParams = [], $mode = 'safe',
*/
public static function skipMerge($mainId, $otherId, &$migrationInfo, $mode = 'safe', &$conflicts = []) {

$conflicts = self::getConflicts($migrationInfo, $mainId, $otherId, $mode)['conflicts'];
$conflicts = self::getConflicts($migrationInfo, (int) $mainId, (int) $otherId, $mode)['conflicts'];
// A hook could have set skip_merge in order to alter merge behaviour.
// This is a something we might ideally deprecate since they really 'should'
// mess with the conflicts array instead.
Expand Down Expand Up @@ -1209,7 +1209,7 @@ public static function getRowsElementsAndInfo($mainId, $otherId, $checkPermissio
$locations = ['main' => [], 'other' => []];

foreach ($locationBlocks as $blockName => $blockInfo) {
list($locations, $rows, $elements, $migrationInfo) = self::addLocationFieldInfo($mainId, $otherId, $blockInfo, $blockName, $locations, $rows, $elements, $migrationInfo);
[$locations, $rows, $elements, $migrationInfo] = self::addLocationFieldInfo($mainId, $otherId, $blockInfo, $blockName, $locations, $rows, $elements, $migrationInfo);
} // End loop through each location block entity

// add the related tables and unset the ones that don't sport any of the duplicate contact's info
Expand Down Expand Up @@ -1374,7 +1374,7 @@ public static function moveAllBelongings($mainId, $otherId, $migrationInfo, $che
}
$mergeHandler = new CRM_Dedupe_MergeHandler((int) $mainId, (int) $otherId);
$mergeHandler->setMigrationInfo($migrationInfo);
self::mergeLocations($mergeHandler);
$mergeHandler->mergeLocations();

// **** Do contact related migrations
// @todo - move all custom field processing to the move class & eventually have an
Expand Down Expand Up @@ -1427,7 +1427,7 @@ public static function moveAllBelongings($mainId, $otherId, $migrationInfo, $che
$submitted = [];
}
foreach ($submitted as $key => $value) {
list($cFields, $submitted) = self::processCustomFields($mainId, $key, $cFields, $submitted, $value);
[$cFields, $submitted] = self::processCustomFields($mainId, $key, $cFields, $submitted, $value);
}

// move view only custom fields CRM-5362
Expand Down Expand Up @@ -1743,114 +1743,6 @@ public static function getMergeContactDetails($contact_id) {
return $result['values'][$contact_id];
}

/**
* Merge location.
*
* Based on the data in the $locationMigrationInfo merge the locations for 2 contacts.
*
* The data is in the format received from the merge form (which is a fairly confusing format).
*
* It is converted into an array of DAOs which is passed to the alterLocationMergeData hook
* before saving or deleting the DAOs. A new hook is added to allow these to be altered after they have
* been calculated and before saving because
* - the existing format & hook combo is so confusing it is hard for developers to change & inherently fragile
* - passing to a hook right before save means calculations only have to be done once
* - the existing pattern of passing dissimilar data to the same (merge) hook with a different 'type' is just
* ugly.
*
* The use of the new hook is tested, including the fact it is called before contributions are merged, as this
* is likely to be significant data in merge hooks.
*
* @param \CRM_Dedupe_MergeHandler $mergeHandler
*/
public static function mergeLocations($mergeHandler) {
$locBlocks = $mergeHandler->getLocationBlocksToMerge();
$blocksDAO = [];
$migrationInfo = $mergeHandler->getMigrationInfo();

// @todo Handle OpenID (not currently in API).
if (!empty($locBlocks)) {
$locationBlocks = self::getLocationBlockInfo();

$primaryBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($mergeHandler->getToKeepID(), ['is_primary' => 1]);
$billingBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($mergeHandler->getToKeepID(), ['is_billing' => 1]);

foreach ($locBlocks as $name => $block) {
$blocksDAO[$name] = ['delete' => [], 'update' => []];
$daoName = 'CRM_Core_DAO_' . $locationBlocks[$name]['label'];
$changePrimary = FALSE;
$primaryDAOId = (array_key_exists($name, $primaryBlockIds)) ? array_pop($primaryBlockIds[$name]) : NULL;
$billingDAOId = (array_key_exists($name, $billingBlockIds)) ? array_pop($billingBlockIds[$name]) : NULL;

foreach ($block as $blkCount => $values) {
$otherBlockId = $migrationInfo['other_details']['location_blocks'][$name][$blkCount]['id'] ?? NULL;
$mainBlockId = CRM_Utils_Array::value('mainContactBlockId', $migrationInfo['location_blocks'][$name][$blkCount], 0);
if (!$otherBlockId) {
continue;
}
$otherBlockDAO = $mergeHandler->copyDataToNewBlockDAO($otherBlockId, $name, $blkCount);

// If we're deliberately setting this as primary then add the flag
// and remove it from the current primary location (if there is one).
// But only once for each entity.
$set_primary = $migrationInfo['location_blocks'][$name][$blkCount]['set_other_primary'] ?? NULL;
if (!$changePrimary && $set_primary == "1") {
$otherBlockDAO->is_primary = 1;
if ($primaryDAOId) {
$removePrimaryDAO = $mergeHandler->getDAOForLocationEntity($name);
$removePrimaryDAO->id = $primaryDAOId;
$removePrimaryDAO->is_primary = 0;
$blocksDAO[$name]['update'][$primaryDAOId] = $removePrimaryDAO;
}
$changePrimary = TRUE;
}
// Otherwise, if main contact already has primary, set it to 0.
elseif ($primaryDAOId) {
$otherBlockDAO->is_primary = 0;
}

// If the main contact already has a billing location, set this to 0.
if ($billingDAOId) {
$otherBlockDAO->is_billing = 0;
}

// overwrite - need to delete block which belongs to main-contact.
if (!empty($mainBlockId) && $values['is_replace']) {
$deleteDAO = $mergeHandler->getDAOForLocationEntity($name);
$deleteDAO->id = $mainBlockId;
$deleteDAO->find(TRUE);

// if we about to delete a primary / billing block, set the flags for new block
// that we going to assign to main-contact
if ($primaryDAOId && ($primaryDAOId == $deleteDAO->id)) {
$otherBlockDAO->is_primary = 1;
}
if ($billingDAOId && ($billingDAOId == $deleteDAO->id)) {
$otherBlockDAO->is_billing = 1;
}
$blocksDAO[$name]['delete'][$deleteDAO->id] = $deleteDAO;
}
$blocksDAO[$name]['update'][$otherBlockDAO->id] = $otherBlockDAO;
}
$blocksDAO[$name]['update'] += $mergeHandler->getBlocksToUpdateForDeletedContact($name);
}
}

CRM_Utils_Hook::alterLocationMergeData($blocksDAO, $mergeHandler->getToKeepID(), $mergeHandler->getToRemoveID(), $migrationInfo);
foreach ($blocksDAO as $blockDAOs) {
if (!empty($blockDAOs['update'])) {
foreach ($blockDAOs['update'] as $blockDAO) {
$blockDAO->save();
}
}
if (!empty($blockDAOs['delete'])) {
foreach ($blockDAOs['delete'] as $blockDAO) {
$blockDAO->delete();
}
}
}
}

/**
* Dedupe a pair of contacts.
*
Expand Down Expand Up @@ -2092,7 +1984,7 @@ protected static function getCustomFieldMetadata($contactType) {
* @throws \CRM_Core_Exception
* @throws \CiviCRM_API3_Exception
*/
public static function getConflicts(&$migrationInfo, $mainId, $otherId, $mode) {
public static function getConflicts(array &$migrationInfo, int $mainId, int $otherId, string $mode): array {
$conflicts = [];
// Generate var $migrationInfo. The variable structure is exactly same as
// $formValues submitted during a UI merge for a pair of contacts.
Expand All @@ -2111,8 +2003,8 @@ public static function getConflicts(&$migrationInfo, $mainId, $otherId, $mode) {
continue;
}
elseif ((in_array(substr($key, 5), CRM_Dedupe_Merger::getContactFields()) or
substr($key, 0, 12) === 'move_custom_'
) and $val != NULL
strpos($key, 'move_custom_') === 0
) and $val !== NULL
) {
// Rule: If both main-contact, and other-contact have a field with a
// different value, then let $mode decide if to merge it or not
Expand Down
2 changes: 1 addition & 1 deletion CRM/Event/BAO/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -1320,7 +1320,7 @@ public static function buildCustomDisplay(
$groupTitle = NULL;
foreach ($fields as $k => $v) {
if (!$groupTitle) {
$groupTitle = $v['groupTitle'];
$groupTitle = $v['groupDisplayTitle'];
}
// suppress all file fields from display
if (
Expand Down
4 changes: 3 additions & 1 deletion CRM/Export/BAO/ExportProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -1458,7 +1458,9 @@ public function getSqlColumnDefinition($fieldName, $columnName) {
if (in_array(CRM_Utils_Array::value('data_type', $fieldSpec), ['Country', 'StateProvince', 'ContactReference'])) {
return "`$fieldName` varchar(255)";
}
return "`$fieldName` varchar(16)";
// some of those will be exported as a (localisable) string
// @see https://lab.civicrm.org/dev/core/-/issues/2164
return "`$fieldName` varchar(64)";

case CRM_Utils_Type::T_STRING:
if (isset($fieldSpec['maxlength'])) {
Expand Down
Loading