Merge branch 'master' into 5.15
[civicrm-core.git] / CRM / Case / Form / Case.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
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-2019
32 */
33
34 /**
35 * This class generates form components for case activity.
36 */
37 class CRM_Case_Form_Case extends CRM_Core_Form {
38
39 /**
40 * The context
41 *
42 * @var string
43 */
44 public $_context = 'case';
45
46 /**
47 * Case Id
48 * @var int
49 */
50 public $_caseId = NULL;
51
52 /**
53 * Client Id
54 * @var int
55 */
56 public $_currentlyViewedContactId = NULL;
57
58 /**
59 * Activity Type File
60 * @var int
61 */
62 public $_activityTypeFile = NULL;
63
64 /**
65 * Logged in contact Id
66 * @var int
67 */
68 public $_currentUserId = NULL;
69
70 /**
71 * Activity type Id
72 * @var int
73 */
74 public $_activityTypeId = NULL;
75
76 /**
77 * Activity type Id
78 * @var int
79 */
80 public $_activityId = NULL;
81
82 /**
83 * Action
84 * @var int
85 */
86 public $_action;
87
88 /**
89 * Case type id
90 * @var int
91 */
92 public $_caseTypeId = NULL;
93
94 public $submitOnce = TRUE;
95
96 /**
97 * Explicitly declare the entity api name.
98 */
99 public function getDefaultEntity() {
100 return 'Case';
101 }
102
103 /**
104 * Get the entity id being edited.
105 *
106 * @return int|null
107 */
108 public function getEntityId() {
109 return $this->_caseId;
110 }
111
112 /**
113 * Get the entity subtype ID being edited
114 *
115 * @param $subTypeId
116 *
117 * @return int|null
118 */
119 public function getEntitySubTypeId($subTypeId) {
120 if ($subTypeId) {
121 return $subTypeId;
122 }
123 return $this->_caseTypeId;
124 }
125
126 /**
127 * Build the form object.
128 */
129 public function preProcess() {
130 if (empty($this->_action)) {
131 $this->_action = CRM_Core_Action::ADD;
132 }
133
134 $this->_caseId = CRM_Utils_Request::retrieve('id', 'Positive', $this);
135
136 $this->_currentlyViewedContactId = CRM_Utils_Request::retrieve('cid', 'Positive', $this);
137
138 if ($this->_action & CRM_Core_Action::ADD && !$this->_currentlyViewedContactId) {
139 // check for add contacts permissions
140 if (!CRM_Core_Permission::check('add contacts')) {
141 CRM_Utils_System::permissionDenied();
142 return;
143 }
144 }
145
146 //CRM-4418
147 if (!CRM_Core_Permission::checkActionPermission('CiviCase', $this->_action)) {
148 CRM_Core_Error::fatal(ts('You do not have permission to access this page.'));
149 }
150
151 if ($this->_action & CRM_Core_Action::DELETE || $this->_action & CRM_Core_Action::RENEW) {
152 return TRUE;
153 }
154
155 if (!$this->_caseId) {
156 $caseAttributes = [
157 'case_type_id' => ts('Case Type'),
158 'status_id' => ts('Case Status'),
159 'medium_id' => ts('Activity Medium'),
160 ];
161
162 foreach ($caseAttributes as $key => $label) {
163 if (!CRM_Case_BAO_Case::buildOptions($key, 'create')) {
164 CRM_Core_Error::fatal(ts('You do not have any active %1', [1 => $label]));
165 }
166 }
167 }
168
169 if ($this->_action & CRM_Core_Action::ADD) {
170 $this->_activityTypeId = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Open Case');
171 if (!$this->_activityTypeId) {
172 CRM_Core_Error::fatal(ts('The Open Case activity type is missing or disabled. Please have your site administrator check Administer > Option Lists > Activity Types for the CiviCase component.'));
173 }
174 }
175
176 //check for case permissions.
177 if (!CRM_Case_BAO_Case::accessCiviCase()) {
178 CRM_Core_Error::fatal(ts('You are not authorized to access this page.'));
179 }
180 if (($this->_action & CRM_Core_Action::ADD) &&
181 (!CRM_Core_Permission::check('access all cases and activities') &&
182 !CRM_Core_Permission::check('add cases')
183 )
184 ) {
185 CRM_Core_Error::fatal(ts('You are not authorized to access this page.'));
186 }
187
188 if ($this->_activityTypeFile = CRM_Activity_BAO_Activity::getFileForActivityTypeId($this->_activityTypeId,
189 'Case'
190 )
191 ) {
192 $this->assign('activityTypeFile', $this->_activityTypeFile);
193 }
194
195 $details = CRM_Case_PseudoConstant::caseActivityType(FALSE);
196
197 CRM_Utils_System::setTitle($details[$this->_activityTypeId]['label']);
198 $this->assign('activityType', $details[$this->_activityTypeId]['label']);
199 $this->assign('activityTypeDescription', $details[$this->_activityTypeId]['description']);
200
201 if (isset($this->_currentlyViewedContactId)) {
202 $contact = new CRM_Contact_DAO_Contact();
203 $contact->id = $this->_currentlyViewedContactId;
204 if (!$contact->find(TRUE)) {
205 CRM_Core_Error::statusBounce(ts('Client contact does not exist: %1', [1 => $this->_currentlyViewedContactId]));
206 }
207 $this->assign('clientName', $contact->display_name);
208 }
209
210 $session = CRM_Core_Session::singleton();
211 $this->_currentUserId = $session->get('userID');
212
213 //Add activity custom data is included in this page
214 CRM_Custom_Form_CustomData::preProcess($this, NULL, $this->_activityTypeId, 1, 'Activity');
215 $className = "CRM_Case_Form_Activity_{$this->_activityTypeFile}";
216 $className::preProcess($this);
217 $activityGroupTree = $this->_groupTree;
218
219 // Add case custom data to form
220 $caseTypeId = CRM_Utils_Array::value('case_type_id', CRM_Utils_Request::exportValues(), $this->_caseTypeId);
221 CRM_Custom_Form_CustomData::addToForm($this, $caseTypeId);
222
223 // so that grouptree is not populated with case fields, since the grouptree is used
224 // for populating activity custom fields.
225 $this->_groupTree = $activityGroupTree;
226 }
227
228 /**
229 * Set default values for the form.
230 */
231 public function setDefaultValues() {
232 if ($this->_action & CRM_Core_Action::DELETE || $this->_action & CRM_Core_Action::RENEW) {
233 return TRUE;
234 }
235 $className = "CRM_Case_Form_Activity_{$this->_activityTypeFile}";
236 $defaults = $className::setDefaultValues($this);
237 $defaults = array_merge($defaults, CRM_Custom_Form_CustomData::setDefaultValues($this));
238 return $defaults;
239 }
240
241 public function buildQuickForm() {
242 $xmlProcessorProcess = new CRM_Case_XMLProcessor_Process();
243 $isMultiClient = $xmlProcessorProcess->getAllowMultipleCaseClients();
244 $this->assign('multiClient', $isMultiClient);
245
246 if ($this->_action & CRM_Core_Action::DELETE || $this->_action & CRM_Core_Action::RENEW) {
247 $title = ts('Delete');
248 if ($this->_action & CRM_Core_Action::RENEW) {
249 $title = ts('Restore');
250 }
251 $this->addButtons([
252 [
253 'type' => 'next',
254 'name' => $title,
255 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
256 'isDefault' => TRUE,
257 ],
258 [
259 'type' => 'cancel',
260 'name' => ts('Cancel'),
261 ],
262 ]);
263 return;
264 }
265
266 // Add the activity custom data to the form
267 CRM_Custom_Form_CustomData::buildQuickForm($this);
268
269 // we don't want to show button on top of custom form
270 $this->assign('noPreCustomButton', TRUE);
271
272 $s = CRM_Core_DAO::getAttribute('CRM_Activity_DAO_Activity', 'subject');
273 if (!is_array($s)) {
274 $s = [];
275 }
276 $this->add('text', 'activity_subject', ts('Subject'),
277 array_merge($s, [
278 'maxlength' => '128',
279 ]), TRUE
280 );
281
282 $tags = CRM_Core_BAO_Tag::getColorTags('civicrm_case');
283
284 if (!empty($tags)) {
285 $this->add('select2', 'tag', ts('Tags'), $tags, FALSE,
286 ['class' => 'huge', 'multiple' => 'multiple']
287 );
288 }
289
290 // build tag widget
291 $parentNames = CRM_Core_BAO_Tag::getTagSet('civicrm_case');
292 CRM_Core_Form_Tag::buildQuickForm($this, $parentNames, 'civicrm_case', NULL, FALSE, TRUE);
293
294 $this->addButtons([
295 [
296 'type' => 'next',
297 'name' => ts('Save'),
298 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
299 'isDefault' => TRUE,
300 ],
301 [
302 'type' => 'cancel',
303 'name' => ts('Cancel'),
304 ],
305 ]);
306
307 $className = "CRM_Case_Form_Activity_{$this->_activityTypeFile}";
308 $className::buildQuickForm($this);
309 }
310
311 /**
312 * Add local and global form rules.
313 *
314 * @return bool
315 */
316 public function addRules() {
317 if ($this->_action & CRM_Core_Action::DELETE || $this->_action & CRM_Core_Action::RENEW) {
318 return TRUE;
319 }
320 $className = "CRM_Case_Form_Activity_{$this->_activityTypeFile}";
321 $this->addFormRule([$className, 'formRule'], $this);
322 $this->addFormRule(['CRM_Case_Form_Case', 'formRule'], $this);
323 }
324
325 /**
326 * Global validation rules for the form.
327 *
328 * @param array $values
329 * Posted values of the form.
330 *
331 * @param $files
332 * @param CRM_Core_Form $form
333 *
334 * @return array
335 * list of errors to be posted back to the form
336 */
337 public static function formRule($values, $files, $form) {
338 return TRUE;
339 }
340
341 /**
342 * Wrapper for unit testing the post process submit function.
343 *
344 * @param $params
345 * @param $activityTypeFile
346 * @param $contactId
347 * @param $context
348 * @return CRM_Case_BAO_Case
349 */
350 public function testSubmit($params, $activityTypeFile, $contactId, $context = "case") {
351 $this->controller = new CRM_Core_Controller();
352
353 $this->_activityTypeFile = $activityTypeFile;
354 $this->_currentUserId = $contactId;
355 $this->_context = $context;
356
357 return $this->submit($params);
358 }
359
360 /**
361 * Submit the form with given params.
362 *
363 * @param $params
364 */
365 public function submit(&$params) {
366 $params['now'] = date("Ymd");
367
368 // 1. call begin post process
369 if ($this->_activityTypeFile) {
370 $className = "CRM_Case_Form_Activity_{$this->_activityTypeFile}";
371 $className::beginPostProcess($this, $params);
372 }
373
374 if (!empty($params['hidden_custom']) &&
375 !isset($params['custom'])
376 ) {
377 $params['custom'] = CRM_Core_BAO_CustomField::postProcess(
378 $params,
379 NULL,
380 'Case'
381 );
382 }
383
384 // 2. create/edit case
385 if (!empty($params['case_type_id'])) {
386 $params['case_type'] = CRM_Core_DAO::getFieldValue('CRM_Case_DAO_CaseType', $params['case_type_id'], 'name', 'id');
387 $params['subject'] = $params['activity_subject'];
388 }
389 $caseObj = CRM_Case_BAO_Case::create($params);
390 $this->_caseId = $params['case_id'] = $caseObj->id;
391 // unset any ids, custom data
392 unset($params['id'], $params['custom']);
393
394 // add tags if exists
395 $tagParams = [];
396 if (!empty($params['tag'])) {
397 $tagParams = [];
398 if (!is_array($params['tag'])) {
399 $params['tag'] = explode(',', $params['tag']);
400 }
401 foreach ($params['tag'] as $tag) {
402 $tagParams[$tag] = 1;
403 }
404 }
405 CRM_Core_BAO_EntityTag::create($tagParams, 'civicrm_case', $caseObj->id);
406
407 //save free tags
408 if (isset($params['case_taglist']) && !empty($params['case_taglist'])) {
409 CRM_Core_Form_Tag::postProcess($params['case_taglist'], $caseObj->id, 'civicrm_case', $this);
410 }
411
412 // user context
413 $url = CRM_Utils_System::url('civicrm/contact/view/case',
414 "reset=1&action=view&cid={$this->_currentlyViewedContactId}&id={$caseObj->id}"
415 );
416 CRM_Core_Session::singleton()->pushUserContext($url);
417
418 // 3. format activity custom data
419 if (!empty($params['hidden_custom'])) {
420 $customFields = CRM_Core_BAO_CustomField::getFields('Activity', FALSE, FALSE, $this->_activityTypeId);
421 $customFields = CRM_Utils_Array::crmArrayMerge($customFields,
422 CRM_Core_BAO_CustomField::getFields('Activity', FALSE, FALSE,
423 NULL, NULL, TRUE
424 )
425 );
426 $params['custom'] = CRM_Core_BAO_CustomField::postProcess($params,
427 $this->_activityId,
428 'Activity'
429 );
430 }
431
432 // 4. call end post process
433 if ($this->_activityTypeFile) {
434 $className::endPostProcess($this, $params);
435 }
436
437 return $caseObj;
438 }
439
440 /**
441 * Process the form submission.
442 */
443 public function postProcess() {
444 $transaction = new CRM_Core_Transaction();
445
446 // check if dedupe button, if so return.
447 $buttonName = $this->controller->getButtonName();
448 if (isset($this->_dedupeButtonName) && $buttonName == $this->_dedupeButtonName) {
449 return;
450 }
451
452 if ($this->_action & CRM_Core_Action::DELETE) {
453 $caseDelete = CRM_Case_BAO_Case::deleteCase($this->_caseId, TRUE);
454 if ($caseDelete) {
455 CRM_Core_Session::setStatus(ts('You can view and / or restore deleted cases by checking the "Deleted Cases" option under Find Cases.'), ts('Case Deleted'), 'success');
456 }
457 return;
458 }
459
460 if ($this->_action & CRM_Core_Action::RENEW) {
461 $caseRestore = CRM_Case_BAO_Case::restoreCase($this->_caseId);
462 if ($caseRestore) {
463 CRM_Core_Session::setStatus(ts('The selected case has been restored.'), ts('Restored'), 'success');
464 }
465 return;
466 }
467 // store the submitted values in an array
468 $params = $this->controller->exportValues($this->_name);
469 $this->submit($params);
470
471 CRM_Core_Session::setStatus($params['statusMsg'], ts('Saved'), 'success');
472
473 }
474
475 }