1<?php
2
3/**
4 * DokuWiki Plugin struct (Helper Component)
5 *
6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
7 * @author  Andreas Gohr, Michael Große <dokuwiki@cosmocode.de>
8 */
9
10// must be run within Dokuwiki
11use dokuwiki\Remote\RemoteException;
12use dokuwiki\Extension\RemotePlugin;
13use dokuwiki\Remote\AccessDeniedException;
14use dokuwiki\plugin\struct\meta\Value;
15use dokuwiki\plugin\struct\meta\ConfigParser;
16use dokuwiki\plugin\struct\meta\SearchConfig;
17use dokuwiki\plugin\struct\meta\StructException;
18
19class remote_plugin_struct extends RemotePlugin
20{
21    /** @var helper_plugin_struct hlp */
22    protected $hlp;
23
24    /**
25     * remote_plugin_struct constructor.
26     */
27    public function __construct()
28    {
29        parent::__construct();
30
31        $this->hlp = plugin_load('helper', 'struct');
32    }
33
34    /**
35     * Get the structured data of a given page
36     *
37     * @param string $page The page to get data for
38     * @param string $schema The schema to use empty for all
39     * @param int $time A timestamp if you want historic data (0 for now)
40     * @return array ('schema' => ( 'fieldlabel' => 'value', ...))
41     * @throws AccessDeniedException
42     * @throws RemoteException
43     */
44    public function getData($page, $schema, $time)
45    {
46        $page = cleanID($page);
47
48        if (auth_quickaclcheck($page) < AUTH_READ) {
49            throw new AccessDeniedException('no permissions to access data of that page');
50        }
51
52        if (!$schema) $schema = null;
53
54        try {
55            return $this->hlp->getData($page, $schema, $time);
56        } catch (StructException $e) {
57            throw new RemoteException($e->getMessage(), 0, $e);
58        }
59    }
60
61
62    /**
63     * Saves data for a given page (creates a new revision)
64     *
65     * If this call succeeds you can assume your data has either been saved or it was
66     * not necessary to save it because the data already existed in the wanted form or
67     * the given schemas are no longer assigned to that page.
68     *
69     * @param string $page
70     * @param array $data ('schema' => ( 'fieldlabel' => 'value', ...))
71     * @param string $summary
72     * @param bool $minor
73     * @return bool returns always true
74     * @throws AccessDeniedException
75     * @throws RemoteException
76     */
77    public function saveData($page, $data, $summary, $minor = false)
78    {
79        $page = cleanID($page);
80
81        if (auth_quickaclcheck($page) < AUTH_EDIT) {
82            throw new AccessDeniedException('no permissions to save data for that page');
83        }
84
85        try {
86            $this->hlp->saveData($page, $data, $summary, $minor);
87            return true;
88        } catch (StructException $e) {
89            throw new RemoteException($e->getMessage(), 0, $e);
90        }
91    }
92
93    /**
94     * Get info about existing schemas columns
95     *
96     * Returns only current, enabled columns
97     *
98     * @param string $schema the schema to query, empty for all
99     * @return array
100     * @throws AccessDeniedException
101     * @throws RemoteException
102     */
103    public function getSchema($schema = null)
104    {
105        if (!auth_ismanager()) {
106            throw new AccessDeniedException('you need to be manager to access schema info');
107        }
108
109        try {
110            $result = [];
111            $schemas = $this->hlp::getSchema($schema ?: null);
112            foreach ($schemas as $name => $schema) {
113                $result[$name] = [];
114                foreach ($schema->getColumns(false) as $column) {
115                    $class = explode('\\', get_class($column->getType()));
116                    $class = array_pop($class);
117                    $result[$name][] = [
118                        'name' => $column->getLabel(),
119                        'type' => $class,
120                        'ismulti' => $column->isMulti()];
121                }
122            }
123            return $result;
124        } catch (StructException $e) {
125            throw new RemoteException($e->getMessage(), 0, $e);
126        }
127    }
128
129    /**
130     * Get the data that would be shown in an aggregation
131     *
132     * @param array $schemas array of strings with the schema-names
133     * @param array $cols array of strings with the columns
134     * @param array $filter array of arrays with ['logic'=> 'and'|'or', 'condition' => 'your condition']
135     * @param string $sort string indicating the column to sort by
136     *
137     * @return array array of rows, each row is an array of the column values
138     * @throws RemoteException
139     */
140    public function getAggregationData(array $schemas, array $cols, array $filter = [], $sort = '')
141    {
142        $schemaLine = 'schema: ' . implode(', ', $schemas);
143        $columnLine = 'cols: ' . implode(', ', $cols);
144        $filterLines = array_map(
145            static fn($filter) => 'filter' . $filter['logic'] . ': ' . $filter['condition'],
146            $filter
147        );
148        $sortLine = 'sort: ' . $sort;
149        // schemas, cols, REV?, filter, order
150
151        try {
152            $parser = new ConfigParser(array_merge([$schemaLine, $columnLine, $sortLine], $filterLines));
153            $config = $parser->getConfig();
154            $search = new SearchConfig($config);
155            $results = $search->getRows();
156            $data = [];
157            /** @var Value[] $rowValues */
158            foreach ($results as $rowValues) {
159                $row = [];
160                foreach ($rowValues as $value) {
161                    $row[$value->getColumn()->getFullQualifiedLabel()] = $value->getDisplayValue();
162                }
163                $data[] = $row;
164            }
165            return $data;
166        } catch (StructException $e) {
167            throw new RemoteException($e->getMessage(), 0, $e);
168        }
169    }
170}
171