From 33e61cb8fb2f7055b266af28fae6d24e340492c9 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Tue, 1 Dec 2015 21:54:20 -0500 Subject: [PATCH] CRM-17646 - Add hook_civicrm_fieldOptions + tests --- CRM/Core/PseudoConstant.php | 15 +++++- CRM/Utils/Hook.php | 17 ++++++ tests/phpunit/CRM/Core/FieldOptionsTest.php | 59 +++++++++++++++++++++ tests/phpunit/CRM/Group/Page/AjaxTest.php | 5 +- 4 files changed, 93 insertions(+), 3 deletions(-) diff --git a/CRM/Core/PseudoConstant.php b/CRM/Core/PseudoConstant.php index 1335766dc7..99508a78a7 100644 --- a/CRM/Core/PseudoConstant.php +++ b/CRM/Core/PseudoConstant.php @@ -218,7 +218,9 @@ class CRM_Core_PseudoConstant { 'localize' => FALSE, 'onlyActive' => ($context == 'validate' || $context == 'get') ? FALSE : TRUE, 'fresh' => FALSE, + 'context' => $context, ); + $entity = CRM_Core_DAO_AllCoreTables::getBriefName(CRM_Core_DAO_AllCoreTables::getCanonicalClassName($daoName)); // Custom fields are not in the schema if (strpos($fieldName, 'custom_') === 0 && is_numeric($fieldName[7])) { @@ -250,6 +252,7 @@ class CRM_Core_PseudoConstant { } } CRM_Utils_Hook::customFieldOptions($customField->id, $options, FALSE); + CRM_Utils_Hook::fieldOptions($entity, "custom_{$customField->id}", $options, $params); if ($options && $flip) { $options = array_flip($options); } @@ -261,7 +264,11 @@ class CRM_Core_PseudoConstant { $dao = new $daoName(); $fieldSpec = $dao->getFieldSpec($fieldName); $dao->free(); - // If neither worked then this field doesn't exist. Return false. + + // Ensure we have the canonical name for this field + $fieldName = CRM_Utils_Array::value('name', $fieldSpec, $fieldName); + + // Return false if field doesn't exist. if (empty($fieldSpec)) { return FALSE; } @@ -304,7 +311,7 @@ class CRM_Core_PseudoConstant { $params['keyColumn'] = 'name'; } // Call our generic fn for retrieving from the option_value table - return CRM_Core_OptionGroup::values( + $options = CRM_Core_OptionGroup::values( $pseudoconstant['optionGroupName'], $flip, $params['grouping'], @@ -315,6 +322,8 @@ class CRM_Core_PseudoConstant { $params['fresh'], $params['keyColumn'] ? $params['keyColumn'] : 'value' ); + CRM_Utils_Hook::fieldOptions($entity, $fieldName, $options, $params); + return $options; } // Fetch options from other tables @@ -415,6 +424,7 @@ class CRM_Core_PseudoConstant { CRM_Utils_Array::asort($output); } } + CRM_Utils_Hook::fieldOptions($entity, $fieldName, $output, $params); self::$cache[$cacheKey] = $output; } return $flip ? array_flip($output) : $output; @@ -424,6 +434,7 @@ class CRM_Core_PseudoConstant { // Return "Yes" and "No" for boolean fields elseif (CRM_Utils_Array::value('type', $fieldSpec) === CRM_Utils_Type::T_BOOLEAN) { $output = $context == 'validate' ? array(0, 1) : array(1 => ts('Yes'), 0 => ts('No')); + CRM_Utils_Hook::fieldOptions($entity, $fieldName, $output, $params); return $flip ? array_flip($output) : $output; } // If we're still here, it's an error. Return FALSE. diff --git a/CRM/Utils/Hook.php b/CRM/Utils/Hook.php index 39eee8a03b..706757b6d9 100644 --- a/CRM/Utils/Hook.php +++ b/CRM/Utils/Hook.php @@ -793,6 +793,23 @@ abstract class CRM_Utils_Hook { ); } + /** + * Hook for modifying field options + * + * @param string $entity + * @param string $field + * @param array $options + * @param array $params + * + * @return mixed + */ + public static function fieldOptions($entity, $field, &$options, $params) { + return self::singleton()->invoke(5, $entity, $field, $options, $params, + self::$_nullObject, self::$_nullObject, + 'civicrm_fieldOptions' + ); + } + /** * * This hook is called to display the list of actions allowed after doing a search. diff --git a/tests/phpunit/CRM/Core/FieldOptionsTest.php b/tests/phpunit/CRM/Core/FieldOptionsTest.php index a9978d22eb..dbafee061d 100644 --- a/tests/phpunit/CRM/Core/FieldOptionsTest.php +++ b/tests/phpunit/CRM/Core/FieldOptionsTest.php @@ -31,8 +31,22 @@ require_once 'CiviTest/CiviUnitTestCase.php'; * Tests for field options */ class CRM_Core_FieldOptionsTest extends CiviUnitTestCase { + + /** @var CRM_Utils_Hook_UnitTests */ + public $hookClass; + + /** @var array */ + public $replaceOptions; + + /** @var array */ + public $appendOptions; + + /** @var string */ + public $targetField; + public function setUp() { parent::setUp(); + $this->hookClass = CRM_Utils_Hook::singleton(); } /** @@ -93,4 +107,49 @@ class CRM_Core_FieldOptionsTest extends CiviUnitTestCase { } } + /** + * Ensure hook_civicrm_fieldOptions is working + */ + public function testHookFieldOptions() { + $this->hookClass->setHook('civicrm_fieldOptions', array($this, 'hook_civicrm_fieldOptions')); + CRM_Core_PseudoConstant::flush(); + + // Test replacing all options with a hook + $this->targetField = 'case_type_id'; + $this->replaceOptions = array('foo' => 'Foo', 'bar' => 'Bar'); + $result = $this->callAPISuccess('case', 'getoptions', array('field' => 'case_type_id')); + $this->assertEquals($result['values'], $this->replaceOptions); + + // TargetField doesn't match - should get unmodified option list + $originalGender = CRM_Contact_BAO_Contact::buildOptions('gender_id'); + $this->assertNotEquals($originalGender, $this->replaceOptions); + + // This time we should get foo bar appended to the list + $this->targetField = 'gender_id'; + $this->appendOptions = array('foo' => 'Foo', 'bar' => 'Bar'); + $this->replaceOptions = NULL; + CRM_Core_PseudoConstant::flush(); + $result = CRM_Contact_BAO_Contact::buildOptions('gender_id'); + $this->assertEquals($result, $originalGender + $this->appendOptions); + } + + /** + * Implements hook_civicrm_fieldOptions + * + * @param $entity + * @param $field + * @param $options + * @param $params + */ + public function hook_civicrm_fieldOptions($entity, $field, &$options, $params) { + if ($field == $this->targetField) { + if (is_array($this->replaceOptions)) { + $options = $this->replaceOptions; + } + if ($this->appendOptions) { + $options += $this->appendOptions; + } + } + } + } diff --git a/tests/phpunit/CRM/Group/Page/AjaxTest.php b/tests/phpunit/CRM/Group/Page/AjaxTest.php index 04782a1dd7..6d5dc350d2 100644 --- a/tests/phpunit/CRM/Group/Page/AjaxTest.php +++ b/tests/phpunit/CRM/Group/Page/AjaxTest.php @@ -13,10 +13,13 @@ class CRM_Group_Page_AjaxTest extends CiviUnitTestCase { protected $_permissionedGroup; /** * AS disabled group the contact has permission to. - * @var unknown + * @var int */ protected $_permissionedDisabledGroup; + /** + * @var CRM_Utils_Hook_UnitTests + */ public $hookClass; protected $_params = array(); -- 2.25.1