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