/** * Export part of module * Setting content in $this->content * * @param array $inData Content of POST VAR tx_impexp[].. * @throws \InvalidArgumentException * @throws \RuntimeException * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException * @return void */ public function exportData($inData) { // BUILDING EXPORT DATA: // Processing of InData array values: $inData['pagetree']['maxNumber'] = MathUtility::forceIntegerInRange($inData['pagetree']['maxNumber'], 1, 1000000, 100); $inData['listCfg']['maxNumber'] = MathUtility::forceIntegerInRange($inData['listCfg']['maxNumber'], 1, 1000000, 100); $inData['maxFileSize'] = MathUtility::forceIntegerInRange($inData['maxFileSize'], 1, 1000000, 1000); $inData['filename'] = trim(preg_replace('/[^[:alnum:]._-]*/', '', preg_replace('/\\.(t3d|xml)$/', '', $inData['filename']))); if (strlen($inData['filename'])) { $inData['filename'] .= $inData['filetype'] == 'xml' ? '.xml' : '.t3d'; } // Set exclude fields in export object: if (!is_array($inData['exclude'])) { $inData['exclude'] = array(); } // Saving/Loading/Deleting presets: $this->processPresets($inData); // Create export object and configure it: $this->export = GeneralUtility::makeInstance(\TYPO3\CMS\Impexp\ImportExport::class); $this->export->init(0, 'export'); $this->export->setCharset($this->lang->charSet); $this->export->maxFileSize = $inData['maxFileSize'] * 1024; $this->export->excludeMap = (array) $inData['exclude']; $this->export->softrefCfg = (array) $inData['softrefCfg']; $this->export->extensionDependencies = (array) $inData['extension_dep']; $this->export->showStaticRelations = $inData['showStaticRelations']; $this->export->includeExtFileResources = !$inData['excludeHTMLfileResources']; // Static tables: if (is_array($inData['external_static']['tables'])) { $this->export->relStaticTables = $inData['external_static']['tables']; } // Configure which tables external relations are included for: if (is_array($inData['external_ref']['tables'])) { $this->export->relOnlyTables = $inData['external_ref']['tables']; } $saveFilesOutsideExportFile = false; if (isset($inData['save_export']) && isset($inData['saveFilesOutsideExportFile']) && $inData['saveFilesOutsideExportFile'] === '1') { $this->export->setSaveFilesOutsideExportFile(true); $saveFilesOutsideExportFile = true; } $this->export->setHeaderBasics(); // Meta data setting: $beUser = $this->getBackendUser(); $this->export->setMetaData($inData['meta']['title'], $inData['meta']['description'], $inData['meta']['notes'], $beUser->user['username'], $beUser->user['realName'], $beUser->user['email']); if ($inData['meta']['thumbnail']) { $theThumb = $this->getFile($inData['meta']['thumbnail']); if ($theThumb !== null && $theThumb->exists()) { $this->export->addThumbnail($theThumb->getForLocalProcessing(false)); } } // Configure which records to export if (is_array($inData['record'])) { foreach ($inData['record'] as $ref) { $rParts = explode(':', $ref); $this->export->export_addRecord($rParts[0], BackendUtility::getRecord($rParts[0], $rParts[1])); } } // Configure which tables to export if (is_array($inData['list'])) { $db = $this->getDatabaseConnection(); foreach ($inData['list'] as $ref) { $rParts = explode(':', $ref); if ($beUser->check('tables_select', $rParts[0])) { $res = $this->exec_listQueryPid($rParts[0], $rParts[1], MathUtility::forceIntegerInRange($inData['listCfg']['maxNumber'], 1)); while ($subTrow = $db->sql_fetch_assoc($res)) { $this->export->export_addRecord($rParts[0], $subTrow); } $db->sql_free_result($res); } } } // Pagetree if (isset($inData['pagetree']['id'])) { // Based on click-expandable tree $idH = null; if ($inData['pagetree']['levels'] == -1) { $pagetree = GeneralUtility::makeInstance(\TYPO3\CMS\Impexp\View\ExportPageTreeView::class); $tree = $pagetree->ext_tree($inData['pagetree']['id'], $this->filterPageIds($this->export->excludeMap)); $this->treeHTML = $pagetree->printTree($tree); $idH = $pagetree->buffer_idH; } elseif ($inData['pagetree']['levels'] == -2) { $this->addRecordsForPid($inData['pagetree']['id'], $inData['pagetree']['tables'], $inData['pagetree']['maxNumber']); } else { // Based on depth // Drawing tree: // If the ID is zero, export root if (!$inData['pagetree']['id'] && $beUser->isAdmin()) { $sPage = array('uid' => 0, 'title' => 'ROOT'); } else { $sPage = BackendUtility::getRecordWSOL('pages', $inData['pagetree']['id'], '*', ' AND ' . $this->perms_clause); } if (is_array($sPage)) { $pid = $inData['pagetree']['id']; $tree = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\View\PageTreeView::class); $tree->init('AND ' . $this->perms_clause . $this->filterPageIds($this->export->excludeMap)); $HTML = $this->iconFactory->getIconForRecord('pages', $sPage, Icon::SIZE_SMALL)->render(); $tree->tree[] = array('row' => $sPage, 'HTML' => $HTML); $tree->buffer_idH = array(); if ($inData['pagetree']['levels'] > 0) { $tree->getTree($pid, $inData['pagetree']['levels'], ''); } $idH = array(); $idH[$pid]['uid'] = $pid; if (!empty($tree->buffer_idH)) { $idH[$pid]['subrow'] = $tree->buffer_idH; } $pagetree = GeneralUtility::makeInstance(\TYPO3\CMS\Impexp\View\ExportPageTreeView::class); $this->treeHTML = $pagetree->printTree($tree->tree); $this->shortcutName .= ' (' . $sPage['title'] . ')'; } } // In any case we should have a multi-level array, $idH, with the page structure // here (and the HTML-code loaded into memory for nice display...) if (is_array($idH)) { // Sets the pagetree and gets a 1-dim array in return with the pages (in correct submission order BTW...) $flatList = $this->export->setPageTree($idH); foreach ($flatList as $k => $value) { $this->export->export_addRecord('pages', BackendUtility::getRecord('pages', $k)); $this->addRecordsForPid($k, $inData['pagetree']['tables'], $inData['pagetree']['maxNumber']); } } } // After adding ALL records we set relations: for ($a = 0; $a < 10; $a++) { $addR = $this->export->export_addDBRelations($a); if (empty($addR)) { break; } } // Finally files are added: // MUST be after the DBrelations are set so that files from ALL added records are included! $this->export->export_addFilesFromRelations(); $this->export->export_addFilesFromSysFilesRecords(); // If the download button is clicked, return file if ($inData['download_export'] || $inData['save_export']) { switch ((string) $inData['filetype']) { case 'xml': $out = $this->export->compileMemoryToFileContent('xml'); $fExt = '.xml'; break; case 't3d': $this->export->dontCompress = 1; // intentional fall-through // intentional fall-through default: $out = $this->export->compileMemoryToFileContent(); $fExt = ($this->export->doOutputCompress() ? '-z' : '') . '.t3d'; } // Filename: $dlFile = $inData['filename']; if (!$dlFile) { $exportName = substr(preg_replace('/[^[:alnum:]_]/', '-', $inData['download_export_name']), 0, 20); $dlFile = 'T3D_' . $exportName . '_' . date('Y-m-d_H-i') . $fExt; } // Export for download: if ($inData['download_export']) { $mimeType = 'application/octet-stream'; Header('Content-Type: ' . $mimeType); Header('Content-Length: ' . strlen($out)); Header('Content-Disposition: attachment; filename=' . basename($dlFile)); echo $out; die; } // Export by saving: if ($inData['save_export']) { $saveFolder = $this->getDefaultImportExportFolder(); if ($saveFolder !== false && $saveFolder->checkActionPermission('write')) { $temporaryFileName = GeneralUtility::tempnam('export'); file_put_contents($temporaryFileName, $out); $file = $saveFolder->addFile($temporaryFileName, $dlFile, 'replace'); if ($saveFilesOutsideExportFile) { $filesFolderName = $dlFile . '.files'; $filesFolder = $saveFolder->createFolder($filesFolderName); $temporaryFolderForExport = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->export->getTemporaryFilesPathForExport()); $temporaryFilesForExport = $temporaryFolderForExport->getFiles(); foreach ($temporaryFilesForExport as $temporaryFileForExport) { $filesFolder->getStorage()->moveFile($temporaryFileForExport, $filesFolder); } $temporaryFolderForExport->delete(); } /** @var FlashMessage $flashMessage */ $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, sprintf($GLOBALS['LANG']->getLL('exportdata_savedInSBytes', true), $file->getPublicUrl(), GeneralUtility::formatSize(strlen($out))), $GLOBALS['LANG']->getLL('exportdata_savedFile'), FlashMessage::OK); } else { /** @var FlashMessage $flashMessage */ $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, sprintf($GLOBALS['LANG']->getLL('exportdata_badPathS', true), $saveFolder->getPublicUrl()), $GLOBALS['LANG']->getLL('exportdata_problemsSavingFile'), FlashMessage::ERROR); } $this->content .= $flashMessage->render(); } } // OUTPUT to BROWSER: // Now, if we didn't make download file, show configuration form based on export: $menuItems = array(); // Export configuration $row = array(); $this->makeConfigurationForm($inData, $row); $menuItems[] = array('label' => $this->lang->getLL('tableselec_configuration'), 'content' => ' <table border="0" cellpadding="1" cellspacing="1"> ' . implode(' ', $row) . ' </table> '); // File options $row = array(); $this->makeSaveForm($inData, $row); $menuItems[] = array('label' => $this->lang->getLL('exportdata_filePreset'), 'content' => ' <table border="0" cellpadding="1" cellspacing="1"> ' . implode(' ', $row) . ' </table> '); // File options $row = array(); $this->makeAdvancedOptionsForm($inData, $row); $menuItems[] = array('label' => $this->lang->getLL('exportdata_advancedOptions'), 'content' => ' <table border="0" cellpadding="1" cellspacing="1"> ' . implode(' ', $row) . ' </table> '); // Generate overview: $overViewContent = $this->export->displayContentOverview(); // Print errors that might be: $errors = $this->export->printErrorLog(); $menuItems[] = array('label' => $this->lang->getLL('exportdata_messages'), 'content' => $errors, 'stateIcon' => $errors ? 2 : 0); // Add hidden fields and create tabs: $content = $this->moduleTemplate->getDynamicTabMenu($menuItems, 'tx_impexp_export', 1, false, true, false); $content .= '<input type="hidden" name="tx_impexp[action]" value="export" />'; $this->content .= $this->moduleTemplate->section('', $content, 0, 1); // Output Overview: $this->content .= $this->moduleTemplate->section($this->lang->getLL('execlistqu_structureToBeExported'), $overViewContent, 0, 1); }