diff --git a/src/CrowdinApiClient/Api/BranchApi.php b/src/CrowdinApiClient/Api/BranchApi.php
index b82f3157..b4083b04 100644
--- a/src/CrowdinApiClient/Api/BranchApi.php
+++ b/src/CrowdinApiClient/Api/BranchApi.php
@@ -3,6 +3,9 @@
namespace CrowdinApiClient\Api;
use CrowdinApiClient\Model\Branch;
+use CrowdinApiClient\Model\BranchClone;
+use CrowdinApiClient\Model\BranchMerge;
+use CrowdinApiClient\Model\BranchMergeSummary;
use CrowdinApiClient\ModelCollection;
/**
@@ -57,7 +60,8 @@ public function get(int $projectId, int $branchId): ?Branch
* string $data[name] required Note: Can't contain \\ / : * ? \" < > | symbols
* string $data[title]
* string $data[exportPattern] Note: Can't contain \\ / : * ? \" < > | symbols
- * string $data[priority] Enum: "low" "normal" "high"
+ * string $data[priority] Enum: "low" "normal" "high"
+ * bool $data[isProtected] String-based projects only
* @return Branch|null
*/
public function create(int $projectId, array $data): ?Branch
@@ -95,4 +99,101 @@ public function delete(int $projectId, int $branchId)
$path = sprintf('projects/%d/branches/%d', $projectId, $branchId);
return $this->_delete($path);
}
+
+ /**
+ * Clone Branch
+ * @link https://developer.crowdin.com/api/v2/string-based/#operation/api.projects.branches.clones.post API Documentation
+ *
+ * @param int $projectId
+ * @param int $branchId
+ * @param array $data
+ * string $data[name] required Note: Can't contain \\ / : * ? \" < > | symbols
+ * string $data[title]
+ * bool $data[isProtected]
+ * @return BranchClone|null
+ */
+ public function cloneBranch(int $projectId, int $branchId, array $data): ?BranchClone
+ {
+ $path = sprintf('projects/%d/branches/%d/clones', $projectId, $branchId);
+ return $this->_post($path, BranchClone::class, $data);
+ }
+
+ /**
+ * Check Branch Clone Status
+ * @link https://developer.crowdin.com/api/v2/string-based/#operation/api.projects.branches.clones.get API Documentation
+ *
+ * @param int $projectId
+ * @param int $branchId
+ * @param string $cloneId
+ * @return BranchClone|null
+ */
+ public function checkCloneStatus(int $projectId, int $branchId, string $cloneId): ?BranchClone
+ {
+ $path = sprintf('projects/%d/branches/%d/clones/%s', $projectId, $branchId, $cloneId);
+ return $this->_get($path, BranchClone::class);
+ }
+
+ /**
+ * Get Cloned Branch
+ * @link https://developer.crowdin.com/api/v2/string-based/#operation/api.projects.branches.clones.branch.get API Documentation
+ *
+ * @param int $projectId
+ * @param int $branchId
+ * @param string $cloneId
+ * @return Branch|null
+ */
+ public function getClonedBranch(int $projectId, int $branchId, string $cloneId): ?Branch
+ {
+ $path = sprintf('projects/%d/branches/%d/clones/%s/branch', $projectId, $branchId, $cloneId);
+ return $this->_get($path, Branch::class);
+ }
+
+ /**
+ * Merge Branch
+ * @link https://developer.crowdin.com/api/v2/string-based/#operation/api.projects.branches.merges.post API Documentation
+ *
+ * @param int $projectId
+ * @param int $branchId
+ * @param array $data
+ * int $data[sourceBranchId] required
+ * bool $data[deleteAfterMerge]
+ * bool $data[dryRun]
+ * bool $data[acceptSourceChanges]
+ * @return BranchMerge|null
+ */
+ public function mergeBranch(int $projectId, int $branchId, array $data): ?BranchMerge
+ {
+ $path = sprintf('projects/%d/branches/%d/merges', $projectId, $branchId);
+ return $this->_post($path, BranchMerge::class, $data);
+ }
+
+ /**
+ * Check Branch Merge Status
+ * @link https://developer.crowdin.com/api/v2/string-based/#operation/api.projects.branches.merges.get API Documentation
+ *
+ * @param int $projectId
+ * @param int $branchId
+ * @param string $mergeId
+ * @return BranchMerge|null
+ */
+ public function checkMergeStatus(int $projectId, int $branchId, string $mergeId): ?BranchMerge
+ {
+ $path = sprintf('projects/%d/branches/%d/merges/%s', $projectId, $branchId, $mergeId);
+ return $this->_get($path, BranchMerge::class);
+ }
+
+ /**
+ * Get Branch Merge Summary
+ * @link https://developer.crowdin.com/api/v2/string-based/#operation/api.projects.branches.merges.summary.get API Documentation
+ *
+ * @param int $projectId
+ * @param int $branchId
+ * @param string $mergeId
+ * @return BranchMergeSummary|null
+ */
+ public function getMergeSummary(int $projectId, int $branchId, string $mergeId): ?BranchMergeSummary
+ {
+ $path = sprintf('projects/%d/branches/%d/merges/%s/summary', $projectId, $branchId, $mergeId);
+ return $this->_get($path, BranchMergeSummary::class);
+ }
}
diff --git a/src/CrowdinApiClient/Api/BundleApi.php b/src/CrowdinApiClient/Api/BundleApi.php
index 55933be8..14e7b018 100644
--- a/src/CrowdinApiClient/Api/BundleApi.php
+++ b/src/CrowdinApiClient/Api/BundleApi.php
@@ -2,6 +2,7 @@
namespace CrowdinApiClient\Api;
+use CrowdinApiClient\Model\Branch;
use CrowdinApiClient\Model\Bundle;
use CrowdinApiClient\Model\BundleExport;
use CrowdinApiClient\Model\DownloadFile;
@@ -116,6 +117,23 @@ public function listFiles(int $projectId, int $bundleId, array $params = []): Mo
return $this->_list($path, File::class, $params);
}
+ /**
+ * List Bundle Branches
+ * @link https://developer.crowdin.com/api/v2/string-based/#operation/api.projects.bundles.branches.getMany API Documentation
+ *
+ * @param int $projectId
+ * @param int $bundleId
+ * @param array $params
+ * integer $params[limit]
+ * integer $params[offset]
+ * @return ModelCollection
+ */
+ public function listBranches(int $projectId, int $bundleId, array $params = []): ModelCollection
+ {
+ $path = sprintf('projects/%d/bundles/%d/branches', $projectId, $bundleId);
+ return $this->_list($path, Branch::class, $params);
+ }
+
/**
* Export Bundle
* @link https://developer.crowdin.com/api/v2/#operation/api.projects.bundles.exports.post API Documentation
diff --git a/src/CrowdinApiClient/Api/DistributionApi.php b/src/CrowdinApiClient/Api/DistributionApi.php
index ea6eb016..c0520475 100644
--- a/src/CrowdinApiClient/Api/DistributionApi.php
+++ b/src/CrowdinApiClient/Api/DistributionApi.php
@@ -51,9 +51,10 @@ public function get(int $projectId, string $hash): ?Distribution
*
* @param int $projectId
* @param array $data
- * string $data[exportMode] Enum: "default" "bundle" Default: "default"
+ * string $data[exportMode] Enum: "default" "bundle" Default: "default" Note: String-based projects use "bundle" only
* string $data[name] required
- * int[] $data[fileIds] required
+ * int[] $data[fileIds] Required for file-based projects (default export mode)
+ * int[] $data[bundleIds] Required for string-based projects
* string $data[format] required for 'bundle' export mode
* string $data[exportPattern] required for 'bundle' export mode. Note: Can't contain \\ / : * ? \" < > | symbols
* int[] $data[labelIds]
diff --git a/src/CrowdinApiClient/Api/SourceStringApi.php b/src/CrowdinApiClient/Api/SourceStringApi.php
index e84abc5c..a951b312 100644
--- a/src/CrowdinApiClient/Api/SourceStringApi.php
+++ b/src/CrowdinApiClient/Api/SourceStringApi.php
@@ -3,6 +3,7 @@
namespace CrowdinApiClient\Api;
use CrowdinApiClient\Model\SourceString;
+use CrowdinApiClient\Model\StringUpload;
use CrowdinApiClient\ModelCollection;
/**
@@ -50,9 +51,10 @@ public function get(int $projectId, int $stringId): ?SourceString
*
* @param int $projectId
* @param array $data
- * string $data[identifier] Required for strings-based projects or file-based projects if scheme of CSV file includes identifier column
+ * string $data[identifier] Required for string-based projects or file-based projects if scheme of CSV file includes identifier column
* string $data[text] required
- * integer $data[fileId]
+ * integer $data[branchId] Required for string-based projects
+ * integer $data[fileId] Required for file-based projects
* string $data[context]
* bool $data[isHidden]
* integer $data[maxLength]
@@ -110,4 +112,41 @@ public function batchOperations(int $projectId, array $data)
$path = sprintf('projects/%d/strings', $projectId);
return $this->_patch($path, SourceString::class, $data);
}
+
+ /**
+ * Upload Strings
+ * @link https://developer.crowdin.com/api/v2/string-based/#operation/api.projects.strings.uploads.post API Documentation
+ *
+ * @param int $projectId
+ * @param array $data
+ * int $data[storageId] required
+ * int $data[branchId] required
+ * string $data[type]
+ * int $data[parserVersion]
+ * int[] $data[labelIds]
+ * bool $data[updateStrings]
+ * bool $data[cleanupMode]
+ * array $data[importOptions]
+ * string $data[updateOption]
+ * @return StringUpload|null
+ */
+ public function uploadStrings(int $projectId, array $data): ?StringUpload
+ {
+ $path = sprintf('projects/%d/strings/uploads', $projectId);
+ return $this->_post($path, StringUpload::class, $data);
+ }
+
+ /**
+ * Check Upload Strings Status
+ * @link https://developer.crowdin.com/api/v2/string-based/#operation/api.projects.strings.uploads.get API Documentation
+ *
+ * @param int $projectId
+ * @param string $uploadId
+ * @return StringUpload|null
+ */
+ public function checkUploadStatus(int $projectId, string $uploadId): ?StringUpload
+ {
+ $path = sprintf('projects/%d/strings/uploads/%s', $projectId, $uploadId);
+ return $this->_get($path, StringUpload::class);
+ }
}
diff --git a/src/CrowdinApiClient/Api/TranslationApi.php b/src/CrowdinApiClient/Api/TranslationApi.php
index 04183a5a..613d1e28 100644
--- a/src/CrowdinApiClient/Api/TranslationApi.php
+++ b/src/CrowdinApiClient/Api/TranslationApi.php
@@ -43,7 +43,8 @@ public function listPreTranslations(int $projectId, array $params = []): ModelCo
* @param int $projectId
* @param array $params
* string[] $params[languageIds] required
- * int[] $params[fileIds] required
+ * int[] $params[fileIds] Required for file-based projects
+ * int[] $params[branchIds] String-based projects only
* string $params[method]
* int $params[engineId]
* string $params[autoApproveOption]
diff --git a/src/CrowdinApiClient/Model/Branch.php b/src/CrowdinApiClient/Model/Branch.php
index 6af34609..34d81bbf 100644
--- a/src/CrowdinApiClient/Model/Branch.php
+++ b/src/CrowdinApiClient/Model/Branch.php
@@ -37,6 +37,11 @@ class Branch extends BaseModel
*/
protected $priority;
+ /**
+ * @var bool
+ */
+ protected $isProtected;
+
/**
* @var string
*/
@@ -57,6 +62,7 @@ public function __construct(array $data = [])
$this->title = (string)$this->getDataProperty('title');
$this->exportPattern = (string)$this->getDataProperty('exportPattern');
$this->priority = (string)$this->getDataProperty('priority');
+ $this->isProtected = (bool)$this->getDataProperty('isProtected');
$this->createdAt = (string)$this->getDataProperty('createdAt');
$this->updatedAt = (string)$this->getDataProperty('updatedAt');
}
@@ -141,6 +147,11 @@ public function setPriority(string $priority): void
$this->priority = $priority;
}
+ public function isProtected(): bool
+ {
+ return $this->isProtected;
+ }
+
/**
* @return string
*/
diff --git a/src/CrowdinApiClient/Model/BranchClone.php b/src/CrowdinApiClient/Model/BranchClone.php
new file mode 100644
index 00000000..e35b5f8d
--- /dev/null
+++ b/src/CrowdinApiClient/Model/BranchClone.php
@@ -0,0 +1,103 @@
+identifier = (string)$this->getDataProperty('identifier');
+ $this->status = (string)$this->getDataProperty('status');
+ $this->progress = (int)$this->getDataProperty('progress');
+ $this->attributes = (array)$this->getDataProperty('attributes');
+ $this->createdAt = (string)$this->getDataProperty('createdAt');
+ $this->updatedAt = (string)$this->getDataProperty('updatedAt');
+ $this->startedAt = $this->getDataProperty('startedAt');
+ $this->finishedAt = $this->getDataProperty('finishedAt');
+ }
+
+ public function getIdentifier(): string
+ {
+ return $this->identifier;
+ }
+
+ public function getStatus(): string
+ {
+ return $this->status;
+ }
+
+ public function getProgress(): int
+ {
+ return $this->progress;
+ }
+
+ public function getAttributes(): array
+ {
+ return $this->attributes;
+ }
+
+ public function getCreatedAt(): string
+ {
+ return $this->createdAt;
+ }
+
+ public function getUpdatedAt(): string
+ {
+ return $this->updatedAt;
+ }
+
+ public function getStartedAt(): ?string
+ {
+ return $this->startedAt;
+ }
+
+ public function getFinishedAt(): ?string
+ {
+ return $this->finishedAt;
+ }
+}
diff --git a/src/CrowdinApiClient/Model/BranchMerge.php b/src/CrowdinApiClient/Model/BranchMerge.php
new file mode 100644
index 00000000..7ab9fc3a
--- /dev/null
+++ b/src/CrowdinApiClient/Model/BranchMerge.php
@@ -0,0 +1,103 @@
+identifier = (string)$this->getDataProperty('identifier');
+ $this->status = (string)$this->getDataProperty('status');
+ $this->progress = (int)$this->getDataProperty('progress');
+ $this->attributes = (array)$this->getDataProperty('attributes');
+ $this->createdAt = (string)$this->getDataProperty('createdAt');
+ $this->updatedAt = (string)$this->getDataProperty('updatedAt');
+ $this->startedAt = $this->getDataProperty('startedAt');
+ $this->finishedAt = $this->getDataProperty('finishedAt');
+ }
+
+ public function getIdentifier(): string
+ {
+ return $this->identifier;
+ }
+
+ public function getStatus(): string
+ {
+ return $this->status;
+ }
+
+ public function getProgress(): int
+ {
+ return $this->progress;
+ }
+
+ public function getAttributes(): array
+ {
+ return $this->attributes;
+ }
+
+ public function getCreatedAt(): string
+ {
+ return $this->createdAt;
+ }
+
+ public function getUpdatedAt(): string
+ {
+ return $this->updatedAt;
+ }
+
+ public function getStartedAt(): ?string
+ {
+ return $this->startedAt;
+ }
+
+ public function getFinishedAt(): ?string
+ {
+ return $this->finishedAt;
+ }
+}
diff --git a/src/CrowdinApiClient/Model/BranchMergeSummary.php b/src/CrowdinApiClient/Model/BranchMergeSummary.php
new file mode 100644
index 00000000..eef3527e
--- /dev/null
+++ b/src/CrowdinApiClient/Model/BranchMergeSummary.php
@@ -0,0 +1,81 @@
+status = (string)$this->getDataProperty('status');
+ $this->sourceBranchId = (int)$this->getDataProperty('sourceBranchId');
+ $this->targetBranchId = (int)$this->getDataProperty('targetBranchId');
+ $this->dryRun = (bool)$this->getDataProperty('dryRun');
+ $this->acceptSourceChanges = (bool)$this->getDataProperty('acceptSourceChanges');
+ $this->details = (array)$this->getDataProperty('details');
+ }
+
+ public function getStatus(): string
+ {
+ return $this->status;
+ }
+
+ public function getSourceBranchId(): int
+ {
+ return $this->sourceBranchId;
+ }
+
+ public function getTargetBranchId(): int
+ {
+ return $this->targetBranchId;
+ }
+
+ public function isDryRun(): bool
+ {
+ return $this->dryRun;
+ }
+
+ public function isAcceptSourceChanges(): bool
+ {
+ return $this->acceptSourceChanges;
+ }
+
+ public function getDetails(): array
+ {
+ return $this->details;
+ }
+}
diff --git a/src/CrowdinApiClient/Model/StringUpload.php b/src/CrowdinApiClient/Model/StringUpload.php
new file mode 100644
index 00000000..49e85d3f
--- /dev/null
+++ b/src/CrowdinApiClient/Model/StringUpload.php
@@ -0,0 +1,103 @@
+identifier = (string)$this->getDataProperty('identifier');
+ $this->status = (string)$this->getDataProperty('status');
+ $this->progress = (int)$this->getDataProperty('progress');
+ $this->attributes = (array)$this->getDataProperty('attributes');
+ $this->createdAt = (string)$this->getDataProperty('createdAt');
+ $this->updatedAt = (string)$this->getDataProperty('updatedAt');
+ $this->startedAt = $this->getDataProperty('startedAt');
+ $this->finishedAt = $this->getDataProperty('finishedAt');
+ }
+
+ public function getIdentifier(): string
+ {
+ return $this->identifier;
+ }
+
+ public function getStatus(): string
+ {
+ return $this->status;
+ }
+
+ public function getProgress(): int
+ {
+ return $this->progress;
+ }
+
+ public function getAttributes(): array
+ {
+ return $this->attributes;
+ }
+
+ public function getCreatedAt(): string
+ {
+ return $this->createdAt;
+ }
+
+ public function getUpdatedAt(): string
+ {
+ return $this->updatedAt;
+ }
+
+ public function getStartedAt(): ?string
+ {
+ return $this->startedAt;
+ }
+
+ public function getFinishedAt(): ?string
+ {
+ return $this->finishedAt;
+ }
+}
diff --git a/tests/CrowdinApiClient/Api/BranchApiTest.php b/tests/CrowdinApiClient/Api/BranchApiTest.php
index 80aa6ed0..47d0b14d 100644
--- a/tests/CrowdinApiClient/Api/BranchApiTest.php
+++ b/tests/CrowdinApiClient/Api/BranchApiTest.php
@@ -3,6 +3,9 @@
namespace CrowdinApiClient\Tests\Api;
use CrowdinApiClient\Model\Branch;
+use CrowdinApiClient\Model\BranchClone;
+use CrowdinApiClient\Model\BranchMerge;
+use CrowdinApiClient\Model\BranchMergeSummary;
use CrowdinApiClient\ModelCollection;
class BranchApiTest extends AbstractTestApi
@@ -130,6 +133,193 @@ public function testDelete()
$this->crowdin->branch->delete(2, 34);
}
+ public function testCloneBranch(): void
+ {
+ $params = [
+ 'name' => 'develop-master-clone',
+ 'title' => 'Clone of Master branch',
+ ];
+
+ $this->mockRequest([
+ 'path' => '/projects/2/branches/34/clones',
+ 'method' => 'post',
+ 'body' => json_encode($params),
+ 'response' => json_encode([
+ 'data' => [
+ 'identifier' => 'a3b4c5d6-e7f8-9012-3456-789abc123def',
+ 'status' => 'created',
+ 'progress' => 0,
+ 'attributes' => [],
+ 'createdAt' => '2023-09-11T11:26:54+00:00',
+ 'updatedAt' => '2023-09-11T11:26:54+00:00',
+ 'startedAt' => null,
+ 'finishedAt' => null,
+ ],
+ ]),
+ ]);
+
+ $clone = $this->crowdin->branch->cloneBranch(2, 34, $params);
+
+ $this->assertInstanceOf(BranchClone::class, $clone);
+ $this->assertEquals('a3b4c5d6-e7f8-9012-3456-789abc123def', $clone->getIdentifier());
+ $this->assertEquals('created', $clone->getStatus());
+ $this->assertEquals(0, $clone->getProgress());
+ $this->assertEquals('2023-09-11T11:26:54+00:00', $clone->getCreatedAt());
+ }
+
+ public function testCheckCloneStatus(): void
+ {
+ $this->mockRequestGet(
+ '/projects/2/branches/34/clones/a3b4c5d6-e7f8-9012-3456-789abc123def',
+ json_encode([
+ 'data' => [
+ 'identifier' => 'a3b4c5d6-e7f8-9012-3456-789abc123def',
+ 'status' => 'finished',
+ 'progress' => 100,
+ 'attributes' => [],
+ 'createdAt' => '2023-09-11T11:26:54+00:00',
+ 'updatedAt' => '2023-09-11T11:26:57+00:00',
+ 'startedAt' => '2023-09-11T11:26:55+00:00',
+ 'finishedAt' => '2023-09-11T11:26:57+00:00',
+ ],
+ ])
+ );
+
+ $clone = $this->crowdin->branch->checkCloneStatus(2, 34, 'a3b4c5d6-e7f8-9012-3456-789abc123def');
+
+ $this->assertInstanceOf(BranchClone::class, $clone);
+ $this->assertEquals('finished', $clone->getStatus());
+ $this->assertEquals(100, $clone->getProgress());
+ $this->assertEquals('2023-09-11T11:26:57+00:00', $clone->getFinishedAt());
+ }
+
+ public function testGetClonedBranch(): void
+ {
+ $this->mockRequestGet(
+ '/projects/2/branches/34/clones/a3b4c5d6-e7f8-9012-3456-789abc123def/branch',
+ json_encode([
+ 'data' => [
+ 'id' => 35,
+ 'projectId' => 2,
+ 'name' => 'develop-master-clone',
+ 'title' => 'Clone of Master branch',
+ 'isProtected' => false,
+ 'createdAt' => '2023-09-11T11:26:57+00:00',
+ 'updatedAt' => null,
+ ],
+ ])
+ );
+
+ $branch = $this->crowdin->branch->getClonedBranch(2, 34, 'a3b4c5d6-e7f8-9012-3456-789abc123def');
+
+ $this->assertInstanceOf(Branch::class, $branch);
+ $this->assertEquals(35, $branch->getId());
+ $this->assertEquals(2, $branch->getProjectId());
+ $this->assertEquals('develop-master-clone', $branch->getName());
+ $this->assertFalse($branch->isProtected());
+ }
+
+ public function testMergeBranch(): void
+ {
+ $params = [
+ 'sourceBranchId' => 33,
+ 'deleteAfterMerge' => false,
+ ];
+
+ $this->mockRequest([
+ 'path' => '/projects/2/branches/34/merges',
+ 'method' => 'post',
+ 'body' => json_encode($params),
+ 'response' => json_encode([
+ 'data' => [
+ 'identifier' => 'b4c5d6e7-f8a9-0123-4567-890bcd234efa',
+ 'status' => 'created',
+ 'progress' => 0,
+ 'attributes' => [
+ 'sourceBranchId' => 33,
+ 'deleteAfterMerge' => false,
+ 'dryRun' => false,
+ 'acceptSourceChanges' => false,
+ ],
+ 'createdAt' => '2023-09-11T11:26:54+00:00',
+ 'updatedAt' => '2023-09-11T11:26:54+00:00',
+ 'startedAt' => null,
+ 'finishedAt' => null,
+ ],
+ ]),
+ ]);
+
+ $merge = $this->crowdin->branch->mergeBranch(2, 34, $params);
+
+ $this->assertInstanceOf(BranchMerge::class, $merge);
+ $this->assertEquals('b4c5d6e7-f8a9-0123-4567-890bcd234efa', $merge->getIdentifier());
+ $this->assertEquals('created', $merge->getStatus());
+ $this->assertEquals(0, $merge->getProgress());
+ }
+
+ public function testCheckMergeStatus(): void
+ {
+ $this->mockRequestGet(
+ '/projects/2/branches/34/merges/b4c5d6e7-f8a9-0123-4567-890bcd234efa',
+ json_encode([
+ 'data' => [
+ 'identifier' => 'b4c5d6e7-f8a9-0123-4567-890bcd234efa',
+ 'status' => 'finished',
+ 'progress' => 100,
+ 'attributes' => [
+ 'sourceBranchId' => 33,
+ 'deleteAfterMerge' => false,
+ 'dryRun' => false,
+ 'acceptSourceChanges' => false,
+ ],
+ 'createdAt' => '2023-09-11T11:26:54+00:00',
+ 'updatedAt' => '2023-09-11T11:26:56+00:00',
+ 'startedAt' => '2023-09-11T11:26:55+00:00',
+ 'finishedAt' => '2023-09-11T11:26:56+00:00',
+ ],
+ ])
+ );
+
+ $merge = $this->crowdin->branch->checkMergeStatus(2, 34, 'b4c5d6e7-f8a9-0123-4567-890bcd234efa');
+
+ $this->assertInstanceOf(BranchMerge::class, $merge);
+ $this->assertEquals('finished', $merge->getStatus());
+ $this->assertEquals(100, $merge->getProgress());
+ $this->assertEquals('2023-09-11T11:26:56+00:00', $merge->getFinishedAt());
+ }
+
+ public function testGetMergeSummary(): void
+ {
+ $this->mockRequestGet(
+ '/projects/2/branches/34/merges/b4c5d6e7-f8a9-0123-4567-890bcd234efa/summary',
+ json_encode([
+ 'data' => [
+ 'status' => 'merged',
+ 'sourceBranchId' => 33,
+ 'targetBranchId' => 34,
+ 'dryRun' => false,
+ 'acceptSourceChanges' => false,
+ 'details' => [
+ 'added' => 5,
+ 'deleted' => 1,
+ 'updated' => 3,
+ 'conflicted' => 0,
+ ],
+ ],
+ ])
+ );
+
+ $summary = $this->crowdin->branch->getMergeSummary(2, 34, 'b4c5d6e7-f8a9-0123-4567-890bcd234efa');
+
+ $this->assertInstanceOf(BranchMergeSummary::class, $summary);
+ $this->assertEquals('merged', $summary->getStatus());
+ $this->assertEquals(33, $summary->getSourceBranchId());
+ $this->assertEquals(34, $summary->getTargetBranchId());
+ $this->assertFalse($summary->isDryRun());
+ $this->assertFalse($summary->isAcceptSourceChanges());
+ $this->assertEquals(['added' => 5, 'deleted' => 1, 'updated' => 3, 'conflicted' => 0], $summary->getDetails());
+ }
+
public function testUpdate()
{
$mock = $this->mockClient
diff --git a/tests/CrowdinApiClient/Api/BundleApiTest.php b/tests/CrowdinApiClient/Api/BundleApiTest.php
index 7362158e..b7439fbc 100644
--- a/tests/CrowdinApiClient/Api/BundleApiTest.php
+++ b/tests/CrowdinApiClient/Api/BundleApiTest.php
@@ -2,6 +2,7 @@
namespace CrowdinApiClient\Tests\Api;
+use CrowdinApiClient\Model\Branch;
use CrowdinApiClient\Model\Bundle;
use CrowdinApiClient\Model\BundleExport;
use CrowdinApiClient\Model\DownloadFile;
@@ -218,6 +219,42 @@ public function testListFiles(): void
$this->assertEquals(44, $files[0]->getId());
}
+ public function testListBranches(): void
+ {
+ $this->mockRequest([
+ 'path' => '/projects/2/bundles/34/branches',
+ 'method' => 'get',
+ 'response' => json_encode([
+ 'data' => [
+ [
+ 'data' => [
+ 'id' => 10,
+ 'projectId' => 2,
+ 'name' => 'develop-master',
+ 'title' => 'Master branch',
+ 'isProtected' => false,
+ 'createdAt' => '2023-09-11T11:26:54+00:00',
+ 'updatedAt' => null,
+ ],
+ ],
+ ],
+ 'pagination' => [
+ 'offset' => 0,
+ 'limit' => 25,
+ ],
+ ]),
+ ]);
+
+ $branches = $this->crowdin->bundle->listBranches(2, 34);
+
+ $this->assertInstanceOf(ModelCollection::class, $branches);
+ $this->assertCount(1, $branches);
+ $this->assertInstanceOf(Branch::class, $branches[0]);
+ $this->assertEquals(10, $branches[0]->getId());
+ $this->assertEquals('develop-master', $branches[0]->getName());
+ $this->assertFalse($branches[0]->isProtected());
+ }
+
public function testExport(): void
{
$params = [];
diff --git a/tests/CrowdinApiClient/Api/SourceStringApiTest.php b/tests/CrowdinApiClient/Api/SourceStringApiTest.php
index b8fc3a1c..c7633f99 100644
--- a/tests/CrowdinApiClient/Api/SourceStringApiTest.php
+++ b/tests/CrowdinApiClient/Api/SourceStringApiTest.php
@@ -3,6 +3,7 @@
namespace CrowdinApiClient\Tests\Api;
use CrowdinApiClient\Model\SourceString;
+use CrowdinApiClient\Model\StringUpload;
use CrowdinApiClient\ModelCollection;
class SourceStringApiTest extends AbstractTestApi
@@ -221,4 +222,71 @@ public function testBatch()
$this->assertInstanceOf(SourceString::class, $batchResult);
}
+
+ public function testUploadStrings(): void
+ {
+ $params = [
+ 'storageId' => 1001,
+ 'branchId' => 34,
+ ];
+
+ $this->mockRequest([
+ 'path' => '/projects/2/strings/uploads',
+ 'method' => 'post',
+ 'body' => json_encode($params),
+ 'response' => json_encode([
+ 'data' => [
+ 'identifier' => 'c5d6e7f8-a9b0-1234-5678-901cde345fab',
+ 'status' => 'created',
+ 'progress' => 0,
+ 'attributes' => [
+ 'storageId' => 1001,
+ 'branchId' => 34,
+ ],
+ 'createdAt' => '2023-09-11T11:26:54+00:00',
+ 'updatedAt' => '2023-09-11T11:26:54+00:00',
+ 'startedAt' => null,
+ 'finishedAt' => null,
+ ],
+ ]),
+ ]);
+
+ $upload = $this->crowdin->sourceString->uploadStrings(2, $params);
+
+ $this->assertInstanceOf(StringUpload::class, $upload);
+ $this->assertEquals('c5d6e7f8-a9b0-1234-5678-901cde345fab', $upload->getIdentifier());
+ $this->assertEquals('created', $upload->getStatus());
+ $this->assertEquals(0, $upload->getProgress());
+ $this->assertEquals(['storageId' => 1001, 'branchId' => 34], $upload->getAttributes());
+ }
+
+ public function testCheckUploadStatus(): void
+ {
+ $this->mockRequestGet(
+ '/projects/2/strings/uploads/c5d6e7f8-a9b0-1234-5678-901cde345fab',
+ json_encode([
+ 'data' => [
+ 'identifier' => 'c5d6e7f8-a9b0-1234-5678-901cde345fab',
+ 'status' => 'finished',
+ 'progress' => 100,
+ 'attributes' => [
+ 'storageId' => 1001,
+ 'branchId' => 34,
+ ],
+ 'createdAt' => '2023-09-11T11:26:54+00:00',
+ 'updatedAt' => '2023-09-11T11:26:56+00:00',
+ 'startedAt' => '2023-09-11T11:26:55+00:00',
+ 'finishedAt' => '2023-09-11T11:26:56+00:00',
+ ],
+ ])
+ );
+
+ $upload = $this->crowdin->sourceString->checkUploadStatus(2, 'c5d6e7f8-a9b0-1234-5678-901cde345fab');
+
+ $this->assertInstanceOf(StringUpload::class, $upload);
+ $this->assertEquals('finished', $upload->getStatus());
+ $this->assertEquals(100, $upload->getProgress());
+ $this->assertEquals('2023-09-11T11:26:56+00:00', $upload->getFinishedAt());
+ $this->assertEquals('2023-09-11T11:26:55+00:00', $upload->getStartedAt());
+ }
}