diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 7275b011..8410154f 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -37,7 +37,8 @@ public function getConfigTreeBuilder(): TreeBuilder ->info('Enable csrf protection for dynamic forms.') ->defaultFalse() ->end() - ->scalarNode('sendinblue_api_key')->defaultValue(null)->end() + ->scalarNode('sendinblue_api_key')->setDeprecated('sendinblue/api-v3-sdk', '1.0.0', 'The Sendinblue integration is deprecated, use Brevo integration instead (brevo_api_key).')->defaultValue(null)->end() + ->scalarNode('brevo_api_key')->defaultValue(null)->end() ->scalarNode('mailchimp_api_key')->defaultValue(null)->end() ->scalarNode('mailchimp_subscribe_status')->defaultValue('subscribed')->end() ->enumNode('media_collection_strategy') diff --git a/DependencyInjection/SuluFormExtension.php b/DependencyInjection/SuluFormExtension.php index f8db7e9e..9901f3a8 100644 --- a/DependencyInjection/SuluFormExtension.php +++ b/DependencyInjection/SuluFormExtension.php @@ -204,6 +204,14 @@ public function load(array $configs, ContainerBuilder $container): void $loader->load('type_sendinblue.xml'); } + if ($config['brevo_api_key']) { + if (!\class_exists(\Brevo\Client\Configuration::class)) { + throw new \LogicException('You need to install the "getbrevo/brevo-php" package to use the Brevo type.'); + } + + $loader->load('type_brevo.xml'); + } + if ($config['mailchimp_api_key']) { if (!\class_exists(\DrewM\MailChimp\MailChimp::class)) { throw new \LogicException('You need to install the "drewm/mailchimp-api" package to use the mailchimp type.'); diff --git a/Dynamic/Helper/BrevoListSelect.php b/Dynamic/Helper/BrevoListSelect.php new file mode 100644 index 00000000..c233c09c --- /dev/null +++ b/Dynamic/Helper/BrevoListSelect.php @@ -0,0 +1,84 @@ +setApiKey('api-key', $apiKey); + + $this->contactsApi = new ContactsApi(null, $config); + } + + /** + * Returns array of Brevo lists of given account defined by the API key. + * + * @return mixed[] + */ + public function getValues(): array + { + if (!$this->contactsApi) { + return []; + } + + $limit = 50; + $offset = 0; + $total = null; + $listObjects = []; + + do { + $response = $this->contactsApi->getLists($limit, $offset); + + if (null === $total) { + $total = $response->getCount(); + } + + $newListObjects = $response->getLists(); + if (0 === \count($newListObjects)) { + break; + } + + $listObjects = \array_merge($listObjects, $newListObjects); + $offset += $limit; + } while (\count($listObjects) < $total); + + $lists = []; + + foreach ($listObjects as $list) { + $lists[] = [ + 'name' => $list['id'], + 'title' => $list['name'], + ]; + } + + return $lists; + } +} diff --git a/Dynamic/Helper/BrevoMailTemplateSelect.php b/Dynamic/Helper/BrevoMailTemplateSelect.php new file mode 100644 index 00000000..2a85e7d4 --- /dev/null +++ b/Dynamic/Helper/BrevoMailTemplateSelect.php @@ -0,0 +1,88 @@ +setApiKey('api-key', $apiKey); + + $this->transactionalEmailsApi = new TransactionalEmailsApi(null, $config); + } + + /** + * Returns array of Brevo mail templates of given account defined by the API key. + * + * @return mixed[] + */ + public function getValues(): array + { + if (!$this->transactionalEmailsApi) { + return []; + } + + $limit = 50; + $offset = 0; + $total = null; + $mailTemplateObjects = []; + + do { + $response = $this->transactionalEmailsApi->getSmtpTemplates(true, $limit, $offset); + + if (null === $total) { + $total = $response->getCount(); + } + + $newMailTemplateObjects = $response->getTemplates(); + if (0 === \count($newMailTemplateObjects)) { + break; + } + + $mailTemplateObjects = \array_merge($mailTemplateObjects, $newMailTemplateObjects); + $offset += $limit; + } while (\count($mailTemplateObjects) < $total); + + $mailTemplates = []; + + foreach ($mailTemplateObjects as $template) { + if (($template['tag'] ?? null) !== 'optin') { + continue; + } + + $mailTemplates[] = [ + 'name' => $template['id'], + 'title' => $template['name'], + ]; + } + + return $mailTemplates; + } +} diff --git a/Dynamic/Helper/SendinblueListSelect.php b/Dynamic/Helper/SendinblueListSelect.php index 34ce7b27..9fbc826f 100644 --- a/Dynamic/Helper/SendinblueListSelect.php +++ b/Dynamic/Helper/SendinblueListSelect.php @@ -18,6 +18,8 @@ * @final * * @internal + * + * @deprecated */ class SendinblueListSelect { diff --git a/Dynamic/Helper/SendinblueMailTemplateSelect.php b/Dynamic/Helper/SendinblueMailTemplateSelect.php index 282ac653..9e06167e 100644 --- a/Dynamic/Helper/SendinblueMailTemplateSelect.php +++ b/Dynamic/Helper/SendinblueMailTemplateSelect.php @@ -18,6 +18,8 @@ * @final * * @internal + * + * @deprecated */ class SendinblueMailTemplateSelect { diff --git a/Dynamic/Types/BrevoType.php b/Dynamic/Types/BrevoType.php new file mode 100644 index 00000000..fdbfc9db --- /dev/null +++ b/Dynamic/Types/BrevoType.php @@ -0,0 +1,44 @@ +add($field->getKey(), $type, $options); + } + + public function getDefaultValue(FormField $field, string $locale) + { + return $field->getTranslation($locale)->getDefaultValue(); + } +} diff --git a/Dynamic/Types/SendinblueType.php b/Dynamic/Types/SendinblueType.php index cc5991a2..4e367cec 100644 --- a/Dynamic/Types/SendinblueType.php +++ b/Dynamic/Types/SendinblueType.php @@ -19,6 +19,8 @@ /** * The Sendinblue form field type. + * + * @deprecated */ class SendinblueType implements FormFieldTypeInterface { diff --git a/Event/BrevoListSubscriber.php b/Event/BrevoListSubscriber.php new file mode 100644 index 00000000..0975ab5f --- /dev/null +++ b/Event/BrevoListSubscriber.php @@ -0,0 +1,187 @@ +requestStack = $requestStack; + $this->linkProviderPool = $linkProviderPool; + + if (!$apiKey) { + return; + } + + $config = new Configuration(); + $config->setApiKey('api-key', $apiKey); + + $this->contactsApi = new ContactsApi($client, $config); + } + + public static function getSubscribedEvents() + { + return [ + FormSavePostEvent::NAME => 'listSubscribe', + ]; + } + + public function listSubscribe(FormSavePostEvent $event): void + { + if (!$this->contactsApi) { + return; + } + + $dynamic = $event->getData(); + $request = $this->requestStack->getCurrentRequest(); + + if (!$dynamic instanceof Dynamic) { + return; + } + + if (!$request) { + return; + } + + $form = $dynamic->getForm()->serializeForLocale($dynamic->getLocale(), $dynamic); + + $email = ''; + $firstName = ''; + $lastName = ''; + $redirectionUrl = $request->getUriForPath($request->getPathInfo()) . '?send=true&subscribe=true'; + $linkUrl = null; + $listIdsByMailTemplate = []; + + foreach ($form['fields'] as $field) { + if ('firstName' === $field['type'] && !$firstName) { + $firstName = $field['value']; + } elseif ('lastName' === $field['type'] && !$lastName) { + $lastName = $field['value']; + } elseif ('email' === $field['type'] && !$email) { + $email = $field['value']; + } elseif ('brevo' == $field['type'] && $field['value']) { + /** @var string|int|null $listId */ + $mailTemplateId = $field['options']['mailTemplateId'] ?? null; + /** @var int|null $listId */ + $listId = $field['options']['listId'] ?? null; + $redirectLink = $field['options']['redirectLink'] ?? null; + + if ($redirectLink) { + $linkUrl = $this->getUrlFromLink($redirectLink); + } + + if (!$mailTemplateId || !$listId) { + continue; + } + + $listIdsByMailTemplate[$mailTemplateId][] = $listId; + } + } + + /** @var string $email */ + if (!$email || 0 === \count($listIdsByMailTemplate)) { + return; + } + + foreach ($listIdsByMailTemplate as $mailTemplateId => $listIds) { + $createDoiContact = new CreateDoiContact([ + 'email' => $email, + 'templateId' => $mailTemplateId, + 'includeListIds' => $listIds, + 'redirectionUrl' => $linkUrl ?? $redirectionUrl, + 'attributes' => [ + 'firstname' => $firstName, + 'lastname' => $lastName, + ], + ]); + + $this->contactsApi->createDoiContact($createDoiContact); + } + } + + /** + * @param array{ + * provider: ?string, + * target: ?string, + * anchor: ?string, + * query: ?string, + * href: ?string, + * title: ?string, + * rel: ?string, + * locale: ?string, + * } $redirectLink + */ + private function getUrlFromLink(array $redirectLink): ?string + { + if (!$redirectLink['provider']) { + return null; + } + + if ('external' === $redirectLink['provider']) { + return $redirectLink['href']; + } + + if (!$this->linkProviderPool) { + return null; + } + + $linkProvider = $this->linkProviderPool->getProvider($redirectLink['provider']); + $linkItems = $linkProvider->preload([$redirectLink['href']], $redirectLink['locale'], true); + + if (0 === \count($linkItems)) { + return null; + } + + $url = \reset($linkItems)->getUrl(); + if (isset($redirectLink['query'])) { + $url = \sprintf('%s?%s', $url, $redirectLink['query']); + } + if (isset($redirectLink['anchor'])) { + $url = \sprintf('%s#%s', $url, $redirectLink['anchor']); + } + + return $url; + } +} diff --git a/Event/SendinblueListSubscriber.php b/Event/SendinblueListSubscriber.php index 300dccd5..ae7acbd1 100644 --- a/Event/SendinblueListSubscriber.php +++ b/Event/SendinblueListSubscriber.php @@ -24,6 +24,8 @@ * @final * * @internal + * + * @deprecated */ class SendinblueListSubscriber implements EventSubscriberInterface { diff --git a/Resources/config/form-fields/field_brevo.xml b/Resources/config/form-fields/field_brevo.xml new file mode 100644 index 00000000..4e37a0e9 --- /dev/null +++ b/Resources/config/form-fields/field_brevo.xml @@ -0,0 +1,44 @@ + + + + + sulu_form.brevo_list + + + + + + + + sulu_form.brevo_mail_template + + + + + + + + + sulu_form.brevo_redirection_url + + + + + + + + + + diff --git a/Resources/config/type_brevo.xml b/Resources/config/type_brevo.xml new file mode 100644 index 00000000..7aa7a7f0 --- /dev/null +++ b/Resources/config/type_brevo.xml @@ -0,0 +1,27 @@ + + + + + + + %sulu_form.brevo_api_key% + null + + + + + + + + + + %sulu_form.brevo_api_key% + + + + %sulu_form.brevo_api_key% + + + diff --git a/Resources/doc/brevo.md b/Resources/doc/brevo.md new file mode 100644 index 00000000..2401167e --- /dev/null +++ b/Resources/doc/brevo.md @@ -0,0 +1,38 @@ +# Brevo Form Field + +The following is showing an example how you can use the Brevo form field to add customers to your Brevo lists. + +## Installation + +First of all you need to install the Brevo php sdk, otherwise the Brevo field type won't be available. + +```json +{ + "require": { + "getbrevo/brevo-php": "^2.0" + } +} +``` + +or + +```bash +composer require getbrevo/brevo-php:"^2.0" +``` + +## Config + +Add the following config to `config/packages/sulu_form.yaml`: + +```yml +sulu_form: + brevo_api_key: "" +``` + +It is recommended to store the api key as environment variable see [Symfony Docs](https://symfony.com/doc/4.4/configuration.html#configuration-environments). + +## Why is there still no Brevo field type? + +1. Did you install the library? +2. Did you add an api key? +3. Did you create a list and an `optin`-tagged mail template that can be shown in the field type? diff --git a/Resources/doc/index.md b/Resources/doc/index.md index 063c1276..4411e270 100644 --- a/Resources/doc/index.md +++ b/Resources/doc/index.md @@ -80,6 +80,7 @@ Make sure you've set the correct permissions in the Sulu backend for this bundle ## Additional form fields - [Mailchimp](mailchimp.md "Mailchimp Form Field") -- [Sendinblue](sendinblue.md "Sendinblue Form Field") +- [Sendinblue](sendinblue.md "Sendinblue Form Field") **deprecated**: use Brevo instead +- [Brevo](brevo.md "Brevo Form Field") - [Recaptcha](recaptcha.md "Recaptcha Form Field") - [Dropzone](dropzone.md "Dropzone Form Field") diff --git a/Resources/translations/admin.de.json b/Resources/translations/admin.de.json index 7552c587..ac23aed9 100644 --- a/Resources/translations/admin.de.json +++ b/Resources/translations/admin.de.json @@ -69,6 +69,7 @@ "sulu_form.type.mailchimp": "Mailchimp", "sulu_form.type.hidden": "Hidden", "sulu_form.type.sendinblue": "Sendinblue", + "sulu_form.type.brevo": "Brevo", "sulu_form.width.full": "Voll", "sulu_form.width.half": "Halb", "sulu_form.width.one_quarter": "Ein Viertel", @@ -83,6 +84,11 @@ "sulu_form.sendinblue_redirection_url": "Weiterleitungs-URL", "sulu_form.sendinblue_attribute_name_first_name": "Attribut-Name [Vorname]", "sulu_form.sendinblue_attribute_name_last_name": "Attribut-Name [Nachname]", + "sulu_form.brevo_list": "Brevo Liste", + "sulu_form.brevo_mail_template": "Brevo Mail Vorlage", + "sulu_form.brevo_redirection_url": "Weiterleitungs-URL", + "sulu_form.brevo_attribute_name_first_name": "Attribut-Name [Vorname]", + "sulu_form.brevo_attribute_name_last_name": "Attribut-Name [Nachname]", "sulu_form.salutation_ms": "Frau", "sulu_form.salutation_mr": "Herr", "sulu_form.salutation_neutral": "Neutral", diff --git a/Resources/translations/admin.en.json b/Resources/translations/admin.en.json index 3bd220cb..7ea88e8e 100644 --- a/Resources/translations/admin.en.json +++ b/Resources/translations/admin.en.json @@ -69,6 +69,7 @@ "sulu_form.type.mailchimp": "Mailchimp", "sulu_form.type.hidden": "Hidden", "sulu_form.type.sendinblue": "Sendinblue", + "sulu_form.type.brevo": "Brevo", "sulu_form.width.full": "Full", "sulu_form.width.half": "Half", "sulu_form.width.one_quarter": "One quarter", @@ -83,6 +84,11 @@ "sulu_form.sendinblue_redirection_url": "Redirection url", "sulu_form.sendinblue_attribute_name_first_name": "Attribute name [First name]", "sulu_form.sendinblue_attribute_name_last_name": "Attribute name [Last name]", + "sulu_form.brevo_list": "Brevo list", + "sulu_form.brevo_mail_template": "Brevo mail template", + "sulu_form.brevo_redirection_url": "Redirection url", + "sulu_form.brevo_attribute_name_first_name": "Attribute name [First name]", + "sulu_form.brevo_attribute_name_last_name": "Attribute name [Last name]", "sulu_form.salutation_ms": "Ms.", "sulu_form.salutation_mr": "Mr.", "sulu_form.salutation_neutral": "Neutral", diff --git a/Tests/Unit/Event/BrevoListSubscriberTest.php b/Tests/Unit/Event/BrevoListSubscriberTest.php new file mode 100644 index 00000000..85054b4e --- /dev/null +++ b/Tests/Unit/Event/BrevoListSubscriberTest.php @@ -0,0 +1,240 @@ + + */ + private $client; + + /** + * @var BrevoListSubscriber + */ + private $brevoListSubscriber; + + /** + * @var LinkProviderPoolInterface|ObjectProphecy + */ + private $linkProviderPool; + + public function setUp(): void + { + $this->requestStack = new RequestStack(); + $this->linkProviderPool = $this->prophesize(LinkProviderPoolInterface::class); + $this->client = $this->prophesize(ClientInterface::class); + + $this->brevoListSubscriber = new BrevoListSubscriber( + $this->requestStack, + 'SOME_KEY', + $this->client->reveal(), + $this->linkProviderPool->reveal() + ); + } + + public function testGetSubscribedEvents(): void + { + $this->assertSame( + [ + 'sulu_form.handler.saved' => 'listSubscribe', + ], + BrevoListSubscriber::getSubscribedEvents() + ); + } + + public function testlistSubscribeNotExist(): void + { + $this->requestStack->push(Request::create('http://localhost/newsletter', 'POST')); + $event = $this->createFormSavePostEvent(); + + $self = $this; + $this->client->send(Argument::cetera())->will(function($args) use ($self) { + /** @var RequestInterface $request */ + $request = $args[0]; + + if ('https://api.brevo.com/v3/contacts/doubleOptinConfirmation' === $request->getUri()->__toString()) { + $self->assertSame('POST', $request->getMethod()); + + $json = \json_decode($request->getBody()->getContents(), true); + + $self->assertSame([ + 'email' => 'john.doe@example.org', + 'attributes' => [ + 'firstname' => 'John', + 'lastname' => 'Doe', + ], + 'includeListIds' => ['789'], + 'templateId' => 456, + 'redirectionUrl' => 'http://localhost/newsletter?send=true&subscribe=true', + ], $json); + + return new Response(); + } + + throw new \RuntimeException('Unexpected request: ' . $request->getUri()->__toString()); + }) + ->shouldBeCalledOnce(); + + // act + $this->brevoListSubscriber->listSubscribe($event); + + $this->assertTrue(true); + } + + public function testlistSubscriberRedirectUrl(): void + { + $this->requestStack->push(Request::create('http://localhost/newsletter', 'POST')); + $event = $this->createFormSavePostEvent(true); + + $self = $this; + $this->client->send(Argument::cetera())->will(function($args) use ($self) { + /** @var RequestInterface $request */ + $request = $args[0]; + + if ('https://api.brevo.com/v3/contacts/doubleOptinConfirmation' === $request->getUri()->__toString()) { + $self->assertSame('POST', $request->getMethod()); + + $json = \json_decode($request->getBody()->getContents(), true); + + $self->assertSame([ + 'email' => 'john.doe@example.org', + 'attributes' => [ + 'firstname' => 'John', + 'lastname' => 'Doe', + ], + 'includeListIds' => ['789'], + 'templateId' => 456, + 'redirectionUrl' => '/test-page', + ], $json); + + return new Response(); + } + + throw new \RuntimeException('Unexpected request: ' . $request->getUri()->__toString()); + }) + ->shouldBeCalledOnce(); + + /** @var LinkProviderInterface|ObjectProphecy $linkProvider */ + $linkProvider = $this->prophesize(LinkProviderInterface::class); + $linkItem = new LinkItem('1', 'test-page', '/test-page', true); + $this->linkProviderPool->getProvider('page')->shouldBeCalled()->willReturn($linkProvider->reveal()); + $linkProvider->preload(['123-123-123'], 'de', true)->shouldBeCalled()->willReturn([$linkItem]); + + // act + $this->brevoListSubscriber->listSubscribe($event); + + $this->assertTrue(true); + } + + private function createFormSavePostEvent(bool $redirectLink = false): FormSavePostEvent + { + $symfonyForm = $this->prophesize(FormInterface::class); + $formConfiguration = new FormConfiguration('en'); + $form = new Form(); + $form->setDefaultLocale('en'); + $formTranslation = new FormTranslation(); + $formTranslation->setLocale('en'); + $formTranslation->setTitle('Form'); + $form->addTranslation($formTranslation); + + $fields = [ + [ + 'type' => 'firstName', + 'required' => true, + ], + [ + 'type' => 'lastName', + 'required' => true, + ], + [ + 'type' => 'email', + 'required' => true, + ], + [ + 'type' => 'brevo', + 'options' => [ + 'mailTemplateId' => '456', + 'listId' => '789', + ], + ], + ]; + + if ($redirectLink) { + $fields[3]['options']['redirectLink'] = [ + 'provider' => 'page', + 'href' => '123-123-123', + 'locale' => 'de', + ]; + } + + foreach ($fields as $key => $field) { + $formField = new FormField(); + $formField->setForm($form); + $formField->setDefaultLocale('en'); + $formField->setType($field['type']); + $formField->setOrder($key); + $formField->setKey($field['type']); + + $formFieldTranslation = $formField->getTranslation('en', true); + $formFieldTranslation->setTitle(\ucfirst($field['type'])); + $formFieldTranslation->setOptions($field['options'] ?? []); + + $form->addField($formField); + } + + $dynamic = new Dynamic( + 'page', + '123', + 'en', + $form, + [ + 'firstName' => 'John', + 'lastName' => 'Doe', + 'email' => 'john.doe@example.org', + 'brevo' => true, + ] + ); + + $symfonyForm->getData()->willReturn($dynamic); + + return new FormSavePostEvent($symfonyForm->reveal(), $formConfiguration); + } +} diff --git a/Tests/Unit/Event/SendinblueListSubscriberTest.php b/Tests/Unit/Event/SendinblueListSubscriberTest.php index 77dfebd6..51c63b0a 100644 --- a/Tests/Unit/Event/SendinblueListSubscriberTest.php +++ b/Tests/Unit/Event/SendinblueListSubscriberTest.php @@ -32,6 +32,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +/** + * @deprecated + */ class SendinblueListSubscriberTest extends TestCase { use ProphecyTrait; diff --git a/UPGRADE.md b/UPGRADE.md index b5f20bd1..01d01bd3 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,25 @@ # Upgrade +## 2.5.x + +### Deprecate SendinBlue's API v3 Php Library + +The Sendinblue Form Field is now deprecated; please use the Brevo Form Field instead. +Both fields offer the same functionality but rely on different SDKs. +Therefore, replace `sendinblue/api-v3-sdk` with `getbrevo/brevo-php` in your dependencies. +Additionally, update the configuration variable from `sendinblue_api_key` to `brevo_api_key` +in `config/packages/sulu_form.yaml`. + +You can find all Brevo configuration options [here](Resources/doc/brevo.md). + +#### Data Migration + +Use the following database query to update all existing forms. + +```sql +UPDATE `fo_form_fields` SET `type` = 'brevo' WHERE `type` = 'sendinblue'; +``` + ## 2.5.3 ### Deprecate attribute max on AttachmentType diff --git a/composer.json b/composer.json index 13287a74..2b4b165d 100644 --- a/composer.json +++ b/composer.json @@ -39,6 +39,7 @@ "doctrine/doctrine-bundle": "^1.10 || ^2.0", "drewm/mailchimp-api": "^2.2", "excelwebzone/recaptcha-bundle": "^1.4.2", + "getbrevo/brevo-php": "^2.0", "handcraftedinthealps/zendsearch": "^2.0", "jackalope/jackalope-doctrine-dbal": "^1.3.2 || ^2.0", "jangregor/phpstan-prophecy": "^1.0", @@ -66,7 +67,7 @@ "suggest": { "excelwebzone/recaptcha-bundle": "Allows to add recaptcha to any dynamic form", "drewm/mailchimp-api": "Allows to add a newsletter subscription over mailchimp to any dynamic form", - "sendinblue/api-v3-sdk": "Allows to add a newsletter subscription over sendinblue to any dynamic form" + "getbrevo/brevo-php": "Allows to add a newsletter subscription over Brevo to any dynamic form" }, "autoload": { "psr-4": { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index e2f04931..5b513f71 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -375,6 +375,26 @@ parameters: count: 1 path: Dynamic/Helper/SendinblueMailTemplateSelect.php + - + message: "#^Cannot access offset 'id' on object\\.$#" + count: 1 + path: Dynamic/Helper/BrevoListSelect.php + + - + message: "#^Cannot access offset 'name' on object\\.$#" + count: 1 + path: Dynamic/Helper/BrevoListSelect.php + + - + message: "#^Offset 'tag' on Brevo\\\\Client\\\\Model\\\\GetSmtpTemplateOverview on left side of \\?\\? does not exist\\.$#" + count: 1 + path: Dynamic/Helper/BrevoMailTemplateSelect.php + + - + message: "#^Unreachable statement \\- code above always terminates\\.$#" + count: 1 + path: Dynamic/Helper/BrevoMailTemplateSelect.php + - message: "#^Cannot call method getOption\\(\\) on Sulu\\\\Bundle\\\\FormBundle\\\\Entity\\\\FormFieldTranslation\\|null\\.$#" count: 4 @@ -535,6 +555,11 @@ parameters: count: 1 path: Dynamic/Types/SendinblueType.php + - + message: "#^Cannot call method getDefaultValue\\(\\) on Sulu\\\\Bundle\\\\FormBundle\\\\Entity\\\\FormFieldTranslation\\|null\\.$#" + count: 1 + path: Dynamic/Types/BrevoType.php + - message: "#^Method Sulu\\\\Bundle\\\\FormBundle\\\\Entity\\\\Dynamic\\:\\:getAttachment\\(\\) should return array\\\\|null but returns mixed\\.$#" count: 1 @@ -865,6 +890,56 @@ parameters: count: 1 path: Event/SendinblueListSubscriber.php + - + message: "#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\\.$#" + count: 1 + path: Event/BrevoListSubscriber.php + + - + message: "#^Cannot access offset 'listId' on mixed\\.$#" + count: 1 + path: Event/BrevoListSubscriber.php + + - + message: "#^Cannot access offset 'mailTemplateId' on mixed\\.$#" + count: 1 + path: Event/BrevoListSubscriber.php + + - + message: "#^Cannot access offset 'options' on mixed\\.$#" + count: 3 + path: Event/BrevoListSubscriber.php + + - + message: "#^Cannot access offset 'redirectLink' on mixed\\.$#" + count: 1 + path: Event/BrevoListSubscriber.php + + - + message: "#^Cannot access offset 'type' on mixed\\.$#" + count: 4 + path: Event/BrevoListSubscriber.php + + - + message: "#^Cannot access offset 'value' on mixed\\.$#" + count: 4 + path: Event/BrevoListSubscriber.php + + - + message: "#^Parameter \\#1 \\$hrefs of method Sulu\\\\Bundle\\\\MarkupBundle\\\\Markup\\\\Link\\\\LinkProviderInterface\\:\\:preload\\(\\) expects array\\, array\\ given\\.$#" + count: 1 + path: Event/BrevoListSubscriber.php + + - + message: "#^Parameter \\#1 \\$redirectLink of method Sulu\\\\Bundle\\\\FormBundle\\\\Event\\\\BrevoListSubscriber\\:\\:getUrlFromLink\\(\\) expects array\\{provider\\: string\\|null, target\\: string\\|null, anchor\\: string\\|null, query\\: string\\|null, href\\: string\\|null, title\\: string\\|null, rel\\: string\\|null, locale\\: string\\|null\\}, mixed given\\.$#" + count: 1 + path: Event/BrevoListSubscriber.php + + - + message: "#^Parameter \\#2 \\$locale of method Sulu\\\\Bundle\\\\MarkupBundle\\\\Markup\\\\Link\\\\LinkProviderInterface\\:\\:preload\\(\\) expects string, string\\|null given\\.$#" + count: 1 + path: Event/BrevoListSubscriber.php + - message: "#^Cannot call method get\\(\\) on Symfony\\\\Component\\\\HttpFoundation\\\\Request\\|null\\.$#" count: 3