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