Add import configuration record

It is now possible to create "Import" records in TYPO3 system.
Those records can then be imported via two new commands.
There is no need to configure everything within the command itself.

That allows:
    * To allow editors to maintain import configuration.
    * Have proper labels, description, csh and UI to create import.
      It no longer is necessary to copy UIDs,
      instead proper wizards from TCA are available to select pages.

Relates: #9649
This commit is contained in:
Daniel Siepmann 2022-01-27 14:14:02 +01:00
parent 4bc4f34525
commit 3d6bf0ac8a
32 changed files with 1280 additions and 322 deletions

View file

@ -7,7 +7,7 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use TYPO3\CMS\Core\Core\Bootstrap;
use Wrm\Events\Domain\DestinationData\Import;
use Wrm\Events\Domain\DestinationData\LegacyImportFactory;
use Wrm\Events\Service\DestinationDataImportService;
class DestinationDataImportCommand extends Command
@ -17,11 +17,18 @@ class DestinationDataImportCommand extends Command
*/
private $destinationDataImportService;
/**
* @var LegacyImportFactory
*/
private $importFactory;
public function __construct(
DestinationDataImportService $destinationDataImportService
DestinationDataImportService $destinationDataImportService,
LegacyImportFactory $importFactory
) {
parent::__construct();
$this->destinationDataImportService = $destinationDataImportService;
$this->importFactory = $importFactory;
}
public function configure(): void
@ -72,12 +79,19 @@ class DestinationDataImportCommand extends Command
$query = '';
}
return $this->destinationDataImportService->import(new Import(
$input->getArgument('rest-experience'),
$input->getArgument('storage-pid'),
$regionUid,
$input->getArgument('files-folder'),
$query
));
$import = $this->importFactory->createFromArray([
'storage_pid' => $input->getArgument('storage-pid'),
'files_folder' => $input->getArgument('files-folder'),
'region_uid' => $regionUid,
'rest_experience' => $input->getArgument('rest-experience'),
'rest_search_query' => $query,
]);
return $this->destinationDataImportService->import(
$import
);
}
}

View file

@ -0,0 +1,54 @@
<?php
namespace Wrm\Events\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use TYPO3\CMS\Core\Core\Bootstrap;
use Wrm\Events\Domain\DestinationData\ImportFactory;
use Wrm\Events\Service\DestinationDataImportService;
class ImportDestinationDataViaAllConfigruationsCommand extends Command
{
/**
* @var DestinationDataImportService
*/
private $destinationDataImportService;
/**
* @var ImportFactory
*/
private $importFactory;
public function __construct(
DestinationDataImportService $destinationDataImportService,
ImportFactory $importFactory
) {
parent::__construct();
$this->destinationDataImportService = $destinationDataImportService;
$this->importFactory = $importFactory;
}
public function configure(): void
{
$this->setDescription('Import Destination Data Events');
$this->setHelp('Destination Data Events are imported from all configuration records.');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
Bootstrap::initializeBackendAuthentication();
$finalResult = 0;
foreach ($this->importFactory->createAll() as $import) {
$result = $this->destinationDataImportService->import($import);
if ($result !== 0) {
$finalResult = $result;
}
}
return $finalResult;
}
}

View file

@ -0,0 +1,64 @@
<?php
namespace Wrm\Events\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use TYPO3\CMS\Core\Core\Bootstrap;
use Wrm\Events\Domain\DestinationData\ImportFactory;
use Wrm\Events\Service\DestinationDataImportService;
class ImportDestinationDataViaConfigruationCommand extends Command
{
/**
* @var DestinationDataImportService
*/
private $destinationDataImportService;
/**
* @var ImportFactory
*/
private $importFactory;
public function __construct(
DestinationDataImportService $destinationDataImportService,
ImportFactory $importFactory
) {
parent::__construct();
$this->destinationDataImportService = $destinationDataImportService;
$this->importFactory = $importFactory;
}
public function configure(): void
{
$this->setDescription('Import Destination Data Events');
$this->setHelp('Destination Data Events are imported from given configuration record.');
$this->addArgument(
'configurationUid',
InputArgument::REQUIRED,
'UID of the configuration to import'
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
Bootstrap::initializeBackendAuthentication();
$configurationUid = $input->getArgument('configurationUid');
if (is_numeric($configurationUid)) {
$configurationUid = (int) $configurationUid;
} else {
throw new \Exception('No numeric uid for configuration provided.', 1643267138);
}
$import = $this->importFactory->createFromUid(
$configurationUid
);
return $this->destinationDataImportService->import(
$import
);
}
}

View file

@ -1,74 +0,0 @@
<?php
namespace Wrm\Events\Domain\DestinationData;
/**
* Actual request to import.
* Includes all configuration specific to a concrete import.
*/
class Import
{
/**
* @var string
*/
private $restExperience;
/**
* @var int
*/
private $storagePid;
/**
* @var int|null
*/
private $regionUid;
/**
* @var string
*/
private $filesFolder;
/**
* @var string
*/
private $searchQuery;
public function __construct(
string $restExperience,
int $storagePid,
?int $regionUid,
string $filesFolder,
string $searchQuery
) {
$this->restExperience = $restExperience;
$this->storagePid = $storagePid;
$this->regionUid = $regionUid;
$this->filesFolder = $filesFolder;
$this->searchQuery = $searchQuery;
}
public function getRestExperience(): string
{
return $this->restExperience;
}
public function getStoragePid(): int
{
return $this->storagePid;
}
public function getRegionUid(): ?int
{
return $this->regionUid;
}
public function getFilesFolder(): string
{
return $this->filesFolder;
}
public function getSearchQuery(): string
{
return $this->searchQuery;
}
}

View file

@ -0,0 +1,129 @@
<?php
namespace Wrm\Events\Domain\DestinationData;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Resource\Folder;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
use TYPO3\CMS\Extbase\Persistence\Generic\Session;
use Wrm\Events\Domain\Model\Import;
class ImportFactory
{
/**
* @var ConnectionPool
*/
private $connectionPool;
/**
* @var Session
*/
private $extbasePersistenceSession;
/**
* @var DataMapper
*/
private $dataMapper;
/**
* @var ResourceFactory
*/
private $resourceFactory;
/**
* @var Folder
*/
private $folderInstance;
public function __construct(
ConnectionPool $connectionPool,
Session $extbasePersistenceSession,
DataMapper $dataMapper,
ResourceFactory $resourceFactory
) {
$this->connectionPool = $connectionPool;
$this->extbasePersistenceSession = $extbasePersistenceSession;
$this->dataMapper = $dataMapper;
$this->resourceFactory = $resourceFactory;
}
public function createFromUid(int $uid): Import
{
return $this->create($this->fetchImportRecord($uid));
}
/**
* @return Import[]
*/
public function createAll(): array
{
return array_map(
[$this, 'create'],
$this->fetchImportRecords()
);
}
private function fetchImportRecord(int $uid): array
{
$qb = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_import');
$qb->select('*');
$qb->from('tx_events_domain_model_import');
$qb->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid, \PDO::PARAM_INT)));
$result = $qb->execute()->fetch();
if (is_array($result) === false) {
throw new \Exception('Could not fetch import record with uid "' . $uid . '".', 1643267492);
}
$result = array_map('strval', $result);
return $result;
}
private function fetchImportRecords(): array
{
$qb = $this->connectionPool->getQueryBuilderForTable('tx_events_domain_model_import');
$qb->select('*');
$qb->from('tx_events_domain_model_import');
$result = $qb->execute()->fetchAll();
if (count($result) === 0) {
throw new \Exception('Could not fetch any import record.', 1643267492);
}
foreach ($result as $key => $entry) {
$result[$key] = array_map('strval', $entry);
}
return $result;
}
/**
* Only public in order to be used by LegacyImportFactory.
* Make private once the class is removed.
*
* @internal
*/
public function create(array $data): Import
{
$this->createWorkarounds($data);
$result = $this->dataMapper->map(Import::class, [$data])[0];
$this->cleanupWorkarounds();
return $result;
}
private function createWorkarounds(array $data): void
{
$this->folderInstance = $this->resourceFactory->getFolderObjectFromCombinedIdentifier($data['files_folder']);
$this->extbasePersistenceSession->registerObject($this->folderInstance, $data['files_folder']);
}
private function cleanupWorkarounds(): void
{
$this->extbasePersistenceSession->unregisterObject($this->folderInstance);
}
}

View file

