Index: trunk/phase3/includes/ProtectionForm.php |
— | — | @@ -318,10 +318,10 @@ |
319 | 319 | return false; |
320 | 320 | } |
321 | 321 | |
322 | | - if( $wgRequest->getCheck( 'mwProtectWatch' ) && $wgUser->isLoggedIn() ) { |
323 | | - Action::factory( 'watch', $this->mArticle )->execute(); |
324 | | - } elseif( $this->mTitle->userIsWatching() ) { |
325 | | - Action::factory( 'unwatch', $this->mArticle )->execute(); |
| 322 | + if ( $wgRequest->getCheck( 'mwProtectWatch' ) && $wgUser->isLoggedIn() ) { |
| 323 | + WatchAction::doWatch( $this->mTitle, $wgUser ); |
| 324 | + } elseif ( $this->mTitle->userIsWatching() ) { |
| 325 | + WatchAction::doUnwatch( $this->mTitle, $wgUser ); |
326 | 326 | } |
327 | 327 | return $ok; |
328 | 328 | } |
Index: trunk/phase3/includes/Article.php |
— | — | @@ -2382,7 +2382,8 @@ |
2383 | 2383 | } |
2384 | 2384 | |
2385 | 2385 | /** |
2386 | | - * User-interface handler for the "watch" action |
| 2386 | + * User-interface handler for the "watch" action. |
| 2387 | + * Requires Request to pass a token as of 1.19. |
2387 | 2388 | * @deprecated since 1.18 |
2388 | 2389 | */ |
2389 | 2390 | public function watch() { |
— | — | @@ -2398,11 +2399,13 @@ |
2399 | 2400 | * @deprecated since 1.18 |
2400 | 2401 | */ |
2401 | 2402 | public function doWatch() { |
2402 | | - return Action::factory( 'watch', $this )->execute(); |
| 2403 | + global $wgUser; |
| 2404 | + return WatchAction:doWatch( $this->mTitle, $wgUser ); |
2403 | 2405 | } |
2404 | 2406 | |
2405 | 2407 | /** |
2406 | 2408 | * User interface handler for the "unwatch" action. |
| 2409 | + * Requires Request to pass a token as of 1.19. |
2407 | 2410 | * @deprecated since 1.18 |
2408 | 2411 | */ |
2409 | 2412 | public function unwatch() { |
— | — | @@ -2415,7 +2418,8 @@ |
2416 | 2419 | * @deprecated since 1.18 |
2417 | 2420 | */ |
2418 | 2421 | public function doUnwatch() { |
2419 | | - return Action::factory( 'unwatch', $this )->execute(); |
| 2422 | + global $wgUser; |
| 2423 | + return WatchAction:doUnwatch( $this->mTitle, $wgUser ); |
2420 | 2424 | } |
2421 | 2425 | |
2422 | 2426 | /** |
Index: trunk/phase3/includes/EditPage.php |
— | — | @@ -1176,13 +1176,14 @@ |
1177 | 1177 | * Commit the change of watch status |
1178 | 1178 | */ |
1179 | 1179 | protected function commitWatch() { |
| 1180 | + global $wgUser; |
1180 | 1181 | if ( $this->watchthis xor $this->mTitle->userIsWatching() ) { |
1181 | 1182 | $dbw = wfGetDB( DB_MASTER ); |
1182 | 1183 | $dbw->begin(); |
1183 | 1184 | if ( $this->watchthis ) { |
1184 | | - Action::factory( 'watch', $this->mArticle )->execute(); |
| 1185 | + WatchAction::doWatch( $this->mTitle, $wgUser ); |
1185 | 1186 | } else { |
1186 | | - Action::factory( 'unwatch', $this->mArticle )->execute(); |
| 1187 | + WatchAction::doUnwatch( $this->mTitle, $wgUser ); |
1187 | 1188 | } |
1188 | 1189 | $dbw->commit(); |
1189 | 1190 | } |
Index: trunk/phase3/includes/actions/DeleteAction.php |
— | — | @@ -1,6 +1,6 @@ |
2 | 2 | <?php |
3 | 3 | /** |
4 | | - * Performs the watch and unwatch actions on a page |
| 4 | + * Performs the delete action on a page |
5 | 5 | * |
6 | 6 | * This program is free software; you can redistribute it and/or modify |
7 | 7 | * it under the terms of the GNU General Public License as published by |
— | — | @@ -196,9 +196,9 @@ |
197 | 197 | public function onSuccess(){ |
198 | 198 | // Watch or unwatch, if requested |
199 | 199 | if( $this->getRequest()->getCheck( 'wpWatch' ) && $this->getUser()->isLoggedIn() ) { |
200 | | - Action::factory( 'watch', $this->page )->execute(); |
| 200 | + WatchAction::doWatch( $this->getTitle(), $this->getUser() ); |
201 | 201 | } elseif ( $this->getTitle()->userIsWatching() ) { |
202 | | - Action::factory( 'unwatch', $this->page )->execute(); |
| 202 | + WatchAction::doUnwatch( $this->getTitle(), $this->getUser() ); |
203 | 203 | } |
204 | 204 | |
205 | 205 | $this->getOutput()->setPagetitle( wfMsg( 'actioncomplete' ) ); |
Index: trunk/phase3/includes/actions/WatchAction.php |
— | — | @@ -39,9 +39,20 @@ |
40 | 40 | } |
41 | 41 | |
42 | 42 | protected function checkCanExecute( User $user ) { |
| 43 | + |
| 44 | + // Must be logged in |
43 | 45 | if ( $user->isAnon() ) { |
44 | 46 | throw new ErrorPageError( 'watchnologin', 'watchnologintext' ); |
45 | 47 | } |
| 48 | + |
| 49 | + // Must have valid token for this action/title |
| 50 | + $salt = array( $this->getName(), $this->getTitle()->getDBkey() ); |
| 51 | + |
| 52 | + if ( !$user->matchEditToken( $this->getRequest()->getVal( 'token' ), $salt ) ) { |
| 53 | + throw new ErrorPageError( 'sessionfailure-title', 'sessionfailure' ); |
| 54 | + return; |
| 55 | + } |
| 56 | + |
46 | 57 | return parent::checkCanExecute( $user ); |
47 | 58 | } |
48 | 59 | |
— | — | @@ -49,15 +60,66 @@ |
50 | 61 | wfProfileIn( __METHOD__ ); |
51 | 62 | |
52 | 63 | $user = $this->getUser(); |
53 | | - if ( wfRunHooks( 'WatchArticle', array( &$user, &$this->page ) ) ) { |
54 | | - $this->getUser()->addWatch( $this->getTitle() ); |
55 | | - wfRunHooks( 'WatchArticleComplete', array( &$user, &$this->page ) ); |
56 | | - } |
| 64 | + self::doWatch( $this->getTitle(), $user ); |
57 | 65 | |
58 | 66 | wfProfileOut( __METHOD__ ); |
59 | 67 | |
60 | 68 | return wfMessage( 'addedwatchtext', $this->getTitle()->getPrefixedText() )->parse(); |
61 | 69 | } |
| 70 | + |
| 71 | + public static function doWatch( Title $title, User $user ) { |
| 72 | + $page = new Article( $title ); |
| 73 | + |
| 74 | + if ( wfRunHooks( 'WatchArticle', array( &$user, &$page ) ) ) { |
| 75 | + $user->addWatch( $title ); |
| 76 | + wfRunHooks( 'WatchArticleComplete', array( &$user, &$page ) ); |
| 77 | + } |
| 78 | + return true; |
| 79 | + } |
| 80 | + |
| 81 | + public static function doUnwatch( Title $title, User $user ) { |
| 82 | + $page = new Article( $title ); |
| 83 | + |
| 84 | + if ( wfRunHooks( 'UnwatchArticle', array( &$user, &$page ) ) ) { |
| 85 | + $user->removeWatch( $title ); |
| 86 | + wfRunHooks( 'UnwatchArticleComplete', array( &$user, &$page ) ); |
| 87 | + } |
| 88 | + return true; |
| 89 | + } |
| 90 | + |
| 91 | + /** |
| 92 | + * Get token to watch (or unwatch) a page for a user |
| 93 | + * |
| 94 | + * @param Title $title Title object of page to watch |
| 95 | + * @param User $title User for whom the action is going to be performed |
| 96 | + * @param string $action Optionally override the action to 'unwatch' |
| 97 | + * @return string Token |
| 98 | + * @since 1.19 |
| 99 | + */ |
| 100 | + public static function getWatchToken( Title $title, User $user, $action = 'watch' ) { |
| 101 | + if ( $action != 'unwatch' ) { |
| 102 | + $action = 'watch'; |
| 103 | + } |
| 104 | + $salt = array( $action, $title->getDBkey() ); |
| 105 | + |
| 106 | + // This token stronger salted and not compatible with ApiWatch |
| 107 | + // It's title/action specific because index.php is GET and API is POST |
| 108 | + return $user->editToken( $salt ); |
| 109 | + } |
| 110 | + |
| 111 | + /** |
| 112 | + * Get token to unwatch (or watch) a page for a user |
| 113 | + * |
| 114 | + * @param Title $title Title object of page to unwatch |
| 115 | + * @param User $title User for whom the action is going to be performed |
| 116 | + * @param string $action Optionally override the action to 'watch' |
| 117 | + * @return string Token |
| 118 | + * @since 1.19 |
| 119 | + */ |
| 120 | + public static function getUnwatchToken( Title $title, User $user, $action = 'unwatch' ) { |
| 121 | + return self::getWatchToken( $title, $user, $action ); |
| 122 | + } |
| 123 | + |
62 | 124 | } |
63 | 125 | |
64 | 126 | class UnwatchAction extends WatchAction { |
— | — | @@ -74,10 +136,7 @@ |
75 | 137 | wfProfileIn( __METHOD__ ); |
76 | 138 | |
77 | 139 | $user = $this->getUser(); |
78 | | - if ( wfRunHooks( 'UnwatchArticle', array( &$user, &$this->page ) ) ) { |
79 | | - $this->getUser()->removeWatch( $this->getTitle() ); |
80 | | - wfRunHooks( 'UnwatchArticleComplete', array( &$user, &$this->page ) ); |
81 | | - } |
| 140 | + self::doUnwatch( $this->getTitle(), $user ); |
82 | 141 | |
83 | 142 | wfProfileOut( __METHOD__ ); |
84 | 143 | |
Index: trunk/phase3/includes/api/ApiWatch.php |
— | — | @@ -59,11 +59,11 @@ |
60 | 60 | if ( $params['unwatch'] ) { |
61 | 61 | $res['unwatched'] = ''; |
62 | 62 | $res['message'] = wfMsgExt( 'removedwatchtext', array( 'parse' ), $title->getPrefixedText() ); |
63 | | - $success = Action::factory( 'unwatch', $article )->execute(); |
| 63 | + $success = WatchAction::doWatch( $title, $wgUser ); |
64 | 64 | } else { |
65 | 65 | $res['watched'] = ''; |
66 | 66 | $res['message'] = wfMsgExt( 'addedwatchtext', array( 'parse' ), $title->getPrefixedText() ); |
67 | | - $success = Action::factory( 'watch', $article )->execute(); |
| 67 | + $success = UnwatchAction::doUnwatch( $title, $wgUser ); |
68 | 68 | } |
69 | 69 | if ( !$success ) { |
70 | 70 | $this->dieUsageMsg( 'hookaborted' ); |
Index: trunk/phase3/includes/api/ApiBase.php |
— | — | @@ -645,17 +645,17 @@ |
646 | 646 | * @param $titleObj Title the article's title to change |
647 | 647 | * @param $userOption String The user option to consider when $watch=preferences |
648 | 648 | */ |
649 | | - protected function setWatch ( $watch, $titleObj, $userOption = null ) { |
| 649 | + protected function setWatch( $watch, $titleObj, $userOption = null ) { |
650 | 650 | $value = $this->getWatchlistValue( $watch, $titleObj, $userOption ); |
651 | 651 | if ( $value === null ) { |
652 | 652 | return; |
653 | 653 | } |
654 | 654 | |
655 | | - $articleObj = new Article( $titleObj ); |
| 655 | + global $wgUser; |
656 | 656 | if ( $value ) { |
657 | | - Action::factory( 'watch', $articleObj )->execute(); |
| 657 | + WatchAction::doWatch( $titleObj, $wgUser ); |
658 | 658 | } else { |
659 | | - Action::factory( 'unwatch', $articleObj )->execute(); |
| 659 | + WatchAction::doUnwatch( $titleObj, $wgUser ); |
660 | 660 | } |
661 | 661 | } |
662 | 662 | |
Index: trunk/phase3/includes/FileDeleteForm.php |
— | — | @@ -123,10 +123,10 @@ |
124 | 124 | // delete the associated article first |
125 | 125 | if( $article->doDeleteArticle( $reason, $suppress, $id, false ) ) { |
126 | 126 | global $wgRequest; |
127 | | - if( $wgRequest->getCheck( 'wpWatch' ) && $wgUser->isLoggedIn() ) { |
128 | | - Action::factory( 'watch', $article )->execute(); |
129 | | - } elseif( $title->userIsWatching() ) { |
130 | | - Action::factory( 'unwatch', $article )->execute(); |
| 127 | + if ( $wgRequest->getCheck( 'wpWatch' ) && $wgUser->isLoggedIn() ) { |
| 128 | + WatchAction::doWatch( $title, $wgUser ); |
| 129 | + } elseif ( $title->userIsWatching() ) { |
| 130 | + WatchAction::doUnwatch( $title, $wgUser ); |
131 | 131 | } |
132 | 132 | $status = $file->delete( $reason, $suppress ); |
133 | 133 | if( $status->ok ) { |
Index: trunk/phase3/includes/SkinLegacy.php |
— | — | @@ -672,22 +672,31 @@ |
673 | 673 | } |
674 | 674 | |
675 | 675 | function watchThisPage() { |
676 | | - global $wgOut; |
| 676 | + global $wgOut, $wgUser; |
677 | 677 | ++$this->mWatchLinkNum; |
678 | 678 | |
| 679 | + // Cache |
| 680 | + $title = $this->getSkin()->getTitle(); |
| 681 | + |
679 | 682 | if ( $wgOut->isArticleRelated() ) { |
680 | | - if ( $this->getSkin()->getTitle()->userIsWatching() ) { |
| 683 | + if ( $title->userIsWatching() ) { |
681 | 684 | $text = wfMsg( 'unwatchthispage' ); |
682 | | - $query = array( 'action' => 'unwatch' ); |
| 685 | + $query = array( |
| 686 | + 'action' => 'unwatch', |
| 687 | + 'token' => UnwatchAction::getUnwatchToken( $title, $wgUser ), |
| 688 | + ); |
683 | 689 | $id = 'mw-unwatch-link' . $this->mWatchLinkNum; |
684 | 690 | } else { |
685 | 691 | $text = wfMsg( 'watchthispage' ); |
686 | | - $query = array( 'action' => 'watch' ); |
| 692 | + $query = array( |
| 693 | + 'action' => 'watch', |
| 694 | + 'token' => WatchAction::getWatchToken( $title, $wgUser ), |
| 695 | + ); |
687 | 696 | $id = 'mw-watch-link' . $this->mWatchLinkNum; |
688 | 697 | } |
689 | 698 | |
690 | 699 | $s = $this->getSkin()->link( |
691 | | - $this->getSkin()->getTitle(), |
| 700 | + $title, |
692 | 701 | $text, |
693 | 702 | array( 'id' => $id ), |
694 | 703 | $query, |
Index: trunk/phase3/includes/SkinTemplate.php |
— | — | @@ -1015,10 +1015,11 @@ |
1016 | 1016 | * the global versions. |
1017 | 1017 | */ |
1018 | 1018 | $mode = $title->userIsWatching() ? 'unwatch' : 'watch'; |
| 1019 | + $token = WatchAction::getWatchToken( $title, $wgUser, $mode ); |
1019 | 1020 | $content_navigation['actions'][$mode] = array( |
1020 | 1021 | 'class' => $onPage && ( $action == 'watch' || $action == 'unwatch' ) ? 'selected' : false, |
1021 | 1022 | 'text' => wfMsg( $mode ), // uses 'watch' or 'unwatch' message |
1022 | | - 'href' => $title->getLocalURL( 'action=' . $mode ) |
| 1023 | + 'href' => $title->getLocalURL( array( 'action' => $mode, 'token' => $token ) ) |
1023 | 1024 | ); |
1024 | 1025 | } |
1025 | 1026 | |