MDL-80677 core: Deprecation attribute can apply to interfaces and traits

This commit is contained in:
Andrew Nicols 2024-03-12 09:07:03 +08:00
parent f09d886f11
commit ad9322aba2
No known key found for this signature in database
GPG Key ID: 6D1E3157C8CFBF14
3 changed files with 119 additions and 4 deletions

View File

@ -45,7 +45,7 @@ class deprecation {
return self::from(explode('::', $reference));
}
if (class_exists($reference)) {
if (class_exists($reference) || interface_exists($reference) || trait_exists($reference)) {
// The reference looks to be a class name.
return self::from([$reference]);
}
@ -75,9 +75,11 @@ class deprecation {
return self::from_reflected_object($rc, $reference[1] ?? null);
}
if (is_string($reference[0]) && class_exists($reference[0])) {
$rc = new \ReflectionClass($reference[0]);
return self::from_reflected_object($rc, $reference[1] ?? null);
if (is_string($reference[0])) {
if (class_exists($reference[0]) || interface_exists($reference[0]) || trait_exists($reference[0])) {
$rc = new \ReflectionClass($reference[0]);
return self::from_reflected_object($rc, $reference[1] ?? null);
}
}
// The reference is an array, but it's not an object or a class that currently exists.
@ -152,6 +154,20 @@ class deprecation {
return $classattribute;
}
// Check for any deprecated interfaces.
foreach ($rc->getInterfaces() as $interface) {
if ($attribute = self::get_attribute($interface, $interface->name)) {
return $attribute;
}
}
// And any deprecated traits.
foreach ($rc->getTraits() as $trait) {
if ($attribute = self::get_attribute($trait, $trait->name)) {
return $attribute;
}
}
if ($rc->hasConstant($name)) {
// This class has a constant with the specified name.
// Note: This also applies to enums.

View File

@ -226,16 +226,36 @@ class deprecation_test extends \advanced_testcase {
return [
// Classes.
[\core\fixtures\deprecated_class::class, true],
[\core\fixtures\deprecated_interface::class, true],
[\core\fixtures\deprecated_trait::class, true],
[[\core\fixtures\deprecated_class::class], true],
[[\core\fixtures\deprecated_interface::class], true],
[[\core\fixtures\deprecated_trait::class], true],
[\core\fixtures\not_deprecated_class_using_deprecated_trait_features::class, false],
[[\core\fixtures\not_deprecated_class_using_deprecated_trait_features::class], false],
[\core\fixtures\not_deprecated_class::class, false],
[\core\fixtures\not_deprecated_interface::class, false],
[\core\fixtures\not_deprecated_trait::class, false],
[[\core\fixtures\not_deprecated_class::class], false],
[[\core\fixtures\not_deprecated_interface::class], false],
[[\core\fixtures\not_deprecated_trait::class], false],
// Class properties in a deprecated class.
[\core\fixtures\deprecated_class::class . '::deprecatedproperty', true],
[[\core\fixtures\deprecated_class::class, 'deprecatedproperty'], true],
[\core\fixtures\not_deprecated_class_using_deprecated_trait_features::class . '::deprecatedproperty', true],
[[\core\fixtures\not_deprecated_class_using_deprecated_trait_features::class, 'deprecatedproperty'], true],
[\core\fixtures\not_deprecated_class_using_not_deprecated_trait_features::class . '::deprecatedproperty', true],
[[\core\fixtures\not_deprecated_class_using_not_deprecated_trait_features::class, 'deprecatedproperty'], true],
[\core\fixtures\deprecated_class::class . '::notdeprecatedproperty', true],
[[\core\fixtures\deprecated_class::class, 'notdeprecatedproperty'], true],
[\core\fixtures\not_deprecated_class_using_deprecated_trait_features::class . '::notdeprecatedproperty', true],
[[\core\fixtures\not_deprecated_class_using_deprecated_trait_features::class, 'notdeprecatedproperty'], true],
[\core\fixtures\not_deprecated_class_using_not_deprecated_trait_features::class . '::notdeprecatedproperty', false],
[[\core\fixtures\not_deprecated_class_using_not_deprecated_trait_features::class, 'notdeprecatedproperty'], false],
// Class constants in a deprecated class.
[\core\fixtures\deprecated_class::class . '::DEPRECATED_CONST', true],
@ -248,9 +268,19 @@ class deprecation_test extends \advanced_testcase {
[\core\fixtures\deprecated_class::class . '::deprecated_method', true],
[[\core\fixtures\deprecated_class::class, 'deprecated_method'], true],
[\core\fixtures\not_deprecated_class_using_deprecated_trait_features::class . '::deprecated_method', true],
[[\core\fixtures\not_deprecated_class_using_deprecated_trait_features::class, 'deprecated_method'], true],
[\core\fixtures\not_deprecated_class_using_not_deprecated_trait_features::class . '::deprecated_method', true],
[[\core\fixtures\not_deprecated_class_using_not_deprecated_trait_features::class, 'deprecated_method'], true],
[\core\fixtures\deprecated_class::class . '::not_deprecated_method', true],
[[\core\fixtures\deprecated_class::class, 'not_deprecated_method'], true],
[\core\fixtures\not_deprecated_class_using_deprecated_trait_features::class . '::not_deprecated_method', true],
[[\core\fixtures\not_deprecated_class_using_deprecated_trait_features::class, 'not_deprecated_method'], true],
[\core\fixtures\not_deprecated_class_implementing_deprecated_interface::class . '::not_deprecated_method', true],
[[\core\fixtures\not_deprecated_class_implementing_deprecated_interface::class, 'not_deprecated_method'], true],
// Class properties in a not-deprecated class.
[\core\fixtures\not_deprecated_class::class . '::deprecatedproperty', true],
[[\core\fixtures\not_deprecated_class::class, 'deprecatedproperty'], true],
@ -265,6 +295,12 @@ class deprecation_test extends \advanced_testcase {
[\core\fixtures\not_deprecated_class::class . '::NOT_DEPRECATED_CONST', false],
[[\core\fixtures\not_deprecated_class::class, 'NOT_DEPRECATED_CONST'], false],
[\core\fixtures\not_deprecated_interface::class . '::DEPRECATED_CONST', true],
[[\core\fixtures\not_deprecated_interface::class, 'DEPRECATED_CONST'], true],
[\core\fixtures\not_deprecated_interface::class . '::NOT_DEPRECATED_CONST', false],
[[\core\fixtures\not_deprecated_interface::class, 'NOT_DEPRECATED_CONST'], false],
// Class methods in a not-deprecated class.
[\core\fixtures\not_deprecated_class::class . '::deprecated_method', true],
[[\core\fixtures\not_deprecated_class::class, 'deprecated_method'], true],

View File

@ -71,3 +71,66 @@ function not_deprecated_function() {
#[deprecated('not_deprecated_class::not_deprecated_method()')]
function deprecated_function() {
}
interface not_deprecated_interface {
const NOT_DEPRECATED_CONST = 'Not deprecated const';
#[deprecated('self::NOT_DEPRECATED_CONST')]
const DEPRECATED_CONST = 'Deprecated const';
// Note: It does not make sense to deprecate methods in an _interface_ as the interface itself should be deprecated.
}
#[deprecated('not_deprecated_interface')]
interface deprecated_interface {
const DEPRECATED_CONST = 'Deprecated const';
public function not_deprecated_method();
}
trait not_deprecated_trait {
protected string $notdeprecatedproperty = 'Not deprecated property';
#[deprecated('$this->notdeprecatedproperty')]
protected string $deprecatedproperty = 'Deprecated property';
public function not_deprecated_method() {
}
#[deprecated('$this->not_deprecated_method()')]
public function deprecated_method() {
}
}
#[deprecated(not_deprecated_trait::class)]
trait deprecated_trait {
protected string $notdeprecatedproperty = 'Not deprecated property';
#[deprecated('$this->notdeprecatedproperty')]
protected string $deprecatedproperty = 'Deprecated property';
public function not_deprecated_method() {
}
#[deprecated(replacement: null, mdl: 'MDL-80677')]
public function deprecated_method() {
}
}
class not_deprecated_class_using_deprecated_trait_features {
use deprecated_trait;
}
class not_deprecated_class_implementing_deprecated_interface implements deprecated_interface {
public function not_deprecated_method() {
}
}
class not_deprecated_class_using_not_deprecated_trait_features {
use not_deprecated_trait;
}
class not_deprecated_class_implementing_not_deprecated_interface implements not_deprecated_interface {
public function not_deprecated_method() {
}
}