Documentation

CRM_Dedupe_Merger
in package

Tags
copyright

CiviCRM LLC https://civicrm.org/licensing

Table of Contents

Methods

addMembershipToRelatedContacts()  : mixed
Added for CRM-12695 Based on the contactID provided add/update membership(s) to related contacts
batchMerge()  : array<string|int, mixed>|bool
Batch merge a set of contacts based on rule-group and group.
cidRefs()  : mixed
Get array tables and fields that reference civicrm_contact.id.
cpTables()  : mixed
Tables which require custom processing should declare functions to call here.
createMergeActivities()  : mixed
Create activities tracking the merge on affected contacts.
eidRefs()  : mixed
Return tables and their fields referencing civicrm_contact.contact_id with entity_id
getActiveRelTables()  : array<string|int, mixed>
Returns the related tables groups for which a contact has any info entered.
getConflicts()  : array<string|int, mixed>
Get conflicts for proposed merge pair.
getContactFields()  : array<string|int, mixed>
Get fields in the contact table suitable for merging.
getDuplicatePairs()  : array<string|int, mixed>
Get Duplicate Pairs based on a rule for a group.
getJoinOnDedupeTable()  : string
Get the string to join the prevnext cache to the dedupe table.
getLocationBlockInfo()  : array<string|int, mixed>
A function to build an array of information about location blocks that is required when merging location fields
getLocationDataFields()  : mixed
Get the location data from a location array, filtering out metadata.
getMergeCacheKeyString()  : string
Get the cache key string for the merge action.
getMergeContactDetails()  : array<string|int, mixed>
Get the details of the contact to be merged.
getMergeFieldsMetadata()  : array<string|int, mixed>
Get the metadata for the merge fields.
getMergeStats()  : array<string|int, mixed>
Get merge outcome statistics.
getMergeStatsMsg()  : string
Get merge statistics message.
getMultiValueCustomSets()  : array<string|int, mixed>
We treat multi-valued custom sets as "related tables" similar to activities, contributions, etc.
getRowsElementsAndInfo()  : array<string|int, mixed>|bool|int
A function to build an array of information required by merge function and the merge UI.
locationHasData()  : bool
Does the location array have valid data.
locationIsSame()  : bool
Compare 2 addresses to see if they are the effectively the same.
locTables()  : mixed
Return tables using locations.
merge()  : array<string|int, mixed>|bool
Merge given set of contacts. Performs core operation.
moveAllBelongings()  : bool
Based on the provided two contact_ids and a set of tables, move the belongings of the other contact to the main one - be it Location / CustomFields or Contact .. related info.
moveContactBelongings()  : mixed
Based on the provided two contact_ids and a set of tables, move the belongings of the other contact to the main one.
operationSql()  : array<string|int, mixed>
paymentSql()  : array<string|int, mixed>
Return payment update Query.
paymentTables()  : mixed
Return payment related table.
relTables()  : array<string|int, mixed>
FIXME: consider creating a common structure with cidRefs() and eidRefs() FIXME: the sub-pages references by the URLs should be loaded dynamically on the merge form instead
removeContactBelongings()  : mixed
Based on the provided two contact_ids and a set of tables, remove the belongings of the other contact and of their relations.
resetMergeStats()  : mixed
Delete information about merges for the given string.
retrieveFields()  : array<string|int, mixed>
Load all non-empty fields for the contacts
skipMerge()  : bool
A function which uses various rules / algorithms for choosing which contact to bias to when there's a conflict (to handle "gotchas"). Plus the safest route to merge.
updateMergeStats()  : mixed
Update the statistics for the merge set.
addLocationFieldInfo()  : array<string|int, mixed>
dedupePair()  : bool|array<string|int, mixed>
Dedupe a pair of contacts.
deletePairFromPrevNextCache()  : mixed
Delete merged pair from the previous next cache table as the are no longer a merge candidate.
filterRowBasedCustomDataFromCustomTables()  : mixed
Filter out custom tables from cidRefs unless they are there due to a contact reference or are a multiple set.
formatConflictArray()  : mixed
getCachedDuplicateMatches()  : array<string|int, mixed>
Get any duplicate merge pairs that have been previously cached.
getLocationEntityForKey()  : string
Get the relevant location entity for the array key.
getLocksOnContacts()  : array<string|int, mixed>
Get a lock on the given contact.
getMultiValueCidRefs()  : mixed
Return an array of tables & fields which hold serialized arrays of contact ids
getWhereString()  : string
Get where string for dedupe join.
ignoredFields()  : array<string|int, mixed>
Get fields that should not be transferred.
processCustomFields()  : array<string|int, mixed>
Honestly - what DOES this do - hopefully some refactoring will reveal it's purpose.
releaseLocks()  : mixed
Release contact locks so another process can alter them if it wants.
swapOutFieldsAffectedByQFZeroBug()  : mixed
Replace the pseudo QFKey with zero if it is present.
updateContact()  : void
Update the contact with the new parameters.
buildLocationBlockForContact()  : array<string|int, mixed>
Build up the location block for the contact in dedupe-screen display format.
formatProfileContactParams()  : array<string|int, mixed>
Format profile contact parameters.
getFieldValueAndLabel()  : array<string|int, mixed>
Get the field value & label for the given field.

