* @return CommentStoreComment
*/
public function createComment( IDatabase $dbw, $comment, array $data = null ) {
- global $wgContLang;
-
- if ( !$comment instanceof CommentStoreComment ) {
- if ( $data !== null ) {
- foreach ( $data as $k => $v ) {
- if ( substr( $k, 0, 1 ) === '_' ) {
- throw new InvalidArgumentException( 'Keys in $data beginning with "_" are reserved' );
- }
- }
- }
- if ( $comment instanceof Message ) {
- $message = clone $comment;
- $text = $message->inLanguage( $wgContLang ) // Avoid $wgForceUIMsgAsContentMsg
- ->setInterfaceMessageFlag( true )
- ->text();
- $comment = new CommentStoreComment( null, $text, $message, $data );
- } else {
- $comment = new CommentStoreComment( null, $comment, null, $data );
- }
- }
+ $comment = CommentStoreComment::newUnsavedComment( $comment, $data );
# Truncate comment in a Unicode-sensitive manner
$comment->text = $this->lang->truncate( $comment->text, self::MAX_COMMENT_LENGTH );
public $data;
/**
- * @private For use by CommentStore only
+ * @private For use by CommentStore only. Use self::newUnsavedComment() instead.
* @param int|null $id
* @param string $text
* @param Message|null $message
$this->message = $message ?: new RawMessage( '$1', [ $text ] );
$this->data = $data;
}
+
+ /**
+ * Create a new, unsaved CommentStoreComment
+ *
+ * @param string|Message|CommentStoreComment $comment Comment text or Message object.
+ * A CommentStoreComment is also accepted here, in which case it is returned unchanged.
+ * @param array|null $data Structured data to store. Keys beginning with '_' are reserved.
+ * Ignored if $comment is a CommentStoreComment.
+ * @return CommentStoreComment
+ */
+ public static function newUnsavedComment( $comment, array $data = null ) {
+ global $wgContLang;
+
+ if ( $comment instanceof CommentStoreComment ) {
+ return $comment;
+ }
+
+ if ( $data !== null ) {
+ foreach ( $data as $k => $v ) {
+ if ( substr( $k, 0, 1 ) === '_' ) {
+ throw new InvalidArgumentException( 'Keys in $data beginning with "_" are reserved' );
+ }
+ }
+ }
+
+ if ( $comment instanceof Message ) {
+ $message = clone $comment;
+ $text = $message->inLanguage( $wgContLang ) // Avoid $wgForceUIMsgAsContentMsg
+ ->setInterfaceMessageFlag( true )
+ ->text();
+ return new CommentStoreComment( null, $text, $message, $data );
+ } else {
+ return new CommentStoreComment( null, $comment, null, $data );
+ }
+ }
}
$sectionTitle = Title::newFromText( '#' . $section );
} else {
$sectionTitle = Title::makeTitleSafe( $title->getNamespace(),
- $title->getDBkey(), $section );
+ $title->getDBkey(), Sanitizer::decodeCharReferences( $section ) );
}
if ( $sectionTitle ) {
$link = Linker::makeCommentLink( $sectionTitle, $wgLang->getArrow(), $wikiId, 'noclasses' );
global $wgExperimentalHtmlIds;
$options = (array)$options;
- $id = self::decodeCharReferences( $id );
-
if ( $wgExperimentalHtmlIds && !in_array( 'legacy', $options ) ) {
$id = preg_replace( '/[ \t\n\r\f_\'"&#%]+/', '_', $id );
$id = trim( $id, '_' );
* @return string
*/
private static function escapeIdInternal( $id, $mode ) {
- $id = self::decodeCharReferences( $id );
-
switch ( $mode ) {
case 'html5':
$id = str_replace( ' ', '_', $id );
) {
$classes[] = 'mw-enhanced-watched';
}
- $classes = array_merge( $classes, $this->getHTMLClassesForFilters( $rcObj ) );
+ $classes = array_merge( $classes, $this->getHTMLClasses( $rcObj, $rcObj->watched ) );
$separator = ' <span class="mw-changeslist-separator">. .</span> ';
public function deletedLink( $id ) {
if ( $this->getUser()->isAllowed( 'deletedhistory' ) ) {
$dbr = wfGetDB( DB_REPLICA );
- $row = $dbr->selectRow( 'archive', '*',
+ $row = $dbr->selectRow( 'archive',
+ Revision::selectArchiveFields(),
[ 'ar_rev_id' => $id ],
__METHOD__ );
if ( $row ) {
if ( $this->historyLine == 0 ) { // called for the first time, return line from cur
$this->historyRes = $dbr->select( 'image',
- [
- '*',
- "'' AS oi_archive_name",
- '0 as oi_deleted',
- 'img_sha1'
+ self::selectFields() + [
+ 'oi_archive_name' => $dbr->addQuotes( '' ),
+ 'oi_deleted' => 0,
],
[ 'img_name' => $this->title->getDBkey() ],
$fname
return false;
}
} elseif ( $this->historyLine == 1 ) {
- $this->historyRes = $dbr->select( 'oldimage', '*',
+ $this->historyRes = $dbr->select(
+ 'oldimage',
+ OldLocalFile::selectFields(),
[ 'oi_name' => $this->title->getDBkey() ],
$fname,
[ 'ORDER BY' => 'oi_timestamp DESC' ]
$wikiPage = $this;
// Trigger post-create hook
$params = [ &$wikiPage, &$user, $content, $summary,
- $flags & EDIT_MINOR, null, null, &$flags, $revision ];
+ $flags & EDIT_MINOR, null, null, &$flags, $revision ];
Hooks::run( 'PageContentInsertComplete', $params );
// Trigger post-save hook
- $params = array_merge( $params, [ &$status, $meta['baseRevId'] ] );
+ $params = array_merge( $params, [ &$status, $meta['baseRevId'], 0 ] );
Hooks::run( 'PageContentSaveComplete', $params );
}
),
# Save headline for section edit hint before it's escaped
$headlineHint = $safeHeadline;
+ # Decode HTML entities
+ $safeHeadline = Sanitizer::decodeCharReferences( $safeHeadline );
$fallbackHeadline = Sanitizer::escapeIdForAttribute( $safeHeadline, Sanitizer::ID_FALLBACK );
$linkAnchor = Sanitizer::escapeIdForLink( $safeHeadline );
$safeHeadline = Sanitizer::escapeIdForAttribute( $safeHeadline, Sanitizer::ID_PRIMARY );
# Strip out wikitext links(they break the anchor)
$text = $this->stripSectionName( $text );
$text = Sanitizer::normalizeSectionNameWhitespace( $text );
+ $text = Sanitizer::decodeCharReferences( $text );
return '#' . Sanitizer::escapeIdForLink( $text );
}
# Strip out wikitext links(they break the anchor)
$text = $this->stripSectionName( $text );
$text = Sanitizer::normalizeSectionNameWhitespace( $text );
+ $text = Sanitizer::decodeCharReferences( $text );
if ( isset( $wgFragmentMode[1] ) && $wgFragmentMode[1] === 'legacy' ) {
// ForAttribute() and ForLink() are the same for legacy encoding
$result .= implode(
'<span class="mw-editsection-divider">'
- . wfMessage( 'pipe-separator' )->inLanguage( $lang )->text()
+ . wfMessage( 'pipe-separator' )->inLanguage( $lang )->escaped()
. '</span>',
$linksHtml
);
'scripts' => [
'resources/src/mediawiki/htmlform/htmlform.Checker.js',
],
+ 'dependencies' => [
+ 'jquery.throttle-debounce',
+ ],
'targets' => [ 'desktop', 'mobile' ],
],
'mediawiki.htmlform.ooui' => [
'resources/src/mediawiki.rcfilters/mw.rcfilters.UriProcessor.js',
],
'dependencies' => [
+ 'jquery.byteLength',
'oojs',
'mediawiki.api',
'mediawiki.api.options',
* @static
* @inheritable
* @param {string} str
- * @return {string}
+ * @return {number}
*/
jQuery.byteLength = function ( str ) {
// This basically figures out how many bytes a UTF-16 string (which is what js sees)
// Stringify state
stringified = JSON.stringify( state );
- if ( stringified.length > 65535 ) {
+ if ( $.byteLength( stringified ) > 65535 ) {
// Sanity check, since the preference can only hold that.
return;
}
);
filtersWidget.setTopSection( wlTopSection.$element );
} // end Special:WL
+
+ /**
+ * Fired when initialization of the filtering interface for changes list is complete.
+ *
+ * @event structuredChangeFilters_ui_initialized
+ * @member mw.hook
+ */
+ mw.hook( 'structuredChangeFilters.ui.initialized' ).fire();
}
};
[[#A&B&C&amp;D&amp;amp;E]]
!! html/php
<h2><span class="mw-headline" id="A.26B.26C.26amp.3BD.26amp.3Bamp.3BE">A&B&C&amp;D&amp;amp;E</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: A&B&C&amp;D&amp;amp;E">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
-<p><a href="#A.26B.26C.26D.26amp.3BE">#A&B&C&amp;D&amp;amp;E</a>
+<p><a href="#A.26B.26C.26amp.3BD.26amp.3Bamp.3BE">#A&B&C&amp;D&amp;amp;E</a>
</p>
!! end
[ '\'', '.27' ],
[ '§', '.C2.A7' ],
[ 'Test:A & B/Here', 'Test:A_.26_B.2FHere' ],
- [ 'A&B&C&amp;D&amp;amp;E', 'A.26B.26C.26amp.3BD.26amp.3Bamp.3BE' ],
+ [ 'A&B&C&amp;D&amp;amp;E', 'A.26B.26amp.3BC.26amp.3Bamp.3BD.26amp.3Bamp.3Bamp.3BE' ],
];
}
public function provideEscapeIdForStuff() {
// Test inputs and outputs
- $text = 'foo тест_#%!\'()[]:<>';
- $legacyEncoded = 'foo_.D1.82.D0.B5.D1.81.D1.82_.23.25.21.27.28.29.5B.5D:.3C.3E';
- $html5Encoded = 'foo_тест_#%!\'()[]:<>';
- $html5Experimental = 'foo_тест_!_()[]:<>';
+ $text = 'foo тест_#%!\'()[]:<>&&&amp;';
+ $legacyEncoded = 'foo_.D1.82.D0.B5.D1.81.D1.82_.23.25.21.27.28.29.5B.5D:.3C.3E' .
+ '.26.26amp.3B.26amp.3Bamp.3B';
+ $html5Encoded = 'foo_тест_#%!\'()[]:<>&&&amp;';
+ $html5Experimental = 'foo_тест_!_()[]:<>_amp;_amp;amp;';
// Settings: last element is $wgExternalInterwikiFragmentMode, the rest is $wgFragmentMode
$legacy = [ 'legacy', 'legacy' ];