diff --git a/src/Symfony/Component/Messenger/Envelope.php b/src/Symfony/Component/Messenger/Envelope.php index 4d5f7a02a9..6ac9bc7f3c 100644 --- a/src/Symfony/Component/Messenger/Envelope.php +++ b/src/Symfony/Component/Messenger/Envelope.php @@ -86,4 +86,15 @@ final class Envelope { return $this->message; } + + /** + * @param object $target + * + * @return Envelope|object The original message or the envelope if the target supports it + * (i.e implements {@link EnvelopeAwareInterface}). + */ + public function getMessageFor($target) + { + return $target instanceof EnvelopeAwareInterface ? $this : $this->message; + } } diff --git a/src/Symfony/Component/Messenger/Middleware/Enhancers/ActivationMiddlewareDecorator.php b/src/Symfony/Component/Messenger/Middleware/Enhancers/ActivationMiddlewareDecorator.php new file mode 100644 index 0000000000..1c812ccc12 --- /dev/null +++ b/src/Symfony/Component/Messenger/Middleware/Enhancers/ActivationMiddlewareDecorator.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Middleware\Enhancers; + +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\EnvelopeAwareInterface; +use Symfony\Component\Messenger\Middleware\MiddlewareInterface; + +/** + * Execute the inner middleware according to an activation strategy. + * + * @author Maxime Steinhausser + */ +class ActivationMiddlewareDecorator implements MiddlewareInterface, EnvelopeAwareInterface +{ + private $inner; + private $activated; + + /** + * @param bool|callable $activated + */ + public function __construct(MiddlewareInterface $inner, $activated) + { + $this->inner = $inner; + $this->activated = $activated; + } + + /** + * @param Envelope $message + */ + public function handle($message, callable $next) + { + if (\is_callable($this->activated) ? ($this->activated)($message) : $this->activated) { + return $this->inner->handle($message->getMessageFor($this->inner), $next); + } + + return $next($message); + } +} diff --git a/src/Symfony/Component/Messenger/Tests/Middleware/Enhancers/ActivationMiddlewareDecoratorTest.php b/src/Symfony/Component/Messenger/Tests/Middleware/Enhancers/ActivationMiddlewareDecoratorTest.php new file mode 100644 index 0000000000..32b4a7d0f2 --- /dev/null +++ b/src/Symfony/Component/Messenger/Tests/Middleware/Enhancers/ActivationMiddlewareDecoratorTest.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Tests\Middleware\Enhancers; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\EnvelopeAwareInterface; +use Symfony\Component\Messenger\Middleware\Enhancers\ActivationMiddlewareDecorator; +use Symfony\Component\Messenger\Middleware\MiddlewareInterface; +use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; + +/** + * @author Maxime Steinhausser + */ +class ActivationMiddlewareDecoratorTest extends TestCase +{ + public function testExecuteMiddlewareOnActivated() + { + $message = new DummyMessage('Hello'); + $envelope = Envelope::wrap($message); + + $next = $this->createPartialMock(\stdClass::class, array('__invoke')); + $next->expects($this->never())->method('__invoke'); + + $middleware = $this->createMock(MiddlewareInterface::class); + $middleware->expects($this->once())->method('handle')->with($message, $next)->willReturn('Hello from middleware'); + + $decorator = new ActivationMiddlewareDecorator($middleware, true); + + $this->assertSame('Hello from middleware', $decorator->handle($envelope, $next)); + } + + public function testExecuteMiddlewareOnActivatedWithCallable() + { + $message = new DummyMessage('Hello'); + $envelope = Envelope::wrap($message); + + $activated = $this->createPartialMock(\stdClass::class, array('__invoke')); + $activated->expects($this->once())->method('__invoke')->with($envelope)->willReturn(true); + + $next = $this->createPartialMock(\stdClass::class, array('__invoke')); + $next->expects($this->never())->method('__invoke'); + + $middleware = $this->createMock(MiddlewareInterface::class); + $middleware->expects($this->once())->method('handle')->with($message, $next)->willReturn('Hello from middleware'); + + $decorator = new ActivationMiddlewareDecorator($middleware, $activated); + + $this->assertSame('Hello from middleware', $decorator->handle($envelope, $next)); + } + + public function testExecuteEnvelopeAwareMiddlewareWithEnvelope() + { + $message = new DummyMessage('Hello'); + $envelope = Envelope::wrap($message); + + $next = $this->createPartialMock(\stdClass::class, array('__invoke')); + $next->expects($this->never())->method('__invoke'); + + $middleware = $this->createMock(array(MiddlewareInterface::class, EnvelopeAwareInterface::class)); + $middleware->expects($this->once())->method('handle')->with($envelope, $next)->willReturn('Hello from middleware'); + + $decorator = new ActivationMiddlewareDecorator($middleware, true); + + $this->assertSame('Hello from middleware', $decorator->handle($envelope, $next)); + } + + public function testExecuteMiddlewareOnDeactivated() + { + $message = new DummyMessage('Hello'); + $envelope = Envelope::wrap($message); + + $next = $this->createPartialMock(\stdClass::class, array('__invoke')); + $next->expects($this->once())->method('__invoke')->with($envelope)->willReturn('Hello from $next'); + + $middleware = $this->createMock(MiddlewareInterface::class); + $middleware->expects($this->never())->method('handle'); + + $decorator = new ActivationMiddlewareDecorator($middleware, false); + + $this->assertSame('Hello from $next', $decorator->handle($envelope, $next)); + } +}