X-Git-Url: https://scripts.mit.edu/gitweb/autoinstallsdev/mediawiki.git/blobdiff_plain/19e297c21b10b1b8a3acad5e73fc71dcb35db44a..6932310fd58ebef145fa01eb76edf7150284d8ea:/includes/specials/SpecialEditTags.php diff --git a/includes/specials/SpecialEditTags.php b/includes/specials/SpecialEditTags.php new file mode 100644 index 00000000..aad09247 --- /dev/null +++ b/includes/specials/SpecialEditTags.php @@ -0,0 +1,471 @@ +checkPermissions(); + $this->checkReadOnly(); + + $output = $this->getOutput(); + $user = $this->getUser(); + $request = $this->getRequest(); + + // Check blocks + if ( $user->isBlocked() ) { + throw new UserBlockedError( $user->getBlock() ); + } + + $this->setHeaders(); + $this->outputHeader(); + + $this->getOutput()->addModules( [ 'mediawiki.special.edittags', + 'mediawiki.special.edittags.styles' ] ); + + $this->submitClicked = $request->wasPosted() && $request->getBool( 'wpSubmit' ); + + // Handle our many different possible input types + $ids = $request->getVal( 'ids' ); + if ( !is_null( $ids ) ) { + // Allow CSV from the form hidden field, or a single ID for show/hide links + $this->ids = explode( ',', $ids ); + } else { + // Array input + $this->ids = array_keys( $request->getArray( 'ids', [] ) ); + } + $this->ids = array_unique( array_filter( $this->ids ) ); + + // No targets? + if ( count( $this->ids ) == 0 ) { + throw new ErrorPageError( 'tags-edit-nooldid-title', 'tags-edit-nooldid-text' ); + } + + $this->typeName = $request->getVal( 'type' ); + $this->targetObj = Title::newFromText( $request->getText( 'target' ) ); + + // sanity check of parameter + switch ( $this->typeName ) { + case 'logentry': + case 'logging': + $this->typeName = 'logentry'; + break; + default: + $this->typeName = 'revision'; + break; + } + + // Allow the list type to adjust the passed target + // Yuck! Copied straight out of SpecialRevisiondelete, but it does exactly + // what we want + $this->targetObj = RevisionDeleter::suggestTarget( + $this->typeName === 'revision' ? 'revision' : 'logging', + $this->targetObj, + $this->ids + ); + + $this->isAllowed = $user->isAllowed( 'changetags' ); + + $this->reason = $request->getVal( 'wpReason' ); + // We need a target page! + if ( is_null( $this->targetObj ) ) { + $output->addWikiMsg( 'undelete-header' ); + return; + } + // Give a link to the logs/hist for this page + $this->showConvenienceLinks(); + + // Either submit or create our form + if ( $this->isAllowed && $this->submitClicked ) { + $this->submit(); + } else { + $this->showForm(); + } + + // Show relevant lines from the tag log + $tagLogPage = new LogPage( 'tag' ); + $output->addHTML( "

" . $tagLogPage->getName()->escaped() . "

\n" ); + LogEventsList::showLogExtract( + $output, + 'tag', + $this->targetObj, + '', /* user */ + [ 'lim' => 25, 'conds' => [], 'useMaster' => $this->wasSaved ] + ); + } + + /** + * Show some useful links in the subtitle + */ + protected function showConvenienceLinks() { + // Give a link to the logs/hist for this page + if ( $this->targetObj ) { + // Also set header tabs to be for the target. + $this->getSkin()->setRelevantTitle( $this->targetObj ); + + $linkRenderer = $this->getLinkRenderer(); + $links = []; + $links[] = $linkRenderer->makeKnownLink( + SpecialPage::getTitleFor( 'Log' ), + $this->msg( 'viewpagelogs' )->text(), + [], + [ + 'page' => $this->targetObj->getPrefixedText(), + 'hide_tag_log' => '0', + ] + ); + if ( !$this->targetObj->isSpecialPage() ) { + // Give a link to the page history + $links[] = $linkRenderer->makeKnownLink( + $this->targetObj, + $this->msg( 'pagehist' )->text(), + [], + [ 'action' => 'history' ] + ); + } + // Link to Special:Tags + $links[] = $linkRenderer->makeKnownLink( + SpecialPage::getTitleFor( 'Tags' ), + $this->msg( 'tags-edit-manage-link' )->text() + ); + // Logs themselves don't have histories or archived revisions + $this->getOutput()->addSubtitle( $this->getLanguage()->pipeList( $links ) ); + } + } + + /** + * Get the list object for this request + * @return ChangeTagsList + */ + protected function getList() { + if ( is_null( $this->revList ) ) { + $this->revList = ChangeTagsList::factory( $this->typeName, $this->getContext(), + $this->targetObj, $this->ids ); + } + + return $this->revList; + } + + /** + * Show a list of items that we will operate on, and show a form which allows + * the user to modify the tags applied to those items. + */ + protected function showForm() { + $userAllowed = true; + + $out = $this->getOutput(); + // Messages: tags-edit-revision-selected, tags-edit-logentry-selected + $out->wrapWikiMsg( "$1", [ + "tags-edit-{$this->typeName}-selected", + $this->getLanguage()->formatNum( count( $this->ids ) ), + $this->targetObj->getPrefixedText() + ] ); + + $this->addHelpLink( 'Help:Tags' ); + $out->addHTML( "" ); + // Explanation text + $out->wrapWikiMsg( '

