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