3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2018 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2018
33 class CRM_Case_XMLProcessor_Process
extends CRM_Case_XMLProcessor
{
37 * @param string $caseType
38 * @param array $params
43 public function run($caseType, &$params) {
44 $xml = $this->retrieve($caseType);
47 $docLink = CRM_Utils_System
::docURL2("user/case-management/set-up");
48 CRM_Core_Error
::fatal(ts("Configuration file could not be retrieved for case type = '%1' %2.",
49 array(1 => $caseType, 2 => $docLink)
54 $xmlProcessorProcess = new CRM_Case_XMLProcessor_Process();
55 $this->_isMultiClient
= $xmlProcessorProcess->getAllowMultipleCaseClients();
57 $this->process($xml, $params);
63 * @param bool $isLabel
64 * @param bool $maskAction
66 * @return array|bool|mixed
69 public function get($caseType, $fieldSet, $isLabel = FALSE, $maskAction = FALSE) {
70 $xml = $this->retrieve($caseType);
72 $docLink = CRM_Utils_System
::docURL2("user/case-management/set-up");
73 CRM_Core_Error
::fatal(ts("Unable to load configuration file for the referenced case type: '%1' %2.",
74 array(1 => $caseType, 2 => $docLink)
81 return $this->caseRoles($xml->CaseRoles
);
84 return $this->activitySets($xml->ActivitySets
);
87 return $this->activityTypes($xml->ActivityTypes
, FALSE, $isLabel, $maskAction);
93 * @param array $params
97 public function process($xml, &$params) {
98 $standardTimeline = CRM_Utils_Array
::value('standardTimeline', $params);
99 $activitySetName = CRM_Utils_Array
::value('activitySetName', $params);
100 $activityTypeName = CRM_Utils_Array
::value('activityTypeName', $params);
102 if ('Open Case' == CRM_Utils_Array
::value('activityTypeName', $params)) {
103 // create relationships for the ones that are required
104 foreach ($xml->CaseRoles
as $caseRoleXML) {
105 foreach ($caseRoleXML->RelationshipType
as $relationshipTypeXML) {
106 if ((int ) $relationshipTypeXML->creator
== 1) {
107 if (!$this->createRelationships((string ) $relationshipTypeXML->name
,
111 CRM_Core_Error
::fatal();
119 if ('Change Case Start Date' == CRM_Utils_Array
::value('activityTypeName', $params)) {
120 // delete all existing activities which are non-empty
121 $this->deleteEmptyActivity($params);
124 foreach ($xml->ActivitySets
as $activitySetsXML) {
125 foreach ($activitySetsXML->ActivitySet
as $activitySetXML) {
126 if ($standardTimeline) {
127 if ((boolean
) $activitySetXML->timeline
) {
128 return $this->processStandardTimeline($activitySetXML,
133 elseif ($activitySetName) {
134 $name = (string ) $activitySetXML->name
;
135 if ($name == $activitySetName) {
136 return $this->processActivitySet($activitySetXML,
146 * @param $activitySetXML
147 * @param array $params
149 public function processStandardTimeline($activitySetXML, &$params) {
150 if ('Change Case Type' == CRM_Utils_Array
::value('activityTypeName', $params)
151 && CRM_Utils_Array
::value('resetTimeline', $params, TRUE)
153 // delete all existing activities which are non-empty
154 $this->deleteEmptyActivity($params);
157 foreach ($activitySetXML->ActivityTypes
as $activityTypesXML) {
158 foreach ($activityTypesXML as $activityTypeXML) {
159 $this->createActivity($activityTypeXML, $params);
165 * @param $activitySetXML
166 * @param array $params
168 public function processActivitySet($activitySetXML, &$params) {
169 foreach ($activitySetXML->ActivityTypes
as $activityTypesXML) {
170 foreach ($activityTypesXML as $activityTypeXML) {
171 $this->createActivity($activityTypeXML, $params);
177 * @param $caseRolesXML
178 * @param bool $isCaseManager
180 * @return array|mixed
182 public function &caseRoles($caseRolesXML, $isCaseManager = FALSE) {
183 $relationshipTypes = &$this->allRelationshipTypes();
186 foreach ($caseRolesXML as $caseRoleXML) {
187 foreach ($caseRoleXML->RelationshipType
as $relationshipTypeXML) {
188 $relationshipTypeName = (string ) $relationshipTypeXML->name
;
189 $relationshipTypeID = array_search($relationshipTypeName,
192 if ($relationshipTypeID === FALSE) {
196 if (!$isCaseManager) {
197 $result[$relationshipTypeID] = $relationshipTypeName;
199 elseif ($relationshipTypeXML->manager
) {
200 return $relationshipTypeID;
208 * @param string $relationshipTypeName
209 * @param array $params
214 public function createRelationships($relationshipTypeName, &$params) {
215 $relationshipTypes = &$this->allRelationshipTypes();
216 // get the relationship id
217 $relationshipTypeID = array_search($relationshipTypeName, $relationshipTypes);
219 if ($relationshipTypeID === FALSE) {
220 $docLink = CRM_Utils_System
::docURL2("user/case-management/set-up");
221 CRM_Core_Error
::fatal(ts('Relationship type %1, found in case configuration file, is not present in the database %2',
222 array(1 => $relationshipTypeName, 2 => $docLink)
227 $client = $params['clientID'];
228 if (!is_array($client)) {
229 $client = array($client);
232 foreach ($client as $key => $clientId) {
233 $relationshipParams = array(
234 'relationship_type_id' => $relationshipTypeID,
235 'contact_id_a' => $clientId,
236 'contact_id_b' => $params['creatorID'],
238 'case_id' => $params['caseID'],
239 'start_date' => date("Ymd"),
240 'end_date' => CRM_Utils_Array
::value('relationship_end_date', $params),
243 if (!$this->createRelationship($relationshipParams)) {
244 CRM_Core_Error
::fatal();
252 * @param array $params
256 public function createRelationship(&$params) {
257 $dao = new CRM_Contact_DAO_Relationship();
258 $dao->copyValues($params);
259 // only create a relationship if it does not exist
260 if (!$dao->find(TRUE)) {
267 * @param $activityTypesXML
268 * @param bool $maxInst
269 * @param bool $isLabel
270 * @param bool $maskAction
274 public function activityTypes($activityTypesXML, $maxInst = FALSE, $isLabel = FALSE, $maskAction = FALSE) {
275 $activityTypes = &$this->allActivityTypes(TRUE, TRUE);
277 foreach ($activityTypesXML as $activityTypeXML) {
278 foreach ($activityTypeXML as $recordXML) {
279 $activityTypeName = (string ) $recordXML->name
;
280 $maxInstances = (string ) $recordXML->max_instances
;
281 $activityTypeInfo = CRM_Utils_Array
::value($activityTypeName, $activityTypes);
283 if ($activityTypeInfo['id']) {
285 if ($maskAction == 'edit' && '0' === (string ) $recordXML->editable
) {
286 $result[$maskAction][] = $activityTypeInfo['id'];
291 //if we want,labels of activities should be returned.
293 $result[$activityTypeInfo['id']] = $activityTypeInfo['label'];
296 $result[$activityTypeInfo['id']] = $activityTypeName;
301 $result[$activityTypeName] = $maxInstances;
309 // call option value hook
310 CRM_Utils_Hook
::optionValues($result, 'case_activity_type');
316 * @param SimpleXMLElement $caseTypeXML
317 * @return array<string> symbolic activity-type names
319 public function getDeclaredActivityTypes($caseTypeXML) {
322 if (!empty($caseTypeXML->ActivityTypes
) && $caseTypeXML->ActivityTypes
->ActivityType
) {
323 foreach ($caseTypeXML->ActivityTypes
->ActivityType
as $activityTypeXML) {
324 $result[] = (string) $activityTypeXML->name
;
328 if (!empty($caseTypeXML->ActivitySets
) && $caseTypeXML->ActivitySets
->ActivitySet
) {
329 foreach ($caseTypeXML->ActivitySets
->ActivitySet
as $activitySetXML) {
330 if ($activitySetXML->ActivityTypes
&& $activitySetXML->ActivityTypes
->ActivityType
) {
331 foreach ($activitySetXML->ActivityTypes
->ActivityType
as $activityTypeXML) {
332 $result[] = (string) $activityTypeXML->name
;
338 $result = array_unique($result);
344 * @param SimpleXMLElement $caseTypeXML
345 * @return array<string> symbolic relationship-type names
347 public function getDeclaredRelationshipTypes($caseTypeXML) {
350 if (!empty($caseTypeXML->CaseRoles
) && $caseTypeXML->CaseRoles
->RelationshipType
) {
351 foreach ($caseTypeXML->CaseRoles
->RelationshipType
as $relTypeXML) {
352 $result[] = (string) $relTypeXML->name
;
356 $result = array_unique($result);
362 * @param array $params
364 public function deleteEmptyActivity(&$params) {
365 $activityContacts = CRM_Activity_BAO_ActivityContact
::buildOptions('record_type_id', 'validate');
366 $targetID = CRM_Utils_Array
::key('Activity Targets', $activityContacts);
370 FROM civicrm_activity a
371 INNER JOIN civicrm_activity_contact t ON t.activity_id = a.id
372 INNER JOIN civicrm_case_activity ca on ca.activity_id = a.id
373 WHERE t.contact_id = %1
374 AND t.record_type_id = $targetID
376 AND a.is_current_revision = 1
379 $sqlParams = array(1 => array($params['clientID'], 'Integer'), 2 => array($params['caseID'], 'Integer'));
380 CRM_Core_DAO
::executeQuery($query, $sqlParams);
384 * @param array $params
388 public function isActivityPresent(&$params) {
391 FROM civicrm_activity a
392 INNER JOIN civicrm_case_activity ca on ca.activity_id = a.id
393 WHERE a.activity_type_id = %1
399 1 => array($params['activityTypeID'], 'Integer'),
400 2 => array($params['caseID'], 'Integer'),
402 $count = CRM_Core_DAO
::singleValueQuery($query, $sqlParams);
404 // check for max instance
405 $caseType = CRM_Case_BAO_Case
::getCaseType($params['caseID'], 'name');
406 $maxInstance = self
::getMaxInstance($caseType, $params['activityTypeName']);
408 return $maxInstance ?
($count < $maxInstance ?
FALSE : TRUE) : FALSE;
412 * @param $activityTypeXML
413 * @param array $params
416 * @throws CRM_Core_Exception
419 public function createActivity($activityTypeXML, &$params) {
420 $activityTypeName = (string) $activityTypeXML->name
;
421 $activityTypes = &$this->allActivityTypes(TRUE, TRUE);
422 $activityTypeInfo = CRM_Utils_Array
::value($activityTypeName, $activityTypes);
424 if (!$activityTypeInfo) {
425 $docLink = CRM_Utils_System
::docURL2("user/case-management/set-up");
426 CRM_Core_Error
::fatal(ts('Activity type %1, found in case configuration file, is not present in the database %2',
427 array(1 => $activityTypeName, 2 => $docLink)
432 $activityTypeID = $activityTypeInfo['id'];
434 if (isset($activityTypeXML->status
)) {
435 $statusName = (string) $activityTypeXML->status
;
438 $statusName = 'Scheduled';
441 $client = (array) $params['clientID'];
445 if (isset($activityTypeXML->order
)) {
446 $orderVal = (string) $activityTypeXML->order
;
449 if ($activityTypeName == 'Open Case') {
450 $activityParams = array(
451 'activity_type_id' => $activityTypeID,
452 'source_contact_id' => $params['creatorID'],
454 'is_current_revision' => 1,
455 'subject' => CRM_Utils_Array
::value('subject', $params) ?
$params['subject'] : $activityTypeName,
456 'status_id' => CRM_Core_PseudoConstant
::getKey('CRM_Activity_BAO_Activity', 'activity_status_id', $statusName),
457 'target_contact_id' => $client,
458 'medium_id' => CRM_Utils_Array
::value('medium_id', $params),
459 'location' => CRM_Utils_Array
::value('location', $params),
460 'details' => CRM_Utils_Array
::value('details', $params),
461 'duration' => CRM_Utils_Array
::value('duration', $params),
462 'weight' => $orderVal,
466 $activityParams = array(
467 'activity_type_id' => $activityTypeID,
468 'source_contact_id' => $params['creatorID'],
470 'is_current_revision' => 1,
471 'status_id' => CRM_Core_PseudoConstant
::getKey('CRM_Activity_BAO_Activity', 'activity_status_id', $statusName),
472 'target_contact_id' => $client,
473 'weight' => $orderVal,
477 //parsing date to default preference format
478 $params['activity_date_time'] = CRM_Utils_Date
::processDate($params['activity_date_time']);
480 if ($activityTypeName == 'Open Case') {
481 // we don't set activity_date_time for auto generated
482 // activities, but we want it to be set for open case.
483 $activityParams['activity_date_time'] = $params['activity_date_time'];
484 if (array_key_exists('custom', $params) && is_array($params['custom'])) {
485 $activityParams['custom'] = $params['custom'];
488 // Add parameters for attachments
490 $numAttachments = Civi
::settings()->get('max_attachments');
491 for ($i = 1; $i <= $numAttachments; $i++
) {
492 $attachName = "attachFile_$i";
493 if (isset($params[$attachName]) && !empty($params[$attachName])) {
494 $activityParams[$attachName] = $params[$attachName];
499 $activityDate = NULL;
500 //get date of reference activity if set.
501 if ($referenceActivityName = (string) $activityTypeXML->reference_activity
) {
503 //we skip open case as reference activity.CRM-4374.
504 if (!empty($params['resetTimeline']) && $referenceActivityName == 'Open Case') {
505 $activityDate = $params['activity_date_time'];
508 $referenceActivityInfo = CRM_Utils_Array
::value($referenceActivityName, $activityTypes);
509 if ($referenceActivityInfo['id']) {
510 $caseActivityParams = array('activity_type_id' => $referenceActivityInfo['id']);
512 //if reference_select is set take according activity.
513 if ($referenceSelect = (string) $activityTypeXML->reference_select
) {
514 $caseActivityParams[$referenceSelect] = 1;
517 $referenceActivity = CRM_Case_BAO_Case
::getCaseActivityDates($params['caseID'], $caseActivityParams, TRUE);
519 if (is_array($referenceActivity)) {
520 foreach ($referenceActivity as $aId => $details) {
521 $activityDate = CRM_Utils_Array
::value('activity_date', $details);
528 if (!$activityDate) {
529 $activityDate = $params['activity_date_time'];
531 list($activity_date, $activity_time) = CRM_Utils_Date
::setDateDefaults($activityDate);
532 $activityDateTime = CRM_Utils_Date
::processDate($activity_date, $activity_time);
533 //add reference offset to date.
534 if ((int) $activityTypeXML->reference_offset
) {
535 $activityDateTime = CRM_Utils_Date
::intervalAdd('day', (int) $activityTypeXML->reference_offset
,
540 $activityParams['activity_date_time'] = CRM_Utils_Date
::format($activityDateTime);
543 // if same activity is already there, skip and dont touch
544 $params['activityTypeID'] = $activityTypeID;
545 $params['activityTypeName'] = $activityTypeName;
546 if ($this->isActivityPresent($params)) {
549 $activityParams['case_id'] = $params['caseID'];
550 if (!empty($activityParams['is_auto'])) {
551 $activityParams['skipRecentView'] = TRUE;
554 // @todo - switch to using api & remove the parameter pre-wrangling above.
555 $activity = CRM_Activity_BAO_Activity
::create($activityParams);
558 CRM_Core_Error
::fatal();
562 // create case activity record
564 'activity_id' => $activity->id
,
565 'case_id' => $params['caseID'],
567 CRM_Case_BAO_Case
::processCaseActivity($caseParams);
572 * @param $activitySetsXML
576 public static function activitySets($activitySetsXML) {
578 foreach ($activitySetsXML as $activitySetXML) {
579 foreach ($activitySetXML as $recordXML) {
580 $activitySetName = (string ) $recordXML->name
;
581 $activitySetLabel = (string ) $recordXML->label
;
582 $result[$activitySetName] = $activitySetLabel;
591 * @param null $activityTypeName
593 * @return array|bool|mixed
596 public function getMaxInstance($caseType, $activityTypeName = NULL) {
597 $xml = $this->retrieve($caseType);
599 if ($xml === FALSE) {
600 CRM_Core_Error
::fatal();
604 $activityInstances = $this->activityTypes($xml->ActivityTypes
, TRUE);
605 return $activityTypeName ? CRM_Utils_Array
::value($activityTypeName, $activityInstances) : $activityInstances;
611 * @return array|mixed
613 public function getCaseManagerRoleId($caseType) {
614 $xml = $this->retrieve($caseType);
615 return $this->caseRoles($xml->CaseRoles
, TRUE);
619 * @param string $caseType
620 * @return array<\Civi\CCase\CaseChangeListener>
622 public function getListeners($caseType) {
623 $xml = $this->retrieve($caseType);
624 $listeners = array();
625 if ($xml->Listeners
&& $xml->Listeners
->Listener
) {
626 foreach ($xml->Listeners
->Listener
as $listenerXML) {
627 $class = (string) $listenerXML;
628 $listeners[] = new $class();
637 public function getRedactActivityEmail() {
638 return $this->getBoolSetting('civicaseRedactActivityEmail', 'RedactActivityEmail');
642 * Retrieves AllowMultipleCaseClients setting.
645 * 1 if allowed, 0 if not
647 public function getAllowMultipleCaseClients() {
648 return $this->getBoolSetting('civicaseAllowMultipleClients', 'AllowMultipleCaseClients');
652 * Retrieves NaturalActivityTypeSort setting.
655 * 1 if natural, 0 if alphabetic
657 public function getNaturalActivityTypeSort() {
658 return $this->getBoolSetting('civicaseNaturalActivityTypeSort', 'NaturalActivityTypeSort');
662 * @param string $settingKey
663 * @param string $xmlTag
664 * @param mixed $default
667 private function getBoolSetting($settingKey, $xmlTag, $default = 0) {
668 $setting = Civi
::settings()->get($settingKey);
669 if ($setting !== 'default') {
670 return (int) $setting;
672 if ($xml = $this->retrieve("Settings")) {
673 return (string) $xml->{$xmlTag} ?
1 : 0;