MediaWiki master
ChangeTags.php
Go to the documentation of this file.
1<?php
8
27
49 public const TAG_CONTENT_MODEL_CHANGE = 'mw-contentmodelchange';
54 public const TAG_NEW_REDIRECT = 'mw-new-redirect';
58 public const TAG_REMOVED_REDIRECT = 'mw-removed-redirect';
62 public const TAG_CHANGED_REDIRECT_TARGET = 'mw-changed-redirect-target';
66 public const TAG_BLANK = 'mw-blank';
70 public const TAG_REPLACE = 'mw-replace';
74 public const TAG_RECREATE = 'mw-recreated';
82 public const TAG_ROLLBACK = 'mw-rollback';
89 public const TAG_UNDO = 'mw-undo';
95 public const TAG_MANUAL_REVERT = 'mw-manual-revert';
103 public const TAG_REVERTED = 'mw-reverted';
107 public const TAG_SERVER_SIDE_UPLOAD = 'mw-server-side-upload';
112 public const TAG_IPBLOCK_APPEAL = 'mw-ipblock-appeal';
117 public const TAG_EDITED_OTHER_USERS_JS = 'mw-edited-other-users-js';
122 public const TAG_EDITED_OTHER_USERS_CSS = 'mw-edited-other-users-css';
123
128
132 public const BYPASS_MAX_USAGE_CHECK = 1;
133
139 private const MAX_DELETE_USES = 5000;
140
144 private const CHANGE_TAG = 'change_tag';
145
146 public const DISPLAY_TABLE_ALIAS = 'changetagdisplay';
147
157 public const TAG_SET_ACTIVE_ONLY = true;
158 public const TAG_SET_ALL = false;
159
168 public const USE_ALL_TAGS = true;
169 public const USE_SOFTWARE_TAGS_ONLY = false;
170
183 public static function formatSummaryRow( $tags, $unused, MessageLocalizer $localizer ) {
184 wfDeprecated( __METHOD__, '1.47' );
185 return MediaWikiServices::getInstance()->getChangeTagsFormatter()->formatTagsAsSummaryList(
186 $tags,
187 $localizer,
188 RequestContext::getMain()->getAuthority()
189 );
190 }
191
206 public static function tagShortDescriptionMessage( $tag, MessageLocalizer $context ) {
207 wfDeprecated( __METHOD__, '1.47' );
208 $msg = $context->msg( "tag-$tag" );
209 if ( !$msg->exists() ) {
210 // No such message
211 // Pass through ->msg(), even though it seems redundant, to avoid requesting
212 // the user's language from session-less entry points (T227233)
213 return $context->msg( new RawMessage( '$1', [ Message::plaintextParam( $tag ) ] ) );
214 }
215 if ( $msg->isDisabled() ) {
216 // The message exists but is disabled, hide the tag.
217 return false;
218 }
219
220 // Message exists and isn't disabled, use it.
221 return $msg;
222 }
223
237 public static function tagHelpLink( $tag, MessageLocalizer $context ) {
238 wfDeprecated( __METHOD__, '1.47' );
239 $msg = $context->msg( "tag-$tag-helppage" )->inContentLanguage();
240 if ( !$msg->isDisabled() ) {
241 return Skin::makeInternalOrExternalUrl( $msg->text() ) ?: null;
242 }
243 return null;
244 }
245
258 public static function tagDescription( $tag, MessageLocalizer $context ) {
259 wfDeprecated( __METHOD__, '1.47' );
260 $description = MediaWikiServices::getInstance()->getChangeTagsFormatter()->getTagDescription( $tag, $context );
261 if ( $description === '' ) {
262 return false;
263 }
264 return $description;
265 }
266
280 public static function tagLongDescriptionMessage( $tag, MessageLocalizer $context ) {
281 wfDeprecated( __METHOD__, '1.47' );
282 $msg = $context->msg( "tag-$tag-description" );
283 return $msg->isDisabled() ? false : $msg;
284 }
285
296 protected static function restrictedTagError( $msgOne, $msgMulti, $tags ) {
297 $tags = array_values( $tags );
298 $count = count( $tags );
299 $status = Status::newFatal( ( $count > 1 ) ? $msgMulti : $msgOne,
300 Message::listParam( $tags ), $count );
301 $status->value = $tags;
302 return $status;
303 }
304
319 public static function canAddTagsAccompanyingChange(
320 array $tags,
321 ?Authority $performer = null,
322 $checkBlock = true
323 ) {
324 $user = null;
325 $services = MediaWikiServices::getInstance();
326 if ( $performer !== null ) {
327 if ( !$performer->isAllowed( 'applychangetags' ) ) {
328 return Status::newFatal( 'tags-apply-no-permission' );
329 }
330
331 if ( $checkBlock && $performer->getBlock() && $performer->getBlock()->isSitewide() ) {
332 return Status::newFatal(
333 'tags-apply-blocked',
334 $performer->getUser()->getName()
335 );
336 }
337
338 // ChangeTagsAllowedAdd hook still needs a full User object
339 $user = $services->getUserFactory()->newFromAuthority( $performer );
340 }
341
342 // to be applied, a tag has to be explicitly defined
343 $allowedTags = $services->getChangeTagsStore()->listExplicitlyDefinedTags();
344 ( new HookRunner( $services->getHookContainer() ) )->onChangeTagsAllowedAdd( $allowedTags, $tags, $user );
345 $disallowedTags = array_diff( $tags, $allowedTags );
346 if ( $disallowedTags ) {
347 return self::restrictedTagError( 'tags-apply-not-allowed-one',
348 'tags-apply-not-allowed-multi', $disallowedTags );
349 }
350
351 return Status::newGood();
352 }
353
369 public static function canUpdateTags(
370 array $tagsToAdd,
371 array $tagsToRemove,
372 ?Authority $performer = null
373 ) {
374 wfDeprecated( __METHOD__, '1.47' );
375 return self::canUpdateTagsInternal(
376 $tagsToAdd,
377 $tagsToRemove,
378 $performer ?? new UltimateAuthority( RequestContext::getMain()->getUser() )
379 );
380 }
381
395 private static function canUpdateTagsInternal(
396 array $tagsToAdd,
397 array $tagsToRemove,
398 Authority $performer
399 ): Status {
400 if ( !$performer->isDefinitelyAllowed( 'changetags' ) ) {
401 return Status::newFatal( 'tags-update-no-permission' );
402 }
403
404 if ( $performer->getBlock() && $performer->getBlock()->isSitewide() ) {
405 return Status::newFatal(
406 'tags-update-blocked',
407 $performer->getUser()->getName()
408 );
409 }
410
411 $changeTagsStore = MediaWikiServices::getInstance()->getChangeTagsStore();
412 if ( $tagsToAdd ) {
413 // to be added, a tag has to be explicitly defined
414 // @todo Allow extensions to define tags that can be applied by users...
415 $explicitlyDefinedTags = $changeTagsStore->listExplicitlyDefinedTags();
416 $diff = array_diff( $tagsToAdd, $explicitlyDefinedTags );
417 if ( $diff ) {
418 return self::restrictedTagError( 'tags-update-add-not-allowed-one',
419 'tags-update-add-not-allowed-multi', $diff );
420 }
421 }
422
423 if ( $tagsToRemove ) {
424 // Restricted tags can only be removed by users who can view the tag. We do this
425 // separately so that private tags that are undefined cannot be removed from changes.
426 $unviewableRestricted = array_filter(
427 $tagsToRemove,
428 static fn ( $tag ) => $changeTagsStore->isRestrictedTag( $tag )
429 && !$changeTagsStore->canViewTag( $tag, $performer )
430 );
431 if ( $unviewableRestricted ) {
432 return self::restrictedTagError( 'tags-update-remove-not-allowed-one',
433 'tags-update-remove-not-allowed-multi', $unviewableRestricted );
434 }
435
436 // to be removed, a tag must not be defined by an extension, or equivalently it
437 // has to be either explicitly defined or not defined at all
438 // (assuming no edge case of a tag both explicitly-defined and extension-defined)
439 $softwareDefinedTags = $changeTagsStore->listSoftwareDefinedTags();
440 $intersect = array_intersect( $tagsToRemove, $softwareDefinedTags );
441 if ( $intersect ) {
442 return self::restrictedTagError( 'tags-update-remove-not-allowed-one',
443 'tags-update-remove-not-allowed-multi', $intersect );
444 }
445 }
446
447 return Status::newGood();
448 }
449
479 public static function updateTagsWithChecks( $tagsToAdd, $tagsToRemove,
480 $rc_id, $rev_id, $log_id, $params, string $reason, Authority $performer
481 ) {
482 if ( !$tagsToAdd && !$tagsToRemove ) {
483 // no-op, don't bother
484 return Status::newGood( (object)[
485 'logId' => null,
486 'addedTags' => [],
487 'removedTags' => [],
488 ] );
489 }
490
491 $tagsToAdd ??= [];
492 $tagsToRemove ??= [];
493
494 // are we allowed to do this?
495 $result = self::canUpdateTagsInternal( $tagsToAdd, $tagsToRemove, $performer );
496 if ( !$result->isOK() ) {
497 $result->value = null;
498 return $result;
499 }
500
501 // basic rate limiting
502 $status = PermissionStatus::newEmpty();
503 if ( !$performer->authorizeAction( 'changetags', $status ) ) {
504 return Status::wrap( $status );
505 }
506
507 // do it!
508 $changeTagsStore = MediaWikiServices::getInstance()->getChangeTagsStore();
509 [ $tagsAdded, $tagsRemoved, $initialTags ] = $changeTagsStore->updateTags( $tagsToAdd,
510 $tagsToRemove, $rc_id, $rev_id, $log_id, $params, null, $performer->getUser() );
511 if ( !$tagsAdded && !$tagsRemoved ) {
512 // no-op, don't log it
513 return Status::newGood( (object)[
514 'logId' => null,
515 'addedTags' => [],
516 'removedTags' => [],
517 ] );
518 }
519
520 // log it
521 $logEntry = new ManualLogEntry( 'tag', 'update' );
522 $logEntry->setPerformer( $performer->getUser() );
523 $logEntry->setComment( $reason );
524
525 // find the appropriate target page
526 if ( $rev_id ) {
527 $revisionRecord = MediaWikiServices::getInstance()
528 ->getRevisionLookup()
529 ->getRevisionById( $rev_id );
530 if ( $revisionRecord ) {
531 $logEntry->setTarget( $revisionRecord->getPageAsLinkTarget() );
532 }
533 } elseif ( $log_id ) {
534 // This function is from revision deletion logic and has nothing to do with
535 // change tags, but it appears to be the only other place in core where we
536 // perform logged actions on log items.
537 $logEntry->setTarget( RevDelLogList::suggestTarget( null, [ $log_id ] ) );
538 }
539
540 if ( !$logEntry->getTarget() ) {
541 // target is required, so we have to set something
542 $logEntry->setTarget( SpecialPage::getTitleFor( 'Tags' ) );
543 }
544
545 $logParams = [
546 '4::revid' => $rev_id,
547 '5::logid' => $log_id,
548 '6:list:tagsAdded' => $tagsAdded,
549 '7:number:tagsAddedCount' => count( $tagsAdded ),
550 '8:list:tagsRemoved' => $tagsRemoved,
551 '9:number:tagsRemovedCount' => count( $tagsRemoved ),
552 'initialTags' => $initialTags,
553 ];
554 $logEntry->setParameters( $logParams );
555 $logEntry->setRelations( [ 'Tag' => array_merge( $tagsAdded, $tagsRemoved ) ] );
556
557 $dbw = MediaWikiServices::getInstance()->getConnectionProvider()->getPrimaryDatabase();
558 $logId = $logEntry->insert( $dbw );
559 // Only send this to UDP, not RC, similar to patrol events
560 $logEntry->publish( $logId, 'udp' );
561
562 return Status::newGood( (object)[
563 'logId' => $logId,
564 'addedTags' => $tagsAdded,
565 'removedTags' => $tagsRemoved,
566 ] );
567 }
568
583 public static function buildTagFilterSelector(
584 $selected, $ooui, IContextSource $context,
585 bool $activeOnly = self::TAG_SET_ACTIVE_ONLY,
586 bool $useAllTags = self::USE_ALL_TAGS
587 ) {
588 wfDeprecated( __METHOD__, '1.47' );
589 return MediaWikiServices::getInstance()->getChangeTagsFormatter()->buildTagFilter(
590 $selected,
591 $ooui ? 'ooui' : 'other',
592 $context,
593 $activeOnly,
594 $useAllTags
595 );
596 }
597
607 public static function canActivateTag( string $tag, ?Authority $performer = null ) {
608 $changeTagsStore = MediaWikiServices::getInstance()->getChangeTagsStore();
609 if ( $performer !== null ) {
610 if ( !$performer->isAllowed( 'managechangetags' ) ) {
611 return Status::newFatal( 'tags-manage-no-permission' );
612 }
613 if ( $performer->getBlock() && $performer->getBlock()->isSitewide() ) {
614 return Status::newFatal(
615 'tags-manage-blocked',
616 $performer->getUser()->getName()
617 );
618 }
619 if ( $changeTagsStore->filterViewableTags( [ $tag ], $performer ) === [] ) {
620 return Status::newFatal( 'tags-activate-not-found', $tag );
621 }
622 }
623
624 // defined tags cannot be activated (a defined tag is either extension-
625 // defined, in which case the extension chooses whether or not to active it;
626 // or user-defined, in which case it is considered active)
627 $definedTags = $changeTagsStore->listDefinedTags();
628 if ( in_array( $tag, $definedTags ) ) {
629 return Status::newFatal( 'tags-activate-not-allowed', $tag );
630 }
631
632 // non-existing tags cannot be activated
633 if ( !isset( $changeTagsStore->tagUsageStatistics()[$tag] ) ) { // we already know the tag is undefined
634 return Status::newFatal( 'tags-activate-not-found', $tag );
635 }
636
637 return Status::newGood();
638 }
639
657 public static function activateTagWithChecks( string $tag, string $reason, Authority $performer,
658 bool $ignoreWarnings = false, array $logEntryTags = []
659 ) {
660 // are we allowed to do this?
661 $result = self::canActivateTag( $tag, $performer );
662 if ( $ignoreWarnings ? !$result->isOK() : !$result->isGood() ) {
663 $result->value = null;
664 return $result;
665 }
666 $changeTagsStore = MediaWikiServices::getInstance()->getChangeTagsStore();
667
668 $changeTagsStore->defineTag( $tag );
669
670 $logId = $changeTagsStore->logTagManagementAction( 'activate', $tag, $reason, $performer->getUser(),
671 null, $logEntryTags );
672
673 return Status::newGood( $logId );
674 }
675
685 public static function canDeactivateTag( string $tag, ?Authority $performer = null ) {
686 $changeTagsStore = MediaWikiServices::getInstance()->getChangeTagsStore();
687 if ( $performer !== null ) {
688 if ( !$performer->isAllowed( 'managechangetags' ) ) {
689 return Status::newFatal( 'tags-manage-no-permission' );
690 }
691 if ( $performer->getBlock() && $performer->getBlock()->isSitewide() ) {
692 return Status::newFatal(
693 'tags-manage-blocked',
694 $performer->getUser()->getName()
695 );
696 }
697 if ( $changeTagsStore->filterViewableTags( [ $tag ], $performer ) === [] ) {
698 return Status::newFatal( 'tags-deactivate-not-found', $tag );
699 }
700 }
701
702 // only explicitly-defined tags can be deactivated
703 $explicitlyDefinedTags = $changeTagsStore->listExplicitlyDefinedTags();
704 if ( !in_array( $tag, $explicitlyDefinedTags ) ) {
705 return Status::newFatal( 'tags-deactivate-not-allowed', $tag );
706 }
707 return Status::newGood();
708 }
709
727 public static function deactivateTagWithChecks( string $tag, string $reason, Authority $performer,
728 bool $ignoreWarnings = false, array $logEntryTags = []
729 ) {
730 // are we allowed to do this?
731 $result = self::canDeactivateTag( $tag, $performer );
732 if ( $ignoreWarnings ? !$result->isOK() : !$result->isGood() ) {
733 $result->value = null;
734 return $result;
735 }
736 $changeTagsStore = MediaWikiServices::getInstance()->getChangeTagsStore();
737
738 $changeTagsStore->undefineTag( $tag );
739
740 $logId = $changeTagsStore->logTagManagementAction( 'deactivate', $tag, $reason,
741 $performer->getUser(), null, $logEntryTags );
742
743 return Status::newGood( $logId );
744 }
745
753 public static function isTagNameValid( $tag ) {
754 // no empty tags
755 if ( $tag === '' ) {
756 return Status::newFatal( 'tags-create-no-name' );
757 }
758
759 // tags cannot contain commas (used to be used as a delimiter in tag_summary table),
760 // pipe (used as a delimiter between multiple tags in
761 // SpecialRecentchanges and friends), or slashes (would break tag description messages in
762 // MediaWiki namespace)
763 if ( str_contains( $tag, ',' ) || str_contains( $tag, '|' ) || str_contains( $tag, '/' ) ) {
764 return Status::newFatal( 'tags-create-invalid-chars' );
765 }
766
767 // could the MediaWiki namespace description messages be created?
768 $title = Title::makeTitleSafe( NS_MEDIAWIKI, "Tag-$tag-description" );
769 if ( $title === null ) {
770 return Status::newFatal( 'tags-create-invalid-title-chars' );
771 }
772
773 $changeTagsStore = MediaWikiServices::getInstance()->getChangeTagsStore();
774 if ( $changeTagsStore->isRestrictedTag( $tag ) ) {
775 return Status::newFatal( 'tags-create-reserved-prefix', ChangeTagsStore::PRIVATE_TAG_PREFIX );
776 }
777
778 return Status::newGood();
779 }
780
793 public static function canCreateTag( $tag, ?Authority $performer = null ) {
794 $user = null;
795 $services = MediaWikiServices::getInstance();
796 if ( $performer !== null ) {
797 if ( !$performer->isAllowed( 'managechangetags' ) ) {
798 return Status::newFatal( 'tags-manage-no-permission' );
799 }
800 if ( $performer->getBlock() && $performer->getBlock()->isSitewide() ) {
801 return Status::newFatal(
802 'tags-manage-blocked',
803 $performer->getUser()->getName()
804 );
805 }
806 // ChangeTagCanCreate hook still needs a full User object
807 $user = $services->getUserFactory()->newFromAuthority( $performer );
808 }
809
810 $status = self::isTagNameValid( $tag );
811 if ( !$status->isGood() ) {
812 return $status;
813 }
814
815 // does the tag already exist?
816 $changeTagsStore = $services->getChangeTagsStore();
817 if (
818 isset( $changeTagsStore->tagUsageStatistics()[$tag] ) ||
819 in_array( $tag, $changeTagsStore->listDefinedTags() )
820 ) {
821 return Status::newFatal( 'tags-create-already-exists', $tag );
822 }
823
824 // check with hooks
825 $canCreateResult = Status::newGood();
826 ( new HookRunner( $services->getHookContainer() ) )->onChangeTagCanCreate( $tag, $user, $canCreateResult );
827 return $canCreateResult;
828 }
829
849 public static function createTagWithChecks( string $tag, string $reason, Authority $performer,
850 bool $ignoreWarnings = false, array $logEntryTags = []
851 ) {
852 // are we allowed to do this?
853 $result = self::canCreateTag( $tag, $performer );
854 if ( $ignoreWarnings ? !$result->isOK() : !$result->isGood() ) {
855 $result->value = null;
856 return $result;
857 }
858
859 $changeTagsStore = MediaWikiServices::getInstance()->getChangeTagsStore();
860 $changeTagsStore->defineTag( $tag );
861 $logId = $changeTagsStore->logTagManagementAction( 'create', $tag, $reason,
862 $performer->getUser(), null, $logEntryTags );
863
864 return Status::newGood( $logId );
865 }
866
879 public static function canDeleteTag( string $tag, ?Authority $performer = null, int $flags = 0 ) {
880 $user = null;
881 $services = MediaWikiServices::getInstance();
882 $changeTagsStore = $services->getChangeTagsStore();
883 if ( $performer !== null ) {
884 if ( !$performer->isAllowed( 'deletechangetags' ) ) {
885 return Status::newFatal( 'tags-delete-no-permission' );
886 }
887 if ( $performer->getBlock() && $performer->getBlock()->isSitewide() ) {
888 return Status::newFatal(
889 'tags-manage-blocked',
890 $performer->getUser()->getName()
891 );
892 }
893 if ( $changeTagsStore->filterViewableTags( [ $tag ], $performer ) === [] ) {
894 return Status::newFatal( 'tags-delete-not-found', $tag );
895 }
896 // ChangeTagCanDelete hook still needs a full User object
897 $user = $services->getUserFactory()->newFromAuthority( $performer );
898 }
899
900 $tagUsage = $changeTagsStore->tagUsageStatistics();
901 if (
902 !isset( $tagUsage[$tag] ) &&
903 !in_array( $tag, $changeTagsStore->listDefinedTags() )
904 ) {
905 return Status::newFatal( 'tags-delete-not-found', $tag );
906 }
907
908 if ( $flags !== self::BYPASS_MAX_USAGE_CHECK &&
909 isset( $tagUsage[$tag] ) &&
910 $tagUsage[$tag] > self::MAX_DELETE_USES
911 ) {
912 return Status::newFatal( 'tags-delete-too-many-uses', $tag, self::MAX_DELETE_USES );
913 }
914
915 $softwareDefined = $changeTagsStore->listSoftwareDefinedTags();
916 if ( in_array( $tag, $softwareDefined ) ) {
917 // extension-defined tags can't be deleted unless the extension
918 // specifically allows it
919 $status = Status::newFatal( 'tags-delete-not-allowed' );
920 } else {
921 // user-defined tags are deletable unless otherwise specified
922 $status = Status::newGood();
923 }
924
925 ( new HookRunner( $services->getHookContainer() ) )->onChangeTagCanDelete( $tag, $user, $status );
926 return $status;
927 }
928
946 public static function deleteTagWithChecks( string $tag, string $reason, Authority $performer,
947 bool $ignoreWarnings = false, array $logEntryTags = []
948 ) {
949 $changeTagsStore = MediaWikiServices::getInstance()->getChangeTagsStore();
950 // are we allowed to do this?
951 $result = self::canDeleteTag( $tag, $performer );
952 if ( $ignoreWarnings ? !$result->isOK() : !$result->isGood() ) {
953 $result->value = null;
954 return $result;
955 }
956
957 // store the tag usage statistics
958 $hitcount = $changeTagsStore->tagUsageStatistics()[$tag] ?? 0;
959
960 // do it!
961 $deleteResult = $changeTagsStore->deleteTagEverywhere( $tag );
962 if ( !$deleteResult->isOK() ) {
963 return $deleteResult;
964 }
965
966 // log it
967 $changeTagsStore = MediaWikiServices::getInstance()->getChangeTagsStore();
968 $logId = $changeTagsStore->logTagManagementAction( 'delete', $tag, $reason, $performer->getUser(),
969 $hitcount, $logEntryTags );
970
971 $deleteResult->value = $logId;
972 return $deleteResult;
973 }
974
1004 public static function getChangeTagListSummary(
1005 MessageLocalizer $localizer,
1006 Language $lang,
1007 bool $activeOnly = self::TAG_SET_ACTIVE_ONLY,
1008 bool $useAllTags = self::USE_ALL_TAGS
1009 ) {
1010 wfDeprecated( __METHOD__, '1.47' );
1011 return MediaWikiServices::getInstance()->getChangeTagsFormatter()->getChangeTagListSummary(
1012 new SimpleLocalizationContext( $localizer, $lang ),
1013 ( $localizer instanceof IContextSource ? $localizer : RequestContext::getMain() )->getAuthority(),
1014 $activeOnly,
1015 $useAllTags
1016 );
1017 }
1018
1035 public static function getChangeTagList(
1036 MessageLocalizer $localizer, Language $lang,
1037 bool $activeOnly = self::TAG_SET_ACTIVE_ONLY, bool $useAllTags = self::USE_ALL_TAGS,
1038 $labelsOnly = false
1039 ) {
1040 wfDeprecated( __METHOD__, '1.47' );
1041 return MediaWikiServices::getInstance()->getChangeTagsFormatter()->getChangeTagList(
1042 new SimpleLocalizationContext( $localizer, $lang ),
1043 ( $localizer instanceof IContextSource ? $localizer : RequestContext::getMain() )->getAuthority(),
1044 $activeOnly,
1045 $useAllTags,
1046 $labelsOnly
1047 );
1048 }
1049
1064 public static function showTagEditingUI( Authority $performer ) {
1065 $changeTagsStore = MediaWikiServices::getInstance()->getChangeTagsStore();
1066 return $performer->isAllowed( 'changetags' ) && (bool)$changeTagsStore->listExplicitlyDefinedTags();
1067 }
1068}
1069
1071class_alias( ChangeTags::class, 'ChangeTags' );
const NS_MEDIAWIKI
Definition Defines.php:59
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:71
const string PRIVATE_TAG_PREFIX
Reserved name prefix for rights-restricted change tags.
Recent changes tagging.
static canCreateTag( $tag, ?Authority $performer=null)
Is it OK to allow the user to create this tag?
const TAG_REVERTED
The tagged edit is reverted by a subsequent edit (which is tagged by one of TAG_ROLLBACK,...
static canDeleteTag(string $tag, ?Authority $performer=null, int $flags=0)
Is it OK to allow the user to delete this tag?
static deleteTagWithChecks(string $tag, string $reason, Authority $performer, bool $ignoreWarnings=false, array $logEntryTags=[])
Deletes a tag, checking whether it is allowed first, and adding a log entry afterwards.
static tagShortDescriptionMessage( $tag, MessageLocalizer $context)
Get the message object for the tag's short description.
const TAG_SERVER_SIDE_UPLOAD
This tagged edit was performed while importing media files using the importImages....
static canAddTagsAccompanyingChange(array $tags, ?Authority $performer=null, $checkBlock=true)
Is it OK to allow the user to apply all the specified tags at the same time as they edit/make the cha...
static buildTagFilterSelector( $selected, $ooui, IContextSource $context, bool $activeOnly=self::TAG_SET_ACTIVE_ONLY, bool $useAllTags=self::USE_ALL_TAGS)
Build a text box to select a change tag.
const BYPASS_MAX_USAGE_CHECK
Flag for canDeleteTag().
const TAG_REMOVED_REDIRECT
The tagged edit turns a redirect page into a non-redirect.
static getChangeTagListSummary(MessageLocalizer $localizer, Language $lang, bool $activeOnly=self::TAG_SET_ACTIVE_ONLY, bool $useAllTags=self::USE_ALL_TAGS)
Get information about change tags, without parsing messages, for tag filter dropdown menus.
static getChangeTagList(MessageLocalizer $localizer, Language $lang, bool $activeOnly=self::TAG_SET_ACTIVE_ONLY, bool $useAllTags=self::USE_ALL_TAGS, $labelsOnly=false)
Get information about change tags for tag filter dropdown menus.
static createTagWithChecks(string $tag, string $reason, Authority $performer, bool $ignoreWarnings=false, array $logEntryTags=[])
Creates a tag by adding it to change_tag_def table.
static formatSummaryRow( $tags, $unused, MessageLocalizer $localizer)
Creates HTML for the given tags.
const TAG_SET_ACTIVE_ONLY
Constants that can be used to set the activeOnly parameter for calling self::buildCustomTagFilterSele...
static canDeactivateTag(string $tag, ?Authority $performer=null)
Is it OK to allow the user to deactivate this tag?
static deactivateTagWithChecks(string $tag, string $reason, Authority $performer, bool $ignoreWarnings=false, array $logEntryTags=[])
Deactivates a tag, checking whether it is allowed first, and adding a log entry afterwards.
static activateTagWithChecks(string $tag, string $reason, Authority $performer, bool $ignoreWarnings=false, array $logEntryTags=[])
Activates a tag, checking whether it is allowed first, and adding a log entry afterwards.
const TAG_RECREATE
The tagged edit recreates a page that has been previously deleted.
const TAG_BLANK
The tagged edit blanks the page (replaces it with the empty string).
static canActivateTag(string $tag, ?Authority $performer=null)
Is it OK to allow the user to activate this tag?
const REVERT_TAGS
List of tags which denote a revert of some sort.
const TAG_EDITED_OTHER_USERS_JS
This tagged edit was performed on a page with the JavaScript content model on a page not a subpage of...
const TAG_EDITED_OTHER_USERS_CSS
This tagged edit was performed on a page with the CSS content model on a page not a subpage of the us...
const TAG_CONTENT_MODEL_CHANGE
The tagged edit changes the content model of the page.
static isTagNameValid( $tag)
Is the tag name valid?
const TAG_NEW_REDIRECT
The tagged edit creates a new redirect (either by creating a new page or turning an existing page int...
const TAG_IPBLOCK_APPEAL
This tagged temporary account auto-creation was performed via Special:Mytalk from an IP address that ...
const TAG_CHANGED_REDIRECT_TARGET
The tagged edit changes the target of a redirect page.
static tagLongDescriptionMessage( $tag, MessageLocalizer $context)
Get the message object for the tag's long description.
static tagDescription( $tag, MessageLocalizer $context)
Get a short description for a tag.
const USE_ALL_TAGS
Constants that can be used to set the useAllTags parameter for calling self::buildCustomTagFilterSele...
const TAG_ROLLBACK
The tagged edit is a rollback (undoes the previous edit and all immediately preceding edits by the sa...
const TAG_MANUAL_REVERT
The tagged edit restores the page to an earlier revision.
static showTagEditingUI(Authority $performer)
Indicate whether change tag editing UI is relevant.
const TAG_REPLACE
The tagged edit removes more than 90% of the content of the page.
static updateTagsWithChecks( $tagsToAdd, $tagsToRemove, $rc_id, $rev_id, $log_id, $params, string $reason, Authority $performer)
Adds and/or removes tags to/from a given change, checking whether it is allowed first,...
const TAG_UNDO
The tagged edit is was performed via the "undo" link.
static canUpdateTags(array $tagsToAdd, array $tagsToRemove, ?Authority $performer=null)
Is it OK to allow the user to adds and remove the given tags to/from a change?
static restrictedTagError( $msgOne, $msgMulti, $tags)
Helper function to generate a fatal status with a 'not-allowed' type error.
static tagHelpLink( $tag, MessageLocalizer $context)
Get the tag's help link.
Group all the pieces relevant to the context of a request into one instance.
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Base class for language-specific code.
Definition Language.php:65
Variant of the Message class.
An implementation of LocalizationContext that implements only the methods defined in the interface.
Class for creating new log entries and inserting them into the database.
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition Message.php:144
static listParam(array $list, $type=ListType::AND)
Definition Message.php:1355
static plaintextParam( $plaintext)
Definition Message.php:1344
A StatusValue for permission errors.
Represents an authority that has all permissions.
List for logging table items.
static suggestTarget( $target, array $ids)
Suggest a target for the revision deletion Optionally override this function.1.22 Title|null
The base class for all skins.
Definition Skin.php:54
Parent class for all special pages.
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,...
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:44
Represents a title within MediaWiki.
Definition Title.php:69
Interface for objects which can provide a MediaWiki context on request.
Interface for localizing messages in MediaWiki.
msg( $key,... $params)
This is the method for getting translated interface messages.
This interface represents the authority associated with the current execution context,...
Definition Authority.php:23
isAllowed(string $permission, ?PermissionStatus $status=null)
Checks whether this authority has the given permission in general.
getUser()
Returns the performer of the actions associated with this authority.
authorizeAction(string $action, ?PermissionStatus $status=null)
Authorize an action.