enabled by setting $wgUsePigLatinVariant to true.
* Added RecentChangesPurgeRows hook to allow extensions to purge data that
depends on the recentchanges table.
+* Added JS config values wgDiffOldId/wgDiffNewId to the output of diff pages.
=== Languages updated in 1.30 ===
*/
$wgExternalDiffEngine = false;
+/**
+ * wikidiff2 supports detection of changes in moved paragraphs.
+ * This setting controls the maximum number of paragraphs to compare before it bails out.
+ * Supported values:
+ * * 0: detection of moved paragraphs is disabled
+ * * int > 0: maximum number of paragraphs to compare
+ * Note: number of paragraph comparisons is in O(n^2).
+ * This setting is only effective if the wikidiff2 PHP/HHVM module is used as diffengine.
+ * See $wgExternalDiffEngine.
+ *
+ * @since 1.30
+ */
+$wgWikiDiff2MovedParagraphDetectionCutoff = 0;
+
/**
* Disable redirects to special pages and interwiki redirects, which use a 302
* and have no "redirected from" link.
* @param Article $article
*/
public function __construct( Article $article ) {
- global $wgOOUIEditPage;
-
$this->mArticle = $article;
$this->page = $article->getPage(); // model object
$this->mTitle = $article->getTitle();
$handler = ContentHandler::getForModelID( $this->contentModel );
$this->contentFormat = $handler->getDefaultFormat();
- $this->oouiEnabled = $wgOOUIEditPage;
+ $this->oouiEnabled = $this->context->getConfig()->get( 'OOUIEditPage' );
}
/**
}
}
+ $out->addJsConfigVars( [
+ 'wgDiffOldId' => $this->mOldid,
+ 'wgDiffNewId' => $this->mNewid,
+ ] );
+
# Make "next revision link"
# Skip next link on the top revision
if ( $samePage && !$this->mNewRev->isCurrent() ) {
$wgExternalDiffEngine = false;
}
+ // Better external diff engine, the 2 may some day be dropped
+ // This one does the escaping and segmenting itself
if ( function_exists( 'wikidiff2_do_diff' ) && $wgExternalDiffEngine === false ) {
- # Better external diff engine, the 2 may some day be dropped
- # This one does the escaping and segmenting itself
- $text = wikidiff2_do_diff( $otext, $ntext, 2 );
+ $wikidiff2Version = phpversion( 'wikidiff2' );
+ if (
+ $wikidiff2Version !== false &&
+ version_compare( $wikidiff2Version, '0.3.0', '>=' )
+ ) {
+ $text = wikidiff2_do_diff(
+ $otext,
+ $ntext,
+ 2,
+ $this->getConfig()->get( 'WikiDiff2MovedParagraphDetectionCutoff' )
+ );
+ } else {
+ // Don't pass the 4th parameter for compatibility with older versions of wikidiff2
+ $text = wikidiff2_do_diff(
+ $otext,
+ $ntext,
+ 2
+ );
+
+ // Log a warning in case the configuration value is set to not silently ignore it
+ if ( $this->getConfig()->get( 'WikiDiff2MovedParagraphDetectionCutoff' ) > 0 ) {
+ wfLogWarning( '$wgWikiDiff2MovedParagraphDetectionCutoff is set but has no
+ effect since the used version of WikiDiff2 does not support it.' );
+ }
+ }
+
$text .= $this->debug( 'wikidiff2' );
return $text;
return "$select<br />\n$textbox";
}
+ protected function getOOUIModules() {
+ return [ 'mediawiki.widgets.SelectWithInputWidget' ];
+ }
+
public function getInputOOUI( $value ) {
- return false;
+ $this->mParent->getOutput()->addModuleStyles( 'mediawiki.widgets.SelectWithInputWidget.styles' );
+
+ # TextInput
+ $textAttribs = [
+ 'id' => $this->mID . '-other',
+ 'name' => $this->mName . '-other',
+ 'size' => $this->getSize(),
+ 'class' => [ 'mw-htmlform-select-and-other-field' ],
+ 'data-id-select' => $this->mID,
+ 'value' => $value[2],
+ ];
+
+ $allowedParams = [
+ 'required',
+ 'autofocus',
+ 'multiple',
+ 'disabled',
+ 'tabindex',
+ 'maxlength',
+ ];
+
+ $textAttribs += OOUI\Element::configFromHtmlAttributes(
+ $this->getAttributes( $allowedParams )
+ );
+
+ if ( $this->mClass !== '' ) {
+ $textAttribs['classes'] = [ $this->mClass ];
+ }
+
+ # DropdownInput
+ $dropdownInputAttribs = [
+ 'name' => $this->mName,
+ 'id' => $this->mID,
+ 'options' => $this->getOptionsOOUI(),
+ 'value' => $value[1],
+ ];
+
+ $allowedParams = [
+ 'tabindex',
+ 'disabled',
+ ];
+
+ $dropdownInputAttribs += OOUI\Element::configFromHtmlAttributes(
+ $this->getAttributes( $allowedParams )
+ );
+
+ if ( $this->mClass !== '' ) {
+ $dropdownInputAttribs['classes'] = [ $this->mClass ];
+ }
+
+ return $this->getInputWidget( [
+ 'textinput' => $textAttribs,
+ 'dropdowninput' => $dropdownInputAttribs,
+ 'or' => false,
+ ] );
+ }
+
+ public function getInputWidget( $params ) {
+ return new Mediawiki\Widget\SelectWithInputWidget( $params );
}
/**
return "$select<br />\n$textbox";
}
+ protected function shouldInfuseOOUI() {
+ return true;
+ }
+
+ protected function getOOUIModules() {
+ return [ 'mediawiki.widgets.SelectWithInputWidget' ];
+ }
+
public function getInputOOUI( $value ) {
- return false;
+ $this->mParent->getOutput()->addModuleStyles( 'mediawiki.widgets.SelectWithInputWidget.styles' );
+
+ $valInSelect = false;
+ if ( $value !== false ) {
+ $value = strval( $value );
+ $valInSelect = in_array(
+ $value, HTMLFormField::flattenOptions( $this->getOptions() ), true
+ );
+ }
+
+ # DropdownInput
+ $dropdownAttribs = [
+ 'id' => $this->mID,
+ 'name' => $this->mName,
+ 'options' => $this->getOptionsOOUI(),
+ 'value' => $valInSelect ? $value : 'other',
+ 'class' => [ 'mw-htmlform-select-or-other' ],
+ ];
+
+ $allowedParams = [
+ 'disabled',
+ 'tabindex',
+ ];
+
+ $dropdownAttribs += OOUI\Element::configFromHtmlAttributes(
+ $this->getAttributes( $allowedParams )
+ );
+
+ # TextInput
+ $textAttribs = [
+ 'id' => $this->mID . '-other',
+ 'name' => $this->mName . '-other',
+ 'size' => $this->getSize(),
+ 'value' => $valInSelect ? '' : $value,
+ ];
+
+ $allowedParams = [
+ 'required',
+ 'autofocus',
+ 'multiple',
+ 'disabled',
+ 'tabindex',
+ 'maxlength',
+ ];
+
+ $textAttribs += OOUI\Element::configFromHtmlAttributes(
+ $this->getAttributes( $allowedParams )
+ );
+
+ if ( $this->mClass !== '' ) {
+ $textAttribs['classes'] = [ $this->mClass ];
+ }
+ if ( $this->mPlaceholder !== '' ) {
+ $textAttribs['placeholder'] = $this->mPlaceholder;
+ }
+
+ return $this->getInputWidget( [
+ 'textinput' => $textAttribs,
+ 'dropdowninput' => $dropdownAttribs,
+ 'or' => true,
+ ] );
+ }
+
+ public function getInputWidget( $params ) {
+ return new Mediawiki\Widget\SelectWithInputWidget( $params );
}
/**
"grunt-eslint": "20.0.0",
"grunt-jsonlint": "1.1.0",
"grunt-karma": "2.0.0",
- "grunt-stylelint": "0.7.0",
+ "grunt-stylelint": "0.8.0",
"grunt-webdriver": "2.0.3",
"karma": "1.5.0",
"karma-chrome-launcher": "2.0.0",
"karma-qunit": "1.0.0",
"nodemw": "0.10.1",
"qunitjs": "1.23.1",
+ "stylelint": "7.8.0",
"stylelint-config-wikimedia": "0.4.1",
"wdio-junit-reporter": "0.2.0",
"wdio-mocha-framework": "0.5.8",
/* Methods */
+ /**
+ * Get the currently focused field, if any
+ *
+ * @private
+ * @return {jQuery}
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.getFocusedField = function () {
+ return this.$fields.find( this.getElementDocument().activeElement );
+ };
+
/**
* Convert a date string to a Date
*
var delta = 0,
spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
- if ( this.isDisabled() ) {
+ if ( this.isDisabled() || !this.getFocusedField().length ) {
return;
}
* @inheritdoc
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.focus = function () {
- if ( !this.$fields.find( document.activeElement ).length ) {
+ if ( !this.getFocusedField().length ) {
this.$fields.find( '.mw-widgets-datetime-dateTimeInputWidget-editField' ).first().focus();
}
return this;
* @inheritdoc
*/
mw.widgets.datetime.DateTimeInputWidget.prototype.blur = function () {
- this.$fields.find( document.activeElement ).blur();
+ this.getFocusedField().blur();
return this;
};
* @param string $text1
* @param string $text2
* @param int $numContextLines
+ * @param int $movedParagraphDetectionCutoff
* @return string
*/
-function wikidiff2_do_diff( $text1, $text2, $numContextLines ) {
+function wikidiff2_do_diff( $text1, $text2, $numContextLines, $movedParagraphDetectionCutoff = 0 ) {
}