diff --git a/Classes/Controller/Backend/AbstractController.php b/Classes/Controller/Backend/AbstractController.php new file mode 100644 index 0000000..2d6da48 --- /dev/null +++ b/Classes/Controller/Backend/AbstractController.php @@ -0,0 +1,59 @@ + + * + * 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\CMS\Backend\View\BackendTemplateView; +use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; +use TYPO3\CMS\Extbase\Mvc\View\ViewInterface; +use WerkraumMedia\ThueCat\View\Backend\Menu; + +abstract class AbstractController extends ActionController +{ + /** + * BackendTemplateContainer + * + * @var BackendTemplateView + */ + protected $view; + + /** + * Backend Template Container + * + * @var string + */ + protected $defaultViewObjectName = BackendTemplateView::class; + + protected function initializeView(ViewInterface $view) + { + if ($view instanceof BackendTemplateView) { + $this->getMenu()->addMenu( + $view->getModuleTemplate()->getDocHeaderComponent()->getMenuRegistry(), + $this->uriBuilder, + get_class($this) + ); + } + } + + abstract protected function getMenu(): Menu; +} diff --git a/Classes/Controller/Backend/ImportController.php b/Classes/Controller/Backend/ImportController.php new file mode 100644 index 0000000..7a849b3 --- /dev/null +++ b/Classes/Controller/Backend/ImportController.php @@ -0,0 +1,80 @@ + + * + * 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; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; +use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportLogRepository; +use WerkraumMedia\ThueCat\Extension; +use WerkraumMedia\ThueCat\Typo3Wrapper\TranslationService; +use WerkraumMedia\ThueCat\View\Backend\Menu; + +class ImportController extends AbstractController +{ + private Importer $importer; + private ImportLogRepository $repository; + private TranslationService $translation; + private Menu $menu; + + public function __construct( + Importer $importer, + ImportLogRepository $repository, + TranslationService $translation, + Menu $menu + ) { + $this->importer = $importer; + $this->repository = $repository; + $this->translation = $translation; + $this->menu = $menu; + } + + public function indexAction(): void + { + $this->view->assignMultiple([ + 'imports' => $this->repository->findAll(), + ]); + } + + public function importAction(ImportConfiguration $importConfiguration): void + { + $this->importer->importConfiguration($importConfiguration); + $this->addFlashMessage( + $this->translation->translate( + 'controller.backend.import.import.success.text', + Extension::EXTENSION_NAME, + [$importConfiguration->getTitle()] + ), + $this->translation->translate( + 'controller.backend.import.import.success.title', + Extension::EXTENSION_NAME + ) + ); + $this->redirect('index', 'Backend\Overview'); + } + + protected function getMenu(): Menu + { + return $this->menu; + } +} diff --git a/Classes/Controller/Backend/OverviewController.php b/Classes/Controller/Backend/OverviewController.php new file mode 100644 index 0000000..39d68c8 --- /dev/null +++ b/Classes/Controller/Backend/OverviewController.php @@ -0,0 +1,58 @@ + + * + * 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\Repository\Backend\ImportConfigurationRepository; +use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; +use WerkraumMedia\ThueCat\View\Backend\Menu; + +class OverviewController extends AbstractController +{ + private OrganisationRepository $organisationRepository; + private ImportConfigurationRepository $importConfigurationRepository; + private Menu $menu; + + public function __construct( + OrganisationRepository $organisationRepository, + ImportConfigurationRepository $importConfigurationRepository, + Menu $menu + ) { + $this->organisationRepository = $organisationRepository; + $this->importConfigurationRepository = $importConfigurationRepository; + $this->menu = $menu; + } + + public function indexAction(): void + { + $this->view->assignMultiple([ + 'importConfigurations' => $this->importConfigurationRepository->findAll(), + 'organisations' => $this->organisationRepository->findAll(), + ]); + } + + protected function getMenu(): Menu + { + return $this->menu; + } +} diff --git a/Classes/DependencyInjection/ConverterPass.php b/Classes/DependencyInjection/ConverterPass.php new file mode 100644 index 0000000..966329d --- /dev/null +++ b/Classes/DependencyInjection/ConverterPass.php @@ -0,0 +1,48 @@ + + * + * 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 Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use WerkraumMedia\ThueCat\Domain\Import\Converter\Registry; + +class ConverterPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $registry = $container->findDefinition(Registry::class); + + foreach ($container->findTaggedServiceIds('thuecat.converter') as $id => $tags) { + $definition = $container->findDefinition($id); + if (!$definition->isAutoconfigured() || $definition->isAbstract()) { + continue; + } + + // Services that implement MyCustomInterface need to be public, + // to be lazy loadable by the registry via $container->get() + // $container->findDefinition($id)->setPublic(true); + $registry->addMethodCall('registerConverter', [$definition]); + } + } +} diff --git a/Classes/DependencyInjection/UrlProvidersPass.php b/Classes/DependencyInjection/UrlProvidersPass.php new file mode 100644 index 0000000..7e62d49 --- /dev/null +++ b/Classes/DependencyInjection/UrlProvidersPass.php @@ -0,0 +1,48 @@ + + * + * 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 Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\Registry; + +class UrlProvidersPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $registry = $container->findDefinition(Registry::class); + + foreach ($container->findTaggedServiceIds('thuecat.urlprovider') as $id => $tags) { + $definition = $container->findDefinition($id); + if (!$definition->isAutoconfigured() || $definition->isAbstract()) { + continue; + } + + // Services that implement MyCustomInterface need to be public, + // to be lazy loadable by the registry via $container->get() + // $container->findDefinition($id)->setPublic(true); + $registry->addMethodCall('registerProvider', [$definition]); + } + } +} diff --git a/Classes/Domain/Import/Converter/Converter.php b/Classes/Domain/Import/Converter/Converter.php new file mode 100644 index 0000000..01ce484 --- /dev/null +++ b/Classes/Domain/Import/Converter/Converter.php @@ -0,0 +1,37 @@ + + * + * 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\Model\Entity; + +interface Converter +{ + /** + * A single type is an array of different types. + * All types together identify a specific entity and possible converter. + */ + public function canConvert(array $type): bool; + + public function convert(array $jsonIdOfEntity): Entity; +} diff --git a/Classes/Domain/Import/Converter/Organisation.php b/Classes/Domain/Import/Converter/Organisation.php new file mode 100644 index 0000000..c04769c --- /dev/null +++ b/Classes/Domain/Import/Converter/Organisation.php @@ -0,0 +1,47 @@ + + * + * 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\Model\GenericEntity; + +class Organisation implements Converter +{ + public function convert(array $jsonIdOfEntity): GenericEntity + { + return new GenericEntity( + 95, + 'tx_thuecat_organisation', + $jsonIdOfEntity['@id'], + [ + 'title' => $jsonIdOfEntity['schema:name']['@value'], + 'description' => $jsonIdOfEntity['schema:description']['@value'], + ] + ); + } + + public function canConvert(array $type): bool + { + return array_search('thuecat:TouristMarketingCompany', $type) !== false; + } +} diff --git a/Classes/Domain/Import/Converter/Registry.php b/Classes/Domain/Import/Converter/Registry.php new file mode 100644 index 0000000..a9421dd --- /dev/null +++ b/Classes/Domain/Import/Converter/Registry.php @@ -0,0 +1,48 @@ + + * + * 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. + */ + +/** + * Central registry of all available converters. + */ +class Registry +{ + private array $converters = []; + + public function registerConverter(Converter $converter): void + { + $this->converters[] = $converter; + } + + public function getConverterBasedOnType(array $type): ?Converter + { + foreach ($this->converters as $converter) { + if ($converter->canConvert($type)) { + return $converter; + } + } + + return null; + } +} diff --git a/Classes/Domain/Import/Converter/TouristInformation.php b/Classes/Domain/Import/Converter/TouristInformation.php new file mode 100644 index 0000000..18c0cd4 --- /dev/null +++ b/Classes/Domain/Import/Converter/TouristInformation.php @@ -0,0 +1,72 @@ + + * + * 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\Model\GenericEntity; +use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; +use WerkraumMedia\ThueCat\Domain\Repository\Backend\TownRepository; + +class TouristInformation implements Converter +{ + private OrganisationRepository $organisationRepository; + private TownRepository $townRepository; + + public function __construct( + OrganisationRepository $organisationRepository, + TownRepository $townRepository + ) { + $this->organisationRepository = $organisationRepository; + $this->townRepository = $townRepository; + } + + public function convert(array $jsonIdOfEntity): GenericEntity + { + $manager = $this->organisationRepository->findOneByRemoteId($jsonIdOfEntity['thuecat:managedBy']['@id']); + $town = $this->townRepository->findOneByRemoteIds($this->getContainedInPlaceIds($jsonIdOfEntity)); + + return new GenericEntity( + 95, + 'tx_thuecat_tourist_information', + $jsonIdOfEntity['@id'], + [ + 'title' => $jsonIdOfEntity['schema:name']['@value'], + 'description' => $jsonIdOfEntity['schema:description'][0]['@value'], + 'managed_by' => $manager ? $manager->getUid() : 0, + 'town' => $town ? $town->getUid() : 0, + ] + ); + } + + public function canConvert(array $type): bool + { + return array_search('thuecat:TouristInformation', $type) !== false; + } + + private function getContainedInPlaceIds(array $jsonIdOfEntity): array + { + return array_map(function (array $place) { + return $place['@id']; + }, $jsonIdOfEntity['schema:containedInPlace']); + } +} diff --git a/Classes/Domain/Import/Converter/Town.php b/Classes/Domain/Import/Converter/Town.php new file mode 100644 index 0000000..cf0d922 --- /dev/null +++ b/Classes/Domain/Import/Converter/Town.php @@ -0,0 +1,58 @@ + + * + * 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\Model\GenericEntity; +use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; + +class Town implements Converter +{ + private OrganisationRepository $organisationRepository; + + public function __construct( + OrganisationRepository $organisationRepository + ) { + $this->organisationRepository = $organisationRepository; + } + + public function convert(array $jsonIdOfEntity): GenericEntity + { + $manager = $this->organisationRepository->findOneByRemoteId($jsonIdOfEntity['thuecat:managedBy']['@id']); + return new GenericEntity( + 95, + 'tx_thuecat_town', + $jsonIdOfEntity['@id'], + [ + 'title' => $jsonIdOfEntity['schema:name']['@value'], + 'description' => $jsonIdOfEntity['schema:description']['@value'] ?? '', + 'managed_by' => $manager ? $manager->getUid() : 0, + ] + ); + } + + public function canConvert(array $type): bool + { + return array_search('thuecat:Town', $type) !== false; + } +} diff --git a/Classes/Domain/Import/Importer.php b/Classes/Domain/Import/Importer.php new file mode 100644 index 0000000..2c9f20a --- /dev/null +++ b/Classes/Domain/Import/Importer.php @@ -0,0 +1,93 @@ + + * + * 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\CMS\Core\Utility\GeneralUtility; +use WerkraumMedia\ThueCat\Domain\Import\Converter\Converter; +use WerkraumMedia\ThueCat\Domain\Import\Converter\Registry as ConverterRegistry; +use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; +use WerkraumMedia\ThueCat\Domain\Import\Importer\SaveData; +use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\Registry as UrlProviderRegistry; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog; +use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportLogRepository; + +class Importer +{ + private UrlProviderRegistry $urls; + private ConverterRegistry $converter; + private FetchData $fetchData; + private SaveData $saveData; + private ImportLog $importLog; + private ImportLogRepository $importLogRepository; + + public function __construct( + UrlProviderRegistry $urls, + ConverterRegistry $converter, + ImportLogRepository $importLogRepository, + FetchData $fetchData, + SaveData $saveData + ) { + $this->urls = $urls; + $this->converter = $converter; + $this->importLogRepository = $importLogRepository; + $this->fetchData = $fetchData; + $this->saveData = $saveData; + } + + public function importConfiguration(ImportConfiguration $configuration): ImportLog + { + $this->importLog = GeneralUtility::makeInstance(ImportLog::class, $configuration); + + $urlProvider = $this->urls->getProviderForConfiguration($configuration); + foreach ($urlProvider->getUrls() as $url) { + $this->importResourceByUrl($url); + } + + $this->importLogRepository->addLog($this->importLog); + return clone $this->importLog; + } + + private function importResourceByUrl(string $url): void + { + $content = $this->fetchData->jsonLDFromUrl($url); + + if ($content === []) { + return; + } + + foreach ($content['@graph'] as $jsonEntity) { + $this->importJsonEntity($jsonEntity); + } + } + + private function importJsonEntity(array $jsonEntity): void + { + $converter = $this->converter->getConverterBasedOnType($jsonEntity['@type']); + if ($converter instanceof Converter) { + $this->saveData->import($converter->convert($jsonEntity), $this->importLog); + return; + } + } +} diff --git a/Classes/Domain/Import/Importer/FetchData.php b/Classes/Domain/Import/Importer/FetchData.php new file mode 100644 index 0000000..241c2cc --- /dev/null +++ b/Classes/Domain/Import/Importer/FetchData.php @@ -0,0 +1,51 @@ + + * + * 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 Psr\Http\Client\ClientInterface; +use Psr\Http\Message\RequestFactoryInterface; + +class FetchData +{ + public function __construct( + RequestFactoryInterface $requestFactory, + ClientInterface $httpClient + ) { + $this->requestFactory = $requestFactory; + $this->httpClient = $httpClient; + } + + public function jsonLDFromUrl(string $url): array + { + $request = $this->requestFactory->createRequest('GET', $url); + $response = $this->httpClient->sendRequest($request); + + $json = json_decode((string) $response->getBody(), true); + if (is_array($json)) { + return $json; + } + + return []; + } +} diff --git a/Classes/Domain/Import/Importer/SaveData.php b/Classes/Domain/Import/Importer/SaveData.php new file mode 100644 index 0000000..e9d415a --- /dev/null +++ b/Classes/Domain/Import/Importer/SaveData.php @@ -0,0 +1,102 @@ + + * + * 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\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\DataHandling\DataHandler; +use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry; + +class SaveData +{ + private DataHandler $dataHandler; + private ConnectionPool $connectionPool; + + public function __construct( + DataHandler $dataHandler, + ConnectionPool $connectionPool + ) { + $this->dataHandler = $dataHandler; + $this->dataHandler->stripslashes_values = 0; + $this->connectionPool = $connectionPool; + } + + public function import(Entity $entity, ImportLog $log): void + { + $dataHandler = clone $this->dataHandler; + + $identifier = $this->getIdentifier($entity); + $dataHandler->start([ + $entity->getTypo3DatabaseTableName() => [ + $identifier => array_merge($entity->getData(), [ + 'pid' => $entity->getTypo3StoragePid(), + 'remote_id' => $entity->getRemoteId(), + ]), + ], + ], []); + $dataHandler->process_datamap(); + + if (isset($dataHandler->substNEWwithIDs[$identifier])) { + $entity->setImportedTypo3Uid($dataHandler->substNEWwithIDs[$identifier]); + } elseif (is_numeric($identifier)) { + $entity->setExistingTypo3Uid((int) $identifier); + } + + $log->addEntry(new ImportLogEntry( + $entity, + $dataHandler->errorLog + )); + } + + private function getIdentifier(Entity $entity): string + { + $existingUid = $this->getExistingUid($entity); + + if ($existingUid > 0) { + return (string) $existingUid; + } + + return 'NEW_1'; + } + + private function getExistingUid(Entity $entity): int + { + $queryBuilder = $this->connectionPool->getQueryBuilderForTable($entity->getTypo3DatabaseTableName()); + $queryBuilder->getRestrictions()->removeAll(); + $queryBuilder->select('uid'); + $queryBuilder->from($entity->getTypo3DatabaseTableName()); + $queryBuilder->where($queryBuilder->expr()->eq( + 'remote_id', + $queryBuilder->createNamedParameter($entity->getRemoteId()) + )); + + $result = $queryBuilder->execute()->fetchColumn(); + if (is_numeric($result)) { + return (int) $result; + } + + return 0; + } +} diff --git a/Classes/Domain/Import/Model/Entity.php b/Classes/Domain/Import/Model/Entity.php new file mode 100644 index 0000000..86a7b70 --- /dev/null +++ b/Classes/Domain/Import/Model/Entity.php @@ -0,0 +1,65 @@ + + * + * 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. + */ + +interface Entity +{ + public function getTypo3StoragePid(): int; + + public function getTypo3DatabaseTableName(): string; + + /** + * Return full remote id as delivered by remote API. + */ + public function getRemoteId(): string; + + /** + * Return db_column_name => db_value. + */ + public function getData(): array; + + /** + * Might be called during import. + * Only in case entitiy already existed. + * Is then called with existing UID from system. + */ + public function setExistingTypo3Uid(int $uid): void; + + /** + * Might be called during import. + * Only in case entitiy didn't exist within system. + * Is then called with new UID from system. + */ + public function setImportedTypo3Uid(int $uid): void; + + /** + * Should be 0 if no uid is known. + */ + public function getTypo3Uid(): int; + + /** + * Must return true in case the entitiy did not exist. + */ + public function wasCreated(): bool; +} diff --git a/Classes/Domain/Import/Model/GenericEntity.php b/Classes/Domain/Import/Model/GenericEntity.php new file mode 100644 index 0000000..2383bdf --- /dev/null +++ b/Classes/Domain/Import/Model/GenericEntity.php @@ -0,0 +1,88 @@ + + * + * 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 GenericEntity implements Entity +{ + private int $typo3StoragePid; + private string $typo3DatabaseTableName; + private bool $created = false; + private int $typo3Uid = 0; + private string $remoteId; + private array $data; + + public function __construct( + int $typo3StoragePid, + string $typo3DatabaseTableName, + string $remoteId, + array $data + ) { + $this->typo3StoragePid = $typo3StoragePid; + $this->typo3DatabaseTableName = $typo3DatabaseTableName; + $this->remoteId = $remoteId; + $this->data = $data; + } + + public function getTypo3StoragePid(): int + { + return $this->typo3StoragePid; + } + + public function getTypo3DatabaseTableName(): string + { + return $this->typo3DatabaseTableName; + } + + public function getRemoteId(): string + { + return $this->remoteId; + } + + public function getData(): array + { + return $this->data; + } + + public function setImportedTypo3Uid(int $uid): void + { + $this->typo3Uid = $uid; + $this->created = true; + } + + public function setExistingTypo3Uid(int $uid): void + { + $this->typo3Uid = $uid; + $this->created = false; + } + + public function getTypo3Uid(): int + { + return $this->typo3Uid; + } + + public function wasCreated(): bool + { + return $this->created; + } +} diff --git a/Classes/Domain/Import/RequestFactory.php b/Classes/Domain/Import/RequestFactory.php new file mode 100644 index 0000000..e6e80e4 --- /dev/null +++ b/Classes/Domain/Import/RequestFactory.php @@ -0,0 +1,41 @@ + + * + * 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 Psr\Http\Message\RequestInterface; +use TYPO3\CMS\Core\Http\RequestFactory as Typo3RequestFactory; +use TYPO3\CMS\Core\Http\Uri; + +class RequestFactory extends Typo3RequestFactory +{ + public function createRequest(string $method, $uri): RequestInterface + { + $uri = new Uri($uri); + $uri = $uri->withQuery('?format=jsonId'); + + // TODO: Add api key from site + + return parent::createRequest($method, $uri); + } +} diff --git a/Classes/Domain/Import/UrlProvider/Registry.php b/Classes/Domain/Import/UrlProvider/Registry.php new file mode 100644 index 0000000..87859db --- /dev/null +++ b/Classes/Domain/Import/UrlProvider/Registry.php @@ -0,0 +1,53 @@ + + * + * 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\Model\Backend\ImportConfiguration; + +/** + * Central registry of all available url provider. + */ +class Registry +{ + private array $provider = []; + + public function registerProvider(UrlProvider $provider): void + { + $this->provider[] = $provider; + } + + /** + * @return UrlProvider[] + */ + public function getProviderForConfiguration(ImportConfiguration $configuration): ?UrlProvider + { + foreach ($this->provider as $provider) { + if ($provider->canProvideForConfiguration($configuration)) { + return $provider->createWithConfiguration($configuration); + } + } + + return null; + } +} diff --git a/Classes/Domain/Import/UrlProvider/StaticUrlProvider.php b/Classes/Domain/Import/UrlProvider/StaticUrlProvider.php new file mode 100644 index 0000000..77228af --- /dev/null +++ b/Classes/Domain/Import/UrlProvider/StaticUrlProvider.php @@ -0,0 +1,57 @@ + + * + * 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\CMS\Core\Utility\GeneralUtility; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; + +class StaticUrlProvider implements UrlProvider +{ + private array $urls = []; + + public function __construct( + ImportConfiguration $configuration + ) { + if ($configuration instanceof ImportConfiguration) { + $this->urls = $configuration->getUrls(); + } + } + + public function canProvideForConfiguration( + ImportConfiguration $configuration + ): bool { + return $configuration->getType() === 'static'; + } + + public function createWithConfiguration( + ImportConfiguration $configuration + ): UrlProvider { + return GeneralUtility::makeInstance(self::class, $configuration); + } + + public function getUrls(): array + { + return $this->urls; + } +} diff --git a/Classes/Domain/Import/UrlProvider/UrlProvider.php b/Classes/Domain/Import/UrlProvider/UrlProvider.php new file mode 100644 index 0000000..215a48d --- /dev/null +++ b/Classes/Domain/Import/UrlProvider/UrlProvider.php @@ -0,0 +1,38 @@ + + * + * 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\Model\Backend\ImportConfiguration; + +interface UrlProvider +{ + /** + * @var string[] + */ + public function getUrls(): array; + + public function canProvideForConfiguration(ImportConfiguration $configuration): bool; + + public function createWithConfiguration(ImportConfiguration $configuration): UrlProvider; +} diff --git a/Classes/Domain/Model/Backend/AbstractEntity.php b/Classes/Domain/Model/Backend/AbstractEntity.php new file mode 100644 index 0000000..9741550 --- /dev/null +++ b/Classes/Domain/Model/Backend/AbstractEntity.php @@ -0,0 +1,54 @@ + + * + * 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\CMS\Extbase\DomainObject\AbstractEntity as Typo3AbstractEntity; + +class AbstractEntity extends Typo3AbstractEntity +{ + protected string $remoteId = ''; + protected string $title = ''; + protected string $description = ''; + protected ?\DateTimeImmutable $tstamp = null; + + public function getRemoteId(): string + { + return $this->remoteId; + } + + public function getTitle(): string + { + return $this->title; + } + + public function getDescription(): string + { + return $this->description; + } + + public function getLastImported(): ?\DateTimeImmutable + { + return $this->tstamp; + } +} diff --git a/Classes/Domain/Model/Backend/ImportConfiguration.php b/Classes/Domain/Model/Backend/ImportConfiguration.php new file mode 100644 index 0000000..3674ed4 --- /dev/null +++ b/Classes/Domain/Model/Backend/ImportConfiguration.php @@ -0,0 +1,77 @@ + + * + * 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\CMS\Core\Utility\ArrayUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; + +class ImportConfiguration extends AbstractEntity +{ + protected string $title = ''; + protected string $type = ''; + protected string $configuration = ''; + protected ?\DateTimeImmutable $tstamp = null; + + public function getTitle(): string + { + return $this->title; + } + + public function getType(): string + { + return $this->type; + } + + public function getTableName(): string + { + return 'tx_thuecat_import_configuration'; + } + + public function getLastChanged(): ?\DateTimeImmutable + { + return $this->tstamp; + } + + public function getUrls(): array + { + if ($this->configuration === '') { + return []; + } + + $entries = array_map(function (array $urlEntry) { + return ArrayUtility::getValueByPath($urlEntry, 'url/el/url/vDEF'); + }, $this->getEntries()); + + return array_values($entries); + } + + private function getEntries(): array + { + return ArrayUtility::getValueByPath( + GeneralUtility::xml2array($this->configuration), + 'data/sDEF/lDEF/urls/el' + ); + } +} diff --git a/Classes/Domain/Model/Backend/ImportLog.php b/Classes/Domain/Model/Backend/ImportLog.php new file mode 100644 index 0000000..1a86914 --- /dev/null +++ b/Classes/Domain/Model/Backend/ImportLog.php @@ -0,0 +1,114 @@ + + * + * 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\CMS\Extbase\DomainObject\AbstractEntity as Typo3AbstractEntity; +use TYPO3\CMS\Extbase\Persistence\ObjectStorage; + +class ImportLog extends Typo3AbstractEntity +{ + /** + * @var ObjectStorage + */ + protected $logEntries = []; + + /** + * @var ImportConfiguration + */ + protected $configuration; + + /** + * @var \DateTimeImmutable|null + */ + protected $crdate; + + public function __construct( + ImportConfiguration $configuration + ) { + $this->logEntries = new ObjectStorage(); + $this->configuration = $configuration; + } + + public function addEntry(ImportLogEntry $entry): void + { + $this->logEntries->attach($entry); + } + + public function getConfiguration(): ImportConfiguration + { + return $this->configuration; + } + + /** + * @return ObjectStorage + */ + public function getEntries(): ObjectStorage + { + return $this->logEntries; + } + + public function getCreated(): ?\DateTimeImmutable + { + return $this->crdate; + } + + public function getListOfErrors(): array + { + $errors = []; + + foreach ($this->getEntries() as $entry) { + if ($entry->hasErrors()) { + $errors = array_merge($errors, $entry->getErrors()); + } + } + + return $errors; + } + + public function hasErrors(): bool + { + foreach ($this->getEntries() as $entry) { + if ($entry->hasErrors()) { + return true; + } + } + + return false; + } + + public function getSummaryOfEntries(): array + { + $summary = []; + + foreach ($this->getEntries() as $entry) { + if (isset($summary[$entry->getRecordDatabaseTableName()])) { + ++$summary[$entry->getRecordDatabaseTableName()]; + continue; + } + $summary[$entry->getRecordDatabaseTableName()] = 1; + } + + return $summary; + } +} diff --git a/Classes/Domain/Model/Backend/ImportLogEntry.php b/Classes/Domain/Model/Backend/ImportLogEntry.php new file mode 100644 index 0000000..afdda84 --- /dev/null +++ b/Classes/Domain/Model/Backend/ImportLogEntry.php @@ -0,0 +1,97 @@ + + * + * 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\CMS\Extbase\DomainObject\AbstractEntity as Typo3AbstractEntity; +use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; + +class ImportLogEntry extends Typo3AbstractEntity +{ + /** + * @var bool + */ + protected $insertion = false; + + /** + * @var int + */ + protected $recordUid = 0; + + /** + * @var int + */ + protected $recordPid = 0; + + /** + * @var string + */ + protected $tableName = ''; + + /** + * @var string + */ + protected $errors = ''; + + protected array $errorsAsArray = []; + + public function __construct( + Entity $entity, + array $dataHandlerErrorLog + ) { + $this->insertion = $entity->wasCreated(); + $this->recordUid = $entity->getTypo3Uid(); + $this->recordPid = $entity->getTypo3StoragePid(); + $this->tableName = $entity->getTypo3DatabaseTableName(); + $this->errorsAsArray = $dataHandlerErrorLog; + } + + public function wasInsertion(): bool + { + return $this->insertion; + } + + public function getRecordUid(): int + { + return $this->recordUid; + } + + public function getRecordDatabaseTableName(): string + { + return $this->tableName; + } + + public function getErrors(): array + { + if ($this->errorsAsArray === [] && $this->errors !== '') { + $this->errorsAsArray = json_decode($this->errors, true); + } + + return $this->errorsAsArray; + } + + public function hasErrors(): bool + { + return $this->getErrors() !== []; + } +} diff --git a/Classes/Domain/Model/Backend/Organisation.php b/Classes/Domain/Model/Backend/Organisation.php new file mode 100644 index 0000000..0ff984d --- /dev/null +++ b/Classes/Domain/Model/Backend/Organisation.php @@ -0,0 +1,54 @@ + + * + * 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\CMS\Extbase\Persistence\ObjectStorage; + +class Organisation extends AbstractEntity +{ + /** + * @var ObjectStorage + */ + protected $managesTowns; + + /** + * @var ObjectStorage + */ + protected $managesTouristInformation; + + public function getManagesTowns(): ObjectStorage + { + return $this->managesTowns; + } + + public function getManagesTouristInformation(): ObjectStorage + { + return $this->managesTouristInformation; + } + + public function getTableName(): string + { + return 'tx_thuecat_organisation'; + } +} diff --git a/Classes/Domain/Model/Backend/TouristInformation.php b/Classes/Domain/Model/Backend/TouristInformation.php new file mode 100644 index 0000000..ba7bb67 --- /dev/null +++ b/Classes/Domain/Model/Backend/TouristInformation.php @@ -0,0 +1,28 @@ + + * + * 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 TouristInformation extends AbstractEntity +{ +} diff --git a/Classes/Domain/Model/Backend/Town.php b/Classes/Domain/Model/Backend/Town.php new file mode 100644 index 0000000..6f40178 --- /dev/null +++ b/Classes/Domain/Model/Backend/Town.php @@ -0,0 +1,39 @@ + + * + * 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\CMS\Extbase\Persistence\ObjectStorage; + +class Town extends AbstractEntity +{ + /** + * @var ObjectStorage + */ + protected $touristInformation; + + public function getTouristInformation(): ObjectStorage + { + return $this->touristInformation; + } +} diff --git a/Classes/Domain/Repository/Backend/ImportConfigurationRepository.php b/Classes/Domain/Repository/Backend/ImportConfigurationRepository.php new file mode 100644 index 0000000..8eaec0a --- /dev/null +++ b/Classes/Domain/Repository/Backend/ImportConfigurationRepository.php @@ -0,0 +1,42 @@ + + * + * 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\CMS\Extbase\Object\ObjectManagerInterface; +use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; +use TYPO3\CMS\Extbase\Persistence\Repository; + +class ImportConfigurationRepository extends Repository +{ + public function __construct( + ObjectManagerInterface $objectManager, + Typo3QuerySettings $querySettings + ) { + parent::__construct($objectManager); + + $querySettings->setRespectStoragePage(false); + + $this->setDefaultQuerySettings($querySettings); + } +} diff --git a/Classes/Domain/Repository/Backend/ImportLogRepository.php b/Classes/Domain/Repository/Backend/ImportLogRepository.php new file mode 100644 index 0000000..f1f54a3 --- /dev/null +++ b/Classes/Domain/Repository/Backend/ImportLogRepository.php @@ -0,0 +1,90 @@ + + * + * 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\CMS\Core\DataHandling\DataHandler; +use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; +use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; +use TYPO3\CMS\Extbase\Persistence\QueryInterface; +use TYPO3\CMS\Extbase\Persistence\Repository; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog; + +class ImportLogRepository extends Repository +{ + private DataHandler $dataHandler; + + public function __construct( + ObjectManagerInterface $objectManager, + DataHandler $dataHandler, + Typo3QuerySettings $querySettings + ) { + parent::__construct($objectManager); + + $this->dataHandler = $dataHandler; + $this->dataHandler->stripslashes_values = 0; + + $querySettings->setRespectStoragePage(false); + $this->setDefaultQuerySettings($querySettings); + + $this->setDefaultOrderings([ + 'crdate' => QueryInterface::ORDER_DESCENDING, + ]); + } + + public function addLog(ImportLog $log): void + { + $dataHandler = clone $this->dataHandler; + $dataHandler->start([ + 'tx_thuecat_import_log' => [ + 'NEW0' => [ + 'pid' => 0, + 'configuration' => $log->getConfiguration()->getUid(), + ], + ], + 'tx_thuecat_import_log_entry' => $this->getLogEntries($log), + ], []); + $dataHandler->process_datamap(); + } + + private function getLogEntries(ImportLog $log): array + { + $number = 1; + $entries = []; + + foreach ($log->getEntries() as $entry) { + $number++; + + $entries['NEW' . $number] = [ + 'pid' => 0, + 'import_log' => 'NEW0', + 'insertion' => $entry->wasInsertion(), + 'record_uid' => $entry->getRecordUid(), + 'table_name' => $entry->getRecordDatabaseTableName(), + 'errors' => json_encode($entry->getErrors()), + ]; + } + + return $entries; + } +} diff --git a/Classes/Domain/Repository/Backend/OrganisationRepository.php b/Classes/Domain/Repository/Backend/OrganisationRepository.php new file mode 100644 index 0000000..741fe0b --- /dev/null +++ b/Classes/Domain/Repository/Backend/OrganisationRepository.php @@ -0,0 +1,44 @@ + + * + * 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\CMS\Extbase\Object\ObjectManagerInterface; +use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; +use TYPO3\CMS\Extbase\Persistence\Repository; + +/** + * @method Organisation|null findOneByRemoteId(string $remoteId) + */ +class OrganisationRepository extends Repository +{ + public function __construct( + ObjectManagerInterface $objectManager, + Typo3QuerySettings $querySettings + ) { + parent::__construct($objectManager); + + $querySettings->setRespectStoragePage(false); + $this->setDefaultQuerySettings($querySettings); + } +} diff --git a/Classes/Domain/Repository/Backend/TownRepository.php b/Classes/Domain/Repository/Backend/TownRepository.php new file mode 100644 index 0000000..1ea6c1d --- /dev/null +++ b/Classes/Domain/Repository/Backend/TownRepository.php @@ -0,0 +1,56 @@ + + * + * 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\CMS\Extbase\Object\ObjectManagerInterface; +use TYPO3\CMS\Extbase\Persistence\Generic\Typo3QuerySettings; +use TYPO3\CMS\Extbase\Persistence\Repository; +use WerkraumMedia\ThueCat\Domain\Model\Backend\Town; + +/** + * @method Town|null findOneByRemoteIds(string[] $remoteIds) + */ +class TownRepository extends Repository +{ + public function __construct( + ObjectManagerInterface $objectManager, + Typo3QuerySettings $querySettings + ) { + parent::__construct($objectManager); + + $querySettings->setRespectStoragePage(false); + + $this->setDefaultQuerySettings($querySettings); + } + + public function findOneByRemoteIds(array $remoteIds): ?Town + { + $query = $this->createQuery(); + + $query->in('remoteId', $remoteIds); + $query->setLimit(1); + + return $query->execute()->getFirst(); + } +} diff --git a/Classes/Extension.php b/Classes/Extension.php new file mode 100644 index 0000000..c717285 --- /dev/null +++ b/Classes/Extension.php @@ -0,0 +1,59 @@ + + * + * 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\CMS\Extbase\Utility\ExtensionUtility; +use WerkraumMedia\ThueCat\Controller\Backend\ImportController; +use WerkraumMedia\ThueCat\Controller\Backend\OverviewController; + +class Extension +{ + public const EXTENSION_KEY = 'thuecat'; + + public const EXTENSION_NAME = 'Thuecat'; + + public static function getLanguagePath(): string + { + return 'LLL:EXT:' . self::EXTENSION_KEY . '/Resources/Private/Language/'; + } + + public static function registerBackendModules(): void + { + ExtensionUtility::registerModule( + self::EXTENSION_NAME, + 'site', + 'thuecat', + '', + [ + OverviewController::class => 'index', + ImportController::class => 'import, index', + ], + [ + 'access' => 'user,group', + 'icon' => 'EXT:' . self::EXTENSION_KEY . '/Resources/Public/Icons/module.svg', + 'labels' => self::getLanguagePath() . 'locallang_mod.xlf', + ] + ); + } +} diff --git a/Classes/Typo3Wrapper/TranslationService.php b/Classes/Typo3Wrapper/TranslationService.php new file mode 100644 index 0000000..2b2a338 --- /dev/null +++ b/Classes/Typo3Wrapper/TranslationService.php @@ -0,0 +1,37 @@ + + * + * 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\CMS\Extbase\Utility\LocalizationUtility; + +class TranslationService +{ + public function translate( + string $id, + string $extensionName, + array $arguments = null + ): string { + return LocalizationUtility::translate($id, $extensionName, $arguments) ?? ''; + } +} diff --git a/Classes/View/Backend/Menu.php b/Classes/View/Backend/Menu.php new file mode 100644 index 0000000..6478446 --- /dev/null +++ b/Classes/View/Backend/Menu.php @@ -0,0 +1,65 @@ + + * + * 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\CMS\Backend\Template\Components\MenuRegistry; +use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder; +use WerkraumMedia\ThueCat\Controller\Backend\ImportController; +use WerkraumMedia\ThueCat\Controller\Backend\OverviewController; +use WerkraumMedia\ThueCat\Extension; +use WerkraumMedia\ThueCat\Typo3Wrapper\TranslationService; + +class Menu +{ + private TranslationService $translation; + + public function __construct( + TranslationService $translation + ) { + $this->translation = $translation; + } + + public function addMenu( + MenuRegistry $registry, + UriBuilder $uriBuilder, + string $controllerClassName + ): void { + $menu = $registry->makeMenu(); + $menu->setIdentifier('action'); + + $menuItem = $menu->makeMenuItem(); + $menuItem->setTitle($this->translation->translate('module.overview.headline', Extension::EXTENSION_NAME)); + $menuItem->setHref($uriBuilder->reset()->uriFor('index', [], 'Backend\Overview')); + $menuItem->setActive($controllerClassName === OverviewController::class); + $menu->addMenuItem($menuItem); + + $menuItem = $menu->makeMenuItem(); + $menuItem->setTitle($this->translation->translate('module.imports.headline', Extension::EXTENSION_NAME)); + $menuItem->setHref($uriBuilder->reset()->uriFor('index', [], 'Backend\Import')); + $menuItem->setActive($controllerClassName === ImportController::class); + $menu->addMenuItem($menuItem); + + $registry->addMenu($menu); + } +} diff --git a/Configuration/Extbase/Persistence/Classes.php b/Configuration/Extbase/Persistence/Classes.php new file mode 100644 index 0000000..280fbe1 --- /dev/null +++ b/Configuration/Extbase/Persistence/Classes.php @@ -0,0 +1,22 @@ + [ + 'tableName' => 'tx_thuecat_organisation', + ], + \WerkraumMedia\ThueCat\Domain\Model\Backend\Town::class => [ + 'tableName' => 'tx_thuecat_town', + ], + \WerkraumMedia\ThueCat\Domain\Model\Backend\TouristInformation::class => [ + 'tableName' => 'tx_thuecat_tourist_information', + ], + \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration::class => [ + 'tableName' => 'tx_thuecat_import_configuration', + ], + \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog::class => [ + 'tableName' => 'tx_thuecat_import_log', + ], + \WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLogEntry::class => [ + 'tableName' => 'tx_thuecat_import_log_entry', + ], +]; diff --git a/Configuration/FlexForm/ImportConfiguration/Static.xml b/Configuration/FlexForm/ImportConfiguration/Static.xml new file mode 100644 index 0000000..33a7d47 --- /dev/null +++ b/Configuration/FlexForm/ImportConfiguration/Static.xml @@ -0,0 +1,39 @@ + + + 1 + + + + + + LLL:EXT:thuecat/Resources/Private/Language/locallang_flexform.xlf:importConfiguration.static.sheetTitle + + array + + + LLL:EXT:thuecat/Resources/Private/Language/locallang_flexform.xlf:importConfiguration.static.urls +
1
+ array + + + LLL:EXT:thuecat/Resources/Private/Language/locallang_flexform.xlf:importConfiguration.static.url + array + + + + + + input + required,trim + + + + + + +
+
+
+
+
+
diff --git a/Configuration/Services.php b/Configuration/Services.php new file mode 100644 index 0000000..8400cbc --- /dev/null +++ b/Configuration/Services.php @@ -0,0 +1,18 @@ +registerForAutoconfiguration(UrlProvider::class)->addTag('thuecat.urlprovider'); + $containerBuilder->addCompilerPass(new DependencyInjection\UrlProvidersPass('thuecat.urlprovider')); + + $containerBuilder->registerForAutoconfiguration(Converter::class)->addTag('thuecat.converter'); + $containerBuilder->addCompilerPass(new DependencyInjection\ConverterPass('thuecat.converter')); +}; diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml new file mode 100644 index 0000000..7820594 --- /dev/null +++ b/Configuration/Services.yaml @@ -0,0 +1,12 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + WerkraumMedia\ThueCat\: + resource: '../Classes/*' + + WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData: + arguments: + $requestFactory: '@WerkraumMedia\ThueCat\Domain\Import\RequestFactory' diff --git a/Configuration/SiteConfiguration/Overrides/sites.php b/Configuration/SiteConfiguration/Overrides/sites.php index 6dcc6ed..7b392ff 100644 --- a/Configuration/SiteConfiguration/Overrides/sites.php +++ b/Configuration/SiteConfiguration/Overrides/sites.php @@ -1,5 +1,7 @@ [ + 'label' => 'title', + 'default_sortby' => 'title', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + 'title' => $languagePath, + 'enablecolumns' => [ + 'disabled' => 'disable', + ], + 'searchFields' => 'title', + 'rootLevel' => 1, + ], + 'columns' => [ + 'title' => [ + 'label' => $languagePath . '.title', + 'config' => [ + 'type' => 'input', + 'max' => 255, + 'eval' => 'required,trim,unique', + ], + ], + 'type' => [ + 'label' => $languagePath . '.type', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'items' => [ + [ + $languagePath . '.type.static', + 'static', + ], + ], + ], + ], + 'configuration' => [ + 'label' => $languagePath . '.configuration', + 'config' => [ + 'type' => 'flex', + 'ds_pointerField' => 'type', + 'ds' => [ + 'default' => $flexFormConfigurationPath . 'ImportConfiguration/Static.xml', + 'static' => $flexFormConfigurationPath . 'ImportConfiguration/Static.xml', + ], + ], + ], + 'tstamp' => [ + 'config' => [ + 'type' => 'input', + 'renderType' => 'inputDateTime', + 'eval' => 'datetime', + 'readOnly' => true, + ], + ], + ], + 'types' => [ + '0' => [ + 'showitem' => 'title, type, configuration', + ], + ], + ]; +})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_import_configuration'); diff --git a/Configuration/TCA/tx_thuecat_import_log.php b/Configuration/TCA/tx_thuecat_import_log.php new file mode 100644 index 0000000..0126abc --- /dev/null +++ b/Configuration/TCA/tx_thuecat_import_log.php @@ -0,0 +1,57 @@ + [ + 'label' => 'crdate', + 'default_sortby' => 'crdate', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + 'title' => $languagePath, + 'enablecolumns' => [ + 'disabled' => 'disable', + ], + 'rootLevel' => 1, + ], + 'columns' => [ + 'configuration' => [ + 'label' => $languagePath . '.configuration', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'foreign_table' => 'tx_thuecat_import_configuration', + 'readOnly' => true, + ], + ], + 'log_entries' => [ + 'label' => $languagePath . '.log_entries', + 'config' => [ + 'type' => 'inline', + 'foreign_table' => 'tx_thuecat_import_log_entry', + 'foreign_field' => 'import_log', + 'readOnly' => true, + ], + ], + 'crdate' => [ + 'label' => $languagePath . '.crdate', + 'config' => [ + 'type' => 'input', + 'renderType' => 'inputDateTime', + 'eval' => 'datetime', + 'readOnly' => true, + ], + ], + ], + 'types' => [ + '0' => [ + 'showitem' => 'crdate, log_entries, configuration', + ], + ], + ]; +})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_import_log'); diff --git a/Configuration/TCA/tx_thuecat_import_log_entry.php b/Configuration/TCA/tx_thuecat_import_log_entry.php new file mode 100644 index 0000000..533dd63 --- /dev/null +++ b/Configuration/TCA/tx_thuecat_import_log_entry.php @@ -0,0 +1,88 @@ + [ + 'label' => 'table_name', + 'label_alt' => 'record_uid', + 'label_alt_force' => true, + 'default_sortby' => 'title', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + 'title' => $languagePath, + 'enablecolumns' => [ + 'disabled' => 'disable', + ], + 'rootLevel' => 1, + 'hideTable' => true, + ], + 'columns' => [ + 'insertion' => [ + 'label' => $languagePath . '.insertion', + 'config' => [ + 'type' => 'check', + 'renderType' => 'checkboxLabeledToggle', + 'items' => [ + [ + 0 => '', + 1 => '', + 'labelChecked' => $languagePath . '.insertion.yes', + 'labelUnchecked' => $languagePath . '.insertion.no', + ], + ], + 'readOnly' => true, + ], + ], + 'table_name' => [ + 'label' => $languagePath . '.table_name', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'record_uid' => [ + 'label' => $languagePath . '.record_uid', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'errors' => [ + 'label' => $languagePath . '.errors', + 'config' => [ + 'type' => 'text', + 'readOnly' => true, + ], + ], + 'import_log' => [ + 'label' => $languagePath . '.import_log', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'foreign_table' => 'tx_thuecat_import_log', + 'readOnly' => true, + ], + ], + 'crdate' => [ + 'label' => $languagePath . '.crdate', + 'config' => [ + 'type' => 'input', + 'renderType' => 'inputDateTime', + 'eval' => 'datetime', + 'readOnly' => true, + ], + ], + ], + 'types' => [ + '0' => [ + 'showitem' => 'table_name, record_uid, insertion, errors, import_log, crdate', + ], + ], + ]; +})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_import_log_entry'); diff --git a/Configuration/TCA/tx_thuecat_organisation.php b/Configuration/TCA/tx_thuecat_organisation.php new file mode 100644 index 0000000..e10be7e --- /dev/null +++ b/Configuration/TCA/tx_thuecat_organisation.php @@ -0,0 +1,81 @@ + [ + 'label' => 'title', + 'default_sortby' => 'title', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + 'title' => $languagePath, + 'enablecolumns' => [ + 'disabled' => 'disable', + ], + 'searchFields' => 'title', + ], + 'columns' => [ + 'title' => [ + 'label' => $languagePath . '.title', + 'config' => [ + 'type' => 'input', + 'size' => 20, + 'max' => 255, + 'readOnly' => true, + ], + ], + 'description' => [ + 'label' => $languagePath . '.description', + 'config' => [ + 'type' => 'text', + 'readOnly' => true, + ], + ], + 'remote_id' => [ + 'label' => $languagePath . '.remote_id', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'manages_towns' => [ + 'label' => $languagePath . '.manages_towns', + 'config' => [ + 'type' => 'inline', + 'foreign_table' => 'tx_thuecat_town', + 'foreign_field' => 'managed_by', + 'readOnly' => true, + ], + ], + 'manages_tourist_information' => [ + 'label' => $languagePath . '.manages_tourist_information', + 'config' => [ + 'type' => 'inline', + 'foreign_table' => 'tx_thuecat_tourist_information', + 'foreign_field' => 'managed_by', + 'readOnly' => true, + ], + ], + 'tstamp' => [ + 'label' => $languagePath . '.tstamp', + 'config' => [ + 'type' => 'input', + 'renderType' => 'inputDateTime', + 'eval' => 'datetime', + 'readOnly' => true, + ], + ], + ], + 'types' => [ + '0' => [ + 'showitem' => 'title, description, remote_id, tstamp' + . ',--div--;' . $languagePath . '.div.manages' + . ',manages_towns, manages_tourist_information', + ], + ], + ]; +})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_organisation'); diff --git a/Configuration/TCA/tx_thuecat_tourist_information.php b/Configuration/TCA/tx_thuecat_tourist_information.php new file mode 100644 index 0000000..dfa24ce --- /dev/null +++ b/Configuration/TCA/tx_thuecat_tourist_information.php @@ -0,0 +1,82 @@ + [ + 'label' => 'title', + 'default_sortby' => 'title', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + 'title' => $languagePath, + 'enablecolumns' => [ + 'disabled' => 'disable', + ], + 'searchFields' => 'title', + ], + 'columns' => [ + 'title' => [ + 'label' => $languagePath . '.title', + 'config' => [ + 'type' => 'input', + 'size' => 20, + 'max' => 255, + 'readOnly' => true, + ], + ], + 'description' => [ + 'label' => $languagePath . '.description', + 'config' => [ + 'type' => 'text', + 'readOnly' => true, + ], + ], + 'remote_id' => [ + 'label' => $languagePath . '.remote_id', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'town' => [ + 'label' => $languagePath . '.town', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'foreign_table' => 'tx_thuecat_town', + 'items' => [ + [ + $languagePath . '.town.unkown', + 0, + ], + ], + 'readOnly' => true, + ], + ], + 'managed_by' => [ + 'label' => $languagePath . '.managed_by', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'foreign_table' => 'tx_thuecat_organisation', + 'items' => [ + [ + $languagePath . '.managed_by.unkown', + 0, + ], + ], + 'readOnly' => true, + ], + ], + ], + 'types' => [ + '0' => [ + 'showitem' => 'title, description, remote_id, town, managed_by', + ], + ], + ]; +})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_tourist_information'); diff --git a/Configuration/TCA/tx_thuecat_town.php b/Configuration/TCA/tx_thuecat_town.php new file mode 100644 index 0000000..f39e3d1 --- /dev/null +++ b/Configuration/TCA/tx_thuecat_town.php @@ -0,0 +1,76 @@ + [ + 'label' => 'title', + 'default_sortby' => 'title', + 'tstamp' => 'tstamp', + 'crdate' => 'crdate', + 'cruser_id' => 'cruser_id', + 'title' => $languagePath, + 'enablecolumns' => [ + 'disabled' => 'disable', + ], + 'searchFields' => 'title', + ], + 'columns' => [ + 'title' => [ + 'label' => $languagePath . '.title', + 'config' => [ + 'type' => 'input', + 'size' => 20, + 'max' => 255, + 'readOnly' => true, + ], + ], + 'description' => [ + 'label' => $languagePath . '.description', + 'config' => [ + 'type' => 'text', + 'readOnly' => true, + ], + ], + 'remote_id' => [ + 'label' => $languagePath . '.remote_id', + 'config' => [ + 'type' => 'input', + 'readOnly' => true, + ], + ], + 'managed_by' => [ + 'label' => $languagePath . '.managed_by', + 'config' => [ + 'type' => 'select', + 'renderType' => 'selectSingle', + 'foreign_table' => 'tx_thuecat_organisation', + 'items' => [ + [ + $languagePath . '.managed_by.unkown', + 0, + ], + ], + 'readOnly' => true, + ], + ], + 'tourist_information' => [ + 'label' => $languagePath . '.tourist_information', + 'config' => [ + 'type' => 'inline', + 'foreign_table' => 'tx_thuecat_tourist_information', + 'foreign_field' => 'town', + 'readOnly' => true, + ], + ], + ], + 'types' => [ + '0' => [ + 'showitem' => 'title, description, remote_id, tourist_information, managed_by', + ], + ], + ]; +})(\WerkraumMedia\ThueCat\Extension::EXTENSION_KEY, 'tx_thuecat_town'); diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf new file mode 100644 index 0000000..ad9e211 --- /dev/null +++ b/Resources/Private/Language/locallang.xlf @@ -0,0 +1,102 @@ + + + +
+ + + Actions + + + ThüCAT - Overview + + + + Import Configurations + + + None configured + + + Title + + + Last changed + + + create the first to get started.]]> + + + Edit import configuration + + + Create new import configuration + + + Import based on import configuration + + + + Organisations + + + None imported + + + Please provide an import configuration and trigger import to create an organisation. + + + Organisation + + + Towns + + + - + + + Last imported + + + + ThüCAT - Imports + + + No imports + + + No import was executed yet. + + + Created + + + Number of records + + + Configuration + + + Errors + + + Summary + + + Organisation + + + Town + + + Tourist Information + + + + Import finished + + + Imported configuration "%1$s". + + + + diff --git a/Resources/Private/Language/locallang_be.xlf b/Resources/Private/Language/locallang_be.xlf index 9a52e1e..b632daf 100644 --- a/Resources/Private/Language/locallang_be.xlf +++ b/Resources/Private/Language/locallang_be.xlf @@ -1,6 +1,6 @@ - +
diff --git a/Resources/Private/Language/locallang_flexform.xlf b/Resources/Private/Language/locallang_flexform.xlf new file mode 100644 index 0000000..2264517 --- /dev/null +++ b/Resources/Private/Language/locallang_flexform.xlf @@ -0,0 +1,17 @@ + + + +
+ + + Static import configuration + + + URLs + + + URL + + + + diff --git a/Resources/Private/Language/locallang_mod.xlf b/Resources/Private/Language/locallang_mod.xlf new file mode 100644 index 0000000..54e9d2d --- /dev/null +++ b/Resources/Private/Language/locallang_mod.xlf @@ -0,0 +1,17 @@ + + + +
+ + + ThüCat + + + Provides access to current connection, imported data and configuration. + + + ThüCat + + + + diff --git a/Resources/Private/Language/locallang_tca.xlf b/Resources/Private/Language/locallang_tca.xlf new file mode 100644 index 0000000..4445cf7 --- /dev/null +++ b/Resources/Private/Language/locallang_tca.xlf @@ -0,0 +1,133 @@ + + + +
+ + + Organisation + + + Title + + + Description + + + Remote ID + + + Last imported + + + Manages + + + Towns + + + Tourist Information + + + + Tourist Information + + + Title + + + Description + + + Remote ID + + + Town + + + Managed by + + + Unkown + + + + Town + + + Title + + + Description + + + Remote ID + + + Tourist Information + + + Managed by + + + Unkown + + + + Import Configuration + + + Title + + + Type + + + Static list of URLs + + + Configuration + + + + Import Log + + + Used configuration + + + Imported entries + + + Created + + + + Import Log Entry + + + Was inserted or updated + + + Inserted + + + Updated + + + Table name (record type) + + + Record UID + + + Errors (JSON Format) + + + Part of this import log + + + Created + + + + diff --git a/Resources/Private/Templates/Backend/Import/Index.html b/Resources/Private/Templates/Backend/Import/Index.html new file mode 100644 index 0000000..31f6617 --- /dev/null +++ b/Resources/Private/Templates/Backend/Import/Index.html @@ -0,0 +1,54 @@ + + +

