Skip to content

Commit 45e57bf

Browse files
authored
Merge pull request #2977 from recursivetree/master
feat: Allow any callable in ->addColumn()
2 parents dc699ab + 69b95d9 commit 45e57bf

File tree

2 files changed

+51
-4
lines changed

2 files changed

+51
-4
lines changed

src/Utilities/Helper.php

Lines changed: 33 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,36 @@ 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+
*
63+
* @throws \ReflectionException
64+
* @throws \InvalidArgumentException
65+
*/
66+
private static function reflectCallableParameters($callable)
67+
{
68+
/*
69+
loosely after https://github.com/technically-php/callable-reflection/blob/main/src/CallableReflection.php#L72-L86.
70+
Licence is compatible, both project use MIT
71+
*/
72+
if ($callable instanceof Closure) {
73+
$reflection = new ReflectionFunction($callable);
74+
} elseif (is_string($callable) && function_exists($callable)) {
75+
$reflection = new ReflectionFunction($callable);
76+
} elseif (is_string($callable) && str_contains($callable, '::')) {
77+
$reflection = new ReflectionMethod($callable);
78+
} elseif (is_object($callable) && method_exists($callable, '__invoke')) {
79+
$reflection = new ReflectionMethod($callable, '__invoke');
80+
} else {
81+
throw new \InvalidArgumentException('argument is not callable or the code is wrong');
82+
}
83+
84+
return $reflection->getParameters();
85+
}
86+
5687
/**
5788
* Determines if content is callable or blade string, processes and returns.
5889
*
@@ -69,9 +100,8 @@ public static function compileContent($content, array $data, array|object $param
69100
return static::compileBlade($content, static::getMixedValue($data, $param));
70101
}
71102

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

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

tests/Unit/HelperTest.php

Lines changed: 18 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,23 @@ 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+
{
121+
public function __invoke($obj)
122+
{
123+
return $obj->id;
124+
}
125+
};
126+
$data = ['id' => 2];
127+
$obj = new stdClass();
128+
$obj->id = 2;
129+
130+
$compiled = Helper::compileContent($content, $data, $obj);
131+
$this->assertEquals(2, $compiled);
132+
}
133+
117134
public function test_compile_blade()
118135
{
119136
$content = '{!! $id !!}';

0 commit comments

Comments
 (0)