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