‪TYPO3CMS  10.4
Import.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
16 namespace ‪TYPO3\CMS\Impexp;
17 
36 
42 {
49  public ‪$suggestedInsertUids = [];
50 
56  public ‪$enableLogging = false;
57 
65  public ‪$import_newId = [];
66 
72  public ‪$import_newId_pids = [];
73 
79  public ‪$import_data = [];
80 
86  protected ‪$storageObjects = [];
87 
91  protected ‪$filesPathForImport;
92 
96  protected ‪$unlinkFiles = [];
97 
101  protected ‪$filePathMap = [];
102 
103  /**************************
104  * Initialize
105  *************************/
106 
110  public function ‪init()
111  {
112  parent::init();
113  $this->mode = 'import';
114  }
115 
116  /***********************
117  * Import
118  ***********************/
119 
123  protected function ‪initializeImport()
124  {
125  // Set this flag to indicate that an import is being/has been done.
126  $this->doesImport = 1;
127  // Initialize:
128  // 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.
129  $this->import_mapId = [];
130  $this->import_newId = [];
131  $this->import_newId_pids = [];
132  // Temporary files stack initialized:
133  $this->unlinkFiles = [];
134 
136  }
137 
141  protected function ‪initializeStorageObjects()
142  {
144  $storageRepository = GeneralUtility::makeInstance(StorageRepository::class);
145  $this->storageObjects = $storageRepository->findAll();
146  }
147 
153  public function ‪importData($pid)
154  {
155  $this->‪initializeImport();
156 
157  // Write sys_file_storages first
159  // Write sys_file records and write the binary file data
160  $this->‪writeSysFileRecords();
161  // Write records, first pages, then the rest
162  // Fields with "hard" relations to database, files and flexform fields are kept empty during this run
163  $this->‪writeRecords_pages($pid);
164  $this->‪writeRecords_records($pid);
165  // Finally all the file and DB record references must be fixed. This is done after all records have supposedly been written to database:
166  // $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.
167  $this->‪setRelations();
168  // 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):
169  $this->‪setFlexFormRelations();
170  // Unlink temporary files:
171  $this->‪unlinkTempFiles();
172  // Finally, traverse all records and process softreferences with substitution attributes.
173  $this->‪processSoftReferences();
174  }
175 
179  protected function ‪writeSysFileStorageRecords()
180  {
181  if (!isset($this->dat['header']['records']['sys_file_storage'])) {
182  return;
183  }
184  $sysFileStorageUidsToBeResetToDefaultStorage = [];
185  foreach ($this->dat['header']['records']['sys_file_storage'] as $sysFileStorageUid => $_) {
186  $storageRecord = $this->dat['records']['sys_file_storage:' . $sysFileStorageUid]['data'];
187  // continue with Local, writable and online storage only
188  if ($storageRecord['driver'] === 'Local' && $storageRecord['is_writable'] && $storageRecord['is_online']) {
189  foreach ($this->storageObjects as $localStorage) {
190  if ($this->‪isEquivalentObjectStorage($localStorage, $storageRecord)) {
191  $this->import_mapId['sys_file_storage'][$sysFileStorageUid] = $localStorage->getUid();
192  break;
193  }
194  }
195 
196  if (!isset($this->import_mapId['sys_file_storage'][$sysFileStorageUid])) {
197  // Local, writable and online storage. Is allowed to be used to later write files in.
198  // Does currently not exist so add the record.
199  $this->‪addSingle('sys_file_storage', $sysFileStorageUid, 0);
200  }
201  } else {
202  // Storage with non Local drivers could be imported but must not be used to saves files in, because you
203  // could not be sure, that this is supported. The default storage will be used in this case.
204  // It could happen that non writable and non online storage will be created as dupes because you could not
205  // check the detailed configuration options at this point
206  $this->‪addSingle('sys_file_storage', $sysFileStorageUid, 0);
207  $sysFileStorageUidsToBeResetToDefaultStorage[] = $sysFileStorageUid;
208  }
209  }
210 
211  // Importing the added ones
212  $tce = $this->‪getNewTCE();
213  // Because all records are being submitted in their correct order with positive pid numbers - and so we should reverse submission order internally.
214  $tce->reverseOrder = 1;
215  $tce->isImporting = true;
216  $tce->start($this->import_data, []);
217  $tce->process_datamap();
218  $this->‪addToMapId($tce->substNEWwithIDs);
219 
220  $defaultStorageUid = null;
221  // get default storage
222  $defaultStorage = GeneralUtility::makeInstance(ResourceFactory::class)->getDefaultStorage();
223  if ($defaultStorage !== null) {
224  $defaultStorageUid = $defaultStorage->getUid();
225  }
226  foreach ($sysFileStorageUidsToBeResetToDefaultStorage as $sysFileStorageUidToBeResetToDefaultStorage) {
227  $this->import_mapId['sys_file_storage'][$sysFileStorageUidToBeResetToDefaultStorage] = $defaultStorageUid;
228  }
229 
230  // unset the sys_file_storage records to prevent an import in writeRecords_records
231  unset($this->dat['header']['records']['sys_file_storage']);
232  }
233 
242  protected function ‪isEquivalentObjectStorage(‪ResourceStorage $storageObject, array $storageRecord)
243  {
244  // compare the properties: driver, writable and online
245  if ($storageObject->‪getDriverType() === $storageRecord['driver']
246  && (bool)$storageObject->‪isWritable() === (bool)$storageRecord['is_writable']
247  && (bool)$storageObject->‪isOnline() === (bool)$storageRecord['is_online']
248  ) {
249  $storageRecordConfiguration = GeneralUtility::makeInstance(ResourceFactory::class)->convertFlexFormDataToConfigurationArray($storageRecord['configuration']);
250  $storageObjectConfiguration = $storageObject->‪getConfiguration();
251  // compare the properties: pathType and basePath
252  if ($storageRecordConfiguration['pathType'] === $storageObjectConfiguration['pathType']
253  && $storageRecordConfiguration['basePath'] === $storageObjectConfiguration['basePath']
254  ) {
255  return true;
256  }
257  }
258  return false;
259  }
260 
266  public function ‪checkImportPrerequisites()
267  {
268  $messages = [];
269 
270  // Check #1: Extension dependencies
271  $extKeysToInstall = [];
272  foreach ($this->dat['header']['extensionDependencies'] as $extKey) {
273  if (!empty($extKey) && !‪ExtensionManagementUtility::isLoaded($extKey)) {
274  $extKeysToInstall[] = $extKey;
275  }
276  }
277  if (!empty($extKeysToInstall)) {
278  $messages['missingExtensions'] = 'Before you can install this T3D file you need to install the extensions "'
279  . implode('", "', $extKeysToInstall) . '".';
280  }
281 
282  // Check #2: If the path for every local storage object exists.
283  // Else files can't get moved into a newly imported storage.
284  if (!empty($this->dat['header']['records']['sys_file_storage'])) {
285  foreach ($this->dat['header']['records']['sys_file_storage'] as $sysFileStorageUid => $_) {
286  $storageRecord = $this->dat['records']['sys_file_storage:' . $sysFileStorageUid]['data'];
287  // continue with Local, writable and online storage only
288  if ($storageRecord['driver'] === 'Local'
289  && $storageRecord['is_writable']
290  && $storageRecord['is_online']
291  ) {
292  foreach ($this->storageObjects as $localStorage) {
293  if ($this->‪isEquivalentObjectStorage($localStorage, $storageRecord)) {
294  // There is already an existing storage
295  break;
296  }
297 
298  // The storage from the import does not have an equivalent storage
299  // in the current instance (same driver, same path, etc.). Before
300  // the storage record can get inserted later on take care the path
301  // it points to really exists and is accessible.
302  $storageRecordUid = $storageRecord['uid'];
303  // Unset the storage record UID when trying to create the storage object
304  // as the record does not already exist in DB. The constructor of the
305  // storage object will check whether the target folder exists and set the
306  // isOnline flag depending on the outcome.
307  $storageRecord['uid'] = 0;
308  $resourceStorage = GeneralUtility::makeInstance(ResourceFactory::class)->createStorageObject($storageRecord);
309  if (!$resourceStorage->isOnline()) {
310  $configuration = $resourceStorage->getConfiguration();
311  $messages['resourceStorageFolderMissing_' . $storageRecordUid] =
312  'The resource storage "'
313  . $resourceStorage->getName()
314  . $configuration['basePath']
315  . '" does not exist. Please create the directory prior to starting the import!';
316  }
317  }
318  }
319  }
320  }
321 
322  return $messages;
323  }
324 
328  protected function ‪writeSysFileRecords()
329  {
330  if (!isset($this->dat['header']['records']['sys_file'])) {
331  return;
332  }
333  $this->‪addGeneralErrorsByTable('sys_file');
334 
335  // fetch fresh storage records from database
336  $storageRecords = $this->‪fetchStorageRecords();
337 
338  $defaultStorage = GeneralUtility::makeInstance(ResourceFactory::class)->getDefaultStorage();
339 
340  $sanitizedFolderMappings = [];
341 
342  foreach ($this->dat['header']['records']['sys_file'] as $sysFileUid => $_) {
343  $fileRecord = $this->dat['records']['sys_file:' . $sysFileUid]['data'];
344 
345  $temporaryFile = null;
346  // check if there is the right file already in the local folder
347  if ($this->filesPathForImport !== null) {
348  if (is_file($this->filesPathForImport . '/' . $fileRecord['sha1']) && sha1_file($this->filesPathForImport . '/' . $fileRecord['sha1']) === $fileRecord['sha1']) {
349  $temporaryFile = $this->filesPathForImport . '/' . $fileRecord['sha1'];
350  }
351  }
352 
353  // save file to disk
354  if ($temporaryFile === null) {
355  $fileId = md5($fileRecord['storage'] . ':' . $fileRecord['identifier_hash']);
356  $temporaryFile = $this->‪writeTemporaryFileFromData($fileId);
357  if ($temporaryFile === null) {
358  // error on writing the file. Error message was already added
359  continue;
360  }
361  }
362 
363  $originalStorageUid = $fileRecord['storage'];
364  $useStorageFromStorageRecords = false;
365 
366  // replace storage id, if an alternative one was registered
367  if (isset($this->import_mapId['sys_file_storage'][$fileRecord['storage']])) {
368  $fileRecord['storage'] = $this->import_mapId['sys_file_storage'][$fileRecord['storage']];
369  $useStorageFromStorageRecords = true;
370  }
371 
372  if (empty($fileRecord['storage']) && !$this->‪isFallbackStorage($fileRecord['storage'])) {
373  // no storage for the file is defined, mostly because of a missing default storage.
374  $this->‪error('Error: No storage for the file "' . $fileRecord['identifier'] . '" with storage uid "' . $originalStorageUid . '"');
375  continue;
376  }
377 
378  // using a storage from the local storage is only allowed, if the uid is present in the
379  // mapping. Only in this case we could be sure, that it's a local, online and writable storage.
380  if ($useStorageFromStorageRecords && isset($storageRecords[$fileRecord['storage']])) {
382  $storage = GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject($fileRecord['storage'], $storageRecords[$fileRecord['storage']]);
383  } elseif ($this->‪isFallbackStorage($fileRecord['storage'])) {
384  $storage = GeneralUtility::makeInstance(ResourceFactory::class)->getStorageObject(0);
385  } elseif ($defaultStorage !== null) {
386  $storage = $defaultStorage;
387  } else {
388  $this->‪error('Error: No storage available for the file "' . $fileRecord['identifier'] . '" with storage uid "' . $fileRecord['storage'] . '"');
389  continue;
390  }
391 
392  $newFile = null;
393 
394  // check, if there is an identical file
395  try {
396  if ($storage->hasFile($fileRecord['identifier'])) {
398  $file = $storage->getFile($fileRecord['identifier']);
399  if ($file->getSha1() === $fileRecord['sha1']) {
400  $newFile = $file;
401  }
402  }
403  } catch (Exception $e) {
404  }
405 
406  if ($newFile === null) {
407  $folderName = ‪PathUtility::dirname(ltrim($fileRecord['identifier'], '/'));
408  if (in_array($folderName, $sanitizedFolderMappings)) {
409  $folderName = $sanitizedFolderMappings[$folderName];
410  }
411  if (!$storage->hasFolder($folderName)) {
412  try {
413  $importFolder = $storage->createFolder($folderName);
414  if ($importFolder->getIdentifier() !== $folderName && !in_array($folderName, $sanitizedFolderMappings)) {
415  $sanitizedFolderMappings[$folderName] = $importFolder->getIdentifier();
416  }
417  } catch (Exception $e) {
418  $this->‪error('Error: Folder "' . $folderName . '" could not be created for file "' . $fileRecord['identifier'] . '" with storage uid "' . $fileRecord['storage'] . '"');
419  continue;
420  }
421  } else {
422  $importFolder = $storage->getFolder($folderName);
423  }
424 
425  $this->‪callHook('before_addSysFileRecord', [
426  'fileRecord' => $fileRecord,
427  'importFolder' => $importFolder,
428  'temporaryFile' => $temporaryFile
429  ]);
430 
431  try {
433  $newFile = $storage->addFile($temporaryFile, $importFolder, $fileRecord['name']);
434  } catch (Exception $e) {
435  $this->‪error('Error: File could not be added to the storage: "' . $fileRecord['identifier'] . '" with storage uid "' . $fileRecord['storage'] . '"');
436  continue;
437  }
438 
439  if ($newFile->getSha1() !== $fileRecord['sha1']) {
440  $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'] . '"');
441  }
442  }
443 
444  // save the new uid in the import id map
445  $this->import_mapId['sys_file'][$fileRecord['uid']] = $newFile->getUid();
446  $this->‪fixUidLocalInSysFileReferenceRecords($fileRecord['uid'], $newFile->getUid());
447  }
448 
449  // unset the sys_file records to prevent an import in writeRecords_records
450  unset($this->dat['header']['records']['sys_file']);
451  // remove all sys_file_reference records that point to file records which are unknown
452  // in the system to prevent exceptions
454  }
455 
461  {
462  if (!isset($this->dat['header']['records']['sys_file_reference'])) {
463  return;
464  }
465 
466  foreach ($this->dat['header']['records']['sys_file_reference'] as $sysFileReferenceUid => $_) {
467  $fileReferenceRecord = $this->dat['records']['sys_file_reference:' . $sysFileReferenceUid]['data'];
468  if (!in_array($fileReferenceRecord['uid_local'], $this->import_mapId['sys_file'])) {
469  unset($this->dat['header']['records']['sys_file_reference'][$sysFileReferenceUid]);
470  unset($this->dat['records']['sys_file_reference:' . $sysFileReferenceUid]);
471  $this->‪error(
472  'Error: sys_file_reference record ' . (int)$sysFileReferenceUid
473  . ' with relation to sys_file record ' . (int)$fileReferenceRecord['uid_local']
474  . ', which is not part of the import data, was not imported.'
475  );
476  }
477  }
478  }
479 
486  protected function ‪isFallbackStorage($storageId)
487  {
488  return $storageId === 0 || $storageId === '0';
489  }
490 
506  protected function ‪fixUidLocalInSysFileReferenceRecords($oldFileUid, $newFileUid)
507  {
508  if (!isset($this->dat['header']['records']['sys_file_reference'])) {
509  return;
510  }
511 
512  foreach ($this->dat['header']['records']['sys_file_reference'] as $sysFileReferenceUid => $_) {
513  if (!isset($this->dat['records']['sys_file_reference:' . $sysFileReferenceUid]['hasBeenMapped'])
514  && $this->dat['records']['sys_file_reference:' . $sysFileReferenceUid]['data']['uid_local'] == $oldFileUid
515  ) {
516  $this->dat['records']['sys_file_reference:' . $sysFileReferenceUid]['hasBeenMapped'] = true;
517  $this->dat['records']['sys_file_reference:' . $sysFileReferenceUid]['data']['uid_local'] = $newFileUid;
518  }
519  }
520  }
521 
528  protected function ‪fetchStorageRecords()
529  {
530  $result = GeneralUtility::makeInstance(ConnectionPool::class)
531  ->getQueryBuilderForTable('sys_file_storage')
532  ->select('*')
533  ->from('sys_file_storage')
534  ->orderBy('uid')
535  ->execute();
536  $rows = [];
537  while ($row = $result->fetch()) {
538  $rows[$row['uid']] = $row;
539  }
540  return $rows;
541  }
542 
550  protected function ‪writeTemporaryFileFromData($fileId, $dataKey = 'files_fal')
551  {
552  $temporaryFilePath = null;
553  if (is_array($this->dat[$dataKey][$fileId])) {
554  $temporaryFilePathInternal = GeneralUtility::tempnam('import_temp_');
555  ‪GeneralUtility::writeFile($temporaryFilePathInternal, $this->dat[$dataKey][$fileId]['content']);
556  clearstatcache();
557  if (@is_file($temporaryFilePathInternal)) {
558  $this->unlinkFiles[] = $temporaryFilePathInternal;
559  $temporaryFilePath = $temporaryFilePathInternal;
560  } else {
561  $this->‪error('Error: temporary file ' . $temporaryFilePathInternal . ' was not written as it should have been!');
562  }
563  } else {
564  $this->‪error('Error: No file found for ID ' . $fileId);
565  }
566  return $temporaryFilePath;
567  }
568 
575  public function ‪writeRecords_pages($pid)
576  {
577  // First, write page structure if any:
578  if (is_array($this->dat['header']['records']['pages'])) {
579  $this->‪addGeneralErrorsByTable('pages');
580  // $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.
581  $pageRecords = $this->dat['header']['records']['pages'];
582  $this->import_data = [];
583  // First add page tree if any
584  if (is_array($this->dat['header']['pagetree'])) {
585  $pagesFromTree = $this->‪flatInversePageTree($this->dat['header']['pagetree']);
586  foreach ($pagesFromTree as $uid) {
587  $thisRec = $this->dat['header']['records']['pages'][$uid];
588  // PID: Set the main $pid, unless a NEW-id is found
589  $setPid = $this->import_newId_pids[$thisRec['pid']] ?? $pid;
590  $this->‪addSingle('pages', $uid, $setPid);
591  unset($pageRecords[$uid]);
592  }
593  }
594  // Then add all remaining pages not in tree on root level:
595  if (!empty($pageRecords)) {
596  $remainingPageUids = array_keys($pageRecords);
597  foreach ($remainingPageUids as $pUid) {
598  $this->‪addSingle('pages', (int)$pUid, $pid);
599  }
600  }
601  // Now write to database:
602  $tce = $this->‪getNewTCE();
603  $tce->isImporting = true;
604  $this->‪callHook('before_writeRecordsPages', [
605  'tce' => &$tce,
606  'data' => &$this->import_data
607  ]);
608  $tce->suggestedInsertUids = ‪$this->suggestedInsertUids;
609  $tce->start($this->import_data, []);
610  $tce->process_datamap();
611  $this->‪callHook('after_writeRecordsPages', [
612  'tce' => &$tce
613  ]);
614  // post-processing: Registering new ids (end all DataHandler sessions with this)
615  $this->‪addToMapId($tce->substNEWwithIDs);
616  // In case of an update, order pages from the page tree correctly:
617  if ($this->update && is_array($this->dat['header']['pagetree'])) {
619  }
620  }
621  }
622 
631  public function ‪writeRecords_pages_order()
632  {
633  $cmd_data = [];
634  // Get uid-pid relations and traverse them in order to map to possible new IDs
635  $pidsFromTree = $this->‪flatInversePageTree_pid($this->dat['header']['pagetree']);
636  foreach ($pidsFromTree as $origPid => $newPid) {
637  if ($newPid >= 0 && $this->‪dontIgnorePid('pages', $origPid)) {
638  // If the page had a new id (because it was created) use that instead!
639  if (strpos($this->import_newId_pids[$origPid], 'NEW') === 0) {
640  if ($this->import_mapId['pages'][$origPid]) {
641  $mappedPid = $this->import_mapId['pages'][$origPid];
642  $cmd_data['pages'][$mappedPid]['move'] = $newPid;
643  }
644  } else {
645  $cmd_data['pages'][$origPid]['move'] = $newPid;
646  }
647  }
648  }
649  // Execute the move commands if any:
650  if (!empty($cmd_data)) {
651  $tce = $this->‪getNewTCE();
652  $this->‪callHook('before_writeRecordsPagesOrder', [
653  'tce' => &$tce,
654  'data' => &$cmd_data
655  ]);
656  $tce->start([], $cmd_data);
657  $tce->process_cmdmap();
658  $this->‪callHook('after_writeRecordsPagesOrder', [
659  'tce' => &$tce
660  ]);
661  }
662  }
663 
673  public function ‪flatInversePageTree_pid($idH, $a = [], $pid = -1)
674  {
675  if (is_array($idH)) {
676  $idH = array_reverse($idH);
677  foreach ($idH as $v) {
678  $a[$v['uid']] = $pid;
679  if (is_array($v['subrow'])) {
680  $a = $this->‪flatInversePageTree_pid($v['subrow'], $a, $v['uid']);
681  }
682  }
683  }
684  return $a;
685  }
686 
693  public function ‪writeRecords_records($pid)
694  {
695  // Write the rest of the records
696  $this->import_data = [];
697  if (is_array($this->dat['header']['records'])) {
698  foreach ($this->dat['header']['records'] as $table => $recs) {
699  $table = (string)$table;
700  $this->‪addGeneralErrorsByTable($table);
701  if ($table !== 'pages') {
702  foreach ($recs as $uid => $thisRec) {
703  // PID: Set the main $pid, unless a NEW-id is found
704  $setPid = isset($this->import_mapId['pages'][$thisRec['pid']])
705  ? (int)$this->import_mapId['pages'][$thisRec['pid']]
706  : (int)$pid;
707  if (is_array(‪$GLOBALS['TCA'][$table]) && isset(‪$GLOBALS['TCA'][$table]['ctrl']['rootLevel'])) {
708  $rootLevelSetting = (int)‪$GLOBALS['TCA'][$table]['ctrl']['rootLevel'];
709  if ($rootLevelSetting === 1) {
710  $setPid = 0;
711  } elseif ($rootLevelSetting === 0 && $setPid === 0) {
712  $this->‪error('Error: Record type ' . $table . ' is not allowed on pid 0');
713  continue;
714  }
715  }
716  // Add record:
717  $this->‪addSingle($table, $uid, $setPid);
718  }
719  }
720  }
721  } else {
722  $this->‪error('Error: No records defined in internal data array.');
723  }
724  // Now write to database:
725  $tce = $this->‪getNewTCE();
726  $this->‪callHook('before_writeRecordsRecords', [
727  'tce' => &$tce,
728  'data' => &$this->import_data
729  ]);
730  $tce->suggestedInsertUids = ‪$this->suggestedInsertUids;
731  // Because all records are being submitted in their correct order with positive pid numbers - and so we should reverse submission order internally.
732  $tce->reverseOrder = 1;
733  $tce->isImporting = true;
734  $tce->start($this->import_data, []);
735  $tce->process_datamap();
736  $this->‪callHook('after_writeRecordsRecords', [
737  'tce' => &$tce
738  ]);
739  // post-processing: Removing files and registering new ids (end all DataHandler sessions with this)
740  $this->‪addToMapId($tce->substNEWwithIDs);
741  // In case of an update, order pages from the page tree correctly:
742  if ($this->update) {
743  $this->‪writeRecords_records_order($pid);
744  }
745  }
746 
756  public function ‪writeRecords_records_order($mainPid)
757  {
758  $cmd_data = [];
759  if (is_array($this->dat['header']['pagetree'])) {
760  $pagesFromTree = $this->‪flatInversePageTree($this->dat['header']['pagetree']);
761  } else {
762  $pagesFromTree = [];
763  }
764  if (is_array($this->dat['header']['pid_lookup'])) {
765  foreach ($this->dat['header']['pid_lookup'] as $pid => $recList) {
766  $newPid = $this->import_mapId['pages'][$pid] ?? $mainPid;
768  foreach ($recList as $tableName => $uidList) {
769  // If $mainPid===$newPid then we are on root level and we can consider to move pages as well!
770  // (they will not be in the page tree!)
771  if (($tableName !== 'pages' || !$pagesFromTree[$pid]) && is_array($uidList)) {
772  $uidList = array_reverse(array_keys($uidList));
773  foreach ($uidList as $uid) {
774  if ($this->‪dontIgnorePid($tableName, $uid)) {
775  $cmd_data[$tableName][$uid]['move'] = $newPid;
776  }
777  }
778  }
779  }
780  }
781  }
782  }
783  // Execute the move commands if any:
784  if (!empty($cmd_data)) {
785  $tce = $this->‪getNewTCE();
786  $this->‪callHook('before_writeRecordsRecordsOrder', [
787  'tce' => &$tce,
788  'data' => &$cmd_data
789  ]);
790  $tce->start([], $cmd_data);
791  $tce->process_cmdmap();
792  $this->‪callHook('after_writeRecordsRecordsOrder', [
793  'tce' => &$tce
794  ]);
795  }
796  }
797 
808  public function ‪addSingle($table, $uid, $pid)
809  {
810  if ($this->import_mode[$table . ':' . $uid] === 'exclude') {
811  return;
812  }
813  $record = $this->dat['records'][$table . ':' . $uid]['data'];
814  if (is_array($record)) {
815  if ($this->update && $this->‪doesRecordExist($table, $uid) && $this->import_mode[$table . ':' . $uid] !== 'as_new') {
816  $ID = $uid;
817  } elseif ($table === 'sys_file_metadata' && $record['sys_language_uid'] == '0' && $this->import_mapId['sys_file'][$record['file']]) {
818  // on adding sys_file records the belonging sys_file_metadata record was also created
819  // if there is one the record need to be overwritten instead of creating a new one.
820  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
821  ->getQueryBuilderForTable('sys_file_metadata');
822  $recordInDatabase = $queryBuilder->select('uid')
823  ->from('sys_file_metadata')
824  ->where(
825  $queryBuilder->expr()->eq(
826  'file',
827  $queryBuilder->createNamedParameter(
828  $this->import_mapId['sys_file'][$record['file']],
829  \PDO::PARAM_INT
830  )
831  ),
832  $queryBuilder->expr()->eq(
833  'sys_language_uid',
834  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
835  ),
836  $queryBuilder->expr()->eq(
837  'pid',
838  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
839  )
840  )
841  ->execute()
842  ->fetch();
843  // if no record could be found, $this->import_mapId['sys_file'][$record['file']] is pointing
844  // to a file, that was already there, thus a new metadata record should be created
845  if (is_array($recordInDatabase)) {
846  $this->import_mapId['sys_file_metadata'][$record['uid']] = $recordInDatabase['uid'];
847  $ID = $recordInDatabase['uid'];
848  } else {
849  $ID = ‪StringUtility::getUniqueId('NEW');
850  }
851  } else {
852  $ID = ‪StringUtility::getUniqueId('NEW');
853  }
854  $this->import_newId[$table . ':' . $ID] = ['table' => $table, 'uid' => $uid];
855  if ($table === 'pages') {
856  $this->import_newId_pids[$uid] = $ID;
857  }
858  // Set main record data:
859  $this->import_data[$table][$ID] = $record;
860  $this->import_data[$table][$ID]['tx_impexp_origuid'] = $this->import_data[$table][$ID]['uid'];
861  // Reset permission data:
862  if ($table === 'pages') {
863  // Have to reset the user/group IDs so pages are owned by importing user. Otherwise strange things may happen for non-admins!
864  unset($this->import_data[$table][$ID]['perms_userid']);
865  unset($this->import_data[$table][$ID]['perms_groupid']);
866  }
867  // PID and UID:
868  unset($this->import_data[$table][$ID]['uid']);
869  // Updates:
871  unset($this->import_data[$table][$ID]['pid']);
872  } else {
873  // Inserts:
874  $this->import_data[$table][$ID]['pid'] = $pid;
875  if (($this->import_mode[$table . ':' . $uid] === 'force_uid' && $this->update || $this->force_all_UIDS) && $this->‪getBackendUser()->isAdmin()) {
876  $this->import_data[$table][$ID]['uid'] = $uid;
877  $this->suggestedInsertUids[$table . ':' . $uid] = 'DELETE';
878  }
879  }
880  // Setting db/file blank:
881  foreach ($this->dat['records'][$table . ':' . $uid]['rels'] as $field => $config) {
882  switch ((string)$config['type']) {
883  case 'db':
884 
885  case 'file':
886  // Fixed later in ->setRelations() [because we need to know ALL newly created IDs before we can map relations!]
887  // In the meantime we set NO values for relations.
888  //
889  // BUT for field uid_local of table sys_file_reference the relation MUST not be cleared here,
890  // because the value is already the uid of the right imported sys_file record.
891  // @see fixUidLocalInSysFileReferenceRecords()
892  // If it's empty or a uid to another record the FileExtensionFilter will throw an exception or
893  // delete the reference record if the file extension of the related record doesn't match.
894  if ($table !== 'sys_file_reference' && $field !== 'uid_local') {
895  $this->import_data[$table][$ID][$field] = '';
896  }
897  break;
898  case 'flex':
899  // Fixed later in setFlexFormRelations()
900  // In the meantime we set NO value for flexforms - this is mainly because file references
901  // inside will not be processed properly; In fact references will point to no file
902  // or existing files (in which case there will be double-references which is a big problem of course!)
903  $this->import_data[$table][$ID][$field] = '';
904  break;
905  }
906  }
907  } elseif ($table . ':' . $uid != 'pages:0') {
908  // On root level we don't want this error message.
909  $this->‪error('Error: no record was found in data array!');
910  }
911  }
912 
919  public function ‪addToMapId($substNEWwithIDs)
920  {
921  foreach ($this->import_data as $table => $recs) {
922  foreach ($recs as $id => $value) {
923  $old_uid = $this->import_newId[$table . ':' . $id]['uid'];
924  if (isset($substNEWwithIDs[$id])) {
925  $this->import_mapId[$table][$old_uid] = $substNEWwithIDs[$id];
926  } elseif ($this->update) {
927  // Map same ID to same ID....
928  $this->import_mapId[$table][$old_uid] = $id;
929  } else {
930  // if $this->import_mapId contains already the right mapping, skip the error msg.
931  // See special handling of sys_file_metadata in addSingle() => nothing to do
932  if (!($table === 'sys_file_metadata' && isset($this->import_mapId[$table][$old_uid]) && $this->import_mapId[$table][$old_uid] == $id)) {
933  $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!');
934  }
935  }
936  }
937  }
938  }
939 
945  public function ‪getNewTCE()
946  {
947  $tce = GeneralUtility::makeInstance(DataHandler::class);
948  $tce->dontProcessTransformations = 1;
949  $tce->enableLogging = ‪$this->enableLogging;
950  return $tce;
951  }
952 
956  public function ‪unlinkTempFiles()
957  {
958  foreach ($this->unlinkFiles as $fileName) {
959  GeneralUtility::unlink_tempfile($fileName);
960  clearstatcache();
961  if (is_file($fileName)) {
962  $this->‪error('Error: ' . $fileName . ' was NOT unlinked as it should have been!');
963  }
964  }
965  $this->unlinkFiles = [];
966  }
967 
968  /***************************
969  * Import / Relations setting
970  ***************************/
978  public function ‪setRelations()
979  {
980  $updateData = [];
981  // import_newId contains a register of all records that was in the import memory's "records" key
982  foreach ($this->import_newId as $nId => ‪$dat) {
983  $table = ‪$dat['table'];
984  $uid = ‪$dat['uid'];
985  // original UID - NOT the new one!
986  // If the record has been written and received a new id, then proceed:
987  if (is_array($this->import_mapId[$table]) && isset($this->import_mapId[$table][$uid])) {
988  $thisNewUid = ‪BackendUtility::wsMapId($table, $this->import_mapId[$table][$uid]);
989  if (is_array($this->dat['records'][$table . ':' . $uid]['rels'])) {
990  // Traverse relation fields of each record
991  foreach ($this->dat['records'][$table . ':' . $uid]['rels'] as $field => $config) {
992  // uid_local of sys_file_reference needs no update because the correct reference uid was already written
993  // @see ImportExport::fixUidLocalInSysFileReferenceRecords()
994  if ($table === 'sys_file_reference' && $field === 'uid_local') {
995  continue;
996  }
997  switch ((string)$config['type']) {
998  case 'db':
999  if (is_array($config['itemArray']) && !empty($config['itemArray'])) {
1000  $itemConfig = ‪$GLOBALS['TCA'][$table]['columns'][$field]['config'];
1001  $valArray = $this->‪setRelations_db($config['itemArray'], $itemConfig);
1002  $updateData[$table][$thisNewUid][$field] = implode(',', $valArray);
1003  }
1004  break;
1005  case 'file':
1006  if (is_array($config['newValueFiles']) && !empty($config['newValueFiles'])) {
1007  $valArr = [];
1008  foreach ($config['newValueFiles'] as $fI) {
1009  $valArr[] = $this->‪import_addFileNameToBeCopied($fI);
1010  }
1011  $updateData[$table][$thisNewUid][$field] = implode(',', $valArr);
1012  }
1013  break;
1014  }
1015  }
1016  } else {
1017  $this->‪error('Error: no record was found in data array!');
1018  }
1019  } else {
1020  $this->‪error('Error: this records is NOT created it seems! (' . $table . ':' . $uid . ')');
1021  }
1022  }
1023  if (!empty($updateData)) {
1024  $tce = $this->‪getNewTCE();
1025  $tce->isImporting = true;
1026  $this->‪callHook('before_setRelation', [
1027  'tce' => &$tce,
1028  'data' => &$updateData
1029  ]);
1030  $tce->start($updateData, []);
1031  $tce->process_datamap();
1032  $this->‪callHook('after_setRelations', [
1033  'tce' => &$tce
1034  ]);
1035  }
1036  }
1037 
1045  public function ‪setRelations_db($itemArray, $itemConfig)
1046  {
1047  $valArray = [];
1048  foreach ($itemArray as $relDat) {
1049  if (is_array($this->import_mapId[$relDat['table']]) && isset($this->import_mapId[$relDat['table']][$relDat['id']])) {
1050  if ($itemConfig['type'] === 'input' && isset($itemConfig['wizards']['link'])) {
1051  // If an input field has a relation to a sys_file record this need to be converted back to
1052  // the public path. But use getPublicUrl here, because could normally only be a local file path.
1053  $fileUid = $this->import_mapId[$relDat['table']][$relDat['id']];
1054  // Fallback value
1055  $value = 'file:' . $fileUid;
1056  try {
1057  $file = GeneralUtility::makeInstance(ResourceFactory::class)->retrieveFileOrFolderObject($fileUid);
1058  } catch (\‪Exception $e) {
1059  $file = null;
1060  }
1061  if ($file instanceof ‪FileInterface) {
1062  $value = $file->getPublicUrl();
1063  }
1064  } else {
1065  $value = $relDat['table'] . '_' . $this->import_mapId[$relDat['table']][$relDat['id']];
1066  }
1067  $valArray[] = $value;
1068  } elseif ($this->‪isTableStatic($relDat['table']) || $this->‪isExcluded($relDat['table'], $relDat['id']) || $relDat['id'] < 0) {
1069  // Checking for less than zero because some select types could contain negative values,
1070  // eg. fe_groups (-1, -2) and sys_language (-1 = ALL languages). This must be handled on both export and import.
1071  $valArray[] = $relDat['table'] . '_' . $relDat['id'];
1072  } else {
1073  $this->‪error('Lost relation: ' . $relDat['table'] . ':' . $relDat['id']);
1074  }
1075  }
1076  return $valArray;
1077  }
1078 
1085  public function ‪import_addFileNameToBeCopied($fI)
1086  {
1087  if (is_array($this->dat['files'][$fI['ID']])) {
1088  $tmpFile = null;
1089  // check if there is the right file already in the local folder
1090  if ($this->filesPathForImport !== null) {
1091  if (is_file($this->filesPathForImport . '/' . $this->dat['files'][$fI['ID']]['content_md5']) &&
1092  md5_file($this->filesPathForImport . '/' . $this->dat['files'][$fI['ID']]['content_md5']) === $this->dat['files'][$fI['ID']]['content_md5']) {
1093  $tmpFile = $this->filesPathForImport . '/' . $this->dat['files'][$fI['ID']]['content_md5'];
1094  }
1095  }
1096  if ($tmpFile === null) {
1097  $tmpFile = GeneralUtility::tempnam('import_temp_');
1098  ‪GeneralUtility::writeFile($tmpFile, $this->dat['files'][$fI['ID']]['content']);
1099  }
1100  clearstatcache();
1101  if (@is_file($tmpFile)) {
1102  $this->unlinkFiles[] = $tmpFile;
1103  return $tmpFile;
1104  }
1105  $this->‪error('Error: temporary file ' . $tmpFile . ' was not written as it should have been!');
1106  } else {
1107  $this->‪error('Error: No file found for ID ' . $fI['ID']);
1108  }
1109  return null;
1110  }
1111 
1118  public function ‪setFlexFormRelations()
1119  {
1120  $updateData = [];
1121  // import_newId contains a register of all records that were in the import memory's "records" key
1122  foreach ($this->import_newId as $nId => ‪$dat) {
1123  $table = ‪$dat['table'];
1124  $uid = ‪$dat['uid'];
1125  // original UID - NOT the new one!
1126  // If the record has been written and received a new id, then proceed:
1127  if (!isset($this->import_mapId[$table][$uid])) {
1128  $this->‪error('Error: this records is NOT created it seems! (' . $table . ':' . $uid . ')');
1129  continue;
1130  }
1131 
1132  if (!is_array($this->dat['records'][$table . ':' . $uid]['rels'])) {
1133  $this->‪error('Error: no record was found in data array!');
1134  continue;
1135  }
1136  $thisNewUid = ‪BackendUtility::wsMapId($table, $this->import_mapId[$table][$uid]);
1137  // Traverse relation fields of each record
1138  foreach ($this->dat['records'][$table . ':' . $uid]['rels'] as $field => $config) {
1139  switch ((string)$config['type']) {
1140  case 'flex':
1141  // Get XML content and set as default value (string, non-processed):
1142  $updateData[$table][$thisNewUid][$field] = $this->dat['records'][$table . ':' . $uid]['data'][$field];
1143  // If there has been registered relations inside the flex form field, run processing on the content:
1144  if (!empty($config['flexFormRels']['db']) || !empty($config['flexFormRels']['file'])) {
1145  $origRecordRow = ‪BackendUtility::getRecord($table, $thisNewUid, '*');
1146  // This will fetch the new row for the element (which should be updated with any references to data structures etc.)
1147  $fieldTca = ‪$GLOBALS['TCA'][$table]['columns'][$field];
1148  if (is_array($origRecordRow) && is_array($fieldTca['config']) && $fieldTca['config']['type'] === 'flex') {
1149  // Get current data structure and value array:
1150  $flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
1151  $dataStructureIdentifier = $flexFormTools->getDataStructureIdentifier(
1152  $fieldTca,
1153  $table,
1154  $field,
1155  $origRecordRow
1156  );
1157  $dataStructureArray = $flexFormTools->parseDataStructureByIdentifier($dataStructureIdentifier);
1158  $currentValueArray = ‪GeneralUtility::xml2array($updateData[$table][$thisNewUid][$field]);
1159  // Do recursive processing of the XML data:
1160  $iteratorObj = GeneralUtility::makeInstance(DataHandler::class);
1161  $iteratorObj->callBackObj = $this;
1162  $currentValueArray['data'] = $iteratorObj->checkValue_flex_procInData(
1163  $currentValueArray['data'],
1164  [],
1165  [],
1166  $dataStructureArray,
1167  [$table, $thisNewUid, $field, $config],
1168  'remapListedDBRecords_flexFormCallBack'
1169  );
1170  // The return value is set as an array which means it will be processed by DataHandler for file and DB references!
1171  if (is_array($currentValueArray['data'])) {
1172  $updateData[$table][$thisNewUid][$field] = $currentValueArray;
1173  }
1174  }
1175  }
1176  break;
1177  }
1178  }
1179  }
1180  if (!empty($updateData)) {
1181  $tce = $this->‪getNewTCE();
1182  $tce->isImporting = true;
1183  $this->‪callHook('before_setFlexFormRelations', [
1184  'tce' => &$tce,
1185  'data' => &$updateData
1186  ]);
1187  $tce->start($updateData, []);
1188  $tce->process_datamap();
1189  $this->‪callHook('after_setFlexFormRelations', [
1190  'tce' => &$tce
1191  ]);
1192  }
1193  }
1194 
1207  public function ‪remapListedDBRecords_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2, $path)
1208  {
1209  // Extract parameters:
1210  [, , , $config] = $pParams;
1211  // In case the $path is used as index without a trailing slash we will remove that
1212  if (!is_array($config['flexFormRels']['db'][$path]) && is_array($config['flexFormRels']['db'][rtrim($path, '/')])) {
1213  $path = rtrim($path, '/');
1214  }
1215  if (is_array($config['flexFormRels']['db'][$path])) {
1216  $valArray = $this->‪setRelations_db($config['flexFormRels']['db'][$path], $dsConf);
1217  $dataValue = implode(',', $valArray);
1218  }
1219  if (is_array($config['flexFormRels']['file'][$path])) {
1220  $valArr = [];
1221  foreach ($config['flexFormRels']['file'][$path] as $fI) {
1222  $valArr[] = $this->‪import_addFileNameToBeCopied($fI);
1223  }
1224  $dataValue = implode(',', $valArr);
1225  }
1226  return ['value' => $dataValue];
1227  }
1228 
1229  /**************************
1230  * Import / Soft References
1231  *************************/
1232 
1236  public function ‪processSoftReferences()
1237  {
1238  // Initialize:
1239  $inData = [];
1240  // Traverse records:
1241  if (is_array($this->dat['header']['records'])) {
1242  foreach ($this->dat['header']['records'] as $table => $recs) {
1243  foreach ($recs as $uid => $thisRec) {
1244  // If there are soft references defined, traverse those:
1245  if (isset(‪$GLOBALS['TCA'][$table]) && is_array($thisRec['softrefs'])) {
1246  // First traversal is to collect softref configuration and split them up based on fields.
1247  // This could probably also have been done with the "records" key instead of the header.
1248  $fieldsIndex = [];
1249  foreach ($thisRec['softrefs'] as $softrefDef) {
1250  // If a substitution token is set:
1251  if ($softrefDef['field'] && is_array($softrefDef['subst']) && $softrefDef['subst']['tokenID']) {
1252  $fieldsIndex[$softrefDef['field']][$softrefDef['subst']['tokenID']] = $softrefDef;
1253  }
1254  }
1255  // The new id:
1256  $thisNewUid = ‪BackendUtility::wsMapId($table, $this->import_mapId[$table][$uid]);
1257  // Now, if there are any fields that require substitution to be done, lets go for that:
1258  foreach ($fieldsIndex as $field => $softRefCfgs) {
1259  if (is_array(‪$GLOBALS['TCA'][$table]['columns'][$field])) {
1260  if (‪$GLOBALS['TCA'][$table]['columns'][$field]['config']['type'] === 'flex') {
1261  // This will fetch the new row for the element (which should be updated with any references to data structures etc.)
1262  $origRecordRow = ‪BackendUtility::getRecord($table, $thisNewUid, '*');
1263  if (is_array($origRecordRow)) {
1264  // Get current data structure and value array:
1265  $flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
1266  $dataStructureIdentifier = $flexFormTools->getDataStructureIdentifier(
1267  ‪$GLOBALS['TCA'][$table]['columns'][$field],
1268  $table,
1269  $field,
1270  $origRecordRow
1271  );
1272  $dataStructureArray = $flexFormTools->parseDataStructureByIdentifier($dataStructureIdentifier);
1273  $currentValueArray = ‪GeneralUtility::xml2array($origRecordRow[$field]);
1274  // Do recursive processing of the XML data:
1276  $iteratorObj = GeneralUtility::makeInstance(DataHandler::class);
1277  $iteratorObj->callBackObj = $this;
1278  $currentValueArray['data'] = $iteratorObj->checkValue_flex_procInData($currentValueArray['data'], [], [], $dataStructureArray, [$table, $uid, $field, $softRefCfgs], 'processSoftReferences_flexFormCallBack');
1279  // The return value is set as an array which means it will be processed by DataHandler for file and DB references!
1280  if (is_array($currentValueArray['data'])) {
1281  $inData[$table][$thisNewUid][$field] = $currentValueArray;
1282  }
1283  }
1284  } else {
1285  // Get tokenizedContent string and proceed only if that is not blank:
1286  $tokenizedContent = $this->dat['records'][$table . ':' . $uid]['rels'][$field]['softrefs']['tokenizedContent'];
1287  if (strlen($tokenizedContent) && is_array($softRefCfgs)) {
1288  $inData[$table][$thisNewUid][$field] = $this->‪processSoftReferences_substTokens($tokenizedContent, $softRefCfgs, $table, $uid);
1289  }
1290  }
1291  }
1292  }
1293  }
1294  }
1295  }
1296  }
1297  // Now write to database:
1298  $tce = $this->‪getNewTCE();
1299  $tce->isImporting = true;
1300  $this->‪callHook('before_processSoftReferences', [
1301  'tce' => $tce,
1302  'data' => &$inData
1303  ]);
1304  $tce->enableLogging = true;
1305  $tce->start($inData, []);
1306  $tce->process_datamap();
1307  $this->‪callHook('after_processSoftReferences', [
1308  'tce' => $tce
1309  ]);
1310  }
1311 
1324  public function ‪processSoftReferences_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2, $path)
1325  {
1326  // Extract parameters:
1327  [$table, $origUid, $field, $softRefCfgs] = $pParams;
1328  if (is_array($softRefCfgs)) {
1329  // First, find all soft reference configurations for this structure path (they are listed flat in the header):
1330  $thisSoftRefCfgList = [];
1331  foreach ($softRefCfgs as $sK => $sV) {
1332  if ($sV['structurePath'] === $path) {
1333  $thisSoftRefCfgList[$sK] = $sV;
1334  }
1335  }
1336  // If any was found, do processing:
1337  if (!empty($thisSoftRefCfgList)) {
1338  // Get tokenizedContent string and proceed only if that is not blank:
1339  $tokenizedContent = $this->dat['records'][$table . ':' . $origUid]['rels'][$field]['flexFormRels']['softrefs'][$path]['tokenizedContent'];
1340  if (strlen($tokenizedContent)) {
1341  $dataValue = $this->‪processSoftReferences_substTokens($tokenizedContent, $thisSoftRefCfgList, $table, $origUid);
1342  }
1343  }
1344  }
1345  // Return
1346  return ['value' => $dataValue];
1347  }
1348 
1358  public function ‪processSoftReferences_substTokens($tokenizedContent, $softRefCfgs, $table, $uid)
1359  {
1360  // traverse each softref type for this field:
1361  foreach ($softRefCfgs as $cfg) {
1362  // Get token ID:
1363  $tokenID = $cfg['subst']['tokenID'];
1364  // Default is current token value:
1365  $insertValue = $cfg['subst']['tokenValue'];
1366  // Based on mode:
1367  switch ((string)$this->softrefCfg[$tokenID]['mode']) {
1368  case 'exclude':
1369  // Exclude is a simple passthrough of the value
1370  break;
1371  case 'editable':
1372  // Editable always picks up the value from this input array:
1373  $insertValue = $this->softrefInputValues[$tokenID];
1374  break;
1375  default:
1376  // Mapping IDs/creating files: Based on type, look up new value:
1377  switch ((string)$cfg['subst']['type']) {
1378  case 'file':
1379  // Create / Overwrite file:
1380  $insertValue = $this->‪processSoftReferences_saveFile($cfg['subst']['relFileName'], $cfg, $table, $uid);
1381  break;
1382  case 'db':
1383  default:
1384  // Trying to map database element if found in the mapID array:
1385  [$tempTable, $tempUid] = explode(':', $cfg['subst']['recordRef']);
1386  if (isset($this->import_mapId[$tempTable][$tempUid])) {
1387  $insertValue = ‪BackendUtility::wsMapId($tempTable, $this->import_mapId[$tempTable][$tempUid]);
1388  if (strpos($cfg['subst']['tokenValue'], ':') !== false) {
1389  [$tokenKey] = explode(':', $cfg['subst']['tokenValue']);
1390  $insertValue = $tokenKey . ':' . $insertValue;
1391  }
1392  }
1393  }
1394  }
1395  // Finally, swap the soft reference token in tokenized content with the insert value:
1396  $tokenizedContent = str_replace('{softref:' . $tokenID . '}', $insertValue, $tokenizedContent);
1397  }
1398  return $tokenizedContent;
1399  }
1400 
1410  public function ‪processSoftReferences_saveFile($relFileName, $cfg, $table, $uid)
1411  {
1412  if ($fileHeaderInfo = $this->dat['header']['files'][$cfg['file_ID']]) {
1413  // Initialize; Get directory prefix for file and find possible RTE filename
1414  $dirPrefix = ‪PathUtility::dirname($relFileName) . '/';
1415  if (GeneralUtility::isFirstPartOfStr($dirPrefix, $this->fileadminFolderName . '/')) {
1416  // File in fileadmin/ folder:
1417  // Create file (and possible resources)
1418  $newFileName = $this->‪processSoftReferences_saveFile_createRelFile($dirPrefix, ‪PathUtility::basename($relFileName), $cfg['file_ID'], $table, $uid) ?: '';
1419  if (strlen($newFileName)) {
1420  $relFileName = $newFileName;
1421  } else {
1422  $this->‪error('ERROR: No new file created for "' . $relFileName . '"');
1423  }
1424  } else {
1425  $this->‪error('ERROR: Sorry, cannot operate on non-RTE files which are outside the fileadmin folder.');
1426  }
1427  } else {
1428  $this->‪error('ERROR: Could not find file ID in header.');
1429  }
1430  // Return (new) filename relative to public web path
1431  return $relFileName;
1432  }
1433 
1444  public function ‪processSoftReferences_saveFile_createRelFile($origDirPrefix, $fileName, $fileID, $table, $uid)
1445  {
1446  // If the fileID map contains an entry for this fileID then just return the relative filename of that entry;
1447  // we don't want to write another unique filename for this one!
1448  if (isset($this->fileIDMap[$fileID])) {
1449  return ‪PathUtility::stripPathSitePrefix($this->fileIDMap[$fileID]);
1450  }
1451  // Verify FileMount access to dir-prefix. Returns the best alternative relative path if any
1452  $dirPrefix = (string)$this->‪verifyFolderAccess($origDirPrefix);
1453  if ($dirPrefix && (!$this->update || $origDirPrefix === $dirPrefix) && $this->‪checkOrCreateDir($dirPrefix)) {
1454  $fileHeaderInfo = $this->dat['header']['files'][$fileID];
1455  $updMode = $this->update && $this->import_mapId[$table][$uid] === $uid && $this->import_mode[$table . ':' . $uid] !== 'as_new';
1456  // Create new name for file:
1457  // Must have same ID in map array (just for security, is not really needed) and NOT be set "as_new".
1458 
1459  // Write main file:
1460  if ($updMode) {
1461  $newName = ‪Environment::getPublicPath() . '/' . $dirPrefix . $fileName;
1462  } else {
1463  // Create unique filename:
1465  $newName = (string)‪$fileProcObj->‪getUniqueName($fileName, ‪Environment::getPublicPath() . '/' . $dirPrefix);
1466  }
1467  if ($this->‪writeFileVerify($newName, $fileID)) {
1468  // If the resource was an HTML/CSS file with resources attached, we will write those as well!
1469  if (is_array($fileHeaderInfo['EXT_RES_ID'])) {
1470  $tokenizedContent = $this->dat['files'][$fileID]['tokenizedContent'];
1471  $tokenSubstituted = false;
1473  if ($updMode) {
1474  foreach ($fileHeaderInfo['EXT_RES_ID'] as $res_fileID) {
1475  if ($this->dat['files'][$res_fileID]['filename']) {
1476  // Resolve original filename:
1477  $relResourceFileName = $this->dat['files'][$res_fileID]['parentRelFileName'];
1478  $absResourceFileName = GeneralUtility::resolveBackPath(‪Environment::getPublicPath() . '/' . $origDirPrefix . $relResourceFileName);
1479  $absResourceFileName = GeneralUtility::getFileAbsFileName($absResourceFileName);
1480  if ($absResourceFileName && GeneralUtility::isFirstPartOfStr($absResourceFileName, ‪Environment::getPublicPath() . '/' . $this->fileadminFolderName . '/')) {
1481  $destDir = ‪PathUtility::stripPathSitePrefix(‪PathUtility::dirname($absResourceFileName) . '/');
1482  if ($this->‪verifyFolderAccess($destDir, true) && $this->‪checkOrCreateDir($destDir)) {
1483  $this->‪writeFileVerify($absResourceFileName, $res_fileID);
1484  } else {
1485  $this->‪error('ERROR: Could not create file in directory "' . $destDir . '"');
1486  }
1487  } else {
1488  $this->‪error('ERROR: Could not resolve path for "' . $relResourceFileName . '"');
1489  }
1490  $tokenizedContent = str_replace('{EXT_RES_ID:' . $res_fileID . '}', $relResourceFileName, $tokenizedContent);
1491  $tokenSubstituted = true;
1492  }
1493  }
1494  } else {
1495  // Create the ressource's directory name (filename without extension, suffixed "_FILES")
1496  $resourceDir = ‪PathUtility::dirname($newName) . '/' . preg_replace('/\\.[^.]*$/', '', ‪PathUtility::basename($newName)) . '_FILES';
1497  if (‪GeneralUtility::mkdir($resourceDir)) {
1498  foreach ($fileHeaderInfo['EXT_RES_ID'] as $res_fileID) {
1499  if ($this->dat['files'][$res_fileID]['filename']) {
1500  $absResourceFileName = (string)‪$fileProcObj->‪getUniqueName($this->dat['files'][$res_fileID]['filename'], $resourceDir);
1501  $relResourceFileName = substr($absResourceFileName, strlen(‪PathUtility::dirname($resourceDir)) + 1);
1502  $this->‪writeFileVerify($absResourceFileName, $res_fileID);
1503  $tokenizedContent = str_replace('{EXT_RES_ID:' . $res_fileID . '}', $relResourceFileName, $tokenizedContent);
1504  $tokenSubstituted = true;
1505  }
1506  }
1507  }
1508  }
1509  // If substitutions has been made, write the content to the file again:
1510  if ($tokenSubstituted) {
1511  ‪GeneralUtility::writeFile($newName, $tokenizedContent);
1512  }
1513  }
1514  return ‪PathUtility::stripPathSitePrefix($newName);
1515  }
1516  }
1517  return null;
1518  }
1528  public function ‪writeFileVerify($fileName, $fileID, $bypassMountCheck = false)
1529  {
1531  if (!‪$fileProcObj->actionPerms['addFile']) {
1532  $this->‪error('ERROR: You did not have sufficient permissions to write the file "' . $fileName . '"');
1533  return false;
1534  }
1535  // Just for security, check again. Should actually not be necessary.
1536  if (!$bypassMountCheck) {
1537  try {
1538  GeneralUtility::makeInstance(ResourceFactory::class)->getFolderObjectFromCombinedIdentifier(‪PathUtility::dirname($fileName));
1540  $this->‪error('ERROR: Filename "' . $fileName . '" was not allowed in destination path!');
1541  return false;
1542  }
1543  }
1544  $fI = GeneralUtility::split_fileref($fileName);
1545  if (!GeneralUtility::makeInstance(FileNameValidator::class)->isValid($fI['file'])) {
1546  $this->‪error('ERROR: Filename "' . $fileName . '" failed against extension check or deny-pattern!');
1547  return false;
1548  }
1549  if (!GeneralUtility::getFileAbsFileName($fileName)) {
1550  $this->‪error('ERROR: Filename "' . $fileName . '" was not a valid relative file path!');
1551  return false;
1552  }
1553  if (!$this->dat['files'][$fileID]) {
1554  $this->‪error('ERROR: File ID "' . $fileID . '" could not be found');
1555  return false;
1556  }
1557  ‪GeneralUtility::writeFile($fileName, $this->dat['files'][$fileID]['content']);
1558  $this->fileIDMap[$fileID] = $fileName;
1559  if (hash_equals(md5((string)file_get_contents($fileName)), $this->dat['files'][$fileID]['content_md5'])) {
1560  return true;
1561  }
1562  $this->‪error('ERROR: File content "' . $fileName . '" was corrupted');
1563  return false;
1564  }
1565 
1572  public function ‪checkOrCreateDir($dirPrefix)
1573  {
1574  // Split dir path and remove first directory (which should be "fileadmin")
1575  $filePathParts = explode('/', $dirPrefix);
1576  $firstDir = array_shift($filePathParts);
1577  if ($firstDir === $this->fileadminFolderName && GeneralUtility::getFileAbsFileName($dirPrefix)) {
1578  $pathAcc = '';
1579  foreach ($filePathParts as $dirname) {
1580  $pathAcc .= '/' . $dirname;
1581  if (strlen($dirname)) {
1582  if (!@is_dir(‪Environment::getPublicPath() . '/' . $this->fileadminFolderName . $pathAcc)) {
1583  if (!‪GeneralUtility::mkdir(‪Environment::getPublicPath() . '/' . $this->fileadminFolderName . $pathAcc)) {
1584  $this->‪error('ERROR: Directory could not be created....B');
1585  return false;
1586  }
1587  }
1588  } elseif ($dirPrefix === $this->fileadminFolderName . $pathAcc) {
1589  return true;
1590  } else {
1591  $this->‪error('ERROR: Directory could not be created....A');
1592  }
1593  }
1594  }
1595  return false;
1596  }
1597 
1598  /**************************
1599  * File Input
1600  *************************/
1601 
1609  public function ‪loadFile($filename, $all = false)
1610  {
1611  if (!@is_file($filename)) {
1612  $this->‪error('Filename not found: ' . $filename);
1613  return false;
1614  }
1615  $fI = pathinfo($filename);
1616  if (@is_dir($filename . '.files')) {
1617  if (GeneralUtility::isAllowedAbsPath($filename . '.files')) {
1618  // copy the folder lowlevel to typo3temp, because the files would be deleted after import
1619  $temporaryFolderName = $this->‪getTemporaryFolderName();
1620  GeneralUtility::copyDirectory($filename . '.files', $temporaryFolderName);
1621  $this->filesPathForImport = $temporaryFolderName;
1622  } else {
1623  $this->‪error('External import files for the given import source is currently not supported.');
1624  }
1625  }
1626  if (strtolower($fI['extension']) === 'xml') {
1627  // XML:
1628  $xmlContent = (string)file_get_contents($filename);
1629  if (strlen($xmlContent)) {
1630  $this->dat = ‪GeneralUtility::xml2array($xmlContent, '', true);
1631  if (is_array($this->dat)) {
1632  if ($this->dat['_DOCUMENT_TAG'] === 'T3RecordDocument' && is_array($this->dat['header']) && is_array($this->dat['records'])) {
1633  $this->‪loadInit();
1634  return true;
1635  }
1636  $this->‪error('XML file did not contain proper XML for TYPO3 Import');
1637  } else {
1638  $this->‪error('XML could not be parsed: ' . $this->dat);
1639  }
1640  } else {
1641  $this->‪error('Error opening file: ' . $filename);
1642  }
1643  } else {
1644  // T3D
1645  if ($fd = fopen($filename, 'rb')) {
1646  $this->dat['header'] = $this->‪getNextFilePart($fd, true, 'header');
1647  if ($all) {
1648  $this->dat['records'] = $this->‪getNextFilePart($fd, true, 'records');
1649  $this->dat['files'] = $this->‪getNextFilePart($fd, true, 'files');
1650  $this->dat['files_fal'] = $this->‪getNextFilePart($fd, true, 'files_fal');
1651  }
1652  $this->‪loadInit();
1653  fclose($fd);
1654  return true;
1655  }
1656  $this->‪error('Error opening file: ' . $filename);
1657  }
1658  return false;
1659  }
1660 
1671  public function ‪getNextFilePart($fd, $unserialize = false, $name = '')
1672  {
1673  $initStrLen = 32 + 1 + 1 + 1 + 10 + 1;
1674  // Getting header data
1675  $initStr = fread($fd, $initStrLen);
1676  if (empty($initStr)) {
1677  $this->‪error('File does not contain data for "' . $name . '"');
1678  return null;
1679  }
1680  $initStrDat = explode(':', $initStr);
1681  if (strpos($initStrDat[0], 'Warning') !== false) {
1682  $this->‪error('File read error: Warning message in file. (' . $initStr . fgets($fd) . ')');
1683  return null;
1684  }
1685  if ((string)$initStrDat[3] !== '') {
1686  $this->‪error('File read error: InitString had a wrong length. (' . $name . ')');
1687  return null;
1688  }
1689  $datString = (string)fread($fd, (int)$initStrDat[2]);
1690  fread($fd, 1);
1691  if (hash_equals($initStrDat[0], md5($datString))) {
1692  if ($initStrDat[1]) {
1693  if ($this->compress) {
1694  $datString = (string)gzuncompress($datString);
1695  } else {
1696  $this->‪error('Content read error: This file requires decompression, but this server does not offer gzcompress()/gzuncompress() functions.');
1697  return null;
1698  }
1699  }
1700  return $unserialize ? unserialize($datString, ['allowed_classes' => false]) : $datString;
1701  }
1702  $this->‪error('MD5 check failed (' . $name . ')');
1703 
1704  return null;
1705  }
1706 
1713  public function ‪loadContent($filecontent)
1714  {
1715  $pointer = 0;
1716  $this->dat['header'] = $this->‪getNextContentPart($filecontent, $pointer, true, 'header');
1717  $this->dat['records'] = $this->‪getNextContentPart($filecontent, $pointer, true, 'records');
1718  $this->dat['files'] = $this->‪getNextContentPart($filecontent, $pointer, true, 'files');
1719  $this->‪loadInit();
1720  }
1721 
1731  public function ‪getNextContentPart($filecontent, &$pointer, $unserialize = false, $name = '')
1732  {
1733  $initStrLen = 32 + 1 + 1 + 1 + 10 + 1;
1734  // getting header data
1735  $initStr = substr($filecontent, $pointer, $initStrLen);
1736  $pointer += $initStrLen;
1737  $initStrDat = explode(':', $initStr);
1738  if ((string)$initStrDat[3] !== '') {
1739  $this->‪error('Content read error: InitString had a wrong length. (' . $name . ')');
1740  return null;
1741  }
1742  $datString = (string)substr($filecontent, $pointer, (int)$initStrDat[2]);
1743  $pointer += (int)$initStrDat[2] + 1;
1744  if (hash_equals($initStrDat[0], md5($datString))) {
1745  if ($initStrDat[1]) {
1746  if ($this->compress) {
1747  $datString = (string)gzuncompress($datString);
1748  return $unserialize ? unserialize($datString, ['allowed_classes' => false]) : $datString;
1749  }
1750  $this->‪error('Content read error: This file requires decompression, but this server does not offer gzcompress()/gzuncompress() functions.');
1751  }
1752  } else {
1753  $this->‪error('MD5 check failed (' . $name . ')');
1754  }
1755  return null;
1756  }
1757 
1761  public function ‪loadInit()
1762  {
1763  $this->relStaticTables = (array)$this->dat['header']['relStaticTables'];
1764  $this->excludeMap = (array)$this->dat['header']['excludeMap'];
1765  $this->softrefCfg = (array)$this->dat['header']['softrefCfg'];
1766  }
1767 }
‪TYPO3\CMS\Core\DataHandling\DataHandler
Definition: DataHandler.php:84
‪TYPO3\CMS\Impexp\Import\processSoftReferences_flexFormCallBack
‪array processSoftReferences_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2, $path)
Definition: Import.php:1315
‪TYPO3\CMS\Core\Utility\GeneralUtility\xml2array
‪static mixed xml2array($string, $NSprefix='', $reportDocTag=false)
Definition: GeneralUtility.php:1531
‪TYPO3\CMS\Impexp\Import\$enableLogging
‪bool $enableLogging
Definition: Import.php:54
‪TYPO3\CMS\Impexp\ImportExport\flatInversePageTree
‪array flatInversePageTree($idH, $a=[])
Definition: ImportExport.php:943
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:24
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:74
‪TYPO3\CMS\Impexp\Import\processSoftReferences_substTokens
‪string processSoftReferences_substTokens($tokenizedContent, $softRefCfgs, $table, $uid)
Definition: Import.php:1349
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:180
‪TYPO3\CMS\Core\Resource\FileInterface
Definition: FileInterface.php:22
‪TYPO3\CMS\Impexp\Import\$import_newId
‪array $import_newId
Definition: Import.php:62
‪TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
Definition: InsufficientFolderAccessPermissionsException.php:24
‪TYPO3\CMS\Impexp\ImportExport\callHook
‪callHook($name, $params)
Definition: ImportExport.php:1162
‪TYPO3\CMS\Core\Resource\ResourceStorage\getDriverType
‪string getDriverType()
Definition: ResourceStorage.php:2865
‪TYPO3\CMS\Core\Utility\PathUtility\dirname
‪static string dirname($path)
Definition: PathUtility.php:186
‪TYPO3\CMS\Impexp\Import\checkImportPrerequisites
‪array checkImportPrerequisites()
Definition: Import.php:257
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:22
‪TYPO3\CMS\Core\Resource\Security\FileNameValidator
Definition: FileNameValidator.php:25
‪TYPO3\CMS\Impexp\Import\removeSysFileReferenceRecordsFromImportDataWithRelationToMissingFile
‪removeSysFileReferenceRecordsFromImportDataWithRelationToMissingFile()
Definition: Import.php:451
‪TYPO3\CMS\Impexp\Import\getNewTCE
‪DataHandler getNewTCE()
Definition: Import.php:936
‪TYPO3\CMS\Impexp\Import\setRelations
‪setRelations()
Definition: Import.php:969
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:372
‪TYPO3\CMS\Impexp\Import\loadInit
‪loadInit()
Definition: Import.php:1752
‪TYPO3\CMS\Impexp\ImportExport\error
‪error($msg)
Definition: ImportExport.php:1191
‪TYPO3\CMS\Impexp\Import\setRelations_db
‪array setRelations_db($itemArray, $itemConfig)
Definition: Import.php:1036
‪TYPO3\CMS\Core\Exception
‪TYPO3\CMS\Impexp\Import\writeRecords_records_order
‪writeRecords_records_order($mainPid)
Definition: Import.php:747
‪TYPO3\CMS\Impexp\Import\$import_newId_pids
‪array $import_newId_pids
Definition: Import.php:68
‪TYPO3\CMS\Impexp\Import\flatInversePageTree_pid
‪array flatInversePageTree_pid($idH, $a=[], $pid=-1)
Definition: Import.php:664
‪TYPO3\CMS\Impexp\Import\fixUidLocalInSysFileReferenceRecords
‪fixUidLocalInSysFileReferenceRecords($oldFileUid, $newFileUid)
Definition: Import.php:497
‪TYPO3\CMS\Impexp\Import\writeRecords_pages
‪writeRecords_pages($pid)
Definition: Import.php:566
‪TYPO3\CMS\Impexp\ImportExport\isTableStatic
‪bool isTableStatic($table)
Definition: ImportExport.php:963
‪TYPO3\CMS\Impexp\Import\init
‪init()
Definition: Import.php:101
‪TYPO3\CMS\Core\Utility\PathUtility\basename
‪static string basename($path)
Definition: PathUtility.php:165
‪TYPO3\CMS\Impexp\Import\processSoftReferences_saveFile
‪string processSoftReferences_saveFile($relFileName, $cfg, $table, $uid)
Definition: Import.php:1401
‪TYPO3\CMS\Impexp\Import\loadFile
‪bool loadFile($filename, $all=false)
Definition: Import.php:1600
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility
Definition: ExtensionManagementUtility.php:43
‪TYPO3\CMS\Impexp\Import\$storageObjects
‪ResourceStorage[] $storageObjects
Definition: Import.php:80
‪TYPO3\CMS\Impexp\Import\writeSysFileStorageRecords
‪writeSysFileStorageRecords()
Definition: Import.php:170
‪TYPO3\CMS\Impexp\Import\$suggestedInsertUids
‪array $suggestedInsertUids
Definition: Import.php:48
‪TYPO3\CMS\Impexp\Import\processSoftReferences_saveFile_createRelFile
‪string null processSoftReferences_saveFile_createRelFile($origDirPrefix, $fileName, $fileID, $table, $uid)
Definition: Import.php:1435
‪TYPO3\CMS\Impexp\ImportExport\verifyFolderAccess
‪string bool verifyFolderAccess($dirPrefix, $noAlternative=false)
Definition: ImportExport.php:896
‪TYPO3\CMS\Core\Resource\ResourceStorage\isOnline
‪bool isOnline()
Definition: ResourceStorage.php:448
‪TYPO3\CMS\Impexp\Import\isEquivalentObjectStorage
‪bool isEquivalentObjectStorage(ResourceStorage $storageObject, array $storageRecord)
Definition: Import.php:233
‪TYPO3\CMS\Impexp\Import
Definition: Import.php:42
‪TYPO3\CMS\Impexp\ImportExport\$fileProcObj
‪ExtendedFileUtility $fileProcObj
Definition: ImportExport.php:218
‪TYPO3\CMS\Impexp\Import\writeSysFileRecords
‪writeSysFileRecords()
Definition: Import.php:319
‪TYPO3\CMS\Impexp\Import\addToMapId
‪addToMapId($substNEWwithIDs)
Definition: Import.php:910
‪TYPO3\CMS\Impexp\Import\writeFileVerify
‪bool writeFileVerify($fileName, $fileID, $bypassMountCheck=false)
Definition: Import.php:1519
‪TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools
Definition: FlexFormTools.php:38
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:41
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:31
‪TYPO3\CMS\Impexp\Import\loadContent
‪loadContent($filecontent)
Definition: Import.php:1704
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:24
‪TYPO3\CMS\Impexp\Import\initializeImport
‪initializeImport()
Definition: Import.php:114
‪TYPO3\CMS\Core\Resource\ResourceStorage\getConfiguration
‪array getConfiguration()
Definition: ResourceStorage.php:259
‪TYPO3\CMS\Impexp\Import\initializeStorageObjects
‪initializeStorageObjects()
Definition: Import.php:132
‪TYPO3\CMS\Impexp\ImportExport
Definition: ImportExport.php:70
‪TYPO3\CMS\Impexp\Import\$unlinkFiles
‪array $unlinkFiles
Definition: Import.php:88
‪TYPO3\CMS\Impexp\Import\writeRecords_pages_order
‪writeRecords_pages_order()
Definition: Import.php:622
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:75
‪TYPO3\CMS\Core\Utility\File\BasicFileUtility\getUniqueName
‪string null getUniqueName($theFile, $theDest, $dontCheckForUnique=false)
Definition: BasicFileUtility.php:101
‪TYPO3\CMS\Impexp\Import\unlinkTempFiles
‪unlinkTempFiles()
Definition: Import.php:947
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:95
‪TYPO3\CMS\Impexp\ImportExport\isExcluded
‪bool isExcluded($table, $uid)
Definition: ImportExport.php:991
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:122
‪TYPO3\CMS\Core\Utility\StringUtility\getUniqueId
‪static string getUniqueId($prefix='')
Definition: StringUtility.php:92
‪TYPO3\CMS\Impexp\ImportExport\getTemporaryFolderName
‪string getTemporaryFolderName()
Definition: ImportExport.php:925
‪TYPO3\CMS\Impexp\Import\importData
‪importData($pid)
Definition: Import.php:144
‪TYPO3\CMS\Impexp\Import\addSingle
‪addSingle($table, $uid, $pid)
Definition: Import.php:799
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Impexp\ImportExport\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: ImportExport.php:1209
‪TYPO3\CMS\Impexp\ImportExport\dontIgnorePid
‪bool dontIgnorePid($table, $uid)
Definition: ImportExport.php:1029
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Impexp\Import\$import_data
‪array $import_data
Definition: Import.php:74
‪TYPO3\CMS\Impexp\Import\isFallbackStorage
‪bool isFallbackStorage($storageId)
Definition: Import.php:477
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:22
‪TYPO3\CMS\Impexp\Import\getNextFilePart
‪string null getNextFilePart($fd, $unserialize=false, $name='')
Definition: Import.php:1662
‪TYPO3\CMS\Impexp\ImportExport\getFileProcObj
‪ExtendedFileUtility getFileProcObj()
Definition: ImportExport.php:1147
‪TYPO3\CMS\Impexp\Import\setFlexFormRelations
‪setFlexFormRelations()
Definition: Import.php:1109
‪TYPO3\CMS\Core\Resource\ResourceStorage\isWritable
‪bool isWritable()
Definition: ResourceStorage.php:383
‪TYPO3\CMS\Impexp\ImportExport\addGeneralErrorsByTable
‪addGeneralErrorsByTable($table)
Definition: ImportExport.php:451
‪TYPO3\CMS\Impexp\ImportExport\$dat
‪array $dat
Definition: ImportExport.php:212
‪TYPO3\CMS\Impexp\Import\checkOrCreateDir
‪bool checkOrCreateDir($dirPrefix)
Definition: Import.php:1563
‪TYPO3\CMS\Impexp\Import\remapListedDBRecords_flexFormCallBack
‪array remapListedDBRecords_flexFormCallBack($pParams, $dsConf, $dataValue, $dataValue_ext1, $dataValue_ext2, $path)
Definition: Import.php:1198
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Impexp\Import\writeTemporaryFileFromData
‪string writeTemporaryFileFromData($fileId, $dataKey='files_fal')
Definition: Import.php:541
‪TYPO3\CMS\Impexp\Import\writeRecords_records
‪writeRecords_records($pid)
Definition: Import.php:684
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:22
‪TYPO3\CMS\Core\Utility\GeneralUtility\mkdir
‪static bool mkdir($newFolder)
Definition: GeneralUtility.php:2005
‪TYPO3\CMS\Core\Utility\GeneralUtility\writeFile
‪static bool writeFile($file, $content, $changePermissions=false)
Definition: GeneralUtility.php:1836
‪TYPO3\CMS\Impexp\Import\$filePathMap
‪array $filePathMap
Definition: Import.php:92
‪TYPO3\CMS\Core\Utility\ExtensionManagementUtility\isLoaded
‪static bool isLoaded($key)
Definition: ExtensionManagementUtility.php:114
‪TYPO3\CMS\Impexp\Import\import_addFileNameToBeCopied
‪string null import_addFileNameToBeCopied($fI)
Definition: Import.php:1076
‪TYPO3\CMS\Impexp\Import\getNextContentPart
‪string null getNextContentPart($filecontent, &$pointer, $unserialize=false, $name='')
Definition: Import.php:1722
‪TYPO3\CMS\Impexp
‪TYPO3\CMS\Backend\Utility\BackendUtility\wsMapId
‪static int wsMapId($table, $uid)
Definition: BackendUtility.php:3827
‪TYPO3\CMS\Impexp\Import\processSoftReferences
‪processSoftReferences()
Definition: Import.php:1227
‪TYPO3\CMS\Impexp\ImportExport\doesRecordExist
‪array doesRecordExist($table, $uid, $fields='')
Definition: ImportExport.php:1042
‪TYPO3\CMS\Impexp\Import\$filesPathForImport
‪string null $filesPathForImport
Definition: Import.php:84
‪TYPO3\CMS\Impexp\Import\fetchStorageRecords
‪bool array fetchStorageRecords()
Definition: Import.php:519