Merge "Re-word action-createpage and action-createtalk in singular"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 23 Jun 2016 11:23:25 +0000 (11:23 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 23 Jun 2016 11:23:25 +0000 (11:23 +0000)
includes/EditPage.php
includes/user/User.php
includes/utils/IP.php
languages/Language.php
tests/phpunit/languages/LanguageTest.php

index 3292f70..7fb71f7 100644 (file)
@@ -335,6 +335,9 @@ class EditPage {
        /** @var string */
        public $edittime = '';
 
+       /** @var integer */
+       private $editRevId = null;
+
        /** @var string */
        public $section = '';
 
@@ -839,6 +842,7 @@ class EditPage {
                        $this->sectiontitle = preg_replace( '/^\s*=+\s*(.*?)\s*=+\s*$/', '$1', $this->sectiontitle );
 
                        $this->edittime = $request->getVal( 'wpEdittime' );
+                       $this->editRevId = $request->getIntOrNull( 'editRevId' );
                        $this->starttime = $request->getVal( 'wpStarttime' );
 
                        $undidRev = $request->getInt( 'wpUndidRevision' );
@@ -935,6 +939,7 @@ class EditPage {
                        $this->summary = '';
                        $this->sectiontitle = '';
                        $this->edittime = '';
+                       $this->editRevId = null;
                        $this->starttime = wfTimestampNow();
                        $this->edit = false;
                        $this->preview = false;
@@ -1020,6 +1025,7 @@ class EditPage {
        function initialiseForm() {
                global $wgUser;
                $this->edittime = $this->page->getTimestamp();
+               $this->editRevId = $this->page->getLatest();
 
                $content = $this->getContentObject( false ); # TODO: track content object?!
                if ( $content === false ) {
@@ -1862,10 +1868,14 @@ class EditPage {
 
                        $this->page->clear(); # Force reload of dates, etc.
                        $timestamp = $this->page->getTimestamp();
+                       $latest = $this->page->getLatest();
 
                        wfDebug( "timestamp: {$timestamp}, edittime: {$this->edittime}\n" );
 
-                       if ( $timestamp != $this->edittime ) {
+                       // Check editRevId if set, which handles same-second timestamp collisions
+                       if ( $timestamp != $this->edittime
+                               || ( $this->editRevId !== null && $this->editRevId != $latest )
+                       ) {
                                $this->isConflict = true;
                                if ( $this->section == 'new' ) {
                                        if ( $this->page->getUserText() == $wgUser->getName() &&
@@ -1905,14 +1915,24 @@ class EditPage {
                        if ( $this->isConflict ) {
                                wfDebug( __METHOD__
                                        . ": conflict! getting section '{$this->section}' for time '{$this->edittime}'"
-                                       . " (article time '{$timestamp}')\n" );
-
-                               $content = $this->page->replaceSectionContent(
-                                       $this->section,
-                                       $textbox_content,
-                                       $sectionTitle,
-                                       $this->edittime
-                               );
+                                       . " (id '{$this->editRevId}') (article time '{$timestamp}')\n" );
+                               // @TODO: replaceSectionAtRev() with base ID (not prior current) for ?oldid=X case
+                               // ...or disable section editing for non-current revisions (not exposed anyway).
+                               if ( $this->editRevId !== null ) {
+                                       $content = $this->page->replaceSectionAtRev(
+                                               $this->section,
+                                               $textbox_content,
+                                               $sectionTitle,
+                                               $this->editRevId
+                                       );
+                               } else {
+                                       $content = $this->page->replaceSectionContent(
+                                               $this->section,
+                                               $textbox_content,
+                                               $sectionTitle,
+                                               $this->edittime
+                                       );
+                               }
                        } else {
                                wfDebug( __METHOD__ . ": getting section '{$this->section}'\n" );
                                $content = $this->page->replaceSectionContent(
@@ -2172,8 +2192,9 @@ class EditPage {
        function getBaseRevision() {
                if ( !$this->mBaseRevision ) {
                        $db = wfGetDB( DB_MASTER );
-                       $this->mBaseRevision = Revision::loadFromTimestamp(
-                               $db, $this->mTitle, $this->edittime );
+                       $this->mBaseRevision = $this->editRevId
+                               ? Revision::newFromId( $this->editRevId, Revision::READ_LATEST )
+                               : Revision::loadFromTimestamp( $db, $this->mTitle, $this->edittime );
                }
                return $this->mBaseRevision;
        }
@@ -2756,7 +2777,7 @@ class EditPage {
 
                if ( $this->isConflict ) {
                        $wgOut->wrapWikiMsg( "<div class='mw-explainconflict'>\n$1\n</div>", 'explainconflict' );
-                       $this->edittime = $this->page->getTimestamp();
+                       $this->editRevId = $this->page->getLatest();
                } else {
                        if ( $this->section != '' && !$this->isSectionEditSupported() ) {
                                // We use $this->section to much before this and getVal('wgSection') directly in other places
@@ -3063,6 +3084,7 @@ class EditPage {
 <input type='hidden' value="{$section}" name="wpSection"/>
 <input type='hidden' value="{$this->starttime}" name="wpStarttime" />
 <input type='hidden' value="{$this->edittime}" name="wpEdittime" />
+<input type='hidden' value="{$this->editRevId}" name="editRevId" />
 <input type='hidden' value="{$this->scrolltop}" name="wpScrolltop" id="wpScrolltop" />
 
 HTML
@@ -3271,10 +3293,15 @@ HTML
                }
 
                $textboxContent = $this->toEditContent( $this->textbox1 );
-
-               $newContent = $this->page->replaceSectionContent(
-                                                       $this->section, $textboxContent,
-                                                       $this->summary, $this->edittime );
+               if ( $this->editRevId !== null ) {
+                       $newContent = $this->page->replaceSectionAtRev(
+                               $this->section, $textboxContent, $this->summary, $this->editRevId
+                       );
+               } else {
+                       $newContent = $this->page->replaceSectionContent(
+                               $this->section, $textboxContent, $this->summary, $this->edittime
+                       );
+               }
 
                if ( $newContent ) {
                        ContentHandler::runLegacyHooks( 'EditPageGetDiffText', [ $this, &$newContent ] );
index cc4c6d0..40b5b40 100644 (file)
@@ -806,7 +806,7 @@ class User implements IDBAccessObject {
        }
 
        /**
-        * Does the string match an anonymous IPv4 address?
+        * Does the string match an anonymous IP address?
         *
         * This function exists for username validation, in order to reject
         * usernames which are similar in form to IP addresses. Strings such
index 4a2205e..8676baf 100644 (file)
@@ -53,7 +53,7 @@ define( 'RE_IPV6_BLOCK', RE_IPV6_ADD . '\/' . RE_IPV6_PREFIX );
 define( 'RE_IPV6_GAP', ':(?:0+:)*(?::(?:0+:)*)?' );
 define( 'RE_IPV6_V4_PREFIX', '0*' . RE_IPV6_GAP . '(?:ffff:)?' );
 
-// This might be useful for regexps used elsewhere, matches any IPv6 or IPv6 address or network
+// This might be useful for regexps used elsewhere, matches any IPv4 or IPv6 address or network
 define( 'IP_ADDRESS_STRING',
        '(?:' .
                RE_IP_ADD . '(?:\/' . RE_IP_PREFIX . ')?' . // IPv4
index f0c7d76..37f4137 100644 (file)
@@ -1087,7 +1087,7 @@ class Language {
         * @throws MWException
         * @return string
         */
-       public function sprintfDate( $format, $ts, DateTimeZone $zone = null, &$ttl = null ) {
+       public function sprintfDate( $format, $ts, DateTimeZone $zone = null, &$ttl = 'unused' ) {
                $s = '';
                $raw = false;
                $roman = false;
@@ -1452,7 +1452,9 @@ class Language {
                        }
                }
 
-               if ( $usedSecond ) {
+               if ( $ttl === 'unused' ) {
+                       // No need to calculate the TTL, the caller wont use it anyway.
+               } elseif ( $usedSecond ) {
                        $ttl = 1;
                } elseif ( $usedMinute ) {
                        $ttl = 60 - substr( $ts, 12, 2 );
index 9e41a4e..e2e6492 100644 (file)
@@ -638,6 +638,24 @@ class LanguageTest extends LanguageClassesTestCase {
                );
        }
 
+       /**
+        * sprintfDate should only calculate a TTL if the caller is going to use it.
+        * @covers Language::sprintfDate
+        */
+       public function testSprintfDateNoTtlIfNotNeeded() {
+               $noTtl = 'unused'; // Value used to represent that the caller didn't pass a variable in.
+               $ttl = null;
+               $this->getLang()->sprintfDate( 'YmdHis', wfTimestampNow(), null, $noTtl );
+               $this->getLang()->sprintfDate( 'YmdHis', wfTimestampNow(), null, $ttl );
+
+               $this->assertSame(
+                       'unused',
+                       $noTtl,
+                       'If the caller does not set the $ttl variable, do not compute it.'
+               );
+               $this->assertInternalType( 'int', $ttl, 'TTL should have been computed.' );
+       }
+
        public static function provideSprintfDateSamples() {
                return [
                        [