xref: /plugin/structpublish/helper/db.php (revision 9ab8cbae39a6ffa37705f745bc76916ea212a92b)
1e394901aSAnna Dabrowska<?php
2e394901aSAnna Dabrowska
3*9ab8cbaeSanndause dokuwiki\Extension\Plugin;
4*9ab8cbaeSanndause dokuwiki\plugin\sqlite\SQLiteDB;
5ed00f27dSAndreas Gohruse dokuwiki\plugin\structpublish\meta\Assignments;
6ed00f27dSAndreas Gohr
7*9ab8cbaeSanndaclass helper_plugin_structpublish_db extends Plugin
85b1fd00bSAndreas Gohr{
95b1fd00bSAndreas Gohr    protected $initialized = false;
105b1fd00bSAndreas Gohr
11ed00f27dSAndreas Gohr    /**
125b1fd00bSAndreas Gohr     * Access the struct database
135b1fd00bSAndreas Gohr     *
145b1fd00bSAndreas Gohr     * Registers our own IS_PUBLISHER function with sqlite
155b1fd00bSAndreas Gohr     *
16*9ab8cbaeSannda     * @return SQLiteDB|null
17ed00f27dSAndreas Gohr     */
185b1fd00bSAndreas Gohr    public function getDB()
19e394901aSAnna Dabrowska    {
205b1fd00bSAndreas Gohr        /** @var helper_plugin_struct_db $struct */
215b1fd00bSAndreas Gohr        $struct = plugin_load('helper', 'struct_db');
225b1fd00bSAndreas Gohr        if (!$struct) {
235b1fd00bSAndreas Gohr            // FIXME show message?
245b1fd00bSAndreas Gohr            return null;
25ed00f27dSAndreas Gohr        }
265b1fd00bSAndreas Gohr        $sqlite = $struct->getDB(false);
2731e730e1SAnna Dabrowska        if (!$sqlite) {
2831e730e1SAnna Dabrowska            return null;
2931e730e1SAnna Dabrowska        }
305b1fd00bSAndreas Gohr
315b1fd00bSAndreas Gohr        // on init
325b1fd00bSAndreas Gohr        if (!$this->initialized) {
335b1fd00bSAndreas Gohr            $sqlite->getPdo()->sqliteCreateFunction('IS_PUBLISHER', [$this, 'isPublisher'], -1);
345b1fd00bSAndreas Gohr            $this->initialized = true;
355b1fd00bSAndreas Gohr        }
365b1fd00bSAndreas Gohr
375b1fd00bSAndreas Gohr        return $sqlite;
38ed00f27dSAndreas Gohr    }
39939e6e3cSAnna Dabrowska
40e394901aSAnna Dabrowska    /**
41910e7e15SAnna Dabrowska     * Get list of all pages known to the plugin
4231e730e1SAnna Dabrowska     *
43910e7e15SAnna Dabrowska     * @return array
44910e7e15SAnna Dabrowska     */
45126b0b8eSAnna Dabrowska    public function getPages()
46910e7e15SAnna Dabrowska    {
475b1fd00bSAndreas Gohr        $sqlite = $this->getDB();
4831e730e1SAnna Dabrowska        if (!$sqlite) {
4931e730e1SAnna Dabrowska            return [];
5031e730e1SAnna Dabrowska        }
515b1fd00bSAndreas Gohr
52126b0b8eSAnna Dabrowska        $sql = 'SELECT pid FROM titles';
535b1fd00bSAndreas Gohr        $list = $sqlite->queryAll($sql);
54126b0b8eSAnna Dabrowska        return array_column($list, 'pid');
55910e7e15SAnna Dabrowska    }
56910e7e15SAnna Dabrowska
57910e7e15SAnna Dabrowska    /**
582467315aSAnna Dabrowska     * Returns true if the given page is included in publishing workflows.
592467315aSAnna Dabrowska     * If no pid is given, check current page.
60939e6e3cSAnna Dabrowska     *
61939e6e3cSAnna Dabrowska     * @return bool
62939e6e3cSAnna Dabrowska     */
632467315aSAnna Dabrowska    public function isPublishable($pid = null)
64939e6e3cSAnna Dabrowska    {
65939e6e3cSAnna Dabrowska        global $ID;
665b1fd00bSAndreas Gohr        $sqlite = $this->getDB();
6731e730e1SAnna Dabrowska        if (!$sqlite) {
6831e730e1SAnna Dabrowska            return false;
6931e730e1SAnna Dabrowska        }
70939e6e3cSAnna Dabrowska
7131e730e1SAnna Dabrowska        if (!$pid) {
7231e730e1SAnna Dabrowska            $pid = $ID;
7331e730e1SAnna Dabrowska        }
742467315aSAnna Dabrowska
75126b0b8eSAnna Dabrowska        $sql = 'SELECT pid FROM structpublish_assignments WHERE pid = ? AND assigned = 1';
762467315aSAnna Dabrowska        return (bool) $sqlite->queryAll($sql, $pid);
77939e6e3cSAnna Dabrowska    }
782b546eccSAndreas Gohr
792b546eccSAndreas Gohr    /**
802b546eccSAndreas Gohr     * Check if the current user has the given roles on the current page
812b546eccSAndreas Gohr     *
822b546eccSAndreas Gohr     * @param string $pid The page ID to check access for
832b546eccSAndreas Gohr     * @param string[] $roles Roles needed. Empty for any role
842b546eccSAndreas Gohr     * @return bool
852b546eccSAndreas Gohr     */
862b546eccSAndreas Gohr    public function checkAccess($pid, $roles = [])
872b546eccSAndreas Gohr    {
88ed00f27dSAndreas Gohr        return self::userHasRole($pid, '', [], $roles);
89ed00f27dSAndreas Gohr    }
90ed00f27dSAndreas Gohr
91ed00f27dSAndreas Gohr    /**
92ed00f27dSAndreas Gohr     * Function registered in SQLite
93ed00f27dSAndreas Gohr     *
94ed00f27dSAndreas Gohr     * Params are read via function args
95ed00f27dSAndreas Gohr     *
96ed00f27dSAndreas Gohr     * @param ...string $pid, $userId, $groups...
97ed00f27dSAndreas Gohr     * @return int Return an integer instead of boolean for better sqlite compatibility
98ed00f27dSAndreas Gohr     */
99*9ab8cbaeSannda    public function isPublisher(...$args)
100ed00f27dSAndreas Gohr    {
101ed00f27dSAndreas Gohr
102ed00f27dSAndreas Gohr        global $USERINFO;
103ed00f27dSAndreas Gohr        global $INPUT;
104ed00f27dSAndreas Gohr        $pid = $args[0];
1052467315aSAnna Dabrowska
10631e730e1SAnna Dabrowska        if (!$pid || !$this->isPublishable($pid)) {
1072467315aSAnna Dabrowska            return 1;
1082467315aSAnna Dabrowska        }
1092467315aSAnna Dabrowska
110ed00f27dSAndreas Gohr        $userId = $args[1] ?? $INPUT->server->str('REMOTE_USER');
111ed00f27dSAndreas Gohr        $grps = $args[2] ?? ($USERINFO['grps'] ?? []);
112ed00f27dSAndreas Gohr
113*9ab8cbaeSannda        return (int)static::userHasRole($pid, $userId, $grps);
114ed00f27dSAndreas Gohr    }
115ed00f27dSAndreas Gohr
116ed00f27dSAndreas Gohr    /**
117ed00f27dSAndreas Gohr     * Check if a given user has role assignment for a given page
118ed00f27dSAndreas Gohr     *
119ed00f27dSAndreas Gohr     * @param string $pid Page to check
120ed00f27dSAndreas Gohr     * @param string $userId User login name, current user if empty
121ed00f27dSAndreas Gohr     * @param string[] $grps Groups the user has, current user's groups if empty user
122ed00f27dSAndreas Gohr     * @param string[] $roles Roles the user should have, empty for any role
123ed00f27dSAndreas Gohr     * @return bool
124ed00f27dSAndreas Gohr     */
125ed00f27dSAndreas Gohr    public static function userHasRole($pid, $userId = '', $grps = [], $roles = [])
126ed00f27dSAndreas Gohr    {
127ed00f27dSAndreas Gohr        global $INPUT;
128ed00f27dSAndreas Gohr        global $USERINFO;
129ed00f27dSAndreas Gohr
130ed00f27dSAndreas Gohr        if (blank($userId)) {
131ed00f27dSAndreas Gohr            $userId = $INPUT->server->str('REMOTE_USER');
132ed00f27dSAndreas Gohr            $grps = $USERINFO['grps'] ?? [];
133ed00f27dSAndreas Gohr        }
134ed00f27dSAndreas Gohr
135ed00f27dSAndreas Gohr        $assignments = Assignments::getInstance();
136ed00f27dSAndreas Gohr        $rules = $assignments->getPageAssignments($pid);
137ed00f27dSAndreas Gohr
138ed00f27dSAndreas Gohr        // if no roles are given, any role is fine
139ed00f27dSAndreas Gohr        if (empty($roles)) {
140ed00f27dSAndreas Gohr            return auth_isMember(
141ed00f27dSAndreas Gohr                implode(',', array_merge(...array_values($rules))),
142ed00f27dSAndreas Gohr                $userId,
143ed00f27dSAndreas Gohr                $grps
144ed00f27dSAndreas Gohr            );
145ed00f27dSAndreas Gohr        }
146ed00f27dSAndreas Gohr
147ed00f27dSAndreas Gohr        foreach ($roles as $role) {
148ed00f27dSAndreas Gohr            if (isset($rules[$role])) {
149ed00f27dSAndreas Gohr                $users = $rules[$role];
150ed00f27dSAndreas Gohr                if (auth_isMember(implode(',', $users), $userId, $grps)) {
151ed00f27dSAndreas Gohr                    return true;
152ed00f27dSAndreas Gohr                }
153ed00f27dSAndreas Gohr            }
154ed00f27dSAndreas Gohr        }
155ed00f27dSAndreas Gohr
156ed00f27dSAndreas Gohr        return false;
1572b546eccSAndreas Gohr    }
158e394901aSAnna Dabrowska}
159