| Current File : /home/jvzmxxx/wiki1/extensions/Wikibase/repo/tests/phpunit/includes/Api/SetSiteLinkTest.php |
<?php
namespace Wikibase\Test\Repo\Api;
use UsageException;
use Wikibase\DataModel\Entity\Item;
use Wikibase\DataModel\Entity\ItemId;
use Wikibase\Repo\WikibaseRepo;
/**
* @covers Wikibase\Repo\Api\SetSiteLink
* @covers Wikibase\Repo\Api\ModifyEntity
*
* @license GPL-2.0+
* @author John Erling Blad < jeblad@gmail.com >
* @author Daniel Kinzler
* @author Addshore
* @author Michał Łazowik
* @author Bene* < benestar.wikimedia@gmail.com >
* @author Marius Hoch < hoo@online.de >
*
* @group API
* @group Wikibase
* @group WikibaseAPI
* @group WikibaseRepo
* @group SetSiteLinkTest
* @group BreakingTheSlownessBarrier
*
* The database group has as a side effect that temporal database tables are created. This makes
* it possible to test without poisoning a production database.
* @group Database
*
* Some of the tests takes more time, and needs therefore longer time before they can be aborted
* as non-functional. The reason why tests are aborted is assumed to be set up of temporal databases
* that hold the first tests in a pending state awaiting access to the database.
* @group medium
*/
class SetSiteLinkTest extends WikibaseApiTestCase {
private static $hasSetup;
/* @var ItemId */
private static $gaItemId;
/* @var ItemId */
private static $faItemId;
/* @var ItemId */
private static $otherItemId;
public function provideData() {
return array(
array( //0 set new link using id
'p' => array(
'handle' => 'Leipzig',
'linksite' => 'dewiki',
'linktitle' => 'leipzig',
'badges' => '{gaItem}|{faItem}'
),
'e' => array(
'value' => array( 'dewiki' => array(
'title' => 'Leipzig',
'badges' => array( '{gaItem}', '{faItem}' )
) )
)
),
array( //1 set new link using sitelink
'p' => array(
'site' => 'dewiki',
'title' => 'Berlin',
'linksite' => 'nowiki',
'linktitle' => 'berlin'
),
'e' => array(
'value' => array( 'nowiki' => array(
'title' => 'Berlin',
'badges' => array()
) ),
'indb' => 5
)
),
array( //2 modify link using id
'p' => array(
'handle' => 'Leipzig',
'linksite' => 'dewiki',
'linktitle' => 'Leipzig_Two',
'badges' => ''
),
'e' => array(
'value' => array( 'dewiki' => array(
'title' => 'Leipzig Two',
'badges' => array()
) )
)
),
array( //3 modify link using sitelink
'p' => array(
'site' => 'dewiki',
'title' => 'Berlin',
'linksite' => 'nowiki',
'linktitle' => 'Berlin_Two'
),
'e' => array(
'value' => array( 'nowiki' => array(
'title' => 'Berlin Two',
'badges' => array()
) ),
'indb' => 5
)
),
array( //4 remove link using id (with a summary)
'p' => array(
'handle' => 'Leipzig',
'linksite' => 'dewiki',
'linktitle' => '',
'summary' => 'WooSummary'
),
'e' => array( 'value' => array() ) ),
array( //5 remove link using sitelink
'p' => array(
'site' => 'dewiki',
'title' => 'Berlin',
'linksite' => 'nowiki',
'linktitle' => ''
),
'e' => array( 'value' => array(), 'indb' => 4 ) ),
array( //6 add badges to existing sitelink
'p' => array(
'site' => 'dewiki',
'title' => 'Berlin',
'linksite' => 'dewiki',
'linktitle' => 'Berlin',
'badges' => '{faItem}|{gaItem}'
),
'e' => array(
'value' => array( 'dewiki' => array(
'title' => 'Berlin',
'badges' => array( '{faItem}', '{gaItem}' )
) ),
'indb' => 4
)
),
array( //7 add duplicate badges to existing sitelink
'p' => array(
'site' => 'dewiki',
'title' => 'Berlin',
'linksite' => 'dewiki',
'linktitle' => 'Berlin',
'badges' => '{gaItem}|{gaItem}|{faItem}|{gaItem}'
),
'e' => array(
'value' => array( 'dewiki' => array(
'title' => 'Berlin',
'badges' => array( '{gaItem}', '{faItem}' )
) ),
'indb' => 4
)
),
array( //8 no change
'p' => array(
'site' => 'dewiki',
'title' => 'Berlin',
'linksite' => 'dewiki',
'linktitle' => 'Berlin',
'badges' => '{gaItem}|{faItem}'
),
'e' => array(
'value' => array( 'dewiki' => array(
'title' => 'Berlin',
'badges' => array( '{gaItem}', '{faItem}' )
) ),
'indb' => 4
)
),
array( //9 change only title, badges should be intact
'p' => array(
'site' => 'dewiki',
'title' => 'Berlin',
'linksite' => 'dewiki',
'linktitle' => 'Berlin_Two'
),
'e' => array(
'value' => array( 'dewiki' => array(
'title' => 'Berlin Two',
'badges' => array( '{gaItem}', '{faItem}' )
) ),
'indb' => 4
)
),
array( //10 change both title and badges
'p' => array(
'site' => 'dewiki',
'title' => 'Berlin Two',
'linksite' => 'dewiki',
'linktitle' => 'Berlin',
'badges' => '{gaItem}'
),
'e' => array(
'value' => array( 'dewiki' => array(
'title' => 'Berlin',
'badges' => array( '{gaItem}' )
) ),
'indb' => 4
)
),
array( //11 change only badges, title intact
'p' => array(
'site' => 'dewiki',
'title' => 'Berlin',
'linksite' => 'dewiki',
'badges' => '{gaItem}|{faItem}'
),
'e' => array(
'value' => array( 'dewiki' => array(
'title' => 'Berlin',
'badges' => array( '{gaItem}', '{faItem}' )
) ),
'indb' => 4
)
),
array( //12 set new link using id (without badges)
'p' => array(
'handle' => 'Berlin',
'linksite' => 'svwiki',
'linktitle' => 'Berlin'
),
'e' => array(
'value' => array( 'svwiki' => array(
'title' => 'Berlin',
'badges' => array()
) ),
'indb' => 5
)
),
array( //13 delete link by not providing neither title nor badges
'p' => array( 'handle' => 'Berlin', 'linksite' => 'svwiki' ),
'e' => array( 'value' => array(), 'indb' => 4 )
),
);
}
public function provideExceptionData() {
return array(
array( //0 badtoken
'p' => array(
'site' => 'dewiki',
'title' => 'Berlin',
'linksite' => 'svwiki',
'linktitle' => 'testSetSiteLinkWithNoToken'
),
'e' => array( 'exception' => array(
'type' => UsageException::class,
'code' => 'notoken',
'message' => 'The token parameter must be set'
) )
),
array( //1
'p' => array(
'site' => 'dewiki',
'title' => 'Berlin',
'linksite' => 'svwiki',
'linktitle' => 'testSetSiteLinkWithBadToken',
'token' => '88888888888888888888888888888888+\\'
),
'e' => array( 'exception' => array(
'type' => UsageException::class,
'code' => 'badtoken',
'message' => 'Invalid token'
) )
),
array( //2 testSetSiteLinkWithNoId
'p' => array(
'linksite' => 'enwiki',
'linktitle' => 'testSetSiteLinkWithNoId'
),
'e' => array( 'exception' => array( 'type' => UsageException::class ) ) ),
array( //3 testSetSiteLinkWithBadId
'p' => array(
'id' => 123456789,
'linksite' => 'enwiki',
'linktitle' => 'testSetSiteLinkWithNoId'
),
'e' => array( 'exception' => array( 'type' => UsageException::class ) ) ),
array( //4 testSetSiteLinkWithBadSite
'p' => array(
'site' => 'dewiktionary',
'title' => 'Berlin',
'linksite' => 'enwiki',
'linktitle' => 'Berlin'
),
'e' => array( 'exception' => array( 'type' => UsageException::class ) ) ),
array( //5 testSetSiteLinkWithBadTitle
'p' => array(
'site' => 'dewiki',
'title' => 'BadTitle_de',
'linksite' => 'enwiki',
'linktitle' => 'BadTitle_en'
),
'e' => array( 'exception' => array( 'type' => UsageException::class ) ) ),
array( //6 testSetSiteLinkWithBadTargetSite
'p' => array(
'site' => 'dewiki',
'title' => 'Berlin',
'linksite' => 'enwiktionary',
'linktitle' => 'Berlin'
),
'e' => array( 'exception' => array( 'type' => UsageException::class ) ) ),
array( //7 badge item does not exist
'p' => array(
'site' => 'enwiki',
'title' => 'Berlin',
'linksite' => 'enwiki',
'linktitle' => 'Berlin',
'badges' => 'Q99999|{faItem}'
),
'e' => array( 'exception' => array(
'type' => UsageException::class,
'code' => 'no-such-entity'
) )
),
array( //8 no sitelink - cannot change badges
'p' => array(
'site' => 'enwiki',
'title' => 'Berlin',
'linksite' => 'svwiki',
'badges' => '{gaItem}|{faItem}'
),
'e' => array( 'exception' => array(
'type' => UsageException::class,
'code' => 'no-such-sitelink'
) )
),
);
}
public function provideBadBadgeData() {
return array(
array( //0 bad badge id
array( 'site' => 'enwiki',
'title' => 'Berlin',
'linksite' => 'enwiki',
'linktitle' => 'Berlin',
'badges' => 'abc|{faItem}'
),
),
array( //1 badge id is not an item id
array( 'site' => 'enwiki',
'title' => 'Berlin',
'linksite' => 'enwiki',
'linktitle' => 'Berlin',
'badges' => 'P2|{faItem}'
),
),
array( //2 badge id is not specified
array( 'site' => 'enwiki',
'title' => 'Berlin',
'linksite' => 'enwiki',
'linktitle' => 'Berlin',
'badges' => '{faItem}|{otherItem}'
)
)
);
}
protected function setUp() {
parent::setUp();
if ( !isset( self::$hasSetup ) ) {
$wikibaseRepo = WikibaseRepo::getDefaultInstance();
$store = $wikibaseRepo->getEntityStore();
$this->initTestEntities( array( 'StringProp', 'Leipzig', 'Berlin' ) );
$badge = new Item();
$store->saveEntity( $badge, 'SetSiteLinkTestGA', $GLOBALS['wgUser'], EDIT_NEW );
self::$gaItemId = $badge->getId();
$badge = new Item();
$store->saveEntity( $badge, 'SetSiteLinkTestFA', $GLOBALS['wgUser'], EDIT_NEW );
self::$faItemId = $badge->getId();
$badge = new Item();
$store->saveEntity( $badge, 'SetSiteLinkTestOther', $GLOBALS['wgUser'], EDIT_NEW );
self::$otherItemId = $badge->getId();
$wikibaseRepo->getSettings()->setSetting( 'badgeItems', array(
self::$gaItemId->getSerialization() => '',
self::$faItemId->getSerialization() => '',
'Q99999' => '', // Just in case we have a wrong config
) );
}
self::$hasSetup = true;
}
/**
* Replace badge item id placeholders in expected results
*
* @param array $value
* @return array
*/
private function expectionPlaceholder( array $value ) {
foreach ( $value as &$site ) {
if ( !isset( $site['badges'] ) ) {
continue;
}
foreach ( $site['badges'] as &$dummy ) {
if ( $dummy === '{gaItem}' ) {
$dummy = self::$gaItemId->getSerialization();
} elseif ( $dummy === '{faItem}' ) {
$dummy = self::$faItemId->getSerialization();
} elseif ( $dummy === '{otherItem}' ) {
$dummy = self::$otherItemId->getSerialization();
}
}
}
return $value;
}
/**
* @dataProvider provideData
*/
public function testSetSiteLink( array $params, array $expected ) {
// -- set any defaults ------------------------------------
if ( array_key_exists( 'handle', $params ) ) {
$params['id'] = EntityTestHelper::getId( $params['handle'] );
unset( $params['handle'] );
}
$params['action'] = 'wbsetsitelink';
// Replace the placeholder item ids in the API params
if ( isset( $params['badges'] ) ) {
$params['badges'] = str_replace(
array( '{gaItem}', '{faItem}', '{otherItem}' ),
array( self::$gaItemId->getSerialization(), self::$faItemId->getSerialization(), self::$otherItemId->getSerialization() ),
$params['badges']
);
}
// -- do the request --------------------------------------------------
list( $result, , ) = $this->doApiRequestWithToken( $params );
//@todo all of the below is very similar to the code in ModifyTermTestCase
//This might be able to go in the same place
// Replace the placeholder item ids in the expected results... this sucks
if ( is_array( $expected['value'] ) ) {
$expected['value'] = $this->expectionPlaceholder( $expected['value'] );
}
// -- check the result ------------------------------------------------
$this->assertArrayHasKey( 'success', $result, "Missing 'success' marker in response." );
$this->assertResultHasEntityType( $result );
$this->assertArrayHasKey( 'entity', $result, "Missing 'entity' section in response." );
$this->assertArrayHasKey( 'lastrevid', $result['entity'], 'entity should contain lastrevid key' );
// -- check the result only has our changed data (if any) ------------
$linkSite = $params['linksite'];
$siteLinks = $result['entity']['sitelinks'];
$this->assertEquals( 1, count( $siteLinks ),
"Entity return contained more than a single site"
);
$this->assertArrayHasKey( $linkSite, $siteLinks,
"Entity doesn't return expected site"
);
$siteLink = $siteLinks[$linkSite];
$this->assertEquals( $linkSite, $siteLink['site'],
"Returned incorrect site"
);
if ( array_key_exists( $linkSite, $expected['value'] ) ) {
$expectedSiteLink = $expected['value'][$linkSite];
$this->assertArrayHasKey( 'url', $siteLink );
$this->assertEquals( $expectedSiteLink['title'], $siteLink['title'],
"Returned incorrect title"
);
$this->assertArrayHasKey( 'badges', $siteLink );
$this->assertArrayEquals( $expectedSiteLink['badges'], $siteLink['badges'] );
} elseif ( empty( $expected['value'] ) ) {
$this->assertArrayHasKey( 'removed', $siteLink,
"Entity doesn't return expected 'removed' marker"
);
}
// -- check any warnings ----------------------------------------------
if ( array_key_exists( 'warning', $expected ) ) {
$this->assertArrayHasKey( 'warnings', $result, "Missing 'warnings' section in response." );
$this->assertEquals( $expected['warning'], $result['warnings']['messages']['0']['name'] );
$this->assertArrayHasKey( 'html', $result['warnings']['messages'] );
}
// -- check item in database -------------------------------------------
$dbEntity = $this->loadEntity( $result['entity']['id'] );
$expectedInDb = count( $expected['value'] );
if ( array_key_exists( 'indb', $expected ) ) {
$expectedInDb = $expected['indb'];
}
$this->assertArrayHasKey( 'sitelinks', $dbEntity );
$this->assertCount( $expectedInDb, $dbEntity['sitelinks'] );
$this->assertContainsAllSiteLinks( $expected['value'], $dbEntity['sitelinks'] );
// -- check the edit summary --------------------------------------------
if ( ! array_key_exists( 'warning', $expected ) || $expected['warning'] != 'edit-no-change' ) {
$this->assertRevisionSummary( array( 'wbsetsitelink', $params['linksite'] ), $result['entity']['lastrevid'] );
if ( array_key_exists( 'summary', $params ) ) {
$this->assertRevisionSummary( "/{$params['summary']}/", $result['entity']['lastrevid'] );
}
}
}
/**
* @param array[] $expectedSiteLinks
* @param array[] $dbSiteLinks
*/
private function assertContainsAllSiteLinks( array $expectedSiteLinks, array $dbSiteLinks ) {
foreach ( $expectedSiteLinks as $site => $expectedSiteLink ) {
$this->assertArrayHasKey( $site, $dbSiteLinks );
$dbSiteLink = $dbSiteLinks[$site];
$this->assertArrayHasKey( 'title', $dbSiteLink );
$this->assertInternalType( 'string', $dbSiteLink['title'] );
$this->assertSame( $expectedSiteLink['title'], $dbSiteLink['title'] );
$this->assertArrayHasKey( 'badges', $dbSiteLink );
$this->assertInternalType( 'array', $dbSiteLink['badges'] );
$this->assertArrayEquals( $expectedSiteLink['badges'], $dbSiteLink['badges'] );
}
}
/**
* @dataProvider provideExceptionData
*/
public function testSetSiteLinkExceptions( array $params, array $expected ) {
// -- set any defaults ------------------------------------
$params['action'] = 'wbsetsitelink';
// Replace the placeholder item ids in the API params
if ( isset( $params['badges'] ) ) {
$params['badges'] = str_replace(
array( '{gaItem}', '{faItem}', '{otherItem}' ),
array( self::$gaItemId->getSerialization(), self::$faItemId->getSerialization(), self::$otherItemId->getSerialization() ),
$params['badges']
);
}
$this->doTestQueryExceptions( $params, $expected['exception'] );
}
/**
* @dataProvider provideBadBadgeData
*/
public function testBadBadges( array $params ) {
// -- set any defaults ------------------------------------
$params['action'] = 'wbsetsitelink';
// Replace the placeholder item ids in the API params
if ( isset( $params['badges'] ) ) {
$params['badges'] = str_replace(
array( '{gaItem}', '{faItem}', '{otherItem}' ),
array( self::$gaItemId->getSerialization(), self::$faItemId->getSerialization(), self::$otherItemId->getSerialization() ),
$params['badges']
);
}
list( $result, ) = $this->doApiRequestWithToken( $params );
$warning = $result['warnings']['wbsetsitelink']['warnings'];
$this->assertContains( 'Unrecognized value for parameter \'badges\'', $warning );
}
}