mirror of
https://github.com/werkraum-media/thuecat.git
synced 2024-12-06 12:06:12 +01:00
Support sync scope
Add new configuration to support sync scope. This one requires the provided sync scope id and will always update all entries. Relates: #23
This commit is contained in:
parent
22932545d3
commit
197a3e4696
22 changed files with 927 additions and 27 deletions
|
@ -25,7 +25,10 @@ namespace WerkraumMedia\ThueCat\Domain\Import\Importer;
|
|||
|
||||
use Psr\Http\Client\ClientInterface;
|
||||
use Psr\Http\Message\RequestFactoryInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface as CacheFrontendInterface;
|
||||
use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData\InvalidResponseException;
|
||||
|
||||
class FetchData
|
||||
{
|
||||
|
@ -44,6 +47,16 @@ class FetchData
|
|||
*/
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $databaseUrlPrefix = 'https://cdb.thuecat.org';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $urlPrefix = 'https://thuecat.org';
|
||||
|
||||
public function __construct(
|
||||
RequestFactoryInterface $requestFactory,
|
||||
ClientInterface $httpClient,
|
||||
|
@ -54,6 +67,15 @@ class FetchData
|
|||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
public function updatedNodes(string $scopeId): array
|
||||
{
|
||||
return $this->jsonLDFromUrl(
|
||||
$this->databaseUrlPrefix
|
||||
. '/api/ext-sync/get-updated-nodes?syncScopeId='
|
||||
. urlencode($scopeId)
|
||||
);
|
||||
}
|
||||
|
||||
public function jsonLDFromUrl(string $url): array
|
||||
{
|
||||
$cacheIdentifier = sha1($url);
|
||||
|
@ -65,6 +87,8 @@ class FetchData
|
|||
$request = $this->requestFactory->createRequest('GET', $url);
|
||||
$response = $this->httpClient->sendRequest($request);
|
||||
|
||||
$this->handleInvalidResponse($response, $request);
|
||||
|
||||
$jsonLD = json_decode((string) $response->getBody(), true);
|
||||
if (is_array($jsonLD)) {
|
||||
$this->cache->set($cacheIdentifier, $jsonLD);
|
||||
|
@ -73,4 +97,35 @@ class FetchData
|
|||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getResourceEndpoint(): string
|
||||
{
|
||||
return $this->urlPrefix . '/resources/';
|
||||
}
|
||||
|
||||
private function handleInvalidResponse(
|
||||
ResponseInterface $response,
|
||||
RequestInterface $request
|
||||
): void {
|
||||
if ($response->getStatusCode() === 200) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($response->getStatusCode() === 401) {
|
||||
throw new InvalidResponseException(
|
||||
'Unauthorized API request, ensure apiKey is properly configured.',
|
||||
1622461709
|
||||
);
|
||||
}
|
||||
|
||||
if ($response->getStatusCode() === 404) {
|
||||
throw new InvalidResponseException(
|
||||
sprintf(
|
||||
'Not found, given resource could not be found: "%s".',
|
||||
$request->getUri()
|
||||
),
|
||||
1622461820
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
class InvalidResponseException extends \RuntimeException
|
||||
{
|
||||
}
|
|
@ -24,17 +24,41 @@ namespace WerkraumMedia\ThueCat\Domain\Import;
|
|||
*/
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException;
|
||||
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
|
||||
use TYPO3\CMS\Core\Http\RequestFactory as Typo3RequestFactory;
|
||||
use TYPO3\CMS\Core\Http\Uri;
|
||||
|
||||
class RequestFactory extends Typo3RequestFactory
|
||||
{
|
||||
/**
|
||||
* @var ExtensionConfiguration
|
||||
*/
|
||||
private $extensionConfiguration;
|
||||
|
||||
public function __construct(
|
||||
ExtensionConfiguration $extensionConfiguration
|
||||
) {
|
||||
$this->extensionConfiguration = $extensionConfiguration;
|
||||
}
|
||||
|
||||
public function createRequest(string $method, $uri): RequestInterface
|
||||
{
|
||||
$uri = new Uri((string) $uri);
|
||||
$uri = $uri->withQuery('?format=jsonld');
|
||||
|
||||
// TODO: Add api key from site
|
||||
$query = [];
|
||||
parse_str($uri->getQuery(), $query);
|
||||
$query = array_merge($query, [
|
||||
'format' => 'jsonld',
|
||||
]);
|
||||
|
||||
try {
|
||||
$query['api_key'] = $this->extensionConfiguration->get('thuecat', 'apiKey');
|
||||
} catch (ExtensionConfigurationExtensionNotConfiguredException $e) {
|
||||
// Nothing todo, not configured, don't add.
|
||||
}
|
||||
|
||||
$uri = $uri->withQuery(http_build_query($query));
|
||||
|
||||
return parent::createRequest($method, $uri);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ namespace WerkraumMedia\ThueCat\Domain\Import\UrlProvider;
|
|||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration;
|
||||
|
||||
class StaticUrlProvider implements UrlProvider
|
||||
|
@ -33,14 +32,6 @@ class StaticUrlProvider implements UrlProvider
|
|||
*/
|
||||
private $urls = [];
|
||||
|
||||
public function __construct(
|
||||
ImportConfiguration $configuration
|
||||
) {
|
||||
if ($configuration instanceof ImportConfiguration) {
|
||||
$this->urls = $configuration->getUrls();
|
||||
}
|
||||
}
|
||||
|
||||
public function canProvideForConfiguration(
|
||||
ImportConfiguration $configuration
|
||||
): bool {
|
||||
|
@ -50,7 +41,10 @@ class StaticUrlProvider implements UrlProvider
|
|||
public function createWithConfiguration(
|
||||
ImportConfiguration $configuration
|
||||
): UrlProvider {
|
||||
return GeneralUtility::makeInstance(self::class, $configuration);
|
||||
$instance = clone $this;
|
||||
$instance->urls = $configuration->getUrls();
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
public function getUrls(): array
|
||||
|
|
74
Classes/Domain/Import/UrlProvider/SyncScopeUrlProvider.php
Normal file
74
Classes/Domain/Import/UrlProvider/SyncScopeUrlProvider.php
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WerkraumMedia\ThueCat\Domain\Import\UrlProvider;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData;
|
||||
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration;
|
||||
|
||||
class SyncScopeUrlProvider implements UrlProvider
|
||||
{
|
||||
/**
|
||||
* @var FetchData
|
||||
*/
|
||||
private $fetchData;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $syncScopeId = '';
|
||||
|
||||
public function __construct(
|
||||
FetchData $fetchData
|
||||
) {
|
||||
$this->fetchData = $fetchData;
|
||||
}
|
||||
|
||||
public function canProvideForConfiguration(
|
||||
ImportConfiguration $configuration
|
||||
): bool {
|
||||
return $configuration->getType() === 'syncScope';
|
||||
}
|
||||
|
||||
public function createWithConfiguration(
|
||||
ImportConfiguration $configuration
|
||||
): UrlProvider {
|
||||
$instance = clone $this;
|
||||
$instance->syncScopeId = $configuration->getSyncScopeId();
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
public function getUrls(): array
|
||||
{
|
||||
$response = $this->fetchData->updatedNodes($this->syncScopeId);
|
||||
|
||||
$resourceIds = array_values($response['data']['createdOrUpdated'] ?? []);
|
||||
|
||||
$urls = array_map(function (string $id) {
|
||||
return $this->fetchData->getResourceEndpoint() . $id;
|
||||
}, $resourceIds);
|
||||
|
||||
return $urls;
|
||||
}
|
||||
}
|
|
@ -97,14 +97,46 @@ class ImportConfiguration extends AbstractEntity
|
|||
return ArrayUtility::getValueByPath($urlEntry, 'url/el/url/vDEF');
|
||||
}, $this->getEntries());
|
||||
|
||||
$entries = array_filter($entries);
|
||||
|
||||
return array_values($entries);
|
||||
}
|
||||
|
||||
public function getSyncScopeId(): string
|
||||
{
|
||||
if ($this->configuration === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$configurationAsArray = $this->getConfigurationAsArray();
|
||||
$arrayPath = 'data/sDEF/lDEF/syncScopeId/vDEF';
|
||||
|
||||
if (ArrayUtility::isValidPath($configurationAsArray, $arrayPath) === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return ArrayUtility::getValueByPath(
|
||||
$configurationAsArray,
|
||||
$arrayPath
|
||||
);
|
||||
}
|
||||
|
||||
private function getEntries(): array
|
||||
{
|
||||
$configurationAsArray = $this->getConfigurationAsArray();
|
||||
|
||||
if (ArrayUtility::isValidPath($configurationAsArray, 'data/sDEF/lDEF/urls/el') === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return ArrayUtility::getValueByPath(
|
||||
GeneralUtility::xml2array($this->configuration),
|
||||
$configurationAsArray,
|
||||
'data/sDEF/lDEF/urls/el'
|
||||
);
|
||||
}
|
||||
|
||||
private function getConfigurationAsArray(): array
|
||||
{
|
||||
return GeneralUtility::xml2array($this->configuration);
|
||||
}
|
||||
}
|
||||
|
|
35
Configuration/FlexForm/ImportConfiguration/SyncScope.xml
Normal file
35
Configuration/FlexForm/ImportConfiguration/SyncScope.xml
Normal file
|
@ -0,0 +1,35 @@
|
|||
<T3DataStructure>
|
||||
<meta>
|
||||
<langDisable>1</langDisable>
|
||||
</meta>
|
||||
<sheets>
|
||||
<sDEF>
|
||||
<ROOT>
|
||||
<TCEforms>
|
||||
<sheetTitle>LLL:EXT:thuecat/Resources/Private/Language/locallang_flexform.xlf:importConfiguration.syncScope.sheetTitle</sheetTitle>
|
||||
</TCEforms>
|
||||
<type>array</type>
|
||||
<el>
|
||||
<storagePid>
|
||||
<TCEforms>
|
||||
<label>LLL:EXT:thuecat/Resources/Private/Language/locallang_flexform.xlf:importConfiguration.syncScope.storagePid</label>
|
||||
<config>
|
||||
<type>input</type>
|
||||
<eval>int,required</eval>
|
||||
</config>
|
||||
</TCEforms>
|
||||
</storagePid>
|
||||
<syncScopeId>
|
||||
<TCEforms>
|
||||
<label>LLL:EXT:thuecat/Resources/Private/Language/locallang_flexform.xlf:importConfiguration.syncScope.syncScopeId</label>
|
||||
<config>
|
||||
<type>input</type>
|
||||
<eval>trim,required</eval>
|
||||
</config>
|
||||
</TCEforms>
|
||||
</syncScopeId>
|
||||
</el>
|
||||
</ROOT>
|
||||
</sDEF>
|
||||
</sheets>
|
||||
</T3DataStructure>
|
|
@ -10,6 +10,7 @@ return (static function (string $extensionKey, string $tableName) {
|
|||
'ctrl' => [
|
||||
'label' => 'title',
|
||||
'iconfile' => \WerkraumMedia\ThueCat\Extension::getIconPath() . $tableName . '.svg',
|
||||
'type' => 'type',
|
||||
'default_sortby' => 'title',
|
||||
'tstamp' => 'tstamp',
|
||||
'crdate' => 'crdate',
|
||||
|
@ -40,6 +41,10 @@ return (static function (string $extensionKey, string $tableName) {
|
|||
$languagePath . '.type.static',
|
||||
'static',
|
||||
],
|
||||
[
|
||||
$languagePath . '.type.syncScope',
|
||||
'syncScope',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
@ -51,6 +56,7 @@ return (static function (string $extensionKey, string $tableName) {
|
|||
'ds' => [
|
||||
'default' => $flexFormConfigurationPath . 'ImportConfiguration/Static.xml',
|
||||
'static' => $flexFormConfigurationPath . 'ImportConfiguration/Static.xml',
|
||||
'syncScope' => $flexFormConfigurationPath . 'ImportConfiguration/SyncScope.xml',
|
||||
],
|
||||
],
|
||||
],
|
||||
|
|
16
README.md
16
README.md
|
@ -1,6 +1,5 @@
|
|||
# ThüCAT integration into TYPO3 CMS
|
||||
|
||||
|
||||
ThüCAT is ¨Thüringer Content Architektur Tourismus¨.
|
||||
This is an extension for TYPO3 CMS (https://typo3.org/) to integrate ThüCAT.
|
||||
The existing API is integrated and allows importing data into the system.
|
||||
|
@ -9,8 +8,12 @@ The existing API is integrated and allows importing data into the system.
|
|||
|
||||
The extension already allows:
|
||||
|
||||
* Create static configuration to import specified resources,
|
||||
e.g. defined organisation or towns.
|
||||
* Create configuration to import:
|
||||
|
||||
* specified resources via static configuration,
|
||||
e.g. defined organisation or towns.
|
||||
|
||||
* sync scope, a syncScopeId to always update delivered resources.
|
||||
|
||||
* Support multiple languages
|
||||
|
||||
|
@ -47,3 +50,10 @@ The extension already allows:
|
|||
* Content element to display town, tourist information and organisation.
|
||||
|
||||
* Extending import to include further properties
|
||||
|
||||
## Installation
|
||||
|
||||
Please configure API Key via Extension Configuration.
|
||||
|
||||
Configuration records need to be created, e.g. by visiting the ThüCAT module.
|
||||
Those can then be imported via the same module.
|
||||
|
|
11
Resources/Private/Language/locallang_conf.xlf
Normal file
11
Resources/Private/Language/locallang_conf.xlf
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?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="2021-02-01T09:24:10Z" product-name="ThueCat TCA Labels">
|
||||
<header/>
|
||||
<body>
|
||||
<trans-unit id="apiKey" xml:space="preserve">
|
||||
<source>API-Key</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -3,6 +3,7 @@
|
|||
<file source-language="en" datatype="plaintext" original="messages" date="2021-02-01T09:24:10Z" product-name="ThueCat FlexForms Labels">
|
||||
<header/>
|
||||
<body>
|
||||
<!-- Static Import Configuration -->
|
||||
<trans-unit id="importConfiguration.static.sheetTitle" xml:space="preserve">
|
||||
<source>Static import configuration</source>
|
||||
</trans-unit>
|
||||
|
@ -16,6 +17,17 @@
|
|||
<source>URL</source>
|
||||
</trans-unit>
|
||||
|
||||
<!-- Sync Scope Import Configuration -->
|
||||
<trans-unit id="importConfiguration.syncScope.sheetTitle" xml:space="preserve">
|
||||
<source>Sync Scope import configuration</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importConfiguration.syncScope.storagePid" xml:space="preserve">
|
||||
<source>Storage Page UID</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="importConfiguration.syncScope.syncScopeId" xml:space="preserve">
|
||||
<source>syncScopeId</source>
|
||||
</trans-unit>
|
||||
|
||||
<trans-unit id="pages.tourist_attraction.sheetTitle" xml:space="preserve">
|
||||
<source>Tourist Attraction</source>
|
||||
</trans-unit>
|
||||
|
|
|
@ -130,6 +130,9 @@
|
|||
<trans-unit id="tx_thuecat_import_configuration.type.static" xml:space="preserve">
|
||||
<source>Static list of URLs</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="tx_thuecat_import_configuration.type.syncScope" xml:space="preserve">
|
||||
<source>Synchronization area</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="tx_thuecat_import_configuration.configuration" xml:space="preserve">
|
||||
<source>Configuration</source>
|
||||
</trans-unit>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
HTTP/1.1 200 OK
|
||||
Date: Mon, 31 May 2021 07:45:26 GMT
|
||||
Content-Type: application/json; charset=utf-8
|
||||
Content-Length: 34
|
||||
Connection: keep-alive
|
||||
access-control-allow-origin: https://cdb.thuecat.org
|
||||
content-security-policy: default-src 'self'; script-src 'self' 'sha256-xfTbtWk8kVI65iLJs8LB3lWf2g0g10DS71pDdoutFHc='; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com; img-src 'self' data: blob: *
|
||||
feature-policy: microphone 'none'; camera 'none'; payment 'none'
|
||||
referrer-policy: same-origin
|
||||
x-content-type-options: nosniff
|
||||
x-xss-protection: 1; mode=block
|
||||
x-frame-options: deny
|
||||
access-control-allow-credentials: true
|
||||
strict-transport-security: max-age=15724800; includeSubDomains
|
||||
access-control-allow-headers: Authorization, Content-Type
|
||||
access-control-allow-methods: HEAD, GET, POST, DELETE, OPTIONS
|
||||
set-cookie: ahSession=3d594be0a8f63b6e5aa0683d86c33f0014462fff;path=/;expires=Thu, 01 Jul 2021 07:45:26 GMT;httpOnly=true;
|
||||
|
||||
{"data":{"createdOrUpdated":["835224016581-dara","165868194223-zmqf","215230952334-yyno"],"removed":["319489049949-yzpe","440865870518-kcka","057564926026-ambc","502105041571-gtmz","956950809461-mkyx","505212346932-dgdj","304166137220-qegp","052993102595-yytg","008779699609-ettg","992865433390-jqcw","678174286034-dpza","473249269683-mxjj","r_20704386-oapoi","121412224073-roqx","067447662224-fhpb","103385129122-pypq","764328419582-bdhj","303605630412-cygb","891743863902-bkeb"]}}
|
|
@ -0,0 +1,19 @@
|
|||
HTTP/1.1 200 OK
|
||||
Date: Mon, 31 May 2021 07:45:26 GMT
|
||||
Content-Type: application/json; charset=utf-8
|
||||
Content-Length: 34
|
||||
Connection: keep-alive
|
||||
access-control-allow-origin: https://cdb.thuecat.org
|
||||
content-security-policy: default-src 'self'; script-src 'self' 'sha256-xfTbtWk8kVI65iLJs8LB3lWf2g0g10DS71pDdoutFHc='; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com; img-src 'self' data: blob: *
|
||||
feature-policy: microphone 'none'; camera 'none'; payment 'none'
|
||||
referrer-policy: same-origin
|
||||
x-content-type-options: nosniff
|
||||
x-xss-protection: 1; mode=block
|
||||
x-frame-options: deny
|
||||
access-control-allow-credentials: true
|
||||
strict-transport-security: max-age=15724800; includeSubDomains
|
||||
access-control-allow-headers: Authorization, Content-Type
|
||||
access-control-allow-methods: HEAD, GET, POST, DELETE, OPTIONS
|
||||
set-cookie: ahSession=3d594be0a8f63b6e5aa0683d86c33f0014462fff;path=/;expires=Thu, 01 Jul 2021 07:45:26 GMT;httpOnly=true;
|
||||
|
||||
{"data":{"createdOrUpdated":["835224016581-dara","165868194223-zmqf","215230952334-yyno"],"removed":["319489049949-yzpe","440865870518-kcka","057564926026-ambc","502105041571-gtmz","956950809461-mkyx","505212346932-dgdj","304166137220-qegp","052993102595-yytg","008779699609-ettg","992865433390-jqcw","678174286034-dpza","473249269683-mxjj","r_20704386-oapoi","121412224073-roqx","067447662224-fhpb","103385129122-pypq","764328419582-bdhj","303605630412-cygb","891743863902-bkeb"]}}
|
91
Tests/Functional/Fixtures/Import/ImportsSyncScope.xml
Normal file
91
Tests/Functional/Fixtures/Import/ImportsSyncScope.xml
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<dataset>
|
||||
<pages>
|
||||
<uid>1</uid>
|
||||
<pid>0</pid>
|
||||
<tstamp>1613400587</tstamp>
|
||||
<crdate>1613400558</crdate>
|
||||
<cruser_id>1</cruser_id>
|
||||
<doktype>4</doktype>
|
||||
<title>Rootpage</title>
|
||||
<is_siteroot>1</is_siteroot>
|
||||
</pages>
|
||||
<pages>
|
||||
<uid>10</uid>
|
||||
<pid>1</pid>
|
||||
<tstamp>1613400587</tstamp>
|
||||
<crdate>1613400558</crdate>
|
||||
<cruser_id>1</cruser_id>
|
||||
<doktype>254</doktype>
|
||||
<title>Storage folder</title>
|
||||
</pages>
|
||||
|
||||
<sys_language>
|
||||
<uid>1</uid>
|
||||
<pid>0</pid>
|
||||
<title>English</title>
|
||||
<flag>en-us-gb</flag>
|
||||
<language_isocode>en</language_isocode>
|
||||
</sys_language>
|
||||
|
||||
<sys_language>
|
||||
<uid>2</uid>
|
||||
<pid>0</pid>
|
||||
<title>French</title>
|
||||
<flag>fr</flag>
|
||||
<language_isocode>fr</language_isocode>
|
||||
</sys_language>
|
||||
|
||||
<tx_thuecat_import_configuration>
|
||||
<uid>1</uid>
|
||||
<pid>0</pid>
|
||||
<tstamp>1613400587</tstamp>
|
||||
<crdate>1613400558</crdate>
|
||||
<cruser_id>1</cruser_id>
|
||||
<disable>0</disable>
|
||||
<title>Sync Scope ID</title>
|
||||
<type>syncScope</type>
|
||||
<configuration><![CDATA[<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<T3FlexForms>
|
||||
<data>
|
||||
<sheet index="sDEF">
|
||||
<language index="lDEF">
|
||||
<field index="storagePid">
|
||||
<value index="vDEF">10</value>
|
||||
</field>
|
||||
<field index="syncScopeId">
|
||||
<value index="vDEF">dd4615dc-58a6-4648-a7ce-4950293a06db</value>
|
||||
</field>
|
||||
</language>
|
||||
</sheet>
|
||||
</data>
|
||||
</T3FlexForms>]]></configuration>
|
||||
</tx_thuecat_import_configuration>
|
||||
|
||||
<tx_thuecat_town>
|
||||
<uid>1</uid>
|
||||
<pid>10</pid>
|
||||
<tstamp>1613401129</tstamp>
|
||||
<crdate>1613401129</crdate>
|
||||
<cruser_id>1</cruser_id>
|
||||
<disable>0</disable>
|
||||
<remote_id>https://thuecat.org/resources/043064193523-jcyt</remote_id>
|
||||
<managed_by>1</managed_by>
|
||||
<tourist_information>0</tourist_information>
|
||||
<title>Erfurt</title>
|
||||
</tx_thuecat_town>
|
||||
|
||||
<tx_thuecat_organisation>
|
||||
<uid>1</uid>
|
||||
<pid>10</pid>
|
||||
<tstamp>1613400969</tstamp>
|
||||
<crdate>1613400969</crdate>
|
||||
<cruser_id>1</cruser_id>
|
||||
<disable>0</disable>
|
||||
<remote_id>https://thuecat.org/resources/018132452787-ngbe</remote_id>
|
||||
<title>Erfurt Tourismus und Marketing GmbH</title>
|
||||
<description>Die Erfurt Tourismus & Marketing GmbH (ETMG) wurde 1997 als offizielle Organisation zur Tourismusförderung in der Landeshauptstadt Erfurt gegründet und nahm am 01.0 1.1998 die Geschäftstätigkeit auf.</description>
|
||||
<manages_towns>0</manages_towns>
|
||||
<manages_tourist_information>0</manages_tourist_information>
|
||||
</tx_thuecat_organisation>
|
||||
</dataset>
|
10
Tests/Functional/Fixtures/Import/ImportsSyncScopeResult.csv
Normal file
10
Tests/Functional/Fixtures/Import/ImportsSyncScopeResult.csv
Normal file
|
@ -0,0 +1,10 @@
|
|||
tx_thuecat_tourist_attraction
|
||||
,"uid","pid","sys_language_uid","l18n_parent","l10n_source","l10n_state","remote_id","title","managed_by","town","address","offers"
|
||||
,1,10,0,0,0,\NULL,"https://thuecat.org/resources/835224016581-dara","Dom St. Marien",1,1,"{""street"":""Domstufen 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""dominformation@domberg-erfurt.de"",""phone"":""+49 361 6461265"",""fax"":"""",""geo"":{""latitude"":50.975955358589545,""longitude"":11.023667024961856}}","[]"
|
||||
,2,10,1,1,1,\NULL,"https://thuecat.org/resources/835224016581-dara","Cathedral of St. Mary",1,1,"{""street"":""Domstufen 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""dominformation@domberg-erfurt.de"",""phone"":""+49 361 6461265"",""fax"":"""",""geo"":{""latitude"":50.975955358589545,""longitude"":11.023667024961856}}","[]"
|
||||
,3,10,0,0,0,\NULL,"https://thuecat.org/resources/165868194223-zmqf","Alte Synagoge",1,1,"{""street"":""Waagegasse 8"",""zip"":""99084"",""city"":""Erfurt"",""email"":""altesynagoge@erfurt.de"",""phone"":""+49 361 6551520"",""fax"":""+49 361 6551669"",""geo"":{""latitude"":50.978765,""longitude"":11.029133}}","[{""title"":""F\u00fchrungen"",""description"":""Immer samstags, um 11:15 Uhr findet eine \u00f6ffentliche F\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten"",""prices"":[{""title"":""Erwachsene"",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":""Erm\u00e4\u00dfigt"",""description"":""als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""}]},{""title"":""Eintritt"",""description"":""Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\nAn jedem ersten Dienstag im Monat: Eintritt frei"",""prices"":[{""title"":""Erm\u00e4\u00dfigt"",""description"":""als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":""Familienkarte"",""description"":"""",""price"":17,""currency"":""EUR"",""rule"":""PerGroup""},{""title"":""ErfurtCard"",""description"":"""",""price"":14.9,""currency"":""EUR"",""rule"":""PerPackage""},{""title"":""Erwachsene"",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""}]}]"
|
||||
,4,10,1,3,3,\NULL,"https://thuecat.org/resources/165868194223-zmqf","Old Synagogue",1,1,"{""street"":""Waagegasse 8"",""zip"":""99084"",""city"":""Erfurt"",""email"":""altesynagoge@erfurt.de"",""phone"":""+49 361 6551520"",""fax"":""+49 361 6551669"",""geo"":{""latitude"":50.978765,""longitude"":11.029133}}","[{""title"":""F\u00fchrungen"",""description"":""Immer samstags, um 11:15 Uhr findet eine \u00f6ffentliche F\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten"",""prices"":[{""title"":""Erwachsene"",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":""Erm\u00e4\u00dfigt"",""description"":""als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""}]},{""title"":""Eintritt"",""description"":""Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\nAn jedem ersten Dienstag im Monat: Eintritt frei"",""prices"":[{""title"":""Erm\u00e4\u00dfigt"",""description"":""als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":""Familienkarte"",""description"":"""",""price"":17,""currency"":""EUR"",""rule"":""PerGroup""},{""title"":""ErfurtCard"",""description"":"""",""price"":14.9,""currency"":""EUR"",""rule"":""PerPackage""},{""title"":""Erwachsene"",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""}]}]"
|
||||
,5,10,2,3,3,\NULL,"https://thuecat.org/resources/165868194223-zmqf","La vieille synagogue",1,1,"{""street"":""Waagegasse 8"",""zip"":""99084"",""city"":""Erfurt"",""email"":""altesynagoge@erfurt.de"",""phone"":""+49 361 6551520"",""fax"":""+49 361 6551669"",""geo"":{""latitude"":50.978765,""longitude"":11.029133}}","[{""title"":""F\u00fchrungen"",""description"":""Immer samstags, um 11:15 Uhr findet eine \u00f6ffentliche F\u00fchrung durch das Museum statt. Dauer etwa 90 Minuten"",""prices"":[{""title"":""Erwachsene"",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":""Erm\u00e4\u00dfigt"",""description"":""als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""}]},{""title"":""Eintritt"",""description"":""Schulklassen und Kitagruppen im Rahmen des Unterrichts: Eintritt frei\nAn jedem ersten Dienstag im Monat: Eintritt frei"",""prices"":[{""title"":""Erm\u00e4\u00dfigt"",""description"":""als erm\u00e4\u00dfigt gelten schulpflichtige Kinder, Auszubildende, Studierende, Rentner\/-innen, Menschen mit Behinderungen, Inhaber Sozialausweis der Landeshauptstadt Erfurt"",""price"":5,""currency"":""EUR"",""rule"":""PerPerson""},{""title"":""Familienkarte"",""description"":"""",""price"":17,""currency"":""EUR"",""rule"":""PerGroup""},{""title"":""ErfurtCard"",""description"":"""",""price"":14.9,""currency"":""EUR"",""rule"":""PerPackage""},{""title"":""Erwachsene"",""description"":"""",""price"":8,""currency"":""EUR"",""rule"":""PerPerson""}]}]"
|
||||
,6,10,0,0,0,\NULL,"https://thuecat.org/resources/215230952334-yyno","Krämerbrücke",1,1,"{""street"":""Benediktsplatz 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""service@erfurt-tourismus.de"",""phone"":""+49 361 66 400"",""fax"":"""",""geo"":{""latitude"":50.978772,""longitude"":11.031622}}","[]"
|
||||
,7,10,1,6,6,\NULL,"https://thuecat.org/resources/215230952334-yyno","Merchants' Bridge",1,1,"{""street"":""Benediktsplatz 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""service@erfurt-tourismus.de"",""phone"":""+49 361 66 400"",""fax"":"""",""geo"":{""latitude"":50.978772,""longitude"":11.031622}}","[]"
|
||||
,8,10,2,6,6,\NULL,"https://thuecat.org/resources/215230952334-yyno","Pont de l'épicier",1,1,"{""street"":""Benediktsplatz 1"",""zip"":""99084"",""city"":""Erfurt"",""email"":""service@erfurt-tourismus.de"",""phone"":""+49 361 66 400"",""fax"":"""",""geo"":{""latitude"":50.978772,""longitude"":11.031622}}","[]"
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
@ -91,6 +91,14 @@ class ImportTest extends TestCase
|
|||
'typo3conf/ext/thuecat/Tests/Functional/Fixtures/Import/Sites/' => 'typo3conf/sites',
|
||||
];
|
||||
|
||||
protected $configurationToUseInTestInstance = [
|
||||
'EXTENSIONS' => [
|
||||
'thuecat' => [
|
||||
'apiKey' => null,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
@ -212,6 +220,24 @@ class ImportTest extends TestCase
|
|||
$this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsTouristAttractionsWithRelationsResult.csv');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function importsBasedOnSyncScope(): void
|
||||
{
|
||||
$this->importDataSet(__DIR__ . '/Fixtures/Import/ImportsSyncScope.xml');
|
||||
|
||||
$serverRequest = $this->getServerRequest();
|
||||
|
||||
$extbaseBootstrap = $this->getContainer()->get(Bootstrap::class);
|
||||
$extbaseBootstrap->handleBackendRequest($serverRequest->reveal());
|
||||
|
||||
$touristAttractions = $this->getAllRecords('tx_thuecat_tourist_attraction');
|
||||
self::assertCount(8, $touristAttractions);
|
||||
|
||||
$this->assertCSVDataSet('EXT:thuecat/Tests/Functional/Fixtures/Import/ImportsSyncScopeResult.csv');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ObjectProphecy<ServerRequestInterface>
|
||||
*/
|
||||
|
|
|
@ -31,6 +31,7 @@ use Psr\Http\Message\RequestInterface;
|
|||
use Psr\Http\Message\ResponseInterface;
|
||||
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
|
||||
use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData;
|
||||
use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData\InvalidResponseException;
|
||||
|
||||
/**
|
||||
* @covers WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData
|
||||
|
@ -75,6 +76,7 @@ class FetchDataTest extends TestCase
|
|||
$httpClient->sendRequest($request->reveal())
|
||||
->willReturn($response->reveal());
|
||||
|
||||
$response->getStatusCode()->willReturn(200);
|
||||
$response->getBody()->willReturn('{"@graph":[{"@id":"https://example.com/resources/018132452787-ngbe"}]}');
|
||||
|
||||
$subject = new FetchData(
|
||||
|
@ -111,6 +113,7 @@ class FetchDataTest extends TestCase
|
|||
$httpClient->sendRequest($request->reveal())
|
||||
->willReturn($response->reveal());
|
||||
|
||||
$response->getStatusCode()->willReturn(200);
|
||||
$response->getBody()->willReturn('');
|
||||
|
||||
$subject = new FetchData(
|
||||
|
@ -155,4 +158,74 @@ class FetchDataTest extends TestCase
|
|||
],
|
||||
], $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function throwsExceptionOn404(): void
|
||||
{
|
||||
$requestFactory = $this->prophesize(RequestFactoryInterface::class);
|
||||
$httpClient = $this->prophesize(ClientInterface::class);
|
||||
$cache = $this->prophesize(FrontendInterface::class);
|
||||
|
||||
$request = $this->prophesize(RequestInterface::class);
|
||||
$response = $this->prophesize(ResponseInterface::class);
|
||||
|
||||
$request->getUri()->willReturn('https://example.com/resources/018132452787-ngbe');
|
||||
|
||||
$requestFactory->createRequest('GET', 'https://example.com/resources/018132452787-ngbe')
|
||||
->willReturn($request->reveal());
|
||||
|
||||
$httpClient->sendRequest($request->reveal())
|
||||
->willReturn($response->reveal());
|
||||
|
||||
|
||||
$response->getStatusCode()->willReturn(404);
|
||||
$response->getBody()->willReturn('{"error":"404"}');
|
||||
|
||||
$subject = new FetchData(
|
||||
$requestFactory->reveal(),
|
||||
$httpClient->reveal(),
|
||||
$cache->reveal()
|
||||
);
|
||||
|
||||
$this->expectException(InvalidResponseException::class);
|
||||
$this->expectExceptionCode(1622461820);
|
||||
$this->expectExceptionMessage('Not found, given resource could not be found: "https://example.com/resources/018132452787-ngbe".');
|
||||
|
||||
$subject->jsonLDFromUrl('https://example.com/resources/018132452787-ngbe');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function throwsExceptionOn401(): void
|
||||
{
|
||||
$requestFactory = $this->prophesize(RequestFactoryInterface::class);
|
||||
$httpClient = $this->prophesize(ClientInterface::class);
|
||||
$cache = $this->prophesize(FrontendInterface::class);
|
||||
|
||||
$request = $this->prophesize(RequestInterface::class);
|
||||
$response = $this->prophesize(ResponseInterface::class);
|
||||
|
||||
$requestFactory->createRequest('GET', 'https://example.com/resources/018132452787-ngbe')
|
||||
->willReturn($request->reveal());
|
||||
|
||||
$httpClient->sendRequest($request->reveal())
|
||||
->willReturn($response->reveal());
|
||||
|
||||
$response->getStatusCode()->willReturn(401);
|
||||
|
||||
$subject = new FetchData(
|
||||
$requestFactory->reveal(),
|
||||
$httpClient->reveal(),
|
||||
$cache->reveal()
|
||||
);
|
||||
|
||||
$this->expectException(InvalidResponseException::class);
|
||||
$this->expectExceptionCode(1622461709);
|
||||
$this->expectExceptionMessage('Unauthorized API request, ensure apiKey is properly configured.');
|
||||
|
||||
$subject->jsonLDFromUrl('https://example.com/resources/018132452787-ngbe');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@ namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Import;
|
|||
*/
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationExtensionNotConfiguredException;
|
||||
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
|
||||
use WerkraumMedia\ThueCat\Domain\Import\RequestFactory;
|
||||
|
||||
/**
|
||||
|
@ -31,12 +34,18 @@ use WerkraumMedia\ThueCat\Domain\Import\RequestFactory;
|
|||
*/
|
||||
class RequestFactoryTest extends TestCase
|
||||
{
|
||||
use ProphecyTrait;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function canBeCreated(): void
|
||||
{
|
||||
$subject = new RequestFactory();
|
||||
$extensionConfiguration = $this->prophesize(ExtensionConfiguration::class);
|
||||
|
||||
$subject = new RequestFactory(
|
||||
$extensionConfiguration->reveal()
|
||||
);
|
||||
|
||||
self::assertInstanceOf(RequestFactory::class, $subject);
|
||||
}
|
||||
|
@ -46,9 +55,48 @@ class RequestFactoryTest extends TestCase
|
|||
*/
|
||||
public function returnsRequestWithJsonIdFormat(): void
|
||||
{
|
||||
$subject = new RequestFactory();
|
||||
$request = $subject->createRequest('GET', 'https://example.com/resources/333039283321-xxwg');
|
||||
$extensionConfiguration = $this->prophesize(ExtensionConfiguration::class);
|
||||
|
||||
self::assertSame('format=jsonld', $request->getUri()->getQuery());
|
||||
$subject = new RequestFactory(
|
||||
$extensionConfiguration->reveal()
|
||||
);
|
||||
|
||||
$request = $subject->createRequest('GET', 'https://example.com/api/ext-sync/get-updated-nodes?syncScopeId=dd3738dc-58a6-4748-a6ce-4950293a06db');
|
||||
|
||||
self::assertSame('syncScopeId=dd3738dc-58a6-4748-a6ce-4950293a06db&format=jsonld', $request->getUri()->getQuery());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsRequestWithApiKeyWhenConfigured(): void
|
||||
{
|
||||
$extensionConfiguration = $this->prophesize(ExtensionConfiguration::class);
|
||||
$extensionConfiguration->get('thuecat', 'apiKey')->willReturn('some-api-key');
|
||||
|
||||
$subject = new RequestFactory(
|
||||
$extensionConfiguration->reveal()
|
||||
);
|
||||
|
||||
$request = $subject->createRequest('GET', 'https://example.com/api/ext-sync/get-updated-nodes?syncScopeId=dd3738dc-58a6-4748-a6ce-4950293a06db');
|
||||
|
||||
self::assertSame('syncScopeId=dd3738dc-58a6-4748-a6ce-4950293a06db&format=jsonld&api_key=some-api-key', $request->getUri()->getQuery());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsRequestWithoutApiKeyWhenUnkown(): void
|
||||
{
|
||||
$extensionConfiguration = $this->prophesize(ExtensionConfiguration::class);
|
||||
$extensionConfiguration->get('thuecat', 'apiKey')->willThrow(new ExtensionConfigurationExtensionNotConfiguredException());
|
||||
|
||||
$subject = new RequestFactory(
|
||||
$extensionConfiguration->reveal()
|
||||
);
|
||||
|
||||
$request = $subject->createRequest('GET', 'https://example.com/api/ext-sync/get-updated-nodes?syncScopeId=dd3738dc-58a6-4748-a6ce-4950293a06db');
|
||||
|
||||
self::assertSame('syncScopeId=dd3738dc-58a6-4748-a6ce-4950293a06db&format=jsonld', $request->getUri()->getQuery());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,10 +40,7 @@ class StaticUrlProviderTest extends TestCase
|
|||
*/
|
||||
public function canBeCreated(): void
|
||||
{
|
||||
$configuration = $this->prophesize(ImportConfiguration::class);
|
||||
$configuration->getUrls()->willReturn([]);
|
||||
|
||||
$subject = new StaticUrlProvider($configuration->reveal());
|
||||
$subject = new StaticUrlProvider();
|
||||
self::assertInstanceOf(StaticUrlProvider::class, $subject);
|
||||
}
|
||||
|
||||
|
@ -56,7 +53,7 @@ class StaticUrlProviderTest extends TestCase
|
|||
$configuration->getUrls()->willReturn([]);
|
||||
$configuration->getType()->willReturn('static');
|
||||
|
||||
$subject = new StaticUrlProvider($configuration->reveal());
|
||||
$subject = new StaticUrlProvider();
|
||||
|
||||
$result = $subject->canProvideForConfiguration($configuration->reveal());
|
||||
self::assertTrue($result);
|
||||
|
@ -70,7 +67,7 @@ class StaticUrlProviderTest extends TestCase
|
|||
$configuration = $this->prophesize(ImportConfiguration::class);
|
||||
$configuration->getUrls()->willReturn(['https://example.com']);
|
||||
|
||||
$subject = new StaticUrlProvider($configuration->reveal());
|
||||
$subject = new StaticUrlProvider();
|
||||
|
||||
$result = $subject->createWithConfiguration($configuration->reveal());
|
||||
self::assertInstanceOf(StaticUrlProvider::class, $subject);
|
||||
|
@ -84,7 +81,7 @@ class StaticUrlProviderTest extends TestCase
|
|||
$configuration = $this->prophesize(ImportConfiguration::class);
|
||||
$configuration->getUrls()->willReturn(['https://example.com']);
|
||||
|
||||
$subject = new StaticUrlProvider($configuration->reveal());
|
||||
$subject = new StaticUrlProvider();
|
||||
|
||||
$concreteProvider = $subject->createWithConfiguration($configuration->reveal());
|
||||
$result = $concreteProvider->getUrls();
|
||||
|
|
333
Tests/Unit/Domain/Model/Backend/ImportConfigurationTest.php
Normal file
333
Tests/Unit/Domain/Model/Backend/ImportConfigurationTest.php
Normal file
|
@ -0,0 +1,333 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WerkraumMedia\ThueCat\Tests\Unit\Domain\Model\Backend;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase as TestCase;
|
||||
use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration;
|
||||
|
||||
/**
|
||||
* @covers \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration
|
||||
*/
|
||||
class ImportConfigurationTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function canBeCreated(): void
|
||||
{
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
self::assertInstanceOf(ImportConfiguration::class, $subject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsTitle(): void
|
||||
{
|
||||
$subject = new ImportConfiguration();
|
||||
$subject->_setProperty('title', 'Example Title');
|
||||
|
||||
self::assertSame('Example Title', $subject->getTitle());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsType(): void
|
||||
{
|
||||
$subject = new ImportConfiguration();
|
||||
$subject->_setProperty('type', 'static');
|
||||
|
||||
self::assertSame('static', $subject->getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsTableName(): void
|
||||
{
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
self::assertSame('tx_thuecat_import_configuration', $subject->getTableName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsLastChanged(): void
|
||||
{
|
||||
$lastChanged = new \DateTimeImmutable();
|
||||
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
$subject->_setProperty('tstamp', $lastChanged);
|
||||
|
||||
self::assertSame($lastChanged, $subject->getLastChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsStoragePidWhenSet(): void
|
||||
{
|
||||
$flexForm = implode(PHP_EOL, [
|
||||
'<?xml version="1.0" encoding="utf-8" standalone="yes" ?>',
|
||||
'<T3FlexForms>',
|
||||
'<data>',
|
||||
'<sheet index="sDEF">',
|
||||
'<language index="lDEF">',
|
||||
'<field index="storagePid">',
|
||||
'<value index="vDEF">20</value>',
|
||||
'</field>',
|
||||
'</language>',
|
||||
'</sheet>',
|
||||
'</data>',
|
||||
'</T3FlexForms>',
|
||||
]);
|
||||
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
$subject->_setProperty('configuration', $flexForm);
|
||||
|
||||
self::assertSame(20, $subject->getStoragePid());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsZeroAsStoragePidWhenNoConfigurationExists(): void
|
||||
{
|
||||
$flexForm = '';
|
||||
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
$subject->_setProperty('configuration', $flexForm);
|
||||
|
||||
self::assertSame(0, $subject->getStoragePid());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsZeroAsStoragePidWhenNegativePidIsConfigured(): void
|
||||
{
|
||||
$flexForm = implode(PHP_EOL, [
|
||||
'<?xml version="1.0" encoding="utf-8" standalone="yes" ?>',
|
||||
'<T3FlexForms>',
|
||||
'<data>',
|
||||
'<sheet index="sDEF">',
|
||||
'<language index="lDEF">',
|
||||
'<field index="storagePid">',
|
||||
'<value index="vDEF">-1</value>',
|
||||
'</field>',
|
||||
'</language>',
|
||||
'</sheet>',
|
||||
'</data>',
|
||||
'</T3FlexForms>',
|
||||
]);
|
||||
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
$subject->_setProperty('configuration', $flexForm);
|
||||
|
||||
self::assertSame(0, $subject->getStoragePid());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsZeroAsStoragePidWhenNoneNumericPidIsConfigured(): void
|
||||
{
|
||||
$flexForm = implode(PHP_EOL, [
|
||||
'<?xml version="1.0" encoding="utf-8" standalone="yes" ?>',
|
||||
'<T3FlexForms>',
|
||||
'<data>',
|
||||
'<sheet index="sDEF">',
|
||||
'<language index="lDEF">',
|
||||
'<field index="storagePid">',
|
||||
'<value index="vDEF">abc</value>',
|
||||
'</field>',
|
||||
'</language>',
|
||||
'</sheet>',
|
||||
'</data>',
|
||||
'</T3FlexForms>',
|
||||
]);
|
||||
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
$subject->_setProperty('configuration', $flexForm);
|
||||
|
||||
self::assertSame(0, $subject->getStoragePid());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsUrlsWhenSet(): void
|
||||
{
|
||||
$flexForm = implode(PHP_EOL, [
|
||||
'<?xml version="1.0" encoding="utf-8" standalone="yes" ?>',
|
||||
'<T3FlexForms>',
|
||||
'<data>',
|
||||
'<sheet index="sDEF">',
|
||||
'<language index="lDEF">',
|
||||
'<field index="urls">',
|
||||
'<el index="el">',
|
||||
'<field index="6098e0b6d3fff074555176">',
|
||||
'<value index="url">',
|
||||
'<el>',
|
||||
'<field index="url">',
|
||||
'<value index="vDEF">https://thuecat.org/resources/942302009360-jopp</value>',
|
||||
'</field>',
|
||||
'</el>',
|
||||
'</value>',
|
||||
'<value index="_TOGGLE">0</value>',
|
||||
'</field>',
|
||||
'</el>',
|
||||
'</field>',
|
||||
'</language>',
|
||||
'</sheet>',
|
||||
'</data>',
|
||||
'</T3FlexForms>',
|
||||
]);
|
||||
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
$subject->_setProperty('configuration', $flexForm);
|
||||
|
||||
self::assertSame([
|
||||
'https://thuecat.org/resources/942302009360-jopp',
|
||||
], $subject->getUrls());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsEmptyArrayAsUrlsWhenNoConfigurationExists(): void
|
||||
{
|
||||
$flexForm = '';
|
||||
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
$subject->_setProperty('configuration', $flexForm);
|
||||
|
||||
self::assertSame([], $subject->getUrls());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsEmptyArrayAsUrlsWhenNoUrlsAreConfigured(): void
|
||||
{
|
||||
$flexForm = implode(PHP_EOL, [
|
||||
'<?xml version="1.0" encoding="utf-8" standalone="yes" ?>',
|
||||
'<T3FlexForms>',
|
||||
'<data>',
|
||||
'<sheet index="sDEF">',
|
||||
'<language index="lDEF">',
|
||||
'<field index="storagePid">',
|
||||
'<value index="vDEF">10</value>',
|
||||
'</field>',
|
||||
'</language>',
|
||||
'</sheet>',
|
||||
'</data>',
|
||||
'</T3FlexForms>',
|
||||
]);
|
||||
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
$subject->_setProperty('configuration', $flexForm);
|
||||
|
||||
self::assertSame([], $subject->getUrls());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsSyncScopeIdWhenSet(): void
|
||||
{
|
||||
$flexForm = implode(PHP_EOL, [
|
||||
'<?xml version="1.0" encoding="utf-8" standalone="yes" ?>',
|
||||
'<T3FlexForms>',
|
||||
'<data>',
|
||||
'<sheet index="sDEF">',
|
||||
'<language index="lDEF">',
|
||||
'<field index="syncScopeId">',
|
||||
'<value index="vDEF">dd4639dc-58a7-4648-a6ce-4950293a06db</value>',
|
||||
'</field>',
|
||||
'</language>',
|
||||
'</sheet>',
|
||||
'</data>',
|
||||
'</T3FlexForms>',
|
||||
]);
|
||||
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
$subject->_setProperty('configuration', $flexForm);
|
||||
|
||||
self::assertSame('dd4639dc-58a7-4648-a6ce-4950293a06db', $subject->getSyncScopeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsEmptyStringAsSyncScopeIdWhenNoConfigurationExists(): void
|
||||
{
|
||||
$flexForm = '';
|
||||
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
$subject->_setProperty('configuration', $flexForm);
|
||||
|
||||
self::assertSame('', $subject->getSyncScopeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function returnsEmptyStringAsSyncScopeIdWhenNoSyncScopeIdAreConfigured(): void
|
||||
{
|
||||
$flexForm = implode(PHP_EOL, [
|
||||
'<?xml version="1.0" encoding="utf-8" standalone="yes" ?>',
|
||||
'<T3FlexForms>',
|
||||
'<data>',
|
||||
'<sheet index="sDEF">',
|
||||
'<language index="lDEF">',
|
||||
'<field index="storagePid">',
|
||||
'<value index="vDEF">10</value>',
|
||||
'</field>',
|
||||
'</language>',
|
||||
'</sheet>',
|
||||
'</data>',
|
||||
'</T3FlexForms>',
|
||||
]);
|
||||
|
||||
$subject = new ImportConfiguration();
|
||||
|
||||
$subject->_setProperty('configuration', $flexForm);
|
||||
|
||||
self::assertSame('', $subject->getSyncScopeId());
|
||||
}
|
||||
}
|
2
ext_conf_template.txt
Normal file
2
ext_conf_template.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
# cat=API; type=string; label=LLL:EXT:thuecat/Resources/Private/Language/locallang_conf.xlf:apiKey
|
||||
apiKey =
|
Loading…
Reference in a new issue