15574aad1fbec54f8239be7fcf6798728f604d09
[Packages/TYPO3.CMS.git] / typo3 / sysext / impexp / Classes / Controller / ImportExportController.php
1 <?php
2 namespace TYPO3\CMS\Impexp\Controller;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Utility\IconUtility;
18 use TYPO3\CMS\Core\Database\DatabaseConnection;
19 use TYPO3\CMS\Core\Page\PageRenderer;
20 use TYPO3\CMS\Core\Resource\ResourceFactory;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22 use TYPO3\CMS\Backend\Utility\BackendUtility;
23 use TYPO3\CMS\Core\Utility\MathUtility;
24 use TYPO3\CMS\Core\Utility\PathUtility;
25 use TYPO3\CMS\Lang\LanguageService;
26
27 /**
28 * Main script class for the Import / Export facility
29 */
30 class ImportExportController extends \TYPO3\CMS\Backend\Module\BaseScriptClass {
31
32 /**
33 * @var array|\TYPO3\CMS\Core\Resource\File[]
34 */
35 protected $uploadedFiles = array();
36
37 /**
38 * Array containing the current page.
39 *
40 * @var array
41 */
42 public $pageinfo;
43
44 /**
45 * @var \TYPO3\CMS\Impexp\ImportExport
46 */
47 protected $export;
48
49 /**
50 * @var \TYPO3\CMS\Impexp\ImportExport
51 */
52 protected $import;
53
54 /**
55 * @var \TYPO3\CMS\Core\Utility\File\ExtendedFileUtility
56 */
57 protected $fileProcessor;
58
59 /**
60 * @var string
61 */
62 protected $vC = '';
63
64 /**
65 * @var LanguageService
66 */
67 protected $lang = NULL;
68
69 /**
70 * @var string
71 */
72 protected $treeHTML = '';
73
74 /**
75 * @return void
76 */
77 public function init() {
78 parent::init();
79 $this->vC = GeneralUtility::_GP('vC');
80 $this->lang = $this->getLanguageService();
81 }
82
83 /**
84 * Main module function
85 *
86 * @throws \BadFunctionCallException
87 * @throws \InvalidArgumentException
88 * @return void
89 */
90 public function main() {
91 $this->lang->includeLLFile('EXT:impexp/Resources/Private/Language/locallang.xlf');
92 // Start document template object:
93 $this->doc = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
94 $this->doc->backPath = $GLOBALS['BACK_PATH'];
95 $this->doc->bodyTagId = 'imp-exp-mod';
96 $this->doc->setModuleTemplate(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('impexp') . '/Resources/Private/Templates/template.html');
97 $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
98 // Setting up the context sensitive menu:
99 $this->doc->getContextMenuCode();
100 $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
101 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Impexp/ImportExport');
102 $this->doc->postCode = $this->doc->wrapScriptTags('if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';');
103 $this->doc->form = '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl('xMOD_tximpexp')) . '" method="post" enctype="multipart/form-data">'
104 . '<input type="hidden" name="id" value="' . $this->id . '" />';
105 $this->content .= $this->doc->header($this->lang->getLL('title'));
106 $this->content .= $this->doc->spacer(5);
107 // Input data grabbed:
108 $inData = GeneralUtility::_GP('tx_impexp');
109 $this->checkUpload();
110 switch ((string)$inData['action']) {
111 case 'export':
112 // Finally: If upload went well, set the new file as the thumbnail in the $inData array:
113 if (!empty($this->uploadedFiles[0])) {
114 $inData['meta']['thumbnail'] = $this->uploadedFiles[0]->getCombinedIdentifier();
115 }
116 // Call export interface
117 $this->exportData($inData);
118 break;
119 case 'import':
120 // Finally: If upload went well, set the new file as the import file:
121 if (!empty($this->uploadedFiles[0])) {
122 // Only allowed extensions....
123 if (GeneralUtility::inList('t3d,xml', $this->uploadedFiles[0]->getExtension())) {
124 $inData['file'] = $this->uploadedFiles[0]->getCombinedIdentifier();
125 }
126 }
127 // Call import interface:
128 $this->importData($inData);
129 break;
130 }
131 // Setting up the buttons and markers for docheader
132 $docHeaderButtons = $this->getButtons();
133 $markers['CONTENT'] = $this->content;
134 // Build the <body> for the module
135 $this->content = $this->doc->startPage($this->lang->getLL('title'));
136 $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
137 $this->content .= $this->doc->endPage();
138 $this->content = $this->doc->insertStylesAndJS($this->content);
139 }
140
141 /**
142 * Print the content
143 *
144 * @return void
145 */
146 public function printContent() {
147 echo $this->content;
148 }
149
150 /**
151 * Create the panel of buttons for submitting the form or otherwise perform operations.
152 *
153 * @return array all available buttons as an associated array
154 */
155 protected function getButtons() {
156 $buttons = array(
157 'view' => '',
158 'shortcut' => ''
159 );
160 if ($this->getBackendUser()->mayMakeShortcut()) {
161 $buttons['shortcut'] = $this->doc->makeShortcutIcon('tx_impexp', '', $this->MCONF['name']);
162 }
163 // Input data grabbed:
164 $inData = GeneralUtility::_GP('tx_impexp');
165 if ((string)$inData['action'] == 'import') {
166 if ($this->id && is_array($this->pageinfo) || $this->getBackendUser()->user['admin'] && !$this->id) {
167 if (is_array($this->pageinfo) && $this->pageinfo['uid']) {
168 // View
169 $onClick = BackendUtility::viewOnClick(
170 $this->pageinfo['uid'],
171 $this->doc->backPath,
172 BackendUtility::BEgetRootLine($this->pageinfo['uid'])
173 );
174 $title = $this->lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.showPage', TRUE);
175 $buttons['view'] = '<a href="#" onclick="' . htmlspecialchars($onClick) . '" title="' . $title . '">'
176 . IconUtility::getSpriteIcon('actions-document-view') . '</a>';
177 }
178 }
179 }
180 return $buttons;
181 }
182
183 /**************************
184 * EXPORT FUNCTIONS
185 **************************/
186
187 /**
188 * Export part of module
189 * Setting content in $this->content
190 *
191 * @param array $inData Content of POST VAR tx_impexp[]..
192 * @throws \InvalidArgumentException
193 * @throws \RuntimeException
194 * @throws \TYPO3\CMS\Core\Resource\Exception\ExistingTargetFileNameException
195 * @return void
196 */
197 public function exportData($inData) {
198 // BUILDING EXPORT DATA:
199 // Processing of InData array values:
200 $inData['pagetree']['maxNumber'] = MathUtility::forceIntegerInRange($inData['pagetree']['maxNumber'], 1, 1000000, 100);
201 $inData['listCfg']['maxNumber'] = MathUtility::forceIntegerInRange($inData['listCfg']['maxNumber'], 1, 1000000, 100);
202 $inData['maxFileSize'] = MathUtility::forceIntegerInRange($inData['maxFileSize'], 1, 1000000, 1000);
203 $inData['filename'] = trim(preg_replace('/[^[:alnum:]._-]*/', '', preg_replace('/\\.(t3d|xml)$/', '', $inData['filename'])));
204 if (strlen($inData['filename'])) {
205 $inData['filename'] .= $inData['filetype'] == 'xml' ? '.xml' : '.t3d';
206 }
207 // Set exclude fields in export object:
208 if (!is_array($inData['exclude'])) {
209 $inData['exclude'] = array();
210 }
211 // Saving/Loading/Deleting presets:
212 $this->processPresets($inData);
213 // Create export object and configure it:
214 $this->export = GeneralUtility::makeInstance(\TYPO3\CMS\Impexp\ImportExport::class);
215 $this->export->init(0, 'export');
216 $this->export->setCharset($this->lang->charSet);
217 $this->export->maxFileSize = $inData['maxFileSize'] * 1024;
218 $this->export->excludeMap = (array)$inData['exclude'];
219 $this->export->softrefCfg = (array)$inData['softrefCfg'];
220 $this->export->extensionDependencies = (array)$inData['extension_dep'];
221 $this->export->showStaticRelations = $inData['showStaticRelations'];
222 $this->export->includeExtFileResources = !$inData['excludeHTMLfileResources'];
223 // Static tables:
224 if (is_array($inData['external_static']['tables'])) {
225 $this->export->relStaticTables = $inData['external_static']['tables'];
226 }
227 // Configure which tables external relations are included for:
228 if (is_array($inData['external_ref']['tables'])) {
229 $this->export->relOnlyTables = $inData['external_ref']['tables'];
230 }
231 $saveFilesOutsideExportFile = FALSE;
232 if (isset($inData['save_export']) && isset($inData['saveFilesOutsideExportFile']) && $inData['saveFilesOutsideExportFile'] === '1') {
233 $this->export->setSaveFilesOutsideExportFile(TRUE);
234 $saveFilesOutsideExportFile = TRUE;
235 }
236 $this->export->setHeaderBasics();
237 // Meta data setting:
238
239 $beUser = $this->getBackendUser();
240 $this->export->setMetaData(
241 $inData['meta']['title'],
242 $inData['meta']['description'],
243 $inData['meta']['notes'],
244 $beUser->user['username'],
245 $beUser->user['realName'],
246 $beUser->user['email']
247 );
248 if ($inData['meta']['thumbnail']) {
249 $theThumb = $this->getFile($inData['meta']['thumbnail']);
250 if ($theThumb !== NULL && $theThumb->exists()) {
251 $this->export->addThumbnail($theThumb->getForLocalProcessing(FALSE));
252 }
253 }
254 // Configure which records to export
255 if (is_array($inData['record'])) {
256 foreach ($inData['record'] as $ref) {
257 $rParts = explode(':', $ref);
258 $this->export->export_addRecord($rParts[0], BackendUtility::getRecord($rParts[0], $rParts[1]));
259 }
260 }
261 // Configure which tables to export
262 if (is_array($inData['list'])) {
263 $db = $this->getDatabaseConnection();
264 foreach ($inData['list'] as $ref) {
265 $rParts = explode(':', $ref);
266 if ($beUser->check('tables_select', $rParts[0])) {
267 $res = $this->exec_listQueryPid($rParts[0], $rParts[1], MathUtility::forceIntegerInRange($inData['listCfg']['maxNumber'], 1));
268 while ($subTrow = $db->sql_fetch_assoc($res)) {
269 $this->export->export_addRecord($rParts[0], $subTrow);
270 }
271 $db->sql_free_result($res);
272 }
273 }
274 }
275 // Pagetree
276 if (isset($inData['pagetree']['id'])) {
277 // Based on click-expandable tree
278 $idH = NULL;
279 if ($inData['pagetree']['levels'] == -1) {
280 $pagetree = GeneralUtility::makeInstance(\TYPO3\CMS\Impexp\View\ExportPageTreeView::class);
281 $tree = $pagetree->ext_tree($inData['pagetree']['id'], $this->filterPageIds($this->export->excludeMap));
282 $this->treeHTML = $pagetree->printTree($tree);
283 $idH = $pagetree->buffer_idH;
284 } elseif ($inData['pagetree']['levels'] == -2) {
285 $this->addRecordsForPid($inData['pagetree']['id'], $inData['pagetree']['tables'], $inData['pagetree']['maxNumber']);
286 } else {
287 // Based on depth
288 // Drawing tree:
289 // If the ID is zero, export root
290 if (!$inData['pagetree']['id'] && $beUser->isAdmin()) {
291 $sPage = array(
292 'uid' => 0,
293 'title' => 'ROOT'
294 );
295 } else {
296 $sPage = BackendUtility::getRecordWSOL('pages', $inData['pagetree']['id'], '*', ' AND ' . $this->perms_clause);
297 }
298 if (is_array($sPage)) {
299 $pid = $inData['pagetree']['id'];
300 $tree = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Tree\View\PageTreeView::class);
301 $tree->init('AND ' . $this->perms_clause . $this->filterPageIds($this->export->excludeMap));
302 $HTML = IconUtility::getSpriteIconForRecord('pages', $sPage);
303 $tree->tree[] = array('row' => $sPage, 'HTML' => $HTML);
304 $tree->buffer_idH = array();
305 if ($inData['pagetree']['levels'] > 0) {
306 $tree->getTree($pid, $inData['pagetree']['levels'], '');
307 }
308 $idH = array();
309 $idH[$pid]['uid'] = $pid;
310 if (!empty($tree->buffer_idH)) {
311 $idH[$pid]['subrow'] = $tree->buffer_idH;
312 }
313 $pagetree = GeneralUtility::makeInstance(\TYPO3\CMS\Impexp\View\ExportPageTreeView::class);
314 $this->treeHTML = $pagetree->printTree($tree->tree);
315 }
316 }
317 // In any case we should have a multi-level array, $idH, with the page structure
318 // here (and the HTML-code loaded into memory for nice display...)
319 if (is_array($idH)) {
320 // Sets the pagetree and gets a 1-dim array in return with the pages (in correct submission order BTW...)
321 $flatList = $this->export->setPageTree($idH);
322 foreach ($flatList as $k => $value) {
323 $this->export->export_addRecord('pages', BackendUtility::getRecord('pages', $k));
324 $this->addRecordsForPid($k, $inData['pagetree']['tables'], $inData['pagetree']['maxNumber']);
325 }
326 }
327 }
328 // After adding ALL records we set relations:
329 for ($a = 0; $a < 10; $a++) {
330 $addR = $this->export->export_addDBRelations($a);
331 if (empty($addR)) {
332 break;
333 }
334 }
335 // Finally files are added:
336 // MUST be after the DBrelations are set so that files from ALL added records are included!
337 $this->export->export_addFilesFromRelations();
338
339 $this->export->export_addFilesFromSysFilesRecords();
340
341 // If the download button is clicked, return file
342 if ($inData['download_export'] || $inData['save_export']) {
343 switch ((string)$inData['filetype']) {
344 case 'xml':
345 $out = $this->export->compileMemoryToFileContent('xml');
346 $fExt = '.xml';
347 break;
348 case 't3d':
349 $this->export->dontCompress = 1;
350 // intentional fall-through
351 default:
352 $out = $this->export->compileMemoryToFileContent();
353 $fExt = ($this->export->doOutputCompress() ? '-z' : '') . '.t3d';
354 }
355 // Filename:
356 $dlFile = $inData['filename'];
357 if (!$dlFile) {
358 $exportName = substr(preg_replace('/[^[:alnum:]_]/', '-', $inData['download_export_name']), 0, 20);
359 $dlFile = 'T3D_' . $exportName . '_' . date('Y-m-d_H-i') . $fExt;
360 }
361
362 // Export for download:
363 if ($inData['download_export']) {
364 $mimeType = 'application/octet-stream';
365 Header('Content-Type: ' . $mimeType);
366 Header('Content-Length: ' . strlen($out));
367 Header('Content-Disposition: attachment; filename=' . basename($dlFile));
368 echo $out;
369 die;
370 }
371 // Export by saving:
372 if ($inData['save_export']) {
373 $saveFolder = $this->getDefaultImportExportFolder();
374 if ($saveFolder !== FALSE && $saveFolder->checkActionPermission('write')) {
375 $temporaryFileName = GeneralUtility::tempnam('export');
376 file_put_contents($temporaryFileName, $out);
377 $file = $saveFolder->addFile($temporaryFileName, $dlFile, 'replace');
378 if ($saveFilesOutsideExportFile) {
379 $filesFolderName = $dlFile . '.files';
380 $filesFolder = $saveFolder->createFolder($filesFolderName);
381 $temporaryFolderForExport = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->export->getTemporaryFilesPathForExport());
382 $temporaryFilesForExport = $temporaryFolderForExport->getFiles();
383 foreach ($temporaryFilesForExport as $temporaryFileForExport) {
384 $filesFolder->getStorage()->moveFile($temporaryFileForExport, $filesFolder);
385 }
386 $temporaryFolderForExport->delete();
387 }
388
389 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('exportdata_savedFile'), sprintf($GLOBALS['LANG']->getLL('exportdata_savedInSBytes', TRUE), $file->getPublicUrl(), GeneralUtility::formatSize(strlen($out))), 0, 1);
390 } else {
391 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('exportdata_problemsSavingFile'), sprintf($GLOBALS['LANG']->getLL('exportdata_badPathS', TRUE), $this->getTemporaryFolderPath()), 0, 1, 2);
392 }
393 }
394 }
395 // OUTPUT to BROWSER:
396 // Now, if we didn't make download file, show configuration form based on export:
397 $menuItems = array();
398 // Export configuration
399 $row = array();
400 $this->makeConfigurationForm($inData, $row);
401 $menuItems[] = array(
402 'label' => $this->lang->getLL('tableselec_configuration'),
403 'content' => '
404 <table border="0" cellpadding="1" cellspacing="1">
405 ' . implode('
406 ', $row) . '
407 </table>
408 '
409 );
410 // File options
411 $row = array();
412 $this->makeSaveForm($inData, $row);
413 $menuItems[] = array(
414 'label' => $this->lang->getLL('exportdata_filePreset'),
415 'content' => '
416 <table border="0" cellpadding="1" cellspacing="1">
417 ' . implode('
418 ', $row) . '
419 </table>
420 '
421 );
422 // File options
423 $row = array();
424 $this->makeAdvancedOptionsForm($inData, $row);
425 $menuItems[] = array(
426 'label' => $this->lang->getLL('exportdata_advancedOptions'),
427 'content' => '
428 <table border="0" cellpadding="1" cellspacing="1">
429 ' . implode('
430 ', $row) . '
431 </table>
432 '
433 );
434 // Generate overview:
435 $overViewContent = $this->export->displayContentOverview();
436 // Print errors that might be:
437 $errors = $this->export->printErrorLog();
438 $menuItems[] = array(
439 'label' => $this->lang->getLL('exportdata_messages'),
440 'content' => $errors,
441 'stateIcon' => $errors ? 2 : 0
442 );
443 // Add hidden fields and create tabs:
444
445 $content = $this->doc->getDynamicTabMenu($menuItems, 'tx_impexp_export', 1, FALSE, TRUE, FALSE);
446 $content .= '<input type="hidden" name="tx_impexp[action]" value="export" />';
447 $this->content .= $this->doc->section('', $content, 0, 1);
448 // Output Overview:
449 $this->content .= $this->doc->section($this->lang->getLL('execlistqu_structureToBeExported'), $overViewContent, 0, 1);
450 }
451
452 /**
453 * Adds records to the export object for a specific page id.
454 *
455 * @param int $k Page id for which to select records to add
456 * @param array $tables Array of table names to select from
457 * @param int $maxNumber Max amount of records to select
458 * @return void
459 */
460 public function addRecordsForPid($k, $tables, $maxNumber) {
461 if (!is_array($tables)) {
462 return;
463 }
464 $db = $this->getDatabaseConnection();
465 foreach ($GLOBALS['TCA'] as $table => $value) {
466 if ($table != 'pages' && (in_array($table, $tables) || in_array('_ALL', $tables))) {
467 if ($this->getBackendUser()->check('tables_select', $table) && !$GLOBALS['TCA'][$table]['ctrl']['is_static']) {
468 $res = $this->exec_listQueryPid($table, $k, MathUtility::forceIntegerInRange($maxNumber, 1));
469 while ($subTrow = $db->sql_fetch_assoc($res)) {
470 $this->export->export_addRecord($table, $subTrow);
471 }
472 $db->sql_free_result($res);
473 }
474 }
475 }
476 }
477
478 /**
479 * Selects records from table / pid
480 *
481 * @param string $table Table to select from
482 * @param int $pid Page ID to select from
483 * @param int $limit Max number of records to select
484 * @return \mysqli_result|object Database resource
485 */
486 public function exec_listQueryPid($table, $pid, $limit) {
487 $db = $this->getDatabaseConnection();
488 $orderBy = $GLOBALS['TCA'][$table]['ctrl']['sortby']
489 ? 'ORDER BY ' . $GLOBALS['TCA'][$table]['ctrl']['sortby']
490 : $GLOBALS['TCA'][$table]['ctrl']['default_sortby'];
491 $res = $db->exec_SELECTquery(
492 '*',
493 $table,
494 'pid=' . (int)$pid . BackendUtility::deleteClause($table) . BackendUtility::versioningPlaceholderClause($table),
495 '',
496 $db->stripOrderBy($orderBy),
497 $limit
498 );
499 // Warning about hitting limit:
500 if ($db->sql_num_rows($res) == $limit) {
501 $limitWarning = sprintf($this->lang->getLL('makeconfig_anSqlQueryReturned', TRUE), $limit);
502 $this->content .= $this->doc->section($this->lang->getLL('execlistqu_maxNumberLimit'), $limitWarning, 0, 1, 2);
503 }
504 return $res;
505 }
506
507 /**
508 * Create configuration form
509 *
510 * @param array $inData Form configurat data
511 * @param array $row Table row accumulation variable. This is filled with table rows.
512 * @return void Sets content in $this->content
513 */
514 public function makeConfigurationForm($inData, &$row) {
515 $nameSuggestion = '';
516 // Page tree export options:
517 if (isset($inData['pagetree']['id'])) {
518 $nameSuggestion .= 'tree_PID' . $inData['pagetree']['id'] . '_L' . $inData['pagetree']['levels'];
519 $row[] = '
520 <tr class="tableheader bgColor5">
521 <td colspan="2">' . $this->lang->getLL('makeconfig_exportPagetreeConfiguration', TRUE)
522 . BackendUtility::cshItem('xMOD_tx_impexp', 'pageTreeCfg') . '</td>
523 </tr>';
524 $row[] = '
525 <tr class="bgColor4">
526 <td><strong>' . $this->lang->getLL('makeconfig_pageId', TRUE) . '</strong></td>
527 <td>' . htmlspecialchars($inData['pagetree']['id']) . '<input type="hidden" value="'
528 . htmlspecialchars($inData['pagetree']['id']) . '" name="tx_impexp[pagetree][id]" /></td>
529 </tr>';
530 $row[] = '
531 <tr class="bgColor4">
532 <td><strong>' . $this->lang->getLL('makeconfig_tree', TRUE) . '</strong>'
533 . BackendUtility::cshItem('xMOD_tx_impexp', 'pageTreeDisplay') . '</td>
534 <td>' . ($this->treeHTML ?: $this->lang->getLL('makeconfig_noTreeExportedOnly', TRUE)) . '</td>
535 </tr>';
536 $opt = array(
537 '-2' => $this->lang->getLL('makeconfig_tablesOnThisPage'),
538 '-1' => $this->lang->getLL('makeconfig_expandedTree'),
539 '0' => $this->lang->getLL('makeconfig_onlyThisPage'),
540 '1' => $this->lang->getLL('makeconfig_1Level'),
541 '2' => $this->lang->getLL('makeconfig_2Levels'),
542 '3' => $this->lang->getLL('makeconfig_3Levels'),
543 '4' => $this->lang->getLL('makeconfig_4Levels'),
544 '999' => $this->lang->getLL('makeconfig_infinite')
545 );
546 $row[] = '
547 <tr class="bgColor4">
548 <td><strong>' . $this->lang->getLL('makeconfig_levels', TRUE) . '</strong>'
549 . BackendUtility::cshItem('xMOD_tx_impexp', 'pageTreeMode') . '</td>
550 <td>' . $this->renderSelectBox('tx_impexp[pagetree][levels]', $inData['pagetree']['levels'], $opt) . '</td>
551 </tr>';
552 $row[] = '
553 <tr class="bgColor4">
554 <td><strong>' . $this->lang->getLL('makeconfig_includeTables', TRUE) . '</strong>'
555 . BackendUtility::cshItem('xMOD_tx_impexp', 'pageTreeRecordLimit') . '</td>
556 <td>' . $this->tableSelector('tx_impexp[pagetree][tables]', $inData['pagetree']['tables'], 'pages') . '<br/>
557 ' . $this->lang->getLL('makeconfig_maxNumberOfRecords', TRUE) . '<br/>
558 <input type="text" name="tx_impexp[pagetree][maxNumber]" value="'
559 . htmlspecialchars($inData['pagetree']['maxNumber']) . '"' . $this->doc->formWidth(10) . ' /><br/>
560 </td>
561 </tr>';
562 }
563 // Single record export:
564 if (is_array($inData['record'])) {
565 $row[] = '
566 <tr class="tableheader bgColor5">
567 <td colspan="2">' . $this->lang->getLL('makeconfig_exportSingleRecord', TRUE)
568 . BackendUtility::cshItem('xMOD_tx_impexp', 'singleRecord') . '</td>
569 </tr>';
570 foreach ($inData['record'] as $ref) {
571 $rParts = explode(':', $ref);
572 $tName = $rParts[0];
573 $rUid = $rParts[1];
574 $nameSuggestion .= $tName . '_' . $rUid;
575 $rec = BackendUtility::getRecordWSOL($tName, $rUid);
576 $row[] = '
577 <tr class="bgColor4">
578 <td><strong>' . $this->lang->getLL('makeconfig_record', TRUE) . '</strong></td>
579 <td>' . IconUtility::getSpriteIconForRecord($tName, $rec) . BackendUtility::getRecordTitle($tName, $rec, TRUE)
580 . '<input type="hidden" name="tx_impexp[record][]" value="' . htmlspecialchars(($tName . ':' . $rUid)) . '" /></td>
581 </tr>';
582 }
583 }
584 // Single tables/pids:
585 if (is_array($inData['list'])) {
586 $row[] = '
587 <tr class="tableheader bgColor5">
588 <td colspan="2">' . $this->lang->getLL('makeconfig_exportTablesFromPages', TRUE) . '</td>
589 </tr>';
590 // Display information about pages from which the export takes place
591 $tblList = '';
592 foreach ($inData['list'] as $reference) {
593 $referenceParts = explode(':', $reference);
594 $tableName = $referenceParts[0];
595 if ($this->getBackendUser()->check('tables_select', $tableName)) {
596 // If the page is actually the root, handle it differently
597 // NOTE: we don't compare integers, because the number actually comes from the split string above
598 if ($referenceParts[1] === '0') {
599 $iconAndTitle = IconUtility::getSpriteIcon('apps-pagetree-root') . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
600 } else {
601 $record = BackendUtility::getRecordWSOL('pages', $referenceParts[1]);
602 $iconAndTitle = IconUtility::getSpriteIconForRecord('pages', $record)
603 . BackendUtility::getRecordTitle('pages', $record, TRUE);
604 }
605 $tblList .= 'Table "' . $tableName . '" from ' . $iconAndTitle
606 . '<input type="hidden" name="tx_impexp[list][]" value="' . htmlspecialchars($reference) . '" /><br/>';
607 }
608 }
609 $row[] = '
610 <tr class="bgColor4">
611 <td><strong>' . $this->lang->getLL('makeconfig_tablePids', TRUE) . '</strong>'
612 . BackendUtility::cshItem('xMOD_tx_impexp', 'tableList') . '</td>
613 <td>' . $tblList . '</td>
614 </tr>';
615 $row[] = '
616 <tr class="bgColor4">
617 <td><strong>' . $this->lang->getLL('makeconfig_maxNumberOfRecords', TRUE)
618 . BackendUtility::cshItem('xMOD_tx_impexp', 'tableListMaxNumber') . '</strong></td>
619 <td>
620 <input type="text" name="tx_impexp[listCfg][maxNumber]" value="'
621 . htmlspecialchars($inData['listCfg']['maxNumber']) . '"' . $this->doc->formWidth(10) . ' /><br/>
622 </td>
623 </tr>';
624 }
625 $row[] = '
626 <tr class="tableheader bgColor5">
627 <td colspan="2">' . $this->lang->getLL('makeconfig_relationsAndExclusions', TRUE) . '</td>
628 </tr>';
629 // Add relation selector:
630 $row[] = '
631 <tr class="bgColor4">
632 <td><strong>' . $this->lang->getLL('makeconfig_includeRelationsToTables', TRUE) . '</strong>'
633 . BackendUtility::cshItem('xMOD_tx_impexp', 'inclRelations') . '</td>
634 <td>' . $this->tableSelector('tx_impexp[external_ref][tables]', $inData['external_ref']['tables']) . '</td>
635 </tr>';
636 // Add static relation selector:
637 $row[] = '
638 <tr class="bgColor4">
639 <td><strong>' . $this->lang->getLL('makeconfig_useStaticRelationsFor', TRUE) . '</strong>'
640 . BackendUtility::cshItem('xMOD_tx_impexp', 'staticRelations') . '</td>
641 <td>' . $this->tableSelector('tx_impexp[external_static][tables]', $inData['external_static']['tables']) . '<br/>
642 <label for="checkShowStaticRelations">' . $this->lang->getLL('makeconfig_showStaticRelations', TRUE)
643 . '</label> <input type="checkbox" name="tx_impexp[showStaticRelations]" id="checkShowStaticRelations" value="1"'
644 . ($inData['showStaticRelations'] ? ' checked="checked"' : '') . ' />
645 </td>
646 </tr>';
647 // Exclude:
648 $excludeHiddenFields = '';
649 if (is_array($inData['exclude'])) {
650 foreach ($inData['exclude'] as $key => $value) {
651 $excludeHiddenFields .= '<input type="hidden" name="tx_impexp[exclude][' . $key . ']" value="1" />';
652 }
653 }
654 if (!empty($inData['exclude'])) {
655 $excludedElements = '<em>' . implode(', ', array_keys($inData['exclude'])) . '</em><hr/><label for="checkExclude">'
656 . $this->lang->getLL('makeconfig_clearAllExclusions', TRUE)
657 . '</label> <input type="checkbox" name="tx_impexp[exclude]" id="checkExclude" value="1" />';
658 } else {
659 $excludedElements = $this->lang->getLL('makeconfig_noExcludedElementsYet', TRUE);
660 }
661 $row[] = '
662 <tr class="bgColor4">
663 <td><strong>' . $this->lang->getLL('makeconfig_excludeElements', TRUE) . '</strong>'
664 . BackendUtility::cshItem('xMOD_tx_impexp', 'excludedElements') . '</td>
665 <td>' . $excludeHiddenFields . '
666 ' . $excludedElements . '
667 </td>
668 </tr>';
669 // Add buttons:
670 $row[] = '
671 <tr class="bgColor4">
672 <td>&nbsp;</td>
673 <td>
674 <input class="btn btn-default" type="submit" value="' . $this->lang->getLL('makeadvanc_update', TRUE) . '" />
675 <input type="hidden" name="tx_impexp[download_export_name]" value="' . substr($nameSuggestion, 0, 30) . '" />
676 </td>
677 </tr>';
678 }
679
680 /**
681 * Create advanced options form
682 * Sets content in $this->content
683 *
684 * @param array $inData Form configurat data
685 * @param array $row Table row accumulation variable. This is filled with table rows.
686 * @return void
687 */
688 public function makeAdvancedOptionsForm($inData, &$row) {
689 // Soft references
690 $row[] = '
691 <tr class="tableheader bgColor5">
692 <td colspan="2">' . $this->lang->getLL('makeadvanc_softReferences', TRUE) . '</td>
693 </tr>';
694 $row[] = '
695 <tr class="bgColor4">
696 <td><label for="checkExcludeHTMLfileResources"><strong>'
697 . $this->lang->getLL('makeadvanc_excludeHtmlCssFile', TRUE) . '</strong></label>'
698 . BackendUtility::cshItem('xMOD_tx_impexp', 'htmlCssResources') . '</td>
699 <td><input type="checkbox" name="tx_impexp[excludeHTMLfileResources]" id="checkExcludeHTMLfileResources" value="1"'
700 . ($inData['excludeHTMLfileResources'] ? ' checked="checked"' : '') . ' /></td>
701 </tr>';
702
703 // Files options
704 $row[] = '
705 <tr class="tableheader bgColor5">
706 <td colspan="2">' . $this->lang->getLL('makeadvanc_files', TRUE) . '</td>
707 </tr>';
708 $row[] = '
709 <tr class="bgColor4">
710 <td><label for="saveFilesOutsideExportFile"><strong>'
711 . $this->lang->getLL('makeadvanc_saveFilesOutsideExportFile', TRUE) . '</strong><br />'
712 . $this->lang->getLL('makeadvanc_saveFilesOutsideExportFile_limit', TRUE) . '</label></td>
713 <td><input type="checkbox" name="tx_impexp[saveFilesOutsideExportFile]" id="saveFilesOutsideExportFile" value="1"'
714 . ($inData['saveFilesOutsideExportFile'] ? ' checked="checked"' : '') . ' /></td>
715 </tr>';
716 // Extensions
717 $row[] = '
718 <tr class="tableheader bgColor5">
719 <td colspan="2">' . $this->lang->getLL('makeadvanc_extensionDependencies', TRUE) . '</td>
720 </tr>';
721 $row[] = '
722 <tr class="bgColor4">
723 <td><strong>' . $this->lang->getLL('makeadvanc_selectExtensionsThatThe', TRUE) . '</strong>'
724 . BackendUtility::cshItem('xMOD_tx_impexp', 'extensionDependencies') . '</td>
725 <td>' . $this->extensionSelector('tx_impexp[extension_dep]', $inData['extension_dep']) . '</td>
726 </tr>';
727 // Add buttons:
728 $row[] = '
729 <tr class="bgColor4">
730 <td>&nbsp;</td>
731 <td>
732 <input class="btn btn-default" type="submit" value="' . $this->lang->getLL('makesavefo_update', TRUE) . '" />
733 <input type="hidden" name="tx_impexp[download_export_name]" value="" />
734 </td>
735 </tr>';
736 }
737
738 /**
739 * Create configuration form
740 *
741 * @param array $inData Form configurat data
742 * @param array $row Table row accumulation variable. This is filled with table rows.
743 * @return void Sets content in $this->content
744 */
745 public function makeSaveForm($inData, &$row) {
746 // Presets:
747 $row[] = '
748 <tr class="tableheader bgColor5">
749 <td colspan="2">' . $this->lang->getLL('makesavefo_presets', TRUE) . '</td>
750 </tr>';
751 $opt = array('');
752 $where = '(public>0 OR user_uid=' . (int)$this->getBackendUser()->user['uid'] . ')'
753 . ($inData['pagetree']['id'] ? ' AND (item_uid=' . (int)$inData['pagetree']['id'] . ' OR item_uid=0)' : '');
754 $presets = $this->getDatabaseConnection()->exec_SELECTgetRows('*', 'tx_impexp_presets', $where);
755 if (is_array($presets)) {
756 foreach ($presets as $presetCfg) {
757 $opt[$presetCfg['uid']] = $presetCfg['title'] . ' [' . $presetCfg['uid'] . ']'
758 . ($presetCfg['public'] ? ' [Public]' : '')
759 . ($presetCfg['user_uid'] === $this->getBackendUser()->user['uid'] ? ' [Own]' : '');
760 }
761 }
762 $row[] = '
763 <tr class="bgColor4">
764 <td><strong>' . $this->lang->getLL('makesavefo_presets', TRUE) . '</strong>'
765 . BackendUtility::cshItem('xMOD_tx_impexp', 'presets') . '</td>
766 <td>
767 ' . $this->lang->getLL('makesavefo_selectPreset', TRUE) . '<br/>
768 ' . $this->renderSelectBox('preset[select]', '', $opt) . '
769 <br/>
770 <input type="hidden" name="not-set" value="1" id="t3js-submit-field" />
771 <input class="btn btn-default" type="submit" value="' . $this->lang->getLL('makesavefo_load', TRUE) . '" name="preset[load]" />
772 <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) . '" />
773 <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) . '" />
774 <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) . '" />
775 <br/>
776 ' . $this->lang->getLL('makesavefo_titleOfNewPreset', TRUE) . '
777 <input type="text" name="tx_impexp[preset][title]" value="'
778 . htmlspecialchars($inData['preset']['title']) . '"' . $this->doc->formWidth(30) . ' /><br/>
779 <label for="checkPresetPublic">' . $this->lang->getLL('makesavefo_public', TRUE) . '</label>
780 <input type="checkbox" name="tx_impexp[preset][public]" id="checkPresetPublic" value="1"'
781 . ($inData['preset']['public'] ? ' checked="checked"' : '') . ' /><br/>
782 </td>
783 </tr>';
784 // Output options:
785 $row[] = '
786 <tr class="tableheader bgColor5">
787 <td colspan="2">' . $this->lang->getLL('makesavefo_outputOptions', TRUE) . '</td>
788 </tr>';
789 // Meta data:
790 $thumbnailFiles = array();
791 foreach ($this->getThumbnailFiles() as $thumbnailFile) {
792 $thumbnailFiles[$thumbnailFile->getCombinedIdentifier()] = $thumbnailFile->getName();
793 }
794 if (!empty($thumbnailFiles)) {
795 array_unshift($thumbnailFiles, '');
796 }
797 $thumbnail = NULL;
798 if (!empty($inData['meta']['thumbnail'])) {
799 $thumbnail = $this->getFile($inData['meta']['thumbnail']);
800 }
801 $saveFolder = $this->getDefaultImportExportFolder();
802
803 $row[] = '
804 <tr class="bgColor4">
805 <td><strong>' . $this->lang->getLL('makesavefo_metaData', TRUE) . '</strong>'
806 . BackendUtility::cshItem('xMOD_tx_impexp', 'metadata') . '</td>
807 <td>
808 ' . $this->lang->getLL('makesavefo_title', TRUE) . ' <br/>
809 <input type="text" name="tx_impexp[meta][title]" value="' . htmlspecialchars($inData['meta']['title']) . '"' . $this->doc->formWidth(30) . ' /><br/>
810 ' . $this->lang->getLL('makesavefo_description', TRUE) . ' <br/>
811 <input type="text" name="tx_impexp[meta][description]" value="' . htmlspecialchars($inData['meta']['description']) . '"' . $this->doc->formWidth(30) . ' /><br/>
812 ' . $this->lang->getLL('makesavefo_notes', TRUE) . ' <br/>
813 <textarea name="tx_impexp[meta][notes]"' . $this->doc->formWidth(30, 1) . '>' . htmlspecialchars($inData['meta']['notes']) . '</textarea><br/>
814 ' . (!empty($thumbnailFiles) ? '
815 ' . $this->lang->getLL('makesavefo_thumbnail', TRUE) . '<br/>
816 ' . $this->renderSelectBox('tx_impexp[meta][thumbnail]', $inData['meta']['thumbnail'], $thumbnailFiles) : '') . '<br/>
817 ' . ($thumbnail ? '<img src="' . htmlspecialchars($thumbnail->getPublicUrl(TRUE)) . '" vspace="5" style="border: solid black 1px;" alt="" /><br/>' : '') . '
818 ' . $this->lang->getLL('makesavefo_uploadThumbnail', TRUE) . '<br/>
819 ' . ($saveFolder ? '<input type="file" name="upload_1" ' . $this->doc->formWidth(30) . ' size="30" /><br/>
820 <input type="hidden" name="file[upload][1][target]" value="' . htmlspecialchars($saveFolder->getCombinedIdentifier()) . '" />
821 <input type="hidden" name="file[upload][1][data]" value="1" /><br />' : '') . '
822 </td>
823 </tr>';
824 // Add file options:
825 $opt = array();
826 if ($this->export->compress) {
827 $opt['t3d_compressed'] = $this->lang->getLL('makesavefo_t3dFileCompressed');
828 }
829 $opt['t3d'] = $this->lang->getLL('makesavefo_t3dFile');
830 $opt['xml'] = $this->lang->getLL('makesavefo_xml');
831 $fileName = '';
832 if ($saveFolder) {
833 $fileName = sprintf($this->lang->getLL('makesavefo_filenameSavedInS', TRUE), $saveFolder->getCombinedIdentifier())
834 . '<br/>
835 <input type="text" name="tx_impexp[filename]" value="'
836 . htmlspecialchars($inData['filename']) . '"' . $this->doc->formWidth(30) . ' /><br/>';
837 }
838 $row[] = '
839 <tr>
840 <td>
841 <strong>' . $this->lang->getLL('makesavefo_fileFormat', TRUE) . '</strong>'
842 . BackendUtility::cshItem('xMOD_tx_impexp', 'fileFormat') . '
843 </td>
844 <td>
845 ' . $this->renderSelectBox('tx_impexp[filetype]', $inData['filetype'], $opt) . '<br/>
846 ' . $this->lang->getLL('makesavefo_maxSizeOfFiles', TRUE) . '<br/>
847 <input type="text" name="tx_impexp[maxFileSize]" value="' . htmlspecialchars($inData['maxFileSize']) . '"' . $this->doc->formWidth(10) . ' />
848 <br/>
849 ' . $fileName . '
850 </td>
851 </tr>';
852 // Add buttons:
853 $row[] = '
854 <tr>
855 <td>&nbsp;</td>
856 <td>
857 <input class="btn btn-default" type="submit" value="' . $this->lang->getLL('makesavefo_update', TRUE) . '" /> -
858 <input class="btn btn-default" type="submit" value="' . $this->lang->getLL('makesavefo_downloadExport', TRUE) . '" name="tx_impexp[download_export]" />
859 ' . ($saveFolder ? ' - <input class="btn btn-default" type="submit" value="' . $this->lang->getLL('importdata_saveToFilename', TRUE) . '" name="tx_impexp[save_export]" />' : '') . '
860 </td>
861 </tr>';
862 }
863
864 /**************************
865 * IMPORT FUNCTIONS
866 **************************/
867
868 /**
869 * Import part of module
870 *
871 * @param array $inData Content of POST VAR tx_impexp[]..
872 * @throws \BadFunctionCallException
873 * @throws \InvalidArgumentException
874 * @throws \RuntimeException
875 * @return void Setting content in $this->content
876 */
877 public function importData($inData) {
878 $access = is_array($this->pageinfo) ? 1 : 0;
879 $beUser = $this->getBackendUser();
880 if ($this->id && $access || $beUser->user['admin'] && !$this->id) {
881 if ($beUser->user['admin'] && !$this->id) {
882 $this->pageinfo = array('title' => '[root-level]', 'uid' => 0, 'pid' => 0);
883 }
884 if ($inData['new_import']) {
885 unset($inData['import_mode']);
886 }
887 /** @var $import \TYPO3\CMS\Impexp\ImportExport */
888 $import = GeneralUtility::makeInstance(\TYPO3\CMS\Impexp\ImportExport::class);
889 $import->init(0, 'import');
890 $import->update = $inData['do_update'];
891 $import->import_mode = $inData['import_mode'];
892 $import->enableLogging = $inData['enableLogging'];
893 $import->global_ignore_pid = $inData['global_ignore_pid'];
894 $import->force_all_UIDS = $inData['force_all_UIDS'];
895 $import->showDiff = !$inData['notShowDiff'];
896 $import->allowPHPScripts = $inData['allowPHPScripts'];
897 $import->softrefInputValues = $inData['softrefInputValues'];
898 // OUTPUT creation:
899 $menuItems = array();
900 // Make input selector:
901 // must have trailing slash.
902 $path = $this->getDefaultImportExportFolder();
903 $exportFiles = $this->getExportFiles();
904 // Configuration
905 $row = array();
906 $selectOptions = array('');
907 foreach ($exportFiles as $file) {
908 $selectOptions[$file->getCombinedIdentifier()] = $file->getPublicUrl();
909 }
910 $row[] = '
911 <tr>
912 <th colspan="2">' . $this->lang->getLL('importdata_selectFileToImport', TRUE) . '</th>
913 </tr>';
914 $noCompressorAvailable = !$import->compress
915 ? '<br /><span class="text-danger">' . $this->lang->getLL('importdata_noteNoDecompressorAvailable', TRUE) . '</span>'
916 : '';
917 $row[] = '
918 <tr>
919 <td valign="top">
920 ' . $this->lang->getLL('importdata_file', TRUE) . ''
921 . BackendUtility::cshItem('xMOD_tx_impexp', 'importFile') . '
922 </td>
923 <td>
924 ' . $this->renderSelectBox('tx_impexp[file]', $inData['file'], $selectOptions) . '<br />'
925 . sprintf($this->lang->getLL('importdata_fromPathS', TRUE), $path ? $path->getCombinedIdentifier() : $this->lang->getLL('importdata_no_accessible_file_mount', TRUE)) .
926 $noCompressorAvailable . '
927 </td>
928 </tr>';
929 $row[] = '
930 <tr>
931 <th colspan="2">
932 ' . $this->lang->getLL('importdata_importOptions', TRUE) . '
933 </th>
934 </tr>';
935 $row[] = '
936 <tr>
937 <td valign="top">
938 ' . $this->lang->getLL('importdata_update', TRUE)
939 . BackendUtility::cshItem('xMOD_tx_impexp', 'update') . '
940 </td>
941 <td>
942 <input type="checkbox" name="tx_impexp[do_update]" id="checkDo_update" value="1"'
943 . ($inData['do_update'] ? ' checked="checked"' : '') . ' />
944 <label for="checkDo_update">' . $this->lang->getLL('importdata_updateRecords', TRUE) . '</label>
945 <br/>
946 <em>(' . $this->lang->getLL('importdata_thisOptionRequiresThat', TRUE) . ')</em>' . ($inData['do_update'] ? ' <hr/>
947 <input type="checkbox" name="tx_impexp[global_ignore_pid]" id="checkGlobal_ignore_pid" value="1"'
948 . ($inData['global_ignore_pid'] ? ' checked="checked"' : '') . ' />
949 <label for="checkGlobal_ignore_pid">' . $this->lang->getLL('importdata_ignorePidDifferencesGlobally', TRUE) . '</label><br/>
950 <em>(' . $this->lang->getLL('importdata_ifYouSetThis', TRUE) . ')</em>
951 ' : '') . '
952 </td>
953 </tr>';
954 $allowPhpScripts = $beUser->isAdmin()
955 ? '
956 <input type="checkbox" name="tx_impexp[allowPHPScripts]" id="checkAllowPHPScripts" value="1"'
957 . ($inData['allowPHPScripts'] ? ' checked="checked"' : '') . ' />
958 <label for="checkAllowPHPScripts">' . $this->lang->getLL('importdata_allowToWriteBanned', TRUE) . '</label><br/>'
959 : '';
960 $doUpdate = !$inData['do_update'] && $beUser->isAdmin()
961 ? '
962 <br/>
963 <input type="checkbox" name="tx_impexp[force_all_UIDS]" id="checkForce_all_UIDS" value="1"'
964 . ($inData['force_all_UIDS'] ? ' checked="checked"' : '') . ' />
965 <label for="checkForce_all_UIDS"><span class="text-danger">'
966 . $this->lang->getLL('importdata_force_all_UIDS', TRUE) . '</span></label><br/>
967 <em>(' . $this->lang->getLL('importdata_force_all_UIDS_descr', TRUE) . ')</em>'
968 : '';
969 $row[] = '<tr>
970 <td valign="top">
971 ' . $this->lang->getLL('importdata_options', TRUE) . BackendUtility::cshItem('xMOD_tx_impexp', 'options') . '
972 </td>
973 <td>
974 <input type="checkbox" name="tx_impexp[notShowDiff]" id="checkNotShowDiff" value="1"'
975 . ($inData['notShowDiff'] ? ' checked="checked"' : '') . ' />
976 <label for="checkNotShowDiff">' . $this->lang->getLL('importdata_doNotShowDifferences', TRUE) . '</label><br/>
977 <em>(' . $this->lang->getLL('importdata_greenValuesAreFrom', TRUE) . ')</em>
978 <br/><br/>
979
980 ' . $allowPhpScripts . $doUpdate . '
981 </td>
982 </tr>';
983 $newImport = !$inData['import_file']
984 ? '<input class="btn btn-default" type="submit" value="' . $this->lang->getLL('importdata_preview', TRUE) . '" />' . ($inData['file']
985 ? ' - <input type="hidden" name="not-set" value="1" id="t3js-submit-field" /><input class="btn btn-default t3js-confirm-trigger" type="button" value="' . ($inData['do_update']
986 ? $this->lang->getLL('importdata_update_299e', TRUE)
987 : $this->lang->getLL('importdata_import', TRUE)) . '" name="tx_impexp[import_file]" data-title="' . $this->lang->getLL('pleaseConfirm', TRUE) . '" data-message="' . $this->lang->getLL('importdata_areYouSure', TRUE) . '" />'
988 : '')
989 : '<input class="btn btn-default" type="submit" name="tx_impexp[new_import]" value="' . $this->lang->getLL('importdata_newImport', TRUE) . '" />';
990 $row[] = '<tr>
991 <td valign="top">
992 ' . $this->lang->getLL('importdata_action', TRUE) . BackendUtility::cshItem('xMOD_tx_impexp', 'action') . '
993 </td>
994 <td>
995 ' . $newImport . '
996 <input type="hidden" name="tx_impexp[action]" value="import" />
997 </td>
998 </tr>';
999 $row[] = '<tr>
1000 <td valign="top">
1001 ' . $this->lang->getLL('importdata_enableLogging', TRUE)
1002 . BackendUtility::cshItem('xMOD_tx_impexp', 'enableLogging') . '
1003 </td>
1004 <td>
1005 <input type="checkbox" name="tx_impexp[enableLogging]" id="checkEnableLogging" value="1"'
1006 . ($inData['enableLogging'] ? ' checked="checked"' : '') . ' />
1007 <label for="checkEnableLogging">' . $this->lang->getLL('importdata_writeIndividualDbActions', TRUE) . '</label><br/>
1008 <em>(' . $this->lang->getLL('importdata_thisIsDisabledBy', TRUE) . ')</em>
1009 </td>
1010 </tr>';
1011 $menuItems[] = array(
1012 'label' => $this->lang->getLL('importdata_import', TRUE),
1013 'content' => '
1014 <table border="0" cellpadding="1" cellspacing="1">
1015 ' . implode('
1016 ', $row) . '
1017 </table>
1018 '
1019 );
1020 // Upload file:
1021 $tempFolder = $this->getDefaultImportExportFolder();
1022 if ($tempFolder) {
1023 $row = array();
1024 $row[] = '
1025 <tr>
1026 <th colspan="2">' . $this->lang->getLL('importdata_uploadFileFromLocal', TRUE) . '</th>
1027 </tr>';
1028 $row[] = '
1029 <tr>
1030 <td valign="top">
1031 ' . $this->lang->getLL('importdata_browse', TRUE) . BackendUtility::cshItem('xMOD_tx_impexp', 'upload') . '
1032 </td>
1033 <td>
1034 <input type="file" name="upload_1"' . $this->doc->formWidth(35) . ' size="40" />
1035 <input type="hidden" name="file[upload][1][target]" value="' . htmlspecialchars($tempFolder->getCombinedIdentifier()) . '" />
1036 <input type="hidden" name="file[upload][1][data]" value="1" />
1037 <br />
1038 <input class="btn btn-default" type="submit" name="_upload" value="' . $this->lang->sL('LLL:EXT:lang/locallang_core.xlf:file_upload.php.submit', TRUE) . '" />
1039 <input type="checkbox" name="overwriteExistingFiles" id="checkOverwriteExistingFiles" value="1" checked="checked" />
1040 <label for="checkOverwriteExistingFiles">' . $this->lang->sL('LLL:EXT:lang/locallang_misc.xlf:overwriteExistingFiles', TRUE) . '</label>
1041 </td>
1042 </tr>';
1043 if (GeneralUtility::_POST('_upload')) {
1044 $noFileUploaded = $this->fileProcessor->internalUploadMap[1]
1045 ? $this->lang->getLL('importdata_success', TRUE) . ' ' . $this->uploadedFiles[0]->getName()
1046 : '<span class="text-danger">' . $this->lang->getLL('importdata_failureNoFileUploaded', TRUE) . '</span>';
1047 $row[] = '<tr class="bgColor4">
1048 <td>' . $this->lang->getLL('importdata_uploadStatus', TRUE) . '</td>
1049 <td>' . $noFileUploaded . '</td>
1050 </tr>';
1051 }
1052 $menuItems[] = array(
1053 'label' => $this->lang->getLL('importdata_upload'),
1054 'content' => '
1055 <table border="0" cellpadding="1" cellspacing="1">
1056 ' . implode('
1057 ', $row) . '
1058 </table>
1059 '
1060 );
1061 }
1062 // Perform import or preview depending:
1063 $overviewContent = '';
1064 $extensionInstallationMessage = '';
1065 $inFile = $this->getFile($inData['file']);
1066 if ($inFile !== NULL && $inFile->exists()) {
1067 $trow = array();
1068 if ($import->loadFile($inFile->getForLocalProcessing(FALSE), 1)) {
1069 // Check extension dependencies:
1070 $extKeysToInstall = array();
1071 if (is_array($import->dat['header']['extensionDependencies'])) {
1072 foreach ($import->dat['header']['extensionDependencies'] as $extKey) {
1073 if (!\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($extKey)) {
1074 $extKeysToInstall[] = $extKey;
1075 }
1076 }
1077 }
1078 if (!empty($extKeysToInstall)) {
1079 $extensionInstallationMessage = 'Before you can install this T3D file you need to install the extensions "'
1080 . implode('", "', $extKeysToInstall) . '".';
1081 }
1082 if ($inData['import_file']) {
1083 if (empty($extKeysToInstall)) {
1084 $import->importData($this->id);
1085 BackendUtility::setUpdateSignal('updatePageTree');
1086 }
1087 }
1088 $import->display_import_pid_record = $this->pageinfo;
1089 $overviewContent = $import->displayContentOverview();
1090 }
1091 // Meta data output:
1092 $trow[] = '<tr class="bgColor5">
1093 <td colspan="2"><strong>' . $this->lang->getLL('importdata_metaData', TRUE) . '</strong></td>
1094 </tr>';
1095 $trow[] = '<tr class="bgColor4">
1096 <td><strong>' . $this->lang->getLL('importdata_title', TRUE) . '</strong></td>
1097 <td width="95%">' . nl2br(htmlspecialchars($import->dat['header']['meta']['title'])) . '</td>
1098 </tr>';
1099 $trow[] = '<tr class="bgColor4">
1100 <td><strong>' . $this->lang->getLL('importdata_description', TRUE) . '</strong></td>
1101 <td width="95%">' . nl2br(htmlspecialchars($import->dat['header']['meta']['description'])) . '</td>
1102 </tr>';
1103 $trow[] = '<tr class="bgColor4">
1104 <td><strong>' . $this->lang->getLL('importdata_notes', TRUE) . '</strong></td>
1105 <td width="95%">' . nl2br(htmlspecialchars($import->dat['header']['meta']['notes'])) . '</td>
1106 </tr>';
1107 $trow[] = '<tr class="bgColor4">
1108 <td><strong>' . $this->lang->getLL('importdata_packager', TRUE) . '</strong></td>
1109 <td width="95%">' . nl2br(htmlspecialchars(($import->dat['header']['meta']['packager_name']
1110 . ' (' . $import->dat['header']['meta']['packager_username'] . ')'))) . '<br/>
1111 ' . $this->lang->getLL('importdata_email', TRUE) . ' '
1112 . $import->dat['header']['meta']['packager_email'] . '</td>
1113 </tr>';
1114 // Thumbnail icon:
1115 if (is_array($import->dat['header']['thumbnail'])) {
1116 $pI = pathinfo($import->dat['header']['thumbnail']['filename']);
1117 if (GeneralUtility::inList('gif,jpg,png,jpeg', strtolower($pI['extension']))) {
1118 // Construct filename and write it:
1119 $fileName = PATH_site . 'typo3temp/importthumb.' . $pI['extension'];
1120 GeneralUtility::writeFile($fileName, $import->dat['header']['thumbnail']['content']);
1121 // Check that the image really is an image and not a malicious PHP script...
1122 if (getimagesize($fileName)) {
1123 // Create icon tag:
1124 $iconTag = '<img src="' . $this->doc->backPath . '../' . PathUtility::stripPathSitePrefix($fileName)
1125 . '" ' . $import->dat['header']['thumbnail']['imgInfo'][3]
1126 . ' vspace="5" style="border: solid black 1px;" alt="" />';
1127 $trow[] = '<tr class="bgColor4">
1128 <td><strong>' . $this->lang->getLL('importdata_icon', TRUE) . '</strong></td>
1129 <td>' . $iconTag . '</td>
1130 </tr>';
1131 } else {
1132 GeneralUtility::unlink_tempfile($fileName);
1133 }
1134 }
1135 }
1136 $menuItems[] = array(
1137 'label' => $this->lang->getLL('importdata_metaData_1387'),
1138 'content' => '
1139 <table border="0" cellpadding="1" cellspacing="1">
1140 ' . implode('
1141 ', $trow) . '
1142 </table>
1143 '
1144 );
1145 }
1146 // Print errors that might be:
1147 $errors = $import->printErrorLog();
1148 $menuItems[] = array(
1149 'label' => $this->lang->getLL('importdata_messages'),
1150 'content' => $errors,
1151 'stateIcon' => $errors ? 2 : 0
1152 );
1153 // Output tabs:
1154 $content = $this->doc->getDynamicTabMenu($menuItems, 'tx_impexp_import', 1, FALSE, TRUE, FALSE);
1155 if ($extensionInstallationMessage) {
1156 $content = '<div style="border: 1px black solid; margin: 10px 10px 10px 10px; padding: 10px 10px 10px 10px;">'
1157 . $this->doc->icons(1) . htmlspecialchars($extensionInstallationMessage) . '</div>' . $content;
1158 }
1159 $this->content .= $this->doc->section('', $content, 0, 1);
1160 // Print overview:
1161 if ($overviewContent) {
1162 $this->content .= $this->doc->section($inData['import_file']
1163 ? $this->lang->getLL('importdata_structureHasBeenImported', TRUE)
1164 : $this->lang->getLL('filterpage_structureToBeImported', TRUE), $overviewContent, 0, 1);
1165 }
1166 }
1167 }
1168
1169 /****************************
1170 * Preset functions
1171 ****************************/
1172
1173 /**
1174 * Manipulate presets
1175 *
1176 * @param array $inData In data array, passed by reference!
1177 * @return void
1178 */
1179 public function processPresets(&$inData) {
1180 $presetData = GeneralUtility::_GP('preset');
1181 $err = FALSE;
1182 $msg = '';
1183 // Save preset
1184 $beUser = $this->getBackendUser();
1185 // cast public checkbox to int, since this is an int field and NULL is not allowed
1186 $inData['preset']['public'] = (int)$inData['preset']['public'];
1187 if (isset($presetData['save'])) {
1188 $preset = $this->getPreset($presetData['select']);
1189 // Update existing
1190 if (is_array($preset)) {
1191 if ($beUser->isAdmin() || $preset['user_uid'] === $beUser->user['uid']) {
1192 $fields_values = array(
1193 'public' => $inData['preset']['public'],
1194 'title' => $inData['preset']['title'],
1195 'item_uid' => $inData['pagetree']['id'],
1196 'preset_data' => serialize($inData)
1197 );
1198 $this->getDatabaseConnection()->exec_UPDATEquery('tx_impexp_presets', 'uid=' . (int)$preset['uid'], $fields_values);
1199 $msg = 'Preset #' . $preset['uid'] . ' saved!';
1200 } else {
1201 $msg = 'ERROR: The preset was not saved because you were not the owner of it!';
1202 $err = TRUE;
1203 }
1204 } else {
1205 // Insert new:
1206 $fields_values = array(
1207 'user_uid' => $beUser->user['uid'],
1208 'public' => $inData['preset']['public'],
1209 'title' => $inData['preset']['title'],
1210 'item_uid' => $inData['pagetree']['id'],
1211 'preset_data' => serialize($inData)
1212 );
1213 $this->getDatabaseConnection()->exec_INSERTquery('tx_impexp_presets', $fields_values);
1214 $msg = 'New preset "' . htmlspecialchars($inData['preset']['title']) . '" is created';
1215 }
1216 }
1217 // Delete preset:
1218 if (isset($presetData['delete'])) {
1219 $preset = $this->getPreset($presetData['select']);
1220 if (is_array($preset)) {
1221 // Update existing
1222 if ($beUser->isAdmin() || $preset['user_uid'] === $beUser->user['uid']) {
1223 $this->getDatabaseConnection()->exec_DELETEquery('tx_impexp_presets', 'uid=' . (int)$preset['uid']);
1224 $msg = 'Preset #' . $preset['uid'] . ' deleted!';
1225 } else {
1226 $msg = 'ERROR: You were not the owner of the preset so you could not delete it.';
1227 $err = TRUE;
1228 }
1229 } else {
1230 $msg = 'ERROR: No preset selected for deletion.';
1231 $err = TRUE;
1232 }
1233 }
1234 // Load preset
1235 if (isset($presetData['load']) || isset($presetData['merge'])) {
1236 $preset = $this->getPreset($presetData['select']);
1237 if (is_array($preset)) {
1238 // Update existing
1239 $inData_temp = unserialize($preset['preset_data']);
1240 if (is_array($inData_temp)) {
1241 if (isset($presetData['merge'])) {
1242 // Merge records in:
1243 if (is_array($inData_temp['record'])) {
1244 $inData['record'] = array_merge((array)$inData['record'], $inData_temp['record']);
1245 }
1246 // Merge lists in:
1247 if (is_array($inData_temp['list'])) {
1248 $inData['list'] = array_merge((array)$inData['list'], $inData_temp['list']);
1249 }
1250 } else {
1251 $msg = 'Preset #' . $preset['uid'] . ' loaded!';
1252 $inData = $inData_temp;
1253 }
1254 } else {
1255 $msg = 'ERROR: No configuratio data found in preset record!';
1256 $err = TRUE;
1257 }
1258 } else {
1259 $msg = 'ERROR: No preset selected for loading.';
1260 $err = TRUE;
1261 }
1262 }
1263 // Show message:
1264 if ($msg !== '') {
1265 $this->content .= $this->doc->section('Presets', $msg, 0, 1, $err ? 3 : 1);
1266 }
1267 }
1268
1269 /**
1270 * Get single preset record
1271 *
1272 * @param int $uid Preset record
1273 * @return array Preset record, if any (otherwise FALSE)
1274 */
1275 public function getPreset($uid) {
1276 return $this->getDatabaseConnection()->exec_SELECTgetSingleRow('*', 'tx_impexp_presets', 'uid=' . (int)$uid);
1277 }
1278
1279 /****************************
1280 * Helper functions
1281 ****************************/
1282
1283 /**
1284 * Returns a \TYPO3\CMS\Core\Resource\Folder object for saving export files
1285 * to the server and is also used for uploading import files.
1286 *
1287 * @throws \InvalidArgumentException
1288 * @return NULL|\TYPO3\CMS\Core\Resource\Folder
1289 */
1290 protected function getDefaultImportExportFolder() {
1291 $defaultImportExportFolder = NULL;
1292
1293 $defaultTemporaryFolder = $this->getBackendUser()->getDefaultUploadTemporaryFolder();
1294 if ($defaultTemporaryFolder !== NULL) {
1295
1296 $importExportFolderName = 'importexport';
1297 $createFolder = !$defaultTemporaryFolder->hasFolder($importExportFolderName);
1298 if ($createFolder === TRUE) {
1299 try {
1300 $defaultImportExportFolder = $defaultTemporaryFolder->createFolder($importExportFolderName);
1301 } catch (\TYPO3\CMS\Core\Resource\Exception $folderAccessException) {}
1302 } else {
1303 $defaultImportExportFolder = $defaultTemporaryFolder->getSubfolder($importExportFolderName);
1304 }
1305 }
1306
1307 return $defaultImportExportFolder;
1308 }
1309
1310
1311 /**
1312 * Check if a file has been uploaded
1313 *
1314 * @throws \InvalidArgumentException
1315 * @throws \UnexpectedValueException
1316 * @return void
1317 */
1318 public function checkUpload() {
1319 $file = GeneralUtility::_GP('file');
1320 // Initializing:
1321 $this->fileProcessor = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Utility\File\ExtendedFileUtility::class);
1322 $this->fileProcessor->init(array(), $GLOBALS['TYPO3_CONF_VARS']['BE']['fileExtensions']);
1323 $this->fileProcessor->setActionPermissions();
1324 $this->fileProcessor->setExistingFilesConflictMode((int)GeneralUtility::_GP('overwriteExistingFiles') === 1 ? 'replace' : 'cancel');
1325 // Checking referer / executing:
1326 $refInfo = parse_url(GeneralUtility::getIndpEnv('HTTP_REFERER'));
1327 $httpHost = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY');
1328 if (
1329 $httpHost != $refInfo['host']
1330 && !$GLOBALS['$TYPO3_CONF_VARS']['SYS']['doNotCheckReferer']
1331 && $this->vC != $this->getBackendUser()->veriCode()
1332 ) {
1333 $this->fileProcessor->writeLog(0, 2, 1, 'Referer host "%s" and server host "%s" did not match!', array($refInfo['host'], $httpHost));
1334 } else {
1335 $this->fileProcessor->start($file);
1336 $result = $this->fileProcessor->processData();
1337 if (!empty($result['upload'])) {
1338 foreach ($result['upload'] as $uploadedFiles) {
1339 $this->uploadedFiles += $uploadedFiles;
1340 }
1341 }
1342 }
1343 }
1344
1345 /**
1346 * Makes a selector-box from optValues
1347 *
1348 * @param string $prefix Form element name
1349 * @param string $value Current value
1350 * @param array $optValues Options to display (key/value pairs)
1351 * @return string HTML select element
1352 */
1353 public function renderSelectBox($prefix, $value, $optValues) {
1354 $opt = array();
1355 $isSelFlag = 0;
1356 foreach ($optValues as $k => $v) {
1357 $sel = (string)$k === (string)$value ? ' selected="selected"' : '';
1358 if ($sel) {
1359 $isSelFlag++;
1360 }
1361 $opt[] = '<option value="' . htmlspecialchars($k) . '"' . $sel . '>' . htmlspecialchars($v) . '</option>';
1362 }
1363 if (!$isSelFlag && (string)$value !== '') {
1364 $opt[] = '<option value="' . htmlspecialchars($value) . '" selected="selected">'
1365 . htmlspecialchars(('[\'' . $value . '\']')) . '</option>';
1366 }
1367 return '<select name="' . $prefix . '">' . implode('', $opt) . '</select>';
1368 }
1369
1370 /**
1371 * Returns a selector-box with TCA tables
1372 *
1373 * @param string $prefix Form element name prefix
1374 * @param array $value The current values selected
1375 * @param string $excludeList Table names (and the string "_ALL") to exclude. Comma list
1376 * @return string HTML select element
1377 */
1378 public function tableSelector($prefix, $value, $excludeList = '') {
1379 $optValues = array();
1380 if (!GeneralUtility::inList($excludeList, '_ALL')) {
1381 $optValues['_ALL'] = '[' . $this->lang->getLL('ALL_tables') . ']';
1382 }
1383 foreach ($GLOBALS['TCA'] as $table => $_) {
1384 if ($this->getBackendUser()->check('tables_select', $table) && !GeneralUtility::inList($excludeList, $table)) {
1385 $optValues[$table] = $table;
1386 }
1387 }
1388 // make box:
1389 $opt = array();
1390 $opt[] = '<option value=""></option>';
1391 $sel = '';
1392 foreach ($optValues as $k => $v) {
1393 if (is_array($value)) {
1394 $sel = in_array($k, $value) ? ' selected="selected"' : '';
1395 }
1396 $opt[] = '<option value="' . htmlspecialchars($k) . '"' . $sel . '>' . htmlspecialchars($v) . '</option>';
1397 }
1398 return '<select name="' . $prefix . '[]" multiple="multiple" size="'
1399 . MathUtility::forceIntegerInRange(count($opt), 5, 10) . '">' . implode('', $opt) . '</select>';
1400 }
1401
1402 /**
1403 * Returns a selector-box with loaded extension keys
1404 *
1405 * @param string $prefix Form element name prefix
1406 * @param array $value The current values selected
1407 * @return string HTML select element
1408 */
1409 public function extensionSelector($prefix, $value) {
1410 $loadedExtensions = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::getLoadedExtensionListArray();
1411
1412 // make box:
1413 $opt = array();
1414 $opt[] = '<option value=""></option>';
1415 foreach ($loadedExtensions as $extensionKey) {
1416 $sel = '';
1417 if (is_array($value)) {
1418 $sel = in_array($extensionKey, $value) ? ' selected="selected"' : '';
1419 }
1420 $opt[] = '<option value="' . htmlspecialchars($extensionKey) . '"' . $sel . '>'
1421 . htmlspecialchars($extensionKey) . '</option>';
1422 }
1423 return '<select name="' . $prefix . '[]" multiple="multiple" size="'
1424 . MathUtility::forceIntegerInRange(count($opt), 5, 10) . '">' . implode('', $opt) . '</select>';
1425 }
1426
1427 /**
1428 * Filter page IDs by traversing exclude array, finding all
1429 * excluded pages (if any) and making an AND NOT IN statement for the select clause.
1430 *
1431 * @param array $exclude Exclude array from import/export object.
1432 * @return string AND where clause part to filter out page uids.
1433 */
1434 public function filterPageIds($exclude) {
1435 // Get keys:
1436 $exclude = array_keys($exclude);
1437 // Traverse
1438 $pageIds = array();
1439 foreach ($exclude as $element) {
1440 list($table, $uid) = explode(':', $element);
1441 if ($table === 'pages') {
1442 $pageIds[] = (int)$uid;
1443 }
1444 }
1445 // Add to clause:
1446 if (!empty($pageIds)) {
1447 return ' AND uid NOT IN (' . implode(',', $pageIds) . ')';
1448 }
1449 return '';
1450 }
1451
1452 /**
1453 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
1454 */
1455 protected function getBackendUser() {
1456 return $GLOBALS['BE_USER'];
1457 }
1458
1459 /**
1460 * @return DatabaseConnection
1461 */
1462 protected function getDatabaseConnection() {
1463 return $GLOBALS['TYPO3_DB'];
1464 }
1465
1466 /**
1467 * @return LanguageService
1468 */
1469 protected function getLanguageService() {
1470 return $GLOBALS['LANG'];
1471 }
1472
1473 /**
1474 * Gets thumbnail files.
1475 *
1476 * @throws \InvalidArgumentException
1477 * @return array|\TYPO3\CMS\Core\Resource\File[]
1478 */
1479 protected function getThumbnailFiles() {
1480 $thumbnailFiles = array();
1481 $defaultTemporaryFolder = $this->getDefaultImportExportFolder();
1482
1483 if ($defaultTemporaryFolder === NULL) {
1484 return $thumbnailFiles;
1485 }
1486
1487 /** @var $filter \TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter */
1488 $filter = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter::class);
1489 $filter->setAllowedFileExtensions(array('png', 'gif', 'jpg'));
1490 $defaultTemporaryFolder->getStorage()->addFileAndFolderNameFilter(array($filter, 'filterFileList'));
1491 $thumbnailFiles = $defaultTemporaryFolder->getFiles();
1492
1493 return $thumbnailFiles;
1494 }
1495
1496 /**
1497 * Gets all export files.
1498 *
1499 * @throws \InvalidArgumentException
1500 * @return array|\TYPO3\CMS\Core\Resource\File[]
1501 */
1502 protected function getExportFiles() {
1503 $exportFiles = array();
1504
1505 $folder = $this->getDefaultImportExportFolder();
1506 if ($folder !== NULL) {
1507
1508 /** @var $filter \TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter */
1509 $filter = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter::class);
1510 $filter->setAllowedFileExtensions(array('t3d', 'xml'));
1511 $folder->getStorage()->addFileAndFolderNameFilter(array($filter, 'filterFileList'));
1512
1513 $exportFiles = $folder->getFiles();
1514 }
1515
1516 return $exportFiles;
1517 }
1518
1519 /**
1520 * Gets a file by combined identifier.
1521 *
1522 * @param string $combinedIdentifier
1523 * @return NULL|\TYPO3\CMS\Core\Resource\File
1524 */
1525 protected function getFile($combinedIdentifier) {
1526 try {
1527 $file = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->getFileObjectFromCombinedIdentifier($combinedIdentifier);
1528 } catch (\Exception $exception) {
1529 $file = NULL;
1530 }
1531
1532 return $file;
1533 }
1534
1535 }