diff --git a/.github/workflows/craft-versions.yml b/.github/workflows/craft-versions.yml index ef1f01ed..d34f0335 100644 --- a/.github/workflows/craft-versions.yml +++ b/.github/workflows/craft-versions.yml @@ -116,8 +116,30 @@ jobs: "3.8.5", "3.8.6", "3.8.7", + "3.8.8", + "3.8.9", + "3.8.10", + "3.8.10.1", + "3.8.10.2", + "3.8.11", + "3.8.12", + "3.8.13", + "3.8.14", + "3.8.15", + "3.8.16", + "3.8.17", + "3.9.0", + "3.9.1", + "3.9.2", + "3.9.3", + "3.9.4", + "3.9.5", + "3.9.6", + "3.9.10", + "3.9.11", + "3.9.12", ] - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Set the value diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 528a7a1f..1872640a 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ ubuntu-latest ] + os: [ ubuntu-20.04 ] scenario: [ "cypress/e2e/jobs/copy-source-text-flow/filters.cy.js", "cypress/e2e/jobs/copy-source-text-flow/success-path-multiple.cy.js", diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 4a7ec866..8ff96f74 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -8,7 +8,7 @@ on: - "*" jobs: tests-php-72: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Set the value @@ -23,7 +23,7 @@ jobs: run: make test tests-php-73: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Set the value @@ -38,7 +38,7 @@ jobs: run: make test tests-php-74: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Set the value @@ -53,7 +53,7 @@ jobs: run: make test tests-php-80: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Set the value @@ -68,7 +68,7 @@ jobs: run: make test tests-php-72-guzzle-6: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Set the value @@ -85,7 +85,7 @@ jobs: run: make test tests-php-80-mysql-80: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Set the value @@ -101,7 +101,7 @@ jobs: run: make test tests-php-latest: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: Set the value diff --git a/src/controllers/PostConfigurationController.php b/src/controllers/PostConfigurationController.php index 5a6b2a33..53b3526d 100644 --- a/src/controllers/PostConfigurationController.php +++ b/src/controllers/PostConfigurationController.php @@ -98,6 +98,7 @@ public function actionInvoke(): Response $request->getBodyParam('copyEntriesSlugFromSourceToTarget') ?? '0' ); + // queueEachTranslationFileSeparately $queueEachTranslationFileSeparately = $request->getBodyParam('queueEachTranslationFileSeparately'); if (empty($queueEachTranslationFileSeparately)) { $queueEachTranslationFileSeparately = 0; @@ -108,6 +109,17 @@ public function actionInvoke(): Response (string)$queueEachTranslationFileSeparately ); + // queueDisableAutomaticSync + $queueDisableAutomaticSync = $request->getBodyParam('queueDisableAutomaticSync'); + if (empty($queueDisableAutomaticSync)) { + $queueDisableAutomaticSync = 0; + } + + Craftliltplugin::getInstance()->settingsRepository->save( + SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC, + (string)$queueDisableAutomaticSync + ); + $settingsRequest = new SettingsRequest(); $settingsRequest->setProjectPrefix( $request->getBodyParam('projectPrefix') diff --git a/src/modules/FetchJobStatusFromConnector.php b/src/modules/FetchJobStatusFromConnector.php index 35b937a9..435a4b8d 100644 --- a/src/modules/FetchJobStatusFromConnector.php +++ b/src/modules/FetchJobStatusFromConnector.php @@ -19,6 +19,7 @@ use lilthq\craftliltplugin\elements\Job; use lilthq\craftliltplugin\records\JobRecord; use lilthq\craftliltplugin\records\TranslationRecord; +use lilthq\craftliltplugin\services\repositories\SettingsRepository; class FetchJobStatusFromConnector extends AbstractRetryJob { @@ -107,18 +108,24 @@ public function execute($queue): void } if (!$isJobFinished) { - Queue::push( - (new FetchJobStatusFromConnector( - [ - 'jobId' => $this->jobId, - 'liltJobId' => $this->liltJobId, - ] - )), - self::PRIORITY, - self::getDelay(), - self::TTR + $queueDisableAutomaticSync = (bool) Craftliltplugin::getInstance()->settingsRepository->get( + SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC ); + if (!$queueDisableAutomaticSync) { + Queue::push( + (new FetchJobStatusFromConnector( + [ + 'jobId' => $this->jobId, + 'liltJobId' => $this->liltJobId, + ] + )), + self::PRIORITY, + self::getDelay(), + self::TTR + ); + } + $mutex->release($mutexKey); $this->markAsDone($queue); @@ -177,18 +184,24 @@ function (TranslationResponse $connectorTranslation) { return; } - Queue::push( - (new FetchJobStatusFromConnector( - [ - 'jobId' => $this->jobId, - 'liltJobId' => $this->liltJobId, - ] - )), - self::PRIORITY, - self::getDelay(), - self::TTR + $queueDisableAutomaticSync = (bool) Craftliltplugin::getInstance()->settingsRepository->get( + SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC ); + if (!$queueDisableAutomaticSync) { + Queue::push( + (new FetchJobStatusFromConnector( + [ + 'jobId' => $this->jobId, + 'liltJobId' => $this->liltJobId, + ] + )), + self::PRIORITY, + self::getDelay(), + self::TTR + ); + } + $mutex->release($mutexKey); $this->markAsDone($queue); diff --git a/src/modules/QueueManager.php b/src/modules/QueueManager.php index 00f514aa..e5d31deb 100644 --- a/src/modules/QueueManager.php +++ b/src/modules/QueueManager.php @@ -12,9 +12,11 @@ use Craft; use craft\queue\BaseJob; use craft\helpers\Queue as CraftHelpersQueue; +use lilthq\craftliltplugin\Craftliltplugin; use lilthq\craftliltplugin\elements\Job; use lilthq\craftliltplugin\parameters\CraftliltpluginParameters; use lilthq\craftliltplugin\records\JobRecord; +use lilthq\craftliltplugin\services\repositories\SettingsRepository; class QueueManager extends BaseJob { @@ -25,8 +27,17 @@ class QueueManager extends BaseJob */ public function execute($queue): void { + $queueDisableAutomaticSync = (bool) Craftliltplugin::getInstance()->settingsRepository->get( + SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC + ); + + if ($queueDisableAutomaticSync) { + // skip because automatic sync is disabled + return; + } + $mutex = Craft::$app->getMutex(); - $mutexKey = __CLASS__ . '_' . __FUNCTION__; + $mutexKey = self::getMutexKey(); if (!$mutex->acquire($mutexKey)) { Craft::warning('Lilt queue manager is already running'); @@ -104,4 +115,9 @@ protected function defaultDescription(): ?string { return Craft::t('app', 'Lilt queue manager'); } + + public static function getMutexKey(): string + { + return __CLASS__ . '_' . __FUNCTION__; + } } diff --git a/src/modules/SendTranslationToConnector.php b/src/modules/SendTranslationToConnector.php index 64423abd..19c37380 100644 --- a/src/modules/SendTranslationToConnector.php +++ b/src/modules/SendTranslationToConnector.php @@ -20,6 +20,7 @@ use lilthq\craftliltplugin\models\TranslationModel; use lilthq\craftliltplugin\records\TranslationRecord; use lilthq\craftliltplugin\services\handlers\commands\SendTranslationCommand; +use lilthq\craftliltplugin\services\repositories\SettingsRepository; use Throwable; class SendTranslationToConnector extends AbstractRetryJob @@ -180,15 +181,21 @@ function (TranslationModel $translationModel) { ); } - Queue::push( - (new FetchJobStatusFromConnector([ - 'jobId' => $command->getJob()->id, - 'liltJobId' => $command->getJob()->liltJobId, - ])), - FetchJobStatusFromConnector::PRIORITY, - 10 + $queueDisableAutomaticSync = (bool) Craftliltplugin::getInstance()->settingsRepository->get( + SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC ); + if (!$queueDisableAutomaticSync) { + Queue::push( + (new FetchJobStatusFromConnector([ + 'jobId' => $command->getJob()->id, + 'liltJobId' => $command->getJob()->liltJobId, + ])), + FetchJobStatusFromConnector::PRIORITY, + 10 + ); + } + $this->markAsDone($queue); $this->release(); diff --git a/src/services/handlers/SendJobToLiltConnectorHandler.php b/src/services/handlers/SendJobToLiltConnectorHandler.php index 96e67318..720e7a82 100644 --- a/src/services/handlers/SendJobToLiltConnectorHandler.php +++ b/src/services/handlers/SendJobToLiltConnectorHandler.php @@ -196,14 +196,21 @@ public function __invoke(Job $job): void 'Job uploaded to Lilt Platform' ); - Queue::push( - (new FetchJobStatusFromConnector([ - 'jobId' => $job->id, - 'liltJobId' => $jobLilt->getId(), - ])), - FetchJobStatusFromConnector::PRIORITY, - 10 //10 seconds for fist job + $queueDisableAutomaticSync = (bool) Craftliltplugin::getInstance()->settingsRepository->get( + SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC ); + + if (!$queueDisableAutomaticSync) { + // push fetch status job from connector + Queue::push( + (new FetchJobStatusFromConnector([ + 'jobId' => $job->id, + 'liltJobId' => $jobLilt->getId(), + ])), + FetchJobStatusFromConnector::PRIORITY, + 10 //10 seconds for fist job + ); + } } /** diff --git a/src/services/handlers/SendTranslationToLiltConnectorHandler.php b/src/services/handlers/SendTranslationToLiltConnectorHandler.php index 9c8c5870..26ee0808 100644 --- a/src/services/handlers/SendTranslationToLiltConnectorHandler.php +++ b/src/services/handlers/SendTranslationToLiltConnectorHandler.php @@ -145,6 +145,7 @@ public function send(SendTranslationCommand $sendTranslationCommand): void ); } + $translation->status = TranslationRecord::STATUS_IN_PROGRESS; $translation->sourceContent = $content; $translation->translatedDraftId = $draft->id; $translation->markAttributeDirty('sourceContent'); diff --git a/src/services/repositories/SettingsRepository.php b/src/services/repositories/SettingsRepository.php index 9ad0b040..cb49ffa7 100644 --- a/src/services/repositories/SettingsRepository.php +++ b/src/services/repositories/SettingsRepository.php @@ -17,8 +17,8 @@ class SettingsRepository { public const ENABLE_ENTRIES_FOR_TARGET_SITES = 'enable_entries_for_target_sites'; public const COPY_ENTRIES_SLUG_FROM_SOURCE_TO_TARGET = 'copy_entries_slug_from_source_to_target'; - public const QUEUE_EACH_TRANSLATION_FILE_SEPARATELY = 'queue_each_translation_file_separately'; + public const QUEUE_DISABLE_AUTOMATIC_SYNC = 'queue_disable_automatic_sync'; public const QUEUE_MANAGER_EXECUTED_AT = 'queue_manager_executed_at'; public const IGNORE_DROPDOWNS = 'ignore_dropdowns'; @@ -56,6 +56,25 @@ public function isQueueEachTranslationFileSeparately(): bool return (bool)$settingValue->value; } + public function get(string $name): ?string + { + $tableSchema = Craft::$app->getDb()->schema->getTableSchema(CraftliltpluginParameters::SETTINGS_TABLE_NAME); + if ($tableSchema === null) { + return null; + } + + + $settingValue = SettingRecord::findOne( + ['name' => $name] + ); + + if (empty($settingValue) || empty($settingValue->value)) { + return null; + } + + return $settingValue->value; + } + public function ignoreDropdowns(): bool { $tableSchema = Craft::$app->getDb()->schema->getTableSchema(CraftliltpluginParameters::SETTINGS_TABLE_NAME); diff --git a/src/templates/_components/utilities/configuration.twig b/src/templates/_components/utilities/configuration.twig index cb0eb25f..43210093 100644 --- a/src/templates/_components/utilities/configuration.twig +++ b/src/templates/_components/utilities/configuration.twig @@ -91,6 +91,17 @@ }) }} +
+ {{ forms.checkbox({ + label: 'Disable automatic synchronization of sent translation jobs', + name: 'queueDisableAutomaticSync', + id: 'queueDisableAutomaticSync', + checked: queueDisableAutomaticSync, + errors: model is defined? model.getErrors('queueDisableAutomaticSync') : [], + disabled: liltConfigDisabled + }) }} +
+ {{ forms.textField({ name: 'liltConfigDisabled', id: 'liltConfigDisabled', diff --git a/src/utilities/Configuration.php b/src/utilities/Configuration.php index f4347295..03dbd5b7 100644 --- a/src/utilities/Configuration.php +++ b/src/utilities/Configuration.php @@ -92,6 +92,11 @@ public static function contentHtml(): string ); $queueEachTranslationFileSeparately = (bool) ($queueEachTranslationFileSeparately->value ?? false); + $queueDisableAutomaticSync = SettingRecord::findOne( + ['name' => SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC,] + ); + $queueDisableAutomaticSync = (bool) ($queueDisableAutomaticSync->value ?? false); + return Craft::$app->getView()->renderTemplate( 'craft-lilt-plugin/_components/utilities/configuration.twig', [ @@ -106,6 +111,7 @@ public static function contentHtml(): string 'enableEntriesForTargetSites' => $enableEntriesForTargetSites, 'copyEntriesSlugFromSourceToTarget' => $copyEntriesSlugFromSourceToTarget, 'queueEachTranslationFileSeparately' => $queueEachTranslationFileSeparately, + 'queueDisableAutomaticSync' => $queueDisableAutomaticSync, ] ); } diff --git a/tests/_support/Helper/CraftLiltPluginHelper.php b/tests/_support/Helper/CraftLiltPluginHelper.php index e11b4387..637958f1 100644 --- a/tests/_support/Helper/CraftLiltPluginHelper.php +++ b/tests/_support/Helper/CraftLiltPluginHelper.php @@ -126,7 +126,7 @@ public function assertJobInQueue(BaseJob $expectedJob): void $key = get_class($expectedJob) . '_' . json_encode($expectedJob); - $this->assertArrayHasKey($key, $jobInfos); + $this->assertArrayHasKey($key, $jobInfos, 'No job found in array: ' . json_encode($jobInfos)); $this->assertEquals($expectedJob, $jobInfos[$key]); } @@ -136,7 +136,7 @@ public function assertJobNotInQueue(BaseJob $expectedJob, string $message = ''): $key = get_class($expectedJob) . '_' . json_encode($expectedJob); - $this->assertArrayNotHasKey($key, $jobInfos, $message); + $this->assertArrayNotHasKey($key, $jobInfos, $message . ': ' . json_encode($jobInfos)); } public function assertJobIdNotInQueue(int $jobId, string $message = ''): void @@ -193,6 +193,31 @@ public function setQueueEachTranslationFileSeparately(int $value): void $settingRecord->value = $value; $settingRecord->save(); } + public function enableOption(string $name): void + { + $this->setOption($name, 1); + } + + public function disableOption(string $name): void + { + $this->setOption($name, 0); + } + + + private function setOption(string $name, int $value): void + { + $settingRecord = SettingRecord::findOne( + ['name' => SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC] + ); + if (!$settingRecord) { + $settingRecord = new SettingRecord( + ['name' => SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC] + ); + } + + $settingRecord->value = (string) $value; + $settingRecord->save(); + } public function assertI18NRecordsExist(int $targetSiteId, array $expectedTranslations): void { diff --git a/tests/integration/AbstractIntegrationCest.php b/tests/integration/AbstractIntegrationCest.php index 767139b1..9fd60430 100644 --- a/tests/integration/AbstractIntegrationCest.php +++ b/tests/integration/AbstractIntegrationCest.php @@ -19,6 +19,8 @@ public function _before(IntegrationTester $I): void { WireMock::create('wiremock', 80)->reset(); Db::truncateTable(Craft::$app->queue->tableName); + + $I->clearQueue(); } public function _after(IntegrationTester $I): void { diff --git a/tests/integration/controllers/PostConfigurationControllerCest.php b/tests/integration/controllers/PostConfigurationControllerCest.php index 744c8bfb..3e645423 100644 --- a/tests/integration/controllers/PostConfigurationControllerCest.php +++ b/tests/integration/controllers/PostConfigurationControllerCest.php @@ -20,7 +20,7 @@ class PostConfigurationControllerCest extends AbstractIntegrationCest /** * @throws ModuleException */ - public function testSuccess(IntegrationTester $I): void + public function testSuccessOn(IntegrationTester $I): void { $I->amLoggedInAs( Craft::$app->getUsers()->getUserById(1) @@ -56,17 +56,83 @@ public function testSuccess(IntegrationTester $I): void 'liltTranslationWorkflow' => SettingsResponse::LILT_TRANSLATION_WORKFLOW_INSTANT, 'enableEntriesForTargetSites' => true, 'copyEntriesSlugFromSourceToTarget' => true, + 'queueEachTranslationFileSeparately' => true, + 'queueDisableAutomaticSync' => true, + ] + ); + + $connectorApiKeyRecord = SettingRecord::findOne(['name' => 'connector_api_key']); + $connectorApiUrlRecord = SettingRecord::findOne(['name' => 'connector_api_url']); + $queueEachTranslationFileSeparately = SettingRecord::findOne(['name' => SettingsRepository::QUEUE_EACH_TRANSLATION_FILE_SEPARATELY]); + $enableEntriesForTargetSites = SettingRecord::findOne(['name' => SettingsRepository::ENABLE_ENTRIES_FOR_TARGET_SITES]); + $copyEntriesSlugFromSourceToTarget = SettingRecord::findOne(['name' => SettingsRepository::COPY_ENTRIES_SLUG_FROM_SOURCE_TO_TARGET]); + $queueDisableAutomaticSync = SettingRecord::findOne(['name' => SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC]); + + Assert::assertSame('this-is-connector-api-key', $connectorApiKeyRecord->value); + Assert::assertSame('http://wiremock/api/v1.0/this-is-connector-api-url', $connectorApiUrlRecord->value); + Assert::assertSame('1', $queueEachTranslationFileSeparately->value); + Assert::assertSame('1', $enableEntriesForTargetSites->value); + Assert::assertSame('1', $copyEntriesSlugFromSourceToTarget->value); + Assert::assertSame('1', $queueDisableAutomaticSync->value); + } + + /** + * @throws ModuleException + */ + public function testSuccessOff(IntegrationTester $I): void + { + $I->amLoggedInAs( + Craft::$app->getUsers()->getUserById(1) + ); + + $I->expectSettingsGetRequest( + '/api/v1.0/this-is-connector-api-url/settings', + 'this-is-connector-api-key', + [], + 200 + ); + + $I->expectSettingsUpdateRequest( + '/api/v1.0/this-is-connector-api-url/settings', + [ + 'project_prefix' => 'this-is-connector-project-prefix', + 'project_name_template' => 'this-is-connector-project-name-template', + 'lilt_translation_workflow' => SettingsResponse::LILT_TRANSLATION_WORKFLOW_INSTANT, + ], + 200 + ); + + $I->sendAjaxPostRequest( + sprintf( + '?p=admin/%s', + CraftliltpluginParameters::POST_CONFIGURATION_PATH + ), + [ + 'connectorApiKey' => 'this-is-connector-api-key', + 'connectorApiUrl' => 'http://wiremock/api/v1.0/this-is-connector-api-url', + 'projectPrefix' => 'this-is-connector-project-prefix', + 'projectNameTemplate' => 'this-is-connector-project-name-template', + 'liltTranslationWorkflow' => SettingsResponse::LILT_TRANSLATION_WORKFLOW_INSTANT, + 'enableEntriesForTargetSites' => false, + 'copyEntriesSlugFromSourceToTarget' => false, 'queueEachTranslationFileSeparately' => false, + 'queueDisableAutomaticSync' => false, ] ); $connectorApiKeyRecord = SettingRecord::findOne(['name' => 'connector_api_key']); $connectorApiUrlRecord = SettingRecord::findOne(['name' => 'connector_api_url']); $queueEachTranslationFileSeparately = SettingRecord::findOne(['name' => SettingsRepository::QUEUE_EACH_TRANSLATION_FILE_SEPARATELY]); + $enableEntriesForTargetSites = SettingRecord::findOne(['name' => SettingsRepository::ENABLE_ENTRIES_FOR_TARGET_SITES]); + $copyEntriesSlugFromSourceToTarget = SettingRecord::findOne(['name' => SettingsRepository::COPY_ENTRIES_SLUG_FROM_SOURCE_TO_TARGET]); + $queueDisableAutomaticSync = SettingRecord::findOne(['name' => SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC]); Assert::assertSame('this-is-connector-api-key', $connectorApiKeyRecord->value); Assert::assertSame('http://wiremock/api/v1.0/this-is-connector-api-url', $connectorApiUrlRecord->value); + Assert::assertSame('', $enableEntriesForTargetSites->value); + Assert::assertSame('', $copyEntriesSlugFromSourceToTarget->value); Assert::assertSame('0', $queueEachTranslationFileSeparately->value); + Assert::assertSame('0', $queueDisableAutomaticSync->value); } public function _after(IntegrationTester $I): void diff --git a/tests/integration/modules/FetchJobStatusFromConnectorCest.php b/tests/integration/modules/FetchJobStatusFromConnectorCest.php index e0493591..5f5591ae 100644 --- a/tests/integration/modules/FetchJobStatusFromConnectorCest.php +++ b/tests/integration/modules/FetchJobStatusFromConnectorCest.php @@ -17,7 +17,9 @@ use lilthq\craftliltplugin\modules\FetchJobStatusFromConnector; use lilthq\craftliltplugin\modules\FetchTranslationFromConnector; use lilthq\craftliltplugin\modules\FetchVerifiedJobTranslationsFromConnector; +use lilthq\craftliltplugin\parameters\CraftliltpluginParameters; use lilthq\craftliltplugin\records\TranslationRecord; +use lilthq\craftliltplugin\services\repositories\SettingsRepository; use lilthq\craftliltplugintests\integration\AbstractIntegrationCest; use lilthq\tests\fixtures\EntriesFixture; use PHPUnit\Framework\Assert; @@ -41,6 +43,7 @@ public function _fixtures(): array public function testExecuteSuccessVerified(IntegrationTester $I): void { $I->clearQueue(); + $I->disableOption(SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC); Db::truncateTable(Craft::$app->queue->tableName); @@ -174,6 +177,7 @@ public function testExecuteSuccessVerified(IntegrationTester $I): void public function testExecuteSuccessInstant(IntegrationTester $I): void { $I->clearQueue(); + $I->disableOption(SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC); Db::truncateTable(Craft::$app->queue->tableName); @@ -307,6 +311,7 @@ public function testExecuteSuccessInstant(IntegrationTester $I): void public function testExecuteJobNotFound(IntegrationTester $I): void { $I->clearQueue(); + $I->disableOption(SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC); Db::truncateTable(Craft::$app->queue->tableName); @@ -333,6 +338,7 @@ public function testExecuteJobNotFound(IntegrationTester $I): void public function testExecuteSuccessProcessing(IntegrationTester $I): void { $I->clearQueue(); + $I->disableOption(SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC); Db::truncateTable(Craft::$app->queue->tableName); @@ -377,6 +383,51 @@ public function testExecuteSuccessProcessing(IntegrationTester $I): void ); } + /** + * @throws Exception + * @throws ModuleException + */ + public function testExecuteSuccessProcessingAutomaticSyncDisabled(IntegrationTester $I): void + { + $I->clearQueue(); + $I->enableOption(SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC); + + Db::truncateTable(Craft::$app->queue->tableName); + + $user = Craft::$app->getUsers()->getUserById(1); + $I->amLoggedInAs($user); + + $job = $I->createJob([ + 'title' => 'Awesome test job', + 'elementIds' => [999], + 'targetSiteIds' => '*', + 'sourceSiteId' => Craftliltplugin::getInstance()->languageMapper->getSiteIdByLanguage('en-US'), + 'translationWorkflow' => SettingsResponse::LILT_TRANSLATION_WORKFLOW_INSTANT, + 'versions' => [], + 'authorId' => 1, + 'liltJobId' => 777, + ]); + + $I->expectJobGetRequest( + 777, + 200, + [ + 'status' => JobResponse::STATUS_PROCESSING + ] + ); + + $I->runQueue( + FetchJobStatusFromConnector::class, + [ + 'liltJobId' => 777, + 'jobId' => $job->id, + ] + ); + + $totalJobs = Craft::$app->queue->getJobInfo(); + Assert::assertCount(0, $totalJobs); + } + /** * @throws Exception * @throws ModuleException @@ -384,6 +435,7 @@ public function testExecuteSuccessProcessing(IntegrationTester $I): void public function testExecuteSuccessQueued(IntegrationTester $I): void { $I->clearQueue(); + $I->disableOption(SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC); Db::truncateTable(Craft::$app->queue->tableName); diff --git a/tests/integration/modules/QueueManagerCest.php b/tests/integration/modules/QueueManagerCest.php new file mode 100644 index 00000000..1fcc493a --- /dev/null +++ b/tests/integration/modules/QueueManagerCest.php @@ -0,0 +1,172 @@ + [ + 'class' => EntriesFixture::class, + ] + ]; + } + + /** + * @throws ModuleException + */ + public function testRunSuccess(IntegrationTester $I): void + { + $I->clearQueue(); + Craft::$app->getMutex()->release( + QueueManager::getMutexKey() + ); + + $I->disableOption(SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC); + + $user = Craft::$app->getUsers()->getUserById(1); + $I->amLoggedInAs($user); + + $elementToTranslate = Entry::find() + ->where(['authorId' => 1]) + ->orderBy(['id' => SORT_DESC]) + ->one(); + + $firstJobStatusInProgress = $I->createJob([ + 'title' => 'Awesome test job', + 'elementIds' => [(string)$elementToTranslate->id], //string to check type conversion + 'targetSiteIds' => '*', + 'sourceSiteId' => Craftliltplugin::getInstance()->languageMapper->getSiteIdByLanguage('en-US'), + 'translationWorkflow' => SettingsResponse::LILT_TRANSLATION_WORKFLOW_INSTANT, + 'versions' => [], + 'authorId' => 1, + 'status' => Job::STATUS_IN_PROGRESS + ]); + + $secondJobStatusInProgress = $I->createJob([ + 'title' => 'Awesome test job', + 'elementIds' => [(string)$elementToTranslate->id], //string to check type conversion + 'targetSiteIds' => '*', + 'sourceSiteId' => Craftliltplugin::getInstance()->languageMapper->getSiteIdByLanguage('en-US'), + 'translationWorkflow' => SettingsResponse::LILT_TRANSLATION_WORKFLOW_INSTANT, + 'versions' => [], + 'authorId' => 1, + 'status' => Job::STATUS_IN_PROGRESS + ]); + + $I->createJob([ + 'title' => 'Awesome test job', + 'elementIds' => [(string)$elementToTranslate->id], //string to check type conversion + 'targetSiteIds' => '*', + 'sourceSiteId' => Craftliltplugin::getInstance()->languageMapper->getSiteIdByLanguage('en-US'), + 'translationWorkflow' => SettingsResponse::LILT_TRANSLATION_WORKFLOW_INSTANT, + 'versions' => [], + 'authorId' => 1, + 'status' => Job::STATUS_COMPLETE + ]); + + $I->executeQueue(QueueManager::class); + + $jobInfos = Craft::$app->queue->getJobInfo(); + + Assert::assertNotEmpty($jobInfos); + + $I->assertJobInQueue( + new ManualJobSync( + ['jobIds' => [ + $firstJobStatusInProgress->id, + $secondJobStatusInProgress->id + ]] + ) + ); + } + + /** + * @throws ModuleException + */ + public function testRunSuccessDisableAutomaticSync(IntegrationTester $I): void + { + $I->clearQueue(); + Craft::$app->getMutex()->release( + QueueManager::getMutexKey() + ); + + $I->enableOption(SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC); + + $user = Craft::$app->getUsers()->getUserById(1); + $I->amLoggedInAs($user); + + $elementToTranslate = Entry::find() + ->where(['authorId' => 1]) + ->orderBy(['id' => SORT_DESC]) + ->one(); + + $I->createJob([ + 'title' => 'Awesome test job', + 'elementIds' => [(string)$elementToTranslate->id], //string to check type conversion + 'targetSiteIds' => '*', + 'sourceSiteId' => Craftliltplugin::getInstance()->languageMapper->getSiteIdByLanguage('en-US'), + 'translationWorkflow' => SettingsResponse::LILT_TRANSLATION_WORKFLOW_INSTANT, + 'versions' => [], + 'authorId' => 1, + 'status' => Job::STATUS_IN_PROGRESS + ]); + + $I->createJob([ + 'title' => 'Awesome test job', + 'elementIds' => [(string)$elementToTranslate->id], //string to check type conversion + 'targetSiteIds' => '*', + 'sourceSiteId' => Craftliltplugin::getInstance()->languageMapper->getSiteIdByLanguage('en-US'), + 'translationWorkflow' => SettingsResponse::LILT_TRANSLATION_WORKFLOW_INSTANT, + 'versions' => [], + 'authorId' => 1, + 'status' => Job::STATUS_IN_PROGRESS + ]); + + $I->createJob([ + 'title' => 'Awesome test job', + 'elementIds' => [(string)$elementToTranslate->id], //string to check type conversion + 'targetSiteIds' => '*', + 'sourceSiteId' => Craftliltplugin::getInstance()->languageMapper->getSiteIdByLanguage('en-US'), + 'translationWorkflow' => SettingsResponse::LILT_TRANSLATION_WORKFLOW_INSTANT, + 'versions' => [], + 'authorId' => 1, + 'status' => Job::STATUS_COMPLETE + ]); + + $I->executeQueue(QueueManager::class); + + $jobInfos = Craft::$app->queue->getJobInfo(); + + Assert::assertEmpty($jobInfos); + + // set option back for next tests + $I->disableOption(SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC); + } +} diff --git a/tests/integration/modules/SendTranslationToConnectorCest.php b/tests/integration/modules/SendTranslationToConnectorCest.php new file mode 100644 index 00000000..0aa0291c --- /dev/null +++ b/tests/integration/modules/SendTranslationToConnectorCest.php @@ -0,0 +1,335 @@ +disableOption(SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC); + } + + public function _fixtures(): array + { + return [ + 'entries' => [ + 'class' => EntriesFixture::class, + ] + ]; + } + + /** + * @throws ModuleException + * @throws InvalidFieldException + */ + public function testSendTranslationSuccess(IntegrationTester $I): void + { + $I->clearQueue(); + + $user = Craft::$app->getUsers()->getUserById(1); + $I->amLoggedInAs($user); + + $elementToTranslate = Entry::find() + ->where(['authorId' => 1]) + ->orderBy(['id' => SORT_DESC]) + ->one(); + + /** + * @var TranslationRecord[] $translations + */ + [$job, $translations] = $I->createJobWithTranslations([ + 'title' => 'Awesome test job', + 'elementIds' => [(string)$elementToTranslate->id], //string to check type conversion + 'targetSiteIds' => '*', + 'sourceSiteId' => Craftliltplugin::getInstance()->languageMapper->getSiteIdByLanguage('en-US'), + 'translationWorkflow' => SettingsResponse::LILT_TRANSLATION_WORKFLOW_INSTANT, + 'versions' => [], + 'authorId' => 1, + 'liltJobId' => 1000, + 'status' => Job::STATUS_IN_PROGRESS, + ]); + + $translationsMapped = []; + foreach ($translations as $translation) { + $language = Craftliltplugin::getInstance()->languageMapper->getLanguageBySiteId($translation->targetSiteId); + $translationsMapped[$language] = $translation; + } + + + // mark ru translation as sent + $translationsMapped['ru-RU']->connectorTranslationId = 1111; + $translationsMapped['ru-RU']->status = TranslationRecord::STATUS_IN_PROGRESS; + $translationsMapped['ru-RU']->sourceContent = json_encode(["test" => "already translated"]); + $translationsMapped['ru-RU']->save(); + + // mark es translation as sent + $translationsMapped['es-ES']->status = TranslationRecord::STATUS_IN_PROGRESS; + $translationsMapped['es-ES']->sourceContent = json_encode(["test" => "already translated"]); + $translationsMapped['es-ES']->save(); + + $translationsMapped['de-DE']->status = TranslationRecord::STATUS_NEW; + $translationsMapped['de-DE']->sourceContent = null; + $translationsMapped['de-DE']->translatedDraftId = null; + $translationsMapped['de-DE']->save(); + + $I->expectJobGetRequest( + 1000, + 200, + [ + 'status' => JobResponse::STATUS_DRAFT + ] + ); + + $expectedUrlDe = sprintf( + '/api/v1.0/jobs/1000/files?name=%s' + . '&srclang=en-US' + . '&trglang=de-DE' + . '&due=', + urlencode( + sprintf('element_%d_first-entry-user-1.json+html', $elementToTranslate->getId()) + ) + ); + $I->expectJobTranslationsRequest($expectedUrlDe, [], HttpCode::OK); + + $I->expectJobStartRequest(1000, HttpCode::OK); + + $I->runQueue( + SendTranslationToConnector::class, + [ + 'jobId' => $job->id, + 'translationId' => $translationsMapped['de-DE']->id, + 'targetSiteId' => $translationsMapped['de-DE']->targetSiteId, + 'versionId' => $translationsMapped['de-DE']->versionId, + 'elementId' => $translationsMapped['de-DE']->elementId, + ] + ); + + $expectSourceContentForTranslationId = $translationsMapped['de-DE']->id; + $translations = array_map( + static function ( + TranslationRecord $translationRecord + ) use ( + $elementToTranslate, + $expectSourceContentForTranslationId + ) { + $element = Craft::$app->elements->getElementById( + $translationRecord->translatedDraftId, + null, + $translationRecord->targetSiteId + ); + + $expectedBody = ExpectedElementContent::getExpectedBody($element); + + Assert::assertSame(Job::STATUS_IN_PROGRESS, $translationRecord->status); + Assert::assertSame($elementToTranslate->id, $translationRecord->versionId); + Assert::assertSame($elementToTranslate->id, $translationRecord->elementId); + + if($expectSourceContentForTranslationId === $translationRecord->id) { + Assert::assertEquals($expectedBody, $translationRecord->sourceContent); + } + + Assert::assertSame( + Craftliltplugin::getInstance()->languageMapper->getSiteIdByLanguage('en-US'), + $translationRecord->sourceSiteId + ); + + return [ + 'versionId' => $translationRecord->versionId, + 'translatedDraftId' => $translationRecord->translatedDraftId, + 'sourceSiteId' => $translationRecord->sourceSiteId, + 'targetSiteId' => $translationRecord->targetSiteId, + 'sourceContent' => $translationRecord->sourceContent, + 'status' => $translationRecord->status, + 'connectorTranslationId' => $translationRecord->connectorTranslationId, + ]; + }, TranslationRecord::findAll(['jobId' => $job->id, 'elementId' => $elementToTranslate->id])); + + $languages = Craftliltplugin::getInstance()->languageMapper->getLanguagesBySiteIds( + array_column($translations, 'targetSiteId') + ); + sort($languages); + + Assert::assertEquals( + ['de-DE', 'es-ES', 'ru-RU'], + $languages + ); + + $jobActual = Job::findOne(['id' => $job->id]); + Assert::assertSame(Job::STATUS_IN_PROGRESS, $jobActual->status); + + $I->assertJobInQueue( + new FetchJobStatusFromConnector([ + 'liltJobId' => 1000, + 'jobId' => $job->id + ]) + ); + } + + /** + * @throws ModuleException + * @throws InvalidFieldException + */ + public function testSendTranslationSuccessDisableAutomaticSync(IntegrationTester $I): void + { + $I->clearQueue(); + + $I->enableOption(SettingsRepository::QUEUE_DISABLE_AUTOMATIC_SYNC); + + $user = Craft::$app->getUsers()->getUserById(1); + $I->amLoggedInAs($user); + + $elementToTranslate = Entry::find() + ->where(['authorId' => 1]) + ->orderBy(['id' => SORT_DESC]) + ->one(); + + /** + * @var TranslationRecord[] $translations + */ + [$job, $translations] = $I->createJobWithTranslations([ + 'title' => 'Awesome test job', + 'elementIds' => [(string)$elementToTranslate->id], //string to check type conversion + 'targetSiteIds' => '*', + 'sourceSiteId' => Craftliltplugin::getInstance()->languageMapper->getSiteIdByLanguage('en-US'), + 'translationWorkflow' => SettingsResponse::LILT_TRANSLATION_WORKFLOW_INSTANT, + 'versions' => [], + 'authorId' => 1, + 'liltJobId' => 1000, + 'status' => Job::STATUS_IN_PROGRESS, + ]); + + $translationsMapped = []; + foreach ($translations as $translation) { + $language = Craftliltplugin::getInstance()->languageMapper->getLanguageBySiteId($translation->targetSiteId); + $translationsMapped[$language] = $translation; + } + + + // mark ru translation as sent + $translationsMapped['ru-RU']->connectorTranslationId = 1111; + $translationsMapped['ru-RU']->status = TranslationRecord::STATUS_IN_PROGRESS; + $translationsMapped['ru-RU']->sourceContent = json_encode(["test" => "already translated"]); + $translationsMapped['ru-RU']->save(); + + // mark es translation as sent + $translationsMapped['es-ES']->status = TranslationRecord::STATUS_IN_PROGRESS; + $translationsMapped['es-ES']->sourceContent = json_encode(["test" => "already translated"]); + $translationsMapped['es-ES']->save(); + + $translationsMapped['de-DE']->status = TranslationRecord::STATUS_NEW; + $translationsMapped['de-DE']->sourceContent = null; + $translationsMapped['de-DE']->translatedDraftId = null; + $translationsMapped['de-DE']->save(); + + $I->expectJobGetRequest( + 1000, + 200, + [ + 'status' => JobResponse::STATUS_DRAFT + ] + ); + + $expectedUrlDe = sprintf( + '/api/v1.0/jobs/1000/files?name=%s' + . '&srclang=en-US' + . '&trglang=de-DE' + . '&due=', + urlencode( + sprintf('element_%d_first-entry-user-1.json+html', $elementToTranslate->getId()) + ) + ); + $I->expectJobTranslationsRequest($expectedUrlDe, [], HttpCode::OK); + + $I->expectJobStartRequest(1000, HttpCode::OK); + + $I->runQueue( + SendTranslationToConnector::class, + [ + 'jobId' => $job->id, + 'translationId' => $translationsMapped['de-DE']->id, + 'targetSiteId' => $translationsMapped['de-DE']->targetSiteId, + 'versionId' => $translationsMapped['de-DE']->versionId, + 'elementId' => $translationsMapped['de-DE']->elementId, + ] + ); + + $expectSourceContentForTranslationId = $translationsMapped['de-DE']->id; + $translations = array_map( + static function ( + TranslationRecord $translationRecord + ) use ( + $elementToTranslate, + $expectSourceContentForTranslationId + ) { + $element = Craft::$app->elements->getElementById( + $translationRecord->translatedDraftId, + null, + $translationRecord->targetSiteId + ); + + $expectedBody = ExpectedElementContent::getExpectedBody($element); + + Assert::assertSame(Job::STATUS_IN_PROGRESS, $translationRecord->status); + Assert::assertSame($elementToTranslate->id, $translationRecord->versionId); + Assert::assertSame($elementToTranslate->id, $translationRecord->elementId); + + if($expectSourceContentForTranslationId === $translationRecord->id) { + Assert::assertEquals($expectedBody, $translationRecord->sourceContent); + } + + Assert::assertSame( + Craftliltplugin::getInstance()->languageMapper->getSiteIdByLanguage('en-US'), + $translationRecord->sourceSiteId + ); + + return [ + 'versionId' => $translationRecord->versionId, + 'translatedDraftId' => $translationRecord->translatedDraftId, + 'sourceSiteId' => $translationRecord->sourceSiteId, + 'targetSiteId' => $translationRecord->targetSiteId, + 'sourceContent' => $translationRecord->sourceContent, + 'status' => $translationRecord->status, + 'connectorTranslationId' => $translationRecord->connectorTranslationId, + ]; + }, TranslationRecord::findAll(['jobId' => $job->id, 'elementId' => $elementToTranslate->id])); + + $languages = Craftliltplugin::getInstance()->languageMapper->getLanguagesBySiteIds( + array_column($translations, 'targetSiteId') + ); + sort($languages); + + Assert::assertEquals( + ['de-DE', 'es-ES', 'ru-RU'], + $languages + ); + + $jobActual = Job::findOne(['id' => $job->id]); + Assert::assertSame(Job::STATUS_IN_PROGRESS, $jobActual->status); + + $totalJobs = Craft::$app->queue->getJobInfo(); + Assert::assertCount(0, $totalJobs); + } +}