TYPO3 CMS  TYPO3_7-6
ImportExportController.php
Go to the documentation of this file.
1 <?php
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 
43 
48 {
52  protected $uploadedFiles = [];
53 
59  public $pageinfo;
60 
64  protected $export;
65 
69  protected $import;
70 
74  protected $fileProcessor;
75 
79  protected $vC = '';
80 
84  protected $lang = null;
85 
89  protected $treeHTML = '';
90 
94  protected $iconFactory;
95 
101  protected $moduleName = 'xMOD_tximpexp';
102 
108  protected $moduleTemplate;
109 
115  protected $shortcutName;
116 
122  protected $presetRepository;
123 
127  protected $standaloneView = null;
128 
132  public function __construct()
133  {
134  $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
135  $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
136  $this->presetRepository = GeneralUtility::makeInstance(PresetRepository::class);
137 
138  $templatePath = ExtensionManagementUtility::extPath('impexp') . 'Resources/Private/';
139 
140  /* @var $view StandaloneView */
141  $this->standaloneView = GeneralUtility::makeInstance(StandaloneView::class);
142  $this->standaloneView->setTemplateRootPaths([$templatePath . 'Templates/ImportExport/']);
143  $this->standaloneView->setLayoutRootPaths([$templatePath . 'Layouts/']);
144  $this->standaloneView->setPartialRootPaths([$templatePath . 'Partials/']);
145  $this->standaloneView->getRequest()->setControllerExtensionName('impexp');
146  }
147 
151  public function init()
152  {
153  $this->MCONF['name'] = $this->moduleName;
154  parent::init();
155  $this->vC = GeneralUtility::_GP('vC');
156  $this->lang = $this->getLanguageService();
157  }
158 
167  public function main()
168  {
169  $this->lang->includeLLFile('EXT:impexp/Resources/Private/Language/locallang.xlf');
170 
171  // Start document template object:
172  // We keep this here, in case somebody relies on the old doc being here
173  $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
174  $this->doc->bodyTagId = 'imp-exp-mod';
175  $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->perms_clause);
176  if (is_array($this->pageinfo)) {
177  $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($this->pageinfo);
178  }
179  // Setting up the context sensitive menu:
180  $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/ClickMenu');
181  $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Impexp/ImportExport');
182  $this->moduleTemplate->addJavaScriptCode(
183  'ImpexpInLineJS',
184  'if (top.fsMod) top.fsMod.recentIds["web"] = ' . (int)$this->id . ';'
185  );
186 
187  // Input data grabbed:
188  $inData = GeneralUtility::_GP('tx_impexp');
189  if ($inData === null) {
190  // This happens if the post request was larger than allowed on the server
191  // We set the import action as default and output a user information
192  $inData = [
193  'action' => 'import',
194  ];
195  $flashMessage = GeneralUtility::makeInstance(
196  FlashMessage::class,
197  $this->getLanguageService()->getLL('importdata_upload_nodata'),
198  $this->getLanguageService()->getLL('importdata_upload_error'),
200  );
201  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
202  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
203  $defaultFlashMessageQueue->enqueue($flashMessage);
204  }
205  $this->standaloneView->assign('moduleUrl', BackendUtility::getModuleUrl('xMOD_tximpexp'));
206  $this->standaloneView->assign('id', $this->id);
207  $this->standaloneView->assign('inData', $inData);
208 
209  switch ((string)$inData['action']) {
210  case 'export':
211  $this->shortcutName = $this->lang->getLL('title_export');
212  // Call export interface
213  $this->exportData($inData);
214  $this->standaloneView->setTemplate('Export.html');
215  break;
216  case 'import':
217  $backendUser = $this->getBackendUser();
218  $isEnabledForNonAdmin = $backendUser->getTSConfig('options.impexp.enableImportForNonAdminUser');
219  if (!$backendUser->isAdmin() && empty($isEnabledForNonAdmin['value'])) {
220  throw new \RuntimeException(
221  'Import module is disabled for non admin users and '
222  . 'userTsConfig options.impexp.enableImportForNonAdminUser is not enabled.',
223  1464435459
224  );
225  }
226  $this->shortcutName = $this->lang->getLL('title_import');
227  if (GeneralUtility::_POST('_upload')) {
228  $this->checkUpload();
229  }
230  // Finally: If upload went well, set the new file as the import file:
231  if (!empty($this->uploadedFiles[0])) {
232  // Only allowed extensions....
233  $extension = $this->uploadedFiles[0]->getExtension();
234  if ($extension === 't3d' || $extension === 'xml') {
235  $inData['file'] = $this->uploadedFiles[0]->getCombinedIdentifier();
236  }
237  }
238  // Call import interface:
239  $this->importData($inData);
240  $this->standaloneView->setTemplate('Import.html');
241  break;
242  }
243 
244  // Setting up the buttons and markers for docheader
245  $this->getButtons();
246  }
247 
254  public function printContent()
255  {
257  echo $this->content;
258  }
259 
295  public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
296  {
297  $GLOBALS['SOBE'] = $this;
298  $this->init();
299  $this->main();
300  $this->moduleTemplate->setContent($this->standaloneView->render());
301  $response->getBody()->write($this->moduleTemplate->renderContent());
302 
303  return $response;
304  }
305 
311  protected function getButtons()
312  {
313  $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
314  if ($this->getBackendUser()->mayMakeShortcut()) {
315  $shortcutButton = $buttonBar->makeShortcutButton()
316  ->setGetVariables(['tx_impexp'])
317  ->setDisplayName($this->shortcutName)
318  ->setModuleName($this->moduleName);
319  $buttonBar->addButton($shortcutButton);
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/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->setCharset($this->lang->charSet);
378  $this->export->maxFileSize = $inData['maxFileSize'] * 1024;
379  $this->export->excludeMap = (array)$inData['exclude'];
380  $this->export->softrefCfg = (array)$inData['softrefCfg'];
381  $this->export->extensionDependencies = ($inData['extension_dep'] === '') ? [] : (array)$inData['extension_dep'];
382  $this->export->showStaticRelations = $inData['showStaticRelations'];
383  $this->export->includeExtFileResources = !$inData['excludeHTMLfileResources'];
384 
385  // Static tables:
386  if (is_array($inData['external_static']['tables'])) {
387  $this->export->relStaticTables = $inData['external_static']['tables'];
388  }
389  // Configure which tables external relations are included for:
390  if (is_array($inData['external_ref']['tables'])) {
391  $this->export->relOnlyTables = $inData['external_ref']['tables'];
392  }
393  $saveFilesOutsideExportFile = false;
394  if (isset($inData['save_export']) && isset($inData['saveFilesOutsideExportFile']) && $inData['saveFilesOutsideExportFile'] === '1') {
395  $this->export->setSaveFilesOutsideExportFile(true);
396  $saveFilesOutsideExportFile = true;
397  }
398  $this->export->setHeaderBasics();
399  // Meta data setting:
400 
401  $beUser = $this->getBackendUser();
402  $this->export->setMetaData(
403  $inData['meta']['title'],
404  $inData['meta']['description'],
405  $inData['meta']['notes'],
406  $beUser->user['username'],
407  $beUser->user['realName'],
408  $beUser->user['email']
409  );
410  // Configure which records to export
411  if (is_array($inData['record'])) {
412  foreach ($inData['record'] as $ref) {
413  $rParts = explode(':', $ref);
414  $this->export->export_addRecord($rParts[0], BackendUtility::getRecord($rParts[0], $rParts[1]));
415  }
416  }
417  // Configure which tables to export
418  if (is_array($inData['list'])) {
419  $db = $this->getDatabaseConnection();
420  foreach ($inData['list'] as $ref) {
421  $rParts = explode(':', $ref);
422  if ($beUser->check('tables_select', $rParts[0])) {
423  $res = $this->exec_listQueryPid($rParts[0], $rParts[1], MathUtility::forceIntegerInRange($inData['listCfg']['maxNumber'], 1));
424  while ($subTrow = $db->sql_fetch_assoc($res)) {
425  $this->export->export_addRecord($rParts[0], $subTrow);
426  }
427  $db->sql_free_result($res);
428  }
429  }
430  }
431  // Pagetree
432  if (isset($inData['pagetree']['id'])) {
433  // Based on click-expandable tree
434  $idH = null;
435  if ($inData['pagetree']['levels'] == -1) {
436  $pagetree = GeneralUtility::makeInstance(ExportPageTreeView::class);
437  $tree = $pagetree->ext_tree($inData['pagetree']['id'], $this->filterPageIds($this->export->excludeMap));
438  $this->treeHTML = $pagetree->printTree($tree);
439  $idH = $pagetree->buffer_idH;
440  } elseif ($inData['pagetree']['levels'] == -2) {
441  $this->addRecordsForPid($inData['pagetree']['id'], $inData['pagetree']['tables'], $inData['pagetree']['maxNumber']);
442  } else {
443  // Based on depth
444  // Drawing tree:
445  // If the ID is zero, export root
446  if (!$inData['pagetree']['id'] && $beUser->isAdmin()) {
447  $sPage = [
448  'uid' => 0,
449  'title' => 'ROOT'
450  ];
451  } else {
452  $sPage = BackendUtility::getRecordWSOL('pages', $inData['pagetree']['id'], '*', ' AND ' . $this->perms_clause);
453  }
454  if (is_array($sPage)) {
455  $pid = $inData['pagetree']['id'];
456  $tree = GeneralUtility::makeInstance(PageTreeView::class);
457  $tree->init('AND ' . $this->perms_clause . $this->filterPageIds($this->export->excludeMap));
458  $HTML = $this->iconFactory->getIconForRecord('pages', $sPage, Icon::SIZE_SMALL)->render();
459  $tree->tree[] = ['row' => $sPage, 'HTML' => $HTML];
460  $tree->buffer_idH = [];
461  if ($inData['pagetree']['levels'] > 0) {
462  $tree->getTree($pid, $inData['pagetree']['levels'], '');
463  }
464  $idH = [];
465  $idH[$pid]['uid'] = $pid;
466  if (!empty($tree->buffer_idH)) {
467  $idH[$pid]['subrow'] = $tree->buffer_idH;
468  }
469  $pagetree = GeneralUtility::makeInstance(ExportPageTreeView::class);
470  $this->treeHTML = $pagetree->printTree($tree->tree);
471  $this->shortcutName .= ' (' . $sPage['title'] . ')';
472  }
473  }
474  // In any case we should have a multi-level array, $idH, with the page structure
475  // here (and the HTML-code loaded into memory for nice display...)
476  if (is_array($idH)) {
477  // Sets the pagetree and gets a 1-dim array in return with the pages (in correct submission order BTW...)
478  $flatList = $this->export->setPageTree($idH);
479  foreach ($flatList as $k => $value) {
480  $this->export->export_addRecord('pages', BackendUtility::getRecord('pages', $k));
481  $this->addRecordsForPid($k, $inData['pagetree']['tables'], $inData['pagetree']['maxNumber']);
482  }
483  }
484  }
485  // After adding ALL records we set relations:
486  for ($a = 0; $a < 10; $a++) {
487  $addR = $this->export->export_addDBRelations($a);
488  if (empty($addR)) {
489  break;
490  }
491  }
492  // Finally files are added:
493  // MUST be after the DBrelations are set so that files from ALL added records are included!
494  $this->export->export_addFilesFromRelations();
495 
496  $this->export->export_addFilesFromSysFilesRecords();
497 
498  // If the download button is clicked, return file
499  if ($inData['download_export'] || $inData['save_export']) {
500  switch ((string)$inData['filetype']) {
501  case 'xml':
502  $out = $this->export->compileMemoryToFileContent('xml');
503  $fExt = '.xml';
504  break;
505  case 't3d':
506  $this->export->dontCompress = 1;
507  // intentional fall-through
508  default:
509  $out = $this->export->compileMemoryToFileContent();
510  $fExt = ($this->export->doOutputCompress() ? '-z' : '') . '.t3d';
511  }
512  // Filename:
513  $dlFile = $inData['filename'];
514  if (!$dlFile) {
515  $exportName = substr(preg_replace('/[^[:alnum:]_]/', '-', $inData['download_export_name']), 0, 20);
516  $dlFile = 'T3D_' . $exportName . '_' . date('Y-m-d_H-i') . $fExt;
517  }
518 
519  // Export for download:
520  if ($inData['download_export']) {
521  $mimeType = 'application/octet-stream';
522  header('Content-Type: ' . $mimeType);
523  header('Content-Length: ' . strlen($out));
524  header('Content-Disposition: attachment; filename=' . basename($dlFile));
525  echo $out;
526  die;
527  }
528  // Export by saving:
529  if ($inData['save_export']) {
530  $saveFolder = $this->getDefaultImportExportFolder();
531  $lang = $this->getLanguageService();
532  if ($saveFolder !== false && $saveFolder->checkActionPermission('write')) {
533  $temporaryFileName = GeneralUtility::tempnam('export');
534  file_put_contents($temporaryFileName, $out);
535  $file = $saveFolder->addFile($temporaryFileName, $dlFile, 'replace');
536  if ($saveFilesOutsideExportFile) {
537  $filesFolderName = $dlFile . '.files';
538  $filesFolder = $saveFolder->createFolder($filesFolderName);
539  $temporaryFolderForExport = ResourceFactory::getInstance()->retrieveFileOrFolderObject($this->export->getTemporaryFilesPathForExport());
540  $temporaryFilesForExport = $temporaryFolderForExport->getFiles();
541  foreach ($temporaryFilesForExport as $temporaryFileForExport) {
542  $filesFolder->getStorage()->moveFile($temporaryFileForExport, $filesFolder);
543  }
544  $temporaryFolderForExport->delete();
545  }
546 
548  $flashMessage = GeneralUtility::makeInstance(
549  FlashMessage::class,
550  sprintf($lang->getLL('exportdata_savedInSBytes'), $file->getPublicUrl(), GeneralUtility::formatSize(strlen($out))),
551  $lang->getLL('exportdata_savedFile'),
553  );
554  } else {
556  $flashMessage = GeneralUtility::makeInstance(
557  FlashMessage::class,
558  sprintf($lang->getLL('exportdata_badPathS'), $saveFolder->getPublicUrl()),
559  $lang->getLL('exportdata_problemsSavingFile'),
561  );
562  }
564  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
566  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
567  $defaultFlashMessageQueue->enqueue($flashMessage);
568  }
569  }
570 
571  $this->makeConfigurationForm($inData);
572 
573  $this->makeSaveForm($inData);
574 
575  $this->makeAdvancedOptionsForm($inData);
576 
577  // Print errors that might be:
578  $errors = $this->export->printErrorLog();
579  $this->standaloneView->assign('errors', trim($errors));
580 
581  // Generate overview:
582  $this->standaloneView->assign('contentOverview', $this->export->displayContentOverview());
583  }
584 
593  public function addRecordsForPid($k, $tables, $maxNumber)
594  {
595  if (!is_array($tables)) {
596  return;
597  }
598  $db = $this->getDatabaseConnection();
599  foreach ($GLOBALS['TCA'] as $table => $value) {
600  if ($table != 'pages' && (in_array($table, $tables) || in_array('_ALL', $tables))) {
601  if ($this->getBackendUser()->check('tables_select', $table) && !$GLOBALS['TCA'][$table]['ctrl']['is_static']) {
602  $res = $this->exec_listQueryPid($table, $k, MathUtility::forceIntegerInRange($maxNumber, 1));
603  while ($subTrow = $db->sql_fetch_assoc($res)) {
604  $this->export->export_addRecord($table, $subTrow);
605  }
606  $db->sql_free_result($res);
607  }
608  }
609  }
610  }
611 
620  public function exec_listQueryPid($table, $pid, $limit)
621  {
622  $db = $this->getDatabaseConnection();
623  $orderBy = $GLOBALS['TCA'][$table]['ctrl']['sortby']
624  ? 'ORDER BY ' . $GLOBALS['TCA'][$table]['ctrl']['sortby']
625  : $GLOBALS['TCA'][$table]['ctrl']['default_sortby'];
626  $res = $db->exec_SELECTquery(
627  '*',
628  $table,
629  'pid=' . (int)$pid . BackendUtility::deleteClause($table) . BackendUtility::versioningPlaceholderClause($table),
630  '',
631  $db->stripOrderBy($orderBy),
632  $limit
633  );
634  // Warning about hitting limit:
635  if ($db->sql_num_rows($res) == $limit) {
636  $limitWarning = sprintf($this->lang->getLL('makeconfig_anSqlQueryReturned'), $limit);
638  $flashMessage = GeneralUtility::makeInstance(
639  FlashMessage::class,
640  $this->lang->getLL('execlistqu_maxNumberLimit'),
641  $limitWarning,
643  );
645  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
647  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
648  $defaultFlashMessageQueue->enqueue($flashMessage);
649  }
650  return $res;
651  }
652 
659  public function makeConfigurationForm($inData)
660  {
661  $nameSuggestion = '';
662  // Page tree export options:
663  if (isset($inData['pagetree']['id'])) {
664  $this->standaloneView->assign('treeHTML', $this->treeHTML);
665 
666  $opt = [
667  '-2' => $this->lang->getLL('makeconfig_tablesOnThisPage'),
668  '-1' => $this->lang->getLL('makeconfig_expandedTree'),
669  '0' => $this->lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_0'),
670  '1' => $this->lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_1'),
671  '2' => $this->lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_2'),
672  '3' => $this->lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_3'),
673  '4' => $this->lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_4'),
674  '999' => $this->lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_infi'),
675  ];
676  $this->standaloneView->assign('levelSelectOptions', $opt);
677  $this->standaloneView->assign('tableSelectOptions', $this->getTableSelectOptions('pages'));
678  $nameSuggestion .= 'tree_PID' . $inData['pagetree']['id'] . '_L' . $inData['pagetree']['levels'];
679  }
680  // Single record export:
681  if (is_array($inData['record'])) {
682  $records = [];
683  foreach ($inData['record'] as $ref) {
684  $rParts = explode(':', $ref);
685  $tName = $rParts[0];
686  $rUid = $rParts[1];
687  $nameSuggestion .= $tName . '_' . $rUid;
688  $rec = BackendUtility::getRecordWSOL($tName, $rUid);
689  if (!empty($rec)) {
690  $records[] = '
691  <tr class="bgColor4">
692  <td><strong>' . $this->lang->getLL('makeconfig_record', true) . '</strong></td>
693  <td>' . $this->iconFactory->getIconForRecord($tName, $rec, Icon::SIZE_SMALL)->render() . BackendUtility::getRecordTitle($tName, $rec, true)
694  . '<input type="hidden" name="tx_impexp[record][]" value="' . htmlspecialchars(($tName . ':' . $rUid)) . '" /></td>
695  </tr>';
696  }
697  }
698  $this->standaloneView->assign('records', implode('', $records));
699  }
700  // Single tables/pids:
701  if (is_array($inData['list'])) {
702 
703  // Display information about pages from which the export takes place
704  $tblList = '';
705  foreach ($inData['list'] as $reference) {
706  $referenceParts = explode(':', $reference);
707  $tableName = $referenceParts[0];
708  if ($this->getBackendUser()->check('tables_select', $tableName)) {
709  // If the page is actually the root, handle it differently
710  // NOTE: we don't compare integers, because the number actually comes from the split string above
711  if ($referenceParts[1] === '0') {
712  $iconAndTitle = $this->iconFactory->getIcon('apps-pagetree-root', Icon::SIZE_SMALL)->render() . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
713  } else {
714  $record = BackendUtility::getRecordWSOL('pages', $referenceParts[1]);
715  $iconAndTitle = $this->iconFactory->getIconForRecord('pages', $record, Icon::SIZE_SMALL)->render()
716  . BackendUtility::getRecordTitle('pages', $record, true);
717  }
718  $tblList .= 'Table "' . $tableName . '" from ' . $iconAndTitle
719  . '<input type="hidden" name="tx_impexp[list][]" value="' . htmlspecialchars($reference) . '" /><br/>';
720  }
721  }
722  $this->standaloneView->assign('tableList', $tblList);
723  }
724 
725  $this->standaloneView->assign('externalReferenceTableSelectOptions', $this->getTableSelectOptions());
726  $this->standaloneView->assign('externalStaticTableSelectOptions', $this->getTableSelectOptions());
727 
728  // Exclude:
729  $excludeHiddenFields = '';
730  if (is_array($inData['exclude'])) {
731  foreach ($inData['exclude'] as $key => $value) {
732  $excludeHiddenFields .= '<input type="hidden" name="tx_impexp[exclude][' . $key . ']" value="1" />';
733  }
734  $this->standaloneView->assign('excludedKeys', implode(', ', array_keys($inData['exclude'])));
735  }
736  $this->standaloneView->assign('nameSuggestion', $nameSuggestion);
737  }
738 
746  public function makeAdvancedOptionsForm($inData)
747  {
749  $loadedExtensions = array_combine($loadedExtensions, $loadedExtensions);
750  $this->standaloneView->assign('extensions', $loadedExtensions);
751  $this->standaloneView->assign('inData', $inData);
752  }
753 
760  public function makeSaveForm($inData)
761  {
762 
763  // Presets:
764  $opt = [''];
765  $where = '(public>0 OR user_uid=' . (int)$this->getBackendUser()->user['uid'] . ')'
766  . ($inData['pagetree']['id'] ? ' AND (item_uid=' . (int)$inData['pagetree']['id'] . ' OR item_uid=0)' : '');
767  $presets = $this->getDatabaseConnection()->exec_SELECTgetRows('*', 'tx_impexp_presets', $where);
768  if (is_array($presets)) {
769  foreach ($presets as $presetCfg) {
770  $opt[$presetCfg['uid']] = $presetCfg['title'] . ' [' . $presetCfg['uid'] . ']'
771  . ($presetCfg['public'] ? ' [Public]' : '')
772  . ($presetCfg['user_uid'] === $this->getBackendUser()->user['uid'] ? ' [Own]' : '');
773  }
774  }
775 
776  $this->standaloneView->assign('presetSelectOptions', $opt);
777 
778  $saveFolder = $this->getDefaultImportExportFolder();
779  if ($saveFolder) {
780  $this->standaloneView->assign('saveFolder', $saveFolder->getCombinedIdentifier());
781  }
782 
783  // Add file options:
784  $opt = [];
785  if ($this->export->compress) {
786  $opt['t3d_compressed'] = $this->lang->getLL('makesavefo_t3dFileCompressed');
787  }
788  $opt['t3d'] = $this->lang->getLL('makesavefo_t3dFile');
789  $opt['xml'] = $this->lang->getLL('makesavefo_xml');
790 
791  $this->standaloneView->assign('filetypeSelectOptions', $opt);
792 
793  $fileName = '';
794  if ($saveFolder) {
795  $fileName = sprintf($this->lang->getLL('makesavefo_filenameSavedInS', true), $saveFolder->getPublicUrl())
796  . '<br/>
797  <input type="text" name="tx_impexp[filename]" value="'
798  . htmlspecialchars($inData['filename']) . '" /><br/>';
799 
800  $this->standaloneView->assign('hasSaveFolder', true);
801  }
802  $this->standaloneView->assign('fileName', $fileName);
803  }
804 
805  /**************************
806  * IMPORT FUNCTIONS
807  **************************/
808 
818  public function importData($inData)
819  {
820  $access = is_array($this->pageinfo) ? 1 : 0;
821  $beUser = $this->getBackendUser();
822  if ($this->id && $access || $beUser->user['admin'] && !$this->id) {
823  if ($beUser->user['admin'] && !$this->id) {
824  $this->pageinfo = ['title' => '[root-level]', 'uid' => 0, 'pid' => 0];
825  }
826  if ($inData['new_import']) {
827  unset($inData['import_mode']);
828  }
830  $import = GeneralUtility::makeInstance(Import::class);
831  $import->init();
832  $import->update = $inData['do_update'];
833  $import->import_mode = $inData['import_mode'];
834  $import->enableLogging = $inData['enableLogging'];
835  $import->global_ignore_pid = $inData['global_ignore_pid'];
836  $import->force_all_UIDS = $inData['force_all_UIDS'];
837  $import->showDiff = !$inData['notShowDiff'];
838  $import->allowPHPScripts = $inData['allowPHPScripts'];
839  $import->softrefInputValues = $inData['softrefInputValues'];
840 
841  // OUTPUT creation:
842 
843  // Make input selector:
844  // must have trailing slash.
845  $path = $this->getDefaultImportExportFolder();
846  $exportFiles = $this->getExportFiles();
847 
848  $this->shortcutName .= ' (' . $this->pageinfo['title'] . ')';
849 
850  // Configuration
851  $selectOptions = [''];
852  foreach ($exportFiles as $file) {
853  $selectOptions[$file->getCombinedIdentifier()] = $file->getPublicUrl();
854  }
855 
856  $this->standaloneView->assign('import', $import);
857  $this->standaloneView->assign('inData', $inData);
858  $this->standaloneView->assign('fileSelectOptions', $selectOptions);
859 
860  if ($path) {
861  $this->standaloneView->assign('importPath', sprintf($this->lang->getLL('importdata_fromPathS', true), $path->getCombinedIdentifier()));
862  } else {
863  $this->standaloneView->assign('importPath', $this->lang->getLL('importdata_no_default_upload_folder', true));
864  }
865  $this->standaloneView->assign('isAdmin', $beUser->isAdmin());
866 
867  // Upload file:
868  $tempFolder = $this->getDefaultImportExportFolder();
869  if ($tempFolder) {
870  $this->standaloneView->assign('tempFolder', $tempFolder->getCombinedIdentifier());
871  $this->standaloneView->assign('hasTempUploadFolder', true);
872  if (GeneralUtility::_POST('_upload')) {
873  $this->standaloneView->assign('submitted', GeneralUtility::_POST('_upload'));
874  $this->standaloneView->assign('noFileUploaded', $this->fileProcessor->internalUploadMap[1]);
875  if ($this->uploadedFiles[0]) {
876  $this->standaloneView->assign('uploadedFile', $this->uploadedFiles[0]->getName());
877  }
878  }
879  }
880 
881  // Perform import or preview depending:
882  $inFile = $this->getFile($inData['file']);
883  if ($inFile !== null && $inFile->exists()) {
884  $this->standaloneView->assign('metaDataInFileExists', true);
885  $importInhibitedMessages = [];
886  if ($import->loadFile($inFile->getForLocalProcessing(false), 1)) {
887  $importInhibitedMessages = $import->checkImportPrerequisites();
888  if ($inData['import_file']) {
889  if (empty($importInhibitedMessages)) {
890  $import->importData($this->id);
891  BackendUtility::setUpdateSignal('updatePageTree');
892  }
893  }
894  $import->display_import_pid_record = $this->pageinfo;
895  $this->standaloneView->assign('contentOverview', $import->displayContentOverview());
896  }
897  // Compile messages which are inhibiting a proper import and add them to output.
898  if (!empty($importInhibitedMessages)) {
899  $flashMessageQueue = GeneralUtility::makeInstance(FlashMessageService::class)->getMessageQueueByIdentifier('impexp.errors');
900  foreach ($importInhibitedMessages as $message) {
901  $flashMessageQueue->addMessage(GeneralUtility::makeInstance(
902  FlashMessage::class,
903  $message,
904  '',
906  ));
907  }
908  }
909  }
910  // Print errors that might be:
911  $errors = $import->printErrorLog();
912  $this->standaloneView->assign('errors', trim($errors));
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->init([], $GLOBALS['TYPO3_CONF_VARS']['BE']['fileExtensions']);
961  $this->fileProcessor->setActionPermissions();
962  $this->fileProcessor->setExistingFilesConflictMode((int)GeneralUtility::_GP('overwriteExistingFiles') === 1 ? DuplicationBehavior::REPLACE : DuplicationBehavior::CANCEL);
963  $this->fileProcessor->start($file);
964  $result = $this->fileProcessor->processData();
965  if (!empty($result['upload'])) {
966  foreach ($result['upload'] as $uploadedFiles) {
967  $this->uploadedFiles += $uploadedFiles;
968  }
969  }
970  }
971 
978  public function getTableSelectOptions($excludeList = '')
979  {
980  $optValues = [];
981  if (!GeneralUtility::inList($excludeList, '_ALL')) {
982  $optValues['_ALL'] = '[' . $this->lang->getLL('ALL_tables') . ']';
983  }
984  foreach ($GLOBALS['TCA'] as $table => $_) {
985  if ($this->getBackendUser()->check('tables_select', $table) && !GeneralUtility::inList($excludeList, $table)) {
986  $optValues[$table] = $table;
987  }
988  }
989  return $optValues;
990  }
991 
999  public function filterPageIds($exclude)
1000  {
1001  // Get keys:
1002  $exclude = array_keys($exclude);
1003  // Traverse
1004  $pageIds = [];
1005  foreach ($exclude as $element) {
1006  list($table, $uid) = explode(':', $element);
1007  if ($table === 'pages') {
1008  $pageIds[] = (int)$uid;
1009  }
1010  }
1011  // Add to clause:
1012  if (!empty($pageIds)) {
1013  return ' AND uid NOT IN (' . implode(',', $pageIds) . ')';
1014  }
1015  return '';
1016  }
1017 
1021  protected function getBackendUser()
1022  {
1023  return $GLOBALS['BE_USER'];
1024  }
1025 
1029  protected function getDatabaseConnection()
1030  {
1031  return $GLOBALS['TYPO3_DB'];
1032  }
1033 
1037  protected function getLanguageService()
1038  {
1039  return $GLOBALS['LANG'];
1040  }
1041 
1048  protected function getExportFiles()
1049  {
1050  $exportFiles = [];
1051 
1052  $folder = $this->getDefaultImportExportFolder();
1053  if ($folder !== null) {
1054 
1056  $filter = GeneralUtility::makeInstance(FileExtensionFilter::class);
1057  $filter->setAllowedFileExtensions(['t3d', 'xml']);
1058  $folder->getStorage()->addFileAndFolderNameFilter([$filter, 'filterFileList']);
1059 
1060  $exportFiles = $folder->getFiles();
1061  }
1062 
1063  return $exportFiles;
1064  }
1065 
1072  protected function getFile($combinedIdentifier)
1073  {
1074  try {
1075  $file = ResourceFactory::getInstance()->getFileObjectFromCombinedIdentifier($combinedIdentifier);
1076  } catch (\Exception $exception) {
1077  $file = null;
1078  }
1079 
1080  return $file;
1081  }
1082 }
static readPageAccess($id, $perms_clause)
static forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31
static BEgetRootLine($uid, $clause='', $workspaceOL=false)
static tempnam($filePrefix, $fileSuffix='')
static setUpdateSignal($set='', $params='')
static getRecordTitle($table, $row, $prep=false, $forceResult=true)
static viewOnClick($pageUid, $backPath='', $rootLine=null, $anchorSection='', $alternativeUrl='', $additionalGetVars='', $switchFocus=true)
$uid
Definition: server.php:38
static formatSize($sizeInBytes, $labels='', $base=0)
mainAction(ServerRequestInterface $request, ResponseInterface $response)
static getRecord($table, $uid, $fields=' *', $where='', $useDeleteClause=true)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static getRecordWSOL($table, $uid, $fields=' *', $where='', $useDeleteClause=true, $unsetMovePointers=false)
static deleteClause($table, $tableAlias='')