feat: #3612558 Carry file attachments on OrchestraNotificationEvent and honor them in the mail channels

Fixes #3612558.

Summary

Adds file-attachment support to the channel-neutral OrchestraNotificationEvent, so a dispatcher can deliver generated files (a PDF ticket, a calendar invite, a receipt) alongside a notification. The driving consumer is the Yoyaku ticket submodule, which attaches per-order ticket PDFs to the confirmation email.

What changed

  • NotificationAttachment (@api, Drupal\orchestra): an immutable value object holding a filename, a MIME type and its source as either raw content or a stream-wrapper URI, via ::fromContent() / ::fromUri(). It stays transport neutral, exposing only the file's data, so each channel maps it to its own wire format (a future SMS, WhatsApp or chat channel maps the same object).
  • OrchestraNotificationEvent gains a trailing array $attachments = [] (backward compatible).
  • orchestra_mail maps each attachment to the Drupal mail attachment array and delivers it through params['attachments'].
  • orchestra_easy_email does the same at the mail layer (via the channel's existing mail alter), not on the Easy Email entity, so a private file (a ticket PDF in private://) is never subject to Easy Email's attachment-path allowlist, whose default permits only public://.

Each channel owns its own mapping, so the neutral contract never learns a transport format.

Tests

  • Unit: the value object's factories and content-vs-URI exclusivity.
  • Kernel, per channel: present vs empty attachments, content vs URI, and multiple files, asserting the exact mail-attachment shape and that the private carrier key is consumed.

Docs

Updated docs/notification-delivery.md (event schema and an Attachments section) and both channel READMEs.

Merge request reports

Loading