2 declare(strict_types = 1);
18 use Psr\Http\Message\ResponseInterface;
19 use Psr\Http\Message\ServerRequestInterface;
80 'makeEditForm' =>
'Using EditDocumentController::makeEditForm() is deprecated and will not be possible anymore in TYPO3 v10.0.',
81 'compileForm' =>
'Using EditDocumentController::compileForm() is deprecated and will not be possible anymore in TYPO3 v10.0.',
82 'languageSwitch' =>
'Using EditDocumentController::languageSwitch() is deprecated and will not be possible anymore in TYPO3 v10.0.',
83 'getLanguages' =>
'Using EditDocumentController::getLanguages() is deprecated and will not be possible anymore in TYPO3 v10.0.',
84 'fixWSversioningInEditConf' =>
'Using EditDocumentController::fixWSversioningInEditConf() is deprecated and will not be possible anymore in TYPO3 v10.0.',
85 'getRecordForEdit' =>
'Using EditDocumentController::getRecordForEdit() is deprecated and will not be possible anymore in TYPO3 v10.0.',
94 'editconf' =>
'Using $editconf of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
95 'defVals' =>
'Using $defVals of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
96 'overrideVals' =>
'Using $overrideVals of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
97 'columnsOnly' =>
'Using $columnsOnly of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
98 'returnUrl' =>
'Using $returnUrl of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
99 'closeDoc' =>
'Using $closeDoc of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
100 'doSave' =>
'Using $doSave of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
101 'returnEditConf' =>
'Using $returnEditConf of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
102 'uc' =>
'Using $uc of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
103 'retUrl' =>
'Using $retUrl of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
104 'R_URL_parts' =>
'Using $R_URL_parts of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
105 'R_URL_getvars' =>
'Using $R_URL_getvars of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
106 'storeArray' =>
'Using $storeArray of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
107 'storeUrl' =>
'Using $storeUrl of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
108 'storeUrlMd5' =>
'Using $storeUrlMd5 of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
109 'docDat' =>
'Using $docDat of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
110 'docHandler' =>
'Using $docHandler of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
111 'cmd' =>
'Using $cmd of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
112 'mirror' =>
'Using $mirror of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
113 'cacheCmd' =>
'Using $cacheCmd of class EditDocumentTemplate from the outside is discouraged, the variable will be removed.',
114 'redirect' =>
'Using $redirect of class EditDocumentTemplate from the outside is discouraged, the variable will be removed.',
115 'returnNewPageId' =>
'Using $returnNewPageId of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
116 'popViewId' =>
'Using $popViewId of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
117 'popViewId_addParams' =>
'Using $popViewId_addParams of class EditDocumentTemplate from the outside is discouraged, the variable will be removed.',
118 'viewUrl' =>
'Using $viewUrl of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
119 'recTitle' =>
'Using $recTitle of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
120 'noView' =>
'Using $noView of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
121 'MCONF' =>
'Using $MCONF of class EditDocumentTemplate from the outside is discouraged, the variable will be removed.',
122 'doc' =>
'Using $doc of class EditDocumentTemplate from the outside is discouraged, the variable will be removed.',
123 'perms_clause' =>
'Using $perms_clause of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
124 'template' =>
'Using $template of class EditDocumentTemplate from the outside is discouraged, the variable will be removed.',
125 'content' =>
'Using $content of class EditDocumentTemplate from the outside is discouraged, the variable will be removed.',
126 'R_URI' =>
'Using $R_URI of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
127 'pageinfo' =>
'Using $pageinfo of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
128 'storeTitle' =>
'Using $storeTitle of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
129 'firstEl' =>
'Using $firstEl of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
130 'errorC' =>
'Using $errorC of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
131 'newC' =>
'Using $newC of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
132 'viewId' =>
'Using $viewId of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
133 'viewId_addParams' =>
'Using $viewId_addParams of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
134 'modTSconfig' =>
'Using $modTSconfig of class EditDocumentTemplate from the outside is discouraged, the variable will be removed.',
135 'dontStoreDocumentRef' =>
'Using $dontStoreDocumentRef of class EditDocumentTemplate from the outside is discouraged, as this variable is only used for internal storage.',
506 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
507 $this->moduleTemplate->setUiBlock(
true);
508 $this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
520 public function mainAction(ServerRequestInterface $request): ResponseInterface
524 if ($response = $this->
preInit($request)) {
529 $parsedBody = $request->getParsedBody();
531 || isset($parsedBody[
'_savedok'])
532 || isset($parsedBody[
'_saveandclosedok'])
533 || isset($parsedBody[
'_savedokview'])
534 || isset($parsedBody[
'_savedoknew'])
535 || isset($parsedBody[
'_duplicatedoc'])
542 $this->
init($request);
543 $this->
main($request);
545 return new HtmlResponse($this->moduleTemplate->renderContent());
554 public function preInit(ServerRequestInterface $request =
null): ?ResponseInterface
556 if ($request ===
null) {
561 trigger_error(
'EditDocumentController->preInit() will be set to protected in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
569 $parsedBody = $request->getParsedBody();
570 $queryParams = $request->getQueryParams();
572 $this->editconf = $parsedBody[
'edit'] ?? $queryParams[
'edit'] ?? [];
573 $this->defVals = $parsedBody[
'defVals'] ?? $queryParams[
'defVals'] ??
null;
574 $this->overrideVals = $parsedBody[
'overrideVals'] ?? $queryParams[
'overrideVals'] ??
null;
575 $this->columnsOnly = $parsedBody[
'columnsOnly'] ?? $queryParams[
'columnsOnly'] ??
null;
576 $this->returnUrl = GeneralUtility::sanitizeLocalUrl($parsedBody[
'returnUrl'] ?? $queryParams[
'returnUrl'] ??
null);
577 $this->closeDoc = (int)($parsedBody[
'closeDoc'] ?? $queryParams[
'closeDoc'] ?? self::DOCUMENT_CLOSE_MODE_DEFAULT);
578 $this->doSave = (bool)($parsedBody[
'doSave'] ?? $queryParams[
'doSave'] ??
false);
579 $this->returnEditConf = (bool)($parsedBody[
'returnEditConf'] ?? $queryParams[
'returnEditConf'] ??
false);
580 $this->workspace = $parsedBody[
'workspace'] ?? $queryParams[
'workspace'] ??
null;
581 $this->uc = $parsedBody[
'uc'] ?? $queryParams[
'uc'] ??
null;
585 if (!is_array($this->defVals) && is_array($this->overrideVals)) {
591 $this->retUrl = $this->returnUrl ?: (string)$this->uriBuilder->buildUriFromRoute(
'dummy');
597 $this->R_URL_parts = parse_url($request->getAttribute(
'normalizedParams')->getRequestUri());
598 $this->R_URL_getvars = $queryParams;
605 $this->docHandler = $this->docDat[0];
608 if ((
int)$this->closeDoc > self::DOCUMENT_CLOSE_MODE_DEFAULT) {
609 if ($response = $this->
closeDocument($this->closeDoc, $request)) {
615 if ($this->workspace !==
null) {
632 trigger_error(
'EditDocumentController->doProcessData() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
635 || isset($_POST[
'_savedok'])
636 || isset($_POST[
'_saveandclosedok'])
637 || isset($_POST[
'_savedokview'])
638 || isset($_POST[
'_savedoknew'])
639 || isset($_POST[
'_duplicatedoc']);
650 $data = $queryParams[
'edit'] ?? [];
653 if ($this->columnsOnly && $table !==
false && isset(
$GLOBALS[
'TCA'][$table])) {
654 $fields = GeneralUtility::trimExplode(
',', $this->columnsOnly,
true);
656 if (isset(
$GLOBALS[
'TCA'][$table][
'columns'][$field]) &&
$GLOBALS[
'TCA'][$table][
'columns'][$field][
'config'][
'type'] ===
'slug') {
657 foreach (
$GLOBALS[
'TCA'][$table][
'columns'][$field][
'config'][
'generatorOptions'][
'fields'] as
$fields) {
671 public function processData(ServerRequestInterface $request =
null): ?ResponseInterface
674 $deprecatedCaller =
false;
675 if ($request ===
null) {
680 trigger_error(
'EditDocumentController->processData() will be set to protected in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
682 $deprecatedCaller =
true;
685 $parsedBody = $request->getParsedBody();
686 $queryParams = $request->getQueryParams();
691 $this->data = $parsedBody[
'data'] ?? $queryParams[
'data'] ?? [];
692 $this->cmd = $parsedBody[
'cmd'] ?? $queryParams[
'cmd'] ?? [];
693 $this->mirror = $parsedBody[
'mirror'] ?? $queryParams[
'mirror'] ?? [];
695 $this->cacheCmd = $parsedBody[
'cacheCmd'] ?? $queryParams[
'cacheCmd'] ??
null;
697 $this->redirect = $parsedBody[
'redirect'] ?? $queryParams[
'redirect'] ??
null;
698 $this->returnNewPageId = (bool)($parsedBody[
'returnNewPageId'] ?? $queryParams[
'returnNewPageId'] ??
false);
701 $tce = GeneralUtility::makeInstance(DataHandler::class);
703 $tce->setControl($parsedBody[
'control'] ?? $queryParams[
'control'] ?? []);
706 if (isset($beUser->uc[
'neverHideAtCopy']) && $beUser->uc[
'neverHideAtCopy']) {
707 $tce->neverHideAtCopy = 1;
710 $tce->start($this->data, $this->cmd);
711 if (is_array($this->mirror)) {
712 $tce->setMirror($this->mirror);
716 if ($this->doSave ===
true) {
718 $tce->process_uploads($_FILES);
719 $tce->process_datamap();
720 $tce->process_cmdmap();
723 if ($tce->pagetreeNeedsRefresh
724 && (isset($this->data[
'pages']) || $beUser->workspace != 0 && !empty($this->data))
729 if (!empty($tce->substNEWwithIDs_table)) {
733 foreach ($this->editconf as $tableName => $tableCmds) {
734 $keys = array_keys($tce->substNEWwithIDs_table, $tableName);
736 foreach ($keys as $key) {
737 $editId = $tce->substNEWwithIDs[$key];
739 if (!(is_array($tce->newRelatedIDs[$tableName])
740 && in_array($editId, $tce->newRelatedIDs[$tableName]))
749 $editId = $versionRec[
'uid'];
751 $newEditConf[$tableName][$editId] =
'edit';
754 if ($tableName ===
'pages'
755 && $this->retUrl !== (
string)$this->uriBuilder->buildUriFromRoute(
'dummy')
756 && $this->retUrl !== $this->getCloseUrl()
757 && $this->returnNewPageId
759 $this->retUrl .=
'&id=' . $tce->substNEWwithIDs[$key];
763 $newEditConf[$tableName] = $tableCmds;
767 if (!empty($newEditConf)) {
768 $this->editconf = $newEditConf;
773 unset($this->R_URL_getvars[
'defVals']);
778 if (!empty($tce->autoVersionIdMap)) {
782 if (isset($parsedBody[
'_savedoknew']) && is_array($this->editconf)) {
787 reset($this->editconf);
788 $nTable = key($this->editconf);
790 reset($this->editconf[$nTable]);
791 $nUid = key($this->editconf[$nTable]);
792 $recordFields =
'pid,uid';
793 if (!empty(
$GLOBALS[
'TCA'][$nTable][
'ctrl'][
'versioningWS'])) {
794 $recordFields .=
',t3ver_oid';
801 $this->editconf = [];
803 if ($nRec[
'pid'] != -1) {
804 if ($insertRecordOnTop) {
805 $relatedPageId = $nRec[
'pid'];
807 $relatedPageId = -$nRec[
'uid'];
811 if ($insertRecordOnTop) {
814 $relatedPageId = $liveRecord[
'pid'];
817 $relatedPageId = -$nRec[
't3ver_oid'];
820 $this->editconf[$nTable][$relatedPageId] =
'new';
827 if (isset($parsedBody[
'_duplicatedoc']) && is_array($this->editconf)) {
828 $this->
closeDocument(self::DOCUMENT_CLOSE_MODE_NO_REDIRECT, $request);
830 reset($this->editconf);
831 $nTable = key($this->editconf);
833 reset($this->editconf[$nTable]);
834 $nUid = key($this->editconf[$nTable]);
836 $nUid = $tce->substNEWwithIDs[$nUid];
839 $recordFields =
'pid,uid';
840 if (!empty(
$GLOBALS[
'TCA'][$nTable][
'ctrl'][
'versioningWS'])) {
841 $recordFields .=
',t3ver_oid';
846 $this->editconf = [];
848 if ($nRec[
'pid'] != -1) {
849 $relatedPageId = -$nRec[
'uid'];
851 $relatedPageId = -$nRec[
't3ver_oid'];
855 $duplicateTce = GeneralUtility::makeInstance(DataHandler::class);
860 'copy' => $relatedPageId
865 $duplicateTce->start([], $duplicateCmd);
866 $duplicateTce->process_cmdmap();
868 $duplicateMappingArray = $duplicateTce->copyMappingArray;
869 $duplicateUid = $duplicateMappingArray[$nTable][$nUid];
871 if ($nTable ===
'pages') {
875 $this->editconf[$nTable][$duplicateUid] =
'edit';
882 $flashMessage = GeneralUtility::makeInstance(
884 $this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.recordDuplicated'),
888 $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
889 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
890 $defaultFlashMessageQueue->enqueue($flashMessage);
893 if (isset($parsedBody[
'_savedokview'])) {
895 $table = reset(array_keys($this->data));
896 $id = reset(array_keys($this->data[$table]));
898 $id = $tce->substNEWwithIDs[$id];
901 $this->previewData[
'table'] = $table;
902 $this->previewData[
'id'] = $id;
904 $tce->printLogErrorMessages();
906 if ((
int)$this->closeDoc < self::DOCUMENT_CLOSE_MODE_DEFAULT
907 || isset($parsedBody[
'_saveandclosedok'])
910 $possibleRedirect = $this->
closeDocument(abs($this->closeDoc), $request);
911 if ($deprecatedCaller && $possibleRedirect) {
915 return $possibleRedirect;
925 public function init(ServerRequestInterface $request =
null): void
927 if ($request ===
null) {
932 trigger_error(
'EditDocumentController->init() will be set to protected in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
936 $parsedBody = $request->getParsedBody();
937 $queryParams = $request->getQueryParams();
942 $this->popViewId_addParams = $parsedBody[
'popViewId_addParams'] ?? $queryParams[
'popViewId_addParams'] ??
'';
944 $this->popViewId = (int)($parsedBody[
'popViewId'] ?? $queryParams[
'popViewId'] ?? 0);
945 $this->viewUrl = (string)($parsedBody[
'viewUrl'] ?? $queryParams[
'viewUrl'] ??
'');
946 $this->recTitle = (string)($parsedBody[
'recTitle'] ?? $queryParams[
'recTitle'] ??
'');
947 $this->noView = (bool)($parsedBody[
'noView'] ?? $queryParams[
'noView'] ??
false);
954 $this->MCONF[
'name'] =
'xMOD_alt_doc.php';
958 $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
959 $pageRenderer->addInlineLanguageLabelFile(
'EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf');
962 $this->moduleTemplate->addJavaScriptCode(
966 function launchView(table,uid) {
967 console.warn(\'Calling launchView() has been deprecated in TYPO3 v9 and will be removed in TYPO3 v10.0\');
968 var thePreviewWindow = window.open(
969 ' . GeneralUtility::quoteJSvalue((
string)$this->uriBuilder->buildUriFromRoute(
'show_item') .
'&table=') .
' + encodeURIComponent(table) + "&uid=" + encodeURIComponent(uid),
970 "ShowItem" + Math.random().toString(16).slice(2),
971 "height=300,width=410,status=0,menubar=0,resizable=0,location=0,directories=0,scrollbars=1,toolbar=0"
973 if (thePreviewWindow && thePreviewWindow.focus) {
974 thePreviewWindow.focus();
977 function deleteRecord(table,id,url) {
978 window.location.href = ' . GeneralUtility::quoteJSvalue((
string)$this->uriBuilder->buildUriFromRoute(
'tce_db') .
'&cmd[') .
'+table+"]["+id+"][delete]=1&redirect="+escape(url);
980 ' . (isset($parsedBody[
'_savedokview']) && $this->popViewId ? $this->
generatePreviewCode() :
'')
983 $this->moduleTemplate->getPageRenderer()->loadRequireJsModule(
'TYPO3/CMS/Backend/ContextMenu');
1001 if (window.opener) {
1006 $previewPageRootLine,
1009 $previewUrlParameters,
1018 $previewPageRootLine,
1021 $previewUrlParameters
1035 $linkParameters = [];
1036 $table = $this->previewData[
'table'] ?: $this->firstEl[
'table'];
1037 $recordId = $this->previewData[
'id'] ?: $this->firstEl[
'uid'];
1042 $languageField =
$GLOBALS[
'TCA'][$table][
'ctrl'][
'languageField'] ??
'';
1043 if ($languageField && !empty($recordArray[$languageField])) {
1045 $language = $recordArray[$languageField];
1046 if ($language > 0) {
1047 $linkParameters[
'L'] = $language;
1053 $recordId = $recordArray[
't3ver_oid'];
1057 if (isset($previewConfiguration[
'fieldToParameterMap.'])) {
1058 foreach ($previewConfiguration[
'fieldToParameterMap.'] as $field => $parameterName) {
1059 $value = $recordArray[$field];
1060 if ($field ===
'uid') {
1063 $linkParameters[$parameterName] = $value;
1068 if (isset($previewConfiguration[
'additionalGetParameters.'])) {
1069 $additionalGetParameters = [];
1071 $additionalGetParameters,
1072 $previewConfiguration[
'additionalGetParameters.']
1074 $linkParameters = array_replace($linkParameters, $additionalGetParameters);
1077 if (!empty($previewConfiguration[
'useCacheHash'])) {
1078 $cacheHashCalculator = GeneralUtility::makeInstance(CacheHashCalculator::class);
1080 $cacheHashParameters = $cacheHashCalculator->getRelevantParameters($fullLinkParameters);
1081 $linkParameters[
'cHash'] = $cacheHashCalculator->calculateCacheHash($cacheHashParameters);
1082 } elseif (empty(
$GLOBALS[
'TYPO3_CONF_VARS'][
'FE'][
'disableNoCacheParameter'])) {
1083 $linkParameters[
'no_cache'] = 1;
1096 protected function resolvePreviewRecordId(
string $table, array $recordArray, array $previewConfiguration): int
1098 $l10nPointer =
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerField'] ??
'';
1100 && !empty($recordArray[$l10nPointer])
1103 !isset($previewConfiguration[
'useDefaultLanguageRecord'])
1105 || $previewConfiguration[
'useDefaultLanguageRecord']
1108 return (
int)$recordArray[$l10nPointer];
1110 return (
int)$recordArray[
'uid'];
1120 $table = $this->previewData[
'table'] ?: $this->firstEl[
'table'];
1121 $recordId = $this->previewData[
'id'] ?: $this->firstEl[
'uid'];
1123 return $table ===
'tt_content' ?
'#c' . (int)$recordId :
'';
1134 $table = $this->previewData[
'table'] ?: $this->firstEl[
'table'];
1135 $recordId = $this->previewData[
'id'] ?: $this->firstEl[
'uid'];
1138 if ($table ===
'pages') {
1139 $currentPageId = (int)$recordId;
1146 if (isset($previewConfiguration[
'previewPageId'])) {
1147 $previewPageId = (int)$previewConfiguration[
'previewPageId'];
1150 if (!$previewPageId) {
1151 $rootPageData =
null;
1153 $currentPage = reset($rootLine);
1158 $previewPageId = $currentPageId;
1161 foreach ($rootLine as $page) {
1162 if ($page[
'is_siteroot']) {
1163 $rootPageData = $page;
1167 $previewPageId = isset($rootPageData)
1168 ? (int)$rootPageData[
'uid']
1173 $this->popViewId = $previewPageId;
1175 return $previewPageId;
1189 foreach ($typoScript as $key => $value) {
1190 if (is_array($value)) {
1191 $key = rtrim($key,
'.');
1192 $parameters[$key] = [];
1195 $parameters[$key] = $value;
1205 public function main(ServerRequestInterface $request =
null): void
1207 if ($request ===
null) {
1209 trigger_error(
'EditDocumentController->main() will be set to protected in TYPO3 v10.0.', E_USER_DEPRECATED);
1215 if (is_array($this->editconf)) {
1216 $this->formResultCompiler = GeneralUtility::makeInstance(FormResultCompiler::class);
1221 $this->firstEl = reset($this->elementsData);
1223 if (($this->docDat[1] !== $this->storeUrlMd5 || !isset($this->docHandler[$this->storeUrlMd5]))
1224 && !$this->dontStoreDocumentRef
1235 $body = $this->formResultCompiler->addCssFiles();
1237 $body .= $this->formResultCompiler->printNeededJSFunctions();
1244 if ($this->pageinfo) {
1245 $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageinfo);
1250 (
string)($this->firstEl[
'table'] ??
''),
1251 (
int)($this->firstEl[
'uid'] ?? 0),
1252 isset($this->firstEl[
'pid']) ? (
int)$this->firstEl[
'pid'] :
null
1254 $this->moduleTemplate->setContent($body);
1265 $this->elementsData = [];
1271 foreach ($this->editconf as $table => $conf) {
1272 if (is_array($conf) &&
$GLOBALS[
'TCA'][$table] && $beUser->check(
'tables_modify', $table)) {
1274 foreach ($conf as $cKey => $command) {
1275 if ($command ===
'edit' || $command ===
'new') {
1277 $ids = GeneralUtility::trimExplode(
',', $cKey,
true);
1279 foreach ($ids as $theUid) {
1281 if ($command ===
'new') {
1282 $this->dontStoreDocumentRef = 1;
1286 $formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class);
1287 $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
1288 $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class);
1292 $this->viewId_addParams =
'';
1294 $formDataCompilerInput = [
1295 'tableName' => $table,
1296 'vanillaUid' => (int)$theUid,
1297 'command' => $command,
1298 'returnUrl' => $this->R_URI,
1300 if (is_array($this->overrideVals) && is_array($this->overrideVals[$table])) {
1301 $formDataCompilerInput[
'overrideValues'] = $this->overrideVals[$table];
1303 if (!empty($this->defVals) && is_array($this->defVals)) {
1307 $formData = $formDataCompiler->compile($formDataCompilerInput);
1310 if ($command ===
'new'
1311 && $table !==
'pages'
1312 && !empty($formData[
'parentPageRow'][
'uid'])
1314 $this->viewId = $formData[
'parentPageRow'][
'uid'];
1316 if ($table ===
'pages') {
1317 $this->viewId = $formData[
'databaseRow'][
'uid'];
1318 } elseif (!empty($formData[
'parentPageRow'][
'uid'])) {
1319 $this->viewId = $formData[
'parentPageRow'][
'uid'];
1321 if (!empty($formData[
'processedTca'][
'ctrl'][
'languageField'])
1322 && is_array($formData[
'databaseRow'][$formData[
'processedTca'][
'ctrl'][
'languageField']])
1323 && $formData[
'databaseRow'][$formData[
'processedTca'][
'ctrl'][
'languageField']][0] > 0
1325 $this->viewId_addParams =
'&L=' . $formData[
'databaseRow'][$formData[
'processedTca'][
'ctrl'][
'languageField']][0];
1331 $deleteAccess =
false;
1334 || $command ===
'new'
1336 $permission = $formData[
'userPermissionOnPage'];
1337 if ($formData[
'tableName'] ===
'pages') {
1345 if ($command ===
'edit') {
1348 $flashMessage = GeneralUtility::makeInstance(
1349 FlashMessage::class,
1354 $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
1355 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
1356 $defaultFlashMessageQueue->enqueue($flashMessage);
1361 if (!$this->storeTitle) {
1362 $this->storeTitle = $this->recTitle
1363 ? htmlspecialchars($this->recTitle)
1364 : BackendUtility::getRecordTitle($table, FormEngineUtility::databaseRowCompatibility($formData[
'databaseRow']), true);
1367 $this->elementsData[] = [
1369 'uid' => $formData[
'databaseRow'][
'uid'],
1370 'pid' => $formData[
'databaseRow'][
'pid'],
1372 'deleteAccess' => $deleteAccess
1375 if ($command !==
'new') {
1381 if ($this->columnsOnly) {
1382 if (is_array($this->columnsOnly)) {
1383 $formData[
'fieldListToRender'] = $this->columnsOnly[$table];
1389 $formData[
'renderType'] =
'outerWrapContainer';
1390 $formResult = $nodeFactory->create($formData)->render();
1392 $html = $formResult[
'html'];
1394 $formResult[
'html'] =
'';
1395 $formResult[
'doSaveFieldName'] =
'doSave';
1400 $this->formResultCompiler->mergeResult($formResult);
1403 if ($command ===
'new') {
1406 .
'<input type="hidden"'
1407 .
' name="data[' . htmlspecialchars($table) .
'][' . htmlspecialchars($formData[
'databaseRow'][
'uid']) .
'][pid]"'
1408 .
' value="' . (int)$formData[
'databaseRow'][
'pid'] .
'" />';
1413 }
catch (AccessDeniedException $e) {
1417 $message = $beUser->errorMsg;
1418 if (empty($message)) {
1420 $message = $e->getMessage() .
' ' . $e->getCode();
1422 $editForm .= htmlspecialchars($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noEditPermission'))
1423 .
'<br /><br />' . htmlspecialchars($message) .
'<br /><br />';
1424 }
catch (DatabaseRecordException $e) {
1425 $editForm =
'<div class="alert alert-warning">' . htmlspecialchars($e->getMessage()) .
'</div>';
1440 protected function getButtons(ServerRequestInterface $request): void
1443 $TCActrl =
$GLOBALS[
'TCA'][$this->firstEl[
'table']][
'ctrl'];
1447 $sysLanguageUid = 0;
1449 $this->isSavedRecord
1450 && isset($TCActrl[
'languageField'], $record[$TCActrl[
'languageField']])
1452 $sysLanguageUid = (int)$record[$TCActrl[
'languageField']];
1453 } elseif (isset($this->defVals[
'sys_language_uid'])) {
1454 $sysLanguageUid = (int)$this->defVals[
'sys_language_uid'];
1457 $l18nParent = isset($TCActrl[
'transOrigPointerField'], $record[$TCActrl[
'transOrigPointerField']])
1458 ? (int)$record[$TCActrl[
'transOrigPointerField']]
1463 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
1470 && !
$GLOBALS[
'TCA'][$this->firstEl[
'table']][
'ctrl'][
'readOnly']
1474 if ($this->firstEl[
'cmd'] !==
'new') {
1505 if (!is_bool($this->isSavedRecord)) {
1506 $this->isSavedRecord = (
1507 $this->firstEl[
'cmd'] !==
'new'
1521 $this->pageinfo[
'uid']
1522 )[
'mod'][
'web_layout'][
'allowInconsistentLanguageHandling'];
1524 return $allowInconsistentLanguageHandling[
'value'] ===
'1';
1535 if ($this->firstEl[
'table'] ===
'tt_content') {
1536 if (!$this->isSavedRecord) {
1538 (
int)$this->pageinfo[
'uid'],
1539 (
int)$this->defVals[
'colPos'],
1544 (
int)$this->pageinfo[
'uid'],
1545 (
int)$record[
'colPos'],
1562 $freeTranslationMode =
false;
1568 $freeTranslationMode =
true;
1571 return $freeTranslationMode;
1583 $closeButton = $buttonBar->makeLinkButton()
1585 ->setClasses(
't3js-editform-close')
1587 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.closeDoc'
1589 ->setShowLabelText(
true)
1590 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1595 $buttonBar->addButton($closeButton, $position, $group);
1607 $saveButton = $buttonBar->makeInputButton()
1608 ->setForm(
'EditDocumentController')
1609 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-save',
Icon::SIZE_SMALL))
1610 ->setName(
'_savedok')
1611 ->setShowLabelText(
true)
1613 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.saveDoc'
1617 $buttonBar->addButton($saveButton, $position, $group);
1632 && !empty($this->firstEl[
'table'])
1637 $classNames =
't3js-editform-view';
1641 if (isset($pagesTSconfig[
'TCEMAIN.'][
'preview.'][
'disableButtonForDokType'])) {
1642 $excludeDokTypes = GeneralUtility::intExplode(
1644 $pagesTSconfig[
'TCEMAIN.'][
'preview.'][
'disableButtonForDokType'],
1649 $excludeDokTypes = [
1657 !in_array((
int)$this->pageinfo[
'doktype'], $excludeDokTypes,
true)
1658 || isset($pagesTSconfig[
'TCEMAIN.'][
'preview.'][$this->firstEl[
'table'] .
'.'][
'previewPageId'])
1670 $viewButton = $buttonBar->makeLinkButton()
1671 ->setHref($previewUrl)
1672 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1676 ->setShowLabelText(
true)
1677 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.viewDoc'));
1679 if (!$this->isSavedRecord) {
1680 if ($this->firstEl[
'table'] ===
'pages') {
1681 $viewButton->setDataAttributes([
'is-new' =>
'']);
1685 if ($classNames !==
'') {
1686 $viewButton->setClasses($classNames);
1689 $buttonBar->addButton($viewButton, $position, $group);
1704 ButtonBar $buttonBar,
1707 int $sysLanguageUid,
1711 $this->firstEl[
'table'] !==
'sys_file_metadata'
1712 && !empty($this->firstEl[
'table'])
1717 || $this->isPageInFreeTranslationMode
1719 && $this->firstEl[
'table'] ===
'tt_content'
1722 $this->firstEl[
'table'] !==
'tt_content'
1724 $sysLanguageUid === 0
1725 || $l18nParent === 0
1731 $classNames =
't3js-editform-new';
1733 $newButton = $buttonBar->makeLinkButton()
1735 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1739 ->setShowLabelText(
true)
1740 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.newDoc'));
1742 if (!$this->isSavedRecord) {
1743 $newButton->setDataAttributes([
'is-new' =>
'']);
1746 if ($classNames !==
'') {
1747 $newButton->setClasses($classNames);
1750 $buttonBar->addButton($newButton, $position, $group);
1764 ButtonBar $buttonBar,
1767 int $sysLanguageUid,
1771 $this->firstEl[
'table'] !==
'sys_file_metadata'
1772 && !empty($this->firstEl[
'table'])
1777 || $this->isPageInFreeTranslationMode
1779 && $this->firstEl[
'table'] ===
'tt_content'
1782 $this->firstEl[
'table'] !==
'tt_content'
1784 $sysLanguageUid === 0
1785 || $l18nParent === 0
1791 $classNames =
't3js-editform-duplicate';
1793 $duplicateButton = $buttonBar->makeLinkButton()
1795 ->setShowLabelText(
true)
1796 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.duplicateDoc'))
1797 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1798 'actions-document-duplicates-select',
1802 if (!$this->isSavedRecord) {
1803 $duplicateButton->setDataAttributes([
'is-new' =>
'']);
1806 if ($classNames !==
'') {
1807 $duplicateButton->setClasses($classNames);
1810 $buttonBar->addButton($duplicateButton, $position, $group);
1824 $this->firstEl[
'deleteAccess']
1826 && $this->isSavedRecord
1827 && count($this->elementsData) === 1
1829 $classNames =
't3js-editform-delete-record';
1832 if ($this->firstEl[
'table'] ===
'pages') {
1833 parse_str((
string)parse_url(
$returnUrl, PHP_URL_QUERY), $queryParams);
1835 isset($queryParams[
'route'], $queryParams[
'id'])
1836 && (
string)$this->firstEl[
'uid'] === (
string)$queryParams[
'id']
1840 $returnUrl = (string)$this->uriBuilder->buildUriFromRoutePath($queryParams[
'route'], [
'id' => 0]);
1845 $referenceIndex = GeneralUtility::makeInstance(ReferenceIndex::class);
1846 $numberOfReferences = $referenceIndex->getNumberOfReferencedRecords(
1847 $this->firstEl[
'table'],
1848 (
int)$this->firstEl[
'uid']
1852 $this->firstEl[
'table'],
1853 (
int)$this->firstEl[
'uid'],
1855 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.referencesToRecord'
1860 $this->firstEl[
'table'],
1861 (
int)$this->firstEl[
'uid'],
1863 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.translationsOfRecord'
1867 $deleteButton = $buttonBar->makeLinkButton()
1868 ->setClasses($classNames)
1869 ->setDataAttributes([
1871 'uid' => $this->firstEl[
'uid'],
1872 'table' => $this->firstEl[
'table'],
1873 'reference-count-message' => $referenceCountMessage,
1874 'translation-count-message' => $translationCountMessage
1877 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1878 'actions-edit-delete',
1881 ->setShowLabelText(
true)
1884 $buttonBar->addButton($deleteButton, $position, $group);
1898 count($this->elementsData) === 1
1899 && !empty($this->firstEl[
'table'])
1902 $historyButtonOnClick =
'window.location.href=' .
1903 GeneralUtility::quoteJSvalue(
1904 (
string)$this->uriBuilder->buildUriFromRoute(
1907 'element' => $this->firstEl[
'table'] .
':' . $this->firstEl[
'uid'],
1908 'returnUrl' => $this->R_URI,
1911 ) .
'; return false;';
1913 $historyButton = $buttonBar->makeLinkButton()
1915 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1916 'actions-document-history-open',
1919 ->setOnClick($historyButtonOnClick)
1920 ->setTitle(
'Open history of this record')
1923 $buttonBar->addButton($historyButton, $position, $group);
1938 && count($this->elementsData) === 1
1940 $columnsOnlyButton = $buttonBar->makeLinkButton()
1941 ->setHref($this->R_URI .
'&columnsOnly=')
1943 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1948 $buttonBar->addButton($columnsOnlyButton, $position, $group);
1962 if ($this->returnUrl !== $closeUrl) {
1963 $requestUri = GeneralUtility::linkThisScript([
1964 'returnUrl' => $closeUrl,
1966 $aOnClick =
'vHWin=window.open('
1967 . GeneralUtility::quoteJSvalue($requestUri) .
','
1968 . GeneralUtility::quoteJSvalue(md5($this->R_URI))
1969 .
',\'width=670,height=500,status=0,menubar=0,scrollbars=1,resizable=1\');vHWin.focus();return false;';
1971 $openInNewWindowButton = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()
1974 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.openInNewWindow'))
1975 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-window-open',
Icon::SIZE_SMALL))
1976 ->setOnClick($aOnClick);
1978 $buttonBar->addButton($openInNewWindowButton, $position, $group);
1992 $shortCutButton = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->makeShortcutButton();
1993 $shortCutButton->setModuleName(
'xMOD_alt_doc.php')
2003 $buttonBar->addButton($shortCutButton, $position, $group);
2016 $cshButton = $buttonBar->makeHelpButton()->setModuleName(
'xMOD_csh_corebe')->setFieldName(
'TCEforms');
2018 $buttonBar->addButton($cshButton, $position, $group);
2033 return (
int)$queryBuilder
2035 $queryBuilder->expr()->gt(
2036 $GLOBALS[
'TCA'][
'tt_content'][
'ctrl'][
'transOrigPointerField'],
2037 $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
2056 return (
int)$queryBuilder
2058 $queryBuilder->expr()->eq(
2059 $GLOBALS[
'TCA'][
'tt_content'][
'ctrl'][
'transOrigPointerField'],
2060 $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
2077 $languageField =
$GLOBALS[
'TCA'][
'tt_content'][
'ctrl'][
'languageField'];
2079 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
2080 ->getQueryBuilderForTable(
'tt_content');
2082 $queryBuilder->getRestrictions()
2084 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2085 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
2087 return $queryBuilder
2089 ->from(
'tt_content')
2091 $queryBuilder->expr()->eq(
2093 $queryBuilder->createNamedParameter($page, \PDO::PARAM_INT)
2095 $queryBuilder->expr()->eq(
2097 $queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
2099 $queryBuilder->expr()->eq(
2101 $queryBuilder->createNamedParameter($column, \PDO::PARAM_INT)
2112 protected function compileForm(
string $editForm): string
2116 action="' . htmlspecialchars($this->R_URI) .
'"
2118 enctype="multipart/form-data"
2120 id="EditDocumentController"
2121 onsubmit="TBE_EDITOR.checkAndDoSubmit(1); return false;"
2124 <input type="hidden" name="returnUrl" value="' . htmlspecialchars($this->retUrl) .
'" />
2125 <input type="hidden" name="viewUrl" value="' . htmlspecialchars($this->viewUrl) .
'" />
2126 <input type="hidden" name="popViewId" value="' . htmlspecialchars((
string)$this->viewId) .
'" />
2127 <input type="hidden" name="closeDoc" value="0" />
2128 <input type="hidden" name="doSave" value="0" />
2129 <input type="hidden" name="_serialNumber" value="' . md5(microtime()) .
'" />
2130 <input type="hidden" name="_scrollPosition" value="" />';
2131 if ($this->returnNewPageId) {
2132 $formContent .=
'<input type="hidden" name="returnNewPageId" value="1" />';
2134 if ($this->viewId_addParams) {
2135 $formContent .=
'<input type="hidden" name="popViewId_addParams" value="' . htmlspecialchars($this->viewId_addParams) .
'" />';
2137 return $formContent;
2147 trigger_error(
'EditDocumentController->shortCutLink() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
2150 $shortCutButton = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->makeShortcutButton();
2151 $shortCutButton->setModuleName(
'xMOD_alt_doc.php')
2160 $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->addButton($shortCutButton);
2171 trigger_error(
'EditDocumentController->openInNewWindowLink() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
2174 if ($this->returnUrl !== $closeUrl) {
2175 $aOnClick =
'vHWin=window.open(' . GeneralUtility::quoteJSvalue(GeneralUtility::linkThisScript(
2176 [
'returnUrl' => $closeUrl]
2179 . GeneralUtility::quoteJSvalue(md5($this->R_URI))
2180 .
',\'width=670,height=500,status=0,menubar=0,scrollbars=1,resizable=1\');vHWin.focus();return false;';
2181 $openInNewWindowButton = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()
2184 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.openInNewWindow'))
2185 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-window-open',
Icon::SIZE_SMALL))
2186 ->setOnClick($aOnClick);
2187 $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->addButton(
2188 $openInNewWindowButton,
2202 $disableDelete =
false;
2203 if ($this->firstEl[
'table'] ===
'sys_file_metadata') {
2205 $languageUid = $row[
'sys_language_uid'];
2206 if ($languageUid === 0) {
2207 $disableDelete =
true;
2210 $disableDelete = (bool)$this->
getTsConfigOption($this->firstEl[
'table'] ??
'',
'disableDelete');
2212 return $disableDelete;
2223 $closeUrl = GeneralUtility::getFileAbsFileName(
'EXT:backend/Resources/Public/Html/Close.html');
2241 protected function languageSwitch(
string $table,
int $uid, $pid =
null)
2243 $languageField =
$GLOBALS[
'TCA'][$table][
'ctrl'][
'languageField'];
2244 $transOrigPointerField =
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerField'];
2249 && $transOrigPointerField
2251 if ($pid ===
null) {
2257 if ($table ===
'pages') {
2261 (
int)$row[
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'transOrigPointerField']] ?: $uid,
2265 $availableLanguages = $this->
getLanguages((
int)$pid, $table);
2268 if (count($availableLanguages) > 1) {
2270 $fetchFields =
'uid,' . $languageField .
',' . $transOrigPointerField;
2273 if (!is_array($rowCurrent)) {
2276 $currentLanguage = (int)$rowCurrent[$languageField];
2278 if ($currentLanguage > -1) {
2280 if ($currentLanguage && $rowCurrent[$transOrigPointerField]) {
2283 $rowCurrent[$transOrigPointerField],
2286 if (!is_array($rowsByLang[0])) {
2289 $rowCurrent[$transOrigPointerField],
2294 $rowsByLang[$rowCurrent[$languageField]] = $rowCurrent;
2296 if ($rowCurrent[$transOrigPointerField] || $currentLanguage === 0) {
2299 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
2300 ->getQueryBuilderForTable($table);
2302 $queryBuilder->getRestrictions()
2304 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2305 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
2307 $result = $queryBuilder->select(...GeneralUtility::trimExplode(
',', $fetchFields,
true))
2310 $queryBuilder->expr()->eq(
2312 $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT)
2314 $queryBuilder->expr()->gt(
2316 $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
2318 $queryBuilder->expr()->eq(
2319 $transOrigPointerField,
2320 $queryBuilder->createNamedParameter($rowsByLang[0][
'uid'], \PDO::PARAM_INT)
2325 while ($row = $result->fetch()) {
2326 $rowsByLang[$row[$languageField]] = $row;
2329 $languageMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
2330 $languageMenu->setIdentifier(
'_langSelector');
2331 foreach ($availableLanguages as $language) {
2332 $languageId = $language->getLanguageId();
2333 $selectorOptionLabel = $language->getTitle();
2337 if (!isset($rowsByLang[$languageId])) {
2339 $selectorOptionLabel .=
' [' . htmlspecialchars($this->
getLanguageService()->sL(
'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.new')) .
']';
2340 $redirectUrl = (string)$this->uriBuilder->buildUriFromRoute(
'record_edit', [
2341 'justLocalized' => $table .
':' . $rowsByLang[0][
'uid'] .
':' . $languageId,
2342 'returnUrl' => $this->retUrl
2345 if (array_key_exists(0, $rowsByLang)) {
2347 '&cmd[' . $table .
'][' . $rowsByLang[0][
'uid'] .
'][localize]=' . $languageId,
2355 'edit[' . $table .
'][' . $rowsByLang[$languageId][
'uid'] .
']' =>
'edit',
2358 if ($table ===
'pages') {
2360 $params[
'overrideVals'] = [
2362 'sys_language_uid' => $languageId
2366 $href = (string)$this->uriBuilder->buildUriFromRoute(
'record_edit', $params);
2369 $menuItem = $languageMenu->makeMenuItem()
2370 ->setTitle($selectorOptionLabel)
2372 if ($languageId === $currentLanguage) {
2373 $menuItem->setActive(
true);
2375 $languageMenu->addMenuItem($menuItem);
2378 $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($languageMenu);
2392 $deprecatedCaller =
false;
2393 if (!$request instanceof ServerRequestInterface) {
2396 trigger_error(
'EditDocumentController->localizationRedirect() will be set to protected in TYPO3 v10.0. Do not call from other extension.', E_USER_DEPRECATED);
2397 $justLocalized = $request;
2399 $deprecatedCaller =
true;
2401 $justLocalized = $request->getQueryParams()[
'justLocalized'];
2404 if (empty($justLocalized)) {
2408 list($table, $origUid, $language) = explode(
':', $justLocalized);
2411 &&
$GLOBALS[
'TCA'][$table][
'ctrl'][
'languageField']
2412 &&
$GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerField']
2414 $parsedBody = $request->getParsedBody();
2415 $queryParams = $request->getQueryParams();
2417 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
2418 $queryBuilder->getRestrictions()
2420 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2421 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
2422 $localizedRecord = $queryBuilder->select(
'uid')
2425 $queryBuilder->expr()->eq(
2426 $GLOBALS[
'TCA'][$table][
'ctrl'][
'languageField'],
2427 $queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
2429 $queryBuilder->expr()->eq(
2430 $GLOBALS[
'TCA'][$table][
'ctrl'][
'transOrigPointerField'],
2431 $queryBuilder->createNamedParameter($origUid, \PDO::PARAM_INT)
2436 $returnUrl = $parsedBody[
'returnUrl'] ?? $queryParams[
'returnUrl'] ??
'';
2437 if (is_array($localizedRecord)) {
2438 if ($deprecatedCaller) {
2440 $location = (string)$this->uriBuilder->buildUriFromRoute(
'record_edit', [
2441 'edit[' . $table .
'][' . $localizedRecord[
'uid'] .
']' =>
'edit',
2442 'returnUrl' => GeneralUtility::sanitizeLocalUrl(
$returnUrl)
2448 (
string)$this->uriBuilder->buildUriFromRoute(
2451 'edit[' . $table .
'][' . $localizedRecord[
'uid'] .
']' =>
'edit',
2452 'returnUrl' => GeneralUtility::sanitizeLocalUrl(
$returnUrl)
2471 protected function getLanguages(
int $id,
string $table): array
2474 if ($id < 0 && $table !==
'pages') {
2475 $pageId = $this->pageinfo[
'uid'] ??
null;
2476 if ($pageId !==
null) {
2477 $pageId = (int)$pageId;
2480 $pageId = (int)$fullRecord[
'pid'];
2483 if ($table ===
'pages' && $id > 0) {
2485 $id = (int)($fullRecord[
't3ver_oid'] ?: $fullRecord[
'uid']);
2489 $site = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId($pageId);
2492 $allLanguages = $site->getAvailableLanguages($this->
getBackendUser(),
false, $pageId);
2493 if ($table !==
'pages' && $id > 0) {
2494 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable(
'pages');
2495 $queryBuilder->getRestrictions()->removeAll()
2496 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2497 ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
2498 $statement = $queryBuilder->select(
'uid',
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'languageField'])
2501 $queryBuilder->expr()->eq(
2502 $GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'transOrigPointerField'],
2503 $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
2508 $availableLanguages = [];
2510 if ($allLanguages[0] ??
false) {
2511 $availableLanguages = [
2512 0 => $allLanguages[0]
2516 while ($row = $statement->fetch()) {
2517 $languageId = (int)$row[
$GLOBALS[
'TCA'][
'pages'][
'ctrl'][
'languageField']];
2518 if (isset($allLanguages[$languageId])) {
2519 $availableLanguages[$languageId] = $allLanguages[$languageId];
2522 return $availableLanguages;
2524 return $allLanguages;
2535 if (is_array($this->editconf)) {
2537 foreach ($this->editconf as $table => $conf) {
2538 if (is_array($conf) &&
$GLOBALS[
'TCA'][$table]) {
2541 foreach ($conf as $cKey =>
$cmd) {
2542 if (
$cmd ===
'edit') {
2544 $ids = GeneralUtility::trimExplode(
',', $cKey,
true);
2545 foreach ($ids as $idKey => $theUid) {
2546 if (is_array($mapArray)) {
2547 if ($mapArray[$table][$theUid]) {
2548 $ids[$idKey] = $mapArray[$table][$theUid];
2553 if (is_array($calcPRec)) {
2555 $ids[$idKey] = $calcPRec[
'uid'];
2560 $newConf[implode(
',', $ids)] =
$cmd;
2562 $newConf[$cKey] =
$cmd;
2566 $this->editconf[$table] = $newConf;
2583 if (is_array($reqRecord)) {
2589 if ($reqRecord[
'pid'] == -1) {
2603 return is_array($versionRec) ? $versionRec : $reqRecord;
2623 trigger_error(
'EditDocumentController->compileStoreDat() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
2634 $this->storeArray = GeneralUtility::compileSelectedGetVarsFromArray(
2635 'edit,defVals,overrideVals,columnsOnly,noView,workspace',
2636 $this->R_URL_getvars
2639 $this->storeUrlMd5 = md5($this->storeUrl);
2653 trigger_error(
'EditDocumentController->getNewIconMode() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
2666 return \trim((
string)(
2667 $this->
getBackendUser()->getTSConfig()[
'options.'][$key .
'.'][$table]
2685 public function closeDocument($mode = self::DOCUMENT_CLOSE_MODE_DEFAULT, ServerRequestInterface $request =
null): ?ResponseInterface
2688 $deprecatedCaller =
false;
2689 if ($request ===
null) {
2691 trigger_error(
'EditDocumentController->closeDocument will be set to protected in TYPO3 v10.0.', E_USER_DEPRECATED);
2693 $deprecatedCaller =
true;
2699 if (isset($this->docHandler[$this->storeUrlMd5])) {
2702 if (!is_array($recentDocs)) {
2706 $recentDocs = array_merge([$this->storeUrlMd5 => $closedDoc], $recentDocs);
2707 if (count($recentDocs) > 8) {
2708 $recentDocs = array_slice($recentDocs, 0, 8);
2711 unset($this->docHandler[$this->storeUrlMd5]);
2712 if ($mode === self::DOCUMENT_CLOSE_MODE_CLEAR_ALL) {
2713 $recentDocs = array_merge($this->docHandler, $recentDocs);
2714 $this->docHandler = [];
2720 if ($mode === self::DOCUMENT_CLOSE_MODE_NO_REDIRECT) {
2725 if ($this->returnEditConf && $this->retUrl != (
string)$this->uriBuilder->buildUriFromRoute(
'dummy')) {
2726 $this->retUrl .=
'&returnEditConf=' . rawurlencode(json_encode($this->editconf));
2729 if ($mode === self::DOCUMENT_CLOSE_MODE_DEFAULT || $mode === self::DOCUMENT_CLOSE_MODE_REDIRECT) {
2730 if ($deprecatedCaller) {
2734 return new RedirectResponse($this->retUrl, 303);
2736 if ($this->retUrl ===
'') {
2740 if (is_array($this->docHandler) && !empty($this->docHandler)) {
2741 if (!empty($setupArr[2])) {
2742 $sParts = parse_url($request->getAttribute(
'normalizedParams')->getRequestUri());
2743 $retUrl = $sParts[
'path'] .
'?' . $setupArr[2] .
'&returnUrl=' . rawurlencode(
$retUrl);
2746 if ($deprecatedCaller) {
2763 trigger_error(
'EditDocumentController->setDocument() will be removed in TYPO3 v10.0.', E_USER_DEPRECATED);
2767 if (is_array($this->docHandler) && !empty($this->docHandler)) {
2768 if (isset($this->docHandler[$currentDocFromHandlerMD5])) {
2769 $setupArr = $this->docHandler[$currentDocFromHandlerMD5];
2771 $setupArr = reset($this->docHandler);
2774 $sParts = parse_url(GeneralUtility::getIndpEnv(
'REQUEST_URI'));
2775 $retUrl = $sParts[
'path'] .
'?' . $setupArr[2] .
'&returnUrl=' . rawurlencode(
$retUrl);
2799 if (!isset($this->signalSlotDispatcher)) {
2800 $this->signalSlotDispatcher = GeneralUtility::makeInstance(Dispatcher::class);