Problem/Motivation
TemplateForm and TemplateDeleteForm type-hint the concrete Drupal\Core\Messenger\Messenger class in their constructors instead of Drupal\Core\Messenger\MessengerInterface.
Any module that decorates or replaces the core messenger service therefore breaks both forms with a TypeError. The service is a documented, decoratable service and its contract is the interface, not the concrete class.
I hit this with Drupal Canvas, which decorates messenger to suppress messages on its API routes:
# canvas.services.yml Drupal\canvas\Messenger: decorates: messenger
Drupal\canvas\Messenger correctly implements MessengerInterface, but does not extend core's concrete Messenger class — which is normal, correct decorator design. Canvas is just the module I happened to have; anything decorating messenger triggers this.
Steps to reproduce
- Install Workbench Email 3.0.7 on Drupal 11.4.4.
- Enable any module that decorates the
messengerservice (e.g. Drupal Canvas, or Info Messages). - Visit
/admin/config/workflow/workbench-email-template/add.
Result:
TypeError: Drupal\workbench_email\Form\TemplateForm::__construct(): Argument #6 ($messenger) must be of type Drupal\Core\Messenger\Messenger, Drupal\canvas\Messenger given, called in .../workbench_email/src/Form/TemplateForm.php on line 96
TemplateDeleteForm has the identical defect and fails the same way on the template delete route.
Proposed resolution
Type-hint the interface rather than the concrete class in both constructors, plus the matching use, @param and @var docblocks.
src/Form/TemplateForm.php:
-use Drupal\Core\Messenger\Messenger;
+use Drupal\Core\Messenger\MessengerInterface;
- public function __construct(..., ModuleHandlerInterface $module_handler, Messenger $messenger) {
+ public function __construct(..., ModuleHandlerInterface $module_handler, MessengerInterface $messenger) {
src/Form/TemplateDeleteForm.php:
-use Drupal\Core\Messenger\Messenger;
+use Drupal\Core\Messenger\MessengerInterface;
- public function __construct(Messenger $messenger) {
+ public function __construct(MessengerInterface $messenger) {
No behavioural change: both forms only ever call addMessage() and addStatus(), which are both declared on MessengerInterface.
Precedent
This is a known anti-pattern with an accepted resolution, including once in this module already:
- #2852828 — this module, same class of bug against a different service: "Workbench email processor cannot be initiated, when another module overrides the LoggerChannelFactory". Fixed. The rest of the codebase was never swept for concrete type hints, which is why these two forms still carry it.
- entity_clone #3246560 — identical bug triggered by the Info Messages module's decorator. Fixed by switching to
MessengerInterface, with the reviewer noting that typehinting the interface is best practice.
This also fits the Drupal 12 readiness work already underway in 3.x — depending on a concrete service implementation is exactly the kind of coupling that breaks across major versions.
Remaining tasks
- Review MR !43.
User interface changes
None.
API changes
The constructor type hints widen from Messenger to MessengerInterface. This is a widening, not a narrowing, so all existing callers remain valid. Any subclass that narrowed the parameter back to the concrete class would be affected, but none exist in this module.
Data model changes
None.
Issue fork workbench_email-3617864
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
rajendar reddy commentedComment #4
rajendar reddy commentedComment #6
larowlanThanks! committed to 3.x
Comment #8
larowlanTagging 3.0.8