Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
97.96% |
96 / 98 |
|
71.43% |
5 / 7 |
CRAP | |
0.00% |
0 / 1 |
FormsView | |
97.96% |
96 / 98 |
|
71.43% |
5 / 7 |
11 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
getHtml | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
2 | |||
getFormHtml | |
100.00% |
27 / 27 |
|
100.00% |
1 / 1 |
1 | |||
getSortedGrammaticalFeatures | |
94.44% |
17 / 18 |
|
0.00% |
0 / 1 |
4.00 | |||
renderRepresentationWidget | |
95.65% |
22 / 23 |
|
0.00% |
0 / 1 |
1 | |||
getGrammaticalFeatureHtml | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getStatementSectionHtml | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace Wikibase\Lexeme\Presentation\View; |
4 | |
5 | use Wikibase\DataModel\Entity\ItemId; |
6 | use Wikibase\DataModel\Services\EntityId\EntityIdFormatter; |
7 | use Wikibase\DataModel\Term\Term; |
8 | use Wikibase\Lexeme\Domain\Model\Form; |
9 | use Wikibase\Lexeme\Domain\Model\FormSet; |
10 | use Wikibase\Lexeme\Presentation\View\Template\LexemeTemplateFactory; |
11 | use Wikibase\Lexeme\Presentation\View\Template\VueTemplates; |
12 | use Wikibase\Lib\Store\ItemOrderProvider; |
13 | use Wikibase\View\LocalizedTextProvider; |
14 | use Wikibase\View\StatementGroupListView; |
15 | use WMDE\VueJsTemplating\Templating; |
16 | |
17 | /** |
18 | * @license GPL-2.0-or-later |
19 | * @author Thiemo Kreuz |
20 | */ |
21 | class FormsView { |
22 | |
23 | /** |
24 | * @var LocalizedTextProvider |
25 | */ |
26 | private $textProvider; |
27 | |
28 | /** |
29 | * @var LexemeTemplateFactory |
30 | */ |
31 | private $templateFactory; |
32 | |
33 | /** |
34 | * @var EntityIdFormatter |
35 | */ |
36 | private $entityIdFormatter; |
37 | |
38 | /** |
39 | * @var StatementGroupListView |
40 | */ |
41 | private $statementGroupListView; |
42 | |
43 | /** |
44 | * @var ItemOrderProvider |
45 | */ |
46 | private $grammaticalFeaturesOrderProvider; |
47 | |
48 | public function __construct( |
49 | LocalizedTextProvider $textProvider, |
50 | LexemeTemplateFactory $templateFactory, |
51 | EntityIdFormatter $entityIdFormatter, |
52 | StatementGroupListView $statementGroupListView, |
53 | ItemOrderProvider $grammaticalFeaturesOrderProvider |
54 | ) { |
55 | $this->textProvider = $textProvider; |
56 | $this->templateFactory = $templateFactory; |
57 | $this->entityIdFormatter = $entityIdFormatter; |
58 | $this->statementGroupListView = $statementGroupListView; |
59 | $this->grammaticalFeaturesOrderProvider = $grammaticalFeaturesOrderProvider; |
60 | } |
61 | |
62 | /** |
63 | * @param FormSet $forms |
64 | * |
65 | * @return string HTML |
66 | */ |
67 | public function getHtml( FormSet $forms ) { |
68 | $html = '<div class="wikibase-lexeme-forms-section">'; |
69 | $html .= '<h2 class="wb-section-heading section-heading" id="forms">' |
70 | . htmlspecialchars( $this->textProvider->get( 'wikibaselexeme-header-forms' ) ) |
71 | . '</h2>'; |
72 | |
73 | $html .= '<div class="wikibase-lexeme-forms ">'; |
74 | foreach ( $forms->toArray() as $form ) { |
75 | $html .= $this->getFormHtml( $form ); |
76 | } |
77 | $html .= '</div>'; // wikibase-lexeme-forms |
78 | // @phan-suppress-next-line PhanPluginDuplicateAdjacentStatement |
79 | $html .= '</div>'; // wikibase-lexeme-forms-section |
80 | return $html; |
81 | } |
82 | |
83 | /** |
84 | * @param Form $form |
85 | * |
86 | * @return string HTML |
87 | */ |
88 | private function getFormHtml( Form $form ) { |
89 | $grammaticalFeaturesHtml = $this->templateFactory->render( |
90 | 'wikibase-lexeme-form-grammatical-features', |
91 | [ |
92 | htmlspecialchars( |
93 | $this->textProvider->get( 'wikibaselexeme-form-grammatical-features' ), |
94 | ENT_QUOTES, |
95 | 'UTF-8', |
96 | false |
97 | ), |
98 | implode( |
99 | // Escape HTML without double escaping entities, {@see Message::escaped} |
100 | htmlspecialchars( $this->textProvider->get( 'comma-separator' ), ENT_QUOTES, 'UTF-8', false ), |
101 | array_map( |
102 | function ( ItemId $id ) { |
103 | return '<span>' . $this->getGrammaticalFeatureHtml( $id ) . '</span>'; |
104 | }, |
105 | $this->getSortedGrammaticalFeatures( $form ) |
106 | ) |
107 | ), |
108 | ] |
109 | ); |
110 | |
111 | return $this->templateFactory->render( 'wikibase-lexeme-form', [ |
112 | htmlspecialchars( $form->getId()->getSerialization() ), |
113 | $this->renderRepresentationWidget( $form ), |
114 | $grammaticalFeaturesHtml, |
115 | $this->getStatementSectionHtml( $form ), |
116 | // Anchor separated from ID to avoid issue with front-end rendering |
117 | htmlspecialchars( $form->getId()->getIdSuffix() ), |
118 | ] ); |
119 | } |
120 | |
121 | /** |
122 | * Return a list of grammatical features by a specific order, |
123 | * decided by the list maintained in the wikipage |
124 | * MediaWiki:WikibaseLexeme-SortedGrammaticalFeatures |
125 | * |
126 | * @param Form $form |
127 | * |
128 | * @return ItemId[] |
129 | */ |
130 | private function getSortedGrammaticalFeatures( Form $form ): array { |
131 | $grammaticalFeaturesItemIds = $form->getGrammaticalFeatures(); |
132 | $grammaticalFeaturesOrder = $this->grammaticalFeaturesOrderProvider->getItemOrder(); |
133 | |
134 | if ( $grammaticalFeaturesItemIds === [] ) { |
135 | return []; |
136 | } |
137 | |
138 | $sortedGrammaticalFeatures = []; |
139 | $unsortedGrammaticalFeatures = []; |
140 | |
141 | foreach ( $grammaticalFeaturesItemIds as $grammaticalFeatureItemId ) { |
142 | $key = $grammaticalFeatureItemId->getSerialization(); |
143 | $grammaticalFeaturePosition = $grammaticalFeaturesOrder[ $key ] ?? null; |
144 | if ( $grammaticalFeaturePosition !== null ) { |
145 | $sortedGrammaticalFeatures[ $grammaticalFeaturePosition ] = $grammaticalFeatureItemId; |
146 | } else { |
147 | $unsortedGrammaticalFeatures[] = $grammaticalFeatureItemId; |
148 | } |
149 | } |
150 | ksort( $sortedGrammaticalFeatures, SORT_NUMERIC ); |
151 | // sort new grammatical features numerically |
152 | usort( $unsortedGrammaticalFeatures, static function ( ItemId $a, ItemId $b ) { |
153 | return strcmp( $a->getSerialization(), $b->getSerialization() ); |
154 | } ); |
155 | $sortedGrammaticalFeatures = array_merge( $sortedGrammaticalFeatures, $unsortedGrammaticalFeatures ); |
156 | return $sortedGrammaticalFeatures; |
157 | } |
158 | |
159 | /** |
160 | * @return string |
161 | */ |
162 | private function renderRepresentationWidget( Form $form ) { |
163 | $templating = new Templating(); |
164 | $representationsVueTemplate = file_get_contents( __DIR__ . VueTemplates::REPRESENTATIONS ); |
165 | |
166 | $representations = array_map( |
167 | static function ( Term $r ) { |
168 | return [ 'value' => $r->getText(), 'language' => $r->getLanguageCode() ]; |
169 | }, |
170 | iterator_to_array( $form->getRepresentations() ) |
171 | ); |
172 | |
173 | $result = $templating->render( |
174 | $representationsVueTemplate, |
175 | [ |
176 | 'inEditMode' => false, |
177 | 'representations' => $representations, |
178 | ], |
179 | [ |
180 | 'message' => function ( $key ) { |
181 | return $this->textProvider->get( $key ); |
182 | }, |
183 | ] |
184 | ); |
185 | |
186 | return '<div class="form-representations">' |
187 | . $result |
188 | . '</div>'; |
189 | } |
190 | |
191 | /** |
192 | * @param ItemId $id |
193 | * |
194 | * @return string HTML |
195 | */ |
196 | private function getGrammaticalFeatureHtml( ItemId $id ) { |
197 | return $this->entityIdFormatter->formatEntityId( $id ); |
198 | } |
199 | |
200 | /** |
201 | * @param Form $form |
202 | * |
203 | * @return string HTML |
204 | */ |
205 | private function getStatementSectionHtml( Form $form ) { |
206 | $headerText = htmlspecialchars( |
207 | $this->textProvider->get( |
208 | 'wikibaselexeme-statementsection-statements-about-form', |
209 | [ $form->getId()->getSerialization() ] |
210 | ) |
211 | ); |
212 | |
213 | $statementHeader = <<<HTML |
214 | <h2 class="wb-section-heading section-heading wikibase-statements" dir="auto"> |
215 | $headerText |
216 | </h2> |
217 | HTML; |
218 | |
219 | $statementSection = $this->statementGroupListView->getHtml( |
220 | $form->getStatements()->toArray(), $form->getId()->getIdSuffix() |
221 | ); |
222 | return $statementHeader . $statementSection; |
223 | } |
224 | |
225 | } |