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