From d988d4bd33367347282d37f3d253ecc4d14e1936 Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Mon, 16 Jan 2023 09:09:28 +0100 Subject: [PATCH] WIP|Prevent endless loops --- Classes/Domain/Import/Importer.php | 3 +- .../Typo3Converter/GeneralConverter.php | 43 ++++++++++++++++--- .../Model/Backend/ImportConfiguration.php | 22 +++++++++- .../Model/Backend/RequestedImportType.php | 42 ++++++++++++++++++ Documentation/Maintenance.rst | 1 + Documentation/Maintenance/TYPO3/11.5.rst | 13 ++++++ 6 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 Classes/Domain/Model/Backend/RequestedImportType.php create mode 100644 Documentation/Maintenance/TYPO3/11.5.rst diff --git a/Classes/Domain/Import/Importer.php b/Classes/Domain/Import/Importer.php index fd3f0d4..a7d0799 100644 --- a/Classes/Domain/Import/Importer.php +++ b/Classes/Domain/Import/Importer.php @@ -143,13 +143,14 @@ class Importer } foreach ($urlProvider->getUrls() as $url) { + $this->logger->info('Process url.', ['url' => $url]); $this->importResourceByUrl($url); + $this->logger->info('Finished url.', ['url' => $url]); } } private function importResourceByUrl(string $url): void { - $this->logger->info('Process url.', ['url' => $url]); if ($this->import->handledRemoteId($url)) { $this->logger->notice('Skip Url as we already handled it during import.', ['url' => $url]); return; diff --git a/Classes/Domain/Import/Typo3Converter/GeneralConverter.php b/Classes/Domain/Import/Typo3Converter/GeneralConverter.php index 40613cb..0aecef1 100644 --- a/Classes/Domain/Import/Typo3Converter/GeneralConverter.php +++ b/Classes/Domain/Import/Typo3Converter/GeneralConverter.php @@ -46,6 +46,7 @@ use WerkraumMedia\ThueCat\Domain\Import\Model\Entity; use WerkraumMedia\ThueCat\Domain\Import\Model\GenericEntity; use WerkraumMedia\ThueCat\Domain\Import\ResolveForeignReference; use WerkraumMedia\ThueCat\Domain\Model\Backend\ImportConfiguration; +use WerkraumMedia\ThueCat\Domain\Model\Backend\RequestedImportType; use WerkraumMedia\ThueCat\Domain\Repository\Backend\OrganisationRepository; use WerkraumMedia\ThueCat\Domain\Repository\Backend\ParkingFacilityRepository; use WerkraumMedia\ThueCat\Domain\Repository\Backend\TownRepository; @@ -109,6 +110,14 @@ class GeneralConverter implements Converter Organisation::class => 'tx_thuecat_organisation', ]; + /** + * @var string[] + */ + private $tablesAllowedWithoutManager = [ + 'tx_thuecat_organisation', + 'tx_thuecat_town', + ]; + public function __construct( ResolveForeignReference $resolveForeignReference, Importer $importer, @@ -200,8 +209,11 @@ class GeneralConverter implements Converter return false; } - if ($tableName !== 'tx_thuecat_organisation' && $this->getManagerUid($entity) === '') { - $this->logger->info('Skipped conversion of entity, is not an organisation and no manager was available', [ + if ( + in_array($tableName, $this->tablesAllowedWithoutManager) === false + && $this->getManagerUid($entity) === '' + ) { + $this->logger->info('Skipped conversion of entity, is not an record type that is allowed without manager and no manager was available', [ 'remoteId' => $entity->getId(), ]); return false; @@ -259,19 +271,28 @@ class GeneralConverter implements Converter ]; } - private function getManagerUid(object $entity): string + private function getManagerUid(Minimum $entity): string { + if ($this->importConfiguration->getRequestedImportType()->equals(RequestedImportType::MANAGER)) { + $this->logger->info('Skipped fetching manager uid. We already try to import a manager and do not import managers for managers.', ['url' => $entity->getId()]); + return ''; + } + if ( method_exists($entity, 'getManagedBy') === false || !$entity->getManagedBy() instanceof ForeignReference ) { + $this->logger->info('Skipped fetching manager uid. The entity did not provide a getManagedBy method or the method did not return a ForeignReference.', ['url' => $entity->getId()]); return ''; } + $this->logger->info('Start import for manager.', ['urls' => ResolveForeignReference::convertToRemoteIds([$entity->getManagedBy()])]); $this->importer->importConfiguration( ImportConfiguration::createFromBaseWithForeignReferences( $this->importConfiguration, - [$entity->getManagedBy()] + [$entity->getManagedBy()], + [], + RequestedImportType::MANAGER ) ); $manager = $this->organisationRepository->findOneByRemoteId( @@ -281,20 +302,27 @@ class GeneralConverter implements Converter return $manager ? (string)$manager->getUid() : ''; } - private function getTownUid(object $entity): string + private function getTownUid(Minimum $entity): string { + if ($this->importConfiguration->getRequestedImportType()->equals(RequestedImportType::TOWN)) { + $this->logger->info('Skipped fetching town uid. We already try to import a town and do not import town for town.', ['url' => $entity->getId()]); + return ''; + } if ( $entity instanceof Town || method_exists($entity, 'getContainedInPlaces') === false ) { + $this->logger->info('Skipped fetching town uid. The entity did not provide a getContainedInPlaces method or was a town itself.', ['url' => $entity->getId()]); return ''; } + $this->logger->info('Start import for town.', ['urls' => ResolveForeignReference::convertToRemoteIds($entity->getContainedInPlaces())]); $this->importer->importConfiguration( ImportConfiguration::createFromBaseWithForeignReferences( $this->importConfiguration, $entity->getContainedInPlaces(), - ['thuecat:Town'] + ['thuecat:Town'], + RequestedImportType::TOWN ) ); $town = $this->townRepository->findOneByEntity($entity); @@ -307,6 +335,7 @@ class GeneralConverter implements Converter return []; } + $this->logger->info('Start import for parking facilities near by.', ['urls' => ResolveForeignReference::convertToRemoteIds($entity->getParkingFacilitiesNearBy())]); $this->importer->importConfiguration( ImportConfiguration::createFromBaseWithForeignReferences( $this->importConfiguration, @@ -320,7 +349,7 @@ class GeneralConverter implements Converter } private function getAccessibilitySpecification( - object $entity, + Minimum $entity, string $language ): string { if ( diff --git a/Classes/Domain/Model/Backend/ImportConfiguration.php b/Classes/Domain/Model/Backend/ImportConfiguration.php index 86113b9..621d765 100644 --- a/Classes/Domain/Model/Backend/ImportConfiguration.php +++ b/Classes/Domain/Model/Backend/ImportConfiguration.php @@ -66,11 +66,22 @@ class ImportConfiguration extends AbstractEntity implements ImportConfigurationI /** * @var string[] */ - protected $allowedTypes = []; + private $allowedTypes = []; + + /** + * @var RequestedImportType + */ + private $requestedImportType = null; public function __construct() + { + $this->initializeObject(); + } + + public function initializeObject(): void { $this->logs = new ObjectStorage(); + $this->requestedImportType = new RequestedImportType(); } public function getTitle(): string @@ -142,6 +153,11 @@ class ImportConfiguration extends AbstractEntity implements ImportConfigurationI return $this->allowedTypes; } + public function getRequestedImportType(): RequestedImportType + { + return $this->requestedImportType; + } + public function getSyncScopeId(): string { return $this->getConfigurationValueFromFlexForm('syncScopeId'); @@ -181,12 +197,14 @@ class ImportConfiguration extends AbstractEntity implements ImportConfigurationI public static function createFromBaseWithForeignReferences( self $base, array $foreignReferences, - array $allowedTypes = [] + array $allowedTypes = [], + string $requestedImportType = '' ): self { $configuration = clone $base; $configuration->urls = ResolveForeignReference::convertToRemoteIds($foreignReferences); $configuration->type = 'static'; $configuration->allowedTypes = $allowedTypes; + $configuration->requestedImportType = new RequestedImportType($requestedImportType); return $configuration; } diff --git a/Classes/Domain/Model/Backend/RequestedImportType.php b/Classes/Domain/Model/Backend/RequestedImportType.php new file mode 100644 index 0000000..24a64ad --- /dev/null +++ b/Classes/Domain/Model/Backend/RequestedImportType.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. + */ + +namespace WerkraumMedia\ThueCat\Domain\Model\Backend; + +use TYPO3\CMS\Core\Type\Enumeration; + +/** + * Indicates that a domain specific type was requested to be imported. + * + * This can be used for further checks during import, e.g. abort recursive imports if a manager needs a manager. + */ +class RequestedImportType extends Enumeration +{ + const __default = self::NONE; + + const NONE = ''; + + const MANAGER = 'manager'; + + const TOWN = 'town'; +} diff --git a/Documentation/Maintenance.rst b/Documentation/Maintenance.rst index bc79526..76a2cfb 100644 --- a/Documentation/Maintenance.rst +++ b/Documentation/Maintenance.rst @@ -15,3 +15,4 @@ Those changes are documented so we know what to do once we drop an older version :reversed: Maintenance/PHP/* + Maintenance/TYPO3/* diff --git a/Documentation/Maintenance/TYPO3/11.5.rst b/Documentation/Maintenance/TYPO3/11.5.rst new file mode 100644 index 0000000..0ac9e2a --- /dev/null +++ b/Documentation/Maintenance/TYPO3/11.5.rst @@ -0,0 +1,13 @@ +TYPO3 11.5 +========== + +Changes that should happen once we drop TYPO3 11.5. + +Remove ``initializeObject()`` methods +------------------------------------- + +Those are necessary prior v12 in order to properly initialize none re-constructed +data within Extbase models. +This vanished with v12 where ``makeInstance()`` is used which will call the ``__construct()`` method. + +The content of the method should move to ``__construct()`` and the method should be removed.