Merge pull request #8906 from dejan9393/CRM-19244
[civicrm-core.git] / tests / phpunit / api / v3 / ContactTest.php
1 <?php
2 /**
3 * @file
4 * File for the TestContact class.
5 *
6 * (PHP 5)
7 *
8 * @author Walt Haas <walt@dharmatech.org> (801) 534-1262
9 * @copyright Copyright CiviCRM LLC (C) 2009
10 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html
11 * GNU Affero General Public License version 3
12 * @version $Id: ContactTest.php 31254 2010-12-15 10:09:29Z eileen $
13 * @package CiviCRM
14 *
15 * This file is part of CiviCRM
16 *
17 * CiviCRM is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Affero General Public License
19 * as published by the Free Software Foundation; either version 3 of
20 * the License, or (at your option) any later version.
21 *
22 * CiviCRM is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU Affero General Public License for more details.
26 *
27 * You should have received a copy of the GNU Affero General Public
28 * License along with this program. If not, see
29 * <http://www.gnu.org/licenses/>.
30 */
31
32 /**
33 * Test APIv3 civicrm_contact* functions
34 *
35 * @package CiviCRM_APIv3
36 * @subpackage API_Contact
37 * @group headless
38 */
39 class api_v3_ContactTest extends CiviUnitTestCase {
40 public $DBResetRequired = FALSE;
41 protected $_apiversion;
42 protected $_entity;
43 protected $_params;
44
45 protected $_contactID;
46 protected $_financialTypeId = 1;
47
48 /**
49 * Test setup for every test.
50 *
51 * Connect to the database, truncate the tables that will be used
52 * and redirect stdin to a temporary file
53 */
54 public function setUp() {
55 // Connect to the database.
56 parent::setUp();
57 $this->_apiversion = 3;
58 $this->_entity = 'contact';
59 $this->_params = array(
60 'first_name' => 'abc1',
61 'contact_type' => 'Individual',
62 'last_name' => 'xyz1',
63 );
64 }
65
66 /**
67 * Restore the DB for the next test.
68 *
69 * @throws \Exception
70 */
71 public function tearDown() {
72 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
73 // truncate a few tables
74 $tablesToTruncate = array(
75 'civicrm_email',
76 'civicrm_contribution',
77 'civicrm_line_item',
78 'civicrm_website',
79 'civicrm_relationship',
80 'civicrm_uf_match',
81 'civicrm_phone',
82 'civicrm_address',
83 'civicrm_acl_contact_cache',
84 'civicrm_activity_contact',
85 'civicrm_activity',
86 );
87
88 $this->quickCleanup($tablesToTruncate, TRUE);
89 parent::tearDown();
90 }
91
92 /**
93 * Test civicrm_contact_create.
94 *
95 * Verify that attempt to create individual contact with only
96 * first and last names succeeds
97 */
98 public function testAddCreateIndividual() {
99 $oldCount = CRM_Core_DAO::singleValueQuery('select count(*) from civicrm_contact');
100 $params = array(
101 'first_name' => 'abc1',
102 'contact_type' => 'Individual',
103 'last_name' => 'xyz1',
104 );
105
106 $contact = $this->callAPISuccess('contact', 'create', $params);
107 $this->assertTrue(is_numeric($contact['id']));
108 $this->assertTrue($contact['id'] > 0);
109 $newCount = CRM_Core_DAO::singleValueQuery('select count(*) from civicrm_contact');
110 $this->assertEquals($oldCount + 1, $newCount);
111
112 $this->assertDBState('CRM_Contact_DAO_Contact',
113 $contact['id'],
114 $params
115 );
116 }
117
118 /**
119 * Test for international string acceptance (CRM-10210).
120 *
121 * @dataProvider getInternationalStrings
122 *
123 * @param string $string
124 * String to be tested.
125 *
126 * @throws \Exception
127 */
128 public function testInternationalStrings($string) {
129 $this->callAPISuccess('Contact', 'create', array_merge(
130 $this->_params,
131 array('first_name' => $string)
132 ));
133 $result = $this->callAPISuccessGetSingle('Contact', array('first_name' => $string));
134 $this->assertEquals($string, $result['first_name']);
135
136 $organizationParams = array(
137 'organization_name' => $string,
138 'contact_type' => 'Organization',
139 );
140
141 $this->callAPISuccess('Contact', 'create', $organizationParams);
142 $result = $this->callAPISuccessGetSingle('Contact', $organizationParams);
143 $this->assertEquals($string, $result['organization_name']);
144 }
145
146 /**
147 * Get international string data for testing against api calls.
148 */
149 public function getInternationalStrings() {
150 $invocations = array();
151 $invocations[] = array('Scarabée');
152 $invocations[] = array('Iñtërnâtiônàlizætiøn');
153 $invocations[] = array('これは日本語のテキストです。読めますか');
154 $invocations[] = array('देखें हिन्दी कैसी नजर आती है। अरे वाह ये तो नजर आती है।');
155 return $invocations;
156 }
157
158 /**
159 * Test civicrm_contact_create.
160 *
161 * Verify that preferred language can be set.
162 */
163 public function testAddCreateIndividualWithPreferredLanguage() {
164 $params = array(
165 'first_name' => 'abc1',
166 'contact_type' => 'Individual',
167 'last_name' => 'xyz1',
168 'preferred_language' => 'es_ES',
169 );
170
171 $contact = $this->callAPISuccess('contact', 'create', $params);
172 $this->getAndCheck($params, $contact['id'], 'Contact');
173 }
174
175 /**
176 * Test civicrm_contact_create with sub-types.
177 *
178 * Verify that sub-types are created successfully and not deleted by subsequent updates.
179 */
180 public function testIndividualSubType() {
181 $params = array(
182 'first_name' => 'test abc',
183 'contact_type' => 'Individual',
184 'last_name' => 'test xyz',
185 'contact_sub_type' => array('Student', 'Staff'),
186 );
187 $contact = $this->callAPISuccess('contact', 'create', $params);
188 $cid = $contact['id'];
189
190 $params = array(
191 'id' => $cid,
192 'middle_name' => 'foo',
193 );
194 $this->callAPISuccess('contact', 'create', $params);
195 unset($params['middle_name']);
196
197 $contact = $this->callAPISuccess('contact', 'get', $params);
198
199 $this->assertEquals(array('Student', 'Staff'), $contact['values'][$cid]['contact_sub_type']);
200 }
201
202 /**
203 * Verify that we can retreive contacts of different sub types
204 */
205 public function testGetMultipleContactSubTypes() {
206
207 // This test presumes that there are no parents or students in the dataset
208
209 // create a student
210 $student = $this->callAPISuccess('contact', 'create', array(
211 'email' => 'student@example.com',
212 'contact_type' => 'Individual',
213 'contact_sub_type' => 'Student',
214 ));
215
216 // create a parent
217 $parent = $this->callAPISuccess('contact', 'create', array(
218 'email' => 'parent@example.com',
219 'contact_type' => 'Individual',
220 'contact_sub_type' => 'Parent',
221 ));
222
223 // create a parent
224 $contact = $this->callAPISuccess('contact', 'create', array(
225 'email' => 'parent@example.com',
226 'contact_type' => 'Individual',
227 ));
228
229 // get all students and parents
230 $getParams = array('contact_sub_type' => array('IN' => array('Parent', 'Student')));
231 $result = civicrm_api3('contact', 'get', $getParams);
232
233 // check that we retrieved the student and the parent
234 $this->assertArrayHasKey($student['id'], $result['values']);
235 $this->assertArrayHasKey($parent['id'], $result['values']);
236 $this->assertEquals(2, $result['count']);
237
238 }
239
240
241 /**
242 * Verify that attempt to create contact with empty params fails.
243 */
244 public function testCreateEmptyContact() {
245 $this->callAPIFailure('contact', 'create', array());
246 }
247
248 /**
249 * Verify that attempt to create contact with bad contact type fails.
250 */
251 public function testCreateBadTypeContact() {
252 $params = array(
253 'email' => 'man1@yahoo.com',
254 'contact_type' => 'Does not Exist',
255 );
256 $this->callAPIFailure('contact', 'create', $params, "'Does not Exist' is not a valid option for field contact_type");
257 }
258
259 /**
260 * Verify that attempt to create individual contact without required fields fails.
261 */
262 public function testCreateBadRequiredFieldsIndividual() {
263 $params = array(
264 'middle_name' => 'This field is not required',
265 'contact_type' => 'Individual',
266 );
267 $this->callAPIFailure('contact', 'create', $params);
268 }
269
270 /**
271 * Verify that attempt to create household contact without required fields fails.
272 */
273 public function testCreateBadRequiredFieldsHousehold() {
274 $params = array(
275 'middle_name' => 'This field is not required',
276 'contact_type' => 'Household',
277 );
278 $this->callAPIFailure('contact', 'create', $params);
279 }
280
281 /**
282 * Test required field check.
283 *
284 * Verify that attempt to create organization contact without required fields fails.
285 */
286 public function testCreateBadRequiredFieldsOrganization() {
287 $params = array(
288 'middle_name' => 'This field is not required',
289 'contact_type' => 'Organization',
290 );
291
292 $this->callAPIFailure('contact', 'create', $params);
293 }
294
295 /**
296 * Verify that attempt to create individual contact with only an email succeeds.
297 */
298 public function testCreateEmailIndividual() {
299 $primaryEmail = 'man3@yahoo.com';
300 $notPrimaryEmail = 'man4@yahoo.com';
301 $params = array(
302 'email' => $primaryEmail,
303 'contact_type' => 'Individual',
304 'location_type_id' => 1,
305 );
306
307 $contact1 = $this->callAPISuccess('contact', 'create', $params);
308
309 $this->assertEquals(3, $contact1['id']);
310 $email1 = $this->callAPISuccess('email', 'get', array('contact_id' => $contact1['id']));
311 $this->assertEquals(1, $email1['count']);
312 $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
313
314 $email2 = $this->callAPISuccess('email', 'create', array('contact_id' => $contact1['id'], 'is_primary' => 0, 'email' => $notPrimaryEmail));
315
316 // Case 1: Check with criteria primary 'email' => array('IS NOT NULL' => 1)
317 $result = $this->callAPISuccess('contact', 'get', array('email' => array('IS NOT NULL' => 1)));
318 $primaryEmailContactIds = array_keys($result['values']);
319 $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
320
321 // Case 2: Check with criteria primary 'email' => array('<>' => '')
322 $result = $this->callAPISuccess('contact', 'get', array('email' => array('<>' => '')));
323 $primaryEmailContactIds = array_keys($result['values']);
324 $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
325
326 // Case 3: Check with email_id='primary email id'
327 $result = $this->callAPISuccess('contact', 'get', array('email_id' => $email1['id']));
328 $this->assertEquals(1, $result['count']);
329 $this->assertEquals($contact1['id'], $result['id']);
330
331 $this->callAPISuccess('contact', 'delete', $contact1);
332 }
333
334 /**
335 * Test creating individual by name.
336 *
337 * Verify create individual contact with only first and last names succeeds.
338 */
339 public function testCreateNameIndividual() {
340 $params = array(
341 'first_name' => 'abc1',
342 'contact_type' => 'Individual',
343 'last_name' => 'xyz1',
344 );
345
346 $this->callAPISuccess('contact', 'create', $params);
347 }
348
349 /**
350 * Test creating individual by display_name.
351 *
352 * Display name & sort name should be set.
353 */
354 public function testCreateDisplayNameIndividual() {
355 $params = array(
356 'display_name' => 'abc1',
357 'contact_type' => 'Individual',
358 );
359
360 $contact = $this->callAPISuccess('contact', 'create', $params);
361 $params['sort_name'] = 'abc1';
362 $this->getAndCheck($params, $contact['id'], 'contact');
363 }
364
365 /**
366 * Test old keys still work.
367 *
368 * Verify that attempt to create individual contact with
369 * first and last names and old key values works
370 */
371 public function testCreateNameIndividualOldKeys() {
372 $params = array(
373 'individual_prefix' => 'Dr.',
374 'first_name' => 'abc1',
375 'contact_type' => 'Individual',
376 'last_name' => 'xyz1',
377 'individual_suffix' => 'Jr.',
378 );
379
380 $contact = $this->callAPISuccess('contact', 'create', $params);
381 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
382
383 $this->assertArrayKeyExists('prefix_id', $result);
384 $this->assertArrayKeyExists('suffix_id', $result);
385 $this->assertArrayKeyExists('gender_id', $result);
386 $this->assertEquals(4, $result['prefix_id']);
387 $this->assertEquals(1, $result['suffix_id']);
388 }
389
390 /**
391 * Test preferred keys work.
392 *
393 * Verify that attempt to create individual contact with
394 * first and last names and old key values works
395 */
396 public function testCreateNameIndividualRecommendedKeys2() {
397 $params = array(
398 'prefix_id' => 'Dr.',
399 'first_name' => 'abc1',
400 'contact_type' => 'Individual',
401 'last_name' => 'xyz1',
402 'suffix_id' => 'Jr.',
403 'gender_id' => 'Male',
404 );
405
406 $contact = $this->callAPISuccess('contact', 'create', $params);
407 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
408
409 $this->assertArrayKeyExists('prefix_id', $result);
410 $this->assertArrayKeyExists('suffix_id', $result);
411 $this->assertArrayKeyExists('gender_id', $result);
412 $this->assertEquals(4, $result['prefix_id']);
413 $this->assertEquals(1, $result['suffix_id']);
414 }
415
416 /**
417 * Test household name is sufficient for create.
418 *
419 * Verify that attempt to create household contact with only
420 * household name succeeds
421 */
422 public function testCreateNameHousehold() {
423 $params = array(
424 'household_name' => 'The abc Household',
425 'contact_type' => 'Household',
426 );
427 $this->callAPISuccess('contact', 'create', $params);
428 }
429
430 /**
431 * Test organization name is sufficient for create.
432 *
433 * Verify that attempt to create organization contact with only
434 * organization name succeeds.
435 */
436 public function testCreateNameOrganization() {
437 $params = array(
438 'organization_name' => 'The abc Organization',
439 'contact_type' => 'Organization',
440 );
441 $this->callAPISuccess('contact', 'create', $params);
442 }
443
444 /**
445 * Verify that attempt to create organization contact without organization name fails.
446 */
447 public function testCreateNoNameOrganization() {
448 $params = array(
449 'first_name' => 'The abc Organization',
450 'contact_type' => 'Organization',
451 );
452 $this->callAPIFailure('contact', 'create', $params);
453 }
454
455 /**
456 * Check with complete array + custom field.
457 *
458 * Note that the test is written on purpose without any
459 * variables specific to participant so it can be replicated into other entities
460 * and / or moved to the automated test suite
461 */
462 public function testCreateWithCustom() {
463 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
464
465 $params = $this->_params;
466 $params['custom_' . $ids['custom_field_id']] = "custom string";
467 $description = "This demonstrates setting a custom field through the API.";
468 $result = $this->callAPIAndDocument($this->_entity, 'create', $params, __FUNCTION__, __FILE__, $description);
469
470 $check = $this->callAPISuccess($this->_entity, 'get', array(
471 'return.custom_' . $ids['custom_field_id'] => 1,
472 'id' => $result['id'],
473 ));
474 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
475
476 $this->customFieldDelete($ids['custom_field_id']);
477 $this->customGroupDelete($ids['custom_group_id']);
478 }
479
480 /**
481 * CRM-12773 - expectation is that civicrm quietly ignores fields without values.
482 */
483 public function testCreateWithNULLCustomCRM12773() {
484 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
485 $params = $this->_params;
486 $params['custom_' . $ids['custom_field_id']] = NULL;
487 $this->callAPISuccess('contact', 'create', $params);
488 $this->customFieldDelete($ids['custom_field_id']);
489 $this->customGroupDelete($ids['custom_group_id']);
490 }
491
492 /**
493 * CRM-14232 test preferred language set to site default if not passed.
494 */
495 public function testCreatePreferredLanguageUnset() {
496 $this->callAPISuccess('Contact', 'create', array(
497 'first_name' => 'Snoop',
498 'last_name' => 'Dog',
499 'contact_type' => 'Individual')
500 );
501 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
502 $this->assertEquals('en_US', $result['preferred_language']);
503 }
504
505 /**
506 * CRM-14232 test preferred language returns setting if not passed.
507 */
508 public function testCreatePreferredLanguageSet() {
509 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'fr_FR'));
510 $this->callAPISuccess('Contact', 'create', array(
511 'first_name' => 'Snoop',
512 'last_name' => 'Dog',
513 'contact_type' => 'Individual',
514 ));
515 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
516 $this->assertEquals('fr_FR', $result['preferred_language']);
517 }
518
519 /**
520 * CRM-14232 test preferred language returns setting if not passed where setting is NULL.
521 */
522 public function testCreatePreferredLanguageNull() {
523 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'null'));
524 $this->callAPISuccess('Contact', 'create', array(
525 'first_name' => 'Snoop',
526 'last_name' => 'Dog',
527 'contact_type' => 'Individual',
528 )
529 );
530 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
531 $this->assertEquals(NULL, $result['preferred_language']);
532 }
533
534 /**
535 * CRM-14232 test preferred language returns setting if not passed where setting is NULL.
536 */
537 public function testCreatePreferredLanguagePassed() {
538 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'null'));
539 $this->callAPISuccess('Contact', 'create', array(
540 'first_name' => 'Snoop',
541 'last_name' => 'Dog',
542 'contact_type' => 'Individual',
543 'preferred_language' => 'en_AU',
544 ));
545 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
546 $this->assertEquals('en_AU', $result['preferred_language']);
547 }
548
549 /**
550 * CRM-15792 - create/update datetime field for contact.
551 */
552 public function testCreateContactCustomFldDateTime() {
553 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'datetime_test_group'));
554 $dateTime = CRM_Utils_Date::currentDBDate();
555 //check date custom field is saved along with time when time_format is set
556 $params = array(
557 'first_name' => 'abc3',
558 'last_name' => 'xyz3',
559 'contact_type' => 'Individual',
560 'email' => 'man3@yahoo.com',
561 'api.CustomField.create' => array(
562 'custom_group_id' => $customGroup['id'],
563 'name' => 'test_datetime',
564 'label' => 'Demo Date',
565 'html_type' => 'Select Date',
566 'data_type' => 'Date',
567 'time_format' => 2,
568 'weight' => 4,
569 'is_required' => 1,
570 'is_searchable' => 0,
571 'is_active' => 1,
572 ),
573 );
574
575 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__);
576 $customFldId = $result['values'][$result['id']]['api.CustomField.create']['id'];
577 $this->assertNotNull($result['id']);
578 $this->assertNotNull($customFldId);
579
580 $params = array(
581 'id' => $result['id'],
582 "custom_{$customFldId}" => $dateTime,
583 'api.CustomValue.get' => 1,
584 );
585
586 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__);
587 $this->assertNotNull($result['id']);
588 $customFldDate = date("YmdHis", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
589 $this->assertNotNull($customFldDate);
590 $this->assertEquals($dateTime, $customFldDate);
591 $customValueId = $result['values'][$result['id']]['api.CustomValue.get']['values'][0]['id'];
592 $dateTime = date('Ymd');
593 //date custom field should not contain time part when time_format is null
594 $params = array(
595 'id' => $result['id'],
596 'api.CustomField.create' => array(
597 'id' => $customFldId,
598 'html_type' => 'Select Date',
599 'data_type' => 'Date',
600 'time_format' => '',
601 ),
602 'api.CustomValue.create' => array(
603 'id' => $customValueId,
604 'entity_id' => $result['id'],
605 "custom_{$customFldId}" => $dateTime,
606 ),
607 'api.CustomValue.get' => 1,
608 );
609 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__);
610 $this->assertNotNull($result['id']);
611 $customFldDate = date("Ymd", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
612 $customFldTime = date("His", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
613 $this->assertNotNull($customFldDate);
614 $this->assertEquals($dateTime, $customFldDate);
615 $this->assertEquals(000000, $customFldTime);
616 $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__);
617 }
618
619
620 /**
621 * Test creating a current employer through API.
622 */
623 public function testContactCreateCurrentEmployer() {
624 // Here we will just do the get for set-up purposes.
625 $count = $this->callAPISuccess('contact', 'getcount', array(
626 'organization_name' => 'new employer org',
627 'contact_type' => 'Organization',
628 ));
629 $this->assertEquals(0, $count);
630 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
631 'current_employer' => 'new employer org',
632 )
633 ));
634 // do it again as an update to check it doesn't cause an error
635 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
636 'current_employer' => 'new employer org',
637 'id' => $employerResult['id'],
638 )
639 ));
640 $expectedCount = 1;
641 $this->callAPISuccess('contact', 'getcount', array(
642 'organization_name' => 'new employer org',
643 'contact_type' => 'Organization',
644 ),
645 $expectedCount);
646
647 $result = $this->callAPISuccess('contact', 'getsingle', array(
648 'id' => $employerResult['id'],
649 ));
650
651 $this->assertEquals('new employer org', $result['current_employer']);
652
653 }
654
655 /**
656 * Test creating a current employer through API.
657 *
658 * Check it will re-activate a de-activated employer
659 */
660 public function testContactCreateDuplicateCurrentEmployerEnables() {
661 // Set up - create employer relationship.
662 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
663 'current_employer' => 'new employer org',
664 )
665 ));
666 $relationship = $this->callAPISuccess('relationship', 'get', array(
667 'contact_id_a' => $employerResult['id'],
668 ));
669
670 //disable & check it is disabled
671 $this->callAPISuccess('relationship', 'create', array('id' => $relationship['id'], 'is_active' => 0));
672 $this->callAPISuccess('relationship', 'getvalue', array(
673 'id' => $relationship['id'],
674 'return' => 'is_active',
675 ), 0);
676
677 // Re-set the current employer - thus enabling the relationship.
678 $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
679 'current_employer' => 'new employer org',
680 'id' => $employerResult['id'],
681 )
682 ));
683 //check is_active is now 1
684 $relationship = $this->callAPISuccess('relationship', 'getsingle', array(
685 'return' => 'is_active',
686 ));
687 $this->assertEquals(1, $relationship['is_active']);
688 }
689
690 /**
691 * Check deceased contacts are not retrieved.
692 *
693 * Note at time of writing the default is to return default. This should possibly be changed & test added.
694 */
695 public function testGetDeceasedRetrieved() {
696 $this->callAPISuccess($this->_entity, 'create', $this->_params);
697 $c2 = $this->callAPISuccess($this->_entity, 'create', array(
698 'first_name' => 'bb',
699 'last_name' => 'ccc',
700 'contact_type' => 'Individual',
701 'is_deceased' => 1,
702 ));
703 $result = $this->callAPISuccess($this->_entity, 'get', array('is_deceased' => 0));
704 $this->assertFalse(array_key_exists($c2['id'], $result['values']));
705 }
706
707 /**
708 * Test that sort works - old syntax.
709 */
710 public function testGetSort() {
711 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
712 $c2 = $this->callAPISuccess($this->_entity, 'create', array(
713 'first_name' => 'bb',
714 'last_name' => 'ccc',
715 'contact_type' => 'Individual',
716 ));
717 $result = $this->callAPISuccess($this->_entity, 'get', array(
718 'sort' => 'first_name ASC',
719 'return.first_name' => 1,
720 'sequential' => 1,
721 'rowCount' => 1,
722 'contact_type' => 'Individual',
723 ));
724
725 $this->assertEquals('abc1', $result['values'][0]['first_name']);
726 $result = $this->callAPISuccess($this->_entity, 'get', array(
727 'sort' => 'first_name DESC',
728 'return.first_name' => 1,
729 'sequential' => 1,
730 'rowCount' => 1,
731 ));
732 $this->assertEquals('bb', $result['values'][0]['first_name']);
733
734 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
735 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
736 }
737
738 /**
739 * Test that we can retrieve contacts using array syntax.
740 *
741 * I.e 'id' => array('IN' => array('3,4')).
742 */
743 public function testGetINIDArray() {
744 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
745 $c2 = $this->callAPISuccess($this->_entity, 'create', array(
746 'first_name' => 'bb',
747 'last_name' => 'ccc',
748 'contact_type' => 'Individual',
749 ));
750 $c3 = $this->callAPISuccess($this->_entity, 'create', array(
751 'first_name' => 'hh',
752 'last_name' => 'll',
753 'contact_type' => 'Individual',
754 ));
755 $result = $this->callAPISuccess($this->_entity, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
756 $this->assertEquals(2, $result['count']);
757 $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
758 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
759 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
760 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c3['id']));
761 }
762
763 /**
764 * Test variants on deleted behaviour.
765 */
766 public function testGetDeleted() {
767 $params = $this->_params;
768 $contact1 = $this->callAPISuccess('contact', 'create', $params);
769 $params['is_deleted'] = 1;
770 $params['last_name'] = 'bcd';
771 $contact2 = $this->callAPISuccess('contact', 'create', $params);
772 $countActive = $this->callAPISuccess('contact', 'getcount', array(
773 'showAll' => 'active',
774 'contact_type' => 'Individual',
775 ));
776 $countAll = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'all', 'contact_type' => 'Individual'));
777 $countTrash = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'trash', 'contact_type' => 'Individual'));
778 $countDefault = $this->callAPISuccess('contact', 'getcount', array('contact_type' => 'Individual'));
779 $countDeleted = $this->callAPISuccess('contact', 'getcount', array(
780 'contact_type' => 'Individual',
781 'contact_is_deleted' => 1,
782 ));
783 $countNotDeleted = $this->callAPISuccess('contact', 'getcount', array(
784 'contact_is_deleted' => 0,
785 'contact_type' => 'Individual',
786 ));
787 $this->callAPISuccess('contact', 'delete', array('id' => $contact1['id']));
788 $this->callAPISuccess('contact', 'delete', array('id' => $contact2['id']));
789 $this->assertEquals(1, $countNotDeleted, 'contact_is_deleted => 0 is respected');
790 $this->assertEquals(1, $countActive);
791 $this->assertEquals(1, $countTrash);
792 $this->assertEquals(2, $countAll);
793 $this->assertEquals(1, $countDeleted);
794 $this->assertEquals(1, $countDefault, 'Only active by default in line');
795 }
796
797 /**
798 * Test that sort works - new syntax.
799 */
800 public function testGetSortNewSyntax() {
801 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
802 $c2 = $this->callAPISuccess($this->_entity, 'create', array(
803 'first_name' => 'bb',
804 'last_name' => 'ccc',
805 'contact_type' => 'Individual',
806 ));
807 $result = $this->callAPISuccess($this->_entity, 'getvalue', array(
808 'return' => 'first_name',
809 'contact_type' => 'Individual',
810 'options' => array(
811 'limit' => 1,
812 'sort' => 'first_name',
813 ),
814 ));
815 $this->assertEquals('abc1', $result);
816
817 $result = $this->callAPISuccess($this->_entity, 'getvalue', array(
818 'return' => 'first_name',
819 'contact_type' => 'Individual',
820 'options' => array(
821 'limit' => 1,
822 'sort' => 'first_name DESC',
823 ),
824 ));
825 $this->assertEquals('bb', $result);
826
827 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
828 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
829 }
830
831 /**
832 * Test sort and limit for chained relationship get.
833 *
834 * https://issues.civicrm.org/jira/browse/CRM-15983
835 */
836 public function testSortLimitChainedRelationshipGetCRM15983() {
837 // Some contact
838 $create_result_1 = $this->callAPISuccess('contact', 'create', array(
839 'first_name' => 'Jules',
840 'last_name' => 'Smos',
841 'contact_type' => 'Individual',
842 ));
843
844 // Create another contact with two relationships.
845 $create_params = array(
846 'first_name' => 'Jos',
847 'last_name' => 'Smos',
848 'contact_type' => 'Individual',
849 'api.relationship.create' => array(
850 array(
851 'contact_id_a' => '$value.id',
852 'contact_id_b' => $create_result_1['id'],
853 // spouse of:
854 'relationship_type_id' => 2,
855 'start_date' => '2005-01-12',
856 'end_date' => '2006-01-11',
857 'description' => 'old',
858 ),
859 array(
860 'contact_id_a' => '$value.id',
861 'contact_id_b' => $create_result_1['id'],
862 // spouse of (was married twice :))
863 'relationship_type_id' => 2,
864 'start_date' => '2006-07-01',
865 'end_date' => '2010-07-01',
866 'description' => 'new',
867 ),
868 ),
869 );
870 $create_result = $this->callAPISuccess('contact', 'create', $create_params);
871
872 // Try to retrieve the contact and the most recent relationship.
873 $get_params = array(
874 'sequential' => 1,
875 'id' => $create_result['id'],
876 'api.relationship.get' => array(
877 'contact_id_a' => '$value.id',
878 'options' => array(
879 'limit' => '1',
880 'sort' => 'start_date DESC',
881 )),
882 );
883 $get_result = $this->callAPISuccess('contact', 'getsingle', $get_params);
884
885 // Clean up.
886 $this->callAPISuccess('contact', 'delete', array(
887 'id' => $create_result['id'],
888 ));
889
890 // Assert.
891 $this->assertEquals(1, $get_result['api.relationship.get']['count']);
892 $this->assertEquals('new', $get_result['api.relationship.get']['values'][0]['description']);
893 }
894
895 /**
896 * Test apostrophe works in get & create.
897 */
898 public function testGetApostropheCRM10857() {
899 $params = array_merge($this->_params, array('last_name' => "O'Connor"));
900 $this->callAPISuccess($this->_entity, 'create', $params);
901 $result = $this->callAPISuccess($this->_entity, 'getsingle', array(
902 'last_name' => "O'Connor",
903 'sequential' => 1,
904 ));
905 $this->assertEquals("O'Connor", $result['last_name'], 'in line' . __LINE__);
906 }
907
908 /**
909 * Check with complete array + custom field.
910 *
911 * Note that the test is written on purpose without any
912 * variables specific to participant so it can be replicated into other entities
913 * and / or moved to the automated test suite
914 */
915 public function testGetWithCustom() {
916 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
917
918 $params = $this->_params;
919 $params['custom_' . $ids['custom_field_id']] = "custom string";
920 $description = "This demonstrates setting a custom field through the API.";
921 $subfile = "CustomFieldGet";
922 $result = $this->callAPISuccess($this->_entity, 'create', $params);
923
924 $check = $this->callAPIAndDocument($this->_entity, 'get', array(
925 'return.custom_' . $ids['custom_field_id'] => 1,
926 'id' => $result['id'],
927 ), __FUNCTION__, __FILE__, $description, $subfile);
928
929 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
930 $fields = ($this->callAPISuccess('contact', 'getfields', $params));
931 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
932 $this->customFieldDelete($ids['custom_field_id']);
933 $this->customGroupDelete($ids['custom_group_id']);
934 }
935
936 /**
937 * Check with complete array + custom field.
938 *
939 * Note that the test is written on purpose without any
940 * variables specific to participant so it can be replicated into other entities
941 * and / or moved to the automated test suite
942 */
943 public function testGetWithCustomReturnSyntax() {
944 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
945
946 $params = $this->_params;
947 $params['custom_' . $ids['custom_field_id']] = "custom string";
948 $description = "This demonstrates setting a custom field through the API.";
949 $subfile = "CustomFieldGetReturnSyntaxVariation";
950 $result = $this->callAPISuccess($this->_entity, 'create', $params);
951 $params = array('return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']);
952 $check = $this->callAPIAndDocument($this->_entity, 'get', $params, __FUNCTION__, __FILE__, $description, $subfile);
953
954 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
955 $this->customFieldDelete($ids['custom_field_id']);
956 $this->customGroupDelete($ids['custom_group_id']);
957 }
958
959 /**
960 * Check that address name, ID is returned if required.
961 */
962 public function testGetReturnAddress() {
963 $contactID = $this->individualCreate();
964 $result = $this->callAPISuccess('address', 'create', array(
965 'contact_id' => $contactID,
966 'address_name' => 'My house',
967 'location_type_id' => 'Home',
968 'street_address' => '1 my road',
969 ));
970 $addressID = $result['id'];
971
972 $result = $this->callAPISuccessGetSingle('contact', array(
973 'return' => 'address_name, street_address, address_id',
974 'id' => $contactID,
975 ));
976 $this->assertEquals($addressID, $result['address_id']);
977 $this->assertEquals('1 my road', $result['street_address']);
978 $this->assertEquals('My house', $result['address_name']);
979
980 }
981
982 /**
983 * Test group filter syntaxes.
984 */
985 public function testGetGroupIDFromContact() {
986 $groupId = $this->groupCreate();
987 $description = "Get all from group and display contacts.";
988 $subFile = "GroupFilterUsingContactAPI";
989 $params = array(
990 'email' => 'man2@yahoo.com',
991 'contact_type' => 'Individual',
992 'location_type_id' => 1,
993 'api.group_contact.create' => array('group_id' => $groupId),
994 );
995
996 $this->callAPISuccess('contact', 'create', $params);
997 // testing as integer
998 $params = array(
999 'filter.group_id' => $groupId,
1000 'contact_type' => 'Individual',
1001 );
1002 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__, $description, $subFile);
1003 $this->assertEquals(1, $result['count']);
1004 // group 26 doesn't exist, but we can still search contacts in it.
1005 $params = array(
1006 'filter.group_id' => 26,
1007 'contact_type' => 'Individual',
1008 );
1009 $this->callAPISuccess('contact', 'get', $params);
1010 // testing as string
1011 $params = array(
1012 'filter.group_id' => "$groupId, 26",
1013 'contact_type' => 'Individual',
1014 );
1015 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__, $description, $subFile);
1016 $this->assertEquals(1, $result['count']);
1017 $params = array(
1018 'filter.group_id' => "26,27",
1019 'contact_type' => 'Individual',
1020 );
1021 $this->callAPISuccess('contact', 'get', $params);
1022
1023 // testing as string
1024 $params = array(
1025 'filter.group_id' => array($groupId, 26),
1026 'contact_type' => 'Individual',
1027 );
1028 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__, $description, $subFile);
1029 $this->assertEquals(1, $result['count']);
1030
1031 //test in conjunction with other criteria
1032 $params = array(
1033 'filter.group_id' => array($groupId, 26),
1034 'contact_type' => 'Organization',
1035 );
1036 $this->callAPISuccess('contact', 'get', $params);
1037 $params = array(
1038 'filter.group_id' => array(26, 27),
1039 'contact_type' => 'Individual',
1040 );
1041 $result = $this->callAPISuccess('contact', 'get', $params);
1042 $this->assertEquals(0, $result['count']);
1043 }
1044
1045 /**
1046 * Verify that attempt to create individual contact with two chained websites succeeds.
1047 */
1048 public function testCreateIndividualWithContributionDottedSyntax() {
1049 $description = "This demonstrates the syntax to create 2 chained entities.";
1050 $subFile = "ChainTwoWebsites";
1051 $params = array(
1052 'first_name' => 'abc3',
1053 'last_name' => 'xyz3',
1054 'contact_type' => 'Individual',
1055 'email' => 'man3@yahoo.com',
1056 'api.contribution.create' => array(
1057 'receive_date' => '2010-01-01',
1058 'total_amount' => 100.00,
1059 'financial_type_id' => $this->_financialTypeId,
1060 'payment_instrument_id' => 1,
1061 'non_deductible_amount' => 10.00,
1062 'fee_amount' => 50.00,
1063 'net_amount' => 90.00,
1064 'trxn_id' => 15345,
1065 'invoice_id' => 67990,
1066 'source' => 'SSF',
1067 'contribution_status_id' => 1,
1068 ),
1069 'api.website.create' => array(
1070 'url' => "http://civicrm.org",
1071 ),
1072 'api.website.create.2' => array(
1073 'url' => "http://chained.org",
1074 ),
1075 );
1076
1077 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__, $description, $subFile);
1078
1079 // checking child function result not covered in callAPIAndDocument
1080 $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
1081 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url']);
1082 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url']);
1083
1084 // delete the contact
1085 $this->callAPISuccess('contact', 'delete', $result);
1086 }
1087
1088 /**
1089 * Verify that attempt to create individual contact with chained contribution and website succeeds.
1090 */
1091 public function testCreateIndividualWithContributionChainedArrays() {
1092 $params = array(
1093 'first_name' => 'abc3',
1094 'last_name' => 'xyz3',
1095 'contact_type' => 'Individual',
1096 'email' => 'man3@yahoo.com',
1097 'api.contribution.create' => array(
1098 'receive_date' => '2010-01-01',
1099 'total_amount' => 100.00,
1100 'financial_type_id' => $this->_financialTypeId,
1101 'payment_instrument_id' => 1,
1102 'non_deductible_amount' => 10.00,
1103 'fee_amount' => 50.00,
1104 'net_amount' => 90.00,
1105 'trxn_id' => 12345,
1106 'invoice_id' => 67890,
1107 'source' => 'SSF',
1108 'contribution_status_id' => 1,
1109 ),
1110 'api.website.create' => array(
1111 array(
1112 'url' => "http://civicrm.org",
1113 ),
1114 array(
1115 'url' => "http://chained.org",
1116 'website_type_id' => 2,
1117 ),
1118 ),
1119 );
1120
1121 $description = "Demonstrates creating two websites as an array.";
1122 $subfile = "ChainTwoWebsitesSyntax2";
1123 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__, $description, $subfile);
1124
1125 // the callAndDocument doesn't check the chained call
1126 $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error']);
1127 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url']);
1128 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url']);
1129
1130 $this->callAPISuccess('contact', 'delete', $result);
1131 }
1132
1133 /**
1134 * Test for direction when chaining relationships.
1135 *
1136 * https://issues.civicrm.org/jira/browse/CRM-16084
1137 */
1138 public function testDirectionChainingRelationshipsCRM16084() {
1139 // Some contact, called Jules.
1140 $create_result_1 = $this->callAPISuccess('contact', 'create', array(
1141 'first_name' => 'Jules',
1142 'last_name' => 'Smos',
1143 'contact_type' => 'Individual',
1144 ));
1145
1146 // Another contact: Jos, child of Jules.
1147 $create_params = array(
1148 'first_name' => 'Jos',
1149 'last_name' => 'Smos',
1150 'contact_type' => 'Individual',
1151 'api.relationship.create' => array(
1152 array(
1153 'contact_id_a' => '$value.id',
1154 'contact_id_b' => $create_result_1['id'],
1155 // child of
1156 'relationship_type_id' => 1,
1157 ),
1158 ),
1159 );
1160 $create_result_2 = $this->callAPISuccess('contact', 'create', $create_params);
1161
1162 // Mia is the child of Jos.
1163 $create_params = array(
1164 'first_name' => 'Mia',
1165 'last_name' => 'Smos',
1166 'contact_type' => 'Individual',
1167 'api.relationship.create' => array(
1168 array(
1169 'contact_id_a' => '$value.id',
1170 'contact_id_b' => $create_result_2['id'],
1171 // child of
1172 'relationship_type_id' => 1,
1173 ),
1174 ),
1175 );
1176 $create_result_3 = $this->callAPISuccess('contact', 'create', $create_params);
1177
1178 // Get Jos and his children.
1179 $get_params = array(
1180 'sequential' => 1,
1181 'id' => $create_result_2['id'],
1182 'api.relationship.get' => array(
1183 'contact_id_b' => '$value.id',
1184 'relationship_type_id' => 1,
1185 ),
1186 );
1187 $get_result = $this->callAPISuccess('contact', 'getsingle', $get_params);
1188
1189 // Clean up first.
1190 $this->callAPISuccess('contact', 'delete', array(
1191 'id' => $create_result_1['id'],
1192 ));
1193 $this->callAPISuccess('contact', 'delete', array(
1194 'id' => $create_result_2['id'],
1195 ));
1196 $this->callAPISuccess('contact', 'delete', array(
1197 'id' => $create_result_2['id'],
1198 ));
1199
1200 // Assert.
1201 $this->assertEquals(1, $get_result['api.relationship.get']['count']);
1202 $this->assertEquals($create_result_3['id'], $get_result['api.relationship.get']['values'][0]['contact_id_a']);
1203 }
1204
1205 /**
1206 * Verify that attempt to create individual contact with first, and last names and email succeeds.
1207 */
1208 public function testCreateIndividualWithNameEmail() {
1209 $params = array(
1210 'first_name' => 'abc3',
1211 'last_name' => 'xyz3',
1212 'contact_type' => 'Individual',
1213 'email' => 'man3@yahoo.com',
1214 );
1215
1216 $contact = $this->callAPISuccess('contact', 'create', $params);
1217
1218 $this->callAPISuccess('contact', 'delete', $contact);
1219 }
1220
1221 /**
1222 * Verify that attempt to create individual contact with no data fails.
1223 */
1224 public function testCreateIndividualWithOutNameEmail() {
1225 $params = array(
1226 'contact_type' => 'Individual',
1227 );
1228 $this->callAPIFailure('contact', 'create', $params);
1229 }
1230
1231 /**
1232 * Test create individual contact with first &last names, email and location type succeeds.
1233 */
1234 public function testCreateIndividualWithNameEmailLocationType() {
1235 $params = array(
1236 'first_name' => 'abc4',
1237 'last_name' => 'xyz4',
1238 'email' => 'man4@yahoo.com',
1239 'contact_type' => 'Individual',
1240 'location_type_id' => 1,
1241 );
1242 $result = $this->callAPISuccess('contact', 'create', $params);
1243
1244 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
1245 }
1246
1247 /**
1248 * Verify that when changing employers the old employer relationship becomes inactive.
1249 */
1250 public function testCreateIndividualWithEmployer() {
1251 $employer = $this->organizationCreate();
1252 $employer2 = $this->organizationCreate();
1253
1254 $params = array(
1255 'email' => 'man4@yahoo.com',
1256 'contact_type' => 'Individual',
1257 'employer_id' => $employer,
1258 );
1259
1260 $result = $this->callAPISuccess('contact', 'create', $params);
1261 $relationships = $this->callAPISuccess('relationship', 'get', array(
1262 'contact_id_a' => $result['id'],
1263 'sequential' => 1,
1264 ));
1265
1266 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
1267
1268 // Add more random relationships to make the test more realistic
1269 foreach (array('Employee of', 'Volunteer for') as $relationshipType) {
1270 $relTypeId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', $relationshipType, 'id', 'name_a_b');
1271 $this->callAPISuccess('relationship', 'create', array(
1272 'contact_id_a' => $result['id'],
1273 'contact_id_b' => $this->organizationCreate(),
1274 'is_active' => 1,
1275 'relationship_type_id' => $relTypeId,
1276 ));
1277 }
1278
1279 // Add second employer
1280 $params['employer_id'] = $employer2;
1281 $params['id'] = $result['id'];
1282 $result = $this->callAPISuccess('contact', 'create', $params);
1283
1284 $relationships = $this->callAPISuccess('relationship', 'get', array(
1285 'contact_id_a' => $result['id'],
1286 'sequential' => 1,
1287 'is_active' => 0,
1288 ));
1289
1290 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
1291 }
1292
1293 /**
1294 * Verify that attempt to create household contact with details succeeds.
1295 */
1296 public function testCreateHouseholdDetails() {
1297 $params = array(
1298 'household_name' => 'abc8\'s House',
1299 'nick_name' => 'x House',
1300 'email' => 'man8@yahoo.com',
1301 'contact_type' => 'Household',
1302 );
1303
1304 $contact = $this->callAPISuccess('contact', 'create', $params);
1305
1306 $this->callAPISuccess('contact', 'delete', $contact);
1307 }
1308
1309 /**
1310 * Verify that attempt to create household contact with inadequate details fails.
1311 */
1312 public function testCreateHouseholdInadequateDetails() {
1313 $params = array(
1314 'nick_name' => 'x House',
1315 'email' => 'man8@yahoo.com',
1316 'contact_type' => 'Household',
1317 );
1318 $this->callAPIFailure('contact', 'create', $params);
1319 }
1320
1321 /**
1322 * Verify successful update of individual contact.
1323 */
1324 public function testUpdateIndividualWithAll() {
1325 // Insert a row in civicrm_contact creating individual contact.
1326 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1327 $op->execute($this->_dbconn,
1328 $this->createXMLDataSet(
1329 dirname(__FILE__) . '/dataset/contact_ind.xml'
1330 )
1331 );
1332
1333 $params = array(
1334 'id' => 23,
1335 'first_name' => 'abcd',
1336 'contact_type' => 'Individual',
1337 'nick_name' => 'This is nickname first',
1338 'do_not_email' => '1',
1339 'do_not_phone' => '1',
1340 'do_not_mail' => '1',
1341 'do_not_trade' => '1',
1342 'legal_identifier' => 'ABC23853ZZ2235',
1343 'external_identifier' => '1928837465',
1344 'image_URL' => 'http://some.url.com/image.jpg',
1345 'home_url' => 'http://www.example.org',
1346
1347 );
1348
1349 $this->callAPISuccess('Contact', 'Update', $params);
1350 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
1351 unset($params['contact_id']);
1352 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
1353 //reducing this test partially back to api v2 level to get it through
1354 unset($params['home_url']);
1355 foreach ($params as $key => $value) {
1356 $this->assertEquals($value, $getResult['values'][23][$key]);
1357 }
1358 // Check updated civicrm_contact against expected.
1359 $expected = $this->createXMLDataSet(
1360 dirname(__FILE__) . '/dataset/contact_ind_upd.xml'
1361 );
1362 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1363 $this->_dbconn
1364 );
1365 $actual->addTable('civicrm_contact');
1366 $expected->matches($actual);
1367 }
1368
1369 /**
1370 * Verify successful update of organization contact.
1371 */
1372 public function testUpdateOrganizationWithAll() {
1373 // Insert a row in civicrm_contact creating organization contact
1374 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1375 $op->execute($this->_dbconn,
1376 $this->createXMLDataSet(
1377 dirname(__FILE__) . '/dataset/contact_org.xml'
1378 )
1379 );
1380
1381 $params = array(
1382 'id' => 24,
1383 'organization_name' => 'WebAccess India Pvt Ltd',
1384 'legal_name' => 'WebAccess',
1385 'sic_code' => 'ABC12DEF',
1386 'contact_type' => 'Organization',
1387 );
1388
1389 $this->callAPISuccess('Contact', 'Update', $params);
1390
1391 // Check updated civicrm_contact against expected.
1392 $expected = $this->createXMLDataSet(
1393 dirname(__FILE__) . '/dataset/contact_org_upd.xml'
1394 );
1395 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1396 $this->_dbconn
1397 );
1398 $actual->addTable('civicrm_contact');
1399 $expected->matches($actual);
1400 }
1401
1402 /**
1403 * Verify successful update of household contact.
1404 */
1405 public function testUpdateHouseholdWithAll() {
1406 // Insert a row in civicrm_contact creating household contact
1407 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1408 $op->execute($this->_dbconn,
1409 $this->createXMLDataSet(
1410 dirname(__FILE__) . '/dataset/contact_hld.xml'
1411 )
1412 );
1413
1414 $params = array(
1415 'id' => 25,
1416 'household_name' => 'ABC household',
1417 'nick_name' => 'ABC House',
1418 'contact_type' => 'Household',
1419 );
1420
1421 $result = $this->callAPISuccess('Contact', 'Update', $params);
1422
1423 $expected = array(
1424 'contact_type' => 'Household',
1425 'is_opt_out' => 0,
1426 'sort_name' => 'ABC household',
1427 'display_name' => 'ABC household',
1428 'nick_name' => 'ABC House',
1429 );
1430 $this->getAndCheck($expected, $result['id'], 'contact');
1431 }
1432
1433 /**
1434 * Test civicrm_update() without contact type.
1435 *
1436 * Deliberately exclude contact_type as it should still cope using civicrm_api.
1437 *
1438 * CRM-7645.
1439 */
1440 public function testUpdateCreateWithID() {
1441 // Insert a row in civicrm_contact creating individual contact.
1442 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1443 $op->execute($this->_dbconn,
1444 $this->createXMLDataSet(
1445 dirname(__FILE__) . '/dataset/contact_ind.xml'
1446 )
1447 );
1448
1449 $params = array(
1450 'id' => 23,
1451 'first_name' => 'abcd',
1452 'last_name' => 'wxyz',
1453 );
1454 $this->callAPISuccess('Contact', 'Update', $params);
1455 }
1456
1457 /**
1458 * Test civicrm_contact_delete() with no contact ID.
1459 */
1460 public function testContactDeleteNoID() {
1461 $params = array(
1462 'foo' => 'bar',
1463 );
1464 $this->callAPIFailure('contact', 'delete', $params);
1465 }
1466
1467 /**
1468 * Test civicrm_contact_delete() with error.
1469 */
1470 public function testContactDeleteError() {
1471 $params = array('contact_id' => 999);
1472 $this->callAPIFailure('contact', 'delete', $params);
1473 }
1474
1475 /**
1476 * Test civicrm_contact_delete().
1477 */
1478 public function testContactDelete() {
1479 $contactID = $this->individualCreate();
1480 $params = array(
1481 'id' => $contactID,
1482 );
1483 $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__, __FILE__);
1484 }
1485
1486 /**
1487 * Test civicrm_contact_get() return only first name.
1488 */
1489 public function testContactGetRetFirst() {
1490 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
1491 $params = array(
1492 'contact_id' => $contact['id'],
1493 'return_first_name' => TRUE,
1494 'sort' => 'first_name',
1495 );
1496 $result = $this->callAPISuccess('contact', 'get', $params);
1497 $this->assertEquals(1, $result['count']);
1498 $this->assertEquals($contact['id'], $result['id']);
1499 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name']);
1500 }
1501
1502 /**
1503 * Test civicrm_contact_get() return only first name & last name.
1504 *
1505 * Use comma separated string return with a space.
1506 */
1507 public function testContactGetReturnFirstLast() {
1508 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
1509 $params = array(
1510 'contact_id' => $contact['id'],
1511 'return' => 'first_name, last_name',
1512 );
1513 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1514 $this->assertEquals('abc1', $result['first_name']);
1515 $this->assertEquals('xyz1', $result['last_name']);
1516 //check that other defaults not returns
1517 $this->assertArrayNotHasKey('sort_name', $result);
1518 $params = array(
1519 'contact_id' => $contact['id'],
1520 'return' => 'first_name,last_name',
1521 );
1522 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1523 $this->assertEquals('abc1', $result['first_name']);
1524 $this->assertEquals('xyz1', $result['last_name']);
1525 //check that other defaults not returns
1526 $this->assertArrayNotHasKey('sort_name', $result);
1527 }
1528
1529 /**
1530 * Test civicrm_contact_get() return only first name & last name.
1531 *
1532 * Use comma separated string return without a space
1533 */
1534 public function testContactGetReturnFirstLastNoComma() {
1535 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
1536 $params = array(
1537 'contact_id' => $contact['id'],
1538 'return' => 'first_name,last_name',
1539 );
1540 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1541 $this->assertEquals('abc1', $result['first_name']);
1542 $this->assertEquals('xyz1', $result['last_name']);
1543 //check that other defaults not returns
1544 $this->assertArrayNotHasKey('sort_name', $result);
1545 }
1546
1547 /**
1548 * Test civicrm_contact_get() with default return properties.
1549 */
1550 public function testContactGetRetDefault() {
1551 $contactID = $this->individualCreate();
1552 $params = array(
1553 'contact_id' => $contactID,
1554 'sort' => 'first_name',
1555 );
1556 $result = $this->callAPISuccess('contact', 'get', $params);
1557 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1558 $this->assertEquals('Anthony', $result['values'][$contactID]['first_name']);
1559 }
1560
1561 /**
1562 * Test civicrm_contact_getquick() with empty name param.
1563 */
1564 public function testContactGetQuick() {
1565 // Insert a row in civicrm_contact creating individual contact.
1566 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1567 $op->execute($this->_dbconn,
1568 $this->createXMLDataSet(
1569 dirname(__FILE__) . '/dataset/contact_17.xml'
1570 )
1571 );
1572 $op->execute($this->_dbconn,
1573 $this->createXMLDataSet(
1574 dirname(__FILE__) . '/dataset/email_contact_17.xml'
1575 )
1576 );
1577 $params = array(
1578 'name' => "T",
1579 );
1580
1581 $result = $this->callAPISuccess('contact', 'getquick', $params);
1582 $this->assertEquals(17, $result['values'][0]['id']);
1583 }
1584
1585 /**
1586 * Test civicrm_contact_get) with empty params.
1587 */
1588 public function testContactGetEmptyParams() {
1589 $this->callAPISuccess('contact', 'get', array());
1590 }
1591
1592 /**
1593 * Test civicrm_contact_get(,true) with no matches.
1594 */
1595 public function testContactGetOldParamsNoMatches() {
1596 // Insert a row in civicrm_contact creating contact 17.
1597 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1598 $op->execute($this->_dbconn,
1599 $this->createXMLDataSet(
1600 dirname(__FILE__) . '/dataset/contact_17.xml'
1601 )
1602 );
1603
1604 $params = array(
1605 'first_name' => 'Fred',
1606 );
1607 $result = $this->callAPISuccess('contact', 'get', $params);
1608 $this->assertEquals(0, $result['count']);
1609 }
1610
1611 /**
1612 * Test civicrm_contact_get(,true) with one match.
1613 */
1614 public function testContactGetOldParamsOneMatch() {
1615 // Insert a row in civicrm_contact creating contact 17
1616 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1617 $op->execute($this->_dbconn,
1618 $this->createXMLDataSet(dirname(__FILE__) . '/dataset/contact_17.xml'
1619 )
1620 );
1621
1622 $params = array(
1623 'first_name' => 'Test',
1624 );
1625 $result = $this->callAPISuccess('contact', 'get', $params);
1626 $this->assertEquals(17, $result['values'][17]['contact_id']);
1627 $this->assertEquals(17, $result['id']);
1628 }
1629
1630 /**
1631 * Test civicrm_contact_search_count().
1632 */
1633 public function testContactGetEmail() {
1634 $params = array(
1635 'email' => 'man2@yahoo.com',
1636 'contact_type' => 'Individual',
1637 'location_type_id' => 1,
1638 );
1639
1640 $contact = $this->callAPISuccess('contact', 'create', $params);
1641
1642 $params = array(
1643 'email' => 'man2@yahoo.com',
1644 );
1645 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__);
1646 $this->assertEquals('man2@yahoo.com', $result['values'][$result['id']]['email']);
1647
1648 $this->callAPISuccess('contact', 'delete', $contact);
1649 }
1650
1651 /**
1652 * Test birth date parameters.
1653 *
1654 * These include value, array & birth_date_high, birth_date_low
1655 * && deceased.
1656 */
1657 public function testContactGetBirthDate() {
1658 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('birth_date' => 'first day of next month - 2 years')));
1659 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('birth_date' => 'first day of next month - 5 years')));
1660 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('birth_date' => 'first day of next month -20 years')));
1661
1662 $result = $this->callAPISuccess('contact', 'get', array());
1663 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['birth_date']);
1664 $result = $this->callAPISuccess('contact', 'get', array('birth_date' => 'first day of next month -5 years'));
1665 $this->assertEquals(1, $result['count']);
1666 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1667 $result = $this->callAPISuccess('contact', 'get', array('birth_date_high' => date('Y-m-d', strtotime('-6 years'))));
1668 $this->assertEquals(1, $result['count']);
1669 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['birth_date']);
1670 $result = $this->callAPISuccess('contact', 'get', array(
1671 'birth_date_low' => date('Y-m-d', strtotime('-6 years')),
1672 'birth_date_high' => date('Y-m-d', strtotime('- 3 years')),
1673 ));
1674 $this->assertEquals(1, $result['count']);
1675 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1676 $result = $this->callAPISuccess('contact', 'get', array(
1677 'birth_date_low' => '-6 years',
1678 'birth_date_high' => '- 3 years',
1679 ));
1680 $this->assertEquals(1, $result['count']);
1681 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1682 }
1683
1684 /**
1685 * Test Address parameters
1686 *
1687 * This include state_province, state_province_name, country
1688 */
1689 public function testContactGetWithAddressFields() {
1690 $individuals = array(
1691 array(
1692 'first_name' => 'abc1',
1693 'contact_type' => 'Individual',
1694 'last_name' => 'xyz1',
1695 'api.address.create' => array(
1696 'country' => 'United States',
1697 'state_province_id' => 'Michigan',
1698 'location_type_id' => 1,
1699 ),
1700 ),
1701 array(
1702 'first_name' => 'abc2',
1703 'contact_type' => 'Individual',
1704 'last_name' => 'xyz2',
1705 'api.address.create' => array(
1706 'country' => 'United States',
1707 'state_province_id' => 'Alabama',
1708 'location_type_id' => 1,
1709 ),
1710 ),
1711 );
1712 foreach ($individuals as $params) {
1713 $contact = $this->callAPISuccess('contact', 'create', $params);
1714 }
1715
1716 // Check whether Contact get API return successfully with below Address params.
1717 $fieldsToTest = array(
1718 'state_province_name' => 'Michigan',
1719 'state_province' => 'Michigan',
1720 'country' => 'United States',
1721 'state_province_name' => array('IN' => array('Michigan', 'Alabama')),
1722 'state_province' => array('IN' => array('Michigan', 'Alabama')),
1723 );
1724 foreach ($fieldsToTest as $field => $value) {
1725 $getParams = array(
1726 'id' => $contact['id'],
1727 $field => $value,
1728 );
1729 $result = $this->callAPISuccess('Contact', 'get', $getParams);
1730 $this->assertEquals(1, $result['count']);
1731 }
1732 }
1733
1734 /**
1735 * Test Deceased date parameters.
1736 *
1737 * These include value, array & Deceased_date_high, Deceased date_low
1738 * && deceased.
1739 */
1740 public function testContactGetDeceasedDate() {
1741 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('deceased_date' => 'first day of next month - 2 years')));
1742 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('deceased_date' => 'first day of next month - 5 years')));
1743 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('deceased_date' => 'first day of next month -20 years')));
1744
1745 $result = $this->callAPISuccess('contact', 'get', array());
1746 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['deceased_date']);
1747 $result = $this->callAPISuccess('contact', 'get', array('deceased_date' => 'first day of next month -5 years'));
1748 $this->assertEquals(1, $result['count']);
1749 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1750 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_high' => date('Y-m-d', strtotime('-6 years'))));
1751 $this->assertEquals(1, $result['count']);
1752 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['deceased_date']);
1753 $result = $this->callAPISuccess('contact', 'get', array(
1754 'deceased_date_low' => '-6 years',
1755 'deceased_date_high' => date('Y-m-d', strtotime('- 3 years')),
1756 ));
1757 $this->assertEquals(1, $result['count']);
1758 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1759 }
1760
1761 /**
1762 * Test for Contact.get id=@user:username.
1763 */
1764 public function testContactGetByUsername() {
1765 // Setup - create contact with a uf-match.
1766 $cid = $this->individualCreate(array(
1767 'contact_type' => 'Individual',
1768 'first_name' => 'testGetByUsername',
1769 'last_name' => 'testGetByUsername',
1770 ));
1771
1772 $ufMatchParams = array(
1773 'domain_id' => CRM_Core_Config::domainID(),
1774 'uf_id' => 99,
1775 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
1776 'contact_id' => $cid,
1777 );
1778 $ufMatch = CRM_Core_BAO_UFMatch::create($ufMatchParams);
1779 $this->assertTrue(is_numeric($ufMatch->id));
1780
1781 // setup - mock the calls to CRM_Utils_System_*::getUfId
1782 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1783 $userSystem->expects($this->once())
1784 ->method('getUfId')
1785 ->with($this->equalTo('exampleUser'))
1786 ->will($this->returnValue(99));
1787 CRM_Core_Config::singleton()->userSystem = $userSystem;
1788
1789 // perform a lookup
1790 $result = $this->callAPISuccess('Contact', 'get', array(
1791 'id' => '@user:exampleUser',
1792 ));
1793 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
1794 }
1795
1796 /**
1797 * Test to check return works OK.
1798 */
1799 public function testContactGetReturnValues() {
1800 $extraParams = array(
1801 'nick_name' => 'Bob',
1802 'phone' => '456',
1803 'email' => 'e@mail.com',
1804 );
1805 $contactID = $this->individualCreate($extraParams);
1806 //actually it turns out the above doesn't create a phone
1807 $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456'));
1808 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
1809 foreach ($extraParams as $key => $value) {
1810 $this->assertEquals($result[$key], $value);
1811 }
1812 //now we check they are still returned with 'return' key
1813 $result = $this->callAPISuccess('contact', 'getsingle', array(
1814 'id' => $contactID,
1815 'return' => array_keys($extraParams),
1816 ));
1817 foreach ($extraParams as $key => $value) {
1818 $this->assertEquals($result[$key], $value);
1819 }
1820 }
1821
1822 /**
1823 * Test creating multiple phones using chaining.
1824 *
1825 * @throws \Exception
1826 */
1827 public function testCRM13252MultipleChainedPhones() {
1828 $contactID = $this->householdCreate();
1829 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
1830 $params = array(
1831 'contact_id' => $contactID,
1832 'household_name' => 'Household 1',
1833 'contact_type' => 'Household',
1834 'api.phone.create' => array(
1835 0 => array(
1836 'phone' => '111-111-1111',
1837 'location_type_id' => 1,
1838 'phone_type_id' => 1,
1839 ),
1840 1 => array(
1841 'phone' => '222-222-2222',
1842 'location_type_id' => 1,
1843 'phone_type_id' => 2,
1844 ),
1845 ),
1846 );
1847 $this->callAPISuccess('contact', 'create', $params);
1848 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
1849
1850 }
1851
1852 /**
1853 * Test for Contact.get id=@user:username (with an invalid username).
1854 */
1855 public function testContactGetByUnknownUsername() {
1856 // setup - mock the calls to CRM_Utils_System_*::getUfId
1857 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1858 $userSystem->expects($this->once())
1859 ->method('getUfId')
1860 ->with($this->equalTo('exampleUser'))
1861 ->will($this->returnValue(NULL));
1862 CRM_Core_Config::singleton()->userSystem = $userSystem;
1863
1864 // perform a lookup
1865 $result = $this->callAPIFailure('Contact', 'get', array(
1866 'id' => '@user:exampleUser',
1867 ));
1868 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
1869 }
1870
1871 /**
1872 * Verify attempt to create individual with chained arrays and sequential.
1873 */
1874 public function testGetIndividualWithChainedArraysAndSequential() {
1875 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
1876 $params['custom_' . $ids['custom_field_id']] = "custom string";
1877
1878 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1879 $params = array(
1880 'sequential' => 1,
1881 'first_name' => 'abc3',
1882 'last_name' => 'xyz3',
1883 'contact_type' => 'Individual',
1884 'email' => 'man3@yahoo.com',
1885 'api.website.create' => array(
1886 array(
1887 'url' => "http://civicrm.org",
1888 ),
1889 array(
1890 'url' => "https://civicrm.org",
1891 ),
1892 ),
1893 );
1894
1895 $result = $this->callAPISuccess('Contact', 'create', $params);
1896
1897 // delete the contact and custom groups
1898 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
1899 $this->customGroupDelete($ids['custom_group_id']);
1900 $this->customGroupDelete($moreIDs['custom_group_id']);
1901
1902 $this->assertEquals($result['id'], $result['values'][0]['id']);
1903 $this->assertArrayKeyExists('api.website.create', $result['values'][0]);
1904 }
1905
1906 /**
1907 * Verify attempt to create individual with chained arrays.
1908 */
1909 public function testGetIndividualWithChainedArrays() {
1910 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
1911 $params['custom_' . $ids['custom_field_id']] = "custom string";
1912
1913 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1914 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
1915 $subfile = "APIChainedArray";
1916 $params = array(
1917 'first_name' => 'abc3',
1918 'last_name' => 'xyz3',
1919 'contact_type' => 'Individual',
1920 'email' => 'man3@yahoo.com',
1921 'api.contribution.create' => array(
1922 'receive_date' => '2010-01-01',
1923 'total_amount' => 100.00,
1924 'financial_type_id' => 1,
1925 'payment_instrument_id' => 1,
1926 'non_deductible_amount' => 10.00,
1927 'fee_amount' => 50.00,
1928 'net_amount' => 90.00,
1929 'trxn_id' => 12345,
1930 'invoice_id' => 67890,
1931 'source' => 'SSF',
1932 'contribution_status_id' => 1,
1933 ),
1934 'api.contribution.create.1' => array(
1935 'receive_date' => '2011-01-01',
1936 'total_amount' => 120.00,
1937 'financial_type_id' => $this->_financialTypeId = 1,
1938 'payment_instrument_id' => 1,
1939 'non_deductible_amount' => 10.00,
1940 'fee_amount' => 50.00,
1941 'net_amount' => 90.00,
1942 'trxn_id' => 12335,
1943 'invoice_id' => 67830,
1944 'source' => 'SSF',
1945 'contribution_status_id' => 1,
1946 ),
1947 'api.website.create' => array(
1948 array(
1949 'url' => "http://civicrm.org",
1950 ),
1951 ),
1952 );
1953
1954 $result = $this->callAPISuccess('Contact', 'create', $params);
1955 $params = array(
1956 'id' => $result['id'],
1957 'api.website.get' => array(),
1958 'api.Contribution.get' => array(
1959 'total_amount' => '120.00',
1960 ),
1961 'api.CustomValue.get' => 1,
1962 'api.Note.get' => 1,
1963 );
1964 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
1965 // delete the contact
1966 $this->callAPISuccess('contact', 'delete', $result);
1967 $this->customGroupDelete($ids['custom_group_id']);
1968 $this->customGroupDelete($moreIDs['custom_group_id']);
1969 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error']);
1970 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url']);
1971 }
1972
1973 /**
1974 * Verify attempt to create individual with chained arrays and sequential.
1975 *
1976 * See https://issues.civicrm.org/jira/browse/CRM-15815
1977 */
1978 public function testCreateIndividualWithChainedArrayAndSequential() {
1979 $params = array(
1980 'sequential' => 1,
1981 'first_name' => 'abc5',
1982 'last_name' => 'xyz5',
1983 'contact_type' => 'Individual',
1984 'email' => 'woman5@yahoo.com',
1985 'api.phone.create' => array(
1986 array('phone' => '03-231 07 95'),
1987 array('phone' => '03-232 51 62'),
1988 ),
1989 'api.website.create' => array(
1990 'url' => 'http://civicrm.org',
1991 ),
1992 );
1993 $result = $this->callAPISuccess('Contact', 'create', $params);
1994
1995 // I could try to parse the result to see whether the two phone numbers
1996 // and the website are there, but I am not sure about the correct format.
1997 // So I will just fetch it again before checking.
1998 // See also http://forum.civicrm.org/index.php/topic,35393.0.html
1999 $params = array(
2000 'sequential' => 1,
2001 'id' => $result['id'],
2002 'api.website.get' => array(),
2003 'api.phone.get' => array(),
2004 );
2005 $result = $this->callAPISuccess('Contact', 'get', $params);
2006
2007 // delete the contact
2008 $this->callAPISuccess('contact', 'delete', $result);
2009
2010 $this->assertEquals(2, $result['values'][0]['api.phone.get']['count']);
2011 $this->assertEquals(1, $result['values'][0]['api.website.get']['count']);
2012 }
2013
2014 /**
2015 * Test retrieving an individual with chained array syntax.
2016 */
2017 public function testGetIndividualWithChainedArraysFormats() {
2018 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
2019 $subfile = "APIChainedArrayFormats";
2020 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
2021 $params['custom_' . $ids['custom_field_id']] = "custom string";
2022
2023 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2024 $params = array(
2025 'first_name' => 'abc3',
2026 'last_name' => 'xyz3',
2027 'contact_type' => 'Individual',
2028 'email' => 'man3@yahoo.com',
2029 'api.contribution.create' => array(
2030 'receive_date' => '2010-01-01',
2031 'total_amount' => 100.00,
2032 'financial_type_id' => $this->_financialTypeId,
2033 'payment_instrument_id' => 1,
2034 'non_deductible_amount' => 10.00,
2035 'fee_amount' => 50.00,
2036 'net_amount' => 90.00,
2037 'source' => 'SSF',
2038 'contribution_status_id' => 1,
2039 ),
2040 'api.contribution.create.1' => array(
2041 'receive_date' => '2011-01-01',
2042 'total_amount' => 120.00,
2043 'financial_type_id' => $this->_financialTypeId,
2044 'payment_instrument_id' => 1,
2045 'non_deductible_amount' => 10.00,
2046 'fee_amount' => 50.00,
2047 'net_amount' => 90.00,
2048 'source' => 'SSF',
2049 'contribution_status_id' => 1,
2050 ),
2051 'api.website.create' => array(
2052 array(
2053 'url' => "http://civicrm.org",
2054 ),
2055 ),
2056 );
2057
2058 $result = $this->callAPISuccess('Contact', 'create', $params);
2059 $params = array(
2060 'id' => $result['id'],
2061 'api.website.getValue' => array('return' => 'url'),
2062 'api.Contribution.getCount' => array(),
2063 'api.CustomValue.get' => 1,
2064 'api.Note.get' => 1,
2065 'api.Membership.getCount' => array(),
2066 );
2067 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
2068 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount']);
2069 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error']);
2070 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue']);
2071
2072 $this->callAPISuccess('contact', 'delete', $result);
2073 $this->customGroupDelete($ids['custom_group_id']);
2074 $this->customGroupDelete($moreIDs['custom_group_id']);
2075 }
2076
2077 /**
2078 * Test complex chaining.
2079 */
2080 public function testGetIndividualWithChainedArraysAndMultipleCustom() {
2081 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
2082 $params['custom_' . $ids['custom_field_id']] = "custom string";
2083 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2084 $andMoreIDs = $this->CustomGroupMultipleCreateWithFields(array(
2085 'title' => "another group",
2086 'name' => 'another name',
2087 ));
2088 $description = "This demonstrates the usage of chained api functions with multiple custom fields.";
2089 $subfile = "APIChainedArrayMultipleCustom";
2090 $params = array(
2091 'first_name' => 'abc3',
2092 'last_name' => 'xyz3',
2093 'contact_type' => 'Individual',
2094 'email' => 'man3@yahoo.com',
2095 'api.contribution.create' => array(
2096 'receive_date' => '2010-01-01',
2097 'total_amount' => 100.00,
2098 'financial_type_id' => 1,
2099 'payment_instrument_id' => 1,
2100 'non_deductible_amount' => 10.00,
2101 'fee_amount' => 50.00,
2102 'net_amount' => 90.00,
2103 'trxn_id' => 12345,
2104 'invoice_id' => 67890,
2105 'source' => 'SSF',
2106 'contribution_status_id' => 1,
2107 ),
2108 'api.contribution.create.1' => array(
2109 'receive_date' => '2011-01-01',
2110 'total_amount' => 120.00,
2111 'financial_type_id' => 1,
2112 'payment_instrument_id' => 1,
2113 'non_deductible_amount' => 10.00,
2114 'fee_amount' => 50.00,
2115 'net_amount' => 90.00,
2116 'trxn_id' => 12335,
2117 'invoice_id' => 67830,
2118 'source' => 'SSF',
2119 'contribution_status_id' => 1,
2120 ),
2121 'api.website.create' => array(
2122 array(
2123 'url' => "http://civicrm.org",
2124 ),
2125 ),
2126 'custom_' . $ids['custom_field_id'] => "value 1",
2127 'custom_' . $moreIDs['custom_field_id'][0] => "value 2",
2128 'custom_' . $moreIDs['custom_field_id'][1] => "warm beer",
2129 'custom_' . $andMoreIDs['custom_field_id'][1] => "vegemite",
2130 );
2131
2132 $result = $this->callAPISuccess('Contact', 'create', $params);
2133 $result = $this->callAPISuccess('Contact', 'create', array(
2134 'contact_type' => 'Individual',
2135 'id' => $result['id'],
2136 'custom_' .
2137 $moreIDs['custom_field_id'][0] => "value 3",
2138 'custom_' .
2139 $ids['custom_field_id'] => "value 4",
2140 ));
2141
2142 $params = array(
2143 'id' => $result['id'],
2144 'api.website.getValue' => array('return' => 'url'),
2145 'api.Contribution.getCount' => array(),
2146 'api.CustomValue.get' => 1,
2147 );
2148 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
2149
2150 $this->customGroupDelete($ids['custom_group_id']);
2151 $this->customGroupDelete($moreIDs['custom_group_id']);
2152 $this->customGroupDelete($andMoreIDs['custom_group_id']);
2153 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error']);
2154 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue']);
2155 }
2156
2157 /**
2158 * Test checks usage of $values to pick & choose inputs.
2159 */
2160 public function testChainingValuesCreate() {
2161 $description = "This demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
2162 2 child functions - one receives values from the parent (Contact) and the other child (Tag).";
2163 $subfile = "APIChainedArrayValuesFromSiblingFunction";
2164 $params = array(
2165 'display_name' => 'batman',
2166 'contact_type' => 'Individual',
2167 'api.tag.create' => array(
2168 'name' => '$value.id',
2169 'description' => '$value.display_name',
2170 'format.only_id' => 1,
2171 ),
2172 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
2173 );
2174 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__, __FILE__, $description, $subfile);
2175 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
2176
2177 $tablesToTruncate = array(
2178 'civicrm_contact',
2179 'civicrm_activity',
2180 'civicrm_entity_tag',
2181 'civicrm_tag',
2182 );
2183 $this->quickCleanup($tablesToTruncate, TRUE);
2184 }
2185
2186 /**
2187 * Test TrueFalse format - I couldn't come up with an easy way to get an error on Get.
2188 */
2189 public function testContactGetFormatIsSuccessTrue() {
2190 $this->createContactFromXML();
2191 $description = "This demonstrates use of the 'format.is_success' param.
2192 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
2193 $subfile = "FormatIsSuccess_True";
2194 $params = array('id' => 17, 'format.is_success' => 1);
2195 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
2196 $this->assertEquals(1, $result);
2197 $this->callAPISuccess('Contact', 'Delete', $params);
2198 }
2199
2200 /**
2201 * Test TrueFalse format.
2202 */
2203 public function testContactCreateFormatIsSuccessFalse() {
2204
2205 $description = "This demonstrates use of the 'format.is_success' param.
2206 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
2207 $subfile = "FormatIsSuccess_Fail";
2208 $params = array('id' => 500, 'format.is_success' => 1);
2209 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__, __FILE__, $description, $subfile);
2210 $this->assertEquals(0, $result);
2211 }
2212
2213 /**
2214 * Test Single Entity format.
2215 */
2216 public function testContactGetSingleEntityArray() {
2217 $this->createContactFromXML();
2218 $description = "This demonstrates use of the 'format.single_entity_array' param.
2219 This param causes the only contact to be returned as an array without the other levels.
2220 It will be ignored if there is not exactly 1 result";
2221 $subfile = "GetSingleContact";
2222 $params = array('id' => 17);
2223 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__, __FILE__, $description, $subfile);
2224 $this->assertEquals('Test Contact', $result['display_name']);
2225 $this->callAPISuccess('Contact', 'Delete', $params);
2226 }
2227
2228 /**
2229 * Test Single Entity format.
2230 */
2231 public function testContactGetFormatCountOnly() {
2232 $this->createContactFromXML();
2233 $description = "This demonstrates use of the 'getCount' action.
2234 This param causes the count of the only function to be returned as an integer.";
2235 $params = array('id' => 17);
2236 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__, __FILE__, $description,
2237 'GetCountContact');
2238 $this->assertEquals('1', $result);
2239 $this->callAPISuccess('Contact', 'Delete', $params);
2240 }
2241
2242 /**
2243 * Test id only format.
2244 */
2245 public function testContactGetFormatIDOnly() {
2246 $this->createContactFromXML();
2247 $description = "This demonstrates use of the 'format.id_only' param.
2248 This param causes the id of the only entity to be returned as an integer.
2249 It will be ignored if there is not exactly 1 result";
2250 $subfile = "FormatOnlyID";
2251 $params = array('id' => 17, 'format.only_id' => 1);
2252 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
2253 $this->assertEquals('17', $result);
2254 $this->callAPISuccess('Contact', 'Delete', $params);
2255 }
2256
2257 /**
2258 * Test id only format.
2259 */
2260 public function testContactGetFormatSingleValue() {
2261 $this->createContactFromXML();
2262 $description = "This demonstrates use of the 'format.single_value' param.
2263 This param causes only a single value of the only entity to be returned as an string.
2264 It will be ignored if there is not exactly 1 result";
2265 $subFile = "FormatSingleValue";
2266 $params = array('id' => 17, 'return' => 'display_name');
2267 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__, __FILE__, $description, $subFile);
2268 $this->assertEquals('Test Contact', $result);
2269 $this->callAPISuccess('Contact', 'Delete', $params);
2270 }
2271
2272 /**
2273 * Test that permissions are respected when creating contacts.
2274 */
2275 public function testContactCreationPermissions() {
2276 $params = array(
2277 'contact_type' => 'Individual',
2278 'first_name' => 'Foo',
2279 'last_name' => 'Bear',
2280 'check_permissions' => TRUE,
2281 );
2282 $config = CRM_Core_Config::singleton();
2283 $config->userPermissionClass->permissions = array('access CiviCRM');
2284 $result = $this->callAPIFailure('contact', 'create', $params);
2285 $this->assertEquals('API permission check failed for Contact/create call; insufficient permission: require access CiviCRM and add contacts', $result['error_message'], 'lacking permissions should not be enough to create a contact');
2286
2287 $config->userPermissionClass->permissions = array('access CiviCRM', 'add contacts', 'import contacts');
2288 $this->callAPISuccess('contact', 'create', $params);
2289 }
2290
2291 /**
2292 * Test that delete with skip undelete respects permissions.
2293 */
2294 public function testContactDeletePermissions() {
2295 $contactID = $this->individualCreate();
2296 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM');
2297 $this->callAPIFailure('Contact', 'delete', array(
2298 'id' => $contactID,
2299 'check_permissions' => 1,
2300 'skip_undelete' => 1,
2301 ));
2302 $this->callAPISuccess('Contact', 'delete', array(
2303 'id' => $contactID,
2304 'check_permissions' => 0,
2305 'skip_undelete' => 1,
2306 ));
2307 }
2308
2309 /**
2310 * Test update with check permissions set.
2311 */
2312 public function testContactUpdatePermissions() {
2313 $params = array(
2314 'contact_type' => 'Individual',
2315 'first_name' => 'Foo',
2316 'last_name' => 'Bear',
2317 'check_permissions' => TRUE,
2318 );
2319 $result = $this->callAPISuccess('contact', 'create', $params);
2320 $config = CRM_Core_Config::singleton();
2321 $params = array(
2322 'id' => $result['id'],
2323 'contact_type' => 'Individual',
2324 'last_name' => 'Bar',
2325 'check_permissions' => TRUE,
2326 );
2327
2328 $config->userPermissionClass->permissions = array('access CiviCRM');
2329 $result = $this->callAPIFailure('contact', 'update', $params);
2330 $this->assertEquals('Permission denied to modify contact record', $result['error_message']);
2331
2332 $config->userPermissionClass->permissions = array(
2333 'access CiviCRM',
2334 'add contacts',
2335 'view all contacts',
2336 'edit all contacts',
2337 'import contacts',
2338 );
2339 $this->callAPISuccess('contact', 'update', $params);
2340 }
2341
2342 /**
2343 * Set up helper to create a contact.
2344 */
2345 public function createContactFromXML() {
2346 // Insert a row in civicrm_contact creating contact 17.
2347 $op = new PHPUnit_Extensions_Database_Operation_Insert();
2348 $op->execute($this->_dbconn,
2349 $this->createXMLDataSet(
2350 dirname(__FILE__) . '/dataset/contact_17.xml'
2351 )
2352 );
2353 }
2354
2355 /**
2356 * Test contact proximity api.
2357 */
2358 public function testContactProximity() {
2359 // first create a contact with a SF location with a specific
2360 // geocode
2361 $contactID = $this->organizationCreate();
2362
2363 // now create the address
2364 $params = array(
2365 'street_address' => '123 Main Street',
2366 'city' => 'San Francisco',
2367 'is_primary' => 1,
2368 'country_id' => 1228,
2369 'state_province_id' => 1004,
2370 'geo_code_1' => '37.79',
2371 'geo_code_2' => '-122.40',
2372 'location_type_id' => 1,
2373 'contact_id' => $contactID,
2374 );
2375
2376 $result = $this->callAPISuccess('address', 'create', $params);
2377 $this->assertEquals(1, $result['count']);
2378
2379 // now do a proximity search with a close enough geocode and hope to match
2380 // that specific contact only!
2381 $proxParams = array(
2382 'latitude' => 37.7,
2383 'longitude' => -122.3,
2384 'unit' => 'mile',
2385 'distance' => 10,
2386 );
2387 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
2388 $this->assertEquals(1, $result['count']);
2389 }
2390
2391 /**
2392 * Test that Ajax API permission is sufficient to access getquick api.
2393 *
2394 * (note that getquick api is required for autocomplete & has ACL permissions applied)
2395 */
2396 public function testGetquickPermissionCRM13744() {
2397 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviEvent');
2398 $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2399 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM');
2400 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2401 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access AJAX API');
2402 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2403 }
2404
2405 /**
2406 * Test that getquick returns contacts with an exact first name match first.
2407 *
2408 * The search string 'b' & 'bob' both return ordered by sort_name if includeOrderByClause
2409 * is true (default) but if it is false then matches are returned in ID order.
2410 *
2411 * @dataProvider getSearchSortOptions
2412 */
2413 public function testGetQuickExactFirst($searchParameters, $settings, $firstContact, $secondContact = NULL) {
2414 $this->getQuickSearchSampleData();
2415 $this->callAPISuccess('Setting', 'create', $settings);
2416 $result = $this->callAPISuccess('contact', 'getquick', $searchParameters);
2417 $this->assertEquals($firstContact, $result['values'][0]['sort_name']);
2418 $this->assertEquals($secondContact, $result['values'][1]['sort_name']);
2419 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE));
2420 }
2421
2422 public function getSearchSortOptions() {
2423 $firstAlphabeticalContactBySortName = 'A Bobby, Bobby';
2424 $secondAlphabeticalContactBySortName = 'Aadvark, Bob';
2425 $secondAlphabeticalContactWithEmailBySortName = 'Bob, Bob';
2426 $firstAlphabeticalContactFirstNameBob = 'Aadvark, Bob';
2427 $secondAlphabeticalContactFirstNameBob = 'Bob, Bob';
2428 $firstByIDContactFirstNameBob = 'Bob, Bob';
2429 $secondByIDContactFirstNameBob = 'K Bobby, Bob';
2430 $firstContactByID = 'Bob, Bob';
2431 $secondContactByID = 'E Bobby, Bobby';
2432 $bobLikeEmail = 'A Bobby, Bobby';
2433
2434 return array(
2435 'empty_search_basic' => array(
2436 'search_parameters' => array('name' => '%'),
2437 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2438 'first_contact' => $firstAlphabeticalContactBySortName,
2439 'second_contact' => $secondAlphabeticalContactBySortName,
2440 ),
2441 'empty_search_basic_no_wildcard' => array(
2442 'search_parameters' => array('name' => '%'),
2443 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2444 'first_contact' => $firstAlphabeticalContactBySortName,
2445 'second_contact' => $secondAlphabeticalContactBySortName,
2446 ),
2447 'single_letter_search_basic' => array(
2448 'search_parameters' => array('name' => 'b'),
2449 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2450 'first_contact' => $firstAlphabeticalContactBySortName,
2451 'second_contact' => $secondAlphabeticalContactBySortName,
2452 ),
2453 'bob_search_basic' => array(
2454 'search_parameters' => array('name' => 'bob'),
2455 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2456 'first_contact' => $firstAlphabeticalContactBySortName,
2457 'second_contact' => $secondAlphabeticalContactBySortName,
2458 ),
2459 'bob_search_no_orderby' => array(
2460 'search_parameters' => array('name' => 'bob'),
2461 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => FALSE),
2462 'first_contact' => $firstContactByID,
2463 'second_contact' => $secondContactByID,
2464 ),
2465 'bob_search_no_wildcard' => array(
2466 'search_parameters' => array('name' => 'bob'),
2467 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2468 'second_contact' => $bobLikeEmail,
2469 'first_contact' => $secondAlphabeticalContactFirstNameBob,
2470 ),
2471 // This should be the same as just no wildcard as if we had an exactMatch while searching by
2472 // sort name it would rise to the top CRM-19547
2473 'bob_search_no_wildcard_no_orderby' => array(
2474 'search_parameters' => array('name' => 'bob'),
2475 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2476 'second_contact' => $bobLikeEmail,
2477 'first_contact' => $secondAlphabeticalContactFirstNameBob,
2478 ),
2479 'first_name_search_basic' => array(
2480 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2481 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2482 'first_contact' => $firstAlphabeticalContactFirstNameBob,
2483 'second_contact' => $secondAlphabeticalContactFirstNameBob,
2484 ),
2485 'first_name_search_no_wildcard' => array(
2486 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2487 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2488 'first_contact' => $firstAlphabeticalContactFirstNameBob,
2489 'second_contact' => $secondAlphabeticalContactFirstNameBob,
2490 ),
2491 'first_name_search_no_orderby' => array(
2492 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2493 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => FALSE),
2494 'first_contact' => $firstByIDContactFirstNameBob,
2495 'second_contact' => $secondByIDContactFirstNameBob,
2496 ),
2497 'email_search_basic' => array(
2498 'search_parameters' => array('name' => 'bob', 'field_name' => 'email', 'table_name' => 'eml'),
2499 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2500 'first_contact' => $firstAlphabeticalContactBySortName,
2501 'second_contact' => $secondAlphabeticalContactWithEmailBySortName,
2502 ),
2503 );
2504 }
2505
2506 /**
2507 * Test that getquick returns contacts with an exact first name match first.
2508 */
2509 public function testGetQuickEmail() {
2510 $this->getQuickSearchSampleData();
2511 $loggedInContactID = $this->createLoggedInUser();
2512 $result = $this->callAPISuccess('contact', 'getquick', array(
2513 'name' => 'c',
2514 ));
2515 $expectedData = array(
2516 'A Bobby, Bobby :: bob@bobby.com',
2517 'Bob, Bob :: bob@bob.com',
2518 'C Bobby, Bobby',
2519 'H Bobby, Bobby :: bob@h.com',
2520 'Second Domain',
2521 $this->callAPISuccessGetValue('Contact', array('id' => $loggedInContactID, 'return' => 'last_name')) . ', Logged In :: anthony_anderson@civicrm.org',
2522 );
2523 $this->assertEquals(6, $result['count']);
2524 foreach ($expectedData as $index => $value) {
2525 $this->assertEquals($value, $result['values'][$index]['data']);
2526 }
2527 $result = $this->callAPISuccess('contact', 'getquick', array(
2528 'name' => 'h.',
2529 ));
2530 $expectedData = array(
2531 'H Bobby, Bobby :: bob@h.com',
2532 );
2533 foreach ($expectedData as $index => $value) {
2534 $this->assertEquals($value, $result['values'][$index]['data']);
2535 }
2536 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => FALSE));
2537 $result = $this->callAPISuccess('contact', 'getquick', array(
2538 'name' => 'h.',
2539 ));
2540 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => TRUE));
2541 $this->assertEquals(0, $result['count']);
2542 }
2543
2544 /**
2545 * Test that getquick returns contacts with an exact first name match first.
2546 */
2547 public function testGetQuickEmailACL() {
2548 $this->getQuickSearchSampleData();
2549 $loggedInContactID = $this->createLoggedInUser();
2550 CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
2551 $result = $this->callAPISuccess('contact', 'getquick', array(
2552 'name' => 'c',
2553 ));
2554 $this->assertEquals(0, $result['count']);
2555
2556 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereNoBobH'));
2557 CRM_Contact_BAO_Contact_Permission::cache($loggedInContactID, CRM_Core_Permission::VIEW, TRUE);
2558 $result = $this->callAPISuccess('contact', 'getquick', array(
2559 'name' => 'c',
2560 ));
2561
2562 // Without the acl it would be 6 like the previous email getquick test.
2563 $this->assertEquals(5, $result['count']);
2564 $expectedData = array(
2565 'A Bobby, Bobby :: bob@bobby.com',
2566 'Bob, Bob :: bob@bob.com',
2567 'C Bobby, Bobby',
2568 'Second Domain',
2569 $this->callAPISuccessGetValue('Contact', array('id' => $loggedInContactID, 'return' => 'last_name')) . ', Logged In :: anthony_anderson@civicrm.org',
2570 );
2571 foreach ($expectedData as $index => $value) {
2572 $this->assertEquals($value, $result['values'][$index]['data']);
2573 }
2574 }
2575
2576 /**
2577 * Test that getquick returns contacts with an exact first name match first.
2578 */
2579 public function testGetQuickExternalID() {
2580 $this->getQuickSearchSampleData();
2581 $result = $this->callAPISuccess('contact', 'getquick', array(
2582 'name' => 'b',
2583 'field_name' => 'external_identifier',
2584 'table_name' => 'cc',
2585 ));
2586 $this->assertEquals(0, $result['count']);
2587 $result = $this->callAPISuccess('contact', 'getquick', array(
2588 'name' => 'abc',
2589 'field_name' => 'external_identifier',
2590 'table_name' => 'cc',
2591 ));
2592 $this->assertEquals(1, $result['count']);
2593 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
2594 }
2595
2596 /**
2597 * Test that getquick returns contacts with an exact first name match first.
2598 */
2599 public function testGetQuickID() {
2600 $max = CRM_Core_DAO::singleValueQuery("SELECT max(id) FROM civicrm_contact");
2601 $this->getQuickSearchSampleData();
2602 $result = $this->callAPISuccess('contact', 'getquick', array(
2603 'name' => $max + 2,
2604 'field_name' => 'id',
2605 'table_name' => 'cc',
2606 ));
2607 $this->assertEquals(1, $result['count']);
2608 $this->assertEquals('E Bobby, Bobby', $result['values'][0]['sort_name']);
2609 $result = $this->callAPISuccess('contact', 'getquick', array(
2610 'name' => $max + 2,
2611 'field_name' => 'contact_id',
2612 'table_name' => 'cc',
2613 ));
2614 $this->assertEquals(1, $result['count']);
2615 $this->assertEquals('E Bobby, Bobby', $result['values'][0]['sort_name']);
2616 }
2617
2618 /**
2619 * Test that getquick returns contacts with an exact first name match first.
2620 *
2621 * Depending on the setting the sort name sort might click in next or not - test!
2622 */
2623 public function testGetQuickFirstName() {
2624 $this->getQuickSearchSampleData();
2625 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
2626 $result = $this->callAPISuccess('contact', 'getquick', array(
2627 'name' => 'Bob',
2628 'field_name' => 'first_name',
2629 'table_name' => 'cc',
2630 ));
2631 $expected = array(
2632 'Aadvark, Bob',
2633 'Bob, Bob',
2634 'K Bobby, Bob',
2635 'A Bobby, Bobby',
2636 );
2637
2638 foreach ($expected as $index => $value) {
2639 $this->assertEquals($value, $result['values'][$index]['sort_name']);
2640 }
2641 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
2642 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
2643 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
2644 $this->assertEquals('E Bobby, Bobby', $result['values'][1]['sort_name']);
2645 }
2646
2647 /**
2648 * Test that getquick applies ACLs.
2649 */
2650 public function testGetQuickFirstNameACLs() {
2651 $this->getQuickSearchSampleData();
2652 $userID = $this->createLoggedInUser();
2653 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE, 'search_autocomplete_count' => 15));
2654 CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
2655 $result = $this->callAPISuccess('contact', 'getquick', array(
2656 'name' => 'Bob',
2657 'field_name' => 'first_name',
2658 'table_name' => 'cc',
2659 ));
2660 $this->assertEquals(0, $result['count']);
2661
2662 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereNoBobH'));
2663 CRM_Contact_BAO_Contact_Permission::cache($userID, CRM_Core_Permission::VIEW, TRUE);
2664 $result = $this->callAPISuccess('contact', 'getquick', array(
2665 'name' => 'Bob',
2666 'field_name' => 'first_name',
2667 'table_name' => 'cc',
2668 ));
2669 $this->assertEquals('K Bobby, Bob', $result['values'][2]['sort_name']);
2670 // Without the ACL 9 would be bob@h.com.
2671 $this->assertEquals('I Bobby, Bobby', $result['values'][10]['sort_name']);
2672 }
2673
2674 /**
2675 * Full results returned.
2676 * @implements CRM_Utils_Hook::aclWhereClause
2677 *
2678 * @param string $type
2679 * @param array $tables
2680 * @param array $whereTables
2681 * @param int $contactID
2682 * @param string $where
2683 */
2684 public function aclWhereNoBobH($type, &$tables, &$whereTables, &$contactID, &$where) {
2685 $where = " (email <> 'bob@h.com' OR email IS NULL) ";
2686 $whereTables['civicrm_email'] = "LEFT JOIN civicrm_email e ON contact_a.id = e.contact_id";
2687 }
2688
2689 /**
2690 * Test that getquick returns contacts with an exact last name match first.
2691 */
2692 public function testGetQuickLastName() {
2693 $this->getQuickSearchSampleData();
2694 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
2695 $result = $this->callAPISuccess('contact', 'getquick', array(
2696 'name' => 'Bob',
2697 'field_name' => 'last_name',
2698 'table_name' => 'cc',
2699 ));
2700 $expected = array(
2701 'Bob, Bob',
2702 'A Bobby, Bobby',
2703 'B Bobby, Bobby',
2704 );
2705
2706 foreach ($expected as $index => $value) {
2707 $this->assertEquals($value, $result['values'][$index]['sort_name']);
2708 }
2709 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
2710 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
2711 $this->assertEquals('Bob, Bob :: bob@bob.com', $result['values'][0]['data']);
2712 }
2713
2714 /**
2715 * Test that getquick returns contacts by city.
2716 */
2717 public function testGetQuickCity() {
2718 $this->getQuickSearchSampleData();
2719 $result = $this->callAPISuccess('contact', 'getquick', array(
2720 'name' => 'o',
2721 'field_name' => 'city',
2722 'table_name' => 'sts',
2723 ));
2724 $this->assertEquals('B Bobby, Bobby :: Toronto', $result['values'][0]['data']);
2725 $result = $this->callAPISuccess('contact', 'getquick', array(
2726 'name' => 'n',
2727 'field_name' => 'city',
2728 'table_name' => 'sts',
2729 ));
2730 $this->assertEquals('B Bobby, Bobby :: Toronto', $result['values'][0]['data']);
2731 $this->assertEquals('C Bobby, Bobby :: Whanganui', $result['values'][1]['data']);
2732 }
2733
2734 /**
2735 * Set up some sample data for testing quicksearch.
2736 */
2737 public function getQuickSearchSampleData() {
2738 $contacts = array(
2739 array('first_name' => 'Bob', 'last_name' => 'Bob', 'external_identifier' => 'abc', 'email' => 'bob@bob.com'),
2740 array('first_name' => 'Bobby', 'last_name' => 'E Bobby', 'external_identifier' => 'abcd'),
2741 array(
2742 'first_name' => 'Bobby',
2743 'last_name' => 'B Bobby',
2744 'external_identifier' => 'bcd',
2745 'api.address.create' => array(
2746 'street_address' => 'Sesame Street',
2747 'city' => 'Toronto',
2748 'location_type_id' => 1,
2749 ),
2750 ),
2751 array(
2752 'first_name' => 'Bobby',
2753 'last_name' => 'C Bobby',
2754 'external_identifier' => 'bcde',
2755 'api.address.create' => array(
2756 'street_address' => 'Te huarahi',
2757 'city' => 'Whanganui',
2758 'location_type_id' => 1,
2759 ),
2760 ),
2761 array('first_name' => 'Bobby', 'last_name' => 'D Bobby', 'external_identifier' => 'efg'),
2762 array('first_name' => 'Bobby', 'last_name' => 'A Bobby', 'external_identifier' => 'hij', 'email' => 'bob@bobby.com'),
2763 array('first_name' => 'Bobby', 'last_name' => 'F Bobby', 'external_identifier' => 'klm'),
2764 array('first_name' => 'Bobby', 'last_name' => 'G Bobby', 'external_identifier' => 'nop'),
2765 array('first_name' => 'Bobby', 'last_name' => 'H Bobby', 'external_identifier' => 'qrs', 'email' => 'bob@h.com'),
2766 array('first_name' => 'Bobby', 'last_name' => 'I Bobby'),
2767 array('first_name' => 'Bobby', 'last_name' => 'J Bobby'),
2768 array('first_name' => 'Bob', 'last_name' => 'K Bobby', 'external_identifier' => 'bcdef'),
2769 array('first_name' => 'Bob', 'last_name' => 'Aadvark'),
2770 );
2771 foreach ($contacts as $type => $contact) {
2772 $contact['contact_type'] = 'Individual';
2773 $this->callAPISuccess('Contact', 'create', $contact);
2774 }
2775 }
2776
2777 /**
2778 * Test get ref api - gets a list of references to an entity.
2779 */
2780 public function testGetReferenceCounts() {
2781 $result = $this->callAPISuccess('Contact', 'create', array(
2782 'first_name' => 'Testily',
2783 'last_name' => 'McHaste',
2784 'contact_type' => 'Individual',
2785 'api.Address.replace' => array(
2786 'values' => array(),
2787 ),
2788 'api.Email.replace' => array(
2789 'values' => array(
2790 array(
2791 'email' => 'spam@dev.null',
2792 'is_primary' => 0,
2793 'location_type_id' => 1,
2794 ),
2795 ),
2796 ),
2797 'api.Phone.replace' => array(
2798 'values' => array(
2799 array(
2800 'phone' => '234-567-0001',
2801 'is_primary' => 1,
2802 'location_type_id' => 1,
2803 ),
2804 array(
2805 'phone' => '234-567-0002',
2806 'is_primary' => 0,
2807 'location_type_id' => 1,
2808 ),
2809 ),
2810 ),
2811 ));
2812
2813 //$dao = new CRM_Contact_BAO_Contact();
2814 //$dao->id = $result['id'];
2815 //$this->assertTrue((bool) $dao->find(TRUE));
2816 //
2817 //$refCounts = $dao->getReferenceCounts();
2818 //$this->assertTrue(is_array($refCounts));
2819 //$refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
2820
2821 $refCounts = $this->callAPISuccess('Contact', 'getrefcount', array(
2822 'id' => $result['id'],
2823 ));
2824 $refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts['values']);
2825
2826 $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
2827 $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
2828 $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
2829 $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
2830 $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
2831 }
2832
2833 /**
2834 * Test the use of sql operators.
2835 */
2836 public function testSQLOperatorsOnContactAPI() {
2837 $this->individualCreate();
2838 $this->organizationCreate();
2839 $this->householdCreate();
2840 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE)));
2841 $this->assertEquals($contacts['count'], CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL'));
2842 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE)));
2843 $this->assertEquals($contacts['count'], CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL'));
2844 }
2845
2846 /**
2847 * CRM-14743 - test api respects search operators.
2848 */
2849 public function testGetModifiedDateByOperators() {
2850 $preExistingContactCount = CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact');
2851 $contact1 = $this->individualCreate();
2852 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01', modified_date = '2013-01-01' WHERE id = " . $contact1;
2853 CRM_Core_DAO::executeQuery($sql);
2854 $contact2 = $this->individualCreate();
2855 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01', modified_date = '2013-02-01' WHERE id = " . $contact2;
2856 CRM_Core_DAO::executeQuery($sql);
2857 $contact3 = $this->householdCreate();
2858 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01', modified_date = '2013-03-01' WHERE id = " . $contact3;
2859 CRM_Core_DAO::executeQuery($sql);
2860 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('<' => '2014-01-01')));
2861 $this->assertEquals($contacts['count'], 3);
2862 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('>' => '2014-01-01')));
2863 $this->assertEquals($contacts['count'], $preExistingContactCount);
2864 }
2865
2866 /**
2867 * CRM-14743 - test api respects search operators.
2868 */
2869 public function testGetCreatedDateByOperators() {
2870 $preExistingContactCount = CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact');
2871 $contact1 = $this->individualCreate();
2872 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01' WHERE id = " . $contact1;
2873 CRM_Core_DAO::executeQuery($sql);
2874 $contact2 = $this->individualCreate();
2875 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01' WHERE id = " . $contact2;
2876 CRM_Core_DAO::executeQuery($sql);
2877 $contact3 = $this->householdCreate();
2878 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01' WHERE id = " . $contact3;
2879 CRM_Core_DAO::executeQuery($sql);
2880 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('<' => '2014-01-01')));
2881 $this->assertEquals($contacts['count'], 3);
2882 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('>' => '2014-01-01')));
2883 $this->assertEquals($contacts['count'], $preExistingContactCount);
2884 }
2885
2886 /**
2887 * CRM-14263 check that API is not affected by search profile related bug.
2888 */
2889 public function testReturnCityProfile() {
2890 $contactID = $this->individualCreate();
2891 CRM_Core_Config::singleton()->defaultSearchProfileID = 1;
2892 $this->callAPISuccess('address', 'create', array(
2893 'contact_id' => $contactID,
2894 'city' => 'Cool City',
2895 'location_type_id' => 1,
2896 ));
2897 $result = $this->callAPISuccess('contact', 'get', array('city' => 'Cool City', 'return' => 'contact_type'));
2898 $this->assertEquals(1, $result['count']);
2899 }
2900
2901 /**
2902 * CRM-15443 - ensure getlist api does not return deleted contacts.
2903 */
2904 public function testGetlistExcludeConditions() {
2905 $name = md5(time());
2906 $contact = $this->individualCreate(array('last_name' => $name));
2907 $this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
2908 $this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));
2909 // We should get all but the deleted contact.
2910 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name));
2911 $this->assertEquals(2, $result['count']);
2912 // Force-exclude the deceased contact.
2913 $result = $this->callAPISuccess('contact', 'getlist', array(
2914 'input' => $name,
2915 'params' => array('is_deceased' => 0),
2916 ));
2917 $this->assertEquals(1, $result['count']);
2918 $this->assertEquals($contact, $result['values'][0]['id']);
2919 }
2920
2921 /**
2922 * Test contact getactions.
2923 */
2924 public function testGetActions() {
2925 $description = "Getting the available actions for an entity.";
2926 $result = $this->callAPIAndDocument($this->_entity, 'getactions', array(), __FUNCTION__, __FILE__, $description);
2927 $expected = array(
2928 'create',
2929 'delete',
2930 'get',
2931 'getactions',
2932 'getcount',
2933 'getfields',
2934 'getlist',
2935 'getoptions',
2936 'getquick',
2937 'getrefcount',
2938 'getsingle',
2939 'getvalue',
2940 'merge',
2941 'proximity',
2942 'replace',
2943 'setvalue',
2944 'update',
2945 );
2946 $deprecated = array(
2947 'update',
2948 'getquick',
2949 );
2950 foreach ($expected as $action) {
2951 $this->assertTrue(in_array($action, $result['values']), "Expected action $action");
2952 }
2953 foreach ($deprecated as $action) {
2954 $this->assertArrayKeyExists($action, $result['deprecated']);
2955 }
2956 }
2957
2958 /**
2959 * Test the duplicate check function.
2960 */
2961 public function testDuplicateCheck() {
2962 $this->callAPISuccess('Contact', 'create', array(
2963 'first_name' => 'Harry',
2964 'last_name' => 'Potter',
2965 'email' => 'harry@hogwarts.edu',
2966 'contact_type' => 'Individual',
2967 ));
2968 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
2969 'match' => array(
2970 'first_name' => 'Harry',
2971 'last_name' => 'Potter',
2972 'email' => 'harry@hogwarts.edu',
2973 'contact_type' => 'Individual',
2974 ),
2975 ));
2976
2977 $this->assertEquals(1, $result['count']);
2978 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
2979 'match' => array(
2980 'first_name' => 'Harry',
2981 'last_name' => 'Potter',
2982 'email' => 'no5@privet.drive',
2983 'contact_type' => 'Individual',
2984 ),
2985 ));
2986 $this->assertEquals(0, $result['count']);
2987 }
2988
2989 public function testGetByContactType() {
2990 $individual = $this->callAPISuccess('Contact', 'create', array(
2991 'email' => 'individual@test.com',
2992 'contact_type' => 'Individual',
2993 ));
2994 $household = $this->callAPISuccess('Contact', 'create', array(
2995 'household_name' => 'household@test.com',
2996 'contact_type' => 'Household',
2997 ));
2998 $organization = $this->callAPISuccess('Contact', 'create', array(
2999 'organization_name' => 'organization@test.com',
3000 'contact_type' => 'Organization',
3001 ));
3002 // Test with id - getsingle will throw an exception if not found
3003 $this->callAPISuccess('Contact', 'getsingle', array(
3004 'id' => $individual['id'],
3005 'contact_type' => 'Individual',
3006 ));
3007 $this->callAPISuccess('Contact', 'getsingle', array(
3008 'id' => $individual['id'],
3009 'contact_type' => array('IN' => array('Individual')),
3010 'return' => 'id',
3011 ));
3012 $this->callAPISuccess('Contact', 'getsingle', array(
3013 'id' => $organization['id'],
3014 'contact_type' => array('IN' => array('Individual', 'Organization')),
3015 ));
3016 // Test as array
3017 $result = $this->callAPISuccess('Contact', 'get', array(
3018 'contact_type' => array('IN' => array('Individual', 'Organization')),
3019 'options' => array('limit' => 0),
3020 'return' => 'id',
3021 ));
3022 $this->assertContains($organization['id'], array_keys($result['values']));
3023 $this->assertContains($individual['id'], array_keys($result['values']));
3024 $this->assertNotContains($household['id'], array_keys($result['values']));
3025 // Test as string
3026 $result = $this->callAPISuccess('Contact', 'get', array(
3027 'contact_type' => 'Household',
3028 'options' => array('limit' => 0),
3029 'return' => 'id',
3030 ));
3031 $this->assertNotContains($organization['id'], array_keys($result['values']));
3032 $this->assertNotContains($individual['id'], array_keys($result['values']));
3033 $this->assertContains($household['id'], array_keys($result['values']));
3034 }
3035
3036 /**
3037 * Test merging 2 contacts.
3038 *
3039 * Someone kindly bequethed us the legacy of mixed up use of main_id & other_id
3040 * in the params for contact.merge api.
3041 *
3042 * This test protects that legacy.
3043 */
3044 public function testMergeBizzareOldParams() {
3045 $this->createLoggedInUser();
3046 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params);
3047 $mainContact = $this->callAPISuccess('contact', 'create', $this->_params);
3048 $this->callAPISuccess('contact', 'merge', array(
3049 'main_id' => $mainContact['id'],
3050 'other_id' => $otherContact['id'],
3051 ));
3052 $contacts = $this->callAPISuccess('contact', 'get', $this->_params);
3053 $this->assertEquals($otherContact['id'], $contacts['id']);
3054 }
3055
3056 /**
3057 * Test merging 2 contacts.
3058 */
3059 public function testMerge() {
3060 $this->createLoggedInUser();
3061 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params);
3062 $retainedContact = $this->callAPISuccess('contact', 'create', $this->_params);
3063 $this->callAPISuccess('contact', 'merge', array(
3064 'to_keep_id' => $retainedContact['id'],
3065 'to_remove_id' => $otherContact['id'],
3066 'auto_flip' => FALSE,
3067 ));
3068
3069 $contacts = $this->callAPISuccess('contact', 'get', $this->_params);
3070 $this->assertEquals($retainedContact['id'], $contacts['id']);
3071 $activity = $this->callAPISuccess('Activity', 'getsingle', array(
3072 'target_contact_id' => $retainedContact['id'],
3073 'activity_type_id' => 'Contact Merged',
3074 ));
3075 $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($activity['activity_date_time'])));
3076 $activity2 = $this->callAPISuccess('Activity', 'getsingle', array(
3077 'target_contact_id' => $otherContact['id'],
3078 'activity_type_id' => 'Contact Deleted by Merge',
3079 ));
3080 $this->assertEquals($activity['id'], $activity2['parent_id']);
3081 $this->assertEquals('Normal', civicrm_api3('option_value', 'getvalue', array(
3082 'value' => $activity['priority_id'],
3083 'return' => 'label',
3084 'option_group_id' => 'priority',
3085 )));
3086
3087 }
3088
3089 /**
3090 * Test merging 2 contacts with delete to trash off.
3091 *
3092 * We are checking that there is no error due to attempting to add an activity for the
3093 * deleted contact.
3094 *
3095 * CRM-18307
3096 */
3097 public function testMergeNoTrash() {
3098 $this->createLoggedInUser();
3099 $this->callAPISuccess('Setting', 'create', array('contact_undelete' => FALSE));
3100 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params);
3101 $retainedContact = $this->callAPISuccess('contact', 'create', $this->_params);
3102 $this->callAPISuccess('contact', 'merge', array(
3103 'to_keep_id' => $retainedContact['id'],
3104 'to_remove_id' => $otherContact['id'],
3105 'auto_flip' => FALSE,
3106 ));
3107 $this->callAPISuccess('Setting', 'create', array('contact_undelete' => TRUE));
3108 }
3109
3110 /**
3111 * Ensure format with return=group shows comma-separated group IDs.
3112 *
3113 * CRM-19426
3114 */
3115 public function testContactGetReturnGroup() {
3116 // Set up a contact, asser that they were created.
3117 $contact_params = array(
3118 'contact_type' => 'Individual',
3119 'first_name' => 'Test',
3120 'last_name' => 'Groupmember',
3121 'email' => 'test@example.org',
3122 );
3123 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3124 $this->assertEquals(0, $create_contact['is_error']);
3125 $this->assertInternalType('int', $create_contact['id']);
3126
3127 $created_contact_id = $create_contact['id'];
3128
3129 // Set up multiple groups, add the contact to the groups.
3130 $test_groups = array('Test group A', 'Test group B');
3131 foreach ($test_groups as $title) {
3132 // Use this contact as group owner, since we know they exist.
3133 $group_params = array(
3134 'title' => $title,
3135 'created_id' => $created_contact_id,
3136 );
3137 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3138 $this->assertEquals(0, $create_group['is_error']);
3139 $this->assertInternalType('int', $create_group['id']);
3140
3141 $created_group_ids[] = $create_group['id'];
3142
3143 // Add contact to the new group.
3144 $group_contact_params = array(
3145 'contact_id' => $created_contact_id,
3146 'group_id' => $create_group['id'],
3147 );
3148 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3149 $this->assertEquals(0, $create_group_contact['is_error']);
3150 $this->assertInternalType('int', $create_group_contact['added']);
3151 }
3152
3153 // Use the Contact,get API to retrieve the contact
3154 $contact_get_params = array(
3155 'id' => $created_contact_id,
3156 'return' => 'group',
3157 );
3158 $contact_get = $this->callApiSuccess('Contact', 'get', $contact_get_params);
3159 $this->assertInternalType('array', $contact_get['values'][$created_contact_id]);
3160 $this->assertInternalType('string', $contact_get['values'][$created_contact_id]['groups']);
3161
3162 // Ensure they are shown as being in each created group.
3163 $contact_group_ids = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3164 foreach ($created_group_ids as $created_group_id) {
3165 $this->assertContains($created_group_id, $contact_group_ids);
3166 }
3167 }
3168
3169 }