Skip to content

Commit ce793fb

Browse files
authored
Merge pull request #25 from Invertus/BRD-344-feature/new-mass-update-endpoint
[BRD-344] feature / new-mass-update-endpoint
2 parents 3474e99 + 7091645 commit ce793fb

File tree

9 files changed

+927
-1
lines changed

9 files changed

+927
-1
lines changed

.phpunit.cache/test-results

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"version":1,"defects":{"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithVariants":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testSingleLocaleAdapter":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testFallbackToFirstAvailableValue":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithFeaturesOnlyInOneLocale":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformSimpleProduct":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithMultipleLocales":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformVariantWithoutRemoteId":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testCategoryFlattening":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testEmptyCategories":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testMultiLangName":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testConstructorWithEmptyLocales":7},"times":{"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testConstructorWithEmptyLocales":0.01,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testGetSupportedLocales":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testGetDefaultLocale":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidData":0.004,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithMissingProductsArray":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformSimpleProduct":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithMultipleLocales":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithVariants":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithMissingRequiredFields":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithMissingSku":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformVariantWithoutRemoteId":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testCategoryFlattening":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testEmptyCategories":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testImageUrlTransformation":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testSingleLocaleAdapter":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testFallbackToFirstAvailableValue":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithLocalizedFeatures":0.001,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithFeaturesOnlyInOneLocale":0.007,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testMultiLangName":0}}
1+
{"version":1,"defects":{"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithVariants":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testSingleLocaleAdapter":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testFallbackToFirstAvailableValue":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithFeaturesOnlyInOneLocale":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformSimpleProduct":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithMultipleLocales":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformVariantWithoutRemoteId":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testCategoryFlattening":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testEmptyCategories":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testMultiLangName":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testConstructorWithEmptyLocales":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidDescriptionTypes":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidImageUrlTypes":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidProductUrlTypes":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidCategoriesTypes":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidLocalizedValues":7,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidFeaturesTypes":7,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkTest::testCopyIndexReturnsTaskResponse":8,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkTest::testGetReindexStatusInProgress":8,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkTest::testGetReindexStatusCompleted":8,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkTest::testGetReindexStatusFailed":8,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkTest::testCancelReindexTaskSuccess":8,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkTest::testCancelReindexTaskError":8,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationsSuccess":8,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationsPartialFailure":7,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationsEmptyOperations":8,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationsInvalidOperationType":7,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationValidationIndexProducts":7,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationValidationUpdateProducts":7,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationValidationDeleteProducts":7,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationValidationDeleteIndex":7,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationValidationInvalidIndex":7,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationValidationInvalidProductData":7,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testDeleteIndexOperation":8,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testIndexProductsWithSubfieldsAndEmbeddableFields":8,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidVariantsTypes":7},"times":{"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testConstructorWithEmptyLocales":0.01,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testGetSupportedLocales":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testGetDefaultLocale":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidData":0.005,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithMissingProductsArray":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformSimpleProduct":0.001,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithMultipleLocales":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithVariants":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithMissingRequiredFields":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithMissingSku":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformVariantWithoutRemoteId":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testCategoryFlattening":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testEmptyCategories":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testImageUrlTransformation":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testSingleLocaleAdapter":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testFallbackToFirstAvailableValue":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithLocalizedFeatures":0.001,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformProductWithFeaturesOnlyInOneLocale":0.007,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testMultiLangName":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithZeroPriceValues":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testProductUrlTransformationWithMultipleLocales":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testProductUrlTransformationWithSingleLocale":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testProductUrlTransformationWithEmptyProductUrl":0.001,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testProductUrlTransformationWithFlatStructure":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithNonArrayProducts":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidBrandTypes":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidDescriptionTypes":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidImageUrlTypes":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidProductUrlTypes":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidCategoriesTypes":0.001,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidLocalizedValues":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithNullRequiredFields":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidFeaturesTypes":0,"BradSearch\\SyncSdk\\Tests\\Adapters\\PrestaShopAdapterTest::testTransformWithInvalidVariantsTypes":0,"BradSearch\\SyncSdk\\Tests\\Models\\ReindexResponseModelsTest::testReindexTaskResponseCreation":0,"BradSearch\\SyncSdk\\Tests\\Models\\ReindexResponseModelsTest::testReindexTaskResponseFromArray":0,"BradSearch\\SyncSdk\\Tests\\Models\\ReindexResponseModelsTest::testReindexTaskResponseToArray":0,"BradSearch\\SyncSdk\\Tests\\Models\\ReindexResponseModelsTest::testReindexStatusResponseInProgress":0.001,"BradSearch\\SyncSdk\\Tests\\Models\\ReindexResponseModelsTest::testReindexStatusResponseCompleted":0,"BradSearch\\SyncSdk\\Tests\\Models\\ReindexResponseModelsTest::testReindexStatusResponseFailed":0,"BradSearch\\SyncSdk\\Tests\\Models\\ReindexResponseModelsTest::testReindexStatusResponseToArray":0,"BradSearch\\SyncSdk\\Tests\\Models\\ReindexResponseModelsTest::testReindexCancelResponseSuccess":0,"BradSearch\\SyncSdk\\Tests\\Models\\ReindexResponseModelsTest::testReindexCancelResponseError":0,"BradSearch\\SyncSdk\\Tests\\Models\\ReindexResponseModelsTest::testReindexCancelResponseToArray":0,"BradSearch\\SyncSdk\\Tests\\Models\\BulkOperationTest::testIndexProductsOperation":0,"BradSearch\\SyncSdk\\Tests\\Models\\BulkOperationTest::testUpdateProductsOperation":0,"BradSearch\\SyncSdk\\Tests\\Models\\BulkOperationTest::testDeleteProductsOperation":0,"BradSearch\\SyncSdk\\Tests\\Models\\BulkOperationTest::testDeleteIndexOperation":0,"BradSearch\\SyncSdk\\Tests\\Models\\BulkOperationTest::testIndexProductsWithoutOptionalFields":0,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationsSuccess":0.01,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationsPartialFailure":0,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationsEmptyOperations":0,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationsInvalidOperationType":0,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationValidationIndexProducts":0,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationValidationUpdateProducts":0,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationValidationDeleteProducts":0,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationValidationDeleteIndex":0,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationValidationInvalidIndex":0,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testBulkOperationValidationInvalidProductData":0,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testDeleteIndexOperation":0,"BradSearch\\SyncSdk\\Tests\\SynchronizationApiSdkBulkOperationsTest::testIndexProductsWithSubfieldsAndEmbeddableFields":0}}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
3+
require_once __DIR__ . '/../vendor/autoload.php';
4+
5+
use BradSearch\SyncSdk\SynchronizationApiSdk;
6+
use BradSearch\SyncSdk\Config\SyncConfig;
7+
use BradSearch\SyncSdk\Models\FieldConfig;
8+
use BradSearch\SyncSdk\Models\BulkOperation;
9+
use BradSearch\SyncSdk\Enums\FieldType;
10+
11+
// Example: Bulk Operations API Usage
12+
13+
// Configure the SDK
14+
$config = new SyncConfig('https://your-api-domain.com', 'your-jwt-token');
15+
16+
$fieldConfiguration = [
17+
'id' => new FieldConfig(FieldType::KEYWORD, []),
18+
'name' => new FieldConfig(FieldType::TEXT_KEYWORD, []),
19+
'price' => new FieldConfig(FieldType::FLOAT, []),
20+
'brand' => new FieldConfig(FieldType::TEXT_KEYWORD, []),
21+
'category' => new FieldConfig(FieldType::HIERARCHY, [])
22+
];
23+
24+
$sdk = new SynchronizationApiSdk($config, $fieldConfiguration);
25+
26+
try {
27+
// Create multiple bulk operations
28+
$operations = [
29+
// 1. Index new products
30+
BulkOperation::indexProducts('products-v1', [
31+
[
32+
'id' => 'prod-001',
33+
'name' => 'Wireless Headphones',
34+
'price' => 99.99,
35+
'brand' => 'TechBrand',
36+
'category' => 'Electronics > Audio > Headphones'
37+
],
38+
[
39+
'id' => 'prod-002',
40+
'name' => 'Bluetooth Speaker',
41+
'price' => 149.99,
42+
'brand' => 'AudioTech',
43+
'category' => 'Electronics > Audio > Speakers'
44+
]
45+
],
46+
// Optional: Add subfields configuration
47+
[
48+
'name' => [
49+
'split_by' => [' ', '-'],
50+
'max_count' => 3
51+
]
52+
],
53+
// Optional: Add embeddable fields configuration
54+
[
55+
'description' => 'name'
56+
]),
57+
58+
// 2. Update existing products
59+
BulkOperation::updateProducts('products-v1', [
60+
[
61+
'id' => 'prod-123',
62+
'fields' => [
63+
'name' => 'Premium Wireless Headphones',
64+
'price' => 129.99
65+
]
66+
],
67+
[
68+
'id' => 'prod-124',
69+
'fields' => [
70+
'price' => 139.99
71+
]
72+
]
73+
]),
74+
75+
// 3. Delete specific products
76+
BulkOperation::deleteProducts('products-v1', [
77+
'prod-125',
78+
'prod-126',
79+
'prod-127'
80+
]),
81+
];
82+
83+
// Execute all operations in a single API call
84+
$result = $sdk->bulkOperations($operations);
85+
86+
// Check results
87+
echo "Bulk Operations Result:\n";
88+
echo "Status: " . $result->status . "\n";
89+
echo "Total Operations: " . $result->totalOperations . "\n";
90+
echo "Successful: " . $result->successfulOperations . "\n";
91+
echo "Failed: " . $result->failedOperations . "\n";
92+
echo "Processing Time: " . $result->processingTimeMs . "ms\n\n";
93+
94+
if ($result->isSuccess()) {
95+
echo "✅ All operations completed successfully!\n";
96+
} elseif ($result->isPartialSuccess()) {
97+
echo "⚠️ Some operations failed:\n";
98+
foreach ($result->getFailedResults() as $failed) {
99+
echo "- {$failed['type']}: {$failed['message']}\n";
100+
}
101+
} else {
102+
echo "❌ All operations failed\n";
103+
}
104+
105+
// Detailed results
106+
echo "\nDetailed Results:\n";
107+
foreach ($result->results as $operationResult) {
108+
$status = $operationResult['status'] === 'success' ? '' : '';
109+
echo "{$status} {$operationResult['type']}: {$operationResult['message']}\n";
110+
}
111+
112+
} catch (Exception $e) {
113+
echo "Error: " . $e->getMessage() . "\n";
114+
}

