TYPO3 v15 dev-main snapshot ()
@@ -0,0 +1 @@
|
||||
/vendor/
|
||||
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use TYPO3\CMS\Core\Core\Bootstrap;
|
||||
use TYPO3\CMS\Core\Utility\PathUtility;
|
||||
use TYPO3\CMS\Impexp\Export;
|
||||
|
||||
/**
|
||||
* Command for exporting T3D/XML data files
|
||||
*/
|
||||
#[AsCommand('impexp:export', 'Exports a T3D / XML file with content of a page tree')]
|
||||
class ExportCommand extends Command
|
||||
{
|
||||
public function __construct(protected readonly Export $export)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the command by defining the name, options and arguments
|
||||
*/
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->addArgument(
|
||||
'filename',
|
||||
InputArgument::OPTIONAL,
|
||||
'The filename to export to (without file extension).'
|
||||
)
|
||||
->addOption(
|
||||
'type',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'The file type (xml, t3d, t3d_compressed).',
|
||||
$this->export->getExportFileType()
|
||||
)
|
||||
->addOption(
|
||||
'pid',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'The root page of the exported page tree.',
|
||||
$this->export->getPid()
|
||||
)
|
||||
->addOption(
|
||||
'levels',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
sprintf(
|
||||
'The depth of the exported page tree. '
|
||||
. '"%d": "Records on this page", '
|
||||
. '"0": "This page", '
|
||||
. '"1": "1 level down", '
|
||||
. '.. '
|
||||
. '"%d": "Infinite levels".',
|
||||
Export::LEVELS_RECORDS_ON_THIS_PAGE,
|
||||
Export::LEVELS_INFINITE
|
||||
),
|
||||
$this->export->getLevels()
|
||||
)
|
||||
->addOption(
|
||||
'table',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
|
||||
'Include all records of this table. Examples: "_ALL", "tt_content", "sys_file_reference", etc.'
|
||||
)
|
||||
->addOption(
|
||||
'record',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
|
||||
'Include this specific record. Pattern is "{table}:{record}". Examples: "tt_content:12", etc.'
|
||||
)
|
||||
->addOption(
|
||||
'list',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
|
||||
'Include the records of this table and this page. Pattern is "{table}:{pid}". Examples: "be_users:0", etc.'
|
||||
)
|
||||
->addOption(
|
||||
'include-related',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
|
||||
'Include record relations to this table, including the related record. Examples: "_ALL", "sys_category", etc.'
|
||||
)
|
||||
->addOption(
|
||||
'include-static',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
|
||||
'Include record relations to this table, excluding the related record. Examples: "_ALL", "be_users", etc.'
|
||||
)
|
||||
->addOption(
|
||||
'exclude',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
|
||||
'Exclude this specific record. Pattern is "{table}:{record}". Examples: "fe_users:3", etc.'
|
||||
)
|
||||
->addOption(
|
||||
'exclude-disabled-records',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'Exclude records which are handled as disabled by their TCA configuration, e.g. by fields "disabled", "starttime" or "endtime".'
|
||||
)
|
||||
->addOption(
|
||||
'title',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'The meta title of the export.'
|
||||
)
|
||||
->addOption(
|
||||
'description',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'The meta description of the export.'
|
||||
)
|
||||
->addOption(
|
||||
'notes',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'The meta notes of the export.'
|
||||
)
|
||||
->addOption(
|
||||
'dependency',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
|
||||
'This TYPO3 extension is required for the exported records. Examples: "news", "powermail", etc.'
|
||||
)
|
||||
->addOption(
|
||||
'save-files-outside-export-file',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'Save files into separate folder instead of including them into the common export file. Folder name pattern is "{filename}.files".'
|
||||
)
|
||||
->addOption(
|
||||
'include-site-configurations',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'Include site configurations for exported root pages.'
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the command for exporting a t3d/xml file from the TYPO3 system
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
// Ensure the _cli_ user is authenticated
|
||||
Bootstrap::initializeBackendAuthentication();
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
try {
|
||||
$this->export->setExportFileName(PathUtility::basename((string)$input->getArgument('filename')));
|
||||
$this->export->setExportFileType((string)$input->getOption('type'));
|
||||
$this->export->setPid((int)$input->getOption('pid'));
|
||||
$this->export->setLevels((int)$input->getOption('levels'));
|
||||
$this->export->setTables($input->getOption('table'));
|
||||
$this->export->setRecord($input->getOption('record'));
|
||||
$this->export->setList($input->getOption('list'));
|
||||
$this->export->setRelOnlyTables($input->getOption('include-related'));
|
||||
$this->export->setRelStaticTables($input->getOption('include-static'));
|
||||
$this->export->setExcludeMap(array_fill_keys($input->getOption('exclude'), 1));
|
||||
$this->export->setExcludeDisabledRecords($input->getOption('exclude-disabled-records'));
|
||||
$this->export->setTitle((string)$input->getOption('title'));
|
||||
$this->export->setDescription((string)$input->getOption('description'));
|
||||
$this->export->setNotes((string)$input->getOption('notes'));
|
||||
$this->export->setExtensionDependencies($input->getOption('dependency'));
|
||||
$this->export->setSaveFilesOutsideExportFile($input->getOption('save-files-outside-export-file'));
|
||||
$this->export->setIncludeSiteConfigurations($input->getOption('include-site-configurations'));
|
||||
$this->export->process();
|
||||
$saveFile = $this->export->saveToFile();
|
||||
$io->success('Exporting to ' . $saveFile->getPublicUrl() . ' succeeded.');
|
||||
return Command::SUCCESS;
|
||||
} catch (\Exception $e) {
|
||||
$saveFolder = $this->export->getOrCreateDefaultImportExportFolder();
|
||||
$io->error('Exporting to ' . $saveFolder->getPublicUrl() . ' failed.');
|
||||
if ($io->isVerbose()) {
|
||||
$io->writeln($e->getMessage());
|
||||
}
|
||||
return Command::FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use TYPO3\CMS\Core\Core\Bootstrap;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Impexp\Import;
|
||||
|
||||
/**
|
||||
* Command for importing T3D/XML data files
|
||||
*/
|
||||
#[AsCommand('impexp:import', 'Imports a T3D / XML file with content into a page tree')]
|
||||
class ImportCommand extends Command
|
||||
{
|
||||
public function __construct(protected readonly Import $import)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the command by defining the name, options and arguments
|
||||
*/
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->addArgument(
|
||||
'file',
|
||||
InputArgument::REQUIRED,
|
||||
'The file path to import from (.t3d or .xml).'
|
||||
)
|
||||
->addArgument(
|
||||
'pid',
|
||||
InputArgument::OPTIONAL,
|
||||
'The page to import to.',
|
||||
0
|
||||
)
|
||||
->addOption(
|
||||
'update-records',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'If set, existing records with the same UID will be updated instead of inserted.'
|
||||
)
|
||||
->addOption(
|
||||
'ignore-pid',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'If set, page IDs of updated records are not corrected (only works in conjunction with --update-records).'
|
||||
)
|
||||
->addOption(
|
||||
'force-uid',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'If set, UIDs from file will be forced.'
|
||||
)
|
||||
->addOption(
|
||||
'import-mode',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
|
||||
sprintf(
|
||||
'Set the import mode of this specific record. ' . PHP_EOL
|
||||
. 'Pattern is "{table}:{record}={mode}". ' . PHP_EOL
|
||||
. 'Available modes for new records are "%1$s" and "%3$s" '
|
||||
. 'and for existing records "%2$s", "%4$s", "%5$s" and "%3$s".' . PHP_EOL
|
||||
. 'Examples are "pages:987=%1$s", "tt_content:1=%2$s", etc.',
|
||||
Import::IMPORT_MODE_FORCE_UID,
|
||||
Import::IMPORT_MODE_AS_NEW,
|
||||
Import::IMPORT_MODE_EXCLUDE,
|
||||
Import::IMPORT_MODE_IGNORE_PID,
|
||||
Import::IMPORT_MODE_RESPECT_PID
|
||||
)
|
||||
)
|
||||
->addOption(
|
||||
'enable-log',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'If set, all database actions are logged.'
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the command for importing a t3d/xml file into the TYPO3 system
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
// Ensure the _cli_ user is authenticated
|
||||
Bootstrap::initializeBackendAuthentication();
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
try {
|
||||
$this->import->setPid((int)$input->getArgument('pid'));
|
||||
$this->import->setUpdate($input->getOption('update-records'));
|
||||
$this->import->setGlobalIgnorePid($input->getOption('ignore-pid'));
|
||||
$this->import->setForceAllUids($input->getOption('force-uid'));
|
||||
$this->import->setEnableLogging($input->getOption('enable-log'));
|
||||
$this->import->setImportMode($this->parseAssociativeArray($input, 'import-mode', '='));
|
||||
$this->import->loadFile((string)$input->getArgument('file'));
|
||||
$this->import->checkImportPrerequisites();
|
||||
$this->import->importData();
|
||||
$io->success('Importing ' . $input->getArgument('file') . ' to page ' . $input->getArgument('pid') . ' succeeded.');
|
||||
return Command::SUCCESS;
|
||||
} catch (\Exception $e) {
|
||||
// Since impexp triggers core and DataHandler with potential hooks, and exception could come from "everywhere".
|
||||
$io->error('Importing ' . $input->getArgument('file') . ' to page ' . $input->getArgument('pid') . ' failed.');
|
||||
if ($io->isVerbose()) {
|
||||
$io->writeln($e->getMessage());
|
||||
$io->writeln($this->import->getErrorLog());
|
||||
}
|
||||
return Command::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a basic commandline option array into an associative array by splitting each entry into a key part and
|
||||
* a value part using a specific separator.
|
||||
*/
|
||||
protected function parseAssociativeArray(InputInterface &$input, string $optionName, string $separator): array
|
||||
{
|
||||
$array = [];
|
||||
|
||||
foreach ($input->getOption($optionName) as &$value) {
|
||||
$parts = GeneralUtility::trimExplode($separator, $value, true, 2);
|
||||
if (count($parts) === 2) {
|
||||
$array[$parts[0]] = $parts[1];
|
||||
} else {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf('Command line option "%s" has invalid entry "%s".', $optionName, $value),
|
||||
1610464090
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\ContextMenu;
|
||||
|
||||
use TYPO3\CMS\Backend\ContextMenu\ItemProviders\AbstractProvider;
|
||||
use TYPO3\CMS\Backend\Routing\UriBuilder;
|
||||
|
||||
/**
|
||||
* Context menu item provider adding export and import items
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API.
|
||||
*/
|
||||
class ItemProvider extends AbstractProvider
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $itemsConfiguration = [
|
||||
'exportT3d' => [
|
||||
'type' => 'item',
|
||||
'label' => 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:export',
|
||||
'iconIdentifier' => 'actions-document-export-t3d',
|
||||
'callbackAction' => 'exportT3d',
|
||||
],
|
||||
'importT3d' => [
|
||||
'type' => 'item',
|
||||
'label' => 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:import',
|
||||
'iconIdentifier' => 'actions-document-import-t3d',
|
||||
'callbackAction' => 'importT3d',
|
||||
],
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
private readonly UriBuilder $uriBuilder,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Export item is added for all database records except files
|
||||
*/
|
||||
public function canHandle(): bool
|
||||
{
|
||||
return $this->table !== 'sys_file';
|
||||
}
|
||||
|
||||
/**
|
||||
* This needs to be lower than priority of the RecordProvider
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 50;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds import/export items to the "submenu" if available
|
||||
*/
|
||||
public function addItems(array $items): array
|
||||
{
|
||||
$this->initDisabledItems();
|
||||
$localItems = $this->prepareItems($this->itemsConfiguration);
|
||||
if (isset($items['more']['childItems'])) {
|
||||
$items['more']['childItems'] = $items['more']['childItems'] + $localItems;
|
||||
} else {
|
||||
$items += $localItems;
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
protected function canRender(string $itemName, string $type): bool
|
||||
{
|
||||
if (in_array($itemName, $this->disabledItems, true)) {
|
||||
return false;
|
||||
}
|
||||
$canRender = false;
|
||||
switch ($itemName) {
|
||||
case 'exportT3d':
|
||||
$canRender = $this->backendUser->isExportEnabled();
|
||||
break;
|
||||
case 'importT3d':
|
||||
$canRender = $this->table === 'pages' && $this->backendUser->isImportEnabled();
|
||||
break;
|
||||
}
|
||||
return $canRender;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers custom JS module with item onclick behaviour
|
||||
*/
|
||||
protected function getAdditionalAttributes(string $itemName): array
|
||||
{
|
||||
$attributes = [
|
||||
'data-callback-module' => '@typo3/impexp/context-menu-actions',
|
||||
];
|
||||
|
||||
// Add action url for items
|
||||
switch ($itemName) {
|
||||
case 'exportT3d':
|
||||
$attributes['data-action-url'] = (string)$this->uriBuilder->buildUriFromRoute('tx_impexp_export');
|
||||
break;
|
||||
case 'importT3d':
|
||||
$attributes['data-action-url'] = (string)$this->uriBuilder->buildUriFromRoute('tx_impexp_import');
|
||||
break;
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,386 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Controller;
|
||||
|
||||
use Psr\Http\Message\ResponseFactoryInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use TYPO3\CMS\Backend\Attribute\AsController;
|
||||
use TYPO3\CMS\Backend\Template\ModuleTemplate;
|
||||
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||
use TYPO3\CMS\Core\Exception as CoreException;
|
||||
use TYPO3\CMS\Core\Imaging\IconFactory;
|
||||
use TYPO3\CMS\Core\Imaging\IconSize;
|
||||
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||
use TYPO3\CMS\Core\Resource\Folder;
|
||||
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
|
||||
use TYPO3\CMS\Core\Type\Bitmask\Permission;
|
||||
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Core\Utility\MathUtility;
|
||||
use TYPO3\CMS\Core\Utility\PathUtility;
|
||||
use TYPO3\CMS\Impexp\Domain\Repository\PresetRepository;
|
||||
use TYPO3\CMS\Impexp\Exception\InsufficientUserPermissionsException;
|
||||
use TYPO3\CMS\Impexp\Exception\MalformedPresetException;
|
||||
use TYPO3\CMS\Impexp\Exception\PresetNotFoundException;
|
||||
use TYPO3\CMS\Impexp\Export;
|
||||
|
||||
/**
|
||||
* Export module controller
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API.
|
||||
*/
|
||||
#[AsController]
|
||||
class ExportController
|
||||
{
|
||||
protected array $defaultInputData = [
|
||||
'excludeDisabled' => 1,
|
||||
'preset' => [],
|
||||
'external_static' => [
|
||||
'tables' => [],
|
||||
],
|
||||
'external_ref' => [
|
||||
'tables' => [],
|
||||
],
|
||||
'pagetree' => [
|
||||
'tables' => [],
|
||||
],
|
||||
'extension_dep' => [],
|
||||
'meta' => [
|
||||
'title' => '',
|
||||
'description' => '',
|
||||
'notes' => '',
|
||||
],
|
||||
'record' => [],
|
||||
'list' => [],
|
||||
'includeSiteConfigurations' => 0,
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
protected readonly IconFactory $iconFactory,
|
||||
protected readonly ModuleTemplateFactory $moduleTemplateFactory,
|
||||
protected readonly ResponseFactoryInterface $responseFactory,
|
||||
protected readonly PresetRepository $presetRepository,
|
||||
protected readonly TcaSchemaFactory $tcaSchemaFactory,
|
||||
) {}
|
||||
|
||||
public function handleRequest(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
if ($this->getBackendUser()->isExportEnabled() === false) {
|
||||
throw new \RuntimeException(
|
||||
'Export module is disabled for non admin users and '
|
||||
. 'user TSconfig options.impexp.enableExportForNonAdminUser is not enabled.',
|
||||
1636901978
|
||||
);
|
||||
}
|
||||
|
||||
$backendUser = $this->getBackendUser();
|
||||
$queryParams = $request->getQueryParams();
|
||||
$parsedBody = $request->getParsedBody();
|
||||
|
||||
$id = (int)($parsedBody['id'] ?? $queryParams['id'] ?? 0);
|
||||
$permsClause = $backendUser->getPagePermsClause(Permission::PAGE_SHOW);
|
||||
$pageInfo = BackendUtility::readPageAccess($id, $permsClause) ?: [];
|
||||
if ($pageInfo === []) {
|
||||
throw new \RuntimeException("You don't have access to this page.", 1604308206);
|
||||
}
|
||||
|
||||
// @todo: Only small parts of tx_impexp can be hand over as GET, e.g. ['list'] and 'id', drop GET of everything else.
|
||||
// Also, there's a clash with id: it can be ['list']'table:id', it can be 'id', it can be tx_impexp['id']. This
|
||||
// should be de-messed somehow.
|
||||
$inputDataFromGetPost = $parsedBody['tx_impexp'] ?? $queryParams['tx_impexp'] ?? [];
|
||||
$inputData = $this->defaultInputData;
|
||||
ArrayUtility::mergeRecursiveWithOverrule($inputData, $inputDataFromGetPost);
|
||||
if ($inputData['resetExclude'] ?? false) {
|
||||
$inputData['exclude'] = [];
|
||||
}
|
||||
$inputData['preset']['public'] = (int)($inputData['preset']['public'] ?? 0);
|
||||
|
||||
$view = $this->moduleTemplateFactory->create($request);
|
||||
|
||||
$presetAction = $parsedBody['preset'] ?? [];
|
||||
$inputData = $this->processPresets($view, $presetAction, $inputData);
|
||||
|
||||
$export = $this->configureExportFromFormData($inputData);
|
||||
$export->process();
|
||||
|
||||
if ($inputData['download_export'] ?? false) {
|
||||
return $this->getDownload($export);
|
||||
}
|
||||
$saveFolder = $export->getOrCreateDefaultImportExportFolder();
|
||||
if (($inputData['save_export'] ?? false) && $saveFolder !== null) {
|
||||
$this->saveExportToFile($view, $export, $saveFolder);
|
||||
}
|
||||
$inputData['filename'] = $export->getExportFileName();
|
||||
|
||||
$view->assignMultiple([
|
||||
'id' => $id,
|
||||
'errors' => $export->getErrorLog(),
|
||||
'preview' => $export->renderPreview(),
|
||||
'tableSelectOptions' => $this->getTableSelectOptions(['pages']),
|
||||
'treeHTML' => $export->getTreeHTML(),
|
||||
'levelSelectOptions' => $this->getPageLevelSelectOptions($inputData),
|
||||
'records' => $this->getRecordSelectOptions($inputData),
|
||||
'tableList' => $this->getSelectableTableList($inputData),
|
||||
'externalReferenceTableSelectOptions' => $this->getTableSelectOptions(),
|
||||
'externalStaticTableSelectOptions' => $this->getTableSelectOptions(),
|
||||
'presetSelectOptions' => $this->presetRepository->getPresets($id),
|
||||
'fileName' => '',
|
||||
'filetypeSelectOptions' => $this->getFileSelectOptions($export),
|
||||
'saveFolder' => $saveFolder?->getPublicUrl() ?? '',
|
||||
'hasSaveFolder' => true,
|
||||
'extensions' => $this->getExtensionList(),
|
||||
'inData' => $inputData,
|
||||
'isAdmin' => $backendUser->isAdmin(),
|
||||
]);
|
||||
$view->setModuleName('');
|
||||
$view->getDocHeaderComponent()->setPageBreadcrumb($pageInfo);
|
||||
return $view->renderResponse('Export');
|
||||
}
|
||||
|
||||
protected function processPresets(ModuleTemplate $view, array $presetAction, array $inputData): array
|
||||
{
|
||||
if (empty($presetAction)) {
|
||||
return $inputData;
|
||||
}
|
||||
$presetUid = (int)$presetAction['select'];
|
||||
try {
|
||||
if (isset($presetAction['save'])) {
|
||||
if ($presetUid > 0) {
|
||||
// Update existing
|
||||
$this->presetRepository->updatePreset($presetUid, $inputData);
|
||||
$view->addFlashMessage('Preset #' . $presetUid . ' saved!', 'Presets', ContextualFeedbackSeverity::INFO);
|
||||
} else {
|
||||
// Insert new
|
||||
$this->presetRepository->createPreset($inputData);
|
||||
$view->addFlashMessage('New preset "' . $inputData['preset']['title'] . '" is created', 'Presets', ContextualFeedbackSeverity::INFO);
|
||||
}
|
||||
}
|
||||
if (isset($presetAction['delete'])) {
|
||||
if ($presetUid > 0) {
|
||||
$this->presetRepository->deletePreset($presetUid);
|
||||
$view->addFlashMessage('Preset #' . $presetUid . ' deleted!', 'Presets', ContextualFeedbackSeverity::INFO);
|
||||
} else {
|
||||
$view->addFlashMessage('ERROR: No preset selected for deletion.', 'Presets', ContextualFeedbackSeverity::ERROR);
|
||||
}
|
||||
}
|
||||
if (isset($presetAction['load']) || isset($presetAction['merge'])) {
|
||||
if ($presetUid > 0) {
|
||||
$presetData = $this->presetRepository->loadPreset($presetUid);
|
||||
if (isset($presetAction['merge'])) {
|
||||
// Merge records
|
||||
if (is_array($presetData['record'] ?? null)) {
|
||||
$inputData['record'] = array_merge((array)$inputData['record'], $presetData['record']);
|
||||
}
|
||||
// Merge lists
|
||||
if (is_array($presetData['list'] ?? null)) {
|
||||
$inputData['list'] = array_merge((array)$inputData['list'], $presetData['list']);
|
||||
}
|
||||
$view->addFlashMessage('Preset #' . $presetUid . ' merged!', 'Presets', ContextualFeedbackSeverity::INFO);
|
||||
} else {
|
||||
$inputData = $presetData;
|
||||
$view->addFlashMessage('Preset #' . $presetUid . ' loaded!', 'Presets', ContextualFeedbackSeverity::INFO);
|
||||
}
|
||||
} else {
|
||||
$view->addFlashMessage('ERROR: No preset selected for loading.', 'Presets', ContextualFeedbackSeverity::ERROR);
|
||||
}
|
||||
}
|
||||
} catch (PresetNotFoundException|InsufficientUserPermissionsException|MalformedPresetException $e) {
|
||||
$view->addFlashMessage($e->getMessage(), 'Presets', ContextualFeedbackSeverity::ERROR);
|
||||
}
|
||||
return $inputData;
|
||||
}
|
||||
|
||||
protected function configureExportFromFormData(array $inputData): Export
|
||||
{
|
||||
$export = GeneralUtility::makeInstance(Export::class);
|
||||
$export->setExcludeMap((array)($inputData['exclude'] ?? []));
|
||||
$export->setSoftrefCfg((array)($inputData['softrefCfg'] ?? []));
|
||||
$export->setExtensionDependencies((($inputData['extension_dep'] ?? '') === '') ? [] : (array)$inputData['extension_dep']);
|
||||
$export->setShowStaticRelations((bool)($inputData['showStaticRelations'] ?? false));
|
||||
$export->setExcludeDisabledRecords((bool)($inputData['excludeDisabled'] ?? false));
|
||||
if (!empty($inputData['filetype'])) {
|
||||
$export->setExportFileType((string)$inputData['filetype']);
|
||||
}
|
||||
$export->setExportFileName((string)($inputData['filename'] ?? ''));
|
||||
$export->setRelStaticTables((($inputData['external_static']['tables'] ?? '') === '') ? [] : (array)$inputData['external_static']['tables']);
|
||||
$export->setRelOnlyTables((($inputData['external_ref']['tables'] ?? '') === '') ? [] : (array)$inputData['external_ref']['tables']);
|
||||
if (isset($inputData['save_export'], $inputData['saveFilesOutsideExportFile']) && $inputData['saveFilesOutsideExportFile'] === '1') {
|
||||
$export->setSaveFilesOutsideExportFile(true);
|
||||
}
|
||||
if ($this->getBackendUser()->isAdmin()) {
|
||||
$export->setIncludeSiteConfigurations((bool)($inputData['includeSiteConfigurations'] ?? false));
|
||||
}
|
||||
$export->setTitle((string)($inputData['meta']['title'] ?? ''));
|
||||
$export->setDescription((string)($inputData['meta']['description'] ?? ''));
|
||||
$export->setNotes((string)($inputData['meta']['notes'] ?? ''));
|
||||
$export->setRecord((($inputData['record'] ?? '') === '') ? [] : (array)$inputData['record']);
|
||||
$export->setList((($inputData['list'] ?? '') === '') ? [] : (array)$inputData['list']);
|
||||
if (MathUtility::canBeInterpretedAsInteger($inputData['pagetree']['id'] ?? null)) {
|
||||
$export->setPid((int)$inputData['pagetree']['id']);
|
||||
}
|
||||
if (MathUtility::canBeInterpretedAsInteger($inputData['pagetree']['levels'] ?? null)) {
|
||||
$export->setLevels((int)$inputData['pagetree']['levels']);
|
||||
}
|
||||
$export->setTables((($inputData['pagetree']['tables'] ?? '') === '') ? [] : (array)$inputData['pagetree']['tables']);
|
||||
return $export;
|
||||
}
|
||||
|
||||
protected function getDownload(Export $export): ResponseInterface
|
||||
{
|
||||
$fileName = $export->getOrGenerateExportFileNameWithFileExtension();
|
||||
$fileContent = $export->render();
|
||||
$response = $this->responseFactory->createResponse()
|
||||
->withHeader('Content-Type', 'application/octet-stream')
|
||||
->withHeader('Content-Length', (string)strlen($fileContent))
|
||||
->withHeader('Content-Disposition', 'attachment; filename=' . PathUtility::basename($fileName));
|
||||
$response->getBody()->write($export->render());
|
||||
return $response;
|
||||
}
|
||||
|
||||
protected function saveExportToFile(ModuleTemplate $view, Export $export, Folder $saveFolder): void
|
||||
{
|
||||
$languageService = $this->getLanguageService();
|
||||
try {
|
||||
$saveFile = $export->saveToFile();
|
||||
$saveFileSize = $saveFile->getProperty('size');
|
||||
$view->addFlashMessage(
|
||||
sprintf($languageService->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:exportdata_savedInSBytes'), $saveFile->getPublicUrl(), GeneralUtility::formatSize($saveFileSize)),
|
||||
$languageService->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:exportdata_savedFile')
|
||||
);
|
||||
} catch (CoreException $e) {
|
||||
$view->addFlashMessage(
|
||||
sprintf($languageService->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:exportdata_badPathS'), $saveFolder->getPublicUrl()),
|
||||
$languageService->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:exportdata_problemsSavingFile'),
|
||||
ContextualFeedbackSeverity::ERROR
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getPageLevelSelectOptions(array $inputData): array
|
||||
{
|
||||
$languageService = $this->getLanguageService();
|
||||
$options = [];
|
||||
if (MathUtility::canBeInterpretedAsInteger($inputData['pagetree']['id'] ?? '')) {
|
||||
$options = [
|
||||
Export::LEVELS_RECORDS_ON_THIS_PAGE => $languageService->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_tablesOnThisPage'),
|
||||
0 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_0'),
|
||||
1 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_1'),
|
||||
2 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_2'),
|
||||
3 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_3'),
|
||||
4 => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_4'),
|
||||
Export::LEVELS_INFINITE => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.depth_infi'),
|
||||
];
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
protected function getRecordSelectOptions(array $inputData): array
|
||||
{
|
||||
$records = [];
|
||||
foreach ($inputData['record'] ?? [] as $tableNameColonUid) {
|
||||
[$tableName, $recordUid] = explode(':', $tableNameColonUid);
|
||||
if ($record = BackendUtility::getRecordWSOL((string)$tableName, (int)$recordUid)) {
|
||||
$records[] = [
|
||||
'icon' => $this->iconFactory->getIconForRecord($tableName, $record, IconSize::SMALL)->render(),
|
||||
'title' => BackendUtility::getRecordTitle($tableName, $record, true),
|
||||
'tableName' => $tableName,
|
||||
'recordUid' => $recordUid,
|
||||
];
|
||||
}
|
||||
}
|
||||
return $records;
|
||||
}
|
||||
|
||||
protected function getSelectableTableList(array $inputData): array
|
||||
{
|
||||
$backendUser = $this->getBackendUser();
|
||||
$languageService = $this->getLanguageService();
|
||||
$tableList = [];
|
||||
foreach ($inputData['list'] ?? [] as $reference) {
|
||||
$referenceParts = explode(':', $reference);
|
||||
$tableName = $referenceParts[0];
|
||||
if ($backendUser->check('tables_select', $tableName)) {
|
||||
// If the page is actually the root, handle it differently.
|
||||
// NOTE: we don't compare integers, because the number comes from the split string above
|
||||
if ($referenceParts[1] === '0') {
|
||||
$iconAndTitle = $this->iconFactory->getIcon('apps-pagetree-root', IconSize::SMALL)->render() . $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
|
||||
} else {
|
||||
$record = BackendUtility::getRecordWSOL('pages', (int)$referenceParts[1]);
|
||||
$iconAndTitle = $this->iconFactory->getIconForRecord('pages', $record, IconSize::SMALL)->render()
|
||||
. BackendUtility::getRecordTitle('pages', $record, true);
|
||||
}
|
||||
$tableList[] = [
|
||||
'iconAndTitle' => sprintf($languageService->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_tableListEntry'), $tableName, $iconAndTitle),
|
||||
'reference' => $reference,
|
||||
];
|
||||
}
|
||||
}
|
||||
return $tableList;
|
||||
}
|
||||
|
||||
protected function getExtensionList(): array
|
||||
{
|
||||
$loadedExtensions = ExtensionManagementUtility::getLoadedExtensionListArray();
|
||||
return array_combine($loadedExtensions, $loadedExtensions);
|
||||
}
|
||||
|
||||
protected function getFileSelectOptions(Export $export): array
|
||||
{
|
||||
$languageService = $this->getLanguageService();
|
||||
$fileTypeOptions = [];
|
||||
foreach ($export->getSupportedFileTypes() as $supportedFileType) {
|
||||
$fileTypeOptions[$supportedFileType] = $languageService->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_' . $supportedFileType);
|
||||
}
|
||||
return $fileTypeOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all exportable tables - basically all TCA tables. Blacklist some if wanted.
|
||||
* Returned array keys are table names, values are "translations".
|
||||
*/
|
||||
protected function getTableSelectOptions(array $excludeList = []): array
|
||||
{
|
||||
$languageService = $this->getLanguageService();
|
||||
$backendUser = $this->getBackendUser();
|
||||
$options = [
|
||||
'_ALL' => $languageService->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:ALL_tables'),
|
||||
];
|
||||
foreach ($this->tcaSchemaFactory->all()->getNames() as $table) {
|
||||
if (!in_array($table, $excludeList, true) && $backendUser->check('tables_select', $table)) {
|
||||
$options[$table] = $table;
|
||||
}
|
||||
}
|
||||
natsort($options);
|
||||
return $options;
|
||||
}
|
||||
|
||||
protected function getBackendUser(): BackendUserAuthentication
|
||||
{
|
||||
return $GLOBALS['BE_USER'];
|
||||
}
|
||||
|
||||
protected function getLanguageService(): LanguageService
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Controller;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use TYPO3\CMS\Backend\Attribute\AsController;
|
||||
use TYPO3\CMS\Backend\Routing\PreviewUriBuilder;
|
||||
use TYPO3\CMS\Backend\Template\Components\ComponentFactory;
|
||||
use TYPO3\CMS\Backend\Template\ModuleTemplate;
|
||||
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||
use TYPO3\CMS\Core\Imaging\IconFactory;
|
||||
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||
use TYPO3\CMS\Core\Package\PackageManager;
|
||||
use TYPO3\CMS\Core\Resource\Enum\DuplicationBehavior;
|
||||
use TYPO3\CMS\Core\Resource\File;
|
||||
use TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter;
|
||||
use TYPO3\CMS\Core\Resource\Folder;
|
||||
use TYPO3\CMS\Core\Resource\ResourceFactory;
|
||||
use TYPO3\CMS\Core\Type\Bitmask\Permission;
|
||||
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
|
||||
use TYPO3\CMS\Core\Utility\File\ExtendedFileUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Core\Utility\PathUtility;
|
||||
use TYPO3\CMS\Impexp\Import;
|
||||
|
||||
/**
|
||||
* Import module controller
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API.
|
||||
*/
|
||||
#[AsController]
|
||||
readonly class ImportController
|
||||
{
|
||||
protected const NO_UPLOAD = 0;
|
||||
protected const UPLOAD_DONE = 1;
|
||||
protected const UPLOAD_FAILED = 2;
|
||||
|
||||
/**
|
||||
* File extensions accepted by the import upload. Uploading any other file type is rejected
|
||||
* before the file is written to storage.
|
||||
*/
|
||||
protected const ALLOWED_UPLOAD_EXTENSIONS = ['t3d', 'xml'];
|
||||
protected const ALLOWED_UPLOAD_EXTENSION_LIST = '.t3d,.xml';
|
||||
|
||||
public function __construct(
|
||||
protected IconFactory $iconFactory,
|
||||
protected ModuleTemplateFactory $moduleTemplateFactory,
|
||||
protected ExtendedFileUtility $fileProcessor,
|
||||
protected ResourceFactory $resourceFactory,
|
||||
protected ComponentFactory $componentFactory,
|
||||
) {}
|
||||
|
||||
public function handleRequest(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
if (!$this->getBackendUser()->isImportEnabled()) {
|
||||
throw new \RuntimeException(
|
||||
'Import module is disabled for non admin users and user TSconfig options.impexp.enableImportForNonAdminUser is not enabled.',
|
||||
1464435459
|
||||
);
|
||||
}
|
||||
|
||||
$backendUser = $this->getBackendUser();
|
||||
$languageService = $this->getLanguageService();
|
||||
$queryParams = $request->getQueryParams();
|
||||
$parsedBody = $request->getParsedBody();
|
||||
|
||||
$id = (int)($parsedBody['id'] ?? $queryParams['id'] ?? 0);
|
||||
$permsClause = $backendUser->getPagePermsClause(Permission::PAGE_SHOW);
|
||||
$pageInfo = BackendUtility::readPageAccess($id, $permsClause) ?: [];
|
||||
if ($pageInfo === []) {
|
||||
throw new \RuntimeException("You don't have access to this page.", 1604308205);
|
||||
}
|
||||
|
||||
$inputData = $request->getParsedBody()['tx_impexp'] ?? $request->getQueryParams()['tx_impexp'] ?? [];
|
||||
if ($inputData['new_import'] ?? false) {
|
||||
unset($inputData['import_mode']);
|
||||
}
|
||||
|
||||
$view = $this->moduleTemplateFactory->create($request);
|
||||
|
||||
$import = GeneralUtility::makeInstance(Import::class);
|
||||
$import->setPid($id);
|
||||
// Resolve the upload destination server-side. The import upload target is pinned to this
|
||||
// folder and must never be taken from the (client-controlled) request body.
|
||||
$importFolder = $import->getOrCreateDefaultImportExportFolder();
|
||||
|
||||
$uploadStatus = self::NO_UPLOAD;
|
||||
$uploadedFileName = '';
|
||||
if ($request->getMethod() === 'POST' && empty($parsedBody)) {
|
||||
// This happens if the post request was larger than allowed on the server.
|
||||
$view->addFlashMessage(
|
||||
$languageService->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_upload_nodata'),
|
||||
$languageService->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_upload_error'),
|
||||
ContextualFeedbackSeverity::ERROR
|
||||
);
|
||||
}
|
||||
if ($request->getMethod() === 'POST' && isset($parsedBody['_upload'])) {
|
||||
$uploadStatus = self::UPLOAD_FAILED;
|
||||
$file = $this->handleFileUpload($request, $importFolder, $view);
|
||||
if ($file !== null) {
|
||||
$inputData['file'] = $file->getCombinedIdentifier();
|
||||
$uploadStatus = self::UPLOAD_DONE;
|
||||
$uploadedFileName = $file->getName();
|
||||
}
|
||||
}
|
||||
|
||||
$this->configureImportFromFormDataAndImportIfRequested($view, $import, $inputData);
|
||||
|
||||
if (!$this->getBackendUser()->isAdmin()
|
||||
&& $import->getSiteConfigurations() !== []
|
||||
) {
|
||||
$view->addFlashMessage(
|
||||
$languageService->translate('importdata_siteConfigurationsAdminOnly', 'impexp.messages'),
|
||||
$languageService->translate('importdata_siteConfigurations', 'impexp.messages'),
|
||||
ContextualFeedbackSeverity::WARNING
|
||||
);
|
||||
}
|
||||
|
||||
$view->assignMultiple([
|
||||
'importFolder' => $importFolder?->getCombinedIdentifier() ?? '',
|
||||
'import' => $import,
|
||||
'errors' => $import->getErrorLog(),
|
||||
'preview' => $import->renderPreview(),
|
||||
'id' => $id,
|
||||
'fileSelectOptions' => $this->getSelectableFileList($import),
|
||||
'inData' => $inputData,
|
||||
'isAdmin' => $this->getBackendUser()->isAdmin(),
|
||||
'uploadedFile' => $uploadedFileName,
|
||||
'uploadStatus' => $uploadStatus,
|
||||
'allowedUploadExtensionList' => self::ALLOWED_UPLOAD_EXTENSION_LIST,
|
||||
]);
|
||||
$view->setModuleName('');
|
||||
$view->getDocHeaderComponent()->setPageBreadcrumb($pageInfo);
|
||||
if ((int)($pageInfo['uid'] ?? 0) > 0) {
|
||||
$view->addButtonToButtonBar($this->componentFactory->createViewButton(PreviewUriBuilder::create($pageInfo)
|
||||
->withRootLine(BackendUtility::BEgetRootLine($pageInfo['uid']))
|
||||
->buildDispatcherDataAttributes() ?? []));
|
||||
}
|
||||
return $view->renderResponse('Import');
|
||||
}
|
||||
|
||||
protected function handleFileUpload(ServerRequestInterface $request, ?Folder $importFolder, ModuleTemplate $view): ?File
|
||||
{
|
||||
if ($importFolder === null) {
|
||||
return null;
|
||||
}
|
||||
// Reject any file that is not an import file before it is written to storage. The import
|
||||
// upload must never be used to place arbitrary file types in a (potentially public) storage.
|
||||
$uploadedFile = $request->getUploadedFiles()['upload_1'] ?? null;
|
||||
if (!$uploadedFile instanceof UploadedFileInterface) {
|
||||
return null;
|
||||
}
|
||||
$uploadExtension = strtolower(pathinfo((string)$uploadedFile->getClientFilename(), PATHINFO_EXTENSION));
|
||||
if (!in_array($uploadExtension, self::ALLOWED_UPLOAD_EXTENSIONS, true)) {
|
||||
$view->addFlashMessage(
|
||||
$this->getLanguageService()->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_upload_invalidExtension'),
|
||||
$this->getLanguageService()->sL('LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_upload_error'),
|
||||
ContextualFeedbackSeverity::ERROR
|
||||
);
|
||||
return null;
|
||||
}
|
||||
$parsedBody = $request->getParsedBody() ?? [];
|
||||
$conflictMode = empty($parsedBody['overwriteExistingFiles']) ? DuplicationBehavior::CANCEL : DuplicationBehavior::REPLACE;
|
||||
// The upload target is pinned to the import/export folder resolved server-side and must
|
||||
// not be taken from the (client-controlled) request body, otherwise an uploaded file
|
||||
// could be redirected to an arbitrary, potentially publicly accessible, storage location.
|
||||
$fileCommands = [
|
||||
'upload' => [
|
||||
1 => [
|
||||
'target' => $importFolder->getCombinedIdentifier(),
|
||||
'data' => '1',
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->fileProcessor->setActionPermissions();
|
||||
$this->fileProcessor->setExistingFilesConflictMode($conflictMode);
|
||||
$this->fileProcessor->start($fileCommands, $request->getUploadedFiles());
|
||||
$result = $this->fileProcessor->processData();
|
||||
// If upload went well, set the new file as the import file.
|
||||
return $result['upload'][0][0] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \BadFunctionCallException
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function configureImportFromFormDataAndImportIfRequested(ModuleTemplate $view, Import $import, array $inputData): void
|
||||
{
|
||||
$import->setUpdate((bool)($inputData['do_update'] ?? false));
|
||||
$import->setImportMode((array)($inputData['import_mode'] ?? null));
|
||||
$import->setEnableLogging((bool)($inputData['enableLogging'] ?? false));
|
||||
$import->setGlobalIgnorePid((bool)($inputData['global_ignore_pid'] ?? false));
|
||||
$import->setForceAllUids((bool)($inputData['force_all_UIDS'] ?? false));
|
||||
$import->setShowDiff(!(bool)($inputData['notShowDiff'] ?? false));
|
||||
$import->setSoftrefInputValues((array)($inputData['softrefInputValues'] ?? null));
|
||||
if (!empty($inputData['file'])) {
|
||||
if (PathUtility::isExtensionPath($inputData['file'])) {
|
||||
$filePath = $inputData['file'];
|
||||
} else {
|
||||
$filePath = $this->getFilePathWithinFileMountBoundaries((string)$inputData['file']);
|
||||
}
|
||||
try {
|
||||
$import->loadFile($filePath);
|
||||
$import->checkImportPrerequisites();
|
||||
if ($inputData['import_file'] ?? false) {
|
||||
$import->importData();
|
||||
BackendUtility::setUpdateSignal('updatePageTree');
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$view->addFlashMessage($e->getMessage(), '', ContextualFeedbackSeverity::ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getFilePathWithinFileMountBoundaries(string $filePath): string
|
||||
{
|
||||
try {
|
||||
$file = $this->resourceFactory->getFileObjectFromCombinedIdentifier($filePath);
|
||||
return $file->getForLocalProcessing(false);
|
||||
} catch (\Exception $exception) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
protected function getSelectableFileList(Import $import): array
|
||||
{
|
||||
$exportFiles = [];
|
||||
|
||||
// Fileadmin
|
||||
$folder = $import->getOrCreateDefaultImportExportFolder();
|
||||
if ($folder !== null) {
|
||||
$filter = GeneralUtility::makeInstance(FileExtensionFilter::class);
|
||||
$filter->setAllowedFileExtensions(['t3d', 'xml']);
|
||||
$folder->getStorage()->addFileAndFolderNameFilter([$filter, 'filterFileList']);
|
||||
$exportFiles = $folder->getFiles();
|
||||
}
|
||||
$selectableFiles = [''];
|
||||
foreach ($exportFiles as $file) {
|
||||
$selectableFiles[$file->getCombinedIdentifier()] = $file->getPublicUrl();
|
||||
}
|
||||
|
||||
// Extension Distribution
|
||||
if ($this->getBackendUser()->isAdmin()) {
|
||||
$possibleImportFiles = [
|
||||
'Initialisation/data.t3d',
|
||||
'Initialisation/data.xml',
|
||||
];
|
||||
$activePackages = GeneralUtility::makeInstance(PackageManager::class)->getActivePackages();
|
||||
foreach ($activePackages as $package) {
|
||||
foreach ($possibleImportFiles as $possibleImportFile) {
|
||||
if (!file_exists($package->getPackagePath() . $possibleImportFile)) {
|
||||
continue;
|
||||
}
|
||||
$selectableFiles['EXT:' . $package->getPackageKey() . '/' . $possibleImportFile] = 'EXT:' . $package->getPackageKey() . '/' . $possibleImportFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $selectableFiles;
|
||||
}
|
||||
|
||||
protected function getBackendUser(): BackendUserAuthentication
|
||||
{
|
||||
return $GLOBALS['BE_USER'];
|
||||
}
|
||||
|
||||
protected function getLanguageService(): LanguageService
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Domain\Repository;
|
||||
|
||||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||
use TYPO3\CMS\Core\Context\Context;
|
||||
use TYPO3\CMS\Core\Database\Connection;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Impexp\Exception\InsufficientUserPermissionsException;
|
||||
use TYPO3\CMS\Impexp\Exception\MalformedPresetException;
|
||||
use TYPO3\CMS\Impexp\Exception\PresetNotFoundException;
|
||||
|
||||
/**
|
||||
* Export preset repository manages export presets.
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API.
|
||||
*/
|
||||
final readonly class PresetRepository
|
||||
{
|
||||
private const string PRESET_TABLE = 'tx_impexp_presets';
|
||||
|
||||
public function __construct(
|
||||
private ConnectionPool $connectionPool,
|
||||
private Context $context,
|
||||
) {}
|
||||
|
||||
public function getPresets(int $pageId): array
|
||||
{
|
||||
$backendUser = $this->getBackendUser();
|
||||
$queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::PRESET_TABLE);
|
||||
$queryBuilder->select('*')
|
||||
->from(self::PRESET_TABLE)
|
||||
->where(
|
||||
$queryBuilder->expr()->or(
|
||||
$queryBuilder->expr()->gt('public', $queryBuilder->createNamedParameter(0, Connection::PARAM_INT)),
|
||||
$queryBuilder->expr()->eq('user_uid', $queryBuilder->createNamedParameter($backendUser->user['uid'], Connection::PARAM_INT))
|
||||
)
|
||||
);
|
||||
if ($pageId) {
|
||||
$queryBuilder->andWhere(
|
||||
$queryBuilder->expr()->or(
|
||||
$queryBuilder->expr()->eq('item_uid', $queryBuilder->createNamedParameter($pageId, Connection::PARAM_INT)),
|
||||
$queryBuilder->expr()->eq('item_uid', $queryBuilder->createNamedParameter(0, Connection::PARAM_INT))
|
||||
)
|
||||
);
|
||||
}
|
||||
$presets = $queryBuilder->executeQuery();
|
||||
// @todo: View should handle default option and data details parsing, not repository.
|
||||
$options = [''];
|
||||
while ($presetCfg = $presets->fetchAssociative()) {
|
||||
$options[$presetCfg['uid']] = $presetCfg['title'] . ' [' . $presetCfg['uid'] . ']'
|
||||
. ($presetCfg['public'] ? ' [Public]' : '')
|
||||
. ((int)$presetCfg['user_uid'] === (int)$backendUser->user['uid'] ? ' [Own]' : '');
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
public function createPreset(array $data): void
|
||||
{
|
||||
$timestamp = $this->context->getPropertyFromAspect('date', 'timestamp');
|
||||
$this->connectionPool->getConnectionForTable(self::PRESET_TABLE)->insert(
|
||||
self::PRESET_TABLE,
|
||||
[
|
||||
'user_uid' => $this->getBackendUser()->user['uid'],
|
||||
'public' => $data['preset']['public'],
|
||||
'title' => $data['preset']['title'],
|
||||
'item_uid' => (int)$data['pagetree']['id'],
|
||||
'preset_data' => serialize($data),
|
||||
'tstamp' => $timestamp,
|
||||
'crdate' => $timestamp,
|
||||
],
|
||||
['preset_data' => Connection::PARAM_LOB]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InsufficientUserPermissionsException
|
||||
* @throws PresetNotFoundException
|
||||
*/
|
||||
public function updatePreset(int $uid, array $data): void
|
||||
{
|
||||
$backendUser = $this->getBackendUser();
|
||||
$preset = $this->getPreset($uid);
|
||||
if (!($backendUser->isAdmin() || (int)$preset['user_uid'] === (int)$backendUser->user['uid'])) {
|
||||
throw new InsufficientUserPermissionsException(
|
||||
'ERROR: You were not the owner of the preset so you could not delete it.',
|
||||
1604584766
|
||||
);
|
||||
}
|
||||
$timestamp = $this->context->getPropertyFromAspect('date', 'timestamp');
|
||||
$this->connectionPool->getConnectionForTable(self::PRESET_TABLE)->update(
|
||||
self::PRESET_TABLE,
|
||||
[
|
||||
'public' => $data['preset']['public'],
|
||||
'title' => $data['preset']['title'],
|
||||
'item_uid' => $data['pagetree']['id'],
|
||||
'preset_data' => serialize($data),
|
||||
'tstamp' => $timestamp,
|
||||
],
|
||||
['uid' => $uid],
|
||||
['preset_data' => Connection::PARAM_LOB]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MalformedPresetException
|
||||
*/
|
||||
public function loadPreset(int $uid): array
|
||||
{
|
||||
$preset = $this->getPreset($uid);
|
||||
// @todo: Move this to a json array instead.
|
||||
$presetData = unserialize($preset['preset_data'], ['allowed_classes' => false]);
|
||||
if (!is_array($presetData)) {
|
||||
throw new MalformedPresetException(
|
||||
'ERROR: No configuration data found in preset record!',
|
||||
1604608922
|
||||
);
|
||||
}
|
||||
return $presetData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InsufficientUserPermissionsException
|
||||
* @throws PresetNotFoundException
|
||||
*/
|
||||
public function deletePreset(int $uid): void
|
||||
{
|
||||
$backendUser = $this->getBackendUser();
|
||||
$preset = $this->getPreset($uid);
|
||||
if (!($backendUser->isAdmin() || (int)$preset['user_uid'] === (int)$backendUser->user['uid'])) {
|
||||
throw new InsufficientUserPermissionsException(
|
||||
'ERROR: You were not the owner of the preset so you could not delete it.',
|
||||
1604564346
|
||||
);
|
||||
}
|
||||
$this->connectionPool->getConnectionForTable(self::PRESET_TABLE)->delete(
|
||||
self::PRESET_TABLE,
|
||||
['uid' => $uid]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get raw preset from database. Does not unserialize preset_data as opposed to public loadPreset().
|
||||
*
|
||||
* @throws PresetNotFoundException
|
||||
*/
|
||||
private function getPreset(int $uid): array
|
||||
{
|
||||
$queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::PRESET_TABLE);
|
||||
$preset = $queryBuilder->select('*')
|
||||
->from(self::PRESET_TABLE)
|
||||
->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, Connection::PARAM_INT)))
|
||||
->executeQuery()
|
||||
->fetchAssociative();
|
||||
if (!is_array($preset)) {
|
||||
throw new PresetNotFoundException(
|
||||
'ERROR: No valid preset #' . $uid . ' found.',
|
||||
1604608843
|
||||
);
|
||||
}
|
||||
return $preset;
|
||||
}
|
||||
|
||||
private function getBackendUser(): BackendUserAuthentication
|
||||
{
|
||||
return $GLOBALS['BE_USER'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Event;
|
||||
|
||||
use TYPO3\CMS\Impexp\Import;
|
||||
|
||||
/**
|
||||
* This event is triggered when an import file is about to be imported
|
||||
*/
|
||||
final readonly class BeforeImportEvent
|
||||
{
|
||||
public function __construct(
|
||||
private Import $import,
|
||||
private string $file
|
||||
) {}
|
||||
|
||||
public function getImport(): Import
|
||||
{
|
||||
return $this->import;
|
||||
}
|
||||
|
||||
/**
|
||||
* The file being about to be imported
|
||||
*/
|
||||
public function getFile(): string
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp;
|
||||
|
||||
/**
|
||||
* An exception.
|
||||
* More specific exceptions extend this.
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API. It is allowed to catch exceptions of this type.
|
||||
*/
|
||||
class Exception extends \Exception {}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Exception;
|
||||
|
||||
use TYPO3\CMS\Impexp\Exception;
|
||||
|
||||
/**
|
||||
* Import failed
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API.
|
||||
*/
|
||||
class ImportFailedException extends Exception {}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Exception;
|
||||
|
||||
use TYPO3\CMS\Impexp\Exception;
|
||||
|
||||
/**
|
||||
* Backend user is not allowed to perform import / export action
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API.
|
||||
*/
|
||||
class InsufficientUserPermissionsException extends Exception {}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Exception;
|
||||
|
||||
use TYPO3\CMS\Impexp\Exception;
|
||||
|
||||
/**
|
||||
* File could not be loaded
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API.
|
||||
*/
|
||||
class LoadingFileFailedException extends Exception {}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Exception;
|
||||
|
||||
use TYPO3\CMS\Impexp\Exception;
|
||||
|
||||
/**
|
||||
* Export preset is corrupted and cannot be used
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API.
|
||||
*/
|
||||
class MalformedPresetException extends Exception {}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Exception;
|
||||
|
||||
use TYPO3\CMS\Impexp\Exception;
|
||||
|
||||
/**
|
||||
* Prerequisites are not met
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API.
|
||||
*/
|
||||
class PrerequisitesNotMetException extends Exception {}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Exception;
|
||||
|
||||
use TYPO3\CMS\Impexp\Exception;
|
||||
|
||||
/**
|
||||
* Export preset could not be found
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API.
|
||||
*/
|
||||
class PresetNotFoundException extends Exception {}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Initialization;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use TYPO3\CMS\Core\Attribute\AsEventListener;
|
||||
use TYPO3\CMS\Core\Package\Event\PackageInitializationEvent;
|
||||
use TYPO3\CMS\Core\Package\Initialization\CheckForImportRequirements;
|
||||
use TYPO3\CMS\Core\Registry;
|
||||
use TYPO3\CMS\Impexp\Utility\ImportExportUtility;
|
||||
|
||||
/**
|
||||
* Listener to import a T3D or XML file after package activation
|
||||
*/
|
||||
final readonly class ImportContentOnPackageInitialization
|
||||
{
|
||||
public function __construct(
|
||||
private Registry $registry,
|
||||
private ImportExportUtility $importExportUtility,
|
||||
private LoggerInterface $logger,
|
||||
) {}
|
||||
|
||||
#[AsEventListener(after: CheckForImportRequirements::class)]
|
||||
public function __invoke(PackageInitializationEvent $event): void
|
||||
{
|
||||
$packagePath = $event->getPackage()->getPackagePath();
|
||||
$registryKeyPrefix = $event->getExtensionKey();
|
||||
$registryKeysToCheck = [
|
||||
$registryKeyPrefix . ':Initialisation/data.t3d',
|
||||
$registryKeyPrefix . ':Initialisation/dataImported',
|
||||
];
|
||||
foreach ($registryKeysToCheck as $registryKeyToCheck) {
|
||||
if ($this->registry->get('extensionDataImport', $registryKeyToCheck)) {
|
||||
// Data was imported before -> early return
|
||||
return;
|
||||
}
|
||||
}
|
||||
$importFileToUse = null;
|
||||
$possibleImportFiles = [
|
||||
$packagePath . 'Initialisation/data.t3d',
|
||||
$packagePath . 'Initialisation/data.xml',
|
||||
];
|
||||
foreach ($possibleImportFiles as $possibleImportFile) {
|
||||
if (!file_exists($possibleImportFile)) {
|
||||
continue;
|
||||
}
|
||||
$importFileToUse = $possibleImportFile;
|
||||
}
|
||||
if ($importFileToUse === null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// If the package ships its own site configurations in Initialisation/Site/, defer to
|
||||
// ImportSiteConfigurationsOnPackageInitialization which handles the remapping itself.
|
||||
if (is_dir($packagePath . 'Initialisation/Site')) {
|
||||
$this->importExportUtility->disableSiteConfigurationImport();
|
||||
}
|
||||
$importResult = $this->importExportUtility->importT3DFile($importFileToUse, 0);
|
||||
$this->registry->set('extensionDataImport', $registryKeyPrefix . ':Initialisation/dataImported', 1);
|
||||
$event->addStorageEntry(__CLASS__, [
|
||||
'importResult' => $importResult,
|
||||
'importFileToUse' => $importFileToUse,
|
||||
'import' => $this->importExportUtility->getImport(),
|
||||
]);
|
||||
} catch (\ErrorException $e) {
|
||||
$this->logger->warning($e->getMessage(), ['exception' => $e]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Initialization;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use TYPO3\CMS\Core\Attribute\AsEventListener;
|
||||
use TYPO3\CMS\Core\Configuration\Exception\SiteConfigurationWriteException;
|
||||
use TYPO3\CMS\Core\Configuration\SiteConfiguration;
|
||||
use TYPO3\CMS\Core\Configuration\SiteWriter;
|
||||
use TYPO3\CMS\Core\Core\Environment;
|
||||
use TYPO3\CMS\Core\Package\Event\PackageInitializationEvent;
|
||||
use TYPO3\CMS\Core\Registry;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Impexp\Import;
|
||||
|
||||
/**
|
||||
* Listener to import site configurations after package initialization
|
||||
*/
|
||||
final readonly class ImportSiteConfigurationsOnPackageInitialization
|
||||
{
|
||||
public function __construct(
|
||||
private Registry $registry,
|
||||
private SiteConfiguration $siteConfiguration,
|
||||
private SiteWriter $siteWriter,
|
||||
private LoggerInterface $logger,
|
||||
) {}
|
||||
|
||||
#[AsEventListener(after: ImportContentOnPackageInitialization::class)]
|
||||
public function __invoke(PackageInitializationEvent $event): void
|
||||
{
|
||||
if (!$event->hasStorageEntry(ImportContentOnPackageInitialization::class)
|
||||
|| !($import = $event->getStorageEntry(ImportContentOnPackageInitialization::class)->getResult()['import'] ?? null) instanceof Import
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$extensionKey = $event->getExtensionKey();
|
||||
$importAbsFolder = $event->getPackage()->getPackagePath() . 'Initialisation/Site';
|
||||
if (!is_dir($importAbsFolder)) {
|
||||
return;
|
||||
}
|
||||
$destinationFolder = Environment::getConfigPath() . '/sites';
|
||||
GeneralUtility::mkdir($destinationFolder);
|
||||
$existingSites = $this->siteConfiguration->resolveAllExistingSites(false);
|
||||
// @todo: Get rid of symfony finder here: We should use low level tools
|
||||
// here to locate such files.
|
||||
$finder = GeneralUtility::makeInstance(Finder::class);
|
||||
$finder->directories()->ignoreUnreadableDirs()->in($importAbsFolder);
|
||||
if ($finder->hasResults()) {
|
||||
foreach ($finder as $siteConfigDirectory) {
|
||||
$siteIdentifier = $siteConfigDirectory->getBasename();
|
||||
if (isset($existingSites[$siteIdentifier])) {
|
||||
$this->logger->warning('Skipped importing site configuration from {key} due to existing site identifier {site}', [
|
||||
'key' => $extensionKey,
|
||||
'site' => $siteIdentifier,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
$targetDir = $destinationFolder . '/' . $siteIdentifier;
|
||||
if (!$this->registry->get('siteConfigImport', $siteIdentifier) && !is_dir($targetDir)) {
|
||||
GeneralUtility::mkdir($targetDir);
|
||||
GeneralUtility::copyDirectory($siteConfigDirectory->getPathname(), $targetDir);
|
||||
$this->registry->set('siteConfigImport', $siteIdentifier, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
$newSites = array_diff_key($this->siteConfiguration->resolveAllExistingSites(false), $existingSites);
|
||||
|
||||
$importedPages = $import->getImportMapId()['pages'] ?? [];
|
||||
$newSiteIdentifierList = [];
|
||||
foreach ($newSites as $newSite) {
|
||||
$exportedPageId = $newSite->getRootPageId();
|
||||
$siteIdentifier = $newSite->getIdentifier();
|
||||
$newSiteIdentifierList[] = $siteIdentifier;
|
||||
$importedPageId = $importedPages[$exportedPageId] ?? null;
|
||||
if ($importedPageId === null) {
|
||||
$this->logger->warning('Imported site configuration with identifier {site} could not be mapped to imported page id', [
|
||||
'site' => $siteIdentifier,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
$configuration = $this->siteConfiguration->load($siteIdentifier);
|
||||
$configuration['rootPageId'] = $importedPageId;
|
||||
try {
|
||||
$this->siteWriter->write($siteIdentifier, $configuration);
|
||||
} catch (SiteConfigurationWriteException $e) {
|
||||
$this->logger->warning(
|
||||
sprintf(
|
||||
'Imported site configuration with identifier %s could not be written: %s',
|
||||
$newSite->getIdentifier(),
|
||||
$e->getMessage()
|
||||
)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$event->addStorageEntry(__CLASS__, $newSiteIdentifierList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\Utility;
|
||||
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
|
||||
use TYPO3\CMS\Core\Log\LogManager;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Impexp\Event\BeforeImportEvent;
|
||||
use TYPO3\CMS\Impexp\Import;
|
||||
|
||||
/**
|
||||
* Utility for import / export
|
||||
* Can be used for API access for simple importing of files.
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API.
|
||||
*/
|
||||
#[Autoconfigure(public: true)]
|
||||
class ImportExportUtility
|
||||
{
|
||||
protected ?Import $import = null;
|
||||
protected EventDispatcherInterface $eventDispatcher;
|
||||
protected bool $importSiteConfigurations = true;
|
||||
|
||||
public function __construct(EventDispatcherInterface $eventDispatcher)
|
||||
{
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
|
||||
public function getImport(): ?Import
|
||||
{
|
||||
return $this->import;
|
||||
}
|
||||
|
||||
public function disableSiteConfigurationImport(): void
|
||||
{
|
||||
$this->importSiteConfigurations = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a T3D file directly
|
||||
*
|
||||
* @param string $file The full absolute path to the file
|
||||
* @param int $pid The pid under which the t3d file should be imported
|
||||
* @throws \ErrorException
|
||||
* @return int ID of first created page
|
||||
*/
|
||||
public function importT3DFile(string $file, int $pid): int
|
||||
{
|
||||
$this->import = GeneralUtility::makeInstance(Import::class);
|
||||
$this->import->setPid($pid);
|
||||
if (!$this->importSiteConfigurations) {
|
||||
$this->import->disableSiteConfigurationImport();
|
||||
}
|
||||
|
||||
$this->eventDispatcher->dispatch(new BeforeImportEvent($this->import, $file));
|
||||
|
||||
try {
|
||||
$this->import->loadFile($file);
|
||||
$this->import->importData();
|
||||
} catch (\Exception $e) {
|
||||
$logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__);
|
||||
$logger->warning(
|
||||
$e->getMessage() . PHP_EOL . implode(PHP_EOL, $this->import->getErrorLog())
|
||||
);
|
||||
}
|
||||
|
||||
// Get id of first created page:
|
||||
$importResponse = 0;
|
||||
$importMapId = $this->import->getImportMapId();
|
||||
if (isset($importMapId['pages'])) {
|
||||
$newPages = $importMapId['pages'];
|
||||
$importResponse = (int)reset($newPages);
|
||||
}
|
||||
|
||||
// Check for errors during the import process:
|
||||
if ($this->import->hasErrors()) {
|
||||
if (!$importResponse) {
|
||||
throw new \ErrorException('No page records imported', 1377625537);
|
||||
}
|
||||
}
|
||||
return $importResponse;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Impexp\View;
|
||||
|
||||
use TYPO3\CMS\Backend\Tree\View\AbstractTreeView;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Core\Imaging\IconFactory;
|
||||
use TYPO3\CMS\Core\Imaging\IconSize;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Extension of the page tree class. Used to get the tree of pages to export.
|
||||
*
|
||||
* @internal This class is not considered part of the public TYPO3 API.
|
||||
*/
|
||||
class ExportPageTreeView extends AbstractTreeView
|
||||
{
|
||||
/**
|
||||
* If set, then ALL items will be expanded, regardless of stored settings.
|
||||
*/
|
||||
protected bool $expandAll = false;
|
||||
|
||||
/**
|
||||
* Points to the current mountpoint key
|
||||
* @var int
|
||||
*/
|
||||
public $bank = 0;
|
||||
|
||||
/**
|
||||
* Init function
|
||||
* REMEMBER to feed a $clause which will filter out non-readable pages!
|
||||
*
|
||||
* @param string $clause Part of where query which will filter out non-readable pages.
|
||||
* @param string $orderByFields Record ORDER BY field
|
||||
*/
|
||||
public function init($clause = '', $orderByFields = '')
|
||||
{
|
||||
$tag = \Local\Multilanguage\Service\DefaultLanguageTagService::getTag();
|
||||
parent::init(" AND deleted=0 AND (language_tag='" . $tag . "' OR language_tag='') " . $clause, $orderByFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates title attribute content for pages.
|
||||
* Uses API function in \TYPO3\CMS\Backend\Utility\BackendUtility which will retrieve lots of useful information for pages.
|
||||
*
|
||||
* @param array $row The table row.
|
||||
* @return string
|
||||
*/
|
||||
protected function getTitleAttrib($row)
|
||||
{
|
||||
return BackendUtility::titleAttribForPages($row, '1=1 ', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapping Plus/Minus icon, unused in Export Page Tree
|
||||
*/
|
||||
protected function PMicon($row, $a, $c, $nextCount, $isOpen)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Construction of the tree structure with predefined depth.
|
||||
*
|
||||
* @param int $pid Page ID
|
||||
* @param int $levels Page tree levels
|
||||
*/
|
||||
public function buildTreeByLevels(int $pid, int $levels): void
|
||||
{
|
||||
$this->expandAll = true;
|
||||
$checkSub = $levels > 0;
|
||||
|
||||
$this->buildTree($pid, $levels, $checkSub);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creation of a tree structure with predefined depth to prepare the export.
|
||||
*
|
||||
* @param int $pid Page ID
|
||||
* @param int $levels Page tree levels
|
||||
* @param bool $checkSub Should root page be checked for sub pages?
|
||||
*/
|
||||
protected function buildTree(int $pid, int $levels, bool $checkSub): void
|
||||
{
|
||||
$this->reset();
|
||||
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
|
||||
|
||||
// Root page
|
||||
if ($pid > 0) {
|
||||
$rootRecord = BackendUtility::getRecordWSOL('pages', $pid);
|
||||
$rootHtml = $iconFactory->getIconForRecord('pages', $rootRecord, IconSize::SMALL)->render();
|
||||
} else {
|
||||
$rootRecord = [
|
||||
'title' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'],
|
||||
'uid' => 0,
|
||||
];
|
||||
$rootHtml = $iconFactory->getIcon('apps-pagetree-root', IconSize::SMALL)->render();
|
||||
}
|
||||
|
||||
$this->tree[] = [
|
||||
'HTML' => $rootHtml,
|
||||
'row' => $rootRecord,
|
||||
'hasSub' => $checkSub,
|
||||
'bank' => $this->bank,
|
||||
];
|
||||
|
||||
// Subtree
|
||||
if ($checkSub) {
|
||||
$this->getTree($pid, $levels);
|
||||
}
|
||||
|
||||
$idH = [];
|
||||
$idH[$pid]['uid'] = $pid;
|
||||
if (!empty($this->buffer_idH)) {
|
||||
$idH[$pid]['subrow'] = $this->buffer_idH;
|
||||
}
|
||||
$this->buffer_idH = $idH;
|
||||
|
||||
// Check if root page has subtree
|
||||
if (empty($this->buffer_idH)) {
|
||||
$this->tree[0]['hasSub'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the HTML code for displaying the structure found inside the ->tree array
|
||||
*
|
||||
* @param array|string $treeArr "tree-array" - if blank string, the internal ->tree array is used.
|
||||
* @return string The HTML code for the tree
|
||||
*/
|
||||
public function printTree($treeArr = '')
|
||||
{
|
||||
if (!is_array($treeArr)) {
|
||||
$treeArr = $this->tree;
|
||||
}
|
||||
$out = '';
|
||||
$closeDepth = [];
|
||||
foreach ($treeArr as $treeItem) {
|
||||
if ($treeItem['isFirst'] ?? false) {
|
||||
$out .= '<ul class="treelist">';
|
||||
}
|
||||
|
||||
$idAttr = htmlspecialchars('pages' . $treeItem['row']['uid']);
|
||||
$out .= '
|
||||
<li id="' . $idAttr . '">
|
||||
<span class="treelist-group">
|
||||
<span class="treelist-icon">' . $treeItem['HTML'] . '</span>
|
||||
<span class="treelist-title">' . $this->getTitleStr($treeItem['row']) . '</span>
|
||||
</span>';
|
||||
|
||||
if (!($treeItem['hasSub'] ?? false)) {
|
||||
$out .= '</li>';
|
||||
}
|
||||
|
||||
// We have to remember if this is the last one
|
||||
// on level X so the last child on level X+1 closes the <ul>-tag
|
||||
if ($treeItem['isLast'] ?? false) {
|
||||
$closeDepth[$treeItem['invertedDepth']] = 1;
|
||||
}
|
||||
// If this is the last one and does not have subitems, we need to close
|
||||
// the tree as long as the upper levels have last items too
|
||||
if (($treeItem['isLast'] ?? false) && !($treeItem['hasSub'] ?? false)) {
|
||||
for ($i = $treeItem['invertedDepth']; ($closeDepth[$i] ?? 0) == 1; $i++) {
|
||||
$closeDepth[$i] = 0;
|
||||
$out .= '</ul></li>';
|
||||
}
|
||||
}
|
||||
}
|
||||
return '<ul class="treelist treelist-root treelist-root-clean">' . $out . '</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE/FALSE if the next level for $id should be expanded - based on the ->expandAll flag.
|
||||
* Extending parent function
|
||||
*
|
||||
* @param int $id Record id/key
|
||||
* @return bool
|
||||
* @internal
|
||||
* @see \TYPO3\CMS\Backend\Tree\View\PageTreeView::expandNext()
|
||||
*/
|
||||
public function expandNext($id)
|
||||
{
|
||||
return $this->expandAll;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the title for the input record. If blank, a "no title" label (localized) will be returned.
|
||||
* Do NOT htmlspecialchar the string from this function - has already been done.
|
||||
*
|
||||
* @param array $row The input row array (where the key "title" is used for the title)
|
||||
* @return string The title.
|
||||
*/
|
||||
protected function getTitleStr(array $row): string
|
||||
{
|
||||
$recordTitle = $row['title'] ?? '';
|
||||
if (trim($recordTitle) === '') {
|
||||
return '<em>[' . htmlspecialchars($this->getLanguageService()->sL('core.core:labels.no_title')) . ']</em>';
|
||||
}
|
||||
return htmlspecialchars(BackendUtility::cropToTitleLength($recordTitle));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Definitions for routes provided by EXT:impexp
|
||||
*/
|
||||
return [
|
||||
// Register click menu entry point
|
||||
'tx_impexp_export' => [
|
||||
'path' => '/record/importexport/export',
|
||||
'target' => \TYPO3\CMS\Impexp\Controller\ExportController::class . '::handleRequest',
|
||||
],
|
||||
'tx_impexp_import' => [
|
||||
'path' => '/record/importexport/import',
|
||||
'target' => \TYPO3\CMS\Impexp\Controller\ImportController::class . '::handleRequest',
|
||||
],
|
||||
];
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'status-reference-hard' => [
|
||||
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
|
||||
'source' => 'EXT:impexp/Resources/Public/Icons/status-reference-hard.png',
|
||||
],
|
||||
'status-reference-soft' => [
|
||||
'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider::class,
|
||||
'source' => 'EXT:impexp/Resources/Public/Icons/status-reference-soft.png',
|
||||
],
|
||||
];
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'dependencies' => [
|
||||
'backend',
|
||||
],
|
||||
'imports' => [
|
||||
'@typo3/impexp/' => 'EXT:impexp/Resources/Public/JavaScript/',
|
||||
],
|
||||
];
|
||||
@@ -0,0 +1,8 @@
|
||||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
public: false
|
||||
|
||||
TYPO3\CMS\Impexp\:
|
||||
resource: '../Classes/*'
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
defined('TYPO3') or die();
|
||||
|
||||
$fields = [
|
||||
'tx_impexp_origuid' => [
|
||||
'config' => [
|
||||
'type' => 'passthrough',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('pages', $fields);
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
defined('TYPO3') or die();
|
||||
|
||||
$fields = [
|
||||
'tx_impexp_origuid' => [
|
||||
'config' => [
|
||||
'type' => 'passthrough',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('sys_template', $fields);
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
defined('TYPO3') or die();
|
||||
|
||||
$fields = [
|
||||
'tx_impexp_origuid' => [
|
||||
'config' => [
|
||||
'type' => 'passthrough',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('tt_content', $fields);
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'ctrl' => [
|
||||
'title' => 'impexp.db:tx_impexp_presets',
|
||||
'label' => 'title',
|
||||
'default_sortby' => 'title',
|
||||
'tstamp' => 'tstamp',
|
||||
'crdate' => 'crdate',
|
||||
'typeicon_classes' => [
|
||||
'default' => 'actions-cog',
|
||||
],
|
||||
'hideTable' => true,
|
||||
'rootLevel' => -1,
|
||||
],
|
||||
'columns' => [
|
||||
'title' => [
|
||||
'label' => 'impexp.db:title',
|
||||
'config' => [
|
||||
'type' => 'passthrough',
|
||||
],
|
||||
],
|
||||
'public' => [
|
||||
'label' => 'impexp.db:public',
|
||||
'config' => [
|
||||
'type' => 'passthrough',
|
||||
],
|
||||
],
|
||||
'user_uid' => [
|
||||
'label' => 'impexp.db:user_uid',
|
||||
'config' => [
|
||||
'type' => 'passthrough',
|
||||
],
|
||||
],
|
||||
'item_uid' => [
|
||||
'label' => 'impexp.db:item_uid',
|
||||
'config' => [
|
||||
'type' => 'passthrough',
|
||||
],
|
||||
],
|
||||
'preset_data' => [
|
||||
'label' => 'impexp.db:preset_data',
|
||||
'config' => [
|
||||
'type' => 'passthrough',
|
||||
],
|
||||
],
|
||||
],
|
||||
'types' => [
|
||||
0 => [
|
||||
'showitem' => 'title, public, user_uid, item_uid, preset_data',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
After Width: | Height: | Size: 162 KiB |
@@ -0,0 +1,7 @@
|
||||
.. Automatic screenshot: Remove this line if you want to manually change this file
|
||||
|
||||
.. figure:: /Images/AutomaticScreenshots/CheckAndPerformImport.png
|
||||
:alt: Check and perform the import
|
||||
:class: with-shadow
|
||||
|
||||
Check and perform the import
|
||||
|
After Width: | Height: | Size: 173 KiB |
@@ -0,0 +1,7 @@
|
||||
.. Automatic screenshot: Remove this line if you want to manually change this file
|
||||
|
||||
.. figure:: /Images/AutomaticScreenshots/CheckExport.png
|
||||
:alt: Check the exported data
|
||||
:class: with-shadow
|
||||
|
||||
Check the exported data
|
||||
|
After Width: | Height: | Size: 130 KiB |
@@ -0,0 +1,7 @@
|
||||
.. Automatic screenshot: Remove this line if you want to manually change this file
|
||||
|
||||
.. figure:: /Images/AutomaticScreenshots/ConfigureExport.png
|
||||
:alt: Configure the data to be exported
|
||||
:class: with-shadow
|
||||
|
||||
Configure the data to be exported
|
||||
|
After Width: | Height: | Size: 76 KiB |
@@ -0,0 +1,7 @@
|
||||
.. Automatic screenshot: Remove this line if you want to manually change this file
|
||||
|
||||
.. figure:: /Images/AutomaticScreenshots/ConfigureImport.png
|
||||
:alt: Configure the import
|
||||
:class: with-shadow
|
||||
|
||||
Configure the import
|
||||
|
After Width: | Height: | Size: 115 KiB |
@@ -0,0 +1,7 @@
|
||||
.. Automatic screenshot: Remove this line if you want to manually change this file
|
||||
|
||||
.. figure:: /Images/AutomaticScreenshots/ContextMenuExport.png
|
||||
:alt: Select "More options... > Export"
|
||||
:class: with-shadow
|
||||
|
||||
Select "More options... > Export"
|
||||
|
After Width: | Height: | Size: 106 KiB |
@@ -0,0 +1,7 @@
|
||||
.. Automatic screenshot: Remove this line if you want to manually change this file
|
||||
|
||||
.. figure:: /Images/AutomaticScreenshots/ContextMenuImport.png
|
||||
:alt: Select "More options... > Import"
|
||||
:class: with-shadow
|
||||
|
||||
Select "More options... > Import"
|
||||
|
After Width: | Height: | Size: 58 KiB |
@@ -0,0 +1,7 @@
|
||||
.. Automatic screenshot: Remove this line if you want to manually change this file
|
||||
|
||||
.. figure:: /Images/AutomaticScreenshots/DownloadExport.png
|
||||
:alt: Download the export data
|
||||
:class: with-shadow
|
||||
|
||||
Download the export data
|
||||
|
After Width: | Height: | Size: 71 KiB |
@@ -0,0 +1,7 @@
|
||||
.. Automatic screenshot: Remove this line if you want to manually change this file
|
||||
|
||||
.. figure:: /Images/AutomaticScreenshots/ImpExp.png
|
||||
:alt: Export module of current TYPO3
|
||||
:class: with-shadow
|
||||
|
||||
Export module of current TYPO3
|
||||
|
After Width: | Height: | Size: 33 KiB |
@@ -0,0 +1,7 @@
|
||||
.. Automatic screenshot: Remove this line if you want to manually change this file
|
||||
|
||||
.. figure:: /Images/AutomaticScreenshots/Presets.png
|
||||
:alt: Save or load an export preset
|
||||
:class: with-shadow
|
||||
|
||||
Save or load an export preset
|
||||
|
After Width: | Height: | Size: 57 KiB |
@@ -0,0 +1,7 @@
|
||||
.. Automatic screenshot: Remove this line if you want to manually change this file
|
||||
|
||||
.. figure:: /Images/AutomaticScreenshots/SelectAdvancedExportOptions.png
|
||||
:alt: Select advanced export options
|
||||
:class: with-shadow
|
||||
|
||||
Select advanced export options
|
||||
|
After Width: | Height: | Size: 76 KiB |
@@ -0,0 +1,7 @@
|
||||
.. Automatic screenshot: Remove this line if you want to manually change this file
|
||||
|
||||
.. figure:: /Images/AutomaticScreenshots/UpdateContent.png
|
||||
:alt: Update content in an existing structure
|
||||
:class: with-shadow
|
||||
|
||||
Update content in an existing structure
|
||||
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,7 @@
|
||||
.. Automatic screenshot: Remove this line if you want to manually change this file
|
||||
|
||||
.. figure:: /Images/AutomaticScreenshots/UploadImport.png
|
||||
:alt: Upload the export data
|
||||
:class: with-shadow
|
||||
|
||||
Upload the export data
|
||||
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,5 @@
|
||||
.. figure:: /Images/ManualScreenshots/ImpExpV3.8.png
|
||||
:class: with-shadow
|
||||
:alt: Export module of TYPO3 3.8.0 (year 2005)
|
||||
|
||||
Export module of TYPO3 3.8.0 (year 2005)
|
||||
|
After Width: | Height: | Size: 27 KiB |
@@ -0,0 +1 @@
|
||||
.. You can put central messages to display on all pages here
|
||||
@@ -0,0 +1,53 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _start:
|
||||
|
||||
=====================
|
||||
TYPO3 Import / Export
|
||||
=====================
|
||||
|
||||
:Extension key:
|
||||
impexp
|
||||
|
||||
:Package name:
|
||||
typo3/cms-impexp
|
||||
|
||||
:Version:
|
||||
|release|
|
||||
|
||||
:Language:
|
||||
en
|
||||
|
||||
:Author:
|
||||
TYPO3 contributors
|
||||
|
||||
:License:
|
||||
This document is published under the
|
||||
`Open Content License <https://www.openhub.net/licenses/opl>`__.
|
||||
|
||||
:Rendered:
|
||||
|today|
|
||||
|
||||
----
|
||||
|
||||
This is a tool for importing and exporting records using XML or the custom T3D
|
||||
format.
|
||||
|
||||
----
|
||||
|
||||
**Table of Contents:**
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:titlesonly:
|
||||
|
||||
Introduction/Index
|
||||
Installation/Index
|
||||
Usage/Index
|
||||
Security/Index
|
||||
|
||||
.. Meta Menu
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
Sitemap
|
||||
@@ -0,0 +1,57 @@
|
||||
:navigation-title: Installation
|
||||
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _installation:
|
||||
|
||||
====================================
|
||||
Installation of the impexp extension
|
||||
====================================
|
||||
|
||||
This extension is part of the TYPO3 Core, but not installed by default.
|
||||
|
||||
.. contents:: Table of contents
|
||||
:local:
|
||||
|
||||
.. _installation_composer:
|
||||
|
||||
Installation with Composer
|
||||
==========================
|
||||
|
||||
Check whether you are already using the extension with:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
composer show | grep impexp
|
||||
|
||||
This should either give you no result or something similar to:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
typo3/cms-impexp v12.4.11
|
||||
|
||||
If it is not installed yet, use the ``composer require`` command to install
|
||||
the extension:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
composer require typo3/cms-impexp
|
||||
|
||||
The given version depends on the version of the TYPO3 Core you are using.
|
||||
|
||||
.. _installation_legacy:
|
||||
|
||||
Installation without Composer
|
||||
=============================
|
||||
|
||||
In an installation without Composer, the extension is already shipped but might
|
||||
not be activated yet. Activate it as follows:
|
||||
|
||||
#. In the backend, navigate to the :guilabel:`System > Extensions`
|
||||
module.
|
||||
#. Click the :guilabel:`Activate` icon for the Import / Export extension.
|
||||
|
||||
.. figure:: /Images/ManualScreenshots/InstallActivate.png
|
||||
:class: with-border
|
||||
:alt: Extension manager showing Import / Export extension
|
||||
|
||||
Extension manager showing Import / Export extension
|
||||
@@ -0,0 +1,70 @@
|
||||
:navigation-title: Introduction
|
||||
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _known-problems:
|
||||
.. _introduction:
|
||||
|
||||
======================================================
|
||||
Introduction into the system extension "Import/Export"
|
||||
======================================================
|
||||
|
||||
The system extension "Import/Export" (EXT:impexp) allows content to be exported
|
||||
from one installation of TYPO3 and then imported into another. Exported data
|
||||
includes content from multiple tables including :sql:`tt_content` as well as
|
||||
images and other files stored in :directory:`fileadmin/`.
|
||||
|
||||
This extension is often used to manage content for :ref:`distributions <t3coreapi:distribution>`
|
||||
and also training and demonstration purposes.
|
||||
|
||||
.. _merging_multiple_sets_of_data:
|
||||
|
||||
Merging multiple sets of data
|
||||
=============================
|
||||
|
||||
By default the identifiers are changed when importing data, making it possible to
|
||||
merge several projects into one installation. The table identifiers are
|
||||
automatically changed in such a way that content elements remain attached to
|
||||
their pages and images to their content elements.
|
||||
|
||||
It is also possible to keep the identifiers (`uids`) to allow the reproduction
|
||||
of the exact same page and content tree.
|
||||
|
||||
.. _what-doesnt-it-do:
|
||||
|
||||
What doesn't it do?
|
||||
===================
|
||||
|
||||
* Exported content does not include code from any installed extensions or
|
||||
sitepackages.
|
||||
* This extension is not used for the :guilabel:`Download`
|
||||
feature in the :guilabel:`List` module.
|
||||
|
||||
.. _backward_compatibility:
|
||||
|
||||
Backward compatibility
|
||||
======================
|
||||
|
||||
The data structure for content exports have seen very little changes since their
|
||||
original inception. It is sometimes possible to export content from a fifteen
|
||||
year old TYPO3 installation straight into a current installation of TYPO3.
|
||||
|
||||
It is often more feasible to use the import/export tool
|
||||
than it is to attempt to update old installations of TYPO3.
|
||||
|
||||
The following images show the export dialog of a current TYPO3 installation and
|
||||
TYPO3 v3.8.0: They correspond pretty much.
|
||||
|
||||
However, several details may change due to Deprecations and Breaking Changes,
|
||||
which can lead to issues with old import data. In cases where the import fails,
|
||||
it is recommended to try to manually export assets/files, and re-create the
|
||||
reference Index after import. The older an installation is, the more manual
|
||||
rework is expected.
|
||||
|
||||
Ongoing improvements to the Import/Export code base can only made, when
|
||||
legacy considerations are not the first priority. A "guaranteed" fully-working
|
||||
export and re-import is only given for T3D structures within the same
|
||||
major version.
|
||||
|
||||
.. include:: /Images/AutomaticScreenshots/ImpExp.rst.txt
|
||||
|
||||
.. include:: /Images/ManualScreenshots/ImpExpV3.8.rst.txt
|
||||
@@ -0,0 +1,67 @@
|
||||
:navigation-title: Security
|
||||
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _security:
|
||||
|
||||
=========================================
|
||||
Security considerations regarding exports
|
||||
=========================================
|
||||
|
||||
Exported content in TYPO3 can contain sensitive or restricted information that
|
||||
needs to be properly secured. This document outlines the recommended best
|
||||
practices for managing the security risks associated with exporting content.
|
||||
The following sections explain:
|
||||
|
||||
- Why you should **disable the export extension when not in use** to reduce
|
||||
the risk of unintentional data exposure.
|
||||
- How to **prevent unauthorized access** by restricting the visibility of
|
||||
export options in the TYPO3 interface.
|
||||
- Why it is important to **secure the export directory** to block unauthorized
|
||||
file access on different webserver setups.
|
||||
- How to **report a security issue** to the TYPO3 Security Team if you
|
||||
identify vulnerabilities not addressed in this guide.
|
||||
|
||||
.. contents:: Table of contents
|
||||
|
||||
.. _security-disable-extension:
|
||||
|
||||
Disable the extension when not in use
|
||||
=====================================
|
||||
|
||||
Exported content may contain sensitive and restricted information related to
|
||||
your site. It is recommended that this extension be deactivated when it is not
|
||||
in use to prevent content being exported in error.
|
||||
|
||||
.. _security-prevent-unauthorized-access:
|
||||
|
||||
Prevent unauthorized access
|
||||
===========================
|
||||
|
||||
The export function is available by default for editors without admin rights.
|
||||
It is limited to content to which the editor has access. The export
|
||||
functionality can be hidden in the editor's context menu by using the user
|
||||
TSconfig setting :ref:`contextMenu disableItems
|
||||
<t3tsref:useroptions-contextMenu-key-disableItems>`.
|
||||
|
||||
Note that it cannot be completely disabled as there are currently other entry
|
||||
points.
|
||||
|
||||
.. _security-secure-export-directory:
|
||||
|
||||
Secure the export directory
|
||||
===========================
|
||||
|
||||
Exports are stored in :path:`fileadmin/user_upload/_temp_/importexport/`.
|
||||
TYPO3 will automatically create a :file:`.htaccess` file to prevent access to
|
||||
this folder from external sources. On Nginx webservers, the :file:`.htaccess`
|
||||
file has no effect. Follow the :ref:`Security guidelines for System
|
||||
Administrators <t3coreapi:security-administrators>` to find out how to prevent
|
||||
access to specific directories on Nginx webservers.
|
||||
|
||||
.. _security-reporting-issue:
|
||||
|
||||
Reporting a security issue
|
||||
==========================
|
||||
|
||||
If you believe you have found a security-related issue that is not listed
|
||||
here, please contact the :ref:`TYPO3 Security Team <t3coreapi:security-team>`.
|
||||
@@ -0,0 +1,10 @@
|
||||
:template: sitemap.html
|
||||
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _sitemap:
|
||||
|
||||
=======
|
||||
Sitemap
|
||||
=======
|
||||
|
||||
.. The sitemap.html template will insert here the page tree automatically.
|
||||
@@ -0,0 +1,131 @@
|
||||
:navigation-title: Command line
|
||||
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _command_line:
|
||||
|
||||
======================================================
|
||||
Using the Import/Export tool from the command line
|
||||
======================================================
|
||||
|
||||
The import/export tool can alternatively also be used via the command line.
|
||||
The advantage of using the CLI is that there is no PHP time limit, therefore
|
||||
larger page trees can be exported and imported.
|
||||
|
||||
The exports and imports can be fine-tuned through the complete set of options
|
||||
also available in the :ref:`import <import>` or :ref:`export module <export>`
|
||||
of the TYPO3 backend.
|
||||
|
||||
.. note::
|
||||
|
||||
If your TYPO3 installation is based on Composer, you can run the command
|
||||
with the shortcut :bash:`vendor/bin/typo3` instead of
|
||||
:bash:`typo3/sysext/core/bin/typo3`.
|
||||
|
||||
.. attention::
|
||||
|
||||
Exporting and importing content may expose sensitive data or bypass
|
||||
permission boundaries. Review the :ref:`security considerations regarding
|
||||
exports <security>` before using this functionality.
|
||||
|
||||
.. _command_line-export:
|
||||
|
||||
Exporting content from the command line
|
||||
=======================================
|
||||
|
||||
Export the entire TYPO3 page tree (or selected parts of it) to a data file of
|
||||
format XML or T3D:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Composer mode
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
vendor/bin/typo3 impexp:export [options] [--] [<filename>]
|
||||
|
||||
.. tab:: Classic mode
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
typo3/sysext/core/bin/typo3 impexp:export [options] [--] [<filename>]
|
||||
|
||||
With these options available:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
Arguments:
|
||||
filename The filename to export to (without file extension)
|
||||
|
||||
Options:
|
||||
--type[=TYPE] The file type (xml, t3d, t3d_compressed). [default: "xml"]
|
||||
--pid[=PID] The root page of the exported page tree. [default: -1]
|
||||
--levels[=LEVELS] The depth of the exported page tree.
|
||||
"-2": "Records on this page", "0": "This page",
|
||||
"1": "1 level down", .. "999": "Infinite levels". [default: 0]
|
||||
--table[=TABLE] Include all records of this table.
|
||||
Examples: "_ALL", "tt_content", "sys_file_reference", etc.
|
||||
(multiple values allowed)
|
||||
--record[=RECORD] Include this specific record. Pattern is "{table}:{record}".
|
||||
Examples: "tt_content:12", etc. (multiple values allowed)
|
||||
--list[=LIST] Include records of this table and page. Pattern is "{table}:{pid}".
|
||||
Examples: "be_users:0", etc. (multiple values allowed)
|
||||
--include-related[=INCLUDE-RELATED] Include record relations to this table, including the related record.
|
||||
Examples: "_ALL", "sys_category", etc. (multiple values allowed)
|
||||
--include-static[=INCLUDE-STATIC] Include record relations to this table, excluding the related record.
|
||||
Examples: "_ALL", "be_users", etc. (multiple values allowed)
|
||||
--exclude[=EXCLUDE] Exclude this specific record. Pattern is "{table}:{record}".
|
||||
Examples: "fe_users:3", etc. (multiple values allowed)
|
||||
--exclude-disabled-records Exclude records considered disabled by their TCA configuration,
|
||||
e.g. "disabled", "starttime", or "endtime" fields.
|
||||
--exclude-html-css Exclude referenced HTML and CSS files.
|
||||
--title[=TITLE] The meta title of the export.
|
||||
--description[=DESCRIPTION] The meta description of the export.
|
||||
--notes[=NOTES] The meta notes of the export.
|
||||
--dependency[=DEPENDENCY] Declare required TYPO3 extensions for the export.
|
||||
Examples: "news", "powermail", etc. (multiple values allowed)
|
||||
--save-files-outside-export-file Save files in a separate folder named "{filename}.files"
|
||||
instead of embedding them in the export file.
|
||||
|
||||
.. _command_line-import:
|
||||
|
||||
Importing content from the command line
|
||||
=======================================
|
||||
|
||||
Import an export dump file in XML or T3D format into a TYPO3 instance:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Composer mode
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
vendor/bin/typo3 impexp:import [options] [--] <file> [<pid>]
|
||||
|
||||
.. tab:: Classic mode
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
typo3/sysext/core/bin/typo3 impexp:import [options] [--] <file> [<pid>]
|
||||
|
||||
With these options available:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
Arguments:
|
||||
file The file path to import from (.t3d or .xml).
|
||||
pid The page to import to. [default: 0]
|
||||
|
||||
Options:
|
||||
--update-records Update existing records with the same UID instead of inserting new ones.
|
||||
--ignore-pid Prevent page ID correction for updated records
|
||||
(requires --update-records).
|
||||
--force-uid Force UIDs from the file.
|
||||
--import-mode[=IMPORT-MODE] Set the import mode for specific records.
|
||||
Pattern: "{table}:{record}={mode}".
|
||||
Modes:
|
||||
- For new records: "force_uid", "exclude"
|
||||
- For existing records: "as_new", "ignore_pid",
|
||||
"respect_pid", "exclude"
|
||||
Examples: "pages:987=force_uid", "tt_content:1=as_new",
|
||||
etc. (multiple values allowed)
|
||||
--enable-log Log all database actions.
|
||||
@@ -0,0 +1,128 @@
|
||||
:navigation-title: Export
|
||||
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _export:
|
||||
|
||||
==========================================
|
||||
Exporting content from TYPO3 to XML or T3D
|
||||
==========================================
|
||||
|
||||
The export functionality is only available for admin users and backend
|
||||
users for which the Page TSconfig option
|
||||
:ref:`options.impexp.enableExportForNonAdminUser
|
||||
<t3tsref:useroptions-impexp-enableExportForNonAdminUser>` has been enabled.
|
||||
|
||||
.. attention::
|
||||
|
||||
Exporting content may expose sensitive data or allow unwanted file access.
|
||||
Review the :ref:`security considerations regarding exports <security>`
|
||||
before using this functionality.
|
||||
|
||||
.. _export-open-module:
|
||||
|
||||
Open the export module
|
||||
======================
|
||||
|
||||
In the page tree, right-click the page from which you want to start the
|
||||
export (1) and select :guilabel:`More options ... > Export` (2).
|
||||
|
||||
.. include:: /Images/AutomaticScreenshots/ContextMenuExport.rst.txt
|
||||
|
||||
.. _export-configure-settings:
|
||||
|
||||
Configure the export settings
|
||||
=============================
|
||||
|
||||
On the first tab of the export module you can fine-tune the export (1).
|
||||
|
||||
- If you want to export all data of the selected page including its
|
||||
subpages, select the "Infinite" option in the :guilabel:`Levels`
|
||||
selection box.
|
||||
|
||||
- Under :guilabel:`Include tables` you can limit the types of records to
|
||||
be exported.
|
||||
|
||||
- Under :guilabel:`Include relations to tables` you specify which
|
||||
relations of the records should be included in the export file. The
|
||||
related records will be included even if they are outside the pages
|
||||
selected for export.
|
||||
|
||||
- Under :guilabel:`Use static relations for tables` you select which
|
||||
relations should be included without including the related record. This
|
||||
is useful if the related record already exists in the target TYPO3
|
||||
instance.
|
||||
|
||||
- If the same table is selected in both :guilabel:`Include relations to
|
||||
tables` and :guilabel:`Use static relations for tables`, the relation
|
||||
is treated as static.
|
||||
|
||||
- The :guilabel:`Exclude disabled elements` checkbox excludes records
|
||||
that are disabled according to their TCA configuration. This is checked
|
||||
by default.
|
||||
|
||||
Apply your changes via the :guilabel:`Update` button and repeat this step
|
||||
until the preview meets your expectations.
|
||||
|
||||
.. include:: /Images/AutomaticScreenshots/ConfigureExport.rst.txt
|
||||
|
||||
.. _export-review-records:
|
||||
|
||||
Review the records to be exported
|
||||
=================================
|
||||
|
||||
All pages selected for export are listed in the upper part of the dialog
|
||||
(1).
|
||||
|
||||
Below this is a detailed list of all data to be exported (2). Here you
|
||||
can exclude individual records or manually make them editable, if
|
||||
supported.
|
||||
|
||||
If the relation to records is lost, an orange exclamation mark will be
|
||||
shown. This happens if records are stored outside the export page tree
|
||||
or if excluded tables break relations.
|
||||
|
||||
Apply your changes by pressing the :guilabel:`Update` button and repeat
|
||||
this step as needed until the preview matches your expectations (3).
|
||||
|
||||
Then switch to the :guilabel:`Advanced Options` tab (4).
|
||||
|
||||
.. include:: /Images/AutomaticScreenshots/CheckExport.rst.txt
|
||||
|
||||
.. _export-advanced-options:
|
||||
|
||||
Optionally select advanced export options
|
||||
=========================================
|
||||
|
||||
In the third tab of the export module you can specify further export
|
||||
options (1).
|
||||
|
||||
Checking :guilabel:`Save files in extra folder ..` saves linked files
|
||||
in a separate folder instead of embedding them in the export file. This
|
||||
is mandatory for :ref:`distributions <t3coreapi:distribution>` or
|
||||
useful when handling large file sets that would otherwise bloat the
|
||||
export file and potentially exhaust memory. The folder is named
|
||||
"{filename}.files".
|
||||
|
||||
Apply your changes via the :guilabel:`Update` button (2) and then switch
|
||||
to the :guilabel:`File & Preset` tab (3) to proceed.
|
||||
|
||||
.. include:: /Images/AutomaticScreenshots/SelectAdvancedExportOptions.rst.txt
|
||||
|
||||
.. _export-perform:
|
||||
|
||||
Perform the export
|
||||
==================
|
||||
|
||||
In the second tab of the export module you can specify the metadata for
|
||||
the export (1) before starting the export process.
|
||||
|
||||
You can then either:
|
||||
|
||||
- Download the export file (2.a), or
|
||||
- Save it on the server (2.b).
|
||||
|
||||
Saving on the server is currently required if you have enabled saving
|
||||
related files in a separate folder (see
|
||||
:ref:`export-advanced-options`).
|
||||
|
||||
.. include:: /Images/AutomaticScreenshots/DownloadExport.rst.txt
|
||||
@@ -0,0 +1,84 @@
|
||||
:navigaton-title: Import
|
||||
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _import:
|
||||
|
||||
===========================================
|
||||
Importing `.t3d` files in the TYPO3 backend
|
||||
===========================================
|
||||
|
||||
The import functionality is only available for admin users and Backend
|
||||
users for which the Page TSconfig option
|
||||
:ref:`options.impexp.enableImportForNonAdminUser
|
||||
<t3tsref:useroptions-impexp-enableImportForNonAdminUser>` has been enabled.
|
||||
|
||||
.. contents:: Table of contents
|
||||
|
||||
.. note::
|
||||
|
||||
Make sure that any required extensions are installed and the database
|
||||
schema is up-to-date before starting the import. Otherwise, the data
|
||||
related to non-existing tables will not be imported.
|
||||
|
||||
.. _import-open-module:
|
||||
|
||||
Open the import module
|
||||
======================
|
||||
|
||||
In the page tree, right-click the page you want to import to (1) and
|
||||
select :guilabel:`More options ... > Import` (2).
|
||||
|
||||
.. include:: /Images/AutomaticScreenshots/ContextMenuImport.rst.txt
|
||||
|
||||
.. _import-upload-file:
|
||||
|
||||
Upload the export file
|
||||
======================
|
||||
|
||||
On the second tab of the import module you can upload the export file
|
||||
to your target TYPO3 instance.
|
||||
|
||||
Select the file to upload (1) and click the :guilabel:`Upload files`
|
||||
button (2).
|
||||
|
||||
Then switch to the :guilabel:`Import` tab (3).
|
||||
|
||||
.. include:: /Images/AutomaticScreenshots/UploadImport.rst.txt
|
||||
|
||||
.. _import-configure-settings:
|
||||
|
||||
Configure the import settings
|
||||
=============================
|
||||
|
||||
On the first tab of the import module you can configure the import.
|
||||
|
||||
First select the uploaded export file (1). Then adjust the general
|
||||
settings (2). Finally, press the :guilabel:`Preview` button (3).
|
||||
|
||||
- Checking :guilabel:`Update records` means that existing records with
|
||||
the same UID will be updated instead of newly inserted.
|
||||
|
||||
- Checking :guilabel:`Do not show differences in records` prevents
|
||||
calculation of differences between existing and imported records.
|
||||
Note: The compare function is currently broken and therefore disabled
|
||||
in the screenshot.
|
||||
|
||||
.. include:: /Images/AutomaticScreenshots/ConfigureImport.rst.txt
|
||||
|
||||
.. _import-review-data:
|
||||
|
||||
Review the data to be imported
|
||||
==============================
|
||||
|
||||
A tree with the records to be imported is displayed below the
|
||||
configuration form (1). If you change any of the options (2), you can
|
||||
reload this preview with the :guilabel:`Preview` button (3).
|
||||
|
||||
.. include:: /Images/AutomaticScreenshots/CheckAndPerformImport.rst.txt
|
||||
|
||||
.. _import-execute:
|
||||
|
||||
Execute the import
|
||||
==================
|
||||
|
||||
Click the :guilabel:`Import` button to execute the import process.
|
||||
@@ -0,0 +1,33 @@
|
||||
:navigation-title: Usage
|
||||
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _usage:
|
||||
|
||||
======================================
|
||||
How to use the Import/Export extension
|
||||
======================================
|
||||
|
||||
The import/export tool can be accessed via the :ref:`TYPO3 backend<export>` or
|
||||
the :ref:`command line<command_line>`.
|
||||
|
||||
Users with admin rights can use both the import and the export functionality.
|
||||
Editors with no admin rights can only use the export functionality (unless
|
||||
it is disabled). Editors can only export content they have access to.
|
||||
|
||||
The import functionality can be used for :ref:`content updates<content-update>`
|
||||
instead of importing the entire page tree and its content.
|
||||
|
||||
The export functionality can be used to export initial content for use in
|
||||
:ref:`distributions<t3coreapi:distribution>`.
|
||||
|
||||
It is also possible to save and load export data :ref:`presets<presets>` for
|
||||
recurring export jobs.
|
||||
|
||||
.. toctree::
|
||||
:titlesonly:
|
||||
|
||||
Export
|
||||
Import
|
||||
Update
|
||||
Presets
|
||||
CommandLine
|
||||
@@ -0,0 +1,69 @@
|
||||
:navigation-title: Presets
|
||||
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _presets:
|
||||
|
||||
=====================================================
|
||||
Saving and reusing export configurations with presets
|
||||
=====================================================
|
||||
|
||||
.. include:: /Images/AutomaticScreenshots/Presets.rst.txt
|
||||
|
||||
Any configuration settings made in the :ref:`export module <export>` are not
|
||||
saved automatically. To reuse export configurations, you need to save them
|
||||
as presets.
|
||||
|
||||
Presets are stored internally in the :sql:`tx_impexp_presets` table and can
|
||||
be included in export files by adding this table to the export.
|
||||
|
||||
.. contents:: Table of content
|
||||
|
||||
.. warning::
|
||||
|
||||
If you have manually excluded records from export, the :sql:`uid` values of
|
||||
those exclusions are saved in the preset. This can lead to unexpected
|
||||
exclusions if you reuse the preset in another TYPO3 instance.
|
||||
|
||||
Therefore, review the excluded records in the "Configuration" tab
|
||||
thoroughly when you load a preset.
|
||||
|
||||
.. _presets-save:
|
||||
|
||||
Saving a new preset
|
||||
===================
|
||||
|
||||
To save a new preset:
|
||||
|
||||
1. Go to :guilabel:`Export > File & Preset > Presets`.
|
||||
2. Enter a :guilabel:`Title of new preset` (A.1).
|
||||
3. Click :guilabel:`Save` (A.2).
|
||||
|
||||
.. _presets-load:
|
||||
|
||||
Loading an existing preset
|
||||
==========================
|
||||
|
||||
To load a saved preset:
|
||||
|
||||
1. Select the desired preset from :guilabel:`Select Preset` (B.1).
|
||||
2. Click :guilabel:`Load` (B.2).
|
||||
|
||||
.. _presets-modify:
|
||||
|
||||
Modifying an existing preset
|
||||
============================
|
||||
|
||||
To modify an existing preset:
|
||||
|
||||
1. Load the preset as described above.
|
||||
2. Make the required changes to the export settings.
|
||||
3. Select the same preset again in :guilabel:`Select Preset` (!).
|
||||
4. Click :guilabel:`Save` to overwrite the preset.
|
||||
|
||||
.. _presets-visibility:
|
||||
|
||||
Managing preset visibility
|
||||
==========================
|
||||
|
||||
Checking :guilabel:`Public` allows any TYPO3 backend user to load this preset.
|
||||
If left unchecked, only the creator can access the preset.
|
||||
@@ -0,0 +1,25 @@
|
||||
:navigation-title: Update content
|
||||
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _content-update:
|
||||
|
||||
===========================================================
|
||||
Synchronizing content and page structures across instances
|
||||
===========================================================
|
||||
|
||||
The import/export tool can be used to synchronize content and page structures
|
||||
between different TYPO3 installations, leaving the content
|
||||
outside the exported page tree unchanged.
|
||||
|
||||
.. _content-update-backend:
|
||||
|
||||
Updating content using the TYPO3 backend
|
||||
========================================
|
||||
|
||||
To update existing content without creating duplicates, check the option:
|
||||
|
||||
:guilabel:`Import > Import Options > Update records`
|
||||
|
||||
This ensures that records with matching UIDs are updated in place.
|
||||
|
||||
.. include:: /Images/AutomaticScreenshots/UpdateContent.rst.txt
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<guides xmlns="https://www.phpdoc.org/guides" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://www.phpdoc.org/guides ../vendor/phpdocumentor/guides-cli/resources/schema/guides.xsd"
|
||||
links-are-relative="true">
|
||||
<extension class="\T3Docs\Typo3DocsTheme\DependencyInjection\Typo3DocsThemeExtension"
|
||||
project-home="https://extensions.typo3.org/extension/impexp/"
|
||||
project-contact="https://typo3.slack.com/archives/C025BQLFA"
|
||||
project-repository="https://github.com/typo3/typo3"
|
||||
project-issues="https://forge.typo3.org/projects/typo3cms-core/issues"
|
||||
edit-on-github-branch="main"
|
||||
edit-on-github="typo3/typo3"
|
||||
edit-on-github-directory="typo3/sysext/impexp/Documentation/"
|
||||
typo3-core-preferred="main"
|
||||
interlink-shortcode="typo3/cms-impexp"
|
||||
/>
|
||||
<project title="Import / Export"
|
||||
release="main (development)"
|
||||
version="main (development)"
|
||||
copyright="since 1997 by the TYPO3 contributors"
|
||||
/>
|
||||
</guides>
|
||||
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
@@ -0,0 +1,11 @@
|
||||
==========================
|
||||
TYPO3 extension ``impexp``
|
||||
==========================
|
||||
|
||||
This is a tool for importing and exporting records using XML or the custom T3D
|
||||
format.
|
||||
|
||||
:Repository: https://github.com/typo3/typo3
|
||||
:Issues: https://forge.typo3.org/
|
||||
:Read online: https://docs.typo3.org/c/typo3/cms-impexp/main/en-us/
|
||||
:Packagist: https://packagist.org/packages/typo3/cms-impexp
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en" datatype="plaintext" original="EXT:impexp/Resources/Private/Language/db.xlf" date="2020-09-19T08:53:36Z" product-name="impexp">
|
||||
<header/>
|
||||
<body>
|
||||
<trans-unit id="tx_impexp_presets">
|
||||
<source>Export Configuration</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="public">
|
||||
<source>Public</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="user_uid">
|
||||
<source>Owner</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="item_uid">
|
||||
<source>Page Root</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="preset_data">
|
||||
<source>Configuration</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
@@ -0,0 +1,434 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en" datatype="plaintext" original="EXT:impexp/Resources/Private/Language/locallang.xlf" date="2011-10-17T20:22:33Z" product-name="impexp">
|
||||
<header/>
|
||||
<body>
|
||||
<trans-unit id="import">
|
||||
<source>Import</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="export">
|
||||
<source>Export</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="title">
|
||||
<source>Import / Export</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="title_import">
|
||||
<source>Import</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="title_export">
|
||||
<source>Export</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="tableselec_configuration">
|
||||
<source>Configuration</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="exportdata_savedFile">
|
||||
<source>SAVED FILE</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="exportdata_savedInSBytes">
|
||||
<source>Saved in "%s", bytes %s</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="exportdata_problemsSavingFile">
|
||||
<source>Problems saving file</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="exportdata_badPathS">
|
||||
<source>Bad path: "%s"</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="exportdata_filePreset">
|
||||
<source>File & Preset</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="exportdata_advancedOptions">
|
||||
<source>Advanced Options</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="exportdata_messages">
|
||||
<source>Messages</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="execlistqu_structureToBeExported">
|
||||
<source>Structure to be exported</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_toggle_all_disabled_records">
|
||||
<source>Toggle disabled records</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_exportPagetreeConfiguration">
|
||||
<source>Export pagetree configuration</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_pageId">
|
||||
<source>Page ID</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_tree">
|
||||
<source>Tree</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_noTreeExportedOnly">
|
||||
<source>No tree exported - only tables on the page.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_tablesOnThisPage">
|
||||
<source>Tables on this page</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_levels">
|
||||
<source>Levels</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_includeTables">
|
||||
<source>Include tables</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_exportSingleRecord">
|
||||
<source>Export single record</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_record">
|
||||
<source>Record</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_exportTablesFromPages">
|
||||
<source>Export tables from pages</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_tablePids">
|
||||
<source>Table/Pids</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_tableListEntry">
|
||||
<source>Table "%s" from %s</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_relationsAndExclusions">
|
||||
<source>Relations and Exclusions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_includeRelationsToTables">
|
||||
<source>Include relations to tables</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_useStaticRelationsFor">
|
||||
<source>Use static relations for tables</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_showStaticRelations">
|
||||
<source>Show static relations</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_excludeElements">
|
||||
<source>Exclude elements</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_clearAllManualExclusions">
|
||||
<source>Clear all manual exclusions</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_noManuallyExcludedElementsYet">
|
||||
<source>No manually excluded elements yet. Exclude by setting checkboxes below in the element display.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeconfig_excludeDisabledElements">
|
||||
<source>Exclude disabled elements</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeadvanc_update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeadvanc_files">
|
||||
<source>Files</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeadvanc_saveFilesOutsideExportFile">
|
||||
<source>Save files in extra folder beside the export file</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeadvanc_saveFilesOutsideExportFile_limit">
|
||||
<source>(supported for "Save to filename" only)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeadvanc_siteConfigurations">
|
||||
<source>Site configurations</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeadvanc_includeSiteConfigurations">
|
||||
<source>Include site configurations for exported root pages (admin only)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeadvanc_extensionDependencies">
|
||||
<source>Extension dependencies</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makeadvanc_selectExtensionsThatThe">
|
||||
<source>Select extensions that the exported content depends on</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_presets">
|
||||
<source>Presets</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_selectPreset">
|
||||
<source>Select preset</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_load">
|
||||
<source>Load</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_save">
|
||||
<source>Save</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="pleaseConfirm">
|
||||
<source>Please confirm</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_areYouSure">
|
||||
<source>Are you sure?</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_delete">
|
||||
<source>Delete</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_merge">
|
||||
<source>Merge</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_titleOfNewPreset">
|
||||
<source>Title of new preset</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_public">
|
||||
<source>Public</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_outputOptions">
|
||||
<source>Output options</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_description">
|
||||
<source>Description</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_notes">
|
||||
<source>Notes</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_t3d_compressed">
|
||||
<source>T3D file / compressed</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_t3d">
|
||||
<source>T3D file</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_xml">
|
||||
<source>XML</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_fileFormat">
|
||||
<source>File format</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_filenameSavedInS">
|
||||
<source>Filename (saved in "%s")</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="makesavefo_downloadExport">
|
||||
<source>Download export</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_saveToFilename">
|
||||
<source>Save to filename</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_selectFileToImport">
|
||||
<source>Select file to import</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_file">
|
||||
<source>File</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_fromPathS">
|
||||
<source>From path: %s</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_noteNoDecompressorAvailable">
|
||||
<source>NOTE: No decompressor available for compressed files!</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_importOptions">
|
||||
<source>Import Options</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_updateRecords">
|
||||
<source>Update records</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_thisOptionRequiresThat">
|
||||
<source>This option requires that the structure you import already exists on this server and only needs to be updated with new content!</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_ignorePidDifferencesGlobally">
|
||||
<source>Ignore PID differences globally</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_ifYouSetThis">
|
||||
<source>The position of updated elements will not be updated to match the structure of the input file.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_force_all_UIDS">
|
||||
<source>Force ALL UIDs values</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_force_all_UIDS_descr">
|
||||
<source>BE VERY CAREFUL WITH THIS: the original UID value of all imported records will be forced to be the same (Admin Only).</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_options">
|
||||
<source>Options</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_doNotShowDifferences">
|
||||
<source>Do not show differences in records</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_greenValuesAreFrom">
|
||||
<source>Hides the resulting differences for each field of every imported records in the preview table.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_action">
|
||||
<source>Action</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_preview">
|
||||
<source>Preview</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_import">
|
||||
<source>Import</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_newImport">
|
||||
<source>New import</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_enableLogging">
|
||||
<source>Enable logging</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_writeIndividualDbActions">
|
||||
<source>Write individual database actions during import to the log</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_thisIsDisabledBy">
|
||||
<source>This is disabled by default since there might be hundred of entries generated.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_uploadFileFromLocal">
|
||||
<source>Upload file from local computer</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_browse">
|
||||
<source>Browse</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_uploadStatus">
|
||||
<source>Upload status</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_success">
|
||||
<source>Success</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_failureNoFileUploaded">
|
||||
<source>Failure: No file uploaded - was it too big? Check system log.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_upload_invalidExtension">
|
||||
<source>Only import files with the extensions "t3d" or "xml" can be uploaded.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_upload">
|
||||
<source>Upload</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_upload_error">
|
||||
<source>Upload error</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_upload_nodata">
|
||||
<source>The import module hasn't received any data. This may occur due to a file upload with a large file. Please check the file size of your uploaded file with the server's post_max_size and upload_max_filesize configuration.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_metaData">
|
||||
<source>Meta data</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_description">
|
||||
<source>Description</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_notes">
|
||||
<source>Notes</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_packager">
|
||||
<source>Packager</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_email">
|
||||
<source>Email</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_metaData_1387">
|
||||
<source>Meta data</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_siteConfigurations">
|
||||
<source>Site Configurations</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_siteConfigurationsAdminOnly">
|
||||
<source>This import contains site configurations that will not be imported because importing site configurations requires administrator privileges.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_siteIdentifier">
|
||||
<source>Identifier</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_siteWebsiteTitle">
|
||||
<source>Website Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_siteBase">
|
||||
<source>Base</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_siteRootPage">
|
||||
<source>Root Page</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_siteLanguages">
|
||||
<source>Languages</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_siteLanguageId">
|
||||
<source>ID</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_siteLanguageLocale">
|
||||
<source>Locale</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_siteDependencies">
|
||||
<source>Dependencies</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_messages">
|
||||
<source>Messages</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_structureHasBeenImported">
|
||||
<source>Structure has been imported, here is the result</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_structureNotImported">
|
||||
<source>The Import has failed, refer to the messages tab to view errors</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importdata_no_default_upload_folder">
|
||||
<source>No default upload folder</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="filterpage_structureToBeImported">
|
||||
<source>Structure to be imported</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="ALL_tables">
|
||||
<source>[ ALL tables ]</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_displaycon_controls">
|
||||
<source>Controls</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_displaycon_title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_displaycon_message">
|
||||
<source>Message</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_displaycon_updateMode">
|
||||
<source>Update Mode</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_displaycon_currentPath">
|
||||
<source>Current Path</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_displaycon_result">
|
||||
<source>Result</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_displaycon_insidePagetree">
|
||||
<source>Inside pagetree</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_singlereco_outsidePagetree">
|
||||
<source>Outside pagetree</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_singlereco_softReferencesFiles">
|
||||
<source>Soft References Files</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_singlereco_update">
|
||||
<source>Update</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_singlereco_insert">
|
||||
<source>Insert</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_singlereco_importAsNew">
|
||||
<source>Import as new</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_singlereco_ignorePid">
|
||||
<source>Ignore PID</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_singlereco_respectPid">
|
||||
<source>Respect PID</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_singlereco_forceUidSAdmin">
|
||||
<source>Force UID [%s] (Admin)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_singlereco_exclude">
|
||||
<source>Exclude</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_singlereco_title">
|
||||
<source>Title</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_singlereco_descr">
|
||||
<source>Descr</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_singlereco_value">
|
||||
<source>Value</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_softrefsel_record">
|
||||
<source>Record</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_softrefsel_editable">
|
||||
<source>Editable</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_softrefsel_exclude">
|
||||
<source>Exclude</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="impexpcore_printerror_description">
|
||||
<source>Description</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
@@ -0,0 +1,85 @@
|
||||
<html
|
||||
xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers"
|
||||
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true"
|
||||
>
|
||||
<div class="form-section">
|
||||
|
||||
<h4>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeadvanc_files"/>
|
||||
</h4>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="tx_impexp[saveFilesOutsideExportFile]" value="" />
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
id="saveFilesOutsideExportFile"
|
||||
name="tx_impexp[saveFilesOutsideExportFile]"
|
||||
value="1"
|
||||
{f:if(condition:'{inData.saveFilesOutsideExportFile} == 1', then:'checked="checked"')}
|
||||
/>
|
||||
<label class="form-check-label" for="saveFilesOutsideExportFile">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeadvanc_saveFilesOutsideExportFile"/>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeadvanc_saveFilesOutsideExportFile_limit"/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-section">
|
||||
|
||||
<h4>
|
||||
<f:translate key="makeadvanc_siteConfigurations" domain="impexp.messages"/>
|
||||
</h4>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="tx_impexp[includeSiteConfigurations]" value="" />
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
id="checkIncludeSiteConfigurations"
|
||||
name="tx_impexp[includeSiteConfigurations]"
|
||||
value="1"
|
||||
{f:if(condition:'{inData.includeSiteConfigurations} == 1', then:'checked="checked"')}
|
||||
{f:if(condition:'!{isAdmin}', then:'disabled="disabled"')}
|
||||
/>
|
||||
<label class="form-check-label" for="checkIncludeSiteConfigurations">
|
||||
<f:translate key="makeadvanc_includeSiteConfigurations" domain="impexp.messages"/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-section">
|
||||
|
||||
<h4>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeadvanc_extensionDependencies"/>
|
||||
</h4>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="extension_dep">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeadvanc_selectExtensionsThatThe"/>
|
||||
</label>
|
||||
<select
|
||||
id="extension_dep"
|
||||
class="form-select"
|
||||
name="tx_impexp[extension_dep][]"
|
||||
multiple="multiple"
|
||||
size="{f:if(condition: '{tableSelectOptions -> f:count()} > 9', then: '10', else: '5')}"
|
||||
>
|
||||
<f:for each="{extensions}" as="optionLabel" key="optionValue">
|
||||
<option value="{optionValue}" {f:contains(value: optionValue, subject: inData.extension_dep, then: 'selected="selected"')}>{optionLabel}</option>
|
||||
</f:for>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-default"
|
||||
>
|
||||
<core:icon identifier="actions-refresh" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_update"/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,227 @@
|
||||
<html
|
||||
xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers"
|
||||
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true"
|
||||
>
|
||||
|
||||
<div class="form-section">
|
||||
|
||||
<h3 class="form-section-headline">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_exportPagetreeConfiguration" />
|
||||
</h3>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
<label class="form-label">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_pageId" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
{inData.pagetree.id}
|
||||
<input type="hidden" name="tx_impexp[pagetree][id]" value="{inData.pagetree.id}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
<label class="form-label">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_tree" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<f:if condition="{treeHTML}">
|
||||
<f:then>
|
||||
<f:format.raw>{treeHTML}</f:format.raw>
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_noTreeExportedOnly" />
|
||||
</f:else>
|
||||
</f:if>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="pagetreeLevels">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_levels" />
|
||||
</label>
|
||||
<select
|
||||
id="pagetreeLevels"
|
||||
class="form-select"
|
||||
name="tx_impexp[pagetree][levels]"
|
||||
>
|
||||
<f:for each="{levelSelectOptions}" as="optionLabel" key="optionValue">
|
||||
<option value="{optionValue}" {f:if(condition:'{optionValue} == {inData.pagetree.levels}', then:'selected="selected"')}>{optionLabel}</option>
|
||||
</f:for>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="pagetreeTables">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_includeTables"/>
|
||||
</label>
|
||||
<select
|
||||
id="pagetreeTables"
|
||||
class="form-select"
|
||||
name="tx_impexp[pagetree][tables][]"
|
||||
multiple="multiple"
|
||||
size="{f:if(condition: '{tableSelectOptions -> f:count()} > 9', then: '10', else: '5')}"
|
||||
>
|
||||
<f:for each="{tableSelectOptions}" as="optionLabel" key="optionValue">
|
||||
<option value="{optionValue}" {f:contains(value: optionValue, subject: inData.pagetree.tables, then: 'selected="selected"')}>{optionLabel}</option>
|
||||
</f:for>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<f:if condition="{records -> f:count()} > 0">
|
||||
<h4>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_exportSingleRecord"/>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
<label>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_record"/>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<f:for each="{records}" as="record" iteration="iterator">
|
||||
<f:format.raw>{record.icon}</f:format.raw>
|
||||
{record.title}
|
||||
<input type="hidden" name="tx_impexp[record][]" value="{record.tableName}:{record.recordUid}" />
|
||||
<f:if condition="{iterator.isLast}"><f:else><br></f:else></f:if>
|
||||
</f:for>
|
||||
</div>
|
||||
</div>
|
||||
</f:if>
|
||||
|
||||
<f:if condition="{tableList -> f:count()} > 0">
|
||||
<h4>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_exportTablesFromPages"/>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
<label>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_tablePids"/>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<f:for each="{tableList}" as="table">
|
||||
<f:format.raw>{table.iconAndTitle}</f:format.raw>
|
||||
<input type="hidden" name="tx_impexp[list][]" value="{table.reference}" />
|
||||
<br>
|
||||
</f:for>
|
||||
</div>
|
||||
</div>
|
||||
</f:if>
|
||||
|
||||
<h4>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_relationsAndExclusions"/>
|
||||
</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="externalRefTables">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_includeRelationsToTables"/>
|
||||
</label>
|
||||
<select
|
||||
id="externalRefTables"
|
||||
class="form-select"
|
||||
name="tx_impexp[external_ref][tables][]"
|
||||
multiple="multiple"
|
||||
size="{f:if(condition: '{externalReferenceTableSelectOptions -> f:count()} > 9', then: '10', else: '5')}"
|
||||
>
|
||||
<f:for each="{externalReferenceTableSelectOptions}" as="optionLabel" key="optionValue">
|
||||
<option value="{optionValue}" {f:contains(value: optionValue, subject: inData.external_ref.tables, then: 'selected="selected"')}>{optionLabel}</option>
|
||||
</f:for>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="externalStaticTables">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_useStaticRelationsFor"/>
|
||||
</label>
|
||||
<select
|
||||
id="externalStaticTables"
|
||||
class="form-select"
|
||||
name="tx_impexp[external_static][tables][]"
|
||||
multiple="multiple"
|
||||
size="{f:if(condition: '{externalStaticTableSelectOptions -> f:count()} > 9', then: '10', else: '5')}"
|
||||
>
|
||||
<f:for each="{externalStaticTableSelectOptions}" as="optionLabel" key="optionValue">
|
||||
<option value="{optionValue}" {f:contains(value: optionValue, subject: inData.external_static.tables, then: 'selected="selected"')}>{optionLabel}</option>
|
||||
</f:for>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="tx_impexp[showStaticRelations]" value="" />
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
id="checkShowStaticRelations"
|
||||
name="tx_impexp[showStaticRelations]"
|
||||
value="1"
|
||||
{f:if(condition:'{inData.showStaticRelations} == 1', then:'checked="checked"')}
|
||||
/>
|
||||
<label class="form-check-label" for="checkShowStaticRelations">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_showStaticRelations"/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_excludeElements"/>
|
||||
</label>
|
||||
<f:if condition="{inData.exclude -> f:count()} > 0">
|
||||
<f:then>
|
||||
<p class="form-description">
|
||||
<f:for each="{inData.exclude}" key="key" as="value" iteration="index">
|
||||
<input type="hidden" name="tx_impexp[exclude][{key}]" value="1" />
|
||||
<f:if condition="{index.isLast}">
|
||||
<f:then>{key}</f:then>
|
||||
<f:else>{key},</f:else>
|
||||
</f:if>
|
||||
</f:for>
|
||||
</p>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" name="tx_impexp[resetExclude]" id="checkResetExclude" value="1" class="form-check-input" />
|
||||
<label for="checkResetExclude" class="form-check-label">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_clearAllManualExclusions" />
|
||||
</label>
|
||||
</div>
|
||||
</f:then>
|
||||
<f:else>
|
||||
<p class="form-description">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_noManuallyExcludedElementsYet"/>
|
||||
</p>
|
||||
</f:else>
|
||||
</f:if>
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="tx_impexp[excludeDisabled]" value="" />
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
id="checkExcludeDisabled"
|
||||
name="tx_impexp[excludeDisabled]"
|
||||
value="1"
|
||||
{f:if(condition:'{inData.excludeDisabled} == 1', then:'checked="checked"')}
|
||||
/>
|
||||
<label for="checkExcludeDisabled" class="form-check-label">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeconfig_excludeDisabledElements" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-default"
|
||||
>
|
||||
<core:icon identifier="actions-refresh" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makeadvanc_update" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,205 @@
|
||||
<html
|
||||
xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers"
|
||||
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true"
|
||||
>
|
||||
|
||||
<div class="form-section">
|
||||
|
||||
<h3 class="form-section-headline">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_presets" />
|
||||
</h3>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="preset-select">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_selectPreset" />
|
||||
</label>
|
||||
<select class="form-select" id="preset-select" name="preset[select]">
|
||||
<f:for each="{presetSelectOptions}" as="optionLabel" key="optionValue">
|
||||
<option value="{optionValue}">{optionLabel}</option>
|
||||
</f:for>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input type="hidden" id="t3js-submit-field" name="not-set" value="1">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-default"
|
||||
name="preset[load]"
|
||||
value="1"
|
||||
>
|
||||
<core:icon identifier="actions-upload" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_load" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
name="preset[save]"
|
||||
class="btn btn-default t3js-confirm-trigger"
|
||||
data-title="{f:translate(key: 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:pleaseConfirm')}"
|
||||
data-message="{f:translate(key: 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_areYouSure')}"
|
||||
value="1"
|
||||
>
|
||||
<core:icon identifier="actions-save" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_save" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
name="preset[delete]"
|
||||
class="btn btn-default t3js-confirm-trigger"
|
||||
data-title="{f:translate(key: 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:pleaseConfirm')}"
|
||||
data-message="{f:translate(key: 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_areYouSure')}"
|
||||
value="1"
|
||||
>
|
||||
<core:icon identifier="actions-delete" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_delete" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
name="preset[merge]"
|
||||
class="btn btn-default t3js-confirm-trigger"
|
||||
data-title="{f:translate(key: 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:pleaseConfirm')}"
|
||||
data-message="{f:translate(key: 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_areYouSure')}"
|
||||
value="1"
|
||||
>
|
||||
<core:icon identifier="actions-code-merge" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_merge" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-section">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="preset-title">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_titleOfNewPreset" />
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="tx_impexp[preset][title]"
|
||||
class="form-control"
|
||||
id="preset-title"
|
||||
value="{inData.preset.title}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="tx_impexp[preset][public]" value="" />
|
||||
<input
|
||||
type="checkbox"
|
||||
name="tx_impexp[preset][public]"
|
||||
class="form-check-input"
|
||||
id="checkPresetPublic"
|
||||
value="1"
|
||||
{f:if(condition:'{inData.preset.public} == 1', then:'checked="checked"')}
|
||||
/>
|
||||
<label class="form-check-label" for="checkPresetPublic">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_public"/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-section">
|
||||
|
||||
<h3 class="form-section-headline">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_outputOptions"/>
|
||||
</h3>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="meta-title">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_title"/>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="tx_impexp[meta][title]"
|
||||
class="form-control"
|
||||
id="meta-title"
|
||||
value="{inData.meta.title}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="meta-description">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_description"/>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="tx_impexp[meta][description]"
|
||||
class="form-control"
|
||||
id="meta-description"
|
||||
value="{inData.meta.description}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="meta-notes">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_notes"/>
|
||||
</label>
|
||||
<textarea
|
||||
name="tx_impexp[meta][notes]"
|
||||
class="form-control"
|
||||
id="meta-notes"
|
||||
>{inData.meta.notes}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="tx_impexp_filetype">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_fileFormat"/>
|
||||
</label>
|
||||
<select
|
||||
class="form-select"
|
||||
name="tx_impexp[filetype]"
|
||||
id="tx_impexp_filetype"
|
||||
>
|
||||
<f:for each="{filetypeSelectOptions}" as="optionLabel" key="optionValue">
|
||||
<option value="{optionValue}" {f:if(condition:'{optionValue} == {inData.filetype}', then:'selected="selected"')}>{optionLabel}</option>
|
||||
</f:for>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="impexp-filename">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_filenameSavedInS" arguments="{0: saveFolder}"/>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="tx_impexp[filename]"
|
||||
value="{inData.filename}"
|
||||
class="form-control"
|
||||
id="impexp-filename"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-default"
|
||||
>
|
||||
<core:icon identifier="actions-refresh" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_update" />
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
name="tx_impexp[download_export]"
|
||||
class="btn btn-default"
|
||||
value="1"
|
||||
>
|
||||
<core:icon identifier="actions-download" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_downloadExport" />
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
name="tx_impexp[save_export]"
|
||||
class="btn btn-default"
|
||||
value="1"
|
||||
>
|
||||
<core:icon identifier="actions-file-csv-download" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_saveToFilename" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,213 @@
|
||||
<html
|
||||
xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers"
|
||||
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true"
|
||||
>
|
||||
|
||||
<div class="form-section">
|
||||
|
||||
<h3 class="form-section-headline">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_selectFileToImport" />
|
||||
</h3>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="impexp-file">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_file" />
|
||||
</label>
|
||||
<select
|
||||
name="tx_impexp[file]"
|
||||
class="form-select"
|
||||
id="impexp-file"
|
||||
>
|
||||
<f:for each="{fileSelectOptions}" as="optionLabel" key="optionValue">
|
||||
<option value="{optionValue}" {f:if(condition:'{optionValue} == {inData.file}', then:'selected="selected"')}>{optionLabel}</option>
|
||||
</f:for>
|
||||
</select>
|
||||
<div class="form-text">
|
||||
<f:if condition="{importFolder}">
|
||||
<f:then>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_fromPathS" arguments="{0: importFolder}" />
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_no_default_upload_folder" />
|
||||
</f:else>
|
||||
</f:if>
|
||||
</div>
|
||||
<f:if condition="{import.decompressionAvailable}">
|
||||
<f:else>
|
||||
<span class="text-danger"><f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_noteNoDecompressorAvailable"/></span>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-section">
|
||||
|
||||
<h3 class="form-section-headline">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_importOptions"/>
|
||||
</h3>
|
||||
<h4>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_update"/>
|
||||
</h4>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="tx_impexp[do_update]" value="">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
name="tx_impexp[do_update]"
|
||||
value="1"
|
||||
id="checkDo_update"
|
||||
{f:if(condition:'{inData.do_update} == 1', then:'checked="checked"')}
|
||||
>
|
||||
<label class="form-check-label" for="checkDo_update">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_updateRecords"/>
|
||||
<br><small class="form-text"><f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_thisOptionRequiresThat"/></small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<f:if condition="{inData.do_update}">
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="tx_impexp[global_ignore_pid]" value="">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
name="tx_impexp[global_ignore_pid]"
|
||||
value="1"
|
||||
id="checkGlobal_ignore_pid"
|
||||
{f:if(condition:'{inData.global_ignore_pid} == 1', then:'checked="checked"')}
|
||||
>
|
||||
<label class="form-check-label" for="checkGlobal_ignore_pid">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_ignorePidDifferencesGlobally"/>
|
||||
<br><small class="text-variant"><f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_ifYouSetThis"/></small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</f:if>
|
||||
|
||||
<h4>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_options"/>
|
||||
</h4>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="tx_impexp[notShowDiff]" value="">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
name="tx_impexp[notShowDiff]"
|
||||
value="1"
|
||||
id="checkNotShowDiff"
|
||||
{f:if(condition:'{inData.notShowDiff} == 1', then:'checked="checked"')}
|
||||
>
|
||||
<label class="form-check-label" for="checkNotShowDiff">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_doNotShowDifferences"/>
|
||||
<br><small class="text-variant"><f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_greenValuesAreFrom"/></small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<f:if condition="{isAdmin}">
|
||||
<f:if condition="!{inData.do_update}">
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="tx_impexp[force_all_UIDS]" value="">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
name="tx_impexp[force_all_UIDS]"
|
||||
value="1"
|
||||
id="checkForce_all_UIDS"
|
||||
{f:if(condition:'{inData.force_all_UIDS} == 1', then:'checked="checked"')}
|
||||
>
|
||||
<label for="checkForce_all_UIDS">
|
||||
<span class="text-danger"><f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_force_all_UIDS"/></span>
|
||||
<br><small class="text-variant"><f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_force_all_UIDS_descr"/></small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</f:if>
|
||||
</f:if>
|
||||
|
||||
<h4>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_enableLogging"/>
|
||||
</h4>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="tx_impexp[enableLogging]" value="">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
name="tx_impexp[enableLogging]"
|
||||
value="1"
|
||||
id="checkEnableLogging"
|
||||
{f:if(condition:'{inData.enableLogging} == 1', then:'checked="checked"')}
|
||||
>
|
||||
<label class="form-check-label" for="checkEnableLogging">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_writeIndividualDbActions"/>
|
||||
<br><small class="text-variant"><f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_thisIsDisabledBy"/></small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_action"/>
|
||||
</h4>
|
||||
<div class="form-group">
|
||||
<f:if condition="{inData.import_file}">
|
||||
<f:then>
|
||||
<button
|
||||
type="submit"
|
||||
name="tx_impexp[new_import]"
|
||||
class="btn btn-default"
|
||||
value="1"
|
||||
>
|
||||
<core:icon identifier="actions-upload" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_newImport"/>
|
||||
</button>
|
||||
</f:then>
|
||||
<f:else>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-default"
|
||||
>
|
||||
<core:icon identifier="actions-view" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_preview"/>
|
||||
</button>
|
||||
<f:if condition="{inData.file}">
|
||||
<input type="hidden" name="not-set" value="1" id="t3js-submit-field"/>
|
||||
<f:if condition="{inData.do_update}">
|
||||
<f:then>
|
||||
<button
|
||||
type="button"
|
||||
name="tx_impexp[import_file]"
|
||||
class="btn btn-default t3js-confirm-trigger"
|
||||
data-title="{f:translate(key: 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:pleaseConfirm')}"
|
||||
data-message="{f:translate(key: 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_areYouSure')}"
|
||||
value="1"
|
||||
>
|
||||
<core:icon identifier="actions-upload" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_update" />
|
||||
</button>
|
||||
</f:then>
|
||||
<f:else>
|
||||
<button
|
||||
type="button"
|
||||
name="tx_impexp[import_file]"
|
||||
class="btn btn-default t3js-confirm-trigger"
|
||||
data-title="{f:translate(key: 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:pleaseConfirm')}"
|
||||
data-message="{f:translate(key: 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:makesavefo_areYouSure')}"
|
||||
value="1"
|
||||
>
|
||||
<core:icon identifier="actions-upload" size="small" />
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_import" />
|
||||
</button>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</f:if>
|
||||
</f:else>
|
||||
</f:if>
|
||||
<input type="hidden" name="tx_impexp[action]" value="import" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,132 @@
|
||||
<html
|
||||
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true"
|
||||
>
|
||||
|
||||
<div class="form-section">
|
||||
|
||||
<h3 class="form-section-headline">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_metaData" />
|
||||
</h3>
|
||||
<div class="table-fit table-fit-wrap mb-2">
|
||||
<table class="table table-striped table-hover">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="col-nowrap">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_title" />
|
||||
</th>
|
||||
<td>
|
||||
<f:format.nl2br>{import.metaData.title}</f:format.nl2br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="col-nowrap">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_description" />
|
||||
</th>
|
||||
<td>
|
||||
<f:format.nl2br>{import.metaData.description}</f:format.nl2br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="col-nowrap">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_notes" />
|
||||
</th>
|
||||
<td>
|
||||
<f:format.nl2br>{import.metaData.notes}</f:format.nl2br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="col-nowrap">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_packager" />
|
||||
</th>
|
||||
<td>
|
||||
<f:format.nl2br>{import.metaData.packager_name} ({import.metaData.packager_username})</f:format.nl2br>
|
||||
<br>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_email" />
|
||||
{import.metaData.packager_email}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<f:if condition="{import.siteConfigurations -> f:count()} > 0 && {isAdmin}">
|
||||
<div class="form-section">
|
||||
|
||||
<h3 class="form-section-headline">
|
||||
<f:translate domain="impexp.messages" key="importdata_siteConfigurations" />
|
||||
</h3>
|
||||
|
||||
<f:for each="{import.siteConfigurations}" as="siteConfig" key="siteIdentifier">
|
||||
<h4>{siteIdentifier}</h4>
|
||||
<div class="table-fit table-fit-wrap mb-2">
|
||||
<table class="table table-striped table-hover">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="col-nowrap">
|
||||
<f:translate domain="impexp.messages" key="importdata_siteRootPage" />
|
||||
</th>
|
||||
<td>{siteConfig._rootPageTitle} [{siteConfig.rootPageId}]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="col-nowrap">
|
||||
<f:translate domain="impexp.messages" key="importdata_siteWebsiteTitle" />
|
||||
</th>
|
||||
<td>{siteConfig.websiteTitle}</td>
|
||||
</tr>
|
||||
<f:if condition="{siteConfig.dependencies -> f:count()} > 0">
|
||||
<tr>
|
||||
<th class="col-nowrap">
|
||||
<f:translate domain="impexp.messages" key="importdata_siteDependencies" />
|
||||
</th>
|
||||
<td>
|
||||
<f:for each="{siteConfig.dependencies}" as="dependency">
|
||||
<div>{dependency}</div>
|
||||
</f:for>
|
||||
</td>
|
||||
</tr>
|
||||
</f:if>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<f:if condition="{siteConfig.languages -> f:count()} > 0">
|
||||
<div class="table-fit table-fit-wrap mb-3">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-nowrap">
|
||||
<f:translate domain="impexp.messages" key="importdata_siteLanguageId" />
|
||||
</th>
|
||||
<th class="col-nowrap">
|
||||
<f:translate domain="impexp.messages" key="importdata_title" />
|
||||
</th>
|
||||
<th class="col-nowrap">
|
||||
<f:translate domain="impexp.messages" key="importdata_siteLanguageLocale" />
|
||||
</th>
|
||||
<th class="col-nowrap">
|
||||
<f:translate domain="impexp.messages" key="importdata_siteBase" />
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<f:for each="{siteConfig.languages}" as="language">
|
||||
<tr>
|
||||
<td>{language.languageId}</td>
|
||||
<td>{language.title}</td>
|
||||
<td>{language.locale}</td>
|
||||
<td>{language.base}</td>
|
||||
</tr>
|
||||
</f:for>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</f:if>
|
||||
</f:for>
|
||||
|
||||
</div>
|
||||
</f:if>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,65 @@
|
||||
<html
|
||||
xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers"
|
||||
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true"
|
||||
>
|
||||
|
||||
<div class="form-section">
|
||||
|
||||
<h3 class="form-section-headline">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_uploadFileFromLocal" />
|
||||
</h3>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="impexp_upload_1">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_browse" />
|
||||
</label>
|
||||
<input class="form-control" id="impexp_upload_1" type="file" name="upload_1" accept="{allowedUploadExtensionList}" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="overwriteExistingFiles" value="">
|
||||
<input
|
||||
class="form-check-input"
|
||||
id="checkOverwriteExistingFiles"
|
||||
type="checkbox"
|
||||
name="overwriteExistingFiles"
|
||||
value="replace"
|
||||
checked="checked"
|
||||
>
|
||||
<label class="form-check-label" for="checkOverwriteExistingFiles">
|
||||
<f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_misc.xlf:overwriteExistingFiles" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-default"
|
||||
name="_upload"
|
||||
value="1"
|
||||
>
|
||||
<core:icon identifier="actions-upload" size="small" />
|
||||
<f:translate key="LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:file_upload.php.submit" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<f:if condition="{uploadStatus}">
|
||||
<h4>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_uploadStatus" />
|
||||
</h4>
|
||||
<f:if condition="{uploadStatus} == 1">
|
||||
<f:then>
|
||||
<f:be.infobox title="{f:translate(key: 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_success')} {uploadedFile}" state="{f:constant(name: 'TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::OK')}" />
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:be.infobox title="{f:translate(key: 'LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_failureNoFileUploaded')}" state="{f:constant(name: 'TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::ERROR')}" />
|
||||
</f:else>
|
||||
</f:if>
|
||||
</f:if>
|
||||
|
||||
</div>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,171 @@
|
||||
<html
|
||||
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true"
|
||||
>
|
||||
|
||||
<f:if condition="{import.mode} == 'import'">
|
||||
<f:then>
|
||||
<h2>
|
||||
<f:if condition="{inData.import_file}">
|
||||
<f:then>
|
||||
<f:if condition="{errors}">
|
||||
<f:then>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_structureNotImported" />
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_structureHasBeenImported" />
|
||||
</f:else>
|
||||
</f:if>
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:if condition="{inData.file}">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:filterpage_structureToBeImported" />
|
||||
</f:if>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</h2>
|
||||
</f:then>
|
||||
<f:else>
|
||||
<h2>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:execlistqu_structureToBeExported" />
|
||||
</h2>
|
||||
</f:else>
|
||||
</f:if>
|
||||
|
||||
<f:if condition="{inData.excludeDisabled}">
|
||||
<f:else>
|
||||
<f:if condition="{import.mode} == 'import'">
|
||||
<f:else>
|
||||
<f:form.button class="btn btn-default t3js-impexp-toggledisabled" type="button">
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_toggle_all_disabled_records" />
|
||||
</f:form.button>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</f:else>
|
||||
</f:if>
|
||||
|
||||
<f:if condition="{preview.insidePageTree -> f:count()} > 0">
|
||||
<h3>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_insidePagetree" />
|
||||
</h3>
|
||||
<div class="table-fit">
|
||||
<table class="table table-striped table-hover t3js-impexp-preview">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_controls" />
|
||||
</th>
|
||||
<th>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_title" />
|
||||
</th>
|
||||
<th>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_message" />
|
||||
</th>
|
||||
<f:if condition="{preview.update}">
|
||||
<th>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_updateMode" />
|
||||
</th>
|
||||
<th>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_currentPath" />
|
||||
</th>
|
||||
</f:if>
|
||||
<f:if condition="{preview.showDiff}">
|
||||
<th>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_result" />
|
||||
</th>
|
||||
</f:if>
|
||||
</tr>
|
||||
<f:for each="{preview.insidePageTree}" as="line">
|
||||
<tr data-active="{line.active}">
|
||||
<td>
|
||||
<f:format.raw>{line.controls}</f:format.raw>
|
||||
</td>
|
||||
<td class="col-nowrap">
|
||||
<f:format.raw>{line.preCode} {line.title}</f:format.raw>
|
||||
</td>
|
||||
<td class="col-nowrap">
|
||||
<f:format.raw>{line.message}</f:format.raw>
|
||||
</td>
|
||||
<f:if condition="{preview.update}">
|
||||
<td class="col-nowrap">
|
||||
<f:format.raw>{line.updateMode}</f:format.raw>
|
||||
</td>
|
||||
<td class="col-nowrap">
|
||||
<f:format.raw>{line.updatePath}</f:format.raw>
|
||||
</td>
|
||||
</f:if>
|
||||
<f:if condition="{preview.showDiff}">
|
||||
<td>
|
||||
<f:format.raw>{line.showDiffContent}</f:format.raw>
|
||||
</td>
|
||||
</f:if>
|
||||
</tr>
|
||||
</f:for>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</f:if>
|
||||
|
||||
<f:if condition="{preview.outsidePageTree -> f:count()} > 0">
|
||||
<h3>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_singlereco_outsidePagetree" />
|
||||
</h3>
|
||||
<div class="table-fit">
|
||||
<table class="table table-striped table-hover t3js-impexp-preview">
|
||||
<tbody>
|
||||
<tr data-active="{line.active}">
|
||||
<th>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_controls" />
|
||||
</th>
|
||||
<th>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_title" />
|
||||
</th>
|
||||
<th>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_message" />
|
||||
</th>
|
||||
<f:if condition="{preview.update}">
|
||||
<th>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_updateMode" />
|
||||
</th>
|
||||
<th>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_currentPath" />
|
||||
</th>
|
||||
</f:if>
|
||||
<f:if condition="{preview.showDiff}">
|
||||
<th>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:impexpcore_displaycon_result" />
|
||||
</th>
|
||||
</f:if>
|
||||
</tr>
|
||||
<f:for each="{preview.outsidePageTree}" as="line">
|
||||
<tr>
|
||||
<td>
|
||||
<f:format.raw>{line.controls}</f:format.raw>
|
||||
</td>
|
||||
<td class="col-nowrap">
|
||||
<f:format.raw>{line.preCode} {line.title}</f:format.raw>
|
||||
</td>
|
||||
<td class="col-nowrap">
|
||||
<f:format.raw>{line.message}</f:format.raw>
|
||||
</td>
|
||||
<f:if condition="{preview.update}">
|
||||
<td class="col-nowrap">
|
||||
<f:format.raw>{line.updateMode}</f:format.raw>
|
||||
</td>
|
||||
<td class="col-nowrap">
|
||||
<f:format.raw>{line.updatePath}</f:format.raw>
|
||||
</td>
|
||||
</f:if>
|
||||
<f:if condition="{preview.showDiff}">
|
||||
<td>
|
||||
<f:format.raw>{line.showDiffContent}</f:format.raw>
|
||||
</td>
|
||||
</f:if>
|
||||
</tr>
|
||||
</f:for>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</f:if>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,101 @@
|
||||
<html
|
||||
xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers"
|
||||
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true"
|
||||
>
|
||||
|
||||
<f:layout name="Module" />
|
||||
|
||||
<f:section name="Before">
|
||||
<f:asset.module identifier="@typo3/backend/context-menu.js"/>
|
||||
<f:asset.module identifier="@typo3/impexp/import-export.js"/>
|
||||
<f:asset.module identifier="@typo3/backend/element/immediate-action-element.js"/>
|
||||
<f:variable name="args" value="{0: 'web', 1: id}" />
|
||||
<typo3-immediate-action
|
||||
action="TYPO3.Backend.Storage.ModuleStateStorage.update"
|
||||
args="{args -> f:format.json() -> f:format.htmlspecialchars()}"
|
||||
></typo3-immediate-action>
|
||||
</f:section>
|
||||
|
||||
<f:section name="Content">
|
||||
|
||||
<h1>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:title_export" />
|
||||
</h1>
|
||||
<form action="{f:be.uri(route:'tx_impexp_export')}" method="post" id="ImportExportController">
|
||||
<input type="hidden" name="id" value="{id}" />
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation" class="nav-item">
|
||||
<button
|
||||
type="button"
|
||||
class="nav-link active"
|
||||
data-typo3-tab="#export-configuration"
|
||||
aria-controls="export-configuration"
|
||||
role="tab"
|
||||
>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:tableselec_configuration" />
|
||||
</button>
|
||||
</li>
|
||||
<li role="presentation" class="nav-item">
|
||||
<button
|
||||
type="button"
|
||||
class="nav-link"
|
||||
data-typo3-tab="#export-filepreset"
|
||||
aria-controls="export-filepreset"
|
||||
role="tab"
|
||||
>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:exportdata_filePreset" />
|
||||
</button>
|
||||
</li>
|
||||
<li role="presentation" class="nav-item">
|
||||
<button
|
||||
type="button"
|
||||
class="nav-link"
|
||||
data-typo3-tab="#export-advancedoptions"
|
||||
aria-controls="export-advancedoptions"
|
||||
role="tab"
|
||||
>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:exportdata_advancedOptions" />
|
||||
</button>
|
||||
</li>
|
||||
<f:if condition="{errors -> f:count()} > 0">
|
||||
<li role="presentation" class="nav-item">
|
||||
<button
|
||||
type="button"
|
||||
class="nav-link"
|
||||
data-typo3-tab="#export-errors"
|
||||
aria-controls="export-errors"
|
||||
role="tab"
|
||||
>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:exportdata_messages" />
|
||||
<core:icon identifier="status-dialog-warning" />
|
||||
</button>
|
||||
</li>
|
||||
</f:if>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="export-configuration">
|
||||
<f:render partial="Export/Configuration" arguments="{_all}" />
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="export-filepreset">
|
||||
<f:render partial="Export/Save" arguments="{_all}" />
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="export-advancedoptions">
|
||||
<f:render partial="Export/AdvancedOptions" arguments="{_all}" />
|
||||
</div>
|
||||
<f:if condition="{errors -> f:count()} > 0">
|
||||
<div role="tabpanel" class="tab-pane" id="export-errors">
|
||||
<f:be.infobox state="{f:constant(name: 'TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::ERROR')}" disableIcon="true">
|
||||
<f:for each="{errors}" as="error">
|
||||
<p>{error}</p>
|
||||
</f:for>
|
||||
</f:be.infobox>
|
||||
</div>
|
||||
</f:if>
|
||||
</div>
|
||||
<f:render partial="Preview" arguments="{_all}" />
|
||||
</form>
|
||||
|
||||
</f:section>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,110 @@
|
||||
<html
|
||||
xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers"
|
||||
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
|
||||
data-namespace-typo3-fluid="true"
|
||||
>
|
||||
|
||||
<f:layout name="Module" />
|
||||
|
||||
<f:section name="Before">
|
||||
<f:asset.module identifier="@typo3/backend/context-menu.js"/>
|
||||
<f:asset.module identifier="@typo3/impexp/import-export.js"/>
|
||||
<f:asset.module identifier="@typo3/backend/element/immediate-action-element.js"/>
|
||||
<f:variable name="args" value="{0: 'web', 1: id}" />
|
||||
<typo3-immediate-action
|
||||
action="TYPO3.Backend.Storage.ModuleStateStorage.update"
|
||||
args="{args -> f:format.json() -> f:format.htmlspecialchars()}"
|
||||
></typo3-immediate-action>
|
||||
</f:section>
|
||||
|
||||
<f:section name="Content">
|
||||
|
||||
<h1>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:title_import" />
|
||||
</h1>
|
||||
<form action="{f:be.uri(route:'tx_impexp_import')}" method="post" id="ImportExportController" enctype="multipart/form-data">
|
||||
<input type="hidden" name="id" value="{id}" />
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation" class="nav-item">
|
||||
<button
|
||||
type="button"
|
||||
class="nav-link active"
|
||||
data-typo3-tab="#import-import"
|
||||
aria-controls="import-import"
|
||||
role="tab"
|
||||
>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_import" />
|
||||
</button>
|
||||
</li>
|
||||
<f:if condition="{importFolder}">
|
||||
<li role="presentation" class="nav-item">
|
||||
<button
|
||||
type="button"
|
||||
class="nav-link"
|
||||
data-typo3-tab="#import-upload"
|
||||
aria-controls="import-upload"
|
||||
role="tab"
|
||||
>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_upload" />
|
||||
</button>
|
||||
</li>
|
||||
</f:if>
|
||||
<f:if condition="{import.metaData} || {import.siteConfigurations -> f:count()} > 0">
|
||||
<li role="presentation" class="nav-item">
|
||||
<button
|
||||
type="button"
|
||||
class="nav-link"
|
||||
data-typo3-tab="#import-metadata"
|
||||
aria-controls="import-metadata"
|
||||
role="tab"
|
||||
>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_metaData_1387" />
|
||||
</button>
|
||||
</li>
|
||||
</f:if>
|
||||
<f:if condition="{errors -> f:count()} > 0">
|
||||
<li role="presentation" class="nav-item">
|
||||
<button
|
||||
type="button"
|
||||
class="nav-link"
|
||||
data-typo3-tab="#import-errors"
|
||||
aria-controls="import-errors"
|
||||
role="tab"
|
||||
>
|
||||
<f:translate key="LLL:EXT:impexp/Resources/Private/Language/locallang.xlf:importdata_messages" />
|
||||
<core:icon identifier="status-dialog-warning" />
|
||||
</button>
|
||||
</li>
|
||||
</f:if>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="import-import">
|
||||
<f:render partial="Import/Import" arguments="{_all}" />
|
||||
</div>
|
||||
<f:if condition="{importFolder}">
|
||||
<div role="tabpanel" class="tab-pane" id="import-upload">
|
||||
<f:render partial="Import/Upload" arguments="{_all}" />
|
||||
</div>
|
||||
</f:if>
|
||||
<f:if condition="{import.metaData} || {import.siteConfigurations -> f:count()} > 0">
|
||||
<div role="tabpanel" class="tab-pane" id="import-metadata">
|
||||
<f:render partial="Import/MetaData" arguments="{_all}" />
|
||||
</div>
|
||||
</f:if>
|
||||
<f:if condition="{errors -> f:count()} > 0">
|
||||
<div role="tabpanel" class="tab-pane" id="import-errors">
|
||||
<f:be.infobox state="{f:constant(name: 'TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::ERROR')}" disableIcon="true">
|
||||
<f:for each="{errors}" as="error">
|
||||
<p>{error}</p>
|
||||
</f:for>
|
||||
</f:be.infobox>
|
||||
</div>
|
||||
</f:if>
|
||||
</div>
|
||||
|
||||
<f:render partial="Preview" arguments="{_all}" />
|
||||
</form>
|
||||
|
||||
</f:section>
|
||||
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 788 B |
|
After Width: | Height: | Size: 681 B |
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
class a{exportT3d(t,e,o){const n=o.actionUrl;t==="pages"?top.TYPO3.Backend.ContentContainer.setUrl(n+"&id="+e+"&tx_impexp[pagetree][id]="+e+"&tx_impexp[pagetree][levels]=0&tx_impexp[pagetree][tables][]=_ALL"):top.TYPO3.Backend.ContentContainer.setUrl(n+"&tx_impexp[record][]="+t+":"+e+"&tx_impexp[external_ref][tables][]=_ALL")}importT3d(t,e,o){const n=o.actionUrl;top.TYPO3.Backend.ContentContainer.setUrl(n+"&id="+e+"&table="+t)}}var r=new a;export{r as default};
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
import r from"@typo3/backend/modal.js";import o from"@typo3/core/event/regular-event.js";import n from"@typo3/core/document-service.js";class s{constructor(){n.ready().then(()=>this.registerEvents())}registerEvents(){new o("click",this.triggerConfirmation).delegateTo(document,".t3js-confirm-trigger");const e=document.querySelector(".t3js-impexp-toggledisabled");e!==null&&new o("click",this.toggleDisabled).bindTo(e)}triggerConfirmation(){const e=r.confirm(this.dataset.title,this.dataset.message);e.addEventListener("confirm.button.ok",()=>{const t=document.getElementById("t3js-submit-field");t.name=this.name,t.closest("form").submit(),e.hideModal()}),e.addEventListener("confirm.button.cancel",()=>{e.hideModal()})}toggleDisabled(){const e=document.querySelectorAll('table.t3js-impexp-preview tr[data-active="hidden"] input.t3js-exclude-checkbox');if(e.length>0){const t=e.item(0);e.forEach(i=>{i.checked=!t.checked})}}}var c=new s;export{c as default};
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "typo3/cms-impexp",
|
||||
"type": "typo3-cms-framework",
|
||||
"description": "TYPO3 CMS Import/Export - Tool for importing and exporting records using XML or the custom T3D format.",
|
||||
"homepage": "https://typo3.community/",
|
||||
"funding": [
|
||||
{
|
||||
"type": "membership",
|
||||
"url": "https://typo3.org/membership"
|
||||
}
|
||||
],
|
||||
"license": [
|
||||
"GPL-2.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "TYPO3 Core Team",
|
||||
"email": "typo3cms@typo3.org",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://forge.typo3.org/issues/",
|
||||
"forum": "https://talk.typo3.org/",
|
||||
"source": "https://github.com/TYPO3/typo3/",
|
||||
"docs": "https://docs.typo3.org/c/typo3/cms-impexp/main/en-us/",
|
||||
"rss": "https://news.typo3.com/rss/",
|
||||
"chat": "https://typo3.community/meet/slack/",
|
||||
"security": "https://typo3.org/security/"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"require": {
|
||||
"typo3/cms-core": "15.0.*@dev"
|
||||
},
|
||||
"conflict": {
|
||||
"typo3/cms": "*"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "15.0.x-dev"
|
||||
},
|
||||
"typo3/cms": {
|
||||
"Package": {
|
||||
"partOfFactoryDefault": true
|
||||
},
|
||||
"extension-key": "impexp"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"TYPO3\\CMS\\Impexp\\": "Classes/"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
CREATE TABLE tx_impexp_presets (
|
||||
# type=passthrough fields need manual configuration
|
||||
title varchar(255) DEFAULT '' NOT NULL,
|
||||
public tinyint(3) DEFAULT '0' NOT NULL,
|
||||
item_uid int(11) DEFAULT '0' NOT NULL,
|
||||
user_uid int(11) unsigned DEFAULT '0' NOT NULL,
|
||||
preset_data blob,
|
||||
KEY lookup (item_uid)
|
||||
);
|
||||
|
||||
# Some fields need manual configuration
|
||||
CREATE TABLE tt_content (
|
||||
# type=passthrough fields need manual configuration
|
||||
tx_impexp_origuid int(11) DEFAULT '0' NOT NULL
|
||||
);
|
||||
|
||||
# Some fields need manual configuration
|
||||
CREATE TABLE pages (
|
||||
# type=passthrough fields need manual configuration
|
||||
tx_impexp_origuid int(11) DEFAULT '0' NOT NULL
|
||||
);
|
||||
|
||||
# Some fields need manual configuration
|
||||
CREATE TABLE sys_template (
|
||||
# type=passthrough fields need manual configuration
|
||||
tx_impexp_origuid int(11) DEFAULT '0' NOT NULL
|
||||
);
|
||||