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