MediaWiki  master
SpecialEditWatchlist.php
Go to the documentation of this file.
1 <?php
32 
46  const EDIT_CLEAR = 1;
47  const EDIT_RAW = 2;
48  const EDIT_NORMAL = 3;
49 
50  protected $successMessage;
51 
52  protected $toc;
53 
54  private $badItems = [];
55 
59  private $titleParser;
60 
61  public function __construct() {
62  parent::__construct( 'EditWatchlist', 'editmywatchlist' );
63  }
64 
69  private function initServices() {
70  if ( !$this->titleParser ) {
71  $this->titleParser = MediaWikiServices::getInstance()->getTitleParser();
72  }
73  }
74 
75  public function doesWrites() {
76  return true;
77  }
78 
84  public function execute( $mode ) {
85  $this->initServices();
86  $this->setHeaders();
87 
88  # Anons don't get a watchlist
89  $this->requireLogin( 'watchlistanontext' );
90 
91  $out = $this->getOutput();
92 
93  $this->checkPermissions();
94  $this->checkReadOnly();
95 
96  $this->outputHeader();
97  $this->outputSubtitle();
98  $out->addModuleStyles( 'mediawiki.special' );
99 
100  # B/C: $mode used to be waaay down the parameter list, and the first parameter
101  # was $wgUser
102  if ( $mode instanceof User ) {
103  $args = func_get_args();
104  if ( count( $args ) >= 4 ) {
105  $mode = $args[3];
106  }
107  }
108  $mode = self::getMode( $this->getRequest(), $mode );
109 
110  switch ( $mode ) {
111  case self::EDIT_RAW:
112  $out->setPageTitle( $this->msg( 'watchlistedit-raw-title' ) );
113  $form = $this->getRawForm();
114  if ( $form->show() ) {
115  $out->addHTML( $this->successMessage );
116  $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) );
117  }
118  break;
119  case self::EDIT_CLEAR:
120  $out->setPageTitle( $this->msg( 'watchlistedit-clear-title' ) );
121  $form = $this->getClearForm();
122  if ( $form->show() ) {
123  $out->addHTML( $this->successMessage );
124  $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) );
125  }
126  break;
127 
128  case self::EDIT_NORMAL:
129  default:
130  $this->executeViewEditWatchlist();
131  break;
132  }
133  }
134 
138  protected function outputSubtitle() {
139  $out = $this->getOutput();
140  $out->addSubtitle( $this->msg( 'watchlistfor2', $this->getUser()->getName() )
141  ->rawParams(
142  self::buildTools(
143  $this->getLanguage(),
144  $this->getLinkRenderer()
145  )
146  )
147  );
148  }
149 
153  protected function executeViewEditWatchlist() {
154  $out = $this->getOutput();
155  $out->setPageTitle( $this->msg( 'watchlistedit-normal-title' ) );
156  $form = $this->getNormalForm();
157  if ( $form->show() ) {
158  $out->addHTML( $this->successMessage );
159  $out->addReturnTo( SpecialPage::getTitleFor( 'Watchlist' ) );
160  } elseif ( $this->toc !== false ) {
161  $out->prependHTML( $this->toc );
162  $out->addModuleStyles( 'mediawiki.toc.styles' );
163  }
164  }
165 
172  public function getSubpagesForPrefixSearch() {
173  // SpecialWatchlist uses SpecialEditWatchlist::getMode, so new types should be added
174  // here and there - no 'edit' here, because that the default for this page
175  return [
176  'clear',
177  'raw',
178  ];
179  }
180 
188  private function extractTitles( $list ) {
189  $list = explode( "\n", trim( $list ) );
190  if ( !is_array( $list ) ) {
191  return [];
192  }
193 
194  $titles = [];
195 
196  foreach ( $list as $text ) {
197  $text = trim( $text );
198  if ( strlen( $text ) > 0 ) {
199  $title = Title::newFromText( $text );
200  if ( $title instanceof Title && $title->isWatchable() ) {
201  $titles[] = $title;
202  }
203  }
204  }
205 
206  MediaWikiServices::getInstance()->getGenderCache()->doTitlesArray( $titles );
207 
208  $list = [];
210  foreach ( $titles as $title ) {
211  $list[] = $title->getPrefixedText();
212  }
213 
214  return array_unique( $list );
215  }
216 
217  public function submitRaw( $data ) {
218  $wanted = $this->extractTitles( $data['Titles'] );
219  $current = $this->getWatchlist();
220 
221  if ( count( $wanted ) > 0 ) {
222  $toWatch = array_diff( $wanted, $current );
223  $toUnwatch = array_diff( $current, $wanted );
224  $this->watchTitles( $toWatch );
225  $this->unwatchTitles( $toUnwatch );
226  $this->getUser()->invalidateCache();
227 
228  if ( count( $toWatch ) > 0 || count( $toUnwatch ) > 0 ) {
229  $this->successMessage = $this->msg( 'watchlistedit-raw-done' )->parse();
230  } else {
231  return false;
232  }
233 
234  if ( count( $toWatch ) > 0 ) {
235  $this->successMessage .= ' ' . $this->msg( 'watchlistedit-raw-added' )
236  ->numParams( count( $toWatch ) )->parse();
237  $this->showTitles( $toWatch, $this->successMessage );
238  }
239 
240  if ( count( $toUnwatch ) > 0 ) {
241  $this->successMessage .= ' ' . $this->msg( 'watchlistedit-raw-removed' )
242  ->numParams( count( $toUnwatch ) )->parse();
243  $this->showTitles( $toUnwatch, $this->successMessage );
244  }
245  } else {
246 
247  if ( count( $current ) === 0 ) {
248  return false;
249  }
250 
251  $this->clearUserWatchedItems( $current, 'raw' );
252  $this->showTitles( $current, $this->successMessage );
253  }
254 
255  return true;
256  }
257 
258  public function submitClear( $data ) {
259  $current = $this->getWatchlist();
260  $this->clearUserWatchedItems( $current, 'clear' );
261  $this->showTitles( $current, $this->successMessage );
262  return true;
263  }
264 
269  private function clearUserWatchedItems( $current, $messageFor ) {
270  $watchedItemStore = MediaWikiServices::getInstance()->getWatchedItemStore();
271  if ( $watchedItemStore->clearUserWatchedItems( $this->getUser() ) ) {
272  $this->successMessage = $this->msg( 'watchlistedit-' . $messageFor . '-done' )->parse();
273  $this->successMessage .= ' ' . $this->msg( 'watchlistedit-' . $messageFor . '-removed' )
274  ->numParams( count( $current ) )->parse();
275  $this->getUser()->invalidateCache();
276  } else {
277  $watchedItemStore->clearUserWatchedItemsUsingJobQueue( $this->getUser() );
278  $this->successMessage = $this->msg( 'watchlistedit-clear-jobqueue' )->parse();
279  }
280  }
281 
291  private function showTitles( $titles, &$output ) {
292  $talk = $this->msg( 'talkpagelinktext' )->text();
293  // Do a batch existence check
294  $batch = new LinkBatch();
295  if ( count( $titles ) >= 100 ) {
296  $output = $this->msg( 'watchlistedit-too-many' )->parse();
297  return;
298  }
299  foreach ( $titles as $title ) {
300  if ( !$title instanceof Title ) {
302  }
303 
304  if ( $title instanceof Title ) {
305  $batch->addObj( $title );
306  $batch->addObj( $title->getTalkPage() );
307  }
308  }
309 
310  $batch->execute();
311 
312  // Print out the list
313  $output .= "<ul>\n";
314 
315  $linkRenderer = $this->getLinkRenderer();
316  foreach ( $titles as $title ) {
317  if ( !$title instanceof Title ) {
319  }
320 
321  if ( $title instanceof Title ) {
322  $output .= '<li>' .
323  $linkRenderer->makeLink( $title ) . ' ' .
324  $this->msg( 'parentheses' )->rawParams(
325  $linkRenderer->makeLink( $title->getTalkPage(), $talk )
326  )->escaped() .
327  "</li>\n";
328  }
329  }
330 
331  $output .= "</ul>\n";
332  }
333 
340  private function getWatchlist() {
341  $list = [];
342 
343  $watchedItems = MediaWikiServices::getInstance()->getWatchedItemStore()->getWatchedItemsForUser(
344  $this->getUser(),
345  [ 'forWrite' => $this->getRequest()->wasPosted() ]
346  );
347 
348  if ( $watchedItems ) {
350  $titles = [];
351  foreach ( $watchedItems as $watchedItem ) {
352  $namespace = $watchedItem->getLinkTarget()->getNamespace();
353  $dbKey = $watchedItem->getLinkTarget()->getDBkey();
354  $title = Title::makeTitleSafe( $namespace, $dbKey );
355 
356  if ( $this->checkTitle( $title, $namespace, $dbKey )
357  && !$title->isTalkPage()
358  ) {
359  $titles[] = $title;
360  }
361  }
362 
363  MediaWikiServices::getInstance()->getGenderCache()->doTitlesArray( $titles );
364 
365  foreach ( $titles as $title ) {
366  $list[] = $title->getPrefixedText();
367  }
368  }
369 
370  $this->cleanupWatchlist();
371 
372  return $list;
373  }
374 
381  protected function getWatchlistInfo() {
382  $titles = [];
383  $services = MediaWikiServices::getInstance();
384 
385  $watchedItems = $services->getWatchedItemStore()
386  ->getWatchedItemsForUser( $this->getUser(), [ 'sort' => WatchedItemStore::SORT_ASC ] );
387 
388  $lb = new LinkBatch();
389 
390  foreach ( $watchedItems as $watchedItem ) {
391  $namespace = $watchedItem->getLinkTarget()->getNamespace();
392  $dbKey = $watchedItem->getLinkTarget()->getDBkey();
393  $lb->add( $namespace, $dbKey );
394  if ( !$services->getNamespaceInfo()->isTalk( $namespace ) ) {
395  $titles[$namespace][$dbKey] = 1;
396  }
397  }
398 
399  $lb->execute();
400 
401  return $titles;
402  }
403 
412  private function checkTitle( $title, $namespace, $dbKey ) {
413  if ( $title
414  && ( $title->isExternal()
415  || $title->getNamespace() < 0
416  )
417  ) {
418  $title = false; // unrecoverable
419  }
420 
421  if ( !$title
422  || $title->getNamespace() != $namespace
423  || $title->getDBkey() != $dbKey
424  ) {
425  $this->badItems[] = [ $title, $namespace, $dbKey ];
426  }
427 
428  return (bool)$title;
429  }
430 
434  private function cleanupWatchlist() {
435  if ( $this->badItems === [] ) {
436  return; // nothing to do
437  }
438 
439  $user = $this->getUser();
441  DeferredUpdates::addCallableUpdate( function () use ( $user, $badItems ) {
442  $store = MediaWikiServices::getInstance()->getWatchedItemStore();
443  foreach ( $badItems as $row ) {
444  list( $title, $namespace, $dbKey ) = $row;
445  $action = $title ? 'cleaning up' : 'deleting';
446  wfDebug( "User {$user->getName()} has broken watchlist item " .
447  "ns($namespace):$dbKey, $action.\n" );
448 
449  // NOTE: We *know* that the title is invalid. TitleValue may refuse instantiation.
450  // XXX: We may need an InvalidTitleValue class that allows instantiation of
451  // known bad title values.
452  $store->removeWatch( $user, Title::makeTitle( (int)$namespace, $dbKey ) );
453  // Can't just do an UPDATE instead of DELETE/INSERT due to unique index
454  if ( $title ) {
455  $user->addWatch( $title );
456  }
457  }
458  } );
459  }
460 
469  private function watchTitles( array $targets ) {
470  return MediaWikiServices::getInstance()->getWatchedItemStore()
471  ->addWatchBatchForUser( $this->getUser(), $this->getExpandedTargets( $targets ) )
472  && $this->runWatchUnwatchCompleteHook( 'Watch', $targets );
473  }
474 
487  private function unwatchTitles( array $targets ) {
488  return MediaWikiServices::getInstance()->getWatchedItemStore()
489  ->removeWatchBatchForUser( $this->getUser(), $this->getExpandedTargets( $targets ) )
490  && $this->runWatchUnwatchCompleteHook( 'Unwatch', $targets );
491  }
492 
501  private function runWatchUnwatchCompleteHook( $action, $targets ) {
502  foreach ( $targets as $target ) {
503  $title = $target instanceof TitleValue ?
504  Title::newFromTitleValue( $target ) :
505  Title::newFromText( $target );
506  $page = WikiPage::factory( $title );
507  Hooks::run( $action . 'ArticleComplete', [ $this->getUser(), &$page ] );
508  }
509  return true;
510  }
511 
516  private function getExpandedTargets( array $targets ) {
517  $expandedTargets = [];
518  $services = MediaWikiServices::getInstance();
519  foreach ( $targets as $target ) {
520  if ( !$target instanceof LinkTarget ) {
521  try {
522  $target = $this->titleParser->parseTitle( $target, NS_MAIN );
523  }
524  catch ( MalformedTitleException $e ) {
525  continue;
526  }
527  }
528 
529  $ns = $target->getNamespace();
530  $dbKey = $target->getDBkey();
531  $expandedTargets[] =
532  new TitleValue( $services->getNamespaceInfo()->getSubject( $ns ), $dbKey );
533  $expandedTargets[] =
534  new TitleValue( $services->getNamespaceInfo()->getTalk( $ns ), $dbKey );
535  }
536  return $expandedTargets;
537  }
538 
539  public function submitNormal( $data ) {
540  $removed = [];
541 
542  foreach ( $data as $titles ) {
543  $this->unwatchTitles( $titles );
544  $removed = array_merge( $removed, $titles );
545  }
546 
547  if ( count( $removed ) > 0 ) {
548  $this->successMessage = $this->msg( 'watchlistedit-normal-done'
549  )->numParams( count( $removed ) )->parse();
550  $this->showTitles( $removed, $this->successMessage );
551 
552  return true;
553  } else {
554  return false;
555  }
556  }
557 
563  protected function getNormalForm() {
564  $fields = [];
565  $count = 0;
566 
567  // Allow subscribers to manipulate the list of watched pages (or use it
568  // to preload lots of details at once)
569  $watchlistInfo = $this->getWatchlistInfo();
570  Hooks::run(
571  'WatchlistEditorBeforeFormRender',
572  [ &$watchlistInfo ]
573  );
574 
575  foreach ( $watchlistInfo as $namespace => $pages ) {
576  $options = [];
577 
578  foreach ( array_keys( $pages ) as $dbkey ) {
579  $title = Title::makeTitleSafe( $namespace, $dbkey );
580 
581  if ( $this->checkTitle( $title, $namespace, $dbkey ) ) {
582  $text = $this->buildRemoveLine( $title );
583  $options[$text] = $title->getPrefixedText();
584  $count++;
585  }
586  }
587 
588  // checkTitle can filter some options out, avoid empty sections
589  if ( count( $options ) > 0 ) {
590  $fields['TitlesNs' . $namespace] = [
591  'class' => EditWatchlistCheckboxSeriesField::class,
592  'options' => $options,
593  'section' => "ns$namespace",
594  ];
595  }
596  }
597  $this->cleanupWatchlist();
598 
599  if ( count( $fields ) > 1 && $count > 30 ) {
600  $this->toc = Linker::tocIndent();
601  $tocLength = 0;
602  $contLang = MediaWikiServices::getInstance()->getContentLanguage();
603 
604  foreach ( $fields as $data ) {
605  # strip out the 'ns' prefix from the section name:
606  $ns = substr( $data['section'], 2 );
607 
608  $nsText = ( $ns == NS_MAIN )
609  ? $this->msg( 'blanknamespace' )->escaped()
610  : htmlspecialchars( $contLang->getFormattedNsText( $ns ) );
611  $this->toc .= Linker::tocLine( "editwatchlist-{$data['section']}", $nsText,
612  $this->getLanguage()->formatNum( ++$tocLength ), 1 ) . Linker::tocLineEnd();
613  }
614 
615  $this->toc = Linker::tocList( $this->toc );
616  } else {
617  $this->toc = false;
618  }
619 
620  $context = new DerivativeContext( $this->getContext() );
621  $context->setTitle( $this->getPageTitle() ); // Remove subpage
622  $form = new EditWatchlistNormalHTMLForm( $fields, $context );
623  $form->setSubmitTextMsg( 'watchlistedit-normal-submit' );
624  $form->setSubmitDestructive();
625  # Used message keys:
626  # 'accesskey-watchlistedit-normal-submit', 'tooltip-watchlistedit-normal-submit'
627  $form->setSubmitTooltip( 'watchlistedit-normal-submit' );
628  $form->setWrapperLegendMsg( 'watchlistedit-normal-legend' );
629  $form->addHeaderText( $this->msg( 'watchlistedit-normal-explain' )->parse() );
630  $form->setSubmitCallback( [ $this, 'submitNormal' ] );
631 
632  return $form;
633  }
634 
641  private function buildRemoveLine( $title ) {
642  $linkRenderer = $this->getLinkRenderer();
643  $link = $linkRenderer->makeLink( $title );
644 
645  $tools = [];
646  $tools['talk'] = $linkRenderer->makeLink(
647  $title->getTalkPage(),
648  $this->msg( 'talkpagelinktext' )->text()
649  );
650 
651  if ( $title->exists() ) {
652  $tools['history'] = $linkRenderer->makeKnownLink(
653  $title,
654  $this->msg( 'history_small' )->text(),
655  [],
656  [ 'action' => 'history' ]
657  );
658  }
659 
660  if ( $title->getNamespace() == NS_USER && !$title->isSubpage() ) {
661  $tools['contributions'] = $linkRenderer->makeKnownLink(
662  SpecialPage::getTitleFor( 'Contributions', $title->getText() ),
663  $this->msg( 'contribslink' )->text()
664  );
665  }
666 
667  Hooks::run(
668  'WatchlistEditorBuildRemoveLine',
669  [ &$tools, $title, $title->isRedirect(), $this->getSkin(), &$link ]
670  );
671 
672  if ( $title->isRedirect() ) {
673  // Linker already makes class mw-redirect, so this is redundant
674  $link = '<span class="watchlistredir">' . $link . '</span>';
675  }
676 
677  return $link . ' ' .
678  $this->msg( 'parentheses' )->rawParams( $this->getLanguage()->pipeList( $tools ) )->escaped();
679  }
680 
686  protected function getRawForm() {
687  $titles = implode( "\n", $this->getWatchlist() );
688  $fields = [
689  'Titles' => [
690  'type' => 'textarea',
691  'label-message' => 'watchlistedit-raw-titles',
692  'default' => $titles,
693  ],
694  ];
695  $context = new DerivativeContext( $this->getContext() );
696  $context->setTitle( $this->getPageTitle( 'raw' ) ); // Reset subpage
697  $form = new OOUIHTMLForm( $fields, $context );
698  $form->setSubmitTextMsg( 'watchlistedit-raw-submit' );
699  # Used message keys: 'accesskey-watchlistedit-raw-submit', 'tooltip-watchlistedit-raw-submit'
700  $form->setSubmitTooltip( 'watchlistedit-raw-submit' );
701  $form->setWrapperLegendMsg( 'watchlistedit-raw-legend' );
702  $form->addHeaderText( $this->msg( 'watchlistedit-raw-explain' )->parse() );
703  $form->setSubmitCallback( [ $this, 'submitRaw' ] );
704 
705  return $form;
706  }
707 
713  protected function getClearForm() {
714  $context = new DerivativeContext( $this->getContext() );
715  $context->setTitle( $this->getPageTitle( 'clear' ) ); // Reset subpage
716  $form = new OOUIHTMLForm( [], $context );
717  $form->setSubmitTextMsg( 'watchlistedit-clear-submit' );
718  # Used message keys: 'accesskey-watchlistedit-clear-submit', 'tooltip-watchlistedit-clear-submit'
719  $form->setSubmitTooltip( 'watchlistedit-clear-submit' );
720  $form->setWrapperLegendMsg( 'watchlistedit-clear-legend' );
721  $form->addHeaderText( $this->msg( 'watchlistedit-clear-explain' )->parse() );
722  $form->setSubmitCallback( [ $this, 'submitClear' ] );
723  $form->setSubmitDestructive();
724 
725  return $form;
726  }
727 
736  public static function getMode( $request, $par ) {
737  $mode = strtolower( $request->getVal( 'action', $par ) );
738 
739  switch ( $mode ) {
740  case 'clear':
741  case self::EDIT_CLEAR:
742  return self::EDIT_CLEAR;
743  case 'raw':
744  case self::EDIT_RAW:
745  return self::EDIT_RAW;
746  case 'edit':
747  case self::EDIT_NORMAL:
748  return self::EDIT_NORMAL;
749  default:
750  return false;
751  }
752  }
753 
762  public static function buildTools( $lang, LinkRenderer $linkRenderer = null ) {
763  if ( !$lang instanceof Language ) {
764  // back-compat where the first parameter was $unused
765  global $wgLang;
766  $lang = $wgLang;
767  }
768  if ( !$linkRenderer ) {
769  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
770  }
771 
772  $tools = [];
773  $modes = [
774  'view' => [ 'Watchlist', false ],
775  'edit' => [ 'EditWatchlist', false ],
776  'raw' => [ 'EditWatchlist', 'raw' ],
777  'clear' => [ 'EditWatchlist', 'clear' ],
778  ];
779 
780  foreach ( $modes as $mode => $arr ) {
781  // can use messages 'watchlisttools-view', 'watchlisttools-edit', 'watchlisttools-raw'
782  $tools[] = $linkRenderer->makeKnownLink(
783  SpecialPage::getTitleFor( $arr[0], $arr[1] ),
784  wfMessage( "watchlisttools-{$mode}" )->text()
785  );
786  }
787 
788  return Html::rawElement(
789  'span',
790  [ 'class' => 'mw-watchlist-toollinks' ],
791  wfMessage( 'parentheses' )->rawParams( $lang->pipeList( $tools ) )->escaped()
792  );
793  }
794 }
SpecialPage\getPageTitle
getPageTitle( $subpage=false)
Get a self-referential title object.
Definition: SpecialPage.php:672
SpecialEditWatchlist\submitNormal
submitNormal( $data)
Definition: SpecialEditWatchlist.php:539
SpecialEditWatchlist\EDIT_CLEAR
const EDIT_CLEAR
Editing modes.
Definition: SpecialEditWatchlist.php:46
SpecialEditWatchlist\unwatchTitles
unwatchTitles(array $targets)
Remove a list of titles from a user's watchlist.
Definition: SpecialEditWatchlist.php:487
SpecialEditWatchlist\getWatchlist
getWatchlist()
Prepare a list of titles on a user's watchlist (excluding talk pages) and return an array of (prefixe...
Definition: SpecialEditWatchlist.php:340
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:792
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:317
SpecialEditWatchlist\EDIT_RAW
const EDIT_RAW
Definition: SpecialEditWatchlist.php:47
SpecialEditWatchlist\checkTitle
checkTitle( $title, $namespace, $dbKey)
Validates watchlist entry.
Definition: SpecialEditWatchlist.php:412
SpecialEditWatchlist\initServices
initServices()
Initialize any services we'll need (unless it has already been provided via a setter).
Definition: SpecialEditWatchlist.php:69
LinkBatch
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition: LinkBatch.php:35
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:719
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:130
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:35
UnlistedSpecialPage
Shortcut to construct a special page which is unlisted by default.
Definition: UnlistedSpecialPage.php:29
Linker\tocIndent
static tocIndent()
Add another level to the Table of Contents.
Definition: Linker.php:1614
MediaWiki\Linker\LinkRenderer
Class that generates HTML links for pages.
Definition: LinkRenderer.php:41
SpecialEditWatchlist\__construct
__construct()
Definition: SpecialEditWatchlist.php:61
SpecialEditWatchlist\submitRaw
submitRaw( $data)
Definition: SpecialEditWatchlist.php:217
SpecialPage\checkPermissions
checkPermissions()
Checks if userCanExecute, and if not throws a PermissionsError.
Definition: SpecialPage.php:315
SpecialEditWatchlist\buildRemoveLine
buildRemoveLine( $title)
Build the label for a checkbox, with a link to the title, and various additional bits.
Definition: SpecialEditWatchlist.php:641
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1263
SpecialPage\getTitleFor
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Definition: SpecialPage.php:83
SpecialEditWatchlist\watchTitles
watchTitles(array $targets)
Add a list of targets to a user's watchlist.
Definition: SpecialEditWatchlist.php:469
SpecialPage\getSkin
getSkin()
Shortcut to get the skin being used for this instance.
Definition: SpecialPage.php:739
SpecialEditWatchlist\getExpandedTargets
getExpandedTargets(array $targets)
Definition: SpecialEditWatchlist.php:516
SpecialPage\getLanguage
getLanguage()
Shortcut to get user's language.
Definition: SpecialPage.php:749
SpecialPage\getName
getName()
Get the name of this Special Page.
Definition: SpecialPage.php:153
SpecialEditWatchlist\clearUserWatchedItems
clearUserWatchedItems( $current, $messageFor)
Definition: SpecialEditWatchlist.php:269
Linker\tocLine
static tocLine( $anchor, $tocline, $tocnumber, $level, $sectionIndex=false)
parameter level defines if we are on an indentation level
Definition: Linker.php:1640
SpecialEditWatchlist\$badItems
$badItems
Definition: SpecialEditWatchlist.php:54
Linker\tocList
static tocList( $toc, Language $lang=null)
Wraps the TOC in a table and provides the hide/collapse javascript.
Definition: Linker.php:1676
SpecialEditWatchlist\$titleParser
TitleParser $titleParser
Definition: SpecialEditWatchlist.php:59
SpecialEditWatchlist\runWatchUnwatchCompleteHook
runWatchUnwatchCompleteHook( $action, $targets)
Definition: SpecialEditWatchlist.php:501
OOUIHTMLForm
Compact stacked vertical format for forms, implemented using OOUI widgets.
Definition: OOUIHTMLForm.php:27
SpecialEditWatchlist\execute
execute( $mode)
Main execution point.
Definition: SpecialEditWatchlist.php:84
NS_MAIN
const NS_MAIN
Definition: Defines.php:60
EditWatchlistNormalHTMLForm
Extend OOUIHTMLForm purely so we can have a more sane way of getting the section headers.
Definition: EditWatchlistNormalHTMLForm.php:24
DerivativeContext
An IContextSource implementation which will inherit context from another source but allow individual ...
Definition: DerivativeContext.php:30
SpecialEditWatchlist\EDIT_NORMAL
const EDIT_NORMAL
Definition: SpecialEditWatchlist.php:48
WikiPage\factory
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:141
SpecialEditWatchlist\getRawForm
getRawForm()
Get a form for editing the watchlist in "raw" mode.
Definition: SpecialEditWatchlist.php:686
SpecialEditWatchlist\executeViewEditWatchlist
executeViewEditWatchlist()
Executes an edit mode for the watchlist view, from which you can manage your watchlist.
Definition: SpecialEditWatchlist.php:153
SpecialEditWatchlist\extractTitles
extractTitles( $list)
Extract a list of titles from a blob of text, returning (prefixed) strings; unwatchable titles are ig...
Definition: SpecialEditWatchlist.php:188
$wgLang
$wgLang
Definition: Setup.php:846
Linker\tocLineEnd
static tocLineEnd()
End a Table Of Contents line.
Definition: Linker.php:1664
$args
if( $line===false) $args
Definition: mcc.php:124
SpecialEditWatchlist
Provides the UI through which users can perform editing operations on their watchlist.
Definition: SpecialEditWatchlist.php:41
$title
$title
Definition: testCompression.php:36
SpecialPage\setHeaders
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
Definition: SpecialPage.php:537
SpecialPage\getUser
getUser()
Shortcut to get the User executing this instance.
Definition: SpecialPage.php:729
SpecialEditWatchlist\showTitles
showTitles( $titles, &$output)
Print out a list of linked titles.
Definition: SpecialEditWatchlist.php:291
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:584
TitleParser
A title parser service for MediaWiki.
Definition: TitleParser.php:33
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:913
SpecialPage\getContext
getContext()
Gets the context this SpecialPage is executed in.
Definition: SpecialPage.php:692
SpecialPage\requireLogin
requireLogin( $reasonMsg='exception-nologin-text', $titleMsg='exception-nologin')
If the user is not logged in, throws UserNotLoggedIn error.
Definition: SpecialPage.php:345
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:610
SpecialEditWatchlist\getMode
static getMode( $request, $par)
Determine whether we are editing the watchlist, and if so, what kind of editing operation.
Definition: SpecialEditWatchlist.php:736
SpecialEditWatchlist\getSubpagesForPrefixSearch
getSubpagesForPrefixSearch()
Return an array of subpages that this special page will accept.
Definition: SpecialEditWatchlist.php:172
SpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: SpecialPage.php:709
SpecialEditWatchlist\cleanupWatchlist
cleanupWatchlist()
Attempts to clean up broken items.
Definition: SpecialEditWatchlist.php:434
SpecialEditWatchlist\doesWrites
doesWrites()
Indicates whether this special page may perform database writes.
Definition: SpecialEditWatchlist.php:75
WatchedItemStoreInterface\SORT_ASC
const SORT_ASC
Definition: WatchedItemStoreInterface.php:35
$context
$context
Definition: load.php:40
SpecialEditWatchlist\outputSubtitle
outputSubtitle()
Renders a subheader on the watchlist page.
Definition: SpecialEditWatchlist.php:138
SpecialEditWatchlist\$toc
$toc
Definition: SpecialEditWatchlist.php:52
SpecialPage\getLinkRenderer
getLinkRenderer()
Definition: SpecialPage.php:904
SpecialEditWatchlist\buildTools
static buildTools( $lang, LinkRenderer $linkRenderer=null)
Build a set of links for convenient navigation between watchlist viewing and editing modes.
Definition: SpecialEditWatchlist.php:762
Title
Represents a title within MediaWiki.
Definition: Title.php:42
SpecialEditWatchlist\getClearForm
getClearForm()
Get a form for clearing the watchlist.
Definition: SpecialEditWatchlist.php:713
MalformedTitleException
MalformedTitleException is thrown when a TitleParser is unable to parse a title string.
Definition: MalformedTitleException.php:25
NS_USER
const NS_USER
Definition: Defines.php:62
SpecialEditWatchlist\getNormalForm
getNormalForm()
Get the standard watchlist editing form.
Definition: SpecialEditWatchlist.php:563
SpecialPage\checkReadOnly
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
Definition: SpecialPage.php:328
SpecialPage\$linkRenderer
MediaWiki Linker LinkRenderer null $linkRenderer
Definition: SpecialPage.php:67
MediaWiki\Linker\LinkTarget
Definition: LinkTarget.php:26
SpecialEditWatchlist\getWatchlistInfo
getWatchlistInfo()
Get a list of titles on a user's watchlist, excluding talk pages, and return as a two-dimensional arr...
Definition: SpecialEditWatchlist.php:381
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:52
DeferredUpdates\addCallableUpdate
static addCallableUpdate( $callable, $stage=self::POSTSEND, $dbw=null)
Add a callable update.
Definition: DeferredUpdates.php:125
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
SpecialEditWatchlist\submitClear
submitClear( $data)
Definition: SpecialEditWatchlist.php:258
SpecialPage\outputHeader
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
Definition: SpecialPage.php:639
Language
Internationalisation code.
Definition: Language.php:39
SpecialEditWatchlist\$successMessage
$successMessage
Definition: SpecialEditWatchlist.php:50
TitleValue
Represents a page (or page fragment) title within MediaWiki.
Definition: TitleValue.php:37
Title\newFromTitleValue
static newFromTitleValue(TitleValue $titleValue, $forceClone='')
Returns a Title given a TitleValue.
Definition: Title.php:254