src/Enums/BulkOperationType.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace BradSearch\SyncSdk\Enums;
6+
7+
enum BulkOperationType: string
8+
{
9+
case INDEX_PRODUCTS = 'index_products';
10+
case UPDATE_PRODUCTS = 'update_products';
11+
case DELETE_PRODUCTS = 'delete_products';
12+
}

src/Models/BulkOperation.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace BradSearch\SyncSdk\Models;
6+
7+
use BradSearch\SyncSdk\Enums\BulkOperationType;
8+
9+
class BulkOperation
10+
{
11+
public function __construct(
12+
public readonly BulkOperationType $type,
13+
public readonly array $payload
14+
) {}
15+
16+
public function toArray(): array
17+
{
18+
return [
19+
'type' => $this->type->value,
20+
'payload' => $this->payload
21+
];
22+
}
23+
24+
public static function indexProducts(string $indexName, array $products, array $subfields = [], array $embeddableFields = []): self
25+
{
26+
$payload = [
27+
'index_name' => $indexName,
28+
'products' => $products
29+
];
30+
31+
if (!empty($subfields)) {
32+
$payload['subfields'] = $subfields;
33+
}
34+
35+
if (!empty($embeddableFields)) {
36+
$payload['embeddablefields'] = $embeddableFields;
37+
}
38+
39+
return new self(BulkOperationType::INDEX_PRODUCTS, $payload);
40+
}
41+
42+
public static function updateProducts(string $indexName, array $updates): self
43+
{
44+
return new self(BulkOperationType::UPDATE_PRODUCTS, [
45+
'index_name' => $indexName,
46+
'updates' => $updates
47+
]);
48+
}
49+
50+
public static function deleteProducts(string $indexName, array $productIds): self
51+
{
52+
return new self(BulkOperationType::DELETE_PRODUCTS, [
53+
'index_name' => $indexName,
54+
'product_ids' => $productIds
55+
]);
56+
}
57+
}

