PluginProbe
ووسلام – همگام سازی ووکامرس و باسلام / 1.10.6
ووسلام – همگام سازی ووکامرس و باسلام v1.10.6
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 / UpdateSingleProductService.php

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

229 lines 8.4 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\Services\ApiServiceManager;
7 use SyncBasalam\Jobs\Exceptions\RetryableException;
8 use SyncBasalam\Jobs\Exceptions\NonRetryableException;
9 use SyncBasalam\Utilities\ProductMetaKey;
10
11 defined('ABSPATH') || exit;
12
13 class UpdateSingleProductService
14 {
15 private $apiservice;
16
17 public function __construct()
18 {
19 $this->apiservice = syncBasalamContainer()->get(ApiServiceManager::class);
20 }
21
22 public function updateProductInBasalam($productData, $productId)
23 {
24 if (!get_post_type($productId) === 'product') throw NonRetryableException::invalidData('نوع post �
25 حصول نیست.');
26
27 $productData = apply_filters('sync_basalam_product_data_before_update', $productData, $productId);
28
29 do_action('sync_basalam_before_update_product_api', $productId, $productData);
30
31 $syncBasalamProductId = get_post_meta($productId, ProductMetaKey::basalamProductId(), true);
32
33 ProductConnection::assertUnique($productId, $syncBasalamProductId);
34
35 $url = sprintf(Endpoints::PRODUCT_UPDATE, $syncBasalamProductId);
36
37 $maxDescriptionRetries = 3;
38 $descriptionRetry = 0;
39
40 while (true) {
41 try {
42 $request = $this->apiservice->patch($url, $productData);
43 break;
44 } catch (RetryableException $e) {
45 throw $e;
46 } catch (NonRetryableException $e) {
47 if ($descriptionRetry < $maxDescriptionRetries && $this->stripForbiddenDescription($e, $productData, $productId, $descriptionRetry)) {
48 $descriptionRetry++;
49 continue;
50 }
51 throw $e;
52 } catch (\Exception $e) {
53 throw new \Exception(esc_html('خطا در ارتباط با API باسلا�
54 : ' . $e->getMessage()));
55 }
56 }
57
58 $body = $request['body'] ?? '';
59
60 if (is_string($body)) $body = json_decode($body, true);
61
62 if ($request['status_code'] != 200) {
63 if ($request['status_code'] == 403) throw NonRetryableException::unauthorized("این �
64 حصول �
65 تعلق به غرفه فعلی نیست.");
66
67 if (!is_array($body)) $body = [];
68
69 if (isset($body['messages'][0]['message'])) $message = $body['messages'][0]['message'];
70 elseif (isset($body[0]['message'])) $message = $body[0]['message'];
71 else $message = '';
72
73 if (isset($body['messages'][0]['fields'][0])) $field = $body['messages'][0]['fields'][0];
74 elseif (isset($body[0]['fields'][0])) $field = $body[0]['fields'][0];
75 else $field = '';
76
77 $errorMessage = $message ?: 'درخواست با خطا �
78 واجه شد.';
79 if ($field) $errorMessage .= ' (فیلد: ' . $field . ')';
80
81 throw NonRetryableException::permanent(esc_html($errorMessage));
82 }
83
84 if (is_wp_error($request)) throw NonRetryableException::permanent('خطایی در ارتباط با سرور رخ داد.');
85
86 $product = \wc_get_product($productId);
87 if ($product && $product->is_type('variable')) {
88 $variations = $product->get_children();
89 if (isset($body['variants'])) {
90 $wcVariations = [];
91 $attributes = $product->get_attributes();
92
93 foreach ($variations as $variationId) {
94 $variation = \wc_get_product($variationId);
95 $attributeValues = [];
96
97 foreach ($attributes as $attributeName => $attribute) {
98 if ($attribute->get_variation()) {
99 $cleanAttributeName = str_replace('attribute_', '', $attributeName);
100 $value = $variation->get_attribute($cleanAttributeName);
101
102 $value = urldecode($value);
103 $value = trim($value);
104 $value = mb_strtolower($value, 'UTF-8');
105 $value = str_replace(['ي', 'ك'], ['ی', 'ک'], $value);
106 $value = str_replace(['-', '_', '–', '—'], ' ', $value);
107 $value = preg_replace('/\s+/', ' ', $value);
108
109 if (!empty($value)) $attributeValues[] = $value;
110 }
111 }
112
113 if (!empty($attributeValues)) {
114 $key = implode("_", $attributeValues);
115 $wcVariations[$key] = $variationId;
116 }
117 }
118
119 $syncBasalamVariations = [];
120 foreach ($body['variants'] as $variant) {
121 $attributeValues = [];
122 if (!empty($variant['properties'])) {
123 foreach ($variant['properties'] as $property) {
124 $val = $property['value']['title'];
125
126 $val = trim($val);
127 $val = mb_strtolower($val, 'UTF-8');
128 $val = str_replace(['ي', 'ك'], ['ی', 'ک'], $val);
129 $val = str_replace(['-', '_', '–', '—'], ' ', $val);
130 $val = preg_replace('/\s+/', ' ', $val);
131
132 if (!empty($val)) $attributeValues[] = $val;
133 }
134 }
135
136 if (!empty($attributeValues)) {
137 $key = implode("_", $attributeValues);
138 $syncBasalamVariations[$key] = $variant['id'];
139 }
140 }
141
142 foreach ($wcVariations as $key => $wcVarId) {
143 if (isset($syncBasalamVariations[$key])) {
144 update_post_meta($wcVarId, 'sync_basalam_variation_id', $syncBasalamVariations[$key]);
145 }
146 }
147 }
148 }
149
150 update_post_meta($productId, ProductMetaKey::basalamProductSyncStatus(), 'synced');
151
152 $result = [
153 'success' => true,
154 'message' => 'فرایند بروزرسانی �
155 حصول با �
156 وفقیت انجا�
157 شد.',
158 'status_code' => 200,
159 ];
160
161 do_action('sync_basalam_after_update_product_api', $productId, $body, $result);
162
163 return $result;
164 }
165
166 private function stripForbiddenDescription(NonRetryableException $e, array &$productData, int $productId, int $attempt): bool
167 {
168 if (!isset($productData['description']) || !is_string($productData['description'])) return false;
169
170 $values = DescriptionErrorSanitizer::extractDescriptionValues($e->getResponseData());
171 if (empty($values)) return false;
172
173 $cleaned = DescriptionErrorSanitizer::sanitize($productData['description'], $values);
174 if ($cleaned === $productData['description']) return false;
175
176 $productData['description'] = $cleaned;
177
178 return true;
179 }
180
181 public function updateProductStatus($productId, $status)
182 {
183 $syncBasalamProductId = get_post_meta($productId, ProductMetaKey::basalamProductId(), true);
184
185 ProductConnection::assertUnique($productId, $syncBasalamProductId);
186
187 $url = sprintf(Endpoints::PRODUCT_UPDATE, $syncBasalamProductId);
188
189 $data = ["status" => $status];
190
191 $data = apply_filters('sync_basalam_product_status_data_before_update', $data, $productId, $status);
192
193 do_action('sync_basalam_before_update_product_status', $productId, $status, $data);
194
195 try {
196 $request = $this->apiservice->patch($url, $data);
197 } catch (RetryableException $e) {
198 throw $e;
199 } catch (NonRetryableException $e) {
200 throw $e;
201 } catch (\Exception $e) {
202 throw NonRetryableException::permanent(esc_html($e->getMessage()));
203 }
204
205 if (!is_wp_error($request)) {
206 update_post_meta($productId, ProductMetaKey::basalamProductSyncStatus(), 'synced');
207 update_post_meta($productId, ProductMetaKey::basalamProductStatus(), $status);
208
209 $result = [
210 'success' => true,
211 'message' => 'وضعیت �
212 حصول با �
213 وفقیت در باسلا�
214 تغییر کرد.',
215 'status_code' => 200,
216 ];
217
218 do_action('sync_basalam_after_update_product_status', $productId, $status, $result);
219
220 return $result;
221 }
222
223 throw NonRetryableException::permanent("تغییر وضعیت �
224 حصول در باسلا�
225 نا�
226 وفق بود.");
227 }
228 }
229