Merge pull request #17294 from agh1/sr-rel-perms
[civicrm-core.git] / tests / phpunit / api / v3 / ProfileTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * Test APIv3 civicrm_profile_* functions
14 *
15 * @package CiviCRM
16 * @group headless
17 */
18 class api_v3_ProfileTest extends CiviUnitTestCase {
19 use CRMTraits_Custom_CustomDataTrait;
20
21 protected $_profileID = 0;
22
23 protected $_membershipTypeID;
24
25 protected $_contactID;
26
27 /**
28 * Set up for test.
29 */
30 public function setUp() {
31 parent::setUp();
32 $config = CRM_Core_Config::singleton();
33 $countryLimit = $config->countryLimit;
34 $countryLimit[1] = 1013;
35 $config->countryLimit = $countryLimit;
36
37 $this->createLoggedInUser();
38 $this->_membershipTypeID = $this->membershipTypeCreate();
39 }
40
41 /**
42 * Cleanup after test.
43 *
44 * @throws \Exception
45 */
46 public function tearDown() {
47
48 $this->quickCleanup([
49 'civicrm_contact',
50 'civicrm_phone',
51 'civicrm_address',
52 'civicrm_membership',
53 'civicrm_contribution',
54 'civicrm_uf_match',
55 ], TRUE);
56 $this->callAPISuccess('membership_type', 'delete', ['id' => $this->_membershipTypeID]);
57 CRM_Core_DAO::executeQuery(" DELETE FROM civicrm_uf_group WHERE id = $this->_profileID OR name = 'test_contact_activity_profile'");
58 parent::tearDown();
59 }
60
61 /**
62 * Check Without ProfileId.
63 */
64 public function testProfileGetWithoutProfileId() {
65 $this->callAPIFailure('profile', 'get', ['contact_id' => 1],
66 'Mandatory key(s) missing from params array: profile_id'
67 );
68 }
69
70 /**
71 * Check with no invalid profile Id.
72 */
73 public function testProfileGetInvalidProfileId() {
74 $this->callAPIFailure('profile', 'get', [
75 'contact_id' => 1,
76 'profile_id' => 1000,
77 ]);
78 }
79
80 /**
81 * Check with success.
82 *
83 * @throws \CRM_Core_Exception
84 */
85 public function testProfileGet() {
86 $profileFieldValues = $this->_createIndividualContact();
87 $expected = reset($profileFieldValues);
88 $contactId = key($profileFieldValues);
89 $params = [
90 'profile_id' => $this->_profileID,
91 'contact_id' => $contactId,
92 ];
93 $result = $this->callAPISuccess('profile', 'get', $params)['values'];
94 foreach ($expected as $profileField => $value) {
95 $this->assertEquals($value, CRM_Utils_Array::value($profileField, $result));
96 }
97 }
98
99 /**
100 * Test retrieving a profile with an address custom field in it.
101 *
102 * We are checking that there is no error.
103 *
104 * @throws \CRM_Core_Exception
105 */
106 public function testProfileGetWithAddressCustomData() {
107 $this->_createIndividualContact();
108 $this->entity = 'Address';
109 $this->createCustomGroupWithFieldOfType(['extends' => 'Address']);
110 $this->callAPISuccess('UFField', 'create', [
111 'uf_group_id' => $this->_profileID,
112 'field_name' => $this->getCustomFieldName('text'),
113 'visibility' => 'Public Pages and Listings',
114 'label' => 'My custom field',
115 'field_type' => 'Contact',
116 ]);
117 $this->callAPISuccess('Address', 'get', ['contact_id' => $this->_contactID, 'api.Address.create' => [$this->getCustomFieldName('text') => 'my field']]);
118 $result = $this->callAPISuccess('Profile', 'get', ['profile_id' => $this->_profileID, 'contact_id' => $this->_contactID])['values'];
119 // $this->assertEquals('my field', $result[$this->getCustomFieldName('text')]);
120 }
121
122 /**
123 * Test getting multiple profiles.
124 */
125 public function testProfileGetMultiple() {
126 $profileFieldValues = $this->_createIndividualContact();
127 $expected = reset($profileFieldValues);
128 $contactId = key($profileFieldValues);
129 $params = [
130 'profile_id' => [$this->_profileID, 1, 'Billing'],
131 'contact_id' => $contactId,
132 ];
133
134 $result = $this->callAPIAndDocument('profile', 'get', $params, __FUNCTION__, __FILE__)['values'];
135 foreach ($expected as $profileField => $value) {
136 $this->assertEquals($value, CRM_Utils_Array::value($profileField, $result[$this->_profileID]), " error message: " . "missing/mismatching value for {$profileField}");
137 }
138 $this->assertEquals('abc1', $result[1]['first_name'], " error message: " . "missing/mismatching value for first name");
139 $this->assertFalse(array_key_exists('email-Primary', $result[1]), 'profile 1 does not include email');
140 $this->assertEquals($result['Billing'], [
141 'billing_first_name' => 'abc1',
142 'billing_middle_name' => 'J.',
143 'billing_last_name' => 'xyz1',
144 'billing_street_address-5' => '5 Saint Helier St',
145 'billing_city-5' => 'Gotham City',
146 'billing_state_province_id-5' => '1021',
147 'billing_country_id-5' => '1228',
148 'billing_postal_code-5' => '90210',
149 'billing-email-5' => 'abc1.xyz1@yahoo.com',
150 'email-5' => 'abc1.xyz1@yahoo.com',
151 ]);
152 }
153
154 /**
155 * Test getting billing profile filled using is_billing.
156 */
157 public function testProfileGetBillingUseIsBillingLocation() {
158 $individual = $this->_createIndividualContact();
159 $contactId = key($individual);
160 $this->callAPISuccess('address', 'create', [
161 'is_billing' => 1,
162 'street_address' => 'is billing st',
163 'location_type_id' => 2,
164 'contact_id' => $contactId,
165 ]);
166
167 $params = [
168 'profile_id' => [$this->_profileID, 1, 'Billing'],
169 'contact_id' => $contactId,
170 ];
171
172 $result = $this->callAPISuccess('profile', 'get', $params)['values'];
173 $this->assertEquals('abc1', $result[1]['first_name']);
174 $this->assertEquals([
175 'billing_first_name' => 'abc1',
176 'billing_middle_name' => 'J.',
177 'billing_last_name' => 'xyz1',
178 'billing_street_address-5' => 'is billing st',
179 'billing_city-5' => '',
180 'billing_state_province_id-5' => '',
181 'billing_country_id-5' => '',
182 'billing-email-5' => 'abc1.xyz1@yahoo.com',
183 'email-5' => 'abc1.xyz1@yahoo.com',
184 'billing_postal_code-5' => '',
185 ], $result['Billing']);
186 }
187
188 /**
189 * Test getting multiple profiles, including billing.
190 */
191 public function testProfileGetMultipleHasBillingLocation() {
192 $individual = $this->_createIndividualContact();
193 $contactId = key($individual);
194 $this->callAPISuccess('address', 'create', [
195 'contact_id' => $contactId,
196 'street_address' => '25 Big Street',
197 'city' => 'big city',
198 'location_type_id' => 5,
199 ]);
200 $this->callAPISuccess('email', 'create', [
201 'contact_id' => $contactId,
202 'email' => 'big@once.com',
203 'location_type_id' => 2,
204 'is_billing' => 1,
205 ]);
206
207 $params = [
208 'profile_id' => [$this->_profileID, 1, 'Billing'],
209 'contact_id' => $contactId,
210 ];
211
212 $result = $this->callAPISuccess('profile', 'get', $params);
213 $this->assertEquals('abc1', $result['values'][1]['first_name']);
214 $this->assertEquals($result['values']['Billing'], [
215 'billing_first_name' => 'abc1',
216 'billing_middle_name' => 'J.',
217 'billing_last_name' => 'xyz1',
218 'billing_street_address-5' => '25 Big Street',
219 'billing_city-5' => 'big city',
220 'billing_state_province_id-5' => '',
221 'billing_country_id-5' => '',
222 'billing-email-5' => 'big@once.com',
223 'email-5' => 'big@once.com',
224 'billing_postal_code-5' => '',
225 ]);
226 }
227
228 /**
229 * Get Billing empty contact - this will return generic defaults.
230 */
231 public function testProfileGetBillingEmptyContact() {
232 $this->callAPISuccess('Setting', 'create', ['defaultContactCountry' => 1228]);
233 $params = [
234 'profile_id' => ['Billing'],
235 ];
236
237 $result = $this->callAPISuccess('profile', 'get', $params)['values'];
238 $this->assertEquals([
239 'billing_first_name' => '',
240 'billing_middle_name' => '',
241 'billing_last_name' => '',
242 'billing_street_address-5' => '',
243 'billing_city-5' => '',
244 'billing_state_province_id-5' => '',
245 'billing_country_id-5' => '1228',
246 'billing_email-5' => '',
247 'email-5' => '',
248 'billing_postal_code-5' => '',
249 ], $result['Billing']);
250 }
251
252 /**
253 * Check contact activity profile without activity id.
254 */
255 public function testContactActivityGetWithoutActivityId() {
256 list($params) = $this->_createContactWithActivity();
257
258 unset($params['activity_id']);
259 $this->callAPIFailure('profile', 'get', $params, 'Mandatory key(s) missing from params array: activity_id');
260 }
261
262 /**
263 * Check contact activity profile wrong activity id.
264 */
265 public function testContactActivityGetWrongActivityId() {
266 list($params) = $this->_createContactWithActivity();
267 $params['activity_id'] = 100001;
268 $this->callAPIFailure('profile', 'get', $params, 'Invalid Activity Id (aid).');
269 }
270
271 /**
272 * Check contact activity profile with wrong activity type.
273 *
274 * @throws \Exception
275 */
276 public function testContactActivityGetWrongActivityType() {
277 $activity = $this->callAPISuccess('activity', 'create', [
278 'source_contact_id' => $this->householdCreate(),
279 'activity_type_id' => '2',
280 'subject' => 'Test activity',
281 'activity_date_time' => '20110316',
282 'duration' => '120',
283 'location' => 'Pennsylvania',
284 'details' => 'a test activity',
285 'status_id' => '1',
286 'priority_id' => '1',
287 ])['values'];
288
289 $activityValues = array_pop($activity);
290
291 list($params) = $this->_createContactWithActivity();
292
293 $params['activity_id'] = $activityValues['id'];
294 $this->callAPIFailure('profile', 'get', $params, 'This activity cannot be edited or viewed via this profile.');
295 }
296
297 /**
298 * Check contact activity profile with success.
299 */
300 public function testContactActivityGetSuccess() {
301 list($params, $expected) = $this->_createContactWithActivity();
302
303 $result = $this->callAPISuccess('profile', 'get', $params);
304
305 foreach ($expected as $profileField => $value) {
306 $this->assertEquals($value, CRM_Utils_Array::value($profileField, $result['values']), " error message: " . "missing/mismatching value for {$profileField}"
307 );
308 }
309 }
310
311 /**
312 * Check getfields works & gives us our fields
313 */
314 public function testGetFields() {
315 $this->_createIndividualProfile();
316 $this->_addCustomFieldToProfile($this->_profileID);
317 $result = $this->callAPIAndDocument('profile', 'getfields', [
318 'action' => 'submit',
319 'profile_id' => $this->_profileID,
320 ], __FUNCTION__, __FILE__,
321 'demonstrates retrieving profile fields passing in an id');
322 $this->assertArrayKeyExists('first_name', $result['values']);
323 $this->assertEquals('2', $result['values']['first_name']['type']);
324 $this->assertEquals('Email', $result['values']['email-primary']['title']);
325 $this->assertEquals('civicrm_state_province', $result['values']['state_province-1']['pseudoconstant']['table']);
326 $this->assertEquals('defaultValue', $result['values']['custom_1']['default_value']);
327 $this->assertFalse(array_key_exists('participant_status', $result['values']));
328 }
329
330 /**
331 * Check getfields works & gives us our fields - participant profile
332 */
333 public function testGetFieldsParticipantProfile() {
334 $result = $this->callAPISuccess('profile', 'getfields', [
335 'action' => 'submit',
336 'profile_id' => 'participant_status',
337 'get_options' => 'all',
338 ]);
339 $this->assertTrue(array_key_exists('participant_status_id', $result['values']));
340 $this->assertEquals('Attended', $result['values']['participant_status_id']['options'][2]);
341 $this->assertEquals(['participant_status'], $result['values']['participant_status_id']['api.aliases']);
342 }
343
344 /**
345 * Check getfields works & gives us our fields - membership_batch_entry
346 * (getting to the end with no e-notices is pretty good evidence it's working)
347 */
348 public function testGetFieldsMembershipBatchProfile() {
349 $result = $this->callAPISuccess('profile', 'getfields', [
350 'action' => 'submit',
351 'profile_id' => 'membership_batch_entry',
352 'get_options' => 'all',
353 ]);
354 $this->assertTrue(array_key_exists('total_amount', $result['values']));
355 $this->assertTrue(array_key_exists('financial_type_id', $result['values']));
356 $this->assertEquals([
357 'contribution_type_id',
358 'contribution_type',
359 'financial_type',
360 ], $result['values']['financial_type_id']['api.aliases']);
361 $this->assertTrue(!array_key_exists('financial_type', $result['values']));
362 $this->assertEquals(12, $result['values']['receive_date']['type']);
363 }
364
365 /**
366 * Check getfields works & gives us our fields - do them all
367 * (getting to the end with no e-notices is pretty good evidence it's working)
368 */
369 public function testGetFieldsAllProfiles() {
370 $result = $this->callAPISuccess('uf_group', 'get', ['return' => 'id'])['values'];
371 $profileIDs = array_keys($result);
372 foreach ($profileIDs as $profileID) {
373 $this->callAPISuccess('profile', 'getfields', [
374 'action' => 'submit',
375 'profile_id' => $profileID,
376 'get_options' => 'all',
377 ]);
378 }
379 }
380
381 /**
382 * Check Without ProfileId.
383 */
384 public function testProfileSubmitWithoutProfileId() {
385 $params = [
386 'contact_id' => 1,
387 ];
388 $this->callAPIFailure('profile', 'submit', $params,
389 'Mandatory key(s) missing from params array: profile_id'
390 );
391 }
392
393 /**
394 * Check with no invalid profile Id.
395 */
396 public function testProfileSubmitInvalidProfileId() {
397 $params = [
398 'contact_id' => 1,
399 'profile_id' => 1000,
400 ];
401 $this->callAPIFailure('profile', 'submit', $params);
402 }
403
404 /**
405 * Check with missing required field in profile.
406 */
407 public function testProfileSubmitCheckProfileRequired() {
408 $profileFieldValues = $this->_createIndividualContact();
409 $contactId = key($profileFieldValues);
410 $updateParams = [
411 'first_name' => 'abc2',
412 'last_name' => 'xyz2',
413 'phone-1-1' => '022 321 826',
414 'country-1' => '1013',
415 'state_province-1' => '1000',
416 ];
417
418 $params = array_merge([
419 'profile_id' => $this->_profileID,
420 'contact_id' => $contactId,
421 ],
422 $updateParams
423 );
424
425 $this->callAPIFailure('profile', 'submit', $params,
426 "Mandatory key(s) missing from params array: email-primary"
427 );
428 }
429
430 /**
431 * Check with success.
432 */
433 public function testProfileSubmit() {
434 $profileFieldValues = $this->_createIndividualContact();
435 $contactId = key($profileFieldValues);
436
437 $updateParams = [
438 'first_name' => 'abc2',
439 'last_name' => 'xyz2',
440 'email-primary' => 'abc2.xyz2@gmail.com',
441 'phone-1-1' => '022 321 826',
442 'country-1' => '1013',
443 'state_province-1' => '1000',
444 ];
445
446 $params = array_merge([
447 'profile_id' => $this->_profileID,
448 'contact_id' => $contactId,
449 ], $updateParams);
450
451 $this->callAPIAndDocument('profile', 'submit', $params, __FUNCTION__, __FILE__);
452
453 $getParams = [
454 'profile_id' => $this->_profileID,
455 'contact_id' => $contactId,
456 ];
457 $profileDetails = $this->callAPISuccess('profile', 'get', $getParams);
458
459 foreach ($updateParams as $profileField => $value) {
460 $this->assertEquals($value, CRM_Utils_Array::value($profileField, $profileDetails['values']), "missing/mismatching value for {$profileField}"
461 );
462 }
463 unset($params['email-primary']);
464 $params['email-Primary'] = 'my@mail.com';
465 $this->callAPISuccess('profile', 'submit', $params);
466 $profileDetails = $this->callAPISuccess('profile', 'get', $getParams);
467 $this->assertEquals('my@mail.com', $profileDetails['values']['email-Primary']);
468 }
469
470 /**
471 * Ensure caches are being cleared so we don't get into a debugging trap because of cached metadata
472 * First we delete & create to increment the version & then check for caching problems.
473 */
474 public function testProfileSubmitCheckCaching() {
475 $this->callAPISuccess('membership_type', 'delete', ['id' => $this->_membershipTypeID]);
476 $this->_membershipTypeID = $this->membershipTypeCreate();
477
478 $membershipTypes = $this->callAPISuccess('membership_type', 'get', []);
479 $profileFields = $this->callAPISuccess('profile', 'getfields', [
480 'get_options' => 'all',
481 'action' => 'submit',
482 'profile_id' => 'membership_batch_entry',
483 ]);
484 $getoptions = $this->callAPISuccess('membership', 'getoptions', [
485 'field' => 'membership_type',
486 'context' => 'validate',
487 ]);
488 $this->assertEquals(array_keys($membershipTypes['values']), array_keys($getoptions['values']));
489 $this->assertEquals(array_keys($membershipTypes['values']), array_keys($profileFields['values']['membership_type_id']['options']));
490
491 }
492
493 /**
494 * Test that the fields are returned in the right order despite the faffing around that goes on.
495 */
496 public function testMembershipGetFieldsOrder() {
497 $result = $this->callAPISuccess('profile', 'getfields', [
498 'action' => 'submit',
499 'profile_id' => 'membership_batch_entry',
500 ])['values'];
501 $weight = 1;
502 foreach ($result as $fieldName => $field) {
503 if ($fieldName == 'profile_id') {
504 continue;
505 }
506 $this->assertEquals($field['weight'], $weight);
507 $weight++;
508 }
509 }
510
511 /**
512 * Check we can submit membership batch profiles (create mode)
513 */
514 public function testProfileSubmitMembershipBatch() {
515 $this->_contactID = $this->individualCreate();
516 $this->callAPISuccess('profile', 'submit', [
517 'profile_id' => 'membership_batch_entry',
518 'financial_type_id' => 1,
519 'membership_type' => $this->_membershipTypeID,
520 'join_date' => 'now',
521 'total_amount' => 10,
522 'contribution_status_id' => 1,
523 'receive_date' => 'now',
524 'contact_id' => $this->_contactID,
525 ]);
526 }
527
528 /**
529 * Set is deprecated but we need to ensure it still works.
530 */
531 public function testLegacySet() {
532 $profileFieldValues = $this->_createIndividualContact();
533 $contactId = key($profileFieldValues);
534
535 $updateParams = [
536 'first_name' => 'abc2',
537 'last_name' => 'xyz2',
538 'email-Primary' => 'abc2.xyz2@gmail.com',
539 'phone-1-1' => '022 321 826',
540 'country-1' => '1013',
541 'state_province-1' => '1000',
542 ];
543
544 $params = array_merge([
545 'profile_id' => $this->_profileID,
546 'contact_id' => $contactId,
547 ], $updateParams);
548
549 $result = $this->callAPISuccess('profile', 'set', $params);
550 $this->assertArrayKeyExists('values', $result);
551 $getParams = [
552 'profile_id' => $this->_profileID,
553 'contact_id' => $contactId,
554 ];
555 $profileDetails = $this->callAPISuccess('profile', 'get', $getParams);
556
557 foreach ($updateParams as $profileField => $value) {
558 $this->assertEquals($value, CRM_Utils_Array::value($profileField, $profileDetails['values']), "In line " . __LINE__ . " error message: " . "missing/mismatching value for {$profileField}"
559 );
560 }
561 }
562
563 /**
564 * Check contact activity profile without activity id.
565 */
566 public function testContactActivitySubmitWithoutActivityId() {
567 list($params, $expected) = $this->_createContactWithActivity();
568
569 $params = array_merge($params, $expected);
570 unset($params['activity_id']);
571 $this->callAPIFailure('profile', 'submit', $params, 'Mandatory key(s) missing from params array: activity_id');
572 }
573
574 /**
575 * Check contact activity profile wrong activity id.
576 */
577 public function testContactActivitySubmitWrongActivityId() {
578 list($params, $expected) = $this->_createContactWithActivity();
579 $params = array_merge($params, $expected);
580 $params['activity_id'] = 100001;
581 $this->callAPIFailure('profile', 'submit', $params, 'Invalid Activity Id (aid).');
582 }
583
584 /**
585 * Check contact activity profile with wrong activity type.
586 *
587 * @throws \Exception
588 */
589 public function testContactActivitySubmitWrongActivityType() {
590
591 $sourceContactId = $this->householdCreate();
592
593 $activityParams = [
594 'source_contact_id' => $sourceContactId,
595 'activity_type_id' => '2',
596 'subject' => 'Test activity',
597 'activity_date_time' => '20110316',
598 'duration' => '120',
599 'location' => 'Pennsylvania',
600 'details' => 'a test activity',
601 'status_id' => '1',
602 'priority_id' => '1',
603 ];
604
605 $activity = $this->callAPISuccess('activity', 'create', $activityParams);
606
607 $activityValues = array_pop($activity['values']);
608
609 list($params, $expected) = $this->_createContactWithActivity();
610
611 $params = array_merge($params, $expected);
612 $params['activity_id'] = $activityValues['id'];
613 $this->callAPIFailure('profile', 'submit', $params,
614 'This activity cannot be edited or viewed via this profile.');
615 }
616
617 /**
618 * Check contact activity profile with success.
619 */
620 public function testContactActivitySubmitSuccess() {
621 list($params) = $this->_createContactWithActivity();
622
623 $updateParams = [
624 'first_name' => 'abc2',
625 'last_name' => 'xyz2',
626 'email-Primary' => 'abc2.xyz2@yahoo.com',
627 'activity_subject' => 'Test Meeting',
628 'activity_details' => 'a test activity details',
629 'activity_duration' => '100',
630 'activity_date_time' => '2010-03-08 00:00:00',
631 'activity_status_id' => '2',
632 ];
633 $profileParams = array_merge($params, $updateParams);
634 $this->callAPISuccess('profile', 'submit', $profileParams);
635 $result = $this->callAPISuccess('profile', 'get', $params)['values'];
636
637 foreach ($updateParams as $profileField => $value) {
638 $this->assertEquals($value, CRM_Utils_Array::value($profileField, $result), " error message: " . "missing/mismatching value for {$profileField}"
639 );
640 }
641 }
642
643 /**
644 * Check profile apply Without ProfileId.
645 */
646 public function testProfileApplyWithoutProfileId() {
647 $params = [
648 'contact_id' => 1,
649 ];
650 $this->callAPIFailure('profile', 'apply', $params,
651 'Mandatory key(s) missing from params array: profile_id');
652 }
653
654 /**
655 * Check profile apply with no invalid profile Id.
656 */
657 public function testProfileApplyInvalidProfileId() {
658 $params = [
659 'contact_id' => 1,
660 'profile_id' => 1000,
661 ];
662 $this->callAPIFailure('profile', 'apply', $params);
663 }
664
665 /**
666 * Check with success.
667 */
668 public function testProfileApply() {
669 $profileFieldValues = $this->_createIndividualContact();
670 current($profileFieldValues);
671 $contactId = key($profileFieldValues);
672
673 $params = [
674 'profile_id' => $this->_profileID,
675 'contact_id' => $contactId,
676 'first_name' => 'abc2',
677 'last_name' => 'xyz2',
678 'email-Primary' => 'abc2.xyz2@gmail.com',
679 'phone-1-1' => '022 321 826',
680 'country-1' => '1013',
681 'state_province-1' => '1000',
682 ];
683
684 $result = $this->callAPIAndDocument('profile', 'apply', $params, __FUNCTION__, __FILE__);
685
686 // Expected field values
687 $expected['contact'] = [
688 'contact_id' => $contactId,
689 'contact_type' => 'Individual',
690 'first_name' => 'abc2',
691 'last_name' => 'xyz2',
692 ];
693 $expected['email'] = [
694 'location_type_id' => 1,
695 'is_primary' => 1,
696 'email' => 'abc2.xyz2@gmail.com',
697 ];
698
699 $expected['phone'] = [
700 'location_type_id' => 1,
701 'is_primary' => 1,
702 'phone_type_id' => 1,
703 'phone' => '022 321 826',
704 ];
705 $expected['address'] = [
706 'location_type_id' => 1,
707 'is_primary' => 1,
708 'country_id' => 1013,
709 'state_province_id' => 1000,
710 ];
711
712 foreach ($expected['contact'] as $field => $value) {
713 $this->assertEquals($value, CRM_Utils_Array::value($field, $result['values']), "missing/mismatching value for {$field}"
714 );
715 }
716
717 foreach (['email', 'phone', 'address'] as $fieldType) {
718 $typeValues = array_pop($result['values'][$fieldType]);
719 foreach ($expected[$fieldType] as $field => $value) {
720 $this->assertEquals($value, CRM_Utils_Array::value($field, $typeValues), "missing/mismatching value for {$field} ({$fieldType})"
721 );
722 }
723 }
724 }
725
726 /**
727 * Check success with tags.
728 */
729 public function testSubmitWithTags() {
730 $profileFieldValues = $this->_createIndividualContact();
731 $params = reset($profileFieldValues);
732 $contactId = key($profileFieldValues);
733 $params['profile_id'] = $this->_profileID;
734 $params['contact_id'] = $contactId;
735
736 $this->callAPISuccess('ufField', 'create', [
737 'uf_group_id' => $this->_profileID,
738 'field_name' => 'tag',
739 'visibility' => 'Public Pages and Listings',
740 'field_type' => 'Contact',
741 'label' => 'Tags',
742 ]);
743
744 $tag_1 = $this->callAPISuccess('tag', 'create', ['name' => 'abc'])['id'];
745 $tag_2 = $this->callAPISuccess('tag', 'create', ['name' => 'def'])['id'];
746
747 $params['tag'] = "$tag_1,$tag_2";
748 $this->callAPISuccess('profile', 'submit', $params);
749
750 $tags = $this->callAPISuccess('entityTag', 'get', ['entity_id' => $contactId]);
751 $this->assertEquals(2, $tags['count']);
752
753 $params['tag'] = [$tag_1];
754 $this->callAPISuccess('profile', 'submit', $params);
755
756 $tags = $this->callAPISuccess('entityTag', 'get', ['entity_id' => $contactId]);
757 $this->assertEquals(1, $tags['count']);
758
759 $params['tag'] = '';
760 $this->callAPISuccess('profile', 'submit', $params);
761
762 $tags = $this->callAPISuccess('entityTag', 'get', ['entity_id' => $contactId]);
763 $this->assertEquals(0, $tags['count']);
764
765 }
766
767 /**
768 * Check success with a note.
769 *
770 * @throws \Exception
771 */
772 public function testSubmitWithNote() {
773 $profileFieldValues = $this->_createIndividualContact();
774 $params = reset($profileFieldValues);
775 $contactId = key($profileFieldValues);
776 $params['profile_id'] = $this->_profileID;
777 $params['contact_id'] = $contactId;
778
779 $this->callAPISuccess('ufField', 'create', [
780 'uf_group_id' => $this->_profileID,
781 'field_name' => 'note',
782 'visibility' => 'Public Pages and Listings',
783 'field_type' => 'Contact',
784 'label' => 'Note',
785 ]);
786
787 $params['note'] = "Hello 123";
788 $this->callAPISuccess('profile', 'submit', $params);
789
790 $note = $this->callAPISuccessGetSingle('note', ['entity_id' => $contactId]);
791 $this->assertEquals("Hello 123", $note['note']);
792 }
793
794 /**
795 * Check handling a custom greeting.
796 *
797 * @throws \CiviCRM_API3_Exception
798 */
799 public function testSubmitGreetingFields() {
800 $profileFieldValues = $this->_createIndividualContact();
801 $params = reset($profileFieldValues);
802 $contactId = key($profileFieldValues);
803 $params['profile_id'] = $this->_profileID;
804 $params['contact_id'] = $contactId;
805
806 $this->callAPISuccess('ufField', 'create', [
807 'uf_group_id' => $this->_profileID,
808 'field_name' => 'email_greeting',
809 'visibility' => 'Public Pages and Listings',
810 'field_type' => 'Contact',
811 'label' => 'Email Greeting',
812 ]);
813
814 $emailGreetings = array_column(civicrm_api3('OptionValue', 'get', ['option_group_id' => "email_greeting"])['values'], NULL, 'name');
815
816 $params['email_greeting'] = $emailGreetings['Customized']['value'];
817 // Custom greeting should be required
818 $this->callAPIFailure('profile', 'submit', $params);
819
820 $params['email_greeting_custom'] = 'Hello fool!';
821 $this->callAPISuccess('profile', 'submit', $params);
822
823 // Api3 will not return custom greeting field so resorting to this
824 $greeting = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $contactId, 'email_greeting_custom');
825
826 $this->assertEquals("Hello fool!", $greeting);
827 }
828
829 /**
830 * Helper function to create an Individual with address/email/phone info. Import UF Group and UF Fields
831 *
832 * @param array $params
833 *
834 * @return mixed
835 */
836 public function _createIndividualContact($params = []) {
837 $contactParams = array_merge([
838 'first_name' => 'abc1',
839 'last_name' => 'xyz1',
840 'email' => 'abc1.xyz1@yahoo.com',
841 'api.address.create' => [
842 'location_type_id' => 1,
843 'is_primary' => 1,
844 'street_address' => '5 Saint Helier St',
845 'county' => 'Marin',
846 'country' => 'UNITED STATES',
847 'state_province' => 'Michigan',
848 'supplemental_address_1' => 'Hallmark Ct',
849 'supplemental_address_2' => 'Jersey Village',
850 'supplemental_address_3' => 'My Town',
851 'postal_code' => '90210',
852 'city' => 'Gotham City',
853 'is_billing' => 0,
854 ],
855 'api.phone.create' => [
856 'location_type_id' => '1',
857 'phone' => '021 512 755',
858 'phone_type_id' => '1',
859 'is_primary' => '1',
860 ],
861 ], $params);
862
863 $this->_contactID = $this->individualCreate($contactParams);
864 $this->_createIndividualProfile();
865 // expected result of above created profile with contact Id $contactId
866 $profileData[$this->_contactID] = [
867 'first_name' => 'abc1',
868 'last_name' => 'xyz1',
869 'email-primary' => 'abc1.xyz1@yahoo.com',
870 'phone-1-1' => '021 512 755',
871 'country-1' => '1228',
872 'state_province-1' => '1021',
873 ];
874
875 return $profileData;
876 }
877
878 /**
879 * @return array
880 */
881 public function _createContactWithActivity() {
882 $ufGroupID = $this->callAPISuccess('UFGroup', 'create', [
883 'group_type' => 'Individual,Contact,Activity',
884 'title' => 'Test Contact-Activity Profile',
885 'name' => 'test_contact_activity_profile',
886 ])['id'];
887 $this->callAPISuccess('UFField', 'create', [
888 'uf_group_id' => $ufGroupID,
889 'field_name' => 'first_name',
890 'is_required' => TRUE,
891 'visibility' => 'Public Pages and Listings',
892 'label' => 'First Name',
893 'field_type' => 'Individual',
894 ]);
895 $this->callAPISuccess('UFField', 'create', [
896 'uf_group_id' => $ufGroupID,
897 'field_name' => 'last_name',
898 'is_required' => TRUE,
899 'visibility' => 'Public Pages and Listings',
900 'label' => 'Last Name',
901 'field_type' => 'Individual',
902 ]);
903 $this->callAPISuccess('UFField', 'create', [
904 'uf_group_id' => $ufGroupID,
905 'field_name' => 'email',
906 'is_required' => TRUE,
907 'visibility' => 'Public Pages and Listings',
908 'label' => 'Email',
909 'field_type' => 'Contact',
910 ]);
911 $this->callAPISuccess('UFField', 'create', [
912 'uf_group_id' => $ufGroupID,
913 'field_name' => 'activity_subject',
914 'is_required' => TRUE,
915 'visibility' => 'Public Pages and Listings',
916 'label' => 'Activity Subject',
917 'is_searchable' => TRUE,
918 'field_type' => 'Activity',
919 ]);
920 $this->callAPISuccess('UFField', 'create', [
921 'uf_group_id' => $ufGroupID,
922 'field_name' => 'activity_details',
923 'is_required' => TRUE,
924 'visibility' => 'Public Pages and Listings',
925 'label' => 'Activity Details',
926 'is_searchable' => TRUE,
927 'field_type' => 'Activity',
928 ]);
929 $this->callAPISuccess('UFField', 'create', [
930 'uf_group_id' => $ufGroupID,
931 'field_name' => 'activity_duration',
932 'is_required' => TRUE,
933 'visibility' => 'Public Pages and Listings',
934 'label' => 'Activity Duration',
935 'is_searchable' => TRUE,
936 'field_type' => 'Activity',
937 ]);
938 $this->callAPISuccess('UFField', 'create', [
939 'uf_group_id' => $ufGroupID,
940 'field_name' => 'activity_date_time',
941 'is_required' => TRUE,
942 'visibility' => 'Public Pages and Listings',
943 'label' => 'Activity Date',
944 'is_searchable' => TRUE,
945 'field_type' => 'Activity',
946 ]);
947 $this->callAPISuccess('UFField', 'create', [
948 'uf_group_id' => $ufGroupID,
949 'field_name' => 'activity_status_id',
950 'is_required' => TRUE,
951 'visibility' => 'Public Pages and Listings',
952 'label' => 'Activity Status',
953 'is_searchable' => TRUE,
954 'field_type' => 'Activity',
955 ]);
956
957 // hack: xml data set did not accept \ 1 (CRM_Core_DAO::VALUE_SEPARATOR) - should be possible
958 // to unhack now we use the api.
959 CRM_Core_DAO::setFieldValue('CRM_Core_DAO_UFGroup', $ufGroupID, 'group_type', 'Individual,Contact,Activity' . CRM_Core_DAO::VALUE_SEPARATOR . 'ActivityType:1');
960
961 $sourceContactId = $this->individualCreate();
962 $contactParams = [
963 'first_name' => 'abc1',
964 'last_name' => 'xyz1',
965 'contact_type' => 'Individual',
966 'email' => 'abc1.xyz1@yahoo.com',
967 'api.address.create' => [
968 'location_type_id' => 1,
969 'is_primary' => 1,
970 'name' => 'Saint Helier St',
971 'county' => 'Marin',
972 'country' => 'UNITED STATES',
973 'state_province' => 'Michigan',
974 'supplemental_address_1' => 'Hallmark Ct',
975 'supplemental_address_2' => 'Jersey Village',
976 'supplemental_address_3' => 'My Town',
977 ],
978 ];
979
980 $contact = $this->callAPISuccess('contact', 'create', $contactParams);
981
982 $keys = array_keys($contact['values']);
983 $contactId = array_pop($keys);
984
985 $this->assertEquals(0, $contact['values'][$contactId]['api.address.create']['is_error'], " error message: " . CRM_Utils_Array::value('error_message', $contact['values'][$contactId]['api.address.create'])
986 );
987
988 $activityParams = [
989 'source_contact_id' => $sourceContactId,
990 'assignee_contact_id' => $contactId,
991 'activity_type_id' => '1',
992 'subject' => 'Make-it-Happen Meeting',
993 'activity_date_time' => '2011-03-16 00:00:00',
994 'duration' => '120',
995 'location' => 'Pennsylvania',
996 'details' => 'a test activity',
997 'status_id' => '1',
998 'priority_id' => '1',
999 ];
1000 $activity = $this->callAPISuccess('activity', 'create', $activityParams);
1001
1002 $activityValues = array_pop($activity['values']);
1003
1004 // valid parameters for above profile
1005 $profileParams = [
1006 'profile_id' => $ufGroupID,
1007 'contact_id' => $contactId,
1008 'activity_id' => $activityValues['id'],
1009 ];
1010
1011 // expected result of above created profile
1012 $expected = [
1013 'first_name' => 'abc1',
1014 'last_name' => 'xyz1',
1015 'email-Primary' => 'abc1.xyz1@yahoo.com',
1016 'activity_subject' => 'Make-it-Happen Meeting',
1017 'activity_details' => 'a test activity',
1018 'activity_duration' => '120',
1019 'activity_date_time' => '2011-03-16 00:00:00',
1020 'activity_status_id' => '1',
1021 ];
1022
1023 return [$profileParams, $expected];
1024 }
1025
1026 /**
1027 * Create a profile.
1028 */
1029 public function _createIndividualProfile() {
1030 $ufGroupParams = [
1031 'group_type' => 'Individual,Contact',
1032 // really we should remove this & test the ufField create sets it
1033 'name' => 'test_individual_contact_profile',
1034 'title' => 'Flat Coffee',
1035 'api.uf_field.create' => [
1036 [
1037 'field_name' => 'first_name',
1038 'is_required' => 1,
1039 'visibility' => 'Public Pages and Listings',
1040 'field_type' => 'Individual',
1041 'label' => 'First Name',
1042 ],
1043 [
1044 'field_name' => 'last_name',
1045 'is_required' => 1,
1046 'visibility' => 'Public Pages and Listings',
1047 'field_type' => 'Individual',
1048 'label' => 'Last Name',
1049 ],
1050 [
1051 'field_name' => 'email',
1052 'is_required' => 1,
1053 'visibility' => 'Public Pages and Listings',
1054 'field_type' => 'Contact',
1055 'label' => 'Email',
1056 ],
1057 [
1058 'field_name' => 'phone',
1059 'is_required' => 1,
1060 'visibility' => 'Public Pages and Listings',
1061 'field_type' => 'Contact',
1062 'location_type_id' => 1,
1063 'phone_type_id' => 1,
1064 'label' => 'Phone',
1065 ],
1066 [
1067 'field_name' => 'country',
1068 'is_required' => 1,
1069 'visibility' => 'Public Pages and Listings',
1070 'field_type' => 'Contact',
1071 'location_type_id' => 1,
1072 'label' => 'Country',
1073 ],
1074 [
1075 'field_name' => 'state_province',
1076 'is_required' => 1,
1077 'visibility' => 'Public Pages and Listings',
1078 'field_type' => 'Contact',
1079 'location_type_id' => 1,
1080 'label' => 'State Province',
1081 ],
1082 [
1083 'field_name' => 'postal_code',
1084 'is_required' => 0,
1085 'field_type' => 'Contact',
1086 'location_type_id' => 1,
1087 'label' => 'State Province',
1088 ],
1089 ],
1090 ];
1091 $profile = $this->callAPISuccess('uf_group', 'create', $ufGroupParams);
1092 $this->_profileID = $profile['id'];
1093 }
1094
1095 /**
1096 * @param int $profileID
1097 */
1098 public function _addCustomFieldToProfile($profileID) {
1099 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, '');
1100 $this->uFFieldCreate([
1101 'uf_group_id' => $profileID,
1102 'field_name' => 'custom_' . $ids['custom_field_id'],
1103 'contact_type' => 'Contact',
1104 ]);
1105 }
1106
1107 }