src/Models/BulkOperationResult.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace BradSearch\SyncSdk\Models;
6+
7+
class BulkOperationResult
8+
{
9+
public function __construct(
10+
public readonly string $status,
11+
public readonly string $message,
12+
public readonly int $totalOperations,
13+
public readonly int $successfulOperations,
14+
public readonly int $failedOperations,
15+
public readonly int $processingTimeMs,
16+
public readonly array $results
17+
) {}
18+
19+
public static function fromApiResponse(array $response): self
20+
{
21+
return new self(
22+
status: $response['status'],
23+
message: $response['message'],
24+
totalOperations: $response['total_operations'],
25+
successfulOperations: $response['successful_operations'],
26+
failedOperations: $response['failed_operations'],
27+
processingTimeMs: $response['processing_time_ms'],
28+
results: $response['results']
29+
);
30+
}
31+
32+
public function isSuccess(): bool
33+
{
34+
return $this->status === 'success';
35+
}
36+
37+
public function isPartialSuccess(): bool
38+
{
39+
return $this->status === 'partial';
40+
}
41+
42+
public function hasFailures(): bool
43+
{
44+
return $this->failedOperations > 0;
45+
}
46+
47+
public function getFailedResults(): array
48+
{
49+
return array_filter($this->results, fn($result) => $result['status'] === 'error');
50+
}
51+
52+
public function getSuccessfulResults(): array
53+
{
54+
return array_filter($this->results, fn($result) => $result['status'] === 'success');
55+
}
56+
}

0 commit comments

Comments
 (0)