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