TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
ImportExportController.php
Go to the documentation of this file.
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;
46 
51 {
55  protected $uploadedFiles = [];
56 
62  public $pageinfo;
63 
67  protected $export;
68 
72  protected $import;
73 
77  protected $fileProcessor;
78 
82  protected $vC = '';
83 
87  protected $lang = null;
88 
92  protected $treeHTML = '';
93 
97  protected $iconFactory;
98 
104  protected $moduleName = 'xMOD_tximpexp';
105 
111  protected $moduleTemplate;
112 
118  protected $shortcutName;
119 
125  protected $presetRepository;
126 
130  protected $standaloneView = null;
131 
135  protected $excludeDisabledRecords = false;
136 
142  protected $returnUrl;
143 
147  public function __construct()
148  {
149  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
150  $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
151  $this->presetRepository = GeneralUtility::makeInstance(PresetRepository::class);
152 
153  $templatePath = ExtensionManagementUtility::extPath('impexp') . 'Resources/Private/';
154 
155  /* @var $view StandaloneView */
156  $this->standaloneView = GeneralUtility::makeInstance(StandaloneView::class);
157  $this->standaloneView->setTemplateRootPaths([$templatePath . 'Templates/ImportExport/']);
158  $this->standaloneView->setLayoutRootPaths([$templatePath . 'Layouts/']);
159  $this->standaloneView->setPartialRootPaths([$templatePath . 'Partials/']);
160  $this->standaloneView->getRequest()->setControllerExtensionName('impexp');
161  }
162 
166  public function init()
167  {
168  $this->MCONF['name'] = $this->moduleName;
169  parent::init();
170  $this->vC = GeneralUtility::_GP('vC');
171  $this->returnUrl = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('returnUrl'));
172  $this->lang = $this->getLanguageService();
173  }
174 
183  public function main()
184  {
185  $this->lang->includeLLFile('EXT:impexp/Resources/Private/Language/locallang.xlf');
186 
187  // Start document template object:
188  // We keep this here, in case somebody relies on the old doc being here
189  $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
190  $this->doc->bodyTagId = 'imp-exp-mod';
191  $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
192  if (is_array($this->pageinfo)) {
193  $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageinfo);
194  }
195  // Setting up the context sensitive menu:
196  $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ClickMenu');
197  $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Impexp/ImportExport');
198  $this->moduleTemplate->addJavaScriptCode(
199  'ImpexpInLineJS',
200  'if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';'
201  );
202 
203  // Input data grabbed:
204  $inData = GeneralUtility::_GP('tx_impexp');
205  if (!array_key_exists('excludeDisabled', $inData)) {
206  // flag doesn't exist initially; state is on by default
207  $inData['excludeDisabled'] = 1;
208  }
209  $this->standaloneView->assign('moduleUrl', BackendUtility::getModuleUrl('xMOD_tximpexp'));
210  $this->standaloneView->assign('id', $this->id);
211  $this->standaloneView->assign('inData', $inData);
212 
213  switch ((string)$inData['action']) {
214  case 'export':
215  $this->shortcutName = $this->lang->getLL('title_export');
216  // Call export interface
217  $this->exportData($inData);
218  $this->standaloneView->setTemplate('Export.html');
219  break;
220  case 'import':
221  $backendUser = $this->getBackendUser();
222  $isEnabledForNonAdmin = $backendUser->getTSConfig('options.impexp.enableImportForNonAdminUser');
223  if (!$backendUser->isAdmin() && empty($isEnabledForNonAdmin['value'])) {
224  throw new \RuntimeException(
225  'Import module is disabled for non admin users and '
226  . 'userTsConfig options.impexp.enableImportForNonAdminUser is not enabled.',
227  1464435459
228  );
229  }
230  $this->shortcutName = $this->lang->getLL('title_import');
231  if (GeneralUtility::_POST('_upload')) {
232  $this->checkUpload();
233  }
234  // Finally: If upload went well, set the new file as the import file:
235  if (!empty($this->uploadedFiles[0])) {
236  // Only allowed extensions....
237  $extension = $this->uploadedFiles[0]->getExtension();
238  if ($extension === 't3d' || $extension === 'xml') {
239  $inData['file'] = $this->uploadedFiles[0]->getCombinedIdentifier();
240  }
241  }
242  // Call import interface:
243  $this->importData($inData);
244  $this->standaloneView->setTemplate('Import.html');
245  break;
246  }
247 
248  // Setting up the buttons and markers for docheader
249  $this->getButtons();
250  }
251 
287  public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
288  {
289  $GLOBALS['SOBE'] = $this;
290  $this->init();
291  $this->main();
292  $this->moduleTemplate->setContent($this->standaloneView->render());
293  $response->getBody()->write($this->moduleTemplate->renderContent());
294 
295  return $response;
296  }
297 
303  protected function getButtons()
304  {
305  $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
306  if ($this->getBackendUser()->mayMakeShortcut()) {
307  $shortcutButton = $buttonBar->makeShortcutButton()
308  ->setGetVariables(['tx_impexp'])
309  ->setDisplayName($this->shortcutName)
310  ->setModuleName($this->moduleName);
311  $buttonBar->addButton($shortcutButton);
312  }
313  // back button
314  if ($this->returnUrl) {
315  $backButton = $buttonBar->makeLinkButton()
316  ->setHref($this->returnUrl)
317  ->setTitle($this->lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.goBack'))
318  ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-view-go-back', Icon::SIZE_SMALL));
319  $buttonBar->addButton($backButton);
320  }
321  // Input data grabbed:
322  $inData = GeneralUtility::_GP('tx_impexp');
323  if ((string)$inData['action'] == 'import') {
324  if ($this->id && is_array($this->pageinfo) || $this->getBackendUser()->user['admin'] && !$this->id) {
325  if (is_array($this->pageinfo) && $this->pageinfo['uid']) {
326  // View
327  $onClick = BackendUtility::viewOnClick(
328  $this->pageinfo['uid'],
329  '',
330  BackendUtility::BEgetRootLine($this->pageinfo['uid'])
331  );
332  $viewButton = $buttonBar->makeLinkButton()
333  ->setTitle($this->lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.showPage'))
334  ->setHref('#')
335  ->setIcon($this->iconFactory->getIcon('actions-document-view', Icon::SIZE_SMALL))
336  ->setOnClick($onClick);
337  $buttonBar->addButton($viewButton);
338  }
339  }
340  }
341  }
342 
343  /**************************
344  * EXPORT FUNCTIONS
345  **************************/
346 
357  public function exportData($inData)
358  {
359  // BUILDING EXPORT DATA:
360  // Processing of InData array values:
361  $inData['pagetree']['maxNumber'] = MathUtility::forceIntegerInRange($inData['pagetree']['maxNumber'], 1, 1000000, 100);
362  $inData['listCfg']['maxNumber'] = MathUtility::forceIntegerInRange($inData['listCfg']['maxNumber'], 1, 1000000, 100);
363  $inData['maxFileSize'] = MathUtility::forceIntegerInRange($inData['maxFileSize'], 1, 1000000, 1000);
364  $inData['filename'] = trim(preg_replace('/[^[:alnum:]._-]*/', '', preg_replace('/\\.(t3d|xml)$/', '', $inData['filename'])));
365  if (strlen($inData['filename'])) {
366  $inData['filename'] .= $inData['filetype'] == 'xml' ? '.xml' : '.t3d';
367  }
368  // Set exclude fields in export object:
369  if (!is_array($inData['exclude'])) {
370  $inData['exclude'] = [];
371  }
372  // Saving/Loading/Deleting presets:
373  $this->presetRepository->processPresets($inData);
374  // Create export object and configure it:
375  $this->export = GeneralUtility::makeInstance(Export::class);
376  $this->export->init(0);
377  $this->export->maxFileSize = $inData['maxFileSize'] * 1024;
378  $this->export->excludeMap = (array)$inData['exclude'];
379  $this->export->softrefCfg = (array)$inData['softrefCfg'];
380  $this->export->extensionDependencies = ($inData['extension_dep'] === '') ? [] : (array)$inData['extension_dep'];
381  $this->export->showStaticRelations = $inData['showStaticRelations'];
382  $this->export->includeExtFileResources = !$inData['excludeHTMLfileResources'];
383  $this->excludeDisabledRecords = (bool)$inData['excludeDisabled'];
384  $this->export->setExcludeDisabledRecords($this->excludeDisabledRecords);
385 
386  // Static tables:
387  if (is_array($inData['external_static']['tables'])) {
388  $this->export->relStaticTables = $inData['external_static']['tables'];
389  }
390  // Configure which tables external relations are included for:
391  if (is_array($inData['external_ref']['tables'])) {
392  $this->export->relOnlyTables = $inData['external_ref']['tables'];
393  }
394  $saveFilesOutsideExportFile = false;
395  if (isset($inData['save_export']) && isset($inData['saveFilesOutsideExportFile']) && $inData['saveFilesOutsideExportFile'] === '1') {
396  $this->export->setSaveFilesOutsideExportFile(true);
397  $saveFilesOutsideExportFile = true;
398  }
399  $this->export->setHeaderBasics();
400  // Meta data setting:
401 
402  $beUser = $this->getBackendUser();
403  $this->export->setMetaData(
404  $inData['meta']['title'],
405  $inData['meta']['description'],
406  $inData['meta']['notes'],
407  $beUser->user['username'],
408  $beUser->user['realName'],
409  $beUser->user['email']
410  );
411  // Configure which records to export
412  if (is_array($inData['record'])) {
413  foreach ($inData['record'] as $ref) {
414  $rParts = explode(':', $ref);
415  $this->export->export_addRecord($rParts[0], BackendUtility::getRecord($rParts[0], $rParts[1]));
416  }
417  }
418  // Configure which tables to export
419  if (is_array($inData['list'])) {
420  foreach ($inData['list'] as $ref) {
421  $rParts = explode(':', $ref);
422  if ($beUser->check('tables_select', $rParts[0])) {
423  $statement = $this->exec_listQueryPid($rParts[0], $rParts[1], MathUtility::forceIntegerInRange($inData['listCfg']['maxNumber'], 1));
424  while ($subTrow = $statement->fetch()) {
425  $this->export->export_addRecord($rParts[0], $subTrow);
426  }
427  }
428  }
429  }
430  // Pagetree
431  if (isset($inData['pagetree']['id'])) {
432  // Based on click-expandable tree
433  $idH = null;
434  if ($inData['pagetree']['levels'] == -1) {
435  $pagetree = GeneralUtility::makeInstance(ExportPageTreeView::class);
436  if ($this->excludeDisabledRecords) {
437  $pagetree->init(BackendUtility::BEenableFields('pages'));
438  }
439  $tree = $pagetree->ext_tree($inData['pagetree']['id'], $this->filterPageIds($this->export->excludeMap));
440  $this->treeHTML = $pagetree->printTree($tree);
441  $idH = $pagetree->buffer_idH;
442  } elseif ($inData['pagetree']['levels'] == -2) {
443  $this->addRecordsForPid($inData['pagetree']['id'], $inData['pagetree']['tables'], $inData['pagetree']['maxNumber']);
444  } else {
445  // Based on depth
446  // Drawing tree:
447  // If the ID is zero, export root
448  if (!$inData['pagetree']['id'] && $beUser->isAdmin()) {
449  $sPage = [
450  'uid' => 0,
451  'title' => 'ROOT'
452  ];
453  } else {
454  $sPage = BackendUtility::getRecordWSOL('pages', $inData['pagetree']['id'], '*', ' AND ' . $this->perms_clause);
455  }
456  if (is_array($sPage)) {
457  $pid = $inData['pagetree']['id'];
458  $tree = GeneralUtility::makeInstance(PageTreeView::class);
459  $initClause = 'AND ' . $this->perms_clause . $this->filterPageIds($this->export->excludeMap);
460  if ($this->excludeDisabledRecords) {
461  $initClause .= BackendUtility::BEenableFields('pages');
462  }
463  $tree->init($initClause);
464  $HTML = $this->iconFactory->getIconForRecord('pages', $sPage, Icon::SIZE_SMALL)->render();
465  $tree->tree[] = ['row' => $sPage, 'HTML' => $HTML];
466  $tree->buffer_idH = [];
467  if ($inData['pagetree']['levels'] > 0) {
468  $tree->getTree($pid, $inData['pagetree']['levels'], '');
469  }
470  $idH = [];
471  $idH[$pid]['uid'] = $pid;
472  if (!empty($tree->buffer_idH)) {
473  $idH[$pid]['subrow'] = $tree->buffer_idH;
474  }
475  $pagetree = GeneralUtility::makeInstance(ExportPageTreeView::class);
476  $this->treeHTML = $pagetree->printTree($tree->tree);
477  $this->shortcutName .= ' (' . $sPage['title'] . ')';
478  }
479  }
480  // In any case we should have a multi-level array, $idH, with the page structure
481  // here (and the HTML-code loaded into memory for nice display...)
482  if (is_array($idH)) {
483  // Sets the pagetree and gets a 1-dim array in return with the pages (in correct submission order BTW...)
484  $flatList = $this->export->setPageTree($idH);
485  foreach ($flatList as $k => $value) {
486  $this->export->export_addRecord('pages', BackendUtility::getRecord('pages', $k));
487  $this->addRecordsForPid($k, $inData['pagetree']['tables'], $inData['pagetree']['maxNumber']);
488  }
489  }
490  }
491  // After adding ALL records we set relations:
492  for ($a = 0; $a < 10; $a++) {
493  $addR = $this->export->export_addDBRelations($a);
494  if (empty($addR)) {
495  break;
496  }
497  }
498  // Finally files are added:
499  // MUST be after the DBrelations are set so that files from ALL added records are included!
500  $this->export->export_addFilesFromRelations();
501 
502  $this->export->export_addFilesFromSysFilesRecords();
503 
504  // If the download button is clicked, return file
505  if ($inData['download_export'] || $inData['save_export']) {
506  switch ((string)$inData['filetype']) {
507  case 'xml':
508  $out = $this->export->compileMemoryToFileContent('xml');
509  $fExt = '.xml';
510  break;
511  case 't3d':
512  $this->export->dontCompress = 1;
513  // intentional fall-through
514  default:
515  $out = $this->export->compileMemoryToFileContent();
516  $fExt = ($this->export->doOutputCompress() ? '-z' : '') . '.t3d';
517  }
518  // Filename:
519  $dlFile = $inData['filename'];
520  if (!$dlFile) {
521  $exportName = substr(preg_replace('/[^[:alnum:]_]/', '-', $inData['download_export_name']), 0, 20);
522  $dlFile = 'T3D_' . $exportName . '_' . date('Y-m-d_H-i') . $fExt;
523  }
524 
525  // Export for download:
526  if ($inData['download_export']) {
527  $mimeType = 'application/octet-stream';
528  header('Content-Type: ' . $mimeType);
529  header('Content-Length: ' . strlen($out));
530  header('Content-Disposition: attachment; filename=' . basename($dlFile));
531  echo $out;
532  die;
533  }
534  // Export by saving:
535  if ($inData['save_export']) {
536  $saveFolder = $this->getDefaultImportExportFolder();
537  $lang = $this->getLanguageService();
538  if ($saveFolder !== false && $saveFolder->checkActionPermission('write')) {
539  $temporaryFileName = GeneralUtility::tempnam('export');
540  file_put_contents($temporaryFileName, $out);
541  $file = $saveFolder->addFile($temporaryFileName, $dlFile, 'replace');
542  if ($saveFilesOutsideExportFile) {
543  $filesFolderName = $dlFile . '.files';
544  $filesFolder = $saveFolder->createFolder($filesFolderName);
545  $temporaryFolderForExport = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->export->getTemporaryFilesPathForExport());
546  $temporaryFilesForExport = $temporaryFolderForExport->getFiles();
547  foreach ($temporaryFilesForExport as $temporaryFileForExport) {
548  $filesFolder->getStorage()->moveFile($temporaryFileForExport, $filesFolder);
549  }
550  $temporaryFolderForExport->delete();
551  }
552 
554  $flashMessage = GeneralUtility::makeInstance(
555  FlashMessage::class,
556  sprintf($lang->getLL('exportdata_savedInSBytes'), $file->getPublicUrl(), GeneralUtility::formatSize(strlen($out))),
557  $lang->getLL('exportdata_savedFile'),
559  );
560  } else {
562  $flashMessage = GeneralUtility::makeInstance(
563  FlashMessage::class,
564  sprintf($lang->getLL('exportdata_badPathS'), $saveFolder->getPublicUrl()),
565  $lang->getLL('exportdata_problemsSavingFile'),
567  );
568  }
570  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
572  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
573  $defaultFlashMessageQueue->enqueue($flashMessage);
574  }
575  }
576 
577  $this->makeConfigurationForm($inData);
578 
579  $this->makeSaveForm($inData);
580 
581  $this->makeAdvancedOptionsForm($inData);
582 
583  $this->standaloneView->assign('errors', $this->export->errorLog);
584 
585  // Generate overview:
586  $this->standaloneView->assign(
587  'contentOverview',
588  $this->export->displayContentOverview()
589  );
590  }
591 
600  public function addRecordsForPid($k, $tables, $maxNumber)
601  {
602  if (!is_array($tables)) {
603  return;
604  }
605  foreach ($GLOBALS['TCA'] as $table => $value) {
606  if ($table != 'pages' && (in_array($table, $tables) || in_array('_ALL', $tables))) {
607  if ($this->getBackendUser()->check('tables_select', $table) && !$GLOBALS['TCA'][$table]['ctrl']['is_static']) {
608  $statement = $this->exec_listQueryPid($table, $k, MathUtility::forceIntegerInRange($maxNumber, 1));
609  while ($subTrow = $statement->fetch()) {
610  $this->export->export_addRecord($table, $subTrow);
611  }
612  }
613  }
614  }
615  }
616 
625  public function exec_listQueryPid($table, $pid, $limit)
626  {
627  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
628 
629  $orderBy = $GLOBALS['TCA'][$table]['ctrl']['sortby'] ?: $GLOBALS['TCA'][$table]['ctrl']['default_sortby'];
630  $queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
631 
632  if ($this->excludeDisabledRecords === false) {
633  $queryBuilder->getRestrictions()
634  ->removeAll()
635  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
636  ->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
637  }
638 
639  $queryBuilder->select('*')
640  ->from($table)
641  ->where(
642  $queryBuilder->expr()->eq(
643  'pid',
644  $queryBuilder->createNamedParameter($pid, \PDO::PARAM_INT)
645  )
646  )
647  ->setMaxResults($limit);
648 
649  foreach (QueryHelper::parseOrderBy((string)$orderBy) as $orderPair) {
650  list($fieldName, $order) = $orderPair;
651  $queryBuilder->addOrderBy($fieldName, $order);
652  }
653 
654  $statement = $queryBuilder->execute();
655 
656  // Warning about hitting limit:
657  if ($statement->rowCount() == $limit) {
658  $limitWarning = sprintf($this->lang->getLL('makeconfig_anSqlQueryReturned'), $limit);
660  $flashMessage = GeneralUtility::makeInstance(
661  FlashMessage::class,
662  $this->lang->getLL('execlistqu_maxNumberLimit'),
663  $limitWarning,
665  );
667  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
669  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
670  $defaultFlashMessageQueue->enqueue($flashMessage);
671  }
672 
673  return $statement;
674  }
675 
682  public function makeConfigurationForm($inData)
683  {
684  $nameSuggestion = '';
685  // Page tree export options:
686  if (isset($inData['pagetree']['id'])) {
687  $this->standaloneView->assign('treeHTML', $this->treeHTML);
688 
689  $opt = [
690  '-2' => $this->lang->getLL('makeconfig_tablesOnThisPage'),
691  '-1' => $this->lang->getLL('makeconfig_expandedTree'),
692  '0' => $this->lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
693  '1' => $this->lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
694  '2' => $this->lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
695  '3' => $this->lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
696  '4' => $this->lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
697  '999' => $this->lang->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.depth_infi'),
698  ];
699  $this->standaloneView->assign('levelSelectOptions', $opt);
700  $this->standaloneView->assign('tableSelectOptions', $this->getTableSelectOptions('pages'));
701  $nameSuggestion .= 'tree_PID' . $inData['pagetree']['id'] . '_L' . $inData['pagetree']['levels'];
702  }
703  // Single record export:
704  if (is_array($inData['record'])) {
705  $records = [];
706  foreach ($inData['record'] as $ref) {
707  $rParts = explode(':', $ref);
708  $tName = $rParts[0];
709  $rUid = $rParts[1];
710  $nameSuggestion .= $tName . '_' . $rUid;
711  $rec = BackendUtility::getRecordWSOL($tName, $rUid);
712  if (!empty($rec)) {
713  $records[] = [
714  'icon' => $this->iconFactory->getIconForRecord($tName, $rec, Icon::SIZE_SMALL)->render(),
715  'title' => BackendUtility::getRecordTitle($tName, $rec, true),
716  'tableName' => $tName,
717  'recordUid' => $rUid
718  ];
719  }
720  }
721  $this->standaloneView->assign('records', $records);
722  }
723  // Single tables/pids:
724  if (is_array($inData['list'])) {
725 
726  // Display information about pages from which the export takes place
727  $tableList = [];
728  foreach ($inData['list'] as $reference) {
729  $referenceParts = explode(':', $reference);
730  $tableName = $referenceParts[0];
731  if ($this->getBackendUser()->check('tables_select', $tableName)) {
732  // If the page is actually the root, handle it differently
733  // NOTE: we don't compare integers, because the number actually comes from the split string above
734  if ($referenceParts[1] === '0') {
735  $iconAndTitle = $this->iconFactory->getIcon('apps-pagetree-root', Icon::SIZE_SMALL)->render() . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
736  } else {
737  $record = BackendUtility::getRecordWSOL('pages', $referenceParts[1]);
738  $iconAndTitle = $this->iconFactory->getIconForRecord('pages', $record, Icon::SIZE_SMALL)->render()
739  . BackendUtility::getRecordTitle('pages', $record, true);
740  }
741 
742  $tableList[] = [
743  'iconAndTitle' => sprintf($this->lang->getLL('makeconfig_tableListEntry'), $tableName, $iconAndTitle),
744  'reference' => $reference
745  ];
746  }
747  }
748  $this->standaloneView->assign('tableList', $tableList);
749  }
750 
751  $this->standaloneView->assign('externalReferenceTableSelectOptions', $this->getTableSelectOptions());
752  $this->standaloneView->assign('externalStaticTableSelectOptions', $this->getTableSelectOptions());
753  $this->standaloneView->assign('nameSuggestion', $nameSuggestion);
754  }
755 
763  public function makeAdvancedOptionsForm($inData)
764  {
766  $loadedExtensions = array_combine($loadedExtensions, $loadedExtensions);
767  $this->standaloneView->assign('extensions', $loadedExtensions);
768  $this->standaloneView->assign('inData', $inData);
769  }
770 
777  public function makeSaveForm($inData)
778  {
779  $opt = $this->presetRepository->getPresets((int)$inData['pagetree']['id']);
780 
781  $this->standaloneView->assign('presetSelectOptions', $opt);
782 
783  $saveFolder = $this->getDefaultImportExportFolder();
784  if ($saveFolder) {
785  $this->standaloneView->assign('saveFolder', $saveFolder->getCombinedIdentifier());
786  }
787 
788  // Add file options:
789  $opt = [];
790  if ($this->export->compress) {
791  $opt['t3d_compressed'] = $this->lang->getLL('makesavefo_t3dFileCompressed');
792  }
793  $opt['t3d'] = $this->lang->getLL('makesavefo_t3dFile');
794  $opt['xml'] = $this->lang->getLL('makesavefo_xml');
795 
796  $this->standaloneView->assign('filetypeSelectOptions', $opt);
797 
798  $fileName = '';
799  if ($saveFolder) {
800  $this->standaloneView->assign('saveFolder', $saveFolder->getPublicUrl());
801  $this->standaloneView->assign('hasSaveFolder', true);
802  }
803  $this->standaloneView->assign('fileName', $fileName);
804  }
805 
806  /**************************
807  * IMPORT FUNCTIONS
808  **************************/
809 
819  public function importData($inData)
820  {
821  $access = is_array($this->pageinfo) ? 1 : 0;
822  $beUser = $this->getBackendUser();
823  if ($this->id && $access || $beUser->user['admin'] && !$this->id) {
824  if ($beUser->user['admin'] && !$this->id) {
825  $this->pageinfo = ['title' => '[root-level]', 'uid' => 0, 'pid' => 0];
826  }
827  if ($inData['new_import']) {
828  unset($inData['import_mode']);
829  }
831  $import = GeneralUtility::makeInstance(Import::class);
832  $import->init();
833  $import->update = $inData['do_update'];
834  $import->import_mode = $inData['import_mode'];
835  $import->enableLogging = $inData['enableLogging'];
836  $import->global_ignore_pid = $inData['global_ignore_pid'];
837  $import->force_all_UIDS = $inData['force_all_UIDS'];
838  $import->showDiff = !$inData['notShowDiff'];
839  $import->allowPHPScripts = $inData['allowPHPScripts'];
840  $import->softrefInputValues = $inData['softrefInputValues'];
841 
842  // OUTPUT creation:
843 
844  // Make input selector:
845  // must have trailing slash.
846  $path = $this->getDefaultImportExportFolder();
847  $exportFiles = $this->getExportFiles();
848 
849  $this->shortcutName .= ' (' . $this->pageinfo['title'] . ')';
850 
851  // Configuration
852  $selectOptions = [''];
853  foreach ($exportFiles as $file) {
854  $selectOptions[$file->getCombinedIdentifier()] = $file->getPublicUrl();
855  }
856 
857  $this->standaloneView->assign('import', $import);
858  $this->standaloneView->assign('inData', $inData);
859  $this->standaloneView->assign('fileSelectOptions', $selectOptions);
860 
861  if ($path) {
862  $this->standaloneView->assign('importPath', sprintf($this->lang->getLL('importdata_fromPathS'), $path->getCombinedIdentifier()));
863  } else {
864  $this->standaloneView->assign('importPath', $this->lang->getLL('importdata_no_default_upload_folder'));
865  }
866  $this->standaloneView->assign('isAdmin', $beUser->isAdmin());
867 
868  // Upload file:
869  $tempFolder = $this->getDefaultImportExportFolder();
870  if ($tempFolder) {
871  $this->standaloneView->assign('tempFolder', $tempFolder->getCombinedIdentifier());
872  $this->standaloneView->assign('hasTempUploadFolder', true);
873  if (GeneralUtility::_POST('_upload')) {
874  $this->standaloneView->assign('submitted', GeneralUtility::_POST('_upload'));
875  $this->standaloneView->assign('noFileUploaded', $this->fileProcessor->internalUploadMap[1]);
876  if ($this->uploadedFiles[0]) {
877  $this->standaloneView->assign('uploadedFile', $this->uploadedFiles[0]->getName());
878  }
879  }
880  }
881 
882  // Perform import or preview depending:
883  $inFile = $this->getFile($inData['file']);
884  if ($inFile !== null && $inFile->exists()) {
885  $this->standaloneView->assign('metaDataInFileExists', true);
886  $importInhibitedMessages = [];
887  if ($import->loadFile($inFile->getForLocalProcessing(false), 1)) {
888  $importInhibitedMessages = $import->checkImportPrerequisites();
889  if ($inData['import_file']) {
890  if (empty($importInhibitedMessages)) {
891  $import->importData($this->id);
892  BackendUtility::setUpdateSignal('updatePageTree');
893  }
894  }
895  $import->display_import_pid_record = $this->pageinfo;
896  $this->standaloneView->assign('contentOverview', $import->displayContentOverview());
897  }
898  // Compile messages which are inhibiting a proper import and add them to output.
899  if (!empty($importInhibitedMessages)) {
900  $flashMessageQueue = GeneralUtility::makeInstance(FlashMessageService::class)->getMessageQueueByIdentifier('impexp.errors');
901  foreach ($importInhibitedMessages as $message) {
902  $flashMessageQueue->addMessage(GeneralUtility::makeInstance(
903  FlashMessage::class,
904  $message,
905  '',
907  ));
908  }
909  }
910  }
911 
912  $this->standaloneView->assign('errors', $import->errorLog);
913  }
914  }
915 
916  /****************************
917  * Helper functions
918  ****************************/
919 
927  protected function getDefaultImportExportFolder()
928  {
929  $defaultImportExportFolder = null;
930 
931  $defaultTemporaryFolder = $this->getBackendUser()->getDefaultUploadTemporaryFolder();
932  if ($defaultTemporaryFolder !== null) {
933  $importExportFolderName = 'importexport';
934  $createFolder = !$defaultTemporaryFolder->hasFolder($importExportFolderName);
935  if ($createFolder === true) {
936  try {
937  $defaultImportExportFolder = $defaultTemporaryFolder->createFolder($importExportFolderName);
938  } catch (Exception $folderAccessException) {
939  }
940  } else {
941  $defaultImportExportFolder = $defaultTemporaryFolder->getSubfolder($importExportFolderName);
942  }
943  }
944 
945  return $defaultImportExportFolder;
946  }
947 
955  public function checkUpload()
956  {
957  $file = GeneralUtility::_GP('file');
958  // Initializing:
959  $this->fileProcessor = GeneralUtility::makeInstance(ExtendedFileUtility::class);
960  $this->fileProcessor->setActionPermissions();
961  $conflictMode = empty(GeneralUtility::_GP('overwriteExistingFiles')) ? DuplicationBehavior::__default : DuplicationBehavior::REPLACE;
962  $this->fileProcessor->setExistingFilesConflictMode(DuplicationBehavior::cast($conflictMode));
963  // Checking referer / executing:
964  $refInfo = parse_url(GeneralUtility::getIndpEnv('HTTP_REFERER'));
965  $httpHost = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY');
966  if (
967  $httpHost != $refInfo['host']
968  && !$GLOBALS['$TYPO3_CONF_VARS']['SYS']['doNotCheckReferer']
969  && $this->vC != $this->getBackendUser()->veriCode()
970  ) {
971  $this->fileProcessor->writeLog(0, 2, 1, 'Referer host "%s" and server host "%s" did not match!', [$refInfo['host'], $httpHost]);
972  } else {
973  $this->fileProcessor->start($file);
974  $result = $this->fileProcessor->processData();
975  if (!empty($result['upload'])) {
976  foreach ($result['upload'] as $uploadedFiles) {
977  $this->uploadedFiles += $uploadedFiles;
978  }
979  }
980  }
981  }
982 
989  public function getTableSelectOptions($excludeList = '')
990  {
991  $optValues = [];
992  if (!GeneralUtility::inList($excludeList, '_ALL')) {
993  $optValues['_ALL'] = '[' . $this->lang->getLL('ALL_tables') . ']';
994  }
995  foreach ($GLOBALS['TCA'] as $table => $_) {
996  if ($this->getBackendUser()->check('tables_select', $table) && !GeneralUtility::inList($excludeList, $table)) {
997  $optValues[$table] = $table;
998  }
999  }
1000  return $optValues;
1001  }
1002 
1010  public function filterPageIds($exclude)
1011  {
1012  // Get keys:
1013  $exclude = array_keys($exclude);
1014  // Traverse
1015  $pageIds = [];
1016  foreach ($exclude as $element) {
1017  list($table, $uid) = explode(':', $element);
1018  if ($table === 'pages') {
1019  $pageIds[] = (int)$uid;
1020  }
1021  }
1022  // Add to clause:
1023  if (!empty($pageIds)) {
1024  return ' AND uid NOT IN (' . implode(',', $pageIds) . ')';
1025  }
1026  return '';
1027  }
1028 
1032  protected function getBackendUser()
1033  {
1034  return $GLOBALS['BE_USER'];
1035  }
1036 
1040  protected function getLanguageService()
1041  {
1042  return $GLOBALS['LANG'];
1043  }
1044 
1051  protected function getExportFiles()
1052  {
1053  $exportFiles = [];
1054 
1055  $folder = $this->getDefaultImportExportFolder();
1056  if ($folder !== null) {
1057 
1059  $filter = GeneralUtility::makeInstance(FileExtensionFilter::class);
1060  $filter->setAllowedFileExtensions(['t3d', 'xml']);
1061  $folder->getStorage()->addFileAndFolderNameFilter([$filter, 'filterFileList']);
1062 
1063  $exportFiles = $folder->getFiles();
1064  }
1065 
1066  return $exportFiles;
1067  }
1068 
1075  protected function getFile($combinedIdentifier)
1076  {
1077  try {
1078  $file = ResourceFactory::getInstance()->getFileObjectFromCombinedIdentifier($combinedIdentifier);
1079  } catch (\Exception $exception) {
1080  $file = null;
1081  }
1082 
1083  return $file;
1084  }
1085 }
static getRecordWSOL($table, $uid, $fields= '*', $where= '', $useDeleteClause=true, $unsetMovePointers=false)
static formatSize($sizeInBytes, $labels= '', $base=0)
static getRecordTitle($table, $row, $prep=false, $forceResult=true)
static viewOnClick($pageUid, $backPath= '', $rootLine=null, $anchorSection= '', $alternativeUrl= '', $additionalGetVars= '', $switchFocus=true)
static BEgetRootLine($uid, $clause= '', $workspaceOL=false)
static getRecord($table, $uid, $fields= '*', $where= '', $useDeleteClause=true)
static tempnam($filePrefix, $fileSuffix= '')
mainAction(ServerRequestInterface $request, ResponseInterface $response)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)
static forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31