‪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;
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 
251  protected ‪$storagesAvailableForImport = [];
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->lang->includeLLFile('EXT:impexp/Resources/Private/Language/locallang.xlf');
271  $this->permsClause = $this->‪getBackendUser()->getPagePermsClause(‪Permission::PAGE_SHOW);
272 
273  $this->‪fetchStorages();
274  }
275 
282  protected function ‪fetchStorages(): void
283  {
284  $this->storages = [];
285  $this->storagesAvailableForImport = [];
286  $this->defaultStorage = null;
287 
288  $this->‪getStorageRepository()->‪flush();
289 
290  $storages = $this->‪getStorageRepository()->‪findAll();
291  // @todo: Why by reference here? Test ImagesWithStoragesTest::importMultipleImagesWithMultipleStorages fails otherwise
292  foreach ($storages as &$storage) {
293  $this->storages[$storage->getUid()] = $storage;
294  if ($storage->isOnline() && $storage->isWritable() && $storage->getDriverType() === 'Local') {
295  $this->storagesAvailableForImport[$storage->getUid()] = $storage;
296  }
297  if ($this->defaultStorage === null && $storage->isDefault()) {
298  $this->defaultStorage = $storage;
299  }
300  }
301  }
302 
303  /********************************************************
304  * Visual rendering of import/export memory, $this->dat
305  ********************************************************/
306 
312  public function ‪renderPreview(): array
313  {
314  // @todo: Why is this done?
315  unset($this->dat['files']);
316 
317  $previewData = [
318  'update' => ‪$this->update,
319  'showDiff' => ‪$this->showDiff,
320  'insidePageTree' => [],
321  'outsidePageTree' => [],
322  ];
323 
324  if (!isset($this->dat['header']['pagetree']) && !isset($this->dat['header']['records'])) {
325  return $previewData;
326  }
327 
328  // Traverse header:
329  $this->remainHeader = $this->dat['header'];
330 
331  // Preview of the page tree to be exported
332  if (is_array($this->dat['header']['pagetree'] ?? null)) {
333  $this->‪traversePageTree($this->dat['header']['pagetree'], $previewData['insidePageTree']);
334  foreach ($previewData['insidePageTree'] as &$line) {
335  $line['controls'] = $this->‪renderControls($line);
336  $line['message'] = (($line['msg'] ?? '') && !$this->doesImport ? '<span class="text-danger">' . htmlspecialchars($line['msg']) . '</span>' : '');
337  }
338  }
339 
340  // Preview the remaining records that were not included in the page tree
341  if (is_array($this->remainHeader['records'] ?? null)) {
342  if (is_array($this->remainHeader['records']['pages'] ?? null)) {
343  $this->‪traversePageRecords($this->remainHeader['records']['pages'], $previewData['outsidePageTree']);
344  }
345  $this->‪traverseAllRecords($this->remainHeader['records'], $previewData['outsidePageTree']);
346  foreach ($previewData['outsidePageTree'] as &$line) {
347  $line['controls'] = $this->‪renderControls($line);
348  $line['message'] = (($line['msg'] ?? '') && !$this->doesImport ? '<span class="text-danger">' . htmlspecialchars($line['msg']) . '</span>' : '');
349  }
350  }
351 
352  return $previewData;
353  }
354 
362  protected function ‪traversePageTree(array $pageTree, array &$lines, int $indent = 0): void
363  {
364  foreach ($pageTree as $pageUid => $page) {
365  if ($this->excludeDisabledRecords === true && $this->‪isRecordDisabled('pages', $pageUid)) {
366  $this->‪excludePageAndRecords($pageUid, $page);
367  continue;
368  }
369 
370  // Add page
371  $this->‪addRecord('pages', $pageUid, $lines, $indent);
372 
373  // Add records
374  if (is_array($this->dat['header']['pid_lookup'][$pageUid] ?? null)) {
375  foreach ($this->dat['header']['pid_lookup'][$pageUid] as $table => $records) {
376  $table = (string)$table;
377  if ($table !== 'pages') {
378  foreach (array_keys($records) as $uid) {
379  $this->‪addRecord($table, (int)$uid, $lines, $indent + 2);
380  }
381  }
382  }
383  unset($this->remainHeader['pid_lookup'][$pageUid]);
384  }
385 
386  // Add subtree
387  if (is_array($page['subrow'] ?? null)) {
388  $this->‪traversePageTree($page['subrow'], $lines, $indent + 2);
389  }
390  }
391  }
392 
400  protected function ‪isRecordDisabled(string $table, int $uid): bool
401  {
402  return (bool)($this->dat['records'][$table . ':' . $uid]['data'][
403  ‪$GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled'] ?? ''
404  ] ?? false);
405  }
406 
413  protected function ‪excludePageAndRecords(int $pageUid, array $page): void
414  {
415  // Exclude page
416  unset($this->remainHeader['records']['pages'][$pageUid]);
417 
418  // Exclude records
419  if (is_array($this->dat['header']['pid_lookup'][$pageUid] ?? null)) {
420  foreach ($this->dat['header']['pid_lookup'][$pageUid] as $table => $records) {
421  if ($table !== 'pages') {
422  foreach (array_keys($records) as $uid) {
423  unset($this->remainHeader['records'][$table][$uid]);
424  }
425  }
426  }
427  unset($this->remainHeader['pid_lookup'][$pageUid]);
428  }
429 
430  // Exclude subtree
431  if (is_array($page['subrow'] ?? null)) {
432  foreach ($page['subrow'] as $subPageUid => $subPage) {
433  $this->‪excludePageAndRecords($subPageUid, $subPage);
434  }
435  }
436  }
437 
444  protected function ‪traversePageRecords(array $pageTree, array &$lines): void
445  {
446  foreach ($pageTree as $pageUid => $_) {
447  // Add page
448  $this->‪addRecord('pages', (int)$pageUid, $lines, 0, true);
449 
450  // Add records
451  if (is_array($this->dat['header']['pid_lookup'][$pageUid] ?? null)) {
452  foreach ($this->dat['header']['pid_lookup'][$pageUid] as $table => $records) {
453  if ($table !== 'pages') {
454  foreach (array_keys($records) as $uid) {
455  $this->‪addRecord((string)$table, (int)$uid, $lines, 2);
456  }
457  }
458  }
459  unset($this->remainHeader['pid_lookup'][$pageUid]);
460  }
461  }
462  }
463 
470  protected function ‪traverseAllRecords(array $pageTree, array &$lines): void
471  {
472  foreach ($pageTree as $table => $records) {
473  $this->‪addGeneralErrorsByTable($table);
474  if ($table !== 'pages') {
475  foreach (array_keys($records) as $uid) {
476  $this->‪addRecord((string)$table, (int)$uid, $lines, 0, true);
477  }
478  }
479  }
480  }
481 
487  protected function ‪addGeneralErrorsByTable(string $table): void
488  {
489  if ($this->update && $table === 'sys_file') {
490  $this->‪addError('Updating sys_file records is not supported! They will be imported as new records!');
491  }
492  if ($this->forceAllUids && $table === 'sys_file') {
493  $this->‪addError('Forcing uids of sys_file records is not supported! They will be imported as new records!');
494  }
495  }
496 
506  protected function ‪addRecord(string $table, int $uid, array &$lines, int $indent, bool $checkImportInPidRecord = false): void
507  {
508  $record = $this->dat['header']['records'][$table][$uid] ?? null;
509  unset($this->remainHeader['records'][$table][$uid]);
510  if (!is_array($record) && !($table === 'pages' && $uid === 0)) {
511  $this->‪addError('MISSING RECORD: ' . $table . ':' . $uid);
512  }
513 
514  // Create record information for preview
515  $line = [];
516  $line['ref'] = $table . ':' . $uid;
517  $line['type'] = 'record';
518  $line['msg'] = '';
519  if ($table === '_SOFTREF_') {
520  // Record is a soft reference
521  $line['preCode'] = $this->‪renderIndent($indent);
522  $line['title'] = '<em>' . htmlspecialchars($this->lang->getLL('impexpcore_singlereco_softReferencesFiles')) . '</em>';
523  } elseif (!isset(‪$GLOBALS['TCA'][$table])) {
524  // Record is of unknown table
525  $line['preCode'] = $this->‪renderIndent($indent);
526  $line['title'] = '<em>' . htmlspecialchars((string)$record['title']) . '</em>';
527  $line['msg'] = 'UNKNOWN TABLE "' . $line['ref'] . '"';
528  } else {
529  ‪$pidRecord = $this->‪getPidRecord();
530  $icon = $this->iconFactory->getIconForRecord(
531  $table,
532  (array)($this->dat['records'][$table . ':' . $uid]['data'] ?? []),
534  )->render();
535  $line['preCode'] = sprintf(
536  '%s<span title="%s">%s</span>',
537  $this->‪renderIndent($indent),
538  htmlspecialchars($line['ref']),
539  $icon
540  );
541  $line['title'] = htmlspecialchars($record['title'] ?? '');
542  // Link to page view
543  if ($table === 'pages') {
544  $viewID = $this->mode === 'export' ? $uid : ($this->doesImport ? ($this->importMapId['pages'][$uid] ?? 0) : 0);
545  if ($viewID) {
546  $attributes = ‪PreviewUriBuilder::create($viewID)->serializeDispatcherAttributes();
547  $line['title'] = sprintf('<a href="#" %s>%s</a>', $attributes, $line['title']);
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  }
602  $importRecord = $this->dat['records'][$table . ':' . $uid]['data'] ?? null;
603  if (is_array($databaseRecord) && is_array($importRecord)) {
604  $line['showDiffContent'] = $this->‪compareRecords($databaseRecord, $importRecord, $table, $diffInverse);
605  } else {
606  $line['showDiffContent'] = 'ERROR: One of the inputs were not an array!';
607  }
608  }
609  }
610  }
611  $lines[] = $line;
612 
613  // File relations
614  if (is_array($record['filerefs'] ?? null)) {
615  $this->‪addFiles($record['filerefs'], $lines, $indent);
616  }
617  // Database relations
618  if (is_array($record['rels'] ?? null)) {
619  $this->‪addRelations($record['rels'], $lines, $indent);
620  }
621  // Soft references
622  if (is_array($record['softrefs'] ?? null)) {
623  $this->‪addSoftRefs($record['softrefs'], $lines, $indent);
624  }
625  }
626 
637  protected function ‪addRelations(array $relations, array &$lines, int $indent, array $recursionCheck = []): void
638  {
639  foreach ($relations as $relation) {
640  $table = $relation['table'];
641  $uid = $relation['id'];
642  $line = [];
643  $line['ref'] = $table . ':' . $uid;
644  $line['type'] = 'rel';
645  $line['msg'] = '';
646  if (in_array($line['ref'], $recursionCheck, true)) {
647  continue;
648  }
649  $iconName = 'status-status-checked';
650  $iconClass = '';
651  $staticFixed = false;
652  $record = null;
653  if ($uid > 0) {
654  $record = $this->dat['header']['records'][$table][$uid] ?? null;
655  if (!is_array($record)) {
656  if ($this->‪isTableStatic($table) || $this->‪isRecordExcluded($table, (int)$uid)
657  || ($relation['tokenID'] ?? '') && !$this->‪isSoftRefIncluded($relation['tokenID'] ?? '')) {
658  $line['title'] = htmlspecialchars('STATIC: ' . $line['ref']);
659  $iconClass = 'text-info';
660  $staticFixed = true;
661  } else {
662  $databaseRecord = $this->‪getRecordFromDatabase($table, (int)$uid);
663  $recordPath = $this->‪getRecordPath($databaseRecord === null ? 0 : ($table === 'pages' ? (int)$databaseRecord['uid'] : (int)$databaseRecord['pid']));
664  $line['title'] = sprintf(
665  '<span title="%s">%s</span>',
666  htmlspecialchars($recordPath),
667  htmlspecialchars($line['ref'])
668  );
669  $line['msg'] = 'LOST RELATION' . ($databaseRecord === null ? ' (Record not found!)' : ' (Path: ' . $recordPath . ')');
670  $iconClass = 'text-danger';
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  $icon = $this->iconFactory->getIcon($iconName, ‪Icon::SIZE_SMALL)->render();
690  $line['preCode'] = sprintf(
691  '%s<span class="%s" title="%s">%s</span>',
692  $this->‪renderIndent($indent + 2),
693  $iconClass,
694  htmlspecialchars($line['ref']),
695  $icon
696  );
697  if (!$staticFixed || $this->showStaticRelations) {
698  $lines[] = $line;
699  if (is_array($record) && is_array($record['rels'] ?? null)) {
700  $this->‪addRelations($record['rels'], $lines, $indent + 1, array_merge($recursionCheck, [$line['ref']]));
701  }
702  }
703  }
704  }
705 
718  public function ‪addFiles(array $relations, array &$lines, int $indent, string $tokenID = ''): void
719  {
720  foreach ($relations as $ID) {
721  $line = [];
722  $line['msg'] = '';
723  $fileInfo = $this->dat['header']['files'][$ID];
724  if (!is_array($fileInfo)) {
725  if ($tokenID !== '' || $this->‪isSoftRefIncluded($tokenID)) {
726  $line['msg'] = 'MISSING FILE: ' . $ID;
727  $this->‪addError('MISSING FILE: ' . $ID);
728  } else {
729  return;
730  }
731  }
732  $line['ref'] = 'FILE';
733  $line['type'] = 'file';
734  $line['preCode'] = sprintf(
735  '%s<span title="%s">%s</span>',
736  $this->‪renderIndent($indent + 2),
737  htmlspecialchars($line['ref']),
738  $this->iconFactory->getIcon('status-reference-hard', ‪Icon::SIZE_SMALL)->render()
739  );
740  $line['title'] = htmlspecialchars($fileInfo['filename']);
741  $line['showDiffContent'] = ‪PathUtility::stripPathSitePrefix((string)($this->fileIdMap[$ID] ?? ''));
742  // If import mode and there is a non-RTE soft reference, check the destination directory.
743  if ($this->mode === 'import' && $tokenID !== '' && !($fileInfo['RTE_ORIG_ID'] ?? false)) {
744  // Check folder existence
745  if (isset($fileInfo['parentRelFileName'])) {
746  $line['msg'] = 'Seems like this file is already referenced from within an HTML/CSS file. That takes precedence. ';
747  } else {
748  $origDirPrefix = ‪PathUtility::dirname($fileInfo['relFileName']) . '/';
749  $dirPrefix = $this->‪resolveStoragePath($origDirPrefix);
750  if ($dirPrefix === null) {
751  $line['msg'] = 'ERROR: There are no available file mounts to write file in! ';
752  } elseif ($origDirPrefix !== $dirPrefix) {
753  $line['msg'] = 'File will be attempted written to "' . $dirPrefix . '". ';
754  }
755  }
756  // Check file existence
757  if (file_exists(‪Environment::getPublicPath() . '/' . $fileInfo['relFileName'])) {
758  if ($this->update) {
759  $line['updatePath'] .= 'File exists.';
760  } else {
761  $line['msg'] .= 'File already exists! ';
762  }
763  }
764  // Check file extension
766  if ($fileProcObj->actionPerms['addFile']) {
767  $pathInfo = GeneralUtility::split_fileref(‪Environment::getPublicPath() . '/' . $fileInfo['relFileName']);
768  if (!GeneralUtility::makeInstance(FileNameValidator::class)->isValid($pathInfo['file'])) {
769  $line['msg'] .= 'File extension was not allowed!';
770  }
771  } else {
772  $line['msg'] = 'Your user profile does not allow you to create files on the server!';
773  }
774  }
775  $lines[] = $line;
776  unset($this->remainHeader['files'][$ID]);
777 
778  // RTE originals
779  if ($fileInfo['RTE_ORIG_ID'] ?? false) {
780  $ID = $fileInfo['RTE_ORIG_ID'];
781  $line = [];
782  $fileInfo = $this->dat['header']['files'][$ID];
783  if (!is_array($fileInfo)) {
784  $line['msg'] = 'MISSING RTE original FILE: ' . $ID;
785  $this->‪addError('MISSING RTE original FILE: ' . $ID);
786  }
787  $line['ref'] = 'FILE';
788  $line['type'] = 'file';
789  $line['preCode'] = sprintf(
790  '%s<span title="%s">%s</span>',
791  $this->‪renderIndent($indent + 4),
792  htmlspecialchars($line['ref']),
793  $this->iconFactory->getIcon('status-reference-hard', ‪Icon::SIZE_SMALL)->render()
794  );
795  $line['title'] = htmlspecialchars($fileInfo['filename']) . ' <em>(Original)</em>';
796  $line['showDiffContent'] = ‪PathUtility::stripPathSitePrefix($this->fileIdMap[$ID]);
797  $lines[] = $line;
798  unset($this->remainHeader['files'][$ID]);
799  }
800 
801  // External resources
802  if (is_array($fileInfo['EXT_RES_ID'] ?? null)) {
803  foreach ($fileInfo['EXT_RES_ID'] as $extID) {
804  $line = [];
805  $fileInfo = $this->dat['header']['files'][$extID];
806  if (!is_array($fileInfo)) {
807  $line['msg'] = 'MISSING External Resource FILE: ' . $extID;
808  $this->‪addError('MISSING External Resource FILE: ' . $extID);
809  } else {
810  $line['updatePath'] = $fileInfo['parentRelFileName'];
811  }
812  $line['ref'] = 'FILE';
813  $line['type'] = 'file';
814  $line['preCode'] = sprintf(
815  '%s<span title="%s">%s</span>',
816  $this->‪renderIndent($indent + 4),
817  htmlspecialchars($line['ref']),
818  $this->iconFactory->getIcon('actions-insert-reference', ‪Icon::SIZE_SMALL)->render()
819  );
820  $line['title'] = htmlspecialchars($fileInfo['filename']) . ' <em>(Resource)</em>';
821  $line['showDiffContent'] = ‪PathUtility::stripPathSitePrefix($this->fileIdMap[$extID]);
822  $lines[] = $line;
823  unset($this->remainHeader['files'][$extID]);
824  }
825  }
826  }
827  }
828 
838  protected function ‪addSoftRefs(array $softrefs, array &$lines, int $indent): void
839  {
840  foreach ($softrefs as $softref) {
841  $line = [];
842  $line['ref'] = 'SOFTREF';
843  $line['type'] = 'softref';
844  $line['msg'] = '';
845  $line['preCode'] = sprintf(
846  '%s<span title="%s">%s</span>',
847  $this->‪renderIndent($indent + 2),
848  htmlspecialchars($line['ref']),
849  $this->iconFactory->getIcon('status-reference-soft', ‪Icon::SIZE_SMALL)->render()
850  );
851  $line['title'] = sprintf(
852  '<em>%s, "%s"</em> : <span title="%s">%s</span>',
853  $softref['field'],
854  $softref['spKey'],
855  htmlspecialchars($softref['matchString'] ?? ''),
856  htmlspecialchars(‪GeneralUtility::fixed_lgd_cs($softref['matchString'] ?? '', 60))
857  );
858  if ($softref['subst']['type'] ?? false) {
859  if ($softref['subst']['title'] ?? false) {
860  $line['title'] .= sprintf(
861  '<br/>%s<strong>%s</strong> %s',
862  $this->‪renderIndent($indent + 4),
863  htmlspecialchars($this->lang->getLL('impexpcore_singlereco_title')),
864  htmlspecialchars(‪GeneralUtility::fixed_lgd_cs($softref['subst']['title'], 60))
865  );
866  }
867  if ($softref['subst']['description'] ?? false) {
868  $line['title'] .= sprintf(
869  '<br/>%s<strong>%s</strong> %s',
870  $this->‪renderIndent($indent + 4),
871  htmlspecialchars($this->lang->getLL('impexpcore_singlereco_descr')),
872  htmlspecialchars(‪GeneralUtility::fixed_lgd_cs($softref['subst']['description'], 60))
873  );
874  }
875  if ($softref['subst']['type'] === 'db') {
876  $line['title'] .= sprintf(
877  '<br/>%s%s <strong>%s</strong>',
878  $this->‪renderIndent($indent + 4),
879  htmlspecialchars($this->lang->getLL('impexpcore_softrefsel_record')),
880  $softref['subst']['recordRef']
881  );
882  } elseif ($softref['subst']['type'] === 'file') {
883  $line['title'] .= sprintf(
884  '<br/>%s%s <strong>%s</strong>',
885  $this->‪renderIndent($indent + 4),
886  htmlspecialchars($this->lang->getLL('impexpcore_singlereco_filename')),
887  $softref['subst']['relFileName']
888  );
889  } elseif ($softref['subst']['type'] === 'string') {
890  $line['title'] .= sprintf(
891  '<br/>%s%s <strong>%s</strong>',
892  $this->‪renderIndent($indent + 4),
893  htmlspecialchars($this->lang->getLL('impexpcore_singlereco_value')),
894  $softref['subst']['tokenValue']
895  );
896  }
897  }
898  $line['_softRefInfo'] = $softref;
899  ‪$mode = $this->softrefCfg[$softref['subst']['tokenID'] ?? null]['mode'] ?? '';
901  $line['msg'] .= $softref['error'];
902  }
903  $lines[] = $line;
904 
905  // Add database relations
906  if (($softref['subst']['type'] ?? '') === 'db') {
907  [$referencedTable, $referencedUid] = explode(':', $softref['subst']['recordRef']);
908  $relations = [['table' => $referencedTable, 'id' => $referencedUid, 'tokenID' => $softref['subst']['tokenID']]];
909  $this->‪addRelations($relations, $lines, $indent + 4);
910  }
911  // Add files relations
912  if (($softref['subst']['type'] ?? '') === 'file') {
913  $relations = [$softref['file_ID']];
914  $this->‪addFiles($relations, $lines, $indent + 4, $softref['subst']['tokenID']);
915  }
916  }
917  }
918 
919  protected function ‪renderIndent(int $indent): string
920  {
921  return str_repeat('&nbsp;&nbsp;', $indent);
922  }
923 
931  protected function ‪checkDokType(string $table, int $dokType): bool
932  {
933  return GeneralUtility::makeInstance(PageDoktypeRegistry::class)->isRecordTypeAllowedForDoktype($table, $dokType);
934  }
935 
942  protected function ‪renderControls(array $line): string
943  {
944  if ($this->mode === 'export') {
945  if ($line['type'] === 'record') {
946  return $this->‪renderRecordExcludeCheckbox($line['ref']);
947  }
948  if ($line['type'] === 'softref') {
949  return $this->‪renderSoftRefExportSelector($line['_softRefInfo']);
950  }
951  } elseif ($this->mode === 'import') {
952  if ($line['type'] === 'softref') {
953  return $this->‪renderSoftRefImportTextField($line['_softRefInfo']);
954  }
955  }
956  return '';
957  }
958 
965  protected function ‪renderRecordExcludeCheckbox(string $recordRef): string
966  {
967  return sprintf(
968  '
969  <input type="checkbox" class="t3js-exclude-checkbox" name="tx_impexp[exclude][%1$s]" id="checkExclude%1$s" value="1" />
970  <label for="checkExclude%1$s">%2$s</label>',
971  $recordRef,
972  htmlspecialchars($this->lang->getLL('impexpcore_singlereco_exclude'))
973  );
974  }
975 
982  protected function ‪renderSoftRefImportTextField(array $softref): string
983  {
984  if (isset($softref['subst']['tokenID'])) {
985  $tokenID = $softref['subst']['tokenID'];
986  $cfg = $this->softrefCfg[$tokenID] ?? [];
987  if (($cfg['mode'] ?? '') === ‪Import::SOFTREF_IMPORT_MODE_EDITABLE) {
988  $html = '';
989  if ($cfg['title'] ?? false) {
990  $html .= '<strong>' . htmlspecialchars((string)$cfg['title']) . '</strong><br/>';
991  }
992  $html .= htmlspecialchars((string)$cfg['description']) . '<br/>';
993  $html .= sprintf(
994  '<input type="text" name="tx_impexp[softrefInputValues][%s]" value="%s" />',
995  $tokenID,
996  htmlspecialchars($this->softrefInputValues[$tokenID] ?? $cfg['defValue'])
997  );
998  return $html;
999  }
1000  }
1001 
1002  return '';
1003  }
1004 
1012  protected function ‪renderSoftRefExportSelector(array $softref): string
1013  {
1014  $fileInfo = isset($softref['file_ID']) ? $this->dat['header']['files'][$softref['file_ID']] : [];
1015  // Substitution scheme has to be around and RTE images MUST be exported.
1016  if (isset($softref['subst']['tokenID']) && !isset($fileInfo['RTE_ORIG_ID'])) {
1017  $options = [];
1018  $options[''] = '';
1019  $options[‪Import::SOFTREF_IMPORT_MODE_EDITABLE] = $this->lang->getLL('impexpcore_softrefsel_editable');
1020  $options[‪Import::SOFTREF_IMPORT_MODE_EXCLUDE] = $this->lang->getLL('impexpcore_softrefsel_exclude');
1021  $value = $this->softrefCfg[$softref['subst']['tokenID']]['mode'] ?? '';
1022  $selectHtml = $this->‪renderSelectBox(
1023  'tx_impexp[softrefCfg][' . $softref['subst']['tokenID'] . '][mode]',
1024  $value,
1025  $options
1026  ) . '<br/>';
1027  $textFieldHtml = '';
1028  if ($value === ‪Import::SOFTREF_IMPORT_MODE_EDITABLE) {
1029  if ($softref['subst']['title'] ?? false) {
1030  $textFieldHtml .= sprintf(
1031  '
1032  <input type="hidden" name="tx_impexp[softrefCfg][%1$s][title]" value="%2$s" />
1033  <strong>%2$s</strong><br/>',
1034  $softref['subst']['tokenID'],
1035  htmlspecialchars($softref['subst']['title'])
1036  );
1037  }
1038  if (!($softref['subst']['description'] ?? false)) {
1039  $textFieldHtml .= sprintf(
1040  '
1041  %s<br/>
1042  <input type="text" name="tx_impexp[softrefCfg][%s][description]" value="%s" />',
1043  htmlspecialchars($this->lang->getLL('impexpcore_printerror_description')),
1044  $softref['subst']['tokenID'],
1045  htmlspecialchars($this->softrefCfg[$softref['subst']['tokenID']]['description'] ?? '')
1046  );
1047  } else {
1048  $textFieldHtml .= sprintf(
1049  '
1050  <input type="hidden" name="tx_impexp[softrefCfg][%1$s][description]" value="%2$s" />%2$s',
1051  $softref['subst']['tokenID'],
1052  htmlspecialchars($softref['subst']['description'])
1053  );
1054  }
1055  $textFieldHtml .= sprintf(
1056  '
1057  <input type="hidden" name="tx_impexp[softrefCfg][%s][defValue]" value="%s" />',
1058  $softref['subst']['tokenID'],
1059  htmlspecialchars($softref['subst']['tokenValue'])
1060  );
1061  }
1062  return $selectHtml . $textFieldHtml;
1063  }
1064  return '';
1065  }
1066 
1075  protected function ‪renderImportModeSelector(string $table, int $uid, bool $doesRecordExist): string
1076  {
1077  $options = [];
1078  if (!$doesRecordExist) {
1079  $options[] = $this->lang->getLL('impexpcore_singlereco_insert');
1080  if ($this->‪getBackendUser()->isAdmin()) {
1081  $options[‪Import::IMPORT_MODE_FORCE_UID] = sprintf($this->lang->getLL('impexpcore_singlereco_forceUidSAdmin'), $uid);
1082  }
1083  } else {
1084  $options[] = $this->lang->getLL('impexpcore_singlereco_update');
1085  $options[‪Import::IMPORT_MODE_AS_NEW] = $this->lang->getLL('impexpcore_singlereco_importAsNew');
1086  if (!$this->globalIgnorePid) {
1087  $options[‪Import::IMPORT_MODE_IGNORE_PID] = $this->lang->getLL('impexpcore_singlereco_ignorePid');
1088  } else {
1089  $options[‪Import::IMPORT_MODE_RESPECT_PID] = $this->lang->getLL('impexpcore_singlereco_respectPid');
1090  }
1091  }
1092  $options[‪Import::IMPORT_MODE_EXCLUDE] = $this->lang->getLL('impexpcore_singlereco_exclude');
1093  return $this->‪renderSelectBox(
1094  'tx_impexp[import_mode][' . $table . ':' . $uid . ']',
1095  (string)($this->importMode[$table . ':' . $uid] ?? ''),
1096  $options
1097  );
1098  }
1099 
1108  protected function ‪renderSelectBox(string $name, string $value, array $options): string
1109  {
1110  $optionsHtml = '';
1111  $isValueInOptions = false;
1112 
1113  foreach ($options as $k => $v) {
1114  if ((string)$k === $value) {
1115  $isValueInOptions = true;
1116  $selectedHtml = ' selected="selected"';
1117  } else {
1118  $selectedHtml = '';
1119  }
1120  $optionsHtml .= sprintf(
1121  '<option value="%s"%s>%s</option>',
1122  htmlspecialchars((string)$k),
1123  $selectedHtml,
1124  htmlspecialchars((string)$v)
1125  );
1126  }
1127 
1128  // Append and select the current value as an option of the form "[value]"
1129  // if it is not available in the options.
1130  if (!$isValueInOptions && $value !== '') {
1131  $optionsHtml .= sprintf(
1132  '<option value="%s" selected="selected">%s</option>',
1133  htmlspecialchars($value),
1134  htmlspecialchars('[\'' . $value . '\']')
1135  );
1136  }
1137 
1138  return '<select name="' . $name . '">' . $optionsHtml . '</select>';
1139  }
1140 
1141  public function getFileadminFolderName(): string
1142  {
1143  if (empty($this->fileadminFolderName)) {
1144  if (!empty($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'])) {
1145  $this->fileadminFolderName = rtrim($GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'], '/');
1146  } else {
1147  $this->fileadminFolderName = 'fileadmin';
1148  }
1149  }
1150  return $this->fileadminFolderName;
1151  }
1152 
1153  public function getOrCreateTemporaryFolderName(): string
1154  {
1155  if (empty($this->temporaryFolderName)) {
1156  $this->temporaryFolderName = $this->createTemporaryFolderName();
1157  }
1158  return $this->temporaryFolderName;
1159  }
1160 
1161  protected function createTemporaryFolderName(): string
1162  {
1163  $temporaryPath = Environment::getVarPath() . '/transient';
1164  do {
1165  $temporaryFolderName = sprintf(
1166  '%s/impexp_%s_files_%d',
1167  $temporaryPath,
1168  $this->mode,
1169  random_int(1, PHP_INT_MAX)
1170  );
1171  } while (is_dir($temporaryFolderName));
1172  GeneralUtility::mkdir_deep($temporaryFolderName);
1173  return $temporaryFolderName;
1174  }
1175 
1176  public function removeTemporaryFolderName(): void
1177  {
1178  if (!empty($this->temporaryFolderName)) {
1179  GeneralUtility::rmdir($this->temporaryFolderName, true);
1180  $this->temporaryFolderName = null;
1181  }
1182  }
1183 
1188  public function getOrCreateDefaultImportExportFolder(): ?Folder
1189  {
1190  if (empty($this->defaultImportExportFolder)) {
1191  $this->createDefaultImportExportFolder();
1192  }
1193  return $this->defaultImportExportFolder;
1194  }
1195 
1200  protected function createDefaultImportExportFolder(): void
1201  {
1202  $defaultTemporaryFolder = $this->getBackendUser()->getDefaultUploadTemporaryFolder();
1203  $defaultImportExportFolder = null;
1204  $importExportFolderName = 'importexport';
1205  if ($defaultTemporaryFolder !== null) {
1206  if ($defaultTemporaryFolder->hasFolder($importExportFolderName) === false) {
1207  $defaultImportExportFolder = $defaultTemporaryFolder->createFolder($importExportFolderName);
1208  } else {
1209  $defaultImportExportFolder = $defaultTemporaryFolder->getSubfolder($importExportFolderName);
1210  }
1211  }
1212  $this->defaultImportExportFolder = $defaultImportExportFolder;
1213  }
1214 
1215  public function removeDefaultImportExportFolder(): void
1216  {
1217  if (!empty($this->defaultImportExportFolder)) {
1218  $this->defaultImportExportFolder->delete(true);
1219  $this->defaultImportExportFolder = null;
1220  }
1221  }
1222 
1232  protected function resolveStoragePath(string $dirPrefix, bool $checkAlternatives = true): ?string
1233  {
1234  try {
1235  GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier($dirPrefix);
1236  return $dirPrefix;
1237  } catch (InsufficientFolderAccessPermissionsException $e) {
1238  if ($checkAlternatives) {
1239  $storagesByUser = $this->getBackendUser()->getFileStorages();
1240  foreach ($storagesByUser as $storage) {
1241  try {
1242  $folder = $storage->getFolder(rtrim($dirPrefix, '/'));
1243  return $folder->getPublicUrl();
1244  } catch (InsufficientFolderAccessPermissionsException $e) {
1245  }
1246  }
1247  }
1248  }
1249  return null;
1250  }
1251 
1259  protected function flatInversePageTree(array $pageTree, array &$list, int $pid = -1): void
1260  {
1261  // @todo: return $list instead of by-reference?!
1262  $pageTreeInverse = array_reverse($pageTree);
1263  foreach ($pageTreeInverse as $page) {
1264  $list[$page['uid']] = $pid;
1265  if (is_array($page['subrow'] ?? null)) {
1266  $this->flatInversePageTree($page['subrow'], $list, (int)$page['uid']);
1267  }
1268  }
1269  }
1270 
1277  protected function isTableStatic(string $table): bool
1278  {
1279  if (is_array($GLOBALS['TCA'][$table] ?? null)) {
1280  return ($GLOBALS['TCA'][$table]['ctrl']['is_static'] ?? false)
1281  || in_array($table, $this->relStaticTables, true)
1282  || in_array('_ALL', $this->relStaticTables, true);
1283  }
1284  return false;
1285  }
1286 
1294  protected function isRecordExcluded(string $table, int $uid): bool
1295  {
1296  return (bool)($this->excludeMap[$table . ':' . $uid] ?? false);
1297  }
1298 
1305  protected function isSoftRefIncluded(string $tokenID): bool
1306  {
1307  $mode = $this->softrefCfg[$tokenID]['mode'] ?? '';
1308  return $tokenID && $mode !== Import::SOFTREF_IMPORT_MODE_EXCLUDE && $mode !== Import::SOFTREF_IMPORT_MODE_EDITABLE;
1309  }
1310 
1319  protected function getRecordFromDatabase(string $table, int $uid, string $fields = 'uid,pid'): ?array
1320  {
1321  return BackendUtility::getRecord($table, $uid, $fields);
1322  }
1323 
1330  protected function getRecordPath(int $pid): string
1331  {
1332  if (!isset($this->cacheGetRecordPath[$pid])) {
1333  $this->cacheGetRecordPath[$pid] = (string)BackendUtility::getRecordPath($pid, $this->permsClause, 20);
1334  }
1335  return $this->cacheGetRecordPath[$pid];
1336  }
1337 
1348  protected function compareRecords(array $databaseRecord, array $importRecord, string $table, bool $inverse = false): string
1349  {
1350  $diffHtml = '';
1351 
1352  // Updated fields
1353  foreach ($databaseRecord as $fieldName => $_) {
1354  if (is_array($GLOBALS['TCA'][$table]['columns'][$fieldName] ?? null)
1355  && $GLOBALS['TCA'][$table]['columns'][$fieldName]['config']['type'] !== 'passthrough'
1356  ) {
1357  if (isset($importRecord[$fieldName])) {
1358  if (trim((string)$databaseRecord[$fieldName]) !== trim((string)$importRecord[$fieldName])) {
1359  $diffFieldHtml = $this->getDiffUtility()->makeDiffDisplay(
1360  (string)BackendUtility::getProcessedValue(
1361  $table,
1362  $fieldName,
1363  !$inverse ? $importRecord[$fieldName] : $databaseRecord[$fieldName],
1364  0,
1365  true,
1366  true
1367  ),
1368  (string)BackendUtility::getProcessedValue(
1369  $table,
1370  $fieldName,
1371  !$inverse ? $databaseRecord[$fieldName] : $importRecord[$fieldName],
1372  0,
1373  true,
1374  true
1375  )
1376  );
1377  $diffHtml .= sprintf(
1378  '<tr><td>%s (%s)</td><td>%s</td></tr>' . PHP_EOL,
1379  htmlspecialchars($this->lang->sL($GLOBALS['TCA'][$table]['columns'][$fieldName]['label'])),
1380  htmlspecialchars((string)$fieldName),
1381  $diffFieldHtml
1382  );
1383  }
1384  unset($importRecord[$fieldName]);
1385  }
1386  }
1387  }
1388 
1389  // New fields
1390  foreach ($importRecord as $fieldName => $_) {
1391  if (is_array($GLOBALS['TCA'][$table]['columns'][$fieldName] ?? null)
1392  && $GLOBALS['TCA'][$table]['columns'][$fieldName]['config']['type'] !== 'passthrough'
1393  ) {
1394  $diffFieldHtml = '<strong>Field missing</strong> in database';
1395  $diffHtml .= sprintf(
1396  '<tr><td>%s (%s)</td><td>%s</td></tr>' . PHP_EOL,
1397  htmlspecialchars($this->lang->sL($GLOBALS['TCA'][$table]['columns'][$fieldName]['label'])),
1398  htmlspecialchars((string)$fieldName),
1399  $diffFieldHtml
1400  );
1401  }
1402  }
1403 
1404  if ($diffHtml !== '') {
1405  $diffHtml = '<table class="table table-striped table-hover">' . PHP_EOL . $diffHtml . '</table>';
1406  } else {
1407  $diffHtml = 'Match';
1408  }
1409 
1410  return sprintf(
1411  '<strong class="text-nowrap">[%s]:</strong>' . PHP_EOL . '%s',
1412  htmlspecialchars($table . ':' . $importRecord['uid'] . ' => ' . $databaseRecord['uid']),
1413  $diffHtml
1414  );
1415  }
1416 
1422  protected function getDiffUtility(): DiffUtility
1423  {
1424  if ($this->diffUtility === null) {
1425  $this->diffUtility = GeneralUtility::makeInstance(DiffUtility::class);
1426  }
1427  return $this->diffUtility;
1428  }
1429 
1435  protected function getFileProcObj(): ExtendedFileUtility
1436  {
1437  if ($this->fileProcObj === null) {
1438  $this->fileProcObj = GeneralUtility::makeInstance(ExtendedFileUtility::class);
1439  $this->fileProcObj->setActionPermissions();
1440  }
1441  return $this->fileProcObj;
1442  }
1443 
1449  protected function getStorageRepository(): StorageRepository
1450  {
1451  if ($this->storageRepository === null) {
1452  $this->storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
1453  }
1454  return $this->storageRepository;
1455  }
1457  /*****************************
1458  * Error handling
1459  *****************************/
1460 
1466  protected function addError(string $message): void
1467  {
1468  $this->errorLog[] = $message;
1469  }
1470 
1471  public function hasErrors(): bool
1472  {
1473  return empty($this->errorLog) === false;
1474  }
1475 
1476  protected function getBackendUser(): BackendUserAuthentication
1477  {
1478  return $GLOBALS['BE_USER'];
1479  }
1480 
1481  protected function getLanguageService(): LanguageService
1482  {
1483  return $GLOBALS['LANG'];
1484  }
1485 
1486  public function getPid(): int
1487  {
1488  return $this->pid;
1489  }
1490 
1491  public function setPid(int $pid): void
1492  {
1493  $this->pid = $pid;
1494  $this->pidRecord = null;
1495  }
1504  protected function getPidRecord(): ?array
1505  {
1506  if ($this->pidRecord === null && $this->pid >= 0) {
1507  $pidRecord = BackendUtility::readPageAccess($this->pid, $this->permsClause);
1508 
1509  if (is_array($pidRecord)) {
1510  if ($this->pid === 0) {
1511  $pidRecord += ['title' => '[root-level]', 'uid' => 0, 'pid' => 0];
1512  }
1513  $this->pidRecord = $pidRecord;
1514  }
1515  }
1517  return $this->pidRecord;
1518  }
1519 
1526  public function setExcludeDisabledRecords(bool $excludeDisabledRecords): void
1527  {
1528  $this->excludeDisabledRecords = $excludeDisabledRecords;
1529  }
1530 
1531  public function isExcludeDisabledRecords(): bool
1532  {
1533  return $this->excludeDisabledRecords;
1534  }
1535 
1536  public function getExcludeMap(): array
1537  {
1538  return $this->excludeMap;
1539  }
1540 
1541  public function setExcludeMap(array $excludeMap): void
1542  {
1543  $this->excludeMap = $excludeMap;
1544  }
1545 
1546  public function getSoftrefCfg(): array
1547  {
1548  return $this->softrefCfg;
1549  }
1550 
1551  public function setSoftrefCfg(array $softrefCfg): void
1552  {
1553  $this->softrefCfg = $softrefCfg;
1554  }
1555 
1556  public function getExtensionDependencies(): array
1557  {
1558  return $this->extensionDependencies;
1559  }
1560 
1561  public function setExtensionDependencies(array $extensionDependencies): void
1562  {
1563  $this->extensionDependencies = $extensionDependencies;
1564  }
1565 
1566  public function isShowStaticRelations(): bool
1567  {
1568  return $this->showStaticRelations;
1569  }
1570 
1571  public function setShowStaticRelations(bool $showStaticRelations): void
1572  {
1573  $this->showStaticRelations = $showStaticRelations;
1574  }
1575 
1576  public function getRelStaticTables(): array
1577  {
1578  return $this->relStaticTables;
1579  }
1580 
1581  public function setRelStaticTables(array $relStaticTables): void
1582  {
1583  $this->relStaticTables = $relStaticTables;
1584  }
1585 
1586  public function getErrorLog(): array
1587  {
1588  return $this->errorLog;
1589  }
1590 
1591  public function setErrorLog(array $errorLog): void
1592  {
1593  $this->errorLog = $errorLog;
1594  }
1595 
1596  public function isUpdate(): bool
1597  {
1598  return $this->update;
1599  }
1600 
1601  public function setUpdate(bool $update): void
1602  {
1603  $this->update = $update;
1604  }
1605 
1606  public function getImportMode(): array
1607  {
1608  return $this->importMode;
1609  }
1610 
1611  public function setImportMode(array $importMode): void
1612  {
1613  $this->importMode = $importMode;
1614  }
1615 
1616  public function isGlobalIgnorePid(): bool
1617  {
1618  return $this->globalIgnorePid;
1619  }
1620 
1621  public function setGlobalIgnorePid(bool $globalIgnorePid): void
1622  {
1623  $this->globalIgnorePid = $globalIgnorePid;
1624  }
1625 
1626  public function isForceAllUids(): bool
1627  {
1628  return $this->forceAllUids;
1629  }
1630 
1631  public function setForceAllUids(bool $forceAllUids): void
1632  {
1633  $this->forceAllUids = $forceAllUids;
1634  }
1635 
1636  public function isShowDiff(): bool
1637  {
1638  return $this->showDiff;
1639  }
1640 
1641  public function setShowDiff(bool $showDiff): void
1642  {
1643  $this->showDiff = $showDiff;
1644  }
1645 
1646  public function getSoftrefInputValues(): array
1647  {
1648  return $this->softrefInputValues;
1649  }
1650 
1651  public function setSoftrefInputValues(array $softrefInputValues): void
1652  {
1653  $this->softrefInputValues = $softrefInputValues;
1654  }
1655 
1656  public function getMode(): string
1657  {
1658  return $this->mode;
1659  }
1660 
1661  public function setMode(string $mode): void
1662  {
1663  $this->mode = $mode;
1664  }
1665 
1666  public function getImportMapId(): array
1667  {
1668  return $this->importMapId;
1669  }
1670 
1671  public function setImportMapId(array $importMapId): void
1672  {
1673  $this->importMapId = $importMapId;
1674  }
1675 
1676  public function getDat(): array
1677  {
1678  return $this->dat;
1679  }
1680 }
‪TYPO3\CMS\Core\Utility\DiffUtility
Definition: DiffUtility.php:27
‪TYPO3\CMS\Core\Imaging\Icon\SIZE_SMALL
‪const SIZE_SMALL
Definition: Icon.php:35
‪TYPO3\CMS\Impexp\ImportExport\$extensionDependencies
‪array $extensionDependencies
Definition: ImportExport.php:148
‪TYPO3\CMS\Core\DataHandling\PageDoktypeRegistry
Definition: PageDoktypeRegistry.php:36
‪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:202
‪TYPO3\CMS\Impexp\ImportExport\addGeneralErrorsByTable
‪addGeneralErrorsByTable(string $table)
Definition: ImportExport.php:457
‪TYPO3\CMS\Impexp\ImportExport\$errorLog
‪array $errorLog
Definition: ImportExport.php:160
‪TYPO3\CMS\Impexp\ImportExport\addError
‪addError(string $message)
Definition: ImportExport.php:1436
‪TYPO3\CMS\Impexp\ImportExport\$forceAllUids
‪bool $forceAllUids
Definition: ImportExport.php:105
‪TYPO3\CMS\Impexp\ImportExport\getLanguageService
‪getLanguageService()
Definition: ImportExport.php:1451
‪TYPO3\CMS\Impexp\Import\IMPORT_MODE_AS_NEW
‪const IMPORT_MODE_AS_NEW
Definition: Import.php:50
‪TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
Definition: InsufficientFolderAccessPermissionsException.php:24
‪TYPO3\CMS\Impexp\ImportExport\traversePageRecords
‪traversePageRecords(array $pageTree, array &$lines)
Definition: ImportExport.php:414
‪TYPO3\CMS\Impexp\ImportExport\traversePageTree
‪traversePageTree(array $pageTree, array &$lines, int $indent=0)
Definition: ImportExport.php:332
‪TYPO3\CMS\Core\Resource\Security\FileNameValidator
Definition: FileNameValidator.php:25
‪TYPO3\CMS\Core\Imaging\Icon
Definition: Icon.php:26
‪TYPO3\CMS\Impexp\ImportExport\getStorageRepository
‪StorageRepository getStorageRepository()
Definition: ImportExport.php:1419
‪TYPO3\CMS\Impexp\ImportExport\renderSoftRefImportTextField
‪string renderSoftRefImportTextField(array $softref)
Definition: ImportExport.php:952
‪TYPO3\CMS\Impexp\ImportExport\$globalIgnorePid
‪bool $globalIgnorePid
Definition: ImportExport.php:99
‪TYPO3\CMS\Impexp\ImportExport\fetchStorages
‪fetchStorages()
Definition: ImportExport.php:252
‪TYPO3\CMS\Impexp\ImportExport\addFiles
‪addFiles(array $relations, array &$lines, int $indent, string $tokenID='')
Definition: ImportExport.php:688
‪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:1247
‪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:1045
‪TYPO3\CMS\Impexp\ImportExport\getRecordPath
‪string getRecordPath(int $pid)
Definition: ImportExport.php:1300
‪TYPO3\CMS\Impexp\ImportExport\renderIndent
‪renderIndent(int $indent)
Definition: ImportExport.php:889
‪TYPO3\CMS\Impexp\Import\IMPORT_MODE_FORCE_UID
‪const IMPORT_MODE_FORCE_UID
Definition: Import.php:49
‪TYPO3\CMS\Impexp\ImportExport\excludePageAndRecords
‪excludePageAndRecords(int $pageUid, array $page)
Definition: ImportExport.php:383
‪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:370
‪TYPO3\CMS\Impexp\ImportExport\addSoftRefs
‪addSoftRefs(array $softrefs, array &$lines, int $indent)
Definition: ImportExport.php:808
‪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:1318
‪TYPO3\CMS\Impexp\Import\IMPORT_MODE_EXCLUDE
‪const IMPORT_MODE_EXCLUDE
Definition: Import.php:51
‪TYPO3\CMS\Impexp\ImportExport\getRecordFromDatabase
‪array null getRecordFromDatabase(string $table, int $uid, string $fields='uid, pid')
Definition: ImportExport.php:1289
‪TYPO3\CMS\Core\Utility\File\ExtendedFileUtility
Definition: ExtendedFileUtility.php:75
‪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:66
‪TYPO3\CMS\Impexp\ImportExport\$importMapId
‪array $importMapId
Definition: ImportExport.php:154
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:38
‪TYPO3\CMS\Impexp\ImportExport\addRelations
‪addRelations(array $relations, array &$lines, int $indent, array $recursionCheck=[])
Definition: ImportExport.php:607
‪TYPO3\CMS\Impexp\Import\IMPORT_MODE_RESPECT_PID
‪const IMPORT_MODE_RESPECT_PID
Definition: Import.php:53
‪TYPO3\CMS\Impexp\ImportExport\$storagesAvailableForImport
‪ResourceStorage[] $storagesAvailableForImport
Definition: ImportExport.php:222
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:63
‪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:52
‪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:56
‪TYPO3\CMS\Impexp\ImportExport\renderSelectBox
‪string renderSelectBox(string $name, string $value, array $options)
Definition: ImportExport.php:1078
‪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:55
‪TYPO3\CMS\Impexp\ImportExport\$defaultImportExportFolder
‪Folder $defaultImportExportFolder
Definition: ImportExport.php:203
‪TYPO3\CMS\Impexp\ImportExport\getPidRecord
‪getPidRecord()
Definition: ImportExport.php:1474
‪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\Impexp\ImportExport\isSoftRefIncluded
‪bool isSoftRefIncluded(string $tokenID)
Definition: ImportExport.php:1275
‪TYPO3\CMS\Core\Resource\StorageRepository\flush
‪flush()
Definition: StorageRepository.php:176
‪TYPO3\CMS\Impexp\ImportExport\addRecord
‪addRecord(string $table, int $uid, array &$lines, int $indent, bool $checkImportInPidRecord=false)
Definition: ImportExport.php:476
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Backend\Routing\PreviewUriBuilder
Definition: PreviewUriBuilder.php:45
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Impexp\ImportExport\resolveStoragePath
‪string resolveStoragePath(string $dirPrefix, bool $checkAlternatives=true)
Definition: ImportExport.php:1202
‪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:901
‪TYPO3\CMS\Impexp\ImportExport\$excludeMap
‪array $excludeMap
Definition: ImportExport.php:136
‪TYPO3\CMS\Impexp\ImportExport\renderControls
‪string renderControls(array $line)
Definition: ImportExport.php:912
‪TYPO3\CMS\Impexp\ImportExport\getFileProcObj
‪ExtendedFileUtility getFileProcObj()
Definition: ImportExport.php:1405
‪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:935
‪TYPO3\CMS\Impexp\ImportExport\renderSoftRefExportSelector
‪string renderSoftRefExportSelector(array $softref)
Definition: ImportExport.php:982
‪TYPO3\CMS\Impexp\ImportExport\isRecordExcluded
‪bool isRecordExcluded(string $table, int $uid)
Definition: ImportExport.php:1264
‪TYPO3\CMS\Impexp
‪TYPO3\CMS\Core\Resource\StorageRepository\findAll
‪ResourceStorage[] findAll()
Definition: StorageRepository.php:213
‪TYPO3\CMS\Impexp\ImportExport\$storages
‪ResourceStorage[] $storages
Definition: ImportExport.php:216
‪TYPO3\CMS\Impexp\ImportExport\getBackendUser
‪getBackendUser()
Definition: ImportExport.php:1446
‪TYPO3\CMS\Impexp\ImportExport\traverseAllRecords
‪traverseAllRecords(array $pageTree, array &$lines)
Definition: ImportExport.php:440
‪TYPO3\CMS\Impexp\ImportExport\$softrefInputValues
‪array $softrefInputValues
Definition: ImportExport.php:117
‪TYPO3\CMS\Impexp\ImportExport\renderPreview
‪array renderPreview()
Definition: ImportExport.php:282