Completed
Push — master ( b5c57e...a9243a )
by
unknown
06:33
created

testGetPropertyTermStoreWriter_withLocalProperties()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Wikibase\Repo\Tests;
4
5
use DataValues\DataValue;
6
use DataValues\Geo\Values\GlobeCoordinateValue;
7
use DataValues\Geo\Values\LatLongValue;
8
use DataValues\MonolingualTextValue;
9
use DataValues\QuantityValue;
10
use DataValues\StringValue;
11
use DataValues\TimeValue;
12
use DataValues\UnboundedQuantityValue;
13
use DataValues\UnknownValue;
14
use Deserializers\Deserializer;
15
use LogicException;
16
use MediaWiki\Http\HttpRequestFactory;
17
use MediaWikiIntegrationTestCase;
18
use ReflectionClass;
19
use ReflectionMethod;
20
use RequestContext;
21
use Serializers\Serializer;
22
use User;
23
use Wikibase\DataAccess\EntitySource;
24
use Wikibase\DataAccess\EntitySourceDefinitions;
25
use Wikibase\DataModel\DeserializerFactory;
26
use Wikibase\DataModel\Entity\EntityIdParser;
27
use Wikibase\DataModel\Entity\EntityIdValue;
28
use Wikibase\DataModel\Entity\ItemId;
29
use Wikibase\DataModel\Entity\PropertyId;
30
use Wikibase\DataModel\SerializerFactory;
31
use Wikibase\DataModel\Services\Lookup\EntityLookup;
32
use Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup;
33
use Wikibase\DataModel\Services\Lookup\TermLookup;
34
use Wikibase\DataModel\Services\Statement\StatementGuidParser;
35
use Wikibase\DataModel\Services\Statement\StatementGuidValidator;
36
use Wikibase\DataModel\Services\Term\TermBuffer;
37
use Wikibase\Lib\Changes\EntityChangeFactory;
38
use Wikibase\Lib\ContentLanguages;
39
use Wikibase\Lib\DataTypeDefinitions;
40
use Wikibase\Lib\DataTypeFactory;
41
use Wikibase\Lib\DataValueFactory;
42
use Wikibase\Lib\EntityFactory;
43
use Wikibase\Lib\EntityTypeDefinitions;
44
use Wikibase\Lib\Formatters\OutputFormatSnakFormatterFactory;
45
use Wikibase\Lib\Formatters\OutputFormatValueFormatterFactory;
46
use Wikibase\Lib\Formatters\WikibaseSnakFormatterBuilders;
47
use Wikibase\Lib\Formatters\WikibaseValueFormatterBuilders;
48
use Wikibase\Lib\Interactors\TermSearchInteractor;
49
use Wikibase\Lib\LanguageFallbackChainFactory;
50
use Wikibase\Lib\SettingsArray;
51
use Wikibase\Lib\Store\EntityArticleIdLookup;
52
use Wikibase\Lib\Store\EntityContentDataCodec;
53
use Wikibase\Lib\Store\EntityExistenceChecker;
54
use Wikibase\Lib\Store\EntityIdLookup;
55
use Wikibase\Lib\Store\EntityNamespaceLookup;
56
use Wikibase\Lib\Store\EntityRedirectChecker;
57
use Wikibase\Lib\Store\EntityRevisionLookup;
58
use Wikibase\Lib\Store\EntityStore;
59
use Wikibase\Lib\Store\EntityStoreWatcher;
60
use Wikibase\Lib\Store\EntityTitleLookup;
61
use Wikibase\Lib\Store\EntityTitleTextLookup;
62
use Wikibase\Lib\Store\EntityUrlLookup;
63
use Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookupFactory;
64
use Wikibase\Lib\Store\LinkTargetEntityIdLookup;
65
use Wikibase\Lib\Store\PropertyInfoLookup;
66
use Wikibase\Lib\Store\PropertyInfoStore;
67
use Wikibase\Lib\Store\ThrowingEntityTermStoreWriter;
68
use Wikibase\Lib\StringNormalizer;
69
use Wikibase\Lib\WikibaseSettings;
70
use Wikibase\Repo\Api\ApiHelperFactory;
71
use Wikibase\Repo\BuilderBasedDataTypeValidatorFactory;
72
use Wikibase\Repo\ChangeOp\ChangeOpFactoryProvider;
73
use Wikibase\Repo\ChangeOp\Deserialization\ChangeOpDeserializerFactory;
74
use Wikibase\Repo\ChangeOp\EntityChangeOpProvider;
75
use Wikibase\Repo\Content\EntityContentFactory;
76
use Wikibase\Repo\Content\EntityHandler;
77
use Wikibase\Repo\EditEntity\MediawikiEditEntityFactory;
78
use Wikibase\Repo\EntityIdHtmlLinkFormatterFactory;
79
use Wikibase\Repo\Interactors\ItemMergeInteractor;
80
use Wikibase\Repo\Interactors\ItemRedirectCreationInteractor;
81
use Wikibase\Repo\LinkedData\EntityDataFormatProvider;
82
use Wikibase\Repo\LinkedData\EntityDataUriManager;
83
use Wikibase\Repo\Localizer\ExceptionLocalizer;
84
use Wikibase\Repo\Notifications\ChangeNotifier;
85
use Wikibase\Repo\ParserOutput\EntityParserOutputGeneratorFactory;
86
use Wikibase\Repo\PropertyInfoBuilder;
87
use Wikibase\Repo\Rdf\EntityRdfBuilderFactory;
88
use Wikibase\Repo\Rdf\RdfVocabulary;
89
use Wikibase\Repo\Rdf\ValueSnakRdfBuilderFactory;
90
use Wikibase\Repo\SnakFactory;
91
use Wikibase\Repo\Store\Store;
92
use Wikibase\Repo\SummaryFormatter;
93
use Wikibase\Repo\ValidatorBuilders;
94
use Wikibase\Repo\Validators\CompositeValidator;
95
use Wikibase\Repo\Validators\EntityExistsValidator;
96
use Wikibase\Repo\Validators\TermValidatorFactory;
97
use Wikibase\Repo\ValueParserFactory;
98
use Wikibase\Repo\WikibaseRepo;
99
use Wikimedia\Rdbms\ILoadBalancer;
100
use Wikimedia\Rdbms\LBFactory;
101
use Wikimedia\TestingAccessWrapper;
102
103
/**
104
 * @covers \Wikibase\Repo\WikibaseRepo
105
 *
106
 * @group Wikibase
107
 * @group Database
108
 *
109
 * @license GPL-2.0-or-later
110
 * @author Jeroen De Dauw < [email protected] >
111
 * @author Daniel Kinzler
112
 */