@ -0,0 +1,103 @@
<?php
namespace Wrm\Events\Domain\DestinationData;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3\CMS\Extbase\Persistence\Generic\Session;
use Wrm\Events\Domain\Model\Import;
/**
* This is only for legacy imports where folder is not configured by TCA and provided in TYPO3 way,
* but provided as plain string which was resolved to default storyage within import service.
*
* Should be dropped once old import command is dropped.
*/
class LegacyImportFactory
{
/**
* @var ImportFactory
*/
private $importFactory;
/**
* @var ResourceFactory
*/
private $resourceFactory;
/**
* @var ConfigurationManager
*/
private $configurationManager;
/**
* @var Session
*/
private $extbasePersistenceSession;
public function __construct(
ImportFactory $importFactory,
ResourceFactory $resourceFactory,
ConfigurationManager $configurationManager,
Session $extbasePersistenceSession
) {
$this->importFactory = $importFactory;
$this->resourceFactory = $resourceFactory;
$this->configurationManager = $configurationManager;
$this->extbasePersistenceSession = $extbasePersistenceSession;
}
public function createFromArray(array $configuration): Import
{
$result = array_map('strval', $configuration);
$result['uid'] = $this->getUniqueUid();
$result['files_folder'] = $this->migrateFileFolder($result['files_folder'] ?? '');
$result['region'] = $result['region_uid'];
unset($result['region_uid']);
$result = $this->addCategorySettings($result);
return $this->importFactory->create($result);
}
private function getUniqueUid(): string
{
do {
// Only temporary solution as long as legacy exists.
// Cool solution would be to fetch highest uid + 100, but that's to much for now.
// Also this will vanish in future.
$uid = (string) random_int(999, PHP_INT_MAX);
} while ($this->extbasePersistenceSession->hasIdentifier($uid, Import::class));
return $uid;
}
private function migrateFileFolder(string $fileFolder): string
{
$storage = $this->resourceFactory->getDefaultStorage();
if ($storage === null) {
throw new \Exception('No default storage defined. Cancel import.', 1643290642);
}
$uid = $storage->getUid();
return $uid . ':/' . trim($fileFolder, '/') . '/';
}
private function addCategorySettings(array $result): array
{
$settings = $this->configurationManager->getConfiguration(
ConfigurationManager::CONFIGURATION_TYPE_SETTINGS,
'Events',
'Pi1'
);
$result['categories_pid'] = $settings['destinationData']['categoriesPid'] ?? '';
$result['category_parent'] = $settings['destinationData']['categoryParentUid'] ?? '';
return $result;
}
}

View file

@ -0,0 +1,104 @@
<?php
namespace Wrm\Events\Domain\Model;
use TYPO3\CMS\Core\Resource\Folder;
use TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject;
/**
* Actual request to import.
* Includes all configuration specific to a concrete import.
*/
class Import extends AbstractDomainObject
{
/**
* @var int
*/
protected $storagePid;
/**
* @var Folder
*/
protected $filesFolder;
/**
* @var int
*/
protected $categoriesPid;
/**
* @var Category|null
*/
protected $categoryParent;
/**
* @var Region|null
*/
protected $region;
/**
* @var string
*/
protected $restExperience;
/**
* @var string
*/
protected $restSearchQuery;
public function __construct(
Folder $filesFolder,
int $storagePid,
string $restExperience,
string $restSearchQuery = '',
int $categoriesPid = 0,
?Category $categoryParent = null,
?Region $region = null
) {
$this->filesFolder = $filesFolder;
$this->storagePid = $storagePid;
$this->categoriesPid = $categoriesPid;
$this->categoryParent = $categoryParent;
$this->restExperience = $restExperience;
$this->restSearchQuery = $restSearchQuery;
$this->region = $region;
}
public function getStoragePid(): int
{
return $this->storagePid;
}
public function getFilesFolder(): Folder
{
return $this->filesFolder;
}
public function getCategoriesPid(): int
{
return $this->categoriesPid;
}
public function getCategoryParent(): ?Category
{
return $this->categoryParent;
}
public function getRegion(): ?Region
{
return $this->region;
}
public function getRestExperience(): string
{
return $this->restExperience;
}
public function getSearchQuery(): string
{
return $this->restSearchQuery;
}
}

View file

