Merge pull request #15720 from eileenmcnaughton/test_clean
[civicrm-core.git] / tests / phpunit / CRM / Contact / BAO / RelationshipTest.php
CommitLineData
02e028a0
AS
1<?php
2/*
3 +--------------------------------------------------------------------+
2fe49090 4 | CiviCRM version 5 |
02e028a0 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
02e028a0
AS
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28/**
29 * Test class for CRM_Contact_BAO_Relationship
30 *
31 * @package CiviCRM
32 * @group headless
33 */
34class CRM_Contact_BAO_RelationshipTest extends CiviUnitTestCase {
35
36 /**
37 * Sets up the fixture, for example, opens a network connection.
38 *
39 * This method is called before a test is executed.
40 */
41 protected function setUp() {
42 parent::setUp();
43 }
44
45 /**
46 * Tears down the fixture, for example, closes a network connection.
47 *
48 * This method is called after a test is executed.
310c2031 49 *
50 * @throws \CRM_Core_Exception
02e028a0
AS
51 */
52 protected function tearDown() {
89e45979
MD
53 $this->quickCleanup([
54 'civicrm_relationship_type',
55 'civicrm_relationship',
39b959db 56 'civicrm_contact',
89e45979
MD
57 ]);
58
02e028a0
AS
59 parent::tearDown();
60 }
61
310c2031 62 /**
63 * Test Relationship Type Options Will Return Specified Type
64 *
65 * @throws \CRM_Core_Exception
66 */
89e45979
MD
67 public function testRelationshipTypeOptionsWillReturnSpecifiedType() {
68 $orgToOrgType = 'A_B_relationship';
69 $orgToOrgReverseType = 'B_A_relationship';
310c2031 70 $this->callAPISuccess('RelationshipType', 'create', [
89e45979
MD
71 'name_a_b' => $orgToOrgType,
72 'name_b_a' => $orgToOrgReverseType,
73 'contact_type_a' => 'Organization',
74 'contact_type_b' => 'Organization',
75 ]);
76
77 $result = CRM_Contact_BAO_Relationship::buildRelationshipTypeOptions(
78 ['contact_type' => 'Organization']
79 );
80 $this->assertContains($orgToOrgType, $result);
81 $this->assertContains($orgToOrgReverseType, $result);
82
83 $result = CRM_Contact_BAO_Relationship::buildRelationshipTypeOptions(
84 ['contact_type' => 'Individual']
85 );
86
87 $this->assertNotContains($orgToOrgType, $result);
88 $this->assertNotContains($orgToOrgReverseType, $result);
89 }
90
91 public function testContactIdAndRelationshipIdWillBeUsedInFilter() {
92 $individual = civicrm_api3('Contact', 'create', [
93 'display_name' => 'Individual A',
94 'contact_type' => 'Individual',
95 ]);
96 $organization = civicrm_api3('Contact', 'create', [
97 'organization_name' => 'Organization B',
98 'contact_type' => 'Organization',
99 ]);
100
101 $personToOrgType = 'A_B_relationship';
102 $orgToPersonType = 'B_A_relationship';
103
104 $orgToPersonTypeId = civicrm_api3('RelationshipType', 'create', [
105 'name_a_b' => $personToOrgType,
106 'name_b_a' => $orgToPersonType,
107 'contact_type_a' => 'Individual',
108 'contact_type_b' => 'Organization',
109 ])['id'];
110
111 $personToPersonType = 'A_B_alt_relationship';
112 $personToPersonReverseType = 'B_A_alt_relationship';
113
114 civicrm_api3('RelationshipType', 'create', [
115 'name_a_b' => $personToPersonType,
116 'name_b_a' => $personToPersonReverseType,
117 'contact_type_a' => 'Individual',
118 'contact_type_b' => 'Individual',
119 ]);
120
121 // create a relationship individual => organization
122 $relationship = civicrm_api3('Relationship', 'create', [
123 'contact_id_a' => $individual['id'],
124 'contact_id_b' => $organization['id'],
125 'relationship_type_id' => $orgToPersonTypeId,
126 ]);
127
128 $options = CRM_Contact_BAO_Relationship::buildRelationshipTypeOptions([
129 'relationship_id' => (string) $relationship['id'],
39b959db 130 'contact_id' => $individual['id'],
89e45979
MD
131 ]);
132
133 // for this relationship only individual=>organization is possible
134 $this->assertContains($personToOrgType, $options);
135 $this->assertNotContains($orgToPersonType, $options);
136
137 // by passing relationship ID we know that the "B" side is an organization
138 $this->assertNotContains($personToPersonType, $options);
139 $this->assertNotContains($personToPersonReverseType, $options);
140
141 $options = CRM_Contact_BAO_Relationship::buildRelationshipTypeOptions([
39b959db 142 'contact_id' => $individual['id'],
89e45979
MD
143 ]);
144
145 // for this result we only know that "A" must be an individual
146 $this->assertContains($personToOrgType, $options);
147 $this->assertNotContains($orgToPersonType, $options);
148
149 // unlike when we pass relationship type ID there is no filter by "B" type
150 $this->assertContains($personToPersonType, $options);
151 $this->assertContains($personToPersonReverseType, $options);
152 }
153
02e028a0
AS
154 /**
155 * Test removeRelationshipTypeDuplicates method.
156 *
157 * @dataProvider getRelationshipTypeDuplicates
158 */
159 public function testRemoveRelationshipTypeDuplicates($relationshipTypeList, $suffix = NULL, $expected, $description) {
160 $result = CRM_Contact_BAO_Relationship::removeRelationshipTypeDuplicates($relationshipTypeList, $suffix);
161 $this->assertEquals($expected, $result, "Failure on set '$description'");
162 }
163
164 public function getRelationshipTypeDuplicates() {
9099cab3 165 $relationshipTypeList = [
02e028a0
AS
166 '1_a_b' => 'duplicate one',
167 '1_b_a' => 'duplicate one',
168 '2_a_b' => 'two a',
169 '2_b_a' => 'two b',
9099cab3
CW
170 ];
171 $data = [
172 [
02e028a0
AS
173 $relationshipTypeList,
174 'a_b',
9099cab3 175 [
02e028a0
AS
176 '1_a_b' => 'duplicate one',
177 '2_a_b' => 'two a',
178 '2_b_a' => 'two b',
9099cab3 179 ],
02e028a0 180 'With suffix a_b',
9099cab3
CW
181 ],
182 [
02e028a0
AS
183 $relationshipTypeList,
184 'b_a',
9099cab3 185 [
02e028a0
AS
186 '1_b_a' => 'duplicate one',
187 '2_a_b' => 'two a',
188 '2_b_a' => 'two b',
9099cab3 189 ],
02e028a0 190 'With suffix b_a',
9099cab3
CW
191 ],
192 [
02e028a0
AS
193 $relationshipTypeList,
194 NULL,
9099cab3 195 [
02e028a0
AS
196 '1_a_b' => 'duplicate one',
197 '2_a_b' => 'two a',
198 '2_b_a' => 'two b',
9099cab3 199 ],
02e028a0 200 'With suffix NULL',
9099cab3
CW
201 ],
202 [
02e028a0
AS
203 $relationshipTypeList,
204 NULL,
9099cab3 205 [
02e028a0
AS
206 '1_a_b' => 'duplicate one',
207 '2_a_b' => 'two a',
208 '2_b_a' => 'two b',
9099cab3 209 ],
02e028a0 210 'With suffix "" (empty string)',
9099cab3
CW
211 ],
212 ];
02e028a0
AS
213 return $data;
214 }
215
96c40ac7 216 /**
217 * Test that two similar memberships are not created for two relationships
218 *
219 * @throws \CRM_Core_Exception
220 */
221 public function testSingleMembershipForTwoRelationships() {
222 $individualID = $this->individualCreate(['display_name' => 'Individual A']);
223 $organisationID = $this->organizationCreate(['organization_name' => 'Organization B']);
224 $membershipOrganisationID = $this->organizationCreate(['organization_name' => 'Membership Organization']);
225 $orgToPersonTypeId1 = $this->relationshipTypeCreate(['name_a_b' => 'Inherited_Relationship_1_A_B', 'name_b_a' => 'Inherited_Relationship_1_B_A']);
226 $orgToPersonTypeId2 = $this->relationshipTypeCreate(['name_a_b' => 'Inherited_Relationship_2_A_B', 'name_b_a' => 'Inherited_Relationship_2_B_A']);
227
228 $membershipType = $this->callAPISuccess('MembershipType', 'create', [
229 'member_of_contact_id' => $membershipOrganisationID,
230 'financial_type_id' => 'Member Dues',
231 'duration_unit' => 'year',
232 'duration_interval' => 1,
233 'period_type' => 'rolling',
234 'name' => 'Inherited Membership',
235 'relationship_type_id' => [$orgToPersonTypeId1, $orgToPersonTypeId2],
236 'relationship_direction' => ['b_a', 'a_b'],
237 ]);
238 $membershipType = $this->callAPISuccessGetSingle('MembershipType', ['id' => $membershipType['id']]);
239 // Check the metadata worked....
240 $this->assertEquals([$orgToPersonTypeId1, $orgToPersonTypeId2], $membershipType['relationship_type_id']);
241 $this->assertEquals(['b_a', 'a_b'], $membershipType['relationship_direction']);
242
243 $this->callAPISuccess('Membership', 'create', [
244 'membership_type_id' => $membershipType['id'],
245 'contact_id' => $organisationID,
246 ]);
247
248 $relationshipOne = $this->callAPISuccess('Relationship', 'create', [
249 'contact_id_a' => $individualID,
250 'contact_id_b' => $organisationID,
251 'relationship_type_id' => $orgToPersonTypeId1,
252 ]);
253 $relationshipTwo = $this->callAPISuccess('Relationship', 'create', [
254 'contact_id_a' => $individualID,
255 'contact_id_b' => $organisationID,
256 'relationship_type_id' => $orgToPersonTypeId2,
257 ]);
258
98fd6fc8 259 $this->callAPISuccessGetCount('Membership', ['contact_id' => $individualID], 1);
0a2663fd 260 $this->callAPISuccessGetCount('Membership', ['contact_id' => $organisationID], 1);
310c2031 261 // Disable the relationship & check the membership is not removed because the other relationship is still valid.
98fd6fc8 262 $relationshipOne['is_active'] = 0;
263 $this->callAPISuccess('Relationship', 'create', array_merge($relationshipOne, ['is_active' => 0]));
310c2031 264 $this->callAPISuccessGetCount('Membership', ['contact_id' => $individualID], 1);
265
96c40ac7 266 $relationshipTwo['is_active'] = 0;
267 $this->callAPISuccess('Relationship', 'create', $relationshipTwo);
310c2031 268 $this->callAPISuccessGetCount('Membership', ['contact_id' => $individualID], 0);
98fd6fc8 269
96c40ac7 270 $relationshipOne['is_active'] = 1;
271 $this->callAPISuccess('Relationship', 'create', $relationshipOne);
272 $this->callAPISuccessGetCount('Membership', ['contact_id' => $individualID], 1);
310c2031 273
274 /*
275 * @todo this section not yet working due to bug in would-be-tested code.
96c40ac7 276 $relationshipTwo['is_active'] = 1;
277 $this->callAPISuccess('Relationship', 'create', $relationshipTwo);
278 $this->callAPISuccessGetCount('Membership', ['contact_id' => $individualID], 1);
279 $this->callAPISuccess('Relationship', 'delete', ['id' => $relationshipTwo['id']]);
280 $this->callAPISuccessGetCount('Membership', ['contact_id' => $individualID], 1);
281 $this->callAPISuccess('Relationship', 'delete', ['id' => $relationshipOne['id']]);
282 $this->callAPISuccessGetCount('Membership', ['contact_id' => $individualID], 0);
283 */
284 }
285
0d65e601
D
286 /**
287 * Test CRM_Contact_BAO_Relationship::add() function directly.
288 *
289 * In general it's preferred to use the Relationship-create api since it does
290 * checks and such before calling add(). There are already some good tests
291 * for the api, but since it does some more business logic after too the
292 * tests might not be checking exactly the same thing.
293 */
294 public function testBAOAdd() {
295 // add a new type
296 $relationship_type_id_1 = $this->relationshipTypeCreate([
297 'name_a_b' => 'Food poison tester is',
298 'name_b_a' => 'Food poison tester for',
299 'contact_type_a' => 'Individual',
300 'contact_type_b' => 'Individual',
301 ]);
302
303 // add some people
304 $contact_id_1 = $this->individualCreate();
305 $contact_id_2 = $this->individualCreate([], 1);
306
307 // create new relationship (using BAO)
308 $params = [
309 'relationship_type_id' => $relationship_type_id_1,
310 'contact_id_a' => $contact_id_1,
311 'contact_id_b' => $contact_id_2,
312 ];
313 $relationshipObj = CRM_Contact_BAO_Relationship::add($params);
314 $this->assertEquals($relationshipObj->relationship_type_id, $relationship_type_id_1);
315 $this->assertEquals($relationshipObj->contact_id_a, $contact_id_1);
316 $this->assertEquals($relationshipObj->contact_id_b, $contact_id_2);
317 $this->assertEquals($relationshipObj->is_active, 1);
318
319 // demonstrate PR 15103 - should fail before the patch and pass after
320 $today = date('Ymd');
321 $params = [
322 'id' => $relationshipObj->id,
323 'end_date' => $today,
324 ];
325 $relationshipObj = CRM_Contact_BAO_Relationship::add($params);
326 $this->assertEquals($relationshipObj->relationship_type_id, $relationship_type_id_1);
327 $this->assertEquals($relationshipObj->contact_id_a, $contact_id_1);
328 $this->assertEquals($relationshipObj->contact_id_b, $contact_id_2);
329 $this->assertEquals($relationshipObj->is_active, 1);
330 $this->assertEquals($relationshipObj->end_date, $today);
331 }
332
02e028a0 333}