Passed
Push — deepCloning ( b0de0a )
by no
03:44
created

ItemTest::testClone()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 39
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 39
rs 8.8571
nc 1
cc 1
eloc 30
nop 0
1
<?php
2
3
namespace Wikibase\DataModel\Tests\Entity;
4
5
use Wikibase\DataModel\Entity\Item;
6
use Wikibase\DataModel\Entity\ItemId;
7
use Wikibase\DataModel\Entity\PropertyId;
8
use Wikibase\DataModel\SiteLink;
9
use Wikibase\DataModel\SiteLinkList;
10
use Wikibase\DataModel\Snak\PropertyNoValueSnak;
11
use Wikibase\DataModel\Statement\Statement;
12
use Wikibase\DataModel\Statement\StatementList;
13
use Wikibase\DataModel\Term\Fingerprint;
14
15
/**
16
 * @covers Wikibase\DataModel\Entity\Item
17
 * @covers Wikibase\DataModel\Entity\Entity
18
 *
19
 * Some tests for this class are located in ItemMultilangTextsTest,
20
 * ItemNewEmptyTest and ItemNewFromArrayTest.
21
 *
22
 * @since 0.1
23
 *
24
 * @group Wikibase
25
 * @group WikibaseItem
26
 * @group WikibaseDataModel
27
 * @group WikibaseItemTest
28
 *
29
 * @licence GNU GPL v2+
30
 * @author Jeroen De Dauw < [email protected] >
31
 * @author John Erling Blad < [email protected] >
32
 * @author Michał Łazowik
33
 */
