‪TYPO3CMS  9.5
Export.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 
26 
62 {
67  public ‪$maxFileSize = 1000000;
68 
73  public ‪$maxRecordSize = 1000000;
74 
79  public ‪$maxExportSize = 10000000;
80 
86  public ‪$dontCompress = false;
87 
93  public ‪$includeExtFileResources = false;
94 
100  public ‪$extFileResourceExtensions = 'html,htm,css';
101 
108  protected ‪$recordTypesIncludeFields = [];
109 
115  protected ‪$defaultRecordIncludeFields = ['uid', 'pid'];
116 
120  protected ‪$saveFilesOutsideExportFile = false;
121 
126 
127  /**************************
128  * Initialize
129  *************************/
130 
136  public function ‪init(‪$dontCompress = false)
137  {
138  parent::init();
139  $this->dontCompress = ‪$dontCompress;
140  $this->mode = 'export';
141  }
142 
143  /**************************
144  * Export / Init + Meta Data
145  *************************/
146 
150  public function ‪setHeaderBasics()
151  {
152  // Initializing:
153  if (is_array($this->softrefCfg)) {
154  foreach ($this->softrefCfg as $key => $value) {
155  if (!strlen($value['mode'])) {
156  unset($this->softrefCfg[$key]);
157  }
158  }
159  }
160  // Setting in header memory:
161  // Version of file format
162  $this->dat['header']['XMLversion'] = '1.0';
163  // Initialize meta data array (to put it in top of file)
164  $this->dat['header']['meta'] = [];
165  // Add list of tables to consider static
166  $this->dat['header']['relStaticTables'] = ‪$this->relStaticTables;
167  // The list of excluded records
168  $this->dat['header']['excludeMap'] = ‪$this->excludeMap;
169  // Soft Reference mode for elements
170  $this->dat['header']['softrefCfg'] = ‪$this->softrefCfg;
171  // List of extensions the import depends on.
172  $this->dat['header']['extensionDependencies'] = ‪$this->extensionDependencies;
173  $this->dat['header']['charset'] = 'utf-8';
174  }
175 
181  public function ‪setCharset($charset)
182  {
183  $this->dat['header']['charset'] = $charset;
184  }
185 
196  public function ‪setMetaData($title, $description, $notes, $packager_username, $packager_name, $packager_email)
197  {
198  $this->dat['header']['meta'] = [
199  'title' => $title,
200  'description' => $description,
201  'notes' => $notes,
202  'packager_username' => $packager_username,
203  'packager_name' => $packager_name,
204  'packager_email' => $packager_email,
205  'TYPO3_version' => TYPO3_version,
206  'created' => strftime('%A %e. %B %Y', ‪$GLOBALS['EXEC_TIME'])
207  ];
208  }
209 
218  {
219  $this->saveFilesOutsideExportFile = ‪$saveFilesOutsideExportFile;
220  }
221 
222  /**************************
223  * Export / Init Page tree
224  *************************/
225 
232  public function ‪setPageTree($idH)
233  {
234  $this->dat['header']['pagetree'] = $this->‪unsetExcludedSections($idH);
235  return $this->‪flatInversePageTree($this->dat['header']['pagetree']);
236  }
237 
246  public function ‪unsetExcludedSections($idH)
247  {
248  if (is_array($idH)) {
249  foreach ($idH as $k => $v) {
250  if ($this->excludeMap['pages:' . $idH[$k]['uid']]) {
251  unset($idH[$k]);
252  } elseif (is_array($idH[$k]['subrow'])) {
253  $idH[$k]['subrow'] = $this->‪unsetExcludedSections($idH[$k]['subrow']);
254  }
255  }
256  }
257  return $idH;
258  }
259 
260  /**************************
261  * Export
262  *************************/
263 
271  {
272  foreach (‪$recordTypesIncludeFields as $table => ‪$fields) {
273  if (!is_array(‪$fields)) {
274  throw new ‪Exception('The include fields for record type ' . htmlspecialchars($table) . ' are not defined by an array.', 1391440658);
275  }
277  }
278  }
279 
286  public function ‪setRecordTypeIncludeFields($table, array ‪$fields)
287  {
288  $this->recordTypesIncludeFields[$table] = ‪$fields;
289  }
290 
299  public function ‪export_addRecord($table, $row, $relationLevel = 0)
300  {
301  ‪BackendUtility::workspaceOL($table, $row);
302  if ($this->excludeDisabledRecords && !$this->‪isActive($table, $row['uid'])) {
303  return;
304  }
305  if ((string)$table !== '' && is_array($row) && $row['uid'] > 0 && !$this->excludeMap[$table . ':' . $row['uid']]) {
306  if ($this->‪checkPID($table === 'pages' ? $row['uid'] : $row['pid'])) {
307  if (!isset($this->dat['records'][$table . ':' . $row['uid']])) {
308  // Prepare header info:
309  $row = $this->‪filterRecordFields($table, $row);
310  $headerInfo = [];
311  $headerInfo['uid'] = $row['uid'];
312  $headerInfo['pid'] = $row['pid'];
313  $headerInfo['title'] = GeneralUtility::fixed_lgd_cs(‪BackendUtility::getRecordTitle($table, $row), 40);
314  if ($relationLevel) {
315  $headerInfo['relationLevel'] = $relationLevel;
316  }
317  // Set the header summary:
318  $this->dat['header']['records'][$table][$row['uid']] = $headerInfo;
319  // Create entry in the PID lookup:
320  $this->dat['header']['pid_lookup'][$row['pid']][$table][$row['uid']] = 1;
321  // Initialize reference index object:
322  $refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class);
323  $refIndexObj->enableRuntimeCache();
324  // Yes to workspace overlays for exporting....
325  $refIndexObj->WSOL = true;
326  $relations = $refIndexObj->getRelations($table, $row);
327  $relations = $this->‪fixFileIDsInRelations($relations);
328  $relations = $this->‪removeSoftrefsHavingTheSameDatabaseRelation($relations);
329  // Data:
330  $this->dat['records'][$table . ':' . $row['uid']] = [];
331  $this->dat['records'][$table . ':' . $row['uid']]['data'] = $row;
332  $this->dat['records'][$table . ':' . $row['uid']]['rels'] = $relations;
333  // Add information about the relations in the record in the header:
334  $this->dat['header']['records'][$table][$row['uid']]['rels'] = $this->‪flatDBrels($this->dat['records'][$table . ':' . $row['uid']]['rels']);
335  // Add information about the softrefs to header:
336  $this->dat['header']['records'][$table][$row['uid']]['softrefs'] = $this->‪flatSoftRefs($this->dat['records'][$table . ':' . $row['uid']]['rels']);
337  } else {
338  $this->‪error('Record ' . $table . ':' . $row['uid'] . ' already added.');
339  }
340  } else {
341  $this->‪error('Record ' . $table . ':' . $row['uid'] . ' was outside your DB mounts!');
342  }
343  }
344  }
345 
353  protected function ‪fixFileIDsInRelations(array $relations)
354  {
355  foreach ($relations as $field => $relation) {
356  if (isset($relation['type']) && $relation['type'] === 'file') {
357  foreach ($relation['newValueFiles'] as $key => $fileRelationData) {
358  $absoluteFilePath = $fileRelationData['ID_absFile'];
359  if (GeneralUtility::isFirstPartOfStr($absoluteFilePath, ‪Environment::getPublicPath())) {
360  $relatedFilePath = ‪PathUtility::stripPathSitePrefix($absoluteFilePath);
361  $relations[$field]['newValueFiles'][$key]['ID'] = md5($relatedFilePath);
362  }
363  }
364  }
365  if ($relation['type'] === 'flex') {
366  if (is_array($relation['flexFormRels']['file'])) {
367  foreach ($relation['flexFormRels']['file'] as $key => $subList) {
368  foreach ($subList as $subKey => $fileRelationData) {
369  $absoluteFilePath = $fileRelationData['ID_absFile'];
370  if (GeneralUtility::isFirstPartOfStr($absoluteFilePath, ‪Environment::getPublicPath())) {
371  $relatedFilePath = ‪PathUtility::stripPathSitePrefix($absoluteFilePath);
372  $relations[$field]['flexFormRels']['file'][$key][$subKey]['ID'] = md5($relatedFilePath);
373  }
374  }
375  }
376  }
377  }
378  }
379  return $relations;
380  }
381 
391  protected function ‪removeSoftrefsHavingTheSameDatabaseRelation($relations)
392  {
393  $fixedRelations = [];
394  foreach ($relations as $field => $relation) {
395  $newRelation = $relation;
396  if (isset($newRelation['type']) && $newRelation['type'] === 'db') {
397  foreach ($newRelation['itemArray'] as $key => $dbRelationData) {
398  if ($dbRelationData['table'] === 'sys_file') {
399  if (isset($newRelation['softrefs']['keys']['typolink'])) {
400  foreach ($newRelation['softrefs']['keys']['typolink'] as $softrefKey => $softRefData) {
401  if ($softRefData['subst']['type'] === 'file') {
402  $file = ‪ResourceFactory::getInstance()->‪retrieveFileOrFolderObject($softRefData['subst']['relFileName']);
403  if ($file instanceof ‪File) {
404  if ($file->getUid() == $dbRelationData['id']) {
405  unset($newRelation['softrefs']['keys']['typolink'][$softrefKey]);
406  }
407  }
408  }
409  }
410  if (empty($newRelation['softrefs']['keys']['typolink'])) {
411  unset($newRelation['softrefs']);
412  }
413  }
414  }
415  }
416  }
417  $fixedRelations[$field] = $newRelation;
418  }
419  return $fixedRelations;
420  }
421 
432  public function ‪export_addDBRelations($relationLevel = 0)
433  {
434  // Traverse all "rels" registered for "records"
435  if (!is_array($this->dat['records'])) {
436  $this->‪error('There were no records available.');
437  return [];
438  }
439  $addR = [];
440  foreach ($this->dat['records'] as $k => $value) {
441  if (!is_array($this->dat['records'][$k])) {
442  continue;
443  }
444  foreach ($this->dat['records'][$k]['rels'] as $fieldname => $vR) {
445  // For all DB types of relations:
446  if ($vR['type'] === 'db') {
447  foreach ($vR['itemArray'] as $fI) {
449  }
450  }
451  // For all flex/db types of relations:
452  if ($vR['type'] === 'flex') {
453  // DB relations in flex form fields:
454  if (is_array($vR['flexFormRels']['db'])) {
455  foreach ($vR['flexFormRels']['db'] as $subList) {
456  foreach ($subList as $fI) {
458  }
459  }
460  }
461  // DB oriented soft references in flex form fields:
462  if (is_array($vR['flexFormRels']['softrefs'])) {
463  foreach ($vR['flexFormRels']['softrefs'] as $subList) {
464  foreach ($subList['keys'] as $spKey => $elements) {
465  foreach ($elements as $el) {
466  if ($el['subst']['type'] === 'db' && $this->‪includeSoftref($el['subst']['tokenID'])) {
467  list($tempTable, $tempUid) = explode(':', $el['subst']['recordRef']);
468  $fI = [
469  'table' => $tempTable,
470  'id' => $tempUid
471  ];
472  $this->‪export_addDBRelations_registerRelation($fI, $addR, $el['subst']['tokenID']);
473  }
474  }
475  }
476  }
477  }
478  }
479  // In any case, if there are soft refs:
480  if (is_array($vR['softrefs']['keys'])) {
481  foreach ($vR['softrefs']['keys'] as $spKey => $elements) {
482  foreach ($elements as $el) {
483  if ($el['subst']['type'] === 'db' && $this->‪includeSoftref($el['subst']['tokenID'])) {
484  list($tempTable, $tempUid) = explode(':', $el['subst']['recordRef']);
485  $fI = [
486  'table' => $tempTable,
487  'id' => $tempUid
488  ];
489  $this->‪export_addDBRelations_registerRelation($fI, $addR, $el['subst']['tokenID']);
490  }
491  }
492  }
493  }
494  }
495  }
496 
497  // Now, if there were new records to add, do so:
498  if (!empty($addR)) {
499  foreach ($addR as $fI) {
500  // Get and set record:
501  $row = ‪BackendUtility::getRecord($fI['table'], $fI['id']);
502  // Depending on db driver, int fields may or may not be returned as integer or as string. The
503  // loop aligns that detail and forces strings for everything to have exports more db agnostic.
504  foreach ($row as $fieldName => $value) {
505  // Keep null but force everything else to string
506  $row[$fieldName] = $value === null ? $value : (string)$value;
507  }
508 
509  if (is_array($row)) {
510  $this->‪export_addRecord($fI['table'], $row, $relationLevel + 1);
511  }
512  // Set status message
513  // Relation pointers always larger than zero except certain "select" types with
514  // negative values pointing to uids - but that is not supported here.
515  if ($fI['id'] > 0) {
516  $rId = $fI['table'] . ':' . $fI['id'];
517  if (!isset($this->dat['records'][$rId])) {
518  $this->dat['records'][$rId] = 'NOT_FOUND';
519  $this->‪error('Relation record ' . $rId . ' was not found!');
520  }
521  }
522  }
523  }
524  // Return overview of relations found and added
525  return $addR;
526  }
527 
536  public function ‪export_addDBRelations_registerRelation($fI, &$addR, $tokenID = '')
537  {
538  $rId = $fI['table'] . ':' . $fI['id'];
539  if (
540  isset(‪$GLOBALS['TCA'][$fI['table']]) && !$this->‪isTableStatic($fI['table']) && !$this->‪isExcluded($fI['table'], $fI['id'])
541  && (!$tokenID || $this->‪includeSoftref($tokenID)) && $this->‪inclRelation($fI['table'])
542  ) {
543  if (!isset($this->dat['records'][$rId])) {
544  // Set this record to be included since it is not already.
545  $addR[$rId] = $fI;
546  }
547  }
548  }
549 
556  public function ‪export_addFilesFromRelations()
557  {
558  // Traverse all "rels" registered for "records"
559  if (!is_array($this->dat['records'])) {
560  $this->‪error('There were no records available.');
561  return;
562  }
563  foreach ($this->dat['records'] as $k => $value) {
564  if (!isset($this->dat['records'][$k]['rels']) || !is_array($this->dat['records'][$k]['rels'])) {
565  continue;
566  }
567  foreach ($this->dat['records'][$k]['rels'] as $fieldname => $vR) {
568  // For all file type relations:
569  if ($vR['type'] === 'file') {
570  foreach ($vR['newValueFiles'] as $key => $fI) {
571  $this->‪export_addFile($fI, $k, $fieldname);
572  // Remove the absolute reference to the file so it doesn't expose absolute paths from source server:
573  unset($this->dat['records'][$k]['rels'][$fieldname]['newValueFiles'][$key]['ID_absFile']);
574  }
575  }
576  // For all flex type relations:
577  if ($vR['type'] === 'flex') {
578  if (is_array($vR['flexFormRels']['file'])) {
579  foreach ($vR['flexFormRels']['file'] as $key => $subList) {
580  foreach ($subList as $subKey => $fI) {
581  $this->‪export_addFile($fI, $k, $fieldname);
582  // Remove the absolute reference to the file so it doesn't expose absolute paths from source server:
583  unset($this->dat['records'][$k]['rels'][$fieldname]['flexFormRels']['file'][$key][$subKey]['ID_absFile']);
584  }
585  }
586  }
587  // DB oriented soft references in flex form fields:
588  if (is_array($vR['flexFormRels']['softrefs'])) {
589  foreach ($vR['flexFormRels']['softrefs'] as $key => $subList) {
590  foreach ($subList['keys'] as $spKey => $elements) {
591  foreach ($elements as $subKey => $el) {
592  if ($el['subst']['type'] === 'file' && $this->‪includeSoftref($el['subst']['tokenID'])) {
593  // Create abs path and ID for file:
594  $ID_absFile = GeneralUtility::getFileAbsFileName(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
595  $ID = md5($el['subst']['relFileName']);
596  if ($ID_absFile) {
597  if (!$this->dat['files'][$ID]) {
598  $fI = [
599  'filename' => ‪PathUtility::basename($ID_absFile),
600  'ID_absFile' => $ID_absFile,
601  'ID' => $ID,
602  'relFileName' => $el['subst']['relFileName']
603  ];
604  $this->‪export_addFile($fI, '_SOFTREF_');
605  }
606  $this->dat['records'][$k]['rels'][$fieldname]['flexFormRels']['softrefs'][$key]['keys'][$spKey][$subKey]['file_ID'] = $ID;
607  }
608  }
609  }
610  }
611  }
612  }
613  }
614  // In any case, if there are soft refs:
615  if (is_array($vR['softrefs']['keys'])) {
616  foreach ($vR['softrefs']['keys'] as $spKey => $elements) {
617  foreach ($elements as $subKey => $el) {
618  if ($el['subst']['type'] === 'file' && $this->‪includeSoftref($el['subst']['tokenID'])) {
619  // Create abs path and ID for file:
620  $ID_absFile = GeneralUtility::getFileAbsFileName(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
621  $ID = md5($el['subst']['relFileName']);
622  if ($ID_absFile) {
623  if (!$this->dat['files'][$ID]) {
624  $fI = [
625  'filename' => ‪PathUtility::basename($ID_absFile),
626  'ID_absFile' => $ID_absFile,
627  'ID' => $ID,
628  'relFileName' => $el['subst']['relFileName']
629  ];
630  $this->‪export_addFile($fI, '_SOFTREF_');
631  }
632  $this->dat['records'][$k]['rels'][$fieldname]['softrefs']['keys'][$spKey][$subKey]['file_ID'] = $ID;
633  }
634  }
635  }
636  }
637  }
638  }
639  }
640  }
641 
645  public function ‪export_addFilesFromSysFilesRecords()
646  {
647  if (!isset($this->dat['header']['records']['sys_file']) || !is_array($this->dat['header']['records']['sys_file'])) {
648  return;
649  }
650  foreach ($this->dat['header']['records']['sys_file'] as $sysFileUid => $_) {
651  $recordData = $this->dat['records']['sys_file:' . $sysFileUid]['data'];
653  $this->‪export_addSysFile($file);
654  }
655  }
656 
662  public function ‪export_addSysFile(File $file)
663  {
664  $fileContent = '';
665  try {
666  if (!$this->saveFilesOutsideExportFile) {
667  $fileContent = $file->getContents();
668  } else {
669  $file->checkActionPermission('read');
670  }
671  } catch (\Exception $e) {
672  $this->‪error('Error when trying to add file ' . $file->getCombinedIdentifier() . ': ' . $e->getMessage());
673  return;
674  }
675  $fileUid = $file->getUid();
676  $fileSha1 = $file->getStorage()->hashFile($file, 'sha1');
677  if ($fileSha1 !== $file->getProperty('sha1')) {
678  $this->‪error('File sha1 hash of ' . $file->getCombinedIdentifier() . ' is not up-to-date in index! File added on current sha1.');
679  $this->dat['records']['sys_file:' . $fileUid]['data']['sha1'] = $fileSha1;
680  }
681 
682  $fileRec = [];
683  $fileRec['filename'] = $file->getProperty('name');
684  $fileRec['filemtime'] = $file->getProperty('modification_date');
685 
686  // build unique id based on the storage and the file identifier
687  $fileId = md5($file->getStorage()->getUid() . ':' . $file->getProperty('identifier_hash'));
688 
689  // Setting this data in the header
690  $this->dat['header']['files_fal'][$fileId] = $fileRec;
691 
692  if (!$this->saveFilesOutsideExportFile) {
693  // ... and finally add the heavy stuff:
694  $fileRec['content'] = $fileContent;
695  } else {
696  GeneralUtility::upload_copy_move($file->getForLocalProcessing(false), $this->getTemporaryFilesPathForExport() . $file->getProperty('sha1'));
697  }
698  $fileRec['content_sha1'] = $fileSha1;
699 
700  $this->dat['files_fal'][$fileId] = $fileRec;
701  }
702 
710  public function ‪export_addFile($fI, $recordRef = '', $fieldname = '')
711  {
712  if (!@is_file($fI['ID_absFile'])) {
713  $this->‪error($fI['ID_absFile'] . ' was not a file! Skipping.');
714  return;
715  }
716  $fileInfo = stat($fI['ID_absFile']);
717  $fileRec = [];
718  $fileRec['filename'] = ‪PathUtility::basename($fI['ID_absFile']);
719  $fileRec['filemtime'] = $fileInfo['mtime'];
720  //for internal type file_reference
721  $fileRec['relFileRef'] = ‪PathUtility::stripPathSitePrefix($fI['ID_absFile']);
722  if ($recordRef) {
723  $fileRec['record_ref'] = $recordRef . '/' . $fieldname;
724  }
725  if ($fI['relFileName']) {
726  $fileRec['relFileName'] = $fI['relFileName'];
727  }
728  // Setting this data in the header
729  $this->dat['header']['files'][$fI['ID']] = $fileRec;
730  // ... and for the recordlisting, why not let us know WHICH relations there was...
731  if ($recordRef && $recordRef !== '_SOFTREF_') {
732  $refParts = explode(':', $recordRef, 2);
733  if (!is_array($this->dat['header']['records'][$refParts[0]][$refParts[1]]['filerefs'])) {
734  $this->dat['header']['records'][$refParts[0]][$refParts[1]]['filerefs'] = [];
735  }
736  $this->dat['header']['records'][$refParts[0]][$refParts[1]]['filerefs'][] = $fI['ID'];
737  }
738  $fileMd5 = md5_file($fI['ID_absFile']);
739  if (!$this->saveFilesOutsideExportFile) {
740  // ... and finally add the heavy stuff:
741  $fileRec['content'] = file_get_contents($fI['ID_absFile']);
742  } else {
743  GeneralUtility::upload_copy_move($fI['ID_absFile'], $this->‪getTemporaryFilesPathForExport() . $fileMd5);
744  }
745  $fileRec['content_md5'] = $fileMd5;
746  $this->dat['files'][$fI['ID']] = $fileRec;
747  // For soft references, do further processing:
748  if ($recordRef === '_SOFTREF_') {
749  // RTE files?
750  if ($RTEoriginal = $this->‪getRTEoriginalFilename(‪PathUtility::basename($fI['ID_absFile']))) {
751  $RTEoriginal_absPath = ‪PathUtility::dirname($fI['ID_absFile']) . '/' . $RTEoriginal;
752  if (@is_file($RTEoriginal_absPath)) {
753  $RTEoriginal_ID = md5($RTEoriginal_absPath);
754  $fileInfo = stat($RTEoriginal_absPath);
755  $fileRec = [];
756  $fileRec['filename'] = ‪PathUtility::basename($RTEoriginal_absPath);
757  $fileRec['filemtime'] = $fileInfo['mtime'];
758  $fileRec['record_ref'] = '_RTE_COPY_ID:' . $fI['ID'];
759  $this->dat['header']['files'][$fI['ID']]['RTE_ORIG_ID'] = $RTEoriginal_ID;
760  // Setting this data in the header
761  $this->dat['header']['files'][$RTEoriginal_ID] = $fileRec;
762  $fileMd5 = md5_file($RTEoriginal_absPath);
763  if (!$this->saveFilesOutsideExportFile) {
764  // ... and finally add the heavy stuff:
765  $fileRec['content'] = file_get_contents($RTEoriginal_absPath);
766  } else {
767  GeneralUtility::upload_copy_move($RTEoriginal_absPath, $this->‪getTemporaryFilesPathForExport() . $fileMd5);
768  }
769  $fileRec['content_md5'] = $fileMd5;
770  $this->dat['files'][$RTEoriginal_ID] = $fileRec;
771  } else {
772  $this->‪error('RTE original file "' . ‪PathUtility::stripPathSitePrefix($RTEoriginal_absPath) . '" was not found!');
773  }
774  }
775  // Files with external media?
776  // This is only done with files grabbed by a softreference parser since it is deemed improbable that hard-referenced files should undergo this treatment.
777  $html_fI = pathinfo(‪PathUtility::basename($fI['ID_absFile']));
778  if ($this->includeExtFileResources && GeneralUtility::inList($this->extFileResourceExtensions, strtolower($html_fI['extension']))) {
779  $uniquePrefix = '###' . md5(‪$GLOBALS['EXEC_TIME']) . '###';
780  if (strtolower($html_fI['extension']) === 'css') {
781  $prefixedMedias = explode($uniquePrefix, preg_replace('/(url[[:space:]]*\\([[:space:]]*["\']?)([^"\')]*)(["\']?[[:space:]]*\\))/i', '\\1' . $uniquePrefix . '\\2' . $uniquePrefix . '\\3', $fileRec['content']));
782  } else {
783  // html, htm:
784  $htmlParser = GeneralUtility::makeInstance(HtmlParser::class);
785  $prefixedMedias = explode($uniquePrefix, $htmlParser->prefixResourcePath($uniquePrefix, $fileRec['content'], [], $uniquePrefix));
786  }
787  $htmlResourceCaptured = false;
788  foreach ($prefixedMedias as $k => $v) {
789  if ($k % 2) {
790  $EXTres_absPath = GeneralUtility::resolveBackPath(‪PathUtility::dirname($fI['ID_absFile']) . '/' . $v);
791  $EXTres_absPath = GeneralUtility::getFileAbsFileName($EXTres_absPath);
792  if ($EXTres_absPath && GeneralUtility::isFirstPartOfStr($EXTres_absPath, ‪Environment::getPublicPath() . '/' . $this->fileadminFolderName . '/') && @is_file($EXTres_absPath)) {
793  $htmlResourceCaptured = true;
794  $EXTres_ID = md5($EXTres_absPath);
795  $this->dat['header']['files'][$fI['ID']]['EXT_RES_ID'][] = $EXTres_ID;
796  $prefixedMedias[$k] = '{EXT_RES_ID:' . $EXTres_ID . '}';
797  // Add file to memory if it is not set already:
798  if (!isset($this->dat['header']['files'][$EXTres_ID])) {
799  $fileInfo = stat($EXTres_absPath);
800  $fileRec = [];
801  $fileRec['filename'] = ‪PathUtility::basename($EXTres_absPath);
802  $fileRec['filemtime'] = $fileInfo['mtime'];
803  $fileRec['record_ref'] = '_EXT_PARENT_:' . $fI['ID'];
804  // Media relative to the HTML file.
805  $fileRec['parentRelFileName'] = $v;
806  // Setting this data in the header
807  $this->dat['header']['files'][$EXTres_ID] = $fileRec;
808  // ... and finally add the heavy stuff:
809  $fileRec['content'] = file_get_contents($EXTres_absPath);
810  $fileRec['content_md5'] = md5($fileRec['content']);
811  $this->dat['files'][$EXTres_ID] = $fileRec;
812  }
813  }
814  }
815  }
816  if ($htmlResourceCaptured) {
817  $this->dat['files'][$fI['ID']]['tokenizedContent'] = implode('', $prefixedMedias);
818  }
819  }
820  }
821  }
822 
831  public function ‪getTemporaryFilesPathForExport()
832  {
833  if (!$this->saveFilesOutsideExportFile) {
834  throw new \RuntimeException('You need to set saveFilesOutsideExportFile to TRUE before you want to get the temporary files path for export.', 1401205213);
835  }
836  if ($this->temporaryFilesPathForExport === null) {
837  $temporaryFolderName = $this->‪getTemporaryFolderName();
838  $this->temporaryFilesPathForExport = $temporaryFolderName . '/';
839  }
841  }
842 
850  public function ‪flatDBrels($dbrels)
851  {
852  $list = [];
853  foreach ($dbrels as ‪$dat) {
854  if (‪$dat['type'] === 'db') {
855  foreach (‪$dat['itemArray'] as $i) {
856  $list[$i['table'] . ':' . $i['id']] = $i;
857  }
858  }
859  if (‪$dat['type'] === 'flex' && is_array(‪$dat['flexFormRels']['db'])) {
860  foreach (‪$dat['flexFormRels']['db'] as $subList) {
861  foreach ($subList as $i) {
862  $list[$i['table'] . ':' . $i['id']] = $i;
863  }
864  }
865  }
866  }
867  return $list;
868  }
869 
876  public function ‪flatSoftRefs($dbrels)
877  {
878  $list = [];
879  foreach ($dbrels as $field => ‪$dat) {
880  if (is_array(‪$dat['softrefs']['keys'])) {
881  foreach (‪$dat['softrefs']['keys'] as $spKey => $elements) {
882  if (is_array($elements)) {
883  foreach ($elements as $subKey => $el) {
884  $lKey = $field . ':' . $spKey . ':' . $subKey;
885  $list[$lKey] = array_merge(['field' => $field, 'spKey' => $spKey], $el);
886  // Add file_ID key to header - slightly "risky" way of doing this because if the calculation
887  // changes for the same value in $this->records[...] this will not work anymore!
888  if ($el['subst'] && $el['subst']['relFileName']) {
889  $list[$lKey]['file_ID'] = md5(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
890  }
891  }
892  }
893  }
894  }
895  if (‪$dat['type'] === 'flex' && is_array(‪$dat['flexFormRels']['softrefs'])) {
896  foreach (‪$dat['flexFormRels']['softrefs'] as $structurePath => $subSoftrefs) {
897  if (is_array($subSoftrefs['keys'])) {
898  foreach ($subSoftrefs['keys'] as $spKey => $elements) {
899  foreach ($elements as $subKey => $el) {
900  $lKey = $field . ':' . $structurePath . ':' . $spKey . ':' . $subKey;
901  $list[$lKey] = array_merge(['field' => $field, 'spKey' => $spKey, 'structurePath' => $structurePath], $el);
902  // Add file_ID key to header - slightly "risky" way of doing this because if the calculation
903  // changes for the same value in $this->records[...] this will not work anymore!
904  if ($el['subst'] && $el['subst']['relFileName']) {
905  $list[$lKey]['file_ID'] = md5(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
906  }
907  }
908  }
909  }
910  }
911  }
912  }
913  return $list;
914  }
915 
924  protected function ‪filterRecordFields($table, array $row)
925  {
926  if (isset($this->recordTypesIncludeFields[$table])) {
927  $includeFields = array_unique(array_merge(
928  $this->recordTypesIncludeFields[$table],
929  $this->defaultRecordIncludeFields
930  ));
931  $newRow = [];
932  foreach ($row as $key => $value) {
933  if (in_array($key, $includeFields)) {
934  $newRow[$key] = $value;
935  }
936  }
937  } else {
938  $newRow = $row;
939  }
940  return $newRow;
941  }
942 
943  /**************************
944  * File Output
945  *************************/
946 
953  public function ‪compileMemoryToFileContent($type = '')
954  {
955  if ($type === 'xml') {
956  $out = $this->‪createXML();
957  } else {
959  $out = '';
960  // adding header:
961  $out .= $this->‪addFilePart(serialize($this->dat['header']), ‪$compress);
962  // adding records:
963  $out .= $this->‪addFilePart(serialize($this->dat['records']), ‪$compress);
964  // adding files:
965  $out .= $this->‪addFilePart(serialize($this->dat['files']), ‪$compress);
966  // adding files_fal:
967  $out .= $this->‪addFilePart(serialize($this->dat['files_fal']), ‪$compress);
968  }
969  return $out;
970  }
971 
977  public function ‪createXML()
978  {
979  // Options:
980  $options = [
981  'alt_options' => [
982  '/header' => [
983  'disableTypeAttrib' => true,
984  'clearStackPath' => true,
985  'parentTagMap' => [
986  'files' => 'file',
987  'files_fal' => 'file',
988  'records' => 'table',
989  'table' => 'rec',
990  'rec:rels' => 'relations',
991  'relations' => 'element',
992  'filerefs' => 'file',
993  'pid_lookup' => 'page_contents',
994  'header:relStaticTables' => 'static_tables',
995  'static_tables' => 'tablename',
996  'excludeMap' => 'item',
997  'softrefCfg' => 'softrefExportMode',
998  'extensionDependencies' => 'extkey',
999  'softrefs' => 'softref_element'
1000  ],
1001  'alt_options' => [
1002  '/pagetree' => [
1003  'disableTypeAttrib' => true,
1004  'useIndexTagForNum' => 'node',
1005  'parentTagMap' => [
1006  'node:subrow' => 'node'
1007  ]
1008  ],
1009  '/pid_lookup/page_contents' => [
1010  'disableTypeAttrib' => true,
1011  'parentTagMap' => [
1012  'page_contents' => 'table'
1013  ],
1014  'grandParentTagMap' => [
1015  'page_contents/table' => 'item'
1016  ]
1017  ]
1018  ]
1019  ],
1020  '/records' => [
1021  'disableTypeAttrib' => true,
1022  'parentTagMap' => [
1023  'records' => 'tablerow',
1024  'tablerow:data' => 'fieldlist',
1025  'tablerow:rels' => 'related',
1026  'related' => 'field',
1027  'field:itemArray' => 'relations',
1028  'field:newValueFiles' => 'filerefs',
1029  'field:flexFormRels' => 'flexform',
1030  'relations' => 'element',
1031  'filerefs' => 'file',
1032  'flexform:db' => 'db_relations',
1033  'flexform:file' => 'file_relations',
1034  'flexform:softrefs' => 'softref_relations',
1035  'softref_relations' => 'structurePath',
1036  'db_relations' => 'path',
1037  'file_relations' => 'path',
1038  'path' => 'element',
1039  'keys' => 'softref_key',
1040  'softref_key' => 'softref_element'
1041  ],
1042  'alt_options' => [
1043  '/records/tablerow/fieldlist' => [
1044  'useIndexTagForAssoc' => 'field'
1045  ]
1046  ]
1047  ],
1048  '/files' => [
1049  'disableTypeAttrib' => true,
1050  'parentTagMap' => [
1051  'files' => 'file'
1052  ]
1053  ],
1054  '/files_fal' => [
1055  'disableTypeAttrib' => true,
1056  'parentTagMap' => [
1057  'files_fal' => 'file'
1058  ]
1059  ]
1060  ]
1061  ];
1062  // Creating XML file from $outputArray:
1063  $charset = $this->dat['header']['charset'] ?: 'utf-8';
1064  $XML = '<?xml version="1.0" encoding="' . $charset . '" standalone="yes" ?>' . LF;
1065  $XML .= GeneralUtility::array2xml($this->dat, '', 0, 'T3RecordDocument', 0, $options);
1066  return $XML;
1067  }
1068 
1074  public function ‪doOutputCompress()
1075  {
1076  return $this->compress && !‪$this->dontCompress;
1077  }
1078 
1086  public function ‪addFilePart($data, ‪$compress = false)
1087  {
1088  if (‪$compress) {
1089  $data = gzcompress($data);
1090  }
1091  return md5($data) . ':' . (‪$compress ? '1' : '0') . ':' . str_pad(strlen($data), 10, '0', STR_PAD_LEFT) . ':' . $data . ':';
1092  }
1093 }
‪TYPO3\CMS\Impexp\ImportExport\isActive
‪bool isActive($table, $uid)
Definition: ImportExport.php:367
‪TYPO3\CMS\Impexp\ImportExport\$extensionDependencies
‪array $extensionDependencies
Definition: ImportExport.php:179
‪TYPO3\CMS\Impexp\Export\export_addFilesFromSysFilesRecords
‪export_addFilesFromSysFilesRecords()
Definition: Export.php:635
‪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\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\ResourceFactory\createFileObject
‪File createFileObject(array $fileData, ResourceStorage $storage=null)
Definition: ResourceFactory.php:603
‪TYPO3\CMS\Core\Resource\AbstractFile\getForLocalProcessing
‪string getForLocalProcessing($writable=true)
Definition: AbstractFile.php:548
‪TYPO3\CMS\Impexp\Export\setRecordTypeIncludeFields
‪setRecordTypeIncludeFields($table, array $fields)
Definition: Export.php:276
‪TYPO3\CMS\Core\Html\HtmlParser
Definition: HtmlParser.php:26
‪TYPO3\CMS\Impexp\Export\$recordTypesIncludeFields
‪array $recordTypesIncludeFields
Definition: Export.php:101
‪TYPO3\CMS\Core\Utility\PathUtility\dirname
‪static string dirname($path)
Definition: PathUtility.php:185
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:371
‪TYPO3\CMS\Impexp\ImportExport\error
‪error($msg)
Definition: ImportExport.php:1213
‪TYPO3\CMS\Impexp\Export\setPageTree
‪array setPageTree($idH)
Definition: Export.php:222
‪TYPO3\CMS\Core\Database\ReferenceIndex
Definition: ReferenceIndex.php:50
‪TYPO3\CMS\Impexp\Export\$maxRecordSize
‪int $maxRecordSize
Definition: Export.php:71
‪TYPO3\CMS\Impexp\ImportExport\checkPID
‪bool checkPID($pid)
Definition: ImportExport.php:1017
‪TYPO3\CMS\Impexp\Export\setMetaData
‪setMetaData($title, $description, $notes, $packager_username, $packager_name, $packager_email)
Definition: Export.php:186
‪TYPO3\CMS\Impexp\Export\$maxFileSize
‪int $maxFileSize
Definition: Export.php:66
‪TYPO3\CMS\Impexp\Export\export_addFile
‪export_addFile($fI, $recordRef='', $fieldname='')
Definition: Export.php:700
‪TYPO3\CMS\Impexp\Export\$extFileResourceExtensions
‪string $extFileResourceExtensions
Definition: Export.php:94
‪TYPO3\CMS\Impexp\Export\$maxExportSize
‪int $maxExportSize
Definition: Export.php:76
‪TYPO3\CMS\Core\Exception
‪TYPO3\CMS\Impexp\Export\filterRecordFields
‪array filterRecordFields($table, array $row)
Definition: Export.php:914
‪TYPO3\CMS\Impexp\Export\setHeaderBasics
‪setHeaderBasics()
Definition: Export.php:140
‪TYPO3\CMS\Core\Resource\ResourceFactory\getInstance
‪static ResourceFactory getInstance()
Definition: ResourceFactory.php:39
‪TYPO3\CMS\Impexp\Export\removeSoftrefsHavingTheSameDatabaseRelation
‪array removeSoftrefsHavingTheSameDatabaseRelation($relations)
Definition: Export.php:381
‪TYPO3\CMS\Impexp\Export\$saveFilesOutsideExportFile
‪bool $saveFilesOutsideExportFile
Definition: Export.php:111
‪$fields
‪$fields
Definition: pages.php:4
‪TYPO3\CMS\Impexp\ImportExport\isTableStatic
‪bool isTableStatic($table)
Definition: ImportExport.php:966
‪TYPO3\CMS\Impexp\Export\addFilePart
‪string addFilePart($data, $compress=false)
Definition: Export.php:1076
‪TYPO3\CMS\Impexp\Export\unsetExcludedSections
‪array unsetExcludedSections($idH)
Definition: Export.php:236
‪TYPO3\CMS\Impexp\ImportExport\$softrefCfg
‪array $softrefCfg
Definition: ImportExport.php:173
‪TYPO3\CMS\Core\Utility\PathUtility\basename
‪static string basename($path)
Definition: PathUtility.php:164
‪TYPO3\CMS\Impexp\Export\flatDBrels
‪array flatDBrels($dbrels)
Definition: Export.php:840
‪TYPO3\CMS\Impexp\Export\setRecordTypesIncludeFields
‪setRecordTypesIncludeFields(array $recordTypesIncludeFields)
Definition: Export.php:260
‪TYPO3\CMS\Impexp\Export\export_addDBRelations
‪array export_addDBRelations($relationLevel=0)
Definition: Export.php:422
‪TYPO3\CMS\Impexp\Export\doOutputCompress
‪bool doOutputCompress()
Definition: Export.php:1064
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:33
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:23
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordTitle
‪static string getRecordTitle($table, $row, $prep=false, $forceResult=true)
Definition: BackendUtility.php:1811
‪TYPO3\CMS\Core\Resource\AbstractFile\getCombinedIdentifier
‪string getCombinedIdentifier()
Definition: AbstractFile.php:418
‪TYPO3\CMS\Core\Resource\AbstractFile\getUid
‪int getUid()
Definition: AbstractFile.php:200
‪TYPO3\CMS\Impexp\Export\$includeExtFileResources
‪bool $includeExtFileResources
Definition: Export.php:88
‪TYPO3\CMS\Impexp\Export\export_addFilesFromRelations
‪export_addFilesFromRelations()
Definition: Export.php:546
‪TYPO3\CMS\Impexp\Export\setSaveFilesOutsideExportFile
‪setSaveFilesOutsideExportFile($saveFilesOutsideExportFile)
Definition: Export.php:207
‪TYPO3\CMS\Impexp\Export\fixFileIDsInRelations
‪array fixFileIDsInRelations(array $relations)
Definition: Export.php:343
‪TYPO3\CMS\Impexp\ImportExport
Definition: ImportExport.php:68
‪TYPO3\CMS\Impexp\Export\compileMemoryToFileContent
‪string compileMemoryToFileContent($type='')
Definition: Export.php:943
‪TYPO3\CMS\Impexp\Export\export_addSysFile
‪export_addSysFile(File $file)
Definition: Export.php:652
‪TYPO3\CMS\Impexp\Export\createXML
‪string createXML()
Definition: Export.php:967
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Core\Resource\File\getContents
‪string getContents()
Definition: File.php:130
‪TYPO3\CMS\Impexp\Export\export_addRecord
‪export_addRecord($table, $row, $relationLevel=0)
Definition: Export.php:289
‪TYPO3\CMS\Impexp\Export\flatSoftRefs
‪array flatSoftRefs($dbrels)
Definition: Export.php:866
‪TYPO3\CMS\Core\Resource\File\checkActionPermission
‪bool checkActionPermission($action)
Definition: File.php:262
‪TYPO3\CMS\Impexp\ImportExport\$relStaticTables
‪array $relStaticTables
Definition: ImportExport.php:161
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:130
‪TYPO3\CMS\Impexp\Export\$temporaryFilesPathForExport
‪string null $temporaryFilesPathForExport
Definition: Export.php:115
‪TYPO3\CMS\Impexp\ImportExport\isExcluded
‪bool isExcluded($table, $uid)
Definition: ImportExport.php:994
‪TYPO3\CMS\Impexp\ImportExport\getTemporaryFolderName
‪string getTemporaryFolderName()
Definition: ImportExport.php:928
‪TYPO3\CMS\Impexp\ImportExport\init
‪init()
Definition: ImportExport.php:254
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Utility\BackendUtility\workspaceOL
‪static workspaceOL($table, &$row, $wsid=-99, $unsetMovePointers=false)
Definition: BackendUtility.php:4048
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:39
‪TYPO3\CMS\Impexp\ImportExport\getRTEoriginalFilename
‪string null getRTEoriginalFilename($string)
Definition: ImportExport.php:1151
‪TYPO3\CMS\Core\Resource\File\getProperty
‪mixed getProperty($key)
Definition: File.php:74
‪TYPO3\CMS\Impexp\Export
Definition: Export.php:62
‪TYPO3\CMS\Core\Resource\ResourceStorage\hashFile
‪string hashFile(FileInterface $fileObject, $hash)
Definition: ResourceStorage.php:1268
‪TYPO3\CMS\Impexp\Export\init
‪init($dontCompress=false)
Definition: Export.php:126
‪TYPO3\CMS\Impexp\ImportExport\$excludeMap
‪array $excludeMap
Definition: ImportExport.php:167
‪TYPO3\CMS\Impexp\Export\$dontCompress
‪bool $dontCompress
Definition: Export.php:82
‪TYPO3\CMS\Impexp\ImportExport\$compress
‪bool $compress
Definition: ImportExport.php:210
‪TYPO3\CMS\Impexp\Export\setCharset
‪setCharset($charset)
Definition: Export.php:171
‪TYPO3\CMS\Impexp\ImportExport\$dat
‪array $dat
Definition: ImportExport.php:216
‪TYPO3\CMS\Impexp\Export\export_addDBRelations_registerRelation
‪export_addDBRelations_registerRelation($fI, &$addR, $tokenID='')
Definition: Export.php:526
‪TYPO3\CMS\Impexp\Export\$defaultRecordIncludeFields
‪array $defaultRecordIncludeFields
Definition: Export.php:107
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Impexp\ImportExport\inclRelation
‪bool inclRelation($table)
Definition: ImportExport.php:980
‪TYPO3\CMS\Impexp
‪TYPO3\CMS\Impexp\Export\getTemporaryFilesPathForExport
‪string getTemporaryFilesPathForExport()
Definition: Export.php:821
‪TYPO3\CMS\Core\Resource\ResourceFactory\retrieveFileOrFolderObject
‪File Folder null retrieveFileOrFolderObject($input)
Definition: ResourceFactory.php:491
‪TYPO3\CMS\Impexp\ImportExport\includeSoftref
‪bool includeSoftref($tokenID)
Definition: ImportExport.php:1005
‪TYPO3\CMS\Core\Resource\AbstractFile\getStorage
‪ResourceStorage getStorage()
Definition: AbstractFile.php:361