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