postoffice-1.0.x-dev/extensions/postoffice_image/src/EventSubscriber/ImageAdjustmentSubscriber.php
extensions/postoffice_image/src/EventSubscriber/ImageAdjustmentSubscriber.php
<?php
namespace Drupal\postoffice_image\EventSubscriber;
use Drupal\Component\Utility\Html;
use Drupal\file\Entity\File;
use Drupal\image\Entity\ImageStyle;
use Drupal\image\ImageStyleInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Mailer\Event\MessageEvent;
use Symfony\Component\Mime\Email;
/**
* Applies image adjustments defined by field formatter third party settings.
*
* Runs with priority -50 (after Symfony MessageListener which is responsible
* for body rendering).
*/
class ImageAdjustmentSubscriber implements EventSubscriberInterface {
/**
* Constructs new message subscriber for email image adjustments.
*/
public function __construct(protected RequestStack $requestStack) {
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
$events = [];
$events[MessageEvent::class] = ['onMessage', -50];
return $events;
}
/**
* Embeds images supplied by image field formatter.
*/
public function onMessage(MessageEvent $event): void {
$message = $event->getMessage();
if (
$message instanceof Email &&
$message->getHtmlBody() && (
strpos($message->getHtmlBody(), 'data-postoffice-image-embed-target-id') !== FALSE ||
strpos($message->getHtmlBody(), 'data-postoffice-image-transform-urls') !== FALSE
)
) {
$dom = Html::load($message->getHtmlBody());
$xpath = new \DOMXpath($dom);
foreach ($xpath->query("//img[@data-postoffice-image-embed-target-id]") as $node) {
$fileId = $node->getAttribute('data-postoffice-image-embed-target-id');
$style = $node->getAttribute('data-postoffice-image-embed-style-name');
$file = File::load($fileId);
if ($file) {
$uri = $file->getFileUri();
if (!empty($style)) {
$styleEntity = ImageStyle::load($style);
$uri = $styleEntity ? $this->generateStyle($uri, $styleEntity) : NULL;
}
if (!empty($uri)) {
$cid = \urlencode(\basename($uri));
$message->embedFromPath($uri, $cid);
$node->setAttribute('src', 'cid:' . $cid);
}
}
}
foreach ($xpath->query("//img[@data-postoffice-image-transform-urls and starts-with(@src, '/') and not(starts-with(@src, '//'))]") as $node) {
$url = $this->getSchemeAndHttpHost() . $node->getAttribute('src');
$node->setAttribute('src', $url);
}
$message->html(Html::serialize($dom));
}
}
/**
* Generates derivative and return URI for given image / style.
*/
protected function generateStyle($imageUri, ImageStyleInterface $style): ?string {
$derivativeUri = $style->buildUri($imageUri);
if (!file_exists($derivativeUri)) {
$style->createDerivative($imageUri, $derivativeUri);
}
return file_exists($derivativeUri) ? $derivativeUri : NULL;
}
/**
* Returns scheme and HTTP host.
*/
protected function getSchemeAndHttpHost(): string {
$request = $this->requestStack->getCurrentRequest();
return $request->getSchemeAndHttpHost();
}
}