{f:translate(id: 'module.imports.headline')}

+ + + + + + {f:render(section: 'Imports', arguments: {imports: imports})} + + + + {f:translate(id: 'module.imports.missing.text')} + + + + + + + + + + + + + + + + + + {f:render(section: 'Import', arguments: {import: import})} + + +
{f:translate(id: 'module.imports.th.created')}{f:translate(id: 'module.imports.th.configuration')}{f:translate(id: 'module.imports.th.amountOfRecords')}{f:translate(id: 'module.imports.th.summary')}{f:translate(id: 'module.imports.th.errors')}
+
+ + + + {import.created -> f:format.date(format: 'd.m.Y H:i:s')} + {import.configuration.title} + {import.entries -> f:count()} + + {f:translate(id: 'module.imports.summary.tableName.{tableName}')} {amount}
+
+ + {error}
+
+ +
+ diff --git a/Resources/Private/Templates/Backend/Overview/Index.html b/Resources/Private/Templates/Backend/Overview/Index.html new file mode 100644 index 0000000..c8ed6b4 --- /dev/null +++ b/Resources/Private/Templates/Backend/Overview/Index.html @@ -0,0 +1,138 @@ + + +

{f:translate(id: 'module.overview.headline')}

+ + + +

+ {f:translate(id: 'module.importConfigurations.headline')} + + {f:icon(identifier: 'actions-document-add')} + +

