/** @var string */
public $edittime = '';
- /** @var integer */
+ /** @var int */
private $editRevId = null;
/** @var string */
*/
private $isOldRev = false;
- /**
- * @var bool Whether OOUI should be enabled here
- */
- private $oouiEnabled = false;
-
/**
* @param Article $article
*/
$handler = ContentHandler::getForModelID( $this->contentModel );
$this->contentFormat = $handler->getDefaultFormat();
-
- $this->oouiEnabled = $this->context->getConfig()->get( 'OOUIEditPage' );
}
/**
/**
* Check if the edit page is using OOUI controls
- * @return bool
+ * @return bool Always true
+ * @deprecated since 1.30
*/
public function isOouiEnabled() {
- return $this->oouiEnabled;
+ return true;
}
/**
/**
* This function collects the form data and uses it to populate various member variables.
- * @param WebRequest $request
+ * @param WebRequest &$request
* @throws ErrorPageError
*/
public function importFormData( &$request ) {
global $wgContLang, $wgUser;
- # Allow users to change the mode for testing
- $this->oouiEnabled = $request->getFuzzyBool( 'ooui', $this->oouiEnabled );
-
# Section edit can come from either the form or a link
$this->section = $request->getVal( 'wpSection', $request->getVal( 'section' ) );
* this method should be overridden and return the page text that will be used
* for saving, preview parsing and so on...
*
- * @param WebRequest $request
+ * @param WebRequest &$request
* @return string|null
*/
protected function importContentFormData( &$request ) {
/**
* Make sure the form isn't faking a user's credentials.
*
- * @param WebRequest $request
+ * @param WebRequest &$request
* @return bool
* @private
*/
/**
* Attempt submission
- * @param array|bool $resultDetails See docs for $result in internalAttemptSave
+ * @param array|bool &$resultDetails See docs for $result in internalAttemptSave
* @throws UserBlockedError|ReadOnlyError|ThrottledError|PermissionsError
* @return Status The resulting status object.
*/
global $wgParser;
if ( $this->sectiontitle !== '' ) {
- $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->sectiontitle );
+ $sectionanchor = $this->guessSectionName( $this->sectiontitle );
// If no edit summary was specified, create one automatically from the section
// title and have it link to the new section. Otherwise, respect the summary as
// passed.
->rawParams( $cleanSectionTitle )->inContentLanguage()->text();
}
} elseif ( $this->summary !== '' ) {
- $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $this->summary );
+ $sectionanchor = $this->guessSectionName( $this->summary );
# This is a new section, so create a link to the new section
# in the revision summary.
$cleanSummary = $wgParser->stripSectionName( $this->summary );
/**
* Attempt submission (no UI)
*
- * @param array $result Array to add statuses to, currently with the
+ * @param array &$result Array to add statuses to, currently with the
* possible keys:
* - spam (string): Spam string from content if any spam is detected by
* matchSpamRegex.
* - sectionanchor (string): Section anchor for a section save.
- * - nullEdit (boolean): Set if doEditContent is OK. True if null edit,
+ * - nullEdit (bool): Set if doEditContent is OK. True if null edit,
* false otherwise.
* - redirect (bool): Set if doEditContent is OK. True if resulting
* revision is a redirect.
* time.
*/
public function internalAttemptSave( &$result, $bot = false ) {
- global $wgUser, $wgRequest, $wgParser, $wgMaxArticleSize;
+ global $wgUser, $wgRequest, $wgMaxArticleSize;
global $wgContentHandlerUseDB;
$status = Status::newGood();
# We can't deal with anchors, includes, html etc in the header for now,
# headline would need to be parsed to improve this.
if ( $hasmatch && strlen( $matches[2] ) > 0 ) {
- $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText( $matches[2] );
+ $sectionanchor = $this->guessSectionName( $matches[2] );
}
}
$result['sectionanchor'] = $sectionanchor;
$wgOut->addHTML( Html::openElement(
'form',
[
- 'class' => $this->oouiEnabled ? 'mw-editform-ooui' : 'mw-editform-legacy',
+ // Keep mw-editform-ooui class for backwards-compatibility temporarily
+ 'class' => 'mw-editform mw-editform-ooui',
'id' => self::EDITFORM_ID,
'name' => self::EDITFORM_ID,
'method' => 'post',
$wgOut->addHTML( Html::hidden( 'format', $this->contentFormat ) );
$wgOut->addHTML( Html::hidden( 'model', $this->contentModel ) );
- // Preserve &ooui=1 / &ooui=0 from URL parameters after submitting the page for preview
- $wgOut->addHTML( Html::hidden( 'ooui', $this->oouiEnabled ? '1' : '0' ) );
-
- // following functions will need OOUI, enable it only once; here.
- if ( $this->oouiEnabled ) {
- $wgOut->enableOOUI();
- }
+ $wgOut->enableOOUI();
if ( $this->section == 'new' ) {
$this->showSummaryInput( true, $this->summary );
}
/**
- * Standard summary input and label (wgSummary), abstracted so 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 [ '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 [ $label, $input ]
- */
- public function getSummaryInput( $summary = "", $labelText = null,
- $inputAttrs = null, $spanLabelAttrs = null
- ) {
- $inputAttrs = $this->getSummaryInputAttributes( $inputAttrs );
- $inputAttrs += Linker::tooltipAndAccesskeyAttribs( 'summary' );
-
- $spanLabelAttrs = ( is_array( $spanLabelAttrs ) ? $spanLabelAttrs : [] ) + [
- 'class' => $this->missingSummary ? 'mw-summarymissed' : 'mw-summary',
- 'id' => "wpSummaryLabel"
- ];
-
- $label = null;
- if ( $labelText ) {
- $label = Xml::tags(
- 'label',
- $inputAttrs['id'] ? [ 'for' => $inputAttrs['id'] ] : null,
- $labelText
- );
- $label = Xml::tags( 'span', $spanLabelAttrs, $label );
- }
-
- $input = Html::input( 'wpSummary', $summary, 'text', $inputAttrs );
-
- return [ $label, $input ];
- }
-
- /**
- * Same as self::getSummaryInput, but uses OOUI, instead of plain HTML.
* Builds a standard summary input with a label.
*
* @param string $summary The value of the summary input
}
$labelText = $this->context->msg( $isSubjectPreview ? 'subject' : 'summary' )->parse();
- if ( $this->oouiEnabled ) {
- $wgOut->addHTML( $this->getSummaryInputOOUI(
+ $wgOut->addHTML( $this->getSummaryInputOOUI(
$summary,
$labelText,
[ 'class' => $summaryClass ]
) );
- } else {
- list( $label, $input ) = $this->getSummaryInput(
- $summary,
- $labelText,
- [ 'class' => $summaryClass ]
- );
- $wgOut->addHTML( "{$label} {$input}" );
- }
}
/**
protected function showFormBeforeText() {
global $wgOut;
- $section = htmlspecialchars( $this->section );
- $wgOut->addHTML( <<<HTML
-<input type='hidden' value="{$section}" name="wpSection"/>
-<input type='hidden' value="{$this->starttime}" name="wpStarttime" />
-<input type='hidden' value="{$this->edittime}" name="wpEdittime" />
-<input type='hidden' value="{$this->editRevId}" name="editRevId" />
-<input type='hidden' value="{$this->scrolltop}" name="wpScrolltop" id="wpScrolltop" />
-
-HTML
- );
+
+ $wgOut->addHTML( Html::hidden( 'wpSection', htmlspecialchars( $this->section ) ) );
+ $wgOut->addHTML( Html::hidden( 'wpStarttime', $this->starttime ) );
+ $wgOut->addHTML( Html::hidden( 'wpEdittime', $this->edittime ) );
+ $wgOut->addHTML( Html::hidden( 'editRevId', $this->editRevId ) );
+ $wgOut->addHTML( Html::hidden( 'wpScrolltop', $this->scrolltop ) );
+
if ( !$this->checkUnicodeCompliantBrowser() ) {
$wgOut->addHTML( Html::hidden( 'safemode', '1' ) );
}
}
/**
- * Inserts optional text shown below edit and upload forms. Can be used to offer special characters not present on
- * most keyboards for copying/pasting.
+ * Inserts optional text shown below edit and upload forms. Can be used to offer special
+ * characters not present on most keyboards for copying/pasting.
*/
protected function showEditTools() {
global $wgOut;
$wgOut->addHTML( $this->getSummaryPreview( false, $this->summary ) );
}
- if ( $this->oouiEnabled ) {
- $checkboxes = $this->getCheckboxesOOUI(
- $tabindex,
- [ 'minor' => $this->minoredit, 'watch' => $this->watchthis ]
- );
- $checkboxesHTML = new OOUI\HorizontalLayout( [ 'items' => $checkboxes ] );
- } else {
- $checkboxes = $this->getCheckboxes(
- $tabindex,
- [ 'minor' => $this->minoredit, 'watch' => $this->watchthis ]
- );
- $checkboxesHTML = implode( $checkboxes, "\n" );
- }
+ $checkboxes = $this->getCheckboxesOOUI(
+ $tabindex,
+ [ 'minor' => $this->minoredit, 'watch' => $this->watchthis ]
+ );
+ $checkboxesHTML = new OOUI\HorizontalLayout( [ 'items' => $checkboxes ] );
$wgOut->addHTML( "<div class='editCheckboxes'>" . $checkboxesHTML . "</div>\n" );
} elseif ( $this->getContextTitle()->isRedirect() ) {
$cancelParams['redirect'] = 'no';
}
- if ( $this->oouiEnabled ) {
- return new OOUI\ButtonWidget( [
- 'id' => 'mw-editform-cancel',
- 'href' => $this->getContextTitle()->getLinkUrl( $cancelParams ),
- 'label' => new OOUI\HtmlSnippet( $this->context->msg( 'cancel' )->parse() ),
- 'framed' => false,
- 'infusable' => true,
- 'flags' => 'destructive',
- ] );
- } else {
- return MediaWikiServices::getInstance()->getLinkRenderer()->makeKnownLink(
- $this->getContextTitle(),
- new HtmlArmor( $this->context->msg( 'cancel' )->parse() ),
- Html::buttonAttributes( [ 'id' => 'mw-editform-cancel' ], [ 'mw-ui-quiet' ] ),
- $cancelParams
- );
- }
+
+ return new OOUI\ButtonWidget( [
+ 'id' => 'mw-editform-cancel',
+ 'href' => $this->getContextTitle()->getLinkUrl( $cancelParams ),
+ 'label' => new OOUI\HtmlSnippet( $this->context->msg( 'cancel' )->parse() ),
+ 'framed' => false,
+ 'infusable' => true,
+ 'flags' => 'destructive',
+ ] );
}
/**
* Returns an array of html code of the following checkboxes old style:
* minor and watch
*
- * @param int $tabindex Current tabindex
+ * @param int &$tabindex Current tabindex
* @param array $checked See getCheckboxesDefinition()
* @return array
*/
* Returns an array of html code of the following checkboxes:
* minor and watch
*
- * @param int $tabindex Current tabindex
+ * @param int &$tabindex Current tabindex
* @param array $checked Array of checkbox => bool, where bool indicates the checked
* status of the checkbox
*
$newPage = !$this->mTitle->exists();
if ( $labelAsPublish ) {
- $buttonLabelKey = $newPage ? 'publishpage' : 'publishchanges';
+ $buttonLabelKey = $newPage ? 'publishpage' : 'publishchanges';
} else {
$buttonLabelKey = $newPage ? 'savearticle' : 'savechanges';
}
* Returns an array of html code of the following buttons:
* save, diff and preview
*
- * @param int $tabindex Current tabindex
+ * @param int &$tabindex Current tabindex
*
* @return array
*/
'name' => 'wpSave',
'tabindex' => ++$tabindex,
];
- if ( $this->oouiEnabled ) {
- $saveConfig = OOUI\Element::configFromHtmlAttributes( $attribs );
- $buttons['save'] = new OOUI\ButtonInputWidget( [
- 'id' => 'wpSaveWidget',
- 'inputId' => 'wpSave',
- // Support: IE 6 – Use <input>, otherwise it can't distinguish which button was clicked
- 'useInputTag' => true,
- 'flags' => [ 'constructive', 'primary' ],
- 'label' => $buttonLabel,
- 'infusable' => true,
- 'type' => 'submit',
- 'title' => Linker::titleAttrib( 'save' ),
- 'accessKey' => Linker::accesskey( 'save' ),
- ] + $saveConfig );
- } else {
- $buttons['save'] = Html::submitButton(
- $buttonLabel,
- $attribs + Linker::tooltipAndAccesskeyAttribs( 'save' ) + [ 'id' => 'wpSave' ],
- [ 'mw-ui-progressive' ]
- );
- }
+
+ $saveConfig = OOUI\Element::configFromHtmlAttributes( $attribs );
+ $buttons['save'] = new OOUI\ButtonInputWidget( [
+ 'id' => 'wpSaveWidget',
+ 'inputId' => 'wpSave',
+ // Support: IE 6 – Use <input>, otherwise it can't distinguish which button was clicked
+ 'useInputTag' => true,
+ 'flags' => [ 'constructive', 'primary' ],
+ 'label' => $buttonLabel,
+ 'infusable' => true,
+ 'type' => 'submit',
+ 'title' => Linker::titleAttrib( 'save' ),
+ 'accessKey' => Linker::accesskey( 'save' ),
+ ] + $saveConfig );
$attribs = [
'name' => 'wpPreview',
'tabindex' => ++$tabindex,
];
- if ( $this->oouiEnabled ) {
- $previewConfig = OOUI\Element::configFromHtmlAttributes( $attribs );
- $buttons['preview'] = new OOUI\ButtonInputWidget( [
- 'id' => 'wpPreviewWidget',
- 'inputId' => 'wpPreview',
- // Support: IE 6 – Use <input>, otherwise it can't distinguish which button was clicked
- 'useInputTag' => true,
- 'label' => $this->context->msg( 'showpreview' )->text(),
- 'infusable' => true,
- 'type' => 'submit',
- 'title' => Linker::titleAttrib( 'preview' ),
- 'accessKey' => Linker::accesskey( 'preview' ),
- ] + $previewConfig );
- } else {
- $buttons['preview'] = Html::submitButton(
- $this->context->msg( 'showpreview' )->text(),
- $attribs + Linker::tooltipAndAccesskeyAttribs( 'preview' ) + [ 'id' => 'wpPreview' ]
- );
- }
+
+ $previewConfig = OOUI\Element::configFromHtmlAttributes( $attribs );
+ $buttons['preview'] = new OOUI\ButtonInputWidget( [
+ 'id' => 'wpPreviewWidget',
+ 'inputId' => 'wpPreview',
+ // Support: IE 6 – Use <input>, otherwise it can't distinguish which button was clicked
+ 'useInputTag' => true,
+ 'label' => $this->context->msg( 'showpreview' )->text(),
+ 'infusable' => true,
+ 'type' => 'submit',
+ 'title' => Linker::titleAttrib( 'preview' ),
+ 'accessKey' => Linker::accesskey( 'preview' ),
+ ] + $previewConfig );
+
$attribs = [
'name' => 'wpDiff',
'tabindex' => ++$tabindex,
];
- if ( $this->oouiEnabled ) {
- $diffConfig = OOUI\Element::configFromHtmlAttributes( $attribs );
- $buttons['diff'] = new OOUI\ButtonInputWidget( [
- 'id' => 'wpDiffWidget',
- 'inputId' => 'wpDiff',
- // Support: IE 6 – Use <input>, otherwise it can't distinguish which button was clicked
- 'useInputTag' => true,
- 'label' => $this->context->msg( 'showdiff' )->text(),
- 'infusable' => true,
- 'type' => 'submit',
- 'title' => Linker::titleAttrib( 'diff' ),
- 'accessKey' => Linker::accesskey( 'diff' ),
- ] + $diffConfig );
- } else {
- $buttons['diff'] = Html::submitButton(
- $this->context->msg( 'showdiff' )->text(),
- $attribs + Linker::tooltipAndAccesskeyAttribs( 'diff' ) + [ 'id' => 'wpDiff' ]
- );
- }
+
+ $diffConfig = OOUI\Element::configFromHtmlAttributes( $attribs );
+ $buttons['diff'] = new OOUI\ButtonInputWidget( [
+ 'id' => 'wpDiffWidget',
+ 'inputId' => 'wpDiff',
+ // Support: IE 6 – Use <input>, otherwise it can't distinguish which button was clicked
+ 'useInputTag' => true,
+ 'label' => $this->context->msg( 'showdiff' )->text(),
+ 'infusable' => true,
+ 'type' => 'submit',
+ 'title' => Linker::titleAttrib( 'diff' ),
+ 'accessKey' => Linker::accesskey( 'diff' ),
+ ] + $diffConfig );
// Avoid PHP 7.1 warning of passing $this by reference
$editPage = $this;
}
return $wikitext;
}
+
+ /**
+ * Turns section name wikitext into anchors for use in HTTP redirects. Various
+ * versions of Microsoft browsers misinterpret fragment encoding of Location: headers
+ * resulting in mojibake in address bar. Redirect them to legacy section IDs,
+ * if possible. All the other browsers get HTML5 if the wiki is configured for it, to
+ * spread the new style links more efficiently.
+ *
+ * @param string $text
+ * @return string
+ */
+ private function guessSectionName( $text ) {
+ global $wgParser;
+
+ // Detect Microsoft browsers
+ $userAgent = $this->context->getRequest()->getHeader( 'User-Agent' );
+ if ( $userAgent && preg_match( '/MSIE|Edge/', $userAgent ) ) {
+ // ...and redirect them to legacy encoding, if available
+ return $wgParser->guessLegacySectionNameFromWikiText( $text );
+ }
+ // Meanwhile, real browsers get real anchors
+ return $wgParser->guessSectionNameFromWikiText( $text );
+ }
}