xref: /plugin/structpublish/helper/db.php (revision 2467315abf73fd4101807db1a2bc8556e173dd38)
1e394901aSAnna Dabrowska<?php
2e394901aSAnna Dabrowska
3ed00f27dSAndreas Gohruse dokuwiki\plugin\structpublish\meta\Assignments;
4ed00f27dSAndreas Gohr
55b1fd00bSAndreas Gohrclass helper_plugin_structpublish_db extends DokuWiki_Plugin
65b1fd00bSAndreas Gohr{
75b1fd00bSAndreas Gohr    protected $initialized = false;
85b1fd00bSAndreas Gohr
9ed00f27dSAndreas Gohr    /**
105b1fd00bSAndreas Gohr     * Access the struct database
115b1fd00bSAndreas Gohr     *
125b1fd00bSAndreas Gohr     * Registers our own IS_PUBLISHER function with sqlite
135b1fd00bSAndreas Gohr     *
145b1fd00bSAndreas Gohr     * @return \dokuwiki\plugin\sqlite\SQLiteDB|null
15ed00f27dSAndreas Gohr     */
165b1fd00bSAndreas Gohr    public function getDB()
17e394901aSAnna Dabrowska    {
185b1fd00bSAndreas Gohr        /** @var helper_plugin_struct_db $struct */
195b1fd00bSAndreas Gohr        $struct = plugin_load('helper', 'struct_db');
205b1fd00bSAndreas Gohr        if(!$struct) {
215b1fd00bSAndreas Gohr            // FIXME show message?
225b1fd00bSAndreas Gohr            return null;
23ed00f27dSAndreas Gohr        }
245b1fd00bSAndreas Gohr        $sqlite = $struct->getDB(false);
255b1fd00bSAndreas Gohr        if(!$sqlite) return null;
265b1fd00bSAndreas Gohr
275b1fd00bSAndreas Gohr        // on init
285b1fd00bSAndreas Gohr        if(!$this->initialized) {
295b1fd00bSAndreas Gohr            $sqlite->getPdo()->sqliteCreateFunction('IS_PUBLISHER', [$this, 'isPublisher'], -1);
305b1fd00bSAndreas Gohr            $this->initialized = true;
315b1fd00bSAndreas Gohr        }
325b1fd00bSAndreas Gohr
335b1fd00bSAndreas Gohr        return $sqlite;
34ed00f27dSAndreas Gohr    }
35939e6e3cSAnna Dabrowska
36e394901aSAnna Dabrowska    /**
37910e7e15SAnna Dabrowska     * Get list of all pages known to the plugin
38910e7e15SAnna Dabrowska     * @return array
39910e7e15SAnna Dabrowska     */
40126b0b8eSAnna Dabrowska    public function getPages()
41910e7e15SAnna Dabrowska    {
425b1fd00bSAndreas Gohr        $sqlite = $this->getDB();
435b1fd00bSAndreas Gohr        if(!$sqlite) return [];
445b1fd00bSAndreas Gohr
45126b0b8eSAnna Dabrowska        $sql = 'SELECT pid FROM titles';
465b1fd00bSAndreas Gohr        $list = $sqlite->queryAll($sql);
47126b0b8eSAnna Dabrowska        return array_column($list, 'pid');
48910e7e15SAnna Dabrowska    }
49910e7e15SAnna Dabrowska
50910e7e15SAnna Dabrowska    /**
51*2467315aSAnna Dabrowska     * Returns true if the given page is included in publishing workflows.
52*2467315aSAnna Dabrowska     * If no pid is given, check current page.
53939e6e3cSAnna Dabrowska     *
54939e6e3cSAnna Dabrowska     * @return bool
55939e6e3cSAnna Dabrowska     */
56*2467315aSAnna Dabrowska    public function isPublishable($pid = null)
57939e6e3cSAnna Dabrowska    {
58939e6e3cSAnna Dabrowska        global $ID;
595b1fd00bSAndreas Gohr        $sqlite = $this->getDB();
605b1fd00bSAndreas Gohr        if(!$sqlite) return false;
61939e6e3cSAnna Dabrowska
62*2467315aSAnna Dabrowska        if (!$pid) $pid = $ID;
63*2467315aSAnna Dabrowska
64126b0b8eSAnna Dabrowska        $sql = 'SELECT pid FROM structpublish_assignments WHERE pid = ? AND assigned = 1';
65*2467315aSAnna Dabrowska        return (bool) $sqlite->queryAll($sql, $pid);
66939e6e3cSAnna Dabrowska    }
672b546eccSAndreas Gohr
682b546eccSAndreas Gohr    /**
692b546eccSAndreas Gohr     * Check if the current user has the given roles on the current page
702b546eccSAndreas Gohr     *
712b546eccSAndreas Gohr     * @param string $pid The page ID to check access for
722b546eccSAndreas Gohr     * @param string[] $roles Roles needed. Empty for any role
732b546eccSAndreas Gohr     * @return bool
742b546eccSAndreas Gohr     */
752b546eccSAndreas Gohr    public function checkAccess($pid, $roles = [])
762b546eccSAndreas Gohr    {
77ed00f27dSAndreas Gohr        return self::userHasRole($pid, '', [], $roles);
78ed00f27dSAndreas Gohr    }
79ed00f27dSAndreas Gohr
80ed00f27dSAndreas Gohr    /**
81ed00f27dSAndreas Gohr     * Function registered in SQLite
82ed00f27dSAndreas Gohr     *
83ed00f27dSAndreas Gohr     * Params are read via function args
84ed00f27dSAndreas Gohr     *
85ed00f27dSAndreas Gohr     * @param ...string $pid, $userId, $groups...
86ed00f27dSAndreas Gohr     * @return int Return an integer instead of boolean for better sqlite compatibility
87ed00f27dSAndreas Gohr     */
88ed00f27dSAndreas Gohr    public function isPublisher()
89ed00f27dSAndreas Gohr    {
90ed00f27dSAndreas Gohr
91ed00f27dSAndreas Gohr        global $USERINFO;
92ed00f27dSAndreas Gohr        global $INPUT;
93ed00f27dSAndreas Gohr
94ed00f27dSAndreas Gohr        $args = func_get_args();
95ed00f27dSAndreas Gohr        $pid = $args[0];
96*2467315aSAnna Dabrowska
97*2467315aSAnna Dabrowska        if (!$pid) return 1;
98*2467315aSAnna Dabrowska
99*2467315aSAnna Dabrowska        if (!$this->isPublishable($pid)) {
100*2467315aSAnna Dabrowska            return 1;
101*2467315aSAnna Dabrowska        }
102*2467315aSAnna Dabrowska
103ed00f27dSAndreas Gohr        $userId = $args[1] ?? $INPUT->server->str('REMOTE_USER');
104ed00f27dSAndreas Gohr        $grps = $args[2] ?? ($USERINFO['grps'] ?? []);
105ed00f27dSAndreas Gohr
106ed00f27dSAndreas Gohr        return (int)$this->userHasRole(
107ed00f27dSAndreas Gohr            $pid,
108ed00f27dSAndreas Gohr            $userId,
109ed00f27dSAndreas Gohr            $grps
110ed00f27dSAndreas Gohr        );
111ed00f27dSAndreas Gohr    }
112ed00f27dSAndreas Gohr
113ed00f27dSAndreas Gohr    /**
114ed00f27dSAndreas Gohr     * Check if a given user has role assignment for a given page
115ed00f27dSAndreas Gohr     *
116ed00f27dSAndreas Gohr     * @param string $pid Page to check
117ed00f27dSAndreas Gohr     * @param string $userId User login name, current user if empty
118ed00f27dSAndreas Gohr     * @param string[] $grps Groups the user has, current user's groups if empty user
119ed00f27dSAndreas Gohr     * @param string[] $roles Roles the user should have, empty for any role
120ed00f27dSAndreas Gohr     * @return bool
121ed00f27dSAndreas Gohr     */
122ed00f27dSAndreas Gohr    public static function userHasRole($pid, $userId = '', $grps = [], $roles = [])
123ed00f27dSAndreas Gohr    {
124ed00f27dSAndreas Gohr        global $INPUT;
125ed00f27dSAndreas Gohr        global $USERINFO;
126ed00f27dSAndreas Gohr
127ed00f27dSAndreas Gohr        if (blank($userId)) {
128ed00f27dSAndreas Gohr            $userId = $INPUT->server->str('REMOTE_USER');
129ed00f27dSAndreas Gohr            $grps = $USERINFO['grps'] ?? [];
130ed00f27dSAndreas Gohr        }
131ed00f27dSAndreas Gohr
132ed00f27dSAndreas Gohr        $assignments = Assignments::getInstance();
133ed00f27dSAndreas Gohr        $rules = $assignments->getPageAssignments($pid);
134ed00f27dSAndreas Gohr
135ed00f27dSAndreas Gohr        // if no roles are given, any role is fine
136ed00f27dSAndreas Gohr        if (empty($roles)) {
137ed00f27dSAndreas Gohr            return auth_isMember(
138ed00f27dSAndreas Gohr                implode(',', array_merge(...array_values($rules))),
139ed00f27dSAndreas Gohr                $userId,
140ed00f27dSAndreas Gohr                $grps
141ed00f27dSAndreas Gohr            );
142ed00f27dSAndreas Gohr        }
143ed00f27dSAndreas Gohr
144ed00f27dSAndreas Gohr        foreach ($roles as $role) {
145ed00f27dSAndreas Gohr            if (isset($rules[$role])) {
146ed00f27dSAndreas Gohr                $users = $rules[$role];
147ed00f27dSAndreas Gohr                if (auth_isMember(implode(',', $users), $userId, $grps)) {
148ed00f27dSAndreas Gohr                    return true;
149ed00f27dSAndreas Gohr                }
150ed00f27dSAndreas Gohr            }
151ed00f27dSAndreas Gohr        }
152ed00f27dSAndreas Gohr
153ed00f27dSAndreas Gohr        return false;
1542b546eccSAndreas Gohr    }
1552b546eccSAndreas Gohr
156e394901aSAnna Dabrowska}
157