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