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