Introduce DeprecatablePropertyArray and use it for PageUpdater
Bug: T250638 Change-Id: I53e39be59228ac5a57f34d51d733d1647331889c
This commit is contained in:
parent
4c7fbea780
commit
2704be7df8
4 changed files with 210 additions and 2 deletions
|
|
@ -859,6 +859,7 @@ $wgAutoloadLocalClasses = [
|
|||
'MediaWikiSite' => __DIR__ . '/includes/site/MediaWikiSite.php',
|
||||
'MediaWikiTitleCodec' => __DIR__ . '/includes/title/MediaWikiTitleCodec.php',
|
||||
'MediaWikiVersionFetcher' => __DIR__ . '/includes/MediaWikiVersionFetcher.php',
|
||||
'MediaWiki\\Debug\\DeprecatablePropertyArray' => __DIR__ . '/includes/debug/DeprecatablePropertyArray.php',
|
||||
'MediaWiki\\FileBackend\\FSFile\\TempFSFileFactory' => __DIR__ . '/includes/libs/filebackend/fsfile/TempFSFileFactory.php',
|
||||
'MediaWiki\\Hook\\AbortEmailNotificationHook' => __DIR__ . '/includes/changes/Hook/AbortEmailNotificationHook.php',
|
||||
'MediaWiki\\Hook\\AbortTalkPageEmailNotificationHook' => __DIR__ . '/includes/mail/Hook/AbortTalkPageEmailNotificationHook.php',
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ use InvalidArgumentException;
|
|||
use LogicException;
|
||||
use ManualLogEntry;
|
||||
use MediaWiki\Content\IContentHandlerFactory;
|
||||
use MediaWiki\Debug\DeprecatablePropertyArray;
|
||||
use MediaWiki\HookContainer\HookContainer;
|
||||
use MediaWiki\HookContainer\HookRunner;
|
||||
use MediaWiki\Linker\LinkTarget;
|
||||
|
|
@ -983,7 +984,13 @@ class PageUpdater {
|
|||
$wikiPage = $this->getWikiPage(); // TODO: use for legacy hooks only!
|
||||
|
||||
// Update article, but only if changed.
|
||||
$status = Status::newGood( [ 'new' => false, 'revision' => null, 'revision-record' => null ] );
|
||||
$status = Status::newGood(
|
||||
new DeprecatablePropertyArray(
|
||||
[ 'new' => false, 'revision' => null, 'revision-record' => null ],
|
||||
[], // TODO: [ 'revision' => '1.35' ],
|
||||
__METHOD__ . ' status'
|
||||
)
|
||||
);
|
||||
|
||||
$oldRev = $this->grabParentRevision();
|
||||
$oldid = $oldRev ? $oldRev->getId() : 0;
|
||||
|
|
@ -1139,7 +1146,13 @@ class PageUpdater {
|
|||
throw new PageUpdateException( 'Must provide a main slot when creating a page!' );
|
||||
}
|
||||
|
||||
$status = Status::newGood( [ 'new' => true, 'revision' => null, 'revision-record' => null ] );
|
||||
$status = Status::newGood(
|
||||
new DeprecatablePropertyArray(
|
||||
[ 'new' => true, 'revision' => null, 'revision-record' => null ],
|
||||
[], // TODO: [ 'revision' => '1.35' ],
|
||||
__METHOD__ . ' status'
|
||||
)
|
||||
);
|
||||
|
||||
$newRevisionRecord = $this->makeNewRevision(
|
||||
$summary,
|
||||
|
|
|
|||
94
includes/debug/DeprecatablePropertyArray.php
Normal file
94
includes/debug/DeprecatablePropertyArray.php
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
namespace MediaWiki\Debug;
|
||||
|
||||
use ArrayAccess;
|
||||
|
||||
/**
|
||||
* ArrayAccess implementation that supports deprecating access to certain properties.
|
||||
* It behaves mostly as a normal array, however in order to avoid instantiating
|
||||
* deprecated properties by default, a callable initializer can be set to the property.
|
||||
* It will be executed upon 'get'.
|
||||
* @note setting properties does not emit deprecation warnings.
|
||||
* @newable
|
||||
* @since 1.35
|
||||
*/
|
||||
class DeprecatablePropertyArray implements ArrayAccess {
|
||||
|
||||
/** @var array */
|
||||
private $container;
|
||||
|
||||
/** @var array Map of deprecated property names to deprecation versions */
|
||||
private $deprecatedProperties;
|
||||
|
||||
/** @var string */
|
||||
private $name;
|
||||
|
||||
/** @var string|null */
|
||||
private $component;
|
||||
|
||||
/**
|
||||
* @param array $initializer Initial value of the array.
|
||||
* @param array $deprecatedProperties Map of deprecated property names to versions.
|
||||
* @param string $name Descriptive identifier for the array
|
||||
* @param string|null $component Component to which array belongs.
|
||||
* If not provided, assumed to be MW Core
|
||||
*/
|
||||
public function __construct(
|
||||
array $initializer,
|
||||
array $deprecatedProperties,
|
||||
string $name,
|
||||
string $component = null
|
||||
) {
|
||||
$this->container = $initializer;
|
||||
$this->deprecatedProperties = $deprecatedProperties;
|
||||
$this->name = $name;
|
||||
$this->component = $component;
|
||||
}
|
||||
|
||||
public function offsetExists( $offset ) {
|
||||
$this->checkDeprecatedAccess( $offset, 'exists' );
|
||||
return isset( $this->container[$offset] );
|
||||
}
|
||||
|
||||
public function offsetGet( $offset ) {
|
||||
if ( $this->checkDeprecatedAccess( $offset, 'get' ) ) {
|
||||
if ( is_callable( $this->container[$offset] ) ) {
|
||||
$this->container[$offset] = call_user_func( $this->container[$offset] );
|
||||
}
|
||||
}
|
||||
return $this->container[$offset] ?? null;
|
||||
}
|
||||
|
||||
public function offsetSet( $offset, $value ) {
|
||||
if ( $offset === null ) {
|
||||
$this->container[] = $value;
|
||||
} else {
|
||||
$this->container[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function offsetUnset( $offset ) {
|
||||
$this->checkDeprecatedAccess( $offset, 'unset' );
|
||||
unset( $this->container[$offset] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int $offset
|
||||
* @param string $fname
|
||||
* @return bool
|
||||
*/
|
||||
private function checkDeprecatedAccess( $offset, string $fname ) : bool {
|
||||
if ( array_key_exists( $offset, $this->deprecatedProperties ) ) {
|
||||
$deprecatedVersion = $this->deprecatedProperties[$offset];
|
||||
wfDeprecated(
|
||||
"{$this->name} {$fname} '{$offset}'",
|
||||
$deprecatedVersion,
|
||||
$this->component ?? false,
|
||||
3
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
use MediaWiki\Debug\DeprecatablePropertyArray;
|
||||
use Wikimedia\TestingAccessWrapper;
|
||||
|
||||
/**
|
||||
* @covers \MediaWiki\Debug\DeprecatablePropertyArray
|
||||
*/
|
||||
class DeprecatablePropertyArrayTest extends MediaWikiUnitTestCase {
|
||||
|
||||
private const PROP_NAME = 'test_property';
|
||||
|
||||
/**
|
||||
* @dataProvider provideDeprecationWarning
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function testDeprecationWarning( callable $callback, string $message ) {
|
||||
$GLOBALS['wgDevelopmentWarnings'] = false;
|
||||
$this->assertDeprecationWarningIssued( $callback, $message );
|
||||
}
|
||||
|
||||
public function provideDeprecationWarning() {
|
||||
$propName = self::PROP_NAME;
|
||||
$array = new DeprecatablePropertyArray(
|
||||
[
|
||||
self::PROP_NAME => 'test_value',
|
||||
'callback' => function () {
|
||||
return 'callback_test_value';
|
||||
},
|
||||
],
|
||||
[
|
||||
self::PROP_NAME => 'DEPRECATED_VERSION',
|
||||
'callback' => 'DEPRECATED_VERSION',
|
||||
],
|
||||
'TEST'
|
||||
);
|
||||
|
||||
yield 'get' => [
|
||||
function () use ( $array ) {
|
||||
$this->assertSame( 'test_value', $array[ self::PROP_NAME ] );
|
||||
},
|
||||
"TEST get '{$propName}'"
|
||||
];
|
||||
yield 'get, callback' => [
|
||||
function () use ( $array ) {
|
||||
$this->assertSame( 'callback_test_value', $array[ 'callback' ] );
|
||||
},
|
||||
"TEST get 'callback'"
|
||||
];
|
||||
yield 'exists' => [
|
||||
function () use ( $array ) {
|
||||
$this->assertTrue( isset( $array[ self::PROP_NAME ] ) );
|
||||
},
|
||||
"TEST exists '{$propName}'"
|
||||
];
|
||||
yield 'unset' => [
|
||||
function () use ( $array ) {
|
||||
unset( $array[ self::PROP_NAME ] );
|
||||
},
|
||||
"TEST unset '{$propName}'"
|
||||
];
|
||||
}
|
||||
|
||||
public function testNonDeprecated() {
|
||||
$array = new DeprecatablePropertyArray( [], [], __METHOD__ );
|
||||
$this->assertFalse( isset( $array[self::PROP_NAME] ) );
|
||||
$array[self::PROP_NAME] = 'test_value';
|
||||
$this->assertTrue( isset( $array[self::PROP_NAME] ) );
|
||||
$this->assertSame( 'test_value', $array[self::PROP_NAME] );
|
||||
unset( $array[self::PROP_NAME] );
|
||||
$this->assertFalse( isset( $array[self::PROP_NAME] ) );
|
||||
}
|
||||
|
||||
public function testNonDeprecatedNumerical() {
|
||||
$array = new DeprecatablePropertyArray( [], [], __METHOD__ );
|
||||
$this->assertFalse( isset( $array[0] ) );
|
||||
$array[] = 'test_value';
|
||||
$this->assertTrue( isset( $array[0] ) );
|
||||
$this->assertSame( 'test_value', $array[0] );
|
||||
unset( $array[0] );
|
||||
$this->assertFalse( isset( $array[0] ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that $expectedMessage deprecation warning was emitted while
|
||||
* executing the $callback.
|
||||
* @param callable $callback
|
||||
* @param string $expectedMessage
|
||||
*/
|
||||
protected function assertDeprecationWarningIssued(
|
||||
callable $callback,
|
||||
string $expectedMessage
|
||||
) {
|
||||
MWDebug::clearLog();
|
||||
$callback();
|
||||
$wrapper = TestingAccessWrapper::newFromClass( MWDebug::class );
|
||||
$this->assertCount( 1, $wrapper->deprecationWarnings );
|
||||
$this->assertArrayHasKey( $expectedMessage, $wrapper->deprecationWarnings );
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue