Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
232624b1 | 4 | | CiviCRM version 4.4 | |
6a488035 TO |
5 | +--------------------------------------------------------------------+ |
6 | | Copyright CiviCRM LLC (c) 2004-2013 | | |
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-2013 | |
32 | * $Id$ | |
33 | * | |
34 | */ | |
35 | class 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 = " |
261 | DELETE a | |
262 | FROM civicrm_activity a | |
91da6cd5 DL |
263 | INNER JOIN civicrm_activity_contact t ON t.activity_id = a.id |
264 | WHERE t.contact_id = %1 | |
9e74e3ce | 265 | AND t.record_type_id = $targetID |
6a488035 TO |
266 | AND a.is_auto = 1 |
267 | AND 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 = " | |
275 | SELECT count(a.id) | |
276 | FROM civicrm_activity a | |
277 | INNER JOIN civicrm_case_activity ca on ca.activity_id = a.id | |
278 | WHERE a.activity_type_id = %1 | |
279 | AND ca.case_id = %2 | |
280 | AND 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 | |
289 | $caseType = CRM_Case_BAO_Case::getCaseType($params['caseID'], 'name'); | |
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. | |
391 | if (CRM_Utils_Array::value('resetTimeline', $params) && $referenceActivityName == 'Open Case') { | |
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']; | |
437 | if (CRM_Utils_Array::value('is_auto', $activityParams)) { | |
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 | ||
457 | function activitySets($activitySetsXML) { | |
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 |