Merge "Add .pipeline/ with dev image variant"
[lhc/web/wiklou.git] / includes / content / Content.php
1 <?php
2 /**
3 * A content object represents page content, e.g. the text to show on a page.
4 * Content objects have no knowledge about how they relate to wiki pages.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * http://www.gnu.org/copyleft/gpl.html
20 *
21 * @since 1.21
22 *
23 * @file
24 * @ingroup Content
25 *
26 * @author Daniel Kinzler
27 */
28
29 /**
30 * Base interface for content objects.
31 *
32 * @ingroup Content
33 */
34 interface Content {
35
36 /**
37 * @since 1.21
38 *
39 * @return string A string representing the content in a way useful for
40 * building a full text search index. If no useful representation exists,
41 * this method returns an empty string.
42 *
43 * @todo Test that this actually works
44 * @todo Make sure this also works with LuceneSearch / WikiSearch
45 */
46 public function getTextForSearchIndex();
47
48 /**
49 * @since 1.21
50 *
51 * @return string|bool The wikitext to include when another page includes this
52 * content, or false if the content is not includable in a wikitext page.
53 *
54 * @todo Allow native handling, bypassing wikitext representation, like
55 * for includable special pages.
56 * @todo Allow transclusion into other content models than Wikitext!
57 * @todo Used in WikiPage and MessageCache to get message text. Not so
58 * nice. What should we use instead?!
59 */
60 public function getWikitextForTransclusion();
61
62 /**
63 * Returns a textual representation of the content suitable for use in edit
64 * summaries and log messages.
65 *
66 * @since 1.21
67 *
68 * @param int $maxLength Maximum length of the summary text.
69 *
70 * @return string The summary text.
71 */
72 public function getTextForSummary( $maxLength = 250 );
73
74 /**
75 * Returns native representation of the data. Interpretation depends on
76 * the data model used, as given by getDataModel().
77 *
78 * @since 1.21
79 *
80 * @deprecated since 1.33 use getText() for TextContent instances.
81 * For other content models, use specialized getters.
82 *
83 * @return mixed The native representation of the content. Could be a
84 * string, a nested array structure, an object, a binary blob...
85 * anything, really.
86 *
87 * @note Caller must be aware of content model!
88 */
89 public function getNativeData();
90
91 /**
92 * Returns the content's nominal size in "bogo-bytes".
93 *
94 * @return int
95 */
96 public function getSize();
97
98 /**
99 * Returns the ID of the content model used by this Content object.
100 * Corresponds to the CONTENT_MODEL_XXX constants.
101 *
102 * @since 1.21
103 *
104 * @return string The model id
105 */
106 public function getModel();
107
108 /**
109 * Convenience method that returns the ContentHandler singleton for handling
110 * the content model that this Content object uses.
111 *
112 * Shorthand for ContentHandler::getForContent( $this )
113 *
114 * @since 1.21
115 *
116 * @return ContentHandler
117 */
118 public function getContentHandler();
119
120 /**
121 * Convenience method that returns the default serialization format for the
122 * content model that this Content object uses.
123 *
124 * Shorthand for $this->getContentHandler()->getDefaultFormat()
125 *
126 * @since 1.21
127 *
128 * @return string
129 */
130 public function getDefaultFormat();
131
132 /**
133 * Convenience method that returns the list of serialization formats
134 * supported for the content model that this Content object uses.
135 *
136 * Shorthand for $this->getContentHandler()->getSupportedFormats()
137 *
138 * @since 1.21
139 *
140 * @return string[] List of supported serialization formats
141 */
142 public function getSupportedFormats();
143
144 /**
145 * Returns true if $format is a supported serialization format for this
146 * Content object, false if it isn't.
147 *
148 * Note that this should always return true if $format is null, because null
149 * stands for the default serialization.
150 *
151 * Shorthand for $this->getContentHandler()->isSupportedFormat( $format )
152 *
153 * @since 1.21
154 *
155 * @param string $format The serialization format to check.
156 *
157 * @return bool Whether the format is supported
158 */
159 public function isSupportedFormat( $format );
160
161 /**
162 * Convenience method for serializing this Content object.
163 *
164 * Shorthand for $this->getContentHandler()->serializeContent( $this, $format )
165 *
166 * @since 1.21
167 *
168 * @param string|null $format The desired serialization format, or null for the default format.
169 *
170 * @return string Serialized form of this Content object.
171 */
172 public function serialize( $format = null );
173
174 /**
175 * Returns true if this Content object represents empty content.
176 *
177 * @since 1.21
178 *
179 * @return bool Whether this Content object is empty
180 */
181 public function isEmpty();
182
183 /**
184 * Returns whether the content is valid. This is intended for local validity
185 * checks, not considering global consistency.
186 *
187 * Content needs to be valid before it can be saved.
188 *
189 * This default implementation always returns true.
190 *
191 * @since 1.21
192 *
193 * @return bool
194 */
195 public function isValid();
196
197 /**
198 * Returns true if this Content objects is conceptually equivalent to the
199 * given Content object.
200 *
201 * Contract:
202 *
203 * - Will return false if $that is null.
204 * - Will return true if $that === $this.
205 * - Will return false if $that->getModel() !== $this->getModel().
206 * - Will return false if get_class( $that ) !== get_class( $this )
207 * - Should return false if $that->getModel() == $this->getModel() and
208 * $that is not semantically equivalent to $this, according to
209 * the data model defined by $this->getModel().
210 *
211 * Implementations should be careful to make equals() transitive and reflexive:
212 *
213 * - $a->equals( $b ) <=> $b->equals( $a )
214 * - $a->equals( $b ) && $b->equals( $c ) ==> $a->equals( $c )
215 *
216 * @since 1.21
217 *
218 * @param Content|null $that The Content object to compare to.
219 *
220 * @return bool True if this Content object is equal to $that, false otherwise.
221 */
222 public function equals( Content $that = null );
223
224 /**
225 * Return a copy of this Content object. The following must be true for the
226 * object returned:
227 *
228 * if $copy = $original->copy()
229 *
230 * - get_class($original) === get_class($copy)
231 * - $original->getModel() === $copy->getModel()
232 * - $original->equals( $copy )
233 *
234 * If and only if the Content object is immutable, the copy() method can and
235 * should return $this. That is, $copy === $original may be true, but only
236 * for immutable content objects.
237 *
238 * @since 1.21
239 *
240 * @return Content A copy of this object
241 */
242 public function copy();
243
244 /**
245 * Returns true if this content is countable as a "real" wiki page, provided
246 * that it's also in a countable location (e.g. a current revision in the
247 * main namespace).
248 *
249 * @see SlotRoleHandler::supportsArticleCount
250 *
251 * @since 1.21
252 *
253 * @param bool|null $hasLinks If it is known whether this content contains
254 * links, provide this information here, to avoid redundant parsing to
255 * find out.
256 *
257 * @return bool
258 */
259 public function isCountable( $hasLinks = null );
260
261 /**
262 * Parse the Content object and generate a ParserOutput from the result.
263 * $result->getText() can be used to obtain the generated HTML. If no HTML
264 * is needed, $generateHtml can be set to false; in that case,
265 * $result->getText() may return null.
266 *
267 * @note To control which options are used in the cache key for the
268 * generated parser output, implementations of this method
269 * may call ParserOutput::recordOption() on the output object.
270 *
271 * @param Title $title The page title to use as a context for rendering.
272 * @param int|null $revId ID of the revision being rendered.
273 * See Parser::parse() for the ramifications. (default: null)
274 * @param ParserOptions|null $options Any parser options.
275 * @param bool $generateHtml Whether to generate HTML (default: true). If false,
276 * the result of calling getText() on the ParserOutput object returned by
277 * this method is undefined.
278 *
279 * @since 1.21
280 *
281 * @return ParserOutput
282 */
283 public function getParserOutput( Title $title, $revId = null,
284 ParserOptions $options = null, $generateHtml = true );
285
286 // TODO: make RenderOutput and RenderOptions base classes
287
288 /**
289 * Returns a list of DataUpdate objects for recording information about this
290 * Content in some secondary data store. If the optional second argument,
291 * $old, is given, the updates may model only the changes that need to be
292 * made to replace information about the old content with information about
293 * the new content.
294 *
295 * @deprecated since 1.32, call and override
296 * ContentHandler::getSecondaryDataUpdates instead.
297 *
298 * @note Implementations should call the SecondaryDataUpdates hook, like
299 * AbstractContent does.
300 *
301 * @param Title $title The context for determining the necessary updates
302 * @param Content|null $old An optional Content object representing the
303 * previous content, i.e. the content being replaced by this Content
304 * object.
305 * @param bool $recursive Whether to include recursive updates (default:
306 * false).
307 * @param ParserOutput|null $parserOutput Optional ParserOutput object.
308 * Provide if you have one handy, to avoid re-parsing of the content.
309 *
310 * @return DataUpdate[] A list of DataUpdate objects for putting information
311 * about this content object somewhere.
312 *
313 * @since 1.21
314 */
315 public function getSecondaryDataUpdates( Title $title, Content $old = null,
316 $recursive = true, ParserOutput $parserOutput = null );
317
318 /**
319 * Construct the redirect destination from this content and return an
320 * array of Titles, or null if this content doesn't represent a redirect.
321 * The last element in the array is the final destination after all redirects
322 * have been resolved (up to $wgMaxRedirects times).
323 *
324 * @since 1.21
325 *
326 * @return Title[]|null List of Titles, with the destination last.
327 */
328 public function getRedirectChain();
329
330 /**
331 * Construct the redirect destination from this content and return a Title,
332 * or null if this content doesn't represent a redirect.
333 * This will only return the immediate redirect target, useful for
334 * the redirect table and other checks that don't need full recursion.
335 *
336 * @since 1.21
337 *
338 * @return Title|null The corresponding Title.
339 */
340 public function getRedirectTarget();
341
342 /**
343 * Construct the redirect destination from this content and return the
344 * Title, or null if this content doesn't represent a redirect.
345 *
346 * This will recurse down $wgMaxRedirects times or until a non-redirect
347 * target is hit in order to provide (hopefully) the Title of the final
348 * destination instead of another redirect.
349 *
350 * There is usually no need to override the default behavior, subclasses that
351 * want to implement redirects should override getRedirectTarget().
352 *
353 * @since 1.21
354 *
355 * @return Title|null
356 */
357 public function getUltimateRedirectTarget();
358
359 /**
360 * Returns whether this Content represents a redirect.
361 * Shorthand for getRedirectTarget() !== null.
362 *
363 * @see SlotRoleHandler::supportsRedirects
364 *
365 * @since 1.21
366 *
367 * @return bool
368 */
369 public function isRedirect();
370
371 /**
372 * If this Content object is a redirect, this method updates the redirect target.
373 * Otherwise, it does nothing.
374 *
375 * @since 1.21
376 *
377 * @param Title $target The new redirect target
378 *
379 * @return Content A new Content object with the updated redirect (or $this
380 * if this Content object isn't a redirect)
381 */
382 public function updateRedirect( Title $target );
383
384 /**
385 * Returns the section with the given ID.
386 *
387 * @since 1.21
388 *
389 * @param string|int $sectionId Section identifier as a number or string
390 * (e.g. 0, 1 or 'T-1'). The ID "0" retrieves the section before the first heading, "1" the
391 * text between the first heading (included) and the second heading (excluded), etc.
392 *
393 * @return Content|bool|null The section, or false if no such section
394 * exist, or null if sections are not supported.
395 */
396 public function getSection( $sectionId );
397
398 /**
399 * Replaces a section of the content and returns a Content object with the
400 * section replaced.
401 *
402 * @since 1.21
403 *
404 * @param string|int|null|bool $sectionId Section identifier as a number or string
405 * (e.g. 0, 1 or 'T-1'), null/false or an empty string for the whole page
406 * or 'new' for a new section.
407 * @param Content $with New content of the section
408 * @param string $sectionTitle New section's subject, only if $section is 'new'
409 *
410 * @return string|null Complete article text, or null if error
411 */
412 public function replaceSection( $sectionId, Content $with, $sectionTitle = '' );
413
414 /**
415 * Returns a Content object with pre-save transformations applied (or this
416 * object if no transformations apply).
417 *
418 * @since 1.21
419 *
420 * @param Title $title
421 * @param User $user
422 * @param ParserOptions $parserOptions
423 *
424 * @return Content
425 */
426 public function preSaveTransform( Title $title, User $user, ParserOptions $parserOptions );
427
428 /**
429 * Returns a new WikitextContent object with the given section heading
430 * prepended, if supported. The default implementation just returns this
431 * Content object unmodified, ignoring the section header.
432 *
433 * @since 1.21
434 *
435 * @param string $header
436 *
437 * @return Content
438 */
439 public function addSectionHeader( $header );
440
441 /**
442 * Returns a Content object with preload transformations applied (or this
443 * object if no transformations apply).
444 *
445 * @since 1.21
446 *
447 * @param Title $title
448 * @param ParserOptions $parserOptions
449 * @param array $params
450 *
451 * @return Content
452 */
453 public function preloadTransform( Title $title, ParserOptions $parserOptions, $params = [] );
454
455 /**
456 * Prepare Content for saving. Called before Content is saved by WikiPage::doEditContent() and in
457 * similar places.
458 *
459 * This may be used to check the content's consistency with global state. This function should
460 * NOT write any information to the database.
461 *
462 * Note that this method will usually be called inside the same transaction
463 * bracket that will be used to save the new revision.
464 *
465 * Note that this method is called before any update to the page table is
466 * performed. This means that $page may not yet know a page ID.
467 *
468 * @since 1.21
469 *
470 * @param WikiPage $page The page to be saved.
471 * @param int $flags Bitfield for use with EDIT_XXX constants, see WikiPage::doEditContent()
472 * @param int $parentRevId The ID of the current revision
473 * @param User $user
474 *
475 * @return Status A status object indicating whether the content was
476 * successfully prepared for saving. If the returned status indicates
477 * an error, a rollback will be performed and the transaction aborted.
478 *
479 * @see WikiPage::doEditContent()
480 */
481 public function prepareSave( WikiPage $page, $flags, $parentRevId, User $user );
482
483 /**
484 * Returns a list of updates to perform when this content is deleted.
485 * The necessary updates may be taken from the Content object, or depend on
486 * the current state of the database.
487 *
488 * @since 1.21
489 * @deprecated since 1.32, call and override
490 * ContentHandler::getDeletionUpdates instead.
491 *
492 * @param WikiPage $page The page the content was deleted from.
493 * @param ParserOutput|null $parserOutput Optional parser output object
494 * for efficient access to meta-information about the content object.
495 * Provide if you have one handy.
496 *
497 * @return DeferrableUpdate[] A list of DeferrableUpdate instances that will clean up the
498 * database after deletion.
499 */
500 public function getDeletionUpdates( WikiPage $page,
501 ParserOutput $parserOutput = null );
502
503 /**
504 * Returns true if this Content object matches the given magic word.
505 *
506 * @since 1.21
507 *
508 * @param MagicWord $word The magic word to match
509 *
510 * @return bool Whether this Content object matches the given magic word.
511 */
512 public function matchMagicWord( MagicWord $word );
513
514 /**
515 * Converts this content object into another content object with the given content model,
516 * if that is possible.
517 *
518 * @param string $toModel The desired content model, use the CONTENT_MODEL_XXX flags.
519 * @param string $lossy Optional flag, set to "lossy" to allow lossy conversion. If lossy
520 * conversion is not allowed, full round-trip conversion is expected to work without losing
521 * information.
522 *
523 * @return Content|bool A content object with the content model $toModel, or false if
524 * that conversion is not supported.
525 */
526 public function convert( $toModel, $lossy = '' );
527 // @todo ImagePage and CategoryPage interfere with per-content action handlers
528 // @todo nice&sane integration of GeSHi syntax highlighting
529 // [11:59] <vvv> Hooks are ugly; make CodeHighlighter interface and a
530 // config to set the class which handles syntax highlighting
531 // [12:00] <vvv> And default it to a DummyHighlighter
532
533 }