$url = $match['file'][0];
// Skip fully-qualified and protocol-relative URLs and data URIs
- // Also skips the rare `behavior` property specifying application's default behavior
if (
substr( $url, 0, 2 ) === '//' ||
- parse_url( $url, PHP_URL_SCHEME ) ||
- substr( $url, 0, 9 ) === '#default#'
+ parse_url( $url, PHP_URL_SCHEME )
) {
break;
}
+ // Strip trailing anchors - T115436
+ $anchor = strpos( $url, '#' );
+ if ( $anchor !== false ) {
+ $url = substr( $url, 0, $anchor );
+
+ // '#some-anchors' is not a file
+ if ( $url === '' ) {
+ break;
+ }
+ }
+
$files[] = $path . $url;
}
}
// Pass thru fully-qualified and protocol-relative URLs and data URIs, as well as local URLs if
// we can't expand them.
- // Also skips the rare `behavior` property specifying application's default behavior
+ // Also skips anchors or the rare `behavior` property specifying application's default behavior
if (
self::isRemoteUrl( $url ) ||
self::isLocalUrl( $url ) ||
- substr( $url, 0, 9 ) === '#default#'
+ substr( $url, 0, 1 ) === '#'
) {
return $url;
}
* Take a list of strings and build a locale-friendly comma-separated
* list, using the local comma-separator message.
* The last two strings are chained with an "and".
- * NOTE: This function will only work with standard numeric array keys (0, 1, 2…)
*
- * @param string[] $l
+ * @param string[] $list
* @return string
*/
- function listToText( array $l ) {
- $m = count( $l ) - 1;
- if ( $m < 0 ) {
+ public function listToText( array $list ) {
+ $itemCount = count( $list );
+ if ( $itemCount < 1 ) {
return '';
}
- if ( $m > 0 ) {
+ $text = array_pop( $list );
+ if ( $itemCount > 1 ) {
$and = $this->msg( 'and' )->escaped();
$space = $this->msg( 'word-separator' )->escaped();
- if ( $m > 1 ) {
+ $comma = '';
+ if ( $itemCount > 2 ) {
$comma = $this->msg( 'comma-separator' )->escaped();
}
+ $text = implode( $comma, $list ) . $and . $space . $text;
}
- $s = $l[$m];
- for ( $i = $m - 1; $i >= 0; $i-- ) {
- if ( $i == $m - 1 ) {
- $s = $l[$i] . $and . $space . $s;
- } else {
- $s = $l[$i] . $comma . $s;
- }
- }
- return $s;
+ return $text;
}
/**
*/
private $normalizationFunctions = [];
+ /**
+ * Run disabled parser tests
+ * @var bool
+ */
+ private $runDisabled;
+
+ /**
+ * Run tests intended only for parsoid
+ * @var bool
+ */
+ private $runParsoid;
+
+ /**
+ * Disable parse on article insertion
+ * @var bool
+ */
+ private $disableSaveParse;
+
+ /**
+ * Reuse upload directory
+ * @var bool
+ */
+ private $keepUploads;
+
/**
* @param TestRecorder $recorder
* @param array $options
$this->runDisabled = !empty( $options['run-disabled'] );
$this->runParsoid = !empty( $options['run-parsoid'] );
+ $this->disableSaveParse = !empty( $options['disable-save-parse'] );
+
$this->tidySupport = new TidySupport( !empty( $options['use-tidy-config'] ) );
if ( !$this->tidySupport->isEnabled() ) {
$this->recorder->warning(
'site_stats', 'ipblocks', 'image', 'oldimage',
'recentchanges', 'watchlist', 'interwiki', 'logging', 'log_search',
'querycache', 'objectcache', 'job', 'l10n_cache', 'redirect', 'querycachetwo',
- 'archive', 'user_groups', 'page_props', 'category'
+ 'archive', 'user_groups', 'page_props', 'category',
+ 'slots', 'content', 'slot_roles', 'content_models',
];
if ( $wgCommentTableSchemaMigrationStage >= MIGRATION_WRITE_BOTH ) {
$this->checkSetupDone( 'setupDatabase' );
$this->dbClone->destroy();
- $this->databaseSetupDone = false;
if ( $this->useTemporaryTables ) {
if ( $this->db->getType() == 'sqlite' ) {
);
}
- // Use mock parser, to make debugging of actual parser tests simpler.
+ // Optionally use mock parser, to make debugging of actual parser tests simpler.
// But initialise the MessageCache clone first, don't let MessageCache
// get a reference to the mock object.
- MessageCache::singleton()->getParser();
- $restore = $this->executeSetupSnippets( [ 'wgParser' => new ParserTestMockParser ] );
+ if ( $this->disableSaveParse ) {
+ MessageCache::singleton()->getParser();
+ $restore = $this->executeSetupSnippets( [ 'wgParser' => new ParserTestMockParser ] );
+ } else {
+ $restore = false;
+ }
try {
$status = $page->doEditContent(
$newContent,
EDIT_NEW | EDIT_INTERNAL
);
} finally {
- $restore();
+ if ( $restore ) {
+ $restore();
+ }
}
if ( !$status->isOK() ) {
'be used.', false, true );
$this->addOption( 'run-disabled', 'run disabled tests' );
$this->addOption( 'run-parsoid', 'run parsoid tests (normally disabled)' );
+ $this->addOption( 'disable-save-parse', 'Don\'t run the parser when ' .
+ 'inserting articles into the database' );
$this->addOption( 'dwdiff', 'Use dwdiff to display diff output' );
$this->addOption( 'mark-ws', 'Mark whitespace in diffs by replacing it with symbols' );
$this->addOption( 'norm', 'Apply a comma-separated list of normalization functions to ' .
'keep-uploads' => $this->hasOption( 'keep-uploads' ),
'run-disabled' => $this->hasOption( 'run-disabled' ),
'run-parsoid' => $this->hasOption( 'run-parsoid' ),
+ 'disable-save-parse' => $this->hasOption( 'disable-save-parse' ),
'use-tidy-config' => $this->hasOption( 'use-tidy-config' ),
'file-backend' => $this->getOption( 'file-backend' ),
'upload-dir' => $this->getOption( 'upload-dir' ),
] );
}
+ /**
+ * @dataProvider providesReferencedFiles
+ * @covers CSSMin::getLocalFileReferences
+ */
+ public function testGetLocalFileReferences( $input, $expected ) {
+ $output = CSSMin::getLocalFileReferences( $input, '/' );
+ $this->assertEquals(
+ $expected,
+ $output,
+ 'getLocalFileReferences() must find the local file properly'
+ );
+ }
+
+ public static function providesReferencedFiles() {
+ // input, array of expected local file names
+ return [
+ [ 'url("//example.org")', [] ],
+ [ 'url("https://example.org")', [] ],
+ [ 'url("#default#")', [] ],
+ [ 'url("WikiFont-Glyphs.svg#wikiglyph")', [ '/WikiFont-Glyphs.svg' ] ],
+ [ 'url("#some-anchor")', [] ],
+ ];
+ }
+
/**
* @dataProvider provideSerializeStringValue
* @covers CSSMin::serializeStringValue
[ 'foo { behavior: url(#default#bar); }', false, '/w/', false ],
'foo { behavior: url("#default#bar"); }',
],
+ [
+ 'Keeps anchors',
+ [ 'url(#other)', false, '/', false ],
+ 'url("#other")'
+ ],
+ [
+ 'Keeps anchors after a path',
+ [ 'url(images/file.svg#id)', false, '/', false ],
+ 'url("/images/file.svg#id")'
+ ],
];
}