1<?php
2
3namespace dokuwiki\plugin\struct\test;
4
5use dokuwiki\plugin\struct\meta\ConfigParser;
6use dokuwiki\plugin\struct\meta\PageMeta;
7use dokuwiki\plugin\struct\test\mock\AccessTable;
8use dokuwiki\plugin\struct\test\mock\AccessTablePage;
9use dokuwiki\plugin\struct\test\mock\AggregationEditorTable;
10use dokuwiki\plugin\struct\test\mock\AggregationTable;
11use dokuwiki\plugin\struct\test\mock\SearchConfig;
12
13/**
14 * Testing serial data
15 *
16 * @group plugin_struct
17 * @group plugins
18 */
19class AggregationResults_struct_test extends StructTest
20{
21    protected $sqlite;
22
23    public function setUp(): void
24    {
25        parent::setUp();
26
27        $sqlite = plugin_load('helper', 'struct_db');
28        $this->sqlite = $sqlite->getDB();
29
30        $this->loadSchemaJSON('schema1');
31
32        $assignments = mock\Assignments::getInstance();
33        $assignments->clear(true);
34
35        for ($i = 0; $i < 3; $i++) {
36            // assign a schema
37            $assignments->assignPageSchema("test$i", 'schema1');
38
39            // save wiki pages
40            saveWikiText("test$i", "test$i", "test$i");
41
42            // save serial data
43            $data = [
44                'first' => "foo$i",
45                'second' => ["bar$i", "baz$i"],
46                'third' => "foobar$i",
47                'fourth' => "barfoo$i",
48            ];
49            $access = AccessTable::getSerialAccess('schema1', "test$i");
50            $access->saveData($data);
51        }
52    }
53
54    /**
55     * Test whether serial syntax produces a table of serial data limited to current page
56     */
57    public function test_pid()
58    {
59        // \syntax_plugin_struct_serial accesses the global $ID
60        $id = 'test1';
61        $schema = 'schema1';
62        $result = $this->fetchResult($schema, $id, []);
63
64        $this->assertEquals(1, count($result));
65        $this->assertEquals('test1', $result[0][0]->getValue());
66        // skip %rowid% column and test saved values
67        $this->assertEquals('foo1', $result[0][2]->getValue());
68        $this->assertEquals(['bar1', 'baz1'], $result[0][3]->getValue());
69        $this->assertEquals('foobar1', $result[0][4]->getValue());
70        $this->assertEquals('barfoo1', $result[0][5]->getValue());
71    }
72
73    /**
74     * Test simple text filter
75     */
76    public function test_filter_text()
77    {
78        $schema = 'schema1';
79        $result = $this->fetchResult($schema, 'test0');
80        $this->assertEquals(1, count($result));
81
82        $result = $this->fetchResult($schema, 'test0', ['first', '=', 'foo0', 'AND']);
83        $this->assertEquals(1, count($result));
84
85        $result = $this->fetchResult($schema, 'test0', ['first', '!=', 'foo0', 'AND']);
86        $this->assertEquals(0, count($result));
87    }
88
89    /**
90     * Test filtering on a page field, with 'usetitles' set to true and false
91     */
92    public function test_filter_page()
93    {
94        $this->prepareLookup();
95        $schema = 'pageschema';
96        $result = $this->fetchResult($schema);
97        $this->assertEquals(3, count($result));
98
99        // 'usetitles' = true
100        $result = $this->fetchResult($schema, '', ['singletitle', '*~', 'another', 'AND']);
101        $this->assertEquals(1, count($result));
102
103        // 'usetitles' = false
104        $result = $this->fetchResult($schema, '', ['singlepage', '*~', 'this', 'AND']);
105        $this->assertEquals(0, count($result));
106    }
107
108    /**
109     * Test whether aggregation tables respect revoking of schema assignments
110     */
111    public function test_assignments()
112    {
113        $result = $this->fetchPagesResult('schema1');
114        $this->assertEquals(3, count($result));
115
116        // revoke assignment
117        $assignments = mock\Assignments::getInstance();
118        $assignments->deassignPageSchema('test0', 'schema1');
119
120        $result = $this->fetchPagesResult('schema1');
121        $this->assertEquals(2, count($result));
122    }
123
124
125    /**
126     * Initialize a lookup table from syntax and return the result from its internal search.
127     *
128     * @param string $schema
129     * @param string $id
130     * @param array $filters
131     * @return \dokuwiki\plugin\struct\meta\Value[][]
132     */
133    protected function fetchPagesResult($schema, $id = '', $filters = [])
134    {
135        $syntaxConfig = ['schema: ' . $schema, 'cols: %pageid%, %rowid%, *'];
136        $configParser = new ConfigParser($syntaxConfig);
137        $config = $configParser->getConfig();
138
139        if ($filters) array_push($config['filter'], $filters);
140        $search = new SearchConfig($config);
141
142        $table = new AggregationTable($id, 'xhtml', new \Doku_Renderer_xhtml(), $search);
143        return $table->getResult();
144    }
145
146    /**
147     * Initialize a lookup table from syntax and return the result from its internal search.
148     *
149     * @param string $schema
150     * @param string $id
151     * @param array $filters
152     * @return \dokuwiki\plugin\struct\meta\Value[][]
153     */
154    protected function fetchResult($schema, $id = '', $filters = [])
155    {
156        $syntaxConfig = ['schema: ' . $schema, 'cols: %pageid%, %rowid%, *'];
157        $configParser = new ConfigParser($syntaxConfig);
158        $config = $configParser->getConfig();
159
160        // FIXME simulate addYypeFilter() from \syntax_plugin_struct_serial or \syntax_plugin_struct_lookup
161        if ($id) {
162            $config['filter'][] = ['%rowid%', '!=', (string)AccessTablePage::DEFAULT_PAGE_RID, 'AND'];
163            $config['filter'][] = ['%pageid%', '=', $id, 'AND'];
164        } else {
165            $config['filter'][] = ['%rowid%', '!=', (string)\dokuwiki\plugin\struct\meta\AccessTablePage::DEFAULT_PAGE_RID, 'AND'];
166            $config['filter'][] = ['%pageid%', '=*', '^(?![\s\S])', 'AND'];
167        }
168
169        if ($filters) array_push($config['filter'], $filters);
170        $search = new SearchConfig($config);
171
172        $table = new AggregationEditorTable($id, 'xhtml', new \Doku_Renderer_xhtml(), $search);
173        return $table->getResult();
174    }
175
176    protected function prepareLookup()
177    {
178        saveWikiText('title1', 'test', 'test');
179        $pageMeta = new PageMeta('title1');
180        $pageMeta->setTitle('This is a title');
181
182        saveWikiText('title2', 'test', 'test');
183        $pageMeta = new PageMeta('title2');
184        $pageMeta->setTitle('This is a 2nd title');
185
186        saveWikiText('title3', 'test', 'test');
187        $pageMeta = new PageMeta('title3');
188        $pageMeta->setTitle('Another Title');
189
190        $this->loadSchemaJSON('pageschema');
191        $access = AccessTable::getGlobalAccess('pageschema');
192        $access->saveData(
193            array(
194                'singlepage' => 'title1',
195                'multipage' => array('title1'),
196                'singletitle' => 'title1',
197                'multititle' => array('title1'),
198            )
199        );
200        $access = AccessTable::getGlobalAccess('pageschema');
201        $access->saveData(
202            array(
203                'singlepage' => 'title2',
204                'multipage' => array('title2'),
205                'singletitle' => 'title2',
206                'multititle' => array('title2'),
207            )
208        );
209        $access = AccessTable::getGlobalAccess('pageschema');
210        $access->saveData(
211            array(
212                'singlepage' => 'title3',
213                'multipage' => array('title3'),
214                'singletitle' => 'title3',
215                'multititle' => array('title3'),
216            )
217        );
218    }
219}
220