113
class WikibaseRepoTest extends MediaWikiIntegrationTestCase {
114
115
	/**
116
	 * @var EntityTypeDefinitions
117
	 */
118
	private $entityTypeDefinitions;
119
120
	protected function setUp(): void {
121
		parent::setUp();
122
123
		// WikibaseRepo service getters should never access the database or do http requests
124
		// https://phabricator.wikimedia.org/T243729
125
		$this->disallowDBAccess();
126
		$this->disallowHttpAccess();
127
128
		$this->entityTypeDefinitions = new EntityTypeDefinitions( [] );
129
	}
130
131
	private function disallowDBAccess() {
132
		$this->setService(
133
			'DBLoadBalancerFactory',
134
			function() {
135
				$lb = $this->createMock( ILoadBalancer::class );
136
				$lb->expects( $this->never() )
137
					->method( 'getConnection' );
138
				$lb->expects( $this->never() )
139
					->method( 'getConnectionRef' );
140
				$lb->expects( $this->never() )
141
					->method( 'getMaintenanceConnectionRef' );
142
				$lb->expects( $this->any() )
143
					->method( 'getLocalDomainID' )
144
					->willReturn( 'banana' );
145
146
				$lbFactory = $this->createMock( LBFactory::class );
147
				$lbFactory->expects( $this->any() )
148
					->method( 'getMainLB' )
149
					->willReturn( $lb );
150
151
				return $lbFactory;
152
			}
153
		);
154
	}
155
156
	private function disallowHttpAccess() {
157
		$this->setService(
158
			'HttpRequestFactory',
159
			function() {
160
				$factory = $this->createMock( HttpRequestFactory::class );
161
				$factory->expects( $this->never() )
162
					->method( 'create' );
163
				$factory->expects( $this->never() )
164
					->method( 'request' );
165
				$factory->expects( $this->never() )
166
					->method( 'get' );
167
				$factory->expects( $this->never() )
168
					->method( 'post' );
169
				return $factory;
170
			}
171
		);
172
	}
173
174
	public function testGetDefaultValidatorBuilders() {
175
		$first = WikibaseRepo::getDefaultValidatorBuilders();
176
		$this->assertInstanceOf( ValidatorBuilders::class, $first );
177
178
		$second = WikibaseRepo::getDefaultValidatorBuilders();
179
		$this->assertSame( $first, $second );
180
	}
181
182
	public function testNewValidatorBuilders() {
183
		$valueToValidate = new EntityIdValue( new ItemId( 'Q123' ) );
184
185
		$repo = $this->getWikibaseRepo();
186
187
		$builders = $repo->newValidatorBuilders();
188
		$this->assertInstanceOf( ValidatorBuilders::class, $builders );
189
190
		// We get the resulting ValueValidators and run them against our fake remote-repo
191
		// custom-type EntityIdValue. We skip the existence check though, since we don't
192
		// have a mock lookup in place.
193
		$entityValidators = $builders->buildEntityValidators();
194
		foreach ( $entityValidators as $validator ) {
195
			if ( $validator instanceof EntityExistsValidator ) {
196
				continue;
197
			}
198
199
			$result = $validator->validate( $valueToValidate );
200
			$this->assertTrue( $result->isValid(), get_class( $validator ) );
201
		}
202
	}
203
204
	/**
205
	 * @dataProvider urlSchemesProvider
206
	 */
207
	public function testDefaultUrlValidators( $input, $expected ) {
208
		$validatorBuilders = WikibaseRepo::getDefaultValidatorBuilders();
209
		$urlValidator = new CompositeValidator( $validatorBuilders->buildUrlValidators() );
210
		$result = $urlValidator->validate( new StringValue( $input ) );
211
		$this->assertSame( $expected, $result->isValid() );
212
	}
213
214
	public function urlSchemesProvider() {
215
		return [
216
			[ 'bzr://x', true ],
217
			[ 'cvs://x', true ],
218
			[ 'ftp://x', true ],
219
			[ 'git://x', true ],
220
			[ 'http://x', true ],
221
			[ 'https://x', true ],
222
			[ 'irc://x', true ],
223
			[ 'mailto:x@x', true ],
224
			[ 'ssh://x', true ],
225
			[ 'svn://x', true ],
226
227
			// Supported by UrlSchemeValidators, but not enabled by default.
228
			[ 'ftps://x', false ],
229
			[ 'gopher://x', false ],
230
			[ 'ircs://x', false ],
231
			[ 'mms://x', false ],
232
			[ 'nntp://x', false ],
233
			[ 'redis://x', false ],
234
			[ 'sftp://x', false ],
235
			[ 'telnet://x', false ],
236
			[ 'worldwind://x', false ],
237
		];
238
	}
239
240
	public function testGetDefaultValueFormatterBuilders() {
241
		$first = $this->getWikibaseRepo()->getDefaultValueFormatterBuilders();
242
		$this->assertInstanceOf( WikibaseValueFormatterBuilders::class, $first );
243
244
		$second = $this->getWikibaseRepo()->getDefaultValueFormatterBuilders();
245
		$this->assertSame( $first, $second );
246
	}
247
248
	public function testGetDefaultSnakFormatterBuilders() {
249
		$first = $this->getWikibaseRepo()->getDefaultSnakFormatterBuilders();
250
		$this->assertInstanceOf( WikibaseSnakFormatterBuilders::class, $first );
251
252
		$second = $this->getWikibaseRepo()->getDefaultSnakFormatterBuilders();
253
		$this->assertSame( $first, $second );
254
	}
255
256
	public function testGetDataTypeFactoryReturnType() {
257
		$returnValue = $this->getWikibaseRepo()->getDataTypeFactory();
258
		$this->assertInstanceOf( DataTypeFactory::class, $returnValue );
259
	}
260
261
	public function testGetValueParserFactoryReturnType() {
262
		$returnValue = $this->getWikibaseRepo()->getValueParserFactory();
263
		$this->assertInstanceOf( ValueParserFactory::class, $returnValue );
264
	}
265
266
	public function testGetDataValueFactoryReturnType() {
267
		$returnValue = $this->getWikibaseRepo()->getDataValueFactory();
268
		$this->assertInstanceOf( DataValueFactory::class, $returnValue );
269
	}
270
271
	public function testGetEntityContentFactoryReturnType() {
272
		$returnValue = $this->getWikibaseRepo()->getEntityContentFactory();
273
		$this->assertInstanceOf( EntityContentFactory::class, $returnValue );
274
	}
275
276
	public function testGetEntityStoreWatcherReturnType() {
277
		$returnValue = $this->getWikibaseRepo()->getEntityStoreWatcher();
278
		$this->assertInstanceOf( EntityStoreWatcher::class, $returnValue );
279
	}
280
281
	public function testGetEntityTitleLookupReturnType() {
282
		$returnValue = $this->getWikibaseRepo()->getEntityTitleLookup();
283
		$this->assertInstanceOf( EntityTitleLookup::class, $returnValue );
284
	}
285
286
	public function testGetEntityTitleTextLookupReturnType() {
287
		$returnValue = $this->getWikibaseRepo()->getEntityTitleTextLookup();
288
		$this->assertInstanceOf( EntityTitleTextLookup::class, $returnValue );
289
	}
290
291
	public function testGetEntityUrlLookupReturnType() {
292
		$returnValue = $this->getWikibaseRepo()->getEntityUrlLookup();
293
		$this->assertInstanceOf( EntityUrlLookup::class, $returnValue );
294
	}
295
296
	public function testGetEntityArticleIdLookupReturnType() {
297
		$returnValue = $this->getWikibaseRepo()->getEntityArticleIdLookup();
298
		$this->assertInstanceOf( EntityArticleIdLookup::class, $returnValue );
299
	}
300
301
	public function testGetEntityExistenceCheckerReturnType() {
302
		$returnValue = $this->getWikibaseRepo()->getEntityExistenceChecker();
303
		$this->assertInstanceOf( EntityExistenceChecker::class, $returnValue );
304
	}
305
306
	public function testGetEntityRedirectCheckerReturnType() {
307
		$returnValue = $this->getWikibaseRepo()->getEntityRedirectChecker();
308
		$this->assertInstanceOf( EntityRedirectChecker::class, $returnValue );
309
	}
310
311
	public function testGetEntityIdLookupReturnType() {
312
		$returnValue = $this->getWikibaseRepo()->getEntityIdLookup();
313
		$this->assertInstanceOf( EntityIdLookup::class, $returnValue );
314
	}
315
316
	public function testGetEntityRevisionLookupReturnType() {
317
		$returnValue = $this->getWikibaseRepo()->getEntityRevisionLookup();
318
		$this->assertInstanceOf( EntityRevisionLookup::class, $returnValue );
319
	}
320
321
	public function testNewRedirectCreationInteractorReturnType() {
322
		$user = $this->getMockBuilder( User::class )
323
			->disableOriginalConstructor()
324
			->getMock();
325
		$context = new RequestContext();
326
		$returnValue = $this->getWikibaseRepo()->newItemRedirectCreationInteractor( $user, $context );
327
		$this->assertInstanceOf( ItemRedirectCreationInteractor::class, $returnValue );
328
	}
329
330
	public function testNewTermSearchInteractorReturnType() {
331
		$returnValue = $this->getWikibaseRepo()->newTermSearchInteractor( '' );
332
		$this->assertInstanceOf( TermSearchInteractor::class, $returnValue );
333
	}
334
335
	public function testGetEntityStoreReturnType() {
336
		$returnValue = $this->getWikibaseRepo()->getEntityStore();
337
		$this->assertInstanceOf( EntityStore::class, $returnValue );
338
	}
339
340
	public function testGetPropertyDataTypeLookupReturnType() {
341
		$returnValue = $this->getWikibaseRepo()->getPropertyDataTypeLookup();
342
		$this->assertInstanceOf( PropertyDataTypeLookup::class, $returnValue );
343
	}
344
345
	public function testGetStringNormalizerReturnType() {
346
		$returnValue = $this->getWikibaseRepo()->getStringNormalizer();
347
		$this->assertInstanceOf( StringNormalizer::class, $returnValue );
348
	}
349
350
	public function testGetEntityLookupReturnType() {
351
		$returnValue = $this->getWikibaseRepo()->getEntityLookup();
352
		$this->assertInstanceOf( EntityLookup::class, $returnValue );
353
	}
354
355
	public function testGetSnakFactoryReturnType() {
356
		$returnValue = $this->getWikibaseRepo()->getSnakFactory();
357
		$this->assertInstanceOf( SnakFactory::class, $returnValue );
358
	}
359
360
	public function testGetEntityIdParserReturnType() {
361
		$returnValue = $this->getWikibaseRepo()->getEntityIdParser();
362
		$this->assertInstanceOf( EntityIdParser::class, $returnValue );
363
	}
364
365
	public function testGetStatementGuidParser() {
366
		$returnValue = $this->getWikibaseRepo()->getStatementGuidParser();
367
		$this->assertInstanceOf( StatementGuidParser::class, $returnValue );
368
	}
369
370
	public function testGetEntityChangeOpProvider() {
371
		$provider = $this->getWikibaseRepo()->getEntityChangeOpProvider();
372
		$this->assertInstanceOf( EntityChangeOpProvider::class, $provider );
373
	}
374
375
	public function testGetChangeOpDeserializerFactory() {
376
		$factory = $this->getWikibaseRepo()->getChangeOpDeserializerFactory();
377
		$this->assertInstanceOf( ChangeOpDeserializerFactory::class, $factory );
378
	}
379
380
	public function testGetLanguageFallbackChainFactory() {
381
		$returnValue = $this->getWikibaseRepo()->getLanguageFallbackChainFactory();
382
		$this->assertInstanceOf( LanguageFallbackChainFactory::class, $returnValue );
383
	}
384
385
	public function testGetLanguageFallbackLabelDescriptionLookupFactory() {
386
		$returnValue = $this->getWikibaseRepo()->getLanguageFallbackLabelDescriptionLookupFactory();
387
		$this->assertInstanceOf( LanguageFallbackLabelDescriptionLookupFactory::class, $returnValue );
388
	}
389
390
	public function testGetStatementGuidValidator() {
391
		$returnValue = $this->getWikibaseRepo()->getStatementGuidValidator();
392
		$this->assertInstanceOf( StatementGuidValidator::class, $returnValue );
393
	}
394
395
	public function testGetSettingsReturnType() {
396
		$returnValue = $this->getWikibaseRepo()->getSettings();
397
		$this->assertInstanceOf( SettingsArray::class, $returnValue );
398
	}
399
400
	public function testGetStoreReturnType() {
401
		$returnValue = $this->getWikibaseRepo()->getStore();
402
		$this->assertInstanceOf( Store::class, $returnValue );
403
	}
404
405
	public function testGetSnakFormatterFactory() {
406
		$returnValue = $this->getWikibaseRepo()->getSnakFormatterFactory();
407
		$this->assertInstanceOf( OutputFormatSnakFormatterFactory::class, $returnValue );
408
	}
409
410
	public function testGetValueFormatterFactory() {
411
		$returnValue = $this->getWikibaseRepo()->getValueFormatterFactory();
412
		$this->assertInstanceOf( OutputFormatValueFormatterFactory::class, $returnValue );
413
	}
414
415
	public function testGetSummaryFormatter() {
416
		$returnValue = $this->getWikibaseRepo()->getSummaryFormatter();
417
		$this->assertInstanceOf( SummaryFormatter::class, $returnValue );
418
	}
419
420
	public function testGetTermValidatorFactory() {
421
		$factory = $this->getWikibaseRepo()->getTermValidatorFactory();
422
		$this->assertInstanceOf( TermValidatorFactory::class, $factory );
423
	}
424
425
	public function testGetChangeOpFactory() {
426
		$returnValue = $this->getWikibaseRepo()->getChangeOpFactoryProvider();
427
		$this->assertInstanceOf( ChangeOpFactoryProvider::class, $returnValue );
428
	}
429
430
	public function testGetChangeNotifier() {
431
		$factory = $this->getWikibaseRepo()->getChangeNotifier();
432
		$this->assertInstanceOf( ChangeNotifier::class, $factory );
433
	}
434
435
	public function testGetContentModelMappings() {
436
		$array = $this->getWikibaseRepo()->getContentModelMappings();
437
		$this->assertIsArray( $array );
438
		$this->assertContainsOnly( 'string', $array );
439
	}
440
441
	public function testGetEntityFactory() {
442
		$entityFactory = $this->getWikibaseRepo()->getEntityFactory();
443
		$this->assertInstanceOf( EntityFactory::class, $entityFactory );
444
	}
445
446
	public function testGetLocalEntityTypes() {
447
		$this->entityTypeDefinitions = $this->getEntityTypeDefinitionsWithSubentities();
448
449
		$settings = new SettingsArray( WikibaseRepo::getDefaultInstance()->getSettings()->getArrayCopy() );
450
		$settings->setSetting( 'localEntitySourceName', 'local' );
0 ignored issues
show
Unused Code introduced by
The call to the method Wikibase\Lib\SettingsArray::setSetting() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
451
452
		$wikibaseRepo = new WikibaseRepo(
453
			$settings,
454
			new DataTypeDefinitions( [] ),
455
			$this->entityTypeDefinitions,
456
			new EntitySourceDefinitions( [
457
				new EntitySource(
458
					'local',
459
					false,
460
					[
461
						'foo' => [ 'namespaceId' => 100, 'slot' => 'main' ],
462
						'bar' => [ 'namespaceId' => 102, 'slot' => 'main' ],
463
						'lexeme' => [ 'namespaceId' => 104, 'slot' => 'main' ],
464
					],
465
					'',
466
					'wd',
467
					'',
468
					''
469
				)
470
			], $this->entityTypeDefinitions )
471
		);
472
473
		$localEntityTypes = $wikibaseRepo->getLocalEntityTypes();
474
475
		$this->assertContains( 'foo', $localEntityTypes );
476
		$this->assertContains( 'bar', $localEntityTypes );
477
		$this->assertContains( 'lexeme', $localEntityTypes );
478
		// Sub entities should appear in the list
479
		$this->assertContains( 'form', $localEntityTypes );
480
	}
481
482
	public function testGetLocalEntityNamespaceLookup() {
483
		$settings = new SettingsArray( WikibaseRepo::getDefaultInstance()->getSettings()->getArrayCopy() );
484
		$settings->setSetting( 'localEntitySourceName', 'local' );
0 ignored issues
show
Unused Code introduced by
The call to the method Wikibase\Lib\SettingsArray::setSetting() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
485
486
		$wikibaseRepo = new WikibaseRepo(
487
			$settings,
488
			new DataTypeDefinitions( [] ),
489
			$this->entityTypeDefinitions,
490
			new EntitySourceDefinitions( [
491
				new EntitySource(
492
					'local',
493
					false,
494
					[
495
						'foo' => [ 'namespaceId' => 100, 'slot' => 'main' ],
496
					],
497
					'',
498
					'wd',
499
					'',
500
					''
501
				),
502
				new EntitySource(
503
					'otherSource',
504
					false,
505
					[
506
						'bar' => [ 'namespaceId' => 102, 'slot' => 'main' ],
507
					],
508
					'',
509
					'wd',
510
					'',
511
					''
512
				)
513
			], $this->entityTypeDefinitions )
514
		);
515
516
		$localEntityTypes = $wikibaseRepo->getLocalEntityTypes();
517
518
		$this->assertContains( 'foo', $localEntityTypes );
519
		$this->assertNotContains( 'bar', $localEntityTypes );
520
	}
521
522
	private function getEntityTypeDefinitionsWithSubentities(): EntityTypeDefinitions {
523
		return new EntityTypeDefinitions(
524
			[
525
				'lexeme' => [
526
					EntityTypeDefinitions::SUB_ENTITY_TYPES => [
527
						'form',
528
					],
529
				],
530
			]
531
		);
532
	}
533
534
	public function testGetEnabledEntityTypes() {
535
		if ( !WikibaseSettings::isClientEnabled() ) {
536
			$this->markTestSkipped( 'WikibaseClient must be enabled to run this test' );
537
		}
538
539
		$this->entityTypeDefinitions = $this->getEntityTypeDefinitionsWithSubentities();
540
541
		$settings = new SettingsArray( WikibaseRepo::getDefaultInstance()->getSettings()->getArrayCopy() );
542
543
		$wikibaseRepo = new WikibaseRepo(
544
			$settings,
545
			new DataTypeDefinitions( [] ),
546
			$this->entityTypeDefinitions,
547
			new EntitySourceDefinitions( [
548
				new EntitySource(
549
					'local',
550
					false,
551
					[
552
						'foo' => [ 'namespaceId' => 200, 'slot' => 'main' ],
553
						'bar' => [ 'namespaceId' => 220, 'slot' => 'main' ],
554
					],
555
					'',
556
					'',
557
					'',
558
					''
559
				),
560
				new EntitySource(
561
					'bazwiki',
562
					'bazdb',
563
					[
564
						'baz' => [ 'namespaceId' => 250, 'slot' => 'main' ],
565
					],
566
					'',
567
					'baz',
568
					'baz',
569
					'bazwiki'
570
				),
571
				new EntitySource(
572
					'lexemewiki',
573
					'bazdb',
574
					[
575
						'lexeme' => [ 'namespaceId' => 280, 'slot' => 'main' ],
576
					],
577
					'',
578
					'lex',
579
					'lex',
580
					'lexwiki'
581
				)
582
			], $this->entityTypeDefinitions )
583
		);
584
585
		$enabled = $wikibaseRepo->getEnabledEntityTypes();
586
		$this->assertContains( 'foo', $enabled );
587
		$this->assertContains( 'bar', $enabled );
588
		$this->assertContains( 'baz', $enabled );
589
		$this->assertContains( 'lexeme', $enabled );
590
		$this->assertContains( 'form', $enabled );
591
	}
592
593
	public function testGetExceptionLocalizer() {
594
		$localizer = $this->getWikibaseRepo()->getExceptionLocalizer();
595
		$this->assertInstanceOf( ExceptionLocalizer::class, $localizer );
596
	}
597
598
	public function testGetEntityContentDataCodec() {
599
		$codec = $this->getWikibaseRepo()->getEntityContentDataCodec();
600
		$this->assertInstanceOf( EntityContentDataCodec::class, $codec );
601
	}
602
603
	public function testGetExternalFormatDeserializerFactory() {
604
		$deserializerFactory = $this->getWikibaseRepo()->getBaseDataModelDeserializerFactory();
605
		$this->assertInstanceOf( DeserializerFactory::class, $deserializerFactory );
606
	}
607
608
	public function testGetSerializerFactory() {
609
		$serializerFactory = $this->getWikibaseRepo()->getBaseDataModelSerializerFactory();
610
		$this->assertInstanceOf( SerializerFactory::class, $serializerFactory );
611
	}
612
613
	public function testGetCompactSerializerFactory() {
614
		$serializerFactory = $this->getWikibaseRepo()->getCompactBaseDataModelSerializerFactory();
615
		$this->assertInstanceOf( SerializerFactory::class, $serializerFactory );
616
	}
617
618
	public function testGetInternalFormatEntityDeserializer() {
619
		$deserializer = $this->getWikibaseRepo()->getInternalFormatEntityDeserializer();
620
		$this->assertInstanceOf( Deserializer::class, $deserializer );
621
	}
622
623
	public function testGetEntitySerializer() {
624
		$serializer = $this->getWikibaseRepo()->getAllTypesEntitySerializer();
625
		$this->assertInstanceOf( Serializer::class, $serializer );
626
	}
627
628
	public function testGetCompactEntitySerializer() {
629
		$serializer = $this->getWikibaseRepo()->getCompactEntitySerializer();
630
		$this->assertInstanceOf( Serializer::class, $serializer );
631
	}
632
633
	public function testGetStorageEntitySerializer() {
634
		$serializer = $this->getWikibaseRepo()->getStorageEntitySerializer();
635
		$this->assertInstanceOf( Serializer::class, $serializer );
636
	}
637
638
	public function testGetExternalFormatStatementDeserializer() {
639
		$deserializer = $this->getWikibaseRepo()->getExternalFormatStatementDeserializer();
640
		$this->assertInstanceOf( Deserializer::class, $deserializer );
641
	}
642
643
	public function testGetInternalFormatStatementDeserializer() {
644
		$deserializer = $this->getWikibaseRepo()->getInternalFormatStatementDeserializer();
645
		$this->assertInstanceOf( Deserializer::class, $deserializer );
646
	}
647
648
	public function testGetStatementSerializer() {
649
		$serializer = $this->getWikibaseRepo()->getStatementSerializer();
650
		$this->assertInstanceOf( Serializer::class, $serializer );
651
	}
652
653
	public function testGetEntityChangeFactory() {
654
		$factory = $this->getWikibaseRepo()->getEntityChangeFactory();
655
		$this->assertInstanceOf( EntityChangeFactory::class, $factory );
656
	}
657
658
	public function testNewItemHandler() {
659
		$handler = $this->getWikibaseRepo()->newItemHandler();
660
		$this->assertInstanceOf( EntityHandler::class, $handler );
661
	}
662
663
	public function testNewPropertyHandler() {
664
		$handler = $this->getWikibaseRepo()->newPropertyHandler();
665
		$this->assertInstanceOf( EntityHandler::class, $handler );
666
	}
667
668
	public function testNewItemHandler_noTransform() {
669
		$wikibaseRepo = $this->getWikibaseRepo();
670
		$wikibaseRepo->getSettings()->setSetting( 'transformLegacyFormatOnExport', false );
0 ignored issues
show
Unused Code introduced by
The call to the method Wikibase\Lib\SettingsArray::setSetting() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
671
672
		$handler = $wikibaseRepo->newItemHandler();
673
		$this->assertNull( $handler->getLegacyExportFormatDetector() );
674
	}
675
676
	public function testNewPropertyHandler_noTransform() {
677
		$wikibaseRepo = $this->getWikibaseRepo();
678
		$wikibaseRepo->getSettings()->setSetting( 'transformLegacyFormatOnExport', false );
0 ignored issues
show
Unused Code introduced by
The call to the method Wikibase\Lib\SettingsArray::setSetting() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
679
680
		$handler = $wikibaseRepo->newPropertyHandler();
681
		$this->assertNull( $handler->getLegacyExportFormatDetector() );
682
	}
683
684
	public function testNewItemHandler_withTransform() {
685
		$wikibaseRepo = $this->getWikibaseRepo();
686
		$wikibaseRepo->getSettings()->setSetting( 'transformLegacyFormatOnExport', true );
0 ignored issues
show
Unused Code introduced by
The call to the method Wikibase\Lib\SettingsArray::setSetting() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
687
688
		$handler = $wikibaseRepo->newItemHandler();
689
		$this->assertNotNull( $handler->getLegacyExportFormatDetector() );
690
	}
691
692
	public function testNewPropertyHandler_withTransform() {
693
		$wikibaseRepo = $this->getWikibaseRepo();
694
		$wikibaseRepo->getSettings()->setSetting( 'transformLegacyFormatOnExport', true );
0 ignored issues
show
Unused Code introduced by
The call to the method Wikibase\Lib\SettingsArray::setSetting() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
695
696
		$handler = $wikibaseRepo->newPropertyHandler();
697
		$this->assertNotNull( $handler->getLegacyExportFormatDetector() );
698
	}
699
700
	private function getWikibaseRepo() {
701
		return new WikibaseRepo(
702
			$this->getTestSettings( WikibaseRepo::getDefaultInstance()->getSettings()->getArrayCopy() ),
703
			new DataTypeDefinitions( [] ),
704
			$this->entityTypeDefinitions,
705
			$this->getEntitySourceDefinitions()
706
		);
707
	}
708
709
	/**
710
	 * @param array[] $entityTypeDefinitions
711
	 *
712
	 * @return WikibaseRepo
713
	 */
714
	private function getWikibaseRepoWithCustomEntityTypeDefinitions( $entityTypeDefinitions = [] ) {
715
		$entityTypeDefinitions = new EntityTypeDefinitions( $entityTypeDefinitions );
716
		return new WikibaseRepo(
717
			$this->getTestSettings( WikibaseRepo::getDefaultInstance()->getSettings()->getArrayCopy() ),
718
			new DataTypeDefinitions( [] ),
719
			$entityTypeDefinitions,
720
			$this->getEntitySourceDefinitions( 'test', $entityTypeDefinitions )
721
		);
722
	}
723
724
	private function getWikibaseRepoWithCustomEntitySourceDefinitions( EntitySourceDefinitions $entitySourceDefinitions ) {
725
		return new WikibaseRepo(
726
			$this->getTestSettings( WikibaseRepo::getDefaultInstance()->getSettings()->getArrayCopy() ),
727
			new DataTypeDefinitions( [] ),
728
			$this->entityTypeDefinitions,
729
			$entitySourceDefinitions
730
		);
731
	}
732
733
	private function getTestSettings( $settingsArray ) {
734
		$settings = new SettingsArray( $settingsArray );
735
		$settings->setSetting( 'localEntitySourceName', 'test' );
0 ignored issues
show
Unused Code introduced by
The call to the method Wikibase\Lib\SettingsArray::setSetting() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
736
		return $settings;
737
	}
738
739
	private function getEntitySourceDefinitions(
740
		string $sourceName = 'test',
741
		EntityTypeDefinitions $entityTypeDefinitions = null
742
	) {
743
		return new EntitySourceDefinitions(
744
			[ new EntitySource(
745
				$sourceName,
746
				false,
747
				[
748
					'item' => [ 'namespaceId' => 100, 'slot' => 'main' ],
749
					'property' => [ 'namespaceId' => 200, 'slot' => 'main' ],
750
				],
751
				'',
752
				'',
753
				'',
754
				''
755
			) ],
756
			$entityTypeDefinitions ?? $this->entityTypeDefinitions
757
		);
758
	}
759
760
	public function testGetApiHelperFactory() {
761
		$factory = $this->getWikibaseRepo()->getApiHelperFactory( new RequestContext() );
762
		$this->assertInstanceOf( ApiHelperFactory::class, $factory );
763
	}
764
765
	public function testNewEditEntityFactory() {
766
		$factory = $this->getWikibaseRepo()->newEditEntityFactory( new RequestContext() );
767
		$this->assertInstanceOf( MediawikiEditEntityFactory::class, $factory );
768
	}
769
770
	public function testNewEditEntityFactory_withoutContextParam() {
771
		$factory = $this->getWikibaseRepo()->newEditEntityFactory();
772
		$this->assertInstanceOf( MediawikiEditEntityFactory::class, $factory );
773
	}
774
775
	public function testNewItemMergeInteractor() {
776
		$interactor = $this->getWikibaseRepo()->newItemMergeInteractor( new RequestContext() );
777
		$this->assertInstanceOf( ItemMergeInteractor::class, $interactor );
778
	}
779
780
	public function testGetTermLookup() {
781
		$service = $this->getWikibaseRepo()->getTermLookup();
782
		$this->assertInstanceOf( TermLookup::class, $service );
783
	}
784
785
	public function testGetTermBuffer() {
786
		$service = $this->getWikibaseRepo()->getTermBuffer();
787
		$this->assertInstanceOf( TermBuffer::class, $service );
788
	}
789
790
	public function testGetTermBuffer_instance() {
791
		$repo = $this->getWikibaseRepo();
792
		$service = $repo->getTermBuffer();
793
		$this->assertSame( $service, $repo->getTermBuffer(), 'Second call should return same instance' );
794
		$this->assertSame( $service, $repo->getTermLookup(), 'TermBuffer and TermLookup should be the same object' );
795
	}
796
797
	public function testGetTermsLanguages() {
798
		$service = $this->getWikibaseRepo()->getTermsLanguages();
799
		$this->assertInstanceOf( ContentLanguages::class, $service );
800
	}
801
802
	public function testNewPropertyInfoBuilder() {
803
		$wikibaseRepo = $this->getWikibaseRepo();
804
		$wikibaseRepo->getSettings()->setSetting(
0 ignored issues
show
Unused Code introduced by
The call to the method Wikibase\Lib\SettingsArray::setSetting() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
805
			'formatterUrlProperty',
806
			'P123'
807
		);
808
809
		$wikibaseRepo->getSettings()->setSetting(
0 ignored issues
show
Unused Code introduced by
The call to the method Wikibase\Lib\SettingsArray::setSetting() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
810
			'canonicalUriProperty',
811
			'P321'
812
		);
813
814
		$builder = $wikibaseRepo->newPropertyInfoBuilder();
815
816
		$this->assertInstanceOf( PropertyInfoBuilder::class, $builder );
817
		$expected = [
818
			PropertyInfoLookup::KEY_FORMATTER_URL => new PropertyId( 'P123' ),
819
			PropertyInfoStore::KEY_CANONICAL_URI => new PropertyId( 'P321' )
820
		];
821
		$this->assertEquals( $expected,  $builder->getPropertyIdMap() );
822
	}
823
824
	public function testGetEntityNamespaceLookup() {
825
		$service = $this->getWikibaseRepo()->getEntityNamespaceLookup();
826
		$this->assertInstanceOf( EntityNamespaceLookup::class, $service );
827
	}
828
829
	public function testGetEntityIdHtmlLinkFormatterFactory() {
830
		$service = $this->getWikibaseRepo()->getEntityIdHtmlLinkFormatterFactory();
831
		$this->assertInstanceOf( EntityIdHtmlLinkFormatterFactory::class, $service );
832
	}
833
834
	public function testGetEntityDataFormatProvider() {
835
		$service = $this->getWikibaseRepo()->getEntityDataFormatProvider();
836
		$this->assertInstanceOf( EntityDataFormatProvider::class, $service );
837
	}
838
839
	public function testGetEntityDataUriManager() {
840
		$service = $this->getWikibaseRepo()->getEntityDataUriManager();
841
		$this->assertInstanceOf( EntityDataUriManager::class, $service );
842
	}
843
844
	public function testGetEntityParserOutputGeneratorFactory() {
845
		$service = $this->getWikibaseRepo()->getEntityParserOutputGeneratorFactory();
846
		$this->assertInstanceOf( EntityParserOutputGeneratorFactory::class, $service );
847
	}
848
849
	public function testGetDataTypeValidatorFactory() {
850
		$service = $this->getWikibaseRepo()->getDataTypeValidatorFactory();
851
		$this->assertInstanceOf( BuilderBasedDataTypeValidatorFactory::class, $service );
852
	}
853
854
	public function testGetDataTypeDefinitions() {
855
		$dataTypeDefinitions = $this->getWikibaseRepo()->getDataTypeDefinitions();
856
		$this->assertInstanceOf( DataTypeDefinitions::class, $dataTypeDefinitions );
857
	}
858
859
	public function testGetValueSnakRdfBuilderFactory() {
860
		$factory = $this->getWikibaseRepo()->getValueSnakRdfBuilderFactory();
861
		$this->assertInstanceOf( ValueSnakRdfBuilderFactory::class, $factory );
862
	}
863
864
	public function testGetRdfVocabulary() {
865
		$factory = $this->getWikibaseRepo()->getRdfVocabulary();
866
		$this->assertInstanceOf( RdfVocabulary::class, $factory );
867
	}
868
869
	public function testGetEntityRdfBuilderFactory() {
870
		$provider = $this->getWikibaseRepo()->getEntityRdfBuilderFactory();
871
		$this->assertInstanceOf( EntityRdfBuilderFactory::class, $provider );
872
	}
873
874
	/**
875
	 * @return DataValueFactory
876
	 */
877
	private function getDataValueFactory() {
878
		return $this->getWikibaseRepoWithCustomEntityTypeDefinitions( [
879
			'item' => [
880
				EntityTypeDefinitions::ENTITY_ID_PATTERN => ItemId::PATTERN,
881
				EntityTypeDefinitions::ENTITY_ID_BUILDER => function ( $serialization ) {
882
					return new ItemId( $serialization );
883
				},
884
			],
885
		] )->getDataValueFactory();
886
	}
887
888
	public function dataValueProvider() {
889
		return [
890
			'string' => [ new StringValue( 'Test' ) ],
891
			'unknown' => [ new UnknownValue( [ 'foo' => 'bar' ] ) ],
892
			'globecoordinate' => [ new GlobeCoordinateValue( new LatLongValue( 2, 3 ), 1 ) ],
893
			'monolingualtext' => [ new MonolingualTextValue( 'als', 'Test' ) ],
894
			'unbounded quantity' => [ UnboundedQuantityValue::newFromNumber( 2 ) ],
895
			'quantity' => [ QuantityValue::newFromNumber( 2 ) ],
896
			'time' => [ new TimeValue(
897
				'+1980-10-07T17:33:22Z',
898
				0,
899
				0,
900
				1,
901
				TimeValue::PRECISION_DAY,
902
				TimeValue::CALENDAR_GREGORIAN
903
			) ],
904
			'wikibase-entityid' => [ new EntityIdValue( new ItemId( 'Q13' ) ) ],
905
		];
906
	}
907
908
	/**
909
	 * @dataProvider dataValueProvider
910
	 */
911
	public function testDataValueSerializationDeserializationRoundtrip( DataValue $expected ) {
912
		$service = $this->getDataValueFactory();
913
		$deserialized = $service->newFromArray( $expected->toArray() );
914
915
		$this->assertEquals( $expected, $deserialized );
916
	}
917
918
	public function entityIdValueSerializationProvider() {
919
		return [
920
			'legacy' => [ [
921
				'entity-type' => 'item',
922
				'numeric-id' => 13,
923
			] ],
924
			'intermediate' => [ [
925
				'entity-type' => 'item',
926
				'numeric-id' => 13,
927
				'id' => 'Q13',
928
			] ],
929
			'new' => [ [
930
				'id' => 'Q13',
931
			] ],
932
		];
933
	}
934
935
	/**
936
	 * @dataProvider entityIdValueSerializationProvider
937
	 */
938
	public function testEntityIdValueDeserialization( array $serialization ) {
939
		$service = $this->getDataValueFactory();
940
		$deserialized = $service->newFromArray( [
941
			'type' => 'wikibase-entityid',
942
			'value' => $serialization,
943
		] );
944
945
		$expected = new EntityIdValue( new ItemId( 'Q13' ) );
946
		$this->assertEquals( $expected, $deserialized );
947
	}
948
949
	public function testGetEntityTypeToRepositoryMapping() {
950
		$this->entityTypeDefinitions = $this->getEntityTypeDefinitionsWithSubentities();
951
952
		$settings = new SettingsArray( WikibaseRepo::getDefaultInstance()->getSettings()->getArrayCopy() );
953
954
		$wikibaseRepo = new WikibaseRepo(
955
			$settings,
956
			new DataTypeDefinitions( [] ),
957
			$this->entityTypeDefinitions,
958
			new EntitySourceDefinitions( [
959
				new EntitySource(
960
					'local',
961
					false,
962
					[
963
						'foo' => [ 'namespaceId' => 200, 'slot' => 'main' ],
964
						'bar' => [ 'namespaceId' => 220, 'slot' => 'main' ],
965
					],
966
					'',
967
					'',
968
					'',
969
					''
970
				),
971
				new EntitySource(
972
					'lexemewiki',
973
					'bazdb',
974
					[
975
						'lexeme' => [ 'namespaceId' => 280, 'slot' => 'main' ],
976
					],
977
					'',
978
					'lex',
979
					'lex',
980
					'lexwiki'
981
				)
982
			], $this->entityTypeDefinitions )
983
		);
984
985
		$this->assertEquals(
986
			[
987
				'foo' => [ '' ],
988
				'bar' => [ '' ],
989
				'lexeme' => [ '' ],
990
				'form' => [ '' ],
991
			],
992
			$wikibaseRepo->getEntityTypeToRepositoryMapping()
993
		);
994
	}
995
996
	public function testGetConceptBaseUris() {
997
		$settings = new SettingsArray( WikibaseRepo::getDefaultInstance()->getSettings()->getArrayCopy() );
998
999
		$wikibaseRepo = new WikibaseRepo(
1000
			$settings,
1001
			new DataTypeDefinitions( [] ),
1002
			$this->entityTypeDefinitions,
1003
			new EntitySourceDefinitions( [
1004
				new EntitySource(
1005
					'local',
1006
					false,
1007
					[
1008
						'foo' => [ 'namespaceId' => 200, 'slot' => 'main' ],
1009
						'bar' => [ 'namespaceId' => 220, 'slot' => 'main' ],
1010
					],
1011
					'http://local.wiki/entity/',
1012
					'',
1013
					'',
1014
					''
1015
				),
1016
				new EntitySource(
1017
					'bazwiki',
1018
					'bazdb',
1019
					[
1020
						'baz' => [ 'namespaceId' => 250, 'slot' => 'main' ],
1021
					],
1022
					'http://baz.wiki/entity/',
1023
					'baz',
1024
					'baz',
1025
					'bazwiki'
1026
				)
1027
			], $this->entityTypeDefinitions )
1028
		);
1029
1030
		$this->assertEquals(
1031
			[ 'local' => 'http://local.wiki/entity/', 'bazwiki' => 'http://baz.wiki/entity/' ],
1032
			$wikibaseRepo->getConceptBaseUris()
1033
		);
1034
	}
1035
1036
	public function testParameterLessFunctionCalls() {
1037
		// Make sure (as good as we can) that all functions can be called without
1038
		// exceptions/ fatals and nothing accesses the database or does http requests.
1039
		$wbRepo = $this->getWikibaseRepo();
1040
1041
		$reflectionClass = new ReflectionClass( $wbRepo );
1042
		$publicMethods = $reflectionClass->getMethods( ReflectionMethod::IS_PUBLIC );
1043
		$federatedPropertyMethods = $this->getFederatedPropertyMethodNames();
1044
1045
		foreach ( $publicMethods as $publicMethod ) {
1046
			if ( in_array( $publicMethod->name, $federatedPropertyMethods ) ) {
1047
				// These methods always throw an exception if the feature is disabled
1048
				// These methods are checked in testParameterLessFunctionCallsForFederatedProperties
1049
				continue;
1050
			}
1051
			$this->invokeMethodIfNoRequiredParameters( $wbRepo, $publicMethod );
1052
		}
1053
	}
1054
1055
	public function testNewFederatedPropertiesServiceFactoryDoesntFatal() {
1056
		// Make sure (as good as we can) that all functions can be called without
1057
		// exceptions/ fatals and nothing accesses the database or does http requests.
1058
		$settings = $this->getSettingsCopyWithSettingSet( 'federatedPropertiesEnabled', true );
1059
		$wbRepo = $this->getWikibaseRepoWithCustomSettings( $settings );
1060
1061
		$wbRepo->newFederatedPropertiesServiceFactory();
1062
		$this->addToAssertionCount( 1 );
1063
	}
1064
1065
	public function provideParameterLessFunctionCallsForFederatedPropertiesThrowExceptionWhenDisabled() {
1066
		$methods = $this->getFederatedPropertyMethodNames();
1067
		return array_map(
1068
			function( $a ) {
1069
				return [ $a ];
1070
			},
1071
			$methods
1072
		);
1073
	}
1074
1075
	/**
1076
	 * @dataProvider provideParameterLessFunctionCallsForFederatedPropertiesThrowExceptionWhenDisabled
1077
	 */
1078
	public function testParameterLessFunctionCallsForFederatedPropertiesThrowExceptionWhenDisabled( $methodName ) {
1079
		// Make sure (as good as we can) that all functions can be called without
1080
		// exceptions/ fatals and nothing accesses the database or does http requests.
1081
		$settings = $this->getSettingsCopyWithSettingSet( 'federatedPropertiesEnabled', false );
1082
		$wbRepo = $this->getWikibaseRepoWithCustomSettings( $settings );
1083
1084
		$reflectionClass = new ReflectionClass( $wbRepo );
1085
1086
		$this->expectException( LogicException::class );
1087
		$this->invokeMethodIfNoRequiredParameters( $wbRepo, $reflectionClass->getMethod( $methodName ) );
1088
	}
1089
1090
	private function invokeMethodIfNoRequiredParameters( $wbRepo, $method ) {
1091
		if ( $method->getNumberOfRequiredParameters() === 0 ) {
1092
			$method->invoke( $wbRepo );
1093
		}
1094
	}
1095
1096
	private function getWikibaseRepoWithCustomSettings( SettingsArray $settings ) {
1097
		return new WikibaseRepo(
1098
			$settings,
1099
			new DataTypeDefinitions( [] ),
1100
			$this->entityTypeDefinitions,
1101
			$this->getEntitySourceDefinitions( 'local' )
1102
		);
1103
	}
1104
1105
	private function getSettingsCopyWithSettingSet( $settingName, $settingValue ) {
1106
		$settings = new SettingsArray( WikibaseRepo::getDefaultInstance()->getSettings()->getArrayCopy() );
1107
		$settings->setSetting( $settingName, $settingValue );
0 ignored issues
show
Unused Code introduced by
The call to the method Wikibase\Lib\SettingsArray::setSetting() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
1108
		return $settings;
1109
	}
1110
1111
	public function testGetPropertyTermStoreWriter_withLocalProperties() {
1112
		$repo = $this->getWikibaseRepo();
1113
		$writer = $repo->getPropertyTermStoreWriter();
1114
		$this->assertNotInstanceOf( ThrowingEntityTermStoreWriter::class, $writer );
1115
	}
1116
1117
	public function testGetPropertyTermStoreWriter_withoutLocalProperties() {
1118
		$repo = $this->getWikibaseRepoWithCustomEntitySourceDefinitions(
1119
			new EntitySourceDefinitions(
1120
				[
1121
					new EntitySource(
1122
						'test',
1123
						false,
1124
						[ 'item' => [ 'namespaceId' => 100, 'slot' => 'main' ] ],
1125
						'',
1126
						'',
1127
						'',
1128
						''
1129
					),
1130
				],
1131
				$this->entityTypeDefinitions
1132
			)
1133
		);
1134
		$writer = $repo->getPropertyTermStoreWriter();
1135
		$this->assertInstanceOf( ThrowingEntityTermStoreWriter::class, $writer );
1136
	}
1137
1138
	public function testGetItemTermStoreWriter_withLocalItems() {
1139
		$repo = $this->getWikibaseRepo();
1140
		$writer = $repo->getItemTermStoreWriter();
1141
		$this->assertNotInstanceOf( ThrowingEntityTermStoreWriter::class, $writer );
1142
	}
1143
1144
	public function testGetItemTermStoreWriter_withoutLocalItems() {
1145
		$repo = $this->getWikibaseRepoWithCustomEntitySourceDefinitions(
1146
			new EntitySourceDefinitions(
1147
				[
1148
					new EntitySource(
1149
						'test',
1150
						false,
1151
						[ 'property' => [ 'namespaceId' => 200, 'slot' => 'main' ] ],
1152
						'',
1153
						'',
1154
						'',
1155
						''
1156
					),
1157
				],
1158
				$this->entityTypeDefinitions
1159
			)
1160
		);
1161
		$writer = $repo->getItemTermStoreWriter();
1162
		$this->assertInstanceOf( ThrowingEntityTermStoreWriter::class, $writer );
1163
	}
1164
1165
	public function entitySourceBasedFederationProvider() {
1166
		return [
1167
			[ true ],
1168
			[ false ],
1169
		];
1170
	}
1171
1172
	/**
1173
	 * @dataProvider entitySourceBasedFederationProvider
1174
	 */
1175
	public function testWikibaseServicesParameterLessFunctionCalls( $entitySourceBasedFederation ) {
1176
		$settings = new SettingsArray( WikibaseRepo::getDefaultInstance()->getSettings()->getArrayCopy() );
1177
		$settings->setSetting(
0 ignored issues
show
Unused Code introduced by
The call to the method Wikibase\Lib\SettingsArray::setSetting() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
1178
			'repositories',
1179
			[ '' => [
1180
				'database' => 'dummy',
1181
				'base-uri' => null,
1182
				'prefix-mapping' => [ '' => '' ],
1183
				'entity-namespaces' => $settings->getSetting( 'entityNamespaces' ),
1184
			] ]
1185
		);
1186
		$settings->setSetting( 'useEntitySourceBasedFederation', $entitySourceBasedFederation );
0 ignored issues
show
Unused Code introduced by
The call to the method Wikibase\Lib\SettingsArray::setSetting() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
1187
1188
		$wikibaseRepo = new WikibaseRepo(
1189
			$settings,
1190
			new DataTypeDefinitions( [] ),
1191
			$this->entityTypeDefinitions,
1192
			$this->getEntitySourceDefinitions()
1193
		);
1194
1195
		// Make sure (as good as we can) that all functions can be called without
1196
		// exceptions/ fatals and nothing accesses the database or does http requests.
1197
		$wbRepoServices = $wikibaseRepo->getWikibaseServices();
1198
1199
		$reflectionClass = new ReflectionClass( $wbRepoServices );
1200
		$publicMethods = $reflectionClass->getMethods( ReflectionMethod::IS_PUBLIC );
1201
1202
		foreach ( $publicMethods as $publicMethod ) {
1203
			if ( $publicMethod->getNumberOfRequiredParameters() === 0 ) {
1204
				$publicMethod->invoke( $wbRepoServices );
1205
			}
1206
		}
1207
	}
1208
1209
	public function testLinkTargetEntityIdLookup() {
1210
		$this->assertInstanceOf(
1211
			LinkTargetEntityIdLookup::class,
1212
			$this->getWikibaseRepo()->getLinkTargetEntityIdLookup()
1213
		);
1214
	}
1215
1216
	/**
1217
	 * These methods should throw a Runtime exception when called without enabling the feature.
1218
	 * @return string[]
1219
	 */
1220
	private function getFederatedPropertyMethodNames() {
1221
		return [
1222
			'newFederatedPropertiesServiceFactory'
1223
		];
1224
	}
1225
1226
	public function testGetEntitySourceDefinitionsFromSettingsParsesSettings() {
1227
		$settingsArray = [
1228
			'federatedPropertiesEnabled' => false,
1229
			'federatedPropertiesSourceScriptUrl' => 'https://www.wikidata.org/w/',
1230
			'localEntitySourceName' => 'local',
1231
			'entitySources' =>
1232
				[
1233
					'local' => [
1234
						'entityNamespaces' => [ 'item' => 100, 'property' => 200 ],
1235
						'repoDatabase' => false,
1236
						'baseUri' => 'http://example.com/entity/',
1237
						'rdfNodeNamespacePrefix' => 'wd',
1238
						'rdfPredicateNamespacePrefix' => 'wdt',
1239
						'interwikiPrefix' => 'localwiki'
1240
					]
1241
				]
1242
1243
		];
1244
		$settings = new SettingsArray( $settingsArray );
1245
		$wrapper = TestingAccessWrapper::newFromClass( WikibaseRepo::class );
1246
		$sourceDefinitions = $wrapper->getEntitySourceDefinitionsFromSettings( $settings, $this->entityTypeDefinitions );
1247
1248
		if ( $sourceDefinitions instanceof EntitySourceDefinitions ) {
1249
1250
			$itemSource = $sourceDefinitions->getSourceForEntityType( 'item' );
1251
1252
			$this->assertSame( 'local', $itemSource->getSourceName() );
1253
			$this->assertSame( 'http://example.com/entity/', $itemSource->getConceptBaseUri() );
1254
			$this->assertSame( 'wdt', $itemSource->getRdfPredicateNamespacePrefix() );
1255
			$this->assertSame( 'wd', $itemSource->getRdfNodeNamespacePrefix() );
1256
			$this->assertSame( 'localwiki', $itemSource->getInterwikiPrefix() );
1257
			$this->assertSame( [ 'item' => 100, 'property' => 200 ], $itemSource->getEntityNamespaceIds() );
1258
			$this->assertSame( [ 'item' => 'main', 'property' => 'main' ], $itemSource->getEntitySlotNames() );
1259
			$this->assertSame( [ 'item', 'property' ], $itemSource->getEntityTypes() );
1260
		}
1261
	}
1262
1263
	public function testGetEntitySourceDefinitionsFromSettingsInitializesFederatedPropertiesDefaults() {
1264
		$settingsArray = [
1265
			'federatedPropertiesEnabled' => true,
1266
			'federatedPropertiesSourceScriptUrl' => 'https://www.wikidata.org/w/',
1267
			'localEntitySourceName' => 'local',
1268
			'entityNamespaces' => [ 'item' => 120, 'property' => 122 ],
1269
			'changesDatabase' => false,
1270
			'conceptBaseUri' => 'http://localhost/entity/',
1271
			'foreignRepositories' => []
1272
		];
1273
		$settings = new SettingsArray( $settingsArray );
1274
		$wrapper = TestingAccessWrapper::newFromClass( WikibaseRepo::class );
1275
		$sourceDefinitions = $wrapper->getEntitySourceDefinitionsFromSettings( $settings, $this->entityTypeDefinitions );
1276
1277
		if ( $sourceDefinitions instanceof EntitySourceDefinitions ) {
1278
1279
			$itemSource = $sourceDefinitions->getSourceForEntityType( 'item' );
1280
1281
			$this->assertSame( 'local', $itemSource->getSourceName() );
1282
			$this->assertSame( 'http://localhost/entity/', $itemSource->getConceptBaseUri() );
1283
			$this->assertSame( '', $itemSource->getRdfPredicateNamespacePrefix() );
1284
			$this->assertSame( 'wd', $itemSource->getRdfNodeNamespacePrefix() );
1285
			$this->assertSame( '', $itemSource->getInterwikiPrefix() );
1286
			$this->assertSame( [ 'item' => 120 ], $itemSource->getEntityNamespaceIds() );
1287
			$this->assertSame( [ 'item' => 'main' ], $itemSource->getEntitySlotNames() );
1288
			$this->assertSame( [ 'item' ], $itemSource->getEntityTypes() );
1289
1290
			$propertySource = $sourceDefinitions->getSourceForEntityType( 'property' );
1291
1292
			$this->assertSame( 'fedprops', $propertySource->getSourceName() );
1293
			$this->assertSame( 'http://www.wikidata.org/entity/', $propertySource->getConceptBaseUri() );
1294
			$this->assertSame( 'fpwd', $propertySource->getRdfPredicateNamespacePrefix() );
1295
			$this->assertSame( 'fpwd', $propertySource->getRdfNodeNamespacePrefix() );
1296
			$this->assertSame( 'wikidata', $propertySource->getInterwikiPrefix() );
1297
			$this->assertSame( [ 'property' => 122 ], $propertySource->getEntityNamespaceIds() ); // uses wikidata default not config
1298
			$this->assertSame( [ 'property' => 'main' ], $propertySource->getEntitySlotNames() );
1299
			$this->assertSame( [ 'property' ], $propertySource->getEntityTypes() );
1300
		}
1301
	}
1302
1303
	public function testGetEntitySourceDefinitionsFromSettingsDefaultsToLegacyParser() {
1304
		$settingsArray = [
1305
			'federatedPropertiesEnabled' => false,
1306
			'federatedPropertiesSourceScriptUrl' => 'https://www.wikidata.org/w/',
1307
			'localEntitySourceName' => 'local',
1308
			'entityNamespaces' => [ 'item' => 120, 'property' => 122 ],
1309
			'changesDatabase' => false,
1310
			'conceptBaseUri' => 'http://localhost/entity/',
1311
			'foreignRepositories' => []
1312
		];
1313
1314
		$settings = new SettingsArray( $settingsArray );
1315
		$wrapper = TestingAccessWrapper::newFromClass( WikibaseRepo::class );
1316
		$sourceDefinitions = $wrapper->getEntitySourceDefinitionsFromSettings( $settings, $this->entityTypeDefinitions );
1317
1318
		if ( $sourceDefinitions instanceof EntitySourceDefinitions ) {
1319
1320
			$itemSource = $sourceDefinitions->getSourceForEntityType( 'item' );
1321
1322
			$this->assertSame( 'local', $itemSource->getSourceName() );
1323
			$this->assertSame( 'http://localhost/entity/', $itemSource->getConceptBaseUri() );
1324
			$this->assertSame( '', $itemSource->getRdfPredicateNamespacePrefix() );
1325
			$this->assertSame( 'wd', $itemSource->getRdfNodeNamespacePrefix() );
1326
			$this->assertSame( '', $itemSource->getInterwikiPrefix() );
1327
			$this->assertSame( [ 'item' => 120, 'property' => 122 ], $itemSource->getEntityNamespaceIds() );
1328
			$this->assertSame( [ 'item' => 'main', 'property' => 'main' ], $itemSource->getEntitySlotNames() );
1329
			$this->assertSame( [ 'item', 'property' ], $itemSource->getEntityTypes() );
1330
		}
1331
	}
1332
1333
}
1334