diff --git a/framework/core/src/Foundation/ContainerUtil.php b/framework/core/src/Foundation/ContainerUtil.php index bc566802d..1c5b95972 100644 --- a/framework/core/src/Foundation/ContainerUtil.php +++ b/framework/core/src/Foundation/ContainerUtil.php @@ -24,10 +24,10 @@ class ContainerUtil public static function wrapCallback($callback, Container $container) { if (is_string($callback)) { - $callback = function () use ($container, $callback) { + $callback = function (&...$args) use ($container, $callback) { $callback = $container->make($callback); - return call_user_func_array($callback, func_get_args()); + return $callback(...$args); }; } diff --git a/framework/core/tests/unit/Foundation/ContainerUtilTest.php b/framework/core/tests/unit/Foundation/ContainerUtilTest.php new file mode 100644 index 000000000..f7b8a2992 --- /dev/null +++ b/framework/core/tests/unit/Foundation/ContainerUtilTest.php @@ -0,0 +1,140 @@ +container = new Container(); + } + + /** @test */ + public function it_works_with_closures() + { + $callback = ContainerUtil::wrapCallback(function ($array) { + $array['key'] = 'newValue'; + + return 'return'; + }, $this->container); + + $array = ['key' => 'value']; + $return = $callback($array); + + $this->assertEquals('value', $array['key']); + $this->assertEquals('return', $return); + } + + /** @test */ + public function it_works_with_invokable_classes() + { + $callback = ContainerUtil::wrapCallback(CustomInvokableClass::class, $this->container); + + $array = ['key' => 'value2']; + $return = $callback($array); + + $this->assertEquals('value2', $array['key']); + $this->assertEquals('return2', $return); + } + + /** @test */ + public function it_works_with_invokable_objects() + { + $callback = ContainerUtil::wrapCallback(new class { + public function __invoke($array) + { + $array['key'] = 'newValue5'; + + return 'return5'; + } + }, $this->container); + + $array = ['key' => 'value5']; + $return = $callback($array); + + $this->assertEquals('value5', $array['key']); + $this->assertEquals('return5', $return); + } + + /** @test */ + public function it_allows_passing_args_by_reference_on_closures() + { + $callback = ContainerUtil::wrapCallback(function (&$array) { + $array['key'] = 'newValue3'; + + return 'return3'; + }, $this->container); + + $array = ['key' => 'value3']; + $return = $callback($array); + + $this->assertEquals('newValue3', $array['key']); + $this->assertEquals('return3', $return); + } + + /** @test */ + public function it_allows_passing_args_by_reference_on_invokable_classes() + { + $callback = ContainerUtil::wrapCallback(SecondCustomInvokableClass::class, $this->container); + + $array = ['key' => 'value4']; + $return = $callback($array); + + $this->assertEquals('newValue4', $array['key']); + $this->assertEquals('return4', $return); + } + + /** @test */ + public function it_allows_passing_args_by_reference_on_invokable_objects() + { + $callback = ContainerUtil::wrapCallback(new class { + public function __invoke(&$array) + { + $array['key'] = 'newValue6'; + + return 'return6'; + } + }, $this->container); + + $array = ['key' => 'value6']; + $return = $callback($array); + + $this->assertEquals('newValue6', $array['key']); + $this->assertEquals('return6', $return); + } +} + +class CustomInvokableClass +{ + public function __invoke($array) + { + $array['key'] = 'newValue2'; + + return 'return2'; + } +} + +class SecondCustomInvokableClass +{ + public function __invoke(&$array) + { + $array['key'] = 'newValue4'; + + return 'return4'; + } +}