Methods

addMembershipToRelatedContacts()

Added for CRM-12695 Based on the contactID provided add/update membership(s) to related contacts

public static addMembershipToRelatedContacts(int $contactID) : mixed
Parameters
$contactID : int
Tags
throws
CRM_Core_Exception

batchMerge()

Batch merge a set of contacts based on rule-group and group.

public static batchMerge(int $rgid[, int $gid = NULL ][, string $mode = 'safe' ][, int $batchLimit = 1 ][, int $isSelected = 2 ][, array<string|int, mixed> $criteria = [] ][, bool $checkPermissions = TRUE ][, bool|null $reloadCacheIfEmpty = NULL ][, int $searchLimit = 0 ]) : array<string|int, mixed>|bool
Parameters
$rgid : int

Rule group id.

$gid : int = NULL

Group id.

$mode : string = 'safe'

Helps decide how to behave when there are conflicts. A 'safe' value skips the merge if there are any un-resolved conflicts, wheras 'aggressive' mode does a force merge.

$batchLimit : int = 1

number of merges to carry out in one batch.

$isSelected : int = 2

if records with is_selected column needs to be processed. Note the option of '2' is only used in conjunction with $redirectForPerformance to determine when to reload the cache (!). The use of anything other than a boolean is being grandfathered out in favour of explicitly passing in $reloadCacheIfEmpty

$criteria : array<string|int, mixed> = []

Criteria to use in the filter.

$checkPermissions : bool = TRUE

Respect logged in user permissions.

$reloadCacheIfEmpty : bool|null = NULL

If not set explicitly this is calculated but it is preferred that it be set per comments on isSelected above.

$searchLimit : int = 0

Limit on number of contacts to search for duplicates for. This means that if the limit is 1000 then only duplicates for the first 1000 contacts matching criteria will be found and batchMerged (the number of merges could be less than or greater than 100)

Tags
throws
CRM_Core_Exception
Return values
array<string|int, mixed>|bool

cidRefs()

Get array tables and fields that reference civicrm_contact.id.

public static cidRefs() : mixed

This function calls the merge hook and only exists to wrap the DAO function to support that deprecated call. The entityTypes hook is the recommended way to add tables to this result.

I thought about adding another hook to alter tableReferences but decided it was unclear if there are use cases not covered by entityTables and instead we should wait & see.

cpTables()

Tables which require custom processing should declare functions to call here.

public static cpTables() : mixed

Doing so will override normal processing.

createMergeActivities()

Create activities tracking the merge on affected contacts.

public static createMergeActivities(int $mainId, int $otherId) : mixed
Parameters
$mainId : int
$otherId : int
Tags
throws
CRM_Core_Exception

eidRefs()

Return tables and their fields referencing civicrm_contact.contact_id with entity_id

public static eidRefs() : mixed

getActiveRelTables()

Returns the related tables groups for which a contact has any info entered.

public static getActiveRelTables(int $cid) : array<string|int, mixed>
Parameters
$cid : int
Tags
throws
CRM_Core_Exception
Return values
array<string|int, mixed>

getConflicts()

Get conflicts for proposed merge pair.

public static getConflicts(array<string|int, mixed> &$migrationInfo, int $mainId, int $otherId, string $mode) : array<string|int, mixed>
Parameters
$migrationInfo : array<string|int, mixed>

This is primarily to inform hooks. The can also modify it which feels pretty fragile to do it here - but it is historical.

