1<?php 2 3use MediaWiki\MediaWikiServices; 4 5/** 6 * @covers MediaWiki\Interwiki\ClassicInterwikiLookup 7 * @group Database 8 */ 9class ClassicInterwikiLookupTest extends MediaWikiIntegrationTestCase { 10 11 private function populateDB( $iwrows ) { 12 $dbw = wfGetDB( DB_MASTER ); 13 $dbw->delete( 'interwiki', '*', __METHOD__ ); 14 $dbw->insert( 'interwiki', array_values( $iwrows ), __METHOD__ ); 15 $this->tablesUsed[] = 'interwiki'; 16 } 17 18 public function testDatabaseStorage() { 19 // NOTE: database setup is expensive, so we only do 20 // it once and run all the tests in one go. 21 $dewiki = [ 22 'iw_prefix' => 'de', 23 'iw_url' => 'http://de.wikipedia.org/wiki/', 24 'iw_api' => 'http://de.wikipedia.org/w/api.php', 25 'iw_wikiid' => 'dewiki', 26 'iw_local' => 1, 27 'iw_trans' => 0 28 ]; 29 30 $zzwiki = [ 31 'iw_prefix' => 'zz', 32 'iw_url' => 'http://zzwiki.org/wiki/', 33 'iw_api' => 'http://zzwiki.org/w/api.php', 34 'iw_wikiid' => 'zzwiki', 35 'iw_local' => 0, 36 'iw_trans' => 0 37 ]; 38 39 $this->populateDB( [ $dewiki, $zzwiki ] ); 40 $lookup = new \MediaWiki\Interwiki\ClassicInterwikiLookup( 41 MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( 'en' ), 42 WANObjectCache::newEmpty(), 43 MediaWikiServices::getInstance()->getHookContainer(), 44 60 * 60, 45 false, 46 3, 47 'en' 48 ); 49 50 $this->assertEquals( 51 [ $dewiki, $zzwiki ], 52 $lookup->getAllPrefixes(), 53 'getAllPrefixes()' 54 ); 55 $this->assertEquals( 56 [ $dewiki ], 57 $lookup->getAllPrefixes( true ), 58 'getAllPrefixes()' 59 ); 60 $this->assertEquals( 61 [ $zzwiki ], 62 $lookup->getAllPrefixes( false ), 63 'getAllPrefixes()' 64 ); 65 66 $this->assertTrue( $lookup->isValidInterwiki( 'de' ), 'known prefix is valid' ); 67 $this->assertFalse( $lookup->isValidInterwiki( 'xyz' ), 'unknown prefix is valid' ); 68 69 $this->assertNull( $lookup->fetch( null ), 'no prefix' ); 70 $this->assertFalse( $lookup->fetch( 'xyz' ), 'unknown prefix' ); 71 72 $interwiki = $lookup->fetch( 'de' ); 73 $this->assertInstanceOf( Interwiki::class, $interwiki ); 74 $this->assertSame( $interwiki, $lookup->fetch( 'de' ), 'in-process caching' ); 75 76 $this->assertSame( 'http://de.wikipedia.org/wiki/', $interwiki->getURL(), 'getURL' ); 77 $this->assertSame( 'http://de.wikipedia.org/w/api.php', $interwiki->getAPI(), 'getAPI' ); 78 $this->assertSame( 'dewiki', $interwiki->getWikiID(), 'getWikiID' ); 79 $this->assertSame( true, $interwiki->isLocal(), 'isLocal' ); 80 $this->assertSame( false, $interwiki->isTranscludable(), 'isTranscludable' ); 81 82 $lookup->invalidateCache( 'de' ); 83 $this->assertNotSame( $interwiki, $lookup->fetch( 'de' ), 'invalidate cache' ); 84 } 85 86 /** 87 * @param string $thisSite 88 * @param string[] $local 89 * @param string[] $global 90 * 91 * @return string[] 92 */ 93 private function populateHash( $thisSite, $local, $global ) { 94 $hash = []; 95 $hash[ '__sites:' . wfWikiID() ] = $thisSite; 96 97 $globals = []; 98 $locals = []; 99 100 foreach ( $local as $row ) { 101 $prefix = $row['iw_prefix']; 102 $data = $row['iw_local'] . ' ' . $row['iw_url']; 103 $locals[] = $prefix; 104 $hash[ "_{$thisSite}:{$prefix}" ] = $data; 105 } 106 107 foreach ( $global as $row ) { 108 $prefix = $row['iw_prefix']; 109 $data = $row['iw_local'] . ' ' . $row['iw_url']; 110 $globals[] = $prefix; 111 $hash[ "__global:{$prefix}" ] = $data; 112 } 113 114 $hash[ '__list:__global' ] = implode( ' ', $globals ); 115 $hash[ '__list:_' . $thisSite ] = implode( ' ', $locals ); 116 117 return $hash; 118 } 119 120 private function populateCDB( $thisSite, $local, $global ) { 121 $cdbFile = $this->getNewTempFile(); 122 $cdb = \Cdb\Writer::open( $cdbFile ); 123 124 $hash = $this->populateHash( $thisSite, $local, $global ); 125 126 foreach ( $hash as $key => $value ) { 127 $cdb->set( $key, $value ); 128 } 129 130 $cdb->close(); 131 return $cdbFile; 132 } 133 134 public function testCDBStorage() { 135 // NOTE: CDB setup is expensive, so we only do 136 // it once and run all the tests in one go. 137 138 $zzwiki = [ 139 'iw_prefix' => 'zz', 140 'iw_url' => 'http://zzwiki.org/wiki/', 141 'iw_local' => 0 142 ]; 143 144 $dewiki = [ 145 'iw_prefix' => 'de', 146 'iw_url' => 'http://de.wikipedia.org/wiki/', 147 'iw_local' => 1 148 ]; 149 150 $cdbFile = $this->populateCDB( 151 'en', 152 [ $dewiki ], 153 [ $zzwiki ] 154 ); 155 $lookup = new \MediaWiki\Interwiki\ClassicInterwikiLookup( 156 MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( 'en' ), 157 WANObjectCache::newEmpty(), 158 MediaWikiServices::getInstance()->getHookContainer(), 159 60 * 60, 160 $cdbFile, 161 3, 162 'en' 163 ); 164 165 $this->assertEquals( 166 [ $zzwiki, $dewiki ], 167 $lookup->getAllPrefixes(), 168 'getAllPrefixes()' 169 ); 170 171 $this->assertTrue( $lookup->isValidInterwiki( 'de' ), 'known prefix is valid' ); 172 $this->assertTrue( $lookup->isValidInterwiki( 'zz' ), 'known prefix is valid' ); 173 174 $interwiki = $lookup->fetch( 'de' ); 175 $this->assertInstanceOf( Interwiki::class, $interwiki ); 176 177 $this->assertSame( 'http://de.wikipedia.org/wiki/', $interwiki->getURL(), 'getURL' ); 178 $this->assertSame( true, $interwiki->isLocal(), 'isLocal' ); 179 180 $interwiki = $lookup->fetch( 'zz' ); 181 $this->assertInstanceOf( Interwiki::class, $interwiki ); 182 183 $this->assertSame( 'http://zzwiki.org/wiki/', $interwiki->getURL(), 'getURL' ); 184 $this->assertSame( false, $interwiki->isLocal(), 'isLocal' ); 185 186 // cleanup temp file 187 unlink( $cdbFile ); 188 } 189 190 public function testArrayStorage() { 191 $zzwiki = [ 192 'iw_prefix' => 'zz', 193 'iw_url' => 'http://zzwiki.org/wiki/', 194 'iw_local' => 0 195 ]; 196 $dewiki = [ 197 'iw_prefix' => 'de', 198 'iw_url' => 'http://de.wikipedia.org/wiki/', 199 'iw_local' => 1 200 ]; 201 202 $hash = $this->populateHash( 203 'en', 204 [ $dewiki ], 205 [ $zzwiki ] 206 ); 207 $lookup = new \MediaWiki\Interwiki\ClassicInterwikiLookup( 208 MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( 'en' ), 209 WANObjectCache::newEmpty(), 210 MediaWikiServices::getInstance()->getHookContainer(), 211 60 * 60, 212 $hash, 213 3, 214 'en' 215 ); 216 217 $this->assertEquals( 218 [ $zzwiki, $dewiki ], 219 $lookup->getAllPrefixes(), 220 'getAllPrefixes()' 221 ); 222 223 $this->assertTrue( $lookup->isValidInterwiki( 'de' ), 'known prefix is valid' ); 224 $this->assertTrue( $lookup->isValidInterwiki( 'zz' ), 'known prefix is valid' ); 225 226 $interwiki = $lookup->fetch( 'de' ); 227 $this->assertInstanceOf( Interwiki::class, $interwiki ); 228 229 $this->assertSame( 'http://de.wikipedia.org/wiki/', $interwiki->getURL(), 'getURL' ); 230 $this->assertSame( true, $interwiki->isLocal(), 'isLocal' ); 231 232 $interwiki = $lookup->fetch( 'zz' ); 233 $this->assertInstanceOf( Interwiki::class, $interwiki ); 234 235 $this->assertSame( 'http://zzwiki.org/wiki/', $interwiki->getURL(), 'getURL' ); 236 $this->assertSame( false, $interwiki->isLocal(), 'isLocal' ); 237 } 238 239 public function testGetAllPrefixes() { 240 $zz = [ 241 'iw_prefix' => 'zz', 242 'iw_url' => 'https://azz.example.org/', 243 'iw_local' => 1 244 ]; 245 $de = [ 246 'iw_prefix' => 'de', 247 'iw_url' => 'https://de.example.org/', 248 'iw_local' => 1 249 ]; 250 $azz = [ 251 'iw_prefix' => 'azz', 252 'iw_url' => 'https://azz.example.org/', 253 'iw_local' => 1 254 ]; 255 256 $hash = $this->populateHash( 257 'en', 258 [], 259 [ $zz, $de, $azz ] 260 ); 261 $lookup = new \MediaWiki\Interwiki\ClassicInterwikiLookup( 262 MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( 'en' ), 263 WANObjectCache::newEmpty(), 264 MediaWikiServices::getInstance()->getHookContainer(), 265 60 * 60, 266 $hash, 267 3, 268 'en' 269 ); 270 271 $this->assertEquals( 272 [ $zz, $de, $azz ], 273 $lookup->getAllPrefixes(), 274 'getAllPrefixes() - preserves order' 275 ); 276 } 277 278} 279