/**
     * 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);
        }
    }