‪TYPO3CMS  ‪main
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;
44 
51 {
52  public const ‪LEVELS_RECORDS_ON_THIS_PAGE = -2;
53  public const ‪LEVELS_EXPANDED_TREE = -1;
54  public const ‪LEVELS_INFINITE = 999;
55 
56  public const ‪FILETYPE_XML = 'xml';
57  public const ‪FILETYPE_T3D = 't3d';
58  public const ‪FILETYPE_T3DZ = 't3d_compressed';
59 
63  protected ‪$mode = 'export';
64 
68  protected ‪$title = '';
69 
73  protected ‪$description = '';
74 
78  protected ‪$notes = '';
79 
83  protected ‪$record = [];
84 
88  protected ‪$list = [];
89 
93  protected ‪$levels = 0;
94 
98  protected ‪$tables = [];
99 
106  protected ‪$relOnlyTables = [];
107 
111  protected ‪$treeHTML = '';
112 
118  protected ‪$includeExtFileResources = true;
119 
125  protected ‪$extFileResourceExtensions = 'html,htm,css';
126 
135  protected ‪$recordTypesIncludeFields = [];
136 
142  protected ‪$defaultRecordIncludeFields = ['uid', 'pid'];
143 
147  protected ‪$saveFilesOutsideExportFile = false;
148 
152  protected ‪$exportFileName = '';
153 
158 
162  protected ‪$supportedFileTypes = [];
163 
167  protected ‪$compressionAvailable = false;
168 
174  protected ‪$pageInWebMountCache = [];
175 
179  public function ‪__construct()
180  {
181  parent::__construct();
182  $this->compressionAvailable = function_exists('gzcompress');
183  }
184 
185  /**************************
186  * Export / Init + Meta Data
187  *************************/
188 
192  public function ‪process(): void
193  {
194  $this->‪initializeExport();
195  $this->‪setHeaderBasics();
196  $this->‪setMetaData();
197 
198  // Configure which records to export
199  foreach ($this->record as $ref) {
200  $rParts = explode(':', $ref);
201  $table = $rParts[0];
202  ‪$record = BackendUtility::getRecord($rParts[0], (int)$rParts[1]);
203  if (is_array(‪$record)) {
204  $this->‪exportAddRecord($table, ‪$record);
205  }
206  }
207 
208  // Configure which tables to export
209  foreach ($this->list as $ref) {
210  $rParts = explode(':', $ref);
211  $table = $rParts[0];
212  ‪$pid = (int)$rParts[1];
213  if ($this->‪getBackendUser()->check('tables_select', $table)) {
214  $statement = $this->‪execListQueryPid(‪$pid, $table);
215  while (‪$record = $statement->fetchAssociative()) {
216  if (is_array(‪$record)) {
217  $this->‪exportAddRecord($table, ‪$record);
218  }
219  }
220  }
221  }
222 
223  // Configure which page tree to export
224  if ($this->pid !== -1) {
225  $pageTree = null;
226  if ($this->levels === self::LEVELS_EXPANDED_TREE) {
227  $pageTreeView = GeneralUtility::makeInstance(ExportPageTreeView::class);
228  $initClause = $this->‪getExcludePagesClause();
229  if ($this->excludeDisabledRecords) {
230  $initClause .= BackendUtility::BEenableFields('pages');
231  }
232  $pageTreeView->init($initClause);
233  $pageTreeView->buildTreeByExpandedState($this->pid);
234  $this->treeHTML = $pageTreeView->printTree();
235  $pageTree = $pageTreeView->buffer_idH;
236  } elseif ($this->levels === self::LEVELS_RECORDS_ON_THIS_PAGE) {
237  $this->‪addRecordsForPid($this->pid, $this->tables);
238  } else {
239  $pageTreeView = GeneralUtility::makeInstance(ExportPageTreeView::class);
240  $initClause = $this->‪getExcludePagesClause();
241  if ($this->excludeDisabledRecords) {
242  $initClause .= BackendUtility::BEenableFields('pages');
243  }
244  $pageTreeView->init($initClause);
245  $pageTreeView->buildTreeByLevels($this->pid, $this->levels);
246  $this->treeHTML = $pageTreeView->printTree();
247  $pageTree = $pageTreeView->buffer_idH;
248  }
249  // In most cases, we should have a multi-level array, $pageTree, with the page tree
250  // structure here (and the HTML code loaded into memory for a nice display...)
251  if (is_array($pageTree)) {
252  $pageList = [];
253  $this->‪removeExcludedPagesFromPageTree($pageTree);
254  $this->‪setPageTree($pageTree);
255  $this->‪flatInversePageTree($pageTree, $pageList);
256  foreach ($pageList as $pageUid => $_) {
257  ‪$record = BackendUtility::getRecord('pages', $pageUid);
258  if (is_array(‪$record)) {
259  $this->‪exportAddRecord('pages', ‪$record);
260  }
261  $this->‪addRecordsForPid((int)$pageUid, $this->tables);
262  }
263  }
264  }
265 
266  // After adding ALL records we add records from database relations
267  for ($l = 0; $l < 10; $l++) {
268  if ($this->‪exportAddRecordsFromRelations($l) === 0) {
269  break;
270  }
271  }
272 
273  // Files must be added after the database relations are added,
274  // so that files from ALL added records are included!
277  }
278 
282  protected function ‪initializeExport(): void
283  {
284  $this->dat = [
285  'header' => [],
286  'records' => [],
287  ];
288  }
289 
293  protected function ‪setHeaderBasics(): void
294  {
295  // Initializing:
296  foreach ($this->softrefCfg as $key => $value) {
297  if (!($value['mode'] ?? false)) {
298  unset($this->softrefCfg[$key]);
299  }
300  }
301  // Setting in header memory:
302  // Version of file format
303  $this->dat['header']['XMLversion'] = '1.0';
304  // Initialize meta data array (to put it in top of file)
305  $this->dat['header']['meta'] = [];
306  // Add list of tables to consider static
307  $this->dat['header']['relStaticTables'] = ‪$this->relStaticTables;
308  // The list of excluded records
309  $this->dat['header']['excludeMap'] = ‪$this->excludeMap;
310  // Soft reference mode for elements
311  $this->dat['header']['softrefCfg'] = ‪$this->softrefCfg;
312  // List of extensions the import depends on.
313  $this->dat['header']['extensionDependencies'] = ‪$this->extensionDependencies;
314  $this->dat['header']['charset'] = 'utf-8';
315  }
316 
320  protected function ‪setMetaData(): void
321  {
322  $user = $this->‪getBackendUser();
323  if ($user->user['lang'] ?? false) {
324  $locale = GeneralUtility::makeInstance(Locales::class)->createLocale($user->user['lang']);
325  } else {
326  $locale = new Locale();
327  }
328  $this->dat['header']['meta'] = [
329  'title' => ‪$this->title,
330  'description' => ‪$this->description,
331  'notes' => ‪$this->notes,
332  'packager_username' => $this->‪getBackendUser()->user['username'],
333  'packager_name' => $this->‪getBackendUser()->user['realName'],
334  'packager_email' => $this->‪getBackendUser()->user['email'],
335  'TYPO3_version' => (string)GeneralUtility::makeInstance(Typo3Version::class),
336  'created' => (new ‪DateFormatter())->format(‪$GLOBALS['EXEC_TIME'], 'EEE d. MMMM y', $locale),
337  ];
338  }
339 
340  /**************************
341  * Export / Init Page tree
342  *************************/
343 
349  public function ‪setPageTree(array $pageTree): void
350  {
351  $this->dat['header']['pagetree'] = $pageTree;
352  }
353 
359  protected function ‪removeExcludedPagesFromPageTree(array &$pageTree): void
360  {
361  foreach ($pageTree as ‪$pid => $value) {
362  if ($this->‪isRecordExcluded('pages', (int)($pageTree[‪$pid]['uid'] ?? 0))) {
363  unset($pageTree[‪$pid]);
364  } elseif (is_array($pageTree[‪$pid]['subrow'] ?? null)) {
365  $this->‪removeExcludedPagesFromPageTree($pageTree[‪$pid]['subrow']);
366  }
367  }
368  }
369 
370  /**************************
371  * Export
372  *************************/
373 
383  {
384  foreach (‪$recordTypesIncludeFields as $table => ‪$fields) {
385  if (!is_array(‪$fields)) {
386  throw new Exception('The include fields for record type ' . htmlspecialchars($table) . ' are not defined by an array.', 1391440658);
387  }
389  }
390  }
391 
399  protected function ‪setRecordTypeIncludeFields(string $table, array ‪$fields): void
400  {
401  $this->recordTypesIncludeFields[$table] = ‪$fields;
402  }
403 
410  protected function ‪getExcludePagesClause(): string
411  {
412  $pageIds = [];
413 
414  foreach ($this->excludeMap as $tableAndUid => $isExcluded) {
415  [$table, ‪$uid] = explode(':', $tableAndUid);
416  if ($table === 'pages') {
417  $pageIds[] = (int)‪$uid;
418  }
419  }
420  if (!empty($pageIds)) {
421  return ' AND uid NOT IN (' . implode(',', $pageIds) . ')';
422  }
423  return '';
424  }
425 
432  protected function ‪addRecordsForPid(int ‪$pid, array ‪$tables): void
433  {
434  foreach (‪$GLOBALS['TCA'] as $table => $value) {
435  if ($table !== 'pages'
436  && (in_array($table, ‪$tables, true) || in_array('_ALL', ‪$tables, true))
437  && $this->‪getBackendUser()->check('tables_select', $table)
438  && !(‪$GLOBALS['TCA'][$table]['ctrl']['is_static'] ?? false)
439  ) {
440  $statement = $this->‪execListQueryPid($pid, $table);
441  while (‪$record = $statement->fetchAssociative()) {
442  if (is_array(‪$record)) {
443  $this->‪exportAddRecord($table, ‪$record);
444  }
445  }
446  }
447  }
448  }
449 
457  protected function ‪execListQueryPid(int ‪$pid, string $table): Result
458  {
459  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
460 
461  $orderBy = ‪$GLOBALS['TCA'][$table]['ctrl']['sortby'] ?? ‪$GLOBALS['TCA'][$table]['ctrl']['default_sortby'] ?? '';
462 
463  if ($this->excludeDisabledRecords === false) {
464  $queryBuilder->getRestrictions()
465  ->removeAll()
466  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
467  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
468  } else {
469  $queryBuilder->getRestrictions()
470  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
471  }
472 
473  $queryBuilder->select('*')
474  ->from($table)
475  ->where(
476  $queryBuilder->expr()->eq(
477  'pid',
478  $queryBuilder->createNamedParameter(‪$pid, ‪Connection::PARAM_INT)
479  )
480  );
481 
482  $orderBys = ‪QueryHelper::parseOrderBy((string)$orderBy);
483  foreach ($orderBys as $orderPair) {
484  [$field, $order] = $orderPair;
485  $queryBuilder->addOrderBy($field, $order);
486  }
487  // Ensure deterministic sorting
488  if (!in_array('uid', array_column($orderBys, 0))) {
489  $queryBuilder->addOrderBy('uid', 'ASC');
490  }
491 
492  return $queryBuilder->executeQuery();
493  }
494 
503  public function ‪exportAddRecord(string $table, array $row, int $relationLevel = 0): void
504  {
505  BackendUtility::workspaceOL($table, $row);
506 
507  if ($table === '' || (int)$row['uid'] === 0
508  || $this->‪isRecordExcluded($table, (int)$row['uid'])
509  || $this->excludeDisabledRecords && $this->‪isRecordDisabled($table, (int)$row['uid'])) {
510  return;
511  }
512 
513  if ($this->‪isPageInWebMount($table === 'pages' ? (int)$row['uid'] : (int)$row['pid'])) {
514  if (!isset($this->dat['records'][$table . ':' . $row['uid']])) {
515  // Prepare header info:
516  $row = $this->‪filterRecordFields($table, $row);
517  $headerInfo = [];
518  $headerInfo['uid'] = $row['uid'];
519  $headerInfo['pid'] = $row['pid'];
520  $headerInfo['title'] = ‪GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $row), 40);
521  if ($relationLevel) {
522  $headerInfo['relationLevel'] = $relationLevel;
523  }
524  // Set the header summary:
525  $this->dat['header']['records'][$table][$row['uid']] = $headerInfo;
526  // Create entry in the PID lookup:
527  $this->dat['header']['pid_lookup'][$row['pid']][$table][$row['uid']] = 1;
528  // Initialize reference index object:
529  $refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class);
530  $relations = $refIndexObj->getRelations($table, $row);
531  $this->‪fixFileIdInRelations($relations);
532  $this->‪removeRedundantSoftRefsInRelations($relations);
533  // Data:
534  $this->dat['records'][$table . ':' . $row['uid']] = [];
535  $this->dat['records'][$table . ':' . $row['uid']]['data'] = $row;
536  $this->dat['records'][$table . ':' . $row['uid']]['rels'] = $relations;
537  // Add information about the relations in the record in the header:
538  $this->dat['header']['records'][$table][$row['uid']]['rels'] = $this->‪flatDbRelations($this->dat['records'][$table . ':' . $row['uid']]['rels']);
539  // Add information about the softrefs to header:
540  $this->dat['header']['records'][$table][$row['uid']]['softrefs'] = $this->‪flatSoftRefs($this->dat['records'][$table . ':' . $row['uid']]['rels']);
541  } else {
542  $this->‪addError('Record ' . $table . ':' . $row['uid'] . ' already added.');
543  }
544  } else {
545  $this->‪addError('Record ' . $table . ':' . $row['uid'] . ' was outside your database mounts!');
546  }
547  }
548 
555  protected function ‪isPageInWebMount(int ‪$pid): bool
556  {
557  if (!isset($this->pageInWebMountCache[‪$pid])) {
558  $this->pageInWebMountCache[‪$pid] = (bool)$this->‪getBackendUser()->isInWebMount($pid);
559  }
560  return $this->pageInWebMountCache[‪$pid];
561  }
562 
572  protected function ‪filterRecordFields(string $table, array $row): array
573  {
574  if (isset($this->recordTypesIncludeFields[$table])) {
575  $includeFields = array_unique(array_merge(
576  $this->recordTypesIncludeFields[$table],
577  $this->defaultRecordIncludeFields
578  ));
579  $newRow = [];
580  foreach ($row as $key => $value) {
581  if (in_array($key, $includeFields, true)) {
582  $newRow[$key] = $value;
583  }
584  }
585  } else {
586  $newRow = $row;
587  }
588  return $newRow;
589  }
590 
599  public function ‪fixFileIdInRelations(array &$relations): void
600  {
601  // @todo: Remove by-reference and return final array
602  foreach ($relations as &$relation) {
603  if (isset($relation['type']) && $relation['type'] === 'file') {
604  foreach ($relation['newValueFiles'] as &$fileRelationData) {
605  $absoluteFilePath = (string)$fileRelationData['ID_absFile'];
606  if (str_starts_with($absoluteFilePath, ‪Environment::getPublicPath())) {
607  $relatedFilePath = ‪PathUtility::stripPathSitePrefix($absoluteFilePath);
608  $fileRelationData['ID'] = md5($relatedFilePath);
609  }
610  }
611  unset($fileRelationData);
612  }
613  if (isset($relation['type']) && $relation['type'] === 'flex') {
614  if (is_array($relation['flexFormRels']['file'] ?? null)) {
615  foreach ($relation['flexFormRels']['file'] as &$subList) {
616  foreach ($subList as &$fileRelationData) {
617  $absoluteFilePath = (string)$fileRelationData['ID_absFile'];
618  if (str_starts_with($absoluteFilePath, ‪Environment::getPublicPath())) {
619  $relatedFilePath = ‪PathUtility::stripPathSitePrefix($absoluteFilePath);
620  $fileRelationData['ID'] = md5($relatedFilePath);
621  }
622  }
623  }
624  }
625  }
626  }
627  }
628 
640  public function ‪removeRedundantSoftRefsInRelations(array &$relations): void
641  {
642  // @todo: Remove by-reference and return final array
643  foreach ($relations as &$relation) {
644  if (isset($relation['type']) && $relation['type'] === 'db') {
645  foreach ($relation['itemArray'] as $dbRelationData) {
646  if ($dbRelationData['table'] === 'sys_file') {
647  if (isset($relation['softrefs']['keys']['typolink'])) {
648  foreach ($relation['softrefs']['keys']['typolink'] as $tokenID => &$softref) {
649  if ($softref['subst']['type'] === 'file') {
650  $file = GeneralUtility::makeInstance(ResourceFactory::class)->retrieveFileOrFolderObject($softref['subst']['relFileName']);
651  if ($file instanceof File) {
652  if ($file->getUid() == $dbRelationData['id']) {
653  unset($relation['softrefs']['keys']['typolink'][$tokenID]);
654  }
655  }
656  }
657  }
658  if (empty($relation['softrefs']['keys']['typolink'])) {
659  unset($relation['softrefs']);
660  }
661  }
662  }
663  }
664  }
665  }
666  }
667 
675  protected function ‪flatDbRelations(array $relations): array
676  {
677  ‪$list = [];
678  foreach ($relations as $relation) {
679  if (isset($relation['type'])) {
680  if ($relation['type'] === 'db') {
681  foreach ($relation['itemArray'] as $dbRelationData) {
682  ‪$list[$dbRelationData['table'] . ':' . $dbRelationData['id']] = $dbRelationData;
683  }
684  } elseif ($relation['type'] === 'flex' && is_array($relation['flexFormRels']['db'] ?? null)) {
685  foreach ($relation['flexFormRels']['db'] as $subList) {
686  foreach ($subList as $dbRelationData) {
687  ‪$list[$dbRelationData['table'] . ':' . $dbRelationData['id']] = $dbRelationData;
688  }
689  }
690  }
691  }
692  }
693  return ‪$list;
694  }
695 
703  protected function ‪flatSoftRefs(array $relations): array
704  {
705  ‪$list = [];
706  foreach ($relations as $field => $relation) {
707  if (is_array($relation['softrefs']['keys'] ?? null)) {
708  foreach ($relation['softrefs']['keys'] as $spKey => $elements) {
709  foreach ($elements as $subKey => $el) {
710  $lKey = $field . ':' . $spKey . ':' . $subKey;
711  ‪$list[$lKey] = array_merge(['field' => $field, 'spKey' => $spKey], $el);
712  // Add file_ID key to header - slightly "risky" way of doing this because if the calculation
713  // changes for the same value in $this->records[...] this will not work anymore!
714  if ($el['subst']['relFileName'] ?? false) {
715  ‪$list[$lKey]['file_ID'] = md5(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
716  }
717  }
718  }
719  }
720  if (isset($relation['type'])) {
721  if ($relation['type'] === 'flex' && is_array($relation['flexFormRels']['softrefs'] ?? null)) {
722  foreach ($relation['flexFormRels']['softrefs'] as $structurePath => &$subList) {
723  if (isset($subList['keys'])) {
724  foreach ($subList['keys'] as $spKey => $elements) {
725  foreach ($elements as $subKey => $el) {
726  $lKey = $field . ':' . $structurePath . ':' . $spKey . ':' . $subKey;
727  ‪$list[$lKey] = array_merge([
728  'field' => $field,
729  'spKey' => $spKey,
730  'structurePath' => $structurePath,
731  ], $el);
732  // Add file_ID key to header - slightly "risky" way of doing this because if the calculation
733  // changes for the same value in $this->records[...] this will not work anymore!
734  if ($el['subst']['relFileName'] ?? false) {
735  ‪$list[$lKey]['file_ID'] = md5(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
736  }
737  }
738  }
739  }
740  }
741  }
742  }
743  }
744  return ‪$list;
745  }
746 
758  protected function ‪exportAddRecordsFromRelations(int $relationLevel = 0): int
759  {
760  if (!isset($this->dat['records'])) {
761  $this->‪addError('There were no records available.');
762  return 0;
763  }
764 
765  $addRecords = [];
766 
767  foreach ($this->dat['records'] as ‪$record) {
768  if (!is_array(‪$record)) {
769  continue;
770  }
771  foreach (‪$record['rels'] as $relation) {
772  if (isset($relation['type'])) {
773  if ($relation['type'] === 'db') {
774  foreach ($relation['itemArray'] as $dbRelationData) {
775  $this->‪exportAddRecordsFromRelationsPushRelation($dbRelationData, $addRecords);
776  }
777  }
778  if ($relation['type'] === 'flex') {
779  // Database relations in flex form fields:
780  if (is_array($relation['flexFormRels']['db'] ?? null)) {
781  foreach ($relation['flexFormRels']['db'] as $subList) {
782  foreach ($subList as $dbRelationData) {
783  $this->‪exportAddRecordsFromRelationsPushRelation($dbRelationData, $addRecords);
784  }
785  }
786  }
787 
788  // Database oriented soft references in flex form fields:
789  if (is_array($relation['flexFormRels']['softrefs'] ?? null)) {
790  foreach ($relation['flexFormRels']['softrefs'] as $subList) {
791  foreach ($subList['keys'] as $elements) {
792  foreach ($elements as $el) {
793  if ($el['subst']['type'] === 'db' && $this->‪isSoftRefIncluded($el['subst']['tokenID'])) {
794  [$referencedTable, $referencedUid] = explode(':', $el['subst']['recordRef']);
795  $dbRelationData = [
796  'table' => $referencedTable,
797  'id' => $referencedUid,
798  ];
799  $this->‪exportAddRecordsFromRelationsPushRelation($dbRelationData, $addRecords, $el['subst']['tokenID']);
800  }
801  }
802  }
803  }
804  }
805  }
806  }
807  // In any case, if there are soft refs:
808  if (is_array($relation['softrefs']['keys'] ?? null)) {
809  foreach ($relation['softrefs']['keys'] as $elements) {
810  foreach ($elements as $el) {
811  if (($el['subst']['type'] ?? '') === 'db' && $this->‪isSoftRefIncluded($el['subst']['tokenID'])) {
812  [$referencedTable, $referencedUid] = explode(':', $el['subst']['recordRef']);
813  $dbRelationData = [
814  'table' => $referencedTable,
815  'id' => $referencedUid,
816  ];
817  $this->‪exportAddRecordsFromRelationsPushRelation($dbRelationData, $addRecords, $el['subst']['tokenID']);
818  }
819  }
820  }
821  }
822  }
823  }
824 
825  if (!empty($addRecords)) {
826  foreach ($addRecords as $recordData) {
827  ‪$record = BackendUtility::getRecord($recordData['table'], $recordData['id']);
828 
829  if (is_array(‪$record)) {
830  // Depending on db driver, int fields may or may not be returned as integer or as string. The
831  // loop aligns that detail and forces strings for everything to have exports more db agnostic.
832  foreach (‪$record as $fieldName => $fieldValue) {
833  ‪$record[$fieldName] = $fieldValue === null ? $fieldValue : (string)$fieldValue;
834  }
835  $this->‪exportAddRecord($recordData['table'], ‪$record, $relationLevel + 1);
836  }
837  // Set status message
838  // Relation pointers always larger than zero except certain "select" types with
839  // negative values pointing to uids - but that is not supported here.
840  if ($recordData['id'] > 0) {
841  $recordRef = $recordData['table'] . ':' . $recordData['id'];
842  if (!isset($this->dat['records'][$recordRef])) {
843  $this->dat['records'][$recordRef] = 'NOT_FOUND';
844  $this->‪addError('Relation record ' . $recordRef . ' was not found!');
845  }
846  }
847  }
848  }
849 
850  return count($addRecords);
851  }
852 
861  protected function ‪exportAddRecordsFromRelationsPushRelation(array $recordData, array &$addRecords, string $tokenID = ''): void
862  {
863  // @todo: Remove by-reference and return final array
864  $recordRef = $recordData['table'] . ':' . $recordData['id'];
865  if (
866  isset(‪$GLOBALS['TCA'][$recordData['table']]) && !$this->‪isTableStatic($recordData['table'])
867  && !$this->‪isRecordExcluded($recordData['table'], (int)$recordData['id'])
868  && (!$tokenID || $this->‪isSoftRefIncluded($tokenID)) && $this->‪inclRelation($recordData['table'])
869  && !isset($this->dat['records'][$recordRef])
870  ) {
871  $addRecords[$recordRef] = $recordData;
872  }
873  }
874 
881  protected function ‪inclRelation(string $table): bool
882  {
883  return is_array(‪$GLOBALS['TCA'][$table] ?? null)
884  && (in_array($table, $this->relOnlyTables, true) || in_array('_ALL', $this->relOnlyTables, true))
885  && $this->‪getBackendUser()->check('tables_select', $table);
886  }
887 
894  protected function ‪exportAddFilesFromRelations(): void
895  {
896  // @todo: Consider NOT using by-reference but writing final $this->dat at end of method.
897  if (!isset($this->dat['records'])) {
898  $this->‪addError('There were no records available.');
899  return;
900  }
901 
902  foreach ($this->dat['records'] as $recordRef => &‪$record) {
903  if (!is_array(‪$record)) {
904  continue;
905  }
906  foreach (‪$record['rels'] as $field => &$relation) {
907  // For all file type relations:
908  if (isset($relation['type']) && $relation['type'] === 'file') {
909  foreach ($relation['newValueFiles'] as &$fileRelationData) {
910  $this->‪exportAddFile($fileRelationData, $recordRef, $field);
911  // Remove the absolute reference to the file so it doesn't expose absolute paths from source server:
912  unset($fileRelationData['ID_absFile']);
913  }
914  unset($fileRelationData);
915  }
916  // For all flex type relations:
917  if (isset($relation['type']) && $relation['type'] === 'flex') {
918  if (isset($relation['flexFormRels']['file'])) {
919  foreach ($relation['flexFormRels']['file'] as &$subList) {
920  foreach ($subList as $subKey => &$fileRelationData) {
921  $this->‪exportAddFile($fileRelationData, $recordRef, $field);
922  // Remove the absolute reference to the file so it doesn't expose absolute paths from source server:
923  unset($fileRelationData['ID_absFile']);
924  }
925  }
926  unset($subList, $fileRelationData);
927  }
928  // Database oriented soft references in flex form fields:
929  if (isset($relation['flexFormRels']['softrefs'])) {
930  foreach ($relation['flexFormRels']['softrefs'] as &$subList) {
931  foreach ($subList['keys'] as &$elements) {
932  foreach ($elements as &$el) {
933  if ($el['subst']['type'] === 'file' && $this->‪isSoftRefIncluded($el['subst']['tokenID'])) {
934  // Create abs path and ID for file:
935  $ID_absFile = GeneralUtility::getFileAbsFileName(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
936  $ID = md5($el['subst']['relFileName']);
937  if ($ID_absFile) {
938  if (!$this->dat['files'][$ID]) {
939  $fileRelationData = [
940  'filename' => ‪PathUtility::basename($ID_absFile),
941  'ID_absFile' => $ID_absFile,
942  'ID' => $ID,
943  'relFileName' => $el['subst']['relFileName'],
944  ];
945  $this->‪exportAddFile($fileRelationData, '_SOFTREF_');
946  }
947  $el['file_ID'] = $ID;
948  }
949  }
950  }
951  }
952  }
953  unset($subList, $elements, $el);
954  }
955  }
956  // In any case, if there are soft refs:
957  if (is_array($relation['softrefs']['keys'] ?? null)) {
958  foreach ($relation['softrefs']['keys'] as &$elements) {
959  foreach ($elements as &$el) {
960  if (($el['subst']['type'] ?? '') === 'file' && $this->‪isSoftRefIncluded($el['subst']['tokenID'])) {
961  // Create abs path and ID for file:
962  $ID_absFile = GeneralUtility::getFileAbsFileName(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
963  $ID = md5($el['subst']['relFileName']);
964  if ($ID_absFile) {
965  if (!$this->dat['files'][$ID]) {
966  $fileRelationData = [
967  'filename' => ‪PathUtility::basename($ID_absFile),
968  'ID_absFile' => $ID_absFile,
969  'ID' => $ID,
970  'relFileName' => $el['subst']['relFileName'],
971  ];
972  $this->‪exportAddFile($fileRelationData, '_SOFTREF_');
973  }
974  $el['file_ID'] = $ID;
975  }
976  }
977  }
978  }
979  }
980  }
981  }
982  }
983 
992  protected function ‪exportAddFile(array $fileData, string $recordRef = '', string $field = ''): void
993  {
994  if (!@is_file($fileData['ID_absFile'])) {
995  $this->‪addError($fileData['ID_absFile'] . ' was not a file! Skipping.');
996  return;
997  }
998 
999  $fileStat = stat($fileData['ID_absFile']);
1000  $fileMd5 = md5_file($fileData['ID_absFile']);
1001  $pathInfo = pathinfo(‪PathUtility::basename($fileData['ID_absFile']));
1002 
1003  $fileInfo = [];
1004  $fileInfo['filename'] = ‪PathUtility::basename($fileData['ID_absFile']);
1005  $fileInfo['filemtime'] = $fileStat['mtime'];
1006  $fileInfo['relFileRef'] = ‪PathUtility::stripPathSitePrefix($fileData['ID_absFile']);
1007  if ($recordRef) {
1008  $fileInfo['record_ref'] = $recordRef . '/' . $field;
1009  }
1010  if ($fileData['relFileName']) {
1011  $fileInfo['relFileName'] = $fileData['relFileName'];
1012  }
1013 
1014  // Setting this data in the header
1015  $this->dat['header']['files'][$fileData['ID']] = $fileInfo;
1016 
1017  if (!$this->saveFilesOutsideExportFile) {
1018  $fileInfo['content'] = (string)file_get_contents($fileData['ID_absFile']);
1019  } else {
1020  GeneralUtility::upload_copy_move(
1021  $fileData['ID_absFile'],
1022  $this->‪getOrCreateTemporaryFolderName() . '/' . $fileMd5
1023  );
1024  }
1025  $fileInfo['content_md5'] = $fileMd5;
1026  $this->dat['files'][$fileData['ID']] = $fileInfo;
1027 
1028  // ... and for the recordlisting, why not let us know WHICH relations there was...
1029  if ($recordRef !== '' && $recordRef !== '_SOFTREF_') {
1030  [$referencedTable, $referencedUid] = explode(':', $recordRef, 2);
1031  if (!is_array($this->dat['header']['records'][$referencedTable][$referencedUid]['filerefs'] ?? null)) {
1032  $this->dat['header']['records'][$referencedTable][$referencedUid]['filerefs'] = [];
1033  }
1034  $this->dat['header']['records'][$referencedTable][$referencedUid]['filerefs'][] = $fileData['ID'];
1035  }
1036 
1037  // For soft references, do further processing:
1038  if ($recordRef === '_SOFTREF_') {
1039  // Files with external media?
1040  // This is only done with files grabbed by a soft reference parser since it is deemed improbable
1041  // that hard-referenced files should undergo this treatment.
1042  if ($this->includeExtFileResources
1043  && ‪GeneralUtility::inList($this->extFileResourceExtensions, strtolower($pathInfo['extension']))
1044  ) {
1045  $uniqueDelimiter = '###' . md5(‪$GLOBALS['EXEC_TIME']) . '###';
1046  if (strtolower($pathInfo['extension']) === 'css') {
1047  $fileContentParts = explode(
1048  $uniqueDelimiter,
1049  (string)preg_replace(
1050  '/(url[[:space:]]*\\([[:space:]]*["\']?)([^"\')]*)(["\']?[[:space:]]*\\))/i',
1051  '\\1' . $uniqueDelimiter . '\\2' . $uniqueDelimiter . '\\3',
1052  $fileInfo['content']
1053  )
1054  );
1055  } else {
1056  // html, htm:
1057  $htmlParser = GeneralUtility::makeInstance(HtmlParser::class);
1058  $fileContentParts = explode(
1059  $uniqueDelimiter,
1060  $htmlParser->prefixResourcePath(
1061  $uniqueDelimiter,
1062  $fileInfo['content'],
1063  [],
1064  $uniqueDelimiter
1065  )
1066  );
1067  }
1068  $resourceCaptured = false;
1069  // @todo: drop this by-reference handling
1070  foreach ($fileContentParts as $index => &$fileContentPart) {
1071  if ($index % 2) {
1072  $resRelativePath = &$fileContentPart;
1073  $resAbsolutePath = GeneralUtility::resolveBackPath(‪PathUtility::dirname($fileData['ID_absFile']) . '/' . $resRelativePath);
1074  $resAbsolutePath = GeneralUtility::getFileAbsFileName($resAbsolutePath);
1075  if ($resAbsolutePath !== ''
1076  && str_starts_with($resAbsolutePath, ‪Environment::getPublicPath() . '/' . $this->‪getFileadminFolderName() . '/')
1077  && @is_file($resAbsolutePath)
1078  ) {
1079  $resourceCaptured = true;
1080  $resourceId = md5($resAbsolutePath);
1081  $this->dat['header']['files'][$fileData['ID']]['EXT_RES_ID'][] = $resourceId;
1082  $fileContentParts[$index] = '{EXT_RES_ID:' . $resourceId . '}';
1083  // Add file to memory if it is not set already:
1084  if (!isset($this->dat['header']['files'][$resourceId])) {
1085  $fileStat = stat($resAbsolutePath);
1086  $fileInfo = [];
1087  $fileInfo['filename'] = ‪PathUtility::basename($resAbsolutePath);
1088  $fileInfo['filemtime'] = $fileStat['mtime'];
1089  $fileInfo['record_ref'] = '_EXT_PARENT_:' . $fileData['ID'];
1090  $fileInfo['parentRelFileName'] = $resRelativePath;
1091  // Setting this data in the header
1092  $this->dat['header']['files'][$resourceId] = $fileInfo;
1093  $fileInfo['content'] = (string)file_get_contents($resAbsolutePath);
1094  $fileInfo['content_md5'] = md5($fileInfo['content']);
1095  $this->dat['files'][$resourceId] = $fileInfo;
1096  }
1097  }
1098  }
1099  }
1100  if ($resourceCaptured) {
1101  $this->dat['files'][$fileData['ID']]['tokenizedContent'] = implode('', $fileContentParts);
1102  }
1103  }
1104  }
1105  }
1106 
1110  protected function ‪exportAddFilesFromSysFilesRecords(): void
1111  {
1112  if (!isset($this->dat['header']['records']['sys_file']) || !is_array($this->dat['header']['records']['sys_file'] ?? null)) {
1113  return;
1114  }
1115  foreach ($this->dat['header']['records']['sys_file'] as $sysFileUid => $_) {
1116  $fileData = $this->dat['records']['sys_file:' . $sysFileUid]['data'];
1117  $this->‪exportAddSysFile($fileData);
1118  }
1119  }
1120 
1127  protected function ‪exportAddSysFile(array $fileData): void
1128  {
1129  try {
1130  $file = GeneralUtility::makeInstance(ResourceFactory::class)->createFileObject($fileData);
1131  $file->checkActionPermission('read');
1132  } catch (\Exception $e) {
1133  $this->‪addError('Error when trying to add file ' . $fileData['title'] . ': ' . $e->getMessage());
1134  return;
1135  }
1136 
1137  $fileUid = $file->getUid();
1138  $fileSha1 = $file->getStorage()->hashFile($file, 'sha1');
1139  if ($fileSha1 !== $file->getProperty('sha1')) {
1140  $this->dat['records']['sys_file:' . $fileUid]['data']['sha1'] = $fileSha1;
1141  $this->‪addError(
1142  'The SHA-1 file hash of ' . $file->getCombinedIdentifier() . ' is not up-to-date in the index! ' .
1143  'The file was added based on the current file hash.'
1144  );
1145  }
1146  // Build unique id based on the storage and the file identifier
1147  $fileId = md5($file->getStorage()->getUid() . ':' . $file->getProperty('identifier_hash'));
1148 
1149  $fileInfo = [];
1150  $fileInfo['filename'] = $file->getProperty('name');
1151  $fileInfo['filemtime'] = $file->getProperty('modification_date');
1152 
1153  // Setting this data in the header
1154  $this->dat['header']['files_fal'][$fileId] = $fileInfo;
1155 
1156  if (!$this->saveFilesOutsideExportFile) {
1157  $fileInfo['content'] = $file->getContents();
1158  } else {
1159  GeneralUtility::upload_copy_move(
1160  $file->getForLocalProcessing(false),
1161  $this->getOrCreateTemporaryFolderName() . '/' . $fileSha1
1162  );
1163  }
1164  $fileInfo['content_sha1'] = $fileSha1;
1165  $this->dat['files_fal'][$fileId] = $fileInfo;
1166  }
1167 
1168  /**************************
1169  * File Output
1170  *************************/
1171 
1179  public function ‪render(): string
1180  {
1181  if ($this->exportFileType === self::FILETYPE_XML) {
1182  $out = $this->‪createXML();
1183  } else {
1184  $out = '';
1185  // adding header:
1186  $out .= $this->‪addFilePart(serialize($this->dat['header']));
1187  // adding records:
1188  $out .= $this->‪addFilePart(serialize($this->dat['records']));
1189  // adding files:
1190  $out .= $this->‪addFilePart(serialize($this->dat['files'] ?? null));
1191  // adding files_fal:
1192  $out .= $this->‪addFilePart(serialize($this->dat['files_fal'] ?? null));
1193  }
1194  return $out;
1195  }
1196 
1202  protected function ‪createXML(): string
1203  {
1204  // Options:
1205  $options = [
1206  'alt_options' => [
1207  '/header' => [
1208  'disableTypeAttrib' => true,
1209  'clearStackPath' => true,
1210  'parentTagMap' => [
1211  'files' => 'file',
1212  'files_fal' => 'file',
1213  'records' => 'table',
1214  'table' => 'rec',
1215  'rec:rels' => 'relations',
1216  'relations' => 'element',
1217  'filerefs' => 'file',
1218  'pid_lookup' => 'page_contents',
1219  'header:relStaticTables' => 'static_tables',
1220  'static_tables' => 'tablename',
1221  'excludeMap' => 'item',
1222  'softrefCfg' => 'softrefExportMode',
1223  'extensionDependencies' => 'extkey',
1224  'softrefs' => 'softref_element',
1225  ],
1226  'alt_options' => [
1227  '/pagetree' => [
1228  'disableTypeAttrib' => true,
1229  'useIndexTagForNum' => 'node',
1230  'parentTagMap' => [
1231  'node:subrow' => 'node',
1232  ],
1233  ],
1234  '/pid_lookup/page_contents' => [
1235  'disableTypeAttrib' => true,
1236  'parentTagMap' => [
1237  'page_contents' => 'table',
1238  ],
1239  'grandParentTagMap' => [
1240  'page_contents/table' => 'item',
1241  ],
1242  ],
1243  ],
1244  ],
1245  '/records' => [
1246  'disableTypeAttrib' => true,
1247  'parentTagMap' => [
1248  'records' => 'tablerow',
1249  'tablerow:data' => 'fieldlist',
1250  'tablerow:rels' => 'related',
1251  'related' => 'field',
1252  'field:itemArray' => 'relations',
1253  'field:newValueFiles' => 'filerefs',
1254  'field:flexFormRels' => 'flexform',
1255  'relations' => 'element',
1256  'filerefs' => 'file',
1257  'flexform:db' => 'db_relations',
1258  'flexform:softrefs' => 'softref_relations',
1259  'softref_relations' => 'structurePath',
1260  'db_relations' => 'path',
1261  'path' => 'element',
1262  'keys' => 'softref_key',
1263  'softref_key' => 'softref_element',
1264  ],
1265  'alt_options' => [
1266  '/records/tablerow/fieldlist' => [
1267  'useIndexTagForAssoc' => 'field',
1268  ],
1269  ],
1270  ],
1271  '/files' => [
1272  'disableTypeAttrib' => true,
1273  'parentTagMap' => [
1274  'files' => 'file',
1275  ],
1276  ],
1277  '/files_fal' => [
1278  'disableTypeAttrib' => true,
1279  'parentTagMap' => [
1280  'files_fal' => 'file',
1281  ],
1282  ],
1283  ],
1284  ];
1285  // Creating XML file from $outputArray:
1286  $charset = $this->dat['header']['charset'] ?: 'utf-8';
1287  $XML = '<?xml version="1.0" encoding="' . $charset . '" standalone="yes" ?>' . LF;
1288  $XML .= (new ‪Typo3XmlSerializer())->encodeWithReturningExceptionAsString(
1289  $this->dat,
1291  $options
1292  );
1293  return $XML;
1294  }
1295 
1302  protected function ‪addFilePart(string $data): string
1303  {
1304  $compress = $this->exportFileType === ‪self::FILETYPE_T3DZ;
1305  if ($compress) {
1306  $data = (string)gzcompress($data);
1307  }
1308  return md5($data) . ':' . ($compress ? '1' : '0') . ':' . str_pad((string)strlen($data), 10, '0', STR_PAD_LEFT) . ':' . $data . ':';
1309  }
1310 
1314  public function ‪saveToFile(): File
1315  {
1316  $saveFolder = $this->‪getOrCreateDefaultImportExportFolder();
1318  $filesFolderName = $fileName . '.files';
1319  $fileContent = $this->‪render();
1320 
1321  if (!($saveFolder instanceof Folder && $saveFolder->checkActionPermission('write'))) {
1322  throw new InsufficientFolderWritePermissionsException(
1323  'You are not allowed to write to the target folder "' . $saveFolder->getPublicUrl() . '"',
1324  1602432207
1325  );
1326  }
1327 
1328  if ($saveFolder->hasFolder($filesFolderName)) {
1329  $saveFolder->getSubfolder($filesFolderName)->delete(true);
1330  }
1331 
1332  $temporaryFileName = GeneralUtility::tempnam('export');
1333  ‪GeneralUtility::writeFile($temporaryFileName, $fileContent);
1334  $file = $saveFolder->addFile($temporaryFileName, $fileName, 'replace');
1335 
1336  if ($this->saveFilesOutsideExportFile) {
1337  $filesFolder = $saveFolder->createFolder($filesFolderName);
1338  $temporaryFilesForExport = GeneralUtility::getFilesInDir($this->‪getOrCreateTemporaryFolderName(), '', true);
1339  foreach ($temporaryFilesForExport as $temporaryFileForExport) {
1340  $filesFolder->addFile($temporaryFileForExport);
1341  }
1343  }
1344 
1345  return $file;
1346  }
1347 
1348  public function ‪getExportFileName(): string
1349  {
1350  return ‪$this->exportFileName;
1351  }
1352 
1353  public function ‪setExportFileName(string ‪$exportFileName): void
1354  {
1355  ‪$exportFileName = trim((string)preg_replace('/[^[:alnum:]._-]*/', '', ‪$exportFileName));
1356  $this->exportFileName = ‪$exportFileName;
1357  }
1358 
1359  public function ‪getOrGenerateExportFileNameWithFileExtension(): string
1360  {
1361  if (!empty($this->exportFileName)) {
1363  } else {
1365  }
1367 
1368  return ‪$exportFileName;
1369  }
1371  protected function ‪generateExportFileName(): string
1372  {
1373  if ($this->pid !== -1) {
1374  ‪$exportFileName = 'tree_PID' . $this->pid . '_L' . ‪$this->levels;
1375  } elseif (!empty($this->‪getRecord())) {
1376  ‪$exportFileName = 'recs_' . implode('-', $this->‪getRecord());
1377  ‪$exportFileName = str_replace(':', '_', ‪$exportFileName);
1378  } elseif (!empty($this->‪getList())) {
1379  ‪$exportFileName = 'list_' . implode('-', $this->‪getList());
1380  ‪$exportFileName = str_replace(':', '_', ‪$exportFileName);
1381  } else {
1382  ‪$exportFileName = 'export';
1383  }
1384 
1385  ‪$exportFileName = substr(trim((string)preg_replace('/[^[:alnum:]_-]/', '-', ‪$exportFileName)), 0, 20);
1386 
1387  return 'T3D_' . ‪$exportFileName . '_' . date('Y-m-d_H-i');
1388  }
1389 
1390  public function ‪getExportFileType(): string
1391  {
1392  return ‪$this->exportFileType;
1393  }
1394 
1395  public function ‪setExportFileType(string ‪$exportFileType): void
1396  {
1398  if (!in_array(‪$exportFileType, ‪$supportedFileTypes, true)) {
1399  throw new \InvalidArgumentException(
1400  sprintf(
1401  'File type "%s" is not valid. Supported file types are %s.',
1403  implode(', ', array_map(static function ($fileType) {
1404  return '"' . $fileType . '"';
1406  ),
1407  1602505264
1408  );
1409  }
1410  $this->exportFileType = ‪$exportFileType;
1411  }
1412 
1413  public function ‪getSupportedFileTypes(): array
1414  {
1415  if (empty($this->supportedFileTypes)) {
1419  if ($this->compressionAvailable) {
1421  }
1422  $this->supportedFileTypes = ‪$supportedFileTypes;
1423  }
1425  }
1426 
1427  protected function ‪getFileExtensionByFileType(): string
1428  {
1429  switch ($this->exportFileType) {
1431  return '.xml';
1432  case ‪self::FILETYPE_T3D:
1433  return '.t3d';
1435  default:
1436  return '-z.t3d';
1437  }
1438  }
1439 
1440  public function ‪getTitle(): string
1441  {
1442  return ‪$this->title;
1443  }
1444 
1445  public function ‪setTitle(string ‪$title): void
1446  {
1447  $this->title = ‪$title;
1448  }
1449 
1450  public function ‪getDescription(): string
1451  {
1452  return ‪$this->description;
1453  }
1454 
1455  public function ‪setDescription(string ‪$description): void
1456  {
1458  }
1459 
1460  public function ‪getNotes(): string
1461  {
1462  return ‪$this->notes;
1463  }
1464 
1465  public function ‪setNotes(string ‪$notes): void
1466  {
1467  $this->notes = ‪$notes;
1468  }
1469 
1470  public function ‪getRecord(): array
1471  {
1472  return ‪$this->record;
1473  }
1474 
1475  public function ‪setRecord(array ‪$record): void
1476  {
1477  $this->record = ‪$record;
1478  }
1479 
1480  public function ‪getList(): array
1481  {
1482  return ‪$this->list;
1483  }
1484 
1485  public function ‪setList(array ‪$list): void
1486  {
1487  $this->list = ‪$list;
1488  }
1489 
1490  public function ‪getLevels(): int
1491  {
1492  return ‪$this->levels;
1493  }
1494 
1495  public function ‪setLevels(int ‪$levels): void
1496  {
1497  $this->levels = ‪$levels;
1498  }
1499 
1500  public function ‪getTables(): array
1501  {
1502  return ‪$this->tables;
1503  }
1504 
1505  public function ‪setTables(array ‪$tables): void
1506  {
1507  $this->tables = ‪$tables;
1508  }
1509 
1510  public function ‪getRelOnlyTables(): array
1511  {
1512  return ‪$this->relOnlyTables;
1513  }
1514 
1515  public function ‪setRelOnlyTables(array ‪$relOnlyTables): void
1516  {
1517  $this->relOnlyTables = ‪$relOnlyTables;
1518  }
1519 
1520  public function ‪getTreeHTML(): string
1521  {
1522  return ‪$this->treeHTML;
1523  }
1524 
1525  public function ‪isIncludeExtFileResources(): bool
1526  {
1528  }
1529 
1531  {
1532  $this->includeExtFileResources = ‪$includeExtFileResources;
1533  }
1534 
1542  {
1543  $this->saveFilesOutsideExportFile = ‪$saveFilesOutsideExportFile;
1544  }
1545 
1546  public function ‪isSaveFilesOutsideExportFile(): bool
1547  {
1549  }
1550 }
‪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:738
‪TYPO3\CMS\Impexp\Export\$mode
‪string $mode
Definition: Export.php:62
‪TYPO3\CMS\Impexp\Export\getDescription
‪getDescription()
Definition: Export.php:1430
‪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:1159
‪TYPO3\CMS\Impexp\Export\execListQueryPid
‪Result execListQueryPid(int $pid, string $table)
Definition: Export.php:437
‪TYPO3\CMS\Impexp\ImportExport\$extensionDependencies
‪array $extensionDependencies
Definition: ImportExport.php:148
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static stripPathSitePrefix(string $path)
Definition: PathUtility.php:428
‪TYPO3\CMS\Impexp\Export\getRecord
‪getRecord()
Definition: Export.php:1450
‪TYPO3\CMS\Impexp\ImportExport\getFileadminFolderName
‪getFileadminFolderName()
Definition: ImportExport.php:1107
‪TYPO3\CMS\Impexp\Export\setList
‪setList(array $list)
Definition: Export.php:1465
‪TYPO3\CMS\Impexp\Export\$treeHTML
‪string $treeHTML
Definition: Export.php:101
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:27
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:46
‪TYPO3\CMS\Impexp\Export\$supportedFileTypes
‪array $supportedFileTypes
Definition: Export.php:144
‪TYPO3\CMS\Impexp\Export\filterRecordFields
‪array filterRecordFields(string $table, array $row)
Definition: Export.php:552
‪TYPO3\CMS\Core\Utility\GeneralUtility\fixed_lgd_cs
‪static string fixed_lgd_cs(string $string, int $chars, string $appendString='...')
Definition: GeneralUtility.php:93
‪TYPO3\CMS\Impexp\Export\setExportFileType
‪setExportFileType(string $exportFileType)
Definition: Export.php:1375
‪TYPO3\CMS\Impexp\ImportExport\addError
‪addError(string $message)
Definition: ImportExport.php:1432
‪TYPO3\CMS\Impexp\Export\setRecordTypeIncludeFields
‪setRecordTypeIncludeFields(string $table, array $fields)
Definition: Export.php:379
‪TYPO3\CMS\Impexp\Export\isPageInWebMount
‪bool isPageInWebMount(int $pid)
Definition: Export.php:535
‪TYPO3\CMS\Impexp\Export\setNotes
‪setNotes(string $notes)
Definition: Export.php:1445
‪TYPO3\CMS\Impexp\Export\FILETYPE_XML
‪const FILETYPE_XML
Definition: Export.php:56
‪TYPO3\CMS\Impexp\Export\$exportFileType
‪string $exportFileType
Definition: Export.php:140
‪TYPO3\CMS\Core\Serializer\Typo3XmlSerializer
Definition: Typo3XmlSerializer.php:123
‪TYPO3\CMS\Core\Html\HtmlParser
Definition: HtmlParser.php:26
‪TYPO3\CMS\Impexp\Export\getFileExtensionByFileType
‪getFileExtensionByFileType()
Definition: Export.php:1407
‪TYPO3\CMS\Impexp\Export\setRelOnlyTables
‪setRelOnlyTables(array $relOnlyTables)
Definition: Export.php:1495
‪TYPO3\CMS\Impexp\Export\$recordTypesIncludeFields
‪array $recordTypesIncludeFields
Definition: Export.php:122
‪TYPO3\CMS\Impexp\Export\inclRelation
‪bool inclRelation(string $table)
Definition: Export.php:861
‪TYPO3\CMS\Core\Information\Typo3Version
Definition: Typo3Version.php:21
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:22
‪TYPO3\CMS\Impexp\Export\process
‪process()
Definition: Export.php:172
‪TYPO3\CMS\Impexp\Export\getRelOnlyTables
‪getRelOnlyTables()
Definition: Export.php:1490
‪TYPO3\CMS\Impexp\Export\$title
‪string $title
Definition: Export.php:66
‪TYPO3\CMS\Impexp\Export\getExcludePagesClause
‪string getExcludePagesClause()
Definition: Export.php:390
‪TYPO3\CMS\Impexp\Export\__construct
‪__construct()
Definition: Export.php:159
‪TYPO3\CMS\Impexp\Export\exportAddFilesFromRelations
‪exportAddFilesFromRelations()
Definition: Export.php:874
‪TYPO3\CMS\Core\Database\ReferenceIndex
Definition: ReferenceIndex.php:45
‪TYPO3\CMS\Impexp\Export\$compressionAvailable
‪bool $compressionAvailable
Definition: Export.php:148
‪TYPO3\CMS\Impexp\ImportExport\$pid
‪int $pid
Definition: ImportExport.php:63
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static getPublicPath()
Definition: Environment.php:187
‪TYPO3\CMS\Impexp\View\ExportPageTreeView
Definition: ExportPageTreeView.php:34
‪TYPO3\CMS\Impexp\ImportExport\isTableStatic
‪bool isTableStatic(string $table)
Definition: ImportExport.php:1243
‪TYPO3\CMS\Impexp\Export\$extFileResourceExtensions
‪string $extFileResourceExtensions
Definition: Export.php:113
‪TYPO3\CMS\Core\Exception
‪TYPO3\CMS\Impexp\Export\exportAddFile
‪exportAddFile(array $fileData, string $recordRef='', string $field='')
Definition: Export.php:972
‪TYPO3\CMS\Impexp\Export\$list
‪array $list
Definition: Export.php:82
‪TYPO3\CMS\Impexp\Export\setHeaderBasics
‪setHeaderBasics()
Definition: Export.php:273
‪TYPO3\CMS\Impexp\Export\$exportFileName
‪string $exportFileName
Definition: Export.php:136
‪TYPO3\CMS\Impexp\Export\getExportFileName
‪getExportFileName()
Definition: Export.php:1328
‪TYPO3\CMS\Core\Localization\Locales
Definition: Locales.php:33
‪TYPO3\CMS\Impexp\Export\$saveFilesOutsideExportFile
‪bool $saveFilesOutsideExportFile
Definition: Export.php:132
‪TYPO3\CMS\Impexp\Export\saveToFile
‪saveToFile()
Definition: Export.php:1294
‪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:97
‪TYPO3\CMS\Core\Utility\PathUtility\basename
‪static basename(string $path)
Definition: PathUtility.php:219
‪TYPO3\CMS\Impexp\Export\LEVELS_INFINITE
‪const LEVELS_INFINITE
Definition: Export.php:54
‪TYPO3\CMS\Impexp\ImportExport\$softrefCfg
‪array $softrefCfg
Definition: ImportExport.php:142
‪TYPO3\CMS\Impexp\ImportExport\isRecordDisabled
‪bool isRecordDisabled(string $table, int $uid)
Definition: ImportExport.php:369
‪TYPO3\CMS\Impexp\Export\exportAddSysFile
‪exportAddSysFile(array $fileData)
Definition: Export.php:1107
‪TYPO3\CMS\Impexp\Export\exportAddFilesFromSysFilesRecords
‪exportAddFilesFromSysFilesRecords()
Definition: Export.php:1090
‪TYPO3\CMS\Core\Localization\DateFormatter
Definition: DateFormatter.php:27
‪TYPO3\CMS\Impexp\Export\generateExportFileName
‪generateExportFileName()
Definition: Export.php:1351
‪TYPO3\CMS\Impexp\Export\$pageInWebMountCache
‪array $pageInWebMountCache
Definition: Export.php:154
‪TYPO3\CMS\Impexp\Export\getOrGenerateExportFileNameWithFileExtension
‪getOrGenerateExportFileNameWithFileExtension()
Definition: Export.php:1339
‪TYPO3\CMS\Impexp\Export\removeRedundantSoftRefsInRelations
‪removeRedundantSoftRefsInRelations(array &$relations)
Definition: Export.php:620
‪TYPO3\CMS\Core\Utility\PathUtility\dirname
‪static dirname(string $path)
Definition: PathUtility.php:243
‪TYPO3\CMS\Impexp\Export\setSaveFilesOutsideExportFile
‪setSaveFilesOutsideExportFile(bool $saveFilesOutsideExportFile)
Definition: Export.php:1521
‪TYPO3\CMS\Impexp\Export\getTitle
‪getTitle()
Definition: Export.php:1420
‪TYPO3\CMS\Impexp\ImportExport\getOrCreateTemporaryFolderName
‪getOrCreateTemporaryFolderName()
Definition: ImportExport.php:1119
‪TYPO3\CMS\Impexp\Export\getTables
‪getTables()
Definition: Export.php:1480
‪TYPO3\CMS\Impexp\Export\initializeExport
‪initializeExport()
Definition: Export.php:262
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Impexp\Export\setTitle
‪setTitle(string $title)
Definition: Export.php:1425
‪TYPO3\CMS\Impexp\Export\setRecordTypesIncludeFields
‪setRecordTypesIncludeFields(array $recordTypesIncludeFields)
Definition: Export.php:362
‪TYPO3\CMS\Impexp\Export\FILETYPE_T3D
‪const FILETYPE_T3D
Definition: Export.php:57
‪TYPO3\CMS\Impexp\Export\$description
‪string $description
Definition: Export.php:70
‪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:74
‪TYPO3\CMS\Impexp\Export\$record
‪array $record
Definition: Export.php:78
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:26
‪TYPO3\CMS\Impexp\Export\flatDbRelations
‪array flatDbRelations(array $relations)
Definition: Export.php:655
‪TYPO3\CMS\Core\Resource\Folder\checkActionPermission
‪bool checkActionPermission($action)
Definition: Folder.php:400
‪TYPO3\CMS\Impexp\Export\getExportFileType
‪getExportFileType()
Definition: Export.php:1370
‪TYPO3\CMS\Impexp\Export\getSupportedFileTypes
‪getSupportedFileTypes()
Definition: Export.php:1393
‪TYPO3\CMS\Impexp\Export\exportAddRecord
‪exportAddRecord(string $table, array $row, int $relationLevel=0)
Definition: Export.php:483
‪TYPO3\CMS\Impexp\Export\addRecordsForPid
‪addRecordsForPid(int $pid, array $tables)
Definition: Export.php:412
‪TYPO3\CMS\Impexp\Export\$levels
‪int $levels
Definition: Export.php:86
‪TYPO3\CMS\Impexp\ImportExport\getOrCreateDefaultImportExportFolder
‪getOrCreateDefaultImportExportFolder()
Definition: ImportExport.php:1154
‪TYPO3\CMS\Impexp\Export\$includeExtFileResources
‪bool $includeExtFileResources
Definition: Export.php:107
‪TYPO3\CMS\Impexp\Export\getLevels
‪getLevels()
Definition: Export.php:1470
‪TYPO3\CMS\Impexp\Export\setLevels
‪setLevels(int $levels)
Definition: Export.php:1475
‪TYPO3\CMS\Impexp\Export\setPageTree
‪setPageTree(array $pageTree)
Definition: Export.php:329
‪TYPO3\CMS\Impexp\ImportExport
Definition: ImportExport.php:46
‪TYPO3\CMS\Impexp\Export\LEVELS_EXPANDED_TREE
‪const LEVELS_EXPANDED_TREE
Definition: Export.php:53
‪TYPO3\CMS\Impexp\Export\createXML
‪string createXML()
Definition: Export.php:1182
‪TYPO3\CMS\Impexp\Export\LEVELS_RECORDS_ON_THIS_PAGE
‪const LEVELS_RECORDS_ON_THIS_PAGE
Definition: Export.php:52
‪TYPO3\CMS\Impexp\ImportExport\$relStaticTables
‪array $relStaticTables
Definition: ImportExport.php:130
‪TYPO3\CMS\Impexp\Export\fixFileIdInRelations
‪fixFileIdInRelations(array &$relations)
Definition: Export.php:579
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:35
‪TYPO3\CMS\Core\Serializer\Typo3XmlParserOptions
Definition: Typo3XmlParserOptions.php:24
‪TYPO3\CMS\Impexp\Export\removeExcludedPagesFromPageTree
‪removeExcludedPagesFromPageTree(array &$pageTree)
Definition: Export.php:339
‪TYPO3\CMS\Impexp\ImportExport\flatInversePageTree
‪flatInversePageTree(array $pageTree, array &$list, int $pid=-1)
Definition: ImportExport.php:1225
‪TYPO3\CMS\Impexp\Export\isSaveFilesOutsideExportFile
‪isSaveFilesOutsideExportFile()
Definition: Export.php:1526
‪TYPO3\CMS\Webhooks\Message\$uid
‪identifier readonly int $uid
Definition: PageModificationMessage.php:35
‪TYPO3\CMS\Impexp\ImportExport\isSoftRefIncluded
‪bool isSoftRefIncluded(string $tokenID)
Definition: ImportExport.php:1271
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Impexp\Export\flatSoftRefs
‪array flatSoftRefs(array $relations)
Definition: Export.php:683
‪TYPO3\CMS\Impexp\Export\FILETYPE_T3DZ
‪const FILETYPE_T3DZ
Definition: Export.php:58
‪TYPO3\CMS\Impexp\Export\setDescription
‪setDescription(string $description)
Definition: Export.php:1435
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Impexp\Export\exportAddRecordsFromRelationsPushRelation
‪exportAddRecordsFromRelationsPushRelation(array $recordData, array &$addRecords, string $tokenID='')
Definition: Export.php:841
‪TYPO3\CMS\Impexp\Export\getNotes
‪getNotes()
Definition: Export.php:1440
‪TYPO3\CMS\Impexp\Export
Definition: Export.php:51
‪TYPO3\CMS\Core\Localization\Locale
Definition: Locale.php:30
‪TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException
Definition: InsufficientFolderWritePermissionsException.php:22
‪TYPO3\CMS\Impexp\ImportExport\$excludeMap
‪array $excludeMap
Definition: ImportExport.php:136
‪TYPO3\CMS\Core\Utility\GeneralUtility\inList
‪static bool inList($list, $item)
Definition: GeneralUtility.php:423
‪TYPO3\CMS\Impexp\Export\setTables
‪setTables(array $tables)
Definition: Export.php:1485
‪TYPO3\CMS\Impexp\Export\getList
‪getList()
Definition: Export.php:1460
‪TYPO3\CMS\Impexp\Export\setRecord
‪setRecord(array $record)
Definition: Export.php:1455
‪TYPO3\CMS\Redirects\Message\description
‪identifier description
Definition: RedirectWasHitMessage.php:32
‪TYPO3\CMS\Impexp\Export\addFilePart
‪string addFilePart(string $data)
Definition: Export.php:1282
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:51
‪TYPO3\CMS\Impexp\Export\setIncludeExtFileResources
‪setIncludeExtFileResources(bool $includeExtFileResources)
Definition: Export.php:1510
‪TYPO3\CMS\Impexp\Export\$defaultRecordIncludeFields
‪array $defaultRecordIncludeFields
Definition: Export.php:128
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Impexp\Export\getTreeHTML
‪getTreeHTML()
Definition: Export.php:1500
‪TYPO3\CMS\Impexp\Export\$tables
‪array $tables
Definition: Export.php:90
‪TYPO3\CMS\Impexp\ImportExport\removeTemporaryFolderName
‪removeTemporaryFolderName()
Definition: ImportExport.php:1142
‪TYPO3\CMS\Core\Utility\GeneralUtility\writeFile
‪static bool writeFile($file, $content, $changePermissions=false)
Definition: GeneralUtility.php:1452
‪TYPO3\CMS\Impexp\Export\setMetaData
‪setMetaData()
Definition: Export.php:300
‪TYPO3\CMS\Impexp\ImportExport\isRecordExcluded
‪bool isRecordExcluded(string $table, int $uid)
Definition: ImportExport.php:1260
‪TYPO3\CMS\Impexp
‪TYPO3\CMS\Impexp\ImportExport\getBackendUser
‪getBackendUser()
Definition: ImportExport.php:1442
‪TYPO3\CMS\Impexp\Export\isIncludeExtFileResources
‪isIncludeExtFileResources()
Definition: Export.php:1505
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:39