+ + + {f:render(section: 'ImportConfigurations', arguments: {importConfigurations: importConfigurations})} + + + + {f:translate( + id: 'module.importConfigurations.missing.text', + arguments: { + 0: "{f:uri.newRecord(table: 'tx_thuecat_import_configuration')}" + } + ) -> f:format.raw()} + + + + +

{f:translate(id: 'module.organisations.headline')}

+ + + {f:render(section: 'Organisations', arguments: {organisations: organisations})} + + + {f:translate(id: 'module.organisations.missing.text')} + + + + + + + + + + + + + + + + + + + + + +
{f:translate(id: 'module.importConfigurations.title')}{f:translate(id: 'module.importConfigurations.lastChanged')}{f:translate(id: 'module.actions')}
{importConfiguration.title}{importConfiguration.lastChanged -> f:format.date(format: 'd.m.Y H:i')} + + {f:icon(identifier: 'actions-document-edit')} + + + {f:icon(identifier: 'actions-download')} + +
+
+ + + + + + + + + + + + + + + + + + + + + +
{f:translate(id: 'module.organisation.title')}{f:translate(id: 'module.organisation.towns')}{f:translate(id: 'module.organisation.lastImported')}{f:translate(id: 'module.actions')}
{organisation.title} + {f:render(section: 'Towns', arguments: {towns: organisation.managesTowns})} + {organisation.lastImported -> f:format.date(format: 'd.m.Y H:i')} + + {f:icon(identifier: 'actions-document-edit')} + +
+
+ + + + + {f:translate(id: 'module.organisation.towns.none')} + + + + {town.title} {f:render(section: 'TouristInformation', arguments: {touristInformation: town.touristInformation})} + + + + + ( + + {info.title} + + ) + + diff --git a/Tests/Functional/Domain/Import/ImporterTest.php b/Tests/Functional/Domain/Import/ImporterTest.php new file mode 100644 index 0000000..9140d1f --- /dev/null +++ b/Tests/Functional/Domain/Import/ImporterTest.php @@ -0,0 +1,48 @@ + + * + * 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; + +/** + * @covers WerkraumMedia\ThueCat\Domain\Import\Importer + */ +class ImporterTest extends TestCase +{ + /** + * @test + */ + public function importsNewEntity(): void + { + $command = new CommandTester(); + $command->execute(); + } + + /** + * @test + */ + public function updatesExistingEntity(): void + { + } +} diff --git a/Tests/Unit/Domain/Import/Converter/OrganisationTest.php b/Tests/Unit/Domain/Import/Converter/OrganisationTest.php new file mode 100644 index 0000000..d28d857 --- /dev/null +++ b/Tests/Unit/Domain/Import/Converter/OrganisationTest.php @@ -0,0 +1,91 @@ + + * + * 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 PHPUnit\Framework\TestCase; +use WerkraumMedia\ThueCat\Domain\Import\Converter\Converter; +use WerkraumMedia\ThueCat\Domain\Import\Converter\Organisation; + +/** + * @covers WerkraumMedia\ThueCat\Domain\Import\Converter\Organisation + * @uses WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity + */ +class OrganisationTest extends TestCase +{ + /** + * @test + */ + public function instanceCanBeCreated(): void + { + $subject = new Organisation(); + self::assertInstanceOf(Organisation::class, $subject); + } + + /** + * @test + */ + public function isInstanceOfConverter(): void + { + $subject = new Organisation(); + self::assertInstanceOf(Converter::class, $subject); + } + + /** + * @test + */ + public function canConvertTouristMarketingCompany(): void + { + $subject = new Organisation(); + self::assertTrue($subject->canConvert([ + 'thuecat:TouristMarketingCompany', + 'schema:Thing', + 'ttgds:Organization', + ])); + } + + /** + * @test + */ + public function convertsJsonIdToGenericEntity(): void + { + $subject = new Organisation(); + $entity = $subject->convert([ + '@id' => 'https://example.com/resources/018132452787-ngbe', + 'schema:name' => [ + '@value' => 'Title', + ], + 'schema:description' => [ + '@value' => 'Description', + ], + ]); + + self::assertSame(95, $entity->getTypo3StoragePid()); + self::assertSame('tx_thuecat_organisation', $entity->getTypo3DatabaseTableName()); + self::assertSame('https://example.com/resources/018132452787-ngbe', $entity->getRemoteId()); + self::assertSame([ + 'title' => 'Title', + 'description' => 'Description', + ], $entity->getData()); + } +} diff --git a/Tests/Unit/Domain/Import/Converter/RegistryTest.php b/Tests/Unit/Domain/Import/Converter/RegistryTest.php new file mode 100644 index 0000000..3389a39 --- /dev/null +++ b/Tests/Unit/Domain/Import/Converter/RegistryTest.php @@ -0,0 +1,108 @@ + + * + * 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 PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; +use WerkraumMedia\ThueCat\Domain\Import\Converter\Converter; +use WerkraumMedia\ThueCat\Domain\Import\Converter\Registry; + +/** + * @covers WerkraumMedia\ThueCat\Domain\Import\Converter\Registry + */ +class RegistryTest extends TestCase +{ + use ProphecyTrait; + + /** + * @test + */ + public function canBeCreated(): void + { + $subject = new Registry(); + + self::assertInstanceOf(Registry::class, $subject); + } + + /** + * @test + */ + public function allowsRegistrationOfConverter(): void + { + $subject = new Registry(); + $converter = $this->prophesize(Converter::class); + + $subject->registerConverter($converter->reveal()); + self::assertTrue(true); + } + + /** + * @test + */ + public function returnsConverterForMatchingType(): void + { + $subject = new Registry(); + $converter = $this->prophesize(Converter::class); + $converter->canConvert(['thuecat:Entity'])->willReturn(true); + $subject->registerConverter($converter->reveal()); + + $result = $subject->getConverterBasedOnType(['thuecat:Entity']); + self::assertSame($converter->reveal(), $result); + } + + /** + * @test + */ + public function returnsFirstMatchingConverterForMatchingType(): void + { + $subject = new Registry(); + + $converter1 = $this->prophesize(Converter::class); + $converter1->canConvert(['thuecat:Entity'])->willReturn(true); + $converter2 = $this->prophesize(Converter::class); + $converter2->canConvert(['thuecat:Entity'])->willReturn(true); + + $subject->registerConverter($converter1->reveal()); + $subject->registerConverter($converter2->reveal()); + $result = $subject->getConverterBasedOnType(['thuecat:Entity']); + self::assertSame($converter1->reveal(), $result); + } + + /** + * @test + */ + public function returnsNullForNoMatchingConverter(): void + { + $subject = new Registry(); + + $converter1 = $this->prophesize(Converter::class); + $converter1->canConvert(['thuecat:Entity'])->willReturn(false); + + $subject->registerConverter($converter1->reveal()); + + $result = $subject->getConverterBasedOnType(['thuecat:Entity']); + + self::assertSame(null, $result); + } +} diff --git a/Tests/Unit/Domain/Import/Converter/TouristInformationTest.php b/Tests/Unit/Domain/Import/Converter/TouristInformationTest.php new file mode 100644 index 0000000..496f1e7 --- /dev/null +++ b/Tests/Unit/Domain/Import/Converter/TouristInformationTest.php @@ -0,0 +1,199 @@ + + * + * 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 PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; +use WerkraumMedia\ThueCat\Domain\Import\Converter\Converter; +use WerkraumMedia\ThueCat\Domain\Import\Converter\TouristInformation; +use WerkraumMedia\ThueCat\Domain\Model\Backend\Organisation; +use WerkraumMedia\ThueCat\Domain\Model\Backend\Town; +use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; +use WerkraumMedia\ThueCat\Domain\Repository\Backend\TownRepository; + +/** + * @covers WerkraumMedia\ThueCat\Domain\Import\Converter\TouristInformation + * @uses WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity + */ +class TouristInformationTest extends TestCase +{ + use ProphecyTrait; + + /** + * @test + */ + public function instanceCanBeCreated(): void + { + $organisationRepository = $this->prophesize(OrganisationRepository::class); + $townRepository = $this->prophesize(TownRepository::class); + + $subject = new TouristInformation( + $organisationRepository->reveal(), + $townRepository->reveal() + ); + self::assertInstanceOf(TouristInformation::class, $subject); + } + + /** + * @test + */ + public function isInstanceOfConverter(): void + { + $organisationRepository = $this->prophesize(OrganisationRepository::class); + $townRepository = $this->prophesize(TownRepository::class); + + $subject = new TouristInformation( + $organisationRepository->reveal(), + $townRepository->reveal() + ); + self::assertInstanceOf(Converter::class, $subject); + } + + /** + * @test + */ + public function canConvertTouristMarketingCompany(): void + { + $organisationRepository = $this->prophesize(OrganisationRepository::class); + $townRepository = $this->prophesize(TownRepository::class); + + $subject = new TouristInformation( + $organisationRepository->reveal(), + $townRepository->reveal() + ); + self::assertTrue($subject->canConvert([ + 'thuecat:TouristInformation', + ])); + } + + /** + * @test + */ + public function convertsJsonIdToGenericEntityWithoutRelations(): void + { + $organisationRepository = $this->prophesize(OrganisationRepository::class); + $organisationRepository->findOneByRemoteId('https://example.com/resources/018132452787-xxxx') + ->willReturn(null); + + $townRepository = $this->prophesize(TownRepository::class); + $townRepository->findOneByRemoteIds([ + 'https://example.com/resources/043064193523-jcyt', + 'https://example.com/resources/573211638937-gmqb', + ])->willReturn(null); + + $subject = new TouristInformation( + $organisationRepository->reveal(), + $townRepository->reveal() + ); + $entity = $subject->convert([ + '@id' => 'https://example.com/resources/018132452787-ngbe', + 'thuecat:managedBy' => [ + '@id' => 'https://example.com/resources/018132452787-xxxx', + ], + 'schema:containedInPlace' => [ + [ + '@id' => 'https://example.com/resources/043064193523-jcyt', + ], + [ + '@id' => 'https://example.com/resources/573211638937-gmqb', + ], + ], + 'schema:name' => [ + '@value' => 'Title', + ], + 'schema:description' => [ + [ + '@value' => 'Description', + ], + ], + ]); + + self::assertSame(95, $entity->getTypo3StoragePid()); + self::assertSame('tx_thuecat_tourist_information', $entity->getTypo3DatabaseTableName()); + self::assertSame('https://example.com/resources/018132452787-ngbe', $entity->getRemoteId()); + self::assertSame([ + 'title' => 'Title', + 'description' => 'Description', + 'managed_by' => 0, + 'town' => 0, + ], $entity->getData()); + } + + /** + * @test + */ + public function convertsJsonIdToGenericEntityWithRelations(): void + { + $organisation = $this->prophesize(Organisation::class); + $organisation->getUid()->willReturn(10); + $organisationRepository = $this->prophesize(OrganisationRepository::class); + $organisationRepository->findOneByRemoteId('https://example.com/resources/018132452787-xxxx') + ->willReturn($organisation->reveal()); + + $town = $this->prophesize(Town::class); + $town->getUid()->willReturn(20); + $townRepository = $this->prophesize(TownRepository::class); + $townRepository->findOneByRemoteIds([ + 'https://example.com/resources/043064193523-jcyt', + 'https://example.com/resources/573211638937-gmqb', + ])->willReturn($town->reveal()); + + $subject = new TouristInformation( + $organisationRepository->reveal(), + $townRepository->reveal() + ); + $entity = $subject->convert([ + '@id' => 'https://example.com/resources/018132452787-ngbe', + 'thuecat:managedBy' => [ + '@id' => 'https://example.com/resources/018132452787-xxxx', + ], + 'schema:containedInPlace' => [ + [ + '@id' => 'https://example.com/resources/043064193523-jcyt', + ], + [ + '@id' => 'https://example.com/resources/573211638937-gmqb', + ], + ], + 'schema:name' => [ + '@value' => 'Title', + ], + 'schema:description' => [ + [ + '@value' => 'Description', + ], + ], + ]); + + self::assertSame(95, $entity->getTypo3StoragePid()); + self::assertSame('tx_thuecat_tourist_information', $entity->getTypo3DatabaseTableName()); + self::assertSame('https://example.com/resources/018132452787-ngbe', $entity->getRemoteId()); + self::assertSame([ + 'title' => 'Title', + 'description' => 'Description', + 'managed_by' => 10, + 'town' => 20, + ], $entity->getData()); + } +} diff --git a/Tests/Unit/Domain/Import/Converter/TownTest.php b/Tests/Unit/Domain/Import/Converter/TownTest.php new file mode 100644 index 0000000..b0d4be3 --- /dev/null +++ b/Tests/Unit/Domain/Import/Converter/TownTest.php @@ -0,0 +1,141 @@ + + * + * 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 PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; +use WerkraumMedia\ThueCat\Domain\Import\Converter\Converter; +use WerkraumMedia\ThueCat\Domain\Import\Converter\Town; +use WerkraumMedia\ThueCat\Domain\Model\Backend\Organisation; +use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; + +/** + * @covers WerkraumMedia\ThueCat\Domain\Import\Converter\Town + * @uses WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity + */ +class TownTest extends TestCase +{ + use ProphecyTrait; + + /** + * @test + */ + public function instanceCanBeCreated(): void + { + $organisationRepository = $this->prophesize(OrganisationRepository::class); + + $subject = new Town($organisationRepository->reveal()); + self::assertInstanceOf(Town::class, $subject); + } + + /** + * @test + */ + public function isInstanceOfConverter(): void + { + $organisationRepository = $this->prophesize(OrganisationRepository::class); + + $subject = new Town($organisationRepository->reveal()); + self::assertInstanceOf(Converter::class, $subject); + } + + /** + * @test + */ + public function canConvertTouristMarketingCompany(): void + { + $organisationRepository = $this->prophesize(OrganisationRepository::class); + + $subject = new Town($organisationRepository->reveal()); + self::assertTrue($subject->canConvert([ + 'thuecat:Town', + ])); + } + + /** + * @test + */ + public function convertsJsonIdToGenericEntityWithoutOrganisation(): void + { + $organisationRepository = $this->prophesize(OrganisationRepository::class); + $organisationRepository->findOneByRemoteId('https://example.com/resources/018132452787-xxxx')->willReturn(null); + + $subject = new Town($organisationRepository->reveal()); + $entity = $subject->convert([ + '@id' => 'https://example.com/resources/018132452787-ngbe', + 'thuecat:managedBy' => [ + '@id' => 'https://example.com/resources/018132452787-xxxx', + ], + 'schema:name' => [ + '@value' => 'Title', + ], + 'schema:description' => [ + '@value' => 'Description', + ], + ]); + + self::assertSame(95, $entity->getTypo3StoragePid()); + self::assertSame('tx_thuecat_town', $entity->getTypo3DatabaseTableName()); + self::assertSame('https://example.com/resources/018132452787-ngbe', $entity->getRemoteId()); + self::assertSame([ + 'title' => 'Title', + 'description' => 'Description', + 'managed_by' => 0, + ], $entity->getData()); + } + + /** + * @test + */ + public function convertsJsonIdToGenericEntityWithOrganisation(): void + { + $organisation = $this->prophesize(Organisation::class); + $organisation->getUid()->willReturn(10); + $organisationRepository = $this->prophesize(OrganisationRepository::class); + $organisationRepository->findOneByRemoteId('https://example.com/resources/018132452787-xxxx')->willReturn($organisation->reveal()); + + $subject = new Town($organisationRepository->reveal()); + $entity = $subject->convert([ + '@id' => 'https://example.com/resources/018132452787-ngbe', + 'thuecat:managedBy' => [ + '@id' => 'https://example.com/resources/018132452787-xxxx', + ], + 'schema:name' => [ + '@value' => 'Title', + ], + 'schema:description' => [ + '@value' => 'Description', + ], + ]); + + self::assertSame(95, $entity->getTypo3StoragePid()); + self::assertSame('tx_thuecat_town', $entity->getTypo3DatabaseTableName()); + self::assertSame('https://example.com/resources/018132452787-ngbe', $entity->getRemoteId()); + self::assertSame([ + 'title' => 'Title', + 'description' => 'Description', + 'managed_by' => 10, + ], $entity->getData()); + } +} diff --git a/Tests/Unit/Domain/Import/Importer/FetchDataTest.php b/Tests/Unit/Domain/Import/Importer/FetchDataTest.php new file mode 100644 index 0000000..a6698bd --- /dev/null +++ b/Tests/Unit/Domain/Import/Importer/FetchDataTest.php @@ -0,0 +1,118 @@ + + * + * 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 PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; +use Psr\Http\Client\ClientInterface; +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; +use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; + +/** + * @covers WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData + */ +class FetchDataTest extends TestCase +{ + use ProphecyTrait; + + /** + * @test + */ + public function canBeCreated(): void + { + $requestFactory = $this->prophesize(RequestFactoryInterface::class); + $httpClient = $this->prophesize(ClientInterface::class); + + $subject = new FetchData( + $requestFactory->reveal(), + $httpClient->reveal() + ); + + self::assertInstanceOf(FetchData::class, $subject); + } + + /** + * @test + */ + public function returnsParsedJsonLdBasedOnUrl(): void + { + $requestFactory = $this->prophesize(RequestFactoryInterface::class); + $httpClient = $this->prophesize(ClientInterface::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->getBody()->willReturn('{"@graph":[{"@id":"https://example.com/resources/018132452787-ngbe"}]}'); + + $subject = new FetchData( + $requestFactory->reveal(), + $httpClient->reveal() + ); + + $result = $subject->jsonLDFromUrl('https://example.com/resources/018132452787-ngbe'); + self::assertSame([ + '@graph' => [ + [ + '@id' => 'https://example.com/resources/018132452787-ngbe', + ], + ], + ], $result); + } + + /** + * @test + */ + public function returnsEmptyArrayInCaseOfError(): void + { + $requestFactory = $this->prophesize(RequestFactoryInterface::class); + $httpClient = $this->prophesize(ClientInterface::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->getBody()->willReturn(''); + + $subject = new FetchData( + $requestFactory->reveal(), + $httpClient->reveal() + ); + + $result = $subject->jsonLDFromUrl('https://example.com/resources/018132452787-ngbe'); + self::assertSame([], $result); + } +} diff --git a/Tests/Unit/Domain/Import/ImporterTest.php b/Tests/Unit/Domain/Import/ImporterTest.php new file mode 100644 index 0000000..31a0fca --- /dev/null +++ b/Tests/Unit/Domain/Import/ImporterTest.php @@ -0,0 +1,243 @@ + + * + * 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 PHPUnit\Framework\TestCase; +use Prophecy\Argument; +use Prophecy\PhpUnit\ProphecyTrait; +use WerkraumMedia\ThueCat\Domain\Import\Converter\Converter; +use WerkraumMedia\ThueCat\Domain\Import\Converter\Registry as ConverterRegistry; +use WerkraumMedia\ThueCat\Domain\Import\Importer; +use WerkraumMedia\ThueCat\Domain\Import\Importer\FetchData; +use WerkraumMedia\ThueCat\Domain\Import\Importer\SaveData; +use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; +use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\Registry as UrlProviderRegistry; +use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\UrlProvider; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog; +use WerkraumMedia\ThueCat\Domain\Repository\Backend\ImportLogRepository; + +/** + * @covers WerkraumMedia\ThueCat\Domain\Import\Importer + * @uses WerkraumMedia\ThueCat\Domain\Model\Backend\ImportLog + */ +class ImporterTest extends TestCase +{ + use ProphecyTrait; + + /** + * @test + */ + public function canBeCreated(): void + { + $urls = $this->prophesize(UrlProviderRegistry::class); + $converter = $this->prophesize(ConverterRegistry::class); + $importLogRepository = $this->prophesize(ImportLogRepository::class); + $fetchData = $this->prophesize(FetchData::class); + $saveData = $this->prophesize(SaveData::class); + + $subject = new Importer( + $urls->reveal(), + $converter->reveal(), + $importLogRepository->reveal(), + $fetchData->reveal(), + $saveData->reveal() + ); + self::assertInstanceOf(Importer::class, $subject); + } + + /** + * @test + */ + public function importsNothingIfNoUrlProviderIsGiven(): void + { + $urls = $this->prophesize(UrlProviderRegistry::class); + $urlProvider = $this->prophesize(UrlProvider::class); + $converter = $this->prophesize(ConverterRegistry::class); + $importLogRepository = $this->prophesize(ImportLogRepository::class); + $fetchData = $this->prophesize(FetchData::class); + $saveData = $this->prophesize(SaveData::class); + $configuration = $this->prophesize(ImportConfiguration::class); + + $urls->getProviderForConfiguration($configuration->reveal())->willReturn($urlProvider->reveal()); + $urlProvider->getUrls()->willReturn([]); + $fetchData->jsonLDFromUrl()->shouldNotBeCalled(); + $saveData->import()->shouldNotBeCalled(); + + $subject = new Importer( + $urls->reveal(), + $converter->reveal(), + $importLogRepository->reveal(), + $fetchData->reveal(), + $saveData->reveal() + ); + $subject->importConfiguration($configuration->reveal()); + } + + /** + * @test + */ + public function importsAllUrlsFromAllUrlProvider(): void + { + $urls = $this->prophesize(UrlProviderRegistry::class); + $urlProvider = $this->prophesize(UrlProvider::class); + $converter = $this->prophesize(ConverterRegistry::class); + $concreteConverter = $this->prophesize(Converter::class); + $importLogRepository = $this->prophesize(ImportLogRepository::class); + $fetchData = $this->prophesize(FetchData::class); + $saveData = $this->prophesize(SaveData::class); + $configuration = $this->prophesize(ImportConfiguration::class); + + $entity1 = $this->prophesize(Entity::class); + $entity2 = $this->prophesize(Entity::class); + + $urls->getProviderForConfiguration($configuration->reveal())->willReturn($urlProvider->reveal()); + $urlProvider->getUrls()->willReturn([ + 'https://example.com/resources/34343-ex', + 'https://example.com/resources/34344-es', + ]); + + $fetchData->jsonLDFromUrl('https://example.com/resources/34343-ex')->willReturn(['@graph' => [ + [ + '@id' => 'https://example.com/resources/34343-ex', + '@type' => [ + 'schema:Organization', + 'thuecat:TouristMarketingCompany', + ], + ], + ]]); + $fetchData->jsonLDFromUrl('https://example.com/resources/34344-es')->willReturn(['@graph' => [ + [ + '@id' => 'https://example.com/resources/34344-es', + '@type' => [ + 'schema:Organization', + 'thuecat:TouristMarketingCompany', + ], + ], + ]]); + + $converter->getConverterBasedOnType([ + 'schema:Organization', + 'thuecat:TouristMarketingCompany', + ])->willReturn($concreteConverter->reveal()); + + $concreteConverter->convert(Argument::that(function (array $jsonEntity) { + return $jsonEntity['@id'] === 'https://example.com/resources/34343-ex'; + }))->willReturn($entity1->reveal()); + $concreteConverter->convert(Argument::that(function (array $jsonEntity) { + return $jsonEntity['@id'] === 'https://example.com/resources/34344-es'; + }))->willReturn($entity2->reveal()); + + $saveData->import($entity1->reveal(), Argument::type(ImportLog::class))->shouldBeCalled(); + $saveData->import($entity2->reveal(), Argument::type(ImportLog::class))->shouldBeCalled(); + + $subject = new Importer( + $urls->reveal(), + $converter->reveal(), + $importLogRepository->reveal(), + $fetchData->reveal(), + $saveData->reveal() + ); + $subject->importConfiguration($configuration->reveal()); + } + + /** + * @test + */ + public function handlesMissingConverter(): void + { + $urls = $this->prophesize(UrlProviderRegistry::class); + $urlProvider = $this->prophesize(UrlProvider::class); + $converter = $this->prophesize(ConverterRegistry::class); + $concreteConverter = $this->prophesize(Converter::class); + $importLogRepository = $this->prophesize(ImportLogRepository::class); + $fetchData = $this->prophesize(FetchData::class); + $saveData = $this->prophesize(SaveData::class); + $configuration = $this->prophesize(ImportConfiguration::class); + + $urls->getProviderForConfiguration($configuration->reveal())->willReturn($urlProvider->reveal()); + $urlProvider->getUrls()->willReturn([ + 'https://example.com/resources/34343-ex', + ]); + + $fetchData->jsonLDFromUrl('https://example.com/resources/34343-ex')->willReturn(['@graph' => [ + [ + '@id' => 'https://example.com/resources/34343-ex', + '@type' => [ + 'schema:Organization', + 'thuecat:TouristMarketingCompany', + ], + ], + ]]); + + $converter->getConverterBasedOnType([ + 'schema:Organization', + 'thuecat:TouristMarketingCompany', + ])->willReturn(null); + + $saveData->import()->shouldNotBeCalled(); + + $subject = new Importer( + $urls->reveal(), + $converter->reveal(), + $importLogRepository->reveal(), + $fetchData->reveal(), + $saveData->reveal() + ); + $subject->importConfiguration($configuration->reveal()); + } + + /** + * @test + */ + public function handlesEmptyResponse(): void + { + $urls = $this->prophesize(UrlProviderRegistry::class); + $urlProvider = $this->prophesize(UrlProvider::class); + $converter = $this->prophesize(ConverterRegistry::class); + $concreteConverter = $this->prophesize(Converter::class); + $importLogRepository = $this->prophesize(ImportLogRepository::class); + $fetchData = $this->prophesize(FetchData::class); + $saveData = $this->prophesize(SaveData::class); + $configuration = $this->prophesize(ImportConfiguration::class); + + $urls->getProviderForConfiguration($configuration->reveal())->willReturn($urlProvider->reveal()); + $urlProvider->getUrls()->willReturn([ + 'https://example.com/resources/34343-ex', + ]); + + $fetchData->jsonLDFromUrl('https://example.com/resources/34343-ex')->willReturn([]); + + $converter->getConverterBasedOnType()->shouldNotBeCalled(); + + $subject = new Importer( + $urls->reveal(), + $converter->reveal(), + $importLogRepository->reveal(), + $fetchData->reveal(), + $saveData->reveal() + ); + $subject->importConfiguration($configuration->reveal()); + } +} diff --git a/Tests/Unit/Domain/Import/Model/GenericEntityTest.php b/Tests/Unit/Domain/Import/Model/GenericEntityTest.php new file mode 100644 index 0000000..863285a --- /dev/null +++ b/Tests/Unit/Domain/Import/Model/GenericEntityTest.php @@ -0,0 +1,183 @@ + + * + * 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 PHPUnit\Framework\TestCase; +use WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity; + +/** + * @covers WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity + */ +class GenericEntityTest extends TestCase +{ + /** + * @test + */ + public function canBeCreated(): void + { + $subject = new GenericEntity( + 0, + '', + '', + [] + ); + self::assertInstanceOf(GenericEntity::class, $subject); + } + + /** + * @test + */ + public function returnsTypo3StoragePid(): void + { + $subject = new GenericEntity( + 10, + '', + '', + [] + ); + self::assertSame(10, $subject->getTypo3StoragePid()); + } + + /** + * @test + */ + public function returnsTypo3DatabaseTableName(): void + { + $subject = new GenericEntity( + 0, + 'tx_thuecat_entity', + '', + [] + ); + self::assertSame('tx_thuecat_entity', $subject->getTypo3DatabaseTableName()); + } + + /** + * @test + */ + public function returnsRemoteId(): void + { + $subject = new GenericEntity( + 0, + '', + 'https://example.com/resources/333039283321-xxwg', + [] + ); + self::assertSame( + 'https://example.com/resources/333039283321-xxwg', + $subject->getRemoteId() + ); + } + + /** + * @test + */ + public function returnsData(): void + { + $subject = new GenericEntity( + 0, + '', + '', + [ + 'column_name_1' => 'value 1', + 'column_name_2' => 'value 2', + ] + ); + self::assertSame( + [ + 'column_name_1' => 'value 1', + 'column_name_2' => 'value 2', + ], + $subject->getData() + ); + } + + /** + * @test + */ + public function returnsNotCreatedByDefault(): void + { + $subject = new GenericEntity( + 0, + '', + '', + [] + ); + self::assertSame( + false, + $subject->wasCreated() + ); + } + + /** + * @test + */ + public function returnsZeroAsDefaultTypo3Uid(): void + { + $subject = new GenericEntity( + 0, + '', + '', + [] + ); + self::assertSame( + 0, + $subject->getTypo3Uid() + ); + } + + /** + * @test + */ + public function canBeMarkedAsImported(): void + { + $subject = new GenericEntity( + 0, + '', + '', + [] + ); + + $subject->setImportedTypo3Uid(10); + self::assertSame(true, $subject->wasCreated()); + self::assertSame(10, $subject->getTypo3Uid()); + } + + /** + * @test + */ + public function canBeMarkedAsExisting(): void + { + $subject = new GenericEntity( + 0, + '', + '', + [] + ); + + $subject->setExistingTypo3Uid(10); + self::assertSame(false, $subject->wasCreated()); + self::assertSame(10, $subject->getTypo3Uid()); + } +} diff --git a/Tests/Unit/Domain/Import/RequestFactoryTest.php b/Tests/Unit/Domain/Import/RequestFactoryTest.php new file mode 100644 index 0000000..69e5197 --- /dev/null +++ b/Tests/Unit/Domain/Import/RequestFactoryTest.php @@ -0,0 +1,54 @@ + + * + * 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 PHPUnit\Framework\TestCase; +use WerkraumMedia\ThueCat\Domain\Import\RequestFactory; + +/** + * @covers WerkraumMedia\ThueCat\Domain\Import\RequestFactory + */ +class RequestFactoryTest extends TestCase +{ + /** + * @test + */ + public function canBeCreated(): void + { + $subject = new RequestFactory(); + + self::assertInstanceOf(RequestFactory::class, $subject); + } + + /** + * @test + */ + public function returnsRequestWithJsonIdFormat(): void + { + $subject = new RequestFactory(); + $request = $subject->createRequest('GET', 'https://example.com/resources/333039283321-xxwg'); + + self::assertSame('format=jsonId', $request->getUri()->getQuery()); + } +} diff --git a/Tests/Unit/Domain/Import/UrlProvider/RegistryTest.php b/Tests/Unit/Domain/Import/UrlProvider/RegistryTest.php new file mode 100644 index 0000000..b368137 --- /dev/null +++ b/Tests/Unit/Domain/Import/UrlProvider/RegistryTest.php @@ -0,0 +1,92 @@ + + * + * 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 PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; +use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\Registry; +use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\UrlProvider; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; + +/** + * @covers WerkraumMedia\ThueCat\Domain\Import\UrlProvider\Registry + */ +class RegistryTest extends TestCase +{ + use ProphecyTrait; + + /** + * @test + */ + public function canBeCreated(): void + { + $subject = new Registry(); + + self::assertInstanceOf(Registry::class, $subject); + } + + /** + * @test + */ + public function allowsRegistrationOfUrlProvider(): void + { + $subject = new Registry(); + $provider = $this->prophesize(UrlProvider::class); + + $subject->registerProvider($provider->reveal()); + self::assertTrue(true); + } + + /** + * @test + */ + public function returnsNullIfNoProviderExistsForConfiguration(): void + { + $configuration = $this->prophesize(ImportConfiguration::class); + + $subject = new Registry(); + + $result = $subject->getProviderForConfiguration($configuration->reveal()); + self::assertSame(null, $result); + } + + /** + * @test + */ + public function returnsProviderForConfiguration(): void + { + $configuration = $this->prophesize(ImportConfiguration::class); + + $subject = new Registry(); + + $provider = $this->prophesize(UrlProvider::class); + $concreteProvider = $this->prophesize(UrlProvider::class); + $provider->canProvideForConfiguration($configuration->reveal())->willReturn(true); + $provider->createWithConfiguration($configuration->reveal())->willReturn($concreteProvider->reveal()); + $subject->registerProvider($provider->reveal()); + + $result = $subject->getProviderForConfiguration($configuration->reveal()); + self::assertSame($concreteProvider->reveal(), $result); + } +} diff --git a/Tests/Unit/Domain/Import/UrlProvider/StaticUrlProviderTest.php b/Tests/Unit/Domain/Import/UrlProvider/StaticUrlProviderTest.php new file mode 100644 index 0000000..a9a593b --- /dev/null +++ b/Tests/Unit/Domain/Import/UrlProvider/StaticUrlProviderTest.php @@ -0,0 +1,95 @@ + + * + * 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 PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; +use WerkraumMedia\ThueCat\Domain\Import\UrlProvider\StaticUrlProvider; +use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; + +/** + * @covers WerkraumMedia\ThueCat\Domain\Import\UrlProvider\StaticUrlProvider + */ +class StaticUrlProviderTest extends TestCase +{ + use ProphecyTrait; + + /** + * @test + */ + public function canBeCreated(): void + { + $configuration = $this->prophesize(ImportConfiguration::class); + $configuration->getUrls()->willReturn([]); + + $subject = new StaticUrlProvider($configuration->reveal()); + self::assertInstanceOf(StaticUrlProvider::class, $subject); + } + + /** + * @test + */ + public function canProvideForStaticConfiguration(): void + { + $configuration = $this->prophesize(ImportConfiguration::class); + $configuration->getUrls()->willReturn([]); + $configuration->getType()->willReturn('static'); + + $subject = new StaticUrlProvider($configuration->reveal()); + + $result = $subject->canProvideForConfiguration($configuration->reveal()); + self::assertTrue($result); + } + + /** + * @test + */ + public function returnsConcreteProviderForConfiguration(): void + { + $configuration = $this->prophesize(ImportConfiguration::class); + $configuration->getUrls()->willReturn(['https://example.com']); + + $subject = new StaticUrlProvider($configuration->reveal()); + + $result = $subject->createWithConfiguration($configuration->reveal()); + self::assertInstanceOf(StaticUrlProvider::class, $subject); + } + + /** + * @test + */ + public function concreteProviderReturnsUrls(): void + { + $configuration = $this->prophesize(ImportConfiguration::class); + $configuration->getUrls()->willReturn(['https://example.com']); + + $subject = new StaticUrlProvider($configuration->reveal()); + + $concreteProvider = $subject->createWithConfiguration($configuration->reveal()); + $result = $concreteProvider->getUrls(); + self::assertSame([ + 'https://example.com', + ], $result); + } +} diff --git a/Tests/Unit/ExtensionTest.php b/Tests/Unit/ExtensionTest.php new file mode 100644 index 0000000..fe8239d --- /dev/null +++ b/Tests/Unit/ExtensionTest.php @@ -0,0 +1,42 @@ + + * + * 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 PHPUnit\Framework\TestCase; +use WerkraumMedia\ThueCat\Extension; + +/** + * @covers WerkraumMedia\ThueCat\Extension + * @testdox The extension class + */ +class ExtensionTest extends TestCase +{ + /** + * @test + */ + public function returnsLanguagePath(): void + { + self::assertSame('LLL:EXT:thuecat/Resources/Private/Language/', Extension::getLanguagePath()); + } +} diff --git a/composer.json b/composer.json index fe010a5..9bd886a 100644 --- a/composer.json +++ b/composer.json @@ -15,15 +15,31 @@ "email": "coding@daniel-siepmann.de" } ], + "autoload": { + "psr-4": { + "WerkraumMedia\\ThueCat\\": "Classes/" + } + }, + "autoload-dev": { + "psr-4": { + "WerkraumMedia\\ThueCat\\Tests\\": "Tests/" + } + }, "require": { - "typo3/cms-core": "^10.4" + "php": "^7.4", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "symfony/console": "^5.2", + "typo3/cms-core": "^10.4", + "typo3/cms-extbase": "^10.4" }, "require-dev": { - "phpunit/phpunit": "^9.5", "maglnet/composer-require-checker": "^2.1", "phpspec/prophecy-phpunit": "^2.0", - "typo3/testing-framework": "^6.6", - "symplify/easy-coding-standard": "^9.0" + "phpunit/phpunit": "^9.5", + "symplify/easy-coding-standard": "^9.0", + "typo3/testing-framework": "^6.6" }, "scripts": { "post-autoload-dump": [ diff --git a/ecs.php b/ecs.php index 8c67f1f..9098ea2 100644 --- a/ecs.php +++ b/ecs.php @@ -5,6 +5,7 @@ declare(strict_types=1); use PhpCsFixer\Fixer\ArrayNotation\ArraySyntaxFixer; use PhpCsFixer\Fixer\ArrayNotation\TrailingCommaInMultilineArrayFixer; use PhpCsFixer\Fixer\Import\FullyQualifiedStrictTypesFixer; +use PhpCsFixer\Fixer\Import\NoUnusedImportsFixer; use PhpCsFixer\Fixer\PhpUnit\PhpUnitTestAnnotationFixer; use PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer; use PhpCsFixer\Fixer\StringNotation\SingleQuoteFixer; @@ -17,8 +18,9 @@ return static function (ContainerConfigurator $containerConfigurator): void { $services = $containerConfigurator->services(); $parameters->set(Option::PATHS, [ - __DIR__ . '/Classes', - __DIR__ . '/Tests', + __DIR__ . '/Classes/', + __DIR__ . '/Configuration/', + __DIR__ . '/Tests/', __DIR__ . '/ecs.php', __DIR__ . '/ext_emconf.php', ]); @@ -32,17 +34,20 @@ return static function (ContainerConfigurator $containerConfigurator): void { $parameters->set(Option::SKIP, [ DeclareStrictTypesFixer::class => [ + __DIR__ . '/Configuration/', __DIR__ . '/ext_emconf.php', ], ]); + $services->set(NoUnusedImportsFixer::class); $services->set(FullyQualifiedStrictTypesFixer::class); - $services->set(PhpUnitTestAnnotationFixer::class)->call('configure', [[ - 'style' => 'annotation', - ]]); $services->set(ArraySyntaxFixer::class)->call('configure', [[ 'syntax' => 'short', ]]); $services->set(SingleQuoteFixer::class); $services->set(TrailingCommaInMultilineArrayFixer::class); + + $services->set(PhpUnitTestAnnotationFixer::class)->call('configure', [[ + 'style' => 'annotation', + ]]); }; diff --git a/ext_tables.php b/ext_tables.php new file mode 100644 index 0000000..f338cb8 --- /dev/null +++ b/ext_tables.php @@ -0,0 +1,5 @@ + + + + + + Tests/Unit/ + + + + + + Classes + + + + + + +