1<?php
2
3use dokuwiki\plugin\struct\meta\AccessTable;
4use dokuwiki\plugin\struct\meta\Assignments;
5use dokuwiki\plugin\struct\meta\StructException;
6
7/**
8 * DokuWiki Plugin structacl (Action Component)
9 *
10 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
11 * @author  Anna Dabrowska <dokuwiki@cosmocode.de>
12 */
13class action_plugin_structacl extends \dokuwiki\Extension\ActionPlugin
14{
15    /** @inheritDoc */
16    public function register(Doku_Event_Handler $controller)
17    {
18        $mode = $this->getConf('run');
19        $controller->register_hook('AUTH_ACL_CHECK', $mode, $this, 'handleAclCheck', $mode);
20    }
21
22    /**
23     * Event handler for AUTH_ACL_CHECK.
24     *
25     * If current user is found in a configured struct field of the current page,
26     * upload permissions are granted.
27     *
28     * @param Doku_Event $event event object by reference
29     * @param string $mode BEFORE|AFTER
30     * @return void
31     */
32    public function handleAclCheck(Doku_Event $event, $mode)
33    {
34        global $ID;
35        global $REV;
36
37        $helper = plugin_load('helper', 'structacl');
38        $config = $helper->getConfiguration($this->getConf('fields'));
39
40        if (empty($config)) return;
41
42        // check if current page is assigned a schema from configuration
43        $assignments = Assignments::getInstance();
44        $schemas = $assignments->getPageAssignments($ID);
45
46        if (empty($schemas)) return;
47
48        // get users from schema data
49        $users = [];
50        foreach ($config as $schemaName => $fields) {
51            if (!in_array($schemaName, $schemas)) {
52                continue;
53            }
54            try {
55                $schema = new \dokuwiki\plugin\struct\meta\Schema($schemaName);
56                $schemaData = AccessTable::getPageAccess($schemaName, $ID, (int)$REV);
57                $data = $schemaData->getData();
58                foreach ($fields as $field) {
59                    $col = $schema->findColumn($field);
60                    if ($col && is_a($col->getType(), \dokuwiki\plugin\struct\types\User::class)) {
61                        $value = $data[$field]->getValue();
62                        if (empty($value)) continue;
63                        // multivalue field?
64                        if (is_array($value)) {
65                            $users = array_merge($users, $value);
66                        } else {
67                            $users[] = $value;
68                        }
69                    }
70                }
71            } catch (StructException $ignored) {
72                continue; // no such schema at this revision
73            }
74        }
75
76        // grant upload permissions if current user is found in struct field
77        if (!empty($users) && in_array($event->data['user'], $users)) {
78            $event->result = AUTH_UPLOAD;
79        }
80
81        // disable standard ACL check for non-admins
82        if ($mode === 'BEFORE' && !auth_isadmin()) {
83            $event->preventDefault();
84        }
85    }
86}
87