X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FEditPage.php;h=ca1486436af7118b785687ddac1e0a3b547ac252;hb=1898a81f249291c62079d76b18ff573f21644261;hp=7e4e411d5e6adebf4e26a96a79a0e05254f5b1dd;hpb=196db3429307c04e5c92f6c06a965a394d4a8a87;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/EditPage.php b/includes/EditPage.php index 7e4e411d5e..ca1486436a 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -21,6 +21,8 @@ */ use MediaWiki\Logger\LoggerFactory; +use MediaWiki\MediaWikiServices; +use Wikimedia\ScopedCallback; /** * The edit page/HTML interface (split from Article) @@ -406,6 +408,11 @@ class EditPage { */ protected $context; + /** + * @var bool Whether an old revision is edited + */ + private $isOldRev = false; + /** * @param Article $article */ @@ -577,7 +584,7 @@ class EditPage { ) { $this->displayViewSourcePage( $this->getContentObject(), - wfMessage( + $this->context->msg( 'contentmodelediterror', $revision->getContentModel(), $this->contentModel @@ -714,7 +721,7 @@ class EditPage { Hooks::run( 'EditPage::showReadOnlyForm:initial', [ $this, &$wgOut ] ); $wgOut->setRobotPolicy( 'noindex,nofollow' ); - $wgOut->setPageTitle( wfMessage( + $wgOut->setPageTitle( $this->context->msg( 'viewsource-title', $this->getContextTitle()->getPrefixedText() ) ); @@ -747,8 +754,7 @@ class EditPage { $this->showTextbox( $text, 'wpTextbox1', [ 'readonly' ] ); $wgOut->addHTML( $this->editFormTextAfterContent ); - $wgOut->addHTML( Html::rawElement( 'div', [ 'class' => 'templatesUsed' ], - Linker::formatTemplates( $this->getTemplates() ) ) ); + $wgOut->addHTML( $this->makeTemplatesOnThisPageList( $this->getTemplates() ) ); $wgOut->addModules( 'mediawiki.action.edit.collapsibleFooter' ); @@ -1008,9 +1014,17 @@ class EditPage { // May be overridden by revision. $this->contentFormat = $request->getText( 'format', $this->contentFormat ); - if ( !ContentHandler::getForModelID( $this->contentModel ) - ->isSupportedFormat( $this->contentFormat ) - ) { + try { + $handler = ContentHandler::getForModelID( $this->contentModel ); + } catch ( MWUnknownContentModelException $e ) { + throw new ErrorPageError( + 'editpage-invalidcontentmodel-title', + 'editpage-invalidcontentmodel-text', + [ $this->contentModel ] + ); + } + + if ( !$handler->isSupportedFormat( $this->contentFormat ) ) { throw new ErrorPageError( 'editpage-notsupportedcontentformat-title', 'editpage-notsupportedcontentformat-text', @@ -1030,7 +1044,6 @@ class EditPage { // Allow extensions to modify form data Hooks::run( 'EditPage::importFormData', [ $this, $request ] ); - } /** @@ -1170,12 +1183,12 @@ class EditPage { if ( $firstrev && $firstrev->getId() == $undo ) { $userText = $undorev->getUserText(); if ( $userText === '' ) { - $undoSummary = wfMessage( + $undoSummary = $this->context->msg( 'undo-summary-username-hidden', $undo )->inContentLanguage()->text(); } else { - $undoSummary = wfMessage( + $undoSummary = $this->context->msg( 'undo-summary', $undo, $userText @@ -1184,7 +1197,7 @@ class EditPage { if ( $this->summary === '' ) { $this->summary = $undoSummary; } else { - $this->summary = $undoSummary . wfMessage( 'colon-separator' ) + $this->summary = $undoSummary . $this->context->msg( 'colon-separator' ) ->inContentLanguage()->text() . $this->summary; } $this->undidRev = $undo; @@ -1202,7 +1215,7 @@ class EditPage { // Messages: undo-success, undo-failure, undo-norev, undo-nochange $class = ( $undoMsg == 'success' ? '' : 'error ' ) . "mw-undo-{$undoMsg}"; $this->editFormPageTop .= $wgOut->parse( "
" . - wfMessage( 'undo-' . $undoMsg )->plain() . '
', true, /* interface */true ); + $this->context->msg( 'undo-' . $undoMsg )->plain() . '', true, /* interface */true ); } if ( $content === false ) { @@ -1605,8 +1618,9 @@ class EditPage { protected function runPostMergeFilters( Content $content, Status $status, User $user ) { // Run old style post-section-merge edit filter if ( !ContentHandler::runLegacyHooks( 'EditFilterMerged', - [ $this, $content, &$this->hookError, $this->summary ] ) - ) { + [ $this, $content, &$this->hookError, $this->summary ], + '1.21' + ) ) { # Error messages etc. could be handled within the hook... $status->fatal( 'hookaborted' ); $status->value = self::AS_HOOK_ERROR; @@ -1666,7 +1680,7 @@ class EditPage { // passed. if ( $this->summary === '' ) { $cleanSectionTitle = $wgParser->stripSectionName( $this->sectiontitle ); - return wfMessage( 'newsectionsummary' ) + return $this->context->msg( 'newsectionsummary' ) ->rawParams( $cleanSectionTitle )->inContentLanguage()->text(); } } elseif ( $this->summary !== '' ) { @@ -1674,7 +1688,7 @@ class EditPage { # This is a new section, so create a link to the new section # in the revision summary. $cleanSummary = $wgParser->stripSectionName( $this->summary ); - return wfMessage( 'newsectionsummary' ) + return $this->context->msg( 'newsectionsummary' ) ->rawParams( $cleanSummary )->inContentLanguage()->text(); } return $this->summary; @@ -1838,8 +1852,17 @@ class EditPage { } elseif ( !$wgUser->isAllowed( 'editcontentmodel' ) ) { $status->setResult( false, self::AS_NO_CHANGE_CONTENT_MODEL ); return $status; - } + // Make sure the user can edit the page under the new content model too + $titleWithNewContentModel = clone $this->mTitle; + $titleWithNewContentModel->setContentModel( $this->contentModel ); + if ( !$titleWithNewContentModel->userCan( 'editcontentmodel', $wgUser ) + || !$titleWithNewContentModel->userCan( 'edit', $wgUser ) + ) { + $status->setResult( false, self::AS_NO_CHANGE_CONTENT_MODEL ); + return $status; + } + $changingContentModel = true; $oldContentModel = $this->mTitle->getContentModel(); } @@ -2213,7 +2236,6 @@ class EditPage { * @return bool */ private function mergeChangesIntoContent( &$editContent ) { - $db = wfGetDB( DB_MASTER ); // This is the revision the editor started from @@ -2349,7 +2371,7 @@ class EditPage { if ( $displayTitle === false ) { $displayTitle = $contextTitle->getPrefixedText(); } - $wgOut->setPageTitle( wfMessage( $msg, $displayTitle ) ); + $wgOut->setPageTitle( $this->context->msg( $msg, $displayTitle ) ); # Transmit the name of the message to JavaScript for live preview # Keep Resources.php/mediawiki.action.edit.preview in sync with the possible keys $wgOut->addJsConfigVars( [ @@ -2434,7 +2456,7 @@ class EditPage { # Try to add a custom edit intro, or use the standard one if this is not possible. if ( !$this->showCustomIntro() && !$this->mTitle->exists() ) { $helpLink = wfExpandUrl( Skin::makeInternalOrExternalUrl( - wfMessage( 'helppage' )->inContentLanguage()->text() + $this->context->msg( 'helppage' )->inContentLanguage()->text() ) ); if ( $wgUser->isLoggedIn() ) { $wgOut->wrapWikiMsg( @@ -2576,10 +2598,21 @@ class EditPage { $this->setHeaders(); - if ( $this->showHeader() === false ) { + $this->addTalkPageText(); + $this->addEditNotices(); + + if ( !$this->isConflict && + $this->section != '' && + !$this->isSectionEditSupported() ) { + // We use $this->section to much before this and getVal('wgSection') directly in other places + // at this point we can't reset $this->section to '' to fallback to non-section editing. + // Someone is welcome to try refactoring though + $wgOut->showErrorPage( 'sectioneditnotsupported-title', 'sectioneditnotsupported-text' ); return; } + $this->showHeader(); + $wgOut->addHTML( $this->editFormPageTop ); if ( $wgUser->getOption( 'previewontop' ) ) { @@ -2624,7 +2657,7 @@ class EditPage { . Html::rawElement( 'label', [ 'for' => 'wpAntispam' ], - wfMessage( 'simpleantispam-label' )->parse() + $this->context->msg( 'simpleantispam-label' )->parse() ) . Xml::element( 'input', @@ -2654,8 +2687,8 @@ class EditPage { : 'confirmrecreate'; $wgOut->addHTML( '
' . - wfMessage( $key, $username, "$comment" )->parse() . - Xml::checkLabel( wfMessage( 'recreate' )->text(), 'wpRecreate', 'wpRecreate', false, + $this->context->msg( $key, $username, "$comment" )->parse() . + Xml::checkLabel( $this->context->msg( 'recreate' )->text(), 'wpRecreate', 'wpRecreate', false, [ 'title' => Linker::titleAttrib( 'recreate' ), 'tabindex' => 1, 'id' => 'wpRecreate' ] ) . '
' @@ -2744,15 +2777,13 @@ class EditPage { $wgOut->addHTML( $this->editFormTextAfterTools . "\n" ); - $wgOut->addHTML( Html::rawElement( 'div', [ 'class' => 'templatesUsed' ], - Linker::formatTemplates( $this->getTemplates(), $this->preview, $this->section != '' ) ) ); + $wgOut->addHTML( $this->makeTemplatesOnThisPageList( $this->getTemplates() ) ); $wgOut->addHTML( Html::rawElement( 'div', [ 'class' => 'hiddencats' ], Linker::formatHiddenCategories( $this->page->getHiddenCategories() ) ) ); - if ( $this->mParserOutput ) { - $wgOut->setLimitReportData( $this->mParserOutput->getLimitReportData() ); - } + $wgOut->addHTML( Html::rawElement( 'div', [ 'class' => 'limitreport' ], + self::getPreviewLimitReport( $this->mParserOutput ) ) ); $wgOut->addModules( 'mediawiki.action.edit.collapsibleFooter' ); @@ -2761,7 +2792,7 @@ class EditPage { $this->showConflict(); } catch ( MWContentSerializationException $ex ) { // this can't really happen, but be nice if it does. - $msg = wfMessage( + $msg = $this->context->msg( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, @@ -2791,7 +2822,31 @@ class EditPage { if ( !$wgUser->getOption( 'previewontop' ) ) { $this->displayPreviewArea( $previewOutput, false ); } + } + + /** + * Wrapper around TemplatesOnThisPageFormatter to make + * a "templates on this page" list. + * + * @param Title[] $templates + * @return string HTML + */ + protected function makeTemplatesOnThisPageList( array $templates ) { + $templateListFormatter = new TemplatesOnThisPageFormatter( + $this->context, MediaWikiServices::getInstance()->getLinkRenderer() + ); + + // preview if preview, else section if section, else false + $type = false; + if ( $this->preview ) { + $type = 'preview'; + } elseif ( $this->section != '' ) { + $type = 'section'; + } + return Html::rawElement( 'div', [ 'class' => 'templatesUsed' ], + $templateListFormatter->format( $templates, $type ) + ); } /** @@ -2810,44 +2865,14 @@ class EditPage { } } - /** - * @return bool - */ protected function showHeader() { - global $wgOut, $wgUser, $wgMaxArticleSize, $wgLang; + global $wgOut, $wgUser; global $wgAllowUserCss, $wgAllowUserJs; - if ( $this->mTitle->isTalkPage() ) { - $wgOut->addWikiMsg( 'talkpagetext' ); - } - - // Add edit notices - $editNotices = $this->mTitle->getEditNotices( $this->oldid ); - if ( count( $editNotices ) ) { - $wgOut->addHTML( implode( "\n", $editNotices ) ); - } else { - $msg = wfMessage( 'editnotice-notext' ); - if ( !$msg->isDisabled() ) { - $wgOut->addHTML( - '
' - . $msg->parseAsBlock() - . '
' - ); - } - } - if ( $this->isConflict ) { - $wgOut->wrapWikiMsg( "
\n$1\n
", 'explainconflict' ); + $this->addExplainConflictHeader( $wgOut ); $this->editRevId = $this->page->getLatest(); } else { - if ( $this->section != '' && !$this->isSectionEditSupported() ) { - // We use $this->section to much before this and getVal('wgSection') directly in other places - // at this point we can't reset $this->section to '' to fallback to non-section editing. - // Someone is welcome to try refactoring though - $wgOut->showErrorPage( 'sectioneditnotsupported-title', 'sectioneditnotsupported-text' ); - return false; - } - if ( $this->section != '' && $this->section != 'new' ) { if ( !$this->summary && !$this->preview && !$this->diff ) { $sectionTitle = self::extractSectionTitle( $this->textbox1 ); // FIXME: use Content object @@ -2905,6 +2930,7 @@ class EditPage { if ( !$revision->isCurrent() ) { $this->mArticle->setOldSubtitle( $revision->getId() ); $wgOut->addWikiMsg( 'editingold' ); + $this->isOldRev = true; } } elseif ( $this->mTitle->exists() ) { // Something went wrong @@ -2972,69 +2998,12 @@ class EditPage { } } - if ( $this->mTitle->isProtected( 'edit' ) && - MWNamespace::getRestrictionLevels( $this->mTitle->getNamespace() ) !== [ '' ] - ) { - # Is the title semi-protected? - if ( $this->mTitle->isSemiProtected() ) { - $noticeMsg = 'semiprotectedpagewarning'; - } else { - # Then it must be protected based on static groups (regular) - $noticeMsg = 'protectedpagewarning'; - } - LogEventsList::showLogExtract( $wgOut, 'protect', $this->mTitle, '', - [ 'lim' => 1, 'msgKey' => [ $noticeMsg ] ] ); - } - if ( $this->mTitle->isCascadeProtected() ) { - # Is this page under cascading protection from some source pages? - /** @var Title[] $cascadeSources */ - list( $cascadeSources, /* $restrictions */ ) = $this->mTitle->getCascadeProtectionSources(); - $notice = "
\n$1\n"; - $cascadeSourcesCount = count( $cascadeSources ); - if ( $cascadeSourcesCount > 0 ) { - # Explain, and list the titles responsible - foreach ( $cascadeSources as $page ) { - $notice .= '* [[:' . $page->getPrefixedText() . "]]\n"; - } - } - $notice .= '
'; - $wgOut->wrapWikiMsg( $notice, [ 'cascadeprotectedwarning', $cascadeSourcesCount ] ); - } - if ( !$this->mTitle->exists() && $this->mTitle->getRestrictions( 'create' ) ) { - LogEventsList::showLogExtract( $wgOut, 'protect', $this->mTitle, '', - [ 'lim' => 1, - 'showIfEmpty' => false, - 'msgKey' => [ 'titleprotectedwarning' ], - 'wrap' => "
\n$1
" ] ); - } + $this->addPageProtectionWarningHeaders(); - if ( $this->contentLength === false ) { - $this->contentLength = strlen( $this->textbox1 ); - } + $this->addLongPageWarningHeader(); - if ( $this->tooBig || $this->contentLength > $wgMaxArticleSize * 1024 ) { - $wgOut->wrapWikiMsg( "
\n$1\n
", - [ - 'longpageerror', - $wgLang->formatNum( round( $this->contentLength / 1024, 3 ) ), - $wgLang->formatNum( $wgMaxArticleSize ) - ] - ); - } else { - if ( !wfMessage( 'longpage-hint' )->isDisabled() ) { - $wgOut->wrapWikiMsg( "
\n$1\n
", - [ - 'longpage-hint', - $wgLang->formatSize( strlen( $this->textbox1 ) ), - strlen( $this->textbox1 ) - ] - ); - } - } # Add header copyright warning $this->showHeaderCopyrightWarning(); - - return true; } /** @@ -3042,14 +3011,14 @@ class EditPage { * subclasses may reorganize the form. * Note that you do not need to worry about the label's for=, it will be * inferred by the id given to the input. You can remove them both by - * passing array( 'id' => false ) to $userInputAttrs. + * passing [ 'id' => false ] to $userInputAttrs. * * @param string $summary The value of the summary input * @param string $labelText The html to place inside the label * @param array $inputAttrs Array of attrs to use on the input * @param array $spanLabelAttrs Array of attrs to use on the span inside the label * - * @return array An array in the format array( $label, $input ) + * @return array An array in the format [ $label, $input ] */ function getSummaryInput( $summary = "", $labelText = null, $inputAttrs = null, $spanLabelAttrs = null @@ -3102,7 +3071,7 @@ class EditPage { return; } } - $labelText = wfMessage( $isSubjectPreview ? 'subject' : 'summary' )->parse(); + $labelText = $this->context->msg( $isSubjectPreview ? 'subject' : 'summary' )->parse(); list( $label, $input ) = $this->getSummaryInput( $summary, $labelText, @@ -3129,13 +3098,14 @@ class EditPage { global $wgParser; if ( $isSubjectPreview ) { - $summary = wfMessage( 'newsectionsummary' )->rawParams( $wgParser->stripSectionName( $summary ) ) + $summary = $this->context->msg( 'newsectionsummary' ) + ->rawParams( $wgParser->stripSectionName( $summary ) ) ->inContentLanguage()->text(); } $message = $isSubjectPreview ? 'subject-preview' : 'summary-preview'; - $summary = wfMessage( $message )->parse() + $summary = $this->context->msg( $message )->parse() . Linker::commentBlock( $summary, $this->mTitle, $isSubjectPreview ); return Xml::tags( 'div', [ 'class' => 'mw-summary-preview' ], $summary ); } @@ -3214,6 +3184,10 @@ HTML $classes[] = 'mw-textarea-cprotected'; } } + # Is an old revision being edited? + if ( $this->isOldRev ) { + $classes[] = 'mw-textarea-oldrev'; + } $attribs = [ 'tabindex' => 1 ]; @@ -3244,27 +3218,9 @@ HTML global $wgOut, $wgUser; $wikitext = $this->safeUnicodeOutput( $text ); - if ( strval( $wikitext ) !== '' ) { - // Ensure there's a newline at the end, otherwise adding lines - // is awkward. - // But don't add a newline if the ext is empty, or Firefox in XHTML - // mode will show an extra newline. A bit annoying. - $wikitext .= "\n"; - } - - $attribs = $customAttribs + [ - 'accesskey' => ',', - 'id' => $name, - 'cols' => $wgUser->getIntOption( 'cols' ), - 'rows' => $wgUser->getIntOption( 'rows' ), - // Avoid PHP notices when appending preferences - // (appending allows customAttribs['style'] to still work). - 'style' => '' - ]; + $wikitext = $this->addNewLineAtEnd( $wikitext ); - $pageLang = $this->mTitle->getPageLanguage(); - $attribs['lang'] = $pageLang->getHtmlCode(); - $attribs['dir'] = $pageLang->getDir(); + $attribs = $this->buildTextboxAttribs( $name, $customAttribs, $wgUser ); $wgOut->addHTML( Html::textarea( $name, $wikitext, $attribs ) ); } @@ -3300,7 +3256,7 @@ HTML try { $this->showDiff(); } catch ( MWContentSerializationException $ex ) { - $msg = wfMessage( + $msg = $this->context->msg( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, @@ -3367,7 +3323,7 @@ HTML } if ( $newContent ) { - ContentHandler::runLegacyHooks( 'EditPageGetDiffText', [ $this, &$newContent ] ); + ContentHandler::runLegacyHooks( 'EditPageGetDiffText', [ $this, &$newContent ], '1.21' ); Hooks::run( 'EditPageGetDiffContent', [ $this, &$newContent ] ); $popts = ParserOptions::newFromUserAndLang( $wgUser, $wgContLang ); @@ -3375,8 +3331,8 @@ HTML } if ( ( $oldContent && !$oldContent->isEmpty() ) || ( $newContent && !$newContent->isEmpty() ) ) { - $oldtitle = wfMessage( $oldtitlemsg )->parse(); - $newtitle = wfMessage( 'yourtext' )->parse(); + $oldtitle = $this->context->msg( $oldtitlemsg )->parse(); + $newtitle = $this->context->msg( 'yourtext' )->parse(); if ( !$oldContent ) { $oldContent = $newContent->getContentHandler()->makeEmptyContent(); @@ -3403,7 +3359,7 @@ HTML */ protected function showHeaderCopyrightWarning() { $msg = 'editpage-head-copy-warn'; - if ( !wfMessage( $msg )->isDisabled() ) { + if ( !$this->context->msg( $msg )->isDisabled() ) { global $wgOut; $wgOut->wrapWikiMsg( "
\n$1\n
", 'editpage-head-copy-warn' ); @@ -3421,7 +3377,7 @@ HTML protected function showTosSummary() { $msg = 'editpage-tos-summary'; Hooks::run( 'EditPageTosSummary', [ $this->mTitle, &$msg ] ); - if ( !wfMessage( $msg )->isDisabled() ) { + if ( !$this->context->msg( $msg )->isDisabled() ) { global $wgOut; $wgOut->addHTML( '
' ); $wgOut->addWikiMsg( $msg ); @@ -3432,7 +3388,7 @@ HTML protected function showEditTools() { global $wgOut; $wgOut->addHTML( '
' . - wfMessage( 'edittools' )->inContentLanguage()->parse() . + $this->context->msg( 'edittools' )->inContentLanguage()->parse() . '
' ); } @@ -3453,7 +3409,7 @@ HTML * @param string $format Output format, valid values are any function of a Message object * @return string */ - public static function getCopyrightWarning( $title, $format = 'plain' ) { + public static function getCopyrightWarning( $title, $format = 'plain', $langcode = null ) { global $wgRightsText; if ( $wgRightsText ) { $copywarnMsg = [ 'copyrightwarning', @@ -3466,8 +3422,12 @@ HTML // Allow for site and per-namespace customization of contribution/copyright notice. Hooks::run( 'EditPageCopyrightWarning', [ $title, &$copywarnMsg ] ); + $msg = call_user_func_array( 'wfMessage', $copywarnMsg )->title( $title ); + if ( $langcode ) { + $msg->inLanguage( $langcode ); + } return "
\n" . - call_user_func_array( 'wfMessage', $copywarnMsg )->$format() . "\n
"; + $msg->$format() . "\n
"; } /** @@ -3482,12 +3442,41 @@ HTML return ''; } - return ResourceLoader::makeInlineScript( - ResourceLoader::makeConfigSetScript( - [ 'wgPageParseReport' => $output->getLimitReportData() ], - true - ) + $limitReport = Html::rawElement( 'div', [ 'class' => 'mw-limitReportExplanation' ], + wfMessage( 'limitreport-title' )->parseAsBlock() ); + + // Show/hide animation doesn't work correctly on a table, so wrap it in a div. + $limitReport .= Html::openElement( 'div', [ 'class' => 'preview-limit-report-wrapper' ] ); + + $limitReport .= Html::openElement( 'table', [ + 'class' => 'preview-limit-report wikitable' + ] ) . + Html::openElement( 'tbody' ); + + foreach ( $output->getLimitReportData() as $key => $value ) { + if ( Hooks::run( 'ParserLimitReportFormat', + [ $key, &$value, &$limitReport, true, true ] + ) ) { + $keyMsg = wfMessage( $key ); + $valueMsg = wfMessage( [ "$key-value-html", "$key-value" ] ); + if ( !$valueMsg->exists() ) { + $valueMsg = new RawMessage( '$1' ); + } + if ( !$keyMsg->isDisabled() && !$valueMsg->isDisabled() ) { + $limitReport .= Html::openElement( 'tr' ) . + Html::rawElement( 'th', null, $keyMsg->parse() ) . + Html::rawElement( 'td', null, $valueMsg->params( $value )->parse() ) . + Html::closeElement( 'tr' ); + } + } + } + + $limitReport .= Html::closeElement( 'tbody' ) . + Html::closeElement( 'table' ) . + Html::closeElement( 'div' ); + + return $limitReport; } protected function showStandardInputs( &$tabindex = 2 ) { @@ -3514,19 +3503,19 @@ HTML if ( $cancel !== '' ) { $cancel .= Html::element( 'span', [ 'class' => 'mw-editButtons-pipe-separator' ], - wfMessage( 'pipe-separator' )->text() ); + $this->context->msg( 'pipe-separator' )->text() ); } - $message = wfMessage( 'edithelppage' )->inContentLanguage()->text(); + $message = $this->context->msg( 'edithelppage' )->inContentLanguage()->text(); $edithelpurl = Skin::makeInternalOrExternalUrl( $message ); $attrs = [ 'target' => 'helpwindow', 'href' => $edithelpurl, ]; - $edithelp = Html::linkButton( wfMessage( 'edithelp' )->text(), + $edithelp = Html::linkButton( $this->context->msg( 'edithelp' )->text(), $attrs, [ 'mw-ui-quiet' ] ) . - wfMessage( 'word-separator' )->escaped() . - wfMessage( 'newwindow' )->parse(); + $this->context->msg( 'word-separator' )->escaped() . + $this->context->msg( 'newwindow' )->parse(); $wgOut->addHTML( " {$cancel}\n" ); $wgOut->addHTML( " {$edithelp}\n" ); @@ -3564,8 +3553,8 @@ HTML $de = $handler->createDifferenceEngine( $this->mArticle->getContext() ); $de->setContent( $content2, $content1 ); $de->showDiff( - wfMessage( 'yourtext' )->parse(), - wfMessage( 'storedversion' )->text() + $this->context->msg( 'yourtext' )->parse(), + $this->context->msg( 'storedversion' )->text() ); $wgOut->wrapWikiMsg( '

$1

', "yourtext" ); @@ -3587,7 +3576,7 @@ HTML return Linker::linkKnown( $this->getContextTitle(), - wfMessage( 'cancel' )->parse(), + $this->context->msg( 'cancel' )->parse(), Html::buttonAttributes( $attrs, [ 'mw-ui-quiet' ] ), $cancelParams ); @@ -3664,11 +3653,11 @@ HTML // Quick paranoid permission checks... if ( is_object( $data ) ) { if ( $data->log_deleted & LogPage::DELETED_USER ) { - $data->user_name = wfMessage( 'rev-deleted-user' )->escaped(); + $data->user_name = $this->context->msg( 'rev-deleted-user' )->escaped(); } if ( $data->log_deleted & LogPage::DELETED_COMMENT ) { - $data->log_comment = wfMessage( 'rev-deleted-comment' )->escaped(); + $data->log_comment = $this->context->msg( 'rev-deleted-comment' )->escaped(); } } @@ -3695,7 +3684,8 @@ HTML // string, which happens when you initially edit // a category page, due to automatic preview-on-open. $parsedNote = $wgOut->parse( "
" . - wfMessage( 'session_fail_preview_html' )->text() . "
", true, /* interface */true ); + $this->context->msg( 'session_fail_preview_html' )->text() . "", + true, /* interface */true ); } $stats->increment( 'edit.failures.session_loss' ); return $parsedNote; @@ -3717,22 +3707,22 @@ HTML # provide a anchor link to the editform $continueEditing = '' . '[[#' . self::EDITFORM_ID . '|' . $wgLang->getArrow() . ' ' . - wfMessage( 'continue-editing' )->text() . ']]'; + $this->context->msg( 'continue-editing' )->text() . ']]'; if ( $this->mTriedSave && !$this->mTokenOk ) { if ( $this->mTokenOkExceptSuffix ) { - $note = wfMessage( 'token_suffix_mismatch' )->plain(); + $note = $this->context->msg( 'token_suffix_mismatch' )->plain(); $stats->increment( 'edit.failures.bad_token' ); } else { - $note = wfMessage( 'session_fail_preview' )->plain(); + $note = $this->context->msg( 'session_fail_preview' )->plain(); $stats->increment( 'edit.failures.session_loss' ); } } elseif ( $this->incompleteForm ) { - $note = wfMessage( 'edit_form_incomplete' )->plain(); + $note = $this->context->msg( 'edit_form_incomplete' )->plain(); if ( $this->mTriedSave ) { $stats->increment( 'edit.failures.incomplete_form' ); } } else { - $note = wfMessage( 'previewnote' )->plain() . ' ' . $continueEditing; + $note = $this->context->msg( 'previewnote' )->plain() . ' ' . $continueEditing; } # don't parse non-wikitext pages, show message about preview @@ -3763,7 +3753,7 @@ HTML # Messages: usercsspreview, userjspreview, sitecsspreview, sitejspreview if ( $level && $format ) { $note = "
" . - wfMessage( "{$level}{$format}preview" )->text() . + $this->context->msg( "{$level}{$format}preview" )->text() . ' ' . $continueEditing . "
"; } } @@ -3775,7 +3765,7 @@ HTML } $hook_args = [ $this, &$content ]; - ContentHandler::runLegacyHooks( 'EditPageGetPreviewText', $hook_args ); + ContentHandler::runLegacyHooks( 'EditPageGetPreviewText', $hook_args, '1.25' ); Hooks::run( 'EditPageGetPreviewContent', $hook_args ); $parserResult = $this->doPreviewParse( $content ); @@ -3789,7 +3779,7 @@ HTML } } catch ( MWContentSerializationException $ex ) { - $m = wfMessage( + $m = $this->context->msg( 'content-failed-to-parse', $this->contentModel, $this->contentFormat, @@ -3801,13 +3791,13 @@ HTML if ( $this->isConflict ) { $conflict = '

' - . wfMessage( 'previewconflict' )->escaped() . "

\n"; + . $this->context->msg( 'previewconflict' )->escaped() . "\n"; } else { $conflict = '
'; } $previewhead = "
\n" . - '

' . wfMessage( 'preview' )->escaped() . "

" . + '

' . $this->context->msg( 'preview' )->escaped() . "

" . $wgOut->parse( $note, true, /* interface */true ) . $conflict . "
\n"; $pageViewLang = $this->mTitle->getPageViewLanguage(); @@ -4027,11 +4017,11 @@ HTML // don't show the minor edit checkbox if it's a new page or section if ( !$this->isNew ) { $checkboxes['minor'] = ''; - $minorLabel = wfMessage( 'minoredit' )->parse(); + $minorLabel = $this->context->msg( 'minoredit' )->parse(); if ( $wgUser->isAllowed( 'minoredit' ) ) { $attribs = [ 'tabindex' => ++$tabindex, - 'accesskey' => wfMessage( 'accesskey-minoredit' )->text(), + 'accesskey' => $this->context->msg( 'accesskey-minoredit' )->text(), 'id' => 'wpMinoredit', ]; $minorEditHtml = @@ -4050,12 +4040,12 @@ HTML } } - $watchLabel = wfMessage( 'watchthis' )->parse(); + $watchLabel = $this->context->msg( 'watchthis' )->parse(); $checkboxes['watch'] = ''; if ( $wgUser->isLoggedIn() ) { $attribs = [ 'tabindex' => ++$tabindex, - 'accesskey' => wfMessage( 'accesskey-watch' )->text(), + 'accesskey' => $this->context->msg( 'accesskey-watch' )->text(), 'id' => 'wpWatchthis', ]; $watchThisHtml = @@ -4095,13 +4085,13 @@ HTML } else { $buttonLabelKey = !$this->mTitle->exists() ? 'savearticle' : 'savechanges'; } - $buttonLabel = wfMessage( $buttonLabelKey )->text(); + $buttonLabel = $this->context->msg( $buttonLabelKey )->text(); $attribs = [ 'id' => 'wpSave', 'name' => 'wpSave', 'tabindex' => ++$tabindex, ] + Linker::tooltipAndAccesskeyAttribs( 'save' ); - $buttons['save'] = Html::submitButton( $buttonLabel, $attribs, [ 'mw-ui-constructive' ] ); + $buttons['save'] = Html::submitButton( $buttonLabel, $attribs, [ 'mw-ui-progressive' ] ); ++$tabindex; // use the same for preview and live preview $attribs = [ @@ -4109,7 +4099,7 @@ HTML 'name' => 'wpPreview', 'tabindex' => $tabindex, ] + Linker::tooltipAndAccesskeyAttribs( 'preview' ); - $buttons['preview'] = Html::submitButton( wfMessage( 'showpreview' )->text(), + $buttons['preview'] = Html::submitButton( $this->context->msg( 'showpreview' )->text(), $attribs ); $buttons['live'] = ''; @@ -4118,7 +4108,7 @@ HTML 'name' => 'wpDiff', 'tabindex' => ++$tabindex, ] + Linker::tooltipAndAccesskeyAttribs( 'diff' ); - $buttons['diff'] = Html::submitButton( wfMessage( 'showdiff' )->text(), + $buttons['diff'] = Html::submitButton( $this->context->msg( 'showdiff' )->text(), $attribs ); Hooks::run( 'EditPageBeforeEditButtons', [ &$this, &$buttons, &$tabindex ] ); @@ -4132,9 +4122,9 @@ HTML function noSuchSectionPage() { global $wgOut; - $wgOut->prepareErrorPage( wfMessage( 'nosuchsectiontitle' ) ); + $wgOut->prepareErrorPage( $this->context->msg( 'nosuchsectiontitle' ) ); - $res = wfMessage( 'nosuchsectiontext', $this->section )->parseAsBlock(); + $res = $this->context->msg( 'nosuchsectiontext', $this->section )->parseAsBlock(); Hooks::run( 'EditPageNoSuchSection', [ &$this, &$res ] ); $wgOut->addHTML( $res ); @@ -4153,7 +4143,7 @@ HTML if ( is_array( $match ) ) { $match = $wgLang->listToText( $match ); } - $wgOut->prepareErrorPage( wfMessage( 'spamprotectiontitle' ) ); + $wgOut->prepareErrorPage( $this->context->msg( 'spamprotectiontitle' ) ); $wgOut->addHTML( '
' ); $wgOut->addWikiMsg( 'spamprotectiontext' ); @@ -4219,7 +4209,7 @@ HTML protected function safeUnicodeOutput( $text ) { return $this->checkUnicodeCompliantBrowser() ? $text - : $this->makesafe( $text ); + : $this->makeSafe( $text ); } /** @@ -4304,4 +4294,177 @@ HTML // reverse the transform that we made for reversibility reasons. return strtr( $result, [ "�" => "&#x" ] ); } + + /** + * @since 1.29 + */ + protected function addEditNotices() { + global $wgOut; + + $editNotices = $this->mTitle->getEditNotices( $this->oldid ); + if ( count( $editNotices ) ) { + $wgOut->addHTML( implode( "\n", $editNotices ) ); + } else { + $msg = $this->context->msg( 'editnotice-notext' ); + if ( !$msg->isDisabled() ) { + $wgOut->addHTML( + '
' + . $msg->parseAsBlock() + . '
' + ); + } + } + } + + /** + * @since 1.29 + */ + protected function addTalkPageText() { + global $wgOut; + + if ( $this->mTitle->isTalkPage() ) { + $wgOut->addWikiMsg( 'talkpagetext' ); + } + } + + /** + * @since 1.29 + */ + protected function addLongPageWarningHeader() { + global $wgMaxArticleSize, $wgOut, $wgLang; + + if ( $this->contentLength === false ) { + $this->contentLength = strlen( $this->textbox1 ); + } + + if ( $this->tooBig || $this->contentLength > $wgMaxArticleSize * 1024 ) { + $wgOut->wrapWikiMsg( "
\n$1\n
", + [ + 'longpageerror', + $wgLang->formatNum( round( $this->contentLength / 1024, 3 ) ), + $wgLang->formatNum( $wgMaxArticleSize ) + ] + ); + } else { + if ( !$this->context->msg( 'longpage-hint' )->isDisabled() ) { + $wgOut->wrapWikiMsg( "
\n$1\n
", + [ + 'longpage-hint', + $wgLang->formatSize( strlen( $this->textbox1 ) ), + strlen( $this->textbox1 ) + ] + ); + } + } + } + + /** + * @since 1.29 + */ + protected function addPageProtectionWarningHeaders() { + global $wgOut; + + if ( $this->mTitle->isProtected( 'edit' ) && + MWNamespace::getRestrictionLevels( $this->mTitle->getNamespace() ) !== [ '' ] + ) { + # Is the title semi-protected? + if ( $this->mTitle->isSemiProtected() ) { + $noticeMsg = 'semiprotectedpagewarning'; + } else { + # Then it must be protected based on static groups (regular) + $noticeMsg = 'protectedpagewarning'; + } + LogEventsList::showLogExtract( $wgOut, 'protect', $this->mTitle, '', + [ 'lim' => 1, 'msgKey' => [ $noticeMsg ] ] ); + } + if ( $this->mTitle->isCascadeProtected() ) { + # Is this page under cascading protection from some source pages? + /** @var Title[] $cascadeSources */ + list( $cascadeSources, /* $restrictions */ ) = $this->mTitle->getCascadeProtectionSources(); + $notice = "
\n$1\n"; + $cascadeSourcesCount = count( $cascadeSources ); + if ( $cascadeSourcesCount > 0 ) { + # Explain, and list the titles responsible + foreach ( $cascadeSources as $page ) { + $notice .= '* [[:' . $page->getPrefixedText() . "]]\n"; + } + } + $notice .= '
'; + $wgOut->wrapWikiMsg( $notice, [ 'cascadeprotectedwarning', $cascadeSourcesCount ] ); + } + if ( !$this->mTitle->exists() && $this->mTitle->getRestrictions( 'create' ) ) { + LogEventsList::showLogExtract( $wgOut, 'protect', $this->mTitle, '', + [ 'lim' => 1, + 'showIfEmpty' => false, + 'msgKey' => [ 'titleprotectedwarning' ], + 'wrap' => "
\n$1
" ] ); + } + } + + /** + * @param OutputPage $out + * @since 1.29 + */ + protected function addExplainConflictHeader( OutputPage $out ) { + $out->wrapWikiMsg( "
\n$1\n
", 'explainconflict' ); + } + + /** + * @param string $name + * @param mixed[] $customAttribs + * @param User $user + * @return mixed[] + * @since 1.29 + */ + protected function buildTextboxAttribs( $name, array $customAttribs, User $user ) { + $attribs = $customAttribs + [ + 'accesskey' => ',', + 'id' => $name, + 'cols' => $user->getIntOption( 'cols' ), + 'rows' => $user->getIntOption( 'rows' ), + // Avoid PHP notices when appending preferences + // (appending allows customAttribs['style'] to still work). + 'style' => '' + ]; + + // The following classes can be used here: + // * mw-editfont-default + // * mw-editfont-monospace + // * mw-editfont-sans-serif + // * mw-editfont-serif + $class = 'mw-editfont-' . $user->getOption( 'editfont' ); + + if ( isset( $attribs['class'] ) ) { + if ( is_string( $attribs['class'] ) ) { + $attribs['class'] .= ' ' . $class; + } elseif ( is_array( $attribs['class'] ) ) { + $attribs['class'][] = $class; + } + } else { + $attribs['class'] = $class; + } + + $pageLang = $this->mTitle->getPageLanguage(); + $attribs['lang'] = $pageLang->getHtmlCode(); + $attribs['dir'] = $pageLang->getDir(); + + return $attribs; + } + + /** + * @param string $wikitext + * @return string + * @since 1.29 + */ + protected function addNewLineAtEnd( $wikitext ) { + if ( strval( $wikitext ) !== '' ) { + // Ensure there's a newline at the end, otherwise adding lines + // is awkward. + // But don't add a newline if the text is empty, or Firefox in XHTML + // mode will show an extra newline. A bit annoying. + $wikitext .= "\n"; + return $wikitext; + } + return $wikitext; + } }