$mainId : int

Main contact with whom merge has to happen.

$otherId : int

Duplicate contact which would be deleted after merge operation.

$mode : string

Helps decide how to behave when there are conflicts.

  • A 'safe' value skips the merge if there are any un-resolved conflicts.
  • Does a force merge otherwise (aggressive mode).
Tags
throws
CRM_Core_Exception
Return values
array<string|int, mixed>

getContactFields()

Get fields in the contact table suitable for merging.

public static getContactFields() : array<string|int, mixed>
Tags
throws
CRM_Core_Exception
throws
UnauthorizedException
Return values
array<string|int, mixed>

Array of field names to be potentially merged.

getDuplicatePairs()

Get Duplicate Pairs based on a rule for a group.

public static getDuplicatePairs(int $rule_group_id, int $group_id, bool $reloadCacheIfEmpty, int $batchLimit, bool $isSelected[, bool $includeConflicts = TRUE ][, array<string|int, mixed> $criteria = [] ][, bool $checkPermissions = TRUE ][, int $searchLimit = 0 ][, int $isForceNewSearch = 0 ]) : array<string|int, mixed>
Parameters
$rule_group_id : int
$group_id : int
$reloadCacheIfEmpty : bool

Should the cache be reloaded if empty - this must be false when in a dedupe action!

$batchLimit : int
$isSelected : bool

Limit to selected pairs.

$includeConflicts : bool = TRUE
$criteria : array<string|int, mixed> = []

Additional criteria to narrow down the merge group.

$checkPermissions : bool = TRUE

Respect logged in user permissions.

$searchLimit : int = 0

Limit to searching for matches against this many contacts.

$isForceNewSearch : int = 0

Should a new search be forced, bypassing any cache retrieval.

Tags
throws
CRM_Core_Exception
Return values
array<string|int, mixed>

Array of matches meeting the criteria.

getJoinOnDedupeTable()

Get the string to join the prevnext cache to the dedupe table.

public static getJoinOnDedupeTable() : string
Return values
string

The join string to join prevnext cache on the dedupe table.

getLocationBlockInfo()

A function to build an array of information about location blocks that is required when merging location fields

public static getLocationBlockInfo() : array<string|int, mixed>
Return values
array<string|int, mixed>

getLocationDataFields()

Get the location data from a location array, filtering out metadata.

public static getLocationDataFields(array<string|int, mixed> $location) : mixed

This returns data like street_address but not metadata like is_primary, on_hold etc.

Parameters
$location : array<string|int, mixed>

getMergeCacheKeyString()

Get the cache key string for the merge action.

public static getMergeCacheKeyString(int|null $rule_group_id, int|null $group_id, array<string|int, mixed> $criteria, bool $checkPermissions, int $searchLimit) : string
Parameters
$rule_group_id : int|null
$group_id : int|null
$criteria : array<string|int, mixed>

Additional criteria to narrow down the merge group. Currently we are only supporting the key 'contact' within it.

$checkPermissions : bool

Respect the users permissions.

$searchLimit : int

