‪TYPO3CMS  11.5
Export.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
18 namespace ‪TYPO3\CMS\Impexp;
19 
20 use Doctrine\DBAL\Result;
21 use TYPO3\CMS\Backend\Utility\BackendUtility;
41 
48 {
49  public const ‪LEVELS_RECORDS_ON_THIS_PAGE = -2;
50  public const ‪LEVELS_EXPANDED_TREE = -1;
51  public const ‪LEVELS_INFINITE = 999;
52 
53  public const ‪FILETYPE_XML = 'xml';
54  public const ‪FILETYPE_T3D = 't3d';
55  public const ‪FILETYPE_T3DZ = 't3d_compressed';
56 
60  protected ‪$mode = 'export';
61 
65  protected ‪$title = '';
66 
70  protected ‪$description = '';
71 
75  protected ‪$notes = '';
76 
80  protected ‪$record = [];
81 
85  protected ‪$list = [];
86 
90  protected ‪$levels = 0;
91 
95  protected ‪$tables = [];
96 
103  protected ‪$relOnlyTables = [];
104 
108  protected ‪$treeHTML = '';
109 
115  protected ‪$includeExtFileResources = true;
116 
122  protected ‪$extFileResourceExtensions = 'html,htm,css';
123 
132  protected ‪$recordTypesIncludeFields = [];
133 
139  protected ‪$defaultRecordIncludeFields = ['uid', 'pid'];
140 
144  protected ‪$saveFilesOutsideExportFile = false;
145 
149  protected ‪$exportFileName = '';
150 
155 
159  protected ‪$supportedFileTypes = [];
160 
164  protected ‪$compressionAvailable = false;
165 
171  protected ‪$pageInWebMountCache = [];
172 
176  public function ‪__construct()
177  {
178  parent::__construct();
179  $this->compressionAvailable = function_exists('gzcompress');
180  }
181 
182  /**************************
183  * Export / Init + Meta Data
184  *************************/
185 
189  public function ‪process(): void
190  {
191  $this->‪initializeExport();
192  $this->‪setHeaderBasics();
193  $this->‪setMetaData();
194 
195  // Configure which records to export
196  foreach ($this->record as $ref) {
197  $rParts = explode(':', $ref);
198  $table = $rParts[0];
199  ‪$record = BackendUtility::getRecord($rParts[0], (int)$rParts[1]);
200  if (is_array(‪$record)) {
201  $this->‪exportAddRecord($table, ‪$record);
202  }
203  }
204 
205  // Configure which tables to export
206  foreach ($this->list as $ref) {
207  $rParts = explode(':', $ref);
208  $table = $rParts[0];
209  ‪$pid = (int)$rParts[1];
210  if ($this->‪getBackendUser()->‪check('tables_select', $table)) {
211  $statement = $this->‪execListQueryPid(‪$pid, $table);
212  while (‪$record = $statement->fetchAssociative()) {
213  if (is_array(‪$record)) {
214  $this->‪exportAddRecord($table, ‪$record);
215  }
216  }
217  }
218  }
219 
220  // Configure which page tree to export
221  if ($this->pid !== -1) {
222  $pageTree = null;
223  if ($this->levels === self::LEVELS_EXPANDED_TREE) {
224  $pageTreeView = GeneralUtility::makeInstance(ExportPageTreeView::class);
225  $initClause = $this->‪getExcludePagesClause();
226  if ($this->excludeDisabledRecords) {
227  $initClause .= BackendUtility::BEenableFields('pages');
228  }
229  $pageTreeView->init($initClause);
230  $pageTreeView->buildTreeByExpandedState($this->pid);
231  $this->treeHTML = $pageTreeView->printTree();
232  $pageTree = $pageTreeView->buffer_idH;
233  } elseif ($this->levels === self::LEVELS_RECORDS_ON_THIS_PAGE) {
234  $this->‪addRecordsForPid($this->pid, $this->tables);
235  } else {
236  $pageTreeView = GeneralUtility::makeInstance(ExportPageTreeView::class);
237  $initClause = $this->‪getExcludePagesClause();
238  if ($this->excludeDisabledRecords) {
239  $initClause .= BackendUtility::BEenableFields('pages');
240  }
241  $pageTreeView->init($initClause);
242  $pageTreeView->buildTreeByLevels($this->pid, $this->levels);
243  $this->treeHTML = $pageTreeView->printTree();
244  $pageTree = $pageTreeView->buffer_idH;
245  }
246  // In most cases, we should have a multi-level array, $pageTree, with the page tree
247  // structure here (and the HTML code loaded into memory for a nice display...)
248  if (is_array($pageTree)) {
249  $pageList = [];
250  $this->‪removeExcludedPagesFromPageTree($pageTree);
251  $this->‪setPageTree($pageTree);
252  $this->‪flatInversePageTree($pageTree, $pageList);
253  foreach ($pageList as $pageUid => $_) {
254  ‪$record = BackendUtility::getRecord('pages', $pageUid);
255  if (is_array(‪$record)) {
256  $this->‪exportAddRecord('pages', ‪$record);
257  }
258  $this->‪addRecordsForPid((int)$pageUid, $this->tables);
259  }
260  }
261  }
262 
263  // After adding ALL records we add records from database relations
264  for ($l = 0; $l < 10; $l++) {
265  if ($this->‪exportAddRecordsFromRelations($l) === 0) {
266  break;
267  }
268  }
269 
270  // Files must be added after the database relations are added,
271  // so that files from ALL added records are included!
274  }
275 
279  protected function ‪initializeExport(): void
280  {
281  $this->dat = [
282  'header' => [],
283  'records' => [],
284  ];
285  }
286 
290  protected function ‪setHeaderBasics(): void
291  {
292  // Initializing:
293  foreach ($this->softrefCfg as $key => $value) {
294  if (!($value['mode'] ?? false)) {
295  unset($this->softrefCfg[$key]);
296  }
297  }
298  // Setting in header memory:
299  // Version of file format
300  $this->dat['header']['XMLversion'] = '1.0';
301  // Initialize meta data array (to put it in top of file)
302  $this->dat['header']['meta'] = [];
303  // Add list of tables to consider static
304  $this->dat['header']['relStaticTables'] = ‪$this->relStaticTables;
305  // The list of excluded records
306  $this->dat['header']['excludeMap'] = ‪$this->excludeMap;
307  // Soft reference mode for elements
308  $this->dat['header']['softrefCfg'] = ‪$this->softrefCfg;
309  // List of extensions the import depends on.
310  $this->dat['header']['extensionDependencies'] = ‪$this->extensionDependencies;
311  $this->dat['header']['charset'] = 'utf-8';
312  }
313 
317  protected function ‪setMetaData(): void
318  {
319  $this->dat['header']['meta'] = [
320  'title' => ‪$this->title,
321  'description' => ‪$this->description,
322  'notes' => ‪$this->notes,
323  'packager_username' => $this->‪getBackendUser()->user['username'],
324  'packager_name' => $this->‪getBackendUser()->user['realName'],
325  'packager_email' => $this->‪getBackendUser()->user['email'],
326  'TYPO3_version' => (string)GeneralUtility::makeInstance(Typo3Version::class),
327  // @todo Replace deprecated strftime in php 8.1. Suppress warning in v11.
328  'created' => @strftime('%A %e. %B %Y', ‪$GLOBALS['EXEC_TIME']),
329  ];
330  }
331 
332  /**************************
333  * Export / Init Page tree
334  *************************/
335 
341  public function ‪setPageTree(array $pageTree): void
342  {
343  $this->dat['header']['pagetree'] = $pageTree;
344  }
345 
351  protected function ‪removeExcludedPagesFromPageTree(array &$pageTree): void
352  {
353  foreach ($pageTree as ‪$pid => $value) {
354  if ($this->‪isRecordExcluded('pages', (int)($pageTree[‪$pid]['uid'] ?? 0))) {
355  unset($pageTree[‪$pid]);
356  } elseif (is_array($pageTree[‪$pid]['subrow'] ?? null)) {
357  $this->‪removeExcludedPagesFromPageTree($pageTree[‪$pid]['subrow']);
358  }
359  }
360  }
361 
362  /**************************
363  * Export
364  *************************/
365 
375  {
376  foreach (‪$recordTypesIncludeFields as $table => ‪$fields) {
377  if (!is_array(‪$fields)) {
378  throw new Exception('The include fields for record type ' . htmlspecialchars($table) . ' are not defined by an array.', 1391440658);
379  }
381  }
382  }
383 
391  protected function ‪setRecordTypeIncludeFields(string $table, array ‪$fields): void
392  {
393  $this->recordTypesIncludeFields[$table] = ‪$fields;
394  }
395 
402  protected function ‪getExcludePagesClause(): string
403  {
404  $pageIds = [];
405 
406  foreach ($this->excludeMap as $tableAndUid => $isExcluded) {
407  [$table, $uid] = explode(':', $tableAndUid);
408  if ($table === 'pages') {
409  $pageIds[] = (int)$uid;
410  }
411  }
412  if (!empty($pageIds)) {
413  return ' AND uid NOT IN (' . implode(',', $pageIds) . ')';
414  }
415  return '';
416  }
417 
424  protected function ‪addRecordsForPid(int ‪$pid, array ‪$tables): void
425  {
426  foreach (‪$GLOBALS['TCA'] as $table => $value) {
427  if ($table !== 'pages'
428  && (in_array($table, ‪$tables, true) || in_array('_ALL', ‪$tables, true))
429  && $this->‪getBackendUser()->check('tables_select', $table)
430  && !(‪$GLOBALS['TCA'][$table]['ctrl']['is_static'] ?? false)
431  ) {
432  $statement = $this->‪execListQueryPid($pid, $table);
433  while (‪$record = $statement->fetchAssociative()) {
434  if (is_array(‪$record)) {
435  $this->‪exportAddRecord($table, ‪$record);
436  }
437  }
438  }
439  }
440  }
441 
449  protected function ‪execListQueryPid(int ‪$pid, string $table): Result
450  {
451  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
452 
453  $orderBy = ‪$GLOBALS['TCA'][$table]['ctrl']['sortby'] ?? ‪$GLOBALS['TCA'][$table]['ctrl']['default_sortby'] ?? '';
454 
455  if ($this->excludeDisabledRecords === false) {
456  $queryBuilder->getRestrictions()
457  ->removeAll()
458  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
459  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
460  } else {
461  $queryBuilder->getRestrictions()
462  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
463  }
464 
465  $queryBuilder->select('*')
466  ->from($table)
467  ->where(
468  $queryBuilder->expr()->eq(
469  'pid',
470  $queryBuilder->createNamedParameter(‪$pid, ‪Connection::PARAM_INT)
471  )
472  );
473 
474  $orderBys = ‪QueryHelper::parseOrderBy((string)$orderBy);
475  foreach ($orderBys as $orderPair) {
476  [$field, $order] = $orderPair;
477  $queryBuilder->addOrderBy($field, $order);
478  }
479  // Ensure deterministic sorting
480  if (!in_array('uid', array_column($orderBys, 0))) {
481  $queryBuilder->addOrderBy('uid', 'ASC');
482  }
483 
484  return $queryBuilder->executeQuery();
485  }
486 
495  public function ‪exportAddRecord(string $table, array $row, int $relationLevel = 0): void
496  {
497  BackendUtility::workspaceOL($table, $row);
498 
499  if ($table === '' || (int)$row['uid'] === 0
500  || $this->‪isRecordExcluded($table, (int)$row['uid'])
501  || $this->excludeDisabledRecords && $this->‪isRecordDisabled($table, (int)$row['uid'])) {
502  return;
503  }
504 
505  if ($this->‪isPageInWebMount($table === 'pages' ? (int)$row['uid'] : (int)$row['pid'])) {
506  if (!isset($this->dat['records'][$table . ':' . $row['uid']])) {
507  // Prepare header info:
508  $row = $this->‪filterRecordFields($table, $row);
509  $headerInfo = [];
510  $headerInfo['uid'] = $row['uid'];
511  $headerInfo['pid'] = $row['pid'];
512  $headerInfo['title'] = GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $row), 40);
513  if ($relationLevel) {
514  $headerInfo['relationLevel'] = $relationLevel;
515  }
516  // Set the header summary:
517  $this->dat['header']['records'][$table][$row['uid']] = $headerInfo;
518  // Create entry in the PID lookup:
519  $this->dat['header']['pid_lookup'][$row['pid']][$table][$row['uid']] = 1;
520  // Initialize reference index object:
521  $refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class);
522  $relations = $refIndexObj->getRelations($table, $row);
523  $this->‪fixFileIdInRelations($relations);
524  $this->‪removeRedundantSoftRefsInRelations($relations);
525  // Data:
526  $this->dat['records'][$table . ':' . $row['uid']] = [];
527  $this->dat['records'][$table . ':' . $row['uid']]['data'] = $row;
528  $this->dat['records'][$table . ':' . $row['uid']]['rels'] = $relations;
529  // Add information about the relations in the record in the header:
530  $this->dat['header']['records'][$table][$row['uid']]['rels'] = $this->‪flatDbRelations($this->dat['records'][$table . ':' . $row['uid']]['rels']);
531  // Add information about the softrefs to header:
532  $this->dat['header']['records'][$table][$row['uid']]['softrefs'] = $this->‪flatSoftRefs($this->dat['records'][$table . ':' . $row['uid']]['rels']);
533  } else {
534  $this->‪addError('Record ' . $table . ':' . $row['uid'] . ' already added.');
535  }
536  } else {
537  $this->‪addError('Record ' . $table . ':' . $row['uid'] . ' was outside your database mounts!');
538  }
539  }
540 
547  protected function ‪isPageInWebMount(int ‪$pid): bool
548  {
549  if (!isset($this->pageInWebMountCache[‪$pid])) {
550  $this->pageInWebMountCache[‪$pid] = (bool)$this->‪getBackendUser()->‪isInWebMount($pid);
551  }
552  return $this->pageInWebMountCache[‪$pid];
553  }
554 
564  protected function ‪filterRecordFields(string $table, array $row): array
565  {
566  if (isset($this->recordTypesIncludeFields[$table])) {
567  $includeFields = array_unique(array_merge(
568  $this->recordTypesIncludeFields[$table],
569  $this->defaultRecordIncludeFields
570  ));
571  $newRow = [];
572  foreach ($row as $key => $value) {
573  if (in_array($key, $includeFields, true)) {
574  $newRow[$key] = $value;
575  }
576  }
577  } else {
578  $newRow = $row;
579  }
580  return $newRow;
581  }
582 
591  public function ‪fixFileIdInRelations(array &$relations): void
592  {
593  // @todo: Remove by-reference and return final array
594  foreach ($relations as &$relation) {
595  if (isset($relation['type']) && $relation['type'] === 'file') {
596  foreach ($relation['newValueFiles'] as &$fileRelationData) {
597  $absoluteFilePath = (string)$fileRelationData['ID_absFile'];
598  if (str_starts_with($absoluteFilePath, ‪Environment::getPublicPath())) {
599  $relatedFilePath = ‪PathUtility::stripPathSitePrefix($absoluteFilePath);
600  $fileRelationData['ID'] = md5($relatedFilePath);
601  }
602  }
603  unset($fileRelationData);
604  }
605  if (isset($relation['type']) && $relation['type'] === 'flex') {
606  if (is_array($relation['flexFormRels']['file'] ?? null)) {
607  foreach ($relation['flexFormRels']['file'] as &$subList) {
608  foreach ($subList as &$fileRelationData) {
609  $absoluteFilePath = (string)$fileRelationData['ID_absFile'];
610  if (str_starts_with($absoluteFilePath, ‪Environment::getPublicPath())) {
611  $relatedFilePath = ‪PathUtility::stripPathSitePrefix($absoluteFilePath);
612  $fileRelationData['ID'] = md5($relatedFilePath);
613  }
614  }
615  }
616  }
617  }
618  }
619  }
620 
632  public function ‪removeRedundantSoftRefsInRelations(array &$relations): void
633  {
634  // @todo: Remove by-reference and return final array
635  foreach ($relations as &$relation) {
636  if (isset($relation['type']) && $relation['type'] === 'db') {
637  foreach ($relation['itemArray'] as $dbRelationData) {
638  if ($dbRelationData['table'] === 'sys_file') {
639  if (isset($relation['softrefs']['keys']['typolink'])) {
640  foreach ($relation['softrefs']['keys']['typolink'] as $tokenID => &$softref) {
641  if ($softref['subst']['type'] === 'file') {
642  $file = GeneralUtility::makeInstance(ResourceFactory::class)->retrieveFileOrFolderObject($softref['subst']['relFileName']);
643  if ($file instanceof File) {
644  if ($file->getUid() == $dbRelationData['id']) {
645  unset($relation['softrefs']['keys']['typolink'][$tokenID]);
646  }
647  }
648  }
649  }
650  if (empty($relation['softrefs']['keys']['typolink'])) {
651  unset($relation['softrefs']);
652  }
653  }
654  }
655  }
656  }
657  }
658  }
659 
667  protected function ‪flatDbRelations(array $relations): array
668  {
669  ‪$list = [];
670  foreach ($relations as $relation) {
671  if (isset($relation['type'])) {
672  if ($relation['type'] === 'db') {
673  foreach ($relation['itemArray'] as $dbRelationData) {
674  ‪$list[$dbRelationData['table'] . ':' . $dbRelationData['id']] = $dbRelationData;
675  }
676  } elseif ($relation['type'] === 'flex' && is_array($relation['flexFormRels']['db'] ?? null)) {
677  foreach ($relation['flexFormRels']['db'] as $subList) {
678  foreach ($subList as $dbRelationData) {
679  ‪$list[$dbRelationData['table'] . ':' . $dbRelationData['id']] = $dbRelationData;
680  }
681  }
682  }
683  }
684  }
685  return ‪$list;
686  }
687 
695  protected function ‪flatSoftRefs(array $relations): array
696  {
697  ‪$list = [];
698  foreach ($relations as $field => $relation) {
699  if (is_array($relation['softrefs']['keys'] ?? null)) {
700  foreach ($relation['softrefs']['keys'] as $spKey => $elements) {
701  foreach ($elements as $subKey => $el) {
702  $lKey = $field . ':' . $spKey . ':' . $subKey;
703  ‪$list[$lKey] = array_merge(['field' => $field, 'spKey' => $spKey], $el);
704  // Add file_ID key to header - slightly "risky" way of doing this because if the calculation
705  // changes for the same value in $this->records[...] this will not work anymore!
706  if ($el['subst']['relFileName'] ?? false) {
707  ‪$list[$lKey]['file_ID'] = md5(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
708  }
709  }
710  }
711  }
712  if (isset($relation['type'])) {
713  if ($relation['type'] === 'flex' && is_array($relation['flexFormRels']['softrefs'] ?? null)) {
714  foreach ($relation['flexFormRels']['softrefs'] as $structurePath => &$subList) {
715  if (isset($subList['keys'])) {
716  foreach ($subList['keys'] as $spKey => $elements) {
717  foreach ($elements as $subKey => $el) {
718  $lKey = $field . ':' . $structurePath . ':' . $spKey . ':' . $subKey;
719  ‪$list[$lKey] = array_merge([
720  'field' => $field,
721  'spKey' => $spKey,
722  'structurePath' => $structurePath,
723  ], $el);
724  // Add file_ID key to header - slightly "risky" way of doing this because if the calculation
725  // changes for the same value in $this->records[...] this will not work anymore!
726  if ($el['subst']['relFileName'] ?? false) {
727  ‪$list[$lKey]['file_ID'] = md5(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
728  }
729  }
730  }
731  }
732  }
733  }
734  }
735  }
736  return ‪$list;
737  }
738 
750  protected function ‪exportAddRecordsFromRelations(int $relationLevel = 0): int
751  {
752  if (!isset($this->dat['records'])) {
753  $this->‪addError('There were no records available.');
754  return 0;
755  }
756 
757  $addRecords = [];
758 
759  foreach ($this->dat['records'] as ‪$record) {
760  if (!is_array(‪$record)) {
761  continue;
762  }
763  foreach (‪$record['rels'] as $relation) {
764  if (isset($relation['type'])) {
765  if ($relation['type'] === 'db') {
766  foreach ($relation['itemArray'] as $dbRelationData) {
767  $this->‪exportAddRecordsFromRelationsPushRelation($dbRelationData, $addRecords);
768  }
769  }
770  if ($relation['type'] === 'flex') {
771  // Database relations in flex form fields:
772  if (is_array($relation['flexFormRels']['db'] ?? null)) {
773  foreach ($relation['flexFormRels']['db'] as $subList) {
774  foreach ($subList as $dbRelationData) {
775  $this->‪exportAddRecordsFromRelationsPushRelation($dbRelationData, $addRecords);
776  }
777  }
778  }
779 
780  // Database oriented soft references in flex form fields:
781  if (is_array($relation['flexFormRels']['softrefs'] ?? null)) {
782  foreach ($relation['flexFormRels']['softrefs'] as $subList) {
783  foreach ($subList['keys'] as $elements) {
784  foreach ($elements as $el) {
785  if ($el['subst']['type'] === 'db' && $this->‪isSoftRefIncluded($el['subst']['tokenID'])) {
786  [$referencedTable, $referencedUid] = explode(':', $el['subst']['recordRef']);
787  $dbRelationData = [
788  'table' => $referencedTable,
789  'id' => $referencedUid,
790  ];
791  $this->‪exportAddRecordsFromRelationsPushRelation($dbRelationData, $addRecords, $el['subst']['tokenID']);
792  }
793  }
794  }
795  }
796  }
797  }
798  }
799  // In any case, if there are soft refs:
800  if (is_array($relation['softrefs']['keys'] ?? null)) {
801  foreach ($relation['softrefs']['keys'] as $elements) {
802  foreach ($elements as $el) {
803  if (($el['subst']['type'] ?? '') === 'db' && $this->‪isSoftRefIncluded($el['subst']['tokenID'])) {
804  [$referencedTable, $referencedUid] = explode(':', $el['subst']['recordRef']);
805  $dbRelationData = [
806  'table' => $referencedTable,
807  'id' => $referencedUid,
808  ];
809  $this->‪exportAddRecordsFromRelationsPushRelation($dbRelationData, $addRecords, $el['subst']['tokenID']);
810  }
811  }
812  }
813  }
814  }
815  }
816 
817  if (!empty($addRecords)) {
818  foreach ($addRecords as $recordData) {
819  ‪$record = BackendUtility::getRecord($recordData['table'], $recordData['id']);
820 
821  if (is_array(‪$record)) {
822  // Depending on db driver, int fields may or may not be returned as integer or as string. The
823  // loop aligns that detail and forces strings for everything to have exports more db agnostic.
824  foreach (‪$record as $fieldName => $fieldValue) {
825  ‪$record[$fieldName] = $fieldValue === null ? $fieldValue : (string)$fieldValue;
826  }
827  $this->‪exportAddRecord($recordData['table'], ‪$record, $relationLevel + 1);
828  }
829  // Set status message
830  // Relation pointers always larger than zero except certain "select" types with
831  // negative values pointing to uids - but that is not supported here.
832  if ($recordData['id'] > 0) {
833  $recordRef = $recordData['table'] . ':' . $recordData['id'];
834  if (!isset($this->dat['records'][$recordRef])) {
835  $this->dat['records'][$recordRef] = 'NOT_FOUND';
836  $this->‪addError('Relation record ' . $recordRef . ' was not found!');
837  }
838  }
839  }
840  }
841 
842  return count($addRecords);
843  }
844 
853  protected function ‪exportAddRecordsFromRelationsPushRelation(array $recordData, array &$addRecords, string $tokenID = ''): void
854  {
855  // @todo: Remove by-reference and return final array
856  $recordRef = $recordData['table'] . ':' . $recordData['id'];
857  if (
858  isset(‪$GLOBALS['TCA'][$recordData['table']]) && !$this->‪isTableStatic($recordData['table'])
859  && !$this->‪isRecordExcluded($recordData['table'], (int)$recordData['id'])
860  && (!$tokenID || $this->‪isSoftRefIncluded($tokenID)) && $this->‪inclRelation($recordData['table'])
861  && !isset($this->dat['records'][$recordRef])
862  ) {
863  $addRecords[$recordRef] = $recordData;
864  }
865  }
866 
873  protected function ‪inclRelation(string $table): bool
874  {
875  return is_array(‪$GLOBALS['TCA'][$table] ?? null)
876  && (in_array($table, $this->relOnlyTables, true) || in_array('_ALL', $this->relOnlyTables, true))
877  && $this->‪getBackendUser()->‪check('tables_select', $table);
878  }
879 
886  protected function ‪exportAddFilesFromRelations(): void
887  {
888  // @todo: Consider NOT using by-reference but writing final $this->dat at end of method.
889  if (!isset($this->dat['records'])) {
890  $this->‪addError('There were no records available.');
891  return;
892  }
893 
894  foreach ($this->dat['records'] as $recordRef => &‪$record) {
895  if (!is_array(‪$record)) {
896  continue;
897  }
898  foreach (‪$record['rels'] as $field => &$relation) {
899  // For all file type relations:
900  if (isset($relation['type']) && $relation['type'] === 'file') {
901  foreach ($relation['newValueFiles'] as &$fileRelationData) {
902  $this->‪exportAddFile($fileRelationData, $recordRef, $field);
903  // Remove the absolute reference to the file so it doesn't expose absolute paths from source server:
904  unset($fileRelationData['ID_absFile']);
905  }
906  unset($fileRelationData);
907  }
908  // For all flex type relations:
909  if (isset($relation['type']) && $relation['type'] === 'flex') {
910  if (isset($relation['flexFormRels']['file'])) {
911  foreach ($relation['flexFormRels']['file'] as &$subList) {
912  foreach ($subList as $subKey => &$fileRelationData) {
913  $this->‪exportAddFile($fileRelationData, $recordRef, $field);
914  // Remove the absolute reference to the file so it doesn't expose absolute paths from source server:
915  unset($fileRelationData['ID_absFile']);
916  }
917  }
918  unset($subList, $fileRelationData);
919  }
920  // Database oriented soft references in flex form fields:
921  if (isset($relation['flexFormRels']['softrefs'])) {
922  foreach ($relation['flexFormRels']['softrefs'] as &$subList) {
923  foreach ($subList['keys'] as &$elements) {
924  foreach ($elements as &$el) {
925  if ($el['subst']['type'] === 'file' && $this->‪isSoftRefIncluded($el['subst']['tokenID'])) {
926  // Create abs path and ID for file:
927  $ID_absFile = GeneralUtility::getFileAbsFileName(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
928  $ID = md5($el['subst']['relFileName']);
929  if ($ID_absFile) {
930  if (!$this->dat['files'][$ID]) {
931  $fileRelationData = [
932  'filename' => ‪PathUtility::basename($ID_absFile),
933  'ID_absFile' => $ID_absFile,
934  'ID' => $ID,
935  'relFileName' => $el['subst']['relFileName'],
936  ];
937  $this->‪exportAddFile($fileRelationData, '_SOFTREF_');
938  }
939  $el['file_ID'] = $ID;
940  }
941  }
942  }
943  }
944  }
945  unset($subList, $elements, $el);
946  }
947  }
948  // In any case, if there are soft refs:
949  if (is_array($relation['softrefs']['keys'] ?? null)) {
950  foreach ($relation['softrefs']['keys'] as &$elements) {
951  foreach ($elements as &$el) {
952  if (($el['subst']['type'] ?? '') === 'file' && $this->‪isSoftRefIncluded($el['subst']['tokenID'])) {
953  // Create abs path and ID for file:
954  $ID_absFile = GeneralUtility::getFileAbsFileName(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
955  $ID = md5($el['subst']['relFileName']);
956  if ($ID_absFile) {
957  if (!$this->dat['files'][$ID]) {
958  $fileRelationData = [
959  'filename' => ‪PathUtility::basename($ID_absFile),
960  'ID_absFile' => $ID_absFile,
961  'ID' => $ID,
962  'relFileName' => $el['subst']['relFileName'],
963  ];
964  $this->‪exportAddFile($fileRelationData, '_SOFTREF_');
965  }
966  $el['file_ID'] = $ID;
967  }
968  }
969  }
970  }
971  }
972  }
973  }
974  }
975 
984  protected function ‪exportAddFile(array $fileData, string $recordRef = '', string $field = ''): void
985  {
986  if (!@is_file($fileData['ID_absFile'])) {
987  $this->‪addError($fileData['ID_absFile'] . ' was not a file! Skipping.');
988  return;
989  }
990 
991  $fileStat = stat($fileData['ID_absFile']);
992  $fileMd5 = md5_file($fileData['ID_absFile']);
993  $pathInfo = pathinfo(‪PathUtility::basename($fileData['ID_absFile']));
994 
995  $fileInfo = [];
996  $fileInfo['filename'] = ‪PathUtility::basename($fileData['ID_absFile']);
997  $fileInfo['filemtime'] = $fileStat['mtime'];
998  $fileInfo['relFileRef'] = ‪PathUtility::stripPathSitePrefix($fileData['ID_absFile']);
999  if ($recordRef) {
1000  $fileInfo['record_ref'] = $recordRef . '/' . $field;
1001  }
1002  if ($fileData['relFileName']) {
1003  $fileInfo['relFileName'] = $fileData['relFileName'];
1004  }
1005 
1006  // Setting this data in the header
1007  $this->dat['header']['files'][$fileData['ID']] = $fileInfo;
1008 
1009  if (!$this->saveFilesOutsideExportFile) {
1010  $fileInfo['content'] = (string)file_get_contents($fileData['ID_absFile']);
1011  } else {
1012  GeneralUtility::upload_copy_move(
1013  $fileData['ID_absFile'],
1014  $this->‪getOrCreateTemporaryFolderName() . '/' . $fileMd5
1015  );
1016  }
1017  $fileInfo['content_md5'] = $fileMd5;
1018  $this->dat['files'][$fileData['ID']] = $fileInfo;
1019 
1020  // ... and for the recordlisting, why not let us know WHICH relations there was...
1021  if ($recordRef !== '' && $recordRef !== '_SOFTREF_') {
1022  [$referencedTable, $referencedUid] = explode(':', $recordRef, 2);
1023  if (!is_array($this->dat['header']['records'][$referencedTable][$referencedUid]['filerefs'] ?? null)) {
1024  $this->dat['header']['records'][$referencedTable][$referencedUid]['filerefs'] = [];
1025  }
1026  $this->dat['header']['records'][$referencedTable][$referencedUid]['filerefs'][] = $fileData['ID'];
1027  }
1028 
1029  // For soft references, do further processing:
1030  if ($recordRef === '_SOFTREF_') {
1031  // Files with external media?
1032  // This is only done with files grabbed by a soft reference parser since it is deemed improbable
1033  // that hard-referenced files should undergo this treatment.
1034  if ($this->includeExtFileResources
1035  && GeneralUtility::inList($this->extFileResourceExtensions, strtolower($pathInfo['extension']))
1036  ) {
1037  $uniqueDelimiter = '###' . md5(‪$GLOBALS['EXEC_TIME']) . '###';
1038  if (strtolower($pathInfo['extension']) === 'css') {
1039  $fileContentParts = explode(
1040  $uniqueDelimiter,
1041  (string)preg_replace(
1042  '/(url[[:space:]]*\\([[:space:]]*["\']?)([^"\')]*)(["\']?[[:space:]]*\\))/i',
1043  '\\1' . $uniqueDelimiter . '\\2' . $uniqueDelimiter . '\\3',
1044  $fileInfo['content']
1045  )
1046  );
1047  } else {
1048  // html, htm:
1049  $htmlParser = GeneralUtility::makeInstance(HtmlParser::class);
1050  $fileContentParts = explode(
1051  $uniqueDelimiter,
1052  $htmlParser->prefixResourcePath(
1053  $uniqueDelimiter,
1054  $fileInfo['content'],
1055  [],
1056  $uniqueDelimiter
1057  )
1058  );
1059  }
1060  $resourceCaptured = false;
1061  // @todo: drop this by-reference handling
1062  foreach ($fileContentParts as $index => &$fileContentPart) {
1063  if ($index % 2) {
1064  $resRelativePath = &$fileContentPart;
1065  $resAbsolutePath = GeneralUtility::resolveBackPath(‪PathUtility::dirname($fileData['ID_absFile']) . '/' . $resRelativePath);
1066  $resAbsolutePath = GeneralUtility::getFileAbsFileName($resAbsolutePath);
1067  if ($resAbsolutePath !== ''
1068  && str_starts_with($resAbsolutePath, ‪Environment::getPublicPath() . '/' . $this->‪getFileadminFolderName() . '/')
1069  && @is_file($resAbsolutePath)
1070  ) {
1071  $resourceCaptured = true;
1072  $resourceId = md5($resAbsolutePath);
1073  $this->dat['header']['files'][$fileData['ID']]['EXT_RES_ID'][] = $resourceId;
1074  $fileContentParts[$index] = '{EXT_RES_ID:' . $resourceId . '}';
1075  // Add file to memory if it is not set already:
1076  if (!isset($this->dat['header']['files'][$resourceId])) {
1077  $fileStat = stat($resAbsolutePath);
1078  $fileInfo = [];
1079  $fileInfo['filename'] = ‪PathUtility::basename($resAbsolutePath);
1080  $fileInfo['filemtime'] = $fileStat['mtime'];
1081  $fileInfo['record_ref'] = '_EXT_PARENT_:' . $fileData['ID'];
1082  $fileInfo['parentRelFileName'] = $resRelativePath;
1083  // Setting this data in the header
1084  $this->dat['header']['files'][$resourceId] = $fileInfo;
1085  $fileInfo['content'] = (string)file_get_contents($resAbsolutePath);
1086  $fileInfo['content_md5'] = md5($fileInfo['content']);
1087  $this->dat['files'][$resourceId] = $fileInfo;
1088  }
1089  }
1090  }
1091  }
1092  if ($resourceCaptured) {
1093  $this->dat['files'][$fileData['ID']]['tokenizedContent'] = implode('', $fileContentParts);
1094  }
1095  }
1096  }
1097  }
1098 
1102  protected function ‪exportAddFilesFromSysFilesRecords(): void
1103  {
1104  if (!isset($this->dat['header']['records']['sys_file']) || !is_array($this->dat['header']['records']['sys_file'] ?? null)) {
1105  return;
1106  }
1107  foreach ($this->dat['header']['records']['sys_file'] as $sysFileUid => $_) {
1108  $fileData = $this->dat['records']['sys_file:' . $sysFileUid]['data'];
1109  $this->‪exportAddSysFile($fileData);
1110  }
1111  }
1112 
1120  protected function ‪exportAddSysFile(array $fileData): void
1121  {
1122  try {
1123  $file = GeneralUtility::makeInstance(ResourceFactory::class)->createFileObject($fileData);
1124  $file->checkActionPermission('read');
1125  } catch (\Exception $e) {
1126  $this->‪addError('Error when trying to add file ' . $fileData['title'] . ': ' . $e->getMessage());
1127  return;
1128  }
1129 
1130  $fileUid = $file->getUid();
1131  $fileSha1 = $file->getStorage()->hashFile($file, 'sha1');
1132  if ($fileSha1 !== $file->getProperty('sha1')) {
1133  $this->dat['records']['sys_file:' . $fileUid]['data']['sha1'] = $fileSha1;
1134  $this->‪addError(
1135  'The SHA-1 file hash of ' . $file->getCombinedIdentifier() . ' is not up-to-date in the index! ' .
1136  'The file was added based on the current file hash.'
1137  );
1138  }
1139  // Build unique id based on the storage and the file identifier
1140  $fileId = md5($file->getStorage()->getUid() . ':' . $file->getProperty('identifier_hash'));
1141 
1142  $fileInfo = [];
1143  $fileInfo['filename'] = $file->getProperty('name');
1144  $fileInfo['filemtime'] = $file->getProperty('modification_date');
1145 
1146  // Setting this data in the header
1147  $this->dat['header']['files_fal'][$fileId] = $fileInfo;
1148 
1149  if (!$this->saveFilesOutsideExportFile) {
1150  $fileInfo['content'] = $file->getContents();
1151  } else {
1152  GeneralUtility::upload_copy_move(
1153  $file->getForLocalProcessing(false),
1154  $this->getOrCreateTemporaryFolderName() . '/' . $fileSha1
1155  );
1156  }
1157  $fileInfo['content_sha1'] = $fileSha1;
1158  $this->dat['files_fal'][$fileId] = $fileInfo;
1159  }
1160 
1161  /**************************
1162  * File Output
1163  *************************/
1164 
1172  public function ‪render(): string
1173  {
1174  if ($this->exportFileType === self::FILETYPE_XML) {
1175  $out = $this->‪createXML();
1176  } else {
1177  $out = '';
1178  // adding header:
1179  $out .= $this->‪addFilePart(serialize($this->dat['header']));
1180  // adding records:
1181  $out .= $this->‪addFilePart(serialize($this->dat['records']));
1182  // adding files:
1183  $out .= $this->‪addFilePart(serialize($this->dat['files'] ?? null));
1184  // adding files_fal:
1185  $out .= $this->‪addFilePart(serialize($this->dat['files_fal'] ?? null));
1186  }
1187  return $out;
1188  }
1189 
1195  protected function ‪createXML(): string
1196  {
1197  // Options:
1198  $options = [
1199  'alt_options' => [
1200  '/header' => [
1201  'disableTypeAttrib' => true,
1202  'clearStackPath' => true,
1203  'parentTagMap' => [
1204  'files' => 'file',
1205  'files_fal' => 'file',
1206  'records' => 'table',
1207  'table' => 'rec',
1208  'rec:rels' => 'relations',
1209  'relations' => 'element',
1210  'filerefs' => 'file',
1211  'pid_lookup' => 'page_contents',
1212  'header:relStaticTables' => 'static_tables',
1213  'static_tables' => 'tablename',
1214  'excludeMap' => 'item',
1215  'softrefCfg' => 'softrefExportMode',
1216  'extensionDependencies' => 'extkey',
1217  'softrefs' => 'softref_element',
1218  ],
1219  'alt_options' => [
1220  '/pagetree' => [
1221  'disableTypeAttrib' => true,
1222  'useIndexTagForNum' => 'node',
1223  'parentTagMap' => [
1224  'node:subrow' => 'node',
1225  ],
1226  ],
1227  '/pid_lookup/page_contents' => [
1228  'disableTypeAttrib' => true,
1229  'parentTagMap' => [
1230  'page_contents' => 'table',
1231  ],
1232  'grandParentTagMap' => [
1233  'page_contents/table' => 'item',
1234  ],
1235  ],
1236  ],
1237  ],
1238  '/records' => [
1239  'disableTypeAttrib' => true,
1240  'parentTagMap' => [
1241  'records' => 'tablerow',
1242  'tablerow:data' => 'fieldlist',
1243  'tablerow:rels' => 'related',
1244  'related' => 'field',
1245  'field:itemArray' => 'relations',
1246  'field:newValueFiles' => 'filerefs',
1247  'field:flexFormRels' => 'flexform',
1248  'relations' => 'element',
1249  'filerefs' => 'file',
1250  'flexform:db' => 'db_relations',
1251  'flexform:softrefs' => 'softref_relations',
1252  'softref_relations' => 'structurePath',
1253  'db_relations' => 'path',
1254  'path' => 'element',
1255  'keys' => 'softref_key',
1256  'softref_key' => 'softref_element',
1257  ],
1258  'alt_options' => [
1259  '/records/tablerow/fieldlist' => [
1260  'useIndexTagForAssoc' => 'field',
1261  ],
1262  ],
1263  ],
1264  '/files' => [
1265  'disableTypeAttrib' => true,
1266  'parentTagMap' => [
1267  'files' => 'file',
1268  ],
1269  ],
1270  '/files_fal' => [
1271  'disableTypeAttrib' => true,
1272  'parentTagMap' => [
1273  'files_fal' => 'file',
1274  ],
1275  ],
1276  ],
1277  ];
1278  // Creating XML file from $outputArray:
1279  $charset = $this->dat['header']['charset'] ?: 'utf-8';
1280  $XML = '<?xml version="1.0" encoding="' . $charset . '" standalone="yes" ?>' . LF;
1281  $XML .= (new ‪Typo3XmlSerializer())->encodeWithReturningExceptionAsString(
1282  $this->dat,
1284  $options
1285  );
1286  return $XML;
1287  }
1295  protected function ‪addFilePart(string $data): string
1296  {
1297  $compress = $this->exportFileType === ‪self::FILETYPE_T3DZ;
1298  if ($compress) {
1299  $data = (string)gzcompress($data);
1300  }
1301  return md5($data) . ':' . ($compress ? '1' : '0') . ':' . str_pad((string)strlen($data), 10, '0', STR_PAD_LEFT) . ':' . $data . ':';
1302  }
1303 
1308  public function ‪saveToFile(): ‪File
1309  {
1310  $saveFolder = $this->‪getOrCreateDefaultImportExportFolder();
1312  $filesFolderName = $fileName . '.files';
1313  $fileContent = $this->‪render();
1314 
1315  if (!($saveFolder instanceof ‪Folder && $saveFolder->‪checkActionPermission('write'))) {
1317  'You are not allowed to write to the target folder "' . $saveFolder->getPublicUrl() . '"',
1318  1602432207
1319  );
1320  }
1321 
1322  if ($saveFolder->hasFolder($filesFolderName)) {
1323  $saveFolder->getSubfolder($filesFolderName)->delete(true);
1324  }
1326  $temporaryFileName = GeneralUtility::tempnam('export');
1327  ‪GeneralUtility::writeFile($temporaryFileName, $fileContent);
1328  $file = $saveFolder->addFile($temporaryFileName, $fileName, 'replace');
1329 
1330  if ($this->saveFilesOutsideExportFile) {
1331  $filesFolder = $saveFolder->createFolder($filesFolderName);
1332  $temporaryFilesForExport = GeneralUtility::getFilesInDir($this->‪getOrCreateTemporaryFolderName(), '', true);
1333  foreach ($temporaryFilesForExport as $temporaryFileForExport) {
1334  $filesFolder->addFile($temporaryFileForExport);
1335  }
1337  }
1338 
1339  return $file;
1340  }
1341 
1345  public function ‪getExportFileName(): string
1346  {
1347  return ‪$this->exportFileName;
1348  }
1349 
1353  public function ‪setExportFileName(string ‪$exportFileName): void
1354  {
1355  ‪$exportFileName = trim((string)preg_replace('/[^[:alnum:]._-]*/', '', ‪$exportFileName));
1356  $this->exportFileName = ‪$exportFileName;
1357  }
1358 
1362  public function ‪getOrGenerateExportFileNameWithFileExtension(): string
1363  {
1364  if (!empty($this->exportFileName)) {
1366  } else {
1368  }
1369  $exportFileName .= $this->‪getFileExtensionByFileType();
1370 
1371  return ‪$exportFileName;
1372  }
1373 
1377  protected function ‪generateExportFileName(): string
1378  {
1379  if ($this->pid !== -1) {
1380  ‪$exportFileName = 'tree_PID' . $this->pid . '_L' . ‪$this->levels;
1381  } elseif (!empty($this->‪getRecord())) {
1382  $exportFileName = 'recs_' . implode('-', $this->‪getRecord());
1383  $exportFileName = str_replace(':', '_', ‪$exportFileName);
1384  } elseif (!empty($this->‪getList())) {
1385  $exportFileName = 'list_' . implode('-', $this->‪getList());
1386  $exportFileName = str_replace(':', '_', ‪$exportFileName);
1387  } else {
1388  ‪$exportFileName = 'export';
1389  }
1390 
1391  ‪$exportFileName = substr(trim((string)preg_replace('/[^[:alnum:]_-]/', '-', ‪$exportFileName)), 0, 20);
1392 
1393  return 'T3D_' . ‪$exportFileName . '_' . date('Y-m-d_H-i');
1394  }
1395 
1399  public function ‪getExportFileType(): string
1400  {
1401  return ‪$this->exportFileType;
1402  }
1403 
1407  public function ‪setExportFileType(string ‪$exportFileType): void
1408  {
1410  if (!in_array(‪$exportFileType, ‪$supportedFileTypes, true)) {
1411  throw new \InvalidArgumentException(
1412  sprintf(
1413  'File type "%s" is not valid. Supported file types are %s.',
1415  implode(', ', array_map(static function ($fileType) {
1416  return '"' . $fileType . '"';
1418  ),
1419  1602505264
1420  );
1421  }
1422  $this->exportFileType = ‪$exportFileType;
1423  }
1424 
1428  public function ‪getSupportedFileTypes(): array
1429  {
1430  if (empty($this->supportedFileTypes)) {
1434  if ($this->compressionAvailable) {
1436  }
1437  $this->supportedFileTypes = ‪$supportedFileTypes;
1438  }
1440  }
1441 
1445  protected function ‪getFileExtensionByFileType(): string
1446  {
1447  switch ($this->exportFileType) {
1448  case ‪self::FILETYPE_XML:
1449  return '.xml';
1450  case ‪self::FILETYPE_T3D:
1451  return '.t3d';
1453  default:
1454  return '-z.t3d';
1455  }
1456  }
1457 
1458  /**************************
1459  * Getters and Setters
1460  *************************/
1465  public function ‪getTitle(): string
1466  {
1467  return ‪$this->title;
1468  }
1473  public function ‪setTitle(string ‪$title): void
1474  {
1475  $this->title = ‪$title;
1476  }
1481  public function ‪getDescription(): string
1482  {
1483  return ‪$this->description;
1484  }
1489  public function ‪setDescription(string ‪$description): void
1490  {
1491  $this->description = ‪$description;
1492  }
1497  public function ‪getNotes(): string
1498  {
1499  return ‪$this->notes;
1500  }
1505  public function ‪setNotes(string ‪$notes): void
1506  {
1507  $this->notes = ‪$notes;
1508  }
1513  public function ‪getRecord(): array
1514  {
1515  return ‪$this->record;
1516  }
1521  public function ‪setRecord(array ‪$record): void
1522  {
1523  $this->record = ‪$record;
1524  }
1529  public function ‪getList(): array
1530  {
1531  return ‪$this->list;
1532  }
1537  public function ‪setList(array ‪$list): void
1538  {
1539  $this->list = ‪$list;
1540  }
1545  public function ‪getLevels(): int
1546  {
1547  return ‪$this->levels;
1548  }
1553  public function ‪setLevels(int ‪$levels): void
1554  {
1555  $this->levels = ‪$levels;
1556  }
1561  public function ‪getTables(): array
1562  {
1563  return ‪$this->tables;
1564  }
1569  public function ‪setTables(array ‪$tables): void
1570  {
1571  $this->tables = ‪$tables;
1572  }
1577  public function ‪getRelOnlyTables(): array
1578  {
1579  return ‪$this->relOnlyTables;
1580  }
1585  public function ‪setRelOnlyTables(array ‪$relOnlyTables): void
1586  {
1587  $this->relOnlyTables = ‪$relOnlyTables;
1588  }
1593  public function ‪getTreeHTML(): string
1594  {
1595  return ‪$this->treeHTML;
1596  }
1597 
1601  public function ‪isIncludeExtFileResources(): bool
1602  {
1604  }
1605 
1610  {
1611  $this->includeExtFileResources = ‪$includeExtFileResources;
1612  }
1613 
1622  {
1623  $this->saveFilesOutsideExportFile = ‪$saveFilesOutsideExportFile;
1624  }
1625 
1629  public function ‪isSaveFilesOutsideExportFile(): bool
1630  {
1632  }
1633 }
‪TYPO3\CMS\Impexp\Export\setExportFileName
‪setExportFileName(string $exportFileName)
Definition: Export.php:1333
‪TYPO3\CMS\Impexp\Export\exportAddRecordsFromRelations
‪int exportAddRecordsFromRelations(int $relationLevel=0)
Definition: Export.php:730
‪TYPO3\CMS\Impexp\Export\$mode
‪string $mode
Definition: Export.php:59
‪TYPO3\CMS\Impexp\ImportExport\getFileadminFolderName
‪string getFileadminFolderName()
Definition: ImportExport.php:1122
‪TYPO3\CMS\Impexp\ImportExport\getOrCreateTemporaryFolderName
‪string getOrCreateTemporaryFolderName()
Definition: ImportExport.php:1137
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseOrderBy
‪static array array[] parseOrderBy(string $input)
Definition: QueryHelper.php:44
‪TYPO3\CMS\Impexp\Export\render
‪string render()
Definition: Export.php:1152
‪TYPO3\CMS\Impexp\Export\execListQueryPid
‪Result execListQueryPid(int $pid, string $table)
Definition: Export.php:429
‪TYPO3\CMS\Impexp\ImportExport\$extensionDependencies
‪array $extensionDependencies
Definition: ImportExport.php:147
‪TYPO3\CMS\Impexp\Export\getDescription
‪string getDescription()
Definition: Export.php:1461
‪TYPO3\CMS\Impexp\Export\setList
‪setList(array $list)
Definition: Export.php:1517
‪TYPO3\CMS\Impexp\Export\$treeHTML
‪string $treeHTML
Definition: Export.php:98
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:25
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:49
‪TYPO3\CMS\Impexp\Export\$supportedFileTypes
‪array $supportedFileTypes
Definition: Export.php:141
‪TYPO3\CMS\Impexp\Export\filterRecordFields
‪array filterRecordFields(string $table, array $row)
Definition: Export.php:544
‪TYPO3\CMS\Impexp\Export\setExportFileType
‪setExportFileType(string $exportFileType)
Definition: Export.php:1387
‪TYPO3\CMS\Impexp\ImportExport\addError
‪addError(string $message)
Definition: ImportExport.php:1453
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:206
‪TYPO3\CMS\Impexp\Export\getRecord
‪array getRecord()
Definition: Export.php:1493
‪TYPO3\CMS\Impexp\Export\setRecordTypeIncludeFields
‪setRecordTypeIncludeFields(string $table, array $fields)
Definition: Export.php:371
‪TYPO3\CMS\Impexp\Export\isPageInWebMount
‪bool isPageInWebMount(int $pid)
Definition: Export.php:527
‪TYPO3\CMS\Impexp\Export\saveToFile
‪File saveToFile()
Definition: Export.php:1288
‪TYPO3\CMS\Impexp\Export\setNotes
‪setNotes(string $notes)
Definition: Export.php:1485
‪TYPO3\CMS\Impexp\Export\FILETYPE_XML
‪const FILETYPE_XML
Definition: Export.php:53
‪TYPO3\CMS\Impexp\Export\$exportFileType
‪string $exportFileType
Definition: Export.php:137
‪TYPO3\CMS\Core\Serializer\Typo3XmlSerializer
Definition: Typo3XmlSerializer.php:123
‪TYPO3\CMS\Core\Html\HtmlParser
Definition: HtmlParser.php:27
‪TYPO3\CMS\Impexp\Export\setRelOnlyTables
‪setRelOnlyTables(array $relOnlyTables)
Definition: Export.php:1565
‪TYPO3\CMS\Impexp\Export\$recordTypesIncludeFields
‪array $recordTypesIncludeFields
Definition: Export.php:119
‪TYPO3\CMS\Impexp\Export\inclRelation
‪bool inclRelation(string $table)
Definition: Export.php:853
‪TYPO3\CMS\Core\Utility\PathUtility\dirname
‪static string dirname($path)
Definition: PathUtility.php:251
‪TYPO3\CMS\Core\Information\Typo3Version
Definition: Typo3Version.php:21
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Impexp\Export\process
‪process()
Definition: Export.php:169
‪TYPO3\CMS\Impexp\Export\$title
‪string $title
Definition: Export.php:63
‪TYPO3\CMS\Impexp\Export\getExcludePagesClause
‪string getExcludePagesClause()
Definition: Export.php:382
‪TYPO3\CMS\Impexp\Export\__construct
‪__construct()
Definition: Export.php:156
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static string stripPathSitePrefix($path)
Definition: PathUtility.php:445
‪TYPO3\CMS\Impexp\Export\exportAddFilesFromRelations
‪exportAddFilesFromRelations()
Definition: Export.php:866
‪TYPO3\CMS\Core\Database\ReferenceIndex
Definition: ReferenceIndex.php:42
‪TYPO3\CMS\Impexp\Export\$compressionAvailable
‪bool $compressionAvailable
Definition: Export.php:145
‪TYPO3\CMS\Impexp\ImportExport\$pid
‪int $pid
Definition: ImportExport.php:62
‪TYPO3\CMS\Impexp\View\ExportPageTreeView
Definition: ExportPageTreeView.php:34
‪TYPO3\CMS\Impexp\Export\getFileExtensionByFileType
‪string getFileExtensionByFileType()
Definition: Export.php:1425
‪TYPO3\CMS\Impexp\ImportExport\isTableStatic
‪bool isTableStatic(string $table)
Definition: ImportExport.php:1264
‪TYPO3\CMS\Impexp\Export\$extFileResourceExtensions
‪string $extFileResourceExtensions
Definition: Export.php:110
‪TYPO3\CMS\Core\Exception
‪TYPO3\CMS\Impexp\Export\exportAddFile
‪exportAddFile(array $fileData, string $recordRef='', string $field='')
Definition: Export.php:964
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\check
‪bool check($type, $value)
Definition: BackendUserAuthentication.php:585
‪TYPO3\CMS\Impexp\Export\$list
‪array $list
Definition: Export.php:79
‪TYPO3\CMS\Impexp\Export\setHeaderBasics
‪setHeaderBasics()
Definition: Export.php:270
‪TYPO3\CMS\Impexp\Export\$exportFileName
‪string $exportFileName
Definition: Export.php:133
‪TYPO3\CMS\Impexp\Export\isIncludeExtFileResources
‪bool isIncludeExtFileResources()
Definition: Export.php:1581
‪TYPO3\CMS\Impexp\Export\$saveFilesOutsideExportFile
‪bool $saveFilesOutsideExportFile
Definition: Export.php:129
‪TYPO3\CMS\Core\Serializer\Typo3XmlParserOptions\ROOT_NODE_NAME
‪const ROOT_NODE_NAME
Definition: Typo3XmlParserOptions.php:29
‪$fields
‪$fields
Definition: pages.php:5
‪TYPO3\CMS\Impexp\Export\$relOnlyTables
‪array $relOnlyTables
Definition: Export.php:94
‪TYPO3\CMS\Impexp\Export\LEVELS_INFINITE
‪const LEVELS_INFINITE
Definition: Export.php:51
‪TYPO3\CMS\Impexp\ImportExport\$softrefCfg
‪array $softrefCfg
Definition: ImportExport.php:141
‪TYPO3\CMS\Impexp\Export\getSupportedFileTypes
‪array getSupportedFileTypes()
Definition: Export.php:1408
‪TYPO3\CMS\Impexp\ImportExport\isRecordDisabled
‪bool isRecordDisabled(string $table, int $uid)
Definition: ImportExport.php:369
‪TYPO3\CMS\Core\Utility\PathUtility\basename
‪static string basename($path)
Definition: PathUtility.php:226
‪TYPO3\CMS\Impexp\Export\exportAddSysFile
‪exportAddSysFile(array $fileData)
Definition: Export.php:1100
‪TYPO3\CMS\Impexp\Export\exportAddFilesFromSysFilesRecords
‪exportAddFilesFromSysFilesRecords()
Definition: Export.php:1082
‪TYPO3\CMS\Impexp\Export\$pageInWebMountCache
‪array $pageInWebMountCache
Definition: Export.php:151
‪TYPO3\CMS\Impexp\Export\removeRedundantSoftRefsInRelations
‪removeRedundantSoftRefsInRelations(array &$relations)
Definition: Export.php:612
‪TYPO3\CMS\Impexp\ImportExport\getOrCreateDefaultImportExportFolder
‪Folder null getOrCreateDefaultImportExportFolder()
Definition: ImportExport.php:1174
‪TYPO3\CMS\Impexp\Export\setSaveFilesOutsideExportFile
‪setSaveFilesOutsideExportFile(bool $saveFilesOutsideExportFile)
Definition: Export.php:1601
‪TYPO3\CMS\Impexp\Export\initializeExport
‪initializeExport()
Definition: Export.php:259
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Impexp\Export\setTitle
‪setTitle(string $title)
Definition: Export.php:1453
‪TYPO3\CMS\Impexp\Export\setRecordTypesIncludeFields
‪setRecordTypesIncludeFields(array $recordTypesIncludeFields)
Definition: Export.php:354
‪TYPO3\CMS\Impexp\Export\FILETYPE_T3D
‪const FILETYPE_T3D
Definition: Export.php:54
‪TYPO3\CMS\Impexp\Export\$description
‪string $description
Definition: Export.php:67
‪TYPO3\CMS\Impexp\Export\getOrGenerateExportFileNameWithFileExtension
‪string getOrGenerateExportFileNameWithFileExtension()
Definition: Export.php:1342
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:37
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:41
‪TYPO3\CMS\Impexp\Export\$notes
‪string $notes
Definition: Export.php:71
‪TYPO3\CMS\Impexp\Export\$record
‪array $record
Definition: Export.php:75
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:24
‪TYPO3\CMS\Impexp\Export\flatDbRelations
‪array flatDbRelations(array $relations)
Definition: Export.php:647
‪TYPO3\CMS\Core\Resource\Folder\checkActionPermission
‪bool checkActionPermission($action)
Definition: Folder.php:436
‪TYPO3\CMS\Impexp\Export\getTables
‪array getTables()
Definition: Export.php:1541
‪TYPO3\CMS\Impexp\Export\exportAddRecord
‪exportAddRecord(string $table, array $row, int $relationLevel=0)
Definition: Export.php:475
‪TYPO3\CMS\Impexp\Export\addRecordsForPid
‪addRecordsForPid(int $pid, array $tables)
Definition: Export.php:404
‪TYPO3\CMS\Impexp\Export\$levels
‪int $levels
Definition: Export.php:83
‪TYPO3\CMS\Impexp\Export\$includeExtFileResources
‪bool $includeExtFileResources
Definition: Export.php:104
‪TYPO3\CMS\Impexp\Export\setLevels
‪setLevels(int $levels)
Definition: Export.php:1533
‪TYPO3\CMS\Impexp\Export\setPageTree
‪setPageTree(array $pageTree)
Definition: Export.php:321
‪TYPO3\CMS\Impexp\ImportExport
Definition: ImportExport.php:45
‪TYPO3\CMS\Impexp\Export\LEVELS_EXPANDED_TREE
‪const LEVELS_EXPANDED_TREE
Definition: Export.php:50
‪TYPO3\CMS\Impexp\Export\createXML
‪string createXML()
Definition: Export.php:1175
‪TYPO3\CMS\Impexp\Export\getLevels
‪int getLevels()
Definition: Export.php:1525
‪TYPO3\CMS\Impexp\Export\LEVELS_RECORDS_ON_THIS_PAGE
‪const LEVELS_RECORDS_ON_THIS_PAGE
Definition: Export.php:49
‪TYPO3\CMS\Impexp\ImportExport\$relStaticTables
‪array $relStaticTables
Definition: ImportExport.php:129
‪TYPO3\CMS\Impexp\Export\getRelOnlyTables
‪array getRelOnlyTables()
Definition: Export.php:1557
‪TYPO3\CMS\Impexp\Export\getTitle
‪string getTitle()
Definition: Export.php:1445
‪TYPO3\CMS\Impexp\Export\getTreeHTML
‪string getTreeHTML()
Definition: Export.php:1573
‪TYPO3\CMS\Impexp\Export\fixFileIdInRelations
‪fixFileIdInRelations(array &$relations)
Definition: Export.php:571
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:38
‪TYPO3\CMS\Core\Serializer\Typo3XmlParserOptions
Definition: Typo3XmlParserOptions.php:24
‪TYPO3\CMS\Impexp\Export\removeExcludedPagesFromPageTree
‪removeExcludedPagesFromPageTree(array &$pageTree)
Definition: Export.php:331
‪TYPO3\CMS\Impexp\ImportExport\flatInversePageTree
‪flatInversePageTree(array $pageTree, array &$list, int $pid=-1)
Definition: ImportExport.php:1246
‪TYPO3\CMS\Impexp\Export\getNotes
‪string getNotes()
Definition: Export.php:1477
‪TYPO3\CMS\Impexp\ImportExport\isSoftRefIncluded
‪bool isSoftRefIncluded(string $tokenID)
Definition: ImportExport.php:1292
‪TYPO3\CMS\Impexp\Export\getExportFileName
‪string getExportFileName()
Definition: Export.php:1325
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Impexp\Export\getList
‪array getList()
Definition: Export.php:1509
‪TYPO3\CMS\Impexp\ImportExport\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: ImportExport.php:1466
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Impexp\Export\flatSoftRefs
‪array flatSoftRefs(array $relations)
Definition: Export.php:675
‪TYPO3\CMS\Impexp\Export\FILETYPE_T3DZ
‪const FILETYPE_T3DZ
Definition: Export.php:55
‪TYPO3\CMS\Impexp\Export\setDescription
‪setDescription(string $description)
Definition: Export.php:1469
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:43
‪TYPO3\CMS\Impexp\Export\exportAddRecordsFromRelationsPushRelation
‪exportAddRecordsFromRelationsPushRelation(array $recordData, array &$addRecords, string $tokenID='')
Definition: Export.php:833
‪TYPO3\CMS\Impexp\Export
Definition: Export.php:48
‪TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException
Definition: InsufficientFolderWritePermissionsException.php:21
‪TYPO3\CMS\Impexp\ImportExport\$excludeMap
‪array $excludeMap
Definition: ImportExport.php:135
‪TYPO3\CMS\Impexp\Export\setTables
‪setTables(array $tables)
Definition: Export.php:1549
‪TYPO3\CMS\Impexp\Export\isSaveFilesOutsideExportFile
‪bool isSaveFilesOutsideExportFile()
Definition: Export.php:1609
‪TYPO3\CMS\Impexp\Export\setRecord
‪setRecord(array $record)
Definition: Export.php:1501
‪TYPO3\CMS\Impexp\Export\addFilePart
‪string addFilePart(string $data)
Definition: Export.php:1275
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\isInWebMount
‪int null isInWebMount($idOrRow, $readPerms='', $exitOnError=null)
Definition: BackendUserAuthentication.php:304
‪TYPO3\CMS\Impexp\Export\setIncludeExtFileResources
‪setIncludeExtFileResources(bool $includeExtFileResources)
Definition: Export.php:1589
‪TYPO3\CMS\Impexp\Export\$defaultRecordIncludeFields
‪array $defaultRecordIncludeFields
Definition: Export.php:125
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Impexp\Export\$tables
‪array $tables
Definition: Export.php:87
‪TYPO3\CMS\Impexp\ImportExport\removeTemporaryFolderName
‪removeTemporaryFolderName()
Definition: ImportExport.php:1160
‪TYPO3\CMS\Core\Utility\GeneralUtility\writeFile
‪static bool writeFile($file, $content, $changePermissions=false)
Definition: GeneralUtility.php:1722
‪TYPO3\CMS\Impexp\Export\generateExportFileName
‪string generateExportFileName()
Definition: Export.php:1357
‪TYPO3\CMS\Impexp\Export\setMetaData
‪setMetaData()
Definition: Export.php:297
‪TYPO3\CMS\Impexp\ImportExport\isRecordExcluded
‪bool isRecordExcluded(string $table, int $uid)
Definition: ImportExport.php:1281
‪TYPO3\CMS\Impexp
‪TYPO3\CMS\Impexp\Export\getExportFileType
‪string getExportFileType()
Definition: Export.php:1379
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:40