14048d1eeSSzymon Olewniczak<?php 29de4e228SAnna Dabrowska 3*92c202adSanndause dokuwiki\Extension\Plugin; 4*92c202adSannda 54048d1eeSSzymon Olewniczak/** 64048d1eeSSzymon Olewniczak * DokuWiki Plugin struct (Helper Component) 74048d1eeSSzymon Olewniczak * 84048d1eeSSzymon Olewniczak * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 94048d1eeSSzymon Olewniczak * @author Szymon Olewniczak <dokuwiki@cosmocode.de> 104048d1eeSSzymon Olewniczak */ 11*92c202adSanndaclass helper_plugin_watchcycle extends Plugin 121cd7657bSMichael Große{ 139de4e228SAnna Dabrowska public const MAINTAINERS_RAW = 0; 149de4e228SAnna Dabrowska public const MAINTAINERS_FLAT = 1; 159de4e228SAnna Dabrowska public const MAINTAINERS_EXPANDED = 2; 167ec9f11bSAnna Dabrowska 1738cc216eSMichael Große /** 1838cc216eSMichael Große * Create HTML for an icon showing the maintenance status of the provided pageid 1938cc216eSMichael Große * 2038cc216eSMichael Große * @param string $pageid the full pageid 2138cc216eSMichael Große * 2238cc216eSMichael Große * @return string span with inline svg icon and classes 2338cc216eSMichael Große */ 241cd7657bSMichael Große public function getSearchResultIconHTML($pageid) 251cd7657bSMichael Große { 2638cc216eSMichael Große /* @var \DokuWiki_Auth_Plugin $auth */ 2738cc216eSMichael Große global $auth; 28208265aeSAndreas Gohr if ($auth === null) return ''; 2938cc216eSMichael Große 3038cc216eSMichael Große /* @var \helper_plugin_watchcycle $helper */ 3138cc216eSMichael Große $helper = plugin_load('helper', 'watchcycle'); 3238cc216eSMichael Große $watchcycle = p_get_metadata($pageid, 'plugin watchcycle'); 3338cc216eSMichael Große if (!$watchcycle) { 3438cc216eSMichael Große return ''; 3538cc216eSMichael Große } 3638cc216eSMichael Große 3738cc216eSMichael Große $days_ago = $helper->daysAgo($watchcycle['last_maintainer_rev']); 3838cc216eSMichael Große 3938cc216eSMichael Große $check_needed = false; 4038cc216eSMichael Große if ($days_ago > $watchcycle['cycle']) { 4138cc216eSMichael Große $check_needed = true; 4238cc216eSMichael Große } 4338cc216eSMichael Große 447e31aba7SAndreas Gohr $all = $this->getMaintainers($watchcycle['maintainer']); 457e31aba7SAndreas Gohr $title = $this->getLang('maintained by') . implode(', ', array_keys($all)) . ' '; 4638cc216eSMichael Große 4738cc216eSMichael Große if ($watchcycle['changes'] === -1) { 4838cc216eSMichael Große $title .= $this->getLang('never checked'); 4938cc216eSMichael Große } else { 5038cc216eSMichael Große $title .= sprintf($this->getLang('last check'), $days_ago); 5138cc216eSMichael Große } 5238cc216eSMichael Große 5338cc216eSMichael Große $class = ['plugin__watchcycle_searchresult_icon']; 5438cc216eSMichael Große if ($check_needed) { 5538cc216eSMichael Große $class[] = 'check_needed'; 5638cc216eSMichael Große $title .= ' (' . $this->getLang('check needed') . ')'; 5738cc216eSMichael Große } 5838cc216eSMichael Große $icon = '<span class="' . implode(' ', $class) . '" title="' . $title . '">'; 5938cc216eSMichael Große $icon .= inlineSVG(DOKU_PLUGIN . 'watchcycle/admin.svg'); 6038cc216eSMichael Große $icon .= '</span>'; 6138cc216eSMichael Große return $icon; 6238cc216eSMichael Große } 631cd7657bSMichael Große 641cd7657bSMichael Große /** 651cd7657bSMichael Große * @param $time 661cd7657bSMichael Große * @param $now 671cd7657bSMichael Große * 681cd7657bSMichael Große * @return int 691cd7657bSMichael Große */ 701cd7657bSMichael Große public function daysAgo($time, $now = false) 711cd7657bSMichael Große { 721cd7657bSMichael Große if (!$now) { 731cd7657bSMichael Große $now = time(); 741cd7657bSMichael Große } 751cd7657bSMichael Große 761cd7657bSMichael Große $diff = ($now - $time) / (60 * 60 * 24); 771cd7657bSMichael Große return (int)$diff; 781cd7657bSMichael Große } 797ec9f11bSAnna Dabrowska 807ec9f11bSAnna Dabrowska 817ec9f11bSAnna Dabrowska /** 827ec9f11bSAnna Dabrowska * Returns true if the maintainer definition matches existing users and groups 837ec9f11bSAnna Dabrowska * 847ec9f11bSAnna Dabrowska * @param string $def 857ec9f11bSAnna Dabrowska * @return bool 867ec9f11bSAnna Dabrowska */ 877ec9f11bSAnna Dabrowska public function validateMaintainerString($def) 887ec9f11bSAnna Dabrowska { 897ec9f11bSAnna Dabrowska /* @var DokuWiki_Auth_Plugin $auth */ 907ec9f11bSAnna Dabrowska global $auth; 91208265aeSAndreas Gohr if ($auth === null) return false; // no valid auth setup 927ec9f11bSAnna Dabrowska 937ec9f11bSAnna Dabrowska $all = explode(',', $def); 947ec9f11bSAnna Dabrowska foreach ($all as $item) { 957ec9f11bSAnna Dabrowska $item = trim($item); 967ec9f11bSAnna Dabrowska if (strpos($item, '@') !== false) { 977ec9f11bSAnna Dabrowska // check if group exists 98*92c202adSannda if (empty($auth->retrieveUsers(0, 1, ['grps' => ltrim($item, '@')]))) { 997ec9f11bSAnna Dabrowska return false; 1007ec9f11bSAnna Dabrowska } 101*92c202adSannda } elseif ($auth->getUserData($item) === false) { 1027ec9f11bSAnna Dabrowska return false; 1037ec9f11bSAnna Dabrowska } 1047ec9f11bSAnna Dabrowska } 1057ec9f11bSAnna Dabrowska return true; 1067ec9f11bSAnna Dabrowska } 1077ec9f11bSAnna Dabrowska 1087ec9f11bSAnna Dabrowska /** 1097e31aba7SAndreas Gohr * Returns a parsed representation of the maintainer string 1107ec9f11bSAnna Dabrowska * 1117e31aba7SAndreas Gohr * keys are the user and group names, value is either: 1127e31aba7SAndreas Gohr * 1137e31aba7SAndreas Gohr * - the user data array 1147e31aba7SAndreas Gohr * - null for groups 1157e31aba7SAndreas Gohr * - false for unknown users 1167e31aba7SAndreas Gohr * 1177e31aba7SAndreas Gohr * @param string $def maintainer definition as given in the syntax 1187ec9f11bSAnna Dabrowska * @return array 1197ec9f11bSAnna Dabrowska */ 1207e31aba7SAndreas Gohr public function getMaintainers($def) 1217ec9f11bSAnna Dabrowska { 1227ec9f11bSAnna Dabrowska /* @var DokuWiki_Auth_Plugin $auth */ 1237ec9f11bSAnna Dabrowska global $auth; 1247ec9f11bSAnna Dabrowska 1257e31aba7SAndreas Gohr $found = []; 126208265aeSAndreas Gohr if ($auth === null) return $found; 1277ec9f11bSAnna Dabrowska 1287ec9f11bSAnna Dabrowska $all = explode(',', $def); 1297ec9f11bSAnna Dabrowska foreach ($all as $item) { 1307ec9f11bSAnna Dabrowska $item = trim($item); 1317e31aba7SAndreas Gohr if ($item[0] === '@') { 1327e31aba7SAndreas Gohr $found[$item] = null; // no detail info on groups 1337ec9f11bSAnna Dabrowska } else { 1347e31aba7SAndreas Gohr $found[$item] = $auth->getUserData($item); 1357ec9f11bSAnna Dabrowska } 1367ec9f11bSAnna Dabrowska } 1377ec9f11bSAnna Dabrowska 1387ec9f11bSAnna Dabrowska return $found; 1397ec9f11bSAnna Dabrowska } 1407ec9f11bSAnna Dabrowska 1417ec9f11bSAnna Dabrowska /** 1427e31aba7SAndreas Gohr * @param string $def maintainer definition as given in the syntax 1437e31aba7SAndreas Gohr * @return string[] list of email addresses to inform 1447e31aba7SAndreas Gohr */ 1457e31aba7SAndreas Gohr public function getMaintainerMails($def) 1467e31aba7SAndreas Gohr { 147ba165cbdSAnna Dabrowska /* @var \dokuwiki\Extension\AuthPlugin $auth */ 1487e31aba7SAndreas Gohr global $auth; 149*92c202adSannda $auth ??= auth_setup(); 1507e31aba7SAndreas Gohr if (!$auth) return []; 1517e31aba7SAndreas Gohr 1527e31aba7SAndreas Gohr $data = $this->getMaintainers($def); 1537e31aba7SAndreas Gohr $mails = []; 1547e31aba7SAndreas Gohr foreach ($data as $name => $info) { 1557e31aba7SAndreas Gohr if (is_array($info)) { 1567e31aba7SAndreas Gohr $mails[] = $info['mail']; 1577e31aba7SAndreas Gohr } elseif ($name[0] === '@' && $auth->canDo('getUsers')) { 158*92c202adSannda $members = $auth->retrieveUsers(0, 0, ['grps' => ltrim($name, '@')]); 1597e31aba7SAndreas Gohr foreach ($members as $user) { 1607e31aba7SAndreas Gohr $mails[] = $user['mail']; 1617e31aba7SAndreas Gohr } 1627e31aba7SAndreas Gohr } 1637e31aba7SAndreas Gohr } 1647e31aba7SAndreas Gohr 1657e31aba7SAndreas Gohr return array_values(array_unique($mails)); 1667e31aba7SAndreas Gohr } 1677e31aba7SAndreas Gohr 1687e31aba7SAndreas Gohr /** 1697ec9f11bSAnna Dabrowska * @param string $user 1707ec9f11bSAnna Dabrowska * @param string $def 1717ec9f11bSAnna Dabrowska * @return bool 1727ec9f11bSAnna Dabrowska */ 1737ec9f11bSAnna Dabrowska public function isMaintainer($user, $def) 1747ec9f11bSAnna Dabrowska { 1757ec9f11bSAnna Dabrowska /* @var DokuWiki_Auth_Plugin $auth */ 1767ec9f11bSAnna Dabrowska global $auth; 177208265aeSAndreas Gohr if ($auth === null) return false; 17830e745d9SAndreas Gohr if ($user === '') return false; 1797ec9f11bSAnna Dabrowska $userData = $auth->getUserData($user); 1807ec9f11bSAnna Dabrowska 1817ec9f11bSAnna Dabrowska $all = explode(',', $def); 1827ec9f11bSAnna Dabrowska foreach ($all as $item) { 1837ec9f11bSAnna Dabrowska $item = trim($item); 1847ec9f11bSAnna Dabrowska if (strpos($item, '@') !== false && in_array(ltrim($item, '@'), $userData['grps'])) { 1857ec9f11bSAnna Dabrowska return true; 1867ec9f11bSAnna Dabrowska } elseif ($item === $user) { 1877ec9f11bSAnna Dabrowska return true; 1887ec9f11bSAnna Dabrowska } 1897ec9f11bSAnna Dabrowska } 1907ec9f11bSAnna Dabrowska 1917ec9f11bSAnna Dabrowska return false; 1927ec9f11bSAnna Dabrowska } 1937ec9f11bSAnna Dabrowska 1947ec9f11bSAnna Dabrowska /** 195ba165cbdSAnna Dabrowska * Inform all maintainers that the page needs checking 196ba165cbdSAnna Dabrowska * 197ba165cbdSAnna Dabrowska * @param string $def defined maintainers 198ba165cbdSAnna Dabrowska * @param string $page that needs checking 199ba165cbdSAnna Dabrowska */ 200ba165cbdSAnna Dabrowska public function informMaintainer($def, $page) 201ba165cbdSAnna Dabrowska { 202ba165cbdSAnna Dabrowska $mails = $this->getMaintainerMails($def); 203ba165cbdSAnna Dabrowska foreach ($mails as $mail) { 204ba165cbdSAnna Dabrowska $this->sendMail($mail, $page); 205ba165cbdSAnna Dabrowska } 206ba165cbdSAnna Dabrowska } 207ba165cbdSAnna Dabrowska 208ba165cbdSAnna Dabrowska /** 209ba165cbdSAnna Dabrowska * Sends an email 210ba165cbdSAnna Dabrowska * 211ba165cbdSAnna Dabrowska * @param array $mail 212ba165cbdSAnna Dabrowska * @param string $page 213ba165cbdSAnna Dabrowska */ 214ba165cbdSAnna Dabrowska protected function sendMail($mail, $page) 215ba165cbdSAnna Dabrowska { 216ba165cbdSAnna Dabrowska $mailer = new Mailer(); 217ba165cbdSAnna Dabrowska $mailer->to($mail); 218ba165cbdSAnna Dabrowska $mailer->subject($this->getLang('mail subject')); 219*92c202adSannda 220ba165cbdSAnna Dabrowska $text = sprintf($this->getLang('mail body'), $page); 221ba165cbdSAnna Dabrowska $link = '<a href="' . wl($page, '', true) . '">' . $page . '</a>'; 222ba165cbdSAnna Dabrowska $html = sprintf($this->getLang('mail body'), $link); 223ba165cbdSAnna Dabrowska $mailer->setBody($text, null, null, $html); 224ba165cbdSAnna Dabrowska 225ba165cbdSAnna Dabrowska if (!$mailer->send()) { 226ba165cbdSAnna Dabrowska msg($this->getLang('error mail'), -1); 227ba165cbdSAnna Dabrowska } 228ba165cbdSAnna Dabrowska } 229ba165cbdSAnna Dabrowska 230ba165cbdSAnna Dabrowska /** 2317ec9f11bSAnna Dabrowska * Puts users and groups into a flat array; useful for simple string output 2327ec9f11bSAnna Dabrowska * @param array $all 2337ec9f11bSAnna Dabrowska * @return array 2347ec9f11bSAnna Dabrowska */ 2357ec9f11bSAnna Dabrowska protected function flattenMaintainers($all) 2367ec9f11bSAnna Dabrowska { 2377ec9f11bSAnna Dabrowska if (empty($all['users'])) { 2387ec9f11bSAnna Dabrowska return $all; 2397ec9f11bSAnna Dabrowska } 2407ec9f11bSAnna Dabrowska 241*92c202adSannda $users = array_map(static fn($user) => $user['name'], $all['users']); 2427ec9f11bSAnna Dabrowska 2437ec9f11bSAnna Dabrowska return array_merge($users, $all['groups']); 2447ec9f11bSAnna Dabrowska } 2452ca9f4fbSAnna Dabrowska 2462ca9f4fbSAnna Dabrowska /** 2472ca9f4fbSAnna Dabrowska * Expands groups into users; useful for email notification 2482ca9f4fbSAnna Dabrowska * 2492ca9f4fbSAnna Dabrowska * @param array $all 2502ca9f4fbSAnna Dabrowska * @return array 2512ca9f4fbSAnna Dabrowska */ 2522ca9f4fbSAnna Dabrowska protected function expandMaintainers($all) 2532ca9f4fbSAnna Dabrowska { 2542ca9f4fbSAnna Dabrowska if (empty($all['groups'])) { 2552ca9f4fbSAnna Dabrowska return $all; 2562ca9f4fbSAnna Dabrowska } 2572ca9f4fbSAnna Dabrowska 2582ca9f4fbSAnna Dabrowska /* @var DokuWiki_Auth_Plugin $auth */ 2592ca9f4fbSAnna Dabrowska global $auth; 260208265aeSAndreas Gohr if ($auth === null) return []; 2612ca9f4fbSAnna Dabrowska 262*92c202adSannda $members = []; 2632ca9f4fbSAnna Dabrowska foreach ($all['groups'] as $group) { 264*92c202adSannda $members = array_merge($members, $auth->retrieveUsers(0, 0, ['grps' => ltrim($group, '@')])); 2652ca9f4fbSAnna Dabrowska } 2662ca9f4fbSAnna Dabrowska 2672ca9f4fbSAnna Dabrowska // merge eliminates any duplicates since we use string keys 2682ca9f4fbSAnna Dabrowska return array_merge($all['users'], $members); 2692ca9f4fbSAnna Dabrowska } 2704048d1eeSSzymon Olewniczak} 271