/** * Send an email notification to users in workspace * * @param array $stat Workspace access array from \TYPO3\CMS\Core\Authentication\BackendUserAuthentication::checkWorkspace() * @param int $stageId New Stage number: 0 = editing, 1= just ready for review, 10 = ready for publication, -1 = rejected! * @param string $table Table name of element (or list of element names if $id is zero) * @param int $id Record uid of element (if zero, then $table is used as reference to element(s) alone) * @param string $comment User comment sent along with action * @param DataHandler $tcemainObj TCEmain object * @param array $notificationAlternativeRecipients List of recipients to notify instead of be_users selected by sys_workspace, list is generated by workspace extension module * @return void */ protected function notifyStageChange(array $stat, $stageId, $table, $id, $comment, DataHandler $tcemainObj, array $notificationAlternativeRecipients = array()) { $workspaceRec = BackendUtility::getRecord('sys_workspace', $stat['uid']); // So, if $id is not set, then $table is taken to be the complete element name! $elementName = $id ? $table . ':' . $id : $table; if (!is_array($workspaceRec)) { return; } // Get the new stage title from workspaces library, if workspaces extension is installed if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('workspaces')) { $stageService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\StagesService::class); $newStage = $stageService->getStageTitle((int) $stageId); } else { // @todo CONSTANTS SHOULD BE USED - tx_service_workspace_workspaces // @todo use localized labels // Compile label: switch ((int) $stageId) { case 1: $newStage = 'Ready for review'; break; case 10: $newStage = 'Ready for publishing'; break; case -1: $newStage = 'Element was rejected!'; break; case 0: $newStage = 'Rejected element was noticed and edited'; break; default: $newStage = 'Unknown state change!?'; } } if (count($notificationAlternativeRecipients) == 0) { // Compile list of recipients: $emails = array(); switch ((int) $stat['stagechg_notification']) { case 1: switch ((int) $stageId) { case 1: $emails = $this->getEmailsForStageChangeNotification($workspaceRec['reviewers']); break; case 10: $emails = $this->getEmailsForStageChangeNotification($workspaceRec['adminusers'], TRUE); break; case -1: // List of elements to reject: $allElements = explode(',', $elementName); // Traverse them, and find the history of each foreach ($allElements as $elRef) { list($eTable, $eUid) = explode(':', $elRef); $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('log_data,tstamp,userid', 'sys_log', 'action=6 and details_nr=30 AND tablename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($eTable, 'sys_log') . ' AND recuid=' . (int) $eUid, '', 'uid DESC'); // Find all implicated since the last stage-raise from editing to review: foreach ($rows as $dat) { $data = unserialize($dat['log_data']); $emails = $this->getEmailsForStageChangeNotification($dat['userid'], TRUE) + $emails; if ($data['stage'] == 1) { break; } } } break; case 0: $emails = $this->getEmailsForStageChangeNotification($workspaceRec['members']); break; default: $emails = $this->getEmailsForStageChangeNotification($workspaceRec['adminusers'], TRUE); } break; case 10: $emails = $this->getEmailsForStageChangeNotification($workspaceRec['adminusers'], TRUE); $emails = $this->getEmailsForStageChangeNotification($workspaceRec['reviewers']) + $emails; $emails = $this->getEmailsForStageChangeNotification($workspaceRec['members']) + $emails; break; default: // Do nothing } } else { $emails = $notificationAlternativeRecipients; } // prepare and then send the emails if (count($emails)) { // Path to record is found: list($elementTable, $elementUid) = explode(':', $elementName); $elementUid = (int) $elementUid; $elementRecord = BackendUtility::getRecord($elementTable, $elementUid); $recordTitle = BackendUtility::getRecordTitle($elementTable, $elementRecord); if ($elementTable == 'pages') { $pageUid = $elementUid; } else { BackendUtility::fixVersioningPid($elementTable, $elementRecord); $pageUid = $elementUid = $elementRecord['pid']; } // fetch the TSconfig settings for the email // old way, options are TCEMAIN.notificationEmail_body/subject $TCEmainTSConfig = $tcemainObj->getTCEMAIN_TSconfig($pageUid); // new way, options are // pageTSconfig: tx_version.workspaces.stageNotificationEmail.subject // userTSconfig: page.tx_version.workspaces.stageNotificationEmail.subject $pageTsConfig = BackendUtility::getPagesTSconfig($pageUid); $emailConfig = $pageTsConfig['tx_version.']['workspaces.']['stageNotificationEmail.']; $markers = array('###RECORD_TITLE###' => $recordTitle, '###RECORD_PATH###' => BackendUtility::getRecordPath($elementUid, '', 20), '###SITE_NAME###' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], '###SITE_URL###' => GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir, '###WORKSPACE_TITLE###' => $workspaceRec['title'], '###WORKSPACE_UID###' => $workspaceRec['uid'], '###ELEMENT_NAME###' => $elementName, '###NEXT_STAGE###' => $newStage, '###COMMENT###' => $comment, '###USER_REALNAME###' => $tcemainObj->BE_USER->user['realName'], '###USER_FULLNAME###' => $tcemainObj->BE_USER->user['realName'], '###USER_USERNAME###' => $tcemainObj->BE_USER->user['username']); // add marker for preview links if workspace extension is loaded if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('workspaces')) { $this->workspaceService = GeneralUtility::makeInstance(\TYPO3\CMS\Workspaces\Service\WorkspaceService::class); // only generate the link if the marker is in the template - prevents database from getting to much entries if (GeneralUtility::isFirstPartOfStr($emailConfig['message'], 'LLL:')) { $tempEmailMessage = $GLOBALS['LANG']->sL($emailConfig['message']); } else { $tempEmailMessage = $emailConfig['message']; } if (strpos($tempEmailMessage, '###PREVIEW_LINK###') !== FALSE) { $markers['###PREVIEW_LINK###'] = $this->workspaceService->generateWorkspacePreviewLink($elementUid); } unset($tempEmailMessage); $markers['###SPLITTED_PREVIEW_LINK###'] = $this->workspaceService->generateWorkspaceSplittedPreviewLink($elementUid, TRUE); } // Hook for preprocessing of the content for formmails: if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/version/class.tx_version_tcemain.php']['notifyStageChange-postModifyMarkers'])) { foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/version/class.tx_version_tcemain.php']['notifyStageChange-postModifyMarkers'] as $_classRef) { $_procObj =& GeneralUtility::getUserObj($_classRef); $markers = $_procObj->postModifyMarkers($markers, $this); } } // send an email to each individual user, to ensure the // multilanguage version of the email $emailRecipients = array(); // an array of language objects that are needed // for emails with different languages $languageObjects = array($GLOBALS['LANG']->lang => $GLOBALS['LANG']); // loop through each recipient and send the email foreach ($emails as $recipientData) { // don't send an email twice if (isset($emailRecipients[$recipientData['email']])) { continue; } $emailSubject = $emailConfig['subject']; $emailMessage = $emailConfig['message']; $emailRecipients[$recipientData['email']] = $recipientData['email']; // check if the email needs to be localized // in the users' language if (GeneralUtility::isFirstPartOfStr($emailSubject, 'LLL:') || GeneralUtility::isFirstPartOfStr($emailMessage, 'LLL:')) { $recipientLanguage = $recipientData['lang'] ? $recipientData['lang'] : 'default'; if (!isset($languageObjects[$recipientLanguage])) { // a LANG object in this language hasn't been // instantiated yet, so this is done here /** @var $languageObject \TYPO3\CMS\Lang\LanguageService */ $languageObject = GeneralUtility::makeInstance(\TYPO3\CMS\Lang\LanguageService::class); $languageObject->init($recipientLanguage); $languageObjects[$recipientLanguage] = $languageObject; } else { $languageObject = $languageObjects[$recipientLanguage]; } if (GeneralUtility::isFirstPartOfStr($emailSubject, 'LLL:')) { $emailSubject = $languageObject->sL($emailSubject); } if (GeneralUtility::isFirstPartOfStr($emailMessage, 'LLL:')) { $emailMessage = $languageObject->sL($emailMessage); } } $emailSubject = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($emailSubject, $markers, '', TRUE, TRUE); $emailMessage = \TYPO3\CMS\Core\Html\HtmlParser::substituteMarkerArray($emailMessage, $markers, '', TRUE, TRUE); // Send an email to the recipient /** @var $mail \TYPO3\CMS\Core\Mail\MailMessage */ $mail = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Mail\MailMessage::class); if (!empty($recipientData['realName'])) { $recipient = array($recipientData['email'] => $recipientData['realName']); } else { $recipient = $recipientData['email']; } $mail->setTo($recipient)->setSubject($emailSubject)->setFrom(\TYPO3\CMS\Core\Utility\MailUtility::getSystemFrom())->setBody($emailMessage); $mail->send(); } $emailRecipients = implode(',', $emailRecipients); $tcemainObj->newlog2('Notification email for stage change was sent to "' . $emailRecipients . '"', $table, $id); } }