'editfont' => 'monospace',
'editondblclick' => 0,
'editsectiononrightclick' => 0,
+ 'email-allow-new-users' => 1,
'enotifminoredits' => 0,
'enotifrevealaddr' => 0,
'enotifusertalkpages' => 1,
$section = str_replace( '[[', '', $section );
$section = str_replace( ']]', '', $section );
- $section = Sanitizer::normalizeSectionNameWhitespace( $section ); # T24784
+ $section = substr( Parser::guessSectionNameFromStrippedText( $section ), 1 );
if ( $local ) {
- $sectionTitle = Title::newFromText( '#' . $section );
+ $sectionTitle = Title::makeTitleSafe( NS_MAIN, '', $section );
} else {
$sectionTitle = Title::makeTitleSafe( $title->getNamespace(),
- $title->getDBkey(), Sanitizer::decodeCharReferences( $section ) );
+ $title->getDBkey(), $section );
}
if ( $sectionTitle ) {
$link = Linker::makeCommentLink( $sectionTitle, $wgLang->getArrow(), $wikiId, 'noclasses' );
if ( $config->get( 'EnableUserEmail' ) && $user->isAllowed( 'sendemail' ) ) {
$defaultPreferences['disablemail'] = [
+ 'id' => 'wpAllowEmail',
'type' => 'toggle',
'invert' => true,
'section' => 'personal/email',
'label-message' => 'allowemail',
'disabled' => $disableEmailPrefs,
];
+
+ $defaultPreferences['email-allow-new-users'] = [
+ 'id' => 'wpAllowEmailFromNewUsers',
+ 'type' => 'toggle',
+ 'section' => 'personal/email',
+ 'label-message' => 'email-allow-new-users-label',
+ 'disabled' => $disableEmailPrefs,
+ ];
+
$defaultPreferences['ccmeonemails'] = [
'type' => 'toggle',
'section' => 'personal/email',
'disabled' => $disableEmailPrefs,
];
- if ( $config->get( 'EnableUserEmailBlacklist' )
- && !$disableEmailPrefs
- && !(bool)$user->getOption( 'disablemail' )
- ) {
+ if ( $config->get( 'EnableUserEmailBlacklist' ) ) {
$lookup = CentralIdLookup::factory();
$ids = $user->getOption( 'email-blacklist', [] );
$names = $ids ? $lookup->namesFromCentralIds( $ids, $user ) : [];
'label-message' => 'email-blacklist-label',
'section' => 'personal/email',
'default' => implode( "\n", $names ),
+ 'disabled' => $disableEmailPrefs,
];
}
}
public function getInputOOUI( $value ) {
$params = [ 'name' => $this->mName ];
+ if ( isset( $this->mParams['id'] ) ) {
+ $params['id'] = $this->mParams['id'];
+ }
+
+ if ( isset( $this->mParams['disabled'] ) ) {
+ $params['disabled'] = $this->mParams['disabled'];
+ }
+
if ( isset( $this->mParams['default'] ) ) {
$params['default'] = $this->mParams['default'];
}
# Decode HTML entities
$safeHeadline = Sanitizer::decodeCharReferences( $safeHeadline );
- $safeHeadline = $this->normalizeSectionName( $safeHeadline );
+ $safeHeadline = self::normalizeSectionName( $safeHeadline );
$fallbackHeadline = Sanitizer::escapeIdForAttribute( $safeHeadline, Sanitizer::ID_FALLBACK );
$linkAnchor = Sanitizer::escapeIdForLink( $safeHeadline );
return $this->mDefaultSort;
}
+ private static function getSectionNameFromStrippedText( $text ) {
+ $text = Sanitizer::normalizeSectionNameWhitespace( $text );
+ $text = Sanitizer::decodeCharReferences( $text );
+ $text = self::normalizeSectionName( $text );
+ return $text;
+ }
+
+ private static function makeAnchor( $sectionName ) {
+ return '#' . Sanitizer::escapeIdForLink( $sectionName );
+ }
+
+ private static function makeLegacyAnchor( $sectionName ) {
+ global $wgFragmentMode;
+ if ( isset( $wgFragmentMode[1] ) && $wgFragmentMode[1] === 'legacy' ) {
+ // ForAttribute() and ForLink() are the same for legacy encoding
+ $id = Sanitizer::escapeIdForAttribute( $text, Sanitizer::ID_FALLBACK );
+ } else {
+ $id = Sanitizer::escapeIdForLink( $text );
+ }
+
+ return "#$id";
+ }
+
/**
* Try to guess the section anchor name based on a wikitext fragment
* presumably extracted from a heading, for example "Header" from
* "== Header ==".
*
* @param string $text
- *
- * @return string
+ * @return string Anchor (starting with '#')
*/
public function guessSectionNameFromWikiText( $text ) {
# Strip out wikitext links(they break the anchor)
$text = $this->stripSectionName( $text );
- $text = Sanitizer::normalizeSectionNameWhitespace( $text );
- $text = Sanitizer::decodeCharReferences( $text );
- $text = $this->normalizeSectionName( $text );
-
- return '#' . Sanitizer::escapeIdForLink( $text );
+ $sectionName = self::getSectionNameFromStrippedText( $text );
+ return self::makeAnchor( $sectionName );
}
/**
* than UTF-8, resulting in breakage.
*
* @param string $text The section name
- * @return string An anchor
+ * @return string Anchor (starting with '#')
*/
public function guessLegacySectionNameFromWikiText( $text ) {
- global $wgFragmentMode;
-
# Strip out wikitext links(they break the anchor)
$text = $this->stripSectionName( $text );
- $text = Sanitizer::normalizeSectionNameWhitespace( $text );
- $text = Sanitizer::decodeCharReferences( $text );
- $text = $this->normalizeSectionName( $text );
-
- if ( isset( $wgFragmentMode[1] ) && $wgFragmentMode[1] === 'legacy' ) {
- // ForAttribute() and ForLink() are the same for legacy encoding
- $id = Sanitizer::escapeIdForAttribute( $text, Sanitizer::ID_FALLBACK );
- } else {
- $id = Sanitizer::escapeIdForLink( $text );
- }
+ $sectionName = self::getSectionNameFromStrippedText( $text );
+ return self::makeLegacyAnchor( $sectionName );
+ }
- return "#$id";
+ /**
+ * Like guessSectionNameFromWikiText(), but takes already-stripped text as input.
+ * @param string $text Section name (plain text)
+ * @return string Anchor (starting with '#')
+ */
+ public static function guessSectionNameFromStrippedText( $text ) {
+ $sectionName = self::getSectionNameFromStrippedText( $text );
+ return self::makeAnchor( $sectionName );
}
/**
* @param string $text
* @return string
*/
- private function normalizeSectionName( $text ) {
+ private static function normalizeSectionName( $text ) {
# T90902: ensure the same normalization is applied for IDs as to links
$titleParser = MediaWikiServices::getInstance()->getTitleParser();
try {
return 'nowikiemail';
}
- if (
- $target->getEditCount() === 0
- && ( $sender === null || !$sender->isAllowed( 'sendemail-new-users' ) )
+ if ( $target->getEditCount() === 0 &&
+ ( $sender === null || !$sender->isAllowed( 'sendemail-new-users' ) )
) {
// Determine if target has any other logged actions.
$dbr = wfGetDB( DB_REPLICA );
}
}
+ if ( $sender !== null && !$target->getOption( 'email-allow-new-users' ) &&
+ $sender->isNewbie()
+ ) {
+ wfDebug( "User does not allow user emails from new users.\n" );
+
+ return 'nowikiemail';
+ }
+
if ( $sender !== null ) {
$blacklist = $target->getOption( 'email-blacklist', [] );
if ( $blacklist ) {
}
private function outputNamespaceProtectionInfo() {
- global $wgParser, $wgContLang;
+ global $wgContLang;
$out = $this->getOutput();
$namespaceProtection = $this->getConfig()->get( 'NamespaceProtection' );
return;
}
- $header = $this->msg( 'listgrouprights-namespaceprotection-header' )->parse();
+ $header = $this->msg( 'listgrouprights-namespaceprotection-header' )->text();
$out->addHTML(
Html::rawElement( 'h2', [], Html::element( 'span', [
'class' => 'mw-headline',
- 'id' => $wgParser->guessSectionNameFromWikiText( $header )
+ 'id' => substr( Parser::guessSectionNameFromStrippedText( $header ), 1 )
], $header ) ) .
Xml::openElement( 'table', [ 'class' => 'wikitable' ] ) .
Html::element(
"timezoneregion-indian": "Indian Ocean",
"timezoneregion-pacific": "Pacific Ocean",
"allowemail": "Allow other users to email me",
+ "email-allow-new-users-label": "Allow emails from brand-new users",
"email-blacklist-label": "Prohibit these users from emailing me:",
"prefs-searchoptions": "Search",
"prefs-namespaces": "Namespaces",
"timezoneregion-indian": "Used in \"Time zone\" listbox in [[Special:Preferences#mw-prefsection-datetime|preferences]], \"date and time\" tab.\n{{Related|Timezoneregion}}",
"timezoneregion-pacific": "Used in \"Time zone\" listbox in [[Special:Preferences#mw-prefsection-datetime|preferences]], \"date and time\" tab.\n{{Related|Timezoneregion}}",
"allowemail": "Used in [[Special:Preferences]] > {{int:prefs-personal}} > {{int:email}}.",
+ "email-allow-new-users-label": "Used in [[Special:Preferences]] > {{int:prefs-prohibit}} > {{int:email}}.",
"email-blacklist-label": "Used in [[Special:Preferences]] > {{int:prefs-prohibit}} > {{int:email}}.",
"prefs-searchoptions": "{{Identical|Search}}",
"prefs-namespaces": "Shown as legend of the second fieldset of the tab 'Search' in [[Special:Preferences]]\n{{Identical|Namespace}}",
$missingTextRows = array_flip( $this->oldIdMap );
$externalRevs = [];
$objectRevs = [];
- $res = $dbr->select( 'text', [ 'old_id', 'old_flags' ],
- 'old_id IN (' . implode( ',', $this->oldIdMap ) . ')', __METHOD__ );
+ $res = $dbr->select(
+ 'text',
+ [ 'old_id', 'old_flags' ],
+ [ 'old_id' => $this->oldIdMap ],
+ __METHOD__
+ );
foreach ( $res as $row ) {
/**
* @var $flags int
$externalConcatBlobs = [];
$externalNormalBlobs = [];
if ( count( $externalRevs ) ) {
- $res = $dbr->select( 'text', [ 'old_id', 'old_flags', 'old_text' ],
- [ 'old_id IN (' . implode( ',', $externalRevs ) . ')' ], __METHOD__ );
+ $res = $dbr->select(
+ 'text',
+ [ 'old_id', 'old_flags', 'old_text' ],
+ [ 'old_id' => $externalRevs ],
+ __METHOD__
+ );
foreach ( $res as $row ) {
$urlParts = explode( '://', $row->old_text, 2 );
if ( count( $urlParts ) !== 2 || $urlParts[1] == '' ) {
$res = $dbr->select(
'text',
[ 'old_id', 'old_flags', "LEFT(old_text, $headerLength) AS header" ],
- [ 'old_id IN (' . implode( ',', $objectRevs ) . ')' ],
+ [ 'old_id' => $objectRevs ],
__METHOD__
);
foreach ( $res as $row ) {
$res = $dbr->select(
'text',
[ 'old_id', 'old_flags', "LEFT(old_text, $headerLength) AS header" ],
- [ 'old_id IN (' . implode( ',', array_keys( $concatBlobs ) ) . ')' ],
+ [ 'old_id' => array_keys( $concatBlobs ) ],
__METHOD__
);
foreach ( $res as $row ) {
'resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js',
'resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js',
'resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js',
+ 'resources/src/mediawiki.special/mediawiki.special.preferences.personalEmail.js',
],
'messages' => [
'prefs-tabs-navigation-hint',
--- /dev/null
+/*!
+ * JavaScript for Special:Preferences: Email preferences better UX
+ */
+( function ( $ ) {
+ $( function () {
+ var allowEmail, allowEmailFromNewUsers;
+
+ allowEmail = $( '#wpAllowEmail' );
+ allowEmailFromNewUsers = $( '#wpAllowEmailFromNewUsers' );
+
+ function toggleDisabled() {
+ if ( allowEmail.is( ':checked' ) && allowEmail.is( ':enabled' ) ) {
+ allowEmailFromNewUsers.prop( 'disabled', false );
+ } else {
+ allowEmailFromNewUsers.prop( 'disabled', true );
+ }
+ }
+
+ if ( allowEmail ) {
+ allowEmail.on( 'change', toggleDisabled );
+ toggleDisabled();
+ }
+ } );
+}( jQuery ) );