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