CRM-17645 - Convert case autocompletes to use EntityRef
[civicrm-core.git] / CRM / Case / Form / CaseView.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2015
32 */
33
34 /**
35 * This class generates view mode for CiviCase.
36 */
37 class CRM_Case_Form_CaseView extends CRM_Core_Form {
38 /**
39 * Check for merge cases.
40 * @var bool
41 */
42 private $_mergeCases = FALSE;
43
44 /**
45 * Set variables up before form is built.
46 */
47 public function preProcess() {
48 $this->_showRelatedCases = CRM_Utils_Array::value('relatedCases', $_GET);
49
50 $xmlProcessorProcess = new CRM_Case_XMLProcessor_Process();
51 $isMultiClient = $xmlProcessorProcess->getAllowMultipleCaseClients();
52 $this->assign('multiClient', $isMultiClient);
53
54 //pull the related cases.
55 $this->assign('showRelatedCases', FALSE);
56 if ($this->_showRelatedCases) {
57 $relatedCases = $this->get('relatedCases');
58 if (!isset($relatedCases)) {
59 $cId = CRM_Utils_Request::retrieve('cid', 'Integer', CRM_Core_DAO::$_nullObject);
60 $caseId = CRM_Utils_Request::retrieve('id', 'Integer', CRM_Core_DAO::$_nullObject);
61 $relatedCases = CRM_Case_BAO_Case::getRelatedCases($caseId, $cId);
62 }
63 $this->assign('relatedCases', $relatedCases);
64 $this->assign('showRelatedCases', TRUE);
65 CRM_Utils_System::setTitle(ts('Related Cases'));
66 return;
67 }
68
69 //check for civicase access.
70 if (!CRM_Case_BAO_Case::accessCiviCase()) {
71 CRM_Core_Error::fatal(ts('You are not authorized to access this page.'));
72 }
73 $this->_hasAccessToAllCases = CRM_Core_Permission::check('access all cases and activities');
74 $this->assign('hasAccessToAllCases', $this->_hasAccessToAllCases);
75
76 $this->_contactID = $this->get('cid');
77 $this->_caseID = $this->get('id');
78
79 $fulltext = CRM_Utils_Request::retrieve('context', 'String', CRM_Core_DAO::$_nullObject);
80 if ($fulltext == 'fulltext') {
81 $this->assign('fulltext', $fulltext);
82 }
83
84 $this->assign('caseID', $this->_caseID);
85 $this->assign('contactID', $this->_contactID);
86 $this->assign('contactType', CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_contactID, 'contact_type'));
87
88 //validate case id.
89 $this->_userCases = array();
90 $session = CRM_Core_Session::singleton();
91 $userID = $session->get('userID');
92 if (!$this->_hasAccessToAllCases) {
93 $this->_userCases = CRM_Case_BAO_Case::getCases(FALSE, $userID, 'any');
94 if (!array_key_exists($this->_caseID, $this->_userCases)) {
95 CRM_Core_Error::fatal(ts('You are not authorized to access this page.'));
96 }
97 }
98 $this->assign('userID', $userID);
99
100 if (CRM_Case_BAO_Case::caseCount($this->_contactID) >= 2) {
101 $this->_mergeCases = TRUE;
102 }
103 $this->assign('mergeCases', $this->_mergeCases);
104
105 //retrieve details about case
106 $params = array('id' => $this->_caseID);
107
108 $returnProperties = array('case_type_id', 'subject', 'status_id', 'start_date');
109 CRM_Core_DAO::commonRetrieve('CRM_Case_BAO_Case', $params, $values, $returnProperties);
110
111 $statuses = CRM_Case_PseudoConstant::caseStatus('label', FALSE);
112 $caseTypeName = CRM_Case_BAO_Case::getCaseType($this->_caseID, 'name');
113 $caseType = CRM_Case_BAO_Case::getCaseType($this->_caseID);
114
115 $this->_caseDetails = array(
116 'case_type' => $caseType,
117 'case_status' => CRM_Utils_Array::value($values['case_status_id'], $statuses),
118 'case_subject' => CRM_Utils_Array::value('subject', $values),
119 'case_start_date' => $values['case_start_date'],
120 );
121 $this->_caseType = $caseTypeName;
122 $this->assign('caseDetails', $this->_caseDetails);
123
124 $reportUrl = CRM_Utils_System::url('civicrm/case/report',
125 "reset=1&cid={$this->_contactID}&caseid={$this->_caseID}&asn=",
126 FALSE, NULL, FALSE
127 );
128 $this->assign('reportUrl', $reportUrl);
129
130 // add to recently viewed
131
132 $url = CRM_Utils_System::url('civicrm/contact/view/case',
133 "action=view&reset=1&id={$this->_caseID}&cid={$this->_contactID}&context=home"
134 );
135
136 $displayName = CRM_Contact_BAO_Contact::displayName($this->_contactID);
137 $this->assign('displayName', $displayName);
138
139 CRM_Utils_System::setTitle($displayName . ' - ' . $caseType);
140
141 $recentOther = array();
142 if (CRM_Core_Permission::checkActionPermission('CiviCase', CRM_Core_Action::DELETE)) {
143 $recentOther['deleteUrl'] = CRM_Utils_System::url('civicrm/contact/view/case',
144 "action=delete&reset=1&id={$this->_caseID}&cid={$this->_contactID}&context=home"
145 );
146 }
147
148 // Add the recently viewed case
149 CRM_Utils_Recent::add($displayName . ' - ' . $caseType,
150 $url,
151 $this->_caseID,
152 'Case',
153 $this->_contactID,
154 NULL,
155 $recentOther
156 );
157
158 //get the related cases for given case.
159 $relatedCases = $this->get('relatedCases');
160 if (!isset($relatedCases)) {
161 $relatedCases = CRM_Case_BAO_Case::getRelatedCases($this->_caseID, $this->_contactID);
162 $relatedCases = empty($relatedCases) ? FALSE : $relatedCases;
163 $this->set('relatedCases', $relatedCases);
164 }
165 $this->assign('hasRelatedCases', (bool) $relatedCases);
166 if ($relatedCases) {
167 $this->assign('relatedCaseLabel', ts('%1 Related Case', array(
168 'count' => count($relatedCases),
169 'plural' => '%1 Related Cases',
170 )));
171 $this->assign('relatedCaseUrl', CRM_Utils_System::url('civicrm/contact/view/case', array(
172 'id' => $this->_caseID,
173 'cid' => $this->_contactID,
174 'relatedCases' => 1,
175 'action' => 'view',
176 )));
177 }
178
179 $entitySubType = !empty($values['case_type_id']) ? $values['case_type_id'] : NULL;
180 $this->assign('caseTypeID', $entitySubType);
181 $groupTree = &CRM_Core_BAO_CustomGroup::getTree('Case',
182 $this,
183 $this->_caseID,
184 NULL,
185 $entitySubType
186 );
187 CRM_Core_BAO_CustomGroup::buildCustomDataView($this, $groupTree, FALSE, NULL, NULL, NULL, $this->_caseID);
188 }
189
190 /**
191 * Set default values for the form.
192 *
193 * @return array;
194 */
195 public function setDefaultValues() {
196 $defaults = array();
197 return $defaults;
198 }
199
200 /**
201 * Build the form object.
202 */
203 public function buildQuickForm() {
204 //this call is for show related cases.
205 if ($this->_showRelatedCases) {
206 return;
207 }
208
209 $allowedRelationshipTypes = CRM_Contact_BAO_Relationship::getContactRelationshipType($this->_contactID);
210
211 CRM_Core_Resources::singleton()
212 ->addScriptFile('civicrm', 'js/crm.livePage.js', 1, 'html-header')
213 ->addScriptFile('civicrm', 'templates/CRM/Case/Form/CaseView.js', 2, 'html-header')
214 ->addVars('relationshipTypes', CRM_Contact_Form_Relationship::getRelationshipTypeMetadata($allowedRelationshipTypes));
215
216 $xmlProcessor = new CRM_Case_XMLProcessor_Process();
217 $caseRoles = $xmlProcessor->get($this->_caseType, 'CaseRoles');
218 $reports = $xmlProcessor->get($this->_caseType, 'ActivitySets');
219
220 //adding case manager.CRM-4510.
221 $managerRoleId = $xmlProcessor->getCaseManagerRoleId($this->_caseType);
222 if (!empty($managerRoleId)) {
223 $caseRoles[$managerRoleId] = $caseRoles[$managerRoleId] . '<br />' . '(' . ts('Case Manager') . ')';
224 }
225
226 $aTypes = $xmlProcessor->get($this->_caseType, 'ActivityTypes', TRUE);
227
228 $allActTypes = CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'name');
229
230 $emailActivityType = array_search('Email', $allActTypes);
231 $pdfActivityType = array_search('Print PDF Letter', $allActTypes);
232
233 if ($pdfActivityType) {
234 $this->assign('exportDoc', CRM_Utils_System::url('civicrm/activity/pdf/add',
235 "action=add&context=standalone&reset=1&cid={$this->_contactID}&caseid={$this->_caseID}&atype=$pdfActivityType"));
236 }
237
238 // remove Open Case activity type since we're inside an existing case
239 if ($openActTypeId = array_search('Open Case', $allActTypes)) {
240 unset($aTypes[$openActTypeId]);
241 }
242
243 // Only show "link cases" activity if other cases exist.
244 $linkActTypeId = array_search('Link Cases', $allActTypes);
245 if ($linkActTypeId) {
246 $count = civicrm_api3('Case', 'getcount', array(
247 'id' => array('!=' => $this->_caseID),
248 'is_deleted' => 0,
249 ));
250 if (!$count) {
251 unset($aTypes[$linkActTypeId]);
252 }
253 }
254
255 if (!$xmlProcessor->getNaturalActivityTypeSort()) {
256 asort($aTypes);
257 }
258
259 $activityLinks = array('' => ts('Add Activity'));
260 foreach ($aTypes as $type => $label) {
261 if ($type == $emailActivityType) {
262 $url = CRM_Utils_System::url('civicrm/activity/email/add',
263 "action=add&context=standalone&reset=1&caseid={$this->_caseID}&atype=$type",
264 FALSE, NULL, FALSE
265 );
266 }
267 elseif ($type == $pdfActivityType) {
268 $url = CRM_Utils_System::url('civicrm/activity/pdf/add',
269 "action=add&context=standalone&reset=1&cid={$this->_contactID}&caseid={$this->_caseID}&atype=$type",
270 FALSE, NULL, FALSE);
271 }
272 else {
273 $url = CRM_Utils_System::url('civicrm/case/activity',
274 "action=add&reset=1&cid={$this->_contactID}&caseid={$this->_caseID}&atype=$type",
275 FALSE, NULL, FALSE
276 );
277 }
278 $activityLinks[$url] = $label;
279 }
280
281 $this->add('select', 'add_activity_type_id', '', $activityLinks, FALSE, array('class' => 'crm-select2 crm-action-menu fa-calendar-check-o twenty'));
282 if ($this->_hasAccessToAllCases) {
283 $this->add('select', 'report_id', '',
284 array('' => ts('Activity Audit')) + $reports,
285 FALSE,
286 array('class' => 'crm-select2 crm-action-menu fa-list-alt')
287 );
288 $this->add('select', 'timeline_id', '',
289 array('' => ts('Add Timeline')) + $reports,
290 FALSE,
291 array('class' => 'crm-select2 crm-action-menu fa-list-ol')
292 );
293 }
294 $this->addElement('submit', $this->getButtonName('next'), ' ', array('class' => 'hiddenElement'));
295
296 if ($this->_mergeCases) {
297 $allCases = CRM_Case_BAO_Case::getContactCases($this->_contactID);
298 $otherCases = array();
299 foreach ($allCases as $caseId => $details) {
300 //filter current and own cases.
301 if (($caseId == $this->_caseID) ||
302 (!$this->_hasAccessToAllCases &&
303 !array_key_exists($caseId, $this->_userCases)
304 )
305 ) {
306 continue;
307 }
308
309 $otherCases[$caseId] = 'Case ID: ' . $caseId . ' Type: ' . $details['case_type'] . ' Start: ' . $details['case_start_date'];
310 }
311 if (empty($otherCases)) {
312 $this->_mergeCases = FALSE;
313 $this->assign('mergeCases', $this->_mergeCases);
314 }
315 else {
316 $this->add('select', 'merge_case_id',
317 ts('Select Case for Merge'),
318 array(
319 '' => ts('- select case -'),
320 ) + $otherCases,
321 FALSE,
322 array('class' => 'crm-select2 huge')
323 );
324 $this->addElement('submit',
325 $this->getButtonName('next', 'merge_case'),
326 ts('Merge'),
327 array(
328 'class' => 'hiddenElement',
329 )
330 );
331 }
332 }
333
334 //call activity form
335 self::activityForm($this, $aTypes);
336
337 //get case related relationships (Case Role)
338 $caseRelationships = CRM_Case_BAO_Case::getCaseRoles($this->_contactID, $this->_caseID);
339
340 //save special label because we unset it in the loop
341 $managerLabel = empty($managerRoleId) ? '' : $caseRoles[$managerRoleId];
342
343 foreach ($caseRelationships as $key => & $value) {
344 if (!empty($managerRoleId)) {
345 if ($managerRoleId == $value['relation_type']) {
346 $value['relation'] = $managerLabel;
347 }
348 }
349
350 //calculate roles that don't have relationships
351 if (!empty($caseRoles[$value['relation_type']])) {
352 unset($caseRoles[$value['relation_type']]);
353 }
354 }
355
356 $this->assign('caseRelationships', $caseRelationships);
357
358 //also add client as role. CRM-4438
359 $caseRoles['client'] = CRM_Case_BAO_Case::getContactNames($this->_caseID);
360
361 $this->assign('caseRoles', $caseRoles);
362
363 // Retrieve ALL client relationships
364 $relClient = CRM_Contact_BAO_Relationship::getRelationship($this->_contactID,
365 CRM_Contact_BAO_Relationship::CURRENT,
366 0, 0, 0, NULL, NULL, FALSE
367 );
368
369 // Now build 'Other Relationships' array by removing relationships that are already listed under Case Roles
370 // so they don't show up twice.
371 $clientRelationships = array();
372 foreach ($relClient as $r) {
373 if (!array_key_exists($r['id'], $caseRelationships)) {
374 $clientRelationships[] = $r;
375 }
376 }
377 $this->assign('clientRelationships', $clientRelationships);
378
379 // Now global contact list that appears on all cases.
380 $globalGroupInfo = array();
381 CRM_Case_BAO_Case::getGlobalContacts($globalGroupInfo);
382 $this->assign('globalGroupInfo', $globalGroupInfo);
383
384 // List relationship types for adding an arbitrary new role to the case
385 $this->add('select',
386 'role_type',
387 ts('Relationship Type'),
388 array('' => ts('- select type -')) + $allowedRelationshipTypes,
389 FALSE,
390 array('class' => 'crm-select2 twenty', 'data-select-params' => '{"allowClear": false}')
391 );
392
393 $hookCaseSummary = CRM_Utils_Hook::caseSummary($this->_caseID);
394 if (is_array($hookCaseSummary)) {
395 $this->assign('hookCaseSummary', $hookCaseSummary);
396 }
397
398 CRM_Core_BAO_Tag::getTags('civicrm_case', $allTags, NULL,
399 '&nbsp;&nbsp;', TRUE);
400
401 if (!empty($allTags)) {
402 $this->add('select', 'case_tag', ts('Tags'), $allTags, FALSE,
403 array('id' => 'tags', 'multiple' => 'multiple', 'class' => 'crm-select2')
404 );
405
406 $tags = CRM_Core_BAO_EntityTag::getTag($this->_caseID, 'civicrm_case');
407
408 $this->setDefaults(array('case_tag' => $tags));
409
410 foreach ($tags as $tid) {
411 if (isset($allTags[$tid])) {
412 $tags[$tid] = $allTags[$tid];
413 }
414 else {
415 unset($tags[$tid]);
416 }
417 }
418
419 $this->assign('tags', implode(', ', array_filter($tags)));
420 $this->assign('showTags', TRUE);
421 }
422 else {
423 $this->assign('showTags', FALSE);
424 }
425
426 // build tagset widget
427
428 // see if we have any tagsets which can be assigned to cases
429 $parentNames = CRM_Core_BAO_Tag::getTagSet('civicrm_case');
430 if ($parentNames) {
431 $this->assign('showTagsets', TRUE);
432 }
433 else {
434 $this->assign('showTagsets', FALSE);
435 }
436 CRM_Core_Form_Tag::buildQuickForm($this, $parentNames, 'civicrm_case', $this->_caseID, FALSE, TRUE);
437
438 $this->addButtons(array(
439 array(
440 'type' => 'cancel',
441 'name' => ts('Done'),
442 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
443 'isDefault' => TRUE,
444 ),
445 )
446 );
447 }
448
449 /**
450 * Process the form.
451 */
452 public function postProcess() {
453 $params = $this->controller->exportValues($this->_name);
454 $buttonName = $this->controller->getButtonName();
455
456 // user context
457 $url = CRM_Utils_System::url('civicrm/contact/view/case',
458 "reset=1&action=view&cid={$this->_contactID}&id={$this->_caseID}&show=1"
459 );
460 $session = CRM_Core_Session::singleton();
461 $session->pushUserContext($url);
462
463 if (!empty($params['timeline_id']) && !empty($_POST['_qf_CaseView_next'])) {
464 $session = CRM_Core_Session::singleton();
465 $this->_uid = $session->get('userID');
466 $xmlProcessor = new CRM_Case_XMLProcessor_Process();
467 $xmlProcessorParams = array(
468 'clientID' => $this->_contactID,
469 'creatorID' => $this->_uid,
470 'standardTimeline' => 0,
471 'activity_date_time' => date('YmdHis'),
472 'caseID' => $this->_caseID,
473 'caseType' => $this->_caseType,
474 'activitySetName' => $params['timeline_id'],
475 );
476 $xmlProcessor->run($this->_caseType, $xmlProcessorParams);
477 $reports = $xmlProcessor->get($this->_caseType, 'ActivitySets');
478
479 CRM_Core_Session::setStatus(ts('Activities from the %1 activity set have been added to this case.',
480 array(1 => $reports[$params['timeline_id']])
481 ), ts('Done'), 'success');
482 }
483 elseif ($this->_mergeCases &&
484 $buttonName == '_qf_CaseView_next_merge_case'
485 ) {
486
487 $mainCaseId = $params['merge_case_id'];
488 $otherCaseId = $this->_caseID;
489
490 //merge two cases.
491 CRM_Case_BAO_Case::mergeCases($this->_contactID, $mainCaseId, NULL, $otherCaseId);
492
493 //redirect user to main case view.
494 $url = CRM_Utils_System::url('civicrm/contact/view/case',
495 "reset=1&action=view&cid={$this->_contactID}&id={$mainCaseId}&show=1"
496 );
497 $session = CRM_Core_Session::singleton();
498 $session->pushUserContext($url);
499 }
500 }
501
502 /**
503 * Build the activity selector/datatable
504 * @param CRM_Core_Form $form
505 * @param array $aTypes
506 * To include acivities related to current case id $form->_caseID.
507 */
508 public static function activityForm($form, $aTypes = array()) {
509 $caseRelationships = CRM_Case_BAO_Case::getCaseRoles($form->_contactID, $form->_caseID);
510 //build reporter select
511 $reporters = array("" => ts(' - any reporter - '));
512 foreach ($caseRelationships as $key => & $value) {
513 $reporters[$value['cid']] = $value['name'] . " ( {$value['relation']} )";
514 }
515 $form->add('select', 'reporter_id', ts('Reporter/Role'), $reporters, FALSE, array('id' => 'reporter_id_' . $form->_caseID));
516
517 // take all case activity types for search filter, CRM-7187
518 $aTypesFilter = array();
519 $allCaseActTypes = CRM_Case_PseudoConstant::caseActivityType();
520 foreach ($allCaseActTypes as $typeDetails) {
521 if (!in_array($typeDetails['name'], array('Open Case'))) {
522 $aTypesFilter[$typeDetails['id']] = CRM_Utils_Array::value('label', $typeDetails);
523 }
524 }
525 $aTypesFilter = $aTypesFilter + $aTypes;
526 asort($aTypesFilter);
527 $form->add('select', 'activity_type_filter_id', ts('Activity Type'), array('' => ts('- select activity type -')) + $aTypesFilter, FALSE, array('id' => 'activity_type_filter_id_' . $form->_caseID));
528
529 $activityStatus = CRM_Core_PseudoConstant::activityStatus();
530 $form->add('select', 'status_id', ts('Status'), array("" => ts(' - any status - ')) + $activityStatus, FALSE, array('id' => 'status_id_' . $form->_caseID));
531
532 // activity dates
533 $form->addDate('activity_date_low_' . $form->_caseID, ts('Activity Dates - From'), FALSE, array('formatType' => 'searchDate'));
534 $form->addDate('activity_date_high_' . $form->_caseID, ts('To'), FALSE, array('formatType' => 'searchDate'));
535
536 if (CRM_Core_Permission::check('administer CiviCRM')) {
537 $form->add('checkbox', 'activity_deleted', ts('Deleted Activities'), '', FALSE, array('id' => 'activity_deleted_' . $form->_caseID));
538 }
539 }
540
541 }