diff --git a/rules-tests/Php81/Rector/Array_/ArrayToFirstClassCallableRector/Fixture/some_class_with_own_private.php.inc b/rules-tests/Php81/Rector/Array_/ArrayToFirstClassCallableRector/Fixture/some_class_with_own_private.php.inc new file mode 100644 index 00000000000..f7563cda6f1 --- /dev/null +++ b/rules-tests/Php81/Rector/Array_/ArrayToFirstClassCallableRector/Fixture/some_class_with_own_private.php.inc @@ -0,0 +1,35 @@ + +----- +name(...); + } + + private function name() + { + } +} + +?> diff --git a/rules/Php81/Rector/Array_/ArrayToFirstClassCallableRector.php b/rules/Php81/Rector/Array_/ArrayToFirstClassCallableRector.php index 390cd36d440..7112ac968d8 100644 --- a/rules/Php81/Rector/Array_/ArrayToFirstClassCallableRector.php +++ b/rules/Php81/Rector/Array_/ArrayToFirstClassCallableRector.php @@ -72,6 +72,7 @@ public function name() } } CODE_SAMPLE + , ), ]); } @@ -123,7 +124,7 @@ public function refactor(Node $node): StaticCall|MethodCall|null if ($type instanceof FullyQualifiedObjectType && $this->isNonStaticOtherObject( $type, $arrayCallable, - $scope + $scope, )) { return null; } @@ -133,13 +134,9 @@ public function refactor(Node $node): StaticCall|MethodCall|null $methodName = $arrayCallable->getMethod(); $methodCall = new MethodCall($callerExpr, $methodName, $args); - $classReflection = $this->reflectionResolver->resolveClassReflectionSourceObject($methodCall); - if ($classReflection instanceof ClassReflection && $classReflection->hasNativeMethod($methodName)) { - $method = $classReflection->getNativeMethod($methodName); - if (! $method->isPublic()) { - return null; - } + if ($this->isReferenceToNonPublicMethodOutsideOwningScope($methodCall, $methodName)) { + return null; } return $methodCall; @@ -174,4 +171,25 @@ private function isNonStaticOtherObject( return ! $extendedMethodReflection->isPublic(); } + + private function isReferenceToNonPublicMethodOutsideOwningScope(MethodCall $methodCall, string $methodName): bool + { + if ($methodCall->var instanceof Variable && $methodCall->var->name === 'this') { + // If the callable is scoped to `$this` then it can be converted even if it is protected / private + return false; + } + + // If the callable is scoped to another object / variable then it should only be converted if it is public + // https://github.com/rectorphp/rector/issues/8659 + $classReflection = $this->reflectionResolver->resolveClassReflectionSourceObject($methodCall); + + if ($classReflection instanceof ClassReflection && $classReflection->hasNativeMethod($methodName)) { + $method = $classReflection->getNativeMethod($methodName); + if (! $method->isPublic()) { + return true; + } + } + + return false; + } }