Merge pull request #9783 from mattwire/back_to_single_lang
[civicrm-core.git] / tests / phpunit / api / v3 / CaseTest.php
1 <?php
2 /**
3 * @file
4 * File for the TestCase 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: ActivityTest.php 31254 2010-12-15 10:09:29Z eileen $
13 * @package CiviCRM
14 *
15 * This file is part of CiviCRM
16 *
17 * CiviCRM is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Affero General Public License
19 * as published by the Free Software Foundation; either version 3 of
20 * the License, or (at your option) any later version.
21 *
22 * CiviCRM is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU Affero General Public License for more details.
26 *
27 * You should have received a copy of the GNU Affero General Public
28 * License along with this program. If not, see
29 * <http://www.gnu.org/licenses/>.
30 */
31
32 /**
33 * Include class definitions
34 */
35
36 /**
37 * Test APIv3 civicrm_case_* functions
38 *
39 * @package CiviCRM_APIv3
40 * @group headless
41 */
42 class api_v3_CaseTest extends CiviCaseTestCase {
43 protected $_params;
44 protected $_entity;
45 protected $_apiversion = 3;
46 protected $followup_activity_type_value;
47 /**
48 * Activity ID of created case.
49 *
50 * @var int
51 */
52 protected $_caseActivityId;
53
54 /**
55 * @var \Civi\Core\SettingsStack
56 */
57 protected $settingsStack;
58
59 /**
60 * Test setup for every test.
61 *
62 * Connect to the database, truncate the tables that will be used
63 * and redirect stdin to a temporary file.
64 */
65 public function setUp() {
66 $this->_entity = 'case';
67
68 parent::setUp();
69
70 $activityTypes = $this->callAPISuccess('option_value', 'get', array(
71 'option_group_id' => 2,
72 'name' => 'Follow Up',
73 'label' => 'Follow Up',
74 'sequential' => 1,
75 ));
76 $this->followup_activity_type_value = $activityTypes['values'][0]['value'];
77
78 $this->_params = array(
79 'case_type_id' => $this->caseTypeId,
80 'subject' => 'Test case',
81 'contact_id' => 17,
82 );
83
84 $this->settingsStack = new \Civi\Core\SettingsStack();
85 }
86
87 public function tearDown() {
88 $this->settingsStack->popAll();
89 parent::tearDown();
90 }
91
92 /**
93 * Check with empty array.
94 */
95 public function testCaseCreateEmpty() {
96 $this->callAPIFailure('case', 'create', array());
97 }
98
99 /**
100 * Check if required fields are not passed.
101 */
102 public function testCaseCreateWithoutRequired() {
103 $params = array(
104 'subject' => 'this case should fail',
105 'case_type_id' => 1,
106 );
107
108 $this->callAPIFailure('case', 'create', $params);
109 }
110
111 /**
112 * Test Getlist with id and case_id
113 */
114 public function testCaseGetListById() {
115 $params = $this->_params;
116 $params['contact_id'] = $this->individualCreate();
117
118 //Create 3 sample Cases.
119 $case1 = $this->callAPISuccess('case', 'create', $params);
120 $params['subject'] = 'Test Case 2';
121 $case2 = $this->callAPISuccess('case', 'create', $params);
122 $params['subject'] = 'Test Case 3';
123 $case3 = $this->callAPISuccess('case', 'create', $params);
124
125 $getParams = array(
126 'id' => array($case1['id']),
127 'extra' => array('contact_id'),
128 'params' => array(
129 'version' => 3,
130 'case_id' => array('!=' => $case2['id']),
131 'case_id.is_deleted' => 0,
132 'case_id.status_id' => array('!=' => "Closed"),
133 'case_id.end_date' => array('IS NULL' => 1),
134 ),
135 );
136 $result = $this->callAPISuccess('case', 'getlist', $getParams);
137
138 //Only 1 case should be returned.
139 $this->assertEquals(count($result['values']), 1);
140 $this->assertEquals($result['values'][0]['id'], $case1['id']);
141 }
142
143 /**
144 * Test create function with valid parameters.
145 */
146 public function testCaseCreate() {
147 $params = $this->_params;
148 // Test using label instead of value.
149 unset($params['case_type_id']);
150 $params['case_type'] = $this->caseType;
151 $result = $this->callAPIAndDocument('case', 'create', $params, __FUNCTION__, __FILE__);
152 $id = $result['id'];
153
154 // Check result
155 $result = $this->callAPISuccess('case', 'get', array('id' => $id));
156 $this->assertEquals($result['values'][$id]['id'], $id);
157 $this->assertEquals($result['values'][$id]['case_type_id'], $this->caseTypeId);
158 $this->assertEquals($result['values'][$id]['subject'], $params['subject']);
159 }
160
161 /**
162 * Test case create with valid parameters and custom data.
163 */
164 public function testCaseCreateCustom() {
165 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
166 $params = $this->_params;
167 $params['custom_' . $ids['custom_field_id']] = "custom string";
168 $result = $this->callAPIAndDocument($this->_entity, 'create', $params, __FUNCTION__, __FILE__);
169 $result = $this->callAPISuccess($this->_entity, 'get', array(
170 'return.custom_' . $ids['custom_field_id'] => 1,
171 'id' => $result['id'],
172 ));
173 $this->assertEquals("custom string", $result['values'][$result['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
174
175 $this->customFieldDelete($ids['custom_field_id']);
176 $this->customGroupDelete($ids['custom_group_id']);
177 }
178
179 /**
180 * Test update (create with id) function with valid parameters.
181 */
182 public function testCaseUpdate() {
183 $params = $this->_params;
184 // Test using name instead of value
185 unset($params['case_type_id']);
186 $params['case_type'] = $this->caseType;
187 $result = $this->callAPISuccess('case', 'create', $params);
188 $id = $result['id'];
189 $case = $this->callAPISuccess('case', 'getsingle', array('id' => $id));
190
191 // Update Case.
192 $params = array('id' => $id);
193 $params['subject'] = $case['subject'] = 'Something Else';
194 $this->callAPISuccess('case', 'create', $params);
195
196 // Verify that updated case is exactly equal to the original with new subject.
197 $result = $this->callAPISuccessGetSingle('Case', array('case_id' => $id));
198 $this->assertAPIArrayComparison($result, $case);
199 }
200
201 /**
202 * Test case update with custom data
203 */
204 public function testCaseUpdateCustom() {
205 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
206 $params = $this->_params;
207
208 // Create a case with custom data
209 $params['custom_' . $ids['custom_field_id']] = 'custom string';
210 $result = $this->callAPISuccess($this->_entity, 'create', $params);
211
212 $caseId = $result['id'];
213 $result = $this->callAPISuccess($this->_entity, 'get', array(
214 'return.custom_' . $ids['custom_field_id'] => 1,
215 'version' => 3,
216 'id' => $result['id'],
217 ));
218 $this->assertEquals("custom string", $result['values'][$result['id']]['custom_' . $ids['custom_field_id']]);
219 $fields = $this->callAPISuccess($this->_entity, 'getfields', array('version' => $this->_apiversion));
220 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
221
222 // Update the activity with custom data.
223 $params = array(
224 'id' => $caseId,
225 'custom_' . $ids['custom_field_id'] => 'Updated my test data',
226 'version' => $this->_apiversion,
227 );
228 $result = $this->callAPISuccess($this->_entity, 'create', $params);
229
230 $result = $this->callAPISuccess($this->_entity, 'get', array(
231 'return.custom_' . $ids['custom_field_id'] => 1,
232 'version' => 3,
233 'id' => $result['id'],
234 ));
235 $this->assertEquals("Updated my test data", $result['values'][$result['id']]['custom_' . $ids['custom_field_id']]);
236 }
237
238 /**
239 * Test delete function with valid parameters.
240 */
241 public function testCaseDelete() {
242 // Create Case
243 $result = $this->callAPISuccess('case', 'create', $this->_params);
244
245 // Move Case to Trash
246 $id = $result['id'];
247 $this->callAPISuccess('case', 'delete', array('id' => $id, 'move_to_trash' => 1));
248
249 // Check result - also check that 'case_id' works as well as 'id'
250 $result = $this->callAPISuccess('case', 'get', array('case_id' => $id));
251 $this->assertEquals(1, $result['values'][$id]['is_deleted']);
252
253 // Restore Case from Trash
254 $this->callAPISuccess('case', 'restore', array('id' => $id));
255
256 // Check result
257 $result = $this->callAPISuccess('case', 'get', array('case_id' => $id));
258 $this->assertEquals(0, $result['values'][$id]['is_deleted']);
259
260 // Delete Case Permanently
261 $this->callAPISuccess('case', 'delete', array('case_id' => $id));
262
263 // Check result - case should no longer exist
264 $result = $this->callAPISuccess('case', 'get', array('id' => $id));
265 $this->assertEquals(0, $result['count']);
266 }
267
268 /**
269 * Test get function based on activity.
270 */
271 public function testCaseGetByActivity() {
272 // Create Case
273 $result = $this->callAPISuccess('case', 'create', $this->_params);
274 $id = $result['id'];
275
276 // Check result - we should get a list of activity ids
277 $result = $this->callAPISuccess('case', 'get', array('id' => $id, 'return' => 'activities'));
278 $case = $result['values'][$id];
279 $activity = $case['activities'][0];
280
281 // Fetch case based on an activity id
282 $result = $this->callAPISuccess('case', 'get', array(
283 'activity_id' => $activity,
284 'return' => 'activities',
285 ));
286 $this->assertEquals(FALSE, empty($result['values'][$id]));
287 $this->assertEquals($result['values'][$id], $case);
288 }
289
290 /**
291 * Test get function based on contact id.
292 */
293 public function testCaseGetByContact() {
294 // Create Case
295 $result = $this->callAPISuccess('case', 'create', $this->_params);
296 $id = $result['id'];
297
298 // Store result for later
299 $case = $this->callAPISuccessGetSingle('case', array('id' => $id, 'return' => array('activities', 'contacts')));
300
301 // Fetch case based on client contact id
302 $result = $this->callAPISuccess('case', 'get', array(
303 'client_id' => $this->_params['contact_id'],
304 'return' => array('activities', 'contacts'),
305 ));
306 $this->assertAPIArrayComparison($result['values'][$id], $case);
307 }
308
309 /**
310 * Test get function based on subject.
311 */
312 public function testCaseGetBySubject() {
313 // Create Case
314 $result = $this->callAPISuccess('case', 'create', $this->_params);
315 $id = $result['id'];
316
317 // Store result for later
318 $case = $this->callAPISuccessGetSingle('Case', array('id' => $id, 'return' => 'subject'));
319
320 // Fetch case based on client contact id
321 $result = $this->callAPISuccess('case', 'get', array(
322 'subject' => $this->_params['subject'],
323 'return' => array('subject'),
324 ));
325 $this->assertAPIArrayComparison($result['values'][$id], $case);
326 }
327
328 /**
329 * Test get function based on wrong subject.
330 */
331 public function testCaseGetByWrongSubject() {
332 $result = $this->callAPISuccess('case', 'create', $this->_params);
333
334 // Append 'wrong' to subject so that it is no longer the same.
335 $result = $this->callAPISuccess('case', 'get', array(
336 'subject' => $this->_params['subject'] . 'wrong',
337 'return' => array('activities', 'contacts'),
338 ));
339 $this->assertEquals(0, $result['count']);
340 }
341
342 /**
343 * Test get function with no criteria.
344 */
345 public function testCaseGetNoCriteria() {
346 $result = $this->callAPISuccess('case', 'create', $this->_params);
347 $id = $result['id'];
348
349 // Store result for later
350 $case = $this->callAPISuccessGetSingle('Case', array('id' => $id, 'return' => 'contact_id'));
351
352 $result = $this->callAPISuccess('case', 'get', array('limit' => 0, 'return' => array('contact_id')));
353 $this->assertAPIArrayComparison($result['values'][$id], $case);
354 }
355
356 /**
357 * Test activity api create for case activities.
358 */
359 public function testCaseActivityCreate() {
360 $params = $this->_params;
361 $case = $this->callAPISuccess('case', 'create', $params);
362 $params = array(
363 'case_id' => $case['id'],
364 // follow up
365 'activity_type_id' => $this->followup_activity_type_value,
366 'subject' => 'Test followup 123',
367 'source_contact_id' => $this->_loggedInUser,
368 'target_contact_id' => $this->_params['contact_id'],
369 );
370 $result = $this->callAPISuccess('activity', 'create', $params);
371 $this->assertEquals($result['values'][$result['id']]['activity_type_id'], $params['activity_type_id']);
372
373 // might need this for other tests that piggyback on this one
374 $this->_caseActivityId = $result['values'][$result['id']]['id'];
375
376 // Check other DB tables populated properly - is there a better way to do this? assertDBState() requires that we know the id already.
377 $dao = new CRM_Case_DAO_CaseActivity();
378 $dao->case_id = $case['id'];
379 $dao->activity_id = $this->_caseActivityId;
380 $this->assertEquals($dao->find(), 1, 'case_activity table not populated correctly in line ' . __LINE__);
381 $dao->free();
382
383 $dao = new CRM_Activity_DAO_ActivityContact();
384 $dao->activity_id = $this->_caseActivityId;
385 $dao->contact_id = $this->_params['contact_id'];
386 $dao->record_type_id = 3;
387 $this->assertEquals($dao->find(), 1, 'activity_contact table not populated correctly in line ' . __LINE__);
388 $dao->free();
389
390 // Check that fetching an activity by case id works, as well as returning case_id
391 $result = $this->callAPISuccessGetSingle('Activity', array(
392 'case_id' => $case['id'],
393 'activity_type_id' => $this->followup_activity_type_value,
394 'subject' => 'Test followup 123',
395 'return' => array('case_id'),
396 ));
397 $this->assertContains($case['id'], $result['case_id']);
398 }
399
400 /**
401 * Test activity api update for case activities.
402 */
403 public function testCaseActivityUpdate_Tracked() {
404 $this->settingsStack->push('civicaseActivityRevisions', TRUE);
405
406 // Need to create the case and activity before we can update it
407 $this->testCaseActivityCreate();
408
409 $params = array(
410 'activity_id' => $this->_caseActivityId,
411 'case_id' => 1,
412 'activity_type_id' => 14,
413 'source_contact_id' => $this->_loggedInUser,
414 'subject' => 'New subject',
415 );
416 $result = $this->callAPISuccess('activity', 'create', $params);
417
418 $this->assertEquals($result['values'][$result['id']]['subject'], $params['subject']);
419
420 // id should be one greater, since this is a new revision
421 $this->assertEquals($result['values'][$result['id']]['id'],
422 $this->_caseActivityId + 1,
423 'in line ' . __LINE__
424 );
425 $this->assertEquals($result['values'][$result['id']]['original_id'],
426 $this->_caseActivityId,
427 'in line ' . __LINE__
428 );
429
430 // Check revision is as expected
431 $revParams = array(
432 'activity_id' => $this->_caseActivityId,
433 );
434 $revActivity = $this->callAPISuccess('activity', 'get', $revParams);
435 $this->assertEquals($revActivity['values'][$this->_caseActivityId]['is_current_revision'],
436 0);
437 $this->assertEquals($revActivity['values'][$this->_caseActivityId]['is_deleted'],
438 0
439 );
440
441 //TODO: check some more things
442 }
443
444 /**
445 * If you disable `civicaseActivityRevisions`, then editing an activity
446 * will *not* create or change IDs.
447 */
448 public function testCaseActivityUpdate_Untracked() {
449 $this->settingsStack->push('civicaseActivityRevisions', FALSE);
450
451 // Need to create the case and activity before we can update it
452 $this->testCaseActivityCreate();
453
454 $oldIDs = CRM_Utils_SQL_Select::from('civicrm_activity')
455 ->select('id, original_id, is_current_revision')
456 ->orderBy('id')
457 ->execute()->fetchAll();
458
459 $params = array(
460 'activity_id' => $this->_caseActivityId,
461 'case_id' => 1,
462 'activity_type_id' => 14,
463 'source_contact_id' => $this->_loggedInUser,
464 'subject' => 'New subject',
465 );
466 $result = $this->callAPISuccess('activity', 'create', $params);
467 $this->assertEquals($result['values'][$result['id']]['subject'], $params['subject']);
468
469 // id should not change because we've opted out.
470 $this->assertEquals($this->_caseActivityId, $result['values'][$result['id']]['id']);
471 $this->assertEmpty($result['values'][$result['id']]['original_id']);
472
473 $newIDs = CRM_Utils_SQL_Select::from('civicrm_activity')
474 ->select('id, original_id, is_current_revision')
475 ->orderBy('id')
476 ->execute()->fetchAll();
477 $this->assertEquals($oldIDs, $newIDs);
478 }
479
480 public function testCaseActivityUpdateCustom() {
481 $this->settingsStack->push('civicaseActivityRevisions', TRUE);
482
483 // Create a case first
484 $result = $this->callAPISuccess('case', 'create', $this->_params);
485
486 // Create custom field group
487 // Note the second parameter is Activity on purpose, not Case.
488 $custom_ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, 'ActivityTest.php');
489
490 // create activity
491 $params = array(
492 'case_id' => $result['id'],
493 // follow up
494 'activity_type_id' => 14,
495 'subject' => 'Test followup',
496 'source_contact_id' => $this->_loggedInUser,
497 'target_contact_id' => $this->_params['contact_id'],
498 'custom_' . $custom_ids['custom_field_id'] => "custom string",
499 );
500 $result = $this->callAPISuccess('activity', 'create', $params);
501
502 $aid = $result['values'][$result['id']]['id'];
503
504 // Update activity
505 $params = array(
506 'activity_id' => $aid,
507 'case_id' => 1,
508 'activity_type_id' => 14,
509 'source_contact_id' => $this->_loggedInUser,
510 'subject' => 'New subject',
511 );
512 $this->callAPISuccess('activity', 'create', $params);
513
514 // Retrieve revision and check custom fields got copied.
515 $revParams = array(
516 'activity_id' => $aid + 1,
517 'return.custom_' . $custom_ids['custom_field_id'] => 1,
518 );
519 $revAct = $this->callAPISuccess('activity', 'get', $revParams);
520
521 $this->assertEquals($revAct['values'][$aid + 1]['custom_' . $custom_ids['custom_field_id']], "custom string",
522 "Error message: " . CRM_Utils_Array::value('error_message', $revAct));
523
524 $this->customFieldDelete($custom_ids['custom_field_id']);
525 $this->customGroupDelete($custom_ids['custom_group_id']);
526 }
527
528 public function testCaseGetByStatus() {
529 // Create 2 cases with different status ids.
530 $case1 = $this->callAPISuccess('Case', 'create', array(
531 'contact_id' => 17,
532 'subject' => "Test case 1",
533 'case_type_id' => $this->caseTypeId,
534 'status_id' => "Open",
535 'sequential' => 1,
536 ));
537 $this->callAPISuccess('Case', 'create', array(
538 'contact_id' => 17,
539 'subject' => "Test case 2",
540 'case_type_id' => $this->caseTypeId,
541 'status_id' => "Urgent",
542 'sequential' => 1,
543 ));
544 $result = $this->callAPISuccessGetSingle('Case', array(
545 'sequential' => 1,
546 'contact_id' => 17,
547 'status_id' => "Open",
548 ));
549 $this->assertEquals($case1['id'], $result['id']);
550 }
551
552 public function testCaseGetWithRoles() {
553 $case1 = $this->callAPISuccess('Case', 'create', array(
554 'contact_id' => 17,
555 'subject' => "Test case with roles",
556 'case_type_id' => $this->caseTypeId,
557 'status_id' => "Open",
558 ));
559 $result = $this->callAPISuccessGetSingle('Case', array(
560 'id' => $case1['id'],
561 'status_id' => "Open",
562 'return' => array('contacts'),
563 ));
564 foreach ($result['contacts'] as $contact) {
565 if ($contact['role'] == 'Client') {
566 $this->assertEquals(17, $contact['contact_id']);
567 }
568 elseif ($contact['role'] == 'Homeless Services Coordinator') {
569 $this->assertEquals(1, $contact['creator']);
570 $this->assertEquals(1, $contact['manager']);
571 }
572 }
573 }
574
575 public function testCaseGetWithDefinition() {
576 $case1 = $this->callAPISuccess('Case', 'create', array(
577 'contact_id' => 17,
578 'subject' => "Test case with definition",
579 'case_type_id' => $this->caseTypeId,
580 'status_id' => "Open",
581 ));
582 $result1 = $this->callAPISuccessGetSingle('Case', array(
583 'id' => $case1['id'],
584 'status_id' => "Open",
585 'return' => array('case_type_id.definition'),
586 ));
587 $result2 = $this->callAPISuccessGetSingle('Case', array(
588 'id' => $case1['id'],
589 'status_id' => "Open",
590 'return' => array('case_type_id', 'case_type_id.definition'),
591 ));
592 $this->assertEquals($result1['case_type_id.definition'], $result2['case_type_id.definition']);
593 $def = $result1['case_type_id.definition'];
594 $this->assertEquals(array('name' => 'Open Case', 'max_instances' => 1), $def['activityTypes'][0]);
595 $this->assertNotEmpty($def['activitySets'][0]['activityTypes']);
596 $this->assertNotEmpty($def['caseRoles'][0]['manager']);
597 $this->assertNotEmpty($def['caseRoles'][0]['creator']);
598 }
599
600 public function testCaseGetTags() {
601 $case1 = $this->callAPISuccess('Case', 'create', array(
602 'contact_id' => 17,
603 'subject' => "Test case with tags",
604 'case_type_id' => $this->caseTypeId,
605 'status_id' => "Open",
606 ));
607 $tag1 = $this->tagCreate(array(
608 'name' => 'CaseTag1',
609 'used_for' => 'civicrm_case',
610 ));
611 $tag2 = $this->tagCreate(array(
612 'name' => 'CaseTag2',
613 'used_for' => 'civicrm_case',
614 ));
615 $this->callAPISuccess('EntityTag', 'create', array(
616 'entity_table' => 'civicrm_case',
617 'entity_id' => $case1['id'],
618 'tag_id' => $tag1['id'],
619 ));
620 $this->callAPIFailure('Case', 'getsingle', array(
621 'tag_id' => $tag2['id'],
622 ));
623 $result = $this->callAPISuccessGetSingle('Case', array(
624 'tag_id' => $tag1['id'],
625 'return' => 'tag_id.name',
626 ));
627 $this->assertEquals('CaseTag1', $result['tag_id'][$tag1['id']]['tag_id.name']);
628 }
629
630 /**
631 * Test that a chained api call can use the operator syntax.
632 *
633 * E.g. array('IN' => $value.contact_id)
634 *
635 * @throws \Exception
636 */
637 public function testCaseGetChainedOp() {
638 $contact1 = $this->individualCreate(array(), 1);
639 $contact2 = $this->individualCreate(array(), 2);
640 $case1 = $this->callAPISuccess('Case', 'create', array(
641 'contact_id' => $contact1,
642 'subject' => "Test case 1",
643 'case_type_id' => $this->caseTypeId,
644 ));
645 $case2 = $this->callAPISuccess('Case', 'create', array(
646 'contact_id' => $contact2,
647 'subject' => "Test case 2",
648 'case_type_id' => $this->caseTypeId,
649 ));
650 $case3 = $this->callAPISuccess('Case', 'create', array(
651 'contact_id' => array($contact1, $contact2),
652 'subject' => "Test case 3",
653 'case_type_id' => $this->caseTypeId,
654 ));
655
656 // Fetch case 1 and all cases with the same client. Chained get should return case 3.
657 $result = $this->callAPISuccessGetSingle('Case', array(
658 'id' => $case1['id'],
659 'return' => 'contact_id',
660 'api.Case.get' => array(
661 'contact_id' => array('IN' => "\$value.contact_id"),
662 'id' => array('!=' => "\$value.id"),
663 ),
664 ));
665 $this->assertEquals($case3['id'], $result['api.Case.get']['id']);
666
667 // Fetch case 3 and all cases with the same clients. Chained get should return case 1&2.
668 $result = $this->callAPISuccessGetSingle('Case', array(
669 'id' => $case3['id'],
670 'return' => array('contact_id'),
671 'api.Case.get' => array(
672 'return' => 'id',
673 'contact_id' => array('IN' => "\$value.contact_id"),
674 'id' => array('!=' => "\$value.id"),
675 ),
676 ));
677 $this->assertEquals(array($case1['id'], $case2['id']), array_keys(CRM_Utils_Array::rekey($result['api.Case.get']['values'], 'id')));
678 }
679
680 /**
681 * Test the ability to order by client using the join syntax.
682 *
683 * For multi-client cases, should order by the first client.
684 */
685 public function testCaseGetOrderByClient() {
686 $contact1 = $this->individualCreate(array('first_name' => 'Aa', 'last_name' => 'Zz'));
687 $contact2 = $this->individualCreate(array('first_name' => 'Bb', 'last_name' => 'Zz'));
688 $contact3 = $this->individualCreate(array('first_name' => 'Cc', 'last_name' => 'Xx'));
689
690 $case1 = $this->callAPISuccess('Case', 'create', array(
691 'contact_id' => $contact1,
692 'subject' => "Test case 1",
693 'case_type_id' => $this->caseTypeId,
694 ));
695 $case2 = $this->callAPISuccess('Case', 'create', array(
696 'contact_id' => $contact2,
697 'subject' => "Test case 2",
698 'case_type_id' => $this->caseTypeId,
699 ));
700 $case3 = $this->callAPISuccess('Case', 'create', array(
701 'contact_id' => array($contact3, $contact1),
702 'subject' => "Test case 3",
703 'case_type_id' => $this->caseTypeId,
704 ));
705
706 $result = $this->callAPISuccess('Case', 'get', array(
707 'contact_id' => array('IN' => array($contact1, $contact2, $contact3)),
708 'sequential' => 1,
709 'return' => 'id',
710 'options' => array('sort' => 'contact_id.first_name'),
711 ));
712 $this->assertEquals($case3['id'], $result['values'][2]['id']);
713 $this->assertEquals($case2['id'], $result['values'][1]['id']);
714 $this->assertEquals($case1['id'], $result['values'][0]['id']);
715
716 $result = $this->callAPISuccess('Case', 'get', array(
717 'contact_id' => array('IN' => array($contact1, $contact2, $contact3)),
718 'sequential' => 1,
719 'return' => 'id',
720 'options' => array('sort' => 'contact_id.last_name ASC, contact_id.first_name DESC'),
721 ));
722 $this->assertEquals($case1['id'], $result['values'][2]['id']);
723 $this->assertEquals($case2['id'], $result['values'][1]['id']);
724 $this->assertEquals($case3['id'], $result['values'][0]['id']);
725
726 $result = $this->callAPISuccess('Case', 'get', array(
727 'contact_id' => array('IN' => array($contact1, $contact2, $contact3)),
728 'sequential' => 1,
729 'return' => 'id',
730 'options' => array('sort' => 'contact_id.first_name DESC'),
731 ));
732 $this->assertEquals($case1['id'], $result['values'][2]['id']);
733 $this->assertEquals($case2['id'], $result['values'][1]['id']);
734 $this->assertEquals($case3['id'], $result['values'][0]['id']);
735
736 $result = $this->callAPISuccess('Case', 'get', array(
737 'contact_id' => array('IN' => array($contact1, $contact2, $contact3)),
738 'sequential' => 1,
739 'return' => 'id',
740 'options' => array('sort' => 'case_type_id, contact_id DESC, status_id'),
741 ));
742 $this->assertEquals($case1['id'], $result['values'][2]['id']);
743 $this->assertEquals($case2['id'], $result['values'][1]['id']);
744 $this->assertEquals($case3['id'], $result['values'][0]['id']);
745 $this->assertCount(3, $result['values']);
746 }
747
748 /**
749 * Test the ability to add a timeline to an existing case.
750 *
751 * See the case.addtimeline api.
752 *
753 * @dataProvider caseActivityRevisionExamples
754 * @throws \Exception
755 */
756 public function testCaseAddtimeline($enableRevisions) {
757 $this->settingsStack->push('civicaseActivityRevisions', $enableRevisions);
758
759 $caseSpec = array(
760 'title' => 'Application with Definition',
761 'name' => 'Application_with_Definition',
762 'is_active' => 1,
763 'weight' => 4,
764 'definition' => array(
765 'activityTypes' => array(
766 array('name' => 'Follow up'),
767 ),
768 'activitySets' => array(
769 array(
770 'name' => 'set1',
771 'label' => 'Label 1',
772 'timeline' => 1,
773 'activityTypes' => array(
774 array('name' => 'Open Case', 'status' => 'Completed'),
775 ),
776 ),
777 array(
778 'name' => 'set2',
779 'label' => 'Label 2',
780 'timeline' => 1,
781 'activityTypes' => array(
782 array('name' => 'Follow up'),
783 ),
784 ),
785 ),
786 'caseRoles' => array(
787 array('name' => 'Homeless Services Coordinator', 'creator' => 1, 'manager' => 1),
788 ),
789 ),
790 );
791 $cid = $this->individualCreate();
792 $caseType = $this->callAPISuccess('CaseType', 'create', $caseSpec);
793 $case = $this->callAPISuccess('Case', 'create', array(
794 'case_type_id' => $caseType['id'],
795 'contact_id' => $cid,
796 'subject' => 'Test case with timeline',
797 ));
798 // Created case should only have 1 activity per the spec
799 $result = $this->callAPISuccessGetSingle('Activity', array('case_id' => $case['id'], 'return' => 'activity_type_id.name'));
800 $this->assertEquals('Open Case', $result['activity_type_id.name']);
801 // Add timeline
802 $timeline = civicrm_api('Case', 'addtimeline', array(
803 'case_id' => $case['id'],
804 'timeline' => 'set2',
805 'version' => 3,
806 ));
807 $result = $this->callAPISuccess('Activity', 'get', array(
808 'case_id' => $case['id'],
809 'return' => 'activity_type_id.name',
810 'sequential' => 1,
811 'options' => array('sort' => 'id'),
812 ));
813 $this->assertEquals(2, $result['count']);
814 $this->assertEquals('Follow up', $result['values'][1]['activity_type_id.name']);
815 }
816
817 /**
818 * Test the case merge function.
819 *
820 * 2 cases should be mergeable into 1
821 *
822 * @throws \Exception
823 */
824 public function testCaseMerge() {
825 $contact1 = $this->individualCreate(array(), 1);
826 $case1 = $this->callAPISuccess('Case', 'create', array(
827 'contact_id' => $contact1,
828 'subject' => "Test case 1",
829 'case_type_id' => $this->caseTypeId,
830 ));
831 $case2 = $this->callAPISuccess('Case', 'create', array(
832 'contact_id' => $contact1,
833 'subject' => "Test case 2",
834 'case_type_id' => $this->caseTypeId,
835 ));
836 $result = $this->callAPISuccess('Case', 'getcount', array('contact_id' => $contact1));
837 $this->assertEquals(2, $result);
838
839 $this->callAPISuccess('Case', 'merge', array('case_id_1' => $case1['id'], 'case_id_2' => $case2['id']));
840
841 $result = $this->callAPISuccess('Case', 'getsingle', array('id' => $case2['id']));
842 $this->assertEquals(1, $result['is_deleted']);
843 }
844
845 public function caseActivityRevisionExamples() {
846 $examples = array();
847 $examples[] = array(FALSE);
848 $examples[] = array(TRUE);
849 return $examples;
850 }
851
852 }