Skip to content

Commit

Permalink
add isCallable helper
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell committed Oct 27, 2020
1 parent 302766f commit 8c16891
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/Illuminate/Support/Reflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,52 @@
namespace Illuminate\Support;

use ReflectionClass;
use ReflectionMethod;
use ReflectionNamedType;

class Reflector
{
/**
* This is a PHP 7.4 compatible implementation of is_callable.
*
* @param mixed $var
* @param bool $syntaxOnly
* @return bool
*/
public static function isCallable($var, $syntaxOnly = false)
{
if (! is_array($var)) {
return is_callable($var, $syntaxOnly);
}

if (! isset($var[0]) && ! isset($var[1]) ||
! is_string($var[1])) {
return false;
}

$class = is_object($var[0]) ? get_class($var[0]) : $var[0];

$method = $var[1];

if (! class_exists($class)) {
return false;
}

if (method_exists($class, $method)) {
return (new ReflectionMethod($class, $method))->isPublic();
}

if (is_object($var[0]) && method_exists($class, '__call')) {
return (new ReflectionMethod($class, '__call'))->isPublic();
}

if (! is_object($var[0]) && method_exists($class, '__callStatic')) {
return (new ReflectionMethod($class, '__callStatic'))->isPublic();
}

return false;
}

/**
* Get the class name of the given parameter's type, if possible.
*
Expand Down
26 changes: 26 additions & 0 deletions tests/Support/SupportReflectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ public function testUnionTypeName()

$this->assertNull(Reflector::getParameterClassName($method->getParameters()[0]));
}

public function testIsCallable()
{
$this->assertTrue(Reflector::isCallable(function () {}));
$this->assertTrue(Reflector::isCallable([B::class, 'f']));
$this->assertFalse(Reflector::isCallable([TestClassWithCall::class, 'f']));
$this->assertTrue(Reflector::isCallable([new TestClassWithCall, 'f']));
$this->assertTrue(Reflector::isCallable([TestClassWithCallStatic::class, 'f']));
$this->assertFalse(Reflector::isCallable([new TestClassWithCallStatic, 'f']));
}
}

class A
Expand All @@ -82,3 +92,19 @@ public function f(A|Model $x)
}'
);
}

class TestClassWithCall
{
public function __call($method, $parameters)
{

}
}

class TestClassWithCallStatic
{
public static function __callStatic($method, $parameters)
{

}
}

0 comments on commit 8c16891

Please sign in to comment.