Merge pull request #3367 from kirkatcaat/empty-labels-on-profile-fields
[civicrm-core.git] / Civi / CCase / SequenceListener.php
1 <?php
2 namespace Civi\CCase;
3
4 /**
5 * The sequence-listener looks for CiviCase XML tags with "<sequence>". If
6 * a change is made to any record in case-type which uses "<sequence>", then
7 * it attempts to add the next step in the sequence.
8 */
9 class SequenceListener implements CaseChangeListener {
10
11 /**
12 * @var SequenceListener
13 */
14 private static $singleton;
15
16 /**
17 * @param bool $reset whether to forcibly rebuild the entire container
18 * @return \Symfony\Component\DependencyInjection\TaggedContainerInterface
19 */
20 public static function singleton($reset = FALSE) {
21 if ($reset || self::$singleton === NULL) {
22 self::$singleton = new SequenceListener();
23 }
24 return self::$singleton;
25 }
26
27 public static function onCaseChange_static(\Civi\CCase\Event\CaseChangeEvent $event) {
28 self::singleton()->onCaseChange($event);
29 }
30
31 public function onCaseChange(\Civi\CCase\Event\CaseChangeEvent $event) {
32 /** @var \Civi\CCase\Analyzer $analyzer */
33 $analyzer = $event->analyzer;
34
35 $activitySetXML = $this->getSequenceXml($analyzer->getXml());
36 if (!$activitySetXML) {
37 return;
38 }
39
40 $actTypes = array_flip(\CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'name'));
41 $actStatuses = array_flip(\CRM_Core_PseudoConstant::activityStatus('name'));
42
43 $actIndex = $analyzer->getActivityIndex(array('activity_type_id', 'status_id'));
44
45 foreach ($activitySetXML->ActivityTypes->ActivityType as $actTypeXML) {
46 $actTypeId = $actTypes[(string) $actTypeXML->name];
47 if (empty($actIndex[$actTypeId])) {
48 // Haven't tried this step yet!
49 $this->createActivity($analyzer, $actTypeXML);
50 return;
51 }
52 elseif (empty($actIndex[$actTypeId][$actStatuses['Completed']])) {
53 // Haven't gotten past this step yet!
54 return;
55 }
56 }
57
58 // OK, the activity has completed every step in the sequence!
59 civicrm_api3('Case', 'create', array(
60 'id' => $analyzer->getCaseId(),
61 'status_id' => 'Closed',
62 ));
63 $analyzer->flush();
64 }
65
66 /**
67 * Find the ActivitySet which defines the pipeline.
68 *
69 * @param \SimpleXMLElement $xml
70 * @return \SimpleXMLElement|NULL
71 */
72 public function getSequenceXml($xml) {
73 if ($xml->ActivitySets && $xml->ActivitySets->ActivitySet) {
74 foreach ($xml->ActivitySets->ActivitySet as $activitySetXML) {
75 $seq = (string) $activitySetXML->sequence;
76 if ($seq && strtolower($seq) == 'true') {
77 if ($activitySetXML->ActivityTypes && $activitySetXML->ActivityTypes->ActivityType) {
78 return $activitySetXML;
79 }
80 else {
81 return NULL;
82 }
83 }
84 }
85 }
86 return NULL;
87 }
88
89 /**
90 * @param Analyzer $analyzer the case being analyzed -- to which we want to add an activity
91 * @param \SimpleXMLElement $actXML the <ActivityType> tag which describes the new activity
92 */
93 public function createActivity(Analyzer $analyzer, \SimpleXMLElement $actXML) {
94 $params = array(
95 'activity_type_id' => (string) $actXML->name,
96 'status_id' => 'Scheduled',
97 'activity_date_time' => \CRM_Utils_Time::getTime('YmdHis'),
98 'case_id' => $analyzer->getCaseId(),
99 );
100 $r = civicrm_api3('Activity', 'create', $params);
101 $analyzer->flush();
102 }
103 }