- Issue created by @adamps
- Status changed to Needs review
over 1 year ago 6:39pm 11 June 2023 - last update
over 1 year ago 5 pass - last update
over 1 year ago 5 pass - π¬π§United Kingdom adamps
This can't be fixed until 2.x. Created π Warn about unsupported override combinations Fixed to warn about it in the meantime.
- ππΊHungary huzooka Hungary ππΊπͺπΊ
We just run into this issue with 1.3.0 (issue still seems to be present in 1.x too).
We have custom module namedcontact_form
. If we try to send an email on behalf of this module, Drupal Symfony Mailer won't find a matching email builder (nor a dynamically created instance using theLegacyEmailBuilder
class).How we worked around this temporarily
We prefixed the mail module param with an extra string, and we added an email builder plugin with the mathcing ID.
Analysis
This happens because we won't have any builder plugin definition for this module. Why? Let's see what happens during the discovery phase under the hood:
- The discovery specified in
DefaultPluginManager
discover all the available email builder plugins. EmailBuilderManager::processDefinition()
processes the definitions. In case of theContactPageEmailBuilder
plugin, the plugin IDcontact_form
also must contain the config entity type ID associated with the email builder plugin (thehas_entity
annotation is set to TRUE),::processDefinition
checks whether there is a entity type with IDcontact_form
available or not. It isn't (we don't have contact module being enabled), so the provider in the definition is set to_
.symfony_mailer_mailer_builder_info_alter
start to alter these definitions.- Our module's
hook_mail()
implementation gets discovered, but since Drupal Symfony Mailer already defines a plugin with IDcontact_form
, the logic inside the foreach loop won't generate builder plugin instance for our module - because there is already a builder plugin with that ID! - Since the contact module (what
contact_form
builder plugin provider is '_', it gets removed inDefaultPluginManager::findDefinitions()
. - So when we try to send an email through that module with
MailManagerReplacement::mail()
,EmailBuilderManagerInterface->createInstanceFromMessage()
wont't find any matching email builder plugin, so it doesn't return anything (which is actually equal to returning aNULL
in this case) β‘οΈ we get the same error message as in the IS (but for a bit different reason).
Suggestion for a BC-safe fix
Separate module name / builder plugin ID / ID of the related entity type:
- Instead of assuming that
plugin ID === module
name, utilize theprovider
annotation property: the provider could be added to the plugin annotations:provider => "contact"
. Any module can define plugin on behalf of other modules! This could replace the problematic parts in point 2.If this turns to be trickier than ideal, introduce a '
provider_module
' or 'module
' annotation instead, but I think that usingprovider
is enough. - Instead of assuming that the related entity type is the same as the plugin ID (as I see this happens if
has_entity
is set to TRUE), add a 'content_entity_type_id
' (or something similar) annotation property (and maybe deprecate 'has_entity
'). BTW, does this module uses this info for anything else than calculating the provider? (Didn't checked yet, just thinking loudly.) - Change logic behind
EmailBuilderManager::createInstanceFromMessage():
:- Instead of assuming that plugin IDs are matching
$module
or$module.$key
pattern, find the corresponding plugin based on theprovider
annotation of the builder plugin (and also checking the sub_types if any). But! The current approach could be kept as fallback (so we can still use plugin IDs likemymodule.my_email_key
, but it won't be a must.) AND - Make
EmailBuilderManager
usingFallbackPluginManagerInterface
, and convertLegacyMailBuilder
into a real (annotated) plugin - which then can be used as the fallback builder plugin (e.g. this is what theBlock(Plugin)Manager
does in Drupal core). This can eliminate the requirement on the logic implemented insymfony_mailer_mailer_builder_info_alter
.
- Instead of assuming that plugin IDs are matching
@AdamPS, what do you think?
- The discovery specified in
- π¬π§United Kingdom adamps
@huzooka interesting, thanks for the report. I agree that the problem you see has the same symptoms as this issue. However it's a separate bug as it has different steps to reproduce, and will have a different fix. Therefore I raised a new issue π Disabled overrides should not cause conflicts Fixed - please continue the discussion there.
LegacyEmailBuilder
doesn't have @EmailBuilder annotation because we want to create multiple instances of it with different id, label and provider - seesymfony_mailer_mailer_builder_info_alter()
. These instances are used by the mailer policy form and perhaps other places. - π¬π§United Kingdom adamps
@huzooka Please can you test the patch on π Disabled overrides should not cause conflicts Fixed ?
- π¬π§United Kingdom adamps
Fixed by π Improvements to email interface Active , but excluding the update hook.