Index: trunk/phase3/includes/User.php |
— | — | @@ -2635,28 +2635,15 @@ |
2636 | 2636 | // The query to find out if it is watched is cached both in memcached and per-invocation, |
2637 | 2637 | // and when it does have to be executed, it can be on a slave |
2638 | 2638 | // If this is the user's newtalk page, we always update the timestamp |
2639 | | - if( $title->getNamespace() == NS_USER_TALK && |
| 2639 | + $force = ''; |
| 2640 | + if ( $title->getNamespace() == NS_USER_TALK && |
2640 | 2641 | $title->getText() == $this->getName() ) |
2641 | 2642 | { |
2642 | | - $watched = true; |
2643 | | - } else { |
2644 | | - $watched = $this->isWatched( $title ); |
| 2643 | + $force = 'force'; |
2645 | 2644 | } |
2646 | 2645 | |
2647 | | - // If the page is watched by the user (or may be watched), update the timestamp on any |
2648 | | - // any matching rows |
2649 | | - if ( $watched ) { |
2650 | | - $dbw = wfGetDB( DB_MASTER ); |
2651 | | - $dbw->update( 'watchlist', |
2652 | | - array( /* SET */ |
2653 | | - 'wl_notificationtimestamp' => null |
2654 | | - ), array( /* WHERE */ |
2655 | | - 'wl_title' => $title->getDBkey(), |
2656 | | - 'wl_namespace' => $title->getNamespace(), |
2657 | | - 'wl_user' => $this->getID() |
2658 | | - ), __METHOD__ |
2659 | | - ); |
2660 | | - } |
| 2646 | + $wi = WatchedItem::fromUserTitle( $this, $title ); |
| 2647 | + $wi->resetNotificationTimestamp( $force ); |
2661 | 2648 | } |
2662 | 2649 | |
2663 | 2650 | /** |
Index: trunk/phase3/includes/WatchedItem.php |
— | — | @@ -9,6 +9,7 @@ |
10 | 10 | */ |
11 | 11 | class WatchedItem { |
12 | 12 | var $mTitle, $mUser, $id, $ns, $ti; |
| 13 | + private $loaded = false, $watched, $timestamp; |
13 | 14 | |
14 | 15 | /** |
15 | 16 | * Create a WatchedItem object with the given user and title |
— | — | @@ -32,21 +33,86 @@ |
33 | 34 | } |
34 | 35 | |
35 | 36 | /** |
36 | | - * Is mTitle being watched by mUser? |
37 | | - * @return bool |
| 37 | + * Return an array of conditions to select or update the appropriate database |
| 38 | + * row. |
| 39 | + * |
| 40 | + * @return array |
38 | 41 | */ |
39 | | - public function isWatched() { |
| 42 | + private function dbCond() { |
| 43 | + return array( 'wl_user' => $this->id, 'wl_namespace' => $this->ns, 'wl_title' => $this->ti ); |
| 44 | + } |
| 45 | + |
| 46 | + /** |
| 47 | + * Load the object from the database |
| 48 | + */ |
| 49 | + private function load() { |
| 50 | + if ( $this->loaded ) { |
| 51 | + return; |
| 52 | + } |
| 53 | + $this->loaded = true; |
| 54 | + |
40 | 55 | # Pages and their talk pages are considered equivalent for watching; |
41 | 56 | # remember that talk namespaces are numbered as page namespace+1. |
42 | 57 | |
43 | 58 | $dbr = wfGetDB( DB_SLAVE ); |
44 | | - $res = $dbr->select( 'watchlist', 1, array( 'wl_user' => $this->id, 'wl_namespace' => $this->ns, |
45 | | - 'wl_title' => $this->ti ), __METHOD__ ); |
46 | | - $iswatched = ($dbr->numRows( $res ) > 0) ? 1 : 0; |
47 | | - return $iswatched; |
| 59 | + $row = $dbr->selectRow( 'watchlist', 'wl_notificationtimestamp', |
| 60 | + $this->dbCond(), __METHOD__ ); |
| 61 | + |
| 62 | + if ( $row === false ) { |
| 63 | + $this->watched = false; |
| 64 | + } else { |
| 65 | + $this->watched = true; |
| 66 | + $this->timestamp = $row->wl_notificationtimestamp; |
| 67 | + } |
48 | 68 | } |
49 | 69 | |
50 | 70 | /** |
| 71 | + * Is mTitle being watched by mUser? |
| 72 | + * @return bool |
| 73 | + */ |
| 74 | + public function isWatched() { |
| 75 | + $this->load(); |
| 76 | + return $this->watched; |
| 77 | + } |
| 78 | + |
| 79 | + /** |
| 80 | + * Get the notification timestamp of this entry. |
| 81 | + * |
| 82 | + * @return false|null|string: false if the page is not watched, the value of |
| 83 | + * the wl_notificationtimestamp field otherwise |
| 84 | + */ |
| 85 | + public function getNotificationTimestamp() { |
| 86 | + $this->load(); |
| 87 | + if ( $this->watched ) { |
| 88 | + return $this->timestamp; |
| 89 | + } else { |
| 90 | + return false; |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + /** |
| 95 | + * Reset the notification timestamp of this entry |
| 96 | + * |
| 97 | + * @param $force Whether to force the write query to be executed even if the |
| 98 | + * page is not watched or the notification timestamp is already NULL. |
| 99 | + */ |
| 100 | + public function resetNotificationTimestamp( $force = '' ) { |
| 101 | + if ( $force != 'force' ) { |
| 102 | + $this->load(); |
| 103 | + if ( !$this->watched || $this->timestamp === null ) { |
| 104 | + return; |
| 105 | + } |
| 106 | + } |
| 107 | + |
| 108 | + // If the page is watched by the user (or may be watched), update the timestamp on any |
| 109 | + // any matching rows |
| 110 | + $dbw = wfGetDB( DB_MASTER ); |
| 111 | + $dbw->update( 'watchlist', array( 'wl_notificationtimestamp' => null ), |
| 112 | + $this->dbCond(), __METHOD__ ); |
| 113 | + $this->timestamp = null; |
| 114 | + } |
| 115 | + |
| 116 | + /** |
51 | 117 | * Given a title and user (assumes the object is setup), add the watch to the |
52 | 118 | * database. |
53 | 119 | * @return bool (always true) |
— | — | @@ -75,6 +141,8 @@ |
76 | 142 | 'wl_notificationtimestamp' => null |
77 | 143 | ), __METHOD__, 'IGNORE' ); |
78 | 144 | |
| 145 | + $this->watched = true; |
| 146 | + |
79 | 147 | wfProfileOut( __METHOD__ ); |
80 | 148 | return true; |
81 | 149 | } |
— | — | @@ -115,6 +183,8 @@ |
116 | 184 | $success = true; |
117 | 185 | } |
118 | 186 | |
| 187 | + $this->watched = false; |
| 188 | + |
119 | 189 | wfProfileOut( __METHOD__ ); |
120 | 190 | return $success; |
121 | 191 | } |
— | — | @@ -139,7 +209,7 @@ |
140 | 210 | * |
141 | 211 | * @return bool |
142 | 212 | */ |
143 | | - private static function doDuplicateEntries( $ot, $nt ) { |
| 213 | + private static function doDuplicateEntries( $ot, $nt ) { |
144 | 214 | $oldnamespace = $ot->getNamespace(); |
145 | 215 | $newnamespace = $nt->getNamespace(); |
146 | 216 | $oldtitle = $ot->getDBkey(); |