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