8000 feature #48542 [Webhook][RemoteEvent] Add the components (fabpot) · symfony/symfony@c918829 · GitHub
[go: up one dir, main page]

Skip to content

Commit c918829

Browse files
committed
feature #48542 [Webhook][RemoteEvent] Add the components (fabpot)
This PR was squashed before being merged into the 6.3 branch. Discussion ---------- [Webhook][RemoteEvent] Add the components | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | yes <!-- please update src/**/CHANGELOG.md files --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tickets | n/a <!-- prefix each issue number with "Fix #", no need to create an issue if none exists, explain below instead --> | License | MIT | Doc PR | n/a See my keynote slide about this here: https://speakerdeck.com/fabpot/symfonycon-2022-keynote-webhooks Video from SymfonyCon Disneyland Paris https://live.symfony.com/account/replay/video/669 Commits ------- e51a2b1 [Webhook][RemoteEvent] Add the components
2 parents cb39a7f + e51a2b1 commit c918829

File tree

102 files changed

+2878
-13
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+2878
-13
lines changed

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
"symfony/property-info": "self.version",
9595
"symfony/proxy-manager-bridge": "self.version",
9696
"symfony/rate-limiter": "self.version",
97+
"symfony/remote-event": "self.version",
9798
"symfony/routing": "self.version",
9899
"symfony/security-bundle": "self.version",
99100
"symfony/security-core": "self.version",
@@ -113,6 +114,7 @@
113114
"symfony/var-exporter": "self.version",
114115
"symfony/web-link": "self.version",
115116
"symfony/web-profiler-bundle": "self.version",
117+
"symfony/webhook": "self.version",
116118
"symfony/workflow": "self.version",
117119
"symfony/yaml": "self.version"
118120
},

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class UnusedTagsPass implements CompilerPassInterface
7474
'property_info.list_extractor',
7575
'property_info.type_extractor',
7676
'proxy',
77+
'remote_event.consumer',
7778
'routing.condition_service',
7879
'routing.expression_language_function',
7980
'routing.expression_language_provider',

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@
3636
use Symfony\Component\PropertyAccess\PropertyAccessor;
3737
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
3838
use Symfony\Component\RateLimiter\Policy\TokenBucketLimiter;
39+
use Symfony\Component\RemoteEvent\RemoteEvent;
3940
use Symfony\Component\Semaphore\Semaphore;
4041
use Symfony\Component\Serializer\Serializer;
4142
use Symfony\Component\Translation\Translator;
4243
use Symfony\Component\Uid\Factory\UuidFactory;
4344
use Symfony\Component\Validator\Validation;
45+
use Symfony\Component\Webhook\Controller\WebhookController;
4446
use Symfony\Component\WebLink\HttpHeaderSerializer;
4547
use Symfony\Component\Workflow\WorkflowEvents;
4648

@@ -179,6 +181,8 @@ public function getConfigTreeBuilder(): TreeBuilder
179181
$this->addRateLimiterSection($rootNode, $enableIfStandalone);
180182
$this->addUidSection($rootNode, $enableIfStandalone);
181183
$this->addHtmlSanitizerSection($rootNode, $enableIfStandalone);
184+
$this->addWebhookSection($rootNode, $enableIfStandalone);
185+
$this->addRemoteEventSection($rootNode, $enableIfStandalone);
182186

183187
return $treeBuilder;
184188
}
@@ -2070,6 +2074,47 @@ private function addNotifierSection(ArrayNodeDefinition $rootNode, callable $ena
20702074
;
20712075
}
20722076

