Skip to content

Commit

Permalink
PropertyIterateUtil is now compatible with php 8.4
Browse files Browse the repository at this point in the history
  • Loading branch information
pjordaan committed Jan 5, 2025
1 parent cfadb86 commit 2df894d
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 48 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
php-version: '8.4'
coverage: pcov
ini-values: pcov.directory=src
- uses: actions/checkout@v2
Expand Down
50 changes: 5 additions & 45 deletions src/ReflectionTypeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,57 +17,17 @@ final class ReflectionTypeFactory
*/
private static array $alreadyCreated = [];

/**
* @codeCoverageIgnore
*/
private static function dummy(): string|false|null
{
return null;
}

private static function createNullType(): ReflectionType
{
$refl = new ReflectionMethod(__CLASS__, 'dummy');
return $refl->getReturnType()->getTypes()[2];
}

private static function createFalseType(): ReflectionType
{
$refl = new ReflectionMethod(__CLASS__, 'dummy');
return $refl->getReturnType()->getTypes()[1];
}

private static function createTrueType(): ReflectionType
{
if (PHP_VERSION_ID < 80200) {
throw new LogicException('true typehint not supported in PHP < 8.2');
}
$fakeClass = eval(
'return new class { public function method(): string|true {} };'
);
$refl = new ReflectionClass($fakeClass);
return $refl->getMethod('method')->getReturnType()->getTypes()[1];
}

public static function createReflectionType(string $typehint): ReflectionType
{
if (strpos($typehint, ';') !== false || strpos($typehint, '/') !== false) {
throw new RuntimeException('Are you trying to exploit this evil method?');
}
if (!isset(self::$alreadyCreated[$typehint])) {
if ($typehint === 'null') {
self::$alreadyCreated[$typehint] = self::createNullType();
} elseif ($typehint === 'false') {
self::$alreadyCreated[$typehint] = self::createFalseType();
} elseif ($typehint === 'true') {
self::$alreadyCreated[$typehint] = self::createTrueType();
} else {
$fakeClass = eval(
'return new class { public function method(): ' . $typehint . '{} };'
);
$refl = new ReflectionClass($fakeClass);
self::$alreadyCreated[$typehint] = $refl->getMethod('method')->getReturnType();
}
$fakeClass = eval(
'return new class { public function method(): ' . $typehint . '{} };'
);
$refl = new ReflectionClass($fakeClass);
self::$alreadyCreated[$typehint] = $refl->getMethod('method')->getReturnType();
}
return self::$alreadyCreated[$typehint];
}
Expand Down
16 changes: 14 additions & 2 deletions src/Utils/PropertyIterateUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,15 @@ public static function getReadProperties(ReflectionClass $class): array
{
$result = [];
foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $property) {
$result[$property->name] = $property->getType() ?? ReflectionTypeFactory::createReflectionType('mixed');
if (PHP_VERSION_ID >= 80400 && $property->isVirtual()) {
$method = $property->getHook(\PropertyHookType::Get);
if ($method === null) {
continue;
}
$result[$property->name] = $method->getReturnType() ?? ReflectionTypeFactory::createReflectionType('mixed');
} else {
$result[$property->name] = $property->getType() ?? ReflectionTypeFactory::createReflectionType('mixed');
}
}
foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
if ($method->isStatic()) {
Expand All @@ -48,7 +56,11 @@ public static function getWriteProperties(ReflectionClass $class): array
if ($property->isReadOnly()) {
continue;
}
$result[$property->name] = $property->getType() ?? ReflectionTypeFactory::createReflectionType('mixed');
$type = PHP_VERSION_ID >= 80400 ? $property->getSettableType() : $property->getType();
if ((string) $type === 'never') {
continue;
}
$result[$property->name] = $type ?? ReflectionTypeFactory::createReflectionType('mixed');
}
foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
if ($method->isStatic()) {
Expand Down

0 comments on commit 2df894d

Please sign in to comment.