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