[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/specials/ -> SpecialEditWatchlist.php (source)

   1  <?php
   2  /**
   3   * @defgroup Watchlist Users watchlist handling
   4   */
   5  
   6  /**
   7   * Implements Special:EditWatchlist
   8   *
   9   * This program is free software; you can redistribute it and/or modify
  10   * it under the terms of the GNU General Public License as published by
  11   * the Free Software Foundation; either version 2 of the License, or
  12   * (at your option) any later version.
  13   *
  14   * This program is distributed in the hope that it will be useful,
  15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17   * GNU General Public License for more details.
  18   *
  19   * You should have received a copy of the GNU General Public License along
  20   * with this program; if not, write to the Free Software Foundation, Inc.,
  21   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  22   * http://www.gnu.org/copyleft/gpl.html
  23   *
  24   * @file
  25   * @ingroup SpecialPage
  26   * @ingroup Watchlist
  27   */
  28  
  29  /**
  30   * Provides the UI through which users can perform editing
  31   * operations on their watchlist
  32   *
  33   * @ingroup SpecialPage
  34   * @ingroup Watchlist
  35   * @author Rob Church <[email protected]>
  36   */
  37  class SpecialEditWatchlist extends UnlistedSpecialPage {
  38      /**
  39       * Editing modes. EDIT_CLEAR is no longer used; the "Clear" link scared people
  40       * too much. Now it's passed on to the raw editor, from which it's very easy to clear.
  41       */
  42      const EDIT_CLEAR = 1;
  43      const EDIT_RAW = 2;
  44      const EDIT_NORMAL = 3;
  45  
  46      protected $successMessage;
  47  
  48      protected $toc;
  49  
  50      private $badItems = array();
  51  
  52  	public function __construct() {
  53          parent::__construct( 'EditWatchlist', 'editmywatchlist' );
  54      }
  55  
  56      /**
  57       * Main execution point
  58       *
  59       * @param int $mode
  60       */
  61  	public function execute( $mode ) {
  62          $this->setHeaders();
  63  
  64          # Anons don't get a watchlist
  65          $this->requireLogin( 'watchlistanontext' );
  66  
  67          $out = $this->getOutput();
  68  
  69          $this->checkPermissions();
  70          $this->checkReadOnly();
  71  
  72          $this->outputHeader();
  73          $this->outputSubtitle();
  74  
  75          # B/C: $mode used to be waaay down the parameter list, and the first parameter
  76          # was $wgUser
  77          if ( $mode instanceof User ) {
  78              $args = func_get_args();
  79              if ( count( $args ) >= 4 ) {
  80                  $mode = $args[3];
  81              }
  82          }
  83          $mode = self::getMode( $this->getRequest(), $mode );
  84  
  85          switch ( $mode ) {
  86              case self::EDIT_RAW:
  87                  $out->setPageTitle( $this->msg( 'watchlistedit-raw-title' ) );
  88                  $form = $this->getRawForm();
  89                  if ( $form->show() ) {
  90                      $out->addHTML( $this->successMessage );
  91                      $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) );
  92                  }
  93                  break;
  94              case self::EDIT_CLEAR:
  95                  $out->setPageTitle( $this->msg( 'watchlistedit-clear-title' ) );
  96                  $form = $this->getClearForm();
  97                  if ( $form->show() ) {
  98                      $out->addHTML( $this->successMessage );
  99                      $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) );
 100                  }
 101                  break;
 102  
 103              case self::EDIT_NORMAL:
 104              default:
 105              $this->executeViewEditWatchlist();
 106                  break;
 107          }
 108      }
 109  
 110      /**
 111       * Renders a subheader on the watchlist page.
 112       */
 113  	protected function outputSubtitle() {
 114          $out = $this->getOutput();
 115          $out->addSubtitle( $this->msg( 'watchlistfor2', $this->getUser()->getName() )
 116              ->rawParams( SpecialEditWatchlist::buildTools( null ) ) );
 117      }
 118  
 119      /**
 120       * Executes an edit mode for the watchlist view, from which you can manage your watchlist
 121       *
 122       */
 123  	protected function executeViewEditWatchlist() {
 124          $out = $this->getOutput();
 125          $out->setPageTitle( $this->msg( 'watchlistedit-normal-title' ) );
 126          $form = $this->getNormalForm();
 127          if ( $form->show() ) {
 128              $out->addHTML( $this->successMessage );
 129              $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) );
 130          } elseif ( $this->toc !== false ) {
 131              $out->prependHTML( $this->toc );
 132              $out->addModules( 'mediawiki.toc' );
 133          }
 134      }
 135  
 136      /**
 137       * Return an array of subpages beginning with $search that this special page will accept.
 138       *
 139       * @param string $search Prefix to search for
 140       * @param int $limit Maximum number of results to return
 141       * @return string[] Matching subpages
 142       */
 143  	public function prefixSearchSubpages( $search, $limit = 10 ) {
 144          return self::prefixSearchArray(
 145              $search,
 146              $limit,
 147              // SpecialWatchlist uses SpecialEditWatchlist::getMode, so new types should be added
 148              // here and there - no 'edit' here, because that the default for this page
 149              array(
 150                  'clear',
 151                  'raw',
 152              )
 153          );
 154      }
 155  
 156      /**
 157       * Extract a list of titles from a blob of text, returning
 158       * (prefixed) strings; unwatchable titles are ignored
 159       *
 160       * @param string $list
 161       * @return array
 162       */
 163  	private function extractTitles( $list ) {
 164          $list = explode( "\n", trim( $list ) );
 165          if ( !is_array( $list ) ) {
 166              return array();
 167          }
 168  
 169          $titles = array();
 170  
 171          foreach ( $list as $text ) {
 172              $text = trim( $text );
 173              if ( strlen( $text ) > 0 ) {
 174                  $title = Title::newFromText( $text );
 175                  if ( $title instanceof Title && $title->isWatchable() ) {
 176                      $titles[] = $title;
 177                  }
 178              }
 179          }
 180  
 181          GenderCache::singleton()->doTitlesArray( $titles );
 182  
 183          $list = array();
 184          /** @var Title $title */
 185          foreach ( $titles as $title ) {
 186              $list[] = $title->getPrefixedText();
 187          }
 188  
 189          return array_unique( $list );
 190      }
 191  
 192  	public function submitRaw( $data ) {
 193          $wanted = $this->extractTitles( $data['Titles'] );
 194          $current = $this->getWatchlist();
 195  
 196          if ( count( $wanted ) > 0 ) {
 197              $toWatch = array_diff( $wanted, $current );
 198              $toUnwatch = array_diff( $current, $wanted );
 199              $this->watchTitles( $toWatch );
 200              $this->unwatchTitles( $toUnwatch );
 201              $this->getUser()->invalidateCache();
 202  
 203              if ( count( $toWatch ) > 0 || count( $toUnwatch ) > 0 ) {
 204                  $this->successMessage = $this->msg( 'watchlistedit-raw-done' )->parse();
 205              } else {
 206                  return false;
 207              }
 208  
 209              if ( count( $toWatch ) > 0 ) {
 210                  $this->successMessage .= ' ' . $this->msg( 'watchlistedit-raw-added' )
 211                      ->numParams( count( $toWatch ) )->parse();
 212                  $this->showTitles( $toWatch, $this->successMessage );
 213              }
 214  
 215              if ( count( $toUnwatch ) > 0 ) {
 216                  $this->successMessage .= ' ' . $this->msg( 'watchlistedit-raw-removed' )
 217                      ->numParams( count( $toUnwatch ) )->parse();
 218                  $this->showTitles( $toUnwatch, $this->successMessage );
 219              }
 220          } else {
 221              $this->clearWatchlist();
 222              $this->getUser()->invalidateCache();
 223  
 224              if ( count( $current ) > 0 ) {
 225                  $this->successMessage = $this->msg( 'watchlistedit-raw-done' )->parse();
 226              } else {
 227                  return false;
 228              }
 229  
 230              $this->successMessage .= ' ' . $this->msg( 'watchlistedit-raw-removed' )
 231                  ->numParams( count( $current ) )->parse();
 232              $this->showTitles( $current, $this->successMessage );
 233          }
 234  
 235          return true;
 236      }
 237  
 238  	public function submitClear( $data ) {
 239          $current = $this->getWatchlist();
 240          $this->clearWatchlist();
 241          $this->getUser()->invalidateCache();
 242          $this->successMessage = $this->msg( 'watchlistedit-clear-done' )->parse();
 243          $this->successMessage .= ' ' . $this->msg( 'watchlistedit-clear-removed' )
 244              ->numParams( count( $current ) )->parse();
 245          $this->showTitles( $current, $this->successMessage );
 246  
 247          return true;
 248      }
 249  
 250      /**
 251       * Print out a list of linked titles
 252       *
 253       * $titles can be an array of strings or Title objects; the former
 254       * is preferred, since Titles are very memory-heavy
 255       *
 256       * @param array $titles Array of strings, or Title objects
 257       * @param string $output
 258       */
 259  	private function showTitles( $titles, &$output ) {
 260          $talk = $this->msg( 'talkpagelinktext' )->escaped();
 261          // Do a batch existence check
 262          $batch = new LinkBatch();
 263          if ( count( $titles ) >= 100 ) {
 264              $output = wfMessage( 'watchlistedit-too-many' )->parse();
 265              return;
 266          }
 267          foreach ( $titles as $title ) {
 268              if ( !$title instanceof Title ) {
 269                  $title = Title::newFromText( $title );
 270              }
 271  
 272              if ( $title instanceof Title ) {
 273                  $batch->addObj( $title );
 274                  $batch->addObj( $title->getTalkPage() );
 275              }
 276          }
 277  
 278          $batch->execute();
 279  
 280          // Print out the list
 281          $output .= "<ul>\n";
 282  
 283          foreach ( $titles as $title ) {
 284              if ( !$title instanceof Title ) {
 285                  $title = Title::newFromText( $title );
 286              }
 287  
 288              if ( $title instanceof Title ) {
 289                  $output .= "<li>"
 290                      . Linker::link( $title )
 291                      . ' (' . Linker::link( $title->getTalkPage(), $talk )
 292                      . ")</li>\n";
 293              }
 294          }
 295  
 296          $output .= "</ul>\n";
 297      }
 298  
 299      /**
 300       * Prepare a list of titles on a user's watchlist (excluding talk pages)
 301       * and return an array of (prefixed) strings
 302       *
 303       * @return array
 304       */
 305  	private function getWatchlist() {
 306          $list = array();
 307          $dbr = wfGetDB( DB_MASTER );
 308  
 309          $res = $dbr->select(
 310              'watchlist',
 311              array(
 312                  'wl_namespace', 'wl_title'
 313              ), array(
 314                  'wl_user' => $this->getUser()->getId(),
 315              ),
 316              __METHOD__
 317          );
 318  
 319          if ( $res->numRows() > 0 ) {
 320              $titles = array();
 321              foreach ( $res as $row ) {
 322                  $title = Title::makeTitleSafe( $row->wl_namespace, $row->wl_title );
 323  
 324                  if ( $this->checkTitle( $title, $row->wl_namespace, $row->wl_title )
 325                      && !$title->isTalkPage()
 326                  ) {
 327                      $titles[] = $title;
 328                  }
 329              }
 330              $res->free();
 331  
 332              GenderCache::singleton()->doTitlesArray( $titles );
 333  
 334              foreach ( $titles as $title ) {
 335                  $list[] = $title->getPrefixedText();
 336              }
 337          }
 338  
 339          $this->cleanupWatchlist();
 340  
 341          return $list;
 342      }
 343  
 344      /**
 345       * Get a list of titles on a user's watchlist, excluding talk pages,
 346       * and return as a two-dimensional array with namespace and title.
 347       *
 348       * @return array
 349       */
 350  	protected function getWatchlistInfo() {
 351          $titles = array();
 352          $dbr = wfGetDB( DB_MASTER );
 353  
 354          $res = $dbr->select(
 355              array( 'watchlist' ),
 356              array( 'wl_namespace', 'wl_title' ),
 357              array( 'wl_user' => $this->getUser()->getId() ),
 358              __METHOD__,
 359              array( 'ORDER BY' => array( 'wl_namespace', 'wl_title' ) )
 360          );
 361  
 362          $lb = new LinkBatch();
 363  
 364          foreach ( $res as $row ) {
 365              $lb->add( $row->wl_namespace, $row->wl_title );
 366              if ( !MWNamespace::isTalk( $row->wl_namespace ) ) {
 367                  $titles[$row->wl_namespace][$row->wl_title] = 1;
 368              }
 369          }
 370  
 371          $lb->execute();
 372  
 373          return $titles;
 374      }
 375  
 376      /**
 377       * Validates watchlist entry
 378       *
 379       * @param Title $title
 380       * @param int $namespace
 381       * @param string $dbKey
 382       * @return bool Whether this item is valid
 383       */
 384  	private function checkTitle( $title, $namespace, $dbKey ) {
 385          if ( $title
 386              && ( $title->isExternal()
 387                  || $title->getNamespace() < 0
 388              )
 389          ) {
 390              $title = false; // unrecoverable
 391          }
 392  
 393          if ( !$title
 394              || $title->getNamespace() != $namespace
 395              || $title->getDBkey() != $dbKey
 396          ) {
 397              $this->badItems[] = array( $title, $namespace, $dbKey );
 398          }
 399  
 400          return (bool)$title;
 401      }
 402  
 403      /**
 404       * Attempts to clean up broken items
 405       */
 406  	private function cleanupWatchlist() {
 407          if ( !count( $this->badItems ) ) {
 408              return; //nothing to do
 409          }
 410  
 411          $dbw = wfGetDB( DB_MASTER );
 412          $user = $this->getUser();
 413  
 414          foreach ( $this->badItems as $row ) {
 415              list( $title, $namespace, $dbKey ) = $row;
 416              $action = $title ? 'cleaning up' : 'deleting';
 417              wfDebug( "User {$user->getName()} has broken watchlist item ns($namespace):$dbKey, $action.\n" );
 418  
 419              $dbw->delete( 'watchlist',
 420                  array(
 421                      'wl_user' => $user->getId(),
 422                      'wl_namespace' => $namespace,
 423                      'wl_title' => $dbKey,
 424                  ),
 425                  __METHOD__
 426              );
 427  
 428              // Can't just do an UPDATE instead of DELETE/INSERT due to unique index
 429              if ( $title ) {
 430                  $user->addWatch( $title );
 431              }
 432          }
 433      }
 434  
 435      /**
 436       * Remove all titles from a user's watchlist
 437       */
 438  	private function clearWatchlist() {
 439          $dbw = wfGetDB( DB_MASTER );
 440          $dbw->delete(
 441              'watchlist',
 442              array( 'wl_user' => $this->getUser()->getId() ),
 443              __METHOD__
 444          );
 445      }
 446  
 447      /**
 448       * Add a list of titles to a user's watchlist
 449       *
 450       * $titles can be an array of strings or Title objects; the former
 451       * is preferred, since Titles are very memory-heavy
 452       *
 453       * @param array $titles Array of strings, or Title objects
 454       */
 455  	private function watchTitles( $titles ) {
 456          $dbw = wfGetDB( DB_MASTER );
 457          $rows = array();
 458  
 459          foreach ( $titles as $title ) {
 460              if ( !$title instanceof Title ) {
 461                  $title = Title::newFromText( $title );
 462              }
 463  
 464              if ( $title instanceof Title ) {
 465                  $rows[] = array(
 466                      'wl_user' => $this->getUser()->getId(),
 467                      'wl_namespace' => MWNamespace::getSubject( $title->getNamespace() ),
 468                      'wl_title' => $title->getDBkey(),
 469                      'wl_notificationtimestamp' => null,
 470                  );
 471                  $rows[] = array(
 472                      'wl_user' => $this->getUser()->getId(),
 473                      'wl_namespace' => MWNamespace::getTalk( $title->getNamespace() ),
 474                      'wl_title' => $title->getDBkey(),
 475                      'wl_notificationtimestamp' => null,
 476                  );
 477              }
 478          }
 479  
 480          $dbw->insert( 'watchlist', $rows, __METHOD__, 'IGNORE' );
 481      }
 482  
 483      /**
 484       * Remove a list of titles from a user's watchlist
 485       *
 486       * $titles can be an array of strings or Title objects; the former
 487       * is preferred, since Titles are very memory-heavy
 488       *
 489       * @param array $titles Array of strings, or Title objects
 490       */
 491  	private function unwatchTitles( $titles ) {
 492          $dbw = wfGetDB( DB_MASTER );
 493  
 494          foreach ( $titles as $title ) {
 495              if ( !$title instanceof Title ) {
 496                  $title = Title::newFromText( $title );
 497              }
 498  
 499              if ( $title instanceof Title ) {
 500                  $dbw->delete(
 501                      'watchlist',
 502                      array(
 503                          'wl_user' => $this->getUser()->getId(),
 504                          'wl_namespace' => MWNamespace::getSubject( $title->getNamespace() ),
 505                          'wl_title' => $title->getDBkey(),
 506                      ),
 507                      __METHOD__
 508                  );
 509  
 510                  $dbw->delete(
 511                      'watchlist',
 512                      array(
 513                          'wl_user' => $this->getUser()->getId(),
 514                          'wl_namespace' => MWNamespace::getTalk( $title->getNamespace() ),
 515                          'wl_title' => $title->getDBkey(),
 516                      ),
 517                      __METHOD__
 518                  );
 519  
 520                  $page = WikiPage::factory( $title );
 521                  wfRunHooks( 'UnwatchArticleComplete', array( $this->getUser(), &$page ) );
 522              }
 523          }
 524      }
 525  
 526  	public function submitNormal( $data ) {
 527          $removed = array();
 528  
 529          foreach ( $data as $titles ) {
 530              $this->unwatchTitles( $titles );
 531              $removed = array_merge( $removed, $titles );
 532          }
 533  
 534          if ( count( $removed ) > 0 ) {
 535              $this->successMessage = $this->msg( 'watchlistedit-normal-done'
 536              )->numParams( count( $removed ) )->parse();
 537              $this->showTitles( $removed, $this->successMessage );
 538  
 539              return true;
 540          } else {
 541              return false;
 542          }
 543      }
 544  
 545      /**
 546       * Get the standard watchlist editing form
 547       *
 548       * @return HTMLForm
 549       */
 550  	protected function getNormalForm() {
 551          global $wgContLang;
 552  
 553          $fields = array();
 554          $count = 0;
 555  
 556          // Allow subscribers to manipulate the list of watched pages (or use it
 557          // to preload lots of details at once)
 558          $watchlistInfo = $this->getWatchlistInfo();
 559          wfRunHooks(
 560              'WatchlistEditorBeforeFormRender',
 561              array( &$watchlistInfo )
 562          );
 563  
 564          foreach ( $watchlistInfo as $namespace => $pages ) {
 565              $options = array();
 566  
 567              foreach ( array_keys( $pages ) as $dbkey ) {
 568                  $title = Title::makeTitleSafe( $namespace, $dbkey );
 569  
 570                  if ( $this->checkTitle( $title, $namespace, $dbkey ) ) {
 571                      $text = $this->buildRemoveLine( $title );
 572                      $options[$text] = $title->getPrefixedText();
 573                      $count++;
 574                  }
 575              }
 576  
 577              // checkTitle can filter some options out, avoid empty sections
 578              if ( count( $options ) > 0 ) {
 579                  $fields['TitlesNs' . $namespace] = array(
 580                      'class' => 'EditWatchlistCheckboxSeriesField',
 581                      'options' => $options,
 582                      'section' => "ns$namespace",
 583                  );
 584              }
 585          }
 586          $this->cleanupWatchlist();
 587  
 588          if ( count( $fields ) > 1 && $count > 30 ) {
 589              $this->toc = Linker::tocIndent();
 590              $tocLength = 0;
 591  
 592              foreach ( $fields as $data ) {
 593                  # strip out the 'ns' prefix from the section name:
 594                  $ns = substr( $data['section'], 2 );
 595  
 596                  $nsText = ( $ns == NS_MAIN )
 597                      ? $this->msg( 'blanknamespace' )->escaped()
 598                      : htmlspecialchars( $wgContLang->getFormattedNsText( $ns ) );
 599                  $this->toc .= Linker::tocLine( "editwatchlist-{$data['section']}", $nsText,
 600                      $this->getLanguage()->formatNum( ++$tocLength ), 1 ) . Linker::tocLineEnd();
 601              }
 602  
 603              $this->toc = Linker::tocList( $this->toc );
 604          } else {
 605              $this->toc = false;
 606          }
 607  
 608          $context = new DerivativeContext( $this->getContext() );
 609          $context->setTitle( $this->getPageTitle() ); // Remove subpage
 610          $form = new EditWatchlistNormalHTMLForm( $fields, $context );
 611          $form->setSubmitTextMsg( 'watchlistedit-normal-submit' );
 612          # Used message keys:
 613          # 'accesskey-watchlistedit-normal-submit', 'tooltip-watchlistedit-normal-submit'
 614          $form->setSubmitTooltip( 'watchlistedit-normal-submit' );
 615          $form->setWrapperLegendMsg( 'watchlistedit-normal-legend' );
 616          $form->addHeaderText( $this->msg( 'watchlistedit-normal-explain' )->parse() );
 617          $form->setSubmitCallback( array( $this, 'submitNormal' ) );
 618  
 619          return $form;
 620      }
 621  
 622      /**
 623       * Build the label for a checkbox, with a link to the title, and various additional bits
 624       *
 625       * @param Title $title
 626       * @return string
 627       */
 628  	private function buildRemoveLine( $title ) {
 629          $link = Linker::link( $title );
 630  
 631          $tools['talk'] = Linker::link( $title->getTalkPage(), $this->msg( 'talkpagelinktext' )->escaped() );
 632  
 633          if ( $title->exists() ) {
 634              $tools['history'] = Linker::linkKnown(
 635                  $title,
 636                  $this->msg( 'history_short' )->escaped(),
 637                  array(),
 638                  array( 'action' => 'history' )
 639              );
 640          }
 641  
 642          if ( $title->getNamespace() == NS_USER && !$title->isSubpage() ) {
 643              $tools['contributions'] = Linker::linkKnown(
 644                  SpecialPage::getTitleFor( 'Contributions', $title->getText() ),
 645                  $this->msg( 'contributions' )->escaped()
 646              );
 647          }
 648  
 649          wfRunHooks(
 650              'WatchlistEditorBuildRemoveLine',
 651              array( &$tools, $title, $title->isRedirect(), $this->getSkin(), &$link )
 652          );
 653  
 654          if ( $title->isRedirect() ) {
 655              // Linker already makes class mw-redirect, so this is redundant
 656              $link = '<span class="watchlistredir">' . $link . '</span>';
 657          }
 658  
 659          return $link . " (" . $this->getLanguage()->pipeList( $tools ) . ")";
 660      }
 661  
 662      /**
 663       * Get a form for editing the watchlist in "raw" mode
 664       *
 665       * @return HTMLForm
 666       */
 667  	protected function getRawForm() {
 668          $titles = implode( $this->getWatchlist(), "\n" );
 669          $fields = array(
 670              'Titles' => array(
 671                  'type' => 'textarea',
 672                  'label-message' => 'watchlistedit-raw-titles',
 673                  'default' => $titles,
 674              ),
 675          );
 676          $context = new DerivativeContext( $this->getContext() );
 677          $context->setTitle( $this->getPageTitle( 'raw' ) ); // Reset subpage
 678          $form = new HTMLForm( $fields, $context );
 679          $form->setSubmitTextMsg( 'watchlistedit-raw-submit' );
 680          # Used message keys: 'accesskey-watchlistedit-raw-submit', 'tooltip-watchlistedit-raw-submit'
 681          $form->setSubmitTooltip( 'watchlistedit-raw-submit' );
 682          $form->setWrapperLegendMsg( 'watchlistedit-raw-legend' );
 683          $form->addHeaderText( $this->msg( 'watchlistedit-raw-explain' )->parse() );
 684          $form->setSubmitCallback( array( $this, 'submitRaw' ) );
 685  
 686          return $form;
 687      }
 688  
 689      /**
 690       * Get a form for clearing the watchlist
 691       *
 692       * @return HTMLForm
 693       */
 694  	protected function getClearForm() {
 695          $context = new DerivativeContext( $this->getContext() );
 696          $context->setTitle( $this->getPageTitle( 'clear' ) ); // Reset subpage
 697          $form = new HTMLForm( array(), $context );
 698          $form->setSubmitTextMsg( 'watchlistedit-clear-submit' );
 699          # Used message keys: 'accesskey-watchlistedit-clear-submit', 'tooltip-watchlistedit-clear-submit'
 700          $form->setSubmitTooltip( 'watchlistedit-clear-submit' );
 701          $form->setWrapperLegendMsg( 'watchlistedit-clear-legend' );
 702          $form->addHeaderText( $this->msg( 'watchlistedit-clear-explain' )->parse() );
 703          $form->setSubmitCallback( array( $this, 'submitClear' ) );
 704  
 705          return $form;
 706      }
 707  
 708      /**
 709       * Determine whether we are editing the watchlist, and if so, what
 710       * kind of editing operation
 711       *
 712       * @param WebRequest $request
 713       * @param string $par
 714       * @return int
 715       */
 716  	public static function getMode( $request, $par ) {
 717          $mode = strtolower( $request->getVal( 'action', $par ) );
 718  
 719          switch ( $mode ) {
 720              case 'clear':
 721              case self::EDIT_CLEAR:
 722                  return self::EDIT_CLEAR;
 723              case 'raw':
 724              case self::EDIT_RAW:
 725                  return self::EDIT_RAW;
 726              case 'edit':
 727              case self::EDIT_NORMAL:
 728                  return self::EDIT_NORMAL;
 729              default:
 730                  return false;
 731          }
 732      }
 733  
 734      /**
 735       * Build a set of links for convenient navigation
 736       * between watchlist viewing and editing modes
 737       *
 738       * @param null $unused
 739       * @return string
 740       */
 741  	public static function buildTools( $unused ) {
 742          global $wgLang;
 743  
 744          $tools = array();
 745          $modes = array(
 746              'view' => array( 'Watchlist', false ),
 747              'edit' => array( 'EditWatchlist', false ),
 748              'raw' => array( 'EditWatchlist', 'raw' ),
 749              'clear' => array( 'EditWatchlist', 'clear' ),
 750          );
 751  
 752          foreach ( $modes as $mode => $arr ) {
 753              // can use messages 'watchlisttools-view', 'watchlisttools-edit', 'watchlisttools-raw'
 754              $tools[] = Linker::linkKnown(
 755                  SpecialPage::getTitleFor( $arr[0], $arr[1] ),
 756                  wfMessage( "watchlisttools-{$mode}" )->escaped()
 757              );
 758          }
 759  
 760          return Html::rawElement(
 761              'span',
 762              array( 'class' => 'mw-watchlist-toollinks' ),
 763              wfMessage( 'parentheses', $wgLang->pipeList( $tools ) )->text()
 764          );
 765      }
 766  }
 767  
 768  /**
 769   * Extend HTMLForm purely so we can have a more sane way of getting the section headers
 770   */
 771  class EditWatchlistNormalHTMLForm extends HTMLForm {
 772  	public function getLegend( $namespace ) {
 773          $namespace = substr( $namespace, 2 );
 774  
 775          return $namespace == NS_MAIN
 776              ? $this->msg( 'blanknamespace' )->escaped()
 777              : htmlspecialchars( $this->getContext()->getLanguage()->getFormattedNsText( $namespace ) );
 778      }
 779  
 780  	public function getBody() {
 781          return $this->displaySection( $this->mFieldTree, '', 'editwatchlist-' );
 782      }
 783  }
 784  
 785  class EditWatchlistCheckboxSeriesField extends HTMLMultiSelectField {
 786      /**
 787       * HTMLMultiSelectField throws validation errors if we get input data
 788       * that doesn't match the data set in the form setup. This causes
 789       * problems if something gets removed from the watchlist while the
 790       * form is open (bug 32126), but we know that invalid items will
 791       * be harmless so we can override it here.
 792       *
 793       * @param string $value The value the field was submitted with
 794       * @param array $alldata The data collected from the form
 795       * @return bool|string Bool true on success, or String error to display.
 796       */
 797  	function validate( $value, $alldata ) {
 798          // Need to call into grandparent to be a good citizen. :)
 799          return HTMLFormField::validate( $value, $alldata );
 800      }
 801  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1