Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
94.29% covered (success)
94.29%
33 / 35
85.71% covered (warning)
85.71%
12 / 14
CRAP
0.00% covered (danger)
0.00%
0 / 1
Form
94.29% covered (success)
94.29%
33 / 35
85.71% covered (warning)
85.71%
12 / 14
23.10
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setId
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 getRepresentations
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setRepresentations
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getGrammaticalFeatures
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setGrammaticalFeatures
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 getStatements
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isEmpty
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 equals
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 copy
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __clone
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 clear
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare( strict_types  = 1 );
4
5namespace Wikibase\Lexeme\Domain\Model;
6
7use LogicException;
8use Wikibase\DataModel\Entity\ClearableEntity;
9use Wikibase\DataModel\Entity\ItemId;
10use Wikibase\DataModel\Entity\StatementListProvidingEntity;
11use Wikibase\DataModel\Statement\StatementList;
12use Wikibase\DataModel\Term\TermList;
13use Wikibase\Lexeme\Domain\DummyObjects\DummyFormId;
14use Wikibase\Lexeme\Domain\DummyObjects\NullFormId;
15use Wikimedia\Assert\Assert;
16
17/**
18 * Mutable (e.g. the provided StatementList can be changed) implementation of a Lexeme's form in the
19 * lexicographical data model.
20 *
21 * @see https://www.mediawiki.org/wiki/Extension:WikibaseLexeme/Data_Model#Form
22 *
23 * @license GPL-2.0-or-later
24 */
25class Form implements StatementListProvidingEntity, ClearableEntity {
26
27    public const ENTITY_TYPE = 'form';
28
29    protected FormId $id;
30
31    protected TermList $representations;
32
33    /** @var ItemId[] */
34    protected array $grammaticalFeatures;
35
36    protected StatementList $statementList;
37
38    /**
39     * @param FormId $id
40     * @param TermList $representations
41     * @param ItemId[] $grammaticalFeatures
42     * @param StatementList|null $statementList
43     */
44    public function __construct(
45        FormId $id,
46        TermList $representations,
47        array $grammaticalFeatures,
48        ?StatementList $statementList = null
49    ) {
50        $this->id = $id;
51        $this->representations = $representations;
52        $this->setGrammaticalFeatures( $grammaticalFeatures );
53        $this->statementList = $statementList ?: new StatementList();
54    }
55
56    public function getType(): string {
57        return self::ENTITY_TYPE;
58    }
59
60    public function getId(): FormId {
61        return $this->id;
62    }
63
64    /**
65     * @param FormId $id
66     */
67    public function setId( $id ): void {
68        Assert::parameterType( FormId::class, $id, '$id' );
69
70        // all dummy FormIds are also FormIds that's why this check looks overly complicated
71        if ( !( $this->id instanceof NullFormId || $this->id instanceof DummyFormId ) ) {
72            throw new LogicException( 'Cannot override a real FormId' );
73        }
74
75        $this->id = $id;
76    }
77
78    /**
79     * The representations of the Form as list of terms.
80     *
81     * Note that in some places "representation" means just the text of a representation and the
82     * language code is called "spelling variant".
83     */
84    public function getRepresentations(): TermList {
85        return $this->representations;
86    }
87
88    public function setRepresentations( TermList $representations ): void {
89        $this->representations = $representations;
90    }
91
92    /**
93     * @return ItemId[]
94     */
95    public function getGrammaticalFeatures(): array {
96        return $this->grammaticalFeatures;
97    }
98
99    public function setGrammaticalFeatures( array $grammaticalFeatures ): void {
100        Assert::parameterElementType( ItemId::class, $grammaticalFeatures, '$grammaticalFeatures' );
101
102        $result = array_unique( $grammaticalFeatures );
103
104        usort( $result, static function ( ItemId $a, ItemId $b ) {
105            return strcmp( $a->getSerialization(), $b->getSerialization() );
106        } );
107
108        $this->grammaticalFeatures = $result;
109    }
110
111    /** @inheritDoc */
112    public function getStatements(): StatementList {
113        return $this->statementList;
114    }
115
116    public function isEmpty(): bool {
117        return $this->representations->isEmpty()
118            && $this->grammaticalFeatures === []
119            && $this->statementList->isEmpty();
120    }
121
122    /**
123     * @see EntityDocument::equals
124     *
125     * @param mixed $target
126     *
127     * @return bool True if the forms contents are equal. Does not consider the ID.
128     */
129    public function equals( $target ): bool {
130        if ( $this === $target ) {
131            return true;
132        }
133
134        return $target instanceof self
135            && $this->representations->equals( $target->representations )
136            && $this->grammaticalFeatures == $target->grammaticalFeatures
137            && $this->statementList->equals( $target->statementList );
138    }
139
140    public function copy(): self {
141        return clone $this;
142    }
143
144    /**
145     * The forms ID and grammatical features (a set of ItemIds) are immutable and don't need
146     * individual cloning.
147     */
148    public function __clone() {
149        $this->representations = clone $this->representations;
150        $this->statementList = clone $this->statementList;
151    }
152
153    /**
154     * Clears the representations, grammatical features and statements of a form.
155     * Note that this leaves the form in an insufficiently initialized state.
156     */
157    public function clear(): void {
158        $this->representations = new TermList();
159        $this->grammaticalFeatures = [];
160        $this->statementList = new StatementList();
161    }
162
163}