mirror of
https://github.com/werkraum-media/thuecat.git
synced 2024-12-05 03:26:13 +01:00
Add command to allow import of a single configuration.
The command is also available as scheduler task. This finally allows to regularly execute imports. This also allows to import from CLI context with differently configured timeouts.
This commit is contained in:
parent
cc072f0683
commit
773098623e
7 changed files with 339 additions and 55 deletions
92
Classes/Command/ImportConfigurationCommand.php
Normal file
92
Classes/Command/ImportConfigurationCommand.php
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WerkraumMedia\ThueCat\Command;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
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 WerkraumMedia\ThueCat\Domain\Import\Importer;
|
||||||
|
use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportConfigurationRepository;
|
||||||
|
|
||||||
|
class ImportConfigurationCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ImportConfigurationRepository
|
||||||
|
*/
|
||||||
|
private $importConfigurationRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Importer
|
||||||
|
*/
|
||||||
|
private $importer;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
ImportConfigurationRepository $importConfigurationRepository,
|
||||||
|
Importer $importer
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->importConfigurationRepository = $importConfigurationRepository;
|
||||||
|
$this->importer = $importer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function configure(): void
|
||||||
|
{
|
||||||
|
$this->setDescription('Executes a single import based on the given configuration.');
|
||||||
|
|
||||||
|
$this->addArgument(
|
||||||
|
'configuration',
|
||||||
|
InputArgument::REQUIRED,
|
||||||
|
'The UID of the import configuration to use'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
Bootstrap::initializeBackendAuthentication();
|
||||||
|
|
||||||
|
$configurationUid = $input->getArgument('configuration');
|
||||||
|
if (is_numeric($configurationUid)) {
|
||||||
|
$configurationUid = (int)$configurationUid;
|
||||||
|
} else {
|
||||||
|
throw new Exception('No numeric uid for configuration provided.', 1643267138);
|
||||||
|
}
|
||||||
|
|
||||||
|
$configuration = $this->importConfigurationRepository->findOneByUid($configurationUid);
|
||||||
|
if ($configuration === null) {
|
||||||
|
throw new Exception('No configuration found for uid: ' . $configurationUid, 1693228522);
|
||||||
|
}
|
||||||
|
|
||||||
|
$importLog = $this->importer->importConfiguration($configuration);
|
||||||
|
|
||||||
|
if ($importLog->hasErrors()) {
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ namespace WerkraumMedia\ThueCat\Domain\Repository\Backend;
|
||||||
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
|
||||||
use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
|
use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings;
|
||||||
use TYPO3\CMS\Extbase\Persistence\Repository;
|
use TYPO3\CMS\Extbase\Persistence\Repository;
|
||||||
|
use WerkraumMedia\ThueCat\Domain\Import\ImportConfiguration;
|
||||||
|
|
||||||
class ImportConfigurationRepository extends Repository
|
class ImportConfigurationRepository extends Repository
|
||||||
{
|
{
|
||||||
|
@ -39,4 +40,16 @@ class ImportConfigurationRepository extends Repository
|
||||||
|
|
||||||
$this->setDefaultQuerySettings($querySettings);
|
$this->setDefaultQuerySettings($querySettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ImportConfiguration|null
|
||||||
|
*/
|
||||||
|
public function findOneByUid(int $uid)
|
||||||
|
{
|
||||||
|
$query = $this->createQuery();
|
||||||
|
|
||||||
|
$query->matching($query->equals('uid', $uid));
|
||||||
|
|
||||||
|
return $query->execute()->getFirst();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,11 @@ services:
|
||||||
WerkraumMedia\ThueCat\:
|
WerkraumMedia\ThueCat\:
|
||||||
resource: '../Classes/*'
|
resource: '../Classes/*'
|
||||||
|
|
||||||
|
WerkraumMedia\ThueCat\Command\ImportConfigurationCommand:
|
||||||
|
tags:
|
||||||
|
- name: 'console.command'
|
||||||
|
command: 'thuecat:importviaconfiguration'
|
||||||
|
|
||||||
WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData:
|
WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData:
|
||||||
arguments:
|
arguments:
|
||||||
$requestFactory: '@WerkraumMedia\ThueCat\Domain\Import\RequestFactory'
|
$requestFactory: '@WerkraumMedia\ThueCat\Domain\Import\RequestFactory'
|
||||||
|
|
31
Documentation/Changelog/2.1.0.rst
Normal file
31
Documentation/Changelog/2.1.0.rst
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
2.1.0
|
||||||
|
=====
|
||||||
|
|
||||||
|
Breaking
|
||||||
|
--------
|
||||||
|
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
* Add command to allow import of a single configuration.
|
||||||
|
The command is also available as scheduler task.
|
||||||
|
This finally allows to regularly execute imports.
|
||||||
|
This also allows to import from CLI context with differently configured timeouts.
|
||||||
|
|
||||||
|
Fixes
|
||||||
|
-----
|
||||||
|
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
Tasks
|
||||||
|
-----
|
||||||
|
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
Deprecation
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Nothing
|
||||||
|
|
92
Tests/Functional/AbstractImportTest.php
Normal file
92
Tests/Functional/AbstractImportTest.php
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WerkraumMedia\ThueCat\Tests\Functional;
|
||||||
|
|
||||||
|
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||||
|
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
|
||||||
|
|
||||||
|
abstract class AbstractImportTest extends FunctionalTestCase
|
||||||
|
{
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
$this->coreExtensionsToLoad = array_merge($this->coreExtensionsToLoad, [
|
||||||
|
'core',
|
||||||
|
'backend',
|
||||||
|
'extbase',
|
||||||
|
'frontend',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->testExtensionsToLoad = array_merge($this->testExtensionsToLoad, [
|
||||||
|
'typo3conf/ext/thuecat/',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->pathsToLinkInTestInstance = array_merge($this->pathsToLinkInTestInstance, [
|
||||||
|
'typo3conf/ext/thuecat/Tests/Functional/Fixtures/Import/Sites/' => 'typo3conf/sites',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->configurationToUseInTestInstance = array_merge($this->configurationToUseInTestInstance, [
|
||||||
|
'LOG' => [
|
||||||
|
'WerkraumMedia' => [
|
||||||
|
'writerConfiguration' => [
|
||||||
|
\TYPO3\CMS\Core\Log\LogLevel::DEBUG => [
|
||||||
|
\TYPO3\CMS\Core\Log\Writer\FileWriter::class => [
|
||||||
|
'logFileInfix' => 'debug',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'EXTENSIONS' => [
|
||||||
|
'thuecat' => [
|
||||||
|
'apiKey' => null,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
parent::setUp();
|
||||||
|
GuzzleClientFaker::registerClient();
|
||||||
|
|
||||||
|
$this->setUpBackendUserFromFixture(1);
|
||||||
|
|
||||||
|
$GLOBALS['LANG'] = $this->getContainer()->get(LanguageService::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function assertPostConditions(): void
|
||||||
|
{
|
||||||
|
$path = self::getInstancePath() . '/typo3temp/var/log/typo3_0493d91d8e.log';
|
||||||
|
$this->assertSame(
|
||||||
|
'',
|
||||||
|
file_get_contents($path),
|
||||||
|
'The TYPO3 log file contained content while expecting to be empty.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
unset($GLOBALS['LANG']);
|
||||||
|
GuzzleClientFaker::tearDown();
|
||||||
|
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
}
|
105
Tests/Functional/ImportConfigurationCommandTest.php
Normal file
105
Tests/Functional/ImportConfigurationCommandTest.php
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace WerkraumMedia\ThueCat\Tests\Functional;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Exception\RuntimeException;
|
||||||
|
use Symfony\Component\Console\Tester\CommandTester;
|
||||||
|
use WerkraumMedia\ThueCat\Command\ImportConfigurationCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \WerkraumMedia\ThueCat\Command\ImportConfigurationCommand
|
||||||
|
* @testdox The 'thuecat:importviaconfiguration' command
|
||||||
|
*/
|
||||||
|
final class ImportConfigurationCommandTest extends AbstractImportTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function canImport(): void
|
||||||
|
{
|
||||||
|
$subject = $this->getContainer()->get(ImportConfigurationCommand::class);
|
||||||
|
self::assertInstanceOf(Command::class, $subject);
|
||||||
|
|
||||||
|
$this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsFreshOrganization.xml');
|
||||||
|
GuzzleClientFaker::appendResponseFromFile(__DIR__ . '/Fixtures/Import/Guzzle/thuecat.org/resources/018132452787-ngbe.json');
|
||||||
|
|
||||||
|
$tester = new CommandTester($subject);
|
||||||
|
$tester->execute(['configuration' => 1], ['capture_stderr_separately' => true]);
|
||||||
|
|
||||||
|
$this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsFreshOrganization.csv');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function throwsExceptionOnNoneExistingConfiguration(): void
|
||||||
|
{
|
||||||
|
$subject = $this->getContainer()->get(ImportConfigurationCommand::class);
|
||||||
|
self::assertInstanceOf(Command::class, $subject);
|
||||||
|
|
||||||
|
$tester = new CommandTester($subject);
|
||||||
|
|
||||||
|
$this->expectException(Exception::class);
|
||||||
|
$this->expectExceptionMessage('No configuration found for uid: 1');
|
||||||
|
$this->expectExceptionCode(1693228522);
|
||||||
|
|
||||||
|
$tester->execute(['configuration' => 1], ['capture_stderr_separately' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function throwsExceptionOnMissingArgument(): void
|
||||||
|
{
|
||||||
|
$subject = $this->getContainer()->get(ImportConfigurationCommand::class);
|
||||||
|
self::assertInstanceOf(Command::class, $subject);
|
||||||
|
|
||||||
|
$tester = new CommandTester($subject);
|
||||||
|
|
||||||
|
$this->expectException(RuntimeException::class);
|
||||||
|
$this->expectExceptionMessage('Not enough arguments (missing: "configuration")');
|
||||||
|
$this->expectExceptionCode(0);
|
||||||
|
|
||||||
|
$tester->execute([], ['capture_stderr_separately' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function throwsExceptionOnNoneNumericConfigurationArgument(): void
|
||||||
|
{
|
||||||
|
$subject = $this->getContainer()->get(ImportConfigurationCommand::class);
|
||||||
|
self::assertInstanceOf(Command::class, $subject);
|
||||||
|
|
||||||
|
$tester = new CommandTester($subject);
|
||||||
|
|
||||||
|
$this->expectException(Exception::class);
|
||||||
|
$this->expectExceptionMessage('No numeric uid for configuration provided.');
|
||||||
|
$this->expectExceptionCode(1643267138);
|
||||||
|
|
||||||
|
$tester->execute(['configuration' => 'a'], ['capture_stderr_separately' => true]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,8 +23,6 @@ namespace WerkraumMedia\ThueCat\Tests\Functional;
|
||||||
* 02110-1301, USA.
|
* 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use TYPO3\CMS\Core\Localization\LanguageService;
|
|
||||||
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase;
|
|
||||||
use WerkraumMedia\ThueCat\Domain\Import\Importer;
|
use WerkraumMedia\ThueCat\Domain\Import\Importer;
|
||||||
use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportConfigurationRepository;
|
use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportConfigurationRepository;
|
||||||
|
|
||||||
|
@ -59,60 +57,8 @@ use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportConfigurationRepositor
|
||||||
*
|
*
|
||||||
* @testdox The import
|
* @testdox The import
|
||||||
*/
|
*/
|
||||||
class ImportTest extends TestCase
|
class ImportTest extends AbstractImportTest
|
||||||
{
|
{
|
||||||
protected $coreExtensionsToLoad = [
|
|
||||||
'core',
|
|
||||||
'backend',
|
|
||||||
'extbase',
|
|
||||||
'frontend',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $testExtensionsToLoad = [
|
|
||||||
'typo3conf/ext/thuecat/',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $pathsToLinkInTestInstance = [
|
|
||||||
'typo3conf/ext/thuecat/Tests/Functional/Fixtures/Import/Sites/' => 'typo3conf/sites',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $configurationToUseInTestInstance = [
|
|
||||||
'LOG' => [
|
|
||||||
'WerkraumMedia' => [
|
|
||||||
'writerConfiguration' => [
|
|
||||||
\TYPO3\CMS\Core\Log\LogLevel::DEBUG => [
|
|
||||||
\TYPO3\CMS\Core\Log\Writer\FileWriter::class => [
|
|
||||||
'logFileInfix' => 'debug',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'EXTENSIONS' => [
|
|
||||||
'thuecat' => [
|
|
||||||
'apiKey' => null,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
protected function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
GuzzleClientFaker::registerClient();
|
|
||||||
|
|
||||||
$this->setUpBackendUserFromFixture(1);
|
|
||||||
|
|
||||||
$GLOBALS['LANG'] = $this->getContainer()->get(LanguageService::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function tearDown(): void
|
|
||||||
{
|
|
||||||
unset($GLOBALS['LANG']);
|
|
||||||
GuzzleClientFaker::tearDown();
|
|
||||||
|
|
||||||
parent::tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue