Skip to content

Commit

Permalink
Add pseudoconstant for Relationship.relationship_type_id
Browse files Browse the repository at this point in the history
This adds basic pseudoconstant support for the field using name_a_b and label_a_b
(it does not support other properties like name_b_a)

For legacy purposes it preserves the work done in civicrm#11853
to return a list like [1_a_b => Child of, 1_b_a => Parent of] if the "is_form" flag is set.
This was very nonstandard but is used to support in-place editing of the relationship type list
on the relationship form.
  • Loading branch information
colemanw committed Dec 28, 2020
1 parent d830d3a commit 1ac9bb5
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 87 deletions.
68 changes: 8 additions & 60 deletions CRM/Contact/BAO/Relationship.php
Original file line number Diff line number Diff line change
Expand Up @@ -2204,71 +2204,19 @@ public static function getColumnHeaders() {
* @inheritdoc
*/
public static function buildOptions($fieldName, $context = NULL, $props = []) {
if ($fieldName === 'relationship_type_id') {
return self::buildRelationshipTypeOptions($props);
// Quickform-specific format, for use when editing relationship type options in a popup from the contact relationship form
if ($fieldName === 'relationship_type_id' && !empty($props['is_form'])) {
return self::getContactRelationshipType(
$props['contact_id'] ?? NULL,
$props['relationship_direction'] ?? 'a_b',
$props['relationship_id'] ?? NULL,
$props['contact_type'] ?? NULL
);
}

return parent::buildOptions($fieldName, $context, $props);
}

/**
* Builds a list of options available for relationship types
*
* @param array $params
* - contact_type: Limits by contact type on the "A" side
* - relationship_id: Used to find the value for contact type for "B" side.
* If contact_a matches provided contact_id then type of contact_b will
* be used. Otherwise uses type of contact_a. Must be used with contact_id
* - contact_id: Limits by contact types of this contact on the "A" side
* - is_form: Returns array with keys indexed for use in a quickform
* - relationship_direction: For relationship types with duplicate names
* on both sides, defines which option should be returned, a_b or b_a
*
* @return array
*/
public static function buildRelationshipTypeOptions($params = []) {
$contactId = $params['contact_id'] ?? NULL;
$direction = CRM_Utils_Array::value('relationship_direction', $params, 'a_b');
$relationshipId = $params['relationship_id'] ?? NULL;
$contactType = $params['contact_type'] ?? NULL;
$isForm = $params['is_form'] ?? NULL;
$showAll = FALSE;

// getContactRelationshipType will return an empty set if these are not set
if (!$contactId && !$relationshipId && !$contactType) {
$showAll = TRUE;
}

$labels = self::getContactRelationshipType(
$contactId,
$direction,
$relationshipId,
$contactType,
$showAll,
'label'
);

if ($isForm) {
return $labels;
}

$names = self::getContactRelationshipType(
$contactId,
$direction,
$relationshipId,
$contactType,
$showAll,
'name'
);

// ensure $names contains only entries in $labels
$names = array_intersect_key($names, $labels);

$nameToLabels = array_combine($names, $labels);

return $nameToLabels;
}

/**
* Process the params from api, form and check if current
* employer should be set or unset.
Expand Down
1 change: 1 addition & 0 deletions CRM/Contact/BAO/RelationshipType.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public static function add($params) {

CRM_Core_PseudoConstant::relationshipType('label', TRUE);
CRM_Core_PseudoConstant::relationshipType('name', TRUE);
CRM_Core_PseudoConstant::flush();
CRM_Case_XMLProcessor::flushStaticCaches();
return $relationshipType;
}
Expand Down
12 changes: 9 additions & 3 deletions CRM/Contact/DAO/Relationship.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*
* Generated from xml/schema/CRM/Contact/Relationship.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
* (GenCodeChecksum:2046fac3c61cd88a17bf21dfe3e6f970)
* (GenCodeChecksum:5c1cfe38206fb7c465befe517bf6f23d)
*/

/**
Expand Down Expand Up @@ -59,7 +59,7 @@ class CRM_Contact_DAO_Relationship extends CRM_Core_DAO {
public $contact_id_b;

/**
* id of the relationship
* Type of relationship
*
* @var int
*/
Expand Down Expand Up @@ -206,7 +206,7 @@ public static function &fields() {
'name' => 'relationship_type_id',
'type' => CRM_Utils_Type::T_INT,
'title' => ts('Relationship Type'),
'description' => ts('id of the relationship'),
'description' => ts('Type of relationship'),
'required' => TRUE,
'where' => 'civicrm_relationship.relationship_type_id',
'table_name' => 'civicrm_relationship',
Expand All @@ -217,6 +217,12 @@ public static function &fields() {
'html' => [
'type' => 'Select',
],
'pseudoconstant' => [
'table' => 'civicrm_relationship_type',
'keyColumn' => 'id',
'labelColumn' => 'label_a_b',
'nameColumn' => 'name_a_b',
],
'add' => '1.1',
],
'relationship_start_date' => [
Expand Down
2 changes: 1 addition & 1 deletion CRM/Core/PseudoConstant.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ public static function get($daoName, $fieldName, $params = [], $context = NULL)

// if callback is specified..
if (!empty($pseudoconstant['callback'])) {
$fieldOptions = call_user_func(Civi\Core\Resolver::singleton()->get($pseudoconstant['callback']), $context);
$fieldOptions = call_user_func(Civi\Core\Resolver::singleton()->get($pseudoconstant['callback']), $context, $params);
//CRM-18223: Allow additions to field options via hook.
CRM_Utils_Hook::fieldOptions($entity, $fieldName, $fieldOptions, $params);
return $fieldOptions;
Expand Down
52 changes: 30 additions & 22 deletions tests/phpunit/CRM/Contact/BAO/RelationshipTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,22 @@ public function testRelationshipTypeOptionsWillReturnSpecifiedType() {
'contact_type_b' => 'Organization',
]);

$result = CRM_Contact_BAO_Relationship::buildRelationshipTypeOptions(
['contact_type' => 'Organization']
);
$this->assertContains($orgToOrgType, $result);
$this->assertContains($orgToOrgReverseType, $result);

$result = CRM_Contact_BAO_Relationship::buildRelationshipTypeOptions(
['contact_type' => 'Individual']
);

$this->assertNotContains($orgToOrgType, $result);
$this->assertNotContains($orgToOrgReverseType, $result);
$result = civicrm_api3('Relationship', 'getoptions', [
'field' => 'relationship_type_id',
'is_form' => TRUE,
'contact_type' => 'Organization',
]);
$this->assertContains($orgToOrgType, $result['values']);
$this->assertContains($orgToOrgReverseType, $result['values']);

$result = civicrm_api3('Relationship', 'getoptions', [
'field' => 'relationship_type_id',
'is_form' => TRUE,
'contact_type' => 'Individual',
]);

$this->assertNotContains($orgToOrgType, $result['values']);
$this->assertNotContains($orgToOrgReverseType, $result['values']);
}

public function testContactIdAndRelationshipIdWillBeUsedInFilter() {
Expand Down Expand Up @@ -109,30 +113,34 @@ public function testContactIdAndRelationshipIdWillBeUsedInFilter() {
'relationship_type_id' => $orgToPersonTypeId,
]);

$options = CRM_Contact_BAO_Relationship::buildRelationshipTypeOptions([
$options = civicrm_api3('Relationship', 'getoptions', [
'field' => 'relationship_type_id',
'is_form' => TRUE,
'relationship_id' => (string) $relationship['id'],
'contact_id' => $individual['id'],
]);

// for this relationship only individual=>organization is possible
$this->assertContains($personToOrgType, $options);
$this->assertNotContains($orgToPersonType, $options);
$this->assertContains($personToOrgType, $options['values']);
$this->assertNotContains($orgToPersonType, $options['values']);

// by passing relationship ID we know that the "B" side is an organization
$this->assertNotContains($personToPersonType, $options);
$this->assertNotContains($personToPersonReverseType, $options);
$this->assertNotContains($personToPersonType, $options['values']);
$this->assertNotContains($personToPersonReverseType, $options['values']);

$options = CRM_Contact_BAO_Relationship::buildRelationshipTypeOptions([
$options = civicrm_api3('Relationship', 'getoptions', [
'field' => 'relationship_type_id',
'is_form' => TRUE,
'contact_id' => $individual['id'],
]);

// for this result we only know that "A" must be an individual
$this->assertContains($personToOrgType, $options);
$this->assertNotContains($orgToPersonType, $options);
$this->assertContains($personToOrgType, $options['values']);
$this->assertNotContains($orgToPersonType, $options['values']);

// unlike when we pass relationship type ID there is no filter by "B" type
$this->assertContains($personToPersonType, $options);
$this->assertContains($personToPersonReverseType, $options);
$this->assertContains($personToPersonType, $options['values']);
$this->assertContains($personToPersonReverseType, $options['values']);
}

/**
Expand Down
8 changes: 7 additions & 1 deletion xml/schema/Contact/Relationship.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,17 @@
<type>int unsigned</type>
<title>Relationship Type</title>
<required>true</required>
<comment>id of the relationship</comment>
<comment>Type of relationship</comment>
<add>1.1</add>
<html>
<type>Select</type>
</html>
<pseudoconstant>
<table>civicrm_relationship_type</table>
<keyColumn>id</keyColumn>
<nameColumn>name_a_b</nameColumn>
<labelColumn>label_a_b</labelColumn>
</pseudoconstant>
</field>
<foreignKey>
<name>relationship_type_id</name>
Expand Down

0 comments on commit 1ac9bb5

Please sign in to comment.