PluginProbe
ووسلام – همگام سازی ووکامرس و باسلام / 1.10.14
ووسلام – همگام سازی ووکامرس و باسلام v1.10.14
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.14, at includes/Services/Products/CreateSingleProductService.php

223 lines 8.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
46 while (true) {
47 try {
48 $request = $this->apiservice->post($url, $productData);
49 break;
50 } catch (RetryableException $e) {
51 throw $e;
52 } catch (NonRetryableException $e) {
53 if ($descriptionRetry < $maxDescriptionRetries && $this->stripForbiddenDescription($e, $productData, $productId, $descriptionRetry)) {
54 $descriptionRetry++;
55 continue;
56 }
57 throw $e;
58 } catch (\Exception $e) {
59 throw new \Exception(esc_html($e->getMessage()));
60 }
61 }
62
63 if ($request['status_code'] != 201 && isset($request['status_code'])) {
64
65 $body = $request['body'] ?? '';
66
67 if (is_string($body))
68 $responseData = json_decode($body, true);
69 else $responseData = $body;
70
71 if (!is_array($responseData)) $responseData = [];
72
73 if ($responseData && isset($responseData['messages'][0])) {
74 $message = $responseData['messages'][0]['message'] ?? 'خطای نا�
75 شخص';
76 $field = $responseData['messages'][0]['fields'][0] ?? '';
77 } else {
78 $message = 'درخواست با تای�
79 اوت �
80 واجه شد.';
81 $field = '';
82 }
83
84 $errorMessage = 'فرایند اضافه کردن �
85 حصول نا�
86 وفق بود: ' . esc_html($message);
87 if ($field) $errorMessage .= ' (فیلد: ' . esc_html($field) . ')';
88
89 throw new \Exception(esc_html($errorMessage));
90 }
91
92 if (is_wp_error($request)) {
93 $body = $request['body'] ?? '';
94
95 if (is_string($body))
96 $responseData = json_decode($body, true);
97 else $responseData = $body;
98
99 $message = $responseData[0]['message'] ?? 'خطای نا�
100 شخص';
101 throw new \Exception('درخواست �
102 وفقیت آ�
103 یز نبود: ' . esc_html($message));
104 }
105
106 $responseData = json_decode($request['body'], true);
107 if (isset($responseData['id'])) {
108 if (isset($responseData['variants'])) {
109 $product = wc_get_product($productId);
110
111 if ($product && $product->is_type('variable')) {
112 $wcVariations = [];
113 $attributes = $product->get_attributes();
114
115 foreach ($product->get_children() as $variationId) {
116 $variation = wc_get_product($variationId);
117 $attributeValues = [];
118
119 foreach ($attributes as $attributeName => $attribute) {
120 if ($attribute->get_variation()) {
121 $cleanAttributeName = str_replace('attribute_', '', $attributeName);
122 $value = $variation->get_attribute($cleanAttributeName);
123
124 $value = urldecode($value);
125 $value = trim($value);
126 $value = mb_strtolower($value, 'UTF-8');
127 $value = str_replace(['ي', 'ك'], ['ی', 'ک'], $value);
128 $value = str_replace(['-', '_', '', ''], ' ', $value);
129 $value = preg_replace('/\s+/', ' ', $value);
130
131 if (!empty($value)) {
132 $attributeValues[] = $value;
133 }
134 }
135 }
136
137 if (!empty($attributeValues)) {
138 $key = implode("_", $attributeValues);
139 $wcVariations[$key] = $variationId;
140 }
141 }
142
143 $syncBasalamVariations = [];
144 foreach ($responseData['variants'] as $variant) {
145 $attributeValues = [];
146 if (!empty($variant['properties'])) {
147 foreach ($variant['properties'] as $property) {
148 $val = trim($property['value']['title']);
149 $val = mb_strtolower($val, 'UTF-8');
150 $val = str_replace(['ي', 'ك'], ['ی', 'ک'], $val);
151 $val = str_replace(['-', '_', '', ''], ' ', $val);
152 $val = preg_replace('/\s+/', ' ', $val);
153 if (!empty($val)) {
154 $attributeValues[] = $val;
155 }
156 }
157 }
158
159 if (!empty($attributeValues)) {
160 $key = implode("_", $attributeValues);
161 $syncBasalamVariations[$key] = $variant['id'];
162 }
163 }
164
165 $variationMapping = [];
166 foreach ($wcVariations as $key => $wcVarId) {
167 if (isset($syncBasalamVariations[$key])) {
168 $variationMapping[$wcVarId] = $syncBasalamVariations[$key];
169 update_post_meta($wcVarId, 'sync_basalam_variation_id', $syncBasalamVariations[$key]);
170 }
171 }
172 }
173 }
174
175 update_post_meta($productId, ProductMetaKey::basalamProductId(), $responseData['id']);
176 update_post_meta($productId, ProductMetaKey::basalamProductStatus(), 2976);
177 update_post_meta($productId, ProductMetaKey::basalamProductSyncStatus(), 'synced');
178
179 $result = [
180 'success' => true,
181 'message' => '�
182 حصول با �
183 وفقیت به باسلا�
184 اضافه شد.',
185 'status_code' => 200,
186 'basalam_id' => $responseData['id'],
187 ];
188
189 do_action('sync_basalam_after_create_product_api', $productId, $responseData, $result);
190
191 return $result;
192 }
193
194 throw new \Exception("فرایند اضافه کردن �
195 حصول نا�
196 وفق بود");
197 }
198
199 private function stripForbiddenDescription(NonRetryableException $e, array &$productData, int $productId, int $attempt): bool
200 {
201 if (!isset($productData['description']) || !is_string($productData['description'])) return false;
202
203 $values = DescriptionErrorSanitizer::extractDescriptionValues($e->getResponseData());
204 if (empty($values)) return false;
205
206 $cleaned = DescriptionErrorSanitizer::sanitize($productData['description'], $values);
207 if ($cleaned === $productData['description']) return false;
208
209 $productData['description'] = $cleaned;
210
211 return true;
212 }
213
214 private function ValidCreateProductData(array $productData, int $productId): void
215 {
216 $validation = $this->validator->validate($productData, $productId);
217
218 if (!$validation['valid']) {
219 throw NonRetryableException::invalidData(esc_html($validation['message']));
220 }
221 }
222 }
223