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