17 use Doctrine\DBAL\DBALException;
18 use Doctrine\DBAL\Platforms\SQLServerPlatform;
80 $this->notificationEmailInfo = [];
98 if ($command ===
'version') {
99 $commandIsProcessed =
true;
100 $action = (string)$value[
'action'];
101 $comment = !empty($value[
'comment']) ? $value[
'comment'] :
'';
102 $notificationAlternativeRecipients = isset($value[
'notificationAlternativeRecipients']) && is_array($value[
'notificationAlternativeRecipients']) ? $value[
'notificationAlternativeRecipients'] : [];
112 (
bool)$value[
'swapIntoWS'],
116 $notificationAlternativeRecipients
126 $elementIds = GeneralUtility::trimExplode(
',', $id,
true);
127 foreach ($elementIds as $elementId) {
135 $notificationAlternativeRecipients
154 foreach ($this->notificationEmailInfo as $notifItem) {
155 $this->
notifyStageChange($notifItem[
'shared'][0], $notifItem[
'shared'][1], implode(
', ', $notifItem[
'elements']), 0, $notifItem[
'shared'][2], $dataHandler, $notifItem[
'alternativeRecipients']);
158 $this->notificationEmailInfo = [];
160 $this->remappedIds = [];
178 if ($recordWasDeleted) {
181 $recordWasDeleted =
true;
184 if ($record[
'pid'] != -1) {
186 $record = $wsVersion;
187 $id = $record[
'uid'];
192 if ($record[
'pid'] == -1) {
193 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'versioningWS']) {
195 if ($dataHandler->BE_USER->workspace == 0 || (
int)$record[
't3ver_wsid'] == $dataHandler->BE_USER->workspace) {
201 && !empty($dataHandler->cmdmap[$table][$liveRec[
'uid']][
'version'][
'action'])
202 && !empty($dataHandler->cmdmap[$table][$liveRec[
'uid']][
'version'][
'swapWith'])
203 && $dataHandler->cmdmap[$table][$liveRec[
'uid']][
'version'][
'action'] ===
'swap'
204 && $dataHandler->cmdmap[$table][$liveRec[
'uid']][
'version'][
'swapWith'] == $id
212 GeneralUtility::makeInstance(ConnectionPool::class)
213 ->getConnectionForTable($table)
217 't3ver_label' =>
'DELETED!',
225 } elseif ($record[
't3ver_wsid'] == 0 || !$liveRecordVersionState->indicatesPlaceholder()) {
231 if (!empty($movePlaceholder)) {
232 $dataHandler->
deleteEl($table, $movePlaceholder[
'uid']);
241 $dataHandler->
newlog(
'Tried to delete record from another workspace', 1);
244 $dataHandler->
newlog(
'Versioning not enabled for record with PID = -1!', 2);
246 } elseif ($res = $dataHandler->BE_USER->workspaceAllowLiveRecordsInPID($record[
'pid'], $table)) {
251 $dataHandler->
newlog(
'Stage of root point did not allow for deletion', 1);
260 GeneralUtility::makeInstance(ConnectionPool::class)
261 ->getConnectionForTable($table)
267 [
'uid' => (
int)$wsRec[
'uid']]
273 $copyMappingArray = $dataHandler->copyMappingArray;
279 foreach ($versionizedElements as $versionizedTableName => $versionizedOriginalIds) {
280 foreach ($versionizedOriginalIds as $versionizedOriginalId => $_) {
300 if ($command ===
'delete') {
322 public function moveRecord($table, $uid, $destPid, array $propArr, array $moveRec, $resolvedPid, &$recordWasMoved,
DataHandler $dataHandler)
325 if ($dataHandler->BE_USER->workspace === 0) {
331 if ($movePlaceHolder !==
false) {
332 $resolvedPid = $movePlaceHolder[
'pid'];
335 $recordWasMoved =
true;
345 if (empty($WSversion[
'uid'])) {
348 if ((
int)$resolvedPid !== (
int)$propArr[
'pid']) {
351 } elseif ($dataHandler->
isRecordCopied($table, $uid) && (
int)$dataHandler->copyMappingArray[$table][$uid] === (
int)$WSversion[
'uid']) {
353 if ((
int)$resolvedPid !== (
int)$propArr[
'pid']) {
359 $workspaceAccessBlocked = [];
361 $recIsNewVersion = $moveRecVersionState->indicatesPlaceholder();
362 $destRes = $dataHandler->BE_USER->workspaceAllowLiveRecordsInPID($resolvedPid, $table);
365 if (!$recIsNewVersion) {
366 $errorCode = $dataHandler->BE_USER->workspaceCannotEditRecord($table, $WSversion[
'uid'] ? $WSversion[
'uid'] : $uid);
368 $workspaceAccessBlocked[
'src1'] =
'Record could not be edited in workspace: ' . $errorCode .
' ';
369 } elseif (!$canMoveRecord && $dataHandler->BE_USER->workspaceAllowLiveRecordsInPID($moveRec[
'pid'], $table) <= 0) {
370 $workspaceAccessBlocked[
'src2'] =
'Could not remove record from table "' . $table .
'" from its page "' . $moveRec[
'pid'] .
'" ';
379 if (!($destRes > 0 || $canMoveRecord && !$destRes)) {
380 $workspaceAccessBlocked[
'dest1'] =
'Could not insert record from table "' . $table .
'" in destination PID "' . $resolvedPid .
'" ';
381 } elseif ($destRes == 1 && $WSversion[
'uid']) {
382 $workspaceAccessBlocked[
'dest2'] =
'Could not insert other versions in destination PID ';
384 if (empty($workspaceAccessBlocked)) {
392 $recordWasMoved =
false;
395 $dataHandler->
newlog(
'Move attempt failed due to workspace restrictions: ' . implode(
' // ', $workspaceAccessBlocked), 1);
410 if (empty($versionedRecord)) {
413 foreach ($versionedRecord as $field => $value) {
414 if (empty(
$GLOBALS[
'TCA'][$table][
'columns'][$field][
'config'])) {
424 $GLOBALS[
'TCA'][$table][
'columns'][$field][
'config']
443 $inlineProcessing = (
444 ($inlineFieldType ===
'list' || $inlineFieldType ===
'field')
446 && (!isset($configuration[
'behaviour'][
'disableMovingChildrenWithParent']) || !$configuration[
'behaviour'][
'disableMovingChildrenWithParent'])
449 if ($inlineProcessing) {
450 if ($table ===
'pages') {
453 $resolvedPageId = $uid;
457 $dbAnalysis->start($value, $configuration[
'foreign_table'],
'', $uid, $table, $configuration);
461 foreach ($dbAnalysis->itemArray as $item) {
463 if (empty($versionedRecord) ||
VersionState::cast($versionedRecord[
't3ver_state'])->indicatesPlaceholder()) {
466 $dataHandler->
moveRecord($item[
'table'], $item[
'id'], $resolvedPageId);
485 protected function notifyStageChange(array $stat, $stageId, $table, $id, $comment,
DataHandler $dataHandler, array $notificationAlternativeRecipients = [])
489 $elementName = $id ? $table .
':' . $id : $table;
490 if (!is_array($workspaceRec)) {
495 $stageService = GeneralUtility::makeInstance(StagesService::class);
496 $newStage = $stageService->getStageTitle((
int)$stageId);
497 if (empty($notificationAlternativeRecipients)) {
500 switch ((
int)$stat[
'stagechg_notification']) {
502 switch ((
int)$stageId) {
511 $allElements = explode(
',', $elementName);
513 foreach ($allElements as $elRef) {
514 [$eTable, $eUid] = explode(
':', $elRef);
516 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
517 ->getQueryBuilderForTable(
'sys_log');
519 $queryBuilder->getRestrictions()->removeAll();
521 $result = $queryBuilder
522 ->select(
'log_data',
'tstamp',
'userid')
525 $queryBuilder->expr()->eq(
527 $queryBuilder->createNamedParameter(6, \PDO::PARAM_INT)
529 $queryBuilder->expr()->eq(
531 $queryBuilder->createNamedParameter(30, \PDO::PARAM_INT)
533 $queryBuilder->expr()->eq(
535 $queryBuilder->createNamedParameter($eTable, \PDO::PARAM_STR)
537 $queryBuilder->expr()->eq(
539 $queryBuilder->createNamedParameter($eUid, \PDO::PARAM_INT)
542 ->orderBy(
'uid',
'DESC')
546 while ($dat = $result->fetch()) {
547 $data = unserialize($dat[
'log_data']);
549 if ($data[
'stage'] == 1) {
571 $emails = $notificationAlternativeRecipients;
574 if (!empty($emails)) {
575 $previewUriBuilder = GeneralUtility::makeInstance(PreviewUriBuilder::class);
577 [$elementTable, $elementUid] = explode(
':', $elementName);
578 $elementUid = (int)$elementUid;
581 if ($elementTable ===
'pages') {
582 $pageUid = $elementUid;
585 $pageUid = ($elementUid = $elementRecord[
'pid']);
592 $emailConfig = $pageTsConfig[
'tx_version.'][
'workspaces.'][
'stageNotificationEmail.'];
594 '###RECORD_TITLE###' => $recordTitle,
596 '###SITE_NAME###' =>
$GLOBALS[
'TYPO3_CONF_VARS'][
'SYS'][
'sitename'],
597 '###SITE_URL###' => GeneralUtility::getIndpEnv(
'TYPO3_SITE_URL') . TYPO3_mainDir,
598 '###WORKSPACE_TITLE###' => $workspaceRec[
'title'],
599 '###WORKSPACE_UID###' => $workspaceRec[
'uid'],
600 '###ELEMENT_NAME###' => $elementName,
601 '###NEXT_STAGE###' => $newStage,
602 '###COMMENT###' => $comment,
604 '###USER_REALNAME###' => $dataHandler->BE_USER->user[
'realName'],
605 '###USER_FULLNAME###' => $dataHandler->BE_USER->user[
'realName'],
606 '###USER_USERNAME###' => $dataHandler->BE_USER->user[
'username']
609 $this->workspaceService = GeneralUtility::makeInstance(WorkspaceService::class);
611 if (GeneralUtility::isFirstPartOfStr($emailConfig[
'message'],
'LLL:')) {
614 $tempEmailMessage = $emailConfig[
'message'];
616 if (strpos($tempEmailMessage,
'###PREVIEW_LINK###') !==
false) {
617 $markers[
'###PREVIEW_LINK###'] = $previewUriBuilder->buildUriForPage((
int)$elementUid, 0);
619 unset($tempEmailMessage);
621 $markers[
'###SPLITTED_PREVIEW_LINK###'] = $previewUriBuilder->buildUriForWorkspaceSplitPreview((
int)$elementUid,
true);
623 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'ext/version/class.tx_version_tcemain.php'][
'notifyStageChange-postModifyMarkers'] ?? [] as $className) {
624 $_procObj = GeneralUtility::makeInstance($className);
625 $markers = $_procObj->postModifyMarkers($markers, $this);
629 $emailRecipients = [];
636 foreach ($emails as $recipientData) {
638 if (isset($emailRecipients[$recipientData[
'email']])) {
641 $emailSubject = $emailConfig[
'subject'];
642 $emailMessage = $emailConfig[
'message'];
643 $emailRecipients[$recipientData[
'email']] = $recipientData[
'email'];
646 if (GeneralUtility::isFirstPartOfStr($emailSubject,
'LLL:') || GeneralUtility::isFirstPartOfStr($emailMessage,
'LLL:')) {
647 $recipientLanguage = $recipientData[
'lang'] ? $recipientData[
'lang'] :
'default';
648 if (!isset($languageObjects[$recipientLanguage])) {
651 $languageObject = GeneralUtility::makeInstance(LanguageService::class);
652 $languageObject->init($recipientLanguage);
653 $languageObjects[$recipientLanguage] = $languageObject;
655 $languageObject = $languageObjects[$recipientLanguage];
657 if (GeneralUtility::isFirstPartOfStr($emailSubject,
'LLL:')) {
658 $emailSubject = $languageObject->sL($emailSubject);
660 if (GeneralUtility::isFirstPartOfStr($emailMessage,
'LLL:')) {
661 $emailMessage = $languageObject->sL($emailMessage);
664 $templateService = GeneralUtility::makeInstance(MarkerBasedTemplateService::class);
665 $emailSubject = $templateService->substituteMarkerArray($emailSubject, $markers,
'',
true,
true);
666 $emailMessage = $templateService->substituteMarkerArray($emailMessage, $markers,
'',
true,
true);
669 $mail = GeneralUtility::makeInstance(\
TYPO3\CMS\Core\Mail\MailMessage::class);
670 if (!empty($recipientData[
'realName'])) {
671 $recipient = [$recipientData[
'email'] => $recipientData[
'realName']];
673 $recipient = $recipientData[
'email'];
675 $mail->setTo($recipient)
676 ->setSubject($emailSubject)
677 ->setBody($emailMessage);
680 $emailRecipients = implode(
',', $emailRecipients);
681 if ($dataHandler->enableLogging) {
683 $pid = $propertyArray[
'pid'];
684 $dataHandler->
log($table, $id, 0, 0, 0,
'Notification email for stage change was sent to "' . $emailRecipients .
'"', -1, [], $dataHandler->
eventPid($table, $id, $pid));
699 $users = GeneralUtility::trimExplode(
',', $listOfUsers,
true);
701 foreach ($users as $userIdent) {
702 if ($noTablePrefix) {
703 $id = (int)$userIdent;
705 [$table, $id] = GeneralUtility::revExplode(
'_', $userIdent, 2);
707 if ($table ===
'be_users' || $noTablePrefix) {
709 if (trim($userRecord[
'email']) !==
'') {
710 $emails[$id] = $userRecord;
734 if ($errorCode = $dataHandler->BE_USER->workspaceCannotEditOfflineVersion($table, $id)) {
735 $dataHandler->
newlog(
'Attempt to set stage for record failed: ' . $errorCode, 1);
738 $stat = $dataHandler->BE_USER->checkWorkspace($record[
't3ver_wsid']);
740 if ($dataHandler->BE_USER->workspaceCheckStageForCurrent($record[
't3ver_stage'])) {
742 GeneralUtility::makeInstance(ConnectionPool::class)
743 ->getConnectionForTable($table)
747 't3ver_stage' => $stageId,
752 if ($dataHandler->enableLogging) {
754 $pid = $propertyArray[
'pid'];
755 $dataHandler->
log($table, $id, 0, 0, 0,
'Stage for record was changed to ' . $stageId .
'. Comment was: "' . substr($comment, 0, 100) .
'"', -1, [], $dataHandler->
eventPid($table, $id, $pid));
758 $dataHandler->
log($table, $id, 6, 0, 0,
'Stage raised...', 30, [
'comment' => $comment,
'stage' => $stageId]);
759 if ((
int)$stat[
'stagechg_notification'] > 0) {
761 $this->notificationEmailInfo[$stat[
'uid'] .
':' . $stageId .
':' . $comment][
'shared'] = [$stat, $stageId, $comment];
762 $this->notificationEmailInfo[$stat[
'uid'] .
':' . $stageId .
':' . $comment][
'elements'][] = $table .
':' . $id;
763 $this->notificationEmailInfo[$stat[
'uid'] .
':' . $stageId .
':' . $comment][
'alternativeRecipients'] = $notificationAlternativeRecipients;
765 $this->
notifyStageChange($stat, $stageId, $table, $id, $comment, $dataHandler, $notificationAlternativeRecipients);
769 $dataHandler->
newlog(
'The member user tried to set a stage value "' . $stageId .
'" that was not allowed', 1);
772 $dataHandler->
newlog(
'Attempt to set stage for record failed because you do not have edit access', 1);
805 $dataHandler->
newlog(
'Error: You cannot swap versions for a record you do not have access to edit!', 1);
813 if (!(is_array($curVersion) && is_array($swapVersion))) {
814 $dataHandler->
newlog(
'Error: Either online or swap version could not be selected!', 2);
817 if (!$dataHandler->BE_USER->workspacePublishAccess($swapVersion[
't3ver_wsid'])) {
818 $dataHandler->
newlog(
'User could not publish records from workspace #' . $swapVersion[
't3ver_wsid'], 1);
821 $wsAccess = $dataHandler->BE_USER->checkWorkspace($swapVersion[
't3ver_wsid']);
822 if (!($swapVersion[
't3ver_wsid'] <= 0 || !($wsAccess[
'publish_access'] & 1) || (
int)$swapVersion[
't3ver_stage'] === -10)) {
823 $dataHandler->
newlog(
'Records in workspace #' . $swapVersion[
't3ver_wsid'] .
' can only be published when in "Publish" stage.', 1);
827 $dataHandler->
newlog(
'You cannot publish a record you do not have edit and show permissions for', 1);
830 if ($swapIntoWS && !$dataHandler->BE_USER->workspaceSwapAccess()) {
831 $dataHandler->
newlog(
'Workspace #' . $swapVersion[
't3ver_wsid'] .
' does not support swapping.', 1);
835 if (!(((
int)$swapVersion[
'pid'] == -1 && (
int)$curVersion[
'pid'] >= 0) && (
int)$swapVersion[
't3ver_oid'] === (
int)$id)) {
836 $dataHandler->
newlog(
'In swap version, either pid was not -1 or the t3ver_oid didn\'t match the id of the online version as it must!', 2);
841 if (@is_file($lockFileName)) {
842 $dataHandler->
newlog(
'A swapping lock file was present. Either another swap process is already running or a previous swap process failed. Ask your administrator to handle the situation.', 2);
849 GeneralUtility::writeFileToTypo3tempDir($lockFileName, serialize([
851 'user' => $dataHandler->BE_USER->user[
'username'],
852 'curVersion' => $curVersion,
853 'swapVersion' => $swapVersion
857 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'sortby']) {
858 $keepFields[] =
$GLOBALS[
'TCA'][$table][
'ctrl'][
'sortby'];
862 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerField']) {
863 $keepFields[] =
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerField'];
866 foreach ($keepFields as $fN) {
867 $tmp = $swapVersion[$fN];
868 $swapVersion[$fN] = $curVersion[$fN];
869 $curVersion[$fN] = $tmp;
873 $t3ver_state[
'swapVersion'] = $swapVersion[
't3ver_state'];
874 $t3ver_state[
'curVersion'] = $curVersion[
't3ver_state'];
876 $tmp_wsid = $swapVersion[
't3ver_wsid'];
878 $swapVersion[
'pid'] = (int)$curVersion[
'pid'];
882 $swapVersion[
't3ver_oid'] = 0;
887 $swapVersion[
't3ver_wsid'] = 0;
889 if ($t3ver_state[
'swapVersion'] > 0) {
890 $swapVersion[
't3ver_wsid'] = $dataHandler->BE_USER->workspace;
892 $swapVersion[
't3ver_wsid'] = (int)$curVersion[
't3ver_wsid'];
895 $swapVersion[
't3ver_tstamp'] =
$GLOBALS[
'EXEC_TIME'];
896 $swapVersion[
't3ver_stage'] = 0;
904 $movePlhID = $plhRec[
'uid'];
905 $movePlh[
'pid'] = $swapVersion[
'pid'];
906 $swapVersion[
'pid'] = (int)$plhRec[
'pid'];
907 $curVersion[
't3ver_state'] = (int)$swapVersion[
't3ver_state'];
909 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'sortby']) {
911 $movePlh[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'sortby']] = $swapVersion[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'sortby']];
912 $swapVersion[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'sortby']] = $plhRec[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'sortby']];
917 if (is_array(
$GLOBALS[
'TCA'][$table][
'columns'])) {
918 foreach (
$GLOBALS[
'TCA'][$table][
'columns'] as $field => $fieldConf) {
919 if (isset($fieldConf[
'config']) && is_array($fieldConf[
'config'])) {
924 unset($swapVersion[
'uid']);
926 unset($curVersion[
'uid']);
928 $curVersion[
'pid'] = -1;
929 $curVersion[
't3ver_oid'] = (int)$id;
930 $curVersion[
't3ver_wsid'] = $swapIntoWS ? (int)$tmp_wsid : 0;
931 $curVersion[
't3ver_tstamp'] =
$GLOBALS[
'EXEC_TIME'];
932 $curVersion[
't3ver_count'] = $curVersion[
't3ver_count'] + 1;
934 $curVersion[
't3ver_stage'] = 0;
946 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
948 $platform = $connection->getDatabasePlatform();
949 $tableDetails =
null;
950 if ($platform instanceof SQLServerPlatform) {
952 $tableDetails = $connection->getSchemaManager()->listTableDetails($table);
958 if ($platform instanceof SQLServerPlatform) {
959 foreach ($curVersion as $columnName => $columnValue) {
960 $types[$columnName] = $tableDetails->getColumn($columnName)->getType()->getBindingType();
970 }
catch (DBALException $e) {
971 $sqlErrors[] = $e->getPrevious()->getMessage();
974 if (empty($sqlErrors)) {
977 if ($platform instanceof SQLServerPlatform) {
978 foreach ($curVersion as $columnName => $columnValue) {
979 $types[$columnName] = $tableDetails->getColumn($columnName)->getType()->getBindingType();
986 [
'uid' => (
int)$swapWith],
989 unlink($lockFileName);
990 }
catch (DBALException $e) {
991 $sqlErrors[] = $e->getPrevious()->getMessage();
995 if (!empty($sqlErrors)) {
996 $dataHandler->
newlog(
'During Swapping: SQL errors happened: ' . implode(
'; ', $sqlErrors), 2);
999 $this->remappedIds[$table][$id] = $swapWith;
1000 $this->remappedIds[$table][$swapWith] = $id;
1006 $dataHandler->
deleteEl($table, $movePlhID,
true,
true);
1009 GeneralUtility::makeInstance(ConnectionPool::class)
1010 ->getConnectionForTable($table)
1014 [
'uid' => (
int)$movePlhID]
1021 if (!$swapIntoWS && ((
int)$t3ver_state[
'swapVersion'] === 1 || (
int)$t3ver_state[
'swapVersion'] === 2)) {
1023 $dataHandler->
deleteEl($table, $id,
true);
1025 if ($dataHandler->enableLogging) {
1026 $dataHandler->
log($table, $id, 0, 0, 0, ($swapIntoWS ?
'Swapping' :
'Publishing') .
' successful for table "' . $table .
'" uid ' . $id .
'=>' . $swapWith, -1, [], $dataHandler->
eventPid($table, $id, $swapVersion[
'pid']));
1033 if ($propArr[
'_ORIG_pid'] == -1) {
1034 $label = $this->
getLanguageService()->
sL(
'LLL:EXT:workspaces/Resources/Private/Language/locallang_tcemain.xlf:version_swap.offline_record_updated');
1036 $label = $this->
getLanguageService()->
sL(
'LLL:EXT:workspaces/Resources/Private/Language/locallang_tcemain.xlf:version_swap.online_record_updated');
1038 $theLogId = $dataHandler->
log($table, $id, 2, $propArr[
'pid'], 0, $label, 10, [$propArr[
'header'], $table .
':' . $id], $propArr[
'event_pid']);
1039 $dataHandler->
setHistory($table, $id, $theLogId);
1044 if ($propArr[
'_ORIG_pid'] == -1) {
1045 $label = $this->
getLanguageService()->
sL(
'LLL:EXT:workspaces/Resources/Private/Language/locallang_tcemain.xlf:version_swap.offline_record_updated');
1047 $label = $this->
getLanguageService()->
sL(
'LLL:EXT:workspaces/Resources/Private/Language/locallang_tcemain.xlf:version_swap.online_record_updated');
1049 $theLogId = $dataHandler->
log($table, $swapWith, 2, $propArr[
'pid'], 0, $label, 10, [$propArr[
'header'], $table .
':' . $swapWith], $propArr[
'event_pid']);
1050 $dataHandler->
setHistory($table, $swapWith, $theLogId);
1054 $notificationEmailInfoKey = $wsAccess[
'uid'] .
':' . $stageId .
':' . $comment;
1055 $this->notificationEmailInfo[$notificationEmailInfoKey][
'shared'] = [$wsAccess, $stageId, $comment];
1056 $this->notificationEmailInfo[$notificationEmailInfoKey][
'elements'][] = $table .
':' . $id;
1057 $this->notificationEmailInfo[$notificationEmailInfoKey][
'alternativeRecipients'] = $notificationAlternativeRecipients;
1059 $this->
notifyStageChange($wsAccess, $stageId, $table, $id, $comment, $dataHandler, $notificationAlternativeRecipients);
1062 if ($dataHandler->enableLogging) {
1064 $pid = $propArr[
'pid'];
1065 $dataHandler->
log($table, $id, 0, 0, 0,
'Stage for record was changed to ' . $stageId .
'. Comment was: "' . substr($comment, 0, 100) .
'"', -1, [], $dataHandler->
eventPid($table, $id, $pid));
1067 $dataHandler->
log($table, $id, 6, 0, 0,
'Published', 30, [
'comment' => $comment,
'stage' => $stageId]);
1072 if (!$swapIntoWS && $t3ver_state[
'curVersion'] > 0) {
1074 if ($table ===
'pages') {
1079 $dataHandler->
deleteEl($table, $swapWith,
true,
true,
false);
1081 $dataHandler->
deleteEl($table, $swapWith,
true,
true);
1087 $refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class);
1088 $refIndexObj->setWorkspaceId(0);
1089 $refIndexObj->updateRefIndexTable($table, $id);
1090 $refIndexObj->updateRefIndexTable($table, $swapWith);
1103 foreach ($dbAnalysis->itemArray as &$item) {
1104 if (isset($this->remappedIds[$item[
'table']][$item[
'id']])) {
1105 $item[
'id'] = $this->remappedIds[$item[
'table']][$item[
'id']];
1125 if ($inlineType !==
'field') {
1128 $foreignTable = $configuration[
'foreign_table'];
1131 $liveRelations->setWorkspaceId(0);
1132 $liveRelations->start(
'', $foreignTable,
'', $liveData[
'uid'], $tableName, $configuration);
1135 $versionRelations->setUseLiveReferenceIds(
false);
1136 $versionRelations->start(
'', $foreignTable,
'', $versionData[
'uid'], $tableName, $configuration);
1138 if (count($liveRelations->itemArray)) {
1142 [$this,
'updateInlineForeignFieldSorting'],
1143 [$tableName, $liveData[
'uid'], $foreignTable, $liveRelations->tableArray[$foreignTable], $configuration, $dataHandler->BE_USER->workspace]
1146 if (count($versionRelations->itemArray)) {
1150 [$this,
'updateInlineForeignFieldSorting'],
1151 [$tableName, $liveData[
'uid'], $foreignTable, $versionRelations->tableArray[$foreignTable], $configuration, 0]
1177 foreach ($foreignIds as $foreignId) {
1178 if (!empty($this->remappedIds[$foreignTableName][$foreignId])) {
1179 $remappedIds[] = $this->remappedIds[$foreignTableName][$foreignId];
1186 $relationHandler->setWorkspaceId($targetWorkspaceId);
1187 $relationHandler->setUseLiveReferenceIds(
false);
1188 $relationHandler->start(implode(
',',
$remappedIds), $foreignTableName);
1189 $relationHandler->processDeletePlaceholder();
1190 $relationHandler->writeForeignField($configuration, $parentId);
1203 if ($errorCode = $dataHandler->BE_USER->workspaceCannotEditOfflineVersion($table, $id)) {
1204 $dataHandler->
newlog(
'Attempt to reset workspace for record failed: ' . $errorCode, 1);
1208 $dataHandler->
newlog(
'Attempt to reset workspace for record failed because you do not have edit access', 1);
1218 't3ver_tstamp' =>
$GLOBALS[
'EXEC_TIME']
1220 $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table);
1221 $connection->update(
1232 $connection->update(
1235 [
'uid' => (
int)$liveRec[
'uid']]
1239 $dataHandler->
deleteEl($table, $liveRec[
'uid'],
true);
1251 $dataHandler->
deleteEl($table, $id,
true,
true);
1256 $dataHandler->
deleteEl($table, $plhRec[
'uid'],
true,
true);
1272 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1273 ->getQueryBuilderForTable($tcaTable);
1279 $queryBuilder->expr()->eq(
1281 $queryBuilder->createNamedParameter($stageId, \PDO::PARAM_INT)
1283 $queryBuilder->expr()->eq(
1285 $queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT)
1287 $queryBuilder->expr()->gt(
1289 $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
1307 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1308 ->getQueryBuilderForTable($tcaTable);
1309 $queryBuilder->getRestrictions()
1311 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1312 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class, $workspaceId,
false));
1314 $result = $queryBuilder
1320 while (($recordId = $result->fetchColumn()) !==
false) {
1321 $command[$tcaTable][$recordId][
'version'][
'action'] =
'flush';
1325 if (!empty($command)) {
1327 $dataHandler->
start([], $command);
1347 return GeneralUtility::makeInstance(DataHandler::class);
1357 $workspacesCache = GeneralUtility::makeInstance(CacheManager::class)->getCache(
'workspaces_cache');
1358 $workspacesCache->flushByTag($workspaceId);
1377 $workspaceId = (int)$rec[
't3ver_wsid'];
1379 if ($workspaceId === 0) {
1380 return $elementData;
1383 if ($table !==
'pages') {
1385 $pageId = $rec[
'pid'];
1388 $offlinePageId = $rec[
'_ORIG_uid'];
1391 $offlinePageId = $offlineId;
1394 foreach (
$GLOBALS[
'TCA'] as $table => $cfg) {
1395 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'versioningWS'] && $table !==
'pages') {
1396 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1397 ->getQueryBuilderForTable($table);
1399 $queryBuilder->getRestrictions()
1401 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1403 $statement = $queryBuilder
1404 ->select(
'A.uid AS offlineUid',
'B.uid AS uid')
1408 $queryBuilder->expr()->eq(
1410 $queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT)
1412 $queryBuilder->expr()->eq(
1414 $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
1416 $queryBuilder->expr()->eq(
1418 $queryBuilder->createNamedParameter($workspaceId, \PDO::PARAM_INT)
1420 $queryBuilder->expr()->eq(
'A.t3ver_oid', $queryBuilder->quoteIdentifier(
'B.uid'))
1424 while ($row = $statement->fetch()) {
1425 $elementData[$table][] = [$row[
'uid'], $row[
'offlineUid']];
1429 if ($offlinePageId && $offlinePageId != $pageId) {
1430 $elementData[
'pages'][] = [$pageId, $offlinePageId];
1433 return $elementData;
1445 if ($workspaceId == 0) {
1449 foreach (
$GLOBALS[
'TCA'] as $table => $cfg) {
1450 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'versioningWS'] && $table !==
'pages') {
1451 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1452 ->getQueryBuilderForTable($table);
1454 $queryBuilder->getRestrictions()
1456 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1458 $statement = $queryBuilder
1463 $queryBuilder->expr()->eq(
1465 $queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT)
1467 $queryBuilder->expr()->in(
1469 $queryBuilder->createNamedParameter($pageIdList, Connection::PARAM_INT_ARRAY)
1471 $queryBuilder->expr()->eq(
1473 $queryBuilder->createNamedParameter($workspaceId, \PDO::PARAM_INT)
1475 $queryBuilder->expr()->eq(
'A.t3ver_oid', $queryBuilder->quoteIdentifier(
'B.uid'))
1480 while ($row = $statement->fetch()) {
1481 $elementList[$table][] = $row[
'uid'];
1483 if (is_array($elementList[$table])) {
1486 $elementList[$table] = array_unique($elementList[$table]);
1503 if ($workspaceId == 0) {
1507 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1508 ->getQueryBuilderForTable($table);
1509 $queryBuilder->getRestrictions()
1511 ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
1513 $statement = $queryBuilder
1518 $queryBuilder->expr()->eq(
1520 $queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT)
1522 $queryBuilder->expr()->eq(
1524 $queryBuilder->createNamedParameter($workspaceId, \PDO::PARAM_INT)
1526 $queryBuilder->expr()->in(
1528 $queryBuilder->createNamedParameter($idList, Connection::PARAM_INT_ARRAY)
1530 $queryBuilder->expr()->eq(
'A.t3ver_oid', $queryBuilder->quoteIdentifier(
'B.uid'))
1535 while ($row = $statement->fetch()) {
1536 $pageIdList[] = $row[
'pid'];
1542 if ($rec[
'_ORIG_uid']) {
1543 $elementList[
'pages'][$row[0]] = $rec[
'_ORIG_uid'];
1548 $pageIdList = array_unique($pageIdList);
1558 foreach ($idList as $key => $id) {
1560 if ($rec[
't3ver_oid'] > 0) {
1561 $idList[$key] = $rec[
't3ver_oid'];
1583 $originalRecordDestinationPid = $destPid;
1586 if ($movePlaceHolder !==
false) {
1587 $destPid = -$movePlaceHolder[
'uid'];
1596 $newVersion_placeholderFieldArray = [];
1598 $factory = GeneralUtility::makeInstance(
1599 PlaceholderShadowColumnsResolver::class,
1603 $shadowColumns = $factory->forMovePlaceholder();
1605 if (!empty($shadowColumns)) {
1607 foreach ($shadowColumns as $shadowColumn) {
1608 if (isset($versionedRecord[$shadowColumn])) {
1609 $newVersion_placeholderFieldArray[$shadowColumn] = $versionedRecord[$shadowColumn];
1614 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'crdate']) {
1615 $newVersion_placeholderFieldArray[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'crdate']] =
$GLOBALS[
'EXEC_TIME'];
1617 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'cruser_id']) {
1618 $newVersion_placeholderFieldArray[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'cruser_id']] = $dataHandler->userid;
1620 if (
$GLOBALS[
'TCA'][$table][
'ctrl'][
'tstamp']) {
1621 $newVersion_placeholderFieldArray[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'tstamp']] =
$GLOBALS[
'EXEC_TIME'];
1623 if ($table ===
'pages') {
1627 $newVersion_placeholderFieldArray[
'perms_userid'] = $access[
'perms_userid'];
1628 $newVersion_placeholderFieldArray[
'perms_groupid'] = $access[
'perms_groupid'];
1629 $newVersion_placeholderFieldArray[
'perms_user'] = $access[
'perms_user'];
1630 $newVersion_placeholderFieldArray[
'perms_group'] = $access[
'perms_group'];
1631 $newVersion_placeholderFieldArray[
'perms_everybody'] = $access[
'perms_everybody'];
1633 $newVersion_placeholderFieldArray[
't3ver_label'] =
'MovePlaceholder #' . $uid;
1634 $newVersion_placeholderFieldArray[
't3ver_move_id'] = $uid;
1638 $newVersion_placeholderFieldArray[
't3ver_wsid'] = $dataHandler->BE_USER->workspace;
1641 if (isset(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'languageField']) && isset(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerField'])) {
1643 $newVersion_placeholderFieldArray[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'languageField']] = $l10nParentRec[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'languageField']];
1644 $newVersion_placeholderFieldArray[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerField']] = $l10nParentRec[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerField']];
1645 if (isset(
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigDiffSourceField'])) {
1646 $newVersion_placeholderFieldArray[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigDiffSourceField']] = $l10nParentRec[
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigDiffSourceField']];
1648 unset($l10nParentRec);
1651 $newVersion_placeholderFieldArray[
'pid'] = 0;
1652 $id =
'NEW_MOVE_PLH';
1654 $dataHandler->
insertDB($table, $id, $newVersion_placeholderFieldArray,
false);
1656 $dataHandler->
moveRecord_raw($table, $dataHandler->substNEWwithIDs[$id], $destPid);
1663 GeneralUtility::makeInstance(ConnectionPool::class)
1664 ->getConnectionForTable($table)
1668 [
'uid' => (
int)$wsUid]
1683 return GeneralUtility::makeInstance(
1687 $dataHandler->cmdmap,
1688 $dataHandler->BE_USER->workspace
1701 if (empty(
$GLOBALS[
'TCA'][$table][
'columns'])) {
1704 foreach (
$GLOBALS[
'TCA'][$table][
'columns'] as $field => $configArr) {
1705 if ($configArr[
'config'][
'type'] ===
'input') {
1706 $evalCodesArray = GeneralUtility::trimExplode(
',', $configArr[
'config'][
'eval'],
true);
1707 if (in_array(
'uniqueInPid', $evalCodesArray) || in_array(
'unique', $evalCodesArray)) {
1708 $listArr[] = $field;
1720 return GeneralUtility::makeInstance(RelationHandler::class);