Number of contacts to seek dupes for (we need this because if we change it the results won't be refreshed otherwise. Changing the limit from 100 to 1000 SHOULD result in a new dedupe search).

Return values
string

getMergeContactDetails()

Get the details of the contact to be merged.

public static getMergeContactDetails(int $contactID) : array<string|int, mixed>
Parameters
$contactID : int
Tags
throws
CRM_Core_Exception
Return values
array<string|int, mixed>

getMergeFieldsMetadata()

Get the metadata for the merge fields.

public static getMergeFieldsMetadata([bool $checkPermissions = TRUE ]) : array<string|int, mixed>

This is basically the contact metadata, augmented with fields to represent email greeting, postal greeting & addressee.

Parameters
$checkPermissions : bool = TRUE
Tags
throws
CRM_Core_Exception
throws
UnauthorizedException
Return values
array<string|int, mixed>

getMergeStats()

Get merge outcome statistics.

public static getMergeStats(string $cacheKeyString) : array<string|int, mixed>
Parameters
$cacheKeyString : string
Tags
throws
CRM_Core_Exception
Return values
array<string|int, mixed>

Array of how many were merged and how many were skipped.

getMergeStatsMsg()

Get merge statistics message.

public static getMergeStatsMsg(array<string|int, mixed> $stats) : string
Parameters
$stats : array<string|int, mixed>
Return values
string

getMultiValueCustomSets()

We treat multi-valued custom sets as "related tables" similar to activities, contributions, etc.

public static getMultiValueCustomSets(string $request) : array<string|int, mixed>
Parameters
$request : string

'relTables' or 'cidRefs'.

Tags
throws
CRM_Core_Exception
see

CRM-13836

Return values
array<string|int, mixed>

getRowsElementsAndInfo()

A function to build an array of information required by merge function and the merge UI.

public static getRowsElementsAndInfo(int $mainID, int $otherID[, bool $checkPermissions = TRUE ]) : array<string|int, mixed>|bool|int
Parameters
$mainID : int

Main contact with whom merge has to happen.

$otherID : int

Duplicate contact which would be deleted after merge operation.

$checkPermissions : bool = TRUE

Should the logged in user's permissions be ignore. Setting this to false is highly risky as it could cause data to be lost due to conflicts not showing up. OTOH there is a risk a merger might view custom data they do not have permission to. Hence for now only making this really explicit and making it reflect perms in an api call.

Tags
todo

review permissions issue!

todo

review permissions issue!

throws
CRM_Core_Exception
Return values
array<string|int, mixed>|bool|int

rows => An array of arrays, each is row of merge information for the table Format: move_fieldname, eg: move_contact_type main => Value associated with the main contact other => Value associated with the other contact title => The title of the field to display in the merge table

elements => An array of form elements for the merge UI

rel_tables => Stores the tables that have related entities for the contact for example mailings, groups

main_details => An array of core contact field values, eg: first_name, etc. location_blocks => An array of location block data for the main contact stored as the 'result' of an API call. eg: main_details['location_blocks']['address'][0]['id'] eg: main_details['location_blocks']['email'][1]['id']

other_details => As above, but for the 'other' contact

migration_info => Stores the 'default' merge actions for each field which is used when programatically merging contacts. It contains instructions to move all fields from the 'other' contact to the 'main' contact, as though the form had been submitted with those options.

locationHasData()

Does the location array have valid data.

public static locationHasData(array<string|int, mixed> $location) : bool

While not UI-creatable some sites wind up with email or address rows with no actual email or address through non core-UI processes.

Parameters
$location : array<string|int, mixed>
Return values
bool

locationIsSame()

Compare 2 addresses to see if they are the effectively the same.

public static locationIsSame(array<string|int, mixed> $mainAddress, array<string|int, mixed> $comparisonAddress) : bool

Being the same would mean same location type and any populated fields that describe the locationn match.

Metadata fields such as is_primary, on_hold, manual_geocode may differ.

Parameters
$mainAddress : array<string|int, mixed>
$comparisonAddress : array<string|int, mixed>
Return values
bool

locTables()

Return tables using locations.

public static locTables() : mixed

merge()

Merge given set of contacts. Performs core operation.

public static merge([array<string|int, mixed> $dupePairs = [] ][, array<string|int, mixed> $cacheParams = [] ][, string $mode = 'safe' ][, bool $redirectForPerformance = FALSE ][, bool $checkPermissions = TRUE ]) : array<string|int, mixed>|bool
Parameters
$dupePairs : array<string|int, mixed> = []

Set of pair of contacts for whom merge is to be done.

$cacheParams : array<string|int, mixed> = []

Prev-next-cache params based on which next pair of contacts are computed. Generally used with batch-merge.

$mode : string = 'safe'

Helps decide how to behave when there are conflicts. A 'safe' value skips the merge if there are any un-resolved conflicts. Does a force merge otherwise (aggressive mode).

$redirectForPerformance : bool = FALSE

Redirect to a url for batch processing.

$checkPermissions : bool = TRUE

Respect logged in user permissions.

Tags
throws
CRM_Core_Exception
Return values
array<string|int, mixed>|bool

moveAllBelongings()

Based on the provided two contact_ids and a set of tables, move the belongings of the other contact to the main one - be it Location / CustomFields or Contact .. related info.

public static moveAllBelongings(int $mainId, int $otherId, array<string|int, mixed> $migrationInfo[, bool $checkPermissions = TRUE ]) : bool

A superset of moveContactBelongings() function.

Parameters
$mainId : int

Main contact with whom merge has to happen.

$otherId : int

Duplicate contact which would be deleted after merge operation.

$migrationInfo : array<string|int, mixed>
$checkPermissions : bool = TRUE

Respect logged in user permissions.

Tags
throws
CRM_Core_Exception
throws
UnauthorizedException
Return values
bool

moveContactBelongings()

Based on the provided two contact_ids and a set of tables, move the belongings of the other contact to the main one.

public static moveContactBelongings(CRM_Dedupe_MergeHandler $mergeHandler, array<string|int, mixed> $tables, array<string|int, mixed> $tableOperations) : mixed
Parameters
$mergeHandler : CRM_Dedupe_MergeHandler
$tables : array<string|int, mixed>
$tableOperations : array<string|int, mixed>
Tags
throws
CRM_Core_Exception
throws
UnauthorizedException

operationSql()

public static operationSql(int $mainId, int $otherId, string $tableName[, array<string|int, mixed> $tableOperations = [] ][, string $mode = 'add' ]) : array<string|int, mixed>
Parameters
$mainId : int
$otherId : int
$tableName : string
$tableOperations : array<string|int, mixed> = []
$mode : string = 'add'
Return values
array<string|int, mixed>

paymentSql()

Return payment update Query.

public static paymentSql(string $tableName, int $mainContactId, int $otherContactId) : array<string|int, mixed>
Parameters
$tableName : string
$mainContactId : int
$otherContactId : int
Return values
array<string|int, mixed>

paymentTables()

Return payment related table.

public static paymentTables() : mixed

relTables()

FIXME: consider creating a common structure with cidRefs() and eidRefs() FIXME: the sub-pages references by the URLs should be loaded dynamically on the merge form instead

public static relTables() : array<string|int, mixed>
Tags
throws
CRM_Core_Exception
Return values
array<string|int, mixed>

removeContactBelongings()

Based on the provided two contact_ids and a set of tables, remove the belongings of the other contact and of their relations.

public static removeContactBelongings(int $otherID, array<string|int, mixed> $tables) : mixed
Parameters
$otherID : int
$tables : array<string|int, mixed>
Tags
throws
CRM_Core_Exception

resetMergeStats()

Delete information about merges for the given string.

public static resetMergeStats(mixed $cacheKeyString) : mixed
Parameters
$cacheKeyString : mixed

retrieveFields()

Load all non-empty fields for the contacts

public static retrieveFields(array<string|int, mixed> $main, array<string|int, mixed> $other) : array<string|int, mixed>
Parameters
$main : array<string|int, mixed>

Contact details.

$other : array<string|int, mixed>

Contact details.

Tags
throws
CRM_Core_Exception
Return values
array<string|int, mixed>

skipMerge()

A function which uses various rules / algorithms for choosing which contact to bias to when there's a conflict (to handle "gotchas"). Plus the safest route to merge.

public static skipMerge(int $mainId, int $otherId, array<string|int, mixed> &$migrationInfo[, string $mode = 'safe' ][, array<string|int, mixed> &$conflicts = [] ]) : bool
Parameters
$mainId : int

Main contact with whom merge has to happen.

$otherId : int

Duplicate contact which would be deleted after merge operation.

$migrationInfo : array<string|int, mixed>

Array of information about which elements to merge.

$mode : string = 'safe'

Helps decide how to behave when there are conflicts.

  • A 'safe' value skips the merge if there are any un-resolved conflicts.
  • Does a force merge otherwise (aggressive mode).
$conflicts : array<string|int, mixed> = []

An empty array to be filed with conflict information.

Tags
throws
CRM_Core_Exception
Return values
bool

updateMergeStats()

Update the statistics for the merge set.

public static updateMergeStats(string $cacheKeyString[, array<string|int, mixed> $result = [] ]) : mixed
Parameters
$cacheKeyString : string
$result : array<string|int, mixed> = []
Tags
throws
CRM_Core_Exception

addLocationFieldInfo()

protected static addLocationFieldInfo(mixed $mainId, mixed $otherId, mixed $blockInfo, mixed $blockName, array<string|int, mixed> $locations, array<string|int, mixed> $rows, array<string|int, mixed> $elements, array<string|int, mixed> $migrationInfo) : array<string|int, mixed>
Parameters
$mainId : mixed
$otherId : mixed
$blockInfo : mixed
$blockName : mixed
$locations : array<string|int, mixed>
$rows : array<string|int, mixed>
$elements : array<string|int, mixed>
$migrationInfo : array<string|int, mixed>
Tags
throws
CRM_Core_Exception
Return values
array<string|int, mixed>

dedupePair()

Dedupe a pair of contacts.

protected static dedupePair(int $mainId, int $otherId[, string $mode = 'safe' ][, bool $checkPermissions = TRUE ][, string $cacheKeyString = NULL ]) : bool|array<string|int, mixed>
Parameters
$mainId : int

Id of contact to keep.

$otherId : int

Id of contact to delete.

$mode : string = 'safe'
$checkPermissions : bool = TRUE
$cacheKeyString : string = NULL
Tags
throws
CRM_Core_Exception
throws
CRM_Core_Exception_ResourceConflictException
throws
CRM_Core_Exception
throws
UnauthorizedException
Return values
bool|array<string|int, mixed>

deletePairFromPrevNextCache()

Delete merged pair from the previous next cache table as the are no longer a merge candidate.

protected static deletePairFromPrevNextCache(int $contactID1, int $contactID2) : mixed

It's possible there may be more than one set of merge results cached, with different cache keys. Once we have merged a pair these should all go (even from a different merge search) as they can only be merged once.

Parameters
$contactID1 : int
$contactID2 : int

filterRowBasedCustomDataFromCustomTables()

Filter out custom tables from cidRefs unless they are there due to a contact reference or are a multiple set.

protected static filterRowBasedCustomDataFromCustomTables(array<string|int, mixed> &$cidRefs) : mixed

The only fields where we want to move the data by sql is where entity reference fields on another contact refer to the contact being merged, or it is a multiple record set. The transference of custom data from one contact to another is done in 2 other places in the dedupe process but should not be done in moveAllContactData.

Note it's a bit silly the way we build & then cull cidRefs - however, poor hook placement means that until we fully deprecate calling the hook from cidRefs we are stuck.

It was deprecated in code (via deprecation notices if people altered it) in Mar 2019 but in docs only in Apri 2020.

Parameters
$cidRefs : array<string|int, mixed>
Tags
throws
CRM_Core_Exception

formatConflictArray()

protected static formatConflictArray(array<string|int, mixed> $conflicts, array<string|int, mixed> $migrationInfo, mixed $toKeepContactLocationBlocks, mixed $toRemoveContactLocationBlocks, mixed $toKeepID, mixed $toRemoveID, string $mode) : mixed
Parameters
$conflicts : array<string|int, mixed>
$migrationInfo : array<string|int, mixed>
$toKeepContactLocationBlocks : mixed
$toRemoveContactLocationBlocks : mixed
$toKeepID : mixed
$toRemoveID : mixed
$mode : string
Tags
throws
CRM_Core_Exception

getCachedDuplicateMatches()

Get any duplicate merge pairs that have been previously cached.

protected static getCachedDuplicateMatches(int $rule_group_id, int $group_id, int $batchLimit, bool $isSelected, bool $includeConflicts, array<string|int, mixed> $criteria, int $checkPermissions[, int $searchLimit = 0 ]) : array<string|int, mixed>
Parameters
$rule_group_id : int
$group_id : int
$batchLimit : int
$isSelected : bool
$includeConflicts : bool
$criteria : array<string|int, mixed>
$checkPermissions : int
$searchLimit : int = 0
Return values
array<string|int, mixed>

getLocationEntityForKey()

Get the relevant location entity for the array key.

protected static getLocationEntityForKey(string $fieldName) : string

This function is duplicated from CRM_Contact_BAO_Contact to allow cleanup. See self::formatProfileContactParams

Based on the field name we determine which location entity we are dealing with. Apart from a few specific ones they are mostly 'address' (the default).

Parameters
$fieldName : string
Return values
string

getLocksOnContacts()

Get a lock on the given contact.

protected static getLocksOnContacts(array<string|int, mixed> $contacts) : array<string|int, mixed>

The lock is like a gentleman's agreement between php & mysql. It is reserved at the mysql level so it works across php processes but it doesn't actually lock the database.

Instead php can check the lock to see if it has been acquired before taking an action.

In this case we really don't want to attempt to dedupe contacts if another process is trying to act on the specific contact as it could result in messy deadlocks & possibly data corruption. In most databases this would be a rare event but if multiple dedupe processes are running at once (for example) or there is also an import process in play there is potential for them to crash. By throwing a specific error the calling process can catch it and determine it is worth trying again later without a lot of noise.

As of writing no other processes DO grab contact locks but it would be reasonable to consider grabbing them doing contact edits in general as well as imports etc.

Parameters
$contacts : array<string|int, mixed>
Tags
throws
CRM_Core_Exception
throws
CRM_Core_Exception_ResourceConflictException
Return values
array<string|int, mixed>

getMultiValueCidRefs()

Return an array of tables & fields which hold serialized arrays of contact ids

protected static getMultiValueCidRefs() : mixed

Return format is ['table_name' => ['field_name' => SERIALIZE_METHOD]]

For now, only custom fields can be serialized and the only method used is CRM_Core_DAO::SERIALIZE_SEPARATOR_BOOKEND.

getWhereString()

Get where string for dedupe join.

protected static getWhereString(bool $isSelected) : string
Parameters
$isSelected : bool
Return values
string

ignoredFields()

Get fields that should not be transferred.

protected static ignoredFields([string $type = 'location' ]) : array<string|int, mixed>

This is primarily because they are calculated.

Parameters
$type : string = 'location'
Return values
array<string|int, mixed>

processCustomFields()

Honestly - what DOES this do - hopefully some refactoring will reveal it's purpose.

protected static processCustomFields(int $mainId, string $key, array<string|int, mixed> $submitted, mixed $value, int $fieldID, bool $isView, string $htmlType, bool $isSerialized) : array<string|int, mixed>

Update this function formats fields in preparation for them to be submitted to the 'ProfileContactCreate action. This is a lot of code to do this & for

  • for some fields it fails - e.g Country - per testMergeCustomFields.

Goal is to move all custom field handling into 'move' functions on the various BAO with an underlying DAO function. For custom fields it has been started on the BAO.

Parameters
$mainId : int
$key : string
$submitted : array<string|int, mixed>
$value : mixed
$fieldID : int
$isView : bool
$htmlType : string
$isSerialized : bool
Tags
throws
CRM_Core_Exception
Return values
array<string|int, mixed>

releaseLocks()

Release contact locks so another process can alter them if it wants.

protected static releaseLocks(array<string|int, mixed> $locks) : mixed
Parameters
$locks : array<string|int, mixed>

swapOutFieldsAffectedByQFZeroBug()

Replace the pseudo QFKey with zero if it is present.

protected static swapOutFieldsAffectedByQFZeroBug(array<string|int, mixed> &$migrationInfo) : mixed
Parameters
$migrationInfo : array<string|int, mixed>
Tags
todo
  • on the slim chance this is still relevant it should be moved to the form layer.

Details about this bug are somewhat obscured by the move from svn but perhaps JIRA can still help.

updateContact()

Update the contact with the new parameters.

protected static updateContact(int $contactID, array<string|int, mixed> $params) : void

This function is intended as an interim function, with the intent being an apiv4 call.

The function was calling the rather-terrifying createProfileContact. I copied all that code into this function and then removed all the parts that have no effect in this scenario.

Parameters
$contactID : int
$params : array<string|int, mixed>
Tags
throws
CRM_Core_Exception
throws
UnauthorizedException

buildLocationBlockForContact()

Build up the location block for the contact in dedupe-screen display format.

private static buildLocationBlockForContact(int $cid, array<string|int, mixed> $blockInfo, string $blockName) : array<string|int, mixed>
Parameters
$cid : int
$blockInfo : array<string|int, mixed>
$blockName : string
Tags
throws
CRM_Core_Exception
Return values
array<string|int, mixed>

formatProfileContactParams()

Format profile contact parameters.

private static formatProfileContactParams(array<string|int, mixed> $params, int $contactID) : array<string|int, mixed>

Note this function has been duplicated from CRM_Contact_BAO_Contact in order to allow us to unravel all the work this class does to prepare to call this & create some sanity. Also start to eliminate a toxic function.

Parameters
$params : array<string|int, mixed>
$contactID : int
Return values
array<string|int, mixed>

getFieldValueAndLabel()

Get the field value & label for the given field.

private static getFieldValueAndLabel(string $field, array<string|int, mixed> $contact, bool $checkPermissions) : array<string|int, mixed>
Parameters
$field : string
$contact : array<string|int, mixed>
$checkPermissions : bool
Tags
throws
Exception
Return values
array<string|int, mixed>

        
On this page

Search results