Skip to content

Commit c9d471a

Browse files
committed
add detection for any callable
add test case fix detection for callable
1 parent dc699ab commit c9d471a

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

src/Utilities/Helper.php

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Illuminate\Support\Arr;
99
use Illuminate\Support\Str;
1010
use ReflectionFunction;
11+
use ReflectionMethod;
1112

1213
class Helper
1314
{
@@ -53,6 +54,35 @@ protected static function isItemOrderInvalid($item, $array)
5354
return $item['order'] === false || $item['order'] >= count($array);
5455
}
5556

57+
/**
58+
* Gets the parameter of a callable thing (from is_callable) and returns it's arguments using reflection
59+
*
60+
* @param callable $callable
61+
* @return \ReflectionParameter[]
62+
* @throws \ReflectionException
63+
* @throws \InvalidArgumentException
64+
*/
65+
private static function reflectCallableParameters($callable)
66+
{
67+
/*
68+
loosely after https://github.com/technically-php/callable-reflection/blob/main/src/CallableReflection.php#L72-L86.
69+
Licence is compatible, both project use MIT
70+
*/
71+
if ($callable instanceof Closure) {
72+
$reflection = new ReflectionFunction($callable);
73+
} else if (is_string($callable) && function_exists($callable)) {
74+
$reflection = new ReflectionFunction($callable);
75+
} else if (is_string($callable) && str_contains($callable, '::')) {
76+
$reflection = new ReflectionMethod($callable);
77+
} else if (is_object($callable) && method_exists($callable, '__invoke')) {
78+
$reflection = new ReflectionMethod($callable, '__invoke');
79+
} else {
80+
throw new \InvalidArgumentException("argument is not callable or the code is wrong");
81+
}
82+
83+
return $reflection->getParameters();
84+
}
85+
5686
/**
5787
* Determines if content is callable or blade string, processes and returns.
5888
*
@@ -69,9 +99,8 @@ public static function compileContent($content, array $data, array|object $param
6999
return static::compileBlade($content, static::getMixedValue($data, $param));
70100
}
71101

72-
if ($content instanceof Closure) {
73-
$reflection = new ReflectionFunction($content);
74-
$arguments = $reflection->getParameters();
102+
if (is_callable($content)) {
103+
$arguments = self::reflectCallableParameters($content);
75104

76105
if (count($arguments) > 0) {
77106
return app()->call($content, [$arguments[0]->name => $param]);

tests/Unit/HelperTest.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public function test_compile_content_integer()
101101
$this->assertEquals(1, $compiled);
102102
}
103103

104-
public function test_compile_content_callable()
104+
public function test_compile_content_function()
105105
{
106106
$content = function ($obj) {
107107
return $obj->id;
@@ -114,6 +114,22 @@ public function test_compile_content_callable()
114114
$this->assertEquals(2, $compiled);
115115
}
116116

117+
public function test_compile_content_callable_class()
118+
{
119+
$content = new class {
120+
public function __invoke($obj)
121+
{
122+
return $obj->id;
123+
}
124+
};
125+
$data = ['id' => 2];
126+
$obj = new stdClass();
127+
$obj->id = 2;
128+
129+
$compiled = Helper::compileContent($content, $data, $obj);
130+
$this->assertEquals(2, $compiled);
131+
}
132+
117133
public function test_compile_blade()
118134
{
119135
$content = '{!! $id !!}';

0 commit comments

Comments
 (0)