/** * 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->presetRepository->processPresets($inData); // Create export object and configure it: $this->export = GeneralUtility::makeInstance(Export::class); $this->export->init(0); $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']); // 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(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(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(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(); $lang = $this->getLanguageService(); 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($lang->getLL('exportdata_savedInSBytes'), $file->getPublicUrl(), GeneralUtility::formatSize(strlen($out))), $lang->getLL('exportdata_savedFile'), FlashMessage::OK); } else { /** @var FlashMessage $flashMessage */ $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, sprintf($lang->getLL('exportdata_badPathS'), $saveFolder->getPublicUrl()), $lang->getLL('exportdata_problemsSavingFile'), FlashMessage::ERROR); } /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */ $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class); /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */ $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier(); $defaultFlashMessageQueue->enqueue($flashMessage); } } $this->makeConfigurationForm($inData); $this->makeSaveForm($inData); $this->makeAdvancedOptionsForm($inData); // Print errors that might be: $errors = $this->export->printErrorLog(); $this->standaloneView->assign('errors', trim($errors)); // Generate overview: $this->standaloneView->assign('contentOverview', $this->export->displayContentOverview()); }
/** * Create configuration form * * @param array $inData Form configurat data * @param array $row Table row accumulation variable. This is filled with table rows. * @return void Sets content in $this->content */ public function makeSaveForm($inData, &$row) { // Presets: $row[] = ' <tr class="tableheader bgColor5"> <td colspan="2">' . $this->lang->getLL('makesavefo_presets', true) . '</td> </tr>'; $row[] = ' <tr class="bgColor4"> <td><strong>' . $this->lang->getLL('makesavefo_presets', true) . '</strong>' . BackendUtility::cshItem('xMOD_tx_impexp', 'presets') . '</td> <td> ' . $this->lang->getLL('makesavefo_selectPreset', true) . '<br/> ' . $this->renderSelectBox('preset[select]', '', $this->presetRepository->getPresets($inData['pagetree']['id'])) . ' <br/> <input type="hidden" name="not-set" value="1" id="t3js-submit-field" /> <input class="btn btn-default" type="submit" value="' . $this->lang->getLL('makesavefo_load', true) . '" name="preset[load]" /> <input class="btn btn-default t3js-confirm-trigger" type="button" value="' . $this->lang->getLL('makesavefo_save', true) . '" name="preset[save]" data-title="' . $this->lang->getLL('pleaseConfirm', true) . '" data-message="' . $this->lang->getLL('makesavefo_areYouSure', true) . '" /> <input class="btn btn-default t3js-confirm-trigger" type="button" value="' . $this->lang->getLL('makesavefo_delete', true) . '" name="preset[delete]" data-title="' . $this->lang->getLL('pleaseConfirm', true) . '" data-message="' . $this->lang->getLL('makesavefo_areYouSure', true) . '" /> <input class="btn btn-default t3js-confirm-trigger" type="button" value="' . $this->lang->getLL('makesavefo_merge', true) . '" name="preset[merge]" data-title="' . $this->lang->getLL('pleaseConfirm', true) . '" data-message="' . $this->lang->getLL('makesavefo_areYouSure', true) . '" /> <br/> ' . $this->lang->getLL('makesavefo_titleOfNewPreset', true) . ' <input type="text" name="tx_impexp[preset][title]" value="' . htmlspecialchars($inData['preset']['title']) . '" /><br/> <label for="checkPresetPublic">' . $this->lang->getLL('makesavefo_public', true) . '</label> <input type="checkbox" name="tx_impexp[preset][public]" id="checkPresetPublic" value="1" ' . ($inData['preset']['public'] ? 'checked="checked "' : '') . '/><br/> </td> </tr>'; // Output options: $row[] = ' <tr class="tableheader bgColor5"> <td colspan="2">' . $this->lang->getLL('makesavefo_outputOptions', true) . '</td> </tr>'; $saveFolder = $this->getDefaultImportExportFolder(); $row[] = ' <tr class="bgColor4"> <td><strong>' . $this->lang->getLL('makesavefo_metaData', true) . '</strong>' . BackendUtility::cshItem('xMOD_tx_impexp', 'metadata') . '</td> <td> ' . $this->lang->getLL('makesavefo_title', true) . ' <br/> <input type="text" name="tx_impexp[meta][title]" value="' . htmlspecialchars($inData['meta']['title']) . '" /><br/> ' . $this->lang->getLL('makesavefo_description', true) . ' <br/> <input type="text" name="tx_impexp[meta][description]" value="' . htmlspecialchars($inData['meta']['description']) . '" /><br/> ' . $this->lang->getLL('makesavefo_notes', true) . ' <br/> <textarea name="tx_impexp[meta][notes]">' . htmlspecialchars($inData['meta']['notes']) . '</textarea><br/> ' . ($saveFolder ? ' <input type="hidden" name="file[upload][1][target]" value="' . htmlspecialchars($saveFolder->getCombinedIdentifier()) . '" /> <input type="hidden" name="file[upload][1][data]" value="1" /><br />' : '') . ' </td> </tr>'; // Add file options: $opt = array(); if ($this->export->compress) { $opt['t3d_compressed'] = $this->lang->getLL('makesavefo_t3dFileCompressed'); } $opt['t3d'] = $this->lang->getLL('makesavefo_t3dFile'); $opt['xml'] = $this->lang->getLL('makesavefo_xml'); $fileName = ''; if ($saveFolder) { $fileName = sprintf($this->lang->getLL('makesavefo_filenameSavedInS', true), $saveFolder->getPublicUrl()) . '<br/> <input type="text" name="tx_impexp[filename]" value="' . htmlspecialchars($inData['filename']) . '" /><br/>'; } $row[] = ' <tr> <td> <strong>' . $this->lang->getLL('makesavefo_fileFormat', true) . '</strong>' . BackendUtility::cshItem('xMOD_tx_impexp', 'fileFormat') . ' </td> <td> ' . $this->renderSelectBox('tx_impexp[filetype]', $inData['filetype'], $opt) . '<br/> ' . $this->lang->getLL('makesavefo_maxSizeOfFiles', true) . '<br/> <input type="text" name="tx_impexp[maxFileSize]" value="' . htmlspecialchars($inData['maxFileSize']) . '" /> <br/> ' . $fileName . ' </td> </tr>'; // Add buttons: $row[] = ' <tr> <td> </td> <td> <input class="btn btn-default" type="submit" value="' . $this->lang->getLL('makesavefo_update', true) . '" /> - <input class="btn btn-default" type="submit" value="' . $this->lang->getLL('makesavefo_downloadExport', true) . '" name="tx_impexp[download_export]" /> ' . ($saveFolder ? ' - <input class="btn btn-default" type="submit" value="' . $this->lang->getLL('importdata_saveToFilename', true) . '" name="tx_impexp[save_export]" />' : '') . ' </td> </tr>'; }