‪TYPO3CMS  9.5
Import.php
Go to the documentation of this file.
1 <?php
2 namespace ‪TYPO3\CMS\Impexp;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
34 
40 {
47  public ‪$suggestedInsertUids = [];
48 
54  public ‪$enableLogging = false;
55 
63  public ‪$import_newId = [];
64 
70  public ‪$import_newId_pids = [];
71 
77  public ‪$import_data = [];
78 
84  protected ‪$storageObjects = [];
85 
89  protected ‪$filesPathForImport;
90 
94  protected ‪$unlinkFiles = [];
95 
99  protected ‪$alternativeFileName = [];
100 
104  protected ‪$alternativeFilePath = [];
105 
109  protected ‪$filePathMap = [];
110 
111  /**************************
112  * Initialize
113  *************************/
114 
118  public function ‪init()
119  {
120  parent::init();
121  $this->mode = 'import';
122  }
123 
124  /***********************
125  * Import
126  ***********************/
127 
131  protected function ‪initializeImport()
132  {
133  // Set this flag to indicate that an import is being/has been done.
134  $this->doesImport = 1;
135  // Initialize:
136  // These vars MUST last for the whole section not being cleared. They are used by the method setRelations() which are called at the end of the import session.
137  $this->import_mapId = [];
138  $this->import_newId = [];
139  $this->import_newId_pids = [];
140  // Temporary files stack initialized:
141  $this->unlinkFiles = [];
142  $this->alternativeFileName = [];
143  $this->alternativeFilePath = [];
144 
146  }
147 
151  protected function ‪initializeStorageObjects()
152  {
154  $storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
155  $this->storageObjects = $storageRepository->findAll();
156  }
157 
163  public function ‪importData($pid)
164  {
165  $this->‪initializeImport();
166 
167  // Write sys_file_storages first
169  // Write sys_file records and write the binary file data
170  $this->‪writeSysFileRecords();
171  // Write records, first pages, then the rest
172  // Fields with "hard" relations to database, files and flexform fields are kept empty during this run
173  $this->‪writeRecords_pages($pid);
174  $this->‪writeRecords_records($pid);
175  // Finally all the file and DB record references must be fixed. This is done after all records have supposedly been written to database:
176  // $this->import_mapId will indicate two things: 1) that a record WAS written to db and 2) that it has got a new id-number.
177  $this->‪setRelations();
178  // And when all DB relations are in place, we can fix file and DB relations in flexform fields (since data structures often depends on relations to a DS record):
179  $this->‪setFlexFormRelations();
180  // Unlink temporary files:
181  $this->‪unlinkTempFiles();
182  // Finally, traverse all records and process softreferences with substitution attributes.
183  $this->‪processSoftReferences();
184  }
185 
189  protected function ‪writeSysFileStorageRecords()
190  {
191  if (!isset($this->dat['header']['records']['sys_file_storage'])) {
192  return;
193  }
194  $sysFileStorageUidsToBeResetToDefaultStorage = [];
195  foreach ($this->dat['header']['records']['sys_file_storage'] as $sysFileStorageUid => $_) {
196  $storageRecord = $this->dat['records']['sys_file_storage:' . $sysFileStorageUid]['data'];
197  // continue with Local, writable and online storage only
198  if ($storageRecord['driver'] === 'Local' && $storageRecord['is_writable'] && $storageRecord['is_online']) {
199  foreach ($this->storageObjects as $localStorage) {
200  if ($this->‪isEquivalentObjectStorage($localStorage, $storageRecord)) {
201  $this->import_mapId['sys_file_storage'][$sysFileStorageUid] = $localStorage->getUid();
202  break;
203  }
204  }
205 
206  if (!isset($this->import_mapId['sys_file_storage'][$sysFileStorageUid])) {
207  // Local, writable and online storage. Is allowed to be used to later write files in.
208  // Does currently not exist so add the record.
209  $this->‪addSingle('sys_file_storage', $sysFileStorageUid, 0);
210  }
211  } else {
212  // Storage with non Local drivers could be imported but must not be used to saves files in, because you
213  // could not be sure, that this is supported. The default storage will be used in this case.
214  // It could happen that non writable and non online storage will be created as dupes because you could not
215  // check the detailed configuration options at this point
216  $this->‪addSingle('sys_file_storage', $sysFileStorageUid, 0);
217  $sysFileStorageUidsToBeResetToDefaultStorage[] = $sysFileStorageUid;
218  }
219  }
220 
221  // Importing the added ones
222  $tce = $this->‪getNewTCE();
223  // Because all records are being submitted in their correct order with positive pid numbers - and so we should reverse submission order internally.
224  $tce->reverseOrder = 1;
225  $tce->isImporting = true;
226  $tce->start($this->import_data, []);
227  $tce->process_datamap();
228  $this->‪addToMapId($tce->substNEWwithIDs);
229 
230  $defaultStorageUid = null;
231  // get default storage
233  if ($defaultStorage !== null) {
234  $defaultStorageUid = $defaultStorage->‪getUid();
235  }
236  foreach ($sysFileStorageUidsToBeResetToDefaultStorage as $sysFileStorageUidToBeResetToDefaultStorage) {
237  $this->import_mapId['sys_file_storage'][$sysFileStorageUidToBeResetToDefaultStorage] = $defaultStorageUid;
238  }
239 
240  // unset the sys_file_storage records to prevent an import in writeRecords_records
241  unset($this->dat['header']['records']['sys_file_storage']);
242  }
243 
252  protected function ‪isEquivalentObjectStorage(‪ResourceStorage $storageObject, array $storageRecord)
253  {
254  // compare the properties: driver, writable and online
255  if ($storageObject->‪getDriverType() === $storageRecord['driver']
256  && (bool)$storageObject->‪isWritable() === (bool)$storageRecord['is_writable']
257  && (bool)$storageObject->‪isOnline() === (bool)$storageRecord['is_online']
258  ) {
259  $storageRecordConfiguration = ‪ResourceFactory::getInstance()->‪convertFlexFormDataToConfigurationArray($storageRecord['configuration']);
260  $storageObjectConfiguration = $storageObject->‪getConfiguration();
261  // compare the properties: pathType and basePath
262  if ($storageRecordConfiguration['pathType'] === $storageObjectConfiguration['pathType']
263  && $storageRecordConfiguration['basePath'] === $storageObjectConfiguration['basePath']
264  ) {
265  return true;
266  }
267  }
268  return false;
269  }
270 
276  public function ‪checkImportPrerequisites()
277  {
278  $messages = [];
279 
280  // Check #1: Extension dependencies
281  $extKeysToInstall = [];
282  foreach ($this->dat['header']['extensionDependencies'] as $extKey) {
283  if (!empty($extKey) && !‪ExtensionManagementUtility::isLoaded($extKey)) {
284  $extKeysToInstall[] = $extKey;
285  }
286  }
287  if (!empty($extKeysToInstall)) {
288  $messages['missingExtensions'] = 'Before you can install this T3D file you need to install the extensions "'
289  . implode('", "', $extKeysToInstall) . '".';
290  }
291 
292  // Check #2: If the path for every local storage object exists.
293  // Else files can't get moved into a newly imported storage.
294  if (!empty($this->dat['header']['records']['sys_file_storage'])) {
295  foreach ($this->dat['header']['records']['sys_file_storage'] as $sysFileStorageUid => $_) {
296  $storageRecord = $this->dat['records']['sys_file_storage:' . $sysFileStorageUid]['data'];
297  // continue with Local, writable and online storage only
298  if ($storageRecord['driver'] === 'Local'
299  && $storageRecord['is_writable']
300  && $storageRecord['is_online']
301  ) {
302  foreach ($this->storageObjects as $localStorage) {
303  if ($this->‪isEquivalentObjectStorage($localStorage, $storageRecord)) {
304  // There is already an existing storage
305  break;
306  }
307 
308  // The storage from the import does not have an equivalent storage
309  // in the current instance (same driver, same path, etc.). Before
310  // the storage record can get inserted later on take care the path
311  // it points to really exists and is accessible.
312  $storageRecordUid = $storageRecord['uid'];
313  // Unset the storage record UID when trying to create the storage object
314  // as the record does not already exist in DB. The constructor of the
315  // storage object will check whether the target folder exists and set the
316  // isOnline flag depending on the outcome.
317  $storageRecord['uid'] = 0;
318  $resourceStorage = ‪ResourceFactory::getInstance()->‪createStorageObject($storageRecord);
319  if (!$resourceStorage->isOnline()) {
320  $configuration = $resourceStorage->‪getConfiguration();
321  $messages['resourceStorageFolderMissing_' . $storageRecordUid] =
322  'The resource storage "'
323  . $resourceStorage->getName()
324  . $configuration['basePath']
325  . '" does not exist. Please create the directory prior to starting the import!';
326  }
327  }
328  }
329  }
330  }
331 
332  return $messages;
333  }
334 
338  protected function ‪writeSysFileRecords()
339  {
340  if (!isset($this->dat['header']['records']['sys_file'])) {
341  return;
342  }
343  $this->‪addGeneralErrorsByTable('sys_file');
344 
345  // fetch fresh storage records from database
346  $storageRecords = $this->‪fetchStorageRecords();
347 
349 
350  $sanitizedFolderMappings = [];
351 
352  foreach ($this->dat['header']['records']['sys_file'] as $sysFileUid => $_) {
353  $fileRecord = $this->dat['records']['sys_file:' . $sysFileUid]['data'];
354 
355  $temporaryFile = null;
356  // check if there is the right file already in the local folder
357  if ($this->filesPathForImport !== null) {
358  if (is_file($this->filesPathForImport . '/' . $fileRecord['sha1']) && sha1_file($this->filesPathForImport . '/' . $fileRecord['sha1']) === $fileRecord['sha1']) {
359  $temporaryFile = $this->filesPathForImport . '/' . $fileRecord['sha1'];
360  }
361  }
362 
363  // save file to disk
364  if ($temporaryFile === null) {
365  $fileId = md5($fileRecord['storage'] . ':' . $fileRecord['identifier_hash']);
366  $temporaryFile = $this->‪writeTemporaryFileFromData($fileId);
367  if ($temporaryFile === null) {
368  // error on writing the file. Error message was already added
369  continue;
370  }
371  }
372 
373  $originalStorageUid = $fileRecord['storage'];
374  $useStorageFromStorageRecords = false;
375 
376  // replace storage id, if an alternative one was registered
377  if (isset($this->import_mapId['sys_file_storage'][$fileRecord['storage']])) {
378  $fileRecord['storage'] = $this->import_mapId['sys_file_storage'][$fileRecord['storage']];
379  $useStorageFromStorageRecords = true;
380  }
381 
382  if (empty($fileRecord['storage']) && !$this->‪isFallbackStorage($fileRecord['storage'])) {
383  // no storage for the file is defined, mostly because of a missing default storage.
384  $this->‪error('Error: No storage for the file "' . $fileRecord['identifier'] . '" with storage uid "' . $originalStorageUid . '"');
385  continue;
386  }
387 
388  // using a storage from the local storage is only allowed, if the uid is present in the
389  // mapping. Only in this case we could be sure, that it's a local, online and writable storage.
390  if ($useStorageFromStorageRecords && isset($storageRecords[$fileRecord['storage']])) {
392  $storage = ‪ResourceFactory::getInstance()->‪getStorageObject($fileRecord['storage'], $storageRecords[$fileRecord['storage']]);
393  } elseif ($this->‪isFallbackStorage($fileRecord['storage'])) {
395  } elseif ($defaultStorage !== null) {
396  $storage = $defaultStorage;
397  } else {
398  $this->‪error('Error: No storage available for the file "' . $fileRecord['identifier'] . '" with storage uid "' . $fileRecord['storage'] . '"');
399  continue;
400  }
401 
402  $newFile = null;
403 
404  // check, if there is an identical file
405  try {
406  if ($storage->hasFile($fileRecord['identifier'])) {
407  $file = $storage->getFile($fileRecord['identifier']);
408  if ($file->getSha1() === $fileRecord['sha1']) {
409  $newFile = $file;
410  }
411  }
412  } catch (Exception $e) {
413  }
414 
415  if ($newFile === null) {
416  $folderName = ‪PathUtility::dirname(ltrim($fileRecord['identifier'], '/'));
417  if (in_array($folderName, $sanitizedFolderMappings)) {
418  $folderName = $sanitizedFolderMappings[$folderName];
419  }
420  if (!$storage->hasFolder($folderName)) {
421  try {
422  $importFolder = $storage->createFolder($folderName);
423  if ($importFolder->getIdentifier() !== $folderName && !in_array($folderName, $sanitizedFolderMappings)) {
424  $sanitizedFolderMappings[$folderName] = $importFolder->getIdentifier();
425  }
426  } catch (Exception $e) {
427  $this->‪error('Error: Folder "' . $folderName . '" could not be created for file "' . $fileRecord['identifier'] . '" with storage uid "' . $fileRecord['storage'] . '"');
428  continue;
429  }
430  } else {
431  $importFolder = $storage->getFolder($folderName);
432  }
433 
434  $this->‪callHook('before_addSysFileRecord', [
435  'fileRecord' => $fileRecord,
436  'importFolder' => $importFolder,
437  'temporaryFile' => $temporaryFile
438  ]);
439 
440  try {
442  $newFile = $storage->addFile($temporaryFile, $importFolder, $fileRecord['name']);
443  } catch (Exception $e) {
444  $this->‪error('Error: File could not be added to the storage: "' . $fileRecord['identifier'] . '" with storage uid "' . $fileRecord['storage'] . '"');
445  continue;
446  }
447 
448  if ($newFile->getSha1() !== $fileRecord['sha1']) {
449  $this->‪error('Error: The hash of the written file is not identical to the import data! File could be corrupted! File: "' . $fileRecord['identifier'] . '" with storage uid "' . $fileRecord['storage'] . '"');
450  }
451  }
452 
453  // save the new uid in the import id map
454  $this->import_mapId['sys_file'][$fileRecord['uid']] = $newFile->getUid();
455  $this->‪fixUidLocalInSysFileReferenceRecords($fileRecord['uid'], $newFile->getUid());
456  }
457 
458  // unset the sys_file records to prevent an import in writeRecords_records
459  unset($this->dat['header']['records']['sys_file']);
460  // remove all sys_file_reference records that point to file records which are unknown
461  // in the system to prevent exceptions
463  }
464 
470  {
471  if (!isset($this->dat['header']['records']['sys_file_reference'])) {
472  return;
473  }
474 
475  foreach ($this->dat['header']['records']['sys_file_reference'] as $sysFileReferenceUid => $_) {
476  $fileReferenceRecord = $this->dat['records']['sys_file_reference:' . $sysFileReferenceUid]['data'];
477  if (!in_array($fileReferenceRecord['uid_local'], $this->import_mapId['sys_file'])) {
478  unset($this->dat['header']['records']['sys_file_reference'][$sysFileReferenceUid]);
479  unset($this->dat['records']['sys_file_reference:' . $sysFileReferenceUid]);
480  $this->‪error(
481  'Error: sys_file_reference record ' . (int)$sysFileReferenceUid
482  . ' with relation to sys_file record ' . (int)$fileReferenceRecord['uid_local']
483  . ', which is not part of the import data, was not imported.'
484  );
485  }
486  }
487  }
488 
495  protected function ‪isFallbackStorage($storageId)
496  {
497  return $storageId === 0 || $storageId === '0';
498  }
499 
515  protected function ‪fixUidLocalInSysFileReferenceRecords($oldFileUid, $newFileUid)
516  {
517  if (!isset($this->dat['header']['records']['sys_file_reference'])) {
518  return;
519  }
520 
521  foreach ($this->dat['header']['records']['sys_file_reference'] as $sysFileReferenceUid => $_) {
522  if (!isset($this->dat['records']['sys_file_reference:' . $sysFileReferenceUid]['hasBeenMapped'])
523  && $this->dat['records']['sys_file_reference:' . $sysFileReferenceUid]['data']['uid_local'] == $oldFileUid
524  ) {
525  $this->dat['records']['sys_file_reference:' . $sysFileReferenceUid]['hasBeenMapped'] = true;
526  $this->dat['records']['sys_file_reference:' . $sysFileReferenceUid]['data']['uid_local'] = $newFileUid;
527  }
528  }
529  }
530 
537  protected function ‪fetchStorageRecords()
538  {
539  $result = GeneralUtility::makeInstance(ConnectionPool::class)
540  ->getQueryBuilderForTable('sys_file_storage')
541  ->select('*')
542  ->from('sys_file_storage')
543  ->orderBy('uid')
544  ->execute();
545  $rows = [];
546  while ($row = $result->fetch()) {
547  $rows[$row['uid']] = $row;
548  }
549  return $rows;
550  }
551 
559  protected function ‪writeTemporaryFileFromData($fileId, $dataKey = 'files_fal')
560  {
561  $temporaryFilePath = null;
562  if (is_array($this->dat[$dataKey][$fileId])) {
563  $temporaryFilePathInternal = GeneralUtility::tempnam('import_temp_');
564  GeneralUtility::writeFile($temporaryFilePathInternal, $this->dat[$dataKey][$fileId]['content']);
565  clearstatcache();
566  if (@is_file($temporaryFilePathInternal)) {
567  $this->unlinkFiles[] = $temporaryFilePathInternal;
568  $temporaryFilePath = $temporaryFilePathInternal;
569  } else {
570  $this->‪error('Error: temporary file ' . $temporaryFilePathInternal . ' was not written as it should have been!');
571  }
572  } else {
573  $this->‪error('Error: No file found for ID ' . $fileId);
574  }
575  return $temporaryFilePath;
576  }
577 
584  public function ‪writeRecords_pages($pid)
585  {
586  // First, write page structure if any:
587  if (is_array($this->dat['header']['records']['pages'])) {
588  $this->‪addGeneralErrorsByTable('pages');
589  // $pageRecords is a copy of the pages array in the imported file. Records here are unset one by one when the addSingle function is called.
590  $pageRecords = $this->dat['header']['records']['pages'];
591  $this->import_data = [];
592  // First add page tree if any
593  if (is_array($this->dat['header']['pagetree'])) {
594  $pagesFromTree = $this->‪flatInversePageTree($this->dat['header']['pagetree']);
595  foreach ($pagesFromTree as $uid) {
596  $thisRec = $this->dat['header']['records']['pages'][$uid];
597  // PID: Set the main $pid, unless a NEW-id is found
598  $setPid = $this->import_newId_pids[$thisRec['pid']] ?? $pid;
599  $this->‪addSingle('pages', $uid, $setPid);
600  unset($pageRecords[$uid]);
601  }
602  }
603  // Then add all remaining pages not in tree on root level:
604  if (!empty($pageRecords)) {
605  $remainingPageUids = array_keys($pageRecords);
606  foreach ($remainingPageUids as $pUid) {
607  $this->‪addSingle('pages', $pUid, $pid);
608  }
609  }
610  // Now write to database:
611  $tce = $this->‪getNewTCE();
612  $tce->isImporting = true;
613  $this->‪callHook('before_writeRecordsPages', [
614  'tce' => &$tce,
615  'data' => &$this->import_data
616  ]);
617  $tce->suggestedInsertUids = ‪$this->suggestedInsertUids;
618  $tce->start($this->import_data, []);
619  $tce->process_datamap();
620  $this->‪callHook('after_writeRecordsPages', [
621  'tce' => &$tce
622  ]);
623  // post-processing: Registering new ids (end all DataHandler sessions with this)
624  $this->‪addToMapId($tce->substNEWwithIDs);
625  // In case of an update, order pages from the page tree correctly:
626  if ($this->update && is_array($this->dat['header']['pagetree'])) {
628  }
629  }
630  }
631 
639  public function ‪writeRecords_pages_order()
640  {
641  $cmd_data = [];
642  // Get uid-pid relations and traverse them in order to map to possible new IDs
643  $pidsFromTree = $this->‪flatInversePageTree_pid($this->dat['header']['pagetree']);
644  foreach ($pidsFromTree as $origPid => $newPid) {
645  if ($newPid >= 0 && $this->‪dontIgnorePid('pages', $origPid)) {
646  // If the page had a new id (because it was created) use that instead!
647  if (strpos($this->import_newId_pids[$origPid], 'NEW') === 0) {
648  if ($this->import_mapId['pages'][$origPid]) {
649  $mappedPid = $this->import_mapId['pages'][$origPid];
650  $cmd_data['pages'][$mappedPid]['move'] = $newPid;
651  }
652  } else {
653  $cmd_data['pages'][$origPid]['move'] = $newPid;
654  }
655  }
656  }
657  // Execute the move commands if any:
658  if (!empty($cmd_data)) {
659  $tce = $this->‪getNewTCE();
660  $this->‪callHook('before_writeRecordsPagesOrder', [
661  'tce' => &$tce,
662  'data' => &$cmd_data
663  ]);
664  $tce->start([], $cmd_data);
665  $tce->process_cmdmap();
666  $this->‪callHook('after_writeRecordsPagesOrder', [
667  'tce' => &$tce
668  ]);
669  }
670  }
671 
681  public function ‪flatInversePageTree_pid($idH, $a = [], $pid = -1)
682  {
683  if (is_array($idH)) {
684  $idH = array_reverse($idH);
685  foreach ($idH as $v) {
686  $a[$v['uid']] = $pid;
687  if (is_array($v['subrow'])) {
688  $a = $this->‪flatInversePageTree_pid($v['subrow'], $a, $v['uid']);
689  }
690  }
691  }
692  return $a;
693  }
694 
701  public function ‪writeRecords_records($pid)
702  {
703  // Write the rest of the records
704  $this->import_data = [];
705  if (is_array($this->dat['header']['records'])) {
706  foreach ($this->dat['header']['records'] as $table => $recs) {
707  $this->‪addGeneralErrorsByTable($table);
708  if ($table !== 'pages') {
709  foreach ($recs as $uid => $thisRec) {
710  // PID: Set the main $pid, unless a NEW-id is found
711  $setPid = isset($this->import_mapId['pages'][$thisRec['pid']])
712  ? (int)$this->import_mapId['pages'][$thisRec['pid']]
713  : (int)$pid;
714  if (is_array(‪$GLOBALS['TCA'][$table]) && isset(‪$GLOBALS['TCA'][$table]['ctrl']['rootLevel'])) {
715  $rootLevelSetting = (int)‪$GLOBALS['TCA'][$table]['ctrl']['rootLevel'];
716  if ($rootLevelSetting === 1) {
717  $setPid = 0;
718  } elseif ($rootLevelSetting === 0 && $setPid === 0) {
719  $this->‪error('Error: Record type ' . $table . ' is not allowed on pid 0');
720  continue;
721  }
722  }
723  // Add record:
724  $this->‪addSingle($table, $uid, $setPid);
725  }
726  }
727  }
728  } else {
729  $this->‪error('Error: No records defined in internal data array.');
730  }
731  // Now write to database:
732  $tce = $this->‪getNewTCE();
733  $this->‪callHook('before_writeRecordsRecords', [
734  'tce' => &$tce,
735  'data' => &$this->import_data
736  ]);
737  $tce->suggestedInsertUids = ‪$this->suggestedInsertUids;
738  // Because all records are being submitted in their correct order with positive pid numbers - and so we should reverse submission order internally.
739  $tce->reverseOrder = 1;
740  $tce->isImporting = true;
741  $tce->start($this->import_data, []);
742  $tce->process_datamap();
743  $this->‪callHook('after_writeRecordsRecords', [
744  'tce' => &$tce
745  ]);
746  // post-processing: Removing files and registering new ids (end all DataHandler sessions with this)
747  $this->‪addToMapId($tce->substNEWwithIDs);
748  // In case of an update, order pages from the page tree correctly:
749  if ($this->update) {
750  $this->‪writeRecords_records_order($pid);
751  }
752  }
753 
762  public function ‪writeRecords_records_order($mainPid)
763  {
764  $cmd_data = [];
765  if (is_array($this->dat['header']['pagetree'])) {
766  $pagesFromTree = $this->‪flatInversePageTree($this->dat['header']['pagetree']);
767  } else {
768  $pagesFromTree = [];
769  }
770  if (is_array($this->dat['header']['pid_lookup'])) {
771  foreach ($this->dat['header']['pid_lookup'] as $pid => $recList) {
772  $newPid = $this->import_mapId['pages'][$pid] ?? $mainPid;
774  foreach ($recList as $tableName => $uidList) {
775  // If $mainPid===$newPid then we are on root level and we can consider to move pages as well!
776  // (they will not be in the page tree!)
777  if (($tableName !== 'pages' || !$pagesFromTree[$pid]) && is_array($uidList)) {
778  $uidList = array_reverse(array_keys($uidList));
779  foreach ($uidList as $uid) {
780  if ($this->‪dontIgnorePid($tableName, $uid)) {
781  $cmd_data[$tableName][$uid]['move'] = $newPid;
782  }
783  }
784  }
785  }
786  }
787  }
788  }
789  // Execute the move commands if any:
790  if (!empty($cmd_data)) {
791  $tce = $this->‪getNewTCE();
792  $this->‪callHook('before_writeRecordsRecordsOrder', [
793  'tce' => &$tce,
794  'data' => &$cmd_data
795  ]);
796  $tce->start([], $cmd_data);
797  $tce->process_cmdmap();
798  $this->‪callHook('after_writeRecordsRecordsOrder', [
799  'tce' => &$tce
800  ]);
801  }
802  }
803 
814  public function ‪addSingle($table, $uid, $pid)
815  {
816  if ($this->import_mode[$table . ':' . $uid] === 'exclude') {
817  return;
818  }
819  $record = $this->dat['records'][$table . ':' . $uid]['data'];
820  if (is_array($record)) {
821  if ($this->update && $this->‪doesRecordExist($table, $uid) && $this->import_mode[$table . ':' . $uid] !== 'as_new') {
822  $ID = $uid;
823  } elseif ($table === 'sys_file_metadata' && $record['sys_language_uid'] == '0' && $this->import_mapId['sys_file'][$record['file']]) {
824  // on adding sys_file records the belonging sys_file_metadata record was also created
825  // if there is one the record need to be overwritten instead of creating a new one.
826  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
827  ->getQueryBuilderForTable('sys_file_metadata');
828  $recordInDatabase = $queryBuilder->select('uid')
829  ->from('sys_file_metadata')
830  ->where(
831  $queryBuilder->expr()->eq(
832  'file',
833  $queryBuilder->createNamedParameter(
834  $this->import_mapId['sys_file'][$record['file']],
835  \PDO::PARAM_INT
836  )
837  ),
838  $queryBuilder->expr()->eq(
839  'sys_language_uid',
840  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
841  ),
842  $queryBuilder->expr()->eq(
843  'pid',
844  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
845  )
846  )
847  ->execute()
848  ->fetch();
849  // if no record could be found, $this->import_mapId['sys_file'][$record['file']] is pointing
850  // to a file, that was already there, thus a new metadata record should be created
851  if (is_array($recordInDatabase)) {
852  $this->import_mapId['sys_file_metadata'][$record['uid']] = $recordInDatabase['uid'];
853  $ID = $recordInDatabase['uid'];
854  } else {
855  $ID = ‪StringUtility::getUniqueId('NEW');
856  }
857  } else {
858  $ID = ‪StringUtility::getUniqueId('NEW');
859  }
860  $this->import_newId[$table . ':' . $ID] = ['table' => $table, 'uid' => $uid];
861  if ($table === 'pages') {
862  $this->import_newId_pids[$uid] = $ID;
863  }
864  // Set main record data:
865  $this->import_data[$table][$ID] = $record;
866  $this->import_data[$table][$ID]['tx_impexp_origuid'] = $this->import_data[$table][$ID]['uid'];
867  // Reset permission data:
868  if ($table === 'pages') {
869  // Have to reset the user/group IDs so pages are owned by importing user. Otherwise strange things may happen for non-admins!
870  unset($this->import_data[$table][$ID]['perms_userid']);
871  unset($this->import_data[$table][$ID]['perms_groupid']);
872  }
873  // PID and UID:
874  unset($this->import_data[$table][$ID]['uid']);
875  // Updates:
877  unset($this->import_data[$table][$ID]['pid']);
878  } else {
879  // Inserts:
880  $this->import_data[$table][$ID]['pid'] = $pid;
881  if (($this->import_mode[$table . ':' . $uid] === 'force_uid' && $this->update || $this->force_all_UIDS) && $this->‪getBackendUser()->isAdmin()) {
882  $this->import_data[$table][$ID]['uid'] = $uid;
883  $this->suggestedInsertUids[$table . ':' . $uid] = 'DELETE';
884  }
885  }
886  // Setting db/file blank:
887  foreach ($this->dat['records'][$table . ':' . $uid]['rels'] as $field => $config) {
888  switch ((string)$config['type']) {
889  case 'db':
890 
891  case 'file':
892  // Fixed later in ->setRelations() [because we need to know ALL newly created IDs before we can map relations!]
893  // In the meantime we set NO values for relations.
894  //
895  // BUT for field uid_local of table sys_file_reference the relation MUST not be cleared here,
896  // because the value is already the uid of the right imported sys_file record.
897  // @see fixUidLocalInSysFileReferenceRecords()
898  // If it's empty or a uid to another record the FileExtensionFilter will throw an exception or
899  // delete the reference record if the file extension of the related record doesn't match.
900  if ($table !== 'sys_file_reference' && $field !== 'uid_local') {
901  $this->import_data[$table][$ID][$field] = '';
902  }
903  break;
904  case 'flex':
905  // Fixed later in setFlexFormRelations()
906  // In the meantime we set NO value for flexforms - this is mainly because file references
907  // inside will not be processed properly; In fact references will point to no file
908  // or existing files (in which case there will be double-references which is a big problem of course!)
909  $this->import_data[$table][$ID][$field] = '';
910  break;
911  }
912  }
913  } elseif ($table . ':' . $uid != 'pages:0') {
914  // On root level we don't want this error message.
915  $this->‪error('Error: no record was found in data array!');
916  }
917  }
918 
925  public function ‪addToMapId($substNEWwithIDs)
926  {
927  foreach ($this->import_data as $table => $recs) {
928  foreach ($recs as $id => $value) {
929  $old_uid = $this->import_newId[$table . ':' . $id]['uid'];
930  if (isset($substNEWwithIDs[$id])) {
931  $this->import_mapId[$table][$old_uid] = $substNEWwithIDs[$id];
932  } elseif ($this->update) {
933  // Map same ID to same ID....
934  $this->import_mapId[$table][$old_uid] = $id;
935  } else {
936  // if $this->import_mapId contains already the right mapping, skip the error msg.
937  // See special handling of sys_file_metadata in addSingle() => nothing to do
938  if (!($table === 'sys_file_metadata' && isset($this->import_mapId[$table][$old_uid]) && $this->import_mapId[$table][$old_uid] == $id)) {
939  $this->‪error('Possible error: ' . $table . ':' . $old_uid . ' had no new id assigned to it. This indicates that the record was not added to database during import. Please check changelog!');
940  }
941  }
942  }
943  }
944  }
945 
951  public function ‪getNewTCE()
952  {
953  $tce = GeneralUtility::makeInstance(DataHandler::class);
954  $tce->dontProcessTransformations = 1;
955  $tce->enableLogging = ‪$this->enableLogging;
956  $tce->alternativeFileName = ‪$this->alternativeFileName;
957  $tce->alternativeFilePath = ‪$this->alternativeFilePath;
958  return $tce;
959  }
960 
964  public function ‪unlinkTempFiles()
965  {
966  foreach ($this->unlinkFiles as $fileName) {
967  GeneralUtility::unlink_tempfile($fileName);
968  clearstatcache();
969  if (is_file($fileName)) {
970  $this->‪error('Error: ' . $fileName . ' was NOT unlinked as it should have been!');
971  }
972  }
973  $this->unlinkFiles = [];
974  }
975 
976  /***************************
977  * Import / Relations setting
978  ***************************/
979 
987  public function ‪setRelations()
988  {
989  $updateData = [];
990  // import_newId contains a register of all records that was in the import memorys "records" key
991  foreach ($this->import_newId as $nId => ‪$dat) {
992  $table = ‪$dat['table'];
993  $uid = ‪$dat['uid'];
994  // original UID - NOT the new one!
995  // If the record has been written and received a new id, then proceed:
996  if (is_array($this->import_mapId[$table]) && isset($this->import_mapId[$table][$uid])) {
997  $thisNewUid = ‪BackendUtility::wsMapId($table, $this->import_mapId[$table][$uid]);
998  if (is_array($this->dat['records'][$table . ':' . $uid]['rels'])) {
999  // Traverse relation fields of each record
1000  foreach ($this->dat['records'][$table . ':' . $uid]['rels'] as $field => $config) {
1001  // uid_local of sys_file_reference needs no update because the correct reference uid was already written
1002  // @see ImportExport::fixUidLocalInSysFileReferenceRecords()
1003  if ($table === 'sys_file_reference' && $field === 'uid_local') {
1004  continue;
1005  }
1006  switch ((string)$config['type']) {
1007  case 'db':
1008  if (is_array($config['itemArray']) && !empty($config['itemArray'])) {
1009  $itemConfig = ‪$GLOBALS['TCA'][$table]['columns'][$field]['config'];
1010  $valArray = $this->‪setRelations_db($config['itemArray'], $itemConfig);
1011  $updateData[$table][$thisNewUid][$field] = implode(',', $valArray);
1012  }
1013  break;
1014  case 'file':
1015  if (is_array($config['newValueFiles']) && !empty($config['newValueFiles'])) {
1016  $valArr = [];
1017  foreach ($config['newValueFiles'] as $fI) {
1018  $valArr[] = $this->‪import_addFileNameToBeCopied($fI);
1019  }
1020  $updateData[$table][$thisNewUid][$field] = implode(',', $valArr);
1021  }
1022  break;
1023  }
1024  }
1025  } else {
1026  $this->‪error('Error: no record was found in data array!');
1027  }
1028  } else {
1029  $this->‪error('Error: this records is NOT created it seems! (' . $table . ':' . $uid . ')');
1030  }
1031  }
1032  if (!empty($updateData)) {
1033  $tce = $this->‪getNewTCE();
1034  $tce->isImporting = true;
1035  $this->‪callHook('before_setRelation', [
1036  'tce' => &$tce,
1037  'data' => &$updateData
1038  ]);
1039  $tce->start($updateData, []);
1040  $tce->process_datamap();
1041  $this->‪callHook('after_setRelations', [
1042  'tce' => &$tce
1043  ]);
1044  }
1045  }
1046 
1054  public function ‪setRelations_db($itemArray, $itemConfig)
1055  {
1056  $valArray = [];
1057  foreach ($itemArray as $relDat) {
1058  if (is_array($this->import_mapId[$relDat['table']]) && isset($this->import_mapId[$relDat['table']][$relDat['id']])) {
1059  // Since non FAL file relation type group internal_type file_reference are handled as reference to
1060  // sys_file records Datahandler requires the value as uid of the the related sys_file record only
1061  if ($itemConfig['type'] === 'group' && $itemConfig['internal_type'] === 'file_reference') {
1062  $value = $this->import_mapId[$relDat['table']][$relDat['id']];
1063  } elseif ($itemConfig['type'] === 'input' && isset($itemConfig['wizards']['link'])) {
1064  // If an input field has a relation to a sys_file record this need to be converted back to
1065  // the public path. But use getPublicUrl here, because could normally only be a local file path.
1066  $fileUid = $this->import_mapId[$relDat['table']][$relDat['id']];
1067  // Fallback value
1068  $value = 'file:' . $fileUid;
1069  try {
1071  } catch (\Exception $e) {
1072  $file = null;
1073  }
1074  if ($file instanceof FileInterface) {
1075  $value = $file->‪getPublicUrl();
1076  }
1077  } else {
1078  $value = $relDat['table'] . '_' . $this->import_mapId[$relDat['table']][$relDat['id']];
1079  }
1080  $valArray[] = $value;
1081  } elseif ($this->‪isTableStatic($relDat['table']) || $this->‪isExcluded($relDat['table'], $relDat['id']) || $relDat['id'] < 0) {
1082  // Checking for less than zero because some select types could contain negative values,
1083  // eg. fe_groups (-1, -2) and sys_language (-1 = ALL languages). This must be handled on both export and import.
1084  $valArray[] = $relDat['table'] . '_' . $relDat['id'];
1085  } else {
1086  $this->‪error('Lost relation: ' . $relDat['table'] . ':' . $relDat['id']);
1087  }
1088  }
1089  return $valArray;
1090  }
1091 
1098  public function ‪import_addFileNameToBeCopied($fI)
1099  {
1100  if (is_array($this->dat['files'][$fI['ID']])) {
1101  $tmpFile = null;
1102  // check if there is the right file already in the local folder
1103  if ($this->filesPathForImport !== null) {
1104  if (is_file($this->filesPathForImport . '/' . $this->dat['files'][$fI['ID']]['content_md5']) &&
1105  md5_file($this->filesPathForImport . '/' . $this->dat['files'][$fI['ID']]['content_md5']) === $this->dat['files'][$fI['ID']]['content_md5']) {
1106  $tmpFile = $this->filesPathForImport . '/' . $this->dat['files'][$fI['ID']]['content_md5'];
1107  }
1108  }
1109  if ($tmpFile === null) {
1110  $tmpFile = GeneralUtility::tempnam('import_temp_');
1111  GeneralUtility::writeFile($tmpFile, $this->dat['files'][$fI['ID']]['content']);
1112  }
1113  clearstatcache();
1114  if (@is_file($tmpFile)) {
1115  $this->unlinkFiles[] = $tmpFile;
1116  $this->alternativeFileName[$tmpFile] = $fI['filename'];
1117  $this->alternativeFilePath[$tmpFile] = $this->dat['files'][$fI['ID']]['relFileRef'];
1118  return $tmpFile;
1119  }
1120  $this->‪error('Error: temporary file ' . $tmpFile . ' was not written as it should have been!');
1121  } else {
1122  $this->‪error('Error: No file found for ID ' . $fI['ID']);
1123  }
1124  return null;
1125  }
1126 
1133  public function ‪setFlexFormRelations()
1134  {
1135  $updateData = [];
1136  // import_newId contains a register of all records that was in the import memorys "records" key
1137  foreach ($this->import_newId as $nId => ‪$dat) {
1138  $table = ‪$dat['table'];
1139  $uid = ‪$dat['uid'];
1140  // original UID - NOT the new one!
1141  // If the record has been written and received a new id, then proceed:
1142  if (!isset($this->import_mapId[$table][$uid])) {
1143  $this->‪error('Error: this records is NOT created it seems! (' . $table . ':' . $uid . ')');
1144  continue;
1145  }
1146 
1147  if (!is_array($this->dat['records'][$table . ':' . $uid]['rels'])) {
1148  $this->‪error('Error: no record was found in data array!');
1149  continue;
1150  }
1151  $thisNewUid = ‪BackendUtility::wsMapId($table, $this->import_mapId[$table][$uid]);
1152  // Traverse relation fields of each record
1153  foreach ($this->dat['records'][$table . ':' . $uid]['rels'] as $field => $config) {
1154  switch ((string)$config['type']) {
1155  case 'flex':
1156  // Get XML content and set as default value (string, non-processed):
1157  $updateData[$table][$thisNewUid][$field] = $this->dat['records'][$table . ':' . $uid]['data'][$field];
1158  // If there has been registered relations inside the flex form field, run processing on the content:
1159  if (!empty($config['flexFormRels']['db']) || !empty($config['flexFormRels']['file'])) {
1160  $origRecordRow = ‪BackendUtility::getRecord($table, $thisNewUid, '*');
1161  // This will fetch the new row for the element (which should be updated with any references to data structures etc.)
1162  $fieldTca = ‪$GLOBALS['TCA'][$table]['columns'][$field];
1163  if (is_array($origRecordRow) && is_array($fieldTca['config']) && $fieldTca['config']['type'] === 'flex') {
1164  // Get current data structure and value array:
1165  $flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
1166  $dataStructureIdentifier = $flexFormTools->getDataStructureIdentifier(
1167  $fieldTca,
1168  $table,
1169  $field,
1170  $origRecordRow
1171  );
1172  $dataStructureArray = $flexFormTools->parseDataStructureByIdentifier($dataStructureIdentifier);
1173  $currentValueArray = GeneralUtility::xml2array($updateData[$table][$thisNewUid][$field]);
1174  // Do recursive processing of the XML data:
1175  $iteratorObj = GeneralUtility::makeInstance(DataHandler::class);
1176  $iteratorObj->callBackObj = $this;
1177  $currentValueArray['data'] = $iteratorObj->checkValue_flex_procInData(
1178  $currentValueArray['data'],
1179  [],
1180  [],
1181  $dataStructureArray,
1182  [$table, $thisNewUid, $field, $config],
1183  'remapListedDBRecords_flexFormCallBack'
1184  );
1185  // The return value is set as an array which means it will be processed by DataHandler for file and DB references!
1186  if (is_array($currentValueArray['data'])) {
1187  $updateData[$table][$thisNewUid][$field] = $currentValueArray;
1188  }
1189  }
1190  }
1191  break;
1192  }
1193  }
1194  }
1195  if (!empty($updateData)) {
1196  $tce = $this->‪getNewTCE();
1197  $tce->isImporting = true;
1198  $this->‪callHook('before_setFlexFormRelations', [
1199  'tce' => &$tce,
1200  'data' => &$updateData
1201  ]);
1202  $tce->start($updateData, []);
1203  $tce->process_datamap();
1204  $this->‪callHook('after_setFlexFormRelations', [
1205  'tce' => &$tce
1206  ]);
1207  }
1208  }
1209 
1222  public function ‪remapListedDBRecords_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2, $path)
1223  {
1224  // Extract parameters:
1225  list(, , , $config) = $pParams;
1226  // In case the $path is used as index without a trailing slash we will remove that
1227  if (!is_array($config['flexFormRels']['db'][$path]) && is_array($config['flexFormRels']['db'][rtrim($path, '/')])) {
1228  $path = rtrim($path, '/');
1229  }
1230  if (is_array($config['flexFormRels']['db'][$path])) {
1231  $valArray = $this->‪setRelations_db($config['flexFormRels']['db'][$path], $dsConf);
1232  $dataValue = implode(',', $valArray);
1233  }
1234  if (is_array($config['flexFormRels']['file'][$path])) {
1235  $valArr = [];
1236  foreach ($config['flexFormRels']['file'][$path] as $fI) {
1237  $valArr[] = $this->‪import_addFileNameToBeCopied($fI);
1238  }
1239  $dataValue = implode(',', $valArr);
1240  }
1241  return ['value' => $dataValue];
1242  }
1243 
1244  /**************************
1245  * Import / Soft References
1246  *************************/
1247 
1251  public function ‪processSoftReferences()
1252  {
1253  // Initialize:
1254  $inData = [];
1255  // Traverse records:
1256  if (is_array($this->dat['header']['records'])) {
1257  foreach ($this->dat['header']['records'] as $table => $recs) {
1258  foreach ($recs as $uid => $thisRec) {
1259  // If there are soft references defined, traverse those:
1260  if (isset(‪$GLOBALS['TCA'][$table]) && is_array($thisRec['softrefs'])) {
1261  // First traversal is to collect softref configuration and split them up based on fields.
1262  // This could probably also have been done with the "records" key instead of the header.
1263  $fieldsIndex = [];
1264  foreach ($thisRec['softrefs'] as $softrefDef) {
1265  // If a substitution token is set:
1266  if ($softrefDef['field'] && is_array($softrefDef['subst']) && $softrefDef['subst']['tokenID']) {
1267  $fieldsIndex[$softrefDef['field']][$softrefDef['subst']['tokenID']] = $softrefDef;
1268  }
1269  }
1270  // The new id:
1271  $thisNewUid = ‪BackendUtility::wsMapId($table, $this->import_mapId[$table][$uid]);
1272  // Now, if there are any fields that require substitution to be done, lets go for that:
1273  foreach ($fieldsIndex as $field => $softRefCfgs) {
1274  if (is_array(‪$GLOBALS['TCA'][$table]['columns'][$field])) {
1275  if (‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['type'] === 'flex') {
1276  // This will fetch the new row for the element (which should be updated with any references to data structures etc.)
1277  $origRecordRow = ‪BackendUtility::getRecord($table, $thisNewUid, '*');
1278  if (is_array($origRecordRow)) {
1279  // Get current data structure and value array:
1280  $flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
1281  $dataStructureIdentifier = $flexFormTools->getDataStructureIdentifier(
1282  ‪$GLOBALS['TCA'][$table]['columns'][$field],
1283  $table,
1284  $field,
1285  $origRecordRow
1286  );
1287  $dataStructureArray = $flexFormTools->parseDataStructureByIdentifier($dataStructureIdentifier);
1288  $currentValueArray = GeneralUtility::xml2array($origRecordRow[$field]);
1289  // Do recursive processing of the XML data:
1291  $iteratorObj = GeneralUtility::makeInstance(DataHandler::class);
1292  $iteratorObj->callBackObj = $this;
1293  $currentValueArray['data'] = $iteratorObj->checkValue_flex_procInData($currentValueArray['data'], [], [], $dataStructureArray, [$table, $uid, $field, $softRefCfgs], 'processSoftReferences_flexFormCallBack');
1294  // The return value is set as an array which means it will be processed by DataHandler for file and DB references!
1295  if (is_array($currentValueArray['data'])) {
1296  $inData[$table][$thisNewUid][$field] = $currentValueArray;
1297  }
1298  }
1299  } else {
1300  // Get tokenizedContent string and proceed only if that is not blank:
1301  $tokenizedContent = $this->dat['records'][$table . ':' . $uid]['rels'][$field]['softrefs']['tokenizedContent'];
1302  if (strlen($tokenizedContent) && is_array($softRefCfgs)) {
1303  $inData[$table][$thisNewUid][$field] = $this->‪processSoftReferences_substTokens($tokenizedContent, $softRefCfgs, $table, $uid);
1304  }
1305  }
1306  }
1307  }
1308  }
1309  }
1310  }
1311  }
1312  // Now write to database:
1313  $tce = $this->‪getNewTCE();
1314  $tce->isImporting = true;
1315  $this->‪callHook('before_processSoftReferences', [
1316  'tce' => $tce,
1317  'data' => &$inData
1318  ]);
1319  $tce->enableLogging = true;
1320  $tce->start($inData, []);
1321  $tce->process_datamap();
1322  $this->‪callHook('after_processSoftReferences', [
1323  'tce' => $tce
1324  ]);
1325  }
1326 
1339  public function ‪processSoftReferences_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2, $path)
1340  {
1341  // Extract parameters:
1342  list($table, $origUid, $field, $softRefCfgs) = $pParams;
1343  if (is_array($softRefCfgs)) {
1344  // First, find all soft reference configurations for this structure path (they are listed flat in the header):
1345  $thisSoftRefCfgList = [];
1346  foreach ($softRefCfgs as $sK => $sV) {
1347  if ($sV['structurePath'] === $path) {
1348  $thisSoftRefCfgList[$sK] = $sV;
1349  }
1350  }
1351  // If any was found, do processing:
1352  if (!empty($thisSoftRefCfgList)) {
1353  // Get tokenizedContent string and proceed only if that is not blank:
1354  $tokenizedContent = $this->dat['records'][$table . ':' . $origUid]['rels'][$field]['flexFormRels']['softrefs'][$path]['tokenizedContent'];
1355  if (strlen($tokenizedContent)) {
1356  $dataValue = $this->‪processSoftReferences_substTokens($tokenizedContent, $thisSoftRefCfgList, $table, $origUid);
1357  }
1358  }
1359  }
1360  // Return
1361  return ['value' => $dataValue];
1362  }
1363 
1373  public function ‪processSoftReferences_substTokens($tokenizedContent, $softRefCfgs, $table, $uid)
1374  {
1375  // traverse each softref type for this field:
1376  foreach ($softRefCfgs as $cfg) {
1377  // Get token ID:
1378  $tokenID = $cfg['subst']['tokenID'];
1379  // Default is current token value:
1380  $insertValue = $cfg['subst']['tokenValue'];
1381  // Based on mode:
1382  switch ((string)$this->softrefCfg[$tokenID]['mode']) {
1383  case 'exclude':
1384  // Exclude is a simple passthrough of the value
1385  break;
1386  case 'editable':
1387  // Editable always picks up the value from this input array:
1388  $insertValue = $this->softrefInputValues[$tokenID];
1389  break;
1390  default:
1391  // Mapping IDs/creating files: Based on type, look up new value:
1392  switch ((string)$cfg['subst']['type']) {
1393  case 'file':
1394  // Create / Overwrite file:
1395  $insertValue = $this->‪processSoftReferences_saveFile($cfg['subst']['relFileName'], $cfg, $table, $uid);
1396  break;
1397  case 'db':
1398  default:
1399  // Trying to map database element if found in the mapID array:
1400  list($tempTable, $tempUid) = explode(':', $cfg['subst']['recordRef']);
1401  if (isset($this->import_mapId[$tempTable][$tempUid])) {
1402  $insertValue = ‪BackendUtility::wsMapId($tempTable, $this->import_mapId[$tempTable][$tempUid]);
1403  // Look if reference is to a page and the original token value was NOT an integer - then we assume is was an alias and try to look up the new one!
1404  if ($tempTable === 'pages' && !‪MathUtility::canBeInterpretedAsInteger($cfg['subst']['tokenValue'])) {
1405  $recWithUniqueValue = ‪BackendUtility::getRecord($tempTable, $insertValue, 'alias');
1406  if ($recWithUniqueValue['alias']) {
1407  $insertValue = $recWithUniqueValue['alias'];
1408  }
1409  } elseif (strpos($cfg['subst']['tokenValue'], ':') !== false) {
1410  list($tokenKey) = explode(':', $cfg['subst']['tokenValue']);
1411  $insertValue = $tokenKey . ':' . $insertValue;
1412  }
1413  }
1414  }
1415  }
1416  // Finally, swap the soft reference token in tokenized content with the insert value:
1417  $tokenizedContent = str_replace('{softref:' . $tokenID . '}', $insertValue, $tokenizedContent);
1418  }
1419  return $tokenizedContent;
1420  }
1421 
1431  public function ‪processSoftReferences_saveFile($relFileName, $cfg, $table, $uid)
1432  {
1433  if ($fileHeaderInfo = $this->dat['header']['files'][$cfg['file_ID']]) {
1434  // Initialize; Get directory prefix for file and find possible RTE filename
1435  $dirPrefix = ‪PathUtility::dirname($relFileName) . '/';
1436  $rteOrigName = $this->‪getRTEoriginalFilename(‪PathUtility::basename($relFileName));
1437  // If filename looks like an RTE file, and the directory is in "uploads/", then process as a RTE file!
1438  if ($rteOrigName && GeneralUtility::isFirstPartOfStr($dirPrefix, 'uploads/')) {
1439  // RTE:
1440  // First, find unique RTE file name:
1441  if (@is_dir(‪Environment::getPublicPath() . '/' . $dirPrefix)) {
1442  // From the "original" RTE filename, produce a new "original" destination filename which is unused.
1443  // Even if updated, the image should be unique. Currently the problem with this is that it leaves a lot of unused RTE images...
1445  $origDestName = ‪$fileProcObj->‪getUniqueName($rteOrigName, ‪Environment::getPublicPath() . '/' . $dirPrefix);
1446  // Create copy file name:
1447  $pI = pathinfo($relFileName);
1448  $copyDestName = ‪PathUtility::dirname($origDestName) . '/RTEmagicC_' . substr(‪PathUtility::basename($origDestName), 10) . '.' . $pI['extension'];
1449  if (
1450  !@is_file($copyDestName) && !@is_file($origDestName)
1451  && $origDestName === GeneralUtility::getFileAbsFileName($origDestName)
1452  && $copyDestName === GeneralUtility::getFileAbsFileName($copyDestName)
1453  ) {
1454  if ($this->dat['header']['files'][$fileHeaderInfo['RTE_ORIG_ID']]) {
1455  // Write the copy and original RTE file to the respective filenames:
1456  $this->‪writeFileVerify($copyDestName, $cfg['file_ID'], true);
1457  $this->‪writeFileVerify($origDestName, $fileHeaderInfo['RTE_ORIG_ID'], true);
1458  // Return the relative path of the copy file name:
1459  return ‪PathUtility::stripPathSitePrefix($copyDestName);
1460  }
1461  $this->‪error('ERROR: Could not find original file ID');
1462  } else {
1463  $this->‪error('ERROR: The destination filenames "' . $copyDestName . '" and "' . $origDestName . '" either existed or have non-valid names');
1464  }
1465  } else {
1466  $this->‪error('ERROR: "' . ‪Environment::getPublicPath() . '/' . $dirPrefix . '" was not a directory, so could not process file "' . $relFileName . '"');
1467  }
1468  } elseif (GeneralUtility::isFirstPartOfStr($dirPrefix, $this->fileadminFolderName . '/')) {
1469  // File in fileadmin/ folder:
1470  // Create file (and possible resources)
1471  $newFileName = $this->‪processSoftReferences_saveFile_createRelFile($dirPrefix, ‪PathUtility::basename($relFileName), $cfg['file_ID'], $table, $uid);
1472  if (strlen($newFileName)) {
1473  $relFileName = $newFileName;
1474  } else {
1475  $this->‪error('ERROR: No new file created for "' . $relFileName . '"');
1476  }
1477  } else {
1478  $this->‪error('ERROR: Sorry, cannot operate on non-RTE files which are outside the fileadmin folder.');
1479  }
1480  } else {
1481  $this->‪error('ERROR: Could not find file ID in header.');
1482  }
1483  // Return (new) filename relative to public web path
1484  return $relFileName;
1485  }
1497  public function ‪processSoftReferences_saveFile_createRelFile($origDirPrefix, $fileName, $fileID, $table, $uid)
1498  {
1499  // If the fileID map contains an entry for this fileID then just return the relative filename of that entry;
1500  // we don't want to write another unique filename for this one!
1501  if (isset($this->fileIDMap[$fileID])) {
1502  return ‪PathUtility::stripPathSitePrefix($this->fileIDMap[$fileID]);
1503  }
1504  // Verify FileMount access to dir-prefix. Returns the best alternative relative path if any
1505  $dirPrefix = $this->‪verifyFolderAccess($origDirPrefix);
1506  if ($dirPrefix && (!$this->update || $origDirPrefix === $dirPrefix) && $this->‪checkOrCreateDir($dirPrefix)) {
1507  $fileHeaderInfo = $this->dat['header']['files'][$fileID];
1508  $updMode = $this->update && $this->import_mapId[$table][$uid] === $uid && $this->import_mode[$table . ':' . $uid] !== 'as_new';
1509  // Create new name for file:
1510  // Must have same ID in map array (just for security, is not really needed) and NOT be set "as_new".
1511 
1512  // Write main file:
1513  if ($updMode) {
1514  $newName = ‪Environment::getPublicPath() . '/' . $dirPrefix . $fileName;
1515  } else {
1516  // Create unique filename:
1518  $newName = ‪$fileProcObj->‪getUniqueName($fileName, ‪Environment::getPublicPath() . '/' . $dirPrefix);
1519  }
1520  if ($this->‪writeFileVerify($newName, $fileID)) {
1521  // If the resource was an HTML/CSS file with resources attached, we will write those as well!
1522  if (is_array($fileHeaderInfo['EXT_RES_ID'])) {
1523  $tokenizedContent = $this->dat['files'][$fileID]['tokenizedContent'];
1524  $tokenSubstituted = false;
1526  if ($updMode) {
1527  foreach ($fileHeaderInfo['EXT_RES_ID'] as $res_fileID) {
1528  if ($this->dat['files'][$res_fileID]['filename']) {
1529  // Resolve original filename:
1530  $relResourceFileName = $this->dat['files'][$res_fileID]['parentRelFileName'];
1531  $absResourceFileName = GeneralUtility::resolveBackPath(‪Environment::getPublicPath() . '/' . $origDirPrefix . $relResourceFileName);
1532  $absResourceFileName = GeneralUtility::getFileAbsFileName($absResourceFileName);
1533  if ($absResourceFileName && GeneralUtility::isFirstPartOfStr($absResourceFileName, ‪Environment::getPublicPath() . '/' . $this->fileadminFolderName . '/')) {
1534  $destDir = ‪PathUtility::stripPathSitePrefix(‪PathUtility::dirname($absResourceFileName) . '/');
1535  if ($this->‪verifyFolderAccess($destDir, true) && $this->‪checkOrCreateDir($destDir)) {
1536  $this->‪writeFileVerify($absResourceFileName, $res_fileID);
1537  } else {
1538  $this->‪error('ERROR: Could not create file in directory "' . $destDir . '"');
1539  }
1540  } else {
1541  $this->‪error('ERROR: Could not resolve path for "' . $relResourceFileName . '"');
1542  }
1543  $tokenizedContent = str_replace('{EXT_RES_ID:' . $res_fileID . '}', $relResourceFileName, $tokenizedContent);
1544  $tokenSubstituted = true;
1545  }
1546  }
1547  } else {
1548  // Create the resouces directory name (filename without extension, suffixed "_FILES")
1549  $resourceDir = ‪PathUtility::dirname($newName) . '/' . preg_replace('/\\.[^.]*$/', '', ‪PathUtility::basename($newName)) . '_FILES';
1550  if (GeneralUtility::mkdir($resourceDir)) {
1551  foreach ($fileHeaderInfo['EXT_RES_ID'] as $res_fileID) {
1552  if ($this->dat['files'][$res_fileID]['filename']) {
1553  $absResourceFileName = ‪$fileProcObj->‪getUniqueName($this->dat['files'][$res_fileID]['filename'], $resourceDir);
1554  $relResourceFileName = substr($absResourceFileName, strlen(‪PathUtility::dirname($resourceDir)) + 1);
1555  $this->‪writeFileVerify($absResourceFileName, $res_fileID);
1556  $tokenizedContent = str_replace('{EXT_RES_ID:' . $res_fileID . '}', $relResourceFileName, $tokenizedContent);
1557  $tokenSubstituted = true;
1558  }
1559  }
1560  }
1561  }
1562  // If substitutions has been made, write the content to the file again:
1563  if ($tokenSubstituted) {
1564  GeneralUtility::writeFile($newName, $tokenizedContent);
1565  }
1566  }
1567  return ‪PathUtility::stripPathSitePrefix($newName);
1568  }
1569  }
1570  return null;
1571  }
1572 
1581  public function ‪writeFileVerify($fileName, $fileID, $bypassMountCheck = false)
1582  {
1584  if (!‪$fileProcObj->actionPerms['addFile']) {
1585  $this->‪error('ERROR: You did not have sufficient permissions to write the file "' . $fileName . '"');
1586  return false;
1587  }
1588  // Just for security, check again. Should actually not be necessary.
1589  if (!$bypassMountCheck) {
1590  try {
1592  } catch (InsufficientFolderAccessPermissionsException $e) {
1593  $this->‪error('ERROR: Filename "' . $fileName . '" was not allowed in destination path!');
1594  return false;
1595  }
1596  }
1597  $fI = GeneralUtility::split_fileref($fileName);
1598  if (!‪$fileProcObj->‪checkIfAllowed($fI['fileext'], $fI['path'], $fI['file']) && (!$this->allowPHPScripts || !$this->getBackendUser()->isAdmin())) {
1599  $this->‪error('ERROR: Filename "' . $fileName . '" failed against extension check or deny-pattern!');
1600  return false;
1601  }
1602  if (!GeneralUtility::getFileAbsFileName($fileName)) {
1603  $this->‪error('ERROR: Filename "' . $fileName . '" was not a valid relative file path!');
1604  return false;
1605  }
1606  if (!$this->dat['files'][$fileID]) {
1607  $this->‪error('ERROR: File ID "' . $fileID . '" could not be found');
1608  return false;
1609  }
1610  GeneralUtility::writeFile($fileName, $this->dat['files'][$fileID]['content']);
1611  $this->fileIDMap[$fileID] = $fileName;
1612  if (hash_equals(md5(file_get_contents($fileName)), $this->dat['files'][$fileID]['content_md5'])) {
1613  return true;
1614  }
1615  $this->‪error('ERROR: File content "' . $fileName . '" was corrupted');
1616  return false;
1617  }
1618 
1625  public function ‪checkOrCreateDir($dirPrefix)
1626  {
1627  // Split dir path and remove first directory (which should be "fileadmin")
1628  $filePathParts = explode('/', $dirPrefix);
1629  $firstDir = array_shift($filePathParts);
1630  if ($firstDir === $this->fileadminFolderName && GeneralUtility::getFileAbsFileName($dirPrefix)) {
1631  $pathAcc = '';
1632  foreach ($filePathParts as $dirname) {
1633  $pathAcc .= '/' . $dirname;
1634  if (strlen($dirname)) {
1635  if (!@is_dir(‪Environment::getPublicPath() . '/' . $this->fileadminFolderName . $pathAcc)) {
1636  if (!GeneralUtility::mkdir(‪Environment::getPublicPath() . '/' . $this->fileadminFolderName . $pathAcc)) {
1637  $this->‪error('ERROR: Directory could not be created....B');
1638  return false;
1639  }
1640  }
1641  } elseif ($dirPrefix === $this->fileadminFolderName . $pathAcc) {
1642  return true;
1643  } else {
1644  $this->‪error('ERROR: Directory could not be created....A');
1645  }
1646  }
1647  }
1648  return false;
1649  }
1650 
1651  /**************************
1652  * File Input
1653  *************************/
1654 
1662  public function ‪loadFile($filename, $all = false)
1663  {
1664  if (!@is_file($filename)) {
1665  $this->‪error('Filename not found: ' . $filename);
1666  return false;
1667  }
1668  $fI = pathinfo($filename);
1669  if (@is_dir($filename . '.files')) {
1670  if (GeneralUtility::isAllowedAbsPath($filename . '.files')) {
1671  // copy the folder lowlevel to typo3temp, because the files would be deleted after import
1672  $temporaryFolderName = $this->‪getTemporaryFolderName();
1673  GeneralUtility::copyDirectory($filename . '.files', $temporaryFolderName);
1674  $this->filesPathForImport = $temporaryFolderName;
1675  } else {
1676  $this->‪error('External import files for the given import source is currently not supported.');
1677  }
1678  }
1679  if (strtolower($fI['extension']) === 'xml') {
1680  // XML:
1681  $xmlContent = file_get_contents($filename);
1682  if (strlen($xmlContent)) {
1683  $this->dat = GeneralUtility::xml2array($xmlContent, '', true);
1684  if (is_array($this->dat)) {
1685  if ($this->dat['_DOCUMENT_TAG'] === 'T3RecordDocument' && is_array($this->dat['header']) && is_array($this->dat['records'])) {
1686  $this->‪loadInit();
1687  return true;
1688  }
1689  $this->‪error('XML file did not contain proper XML for TYPO3 Import');
1690  } else {
1691  $this->‪error('XML could not be parsed: ' . $this->dat);
1692  }
1693  } else {
1694  $this->‪error('Error opening file: ' . $filename);
1695  }
1696  } else {
1697  // T3D
1698  if ($fd = fopen($filename, 'rb')) {
1699  $this->dat['header'] = $this->‪getNextFilePart($fd, 1, 'header');
1700  if ($all) {
1701  $this->dat['records'] = $this->‪getNextFilePart($fd, 1, 'records');
1702  $this->dat['files'] = $this->‪getNextFilePart($fd, 1, 'files');
1703  $this->dat['files_fal'] = $this->‪getNextFilePart($fd, 1, 'files_fal');
1704  }
1705  $this->‪loadInit();
1706  return true;
1707  }
1708  $this->‪error('Error opening file: ' . $filename);
1709 
1710  fclose($fd);
1711  }
1712  return false;
1713  }
1725  public function ‪getNextFilePart($fd, $unserialize = false, $name = '')
1726  {
1727  $initStrLen = 32 + 1 + 1 + 1 + 10 + 1;
1728  // Getting header data
1729  $initStr = fread($fd, $initStrLen);
1730  if (empty($initStr)) {
1731  $this->‪error('File does not contain data for "' . $name . '"');
1732  return null;
1733  }
1734  $initStrDat = explode(':', $initStr);
1735  if (strstr($initStrDat[0], 'Warning')) {
1736  $this->‪error('File read error: Warning message in file. (' . $initStr . fgets($fd) . ')');
1737  return null;
1738  }
1739  if ((string)$initStrDat[3] !== '') {
1740  $this->‪error('File read error: InitString had a wrong length. (' . $name . ')');
1741  return null;
1742  }
1743  $datString = fread($fd, (int)$initStrDat[2]);
1744  fread($fd, 1);
1745  if (hash_equals($initStrDat[0], md5($datString))) {
1746  if ($initStrDat[1]) {
1747  if ($this->compress) {
1748  $datString = gzuncompress($datString);
1749  } else {
1750  $this->‪error('Content read error: This file requires decompression, but this server does not offer gzcompress()/gzuncompress() functions.');
1751  return null;
1752  }
1753  }
1754  return $unserialize ? unserialize($datString, ['allowed_classes' => false]) : $datString;
1755  }
1756  $this->‪error('MD5 check failed (' . $name . ')');
1757 
1758  return null;
1759  }
1760 
1767  public function ‪loadContent($filecontent)
1768  {
1769  $pointer = 0;
1770  $this->dat['header'] = $this->‪getNextContentPart($filecontent, $pointer, 1, 'header');
1771  $this->dat['records'] = $this->‪getNextContentPart($filecontent, $pointer, 1, 'records');
1772  $this->dat['files'] = $this->‪getNextContentPart($filecontent, $pointer, 1, 'files');
1773  $this->‪loadInit();
1774  }
1775 
1785  public function ‪getNextContentPart($filecontent, &$pointer, $unserialize = false, $name = '')
1786  {
1787  $initStrLen = 32 + 1 + 1 + 1 + 10 + 1;
1788  // getting header data
1789  $initStr = substr($filecontent, $pointer, $initStrLen);
1790  $pointer += $initStrLen;
1791  $initStrDat = explode(':', $initStr);
1792  if ((string)$initStrDat[3] !== '') {
1793  $this->‪error('Content read error: InitString had a wrong length. (' . $name . ')');
1794  return null;
1795  }
1796  $datString = substr($filecontent, $pointer, (int)$initStrDat[2]);
1797  $pointer += (int)$initStrDat[2] + 1;
1798  if (hash_equals($initStrDat[0], md5($datString))) {
1799  if ($initStrDat[1]) {
1800  if ($this->compress) {
1801  $datString = gzuncompress($datString);
1802  return $unserialize ? unserialize($datString, ['allowed_classes' => false]) : $datString;
1803  }
1804  $this->‪error('Content read error: This file requires decompression, but this server does not offer gzcompress()/gzuncompress() functions.');
1805  }
1806  } else {
1807  $this->‪error('MD5 check failed (' . $name . ')');
1808  }
1809  return null;
1810  }
1811 
1815  public function ‪loadInit()
1816  {
1817  $this->relStaticTables = (array)$this->dat['header']['relStaticTables'];
1818  $this->excludeMap = (array)$this->dat['header']['excludeMap'];
1819  $this->softrefCfg = (array)$this->dat['header']['softrefCfg'];
1820  }
1821 }
‪TYPO3\CMS\Core\DataHandling\DataHandler
Definition: DataHandler.php:81
‪TYPO3\CMS\Impexp\Import\processSoftReferences_flexFormCallBack
‪array processSoftReferences_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2, $path)
Definition: Import.php:1328
‪TYPO3\CMS\Impexp\Import\$enableLogging
‪bool $enableLogging
Definition: Import.php:52
‪TYPO3\CMS\Impexp\ImportExport\flatInversePageTree
‪array flatInversePageTree($idH, $a=[])
Definition: ImportExport.php:946
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:23
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Impexp\Import\processSoftReferences_substTokens
‪string processSoftReferences_substTokens($tokenizedContent, $softRefCfgs, $table, $uid)
Definition: Import.php:1362
‪TYPO3\CMS\Core\Resource\ResourceStorage\getUid
‪int getUid()
Definition: ResourceStorage.php:271
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:153
‪TYPO3\CMS\Core\Resource\File\getPublicUrl
‪string null getPublicUrl($relativeToCurrentScript=false)
Definition: File.php:360
‪TYPO3\CMS\Core\Resource\FileInterface
Definition: FileInterface.php:21
‪TYPO3\CMS\Impexp\Import\$import_newId
‪array $import_newId
Definition: Import.php:60
‪TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
Definition: InsufficientFolderAccessPermissionsException.php:21
‪TYPO3\CMS\Impexp\ImportExport\callHook
‪callHook($name, $params)
Definition: ImportExport.php:1184
‪TYPO3\CMS\Core\Resource\ResourceStorage\getDriverType
‪string getDriverType()
Definition: ResourceStorage.php:3133
‪TYPO3\CMS\Core\Utility\PathUtility\dirname
‪static string dirname($path)
Definition: PathUtility.php:185
‪TYPO3\CMS\Impexp\Import\checkImportPrerequisites
‪array checkImportPrerequisites()
Definition: Import.php:265
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Impexp\Import\removeSysFileReferenceRecordsFromImportDataWithRelationToMissingFile
‪removeSysFileReferenceRecordsFromImportDataWithRelationToMissingFile()
Definition: Import.php:458
‪TYPO3\CMS\Impexp\Import\getNewTCE
‪DataHandler getNewTCE()
Definition: Import.php:940
‪TYPO3\CMS\Impexp\Import\setRelations
‪setRelations()
Definition: Import.php:976
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:371
‪TYPO3\CMS\Impexp\Import\loadInit
‪loadInit()
Definition: Import.php:1804
‪TYPO3\CMS\Impexp\ImportExport\error
‪error($msg)
Definition: ImportExport.php:1213
‪TYPO3\CMS\Impexp\Import\setRelations_db
‪array setRelations_db($itemArray, $itemConfig)
Definition: Import.php:1043
‪TYPO3\CMS\Core\Exception
‪TYPO3\CMS\Impexp\Import\writeRecords_records_order
‪writeRecords_records_order($mainPid)
Definition: Import.php:751
‪TYPO3\CMS\Core\Resource\ResourceFactory\getFolderObjectFromCombinedIdentifier
‪Folder getFolderObjectFromCombinedIdentifier($identifier)
Definition: ResourceFactory.php:539
‪TYPO3\CMS\Impexp\Import\$import_newId_pids
‪array $import_newId_pids
Definition: Import.php:66
‪TYPO3\CMS\Impexp\Import\flatInversePageTree_pid
‪array flatInversePageTree_pid($idH, $a=[], $pid=-1)
Definition: Import.php:670
‪TYPO3\CMS\Core\Resource\ResourceFactory\getInstance
‪static ResourceFactory getInstance()
Definition: ResourceFactory.php:39
‪TYPO3\CMS\Core\Resource\ResourceFactory\createStorageObject
‪ResourceStorage createStorageObject(array $storageRecord, array $storageConfiguration=null)
Definition: ResourceFactory.php:365
‪TYPO3\CMS\Impexp\Import\fixUidLocalInSysFileReferenceRecords
‪fixUidLocalInSysFileReferenceRecords($oldFileUid, $newFileUid)
Definition: Import.php:504
‪TYPO3\CMS\Impexp\Import\writeRecords_pages
‪writeRecords_pages($pid)
Definition: Import.php:573
‪TYPO3\CMS\Impexp\ImportExport\isTableStatic
‪bool isTableStatic($table)
Definition: ImportExport.php:966
‪TYPO3\CMS\Impexp\Import\init
‪init()
Definition: Import.php:107
‪TYPO3\CMS\Core\Utility\PathUtility\basename
‪static string basename($path)
Definition: PathUtility.php:164
‪TYPO3\CMS\Impexp\Import\processSoftReferences_saveFile
‪string processSoftReferences_saveFile($relFileName, $cfg, $table, $uid)
Definition: Import.php:1420
‪TYPO3\CMS\Impexp\Import\loadFile
‪bool loadFile($filename, $all=false)
Definition: Import.php:1651
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:36
‪TYPO3\CMS\Impexp\Import\$storageObjects
‪ResourceStorage[] $storageObjects
Definition: Import.php:78
‪TYPO3\CMS\Impexp\Import\writeSysFileStorageRecords
‪writeSysFileStorageRecords()
Definition: Import.php:178
‪TYPO3\CMS\Impexp\Import\$suggestedInsertUids
‪array $suggestedInsertUids
Definition: Import.php:46
‪TYPO3\CMS\Impexp\Import\processSoftReferences_saveFile_createRelFile
‪string null processSoftReferences_saveFile_createRelFile($origDirPrefix, $fileName, $fileID, $table, $uid)
Definition: Import.php:1486
‪TYPO3\CMS\Impexp\ImportExport\verifyFolderAccess
‪string bool verifyFolderAccess($dirPrefix, $noAlternative=false)
Definition: ImportExport.php:899
‪TYPO3\CMS\Core\Resource\ResourceStorage\isOnline
‪bool isOnline()
Definition: ResourceStorage.php:395
‪TYPO3\CMS\Impexp\Import\$alternativeFileName
‪array $alternativeFileName
Definition: Import.php:90
‪TYPO3\CMS\Impexp\Import\isEquivalentObjectStorage
‪bool isEquivalentObjectStorage(ResourceStorage $storageObject, array $storageRecord)
Definition: Import.php:241
‪TYPO3\CMS\Impexp\Import
Definition: Import.php:40
‪TYPO3\CMS\Impexp\ImportExport\$fileProcObj
‪ExtendedFileUtility $fileProcObj
Definition: ImportExport.php:222
‪TYPO3\CMS\Core\Utility\File\BasicFileUtility\getUniqueName
‪string getUniqueName($theFile, $theDest, $dontCheckForUnique=false)
Definition: BasicFileUtility.php:155
‪TYPO3\CMS\Core\Resource\ResourceFactory\convertFlexFormDataToConfigurationArray
‪array convertFlexFormDataToConfigurationArray($flexFormData)
Definition: ResourceFactory.php:292
‪TYPO3\CMS\Impexp\Import\writeSysFileRecords
‪writeSysFileRecords()
Definition: Import.php:327
‪TYPO3\CMS\Impexp\Import\addToMapId
‪addToMapId($substNEWwithIDs)
Definition: Import.php:914
‪TYPO3\CMS\Core\Utility\File\BasicFileUtility\checkIfAllowed
‪bool checkIfAllowed($ext, $_, $filename='')
Definition: BasicFileUtility.php:119
‪TYPO3\CMS\Impexp\Import\writeFileVerify
‪bool writeFileVerify($fileName, $fileID, $bypassMountCheck=false)
Definition: Import.php:1570
‪TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools
Definition: FlexFormTools.php:36
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:33
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:29
‪TYPO3\CMS\Impexp\Import\loadContent
‪loadContent($filecontent)
Definition: Import.php:1756
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:23
‪TYPO3\CMS\Impexp\Import\initializeImport
‪initializeImport()
Definition: Import.php:120
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key, $exitOnError=null)
Definition: ExtensionManagementUtility.php:115
‪TYPO3\CMS\Core\Resource\ResourceStorage\getConfiguration
‪array getConfiguration()
Definition: ResourceStorage.php:209
‪TYPO3\CMS\Impexp\Import\initializeStorageObjects
‪initializeStorageObjects()
Definition: Import.php:140
‪TYPO3\CMS\Impexp\ImportExport
Definition: ImportExport.php:68
‪TYPO3\CMS\Impexp\Import\$unlinkFiles
‪array $unlinkFiles
Definition: Import.php:86
‪TYPO3\CMS\Impexp\Import\writeRecords_pages_order
‪writeRecords_pages_order()
Definition: Import.php:628
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Impexp\Import\unlinkTempFiles
‪unlinkTempFiles()
Definition: Import.php:953
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:130
‪TYPO3\CMS\Impexp\ImportExport\isExcluded
‪bool isExcluded($table, $uid)
Definition: ImportExport.php:994
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:74
‪TYPO3\CMS\Core\Utility\StringUtility\getUniqueId
‪static string getUniqueId($prefix='')
Definition: StringUtility.php:91
‪TYPO3\CMS\Impexp\ImportExport\getTemporaryFolderName
‪string getTemporaryFolderName()
Definition: ImportExport.php:928
‪TYPO3\CMS\Impexp\Import\importData
‪importData($pid)
Definition: Import.php:152
‪TYPO3\CMS\Core\Resource\ResourceFactory\getStorageObject
‪ResourceStorage getStorageObject($uid, array $recordData=[], &$fileIdentifier=null)
Definition: ResourceFactory.php:131
‪TYPO3\CMS\Impexp\Import\addSingle
‪addSingle($table, $uid, $pid)
Definition: Import.php:803
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Impexp\Import\$alternativeFilePath
‪array $alternativeFilePath
Definition: Import.php:94
‪TYPO3\CMS\Impexp\ImportExport\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: ImportExport.php:1231
‪TYPO3\CMS\Impexp\ImportExport\dontIgnorePid
‪bool dontIgnorePid($table, $uid)
Definition: ImportExport.php:1032
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:39
‪TYPO3\CMS\Impexp\ImportExport\getRTEoriginalFilename
‪string null getRTEoriginalFilename($string)
Definition: ImportExport.php:1151
‪TYPO3\CMS\Impexp\Import\$import_data
‪array $import_data
Definition: Import.php:72
‪TYPO3\CMS\Impexp\Import\isFallbackStorage
‪bool isFallbackStorage($storageId)
Definition: Import.php:484
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Impexp\Import\getNextFilePart
‪string null getNextFilePart($fd, $unserialize=false, $name='')
Definition: Import.php:1714
‪TYPO3\CMS\Core\Resource\ResourceFactory\getDefaultStorage
‪ResourceStorage null getDefaultStorage()
Definition: ResourceFactory.php:107
‪TYPO3\CMS\Impexp\ImportExport\getFileProcObj
‪ExtendedFileUtility getFileProcObj()
Definition: ImportExport.php:1169
‪TYPO3\CMS\Impexp\Import\setFlexFormRelations
‪setFlexFormRelations()
Definition: Import.php:1122
‪TYPO3\CMS\Core\Resource\ResourceStorage\isWritable
‪bool isWritable()
Definition: ResourceStorage.php:330
‪TYPO3\CMS\Impexp\ImportExport\addGeneralErrorsByTable
‪addGeneralErrorsByTable($table)
Definition: ImportExport.php:454
‪TYPO3\CMS\Impexp\ImportExport\$dat
‪array $dat
Definition: ImportExport.php:216
‪TYPO3\CMS\Impexp\Import\checkOrCreateDir
‪bool checkOrCreateDir($dirPrefix)
Definition: Import.php:1614
‪TYPO3\CMS\Impexp\Import\remapListedDBRecords_flexFormCallBack
‪array remapListedDBRecords_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2, $path)
Definition: Import.php:1211
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Impexp\Import\writeTemporaryFileFromData
‪string writeTemporaryFileFromData($fileId, $dataKey='files_fal')
Definition: Import.php:548
‪TYPO3\CMS\Impexp\Import\writeRecords_records
‪writeRecords_records($pid)
Definition: Import.php:690
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:21
‪TYPO3\CMS\Impexp\Import\$filePathMap
‪array $filePathMap
Definition: Import.php:98
‪TYPO3\CMS\Impexp\Import\import_addFileNameToBeCopied
‪string null import_addFileNameToBeCopied($fI)
Definition: Import.php:1087
‪TYPO3\CMS\Impexp\Import\getNextContentPart
‪string null getNextContentPart($filecontent, &$pointer, $unserialize=false, $name='')
Definition: Import.php:1774
‪TYPO3\CMS\Impexp
‪TYPO3\CMS\Backend\Utility\BackendUtility\wsMapId
‪static int wsMapId($table, $uid)
Definition: BackendUtility.php:4288
‪TYPO3\CMS\Impexp\Import\processSoftReferences
‪processSoftReferences()
Definition: Import.php:1240
‪TYPO3\CMS\Core\Resource\ResourceFactory\retrieveFileOrFolderObject
‪File Folder null retrieveFileOrFolderObject($input)
Definition: ResourceFactory.php:491
‪TYPO3\CMS\Impexp\ImportExport\doesRecordExist
‪array doesRecordExist($table, $uid, $fields='')
Definition: ImportExport.php:1045
‪TYPO3\CMS\Impexp\Import\$filesPathForImport
‪string null $filesPathForImport
Definition: Import.php:82
‪TYPO3\CMS\Impexp\Import\fetchStorageRecords
‪bool array fetchStorageRecords()
Definition: Import.php:526