Passed
Push — rankClass ( 1b9cf4...7f76c7 )
by no
04:15 queued 16s
created

PropertyTest::testClear()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.7
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Wikibase\DataModel\Tests\Entity;
4
5
use InvalidArgumentException;
6
use PHPUnit_Framework_TestCase;
7
use Wikibase\DataModel\Entity\Property;
8
use Wikibase\DataModel\Entity\PropertyId;
9
use Wikibase\DataModel\Snak\PropertyNoValueSnak;
10
use Wikibase\DataModel\Snak\PropertySomeValueSnak;
11
use Wikibase\DataModel\Statement\Statement;
12
use Wikibase\DataModel\Statement\StatementList;
13
use Wikibase\DataModel\Term\AliasGroup;
14
use Wikibase\DataModel\Term\AliasGroupList;
15
use Wikibase\DataModel\Term\Fingerprint;
16
use Wikibase\DataModel\Term\Term;
17
use Wikibase\DataModel\Term\TermList;
18
19
/**
20
 * @covers \Wikibase\DataModel\Entity\Property
21
 *
22
 * @group Wikibase
23
 * @group WikibaseDataModel
24
 *
25
 * @license GPL-2.0+
26
 * @author Jeroen De Dauw < [email protected] >
27
 */
28
class PropertyTest extends PHPUnit_Framework_TestCase {
29
30
	/**
31
	 * @return Property
32
	 */
33
	private function getNewEmpty() {
34
		return Property::newFromType( 'string' );
35
	}
36
37
	public function testConstructorWithAllParameters() {
38
		$property = new Property(
39
			new PropertyId( 'P42' ),
40
			new Fingerprint(),
41
			'string',
42
			new StatementList()
43
		);
44
		$this->assertInstanceOf( Property::class, $property );
45
		$this->assertEquals( new PropertyId( 'P42' ), $property->getId() );
46
		$this->assertEquals( new Fingerprint(), $property->getFingerprint() );
47
		$this->assertSame( 'string', $property->getDataTypeId() );
48
		$this->assertEquals( new StatementList(), $property->getStatements() );
49
	}
50
51
	public function testConstructorWithMinimalParameters() {
52
		$property = new Property( null, null, '' );
53
		$this->assertInstanceOf( Property::class, $property );
54
		$this->assertNull( $property->getId() );
55
		$this->assertEquals( new Fingerprint(), $property->getFingerprint() );
56
		$this->assertSame( '', $property->getDataTypeId() );
57
		$this->assertEquals( new StatementList(), $property->getStatements() );
58
	}
59
60
	/**
61
	 * @expectedException InvalidArgumentException
62
	 */
63
	public function testGivenInvalidType_ConstructorThrowsException() {
64
		new Property( null, null, null );
65
	}
66
67
	public function testNewFromType() {
68
		$property = Property::newFromType( 'string' );
69
		$this->assertInstanceOf( Property::class, $property );
70
		$this->assertSame( 'string', $property->getDataTypeId() );
71
	}
72
73
	public function testSetAndGetDataTypeId() {
74
		$property = Property::newFromType( 'string' );
75
76
		foreach ( [ 'string', 'foobar', 'nyan', 'string' ] as $typeId ) {
77
			$property->setDataTypeId( $typeId );
78
			$this->assertSame( $typeId, $property->getDataTypeId() );
79
		}
80
	}
81
82
	protected function assertHasCorrectIdType( Property $property ) {
83
		$this->assertInstanceOf( PropertyId::class, $property->getId() );
84
	}
85
86
	public function testWhenIdSetWithPropertyId_GetIdReturnsPropertyId() {
87
		$property = Property::newFromType( 'string' );
88
		$property->setId( new PropertyId( 'P42' ) );
89
90
		$this->assertHasCorrectIdType( $property );
91
	}
92
93
	public function testPropertyWithTypeIsEmpty() {
94
		$this->assertTrue( Property::newFromType( 'string' )->isEmpty() );
95
	}
96
97
	public function testPropertyWithIdIsEmpty() {
98
		$property = Property::newFromType( 'string' );
99
		$property->setId( new PropertyId( 'P1337' ) );
100
		$this->assertTrue( $property->isEmpty() );
101
	}
102
103
	public function testPropertyWithFingerprintIsNotEmpty() {
104
		$property = Property::newFromType( 'string' );
105
		$property->setAliases( 'en', [ 'foo' ] );
106
		$this->assertFalse( $property->isEmpty() );
107
	}
108
109
	public function testGetStatementsReturnsEmptyListForEmptyProperty() {
110
		$property = Property::newFromType( 'string' );
111
112
		$this->assertEquals( new StatementList(), $property->getStatements() );
113
	}
114
115
	public function testSetAndGetStatements() {
116
		$property = Property::newFromType( 'string' );
117
118
		$statementList = $this->newNonEmptyStatementList();
119
		$property->setStatements( $statementList );
120
121
		$this->assertEquals( $statementList, $property->getStatements() );
122
	}
123
124
	private function newNonEmptyStatementList() {
125
		$statementList = new StatementList();
126
		$statementList->addNewStatement( new PropertyNoValueSnak( 42 ) );
127
		$statementList->addNewStatement( new PropertyNoValueSnak( 1337 ) );
128
129
		return $statementList;
130
	}
131
132
	public function equalsProvider() {
133
		$firstProperty = Property::newFromType( 'string' );
134
		$firstProperty->setStatements( $this->newNonEmptyStatementList() );
135
136
		$secondProperty = Property::newFromType( 'string' );
137
		$secondProperty->setStatements( $this->newNonEmptyStatementList() );
138
139
		$secondPropertyWithId = $secondProperty->copy();
140
		$secondPropertyWithId->setId( new PropertyId( 'P42' ) );
141
142
		$differentId = $secondPropertyWithId->copy();
143
		$differentId->setId( new PropertyId( 'P43' ) );
144
145
		return [
146
			[ Property::newFromType( 'string' ), Property::newFromType( 'string' ) ],
147
			[ $firstProperty, $secondProperty ],
148
			[ $secondProperty, $secondPropertyWithId ],
149
			[ $secondPropertyWithId, $differentId ],
150
		];
151
	}
152
153
	/**
154
	 * @dataProvider equalsProvider
155
	 */
156
	public function testEquals( Property $firstProperty, Property $secondProperty ) {
157
		$this->assertTrue( $firstProperty->equals( $secondProperty ) );
158
		$this->assertTrue( $secondProperty->equals( $firstProperty ) );
159
	}
160
161
	private function getBaseProperty() {
162
		$property = Property::newFromType( 'string' );
163
164
		$property->setId( new PropertyId( 'P42' ) );
165
		$property->setLabel( 'en', 'Same' );
166
		$property->setDescription( 'en', 'Same' );
167
		$property->setAliases( 'en', [ 'Same' ] );
168
		$property->setStatements( $this->newNonEmptyStatementList() );
169
170
		return $property;
171
	}
172
173
	public function notEqualsProvider() {
174
		$differentLabel = $this->getBaseProperty();
175
		$differentLabel->setLabel( 'en', 'Different' );
176
177
		$differentDescription = $this->getBaseProperty();
178
		$differentDescription->setDescription( 'en', 'Different' );
179
180
		$differentAlias = $this->getBaseProperty();
181
		$differentAlias->setAliases( 'en', [ 'Different' ] );
182
183
		$differentStatement = $this->getBaseProperty();
184
		$differentStatement->setStatements( new StatementList() );
185
186
		$property = $this->getBaseProperty();
187
188
		return [
189
			'empty' => [ $property, Property::newFromType( 'string' ) ],
190
			'label' => [ $property, $differentLabel ],
191
			'description' => [ $property, $differentDescription ],
192
			'alias' => [ $property, $differentAlias ],
193
			'dataType' => [ Property::newFromType( 'string' ), Property::newFromType( 'foo' ) ],
194
			'statement' => [ $property, $differentStatement ],
195
		];
196
	}
197
198
	/**
199
	 * @dataProvider notEqualsProvider
200
	 */
201
	public function testNotEquals( Property $firstProperty, Property $secondProperty ) {
202
		$this->assertFalse( $firstProperty->equals( $secondProperty ) );
203
		$this->assertFalse( $secondProperty->equals( $firstProperty ) );
204
	}
205
206
	public function testPropertyWithStatementsIsNotEmpty() {
207
		$property = Property::newFromType( 'string' );
208
		$property->setStatements( $this->newNonEmptyStatementList() );
209
210
		$this->assertFalse( $property->isEmpty() );
211
	}
212
213
	public function cloneProvider() {
214
		$property = new Property( new PropertyId( 'P1' ), null, 'string' );
215
		$property->setLabel( 'en', 'original' );
216
		$property->getStatements()->addNewStatement( new PropertyNoValueSnak( 1 ) );
217
218
		return [
219
			'copy' => [ $property, $property->copy() ],
220
			'native clone' => [ $property, clone $property ],
221
		];
222
	}
223
224
	/**
225
	 * @dataProvider cloneProvider
226
	 */
227
	public function testCloneIsEqualButNotIdentical( Property $original, Property $clone ) {
228
		$this->assertNotSame( $original, $clone );
229
		$this->assertTrue( $original->equals( $clone ) );
230
		$this->assertSame(
231
			$original->getId(),
232
			$clone->getId(),
233
			'id is immutable and must not be cloned'
234
		);
235
236
		// The clone must not reference the same mutable objects
237
		$this->assertNotSame( $original->getFingerprint(), $clone->getFingerprint() );
238
		$this->assertNotSame( $original->getStatements(), $clone->getStatements() );
239
		$this->assertNotSame(
240
			$original->getStatements()->getFirstStatementWithGuid( null ),
241
			$clone->getStatements()->getFirstStatementWithGuid( null )
242
		);
243
	}
244
245
	/**
246
	 * @dataProvider cloneProvider
247
	 */
248
	public function testOriginalDoesNotChangeWithClone( Property $original, Property $clone ) {
249
		$originalStatement = $original->getStatements()->getFirstStatementWithGuid( null );
250
		$clonedStatement = $clone->getStatements()->getFirstStatementWithGuid( null );
251
252
		$clone->setLabel( 'en', 'clone' );
253
		$clone->setDescription( 'en', 'clone' );
254
		$clone->setAliases( 'en', [ 'clone' ] );
255
		$clonedStatement->setGuid( 'clone' );
256
		$clonedStatement->setMainSnak( new PropertySomeValueSnak( 666 ) );
257
		$clonedStatement->setRank( Statement::RANK_DEPRECATED );
0 ignored issues
show
Deprecated Code introduced by
The constant Wikibase\DataModel\State...tement::RANK_DEPRECATED has been deprecated with message: since 4.4, use StatementRank::DEPRECATED instead.

This class constant 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 constant will be removed from the class and what other constant to use instead.

Loading history...
258
		$clonedStatement->getQualifiers()->addSnak( new PropertyNoValueSnak( 1 ) );
259
		$clonedStatement->getReferences()->addNewReference( new PropertyNoValueSnak( 1 ) );
260
261
		$this->assertSame( 'original', $original->getLabels()->getByLanguage( 'en' )->getText() );
262
		$this->assertFalse( $original->getDescriptions()->hasTermForLanguage( 'en' ) );
263
		$this->assertFalse( $original->getAliasGroups()->hasGroupForLanguage( 'en' ) );
264
		$this->assertNull( $originalStatement->getGuid() );
265
		$this->assertSame( 'novalue', $originalStatement->getMainSnak()->getType() );
266
		$this->assertSame( Statement::RANK_NORMAL, $originalStatement->getRank() );
0 ignored issues
show
Deprecated Code introduced by
The constant Wikibase\DataModel\State...\Statement::RANK_NORMAL has been deprecated with message: since 4.4, use StatementRank::NORMAL instead.

This class constant 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 constant will be removed from the class and what other constant to use instead.

Loading history...
267
		$this->assertTrue( $originalStatement->getQualifiers()->isEmpty() );
268
		$this->assertTrue( $originalStatement->getReferences()->isEmpty() );
269
	}
270
271
	// Below are tests copied from EntityTest
272
273
	public function labelProvider() {
274
		return [
275
			[ 'en', 'spam' ],
276
			[ 'en', 'spam', 'spam' ],
277
			[ 'de', 'foo bar baz' ],
278
		];
279
	}
280
281
	/**
282
	 * @dataProvider labelProvider
283
	 * @param string $languageCode
284
	 * @param string $labelText
285
	 * @param string $moarText
286
	 */
287
	public function testSetLabel( $languageCode, $labelText, $moarText = 'ohi there' ) {
288
		$entity = $this->getNewEmpty();
289
290
		$entity->setLabel( $languageCode, $labelText );
291
292
		$this->assertSame( $labelText, $entity->getFingerprint()->getLabel( $languageCode )->getText() );
293
294
		$entity->setLabel( $languageCode, $moarText );
295
296
		$this->assertSame( $moarText, $entity->getFingerprint()->getLabel( $languageCode )->getText() );
297
	}
298
299
	public function descriptionProvider() {
300
		return [
301
			[ 'en', 'spam' ],
302
			[ 'en', 'spam', 'spam' ],
303
			[ 'de', 'foo bar baz' ],
304
		];
305
	}
306
307
	/**
308
	 * @dataProvider descriptionProvider
309
	 * @param string $languageCode
310
	 * @param string $description
311
	 * @param string $moarText
312
	 */
313
	public function testSetDescription( $languageCode, $description, $moarText = 'ohi there' ) {
314
		$entity = $this->getNewEmpty();
315
316
		$entity->setDescription( $languageCode, $description );
317
318
		$this->assertSame( $description, $entity->getFingerprint()->getDescription( $languageCode )->getText() );
319
320
		$entity->setDescription( $languageCode, $moarText );
321
322
		$this->assertSame( $moarText, $entity->getFingerprint()->getDescription( $languageCode )->getText() );
323
	}
324
325
	public function aliasesProvider() {
326
		return [
327
			[ [
328
				'en' => [ [ 'spam' ] ],
329
			] ],
330
			[ [
331
				'en' => [ [ 'foo', 'bar', 'baz' ] ],
332
			] ],
333
			[ [
334
				'en' => [ [ 'foo', 'bar' ], [ 'baz', 'spam' ] ],
335
			] ],
336
			[ [
337
				'en' => [ [ 'foo', 'bar', 'baz' ] ],
338
				'de' => [ [ 'foobar' ], [ 'baz' ] ],
339
			] ],
340
			// with duplicates
341
			[ [
342
				'en' => [ [ 'spam', 'ham', 'ham' ] ],
343
			] ],
344
			[ [
345
				'en' => [ [ 'foo', 'bar' ], [ 'bar', 'spam' ] ],
346
			] ],
347
		];
348
	}
349
350
	/**
351
	 * @dataProvider aliasesProvider
352
	 */
353
	public function testSetAliases( array $aliasesLists ) {
354
		$entity = $this->getNewEmpty();
355
356
		foreach ( $aliasesLists as $langCode => $aliasesList ) {
357
			foreach ( $aliasesList as $aliases ) {
358
				$entity->setAliases( $langCode, $aliases );
359
			}
360
		}
361
362
		foreach ( $aliasesLists as $langCode => $aliasesList ) {
363
			$expected = array_values( array_unique( array_pop( $aliasesList ) ) );
364
			$actual = $entity->getFingerprint()->getAliasGroup( $langCode )->getAliases();
365
			$this->assertSame( $expected, $actual );
366
		}
367
	}
368
369
	public function testSetEmptyAlias() {
370
		$property = Property::newFromType( 'string' );
371
372
		$property->setAliases( 'en', [ 'wind', 'air', '', 'fire' ] );
373
		$this->assertSame(
374
			[ 'wind', 'air', 'fire' ],
375
			$property->getAliasGroups()->getByLanguage( 'en' )->getAliases()
376
		);
377
378
		$property->setAliases( 'en', [ '', '' ] );
379
		$this->assertFalse( $property->getAliasGroups()->hasGroupForLanguage( 'en' ) );
380
	}
381
382
	public function instanceProvider() {
383
		$entities = [];
384
385
		// empty
386
		$entity = $this->getNewEmpty();
387
		$entities[] = $entity;
388
389
		// ID only
390
		$entity = clone $entity;
391
		$entity->setId( new PropertyId( 'P44' ) );
392
393
		$entities[] = $entity;
394
395
		// with labels and stuff
396
		$entity = $this->getNewEmpty();
397
		$entity->setAliases( 'en', [ 'o', 'noez' ] );
398
		$entity->setLabel( 'de', 'spam' );
399
		$entity->setDescription( 'en', 'foo bar baz' );
400
401
		$entities[] = $entity;
402
403
		// with labels etc and ID
404
		$entity = clone $entity;
405
		$entity->setId( new PropertyId( 'P42' ) );
406
407
		$entities[] = $entity;
408
409
		$argLists = [];
410
411
		foreach ( $entities as $entity ) {
412
			$argLists[] = [ $entity ];
413
		}
414
415
		return $argLists;
416
	}
417
418
	/**
419
	 * @dataProvider instanceProvider
420
	 * @param Property $entity
421
	 */
422
	public function testCopy( Property $entity ) {
423
		$copy = $entity->copy();
424
425
		// The equality method alone is not enough since it does not check the IDs.
426
		$this->assertTrue( $entity->equals( $copy ) );
427
		$this->assertEquals( $entity->getId(), $copy->getId() );
428
429
		$this->assertNotSame( $entity, $copy );
430
	}
431
432
	public function testCopyRetainsLabels() {
433
		$property = Property::newFromType( 'string' );
434
435
		$property->getFingerprint()->setLabel( 'en', 'foo' );
436
		$property->getFingerprint()->setLabel( 'de', 'bar' );
437
438
		$newProperty = $property->copy();
439
440
		$this->assertTrue( $newProperty->getFingerprint()->getLabels()->hasTermForLanguage( 'en' ) );
441
		$this->assertTrue( $newProperty->getFingerprint()->getLabels()->hasTermForLanguage( 'de' ) );
442
	}
443
444
	/**
445
	 * @dataProvider instanceProvider
446
	 * @param Property $entity
447
	 */
448
	public function testSerialize( Property $entity ) {
449
		$string = serialize( $entity );
450
451
		$this->assertInternalType( 'string', $string );
452
453
		$instance = unserialize( $string );
454
455
		$this->assertTrue( $entity->equals( $instance ) );
456
		$this->assertEquals( $entity->getId(), $instance->getId() );
457
	}
458
459
	public function testWhenNoStuffIsSet_getFingerprintReturnsEmptyFingerprint() {
460
		$entity = $this->getNewEmpty();
461
462
		$this->assertEquals(
463
			new Fingerprint(),
464
			$entity->getFingerprint()
465
		);
466
	}
467
468
	public function testWhenLabelsAreSet_getFingerprintReturnsFingerprintWithLabels() {
469
		$entity = $this->getNewEmpty();
470
471
		$entity->setLabel( 'en', 'foo' );
472
		$entity->setLabel( 'de', 'bar' );
473
474
		$this->assertEquals(
475
			new Fingerprint(
476
				new TermList( [
477
					new Term( 'en', 'foo' ),
478
					new Term( 'de', 'bar' ),
479
				] )
480
			),
481
			$entity->getFingerprint()
482
		);
483
	}
484
485
	public function testWhenTermsAreSet_getFingerprintReturnsFingerprintWithTerms() {
486
		$entity = $this->getNewEmpty();
487
488
		$entity->setLabel( 'en', 'foo' );
489
		$entity->setDescription( 'en', 'foo bar' );
490
		$entity->setAliases( 'en', [ 'foo', 'bar' ] );
491
492
		$this->assertEquals(
493
			new Fingerprint(
494
				new TermList( [
495
					new Term( 'en', 'foo' ),
496
				] ),
497
				new TermList( [
498
					new Term( 'en', 'foo bar' )
499
				] ),
500
				new AliasGroupList( [
501
					new AliasGroup( 'en', [ 'foo', 'bar' ] )
502
				] )
503
			),
504
			$entity->getFingerprint()
505
		);
506
	}
507
508
	public function testGivenEmptyFingerprint_noTermsAreSet() {
509
		$entity = $this->getNewEmpty();
510
		$entity->setFingerprint( new Fingerprint() );
511
512
		$this->assertTrue( $entity->getFingerprint()->isEmpty() );
513
	}
514
515
	public function testGivenEmptyFingerprint_existingTermsAreRemoved() {
516
		$entity = $this->getNewEmpty();
517
518
		$entity->setLabel( 'en', 'foo' );
519
		$entity->setDescription( 'en', 'foo bar' );
520
		$entity->setAliases( 'en', [ 'foo', 'bar' ] );
521
522
		$entity->setFingerprint( new Fingerprint() );
523
524
		$this->assertTrue( $entity->getFingerprint()->isEmpty() );
525
	}
526
527
	public function testWhenSettingFingerprint_getFingerprintReturnsIt() {
528
		$fingerprint = new Fingerprint(
529
			new TermList( [
530
				new Term( 'en', 'english label' ),
531
			] ),
532
			new TermList( [
533
				new Term( 'en', 'english description' )
534
			] ),
535
			new AliasGroupList( [
536
				new AliasGroup( 'en', [ 'first en alias', 'second en alias' ] )
537
			] )
538
		);
539
540
		$entity = $this->getNewEmpty();
541
		$entity->setFingerprint( $fingerprint );
542
		$newFingerprint = $entity->getFingerprint();
543
544
		$this->assertSame( $fingerprint, $newFingerprint );
545
	}
546
547
	public function testGetLabels() {
548
		$property = Property::newFromType( 'string' );
549
		$property->setLabel( 'en', 'foo' );
550
551
		$this->assertEquals(
552
			new TermList( [
553
				new Term( 'en', 'foo' )
554
			] ),
555
			$property->getLabels()
556
		);
557
	}
558
559
	public function testGetDescriptions() {
560
		$property = Property::newFromType( 'string' );
561
		$property->setDescription( 'en', 'foo bar' );
562
563
		$this->assertEquals(
564
			new TermList( [
565
				new Term( 'en', 'foo bar' )
566
			] ),
567
			$property->getDescriptions()
568
		);
569
	}
570
571
	public function testGetAliasGroups() {
572
		$property = Property::newFromType( 'string' );
573
		$property->setAliases( 'en', [ 'foo', 'bar' ] );
574
575
		$this->assertEquals(
576
			new AliasGroupList( [
577
				new AliasGroup( 'en', [ 'foo', 'bar' ] )
578
			] ),
579
			$property->getAliasGroups()
580
		);
581
	}
582
583
	public function testGetLabels_sameListAsFingerprint() {
584
		$property = Property::newFromType( 'string' );
585
586
		$this->assertSame(
587
			$property->getFingerprint()->getLabels(),
588
			$property->getLabels()
589
		);
590
	}
591
592
	public function testGetDescriptions_sameListAsFingerprint() {
593
		$property = Property::newFromType( 'string' );
594
595
		$this->assertSame(
596
			$property->getFingerprint()->getDescriptions(),
597
			$property->getDescriptions()
598
		);
599
	}
600
601
	public function testGetAliasGroups_sameListAsFingerprint() {
602
		$property = Property::newFromType( 'string' );
603
604
		$this->assertSame(
605
			$property->getFingerprint()->getAliasGroups(),
606
			$property->getAliasGroups()
607
		);
608
	}
609
610
	/**
611
	 * @dataProvider clearableProvider
612
	 */
613
	public function testClear( Property $property ) {
614
		$clone = $property->copy();
615
616
		$property->clear();
617
618
		$this->assertEquals(
619
			$clone->getId(),
620
			$property->getId(),
621
			'cleared Property should keep its id'
622
		);
623
		$this->assertEquals(
624
			$clone->getDataTypeId(),
625
			$property->getDataTypeId(),
626
			'cleared Property should keep its data type'
627
		);
628
		$this->assertTrue( $property->isEmpty(), 'cleared Property should be empty' );
629
	}
630
631
	public function clearableProvider() {
632
		return [
633
			'empty' => [
634
				new Property( new PropertyId( 'P123' ), null, 'string' ),
635
			],
636
			'with fingerprint' => [
637
				new Property(
638
					new PropertyId( 'P321' ),
639
					new Fingerprint( new TermList( [ new Term( 'en', 'foo' ) ] ) ),
640
					'time'
641
				),
642
			],
643
			'with statement' => [
644
				new Property(
645
					new PropertyId( 'P234' ),
646
					null,
647
					'wikibase-entityid',
648
					$this->newNonEmptyStatementList()
649
				)
650
			],
651
		];
652
	}
653
654
}
655