34
class ItemTest extends EntityTest {
0 ignored issues
show
Deprecated Code introduced by
The class Wikibase\DataModel\Tests\Entity\EntityTest has been deprecated with message: This test class is to be phased out, and should not be used from outside of the component!

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
35
36
	/**
37
	 * @see EntityTest::getNewEmpty
38
	 *
39
	 * @since 0.1
40
	 *
41
	 * @return Item
42
	 */
43
	protected function getNewEmpty() {
44
		return new Item();
45
	}
46
47
	public function testGetId() {
48
		$item = new Item();
49
		$this->assertNull( $item->getId() );
50
51
		$item->setId( new ItemId( 'Q1' ) );
52
		$this->assertEquals( new ItemId( 'Q1' ), $item->getId() );
53
54
		$item->setId( null );
55
		$this->assertNull( $item->getId() );
56
57
		$item = new Item( new ItemId( 'Q2' ) );
58
		$this->assertEquals( new ItemId( 'Q2' ), $item->getId() );
59
	}
60
61
	public function testSetIdUsingNumber() {
62
		$item = new Item();
63
		$item->setId( 42 );
64
		$this->assertEquals( new ItemId( 'Q42' ), $item->getId() );
65
	}
66
67
	public function itemProvider() {
68
		$items = array();
69
70
		$items[] = new Item();
71
72
		$item = new Item();
73
		$item->setDescription( 'en', 'foo' );
74
		$items[] = $item;
75
76
		$item = new Item();
77
		$item->setDescription( 'en', 'foo' );
78
		$item->setDescription( 'de', 'foo' );
79
		$item->setLabel( 'en', 'foo' );
80
		$item->setAliases( 'de', array( 'bar', 'baz' ) );
81
		$items[] = $item;
82
83
		$item = clone $item;
84
		$item->getStatements()->addNewStatement(
85
			new PropertyNoValueSnak( new PropertyId( 'P42' ) )
86
		);
87
		$items[] = $item;
88
89
		$argLists = array();
90
91
		foreach ( $items as $item ) {
92
			$argLists[] = array( $item );
93
		}
94
95
		return $argLists;
96
	}
97
98
	public function testGetSiteLinkWithNonSetSiteId() {
99
		$item = new Item();
100
101
		$this->setExpectedException( 'OutOfBoundsException' );
0 ignored issues
show
Deprecated Code introduced by
The method PHPUnit_Framework_TestCase::setExpectedException() has been deprecated with message: Method deprecated since Release 5.2.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
102
		$item->getSiteLinkList()->getBySiteId( 'enwiki' );
103
	}
104
105
	/**
106
	 * @dataProvider simpleSiteLinkProvider
107
	 */
108
	public function testAddSiteLink( SiteLink $siteLink ) {
109
		$item = new Item();
110
111
		$item->getSiteLinkList()->addSiteLink( $siteLink );
112
113
		$this->assertEquals(
114
			$siteLink,
115
			$item->getSiteLinkList()->getBySiteId( $siteLink->getSiteId() )
116
		);
117
	}
118
119
	public function simpleSiteLinkProvider() {
120
		$argLists = array();
121
122
		$argLists[] = array(
123
			new SiteLink(
124
				'enwiki',
125
				'Wikidata',
126
				array(
127
					new ItemId( 'Q42' )
128
				)
129
			)
130
		);
131
		$argLists[] = array(
132
			new SiteLink(
133
				'nlwiki',
134
				'Wikidata'
135
			)
136
		);
137
		$argLists[] = array(
138
			new SiteLink(
139
				'enwiki',
140
				'Nyan!',
141
				array(
142
					new ItemId( 'Q42' ),
143
					new ItemId( 'Q149' )
144
				)
145
			)
146
		);
147
		$argLists[] = array(
148
			new SiteLink(
149
				'foo bar',
150
				'baz bah',
151
				array(
152
					new ItemId( 'Q3' ),
153
					new ItemId( 'Q7' )
154
				)
155
			)
156
		);
157
158
		return $argLists;
159
	}
160
161
	/**
162
	 * @dataProvider simpleSiteLinksProvider
163
	 */
164
	public function testGetSiteLinks() {
165
		$siteLinks = func_get_args();
166
		$item = new Item();
167
168
		foreach ( $siteLinks as $siteLink ) {
169
			$item->getSiteLinkList()->addSiteLink( $siteLink );
170
		}
171
172
		$this->assertInternalType( 'array', $item->getSiteLinks() );
0 ignored issues
show
Deprecated Code introduced by
The method Wikibase\DataModel\Entity\Item::getSiteLinks() has been deprecated with message: since 0.8, use getSiteLinkList() instead,

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
173
		$this->assertEquals( $siteLinks, $item->getSiteLinks() );
0 ignored issues
show
Deprecated Code introduced by
The method Wikibase\DataModel\Entity\Item::getSiteLinks() has been deprecated with message: since 0.8, use getSiteLinkList() instead,

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
174
	}
175
176
	public function simpleSiteLinksProvider() {
177
		$argLists = array();
178
179
		$argLists[] = array();
180
181
		$argLists[] = array( new SiteLink( 'enwiki', 'Wikidata', array( new ItemId( 'Q42' ) ) ) );
182
183
		$argLists[] = array(
184
			new SiteLink( 'enwiki', 'Wikidata' ),
185
			new SiteLink( 'nlwiki', 'Wikidata', array( new ItemId( 'Q3' ) ) )
186
		);
187
188
		$argLists[] = array(
189
			new SiteLink( 'enwiki', 'Wikidata' ),
190
			new SiteLink( 'nlwiki', 'Wikidata' ),
191
			new SiteLink( 'foo bar', 'baz bah', array( new ItemId( 'Q2' ) ) )
192
		);
193
194
		return $argLists;
195
	}
196
197
	public function testHasLinkToSiteForFalse() {
198
		$item = new Item();
199
		$item->getSiteLinkList()->addNewSiteLink( 'ENWIKI', 'Wikidata', array( new ItemId( 'Q42' ) ) );
200
201
		$this->assertFalse( $item->getSiteLinkList()->hasLinkWithSiteId( 'enwiki' ) );
202
		$this->assertFalse( $item->getSiteLinkList()->hasLinkWithSiteId( 'dewiki' ) );
203
		$this->assertFalse( $item->getSiteLinkList()->hasLinkWithSiteId( 'foo bar' ) );
204
	}
205
206
	public function testHasLinkToSiteForTrue() {
207
		$item = new Item();
208
		$item->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Wikidata', array( new ItemId( 'Q42' ) ) );
209
		$item->getSiteLinkList()->addNewSiteLink( 'dewiki', 'Wikidata' );
210
		$item->getSiteLinkList()->addNewSiteLink( 'foo bar', 'Wikidata' );
211
212
		$this->assertTrue( $item->getSiteLinkList()->hasLinkWithSiteId( 'enwiki' ) );
213
		$this->assertTrue( $item->getSiteLinkList()->hasLinkWithSiteId( 'dewiki' ) );
214
		$this->assertTrue( $item->getSiteLinkList()->hasLinkWithSiteId( 'foo bar' ) );
215
	}
216
217
	public function testEmptyItemReturnsEmptySiteLinkList() {
218
		$item = new Item();
219
		$this->assertTrue( $item->getSiteLinkList()->isEmpty() );
220
	}
221
222
	public function testAddSiteLinkOverridesOldLinks() {
223
		$item = new Item();
224
225
		$item->getSiteLinkList()->addNewSiteLink( 'kittens', 'foo' );
226
227
		$newLink = new SiteLink( 'kittens', 'bar' );
228
		$item->addSiteLink( $newLink );
0 ignored issues
show
Deprecated Code introduced by
The method Wikibase\DataModel\Entity\Item::addSiteLink() has been deprecated with message: since 0.8, use getSiteLinkList()->addSiteLink() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
229
230
		$this->assertTrue( $item->getSiteLinkList()->getBySiteId( 'kittens' )->equals( $newLink ) );
231
	}
232
233
	public function testEmptyItemIsEmpty() {
234
		$item = new Item();
235
		$this->assertTrue( $item->isEmpty() );
236
	}
237
238
	public function testItemWithIdIsEmpty() {
239
		$item = new Item( new ItemId( 'Q1337' ) );
240
		$this->assertTrue( $item->isEmpty() );
241
	}
242
243
	public function testItemWithStuffIsNotEmpty() {
244
		$item = new Item();
245
		$item->getFingerprint()->setAliasGroup( 'en', array( 'foo' ) );
246
		$this->assertFalse( $item->isEmpty() );
247
248
		$item = new Item();
249
		$item->getSiteLinkList()->addNewSiteLink( 'en', 'o_O' );
250
		$this->assertFalse( $item->isEmpty() );
251
252
		$item = new Item();
253
		$item->getStatements()->addStatement( $this->newStatement() );
254
		$this->assertFalse( $item->isEmpty() );
255
	}
256
257
	public function testItemWithSitelinksHasSitelinks() {
258
		$item = new Item();
259
		$item->getSiteLinkList()->addNewSiteLink( 'en', 'foo' );
260
		$this->assertFalse( $item->getSiteLinkList()->isEmpty() );
261
	}
262
263
	public function testItemWithoutSitelinksHasNoSitelinks() {
264
		$item = new Item();
265
		$this->assertTrue( $item->getSiteLinkList()->isEmpty() );
266
	}
267
268
	private function newStatement() {
269
		$statement = new Statement( new PropertyNoValueSnak( 42 ) );
270
		$statement->setGuid( 'kittens' );
271
		return $statement;
272
	}
273
274
	public function testClearRemovesAllButId() {
275
		$item = new Item( new ItemId( 'Q42' ) );
276
		$item->getFingerprint()->setLabel( 'en', 'foo' );
277
		$item->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Foo' );
278
		$item->getStatements()->addStatement( $this->newStatement() );
279
280
		$item->clear();
281
282
		$this->assertEquals( new ItemId( 'Q42' ), $item->getId() );
283
		$this->assertTrue( $item->getFingerprint()->isEmpty() );
284
		$this->assertTrue( $item->getSiteLinkList()->isEmpty() );
285
		$this->assertTrue( $item->getStatements()->isEmpty() );
286
	}
287
288
	public function testEmptyConstructor() {
289
		$item = new Item();
290
291
		$this->assertNull( $item->getId() );
292
		$this->assertTrue( $item->getFingerprint()->isEmpty() );
293
		$this->assertTrue( $item->getSiteLinkList()->isEmpty() );
294
		$this->assertTrue( $item->getStatements()->isEmpty() );
295
	}
296
297
	public function testCanConstructWithStatementList() {
298
		$statement = new Statement( new PropertyNoValueSnak( 42 ) );
299
		$statement->setGuid( 'meh' );
300
301
		$statements = new StatementList( $statement );
302
303
		$item = new Item( null, null, null, $statements );
304
305
		$this->assertEquals(
306
			$statements,
307
			$item->getStatements()
308
		);
309
	}
310
311
	public function testSetStatements() {
312
		$item = new Item();
313
		$item->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) );
