‪TYPO3CMS  ‪main
ImportExport.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 
18 namespace ‪TYPO3\CMS\Impexp;
19 
21 use TYPO3\CMS\Backend\Utility\BackendUtility;
26 use TYPO3\CMS\Core\Imaging\IconSize;
39 
45 abstract class ‪ImportExport
46 {
52  protected ‪$mode = '';
53 
59  protected ‪$permsClause;
60 
66  protected ‪$pid = -1;
67 
71  protected ?array ‪$pidRecord = null;
72 
78  protected ‪$showStaticRelations = false;
79 
85  protected ‪$update = false;
86 
92  protected ‪$doesImport = false;
93 
100  protected ‪$importMode = [];
101 
107  protected ‪$globalIgnorePid = false;
108 
114  protected ‪$forceAllUids = false;
115 
121  protected ‪$showDiff = false;
122 
128  protected ‪$softrefInputValues = [];
129 
135  protected ‪$fileIdMap = [];
136 
143  protected ‪$relStaticTables = [];
144 
150  protected ‪$excludeMap = [];
151 
157  protected ‪$softrefCfg = [];
158 
164  protected ‪$extensionDependencies = [];
165 
171  protected ‪$importMapId = [];
172 
178  protected ‪$errorLog = [];
179 
185  protected ‪$cacheGetRecordPath = [];
186 
192  protected ‪$dat = [];
193 
199  protected ‪$fileProcObj;
200 
204  protected ‪$diffUtility;
205 
209  protected ‪$remainHeader = [];
210 
214  protected ‪$lang;
215 
219  protected ‪$iconFactory;
220 
226  protected ‪$fileadminFolderName = '';
227 
228  protected ?string ‪$temporaryFolderName = null;
229  protected ?‪Folder ‪$defaultImportExportFolder = null;
230 
237  protected ‪$excludeDisabledRecords = false;
238 
244  protected ‪$storages = [];
245 
252 
256  protected ?‪ResourceStorage ‪$defaultStorage = null;
257 
261  protected ‪$storageRepository;
262 
266  public function ‪__construct()
267  {
268  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
269  $this->lang = $this->‪getLanguageService();
270  $this->permsClause = $this->‪getBackendUser()->getPagePermsClause(‪Permission::PAGE_SHOW);
271 
272  $this->‪fetchStorages();
273  }
274 
281  protected function ‪fetchStorages(): void
282  {
283  $this->storages = [];
284  $this->storagesAvailableForImport = [];
285  $this->defaultStorage = null;
286 
287  $this->‪getStorageRepository()->‪flush();
288 
289  $storages = $this->‪getStorageRepository()->‪findAll();
290  // @todo: Why by reference here? Test ImagesWithStoragesTest::importMultipleImagesWithMultipleStorages fails otherwise
291  foreach ($storages as &$storage) {
292  $this->storages[$storage->getUid()] = $storage;
293  if ($storage->isOnline() && $storage->isWritable() && $storage->getDriverType() === 'Local') {
294  $this->storagesAvailableForImport[$storage->getUid()] = $storage;
295  }
296  if ($this->defaultStorage === null && $storage->isDefault()) {
297  $this->defaultStorage = $storage;
298  }
299  }
300  }
301 
302  /********************************************************
303  * Visual rendering of import/export memory, $this->dat
304  ********************************************************/
305 
311  public function ‪renderPreview(): array
312  {
313  // @todo: Why is this done?
314  unset($this->dat['files']);
315 
316  $previewData = [
317  'update' => ‪$this->update,
318  'showDiff' => ‪$this->showDiff,
319  'insidePageTree' => [],
320  'outsidePageTree' => [],
321  ];
322 
323  if (!isset($this->dat['header']['pagetree']) && !isset($this->dat['header']['records'])) {
324  return $previewData;
325  }
326 
327  // Traverse header:
328  $this->remainHeader = $this->dat['header'];
329 
330  // Preview of the page tree to be exported
331  if (is_array($this->dat['header']['pagetree'] ?? null)) {
332  $this->‪traversePageTree($this->dat['header']['pagetree'], $previewData['insidePageTree']);
333  foreach ($previewData['insidePageTree'] as &$line) {
334  $line['controls'] = $this->‪renderControls($line);
335  $line['message'] = (($line['msg'] ?? '') && !$this->doesImport ? '<span class="text-danger">' . htmlspecialchars($line['msg']) . '</span>' : '');
336  }
337  }
338 
339  // Preview the remaining records that were not included in the page tree
340  if (is_array($this->remainHeader['records'] ?? null)) {
341  if (is_array($this->remainHeader['records']['pages'] ?? null)) {
342  $this->‪traversePageRecords($this->remainHeader['records']['pages'], $previewData['outsidePageTree']);
343  }
344  $this->‪traverseAllRecords($this->remainHeader['records'], $previewData['outsidePageTree']);
345  foreach ($previewData['outsidePageTree'] as &$line) {
346  $line['controls'] = $this->‪renderControls($line);
347  $line['message'] = (($line['msg'] ?? '') && !$this->doesImport ? '<span class="text-danger">' . htmlspecialchars($line['msg']) . '</span>' : '');
348  }
349  }
350 
351  return $previewData;
352  }
353 
361  protected function ‪traversePageTree(array $pageTree, array &$lines, int $indent = 0): void
362  {
363  foreach ($pageTree as $pageUid => $page) {
364  if ($this->excludeDisabledRecords === true && $this->‪isRecordDisabled('pages', $pageUid)) {
365  $this->‪excludePageAndRecords($pageUid, $page);
366  continue;
367  }
368 
369  // Add page
370  $this->‪addRecord('pages', $pageUid, $lines, $indent);
371 
372  // Add records
373  if (is_array($this->dat['header']['pid_lookup'][$pageUid] ?? null)) {
374  foreach ($this->dat['header']['pid_lookup'][$pageUid] as $table => $records) {
375  $table = (string)$table;
376  if ($table !== 'pages') {
377  foreach (array_keys($records) as ‪$uid) {
378  $this->‪addRecord($table, (int)‪$uid, $lines, $indent + 1);
379  }
380  }
381  }
382  unset($this->remainHeader['pid_lookup'][$pageUid]);
383  }
384 
385  // Add subtree
386  if (is_array($page['subrow'] ?? null)) {
387  $this->‪traversePageTree($page['subrow'], $lines, $indent + 1);
388  }
389  }
390  }
391 
399  protected function ‪isRecordDisabled(string $table, int ‪$uid): bool
400  {
401  return (bool)($this->dat['records'][$table . ':' . ‪$uid]['data'][
402  ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'] ?? ''
403  ] ?? false);
404  }
405 
412  protected function ‪excludePageAndRecords(int $pageUid, array $page): void
413  {
414  // Exclude page
415  unset($this->remainHeader['records']['pages'][$pageUid]);
416 
417  // Exclude records
418  if (is_array($this->dat['header']['pid_lookup'][$pageUid] ?? null)) {
419  foreach ($this->dat['header']['pid_lookup'][$pageUid] as $table => $records) {
420  if ($table !== 'pages') {
421  foreach (array_keys($records) as ‪$uid) {
422  unset($this->remainHeader['records'][$table][‪$uid]);
423  }
424  }
425  }
426  unset($this->remainHeader['pid_lookup'][$pageUid]);
427  }
428 
429  // Exclude subtree
430  if (is_array($page['subrow'] ?? null)) {
431  foreach ($page['subrow'] as $subPageUid => $subPage) {
432  $this->‪excludePageAndRecords($subPageUid, $subPage);
433  }
434  }
435  }
436 
443  protected function ‪traversePageRecords(array $pageTree, array &$lines): void
444  {
445  foreach ($pageTree as $pageUid => $_) {
446  // Add page
447  $this->‪addRecord('pages', (int)$pageUid, $lines, 0, true);
448 
449  // Add records
450  if (is_array($this->dat['header']['pid_lookup'][$pageUid] ?? null)) {
451  foreach ($this->dat['header']['pid_lookup'][$pageUid] as $table => $records) {
452  if ($table !== 'pages') {
453  foreach (array_keys($records) as ‪$uid) {
454  $this->‪addRecord((string)$table, (int)‪$uid, $lines, 2);
455  }
456  }
457  }
458  unset($this->remainHeader['pid_lookup'][$pageUid]);
459  }
460  }
461  }
462 
469  protected function ‪traverseAllRecords(array $pageTree, array &$lines): void
470  {
471  foreach ($pageTree as $table => $records) {
472  $this->‪addGeneralErrorsByTable($table);
473  if ($table !== 'pages') {
474  foreach (array_keys($records) as ‪$uid) {
475  $this->‪addRecord((string)$table, (int)‪$uid, $lines, 0, true);
476  }
477  }
478  }
479  }
480 
486  protected function ‪addGeneralErrorsByTable(string $table): void
487  {
488  if ($this->update && $table === 'sys_file') {
489  $this->‪addError('Updating sys_file records is not supported! They will be imported as new records!');
490  }
491  if ($this->forceAllUids && $table === 'sys_file') {
492  $this->‪addError('Forcing uids of sys_file records is not supported! They will be imported as new records!');
493  }
494  }
495 
505  protected function ‪addRecord(string $table, int ‪$uid, array &$lines, int $indent, bool $checkImportInPidRecord = false): void
506  {
507  ‪$record = $this->dat['header']['records'][$table][‪$uid] ?? null;
508  unset($this->remainHeader['records'][$table][‪$uid]);
509  if (!is_array(‪$record) && !($table === 'pages' && ‪$uid === 0)) {
510  $this->‪addError('MISSING RECORD: ' . $table . ':' . ‪$uid);
511  }
512 
513  // Create record information for preview
514  $line = [];
515  $line['ref'] = $table . ':' . ‪$uid;
516  $line['type'] = 'record';
517  $line['msg'] = '';
518  if ($table === '_SOFTREF_') {
519  // Record is a soft reference
520  $line['preCode'] = $this->‪renderIndent($indent);
521  $line['title'] = '<em>' . htmlspecialchars($this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_softReferencesFiles')) . '</em>';
522  } elseif (!isset(‪$GLOBALS['TCA'][$table])) {
523  // Record is of unknown table
524  $line['preCode'] = $this->‪renderIndent($indent);
525  $line['title'] = '<em>' . htmlspecialchars((string)‪$record['title']) . '</em>';
526  $line['msg'] = 'UNKNOWN TABLE "' . $line['ref'] . '"';
527  } else {
528  ‪$pidRecord = $this->‪getPidRecord();
529  $line['preCode'] = ''
530  . $this->‪renderIndent($indent)
531  . $this->iconFactory
532  ->getIconForRecord(
533  $table,
534  (array)($this->dat['records'][$table . ':' . ‪$uid]['data'] ?? []),
535  IconSize::SMALL
536  )
537  ->setTitle($line['ref'])
538  ->render();
539  $line['title'] = htmlspecialchars(‪$record['title'] ?? '');
540  // Link to page view
541  if ($table === 'pages') {
542  $viewID = $this->mode === 'export' ? ‪$uid : ($this->doesImport ? ($this->importMapId['pages'][‪$uid] ?? 0) : 0);
543  if ($viewID) {
544  $attributes = ‪PreviewUriBuilder::create($viewID)->serializeDispatcherAttributes();
545  if ($attributes) {
546  $line['title'] = sprintf('<a href="#" %s>%s</a>', $attributes, $line['title']);
547  }
548  }
549  }
550  $line['active'] = !$this->‪isRecordDisabled($table, ‪$uid) ? 'active' : 'hidden';
551  if ($this->mode === 'import' && ‪$pidRecord !== null) {
552  if ($checkImportInPidRecord) {
553  if (!$this->‪getBackendUser()->doesUserHaveAccess(‪$pidRecord, ($table === 'pages' ? 8 : 16))) {
554  $line['msg'] .= '"' . $line['ref'] . '" cannot be INSERTED on this page! ';
555  }
556  if ($this->pid > 0 && !$this->‪checkDokType($table, ‪$pidRecord['doktype']) && !‪$GLOBALS['TCA'][$table]['ctrl']['rootLevel']) {
557  $line['msg'] .= '"' . $table . '" cannot be INSERTED on this page type (change page type to "Folder".) ';
558  }
559  }
560  if (!$this->‪getBackendUser()->check('tables_modify', $table)) {
561  $line['msg'] .= 'You are not allowed to CREATE "' . $table . '" tables! ';
562  }
563  if (‪$GLOBALS['TCA'][$table]['ctrl']['readOnly'] ?? false) {
564  $line['msg'] .= 'TABLE "' . $table . '" is READ ONLY! ';
565  }
566  if ((‪$GLOBALS['TCA'][$table]['ctrl']['adminOnly'] ?? false) && !$this->‪getBackendUser()->isAdmin()) {
567  $line['msg'] .= 'TABLE "' . $table . '" is ADMIN ONLY! ';
568  }
569  if (‪$GLOBALS['TCA'][$table]['ctrl']['is_static'] ?? false) {
570  $line['msg'] .= 'TABLE "' . $table . '" is a STATIC TABLE! ';
571  }
572  if ((int)(‪$GLOBALS['TCA'][$table]['ctrl']['rootLevel'] ?? 0) === 1) {
573  $line['msg'] .= 'TABLE "' . $table . '" will be inserted on ROOT LEVEL! ';
574  }
575  $databaseRecord = null;
576  if ($this->update) {
577  $databaseRecord = $this->‪getRecordFromDatabase($table, ‪$uid, $this->showDiff ? '*' : 'uid,pid');
578  if ($databaseRecord === null) {
579  $line['updatePath'] = '<strong>NEW!</strong>';
580  } else {
581  $line['updatePath'] = htmlspecialchars($this->‪getRecordPath((int)($databaseRecord['pid'] ?? 0)));
582  }
583  if ($table === 'sys_file') {
584  $line['updateMode'] = '';
585  } else {
586  $line['updateMode'] = $this->‪renderImportModeSelector(
587  $table,
588  ‪$uid,
589  $databaseRecord !== null
590  );
591  }
592  }
593  // Diff view
594  if ($this->showDiff) {
595  $diffInverse = $this->update ? true : false;
596  // For imports, get new id:
597  if (isset($this->importMapId[$table][‪$uid]) && $newUid = $this->importMapId[$table][‪$uid]) {
598  $diffInverse = false;
599  $databaseRecord = $this->‪getRecordFromDatabase($table, $newUid, '*');
600  BackendUtility::workspaceOL($table, $databaseRecord);
601  }
603  $importRecord = $this->dat['records'][$table . ':' . ‪$uid]['data'] ?? null;
604  if ($databaseRecord === null) {
605  $line['showDiffContent'] = '';
606  } elseif (is_array($databaseRecord) && is_array($importRecord)) {
607  $line['showDiffContent'] = $this->‪compareRecords($databaseRecord, $importRecord, $table, $diffInverse);
608  } else {
609  $line['showDiffContent'] = 'ERROR: One of the inputs were not an array!';
610  }
611  }
612  }
613  }
614  $lines[] = $line;
615 
616  // File relations
617  if (is_array(‪$record['filerefs'] ?? null)) {
618  $this->‪addFiles(‪$record['filerefs'], $lines, $indent);
619  }
620  // Database relations
621  if (is_array(‪$record['rels'] ?? null)) {
622  $this->‪addRelations(‪$record['rels'], $lines, $indent);
623  }
624  // Soft references
625  if (is_array(‪$record['softrefs'] ?? null)) {
626  $this->‪addSoftRefs(‪$record['softrefs'], $lines, $indent);
627  }
628  }
629 
640  protected function ‪addRelations(array $relations, array &$lines, int $indent, array $recursionCheck = []): void
641  {
642  foreach ($relations as $relation) {
643  $table = $relation['table'];
644  ‪$uid = $relation['id'];
645  $line = [];
646  $line['ref'] = $table . ':' . ‪$uid;
647  $line['type'] = 'rel';
648  $line['msg'] = '';
649  if (in_array($line['ref'], $recursionCheck, true)) {
650  continue;
651  }
652  $iconName = 'status-status-checked';
653  $staticFixed = false;
654  ‪$record = null;
655  if (‪$uid > 0) {
656  ‪$record = $this->dat['header']['records'][$table][‪$uid] ?? null;
657  if (!is_array(‪$record)) {
658  if ($this->‪isTableStatic($table) || $this->‪isRecordExcluded($table, (int)‪$uid)
659  || ($relation['tokenID'] ?? '') && !$this->‪isSoftRefIncluded($relation['tokenID'] ?? '')) {
660  $line['title'] = htmlspecialchars('STATIC: ' . $line['ref']);
661  $staticFixed = true;
662  } else {
663  $databaseRecord = $this->‪getRecordFromDatabase($table, (int)‪$uid);
664  $recordPath = $this->‪getRecordPath($databaseRecord === null ? 0 : ($table === 'pages' ? (int)$databaseRecord['uid'] : (int)$databaseRecord['pid']));
665  $line['title'] = sprintf(
666  '<span title="%s">%s</span>',
667  htmlspecialchars($recordPath),
668  htmlspecialchars($line['ref'])
669  );
670  $line['msg'] = 'LOST RELATION' . ($databaseRecord === null ? ' (Record not found!)' : ' (Path: ' . $recordPath . ')');
671  $iconName = 'status-dialog-warning';
672  }
673  } else {
674  $recordPath = $this->‪getRecordPath($table === 'pages' ? (int)‪$record['uid'] : (int)‪$record['pid']);
675  $line['title'] = sprintf(
676  '<span title="%s">%s</span>',
677  htmlspecialchars($recordPath),
678  htmlspecialchars((string)‪$record['title'])
679  );
680  }
681  } else {
682  // Negative values in relation fields. These are typically fields of e.g. fe_users.
683  // They are static values. They CAN theoretically be negative pointers to uids in other tables,
684  // but this is so rarely used that it is not supported.
685  $line['title'] = htmlspecialchars('FIXED: ' . $line['ref']);
686  $staticFixed = true;
687  }
688 
689  $line['preCode'] = ''
690  . $this->‪renderIndent($indent + 1)
691  . $this->iconFactory
692  ->getIcon($iconName, IconSize::SMALL)
693  ->setTitle($line['ref'])
694  ->render();
695  if (!$staticFixed || $this->showStaticRelations) {
696  $lines[] = $line;
697  if (is_array(‪$record) && is_array(‪$record['rels'] ?? null)) {
698  $this->‪addRelations(‪$record['rels'], $lines, $indent + 1, array_merge($recursionCheck, [$line['ref']]));
699  }
700  }
701  }
702  }
703 
716  public function ‪addFiles(array $relations, array &$lines, int $indent, string $tokenID = ''): void
717  {
718  foreach ($relations as $ID) {
719  $line = [];
720  $line['msg'] = '';
721  $fileInfo = $this->dat['header']['files'][$ID];
722  if (!is_array($fileInfo)) {
723  if ($tokenID !== '' || $this->‪isSoftRefIncluded($tokenID)) {
724  $line['msg'] = 'MISSING FILE: ' . $ID;
725  $this->‪addError('MISSING FILE: ' . $ID);
726  } else {
727  return;
728  }
729  }
730  $line['ref'] = 'FILE';
731  $line['type'] = 'file';
732  $line['preCode'] = ''
733  . $this->‪renderIndent($indent + 1)
734  . $this->iconFactory
735  ->getIcon('status-reference-hard', IconSize::SMALL)
736  ->setTitle($line['ref'])
737  ->render();
738  $line['title'] = htmlspecialchars($fileInfo['filename']);
739  $line['showDiffContent'] = ‪PathUtility::stripPathSitePrefix((string)($this->fileIdMap[$ID] ?? ''));
740  // If import mode and there is a non-RTE soft reference, check the destination directory.
741  if ($this->mode === 'import' && $tokenID !== '' && !($fileInfo['RTE_ORIG_ID'] ?? false)) {
742  // Check folder existence
743  if (isset($fileInfo['parentRelFileName'])) {
744  $line['msg'] = 'Seems like this file is already referenced from within an HTML/CSS file. That takes precedence. ';
745  } else {
746  $origDirPrefix = ‪PathUtility::dirname($fileInfo['relFileName']) . '/';
747  $dirPrefix = $this->‪resolveStoragePath($origDirPrefix);
748  if ($dirPrefix === null) {
749  $line['msg'] = 'ERROR: There are no available file mounts to write file in!';
750  } elseif ($origDirPrefix !== $dirPrefix) {
751  $line['msg'] = 'File will be attempted written to "' . $dirPrefix . '". ';
752  }
753  }
754  // Check file existence
755  if (file_exists(‪Environment::getPublicPath() . '/' . $fileInfo['relFileName'])) {
756  if ($this->update) {
757  $line['updatePath'] = 'File exists.';
758  } else {
759  $line['msg'] .= 'File already exists! ';
760  }
761  }
762  // Check file extension
764  if ($fileProcObj->actionPerms['addFile']) {
765  $pathInfo = GeneralUtility::split_fileref(‪Environment::getPublicPath() . '/' . $fileInfo['relFileName']);
766  if (!GeneralUtility::makeInstance(FileNameValidator::class)->isValid($pathInfo['file'])) {
767  $line['msg'] .= 'File extension was not allowed!';
768  }
769  } else {
770  $line['msg'] = 'Your user profile does not allow you to create files on the server!';
771  }
772  }
773  $lines[] = $line;
774  unset($this->remainHeader['files'][$ID]);
775 
776  // RTE originals
777  if ($fileInfo['RTE_ORIG_ID'] ?? false) {
778  $ID = $fileInfo['RTE_ORIG_ID'];
779  $line = [];
780  $fileInfo = $this->dat['header']['files'][$ID];
781  if (!is_array($fileInfo)) {
782  $line['msg'] = 'MISSING RTE original FILE: ' . $ID;
783  $this->‪addError('MISSING RTE original FILE: ' . $ID);
784  }
785  $line['ref'] = 'FILE';
786  $line['type'] = 'file';
787  $line['preCode'] = ''
788  . $this->‪renderIndent($indent + 1)
789  . $this->iconFactory
790  ->getIcon('status-reference-hard', IconSize::SMALL)
791  ->setTitle($line['ref'])
792  ->render();
793  $line['title'] = htmlspecialchars($fileInfo['filename']) . ' <em>(Original)</em>';
794  $line['showDiffContent'] = ‪PathUtility::stripPathSitePrefix($this->fileIdMap[$ID]);
795  $lines[] = $line;
796  unset($this->remainHeader['files'][$ID]);
797  }
798 
799  // External resources
800  if (is_array($fileInfo['EXT_RES_ID'] ?? null)) {
801  foreach ($fileInfo['EXT_RES_ID'] as $extID) {
802  $line = [];
803  $fileInfo = $this->dat['header']['files'][$extID];
804  if (!is_array($fileInfo)) {
805  $line['msg'] = 'MISSING External Resource FILE: ' . $extID;
806  $this->‪addError('MISSING External Resource FILE: ' . $extID);
807  } else {
808  $line['updatePath'] = $fileInfo['parentRelFileName'];
809  }
810  $line['ref'] = 'FILE';
811  $line['type'] = 'file';
812  $line['preCode'] = ''
813  . $this->‪renderIndent($indent + 1)
814  . $this->iconFactory
815  ->getIcon('actions-insert-reference', IconSize::SMALL)
816  ->setTitle($line['ref'])
817  ->render();
818  $line['title'] = htmlspecialchars($fileInfo['filename']) . ' <em>(Resource)</em>';
819  $line['showDiffContent'] = ‪PathUtility::stripPathSitePrefix($this->fileIdMap[$extID]);
820  $lines[] = $line;
821  unset($this->remainHeader['files'][$extID]);
822  }
823  }
824  }
825  }
826 
836  protected function ‪addSoftRefs(array $softrefs, array &$lines, int $indent): void
837  {
838  foreach ($softrefs as $softref) {
839  $line = [];
840  $line['ref'] = 'SOFTREF';
841  $line['type'] = 'softref';
842  $line['msg'] = '';
843  $line['preCode'] = ''
844  . $this->‪renderIndent($indent)
845  . $this->iconFactory
846  ->getIcon('status-reference-soft', IconSize::SMALL)
847  ->setTitle($line['ref'])
848  ->render();
849  $line['title'] = sprintf(
850  '<em>%s, "%s"</em>: <span title="%s">%s</span>',
851  $softref['field'],
852  $softref['spKey'],
853  htmlspecialchars($softref['matchString'] ?? ''),
854  htmlspecialchars(‪GeneralUtility::fixed_lgd_cs($softref['matchString'] ?? '', 60))
855  );
856  if ($softref['subst']['type'] ?? false) {
857  if ($softref['subst']['title'] ?? false) {
858  $line['title'] .= sprintf(
859  '<br>%s <strong>%s</strong> %s',
860  $this->‪renderIndent($indent + 1),
861  htmlspecialchars($this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_title')),
862  htmlspecialchars(‪GeneralUtility::fixed_lgd_cs($softref['subst']['title'], 60))
863  );
864  }
865  if ($softref['subst']['description'] ?? false) {
866  $line['title'] .= sprintf(
867  '<br>%s <strong>%s</strong> %s',
868  $this->‪renderIndent($indent + 1),
869  htmlspecialchars($this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_descr')),
870  htmlspecialchars(‪GeneralUtility::fixed_lgd_cs($softref['subst']['description'], 60))
871  );
872  }
873  if ($softref['subst']['type'] === 'db') {
874  $line['title'] .= sprintf(
875  '<br>%s <strong>%s</strong> %s',
876  $this->‪renderIndent($indent + 1),
877  htmlspecialchars($this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_softrefsel_record')),
878  $softref['subst']['recordRef']
879  );
880  } elseif ($softref['subst']['type'] === 'file') {
881  $line['title'] .= sprintf(
882  '<br>%s <strong>%s</strong> %s',
883  $this->‪renderIndent($indent + 1),
884  htmlspecialchars($this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_filename')),
885  $softref['subst']['relFileName']
886  );
887  } elseif ($softref['subst']['type'] === 'string') {
888  $line['title'] .= sprintf(
889  '<br>%s <strong>%s</strong> %s',
890  $this->‪renderIndent($indent + 1),
891  htmlspecialchars($this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_value')),
892  $softref['subst']['tokenValue']
893  );
894  }
895  }
896  $line['_softRefInfo'] = $softref;
897  ‪$mode = $this->softrefCfg[$softref['subst']['tokenID'] ?? null]['mode'] ?? '';
899  $line['msg'] .= $softref['error'];
900  }
901  $lines[] = $line;
902 
903  // Add database relations
904  if (($softref['subst']['type'] ?? '') === 'db') {
905  [$referencedTable, $referencedUid] = explode(':', $softref['subst']['recordRef']);
906  $relations = [['table' => $referencedTable, 'id' => $referencedUid, 'tokenID' => $softref['subst']['tokenID']]];
907  $this->‪addRelations($relations, $lines, $indent + 1);
908  }
909  // Add files relations
910  if (($softref['subst']['type'] ?? '') === 'file') {
911  $relations = [$softref['file_ID']];
912  $this->‪addFiles($relations, $lines, $indent + 1, $softref['subst']['tokenID']);
913  }
914  }
915  }
916 
917  protected function ‪renderIndent(int $indent): string
918  {
919  return $indent > 0 ? '<span class="indent indent-inline-block" style="--indent-level: ' . $indent . '"></span>' : '';
920  }
921 
929  protected function ‪checkDokType(string $table, int $dokType): bool
930  {
931  return GeneralUtility::makeInstance(PageDoktypeRegistry::class)->isRecordTypeAllowedForDoktype($table, $dokType);
932  }
933 
940  protected function ‪renderControls(array $line): string
941  {
942  if ($this->mode === 'export') {
943  if ($line['type'] === 'record') {
944  return $this->‪renderRecordExcludeCheckbox($line['ref']);
945  }
946  if ($line['type'] === 'softref') {
947  return $this->‪renderSoftRefExportSelector($line['_softRefInfo']);
948  }
949  } elseif ($this->mode === 'import') {
950  if ($line['type'] === 'softref') {
951  return $this->‪renderSoftRefImportTextField($line['_softRefInfo']);
952  }
953  }
954  return '';
955  }
956 
963  protected function ‪renderRecordExcludeCheckbox(string $recordRef): string
964  {
965  return ''
966  . '<div class="form-check mb-0">'
967  . '<input class="form-check-input t3js-exclude-checkbox" type="checkbox" name="tx_impexp[exclude][' . $recordRef . ']" id="checkExclude' . $recordRef . '" value="1" />'
968  . '<label class="form-check-label" for="checkExclude' . $recordRef . '">' . htmlspecialchars($this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_exclude')) . '</label>'
969  . '</div>';
970  }
971 
978  protected function ‪renderSoftRefImportTextField(array $softref): string
979  {
980  if (isset($softref['subst']['tokenID'])) {
981  $tokenID = $softref['subst']['tokenID'];
982  $cfg = $this->softrefCfg[$tokenID] ?? [];
983  if (($cfg['mode'] ?? '') === ‪Import::SOFTREF_IMPORT_MODE_EDITABLE) {
984  $html = '';
985  if ($cfg['title'] ?? false) {
986  $html .= '<strong>' . htmlspecialchars((string)$cfg['title']) . '</strong><br>';
987  }
988  $html .= htmlspecialchars((string)$cfg['description']) . '<br>';
989  $html .= sprintf(
990  '<input type="text" name="tx_impexp[softrefInputValues][%s]" value="%s" />',
991  $tokenID,
992  htmlspecialchars($this->softrefInputValues[$tokenID] ?? $cfg['defValue'])
993  );
994  return $html;
995  }
996  }
997 
998  return '';
999  }
1000 
1008  protected function ‪renderSoftRefExportSelector(array $softref): string
1009  {
1010  $fileInfo = isset($softref['file_ID']) ? $this->dat['header']['files'][$softref['file_ID']] : [];
1011  // Substitution scheme has to be around and RTE images MUST be exported.
1012  if (isset($softref['subst']['tokenID']) && !isset($fileInfo['RTE_ORIG_ID'])) {
1013  $options = [];
1014  $options[''] = '';
1015  $options[‪Import::SOFTREF_IMPORT_MODE_EDITABLE] = $this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_softrefsel_editable');
1016  $options[‪Import::SOFTREF_IMPORT_MODE_EXCLUDE] = $this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_softrefsel_exclude');
1017  $value = $this->softrefCfg[$softref['subst']['tokenID']]['mode'] ?? '';
1018  $selectHtml = $this->‪renderSelectBox(
1019  'tx_impexp[softrefCfg][' . $softref['subst']['tokenID'] . '][mode]',
1020  $value,
1021  $options
1022  );
1023  $textFieldHtml = '';
1024  if ($value === ‪Import::SOFTREF_IMPORT_MODE_EDITABLE) {
1025  if ($softref['subst']['title'] ?? false) {
1026  $textFieldHtml .= sprintf(
1027  '
1028  <input type="hidden" name="tx_impexp[softrefCfg][%1$s][title]" value="%2$s" />
1029  <strong>%2$s</strong><br>',
1030  $softref['subst']['tokenID'],
1031  htmlspecialchars($softref['subst']['title'])
1032  );
1033  }
1034  if (!($softref['subst']['description'] ?? false)) {
1035  $textFieldHtml .= sprintf(
1036  '
1037  %s<br>
1038  <input type="text" name="tx_impexp[softrefCfg][%s][description]" value="%s" />',
1039  htmlspecialchars($this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_printerror_description')),
1040  $softref['subst']['tokenID'],
1041  htmlspecialchars($this->softrefCfg[$softref['subst']['tokenID']]['description'] ?? '')
1042  );
1043  } else {
1044  $textFieldHtml .= sprintf(
1045  '
1046  <input type="hidden" name="tx_impexp[softrefCfg][%1$s][description]" value="%2$s" />%2$s',
1047  $softref['subst']['tokenID'],
1048  htmlspecialchars($softref['subst']['description'])
1049  );
1050  }
1051  $textFieldHtml .= sprintf(
1052  '
1053  <input type="hidden" name="tx_impexp[softrefCfg][%s][defValue]" value="%s" />',
1054  $softref['subst']['tokenID'],
1055  htmlspecialchars($softref['subst']['tokenValue'])
1056  );
1057  }
1058  return $selectHtml . $textFieldHtml;
1059  }
1060  return '';
1061  }
1062 
1071  protected function ‪renderImportModeSelector(string $table, int ‪$uid, bool $doesRecordExist): string
1072  {
1073  $options = [];
1074  if (!$doesRecordExist) {
1075  $options[] = $this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_insert');
1076  if ($this->‪getBackendUser()->isAdmin()) {
1077  $options[‪Import::IMPORT_MODE_FORCE_UID] = sprintf($this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_forceUidSAdmin'), ‪$uid);
1078  }
1079  } else {
1080  $options[] = $this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_update');
1081  $options[‪Import::IMPORT_MODE_AS_NEW] = $this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_importAsNew');
1082  if (!$this->globalIgnorePid) {
1083  $options[‪Import::IMPORT_MODE_IGNORE_PID] = $this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_ignorePid');
1084  } else {
1085  $options[‪Import::IMPORT_MODE_RESPECT_PID] = $this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_respectPid');
1086  }
1087  }
1088  $options[‪Import::IMPORT_MODE_EXCLUDE] = $this->lang->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_exclude');
1089  return $this->‪renderSelectBox(
1090  'tx_impexp[import_mode][' . $table . ':' . ‪$uid . ']',
1091  (string)($this->importMode[$table . ':' . ‪$uid] ?? ''),
1092  $options
1093  );
1094  }
1095 
1104  protected function ‪renderSelectBox(string $name, string $value, array $options): string
1105  {
1106  $optionsHtml = '';
1107  $isValueInOptions = false;
1108 
1109  foreach ($options as $k => $v) {
1110  if ((string)$k === $value) {
1111  $isValueInOptions = true;
1112  $selectedHtml = ' selected="selected"';
1113  } else {
1114  $selectedHtml = '';
1115  }
1116  $optionsHtml .= sprintf(
1117  '<option value="%s"%s>%s</option>',
1118  htmlspecialchars((string)$k),
1119  $selectedHtml,
1120  htmlspecialchars((string)$v)
1121  );
1122  }
1123 
1124  // Append and select the current value as an option of the form "[value]"
1125  // if it is not available in the options.
1126  if (!$isValueInOptions && $value !== '') {
1127  $optionsHtml .= sprintf(
1128  '<option value="%s" selected="selected">%s</option>',
1129  htmlspecialchars($value),
1130  htmlspecialchars('[\'' . $value . '\']')
1131  );
1132  }
1133 
1134  return '<select class="form-select form-select-sm" name="' . $name . '" style="width: 100px">' . $optionsHtml . '</select>';
1135  }
1136 
1137  public function getFileadminFolderName(): string
1138  {
1139  if (empty($this->fileadminFolderName)) {
1140  if (!empty($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'])) {
1141  $this->fileadminFolderName = rtrim($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], '/');
1142  } else {
1143  $this->fileadminFolderName = 'fileadmin';
1144  }
1145  }
1146  return $this->fileadminFolderName;
1147  }
1148 
1149  public function getOrCreateTemporaryFolderName(): string
1150  {
1151  if (empty($this->temporaryFolderName)) {
1152  $this->temporaryFolderName = $this->createTemporaryFolderName();
1153  }
1154  return $this->temporaryFolderName;
1155  }
1156 
1157  protected function createTemporaryFolderName(): string
1158  {
1159  $temporaryPath = Environment::getVarPath() . '/transient';
1160  do {
1161  $temporaryFolderName = sprintf(
1162  '%s/impexp_%s_files_%d',
1163  $temporaryPath,
1164  $this->mode,
1165  random_int(1, PHP_INT_MAX)
1166  );
1167  } while (is_dir($temporaryFolderName));
1168  GeneralUtility::mkdir_deep($temporaryFolderName);
1169  return $temporaryFolderName;
1170  }
1171 
1172  public function removeTemporaryFolderName(): void
1173  {
1174  if (!empty($this->temporaryFolderName)) {
1175  GeneralUtility::rmdir($this->temporaryFolderName, true);
1176  $this->temporaryFolderName = null;
1177  }
1178  }
1179 
1184  public function getOrCreateDefaultImportExportFolder(): ?Folder
1185  {
1186  if (empty($this->defaultImportExportFolder)) {
1187  $this->createDefaultImportExportFolder();
1188  }
1189  return $this->defaultImportExportFolder;
1190  }
1191 
1196  protected function createDefaultImportExportFolder(): void
1197  {
1198  $defaultTemporaryFolder = $this->getBackendUser()->getDefaultUploadTemporaryFolder();
1199  $defaultImportExportFolder = null;
1200  $importExportFolderName = 'importexport';
1201  if ($defaultTemporaryFolder !== null) {
1202  if ($defaultTemporaryFolder->hasFolder($importExportFolderName) === false) {
1203  $defaultImportExportFolder = $defaultTemporaryFolder->createFolder($importExportFolderName);
1204  } else {
1205  $defaultImportExportFolder = $defaultTemporaryFolder->getSubfolder($importExportFolderName);
1206  }
1207  }
1208  $this->defaultImportExportFolder = $defaultImportExportFolder;
1209  }
1210 
1211  public function removeDefaultImportExportFolder(): void
1212  {
1213  if (!empty($this->defaultImportExportFolder)) {
1214  $this->defaultImportExportFolder->delete(true);
1215  $this->defaultImportExportFolder = null;
1216  }
1217  }
1218 
1228  protected function resolveStoragePath(string $dirPrefix, bool $checkAlternatives = true): ?string
1229  {
1230  try {
1231  GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier($dirPrefix);
1232  return $dirPrefix;
1233  } catch (InsufficientFolderAccessPermissionsException $e) {
1234  if ($checkAlternatives) {
1235  $storagesByUser = $this->getBackendUser()->getFileStorages();
1236  foreach ($storagesByUser as $storage) {
1237  try {
1238  $folder = $storage->getFolder(rtrim($dirPrefix, '/'));
1239  return $folder->getPublicUrl();
1240  } catch (InsufficientFolderAccessPermissionsException $e) {
1241  }
1242  }
1243  }
1244  }
1245  return null;
1246  }
1247 
1255  protected function flatInversePageTree(array $pageTree, array &$list, int $pid = -1): void
1256  {
1257  // @todo: return $list instead of by-reference?!
1258  $pageTreeInverse = array_reverse($pageTree);
1259  foreach ($pageTreeInverse as $page) {
1260  $list[$page['uid']] = $pid;
1261  if (is_array($page['subrow'] ?? null)) {
1262  $this->flatInversePageTree($page['subrow'], $list, (int)$page['uid']);
1263  }
1264  }
1265  }
1266 
1273  protected function isTableStatic(string $table): bool
1274  {
1275  if (is_array($GLOBALS['TCA'][$table] ?? null)) {
1276  return ($GLOBALS['TCA'][$table]['ctrl']['is_static'] ?? false)
1277  || in_array($table, $this->relStaticTables, true)
1278  || in_array('_ALL', $this->relStaticTables, true);
1279  }
1280  return false;
1281  }
1282 
1290  protected function isRecordExcluded(string $table, int $uid): bool
1291  {
1292  return (bool)($this->excludeMap[$table . ':' . $uid] ?? false);
1293  }
1294 
1301  protected function isSoftRefIncluded(string $tokenID): bool
1302  {
1303  $mode = $this->softrefCfg[$tokenID]['mode'] ?? '';
1304  return $tokenID && $mode !== Import::SOFTREF_IMPORT_MODE_EXCLUDE && $mode !== Import::SOFTREF_IMPORT_MODE_EDITABLE;
1305  }
1306 
1315  protected function getRecordFromDatabase(string $table, int $uid, string $fields = 'uid,pid'): ?array
1316  {
1317  return BackendUtility::getRecord($table, $uid, $fields);
1318  }
1319 
1326  protected function getRecordPath(int $pid): string
1327  {
1328  if (!isset($this->cacheGetRecordPath[$pid])) {
1329  $this->cacheGetRecordPath[$pid] = (string)BackendUtility::getRecordPath($pid, $this->permsClause, 20);
1330  }
1331  return $this->cacheGetRecordPath[$pid];
1332  }
1333 
1344  protected function compareRecords(array $databaseRecord, array $importRecord, string $table, bool $inverse = false): string
1345  {
1346  $diffHtml = '';
1347 
1348  // Updated fields
1349  foreach ($databaseRecord as $fieldName => $_) {
1350  if (is_array($GLOBALS['TCA'][$table]['columns'][$fieldName] ?? null)
1351  && $GLOBALS['TCA'][$table]['columns'][$fieldName]['config']['type'] !== 'passthrough'
1352  ) {
1353  if (isset($importRecord[$fieldName])) {
1354  if (trim((string)$databaseRecord[$fieldName]) !== trim((string)$importRecord[$fieldName])) {
1355  $diffFieldHtml = $this->getDiffUtility()->makeDiffDisplay(
1356  (string)BackendUtility::getProcessedValue(
1357  $table,
1358  $fieldName,
1359  !$inverse ? $importRecord[$fieldName] : $databaseRecord[$fieldName],
1360  0,
1361  true,
1362  true
1363  ),
1364  (string)BackendUtility::getProcessedValue(
1365  $table,
1366  $fieldName,
1367  !$inverse ? $databaseRecord[$fieldName] : $importRecord[$fieldName],
1368  0,
1369  true,
1370  true
1371  )
1372  );
1373  $diffHtml .= sprintf(
1374  '<tr><td>%s (%s)</td><td>%s</td></tr>' . PHP_EOL,
1375  htmlspecialchars($this->lang->sL($GLOBALS['TCA'][$table]['columns'][$fieldName]['label'])),
1376  htmlspecialchars((string)$fieldName),
1377  $diffFieldHtml
1378  );
1379  }
1380  unset($importRecord[$fieldName]);
1381  }
1382  }
1383  }
1384 
1385  // New fields
1386  foreach ($importRecord as $fieldName => $_) {
1387  if (is_array($GLOBALS['TCA'][$table]['columns'][$fieldName] ?? null)
1388  && $GLOBALS['TCA'][$table]['columns'][$fieldName]['config']['type'] !== 'passthrough'
1389  ) {
1390  $diffFieldHtml = '<strong>Field missing</strong> in database';
1391  $diffHtml .= sprintf(
1392  '<tr><td>%s (%s)</td><td>%s</td></tr>' . PHP_EOL,
1393  htmlspecialchars($this->lang->sL($GLOBALS['TCA'][$table]['columns'][$fieldName]['label'])),
1394  htmlspecialchars((string)$fieldName),
1395  $diffFieldHtml
1396  );
1397  }
1398  }
1399 
1400  if ($diffHtml !== '') {
1401  $diffHtml = '<table class="table table-striped table-hover">' . PHP_EOL . $diffHtml . '</table>';
1402  } else {
1403  $diffHtml = 'Match';
1404  }
1405 
1406  return sprintf(
1407  '<strong class="text-nowrap">[%s]:</strong>' . PHP_EOL . '%s',
1408  htmlspecialchars($table . ':' . $importRecord['uid'] . ' => ' . $databaseRecord['uid']),
1409  $diffHtml
1410  );
1411  }
1412 
1418  protected function getDiffUtility(): DiffUtility
1419  {
1420  if ($this->diffUtility === null) {
1421  $this->diffUtility = GeneralUtility::makeInstance(DiffUtility::class);
1422  }
1423  return $this->diffUtility;
1424  }
1425 
1431  protected function getFileProcObj(): ExtendedFileUtility
1432  {
1433  if ($this->fileProcObj === null) {
1434  $this->fileProcObj = GeneralUtility::makeInstance(ExtendedFileUtility::class);
1435  $this->fileProcObj->setActionPermissions();
1436  }
1437  return $this->fileProcObj;
1438  }
1439 
1445  protected function getStorageRepository(): StorageRepository
1446  {
1447  if ($this->storageRepository === null) {
1448  $this->storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
1449  }
1450  return $this->storageRepository;
1451  }
1453  /*****************************
1454  * Error handling
1455  *****************************/
1456 
1462  protected function addError(string $message): void
1463  {
1464  $this->errorLog[] = $message;
1465  }
1466 
1467  public function hasErrors(): bool
1468  {
1469  return empty($this->errorLog) === false;
1470  }
1471 
1472  protected function getBackendUser(): BackendUserAuthentication
1473  {
1474  return $GLOBALS['BE_USER'];
1475  }
1476 
1477  protected function getLanguageService(): LanguageService
1478  {
1479  return $GLOBALS['LANG'];
1480  }
1481 
1482  public function getPid(): int
1483  {
1484  return $this->pid;
1485  }
1486 
1487  public function setPid(int $pid): void
1488  {
1489  $this->pid = $pid;
1490  $this->pidRecord = null;
1491  }
1500  protected function getPidRecord(): ?array
1501  {
1502  if ($this->pidRecord === null && $this->pid >= 0) {
1503  $pidRecord = BackendUtility::readPageAccess($this->pid, $this->permsClause);
1504 
1505  if (is_array($pidRecord)) {
1506  if ($this->pid === 0) {
1507  $pidRecord += ['title' => '[root-level]', 'uid' => 0, 'pid' => 0];
1508  }
1509  $this->pidRecord = $pidRecord;
1510  }
1511  }
1513  return $this->pidRecord;
1514  }
1515 
1522  public function setExcludeDisabledRecords(bool $excludeDisabledRecords): void
1523  {
1524  $this->excludeDisabledRecords = $excludeDisabledRecords;
1525  }
1526 
1527  public function isExcludeDisabledRecords(): bool
1528  {
1529  return $this->excludeDisabledRecords;
1530  }
1531 
1532  public function getExcludeMap(): array
1533  {
1534  return $this->excludeMap;
1535  }
1536 
1537  public function setExcludeMap(array $excludeMap): void
1538  {
1539  $this->excludeMap = $excludeMap;
1540  }
1541 
1542  public function getSoftrefCfg(): array
1543  {
1544  return $this->softrefCfg;
1545  }
1546 
1547  public function setSoftrefCfg(array $softrefCfg): void
1548  {
1549  $this->softrefCfg = $softrefCfg;
1550  }
1551 
1552  public function getExtensionDependencies(): array
1553  {
1554  return $this->extensionDependencies;
1555  }
1556 
1557  public function setExtensionDependencies(array $extensionDependencies): void
1558  {
1559  $this->extensionDependencies = $extensionDependencies;
1560  }
1561 
1562  public function isShowStaticRelations(): bool
1563  {
1564  return $this->showStaticRelations;
1565  }
1566 
1567  public function setShowStaticRelations(bool $showStaticRelations): void
1568  {
1569  $this->showStaticRelations = $showStaticRelations;
1570  }
1571 
1572  public function getRelStaticTables(): array
1573  {
1574  return $this->relStaticTables;
1575  }
1576 
1577  public function setRelStaticTables(array $relStaticTables): void
1578  {
1579  $this->relStaticTables = $relStaticTables;
1580  }
1581 
1582  public function getErrorLog(): array
1583  {
1584  return $this->errorLog;
1585  }
1586 
1587  public function setErrorLog(array $errorLog): void
1588  {
1589  $this->errorLog = $errorLog;
1590  }
1591 
1592  public function isUpdate(): bool
1593  {
1594  return $this->update;
1595  }
1596 
1597  public function setUpdate(bool $update): void
1598  {
1599  $this->update = $update;
1600  }
1601 
1602  public function getImportMode(): array
1603  {
1604  return $this->importMode;
1605  }
1606 
1607  public function setImportMode(array $importMode): void
1608  {
1609  $this->importMode = $importMode;
1610  }
1611 
1612  public function isGlobalIgnorePid(): bool
1613  {
1614  return $this->globalIgnorePid;
1615  }
1616 
1617  public function setGlobalIgnorePid(bool $globalIgnorePid): void
1618  {
1619  $this->globalIgnorePid = $globalIgnorePid;
1620  }
1621 
1622  public function isForceAllUids(): bool
1623  {
1624  return $this->forceAllUids;
1625  }
1626 
1627  public function setForceAllUids(bool $forceAllUids): void
1628  {
1629  $this->forceAllUids = $forceAllUids;
1630  }
1631 
1632  public function isShowDiff(): bool
1633  {
1634  return $this->showDiff;
1635  }
1636 
1637  public function setShowDiff(bool $showDiff): void
1638  {
1639  $this->showDiff = $showDiff;
1640  }
1641 
1642  public function getSoftrefInputValues(): array
1643  {
1644  return $this->softrefInputValues;
1645  }
1646 
1647  public function setSoftrefInputValues(array $softrefInputValues): void
1648  {
1649  $this->softrefInputValues = $softrefInputValues;
1650  }
1651 
1652  public function getMode(): string
1653  {
1654  return $this->mode;
1655  }
1656 
1657  public function setMode(string $mode): void
1658  {
1659  $this->mode = $mode;
1660  }
1661 
1662  public function getImportMapId(): array
1663  {
1664  return $this->importMapId;
1665  }
1666 
1667  public function setImportMapId(array $importMapId): void
1668  {
1669  $this->importMapId = $importMapId;
1670  }
1671 
1672  public function getDat(): array
1673  {
1674  return $this->dat;
1675  }
1676 }
‪TYPO3\CMS\Core\Utility\DiffUtility
Definition: DiffUtility.php:27
‪TYPO3\CMS\Impexp\ImportExport\$extensionDependencies
‪array $extensionDependencies
Definition: ImportExport.php:148
‪TYPO3\CMS\Core\DataHandling\PageDoktypeRegistry
Definition: PageDoktypeRegistry.php:35
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static stripPathSitePrefix(string $path)
Definition: PathUtility.php:428
‪TYPO3\CMS\Impexp\ImportExport\$iconFactory
‪IconFactory $iconFactory
Definition: ImportExport.php:194
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:27
‪TYPO3\CMS\Impexp\ImportExport\$pidRecord
‪array $pidRecord
Definition: ImportExport.php:68
‪TYPO3\CMS\Impexp\ImportExport\$showStaticRelations
‪bool $showStaticRelations
Definition: ImportExport.php:74
‪TYPO3\CMS\Impexp\ImportExport\$mode
‪string $mode
Definition: ImportExport.php:51
‪TYPO3\CMS\Impexp\ImportExport\$storageRepository
‪StorageRepository $storageRepository
Definition: ImportExport.php:231
‪TYPO3\CMS\Core\Utility\GeneralUtility\fixed_lgd_cs
‪static string fixed_lgd_cs(string $string, int $chars, string $appendString='...')
Definition: GeneralUtility.php:93
‪TYPO3\CMS\Impexp\ImportExport\addGeneralErrorsByTable
‪addGeneralErrorsByTable(string $table)
Definition: ImportExport.php:456
‪TYPO3\CMS\Impexp\ImportExport\$errorLog
‪array $errorLog
Definition: ImportExport.php:160
‪TYPO3\CMS\Impexp\ImportExport\addError
‪addError(string $message)
Definition: ImportExport.php:1432
‪TYPO3\CMS\Impexp\ImportExport\$forceAllUids
‪bool $forceAllUids
Definition: ImportExport.php:105
‪TYPO3\CMS\Impexp\ImportExport\getLanguageService
‪getLanguageService()
Definition: ImportExport.php:1447
‪TYPO3\CMS\Impexp\Import\IMPORT_MODE_AS_NEW
‪const IMPORT_MODE_AS_NEW
Definition: Import.php:52
‪TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
Definition: InsufficientFolderAccessPermissionsException.php:24
‪TYPO3\CMS\Impexp\ImportExport\traversePageRecords
‪traversePageRecords(array $pageTree, array &$lines)
Definition: ImportExport.php:413
‪TYPO3\CMS\Impexp\ImportExport\traversePageTree
‪traversePageTree(array $pageTree, array &$lines, int $indent=0)
Definition: ImportExport.php:331
‪TYPO3\CMS\Core\Resource\Security\FileNameValidator
Definition: FileNameValidator.php:25
‪TYPO3\CMS\Impexp\ImportExport\getStorageRepository
‪StorageRepository getStorageRepository()
Definition: ImportExport.php:1415
‪TYPO3\CMS\Impexp\ImportExport\renderSoftRefImportTextField
‪string renderSoftRefImportTextField(array $softref)
Definition: ImportExport.php:948
‪TYPO3\CMS\Impexp\ImportExport\$globalIgnorePid
‪bool $globalIgnorePid
Definition: ImportExport.php:99
‪TYPO3\CMS\Impexp\ImportExport\fetchStorages
‪fetchStorages()
Definition: ImportExport.php:251
‪TYPO3\CMS\Impexp\ImportExport\addFiles
‪addFiles(array $relations, array &$lines, int $indent, string $tokenID='')
Definition: ImportExport.php:686
‪TYPO3\CMS\Impexp\ImportExport\$pid
‪int $pid
Definition: ImportExport.php:63
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static getPublicPath()
Definition: Environment.php:187
‪TYPO3\CMS\Impexp\ImportExport\isTableStatic
‪bool isTableStatic(string $table)
Definition: ImportExport.php:1243
‪TYPO3\CMS\Impexp\ImportExport\$diffUtility
‪DiffUtility $diffUtility
Definition: ImportExport.php:182
‪TYPO3\CMS\Impexp\ImportExport\$showDiff
‪bool $showDiff
Definition: ImportExport.php:111
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Impexp\ImportExport\renderImportModeSelector
‪string renderImportModeSelector(string $table, int $uid, bool $doesRecordExist)
Definition: ImportExport.php:1041
‪TYPO3\CMS\Impexp\ImportExport\getRecordPath
‪string getRecordPath(int $pid)
Definition: ImportExport.php:1296
‪TYPO3\CMS\Impexp\ImportExport\renderIndent
‪renderIndent(int $indent)
Definition: ImportExport.php:887
‪TYPO3\CMS\Core\Resource\StorageRepository\findAll
‪list< ResourceStorage > findAll()
Definition: StorageRepository.php:207
‪TYPO3\CMS\Impexp\Import\IMPORT_MODE_FORCE_UID
‪const IMPORT_MODE_FORCE_UID
Definition: Import.php:51
‪TYPO3\CMS\Impexp\ImportExport\excludePageAndRecords
‪excludePageAndRecords(int $pageUid, array $page)
Definition: ImportExport.php:382
‪TYPO3\CMS\Impexp\ImportExport\$lang
‪LanguageService $lang
Definition: ImportExport.php:190
‪TYPO3\CMS\Impexp\ImportExport\$softrefCfg
‪array $softrefCfg
Definition: ImportExport.php:142
‪TYPO3\CMS\Impexp\ImportExport\isRecordDisabled
‪bool isRecordDisabled(string $table, int $uid)
Definition: ImportExport.php:369
‪TYPO3\CMS\Impexp\ImportExport\addSoftRefs
‪addSoftRefs(array $softrefs, array &$lines, int $indent)
Definition: ImportExport.php:806
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:26
‪TYPO3\CMS\Impexp\ImportExport\compareRecords
‪string compareRecords(array $databaseRecord, array $importRecord, string $table, bool $inverse=false)
Definition: ImportExport.php:1314
‪TYPO3\CMS\Impexp\Import\IMPORT_MODE_EXCLUDE
‪const IMPORT_MODE_EXCLUDE
Definition: Import.php:53
‪TYPO3\CMS\Impexp\ImportExport\getRecordFromDatabase
‪array null getRecordFromDatabase(string $table, int $uid, string $fields='uid, pid')
Definition: ImportExport.php:1285
‪TYPO3\CMS\Core\Utility\File\ExtendedFileUtility
Definition: ExtendedFileUtility.php:77
‪TYPO3\CMS\Core\Utility\PathUtility\dirname
‪static dirname(string $path)
Definition: PathUtility.php:243
‪TYPO3\CMS\Impexp\ImportExport\$fileadminFolderName
‪string $fileadminFolderName
Definition: ImportExport.php:200
‪TYPO3\CMS\Impexp\ImportExport\$doesImport
‪bool $doesImport
Definition: ImportExport.php:86
‪TYPO3\CMS\Impexp\ImportExport\$fileProcObj
‪ExtendedFileUtility $fileProcObj
Definition: ImportExport.php:178
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:37
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:41
‪TYPO3\CMS\Backend\Routing\PreviewUriBuilder\create
‪static static create(int $pageId)
Definition: PreviewUriBuilder.php:65
‪TYPO3\CMS\Impexp\ImportExport\$importMapId
‪array $importMapId
Definition: ImportExport.php:154
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:38
‪TYPO3\CMS\Webhooks\Message\$record
‪identifier readonly int readonly array $record
Definition: PageModificationMessage.php:36
‪TYPO3\CMS\Impexp\ImportExport\addRelations
‪addRelations(array $relations, array &$lines, int $indent, array $recursionCheck=[])
Definition: ImportExport.php:610
‪TYPO3\CMS\Impexp\Import\IMPORT_MODE_RESPECT_PID
‪const IMPORT_MODE_RESPECT_PID
Definition: Import.php:55
‪TYPO3\CMS\Impexp\ImportExport\$storagesAvailableForImport
‪ResourceStorage[] $storagesAvailableForImport
Definition: ImportExport.php:222
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:64
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:35
‪TYPO3\CMS\Impexp\ImportExport\__construct
‪__construct()
Definition: ImportExport.php:236
‪TYPO3\CMS\Impexp\Import\IMPORT_MODE_IGNORE_PID
‪const IMPORT_MODE_IGNORE_PID
Definition: Import.php:54
‪TYPO3\CMS\Impexp\ImportExport\$defaultStorage
‪ResourceStorage $defaultStorage
Definition: ImportExport.php:227
‪TYPO3\CMS\Impexp\ImportExport
Definition: ImportExport.php:46
‪TYPO3\CMS\Impexp\ImportExport\$fileIdMap
‪array $fileIdMap
Definition: ImportExport.php:123
‪TYPO3\CMS\Impexp\Import\SOFTREF_IMPORT_MODE_EDITABLE
‪const SOFTREF_IMPORT_MODE_EDITABLE
Definition: Import.php:58
‪TYPO3\CMS\Impexp\ImportExport\renderSelectBox
‪string renderSelectBox(string $name, string $value, array $options)
Definition: ImportExport.php:1074
‪TYPO3\CMS\Impexp\ImportExport\$update
‪bool $update
Definition: ImportExport.php:80
‪TYPO3\CMS\Impexp\ImportExport\$permsClause
‪string $permsClause
Definition: ImportExport.php:57
‪TYPO3\CMS\Impexp\ImportExport\$relStaticTables
‪array $relStaticTables
Definition: ImportExport.php:130
‪TYPO3\CMS\Impexp\Import\SOFTREF_IMPORT_MODE_EXCLUDE
‪const SOFTREF_IMPORT_MODE_EXCLUDE
Definition: Import.php:57
‪TYPO3\CMS\Impexp\ImportExport\$defaultImportExportFolder
‪Folder $defaultImportExportFolder
Definition: ImportExport.php:203
‪TYPO3\CMS\Impexp\ImportExport\getPidRecord
‪getPidRecord()
Definition: ImportExport.php:1470
‪TYPO3\CMS\Impexp\ImportExport\$excludeDisabledRecords
‪bool $excludeDisabledRecords
Definition: ImportExport.php:210
‪TYPO3\CMS\Impexp\ImportExport\$remainHeader
‪array $remainHeader
Definition: ImportExport.php:186
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:127
‪TYPO3\CMS\Impexp\ImportExport\$temporaryFolderName
‪string $temporaryFolderName
Definition: ImportExport.php:202
‪TYPO3\CMS\Webhooks\Message\$uid
‪identifier readonly int $uid
Definition: PageModificationMessage.php:35
‪TYPO3\CMS\Impexp\ImportExport\isSoftRefIncluded
‪bool isSoftRefIncluded(string $tokenID)
Definition: ImportExport.php:1271
‪TYPO3\CMS\Core\Resource\StorageRepository\flush
‪flush()
Definition: StorageRepository.php:170
‪TYPO3\CMS\Impexp\ImportExport\addRecord
‪addRecord(string $table, int $uid, array &$lines, int $indent, bool $checkImportInPidRecord=false)
Definition: ImportExport.php:475
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Backend\Routing\PreviewUriBuilder
Definition: PreviewUriBuilder.php:44
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Impexp\ImportExport\resolveStoragePath
‪string resolveStoragePath(string $dirPrefix, bool $checkAlternatives=true)
Definition: ImportExport.php:1198
‪TYPO3\CMS\Impexp\ImportExport\$importMode
‪array $importMode
Definition: ImportExport.php:93
‪TYPO3\CMS\Impexp\ImportExport\$cacheGetRecordPath
‪array $cacheGetRecordPath
Definition: ImportExport.php:166
‪TYPO3\CMS\Impexp\ImportExport\checkDokType
‪bool checkDokType(string $table, int $dokType)
Definition: ImportExport.php:899
‪TYPO3\CMS\Impexp\ImportExport\$excludeMap
‪array $excludeMap
Definition: ImportExport.php:136
‪TYPO3\CMS\Impexp\ImportExport\renderControls
‪string renderControls(array $line)
Definition: ImportExport.php:910
‪TYPO3\CMS\Impexp\ImportExport\getFileProcObj
‪ExtendedFileUtility getFileProcObj()
Definition: ImportExport.php:1401
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Impexp\ImportExport\$dat
‪array $dat
Definition: ImportExport.php:172
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Impexp\ImportExport\renderRecordExcludeCheckbox
‪string renderRecordExcludeCheckbox(string $recordRef)
Definition: ImportExport.php:933
‪TYPO3\CMS\Impexp\ImportExport\renderSoftRefExportSelector
‪string renderSoftRefExportSelector(array $softref)
Definition: ImportExport.php:978
‪TYPO3\CMS\Impexp\ImportExport\isRecordExcluded
‪bool isRecordExcluded(string $table, int $uid)
Definition: ImportExport.php:1260
‪TYPO3\CMS\Impexp
‪TYPO3\CMS\Impexp\ImportExport\$storages
‪ResourceStorage[] $storages
Definition: ImportExport.php:216
‪TYPO3\CMS\Impexp\ImportExport\getBackendUser
‪getBackendUser()
Definition: ImportExport.php:1442
‪TYPO3\CMS\Impexp\ImportExport\traverseAllRecords
‪traverseAllRecords(array $pageTree, array &$lines)
Definition: ImportExport.php:439
‪TYPO3\CMS\Impexp\ImportExport\$softrefInputValues
‪array $softrefInputValues
Definition: ImportExport.php:117
‪TYPO3\CMS\Impexp\ImportExport\renderPreview
‪array renderPreview()
Definition: ImportExport.php:281