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