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