Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
81.73% |
85 / 104 |
|
77.78% |
7 / 9 |
CRAP | |
0.00% |
0 / 1 |
LexemeView | |
81.73% |
85 / 104 |
|
77.78% |
7 / 9 |
14.03 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
1 | |||
getContent | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
getMainHtml | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
getLexemeHeader | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
2 | |||
getSideHtml | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getTitleHtml | |
5.26% |
1 / 19 |
|
0.00% |
0 / 1 |
17.60 | |||
getLocalizedMessage | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
renderLemmaWidget | |
96.15% |
25 / 26 |
|
0.00% |
0 / 1 |
1 | |||
renderLanguageAndLexicalCategoryWidget | |
100.00% |
24 / 24 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace Wikibase\Lexeme\Presentation\View; |
4 | |
5 | use InvalidArgumentException; |
6 | use MediaWiki\Message\Message; |
7 | use Wikibase\DataModel\Entity\EntityDocument; |
8 | use Wikibase\DataModel\Services\EntityId\EntityIdFormatter; |
9 | use Wikibase\DataModel\Term\Term; |
10 | use Wikibase\Lexeme\Domain\Model\Lexeme; |
11 | use Wikibase\Lexeme\Presentation\Formatters\LexemeTermFormatter; |
12 | use Wikibase\Lexeme\Presentation\View\Template\VueTemplates; |
13 | use Wikibase\View\EntityView; |
14 | use Wikibase\View\LanguageDirectionalityLookup; |
15 | use Wikibase\View\StatementSectionsView; |
16 | use Wikibase\View\Template\TemplateFactory; |
17 | use Wikibase\View\ViewContent; |
18 | use Wikimedia\Assert\Assert; |
19 | use WMDE\VueJsTemplating\Templating; |
20 | |
21 | /** |
22 | * Class for creating HTML views for Lexeme instances. |
23 | * |
24 | * @license GPL-2.0-or-later |
25 | * @author Amir Sarabadani <ladsgroup@gmail.com> |
26 | */ |
27 | class LexemeView extends EntityView { |
28 | |
29 | /** |
30 | * @var FormsView |
31 | */ |
32 | private $formsView; |
33 | |
34 | /** |
35 | * @var SensesView |
36 | */ |
37 | private $sensesView; |
38 | |
39 | /** |
40 | * @var StatementSectionsView |
41 | */ |
42 | private $statementSectionsView; |
43 | |
44 | /** |
45 | * @var EntityIdFormatter |
46 | */ |
47 | private $idFormatter; |
48 | |
49 | /** |
50 | * @var LexemeTermFormatter |
51 | */ |
52 | private $lemmaFormatter; |
53 | |
54 | /** |
55 | * @param TemplateFactory $templateFactory |
56 | * @param LanguageDirectionalityLookup $languageDirectionalityLookup |
57 | * @param string $languageCode |
58 | * @param FormsView $formsView |
59 | * @param SensesView $sensesView |
60 | * @param StatementSectionsView $statementSectionsView |
61 | * @param LexemeTermFormatter $lemmaFormatter |
62 | * @param EntityIdFormatter $idFormatter |
63 | */ |
64 | public function __construct( |
65 | TemplateFactory $templateFactory, |
66 | LanguageDirectionalityLookup $languageDirectionalityLookup, |
67 | $languageCode, |
68 | FormsView $formsView, |
69 | SensesView $sensesView, |
70 | StatementSectionsView $statementSectionsView, |
71 | LexemeTermFormatter $lemmaFormatter, |
72 | EntityIdFormatter $idFormatter |
73 | ) { |
74 | parent::__construct( |
75 | $templateFactory, |
76 | $languageDirectionalityLookup, |
77 | $languageCode |
78 | ); |
79 | |
80 | $this->formsView = $formsView; |
81 | $this->sensesView = $sensesView; |
82 | $this->statementSectionsView = $statementSectionsView; |
83 | $this->idFormatter = $idFormatter; |
84 | $this->lemmaFormatter = $lemmaFormatter; |
85 | } |
86 | |
87 | /** |
88 | * Builds and returns the main content representing a whole Lexeme |
89 | * |
90 | * @param EntityDocument $entity the entity to render |
91 | * @param int|null $revision the revision of the entity to render |
92 | * |
93 | * @return ViewContent |
94 | */ |
95 | public function getContent( EntityDocument $entity, $revision = null ): ViewContent { |
96 | return new ViewContent( |
97 | $this->renderEntityView( $entity ) |
98 | ); |
99 | } |
100 | |
101 | /** |
102 | * @see EntityView::getMainHtml |
103 | * |
104 | * @param EntityDocument $entity |
105 | * |
106 | * @throws InvalidArgumentException if the entity type does not match. |
107 | * @return string HTML |
108 | */ |
109 | protected function getMainHtml( EntityDocument $entity ) { |
110 | /** @var Lexeme $entity */ |
111 | Assert::parameterType( Lexeme::class, $entity, '$entity' ); |
112 | '@phan-var Lexeme $entity'; |
113 | |
114 | $html = $this->getLexemeHeader( $entity ) |
115 | . $this->templateFactory->render( 'wikibase-toc' ) |
116 | . $this->statementSectionsView->getHtml( $entity->getStatements() ) |
117 | . $this->sensesView->getHtml( $entity->getSenses() ) |
118 | . $this->formsView->getHtml( $entity->getForms() ); |
119 | |
120 | return $html; |
121 | } |
122 | |
123 | /** |
124 | * @param Lexeme $entity |
125 | * @return string HTML |
126 | */ |
127 | private function getLexemeHeader( Lexeme $entity ) { |
128 | $id = ''; |
129 | if ( $entity->getId() ) { |
130 | $id = htmlspecialchars( |
131 | $this->getLocalizedMessage( 'parentheses', [ $entity->getId()->getSerialization() ] ) |
132 | ); |
133 | } |
134 | |
135 | $lemmaWidget = $this->renderLemmaWidget( $entity ); |
136 | $languageAndCategory = $this->renderLanguageAndLexicalCategoryWidget( $entity ); |
137 | |
138 | return <<<HTML |
139 | <div id="wb-lexeme-header" class="wb-lexeme-header"> |
140 | <div id="wb-lexeme-header-lemmas"> |
141 | <div class="wb-lexeme-header_id">$id</div> |
142 | <div class="wb-lexeme-header_lemma-widget"> |
143 | $lemmaWidget |
144 | </div> |
145 | </div> |
146 | $languageAndCategory |
147 | </div> |
148 | HTML; |
149 | } |
150 | |
151 | /** |
152 | * @see EntityView::getSideHtml |
153 | * |
154 | * @param EntityDocument $entity |
155 | * |
156 | * @return string HTML |
157 | */ |
158 | protected function getSideHtml( EntityDocument $entity ) { |
159 | return ''; |
160 | } |
161 | |
162 | /** |
163 | * @param EntityDocument $entity |
164 | * |
165 | * @return string |
166 | */ |
167 | public function getTitleHtml( EntityDocument $entity ) { |
168 | /** @var Lexeme $entity */ |
169 | Assert::parameterType( Lexeme::class, $entity, '$entity' ); |
170 | '@phan-var Lexeme $entity'; |
171 | $isEmpty = true; |
172 | $idInParenthesesHtml = ''; |
173 | $labelHtml = ''; |
174 | |
175 | if ( $entity->getId() !== null ) { |
176 | $id = $entity->getId()->getSerialization(); |
177 | $isEmpty = false; |
178 | $idInParenthesesHtml = htmlspecialchars( |
179 | $this->getLocalizedMessage( 'parentheses', [ $id ] ) |
180 | ); |
181 | |
182 | $labelHtml = $this->lemmaFormatter->format( $entity->getLemmas() ); |
183 | } |
184 | |
185 | $title = $isEmpty ? htmlspecialchars( |
186 | $this->getLocalizedMessage( 'wikibase-label-empty' ) ) : $labelHtml; |
187 | |
188 | return $this->templateFactory->render( |
189 | 'wikibase-title', |
190 | $isEmpty ? 'wb-empty' : '', |
191 | $title, |
192 | $idInParenthesesHtml |
193 | ); |
194 | } |
195 | |
196 | /** |
197 | * @param string $key |
198 | * @param array $params |
199 | * |
200 | * @return string Plain text |
201 | */ |
202 | private function getLocalizedMessage( $key, array $params = [] ) { |
203 | return ( new Message( $key, $params ) )->inLanguage( $this->languageCode )->text(); |
204 | } |
205 | |
206 | /** |
207 | * @return string |
208 | */ |
209 | private function renderLemmaWidget( Lexeme $lexeme ) { |
210 | $templating = new Templating(); |
211 | $template = file_get_contents( __DIR__ . VueTemplates::LEMMA ); |
212 | |
213 | $lemmas = array_map( |
214 | static function ( Term $lemma ) { |
215 | return [ 'value' => $lemma->getText(), 'language' => $lemma->getLanguageCode() ]; |
216 | }, |
217 | iterator_to_array( $lexeme->getLemmas() ) |
218 | ); |
219 | |
220 | $result = $templating->render( |
221 | $template, |
222 | [ |
223 | 'isInitialized' => false, |
224 | 'inEditMode' => false, |
225 | 'isSaving' => false, |
226 | 'lemmaList' => $lemmas, |
227 | 'isUnsaveable' => true, |
228 | ], |
229 | [ |
230 | 'message' => function ( $key ) { |
231 | return $this->getLocalizedMessage( $key ); |
232 | }, |
233 | ] |
234 | ); |
235 | |
236 | return '<div id="lemmas-widget">' |
237 | . $result |
238 | . '</div>'; |
239 | } |
240 | |
241 | /** |
242 | * @param Lexeme $lexeme |
243 | * @return string |
244 | */ |
245 | private function renderLanguageAndLexicalCategoryWidget( Lexeme $lexeme ) { |
246 | $templating = new Templating(); |
247 | $categoryTemplate = file_get_contents( __DIR__ . VueTemplates::CATEGORY_WIDGET ); |
248 | |
249 | $languageId = $lexeme->getLanguage(); |
250 | $lexicalCategoryId = $lexeme->getLexicalCategory(); |
251 | |
252 | $result = $templating->render( |
253 | $categoryTemplate, |
254 | [ |
255 | 'isInitialized' => false, |
256 | 'inEditMode' => false, |
257 | 'isSaving' => false, |
258 | 'formattedLanguage' => $this->idFormatter->formatEntityId( $languageId ), |
259 | 'language' => $languageId->getSerialization(), |
260 | 'formattedLexicalCategory' => $this->idFormatter->formatEntityId( |
261 | $lexicalCategoryId |
262 | ), |
263 | 'lexicalCategory' => $lexicalCategoryId->getSerialization(), |
264 | ], |
265 | [ |
266 | 'message' => function ( $key ) { |
267 | return $this->getLocalizedMessage( $key ); |
268 | }, |
269 | ] |
270 | ); |
271 | |
272 | return '<div>' . $result . '</div>'; |
273 | } |
274 | |
275 | } |