merged master (2012-09-11)
[lhc/web/wiklou.git] / includes / Content.php
index 38d2e27..3bce48e 100644 (file)
@@ -329,6 +329,18 @@ interface Content {
         */
        public function isRedirect();
 
+       /**
+        * If this Content object is a redirect, this method updates the redirect target.
+        * Otherwise, it does nothing.
+        *
+        * @since WD.1
+        *
+        * @param Title $target the new redirect target
+        *
+        * @return Content a new Content object with the updated redirect (or $this if this Content object isn't a redirect)
+        */
+       public function updateRedirect( Title $target );
+
        /**
         * Returns the section with the given ID.
         *
@@ -394,13 +406,18 @@ interface Content {
        public function preloadTransform( Title $title, ParserOptions $popts );
 
        /**
-        * Prepare Content for saving. Called before Content is saved by WikiPage::doEditContent().
-        * This may be used to store additional information in the database, or check the content's
-        * consistency with global state.
+        * Prepare Content for saving. Called before Content is saved by WikiPage::doEditContent() and in
+        * similar places.
+        *
+        * This may be used to check the content's consistency with global state. This function should
+        * NOT write any information to the database.
         *
-        * Note that this method will be called inside the same transaction bracket that will be used
+        * Note that this method will usually be called inside the same transaction bracket that will be used
         * to save the new revision.
         *
+        * Note that this method is called before any update to the page table is performed. This means that
+        * $page may not yet know a page ID.
+        *
         * @param WikiPage $page The page to be saved.
         * @param int      $flags bitfield for use with EDIT_XXX constants, see WikiPage::doEditContent()
         * @param int      $baseRevId the ID of the current revision
@@ -421,7 +438,7 @@ interface Content {
         *
         * @since WD.1
         *
-        * @param $title \Title the title of the deleted page
+        * @param $page \WikiPage the deleted page
         * @param $parserOutput null|\ParserOutput optional parser output object
         *    for efficient access to meta-information about the content object.
         *    Provide if you have one handy.
@@ -429,7 +446,7 @@ interface Content {
         * @return array A list of DataUpdate instances that will clean up the
         *    database after deletion.
         */
-       public function getDeletionUpdates( Title $title,
+       public function getDeletionUpdates( WikiPage $page,
                ParserOutput $parserOutput = null );
 
        /**
@@ -684,6 +701,8 @@ abstract class AbstractContent implements Content {
        }
 
        /**
+        * @see Content::isRedirect()
+        *
         * @since WD.1
         *
         * @return bool
@@ -692,6 +711,19 @@ abstract class AbstractContent implements Content {
                return $this->getRedirectTarget() !== null;
        }
 
+       /**
+        * @see Content::updateRedirect()
+        *
+        * This default implementation always returns $this.
+        *
+        * @since WD.1
+        *
+        * @return Content $this
+        */
+       public function updateRedirect( Title $target ) {
+               return $this;
+       }
+
        /**
         * @see Content::getSection()
         */
@@ -743,7 +775,7 @@ abstract class AbstractContent implements Content {
         *
         * @since WD.1
         *
-        * @param $title \Title the title of the deleted page
+        * @param $page \WikiPage the deleted page
         * @param $parserOutput null|\ParserOutput optional parser output object
         *    for efficient access to meta-information about the content object.
         *    Provide if you have one handy.
@@ -751,11 +783,11 @@ abstract class AbstractContent implements Content {
         * @return array A list of DataUpdate instances that will clean up the
         *    database after deletion.
         */
-       public function getDeletionUpdates( Title $title,
+       public function getDeletionUpdates( WikiPage $page,
                ParserOutput $parserOutput = null )
        {
                return array(
-                       new LinksDeletionUpdate( $title ),
+                       new LinksDeletionUpdate( $page ),
                );
        }
 
@@ -995,11 +1027,8 @@ class WikitextContent extends TextContent {
                        return $with; # XXX: copy first?
                } if ( $section == 'new' ) {
                        # Inserting a new section
-                       if ( $sectionTitle ) {
-                               $subject = wfMsgForContent( 'newsectionheaderdefaultlevel', $sectionTitle ) . "\n\n";
-                       } else {
-                               $subject = '';
-                       }
+                       $subject = $sectionTitle ? wfMessage( 'newsectionheaderdefaultlevel' )
+                               ->rawParams( $sectionTitle )->inContentLanguage()->text() . "\n\n" : '';
                        if ( wfRunHooks( 'PlaceNewSection', array( $this, $oldtext, $subject, &$text ) ) ) {
                                $text = strlen( trim( $oldtext ) ) > 0
                                        ? "{$oldtext}\n\n{$subject}{$text}"
@@ -1026,8 +1055,10 @@ class WikitextContent extends TextContent {
         * @return Content
         */
        public function addSectionHeader( $header ) {
-               $text = wfMsgForContent( 'newsectionheaderdefaultlevel', $header ) . "\n\n" . 
-                       $this->getNativeData();
+               $text = wfMessage( 'newsectionheaderdefaultlevel' )
+                               ->inContentLanguage()->params( $header )->text();
+               $text .= "\n\n";
+               $text .= $this->getNativeData();
 
                return new WikitextContent( $text );
        }
@@ -1108,6 +1139,33 @@ class WikitextContent extends TextContent {
                return null;
        }
 
+       /**
+        * @see   Content::updateRedirect()
+        *
+        * This implementation replaces the first link on the page with the given new target
+        * if this Content object is a redirect. Otherwise, this method returns $this.
+        *
+        * @since WD.1
+        *
+        * @param Title $target
+        *
+        * @return Content a new Content object with the updated redirect (or $this if this Content object isn't a redirect)
+        */
+       public function updateRedirect( Title $target ) {
+               if ( !$this->isRedirect() ) {
+                       return $this;
+               }
+
+               # Fix the text
+               # Remember that redirect pages can have categories, templates, etc.,
+               # so the regex has to be fairly general
+               $newText = preg_replace( '/ \[ \[  [^\]]*  \] \] /x',
+                       '[[' . $target->getFullText() . ']]',
+                       $this->getNativeData(), 1 );
+
+               return new WikitextContent( $newText );
+       }
+
        /**
         * Returns true if this content is not a redirect, and this content's text
         * is countable according to the criteria defined by $wgArticleCountMethod.
@@ -1216,52 +1274,134 @@ class WikitextContent extends TextContent {
 }
 
 /**
+ * Wrapper allowing us to handle a system message as a Content object. Note that this is generally *not* used
+ * to represent content from the MediaWiki namespace, and that there is no MessageContentHandler. MessageContent
+ * is just intended as glue for wrapping a message programatically.
+ *
  * @since WD.1
  */
-class MessageContent extends TextContent {
-       public function __construct( $msg_key, $params = null, $options = null ) {
-               # XXX: messages may be wikitext, html or plain text! and maybe even
-               # something else entirely.
-               parent::__construct( null, CONTENT_MODEL_WIKITEXT );
+class MessageContent extends AbstractContent {
 
-               $this->mMessageKey = $msg_key;
+       /**
+        * @var Message
+        */
+       protected $mMessage;
 
-               $this->mParameters = $params;
+       /**
+        * @param Message|String $msg    A Message object, or a message key
+        * @param array|null     $params An optional array of message parameters
+        */
+       public function __construct( $msg, $params = null ) {
+               # XXX: messages may be wikitext, html or plain text! and maybe even something else entirely.
+               parent::__construct( CONTENT_MODEL_WIKITEXT );
 
-               if ( is_null( $options ) ) {
-                       $options = array();
+               if ( is_string( $msg ) ) {
+                       $this->mMessage = wfMessage( $msg );
+               } else {
+                       $this->mMessage = clone $msg;
                }
-               elseif ( is_string( $options ) ) {
-                       $options = array( $options );
+
+               if ( $params ) {
+                       $this->mMessage = $this->mMessage->params( $params );
                }
+       }
 
-               $this->mOptions = $options;
+       /**
+        * Returns the message as rendered HTML
+        *
+        * @return string The message text, parsed into html
+        */
+       public function getHtml() {
+               return $this->mMessage->parse();
        }
 
        /**
-        * Returns the message as rendered HTML, using the options supplied to the
-        * constructor plus "parse".
-        * @param   the message text, parsed
+        * Returns the message as rendered HTML
+        *
+        * @return string The message text, parsed into html
         */
-       public function getHtml(  ) {
-               $opt = array_merge( $this->mOptions, array( 'parse' ) );
+       public function getWikitext() {
+               return $this->mMessage->text();
+       }
 
-               return wfMsgExt( $this->mMessageKey, $this->mParameters, $opt );
+       /**
+        * Returns the message object, with any parameters already substituted.
+        *
+        * @return Message The message object.
+        */
+       public function getNativeData() {
+               //NOTE: Message objects are mutable. Cloning here makes MessageContent immutable.
+               return clone $this->mMessage;
+       }
+
+       /**
+        * @see Content::getTextForSearchIndex
+        */
+       public function getTextForSearchIndex() {
+               return $this->mMessage->plain();
        }
 
+       /**
+        * @see Content::getWikitextForTransclusion
+        */
+       public function getWikitextForTransclusion() {
+               return $this->getWikitext();
+       }
 
        /**
-        * Returns the message as raw text, using the options supplied to the
-        * constructor minus "parse" and "parseinline".
+        * @see Content::getTextForSummary
+        */
+       public function getTextForSummary( $maxlength = 250 ) {
+               return substr( $this->mMessage->plain(), 0, $maxlength );
+       }
+
+       /**
+        * @see Content::getSize
         *
-        * @param   the message text, unparsed.
+        * @return int
         */
-       public function getNativeData( ) {
-               $opt = array_diff( $this->mOptions, array( 'parse', 'parseinline' ) );
+       public function getSize() {
+               return strlen( $this->mMessage->plain() );
+       }
+
+       /**
+        * @see Content::copy
+        *
+        * @return Content. A copy of this object
+        */
+       public function copy() {
+               // MessageContent is immutable (because getNativeData() returns a clone of the Message object)
+               return $this;
+       }
 
-               return wfMsgExt( $this->mMessageKey, $this->mParameters, $opt );
+       /**
+        * @see Content::isCountable
+        *
+        * @return bool false
+        */
+       public function isCountable( $hasLinks = null ) {
+               return false;
        }
 
+       /**
+        * @see Content::getParserOutput
+        *
+        * @return ParserOutput
+        */
+       public function getParserOutput(
+               Title $title, $revId = null,
+               ParserOptions $options = null, $generateHtml = true
+       ) {
+
+               if ( $generateHtml ) {
+                       $html = $this->getHtml();
+               } else {
+                       $html = '';
+               }
+
+               $po = new ParserOutput( $html );
+               return $po;
+       }
 }
 
 /**