14474ed8aSSzymon Olewniczak<?php 24474ed8aSSzymon Olewniczak 3e72eb5b8SSzymon Olewniczakuse dokuwiki\Extension\AuthPlugin; 4e72eb5b8SSzymon Olewniczakuse dokuwiki\Extension\Plugin; 5e72eb5b8SSzymon Olewniczakuse dokuwiki\plugin\sqlite\SQLiteDB; 64474ed8aSSzymon Olewniczak 7b59355cdSSzymon Olewniczakclass helper_plugin_approve_db extends Plugin 84474ed8aSSzymon Olewniczak{ 9e72eb5b8SSzymon Olewniczak protected $db; 104474ed8aSSzymon Olewniczak 11e72eb5b8SSzymon Olewniczak protected $no_apr_namespaces_array; 12e72eb5b8SSzymon Olewniczak 134474ed8aSSzymon Olewniczak public function __construct() 144474ed8aSSzymon Olewniczak { 15e72eb5b8SSzymon Olewniczak $this->db = new SQLiteDB('approve', DOKU_PLUGIN . 'approve/db/'); 16e72eb5b8SSzymon Olewniczak $no_apr_namespaces = $this->getConf('no_apr_namespaces'); 17e72eb5b8SSzymon Olewniczak $this->no_apr_namespaces_array = array_map(function ($namespace) { 18e72eb5b8SSzymon Olewniczak return ltrim($namespace, ':'); 19e72eb5b8SSzymon Olewniczak }, preg_split('/\s+/', $no_apr_namespaces,-1,PREG_SPLIT_NO_EMPTY)); 20e72eb5b8SSzymon Olewniczak $this->initNoApproveNamespaces(); 214474ed8aSSzymon Olewniczak } 224474ed8aSSzymon Olewniczak 23e72eb5b8SSzymon Olewniczak public function getDbFile(): string 244474ed8aSSzymon Olewniczak { 25e72eb5b8SSzymon Olewniczak return $this->db->getDbFile(); 264474ed8aSSzymon Olewniczak } 274474ed8aSSzymon Olewniczak 28e72eb5b8SSzymon Olewniczak protected function initNoApproveNamespaces(): void 29e72eb5b8SSzymon Olewniczak { 30e72eb5b8SSzymon Olewniczak $config_key = 'no_apr_namespaces'; 31e72eb5b8SSzymon Olewniczak $db_value = $this->getDbConf($config_key); 32e72eb5b8SSzymon Olewniczak $config_value = $this->getConf('no_apr_namespaces'); 33e72eb5b8SSzymon Olewniczak if ($db_value !== $config_value) { // $db_value might be null. In this case run the commit anyway. 34e72eb5b8SSzymon Olewniczak $this->db->getPdo()->beginTransaction(); 35e72eb5b8SSzymon Olewniczak $this->setDbConf($config_key, $config_value); 36e72eb5b8SSzymon Olewniczak $pages_meta = $this->getPagesMetadata(); 37e72eb5b8SSzymon Olewniczak foreach ($pages_meta as $page_meta) { 38e72eb5b8SSzymon Olewniczak $page_id = $page_meta['page']; 39e72eb5b8SSzymon Olewniczak $hidden = (int) $this->pageInHiddenNamespace($page_id); 40e72eb5b8SSzymon Olewniczak $this->setPageHiddenStatus($page_id, $hidden); 414474ed8aSSzymon Olewniczak } 42e72eb5b8SSzymon Olewniczak $this->db->getPdo()->commit(); 434474ed8aSSzymon Olewniczak } 44e72eb5b8SSzymon Olewniczak } 454474ed8aSSzymon Olewniczak 46e72eb5b8SSzymon Olewniczak public function getPagesMetadata(): array 47e72eb5b8SSzymon Olewniczak { 48e72eb5b8SSzymon Olewniczak $sql = 'SELECT page, approver, hidden FROM page'; 49e72eb5b8SSzymon Olewniczak return $this->db->queryAll($sql); 504474ed8aSSzymon Olewniczak } 51e72eb5b8SSzymon Olewniczak 52e72eb5b8SSzymon Olewniczak public function getPageMetadata(string $page_id): ?array 53e72eb5b8SSzymon Olewniczak { 54e72eb5b8SSzymon Olewniczak $sql = 'SELECT approver FROM page WHERE page=? AND hidden != 1'; 55e72eb5b8SSzymon Olewniczak return $this->db->queryRecord($sql, $page_id); 564474ed8aSSzymon Olewniczak } 57e72eb5b8SSzymon Olewniczak 58e72eb5b8SSzymon Olewniczak public function getDbConf(string $key): ?string 59e72eb5b8SSzymon Olewniczak { 60e72eb5b8SSzymon Olewniczak $sql = 'SELECT value FROM config WHERE key=?'; 61e72eb5b8SSzymon Olewniczak return $this->db->queryValue($sql, $key); 62e72eb5b8SSzymon Olewniczak } 63e72eb5b8SSzymon Olewniczak 64e72eb5b8SSzymon Olewniczak public function setDbConf(string $key, string $value): void 65e72eb5b8SSzymon Olewniczak { 66e72eb5b8SSzymon Olewniczak $this->db->saveRecord('config', ['key' => $key, 'value' => $value]); 674474ed8aSSzymon Olewniczak } 684474ed8aSSzymon Olewniczak 694474ed8aSSzymon Olewniczak /** 70e72eb5b8SSzymon Olewniczak * @param string $page_id 71e72eb5b8SSzymon Olewniczak * @param int $hidden Must be int since SQLite doesn't suport bool type. 72e72eb5b8SSzymon Olewniczak * @return void 734474ed8aSSzymon Olewniczak */ 74e72eb5b8SSzymon Olewniczak public function setPageHiddenStatus(string $page_id, int $hidden): void 75e72eb5b8SSzymon Olewniczak { 76e72eb5b8SSzymon Olewniczak $sql = 'UPDATE page SET hidden=? WHERE page=?'; 77e72eb5b8SSzymon Olewniczak $this->db->query($sql, $hidden, $page_id); 78e72eb5b8SSzymon Olewniczak } 79e72eb5b8SSzymon Olewniczak 80e72eb5b8SSzymon Olewniczak public function updatePagesAssignments(): void 81e72eb5b8SSzymon Olewniczak { 82e72eb5b8SSzymon Olewniczak $this->db->getPdo()->beginTransaction(); 83e72eb5b8SSzymon Olewniczak 84e72eb5b8SSzymon Olewniczak // clean current settings 85e72eb5b8SSzymon Olewniczak $this->db->query('DELETE FROM page'); 86e72eb5b8SSzymon Olewniczak 87e72eb5b8SSzymon Olewniczak $wikiPages = $this->getWikiPages(); 88e72eb5b8SSzymon Olewniczak foreach ($wikiPages as $id) { 89e72eb5b8SSzymon Olewniczak // update revision information 90e72eb5b8SSzymon Olewniczak $this->updatePage($id); 91e72eb5b8SSzymon Olewniczak } 92e72eb5b8SSzymon Olewniczak $this->db->getPdo()->commit(); 93e72eb5b8SSzymon Olewniczak } 94e72eb5b8SSzymon Olewniczak 95e72eb5b8SSzymon Olewniczak public function getWikiPages(): array 964474ed8aSSzymon Olewniczak { 974474ed8aSSzymon Olewniczak global $conf; 98e72eb5b8SSzymon Olewniczak 99e72eb5b8SSzymon Olewniczak $datadir = realpath($conf['datadir']); // path without ending "/" 100e72eb5b8SSzymon Olewniczak $directory = new RecursiveDirectoryIterator($datadir, FilesystemIterator::SKIP_DOTS); 101e72eb5b8SSzymon Olewniczak $iterator = new RecursiveIteratorIterator($directory); 102e72eb5b8SSzymon Olewniczak 103e72eb5b8SSzymon Olewniczak $pages = []; 104e72eb5b8SSzymon Olewniczak /** @var SplFileInfo $fileinfo */ 105e72eb5b8SSzymon Olewniczak foreach ($iterator as $fileinfo) { 106e72eb5b8SSzymon Olewniczak if (!$fileinfo->isFile()) continue; 107e72eb5b8SSzymon Olewniczak 108e72eb5b8SSzymon Olewniczak $path = $fileinfo->getRealPath(); // it should return "/" both on windows and linux 109e72eb5b8SSzymon Olewniczak // remove dir part 110e72eb5b8SSzymon Olewniczak $path = substr($path, strlen($datadir)); 111e72eb5b8SSzymon Olewniczak // make file a dokuwiki path 112e72eb5b8SSzymon Olewniczak $id = pathID($path); 113e72eb5b8SSzymon Olewniczak $pages[] = $id; 1144474ed8aSSzymon Olewniczak } 115e72eb5b8SSzymon Olewniczak 116e72eb5b8SSzymon Olewniczak return $pages; 1174474ed8aSSzymon Olewniczak } 118e72eb5b8SSzymon Olewniczak 119e72eb5b8SSzymon Olewniczak public function weightedAssignments(): array 120e72eb5b8SSzymon Olewniczak { 121e72eb5b8SSzymon Olewniczak $assignments = $this->db->queryAll('SELECT id, namespace, approver FROM maintainer'); 122e72eb5b8SSzymon Olewniczak 123e72eb5b8SSzymon Olewniczak $weighted_assignments = []; 124e72eb5b8SSzymon Olewniczak foreach ($assignments as $assignment) { 125e72eb5b8SSzymon Olewniczak $ns = $assignment['namespace']; 126e72eb5b8SSzymon Olewniczak // more general namespaces are overridden by more specific ones. 127e72eb5b8SSzymon Olewniczak if (substr($ns, -1) == '*') { 128e72eb5b8SSzymon Olewniczak $weight = substr_count($ns, ':'); 129e72eb5b8SSzymon Olewniczak } else { 130e72eb5b8SSzymon Olewniczak $weight = PHP_INT_MAX; 131e72eb5b8SSzymon Olewniczak } 132e72eb5b8SSzymon Olewniczak 133e72eb5b8SSzymon Olewniczak $assignment['weight'] = $weight; 134e72eb5b8SSzymon Olewniczak $weighted_assignments[] = $assignment; 135e72eb5b8SSzymon Olewniczak } 136e72eb5b8SSzymon Olewniczak array_multisort(array_column($weighted_assignments, 'weight'), $weighted_assignments); 137e72eb5b8SSzymon Olewniczak 138e72eb5b8SSzymon Olewniczak return $weighted_assignments; 1394474ed8aSSzymon Olewniczak } 1404474ed8aSSzymon Olewniczak 1414474ed8aSSzymon Olewniczak /** 142e72eb5b8SSzymon Olewniczak * Returns approver or null if page is not in $weighted_assignments. 143e72eb5b8SSzymon Olewniczak * Approver can be empty string. 1444474ed8aSSzymon Olewniczak * 145e72eb5b8SSzymon Olewniczak * @param string $page_id 146e72eb5b8SSzymon Olewniczak * @param array $weighted_assignments 147e72eb5b8SSzymon Olewniczak * @return string 1484474ed8aSSzymon Olewniczak */ 149e72eb5b8SSzymon Olewniczak public function getPageAssignment(string $page_id, array $weighted_assignments): ?string 1504474ed8aSSzymon Olewniczak { 151e72eb5b8SSzymon Olewniczak $page_approver = null; 152e72eb5b8SSzymon Olewniczak foreach ($weighted_assignments as $assignment) { 153e72eb5b8SSzymon Olewniczak $ns = ltrim($assignment['namespace'], ':'); 154e72eb5b8SSzymon Olewniczak $approver = $assignment['approver']; 155e72eb5b8SSzymon Olewniczak if (substr($ns, -2) == '**') { 156e72eb5b8SSzymon Olewniczak //remove '**' 157e72eb5b8SSzymon Olewniczak $ns = substr($ns, 0, -2); 158e72eb5b8SSzymon Olewniczak if (substr($page_id, 0, strlen($ns)) == $ns) { 159e72eb5b8SSzymon Olewniczak $page_approver = $approver; 1604474ed8aSSzymon Olewniczak } 161e72eb5b8SSzymon Olewniczak } elseif (substr($ns, -1) == '*') { 162e72eb5b8SSzymon Olewniczak //remove '*' 163e72eb5b8SSzymon Olewniczak $ns = substr($ns, 0, -1); 164e72eb5b8SSzymon Olewniczak $noNS = substr($page_id, strlen($ns)); 165e72eb5b8SSzymon Olewniczak if (strpos($noNS, ':') === FALSE && 166e72eb5b8SSzymon Olewniczak substr($page_id, 0, strlen($ns)) == $ns) { 167e72eb5b8SSzymon Olewniczak $page_approver = $approver; 1684474ed8aSSzymon Olewniczak } 169e72eb5b8SSzymon Olewniczak } elseif($page_id == $ns) { 170e72eb5b8SSzymon Olewniczak $page_approver = $approver; 1714474ed8aSSzymon Olewniczak } 1724474ed8aSSzymon Olewniczak } 173e72eb5b8SSzymon Olewniczak return $page_approver; 174e72eb5b8SSzymon Olewniczak } 1754474ed8aSSzymon Olewniczak 176e72eb5b8SSzymon Olewniczak public function pageInHiddenNamespace(string $page_id): bool 177e72eb5b8SSzymon Olewniczak { 178e72eb5b8SSzymon Olewniczak $page_id = ltrim($page_id, ':'); 179e72eb5b8SSzymon Olewniczak foreach ($this->no_apr_namespaces_array as $namespace) { 180e72eb5b8SSzymon Olewniczak if (substr($page_id, 0, strlen($namespace)) == $namespace) { 181e72eb5b8SSzymon Olewniczak return true; 182e72eb5b8SSzymon Olewniczak } 183e72eb5b8SSzymon Olewniczak } 184e72eb5b8SSzymon Olewniczak return false; 185e72eb5b8SSzymon Olewniczak } 186e72eb5b8SSzymon Olewniczak 187e72eb5b8SSzymon Olewniczak public function getPages(string $user='', array $states=['approved', 'draft', 'ready_for_approval'], 188e72eb5b8SSzymon Olewniczak string $namespace='', string $filter=''): array 189e72eb5b8SSzymon Olewniczak { 190e72eb5b8SSzymon Olewniczak /* @var AuthPlugin $auth */ 191e72eb5b8SSzymon Olewniczak global $auth; 192e72eb5b8SSzymon Olewniczak 193e72eb5b8SSzymon Olewniczak $sql = 'SELECT page.page AS id, page.approver, revision.rev, revision.approved, revision.approved_by, 194e72eb5b8SSzymon Olewniczak revision.ready_for_approval, revision.ready_for_approval_by, 195e72eb5b8SSzymon Olewniczak LENGTH(page.page) - LENGTH(REPLACE(page.page, \':\', \'\')) AS colons 196e72eb5b8SSzymon Olewniczak FROM page INNER JOIN revision ON page.page = revision.page 197e72eb5b8SSzymon Olewniczak WHERE page.hidden = 0 AND revision.current=1 AND page.page GLOB ? AND page.page REGEXP ? 198e72eb5b8SSzymon Olewniczak ORDER BY colons, page.page'; 199e72eb5b8SSzymon Olewniczak $pages = $this->db->queryAll($sql, $namespace.'*', $filter); 200e72eb5b8SSzymon Olewniczak 201e72eb5b8SSzymon Olewniczak // add status to the page 202e72eb5b8SSzymon Olewniczak $pages = array_map([$this, 'setPageStatus'], $pages); 203e72eb5b8SSzymon Olewniczak 204e72eb5b8SSzymon Olewniczak if ($user !== '') { 205e72eb5b8SSzymon Olewniczak $user_data = $auth->getUserData($user); 206e72eb5b8SSzymon Olewniczak $user_groups = $user_data['grps']; 207e72eb5b8SSzymon Olewniczak $pages = array_filter($pages, function ($page) use ($user, $user_groups) { 208e72eb5b8SSzymon Olewniczak return $page['approver'][0] == '@' && in_array(substr($page['approver'], 1), $user_groups) || 209e72eb5b8SSzymon Olewniczak $page['approver'] == $user; 210e72eb5b8SSzymon Olewniczak }); 211e72eb5b8SSzymon Olewniczak } 212e72eb5b8SSzymon Olewniczak 213e72eb5b8SSzymon Olewniczak // filter by status 214e72eb5b8SSzymon Olewniczak $pages = array_filter($pages, function ($page) use ($states) { 215e72eb5b8SSzymon Olewniczak return in_array($page['status'], $states); 216e72eb5b8SSzymon Olewniczak }); 217e72eb5b8SSzymon Olewniczak 218e72eb5b8SSzymon Olewniczak return $pages; 219e72eb5b8SSzymon Olewniczak } 220e72eb5b8SSzymon Olewniczak 221e72eb5b8SSzymon Olewniczak public function getPageRevisions(string $page_id): array { 222e72eb5b8SSzymon Olewniczak $sql = 'SELECT page AS id, rev, approved, approved_by, ready_for_approval, ready_for_approval_by 223e72eb5b8SSzymon Olewniczak FROM revision WHERE page=?'; 224e72eb5b8SSzymon Olewniczak $revisions = $this->db->queryAll($sql, $page_id); 225e72eb5b8SSzymon Olewniczak // add status to the page 226e72eb5b8SSzymon Olewniczak $revisions = array_map([$this, 'setPageStatus'], $revisions); 227e72eb5b8SSzymon Olewniczak 228e72eb5b8SSzymon Olewniczak return $revisions; 229e72eb5b8SSzymon Olewniczak } 230e72eb5b8SSzymon Olewniczak 231e72eb5b8SSzymon Olewniczak public function getPageRevision(string $page_id, int $rev): ?array 232e72eb5b8SSzymon Olewniczak { 233e72eb5b8SSzymon Olewniczak $sql = 'SELECT ready_for_approval, ready_for_approval_by, approved, approved_by, version 234e72eb5b8SSzymon Olewniczak FROM revision WHERE page=? AND rev=?'; 235e72eb5b8SSzymon Olewniczak $page = $this->db->queryRecord($sql, $page_id, $rev); 236e72eb5b8SSzymon Olewniczak 237e72eb5b8SSzymon Olewniczak if ($page == null) { 238e72eb5b8SSzymon Olewniczak $page = [ 239e72eb5b8SSzymon Olewniczak 'ready_for_approval' => null, 240e72eb5b8SSzymon Olewniczak 'ready_for_approval_by' => null, 241e72eb5b8SSzymon Olewniczak 'approved' => null, 242e72eb5b8SSzymon Olewniczak 'approved_by' => null 243e72eb5b8SSzymon Olewniczak ]; 244e72eb5b8SSzymon Olewniczak } 245e72eb5b8SSzymon Olewniczak $page['id'] = $page_id; 246e72eb5b8SSzymon Olewniczak $page['rev'] = $rev; 247e72eb5b8SSzymon Olewniczak $page = $this->setPageStatus($page); 248e72eb5b8SSzymon Olewniczak 249e72eb5b8SSzymon Olewniczak return $page; 250e72eb5b8SSzymon Olewniczak } 251e72eb5b8SSzymon Olewniczak 252e72eb5b8SSzymon Olewniczak protected function setPageStatus(array $page): array 253e72eb5b8SSzymon Olewniczak { 254e72eb5b8SSzymon Olewniczak if ($page['approved'] !== null) { 255e72eb5b8SSzymon Olewniczak $page['status'] = 'approved'; 256e72eb5b8SSzymon Olewniczak } elseif ($page['ready_for_approval'] !== null) { 257e72eb5b8SSzymon Olewniczak $page['status'] = 'ready_for_approval'; 258e72eb5b8SSzymon Olewniczak } else { 259e72eb5b8SSzymon Olewniczak $page['status'] = 'draft'; 260e72eb5b8SSzymon Olewniczak } 261e72eb5b8SSzymon Olewniczak return $page; 262e72eb5b8SSzymon Olewniczak } 263e72eb5b8SSzymon Olewniczak 264e72eb5b8SSzymon Olewniczak public function moveRevisionHistory(string $old_page_id, string $new_page_id): void 265e72eb5b8SSzymon Olewniczak { 266e72eb5b8SSzymon Olewniczak $this->db->exec('UPDATE revision SET page=? WHERE page=?', $new_page_id, $old_page_id); 267e72eb5b8SSzymon Olewniczak } 268e72eb5b8SSzymon Olewniczak 269e72eb5b8SSzymon Olewniczak public function getLastDbRev(string $page_id, ?string $status=null): ?int 270e72eb5b8SSzymon Olewniczak { 271e72eb5b8SSzymon Olewniczak if ($status == 'approved') { 272e72eb5b8SSzymon Olewniczak $sql = 'SELECT rev FROM revision WHERE page=? AND approved IS NOT NULL ORDER BY rev DESC LIMIT 1'; 273e72eb5b8SSzymon Olewniczak return $this->db->queryValue($sql, $page_id); 274e72eb5b8SSzymon Olewniczak } elseif ($status == 'ready_for_approval') { 275e72eb5b8SSzymon Olewniczak $sql = 'SELECT rev FROM revision WHERE page=? AND ready_for_approval IS NOT NULL ORDER BY rev DESC LIMIT 1'; 276e72eb5b8SSzymon Olewniczak return $this->db->queryValue($sql, $page_id); 277e72eb5b8SSzymon Olewniczak } 278e72eb5b8SSzymon Olewniczak $sql = 'SELECT rev FROM revision WHERE page=? AND current=1'; 279e72eb5b8SSzymon Olewniczak return $this->db->queryValue($sql, $page_id); 280e72eb5b8SSzymon Olewniczak } 281e72eb5b8SSzymon Olewniczak 282e72eb5b8SSzymon Olewniczak public function setApprovedStatus(string $page_id): void 283e72eb5b8SSzymon Olewniczak { 284e72eb5b8SSzymon Olewniczak global $INFO; 285e72eb5b8SSzymon Olewniczak 286e72eb5b8SSzymon Olewniczak // approved IS NULL prevents from overriding already approved page 287e72eb5b8SSzymon Olewniczak $sql = 'UPDATE revision SET approved=?, approved_by=?, 288e72eb5b8SSzymon Olewniczak version=(SELECT IFNULL(MAX(version), 0) FROM revision WHERE page=?) + 1 289e72eb5b8SSzymon Olewniczak WHERE page=? AND current=1 AND approved IS NULL'; 290e72eb5b8SSzymon Olewniczak $this->db->exec($sql, date('c'), $INFO['client'], $page_id, $page_id); 291e72eb5b8SSzymon Olewniczak } 292e72eb5b8SSzymon Olewniczak 293e72eb5b8SSzymon Olewniczak public function setReadyForApprovalStatus(string $page_id): void 294e72eb5b8SSzymon Olewniczak { 295e72eb5b8SSzymon Olewniczak global $INFO; 296e72eb5b8SSzymon Olewniczak 297e72eb5b8SSzymon Olewniczak // approved IS NULL prevents from overriding already approved page 298e72eb5b8SSzymon Olewniczak $sql = 'UPDATE revision SET ready_for_approval=?, ready_for_approval_by=? 299e72eb5b8SSzymon Olewniczak WHERE page=? AND current=1 AND ready_for_approval IS NULL'; 300e72eb5b8SSzymon Olewniczak $this->db->exec($sql, date('c'), $INFO['client'], $page_id); 301e72eb5b8SSzymon Olewniczak } 302e72eb5b8SSzymon Olewniczak 303e72eb5b8SSzymon Olewniczak protected function deletePage($page_id): void 304e72eb5b8SSzymon Olewniczak { 305e72eb5b8SSzymon Olewniczak // delete information about availability of a page but keep the history 306e72eb5b8SSzymon Olewniczak $this->db->exec('DELETE FROM page WHERE page=?', $page_id); 307e72eb5b8SSzymon Olewniczak $this->db->exec('DELETE FROM revision WHERE page=? AND approved IS NULL AND ready_for_approval IS NULL' 308e72eb5b8SSzymon Olewniczak , $page_id); 309e72eb5b8SSzymon Olewniczak $this->db->exec('UPDATE revision SET current=0 WHERE page=? AND current=1', $page_id); 310e72eb5b8SSzymon Olewniczak } 311e72eb5b8SSzymon Olewniczak 312e72eb5b8SSzymon Olewniczak public function handlePageDelete(string $page_id): void 313e72eb5b8SSzymon Olewniczak { 314e72eb5b8SSzymon Olewniczak $this->db->getPdo()->beginTransaction(); 315e72eb5b8SSzymon Olewniczak $this->deletePage($page_id); 316e72eb5b8SSzymon Olewniczak $this->db->getPdo()->commit(); 317e72eb5b8SSzymon Olewniczak } 318e72eb5b8SSzymon Olewniczak 319e72eb5b8SSzymon Olewniczak protected function updatePage(string $page_id): void 320e72eb5b8SSzymon Olewniczak { 321e72eb5b8SSzymon Olewniczak // delete all unimportant revisions 322e72eb5b8SSzymon Olewniczak $this->db->exec('DELETE FROM revision WHERE page=? AND approved IS NULL AND ready_for_approval IS NULL' 323e72eb5b8SSzymon Olewniczak , $page_id); 324e72eb5b8SSzymon Olewniczak 325e72eb5b8SSzymon Olewniczak $weighted_assignments = $this->weightedAssignments(); 326e72eb5b8SSzymon Olewniczak $approver = $this->getPageAssignment($page_id, $weighted_assignments); 327e72eb5b8SSzymon Olewniczak if ($approver !== null) { 328e72eb5b8SSzymon Olewniczak $data = [ 329e72eb5b8SSzymon Olewniczak 'page' => $page_id, 330e72eb5b8SSzymon Olewniczak 'hidden' => (int) $this->pageInHiddenNamespace($page_id), 331e72eb5b8SSzymon Olewniczak 'approver' => $approver 332e72eb5b8SSzymon Olewniczak ]; 333*4e9ce638SSzymon Olewniczak $this->db->saveRecord('page', $data); // insert or replace 334e72eb5b8SSzymon Olewniczak } 335e72eb5b8SSzymon Olewniczak 336e72eb5b8SSzymon Olewniczak $last_change_date = @filemtime(wikiFN($page_id)); 337*4e9ce638SSzymon Olewniczak // record for current revision exists 338*4e9ce638SSzymon Olewniczak $sql = 'SELECT 1 FROM revision WHERE page=? AND rev=?'; 339*4e9ce638SSzymon Olewniczak $exists = $this->db->queryValue($sql, $page_id, $last_change_date); 340*4e9ce638SSzymon Olewniczak if ($exists === null) { 341*4e9ce638SSzymon Olewniczak // mark previous revision as old. this may be already deleted by DELETE 342*4e9ce638SSzymon Olewniczak $this->db->exec('UPDATE revision SET current=0 WHERE page=? AND current=1', $page_id); 343*4e9ce638SSzymon Olewniczak // create new record 344e72eb5b8SSzymon Olewniczak $this->db->saveRecord('revision', [ 345e72eb5b8SSzymon Olewniczak 'page' => $page_id, 346e72eb5b8SSzymon Olewniczak 'rev' => $last_change_date, 347e72eb5b8SSzymon Olewniczak 'current' => 1 348e72eb5b8SSzymon Olewniczak ]); 349e72eb5b8SSzymon Olewniczak } 350e72eb5b8SSzymon Olewniczak 351*4e9ce638SSzymon Olewniczak } 352*4e9ce638SSzymon Olewniczak 353e72eb5b8SSzymon Olewniczak public function handlePageEdit(string $page_id): void 354e72eb5b8SSzymon Olewniczak { 355e72eb5b8SSzymon Olewniczak $this->db->getPdo()->beginTransaction(); 356e72eb5b8SSzymon Olewniczak $this->updatePage($page_id); 357e72eb5b8SSzymon Olewniczak $this->db->getPdo()->commit(); 358e72eb5b8SSzymon Olewniczak } 359e72eb5b8SSzymon Olewniczak 360e72eb5b8SSzymon Olewniczak public function deleteMaintainer(int $maintainer_id): void 361e72eb5b8SSzymon Olewniczak { 362e72eb5b8SSzymon Olewniczak $this->db->getPdo()->beginTransaction(); 363e72eb5b8SSzymon Olewniczak $this->db->exec('DELETE FROM maintainer WHERE id=?', $maintainer_id); 364e72eb5b8SSzymon Olewniczak $this->db->getPdo()->commit(); 365e72eb5b8SSzymon Olewniczak } 366e72eb5b8SSzymon Olewniczak 367e72eb5b8SSzymon Olewniczak public function addMaintainer(string $namespace, string $approver): void 368e72eb5b8SSzymon Olewniczak { 369e72eb5b8SSzymon Olewniczak $this->db->getPdo()->beginTransaction(); 370e72eb5b8SSzymon Olewniczak $this->db->saveRecord('maintainer', [ 371e72eb5b8SSzymon Olewniczak 'namespace' => $namespace, 372e72eb5b8SSzymon Olewniczak 'approver' => $approver 373e72eb5b8SSzymon Olewniczak ]); 374e72eb5b8SSzymon Olewniczak $this->db->getPdo()->commit(); 375e72eb5b8SSzymon Olewniczak } 376b59355cdSSzymon Olewniczak 377b59355cdSSzymon Olewniczak public function getMaintainers(): ?array 378b59355cdSSzymon Olewniczak { 379b59355cdSSzymon Olewniczak $sql = 'SELECT id, namespace, approver FROM maintainer ORDER BY namespace'; 380b59355cdSSzymon Olewniczak return $this->db->queryAll($sql); 381b59355cdSSzymon Olewniczak } 382e72eb5b8SSzymon Olewniczak} 383