‪TYPO3CMS  10.4
Export.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 
28 
64 {
70  public ‪$dontCompress = false;
71 
77  public ‪$includeExtFileResources = false;
78 
84  public ‪$extFileResourceExtensions = 'html,htm,css';
85 
92  protected ‪$recordTypesIncludeFields = [];
93 
99  protected ‪$defaultRecordIncludeFields = ['uid', 'pid'];
100 
104  protected ‪$saveFilesOutsideExportFile = false;
105 
110 
111  /**************************
112  * Initialize
113  *************************/
114 
120  public function ‪init(‪$dontCompress = false)
121  {
122  parent::init();
123  $this->dontCompress = ‪$dontCompress;
124  $this->mode = 'export';
125  }
126 
127  /**************************
128  * Export / Init + Meta Data
129  *************************/
130 
134  public function ‪setHeaderBasics()
135  {
136  // Initializing:
137  if (is_array($this->softrefCfg)) {
138  foreach ($this->softrefCfg as $key => $value) {
139  if (!strlen($value['mode'])) {
140  unset($this->softrefCfg[$key]);
141  }
142  }
143  }
144  // Setting in header memory:
145  // Version of file format
146  $this->dat['header']['XMLversion'] = '1.0';
147  // Initialize meta data array (to put it in top of file)
148  $this->dat['header']['meta'] = [];
149  // Add list of tables to consider static
150  $this->dat['header']['relStaticTables'] = ‪$this->relStaticTables;
151  // The list of excluded records
152  $this->dat['header']['excludeMap'] = ‪$this->excludeMap;
153  // Soft Reference mode for elements
154  $this->dat['header']['softrefCfg'] = ‪$this->softrefCfg;
155  // List of extensions the import depends on.
156  $this->dat['header']['extensionDependencies'] = ‪$this->extensionDependencies;
157  $this->dat['header']['charset'] = 'utf-8';
158  }
159 
165  public function ‪setCharset($charset)
166  {
167  $this->dat['header']['charset'] = $charset;
168  }
169 
180  public function ‪setMetaData($title, $description, $notes, $packager_username, $packager_name, $packager_email)
181  {
182  $this->dat['header']['meta'] = [
183  'title' => $title,
184  'description' => $description,
185  'notes' => $notes,
186  'packager_username' => $packager_username,
187  'packager_name' => $packager_name,
188  'packager_email' => $packager_email,
189  'TYPO3_version' => (string)GeneralUtility::makeInstance(Typo3Version::class),
190  'created' => strftime('%A %e. %B %Y', ‪$GLOBALS['EXEC_TIME'])
191  ];
192  }
193 
202  {
203  $this->saveFilesOutsideExportFile = ‪$saveFilesOutsideExportFile;
204  }
205 
206  /**************************
207  * Export / Init Page tree
208  *************************/
209 
216  public function ‪setPageTree($idH)
217  {
218  $this->dat['header']['pagetree'] = $this->‪unsetExcludedSections($idH);
219  return $this->‪flatInversePageTree($this->dat['header']['pagetree']);
220  }
221 
230  public function ‪unsetExcludedSections($idH)
231  {
232  if (is_array($idH)) {
233  foreach ($idH as $k => $v) {
234  if ($this->excludeMap['pages:' . $idH[$k]['uid']]) {
235  unset($idH[$k]);
236  } elseif (is_array($idH[$k]['subrow'])) {
237  $idH[$k]['subrow'] = $this->‪unsetExcludedSections($idH[$k]['subrow']);
238  }
239  }
240  }
241  return $idH;
242  }
243 
244  /**************************
245  * Export
246  *************************/
247 
255  {
256  foreach (‪$recordTypesIncludeFields as $table => ‪$fields) {
257  if (!is_array(‪$fields)) {
258  throw new ‪Exception('The include fields for record type ' . htmlspecialchars($table) . ' are not defined by an array.', 1391440658);
259  }
261  }
262  }
263 
270  public function ‪setRecordTypeIncludeFields($table, array ‪$fields)
271  {
272  $this->recordTypesIncludeFields[$table] = ‪$fields;
273  }
274 
283  public function ‪export_addRecord($table, $row, $relationLevel = 0)
284  {
285  ‪BackendUtility::workspaceOL($table, $row);
286  if ($this->excludeDisabledRecords && !$this->‪isActive($table, $row['uid'])) {
287  return;
288  }
289  if ((string)$table !== '' && is_array($row) && $row['uid'] > 0 && !$this->excludeMap[$table . ':' . $row['uid']]) {
290  if ($this->‪checkPID($table === 'pages' ? $row['uid'] : $row['pid'])) {
291  if (!isset($this->dat['records'][$table . ':' . $row['uid']])) {
292  // Prepare header info:
293  $row = $this->‪filterRecordFields($table, $row);
294  $headerInfo = [];
295  $headerInfo['uid'] = $row['uid'];
296  $headerInfo['pid'] = $row['pid'];
297  $headerInfo['title'] = GeneralUtility::fixed_lgd_cs(‪BackendUtility::getRecordTitle($table, $row), 40);
298  if ($relationLevel) {
299  $headerInfo['relationLevel'] = $relationLevel;
300  }
301  // Set the header summary:
302  $this->dat['header']['records'][$table][$row['uid']] = $headerInfo;
303  // Create entry in the PID lookup:
304  $this->dat['header']['pid_lookup'][$row['pid']][$table][$row['uid']] = 1;
305  // Initialize reference index object:
306  $refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class);
307  $refIndexObj->enableRuntimeCache();
308  $relations = $refIndexObj->getRelations($table, $row);
309  $relations = $this->‪fixFileIDsInRelations($relations);
310  $relations = $this->‪removeSoftrefsHavingTheSameDatabaseRelation($relations);
311  // Data:
312  $this->dat['records'][$table . ':' . $row['uid']] = [];
313  $this->dat['records'][$table . ':' . $row['uid']]['data'] = $row;
314  $this->dat['records'][$table . ':' . $row['uid']]['rels'] = $relations;
315  // Add information about the relations in the record in the header:
316  $this->dat['header']['records'][$table][$row['uid']]['rels'] = $this->‪flatDBrels($this->dat['records'][$table . ':' . $row['uid']]['rels']);
317  // Add information about the softrefs to header:
318  $this->dat['header']['records'][$table][$row['uid']]['softrefs'] = $this->‪flatSoftRefs($this->dat['records'][$table . ':' . $row['uid']]['rels']);
319  } else {
320  $this->‪error('Record ' . $table . ':' . $row['uid'] . ' already added.');
321  }
322  } else {
323  $this->‪error('Record ' . $table . ':' . $row['uid'] . ' was outside your DB mounts!');
324  }
325  }
326  }
327 
335  protected function ‪fixFileIDsInRelations(array $relations)
336  {
337  foreach ($relations as $field => $relation) {
338  if (isset($relation['type']) && $relation['type'] === 'file') {
339  foreach ($relation['newValueFiles'] as $key => $fileRelationData) {
340  $absoluteFilePath = $fileRelationData['ID_absFile'];
341  if (GeneralUtility::isFirstPartOfStr($absoluteFilePath, ‪Environment::getPublicPath())) {
342  $relatedFilePath = ‪PathUtility::stripPathSitePrefix($absoluteFilePath);
343  $relations[$field]['newValueFiles'][$key]['ID'] = md5($relatedFilePath);
344  }
345  }
346  }
347  if ($relation['type'] === 'flex') {
348  if (is_array($relation['flexFormRels']['file'])) {
349  foreach ($relation['flexFormRels']['file'] as $key => $subList) {
350  foreach ($subList as $subKey => $fileRelationData) {
351  $absoluteFilePath = $fileRelationData['ID_absFile'];
352  if (GeneralUtility::isFirstPartOfStr($absoluteFilePath, ‪Environment::getPublicPath())) {
353  $relatedFilePath = ‪PathUtility::stripPathSitePrefix($absoluteFilePath);
354  $relations[$field]['flexFormRels']['file'][$key][$subKey]['ID'] = md5($relatedFilePath);
355  }
356  }
357  }
358  }
359  }
360  }
361  return $relations;
362  }
363 
373  protected function ‪removeSoftrefsHavingTheSameDatabaseRelation($relations)
374  {
375  $fixedRelations = [];
376  foreach ($relations as $field => $relation) {
377  $newRelation = $relation;
378  if (isset($newRelation['type']) && $newRelation['type'] === 'db') {
379  foreach ($newRelation['itemArray'] as $key => $dbRelationData) {
380  if ($dbRelationData['table'] === 'sys_file') {
381  if (isset($newRelation['softrefs']['keys']['typolink'])) {
382  foreach ($newRelation['softrefs']['keys']['typolink'] as $softrefKey => $softRefData) {
383  if ($softRefData['subst']['type'] === 'file') {
384  $file = GeneralUtility::makeInstance(ResourceFactory::class)->retrieveFileOrFolderObject($softRefData['subst']['relFileName']);
385  if ($file instanceof File) {
386  if ($file->getUid() == $dbRelationData['id']) {
387  unset($newRelation['softrefs']['keys']['typolink'][$softrefKey]);
388  }
389  }
390  }
391  }
392  if (empty($newRelation['softrefs']['keys']['typolink'])) {
393  unset($newRelation['softrefs']);
394  }
395  }
396  }
397  }
398  }
399  $fixedRelations[$field] = $newRelation;
400  }
401  return $fixedRelations;
402  }
403 
414  public function ‪export_addDBRelations($relationLevel = 0)
415  {
416  // Traverse all "rels" registered for "records"
417  if (!is_array($this->dat['records'])) {
418  $this->‪error('There were no records available.');
419  return [];
420  }
421  $addR = [];
422  foreach ($this->dat['records'] as $k => $value) {
423  if (!is_array($this->dat['records'][$k])) {
424  continue;
425  }
426  foreach ($this->dat['records'][$k]['rels'] as $fieldname => $vR) {
427  // For all DB types of relations:
428  if ($vR['type'] === 'db') {
429  foreach ($vR['itemArray'] as $fI) {
431  }
432  }
433  // For all flex/db types of relations:
434  if ($vR['type'] === 'flex') {
435  // DB relations in flex form fields:
436  if (is_array($vR['flexFormRels']['db'])) {
437  foreach ($vR['flexFormRels']['db'] as $subList) {
438  foreach ($subList as $fI) {
440  }
441  }
442  }
443  // DB oriented soft references in flex form fields:
444  if (is_array($vR['flexFormRels']['softrefs'])) {
445  foreach ($vR['flexFormRels']['softrefs'] as $subList) {
446  foreach ($subList['keys'] as $spKey => $elements) {
447  foreach ($elements as $el) {
448  if ($el['subst']['type'] === 'db' && $this->‪includeSoftref($el['subst']['tokenID'])) {
449  [$tempTable, $tempUid] = explode(':', $el['subst']['recordRef']);
450  $fI = [
451  'table' => $tempTable,
452  'id' => $tempUid
453  ];
454  $this->‪export_addDBRelations_registerRelation($fI, $addR, $el['subst']['tokenID']);
455  }
456  }
457  }
458  }
459  }
460  }
461  // In any case, if there are soft refs:
462  if (is_array($vR['softrefs']['keys'])) {
463  foreach ($vR['softrefs']['keys'] as $spKey => $elements) {
464  foreach ($elements as $el) {
465  if ($el['subst']['type'] === 'db' && $this->‪includeSoftref($el['subst']['tokenID'])) {
466  [$tempTable, $tempUid] = explode(':', $el['subst']['recordRef']);
467  $fI = [
468  'table' => $tempTable,
469  'id' => $tempUid
470  ];
471  $this->‪export_addDBRelations_registerRelation($fI, $addR, $el['subst']['tokenID']);
472  }
473  }
474  }
475  }
476  }
477  }
478 
479  // Now, if there were new records to add, do so:
480  if (!empty($addR)) {
481  foreach ($addR as $fI) {
482  // Get and set record:
483  $row = ‪BackendUtility::getRecord($fI['table'], $fI['id']);
484 
485  if (is_array($row)) {
486  // Depending on db driver, int fields may or may not be returned as integer or as string. The
487  // loop aligns that detail and forces strings for everything to have exports more db agnostic.
488  foreach ($row as $fieldName => $value) {
489  // Keep null but force everything else to string
490  $row[$fieldName] = $value === null ? $value : (string)$value;
491  }
492  $this->‪export_addRecord($fI['table'], $row, $relationLevel + 1);
493  }
494  // Set status message
495  // Relation pointers always larger than zero except certain "select" types with
496  // negative values pointing to uids - but that is not supported here.
497  if ($fI['id'] > 0) {
498  $rId = $fI['table'] . ':' . $fI['id'];
499  if (!isset($this->dat['records'][$rId])) {
500  $this->dat['records'][$rId] = 'NOT_FOUND';
501  $this->‪error('Relation record ' . $rId . ' was not found!');
502  }
503  }
504  }
505  }
506  // Return overview of relations found and added
507  return $addR;
508  }
509 
518  public function ‪export_addDBRelations_registerRelation($fI, &$addR, $tokenID = '')
519  {
520  $rId = $fI['table'] . ':' . $fI['id'];
521  if (
522  isset(‪$GLOBALS['TCA'][$fI['table']]) && !$this->‪isTableStatic($fI['table']) && !$this->‪isExcluded($fI['table'], $fI['id'])
523  && (!$tokenID || $this->‪includeSoftref($tokenID)) && $this->‪inclRelation($fI['table'])
524  ) {
525  if (!isset($this->dat['records'][$rId])) {
526  // Set this record to be included since it is not already.
527  $addR[$rId] = $fI;
528  }
529  }
530  }
531 
538  public function ‪export_addFilesFromRelations()
539  {
540  // Traverse all "rels" registered for "records"
541  if (!is_array($this->dat['records'])) {
542  $this->‪error('There were no records available.');
543  return;
544  }
545  foreach ($this->dat['records'] as $k => $value) {
546  if (!isset($this->dat['records'][$k]['rels']) || !is_array($this->dat['records'][$k]['rels'])) {
547  continue;
548  }
549  foreach ($this->dat['records'][$k]['rels'] as $fieldname => $vR) {
550  // For all file type relations:
551  if ($vR['type'] === 'file') {
552  foreach ($vR['newValueFiles'] as $key => $fI) {
553  $this->‪export_addFile($fI, $k, $fieldname);
554  // Remove the absolute reference to the file so it doesn't expose absolute paths from source server:
555  unset($this->dat['records'][$k]['rels'][$fieldname]['newValueFiles'][$key]['ID_absFile']);
556  }
557  }
558  // For all flex type relations:
559  if ($vR['type'] === 'flex') {
560  if (is_array($vR['flexFormRels']['file'])) {
561  foreach ($vR['flexFormRels']['file'] as $key => $subList) {
562  foreach ($subList as $subKey => $fI) {
563  $this->‪export_addFile($fI, $k, $fieldname);
564  // Remove the absolute reference to the file so it doesn't expose absolute paths from source server:
565  unset($this->dat['records'][$k]['rels'][$fieldname]['flexFormRels']['file'][$key][$subKey]['ID_absFile']);
566  }
567  }
568  }
569  // DB oriented soft references in flex form fields:
570  if (is_array($vR['flexFormRels']['softrefs'])) {
571  foreach ($vR['flexFormRels']['softrefs'] as $key => $subList) {
572  foreach ($subList['keys'] as $spKey => $elements) {
573  foreach ($elements as $subKey => $el) {
574  if ($el['subst']['type'] === 'file' && $this->‪includeSoftref($el['subst']['tokenID'])) {
575  // Create abs path and ID for file:
576  $ID_absFile = GeneralUtility::getFileAbsFileName(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
577  $ID = md5($el['subst']['relFileName']);
578  if ($ID_absFile) {
579  if (!$this->dat['files'][$ID]) {
580  $fI = [
581  'filename' => ‪PathUtility::basename($ID_absFile),
582  'ID_absFile' => $ID_absFile,
583  'ID' => $ID,
584  'relFileName' => $el['subst']['relFileName']
585  ];
586  $this->‪export_addFile($fI, '_SOFTREF_');
587  }
588  $this->dat['records'][$k]['rels'][$fieldname]['flexFormRels']['softrefs'][$key]['keys'][$spKey][$subKey]['file_ID'] = $ID;
589  }
590  }
591  }
592  }
593  }
594  }
595  }
596  // In any case, if there are soft refs:
597  if (is_array($vR['softrefs']['keys'])) {
598  foreach ($vR['softrefs']['keys'] as $spKey => $elements) {
599  foreach ($elements as $subKey => $el) {
600  if ($el['subst']['type'] === 'file' && $this->‪includeSoftref($el['subst']['tokenID'])) {
601  // Create abs path and ID for file:
602  $ID_absFile = GeneralUtility::getFileAbsFileName(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
603  $ID = md5($el['subst']['relFileName']);
604  if ($ID_absFile) {
605  if (!$this->dat['files'][$ID]) {
606  $fI = [
607  'filename' => ‪PathUtility::basename($ID_absFile),
608  'ID_absFile' => $ID_absFile,
609  'ID' => $ID,
610  'relFileName' => $el['subst']['relFileName']
611  ];
612  $this->‪export_addFile($fI, '_SOFTREF_');
613  }
614  $this->dat['records'][$k]['rels'][$fieldname]['softrefs']['keys'][$spKey][$subKey]['file_ID'] = $ID;
615  }
616  }
617  }
618  }
619  }
620  }
621  }
622  }
623 
627  public function ‪export_addFilesFromSysFilesRecords()
628  {
629  if (!isset($this->dat['header']['records']['sys_file']) || !is_array($this->dat['header']['records']['sys_file'])) {
630  return;
631  }
632  foreach ($this->dat['header']['records']['sys_file'] as $sysFileUid => $_) {
633  $recordData = $this->dat['records']['sys_file:' . $sysFileUid]['data'];
634  $file = GeneralUtility::makeInstance(ResourceFactory::class)->createFileObject($recordData);
635  $this->‪export_addSysFile($file);
636  }
637  }
638 
644  public function ‪export_addSysFile(‪File $file)
645  {
646  $fileContent = '';
647  try {
648  if (!$this->saveFilesOutsideExportFile) {
649  $fileContent = $file->‪getContents();
650  } else {
651  $file->‪checkActionPermission('read');
652  }
653  } catch (\Exception $e) {
654  $this->‪error('Error when trying to add file ' . $file->‪getCombinedIdentifier() . ': ' . $e->getMessage());
655  return;
656  }
657  $fileUid = $file->‪getUid();
658  $fileSha1 = $file->‪getStorage()->‪hashFile($file, 'sha1');
659  if ($fileSha1 !== $file->‪getProperty('sha1')) {
660  $this->‪error('File sha1 hash of ' . $file->‪getCombinedIdentifier() . ' is not up-to-date in index! File added on current sha1.');
661  $this->dat['records']['sys_file:' . $fileUid]['data']['sha1'] = $fileSha1;
662  }
663 
664  $fileRec = [];
665  $fileRec['filename'] = $file->‪getProperty('name');
666  $fileRec['filemtime'] = $file->‪getProperty('modification_date');
667 
668  // build unique id based on the storage and the file identifier
669  $fileId = md5($file->‪getStorage()->‪getUid() . ':' . $file->‪getProperty('identifier_hash'));
670 
671  // Setting this data in the header
672  $this->dat['header']['files_fal'][$fileId] = $fileRec;
673 
674  if (!$this->saveFilesOutsideExportFile) {
675  // ... and finally add the heavy stuff:
676  $fileRec['content'] = $fileContent;
677  } else {
678  GeneralUtility::upload_copy_move($file->‪getForLocalProcessing(false), $this->getTemporaryFilesPathForExport() . $file->‪getProperty('sha1'));
679  }
680  $fileRec['content_sha1'] = $fileSha1;
681 
682  $this->dat['files_fal'][$fileId] = $fileRec;
683  }
684 
692  public function ‪export_addFile($fI, $recordRef = '', $fieldname = '')
693  {
694  if (!@is_file($fI['ID_absFile'])) {
695  $this->‪error($fI['ID_absFile'] . ' was not a file! Skipping.');
696  return;
697  }
698  $fileInfo = stat($fI['ID_absFile']);
699  $fileRec = [];
700  $fileRec['filename'] = ‪PathUtility::basename($fI['ID_absFile']);
701  $fileRec['filemtime'] = $fileInfo['mtime'];
702  //for internal type file_reference
703  $fileRec['relFileRef'] = ‪PathUtility::stripPathSitePrefix($fI['ID_absFile']);
704  if ($recordRef) {
705  $fileRec['record_ref'] = $recordRef . '/' . $fieldname;
706  }
707  if ($fI['relFileName']) {
708  $fileRec['relFileName'] = $fI['relFileName'];
709  }
710  // Setting this data in the header
711  $this->dat['header']['files'][$fI['ID']] = $fileRec;
712  // ... and for the recordlisting, why not let us know WHICH relations there was...
713  if ($recordRef && $recordRef !== '_SOFTREF_') {
714  $refParts = explode(':', $recordRef, 2);
715  if (!is_array($this->dat['header']['records'][$refParts[0]][$refParts[1]]['filerefs'])) {
716  $this->dat['header']['records'][$refParts[0]][$refParts[1]]['filerefs'] = [];
717  }
718  $this->dat['header']['records'][$refParts[0]][$refParts[1]]['filerefs'][] = $fI['ID'];
719  }
720  $fileMd5 = md5_file($fI['ID_absFile']);
721  if (!$this->saveFilesOutsideExportFile) {
722  // ... and finally add the heavy stuff:
723  $fileRec['content'] = (string)file_get_contents($fI['ID_absFile']);
724  } else {
725  GeneralUtility::upload_copy_move($fI['ID_absFile'], $this->‪getTemporaryFilesPathForExport() . $fileMd5);
726  }
727  $fileRec['content_md5'] = $fileMd5;
728  $this->dat['files'][$fI['ID']] = $fileRec;
729  // For soft references, do further processing:
730  if ($recordRef === '_SOFTREF_') {
731  // Files with external media?
732  // This is only done with files grabbed by a softreference parser since it is deemed improbable that hard-referenced files should undergo this treatment.
733  $html_fI = pathinfo(‪PathUtility::basename($fI['ID_absFile']));
734  if ($this->includeExtFileResources && GeneralUtility::inList($this->extFileResourceExtensions, strtolower($html_fI['extension']))) {
735  $uniquePrefix = '###' . md5(‪$GLOBALS['EXEC_TIME']) . '###';
736  if (strtolower($html_fI['extension']) === 'css') {
737  $prefixedMedias = explode($uniquePrefix, (string)preg_replace('/(url[[:space:]]*\\([[:space:]]*["\']?)([^"\')]*)(["\']?[[:space:]]*\\))/i', '\\1' . $uniquePrefix . '\\2' . $uniquePrefix . '\\3', $fileRec['content']));
738  } else {
739  // html, htm:
740  $htmlParser = GeneralUtility::makeInstance(HtmlParser::class);
741  $prefixedMedias = explode($uniquePrefix, $htmlParser->prefixResourcePath($uniquePrefix, $fileRec['content'], [], $uniquePrefix));
742  }
743  $htmlResourceCaptured = false;
744  foreach ($prefixedMedias as $k => $v) {
745  if ($k % 2) {
746  $EXTres_absPath = GeneralUtility::resolveBackPath(‪PathUtility::dirname($fI['ID_absFile']) . '/' . $v);
747  $EXTres_absPath = GeneralUtility::getFileAbsFileName($EXTres_absPath);
748  if ($EXTres_absPath && GeneralUtility::isFirstPartOfStr($EXTres_absPath, ‪Environment::getPublicPath() . '/' . $this->fileadminFolderName . '/') && @is_file($EXTres_absPath)) {
749  $htmlResourceCaptured = true;
750  $EXTres_ID = md5($EXTres_absPath);
751  $this->dat['header']['files'][$fI['ID']]['EXT_RES_ID'][] = $EXTres_ID;
752  $prefixedMedias[$k] = '{EXT_RES_ID:' . $EXTres_ID . '}';
753  // Add file to memory if it is not set already:
754  if (!isset($this->dat['header']['files'][$EXTres_ID])) {
755  $fileInfo = stat($EXTres_absPath);
756  $fileRec = [];
757  $fileRec['filename'] = ‪PathUtility::basename($EXTres_absPath);
758  $fileRec['filemtime'] = $fileInfo['mtime'];
759  $fileRec['record_ref'] = '_EXT_PARENT_:' . $fI['ID'];
760  // Media relative to the HTML file.
761  $fileRec['parentRelFileName'] = $v;
762  // Setting this data in the header
763  $this->dat['header']['files'][$EXTres_ID] = $fileRec;
764  // ... and finally add the heavy stuff:
765  $fileRec['content'] = (string)file_get_contents($EXTres_absPath);
766  $fileRec['content_md5'] = md5($fileRec['content']);
767  $this->dat['files'][$EXTres_ID] = $fileRec;
768  }
769  }
770  }
771  }
772  if ($htmlResourceCaptured) {
773  $this->dat['files'][$fI['ID']]['tokenizedContent'] = implode('', $prefixedMedias);
774  }
775  }
776  }
777  }
778 
787  public function ‪getTemporaryFilesPathForExport()
788  {
789  if (!$this->saveFilesOutsideExportFile) {
790  throw new \RuntimeException('You need to set saveFilesOutsideExportFile to TRUE before you want to get the temporary files path for export.', 1401205213);
791  }
792  if ($this->temporaryFilesPathForExport === null) {
793  $temporaryFolderName = $this->‪getTemporaryFolderName();
794  $this->temporaryFilesPathForExport = $temporaryFolderName . '/';
795  }
797  }
798 
806  public function ‪flatDBrels($dbrels)
807  {
808  $list = [];
809  foreach ($dbrels as ‪$dat) {
810  if (‪$dat['type'] === 'db') {
811  foreach (‪$dat['itemArray'] as $i) {
812  $list[$i['table'] . ':' . $i['id']] = $i;
813  }
814  }
815  if (‪$dat['type'] === 'flex' && is_array(‪$dat['flexFormRels']['db'])) {
816  foreach (‪$dat['flexFormRels']['db'] as $subList) {
817  foreach ($subList as $i) {
818  $list[$i['table'] . ':' . $i['id']] = $i;
819  }
820  }
821  }
822  }
823  return $list;
824  }
825 
832  public function ‪flatSoftRefs($dbrels)
833  {
834  $list = [];
835  foreach ($dbrels as $field => ‪$dat) {
836  if (is_array(‪$dat['softrefs']['keys'])) {
837  foreach (‪$dat['softrefs']['keys'] as $spKey => $elements) {
838  if (is_array($elements)) {
839  foreach ($elements as $subKey => $el) {
840  $lKey = $field . ':' . $spKey . ':' . $subKey;
841  $list[$lKey] = array_merge(['field' => $field, 'spKey' => $spKey], $el);
842  // Add file_ID key to header - slightly "risky" way of doing this because if the calculation
843  // changes for the same value in $this->records[...] this will not work anymore!
844  if ($el['subst'] && $el['subst']['relFileName']) {
845  $list[$lKey]['file_ID'] = md5(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
846  }
847  }
848  }
849  }
850  }
851  if (‪$dat['type'] === 'flex' && is_array(‪$dat['flexFormRels']['softrefs'])) {
852  foreach (‪$dat['flexFormRels']['softrefs'] as $structurePath => $subSoftrefs) {
853  if (is_array($subSoftrefs['keys'])) {
854  foreach ($subSoftrefs['keys'] as $spKey => $elements) {
855  foreach ($elements as $subKey => $el) {
856  $lKey = $field . ':' . $structurePath . ':' . $spKey . ':' . $subKey;
857  $list[$lKey] = array_merge(['field' => $field, 'spKey' => $spKey, 'structurePath' => $structurePath], $el);
858  // Add file_ID key to header - slightly "risky" way of doing this because if the calculation
859  // changes for the same value in $this->records[...] this will not work anymore!
860  if ($el['subst'] && $el['subst']['relFileName']) {
861  $list[$lKey]['file_ID'] = md5(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
862  }
863  }
864  }
865  }
866  }
867  }
868  }
869  return $list;
870  }
871 
880  protected function ‪filterRecordFields($table, array $row)
881  {
882  if (isset($this->recordTypesIncludeFields[$table])) {
883  $includeFields = array_unique(array_merge(
884  $this->recordTypesIncludeFields[$table],
885  $this->defaultRecordIncludeFields
886  ));
887  $newRow = [];
888  foreach ($row as $key => $value) {
889  if (in_array($key, $includeFields)) {
890  $newRow[$key] = $value;
891  }
892  }
893  } else {
894  $newRow = $row;
895  }
896  return $newRow;
897  }
898 
899  /**************************
900  * File Output
901  *************************/
902 
909  public function ‪compileMemoryToFileContent($type = '')
910  {
911  if ($type === 'xml') {
912  $out = $this->‪createXML();
913  } else {
915  $out = '';
916  // adding header:
917  $out .= $this->‪addFilePart(serialize($this->dat['header']), ‪$compress);
918  // adding records:
919  $out .= $this->‪addFilePart(serialize($this->dat['records']), ‪$compress);
920  // adding files:
921  $out .= $this->‪addFilePart(serialize($this->dat['files']), ‪$compress);
922  // adding files_fal:
923  $out .= $this->‪addFilePart(serialize($this->dat['files_fal']), ‪$compress);
924  }
925  return $out;
926  }
927 
933  public function ‪createXML()
934  {
935  // Options:
936  $options = [
937  'alt_options' => [
938  '/header' => [
939  'disableTypeAttrib' => true,
940  'clearStackPath' => true,
941  'parentTagMap' => [
942  'files' => 'file',
943  'files_fal' => 'file',
944  'records' => 'table',
945  'table' => 'rec',
946  'rec:rels' => 'relations',
947  'relations' => 'element',
948  'filerefs' => 'file',
949  'pid_lookup' => 'page_contents',
950  'header:relStaticTables' => 'static_tables',
951  'static_tables' => 'tablename',
952  'excludeMap' => 'item',
953  'softrefCfg' => 'softrefExportMode',
954  'extensionDependencies' => 'extkey',
955  'softrefs' => 'softref_element'
956  ],
957  'alt_options' => [
958  '/pagetree' => [
959  'disableTypeAttrib' => true,
960  'useIndexTagForNum' => 'node',
961  'parentTagMap' => [
962  'node:subrow' => 'node'
963  ]
964  ],
965  '/pid_lookup/page_contents' => [
966  'disableTypeAttrib' => true,
967  'parentTagMap' => [
968  'page_contents' => 'table'
969  ],
970  'grandParentTagMap' => [
971  'page_contents/table' => 'item'
972  ]
973  ]
974  ]
975  ],
976  '/records' => [
977  'disableTypeAttrib' => true,
978  'parentTagMap' => [
979  'records' => 'tablerow',
980  'tablerow:data' => 'fieldlist',
981  'tablerow:rels' => 'related',
982  'related' => 'field',
983  'field:itemArray' => 'relations',
984  'field:newValueFiles' => 'filerefs',
985  'field:flexFormRels' => 'flexform',
986  'relations' => 'element',
987  'filerefs' => 'file',
988  'flexform:db' => 'db_relations',
989  'flexform:softrefs' => 'softref_relations',
990  'softref_relations' => 'structurePath',
991  'db_relations' => 'path',
992  'path' => 'element',
993  'keys' => 'softref_key',
994  'softref_key' => 'softref_element'
995  ],
996  'alt_options' => [
997  '/records/tablerow/fieldlist' => [
998  'useIndexTagForAssoc' => 'field'
999  ]
1000  ]
1001  ],
1002  '/files' => [
1003  'disableTypeAttrib' => true,
1004  'parentTagMap' => [
1005  'files' => 'file'
1006  ]
1007  ],
1008  '/files_fal' => [
1009  'disableTypeAttrib' => true,
1010  'parentTagMap' => [
1011  'files_fal' => 'file'
1012  ]
1013  ]
1014  ]
1015  ];
1016  // Creating XML file from $outputArray:
1017  $charset = $this->dat['header']['charset'] ?: 'utf-8';
1018  $XML = '<?xml version="1.0" encoding="' . $charset . '" standalone="yes" ?>' . LF;
1019  $XML .= GeneralUtility::array2xml($this->dat, '', 0, 'T3RecordDocument', 0, $options);
1020  return $XML;
1021  }
1022 
1028  public function ‪doOutputCompress()
1029  {
1030  return $this->compress && !‪$this->dontCompress;
1031  }
1032 
1040  public function ‪addFilePart($data, ‪$compress = false)
1041  {
1042  if (‪$compress) {
1043  $data = (string)gzcompress($data);
1044  }
1045  return md5($data) . ':' . (‪$compress ? '1' : '0') . ':' . str_pad((string)strlen($data), 10, '0', STR_PAD_LEFT) . ':' . $data . ':';
1046  }
1047 }
‪TYPO3\CMS\Impexp\ImportExport\isActive
‪bool isActive($table, $uid)
Definition: ImportExport.php:364
‪TYPO3\CMS\Impexp\ImportExport\$extensionDependencies
‪array $extensionDependencies
Definition: ImportExport.php:175
‪TYPO3\CMS\Impexp\Export\export_addFilesFromSysFilesRecords
‪export_addFilesFromSysFilesRecords()
Definition: Export.php:620
‪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\Resource\ResourceStorage\getUid
‪int getUid()
Definition: ResourceStorage.php:321
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:180
‪TYPO3\CMS\Core\Resource\AbstractFile\getForLocalProcessing
‪string getForLocalProcessing($writable=true)
Definition: AbstractFile.php:577
‪TYPO3\CMS\Impexp\Export\setRecordTypeIncludeFields
‪setRecordTypeIncludeFields($table, array $fields)
Definition: Export.php:263
‪TYPO3\CMS\Core\Html\HtmlParser
Definition: HtmlParser.php:27
‪TYPO3\CMS\Impexp\Export\$recordTypesIncludeFields
‪array $recordTypesIncludeFields
Definition: Export.php:88
‪TYPO3\CMS\Core\Utility\PathUtility\dirname
‪static string dirname($path)
Definition: PathUtility.php:186
‪TYPO3\CMS\Core\Information\Typo3Version
Definition: Typo3Version.php:21
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:22
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:372
‪TYPO3\CMS\Impexp\ImportExport\error
‪error($msg)
Definition: ImportExport.php:1191
‪TYPO3\CMS\Impexp\Export\setPageTree
‪array setPageTree($idH)
Definition: Export.php:209
‪TYPO3\CMS\Core\Database\ReferenceIndex
Definition: ReferenceIndex.php:48
‪TYPO3\CMS\Impexp\ImportExport\checkPID
‪bool checkPID($pid)
Definition: ImportExport.php:1014
‪TYPO3\CMS\Impexp\Export\setMetaData
‪setMetaData($title, $description, $notes, $packager_username, $packager_name, $packager_email)
Definition: Export.php:173
‪TYPO3\CMS\Impexp\Export\export_addFile
‪export_addFile($fI, $recordRef='', $fieldname='')
Definition: Export.php:685
‪TYPO3\CMS\Impexp\Export\$extFileResourceExtensions
‪string $extFileResourceExtensions
Definition: Export.php:81
‪TYPO3\CMS\Core\Exception
‪TYPO3\CMS\Impexp\Export\filterRecordFields
‪array filterRecordFields($table, array $row)
Definition: Export.php:873
‪TYPO3\CMS\Impexp\Export\setHeaderBasics
‪setHeaderBasics()
Definition: Export.php:127
‪TYPO3\CMS\Impexp\Export\removeSoftrefsHavingTheSameDatabaseRelation
‪array removeSoftrefsHavingTheSameDatabaseRelation($relations)
Definition: Export.php:366
‪TYPO3\CMS\Impexp\Export\$saveFilesOutsideExportFile
‪bool $saveFilesOutsideExportFile
Definition: Export.php:98
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Impexp\ImportExport\isTableStatic
‪bool isTableStatic($table)
Definition: ImportExport.php:963
‪TYPO3\CMS\Impexp\Export\addFilePart
‪string addFilePart($data, $compress=false)
Definition: Export.php:1033
‪TYPO3\CMS\Impexp\Export\unsetExcludedSections
‪array unsetExcludedSections($idH)
Definition: Export.php:223
‪TYPO3\CMS\Impexp\ImportExport\$softrefCfg
‪array $softrefCfg
Definition: ImportExport.php:169
‪TYPO3\CMS\Core\Utility\PathUtility\basename
‪static string basename($path)
Definition: PathUtility.php:165
‪TYPO3\CMS\Impexp\Export\flatDBrels
‪array flatDBrels($dbrels)
Definition: Export.php:799
‪TYPO3\CMS\Impexp\Export\setRecordTypesIncludeFields
‪setRecordTypesIncludeFields(array $recordTypesIncludeFields)
Definition: Export.php:247
‪TYPO3\CMS\Impexp\Export\export_addDBRelations
‪array export_addDBRelations($relationLevel=0)
Definition: Export.php:407
‪TYPO3\CMS\Impexp\Export\doOutputCompress
‪bool doOutputCompress()
Definition: Export.php:1021
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:41
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:24
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordTitle
‪static string getRecordTitle($table, $row, $prep=false, $forceResult=true)
Definition: BackendUtility.php:1541
‪TYPO3\CMS\Core\Resource\AbstractFile\getCombinedIdentifier
‪string getCombinedIdentifier()
Definition: AbstractFile.php:447
‪TYPO3\CMS\Core\Resource\AbstractFile\getUid
‪int getUid()
Definition: AbstractFile.php:202
‪TYPO3\CMS\Impexp\Export\$includeExtFileResources
‪bool $includeExtFileResources
Definition: Export.php:75
‪TYPO3\CMS\Impexp\Export\export_addFilesFromRelations
‪export_addFilesFromRelations()
Definition: Export.php:531
‪TYPO3\CMS\Impexp\Export\setSaveFilesOutsideExportFile
‪setSaveFilesOutsideExportFile($saveFilesOutsideExportFile)
Definition: Export.php:194
‪TYPO3\CMS\Impexp\Export\fixFileIDsInRelations
‪array fixFileIDsInRelations(array $relations)
Definition: Export.php:328
‪TYPO3\CMS\Impexp\ImportExport
Definition: ImportExport.php:70
‪TYPO3\CMS\Impexp\Export\compileMemoryToFileContent
‪string compileMemoryToFileContent($type='')
Definition: Export.php:902
‪TYPO3\CMS\Impexp\Export\export_addSysFile
‪export_addSysFile(File $file)
Definition: Export.php:637
‪TYPO3\CMS\Impexp\Export\createXML
‪string createXML()
Definition: Export.php:926
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:75
‪TYPO3\CMS\Core\Resource\File\getContents
‪string getContents()
Definition: File.php:128
‪TYPO3\CMS\Impexp\Export\export_addRecord
‪export_addRecord($table, $row, $relationLevel=0)
Definition: Export.php:276
‪TYPO3\CMS\Impexp\Export\flatSoftRefs
‪array flatSoftRefs($dbrels)
Definition: Export.php:825
‪TYPO3\CMS\Core\Resource\File\checkActionPermission
‪bool checkActionPermission($action)
Definition: File.php:235
‪TYPO3\CMS\Impexp\ImportExport\$relStaticTables
‪array $relStaticTables
Definition: ImportExport.php:157
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecord
‪static array null getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
Definition: BackendUtility.php:95
‪TYPO3\CMS\Impexp\Export\$temporaryFilesPathForExport
‪string null $temporaryFilesPathForExport
Definition: Export.php:102
‪TYPO3\CMS\Impexp\ImportExport\isExcluded
‪bool isExcluded($table, $uid)
Definition: ImportExport.php:991
‪TYPO3\CMS\Impexp\ImportExport\getTemporaryFolderName
‪string getTemporaryFolderName()
Definition: ImportExport.php:925
‪TYPO3\CMS\Impexp\ImportExport\init
‪init()
Definition: ImportExport.php:250
‪$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:3586
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:40
‪TYPO3\CMS\Core\Resource\File\getProperty
‪mixed getProperty($key)
Definition: File.php:65
‪TYPO3\CMS\Impexp\Export
Definition: Export.php:64
‪TYPO3\CMS\Core\Resource\ResourceStorage\hashFile
‪string hashFile(FileInterface $fileObject, $hash)
Definition: ResourceStorage.php:1320
‪TYPO3\CMS\Impexp\Export\init
‪init($dontCompress=false)
Definition: Export.php:113
‪TYPO3\CMS\Impexp\ImportExport\$excludeMap
‪array $excludeMap
Definition: ImportExport.php:163
‪TYPO3\CMS\Impexp\Export\$dontCompress
‪bool $dontCompress
Definition: Export.php:69
‪TYPO3\CMS\Impexp\ImportExport\$compress
‪bool $compress
Definition: ImportExport.php:206
‪TYPO3\CMS\Impexp\Export\setCharset
‪setCharset($charset)
Definition: Export.php:158
‪TYPO3\CMS\Impexp\ImportExport\$dat
‪array $dat
Definition: ImportExport.php:212
‪TYPO3\CMS\Impexp\Export\export_addDBRelations_registerRelation
‪export_addDBRelations_registerRelation($fI, &$addR, $tokenID='')
Definition: Export.php:511
‪TYPO3\CMS\Impexp\Export\$defaultRecordIncludeFields
‪array $defaultRecordIncludeFields
Definition: Export.php:94
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Impexp\ImportExport\inclRelation
‪bool inclRelation($table)
Definition: ImportExport.php:977
‪TYPO3\CMS\Impexp
‪TYPO3\CMS\Impexp\Export\getTemporaryFilesPathForExport
‪string getTemporaryFilesPathForExport()
Definition: Export.php:780
‪TYPO3\CMS\Impexp\ImportExport\includeSoftref
‪bool includeSoftref($tokenID)
Definition: ImportExport.php:1002
‪TYPO3\CMS\Core\Resource\AbstractFile\getStorage
‪ResourceStorage getStorage()
Definition: AbstractFile.php:390