diff options
-rw-r--r-- | includes/debug/MWDebug.php | 59 | ||||
-rw-r--r-- | includes/skins/Skin.php | 11 | ||||
-rw-r--r-- | tests/phpunit/includes/debug/MWDebugTest.php | 36 |
3 files changed, 92 insertions, 14 deletions
diff --git a/includes/debug/MWDebug.php b/includes/debug/MWDebug.php index 87d20da342a6..3aeeea1552ac 100644 --- a/includes/debug/MWDebug.php +++ b/includes/debug/MWDebug.php @@ -206,14 +206,10 @@ class MWDebug { /** * Show a warning that $function is deprecated. - * This will send it to the following locations: - * - Debug toolbar, with one item per function and caller, if $wgDebugToolbar - * is set to true. - * - PHP's error log, with level E_USER_DEPRECATED, if $wgDevelopmentWarnings - * is set to true. - * - MediaWiki's debug log, if $wgDevelopmentWarnings is set to false. * + * @see deprecatedMsg() * @since 1.19 + * * @param string $function Function that is deprecated. * @param string|false $version Version in which the function was deprecated. * @param string|bool $component Component to which the function belongs. @@ -235,6 +231,49 @@ class MWDebug { } /** + * Show a warning if $method declared in $class is overridden in $instance. + * + * @since 1.36 + * @see deprecatedMsg() + * + * phpcs:ignore MediaWiki.Commenting.FunctionComment.ObjectTypeHintParam + * @param object $instance Object on which to detect deprecated overrides (typically $this). + * @param string $class Class declaring the deprecated method (typically __CLASS__ ) + * @param string $method The name of the deprecated method. + * @param string|false $version Version in which the method was deprecated. + * @param string|bool $component Component to which the class belongs. + * If false, it is assumed the class is in MediaWiki core. + * @param int $callerOffset How far up the callstack is the original + * caller. 2 = function that called the function that called + * MWDebug::detectDeprecatedOverride() + * + * @return bool True if the method was overridden, false otherwise. If the method + * was overridden, it should be called. The deprecated method's default + * implementation should call MWDebug::deprecated(). + */ + public static function detectDeprecatedOverride( $instance, $class, $method, $version = false, + $component = false, $callerOffset = 2 + ) { + $reflectionMethod = new ReflectionMethod( $instance, $method ); + $declaringClass = $reflectionMethod->getDeclaringClass()->getName(); + + if ( $declaringClass === $class ) { + // not overridden, nothing to do + return false; + } + + if ( $version ) { + $component = $component ?: 'MediaWiki'; + $msg = "$declaringClass overrides $method which was deprecated in $component $version."; + } else { + $msg = "$declaringClass overrides $method which is deprecated."; + } + self::deprecatedMsg( $msg, $version, $component, $callerOffset + 1 ); + + return true; + } + + /** * Log a deprecation warning with arbitrary message text. A caller * description will be appended. If the message has already been sent for * this caller, it won't be sent again. @@ -243,6 +282,14 @@ class MWDebug { * automatically appended to the message. The message text should include * information about when the thing was deprecated. * + * The warning will be sent to the following locations: + * - Debug toolbar, with one item per function and caller, if $wgDebugToolbar + * is set to true. + * - PHP's error log, with level E_USER_DEPRECATED, if $wgDevelopmentWarnings + * is set to true. This is the case in phpunit tests per default, and will + * cause tests to fail. + * - MediaWiki's debug log, if $wgDevelopmentWarnings is set to false. + * * @since 1.35 * * @param string $msg The message diff --git a/includes/skins/Skin.php b/includes/skins/Skin.php index 8f97258bed19..8ed44b538386 100644 --- a/includes/skins/Skin.php +++ b/includes/skins/Skin.php @@ -472,13 +472,8 @@ abstract class Skin extends ContextSource { * setupSkinUserCss is required. */ final public function doSetupSkinUserCss( OutputPage $out ) { - $stylesBefore = $out->getModuleStyles(); - $this->setupSkinUserCss( $out ); - $stylesAfter = $out->getModuleStyles(); - if ( count( $stylesAfter ) !== count( $stylesBefore ) ) { - // Styles were added by the setupSkinUserCss method. This is no longer allowed. - wfDeprecatedMsg( get_class( $this ) . '::setupSkinUserCss must not modify ' . - 'the style module list, this is deprecated since 1.32', '1.32' ); + if ( MWDebug::detectDeprecatedOverride( $this, __CLASS__, 'setupSkinUserCss', '1.32' ) ) { + $this->setupSkinUserCss( $out ); } } @@ -491,7 +486,7 @@ abstract class Skin extends ContextSource { * @param OutputPage $out Legacy parameter, identical to $this->getOutput() */ public function setupSkinUserCss( OutputPage $out ) { - // Stub. + wfDeprecated( __METHOD__, '1.32' ); } /** diff --git a/tests/phpunit/includes/debug/MWDebugTest.php b/tests/phpunit/includes/debug/MWDebugTest.php index 4e7e375b1b66..8734b523548d 100644 --- a/tests/phpunit/includes/debug/MWDebugTest.php +++ b/tests/phpunit/includes/debug/MWDebugTest.php @@ -51,6 +51,42 @@ class MWDebugTest extends MediaWikiIntegrationTestCase { } /** + * @covers MWDebug::detectDeprecatedOverride + */ + public function testDetectDeprecatedOverride() { + $baseclassInstance = new TitleValue( NS_MAIN, 'Test' ); + + $this->assertFalse( + MWDebug::detectDeprecatedOverride( + $baseclassInstance, + TitleValue::class, + 'getNamespace', + MW_VERSION + ) + ); + + // create a dummy subclass that overrides a method + $subclassInstance = new class ( NS_MAIN, 'Test' ) extends TitleValue { + public function getNamespace() { + // never called + return -100; + } + }; + + $this->assertTrue( + MWDebug::detectDeprecatedOverride( + $subclassInstance, + TitleValue::class, + 'getNamespace', + MW_VERSION + ) + ); + + // A warning should have been logged + $this->assertCount( 1, MWDebug::getLog() ); + } + + /** * @covers MWDebug::deprecated */ public function testAvoidDuplicateDeprecations() { |