1<?php 2 3use dokuwiki\plugin\structpublish\meta\Assignments; 4 5class helper_plugin_structpublish_db extends DokuWiki_Plugin 6{ 7 protected $initialized = false; 8 9 /** 10 * Access the struct database 11 * 12 * Registers our own IS_PUBLISHER function with sqlite 13 * 14 * @return \dokuwiki\plugin\sqlite\SQLiteDB|null 15 */ 16 public function getDB() 17 { 18 /** @var helper_plugin_struct_db $struct */ 19 $struct = plugin_load('helper', 'struct_db'); 20 if(!$struct) { 21 // FIXME show message? 22 return null; 23 } 24 $sqlite = $struct->getDB(false); 25 if(!$sqlite) return null; 26 27 // on init 28 if(!$this->initialized) { 29 $sqlite->getPdo()->sqliteCreateFunction('IS_PUBLISHER', [$this, 'isPublisher'], -1); 30 $this->initialized = true; 31 } 32 33 return $sqlite; 34 } 35 36 /** 37 * Get list of all pages known to the plugin 38 * @return array 39 */ 40 public function getPages() 41 { 42 $sqlite = $this->getDB(); 43 if(!$sqlite) return []; 44 45 $sql = 'SELECT pid FROM titles'; 46 $list = $sqlite->queryAll($sql); 47 return array_column($list, 'pid'); 48 } 49 50 /** 51 * Returns true if the given page is included in publishing workflows. 52 * If no pid is given, check current page. 53 * 54 * @return bool 55 */ 56 public function isPublishable($pid = null) 57 { 58 global $ID; 59 $sqlite = $this->getDB(); 60 if(!$sqlite) return false; 61 62 if (!$pid) $pid = $ID; 63 64 $sql = 'SELECT pid FROM structpublish_assignments WHERE pid = ? AND assigned = 1'; 65 return (bool) $sqlite->queryAll($sql, $pid); 66 } 67 68 /** 69 * Check if the current user has the given roles on the current page 70 * 71 * @param string $pid The page ID to check access for 72 * @param string[] $roles Roles needed. Empty for any role 73 * @return bool 74 */ 75 public function checkAccess($pid, $roles = []) 76 { 77 return self::userHasRole($pid, '', [], $roles); 78 } 79 80 /** 81 * Function registered in SQLite 82 * 83 * Params are read via function args 84 * 85 * @param ...string $pid, $userId, $groups... 86 * @return int Return an integer instead of boolean for better sqlite compatibility 87 */ 88 public function isPublisher() 89 { 90 91 global $USERINFO; 92 global $INPUT; 93 94 $args = func_get_args(); 95 $pid = $args[0]; 96 97 if (!$pid) return 1; 98 99 if (!$this->isPublishable($pid)) { 100 return 1; 101 } 102 103 $userId = $args[1] ?? $INPUT->server->str('REMOTE_USER'); 104 $grps = $args[2] ?? ($USERINFO['grps'] ?? []); 105 106 return (int)$this->userHasRole( 107 $pid, 108 $userId, 109 $grps 110 ); 111 } 112 113 /** 114 * Check if a given user has role assignment for a given page 115 * 116 * @param string $pid Page to check 117 * @param string $userId User login name, current user if empty 118 * @param string[] $grps Groups the user has, current user's groups if empty user 119 * @param string[] $roles Roles the user should have, empty for any role 120 * @return bool 121 */ 122 public static function userHasRole($pid, $userId = '', $grps = [], $roles = []) 123 { 124 global $INPUT; 125 global $USERINFO; 126 127 if (blank($userId)) { 128 $userId = $INPUT->server->str('REMOTE_USER'); 129 $grps = $USERINFO['grps'] ?? []; 130 } 131 132 $assignments = Assignments::getInstance(); 133 $rules = $assignments->getPageAssignments($pid); 134 135 // if no roles are given, any role is fine 136 if (empty($roles)) { 137 return auth_isMember( 138 implode(',', array_merge(...array_values($rules))), 139 $userId, 140 $grps 141 ); 142 } 143 144 foreach ($roles as $role) { 145 if (isset($rules[$role])) { 146 $users = $rules[$role]; 147 if (auth_isMember(implode(',', $users), $userId, $grps)) { 148 return true; 149 } 150 } 151 } 152 153 return false; 154 } 155 156} 157