diff --git a/examples/ButtonCallback.php b/examples/ButtonCallback.php index c4dbb26..e70618e 100644 --- a/examples/ButtonCallback.php +++ b/examples/ButtonCallback.php @@ -12,7 +12,7 @@ class ButtonCallback extends CallbackCommand protected string $name = 'button1'; protected string $description = 'Button 1 callback'; protected array $middlewares = [ - EchoPayload::class, + EchoPayload::class . ':This is the example param', ]; public function execute(array $args = []) @@ -38,14 +38,29 @@ public function execute(array $args = []) } } +/** + * This payload format the params sent in the callback query as + * Received new payload: "payload" + */ class EchoPayload extends Middleware { + public function __construct(private string $exampleParam = '') + { + } + /** * @throws StopCommand Stop execution command if payload is empty */ public function __invoke(Context $ctx, Api $api, array $args = []) { - var_dump('Old results: ', $args); + $ctx->logger?->debug( + message: 'Old results: {args}', + context: ['args' => json_encode($args)] + ); + $ctx->logger?->debug( + message: 'Param passed to the middleware: {param}', + context: ['param' => $this->exampleParam] + ); $message = 'Received new payload: "%s"'; if (empty($ctx->getPayload())) { diff --git a/src/Events/abstractEvent.php b/src/Events/abstractEvent.php index e8eaa1e..3eedd92 100644 --- a/src/Events/abstractEvent.php +++ b/src/Events/abstractEvent.php @@ -6,6 +6,7 @@ use Closure; use Mateodioev\Bots\Telegram\Api; +use Mateodioev\TgHandler\BotException; use Mateodioev\TgHandler\Db\{DbInterface, PrefixDb}; use Mateodioev\TgHandler\Filters\{Filter, FilterCollection}; use Mateodioev\TgHandler\{Bot, Context, Middleware\ClosureMiddleware, Middleware\Middleware}; @@ -14,7 +15,12 @@ use ReflectionException; use Revolt\EventLoop; +use Throwable; + use function Amp\delay; +use function class_exists; +use function explode; +use function is_callable; abstract class abstractEvent implements EventInterface { @@ -171,12 +177,11 @@ public function middlewares(): array $middlewares = []; foreach ($this->middlewares as $i => $middleware) { if ($middleware instanceof Closure) { - $middlewares[(string) $i] = ClosureMiddleware::create($middleware) - ->withId($i); + $middlewares[(string) $i] = ClosureMiddleware::create($middleware)->withId($i); continue; } if (is_string($middleware)) { - $middleware = new $middleware(); + $middleware = $this->createMiddlewareFromString($middleware); $middlewares[$middleware->name()] = $middleware; continue; } @@ -192,6 +197,32 @@ public function middlewares(): array return $this->middlewares; } + private function createMiddlewareFromString(string $strMiddleware): Middleware + { + [$className, $parts] = explode(':', "$strMiddleware:"); // add ":" to avoid errors + + $existsClass = class_exists($className); + if (!$existsClass && is_callable($className)) { + // Parts are not needed for closures + return ClosureMiddleware::create($className); + } + if ($existsClass === false) { + throw new BotException("Middleware class $className not found"); + } + + $parts = explode(',', $parts); + + if (empty($parts)) { + return new $className(); + } + + try { + return new $className(...$parts); + } catch (Throwable $th) { + throw new BotException("Error creating middleware $className: " . $th->getMessage()); + } + } + /** * @throws ReflectionException */ diff --git a/tests/Events/MiddlewareTest.php b/tests/Events/MiddlewareTest.php index b731dc4..6e67846 100644 --- a/tests/Events/MiddlewareTest.php +++ b/tests/Events/MiddlewareTest.php @@ -7,7 +7,6 @@ use Mateodioev\Bots\Telegram\Api; use Mateodioev\TgHandler\Context; use Mateodioev\TgHandler\Events\Types\AllEvent; - use Mateodioev\TgHandler\Middleware\{ClosureMiddleware, Middleware}; use Monolog\Test\TestCase; @@ -72,6 +71,23 @@ public function testGetEventMiddleware() } } + public function testMiddlewareWithParams() + { + $middleware = $this->createMiddlewareWithParams('param'); + $this->assertIsString($middleware->name()); + $this->assertEquals('param', $middleware->name()); + + $event = $this->createEvent(); + $event->addMiddleware($middleware); + + $this->assertNotEmpty($event->middlewares()); + $this->assertEquals(1, count($event->middlewares())); + $this->assertIsArray($event->middlewares()); + + $this->assertIsString($event->middlewares()['param']->name()); + $this->assertEquals('param', $event->middlewares()['param']->name()); + } + private function createMiddleware() { return new class () extends Middleware { @@ -96,4 +112,24 @@ public function execute(array $args = []) } }; } + + private function createMiddlewareWithParams(string $param) + { + return new class ($param) extends Middleware { + public function __construct( + private string $param + ) { + } + + public function __invoke(Context $ctx, Api $api, array $args = []) + { + return $this->param; + } + + public function name(): string + { + return $this->param; // Use the param passed + } + }; + } }