From 5dff00210fea41ea1641a765a22889fdaca9e345 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 31 May 2024 13:52:48 +0200 Subject: [PATCH] [TASK] Streamline factory process from glossary build function In order to test a delimitation and simpler function the factory function for glossary was moved to a factory class and covered with testes. --- .../Domain/Repository/GlossaryRepository.php | 265 +++++------------- Classes/Factory/GlossaryFactory.php | 184 ++++++++++++ Configuration/Services.php | 8 + .../Factory/Fixtures/BackendUser.csv | 3 + .../Functional/Factory/Fixtures/Glossary.csv | 18 ++ Tests/Functional/Factory/Fixtures/Pages.csv | 3 + .../Factory/GlossaryFactoryTest.php | 218 ++++++++++++++ composer.json | 1 + 8 files changed, 511 insertions(+), 189 deletions(-) create mode 100644 Classes/Factory/GlossaryFactory.php create mode 100644 Tests/Functional/Factory/Fixtures/BackendUser.csv create mode 100644 Tests/Functional/Factory/Fixtures/Glossary.csv create mode 100644 Tests/Functional/Factory/Fixtures/Pages.csv create mode 100644 Tests/Functional/Factory/GlossaryFactoryTest.php diff --git a/Classes/Domain/Repository/GlossaryRepository.php b/Classes/Domain/Repository/GlossaryRepository.php index fbef837c..8f961d05 100644 --- a/Classes/Domain/Repository/GlossaryRepository.php +++ b/Classes/Domain/Repository/GlossaryRepository.php @@ -7,119 +7,33 @@ use DeepL\GlossaryInfo; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\Exception; -use TYPO3\CMS\Backend\Configuration\TranslationConfigurationProvider; -use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Database\Connection; use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Domain\Repository\PageRepository; use TYPO3\CMS\Core\Exception\SiteNotFoundException; -use TYPO3\CMS\Core\Site\Entity\Site; use TYPO3\CMS\Core\Site\SiteFinder; use TYPO3\CMS\Core\Utility\GeneralUtility; -use WebVision\WvDeepltranslate\Service\DeeplGlossaryService; +use WebVision\WvDeepltranslate\Factory\GlossaryFactory; // @todo Consider to rename/move this as service class. final class GlossaryRepository { + private ConnectionPool $connectionPool; + + public function __construct( + ConnectionPool $connectionPool + ) { + $this->connectionPool = $connectionPool; + } + /** - * @return array - * }> - * - * @throws DBALException - * @throws Exception - * @throws SiteNotFoundException - * @throws \Doctrine\DBAL\Exception + * @deprecated and will be removed with later version, please use see WebVision\WvDeepltranslate\Factory\GlossaryFactory::createGlossaryInformation() */ public function getGlossaryInformationForSync(int $pageId): array { - $glossaries = []; - $localizationArray = []; - - $page = BackendUtility::getRecord( - 'pages', - $pageId - ); - - $entries = $this->getOriginalEntries($pageId); - $localizationLanguageIds = $this->getAvailableLocalizations($pageId); - $site = GeneralUtility::makeInstance(SiteFinder::class) - ->getSiteByPageId($pageId); - $sourceLangIsoCode = $site->getDefaultLanguage()->getTwoLetterIsoCode(); - - $localizationArray[$sourceLangIsoCode] = $entries; - - // fetch all language information available for building all glossaries - foreach ($localizationLanguageIds as $localizationLanguageId) { - $localizedEntries = $this->getLocalizedEntries($pageId, $localizationLanguageId); - $targetLanguageIsoCode = $this->getTargetLanguageIsoCode($site, $localizationLanguageId); - $localizationArray[$targetLanguageIsoCode] = $localizedEntries; - } - - $availableLanguagePairs = GeneralUtility::makeInstance(DeeplGlossaryService::class) - ->getPossibleGlossaryLanguageConfig(); - - foreach ($availableLanguagePairs as $sourceLang => $availableTargets) { - // no entry to possible source in the current page - if (!isset($localizationArray[$sourceLang])) { - continue; - } - - foreach ($availableTargets as $targetLang) { - // target isn't configured in the current page - if (!isset($localizationArray[$targetLang])) { - continue; - } - - // target is site default, continue - if ($targetLang === $sourceLangIsoCode) { - continue; - } - - $glossaryInformation = $this->getGlossaryBySourceAndTargetForSync( - $sourceLang, - $targetLang, - $page - ); - $glossaryInformation['source_lang'] = $sourceLang; - $glossaryInformation['target_lang'] = $targetLang; - - $entries = []; - foreach ($localizationArray[$sourceLang] as $entryId => $sourceEntry) { - // no source target pair, next - if (!isset($localizationArray[$targetLang][$entryId])) { - continue; - } - $entries[] = [ - 'source' => $sourceEntry['term'], - 'target' => $localizationArray[$targetLang][$entryId]['term'], - ]; - } - // no pairs detected - if (count($entries) == 0) { - continue; - } - // remove duplicates - $sources = []; - foreach ($entries as $position => $entry) { - if (in_array($entry['source'], $sources)) { - unset($entries[$position]); - continue; - } - $sources[] = $entry['source']; - } - - // reset entries keys - $glossaryInformation['entries'] = array_values($entries); - $glossaries[] = $glossaryInformation; - } - } - - return $glossaries; + /** @var GlossaryFactory $glossaryFactory */ + $glossaryFactory = GeneralUtility::makeInstance(GlossaryFactory::class); + return $glossaryFactory->createGlossaryInformation($pageId); } /** @@ -128,15 +42,12 @@ public function getGlossaryInformationForSync(int $pageId): array */ public function findByGlossaryId(string $glossaryId): ?array { - $db = GeneralUtility::makeInstance(ConnectionPool::class) - ->getConnectionForTable('tx_wvdeepltranslate_glossary'); + $connection = $this->connectionPool->getConnectionForTable('tx_wvdeepltranslate_glossary'); - $result = $db->select( + $result = $connection->select( ['*'], 'tx_wvdeepltranslate_glossary', - [ - 'glossary_id' => $glossaryId, - ], + ['glossary_id' => $glossaryId], [], [], 1 @@ -153,10 +64,9 @@ public function updateLocalGlossary(GlossaryInfo $information, int $uid): void 'glossary_lastsync' => $information->creationTime->getTimestamp(), ]; - $db = GeneralUtility::makeInstance(ConnectionPool::class) - ->getConnectionForTable('tx_wvdeepltranslate_glossary'); + $connection = $this->connectionPool->getConnectionForTable('tx_wvdeepltranslate_glossary'); - $db->update( + $connection->update( 'tx_wvdeepltranslate_glossary', $insertParams, [ @@ -171,16 +81,16 @@ public function updateLocalGlossary(GlossaryInfo $information, int $uid): void */ public function findAllGlossaries(): array { - $db = GeneralUtility::makeInstance(ConnectionPool::class) + $connection = GeneralUtility::makeInstance(ConnectionPool::class) ->getConnectionForTable('pages'); $identifiers = [ 'module' => 'glossary', - 'doktype' => 254, + 'doktype' => PageRepository::DOKTYPE_SYSFOLDER, 'sys_language_uid' => 0, ]; - return $db->select( + return $connection->select( ['uid'], 'pages', $identifiers @@ -213,14 +123,18 @@ public function getGlossaryBySourceAndTarget( 'glossary_lastsync' => 0, 'glossary_ready' => 0, ]; + if (empty($page)) { return $defaultGlossary; } + $lowerSourceLang = strtolower($sourceLanguage); $lowerTargetLang = strtolower($targetLanguage); + if (strlen($lowerTargetLang) > 2) { $lowerTargetLang = substr($lowerTargetLang, 0, 2); } + return $this->getGlossary( $lowerSourceLang, $lowerTargetLang, @@ -270,10 +184,9 @@ public function getGlossaryBySourceAndTargetForSync( 'target_lang' => $lowerTargetLang, 'pid' => $page['uid'], ]; - $db = GeneralUtility::makeInstance(ConnectionPool::class) - ->getConnectionForTable('tx_wvdeepltranslate_glossary'); - $db->insert('tx_wvdeepltranslate_glossary', $insert); - $lastInsertId = $db->lastInsertId('tx_wvdeepltranslate_glossary'); + $connection = $this->connectionPool->getConnectionForTable('tx_wvdeepltranslate_glossary'); + $connection->insert('tx_wvdeepltranslate_glossary', $insert); + $lastInsertId = $connection->lastInsertId('tx_wvdeepltranslate_glossary'); $insert['uid'] = $lastInsertId; unset($insert['pid']); return $insert; @@ -284,10 +197,9 @@ public function getGlossaryBySourceAndTargetForSync( public function removeGlossarySync(string $glossaryId): bool { - $db = GeneralUtility::makeInstance(ConnectionPool::class) - ->getConnectionForTable('tx_wvdeepltranslate_glossary'); + $connection = $this->connectionPool->getConnectionForTable('tx_wvdeepltranslate_glossary'); - $count = $db->update( + $count = $connection->update( 'tx_wvdeepltranslate_glossary', [ 'glossary_id' => '', @@ -304,19 +216,20 @@ public function removeGlossarySync(string $glossaryId): bool /** * @return array + * * @throws Exception * @throws \Doctrine\DBAL\Exception * @throws DBALException */ public function getGlossariesDeeplConnected(): array { - $db = GeneralUtility::makeInstance(ConnectionPool::class) + $queryBuilder = $this->connectionPool ->getQueryBuilderForTable('tx_wvdeepltranslate_glossary'); - $statement = $db + $statement = $queryBuilder ->select('uid', 'glossary_id') ->from('tx_wvdeepltranslate_glossary') ->where( - $db->expr()->neq('glossary_id', $db->createNamedParameter('')) + $queryBuilder->expr()->neq('glossary_id', $queryBuilder->createNamedParameter('')) ); $result = $statement->executeQuery()->fetchAssociative(); @@ -333,27 +246,27 @@ public function getGlossariesDeeplConnected(): array * @throws \Doctrine\DBAL\Exception * @throws DBALException */ - private function getOriginalEntries(int $pageId): array + public function getOriginalEntries(int $pageId): array { - $db = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('tx_wvdeepltranslate_glossaryentry'); - $statement = $db + $queryBuilder = $this->connectionPool->getQueryBuilderForTable('tx_wvdeepltranslate_glossaryentry'); + $statement = $queryBuilder ->select('uid', 'term') ->from('tx_wvdeepltranslate_glossaryentry') ->where( - $db->expr()->eq( + $queryBuilder->expr()->eq( 'pid', - $db->createNamedParameter($pageId, Connection::PARAM_INT) + $queryBuilder->createNamedParameter($pageId, Connection::PARAM_INT) ), - $db->expr()->eq( + $queryBuilder->expr()->eq( 'sys_language_uid', - $db->createNamedParameter(0, Connection::PARAM_INT) + $queryBuilder->createNamedParameter(0, Connection::PARAM_INT) ) ); $entries = []; foreach ($statement->executeQuery()->fetchAllAssociative() ?: [] as $entry) { $entries[$entry['uid']] = $entry; } + return $entries; } @@ -363,21 +276,21 @@ private function getOriginalEntries(int $pageId): array * @throws \Doctrine\DBAL\Exception * @throws DBALException */ - private function getLocalizedEntries(int $pageId, int $languageId): array + public function getLocalizedEntries(int $pageId, int $languageId): array { - $db = GeneralUtility::makeInstance(ConnectionPool::class) + $queryBuilder = $this->connectionPool ->getQueryBuilderForTable('tx_wvdeepltranslate_glossaryentry'); - $statement = $db + $statement = $queryBuilder ->select('uid', 'term', 'l10n_parent') ->from('tx_wvdeepltranslate_glossaryentry') ->where( - $db->expr()->eq( + $queryBuilder->expr()->eq( 'pid', - $db->createNamedParameter($pageId, Connection::PARAM_INT) + $queryBuilder->createNamedParameter($pageId, Connection::PARAM_INT) ), - $db->expr()->eq( + $queryBuilder->expr()->eq( 'sys_language_uid', - $db->createNamedParameter($languageId, Connection::PARAM_INT) + $queryBuilder->createNamedParameter($languageId, Connection::PARAM_INT) ) ); @@ -385,32 +298,8 @@ private function getLocalizedEntries(int $pageId, int $languageId): array foreach ($statement->executeQuery()->fetchAllAssociative() as $localizedEntry) { $localizedEntries[$localizedEntry['l10n_parent']] = $localizedEntry; } - return $localizedEntries; - } - /** - * @return array - */ - private function getAvailableLocalizations(int $pageId): array - { - $translations = GeneralUtility::makeInstance(TranslationConfigurationProvider::class) - ->translationInfo('pages', $pageId); - - // Error string given, if not matching. Return an empty array then - if (!is_array($translations)) { - return []; - } - $availableTranslations = []; - foreach ($translations['translations'] as $translation) { - $availableTranslations[] = $translation['sys_language_uid']; - } - - return $availableTranslations; - } - - protected function getTargetLanguageIsoCode(Site $site, int $languageId): string - { - return $site->getLanguageById($languageId)->getTwoLetterIsoCode(); + return $localizedEntries; } /** @@ -431,34 +320,31 @@ private function getGlossary( int $pageUid, bool $recursive = false ): ?array { - $db = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('tx_wvdeepltranslate_glossary'); + $queryBuilder = $this->connectionPool->getQueryBuilderForTable('tx_wvdeepltranslate_glossary'); + + $constrains = [ + $queryBuilder->expr()->eq('source_lang', $queryBuilder->createNamedParameter($sourceLanguage)), + $queryBuilder->expr()->eq('target_lang', $queryBuilder->createNamedParameter($targetLanguage)), + ]; - $pidConstraint = null; if ($recursive === true) { $glossaryPages = $this->getGlossariesInRootByCurrentPage($pageUid); if (count($glossaryPages) > 0) { - $pidConstraint = $db->expr()->in('pid', $glossaryPages); + $constrains[] = $queryBuilder->expr()->in('pid', $glossaryPages); } } else { - $pidConstraint = $db->expr()->eq('pid', $db->createNamedParameter($pageUid, Connection::PARAM_INT)); + $constrains[] = $queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pageUid, Connection::PARAM_INT)); } - $where = $db->expr()->and( - $db->expr()->eq('source_lang', $db->createNamedParameter($sourceLanguage)), - $db->expr()->eq('target_lang', $db->createNamedParameter($targetLanguage)), - $pidConstraint - ); - $statement = $db - ->select( - 'uid', - 'glossary_id', - 'glossary_name', - 'glossary_lastsync', - 'glossary_ready', - ) + $statement = $queryBuilder->select( + 'uid', + 'glossary_id', + 'glossary_name', + 'glossary_lastsync', + 'glossary_ready', + ) ->from('tx_wvdeepltranslate_glossary') - ->where($where); + ->where(...$constrains); return $statement->executeQuery()->fetchAssociative() ?: null; } @@ -473,17 +359,19 @@ private function getGlossariesInRootByCurrentPage(int $pageId): array $site = GeneralUtility::makeInstance(SiteFinder::class) ->getSiteByPageId($pageId); $rootPage = $site->getRootPageId(); + $allPages = GeneralUtility::makeInstance(PageTreeRepository::class) ->getTreeList($rootPage, 999); - $db = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages'); - $statement = $db + + $queryBuilder = $this->connectionPool->getQueryBuilderForTable('pages'); + + $statement = $queryBuilder ->select('uid') ->from('pages') ->where( - $db->expr()->in('uid', $allPages), - $db->expr()->eq('doktype', $db->createNamedParameter(254, Connection::PARAM_INT)), - $db->expr()->eq('module', $db->createNamedParameter('glossary')) + $queryBuilder->expr()->in('uid', $allPages), + $queryBuilder->expr()->eq('doktype', $queryBuilder->createNamedParameter(PageRepository::DOKTYPE_SYSFOLDER, Connection::PARAM_INT)), + $queryBuilder->expr()->eq('module', $queryBuilder->createNamedParameter('glossary')) ); $result = $statement->executeQuery()->fetchAllAssociative(); @@ -499,8 +387,7 @@ private function getGlossariesInRootByCurrentPage(int $pageId): array public function setGlossaryNotSyncOnPage(int $pageId): void { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('tx_wvdeepltranslate_glossary'); + $queryBuilder = $this->connectionPool->getQueryBuilderForTable('tx_wvdeepltranslate_glossary'); $queryBuilder->update('tx_wvdeepltranslate_glossary') ->set('glossary_ready', 0) diff --git a/Classes/Factory/GlossaryFactory.php b/Classes/Factory/GlossaryFactory.php new file mode 100644 index 00000000..6ee848d9 --- /dev/null +++ b/Classes/Factory/GlossaryFactory.php @@ -0,0 +1,184 @@ +siteFinder = $siteFinder; + $this->glossaryRepository = $glossaryRepository; + $this->deeplGlossaryService = $deeplGlossaryService; + } + + /** + * @param int $pageId + * @return array + * }> + * + * @throws Exception + * @throws \Doctrine\DBAL\Exception + * @throws SiteNotFoundException + */ + public function createGlossaryInformation(int $pageId): array + { + $glossaries = []; + $localizationArray = []; + + $page = BackendUtility::getRecord('pages', $pageId, '*'); + if ($page['module'] !== 'glossary') { + throw new \RuntimeException('', 1716556217634); + } + + $availableLanguagePairs = $this->deeplGlossaryService->getPossibleGlossaryLanguageConfig(); + $sourceLangIsoCode = $this->getDefaultLanguageCode($pageId); + + $entries = $this->glossaryRepository->getOriginalEntries($pageId); + + $localizationArray[$sourceLangIsoCode] = $entries; + + $localizationLanguageIds = $this->getAvailableLocalizations($pageId); + // fetch all language information available for building all glossaries + foreach ($localizationLanguageIds as $localizationLanguageId) { + $localizedEntries = $this->glossaryRepository->getLocalizedEntries($pageId, $localizationLanguageId); + $targetLanguageIsoCode = $this->getTargetLanguageCode($pageId, $localizationLanguageId); + $localizationArray[$targetLanguageIsoCode] = $localizedEntries; + } + + foreach ($availableLanguagePairs as $sourceLang => $availableTargets) { + // no entry to possible source in the current page + if (!isset($localizationArray[$sourceLang])) { + continue; + } + + foreach ($availableTargets as $targetLang) { + // target isn't configured in the current page + if (!isset($localizationArray[$targetLang])) { + continue; + } + + // target is site default, continue + if ($targetLang === $sourceLangIsoCode) { + continue; + } + + $glossaryInformation = $this->glossaryRepository->getGlossaryBySourceAndTargetForSync( + $sourceLang, + $targetLang, + $page + ); + $glossaryInformation['source_lang'] = $sourceLang; + $glossaryInformation['target_lang'] = $targetLang; + + $entries = []; + foreach ($localizationArray[$sourceLang] as $entryId => $sourceEntry) { + // no source target pair, next + if (!isset($localizationArray[$targetLang][$entryId])) { + continue; + } + $entries[] = [ + 'source' => $sourceEntry['term'], + 'target' => $localizationArray[$targetLang][$entryId]['term'], + ]; + } + // no pairs detected + if (count($entries) == 0) { + continue; + } + + // remove duplicates + $sources = []; + foreach ($entries as $position => $entry) { + if (in_array($entry['source'], $sources)) { + unset($entries[$position]); + continue; + } + $sources[] = $entry['source']; + } + + // reset entries keys + $glossaryInformation['entries'] = array_values($entries); + $glossaries[] = $glossaryInformation; + } + } + + return $glossaries; + } + + /** + * @return array + */ + private function getAvailableLocalizations(int $pageId): array + { + $translations = GeneralUtility::makeInstance(TranslationConfigurationProvider::class) + ->translationInfo('pages', $pageId); + + // Error string given, if not matching. Return an empty array then + if (!is_array($translations)) { + return []; + } + + $availableTranslations = []; + foreach ($translations['translations'] as $translation) { + $availableTranslations[] = $translation['sys_language_uid']; + } + + return $availableTranslations; + } + + protected function getTargetLanguageCode(int $pageId, int $languageId): string + { + $site = $this->siteFinder->getSiteByPageId($pageId); + $typo3Version = new Typo3Version(); + if ($typo3Version->getMajorVersion() < 12) { + $targetLangIsoCode = $site->getLanguageById($languageId)->getTwoLetterIsoCode(); + } else { + $targetLangIsoCode = $site->getLanguageById($languageId)->getLocale()->getLanguageCode(); + } + + return $targetLangIsoCode; + } + + private function getDefaultLanguageCode(int $pageId): string + { + $site = $this->siteFinder->getSiteByPageId($pageId); + $typo3Version = new Typo3Version(); + if ($typo3Version->getMajorVersion() < 12) { + $sourceLangIsoCode = $site->getDefaultLanguage()->getTwoLetterIsoCode(); + } else { + $sourceLangIsoCode = $site->getDefaultLanguage()->getLocale()->getLanguageCode(); + } + return $sourceLangIsoCode; + } +} diff --git a/Configuration/Services.php b/Configuration/Services.php index 7f23e1e2..ff4d44b7 100644 --- a/Configuration/Services.php +++ b/Configuration/Services.php @@ -16,8 +16,10 @@ use WebVision\WvDeepltranslate\Command\GlossarySyncCommand; use WebVision\WvDeepltranslate\Controller\Backend\AjaxController; use WebVision\WvDeepltranslate\Controller\GlossarySyncController; +use WebVision\WvDeepltranslate\Domain\Repository\GlossaryRepository; use WebVision\WvDeepltranslate\Event\Listener\GlossarySyncButtonProvider; use WebVision\WvDeepltranslate\Event\Listener\UsageToolBarEventListener; +use WebVision\WvDeepltranslate\Factory\GlossaryFactory; use WebVision\WvDeepltranslate\Form\Item\SiteConfigSupportedLanguageItemsProcFunc; use WebVision\WvDeepltranslate\Hooks\Glossary\UpdatedGlossaryEntryTermHook; use WebVision\WvDeepltranslate\Hooks\TranslateHook; @@ -107,6 +109,12 @@ $services ->set(GlossarySyncController::class) ->public(); + $services + ->set(GlossaryRepository::class) + ->public(); + $services + ->set(GlossaryFactory::class) + ->public(); $services->alias(ClientInterface::class, Client::class); diff --git a/Tests/Functional/Factory/Fixtures/BackendUser.csv b/Tests/Functional/Factory/Fixtures/BackendUser.csv new file mode 100644 index 00000000..4fe109c3 --- /dev/null +++ b/Tests/Functional/Factory/Fixtures/BackendUser.csv @@ -0,0 +1,3 @@ +be_users,,,,, +,uid,pid,username,password,admin +,2,0,"Deepl-Functional-Test BeUser","123",1 \ No newline at end of file diff --git a/Tests/Functional/Factory/Fixtures/Glossary.csv b/Tests/Functional/Factory/Fixtures/Glossary.csv new file mode 100644 index 00000000..f9c86808 --- /dev/null +++ b/Tests/Functional/Factory/Fixtures/Glossary.csv @@ -0,0 +1,18 @@ +pages,,,,,,,, +,uid,pid,is_siteroot,doktype,title,module,sys_language_uid,l10n_parent +,5,1,1,245,"DeepL-Glossary","glossary",0,0 +,6,1,1,245,"DeepL-Glossary Deutsch","glossary",1,5 +,7,1,1,245,"DeepL-Glossary Polish","glossary",2,5 +,8,1,1,245,"DeepL-Glossary Spanish","glossary",3,5 +,9,1,1,245,"DeepL-Glossary French","glossary",4,5 +,10,1,1,245,"DeepL-Glossary Italian","glossary",5,5 +,11,1,1,245,"DeepL-Glossary Dutch","glossary",6,5 +tx_wvdeepltranslate_glossaryentry,,,,, +,uid,pid,hidden,term,sys_language_uid,l10n_parent +,1,5,0,"Hello World Default",0,0 +,2,5,0,"Hallo Welt Deutsch",1,1 +,3,5,0,"Hello World Polish",2,1 +,4,5,0,"Hello World Spanish",3,1 +,5,5,0,"Hello World French",4,1 +,6,5,0,"Hello World Italian",5,1 +,7,5,0,"Hello World Dutch",6,1 \ No newline at end of file diff --git a/Tests/Functional/Factory/Fixtures/Pages.csv b/Tests/Functional/Factory/Fixtures/Pages.csv new file mode 100644 index 00000000..284e3cc3 --- /dev/null +++ b/Tests/Functional/Factory/Fixtures/Pages.csv @@ -0,0 +1,3 @@ +pages,,,,, +,uid,pid,is_siteroot,doktype,title, +,1,0,1,1,"DeepL-Functional-Tests" diff --git a/Tests/Functional/Factory/GlossaryFactoryTest.php b/Tests/Functional/Factory/GlossaryFactoryTest.php new file mode 100644 index 00000000..75385fac --- /dev/null +++ b/Tests/Functional/Factory/GlossaryFactoryTest.php @@ -0,0 +1,218 @@ + [ + 'id' => 0, + 'title' => 'English', + 'locale' => 'en_US.UTF-8', + 'iso' => 'en', + 'hrefLang' => 'en-US', + 'direction' => '', + 'custom' => [ + 'deeplTargetLanguage' => '', + ], + ], + // de + 'DE' => [ + 'id' => 1, + 'title' => 'Deutsch', + 'locale' => 'de_DE', + 'hrefLang' => 'de-DE', + 'navigationTitle' => 'Deutsch', + 'flag' => 'de', + 'custom' => [ + 'deeplTargetLanguage' => 'DE', + ], + ], + // pl + 'PL' => [ + 'id' => 2, + 'title' => 'Polish', + 'locale' => 'pl_PL', + 'hrefLang' => 'pl-PL', + 'navigationTitle' => 'Polski', + 'flag' => 'pl', + 'custom' => [ + 'deeplTargetLanguage' => 'PL', + ], + ], + // es + 'ES' => [ + 'id' => 3, + 'title' => 'Spanish', + 'locale' => 'es_ES', + 'hrefLang' => 'es-ES', + 'navigationTitle' => 'Español', + 'flag' => 'es', + 'custom' => [ + 'deeplTargetLanguage' => 'ES', + ], + ], + // fr + 'FR' => [ + 'id' => 4, + 'title' => 'French', + 'locale' => 'fr_FR', + 'hrefLang' => 'de-DE', + 'navigationTitle' => 'Français', + 'flag' => 'fr', + 'custom' => [ + 'deeplTargetLanguage' => 'FR', + ], + ], + // it + 'IT' => [ + 'id' => 5, + 'title' => 'Italian', + 'locale' => 'it_IT', + 'hrefLang' => 'it-IT', + 'navigationTitle' => 'Italiano', + 'flag' => 'it', + 'custom' => [ + 'deeplTargetLanguage' => 'IT', + ], + ], + // nl + 'NL' => [ + 'id' => 6, + 'title' => 'Dutch', + 'locale' => 'nl_NL', + 'hrefLang' => 'nl-NL', + 'navigationTitle' => 'Nederlands', + 'flag' => 'nl', + 'custom' => [ + 'deeplTargetLanguage' => 'IT', + ], + ], + ]; + + protected function setUp(): void + { + $this->configurationToUseInTestInstance = array_merge( + $this->configurationToUseInTestInstance, + require __DIR__ . '/../Fixtures/ExtensionConfig.php' + ); + + parent::setUp(); + + $this->importCSVDataSet(__DIR__ . '/Fixtures/Pages.csv'); + + $this->writeSiteConfiguration( + 'acme', + $this->buildSiteConfiguration(1, '/', 'Home'), + [ + $this->buildDefaultLanguageConfiguration('EN', '/'), + $this->buildLanguageConfiguration('DE', '/de/', ['EN'], 'strict'), + $this->buildLanguageConfiguration('PL', '/pl/', ['EN'], 'strict'), + $this->buildLanguageConfiguration('ES', '/es/', ['EN'], 'strict'), + $this->buildLanguageConfiguration('FR', '/fr/', ['EN'], 'strict'), + $this->buildLanguageConfiguration('IT', '/it/', ['EN'], 'strict'), + $this->buildLanguageConfiguration('NL', '/nl/', ['EN'], 'strict'), + ] + ); + $this->setUpFrontendRootPage(1, [], []); + + $this->importCSVDataSet(__DIR__ . '/Fixtures/Glossary.csv'); + $this->importCSVDataSet(__DIR__ . '/Fixtures/BackendUser.csv'); + $this->setUpBackendUser(2); + } + + /** + * @test + */ + public function createGlossaryInformation(): void + { + /** @var GlossaryFactory $subject */ + $subject = GeneralUtility::makeInstance(GlossaryFactory::class); + $glossaries = $subject->createGlossaryInformation(5); + + static::assertCount(8, $glossaries); + $glossary = $glossaries[0]; + static::assertArraySubset($glossary, [ + 'glossary_name' => 'DeepL-Glossary: de => fr', + 'glossary_id' => '', + 'glossary_lastsync' => 0, + 'glossary_ready' => 0, + 'source_lang' => 'de', + 'target_lang' => 'fr', + 'uid' => 1, + 'entries' => [ + 0 => [ + 'source' => 'Hallo Welt Deutsch', + 'target' => 'Hello World French', + ], + ], + ]); + } + + public static function glossaryLanguageCollectionDataProvider(): \Generator + { + yield 'default language has 6 glossary' => [ + 'en', + ['de', 'es', 'fr', 'it', 'nl', 'pl'], + 6, + ]; + yield 'language de has 1 glossary' => [ + 'sourceLang' => 'de', + 'targetLang' => ['fr'], + 'exceptedGlossaryCount' => 1, + ]; + yield 'language en has 0 glossary' => [ + 'sourceLang' => 'en', + 'targetLang' => [], + 'exceptedGlossaryCount' => 0, + ]; + yield 'language fr has 1 glossary' => [ + 'sourceLang' => 'fr', + 'targetLang' => ['de'], + 'exceptedGlossaryCount' => 1, + ]; + yield 'language it has 0 glossary, because not supported (about mock server)' => [ + 'sourceLang' => 'it', + 'targetLang' => [], + 'exceptedGlossaryCount' => 0, + ]; + yield 'language nl has 0 glossary, because not supported (about mock server)' => [ + 'sourceLang' => 'nl', + 'targetLang' => [], + 'exceptedGlossaryCount' => 0, + ]; + yield 'language pl has 0 glossary, because not supported (about mock server)' => [ + 'sourceLang' => 'pl', + 'targetLang' => [], + 'exceptedGlossaryCount' => 0, + ]; + } + + /** + * @test + * @dataProvider glossaryLanguageCollectionDataProvider + */ + public function glossaryInformationCountOfExpectedMatches(string $sourceLang, array $targetLang, int $exceptedGlossaryCount): void + { + /** @var GlossaryFactory $subject */ + $subject = GeneralUtility::makeInstance(GlossaryFactory::class); + $glossaries = $subject->createGlossaryInformation(5); + + $filteredGlossary = array_filter($glossaries, function (array $glossary) use ($sourceLang, $targetLang) { + return $glossary['source_lang'] === $sourceLang && in_array($glossary['target_lang'], $targetLang); + }); + + static::assertCount($exceptedGlossaryCount, $filteredGlossary); + } +} diff --git a/composer.json b/composer.json index 2ec9db5c..cb908443 100644 --- a/composer.json +++ b/composer.json @@ -81,6 +81,7 @@ }, "require-dev": { "b13/container": "^2.2", + "dms/phpunit-arraysubset-asserts": "^0.5.0", "friendsofphp/php-cs-fixer": "^3.41", "helhum/typo3-console": "^7.1.6 || ^8.0.2", "helmich/phpunit-json-assert": "^3.4.3 || ^3.5.1",