ImportTest.php 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. <?php
  2. use MediaWiki\MediaWikiServices;
  3. /**
  4. * Test class for Import methods.
  5. *
  6. * @group Database
  7. *
  8. * @author Sebastian Brückner < sebastian.brueckner@student.hpi.uni-potsdam.de >
  9. */
  10. class ImportTest extends MediaWikiLangTestCase {
  11. private function getDataSource( $xml ) {
  12. return new ImportStringSource( $xml );
  13. }
  14. /**
  15. * @covers WikiImporter
  16. * @dataProvider getUnknownTagsXML
  17. * @param string $xml
  18. * @param string $text
  19. * @param string $title
  20. */
  21. public function testUnknownXMLTags( $xml, $text, $title ) {
  22. $source = $this->getDataSource( $xml );
  23. $importer = new WikiImporter(
  24. $source,
  25. MediaWikiServices::getInstance()->getMainConfig()
  26. );
  27. $importer->doImport();
  28. $title = Title::newFromText( $title );
  29. $this->assertTrue( $title->exists() );
  30. $this->assertEquals( WikiPage::factory( $title )->getContent()->getNativeData(), $text );
  31. }
  32. public function getUnknownTagsXML() {
  33. // phpcs:disable Generic.Files.LineLength
  34. return [
  35. [
  36. <<< EOF
  37. <mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
  38. <page unknown="123" dontknow="533">
  39. <title>TestImportPage</title>
  40. <unknowntag>Should be ignored</unknowntag>
  41. <ns>0</ns>
  42. <id unknown="123" dontknow="533">14</id>
  43. <revision>
  44. <id unknown="123" dontknow="533">15</id>
  45. <unknowntag>Should be ignored</unknowntag>
  46. <timestamp>2016-01-03T11:18:43Z</timestamp>
  47. <contributor>
  48. <unknowntag>Should be ignored</unknowntag>
  49. <username unknown="123" dontknow="533">Admin</username>
  50. <id>1</id>
  51. </contributor>
  52. <model>wikitext</model>
  53. <format>text/x-wiki</format>
  54. <text xml:space="preserve" bytes="0">noitazinagro tseb eht si ikiWaideM</text>
  55. <sha1>phoiac9h4m842xq45sp7s6u21eteeq1</sha1>
  56. <unknowntag>Should be ignored</unknowntag>
  57. </revision>
  58. </page>
  59. <unknowntag>Should be ignored</unknowntag>
  60. </mediawiki>
  61. EOF
  62. ,
  63. 'noitazinagro tseb eht si ikiWaideM',
  64. 'TestImportPage'
  65. ]
  66. ];
  67. // phpcs:enable
  68. }
  69. /**
  70. * @covers WikiImporter::handlePage
  71. * @dataProvider getRedirectXML
  72. * @param string $xml
  73. * @param string|null $redirectTitle
  74. */
  75. public function testHandlePageContainsRedirect( $xml, $redirectTitle ) {
  76. $source = $this->getDataSource( $xml );
  77. $redirect = null;
  78. $callback = function ( Title $title, ForeignTitle $foreignTitle, $revCount,
  79. $sRevCount, $pageInfo ) use ( &$redirect ) {
  80. if ( array_key_exists( 'redirect', $pageInfo ) ) {
  81. $redirect = $pageInfo['redirect'];
  82. }
  83. };
  84. $importer = new WikiImporter(
  85. $source,
  86. MediaWikiServices::getInstance()->getMainConfig()
  87. );
  88. $importer->setPageOutCallback( $callback );
  89. $importer->doImport();
  90. $this->assertEquals( $redirectTitle, $redirect );
  91. }
  92. public function getRedirectXML() {
  93. // phpcs:disable Generic.Files.LineLength
  94. return [
  95. [
  96. <<< EOF
  97. <mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
  98. <page>
  99. <title>Test</title>
  100. <ns>0</ns>
  101. <id>21</id>
  102. <redirect title="Test22"/>
  103. <revision>
  104. <id>20</id>
  105. <timestamp>2014-05-27T10:00:00Z</timestamp>
  106. <contributor>
  107. <username>Admin</username>
  108. <id>10</id>
  109. </contributor>
  110. <comment>Admin moved page [[Test]] to [[Test22]]</comment>
  111. <model>wikitext</model>
  112. <format>text/x-wiki</format>
  113. <text xml:space="preserve" bytes="20">#REDIRECT [[Test22]]</text>
  114. <sha1>tq456o9x3abm7r9ozi6km8yrbbc56o6</sha1>
  115. </revision>
  116. </page>
  117. </mediawiki>
  118. EOF
  119. ,
  120. 'Test22'
  121. ],
  122. [
  123. <<< EOF
  124. <mediawiki xmlns="http://www.mediawiki.org/xml/export-0.9/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.9/ http://www.mediawiki.org/xml/export-0.9.xsd" version="0.9" xml:lang="en">
  125. <page>
  126. <title>Test</title>
  127. <ns>0</ns>
  128. <id>42</id>
  129. <revision>
  130. <id>421</id>
  131. <timestamp>2014-05-27T11:00:00Z</timestamp>
  132. <contributor>
  133. <username>Admin</username>
  134. <id>10</id>
  135. </contributor>
  136. <text xml:space="preserve" bytes="4">Abcd</text>
  137. <sha1>n7uomjq96szt60fy5w3x7ahf7q8m8rh</sha1>
  138. <model>wikitext</model>
  139. <format>text/x-wiki</format>
  140. </revision>
  141. </page>
  142. </mediawiki>
  143. EOF
  144. ,
  145. null
  146. ],
  147. ];
  148. // phpcs:enable
  149. }
  150. /**
  151. * @covers WikiImporter::handleSiteInfo
  152. * @dataProvider getSiteInfoXML
  153. * @param string $xml
  154. * @param array|null $namespaces
  155. */
  156. public function testSiteInfoContainsNamespaces( $xml, $namespaces ) {
  157. $source = $this->getDataSource( $xml );
  158. $importNamespaces = null;
  159. $callback = function ( array $siteinfo, $innerImporter ) use ( &$importNamespaces ) {
  160. $importNamespaces = $siteinfo['_namespaces'];
  161. };
  162. $importer = new WikiImporter(
  163. $source,
  164. MediaWikiServices::getInstance()->getMainConfig()
  165. );
  166. $importer->setSiteInfoCallback( $callback );
  167. $importer->doImport();
  168. $this->assertEquals( $importNamespaces, $namespaces );
  169. }
  170. public function getSiteInfoXML() {
  171. // phpcs:disable Generic.Files.LineLength
  172. return [
  173. [
  174. <<< EOF
  175. <mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
  176. <siteinfo>
  177. <namespaces>
  178. <namespace key="-2" case="first-letter">Media</namespace>
  179. <namespace key="-1" case="first-letter">Special</namespace>
  180. <namespace key="0" case="first-letter" />
  181. <namespace key="1" case="first-letter">Talk</namespace>
  182. <namespace key="2" case="first-letter">User</namespace>
  183. <namespace key="3" case="first-letter">User talk</namespace>
  184. <namespace key="100" case="first-letter">Portal</namespace>
  185. <namespace key="101" case="first-letter">Portal talk</namespace>
  186. </namespaces>
  187. </siteinfo>
  188. </mediawiki>
  189. EOF
  190. ,
  191. [
  192. '-2' => 'Media',
  193. '-1' => 'Special',
  194. '0' => '',
  195. '1' => 'Talk',
  196. '2' => 'User',
  197. '3' => 'User talk',
  198. '100' => 'Portal',
  199. '101' => 'Portal talk',
  200. ]
  201. ],
  202. ];
  203. // phpcs:enable
  204. }
  205. /**
  206. * @dataProvider provideUnknownUserHandling
  207. * @param bool $assign
  208. * @param bool $create
  209. */
  210. public function testUnknownUserHandling( $assign, $create ) {
  211. $hookId = -99;
  212. $this->setMwGlobals( 'wgHooks', [
  213. 'ImportHandleUnknownUser' => [ function ( $name ) use ( $assign, $create, &$hookId ) {
  214. if ( !$assign ) {
  215. $this->fail( 'ImportHandleUnknownUser was called unexpectedly' );
  216. }
  217. $this->assertEquals( 'UserDoesNotExist', $name );
  218. if ( $create ) {
  219. $user = User::createNew( $name );
  220. $this->assertNotNull( $user );
  221. $hookId = $user->getId();
  222. return false;
  223. }
  224. return true;
  225. } ]
  226. ] );
  227. $user = $this->getTestUser()->getUser();
  228. $n = ( $assign ? 1 : 0 ) + ( $create ? 2 : 0 );
  229. // phpcs:disable Generic.Files.LineLength
  230. $source = $this->getDataSource( <<<EOF
  231. <mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
  232. <page>
  233. <title>TestImportPage</title>
  234. <ns>0</ns>
  235. <id>14</id>
  236. <revision>
  237. <id>15</id>
  238. <timestamp>2016-01-01T0$n:00:00Z</timestamp>
  239. <contributor>
  240. <username>UserDoesNotExist</username>
  241. <id>1</id>
  242. </contributor>
  243. <model>wikitext</model>
  244. <format>text/x-wiki</format>
  245. <text xml:space="preserve" bytes="3">foo</text>
  246. <sha1>1e6gpc3ehk0mu2jqu8cg42g009s796b</sha1>
  247. </revision>
  248. <revision>
  249. <id>16</id>
  250. <timestamp>2016-01-01T0$n:00:01Z</timestamp>
  251. <contributor>
  252. <username>{$user->getName()}</username>
  253. <id>{$user->getId()}</id>
  254. </contributor>
  255. <model>wikitext</model>
  256. <format>text/x-wiki</format>
  257. <text xml:space="preserve" bytes="3">bar</text>
  258. <sha1>bjhlo6dxh5wivnszm93u4b78fheiy4t</sha1>
  259. </revision>
  260. </page>
  261. </mediawiki>
  262. EOF
  263. );
  264. // phpcs:enable
  265. $importer = new WikiImporter( $source, MediaWikiServices::getInstance()->getMainConfig() );
  266. $importer->setUsernamePrefix( 'Xxx', $assign );
  267. $importer->doImport();
  268. $db = wfGetDB( DB_MASTER );
  269. $revQuery = Revision::getQueryInfo();
  270. $row = $db->selectRow(
  271. $revQuery['tables'],
  272. $revQuery['fields'],
  273. [ 'rev_timestamp' => $db->timestamp( "201601010{$n}0000" ) ],
  274. __METHOD__,
  275. [],
  276. $revQuery['joins']
  277. );
  278. $this->assertSame(
  279. $assign && $create ? 'UserDoesNotExist' : 'Xxx>UserDoesNotExist',
  280. $row->rev_user_text
  281. );
  282. $this->assertSame( $assign && $create ? $hookId : 0, (int)$row->rev_user );
  283. $row = $db->selectRow(
  284. $revQuery['tables'],
  285. $revQuery['fields'],
  286. [ 'rev_timestamp' => $db->timestamp( "201601010{$n}0001" ) ],
  287. __METHOD__,
  288. [],
  289. $revQuery['joins']
  290. );
  291. $this->assertSame( ( $assign ? '' : 'Xxx>' ) . $user->getName(), $row->rev_user_text );
  292. $this->assertSame( $assign ? $user->getId() : 0, (int)$row->rev_user );
  293. }
  294. public static function provideUnknownUserHandling() {
  295. return [
  296. 'no assign' => [ false, false ],
  297. 'assign, no create' => [ true, false ],
  298. 'assign, create' => [ true, true ],
  299. ];
  300. }
  301. }