Action schedule API modifications
[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 // do it again as an update to check it doesn't cause an error
374 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
375 'current_employer' => 'new employer org', 'id' => $employerResult['id'])
376 ));
377 $expectedCount = 1;
378 $count = $this->callAPISuccess('contact', 'getcount', array(
379 'organization_name' => 'new employer org',
380 'contact_type' => 'Organization'
381 ),
382 $expectedCount);
383
384 $result = $this->callAPISuccess('contact', 'getsingle', array(
385 'id' => $employerResult['id'],
386 ));
387
388 $this->assertEquals('new employer org', $result['current_employer']);
389
390 }
391 /*
392 * Test creating a current employer through API
393 * - check it will re-activate a de-activated employer
394 */
395 function testContactCreateDuplicateCurrentEmployerEnables(){
396 //set up - create employer relationship
397 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
398 'current_employer' => 'new employer org',)
399 ));
400 $relationship = $this->callAPISuccess('relationship','get', array(
401 'contact_id_a' => $employerResult['id'],
402 ));
403
404 //disable & check it is disabled
405 $this->callAPISuccess('relationship', 'create', array('id' => $relationship['id'], 'is_active' => 0));
406 $relationship = $this->callAPISuccess('relationship','getvalue', array(
407 'id' => $relationship['id'],
408 'return' => 'is_active'
409 ), 0);
410
411 //re-set the current employer - thus enabling the relationshp
412 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
413 'current_employer' => 'new employer org', 'id' => $employerResult['id'])
414 ));
415 //check is_active is now 1
416 $relationship = $this->callAPISuccess('relationship','getsingle', array(
417 'return' => 'is_active',));
418 $this->assertEquals(1, $relationship['is_active']);
419 }
420
421 /**
422 * Check deceased contacts are not retrieved
423 * Note at time of writing the default is to return default. This should possibly be changed & test added
424 *
425 */
426 function testGetDeceasedRetrieved() {
427 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
428 $c2 = $this->callAPISuccess($this->_entity, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual', 'is_deceased' => 1));
429 $result = $this->callAPISuccess($this->_entity, 'get', array('is_deceased' => 0));
430 $this->assertFalse(array_key_exists($c2['id'], $result['values']));
431 }
432
433 /*
434 * Test that sort works - old syntax
435 */
436 function testGetSort() {
437 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
438 $c2 = $this->callAPISuccess($this->_entity, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual'));
439 $result = $this->callAPISuccess($this->_entity, 'get', array(
440 'sort' => 'first_name ASC',
441 'return.first_name' => 1,
442 'sequential' => 1,
443 'rowCount' => 1,
444 ));
445
446 $this->assertEquals('abc1', $result['values'][0]['first_name']);
447 $result = $this->callAPISuccess($this->_entity, 'get', array(
448 'sort' => 'first_name DESC',
449 'return.first_name' => 1,
450 'sequential' => 1,
451 'rowCount' => 1,
452 ));
453 $this->assertEquals('bb', $result['values'][0]['first_name']);
454
455 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
456 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
457 }
458 /*
459 * Test that we can retrieve contacts using
460 * 'id' => array('IN' => array('3,4')) syntax
461 */
462 function testGetINIDArray() {
463 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
464 $c2 = $this->callAPISuccess($this->_entity, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual'));
465 $c3 = $this->callAPISuccess($this->_entity, 'create', array('first_name' => 'hh', 'last_name' => 'll', 'contact_type' => 'Individual'));
466 $result = $this->callAPISuccess($this->_entity, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
467 $this->assertEquals(2, $result['count']);
468 $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
469 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
470 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
471 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c3['id']));
472 }
473 /*
474 * Test variants on deleted behaviour
475 */
476 function testGetDeleted() {
477 $params = $this->_params;
478 $contact1 = $this->callAPISuccess('contact', 'create', $params);
479 $params['is_deleted'] = 1;
480 $params['last_name'] = 'bcd';
481 $contact2 = $this->callAPISuccess('contact', 'create', $params);
482 $countActive = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'active'));
483 $countAll = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'all'));
484 $countTrash = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'trash'));
485 $countDefault = $this->callAPISuccess('contact', 'getcount', array());
486 $countDeleted = $this->callAPISuccess('contact', 'getcount', array(
487 'contact_is_deleted' => 1,
488 ));
489 $countNotDeleted = $this->callAPISuccess('contact', 'getcount', array(
490 'contact_is_deleted' => 0,
491 ));
492 $this->callAPISuccess('contact', 'delete', array('id' => $contact1['id']));
493 $this->callAPISuccess('contact', 'delete', array('id' => $contact2['id']));
494 $this->assertEquals(1, $countNotDeleted, 'contact_is_deleted => 0 is respected in line ' . __LINE__);
495 $this->assertEquals(1, $countActive, 'in line ' . __LINE__);
496 $this->assertEquals(1, $countTrash, 'in line ' . __LINE__);
497 $this->assertEquals(2, $countAll, 'in line ' . __LINE__);
498 $this->assertEquals(1, $countDeleted, 'in line ' . __LINE__);
499 $this->assertEquals(1, $countDefault, 'Only active by default in line ' . __LINE__);
500 }
501 /*
502 * Test that sort works - new syntax
503 */
504 function testGetSortNewSYntax() {
505 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
506 $c2 = $this->callAPISuccess($this->_entity, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual'));
507 $result = $this->callAPISuccess($this->_entity, 'getvalue', array(
508 'return' => 'first_name',
509 'options' => array(
510 'limit' => 1,
511 'sort' => 'first_name',
512 ),
513 ));
514 $this->assertEquals('abc1', $result, 'in line' . __LINE__);
515
516 $result = $this->callAPISuccess($this->_entity, 'getvalue', array(
517 'return' => 'first_name',
518 'options' => array(
519 'limit' => 1,
520 'sort' => 'first_name DESC',
521 ),
522 ));
523 $this->assertEquals('bb', $result);
524
525 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
526 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
527 }
528 /*
529 * Test appostrophe works in get & create
530 */
531 function testGetAppostropheCRM10857() {
532 $params = array_merge($this->_params, array('last_name' => "O'Connor"));
533 $contact = $this->callAPISuccess($this->_entity, 'create', $params);
534 $result = $this->callAPISuccess($this->_entity, 'getsingle', array(
535 'last_name' => "O'Connor",
536 'sequential' => 1,
537 ));
538 $this->assertEquals("O'Connor", $result['last_name'], 'in line' . __LINE__);
539 }
540
541 /**
542 * check with complete array + custom field
543 * Note that the test is written on purpose without any
544 * variables specific to participant so it can be replicated into other entities
545 * and / or moved to the automated test suite
546 */
547 function testGetWithCustom() {
548 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
549
550 $params = $this->_params;
551 $params['custom_' . $ids['custom_field_id']] = "custom string";
552 $description = "/*this demonstrates setting a custom field through the API ";
553 $subfile = "CustomFieldGet";
554 $result = $this->callAPISuccess($this->_entity, 'create', $params);
555
556 $check = $this->callAPIAndDocument($this->_entity, 'get', array('return.custom_' . $ids['custom_field_id'] => 1, 'id' => $result['id']), __FUNCTION__, __FILE__, $description, $subfile);
557
558 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
559 $fields = ($this->callAPISuccess('contact', 'getfields', $params));
560 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
561 $this->customFieldDelete($ids['custom_field_id']);
562 $this->customGroupDelete($ids['custom_group_id']);
563 }
564 /*
565 * check with complete array + custom field
566 * Note that the test is written on purpose without any
567 * variables specific to participant so it can be replicated into other entities
568 * and / or moved to the automated test suite
569 */
570 function testGetWithCustomReturnSyntax() {
571 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
572
573 $params = $this->_params;
574 $params['custom_' . $ids['custom_field_id']] = "custom string";
575 $description = "/*this demonstrates setting a custom field through the API ";
576 $subfile = "CustomFieldGetReturnSyntaxVariation";
577 $result = $this->callAPISuccess($this->_entity, 'create', $params);
578 $params = array('return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']);
579 $check = $this->callAPIAndDocument($this->_entity, 'get', $params, __FUNCTION__, __FILE__, $description, $subfile);
580
581 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
582 $this->customFieldDelete($ids['custom_field_id']);
583 $this->customGroupDelete($ids['custom_group_id']);
584 }
585
586 function testGetGroupIDFromContact() {
587 $groupId = $this->groupCreate(NULL);
588 $description = "Get all from group and display contacts";
589 $subfile = "GroupFilterUsingContactAPI";
590 $params = array(
591 'email' => 'man2@yahoo.com',
592 'contact_type' => 'Individual',
593 'location_type_id' => 1,
594 'api.group_contact.create' => array('group_id' => $groupId),
595 );
596
597 $contact = $this->callAPISuccess('contact', 'create', $params);
598 // testing as integer
599 $params = array(
600 'filter.group_id' => $groupId,
601 'contact_type' => 'Individual',
602 );
603 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__, $description, $subfile);
604 $this->assertEquals(1, $result['count']);
605 // group 26 doesn't exist, but we can still search contacts in it.
606 $params = array(
607 'filter.group_id' => 26,
608 'contact_type' => 'Individual',
609 );
610 $result = $this->callAPISuccess('contact', 'get', $params);
611 // testing as string
612 $params = array(
613 'filter.group_id' => "$groupId, 26",
614 'contact_type' => 'Individual',
615 );
616 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__, $description, $subfile);
617 $this->assertEquals(1, $result['count']);
618 $params = array(
619 'filter.group_id' => "26,27",
620 'contact_type' => 'Individual',
621 );
622 $result = $this->callAPISuccess('contact', 'get', $params);
623
624 // testing as string
625 $params = array('filter.group_id' => array($groupId, 26),
626 'contact_type' => 'Individual',
627 );
628 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__, $description, $subfile);
629 $this->assertEquals(1, $result['count']);
630
631 //test in conjunction with other criteria
632 $params = array('filter.group_id' => array($groupId, 26),
633 'contact_type' => 'Organization',
634 );
635 $result = $this->callAPISuccess('contact', 'get', $params);
636 $params = array('filter.group_id' => array(26, 27),
637 'contact_type' => 'Individual',
638 );
639 $result = $this->callAPISuccess('contact', 'get', $params);
640 $this->assertEquals(0, $result['count'], " in line " . __LINE__);
641 }
642
643 /**
644 * Verify that attempt to create individual contact with two chained websites succeeds
645 */
646 function testCreateIndividualWithContributionDottedSyntax() {
647 $description = "test demonstrates the syntax to create 2 chained entities";
648 $subfile = "ChainTwoWebsites";
649 $params = array(
650 'first_name' => 'abc3',
651 'last_name' => 'xyz3',
652 'contact_type' => 'Individual',
653 'email' => 'man3@yahoo.com',
654 'api.contribution.create' => array(
655 'receive_date' => '2010-01-01',
656 'total_amount' => 100.00,
657 'financial_type_id' => $this->_financialTypeId,
658 'payment_instrument_id' => 1,
659 'non_deductible_amount' => 10.00,
660 'fee_amount' => 50.00,
661 'net_amount' => 90.00,
662 'trxn_id' => 15345,
663 'invoice_id' => 67990,
664 'source' => 'SSF',
665 'contribution_status_id' => 1,
666 ),
667 'api.website.create' => array(
668 'url' => "http://civicrm.org",
669 ),
670 'api.website.create.2' => array(
671 'url' => "http://chained.org",
672 ),
673 );
674
675 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__, $description, $subfile);
676
677 $this->assertEquals(1, $result['id'], "In line " . __LINE__);
678 // checking child function result not covered in callAPIAndDocument
679 $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
680 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url'], "In line " . __LINE__);
681 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url'], "In line " . __LINE__);
682
683 // delete the contact
684 $this->callAPISuccess('contact', 'delete', $result);
685 }
686
687 /**
688 * Verify that attempt to create individual contact with chained contribution and website succeeds
689 */
690 function testCreateIndividualWithContributionChainedArrays() {
691 $params = array(
692 'first_name' => 'abc3',
693 'last_name' => 'xyz3',
694 'contact_type' => 'Individual',
695 'email' => 'man3@yahoo.com',
696 'api.contribution.create' => array(
697 'receive_date' => '2010-01-01',
698 'total_amount' => 100.00,
699 'financial_type_id' => $this->_financialTypeId,
700 'payment_instrument_id' => 1,
701 'non_deductible_amount' => 10.00,
702 'fee_amount' => 50.00,
703 'net_amount' => 90.00,
704 'trxn_id' => 12345,
705 'invoice_id' => 67890,
706 'source' => 'SSF',
707 'contribution_status_id' => 1,
708 ),
709 'api.website.create' => array(
710 array(
711 'url' => "http://civicrm.org",
712 ),
713 array(
714 'url' => "http://chained.org",
715 'website_type_id' => 2,
716 ),
717 ),
718 );
719
720 $description = "demonstrates creating two websites as an array";
721 $subfile = "ChainTwoWebsitesSyntax2";
722 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__, $description, $subfile);
723
724 $this->assertEquals(1, $result['id']);
725 // the callAndDocument doesn't check the chained call
726 $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error'], "In line " . __LINE__);
727 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url'], "In line " . __LINE__);
728 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url'], "In line " . __LINE__);
729
730 $this->callAPISuccess('contact', 'delete', $result);
731 }
732
733 /**
734 * Verify that attempt to create individual contact with first
735 * and last names and email succeeds
736 */
737 function testCreateIndividualWithNameEmail() {
738 $params = array(
739 'first_name' => 'abc3',
740 'last_name' => 'xyz3',
741 'contact_type' => 'Individual',
742 'email' => 'man3@yahoo.com',
743 );
744
745 $contact = $this->callAPISuccess('contact', 'create', $params);
746 $this->assertEquals(1, $contact['id'], "In line " . __LINE__);
747
748 // delete the contact
749 $this->callAPISuccess('contact', 'delete', $contact);
750 }
751 /**
752 * Verify that attempt to create individual contact with no data fails
753 */
754 function testCreateIndividualWithOutNameEmail() {
755 $params = array(
756 'contact_type' => 'Individual',
757 );
758
759 $result = $this->callAPIFailure('contact', 'create', $params);
760 }
761 /**
762 * Verify that attempt to create individual contact with first
763 * and last names, email and location type succeeds
764 */
765 function testCreateIndividualWithNameEmailLocationType() {
766 $params = array(
767 'first_name' => 'abc4',
768 'last_name' => 'xyz4',
769 'email' => 'man4@yahoo.com',
770 'contact_type' => 'Individual',
771 'location_type_id' => 1,
772 );
773 $result = $this->callAPISuccess('contact', 'create', $params);
774
775 $this->assertEquals(1, $result['id'], "In line " . __LINE__);
776
777 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
778 }
779
780 /**
781 * Verify that when changing employers
782 * the old employer relationship becomes inactive
783 */
784 function testCreateIndividualWithEmployer() {
785 $employer = $this->organizationCreate();
786 $employer2 = $this->organizationCreate();
787
788 $params = array(
789 'email' => 'man4@yahoo.com',
790 'contact_type' => 'Individual',
791 'employer_id' => $employer,
792 );
793
794 $result = $this->callAPISuccess('contact', 'create', $params);
795 $relationships = $this->callAPISuccess('relationship', 'get', array(
796 'contact_id_a' => $result['id'],
797 'sequential' => 1,
798 ));
799
800 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
801
802 // Add more random relationships to make the test more realistic
803 foreach (array('Employee of', 'Volunteer for') as $rtype) {
804 $relTypeId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', $rtype, 'id', 'name_a_b');
805 $random_rel = $this->callAPISuccess('relationship', 'create', array(
806 'contact_id_a' => $result['id'],
807 'contact_id_b' => $this->organizationCreate(),
808 'is_active' => 1,
809 'relationship_type_id' => $relTypeId,
810 ));
811 }
812
813 // Add second employer
814 $params['employer_id'] = $employer2;
815 $params['id'] = $result['id'];
816 $result = $this->callAPISuccess('contact', 'create', $params);
817
818 $relationships = $this->callAPISuccess('relationship', 'get', array(
819 'contact_id_a' => $result['id'],
820 'sequential' => 1,
821 'is_active' => 0,
822 ));
823
824 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
825 }
826
827 /**
828 * Verify that attempt to create household contact with details
829 * succeeds
830 */
831 function testCreateHouseholdDetails() {
832 $params = array(
833 'household_name' => 'abc8\'s House',
834 'nick_name' => 'x House',
835 'email' => 'man8@yahoo.com',
836 'contact_type' => 'Household',
837 );
838
839 $contact = $this->callAPISuccess('contact', 'create', $params);
840
841 $this->assertEquals(1, $contact['id'], "In line " . __LINE__);
842
843 $this->callAPISuccess('contact', 'delete', $contact);
844 }
845 /**
846 * Verify that attempt to create household contact with inadequate details
847 * fails
848 */
849 function testCreateHouseholdInadequateDetails() {
850 $params = array(
851 'nick_name' => 'x House',
852 'email' => 'man8@yahoo.com',
853 'contact_type' => 'Household',
854 );
855
856 $result = $this->callAPIFailure('contact', 'create', $params);
857 }
858
859 /**
860 * Verify successful update of individual contact
861 */
862 function testUpdateIndividualWithAll() {
863 // Insert a row in civicrm_contact creating individual contact
864 $op = new PHPUnit_Extensions_Database_Operation_Insert();
865 $op->execute($this->_dbconn,
866 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
867 dirname(__FILE__) . '/dataset/contact_ind.xml'
868 )
869 );
870
871 $params = array(
872 'id' => 23,
873 'first_name' => 'abcd',
874 'contact_type' => 'Individual',
875 'nick_name' => 'This is nickname first',
876 'do_not_email' => '1',
877 'do_not_phone' => '1',
878 'do_not_mail' => '1',
879 'do_not_trade' => '1',
880 'legal_identifier' => 'ABC23853ZZ2235',
881 'external_identifier' => '1928837465',
882 'image_URL' => 'http://some.url.com/image.jpg',
883 'home_url' => 'http://www.example.org',
884
885 );
886 $getResult = $this->callAPISuccess('Contact', 'Get', array());
887 $result = $this->callAPISuccess('Contact', 'Update', $params);
888 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
889 unset($params['contact_id']);
890 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
891 //reducing this test partially back to apiv2 level to get it through
892 unset($params['home_url']);
893 foreach ($params as $key => $value) {
894 $this->assertEquals($value, $result['values'][23][$key], "In line " . __LINE__);
895 }
896 // Check updated civicrm_contact against expected
897 $expected = new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
898 dirname(__FILE__) . '/dataset/contact_ind_upd.xml'
899 );
900 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataset(
901 $this->_dbconn
902 );
903 $actual->addTable('civicrm_contact');
904 $expected->matches($actual);
905 }
906
907 /**
908 * Verify successful update of organization contact
909 */
910 function testUpdateOrganizationWithAll() {
911 // Insert a row in civicrm_contact creating organization contact
912 $op = new PHPUnit_Extensions_Database_Operation_Insert();
913 $op->execute($this->_dbconn,
914 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
915 dirname(__FILE__) . '/dataset/contact_org.xml'
916 )
917 );
918
919 $params = array(
920 'id' => 24,
921 'organization_name' => 'WebAccess India Pvt Ltd',
922 'legal_name' => 'WebAccess',
923 'sic_code' => 'ABC12DEF',
924 'contact_type' => 'Organization',
925 );
926
927 $result = $this->callAPISuccess('Contact', 'Update', $params);
928
929 // Check updated civicrm_contact against expected
930 $expected = new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
931 dirname(__FILE__) . '/dataset/contact_org_upd.xml'
932 );
933 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataset(
934 $this->_dbconn
935 );
936 $actual->addTable('civicrm_contact');
937 $expected->matches($actual);
938 }
939
940 /**
941 * Verify successful update of household contact
942 */
943 function testUpdateHouseholdwithAll() {
944 // Insert a row in civicrm_contact creating household 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_hld.xml'
949 )
950 );
951
952 $params = array(
953 'id' => 25,
954 'household_name' => 'ABC household',
955 'nick_name' => 'ABC House',
956 'contact_type' => 'Household',
957 );
958
959 $result = $this->callAPISuccess('Contact', 'Update', $params);
960
961 // Check updated civicrm_contact against expected
962 $expected = new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
963 dirname(__FILE__) . '/dataset/contact_hld_upd.xml'
964 );
965 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataset(
966 $this->_dbconn
967 );
968 $actual->addTable('civicrm_contact');
969 $expected->matches($actual);
970 }
971
972 /**
973 * Test civicrm_update() Deliberately exclude contact_type as it should still
974 * cope using civicrm_api CRM-7645
975 */
976
977 public function testUpdateCreateWithID() {
978 // Insert a row in civicrm_contact creating individual contact
979 $op = new PHPUnit_Extensions_Database_Operation_Insert();
980 $op->execute($this->_dbconn,
981 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
982 dirname(__FILE__) . '/dataset/contact_ind.xml'
983 )
984 );
985
986
987
988 $params = array(
989 'id' => 23,
990 'first_name' => 'abcd',
991 'last_name' => 'wxyz',
992 );
993
994 $result = $this->callAPISuccess('Contact', 'Update', $params);
995 }
996
997 /**
998 * Test civicrm_contact_delete() with no contact ID
999 */
1000 function testContactDeleteNoID() {
1001 $params = array(
1002 'foo' => 'bar',
1003 );
1004 $result = $this->callAPIFailure('contact', 'delete', $params);
1005 }
1006
1007 /**
1008 * Test civicrm_contact_delete() with error
1009 */
1010 function testContactDeleteError() {
1011 $params = array('contact_id' => 999);
1012 $result = $this->callAPIFailure('contact', 'delete', $params);
1013 }
1014
1015 /**
1016 * Test civicrm_contact_delete()
1017 */
1018 function testContactDelete() {
1019 $contactID = $this->individualCreate();
1020 $params = array(
1021 'id' => $contactID ,
1022 );
1023 $result = $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__, __FILE__);
1024 }
1025
1026 /**
1027 * Test civicrm_contact_get() return only first name
1028 */
1029 public function testContactGetRetFirst() {
1030 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
1031 $params = array(
1032 'contact_id' => $contact['id'],
1033 'return_first_name' => TRUE,
1034 'sort' => 'first_name',
1035 );
1036 $result = $this->callAPISuccess('contact', 'get', $params);
1037 $this->assertEquals(1, $result['count'], "In line " . __LINE__);
1038 $this->assertEquals($contact['id'], $result['id'], "In line " . __LINE__);
1039 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name'], "In line " . __LINE__);
1040 }
1041
1042 /**
1043 * Test civicrm_contact_get() return only first name & last name
1044 * Use comma separated string return with a space
1045 */
1046 public function testContactGetRetFirstLast() {
1047 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
1048 $params = array(
1049 'contact_id' => $contact['id'],
1050 'return' => 'first_name, last_name',
1051 );
1052 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1053 $this->assertEquals('abc1', $result['first_name'], "In line " . __LINE__);
1054 $this->assertEquals('xyz1', $result['last_name'], "In line " . __LINE__);
1055 //check that other defaults not returns
1056 $this->assertArrayNotHasKey('sort_name', $result);
1057 $params = array(
1058 'contact_id' => $contact['id'],
1059 'return' => 'first_name,last_name',
1060 );
1061 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1062 $this->assertEquals('abc1', $result['first_name'], "In line " . __LINE__);
1063 $this->assertEquals('xyz1', $result['last_name'], "In line " . __LINE__);
1064 //check that other defaults not returns
1065 $this->assertArrayNotHasKey('sort_name', $result);
1066 }
1067
1068 /**
1069 * Test civicrm_contact_get() return only first name & last name
1070 * Use comma separated string return without a space
1071 */
1072 public function testContactGetRetFirstLastNoComma() {
1073 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
1074 $params = array(
1075 'contact_id' => $contact['id'],
1076 'return' => 'first_name,last_name',
1077 );
1078 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1079 $this->assertEquals('abc1', $result['first_name'], "In line " . __LINE__);
1080 $this->assertEquals('xyz1', $result['last_name'], "In line " . __LINE__);
1081 //check that other defaults not returns
1082 $this->assertArrayNotHasKey('sort_name', $result);
1083 }
1084
1085 /**
1086 * Test civicrm_contact_get() with default return properties
1087 */
1088 public function testContactGetRetDefault() {
1089 // Insert a row in civicrm_contact creating contact 17
1090 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1091 $op->execute($this->_dbconn,
1092 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
1093 dirname(__FILE__) . '/dataset/contact_17.xml'
1094 )
1095 );
1096 $params = array(
1097 'contact_id' => 17,
1098 'sort' => 'first_name',
1099 );
1100 $result = $this->callAPISuccess('contact', 'get', $params);
1101 $this->assertEquals(17, $result['values'][17]['contact_id'], "In line " . __LINE__);
1102 $this->assertEquals('Test', $result['values'][17]['first_name'], "In line " . __LINE__);
1103 }
1104
1105 /**
1106 * Test civicrm_contact_quicksearch() with empty name param
1107 */
1108 public function testContactGetQuickEmpty() {
1109 $result = $this->callAPIFailure('contact', 'getquick', array());
1110 }
1111
1112 /**
1113 * Test civicrm_contact_quicksearch() with empty name param
1114 */
1115 public function testContactGetQuick() {
1116 // Insert a row in civicrm_contact creating individual contact
1117 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1118 $op->execute($this->_dbconn,
1119 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
1120 dirname(__FILE__) . '/dataset/contact_17.xml'
1121 )
1122 );
1123 $op->execute($this->_dbconn,
1124 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
1125 dirname(__FILE__) . '/dataset/email_contact_17.xml'
1126 )
1127 );
1128 $params = array(
1129 'name' => "T",
1130 );
1131
1132 $result = $this->callAPISuccess('contact', 'quicksearch', $params);
1133 $this->assertEquals(17, $result['values'][0]['id'], 'in line ' . __LINE__);
1134 }
1135
1136 /**
1137 * Test civicrm_contact_get) with empty params
1138 */
1139 public function testContactGetEmptyParams() {
1140 $result = $this->callAPISuccess('contact', 'get', array());
1141 }
1142
1143 /**
1144 * Test civicrm_contact_get(,true) with no matches
1145 */
1146 public function testContactGetOldParamsNoMatches() {
1147 // Insert a row in civicrm_contact creating contact 17
1148 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1149 $op->execute($this->_dbconn,
1150 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
1151 dirname(__FILE__) . '/dataset/contact_17.xml'
1152 )
1153 );
1154
1155 $params = array(
1156 'first_name' => 'Fred',
1157 );
1158 $result = $this->callAPISuccess('contact', 'get', $params);
1159 $this->assertEquals(0, $result['count'], 'in line ' . __LINE__);
1160 }
1161
1162 /**
1163 * Test civicrm_contact_get(,true) with one match
1164 */
1165 public function testContactGetOldParamsOneMatch() {
1166 // Insert a row in civicrm_contact creating contact 17
1167 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1168 $op->execute($this->_dbconn,
1169 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(dirname(__FILE__) . '/dataset/contact_17.xml'
1170 )
1171 );
1172
1173 $params = array(
1174 'first_name' => 'Test',
1175 );
1176 $result = $this->callAPISuccess('contact', 'get', $params);
1177 $this->assertEquals(17, $result['values'][17]['contact_id'], 'in line ' . __LINE__);
1178 $this->assertEquals(17, $result['id'], 'in line ' . __LINE__);
1179 }
1180
1181 /**
1182 * Test civicrm_contact_search_count()
1183 */
1184 public function testContactGetEmail() {
1185 $params = array(
1186 'email' => 'man2@yahoo.com',
1187 'contact_type' => 'Individual',
1188 'location_type_id' => 1,
1189 );
1190
1191 $contact = $this->callAPISuccess('contact', 'create', $params);
1192
1193 $this->assertEquals(1, $contact['id'], "In line " . __LINE__);
1194
1195 $params = array(
1196 'email' => 'man2@yahoo.com',
1197 );
1198 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__);
1199 $this->assertEquals(1, $result['values'][1]['contact_id'], "In line " . __LINE__);
1200 $this->assertEquals('man2@yahoo.com', $result['values'][1]['email'], "In line " . __LINE__);
1201
1202 // delete the contact
1203 $this->callAPISuccess('contact', 'delete', $contact);
1204 }
1205
1206 /**
1207 * Test for Contact.get id=@user:username
1208 */
1209 function testContactGetByUsername() {
1210 // setup - create contact with a uf-match
1211 $cid = $this->individualCreate(array(
1212 'contact_type' => 'Individual',
1213 'first_name' => 'testGetByUsername',
1214 'last_name' => 'testGetByUsername',
1215 ));
1216
1217 $ufMatchParams = array(
1218 'domain_id' => CRM_Core_Config::domainID(),
1219 'uf_id' => 99,
1220 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
1221 'contact_id' => $cid,
1222 );
1223 $ufMatch = CRM_Core_BAO_UFMatch::create($ufMatchParams);
1224 $this->assertTrue(is_numeric($ufMatch->id));
1225
1226 // setup - mock the calls to CRM_Utils_System_*::getUfId
1227 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1228 $userSystem->expects($this->once())
1229 ->method('getUfId')
1230 ->with($this->equalTo('exampleUser'))
1231 ->will($this->returnValue(99));
1232 CRM_Core_Config::singleton()->userSystem = $userSystem;
1233
1234 // perform a lookup
1235 $result = $this->callAPISuccess('Contact', 'get', array(
1236 'id' => '@user:exampleUser',
1237 ));
1238 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
1239 }
1240
1241 /**
1242 * Test to check return works OK
1243 */
1244 function testContactGetReturnValues() {
1245 $extraParams = array('nick_name' => 'Bob', 'phone' => '456', 'email' => 'e@mail.com');
1246 $contactID = $this->individualCreate($extraParams);
1247 //actually it turns out the above doesn't create a phone
1248 $phones = $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456',));
1249 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
1250 foreach ($extraParams as $key => $value) {
1251 $this->assertEquals($result[$key], $value);
1252 }
1253 //now we check they are still returned with 'return' key
1254 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID, 'return' => array_keys($extraParams)));
1255 foreach ($extraParams as $key => $value) {
1256 $this->assertEquals($result[$key], $value);
1257 }
1258 }
1259
1260 function testCRM13252MultipleChainedPhones() {
1261 $contactID = $this->householdCreate();
1262 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
1263 $params = array(
1264 'contact_id' => $contactID,
1265 'household_name' => 'Household 1',
1266 'contact_type' => 'Household',
1267 'api.phone.create' => array(
1268 0 => array(
1269 'phone' => '111-111-1111',
1270 'location_type_id' => 1,
1271 'phone_type_id' => 1,
1272 ),
1273 1 => array(
1274 'phone' => '222-222-2222',
1275 'location_type_id' => 1,
1276 'phone_type_id' => 2,
1277 )
1278 )
1279 );
1280 $result = $this->callAPISuccess('contact', 'create', $params);
1281 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
1282
1283 }
1284 /**
1285 * Test for Contact.get id=@user:username (with an invalid username)
1286 */
1287 function testContactGetByUnknownUsername() {
1288 // setup - mock the calls to CRM_Utils_System_*::getUfId
1289 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1290 $userSystem->expects($this->once())
1291 ->method('getUfId')
1292 ->with($this->equalTo('exampleUser'))
1293 ->will($this->returnValue(NULL));
1294 CRM_Core_Config::singleton()->userSystem = $userSystem;
1295
1296 // perform a lookup
1297 $result = $this->callAPIFailure('Contact', 'get', array(
1298 'id' => '@user:exampleUser',
1299 ));
1300 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
1301 }
1302
1303 /**
1304 * Verify attempt to create individual with chained arrays
1305 */
1306 function testGetIndividualWithChainedArrays() {
1307 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
1308 $params['custom_' . $ids['custom_field_id']] = "custom string";
1309
1310 $moreids = $this->CustomGroupMultipleCreateWithFields();
1311 $description = "/*this demonstrates the usage of chained api functions. In this case no notes or custom fields have been created ";
1312 $subfile = "APIChainedArray";
1313 $params = array(
1314 'first_name' => 'abc3',
1315 'last_name' => 'xyz3',
1316 'contact_type' => 'Individual',
1317 'email' => 'man3@yahoo.com',
1318 'api.contribution.create' => array(
1319 'receive_date' => '2010-01-01',
1320 'total_amount' => 100.00,
1321 'financial_type_id' => 1,
1322 'payment_instrument_id' => 1,
1323 'non_deductible_amount' => 10.00,
1324 'fee_amount' => 50.00,
1325 'net_amount' => 90.00,
1326 'trxn_id' => 12345,
1327 'invoice_id' => 67890,
1328 'source' => 'SSF',
1329 'contribution_status_id' => 1,
1330 ),
1331 'api.contribution.create.1' => array(
1332 'receive_date' => '2011-01-01',
1333 'total_amount' => 120.00,
1334 'financial_type_id' => $this->_financialTypeId =1,
1335 'payment_instrument_id' => 1,
1336 'non_deductible_amount' => 10.00,
1337 'fee_amount' => 50.00,
1338 'net_amount' => 90.00,
1339 'trxn_id' => 12335,
1340 'invoice_id' => 67830,
1341 'source' => 'SSF',
1342 'contribution_status_id' => 1,
1343 ),
1344 'api.website.create' => array(
1345 array(
1346 'url' => "http://civicrm.org",
1347 ),
1348 ),
1349 );
1350
1351 $result = $this->callAPISuccess('Contact', 'create', $params);
1352 $params = array(
1353 'id' => $result['id'],
1354 'api.website.get' => array(),
1355 'api.Contribution.get' => array(
1356 'total_amount' => '120.00',
1357 ), 'api.CustomValue.get' => 1,
1358 'api.Note.get' => 1,
1359 );
1360 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
1361 // delete the contact
1362 $this->callAPISuccess('contact', 'delete', $result);
1363 $this->customGroupDelete($ids['custom_group_id']);
1364 $this->customGroupDelete($moreids['custom_group_id']);
1365 $this->assertEquals(1, $result['id'], "In line " . __LINE__);
1366 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error'], "In line " . __LINE__);
1367 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url'], "In line " . __LINE__);
1368 }
1369
1370 function testGetIndividualWithChainedArraysFormats() {
1371 $description = "/*this demonstrates the usage of chained api functions. A variety of return formats are used. Note that no notes
1372 *custom fields or memberships exist";
1373 $subfile = "APIChainedArrayFormats";
1374 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
1375 $params['custom_' . $ids['custom_field_id']] = "custom string";
1376
1377 $moreids = $this->CustomGroupMultipleCreateWithFields();
1378 $params = array(
1379 'first_name' => 'abc3',
1380 'last_name' => 'xyz3',
1381 'contact_type' => 'Individual',
1382 'email' => 'man3@yahoo.com',
1383 'api.contribution.create' => array(
1384 'receive_date' => '2010-01-01',
1385 'total_amount' => 100.00,
1386 'financial_type_id' => $this->_financialTypeId,
1387 'payment_instrument_id' => 1,
1388 'non_deductible_amount' => 10.00,
1389 'fee_amount' => 50.00,
1390 'net_amount' => 90.00,
1391 'source' => 'SSF',
1392 'contribution_status_id' => 1,
1393 ),
1394 'api.contribution.create.1' => array(
1395 'receive_date' => '2011-01-01',
1396 'total_amount' => 120.00,
1397 'financial_type_id' => $this->_financialTypeId,
1398 'payment_instrument_id' => 1,
1399 'non_deductible_amount' => 10.00,
1400 'fee_amount' => 50.00,
1401 'net_amount' => 90.00,
1402 'source' => 'SSF',
1403 'contribution_status_id' => 1,
1404 ),
1405 'api.website.create' => array(
1406 array(
1407 'url' => "http://civicrm.org",
1408 ),
1409 ),
1410 );
1411
1412
1413 $result = $this->callAPISuccess('Contact', 'create', $params);
1414 $params = array(
1415 'id' => $result['id'],
1416 'api.website.getValue' => array('return' => 'url'),
1417 'api.Contribution.getCount' => array(),
1418 'api.CustomValue.get' => 1,
1419 'api.Note.get' => 1,
1420 'api.Membership.getCount' => array(),
1421 );
1422 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
1423 $this->assertEquals(1, $result['id'], "In line " . __LINE__);
1424 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount'], "In line " . __LINE__);
1425 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error'], "In line " . __LINE__);
1426 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue'], "In line " . __LINE__);
1427
1428 $this->callAPISuccess('contact', 'delete', $result);
1429 $this->customGroupDelete($ids['custom_group_id']);
1430 $this->customGroupDelete($moreids['custom_group_id']);
1431 }
1432
1433 function testGetIndividualWithChainedArraysAndMultipleCustom() {
1434 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
1435 $params['custom_' . $ids['custom_field_id']] = "custom string";
1436 $moreids = $this->CustomGroupMultipleCreateWithFields();
1437 $andmoreids = $this->CustomGroupMultipleCreateWithFields(array('title' => "another group", 'name' => 'another name'));
1438 $description = "/*this demonstrates the usage of chained api functions. A variety of techniques are used";
1439 $subfile = "APIChainedArrayMultipleCustom";
1440 $params = array(
1441 'first_name' => 'abc3',
1442 'last_name' => 'xyz3',
1443 'contact_type' => 'Individual',
1444 'email' => 'man3@yahoo.com',
1445 'api.contribution.create' => array(
1446 'receive_date' => '2010-01-01',
1447 'total_amount' => 100.00,
1448 'financial_type_id' => 1,
1449 'payment_instrument_id' => 1,
1450 'non_deductible_amount' => 10.00,
1451 'fee_amount' => 50.00,
1452 'net_amount' => 90.00,
1453 'trxn_id' => 12345,
1454 'invoice_id' => 67890,
1455 'source' => 'SSF',
1456 'contribution_status_id' => 1,
1457 ),
1458 'api.contribution.create.1' => array(
1459 'receive_date' => '2011-01-01',
1460 'total_amount' => 120.00,
1461 'financial_type_id' => 1,
1462 'payment_instrument_id' => 1,
1463 'non_deductible_amount' => 10.00,
1464 'fee_amount' => 50.00,
1465 'net_amount' => 90.00,
1466 'trxn_id' => 12335,
1467 'invoice_id' => 67830,
1468 'source' => 'SSF',
1469 'contribution_status_id' => 1,
1470 ),
1471 'api.website.create' => array(
1472 array(
1473 'url' => "http://civicrm.org",
1474 ),
1475 ),
1476 'custom_' . $ids['custom_field_id'] => "value 1",
1477 'custom_' . $moreids['custom_field_id'][0] => "value 2",
1478 'custom_' . $moreids['custom_field_id'][1] => "warm beer",
1479 'custom_' . $andmoreids['custom_field_id'][1] => "vegemite",
1480 );
1481
1482
1483 $result = $this->callAPISuccess('Contact', 'create', $params);
1484 $result = $this->callAPISuccess('Contact', 'create', array(
1485 'contact_type' => 'Individual', 'id' => $result['id'], 'custom_' . $moreids['custom_field_id'][0] => "value 3", 'custom_' . $ids['custom_field_id'] => "value 4",
1486 ));
1487
1488 $params = array(
1489 'id' => $result['id'],
1490 'api.website.getValue' => array('return' => 'url'),
1491 'api.Contribution.getCount' => array(),
1492 'api.CustomValue.get' => 1,
1493 );
1494 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
1495
1496 $this->customGroupDelete($ids['custom_group_id']);
1497 $this->customGroupDelete($moreids['custom_group_id']);
1498 $this->customGroupDelete($andmoreids['custom_group_id']);
1499 $this->assertEquals(1, $result['id'], "In line " . __LINE__);
1500 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error'], "In line " . __LINE__);
1501 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue'], "In line " . __LINE__);
1502 }
1503 /*
1504 * Test checks siusage of $values to pick & choose inputs
1505 */
1506 function testChainingValuesCreate() {
1507 $description = "/*this demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
1508 2 child functions - one receives values from the parent (Contact) and the other child (Tag). ";
1509 $subfile = "APIChainedArrayValuesFromSiblingFunction";
1510 $params = array(
1511 'display_name' => 'batman', 'contact_type' => 'Individual',
1512 'api.tag.create' => array('name' => '$value.id', 'description' => '$value.display_name', 'format.only_id' => 1),
1513 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
1514 );
1515 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__, __FILE__, $description, $subfile);
1516 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
1517
1518 $tablesToTruncate = array(
1519 'civicrm_contact',
1520 'civicrm_activity',
1521 'civicrm_entity_tag',
1522 'civicrm_tag',
1523 );
1524 $this->quickCleanup($tablesToTruncate, TRUE);
1525 }
1526
1527 /*
1528 * test TrueFalse format - I couldn't come up with an easy way to get an error on Get
1529 */
1530 function testContactGetFormatIsSuccessTrue() {
1531 $this->createContactFromXML();
1532 $description = "This demonstrates use of the 'format.is_success' param.
1533 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1534 $subfile = "FormatIsSuccess_True";
1535 $params = array('id' => 17, 'format.is_success' => 1);
1536 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
1537 $this->assertEquals(1, $result);
1538 $this->callAPISuccess('Contact', 'Delete', $params);
1539 }
1540 /*
1541 * test TrueFalse format
1542 */
1543 function testContactCreateFormatIsSuccessFalse() {
1544
1545 $description = "This demonstrates use of the 'format.is_success' param.
1546 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1547 $subfile = "FormatIsSuccess_Fail";
1548 $params = array('id' => 500, 'format.is_success' => 1);
1549 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__, __FILE__, $description, $subfile);
1550 $this->assertEquals(0, $result);
1551 }
1552 /*
1553 * test Single Entity format
1554 */
1555 function testContactGetSingle_entity_array() {
1556 $this->createContactFromXML();
1557 $description = "This demonstrates use of the 'format.single_entity_array' param.
1558 /* This param causes the only contact to be returned as an array without the other levels.
1559 /* it will be ignored if there is not exactly 1 result";
1560 $subfile = "GetSingleContact";
1561 $params = array('id' => 17);
1562 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__, __FILE__, $description, $subfile);
1563 $this->assertEquals('Test Contact', $result['display_name'], "in line " . __LINE__);
1564 $this->callAPISuccess('Contact', 'Delete', $params);
1565 }
1566
1567 /*
1568 * test Single Entity format
1569 */
1570 function testContactGetFormatcount_only() {
1571 $this->createContactFromXML();
1572 $description = "/*This demonstrates use of the 'getCount' action
1573 /* This param causes the count of the only function to be returned as an integer";
1574 $subfile = "GetCountContact";
1575 $params = array('id' => 17);
1576 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__, __FILE__, $description, $subfile);
1577 $this->assertEquals('1', $result, "in line " . __LINE__);
1578 $this->callAPISuccess('Contact', 'Delete', $params);
1579 }
1580 /*
1581 * Test id only format
1582 */
1583 function testContactGetFormatID_only() {
1584 $this->createContactFromXML();
1585 $description = "This demonstrates use of the 'format.id_only' param.
1586 /* This param causes the id of the only entity to be returned as an integer.
1587 /* it will be ignored if there is not exactly 1 result";
1588 $subfile = "FormatOnlyID";
1589 $params = array('id' => 17, 'format.only_id' => 1);
1590 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
1591 $this->assertEquals('17', $result, "in line " . __LINE__);
1592 $this->callAPISuccess('Contact', 'Delete', $params);
1593 }
1594
1595 /*
1596 * Test id only format
1597 */
1598 function testContactGetFormatSingleValue() {
1599 $this->createContactFromXML();
1600 $description = "This demonstrates use of the 'format.single_value' param.
1601 /* This param causes only a single value of the only entity to be returned as an string.
1602 /* it will be ignored if there is not exactly 1 result";
1603 $subfile = "FormatSingleValue";
1604 $params = array('id' => 17, 'return' => 'display_name');
1605 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__, __FILE__, $description, $subfile,'getvalue');
1606 $this->assertEquals('Test Contact', $result, "in line " . __LINE__);
1607 $this->callAPISuccess('Contact', 'Delete', $params);
1608 }
1609
1610 function testContactCreationPermissions() {
1611 $params = array(
1612 'contact_type' => 'Individual', 'first_name' => 'Foo',
1613 'last_name' => 'Bear',
1614 'check_permissions' => TRUE,
1615 );
1616 $config = CRM_Core_Config::singleton();
1617 $config->userPermissionClass->permissions = array('access CiviCRM');
1618 $result = $this->callAPIFailure('contact', 'create', $params);
1619 $this->assertEquals('API permission check failed for contact/create call; insufficient permission: require access CiviCRM and add contacts', $result['error_message'], 'lacking permissions should not be enough to create a contact');
1620
1621 $config->userPermissionClass->permissions = array('access CiviCRM', 'add contacts', 'import contacts');
1622 $result = $this->callAPISuccess('contact', 'create', $params, NULL, 'overfluous permissions should be enough to create a contact');
1623 }
1624
1625 function testContactUpdatePermissions() {
1626 $params = array('contact_type' => 'Individual', 'first_name' => 'Foo', 'last_name' => 'Bear', 'check_permissions' => TRUE,);
1627 $result = $this->callAPISuccess('contact', 'create', $params);
1628 $config = CRM_Core_Config::singleton();
1629 $params = array('id' => $result['id'], 'contact_type' => 'Individual', 'last_name' => 'Bar', 'check_permissions' => TRUE,);
1630
1631 $config->userPermissionClass->permissions = array('access CiviCRM');
1632 $result = $this->callAPIFailure('contact', 'update', $params);
1633 $this->assertEquals('API permission check failed for contact/update call; insufficient permission: require access CiviCRM and edit all contacts', $result['error_message'], 'lacking permissions should not be enough to update a contact');
1634
1635 $config->userPermissionClass->permissions = array('access CiviCRM', 'add contacts', 'view all contacts', 'edit all contacts', 'import contacts');
1636 $result = $this->callAPISuccess('contact', 'update', $params, NULL, 'overfluous permissions should be enough to update a contact');
1637 }
1638
1639 function createContactFromXML() {
1640 // Insert a row in civicrm_contact creating contact 17
1641 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1642 $op->execute($this->_dbconn,
1643 new PHPUnit_Extensions_Database_DataSet_XMLDataSet(
1644 dirname(__FILE__) . '/dataset/contact_17.xml'
1645 )
1646 );
1647 }
1648
1649 function testContactProximity() {
1650 // first create a contact with a SF location with a specific
1651 // geocode
1652 $contactID = $this->organizationCreate();
1653
1654 // now create the address
1655 $params = array(
1656 'street_address' => '123 Main Street',
1657 'city' => 'San Francisco',
1658 'is_primary' => 1,
1659 'country_id' => 1228,
1660 'state_province_id' => 1004,
1661 'geo_code_1' => '37.79',
1662 'geo_code_2' => '-122.40',
1663 'location_type_id' => 1,
1664 'contact_id' => $contactID,
1665 );
1666
1667 $result = $this->callAPISuccess('address', 'create', $params);
1668 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__);
1669
1670 // now do a proximity search with a close enough geocode and hope to match
1671 // that specific contact only!
1672 $proxParams = array(
1673 'latitude' => 37.7,
1674 'longitude' => -122.3,
1675 'unit' => 'mile',
1676 'distance' => 10,
1677 );
1678 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
1679 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__);
1680 }
1681
1682 /**
1683 * Test that Ajax API permission is suffient to access quicksearch api
1684 * (note that quicksearch api is required for autocomplete & has ACL permissions applied)
1685 */
1686 function testQuickSearchPermission_CRM_13744() {
1687 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviEvent');
1688 $result = $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1689 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM');
1690 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1691 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access AJAX API');
1692 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1693 }
1694 }