‪TYPO3CMS  10.4
EditDocumentController.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\EventDispatcher\EventDispatcherInterface;
21 use Psr\Http\Message\ResponseInterface;
22 use Psr\Http\Message\ServerRequestInterface;
58 
67 {
68  protected const ‪DOCUMENT_CLOSE_MODE_DEFAULT = 0;
69  // works like DOCUMENT_CLOSE_MODE_DEFAULT
70  protected const ‪DOCUMENT_CLOSE_MODE_REDIRECT = 1;
71  protected const ‪DOCUMENT_CLOSE_MODE_CLEAR_ALL = 3;
73 
79  protected ‪$editconf = [];
80 
87  protected ‪$columnsOnly;
88 
94  protected ‪$defVals;
95 
101  protected ‪$overrideVals;
102 
109  protected ‪$returnUrl;
110 
118  protected ‪$retUrl;
119 
125  protected ‪$closeDoc;
126 
134  protected ‪$doSave;
135 
143  public ‪$data;
144 
150  protected ‪$cmd;
151 
157  protected ‪$mirror;
158 
165  protected ‪$returnNewPageId = false;
166 
173  protected ‪$uc;
174 
180  protected ‪$popViewId;
181 
187  protected ‪$viewUrl;
188 
194  protected ‪$recTitle;
195 
201  protected ‪$noView;
202 
206  protected ‪$perms_clause;
207 
213  protected ‪$returnEditConf;
214 
220  protected ‪$R_URL_parts;
221 
228  protected ‪$R_URL_getvars;
229 
235  protected ‪$R_URI;
236 
240  protected ‪$pageinfo;
241 
248  protected ‪$storeTitle = '';
249 
256  protected ‪$storeArray;
257 
263  protected ‪$storeUrl;
264 
270  protected ‪$storeUrlMd5;
271 
277  protected ‪$docDat;
278 
287  protected ‪$docHandler;
288 
296  public ‪$elementsData;
297 
303  protected ‪$firstEl;
304 
310  protected ‪$errorC;
311 
317  protected ‪$newC;
318 
325  protected ‪$viewId;
326 
332  protected ‪$viewId_addParams;
333 
338 
344  protected ‪$dontStoreDocumentRef = 0;
345 
351  protected ‪$previewData = [];
352 
358  protected ‪$moduleTemplate;
359 
365  protected ‪$isSavedRecord;
366 
372  protected ‪$isPageInFreeTranslationMode = false;
373 
377  protected ‪$eventDispatcher;
378 
382  protected ‪$uriBuilder;
383 
384  public function ‪__construct(EventDispatcherInterface ‪$eventDispatcher)
385  {
386  $this->eventDispatcher = ‪$eventDispatcher;
387  $this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
388  $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
389  $this->moduleTemplate->setUiBlock(true);
390  // @todo Used by TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching
391  ‪$GLOBALS['SOBE'] = $this;
392  $this->‪getLanguageService()->‪includeLLFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf');
393  }
394 
401  public function ‪mainAction(ServerRequestInterface $request): ResponseInterface
402  {
403  // Unlock all locked records
405  if ($response = $this->‪preInit($request)) {
406  return $response;
407  }
408 
409  // Process incoming data via DataHandler?
410  $parsedBody = $request->getParsedBody();
411  if ($this->doSave
412  || isset($parsedBody['_savedok'])
413  || isset($parsedBody['_saveandclosedok'])
414  || isset($parsedBody['_savedokview'])
415  || isset($parsedBody['_savedoknew'])
416  || isset($parsedBody['_duplicatedoc'])
417  ) {
418  if ($response = $this->‪processData($request)) {
419  return $response;
420  }
421  }
422 
423  $this->‪init($request);
424  $this->‪main($request);
425 
426  return new ‪HtmlResponse($this->moduleTemplate->renderContent());
427  }
428 
435  protected function ‪preInit(ServerRequestInterface $request): ?ResponseInterface
436  {
437  if ($response = $this->‪localizationRedirect($request)) {
438  return $response;
439  }
440 
441  $parsedBody = $request->getParsedBody();
442  $queryParams = $request->getQueryParams();
443 
444  $this->editconf = $parsedBody['edit'] ?? $queryParams['edit'] ?? [];
445  $this->defVals = $parsedBody['defVals'] ?? $queryParams['defVals'] ?? null;
446  $this->overrideVals = $parsedBody['overrideVals'] ?? $queryParams['overrideVals'] ?? null;
447  $this->columnsOnly = $parsedBody['columnsOnly'] ?? $queryParams['columnsOnly'] ?? null;
448  $this->returnUrl = GeneralUtility::sanitizeLocalUrl($parsedBody['returnUrl'] ?? $queryParams['returnUrl'] ?? null);
449  $this->closeDoc = (int)($parsedBody['closeDoc'] ?? $queryParams['closeDoc'] ?? self::DOCUMENT_CLOSE_MODE_DEFAULT);
450  $this->doSave = (bool)($parsedBody['doSave'] ?? $queryParams['doSave'] ?? false);
451  $this->returnEditConf = (bool)($parsedBody['returnEditConf'] ?? $queryParams['returnEditConf'] ?? false);
452  $this->uc = $parsedBody['uc'] ?? $queryParams['uc'] ?? null;
453 
454  // Set overrideVals as default values if defVals does not exist.
455  // @todo: Why?
456  if (!is_array($this->defVals) && is_array($this->overrideVals)) {
457  $this->defVals = ‪$this->overrideVals;
458  }
459  $this->‪addSlugFieldsToColumnsOnly($queryParams);
460 
461  // Set final return URL
462  $this->retUrl = $this->returnUrl ?: (string)$this->uriBuilder->buildUriFromRoute('dummy');
463 
464  // Change $this->editconf if versioning applies to any of the records
466 
467  // Prepare R_URL (request url)
468  $this->R_URL_parts = parse_url($request->getAttribute('normalizedParams')->getRequestUri());
469  $this->R_URL_getvars = $queryParams;
470  $this->R_URL_getvars['edit'] = ‪$this->editconf;
471 
472  // Prepare 'open documents' url, this is later modified again various times
473  $this->‪compileStoreData();
474  // Backend user session data of this module
475  $this->docDat = $this->‪getBackendUser()->‪getModuleData('FormEngine', 'ses');
476  $this->docHandler = $this->docDat[0];
477 
478  // Close document if a request for closing the document has been sent
479  if ((int)$this->closeDoc > self::DOCUMENT_CLOSE_MODE_DEFAULT) {
480  if ($response = $this->‪closeDocument($this->closeDoc, $request)) {
481  return $response;
482  }
483  }
484 
485  $event = new BeforeFormEnginePageInitializedEvent($this, $request);
486  $this->eventDispatcher->dispatch($event);
487  return null;
488  }
489 
495  protected function ‪addSlugFieldsToColumnsOnly(array $queryParams): void
496  {
497  ‪$data = $queryParams['edit'] ?? [];
498  ‪$data = array_keys(‪$data);
499  $table = reset(‪$data);
500  if ($this->columnsOnly && $table !== false && isset(‪$GLOBALS['TCA'][$table])) {
501  ‪$fields = ‪GeneralUtility::trimExplode(',', $this->columnsOnly, true);
502  foreach (‪$fields as $field) {
503  $postModifiers = ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['generatorOptions']['postModifiers'] ?? [];
504  if (isset(‪$GLOBALS['TCA'][$table]['columns'][$field])
505  && ‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['type'] === 'slug'
506  && (!is_array($postModifiers) || $postModifiers === [])
507  ) {
508  foreach (‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['generatorOptions']['fields'] ?? [] as ‪$fields) {
509  $this->columnsOnly .= ',' . (is_array(‪$fields) ? implode(',', ‪$fields) : ‪$fields);
510  }
511  }
512  }
513  }
514  }
515 
522  protected function ‪processData(ServerRequestInterface $request): ?ResponseInterface
523  {
524  $parsedBody = $request->getParsedBody();
525  $queryParams = $request->getQueryParams();
526 
527  $beUser = $this->‪getBackendUser();
528 
529  // Processing related GET / POST vars
530  $this->data = $parsedBody['data'] ?? $queryParams['data'] ?? [];
531  $this->cmd = $parsedBody['cmd'] ?? $queryParams['cmd'] ?? [];
532  $this->mirror = $parsedBody['mirror'] ?? $queryParams['mirror'] ?? [];
533  $this->returnNewPageId = (bool)($parsedBody['returnNewPageId'] ?? $queryParams['returnNewPageId'] ?? false);
534 
535  // Only options related to $this->data submission are included here
536  $tce = GeneralUtility::makeInstance(DataHandler::class);
537 
538  $tce->setControl($parsedBody['control'] ?? $queryParams['control'] ?? []);
539 
540  // Set internal vars
541  if (isset($beUser->uc['neverHideAtCopy']) && $beUser->uc['neverHideAtCopy']) {
542  $tce->neverHideAtCopy = 1;
543  }
544 
545  // Set default values fetched previously from GET / POST vars
546  if (is_array($this->defVals) && $this->defVals !== [] && is_array($tce->defaultValues)) {
547  $tce->defaultValues = array_merge_recursive($this->defVals, $tce->defaultValues);
548  }
549 
550  // Load DataHandler with data
551  $tce->start($this->data, $this->cmd);
552  if (is_array($this->mirror)) {
553  $tce->setMirror($this->mirror);
554  }
555 
556  // Perform the saving operation with DataHandler:
557  if ($this->doSave === true) {
558  $tce->process_datamap();
559  $tce->process_cmdmap();
560  }
561  // If pages are being edited, we set an instruction about updating the page tree after this operation.
562  if ($tce->pagetreeNeedsRefresh
563  && (isset($this->data['pages']) || $beUser->workspace != 0 && !empty($this->data))
564  ) {
565  ‪BackendUtility::setUpdateSignal('updatePageTree');
566  }
567  // If there was saved any new items, load them:
568  if (!empty($tce->substNEWwithIDs_table)) {
569  // Save the expanded/collapsed states for new inline records, if any
571  $newEditConf = [];
572  foreach ($this->editconf as $tableName => $tableCmds) {
573  $keys = array_keys($tce->substNEWwithIDs_table, $tableName);
574  if (!empty($keys)) {
575  foreach ($keys as $key) {
576  $editId = $tce->substNEWwithIDs[$key];
577  // Check if the $editId isn't a child record of an IRRE action
578  if (!(is_array($tce->newRelatedIDs[$tableName])
579  && in_array($editId, $tce->newRelatedIDs[$tableName]))
580  ) {
581  // Translate new id to the workspace version
583  $beUser->workspace,
584  $tableName,
585  $editId,
586  'uid'
587  )) {
588  $editId = $versionRec['uid'];
589  }
590  $newEditConf[$tableName][$editId] = 'edit';
591  }
592  // Traverse all new records and forge the content of ->editconf so we can continue to edit these records!
593  if ($tableName === 'pages'
594  && $this->retUrl !== (string)$this->uriBuilder->buildUriFromRoute('dummy')
595  && $this->retUrl !== $this->getCloseUrl()
596  && $this->returnNewPageId
597  ) {
598  $this->retUrl .= '&id=' . $tce->substNEWwithIDs[$key];
599  }
600  }
601  } else {
602  $newEditConf[$tableName] = $tableCmds;
603  }
604  }
605  // Reset editconf if newEditConf has values
606  if (!empty($newEditConf)) {
607  $this->editconf = $newEditConf;
608  }
609  // Finally, set the editconf array in the "getvars" so they will be passed along in URLs as needed.
610  $this->R_URL_getvars['edit'] = ‪$this->editconf;
611  // Unset default values since we don't need them anymore.
612  unset($this->R_URL_getvars['defVals']);
613  // Recompile the store* values since editconf changed
614  $this->‪compileStoreData();
615  }
616  // See if any records was auto-created as new versions?
617  if (!empty($tce->autoVersionIdMap)) {
618  $this->‪fixWSversioningInEditConf($tce->autoVersionIdMap);
619  }
620  // If a document is saved and a new one is created right after.
621  if (isset($parsedBody['_savedoknew']) && is_array($this->editconf)) {
622  if ($redirect = $this->‪closeDocument(self::DOCUMENT_CLOSE_MODE_NO_REDIRECT, $request)) {
623  return $redirect;
624  }
625  // Find the current table
626  reset($this->editconf);
627  $nTable = (string)key($this->editconf);
628  // Finding the first id, getting the records pid+uid
629  reset($this->editconf[$nTable]);
630  $nUid = (int)key($this->editconf[$nTable]);
631  $recordFields = 'pid,uid';
633  $recordFields .= ',t3ver_oid';
634  }
635  $nRec = ‪BackendUtility::getRecord($nTable, $nUid, $recordFields);
636  // Determine insertion mode: 'top' is self-explaining,
637  // otherwise new elements are inserted after one using a negative uid
638  $insertRecordOnTop = ($this->‪getTsConfigOption($nTable, 'saveDocNew') === 'top');
639  // Setting a blank editconf array for a new record:
640  $this->editconf = [];
641  // Determine related page ID for regular live context
642  if ((int)($nRec['t3ver_oid'] ?? 0) === 0) {
643  if ($insertRecordOnTop) {
644  $relatedPageId = $nRec['pid'];
645  } else {
646  $relatedPageId = -$nRec['uid'];
647  }
648  } else {
649  // Determine related page ID for workspace context
650  if ($insertRecordOnTop) {
651  // Fetch live version of workspace version since the pid value is always -1 in workspaces
652  $liveRecord = ‪BackendUtility::getRecord($nTable, $nRec['t3ver_oid'], $recordFields);
653  $relatedPageId = $liveRecord['pid'];
654  } else {
655  // Use uid of live version of workspace version
656  $relatedPageId = -$nRec['t3ver_oid'];
657  }
658  }
659  $this->editconf[$nTable][$relatedPageId] = 'new';
660  // Finally, set the editconf array in the "getvars" so they will be passed along in URLs as needed.
661  $this->R_URL_getvars['edit'] = ‪$this->editconf;
662  // Recompile the store* values since editconf changed...
663  $this->‪compileStoreData();
664  }
665  // If a document should be duplicated.
666  if (isset($parsedBody['_duplicatedoc']) && is_array($this->editconf)) {
667  $this->‪closeDocument(self::DOCUMENT_CLOSE_MODE_NO_REDIRECT, $request);
668  // Find current table
669  reset($this->editconf);
670  $nTable = (string)key($this->editconf);
671  // Find the first id, getting the records pid+uid
672  reset($this->editconf[$nTable]);
673  $nUid = key($this->editconf[$nTable]);
675  $nUid = $tce->substNEWwithIDs[$nUid];
676  }
677 
678  $recordFields = 'pid,uid';
680  $recordFields .= ',t3ver_oid';
681  }
682  $nRec = ‪BackendUtility::getRecord($nTable, $nUid, $recordFields);
683 
684  // Setting a blank editconf array for a new record:
685  $this->editconf = [];
686 
687  if ((int)($nRec['t3ver_oid'] ?? 0) === 0) {
688  $relatedPageId = -$nRec['uid'];
689  } else {
690  $relatedPageId = -$nRec['t3ver_oid'];
691  }
692 
694  $duplicateTce = GeneralUtility::makeInstance(DataHandler::class);
695 
696  $duplicateCmd = [
697  $nTable => [
698  $nUid => [
699  'copy' => $relatedPageId
700  ]
701  ]
702  ];
703 
704  $duplicateTce->start([], $duplicateCmd);
705  $duplicateTce->process_cmdmap();
706 
707  $duplicateMappingArray = $duplicateTce->copyMappingArray;
708  $duplicateUid = $duplicateMappingArray[$nTable][$nUid];
709 
710  if ($nTable === 'pages') {
711  ‪BackendUtility::setUpdateSignal('updatePageTree');
712  }
713 
714  $this->editconf[$nTable][$duplicateUid] = 'edit';
715  // Finally, set the editconf array in the "getvars" so they will be passed along in URLs as needed.
716  $this->R_URL_getvars['edit'] = ‪$this->editconf;
717  // Recompile the store* values since editconf changed...
718  $this->‪compileStoreData();
719 
720  // Inform the user of the duplication
721  $flashMessage = GeneralUtility::makeInstance(
722  FlashMessage::class,
723  $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.recordDuplicated'),
724  '',
726  );
727  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
728  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
729  $defaultFlashMessageQueue->enqueue($flashMessage);
730  }
731  // If a preview is requested
732  if (isset($parsedBody['_savedokview'])) {
733  $array_keys = array_keys($this->data);
734  // Get the first table and id of the data array from DataHandler
735  $table = reset($array_keys);
736  $array_keys = array_keys($this->data[$table]);
737  $id = reset($array_keys);
739  $id = $tce->substNEWwithIDs[$id];
740  }
741  // Store this information for later use
742  $this->previewData['table'] = $table;
743  $this->previewData['id'] = $id;
744  }
745  $tce->printLogErrorMessages();
746 
747  if ((int)$this->closeDoc < self::DOCUMENT_CLOSE_MODE_DEFAULT
748  || isset($parsedBody['_saveandclosedok'])
749  ) {
750  // Redirect if element should be closed after save
751  return $this->‪closeDocument((int)abs($this->closeDoc), $request);
752  }
753  return null;
754  }
755 
761  protected function ‪init(ServerRequestInterface $request): void
762  {
763  $parsedBody = $request->getParsedBody();
764  $queryParams = $request->getQueryParams();
765 
766  $beUser = $this->‪getBackendUser();
767 
768  $this->popViewId = (int)($parsedBody['popViewId'] ?? $queryParams['popViewId'] ?? 0);
769  $this->viewUrl = (string)($parsedBody['viewUrl'] ?? $queryParams['viewUrl'] ?? '');
770  $this->recTitle = (string)($parsedBody['recTitle'] ?? $queryParams['recTitle'] ?? '');
771  $this->noView = (bool)($parsedBody['noView'] ?? $queryParams['noView'] ?? false);
772  $this->perms_clause = $beUser->getPagePermsClause(‪Permission::PAGE_SHOW);
773  // Set other internal variables:
774  $this->R_URL_getvars['returnUrl'] = ‪$this->retUrl;
775  $this->R_URI = $this->R_URL_parts['path'] . ‪HttpUtility::buildQueryString($this->R_URL_getvars, '?');
776 
777  $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
778  $pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf');
779 
780  $this->moduleTemplate->addJavaScriptCode(
781  'previewCode',
782  (isset($parsedBody['_savedokview']) && $this->popViewId ? $this->‪generatePreviewCode() : '')
783  );
784  // Set context sensitive menu
785  $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ContextMenu');
786 
787  $event = new ‪AfterFormEnginePageInitializedEvent($this, $request);
788  $this->eventDispatcher->dispatch($event);
789  }
790 
796  protected function ‪generatePreviewCode(): string
797  {
798  $previewPageId = $this->‪getPreviewPageId();
799  $previewPageRootLine = ‪BackendUtility::BEgetRootLine($previewPageId);
800  $anchorSection = $this->‪getPreviewUrlAnchorSection();
801 
802  try {
803  $previewUrlParameters = $this->‪getPreviewUrlParameters($previewPageId);
804  return '
805  if (window.opener) {
806  '
808  $previewPageId,
809  '',
810  $previewPageRootLine,
811  $anchorSection,
812  $this->viewUrl,
813  $previewUrlParameters,
814  false
815  )
816  . '
817  } else {
818  '
820  $previewPageId,
821  '',
822  $previewPageRootLine,
823  $anchorSection,
824  $this->viewUrl,
825  $previewUrlParameters
826  )
827  . '
828  }';
829  } catch (‪UnableToLinkToPageException $e) {
830  return '';
831  }
832  }
833 
840  protected function ‪getPreviewUrlParameters(int $previewPageId): string
841  {
842  $linkParameters = [];
843  $table = $this->previewData['table'] ?: $this->firstEl['table'];
844  $recordId = $this->previewData['id'] ?: $this->firstEl['uid'];
845  $previewConfiguration = ‪BackendUtility::getPagesTSconfig($previewPageId)['TCEMAIN.']['preview.'][$table . '.'] ?? [];
846  $recordArray = ‪BackendUtility::getRecord($table, $recordId);
847 
848  // language handling
849  $languageField = ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'] ?? '';
850  if ($languageField && !empty($recordArray[$languageField])) {
851  $recordId = $this->‪resolvePreviewRecordId($table, $recordArray, $previewConfiguration);
852  $language = $recordArray[$languageField];
853  if ($language > 0) {
854  $linkParameters['L'] = $language;
855  }
856  }
857 
858  // Always use live workspace record uid for the preview
859  if (‪BackendUtility::isTableWorkspaceEnabled($table) && ($recordArray['t3ver_oid'] ?? 0) > 0) {
860  $recordId = $recordArray['t3ver_oid'];
861  }
862 
863  // map record data to GET parameters
864  if (isset($previewConfiguration['fieldToParameterMap.'])) {
865  foreach ($previewConfiguration['fieldToParameterMap.'] as $field => $parameterName) {
866  $value = $recordArray[$field];
867  if ($field === 'uid') {
868  $value = $recordId;
869  }
870  $linkParameters[$parameterName] = $value;
871  }
872  }
873 
874  // add/override parameters by configuration
875  if (isset($previewConfiguration['additionalGetParameters.'])) {
876  $additionalGetParameters = [];
878  $additionalGetParameters,
879  $previewConfiguration['additionalGetParameters.']
880  );
881  $linkParameters = array_replace($linkParameters, $additionalGetParameters);
882  }
883 
884  return ‪HttpUtility::buildQueryString($linkParameters, '&');
885  }
886 
894  protected function ‪resolvePreviewRecordId(string $table, array $recordArray, array $previewConfiguration): int
895  {
896  $l10nPointer = ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ?? '';
897  if ($l10nPointer
898  && !empty($recordArray[$l10nPointer])
899  && (
900  // not set -> default to true
901  !isset($previewConfiguration['useDefaultLanguageRecord'])
902  // or set -> use value
903  || $previewConfiguration['useDefaultLanguageRecord']
904  )
905  ) {
906  return (int)$recordArray[$l10nPointer];
907  }
908  return (int)$recordArray['uid'];
909  }
910 
916  protected function ‪getPreviewUrlAnchorSection(): string
917  {
918  $table = $this->previewData['table'] ?: $this->firstEl['table'];
919  $recordId = $this->previewData['id'] ?: $this->firstEl['uid'];
920 
921  return $table === 'tt_content' ? '#c' . (int)$recordId : '';
922  }
923 
929  protected function ‪getPreviewPageId(): int
930  {
931  $previewPageId = 0;
932  $table = $this->previewData['table'] ?: $this->firstEl['table'];
933  $recordId = $this->previewData['id'] ?: $this->firstEl['uid'];
934  $pageId = $this->popViewId ?: ‪$this->viewId;
935 
936  if ($table === 'pages') {
937  $currentPageId = (int)$recordId;
938  } else {
939  $currentPageId = ‪MathUtility::convertToPositiveInteger($pageId);
940  }
941 
942  $previewConfiguration = ‪BackendUtility::getPagesTSconfig($currentPageId)['TCEMAIN.']['preview.'][$table . '.'] ?? [];
943 
944  if (isset($previewConfiguration['previewPageId'])) {
945  $previewPageId = (int)$previewConfiguration['previewPageId'];
946  }
947  // if no preview page was configured
948  if (!$previewPageId) {
949  $rootPageData = null;
950  $rootLine = ‪BackendUtility::BEgetRootLine($currentPageId);
951  $currentPage = (array)(reset($rootLine) ?: []);
952  if ($this->‪canViewDoktype($currentPage)) {
953  // try the current page
954  $previewPageId = $currentPageId;
955  } else {
956  // or search for the root page
957  foreach ($rootLine as $page) {
958  if ($page['is_siteroot']) {
959  $rootPageData = $page;
960  break;
961  }
962  }
963  $previewPageId = isset($rootPageData)
964  ? (int)$rootPageData['uid']
965  : $currentPageId;
966  }
967  }
968 
969  $this->popViewId = $previewPageId;
970 
971  return $previewPageId;
972  }
973 
980  protected function ‪canViewDoktype(array $currentPage): bool
981  {
982  if (!isset($currentPage['uid']) || !($currentPage['doktype'] ?? false)) {
983  // In case the current page record is invalid, the element can not be viewed
984  return false;
985  }
986 
987  return !in_array((int)$currentPage['doktype'], [
991  ], true);
992  }
993 
1003  protected function ‪parseAdditionalGetParameters(array &$parameters, array $typoScript)
1004  {
1005  foreach ($typoScript as $key => $value) {
1006  if (is_array($value)) {
1007  $key = rtrim($key, '.');
1008  $parameters[$key] = [];
1009  $this->‪parseAdditionalGetParameters($parameters[$key], $value);
1010  } else {
1011  $parameters[$key] = $value;
1012  }
1013  }
1014  }
1015 
1021  protected function ‪main(ServerRequestInterface $request): void
1022  {
1023  $body = '';
1024  // Begin edit
1025  if (is_array($this->editconf)) {
1026  $this->formResultCompiler = GeneralUtility::makeInstance(FormResultCompiler::class);
1027 
1028  // Creating the editing form, wrap it with buttons, document selector etc.
1029  $editForm = $this->‪makeEditForm();
1030  if ($editForm) {
1031  $this->firstEl = reset($this->elementsData);
1032  // Checking if the currently open document is stored in the list of "open documents" - if not, add it:
1033  if (($this->docDat[1] !== $this->storeUrlMd5 || !isset($this->docHandler[$this->storeUrlMd5]))
1034  && !$this->dontStoreDocumentRef
1035  ) {
1036  $this->docHandler[‪$this->storeUrlMd5] = [
1041  ];
1042  $this->‪getBackendUser()->‪pushModuleData('FormEngine', [$this->docHandler, $this->storeUrlMd5]);
1043  ‪BackendUtility::setUpdateSignal('OpendocsController::updateNumber', count($this->docHandler));
1044  }
1045  $body = $this->formResultCompiler->addCssFiles();
1046  $body .= $this->‪compileForm($editForm);
1047  $body .= $this->formResultCompiler->printNeededJSFunctions();
1048  $body .= '</form>';
1049  }
1050  }
1051  // Access check...
1052  // The page will show only if there is a valid page and if this page may be viewed by the user
1053  $this->pageinfo = ‪BackendUtility::readPageAccess($this->viewId, $this->perms_clause);
1054  if ($this->pageinfo) {
1055  $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageinfo);
1056  }
1057  // Setting up the buttons and markers for doc header
1058  $this->‪getButtons($request);
1059 
1060  // Create language switch options if the record is already persisted
1061  if ($this->isSavedRecord) {
1062  $this->‪languageSwitch(
1063  (string)($this->firstEl['table'] ?? ''),
1064  (int)($this->firstEl['uid'] ?? 0),
1065  isset($this->firstEl['pid']) ? (int)$this->firstEl['pid'] : null
1066  );
1067  }
1068  $this->moduleTemplate->setContent($body);
1069  }
1070 
1076  protected function ‪makeEditForm(): string
1077  {
1078  // Initialize variables
1079  $this->elementsData = [];
1080  $this->errorC = 0;
1081  $this->newC = 0;
1082  $editForm = '';
1083  $beUser = $this->‪getBackendUser();
1084  // Traverse the GPvar edit array tables
1085  foreach ($this->editconf as $table => $conf) {
1086  if (is_array($conf) && ‪$GLOBALS['TCA'][$table] && $beUser->check('tables_modify', $table)) {
1087  // Traverse the keys/comments of each table (keys can be a comma list of uids)
1088  foreach ($conf as $cKey => $command) {
1089  if ($command === 'edit' || $command === 'new') {
1090  // Get the ids:
1091  $ids = ‪GeneralUtility::trimExplode(',', $cKey, true);
1092  // Traverse the ids:
1093  foreach ($ids as $theUid) {
1094  // Don't save this document title in the document selector if the document is new.
1095  if ($command === 'new') {
1096  $this->dontStoreDocumentRef = 1;
1097  }
1098 
1099  try {
1100  $formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class);
1101  $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
1102  $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class);
1103 
1104  // Reset viewId - it should hold data of last entry only
1105  $this->viewId = 0;
1106  $this->viewId_addParams = '';
1107 
1108  $formDataCompilerInput = [
1109  'tableName' => $table,
1110  'vanillaUid' => (int)$theUid,
1111  'command' => $command,
1112  'returnUrl' => $this->R_URI,
1113  ];
1114  if (is_array($this->overrideVals) && is_array($this->overrideVals[$table])) {
1115  $formDataCompilerInput['overrideValues'] = $this->overrideVals[$table];
1116  }
1117  if (!empty($this->defVals) && is_array($this->defVals)) {
1118  $formDataCompilerInput['defaultValues'] = ‪$this->defVals;
1119  }
1120 
1121  $formData = $formDataCompiler->compile($formDataCompilerInput);
1122 
1123  // Set this->viewId if possible
1124  if ($command === 'new'
1125  && $table !== 'pages'
1126  && !empty($formData['parentPageRow']['uid'])
1127  ) {
1128  $this->viewId = $formData['parentPageRow']['uid'];
1129  } else {
1130  if ($table === 'pages') {
1131  $this->viewId = $formData['databaseRow']['uid'];
1132  } elseif (!empty($formData['parentPageRow']['uid'])) {
1133  $this->viewId = $formData['parentPageRow']['uid'];
1134  // Adding "&L=xx" if the record being edited has a languageField with a value larger than zero!
1135  if (!empty($formData['processedTca']['ctrl']['languageField'])
1136  && is_array($formData['databaseRow'][$formData['processedTca']['ctrl']['languageField']])
1137  && $formData['databaseRow'][$formData['processedTca']['ctrl']['languageField']][0] > 0
1138  ) {
1139  $this->viewId_addParams = '&L=' . $formData['databaseRow'][$formData['processedTca']['ctrl']['languageField']][0];
1140  }
1141  }
1142  }
1143 
1144  // Determine if delete button can be shown
1145  $deleteAccess = false;
1146  if (
1147  $command === 'edit'
1148  || $command === 'new'
1149  ) {
1150  $permission = $formData['userPermissionOnPage'];
1151  if ($formData['tableName'] === 'pages') {
1152  $deleteAccess = $permission & ‪Permission::PAGE_DELETE ? true : false;
1153  } else {
1154  $deleteAccess = $permission & ‪Permission::CONTENT_EDIT ? true : false;
1155  }
1156  }
1157 
1158  // Display "is-locked" message
1159  if ($command === 'edit') {
1160  $lockInfo = ‪BackendUtility::isRecordLocked($table, $formData['databaseRow']['uid']);
1161  if ($lockInfo) {
1162  $flashMessage = GeneralUtility::makeInstance(
1163  FlashMessage::class,
1164  $lockInfo['msg'],
1165  '',
1167  );
1168  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
1169  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
1170  $defaultFlashMessageQueue->enqueue($flashMessage);
1171  }
1172  }
1173 
1174  // Record title
1175  if (!$this->storeTitle) {
1176  $this->storeTitle = htmlspecialchars($this->recTitle ?: ($formData['recordTitle'] ?? ''));
1177  }
1178 
1179  $this->elementsData[] = [
1180  'table' => $table,
1181  'uid' => $formData['databaseRow']['uid'],
1182  'pid' => $formData['databaseRow']['pid'],
1183  'cmd' => $command,
1184  'deleteAccess' => $deleteAccess
1185  ];
1186 
1187  if ($command !== 'new') {
1188  ‪BackendUtility::lockRecords($table, $formData['databaseRow']['uid'], $table === 'tt_content' ? $formData['databaseRow']['pid'] : 0);
1189  }
1190 
1191  // Set list if only specific fields should be rendered. This will trigger
1192  // ListOfFieldsContainer instead of FullRecordContainer in OuterWrapContainer
1193  if ($this->columnsOnly) {
1194  if (is_array($this->columnsOnly)) {
1195  $formData['fieldListToRender'] = $this->columnsOnly[$table];
1196  } else {
1197  $formData['fieldListToRender'] = ‪$this->columnsOnly;
1198  }
1199  }
1200 
1201  $formData['renderType'] = 'outerWrapContainer';
1202  $formResult = $nodeFactory->create($formData)->render();
1203 
1204  $html = $formResult['html'];
1205 
1206  $formResult['html'] = '';
1207  $formResult['doSaveFieldName'] = 'doSave';
1208 
1209  // @todo: Put all the stuff into FormEngine as final "compiler" class
1210  // @todo: This is done here for now to not rewrite addCssFiles()
1211  // @todo: and printNeededJSFunctions() now
1212  $this->formResultCompiler->mergeResult($formResult);
1213 
1214  // Seems the pid is set as hidden field (again) at end?!
1215  if ($command === 'new') {
1216  // @todo: looks ugly
1217  $html .= LF
1218  . '<input type="hidden"'
1219  . ' name="data[' . htmlspecialchars($table) . '][' . htmlspecialchars($formData['databaseRow']['uid']) . '][pid]"'
1220  . ' value="' . (int)$formData['databaseRow']['pid'] . '" />';
1221  $this->newC++;
1222  }
1223 
1224  $editForm .= $html;
1225  } catch (AccessDeniedException $e) {
1226  $this->errorC++;
1227  // Try to fetch error message from "recordInternals" be user object
1228  // @todo: This construct should be logged and localized and de-uglified
1229  $message = (!empty($beUser->errorMsg)) ? $beUser->errorMsg : $message = $e->getMessage() . ' ' . $e->getCode();
1230  $title = $this->‪getLanguageService()
1231  ->‪sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.noEditPermission');
1232  $editForm .= $this->‪getInfobox($message, $title);
1234  $editForm .= $this->‪getInfobox($e->getMessage());
1235  }
1236  } // End of for each uid
1237  }
1238  }
1239  }
1240  }
1241  return $editForm;
1242  }
1243 
1251  protected function ‪getInfobox(string $message, ?string $title = null): string
1252  {
1253  return '<div class="callout callout-danger">' .
1254  '<div class="media">' .
1255  '<div class="media-left">' .
1256  '<span class="fa-stack fa-lg callout-icon">' .
1257  '<i class="fa fa-circle fa-stack-2x"></i>' .
1258  '<i class="fa fa-times fa-stack-1x"></i>' .
1259  '</span>' .
1260  '</div>' .
1261  '<div class="media-body">' .
1262  ($title ? '<h4 class="callout-title">' . htmlspecialchars($title) . '</h4>' : '') .
1263  '<div class="callout-body">' . htmlspecialchars($message) . '</div>' .
1264  '</div>' .
1265  '</div>' .
1266  '</div>';
1267  }
1268 
1274  protected function ‪getButtons(ServerRequestInterface $request): void
1275  {
1276  $record = ‪BackendUtility::getRecord($this->firstEl['table'], $this->firstEl['uid']);
1277  $TCActrl = ‪$GLOBALS['TCA'][$this->firstEl['table']]['ctrl'];
1278 
1279  $this->‪setIsSavedRecord();
1280 
1281  $sysLanguageUid = 0;
1282  if (
1283  $this->isSavedRecord
1284  && isset($TCActrl['languageField'], $record[$TCActrl['languageField']])
1285  ) {
1286  $sysLanguageUid = (int)$record[$TCActrl['languageField']];
1287  } elseif (isset($this->defVals['sys_language_uid'])) {
1288  $sysLanguageUid = (int)$this->defVals['sys_language_uid'];
1289  }
1290 
1291  $l18nParent = isset($TCActrl['transOrigPointerField'], $record[$TCActrl['transOrigPointerField']])
1292  ? (int)$record[$TCActrl['transOrigPointerField']]
1293  : 0;
1294 
1295  $this->‪setIsPageInFreeTranslationMode($record, $sysLanguageUid);
1297  $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
1298 
1300 
1301  // Show buttons when table is not read-only
1302  if (
1303  !$this->errorC
1304  && !‪$GLOBALS['TCA'][$this->firstEl['table']]['ctrl']['readOnly']
1305  ) {
1308  if ($this->firstEl['cmd'] !== 'new') {
1310  $buttonBar,
1312  4,
1313  $sysLanguageUid,
1314  $l18nParent
1315  );
1317  $buttonBar,
1319  5,
1320  $sysLanguageUid,
1321  $l18nParent
1322  );
1323  }
1327  }
1328 
1332  }
1333 
1337  protected function ‪setIsSavedRecord()
1338  {
1339  if (!is_bool($this->isSavedRecord)) {
1340  $this->isSavedRecord = (
1341  $this->firstEl['cmd'] !== 'new'
1342  && ‪MathUtility::canBeInterpretedAsInteger($this->firstEl['uid'])
1343  );
1344  }
1345  }
1346 
1352  protected function ‪isInconsistentLanguageHandlingAllowed(): bool
1353  {
1354  $allowInconsistentLanguageHandling = ‪BackendUtility::getPagesTSconfig(
1355  $this->pageinfo['uid']
1356  )['mod']['web_layout']['allowInconsistentLanguageHandling'];
1357 
1358  return $allowInconsistentLanguageHandling['value'] === '1';
1359  }
1360 
1367  protected function ‪setIsPageInFreeTranslationMode($record, int $sysLanguageUid)
1368  {
1369  if ($this->firstEl['table'] === 'tt_content') {
1370  if (!$this->isSavedRecord) {
1371  $this->isPageInFreeTranslationMode = $this->‪getFreeTranslationMode(
1372  (int)$this->pageinfo['uid'],
1373  (int)$this->defVals['colPos'],
1374  $sysLanguageUid
1375  );
1376  } else {
1377  $this->isPageInFreeTranslationMode = $this->‪getFreeTranslationMode(
1378  (int)$this->pageinfo['uid'],
1379  (int)$record['colPos'],
1380  $sysLanguageUid
1381  );
1382  }
1383  }
1384  }
1385 
1394  protected function ‪getFreeTranslationMode(int $page, int $column, int $language): bool
1395  {
1396  $freeTranslationMode = false;
1397 
1398  if (
1399  $this->‪getConnectedContentElementTranslationsCount($page, $column, $language) === 0
1400  && $this->‪getStandAloneContentElementTranslationsCount($page, $column, $language) >= 0
1401  ) {
1402  $freeTranslationMode = true;
1403  }
1404 
1405  return $freeTranslationMode;
1406  }
1407 
1415  protected function ‪registerCloseButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
1416  {
1417  $closeButton = $buttonBar->makeLinkButton()
1418  ->setHref('#')
1419  ->setClasses('t3js-editform-close')
1420  ->setTitle($this->‪getLanguageService()->sL(
1421  'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.closeDoc'
1422  ))
1423  ->setShowLabelText(true)
1424  ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1425  'actions-close',
1427  ));
1428 
1429  $buttonBar->addButton($closeButton, $position, $group);
1430  }
1431 
1439  protected function ‪registerSaveButtonToButtonBar(‪ButtonBar $buttonBar, string $position, int $group)
1440  {
1441  $saveButton = $buttonBar->‪makeInputButton()
1442  ->‪setForm('EditDocumentController')
1443  ->‪setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-save', ‪Icon::SIZE_SMALL))
1444  ->setName('_savedok')
1445  ->setShowLabelText(true)
1446  ->setTitle($this->‪getLanguageService()->sL(
1447  'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.saveDoc'
1448  ))
1449  ->setValue('1');
1450 
1451  $buttonBar->‪addButton($saveButton, $position, $group);
1452  }
1453 
1461  protected function ‪registerViewButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
1462  {
1463  if (
1464  $this->viewId // Pid to show the record
1465  && !$this->noView // Passed parameter
1466  && !empty($this->firstEl['table']) // No table
1467 
1468  // @TODO: TsConfig option should change to viewDoc
1469  && $this->‪getTsConfigOption($this->firstEl['table'], 'saveDocView')
1470  ) {
1471  $classNames = 't3js-editform-view';
1472 
1473  $pagesTSconfig = ‪BackendUtility::getPagesTSconfig($this->pageinfo['uid']);
1474 
1475  if (isset($pagesTSconfig['TCEMAIN.']['preview.']['disableButtonForDokType'])) {
1476  $excludeDokTypes = ‪GeneralUtility::intExplode(
1477  ',',
1478  $pagesTSconfig['TCEMAIN.']['preview.']['disableButtonForDokType'],
1479  true
1480  );
1481  } else {
1482  // exclude sysfolders, spacers and recycler by default
1483  $excludeDokTypes = [
1487  ];
1488  }
1489 
1490  if (
1491  !in_array((int)$this->pageinfo['doktype'], $excludeDokTypes, true)
1492  || isset($pagesTSconfig['TCEMAIN.']['preview.'][$this->firstEl['table'] . '.']['previewPageId'])
1493  ) {
1494  $previewPageId = $this->‪getPreviewPageId();
1495  try {
1496  $previewUrl = ‪BackendUtility::getPreviewUrl(
1497  $previewPageId,
1498  '',
1499  ‪BackendUtility::BEgetRootLine($previewPageId),
1501  $this->viewUrl,
1502  $this->‪getPreviewUrlParameters($previewPageId)
1503  );
1504 
1505  $viewButton = $buttonBar->makeLinkButton()
1506  ->setHref($previewUrl)
1507  ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1508  'actions-view',
1510  ))
1511  ->setShowLabelText(true)
1512  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.viewDoc'));
1513 
1514  if (!$this->isSavedRecord) {
1515  if ($this->firstEl['table'] === 'pages') {
1516  $viewButton->setDataAttributes(['is-new' => '']);
1517  }
1518  }
1519 
1520  if ($classNames !== '') {
1521  $viewButton->setClasses($classNames);
1522  }
1523 
1524  $buttonBar->addButton($viewButton, $position, $group);
1525  } catch (UnableToLinkToPageException $e) {
1526  // Do not add any button
1527  }
1528  }
1529  }
1530  }
1531 
1541  protected function ‪registerNewButtonToButtonBar(
1542  ButtonBar $buttonBar,
1543  string $position,
1544  int $group,
1545  int $sysLanguageUid,
1546  int $l18nParent
1547  ) {
1548  if (
1549  $this->firstEl['table'] !== 'sys_file_metadata'
1550  && !empty($this->firstEl['table'])
1551  && (
1552  (
1553  (
1555  || $this->isPageInFreeTranslationMode
1556  )
1557  && $this->firstEl['table'] === 'tt_content'
1558  )
1559  || (
1560  $this->firstEl['table'] !== 'tt_content'
1561  && (
1562  $sysLanguageUid === 0
1563  || $l18nParent === 0
1564  )
1565  )
1566  )
1567  && $this->‪getTsConfigOption($this->firstEl['table'], 'saveDocNew')
1568  ) {
1569  $classNames = 't3js-editform-new';
1570 
1571  $newButton = $buttonBar->makeLinkButton()
1572  ->setHref('#')
1573  ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1574  'actions-add',
1576  ))
1577  ->setShowLabelText(true)
1578  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.newDoc'));
1579 
1580  if (!$this->isSavedRecord) {
1581  $newButton->setDataAttributes(['is-new' => '']);
1582  }
1583 
1584  if ($classNames !== '') {
1585  $newButton->setClasses($classNames);
1586  }
1587 
1588  $buttonBar->addButton($newButton, $position, $group);
1589  }
1590  }
1591 
1601  protected function ‪registerDuplicationButtonToButtonBar(
1602  ButtonBar $buttonBar,
1603  string $position,
1604  int $group,
1605  int $sysLanguageUid,
1606  int $l18nParent
1607  ) {
1608  if (
1609  $this->firstEl['table'] !== 'sys_file_metadata'
1610  && !empty($this->firstEl['table'])
1611  && (
1612  (
1613  (
1615  || $this->isPageInFreeTranslationMode
1616  )
1617  && $this->firstEl['table'] === 'tt_content'
1618  )
1619  || (
1620  $this->firstEl['table'] !== 'tt_content'
1621  && (
1622  $sysLanguageUid === 0
1623  || $l18nParent === 0
1624  )
1625  )
1626  )
1627  && $this->‪getTsConfigOption($this->firstEl['table'], 'showDuplicate')
1628  ) {
1629  $classNames = 't3js-editform-duplicate';
1630 
1631  $duplicateButton = $buttonBar->makeLinkButton()
1632  ->setHref('#')
1633  ->setShowLabelText(true)
1634  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.duplicateDoc'))
1635  ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1636  'actions-document-duplicates-select',
1638  ));
1639 
1640  if (!$this->isSavedRecord) {
1641  $duplicateButton->setDataAttributes(['is-new' => '']);
1642  }
1643 
1644  if ($classNames !== '') {
1645  $duplicateButton->setClasses($classNames);
1646  }
1647 
1648  $buttonBar->addButton($duplicateButton, $position, $group);
1649  }
1650  }
1651 
1659  protected function ‪registerDeleteButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
1660  {
1661  if (
1662  $this->firstEl['deleteAccess']
1663  && !$this->‪getDisableDelete()
1664  && !$this->‪isRecordCurrentBackendUser()
1665  && $this->isSavedRecord
1666  && count($this->elementsData) === 1
1667  ) {
1668  $classNames = 't3js-editform-delete-record';
1670  if ($this->firstEl['table'] === 'pages') {
1671  parse_str((string)parse_url(‪$returnUrl, PHP_URL_QUERY), $queryParams);
1672  if (
1673  isset($queryParams['route'], $queryParams['id'])
1674  && (string)$this->firstEl['uid'] === (string)$queryParams['id']
1675  ) {
1676  // TODO: Use the page's pid instead of 0, this requires a clean API to manipulate the page
1677  // tree from the outside to be able to mark the pid as active
1678  ‪$returnUrl = (string)$this->uriBuilder->buildUriFromRoutePath($queryParams['route'], ['id' => 0]);
1679  }
1680  }
1681 
1683  $referenceIndex = GeneralUtility::makeInstance(ReferenceIndex::class);
1684  $numberOfReferences = $referenceIndex->getNumberOfReferencedRecords(
1685  $this->firstEl['table'],
1686  (int)$this->firstEl['uid']
1687  );
1688 
1689  $referenceCountMessage = ‪BackendUtility::referenceCount(
1690  $this->firstEl['table'],
1691  (string)(int)$this->firstEl['uid'],
1692  $this->‪getLanguageService()->sL(
1693  'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.referencesToRecord'
1694  ),
1695  (string)$numberOfReferences
1696  );
1697  $translationCountMessage = ‪BackendUtility::translationCount(
1698  $this->firstEl['table'],
1699  (string)(int)$this->firstEl['uid'],
1700  $this->‪getLanguageService()->sL(
1701  'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.translationsOfRecord'
1702  )
1703  );
1704 
1705  $deleteUrl = (string)$this->uriBuilder->buildUriFromRoute('tce_db', [
1706  'cmd' => [
1707  $this->firstEl['table'] => [
1708  $this->firstEl['uid'] => [
1709  'delete' => '1'
1710  ]
1711  ]
1712  ],
1713  'redirect' => $this->retUrl
1714  ]);
1715 
1716  $deleteButton = $buttonBar->makeLinkButton()
1717  ->setClasses($classNames)
1718  ->setDataAttributes([
1719  'return-url' => ‪$returnUrl,
1720  'uid' => $this->firstEl['uid'],
1721  'table' => $this->firstEl['table'],
1722  'reference-count-message' => $referenceCountMessage,
1723  'translation-count-message' => $translationCountMessage
1724  ])
1725  ->setHref($deleteUrl)
1726  ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1727  'actions-edit-delete',
1729  ))
1730  ->setShowLabelText(true)
1731  ->setTitle($this->‪getLanguageService()->‪getLL('deleteItem'));
1732 
1733  $buttonBar->addButton($deleteButton, $position, $group);
1734  }
1735  }
1736 
1744  protected function ‪registerHistoryButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
1745  {
1746  if (
1747  count($this->elementsData) === 1
1748  && !empty($this->firstEl['table'])
1749  && $this->‪getTsConfigOption($this->firstEl['table'], 'showHistory')
1750  ) {
1751  $historyUrl = (string)$this->uriBuilder->buildUriFromRoute('record_history', [
1752  'element' => $this->firstEl['table'] . ':' . $this->firstEl['uid'],
1753  'returnUrl' => $this->R_URI,
1754  ]);
1755  $historyButton = $buttonBar->makeLinkButton()
1756  ->setHref($historyUrl)
1757  ->setTitle('Open history of this record')
1758  ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1759  'actions-document-history-open',
1761  ));
1762 
1763  $buttonBar->addButton($historyButton, $position, $group);
1764  }
1765  }
1766 
1774  protected function ‪registerColumnsOnlyButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
1775  {
1776  if (
1777  $this->columnsOnly
1778  && count($this->elementsData) === 1
1779  ) {
1780  $columnsOnlyButton = $buttonBar->makeLinkButton()
1781  ->setHref($this->R_URI . '&columnsOnly=')
1782  ->setTitle($this->‪getLanguageService()->getLL('editWholeRecord'))
1783  ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
1784  'actions-open',
1786  ));
1787 
1788  $buttonBar->addButton($columnsOnlyButton, $position, $group);
1789  }
1790  }
1791 
1799  protected function ‪registerOpenInNewWindowButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
1800  {
1801  $closeUrl = $this->‪getCloseUrl();
1802  if ($this->returnUrl !== $closeUrl) {
1803  $requestUri = GeneralUtility::linkThisScript([
1804  'returnUrl' => $closeUrl,
1805  ]);
1806  $aOnClick = 'vHWin=window.open('
1807  . GeneralUtility::quoteJSvalue($requestUri) . ','
1808  . GeneralUtility::quoteJSvalue(md5($this->R_URI))
1809  . ',\'width=670,height=500,status=0,menubar=0,scrollbars=1,resizable=1\');vHWin.focus();return false;';
1810 
1811  $openInNewWindowButton = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()
1812  ->makeLinkButton()
1813  ->setHref('#')
1814  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.openInNewWindow'))
1815  ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-window-open', ‪Icon::SIZE_SMALL))
1816  ->setOnClick($aOnClick);
1817 
1818  $buttonBar->addButton($openInNewWindowButton, $position, $group);
1819  }
1820  }
1821 
1829  protected function ‪registerShortcutButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
1830  {
1831  if ($this->returnUrl !== $this->‪getCloseUrl()) {
1832  $shortCutButton = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar()->makeShortcutButton();
1833  $shortCutButton->setModuleName('xMOD_alt_doc.php')
1834  ->setGetVariables([
1835  'returnUrl',
1836  'edit',
1837  'defVals',
1838  'overrideVals',
1839  'columnsOnly',
1840  'returnNewPageId',
1841  'noView']);
1842 
1843  $buttonBar->addButton($shortCutButton, $position, $group);
1844  }
1845  }
1846 
1854  protected function ‪registerCshButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
1855  {
1856  $cshButton = $buttonBar->makeHelpButton()->setModuleName('xMOD_csh_corebe')->setFieldName('TCEforms');
1857 
1858  $buttonBar->addButton($cshButton, $position, $group);
1859  }
1860 
1869  protected function ‪getConnectedContentElementTranslationsCount(int $page, int $column, int $language): int
1870  {
1871  $queryBuilder = $this->‪getQueryBuilderForTranslationMode($page, $column, $language);
1872 
1873  return (int)$queryBuilder
1874  ->andWhere(
1875  $queryBuilder->expr()->gt(
1876  ‪$GLOBALS['TCA']['tt_content']['ctrl']['transOrigPointerField'],
1877  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
1878  )
1879  )
1880  ->execute()
1881  ->fetchColumn(0);
1882  }
1883 
1892  protected function ‪getStandAloneContentElementTranslationsCount(int $page, int $column, int $language): int
1893  {
1894  $queryBuilder = $this->‪getQueryBuilderForTranslationMode($page, $column, $language);
1895 
1896  return (int)$queryBuilder
1897  ->andWhere(
1898  $queryBuilder->expr()->eq(
1899  ‪$GLOBALS['TCA']['tt_content']['ctrl']['transOrigPointerField'],
1900  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
1901  )
1902  )
1903  ->execute()
1904  ->fetchColumn(0);
1905  }
1906 
1915  protected function ‪getQueryBuilderForTranslationMode(int $page, int $column, int $language): QueryBuilder
1916  {
1917  $languageField = ‪$GLOBALS['TCA']['tt_content']['ctrl']['languageField'];
1918 
1919  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
1920  ->getQueryBuilderForTable('tt_content');
1921 
1922  $queryBuilder->getRestrictions()
1923  ->removeAll()
1924  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
1925  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->‪getBackendUser()->workspace));
1926 
1927  return $queryBuilder
1928  ->count('uid')
1929  ->from('tt_content')
1930  ->where(
1931  $queryBuilder->expr()->eq(
1932  'pid',
1933  $queryBuilder->createNamedParameter($page, \PDO::PARAM_INT)
1934  ),
1935  $queryBuilder->expr()->eq(
1936  $languageField,
1937  $queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
1938  ),
1939  $queryBuilder->expr()->eq(
1940  'colPos',
1941  $queryBuilder->createNamedParameter($column, \PDO::PARAM_INT)
1942  )
1943  );
1944  }
1945 
1952  protected function ‪compileForm(string $editForm): string
1953  {
1954  $formContent = '
1955  <form
1956  action="' . htmlspecialchars($this->R_URI) . '"
1957  method="post"
1958  enctype="multipart/form-data"
1959  name="editform"
1960  id="EditDocumentController"
1961  >
1962  ' . $editForm . '
1963  <input type="hidden" name="returnUrl" value="' . htmlspecialchars($this->retUrl) . '" />
1964  <input type="hidden" name="viewUrl" value="' . htmlspecialchars($this->viewUrl) . '" />
1965  <input type="hidden" name="popViewId" value="' . htmlspecialchars((string)$this->viewId) . '" />
1966  <input type="hidden" name="closeDoc" value="0" />
1967  <input type="hidden" name="doSave" value="0" />
1968  <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" />
1969  <input type="hidden" name="_scrollPosition" value="" />';
1970  if ($this->returnNewPageId) {
1971  $formContent .= '<input type="hidden" name="returnNewPageId" value="1" />';
1972  }
1973  if ($this->viewId_addParams) {
1974  $formContent .= '<input type="hidden" name="popViewId_addParams" value="' . htmlspecialchars($this->viewId_addParams) . '" />';
1975  }
1976  return $formContent;
1977  }
1985  protected function ‪getDisableDelete(): bool
1986  {
1987  $disableDelete = false;
1988  if ($this->firstEl['table'] === 'sys_file_metadata') {
1989  $row = ‪BackendUtility::getRecord('sys_file_metadata', $this->firstEl['uid'], 'sys_language_uid');
1990  $languageUid = $row['sys_language_uid'];
1991  if ($languageUid === 0) {
1992  $disableDelete = true;
1993  }
1994  } else {
1995  $disableDelete = (bool)$this->‪getTsConfigOption($this->firstEl['table'] ?? '', 'disableDelete');
1996  }
1997  return $disableDelete;
1998  }
1999 
2005  protected function ‪isRecordCurrentBackendUser(): bool
2006  {
2007  $backendUser = $this->‪getBackendUser();
2008 
2009  return $this->firstEl['table'] === 'be_users'
2010  && (int)($this->firstEl['uid'] ?? 0) === (int)$backendUser->user[$backendUser->userid_column];
2011  }
2012 
2019  protected function ‪getCloseUrl(): string
2020  {
2021  $closeUrl = GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Public/Html/Close.html');
2022  return ‪PathUtility::getAbsoluteWebPath($closeUrl);
2023  }
2024 
2025  /***************************
2026  *
2027  * Localization stuff
2028  *
2029  ***************************/
2038  protected function ‪languageSwitch(string $table, int $uid, $pid = null)
2039  {
2040  $backendUser = $this->‪getBackendUser();
2041  $languageField = ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'];
2042  $transOrigPointerField = ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
2043  // Table editable and activated for languages?
2044  if ($backendUser->check('tables_modify', $table)
2045  && $languageField
2046  && $transOrigPointerField
2047  ) {
2048  if ($pid === null) {
2049  $row = ‪BackendUtility::getRecord($table, $uid, 'pid');
2050  $pid = $row['pid'];
2051  }
2052  // Get all available languages for the page
2053  // If editing a page, the translations of the current UID need to be fetched
2054  if ($table === 'pages') {
2055  $row = ‪BackendUtility::getRecord($table, $uid, ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']);
2056  // Ensure the check is always done against the default language page
2057  $availableLanguages = $this->‪getLanguages(
2058  (int)$row[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']] ?: $uid,
2059  $table
2060  );
2061  } else {
2062  $availableLanguages = $this->‪getLanguages((int)$pid, $table);
2063  }
2064  // Remove default language, if user does not have access. This is necessary, since
2065  // the default language is always added when fetching the system languages (#88504).
2066  if (isset($availableLanguages[0]) && !$this->‪getBackendUser()->checkLanguageAccess(0)) {
2067  unset($availableLanguages[0]);
2068  }
2069  // Page available in other languages than default language?
2070  if (count($availableLanguages) > 1) {
2071  $rowsByLang = [];
2072  $fetchFields = 'uid,' . $languageField . ',' . $transOrigPointerField;
2073  // Get record in current language
2074  $rowCurrent = ‪BackendUtility::getLiveVersionOfRecord($table, $uid, $fetchFields);
2075  if (!is_array($rowCurrent)) {
2076  $rowCurrent = ‪BackendUtility::getRecord($table, $uid, $fetchFields);
2077  }
2078  $currentLanguage = (int)$rowCurrent[$languageField];
2079  // Disabled for records with [all] language!
2080  if ($currentLanguage > -1) {
2081  // Get record in default language if needed
2082  if ($currentLanguage && $rowCurrent[$transOrigPointerField]) {
2084  $table,
2085  $rowCurrent[$transOrigPointerField],
2086  $fetchFields
2087  );
2088  if (!is_array($rowsByLang[0])) {
2089  $rowsByLang[0] = ‪BackendUtility::getRecord(
2090  $table,
2091  $rowCurrent[$transOrigPointerField],
2092  $fetchFields
2093  );
2094  }
2095  } else {
2096  $rowsByLang[$rowCurrent[$languageField]] = $rowCurrent;
2097  }
2098  // List of language id's that should not be added to the selector
2099  $noAddOption = [];
2100  if ($rowCurrent[$transOrigPointerField] || $currentLanguage === 0) {
2101  // Get record in other languages to see what's already available
2102 
2103  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
2104  ->getQueryBuilderForTable($table);
2105 
2106  $queryBuilder->getRestrictions()
2107  ->removeAll()
2108  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2109  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $backendUser->workspace));
2110 
2111  $result = $queryBuilder->select(...‪GeneralUtility::trimExplode(',', $fetchFields, true))
2112  ->from($table)
2113  ->where(
2114  $queryBuilder->expr()->eq(
2115  'pid',
2116  $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT)
2117  ),
2118  $queryBuilder->expr()->gt(
2119  $languageField,
2120  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
2121  ),
2122  $queryBuilder->expr()->eq(
2123  $transOrigPointerField,
2124  $queryBuilder->createNamedParameter($rowsByLang[0]['uid'], \PDO::PARAM_INT)
2125  )
2126  )
2127  ->execute();
2128 
2129  while ($row = $result->fetch()) {
2130  if ($backendUser->workspace !== 0 && ‪BackendUtility::isTableWorkspaceEnabled($table)) {
2131  $workspaceVersion = ‪BackendUtility::getWorkspaceVersionOfRecord($backendUser->workspace, $table, $row['uid'], 'uid,t3ver_state');
2132  if (!empty($workspaceVersion)) {
2133  $versionState = ‪VersionState::cast($workspaceVersion['t3ver_state']);
2134  if ($versionState->equals(‪VersionState::DELETE_PLACEHOLDER)) {
2135  // If a workspace delete placeholder exists for this translation: Mark
2136  // this language as "don't add to selector" and continue with next row,
2137  // otherwise an edit link to a delete placeholder would be created, which
2138  // does not make sense.
2139  $noAddOption[] = (int)$row[$languageField];
2140  continue;
2141  }
2142  }
2143  }
2144  $rowsByLang[$row[$languageField]] = $row;
2145  }
2146  }
2147  $languageMenu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
2148  $languageMenu->setIdentifier('_langSelector');
2149  foreach ($availableLanguages as $languageId => $language) {
2150  $selectorOptionLabel = $language['title'];
2151  // Create url for creating a localized record
2152  $addOption = true;
2153  $href = '';
2154  if (!isset($rowsByLang[$languageId])) {
2155  // Translation in this language does not exist
2156  $selectorOptionLabel .= ' [' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.new')) . ']';
2157  $redirectUrl = (string)$this->uriBuilder->buildUriFromRoute('record_edit', [
2158  'justLocalized' => $table . ':' . $rowsByLang[0]['uid'] . ':' . $languageId,
2159  'returnUrl' => $this->retUrl
2160  ]);
2161 
2162  if (array_key_exists(0, $rowsByLang)) {
2164  '&cmd[' . $table . '][' . $rowsByLang[0]['uid'] . '][localize]=' . $languageId,
2165  $redirectUrl
2166  );
2167  } else {
2168  $addOption = false;
2169  }
2170  } else {
2171  $params = [
2172  'edit[' . $table . '][' . $rowsByLang[$languageId]['uid'] . ']' => 'edit',
2173  'returnUrl' => ‪$this->retUrl
2174  ];
2175  if ($table === 'pages') {
2176  // Disallow manual adjustment of the language field for pages
2177  $params['overrideVals'] = [
2178  'pages' => [
2179  'sys_language_uid' => $languageId
2180  ]
2181  ];
2182  }
2183  $href = (string)$this->uriBuilder->buildUriFromRoute('record_edit', $params);
2184  }
2185  if ($addOption && !in_array($languageId, $noAddOption, true)) {
2186  $menuItem = $languageMenu->makeMenuItem()
2187  ->setTitle($selectorOptionLabel)
2188  ->setHref($href);
2189  if ($languageId === $currentLanguage) {
2190  $menuItem->setActive(true);
2191  }
2192  $languageMenu->addMenuItem($menuItem);
2193  }
2194  }
2195  $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($languageMenu);
2196  }
2197  }
2198  }
2199  }
2200 
2207  protected function ‪localizationRedirect(ServerRequestInterface $request): ?ResponseInterface
2208  {
2209  $justLocalized = $request->getQueryParams()['justLocalized'];
2210 
2211  if (empty($justLocalized)) {
2212  return null;
2213  }
2214 
2215  [$table, $origUid, $language] = explode(':', $justLocalized);
2216 
2217  if (‪$GLOBALS['TCA'][$table]
2218  && ‪$GLOBALS['TCA'][$table]['ctrl']['languageField']
2219  && ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']
2220  ) {
2221  $parsedBody = $request->getParsedBody();
2222  $queryParams = $request->getQueryParams();
2223 
2224  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
2225  $queryBuilder->getRestrictions()
2226  ->removeAll()
2227  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2228  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->‪getBackendUser()->workspace));
2229  $localizedRecord = $queryBuilder->select('uid')
2230  ->from($table)
2231  ->where(
2232  $queryBuilder->expr()->eq(
2233  ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'],
2234  $queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
2235  ),
2236  $queryBuilder->expr()->eq(
2237  ‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'],
2238  $queryBuilder->createNamedParameter($origUid, \PDO::PARAM_INT)
2239  )
2240  )
2241  ->execute()
2242  ->fetch();
2243  ‪$returnUrl = $parsedBody['returnUrl'] ?? $queryParams['returnUrl'] ?? '';
2244  if (is_array($localizedRecord)) {
2245  // Create redirect response to self to edit just created record
2246  return new ‪RedirectResponse(
2247  (string)$this->uriBuilder->buildUriFromRoute(
2248  'record_edit',
2249  [
2250  'edit[' . $table . '][' . $localizedRecord['uid'] . ']' => 'edit',
2251  'returnUrl' => GeneralUtility::sanitizeLocalUrl(‪$returnUrl)
2252  ]
2253  ),
2254  303
2255  );
2256  }
2257  }
2258  return null;
2259  }
2260 
2270  protected function ‪getLanguages(int $id, string $table): array
2271  {
2272  // This usually happens when a non-pages record is added after another, so we are fetching the proper page ID
2273  if ($id < 0 && $table !== 'pages') {
2274  $pageId = $this->pageinfo['uid'] ?? null;
2275  if ($pageId !== null) {
2276  $pageId = (int)$pageId;
2277  } else {
2278  $fullRecord = ‪BackendUtility::getRecord($table, abs($id));
2279  $pageId = (int)$fullRecord['pid'];
2280  }
2281  } else {
2282  if ($table === 'pages' && $id > 0) {
2283  $fullRecord = ‪BackendUtility::getRecordWSOL('pages', $id);
2284  $id = (int)($fullRecord['t3ver_oid'] ?: $fullRecord['uid']);
2285  }
2286  $pageId = $id;
2287  }
2288  // Fetch the current translations of this page, to only show the ones where there is a page translation
2289  $allLanguages = array_filter(
2290  GeneralUtility::makeInstance(TranslationConfigurationProvider::class)->getSystemLanguages($pageId),
2291  static function (array $language): bool {
2292  return (int)$language['uid'] !== -1;
2293  }
2294  );
2295  if ($table !== 'pages' && $id > 0) {
2296  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
2297  $queryBuilder->getRestrictions()->removeAll()
2298  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
2299  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->‪getBackendUser()->workspace));
2300  $statement = $queryBuilder->select('uid', ‪$GLOBALS['TCA']['pages']['ctrl']['languageField'])
2301  ->from('pages')
2302  ->where(
2303  $queryBuilder->expr()->eq(
2304  ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
2305  $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
2306  )
2307  )
2308  ->execute();
2309 
2310  $availableLanguages = [];
2311 
2312  if ($allLanguages[0] ?? false) {
2313  $availableLanguages = [
2314  0 => $allLanguages[0]
2315  ];
2316  }
2317 
2318  while ($row = $statement->fetch()) {
2319  $languageId = (int)$row[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']];
2320  if (isset($allLanguages[$languageId])) {
2321  $availableLanguages[$languageId] = $allLanguages[$languageId];
2322  }
2323  }
2324  return $availableLanguages;
2325  }
2326  return $allLanguages;
2327  }
2328 
2334  protected function ‪fixWSversioningInEditConf($mapArray = false): void
2335  {
2336  // Traverse the editConf array
2337  if (is_array($this->editconf)) {
2338  // Tables:
2339  foreach ($this->editconf as $table => $conf) {
2340  if (is_array($conf) && ‪$GLOBALS['TCA'][$table]) {
2341  // Traverse the keys/comments of each table (keys can be a comma list of uids)
2342  $newConf = [];
2343  foreach ($conf as $cKey => ‪$cmd) {
2344  if (‪$cmd === 'edit') {
2345  // Traverse the ids:
2346  $ids = ‪GeneralUtility::trimExplode(',', $cKey, true);
2347  foreach ($ids as $idKey => $theUid) {
2348  if (is_array($mapArray)) {
2349  if ($mapArray[$table][$theUid]) {
2350  $ids[$idKey] = $mapArray[$table][$theUid];
2351  }
2352  } else {
2353  // Default, look for versions in workspace for record:
2354  $calcPRec = $this->‪getRecordForEdit((string)$table, (int)$theUid);
2355  if (is_array($calcPRec)) {
2356  // Setting UID again if it had changed, eg. due to workspace versioning.
2357  $ids[$idKey] = $calcPRec['uid'];
2358  }
2359  }
2360  }
2361  // Add the possibly manipulated IDs to the new-build newConf array:
2362  $newConf[implode(',', $ids)] = ‪$cmd;
2363  } else {
2364  $newConf[$cKey] = ‪$cmd;
2365  }
2366  }
2367  // Store the new conf array:
2368  $this->editconf[$table] = $newConf;
2369  }
2370  }
2371  }
2372  }
2373 
2381  protected function ‪getRecordForEdit(string $table, int $theUid)
2382  {
2383  $tableSupportsVersioning = ‪BackendUtility::isTableWorkspaceEnabled($table);
2384  // Fetch requested record:
2385  $reqRecord = ‪BackendUtility::getRecord($table, $theUid, 'uid,pid' . ($tableSupportsVersioning ? ',t3ver_oid' : ''));
2386  if (is_array($reqRecord)) {
2387  // If workspace is OFFLINE:
2388  if ($this->‪getBackendUser()->workspace != 0) {
2389  // Check for versioning support of the table:
2390  if ($tableSupportsVersioning) {
2391  // If the record is already a version of "something" pass it by.
2392  if ($reqRecord['t3ver_oid'] > 0) {
2393  // (If it turns out not to be a version of the current workspace there will be trouble, but
2394  // that is handled inside DataHandler then and in the interface it would clearly be an error of
2395  // links if the user accesses such a scenario)
2396  return $reqRecord;
2397  }
2398  // The input record was online and an offline version must be found or made:
2399  // Look for version of this workspace:
2401  $this->‪getBackendUser()->workspace,
2402  $table,
2403  $reqRecord['uid'],
2404  'uid,pid,t3ver_oid'
2405  );
2406  return is_array($versionRec) ? $versionRec : $reqRecord;
2407  }
2408  // This means that editing cannot occur on this record because it was not supporting versioning
2409  // which is required inside an offline workspace.
2410  return false;
2411  }
2412  // In ONLINE workspace, just return the originally requested record:
2413  return $reqRecord;
2414  }
2415  // Return FALSE because the table/uid was not found anyway.
2416  return false;
2417  }
2418 
2423  protected function ‪compileStoreData(): void
2424  {
2425  // @todo: Refactor in TYPO3 v10: This GeneralUtility method fiddles with _GP()
2426  $this->storeArray = GeneralUtility::compileSelectedGetVarsFromArray(
2427  'edit,defVals,overrideVals,columnsOnly,noView',
2428  $this->R_URL_getvars
2429  );
2430  $this->storeUrl = ‪HttpUtility::buildQueryString($this->storeArray, '&');
2431  $this->storeUrlMd5 = md5($this->storeUrl);
2432  }
2433 
2441  protected function ‪getTsConfigOption(string $table, string $key): string
2442  {
2443  return \trim((string)(
2444  $this->‪getBackendUser()->getTSConfig()['options.'][$key . '.'][$table]
2445  ?? $this->‪getBackendUser()->getTSConfig()['options.'][$key]
2446  ?? ''
2447  ));
2448  }
2449 
2462  protected function ‪closeDocument($mode, ServerRequestInterface $request): ?ResponseInterface
2463  {
2464  $setupArr = [];
2465  $mode = (int)$mode;
2466  // If current document is found in docHandler,
2467  // then unset it, possibly unset it ALL and finally, write it to the session data
2468  if (isset($this->docHandler[$this->storeUrlMd5])) {
2469  // add the closing document to the recent documents
2470  $recentDocs = $this->‪getBackendUser()->‪getModuleData('opendocs::recent');
2471  if (!is_array($recentDocs)) {
2472  $recentDocs = [];
2473  }
2474  $closedDoc = $this->docHandler[‪$this->storeUrlMd5];
2475  $recentDocs = array_merge([$this->storeUrlMd5 => $closedDoc], $recentDocs);
2476  if (count($recentDocs) > 8) {
2477  $recentDocs = array_slice($recentDocs, 0, 8);
2478  }
2479  // remove it from the list of the open documents
2480  unset($this->docHandler[$this->storeUrlMd5]);
2481  if ($mode === self::DOCUMENT_CLOSE_MODE_CLEAR_ALL) {
2482  $recentDocs = array_merge($this->docHandler, $recentDocs);
2483  $this->docHandler = [];
2484  }
2485  $this->‪getBackendUser()->‪pushModuleData('opendocs::recent', $recentDocs);
2486  $this->‪getBackendUser()->‪pushModuleData('FormEngine', [$this->docHandler, $this->docDat[1]]);
2487  ‪BackendUtility::setUpdateSignal('OpendocsController::updateNumber', count($this->docHandler));
2488  }
2489  if ($mode === self::DOCUMENT_CLOSE_MODE_NO_REDIRECT) {
2490  return null;
2491  }
2492  // If ->returnEditConf is set, then add the current content of editconf to the ->retUrl variable: used by
2493  // other scripts, like wizard_add, to know which records was created or so...
2494  if ($this->returnEditConf && $this->retUrl != (string)$this->uriBuilder->buildUriFromRoute('dummy')) {
2495  $this->retUrl .= '&returnEditConf=' . rawurlencode((string)json_encode($this->editconf));
2496  }
2497  // If mode is NOT set (means 0) OR set to 1, then make a header location redirect to $this->retUrl
2498  if ($mode === self::DOCUMENT_CLOSE_MODE_DEFAULT || $mode === self::DOCUMENT_CLOSE_MODE_REDIRECT) {
2499  return new RedirectResponse($this->retUrl, 303);
2500  }
2501  if ($this->retUrl === '') {
2502  return null;
2503  }
2504  ‪$retUrl = (string)$this->returnUrl;
2505  if (is_array($this->docHandler) && !empty($this->docHandler)) {
2506  if (!empty($setupArr[2])) {
2507  $sParts = parse_url($request->getAttribute('normalizedParams')->getRequestUri());
2508  ‪$retUrl = $sParts['path'] . '?' . $setupArr[2] . '&returnUrl=' . rawurlencode(‪$retUrl);
2509  }
2510  }
2511  return new RedirectResponse(‪$retUrl, 303);
2512  }
2513 
2517  protected function ‪getBackendUser()
2518  {
2519  return ‪$GLOBALS['BE_USER'];
2520  }
2521 
2527  protected function ‪getLanguageService()
2528  {
2529  return ‪$GLOBALS['LANG'];
2530  }
2531 }
‪TYPO3\CMS\Core\DataHandling\DataHandler
Definition: DataHandler.php:84
‪TYPO3\CMS\Backend\Controller\EditDocumentController\registerShortcutButtonToButtonBar
‪registerShortcutButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
Definition: EditDocumentController.php:1788
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getPreviewUrlParameters
‪string getPreviewUrlParameters(int $previewPageId)
Definition: EditDocumentController.php:799
‪TYPO3\CMS\Backend\Template\Components\AbstractControl\setClasses
‪$this setClasses($classes)
Definition: AbstractControl.php:96
‪TYPO3\CMS\Core\Imaging\Icon\SIZE_SMALL
‪const SIZE_SMALL
Definition: Icon.php:30
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getLanguageService
‪TYPO3 CMS Core Localization LanguageService getLanguageService()
Definition: EditDocumentController.php:2486
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$columnsOnly
‪string null $columnsOnly
Definition: EditDocumentController.php:85
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$storeUrlMd5
‪string $storeUrlMd5
Definition: EditDocumentController.php:244
‪TYPO3\CMS\Backend\Form\FormResultCompiler
Definition: FormResultCompiler.php:30
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:24
‪TYPO3\CMS\Core\Localization\LanguageService\includeLLFile
‪array includeLLFile($fileRef, $setGlobal=null, $mergeLocalOntoDefault=null)
Definition: LanguageService.php:297
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_LEFT
‪const BUTTON_POSITION_LEFT
Definition: ButtonBar.php:36
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:74
‪TYPO3\CMS\Backend\Template\Components\ButtonBar
Definition: ButtonBar.php:32
‪TYPO3\CMS\Backend\Controller\EditDocumentController\canViewDoktype
‪bool canViewDoktype(array $currentPage)
Definition: EditDocumentController.php:939
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$perms_clause
‪string $perms_clause
Definition: EditDocumentController.php:189
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLinkToDataHandlerAction
‪static string getLinkToDataHandlerAction($parameters, $redirectUrl='')
Definition: BackendUtility.php:2539
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$returnUrl
‪string null $returnUrl
Definition: EditDocumentController.php:104
‪TYPO3\CMS\Backend\Template\Components\Buttons\AbstractButton\setIcon
‪$this setIcon(Icon $icon)
Definition: AbstractButton.php:94
‪TYPO3\CMS\Backend\Controller\EditDocumentController\registerOpenInNewWindowButtonToButtonBar
‪registerOpenInNewWindowButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
Definition: EditDocumentController.php:1758
‪TYPO3\CMS\Backend\Controller\EditDocumentController\isRecordCurrentBackendUser
‪bool isRecordCurrentBackendUser()
Definition: EditDocumentController.php:1964
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$mirror
‪array $mirror
Definition: EditDocumentController.php:147
‪TYPO3\CMS\Backend\Controller\EditDocumentController\mainAction
‪ResponseInterface mainAction(ServerRequestInterface $request)
Definition: EditDocumentController.php:360
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$moduleTemplate
‪ModuleTemplate $moduleTemplate
Definition: EditDocumentController.php:321
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getRecordForEdit
‪array false getRecordForEdit(string $table, int $theUid)
Definition: EditDocumentController.php:2340
‪TYPO3\CMS\Core\Imaging\Icon
Definition: Icon.php:26
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$elementsData
‪$elementsData
Definition: EditDocumentController.php:268
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$uc
‪array null $uc
Definition: EditDocumentController.php:161
‪TYPO3\CMS\Backend\Utility\BackendUtility\setUpdateSignal
‪static setUpdateSignal($set='', $params='')
Definition: BackendUtility.php:2798
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$recTitle
‪string $recTitle
Definition: EditDocumentController.php:179
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$data
‪$data
Definition: EditDocumentController.php:135
‪TYPO3\CMS\Core\Database\ReferenceIndex
Definition: ReferenceIndex.php:48
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$firstEl
‪array $firstEl
Definition: EditDocumentController.php:274
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getCloseUrl
‪string getCloseUrl()
Definition: EditDocumentController.php:1978
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getTsConfigOption
‪string getTsConfigOption(string $table, string $key)
Definition: EditDocumentController.php:2400
‪TYPO3\CMS\Backend\Controller\EditDocumentController\init
‪init(ServerRequestInterface $request)
Definition: EditDocumentController.php:720
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getConnectedContentElementTranslationsCount
‪int getConnectedContentElementTranslationsCount(int $page, int $column, int $language)
Definition: EditDocumentController.php:1828
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$R_URL_parts
‪array $R_URL_parts
Definition: EditDocumentController.php:201
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getPreviewPageId
‪int getPreviewPageId()
Definition: EditDocumentController.php:888
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$isPageInFreeTranslationMode
‪bool $isPageInFreeTranslationMode
Definition: EditDocumentController.php:333
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getDisableDelete
‪bool getDisableDelete()
Definition: EditDocumentController.php:1944
‪TYPO3\CMS\Backend\Controller\EditDocumentController\languageSwitch
‪languageSwitch(string $table, int $uid, $pid=null)
Definition: EditDocumentController.php:1997
‪TYPO3\CMS\Backend\Controller\EditDocumentController\addSlugFieldsToColumnsOnly
‪addSlugFieldsToColumnsOnly(array $queryParams)
Definition: EditDocumentController.php:454
‪TYPO3\CMS\Backend\Controller\EditDocumentController\DOCUMENT_CLOSE_MODE_REDIRECT
‪const DOCUMENT_CLOSE_MODE_REDIRECT
Definition: EditDocumentController.php:70
‪TYPO3\CMS\Backend\Utility\BackendUtility\lockRecords
‪static lockRecords($table='', $uid=0, $pid=0)
Definition: BackendUtility.php:2967
‪TYPO3\CMS\Backend\Controller\EditDocumentController\DOCUMENT_CLOSE_MODE_DEFAULT
‪const DOCUMENT_CLOSE_MODE_DEFAULT
Definition: EditDocumentController.php:68
‪TYPO3\CMS\Backend\Controller\EditDocumentController\__construct
‪__construct(EventDispatcherInterface $eventDispatcher)
Definition: EditDocumentController.php:343
‪TYPO3\CMS\Core\Versioning\VersionState\DELETE_PLACEHOLDER
‪const DELETE_PLACEHOLDER
Definition: VersionState.php:55
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$isSavedRecord
‪bool $isSavedRecord
Definition: EditDocumentController.php:327
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$previewData
‪array $previewData
Definition: EditDocumentController.php:315
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$docHandler
‪array $docHandler
Definition: EditDocumentController.php:259
‪TYPO3\CMS\Backend\Controller\EditDocumentController\isInconsistentLanguageHandlingAllowed
‪bool isInconsistentLanguageHandlingAllowed()
Definition: EditDocumentController.php:1311
‪TYPO3\CMS\Core\Localization\LanguageService\sL
‪string sL($input)
Definition: LanguageService.php:194
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$dontStoreDocumentRef
‪int $dontStoreDocumentRef
Definition: EditDocumentController.php:309
‪TYPO3\CMS\Backend\Controller\EditDocumentController\DOCUMENT_CLOSE_MODE_CLEAR_ALL
‪const DOCUMENT_CLOSE_MODE_CLEAR_ALL
Definition: EditDocumentController.php:71
‪TYPO3\CMS\Backend\Utility\BackendUtility\BEgetRootLine
‪static array BEgetRootLine($uid, $clause='', $workspaceOL=false, array $additionalFields=[])
Definition: BackendUtility.php:343
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPreviewUrl
‪static string getPreviewUrl( $pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', &$switchFocus=true)
Definition: BackendUtility.php:2403
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getLanguages
‪array getLanguages(int $id, string $table)
Definition: EditDocumentController.php:2229
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Backend\Template\Components\Buttons\Action\HelpButton\setFieldName
‪HelpButton setFieldName($fieldName)
Definition: HelpButton.php:85
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getQueryBuilderForTranslationMode
‪QueryBuilder getQueryBuilderForTranslationMode(int $page, int $column, int $language)
Definition: EditDocumentController.php:1874
‪TYPO3\CMS\Backend\Controller\EditDocumentController\registerSaveButtonToButtonBar
‪registerSaveButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
Definition: EditDocumentController.php:1398
‪TYPO3\CMS\Backend\Controller\EditDocumentController\compileForm
‪string compileForm(string $editForm)
Definition: EditDocumentController.php:1911
‪TYPO3\CMS\Backend\Template\ModuleTemplate
Definition: ModuleTemplate.php:43
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\makeInputButton
‪InputButton makeInputButton()
Definition: ButtonBar.php:101
‪TYPO3\CMS\Backend\Form\Exception\DatabaseRecordWorkspaceDeletePlaceholderException
Definition: DatabaseRecordWorkspaceDeletePlaceholderException.php:26
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:24
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\addButton
‪$this addButton(ButtonInterface $button, $buttonPosition=self::BUTTON_POSITION_LEFT, $buttonGroup=1)
Definition: ButtonBar.php:60
‪TYPO3\CMS\Backend\Controller\EditDocumentController\registerHistoryButtonToButtonBar
‪registerHistoryButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
Definition: EditDocumentController.php:1703
‪TYPO3\CMS\Backend\Controller\EditDocumentController\parseAdditionalGetParameters
‪parseAdditionalGetParameters(array &$parameters, array $typoScript)
Definition: EditDocumentController.php:962
‪TYPO3\CMS\Backend\Form\Utility\FormEngineUtility
Definition: FormEngineUtility.php:39
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:52
‪TYPO3\CMS\Backend\Utility\BackendUtility\isTableWorkspaceEnabled
‪static bool isTableWorkspaceEnabled($table)
Definition: BackendUtility.php:4021
‪TYPO3\CMS\Backend\Utility\BackendUtility\translationCount
‪static string translationCount($table, $ref, $msg='')
Definition: BackendUtility.php:3361
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$returnNewPageId
‪bool $returnNewPageId
Definition: EditDocumentController.php:154
‪TYPO3\CMS\Backend\Form\Utility\FormEngineUtility\updateInlineView
‪static updateInlineView(&$uc, $tce)
Definition: FormEngineUtility.php:147
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$viewId_addParams
‪string $viewId_addParams
Definition: EditDocumentController.php:299
‪TYPO3\CMS\Backend\Controller\EditDocumentController\registerViewButtonToButtonBar
‪registerViewButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
Definition: EditDocumentController.php:1420
‪TYPO3\CMS\Backend\Controller\Event\AfterFormEnginePageInitializedEvent
Definition: AfterFormEnginePageInitializedEvent.php:27
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:186
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:42
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$pageinfo
‪array $pageinfo
Definition: EditDocumentController.php:218
‪TYPO3\CMS\Core\Messaging\AbstractMessage\WARNING
‪const WARNING
Definition: AbstractMessage.php:30
‪TYPO3\CMS\Backend\Controller\EditDocumentController\registerCloseButtonToButtonBar
‪registerCloseButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
Definition: EditDocumentController.php:1374
‪TYPO3\CMS\Backend\Controller\EditDocumentController\compileStoreData
‪compileStoreData()
Definition: EditDocumentController.php:2382
‪TYPO3\CMS\Backend\Controller\EditDocumentController
Definition: EditDocumentController.php:67
‪TYPO3\CMS\Backend\Controller\EditDocumentController\resolvePreviewRecordId
‪int resolvePreviewRecordId(string $table, array $recordArray, array $previewConfiguration)
Definition: EditDocumentController.php:853
‪TYPO3\CMS\Backend\Controller\EditDocumentController\generatePreviewCode
‪string generatePreviewCode()
Definition: EditDocumentController.php:755
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$noView
‪bool $noView
Definition: EditDocumentController.php:185
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$R_URL_getvars
‪array $R_URL_getvars
Definition: EditDocumentController.php:208
‪TYPO3\CMS\Backend\Controller\EditDocumentController\setIsSavedRecord
‪setIsSavedRecord()
Definition: EditDocumentController.php:1296
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:38
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\getModuleData
‪mixed getModuleData($module, $type='')
Definition: AbstractUserAuthentication.php:1181
‪TYPO3\CMS\Backend\Controller\EditDocumentController\localizationRedirect
‪ResponseInterface null localizationRedirect(ServerRequestInterface $request)
Definition: EditDocumentController.php:2166
‪TYPO3\CMS\Core\Utility\HttpUtility\buildQueryString
‪static string buildQueryString(array $parameters, string $prependCharacter='', bool $skipEmptyParameters=false)
Definition: HttpUtility.php:163
‪TYPO3\CMS\Backend\Utility\BackendUtility\getLiveVersionOfRecord
‪static array null getLiveVersionOfRecord($table, $uid, $fields=' *')
Definition: BackendUtility.php:3748
‪TYPO3\CMS\Backend\Utility\BackendUtility\getPagesTSconfig
‪static array getPagesTSconfig($id)
Definition: BackendUtility.php:698
‪TYPO3\CMS\Core\Authentication\AbstractUserAuthentication\pushModuleData
‪pushModuleData($module, $data, $noSave=0)
Definition: AbstractUserAuthentication.php:1161
‪TYPO3\CMS\Backend\Controller\EditDocumentController\preInit
‪ResponseInterface preInit(ServerRequestInterface $request)
Definition: EditDocumentController.php:394
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SPACER
‪const DOKTYPE_SPACER
Definition: PageRepository.php:108
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getBackendUser
‪TYPO3 CMS Core Authentication BackendUserAuthentication getBackendUser()
Definition: EditDocumentController.php:2476
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$editconf
‪array< string, array > $editconf
Definition: EditDocumentController.php:78
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$closeDoc
‪int $closeDoc
Definition: EditDocumentController.php:118
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getInfobox
‪string getInfobox(string $message, ?string $title=null)
Definition: EditDocumentController.php:1210
‪TYPO3\CMS\Backend\Controller\EditDocumentController\setIsPageInFreeTranslationMode
‪setIsPageInFreeTranslationMode($record, int $sysLanguageUid)
Definition: EditDocumentController.php:1326
‪TYPO3\CMS\Backend\Controller\Event\BeforeFormEnginePageInitializedEvent
Definition: BeforeFormEnginePageInitializedEvent.php:27
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:33
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_SYSFOLDER
‪const DOKTYPE_SYSFOLDER
Definition: PageRepository.php:109
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:75
‪TYPO3\CMS\Backend\Utility\BackendUtility\getWorkspaceVersionOfRecord
‪static array bool getWorkspaceVersionOfRecord($workspace, $table, $uid, $fields=' *')
Definition: BackendUtility.php:3705
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\makeLinkButton
‪LinkButton makeLinkButton()
Definition: ButtonBar.php:121
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordWSOL
‪static array getRecordWSOL( $table, $uid, $fields=' *', $where='', $useDeleteClause=true, $unsetMovePointers=false)
Definition: BackendUtility.php:139
‪TYPO3\CMS\Backend\Template\Components\Buttons\InputButton\setForm
‪InputButton setForm($form)
Definition: InputButton.php:116
‪TYPO3\CMS\Backend\Controller\EditDocumentController\fixWSversioningInEditConf
‪fixWSversioningInEditConf($mapArray=false)
Definition: EditDocumentController.php:2293
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$cmd
‪array $cmd
Definition: EditDocumentController.php:141
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$storeUrl
‪string $storeUrl
Definition: EditDocumentController.php:238
‪TYPO3\CMS\Core\Utility\MathUtility\convertToPositiveInteger
‪static int convertToPositiveInteger($theInt)
Definition: MathUtility.php:56
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:95
‪TYPO3\CMS\Core\Http\RedirectResponse
Definition: RedirectResponse.php:28
‪TYPO3\CMS\Backend\Controller\EditDocumentController\makeEditForm
‪string makeEditForm()
Definition: EditDocumentController.php:1035
‪TYPO3\CMS\Core\Versioning\VersionState
Definition: VersionState.php:24
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static string[] trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:1059
‪TYPO3\CMS\Backend\Form\NodeFactory
Definition: NodeFactory.php:37
‪TYPO3\CMS\Backend\Utility\BackendUtility\readPageAccess
‪static array false readPageAccess($id, $perms_clause)
Definition: BackendUtility.php:597
‪TYPO3\CMS\Core\Messaging\AbstractMessage\OK
‪const OK
Definition: AbstractMessage.php:29
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$defVals
‪array null $defVals
Definition: EditDocumentController.php:91
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$newC
‪int $newC
Definition: EditDocumentController.php:286
‪TYPO3\CMS\Backend\Form\Exception\DatabaseRecordException
Definition: DatabaseRecordException.php:24
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$formResultCompiler
‪FormResultCompiler $formResultCompiler
Definition: EditDocumentController.php:303
‪TYPO3\CMS\Backend\Utility\BackendUtility\viewOnClick
‪static string viewOnClick( $pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=true)
Definition: BackendUtility.php:2359
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\makeHelpButton
‪HelpButton makeHelpButton()
Definition: ButtonBar.php:151
‪TYPO3\CMS\Backend\Controller\EditDocumentController\registerDeleteButtonToButtonBar
‪registerDeleteButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
Definition: EditDocumentController.php:1618
‪TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider
Definition: TranslationConfigurationProvider.php:35
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:24
‪TYPO3\CMS\Core\Type\Bitmask\Permission\CONTENT_EDIT
‪const CONTENT_EDIT
Definition: Permission.php:53
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$errorC
‪int $errorC
Definition: EditDocumentController.php:280
‪TYPO3\CMS\Backend\Controller\EditDocumentController\registerNewButtonToButtonBar
‪registerNewButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group, int $sysLanguageUid, int $l18nParent)
Definition: EditDocumentController.php:1500
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$storeTitle
‪string $storeTitle
Definition: EditDocumentController.php:225
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Form\Exception\AccessDeniedException
Definition: AccessDeniedException.php:26
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$viewUrl
‪string $viewUrl
Definition: EditDocumentController.php:173
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_DELETE
‪const PAGE_DELETE
Definition: Permission.php:43
‪TYPO3\CMS\Backend\Controller\EditDocumentController\DOCUMENT_CLOSE_MODE_NO_REDIRECT
‪const DOCUMENT_CLOSE_MODE_NO_REDIRECT
Definition: EditDocumentController.php:72
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$uriBuilder
‪UriBuilder $uriBuilder
Definition: EditDocumentController.php:341
‪TYPO3\CMS\Backend\Controller\EditDocumentController\closeDocument
‪ResponseInterface null closeDocument($mode, ServerRequestInterface $request)
Definition: EditDocumentController.php:2421
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static int[] intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:988
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getButtons
‪getButtons(ServerRequestInterface $request)
Definition: EditDocumentController.php:1233
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:22
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$R_URI
‪string $R_URI
Definition: EditDocumentController.php:214
‪TYPO3\CMS\Backend\Template\Components\Buttons\Action\HelpButton\setModuleName
‪HelpButton setModuleName($moduleName)
Definition: HelpButton.php:63
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getPreviewUrlAnchorSection
‪string getPreviewUrlAnchorSection()
Definition: EditDocumentController.php:875
‪TYPO3\CMS\Core\Utility\HttpUtility
Definition: HttpUtility.php:24
‪TYPO3\CMS\Backend\Controller\EditDocumentController\processData
‪ResponseInterface null processData(ServerRequestInterface $request)
Definition: EditDocumentController.php:481
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$doSave
‪bool $doSave
Definition: EditDocumentController.php:126
‪TYPO3\CMS\Core\Domain\Repository\PageRepository
Definition: PageRepository.php:52
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$storeArray
‪array $storeArray
Definition: EditDocumentController.php:232
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$eventDispatcher
‪EventDispatcherInterface $eventDispatcher
Definition: EditDocumentController.php:337
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Backend\Controller\EditDocumentController\registerDuplicationButtonToButtonBar
‪registerDuplicationButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group, int $sysLanguageUid, int $l18nParent)
Definition: EditDocumentController.php:1560
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$overrideVals
‪array null $overrideVals
Definition: EditDocumentController.php:97
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getFreeTranslationMode
‪bool getFreeTranslationMode(int $page, int $column, int $language)
Definition: EditDocumentController.php:1353
‪TYPO3\CMS\Core\Localization\LanguageService\getLL
‪string getLL($index)
Definition: LanguageService.php:154
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Backend\Template\Components\AbstractControl\setTitle
‪$this setTitle($title)
Definition: AbstractControl.php:109
‪TYPO3\CMS\Backend\Form\FormDataCompiler
Definition: FormDataCompiler.php:25
‪TYPO3\CMS\Backend\Controller\EditDocumentController\registerColumnsOnlyButtonToButtonBar
‪registerColumnsOnlyButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
Definition: EditDocumentController.php:1733
‪TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord
Definition: TcaDatabaseRecord.php:25
‪TYPO3\CMS\Core\Utility\PathUtility\getAbsoluteWebPath
‪static string getAbsoluteWebPath($targetPath)
Definition: PathUtility.php:43
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_RIGHT
‪const BUTTON_POSITION_RIGHT
Definition: ButtonBar.php:41
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$viewId
‪int $viewId
Definition: EditDocumentController.php:293
‪TYPO3\CMS\Backend\Controller
Definition: AbstractFormEngineAjaxController.php:18
‪TYPO3\CMS\Backend\Controller\EditDocumentController\registerCshButtonToButtonBar
‪registerCshButtonToButtonBar(ButtonBar $buttonBar, string $position, int $group)
Definition: EditDocumentController.php:1813
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$returnEditConf
‪bool $returnEditConf
Definition: EditDocumentController.php:195
‪TYPO3\CMS\Core\Domain\Repository\PageRepository\DOKTYPE_RECYCLER
‪const DOKTYPE_RECYCLER
Definition: PageRepository.php:110
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$docDat
‪array $docDat
Definition: EditDocumentController.php:250
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:27
‪TYPO3\CMS\Backend\Utility\BackendUtility\referenceCount
‪static string int referenceCount($table, $ref, $msg='', $count=null)
Definition: BackendUtility.php:3311
‪TYPO3\CMS\Core\Http\HtmlResponse
Definition: HtmlResponse.php:26
‪TYPO3\CMS\Backend\Utility\BackendUtility\isRecordLocked
‪static array bool isRecordLocked($table, $uid)
Definition: BackendUtility.php:3011
‪TYPO3\CMS\Backend\Controller\EditDocumentController\main
‪main(ServerRequestInterface $request)
Definition: EditDocumentController.php:980
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$popViewId
‪int $popViewId
Definition: EditDocumentController.php:167
‪TYPO3\CMS\Backend\Template\Components\Buttons\AbstractButton\setShowLabelText
‪$this setShowLabelText($showLabelText)
Definition: AbstractButton.php:61
‪TYPO3\CMS\Backend\Controller\EditDocumentController\getStandAloneContentElementTranslationsCount
‪int getStandAloneContentElementTranslationsCount(int $page, int $column, int $language)
Definition: EditDocumentController.php:1851
‪TYPO3\CMS\Backend\Controller\EditDocumentController\$retUrl
‪string $retUrl
Definition: EditDocumentController.php:112
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:39