Index: trunk/phase3/includes/WatchlistEditor.php |
— | — | @@ -25,6 +25,7 @@ |
26 | 26 | * @param int $mode |
27 | 27 | */ |
28 | 28 | public function execute( $user, $output, $request, $mode ) { |
| 29 | + global $wgUser; |
29 | 30 | if( wfReadOnly() ) { |
30 | 31 | $output->readOnlyPage(); |
31 | 32 | return; |
— | — | @@ -32,7 +33,7 @@ |
33 | 34 | switch( $mode ) { |
34 | 35 | case self::EDIT_CLEAR: |
35 | 36 | $output->setPageTitle( wfMsg( 'watchlistedit-clear-title' ) ); |
36 | | - if( $request->wasPosted() && $this->checkToken( $request, $user ) ) { |
| 37 | + if( $request->wasPosted() && $this->checkToken( $request, $wgUser ) ) { |
37 | 38 | $this->clearWatchlist( $user ); |
38 | 39 | $user->invalidateCache(); |
39 | 40 | $output->addHtml( wfMsgExt( 'watchlistedit-clear-done', 'parse' ) ); |
— | — | @@ -42,7 +43,7 @@ |
43 | 44 | break; |
44 | 45 | case self::EDIT_RAW: |
45 | 46 | $output->setPageTitle( wfMsg( 'watchlistedit-raw-title' ) ); |
46 | | - if( $request->wasPosted() && $this->checkToken( $request, $user ) ) { |
| 47 | + if( $request->wasPosted() && $this->checkToken( $request, $wgUser ) ) { |
47 | 48 | $current = $this->getWatchlist( $user ); |
48 | 49 | $wanted = $this->extractTitles( $request->getText( 'titles' ) ); |
49 | 50 | $toWatch = array_diff( $wanted, $current ); |
— | — | @@ -54,24 +55,24 @@ |
55 | 56 | $output->addHtml( wfMsgExt( 'watchlistedit-raw-done', 'parse' ) ); |
56 | 57 | if( ( $count = count( $toWatch ) ) > 0 ) { |
57 | 58 | $output->addHtml( wfMsgExt( 'watchlistedit-raw-added', 'parse', $count ) ); |
58 | | - $this->showTitles( $toWatch, $output, $user->getSkin() ); |
| 59 | + $this->showTitles( $toWatch, $output, $wgUser->getSkin() ); |
59 | 60 | } |
60 | 61 | if( ( $count = count( $toUnwatch ) ) > 0 ) { |
61 | 62 | $output->addHtml( wfMsgExt( 'watchlistedit-raw-removed', 'parse', $count ) ); |
62 | | - $this->showTitles( $toUnwatch, $output, $user->getSkin() ); |
| 63 | + $this->showTitles( $toUnwatch, $output, $wgUser->getSkin() ); |
63 | 64 | } |
64 | 65 | } |
65 | 66 | $this->showRawForm( $output, $user ); |
66 | 67 | break; |
67 | 68 | case self::EDIT_NORMAL: |
68 | 69 | $output->setPageTitle( wfMsg( 'watchlistedit-normal-title' ) ); |
69 | | - if( $request->wasPosted() && $this->checkToken( $request, $user ) ) { |
| 70 | + if( $request->wasPosted() && $this->checkToken( $request, $wgUser ) ) { |
70 | 71 | $titles = $this->extractTitles( $request->getArray( 'titles' ) ); |
71 | 72 | $this->unwatchTitles( $titles, $user ); |
72 | 73 | $user->invalidateCache(); |
73 | 74 | $output->addHtml( wfMsgExt( 'watchlistedit-normal-done', 'parse', |
74 | 75 | $GLOBALS['wgLang']->formatNum( count( $titles ) ) ) ); |
75 | | - $this->showTitles( $titles, $output, $user->getSkin() ); |
| 76 | + $this->showTitles( $titles, $output, $wgUser->getSkin() ); |
76 | 77 | } |
77 | 78 | $this->showNormalForm( $output, $user ); |
78 | 79 | } |
— | — | @@ -89,8 +90,8 @@ |
90 | 91 | } |
91 | 92 | |
92 | 93 | /** |
93 | | - * Extract a list of titles from a text list; if we're given |
94 | | - * an array, convert each item into a Title (ignores unwatchable titles) |
| 94 | + * Extract a list of titles from a blob of text, returning |
| 95 | + * (prefixed) strings; unwatchable titles are ignored |
95 | 96 | * |
96 | 97 | * @param mixed $list |
97 | 98 | * @return array |
— | — | @@ -107,7 +108,7 @@ |
108 | 109 | if( strlen( $text ) > 0 ) { |
109 | 110 | $title = Title::newFromText( $text ); |
110 | 111 | if( $title instanceof Title && $title->isWatchable() ) |
111 | | - $titles[] = $title; |
| 112 | + $titles[] = $title->getPrefixedText(); |
112 | 113 | } |
113 | 114 | } |
114 | 115 | return $titles; |
— | — | @@ -116,7 +117,10 @@ |
117 | 118 | /** |
118 | 119 | * Print out a list of linked titles |
119 | 120 | * |
120 | | - * @param array $titles |
| 121 | + * $titles can be an array of strings or Title objects; the former |
| 122 | + * is preferred, since Titles are very memory-heavy |
| 123 | + * |
| 124 | + * @param array $titles An array of strings, or Title objects |
121 | 125 | * @param OutputPage $output |
122 | 126 | * @param Skin $skin |
123 | 127 | */ |
— | — | @@ -125,15 +129,24 @@ |
126 | 130 | // Do a batch existence check |
127 | 131 | $batch = new LinkBatch(); |
128 | 132 | foreach( $titles as $title ) { |
129 | | - $batch->addObj( $title ); |
130 | | - $batch->addObj( $title->getTalkPage() ); |
| 133 | + if( !$title instanceof Title ) |
| 134 | + $title = Title::newFromText( $title ); |
| 135 | + if( $title instanceof Title ) { |
| 136 | + $batch->addObj( $title ); |
| 137 | + $batch->addObj( $title->getTalkPage() ); |
| 138 | + } |
131 | 139 | } |
132 | 140 | $batch->execute(); |
133 | 141 | // Print out the list |
134 | 142 | $output->addHtml( "<ul>\n" ); |
135 | | - foreach( $titles as $title ) |
136 | | - $output->addHtml( "<li>" . $skin->makeLinkObj( $title ) |
137 | | - . ' (' . $skin->makeLinkObj( $title->getTalkPage(), $talk ) . ")</li>\n" ); |
| 143 | + foreach( $titles as $title ) { |
| 144 | + if( !$title instanceof Title ) |
| 145 | + $title = Title::newFromText( $title ); |
| 146 | + if( $title instanceof Title ) { |
| 147 | + $output->addHtml( "<li>" . $skin->makeLinkObj( $title ) |
| 148 | + . ' (' . $skin->makeLinkObj( $title->getTalkPage(), $talk ) . ")</li>\n" ); |
| 149 | + } |
| 150 | + } |
138 | 151 | $output->addHtml( "</ul>\n" ); |
139 | 152 | } |
140 | 153 | |
— | — | @@ -151,24 +164,32 @@ |
152 | 165 | } |
153 | 166 | |
154 | 167 | /** |
155 | | - * Get a list of titles on a user's watchlist, excluding talk pages |
| 168 | + * Prepare a list of titles on a user's watchlist (excluding talk pages) |
| 169 | + * and return an array of (prefixed) strings |
156 | 170 | * |
157 | 171 | * @param User $user |
158 | 172 | * @return array |
159 | 173 | */ |
160 | 174 | private function getWatchlist( $user ) { |
161 | | - $titles = array(); |
| 175 | + $list = array(); |
162 | 176 | $dbr = wfGetDB( DB_SLAVE ); |
163 | | - $res = $dbr->select( 'watchlist', '*', array( 'wl_user' => $user->getId() ), __METHOD__ ); |
164 | | - if( $res && $dbr->numRows( $res ) > 0 ) { |
165 | | - while( $row = $dbr->fetchObject( $res ) ) { |
| 177 | + $res = $dbr->select( |
| 178 | + 'watchlist', |
| 179 | + '*', |
| 180 | + array( |
| 181 | + 'wl_user' => $user->getId(), |
| 182 | + ), |
| 183 | + __METHOD__ |
| 184 | + ); |
| 185 | + if( $res->numRows() > 0 ) { |
| 186 | + while( $row = $res->fetchObject() ) { |
166 | 187 | $title = Title::makeTitleSafe( $row->wl_namespace, $row->wl_title ); |
167 | 188 | if( $title instanceof Title && !$title->isTalkPage() ) |
168 | | - $titles[] = $title; |
| 189 | + $list[] = $title->getPrefixedText(); |
169 | 190 | } |
170 | | - $dbr->freeResult( $res ); |
| 191 | + $res->free(); |
171 | 192 | } |
172 | | - return $titles; |
| 193 | + return $list; |
173 | 194 | } |
174 | 195 | |
175 | 196 | /** |
— | — | @@ -239,25 +260,32 @@ |
240 | 261 | /** |
241 | 262 | * Add a list of titles to a user's watchlist |
242 | 263 | * |
243 | | - * @param array $titles |
| 264 | + * $titles can be an array of strings or Title objects; the former |
| 265 | + * is preferred, since Titles are very memory-heavy |
| 266 | + * |
| 267 | + * @param array $titles An array of strings, or Title objects |
244 | 268 | * @param User $user |
245 | 269 | */ |
246 | 270 | private function watchTitles( $titles, $user ) { |
247 | 271 | $dbw = wfGetDB( DB_MASTER ); |
248 | 272 | $rows = array(); |
249 | 273 | foreach( $titles as $title ) { |
250 | | - $rows[] = array( |
251 | | - 'wl_user' => $user->getId(), |
252 | | - 'wl_namespace' => ( $title->getNamespace() & ~1 ), |
253 | | - 'wl_title' => $title->getDBkey(), |
254 | | - 'wl_notificationtimestamp' => null, |
255 | | - ); |
256 | | - $rows[] = array( |
257 | | - 'wl_user' => $user->getId(), |
258 | | - 'wl_namespace' => ( $title->getNamespace() | 1 ), |
259 | | - 'wl_title' => $title->getDBkey(), |
260 | | - 'wl_notificationtimestamp' => null, |
261 | | - ); |
| 274 | + if( !$title instanceof Title ) |
| 275 | + $title = Title::newFromText( $title ); |
| 276 | + if( $title instanceof Title ) { |
| 277 | + $rows[] = array( |
| 278 | + 'wl_user' => $user->getId(), |
| 279 | + 'wl_namespace' => ( $title->getNamespace() & ~1 ), |
| 280 | + 'wl_title' => $title->getDBkey(), |
| 281 | + 'wl_notificationtimestamp' => null, |
| 282 | + ); |
| 283 | + $rows[] = array( |
| 284 | + 'wl_user' => $user->getId(), |
| 285 | + 'wl_namespace' => ( $title->getNamespace() | 1 ), |
| 286 | + 'wl_title' => $title->getDBkey(), |
| 287 | + 'wl_notificationtimestamp' => null, |
| 288 | + ); |
| 289 | + } |
262 | 290 | } |
263 | 291 | $dbw->insert( 'watchlist', $rows, __METHOD__, 'IGNORE' ); |
264 | 292 | } |
— | — | @@ -265,30 +293,37 @@ |
266 | 294 | /** |
267 | 295 | * Remove a list of titles from a user's watchlist |
268 | 296 | * |
269 | | - * @param array $titles |
| 297 | + * $titles can be an array of strings or Title objects; the former |
| 298 | + * is preferred, since Titles are very memory-heavy |
| 299 | + * |
| 300 | + * @param array $titles An array of strings, or Title objects |
270 | 301 | * @param User $user |
271 | 302 | */ |
272 | 303 | private function unwatchTitles( $titles, $user ) { |
273 | 304 | $dbw = wfGetDB( DB_MASTER ); |
274 | 305 | foreach( $titles as $title ) { |
275 | | - $dbw->delete( |
276 | | - 'watchlist', |
277 | | - array( |
278 | | - 'wl_user' => $user->getId(), |
279 | | - 'wl_namespace' => ( $title->getNamespace() & ~1 ), |
280 | | - 'wl_title' => $title->getDBkey(), |
281 | | - ), |
282 | | - __METHOD__ |
283 | | - ); |
284 | | - $dbw->delete( |
285 | | - 'watchlist', |
286 | | - array( |
287 | | - 'wl_user' => $user->getId(), |
288 | | - 'wl_namespace' => ( $title->getNamespace() | 1 ), |
289 | | - 'wl_title' => $title->getDBkey(), |
290 | | - ), |
291 | | - __METHOD__ |
292 | | - ); |
| 306 | + if( !$title instanceof Title ) |
| 307 | + $title = Title::newFromText( $title ); |
| 308 | + if( $title instanceof Title ) { |
| 309 | + $dbw->delete( |
| 310 | + 'watchlist', |
| 311 | + array( |
| 312 | + 'wl_user' => $user->getId(), |
| 313 | + 'wl_namespace' => ( $title->getNamespace() & ~1 ), |
| 314 | + 'wl_title' => $title->getDBkey(), |
| 315 | + ), |
| 316 | + __METHOD__ |
| 317 | + ); |
| 318 | + $dbw->delete( |
| 319 | + 'watchlist', |
| 320 | + array( |
| 321 | + 'wl_user' => $user->getId(), |
| 322 | + 'wl_namespace' => ( $title->getNamespace() | 1 ), |
| 323 | + 'wl_title' => $title->getDBkey(), |
| 324 | + ), |
| 325 | + __METHOD__ |
| 326 | + ); |
| 327 | + } |
293 | 328 | } |
294 | 329 | } |
295 | 330 | |
— | — | @@ -299,11 +334,12 @@ |
300 | 335 | * @param User $user |
301 | 336 | */ |
302 | 337 | private function showClearForm( $output, $user ) { |
| 338 | + global $wgUser; |
303 | 339 | if( ( $count = $this->showItemCount( $output, $user ) ) > 0 ) { |
304 | 340 | $self = SpecialPage::getTitleFor( 'Watchlist' ); |
305 | 341 | $form = Xml::openElement( 'form', array( 'method' => 'post', |
306 | 342 | 'action' => $self->getLocalUrl( 'action=clear' ) ) ); |
307 | | - $form .= Xml::hidden( 'token', $user->editToken( 'watchlistedit' ) ); |
| 343 | + $form .= Xml::hidden( 'token', $wgUser->editToken( 'watchlistedit' ) ); |
308 | 344 | $form .= '<fieldset><legend>' . wfMsgHtml( 'watchlistedit-clear-legend' ) . '</legend>'; |
309 | 345 | $form .= wfMsgExt( 'watchlistedit-clear-confirm', 'parse' ); |
310 | 346 | $form .= '<p>' . Xml::submitButton( wfMsg( 'watchlistedit-clear-submit' ) ) . '</p>'; |
— | — | @@ -319,11 +355,12 @@ |
320 | 356 | * @param User $user |
321 | 357 | */ |
322 | 358 | private function showNormalForm( $output, $user ) { |
| 359 | + global $wgUser; |
323 | 360 | if( ( $count = $this->showItemCount( $output, $user ) ) > 0 ) { |
324 | 361 | $self = SpecialPage::getTitleFor( 'Watchlist' ); |
325 | 362 | $form = Xml::openElement( 'form', array( 'method' => 'post', |
326 | 363 | 'action' => $self->getLocalUrl( 'action=edit' ) ) ); |
327 | | - $form .= Xml::hidden( 'token', $user->editToken( 'watchlistedit' ) ); |
| 364 | + $form .= Xml::hidden( 'token', $wgUser->editToken( 'watchlistedit' ) ); |
328 | 365 | $form .= '<fieldset><legend>' . wfMsgHtml( 'watchlistedit-normal-legend' ) . '</legend>'; |
329 | 366 | $form .= wfMsgExt( 'watchlistedit-normal-explain', 'parse' ); |
330 | 367 | foreach( $this->getWatchlistInfo( $user ) as $namespace => $pages ) { |
— | — | @@ -331,7 +368,7 @@ |
332 | 369 | $form .= '<ul>'; |
333 | 370 | foreach( $pages as $dbkey => $redirect ) { |
334 | 371 | $title = Title::makeTitleSafe( $namespace, $dbkey ); |
335 | | - $form .= $this->buildRemoveLine( $title, $redirect, $user->getSkin() ); |
| 372 | + $form .= $this->buildRemoveLine( $title, $redirect, $wgUser->getSkin() ); |
336 | 373 | } |
337 | 374 | $form .= '</ul>'; |
338 | 375 | } |
— | — | @@ -382,18 +419,20 @@ |
383 | 420 | * @param User $user |
384 | 421 | */ |
385 | 422 | public function showRawForm( $output, $user ) { |
| 423 | + global $wgUser; |
386 | 424 | $this->showItemCount( $output, $user ); |
387 | 425 | $self = SpecialPage::getTitleFor( 'Watchlist' ); |
388 | 426 | $form = Xml::openElement( 'form', array( 'method' => 'post', |
389 | 427 | 'action' => $self->getLocalUrl( 'action=raw' ) ) ); |
390 | | - $form .= Xml::hidden( 'token', $user->editToken( 'watchlistedit' ) ); |
| 428 | + $form .= Xml::hidden( 'token', $wgUser->editToken( 'watchlistedit' ) ); |
391 | 429 | $form .= '<fieldset><legend>' . wfMsgHtml( 'watchlistedit-raw-legend' ) . '</legend>'; |
392 | 430 | $form .= wfMsgExt( 'watchlistedit-raw-explain', 'parse' ); |
393 | 431 | $form .= Xml::label( wfMsg( 'watchlistedit-raw-titles' ), 'titles' ); |
394 | 432 | $form .= Xml::openElement( 'textarea', array( 'id' => 'titles', 'name' => 'titles', |
395 | | - 'rows' => 6, 'cols' => 80 ) ); |
396 | | - foreach( $this->getWatchlist( $user ) as $title ) |
397 | | - $form .= htmlspecialchars( $title->getPrefixedText() ) . "\n"; |
| 433 | + 'rows' => $wgUser->getIntOption( 'rows' ), 'cols' => $wgUser->getIntOption( 'cols' ) ) ); |
| 434 | + $titles = $this->getWatchlist( $user ); |
| 435 | + foreach( $titles as $title ) |
| 436 | + $form .= htmlspecialchars( $title ) . "\n"; |
398 | 437 | $form .= '</textarea>'; |
399 | 438 | $form .= '<p>' . Xml::submitButton( wfMsg( 'watchlistedit-raw-submit' ) ) . '</p>'; |
400 | 439 | $form .= '</fieldset></form>'; |