getFieldValue failed on empty multiple-contact reference field
When submitting a record that includes a custom field of multiple contact reference type, if that field is empty (i.e. no contacts), an error message "getFieldValue failed" sometimes occurs and the screen freezes and needs to be reloaded. The record update seems to go ahead nonetheless.
This seems to be due to a change introduced in https://github.com/civicrm/civicrm-core/pull/18941 that adds support to CRM/Core/BAO/CustomField.php for multiple contact fields. The new logic checks that the value is of the correct type (array or numeric) but omits the check that the value is not empty. (Before this change, one of the conditions was that the value does not equate to false).
Before change (note the && $value
):
if ($field['data_type'] == 'ContactReference' && $value) {
if (is_numeric($value)) {
$display = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $value, 'display_name');
}
else {
$display = $value;
}
}
After change:
if ($field['data_type'] == 'ContactReference' && (is_array($value) || is_numeric($value))) {
$displayNames = [];
foreach ((array) $value as $contactId) {
$displayNames[] = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contactId, 'display_name');
}
$display = implode(', ', $displayNames);
}
elseif ($field['data_type'] == 'ContactReference') {
$display = $value;
}
Suggested fix - remove vulnerability to empty scalar values being passed:
if ($field['data_type'] == 'ContactReference' && (is_array($value) || is_numeric($value))) {
if (empty($value))
{
$display = '';
}
else
{
$displayNames = [];
foreach ((array) $value as $contactId) {
$displayNames[] = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contactId, 'display_name');
}
$display = implode(', ', $displayNames);
}
}
elseif ($field['data_type'] == 'ContactReference') {
$display = $value;
}