Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 48 |
|
0.00% |
0 / 23 |
CRAP | |
0.00% |
0 / 1 |
AbstractContent | |
0.00% |
0 / 47 |
|
0.00% |
0 / 23 |
992 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getModel | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
checkModelID | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
getContentHandler | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getContentHandlerFactory | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDefaultFormat | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSupportedFormats | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isSupportedFormat | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
checkFormat | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
serialize | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getNativeData | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
isEmpty | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isValid | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
equals | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
30 | |||
equalsInternal | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getRedirectTarget | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isRedirect | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
updateRedirect | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSection | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
replaceSection | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
addSectionHeader | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
matchMagicWord | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
convert | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | /** |
3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
16 | * http://www.gnu.org/copyleft/gpl.html |
17 | * |
18 | * @file |
19 | * @author Daniel Kinzler |
20 | */ |
21 | |
22 | namespace MediaWiki\Content; |
23 | |
24 | use LogicException; |
25 | use MediaWiki\Exception\MWException; |
26 | use MediaWiki\HookContainer\HookRunner; |
27 | use MediaWiki\MediaWikiServices; |
28 | use MediaWiki\Parser\MagicWord; |
29 | use MediaWiki\Title\Title; |
30 | |
31 | /** |
32 | * Base class for all Content objects. Refer to Content for more information. |
33 | * |
34 | * @stable to extend |
35 | * @since 1.21 |
36 | * @ingroup Content |
37 | */ |
38 | abstract class AbstractContent implements Content { |
39 | /** |
40 | * @var string |
41 | * @since 1.21 |
42 | */ |
43 | protected $model_id; |
44 | |
45 | /** |
46 | * @stable to call |
47 | * @since 1.21 |
48 | * @param string|null $modelId One of the CONTENT_MODEL_XXX constants. |
49 | */ |
50 | public function __construct( $modelId = null ) { |
51 | $this->model_id = $modelId; |
52 | } |
53 | |
54 | /** |
55 | * @see Content::getModel |
56 | * @since 1.21 |
57 | * @return string |
58 | */ |
59 | public function getModel() { |
60 | return $this->model_id; |
61 | } |
62 | |
63 | /** |
64 | * Helper for subclasses |
65 | * |
66 | * @since 1.21 |
67 | * @param string $modelId The model to check |
68 | * @throws MWException If the provided model ID differs from this Content object |
69 | */ |
70 | protected function checkModelID( $modelId ) { |
71 | if ( $modelId !== $this->model_id ) { |
72 | throw new MWException( |
73 | "Bad content model: expected {$this->model_id} but got $modelId." |
74 | ); |
75 | } |
76 | } |
77 | |
78 | /** |
79 | * @see Content::getContentHandler |
80 | * @since 1.21 |
81 | * @return ContentHandler |
82 | */ |
83 | public function getContentHandler() { |
84 | return $this->getContentHandlerFactory()->getContentHandler( $this->getModel() ); |
85 | } |
86 | |
87 | protected function getContentHandlerFactory(): IContentHandlerFactory { |
88 | return MediaWikiServices::getInstance()->getContentHandlerFactory(); |
89 | } |
90 | |
91 | /** |
92 | * @see Content::getDefaultFormat |
93 | * @since 1.21 |
94 | * @return string |
95 | */ |
96 | public function getDefaultFormat() { |
97 | return $this->getContentHandler()->getDefaultFormat(); |
98 | } |
99 | |
100 | /** |
101 | * @see Content::getSupportedFormats |
102 | * @since 1.21 |
103 | * @return string[] |
104 | */ |
105 | public function getSupportedFormats() { |
106 | return $this->getContentHandler()->getSupportedFormats(); |
107 | } |
108 | |
109 | /** |
110 | * @see Content::isSupportedFormat |
111 | * @since 1.21 |
112 | * @param string $format |
113 | * @return bool |
114 | */ |
115 | public function isSupportedFormat( $format ) { |
116 | if ( !$format ) { |
117 | return true; // this means "use the default" |
118 | } |
119 | |
120 | return $this->getContentHandler()->isSupportedFormat( $format ); |
121 | } |
122 | |
123 | /** |
124 | * Helper for subclasses. |
125 | * |
126 | * @since 1.21 |
127 | * @param string $format The serialization format to check. |
128 | * @throws MWException If the format is not supported by this Content object |
129 | */ |
130 | protected function checkFormat( $format ) { |
131 | if ( !$this->isSupportedFormat( $format ) ) { |
132 | throw new MWException( |
133 | "Format $format is not supported for content model " . |
134 | $this->getModel() |
135 | ); |
136 | } |
137 | } |
138 | |
139 | /** |
140 | * @stable to override |
141 | * @see Content::serialize |
142 | * @since 1.21 |
143 | * @param string|null $format |
144 | * @return string |
145 | */ |
146 | public function serialize( $format = null ) { |
147 | return $this->getContentHandler()->serializeContent( $this, $format ); |
148 | } |
149 | |
150 | /** |
151 | * @see Content::getNativeData |
152 | * @stable to override |
153 | * @deprecated since 1.33 Use TextContent::getText() instead. |
154 | * For other content models, use specialized getters. |
155 | * @since 1.21 |
156 | * @return mixed |
157 | */ |
158 | public function getNativeData() { |
159 | wfDeprecated( __METHOD__, '1.33' ); |
160 | throw new LogicException( __METHOD__ . ': not implemented' ); |
161 | } |
162 | |
163 | /** |
164 | * @see Content::isEmpty |
165 | * @stable to override |
166 | * @since 1.21 |
167 | * @return bool |
168 | */ |
169 | public function isEmpty() { |
170 | return $this->getSize() === 0; |
171 | } |
172 | |
173 | /** |
174 | * @see Content::isValid |
175 | * @stable to override |
176 | * @since 1.21 |
177 | * @return bool |
178 | */ |
179 | public function isValid() { |
180 | return true; |
181 | } |
182 | |
183 | /** |
184 | * @see Content::equals |
185 | * @stable to override |
186 | * @since 1.21 |
187 | * @param Content|null $that |
188 | * @return bool |
189 | */ |
190 | public function equals( ?Content $that = null ) { |
191 | if ( $that === null ) { |
192 | return false; |
193 | } |
194 | |
195 | if ( $that === $this ) { |
196 | return true; |
197 | } |
198 | |
199 | if ( $that->getModel() !== $this->getModel() ) { |
200 | return false; |
201 | } |
202 | |
203 | // For type safety. Needed for odd cases like non-TextContents using CONTENT_MODEL_WIKITEXT |
204 | if ( get_class( $that ) !== get_class( $this ) ) { |
205 | return false; |
206 | } |
207 | |
208 | return $this->equalsInternal( $that ); |
209 | } |
210 | |
211 | /** |
212 | * Helper for AbstractContent::equals. |
213 | * |
214 | * @note Do not call this method directly, call Content::equals() instead. |
215 | * |
216 | * This method can be overwritten by subclasses that only need to implement custom |
217 | * equality checks, with the rest of the Content::equals contract taken care of by |
218 | * AbstractContent::equals. |
219 | * |
220 | * This default implementation compares Content::serialize of each object. |
221 | * |
222 | * If you override this method, you can safely assume that $that is an instance of the same |
223 | * class as the current Content object. This is ensured by AbstractContent::equals. |
224 | * |
225 | * @see Content::equals |
226 | * @stable to override |
227 | * @param Content $that |
228 | * @return bool |
229 | */ |
230 | protected function equalsInternal( Content $that ) { |
231 | return $this->serialize() === $that->serialize(); |
232 | } |
233 | |
234 | /** |
235 | * Subclasses that implement redirects should override this. |
236 | * |
237 | * @see Content::getRedirectTarget |
238 | * @stable to override |
239 | * @since 1.21 |
240 | * @return Title|null |
241 | */ |
242 | public function getRedirectTarget() { |
243 | return null; |
244 | } |
245 | |
246 | /** |
247 | * @see Content::isRedirect |
248 | * @since 1.21 |
249 | * @return bool |
250 | */ |
251 | public function isRedirect() { |
252 | return $this->getRedirectTarget() !== null; |
253 | } |
254 | |
255 | /** |
256 | * This default implementation always returns $this. |
257 | * Subclasses that implement redirects should override this. |
258 | * |
259 | * @stable to override |
260 | * @see Content::updateRedirect |
261 | * @since 1.21 |
262 | * @param Title $target |
263 | * @return Content $this |
264 | * |
265 | */ |
266 | public function updateRedirect( Title $target ) { |
267 | return $this; |
268 | } |
269 | |
270 | /** |
271 | * @stable to override |
272 | * @see Content::getSection |
273 | * @since 1.21 |
274 | * @param string|int $sectionId |
275 | * @return null |
276 | */ |
277 | public function getSection( $sectionId ) { |
278 | return null; |
279 | } |
280 | |
281 | /** |
282 | * @stable to override |
283 | * @see Content::replaceSection |
284 | * @since 1.21 |
285 | * @param string|int|null|false $sectionId |
286 | * @param Content $with |
287 | * @param string $sectionTitle |
288 | * @return null |
289 | * |
290 | */ |
291 | public function replaceSection( $sectionId, Content $with, $sectionTitle = '' ) { |
292 | return null; |
293 | } |
294 | |
295 | /** |
296 | * @stable to override |
297 | * @see Content::addSectionHeader |
298 | * @since 1.21 |
299 | * @param string $header |
300 | * @return Content $this |
301 | */ |
302 | public function addSectionHeader( $header ) { |
303 | return $this; |
304 | } |
305 | |
306 | /** |
307 | * This default implementation always returns false. Subclasses may override |
308 | * this to supply matching logic. |
309 | * |
310 | * @stable to override |
311 | * @see Content::matchMagicWord |
312 | * @since 1.21 |
313 | * @param MagicWord $word |
314 | * @return bool |
315 | */ |
316 | public function matchMagicWord( MagicWord $word ) { |
317 | return false; |
318 | } |
319 | |
320 | /** |
321 | * This base implementation calls the hook ConvertContent to enable custom conversions. |
322 | * Subclasses may override this to implement conversion for "their" content model. |
323 | * |
324 | * @stable to override |
325 | * @see Content::convert() |
326 | * @param string $toModel |
327 | * @param string $lossy |
328 | * @return Content|false |
329 | */ |
330 | public function convert( $toModel, $lossy = '' ) { |
331 | if ( $this->getModel() === $toModel ) { |
332 | // nothing to do, shorten out. |
333 | return $this; |
334 | } |
335 | |
336 | $lossy = ( $lossy === 'lossy' ); // string flag, convert to boolean for convenience |
337 | $result = false; |
338 | |
339 | ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) ) |
340 | ->onConvertContent( $this, $toModel, $lossy, $result ); |
341 | |
342 | return $result; |
343 | } |
344 | |
345 | } |
346 | |
347 | /** @deprecated class alias since 1.43 */ |
348 | class_alias( AbstractContent::class, 'AbstractContent' ); |