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