xref: /plugin/structpublish/helper/db.php (revision 2467315abf73fd4101807db1a2bc8556e173dd38)
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