314
315
		$item->setStatements( new StatementList() );
316
		$this->assertTrue( $item->getStatements()->isEmpty() );
317
	}
318
319
	public function testGetStatementsReturnsCorrectTypeAfterClear() {
320
		$item = new Item();
321
		$item->clear();
322
323
		$this->assertTrue( $item->getStatements()->isEmpty() );
324
	}
325
326
	public function equalsProvider() {
327
		$firstItem = new Item();
328
		$firstItem->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) );
329
330
		$secondItem = new Item();
331
		$secondItem->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) );
332
333
		$secondItemWithId = clone $secondItem;
334
		$secondItemWithId->setId( 42 );
335
336
		$differentId = clone $secondItemWithId;
337
		$differentId->setId( 43 );
338
339
		return array(
340
			array( new Item(), new Item() ),
341
			array( $firstItem, $secondItem ),
342
			array( $secondItem, $secondItemWithId ),
343
			array( $secondItemWithId, $differentId ),
344
		);
345
	}
346
347
	/**
348
	 * @dataProvider equalsProvider
349
	 */
350
	public function testEquals( Item $firstItem, Item $secondItem ) {
351
		$this->assertTrue( $firstItem->equals( $secondItem ) );
352
		$this->assertTrue( $secondItem->equals( $firstItem ) );
353
	}
