Updating of redirect target in Content objects
authordaniel <daniel.kinzler@wikimedia.de>
Tue, 21 Aug 2012 15:32:44 +0000 (17:32 +0200)
committerdaniel <daniel.kinzler@wikimedia.de>
Tue, 28 Aug 2012 11:50:05 +0000 (13:50 +0200)
Content::updateRedirect may be used to change the redirect target
without knowing anything about the content's format.

Change-Id: Ifaf8f2bdd9d1cbf984e2ef3c60d0282c984c18c1

includes/Content.php
includes/job/DoubleRedirectJob.php
tests/phpunit/includes/JavascriptContentTest.php
tests/phpunit/includes/WikitextContentTest.php

index 38d2e27..f795462 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.
         *
@@ -684,6 +696,8 @@ abstract class AbstractContent implements Content {
        }
 
        /**
+        * @see Content::isRedirect()
+        *
         * @since WD.1
         *
         * @return bool
@@ -692,6 +706,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()
         */
@@ -1108,6 +1135,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.
index 7acc4f2..11a4b98 100644 (file)
@@ -127,14 +127,10 @@ class DoubleRedirectJob extends Job {
                $text = ContentHandler::getContentText( $content ); #FIXME: get rid of 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',
-                       '[[' . $newTitle->getFullText() . ']]',
-                       $text, 1 ); #FIXME: need a way to do this via ContentHandler!
-
-               if ( $newText === $text ) {
-                       $this->setLastError( 'Text unchanged???' );
+               $newContent = $content->updateRedirect( $newTitle );
+
+               if ( $newContent->equals( $content ) ) {
+                       $this->setLastError( 'Content unchanged???' );
                        return false;
                }
 
@@ -146,7 +142,7 @@ class DoubleRedirectJob extends Job {
                $reason = wfMessage( 'double-redirect-fixed-' . $this->reason,
                        $this->redirTitle->getPrefixedText(), $newTitle->getPrefixedText()
                )->inContentLanguage()->text();
-               $article->doEdit( $newText, $reason, EDIT_UPDATE | EDIT_SUPPRESS_RC, false, $this->getUser() );
+               $article->doEditContent( $newContent, $reason, EDIT_UPDATE | EDIT_SUPPRESS_RC, false, $this->getUser() );
                $wgUser = $oldUser;
 
                return true;
index 84cde8c..da03d62 100644 (file)
@@ -221,6 +221,15 @@ class JavascriptContentTest extends WikitextContentTest {
                $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word, since it's not wikitext" );
        }
 
+       public function testUpdateRedirect( ) {
+               $target = Title::newFromText( "testUpdateRedirect_target" );
+
+               $content = $this->newContent( "#REDIRECT [[Someplace]]" );
+               $newContent = $content->updateRedirect( $target );
+
+               $this->assertTrue( $content->equals( $newContent ), "content should be unchanged since it's not wikitext" );
+       }
+
        # =================================================================================================================
 
        public function testGetModel() {
index 602a9a2..449423b 100644 (file)
@@ -429,6 +429,25 @@ just a test"
                $this->assertFalse( $content->matchMagicWord( $mw ), "should not have matched magic word" );
        }
 
+       public function testUpdateRedirect( ) {
+               $target = Title::newFromText( "testUpdateRedirect_target" );
+
+               // test with non-redirect page
+               $content = $this->newContent( "hello world." );
+               $newContent = $content->updateRedirect( $target );
+
+               $this->assertTrue( $content->equals( $newContent ), "content should be unchanged" );
+
+               // test with actual redirect
+               $content = $this->newContent( "#REDIRECT [[Someplace]]" );
+               $newContent = $content->updateRedirect( $target );
+
+               $this->assertFalse( $content->equals( $newContent ), "content should have changed" );
+               $this->assertTrue( $newContent->isRedirect(), "new content should be a redirect" );
+
+               $this->assertEquals( $target->getFullText(), $newContent->getRedirectTarget()->getFullText() );
+       }
+
        # =================================================================================================================
 
        public function testGetModel() {