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