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 / CreateSingleProductService.php

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

253 lines 9.7 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\Admin\Product\Data\Validators\CreateProductDataValidator;
6 use SyncBasalam\Admin\Settings\SettingsConfig;
7 use SyncBasalam\Config\Endpoints;
8 use SyncBasalam\Services\ApiServiceManager;
9 use SyncBasalam\Jobs\Exceptions\RetryableException;
10 use SyncBasalam\Jobs\Exceptions\NonRetryableException;
11 use SyncBasalam\Utilities\ProductMetaKey;
12 use SyncBasalam\Services\VendorSyncPolicy;
13
14 defined('ABSPATH') || exit;
15
16 class CreateSingleProductService
17 {
18 private $apiservice;
19 private $validator;
20
21 public function __construct($validator = null)
22 {
23 $this->apiservice = syncBasalamContainer()->get(ApiServiceManager::class);
24 $this->validator = $validator ?: new CreateProductDataValidator();
25 }
26
27 public function createProductInBasalam($productData, $productId)
28 {
29 $vendorSyncPolicy = syncBasalamContainer()->get(VendorSyncPolicy::class);
30 if (!$vendorSyncPolicy->canCreate()) {
31 throw NonRetryableException::invalidData($vendorSyncPolicy->getRestrictionMessage(false));
32 }
33
34 $productData = apply_filters('sync_basalam_product_data_before_create', $productData, $productId);
35 $this->ValidCreateProductData($productData, $productId);
36
37 do_action('sync_basalam_before_create_product_api', $productId, $productData);
38
39 $vendorId = syncBasalamSettings()->getSettings(SettingsConfig::VENDOR_ID);
40
41 $url = sprintf(Endpoints::PRODUCT_CREATE, $vendorId);
42
43 $maxDescriptionRetries = 3;
44 $descriptionRetry = 0;
45 $skuRetry = false;
46
47 while (true) {
48 try {
49 $request = $this->apiservice->post($url, $productData);
50 } catch (RetryableException $e) {
51 if ($this->retryWithoutDuplicateSku($productData, $e, $skuRetry)) {
52 continue;
53 }
54
55 throw $e;
56 } catch (NonRetryableException $e) {
57 if ($this->retryWithoutDuplicateSku($productData, $e, $skuRetry)) {
58 continue;
59 }
60
61 if ($descriptionRetry < $maxDescriptionRetries && $this->stripForbiddenDescription($e, $productData, $productId, $descriptionRetry)) {
62 $descriptionRetry++;
63 continue;
64 }
65 throw $e;
66 } catch (\Exception $e) {
67 if ($this->retryWithoutDuplicateSku($productData, $e, $skuRetry)) {
68 continue;
69 }
70
71 throw new \Exception(esc_html($e->getMessage()));
72 }
73
74 // Some API adapters return a non-2xx response instead of throwing it.
75 if ($this->retryWithoutDuplicateSku($productData, $request, $skuRetry)) {
76 continue;
77 }
78
79 break;
80 }
81
82 if ($request['status_code'] != 201 && isset($request['status_code'])) {
83
84 $body = $request['body'] ?? '';
85
86 if (is_string($body))
87 $responseData = json_decode($body, true);
88 else $responseData = $body;
89
90 if (!is_array($responseData)) $responseData = [];
91
92 if ($responseData && isset($responseData['messages'][0])) {
93 $message = $responseData['messages'][0]['message'] ?? 'خطای نا�
94 شخص';
95 $field = $responseData['messages'][0]['fields'][0] ?? '';
96 } else {
97 $message = 'درخواست با تای�
98 اوت �
99 واجه شد.';
100 $field = '';
101 }
102
103 $errorMessage = 'فرایند اضافه کردن �
104 حصول نا�
105 وفق بود: ' . esc_html($message);
106 if ($field) $errorMessage .= ' (فیلد: ' . esc_html($field) . ')';
107
108 throw new \Exception(esc_html($errorMessage));
109 }
110
111 if (is_wp_error($request)) {
112 $body = $request['body'] ?? '';
113
114 if (is_string($body))
115 $responseData = json_decode($body, true);
116 else $responseData = $body;
117
118 $message = $responseData[0]['message'] ?? 'خطای نا�
119 شخص';
120 throw new \Exception('درخواست �
121 وفقیت آ�
122 یز نبود: ' . esc_html($message));
123 }
124
125 $responseData = json_decode($request['body'], true);
126 if (isset($responseData['id'])) {
127 if (isset($responseData['variants'])) {
128 $product = wc_get_product($productId);
129
130 if ($product && $product->is_type('variable')) {
131 $wcVariations = [];
132 $attributes = $product->get_attributes();
133
134 foreach ($product->get_children() as $variationId) {
135 $variation = wc_get_product($variationId);
136 $attributeValues = [];
137
138 foreach ($attributes as $attributeName => $attribute) {
139 if ($attribute->get_variation()) {
140 $cleanAttributeName = str_replace('attribute_', '', $attributeName);
141 $value = $variation->get_attribute($cleanAttributeName);
142
143 $value = urldecode($value);
144 $value = trim($value);
145 $value = mb_strtolower($value, 'UTF-8');
146 $value = str_replace(['ي', 'ك'], ['ی', 'ک'], $value);
147 $value = str_replace(['-', '_', '', ''], ' ', $value);
148 $value = preg_replace('/\s+/', ' ', $value);
149
150 if (!empty($value)) {
151 $attributeValues[] = $value;
152 }
153 }
154 }
155
156 if (!empty($attributeValues)) {
157 $key = implode("_", $attributeValues);
158 $wcVariations[$key] = $variationId;
159 }
160 }
161
162 $syncBasalamVariations = [];
163 foreach ($responseData['variants'] as $variant) {
164 $attributeValues = [];
165 if (!empty($variant['properties'])) {
166 foreach ($variant['properties'] as $property) {
167 $val = trim($property['value']['title']);
168 $val = mb_strtolower($val, 'UTF-8');
169 $val = str_replace(['ي', 'ك'], ['ی', 'ک'], $val);
170 $val = str_replace(['-', '_', '', ''], ' ', $val);
171 $val = preg_replace('/\s+/', ' ', $val);
172 if (!empty($val)) {
173 $attributeValues[] = $val;
174 }
175 }
176 }
177
178 if (!empty($attributeValues)) {
179 $key = implode("_", $attributeValues);
180 $syncBasalamVariations[$key] = $variant['id'];
181 }
182 }
183
184 $variationMapping = [];
185 foreach ($wcVariations as $key => $wcVarId) {
186 if (isset($syncBasalamVariations[$key])) {
187 $variationMapping[$wcVarId] = $syncBasalamVariations[$key];
188 update_post_meta($wcVarId, 'sync_basalam_variation_id', $syncBasalamVariations[$key]);
189 }
190 }
191 }
192 }
193
194 update_post_meta($productId, ProductMetaKey::basalamProductId(), $responseData['id']);
195 update_post_meta($productId, ProductMetaKey::basalamProductStatus(), 2976);
196 update_post_meta($productId, ProductMetaKey::basalamProductSyncStatus(), 'synced');
197
198 $result = [
199 'success' => true,
200 'message' => '�
201 حصول با �
202 وفقیت به باسلا�
203 اضافه شد.',
204 'status_code' => 200,
205 'basalam_id' => $responseData['id'],
206 ];
207
208 do_action('sync_basalam_after_create_product_api', $productId, $responseData, $result);
209
210 return $result;
211 }
212
213 throw new \Exception("فرایند اضافه کردن �
214 حصول نا�
215 وفق بود");
216 }
217
218 private function stripForbiddenDescription(NonRetryableException $e, array &$productData, int $productId, int $attempt): bool
219 {
220 if (!isset($productData['description']) || !is_string($productData['description'])) return false;
221
222 $values = DescriptionErrorSanitizer::extractDescriptionValues($e->getResponseData());
223 if (empty($values)) return false;
224
225 $cleaned = DescriptionErrorSanitizer::sanitize($productData['description'], $values);
226 if ($cleaned === $productData['description']) return false;
227
228 $productData['description'] = $cleaned;
229
230 return true;
231 }
232
233 private function retryWithoutDuplicateSku(array &$productData, $error, bool &$retried): bool
234 {
235 if ($retried || !ProductSkuRetry::hasSku($productData)) return false;
236 if (!ProductSkuRetry::isDuplicateSkuError($error)) return false;
237
238 $productData = ProductSkuRetry::withoutSkus($productData);
239 $retried = true;
240
241 return true;
242 }
243
244 private function ValidCreateProductData(array $productData, int $productId): void
245 {
246 $validation = $this->validator->validate($productData, $productId);
247
248 if (!$validation['valid']) {
249 throw NonRetryableException::invalidData(esc_html($validation['message']));
250 }
251 }
252 }
253