@ -2,7 +2,6 @@
namespace Wrm\Events\Service;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\DataHandling\SlugHelper;
@ -11,7 +10,6 @@ use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException;
use TYPO3\CMS\Core\Resource\File;
use TYPO3\CMS\Core\Resource\Index\MetaDataRepository;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Resource\ResourceStorage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
@ -19,17 +17,16 @@ use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
use Wrm\Events\Domain\DestinationData\Import;
use Wrm\Events\Domain\Model\Category;
use Wrm\Events\Domain\Model\Date;
use Wrm\Events\Domain\Model\Event;
use Wrm\Events\Domain\Model\Import;
use Wrm\Events\Domain\Model\Organizer;
use Wrm\Events\Domain\Model\Region;
use Wrm\Events\Domain\Repository\CategoryRepository;
use Wrm\Events\Domain\Repository\DateRepository;
use Wrm\Events\Domain\Repository\EventRepository;
use Wrm\Events\Domain\Repository\OrganizerRepository;
use Wrm\Events\Domain\Repository\RegionRepository;
use Wrm\Events\Service\DestinationDataImportService\DataFetcher;
class DestinationDataImportService
@ -39,21 +36,6 @@ class DestinationDataImportService
*/
private $import;
/**
* @var int
*/
private $categoriesPid;
/**
* @var int
*/
private $categoryParentUid;
/**
* @var Environment
*/
private $environment;
/**
* @var Event
*/
@ -69,11 +51,6 @@ class DestinationDataImportService
*/
private $eventRepository;
/**
* @var RegionRepository
*/
private $regionRepository;
/**
* @var OrganizerRepository
*/
@ -109,11 +86,6 @@ class DestinationDataImportService
*/
private $persistenceManager;
/**
* @var ResourceFactory
*/
private $resourceFactory;
/**
* @var DataFetcher
*/
@ -122,52 +94,35 @@ class DestinationDataImportService
/**
* ImportService constructor.
* @param EventRepository $eventRepository
* @param RegionRepository $regionRepository
* @param OrganizerRepository $organizerRepository
* @param DateRepository $dateRepository
* @param CategoryRepository $sysCategoriesRepository
* @param MetaDataRepository $metaDataRepository
* @param ConfigurationManager $configurationManager
* @param PersistenceManager $persistenceManager
* @param ResourceFactory $resourceFactory
* @param ObjectManager $objectManager
* @param Environment $environment
* @param DataFetcher $dataFetcher
*/
public function __construct(
EventRepository $eventRepository,
RegionRepository $regionRepository,
OrganizerRepository $organizerRepository,
DateRepository $dateRepository,
CategoryRepository $sysCategoriesRepository,
MetaDataRepository $metaDataRepository,
ConfigurationManager $configurationManager,
PersistenceManager $persistenceManager,
ResourceFactory $resourceFactory,
ObjectManager $objectManager,
Environment $environment,
DataFetcher $dataFetcher
) {
$this->eventRepository = $eventRepository;
$this->regionRepository = $regionRepository;
$this->organizerRepository = $organizerRepository;
$this->dateRepository = $dateRepository;
$this->sysCategoriesRepository = $sysCategoriesRepository;
$this->metaDataRepository = $metaDataRepository;
$this->configurationManager = $configurationManager;
$this->persistenceManager = $persistenceManager;
$this->resourceFactory = $resourceFactory;
$this->objectManager = $objectManager;
$this->environment = $environment;
$this->dataFetcher = $dataFetcher;
$settings = $this->configurationManager->getConfiguration(
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
'Events',
'Pi1'
)['destinationData'] ?? [];
$this->categoriesPid = (int) $settings['categoriesPid'];
$this->categoryParentUid = (int) $settings['categoryParentUid'];
}
public function import(
@ -207,10 +162,7 @@ class DestinationDataImportService
$this->logger->info('Processing json ' . count($data['items']));
// Get selected region
$selectedRegion = null;
if (is_int($this->import->getRegionUid())) {
$selectedRegion = $this->regionRepository->findByUid($this->import->getRegionUid());
}
$selectedRegion = $this->import->getRegion();
foreach ($data['items'] as $event) {
$this->logger->info('Processing event ' . substr($event['title'], 0, 20));
@ -298,16 +250,8 @@ class DestinationDataImportService
*/
private function setCategories(array $categories): void
{
if ($this->categoryParentUid === 0) {
return;
}
$sysParentCategory = $this->sysCategoriesRepository->findByUid($this->categoryParentUid);
$sysParentCategory = $this->import->getCategoryParent();
if (!$sysParentCategory instanceof Category) {
$this->logger->warning(
'Could not fetch system parent category by uid.',
['uid' => $this->categoryParentUid]
);
return;
}
@ -318,7 +262,7 @@ class DestinationDataImportService
$tmpSysCategory = $this->objectManager->get(Category::class);
$tmpSysCategory->setTitle($categoryTitle);
$tmpSysCategory->setParent($sysParentCategory);
$tmpSysCategory->setPid($this->categoriesPid);
$tmpSysCategory->setPid($this->import->getCategoriesPid());
$this->sysCategoriesRepository->add($tmpSysCategory);
$this->tmpCurrentEvent->addCategory($tmpSysCategory);
} else {
@ -563,18 +507,14 @@ class DestinationDataImportService
{
$this->logger->info("Set assets");
$storage = $this->resourceFactory->getDefaultStorage();
if (!$storage instanceof ResourceStorage) {
$this->logger->error('No default storage defined. Cancel import.');
exit();
}
$importFolder = $this->import->getFilesFolder();
$error = false;
foreach ($assets as $media_object) {
if ($media_object['rel'] == "default" && $media_object['type'] == "image/jpeg") {
$fileUrl = urldecode($media_object['url']);
$orgFileNameSanitized = $storage->sanitizeFileName(
$orgFileNameSanitized = $importFolder->getStorage()->sanitizeFileName(
basename(
urldecode($media_object['url'])
)
@ -583,11 +523,7 @@ class DestinationDataImportService
$this->logger->info('File attached:' . $fileUrl);
$this->logger->info('File attached sanitized:' . $orgFileNameSanitized);
$targetFilePath = $this->environment->getPublicPath() . '/fileadmin/' . $this->import->getFilesFolder()
. $orgFileNameSanitized;
// Check if file already exists
if (file_exists($targetFilePath)) {
if ($importFolder->hasFile($orgFileNameSanitized)) {
$this->logger->info('File already exists');
} else {
$this->logger->info("File don't exist " . $orgFileNameSanitized);
@ -596,13 +532,7 @@ class DestinationDataImportService
// Move file to defined folder
$this->logger->info('Adding file ' . $filename);
try {
$targetFolder = $storage->getFolder($this->import->getFilesFolder());
} catch (FolderDoesNotExistException $e) {
$targetFolder = $storage->createFolder($this->import->getFilesFolder());
}
$storage->addFile($filename, $targetFolder, basename($fileUrl));
$importFolder->addFile($filename, basename($fileUrl));
} else {
$error = true;
}
@ -614,12 +544,17 @@ class DestinationDataImportService
// TODO: How to delete file references?
} else {
$this->logger->info('No relation found');
$fileIdentifier = $this->import->getFilesFolder() . $orgFileNameSanitized;
$file = $storage->getFile($fileIdentifier);
if (!$file instanceof File) {
$this->logger->warning('Could not find file.', [$fileIdentifier]);
if ($importFolder->hasFile($orgFileNameSanitized) === false) {
$this->logger->warning('Could not find file.', [$orgFileNameSanitized]);
continue;
}
$file = $importFolder->getStorage()->getFileInFolder($orgFileNameSanitized, $importFolder);
if (!$file instanceof File) {
$this->logger->warning('Could not find file.', [$orgFileNameSanitized]);
continue;
}
$this->metaDataRepository->update(
$file->getUid(),
[

View file

@ -8,7 +8,7 @@ use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Log\Logger;
use TYPO3\CMS\Core\Log\LogManager;
use Wrm\Events\Domain\DestinationData\Import;
use Wrm\Events\Domain\Model\Import;
/**
* Provides API to fetch data from remote.

View file

@ -5,7 +5,7 @@ namespace Wrm\Events\Service\DestinationDataImportService;
use TYPO3\CMS\Core\Http\Uri;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use Wrm\Events\Domain\DestinationData\Import;
use Wrm\Events\Domain\Model\Import;
/**
* Factory to create URLs used during import of Destination Data.

View file

@ -20,6 +20,18 @@ services:
command: 'events:destinationdataimport'
description: 'Import Destination Data Events'
Wrm\Events\Command\ImportDestinationDataViaConfigruationCommand:
tags:
- name: 'console.command'
command: 'events:destinationdataimportviaconfiguration'
description: 'Import Destination Data Events'
Wrm\Events\Command\ImportDestinationDataViaAllConfigruationsCommand:
tags:
- name: 'console.command'
command: 'events:destinationdataimportviaallconfigurations'
description: 'Import Destination Data Events from all configurations'
Wrm\Events\Command\RemoveAllCommand:
tags:
- name: 'console.command'

View file

@ -0,0 +1,150 @@
<?php
return [
'ctrl' => [
'title' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import',
'label' => 'title',
'label_alt' => 'rest_experience',
'label_alt_force' => true,
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'delete' => 'deleted',
'enablecolumns' => [
'disabled' => 'hidden',
],
'searchFields' => 'title',
'iconfile' => 'EXT:events/Resources/Public/Icons/tx_events_domain_model_import.svg'
],
'types' => [
'1' => [
'showitem' => 'title, hidden, --div--;LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.div.typo3, --palette--;;typo3_storage, --palette--;;categories, --palette--;;relations, --div--;LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.div.rest, rest_experience, rest_search_query'
],
],
'palettes' => [
'typo3_storage' => [
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.palette.typo3_storage',
'showitem' => 'storage_pid, files_folder'
],
'categories' => [
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.palette.categories',
'showitem' => 'category_parent, categories_pid'
],
'relations' => [
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.palette.relations',
'showitem' => 'region'
],
],
'columns' => [
'hidden' => [
'exclude' => true,
'label' => 'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.visible',
'config' => [
'type' => 'check',
'renderType' => 'checkboxToggle',
'items' => [
[
0 => '',
1 => '',
'invertStateDisplay' => true
]
],
],
],
'title' => [
'exclude' => true,
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.title',
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.title.description',
'config' => [
'type' => 'input',
'size' => 50,
'max' => 255,
],
],
'storage_pid' => [
'exclude' => true,
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.storage_pid',
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.storage_pid.description',
'config' => [
'type' => 'group',
'internal_type' => 'db',
'allowed' => 'pages',
'size' => 1,
'maxitems' => 1,
'minitems' => 1,
],
],
'region' => [
'exclude' => true,
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.region',
'config' => [
'type' => 'group',
'internal_type' => 'db',
'allowed' => 'tx_events_domain_model_region',
'size' => 1,
'maxitems' => 1,
'minitems' => 0,
],
],
'categories_pid' => [
'exclude' => true,
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.categories_pid',
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.categories_pid.description',
'config' => [
'type' => 'group',
'internal_type' => 'db',
'allowed' => 'pages',
'size' => 1,
'maxitems' => 1,
'minitems' => 0,
],
],
'category_parent' => [
'exclude' => true,
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.category_parent',
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.category_parent.description',
'config' => [
'type' => 'group',
'internal_type' => 'db',
'allowed' => 'sys_category',
'size' => 1,
'maxitems' => 1,
'minitems' => 0,
],
],
'files_folder' => [
'exclude' => true,
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.files_folder',
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.files_folder.description',
'config' => [
'type' => 'group',
'internal_type' => 'folder',
'size' => 1,
'maxitems' => 1,
'minitems' => 1,
],
],
'rest_experience' => [
'exclude' => true,
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.rest_experience',
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.rest_experience.description',
'config' => [
'type' => 'input',
'size' => 50,
'max' => 255,
],
],
'rest_search_query' => [
'exclude' => true,
'label' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.rest_search_query',
'description' => 'LLL:EXT:events/Resources/Private/Language/locallang_csh_import.xlf:tx_events_domain_model_import.rest_search_query.description',
'config' => [
'type' => 'input',
'size' => 50,
'max' => 255,
],
],
],
];

View file

@ -9,6 +9,12 @@ Nothing
Features
--------
* Import configuration can now be configured as database records within TYPO3 folders.
This allows for better support (e.g. permission of backend users and validation and wizards like page selection).
Two new import commands are added.
One allows to process all available import configurations.
The other allows to process a single import configuration which needs to be configured.
* Add new option ``query`` to ``DestinationDataImportCommand``.
It is appended as ``q`` parameter to the initial search URL to fetch data for import.
The value is documented at https://developer.et4.de/reference/current/#eT4META-search-param-q.html.

View file

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="messages" date="2022-01-27T08:22:40Z" product-name="Events">
<header/>
<body>
<trans-unit id="tx_events_domain_model_import">
<source>Import Configuration</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.div.typo3">
<source>TYPO3</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.div.rest">
<source>REST</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.palette.relations">
<source>Relations</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.palette.typo3_storage">
<source>TYPO3 Storages</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.palette.categories">
<source>Categories</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.title">
<source>Title</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.title.description">
<source>Only for backend search and UX, not used for actual import.</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.storage_pid">
<source>Storage Page</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.storage_pid.description">
<source>TYPO3 page to use for storing imported data.</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.region">
<source>Region</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.categories_pid">
<source>Categories Storage Folder</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.categories_pid.description">
<source>TYPO3 page to use for storing imported categories.</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.category_parent">
<source>Parent Category</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.category_parent.description">
<source>Existing TYPO3 category used as parent for all categories created during import.</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.files_folder">
<source>Folder</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.files_folder.description">
<source>TYPO3 folder to use for storing imported files.</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.rest_experience">
<source>Experience</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.rest_experience.description">
<source>See: https://developer.et4.de/reference/current/#eT4META-search-param-experience.html (todo check, was not loadable)</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.rest_search_query">
<source>Search Query</source>
</trans-unit>
<trans-unit id="tx_events_domain_model_import.rest_search_query.description">
<source>See: https://developer.et4.de/reference/current/#eT4META-search-param-q.html (todo check, was not loadable)</source>
</trans-unit>
</body>
</file>
</xliff>

View file

@ -0,0 +1 @@
<svg id="Ebene_1" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><rect width="16" height="16" fill="#f18519"/><polygon points="9.348 13.939 7.736 13.348 6.403 12.431 4.837 12.323 3.438 11.883 6.98 1.703 8.072 2.083 9.475 3.241 11.293 3.203 12.89 3.759 9.348 13.939" fill="#fff"/><line x1="5.56817" y1="9.89512" x2="6.60766" y2="10.25681" fill="#f18519" stroke="#f18519" stroke-linecap="round" stroke-miterlimit="10" stroke-width="0.5"/><line x1="7.75059" y1="10.65449" x2="8.76597" y2="11.00779" fill="#f18519" stroke="#f18519" stroke-linecap="round" stroke-miterlimit="10" stroke-width="0.5"/><path d="M8.42341,1.942,6.73947,1.3561l-3.725,10.70565,1.81686.63217A1.61336,1.61336,0,0,1,7.424,13.596l1.98114.68933,3.725-10.70565-2.01139-.69985A1.59583,1.59583,0,0,1,8.42341,1.942Z" fill="none" stroke="#fff" stroke-miterlimit="10" stroke-width="0.75"/><line x1="9.76625" y1="11.35583" x2="10.66971" y2="11.67018" fill="#f18519" stroke="#f18519" stroke-linecap="round" stroke-miterlimit="10" stroke-width="0.5"/><line x1="3.63513" y1="9.22253" x2="4.5725" y2="9.54869" fill="#f18519" stroke="#f18519" stroke-linecap="round" stroke-miterlimit="10" stroke-width="0.5"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -14,6 +14,10 @@ use Wrm\Events\Tests\ClientFactory;
abstract class AbstractTest extends FunctionalTestCase
{
protected $coreExtensionsToLoad = [
'filelist',
];
protected $testExtensionsToLoad = [
'typo3conf/ext/events',
];
@ -65,9 +69,11 @@ abstract class AbstractTest extends FunctionalTestCase
return $requests;
}
protected function executeCommand(array $argumentsAndOptions): CommandTester
{
$subject = $this->getContainer()->get(DestinationDataImportCommand::class);
protected function executeCommand(
array $argumentsAndOptions,
string $command = DestinationDataImportCommand::class
): CommandTester {
$subject = $this->getContainer()->get($command);
self::assertInstanceOf(Command::class, $subject);
$tester = new CommandTester($subject);

View file

@ -0,0 +1,67 @@
"tx_events_domain_model_organizer",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,"uid","pid","cruser_id","deleted","hidden","starttime","endtime","sys_language_uid","l10n_parent","t3ver_oid","t3ver_wsid","t3ver_state","t3ver_stage","name","street","district","city","zip","phone","web","email",,,,,,,,,,,,,,,,,,,,,,
,"1","2","0","0","0","0","0","-1","0","0","0","0","0","Schillerhaus Rudolstadt","Schillerstraße 25",,"Rudolstadt","07407","+ 49 3672 / 486470","http://schillerhaus.rudolstadt.de","schillerhaus@rudolstadt.de",,,,,,,,,,,,,,,,,,,,,,
,"2","2","0","0","0","0","0","-1","0","0","0","0","0","Stadtbibliothek Rudolstadt","Schulplatz 13",,"Rudolstadt","07407","0 36 72 - 48 64 20","http://www.stadtbibliothek-rudolstadt.de ","stadtbibliothek@rudolstadt.de",,,,,,,,,,,,,,,,,,,,,,
,"3","2","0","0","0","0","0","-1","0","0","0","0","0","Lutherkirche","Caspar-Schulte-Straße",,"Rudolstadt","07407","03672 - 48 96 13",,,,,,,,,,,,,,,,,,,,,,,,
,"4","3","0","0","0","0","0","-1","0","0","0","0","0","Schillerhaus Rudolstadt","Schillerstraße 25",,"Rudolstadt","07407","+ 49 3672 / 486470","http://schillerhaus.rudolstadt.de","schillerhaus@rudolstadt.de",,,,,,,,,,,,,,,,,,,,,,
,"5","3","0","0","0","0","0","-1","0","0","0","0","0","Stadtbibliothek Rudolstadt","Schulplatz 13",,"Rudolstadt","07407","0 36 72 - 48 64 20","http://www.stadtbibliothek-rudolstadt.de ","stadtbibliothek@rudolstadt.de",,,,,,,,,,,,,,,,,,,,,,
,"6","3","0","0","0","0","0","-1","0","0","0","0","0","Lutherkirche","Caspar-Schulte-Straße",,"Rudolstadt","07407","03672 - 48 96 13",,,,,,,,,,,,,,,,,,,,,,,,
"tx_events_domain_model_event",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,"uid","pid","cruser_id","deleted","hidden","starttime","endtime","sys_language_uid","l10n_parent","t3ver_oid","t3ver_wsid","t3ver_state","t3ver_stage","title","subtitle","global_id","slug","highlight","teaser","details","price_info","name","street","district","city","zip","country","web","phone","ticket","facebook","youtube","instagram","latitude","longitude","images","categories","pages","dates","organizer","partner","region","references_events"
,"1","2","0","0","0","0","0","-1","0","0","0","0","0","Allerlei Weihnachtliches (Heute mit Johannes Geißer)",,"e_100347853","e-100347853","0",,"Die Lichter sind entzündet, die Plätzchen duften, man rückt endlich wieder näher zusammen und lauscht den Geschichten. Vier Schauspieler*innen unseres Theaters überraschen mit ihren weihnachtlichen Texten, die sie für uns ausgewählt haben. Dazu plaudern sie über persönliche Anekdoten und erinnern sich an ihre schönsten und verrücktesten Weihnachtsfeste. Und da der Genuss in der Vorweihnachtszeit nicht fehlen darf, wird an jedem Adventssonntag eine andere weihnachtliche Spezialität serviert.
Eintritt: 10 € (inkl. Gedeck mit weihnachtlicher Schillerlocke)
Um Voranmeldung unter 03672-486470 oder schillerhaus@rudolstadt.de wird gebeten.
Es gilt die 2G-PLUS-Regel.",,"Schillerhaus Rudolstadt","Schillerstraße 25",,"Rudolstadt","07407","Deutschland","http://www.schillerhaus.rudolstadt.de/","+ 49 3672 / 486470",,,,,"50.720971023259","11.335229873657","1","1",,"1","1",,"1",
,"2","2","0","0","0","0","0","-1","0","0","0","0","0","Tüftlerzeit",,"e_100354481","e-100354481","0",,"Die Tüftlerzeit wird dieses Mal ein weihnachtliches Angebot bereithalten. Alle kleinen Tüftler dürfen gespannt sein.
Voranmeldung über: kinderbibliothek@rudolstadt.de oder 03672-486420
Bitte beachten Sie die derzeit geltenden Zugangsregeln.",,"Stadtbibliothek Rudolstadt","Schulplatz 13",,"Rudolstadt","07407","Deutschland","http://www.stadtbibliothek-rudolstadt.de/","0 36 72 - 48 64 20",,,,,"50.720835175056","11.342568397522","1","1",,"3","2",,"1",
,"3","2","0","0","0","0","0","-1","0","0","0","0","0","Adventliche Orgelmusik (Orgel: KMD Frank Bettenhausen)",,"e_100350503","e-100350503","0",,"Immer mittwochs in der Adventszeit spielt Frank Bettenhausen solo und zusammen mit anderen Musikern auf der Steinmeyerorgel aus dem Jahr 1906. Bekannte Adventslieder, barocke und romantische Kompositionen stehen neben besinnlichen Texten von Pfarrer Johannes-Martin Weiss.
Es gilt die 2G-PLUS-Regel.",,"Lutherkirche","Caspar-Schulte-Straße",,"Rudolstadt","07407","Deutschland",,"03672 - 48 96 13",,,,,"50.718688721183","11.327333450317","1","2",,"4","3",,"1",
,"4","3","0","0","0","0","0","-1","0","0","0","0","0","Allerlei Weihnachtliches (Heute mit Johannes Geißer)",,"e_100347853","e-100347853","0",,"Die Lichter sind entzündet, die Plätzchen duften, man rückt endlich wieder näher zusammen und lauscht den Geschichten. Vier Schauspieler*innen unseres Theaters überraschen mit ihren weihnachtlichen Texten, die sie für uns ausgewählt haben. Dazu plaudern sie über persönliche Anekdoten und erinnern sich an ihre schönsten und verrücktesten Weihnachtsfeste. Und da der Genuss in der Vorweihnachtszeit nicht fehlen darf, wird an jedem Adventssonntag eine andere weihnachtliche Spezialität serviert.
Eintritt: 10 € (inkl. Gedeck mit weihnachtlicher Schillerlocke)
Um Voranmeldung unter 03672-486470 oder schillerhaus@rudolstadt.de wird gebeten.
Es gilt die 2G-PLUS-Regel.",,"Schillerhaus Rudolstadt","Schillerstraße 25",,"Rudolstadt","07407","Deutschland","http://www.schillerhaus.rudolstadt.de/","+ 49 3672 / 486470",,,,,"50.720971023259","11.335229873657","1","1",,"1","4",,"1",
,"5","3","0","0","0","0","0","-1","0","0","0","0","0","Tüftlerzeit",,"e_100354481","e-100354481","0",,"Die Tüftlerzeit wird dieses Mal ein weihnachtliches Angebot bereithalten. Alle kleinen Tüftler dürfen gespannt sein.
Voranmeldung über: kinderbibliothek@rudolstadt.de oder 03672-486420
Bitte beachten Sie die derzeit geltenden Zugangsregeln.",,"Stadtbibliothek Rudolstadt","Schulplatz 13",,"Rudolstadt","07407","Deutschland","http://www.stadtbibliothek-rudolstadt.de/","0 36 72 - 48 64 20",,,,,"50.720835175056","11.342568397522","1","1",,"3","5",,"1",
,"6","3","0","0","0","0","0","-1","0","0","0","0","0","Adventliche Orgelmusik (Orgel: KMD Frank Bettenhausen)",,"e_100350503","e-100350503","0",,"Immer mittwochs in der Adventszeit spielt Frank Bettenhausen solo und zusammen mit anderen Musikern auf der Steinmeyerorgel aus dem Jahr 1906. Bekannte Adventslieder, barocke und romantische Kompositionen stehen neben besinnlichen Texten von Pfarrer Johannes-Martin Weiss.
Es gilt die 2G-PLUS-Regel.",,"Lutherkirche","Caspar-Schulte-Straße",,"Rudolstadt","07407","Deutschland",,"03672 - 48 96 13",,,,,"50.718688721183","11.327333450317","1","2",,"4","6",,"1",
"tx_events_domain_model_date",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,"uid","pid","cruser_id","hidden","starttime","endtime","sys_language_uid","l10n_parent","t3ver_oid","t3ver_wsid","t3ver_state","event","start","end","canceled","postponed_date","canceled_link",,,,,,,,,,,,,,,,,,,,,,,,,,
,"1","2","0","0","0","0",-1,0,"0","0","0","1","4101372000","4101377400","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"2","2","0","0","0","0",-1,0,"0","0","0","2","4101112800","4101118200","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"3","2","0","0","0","0",-1,0,"0","0","0","2","4072600800","4072608000","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"4","2","0","0","0","0",-1,0,"0","0","0","2","4075020000","4075027200","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"5","2","0","0","0","0",-1,0,"0","0","0","3","4099831200","4099834800","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"6","2","0","0","0","0",-1,0,"0","0","0","3","4100436000","4100439600","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"7","2","0","0","0","0",-1,0,"0","0","0","3","4101040800","4101044400","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"8","2","0","0","0","0",-1,0,"0","0","0","3","4101645600","4101649200","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"9","3","0","0","0","0",-1,0,"0","0","0","4","4101372000","4101377400","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"10","3","0","0","0","0",-1,0,"0","0","0","5","4101112800","4101118200","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"11","3","0","0","0","0",-1,0,"0","0","0","5","4072600800","4072608000","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"12","3","0","0","0","0",-1,0,"0","0","0","5","4075020000","4075027200","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"13","3","0","0","0","0",-1,0,"0","0","0","6","4099831200","4099834800","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"14","3","0","0","0","0",-1,0,"0","0","0","6","4100436000","4100439600","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"15","3","0","0","0","0",-1,0,"0","0","0","6","4101040800","4101044400","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
,"16","3","0","0","0","0",-1,0,"0","0","0","6","4101645600","4101649200","no","0",,,,,,,,,,,,,,,,,,,,,,,,,,,
"sys_category",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,"uid","pid","cruser_id","hidden","starttime","endtime","sys_language_uid","l10n_parent","title","items","parent",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,1,2,0,0,0,0,0,0,"Top Category",0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,2,2,0,0,0,0,0,0,"Event Category Parent",0,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,3,2,0,0,0,0,0,0,"Weihnachten",0,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,4,2,0,0,0,0,0,0,"Kinder",0,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,5,2,0,0,0,0,0,0,"Konzerte, Festivals, Show & Tanz",0,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
"sys_category_record_mm",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,"uid_local","uid_foreign","tablenames","fieldname",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,3,1,"tx_events_domain_model_event","categories",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,4,2,"tx_events_domain_model_event","categories",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,5,3,"tx_events_domain_model_event","categories",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,3,3,"tx_events_domain_model_event","categories",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,3,4,"tx_events_domain_model_event","categories",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,4,5,"tx_events_domain_model_event","categories",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,5,6,"tx_events_domain_model_event","categories",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,3,6,"tx_events_domain_model_event","categories",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1 tx_events_domain_model_organizer
2 uid pid cruser_id deleted hidden starttime endtime sys_language_uid l10n_parent t3ver_oid t3ver_wsid t3ver_state t3ver_stage name street district city zip phone web email
3 1 2 0 0 0 0 0 -1 0 0 0 0 0 Schillerhaus Rudolstadt Schillerstraße 25 Rudolstadt 07407 + 49 3672 / 486470 http://schillerhaus.rudolstadt.de schillerhaus@rudolstadt.de
4 2 2 0 0 0 0 0 -1 0 0 0 0 0 Stadtbibliothek Rudolstadt Schulplatz 13 Rudolstadt 07407 0 36 72 - 48 64 20 http://www.stadtbibliothek-rudolstadt.de stadtbibliothek@rudolstadt.de
5 3 2 0 0 0 0 0 -1 0 0 0 0 0 Lutherkirche Caspar-Schulte-Straße Rudolstadt 07407 03672 - 48 96 13
6 4 3 0 0 0 0 0 -1 0 0 0 0 0 Schillerhaus Rudolstadt Schillerstraße 25 Rudolstadt 07407 + 49 3672 / 486470 http://schillerhaus.rudolstadt.de schillerhaus@rudolstadt.de
7 5 3 0 0 0 0 0 -1 0 0 0 0 0 Stadtbibliothek Rudolstadt Schulplatz 13 Rudolstadt 07407 0 36 72 - 48 64 20 http://www.stadtbibliothek-rudolstadt.de stadtbibliothek@rudolstadt.de
8 6 3 0 0 0 0 0 -1 0 0 0 0 0 Lutherkirche Caspar-Schulte-Straße Rudolstadt 07407 03672 - 48 96 13
9 tx_events_domain_model_event
10 uid pid cruser_id deleted hidden starttime endtime sys_language_uid l10n_parent t3ver_oid t3ver_wsid t3ver_state t3ver_stage title subtitle global_id slug highlight teaser details price_info name street district city zip country web phone ticket facebook youtube instagram latitude longitude images categories pages dates organizer partner region references_events
11 1 2 0 0 0 0 0 -1 0 0 0 0 0 Allerlei Weihnachtliches (Heute mit Johannes Geißer) e_100347853 e-100347853 0 Die Lichter sind entzündet, die Plätzchen duften, man rückt endlich wieder näher zusammen und lauscht den Geschichten. Vier Schauspieler*innen unseres Theaters überraschen mit ihren weihnachtlichen Texten, die sie für uns ausgewählt haben. Dazu plaudern sie über persönliche Anekdoten und erinnern sich an ihre schönsten und verrücktesten Weihnachtsfeste. Und da der Genuss in der Vorweihnachtszeit nicht fehlen darf, wird an jedem Adventssonntag eine andere weihnachtliche Spezialität serviert. Eintritt: 10 € (inkl. Gedeck mit weihnachtlicher Schillerlocke) Um Voranmeldung unter 03672-486470 oder schillerhaus@rudolstadt.de wird gebeten. Es gilt die 2G-PLUS-Regel. Schillerhaus Rudolstadt Schillerstraße 25 Rudolstadt 07407 Deutschland http://www.schillerhaus.rudolstadt.de/ + 49 3672 / 486470 50.720971023259 11.335229873657 1 1 1 1 1
12 2 2 0 0 0 0 0 -1 0 0 0 0 0 Tüftlerzeit e_100354481 e-100354481 0 Die Tüftlerzeit wird dieses Mal ein weihnachtliches Angebot bereithalten. Alle kleinen Tüftler dürfen gespannt sein. Voranmeldung über: kinderbibliothek@rudolstadt.de oder 03672-486420 Bitte beachten Sie die derzeit geltenden Zugangsregeln. Stadtbibliothek Rudolstadt Schulplatz 13 Rudolstadt 07407 Deutschland http://www.stadtbibliothek-rudolstadt.de/ 0 36 72 - 48 64 20 50.720835175056 11.342568397522 1 1 3 2 1
13 3 2 0 0 0 0 0 -1 0 0 0 0 0 Adventliche Orgelmusik (Orgel: KMD Frank Bettenhausen) e_100350503 e-100350503 0 Immer mittwochs in der Adventszeit spielt Frank Bettenhausen solo und zusammen mit anderen Musikern auf der Steinmeyerorgel aus dem Jahr 1906. Bekannte Adventslieder, barocke und romantische Kompositionen stehen neben besinnlichen Texten von Pfarrer Johannes-Martin Weiss. Es gilt die 2G-PLUS-Regel. Lutherkirche Caspar-Schulte-Straße Rudolstadt 07407 Deutschland 03672 - 48 96 13 50.718688721183 11.327333450317 1 2 4 3 1
14 4 3 0 0 0 0 0 -1 0 0 0 0 0 Allerlei Weihnachtliches (Heute mit Johannes Geißer) e_100347853 e-100347853 0 Die Lichter sind entzündet, die Plätzchen duften, man rückt endlich wieder näher zusammen und lauscht den Geschichten. Vier Schauspieler*innen unseres Theaters überraschen mit ihren weihnachtlichen Texten, die sie für uns ausgewählt haben. Dazu plaudern sie über persönliche Anekdoten und erinnern sich an ihre schönsten und verrücktesten Weihnachtsfeste. Und da der Genuss in der Vorweihnachtszeit nicht fehlen darf, wird an jedem Adventssonntag eine andere weihnachtliche Spezialität serviert. Eintritt: 10 € (inkl. Gedeck mit weihnachtlicher Schillerlocke) Um Voranmeldung unter 03672-486470 oder schillerhaus@rudolstadt.de wird gebeten. Es gilt die 2G-PLUS-Regel. Schillerhaus Rudolstadt Schillerstraße 25 Rudolstadt 07407 Deutschland http://www.schillerhaus.rudolstadt.de/ + 49 3672 / 486470 50.720971023259 11.335229873657 1 1 1 4 1
15 5 3 0 0 0 0 0 -1 0 0 0 0 0 Tüftlerzeit e_100354481 e-100354481 0 Die Tüftlerzeit wird dieses Mal ein weihnachtliches Angebot bereithalten. Alle kleinen Tüftler dürfen gespannt sein. Voranmeldung über: kinderbibliothek@rudolstadt.de oder 03672-486420 Bitte beachten Sie die derzeit geltenden Zugangsregeln. Stadtbibliothek Rudolstadt Schulplatz 13 Rudolstadt 07407 Deutschland http://www.stadtbibliothek-rudolstadt.de/ 0 36 72 - 48 64 20 50.720835175056 11.342568397522 1 1 3 5 1
16 6 3 0 0 0 0 0 -1 0 0 0 0 0 Adventliche Orgelmusik (Orgel: KMD Frank Bettenhausen) e_100350503 e-100350503 0 Immer mittwochs in der Adventszeit spielt Frank Bettenhausen solo und zusammen mit anderen Musikern auf der Steinmeyerorgel aus dem Jahr 1906. Bekannte Adventslieder, barocke und romantische Kompositionen stehen neben besinnlichen Texten von Pfarrer Johannes-Martin Weiss. Es gilt die 2G-PLUS-Regel. Lutherkirche Caspar-Schulte-Straße Rudolstadt 07407 Deutschland 03672 - 48 96 13 50.718688721183 11.327333450317 1 2 4 6 1
17 tx_events_domain_model_date
18 uid pid cruser_id hidden starttime endtime sys_language_uid l10n_parent t3ver_oid t3ver_wsid t3ver_state event start end canceled postponed_date canceled_link
19 1 2 0 0 0 0 -1 0 0 0 0 1 4101372000 4101377400 no 0
20 2 2 0 0 0 0 -1 0 0 0 0 2 4101112800 4101118200 no 0
21 3 2 0 0 0 0 -1 0 0 0 0 2 4072600800 4072608000 no 0
22 4 2 0 0 0 0 -1 0 0 0 0 2 4075020000 4075027200 no 0
23 5 2 0 0 0 0 -1 0 0 0 0 3 4099831200 4099834800 no 0
24 6 2 0 0 0 0 -1 0 0 0 0 3 4100436000 4100439600 no 0
25 7 2 0 0 0 0 -1 0 0 0 0 3 4101040800 4101044400 no 0
26 8 2 0 0 0 0 -1 0 0 0 0 3 4101645600 4101649200 no 0
27 9 3 0 0 0 0 -1 0 0 0 0 4 4101372000 4101377400 no 0
28 10 3 0 0 0 0 -1 0 0 0 0 5 4101112800 4101118200 no 0
29 11 3 0 0 0 0 -1 0 0 0 0 5 4072600800 4072608000 no 0
30 12 3 0 0 0 0 -1 0 0 0 0 5 4075020000 4075027200 no 0
31 13 3 0 0 0 0 -1 0 0 0 0 6 4099831200 4099834800 no 0
32 14 3 0 0 0 0 -1 0 0 0 0 6 4100436000 4100439600 no 0
33 15 3 0 0 0 0 -1 0 0 0 0 6 4101040800 4101044400 no 0
34 16 3 0 0 0 0 -1 0 0 0 0 6 4101645600 4101649200 no 0
35 sys_category
36 uid pid cruser_id hidden starttime endtime sys_language_uid l10n_parent title items parent
37 1 2 0 0 0 0 0 0 Top Category 0 0
38 2 2 0 0 0 0 0 0 Event Category Parent 0 1
39 3 2 0 0 0 0 0 0 Weihnachten 0 2
40 4 2 0 0 0 0 0 0 Kinder 0 2
41 5 2 0 0 0 0 0 0 Konzerte, Festivals, Show & Tanz 0 2
42 sys_category_record_mm
43 uid_local uid_foreign tablenames fieldname
44 3 1 tx_events_domain_model_event categories
45 4 2 tx_events_domain_model_event categories
46 5 3 tx_events_domain_model_event categories
47 3 3 tx_events_domain_model_event categories
48 3 4 tx_events_domain_model_event categories
49 4 5 tx_events_domain_model_event categories
50 5 6 tx_events_domain_model_event categories
51 3 6 tx_events_domain_model_event categories

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<tx_events_domain_model_import>
<uid>2</uid>
<pid>2</pid>
<title>Second Example import configuration</title>
<storage_pid>3</storage_pid>
<files_folder>1:/staedte/anderestadt/events/</files_folder>
<categories_pid>2</categories_pid>
<category_parent>2</category_parent>
<region>1</region>
<rest_experience>anderestadt</rest_experience>
<rest_search_query>name:"Beispiel2"</rest_search_query>
</tx_events_domain_model_import>
<pages>
<pid>1</pid>
<uid>3</uid>
<title>Storage</title>
<doktype>254</doktype>
</pages>
</dataset>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<tx_events_domain_model_import>
<uid>1</uid>
<pid>2</pid>
<title>Example import configuration</title>
<storage_pid>2</storage_pid>
<files_folder>1:/staedte/beispielstadt/events/</files_folder>
<categories_pid>2</categories_pid>
<category_parent>2</category_parent>
<region>1</region>
<rest_experience>beispielstadt</rest_experience>
<rest_search_query>name:"Beispiel"</rest_search_query>
</tx_events_domain_model_import>
</dataset>

View file

@ -16,7 +16,10 @@ class ImportCleansTransientFilesTest extends AbstractTest
*/
public function cleansTransientFiles(): void
{
$fileImportPath = 'staedte/beispielstadt/events/';
$fileImportPathConfiguration = 'staedte/beispielstadt/events/';
$fileImportPath = $this->getInstancePath() . '/fileadmin/' . $fileImportPathConfiguration;
GeneralUtility::mkdir_deep($fileImportPath);
$this->setUpConfiguration([
'restUrl = https://example.com/some-path/',
'license = example-license',
@ -38,7 +41,7 @@ class ImportCleansTransientFilesTest extends AbstractTest
$tester = $this->executeCommand([
'storage-pid' => '2',
'rest-experience' => 'beispielstadt',
'files-folder' => $fileImportPath,
'files-folder' => $fileImportPathConfiguration,
]);
self::assertSame(0, $tester->getStatusCode());
@ -49,7 +52,7 @@ class ImportCleansTransientFilesTest extends AbstractTest
self::assertSame('https://dam.destination.one/828118/f13bbf5602ffc406ebae2faa3527654dea84194666bce4925a1ca8bd3f50c5e9/tueftlerzeit-sfz-rudolstadt-jpg.jpg', (string)$requests[2]['request']->getUri());
self::assertSame('https://dam.destination.one/853436/109ac1cf87913e21b5e2b0ef0cc63d223a14374364952a855746a8e7c3fcfc36/lutherkirche-jpg.jpg', (string)$requests[3]['request']->getUri());
$importedFiles = GeneralUtility::getFilesInDir($this->getInstancePath() . '/fileadmin/' . $fileImportPath);
$importedFiles = GeneralUtility::getFilesInDir($fileImportPath);
self::assertIsArray($importedFiles, 'Failed to retrieve imported files from filesystem.');
self::assertSame(
[

View file

@ -16,7 +16,9 @@ class ImportDoesNotUseUploadsFolderTest extends AbstractTest
*/
public function doesNotUseUploadsFolder(): void
{
$fileImportPath = 'staedte/beispielstadt/events/';
$fileImportPathConfiguration = 'staedte/beispielstadt/events/';
$fileImportPath = $this->getInstancePath() . '/fileadmin/' . $fileImportPathConfiguration;
GeneralUtility::mkdir_deep($fileImportPath);
$this->setUpConfiguration([
'restUrl = https://example.com/some-path/',
@ -39,7 +41,7 @@ class ImportDoesNotUseUploadsFolderTest extends AbstractTest
$tester = $this->executeCommand([
'storage-pid' => '2',
'rest-experience' => 'beispielstadt',
'files-folder' => $fileImportPath,
'files-folder' => $fileImportPathConfiguration,
]);
self::assertSame(0, $tester->getStatusCode());
@ -49,7 +51,7 @@ class ImportDoesNotUseUploadsFolderTest extends AbstractTest
self::assertSame('https://dam.destination.one/828118/f13bbf5602ffc406ebae2faa3527654dea84194666bce4925a1ca8bd3f50c5e9/tueftlerzeit-sfz-rudolstadt-jpg.jpg', (string)$requests[2]['request']->getUri());
self::assertSame('https://dam.destination.one/853436/109ac1cf87913e21b5e2b0ef0cc63d223a14374364952a855746a8e7c3fcfc36/lutherkirche-jpg.jpg', (string)$requests[3]['request']->getUri());
$importedFiles = GeneralUtility::getFilesInDir($this->getInstancePath() . '/fileadmin/' . $fileImportPath);
$importedFiles = GeneralUtility::getFilesInDir($fileImportPath);
self::assertIsArray($importedFiles, 'Failed to retrieve imported files from filesystem.');
self::assertSame(
[

View file

@ -0,0 +1,109 @@
<?php
namespace Wrm\Events\Tests\Functional\Import\DestinationDataTest;
use GuzzleHttp\Psr7\Response;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use Wrm\Events\Command\ImportDestinationDataViaAllConfigruationsCommand;
/**
* @testdox Import of configuration
*/
class ImportsAllConfigurationTest extends AbstractTest
{
/**
* @test
*/
public function importsConfiguration(): void
{
$fileImportPathConfiguration1 = 'staedte/beispielstadt/events/';
$fileImportPath1 = $this->getInstancePath() . '/fileadmin/' . $fileImportPathConfiguration1;
GeneralUtility::mkdir_deep($fileImportPath1);
$fileImportPathConfiguration2 = 'staedte/anderestadt/events/';
$fileImportPath2 = $this->getInstancePath() . '/fileadmin/' . $fileImportPathConfiguration2;
GeneralUtility::mkdir_deep($fileImportPath2);
$this->importDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Fixtures/SingleRegion.xml');
$this->importDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Fixtures/SingleCategory.xml');
$this->importDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Fixtures/SingleImportConfiguration.xml');
$this->importDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Fixtures/SecondImportConfiguration.xml');
$this->setUpConfiguration([
'restUrl = https://example.com/some-path/',
'license = example-license',
'restType = Event',
'restTemplate = ET2014A.json',
'restLimit = 3',
'restMode = next_months,12',
]);
$requests = &$this->setUpResponses([
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/Response.json') ?: ''),
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ExampleImage.jpg') ?: ''),
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ExampleImage.jpg') ?: ''),
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ExampleImage.jpg') ?: ''),
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/Response.json') ?: ''),
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ExampleImage.jpg') ?: ''),
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ExampleImage.jpg') ?: ''),
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ExampleImage.jpg') ?: ''),
]);
$tester = $this->executeCommand([], ImportDestinationDataViaAllConfigruationsCommand::class);
self::assertSame(0, $tester->getStatusCode());
self::assertCount(8, $requests, 'Unexpected number of requests were made.');
self::assertSame('https://example.com/some-path/?experience=beispielstadt&licensekey=example-license&type=Event&mode=next_months%2C12&limit=3&template=ET2014A.json&q=name%3A%22Beispiel%22', (string)$requests[0]['request']->getUri());
self::assertSame('https://dam.destination.one/849917/279ac45b3fc701a7197131f627164fffd9f8cc77bc75165e2fc2b864ed606920/theater-rudolstadt_johannes-gei-er_photo-by-lisa-stern_web_-jpg.jpg', (string)$requests[1]['request']->getUri());
self::assertSame('https://dam.destination.one/828118/f13bbf5602ffc406ebae2faa3527654dea84194666bce4925a1ca8bd3f50c5e9/tueftlerzeit-sfz-rudolstadt-jpg.jpg', (string)$requests[2]['request']->getUri());
self::assertSame('https://dam.destination.one/853436/109ac1cf87913e21b5e2b0ef0cc63d223a14374364952a855746a8e7c3fcfc36/lutherkirche-jpg.jpg', (string)$requests[3]['request']->getUri());
self::assertSame('https://example.com/some-path/?experience=anderestadt&licensekey=example-license&type=Event&mode=next_months%2C12&limit=3&template=ET2014A.json&q=name%3A%22Beispiel2%22', (string)$requests[4]['request']->getUri());
self::assertSame('https://dam.destination.one/849917/279ac45b3fc701a7197131f627164fffd9f8cc77bc75165e2fc2b864ed606920/theater-rudolstadt_johannes-gei-er_photo-by-lisa-stern_web_-jpg.jpg', (string)$requests[5]['request']->getUri());
self::assertSame('https://dam.destination.one/828118/f13bbf5602ffc406ebae2faa3527654dea84194666bce4925a1ca8bd3f50c5e9/tueftlerzeit-sfz-rudolstadt-jpg.jpg', (string)$requests[6]['request']->getUri());
self::assertSame('https://dam.destination.one/853436/109ac1cf87913e21b5e2b0ef0cc63d223a14374364952a855746a8e7c3fcfc36/lutherkirche-jpg.jpg', (string)$requests[7]['request']->getUri());
self::assertCount(
0,
$this->getAllRecords('tx_events_domain_model_partner'),
'Added unexpected partners.'
);
self::assertCount(
1,
$this->getAllRecords('tx_events_domain_model_region'),
'Added or removed unexpected region.'
);
$this->assertCSVDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Assertions/ImportsAllConfigurationTest.csv');
$importedFiles = GeneralUtility::getFilesInDir($fileImportPath1);
self::assertIsArray($importedFiles, 'Failed to retrieve imported files from filesystem.');
self::assertSame(
[
'lutherkirche-jpg.jpg',
'theater-rudolstadt_johannes-gei-er_photo-by-lisa-stern_web_-jpg.jpg',
'tueftlerzeit-sfz-rudolstadt-jpg.jpg',
],
array_values($importedFiles),
'Got unexpected number of files'
);
$importedFiles = GeneralUtility::getFilesInDir($fileImportPath2);
self::assertIsArray($importedFiles, 'Failed to retrieve imported files from filesystem.');
self::assertSame(
[
'lutherkirche-jpg.jpg',
'theater-rudolstadt_johannes-gei-er_photo-by-lisa-stern_web_-jpg.jpg',
'tueftlerzeit-sfz-rudolstadt-jpg.jpg',
],
array_values($importedFiles),
'Got unexpected number of files'
);
self::assertFileEquals(
__DIR__ . '/Assertions/EmptyLogFile.txt',
$this->getInstancePath() . '/typo3temp/var/log/typo3_0493d91d8e.log',
'Logfile was not empty.'
);
}
}

View file

@ -15,7 +15,9 @@ class ImportsExampleAsExpectedTest extends AbstractTest
*/
public function importsExampleAsExpected(): void
{
$fileImportPath = 'staedte/beispielstadt/events/';
$fileImportPathConfiguration = 'staedte/beispielstadt/events/';
$fileImportPath = $this->getInstancePath() . '/fileadmin/' . $fileImportPathConfiguration;
GeneralUtility::mkdir_deep($fileImportPath);
$this->importDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Fixtures/SingleRegion.xml');
$this->importDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Fixtures/SingleCategory.xml');
@ -40,7 +42,7 @@ class ImportsExampleAsExpectedTest extends AbstractTest
$tester = $this->executeCommand([
'storage-pid' => '2',
'rest-experience' => 'beispielstadt',
'files-folder' => $fileImportPath,
'files-folder' => $fileImportPathConfiguration,
'region-uid' => '1',
]);
@ -64,7 +66,7 @@ class ImportsExampleAsExpectedTest extends AbstractTest
);
$this->assertCSVDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Assertions/ImportsExampleAsExpected.csv');
$importedFiles = GeneralUtility::getFilesInDir($this->getInstancePath() . '/fileadmin/' . $fileImportPath);
$importedFiles = GeneralUtility::getFilesInDir($fileImportPath);
self::assertIsArray($importedFiles, 'Failed to retrieve imported files from filesystem.');
self::assertSame(
[

View file

@ -0,0 +1,84 @@
<?php
namespace Wrm\Events\Tests\Functional\Import\DestinationDataTest;
use GuzzleHttp\Psr7\Response;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use Wrm\Events\Command\ImportDestinationDataViaConfigruationCommand;
/**
* @testdox Import of configuration
*/
class ImportsSingleConfigurationTest extends AbstractTest
{
/**
* @test
*/
public function importsConfiguration(): void
{
$fileImportPathConfiguration = 'staedte/beispielstadt/events/';
$fileImportPath = $this->getInstancePath() . '/fileadmin/' . $fileImportPathConfiguration;
GeneralUtility::mkdir_deep($fileImportPath);
$this->importDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Fixtures/SingleRegion.xml');
$this->importDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Fixtures/SingleCategory.xml');
$this->importDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Fixtures/SingleImportConfiguration.xml');
$this->setUpConfiguration([
'restUrl = https://example.com/some-path/',
'license = example-license',
'restType = Event',
'restTemplate = ET2014A.json',
'restLimit = 3',
'restMode = next_months,12',
]);
$requests = &$this->setUpResponses([
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/Response.json') ?: ''),
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ExampleImage.jpg') ?: ''),
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ExampleImage.jpg') ?: ''),
new Response(200, [], file_get_contents(__DIR__ . '/Fixtures/ExampleImage.jpg') ?: ''),
]);
$tester = $this->executeCommand([
'configurationUid' => '1',
], ImportDestinationDataViaConfigruationCommand::class);
self::assertSame(0, $tester->getStatusCode());
self::assertCount(4, $requests, 'Unexpected number of requests were made.');
self::assertSame('https://example.com/some-path/?experience=beispielstadt&licensekey=example-license&type=Event&mode=next_months%2C12&limit=3&template=ET2014A.json&q=name%3A%22Beispiel%22', (string)$requests[0]['request']->getUri());
self::assertSame('https://dam.destination.one/849917/279ac45b3fc701a7197131f627164fffd9f8cc77bc75165e2fc2b864ed606920/theater-rudolstadt_johannes-gei-er_photo-by-lisa-stern_web_-jpg.jpg', (string)$requests[1]['request']->getUri());
self::assertSame('https://dam.destination.one/828118/f13bbf5602ffc406ebae2faa3527654dea84194666bce4925a1ca8bd3f50c5e9/tueftlerzeit-sfz-rudolstadt-jpg.jpg', (string)$requests[2]['request']->getUri());
self::assertSame('https://dam.destination.one/853436/109ac1cf87913e21b5e2b0ef0cc63d223a14374364952a855746a8e7c3fcfc36/lutherkirche-jpg.jpg', (string)$requests[3]['request']->getUri());
self::assertCount(
0,
$this->getAllRecords('tx_events_domain_model_partner'),
'Added unexpected partners.'
);
self::assertCount(
1,
$this->getAllRecords('tx_events_domain_model_region'),
'Added or removed unexpected region.'
);
$this->assertCSVDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Assertions/ImportsExampleAsExpected.csv');
$importedFiles = GeneralUtility::getFilesInDir($fileImportPath);
self::assertIsArray($importedFiles, 'Failed to retrieve imported files from filesystem.');
self::assertSame(
[
'lutherkirche-jpg.jpg',
'theater-rudolstadt_johannes-gei-er_photo-by-lisa-stern_web_-jpg.jpg',
'tueftlerzeit-sfz-rudolstadt-jpg.jpg',
],
array_values($importedFiles),
'Got unexpected number of files'
);
self::assertFileEquals(
__DIR__ . '/Assertions/EmptyLogFile.txt',
$this->getInstancePath() . '/typo3temp/var/log/typo3_0493d91d8e.log',
'Logfile was not empty.'
);
}
}

View file

@ -15,7 +15,9 @@ class ImportsWithoutCategoryIfNotProvidedTest extends AbstractTest
*/
public function importsWithoutCategoryIfNotProvided(): void
{
$fileImportPath = 'staedte/beispielstadt/events/';
$fileImportPathConfiguration = 'staedte/beispielstadt/events/';
$fileImportPath = $this->getInstancePath() . '/fileadmin/' . $fileImportPathConfiguration;
GeneralUtility::mkdir_deep($fileImportPath);
$this->importDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Fixtures/SingleRegion.xml');
$this->setUpConfiguration([
@ -39,7 +41,7 @@ class ImportsWithoutCategoryIfNotProvidedTest extends AbstractTest
$tester = $this->executeCommand([
'storage-pid' => '2',
'rest-experience' => 'beispielstadt',
'files-folder' => $fileImportPath,
'files-folder' => $fileImportPathConfiguration,
'region-uid' => '1',
]);
@ -69,7 +71,7 @@ class ImportsWithoutCategoryIfNotProvidedTest extends AbstractTest
$this->assertCSVDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Assertions/ImportsWithoutCategoryIfNotProvided.csv');
$importedFiles = GeneralUtility::getFilesInDir($this->getInstancePath() . '/fileadmin/' . $fileImportPath);
$importedFiles = GeneralUtility::getFilesInDir($fileImportPath);
self::assertIsArray($importedFiles, 'Failed to retrieve imported files from filesystem.');
self::assertSame(
[

View file

@ -15,7 +15,10 @@ class ImportsWithoutRegionIfNotProvidedTest extends AbstractTest
*/
public function importsWithoutRegionIfNotProvided(): void
{
$fileImportPath = 'staedte/beispielstadt/events/';
$fileImportPathConfiguration = 'staedte/beispielstadt/events/';
$fileImportPath = $this->getInstancePath() . '/fileadmin/' . $fileImportPathConfiguration;
GeneralUtility::mkdir_deep($fileImportPath);
$this->importDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Fixtures/SingleCategory.xml');
$this->setUpConfiguration([
'restUrl = https://example.com/some-path/',
@ -37,7 +40,7 @@ class ImportsWithoutRegionIfNotProvidedTest extends AbstractTest
$tester = $this->executeCommand([
'storage-pid' => '2',
'rest-experience' => 'beispielstadt',
'files-folder' => $fileImportPath,
'files-folder' => $fileImportPathConfiguration,
'region-uid' => '',
]);
@ -62,7 +65,7 @@ class ImportsWithoutRegionIfNotProvidedTest extends AbstractTest
$this->assertCSVDataSet('EXT:events/Tests/Functional/Import/DestinationDataTest/Assertions/ImportsWithoutRegionIfNotProvided.csv');
$importedFiles = GeneralUtility::getFilesInDir($this->getInstancePath() . '/fileadmin/' . $fileImportPath);
$importedFiles = GeneralUtility::getFilesInDir($fileImportPath);
self::assertIsArray($importedFiles, 'Failed to retrieve imported files from filesystem.');
self::assertSame(
[

View file

@ -1,126 +0,0 @@
<?php
namespace Wrm\Events\Tests\Unit\Domain\DestinationData;
use Wrm\Events\Domain\DestinationData\Import;
use PHPUnit\Framework\TestCase;
/**
* @covers \Wrm\Events\Domain\DestinationData\Import
*/
class ImportTest extends TestCase
{
/**
* @test
*/
public function canBeCreated(): void
{
$subject = new Import(
'',
0,
null,
'',
''
);
self::assertInstanceOf(
Import::class,
$subject
);
}
/**
* @test
*/
public function returnsRestExperience(): void
{
$subject = new Import(
'experience',
0,
null,
'',
''
);
self::assertSame(
'experience',
$subject->getRestExperience()
);
}
/**
* @test
*/
public function returnsStoragePid(): void
{
$subject = new Import(
'',
20,
null,
'',
''
);
self::assertSame(
20,
$subject->getStoragePid()
);
}
/**
* @test
*/
public function returnsRegionUid(): void
{
$subject = new Import(
'',
0,
30,
'',
''
);
self::assertSame(
30,
$subject->getRegionUid()
);
}
/**
* @test
*/
public function returnsFilesFolder(): void
{
$subject = new Import(
'',
0,
null,
'test/folder',
''
);
self::assertSame(
'test/folder',
$subject->getFilesFolder()
);
}
/**
* @test
*/
public function returnsSearchQuery(): void
{
$subject = new Import(
'',
0,
null,
'test/folder',
'name:"Test"'
);
self::assertSame(
'name:"Test"',
$subject->getSearchQuery()
);
}
}

View file

@ -0,0 +1,183 @@
<?php
namespace Wrm\Events\Tests\Unit\Domain\Model;
use TYPO3\CMS\Core\Resource\Folder;
use Wrm\Events\Domain\Model\Category;
use Wrm\Events\Domain\Model\Import;
use PHPUnit\Framework\TestCase;
use Wrm\Events\Domain\Model\Region;
use Wrm\Events\Tests\ProphecyTrait;
/**
* @covers \Wrm\Events\Domain\Model\Import
*/
class ImportTest extends TestCase
{
use ProphecyTrait;
/**
* @test
*/
public function canBeCreated(): void
{
$folder = $this->prophesize(Folder::class);
$subject = new Import(
$folder->reveal(),
0,
''
);
self::assertInstanceOf(
Import::class,
$subject
);
}
/**
* @test
*/
public function returnsRestExperience(): void
{
$folder = $this->prophesize(Folder::class);
$subject = new Import(
$folder->reveal(),
0,
'experience'
);
self::assertSame(
'experience',
$subject->getRestExperience()
);
}
/**
* @test
*/
public function returnsStoragePid(): void
{
$folder = $this->prophesize(Folder::class);
$subject = new Import(
$folder->reveal(),
20,
''
);
self::assertSame(
20,
$subject->getStoragePid()
);
}
/**
* @test
*/
public function returnsRegion(): void
{
$folder = $this->prophesize(Folder::class);
$region = $this->prophesize(Region::class);
$subject = new Import(
$folder->reveal(),
0,
'',
'',
0,
null,
$region->reveal()
);
self::assertSame(
$region->reveal(),
$subject->getRegion()
);
}
/**
* @test
*/
public function returnsFilesFolder(): void
{
$folder = $this->prophesize(Folder::class);
$subject = new Import(
$folder->reveal(),
0,
''
);
self::assertSame(
$folder->reveal(),
$subject->getFilesFolder()
);
}
/**
* @test
*/
public function returnsCategoriesPid(): void
{
$folder = $this->prophesize(Folder::class);
$subject = new Import(
$folder->reveal(),
0,
'',
'',
10
);
self::assertSame(
10,
$subject->getCategoriesPid()
);
}
/**
* @test
*/
public function returnsCategoryParent(): void
{
$category = $this->prophesize(Category::class);
$folder = $this->prophesize(Folder::class);
$subject = new Import(
$folder->reveal(),
0,
'',
'',
0,
$category->reveal()
);
self::assertSame(
$category->reveal(),
$subject->getCategoryParent()
);
}
/**
* @test
*/
public function returnsSearchQuery(): void
{
$folder = $this->prophesize(Folder::class);
$subject = new Import(
$folder->reveal(),
0,
'',
'name:"Test"'
);
self::assertSame(
'name:"Test"',
$subject->getSearchQuery()
);
}
}

View file

@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use Wrm\Events\Domain\DestinationData\Import;
use Wrm\Events\Domain\Model\Import;
use Wrm\Events\Service\DestinationDataImportService\UrlFactory;
use Wrm\Events\Tests\ProphecyTrait;

View file

@ -19,7 +19,8 @@
"typo3/cms-core": "^10.4 || ^11.5",
"typo3/cms-extbase": "^10.4 || ^11.5",
"typo3/cms-fluid": "^10.4 || ^11.5",
"typo3/cms-frontend": "^10.4 || ^11.5"
"typo3/cms-frontend": "^10.4 || ^11.5",
"typo3/cms-filelist": "^10.4 || ^11.5"
},
"autoload": {
"psr-4": {

View file

@ -96,3 +96,18 @@ CREATE TABLE tx_events_domain_model_date (
canceled_link varchar(1024) DEFAULT '' NOT NULL,
);
CREATE TABLE tx_events_domain_model_import (
title varchar(1024) DEFAULT '' NOT NULL,
storage_pid int(11) unsigned DEFAULT '0' NOT NULL,
files_folder varchar(1024) DEFAULT '' NOT NULL,
categories_pid int(11) unsigned DEFAULT '0' NOT NULL,
category_parent int(11) unsigned DEFAULT '0' NOT NULL,
region int(11) unsigned DEFAULT '0' NOT NULL,
rest_experience varchar(1024) DEFAULT '' NOT NULL,
rest_search_query varchar(1024) DEFAULT '' NOT NULL,
);

View file

@ -1,19 +1,14 @@
parameters:
ignoreErrors:
-
message: "#^Parameter \\#1 \\$restExperience of class Wrm\\\\Events\\\\Domain\\\\DestinationData\\\\Import constructor expects string, mixed given\\.$#"
message: "#^Parameter \\#2 \\$array of function array_map expects array, mixed given\\.$#"
count: 1
path: Classes/Command/DestinationDataImportCommand.php
path: Classes/Domain/DestinationData/ImportFactory.php
-
message: "#^Parameter \\#2 \\$storagePid of class Wrm\\\\Events\\\\Domain\\\\DestinationData\\\\Import constructor expects int, mixed given\\.$#"
message: "#^Parameter \\#1 \\$min \\(999\\) of function random_int expects lower number than parameter \\#2 \\$max \\(int\\<1, max\\>\\)\\.$#"
count: 1
path: Classes/Command/DestinationDataImportCommand.php
-
message: "#^Parameter \\#4 \\$filesFolder of class Wrm\\\\Events\\\\Domain\\\\DestinationData\\\\Import constructor expects string, mixed given\\.$#"
count: 1
path: Classes/Command/DestinationDataImportCommand.php
path: Classes/Domain/DestinationData/LegacyImportFactory.php
-
message: "#^Call to method deleteFile\\(\\) on an unknown class TYPO3\\\\CMS\\\\Core\\\\Resource\\\\Storage\\.$#"