$1

', "tags-edit-{$this->typeName}-explanation" ); + + // Show form if the user can submit + if ( $this->isAllowed ) { + $form = Xml::openElement( 'form', [ 'method' => 'post', + 'action' => $this->getPageTitle()->getLocalURL( [ 'action' => 'submit' ] ), + 'id' => 'mw-revdel-form-revisions' ] ) . + Xml::fieldset( $this->msg( "tags-edit-{$this->typeName}-legend", + count( $this->ids ) )->text() ) . + $this->buildCheckBoxes() . + Xml::openElement( 'table' ) . + "\n" . + '' . + Xml::label( $this->msg( 'tags-edit-reason' )->text(), 'wpReason' ) . + '' . + '' . + Xml::input( + 'wpReason', + 60, + $this->reason, + [ 'id' => 'wpReason', 'maxlength' => 100 ] + ) . + '' . + "\n" . + '' . + '' . + Xml::submitButton( $this->msg( "tags-edit-{$this->typeName}-submit", + $numRevisions )->text(), [ 'name' => 'wpSubmit' ] ) . + '' . + "\n" . + Xml::closeElement( 'table' ) . + Html::hidden( 'wpEditToken', $this->getUser()->getEditToken() ) . + Html::hidden( 'target', $this->targetObj->getPrefixedText() ) . + Html::hidden( 'type', $this->typeName ) . + Html::hidden( 'ids', implode( ',', $this->ids ) ) . + Xml::closeElement( 'fieldset' ) . "\n" . + Xml::closeElement( 'form' ) . "\n"; + } else { + $form = ''; + } + $out->addHTML( $form ); + } + + /** + * @return string HTML + */ + protected function buildCheckBoxes() { + // If there is just one item, provide the user with a multi-select field + $list = $this->getList(); + $tags = []; + if ( $list->length() == 1 ) { + $list->reset(); + $tags = $list->current()->getTags(); + if ( $tags ) { + $tags = explode( ',', $tags ); + } else { + $tags = []; + } + + $html = ''; + $html .= ''; + $tagSelect = $this->getTagSelect( $tags, $this->msg( 'tags-edit-new-tags' )->plain() ); + $html .= '
' . $this->msg( 'tags-edit-existing-tags' )->escaped() . + ''; + if ( $tags ) { + $html .= $this->getLanguage()->commaList( array_map( 'htmlspecialchars', $tags ) ); + } else { + $html .= $this->msg( 'tags-edit-existing-tags-none' )->parse(); + } + $html .= '
' . $tagSelect[0] . '' . $tagSelect[1]; + } else { + // Otherwise, use a multi-select field for adding tags, and a list of + // checkboxes for removing them + + // @codingStandardsIgnoreStart Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed + for ( $list->reset(); $list->current(); $list->next() ) { + // @codingStandardsIgnoreEnd + $currentTags = $list->current()->getTags(); + if ( $currentTags ) { + $tags = array_merge( $tags, explode( ',', $currentTags ) ); + } + } + $tags = array_unique( $tags ); + + $html = '
'; + $tagSelect = $this->getTagSelect( [], $this->msg( 'tags-edit-add' )->plain() ); + $html .= '

' . $tagSelect[0] . '

' . $tagSelect[1] . '
'; + $html .= Xml::element( 'p', null, $this->msg( 'tags-edit-remove' )->plain() ); + $html .= Xml::checkLabel( $this->msg( 'tags-edit-remove-all-tags' )->plain(), + 'wpRemoveAllTags', 'mw-edittags-remove-all' ); + $i = 0; // used for generating checkbox IDs only + foreach ( $tags as $tag ) { + $html .= Xml::element( 'br' ) . "\n" . Xml::checkLabel( $tag, + 'wpTagsToRemove[]', 'mw-edittags-remove-' . $i++, false, [ + 'value' => $tag, + 'class' => 'mw-edittags-remove-checkbox', + ] ); + } + } + + // also output the tags currently applied as a hidden form field, so we + // know what to remove from the revision/log entry when the form is submitted + $html .= Html::hidden( 'wpExistingTags', implode( ',', $tags ) ); + $html .= '
'; + + return $html; + } + + /** + * Returns a + * element. + * @param string $label The text of a