Case Type refactoring
[civicrm-core.git] / CRM / Case / XMLProcessor / Process.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
06b69b18 4 | CiviCRM version 4.5 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
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
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35class CRM_Case_XMLProcessor_Process extends CRM_Case_XMLProcessor {
36 function run($caseType, &$params) {
37 $xml = $this->retrieve($caseType);
38
39 if ($xml === FALSE) {
40 $docLink = CRM_Utils_System::docURL2("user/case-management/setup");
41 CRM_Core_Error::fatal(ts("Configuration file could not be retrieved for case type = '%1' %2.",
42 array(1 => $caseType, 2 => $docLink)
43 ));
44 return FALSE;
45 }
46
47 $xmlProcessorProcess = new CRM_Case_XMLProcessor_Process();
48 $this->_isMultiClient = $xmlProcessorProcess->getAllowMultipleCaseClients();
49
50 $this->process($xml, $params);
51 }
52
53 function get($caseType, $fieldSet, $isLabel = FALSE, $maskAction = FALSE) {
54 $xml = $this->retrieve($caseType);
55 if ($xml === FALSE) {
56 $docLink = CRM_Utils_System::docURL2("user/case-management/setup");
57 CRM_Core_Error::fatal(ts("Unable to load configuration file for the referenced case type: '%1' %2.",
58 array(1 => $caseType, 2 => $docLink)
59 ));
60 return FALSE;
61 }
62
63 switch ($fieldSet) {
64 case 'CaseRoles':
65 return $this->caseRoles($xml->CaseRoles);
66
67 case 'ActivitySets':
68 return $this->activitySets($xml->ActivitySets);
69
70 case 'ActivityTypes':
71 return $this->activityTypes($xml->ActivityTypes, FALSE, $isLabel, $maskAction);
72 }
73 }
74
75 function process($xml, &$params) {
76 $standardTimeline = CRM_Utils_Array::value('standardTimeline', $params);
77 $activitySetName = CRM_Utils_Array::value('activitySetName', $params);
78 $activityTypeName = CRM_Utils_Array::value('activityTypeName', $params);
79
80 if ('Open Case' == CRM_Utils_Array::value('activityTypeName', $params)) {
81 // create relationships for the ones that are required
82 foreach ($xml->CaseRoles as $caseRoleXML) {
83 foreach ($caseRoleXML->RelationshipType as $relationshipTypeXML) {
84 if ((int ) $relationshipTypeXML->creator == 1) {
85 if (!$this->createRelationships((string ) $relationshipTypeXML->name,
86 $params
87 )) {
88 CRM_Core_Error::fatal();
89 return FALSE;
90 }
91 }
92 }
93 }
94 }
95
96 if ('Change Case Start Date' == CRM_Utils_Array::value('activityTypeName', $params)) {
97 // delete all existing activities which are non-empty
98 $this->deleteEmptyActivity($params);
99 }
100
101 foreach ($xml->ActivitySets as $activitySetsXML) {
102 foreach ($activitySetsXML->ActivitySet as $activitySetXML) {
103 if ($standardTimeline) {
104 if ((boolean ) $activitySetXML->timeline) {
105 return $this->processStandardTimeline($activitySetXML,
106 $params
107 );
108 }
109 }
110 elseif ($activitySetName) {
111 $name = (string ) $activitySetXML->name;
112 if ($name == $activitySetName) {
113 return $this->processActivitySet($activitySetXML,
114 $params
115 );
116 }
117 }
118 }
119 }
120 }
121
122 function processStandardTimeline($activitySetXML, &$params) {
448e7600
PJ
123 if ('Change Case Type' == CRM_Utils_Array::value('activityTypeName', $params)
124 && CRM_Utils_Array::value('resetTimeline', $params, TRUE)) {
6a488035
TO
125 // delete all existing activities which are non-empty
126 $this->deleteEmptyActivity($params);
127 }
128
129 foreach ($activitySetXML->ActivityTypes as $activityTypesXML) {
130 foreach ($activityTypesXML as $activityTypeXML) {
131 $this->createActivity($activityTypeXML, $params);
132 }
133 }
134 }
135
136 function processActivitySet($activitySetXML, &$params) {
137 foreach ($activitySetXML->ActivityTypes as $activityTypesXML) {
138 foreach ($activityTypesXML as $activityTypeXML) {
139 $this->createActivity($activityTypeXML, $params);
140 }
141 }
142 }
143
144 function &caseRoles($caseRolesXML, $isCaseManager = FALSE) {
145 $relationshipTypes = &$this->allRelationshipTypes();
146
147 $result = array();
148 foreach ($caseRolesXML as $caseRoleXML) {
149 foreach ($caseRoleXML->RelationshipType as $relationshipTypeXML) {
150 $relationshipTypeName = (string ) $relationshipTypeXML->name;
151 $relationshipTypeID = array_search($relationshipTypeName,
152 $relationshipTypes
153 );
154 if ($relationshipTypeID === FALSE) {
155 continue;
156 }
157
158 if (!$isCaseManager) {
159 $result[$relationshipTypeID] = $relationshipTypeName;
160 }
161 elseif ($relationshipTypeXML->manager) {
162 return $relationshipTypeID;
163 }
164 }
165 }
166 return $result;
167 }
168
169 function createRelationships($relationshipTypeName, &$params) {
170 $relationshipTypes = &$this->allRelationshipTypes();
171 // get the relationship id
172 $relationshipTypeID = array_search($relationshipTypeName, $relationshipTypes);
173
174 if ($relationshipTypeID === FALSE) {
175 $docLink = CRM_Utils_System::docURL2("user/case-management/setup");
176 CRM_Core_Error::fatal(ts('Relationship type %1, found in case configuration file, is not present in the database %2',
177 array(1 => $relationshipTypeName, 2 => $docLink)
178 ));
179 return FALSE;
180 }
181
182 $client = $params['clientID'];
183 if (!is_array($client)) {
184 $client = array($client);
185 }
186
187 foreach ($client as $key => $clientId) {
188 $relationshipParams = array(
189 'relationship_type_id' => $relationshipTypeID,
190 'contact_id_a' => $clientId,
191 'contact_id_b' => $params['creatorID'],
192 'is_active' => 1,
193 'case_id' => $params['caseID'],
194 'start_date' => date("Ymd"),
195 );
196
197 if (!$this->createRelationship($relationshipParams)) {
198 CRM_Core_Error::fatal();
199 return FALSE;
200 }
201 }
202 return TRUE;
203 }
204
205 function createRelationship(&$params) {
206 $dao = new CRM_Contact_DAO_Relationship();
207 $dao->copyValues($params);
208 // only create a relationship if it does not exist
209 if (!$dao->find(TRUE)) {
210 $dao->save();
211 }
212 return TRUE;
213 }
214
215 function activityTypes($activityTypesXML, $maxInst = FALSE, $isLabel = FALSE, $maskAction = FALSE) {
216 $activityTypes = &$this->allActivityTypes(TRUE, TRUE);
217 $result = array();
218 foreach ($activityTypesXML as $activityTypeXML) {
219 foreach ($activityTypeXML as $recordXML) {
220 $activityTypeName = (string ) $recordXML->name;
221 $maxInstances = (string ) $recordXML->max_instances;
222 $activityTypeInfo = CRM_Utils_Array::value($activityTypeName, $activityTypes);
223
224 if ($activityTypeInfo['id']) {
225 if ($maskAction) {
226 if ($maskAction == 'edit' && '0' === (string ) $recordXML->editable) {
227 $result[$maskAction][] = $activityTypeInfo['id'];
228 }
229 }
230 else {
231 if (!$maxInst) {
232 //if we want,labels of activities should be returned.
233 if ($isLabel) {
234 $result[$activityTypeInfo['id']] = $activityTypeInfo['label'];
235 }
236 else {
237 $result[$activityTypeInfo['id']] = $activityTypeName;
238 }
239 }
240 else {
241 if ($maxInstances) {
242 $result[$activityTypeName] = $maxInstances;
243 }
244 }
245 }
246 }
247 }
248 }
249
250 // call option value hook
251 CRM_Utils_Hook::optionValues($result, 'case_activity_type');
252
253 return $result;
254 }
255
256 function deleteEmptyActivity(&$params) {
e7e657f0 257 $activityContacts = CRM_Core_OptionGroup::values('activity_contacts', FALSE, FALSE, FALSE, NULL, 'name');
9e74e3ce 258 $targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
8ef12e64 259
6a488035
TO
260 $query = "
261DELETE a
262FROM civicrm_activity a
91da6cd5
DL
263INNER JOIN civicrm_activity_contact t ON t.activity_id = a.id
264WHERE t.contact_id = %1
9e74e3ce 265AND t.record_type_id = $targetID
6a488035
TO
266AND a.is_auto = 1
267AND a.is_current_revision = 1
268";
269 $sqlParams = array(1 => array($params['clientID'], 'Integer'));
270 CRM_Core_DAO::executeQuery($query, $sqlParams);
271 }
272
273 function isActivityPresent(&$params) {
274 $query = "
275SELECT count(a.id)
276FROM civicrm_activity a
277INNER JOIN civicrm_case_activity ca on ca.activity_id = a.id
278WHERE a.activity_type_id = %1
279AND ca.case_id = %2
280AND a.is_deleted = 0
281";
282
283 $sqlParams = array(1 => array($params['activityTypeID'], 'Integer'),
284 2 => array($params['caseID'], 'Integer'),
285 );
286 $count = CRM_Core_DAO::singleValueQuery($query, $sqlParams);
287
288 // check for max instance
8ffdec17 289 $caseType = CRM_Case_BAO_Case::getCaseType($params['caseID'], 'title');
6a488035
TO
290 $maxInstance = self::getMaxInstance($caseType, $params['activityTypeName']);
291
292 return $maxInstance ? ($count < $maxInstance ? FALSE : TRUE) : FALSE;
293 }
294
295 function createActivity($activityTypeXML, &$params) {
296 $activityTypeName = (string) $activityTypeXML->name;
297 $activityTypes = &$this->allActivityTypes(TRUE, TRUE);
298 $activityTypeInfo = CRM_Utils_Array::value($activityTypeName, $activityTypes);
299
300 if (!$activityTypeInfo) {
301 $docLink = CRM_Utils_System::docURL2("user/case-management/setup");
302 CRM_Core_Error::fatal(ts('Activity type %1, found in case configuration file, is not present in the database %2',
303 array(1 => $activityTypeName, 2 => $docLink)
304 ));
305 return FALSE;
306 }
307
308 $activityTypeID = $activityTypeInfo['id'];
309
310 if (isset($activityTypeXML->status)) {
311 $statusName = (string) $activityTypeXML->status;
312 }
313 else {
314 $statusName = 'Scheduled';
315 }
316
317 if ($this->_isMultiClient) {
318 $client = $params['clientID'];
319 }
320 else {
321 $client = array(1 => $params['clientID']);
322 }
323
324 //set order
325 $orderVal = '';
326 if (isset($activityTypeXML->order)) {
327 $orderVal = (string) $activityTypeXML->order;
328 }
329
330 if ($activityTypeName == 'Open Case') {
331 $activityParams = array(
332 'activity_type_id' => $activityTypeID,
333 'source_contact_id' => $params['creatorID'],
334 'is_auto' => FALSE,
335 'is_current_revision' => 1,
336 'subject' => CRM_Utils_Array::value('subject', $params) ? $params['subject'] : $activityTypeName,
337 'status_id' => CRM_Core_OptionGroup::getValue('activity_status',
338 $statusName,
339 'name'
340 ),
341 'target_contact_id' => $client,
342 'medium_id' => CRM_Utils_Array::value('medium_id', $params),
343 'location' => CRM_Utils_Array::value('location', $params),
344 'details' => CRM_Utils_Array::value('details', $params),
345 'duration' => CRM_Utils_Array::value('duration', $params),
346 'weight' => $orderVal,
347 );
348 }
349 else {
350 $activityParams = array(
351 'activity_type_id' => $activityTypeID,
352 'source_contact_id' => $params['creatorID'],
353 'is_auto' => TRUE,
354 'is_current_revision' => 1,
355 'status_id' => CRM_Core_OptionGroup::getValue('activity_status',
356 $statusName,
357 'name'
358 ),
359 'target_contact_id' => $client,
360 'weight' => $orderVal,
361 );
362 }
363
364 //parsing date to default preference format
365 $params['activity_date_time'] = CRM_Utils_Date::processDate($params['activity_date_time']);
366
367 if ($activityTypeName == 'Open Case') {
368 // we don't set activity_date_time for auto generated
369 // activities, but we want it to be set for open case.
370 $activityParams['activity_date_time'] = $params['activity_date_time'];
371 if (array_key_exists('custom', $params) && is_array($params['custom'])) {
372 $activityParams['custom'] = $params['custom'];
373 }
374
375 // Add parameters for attachments
376
377 $numAttachments = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'max_attachments');
378 for ( $i = 1; $i <= $numAttachments; $i++ ) {
379 $attachName = "attachFile_$i";
380 if ( isset( $params[$attachName] ) && !empty( $params[$attachName] ) ) {
381 $activityParams[$attachName] = $params[$attachName];
382 }
383 }
384 }
385 else {
386 $activityDate = NULL;
387 //get date of reference activity if set.
388 if ($referenceActivityName = (string) $activityTypeXML->reference_activity) {
389
390 //we skip open case as reference activity.CRM-4374.
a7488080 391 if (!empty($params['resetTimeline']) && $referenceActivityName == 'Open Case') {
6a488035
TO
392 $activityDate = $params['activity_date_time'];
393 }
394 else {
395 $referenceActivityInfo = CRM_Utils_Array::value($referenceActivityName, $activityTypes);
396 if ($referenceActivityInfo['id']) {
397 $caseActivityParams = array('activity_type_id' => $referenceActivityInfo['id']);
398
399 //if reference_select is set take according activity.
400 if ($referenceSelect = (string) $activityTypeXML->reference_select) {
401 $caseActivityParams[$referenceSelect] = 1;
402 }
403
404 $referenceActivity = CRM_Case_BAO_Case::getCaseActivityDates($params['caseID'], $caseActivityParams, TRUE);
405
406 if (is_array($referenceActivity)) {
407 foreach ($referenceActivity as $aId => $details) {
408 $activityDate = CRM_Utils_Array::value('activity_date', $details);
409 break;
410 }
411 }
412 }
413 }
414 }
415 if (!$activityDate) {
416 $activityDate = $params['activity_date_time'];
417 }
418 list($activity_date, $activity_time) = CRM_Utils_Date::setDateDefaults($activityDate);
419 $activityDateTime = CRM_Utils_Date::processDate($activity_date, $activity_time);
420 //add reference offset to date.
421 if ((int) $activityTypeXML->reference_offset) {
422 $activityDateTime = CRM_Utils_Date::intervalAdd('day', (int) $activityTypeXML->reference_offset,
423 $activityDateTime
424 );
425 }
426
427 $activityParams['activity_date_time'] = CRM_Utils_Date::format($activityDateTime);
428 }
429
430 // if same activity is already there, skip and dont touch
431 $params['activityTypeID'] = $activityTypeID;
432 $params['activityTypeName'] = $activityTypeName;
433 if ($this->isActivityPresent($params)) {
434 return TRUE;
435 }
436 $activityParams['case_id'] = $params['caseID'];
a7488080 437 if (!empty($activityParams['is_auto'])) {
6a488035
TO
438 $activityParams['skipRecentView'] = TRUE;
439 }
440
441 $activity = CRM_Activity_BAO_Activity::create($activityParams);
442
443 if (!$activity) {
444 CRM_Core_Error::fatal();
445 return FALSE;
446 }
447
448 // create case activity record
449 $caseParams = array(
450 'activity_id' => $activity->id,
451 'case_id' => $params['caseID'],
452 );
453 CRM_Case_BAO_Case::processCaseActivity($caseParams);
454 return TRUE;
455 }
456
916bdc36 457 static function activitySets($activitySetsXML) {
6a488035
TO
458 $result = array();
459 foreach ($activitySetsXML as $activitySetXML) {
460 foreach ($activitySetXML as $recordXML) {
461 $activitySetName = (string ) $recordXML->name;
462 $activitySetLabel = (string ) $recordXML->label;
463 $result[$activitySetName] = $activitySetLabel;
464 }
465 }
466
467 return $result;
468 }
469
470 function getMaxInstance($caseType, $activityTypeName = NULL) {
471 $xml = $this->retrieve($caseType);
472
473 if ($xml === FALSE) {
474 CRM_Core_Error::fatal();
475 return FALSE;
476 }
477
478 $activityInstances = $this->activityTypes($xml->ActivityTypes, TRUE);
479 return $activityTypeName ? CRM_Utils_Array::value($activityTypeName, $activityInstances) : $activityInstances;
480 }
481
482 function getCaseManagerRoleId($caseType) {
483 $xml = $this->retrieve($caseType);
484 return $this->caseRoles($xml->CaseRoles, TRUE);
485 }
486
487 function getRedactActivityEmail() {
488 $xml = $this->retrieve("Settings");
489 return ( string ) $xml->RedactActivityEmail ? 1 : 0;
490 }
491
492 /**
493 * Retrieves AllowMultipleCaseClients setting
494 *
495 * @return string 1 if allowed, 0 if not
496 */
497 function getAllowMultipleCaseClients() {
498 $xml = $this->retrieve("Settings");
499 if ($xml) {
500 return ( string ) $xml->AllowMultipleCaseClients ? 1 : 0;
501 }
502 return 0;
503 }
504
505 /**
506 * Retrieves NaturalActivityTypeSort setting
507 *
508 * @return string 1 if natural, 0 if alphabetic
509 */
510 function getNaturalActivityTypeSort() {
511 $xml = $this->retrieve("Settings");
512 return ( string ) $xml->NaturalActivityTypeSort ? 1 : 0;
513 }
514}
515