Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
37.23% |
35 / 94 |
|
33.33% |
4 / 12 |
CRAP | |
0.00% |
0 / 1 |
EntitySchemaContentHandler | |
37.23% |
35 / 94 |
|
33.33% |
4 / 12 |
236.95 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getContentClass | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSlotDiffRendererWithOptions | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
getPageViewLanguage | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
canBeUsedOn | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
getActionOverrides | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
getActionOverridesEdit | |
0.00% |
0 / 31 |
|
0.00% |
0 / 1 |
30 | |||
getActionOverridesSubmit | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
20 | |||
supportsDirectApiEditing | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getUndoContent | |
79.17% |
19 / 24 |
|
0.00% |
0 / 1 |
8.58 | |||
isParserCacheSupported | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
fillParserOutput | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
3 |
1 | <?php |
2 | |
3 | declare( strict_types = 1 ); |
4 | |
5 | namespace EntitySchema\MediaWiki\Content; |
6 | |
7 | use Action; |
8 | use Article; |
9 | use Content; |
10 | use EntitySchema\DataAccess\EntitySchemaEncoder; |
11 | use EntitySchema\MediaWiki\Actions\EntitySchemaEditAction; |
12 | use EntitySchema\MediaWiki\Actions\EntitySchemaSubmitAction; |
13 | use EntitySchema\MediaWiki\Actions\RestoreSubmitAction; |
14 | use EntitySchema\MediaWiki\Actions\RestoreViewAction; |
15 | use EntitySchema\MediaWiki\Actions\UndoSubmitAction; |
16 | use EntitySchema\MediaWiki\Actions\UndoViewAction; |
17 | use EntitySchema\MediaWiki\UndoHandler; |
18 | use EntitySchema\Presentation\InputValidator; |
19 | use EntitySchema\Services\Converter\EntitySchemaConverter; |
20 | use IContextSource; |
21 | use JsonContentHandler; |
22 | use Language; |
23 | use LogicException; |
24 | use MediaWiki\Content\IContentHandlerFactory; |
25 | use MediaWiki\Content\Renderer\ContentParseParams; |
26 | use MediaWiki\MediaWikiServices; |
27 | use MediaWiki\Title\Title; |
28 | use ParserOutput; |
29 | use RequestContext; |
30 | use Wikibase\Repo\WikibaseRepo; |
31 | |
32 | /** |
33 | * Content handler for the EntitySchema content |
34 | * |
35 | * @license GPL-2.0-or-later |
36 | */ |
37 | class EntitySchemaContentHandler extends JsonContentHandler { |
38 | |
39 | private IContentHandlerFactory $contentHandlerFactory; |
40 | |
41 | public function __construct( |
42 | string $modelId, |
43 | IContentHandlerFactory $contentHandlerFactory |
44 | ) { |
45 | // $modelId is typically EntitySchemaContent::CONTENT_MODEL_ID |
46 | parent::__construct( $modelId ); |
47 | $this->contentHandlerFactory = $contentHandlerFactory; |
48 | } |
49 | |
50 | protected function getContentClass(): string { |
51 | return EntitySchemaContent::class; |
52 | } |
53 | |
54 | protected function getSlotDiffRendererWithOptions( |
55 | IContextSource $context, |
56 | $options = [] |
57 | ): EntitySchemaSlotDiffRenderer { |
58 | return new EntitySchemaSlotDiffRenderer( |
59 | $context, |
60 | $this->createTextSlotDiffRenderer( $options ) |
61 | ); |
62 | } |
63 | |
64 | /** |
65 | * @see ContentHandler::getPageViewLanguage |
66 | * |
67 | * This implementation returns the user language, because Schemas get rendered in |
68 | * the user's language. The PageContentLanguage hook is bypassed. |
69 | * |
70 | * @param Title $title (unused) the page to determine the language for. |
71 | * @param Content|null $content (unused) the page's content |
72 | * |
73 | * @return Language The page's language |
74 | */ |
75 | public function getPageViewLanguage( Title $title, Content $content = null ): Language { |
76 | $context = RequestContext::getMain(); |
77 | return $context->getLanguage(); |
78 | } |
79 | |
80 | public function canBeUsedOn( Title $title ): bool { |
81 | return $title->inNamespace( NS_ENTITYSCHEMA_JSON ) && parent::canBeUsedOn( $title ); |
82 | } |
83 | |
84 | public function getActionOverrides(): array { |
85 | return [ |
86 | 'edit' => function ( Article $article, IContextSource $context ) { |
87 | return $this->getActionOverridesEdit( $article, $context ); |
88 | }, |
89 | 'submit' => function ( Article $article, IContextSource $context ) { |
90 | return $this->getActionOverridesSubmit( $article, $context ); |
91 | }, |
92 | ]; |
93 | } |
94 | |
95 | /** |
96 | * @param Article $article |
97 | * @param IContextSource $context |
98 | * @return Action|callable |
99 | */ |
100 | private function getActionOverridesEdit( |
101 | Article $article, |
102 | IContextSource $context |
103 | ) { |
104 | global $wgEditSubmitButtonLabelPublish; |
105 | |
106 | if ( $article->getPage()->getRevisionRecord() === null ) { |
107 | return Action::factory( 'view', $article, $context ); |
108 | } |
109 | |
110 | $req = $context->getRequest(); |
111 | |
112 | if ( |
113 | $req->getCheck( 'undo' ) |
114 | || $req->getCheck( 'undoafter' ) |
115 | ) { |
116 | return new UndoViewAction( |
117 | $article, |
118 | $context, |
119 | $this->getSlotDiffRendererWithOptions( $context ) |
120 | ); |
121 | } |
122 | |
123 | if ( $req->getCheck( 'restore' ) ) { |
124 | return new RestoreViewAction( |
125 | $article, |
126 | $context, |
127 | $this->getSlotDiffRendererWithOptions( $context ) |
128 | ); |
129 | } |
130 | |
131 | // TODo: check redirect? |
132 | // !$article->isRedirect() |
133 | $repoSettings = WikibaseRepo::getSettings(); |
134 | return new EntitySchemaEditAction( |
135 | $article, |
136 | $context, |
137 | new InputValidator( |
138 | $context, |
139 | MediaWikiServices::getInstance()->getMainConfig(), |
140 | MediaWikiServices::getInstance()->getLanguageNameUtils() |
141 | ), |
142 | $wgEditSubmitButtonLabelPublish, |
143 | MediaWikiServices::getInstance()->getUserOptionsLookup(), |
144 | $repoSettings->getSetting( 'dataRightsUrl' ), |
145 | $repoSettings->getSetting( 'dataRightsText' ), |
146 | MediaWikiServices::getInstance()->getTempUserConfig() |
147 | ); |
148 | } |
149 | |
150 | /** |
151 | * @param Article $article |
152 | * @param IContextSource $context |
153 | * @return RestoreSubmitAction|UndoSubmitAction|string |
154 | */ |
155 | private function getActionOverridesSubmit( |
156 | Article $article, |
157 | IContextSource $context |
158 | ) { |
159 | $req = $context->getRequest(); |
160 | |
161 | if ( |
162 | $req->getCheck( 'undo' ) |
163 | || $req->getCheck( 'undoafter' ) |
164 | ) { |
165 | return new UndoSubmitAction( $article, $context ); |
166 | } |
167 | |
168 | if ( $req->getCheck( 'restore' ) ) { |
169 | return new RestoreSubmitAction( $article, $context ); |
170 | } |
171 | |
172 | return EntitySchemaSubmitAction::class; |
173 | } |
174 | |
175 | public function supportsDirectApiEditing(): bool { |
176 | return false; |
177 | } |
178 | |
179 | /** |
180 | * Get the Content object that needs to be saved in order to undo all revisions |
181 | * between $undo and $undoafter. Revisions must belong to the same page, |
182 | * must exist and must not be deleted. |
183 | * |
184 | * @since 1.32 accepts Content objects for all parameters instead of Revision objects. |
185 | * Passing Revision objects is deprecated. |
186 | * @since 1.37 only accepts Content objects |
187 | * |
188 | * @param Content $baseContent The current text |
189 | * @param Content $undoFromContent The content of the revision to undo |
190 | * @param Content $undoToContent Must be from an earlier revision than $undo |
191 | * @param bool $undoIsLatest Set true if $undo is from the current revision (since 1.32) |
192 | * |
193 | * @return Content|false |
194 | */ |
195 | public function getUndoContent( |
196 | Content $baseContent, |
197 | Content $undoFromContent, |
198 | Content $undoToContent, |
199 | $undoIsLatest = false |
200 | ) { |
201 | if ( $undoIsLatest ) { |
202 | return $undoToContent; |
203 | } |
204 | |
205 | // Make sure correct subclass |
206 | if ( !$baseContent instanceof EntitySchemaContent || |
207 | !$undoFromContent instanceof EntitySchemaContent || |
208 | !$undoToContent instanceof EntitySchemaContent |
209 | ) { |
210 | return false; |
211 | } |
212 | |
213 | $undoHandler = new UndoHandler(); |
214 | try { |
215 | $schemaId = $undoHandler->validateContentIds( $undoToContent, $undoFromContent, $baseContent ); |
216 | } catch ( LogicException $e ) { |
217 | return false; |
218 | } |
219 | |
220 | $diffStatus = $undoHandler->getDiffFromContents( $undoFromContent, $undoToContent ); |
221 | if ( !$diffStatus->isOK() ) { |
222 | return false; |
223 | } |
224 | |
225 | $patchStatus = $undoHandler->tryPatching( $diffStatus->getValue(), $baseContent ); |
226 | if ( !$patchStatus->isOK() ) { |
227 | return false; |
228 | } |
229 | $patchedSchema = $patchStatus->getValue()->data; |
230 | |
231 | return new EntitySchemaContent( EntitySchemaEncoder::getPersistentRepresentation( |
232 | $schemaId, |
233 | $patchedSchema['labels'], |
234 | $patchedSchema['descriptions'], |
235 | $patchedSchema['aliases'], |
236 | $patchedSchema['schemaText'] |
237 | ) ); |
238 | } |
239 | |
240 | /** |
241 | * Returns true to indicate that the parser cache can be used for Schemas. |
242 | * |
243 | * @note The html representation of Schemas depends on the user language, so |
244 | * EntitySchemaContent::getParserOutput needs to make sure |
245 | * ParserOutput::recordOption( 'userlang' ) is called to split the cache by user language. |
246 | * |
247 | * @see ContentHandler::isParserCacheSupported |
248 | * |
249 | * @return bool Always true in this default implementation. |
250 | */ |
251 | public function isParserCacheSupported(): bool { |
252 | return true; |
253 | } |
254 | |
255 | /** |
256 | * @inheritDoc |
257 | */ |
258 | protected function fillParserOutput( |
259 | Content $content, |
260 | ContentParseParams $cpoParams, |
261 | ParserOutput &$parserOutput |
262 | ): void { |
263 | '@phan-var EntitySchemaContent $content'; |
264 | $parserOptions = $cpoParams->getParserOptions(); |
265 | $generateHtml = $cpoParams->getGenerateHtml(); |
266 | if ( $generateHtml && $content->isValid() ) { |
267 | $languageCode = $parserOptions->getUserLang(); |
268 | $renderer = new EntitySchemaSlotViewRenderer( $languageCode ); |
269 | $renderer->fillParserOutput( |
270 | ( new EntitySchemaConverter() ) |
271 | ->getFullViewSchemaData( $content->getText(), [ $languageCode ] ), |
272 | $cpoParams->getPage(), |
273 | $parserOutput |
274 | ); |
275 | } else { |
276 | $parserOutput->setText( '' ); |
277 | } |
278 | } |
279 | |
280 | } |