xref: /plugin/struct/_test/AggregationResultsTest.php (revision 4bffd43680da9f5ab6f22a645c1f04bbe99210f8)
18fed17f3SAndreas Gohr<?php
28fed17f3SAndreas Gohr
38fed17f3SAndreas Gohrnamespace dokuwiki\plugin\struct\test;
48fed17f3SAndreas Gohr
58fed17f3SAndreas Gohruse dokuwiki\plugin\struct\meta\AccessTablePage;
68fed17f3SAndreas Gohruse dokuwiki\plugin\struct\meta\ConfigParser;
78fed17f3SAndreas Gohruse dokuwiki\plugin\struct\meta\PageMeta;
88fed17f3SAndreas Gohruse dokuwiki\plugin\struct\test\mock\AccessTable as MockAccessTableAlias;
98fed17f3SAndreas Gohruse dokuwiki\plugin\struct\test\mock\AggregationEditorTable as MockAggregationEditorTableAlias;
108fed17f3SAndreas Gohruse dokuwiki\plugin\struct\test\mock\AggregationTable as MockAggregationTableAlias;
118fed17f3SAndreas Gohruse dokuwiki\plugin\struct\test\mock\SearchConfig as MockSearchConfigAlias;
128fed17f3SAndreas Gohr
138fed17f3SAndreas Gohr/**
148fed17f3SAndreas Gohr * Testing serial data
158fed17f3SAndreas Gohr *
168fed17f3SAndreas Gohr * @group plugin_struct
178fed17f3SAndreas Gohr * @group plugins
188fed17f3SAndreas Gohr */
198fed17f3SAndreas Gohrclass AggregationResultsTest extends StructTest
208fed17f3SAndreas Gohr{
218fed17f3SAndreas Gohr    protected $sqlite;
228fed17f3SAndreas Gohr
238fed17f3SAndreas Gohr    public function setUp(): void
248fed17f3SAndreas Gohr    {
258fed17f3SAndreas Gohr        parent::setUp();
268fed17f3SAndreas Gohr
278fed17f3SAndreas Gohr        $sqlite = plugin_load('helper', 'struct_db');
288fed17f3SAndreas Gohr        $this->sqlite = $sqlite->getDB();
298fed17f3SAndreas Gohr
308fed17f3SAndreas Gohr        $this->loadSchemaJSON('schema1');
318fed17f3SAndreas Gohr
328fed17f3SAndreas Gohr        $assignments = mock\Assignments::getInstance();
338fed17f3SAndreas Gohr        $assignments->clear(true);
348fed17f3SAndreas Gohr
3571769bc3SAndreas Gohr        // different values for each entry
3671769bc3SAndreas Gohr        $second = [
3771769bc3SAndreas Gohr            ['green', 'red'],
3871769bc3SAndreas Gohr            ['green', 'blue'],
3971769bc3SAndreas Gohr            ['blue', 'yellow']
4071769bc3SAndreas Gohr        ];
4171769bc3SAndreas Gohr
428fed17f3SAndreas Gohr        for ($i = 0; $i < 3; $i++) {
438fed17f3SAndreas Gohr            // assign a schema
448fed17f3SAndreas Gohr            $assignments->assignPageSchema("test$i", 'schema1');
458fed17f3SAndreas Gohr
468fed17f3SAndreas Gohr            // save wiki pages
478fed17f3SAndreas Gohr            saveWikiText("test$i", "test$i", "test$i");
488fed17f3SAndreas Gohr
498fed17f3SAndreas Gohr            // save serial data
508fed17f3SAndreas Gohr            $data = [
518fed17f3SAndreas Gohr                'first' => "foo$i",
5271769bc3SAndreas Gohr                'second' => $second[$i],
538fed17f3SAndreas Gohr                'third' => "foobar$i",
548fed17f3SAndreas Gohr                'fourth' => "barfoo$i",
558fed17f3SAndreas Gohr            ];
56*4bffd436SAnna Dabrowska            $accessSerial = MockAccessTableAlias::getSerialAccess('schema1', "test$i");
57*4bffd436SAnna Dabrowska            $accessSerial->saveData($data);
58*4bffd436SAnna Dabrowska            $accessPage = MockAccessTableAlias::getPageAccess('schema1', "test$i");
59*4bffd436SAnna Dabrowska            $accessPage->saveData($data);
608fed17f3SAndreas Gohr        }
618fed17f3SAndreas Gohr    }
628fed17f3SAndreas Gohr
638fed17f3SAndreas Gohr    /**
648fed17f3SAndreas Gohr     * Test whether serial syntax produces a table of serial data limited to current page
658fed17f3SAndreas Gohr     */
668fed17f3SAndreas Gohr    public function test_pid()
678fed17f3SAndreas Gohr    {
688fed17f3SAndreas Gohr        // \syntax_plugin_struct_serial accesses the global $ID
698fed17f3SAndreas Gohr        $id = 'test1';
708fed17f3SAndreas Gohr        $schema = 'schema1';
71*4bffd436SAnna Dabrowska        $result = $this->fetchNonPageResults($schema, $id);
728fed17f3SAndreas Gohr
738fed17f3SAndreas Gohr        $this->assertCount(1, $result);
748fed17f3SAndreas Gohr        $this->assertEquals('test1', $result[0][0]->getValue());
758fed17f3SAndreas Gohr        // skip %rowid% column and test saved values
768fed17f3SAndreas Gohr        $this->assertEquals('foo1', $result[0][2]->getValue());
77fb2252eaSAndreas Gohr        $this->assertEquals(['green', 'blue'], $result[0][3]->getValue());
788fed17f3SAndreas Gohr        $this->assertEquals('foobar1', $result[0][4]->getValue());
798fed17f3SAndreas Gohr        $this->assertEquals('barfoo1', $result[0][5]->getValue());
808fed17f3SAndreas Gohr    }
818fed17f3SAndreas Gohr
828fed17f3SAndreas Gohr    /**
838fed17f3SAndreas Gohr     * Test simple text filter
848fed17f3SAndreas Gohr     */
858fed17f3SAndreas Gohr    public function test_filter_text()
868fed17f3SAndreas Gohr    {
878fed17f3SAndreas Gohr        $schema = 'schema1';
88*4bffd436SAnna Dabrowska        $result = $this->fetchNonPageResults($schema, 'test0');
898fed17f3SAndreas Gohr        $this->assertCount(1, $result);
908fed17f3SAndreas Gohr
91*4bffd436SAnna Dabrowska        $result = $this->fetchNonPageResults($schema, 'test0', ['first', '=', 'foo0', 'AND']);
928fed17f3SAndreas Gohr        $this->assertCount(1, $result);
938fed17f3SAndreas Gohr
94*4bffd436SAnna Dabrowska        $result = $this->fetchNonPageResults($schema, 'test0', ['first', '!=', 'foo0', 'AND']);
958fed17f3SAndreas Gohr        $this->assertCount(0, $result);
968fed17f3SAndreas Gohr    }
978fed17f3SAndreas Gohr
9871769bc3SAndreas Gohr    /** @noinspection PhpUnreachableStatementInspection */
9971769bc3SAndreas Gohr    public function test_filter_multi()
10071769bc3SAndreas Gohr    {
10171769bc3SAndreas Gohr        $schema = 'schema1';
102*4bffd436SAnna Dabrowska        $result = $this->fetchAllResults($schema, '');
103*4bffd436SAnna Dabrowska        $this->assertCount(6, $result);
10471769bc3SAndreas Gohr
105*4bffd436SAnna Dabrowska        $result = $this->fetchAllResults($schema, '', ['second', '=', 'green', 'AND']);
106*4bffd436SAnna Dabrowska        $this->assertCount(4, $result);
10771769bc3SAndreas Gohr
10871769bc3SAndreas Gohr        $this->markTestIncomplete('negative filters currently do not work on multi fields. See #512');
10971769bc3SAndreas Gohr
110*4bffd436SAnna Dabrowska        $result = $this->fetchAllResults($schema, '', ['second', '!~', 'green', 'AND']);
111*4bffd436SAnna Dabrowska        $this->assertCount(2, $result);
11271769bc3SAndreas Gohr    }
11371769bc3SAndreas Gohr
1148fed17f3SAndreas Gohr    /**
1158fed17f3SAndreas Gohr     * Test filtering on a page field, with 'usetitles' set to true and false
1168fed17f3SAndreas Gohr     */
1178fed17f3SAndreas Gohr    public function test_filter_page()
1188fed17f3SAndreas Gohr    {
1198fed17f3SAndreas Gohr        $this->prepareLookup();
1208fed17f3SAndreas Gohr        $schema = 'pageschema';
121*4bffd436SAnna Dabrowska        $result = $this->fetchNonPageResults($schema);
1228fed17f3SAndreas Gohr        $this->assertCount(3, $result);
1238fed17f3SAndreas Gohr
1248fed17f3SAndreas Gohr        // 'usetitles' = true
125*4bffd436SAnna Dabrowska        $result = $this->fetchNonPageResults($schema, '', ['singletitle', '*~', 'another', 'AND']);
1268fed17f3SAndreas Gohr        $this->assertCount(1, $result);
1278fed17f3SAndreas Gohr
1288fed17f3SAndreas Gohr        // 'usetitles' = false
129*4bffd436SAnna Dabrowska        $result = $this->fetchNonPageResults($schema, '', ['singlepage', '*~', 'this', 'AND']);
1308fed17f3SAndreas Gohr        $this->assertCount(0, $result);
1318fed17f3SAndreas Gohr    }
1328fed17f3SAndreas Gohr
1338fed17f3SAndreas Gohr    /**
1348fed17f3SAndreas Gohr     * Test filtering on a DateTime field
1358fed17f3SAndreas Gohr     */
1368fed17f3SAndreas Gohr    public function test_filter_datetime()
1378fed17f3SAndreas Gohr    {
1388fed17f3SAndreas Gohr        $this->prepareDatetime();
1398fed17f3SAndreas Gohr        $schema = 'datetime';
140*4bffd436SAnna Dabrowska        $result = $this->fetchNonPageResults($schema);
1418fed17f3SAndreas Gohr        $this->assertCount(3, $result);
1428fed17f3SAndreas Gohr
143*4bffd436SAnna Dabrowska        $result = $this->fetchNonPageResults($schema, '', ['field', '<', '2023-01-02', 'AND']);
1448fed17f3SAndreas Gohr        $this->assertCount(1, $result);
1458fed17f3SAndreas Gohr
146*4bffd436SAnna Dabrowska        $result = $this->fetchNonPageResults($schema, '', ['field', '<', '2023-01-01 11:00', 'AND']);
1478fed17f3SAndreas Gohr        $this->assertCount(0, $result);
1488fed17f3SAndreas Gohr    }
1498fed17f3SAndreas Gohr
1508fed17f3SAndreas Gohr    /**
1518fed17f3SAndreas Gohr     * Test whether aggregation tables respect revoking of schema assignments
1528fed17f3SAndreas Gohr     */
1538fed17f3SAndreas Gohr    public function test_assignments()
1548fed17f3SAndreas Gohr    {
155*4bffd436SAnna Dabrowska        $result = $this->fetchAllResults('schema1');
156*4bffd436SAnna Dabrowska        $this->assertCount(6, $result);
1578fed17f3SAndreas Gohr
1588fed17f3SAndreas Gohr        // revoke assignment
1598fed17f3SAndreas Gohr        $assignments = mock\Assignments::getInstance();
1608fed17f3SAndreas Gohr        $assignments->deassignPageSchema('test0', 'schema1');
1618fed17f3SAndreas Gohr
162*4bffd436SAnna Dabrowska        $result = $this->fetchAllResults('schema1');
163*4bffd436SAnna Dabrowska        $this->assertCount(5, $result);
1648fed17f3SAndreas Gohr    }
1658fed17f3SAndreas Gohr
1668fed17f3SAndreas Gohr
1678fed17f3SAndreas Gohr    /**
168*4bffd436SAnna Dabrowska     * Initialize a table from syntax and return the result from its internal search.
1698fed17f3SAndreas Gohr     *
1708fed17f3SAndreas Gohr     * @param string $schema
1718fed17f3SAndreas Gohr     * @param string $id
1728fed17f3SAndreas Gohr     * @param array $filters
1738fed17f3SAndreas Gohr     * @return \dokuwiki\plugin\struct\meta\Value[][]
1748fed17f3SAndreas Gohr     */
175*4bffd436SAnna Dabrowska    protected function fetchAllResults($schema, $id = '', $filters = [])
1768fed17f3SAndreas Gohr    {
1778fed17f3SAndreas Gohr        $syntaxConfig = ['schema: ' . $schema, 'cols: %pageid%, %rowid%, *'];
1788fed17f3SAndreas Gohr        $configParser = new ConfigParser($syntaxConfig);
1798fed17f3SAndreas Gohr        $config = $configParser->getConfig();
1808fed17f3SAndreas Gohr
1818fed17f3SAndreas Gohr        if ($filters) $config['filter'][] = $filters;
1828fed17f3SAndreas Gohr        $search = new MockSearchConfigAlias($config);
1838fed17f3SAndreas Gohr
1848fed17f3SAndreas Gohr        $table = new MockAggregationTableAlias($id, 'xhtml', new \Doku_Renderer_xhtml(), $search);
1858fed17f3SAndreas Gohr        return $table->getResult();
1868fed17f3SAndreas Gohr    }
1878fed17f3SAndreas Gohr
1888fed17f3SAndreas Gohr    /**
1898fed17f3SAndreas Gohr     * Initialize a lookup table from syntax and return the result from its internal search.
1908fed17f3SAndreas Gohr     *
1918fed17f3SAndreas Gohr     * @param string $schema
1928fed17f3SAndreas Gohr     * @param string $id
1938fed17f3SAndreas Gohr     * @param array $filters
1948fed17f3SAndreas Gohr     * @return \dokuwiki\plugin\struct\meta\Value[][]
1958fed17f3SAndreas Gohr     */
196*4bffd436SAnna Dabrowska    protected function fetchNonPageResults($schema, $id = '', $filters = [])
1978fed17f3SAndreas Gohr    {
1988fed17f3SAndreas Gohr        $syntaxConfig = ['schema: ' . $schema, 'cols: %pageid%, %rowid%, *'];
1998fed17f3SAndreas Gohr        $configParser = new ConfigParser($syntaxConfig);
2008fed17f3SAndreas Gohr        $config = $configParser->getConfig();
2018fed17f3SAndreas Gohr
202*4bffd436SAnna Dabrowska        // simulate addYypeFilter() from \syntax_plugin_struct_serial and \syntax_plugin_struct_lookup
2038fed17f3SAndreas Gohr        if ($id) {
2048fed17f3SAndreas Gohr            $config['filter'][] = ['%rowid%', '!=', (string)AccessTablePage::DEFAULT_PAGE_RID, 'AND'];
2058fed17f3SAndreas Gohr            $config['filter'][] = ['%pageid%', '=', $id, 'AND'];
2068fed17f3SAndreas Gohr        } else {
2078fed17f3SAndreas Gohr            $config['filter'][] = ['%rowid%', '!=', (string)AccessTablePage::DEFAULT_PAGE_RID, 'AND'];
2088fed17f3SAndreas Gohr            $config['filter'][] = ['%pageid%', '=*', '^(?![\s\S])', 'AND'];
2098fed17f3SAndreas Gohr        }
2108fed17f3SAndreas Gohr
2118fed17f3SAndreas Gohr        if ($filters) $config['filter'][] = $filters;
2128fed17f3SAndreas Gohr        $search = new MockSearchConfigAlias($config);
2138fed17f3SAndreas Gohr
2148fed17f3SAndreas Gohr        $table = new MockAggregationEditorTableAlias($id, 'xhtml', new \Doku_Renderer_xhtml(), $search);
2158fed17f3SAndreas Gohr        return $table->getResult();
2168fed17f3SAndreas Gohr    }
2178fed17f3SAndreas Gohr
2188fed17f3SAndreas Gohr    protected function prepareLookup()
2198fed17f3SAndreas Gohr    {
2208fed17f3SAndreas Gohr        saveWikiText('title1', 'test', 'test');
2218fed17f3SAndreas Gohr        $pageMeta = new PageMeta('title1');
2228fed17f3SAndreas Gohr        $pageMeta->setTitle('This is a title');
2238fed17f3SAndreas Gohr
2248fed17f3SAndreas Gohr        saveWikiText('title2', 'test', 'test');
2258fed17f3SAndreas Gohr        $pageMeta = new PageMeta('title2');
2268fed17f3SAndreas Gohr        $pageMeta->setTitle('This is a 2nd title');
2278fed17f3SAndreas Gohr
2288fed17f3SAndreas Gohr        saveWikiText('title3', 'test', 'test');
2298fed17f3SAndreas Gohr        $pageMeta = new PageMeta('title3');
2308fed17f3SAndreas Gohr        $pageMeta->setTitle('Another Title');
2318fed17f3SAndreas Gohr
2328fed17f3SAndreas Gohr        $this->loadSchemaJSON('pageschema');
2338fed17f3SAndreas Gohr        $access = MockAccessTableAlias::getGlobalAccess('pageschema');
2348fed17f3SAndreas Gohr        $access->saveData(
2358fed17f3SAndreas Gohr            [
2368fed17f3SAndreas Gohr                'singlepage' => 'title1',
2378fed17f3SAndreas Gohr                'multipage' => ['title1'],
2388fed17f3SAndreas Gohr                'singletitle' => 'title1',
2398fed17f3SAndreas Gohr                'multititle' => ['title1'],
2408fed17f3SAndreas Gohr            ]
2418fed17f3SAndreas Gohr        );
2428fed17f3SAndreas Gohr        $access = MockAccessTableAlias::getGlobalAccess('pageschema');
2438fed17f3SAndreas Gohr        $access->saveData(
2448fed17f3SAndreas Gohr            [
2458fed17f3SAndreas Gohr                'singlepage' => 'title2',
2468fed17f3SAndreas Gohr                'multipage' => ['title2'],
2478fed17f3SAndreas Gohr                'singletitle' => 'title2',
2488fed17f3SAndreas Gohr                'multititle' => ['title2'],
2498fed17f3SAndreas Gohr            ]
2508fed17f3SAndreas Gohr        );
2518fed17f3SAndreas Gohr        $access = MockAccessTableAlias::getGlobalAccess('pageschema');
2528fed17f3SAndreas Gohr        $access->saveData(
2538fed17f3SAndreas Gohr            [
2548fed17f3SAndreas Gohr                'singlepage' => 'title3',
2558fed17f3SAndreas Gohr                'multipage' => ['title3'],
2568fed17f3SAndreas Gohr                'singletitle' => 'title3',
2578fed17f3SAndreas Gohr                'multititle' => ['title3'],
2588fed17f3SAndreas Gohr            ]
2598fed17f3SAndreas Gohr        );
2608fed17f3SAndreas Gohr    }
2618fed17f3SAndreas Gohr
2628fed17f3SAndreas Gohr    protected function prepareDatetime()
2638fed17f3SAndreas Gohr    {
2648fed17f3SAndreas Gohr        $this->loadSchemaJSON('datetime');
2658fed17f3SAndreas Gohr        $access = MockAccessTableAlias::getGlobalAccess('datetime');
2668fed17f3SAndreas Gohr        $access->saveData(['field' => '2023-01-01 12:00']);
2678fed17f3SAndreas Gohr        $access = MockAccessTableAlias::getGlobalAccess('datetime');
2688fed17f3SAndreas Gohr        $access->saveData(['field' => '2023-01-02 00:00']);
2698fed17f3SAndreas Gohr        $access = MockAccessTableAlias::getGlobalAccess('datetime');
2708fed17f3SAndreas Gohr        $access->saveData(['field' => '2023-01-02 12:00']);
2718fed17f3SAndreas Gohr    }
2728fed17f3SAndreas Gohr}
273