354
355
	private function getBaseItem() {
356
		$item = new Item( new ItemId( 'Q42' ) );
357
		$item->getFingerprint()->setLabel( 'en', 'Same' );
358
		$item->getFingerprint()->setDescription( 'en', 'Same' );
359
		$item->getFingerprint()->setAliasGroup( 'en', array( 'Same' ) );
360
		$item->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Same' );
361
		$item->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) );
362
363
		return $item;
364
	}
365
366
	public function notEqualsProvider() {
367
		$differentLabel = $this->getBaseItem();
368
		$differentLabel->getFingerprint()->setLabel( 'en', 'Different' );
369
370
		$differentDescription = $this->getBaseItem();
371
		$differentDescription->getFingerprint()->setDescription( 'en', 'Different' );
372
373
		$differentAlias = $this->getBaseItem();
374
		$differentAlias->getFingerprint()->setAliasGroup( 'en', array( 'Different' ) );
375
376
		$differentSiteLink = $this->getBaseItem();
377
		$differentSiteLink->getSiteLinkList()->removeLinkWithSiteId( 'enwiki' );
378
		$differentSiteLink->getSiteLinkList()->addNewSiteLink( 'enwiki', 'Different' );
379
380
		$differentStatement = $this->getBaseItem();
381
		$differentStatement->setStatements( new StatementList() );
382
		$differentStatement->getStatements()->addNewStatement( new PropertyNoValueSnak( 24 ) );
383
384
		$item = $this->getBaseItem();
385
386
		return array(
387
			'empty' => array( $item, new Item() ),
388
			'label' => array( $item, $differentLabel ),
389
			'description' => array( $item, $differentDescription ),
390
			'alias' => array( $item, $differentAlias ),
391
			'siteLink' => array( $item, $differentSiteLink ),
392
			'statement' => array( $item, $differentStatement ),
393
		);
394
	}
395
396
	/**
397
	 * @dataProvider notEqualsProvider
398
	 */
399
	public function testNotEquals( Item $firstItem, Item $secondItem ) {
400
		$this->assertFalse( $firstItem->equals( $secondItem ) );
401
		$this->assertFalse( $secondItem->equals( $firstItem ) );
402
	}
403
404
	public function testClone() {
405
		$id = new ItemId( 'Q1' );
406
		$fingerprint = new Fingerprint();
407
		$fingerprint->setLabel( 'en', 'original' );
408
		$siteLink = new SiteLink( 'enwiki', 'Original' );
409
		$siteLinks = new SiteLinkList( array( $siteLink ) );
410
		$statement = new Statement( new PropertyNoValueSnak( 1 ) );
411
		$statements = new StatementList( $statement );
412
		$original = new Item( $id, $fingerprint, $siteLinks, $statements );
413
414
		$clone = clone $original;
415
416
		// The clone must not reference the same mutable objects
417
		$this->assertSame( 'item', $clone->getType() );
418
		$this->assertSame( $id, $clone->getId(), 'id is immutable and must not be cloned' );
419
		$this->assertNotSame( $fingerprint, $clone->getFingerprint() );
420
		$this->assertNotSame( $siteLinks, $clone->getSiteLinkList() );
421
		$this->assertSame(
422
			$siteLink,
423
			$clone->getSiteLinkList()->toArray()['enwiki'],
424
			'SiteLink is immutable and must not be cloned'
425
		);
426
		$this->assertNotSame( $statements, $clone->getStatements() );
427
		$this->assertNotSame( $statement, $clone->getStatements()->toArray()[0] );
428
429
		// Modify the clone
430
		$clone->getFingerprint()->setLabel( 'en', 'clone' );
431
		$clonedStatement = $clone->getStatements()->toArray()[0];
432
		$clonedStatement->setRank( Statement::RANK_DEPRECATED );
433
		$clonedStatement->getQualifiers()->addSnak( new PropertyNoValueSnak( 1 ) );
434
		$clonedStatement->getReferences()->addNewReference( new PropertyNoValueSnak( 1 ) );
435
436
		// The original must not change
437
		$this->assertSame( 'original', $original->getFingerprint()->getLabel( 'en' )->getText() );
438
		$originalStatement = $original->getStatements()->toArray()[0];
439
		$this->assertSame( Statement::RANK_NORMAL, $originalStatement->getRank() );
440
		$this->assertTrue( $originalStatement->getQualifiers()->isEmpty() );
441
		$this->assertTrue( $originalStatement->getReferences()->isEmpty() );
442
	}
443
444
}
445