<?php
namespace Yoast\PHPUnitPolyfills\Polyfills;
use PHPUnit\Framework\Assert;
use ReflectionObject;
use TypeError;
use Yoast\PHPUnitPolyfills\Autoload;
/**
* Polyfill the Assert::assertObjectHasProperty() and Assert::assertObjectNotHasProperty() methods,
* which replace the Assert::assertObjectHasAttribute() and Assert::assertObjectNotHasAttribute() methods.
*
* Introduced in PHPUnit 10.1.0.
*
* The Assert::assertObjectHasAttribute() and Assert::assertObjectNotHasAttribute() methods
* were deprecated in PHPUnit 9.6.1 and removed in PHPUnit 10.0.0.
*
* @link https://github.com/sebastianbergmann/phpunit/pull/5231
*
* @since 2.1.0
*/
trait AssertObjectProperty {
/**
* Asserts that an object has a specified property.
*
* @param string $propertyName The name of the property.
* @param object $object The object on which to check whether the property exists.
* @param string $message Optional failure message to display.
*
* @return void
*
* @throws TypeError When any of the passed arguments do not meet the required type.
*/
final public static function assertObjectHasProperty( $propertyName, $object, $message = '' ) {
/*
* Parameter input validation.
* In PHPUnit this is done via PHP native type declarations. Emulating this for the polyfill,
* including for those PHPUnit versions where we hand to a native PHPUnit alternative, as
* otherwise the method referenced in the error message would get very confusing and inconsistent.
*/
if ( \is_string( $propertyName ) === false ) {
throw new TypeError(
\sprintf(
'Argument 1 passed to assertObjectHasProperty() must be of type string, %s given',
\gettype( $propertyName )
)
);
}
if ( \is_object( $object ) === false ) {
throw new TypeError(
\sprintf(
'Argument 2 passed to assertObjectHasProperty() must be of type object, %s given',
\gettype( $object )
)
);
}
if ( \method_exists( Assert::class, 'assertObjectHasAttribute' )
&& \version_compare( Autoload::getPHPUnitVersion(), '9.6.0', '<=' )
) {
// PHPUnit <= 9.6.0.
static::assertObjectHasAttribute( $propertyName, $object, $message );
return;
}
/*
* PHPUnit 9.6.1+ and PHPUnit 10.0.x.
* Note: letting this polyfill code kick in for PHPUnit 9.6.1+ as well
* to prevent the PHPUnit deprecation notice showing.
*/
$msg = self::assertObjectHasPropertyFailureDescription( $object );
$msg .= \sprintf( ' has property "%s".', $propertyName );
if ( $message !== '' ) {
$msg = $message . \PHP_EOL . $msg;
}
$hasProperty = ( new ReflectionObject( $object ) )->hasProperty( $propertyName );
static::assertTrue( $hasProperty, $msg );
}
/**
* Asserts that an object does not have a specified property.
*
* @param string $propertyName The name of the property.
* @param object $object The object on which to check whether the property exists.
* @param string $message Optional failure message to display.
*
* @return void
*
* @throws TypeError When any of the passed arguments do not meet the required type.
*/
final public static function assertObjectNotHasProperty( $propertyName, $object, $message = '' ) {
/*
* Parameter input validation.
* In PHPUnit this is done via PHP native type declarations. Emulating this for the polyfill,
* including for those PHPUnit versions where we hand to a native PHPUnit alternative, as
* otherwise the method referenced in the error message would get very confusing and inconsistent.
*/
if ( \is_string( $propertyName ) === false ) {
throw new TypeError(
\sprintf(
'Argument 1 passed to assertObjectNotHasProperty() must be of type string, %s given',
\gettype( $propertyName )
)
);
}
if ( \is_object( $object ) === false ) {
throw new TypeError(
\sprintf(
'Argument 2 passed to assertObjectNotHasProperty() must be of type object, %s given',
\gettype( $object )
)
);
}
if ( \method_exists( Assert::class, 'assertObjectNotHasAttribute' )
&& \version_compare( Autoload::getPHPUnitVersion(), '9.6.0', '<=' )
) {
// PHPUnit <= 9.6.0.
static::assertObjectNotHasAttribute( $propertyName, $object, $message );
return;
}
/*
* PHPUnit 9.6.1+ and PHPUnit 10.0.x.
* Note: letting this polyfill code kick in for PHPUnit 9.6.1+ as well
* to prevent the PHPUnit deprecation notice showing.
*/
$msg = self::assertObjectHasPropertyFailureDescription( $object );
$msg .= \sprintf( ' does not have property "%s".', $propertyName );
if ( $message !== '' ) {
$msg = $message . \PHP_EOL . $msg;
}
$hasProperty = ( new ReflectionObject( $object ) )->hasProperty( $propertyName );
static::assertFalse( $hasProperty, $msg );
}
/**
* Returns the description of the failure.
*
* @param object $object The object under test.
*
* @return string
*/
private static function assertObjectHasPropertyFailureDescription( $object ) {
return \sprintf(
'Failed asserting that object of class "%s"',
\get_class( $object )
);
}
}