1<?php 2/** 3 * DokuWiki Plugin struct (Helper Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author Szymon Olewniczak <dokuwiki@cosmocode.de> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) { 11 die(); 12} 13 14class helper_plugin_watchcycle extends DokuWiki_Plugin 15{ 16 const MAINTAINERS_RAW = 0; 17 const MAINTAINERS_FLAT = 1; 18 const MAINTAINERS_EXPANDED = 2; 19 20 /** 21 * Create HTML for an icon showing the maintenance status of the provided pageid 22 * 23 * @param string $pageid the full pageid 24 * 25 * @return string span with inline svg icon and classes 26 */ 27 public function getSearchResultIconHTML($pageid) 28 { 29 /* @var \DokuWiki_Auth_Plugin $auth */ 30 global $auth; 31 if ($auth === null) return ''; 32 33 /* @var \helper_plugin_watchcycle $helper */ 34 $helper = plugin_load('helper', 'watchcycle'); 35 $watchcycle = p_get_metadata($pageid, 'plugin watchcycle'); 36 if (!$watchcycle) { 37 return ''; 38 } 39 40 $days_ago = $helper->daysAgo($watchcycle['last_maintainer_rev']); 41 42 $check_needed = false; 43 if ($days_ago > $watchcycle['cycle']) { 44 $check_needed = true; 45 } 46 47 $all = $this->getMaintainers($watchcycle['maintainer']); 48 $title = $this->getLang('maintained by') . implode(', ', array_keys($all)) . ' '; 49 50 if ($watchcycle['changes'] === -1) { 51 $title .= $this->getLang('never checked'); 52 } else { 53 $title .= sprintf($this->getLang('last check'), $days_ago); 54 } 55 56 $class = ['plugin__watchcycle_searchresult_icon']; 57 if ($check_needed) { 58 $class[] = 'check_needed'; 59 $title .= ' (' . $this->getLang('check needed') . ')'; 60 } 61 $icon = '<span class="' . implode(' ', $class) . '" title="' . $title . '">'; 62 $icon .= inlineSVG(DOKU_PLUGIN . 'watchcycle/admin.svg'); 63 $icon .= '</span>'; 64 return $icon; 65 } 66 67 /** 68 * @param $time 69 * @param $now 70 * 71 * @return int 72 */ 73 public function daysAgo($time, $now = false) 74 { 75 if (!$now) { 76 $now = time(); 77 } 78 79 $diff = ($now - $time) / (60 * 60 * 24); 80 return (int)$diff; 81 } 82 83 84 /** 85 * Returns true if the maintainer definition matches existing users and groups 86 * 87 * @param string $def 88 * @return bool 89 */ 90 public function validateMaintainerString($def) 91 { 92 /* @var DokuWiki_Auth_Plugin $auth */ 93 global $auth; 94 if ($auth === null) return false; // no valid auth setup 95 96 $all = explode(',', $def); 97 foreach ($all as $item) { 98 $item = trim($item); 99 if (strpos($item, '@') !== false) { 100 // check if group exists 101 if (empty($auth->retrieveUsers(0, 1, array('grps' => ltrim($item, '@'))))) { 102 return false; 103 } 104 } else { 105 if ($auth->getUserData($item) === false) { 106 return false; 107 } 108 } 109 } 110 return true; 111 } 112 113 /** 114 * Returns a parsed representation of the maintainer string 115 * 116 * keys are the user and group names, value is either: 117 * 118 * - the user data array 119 * - null for groups 120 * - false for unknown users 121 * 122 * @param string $def maintainer definition as given in the syntax 123 * @return array 124 */ 125 public function getMaintainers($def) 126 { 127 /* @var DokuWiki_Auth_Plugin $auth */ 128 global $auth; 129 130 $found = []; 131 if ($auth === null) return $found; 132 133 $all = explode(',', $def); 134 foreach ($all as $item) { 135 $item = trim($item); 136 if ($item[0] === '@') { 137 $found[$item] = null; // no detail info on groups 138 } else { 139 $found[$item] = $auth->getUserData($item); 140 } 141 } 142 143 return $found; 144 } 145 146 /** 147 * @param string $def maintainer definition as given in the syntax 148 * @return string[] list of email addresses to inform 149 */ 150 public function getMaintainerMails($def) 151 { 152 /* @var DokuWiki_Auth_Plugin $auth */ 153 global $auth; 154 if (!$auth) return []; 155 156 $data = $this->getMaintainers($def); 157 $mails = []; 158 foreach ($data as $name => $info) { 159 if (is_array($info)) { 160 $mails[] = $info['mail']; 161 } elseif ($name[0] === '@' && $auth->canDo('getUsers')) { 162 $members = $auth->retrieveUsers(0, 0, array('grps' => ltrim($name, '@'))); 163 foreach ($members as $user) { 164 $mails[] = $user['mail']; 165 } 166 } 167 } 168 169 return array_values(array_unique($mails)); 170 } 171 172 /** 173 * @param string $user 174 * @param string $def 175 * @return bool 176 */ 177 public function isMaintainer($user, $def) 178 { 179 /* @var DokuWiki_Auth_Plugin $auth */ 180 global $auth; 181 if ($auth === null) return false; 182 if ($user === '') return false; 183 $userData = $auth->getUserData($user); 184 185 $all = explode(',', $def); 186 foreach ($all as $item) { 187 $item = trim($item); 188 if (strpos($item, '@') !== false && in_array(ltrim($item, '@'), $userData['grps'])) { 189 return true; 190 } elseif ($item === $user) { 191 return true; 192 } 193 } 194 195 return false; 196 } 197 198 /** 199 * Puts users and groups into a flat array; useful for simple string output 200 * @param array $all 201 * @return array 202 */ 203 protected function flattenMaintainers($all) 204 { 205 if (empty($all['users'])) { 206 return $all; 207 } 208 209 $users = array_map(function ($user) { 210 return $user['name']; 211 }, $all['users']); 212 213 return array_merge($users, $all['groups']); 214 } 215 216 /** 217 * Expands groups into users; useful for email notification 218 * 219 * @param array $all 220 * @return array 221 */ 222 protected function expandMaintainers($all) 223 { 224 if (empty($all['groups'])) { 225 return $all; 226 } 227 228 /* @var DokuWiki_Auth_Plugin $auth */ 229 global $auth; 230 if ($auth === null) return []; 231 232 $members = array(); 233 foreach ($all['groups'] as $group) { 234 $members = array_merge($members, $auth->retrieveUsers(0, 0, array('grps' => ltrim($group, '@')))); 235 } 236 237 // merge eliminates any duplicates since we use string keys 238 return array_merge($all['users'], $members); 239 } 240} 241