From 0a2663fd3c29cce0de5ead3a4eab9626585d9476 Mon Sep 17 00:00:00 2001 From: eileen Date: Fri, 23 Aug 2019 14:43:17 +1200 Subject: [PATCH] Make sure inherited memberships are not themselves inherited In trying to make sense of the code / fix / test for https://github.com/civicrm/civicrm-core/pull/15062 I discovered the tests wouldn't pass due to a weird edge case where an individual inherited a membership and that membership was inherited in turn via a relationship the individual had (with the same organization) I don't believe that inheriting inherited memberships is an intentional feature & it DOEs cause issues - this removes that possibility --- CRM/Contact/BAO/Relationship.php | 13 ++++++++++++- tests/phpunit/CRM/Contact/BAO/RelationshipTest.php | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CRM/Contact/BAO/Relationship.php b/CRM/Contact/BAO/Relationship.php index be1fc626b1..b210da587a 100644 --- a/CRM/Contact/BAO/Relationship.php +++ b/CRM/Contact/BAO/Relationship.php @@ -1535,6 +1535,7 @@ LEFT JOIN civicrm_country ON (civicrm_address.country_id = civicrm_country.id) * @param bool $active * * @throws \CRM_Core_Exception + * @throws \CiviCRM_API3_Exception */ public static function relatedMemberships($contactId, &$params, $ids, $action = CRM_Core_Action::ADD, $active = TRUE) { // Check the end date and set the status of the relationship @@ -1691,6 +1692,12 @@ LEFT JOIN civicrm_country ON (civicrm_address.country_id = civicrm_country.id) $mainRelatedContactId = reset($relatedContacts); foreach ($details['memberships'] as $membershipId => $membershipValues) { + $membershipInherittedFromContactID = NULL; + if (!empty($membershipValues['owner_membership_id'])) { + // Use get not getsingle so that we get e-notice noise but not a fatal is the membership has already been deleted. + $inheritedFromMembership = civicrm_api3('Membership', 'get', ['id' => $membershipValues['owner_membership_id'], 'sequential' => 1])['values'][0]; + $membershipInherittedFromContactID = (int) $inheritedFromMembership['contact_id']; + } $relTypeIds = []; if ($action & CRM_Core_Action::DELETE) { // @todo don't return relTypeId here - but it seems to be used later in a cryptic way (hint cryptic is not a complement). @@ -1769,7 +1776,11 @@ LEFT JOIN civicrm_country ON (civicrm_address.country_id = civicrm_country.id) if (!empty($membershipValues['status_id']) && $membershipValues['status_id'] == $pendingStatusId) { $membershipValues['skipStatusCal'] = TRUE; } - $membershipValues = self::addInheritedMembership($membershipValues); + // As long as the membership itself was not created by inheritance from the same contact + // that stands to inherit the membership we add an inherited membership. + if ($membershipInherittedFromContactID !== (int) $membershipValues['contact_id']) { + $membershipValues = self::addInheritedMembership($membershipValues); + } } } elseif ($action & CRM_Core_Action::UPDATE) { diff --git a/tests/phpunit/CRM/Contact/BAO/RelationshipTest.php b/tests/phpunit/CRM/Contact/BAO/RelationshipTest.php index 63722d030f..dde4de9d7f 100644 --- a/tests/phpunit/CRM/Contact/BAO/RelationshipTest.php +++ b/tests/phpunit/CRM/Contact/BAO/RelationshipTest.php @@ -250,7 +250,7 @@ class CRM_Contact_BAO_RelationshipTest extends CiviUnitTestCase { ]); $this->callAPISuccessGetCount('Membership', ['contact_id' => $individualID], 1); - + $this->callAPISuccessGetCount('Membership', ['contact_id' => $organisationID], 1); // Disable the relationship & check the membership is removed. $relationshipOne['is_active'] = 0; $this->callAPISuccess('Relationship', 'create', array_merge($relationshipOne, ['is_active' => 0])); -- 2.25.1