* */ namespace dokuwiki\plugin\structtasks\meta; /** * Abstract base class to handle sending emails about changes to task * state. Each subclass will provide a function which returns a list * of users to be notified (empty if no notification is required) and * template text for the email message. * * @package dokuwiki\plugin\structtasks\meta * */ abstract class AbstractNotifier { /** * First part of keys in the localisation files, corresponding to * content of emails. The following keys are expected to be * present: `PREFIX_subject` (email subject), `PREFIX_text` * (plain-text email content), and `PREFIX_html` (HTML email * content). * * The text of these localisations can make use of the following * macros: * * - @TITLE@ * - @TITLELINK@ * - @EDITURL@ * - @EDITOR@ * - @STATUS@ * - @PREVSTATUS@ * - @DUEDATE@ * - @PREVDUEDATE@ * - @WIKINAME@ * - @DUEIN@ * * Note: DUEIN is the number of days before the task is due or the * number of days elapsed since the due-date. */ const lang_key_prefix = 'DUMMY'; /** * Callable to get configurations for this plugin. */ protected $getConf; /** * Callable to get text in current language. */ protected $getLang; public function __construct(callable $getConf, callable $getLang) { $this->getConf = $getConf; $this->getLang = $getLang; } abstract function getNotifiableUsers($page, $editor_email, $new_data, $old_data); static protected function timeFromLastMidnight($date) { $today = date_create(); $today->setTime(0, 0); $date->setTime(0, 0); // For some reason, diff always seems to return absolute // value, so just handling that manually here $diff = $date->diff($today, true); $factor = ($today < $date) ? 1 : -1; return [$factor * $diff->y, $factor * $diff->m, $factor * $diff->d]; } /** * Works out how many days until the due-date (or since the * due-date, as appropriate) and returns it in a nicely-formatted * string. */ static function dueIn($duedate) { if (is_null($duedate)) { return ''; } list($y, $m, $d) = array_map('abs', self::timeFromLastMidnight($duedate)); $components = []; if ($y != 0) { $val = "{$y} year"; if ($y > 1) $val .= 's'; $components[] = $val; } if ($m != 0) { $val = "{$m} month"; if ($m > 1) $val .= 's'; $components[] = $val; } if ($d != 0) { $val = "{$d} day"; if ($d > 1) $val .= 's'; $components[] = $val; } switch (count($components)) { case 0: return '0 days'; case 1: return $components[0]; case 2: return $components[0] . ' and ' . $components[1]; case 3: return $components[0] . ', ' . $components[1] . ', and ' . $components[2]; default: throw new Exception("Invalid number of date components"); } } /** * Returns true if the regular expression for closed tasks matches * $status. */ function isCompleted($status) { $getConf = $this->getConf; $completed_pattern = $getConf('completed'); return preg_match($completed_pattern, $status); } /** * (Possibly) send a message for revisions to the given page, if * necessary. $old_data and $new_data are associative arrays with * the following keys: * * - content: The page content. * - duedate: A DateTime object specifying when the task is * due. If no date was specified for this page, will be NULL. * - duedate_formatted: A string with the due-date formatted * according to the struct schema. Empty if no date specified. * - assignees: An array of email addresses for the people this * task has been assigned to. * - status: The completion status of the task. */ public function sendMessage($page_id, $page_title, $editor, $editor_email, $new_data, $old_data, $mailer = NULL) { if (is_null($mailer)) $mailer = new \Mailer(); $notifiable_users = $this->getNotifiableUsers($page_id, $editor_email, $new_data, $old_data); if (count($notifiable_users) == 0) return; global $conf; $getLang = $this->getLang; if ($page_title == '') $page_title = $page_id; $url = wl($page_id, [], true); $text_subs = [ 'TITLE' => $page_title, 'TITLELINK' => "\"${page_title}\" <${url}>", 'EDITURL' => wl($page_id, ['do' => 'edit'], true, '&'), 'EDITOR' => $editor, 'STATUS' => $new_data['status'], 'PREVSTATUS' => $old_data['status'], 'DUEDATE' => $new_data['duedate_formatted'], 'PREVDUEDATE' => $old_data['duedate_formatted'], 'WIKINAME' => $conf['title'], 'DUEIN' => $this->dueIn($new_data['duedate']), ]; $html_subs = [ 'TITLELINK' => "“${page_title}”", 'EDITURL' => "edit the page" ]; $subject = str_replace( array_map(function ($x) {return "@$x@";}, array_keys($text_subs)), $text_subs, $getLang($this::lang_key_prefix . '_subject')); $mailer->setBody($getLang($this::lang_key_prefix . '_text'), $text_subs, $html_subs, $getLang($this::lang_key_prefix . '_html')); foreach ($notifiable_users as $user) { $mailer->to($user); $mailer->subject($subject); $mailer->send(); } } }