Tobias Gritschacher has submitted this change and it was merged.

Change subject: (bug 41573) Add entities to watchlist.
......................................................................


(bug 41573) Add entities to watchlist.

When editing an entity, it should get added to the user's watchlist
according to the user's preferences.

Bug: 41573
Change-Id: I36c6a3a285f21cc0f4a1298752b34823140cb736
---
M repo/includes/EditEntity.php
M repo/tests/phpunit/includes/EditEntityTest.php
2 files changed, 255 insertions(+), 10 deletions(-)

Approvals:
  Tobias Gritschacher: Verified; Looks good to me, approved
  jenkins-bot: Verified



diff --git a/repo/includes/EditEntity.php b/repo/includes/EditEntity.php
index 552f254..eae909e 100644
--- a/repo/includes/EditEntity.php
+++ b/repo/includes/EditEntity.php
@@ -265,11 +265,11 @@
         * Returns the Title of the page to be edited.
         * Shorthand for $this->getPage()->getTitle().
         *
-        * @return Title
+        * @return Title|bool
         */
        public function getTitle() {
                if ( $this->isNew() ) {
-                       return null;
+                       return false;
                }
 
                return $this->newContent->getTitle();
@@ -611,17 +611,23 @@
         * @param int         $flags      The edit flags (see 
WikiPage::toEditContent)
         * @param String|bool $token      Edit token to check, or false to 
disable the token check.
         *                                Null will fail the token text, as 
will the empty string.
+        * @param bool|null $watch        Whether the user wants to watch the 
entity.
+        *                                Set to null to apply default 
according to getWatchDefault().
         *
         * @throws \ReadOnlyError
         * @return Status Indicates success and provides detailed warnings or 
error messages. See
         *         getStatus() for more details.
         * @see    WikiPage::doEditContent
         */
-       public function attemptSave( $summary, $flags, $token ) {
+       public function attemptSave( $summary, $flags, $token, $watch = null ) {
                wfProfileIn( __METHOD__ );
 
                if ( wfReadOnly() ) {
                        throw new \ReadOnlyError();
+               }
+
+               if ( $watch === null ) {
+                       $watch = $this->getWatchDefault();
                }
 
                $this->status = Status::newGood();
@@ -715,7 +721,9 @@
                $this->status->setResult( $editStatus->isOK(), 
$editStatus->getValue() );
                $this->status->merge( $editStatus );
 
-               if ( !$this->status->isOK() ) {
+               if ( $this->status->isOK() ) {
+                       $this->updateWatchlist( $watch );
+               } else {
                        $value = $this->status->getValue();
                        $value['errorFlags'] = $this->errorType;
                        $this->status->setResult( false, $value );
@@ -932,4 +940,68 @@
                wfProfileOut( __METHOD__ );
                return true;
        }
+
+       /**
+        * Returns whether the present edit would, per default,
+        * lead to the user watching the page.
+        *
+        * This uses the user's watchdefault and watchcreations settings
+        * and considers whether the entity is already watched by the user.
+        *
+        * @return bool
+        *
+        * @note: keep in sync with logic in EditPage
+        */
+       public function getWatchDefault() {
+               $user = $this->getUser();
+               $title = $this->getTitle();
+
+               if ( $title && !$title->exists() ) {
+                       $title = false;
+               }
+
+               if ( $user->getOption( 'watchdefault' ) ) {
+                       // Watch all edits
+                       return true;
+               } elseif ( $user->getOption( 'watchcreations' ) && !$title ) {
+                       // Watch creations
+                       return true;
+               }
+
+               // keep current state
+               return $title !== false && $user->isWatched( $title );
+       }
+
+       /**
+        * Watches or unwatches the entity.
+        *
+        * @param bool $watch whether to watch or unwatch the page.
+        *
+        * @throws \MWException
+        * @return void : keep in sync with logic in EditPage
+        */
+       public function updateWatchlist( $watch ) {
+               $user = $this->getUser();
+               $title = $this->getTitle();
+
+               if ( !$title ) {
+                       throw new \MWException( "Title not yet known!" );
+               }
+
+               if ( $user->isLoggedIn() && $watch != $user->isWatched( $title 
) ) {
+                       $fname = __METHOD__;
+
+                       // Do this in its own transaction to reduce 
contention...
+                       $dbw = wfGetDB( DB_MASTER );
+                       $dbw->onTransactionIdle( function() use ( $dbw, $title, 
$watch, $user, $fname ) {
+                               $dbw->begin( $fname );
+                               if ( $watch ) {
+                                       \WatchAction::doWatch( $title, $user );
+                               } else {
+                                       \WatchAction::doUnwatch( $title, $user 
);
+                               }
+                               $dbw->commit( $fname );
+                       } );
+               }
+       }
 }
diff --git a/repo/tests/phpunit/includes/EditEntityTest.php 
b/repo/tests/phpunit/includes/EditEntityTest.php
index 3651788..b706de5 100644
--- a/repo/tests/phpunit/includes/EditEntityTest.php
+++ b/repo/tests/phpunit/includes/EditEntityTest.php
@@ -4,8 +4,8 @@
 
 use \Wikibase\EntityContent;
 use \Wikibase\EditEntity;
-use Wikibase\Item;
 use \Wikibase\ItemContent;
+use \Wikibase\Item;
 use \Status;
 use Wikibase\Test\Api\ModifyItemBase;
 
@@ -54,15 +54,21 @@
 
        private static $testRevisions = null;
 
+       protected static function getUser( $name ) {
+               $user = \User::newFromName( $name );
+
+               if ( $user->getId() === 0 ) {
+                       $user = \User::createNew( $user->getName() );
+               }
+
+               return $user;
+       }
+
        protected static function getTestRevisions() {
                global $wgUser;
 
                if ( self::$testRevisions === null ) {
-                       $otherUser = \User::newFromName( "EditEntityTestUser2" 
);
-
-                       if ( $otherUser->getId() === 0 ) {
-                               $otherUser = \User::createNew( 
$otherUser->getName() );
-                       }
+                       $otherUser = self::getUser( "EditEntityTestUser2" );
 
                        $itemContent = ItemContent::newEmpty();
                        $itemContent->getEntity()->setLabel('en', "foo");
@@ -702,4 +708,171 @@
                $this->assertNotEquals( $shouldWork, $edit->hasError( 
EditEntity::TOKEN_ERROR ) );
                $this->assertNotEquals( $shouldWork, $edit->showErrorPage() );
        }
+
+       public static function provideGetWatchDefault() {
+               // $watchdefault, $watchcreations, $new, $watched, $expected
+
+               return array(
+                       array( false, false, false, false, false ),
+                       array( false, false, false, true,  true ),
+                       array( false, false, true,  false, false ),
+                       //array( false, false, true,  true,  true ), // can't 
happen, a new pages is never watched
+
+                       array( false, true,  false, false, false ),
+                       array( false, true,  false, true,  true ),
+                       array( false, true,  true,  false, true ),
+                       //array( false, true,  true,  true,  true ), // can't 
happen, a new pages is never watched
+
+                       array( true,  false, false, false, true ),
+                       array( true,  false, false, true,  true ),
+                       array( true,  false, true,  false, true ),
+                       //array( true,  false, true,  true,  true ), // can't 
happen, a new pages is never watched
+
+                       array( true,  true,  false, false, true ),
+                       array( true,  true,  false, true,  true ),
+                       array( true,  true,  true,  false, true ),
+                       //array( true,  true,  true,  true,  true ), // can't 
happen, a new pages is never watched
+               );
+       }
+
+       /**
+        * @dataProvider provideGetWatchDefault
+        */
+       public function testGetWatchDefault( $watchdefault, $watchcreations, 
$new, $watched, $expected ) {
+               $user = self::getUser( "EditEntityTestUser2" );
+
+               $user->setOption( 'watchdefault', $watchdefault );
+               $user->setOption( 'watchcreations', $watchcreations );
+
+               $item = Item::newEmpty();
+               $item->setLabel( "en", "Test" );
+
+               if ( $new ) {
+                       $item->setId( 33224477 );
+                       $content = ItemContent::newFromItem( $item );
+               } else {
+                       $content = ItemContent::newFromItem( $item );
+                       $stats = $content->save( "testing", null, EDIT_NEW );
+                       $this->assertTrue( $stats->isOK(), "failed to save" ); 
// sanity
+               }
+
+               $title = $content->getTitle();
+               $this->assertType( 'object', $title ); // sanity
+
+               if ( $watched ) {
+                       \WatchAction::doWatch( $title, $user );
+               } else {
+                       \WatchAction::doUnwatch( $title, $user );
+               }
+
+               $edit = new EditEntity( $content, $user );
+               $watch = $edit->getWatchDefault();
+               $this->assertEquals( $expected, $watch, "getWatchDefault" );
+
+               if ( $title && $title->exists() ) {
+                       // clean up
+                       $page = \WikiPage::factory( $title );
+                       $page->doDeleteArticle( "testing" );
+               }
+       }
+
+       public static function provideUpdateWatchlist() {
+               // $wasWatched, $watch, $expected
+
+               return array(
+                       array( false, false, false ),
+                       array( false, true,  true ),
+                       array( true,  false, false ),
+                       array( true,  true,  true ),
+               );
+       }
+
+       /**
+        * @dataProvider provideUpdateWatchlist
+        */
+       public function testUpdateWatchlist( $wasWatched, $watch, $expected ) {
+               $user = self::getUser( "EditEntityTestUser2" );
+
+               $content = ItemContent::newEmpty();
+               $content->getEntity()->setLabel( "en", "Test" );
+               $content->getEntity()->setId( 33224477 );
+
+               $title = $content->getTitle();
+
+               if ( $wasWatched ) {
+                       \WatchAction::doWatch( $title, $user );
+               } else {
+                       \WatchAction::doUnwatch( $title, $user );
+               }
+
+               $edit = new EditEntity( $content, $user );
+               $edit->updateWatchlist( $watch );
+
+               $this->assertEquals( $expected, $user->isWatched( $title ) );
+       }
+
+
+       public static function provideAttemptSaveWatch() {
+               // $watchdefault, $watchcreations, $new, $watched, $watch, 
$expected
+
+               return array(
+                       array( true, true, true, false, null, true ), // watch 
new
+                       array( true, true, true, false, false, false ), // 
override watch new
+
+                       array( true, true, false, false, null, true ), // watch 
edit
+                       array( true, true, false, false, false, false ), // 
override watch edit
+
+                       array( false, false, false, false, null, false ), // 
don't watch edit
+                       array( false, false, false, false, true, true ), // 
override don't watch edit
+
+                       array( false, false, false, true, null, true ), // 
watch watched
+                       array( false, false, false, true, false, false ), // 
override don't watch edit
+               );
+       }
+
+       /**
+        * @dataProvider provideAttemptSaveWatch
+        */
+       public function testAttemptSaveWatch( $watchdefault, $watchcreations, 
$new, $watched, $watch, $expected ) {
+               $user = self::getUser( "EditEntityTestUser2" );
+
+               $user->setOption( 'watchdefault', $watchdefault );
+               $user->setOption( 'watchcreations', $watchcreations );
+
+               $item = Item::newEmpty();
+               $item->setLabel( "en", "Test" );
+
+               if ( $new ) {
+                       $content = ItemContent::newFromItem( $item );
+               } else {
+                       $content = ItemContent::newFromItem( $item );
+                       $stats = $content->save( "testing", null, EDIT_NEW );
+                       $this->assertTrue( $stats->isOK(), "failed to save" ); 
// sanity
+               }
+
+               if ( !$new ) {
+                       $title = $content->getTitle();
+                       $this->assertType( 'object', $title ); // sanity
+
+                       if ( $watched ) {
+                               \WatchAction::doWatch( $title, $user );
+                       } else {
+                               \WatchAction::doUnwatch( $title, $user );
+                       }
+               }
+
+               $edit = new EditEntity( $content, $user );
+               $status = $edit->attemptSave( "testing", $new ? EDIT_NEW : 
EDIT_UPDATE, false, $watch );
+
+               $this->assertTrue( $status->isOK(), "edit failed: " . 
$status->getWikiText() ); // sanity
+
+               $title = $content->getTitle();
+               $this->assertEquals( $expected, $user->isWatched( $title ), 
"watched" );
+
+               if ( $title && $title->exists() ) {
+                       // clean up
+                       $page = \WikiPage::factory( $title );
+                       $page->doDeleteArticle( "testing" );
+               }
+       }
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/54704
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I36c6a3a285f21cc0f4a1298752b34823140cb736
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Daniel Werner <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: John Erling Blad <[email protected]>
Gerrit-Reviewer: Tobias Gritschacher <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to