2077+
private function addWebhookSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
2078+
{
2079+
$rootNode
2080+
->children()
2081+
->arrayNode('webhook')
2082+
->info('Webhook configuration')
2083+
->{$enableIfStandalone('symfony/webhook', WebhookController::class)}()
2084+
->children()
2085+
->scalarNode('message_bus')->defaultValue('messenger.default_bus')->info('The message bus to use.')->end()
2086+
->arrayNode('routing')
2087+
->normalizeKeys(false)
2088+
->useAttributeAsKey('type')
2089+
->prototype('array')
2090+
->children()
2091+
->scalarNode('service')
2092+
->isRequired()
2093+
->cannotBeEmpty()
2094+
->end()
2095+
->scalarNode('secret')
2096+
->defaultValue('')
2097+
->end()
2098+
->end()
2099+
->end()
2100+
->end()
2101+
->end()
2102+
->end()
2103+
;
2104+
}
2105+
2106+
private function addRemoteEventSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone)
2107+
{
2108+
$rootNode
2109+
->children()
2110+
->arrayNode('remote-event')
2111+
->info('RemoteEvent configuration')
2112+
->{$enableIfStandalone('symfony/remote-event', RemoteEvent::class)}()
2113+
->end()
2114+
->end()
2115+
;
2116+
}
2117+
20732118
private function addRateLimiterSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
20742119
{
20752120
$rootNode

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,12 @@
102102
use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory;
103103
use Symfony\Component\Mailer\Bridge\MailerSend\Transport\MailerSendTransportFactory;
104104
use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory;
105+
use Symfony\Component\Mailer\Bridge\Mailgun\Webhook\MailgunRequestParser;
105106
use Symfony\Component\Mailer\Bridge\Mailjet\Transport\MailjetTransportFactory;
106107
use Symfony\Component\Mailer\Bridge\MailPace\Transport\MailPaceTransportFactory;
107108
use Symfony\Component\Mailer\Bridge\OhMySmtp\Transport\OhMySmtpTransportFactory;
108109
use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory;
110+
use Symfony\Component\Mailer\Bridge\Postmark\Webhook\PostmarkRequestParser;
109111
use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory;
110112
use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory;
111113
use Symfony\Component\Mailer\Command\MailerTestCommand;
@@ -210,6 +212,8 @@
210212
use Symfony\Component\RateLimiter\LimiterInterface;
211213
use Symfony\Component\RateLimiter\RateLimiterFactory;
212214
use Symfony\Component\RateLimiter\Storage\CacheStorage;
215+
use Symfony\Component\RemoteEvent\Attribute\AsRemoteEventConsumer;
216+
use Symfony\Component\RemoteEvent\RemoteEvent;
213217
use Symfony\Component\Routing\Loader\Psr4DirectoryLoader;
214218
use Symfony\Component\Security\Core\AuthenticationEvents;
215219
use Symfony\Component\Security\Core\Exception\AuthenticationException;
@@ -244,6 +248,7 @@
244248
use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
245249
use Symfony\Component\Validator\ObjectInitializerInterface;
246250
use Symfony\Component\Validator\Validation;
251+
use Symfony\Component\Webhook\Controller\WebhookController;
247252
use Symfony\Component\WebLink\HttpHeaderSerializer;
248253
use Symfony\Component\Workflow;
249254
use Symfony\Component\Workflow\WorkflowInterface;
@@ -403,7 +408,7 @@ public function load(array $configs, ContainerBuilder $container)
403408
}
404409

