3 * +--------------------------------------------------------------------+
4 * | CiviCRM version 5 |
5 * +--------------------------------------------------------------------+
6 * | Copyright CiviCRM LLC (c) 2004-2019 |
7 * +--------------------------------------------------------------------+
8 * | This file is a part of CiviCRM. |
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. |
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. |
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 * +--------------------------------------------------------------------+
29 * Class contains api test cases for "civicrm_relationship"
32 class api_v3_RelationshipTest
extends CiviUnitTestCase
{
34 use CRMTraits_Custom_CustomDataTrait
;
45 * Second organization contact.
50 protected $_relTypeID;
52 protected $_customFieldId = NULL;
60 public function setUp() {
62 $this->_cId_a
= $this->individualCreate();
63 $this->_cId_a_2
= $this->individualCreate([
66 'contact_type' => 'Individual',
68 $this->_cId_b
= $this->organizationCreate();
69 $this->_cId_b2
= $this->organizationCreate(['organization_name' => ' Org 2']);
70 $this->entity
= 'Relationship';
71 //Create a relationship type.
73 'name_a_b' => 'Relation 1 for delete',
74 'name_b_a' => 'Relation 2 for delete',
75 'description' => 'Testing relationship type',
76 'contact_type_a' => 'Individual',
77 'contact_type_b' => 'Organization',
82 $this->_relTypeID
= $this->relationshipTypeCreate($relTypeParams);
84 'contact_id_a' => $this->_cId_a
,
85 'contact_id_b' => $this->_cId_b
,
86 'relationship_type_id' => $this->_relTypeID
,
87 'start_date' => '2008-12-20',
98 public function tearDown() {
99 $this->contactDelete($this->_cId_a
);
100 $this->contactDelete($this->_cId_a_2
);
101 $this->contactDelete($this->_cId_b
);
102 $this->contactDelete($this->_cId_b2
);
103 $this->quickCleanup(['civicrm_relationship'], TRUE);
104 $this->relationshipTypeDelete($this->_relTypeID
);
109 * Check with empty array.
110 * @param int $version
111 * @dataProvider versionThreeAndFour
113 public function testRelationshipCreateEmpty($version) {
114 $this->_apiversion
= $version;
115 $this->callAPIFailure('relationship', 'create', []);
119 * Test Current Employer is correctly set.
121 * @throws \CRM_Core_Exception
123 public function testCurrentEmployerRelationship() {
124 $employerRelationshipID = $this->callAPISuccessGetValue('RelationshipType', [
126 'name_b_a' => 'Employer Of',
128 $employerRelationship = $this->callAPISuccess('Relationship', 'create', [
129 'contact_id_a' => $this->_cId_a
,
130 'contact_id_b' => $this->_cId_b
,
131 'relationship_type_id' => $employerRelationshipID,
132 'is_current_employer' => 1,
135 //Check if current employer is correctly set.
136 $employer = $this->callAPISuccessGetValue('Contact', [
137 'return' => 'current_employer',
138 'id' => $this->_cId_a
,
140 $organisation = $this->callAPISuccessGetValue('Contact', [
141 'return' => "sort_name",
142 'id' => $this->_cId_b
,
144 $this->assertEquals($employer, $organisation);
146 //Update relationship type
147 $update = $this->callAPISuccess('Relationship', 'create', [
148 'id' => $employerRelationship['id'],
149 'relationship_type_id' => $this->_relTypeID
,
151 $employeeContact = $this->callAPISuccessGetSingle('Contact', [
152 'return' => ['current_employer'],
153 'id' => $this->_cId_a
,
155 //current employer should be removed.
156 $this->assertEmpty($employeeContact['current_employer']);
160 * Check if required fields are not passed.
161 * @param int $version
162 * @dataProvider versionThreeAndFour
164 public function testRelationshipCreateWithoutRequired($version) {
165 $this->_apiversion
= $version;
167 'start_date' => ['d' => '10', 'M' => '1', 'Y' => '2008'],
168 'end_date' => ['d' => '10', 'M' => '1', 'Y' => '2009'],
172 $this->callAPIFailure('relationship', 'create', $params);
176 * Check with incorrect required fields.
177 * @param int $version
178 * @dataProvider versionThreeAndFour
180 public function testRelationshipCreateWithIncorrectData($version) {
181 $this->_apiversion
= $version;
184 'contact_id_a' => $this->_cId_a
,
185 'contact_id_b' => $this->_cId_b
,
186 'relationship_type_id' => 'Breaking Relationship',
189 $this->callAPIFailure('relationship', 'create', $params);
191 //contact id is not an integer
193 'contact_id_a' => 'invalid',
194 'contact_id_b' => $this->_cId_b
,
195 'relationship_type_id' => $this->_relTypeID
,
196 'start_date' => ['d' => '10', 'M' => '1', 'Y' => '2008'],
199 $this->callAPIFailure('relationship', 'create', $params);
201 // Contact id does not exist.
202 $params['contact_id_a'] = 999;
203 $this->callAPIFailure('relationship', 'create', $params);
206 $params['contact_id_a'] = $this->_cId_a
;
207 $params['start_date'] = ['d' => '1', 'M' => '1'];
208 $this->callAPIFailure('relationship', 'create', $params);
212 * Check relationship creation with invalid Relationship.
213 * @param int $version
214 * @dataProvider versionThreeAndFour
216 public function testRelationshipCreateInvalidRelationship($version) {
217 $this->_apiversion
= $version;
218 // Both have the contact type Individual.
220 'contact_id_a' => $this->_cId_a
,
221 'contact_id_b' => $this->_cId_a
,
222 'relationship_type_id' => $this->_relTypeID
,
223 'start_date' => '2008-01-10',
227 $this->callAPIFailure('relationship', 'create', $params);
229 // both the contact of type Organization
231 'contact_id_a' => $this->_cId_b
,
232 'contact_id_b' => $this->_cId_b
,
233 'relationship_type_id' => $this->_relTypeID
,
234 'start_date' => '2008-01-10',
238 $this->callAPIFailure('relationship', 'create', $params);
242 * Check relationship already exists.
243 * @param int $version
244 * @dataProvider versionThreeAndFour
246 public function testRelationshipCreateAlreadyExists($version) {
247 $this->_apiversion
= $version;
249 'contact_id_a' => $this->_cId_a
,
250 'contact_id_b' => $this->_cId_b
,
251 'relationship_type_id' => $this->_relTypeID
,
252 'start_date' => '2008-12-20',
256 $relationship = $this->callAPISuccess('relationship', 'create', $params);
259 'contact_id_a' => $this->_cId_a
,
260 'contact_id_b' => $this->_cId_b
,
261 'relationship_type_id' => $this->_relTypeID
,
262 'start_date' => '2008-12-20',
265 $this->callAPIFailure('relationship', 'create', $params, 'Duplicate Relationship');
267 $params['id'] = $relationship['id'];
268 $this->callAPISuccess('relationship', 'delete', $params);
272 * Check relationship already exists.
273 * @param int $version
274 * @dataProvider versionThreeAndFour
276 public function testRelationshipCreateUpdateAlreadyExists($version) {
277 $this->_apiversion
= $version;
279 'contact_id_a' => $this->_cId_a
,
280 'contact_id_b' => $this->_cId_b
,
281 'relationship_type_id' => $this->_relTypeID
,
282 'start_date' => '2008-12-20',
287 $relationship = $this->callAPISuccess('relationship', 'create', $params);
289 'id' => $relationship['id'],
293 $this->callAPISuccess('relationship', 'create', $params);
294 $this->callAPISuccess('relationship', 'get', $params);
295 $params['id'] = $relationship['id'];
296 $this->callAPISuccess('relationship', 'delete', $params);
300 * Check update doesn't reset stuff badly - CRM-11789.
301 * @param int $version
302 * @dataProvider versionThreeAndFour
304 public function testRelationshipCreateUpdateDoesNotMangle($version) {
305 $this->_apiversion
= $version;
307 'contact_id_a' => $this->_cId_a
,
308 'contact_id_b' => $this->_cId_b
,
309 'relationship_type_id' => $this->_relTypeID
,
310 'start_date' => '2008-12-20',
312 'is_permission_a_b' => 1,
313 'description' => 'my desc',
315 $relationship = $this->callAPISuccess('relationship', 'create', $params);
318 'id' => $relationship['id'],
319 'relationship_type_id' => $this->_relTypeID
,
321 $this->callAPISuccess('relationship', 'create', $updateParams);
323 //make sure the orig params didn't get changed
324 $this->getAndCheck($params, $relationship['id'], 'relationship');
329 * Check relationship creation.
330 * @param int $version
331 * @dataProvider versionThreeAndFour
333 public function testRelationshipCreate($version) {
334 $this->_apiversion
= $version;
336 'contact_id_a' => $this->_cId_a
,
337 'contact_id_b' => $this->_cId_b
,
338 'relationship_type_id' => $this->_relTypeID
,
339 'start_date' => '2010-10-30',
340 'end_date' => '2010-12-30',
345 $result = $this->callAPIAndDocument('relationship', 'create', $params, __FUNCTION__
, __FILE__
);
346 $this->assertNotNull($result['id']);
348 'id' => $result['id'],
351 // assertDBState compares expected values in $result to actual values in the DB
352 $this->assertDBState('CRM_Contact_DAO_Relationship', $result['id'], $relationParams);
353 $result = $this->callAPISuccess('relationship', 'get', ['id' => $result['id']]);
354 $values = $result['values'][$result['id']];
355 foreach ($params as $key => $value) {
356 if ($key == 'note') {
359 $this->assertEquals($value, $values[$key], $key . " doesn't match " . print_r($values, TRUE));
361 $params['id'] = $result['id'];
362 $this->callAPISuccess('relationship', 'delete', $params);
366 * Ensure disabling works.
367 * @param int $version
368 * @dataProvider versionThreeAndFour
370 public function testRelationshipUpdate($version) {
371 $this->_apiversion
= $version;
372 $result = $this->callAPISuccess('relationship', 'create', $this->_params
);
373 $relID = $result['id'];
374 $result = $this->callAPISuccess('relationship', 'create', ['id' => $relID, 'description' => 'blah']);
375 $this->assertEquals($relID, $result['id']);
377 $this->assertEquals('blah', $result['values'][$result['id']]['description']);
379 $result = $this->callAPISuccess('relationship', 'create', ['id' => $relID, 'is_permission_b_a' => 1]);
380 $this->assertEquals(1, $result['values'][$result['id']]['is_permission_b_a']);
381 $result = $this->callAPISuccess('relationship', 'create', ['id' => $result['id'], 'is_active' => 0]);
382 $result = $this->callAPISuccess('relationship', 'get', ['id' => $result['id']]);
383 $this->assertEquals(0, $result['values'][$result['id']]['is_active']);
384 $this->assertEquals('blah', $result['values'][$result['id']]['description']);
385 $this->assertEquals(1, $result['values'][$result['id']]['is_permission_b_a']);
389 * Check relationship creation.
390 * @param int $version
391 * @dataProvider versionThreeAndFour
393 public function testRelationshipCreateEmptyEndDate($version) {
394 $this->_apiversion
= $version;
396 'contact_id_a' => $this->_cId_a
,
397 'contact_id_b' => $this->_cId_b
,
398 'relationship_type_id' => $this->_relTypeID
,
399 'start_date' => '2010-10-30',
405 $result = $this->callAPISuccess('relationship', 'create', $params);
406 $this->assertNotNull($result['id']);
408 'id' => $result['id'],
411 // assertDBState compares expected values in $result to actual values in the DB
412 $this->assertDBState('CRM_Contact_DAO_Relationship', $result['id'], $relationParams);
413 $result = $this->callAPISuccess('relationship', 'get', ['id' => $result['id']]);
414 $values = $result['values'][$result['id']];
415 foreach ($params as $key => $value) {
416 if ($key == 'note') {
419 if ($key == 'end_date') {
420 $this->assertTrue(empty($values[$key]));
423 $this->assertEquals($value, $values[$key], $key . " doesn't match " . print_r($values, TRUE) . 'in line' . __LINE__
);
425 $params['id'] = $result['id'];
426 $this->callAPISuccess('relationship', 'delete', $params);
430 * Check relationship creation with custom data.
433 public function testRelationshipCreateEditWithCustomData() {
434 $this->createCustomGroupWithFieldsOfAllTypes();
435 //few custom Values for comparing
437 $this->getCustomFieldName('text') => 'Hello! this is custom data for relationship',
438 $this->getCustomFieldName('select_string') => 'Y',
439 $this->getCustomFieldName('select_date') => '2009-07-11 00:00:00',
440 $this->getCustomFieldName('link') => 'http://example.com',
444 'contact_id_a' => $this->_cId_a
,
445 'contact_id_b' => $this->_cId_b
,
446 'relationship_type_id' => $this->_relTypeID
,
447 'start_date' => '2008-12-20',
450 $params = array_merge($params, $custom_params);
451 $result = $this->callAPISuccess('relationship', 'create', $params);
453 $relationParams = ['id' => $result['id']];
454 $this->assertDBState('CRM_Contact_DAO_Relationship', $result['id'], $relationParams);
456 //Test Edit of custom field from the form.
457 $getParams = ['id' => $result['id']];
458 $updateParams = array_merge($getParams, [
459 $this->getCustomFieldName('text') => 'Edited Text Value',
460 'relationship_type_id' => $this->_relTypeID
. '_b_a',
461 'related_contact_id' => $this->_cId_a
,
463 $reln = new CRM_Contact_Form_Relationship();
464 $reln->_action
= CRM_Core_Action
::UPDATE
;
465 $reln->_relationshipId
= $result['id'];
466 $reln->submit($updateParams);
468 $check = $this->callAPISuccess('relationship', 'get', $getParams);
469 $this->assertEquals("Edited Text Value", $check['values'][$check['id']][$this->getCustomFieldName('text')]);
471 $params['id'] = $result['id'];
472 $this->callAPISuccess('relationship', 'delete', $params);
473 $this->relationshipTypeDelete($this->_relTypeID
);
477 * Check with complete array + custom field
478 * Note that the test is written on purpose without any
479 * variables specific to participant so it can be replicated into other entities
480 * and / or moved to the automated test suite
483 public function testGetWithCustom() {
484 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
486 $params = $this->_params
;
487 $params['custom_' . $ids['custom_field_id']] = "custom string";
489 $result = $this->callAPISuccess($this->entity
, 'create', $params);
490 $this->assertEquals($result['id'], $result['values'][$result['id']]['id']);
492 $getParams = ['id' => $result['id']];
493 $check = $this->callAPIAndDocument($this->entity
, 'get', $getParams, __FUNCTION__
, __FILE__
);
494 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__
);
496 $this->customFieldDelete($ids['custom_field_id']);
497 $this->customGroupDelete($ids['custom_group_id']);
501 * Check if required fields are not passed.
502 * @param int $version
503 * @dataProvider versionThreeAndFour
505 public function testRelationshipDeleteWithoutRequired($version) {
506 $this->_apiversion
= $version;
508 'start_date' => '2008-12-20',
509 'end_date' => '2009-12-20',
513 $this->callAPIFailure('relationship', 'delete', $params);
517 * Check with incorrect required fields.
519 public function testRelationshipDeleteWithIncorrectData() {
521 'contact_id_a' => $this->_cId_a
,
522 'contact_id_b' => $this->_cId_b
,
523 'relationship_type_id' => 'Breaking Relationship',
526 $this->callAPIFailure('relationship', 'delete', $params, 'Mandatory key(s) missing from params array: id');
528 $params['id'] = "Invalid";
529 $this->callAPIFailure('relationship', 'delete', $params, 'id is not a valid integer');
533 * Check relationship creation.
534 * @param int $version
535 * @dataProvider versionThreeAndFour
537 public function testRelationshipDelete($version) {
538 $this->_apiversion
= $version;
540 'contact_id_a' => $this->_cId_a
,
541 'contact_id_b' => $this->_cId_b
,
542 'relationship_type_id' => $this->_relTypeID
,
543 'start_date' => '2008-12-20',
547 $result = $this->callAPISuccess('relationship', 'create', $params);
548 $params = ['id' => $result['id']];
549 $this->callAPIAndDocument('relationship', 'delete', $params, __FUNCTION__
, __FILE__
);
550 $this->relationshipTypeDelete($this->_relTypeID
);
553 ///////////////// civicrm_relationship_update methods
556 * Check with empty array.
557 * @param int $version
558 * @dataProvider versionThreeAndFour
560 public function testRelationshipUpdateEmpty($version) {
561 $this->_apiversion
= $version;
562 $this->callAPIFailure('relationship', 'create', [],
563 'contact_id_a, contact_id_b, relationship_type_id');
567 * Check if required fields are not passed.
571 * Check relationship update.
572 * @param int $version
573 * @dataProvider versionThreeAndFour
575 public function testRelationshipCreateDuplicate($version) {
576 $this->_apiversion
= $version;
578 'contact_id_a' => $this->_cId_a
,
579 'contact_id_b' => $this->_cId_b
,
580 'relationship_type_id' => $this->_relTypeID
,
581 'start_date' => '20081214',
582 'end_date' => '20091214',
586 $result = $this->callAPISuccess('relationship', 'create', $relParams);
588 $this->assertNotNull($result['id']);
591 'contact_id_a' => $this->_cId_a
,
592 'contact_id_b' => $this->_cId_b
,
593 'relationship_type_id' => $this->_relTypeID
,
594 'start_date' => '20081214',
595 'end_date' => '20091214',
599 $this->callAPIFailure('relationship', 'create', $params, 'Duplicate Relationship');
601 $this->callAPISuccess('relationship', 'delete', ['id' => $result['id']]);
602 $this->relationshipTypeDelete($this->_relTypeID
);
606 * CRM-13725 - Two relationships of same type with same start and end date
607 * should be OK if the custom field values differ.
610 public function testRelationshipCreateDuplicateWithCustomFields() {
611 $this->createCustomGroupWithFieldsOfAllTypes();
614 $this->getCustomFieldName('text') => 'Hello! this is custom data for relationship',
615 $this->getCustomFieldName('select_string') => 'Y',
616 $this->getCustomFieldName('select_date') => '2009-07-11 00:00:00',
617 $this->getCustomFieldName('link') => 'http://example.com',
621 $this->getCustomFieldName('text') => 'Hello! this is other custom data',
622 $this->getCustomFieldName('select_string') => 'Y',
623 $this->getCustomFieldName('select_date') => '2009-07-11 00:00:00',
624 $this->getCustomFieldName('link') => 'http://example.org',
628 'contact_id_a' => $this->_cId_a
,
629 'contact_id_b' => $this->_cId_b
,
630 'relationship_type_id' => $this->_relTypeID
,
631 'start_date' => '2008-12-20',
635 $params_1 = array_merge($params, $custom_params_1);
636 $params_2 = array_merge($params, $custom_params_2);
638 $result_1 = $this->callAPISuccess('relationship', 'create', $params_1);
639 $result_2 = $this->callAPISuccess('relationship', 'create', $params_2);
641 $this->assertNotNull($result_2['id']);
642 $this->assertEquals(0, $result_2['is_error']);
644 $this->relationshipTypeDelete($this->_relTypeID
);
648 * CRM-13725 - Two relationships of same type with same start and end date
649 * should be OK if the custom field values differ. In this case, the
650 * existing relationship does not have custom values, but the new one
654 public function testRelationshipCreateDuplicateWithCustomFields2() {
655 $this->createCustomGroupWithFieldsOfAllTypes();
658 $this->getCustomFieldName('text') => 'Hello! this is other custom data',
659 $this->getCustomFieldName('select_string') => 'Y',
660 $this->getCustomFieldName('select_date') => '2009-07-11 00:00:00',
661 $this->getCustomFieldName('link') => 'http://example.org',
665 'contact_id_a' => $this->_cId_a
,
666 'contact_id_b' => $this->_cId_b
,
667 'relationship_type_id' => $this->_relTypeID
,
668 'start_date' => '2008-12-20',
672 $params_2 = array_merge($params_1, $custom_params_2);
674 $this->callAPISuccess('relationship', 'create', $params_1);
675 $result_2 = $this->callAPISuccess('relationship', 'create', $params_2);
677 $this->assertNotNull($result_2['id']);
678 $this->assertEquals(0, $result_2['is_error']);
680 $this->relationshipTypeDelete($this->_relTypeID
);
684 * CRM-13725 - Two relationships of same type with same start and end date
685 * should be OK if the custom field values differ. In this case, the
686 * existing relationship does have custom values, but the new one
690 public function testRelationshipCreateDuplicateWithCustomFields3() {
691 $this->createCustomGroupWithFieldsOfAllTypes();
694 $this->getCustomFieldName('text') => 'Hello! this is other custom data',
695 $this->getCustomFieldName('select_string') => 'Y',
696 $this->getCustomFieldName('select_date') => '2009-07-11 00:00:00',
697 $this->getCustomFieldName('link') => 'http://example.org',
701 'contact_id_a' => $this->_cId_a
,
702 'contact_id_b' => $this->_cId_b
,
703 'relationship_type_id' => $this->_relTypeID
,
704 'start_date' => '2008-12-20',
708 $params_1 = array_merge($params_2, $custom_params_1);
710 $this->callAPISuccess('relationship', 'create', $params_1);
711 $result_2 = $this->callAPISuccess('relationship', 'create', $params_2);
713 $this->assertNotNull($result_2['id']);
714 $this->assertEquals(0, $result_2['is_error']);
716 $this->relationshipTypeDelete($this->_relTypeID
);
720 * Check with valid params array.
722 public function testRelationshipsGet() {
724 'contact_id_a' => $this->_cId_a
,
725 'contact_id_b' => $this->_cId_b
,
726 'relationship_type_id' => $this->_relTypeID
,
727 'start_date' => '2011-01-01',
728 'end_date' => '2013-01-01',
732 $this->callAPISuccess('relationship', 'create', $relParams);
736 'contact_id' => $this->_cId_b
,
738 $result = $this->callAPISuccess('relationship', 'get', $params);
739 $this->assertEquals($result['count'], 1);
741 'contact_id_a' => $this->_cId_a
,
743 $result = $this->callAPISuccess('relationship', 'get', $params);
744 $this->assertEquals($result['count'], 1);
745 // contact_id_a is wrong so should be no matches
747 'contact_id_a' => $this->_cId_b
,
749 $result = $this->callAPISuccess('relationship', 'get', $params);
750 $this->assertEquals($result['count'], 0);
754 * Chain Relationship.get and to Contact.get.
755 * @param int $version
756 * @dataProvider versionThreeAndFour
758 public function testRelationshipGetWithChainedCall($version) {
759 $this->_apiversion
= $version;
760 // Create a relationship.
761 $createResult = $this->callAPISuccess('relationship', 'create', $this->_params
);
762 $id = $createResult['id'];
764 // Try to retrieve it using chaining.
766 'relationship_type_id' => $this->_relTypeID
,
768 'api.Contact.get' => [
769 'id' => '$value.contact_id_b',
773 $result = $this->callAPISuccess('relationship', 'get', $params);
775 $this->assertEquals(1, $result['count']);
776 $relationship = CRM_Utils_Array
::first($result['values']);
777 $this->assertEquals(1, $relationship['api.Contact.get']['count']);
778 $contact = CRM_Utils_Array
::first($relationship['api.Contact.get']['values']);
779 $this->assertEquals($this->_cId_b
, $contact['id']);
783 * Chain Contact.get to Relationship.get and again to Contact.get.
784 * @param int $version
785 * @dataProvider versionThreeAndFour
787 public function testRelationshipGetInChainedCall($version) {
788 $this->_apiversion
= $version;
789 // Create a relationship.
790 $this->callAPISuccess('relationship', 'create', $this->_params
);
792 // Try to retrieve it using chaining.
794 'id' => $this->_cId_a
,
795 'api.Relationship.get' => [
796 'relationship_type_id' => $this->_relTypeID
,
797 'contact_id_a' => '$value.id',
798 'api.Contact.get' => [
799 'id' => '$value.contact_id_b',
804 $result = $this->callAPISuccess('contact', 'get', $params);
805 $this->assertEquals(1, $result['count']);
806 $contact = CRM_Utils_Array
::first($result['values']);
807 $this->assertEquals(1, $contact['api.Relationship.get']['count']);
808 $relationship = CRM_Utils_Array
::first($contact['api.Relationship.get']['values']);
809 $this->assertEquals(1, $relationship['api.Contact.get']['count']);
810 $contact = CRM_Utils_Array
::first($relationship['api.Contact.get']['values']);
811 $this->assertEquals($this->_cId_b
, $contact['id']);
815 * Check with valid params array.
816 * (The get function will behave differently without 'contact_id' passed
817 * @param int $version
818 * @dataProvider versionThreeAndFour
820 public function testRelationshipsGetGeneric($version) {
821 $this->_apiversion
= $version;
823 'contact_id_a' => $this->_cId_a
,
824 'contact_id_b' => $this->_cId_b
,
825 'relationship_type_id' => $this->_relTypeID
,
826 'start_date' => '2011-01-01',
827 'end_date' => '2013-01-01',
831 $this->callAPISuccess('relationship', 'create', $relParams);
835 'contact_id_b' => $this->_cId_b
,
837 $this->callAPISuccess('relationship', 'get', $params);
841 * Test retrieving only current relationships.
842 * @param int $version
843 * @dataProvider versionThreeAndFour
845 public function testGetIsCurrent($version) {
846 $this->_apiversion
= $version;
848 'contact_id_a' => $this->_cId_a
,
849 'contact_id_b' => $this->_cId_b2
,
850 'relationship_type_id' => $this->_relTypeID
,
851 'start_date' => '2008-12-20',
854 $rel0 = $this->callAPISuccess('relationship', 'create', $rel2Params);
855 $rel1 = $this->callAPISuccess('relationship', 'create', $this->_params
);
857 $getParams = ['filters' => ['is_current' => 1]];
858 $description = "Demonstrates is_current filter.";
859 $subfile = 'filterIsCurrent';
860 $result = $this->callAPIAndDocument('relationship', 'get', $getParams, __FUNCTION__
, __FILE__
, $description, $subfile);
861 $this->assertEquals($result['count'], 1);
862 $this->AssertEquals($rel1['id'], $result['id']);
864 // now try not started
865 $rel2Params['is_active'] = 1;
866 $rel2Params['start_date'] = 'tomorrow';
867 $rel2 = $this->callAPISuccess('relationship', 'create', $rel2Params);
870 $rel2Params['start_date'] = 'last week';
871 $rel2Params['end_date'] = 'yesterday';
872 $rel3 = $this->callAPISuccess('relationship', 'create', $rel2Params);
874 $result = $this->callAPISuccess('relationship', 'get', $getParams);
875 $this->assertEquals($result['count'], 1);
876 $this->AssertEquals($rel1['id'], $result['id']);
878 foreach ([$rel0, $rel1, $rel2, $rel3] as $rel) {
879 $this->callAPISuccess('Relationship', 'delete', $rel);
884 * Test using various operators.
885 * @param int $version
886 * @dataProvider versionThreeAndFour
888 public function testGetTypeOperators($version) {
889 $this->_apiversion
= $version;
891 'name_a_b' => 'Relation 3 for delete',
892 'name_b_a' => 'Relation 6 for delete',
893 'description' => 'Testing relationship type 2',
894 'contact_type_a' => 'Individual',
895 'contact_type_b' => 'Organization',
899 $relationType2 = $this->relationshipTypeCreate($relTypeParams);
901 'name_a_b' => 'Relation 8 for delete',
902 'name_b_a' => 'Relation 9 for delete',
903 'description' => 'Testing relationship type 7',
904 'contact_type_a' => 'Individual',
905 'contact_type_b' => 'Organization',
909 $relationType3 = $this->relationshipTypeCreate($relTypeParams);
912 'name_a_b' => 'Relation 6 for delete',
913 'name_b_a' => 'Relation 88for delete',
914 'description' => 'Testing relationship type 00',
915 'contact_type_a' => 'Individual',
916 'contact_type_b' => 'Organization',
920 $relationType4 = $this->relationshipTypeCreate($relTypeParams);
922 $rel1 = $this->callAPISuccess('relationship', 'create', $this->_params
);
923 $rel2 = $this->callAPISuccess('relationship', 'create', array_merge($this->_params
,
924 ['relationship_type_id' => $relationType2]));
925 $rel3 = $this->callAPISuccess('relationship', 'create', array_merge($this->_params
,
926 ['relationship_type_id' => $relationType3]));
927 $rel4 = $this->callAPISuccess('relationship', 'create', array_merge($this->_params
,
928 ['relationship_type_id' => $relationType4]));
931 'relationship_type_id' => ['IN' => [$relationType2, $relationType3]],
934 $description = "Demonstrates use of IN filter.";
935 $subfile = 'INRelationshipType';
937 $result = $this->callAPIAndDocument('relationship', 'get', $getParams, __FUNCTION__
, __FILE__
, $description, $subfile);
938 $this->assertEquals($result['count'], 2);
939 $this->AssertEquals([$rel2['id'], $rel3['id']], array_keys($result['values']));
941 $description = "Demonstrates use of NOT IN filter.";
942 $subfile = 'NotInRelationshipType';
944 'relationship_type_id' => ['NOT IN' => [$relationType2, $relationType3]],
946 $result = $this->callAPIAndDocument('relationship', 'get', $getParams, __FUNCTION__
, __FILE__
, $description, $subfile);
947 $this->assertEquals($result['count'], 2);
948 $this->AssertEquals([$rel1['id'], $rel4['id']], array_keys($result['values']));
950 $description = "Demonstrates use of BETWEEN filter.";
951 $subfile = 'BetweenRelationshipType';
953 'relationship_type_id' => ['BETWEEN' => [$relationType2, $relationType4]],
955 $result = $this->callAPIAndDocument('relationship', 'get', $getParams, __FUNCTION__
, __FILE__
, $description, $subfile);
956 $this->assertEquals($result['count'], 3);
957 $this->AssertEquals([$rel2['id'], $rel3['id'], $rel4['id']], array_keys($result['values']));
959 $description = "Demonstrates use of Not BETWEEN filter.";
960 $subfile = 'NotBetweenRelationshipType';
962 'relationship_type_id' => ['NOT BETWEEN' => [$relationType2, $relationType4]],
964 $result = $this->callAPIAndDocument('relationship', 'get', $getParams, __FUNCTION__
, __FILE__
, $description, $subfile);
965 $this->assertEquals($result['count'], 1);
966 $this->AssertEquals([$rel1['id']], array_keys($result['values']));
968 foreach ([$relationType2, $relationType3, $relationType4] as $id) {
969 $this->callAPISuccess('RelationshipType', 'delete', ['id' => $id]);
974 * Check with invalid relationshipType Id.
976 public function testRelationshipTypeAddInvalidId() {
979 'name_a_b' => 'Relation 1 for delete',
980 'name_b_a' => 'Relation 2 for delete',
981 'contact_type_a' => 'Individual',
982 'contact_type_b' => 'Organization',
984 $this->callAPIFailure('relationship_type', 'create', $relTypeParams,
985 'id is not a valid integer');
989 * Check with valid data with contact_b.
991 public function testGetRelationshipWithContactB() {
993 'contact_id_a' => $this->_cId_a
,
994 'contact_id_b' => $this->_cId_b
,
995 'relationship_type_id' => $this->_relTypeID
,
996 'start_date' => '2011-01-01',
997 'end_date' => '2013-01-01',
1001 $relationship = $this->callAPISuccess('relationship', 'create', $relParams);
1004 'contact_id' => $this->_cId_a
,
1007 $result = $this->callAPISuccess('relationship', 'get', $contacts);
1008 $this->assertGreaterThan(0, $result['count']);
1010 'id' => $relationship['id'],
1012 $this->callAPISuccess('relationship', 'delete', $params);
1013 $this->relationshipTypeDelete($this->_relTypeID
);
1017 * Check with valid data with relationshipTypes.
1019 public function testGetRelationshipWithRelTypes() {
1021 'contact_id_a' => $this->_cId_a
,
1022 'contact_id_b' => $this->_cId_b
,
1023 'relationship_type_id' => $this->_relTypeID
,
1024 'start_date' => '2011-01-01',
1025 'end_date' => '2013-01-01',
1029 $relationship = $this->callAPISuccess('relationship', 'create', $relParams);
1032 'contact_id' => $this->_cId_a
,
1034 $this->callAPISuccess('relationship', 'get', $contact_a);
1037 'id' => $relationship['id'],
1039 $this->callAPISuccess('relationship', 'delete', $params);
1040 $this->relationshipTypeDelete($this->_relTypeID
);
1044 * Checks that passing in 'contact_id' + a relationship type
1045 * will filter by relationship type (relationships go in both directions)
1046 * as relationship api does a reciprocal check if contact_id provided
1048 * We should get 1 result without or with correct relationship type id & 0 with
1051 public function testGetRelationshipByTypeReciprocal() {
1052 $created = $this->callAPISuccess($this->entity
, 'create', $this->_params
);
1053 $result = $this->callAPISuccess($this->entity
, 'get', [
1054 'contact_id' => $this->_cId_a
,
1055 'relationship_type_id' => $this->_relTypeID
,
1057 $this->assertEquals(1, $result['count']);
1058 $result = $this->callAPISuccess($this->entity
, 'get', [
1059 'contact_id' => $this->_cId_a
,
1060 'relationship_type_id' => $this->_relTypeID +
1,
1062 $this->assertEquals(0, $result['count']);
1063 $this->callAPISuccess($this->entity
, 'delete', ['id' => $created['id']]);
1067 * Checks that passing in 'contact_id_b' + a relationship type
1068 * will filter by relationship type for contact b
1070 * We should get 1 result without or with correct relationship type id & 0 with
1072 * @param int $version
1073 * @dataProvider versionThreeAndFour
1075 public function testGetRelationshipByTypeDAO($version) {
1076 $this->_apiversion
= $version;
1077 $this->_ids
['relationship'] = $this->callAPISuccess($this->entity
, 'create', ['format.only_id' => TRUE] +
1079 $this->callAPISuccess($this->entity
, 'getcount', [
1080 'contact_id_a' => $this->_cId_a
,
1082 $result = $this->callAPISuccess($this->entity
, 'get', [
1083 'contact_id_a' => $this->_cId_a
,
1084 'relationship_type_id' => $this->_relTypeID
,
1086 $this->assertEquals(1, $result['count']);
1087 $result = $this->callAPISuccess($this->entity
, 'get', [
1088 'contact_id_a' => $this->_cId_a
,
1089 'relationship_type_id' => $this->_relTypeID +
1,
1091 $this->assertEquals(0, $result['count']);
1095 * Checks that passing in 'contact_id_b' + a relationship type
1096 * will filter by relationship type for contact b
1098 * We should get 1 result without or with correct relationship type id & 0 with
1100 * @param int $version
1101 * @dataProvider versionThreeAndFour
1103 public function testGetRelationshipByTypeArrayDAO($version) {
1104 $this->_apiversion
= $version;
1105 $this->callAPISuccess($this->entity
, 'create', $this->_params
);
1106 $org3 = $this->organizationCreate();
1107 // lets just assume built in ones aren't being messed with!
1109 // lets just assume built in ones aren't being messed with!
1113 $this->callAPISuccess($this->entity
, 'create',
1114 array_merge($this->_params
, [
1115 'relationship_type_id' => $relType2,
1116 'contact_id_b' => $this->_cId_b2
,
1121 $this->callAPISuccess($this->entity
, 'create',
1122 array_merge($this->_params
, [
1123 'relationship_type_id' => $relType3,
1124 'contact_id_b' => $org3,
1128 $result = $this->callAPISuccess($this->entity
, 'get', [
1129 'contact_id_a' => $this->_cId_a
,
1130 'relationship_type_id' => ['IN' => [$this->_relTypeID
, $relType3]],
1133 $this->assertEquals(2, $result['count']);
1134 foreach ($result['values'] as $key => $value) {
1135 $this->assertTrue(in_array($value['relationship_type_id'], [$this->_relTypeID
, $relType3]));
1140 * Checks that passing in 'contact_id_b' + a relationship type
1141 * will filter by relationship type for contact b
1143 * We should get 1 result without or with correct relationship type id & 0 with
1146 public function testGetRelationshipByTypeArrayReciprocal() {
1147 $this->callAPISuccess($this->entity
, 'create', $this->_params
);
1148 $org3 = $this->organizationCreate();
1149 // lets just assume built in ones aren't being messed with!
1154 $this->callAPISuccess($this->entity
, 'create',
1155 array_merge($this->_params
, [
1156 'relationship_type_id' => $relType2,
1157 'contact_id_b' => $this->_cId_b2
,
1162 $this->callAPISuccess($this->entity
, 'create',
1163 array_merge($this->_params
, [
1164 'relationship_type_id' => $relType3,
1165 'contact_id_b' => $org3,
1169 $result = $this->callAPISuccess($this->entity
, 'get', [
1170 'contact_id' => $this->_cId_a
,
1171 'relationship_type_id' => ['IN' => [$this->_relTypeID
, $relType3]],
1174 $this->assertEquals(2, $result['count']);
1175 foreach ($result['values'] as $key => $value) {
1176 $this->assertTrue(in_array($value['relationship_type_id'], [$this->_relTypeID
, $relType3]));
1181 * Test relationship get by membership type.
1183 * Checks that passing in 'contact_id_b' + a relationship type
1184 * will filter by relationship type for contact b
1186 * We should get 1 result without or with correct relationship type id & 0 with
1188 * @param int $version
1189 * @dataProvider versionThreeAndFour
1191 public function testGetRelationshipByMembershipTypeDAO($version) {
1192 $this->_apiversion
= $version;
1193 $this->callAPISuccess($this->entity
, 'create', $this->_params
);
1194 $org3 = $this->organizationCreate();
1196 // lets just assume built in ones aren't being messed with!
1198 // lets just assume built in ones aren't being messed with!
1201 $memberType = $this->membershipTypeCreate([
1202 'relationship_type_id' => CRM_Core_DAO
::VALUE_SEPARATOR
. $relType1 . CRM_Core_DAO
::VALUE_SEPARATOR
. $relType3 . CRM_Core_DAO
::VALUE_SEPARATOR
,
1203 'relationship_direction' => CRM_Core_DAO
::VALUE_SEPARATOR
. 'a_b' . CRM_Core_DAO
::VALUE_SEPARATOR
. 'b_a' . CRM_Core_DAO
::VALUE_SEPARATOR
,
1207 $this->callAPISuccess($this->entity
, 'create',
1208 array_merge($this->_params
, [
1209 'relationship_type_id' => $relType2,
1210 'contact_id_b' => $this->_cId_b2
,
1215 $this->callAPISuccess($this->entity
, 'create',
1216 array_merge($this->_params
, [
1217 'relationship_type_id' => $relType3,
1218 'contact_id_b' => $org3,
1222 // Relationship 4 with reversal.
1223 $this->callAPISuccess($this->entity
, 'create',
1224 array_merge($this->_params
, [
1225 'relationship_type_id' => $relType1,
1226 'contact_id_a' => $this->_cId_a
,
1227 'contact_id_b' => $this->_cId_a_2
,
1231 $result = $this->callAPISuccess($this->entity
, 'get', [
1232 'contact_id_a' => $this->_cId_a
,
1233 'membership_type_id' => $memberType,
1235 // although our contact has more than one relationship we have passed them in as contact_id_a & can't get reciprocal
1236 $this->assertEquals(1, $result['count']);
1237 foreach ($result['values'] as $key => $value) {
1238 $this->assertTrue(in_array($value['relationship_type_id'], [$relType1]));
1243 * Checks that passing in 'contact_id_b' + a relationship type
1244 * will filter by relationship type for contact b
1246 * We should get 1 result without or with correct relationship type id & 0 with
1248 * @param int $version
1249 * @dataProvider versionThreeAndFour
1251 public function testGetRelationshipByMembershipTypeReciprocal($version) {
1252 $this->_apiversion
= $version;
1253 $this->callAPISuccess($this->entity
, 'create', $this->_params
);
1254 $org3 = $this->organizationCreate();
1256 // Let's just assume built in ones aren't being messed with!
1260 $memberType = $this->membershipTypeCreate([
1261 'relationship_type_id' => CRM_Core_DAO
::VALUE_SEPARATOR
. $relType1 . CRM_Core_DAO
::VALUE_SEPARATOR
. $relType3 . CRM_Core_DAO
::VALUE_SEPARATOR
,
1262 'relationship_direction' => CRM_Core_DAO
::VALUE_SEPARATOR
. 'a_b' . CRM_Core_DAO
::VALUE_SEPARATOR
. 'b_a' . CRM_Core_DAO
::VALUE_SEPARATOR
,
1266 $this->callAPISuccess($this->entity
, 'create',
1267 array_merge($this->_params
, [
1268 'relationship_type_id' => $relType2,
1269 'contact_id_b' => $this->_cId_b2
,
1274 $this->callAPISuccess($this->entity
, 'create',
1275 array_merge($this->_params
, [
1276 'relationship_type_id' => $relType3,
1277 'contact_id_b' => $org3,
1281 // Relationship 4 with reversal.
1282 $this->callAPISuccess($this->entity
, 'create',
1283 array_merge($this->_params
, [
1284 'relationship_type_id' => $relType1,
1285 'contact_id_a' => $this->_cId_a
,
1286 'contact_id_b' => $this->_cId_a_2
,
1290 $result = $this->callAPISuccess($this->entity
, 'get', [
1291 'contact_id' => $this->_cId_a
,
1292 'membership_type_id' => $memberType,
1294 // Although our contact has more than one relationship we have passed them in as contact_id_a & can't get reciprocal
1295 $this->assertEquals(2, $result['count']);
1297 foreach ($result['values'] as $key => $value) {
1298 $this->assertTrue(in_array($value['relationship_type_id'], [$relType1, $relType3]));
1303 * Check for e-notices on enable & disable as reported in CRM-14350
1304 * @param int $version
1305 * @dataProvider versionThreeAndFour
1307 public function testSetActive($version) {
1308 $this->_apiversion
= $version;
1309 $relationship = $this->callAPISuccess($this->entity
, 'create', $this->_params
);
1310 $this->callAPISuccess($this->entity
, 'create', ['id' => $relationship['id'], 'is_active' => 0]);
1311 $this->callAPISuccess($this->entity
, 'create', ['id' => $relationship['id'], 'is_active' => 1]);
1315 * Test creating related memberships.
1316 * @param int $version
1317 * @dataProvider versionThreeAndFour
1319 public function testCreateRelatedMembership($version) {
1320 $this->_apiversion
= $version;
1321 $relatedMembershipType = $this->callAPISuccess('MembershipType', 'create', [
1322 'name' => 'Membership with Related',
1323 'member_of_contact_id' => 1,
1324 'financial_type_id' => 1,
1325 'minimum_fee' => 0.00,
1326 'duration_unit' => 'year',
1327 'duration_interval' => 1,
1328 'period_type' => 'rolling',
1329 'relationship_type_id' => $this->_relTypeID
,
1330 'relationship_direction' => 'b_a',
1331 'visibility' => 'Public',
1334 'domain_id' => CRM_Core_Config
::domainID(),
1336 $originalMembership = $this->callAPISuccess('Membership', 'create', [
1337 'membership_type_id' => $relatedMembershipType['id'],
1338 'contact_id' => $this->_cId_b
,
1340 $this->callAPISuccess('Relationship', 'create', [
1341 'relationship_type_id' => $this->_relTypeID
,
1342 'contact_id_a' => $this->_cId_a
,
1343 'contact_id_b' => $this->_cId_b
,
1345 $contactAMembership = $this->callAPISuccessGetSingle('membership', ['contact_id' => $this->_cId_a
]);
1346 $this->assertEquals($originalMembership['id'], $contactAMembership['owner_membership_id']);
1348 // Adding a relationship with a future start date should NOT create a membership
1349 $this->callAPISuccess('Relationship', 'create', [
1350 'relationship_type_id' => $this->_relTypeID
,
1351 'contact_id_a' => $this->_cId_a_2
,
1352 'contact_id_b' => $this->_cId_b
,
1353 'start_date' => 'now + 1 week',
1355 $this->callAPISuccessGetCount('membership', ['contact_id' => $this->_cId_a_2
], 0);
1357 // Deleting the organization should cause the related membership to be deleted.
1358 $this->callAPISuccess('contact', 'delete', ['id' => $this->_cId_b
]);
1359 $this->callAPISuccessGetCount('membership', ['contact_id' => $this->_cId_a
], 0);
1363 * Test api respects is_current_employer.
1365 * @throws \CRM_Core_Exception
1367 public function testRelationshipCreateWithEmployerData() {
1368 // CASE A: Create a current employee relationship without setting end date, ensure that employer field is set
1370 'relationship_type_id' => '5_a_b',
1371 'related_contact_id' => $this->_cId_b
,
1372 'start_date' => '2008-12-20',
1375 'is_current_employer' => 1,
1376 'is_permission_a_b' => 0,
1377 'is_permission_b_a' => 0,
1379 $reln = new CRM_Contact_Form_Relationship();
1380 $reln->_action
= CRM_Core_Action
::ADD
;
1381 $reln->_contactId
= $this->_cId_a
;
1382 list ($params, $relationshipIds) = $reln->submit($params);
1383 $this->assertEquals(
1385 $this->callAPISuccess('Contact', 'getvalue', [
1386 'id' => $this->_cId_a
,
1387 'return' => 'current_employer_id',
1389 // CASE B: Create a past employee relationship by setting end date of past, ensure that employer field is cleared
1391 'relationship_type_id' => '5_a_b',
1392 'related_contact_id' => $this->_cId_b
,
1393 // set date to past date
1394 'end_date' => '2010-12-20',
1396 $reln->_action
= CRM_Core_Action
::UPDATE
;
1397 $reln->_relationshipId
= $relationshipIds[0];
1398 list ($params, $relationshipIds) = $reln->submit($params);
1399 $this->assertEmpty($this->callAPISuccess('Contact', 'getvalue', [
1400 'id' => $this->_cId_a
,
1401 'return' => 'current_employer_id',
1403 $this->callAPISuccess('relationship', 'delete', ['id' => $relationshipIds[0]]);
1407 * Test disabling an expired relationship does not incorrectly clear employer_id.
1409 * See https://lab.civicrm.org/dev/core/issues/470
1411 * @throws \CRM_Core_Exception
1412 * @throws \CiviCRM_API3_Exception
1414 public function testDisableExpiredRelationships() {
1415 // Step 1: Create a current employer relationship with Org A
1417 'relationship_type_id' => '5',
1418 'contact_id_a' => $this->_cId_a
,
1419 'contact_id_b' => $this->_cId_b
,
1420 'start_date' => '2008-12-20',
1423 'is_current_employer' => 1,
1424 'is_permission_a_b' => 0,
1425 'is_permission_b_a' => 0,
1427 $this->callAPISuccess('Relationship', 'create', $params);
1429 // ensure that the employer_id field is sucessfully set
1430 $this->assertEquals(
1432 $this->callAPISuccess('Contact', 'getvalue', [
1433 'id' => $this->_cId_a
,
1434 'return' => 'current_employer_id',
1436 // Step 2: Create a PAST employer relationship with Org B, and setting is_current_employer = FALSE
1437 $orgID2 = $this->organizationCreate();
1439 'relationship_type_id' => '5',
1440 'contact_id_a' => $this->_cId_a
,
1441 'contact_id_b' => $orgID2,
1442 'start_date' => '2008-12-20',
1443 'end_date' => '2008-12-22',
1445 'is_current_employer' => 0,
1446 'is_permission_a_b' => 0,
1447 'is_permission_b_a' => 0,
1450 $relationshipB = $this->callAPISuccess('Relationship', 'create', $params);
1451 // ensure that the employer_id field is still set to contact b
1452 $this->assertEquals(
1454 $this->callAPISuccess('Contact', 'getvalue', [
1455 'id' => $this->_cId_a
,
1456 'return' => 'current_employer_id',
1459 // Step 3: Call schedule job disable_expired_relationships
1460 CRM_Contact_BAO_Relationship
::disableExpiredRelationships();
1462 // Result A: Ensure that employer field is not cleared
1463 $this->assertEquals(
1465 $this->callAPISuccess('Contact', 'getvalue', [
1466 'id' => $this->_cId_a
,
1467 'return' => 'current_employer_id',
1469 // Result B: Ensure that the previous employer relationship with Org B is successfully disabled
1470 $this->assertEquals(
1472 (bool) $this->callAPISuccess('Relationship', 'getvalue', [
1473 'id' => $relationshipB['id'],
1474 'return' => 'is_active',