xref: /plugin/structpublish/helper/db.php (revision 31e730e145521fb7010758415a11c928f44439b8) !
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);
25*31e730e1SAnna Dabrowska        if (!$sqlite) {
26*31e730e1SAnna Dabrowska            return null;
27*31e730e1SAnna Dabrowska        }
285b1fd00bSAndreas Gohr
295b1fd00bSAndreas Gohr        // on init
305b1fd00bSAndreas Gohr        if (!$this->initialized) {
315b1fd00bSAndreas Gohr            $sqlite->getPdo()->sqliteCreateFunction('IS_PUBLISHER', [$this, 'isPublisher'], -1);
325b1fd00bSAndreas Gohr            $this->initialized = true;
335b1fd00bSAndreas Gohr        }
345b1fd00bSAndreas Gohr
355b1fd00bSAndreas Gohr        return $sqlite;
36ed00f27dSAndreas Gohr    }
37939e6e3cSAnna Dabrowska
38e394901aSAnna Dabrowska    /**
39910e7e15SAnna Dabrowska     * Get list of all pages known to the plugin
40*31e730e1SAnna Dabrowska     *
41910e7e15SAnna Dabrowska     * @return array
42910e7e15SAnna Dabrowska     */
43126b0b8eSAnna Dabrowska    public function getPages()
44910e7e15SAnna Dabrowska    {
455b1fd00bSAndreas Gohr        $sqlite = $this->getDB();
46*31e730e1SAnna Dabrowska        if (!$sqlite) {
47*31e730e1SAnna Dabrowska            return [];
48*31e730e1SAnna Dabrowska        }
495b1fd00bSAndreas Gohr
50126b0b8eSAnna Dabrowska        $sql = 'SELECT pid FROM titles';
515b1fd00bSAndreas Gohr        $list = $sqlite->queryAll($sql);
52126b0b8eSAnna Dabrowska        return array_column($list, 'pid');
53910e7e15SAnna Dabrowska    }
54910e7e15SAnna Dabrowska
55910e7e15SAnna Dabrowska    /**
562467315aSAnna Dabrowska     * Returns true if the given page is included in publishing workflows.
572467315aSAnna Dabrowska     * If no pid is given, check current page.
58939e6e3cSAnna Dabrowska     *
59939e6e3cSAnna Dabrowska     * @return bool
60939e6e3cSAnna Dabrowska     */
612467315aSAnna Dabrowska    public function isPublishable($pid = null)
62939e6e3cSAnna Dabrowska    {
63939e6e3cSAnna Dabrowska        global $ID;
645b1fd00bSAndreas Gohr        $sqlite = $this->getDB();
65*31e730e1SAnna Dabrowska        if (!$sqlite) {
66*31e730e1SAnna Dabrowska            return false;
67*31e730e1SAnna Dabrowska        }
68939e6e3cSAnna Dabrowska
69*31e730e1SAnna Dabrowska        if (!$pid) {
70*31e730e1SAnna Dabrowska            $pid = $ID;
71*31e730e1SAnna Dabrowska        }
722467315aSAnna Dabrowska
73126b0b8eSAnna Dabrowska        $sql = 'SELECT pid FROM structpublish_assignments WHERE pid = ? AND assigned = 1';
742467315aSAnna Dabrowska        return (bool) $sqlite->queryAll($sql, $pid);
75939e6e3cSAnna Dabrowska    }
762b546eccSAndreas Gohr
772b546eccSAndreas Gohr    /**
782b546eccSAndreas Gohr     * Check if the current user has the given roles on the current page
792b546eccSAndreas Gohr     *
802b546eccSAndreas Gohr     * @param string $pid The page ID to check access for
812b546eccSAndreas Gohr     * @param string[] $roles Roles needed. Empty for any role
822b546eccSAndreas Gohr     * @return bool
832b546eccSAndreas Gohr     */
842b546eccSAndreas Gohr    public function checkAccess($pid, $roles = [])
852b546eccSAndreas Gohr    {
86ed00f27dSAndreas Gohr        return self::userHasRole($pid, '', [], $roles);
87ed00f27dSAndreas Gohr    }
88ed00f27dSAndreas Gohr
89ed00f27dSAndreas Gohr    /**
90ed00f27dSAndreas Gohr     * Function registered in SQLite
91ed00f27dSAndreas Gohr     *
92ed00f27dSAndreas Gohr     * Params are read via function args
93ed00f27dSAndreas Gohr     *
94ed00f27dSAndreas Gohr     * @param ...string $pid, $userId, $groups...
95ed00f27dSAndreas Gohr     * @return int Return an integer instead of boolean for better sqlite compatibility
96ed00f27dSAndreas Gohr     */
97ed00f27dSAndreas Gohr    public function isPublisher()
98ed00f27dSAndreas Gohr    {
99ed00f27dSAndreas Gohr
100ed00f27dSAndreas Gohr        global $USERINFO;
101ed00f27dSAndreas Gohr        global $INPUT;
102ed00f27dSAndreas Gohr
103ed00f27dSAndreas Gohr        $args = func_get_args();
104ed00f27dSAndreas Gohr        $pid = $args[0];
1052467315aSAnna Dabrowska
106*31e730e1SAnna 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
113ed00f27dSAndreas Gohr        return (int)$this->userHasRole(
114ed00f27dSAndreas Gohr            $pid,
115ed00f27dSAndreas Gohr            $userId,
116ed00f27dSAndreas Gohr            $grps
117ed00f27dSAndreas Gohr        );
118ed00f27dSAndreas Gohr    }
119ed00f27dSAndreas Gohr
120ed00f27dSAndreas Gohr    /**
121ed00f27dSAndreas Gohr     * Check if a given user has role assignment for a given page
122ed00f27dSAndreas Gohr     *
123ed00f27dSAndreas Gohr     * @param string $pid Page to check
124ed00f27dSAndreas Gohr     * @param string $userId User login name, current user if empty
125ed00f27dSAndreas Gohr     * @param string[] $grps Groups the user has, current user's groups if empty user
126ed00f27dSAndreas Gohr     * @param string[] $roles Roles the user should have, empty for any role
127ed00f27dSAndreas Gohr     * @return bool
128ed00f27dSAndreas Gohr     */
129ed00f27dSAndreas Gohr    public static function userHasRole($pid, $userId = '', $grps = [], $roles = [])
130ed00f27dSAndreas Gohr    {
131ed00f27dSAndreas Gohr        global $INPUT;
132ed00f27dSAndreas Gohr        global $USERINFO;
133ed00f27dSAndreas Gohr
134ed00f27dSAndreas Gohr        if (blank($userId)) {
135ed00f27dSAndreas Gohr            $userId = $INPUT->server->str('REMOTE_USER');
136ed00f27dSAndreas Gohr            $grps = $USERINFO['grps'] ?? [];
137ed00f27dSAndreas Gohr        }
138ed00f27dSAndreas Gohr
139ed00f27dSAndreas Gohr        $assignments = Assignments::getInstance();
140ed00f27dSAndreas Gohr        $rules = $assignments->getPageAssignments($pid);
141ed00f27dSAndreas Gohr
142ed00f27dSAndreas Gohr        // if no roles are given, any role is fine
143ed00f27dSAndreas Gohr        if (empty($roles)) {
144ed00f27dSAndreas Gohr            return auth_isMember(
145ed00f27dSAndreas Gohr                implode(',', array_merge(...array_values($rules))),
146ed00f27dSAndreas Gohr                $userId,
147ed00f27dSAndreas Gohr                $grps
148ed00f27dSAndreas Gohr            );
149ed00f27dSAndreas Gohr        }
150ed00f27dSAndreas Gohr
151ed00f27dSAndreas Gohr        foreach ($roles as $role) {
152ed00f27dSAndreas Gohr            if (isset($rules[$role])) {
153ed00f27dSAndreas Gohr                $users = $rules[$role];
154ed00f27dSAndreas Gohr                if (auth_isMember(implode(',', $users), $userId, $grps)) {
155ed00f27dSAndreas Gohr                    return true;
156ed00f27dSAndreas Gohr                }
157ed00f27dSAndreas Gohr            }
158ed00f27dSAndreas Gohr        }
159ed00f27dSAndreas Gohr
160ed00f27dSAndreas Gohr        return false;
1612b546eccSAndreas Gohr    }
162e394901aSAnna Dabrowska}
163