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