Merge "Rewrite pref cleanup script"
[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 * @return mixed The native representation of the content. Could be a
81 * string, a nested array structure, an object, a binary blob...
82 * anything, really.
83 *
84 * @note Caller must be aware of content model!
85 */
86 public function getNativeData();
87
88 /**
89 * Returns the content's nominal size in "bogo-bytes".
90 *
91 * @return int
92 */
93 public function getSize();
94
95 /**
96 * Returns the ID of the content model used by this Content object.
97 * Corresponds to the CONTENT_MODEL_XXX constants.
98 *
99 * @since 1.21
100 *
101 * @return string The model id
102 */
103 public function getModel();
104
105 /**
106 * Convenience method that returns the ContentHandler singleton for handling
107 * the content model that this Content object uses.
108 *
109 * Shorthand for ContentHandler::getForContent( $this )
110 *
111 * @since 1.21
112 *
113 * @return ContentHandler
114 */
115 public function getContentHandler();
116
117 /**
118 * Convenience method that returns the default serialization format for the
119 * content model that this Content object uses.
120 *
121 * Shorthand for $this->getContentHandler()->getDefaultFormat()
122 *
123 * @since 1.21
124 *
125 * @return string
126 */
127 public function getDefaultFormat();
128
129 /**
130 * Convenience method that returns the list of serialization formats
131 * supported for the content model that this Content object uses.
132 *
133 * Shorthand for $this->getContentHandler()->getSupportedFormats()
134 *
135 * @since 1.21
136 *
137 * @return string[] List of supported serialization formats
138 */
139 public function getSupportedFormats();
140
141 /**
142 * Returns true if $format is a supported serialization format for this
143 * Content object, false if it isn't.
144 *
145 * Note that this should always return true if $format is null, because null
146 * stands for the default serialization.
147 *
148 * Shorthand for $this->getContentHandler()->isSupportedFormat( $format )
149 *
150 * @since 1.21
151 *
152 * @param string $format The serialization format to check.
153 *
154 * @return bool Whether the format is supported
155 */
156 public function isSupportedFormat( $format );
157
158 /**
159 * Convenience method for serializing this Content object.
160 *
161 * Shorthand for $this->getContentHandler()->serializeContent( $this, $format )
162 *
163 * @since 1.21
164 *
165 * @param string $format The desired serialization format, or null for the default format.
166 *
167 * @return string Serialized form of this Content object.
168 */
169 public function serialize( $format = null );
170
171 /**
172 * Returns true if this Content object represents empty content.
173 *
174 * @since 1.21
175 *
176 * @return bool Whether this Content object is empty
177 */
178 public function isEmpty();
179
180 /**
181 * Returns whether the content is valid. This is intended for local validity
182 * checks, not considering global consistency.
183 *
184 * Content needs to be valid before it can be saved.
185 *
186 * This default implementation always returns true.
187 *
188 * @since 1.21
189 *
190 * @return bool
191 */
192 public function isValid();
193
194 /**
195 * Returns true if this Content objects is conceptually equivalent to the
196 * given Content object.
197 *
198 * Contract:
199 *
200 * - Will return false if $that is null.
201 * - Will return true if $that === $this.
202 * - Will return false if $that->getModel() != $this->getModel().
203 * - Will return false if $that->getNativeData() is not equal to $this->getNativeData(),
204 * where the meaning of "equal" depends on the actual data model.
205 *
206 * Implementations should be careful to make equals() transitive and reflexive:
207 *
208 * - $a->equals( $b ) <=> $b->equals( $a )
209 * - $a->equals( $b ) && $b->equals( $c ) ==> $a->equals( $c )
210 *
211 * @since 1.21
212 *
213 * @param Content $that The Content object to compare to.
214 *
215 * @return bool True if this Content object is equal to $that, false otherwise.
216 */
217 public function equals( Content $that = null );
218
219 /**
220 * Return a copy of this Content object. The following must be true for the
221 * object returned:
222 *
223 * if $copy = $original->copy()
224 *
225 * - get_class($original) === get_class($copy)
226 * - $original->getModel() === $copy->getModel()
227 * - $original->equals( $copy )
228 *
229 * If and only if the Content object is immutable, the copy() method can and
230 * should return $this. That is, $copy === $original may be true, but only
231 * for immutable content objects.
232 *
233 * @since 1.21
234 *
235 * @return Content A copy of this object
236 */
237 public function copy();
238
239 /**
240 * Returns true if this content is countable as a "real" wiki page, provided
241 * that it's also in a countable location (e.g. a current revision in the
242 * main namespace).
243 *
244 * @since 1.21
245 *
246 * @param bool|null $hasLinks If it is known whether this content contains
247 * links, provide this information here, to avoid redundant parsing to
248 * find out.
249 *
250 * @return bool
251 */
252 public function isCountable( $hasLinks = null );
253
254 /**
255 * Parse the Content object and generate a ParserOutput from the result.
256 * $result->getText() can be used to obtain the generated HTML. If no HTML
257 * is needed, $generateHtml can be set to false; in that case,
258 * $result->getText() may return null.
259 *
260 * @note To control which options are used in the cache key for the
261 * generated parser output, implementations of this method
262 * may call ParserOutput::recordOption() on the output object.
263 *
264 * @param Title $title The page title to use as a context for rendering.
265 * @param int $revId Optional revision ID being rendered.
266 * @param ParserOptions $options Any parser options.
267 * @param bool $generateHtml Whether to generate HTML (default: true). If false,
268 * the result of calling getText() on the ParserOutput object returned by
269 * this method is undefined.
270 *
271 * @since 1.21
272 *
273 * @return ParserOutput
274 */
275 public function getParserOutput( Title $title, $revId = null,
276 ParserOptions $options = null, $generateHtml = true );
277
278 // TODO: make RenderOutput and RenderOptions base classes
279
280 /**
281 * Returns a list of DataUpdate objects for recording information about this
282 * Content in some secondary data store. If the optional second argument,
283 * $old, is given, the updates may model only the changes that need to be
284 * made to replace information about the old content with information about
285 * the new content.
286 *
287 * This default implementation calls
288 * $this->getParserOutput( $content, $title, null, null, false ),
289 * and then calls getSecondaryDataUpdates( $title, $recursive ) on the
290 * resulting ParserOutput object.
291 *
292 * Subclasses may implement this to determine the necessary updates more
293 * efficiently, or make use of information about the old content.
294 *
295 * @note Implementations should call the SecondaryDataUpdates hook, like
296 * AbstractContent does.
297 *
298 * @param Title $title The context for determining the necessary updates
299 * @param Content $old An optional Content object representing the
300 * previous content, i.e. the content being replaced by this Content
301 * object.
302 * @param bool $recursive Whether to include recursive updates (default:
303 * false).
304 * @param ParserOutput $parserOutput Optional ParserOutput object.
305 * Provide if you have one handy, to avoid re-parsing of the content.
306 *
307 * @return DataUpdate[] A list of DataUpdate objects for putting information
308 * about this content object somewhere.
309 *
310 * @since 1.21
311 */
312 public function getSecondaryDataUpdates( Title $title, Content $old = null,
313 $recursive = true, ParserOutput $parserOutput = null );
314
315 /**
316 * Construct the redirect destination from this content and return an
317 * array of Titles, or null if this content doesn't represent a redirect.
318 * The last element in the array is the final destination after all redirects
319 * have been resolved (up to $wgMaxRedirects times).
320 *
321 * @since 1.21
322 *
323 * @return Title[]|null List of Titles, with the destination last.
324 */
325 public function getRedirectChain();
326
327 /**
328 * Construct the redirect destination from this content and return a Title,
329 * or null if this content doesn't represent a redirect.
330 * This will only return the immediate redirect target, useful for
331 * the redirect table and other checks that don't need full recursion.
332 *
333 * @since 1.21
334 *
335 * @return Title|null The corresponding Title.
336 */
337 public function getRedirectTarget();
338
339 /**
340 * Construct the redirect destination from this content and return the
341 * Title, or null if this content doesn't represent a redirect.
342 *
343 * This will recurse down $wgMaxRedirects times or until a non-redirect
344 * target is hit in order to provide (hopefully) the Title of the final
345 * destination instead of another redirect.
346 *
347 * There is usually no need to override the default behavior, subclasses that
348 * want to implement redirects should override getRedirectTarget().
349 *
350 * @since 1.21
351 *
352 * @return Title|null
353 */
354 public function getUltimateRedirectTarget();
355
356 /**
357 * Returns whether this Content represents a redirect.
358 * Shorthand for getRedirectTarget() !== null.
359 *
360 * @since 1.21
361 *
362 * @return bool
363 */
364 public function isRedirect();
365
366 /**
367 * If this Content object is a redirect, this method updates the redirect target.
368 * Otherwise, it does nothing.
369 *
370 * @since 1.21
371 *
372 * @param Title $target The new redirect target
373 *
374 * @return Content A new Content object with the updated redirect (or $this
375 * if this Content object isn't a redirect)
376 */
377 public function updateRedirect( Title $target );
378
379 /**
380 * Returns the section with the given ID.
381 *
382 * @since 1.21
383 *
384 * @param string|int $sectionId Section identifier as a number or string
385 * (e.g. 0, 1 or 'T-1'). The ID "0" retrieves the section before the first heading, "1" the
386 * text between the first heading (included) and the second heading (excluded), etc.
387 *
388 * @return Content|bool|null The section, or false if no such section
389 * exist, or null if sections are not supported.
390 */
391 public function getSection( $sectionId );
392
393 /**
394 * Replaces a section of the content and returns a Content object with the
395 * section replaced.
396 *
397 * @since 1.21
398 *
399 * @param string|int|null|bool $sectionId Section identifier as a number or string
400 * (e.g. 0, 1 or 'T-1'), null/false or an empty string for the whole page
401 * or 'new' for a new section.
402 * @param Content $with New content of the section
403 * @param string $sectionTitle New section's subject, only if $section is 'new'
404 *
405 * @return string|null Complete article text, or null if error
406 */
407 public function replaceSection( $sectionId, Content $with, $sectionTitle = '' );
408
409 /**
410 * Returns a Content object with pre-save transformations applied (or this
411 * object if no transformations apply).
412 *
413 * @since 1.21
414 *
415 * @param Title $title
416 * @param User $user
417 * @param ParserOptions $parserOptions
418 *
419 * @return Content
420 */
421 public function preSaveTransform( Title $title, User $user, ParserOptions $parserOptions );
422
423 /**
424 * Returns a new WikitextContent object with the given section heading
425 * prepended, if supported. The default implementation just returns this
426 * Content object unmodified, ignoring the section header.
427 *
428 * @since 1.21
429 *
430 * @param string $header
431 *
432 * @return Content
433 */
434 public function addSectionHeader( $header );
435
436 /**
437 * Returns a Content object with preload transformations applied (or this
438 * object if no transformations apply).
439 *
440 * @since 1.21
441 *
442 * @param Title $title
443 * @param ParserOptions $parserOptions
444 * @param array $params
445 *
446 * @return Content
447 */
448 public function preloadTransform( Title $title, ParserOptions $parserOptions, $params = [] );
449
450 /**
451 * Prepare Content for saving. Called before Content is saved by WikiPage::doEditContent() and in
452 * similar places.
453 *
454 * This may be used to check the content's consistency with global state. This function should
455 * NOT write any information to the database.
456 *
457 * Note that this method will usually be called inside the same transaction
458 * bracket that will be used to save the new revision.
459 *
460 * Note that this method is called before any update to the page table is
461 * performed. This means that $page may not yet know a page ID.
462 *
463 * @since 1.21
464 *
465 * @param WikiPage $page The page to be saved.
466 * @param int $flags Bitfield for use with EDIT_XXX constants, see WikiPage::doEditContent()
467 * @param int $parentRevId The ID of the current revision
468 * @param User $user
469 *
470 * @return Status A status object indicating whether the content was
471 * successfully prepared for saving. If the returned status indicates
472 * an error, a rollback will be performed and the transaction aborted.
473 *
474 * @see WikiPage::doEditContent()
475 */
476 public function prepareSave( WikiPage $page, $flags, $parentRevId, User $user );
477
478 /**
479 * Returns a list of updates to perform when this content is deleted.
480 * The necessary updates may be taken from the Content object, or depend on
481 * the current state of the database.
482 *
483 * @since 1.21
484 *
485 * @param WikiPage $page The deleted page
486 * @param ParserOutput|null $parserOutput Optional parser output object
487 * for efficient access to meta-information about the content object.
488 * Provide if you have one handy.
489 *
490 * @return DeferrableUpdate[] A list of DeferrableUpdate instances that will clean up the
491 * database after deletion.
492 */
493 public function getDeletionUpdates( WikiPage $page,
494 ParserOutput $parserOutput = null );
495
496 /**
497 * Returns true if this Content object matches the given magic word.
498 *
499 * @since 1.21
500 *
501 * @param MagicWord $word The magic word to match
502 *
503 * @return bool Whether this Content object matches the given magic word.
504 */
505 public function matchMagicWord( MagicWord $word );
506
507 /**
508 * Converts this content object into another content object with the given content model,
509 * if that is possible.
510 *
511 * @param string $toModel The desired content model, use the CONTENT_MODEL_XXX flags.
512 * @param string $lossy Optional flag, set to "lossy" to allow lossy conversion. If lossy
513 * conversion is not allowed, full round-trip conversion is expected to work without losing
514 * information.
515 *
516 * @return Content|bool A content object with the content model $toModel, or false if
517 * that conversion is not supported.
518 */
519 public function convert( $toModel, $lossy = '' );
520 // @todo ImagePage and CategoryPage interfere with per-content action handlers
521 // @todo nice&sane integration of GeSHi syntax highlighting
522 // [11:59] <vvv> Hooks are ugly; make CodeHighlighter interface and a
523 // config to set the class which handles syntax highlighting
524 // [12:00] <vvv> And default it to a DummyHighlighter
525
526 }