405410
if ($this->readConfigEnabled('mailer', $container, $config['mailer'])) {
406-
$this->registerMailerConfiguration($config['mailer'], $container, $loader);
411+
$this->registerMailerConfiguration($config['mailer'], $container, $loader, $this->readConfigEnabled('webhook', $container, $config['webhook']));
407412

408413
if (!$this->hasConsole() || !class_exists(MailerTestCommand::class)) {
409414
$container->removeDefinition('console.command.mailer_test');
@@ -558,12 +563,20 @@ public function load(array $configs, ContainerBuilder $container)
558563

559564
// notifier depends on messenger, mailer being registered
560565
if ($this->readConfigEnabled('notifier', $container, $config['notifier'])) {
561-
$this->registerNotifierConfiguration($config['notifier'], $container, $loader);
566+
$this->registerNotifierConfiguration($config['notifier'], $container, $loader, $this->readConfigEnabled('webhook', $container, $config['webhook']));
562567
}
563568

564569
// profiler depends on form, validation, translation, messenger, mailer, http-client, notifier, serializer being registered
565570
$this->registerProfilerConfiguration($config['profiler'], $container, $loader);
566571

572+
if ($this->readConfigEnabled('webhook', $container, $config['webhook'])) {
573+
$this->registerWebhookConfiguration($config['webhook'], $container, $loader);
574+
}
575+
576+
if ($this->readConfigEnabled('remote-event', $container, $config['remote-event'])) {
577+
$this->registerRemoteEventConfiguration($config['remote-event'], $container, $loader);
578+
}
579+
567580
if ($this->readConfigEnabled('html_sanitizer', $container, $config['html_sanitizer'])) {
568581
if (!class_exists(HtmlSanitizerConfig::class)) {
569582
throw new LogicException('HtmlSanitizer support cannot be enabled as the HtmlSanitizer component is not installed. Try running "composer require symfony/html-sanitizer".');
@@ -678,7 +691,9 @@ public function load(array $configs, ContainerBuilder $container)
678691
$container->registerAttributeForAutoconfiguration(AsController::class, static function (ChildDefinition $definition, AsController $attribute): void {
679692
$definition->addTag('controller.service_arguments');
680693
});
681-
694+
$container->registerAttributeForAutoconfiguration(AsRemoteEventConsumer::class, static function (ChildDefinition $definition, AsRemoteEventConsumer $attribute): void {
695+
$definition->addTag('remote_event.consumer', ['consumer' => $attribute->name]);
696+
});
682697
$container->registerAttributeForAutoconfiguration(AsMessageHandler::class, static function (ChildDefinition $definition, AsMessageHandler $attribute, \ReflectionClass|\ReflectionMethod $reflector): void {
683698
$tagAttributes = get_object_vars($attri 10000 bute);
684699
$tagAttributes['from_transport'] = $tagAttributes['fromTransport'];
@@ -2467,7 +2482,7 @@ private function registerRetryableHttpClient(array $options, string $name, Conta
24672482
->addTag('monolog.logger', ['channel' => 'http_client']);
24682483
}
24692484

2470-
private function registerMailerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
2485+
private function registerMailerConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, bool $webhookEnabled): void
24712486
{
24722487
if (!class_exists(Mailer::class)) {
24732488
throw new LogicException('Mailer support cannot be enabled as the component is not installed. Try running "composer require symfony/mailer".');
@@ -2512,6 +2527,19 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co
25122527
}
25132528
}
25142529

2530+
$webhookRequestParsers = [
2531+
MailgunRequestParser::class => 'mailer.webhook.request_parser.mailgun',
2532+
PostmarkRequestParser::class => 'mailer.webhook.request_parser.postmark',
2533+
];
2534+
2535+
foreach ($webhookRequestParsers as $class => $service) {
2536+
$package = substr($service, \strlen('mailer.transport_factory.'));
2537+
2538+
if (!ContainerBuilder::willBeAvailable(sprintf('symfony/%s-mailer', 'gmail' === $package ? 'google' : $package), $class, ['symfony/framework-bundle', 'symfony/mailer'])) {
2539+
$container->removeDefinition($service);
2540+
}
2541+
}
2542+
25152543
$envelopeListener = $container->getDefinition('mailer.envelope_listener');
25162544
$envelopeListener->setArgument(0, $config['envelope']['sender'] ?? null);
25172545
$envelopeListener->setArgument(1, $config['envelope']['recipients'] ?? null);
@@ -2534,9 +2562,13 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co
25342562
if (!class_exists(MessengerTransportListener::class)) {
25352563
$container->removeDefinition('mailer.messenger_transport_listener');
25362564
}
2565+
2566+
if ($webhookEnabled) {
2567+
$loader->load('mailer_webhook.php');
2568+
}
25372569
}
25382570

2539-
private function registerNotifierConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
2571+
private function registerNotifierConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, bool $webhookEnabled): void
25402572
{
25412573
if (!class_exists(Notifier::class)) {
25422574
throw new LogicException('Notifier support cannot be enabled as the component is not installed. Try running "composer require symfony/notifier".');
@@ -2701,6 +2733,40 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $
27012733
$notifier->addMethodCall('addAdminRecipient', [new Reference($id)]);
27022734
}
27032735
}
2736+
2737+
if ($webhookEnabled) {
2738+
$loader->load('notifier_webhook.php');
2739+
}
2740+
}
2741+
2742+
private function registerWebhookConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader)
2743+
{
2744+
if (!class_exists(WebhookController::class)) {
2745+
throw new LogicException('Webhook support cannot be enabled as the component is not installed. Try running "composer require symfony/webhook".');
2746+
}
2747+
2748+
$loader->load('webhook.php');
2749+
2750+
$parsers = [];
2751+
foreach ($config['routing'] as $type => $cfg) {
2752+
$parsers[$type] = [
2753+
'parser' => new Reference($cfg['service']),
2754+
'secret' => $cfg['secret'],
2755+
];
2756+
}
2757+
2758+
$controller = $container->getDefinition('webhook.controller');
2759+
$controller->replaceArgument(0, $parsers);
2760+
$controller->replaceArgument(1, new Reference($config['message_bus']));
2761+
}
2762+
2763+
private function registerRemoteEventConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader)
2764+
{
2765+
if (!class_exists(RemoteEvent::class)) {
2766+
throw new LogicException('RemoteEvent support cannot be enabled as the component is not installed. Try running "composer require symfony/remote-event".');
2767+
}
2768+
2769+
$loader->load('remote_event.php');
27042770
}
27052771

