Skip to content

Commit

Permalink
Merge pull request #2977 from recursivetree/master
Browse files Browse the repository at this point in the history
feat: Allow any callable in ->addColumn()
  • Loading branch information
yajra authored Mar 28, 2023
2 parents dc699ab + 69b95d9 commit 45e57bf
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 4 deletions.
36 changes: 33 additions & 3 deletions src/Utilities/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use ReflectionFunction;
use ReflectionMethod;

class Helper
{
Expand Down Expand Up @@ -53,6 +54,36 @@ protected static function isItemOrderInvalid($item, $array)
return $item['order'] === false || $item['order'] >= count($array);
}

/**
* Gets the parameter of a callable thing (from is_callable) and returns it's arguments using reflection.
*
* @param callable $callable
* @return \ReflectionParameter[]
*
* @throws \ReflectionException
* @throws \InvalidArgumentException
*/
private static function reflectCallableParameters($callable)
{
/*
loosely after https://github.com/technically-php/callable-reflection/blob/main/src/CallableReflection.php#L72-L86.
Licence is compatible, both project use MIT
*/
if ($callable instanceof Closure) {
$reflection = new ReflectionFunction($callable);
} elseif (is_string($callable) && function_exists($callable)) {
$reflection = new ReflectionFunction($callable);
} elseif (is_string($callable) && str_contains($callable, '::')) {
$reflection = new ReflectionMethod($callable);
} elseif (is_object($callable) && method_exists($callable, '__invoke')) {
$reflection = new ReflectionMethod($callable, '__invoke');
} else {
throw new \InvalidArgumentException('argument is not callable or the code is wrong');
}

return $reflection->getParameters();
}

/**
* Determines if content is callable or blade string, processes and returns.
*
Expand All @@ -69,9 +100,8 @@ public static function compileContent($content, array $data, array|object $param
return static::compileBlade($content, static::getMixedValue($data, $param));
}

if ($content instanceof Closure) {
$reflection = new ReflectionFunction($content);
$arguments = $reflection->getParameters();
if (is_callable($content)) {
$arguments = self::reflectCallableParameters($content);

if (count($arguments) > 0) {
return app()->call($content, [$arguments[0]->name => $param]);
Expand Down
19 changes: 18 additions & 1 deletion tests/Unit/HelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public function test_compile_content_integer()
$this->assertEquals(1, $compiled);
}

public function test_compile_content_callable()
public function test_compile_content_function()
{
$content = function ($obj) {
return $obj->id;
Expand All @@ -114,6 +114,23 @@ public function test_compile_content_callable()
$this->assertEquals(2, $compiled);
}

public function test_compile_content_callable_class()
{
$content = new class
{
public function __invoke($obj)
{
return $obj->id;
}
};
$data = ['id' => 2];
$obj = new stdClass();
$obj->id = 2;

$compiled = Helper::compileContent($content, $data, $obj);
$this->assertEquals(2, $compiled);
}

public function test_compile_blade()
{
$content = '{!! $id !!}';
Expand Down

0 comments on commit 45e57bf

Please sign in to comment.