1<?php 2 3// must be run within Dokuwiki 4if (!defined('DOKU_INC')) die(); 5class helper_plugin_approve extends DokuWiki_Plugin { 6 7 /** 8 * @param helper_plugin_sqlite $sqlite 9 * @return string 10 */ 11 public function no_apr_namespace(helper_plugin_sqlite $sqlite) { 12 //check for config update 13 $key = 'no_apr_namespaces'; 14 $res = $sqlite->query('SELECT value FROM config WHERE key=?', $key); 15 $no_apr_namespaces_db = $sqlite->res2single($res); 16 $no_apr_namespaces_conf = $this->getConf($key); 17 //update internal config 18 if ($no_apr_namespaces_db != $no_apr_namespaces_conf) { 19 $sqlite->query('UPDATE config SET value=? WHERE key=?', $no_apr_namespaces_conf, $key); 20 21 $res = $sqlite->query('SELECT page, hidden FROM page'); 22 $pages = $sqlite->res2arr($res); 23 foreach ($pages as $page) { 24 $id = $page['page']; 25 $hidden = $page['hidden']; 26 $in_hidden_namespace = $this->in_hidden_namespace($sqlite, $id, $no_apr_namespaces_conf); 27 $new_hidden = $in_hidden_namespace ? '1' : '0'; 28 29 if ($hidden != $new_hidden) { 30 $sqlite->query('UPDATE page SET hidden=? WHERE page=?', $new_hidden, $id); 31 } 32 } 33 } 34 35 return $no_apr_namespaces_conf; 36 } 37 38 /** 39 * @param helper_plugin_sqlite $sqlite 40 * @param $id 41 * @param null $approver 42 * @return bool 43 */ 44 public function use_approve_here(helper_plugin_sqlite $sqlite, $id, &$approver=null) { 45 46 //check if we should update no_apr_namespace 47 $this->no_apr_namespace($sqlite); 48 49 $res = $sqlite->query('SELECT page, approver FROM page WHERE page=? AND hidden=0', $id); 50 $row = $sqlite->res2row($res); 51 $approver = $row['approver']; 52 if ($row) { 53 return true; 54 } 55 return false; 56 } 57 58 /** 59 * @param helper_plugin_sqlite $sqlite 60 * @param $id 61 * @return bool|string 62 */ 63 public function find_last_approved(helper_plugin_sqlite $sqlite, $id) { 64 $res = $sqlite->query('SELECT rev FROM revision 65 WHERE page=? AND approved IS NOT NULL 66 ORDER BY rev DESC LIMIT 1', $id); 67 return $sqlite->res2single($res); 68 } 69 70 /** 71 * @param helper_plugin_sqlite $sqlite 72 * @param null $no_apr_namespaces 73 * @return array|array[]|false|string[] 74 */ 75 public function get_hidden_namespaces_list(helper_plugin_sqlite $sqlite, $no_apr_namespaces=null) { 76 if (!$no_apr_namespaces) { 77 $no_apr_namespaces = $this->no_apr_namespace($sqlite); 78 } 79 80 $no_apr_namespaces_list = preg_split('/\s+/', $no_apr_namespaces,-1, 81 PREG_SPLIT_NO_EMPTY); 82 $no_apr_namespaces_list = array_map(function ($namespace) { 83 return ltrim($namespace, ':'); 84 }, $no_apr_namespaces_list); 85 86 return $no_apr_namespaces_list; 87 } 88 89 /** 90 * @param helper_plugin_sqlite $sqlite 91 * @param $id 92 * @param null $no_apr_namespaces 93 * @return bool|string 94 */ 95 public function in_hidden_namespace(helper_plugin_sqlite $sqlite, $id, $no_apr_namespaces=null) { 96 $no_apr_namespaces_list = $this->get_hidden_namespaces_list($sqlite, $no_apr_namespaces); 97 $id = ltrim($id, ':'); 98 foreach ($no_apr_namespaces_list as $namespace) { 99 if (substr($id, 0, strlen($namespace)) == $namespace) { 100 return true; 101 } 102 } 103 return false; 104 } 105 106 /** 107 * @param helper_plugin_sqlite $sqlite 108 * @return array 109 */ 110 public function weighted_assignments(helper_plugin_sqlite $sqlite) { 111 $res = $sqlite->query('SELECT id,namespace,approver FROM maintainer'); 112 $assignments = $sqlite->res2arr($res); 113 114 $weighted_assignments = []; 115 foreach ($assignments as $assignment) { 116 $ns = $assignment['namespace']; 117 //more general namespaces are overridden by more specific ones. 118 if (substr($ns, -1) == '*') { 119 $weight = substr_count($ns, ':'); 120 } else { 121 $weight = PHP_INT_MAX; 122 } 123 124 $assignment['weight'] = $weight; 125 $weighted_assignments[] = $assignment; 126 } 127 array_multisort(array_column($weighted_assignments, 'weight'), $weighted_assignments); 128 129 return $weighted_assignments; 130 } 131 132 /** 133 * @param helper_plugin_sqlite $sqlite 134 * @param $id 135 * @param null $pageApprover 136 * @param null $weighted_assignments 137 * @return bool 138 */ 139 public function isPageAssigned(helper_plugin_sqlite $sqlite, $id, &$pageApprover=null, $weighted_assignments=null) { 140 if (!$weighted_assignments) { 141 $weighted_assignments = $this->weighted_assignments($sqlite); 142 } 143 foreach ($weighted_assignments as $assignment) { 144 $ns = ltrim($assignment['namespace'], ':'); 145 $approver = $assignment['approver']; 146 if (substr($ns, -2) == '**') { 147 //remove '**' 148 $ns = substr($ns, 0, -2); 149 if (substr($id, 0, strlen($ns)) == $ns) { 150 $newAssignment = true; 151 $pageApprover = $approver; 152 } 153 } elseif (substr($ns, -1) == '*') { 154 //remove '*' 155 $ns = substr($ns, 0, -1); 156 $noNS = substr($id, strlen($id)); 157 if (strpos($noNS, ':') === FALSE && 158 substr($id, 0, strlen($ns)) == $ns) { 159 $newAssignment = true; 160 $pageApprover = $approver; 161 } 162 } elseif($id == $ns) { 163 $newAssignment = true; 164 $pageApprover = $approver; 165 } 166 } 167 return $newAssignment; 168 } 169 170 /** 171 * @param $id 172 * @param string $pageApprover 173 * @return bool 174 */ 175 public function client_can_approve($id, $pageApprover) { 176 global $INFO; 177 //user not log in 178 if (!isset($INFO['userinfo'])) return false; 179 180 //no approver provided, check if approve plugin apply here 181 if ($pageApprover == $INFO['client']) { 182 return true; 183 } elseif (auth_quickaclcheck($id) >= AUTH_DELETE && 184 (!$pageApprover || !$this->getConf('strict_approver'))) { 185 return true; 186 } 187 188 return false; 189 } 190 191 /** 192 * @param $id 193 * @return bool 194 */ 195 public function client_can_mark_ready_for_approval($id) { 196 return auth_quickaclcheck($id) >= AUTH_EDIT; 197 } 198 199 /** 200 * @param $id 201 * @return bool 202 */ 203 public function client_can_see_drafts($id, $pageApprover) { 204 if (!$this->getConf('hide_drafts_for_viewers')) return true; 205 206 if (auth_quickaclcheck($id) >= AUTH_EDIT) return true; 207 if ($this->client_can_approve($id, $pageApprover)) return true; 208 209 return false; 210 } 211 212 /** 213 * Get the array of all pages ids in wiki 214 * 215 * @return array 216 */ 217 public function getPages() { 218 global $conf; 219 220 $datadir = realpath($conf['datadir']); // path without ending "/" 221 $directory = new RecursiveDirectoryIterator($datadir, FilesystemIterator::SKIP_DOTS); 222 $iterator = new RecursiveIteratorIterator($directory); 223 224 $pages = []; 225 /** @var SplFileInfo $fileinfo */ 226 foreach ($iterator as $fileinfo) { 227 if (!$fileinfo->isFile()) continue; 228 229 $path = $fileinfo->getRealPath(); // it should return "/" both on windows and linux 230 //remove dir part 231 $path = substr($path, strlen($datadir)); 232 //make file a dokuwiki path 233 $id = pathID($path); 234 $pages[] = $id; 235 } 236 237 return $pages; 238 } 239} 240