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