Details
-
Type: Bug
-
Status: Done/Fixed
-
Priority: Critical
-
Resolution: Fixed/Completed
-
Affects Version/s: 2.2.9
-
Fix Version/s: 3.0.3
-
Component/s: CiviCRM API, Core CiviCRM
-
Labels:None
Description
(The following has been observed in CiviCRM 2.2.8. The issue is closely tied to the implementation of CRM_Core_BAO_CustomOption::getCustomOption. This code appears the same in 2.2.8 and trunk (r25452), so newer releases are probably affected.)
hook_civicrm_customFieldOptions allows third-party developers to programmaticly populate the list of options in a select, multi-select, or similar custom data field. The documentation specifies the contract:
hook_civicrm_customFieldOptions($fieldID, &$options)
Although this doesn't indicate the format of $options, a developer can use standard debugging techniques and quickly observe that $options follows an "obvious" format – array keys are codes, and array values are printable labels, e.g.
function mymodule_civicrm_customFieldOptions($fieldID, &$options) {
if ($fieldID == 123)
}
Proceeding with this format of $options, a developer can implement the hook so that it appears to function correctly. For example, "civicrm/contact/add" will display the right options in field #123 and (upon submission) it will store selections for field #123 in the appropriate database record. "civicrm/contact/view" will then display the correct selections for field #123.
However, if a user edits an existing contact with "civicrm/contact/add", the previous selection for field #123 is not restored. When the user submits, he unwittingly erases the selection from the database.
I believe the problem is in CRM_Core_BAO_CustomOption::getCustomOption. getCustomOption() expects a different, undocumented contract for hook_civicrm_customFieldOptions, and an "obvious" hook implementation (above) will corrupt $options. A quick read of getCustomOption() suggests the following implementation would comply with the undocumented contract:
function mymodule_civicrm_customFieldOptions($fieldID, &$options, $frobnicate = FALSE ) {
if ($fieldID == 123) {
if ($frobnicate)
else
{ $options['0000ff'] = ts('Blue'); $options['00ff00'] = ts('Green'); } }
}
However, this is unlikely to work because CRM_Utils_Hook::customFieldOptions() does not pass along the $frobnicate parameter.