‪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\ArrayParameterType;
21 use Doctrine\DBAL\Result;
22 use TYPO3\CMS\Backend\Utility\BackendUtility;
45 
52 {
53  public const ‪LEVELS_RECORDS_ON_THIS_PAGE = -2;
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 
60  protected string ‪$mode = 'export';
61  protected string ‪$title = '';
62  protected string ‪$description = '';
63  protected string ‪$notes = '';
64  protected array ‪$record = [];
65  protected array ‪$list = [];
66  protected int ‪$levels = 0;
67  protected array ‪$tables = [];
68 
73  protected array ‪$relOnlyTables = [];
74  protected string ‪$treeHTML = '';
75 
79  protected bool ‪$includeExtFileResources = true;
80 
87  protected array ‪$recordTypesIncludeFields = [];
88 
92  protected array ‪$defaultRecordIncludeFields = ['uid', 'pid'];
93  protected bool ‪$saveFilesOutsideExportFile = false;
94  protected string ‪$exportFileName = '';
96  protected array ‪$supportedFileTypes = [];
97  protected bool ‪$compressionAvailable = false;
98 
102  protected array ‪$pageInWebMountCache = [];
103 
104  public function ‪__construct()
105  {
106  parent::__construct();
107  $this->compressionAvailable = function_exists('gzcompress');
108  }
109 
110  /**************************
111  * Export / Init + Meta Data
112  *************************/
113 
117  public function ‪process(): void
118  {
119  $this->‪initializeExport();
120  $this->‪setHeaderBasics();
121  $this->‪setMetaData();
122 
123  // Configure which records to export
124  foreach ($this->record as $ref) {
125  $rParts = explode(':', $ref);
126  $table = $rParts[0];
127  ‪$record = BackendUtility::getRecord($rParts[0], (int)$rParts[1]);
128  if (is_array(‪$record)) {
129  $this->‪exportAddRecord($table, ‪$record);
130  }
131  }
132 
133  // Configure which tables to export
134  foreach ($this->list as $ref) {
135  $rParts = explode(':', $ref);
136  $table = $rParts[0];
137  ‪$pid = (int)$rParts[1];
138  if ($this->‪getBackendUser()->check('tables_select', $table)) {
139  $statement = $this->‪execListQueryPid(‪$pid, $table);
140  while (‪$record = $statement->fetchAssociative()) {
141  if (is_array(‪$record)) {
142  $this->‪exportAddRecord($table, ‪$record);
143  }
144  }
145  }
146  }
147 
148  // Configure which page tree to export
149  if ($this->pid !== -1) {
150  $pageTree = null;
151  if ($this->levels === self::LEVELS_RECORDS_ON_THIS_PAGE) {
152  $this->‪addRecordsForPid($this->pid, $this->tables);
153  } else {
154  $pageTreeView = GeneralUtility::makeInstance(ExportPageTreeView::class);
155  $initClause = $this->‪getExcludePagesClause();
156  if ($this->excludeDisabledRecords) {
157  $initClause .= BackendUtility::BEenableFields('pages');
158  }
159  $pageTreeView->init($initClause);
160  $pageTreeView->buildTreeByLevels($this->pid, $this->levels);
161  $this->treeHTML = $pageTreeView->printTree();
162  $pageTree = $pageTreeView->buffer_idH;
163  }
164  // In most cases, we should have a multi-level array, $pageTree, with the page tree
165  // structure here (and the HTML code loaded into memory for a nice display...)
166  if (is_array($pageTree)) {
167  $pageList = [];
168  $this->‪removeExcludedPagesFromPageTree($pageTree);
169  $this->‪setPageTree($pageTree);
170  $this->‪flatInversePageTree($pageTree, $pageList);
171  foreach ($pageList as $pageUid => $_) {
172  ‪$record = BackendUtility::getRecord('pages', $pageUid);
173  if (is_array(‪$record)) {
174  $this->‪exportAddRecord('pages', $record);
175  foreach ($this->‪getTranslationForPage((int)$record['uid'], $this->excludeDisabledRecords) as $pageTranslation) {
176  // Export l10n translations
177  // All exported records need to be considered within "insidePageTree", not "outsidePageTree",
178  // because they actually ARE part of the page tree. To achieve this, their UID index is
179  // added into $this->dat['header']['pagetree'].
180  $this->‪exportAddRecord('pages', $pageTranslation);
181  // Be sure to not overwrite existing parts of the pagetree
182  // Integrate the extra record into the internal pagetree array
183  $this->dat['header']['pagetree'][(int)$pageTranslation['uid']]['uid'] = (int)$pageTranslation['uid'];
184  }
185 
186  // Translated pages can also be directly exported; in that case the pageList may
187  // point to the UID of a translated page, and not the root page. Since tt_content
188  // records are bound to the default page UID, those records would be missing.
189  // So we use the page ID of the default language, and then attach all records
190  // for that page ID, which also match the selected page's language.
191  if ((‪$record[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] ?? null] ?? 0) > 0
192  && !empty(‪$GLOBALS['TCA']['pages']['ctrl']['languageField'] ?? '')
193  ) {
194  $this->‪addRecordsForPid(
195  (int)$record[‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField']],
196  $this->tables,
197  [‪$record[‪$GLOBALS['TCA']['pages']['ctrl']['languageField']]]
198  );
199  }
200  }
201  $this->‪addRecordsForPid((int)$pageUid, $this->tables);
202  }
203  }
204  }
205 
206  // After adding ALL records we add records from database relations
207  for ($l = 0; $l < 10; $l++) {
208  if ($this->‪exportAddRecordsFromRelations($l) === 0) {
209  break;
210  }
211  }
212 
213  // Files must be added after the database relations are added,
214  // so that files from ALL added records are included!
217  }
218 
222  protected function ‪getTranslationForPage(
223  int $defaultLanguagePageUid,
224  bool $considerHiddenPages,
225  array $limitToLanguageIds = []
226  ): array {
227  if (empty(‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'] ?? '')
228  || empty(‪$GLOBALS['TCA']['pages']['ctrl']['languageField'] ?? '')
229  ) {
230  return [];
231  }
232  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
233  $queryBuilder->getRestrictions()
234  ->removeAll()
235  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class))
236  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
237  if (!$considerHiddenPages) {
238  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(HiddenRestriction::class));
239  }
240  $constraints = [
241  $queryBuilder->expr()->eq(
242  ‪$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
243  $queryBuilder->createNamedParameter($defaultLanguagePageUid, ‪Connection::PARAM_INT)
244  ),
245  ];
246  if (!empty($limitToLanguageIds)) {
247  $constraints[] = $queryBuilder->expr()->in(
248  ‪$GLOBALS['TCA']['pages']['ctrl']['languageField'],
249  $queryBuilder->createNamedParameter($limitToLanguageIds, ArrayParameterType::INTEGER)
250  );
251  } else {
252  // Ensure consistency by only fetching pages where not only l10n_parent matches, but also a
253  // sys_language_uid > 0 exists.
254  $constraints[] = $queryBuilder->expr()->gt(‪$GLOBALS['TCA']['pages']['ctrl']['languageField'], 0);
255  }
256  return $queryBuilder
257  ->select('*')
258  ->from('pages')
259  ->where(...$constraints)
260  ->orderBy('uid', 'ASC')
261  ->executeQuery()
262  ->fetchAllAssociative();
263  }
264 
268  protected function ‪initializeExport(): void
269  {
270  $this->dat = [
271  'header' => [],
272  'records' => [],
273  ];
274  }
275 
279  protected function ‪setHeaderBasics(): void
280  {
281  // Initializing:
282  foreach ($this->softrefCfg as $key => $value) {
283  if (!($value['mode'] ?? false)) {
284  unset($this->softrefCfg[$key]);
285  }
286  }
287  // Setting in header memory:
288  // Version of file format
289  $this->dat['header']['XMLversion'] = '1.0';
290  // Initialize meta data array (to put it in top of file)
291  $this->dat['header']['meta'] = [];
292  // Add list of tables to consider static
293  $this->dat['header']['relStaticTables'] = ‪$this->relStaticTables;
294  // The list of excluded records
295  $this->dat['header']['excludeMap'] = ‪$this->excludeMap;
296  // Soft reference mode for elements
297  $this->dat['header']['softrefCfg'] = ‪$this->softrefCfg;
298  // List of extensions the import depends on.
299  $this->dat['header']['extensionDependencies'] = ‪$this->extensionDependencies;
300  $this->dat['header']['charset'] = 'utf-8';
301  }
302 
306  protected function ‪setMetaData(): void
307  {
308  $user = $this->‪getBackendUser();
309  if ($user->user['lang'] ?? false) {
310  $locale = GeneralUtility::makeInstance(Locales::class)->createLocale($user->user['lang']);
311  } else {
312  $locale = new ‪Locale();
313  }
314  $this->dat['header']['meta'] = [
315  'title' => ‪$this->title,
316  'description' => ‪$this->description,
317  'notes' => ‪$this->notes,
318  'packager_username' => $this->‪getBackendUser()->user['username'],
319  'packager_name' => $this->‪getBackendUser()->user['realName'],
320  'packager_email' => $this->‪getBackendUser()->user['email'],
321  'TYPO3_version' => (string)GeneralUtility::makeInstance(Typo3Version::class),
322  'created' => (new ‪DateFormatter())->format(‪$GLOBALS['EXEC_TIME'], 'EEE d. MMMM y', $locale),
323  ];
324  }
325 
326  /**************************
327  * Export / Init Page tree
328  *************************/
329 
335  public function ‪setPageTree(array $pageTree): void
336  {
337  $this->dat['header']['pagetree'] = $pageTree;
338  }
339 
345  protected function ‪removeExcludedPagesFromPageTree(array &$pageTree): void
346  {
347  foreach ($pageTree as ‪$pid => $value) {
348  if ($this->‪isRecordExcluded('pages', (int)($pageTree[‪$pid]['uid'] ?? 0))) {
349  unset($pageTree[‪$pid]);
350  } elseif (is_array($pageTree[‪$pid]['subrow'] ?? null)) {
351  $this->‪removeExcludedPagesFromPageTree($pageTree[‪$pid]['subrow']);
352  }
353  }
354  }
355 
356  /**************************
357  * Export
358  *************************/
359 
369  {
370  foreach (‪$recordTypesIncludeFields as $table => ‪$fields) {
371  if (!is_array(‪$fields)) {
372  throw new ‪Exception('The include fields for record type ' . htmlspecialchars($table) . ' are not defined by an array.', 1391440658);
373  }
375  }
376  }
377 
385  protected function ‪setRecordTypeIncludeFields(string $table, array ‪$fields): void
386  {
387  $this->recordTypesIncludeFields[$table] = ‪$fields;
388  }
389 
396  protected function ‪getExcludePagesClause(): string
397  {
398  $pageIds = [];
399 
400  foreach ($this->excludeMap as $tableAndUid => $isExcluded) {
401  [$table, ‪$uid] = explode(':', $tableAndUid);
402  if ($table === 'pages') {
403  $pageIds[] = (int)‪$uid;
404  }
405  }
406  if (!empty($pageIds)) {
407  return ' AND uid NOT IN (' . implode(',', $pageIds) . ')';
408  }
409  return '';
410  }
411 
419  protected function ‪addRecordsForPid(int ‪$pid, array ‪$tables, array $restrictToLanguageIds = []): void
420  {
421  $isRestrictToLanguageIds = $restrictToLanguageIds !== [];
422  foreach (‪$GLOBALS['TCA'] as $table => $value) {
423  if ($table !== 'pages'
424  && (in_array($table, ‪$tables, true) || in_array('_ALL', ‪$tables, true))
425  && $this->‪getBackendUser()->check('tables_select', $table)
426  && !(‪$GLOBALS['TCA'][$table]['ctrl']['is_static'] ?? false)
427  ) {
428  $languageField = ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'] ?? null;
429  $statement = $this->‪execListQueryPid($pid, $table);
430  while (‪$record = $statement->fetchAssociative()) {
431  if (is_array(‪$record)) {
432  // Skip the record, when languageId restrictions are enabled, and the record's language is not requested
433  if ($isRestrictToLanguageIds && $languageField && isset(‪$record[$languageField]) && !in_array(‪$record[$languageField], $restrictToLanguageIds, true)) {
434  continue;
435  }
436  $this->‪exportAddRecord($table, ‪$record);
437  }
438  }
439  }
440  }
441  }
442 
450  protected function ‪execListQueryPid(int ‪$pid, string $table): Result
451  {
452  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
453 
454  $orderBy = ‪$GLOBALS['TCA'][$table]['ctrl']['sortby'] ?? ‪$GLOBALS['TCA'][$table]['ctrl']['default_sortby'] ?? '';
455 
456  if ($this->excludeDisabledRecords === false) {
457  $queryBuilder->getRestrictions()
458  ->removeAll()
459  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
460  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
461  } else {
462  $queryBuilder->getRestrictions()
463  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
464  }
465 
466  $queryBuilder->select('*')
467  ->from($table)
468  ->where(
469  $queryBuilder->expr()->eq(
470  'pid',
471  $queryBuilder->createNamedParameter(‪$pid, ‪Connection::PARAM_INT)
472  )
473  );
474 
475  $orderBys = ‪QueryHelper::parseOrderBy((string)$orderBy);
476  foreach ($orderBys as $orderPair) {
477  [$field, $order] = $orderPair;
478  $queryBuilder->addOrderBy($field, $order);
479  }
480  // Ensure deterministic sorting
481  if (!in_array('uid', array_column($orderBys, 0))) {
482  $queryBuilder->addOrderBy('uid', 'ASC');
483  }
484 
485  return $queryBuilder->executeQuery();
486  }
487 
496  public function ‪exportAddRecord(string $table, array $row, int $relationLevel = 0): void
497  {
498  BackendUtility::workspaceOL($table, $row);
499 
500  if ($table === '' || (int)$row['uid'] === 0
501  || $this->‪isRecordExcluded($table, (int)$row['uid'])
502  || $this->excludeDisabledRecords && $this->‪isRecordDisabled($table, (int)$row['uid'])) {
503  return;
504  }
505 
506  if ($this->‪isPageInWebMount($table === 'pages' ? (int)$row['uid'] : (int)$row['pid'])) {
507  if (!isset($this->dat['records'][$table . ':' . $row['uid']])) {
508  // Prepare header info:
509  $row = $this->‪filterRecordFields($table, $row);
510  $headerInfo = [];
511  $headerInfo['uid'] = $row['uid'];
512  $headerInfo['pid'] = $row['pid'];
513  $headerInfo['title'] = ‪GeneralUtility::fixed_lgd_cs(BackendUtility::getRecordTitle($table, $row), 40);
514  if ($relationLevel) {
515  $headerInfo['relationLevel'] = $relationLevel;
516  }
517  // Set the header summary:
518  $this->dat['header']['records'][$table][$row['uid']] = $headerInfo;
519  // Create entry in the PID lookup:
520  $this->dat['header']['pid_lookup'][$row['pid']][$table][$row['uid']] = 1;
521  // Initialize reference index object:
522  $refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class);
523  $relations = $refIndexObj->getRelations($table, $row, 0);
524  $relations = $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  // There are no refindex entries for l10n_source of pages and tt_content, so we have to add them here manually for now.
530  // @todo can be removed, when this can come from ReferenceIndex.
531  if (($table === 'pages' || $table === 'tt_content')) {
532  $fieldNameTranslationSource = (‪$GLOBALS['TCA'][$table]['ctrl']['translationSource'] ?? '');
533  if (!empty($fieldNameTranslationSource) && ((int)($row[$fieldNameTranslationSource] ?? 0)) > 0) {
534  $this->dat['records'][$table . ':' . $row['uid']]['rels'][$fieldNameTranslationSource]['type'] = 'db';
535  $this->dat['records'][$table . ':' . $row['uid']]['rels'][$fieldNameTranslationSource]['itemArray'][0] = [
536  'id' => $row[$fieldNameTranslationSource],
537  'table' => $table,
538  ];
539  }
540  }
541  // Add information about the relations in the record in the header:
542  $this->dat['header']['records'][$table][$row['uid']]['rels'] = $this->‪flatDbRelations($this->dat['records'][$table . ':' . $row['uid']]['rels']);
543  // Add information about the softrefs to header:
544  $this->dat['header']['records'][$table][$row['uid']]['softrefs'] = $this->‪flatSoftRefs($this->dat['records'][$table . ':' . $row['uid']]['rels']);
545  } else {
546  $this->‪addError('Record ' . $table . ':' . $row['uid'] . ' already added.');
547  }
548  } else {
549  $this->‪addError('Record ' . $table . ':' . $row['uid'] . ' was outside your database mounts!');
550  }
551  }
552 
559  protected function ‪isPageInWebMount(int ‪$pid): bool
560  {
561  if (!isset($this->pageInWebMountCache[‪$pid])) {
562  $this->pageInWebMountCache[‪$pid] = (bool)$this->‪getBackendUser()->isInWebMount($pid);
563  }
564  return $this->pageInWebMountCache[‪$pid];
565  }
566 
576  protected function ‪filterRecordFields(string $table, array $row): array
577  {
578  if (isset($this->recordTypesIncludeFields[$table])) {
579  $includeFields = array_unique(array_merge(
580  $this->recordTypesIncludeFields[$table],
581  $this->defaultRecordIncludeFields
582  ));
583  $newRow = [];
584  foreach ($row as $key => $value) {
585  if (in_array($key, $includeFields, true)) {
586  $newRow[$key] = $value;
587  }
588  }
589  } else {
590  $newRow = $row;
591  }
592  return $newRow;
593  }
594 
602  protected function ‪removeRedundantSoftRefsInRelations(array $relations): array
603  {
604  foreach ($relations as &$relation) {
605  if (isset($relation['type']) && $relation['type'] === 'db') {
606  foreach ($relation['itemArray'] as $dbRelationData) {
607  if ($dbRelationData['table'] === 'sys_file') {
608  if (isset($relation['softrefs']['keys']['typolink'])) {
609  foreach ($relation['softrefs']['keys']['typolink'] as $tokenID => $softref) {
610  if ($softref['subst']['type'] === 'file') {
611  $file = GeneralUtility::makeInstance(ResourceFactory::class)->retrieveFileOrFolderObject($softref['subst']['relFileName']);
612  if ($file instanceof ‪File) {
613  if ($file->getUid() == $dbRelationData['id']) {
614  unset($relation['softrefs']['keys']['typolink'][$tokenID]);
615  }
616  }
617  }
618  }
619  if (empty($relation['softrefs']['keys']['typolink'])) {
620  unset($relation['softrefs']);
621  }
622  }
623  }
624  }
625  }
626  }
627  return $relations;
628  }
629 
637  protected function ‪flatDbRelations(array $relations): array
638  {
639  ‪$list = [];
640  foreach ($relations as $relation) {
641  if (isset($relation['type'])) {
642  if ($relation['type'] === 'db') {
643  foreach ($relation['itemArray'] as $dbRelationData) {
644  ‪$list[$dbRelationData['table'] . ':' . $dbRelationData['id']] = $dbRelationData;
645  }
646  } elseif ($relation['type'] === 'flex' && is_array($relation['flexFormRels']['db'] ?? null)) {
647  foreach ($relation['flexFormRels']['db'] as $subList) {
648  foreach ($subList as $dbRelationData) {
649  ‪$list[$dbRelationData['table'] . ':' . $dbRelationData['id']] = $dbRelationData;
650  }
651  }
652  }
653  }
654  }
655  return ‪$list;
656  }
657 
665  protected function ‪flatSoftRefs(array $relations): array
666  {
667  ‪$list = [];
668  foreach ($relations as $field => $relation) {
669  if (is_array($relation['softrefs']['keys'] ?? null)) {
670  foreach ($relation['softrefs']['keys'] as $spKey => $elements) {
671  foreach ($elements as $subKey => $el) {
672  $lKey = $field . ':' . $spKey . ':' . $subKey;
673  ‪$list[$lKey] = array_merge(['field' => $field, 'spKey' => $spKey], $el);
674  // Add file_ID key to header - slightly "risky" way of doing this because if the calculation
675  // changes for the same value in $this->records[...] this will not work anymore!
676  if ($el['subst']['relFileName'] ?? false) {
677  ‪$list[$lKey]['file_ID'] = md5(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
678  }
679  }
680  }
681  }
682  if (isset($relation['type'])) {
683  if ($relation['type'] === 'flex' && is_array($relation['flexFormRels']['softrefs'] ?? null)) {
684  foreach ($relation['flexFormRels']['softrefs'] as $structurePath => &$subList) {
685  if (isset($subList['keys'])) {
686  foreach ($subList['keys'] as $spKey => $elements) {
687  foreach ($elements as $subKey => $el) {
688  $lKey = $field . ':' . $structurePath . ':' . $spKey . ':' . $subKey;
689  ‪$list[$lKey] = array_merge([
690  'field' => $field,
691  'spKey' => $spKey,
692  'structurePath' => $structurePath,
693  ], $el);
694  // Add file_ID key to header - slightly "risky" way of doing this because if the calculation
695  // changes for the same value in $this->records[...] this will not work anymore!
696  if ($el['subst']['relFileName'] ?? false) {
697  ‪$list[$lKey]['file_ID'] = md5(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
698  }
699  }
700  }
701  }
702  }
703  }
704  }
705  }
706  return ‪$list;
707  }
708 
720  protected function ‪exportAddRecordsFromRelations(int $relationLevel = 0): int
721  {
722  if (!isset($this->dat['records'])) {
723  $this->‪addError('There were no records available.');
724  return 0;
725  }
726 
727  $addRecords = [];
728 
729  foreach ($this->dat['records'] as ‪$record) {
730  if (!is_array(‪$record)) {
731  continue;
732  }
733  foreach (‪$record['rels'] as $relation) {
734  if (isset($relation['type'])) {
735  if ($relation['type'] === 'db') {
736  foreach ($relation['itemArray'] as $dbRelationData) {
737  $this->‪exportAddRecordsFromRelationsPushRelation($dbRelationData, $addRecords);
738  }
739  }
740  if ($relation['type'] === 'flex') {
741  // Database relations in flex form fields:
742  if (is_array($relation['flexFormRels']['db'] ?? null)) {
743  foreach ($relation['flexFormRels']['db'] as $subList) {
744  foreach ($subList as $dbRelationData) {
745  $this->‪exportAddRecordsFromRelationsPushRelation($dbRelationData, $addRecords);
746  }
747  }
748  }
749 
750  // Database oriented soft references in flex form fields:
751  if (is_array($relation['flexFormRels']['softrefs'] ?? null)) {
752  foreach ($relation['flexFormRels']['softrefs'] as $subList) {
753  foreach ($subList['keys'] as $elements) {
754  foreach ($elements as $el) {
755  if ($el['subst']['type'] === 'db' && $this->‪isSoftRefIncluded($el['subst']['tokenID'])) {
756  [$referencedTable, $referencedUid] = explode(':', $el['subst']['recordRef']);
757  $dbRelationData = [
758  'table' => $referencedTable,
759  'id' => $referencedUid,
760  ];
761  $this->‪exportAddRecordsFromRelationsPushRelation($dbRelationData, $addRecords, $el['subst']['tokenID']);
762  }
763  }
764  }
765  }
766  }
767  }
768  }
769  // In any case, if there are soft refs:
770  if (is_array($relation['softrefs']['keys'] ?? null)) {
771  foreach ($relation['softrefs']['keys'] as $elements) {
772  foreach ($elements as $el) {
773  if (($el['subst']['type'] ?? '') === 'db' && $this->‪isSoftRefIncluded($el['subst']['tokenID'])) {
774  [$referencedTable, $referencedUid] = explode(':', $el['subst']['recordRef']);
775  $dbRelationData = [
776  'table' => $referencedTable,
777  'id' => $referencedUid,
778  ];
779  $this->‪exportAddRecordsFromRelationsPushRelation($dbRelationData, $addRecords, $el['subst']['tokenID']);
780  }
781  }
782  }
783  }
784  }
785  }
786 
787  if (!empty($addRecords)) {
788  foreach ($addRecords as $recordData) {
789  ‪$record = BackendUtility::getRecord($recordData['table'], $recordData['id']);
790 
791  if (is_array(‪$record)) {
792  // Depending on db driver, int fields may or may not be returned as integer or as string. The
793  // loop aligns that detail and forces strings for everything to have exports more db agnostic.
794  foreach (‪$record as $fieldName => $fieldValue) {
795  ‪$record[$fieldName] = $fieldValue === null ? $fieldValue : (string)$fieldValue;
796  }
797  $this->‪exportAddRecord($recordData['table'], ‪$record, $relationLevel + 1);
798  }
799  // Set status message
800  // Relation pointers always larger than zero except certain "select" types with
801  // negative values pointing to uids - but that is not supported here.
802  if ($recordData['id'] > 0) {
803  $recordRef = $recordData['table'] . ':' . $recordData['id'];
804  if (!isset($this->dat['records'][$recordRef])) {
805  $this->dat['records'][$recordRef] = 'NOT_FOUND';
806  $this->‪addError('Relation record ' . $recordRef . ' was not found!');
807  }
808  }
809  }
810  }
811 
812  return count($addRecords);
813  }
814 
823  protected function ‪exportAddRecordsFromRelationsPushRelation(array $recordData, array &$addRecords, string $tokenID = ''): void
824  {
825  // @todo: Remove by-reference and return final array
826  $recordRef = $recordData['table'] . ':' . $recordData['id'];
827  if (
828  isset(‪$GLOBALS['TCA'][$recordData['table']]) && !$this->‪isTableStatic($recordData['table'])
829  && !$this->‪isRecordExcluded($recordData['table'], (int)$recordData['id'])
830  && (!$tokenID || $this->‪isSoftRefIncluded($tokenID)) && $this->‪inclRelation($recordData['table'])
831  && !isset($this->dat['records'][$recordRef])
832  ) {
833  $addRecords[$recordRef] = $recordData;
834  }
835  }
836 
843  protected function ‪inclRelation(string $table): bool
844  {
845  return is_array(‪$GLOBALS['TCA'][$table] ?? null)
846  && (in_array($table, $this->relOnlyTables, true) || in_array('_ALL', $this->relOnlyTables, true))
847  && $this->‪getBackendUser()->check('tables_select', $table);
848  }
849 
856  protected function ‪exportAddFilesFromRelations(): void
857  {
858  // @todo: Consider NOT using by-reference but writing final $this->dat at end of method.
859  if (!isset($this->dat['records'])) {
860  $this->‪addError('There were no records available.');
861  return;
862  }
863 
864  foreach ($this->dat['records'] as &‪$record) {
865  if (!is_array(‪$record)) {
866  continue;
867  }
868  foreach (‪$record['rels'] as &$relation) {
869  // For all flex type relations:
870  if (isset($relation['type']) && $relation['type'] === 'flex') {
871  // Database oriented soft references in flex form fields:
872  if (isset($relation['flexFormRels']['softrefs'])) {
873  foreach ($relation['flexFormRels']['softrefs'] as &$subList) {
874  foreach ($subList['keys'] as &$elements) {
875  foreach ($elements as &$el) {
876  if ($el['subst']['type'] === 'file' && $this->‪isSoftRefIncluded($el['subst']['tokenID'])) {
877  // Create abs path and ID for file:
878  $ID_absFile = GeneralUtility::getFileAbsFileName(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
879  $ID = md5($el['subst']['relFileName']);
880  if ($ID_absFile) {
881  if (!$this->dat['files'][$ID]) {
882  $fileRelationData = [
883  'filename' => ‪PathUtility::basename($ID_absFile),
884  'ID_absFile' => $ID_absFile,
885  'ID' => $ID,
886  'relFileName' => $el['subst']['relFileName'],
887  ];
888  $this->‪exportAddFile($fileRelationData);
889  }
890  $el['file_ID'] = $ID;
891  }
892  }
893  }
894  }
895  }
896  unset($subList, $elements, $el);
897  }
898  }
899  // In any case, if there are soft refs:
900  foreach ($relation['softrefs']['keys'] ?? [] as &$elements) {
901  foreach ($elements as &$el) {
902  if (($el['subst']['type'] ?? '') === 'file' && $this->‪isSoftRefIncluded($el['subst']['tokenID'])) {
903  // Create abs path and ID for file:
904  $ID_absFile = GeneralUtility::getFileAbsFileName(‪Environment::getPublicPath() . '/' . $el['subst']['relFileName']);
905  $ID = md5($el['subst']['relFileName']);
906  if ($ID_absFile) {
907  if (!$this->dat['files'][$ID]) {
908  $fileRelationData = [
909  'filename' => ‪PathUtility::basename($ID_absFile),
910  'ID_absFile' => $ID_absFile,
911  'ID' => $ID,
912  'relFileName' => $el['subst']['relFileName'],
913  ];
914  $this->‪exportAddFile($fileRelationData);
915  }
916  $el['file_ID'] = $ID;
917  }
918  }
919  }
920  }
921  }
922  }
923  }
924 
930  protected function ‪exportAddFile(array $fileData): void
931  {
932  if (!@is_file($fileData['ID_absFile'])) {
933  $this->‪addError($fileData['ID_absFile'] . ' was not a file! Skipping.');
934  return;
935  }
936 
937  $fileStat = stat($fileData['ID_absFile']);
938  $fileMd5 = md5_file($fileData['ID_absFile']);
939 
940  $fileInfo = [];
941  $fileInfo['filename'] = ‪PathUtility::basename($fileData['ID_absFile']);
942  $fileInfo['filemtime'] = $fileStat['mtime'];
943  $fileInfo['relFileRef'] = ‪PathUtility::stripPathSitePrefix($fileData['ID_absFile']);
944  if ($fileData['relFileName']) {
945  $fileInfo['relFileName'] = $fileData['relFileName'];
946  }
947 
948  // Setting this data in the header
949  $this->dat['header']['files'][$fileData['ID']] = $fileInfo;
950 
951  if (!$this->saveFilesOutsideExportFile) {
952  $fileInfo['content'] = (string)file_get_contents($fileData['ID_absFile']);
953  } else {
954  GeneralUtility::upload_copy_move(
955  $fileData['ID_absFile'],
956  $this->‪getOrCreateTemporaryFolderName() . '/' . $fileMd5
957  );
958  }
959  $fileInfo['content_md5'] = $fileMd5;
960  $this->dat['files'][$fileData['ID']] = $fileInfo;
961  }
962 
966  protected function ‪exportAddFilesFromSysFilesRecords(): void
967  {
968  foreach ($this->dat['header']['records']['sys_file'] ?? [] as $sysFileUid => $_) {
969  $fileData = $this->dat['records']['sys_file:' . $sysFileUid]['data'];
970  $this->‪exportAddSysFile($fileData);
971  }
972  }
973 
978  protected function ‪exportAddSysFile(array $fileData): void
979  {
980  try {
981  $file = GeneralUtility::makeInstance(ResourceFactory::class)->createFileObject($fileData);
982  $file->checkActionPermission('read');
983  } catch (\‪Exception $e) {
984  $this->‪addError('Error when trying to add file ' . $fileData['title'] . ': ' . $e->getMessage());
985  return;
986  }
987 
988  $fileUid = $file->getUid();
989  $fileSha1 = $file->getStorage()->hashFile($file, 'sha1');
990  if ($fileSha1 !== $file->getProperty('sha1')) {
991  $this->dat['records']['sys_file:' . $fileUid]['data']['sha1'] = $fileSha1;
992  $this->‪addError(
993  'The SHA-1 file hash of ' . $file->getCombinedIdentifier() . ' is not up-to-date in the index! ' .
994  'The file was added based on the current file hash.'
995  );
996  }
997  // Build unique id based on the storage and the file identifier
998  $fileId = md5($file->getStorage()->getUid() . ':' . $file->getProperty('identifier_hash'));
999 
1000  $fileInfo = [];
1001  $fileInfo['filename'] = $file->getProperty('name');
1002  $fileInfo['filemtime'] = $file->getProperty('modification_date');
1003 
1004  // Setting this data in the header
1005  $this->dat['header']['files_fal'][$fileId] = $fileInfo;
1006 
1007  if (!$this->saveFilesOutsideExportFile) {
1008  $fileInfo['content'] = $file->getContents();
1009  } else {
1010  GeneralUtility::upload_copy_move(
1011  $file->getForLocalProcessing(false),
1012  $this->getOrCreateTemporaryFolderName() . '/' . $fileSha1
1013  );
1014  }
1015  $fileInfo['content_sha1'] = $fileSha1;
1016  $this->dat['files_fal'][$fileId] = $fileInfo;
1017  }
1018 
1019  /**************************
1020  * File Output
1021  *************************/
1022 
1030  public function ‪render(): string
1031  {
1032  if ($this->exportFileType === self::FILETYPE_XML) {
1033  $out = $this->‪createXML();
1034  } else {
1035  $out = '';
1036  // adding header:
1037  $out .= $this->‪addFilePart(serialize($this->dat['header']));
1038  // adding records:
1039  $out .= $this->‪addFilePart(serialize($this->dat['records']));
1040  // adding files:
1041  $out .= $this->‪addFilePart(serialize($this->dat['files'] ?? null));
1042  // adding files_fal:
1043  $out .= $this->‪addFilePart(serialize($this->dat['files_fal'] ?? null));
1044  }
1045  return $out;
1046  }
1047 
1053  protected function ‪createXML(): string
1054  {
1055  // Options:
1056  $options = [
1057  'alt_options' => [
1058  '/header' => [
1059  'disableTypeAttrib' => true,
1060  'clearStackPath' => true,
1061  'parentTagMap' => [
1062  'files' => 'file',
1063  'files_fal' => 'file',
1064  'records' => 'table',
1065  'table' => 'rec',
1066  'rec:rels' => 'relations',
1067  'relations' => 'element',
1068  'filerefs' => 'file',
1069  'pid_lookup' => 'page_contents',
1070  'header:relStaticTables' => 'static_tables',
1071  'static_tables' => 'tablename',
1072  'excludeMap' => 'item',
1073  'softrefCfg' => 'softrefExportMode',
1074  'extensionDependencies' => 'extkey',
1075  'softrefs' => 'softref_element',
1076  ],
1077  'alt_options' => [
1078  '/pagetree' => [
1079  'disableTypeAttrib' => true,
1080  'useIndexTagForNum' => 'node',
1081  'parentTagMap' => [
1082  'node:subrow' => 'node',
1083  ],
1084  ],
1085  '/pid_lookup/page_contents' => [
1086  'disableTypeAttrib' => true,
1087  'parentTagMap' => [
1088  'page_contents' => 'table',
1089  ],
1090  'grandParentTagMap' => [
1091  'page_contents/table' => 'item',
1092  ],
1093  ],
1094  ],
1095  ],
1096  '/records' => [
1097  'disableTypeAttrib' => true,
1098  'parentTagMap' => [
1099  'records' => 'tablerow',
1100  'tablerow:data' => 'fieldlist',
1101  'tablerow:rels' => 'related',
1102  'related' => 'field',
1103  'field:itemArray' => 'relations',
1104  'field:flexFormRels' => 'flexform',
1105  'relations' => 'element',
1106  'filerefs' => 'file',
1107  'flexform:db' => 'db_relations',
1108  'flexform:softrefs' => 'softref_relations',
1109  'softref_relations' => 'structurePath',
1110  'db_relations' => 'path',
1111  'path' => 'element',
1112  'keys' => 'softref_key',
1113  'softref_key' => 'softref_element',
1114  ],
1115  'alt_options' => [
1116  '/records/tablerow/fieldlist' => [
1117  'useIndexTagForAssoc' => 'field',
1118  ],
1119  ],
1120  ],
1121  '/files' => [
1122  'disableTypeAttrib' => true,
1123  'parentTagMap' => [
1124  'files' => 'file',
1125  ],
1126  ],
1127  '/files_fal' => [
1128  'disableTypeAttrib' => true,
1129  'parentTagMap' => [
1130  'files_fal' => 'file',
1131  ],
1132  ],
1133  ],
1134  ];
1135  // Creating XML file from $outputArray:
1136  $charset = $this->dat['header']['charset'] ?: 'utf-8';
1137  $XML = '<?xml version="1.0" encoding="' . $charset . '" standalone="yes" ?>' . LF;
1138  $XML .= (new ‪Typo3XmlSerializer())->encodeWithReturningExceptionAsString(
1139  $this->dat,
1141  $options
1142  );
1143  return $XML;
1144  }
1145 
1152  protected function ‪addFilePart(string $data): string
1153  {
1154  $compress = $this->exportFileType === ‪self::FILETYPE_T3DZ;
1155  if ($compress) {
1156  $data = (string)gzcompress($data);
1157  }
1158  return md5($data) . ':' . ($compress ? '1' : '0') . ':' . str_pad((string)strlen($data), 10, '0', STR_PAD_LEFT) . ':' . $data . ':';
1159  }
1160 
1161  public function ‪saveToFile(): ‪File
1162  {
1163  $saveFolder = $this->‪getOrCreateDefaultImportExportFolder();
1165  $filesFolderName = $fileName . '.files';
1166  $fileContent = $this->‪render();
1167 
1168  if (!($saveFolder?->checkActionPermission('write'))) {
1170  'You are not allowed to write to the target folder "' . $saveFolder->getPublicUrl() . '"',
1171  1602432207
1172  );
1173  }
1174 
1175  if ($saveFolder->hasFolder($filesFolderName)) {
1176  $saveFolder->getSubfolder($filesFolderName)->delete();
1177  }
1178 
1179  $temporaryFileName = GeneralUtility::tempnam('export');
1180  ‪GeneralUtility::writeFile($temporaryFileName, $fileContent);
1181  $file = $saveFolder->addFile($temporaryFileName, $fileName, DuplicationBehavior::REPLACE);
1182 
1183  if ($this->saveFilesOutsideExportFile) {
1184  $filesFolder = $saveFolder->createFolder($filesFolderName);
1185  $temporaryFilesForExport = GeneralUtility::getFilesInDir($this->‪getOrCreateTemporaryFolderName(), '', true);
1186  foreach ($temporaryFilesForExport as $temporaryFileForExport) {
1187  $filesFolder->addFile($temporaryFileForExport);
1188  }
1190  }
1191 
1192  return $file;
1193  }
1194 
1195  public function ‪getExportFileName(): string
1196  {
1197  return ‪$this->exportFileName;
1198  }
1199 
1200  public function ‪setExportFileName(string ‪$exportFileName): void
1201  {
1202  ‪$exportFileName = trim((string)preg_replace('/[^[:alnum:]._-]*/', '', ‪$exportFileName));
1203  $this->exportFileName = ‪$exportFileName;
1204  }
1205 
1207  {
1208  if (!empty($this->exportFileName)) {
1210  } else {
1212  }
1213  $exportFileName .= $this->‪getFileExtensionByFileType();
1214 
1215  return ‪$exportFileName;
1216  }
1217 
1218  protected function ‪generateExportFileName(): string
1219  {
1220  if ($this->pid !== -1) {
1221  ‪$exportFileName = 'tree_PID' . $this->pid . '_L' . ‪$this->levels;
1222  } elseif (!empty($this->‪getRecord())) {
1223  $exportFileName = 'recs_' . implode('-', $this->‪getRecord());
1224  $exportFileName = str_replace(':', '_', ‪$exportFileName);
1225  } elseif (!empty($this->‪getList())) {
1226  $exportFileName = 'list_' . implode('-', $this->‪getList());
1227  $exportFileName = str_replace(':', '_', ‪$exportFileName);
1228  } else {
1229  ‪$exportFileName = 'export';
1230  }
1231 
1232  ‪$exportFileName = substr(trim((string)preg_replace('/[^[:alnum:]_-]/', '-', ‪$exportFileName)), 0, 20);
1233 
1234  return 'T3D_' . ‪$exportFileName . '_' . date('Y-m-d_H-i');
1235  }
1236 
1237  public function ‪getExportFileType(): string
1238  {
1239  return ‪$this->exportFileType;
1240  }
1241 
1242  public function ‪setExportFileType(string ‪$exportFileType): void
1243  {
1245  if (!in_array(‪$exportFileType, ‪$supportedFileTypes, true)) {
1246  throw new \InvalidArgumentException(
1247  sprintf(
1248  'File type "%s" is not valid. Supported file types are %s.',
1250  implode(', ', array_map(static function ($fileType) {
1251  return '"' . $fileType . '"';
1253  ),
1254  1602505264
1255  );
1256  }
1257  $this->exportFileType = ‪$exportFileType;
1258  }
1259 
1260  public function ‪getSupportedFileTypes(): array
1261  {
1262  if (empty($this->supportedFileTypes)) {
1266  if ($this->compressionAvailable) {
1268  }
1269  $this->supportedFileTypes = ‪$supportedFileTypes;
1270  }
1272  }
1273 
1274  protected function ‪getFileExtensionByFileType(): string
1275  {
1276  return match ($this->exportFileType) {
1277  self::FILETYPE_XML => '.xml',
1278  self::FILETYPE_T3D => '.t3d',
1279  default => '-z.t3d',
1280  };
1281  }
1282 
1283  public function ‪getTitle(): string
1284  {
1285  return ‪$this->title;
1286  }
1287 
1288  public function ‪setTitle(string ‪$title): void
1289  {
1290  $this->title = ‪$title;
1291  }
1292 
1293  public function ‪getDescription(): string
1294  {
1295  return ‪$this->description;
1296  }
1297 
1298  public function ‪setDescription(string ‪$description): void
1299  {
1301  }
1302 
1303  public function ‪getNotes(): string
1304  {
1305  return ‪$this->notes;
1306  }
1307 
1308  public function ‪setNotes(string ‪$notes): void
1309  {
1310  $this->notes = ‪$notes;
1311  }
1312 
1313  public function ‪getRecord(): array
1314  {
1315  return ‪$this->record;
1316  }
1317 
1318  public function ‪setRecord(array ‪$record): void
1319  {
1320  $this->record = ‪$record;
1321  }
1322 
1323  public function ‪getList(): array
1324  {
1325  return ‪$this->list;
1326  }
1327 
1328  public function ‪setList(array ‪$list): void
1329  {
1330  $this->list = ‪$list;
1331  }
1332 
1333  public function ‪getLevels(): int
1334  {
1335  return ‪$this->levels;
1336  }
1337 
1338  public function ‪setLevels(int ‪$levels): void
1339  {
1340  $this->levels = ‪$levels;
1341  }
1342 
1343  public function ‪getTables(): array
1344  {
1345  return ‪$this->tables;
1346  }
1347 
1348  public function ‪setTables(array ‪$tables): void
1349  {
1350  $this->tables = ‪$tables;
1351  }
1352 
1353  public function ‪getRelOnlyTables(): array
1354  {
1355  return ‪$this->relOnlyTables;
1356  }
1357 
1358  public function ‪setRelOnlyTables(array ‪$relOnlyTables): void
1359  {
1360  $this->relOnlyTables = ‪$relOnlyTables;
1361  }
1362 
1363  public function ‪getTreeHTML(): string
1364  {
1365  return ‪$this->treeHTML;
1366  }
1367 
1368  public function ‪isIncludeExtFileResources(): bool
1369  {
1371  }
1372 
1374  {
1375  $this->includeExtFileResources = ‪$includeExtFileResources;
1376  }
1377 
1385  {
1386  $this->saveFilesOutsideExportFile = ‪$saveFilesOutsideExportFile;
1387  }
1388 
1389  public function ‪isSaveFilesOutsideExportFile(): bool
1390  {
1392  }
1393 }
‪TYPO3\CMS\Impexp\Export\setExportFileName
‪setExportFileName(string $exportFileName)
Definition: Export.php:1200
‪TYPO3\CMS\Impexp\Export\exportAddRecordsFromRelations
‪int exportAddRecordsFromRelations(int $relationLevel=0)
Definition: Export.php:720
‪TYPO3\CMS\Impexp\Export\$mode
‪string $mode
Definition: Export.php:60
‪TYPO3\CMS\Impexp\Export\getDescription
‪getDescription()
Definition: Export.php:1293
‪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:1030
‪TYPO3\CMS\Impexp\Export\execListQueryPid
‪Result execListQueryPid(int $pid, string $table)
Definition: Export.php:450
‪TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction
Definition: HiddenRestriction.php:27
‪TYPO3\CMS\Impexp\ImportExport\$extensionDependencies
‪array $extensionDependencies
Definition: ImportExport.php:134
‪TYPO3\CMS\Core\Utility\PathUtility\stripPathSitePrefix
‪static stripPathSitePrefix(string $path)
Definition: PathUtility.php:428
‪TYPO3\CMS\Impexp\Export\getRecord
‪getRecord()
Definition: Export.php:1313
‪TYPO3\CMS\Impexp\Export\setList
‪setList(array $list)
Definition: Export.php:1328
‪TYPO3\CMS\Impexp\Export\$treeHTML
‪string $treeHTML
Definition: Export.php:74
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:27
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:52
‪TYPO3\CMS\Impexp\Export\$supportedFileTypes
‪array $supportedFileTypes
Definition: Export.php:96
‪TYPO3\CMS\Impexp\Export\filterRecordFields
‪array filterRecordFields(string $table, array $row)
Definition: Export.php:576
‪TYPO3\CMS\Core\Utility\GeneralUtility\fixed_lgd_cs
‪static string fixed_lgd_cs(string $string, int $chars, string $appendString='...')
Definition: GeneralUtility.php:92
‪TYPO3\CMS\Impexp\Export\setExportFileType
‪setExportFileType(string $exportFileType)
Definition: Export.php:1242
‪TYPO3\CMS\Impexp\ImportExport\addError
‪addError(string $message)
Definition: ImportExport.php:1314
‪TYPO3\CMS\Impexp\Export\setRecordTypeIncludeFields
‪setRecordTypeIncludeFields(string $table, array $fields)
Definition: Export.php:385
‪TYPO3\CMS\Impexp\Export\isPageInWebMount
‪bool isPageInWebMount(int $pid)
Definition: Export.php:559
‪TYPO3\CMS\Impexp\Export\setNotes
‪setNotes(string $notes)
Definition: Export.php:1308
‪TYPO3\CMS\Impexp\Export\FILETYPE_XML
‪const FILETYPE_XML
Definition: Export.php:56
‪TYPO3\CMS\Impexp\Export\$exportFileType
‪string $exportFileType
Definition: Export.php:95
‪TYPO3\CMS\Core\Serializer\Typo3XmlSerializer
Definition: Typo3XmlSerializer.php:121
‪TYPO3\CMS\Impexp\Export\getFileExtensionByFileType
‪getFileExtensionByFileType()
Definition: Export.php:1274
‪TYPO3\CMS\Impexp\Export\setRelOnlyTables
‪setRelOnlyTables(array $relOnlyTables)
Definition: Export.php:1358
‪TYPO3\CMS\Impexp\Export\$recordTypesIncludeFields
‪array $recordTypesIncludeFields
Definition: Export.php:87
‪TYPO3\CMS\Impexp\Export\inclRelation
‪bool inclRelation(string $table)
Definition: Export.php:843
‪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:117
‪TYPO3\CMS\Impexp\Export\getRelOnlyTables
‪getRelOnlyTables()
Definition: Export.php:1353
‪TYPO3\CMS\Impexp\Export\$title
‪string $title
Definition: Export.php:61
‪TYPO3\CMS\Impexp\Export\getExcludePagesClause
‪string getExcludePagesClause()
Definition: Export.php:396
‪TYPO3\CMS\Impexp\Export\__construct
‪__construct()
Definition: Export.php:104
‪TYPO3\CMS\Impexp\Export\exportAddFilesFromRelations
‪exportAddFilesFromRelations()
Definition: Export.php:856
‪TYPO3\CMS\Core\Database\ReferenceIndex
Definition: ReferenceIndex.php:40
‪TYPO3\CMS\Impexp\Export\$compressionAvailable
‪bool $compressionAvailable
Definition: Export.php:97
‪TYPO3\CMS\Impexp\ImportExport\$pid
‪int $pid
Definition: ImportExport.php:62
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static getPublicPath()
Definition: Environment.php:187
‪TYPO3\CMS\Impexp\View\ExportPageTreeView
Definition: ExportPageTreeView.php:33
‪TYPO3\CMS\Impexp\ImportExport\isTableStatic
‪bool isTableStatic(string $table)
Definition: ImportExport.php:1138
‪TYPO3\CMS\Core\Exception
‪TYPO3\CMS\Impexp\Export\$list
‪array $list
Definition: Export.php:65
‪TYPO3\CMS\Impexp\Export\setHeaderBasics
‪setHeaderBasics()
Definition: Export.php:279
‪TYPO3\CMS\Impexp\Export\$exportFileName
‪string $exportFileName
Definition: Export.php:94
‪TYPO3\CMS\Impexp\Export\getExportFileName
‪getExportFileName()
Definition: Export.php:1195
‪TYPO3\CMS\Core\Localization\Locales
Definition: Locales.php:36
‪TYPO3\CMS\Impexp\Export\$saveFilesOutsideExportFile
‪bool $saveFilesOutsideExportFile
Definition: Export.php:93
‪TYPO3\CMS\Impexp\Export\saveToFile
‪saveToFile()
Definition: Export.php:1161
‪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:73
‪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:129
‪TYPO3\CMS\Impexp\ImportExport\isRecordDisabled
‪bool isRecordDisabled(string $table, int $uid)
Definition: ImportExport.php:277
‪TYPO3\CMS\Impexp\Export\exportAddSysFile
‪exportAddSysFile(array $fileData)
Definition: Export.php:978
‪TYPO3\CMS\Impexp\Export\exportAddFilesFromSysFilesRecords
‪exportAddFilesFromSysFilesRecords()
Definition: Export.php:966
‪TYPO3\CMS\Core\Localization\DateFormatter
Definition: DateFormatter.php:27
‪TYPO3\CMS\Impexp\Export\generateExportFileName
‪generateExportFileName()
Definition: Export.php:1218
‪TYPO3\CMS\Impexp\Export\$pageInWebMountCache
‪array $pageInWebMountCache
Definition: Export.php:102
‪TYPO3\CMS\Impexp\Export\getOrGenerateExportFileNameWithFileExtension
‪getOrGenerateExportFileNameWithFileExtension()
Definition: Export.php:1206
‪TYPO3\CMS\Impexp\Export\getTranslationForPage
‪getTranslationForPage(int $defaultLanguagePageUid, bool $considerHiddenPages, array $limitToLanguageIds=[])
Definition: Export.php:222
‪TYPO3\CMS\Impexp\Export\setSaveFilesOutsideExportFile
‪setSaveFilesOutsideExportFile(bool $saveFilesOutsideExportFile)
Definition: Export.php:1384
‪TYPO3\CMS\Impexp\Export\getTitle
‪getTitle()
Definition: Export.php:1283
‪TYPO3\CMS\Impexp\ImportExport\getOrCreateTemporaryFolderName
‪getOrCreateTemporaryFolderName()
Definition: ImportExport.php:990
‪TYPO3\CMS\Core\Utility\GeneralUtility\writeFile
‪static bool writeFile(string $file, string $content, bool $changePermissions=false)
Definition: GeneralUtility.php:1464
‪TYPO3\CMS\Impexp\Export\getTables
‪getTables()
Definition: Export.php:1343
‪TYPO3\CMS\Impexp\Export\initializeExport
‪initializeExport()
Definition: Export.php:268
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Impexp\Export\setTitle
‪setTitle(string $title)
Definition: Export.php:1288
‪TYPO3\CMS\Impexp\Export\setRecordTypesIncludeFields
‪setRecordTypesIncludeFields(array $recordTypesIncludeFields)
Definition: Export.php:368
‪TYPO3\CMS\Impexp\Export\FILETYPE_T3D
‪const FILETYPE_T3D
Definition: Export.php:57
‪TYPO3\CMS\Impexp\Export\$description
‪string $description
Definition: Export.php:62
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:42
‪TYPO3\CMS\Impexp\Export\$notes
‪string $notes
Definition: Export.php:63
‪TYPO3\CMS\Impexp\Export\$record
‪array $record
Definition: Export.php:64
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:26
‪TYPO3\CMS\Impexp\Export\flatDbRelations
‪array flatDbRelations(array $relations)
Definition: Export.php:637
‪TYPO3\CMS\Impexp\Export\addRecordsForPid
‪addRecordsForPid(int $pid, array $tables, array $restrictToLanguageIds=[])
Definition: Export.php:419
‪TYPO3\CMS\Impexp\Export\getExportFileType
‪getExportFileType()
Definition: Export.php:1237
‪TYPO3\CMS\Impexp\Export\getSupportedFileTypes
‪getSupportedFileTypes()
Definition: Export.php:1260
‪TYPO3\CMS\Impexp\Export\exportAddRecord
‪exportAddRecord(string $table, array $row, int $relationLevel=0)
Definition: Export.php:496
‪TYPO3\CMS\Impexp\Export\$levels
‪int $levels
Definition: Export.php:66
‪TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior
‪DuplicationBehavior
Definition: DuplicationBehavior.php:28
‪TYPO3\CMS\Impexp\ImportExport\getOrCreateDefaultImportExportFolder
‪getOrCreateDefaultImportExportFolder()
Definition: ImportExport.php:1025
‪TYPO3\CMS\Impexp\Export\$includeExtFileResources
‪bool $includeExtFileResources
Definition: Export.php:79
‪TYPO3\CMS\Impexp\Export\getLevels
‪getLevels()
Definition: Export.php:1333
‪TYPO3\CMS\Impexp\Export\setLevels
‪setLevels(int $levels)
Definition: Export.php:1338
‪TYPO3\CMS\Impexp\Export\setPageTree
‪setPageTree(array $pageTree)
Definition: Export.php:335
‪TYPO3\CMS\Impexp\ImportExport
Definition: ImportExport.php:46
‪TYPO3\CMS\Impexp\Export\createXML
‪string createXML()
Definition: Export.php:1053
‪TYPO3\CMS\Impexp\Export\LEVELS_RECORDS_ON_THIS_PAGE
‪const LEVELS_RECORDS_ON_THIS_PAGE
Definition: Export.php:53
‪TYPO3\CMS\Impexp\Export\exportAddFile
‪exportAddFile(array $fileData)
Definition: Export.php:930
‪TYPO3\CMS\Impexp\ImportExport\$relStaticTables
‪array $relStaticTables
Definition: ImportExport.php:119
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Core\Serializer\Typo3XmlParserOptions
Definition: Typo3XmlParserOptions.php:24
‪TYPO3\CMS\Impexp\Export\removeExcludedPagesFromPageTree
‪removeExcludedPagesFromPageTree(array &$pageTree)
Definition: Export.php:345
‪TYPO3\CMS\Impexp\ImportExport\flatInversePageTree
‪flatInversePageTree(array $pageTree, array &$list, int $pid=-1)
Definition: ImportExport.php:1120
‪TYPO3\CMS\Impexp\Export\removeRedundantSoftRefsInRelations
‪removeRedundantSoftRefsInRelations(array $relations)
Definition: Export.php:602
‪TYPO3\CMS\Impexp\Export\isSaveFilesOutsideExportFile
‪isSaveFilesOutsideExportFile()
Definition: Export.php:1389
‪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:1166
‪$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:665
‪TYPO3\CMS\Impexp\Export\FILETYPE_T3DZ
‪const FILETYPE_T3DZ
Definition: Export.php:58
‪TYPO3\CMS\Impexp\Export\setDescription
‪setDescription(string $description)
Definition: Export.php:1298
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Impexp\Export\exportAddRecordsFromRelationsPushRelation
‪exportAddRecordsFromRelationsPushRelation(array $recordData, array &$addRecords, string $tokenID='')
Definition: Export.php:823
‪TYPO3\CMS\Impexp\Export\getNotes
‪getNotes()
Definition: Export.php:1303
‪TYPO3\CMS\Impexp\Export
Definition: Export.php:52
‪TYPO3\CMS\Core\Localization\Locale
Definition: Locale.php:30
‪TYPO3\CMS\Core\Resource\Exception\InsufficientFolderWritePermissionsException
Definition: InsufficientFolderWritePermissionsException.php:21
‪TYPO3\CMS\Impexp\ImportExport\$excludeMap
‪array $excludeMap
Definition: ImportExport.php:124
‪TYPO3\CMS\Impexp\Export\setTables
‪setTables(array $tables)
Definition: Export.php:1348
‪TYPO3\CMS\Impexp\Export\getList
‪getList()
Definition: Export.php:1323
‪TYPO3\CMS\Impexp\Export\setRecord
‪setRecord(array $record)
Definition: Export.php:1318
‪TYPO3\CMS\Redirects\Message\description
‪identifier description
Definition: RedirectWasHitMessage.php:32
‪TYPO3\CMS\Impexp\Export\addFilePart
‪string addFilePart(string $data)
Definition: Export.php:1152
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Impexp\Export\setIncludeExtFileResources
‪setIncludeExtFileResources(bool $includeExtFileResources)
Definition: Export.php:1373
‪TYPO3\CMS\Impexp\Export\$defaultRecordIncludeFields
‪array $defaultRecordIncludeFields
Definition: Export.php:92
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Impexp\Export\getTreeHTML
‪getTreeHTML()
Definition: Export.php:1363
‪TYPO3\CMS\Impexp\Export\$tables
‪array $tables
Definition: Export.php:67
‪TYPO3\CMS\Impexp\ImportExport\removeTemporaryFolderName
‪removeTemporaryFolderName()
Definition: ImportExport.php:1013
‪TYPO3\CMS\Impexp\Export\setMetaData
‪setMetaData()
Definition: Export.php:306
‪TYPO3\CMS\Impexp\ImportExport\isRecordExcluded
‪bool isRecordExcluded(string $table, int $uid)
Definition: ImportExport.php:1155
‪TYPO3\CMS\Impexp
‪TYPO3\CMS\Impexp\ImportExport\getBackendUser
‪getBackendUser()
Definition: ImportExport.php:1324
‪TYPO3\CMS\Impexp\Export\isIncludeExtFileResources
‪isIncludeExtFileResources()
Definition: Export.php:1368
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:39