1<?php 2 3use dokuwiki\Extension\Plugin; 4use dokuwiki\Extension\AuthPlugin; 5use dokuwiki\plugin\structpublish\meta\Assignments; 6use dokuwiki\plugin\structpublish\meta\Constants; 7use dokuwiki\plugin\structpublish\meta\Revision; 8 9/** 10 * Notification helper 11 */ 12class helper_plugin_structpublish_notify extends Plugin 13{ 14 /** @var helper_plugin_structpublish_db */ 15 protected $dbHelper; 16 17 public function __construct() 18 { 19 $this->dbHelper = plugin_load('helper', 'structpublish_db'); 20 } 21 22 /** 23 * If activated, send emails on configured status changes. 24 * 25 * @param string $action 26 * @param Revision $newRevision 27 * @return void 28 * @throws Exception 29 */ 30 public function sendEmails($action, $newRevision) 31 { 32 33 if (!$this->triggerNotification($action)) { 34 return; 35 } 36 37 // get assignees from DB 38 $assignments = Assignments::getInstance(); 39 $assignees = $assignments->getPageAssignments($newRevision->getId(), false); 40 41 // get recipients for the next workflow step 42 $nextAction = Constants::workflowSteps($action)['nextAction']; 43 if (is_null($nextAction)) { 44 return; 45 } 46 47 if (empty($assignees[$nextAction])) { 48 msg($this->getLang('email_error_norecipients'), -1); 49 return; 50 } 51 52 // flatten the array and split into single user or group items 53 $assignees = implode(',', array_values($assignees[$nextAction])); 54 $assignees = explode(',', $assignees); 55 56 // get recipient emails 57 $recipients = $this->resolveRecipients($assignees); 58 59 // prepare mail text 60 $mailText = $this->prepareMailText($newRevision->getStatus()); 61 62 $this->sendMail(implode(',', $recipients), $mailText); 63 } 64 65 /** 66 * @param string $recipients Comma separated list of emails 67 * @param string $mailText 68 * @return void 69 */ 70 public function sendMail($recipients, $mailText) 71 { 72 $mailer = new Mailer(); 73 $mailer->bcc($recipients); 74 75 $subject = $this->getLang('email_subject'); 76 $mailer->subject($subject); 77 78 $mailer->setBody($mailText); 79 $mailer->send(); 80 } 81 82 /** 83 * Processes an array of (comma separated) recipients 84 * and returns an array of emails 85 * with user groups resolved to individual users 86 * 87 * @param array $recipients 88 * @return array 89 * @throws Exception 90 */ 91 public function resolveRecipients($recipients) 92 { 93 $resolved = []; 94 95 $recipients = array_unique($recipients); 96 97 foreach ($recipients as $recipient) { 98 $recipient = trim($recipient); 99 100 if ($recipient[0] === '@') { 101 $this->resolveGroup($resolved, $recipient); 102 } elseif (strpos($recipient, '@') === false) { 103 $this->resolveUser($resolved, $recipient); 104 } else { 105 $resolved[] = $recipient; 106 } 107 } 108 return $resolved; 109 } 110 111 /** 112 * @param array $resolved 113 * @param string $recipient 114 * @return void 115 * @throws Exception 116 */ 117 protected function resolveGroup(&$resolved, $recipient) 118 { 119 /** @var AuthPlugin $auth */ 120 global $auth; 121 if (!$auth->canDo('getUsers')) { 122 throw new \Exception('Auth cannot fetch users by group.'); 123 } 124 125 // set arbitrary limit because not all backends interpret limit 0 as "no limit" 126 $users = $auth->retrieveUsers(0, 5000, ['grps' => substr($recipient, 1)]); 127 foreach ($users as $user) { 128 $resolved[] = $user['mail']; 129 } 130 } 131 132 /** 133 * @param array $resolved 134 * @param string $recipient 135 * @return void 136 */ 137 protected function resolveUser(&$resolved, $recipient) 138 { 139 /** @var AuthPlugin $auth */ 140 global $auth; 141 $user = $auth->getUserData($recipient); 142 if ($user) { 143 $resolved[] = $user['mail']; 144 } 145 } 146 147 /** 148 * Check configuration to see if a notification should be triggered. 149 * 150 * @return bool 151 */ 152 private function triggerNotification($action) 153 { 154 if (!$this->getConf('email_enable')) { 155 return false; 156 } 157 158 $actions = array_map('trim', explode(',', $this->getConf('email_status'))); 159 return in_array($action, $actions); 160 } 161 162 /** 163 * @return string 164 */ 165 protected function prepareMailText($status) 166 { 167 global $ID; 168 169 $mailtext = file_get_contents($this->localFN('mail')); 170 171 $vars = [ 172 'PAGE' => $ID, 173 'URL' => wl($ID, '', true), 174 'STATUS_CURRENT' => $status, 175 ]; 176 177 foreach ($vars as $var => $val) { 178 $mailtext = str_replace('@' . $var . '@', $val, $mailtext); 179 } 180 181 return $mailtext; 182 } 183} 184