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