27062772
private function registerRateLimiterConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
13+
14+
use Symfony\Component\Mailer\Bridge\Mailgun\RemoteEvent\MailgunPayloadConverter;
15+
use Symfony\Component\Mailer\Bridge\Mailgun\Webhook\MailgunRequestParser;
16+
use Symfony\Component\Mailer\Bridge\Postmark\RemoteEvent\PostmarkPayloadConverter;
17+
use Symfony\Component\Mailer\Bridge\Postmark\Webhook\PostmarkRequestParser;
18+
19+
return static function (ContainerConfigurator $container) {
20+
$container->services()
21+
->set('mailer.payload_converter.mailgun', MailgunPayloadConverter::class)
22+
->set('mailer.webhook.request_parser.mailgun', MailgunRequestParser::class)
23+
->args([service('mailer.payload_converter.mailgun')])
24+
->alias(MailgunRequestParser::class, 'mailer.webhook.request_parser.mailgun')
25+
26+
->set('mailer.payload_converter.postmark', PostmarkPayloadConverter::class)
27+
->set('mailer.webhook.request_parser.postmark', PostmarkRequestParser::class)
28+
->args([service('mailer.payload_converter.postmark')])
29+
->alias(PostmarkRequestParser::class, 'mailer.webhook.request_parser.postmark')
30+
;
31+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
13+
14+
use Symfony\Component\Notifier\Bridge\Twilio\Webhook\TwilioRequestParser;
15+
16+
return static function (ContainerConfigurator $container) {
17+
$container->services()
18+
->set('notifier.webhook.request_parser.twilio', TwilioRequestParser::class)
19+
->alias(TwilioRequestParser::class, 'notifier.webhook.request_parser.twilio')
20+
;
21+
};
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
13+
14+
use Symfony\Component\RemoteEvent\Messenger\ConsumeRemoteEventHandler;
15+
16+
return static function (ContainerConfigurator $container) {
17+
$container->services()
18+
->set('remote_event.messenger.handler', ConsumeRemoteEventHandler::class)
19+
->args([
20+
tagged_locator('remote_event.consumer', 'consumer'),
21+
])
22+
->tag('messenger.message_handler')
23+
;
24+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<routes xmlns="http://symfony.com/schema/routing"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd">
6+
7+
<route id="_webhook_controller" path="/{type}">
8+
<default key="_controller">webhook.controller::handle</default>
9+
</route>
10+
</routes>

src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
<xsd:element name="notifier" type="notifier" minOccurs="0" maxOccurs="1" />
4343
<xsd:element name="html-sanitizer" type="html-sanitizer" minOccurs="0" maxOccurs="1" />
4444
<xsd:element name="enabled-locale" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
45+
<xsd:element name="webhook" type="webhook" minOccurs="0" maxOccurs="1" />
46+
<xsd:element name="remote-event" type="remote-event" minOccurs="0" maxOccurs="1" />
4547
</xsd:choice>
4648

4749
<xsd:attribute name="http-method-override" type="xsd:boolean" />
@@ -916,4 +918,23 @@
916918
</xsd:sequence>
917919
<xsd:attribute name="name" type="xsd:string" use="required" />
918920
</xsd:complexType>
921+
922+
<xsd:complexType name="webhook">
923+
<xsd:sequence>
924+
<xsd:element name="routing" type="webhook_routing" minOccurs="0" maxOccurs="unbounded" />
925+
</xsd:sequence>
926+
<xsd:attribute name="enabled" type="xsd:boolean" />
927+
<xsd:attribute name="message-bus" type="xsd:string" />
928+
</xsd:complexType>
929+
930+
<xsd:complexType name="webhook_routing" mixed="true">
931+
<xsd:sequence>
932+
<xsd:element name="service" type="xsd:string" minOccurs="0" maxOccurs="1" />
933+
<xsd:element name="secret" type="xsd:string" minOccurs="0" maxOccurs="1" />
934+
</xsd:sequence>
935+
</xsd:complexType>
936+
937+
<xsd:complexType name="remote-event">
938+
<xsd:attribute name="enabled" type="xsd:boolean" />
939+
</xsd:complexType>
919940
</xsd:schema>

0 commit comments

Comments
 (0)
0