Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
62.50% |
40 / 64 |
|
63.64% |
7 / 11 |
CRAP | |
0.00% |
0 / 1 |
TextContentHandler | |
63.49% |
40 / 63 |
|
63.64% |
7 / 11 |
36.57 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
serializeContent | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
merge3 | |
83.33% |
15 / 18 |
|
0.00% |
0 / 1 |
5.12 | |||
getContentClass | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
unserializeContent | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
makeEmptyContent | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
supportsDirectEditing | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getFieldsForSearchIndex | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
getDataForSearchIndex | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
preSaveTransform | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
fillParserOutput | |
39.13% |
9 / 23 |
|
0.00% |
0 / 1 |
7.61 |
1 | <?php |
2 | /** |
3 | * Base content handler class for flat text contents. |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * http://www.gnu.org/copyleft/gpl.html |
19 | * |
20 | * @since 1.21 |
21 | * |
22 | * @file |
23 | * @ingroup Content |
24 | */ |
25 | |
26 | namespace MediaWiki\Content; |
27 | |
28 | use MediaWiki\Content\Renderer\ContentParseParams; |
29 | use MediaWiki\Content\Transform\PreSaveTransformParams; |
30 | use MediaWiki\MainConfigNames; |
31 | use MediaWiki\MediaWikiServices; |
32 | use MediaWiki\Parser\ParserOutput; |
33 | use MediaWiki\Revision\RevisionRecord; |
34 | use ReflectionMethod; |
35 | use SearchEngine; |
36 | use SearchIndexField; |
37 | use WikiPage; |
38 | |
39 | /** |
40 | * Base content handler implementation for flat text contents. |
41 | * |
42 | * @ingroup Content |
43 | */ |
44 | class TextContentHandler extends ContentHandler { |
45 | |
46 | public function __construct( $modelId = CONTENT_MODEL_TEXT, $formats = [ CONTENT_FORMAT_TEXT ] ) { |
47 | parent::__construct( $modelId, $formats ); |
48 | } |
49 | |
50 | /** |
51 | * Returns the content's text as-is. |
52 | * |
53 | * @param Content $content |
54 | * @param string|null $format The serialization format to check |
55 | * |
56 | * @return mixed |
57 | */ |
58 | public function serializeContent( Content $content, $format = null ) { |
59 | $this->checkFormat( $format ); |
60 | |
61 | // @phan-suppress-next-line PhanUndeclaredMethod |
62 | return $content->getText(); |
63 | } |
64 | |
65 | /** |
66 | * Attempts to merge differences between three versions. Returns a new |
67 | * Content object for a clean merge and false for failure or a conflict. |
68 | * |
69 | * All three Content objects passed as parameters must have the same |
70 | * content model. |
71 | * |
72 | * This text-based implementation uses wfMerge(). |
73 | * |
74 | * @param Content $oldContent The page's previous content. |
75 | * @param Content $myContent One of the page's conflicting contents. |
76 | * @param Content $yourContent One of the page's conflicting contents. |
77 | * |
78 | * @return Content|false |
79 | */ |
80 | public function merge3( Content $oldContent, Content $myContent, Content $yourContent ) { |
81 | // Nothing to do when the unsaved edit is already identical to the latest revision |
82 | if ( $myContent->equals( $yourContent ) ) { |
83 | return $yourContent; |
84 | } |
85 | // Impossible to have a conflict when the user just edited the latest revision. This can |
86 | // happen e.g. when $wgDiff3 is badly configured. |
87 | if ( $oldContent->equals( $yourContent ) ) { |
88 | return $myContent; |
89 | } |
90 | |
91 | $this->checkModelID( $oldContent->getModel() ); |
92 | $this->checkModelID( $myContent->getModel() ); |
93 | $this->checkModelID( $yourContent->getModel() ); |
94 | |
95 | $format = $this->getDefaultFormat(); |
96 | |
97 | $old = $this->serializeContent( $oldContent, $format ); |
98 | $mine = $this->serializeContent( $myContent, $format ); |
99 | $yours = $this->serializeContent( $yourContent, $format ); |
100 | |
101 | $ok = wfMerge( $old, $mine, $yours, $result ); |
102 | |
103 | if ( !$ok ) { |
104 | return false; |
105 | } |
106 | |
107 | if ( !$result ) { |
108 | return $this->makeEmptyContent(); |
109 | } |
110 | |
111 | $mergedContent = $this->unserializeContent( $result, $format ); |
112 | |
113 | return $mergedContent; |
114 | } |
115 | |
116 | /** |
117 | * Returns the name of the associated Content class, to |
118 | * be used when creating new objects. Override expected |
119 | * by subclasses. |
120 | * |
121 | * @since 1.24 |
122 | * |
123 | * @return class-string<TextContent> |
124 | */ |
125 | protected function getContentClass() { |
126 | return TextContent::class; |
127 | } |
128 | |
129 | /** |
130 | * Unserializes a Content object of the type supported by this ContentHandler. |
131 | * |
132 | * @since 1.21 |
133 | * |
134 | * @param string $text Serialized form of the content |
135 | * @param string|null $format The format used for serialization |
136 | * |
137 | * @return Content The TextContent object wrapping $text |
138 | */ |
139 | public function unserializeContent( $text, $format = null ) { |
140 | $this->checkFormat( $format ); |
141 | |
142 | $class = $this->getContentClass(); |
143 | return new $class( $text ); |
144 | } |
145 | |
146 | /** |
147 | * Creates an empty TextContent object. |
148 | * |
149 | * @since 1.21 |
150 | * |
151 | * @return Content A new TextContent object with empty text. |
152 | */ |
153 | public function makeEmptyContent() { |
154 | $class = $this->getContentClass(); |
155 | return new $class( '' ); |
156 | } |
157 | |
158 | /** |
159 | * @see ContentHandler::supportsDirectEditing |
160 | * |
161 | * @return bool Should return true for TextContent and derivatives. |
162 | */ |
163 | public function supportsDirectEditing() { |
164 | return true; |
165 | } |
166 | |
167 | public function getFieldsForSearchIndex( SearchEngine $engine ) { |
168 | $fields = parent::getFieldsForSearchIndex( $engine ); |
169 | $fields['language'] = |
170 | $engine->makeSearchFieldMapping( 'language', SearchIndexField::INDEX_TYPE_KEYWORD ); |
171 | |
172 | return $fields; |
173 | } |
174 | |
175 | public function getDataForSearchIndex( |
176 | WikiPage $page, |
177 | ParserOutput $output, |
178 | SearchEngine $engine, |
179 | ?RevisionRecord $revision = null |
180 | ) { |
181 | $fields = parent::getDataForSearchIndex( $page, $output, $engine, $revision ); |
182 | $fields['language'] = |
183 | $this->getPageLanguage( $page->getTitle(), $page->getContent() )->getCode(); |
184 | return $fields; |
185 | } |
186 | |
187 | public function preSaveTransform( |
188 | Content $content, |
189 | PreSaveTransformParams $pstParams |
190 | ): Content { |
191 | '@phan-var TextContent $content'; |
192 | |
193 | $text = $content->getText(); |
194 | |
195 | $pst = TextContent::normalizeLineEndings( $text ); |
196 | |
197 | $contentClass = $this->getContentClass(); |
198 | return ( $text === $pst ) ? $content : new $contentClass( $pst, $content->getModel() ); |
199 | } |
200 | |
201 | /** |
202 | * Fills the provided ParserOutput object with information derived from the content. |
203 | * Unless $generateHtml was false, this includes an HTML representation of the content |
204 | * provided by getHtml(). |
205 | * |
206 | * For content models listed in $wgTextModelsToParse, this method will call the MediaWiki |
207 | * wikitext parser on the text to extract any (wikitext) links, magic words, etc., |
208 | * but note that the Table of Contents will *not* be generated |
209 | * (feature added by T307691, but should be refactored: T313455). |
210 | * |
211 | * Subclasses may override this to provide custom content processing. |
212 | * For custom HTML generation alone, it is sufficient to override getHtml(). |
213 | * |
214 | * @stable to override |
215 | * |
216 | * @since 1.38 |
217 | * @param Content $content |
218 | * @param ContentParseParams $cpoParams |
219 | * @param ParserOutput &$output The output object to fill (reference). |
220 | */ |
221 | protected function fillParserOutput( |
222 | Content $content, |
223 | ContentParseParams $cpoParams, |
224 | ParserOutput &$output |
225 | ) { |
226 | $textModelsToParse = MediaWikiServices::getInstance()->getMainConfig()->get( |
227 | MainConfigNames::TextModelsToParse ); |
228 | '@phan-var TextContent $content'; |
229 | if ( in_array( $content->getModel(), $textModelsToParse ) ) { |
230 | // parse just to get links etc into the database, HTML is replaced below. |
231 | $output = MediaWikiServices::getInstance()->getParserFactory()->getInstance() |
232 | ->parse( |
233 | $content->getText(), |
234 | $cpoParams->getPage(), |
235 | $cpoParams->getParserOptions(), |
236 | true, |
237 | true, |
238 | $cpoParams->getRevId() |
239 | ); |
240 | } |
241 | |
242 | if ( $cpoParams->getGenerateHtml() ) { |
243 | // Temporary changes as getHtml() is deprecated, we are working on removing usage of it. |
244 | if ( method_exists( $content, 'getHtml' ) ) { |
245 | $method = new ReflectionMethod( $content, 'getHtml' ); |
246 | $method->setAccessible( true ); |
247 | $html = $method->invoke( $content ); |
248 | $html = "<pre>$html</pre>"; |
249 | } else { |
250 | // Return an HTML representation of the content |
251 | $html = htmlspecialchars( $content->getText(), ENT_COMPAT ); |
252 | $html = "<pre>$html</pre>"; |
253 | } |
254 | } else { |
255 | $html = null; |
256 | } |
257 | |
258 | $output->clearWrapperDivClass(); |
259 | $output->setRawText( $html ); |
260 | } |
261 | } |
262 | /** @deprecated class alias since 1.43 */ |
263 | class_alias( TextContentHandler::class, 'TextContentHandler' ); |