Use Title, not IContextSource; remove createArticle, etc.
[lhc/web/wiklou.git] / includes / Content.php
index 91a0784..9463c91 100644 (file)
@@ -17,12 +17,16 @@ abstract class Content {
        protected $model_id;
 
        /**
+        * @since WD.1
+        *
         * @return String a string representing the content in a way useful for building a full text search index.
         *         If no useful representation exists, this method returns an empty string.
         */
        public abstract function getTextForSearchIndex( );
 
        /**
+        * @since WD.1
+        *
         * @return String the wikitext to include when another page includes this  content, or false if the content is not
         *         includable in a wikitext page.
         *
@@ -34,6 +38,8 @@ abstract class Content {
        /**
         * Returns a textual representation of the content suitable for use in edit summaries and log messages.
         *
+        * @since WD.1
+        *
         * @param int $maxlength maximum length of the summary text
         * @return String the summary text
         */
@@ -43,6 +49,8 @@ abstract class Content {
         * Returns native represenation of the data. Interpretation depends on the data model used,
         * as given by getDataModel().
         *
+        * @since WD.1
+        *
         * @return mixed the native representation of the content. Could be a string, a nested array
         *         structure, an object, a binary blob... anything, really.
         *
@@ -68,6 +76,8 @@ abstract class Content {
         * Returns the id of the content model used by this content objects.
         * Corresponds to the CONTENT_MODEL_XXX constants.
         *
+        * @since WD.1
+        *
         * @return int the model id
         */
        public function getModel() {
@@ -95,6 +105,8 @@ abstract class Content {
         *
         * Shorthand for ContentHandler::getForContent( $this )
         *
+        * @since WD.1
+        *
         * @return ContentHandler
         */
        public function getContentHandler() {
@@ -107,6 +119,8 @@ abstract class Content {
         *
         * Shorthand for $this->getContentHandler()->getDefaultFormat()
         *
+        * @since WD.1
+        *
         * @return ContentHandler
         */
        public function getDefaultFormat() {
@@ -119,6 +133,8 @@ abstract class Content {
         *
         * Shorthand for $this->getContentHandler()->getSupportedFormats()
         *
+        * @since WD.1
+        *
         * @return array of supported serialization formats
         */
        public function getSupportedFormats() {
@@ -134,6 +150,8 @@ abstract class Content {
         *
         * Shorthand for $this->getContentHandler()->isSupportedFormat( $format )
         *
+        * @since WD.1
+        *
         * @param String $format the format to check
         * @return bool whether the format is supported
         */
@@ -162,6 +180,8 @@ abstract class Content {
         *
         * Shorthand for $this->getContentHandler()->serializeContent( $this, $format )
         *
+        * @since WD.1
+        *
         * @param null|String $format the desired serialization format (or null for the default format).
         * @return String serialized form of this Content object
         */
@@ -172,12 +192,39 @@ abstract class Content {
        /**
         * Returns true if this Content object represents empty content.
         *
+        * @since WD.1
+        *
         * @return bool whether this Content object is empty
         */
        public function isEmpty() {
                return $this->getSize() == 0;
        }
 
+       /**
+        * Returns if the content is valid.
+        * It needs to be valid before it can be saved.
+        *
+        * @since WD.1
+        *
+        * @return boolean
+        */
+       public function isValid() {
+               // TODO
+               return true;
+       }
+
+       /**
+        * Diff the content object with what is currently stored in the database.
+        * If it is not currently stored, it will be diffed with an empty object.
+        *
+        * @since WD.diff
+        *
+        * @return ContentDiff
+        */
+       public function diffToDatabase() {
+               // TODO
+       }
+
        /**
         * Returns true if this Content objects is conceptually equivalent to the given Content object.
         *
@@ -192,6 +239,8 @@ abstract class Content {
         * * $a->equals( $b ) <=> $b->equals( $b )
         * * $a->equals( $b ) &&  $b->equals( $c ) ==> $a->equals( $c )
         *
+        * @since WD.1
+        *
         * @param Content $that the Content object to compare to
         * @return bool true if this Content object is euqual to $that, false otherwise.
         */
@@ -223,6 +272,8 @@ abstract class Content {
         * return $this. That is,  $copy === $original may be true, but only for imutable content
         * objects.
         *
+        * @since WD.1
+        *
         * @return Content. A copy of this object
         */
        public abstract function copy( );
@@ -231,6 +282,8 @@ abstract class Content {
         * Returns true if this content is countable as a "real" wiki page, provided
         * that it's also in a countable location (e.g. a current revision in the main namespace).
         *
+        * @since WD.1
+        *
         * @param $hasLinks Bool: if it is known whether this content contains links, provide this information here,
         *                        to avoid redundant parsing to find out.
         * @return boolean
@@ -238,16 +291,43 @@ abstract class Content {
        public abstract function isCountable( $hasLinks = null ) ;
 
        /**
-        * @param IContextSource $context
+        * @param Title $title
         * @param null $revId
         * @param null|ParserOptions $options
         * @param Boolean $generateHtml whether to generate Html (default: true). If false,
         *        the result of calling getText() on the ParserOutput object returned by
         *        this method is undefined.
         *
+        * @since WD.1
+        *
         * @return ParserOutput
         */
-       public abstract function getParserOutput( IContextSource $context, $revId = null, ParserOptions $options = NULL, $generateHtml = true );
+       public abstract function getParserOutput( Title $title, $revId = null, ParserOptions $options = null, $generateHtml = true );
+
+       /**
+        * Returns a list of DataUpdate objects for recording information about this Content in some secondary
+        * data store. If the optional second argument, $old, is given, the updates may model only the changes that
+        * need to be made to replace information about the old content with infomration about the new content.
+        *
+        * This default implementation calls $this->getParserOutput( $title, null, null, false ), and then
+        * calls getSecondaryDataUpdates( $title, $recursive ) on the resulting ParserOutput object.
+        *
+        * Subclasses may implement this to determine the necessary updates more efficiently, or make use of information
+        * about the old content.
+        *
+        * @param Title $title the context for determining the necessary updates
+        * @param Content|null $old a Content object representing the previous content, i.e. the content being
+        *                     replaced by this Content object.
+        * @param bool $recursive whether to include recursive updates (default: false).
+        *
+        * @return Array. A list of DataUpdate objects for putting information about this content object somewhere.
+        *
+        * @since WD.1
+        */
+       public function getSecondaryDataUpdates( Title $title, Content $old = null, $recursive = false ) {
+               $po = $this->getParserOutput( $title, null, null, false );
+               return $po->getSecondaryDataUpdates( $title, $recursive );
+       }
 
        /**
         * Construct the redirect destination from this content and return an
@@ -255,6 +335,8 @@ abstract class Content {
         * The last element in the array is the final destination after all redirects
         * have been resolved (up to $wgMaxRedirects times).
         *
+        * @since WD.1
+        *
         * @return Array of Titles, with the destination last
         */
        public function getRedirectChain() {
@@ -267,6 +349,8 @@ abstract class Content {
         * This will only return the immediate redirect target, useful for
         * the redirect table and other checks that don't need full recursion.
         *
+        * @since WD.1
+        *
         * @return Title: The corresponding Title
         */
        public function getRedirectTarget() {
@@ -279,14 +363,21 @@ abstract class Content {
         * This will recurse down $wgMaxRedirects times or until a non-redirect target is hit
         * in order to provide (hopefully) the Title of the final destination instead of another redirect.
         *
+        * @since WD.1
+        *
         * @return Title
         */
        public function getUltimateRedirectTarget() {
                return null;
        }
 
+       /**
+        * @since WD.1
+        *
+        * @return bool
+        */
        public function isRedirect() {
-               return $this->getRedirectTarget() != null;
+               return $this->getRedirectTarget() !== null;
        }
 
        /**
@@ -294,6 +385,8 @@ abstract class Content {
         *
         * The default implementation returns null.
         *
+        * @since WD.1
+        *
         * @param String $sectionId the section's id, given as a numeric string. The id "0" retrieves the section before
         *          the first heading, "1" the text between the first heading (inluded) and the second heading (excluded), etc.
         * @return Content|Boolean|null the section, or false if no such section exist, or null if sections are not supported
@@ -305,6 +398,8 @@ abstract class Content {
        /**
         * Replaces a section of the content and returns a Content object with the section replaced.
         *
+        * @since WD.1
+        *
         * @param $section empty/null/false or a section number (0, 1, 2, T1, T2...), or "new"
         * @param $with Content: new content of the section
         * @param $sectionTitle String: new section's subject, only if $section is 'new'
@@ -317,6 +412,8 @@ abstract class Content {
        /**
         * Returns a Content object with pre-save transformations applied (or this object if no transformations apply).
         *
+        * @since WD.1
+        *
         * @param Title $title
         * @param User $user
         * @param null|ParserOptions $popts
@@ -330,6 +427,8 @@ abstract class Content {
         * Returns a new WikitextContent object with the given section heading prepended, if supported.
         * The default implementation just returns this Content object unmodified, ignoring the section header.
         *
+        * @since WD.1
+        *
         * @param $header String
         * @return Content
         */
@@ -340,6 +439,8 @@ abstract class Content {
        /**
         * Returns a Content object with preload transformations applied (or this object if no transformations apply).
         *
+        * @since WD.1
+        *
         * @param Title $title
         * @param null|ParserOptions $popts
         * @return Content
@@ -370,6 +471,8 @@ abstract class Content {
  * Content object implementation for representing flat text.
  *
  * TextContent instances are imutable
+ *
+ * @since WD.1
  */
 abstract class TextContent extends Content {
 
@@ -460,7 +563,7 @@ abstract class TextContent extends Content {
         *
         * @return ParserOutput representing the HTML form of the text
         */
-       public function getParserOutput( IContextSource $context, $revId = null, ParserOptions $options = null, $generateHtml = true ) {
+       public function getParserOutput( Title $title, $revId = null, ParserOptions $options = null, $generateHtml = true ) {
                # generic implementation, relying on $this->getHtml()
 
                if ( $generateHtml ) $html = $this->getHtml( $options );
@@ -475,6 +578,9 @@ abstract class TextContent extends Content {
 
 }
 
+/**
+ * @since WD.1
+ */
 class WikitextContent extends TextContent {
 
        public function __construct( $text ) {
@@ -497,14 +603,14 @@ class WikitextContent extends TextContent {
         *
         * @return ParserOutput representing the HTML form of the text
         */
-       public function getParserOutput( IContextSource $context, $revId = null, ParserOptions $options = null, $generateHtml = true ) {
+       public function getParserOutput( Title $title, $revId = null, ParserOptions $options = null, $generateHtml = true ) {
                global $wgParser;
 
                if ( !$options ) {
-                       $options = ParserOptions::newFromUserAndLang( $context->getUser(), $context->getLanguage() );
+                       $options = new ParserOptions();
                }
 
-               $po = $wgParser->parse( $this->mText, $context->getTitle(), $options, true, true, $revId );
+               $po = $wgParser->parse( $this->mText, $title, $options, true, true, $revId );
 
                return $po;
        }
@@ -642,7 +748,7 @@ class WikitextContent extends TextContent {
         *
         * @return bool true if the content is countable
         */
-       public function isCountable( $hasLinks = null, IContextSource $context = null ) {
+       public function isCountable( $hasLinks = null, Title $title = null ) {
                global $wgArticleCountMethod, $wgRequest;
 
                if ( $this->isRedirect( ) ) {
@@ -658,12 +764,12 @@ class WikitextContent extends TextContent {
                                return strpos( $text,  ',' ) !== false;
                        case 'link':
                                if ( $hasLinks === null ) { # not known, find out
-                                       if ( !$context ) { # make dummy context
-                                               //XXX: caller of this method often knows the title, but not a context...
-                                               $context = new RequestContext( $wgRequest );
+                                       if ( !$title ) {
+                                               $context = RequestContext::getMain();
+                                               $title = $context->getTitle();
                                        }
 
-                                       $po = $this->getParserOutput( $context, null, null, false );
+                                       $po = $this->getParserOutput( $title, null, null, false );
                                        $links = $po->getLinks();
                                        $hasLinks = !empty( $links );
                                }
@@ -684,6 +790,9 @@ class WikitextContent extends TextContent {
 
 }
 
+/**
+ * @since WD.1
+ */
 class MessageContent extends TextContent {
        public function __construct( $msg_key, $params = null, $options = null ) {
                parent::__construct(null, CONTENT_MODEL_WIKITEXT); #XXX: messages may be wikitext, html or plain text! and maybe even something else entirely.
@@ -725,7 +834,9 @@ class MessageContent extends TextContent {
 
 }
 
-
+/**
+ * @since WD.1
+ */
 class JavaScriptContent extends TextContent {
        public function __construct( $text ) {
                parent::__construct($text, CONTENT_MODEL_JAVASCRIPT);
@@ -742,6 +853,9 @@ class JavaScriptContent extends TextContent {
 
 }
 
+/**
+ * @since WD.1
+ */
 class CssContent extends TextContent {
        public function __construct( $text ) {
                parent::__construct($text, CONTENT_MODEL_CSS);