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