$totalcnt = $rescnt;
$category = $this->cat;
DeferredUpdates::addCallableUpdate( function () use ( $category ) {
- $category->refreshCounts();
+ # Avoid excess contention on the same category (T162121)
+ $dbw = wfGetDB( DB_MASTER );
+ $name = __METHOD__ . ':' . md5( $this->mName );
+ $scopedLock = $dbw->getScopedLockAndFlush( $name, __METHOD__, 1 );
+ if ( $scopedLock ) {
+ $category->refreshCounts();
+ }
} );
} else {
// Case 3: hopeless. Don't give a total count at all.
$this->addOption( 'LIMIT', $limit + 1 );
$this->addOption(
'USE INDEX',
- [ 'archive' => ( $mode == 'user' ? 'usertext_timestamp' : 'name_title_timestamp' ) ]
+ [ 'archive' => ( $mode == 'user' ? 'ar_usertext_timestamp' : 'name_title_timestamp' ) ]
);
if ( $mode == 'all' ) {
if ( $params['unique'] ) {
$condition = [];
$condition['ar_user_text'] = $this->target;
- $index = 'usertext_timestamp';
+ $index = 'ar_usertext_timestamp';
return [ $index, $condition ];
}
// Result list circle indicators
// Defined and used in mw.rcfilters.ui.ChangesListWrapperWidget.less
-@result-circle-margin: 0.1em;
+@result-circle-margin: 3px;
@result-circle-general-margin: 0.5em;
// In these small sizes, 'em' appears
// squished and inconsistent.
// Pixels are better for this use case:
-@result-circle-diameter: 5px;
+@result-circle-diameter: 6px;
enter: 'onTextInputEnter'
} );
this.capsule.connect( this, { capsuleItemClick: 'onCapsuleItemClick' } );
- this.capsule.popup.connect( this, { toggle: 'onCapsulePopupToggle' } );
+ this.capsule.popup.connect( this, {
+ toggle: 'onCapsulePopupToggle',
+ ready: 'onCapsulePopupReady'
+ } );
// Initialize
this.$element
this.scrollToTop( filterWidget.$element );
};
+ /**
+ * Respond to capsule popup ready event, fired after the popup is visible, positioned and clipped
+ */
+ mw.rcfilters.ui.FilterWrapperWidget.prototype.onCapsulePopupReady = function () {
+ mw.hook( 'RcFilters.popup.open' ).fire( this.filterPopup.getSelectedFilter() );
+
+ this.scrollToTop( this.capsule.$element, 10 );
+ if ( !this.filterPopup.getSelectedFilter() ) {
+ // No selection, scroll the popup list to top
+ setTimeout( function () { this.capsule.popup.$body.scrollTop( 0 ); }.bind( this ), 0 );
+ }
+ };
+
/**
* Respond to popup toggle event. Reset selection in the list when the popup is closed.
*
* @param {boolean} isVisible Popup is visible
*/
mw.rcfilters.ui.FilterWrapperWidget.prototype.onCapsulePopupToggle = function ( isVisible ) {
- if ( !isVisible ) {
- if ( !this.textInput.getValue() ) {
- // Only reset selection if we are not filtering
- this.filterPopup.resetSelection();
- this.capsule.resetSelection();
- }
- } else {
- mw.hook( 'RcFilters.popup.open' ).fire( this.filterPopup.getSelectedFilter() );
-
- this.scrollToTop( this.capsule.$element, 10 );
- if ( !this.filterPopup.getSelectedFilter() ) {
- // No selection, scroll the popup list to top
- setTimeout( function () { this.capsule.popup.$body.scrollTop( 0 ); }.bind( this ), 0 );
- }
+ if ( !isVisible && !this.textInput.getValue() ) {
+ // Only reset selection if we are not filtering
+ this.filterPopup.resetSelection();
+ this.capsule.resetSelection();
}
};
*/
public function __call( $func, $args ) {
static $compatibility = [
- 'assertEmpty' => 'assertEmpty2', // assertEmpty was added in phpunit 3.7.32
];
if ( isset( $compatibility[$func] ) ) {
}
}
- /**
- * Used as a compatibility method for phpunit < 3.7.32
- * @param string $value
- * @param string $msg
- */
- private function assertEmpty2( $value, $msg ) {
- $this->assertTrue( $value == '', $msg );
- }
-
private static function unprefixTable( &$tableName, $ind, $prefix ) {
$tableName = substr( $tableName, strlen( $prefix ) );
}
] );
}
- public static function provideGetModuleRegistrations() {
+ public function provideGetModuleRegistrations() {
return [
[ [
'msg' => 'Empty registry',
"test.blank",
"{blankVer}"
]
+] );',
+ ] ],
+ [ [
+ 'msg' => 'Omit raw modules from registry',
+ 'modules' => [
+ 'test.raw' => new ResourceLoaderTestModule( [ 'isRaw' => true ] ),
+ 'test.blank' => new ResourceLoaderTestModule(),
+ ],
+ 'out' => '
+mw.loader.addSource( {
+ "local": "/w/load.php"
+} );
+mw.loader.register( [
+ [
+ "test.blank",
+ "{blankVer}"
+ ]
+] );',
+ ] ],
+ [ [
+ 'msg' => 'Version falls back gracefully if getVersionHash throws',
+ 'modules' => [
+ 'test.fail' => (
+ ( $mock = $this->getMockBuilder( 'ResourceLoaderTestModule' )
+ ->setMethods( [ 'getVersionHash' ] )->getMock() )
+ && $mock->method( 'getVersionHash' )->will(
+ $this->throwException( new Exception )
+ )
+ ) ? $mock : $mock
+ ],
+ 'out' => '
+mw.loader.addSource( {
+ "local": "/w/load.php"
+} );
+mw.loader.register( [
+ [
+ "test.fail",
+ ""
+ ]
+] );
+mw.loader.state( {
+ "test.fail": "error"
+} );',
+ ] ],
+ [ [
+ 'msg' => 'Use version from getVersionHash',
+ 'modules' => [
+ 'test.version' => (
+ ( $mock = $this->getMockBuilder( 'ResourceLoaderTestModule' )
+ ->setMethods( [ 'getVersionHash' ] )->getMock() )
+ && $mock->method( 'getVersionHash' )->willReturn( '1234567' )
+ ) ? $mock : $mock
+ ],
+ 'out' => '
+mw.loader.addSource( {
+ "local": "/w/load.php"
+} );
+mw.loader.register( [
+ [
+ "test.version",
+ "1234567"
+ ]
+] );',
+ ] ],
+ [ [
+ 'msg' => 'Re-hash version from getVersionHash if too long',
+ 'modules' => [
+ 'test.version' => (
+ ( $mock = $this->getMockBuilder( 'ResourceLoaderTestModule' )
+ ->setMethods( [ 'getVersionHash' ] )->getMock() )
+ && $mock->method( 'getVersionHash' )->willReturn( '12345678' )
+ ) ? $mock : $mock
+ ],
+ 'out' => '
+mw.loader.addSource( {
+ "local": "/w/load.php"
+} );
+mw.loader.register( [
+ [
+ "test.version",
+ "016es8l"
+ ]
] );',
] ],
[ [
/**
* @dataProvider provideGetModuleRegistrations
- * @covers ResourceLoaderStartUpModule::compileUnresolvedDependencies
* @covers ResourceLoaderStartUpModule::getModuleRegistrations
+ * @covers ResourceLoaderStartUpModule::compileUnresolvedDependencies
* @covers ResourceLoader::makeLoaderRegisterScript
*/
public function testGetModuleRegistrations( $case ) {
];
}
/**
+ * @covers ResourceLoaderStartUpModule::getModuleRegistrations
* @dataProvider provideRegistrations
*/
public function testRegistrationsMinified( $modules ) {
}
/**
+ * @covers ResourceLoaderStartUpModule::getModuleRegistrations
* @dataProvider provideRegistrations
*/
public function testRegistrationsUnminified( $modules ) {
* @covers ResourceLoader::register
* @covers ResourceLoader::getModule
*/
- public function testRegisterValid() {
+ public function testRegisterValidObject() {
$module = new ResourceLoaderTestModule();
$resourceLoader = new EmptyResourceLoader();
$resourceLoader->register( 'test', $module );
$this->assertEquals( $module, $resourceLoader->getModule( 'test' ) );
}
+ /**
+ * @covers ResourceLoader::register
+ * @covers ResourceLoader::getModule
+ */
+ public function testRegisterValidArray() {
+ $module = new ResourceLoaderTestModule();
+ $resourceLoader = new EmptyResourceLoader();
+ // Covers case of register() setting $rl->moduleInfos,
+ // but $rl->modules lazy-populated by getModule()
+ $resourceLoader->register( 'test', [ 'object' => $module ] );
+ $this->assertEquals( $module, $resourceLoader->getModule( 'test' ) );
+ }
+
/**
* @covers ResourceLoader::register
*/
);
}
+ /**
+ * @covers ResourceLoader::makeLoaderRegisterScript
+ */
+ public function testMakeLoaderRegisterScript() {
+ $this->assertEquals(
+ 'mw.loader.register( [
+ [
+ "test.name",
+ "1234567"
+ ]
+] );',
+ ResourceLoader::makeLoaderRegisterScript( [
+ [ 'test.name', '1234567' ],
+ ] ),
+ 'Nested array parameter'
+ );
+
+ $this->assertEquals(
+ 'mw.loader.register( "test.name", "1234567" );',
+ ResourceLoader::makeLoaderRegisterScript(
+ 'test.name',
+ '1234567'
+ ),
+ 'Variadic parameters'
+ );
+ }
+
/**
* @covers ResourceLoader::makeLoaderSourcesScript
*/