‪TYPO3CMS  ‪main
StageChangeNotification.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Http\Message\ServerRequestInterface;
21 use Psr\Log\LoggerAwareInterface;
22 use Psr\Log\LoggerAwareTrait;
23 use Symfony\Component\Mailer\Exception\TransportException;
24 use Symfony\Component\Mime\Address;
25 use Symfony\Component\Mime\Exception\RfcComplianceException;
26 use TYPO3\CMS\Backend\Utility\BackendUtility;
34 
42 class ‪StageChangeNotification implements LoggerAwareInterface
43 {
44  use LoggerAwareTrait;
45 
46  public function ‪__construct(
47  private readonly ‪StagesService $stagesService,
48  private readonly ‪PreviewUriBuilder $previewUriBuilder,
49  private readonly ‪MailerInterface $mailer
50  ) {}
51 
62  public function ‪notifyStageChange(array $workspaceRecord, int $stageId, array $affectedElements, string $comment, array $recipients, array $currentUser): void
63  {
64  [$elementTable, $elementUid] = reset($affectedElements);
65  $elementUid = (int)$elementUid;
66  $elementRecord = (array)BackendUtility::getRecord($elementTable, $elementUid, '*', '', false);
67  $recordTitle = BackendUtility::getRecordTitle($elementTable, $elementRecord);
68  $pageUid = $this->‪findFirstPageId($elementTable, $elementUid, $elementRecord);
69  $emailConfig = BackendUtility::getPagesTSconfig($pageUid)['tx_workspaces.']['emails.'] ?? [];
70  $emailConfig = GeneralUtility::removeDotsFromTS($emailConfig);
71 
72  $previewLink = '';
73  try {
74  $languageId = $elementRecord[‪$GLOBALS['TCA'][$elementTable]['ctrl']['languageField'] ?? ''] ?? 0;
75  $previewLink = $this->previewUriBuilder->buildUriForPage($pageUid, $languageId);
76  } catch (‪UnableToLinkToPageException $e) {
77  // Generating a preview for a page that is a "delete placeholder"
78  // in workspaces fails. No preview link in this case.
79  }
80 
81  $viewPlaceholders = [
82  'pageId' => $pageUid,
83  'workspace' => $workspaceRecord,
84  'rootLine' => BackendUtility::getRecordPath($pageUid, '', 20),
85  'currentUser' => $currentUser,
86  'additionalMessage' => $comment,
87  'recordTitle' => $recordTitle,
88  'affectedElements' => $affectedElements,
89  'nextStage' => $this->stagesService->getStageTitle($stageId),
90  'previewLink' => $previewLink,
91  ];
92 
93  $sentEmails = [];
94  foreach ($recipients as $recipientData) {
95  // don't send an email twice
96  if (in_array($recipientData['email'], $sentEmails, true)) {
97  continue;
98  }
99  $sentEmails[] = $recipientData['email'];
100  try {
101  $this->‪sendEmail($recipientData, $emailConfig, $viewPlaceholders);
102  } catch (TransportException $e) {
103  $this->logger->warning('Could not send notification email to "{recipient}" due to mailer settings error', [
104  'recipient' => $recipientData['email'],
105  'recipientList' => array_column($recipients, 'email'),
106  'exception' => $e,
107  ]);
108  // At this point we break since the next attempts will also fail due to the invalid mailer settings
109  break;
110  } catch (RfcComplianceException $e) {
111  $this->logger->warning('Could not send notification email to "{recipient}" due to invalid email address', [
112  'recipient' => $recipientData['email'],
113  'exception' => $e,
114  ]);
115  }
116  }
117  }
118 
127  protected function ‪findFirstPageId(string $elementTable, int $elementUid, array $elementRecord): int
128  {
129  if ($elementTable === 'pages') {
130  return $elementUid;
131  }
132  $pageId = $elementRecord['pid'];
133  BackendUtility::workspaceOL($elementTable, $elementRecord);
134  return (int)($elementRecord['pid'] ?? $pageId);
135  }
136 
140  protected function ‪sendEmail(array $recipientData, array $emailConfig, array $variablesForView): void
141  {
142  $templatePaths = new ‪TemplatePaths(array_replace_recursive(‪$GLOBALS['TYPO3_CONF_VARS']['MAIL'], $emailConfig));
143  $emailObject = GeneralUtility::makeInstance(FluidEmail::class, $templatePaths);
144  $emailObject
145  ->to(new Address($recipientData['email'], $recipientData['realName'] ?? ''))
146  // Will be overridden by the template
147  ->subject('TYPO3 Workspaces: Stage Change')
148  ->setTemplate('StageChangeNotification')
149  ->assignMultiple($variablesForView)
150  ->assign('language', $recipientData['lang'] ?? 'default');
151 
152  // Injecting normalized params
153  if (‪$GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface) {
154  $emailObject->setRequest(‪$GLOBALS['TYPO3_REQUEST']);
155  }
156  if ($emailConfig['format']) {
157  $emailObject->format($emailConfig['format']);
158  }
159  if (!empty($emailConfig['senderEmail']) && GeneralUtility::validEmail($emailConfig['senderEmail'])) {
160  $emailObject->from(new Address($emailConfig['senderEmail'], $emailConfig['senderName'] ?? ''));
161  }
162  $this->mailer->send($emailObject);
163  }
164 }
‪TYPO3\CMS\Workspaces\Notification
Definition: StageChangeNotification.php:18
‪TYPO3\CMS\Fluid\View\TemplatePaths
Definition: TemplatePaths.php:39
‪TYPO3\CMS\Workspaces\Notification\StageChangeNotification\findFirstPageId
‪int findFirstPageId(string $elementTable, int $elementUid, array $elementRecord)
Definition: StageChangeNotification.php:127
‪TYPO3\CMS\Core\Mail\MailerInterface
Definition: MailerInterface.php:28
‪TYPO3\CMS\Workspaces\Notification\StageChangeNotification\sendEmail
‪sendEmail(array $recipientData, array $emailConfig, array $variablesForView)
Definition: StageChangeNotification.php:140
‪TYPO3\CMS\Workspaces\Notification\StageChangeNotification
Definition: StageChangeNotification.php:43
‪TYPO3\CMS\Workspaces\Notification\StageChangeNotification\__construct
‪__construct(private readonly StagesService $stagesService, private readonly PreviewUriBuilder $previewUriBuilder, private readonly MailerInterface $mailer)
Definition: StageChangeNotification.php:46
‪TYPO3\CMS\Core\Mail\FluidEmail
Definition: FluidEmail.php:35
‪TYPO3\CMS\Workspaces\Preview\PreviewUriBuilder
Definition: PreviewUriBuilder.php:47
‪TYPO3\CMS\Workspaces\Service\StagesService
Definition: StagesService.php:33
‪TYPO3\CMS\Workspaces\Notification\StageChangeNotification\notifyStageChange
‪notifyStageChange(array $workspaceRecord, int $stageId, array $affectedElements, string $comment, array $recipients, array $currentUser)
Definition: StageChangeNotification.php:62
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52