diff --git a/Async/Topics.php b/Async/Topics.php index 06528d6..6c7a1b6 100644 --- a/Async/Topics.php +++ b/Async/Topics.php @@ -18,6 +18,7 @@ class Topics const WEBHOOK_ENTITY_CREATE = 'aligent.webhook.entity.create'; const WEBHOOK_ENTITY_UPDATE = 'aligent.webhook.entity.update'; const WEBHOOK_ENTITY_DELETE = 'aligent.webhook.entity.delete'; + const WEBHOOK_ENTITY_CUSTOM = 'aligent.webhook.entity.custom'; const EVENT_MAP = [ WebhookConfigProvider::UPDATE => self::WEBHOOK_ENTITY_UPDATE, diff --git a/Async/WebhookEntityProcessor.php b/Async/WebhookEntityProcessor.php index b4771f1..b144ee2 100644 --- a/Async/WebhookEntityProcessor.php +++ b/Async/WebhookEntityProcessor.php @@ -29,22 +29,12 @@ class WebhookEntityProcessor extends AbstractRetryableProcessor implements Topic Topics::WEBHOOK_ENTITY_UPDATE => WebhookConfigProvider::UPDATE, Topics::WEBHOOK_ENTITY_DELETE => WebhookConfigProvider::DELETE, Topics::WEBHOOK_ENTITY_CREATE => WebhookConfigProvider::CREATE, + Topics::WEBHOOK_ENTITY_CUSTOM => WebhookConfigProvider::CUSTOM, ]; - /** - * @var WebhookConfigProvider - */ - protected $configProvider; - - /** - * @var WebhookTransport - */ - protected $transport; - - /** - * @var SerializerInterface - */ - protected $serializer; + protected WebhookTransport $transport; + protected SerializerInterface $serializer; + protected WebhookConfigProvider $configProvider; /** * @param SerializerInterface $serializer @@ -82,7 +72,7 @@ public function setTransport(WebhookTransport $transport): WebhookEntityProcesso /** * @inheritDoc */ - public function execute(MessageInterface $message) + public function execute(MessageInterface $message): string { $data = JSON::decode($message->getBody()); $topic = $message->getProperty(Config::PARAMETER_TOPIC_NAME); @@ -119,6 +109,7 @@ public function execute(MessageInterface $message) $this->logger->error( $message, [ + 'channelId' => $channel->getId(), 'channel' => $channel->getName(), 'topic' => $topic, @@ -134,26 +125,27 @@ public function execute(MessageInterface $message) /** * @inheritDoc */ - public static function getSubscribedTopics() + public static function getSubscribedTopics(): array { return [ Topics::WEBHOOK_ENTITY_CREATE, Topics::WEBHOOK_ENTITY_DELETE, Topics::WEBHOOK_ENTITY_UPDATE, + Topics::WEBHOOK_ENTITY_CUSTOM, ]; } /** * @param string $event * @param array $data - * @return array + * @return array * @throws \Symfony\Component\Serializer\Exception\ExceptionInterface */ - protected function buildPayload(string $event, array $data) + protected function buildPayload(string $event, array $data): array { $entity = $this->registry->getRepository($data['class'])->find($data['id']); - if ($event === WebhookConfigProvider::CREATE) { + if (in_array($event, [WebhookConfigProvider::CREATE, WebhookConfigProvider::CUSTOM])) { $changeSet = []; } else { // extract all of the before values from the change set diff --git a/Form/Type/WebhookTransportSettingsType.php b/Form/Type/WebhookTransportSettingsType.php index d048e0d..d6200bb 100644 --- a/Form/Type/WebhookTransportSettingsType.php +++ b/Form/Type/WebhookTransportSettingsType.php @@ -14,6 +14,7 @@ use Aligent\AsyncEventsBundle\Entity\WebhookTransport; use Aligent\AsyncEventsBundle\Provider\WebhookConfigProvider; +use Aligent\AsyncEventsBundle\Provider\WebhookCustomEventsProviderInterface; use Doctrine\Persistence\ManagerRegistry; use Oro\Bundle\FormBundle\Form\Type\CollectionType; use Oro\Bundle\FormBundle\Form\Type\OroChoiceType; @@ -25,28 +26,35 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Contracts\Translation\TranslatorInterface; class WebhookTransportSettingsType extends AbstractType { - /** - * @var ManagerRegistry - */ - protected $registry; + protected ManagerRegistry $registry; + protected TranslatorInterface $translator; + protected WebhookCustomEventsProviderInterface $customEventsProvider; /** - * WebhookTransportSettingsType constructor. * @param ManagerRegistry $registry + * @param TranslatorInterface $translator + * @param WebhookCustomEventsProviderInterface $customEventsProvider */ - public function __construct(ManagerRegistry $registry) - { + public function __construct( + ManagerRegistry $registry, + TranslatorInterface $translator, + WebhookCustomEventsProviderInterface $customEventsProvider + ) { $this->registry = $registry; + $this->translator = $translator; + $this->customEventsProvider = $customEventsProvider; } /** * @param FormBuilderInterface $builder - * @param array $options + * @param array $options + * @return void */ - public function buildForm(FormBuilderInterface $builder, array $options) + public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add( @@ -83,7 +91,10 @@ public function buildForm(FormBuilderInterface $builder, array $options) OroChoiceType::class, [ 'required' => true, - 'choices' => $this->getEventsList() + 'choices' => $this->getEventsList(), + 'choice_label' => function ($choice, $key) { + return $this->translator->trans($key); + } ] ) ->add( @@ -117,9 +128,9 @@ public function buildForm(FormBuilderInterface $builder, array $options) } /** - * @return array + * @return array */ - protected function getEntityList() + protected function getEntityList(): array { $em = $this->registry->getManager(); $entities = []; @@ -133,21 +144,28 @@ protected function getEntityList() } /** - * @return array + * @return array */ - protected function getEventsList() + protected function getEventsList(): array { + /** @var array $events */ $events = []; - $events[WebhookConfigProvider::CREATE] = WebhookConfigProvider::CREATE; - $events[WebhookConfigProvider::UPDATE] = WebhookConfigProvider::UPDATE; - $events[WebhookConfigProvider::DELETE] = WebhookConfigProvider::DELETE; + // [ translation for the event's name => event key (event key is saved in the db and is 16 char long ] + $events['aligent.async.transport.form.event.create'] = WebhookConfigProvider::CREATE; + $events['aligent.async.transport.form.event.update'] = WebhookConfigProvider::UPDATE; + $events['aligent.async.transport.form.event.delete'] = WebhookConfigProvider::DELETE; + + foreach ($this->customEventsProvider->getCustomEvents() as $customEvent) { + $events[$customEvent->getTranslationName()] = $customEvent->getKey(); + } return $events; } /** * @param OptionsResolver $resolver + * @return void */ - public function configureOptions(OptionsResolver $resolver) + public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefault('data_class', WebhookTransport::class); } diff --git a/Integration/WebhookChannel.php b/Integration/WebhookChannel.php index 1c7ae31..56eaef0 100644 --- a/Integration/WebhookChannel.php +++ b/Integration/WebhookChannel.php @@ -19,8 +19,8 @@ class WebhookChannel implements ChannelInterface /** * @inheritDoc */ - public function getLabel() + public function getLabel(): string { - return 'aligent.webhook.channel.label'; + return 'aligent.async.channel.label'; } } diff --git a/Integration/WebhookTransport.php b/Integration/WebhookTransport.php index 3310553..61444e0 100644 --- a/Integration/WebhookTransport.php +++ b/Integration/WebhookTransport.php @@ -14,33 +14,20 @@ use Aligent\AsyncEventsBundle\Form\Type\WebhookTransportSettingsType; use GuzzleHttp\Client; +use GuzzleHttp\Exception\GuzzleException; use Oro\Bundle\IntegrationBundle\Entity\Channel; use Oro\Bundle\IntegrationBundle\Entity\Transport; use Oro\Bundle\IntegrationBundle\Provider\TransportInterface; use Oro\Bundle\SecurityBundle\Encoder\SymmetricCrypterInterface; use Psr\Log\LoggerInterface; +use Psr\Http\Message\ResponseInterface; class WebhookTransport implements TransportInterface { - /** - * @var SymmetricCrypterInterface - */ - protected $encoder; - - /** - * @var LoggerInterface - */ - protected $logger; - - /** - * @var Channel - */ - protected $channel; - - /** - * @var Client - */ - protected $client; + protected Client $client; + protected Channel $channel; + protected LoggerInterface $logger; + protected SymmetricCrypterInterface $encoder; /** * AntavoRestTransport constructor. @@ -56,7 +43,7 @@ public function __construct(SymmetricCrypterInterface $encoder, LoggerInterface /** * @inheritDoc */ - public function init(Transport $transportEntity) + public function init(Transport $transportEntity): void { $settings = $transportEntity->getSettingsBag(); $this->channel = $transportEntity->getChannel(); @@ -84,11 +71,11 @@ public function init(Transport $transportEntity) /** * @param string $method - * @param array $payload - * @return \Psr\Http\Message\ResponseInterface - * @throws \GuzzleHttp\Exception\GuzzleException + * @param array $payload + * @return ResponseInterface + * @throws GuzzleException */ - public function sendWebhookEvent($method = 'POST', $payload = []) + public function sendWebhookEvent(string $method = 'POST', array $payload = []): ResponseInterface { return $this->client->request( $method, @@ -102,15 +89,15 @@ public function sendWebhookEvent($method = 'POST', $payload = []) /** * @inheritDoc */ - public function getLabel() + public function getLabel(): string { - return 'aligent.webhook.transport.label'; + return 'aligent.async.transport.label'; } /** * @inheritDoc */ - public function getSettingsFormType() + public function getSettingsFormType(): string { return WebhookTransportSettingsType::class; } @@ -118,7 +105,7 @@ public function getSettingsFormType() /** * @inheritDoc */ - public function getSettingsEntityFQCN() + public function getSettingsEntityFQCN(): string { return \Aligent\AsyncEventsBundle\Entity\WebhookTransport::class; } diff --git a/Provider/WebhookConfigProvider.php b/Provider/WebhookConfigProvider.php index 2f616ef..9f8d80c 100644 --- a/Provider/WebhookConfigProvider.php +++ b/Provider/WebhookConfigProvider.php @@ -4,6 +4,7 @@ use Doctrine\Common\Cache\CacheProvider; use Oro\Bundle\IntegrationBundle\Entity\Channel; +use Oro\Bundle\IntegrationBundle\Entity\Transport; use Symfony\Bridge\Doctrine\ManagerRegistry; /** @@ -20,19 +21,13 @@ class WebhookConfigProvider const CREATE = 'create'; const UPDATE = 'update'; const DELETE = 'delete'; + const CUSTOM = 'custom'; // Cache Keys const CONFIG_CACHE_KEY = 'WebhookConfig'; - /** - * @var ManagerRegistry - */ - protected $registry; - - /** - * @var CacheProvider - */ - protected $cache; + protected CacheProvider $cache; + protected ManagerRegistry $registry; /** * WebhookEntityProvider constructor. @@ -47,8 +42,9 @@ public function __construct(ManagerRegistry $registry, CacheProvider $cache) /** * Initialize the webhook config cache + * @return array>> */ - protected function getWebhookConfig() + protected function getWebhookConfig(): array { if ($webhookConfig = $this->cache->fetch(self::CONFIG_CACHE_KEY)) { return $webhookConfig; @@ -75,20 +71,20 @@ protected function getWebhookConfig() /** * @param $class - * @return array|null + * @return array>|null */ - public function getEntityConfig($class) + public function getEntityConfig($class): ?array { $config = $this->getWebhookConfig(); return $config[$class] ?? null; } /** - * @param $class - * @param $event + * @param string $class + * @param string $event * @return boolean */ - public function isManaged($class, $event) + public function isManaged(string $class, string $event): bool { $entityConfig = $this->getEntityConfig($class); if (!$entityConfig) { @@ -100,22 +96,25 @@ public function isManaged($class, $event) /** * Returns a list of channel id's that wish to be notified of this event for this entity - * @param $class - * @param $event + * @param string $class + * @param string $event * @return int[] */ - public function getNotificationChannels($class, $event) + public function getNotificationChannels(string $class, string $event): array { $entityConfig = $this->getEntityConfig($class); + if ($entityConfig == null) { + return []; + } return $entityConfig[$event]; } /** * Convert the webhook config to an easily queried format - * @param array $config - * @return array + * @param array $config + * @return array>> */ - protected function normalizeConfig(array $config) + protected function normalizeConfig(array $config): array { $normalizedConfig = []; foreach ($config as $id => $webhookTransport) { @@ -126,4 +125,4 @@ protected function normalizeConfig(array $config) return $normalizedConfig; } -} +} \ No newline at end of file diff --git a/Provider/WebhookCustomEventInterface.php b/Provider/WebhookCustomEventInterface.php new file mode 100644 index 0000000..aa02fde --- /dev/null +++ b/Provider/WebhookCustomEventInterface.php @@ -0,0 +1,23 @@ + + * @copyright 2023 Aligent Consulting. + * @link http://www.aligent.com.au/ + */ + +namespace Aligent\AsyncEventsBundle\Provider; + +interface WebhookCustomEventInterface +{ + + /** + * @return string + */ + public static function getTranslationName(): string; + + /** + * @return string + */ + public static function getKey(): string; +} diff --git a/Provider/WebhookCustomEventsProvider.php b/Provider/WebhookCustomEventsProvider.php new file mode 100644 index 0000000..5bdd092 --- /dev/null +++ b/Provider/WebhookCustomEventsProvider.php @@ -0,0 +1,35 @@ + + * @copyright 2023 Aligent Consulting. + * @link http://www.aligent.com.au/ + */ + +namespace Aligent\AsyncEventsBundle\Provider; + +use Symfony\Contracts\Translation\TranslatorInterface; + +class WebhookCustomEventsProvider implements WebhookCustomEventsProviderInterface +{ + /** + * @var iterable + */ + protected iterable $customEvents; + + /** + * @param WebhookCustomEventsProviderInterface[]|iterable $customEvents + */ + public function __construct(iterable $customEvents) + { + $this->customEvents = $customEvents; + } + + /** + * @inheritDoc + */ + public function getCustomEvents(): iterable + { + return $this->customEvents; + } +} diff --git a/Provider/WebhookCustomEventsProviderInterface.php b/Provider/WebhookCustomEventsProviderInterface.php new file mode 100644 index 0000000..3e25217 --- /dev/null +++ b/Provider/WebhookCustomEventsProviderInterface.php @@ -0,0 +1,17 @@ + + * @copyright 2023 Aligent Consulting. + * @link http://www.aligent.com.au/ + */ + +namespace Aligent\AsyncEventsBundle\Provider; + +interface WebhookCustomEventsProviderInterface +{ + /** + * @return iterable + */ + public function getCustomEvents(): iterable; +} diff --git a/Provider/WebhookIntegrationProvider.php b/Provider/WebhookIntegrationProvider.php index 83bfee4..c02e3ec 100644 --- a/Provider/WebhookIntegrationProvider.php +++ b/Provider/WebhookIntegrationProvider.php @@ -19,15 +19,8 @@ class WebhookIntegrationProvider { - /** - * @var ManagerRegistry - */ - protected $registry; - - /** - * @var WebhookTransport - */ - protected $transport; + protected ManagerRegistry $registry; + protected WebhookTransport $transport; /** * WebhookIntegrationProvider constructor. diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 31d69ef..6c4c67b 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -10,9 +10,15 @@ services: Aligent\AsyncEventsBundle\Form\Type\WebhookTransportSettingsType: arguments: - '@doctrine' + - '@translator' + - '@Aligent\AsyncEventsBundle\Provider\WebhookCustomEventsProvider' tags: - { name: form.type } + Aligent\AsyncEventsBundle\Provider\WebhookCustomEventsProvider: + arguments: + - !tagged_iterator aligent_async_events.custom_events + # Caches aligent_webhook.config.cache: public: false diff --git a/Resources/translations/messages.en.yml b/Resources/translations/messages.en.yml index d6a90b5..d1866a1 100644 --- a/Resources/translations/messages.en.yml +++ b/Resources/translations/messages.en.yml @@ -1,5 +1,8 @@ -aligent.webhook.channel.label: Webhook -aligent.webhook.webhooktransport.entity_label: Webhook Transport +aligent.async.channel.label: Webhook +aligent.async.transport.label: Webhook Transport +aligent.async.transport.form.event.create: Create +aligent.async.transport.form.event.update: Update +aligent.async.transport.form.event.delete: Delete aligent.asyncevents.failedjob.entity_plural_label: Failed Jobs aligent.async.failedjob.entity.plural_label: Failed Jobs aligent.async.failedjob.retry.label: Retry