Merge pull request #1923 from civicrm/4.3
[civicrm-core.git] / tests / phpunit / api / v3 / ContactTest.php
1 <?php
2 /**
3 * File for the TestContact class
4 *
5 * (PHP 5)
6 *
7 * @author Walt Haas <walt@dharmatech.org> (801) 534-1262
8 * @copyright Copyright CiviCRM LLC (C) 2009
9 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html
10 * GNU Affero General Public License version 3
11 * @version $Id: ContactTest.php 31254 2010-12-15 10:09:29Z eileen $
12 * @package CiviCRM
13 *
14 * This file is part of CiviCRM
15 *
16 * CiviCRM is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Affero General Public License
18 * as published by the Free Software Foundation; either version 3 of
19 * the License, or (at your option) any later version.
20 *
21 * CiviCRM is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU Affero General Public License for more details.
25 *
26 * You should have received a copy of the GNU Affero General Public
27 * License along with this program. If not, see
28 * <http://www.gnu.org/licenses/>.
29 */
30
31 /**
32 * Include class definitions
33 */
34 require_once 'CiviTest/CiviUnitTestCase.php';
35
36
37 /**
38 * Test APIv3 civicrm_contact* functions
39 *
40 * @package CiviCRM_APIv3
41 * @subpackage API_Contact
42 */
43
44 class api_v3_ContactTest extends CiviUnitTestCase {
45 public $DBResetRequired = FALSE;
46 protected $_apiversion;
47 protected $_entity;
48 protected $_params;
49 public $_eNoticeCompliant = TRUE;
50 protected $_contactID;
51 protected $_financialTypeId =1;
52
53 /**
54 * Constructor
55 *
56 * Initialize configuration
57 */
58 function __construct() {
59 parent::__construct();
60 }
61
62 /**
63 * Test setup for every test
64 *
65 * Connect to the database, truncate the tables that will be used
66 * and redirect stdin to a temporary file
67 */
68 public function setUp() {
69 // Connect to the database
70 parent::setUp();
71 $this->_apiversion = 3;
72 $this->_entity = 'contact';
73 $this->_params = array(
74 'first_name' => 'abc1',
75 'contact_type' => 'Individual',
76 'last_name' => 'xyz1',
77 );
78 }
79
80 function tearDown() {
81 // truncate a few tables
82 $tablesToTruncate = array(
83 'civicrm_contact',
84 'civicrm_email',
85 'civicrm_contribution',
86 'civicrm_line_item',
87 'civicrm_website',
88 'civicrm_relationship',
89 'civicrm_uf_match',
90 'civicrm_phone',
91 );
92
93 $this->quickCleanup($tablesToTruncate, TRUE);
94 }
95
96 /**
97 * Test civicrm_contact_create
98 *
99 * Verify that attempt to create individual contact with only
100 * first and last names succeeds
101 */
102 function testAddCreateIndividual() {
103 $oldCount = CRM_Core_DAO::singleValueQuery('select count(*) from civicrm_contact');
104 $params = array(
105 'first_name' => 'abc1',
106 'contact_type' => 'Individual',
107 'last_name' => 'xyz1',
108 );
109
110 $contact = $this->callAPISuccess('contact', 'create', $params);
111 $this->assertTrue(is_numeric($contact['id']), "In line " . __LINE__);
112 $this->assertTrue($contact['id'] > 0, "In line " . __LINE__);
113 $newCount = CRM_Core_DAO::singleValueQuery('select count(*) from civicrm_contact');
114 $this->assertEquals($oldCount+1, $newCount);
115
116 $this->assertDBState('CRM_Contact_DAO_Contact',
117 $contact['id'],
118 $params
119 );
120 }
121
122 /**
123 * Test civicrm_contact_create with sub-types
124 *
125 * Verify that sub-types are created successfully and not deleted by subsequent updates
126 */
127 function testIndividualSubType() {
128 $params = array(
129 'first_name' => 'test abc',
130 'contact_type' => 'Individual',
131 'last_name' => 'test xyz',
132 'contact_sub_type' => array('Student', 'Staff'),
133 );
134 $contact = $this->callAPISuccess('contact', 'create', $params);
135 $cid = $contact['id'];
136
137 $params = array(
138 'id' => $cid,
139 'middle_name' => 'foo',
140 );
141 $this->callAPISuccess('contact', 'create', $params);
142 unset($params['middle_name']);
143
144 $contact = $this->callAPISuccess('contact', 'get', $params);
145
146 $this->assertEquals(array('Student', 'Staff'), $contact['values'][$cid]['contact_sub_type'], "In line " . __LINE__);
147 }
148
149 /**
150 * Verify that attempt to create contact with empty params fails
151 */
152 function testCreateEmptyContact() {
153 $this->callAPIFailure('contact', 'create', array());
154 }
155
156 /**
157 * Verify that attempt to create contact with bad contact type fails
158 */
159 function testCreateBadTypeContact() {
160 $params = array(
161 'email' => 'man1@yahoo.com',
162 'contact_type' => 'Does not Exist',
163 );
164 $result = $this->callAPIFailure('contact', 'create', $params,"'Does not Exist' is not a valid option for field contact_type");
165 }
166
167 /**
168 * Verify that attempt to create individual contact with required
169 * fields missing fails
170 */
171 function testCreateBadRequiredFieldsIndividual() {
172 $params = array(
173 'middle_name' => 'This field is not required',
174 'contact_type' => 'Individual',
175 );
176
177 $contact = $this->callAPIFailure('contact', 'create', $params);
178 }
179
180 /**
181 * Verify that attempt to create household contact with required
182 * fields missing fails
183 */
184 function testCreateBadRequiredFieldsHousehold() {
185 $params = array(
186 'middle_name' => 'This field is not required',
187 'contact_type' => 'Household',
188 );
189 $contact = $this->callAPIFailure('contact', 'create', $params);
190 }
191
192 /**
193 * Verify that attempt to create organization contact with
194 * required fields missing fails
195 */
196 function testCreateBadRequiredFieldsOrganization() {
197 $params = array(
198 'middle_name' => 'This field is not required',
199 'contact_type' => 'Organization',
200 );
201
202 $contact = $this->callAPIFailure('contact', 'create', $params);
203 }
204
205 /**
206 * Verify that attempt to create individual contact with only an
207 * email succeeds
208 */
209 function testCreateEmailIndividual() {
210
211 $params = array(
212 'email' => 'man3@yahoo.com',
213 'contact_type' => 'Individual',
214 'location_type_id' => 1,
215 );
216
217 $contact = $this->callAPISuccess('contact', 'create', $params);
218
219 $this->assertEquals(1, $contact['id'], "In line " . __LINE__);
220 $email = $this->callAPISuccess('email', 'get', array('contact_id' => $contact['id']));
221 $this->assertEquals(1, $email['count']);
222 $this->assertEquals('man3@yahoo.com', $email['values'][$email['id']]['email']);
223
224 $this->callAPISuccess('contact', 'delete', $contact);
225 }
226
227 /**
228 * Verify that attempt to create individual contact with only
229 * first and last names succeeds
230 */
231 function testCreateNameIndividual() {
232 $params = array(
233 'first_name' => 'abc1',
234 'contact_type' => 'Individual',
235 'last_name' => 'xyz1',
236 );
237
238 $contact = $this->callAPISuccess('contact', 'create', $params);
239 $this->assertEquals(1, $contact['id']);
240 }
241
242 /**
243 * Verify that attempt to create individual contact with
244 * first and last names and old key values works
245 */
246 function testCreateNameIndividualOldKeys() {
247 $params = array(
248 'individual_prefix' => 'Dr.',
249 'first_name' => 'abc1',
250 'contact_type' => 'Individual',
251 'last_name' => 'xyz1',
252 'individual_suffix' => 'Jr.',
253 );
254
255 $contact = $this->callAPISuccess('contact', 'create', $params);
256 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
257
258 $this->assertArrayKeyExists('prefix_id', $result);
259 $this->assertArrayKeyExists('suffix_id', $result);
260 $this->assertArrayKeyExists('gender_id', $result);
261 $this->assertEquals(4, $result['prefix_id']);
262 $this->assertEquals(1, $result['suffix_id']);
263 }
264
265 /**
266 * Verify that attempt to create individual contact with
267 * first and last names and old key values works
268 */
269 function testCreateNameIndividualrecommendedKeys2() {
270 $params = array(
271 'prefix_id' => 'Dr.',
272 'first_name' => 'abc1',
273 'contact_type' => 'Individual',
274 'last_name' => 'xyz1',
275 'suffix_id' => 'Jr.',
276 'gender_id' => 'Male',
277 );
278
279 $contact = $this->callAPISuccess('contact', 'create', $params);
280 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
281
282 $this->assertArrayKeyExists('prefix_id', $result);
283 $this->assertArrayKeyExists('suffix_id', $result);
284 $this->assertArrayKeyExists('gender_id', $result);
285 $this->assertEquals(4, $result['prefix_id']);
286 $this->assertEquals(1, $result['suffix_id']);
287 }
288
289 /**
290 * Verify that attempt to create household contact with only
291 * household name succeeds
292 */
293 function testCreateNameHousehold() {
294 $params = array(
295 'household_name' => 'The abc Household',
296 'contact_type' => 'Household',
297 );
298 $contact = $this->callAPISuccess('contact', 'create', $params);
299 $this->assertEquals(1, $contact['id'], "In line " . __LINE__);
300 }
301
302 /**
303 * Verify that attempt to create organization contact with only
304 * organization name succeeds
305 */
306 function testCreateNameOrganization() {
307 $params = array(
308 'organization_name' => 'The abc Organization',
309 'contact_type' => 'Organization',
310 );
311 $contact = $this->callAPISuccess('contact', 'create', $params);
312 $this->assertEquals(1, $contact['id']);
313 }
314 /**
315 * Verify that attempt to create organization contact without organization name fails
316 */
317 function testCreateNoNameOrganization() {
318 $params = array(
319 'first_name' => 'The abc Organization',
320 'contact_type' => 'Organization',
321 );
322 $result = $this->callAPIFailure('contact', 'create', $params);
323 }
324 /**
325 * check with complete array + custom field
326 * Note that the test is written on purpose without any
327 * variables specific to participant so it can be replicated into other entities
328 * and / or moved to the automated test suite
329 */
330 function testCreateWithCustom() {
331 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
332
333 $params = $this->_params;
334 $params['custom_' . $ids['custom_field_id']] = "custom string";
335 $description = "/*this demonstrates setting a custom field through the API ";
336 $subfile = "CustomFieldCreate";
337 $result = $this->callAPIAndDocument($this->_entity, 'create', $params, __FUNCTION__, __FILE__, $description);
338
339 $check = $this->callAPISuccess($this->_entity, 'get', array('return.custom_' . $ids['custom_field_id'] => 1, 'id' => $result['id']));
340 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
341
342 $this->customFieldDelete($ids['custom_field_id']);
343 $this->customGroupDelete($ids['custom_group_id']);
344 }
345
346 /**
347 * CRM-12773 - expectation is that civicrm quietly ignores
348 * fields without values
349 */
350 function testCreateWithNULLCustomCRM12773() {
351 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
352 $params = $this->_params;
353 $params['custom_' . $ids['custom_field_id']] = NULL;
354 $result = $this->callAPISuccess('contact', 'create', $params);
355 $this->customFieldDelete($ids['custom_field_id']);
356 $this->customGroupDelete($ids['custom_group_id']);
357 }
358
359
360 /*
361 * Test creating a current employer through API
362 */
363 function testContactCreateCurrentEmployer(){
364 //here we will just do the get for set-up purposes
365 $count = $this->callAPISuccess('contact', 'getcount', array(
366 'organization_name' => 'new employer org',
367 'contact_type' => 'Organization'
368 ));
369 $this->assertEquals(0, $count);
370 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
371 'current_employer' => 'new employer org',)
372 ));
373 $expectedCount = 1;
374 $count = $this->callAPISuccess('contact', 'getcount', array(
375 'organization_name' => 'new employer org',
376 'contact_type' => 'Organization'
377 ),
378 $expectedCount);
379
380 $result = $this->callAPISuccess('contact', 'getsingle', array(
381 'id' => $employerResult['id'],
382 ));
383
384 $this->assertEquals('new employer org', $result['current_employer']);
385
386 }
387 /**
388 * Check deceased contacts are not retrieved
389 * Note at time of writing the default is to return default. This should possibly be changed & test added
390 *
391 */
392 function testGetDeceasedRetrieved() {
393 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
394 $c2 = $this->callAPISuccess($this->_entity, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual', 'is_deceased' => 1));
395 $result = $this->callAPISuccess($this->_entity, 'get', array('is_deceased' => 0));
396 $this->assertFalse(array_key_exists($c2['id'], $result['values']));
397 }
398
399 /*
400 * Test that sort works - old syntax
401 */
402 function testGetSort() {
403 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
404 $c2 = $this->callAPISuccess($this->_entity, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual'));
405 $result = $this->callAPISuccess($this->_entity, 'get', array(
406 'sort' => 'first_name ASC',
407 'return.first_name' => 1,
408 'sequential' => 1,
409 'rowCount' => 1,
410 ));
411
412 $this->assertEquals('abc1', $result['values'][0]['first_name']);
413 $result = $this->callAPISuccess($this->_entity, 'get', array(
414 'sort' => 'first_name DESC',
415 'return.first_name' => 1,
416 'sequential' => 1,
417 'rowCount' => 1,
418 ));
419 $this->assertEquals('bb', $result['values'][0]['first_name']);
420
421 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
422 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
423 }
424 /*
425 * Test that we can retrieve contacts using
426 * 'id' => array('IN' => array('3,4')) syntax
427 */
428 function testGetINIDArray() {
429 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
430 $c2 = $this->callAPISuccess($this->_entity, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual'));
431 $c3 = $this->callAPISuccess($this->_entity, 'create', array('first_name' => 'hh', 'last_name' => 'll', 'contact_type' => 'Individual'));
432 $result = $this->callAPISuccess($this->_entity, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
433 $this->assertEquals(2, $result['count']);
434 $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
435 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
436 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
437 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c3['id']));
438 }
439 /*
440 * Test variants on deleted behaviour
441 */
442 function testGetDeleted() {
443 $params = $this->_params;
444 $contact1 = $this->callAPISuccess('contact', 'create', $params);
445 $params['is_deleted'] = 1;
446 $params['last_name'] = 'bcd';
447 $contact2 = $this->callAPISuccess('contact', 'create', $params);
448 $countActive = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'active'));
449 $countAll = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'all'));
450 $countTrash = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'trash'));
451 $countDefault = $this->callAPISuccess('contact', 'getcount', array());
452 $countDeleted = $this->callAPISuccess('contact', 'getcount', array(
453 'contact_is_deleted' => 1,
454 ));
455 $countNotDeleted = $this->callAPISuccess('contact', 'getcount', array(
456 'contact_is_deleted' => 0,
457 ));
458 $this->callAPISuccess('contact', 'delete', array('id' => $contact1['id']));
459 $this->callAPISuccess('contact', 'delete', array('id' => $contact2['id']));
460 $this->assertEquals(1, $countNotDeleted, 'contact_is_deleted => 0 is respected in line ' . __LINE__);
461 $this->assertEquals(1, $countActive, 'in line ' . __LINE__);
462 $this->assertEquals(1, $countTrash, 'in line ' . __LINE__);
463 $this->assertEquals(2, $countAll, 'in line ' . __LINE__);
464 $this->assertEquals(1, $countDeleted, 'in line ' . __LINE__);
465 $this->assertEquals(1, $countDefault, 'Only active by default in line ' . __LINE__);
466 }
467 /*
468 * Test that sort works - new syntax
469 */
470 function testGetSortNewSYntax() {
471 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
472 $c2 = $this->callAPISuccess($this->_entity, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual'));
473 $result = $this->callAPISuccess($this->_entity, 'getvalue', array(
474 'return' => 'first_name',
475 'options' => array(
476 'limit' => 1,
477 'sort' => 'first_name',
478 ),
479 ));
480 $this->assertEquals('abc1', $result, 'in line' . __LINE__);
481
482 $result = $this->callAPISuccess($this->_entity, 'getvalue', array(
483 'return' => 'first_name',
484 'options' => array(
485 'limit' => 1,
486 'sort' => 'first_name DESC',
487 ),
488 ));
489 $this->assertEquals('bb', $result);
490
491 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
492 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
493 }
494 /*
495 * Test appostrophe works in get & create
496 */
497 function testGetAppostropheCRM10857() {
498 $params = array_merge($this->_params, array('last_name' => "O'Connor"));
499 $contact = $this->callAPISuccess($this->_entity, 'create', $params);
500 $result = $this->callAPISuccess($this->_entity, 'getsingle', array(
501 'last_name' => "O'Connor",
502 'sequential' => 1,
503 ));
504 $this->assertEquals("O'Connor", $result['last_name'], 'in line' . __LINE__);
505 }
506
507 /**
508 * check with complete array + custom field
509 * Note that the test is written on purpose without any
510 * variables specific to participant so it can be replicated into other entities
511 * and / or moved to the automated test suite
512 */
513 function testGetWithCustom() {
514 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
515
516 $params = $this->_params;
517 $params['custom_' . $ids['custom_field_id']] = "custom string";
518 $description = "/*this demonstrates setting a custom field through the API ";
519 $subfile = "CustomFieldGet";
520 $result = $this->callAPISuccess($this->_entity, 'create', $params);
521
522 $check = $this->callAPIAndDocument($this->_entity, 'get', array('return.custom_' . $ids['custom_field_id'] => 1, 'id' => $result['id']), __FUNCTION__, __FILE__, $description, $subfile);
523
524 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
525 $fields = ($this->callAPISuccess('contact', 'getfields', $params));
526 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
527 $this->customFieldDelete($ids['custom_field_id']);
528 $this->customGroupDelete($ids['custom_group_id']);
529 }
530 /*
531 * check with complete array + custom field
532 * Note that the test is written on purpose without any
533 * variables specific to participant so it can be replicated into other entities
534 * and / or moved to the automated test suite
535 */
536 function testGetWithCustomReturnSyntax() {
537 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
538
539 $params = $this->_params;
540 $params['custom_' . $ids['custom_field_id']] = "custom string";
541 $description = "/*this demonstrates setting a custom field through the API ";
542 $subfile = "CustomFieldGetReturnSyntaxVariation";
543 $result = $this->callAPISuccess($this->_entity, 'create', $params);
544 $params = array('return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']);
545 $check = $this->callAPIAndDocument($this->_entity, 'get', $params, __FUNCTION__, __FILE__, $description, $subfile);
546
547 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
548 $this->customFieldDelete($ids['custom_field_id']);
549 $this->customGroupDelete($ids['custom_group_id']);
550 }
551
552 function testGetGroupIDFromContact() {
553 $groupId = $this->groupCreate(NULL);
554 $description = "Get all from group and display contacts";
555 $subfile = "GroupFilterUsingContactAPI";
556 $params = array(
557 'email' => 'man2@yahoo.com',
558 'contact_type' => 'Individual',
559 'location_type_id' => 1,
560 'api.group_contact.create' => array('group_id' => $groupId),
561 );
562
563 $contact = $this->callAPISuccess('contact', 'create', $params);
564 // testing as integer
565 $params = array(
566 'filter.group_id' => $groupId,
567 'contact_type' => 'Individual',
568 );
569 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__, $description, $subfile);
570 $this->assertEquals(1, $result['count']);
571 // group 26 doesn't exist, but we can still search contacts in it.
572 $params = array(
573 'filter.group_id' => 26,
574 'contact_type' => 'Individual',
575 );
576 $result = $this->callAPISuccess('contact', 'get', $params);
577 // testing as string
578 $params = array(
579 'filter.group_id' => "$groupId, 26",
580 'contact_type' => 'Individual',
581 );
582 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__, $description, $subfile);
583 $this->assertEquals(1, $result['count']);
584 $params = array(
585 'filter.group_id' => "26,27",
586 'contact_type' => 'Individual',
587 );
588 $result = $this->callAPISuccess('contact', 'get', $params);
589
590 // testing as string
591 $params = array('filter.group_id' => array($groupId, 26),
592 'contact_type' => 'Individual',
593 );
594 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__, $description, $subfile);
595 $this->assertEquals(1, $result['count']);
596
597 //test in conjunction with other criteria
598 $params = array('filter.group_id' => array($groupId, 26),
599 'contact_type' => 'Organization',
600 );
601 $result = $this->callAPISuccess('contact', 'get', $params);
602 $params = array('filter.group_id' => array(26, 27),
603 'contact_type' => 'Individual',
604 );
605 $result = $this->callAPISuccess('contact', 'get', $params);
606 $this->assertEquals(0, $result['count'], " in line " . __LINE__);
607 }
608
609 /**
610 * Verify that attempt to create individual contact with two chained websites succeeds
611 */
612 function testCreateIndividualWithContributionDottedSyntax() {
613 $description = "test demonstrates the syntax to create 2 chained entities";
614 $subfile = "ChainTwoWebsites";
615 $params = array(
616 'first_name' => 'abc3',
617 'last_name' => 'xyz3',
618 'contact_type' => 'Individual',
619 'email' => 'man3@yahoo.com',
620 'api.contribution.create' => array(
621 'receive_date' => '2010-01-01',
622 'total_amount' => 100.00,
623 'financial_type_id' => $this->_financialTypeId,
624 'payment_instrument_id' => 1,
625 'non_deductible_amount' => 10.00,
626 'fee_amount' => 50.00,
627 'net_amount' => 90.00,
628 'trxn_id' => 15345,
629 'invoice_id' => 67990,
630 'source' => 'SSF',
631 'contribution_status_id' => 1,
632 ),
633 'api.website.create' => array(
634 'url' => "http://civicrm.org",
635 ),
636 'api.website.create.2' => array(
637 'url' => "http://chained.org",
638 ),
639 );
640
641 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__, $description, $subfile);
642
643 $this->assertEquals(1, $result['id'], "In line " . __LINE__);
644 // checking child function result not covered in callAPIAndDocument
645 $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
646 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url'], "In line " . __LINE__);
647 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url'], "In line " . __LINE__);
648
649 // delete the contact
650 $this->callAPISuccess('contact', 'delete', $result);
651 }
652
653 /**
654 * Verify that attempt to create individual contact with chained contribution and website succeeds
655 */
656 function testCreateIndividualWithContributionChainedArrays() {
657 $params = array(
658 'first_name' => 'abc3',
659 'last_name' => 'xyz3',
660 'contact_type' => 'Individual',
661 'email' => 'man3@yahoo.com',
662 'api.contribution.create' => array(
663 'receive_date' => '2010-01-01',
664 'total_amount' => 100.00,
665 'financial_type_id' => $this->_financialTypeId,
666 'payment_instrument_id' => 1,
667 'non_deductible_amount' => 10.00,
668 'fee_amount' => 50.00,
669 'net_amount' => 90.00,
670 'trxn_id' => 12345,
671 'invoice_id' => 67890,
672 'source' => 'SSF',
673 'contribution_status_id' => 1,
674 ),
675 'api.website.create' => array(
676 array(
677 'url' => "http://civicrm.org",
678 ),
679 array(
680 'url' => "http://chained.org",
681 'website_type_id' => 2,
682 ),
683 ),
684 );
685
686 $description = "demonstrates creating two websites as an array";
687 $subfile = "ChainTwoWebsitesSyntax2";
688 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__, $description, $subfile);
689
690 $this->assertEquals(1, $result['id']);
691 // the callAndDocument doesn't check the chained call
692 $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error'], "In line " . __LINE__);
693 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url'], "In line " . __LINE__);
694 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url'], "In line " . __LINE__);
695
696 $this->callAPISuccess('contact', 'delete', $result);
697 }
698
699 /**
700 * Verify that attempt to create individual contact with first
701 * and last names and email succeeds
702 */
703 function testCreateIndividualWithNameEmail() {
704 $params = array(
705 'first_name' => 'abc3',
706 'last_name' => 'xyz3',
707 'contact_type' => 'Individual',
708 'email' => 'man3@yahoo.com',
709 );
710
711 $contact = $this->callAPISuccess('contact', 'create', $params);
712 $this->assertEquals(1, $contact['id'], "In line " . __LINE__);
713
714 // delete the contact
715 $this->callAPISuccess('contact', 'delete', $contact);
716 }
717 /**
718 * Verify that attempt to create individual contact with no data fails
719 */
720 function testCreateIndividualWithOutNameEmail() {
721 $params = array(
722 'contact_type' => 'Individual',
723 );
724
725 $result = $this->callAPIFailure('contact', 'create', $params);
726 }
727 /**
728 * Verify that attempt to create individual contact with first
729 * and last names, email and location type succeeds
730 */
731 function testCreateIndividualWithNameEmailLocationType() {
732 $params = array(
733 'first_name' => 'abc4',
734 'last_name' => 'xyz4',
735 'email' => 'man4@yahoo.com',
736 'contact_type' => 'Individual',
737 'location_type_id' => 1,
738 );
739 $result = $this->callAPISuccess('contact', 'create', $params);
740
741 $this->assertEquals(1, $result['id'], "In line " . __LINE__);
742
743 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
744 }
745
746 /**
747 * Verify that when changing employers
748 * the old employer relationship becomes inactive
749 */
750 function testCreateIndividualWithEmployer() {
751 $employer = $this->organizationCreate();
752 $employer2 = $this->organizationCreate();
753
754 $params = array(
755 'email' => 'man4@yahoo.com',
756 'contact_type' => 'Individual',
757 'employer_id' => $employer,
758 );
759
760 $result = $this->callAPISuccess('contact', 'create', $params);
761 $relationships = $this->callAPISuccess('relationship', 'get', array(
762 'contact_id_a' => $result['id'],
763 'sequential' => 1,
764 ));
765
766 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
767
768 // Add more random relationships to make the test more realistic
769 foreach (array('Employee of', 'Volunteer for') as $rtype) {
770 $relTypeId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', $rtype, 'id', 'name_a_b');
771 $random_rel = $this->callAPISuccess('relationship', 'create', array(
772 'contact_id_a' => $result['id'],
773 'contact_id_b' => $this->organizationCreate(),
774 'is_active' => 1,
775 'relationship_type_id' => $relTypeId,
776 ));
777 }
778
779 // Add second employer
780 $params['employer_id'] = $employer2;
781 $params['id'] = $result['id'];
782 $result = $this->callAPISuccess('contact', 'create', $params);
783
784 $relationships = $this->callAPISuccess('relationship', 'get', array(
785 'contact_id_a' => $result['id'],
786 'sequential' => 1,
787 'is_active' => 0,
788 ));
789
790 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
791 }
792
793 /**
794 * Verify that attempt to create household contact with details
795 * succeeds
796 */
797 function testCreateHouseholdDetails() {
798 $params = array(
799 'household_name' => 'abc8\'s House',
800 'nick_name' => 'x House',
801 'email' => 'man8@yahoo.com',
802 'contact_type' => 'Household',
803 );
804
805 $contact = $this->callAPISuccess('contact', 'create', $params);
806
807 $this->assertEquals(1, $contact['id'], "In line " . __LINE__);
808
809 $this->callAPISuccess('contact', 'delete', $contact);
810 }
811 /**
812 * Verify that attempt to create household contact with inadequate details
813 * fails
814 */
815 function testCreateHouseholdInadequateDetails() {
816 $params = array(
817 'nick_name' => 'x House',
818 'email' => 'man8@yahoo.com',
819 'contact_type' => 'Household',
820 );
821
822 $result = $this->callAPIFailure('contact', 'create', $params);
823 }
824
825 /**
826 * Verify successful update of individual contact
827 */
828 function testUpdateIndividualWithAll() {
829 // Insert a row in civicrm_contact creating individual contact
830 $op = new PHPUnit_Extensions_Database_Operation_Insert();
831 $op->execute($this->_dbconn,
832 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
833 dirname(__FILE__) . '/dataset/contact_ind.xml'
834 )
835 );
836
837 $params = array(
838 'id' => 23,
839 'first_name' => 'abcd',
840 'contact_type' => 'Individual',
841 'nick_name' => 'This is nickname first',
842 'do_not_email' => '1',
843 'do_not_phone' => '1',
844 'do_not_mail' => '1',
845 'do_not_trade' => '1',
846 'legal_identifier' => 'ABC23853ZZ2235',
847 'external_identifier' => '1928837465',
848 'image_URL' => 'http://some.url.com/image.jpg',
849 'home_url' => 'http://www.example.org',
850
851 );
852 $getResult = $this->callAPISuccess('Contact', 'Get', array());
853 $result = $this->callAPISuccess('Contact', 'Update', $params);
854 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
855 unset($params['contact_id']);
856 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
857 //reducing this test partially back to apiv2 level to get it through
858 unset($params['home_url']);
859 foreach ($params as $key => $value) {
860 $this->assertEquals($value, $result['values'][23][$key], "In line " . __LINE__);
861 }
862 // Check updated civicrm_contact against expected
863 $expected = new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
864 dirname(__FILE__) . '/dataset/contact_ind_upd.xml'
865 );
866 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataset(
867 $this->_dbconn
868 );
869 $actual->addTable('civicrm_contact');
870 $expected->matches($actual);
871 }
872
873 /**
874 * Verify successful update of organization contact
875 */
876 function testUpdateOrganizationWithAll() {
877 // Insert a row in civicrm_contact creating organization contact
878 $op = new PHPUnit_Extensions_Database_Operation_Insert();
879 $op->execute($this->_dbconn,
880 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
881 dirname(__FILE__) . '/dataset/contact_org.xml'
882 )
883 );
884
885 $params = array(
886 'id' => 24,
887 'organization_name' => 'WebAccess India Pvt Ltd',
888 'legal_name' => 'WebAccess',
889 'sic_code' => 'ABC12DEF',
890 'contact_type' => 'Organization',
891 );
892
893 $result = $this->callAPISuccess('Contact', 'Update', $params);
894
895 // Check updated civicrm_contact against expected
896 $expected = new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
897 dirname(__FILE__) . '/dataset/contact_org_upd.xml'
898 );
899 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataset(
900 $this->_dbconn
901 );
902 $actual->addTable('civicrm_contact');
903 $expected->matches($actual);
904 }
905
906 /**
907 * Verify successful update of household contact
908 */
909 function testUpdateHouseholdwithAll() {
910 // Insert a row in civicrm_contact creating household contact
911 $op = new PHPUnit_Extensions_Database_Operation_Insert();
912 $op->execute($this->_dbconn,
913 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
914 dirname(__FILE__) . '/dataset/contact_hld.xml'
915 )
916 );
917
918 $params = array(
919 'id' => 25,
920 'household_name' => 'ABC household',
921 'nick_name' => 'ABC House',
922 'contact_type' => 'Household',
923 );
924
925 $result = $this->callAPISuccess('Contact', 'Update', $params);
926
927 // Check updated civicrm_contact against expected
928 $expected = new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
929 dirname(__FILE__) . '/dataset/contact_hld_upd.xml'
930 );
931 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataset(
932 $this->_dbconn
933 );
934 $actual->addTable('civicrm_contact');
935 $expected->matches($actual);
936 }
937
938 /**
939 * Test civicrm_update() Deliberately exclude contact_type as it should still
940 * cope using civicrm_api CRM-7645
941 */
942
943 public function testUpdateCreateWithID() {
944 // Insert a row in civicrm_contact creating individual contact
945 $op = new PHPUnit_Extensions_Database_Operation_Insert();
946 $op->execute($this->_dbconn,
947 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
948 dirname(__FILE__) . '/dataset/contact_ind.xml'
949 )
950 );
951
952
953
954 $params = array(
955 'id' => 23,
956 'first_name' => 'abcd',
957 'last_name' => 'wxyz',
958 );
959
960 $result = $this->callAPISuccess('Contact', 'Update', $params);
961 }
962
963 /**
964 * Test civicrm_contact_delete() with no contact ID
965 */
966 function testContactDeleteNoID() {
967 $params = array(
968 'foo' => 'bar',
969 );
970 $result = $this->callAPIFailure('contact', 'delete', $params);
971 }
972
973 /**
974 * Test civicrm_contact_delete() with error
975 */
976 function testContactDeleteError() {
977 $params = array('contact_id' => 999);
978 $result = $this->callAPIFailure('contact', 'delete', $params);
979 }
980
981 /**
982 * Test civicrm_contact_delete()
983 */
984 function testContactDelete() {
985 $contactID = $this->individualCreate();
986 $params = array(
987 'id' => $contactID ,
988 );
989 $result = $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__, __FILE__);
990 }
991
992 /**
993 * Test civicrm_contact_get() return only first name
994 */
995 public function testContactGetRetFirst() {
996 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
997 $params = array(
998 'contact_id' => $contact['id'],
999 'return_first_name' => TRUE,
1000 'sort' => 'first_name',
1001 );
1002 $result = $this->callAPISuccess('contact', 'get', $params);
1003 $this->assertEquals(1, $result['count'], "In line " . __LINE__);
1004 $this->assertEquals($contact['id'], $result['id'], "In line " . __LINE__);
1005 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name'], "In line " . __LINE__);
1006 }
1007
1008 /**
1009 * Test civicrm_contact_get() return only first name & last name
1010 * Use comma separated string return with a space
1011 */
1012 public function testContactGetRetFirstLast() {
1013 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
1014 $params = array(
1015 'contact_id' => $contact['id'],
1016 'return' => 'first_name, last_name',
1017 );
1018 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1019 $this->assertEquals('abc1', $result['first_name'], "In line " . __LINE__);
1020 $this->assertEquals('xyz1', $result['last_name'], "In line " . __LINE__);
1021 //check that other defaults not returns
1022 $this->assertArrayNotHasKey('sort_name', $result);
1023 $params = array(
1024 'contact_id' => $contact['id'],
1025 'return' => 'first_name,last_name',
1026 );
1027 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1028 $this->assertEquals('abc1', $result['first_name'], "In line " . __LINE__);
1029 $this->assertEquals('xyz1', $result['last_name'], "In line " . __LINE__);
1030 //check that other defaults not returns
1031 $this->assertArrayNotHasKey('sort_name', $result);
1032 }
1033
1034 /**
1035 * Test civicrm_contact_get() return only first name & last name
1036 * Use comma separated string return without a space
1037 */
1038 public function testContactGetRetFirstLastNoComma() {
1039 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
1040 $params = array(
1041 'contact_id' => $contact['id'],
1042 'return' => 'first_name,last_name',
1043 );
1044 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1045 $this->assertEquals('abc1', $result['first_name'], "In line " . __LINE__);
1046 $this->assertEquals('xyz1', $result['last_name'], "In line " . __LINE__);
1047 //check that other defaults not returns
1048 $this->assertArrayNotHasKey('sort_name', $result);
1049 }
1050
1051 /**
1052 * Test civicrm_contact_get() with default return properties
1053 */
1054 public function testContactGetRetDefault() {
1055 // Insert a row in civicrm_contact creating contact 17
1056 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1057 $op->execute($this->_dbconn,
1058 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
1059 dirname(__FILE__) . '/dataset/contact_17.xml'
1060 )
1061 );
1062 $params = array(
1063 'contact_id' => 17,
1064 'sort' => 'first_name',
1065 );
1066 $result = $this->callAPISuccess('contact', 'get', $params);
1067 $this->assertEquals(17, $result['values'][17]['contact_id'], "In line " . __LINE__);
1068 $this->assertEquals('Test', $result['values'][17]['first_name'], "In line " . __LINE__);
1069 }
1070
1071 /**
1072 * Test civicrm_contact_quicksearch() with empty name param
1073 */
1074 public function testContactGetQuickEmpty() {
1075 $result = $this->callAPIFailure('contact', 'getquick', array());
1076 }
1077
1078 /**
1079 * Test civicrm_contact_quicksearch() with empty name param
1080 */
1081 public function testContactGetQuick() {
1082 // Insert a row in civicrm_contact creating individual contact
1083 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1084 $op->execute($this->_dbconn,
1085 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
1086 dirname(__FILE__) . '/dataset/contact_17.xml'
1087 )
1088 );
1089 $op->execute($this->_dbconn,
1090 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
1091 dirname(__FILE__) . '/dataset/email_contact_17.xml'
1092 )
1093 );
1094 $params = array(
1095 'name' => "T",
1096 );
1097
1098 $result = $this->callAPISuccess('contact', 'quicksearch', $params);
1099 $this->assertEquals(17, $result['values'][0]['id'], 'in line ' . __LINE__);
1100 }
1101
1102 /**
1103 * Test civicrm_contact_get) with empty params
1104 */
1105 public function testContactGetEmptyParams() {
1106 $result = $this->callAPISuccess('contact', 'get', array());
1107 }
1108
1109 /**
1110 * Test civicrm_contact_get(,true) with no matches
1111 */
1112 public function testContactGetOldParamsNoMatches() {
1113 // Insert a row in civicrm_contact creating contact 17
1114 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1115 $op->execute($this->_dbconn,
1116 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
1117 dirname(__FILE__) . '/dataset/contact_17.xml'
1118 )
1119 );
1120
1121 $params = array(
1122 'first_name' => 'Fred',
1123 );
1124 $result = $this->callAPISuccess('contact', 'get', $params);
1125 $this->assertEquals(0, $result['count'], 'in line ' . __LINE__);
1126 }
1127
1128 /**
1129 * Test civicrm_contact_get(,true) with one match
1130 */
1131 public function testContactGetOldParamsOneMatch() {
1132 // Insert a row in civicrm_contact creating contact 17
1133 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1134 $op->execute($this->_dbconn,
1135 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(dirname(__FILE__) . '/dataset/contact_17.xml'
1136 )
1137 );
1138
1139 $params = array(
1140 'first_name' => 'Test',
1141 );
1142 $result = $this->callAPISuccess('contact', 'get', $params);
1143 $this->assertEquals(17, $result['values'][17]['contact_id'], 'in line ' . __LINE__);
1144 $this->assertEquals(17, $result['id'], 'in line ' . __LINE__);
1145 }
1146
1147 /**
1148 * Test civicrm_contact_search_count()
1149 */
1150 public function testContactGetEmail() {
1151 $params = array(
1152 'email' => 'man2@yahoo.com',
1153 'contact_type' => 'Individual',
1154 'location_type_id' => 1,
1155 );
1156
1157 $contact = $this->callAPISuccess('contact', 'create', $params);
1158
1159 $this->assertEquals(1, $contact['id'], "In line " . __LINE__);
1160
1161 $params = array(
1162 'email' => 'man2@yahoo.com',
1163 );
1164 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__);
1165 $this->assertEquals(1, $result['values'][1]['contact_id'], "In line " . __LINE__);
1166 $this->assertEquals('man2@yahoo.com', $result['values'][1]['email'], "In line " . __LINE__);
1167
1168 // delete the contact
1169 $this->callAPISuccess('contact', 'delete', $contact);
1170 }
1171
1172 /**
1173 * Test for Contact.get id=@user:username
1174 */
1175 function testContactGetByUsername() {
1176 // setup - create contact with a uf-match
1177 $cid = $this->individualCreate(array(
1178 'contact_type' => 'Individual',
1179 'first_name' => 'testGetByUsername',
1180 'last_name' => 'testGetByUsername',
1181 ));
1182
1183 $ufMatchParams = array(
1184 'domain_id' => CRM_Core_Config::domainID(),
1185 'uf_id' => 99,
1186 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
1187 'contact_id' => $cid,
1188 );
1189 $ufMatch = CRM_Core_BAO_UFMatch::create($ufMatchParams);
1190 $this->assertTrue(is_numeric($ufMatch->id));
1191
1192 // setup - mock the calls to CRM_Utils_System_*::getUfId
1193 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1194 $userSystem->expects($this->once())
1195 ->method('getUfId')
1196 ->with($this->equalTo('exampleUser'))
1197 ->will($this->returnValue(99));
1198 CRM_Core_Config::singleton()->userSystem = $userSystem;
1199
1200 // perform a lookup
1201 $result = $this->callAPISuccess('Contact', 'get', array(
1202 'id' => '@user:exampleUser',
1203 ));
1204 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
1205 }
1206
1207 /**
1208 * Test to check return works OK
1209 */
1210 function testContactGetReturnValues() {
1211 $extraParams = array('nick_name' => 'Bob', 'phone' => '456', 'email' => 'e@mail.com');
1212 $contactID = $this->individualCreate($extraParams);
1213 //actually it turns out the above doesn't create a phone
1214 $phones = $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456',));
1215 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
1216 foreach ($extraParams as $key => $value) {
1217 $this->assertEquals($result[$key], $value);
1218 }
1219 //now we check they are still returned with 'return' key
1220 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID, 'return' => array_keys($extraParams)));
1221 foreach ($extraParams as $key => $value) {
1222 $this->assertEquals($result[$key], $value);
1223 }
1224 }
1225
1226 function testCRM13252MultipleChainedPhones() {
1227 $contactID = $this->householdCreate();
1228 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
1229 $params = array(
1230 'contact_id' => $contactID,
1231 'household_name' => 'Household 1',
1232 'contact_type' => 'Household',
1233 'api.phone.create' => array(
1234 0 => array(
1235 'phone' => '111-111-1111',
1236 'location_type_id' => 1,
1237 'phone_type_id' => 1,
1238 ),
1239 1 => array(
1240 'phone' => '222-222-2222',
1241 'location_type_id' => 1,
1242 'phone_type_id' => 2,
1243 )
1244 )
1245 );
1246 $result = $this->callAPISuccess('contact', 'create', $params);
1247 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
1248
1249 }
1250 /**
1251 * Test for Contact.get id=@user:username (with an invalid username)
1252 */
1253 function testContactGetByUnknownUsername() {
1254 // setup - mock the calls to CRM_Utils_System_*::getUfId
1255 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1256 $userSystem->expects($this->once())
1257 ->method('getUfId')
1258 ->with($this->equalTo('exampleUser'))
1259 ->will($this->returnValue(NULL));
1260 CRM_Core_Config::singleton()->userSystem = $userSystem;
1261
1262 // perform a lookup
1263 $result = $this->callAPIFailure('Contact', 'get', array(
1264 'id' => '@user:exampleUser',
1265 ));
1266 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
1267 }
1268
1269 /**
1270 * Verify attempt to create individual with chained arrays
1271 */
1272 function testGetIndividualWithChainedArrays() {
1273 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
1274 $params['custom_' . $ids['custom_field_id']] = "custom string";
1275
1276 $moreids = $this->CustomGroupMultipleCreateWithFields();
1277 $description = "/*this demonstrates the usage of chained api functions. In this case no notes or custom fields have been created ";
1278 $subfile = "APIChainedArray";
1279 $params = array(
1280 'first_name' => 'abc3',
1281 'last_name' => 'xyz3',
1282 'contact_type' => 'Individual',
1283 'email' => 'man3@yahoo.com',
1284 'api.contribution.create' => array(
1285 'receive_date' => '2010-01-01',
1286 'total_amount' => 100.00,
1287 'financial_type_id' => 1,
1288 'payment_instrument_id' => 1,
1289 'non_deductible_amount' => 10.00,
1290 'fee_amount' => 50.00,
1291 'net_amount' => 90.00,
1292 'trxn_id' => 12345,
1293 'invoice_id' => 67890,
1294 'source' => 'SSF',
1295 'contribution_status_id' => 1,
1296 ),
1297 'api.contribution.create.1' => array(
1298 'receive_date' => '2011-01-01',
1299 'total_amount' => 120.00,
1300 'financial_type_id' => $this->_financialTypeId =1,
1301 'payment_instrument_id' => 1,
1302 'non_deductible_amount' => 10.00,
1303 'fee_amount' => 50.00,
1304 'net_amount' => 90.00,
1305 'trxn_id' => 12335,
1306 'invoice_id' => 67830,
1307 'source' => 'SSF',
1308 'contribution_status_id' => 1,
1309 ),
1310 'api.website.create' => array(
1311 array(
1312 'url' => "http://civicrm.org",
1313 ),
1314 ),
1315 );
1316
1317 $result = $this->callAPISuccess('Contact', 'create', $params);
1318 $params = array(
1319 'id' => $result['id'],
1320 'api.website.get' => array(),
1321 'api.Contribution.get' => array(
1322 'total_amount' => '120.00',
1323 ), 'api.CustomValue.get' => 1,
1324 'api.Note.get' => 1,
1325 );
1326 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
1327 // delete the contact
1328 $this->callAPISuccess('contact', 'delete', $result);
1329 $this->customGroupDelete($ids['custom_group_id']);
1330 $this->customGroupDelete($moreids['custom_group_id']);
1331 $this->assertEquals(1, $result['id'], "In line " . __LINE__);
1332 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error'], "In line " . __LINE__);
1333 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url'], "In line " . __LINE__);
1334 }
1335
1336 function testGetIndividualWithChainedArraysFormats() {
1337 $description = "/*this demonstrates the usage of chained api functions. A variety of return formats are used. Note that no notes
1338 *custom fields or memberships exist";
1339 $subfile = "APIChainedArrayFormats";
1340 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
1341 $params['custom_' . $ids['custom_field_id']] = "custom string";
1342
1343 $moreids = $this->CustomGroupMultipleCreateWithFields();
1344 $params = array(
1345 'first_name' => 'abc3',
1346 'last_name' => 'xyz3',
1347 'contact_type' => 'Individual',
1348 'email' => 'man3@yahoo.com',
1349 'api.contribution.create' => array(
1350 'receive_date' => '2010-01-01',
1351 'total_amount' => 100.00,
1352 'financial_type_id' => $this->_financialTypeId,
1353 'payment_instrument_id' => 1,
1354 'non_deductible_amount' => 10.00,
1355 'fee_amount' => 50.00,
1356 'net_amount' => 90.00,
1357 'source' => 'SSF',
1358 'contribution_status_id' => 1,
1359 ),
1360 'api.contribution.create.1' => array(
1361 'receive_date' => '2011-01-01',
1362 'total_amount' => 120.00,
1363 'financial_type_id' => $this->_financialTypeId,
1364 'payment_instrument_id' => 1,
1365 'non_deductible_amount' => 10.00,
1366 'fee_amount' => 50.00,
1367 'net_amount' => 90.00,
1368 'source' => 'SSF',
1369 'contribution_status_id' => 1,
1370 ),
1371 'api.website.create' => array(
1372 array(
1373 'url' => "http://civicrm.org",
1374 ),
1375 ),
1376 );
1377
1378
1379 $result = $this->callAPISuccess('Contact', 'create', $params);
1380 $params = array(
1381 'id' => $result['id'],
1382 'api.website.getValue' => array('return' => 'url'),
1383 'api.Contribution.getCount' => array(),
1384 'api.CustomValue.get' => 1,
1385 'api.Note.get' => 1,
1386 'api.Membership.getCount' => array(),
1387 );
1388 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
1389 $this->assertEquals(1, $result['id'], "In line " . __LINE__);
1390 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount'], "In line " . __LINE__);
1391 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error'], "In line " . __LINE__);
1392 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue'], "In line " . __LINE__);
1393
1394 $this->callAPISuccess('contact', 'delete', $result);
1395 $this->customGroupDelete($ids['custom_group_id']);
1396 $this->customGroupDelete($moreids['custom_group_id']);
1397 }
1398
1399 function testGetIndividualWithChainedArraysAndMultipleCustom() {
1400 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
1401 $params['custom_' . $ids['custom_field_id']] = "custom string";
1402 $moreids = $this->CustomGroupMultipleCreateWithFields();
1403 $andmoreids = $this->CustomGroupMultipleCreateWithFields(array('title' => "another group", 'name' => 'another name'));
1404 $description = "/*this demonstrates the usage of chained api functions. A variety of techniques are used";
1405 $subfile = "APIChainedArrayMultipleCustom";
1406 $params = array(
1407 'first_name' => 'abc3',
1408 'last_name' => 'xyz3',
1409 'contact_type' => 'Individual',
1410 'email' => 'man3@yahoo.com',
1411 'api.contribution.create' => array(
1412 'receive_date' => '2010-01-01',
1413 'total_amount' => 100.00,
1414 'financial_type_id' => 1,
1415 'payment_instrument_id' => 1,
1416 'non_deductible_amount' => 10.00,
1417 'fee_amount' => 50.00,
1418 'net_amount' => 90.00,
1419 'trxn_id' => 12345,
1420 'invoice_id' => 67890,
1421 'source' => 'SSF',
1422 'contribution_status_id' => 1,
1423 ),
1424 'api.contribution.create.1' => array(
1425 'receive_date' => '2011-01-01',
1426 'total_amount' => 120.00,
1427 'financial_type_id' => 1,
1428 'payment_instrument_id' => 1,
1429 'non_deductible_amount' => 10.00,
1430 'fee_amount' => 50.00,
1431 'net_amount' => 90.00,
1432 'trxn_id' => 12335,
1433 'invoice_id' => 67830,
1434 'source' => 'SSF',
1435 'contribution_status_id' => 1,
1436 ),
1437 'api.website.create' => array(
1438 array(
1439 'url' => "http://civicrm.org",
1440 ),
1441 ),
1442 'custom_' . $ids['custom_field_id'] => "value 1",
1443 'custom_' . $moreids['custom_field_id'][0] => "value 2",
1444 'custom_' . $moreids['custom_field_id'][1] => "warm beer",
1445 'custom_' . $andmoreids['custom_field_id'][1] => "vegemite",
1446 );
1447
1448
1449 $result = $this->callAPISuccess('Contact', 'create', $params);
1450 $result = $this->callAPISuccess('Contact', 'create', array(
1451 'contact_type' => 'Individual', 'id' => $result['id'], 'custom_' . $moreids['custom_field_id'][0] => "value 3", 'custom_' . $ids['custom_field_id'] => "value 4",
1452 ));
1453
1454 $params = array(
1455 'id' => $result['id'],
1456 'api.website.getValue' => array('return' => 'url'),
1457 'api.Contribution.getCount' => array(),
1458 'api.CustomValue.get' => 1,
1459 );
1460 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
1461
1462 $this->customGroupDelete($ids['custom_group_id']);
1463 $this->customGroupDelete($moreids['custom_group_id']);
1464 $this->customGroupDelete($andmoreids['custom_group_id']);
1465 $this->assertEquals(1, $result['id'], "In line " . __LINE__);
1466 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error'], "In line " . __LINE__);
1467 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue'], "In line " . __LINE__);
1468 }
1469 /*
1470 * Test checks siusage of $values to pick & choose inputs
1471 */
1472 function testChainingValuesCreate() {
1473 $description = "/*this demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
1474 2 child functions - one receives values from the parent (Contact) and the other child (Tag). ";
1475 $subfile = "APIChainedArrayValuesFromSiblingFunction";
1476 $params = array(
1477 'display_name' => 'batman', 'contact_type' => 'Individual',
1478 'api.tag.create' => array('name' => '$value.id', 'description' => '$value.display_name', 'format.only_id' => 1),
1479 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
1480 );
1481 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__, __FILE__, $description, $subfile);
1482 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
1483
1484 $tablesToTruncate = array(
1485 'civicrm_contact',
1486 'civicrm_activity',
1487 'civicrm_entity_tag',
1488 'civicrm_tag',
1489 );
1490 $this->quickCleanup($tablesToTruncate, TRUE);
1491 }
1492
1493 /*
1494 * test TrueFalse format - I couldn't come up with an easy way to get an error on Get
1495 */
1496 function testContactGetFormatIsSuccessTrue() {
1497 $this->createContactFromXML();
1498 $description = "This demonstrates use of the 'format.is_success' param.
1499 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1500 $subfile = "FormatIsSuccess_True";
1501 $params = array('id' => 17, 'format.is_success' => 1);
1502 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
1503 $this->assertEquals(1, $result);
1504 $this->callAPISuccess('Contact', 'Delete', $params);
1505 }
1506 /*
1507 * test TrueFalse format
1508 */
1509 function testContactCreateFormatIsSuccessFalse() {
1510
1511 $description = "This demonstrates use of the 'format.is_success' param.
1512 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1513 $subfile = "FormatIsSuccess_Fail";
1514 $params = array('id' => 500, 'format.is_success' => 1);
1515 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__, __FILE__, $description, $subfile);
1516 $this->assertEquals(0, $result);
1517 }
1518 /*
1519 * test Single Entity format
1520 */
1521 function testContactGetSingle_entity_array() {
1522 $this->createContactFromXML();
1523 $description = "This demonstrates use of the 'format.single_entity_array' param.
1524 /* This param causes the only contact to be returned as an array without the other levels.
1525 /* it will be ignored if there is not exactly 1 result";
1526 $subfile = "GetSingleContact";
1527 $params = array('id' => 17);
1528 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__, __FILE__, $description, $subfile);
1529 $this->assertEquals('Test Contact', $result['display_name'], "in line " . __LINE__);
1530 $this->callAPISuccess('Contact', 'Delete', $params);
1531 }
1532
1533 /*
1534 * test Single Entity format
1535 */
1536 function testContactGetFormatcount_only() {
1537 $this->createContactFromXML();
1538 $description = "/*This demonstrates use of the 'getCount' action
1539 /* This param causes the count of the only function to be returned as an integer";
1540 $subfile = "GetCountContact";
1541 $params = array('id' => 17);
1542 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__, __FILE__, $description, $subfile);
1543 $this->assertEquals('1', $result, "in line " . __LINE__);
1544 $this->callAPISuccess('Contact', 'Delete', $params);
1545 }
1546 /*
1547 * Test id only format
1548 */
1549 function testContactGetFormatID_only() {
1550 $this->createContactFromXML();
1551 $description = "This demonstrates use of the 'format.id_only' param.
1552 /* This param causes the id of the only entity to be returned as an integer.
1553 /* it will be ignored if there is not exactly 1 result";
1554 $subfile = "FormatOnlyID";
1555 $params = array('id' => 17, 'format.only_id' => 1);
1556 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
1557 $this->assertEquals('17', $result, "in line " . __LINE__);
1558 $this->callAPISuccess('Contact', 'Delete', $params);
1559 }
1560
1561 /*
1562 * Test id only format
1563 */
1564 function testContactGetFormatSingleValue() {
1565 $this->createContactFromXML();
1566 $description = "This demonstrates use of the 'format.single_value' param.
1567 /* This param causes only a single value of the only entity to be returned as an string.
1568 /* it will be ignored if there is not exactly 1 result";
1569 $subfile = "FormatSingleValue";
1570 $params = array('id' => 17, 'return' => 'display_name');
1571 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__, __FILE__, $description, $subfile,'getvalue');
1572 $this->assertEquals('Test Contact', $result, "in line " . __LINE__);
1573 $this->callAPISuccess('Contact', 'Delete', $params);
1574 }
1575
1576 function testContactCreationPermissions() {
1577 $params = array(
1578 'contact_type' => 'Individual', 'first_name' => 'Foo',
1579 'last_name' => 'Bear',
1580 'check_permissions' => TRUE,
1581 );
1582 $config = CRM_Core_Config::singleton();
1583 $config->userPermissionClass->permissions = array('access CiviCRM');
1584 $result = $this->callAPIFailure('contact', 'create', $params);
1585 $this->assertEquals('API permission check failed for contact/create call; missing permission: add contacts.', $result['error_message'], 'lacking permissions should not be enough to create a contact');
1586
1587 $config->userPermissionClass->permissions = array('access CiviCRM', 'add contacts', 'import contacts');
1588 $result = $this->callAPISuccess('contact', 'create', $params, NULL, 'overfluous permissions should be enough to create a contact');
1589 }
1590
1591 function testContactUpdatePermissions() {
1592 $params = array('contact_type' => 'Individual', 'first_name' => 'Foo', 'last_name' => 'Bear', 'check_permissions' => TRUE,);
1593 $result = $this->callAPISuccess('contact', 'create', $params);
1594 $config = CRM_Core_Config::singleton();
1595 $params = array('id' => $result['id'], 'contact_type' => 'Individual', 'last_name' => 'Bar', 'check_permissions' => TRUE,);
1596
1597 $config->userPermissionClass->permissions = array('access CiviCRM');
1598 $result = $this->callAPIFailure('contact', 'update', $params);
1599 $this->assertEquals('API permission check failed for contact/update call; missing permission: edit all contacts.', $result['error_message'], 'lacking permissions should not be enough to update a contact');
1600
1601 $config->userPermissionClass->permissions = array('access CiviCRM', 'add contacts', 'view all contacts', 'edit all contacts', 'import contacts');
1602 $result = $this->callAPISuccess('contact', 'update', $params, NULL, 'overfluous permissions should be enough to update a contact');
1603 }
1604
1605 function createContactFromXML() {
1606 // Insert a row in civicrm_contact creating contact 17
1607 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1608 $op->execute($this->_dbconn,
1609 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
1610 dirname(__FILE__) . '/dataset/contact_17.xml'
1611 )
1612 );
1613 }
1614
1615 function testContactProximity() {
1616 // first create a contact with a SF location with a specific
1617 // geocode
1618 $contactID = $this->organizationCreate();
1619
1620 // now create the address
1621 $params = array(
1622 'street_address' => '123 Main Street',
1623 'city' => 'San Francisco',
1624 'is_primary' => 1,
1625 'country_id' => 1228,
1626 'state_province_id' => 1004,
1627 'geo_code_1' => '37.79',
1628 'geo_code_2' => '-122.40',
1629 'location_type_id' => 1,
1630 'contact_id' => $contactID,
1631 );
1632
1633 $result = $this->callAPISuccess('address', 'create', $params);
1634 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__);
1635
1636 // now do a proximity search with a close enough geocode and hope to match
1637 // that specific contact only!
1638 $proxParams = array(
1639 'latitude' => 37.7,
1640 'longitude' => -122.3,
1641 'unit' => 'mile',
1642 'distance' => 10,
1643 );
1644 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
1645 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__);
1646 }
1647 }