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