From 9e0e04259c055298edccdf1aea48ca90d40bf94b Mon Sep 17 00:00:00 2001 From: MrYamous Date: Wed, 1 Jan 2025 09:30:21 +0100 Subject: [PATCH] use config to create final webhook classes --- src/Maker/MakeWebhook.php | 68 ++++++++++++----------- templates/webhook/RequestParser.tpl.php | 6 +- templates/webhook/WebhookConsumer.tpl.php | 8 +-- tests/Maker/MakeWebhookTest.php | 30 ++++++++++ 4 files changed, 71 insertions(+), 41 deletions(-) diff --git a/src/Maker/MakeWebhook.php b/src/Maker/MakeWebhook.php index a7b3f2423..49a182d99 100644 --- a/src/Maker/MakeWebhook.php +++ b/src/Maker/MakeWebhook.php @@ -19,9 +19,7 @@ use Symfony\Bundle\MakerBundle\InputAwareMakerInterface; use Symfony\Bundle\MakerBundle\InputConfiguration; use Symfony\Bundle\MakerBundle\Maker\Common\InstallDependencyTrait; -use Symfony\Bundle\MakerBundle\Str; -use Symfony\Bundle\MakerBundle\Util\ClassNameDetails; -use Symfony\Bundle\MakerBundle\Util\UseStatementGenerator; +use Symfony\Bundle\MakerBundle\Util\ClassSource\Model\ClassData; use Symfony\Bundle\MakerBundle\Util\YamlSourceManipulator; use Symfony\Bundle\MakerBundle\Validator; use Symfony\Component\Console\Command\Command; @@ -146,21 +144,37 @@ public function interact(InputInterface $input, ConsoleStyle $io, Command $comma public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator): void { - $requestParserDetails = $this->generator->createClassNameDetails( - Str::asClassName($this->name.'RequestParser'), - 'Webhook\\' + $requestParserClassData = ClassData::create( + class: \sprintf('Webhook\\%s', $input->getArgument('name')), + suffix: 'RequestParser', + extendsClass: AbstractRequestParser::class, + useStatements: [ + JsonException::class, + Request::class, + Response::class, + RemoteEvent::class, + AbstractRequestParser::class, + RejectWebhookException::class, + RequestMatcherInterface::class, + ], ); - $remoteEventConsumerDetails = $this->generator->createClassNameDetails( - Str::asClassName($this->name.'WebhookConsumer'), - 'RemoteEvent\\' + + $remoteEventClassData = ClassData::create( + class: \sprintf('RemoteEvent\\%s', $input->getArgument('name')), + suffix: 'WebhookConsumer', + useStatements: [ + AsRemoteEventConsumer::class, + ConsumerInterface::class, + RemoteEvent::class, + ], ); - $this->addToYamlConfig($this->name, $requestParserDetails); + $this->addToYamlConfig($this->name, $requestParserClassData); - $this->generateRequestParser(requestParserDetails: $requestParserDetails); + $this->generateRequestParser($requestParserClassData); - $this->generator->generateClass( - $remoteEventConsumerDetails->getFullName(), + $this->generator->generateClassFromClassData( + $remoteEventClassData, 'webhook/WebhookConsumer.tpl.php', [ 'webhook_name' => $this->name, @@ -178,7 +192,7 @@ private function verifyWebhookName(string $entityName): bool return preg_match(self::WEBHOOK_NAME_PATTERN, $entityName); } - private function addToYamlConfig(string $webhookName, ClassNameDetails $requestParserDetails): void + private function addToYamlConfig(string $webhookName, ClassData $requestParserClassData): void { $yamlConfig = Yaml::dump(['framework' => ['webhook' => ['routing' => []]]], 4, 2); if ($this->fileManager->fileExists(self::WEBHOOK_CONFIG_PATH)) { @@ -193,7 +207,7 @@ private function addToYamlConfig(string $webhookName, ClassNameDetails $requestP } $arrayConfig['framework']['webhook']['routing'][$webhookName] = [ - 'service' => $requestParserDetails->getFullName(), + 'service' => $requestParserClassData->getFullClassName(), 'secret' => 'your_secret_here', ]; $this->ysm->setData( @@ -204,43 +218,31 @@ private function addToYamlConfig(string $webhookName, ClassNameDetails $requestP /** * @throws \Exception */ - private function generateRequestParser(ClassNameDetails $requestParserDetails): void + private function generateRequestParser(ClassData $requestParserClassData): void { - $useStatements = new UseStatementGenerator([ - JsonException::class, - Request::class, - Response::class, - RemoteEvent::class, - AbstractRequestParser::class, - RejectWebhookException::class, - RequestMatcherInterface::class, - ]); - // Use a ChainRequestMatcher if multiple matchers have been added OR if none (will be printed with an empty array) $useChainRequestsMatcher = false; if (1 !== \count($this->requestMatchers)) { $useChainRequestsMatcher = true; - $useStatements->addUseStatement(ChainRequestMatcher::class); + $requestParserClassData->addUseStatement(ChainRequestMatcher::class); } $requestMatcherArguments = []; foreach ($this->requestMatchers as $requestMatcherClass) { - $useStatements->addUseStatement($requestMatcherClass); + $requestParserClassData->addUseStatement($requestMatcherClass); $requestMatcherArguments[$requestMatcherClass] = $this->getRequestMatcherArguments(requestMatcherClass: $requestMatcherClass); if (ExpressionRequestMatcher::class === $requestMatcherClass) { - $useStatements->addUseStatement(Expression::class); - $useStatements->addUseStatement(ExpressionLanguage::class); + $requestParserClassData->addUseStatement([Expression::class, ExpressionLanguage::class]); } } - $this->generator->generateClass( - $requestParserDetails->getFullName(), + $this->generator->generateClassFromClassData( + $requestParserClassData, 'webhook/RequestParser.tpl.php', [ - 'use_statements' => $useStatements, 'use_chained_requests_matcher' => $useChainRequestsMatcher, 'request_matchers' => $this->requestMatchers, 'request_matcher_arguments' => $requestMatcherArguments, diff --git a/templates/webhook/RequestParser.tpl.php b/templates/webhook/RequestParser.tpl.php index 292b87e28..97fa83280 100644 --- a/templates/webhook/RequestParser.tpl.php +++ b/templates/webhook/RequestParser.tpl.php @@ -1,10 +1,10 @@ -namespace ; +namespace getNamespace(); ?>; - +getUseStatements(); ?> -final class extends AbstractRequestParser +getClassDeclaration(); ?> { protected function getRequestMatcher(): RequestMatcherInterface { diff --git a/templates/webhook/WebhookConsumer.tpl.php b/templates/webhook/WebhookConsumer.tpl.php index ab627124b..b04f966b6 100644 --- a/templates/webhook/WebhookConsumer.tpl.php +++ b/templates/webhook/WebhookConsumer.tpl.php @@ -1,13 +1,11 @@ -namespace ; +namespace getNamespace(); ?>; -use Symfony\Component\RemoteEvent\Attribute\AsRemoteEventConsumer; -use Symfony\Component\RemoteEvent\Consumer\ConsumerInterface; -use Symfony\Component\RemoteEvent\RemoteEvent; +getUseStatements(); ?> #[AsRemoteEventConsumer('')] -final class implements ConsumerInterface +getClassDeclaration(); ?> implements ConsumerInterface { public function __construct() { diff --git a/tests/Maker/MakeWebhookTest.php b/tests/Maker/MakeWebhookTest.php index f9bc6b05e..1cba49b12 100644 --- a/tests/Maker/MakeWebhookTest.php +++ b/tests/Maker/MakeWebhookTest.php @@ -14,6 +14,7 @@ use Symfony\Bundle\MakerBundle\Maker\MakeWebhook; use Symfony\Bundle\MakerBundle\Test\MakerTestCase; use Symfony\Bundle\MakerBundle\Test\MakerTestRunner; +use Symfony\Component\Yaml\Yaml; class MakeWebhookTest extends MakerTestCase { @@ -270,5 +271,34 @@ public function getTestDetails(): \Generator ); }), ]; + + yield 'it_makes_webhook_not_final' => [$this->createMakerTest() + ->run(function (MakerTestRunner $runner) { + $runner->writeFile( + 'config/packages/dev/maker.yaml', + Yaml::dump(['when@dev' => ['maker' => ['generate_final_classes' => false]]]) + ); + + $runner->runMaker( + [ + 'remote_service', + '', + ] + ); + + $outputExpectations = [ + 'src/Webhook/RemoteServiceRequestParser.php' => 'class RemoteServiceRequestParser extends AbstractRequestParser;', + 'src/RemoteEvent/RemoteServiceWebhookConsumer.php' => 'class RemoteServiceWebhookConsumer implements ConsumerInterface', + ]; + + foreach ($outputExpectations as $expectedFileName => $expectedContent) { + $path = $runner->getPath($expectedFileName); + + $this->assertFileExists($runner->getPath($expectedFileName)); + $this->assertStringNotContainsString('final', file_get_contents($path)); + $this->assertStringContainsString($expectedContent, file_get_contents($path)); + } + }), + ]; } }