PluginProbe
ووسلام – همگام سازی ووکامرس و باسلام / 1.10.19
ووسلام – همگام سازی ووکامرس و باسلام v1.10.19
1.10.19 1.10.20 1.10.18 1.10.17 1.10.15 1.10.14 1.10.13 1.10.12 1.10.10 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.2 1.9.1 1.9.0 1.8.8 1.8.5 1.8.6 All 53 releases
sync-basalam / includes / Services / Products / UpdateProductVariationsService.php

UpdateProductVariationsService.php in ووسلام – همگام سازی ووکامرس و باسلام 1.10.19, at includes/Services/Products/UpdateProductVariationsService.php

140 lines 4.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SyncBasalam\Services\Products;
4
5 use SyncBasalam\Config\Endpoints;
6 use SyncBasalam\Jobs\Exceptions\NonRetryableException;
7 use SyncBasalam\Jobs\Exceptions\RetryableException;
8 use SyncBasalam\Logger\Logger;
9 use SyncBasalam\Services\ApiServiceManager;
10
11 defined('ABSPATH') || exit;
12
13 class UpdateProductVariationsService
14 {
15 /** Variant fields that are sent to the single-variation endpoint. */
16 private const VARIATION_FIELDS = ['primary_price', 'stock', 'sku'];
17
18 private $apiservice;
19
20 public function __construct()
21 {
22 $this->apiservice = syncBasalamContainer()->get(ApiServiceManager::class);
23 }
24
25 /**
26 * True when every variant already has a Basalam variation id, so each one can be
27 * updated with its own request instead of being sent inside the product payload.
28 */
29 public static function allVariantsHaveBasalamId(array $variants): bool
30 {
31 if (empty($variants)) return false;
32
33 foreach ($variants as $variant) {
34 if (empty($variant['id'])) return false;
35 }
36
37 return true;
38 }
39
40 /**
41 * Sends one PATCH request per variation.
42 *
43 * @return array{updated: int, skipped: int, failed: int}
44 */
45 public function updateVariations($basalamProductId, array $variants, $productId = null): array
46 {
47 $updated = 0;
48 $skipped = 0;
49 $failed = 0;
50 $firstError = null;
51
52 foreach ($variants as $variant) {
53 $data = array_intersect_key($variant, array_flip(self::VARIATION_FIELDS));
54 $data = array_filter($data, fn($value) => $value !== null);
55
56 if (empty($data)) {
57 $skipped++;
58 continue;
59 }
60
61 $url = sprintf(Endpoints::PRODUCT_VARIATION_UPDATE, $basalamProductId, $variant['id']);
62
63 try {
64 $this->sendVariationUpdate($url, $data);
65 $updated++;
66 } catch (RetryableException $e) {
67 throw $e;
68 } catch (\Exception $e) {
69 $failed++;
70 $firstError = $firstError ?: $e->getMessage();
71
72 Logger::error('خطا در بروزرسانی �
73 تغیر �
74 حصول در باسلا�
75 : ' . $e->getMessage(), [
76 'operation' => 'بروزرسانی �
77 تغیر �
78 حصول',
79 'product_id' => $productId,
80 'basalam_product_id' => $basalamProductId,
81 'basalam_variation_id' => $variant['id'],
82 ]);
83 }
84 }
85
86 // Every variation failed with a permanent error: report it instead of pretending success.
87 if ($updated === 0 && $failed > 0) {
88 throw NonRetryableException::permanent(esc_html('بروزرسانی �
89 تغیرهای �
90 حصول نا�
91 وفق بود: ' . $firstError));
92 }
93
94 return ['updated' => $updated, 'skipped' => $skipped, 'failed' => $failed];
95 }
96
97 private function sendVariationUpdate(string $url, array $data): void
98 {
99 $skuRetry = false;
100
101 while (true) {
102 try {
103 $response = $this->apiservice->patch($url, $data);
104 } catch (RetryableException $e) {
105 if ($this->retryWithoutDuplicateSku($data, $e, $skuRetry)) continue;
106
107 throw $e;
108 } catch (\Exception $e) {
109 if ($this->retryWithoutDuplicateSku($data, $e, $skuRetry)) continue;
110
111 throw $e;
112 }
113
114 if ($this->retryWithoutDuplicateSku($data, $response, $skuRetry)) continue;
115
116 // API adapters normally throw client errors, but keep the fallback
117 // bounded if an adapter returns the error response directly.
118 if (ProductSkuRetry::isDuplicateSkuError($response)) {
119 throw NonRetryableException::permanent('SKU �
120 تغیر �
121 حصول در باسلا�
122 تکراری است.');
123 }
124
125 return;
126 }
127 }
128
129 private function retryWithoutDuplicateSku(array &$data, $error, bool &$retried): bool
130 {
131 if ($retried || !ProductSkuRetry::hasSku($data)) return false;
132 if (!ProductSkuRetry::isDuplicateSkuError($error)) return false;
133
134 $data = ProductSkuRetry::withoutSkus($data);
135 $retried = true;
136
137 return true;
138 }
139 }
140