1<?php 2 3namespace dokuwiki\plugin\struct\test; 4 5use dokuwiki\plugin\struct\meta; 6 7/** 8 * Tests for the building of SQL-Queries for the struct plugin 9 * 10 * @group plugin_struct 11 * @group plugins 12 * 13 */ 14class AccessTableDataReplacement_struct_test extends StructTest 15{ 16 17 /** @var array alway enable the needed plugins */ 18 protected $pluginsEnabled = array('struct', 'sqlite'); 19 20 public function setUp(): void 21 { 22 parent::setUp(); 23 $schemafoo = array(); 24 $schemafoo['new']['new1']['label'] = 'pages'; 25 $schemafoo['new']['new1']['ismulti'] = 1; 26 $schemafoo['new']['new1']['class'] = 'Page'; 27 $schemafoo['new']['new1']['isenabled'] = '1'; 28 29 $schemabar['new']['new2']['label'] = 'data'; 30 $schemabar['new']['new2']['ismulti'] = 0; 31 $schemabar['new']['new2']['class'] = 'Text'; 32 $schemabar['new']['new2']['isenabled'] = '1'; 33 34 $builder_foo = new meta\SchemaBuilder('foo', $schemafoo); 35 $builder_foo->build(); 36 37 $builder_bar = new meta\SchemaBuilder('bar', $schemabar); 38 $builder_bar->build(); 39 40 $as = mock\Assignments::getInstance(); 41 $as->assignPageSchema('start', 'foo'); 42 $as->assignPageSchema('no:data', 'foo'); 43 $as->assignPageSchema('page1', 'bar'); 44 $as->assignPageSchema('page2', 'bar'); 45 $as->assignPageSchema('page2', 'bar'); 46 47 // page data is saved with a rev timestamp 48 $now = time(); 49 $this->saveData( 50 'start', 51 'foo', 52 array( 53 'pages' => array('page1', 'page2') 54 ), 55 $now 56 ); 57 58 $this->saveData( 59 'page1', 60 'bar', 61 array( 62 'data' => 'data of page1' 63 ), 64 $now 65 ); 66 67 $this->saveData( 68 'page2', 69 'bar', 70 array( 71 'data' => 'data of page2' 72 ), 73 $now 74 ); 75 } 76 77 public function test_simple() 78 { 79 global $INFO; 80 $INFO['id'] = 'start'; 81 $lines = array( 82 "schema : bar", 83 "cols : %pageid%, data", 84 "filter : %pageid% = \$STRUCT.foo.pages$" 85 ); 86 87 $configParser = new meta\ConfigParser($lines); 88 $actual_config = $configParser->getConfig(); 89 90 $search = new meta\SearchConfig($actual_config); 91 list(, $opts) = $search->getSQL(); 92 $result = $search->execute(); 93 94 $this->assertEquals(array('page1', 'page2'), $opts, '$STRUCT.table.col$ should not require table to be selected'); 95 $this->assertEquals('data of page1', $result[0][1]->getValue()); 96 $this->assertEquals('data of page2', $result[1][1]->getValue()); 97 } 98 99 public function test_emptyfield() 100 { 101 global $ID; 102 $ID = 'no:data'; 103 $lines = array( 104 "schema : bar", 105 "cols : %pageid%, data", 106 "filter : %pageid% = \$STRUCT.foo.pages$" 107 ); 108 109 $configParser = new meta\ConfigParser($lines); 110 $actual_config = $configParser->getConfig(); 111 112 $search = new meta\SearchConfig($actual_config); 113 $result = $search->execute(); 114 115 $this->assertEquals(0, count($result), 'if no pages a given, then none should be shown'); 116 } 117 118 public function dataProvider_DataFiltersAsSubQuery() 119 { 120 return array( 121 array( 122 array( 123 "filter : data = foo" 124 ), 125 "AND ((data_bar.col1 != '' AND data_bar.col1 = ?))", 126 "The WHERE-clauses from page-syntax should be wrapped in parentheses" 127 ), 128 array( 129 array( 130 "OR : data = foo" 131 ), 132 "AND ((data_bar.col1 != '' AND data_bar.col1 = ?))", 133 "A single OR clause should be treated as AND clauses" 134 ), 135 array( 136 array( 137 "filter : data = foo", 138 "OR : data = bar" 139 ), 140 "AND ((data_bar.col1 != '' AND data_bar.col1 = ?) OR (data_bar.col1 != '' AND data_bar.col1 = ?))", 141 "The WHERE-clauses from page-syntax should be wrapped in parentheses" 142 ), 143 array( 144 array( 145 "OR : data = bar", 146 "filter : data = foo" 147 ), 148 "AND ((data_bar.col1 != '' AND data_bar.col1 = ?) AND (data_bar.col1 != '' AND data_bar.col1 = ?))", 149 "A single OR clause should be treated as AND clauses" 150 ) 151 ); 152 } 153 154 /** 155 * @dataProvider dataProvider_DataFiltersAsSubQuery 156 */ 157 public function test_DataFiltersAsSubQuery($inputFilterLines, $expectedFilterWhere, $msg) 158 { 159 $lines = array( 160 "schema : bar", 161 "cols : %pageid%, data", 162 ); 163 164 $lines = array_merge($lines, $inputFilterLines); 165 166 $configParser = new meta\ConfigParser($lines); 167 $actual_config = $configParser->getConfig(); 168 169 $search = new meta\SearchConfig($actual_config); 170 list($sql,) = $search->getSQL(); 171 $where = array_filter(explode("\n", $sql), function ($elem) { 172 return strpos($elem, 'WHERE') !== false; 173 }); 174 $where = trim(reset($where)); 175 176 $baseWhere = "WHERE ( 177 ( 178 data_bar.pid = '' OR ( 179 GETACCESSLEVEL(data_bar.pid) > 0 180 AND PAGEEXISTS(data_bar.pid) = 1 181 AND (ASSIGNED = 1 OR ASSIGNED IS NULL) 182 ) 183 ) 184 AND data_bar.latest = 1"; 185 186 $expected_where = $baseWhere . $expectedFilterWhere . " )"; 187 $this->assertEquals($this->cleanWS($expected_where), $this->cleanWS($where), $msg); 188 } 189 190} 191