Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.00% covered (success)
96.00%
48 / 50
87.50% covered (warning)
87.50%
14 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
FormSet
96.00% covered (success)
96.00%
48 / 50
87.50% covered (warning)
87.50%
14 / 16
27
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
3
 toArray
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 toArrayUnordered
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 sortForms
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 count
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 maxFormIdNumber
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 add
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 remove
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 put
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getById
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 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%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 isEmpty
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 equals
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
3.07
 hasFormWithId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 sameForms
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
4.07
1<?php
2
3namespace Wikibase\Lexeme\Domain\Model;
4
5use Countable;
6use Wikibase\Lexeme\Domain\Model\Exceptions\ConflictException;
7
8/**
9 * Set of Forms in which uniqueness of a Form is controlled by it's ID.
10 * Supposed to be used only inside the Lexeme class
11 *
12 * @license GPL-2.0-or-later
13 */
14class FormSet implements Countable {
15
16    /**
17     * @var Form[] indexed by serialization of FormId
18     */
19    private $forms = [];
20
21    /**
22     * @param Form[] $forms
23     */
24    public function __construct( array $forms = [] ) {
25        foreach ( $forms as $form ) {
26            if ( !$form instanceof Form ) {
27                throw new \InvalidArgumentException( '$forms must be an array of Forms' );
28            }
29
30            $this->add( $form );
31        }
32    }
33
34    /**
35     * @return Form[]
36     */
37    public function toArray() {
38        $forms = $this->sortForms( $this->forms );
39        return array_values( $forms );
40    }
41
42    /**
43     * Return the individual Forms in arbitrary order.
44     *
45     * Only use this method if the order is certainly insignificant,
46     * e.g. because the Forms will be summarized or reduced in some way.
47     * Otherwise, use {@link toArray()}.
48     *
49     * @return Form[]
50     */
51    public function toArrayUnordered(): array {
52        return array_values( $this->forms );
53    }
54
55    /**
56     * @param Form[] $forms
57     * @return array sorted array mapping numeric id to the form
58     */
59    private function sortForms( array $forms ) {
60        $sortedForms = [];
61        foreach ( $forms as $form ) {
62            $formIdPart = explode( '-', $form->getId()->getSerialization(), 2 )[1];
63            $formIdNumber = (int)substr( $formIdPart, 1 );
64            $sortedForms[$formIdNumber] = $form;
65        }
66        ksort( $sortedForms );
67
68        return $sortedForms;
69    }
70
71    /**
72     * @return int
73     */
74    public function count(): int {
75        return count( $this->forms );
76    }
77
78    /**
79     * @return int
80     */
81    public function maxFormIdNumber() {
82        if ( !$this->forms ) {
83            return 0;
84        }
85
86        $numbers = array_map( static function ( $formId ) {
87            [ , $formId ] = explode( '-', $formId, 2 );
88            return (int)substr( $formId, 1 );
89        }, array_keys( $this->forms ) );
90        return max( $numbers );
91    }
92
93    public function add( Form $form ) {
94        $formId = $form->getId()->getSerialization();
95        if ( isset( $this->forms[$formId] ) ) {
96            throw new ConflictException(
97                'At least two forms with the same ID were provided: `' . $formId . '`'
98            );
99        }
100
101        $this->forms[$formId] = $form;
102    }
103
104    public function remove( FormId $formId ) {
105        unset( $this->forms[$formId->getSerialization()] );
106    }
107
108    /**
109     * Replace the form identified by $form->getId() with the given one or add it
110     *
111     * @param Form $form
112     */
113    public function put( Form $form ) {
114        $this->remove( $form->getId() );
115        $this->add( $form );
116    }
117
118    /**
119     * @param FormId $formId
120     *
121     * @return Form|null
122     */
123    public function getById( FormId $formId ) {
124        return $this->forms[$formId->getSerialization()] ?? null;
125    }
126
127    /**
128     * @return self
129     */
130    public function copy() {
131        return clone $this;
132    }
133
134    /**
135     * @see http://php.net/manual/en/language.oop5.cloning.php
136     */
137    public function __clone() {
138        $clonedForms = [];
139        foreach ( $this->forms as $key => $form ) {
140            $clonedForms[$key] = clone $form;
141        }
142        $this->forms = $clonedForms;
143    }
144
145    /**
146     * @return bool
147     */
148    public function isEmpty() {
149        return !$this->forms;
150    }
151
152    public function equals( $other ) {
153        if ( $this === $other ) {
154            return true;
155        }
156
157        if ( !( $other instanceof self ) ) {
158            return false;
159        }
160
161        return $this->sameForms( $other );
162    }
163
164    /**
165     * @param FormId $formId
166     * @return bool
167     */
168    public function hasFormWithId( FormId $formId ) {
169        return $this->getById( $formId ) !== null;
170    }
171
172    /**
173     * @return bool
174     */
175    private function sameForms( FormSet $other ) {
176        if ( $this->count() !== $other->count() ) {
177            return false;
178        }
179
180        foreach ( $this->forms as $form ) {
181            if ( !$form->equals( $other->getById( $form->getId() ) ) ) {
182                return false;
183            }
184        }
185
186        return true;
187    }
188
189}