xref: /plugin/struct/_test/AggregationResultsTest.php (revision 8fed17f342cc190557a6ce94d1787f9e2f63cb6c)
1<?php
2
3namespace dokuwiki\plugin\struct\test;
4
5use dokuwiki\plugin\struct\meta\AccessTablePage;
6use dokuwiki\plugin\struct\meta\ConfigParser;
7use dokuwiki\plugin\struct\meta\PageMeta;
8use dokuwiki\plugin\struct\test\mock\AccessTable as MockAccessTableAlias;
9use dokuwiki\plugin\struct\test\mock\AggregationEditorTable as MockAggregationEditorTableAlias;
10use dokuwiki\plugin\struct\test\mock\AggregationTable as MockAggregationTableAlias;
11use dokuwiki\plugin\struct\test\mock\SearchConfig as MockSearchConfigAlias;
12
13/**
14 * Testing serial data
15 *
16 * @group plugin_struct
17 * @group plugins
18 */
19class AggregationResultsTest 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 = MockAccessTableAlias::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->assertCount(1, $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->assertCount(1, $result);
81
82        $result = $this->fetchResult($schema, 'test0', ['first', '=', 'foo0', 'AND']);
83        $this->assertCount(1, $result);
84
85        $result = $this->fetchResult($schema, 'test0', ['first', '!=', 'foo0', 'AND']);
86        $this->assertCount(0, $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->assertCount(3, $result);
98
99        // 'usetitles' = true
100        $result = $this->fetchResult($schema, '', ['singletitle', '*~', 'another', 'AND']);
101        $this->assertCount(1, $result);
102
103        // 'usetitles' = false
104        $result = $this->fetchResult($schema, '', ['singlepage', '*~', 'this', 'AND']);
105        $this->assertCount(0, $result);
106    }
107
108    /**
109     * Test filtering on a DateTime field
110     */
111    public function test_filter_datetime()
112    {
113        $this->prepareDatetime();
114        $schema = 'datetime';
115        $result = $this->fetchResult($schema);
116        $this->assertCount(3, $result);
117
118        $result = $this->fetchResult($schema, '', ['field', '<', '2023-01-02', 'AND']);
119        $this->assertCount(1, $result);
120
121        $result = $this->fetchResult($schema, '', ['field', '<', '2023-01-01 11:00', 'AND']);
122        $this->assertCount(0, $result);
123    }
124
125    /**
126     * Test whether aggregation tables respect revoking of schema assignments
127     */
128    public function test_assignments()
129    {
130        $result = $this->fetchPagesResult('schema1');
131        $this->assertCount(3, $result);
132
133        // revoke assignment
134        $assignments = mock\Assignments::getInstance();
135        $assignments->deassignPageSchema('test0', 'schema1');
136
137        $result = $this->fetchPagesResult('schema1');
138        $this->assertCount(2, $result);
139    }
140
141
142    /**
143     * Initialize a lookup table from syntax and return the result from its internal search.
144     *
145     * @param string $schema
146     * @param string $id
147     * @param array $filters
148     * @return \dokuwiki\plugin\struct\meta\Value[][]
149     */
150    protected function fetchPagesResult($schema, $id = '', $filters = [])
151    {
152        $syntaxConfig = ['schema: ' . $schema, 'cols: %pageid%, %rowid%, *'];
153        $configParser = new ConfigParser($syntaxConfig);
154        $config = $configParser->getConfig();
155
156        if ($filters) $config['filter'][] = $filters;
157        $search = new MockSearchConfigAlias($config);
158
159        $table = new MockAggregationTableAlias($id, 'xhtml', new \Doku_Renderer_xhtml(), $search);
160        return $table->getResult();
161    }
162
163    /**
164     * Initialize a lookup table from syntax and return the result from its internal search.
165     *
166     * @param string $schema
167     * @param string $id
168     * @param array $filters
169     * @return \dokuwiki\plugin\struct\meta\Value[][]
170     */
171    protected function fetchResult($schema, $id = '', $filters = [])
172    {
173        $syntaxConfig = ['schema: ' . $schema, 'cols: %pageid%, %rowid%, *'];
174        $configParser = new ConfigParser($syntaxConfig);
175        $config = $configParser->getConfig();
176
177        // FIXME simulate addYypeFilter() from \syntax_plugin_struct_serial or \syntax_plugin_struct_lookup
178        if ($id) {
179            $config['filter'][] = ['%rowid%', '!=', (string)AccessTablePage::DEFAULT_PAGE_RID, 'AND'];
180            $config['filter'][] = ['%pageid%', '=', $id, 'AND'];
181        } else {
182            $config['filter'][] = ['%rowid%', '!=', (string)AccessTablePage::DEFAULT_PAGE_RID, 'AND'];
183            $config['filter'][] = ['%pageid%', '=*', '^(?![\s\S])', 'AND'];
184        }
185
186        if ($filters) $config['filter'][] = $filters;
187        $search = new MockSearchConfigAlias($config);
188
189        $table = new MockAggregationEditorTableAlias($id, 'xhtml', new \Doku_Renderer_xhtml(), $search);
190        return $table->getResult();
191    }
192
193    protected function prepareLookup()
194    {
195        saveWikiText('title1', 'test', 'test');
196        $pageMeta = new PageMeta('title1');
197        $pageMeta->setTitle('This is a title');
198
199        saveWikiText('title2', 'test', 'test');
200        $pageMeta = new PageMeta('title2');
201        $pageMeta->setTitle('This is a 2nd title');
202
203        saveWikiText('title3', 'test', 'test');
204        $pageMeta = new PageMeta('title3');
205        $pageMeta->setTitle('Another Title');
206
207        $this->loadSchemaJSON('pageschema');
208        $access = MockAccessTableAlias::getGlobalAccess('pageschema');
209        $access->saveData(
210            [
211                'singlepage' => 'title1',
212                'multipage' => ['title1'],
213                'singletitle' => 'title1',
214                'multititle' => ['title1'],
215            ]
216        );
217        $access = MockAccessTableAlias::getGlobalAccess('pageschema');
218        $access->saveData(
219            [
220                'singlepage' => 'title2',
221                'multipage' => ['title2'],
222                'singletitle' => 'title2',
223                'multititle' => ['title2'],
224            ]
225        );
226        $access = MockAccessTableAlias::getGlobalAccess('pageschema');
227        $access->saveData(
228            [
229                'singlepage' => 'title3',
230                'multipage' => ['title3'],
231                'singletitle' => 'title3',
232                'multititle' => ['title3'],
233            ]
234        );
235    }
236
237    protected function prepareDatetime()
238    {
239        $this->loadSchemaJSON('datetime');
240        $access = MockAccessTableAlias::getGlobalAccess('datetime');
241        $access->saveData(['field' => '2023-01-01 12:00']);
242        $access = MockAccessTableAlias::getGlobalAccess('datetime');
243        $access->saveData(['field' => '2023-01-02 00:00']);
244        $access = MockAccessTableAlias::getGlobalAccess('datetime');
245        $access->saveData(['field' => '2023-01-02 12:00']);
246    }
247}
248