From fd3c93931a72e44cbfef062b591829a81523ed28 Mon Sep 17 00:00:00 2001
From: bhdnb <172895427+bhdnb@users.noreply.github.com>
Date: Thu, 16 Jan 2025 09:44:31 +0200
Subject: [PATCH] fix: If-None-Match header reset in Translation API (#204)
---
src/CrowdinApiClient/Api/AbstractApi.php | 2 +-
src/CrowdinApiClient/Api/TranslationApi.php | 17 +++-
.../CrowdinApiClient/Api/AbstractTestApi.php | 6 +-
.../Api/Enterprise/AbstractTestApi.php | 6 +-
.../Api/Enterprise/TranslationApiTest.php | 4 -
tests/CrowdinApiClient/Api/StorageApiTest.php | 21 ++---
.../Api/TranslationApiTest.php | 88 ++++++++++++-------
7 files changed, 89 insertions(+), 55 deletions(-)
diff --git a/src/CrowdinApiClient/Api/AbstractApi.php b/src/CrowdinApiClient/Api/AbstractApi.php
index 9909b006..62c80853 100644
--- a/src/CrowdinApiClient/Api/AbstractApi.php
+++ b/src/CrowdinApiClient/Api/AbstractApi.php
@@ -77,7 +77,7 @@ public function setHeaders(array $headers)
return $this;
}
- public function hasHeader($header)
+ public function hasHeader($header): bool
{
return isset($this->headers[strtolower($header)]);
}
diff --git a/src/CrowdinApiClient/Api/TranslationApi.php b/src/CrowdinApiClient/Api/TranslationApi.php
index d77a4385..38cf553c 100644
--- a/src/CrowdinApiClient/Api/TranslationApi.php
+++ b/src/CrowdinApiClient/Api/TranslationApi.php
@@ -73,8 +73,11 @@ public function getPreTranslation(int $projectId, string $preTranslationId): ?Pr
* boolean $params[preserveFolderHierarchy] Default: false
* @return TranslationProjectDirectory|null
*/
- public function buildProjectDirectoryTranslation(int $projectId, int $directoryId, array $params = []): ?TranslationProjectDirectory
- {
+ public function buildProjectDirectoryTranslation(
+ int $projectId,
+ int $directoryId,
+ array $params = []
+ ): ?TranslationProjectDirectory {
$path = sprintf('projects/%d/translations/builds/directories/%d', $projectId, $directoryId);
return $this->_post($path, TranslationProjectDirectory::class, $params);
@@ -96,12 +99,18 @@ public function buildProjectDirectoryTranslation(int $projectId, int $directoryI
* boolean $params[skipUntranslatedFiles] true value can't be used with skipUntranslatedStrings=true in same request
* boolean $params[exportApprovedOnly]
*/
- public function buildProjectFileTranslation(int $projectId, int $fileId, array $params = [], string $ifNoneMatch = null): ?DownloadFile
- {
+ public function buildProjectFileTranslation(
+ int $projectId,
+ int $fileId,
+ array $params = [],
+ ?string $ifNoneMatch = null
+ ): ?DownloadFile {
$path = sprintf('projects/%d/translations/builds/files/%d', $projectId, $fileId);
if ($ifNoneMatch) {
$this->setHeader('If-None-Match', $ifNoneMatch);
+ } else {
+ $this->removeHeader('If-None-Match');
}
return $this->_post($path, DownloadFileTranslation::class, $params);
diff --git a/tests/CrowdinApiClient/Api/AbstractTestApi.php b/tests/CrowdinApiClient/Api/AbstractTestApi.php
index 4ef0b906..e51640b3 100644
--- a/tests/CrowdinApiClient/Api/AbstractTestApi.php
+++ b/tests/CrowdinApiClient/Api/AbstractTestApi.php
@@ -46,9 +46,11 @@ public function mockRequest(array $params)
if (isset($params['body'])) {
$this->assertEquals($params['body'], $options['body']);
}
- if (isset($params['header'])) {
- $this->assertEquals($params['header'], $options['header']);
+
+ if (isset($params['headers'])) {
+ $this->assertEquals($params['headers'], $options['headers']);
}
+
return $params['response'] ?? '';
}));
}
diff --git a/tests/CrowdinApiClient/Api/Enterprise/AbstractTestApi.php b/tests/CrowdinApiClient/Api/Enterprise/AbstractTestApi.php
index 82dad661..c652ff52 100644
--- a/tests/CrowdinApiClient/Api/Enterprise/AbstractTestApi.php
+++ b/tests/CrowdinApiClient/Api/Enterprise/AbstractTestApi.php
@@ -47,9 +47,11 @@ public function mockRequest(array $params)
if (isset($params['body'])) {
$this->assertEquals($params['body'], $options['body']);
}
- if (isset($params['header'])) {
- $this->assertEquals($params['header'], $options['header']);
+
+ if (isset($params['headers'])) {
+ $this->assertEquals($params['headers'], $options['headers']);
}
+
return $params['response'] ?? '';
}));
}
diff --git a/tests/CrowdinApiClient/Api/Enterprise/TranslationApiTest.php b/tests/CrowdinApiClient/Api/Enterprise/TranslationApiTest.php
index c0b201a7..e9870a9b 100644
--- a/tests/CrowdinApiClient/Api/Enterprise/TranslationApiTest.php
+++ b/tests/CrowdinApiClient/Api/Enterprise/TranslationApiTest.php
@@ -8,10 +8,6 @@
use CrowdinApiClient\Model\TranslationProjectDirectory;
use CrowdinApiClient\ModelCollection;
-/**
- * Class TranslationApiTest
- * @package Crowdin\Tests\Api
- */
class TranslationApiTest extends AbstractTestApi
{
public function testApplyPreTranslation()
diff --git a/tests/CrowdinApiClient/Api/StorageApiTest.php b/tests/CrowdinApiClient/Api/StorageApiTest.php
index dea3d7ad..be944ce9 100644
--- a/tests/CrowdinApiClient/Api/StorageApiTest.php
+++ b/tests/CrowdinApiClient/Api/StorageApiTest.php
@@ -4,7 +4,7 @@
use CrowdinApiClient\Model\Storage;
use CrowdinApiClient\ModelCollection;
-use CrowdinApiClient\Utility\Mimetypes;
+use SplFileInfo;
class StorageApiTest extends AbstractTestApi
{
@@ -68,21 +68,22 @@ public function testDelete()
$this->crowdin->storage->delete(1);
}
- public function testCreate()
+ public function testCreate(): void
{
- $fileObject = new \SplFileInfo(__FILE__);
+ $fileObject = new SplFileInfo(__FILE__);
$this->mockRequest([
'method' => 'post',
'uri' => 'https://api.crowdin.com/api/v2/storages',
- 'response' => '{
- "data": {
- "id": 1
- }
- }',
+ 'response' => json_encode([
+ 'data' => [
+ 'id' => 1
+ ]
+ ]),
'headers' => [
- 'Content-Type' => Mimetypes::getInstance()->fromFilename($fileObject->getFilename()),
- 'Crowdin-API-FileName' => $fileObject->getFilename(),
+ 'Content-Type' => 'application/octet-stream',
+ 'Crowdin-API-FileName' => 'StorageApiTest.php',
+ 'Authorization' => 'Bearer access_token',
],
]);
diff --git a/tests/CrowdinApiClient/Api/TranslationApiTest.php b/tests/CrowdinApiClient/Api/TranslationApiTest.php
index e625889b..6f316595 100644
--- a/tests/CrowdinApiClient/Api/TranslationApiTest.php
+++ b/tests/CrowdinApiClient/Api/TranslationApiTest.php
@@ -7,17 +7,13 @@
use CrowdinApiClient\Model\TranslationProjectBuild;
use CrowdinApiClient\ModelCollection;
-/**
- * Class TranslationApiTest
- * @package Crowdin\Tests\Api
- */
class TranslationApiTest extends AbstractTestApi
{
public function testApplyPreTranslation()
{
$params = [
'languageIds' => ['uk'],
- 'fileIds' => [0]
+ 'fileIds' => [0],
];
$this->mockRequest([
@@ -50,7 +46,7 @@ public function testApplyPreTranslation()
"startedAt": "2019-11-13T08:17:22Z",
"finishedAt": "2019-11-13T08:17:22Z"
}
- }'
+ }',
]);
$preTranslation = $this->crowdin->translation->applyPreTranslation(2, $params);
@@ -60,7 +56,9 @@ public function testApplyPreTranslation()
public function testGetPreTranslation()
{
- $this->mockRequestGet('/projects/2/pre-translations/9e7de270-4f83-41cb-b606-2f90631f26e2', '{
+ $this->mockRequestGet(
+ '/projects/2/pre-translations/9e7de270-4f83-41cb-b606-2f90631f26e2',
+ '{
"data": {
"identifier": "9e7de270-4f83-41cb-b606-2f90631f26e2",
"status": "created",
@@ -86,7 +84,8 @@ public function testGetPreTranslation()
"startedAt": "2019-11-13T08:17:22Z",
"finishedAt": "2019-11-13T08:17:22Z"
}
- }');
+ }'
+ );
$preTranslation = $this->crowdin->translation->getPreTranslation(2, '9e7de270-4f83-41cb-b606-2f90631f26e2');
@@ -94,20 +93,30 @@ public function testGetPreTranslation()
$this->assertEquals('9e7de270-4f83-41cb-b606-2f90631f26e2', $preTranslation->getIdentifier());
}
- public function testBuildProjectFileTranslation()
+ public function testBuildProjectFileTranslation(): void
{
$this->mockRequest([
'uri' => 'https://api.crowdin.com/api/v2/projects/1/translations/builds/files/2',
'method' => 'post',
- 'response' => '{
- "data": {
- "url": "https://foo.com/file",
- "expireIn": "2019-09-20T10:31:21+00:00"
- }
- }'
+ 'headers' => [
+ 'content-type' => 'application/json',
+ 'if-none-match' => 'bfc13a64729c4290ef5b2c2730249c88ca92d82d',
+ 'Authorization' => 'Bearer access_token',
+ ],
+ 'response' => json_encode([
+ 'data' => [
+ 'url' => 'https://foo.com/file',
+ 'expireIn' => '2019-09-20T10:31:21+00:00',
+ ],
+ ]),
]);
- $file = $this->crowdin->translation->buildProjectFileTranslation(1, 2, ['targetLanguageId' => 'uk']);
+ $file = $this->crowdin->translation->buildProjectFileTranslation(
+ 1,
+ 2,
+ ['targetLanguageId' => 'uk'],
+ 'bfc13a64729c4290ef5b2c2730249c88ca92d82d'
+ );
$this->assertInstanceOf(DownloadFile::class, $file);
$this->assertEquals('https://foo.com/file', $file->getUrl());
@@ -115,7 +124,9 @@ public function testBuildProjectFileTranslation()
public function testListProjectBuilds()
{
- $this->mockRequestGet('/projects/2/translations/builds', '{
+ $this->mockRequestGet(
+ '/projects/2/translations/builds',
+ '{
"data": [
{
"data": {
@@ -140,7 +151,8 @@ public function testListProjectBuilds()
"limit": 0
}
]
- }');
+ }'
+ );
$translationProjectBuilds = $this->crowdin->translation->getProjectBuilds(2);
$this->assertInstanceOf(ModelCollection::class, $translationProjectBuilds);
@@ -173,9 +185,9 @@ public function testBuildProject()
'options' => [
'body' => [
'branchId' => 2,
- 'targetLanguageIds' => ['uk']
- ]
- ]
+ 'targetLanguageIds' => ['uk'],
+ ],
+ ],
]);
$params = [
@@ -197,7 +209,9 @@ public function testBuildProject()
public function testGetProjectBuildStatus()
{
- $this->mockRequestGet('/projects/2/translations/builds/2', '{
+ $this->mockRequestGet(
+ '/projects/2/translations/builds/2',
+ '{
"data": {
"id": 2,
"projectId": 2,
@@ -212,7 +226,8 @@ public function testGetProjectBuildStatus()
"currentFileId": 1
}
}
- }');
+ }'
+ );
$projectBuild = $this->crowdin->translation->getProjectBuildStatus(2, 2);
@@ -222,16 +237,22 @@ public function testGetProjectBuildStatus()
public function testDownloadProjectBuild()
{
- $this->mockRequestGet('/projects/2/translations/builds/2/download', '{
+ $this->mockRequestGet(
+ '/projects/2/translations/builds/2/download',
+ '{
"data": {
"url": "https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff?response-content-disposition=attachment%3B%20filename%3D%22APP.xliff%22&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIGJKLQV66ZXPMMEA%2F20190920%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190920T093121Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=439ebd69a1b7e4c23e6d17891a491c94f832e0c82e4692dedb35a6cd1e624b62",
"expireIn": "2019-09-20T10:31:21+00:00"
}
- }');
+ }'
+ );
$file = $this->crowdin->translation->downloadProjectBuild(2, 2);
$this->assertInstanceOf(DownloadFile::class, $file);
- $this->assertEquals('https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff?response-content-disposition=attachment%3B%20filename%3D%22APP.xliff%22&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIGJKLQV66ZXPMMEA%2F20190920%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190920T093121Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=439ebd69a1b7e4c23e6d17891a491c94f832e0c82e4692dedb35a6cd1e624b62', $file->getUrl());
+ $this->assertEquals(
+ 'https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff?response-content-disposition=attachment%3B%20filename%3D%22APP.xliff%22&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIGJKLQV66ZXPMMEA%2F20190920%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190920T093121Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=439ebd69a1b7e4c23e6d17891a491c94f832e0c82e4692dedb35a6cd1e624b62',
+ $file->getUrl()
+ );
}
public function testDeleteProjectBuild()
@@ -266,8 +287,8 @@ public function testUploadTranslations()
'body' => [
'storageId' => 13,
'fileId' => 2,
- ]
- ]
+ ],
+ ],
]);
$data = $this->crowdin->translation->uploadTranslations(8, 'uk', $params);
@@ -278,7 +299,7 @@ public function testUploadTranslations()
'projectId' => 8,
'storageId' => 34,
'languageId' => 'uk',
- 'fileId' => 56
+ 'fileId' => 56,
], $data);
}
@@ -286,7 +307,7 @@ public function testExportProjectTranslation()
{
$params = [
'targetLanguageId' => 'en',
- 'fileIds' => [7, 14, 15]
+ 'fileIds' => [7, 14, 15],
];
$this->mockRequest(
@@ -298,12 +319,15 @@ public function testExportProjectTranslation()
"url": "https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff?response-content-disposition=attachment%3B%20filename%3D%22APP.xliff%22&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIGJKLQV66ZXPMMEA%2F20190920%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190920T093121Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=439ebd69a1b7e4c23e6d17891a491c94f832e0c82e4692dedb35a6cd1e624b62",
"expireIn": "2019-09-20T10:31:21+00:00"
}
- }'
+ }',
]
);
$file = $this->crowdin->translation->exportProjectTranslation(2, $params);
$this->assertInstanceOf(DownloadFile::class, $file);
- $this->assertEquals('https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff?response-content-disposition=attachment%3B%20filename%3D%22APP.xliff%22&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIGJKLQV66ZXPMMEA%2F20190920%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190920T093121Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=439ebd69a1b7e4c23e6d17891a491c94f832e0c82e4692dedb35a6cd1e624b62', $file->getUrl());
+ $this->assertEquals(
+ 'https://production-enterprise-importer.downloads.crowdin.com/992000002/2/14.xliff?response-content-disposition=attachment%3B%20filename%3D%22APP.xliff%22&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIGJKLQV66ZXPMMEA%2F20190920%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190920T093121Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=439ebd69a1b7e4c23e6d17891a491c94f832e0c82e4692dedb35a6cd1e624b62',
+ $file->getUrl()
+ );
}
}