Skip to content

Commit

Permalink
HandledStamp::fromCallable() factory
Browse files Browse the repository at this point in the history
  • Loading branch information
ogizanagi committed Nov 11, 2018
1 parent c1308e6 commit 6cd29ca
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 37 deletions.
Expand Up @@ -42,48 +42,12 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope
$handler = null;
$message = $envelope->getMessage();
foreach ($this->handlersLocator->getHandlers($envelope) as $handler) {
$envelope = $envelope->with(new HandledStamp($handler($message), $this->formatCallable($handler)));
$envelope = $envelope->with(HandledStamp::fromCallable($handler, $handler($message)));
}
if (null === $handler && !$this->allowNoHandlers) {
throw new NoHandlerForMessageException(sprintf('No handler for message "%s".', \get_class($envelope->getMessage())));
}

return $stack->next()->handle($envelope, $stack);
}

private function formatCallable(callable $callable): ?string
{
if (\is_array($callable)) {
if (\is_object($callable[0])) {
return sprintf('%s::%s()', \get_class($callable[0]), $callable[1]);
}

return sprintf('%s::%s()', $callable[0], $callable[1]);
}

if (\is_string($callable)) {
return sprintf('%s()', $callable);
}

if ($callable instanceof \Closure) {
$r = new \ReflectionFunction($callable);
if (false !== strpos($r->name, '{closure}')) {
return 'Closure()';
}
if ($class = $r->getClosureScopeClass()) {
return sprintf('%s::%s()', $class, $r->name);
}
if ($class = $r->getClosureThis()) {
return sprintf('%s::%s()', \get_class($class), $r->name);
}

return $r->name.'()';
}

if (method_exists($callable, '__invoke')) {
return sprintf('%s::__invoke()', \get_class($callable));
}

return null;
}
}
33 changes: 33 additions & 0 deletions src/Symfony/Component/Messenger/Stamp/HandledStamp.php
Expand Up @@ -36,6 +36,39 @@ public function __construct($result, string $handler = null)
$this->handler = $handler;
}

public static function fromCallable(callable $handler, $result): self
{
if (\is_array($handler)) {
if (\is_object($handler[0])) {
return new self($result, sprintf('%s::%s()', \get_class($handler[0]), $handler[1]));
}

return new self($result, sprintf('%s::%s()', $handler[0], $handler[1]));
}

if (\is_string($handler)) {
return new self($result, sprintf('%s()', $handler));
}

if ($handler instanceof \Closure) {
$r = new \ReflectionFunction($handler);
if (false !== strpos($r->name, '{closure}')) {
return new self($result, 'Closure()');
}
if ($class = $r->getClosureScopeClass()) {
return new self($result, sprintf('%s::%s()', $class->getName(), $r->name));
}

return new self($result, $r->name.'()');
}

if (method_exists($handler, '__invoke')) {
return new self($result, sprintf('%s::__invoke()', \get_class($handler)));
}

return new self($result);
}

public function getResult()
{
return $this->result;
Expand Down
53 changes: 53 additions & 0 deletions src/Symfony/Component/Messenger/Tests/Stamp/HandledStampTest.php
@@ -0,0 +1,53 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Messenger\Tests\Stamp;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Stamp\HandledStamp;
use Symfony\Component\Messenger\Tests\Fixtures\DummyCommandHandler;

class HandledStampTest extends TestCase
{
/**
* @dataProvider provideCallables
*/
public function testFromCallable(callable $handler, ?string $expectedHandlerString)
{
$this->assertStringMatchesFormat($expectedHandlerString, HandledStamp::fromCallable($handler, null)->getHandler());
}

public function provideCallables()
{
yield array(function () {}, 'Closure()');
yield array('var_dump', 'var_dump()');
yield array(new DummyCommandHandler(), DummyCommandHandler::class.'::__invoke()');
yield array(
array(new DummyCommandHandlerWithSpecificMethod(), 'handle'),
DummyCommandHandlerWithSpecificMethod::class.'::handle()',
);
yield array(\Closure::fromCallable(function () {}), 'Closure()');
yield array(\Closure::fromCallable(new DummyCommandHandler()), DummyCommandHandler::class.'::__invoke()');
yield array(\Closure::bind(\Closure::fromCallable(function () {}), new \stdClass()), 'Closure()');
yield array(new class() {
public function __invoke()
{
}
}, 'class@anonymous%sHandledStampTest.php%s::__invoke()');
}
}

class DummyCommandHandlerWithSpecificMethod
{
public function handle(): void
{
}
}

0 comments on commit 6cd29ca

Please sign in to comment.