Changeset 2826597
- Timestamp:
- 11/30/2022 03:52:25 PM (3 years ago)
- Location:
- wooms
- Files:
-
- 2 deleted
- 16 edited
- 1 copied
-
tags/9.0.1 (copied) (copied from wooms/trunk)
-
tags/9.0.1/.editorconfig (deleted)
-
tags/9.0.1/includes/OrderNumber.php (modified) (6 diffs)
-
tags/9.0.1/includes/Orders.php (modified) (2 diffs)
-
tags/9.0.1/includes/ProductVariable.php (modified) (1 diff)
-
tags/9.0.1/includes/Products.php (modified) (5 diffs)
-
tags/9.0.1/includes/ProductsHiding.php (modified) (2 diffs)
-
tags/9.0.1/includes/ProductsServices.php (modified) (3 diffs)
-
tags/9.0.1/readme.txt (modified) (1 diff)
-
tags/9.0.1/wooms.php (modified) (1 diff)
-
trunk/.editorconfig (deleted)
-
trunk/includes/OrderNumber.php (modified) (6 diffs)
-
trunk/includes/Orders.php (modified) (2 diffs)
-
trunk/includes/ProductVariable.php (modified) (1 diff)
-
trunk/includes/Products.php (modified) (5 diffs)
-
trunk/includes/ProductsHiding.php (modified) (2 diffs)
-
trunk/includes/ProductsServices.php (modified) (3 diffs)
-
trunk/readme.txt (modified) (1 diff)
-
trunk/wooms.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
wooms/tags/9.0.1/includes/OrderNumber.php
r2826440 r2826597 7 7 /** 8 8 * Get and save order number from MoySklad 9 * 9 * 10 10 * issue https://github.com/wpcraft-ru/wooms/issues/319 11 11 */ … … 19 19 add_filter('wooms_update_order_from_moysklad', array(__CLASS__, 'set_order_number'), 10, 2); 20 20 21 add_action('admin_init', array(__CLASS__, 'add_settings'), 50);21 add_action('admin_init', array(__CLASS__, 'add_settings'), 30); 22 22 add_action('pre_get_posts', array(__CLASS__, 'search_by_number_from_moysklad')); 23 23 } … … 25 25 /** 26 26 * set_order_number 27 * 27 * 28 28 * use hook $order = apply_filters('wooms_order_update', $order, $result); 29 29 */ … … 56 56 57 57 /** 58 * 58 * 59 59 * use hook $data = apply_filters('wooms_order_data', $data, $order_id); 60 60 */ … … 147 147 /** 148 148 * Если используются номера заказов из Мой Склад, чиним поиску по номеру заказа 149 * 149 * 150 150 * issue https://github.com/wpcraft-ru/wooms/issues/331 151 151 */ … … 167 167 return; 168 168 } 169 169 170 170 $custom_order_id = $query->query['s']; 171 171 $query->query_vars['post__in']=array(); -
wooms/tags/9.0.1/includes/Orders.php
r2826440 r2826597 60 60 add_action('wooms_order_metabox_controls', array(__CLASS__, 'add_controle_for_sync')); 61 61 62 add_action('admin_init', array(__CLASS__, 'add_settings'), 40);62 add_action('admin_init', array(__CLASS__, 'add_settings'), 10); 63 63 64 64 add_action( 'woocommerce_order_item_meta_start', function () { … … 449 449 if (empty($result['id']) || !isset($result['id']) || isset($result['errors'])) { 450 450 update_post_meta($order_id, 'wooms_send_timestamp', date("Y-m-d H:i:s")); 451 // $errors = "\n\r" . 'Код ошибки:' . $result['errors'][0]['code'] . "\n\r"; 452 // $errors .= 'Параметр:' . $result['errors'][0]['parameter'] . "\n\r"; 453 // $errors .= $result['errors'][0]['error']; 451 delete_post_meta( $order_id, 'wooms_order_sync' ); 454 452 455 453 do_action( -
wooms/tags/9.0.1/includes/ProductVariable.php
r2826440 r2826597 11 11 class ProductVariable 12 12 { 13 /** 14 * Save state in DB 15 * 16 * @var string 17 */ 18 public static $state_transient_key = 'wooms_variables_walker_state'; 19 20 /** 21 * Hookd and key for ActionSheduler 22 * 23 * @var string 24 */ 25 public static $walker_hook_name = 'wooms_variables_walker_batch'; 26 27 28 /** 29 * The init 30 */ 31 public static function init() 32 { 33 34 //walker 35 add_action('wooms_variables_walker_batch', array(__CLASS__, 'walker')); 36 37 add_filter('wooms_product_save', array(__CLASS__, 'update_product'), 20, 3); 38 39 add_filter('wooms_save_variation', array(__CLASS__, 'save_attributes_for_variation'), 10, 3); 40 41 //Other 42 add_action('admin_init', array(__CLASS__, 'add_settings'), 150); 43 add_action('woomss_tool_actions_wooms_import_variations_manual_start', array(__CLASS__, 'start_manually')); 44 add_action('woomss_tool_actions_wooms_import_variations_manual_stop', array(__CLASS__, 'stop_manually')); 45 add_action('wooms_main_walker_finish', array(__CLASS__, 'reset_after_main_walker_finish')); 46 add_action('wooms_main_walker_started', array(__CLASS__, 'set_wait')); 47 48 add_action('woomss_tool_actions_btns', array(__CLASS__, 'display_state'), 15); 49 50 add_action('woocommerce_variation_header', array(__CLASS__, 'variation_sync_id'), 10); 51 } 52 53 54 /** 55 * Walker for data variant product from MoySklad 56 */ 57 public static function walker($state = []) 58 { 59 //reset state if new session 60 if (empty($state)) { 61 62 $state = [ 63 'timestamp' => date("YmdHis"), 64 'end_timestamp' => 0, 65 'count' => 0, 66 'query_arg' => [ 67 'offset' => 0, 68 'limit' => apply_filters('wooms_variant_iteration_size', 30), 69 ] 70 ]; 71 72 self::set_state($state); 73 } 74 13 75 /** 14 * Save state in DB 15 * 16 * @var string 76 * issue https://github.com/wpcraft-ru/wooms/issues/296 17 77 */ 18 public static $state_transient_key = 'wooms_variables_walker_state'; 78 $url = 'https://online.moysklad.ru/api/remap/1.2/entity/variant'; 79 80 $url = add_query_arg($state['query_arg'], $url); 81 82 $filters = []; 83 84 $filters = apply_filters('wooms_url_get_variants_filter', $filters); 85 86 $url = add_query_arg('filter', implode(';', $filters), $url); 87 88 $url = apply_filters('wooms_url_get_variants', $url); 89 90 try { 91 92 do_action( 93 'wooms_logger', 94 __CLASS__, 95 sprintf('Вариации. Отправлен запрос: %s', $url), 96 $state 97 ); 98 99 $data = wooms_request($url); 100 101 //Check for errors and send message to UI 102 if (isset($data['errors'][0]["error"])) { 103 throw new \Exception($data['errors'][0]["error"]); 104 } 105 106 //If no rows, that send 'end' and stop walker 107 if (isset($data['rows']) && empty($data['rows'])) { 108 109 self::walker_finish(); 110 return true; 111 } 112 113 $i = self::process_rows($data['rows']); 114 115 $state['count'] += $i; 116 $state['query_arg']['offset'] += count($data['rows']); 117 self::set_state($state); 118 119 do_action('wooms_variations_batch_end'); 120 121 as_schedule_single_action(time() + 1, self::$walker_hook_name, [$state], 'WooMS'); 122 123 return true; 124 } catch (\Exception $e) { 125 self::set_state('lock', 0); 126 do_action( 127 'wooms_logger_error', 128 __CLASS__, 129 $e->getMessage() 130 ); 131 return false; 132 } 133 } 134 135 /** 136 * process rows from api 137 */ 138 public static function process_rows($rows) 139 { 140 141 $i = 0; 142 foreach ($rows as $key => $item) { 143 144 if ($item["meta"]["type"] != 'variant') { 145 continue; 146 } 147 148 $i++; 149 150 self::load_data_variant($item); 151 do_action('wooms_products_variations_item', $item); 152 153 } 154 155 return $i; 156 } 157 158 /** 159 * If started main walker - set wait 160 */ 161 public static function set_wait() 162 { 163 as_unschedule_all_actions(self::$walker_hook_name); 164 self::set_state('end_timestamp', time()); 165 } 166 167 168 /** 169 * Resetting state after completing the main walker 170 * And restart schedules for sync variations 171 */ 172 public static function reset_after_main_walker_finish() 173 { 174 as_schedule_single_action(time() + 5, self::$walker_hook_name, [], 'WooMS'); 175 } 176 177 178 /** 179 * Set attributes for variables 180 */ 181 public static function set_product_attributes_for_variation($product_id, $data_api) 182 { 183 $product = wc_get_product($product_id); 184 185 $ms_attributes = []; 186 foreach ($data_api['characteristics'] as $key => $characteristic) { 187 188 $attribute_label = $characteristic["name"]; 189 190 $ms_attributes[$attribute_label] = [ 191 'name' => $characteristic["name"], 192 'values' => [], 193 ]; 194 } 195 196 $values = array(); 197 foreach ($data_api['characteristics'] as $key => $characteristic) { 198 $attribute_label = $characteristic["name"]; 199 200 if ($attribute_taxonomy_id = self::get_attribute_id_by_label($characteristic['name'])) { 201 $taxonomy_name = wc_attribute_taxonomy_name_by_id((int) $attribute_taxonomy_id); 202 $current_values = $product->get_attribute($taxonomy_name); 203 204 if ($current_values) { 205 $current_values = explode(', ', $current_values); 206 $current_values = array_map('trim', $current_values); 207 } 208 } else { 209 $current_values = $product->get_attribute($characteristic['name']); 210 $current_values = explode(' | ', $current_values); 211 } 212 213 if (empty($current_values)) { 214 $values[] = $characteristic['value']; 215 } else { 216 $values = $current_values; 217 $values[] = $characteristic['value']; 218 } 219 220 $values = apply_filters( 221 'wooms_product_attribute_save_values', 222 $values, 223 $product, 224 $characteristic 225 ); 226 $ms_attributes[$attribute_label]['values'] = $values; 227 } 19 228 20 229 /** 21 * Hookd and key for ActionSheduler 22 * 23 * @var string 230 * check unique for values 24 231 */ 25 public static $walker_hook_name = 'wooms_variables_walker_batch'; 26 232 foreach ($ms_attributes as $key => $value) { 233 $ms_attributes[$key]['values'] = array_unique($value['values']); 234 } 235 236 $attributes = $product->get_attributes('edit'); 237 238 if (empty($attributes)) { 239 $attributes = array(); 240 } 241 242 foreach ($ms_attributes as $key => $value) { 243 $attribute_taxonomy_id = self::get_attribute_id_by_label($value['name']); 244 $attribute_slug = sanitize_title($value['name']); 245 246 if (empty($attribute_taxonomy_id)) { 247 $attribute_object = new \WC_Product_Attribute(); 248 $attribute_object->set_name($value['name']); 249 $attribute_object->set_options($value['values']); 250 $attribute_object->set_position(0); 251 $attribute_object->set_visible(0); 252 $attribute_object->set_variation(1); 253 $attributes[$attribute_slug] = $attribute_object; 254 } else { 255 //Очищаем индивидуальный атрибут с таким именем если есть 256 if (isset($attributes[$attribute_slug])) { 257 unset($attributes[$attribute_slug]); 258 } 259 $taxonomy_name = wc_attribute_taxonomy_name_by_id((int) $attribute_taxonomy_id); 260 $attribute_object = new \WC_Product_Attribute(); 261 $attribute_object->set_id($attribute_taxonomy_id); 262 $attribute_object->set_name($taxonomy_name); 263 $attribute_object->set_options($value['values']); 264 $attribute_object->set_position(0); 265 $attribute_object->set_visible(0); 266 $attribute_object->set_variation(1); 267 $attributes[$taxonomy_name] = $attribute_object; 268 } 269 } 270 271 $attributes = apply_filters('wooms_product_attributes', $attributes, $data_api, $product); 272 273 $product->set_attributes($attributes); 274 275 $product->save(); 276 277 do_action( 278 'wooms_logger', 279 __CLASS__, 280 sprintf( 281 'Сохранены атрибуты для продукта: %s (%s)', 282 $product->get_name(), 283 $product_id 284 ), 285 $attributes 286 ); 287 } 288 289 290 /** 291 * Set attributes and value for variation 292 * 293 * @param $variation_id 294 * @param $characteristics 295 */ 296 public static function save_attributes_for_variation(\WC_Product_Variation $variation, $data_api, $product_id) 297 { 298 $variant_data = $data_api; 299 300 $variation_id = $variation->get_id(); 301 $parent_id = $variation->get_parent_id(); 302 303 $characteristics = $variant_data['characteristics']; 304 305 $attributes = array(); 306 307 foreach ($characteristics as $key => $characteristic) { 308 $attribute_label = $characteristic["name"]; 309 $attribute_slug = sanitize_title($attribute_label); 310 311 if ($attribute_taxonomy_id = self::get_attribute_id_by_label($attribute_label)) { 312 $taxonomy_name = wc_attribute_taxonomy_name_by_id($attribute_taxonomy_id); 313 if (isset($attributes[$attribute_slug])) { 314 unset($attributes[$attribute_slug]); 315 } 316 317 $attribute_value = $characteristic['value']; 318 319 $term = get_term_by('name', $attribute_value, $taxonomy_name); 320 321 if ($term && !is_wp_error($term)) { 322 $attribute_value = $term->slug; 323 } else { 324 $attribute_value = sanitize_title($attribute_value); 325 } 326 327 $attributes[$taxonomy_name] = $attribute_value; 328 } else { 329 $attributes[$attribute_slug] = $characteristic['value']; 330 } 331 } 332 333 $attributes = apply_filters('wooms_variation_attributes', $attributes, $data_api, $variation); 334 335 $variation->set_attributes($attributes); 336 337 do_action( 338 'wooms_logger', 339 __CLASS__, 340 sprintf('Сохранены атрибуты для вариации %s (продукт: %s)', $variation_id, $product_id), 341 wc_print_r($attributes, true) 342 ); 343 344 return $variation; 345 } 346 347 348 /** 349 * Installation of variations for variable product 350 */ 351 public static function load_data_variant($variant) 352 { 353 if (!empty($variant['archived'])) { 354 return; 355 } 356 357 $product_href = $variant['product']['meta']['href']; 358 $product_id = self::get_product_id_by_uuid($product_href); 359 360 if (empty($product_id)) { 361 362 /** 363 * придумать подход при котором вариации будут фильтроваться с учетом уже доступных продуктов на сайте 364 * до этого момента, эта ошибка будет возникать постоянно 365 */ 366 do_action( 367 'wooms_logger_error', 368 __CLASS__, 369 sprintf('Ошибка получения product_id для url %s', $product_href), 370 $variant 371 ); 372 373 return; 374 } 375 376 377 self::update_variant_for_product($product_id, $variant); 27 378 28 379 /** 29 * The init380 * deprecated 30 381 */ 31 public static function init() 32 { 33 34 //walker 35 add_action('wooms_variables_walker_batch', array(__CLASS__, 'batch_handler')); 36 37 add_filter('wooms_product_save', array(__CLASS__, 'update_product'), 20, 3); 38 39 add_filter('wooms_save_variation', array(__CLASS__, 'save_attributes_for_variation'), 10, 3); 40 add_action('wooms_products_variations_item', array(__CLASS__, 'load_data_variant'), 15); 41 42 //Other 43 add_action('admin_init', array(__CLASS__, 'add_settings'), 150); 44 add_action('woomss_tool_actions_wooms_import_variations_manual_start', array(__CLASS__, 'start_manually')); 45 add_action('woomss_tool_actions_wooms_import_variations_manual_stop', array(__CLASS__, 'stop_manually')); 46 add_action('wooms_main_walker_finish', array(__CLASS__, 'reset_after_main_walker_finish')); 47 add_action('wooms_main_walker_started', array(__CLASS__, 'set_wait')); 48 49 add_action('init', array(__CLASS__, 'add_schedule_hook')); 50 51 add_action('woomss_tool_actions_btns', array(__CLASS__, 'display_state'), 15); 52 53 add_action('woocommerce_variation_header', array(__CLASS__, 'variation_sync_id'), 10); 54 } 55 382 do_action('wooms_product_variant', $product_id, $variant); 383 } 384 385 386 /** 387 * Get product variant ID 388 * 389 * @param $uuid 390 */ 391 public static function get_product_id_by_uuid($uuid) 392 { 393 if (strpos($uuid, 'http') !== false) { 394 $uuid = str_replace('https://online.moysklad.ru/api/remap/1.1/entity/product/', '', $uuid); 395 $uuid = str_replace('https://online.moysklad.ru/api/remap/1.2/entity/product/', '', $uuid); 396 } 397 398 $posts = get_posts('post_type=product&meta_key=wooms_id&meta_value=' . $uuid); 399 if (empty($posts[0]->ID)) { 400 return false; 401 } 402 403 return $posts[0]->ID; 404 } 405 406 407 /** 408 * Update and add variables from product 409 * 410 * @param $product_id 411 * @param $value 412 */ 413 public static function update_variant_for_product($product_id, $variant_data) 414 { 415 if (empty($variant_data)) { 416 return; 417 } 418 419 if (!empty($variant_data['archived'])) { 420 return; 421 } 422 423 //добавление атрибутов к основному продукту с пометкой для вариаций 424 self::set_product_attributes_for_variation($product_id, $variant_data); 425 426 if (!$variation_id = self::get_variation_by_wooms_id($product_id, $variant_data['id'])) { 427 $variation_id = self::add_variation($product_id, $variant_data); 428 } 429 430 $variation = wc_get_product($variation_id); 431 $variation->set_name($variant_data['name']); 432 433 $variation->set_stock_status('instock'); 434 435 if (!empty($variant_data["salePrices"][0]['value'])) { 436 $price = $variant_data["salePrices"][0]['value']; 437 } else { 438 $price = 0; 439 } 440 441 $price = floatval($price) / 100; 442 $variation->set_price($price); 443 $variation->set_regular_price($price); 444 445 do_action( 446 'wooms_logger', 447 __CLASS__, 448 sprintf('Цена %s сохранена (для вариации %s продукта %s)', $price, $variation_id, $product_id) 449 ); 450 451 $product_parent = wc_get_product($product_id); 452 if (!$product_parent->is_type('variable')) { 453 $product_parent = new \WC_Product_Variable($product_parent); 454 $product_parent->save(); 455 456 do_action( 457 'wooms_logger_error', 458 __CLASS__, 459 sprintf('Снова сохранили продукт как вариативный %s', $product_id) 460 ); 461 } 462 463 if ($session_id = self::get_session_id()) { 464 $variation->update_meta_data('wooms_session_id', $session_id); 465 } 56 466 57 467 /** 58 * Walker for data variant product from MoySklad468 * deprecated 59 469 */ 60 public static function batch_handler($args = []) 61 { 62 63 $state = self::get_state(); 64 65 if (!empty($state['lock'])) { 66 // return; // блокировка состояни гонки 67 } 68 69 // dd($state); 70 71 self::set_state('lock', 1); 72 73 //reset state if new session 74 if (empty($state['timestamp'])) { 75 76 self::set_state('timestamp', date("YmdHis")); 77 self::set_state('end_timestamp', 0); 78 self::set_state('count', 0); 79 80 $query_arg_default = [ 81 'offset' => 0, 82 'limit' => apply_filters('wooms_variant_iteration_size', 30), 83 ]; 84 85 self::set_state('query_arg', $query_arg_default); 86 } 87 88 89 $query_arg = self::get_state('query_arg'); 90 91 /** 92 * issue https://github.com/wpcraft-ru/wooms/issues/296 93 */ 94 $url = 'https://online.moysklad.ru/api/remap/1.2/entity/variant'; 95 96 $url = add_query_arg($query_arg, $url); 97 98 $filters = [ 99 // 'productid=4dc138a7-d532-11e7-7a69-8f55000890d1', 100 // 'productid=2d0310cd-9194-11e7-7a6c-d2a9002dc49e', 101 ]; 102 103 $filters = apply_filters('wooms_url_get_variants_filter', $filters); 104 105 $url = add_query_arg('filter', implode(';', $filters), $url); 106 107 $url = apply_filters('wooms_url_get_variants', $url); 108 109 try { 110 111 do_action( 112 'wooms_logger', 113 __CLASS__, 114 sprintf('Вариации. Отправлен запрос: %s', $url), 115 $state 116 ); 117 118 $data = wooms_request($url); 119 120 //Check for errors and send message to UI 121 if (isset($data['errors'][0]["error"])) { 122 throw new \Exception($data['errors'][0]["error"]); 123 } 124 125 //If no rows, that send 'end' and stop walker 126 if (isset($data['rows']) && empty($data['rows'])) { 127 128 self::set_state('lock', 0); 129 self::walker_finish(); 130 return true; 131 } 132 133 $i = 0; 134 foreach ($data['rows'] as $key => $item) { 135 136 if ($item["meta"]["type"] != 'variant') { 137 continue; 138 } 139 140 $i++; 141 142 do_action('wooms_products_variations_item', $item); 143 144 /** 145 * deprecated 146 */ 147 do_action('wooms_product_variant_import_row', $item, $key, $data); 148 } 149 150 //update count 151 self::set_state('count', self::get_state('count') + $i); 152 153 //update offset 154 $query_arg['offset'] = $query_arg['offset'] + count($data['rows']); 155 156 self::set_state('query_arg', $query_arg); 157 158 self::set_state('lock', 0); 159 160 self::add_schedule_hook(true); 161 162 do_action('wooms_variations_batch_end'); 163 164 return true; 165 } catch (\Exception $e) { 166 self::set_state('lock', 0); 167 do_action( 168 'wooms_logger_error', 169 __CLASS__, 170 $e->getMessage() 171 ); 172 return false; 173 } 174 } 175 176 177 /** 178 * If started main walker - set wait 179 */ 180 public static function set_wait() 181 { 182 as_unschedule_all_actions(self::$walker_hook_name); 183 self::set_state('end_timestamp', time()); 184 } 185 186 187 /** 188 * Resetting state after completing the main walker 189 * And restart schedules for sync variations 190 */ 191 public static function reset_after_main_walker_finish() 192 { 193 self::set_state('timestamp', 0); 194 self::set_state('count', 0); 195 self::set_state('lock', 0); 196 self::set_state('end_timestamp', 0); 197 self::add_schedule_hook(); 198 } 199 200 201 /** 202 * Set attributes for variables 203 */ 204 public static function set_product_attributes_for_variation($product_id, $data_api) 205 { 206 $product = wc_get_product($product_id); 207 208 $ms_attributes = []; 209 foreach ($data_api['characteristics'] as $key => $characteristic) { 210 211 $attribute_label = $characteristic["name"]; 212 213 $ms_attributes[$attribute_label] = [ 214 'name' => $characteristic["name"], 215 'values' => [], 216 ]; 217 } 218 219 $values = array(); 220 foreach ($data_api['characteristics'] as $key => $characteristic) { 221 $attribute_label = $characteristic["name"]; 222 223 if ($attribute_taxonomy_id = self::get_attribute_id_by_label($characteristic['name'])) { 224 $taxonomy_name = wc_attribute_taxonomy_name_by_id((int) $attribute_taxonomy_id); 225 $current_values = $product->get_attribute($taxonomy_name); 226 227 if ($current_values) { 228 $current_values = explode(', ', $current_values); 229 $current_values = array_map('trim', $current_values); 230 } 231 } else { 232 $current_values = $product->get_attribute($characteristic['name']); 233 $current_values = explode(' | ', $current_values); 234 } 235 236 if (empty($current_values)) { 237 $values[] = $characteristic['value']; 238 } else { 239 $values = $current_values; 240 $values[] = $characteristic['value']; 241 } 242 243 $values = apply_filters( 244 'wooms_product_attribute_save_values', 245 $values, 246 $product, 247 $characteristic 248 ); 249 $ms_attributes[$attribute_label]['values'] = $values; 250 } 251 252 /** 253 * check unique for values 254 */ 255 foreach ($ms_attributes as $key => $value) { 256 $ms_attributes[$key]['values'] = array_unique($value['values']); 257 } 258 259 $attributes = $product->get_attributes('edit'); 260 261 if (empty($attributes)) { 262 $attributes = array(); 263 } 264 265 foreach ($ms_attributes as $key => $value) { 266 $attribute_taxonomy_id = self::get_attribute_id_by_label($value['name']); 267 $attribute_slug = sanitize_title($value['name']); 268 269 if (empty($attribute_taxonomy_id)) { 270 $attribute_object = new \WC_Product_Attribute(); 271 $attribute_object->set_name($value['name']); 272 $attribute_object->set_options($value['values']); 273 $attribute_object->set_position(0); 274 $attribute_object->set_visible(0); 275 $attribute_object->set_variation(1); 276 $attributes[$attribute_slug] = $attribute_object; 277 } else { 278 //Очищаем индивидуальный атрибут с таким именем если есть 279 if (isset($attributes[$attribute_slug])) { 280 unset($attributes[$attribute_slug]); 281 } 282 $taxonomy_name = wc_attribute_taxonomy_name_by_id((int) $attribute_taxonomy_id); 283 $attribute_object = new \WC_Product_Attribute(); 284 $attribute_object->set_id($attribute_taxonomy_id); 285 $attribute_object->set_name($taxonomy_name); 286 $attribute_object->set_options($value['values']); 287 $attribute_object->set_position(0); 288 $attribute_object->set_visible(0); 289 $attribute_object->set_variation(1); 290 $attributes[$taxonomy_name] = $attribute_object; 291 } 292 } 293 294 $attributes = apply_filters('wooms_product_attributes', $attributes, $data_api, $product); 295 296 $product->set_attributes($attributes); 297 298 $product->save(); 299 300 do_action( 301 'wooms_logger', 302 __CLASS__, 303 sprintf( 304 'Сохранены атрибуты для продукта: %s (%s)', 305 $product->get_name(), 306 $product_id 307 ), 308 $attributes 309 ); 310 } 311 312 313 /** 314 * Set attributes and value for variation 315 * 316 * @param $variation_id 317 * @param $characteristics 318 */ 319 public static function save_attributes_for_variation(\WC_Product_Variation $variation, $data_api, $product_id) 320 { 321 $variant_data = $data_api; 322 323 $variation_id = $variation->get_id(); 324 $parent_id = $variation->get_parent_id(); 325 326 $characteristics = $variant_data['characteristics']; 327 328 $attributes = array(); 329 330 foreach ($characteristics as $key => $characteristic) { 331 $attribute_label = $characteristic["name"]; 332 $attribute_slug = sanitize_title($attribute_label); 333 334 if ($attribute_taxonomy_id = self::get_attribute_id_by_label($attribute_label)) { 335 $taxonomy_name = wc_attribute_taxonomy_name_by_id($attribute_taxonomy_id); 336 if (isset($attributes[$attribute_slug])) { 337 unset($attributes[$attribute_slug]); 338 } 339 340 $attribute_value = $characteristic['value']; 341 342 $term = get_term_by('name', $attribute_value, $taxonomy_name); 343 344 if ($term && !is_wp_error($term)) { 345 $attribute_value = $term->slug; 346 } else { 347 $attribute_value = sanitize_title($attribute_value); 348 } 349 350 $attributes[$taxonomy_name] = $attribute_value; 351 } else { 352 $attributes[$attribute_slug] = $characteristic['value']; 353 } 354 } 355 356 $attributes = apply_filters('wooms_variation_attributes', $attributes, $data_api, $variation); 357 358 $variation->set_attributes($attributes); 359 360 do_action( 361 'wooms_logger', 362 __CLASS__, 363 sprintf('Сохранены атрибуты для вариации %s (продукт: %s)', $variation_id, $product_id), 364 wc_print_r($attributes, true) 365 ); 366 367 return $variation; 368 } 369 370 371 /** 372 * Installation of variations for variable product 373 */ 374 public static function load_data_variant($variant) 375 { 376 if (!empty($variant['archived'])) { 377 return; 378 } 379 380 $product_href = $variant['product']['meta']['href']; 381 $product_id = self::get_product_id_by_uuid($product_href); 382 383 if (empty($product_id)) { 384 385 /** 386 * придумать подход при котором вариации будут фильтроваться с учетом уже доступных продуктов на сайте 387 * до этого момента, эта ошибка будет возникать постоянно 388 */ 389 do_action( 390 'wooms_logger_error', 391 __CLASS__, 392 sprintf('Ошибка получения product_id для url %s', $product_href), 393 $variant 394 ); 395 396 return; 397 } 398 399 400 self::update_variant_for_product($product_id, $variant); 401 402 /** 403 * deprecated 404 */ 405 do_action('wooms_product_variant', $product_id, $variant); 406 } 407 408 409 /** 410 * Get product variant ID 411 * 412 * @param $uuid 413 */ 414 public static function get_product_id_by_uuid($uuid) 415 { 416 if (strpos($uuid, 'http') !== false) { 417 $uuid = str_replace('https://online.moysklad.ru/api/remap/1.1/entity/product/', '', $uuid); 418 $uuid = str_replace('https://online.moysklad.ru/api/remap/1.2/entity/product/', '', $uuid); 419 } 420 421 $posts = get_posts('post_type=product&meta_key=wooms_id&meta_value=' . $uuid); 422 if (empty($posts[0]->ID)) { 423 return false; 424 } 425 426 return $posts[0]->ID; 427 } 428 429 430 /** 431 * Update and add variables from product 432 * 433 * @param $product_id 434 * @param $value 435 */ 436 public static function update_variant_for_product($product_id, $data_api) 437 { 438 $variant_data = $data_api; 439 if (empty($data_api)) { 440 return; 441 } 442 443 //добавление атрибутов к основному продукту с пометкой для вариаций 444 self::set_product_attributes_for_variation($product_id, $variant_data); 445 446 if (!$variation_id = self::get_variation_by_wooms_id($product_id, $variant_data['id'])) { 447 $variation_id = self::add_variation($product_id, $variant_data); 448 } 449 450 $variation = wc_get_product($variation_id); 451 $variation->set_name($variant_data['name']); 452 453 $variation->set_stock_status('instock'); 454 455 if (!empty($variant_data["salePrices"][0]['value'])) { 456 $price = $variant_data["salePrices"][0]['value']; 457 } else { 458 $price = 0; 459 } 460 461 // $price = apply_filters('wooms_product_price', $price, $data_api, $variation_id); 462 463 $price = floatval($price) / 100; 464 $variation->set_price($price); 465 $variation->set_regular_price($price); 466 467 do_action( 468 'wooms_logger', 469 __CLASS__, 470 sprintf('Цена %s сохранена (для вариации %s продукта %s)', $price, $variation_id, $product_id) 471 ); 472 473 $product_parent = wc_get_product($product_id); 474 if (!$product_parent->is_type('variable')) { 475 $product_parent = new \WC_Product_Variable($product_parent); 476 $product_parent->save(); 477 478 do_action( 479 'wooms_logger_error', 480 __CLASS__, 481 sprintf('Снова сохранили продукт как вариативный %s', $product_id) 482 ); 483 } 484 485 /** 486 * deprecated 487 */ 488 $variation = apply_filters('wooms_save_variation', $variation, $variant_data, $product_id); 489 490 $variation = apply_filters('wooms_variation_save', $variation, $variant_data, $product_id); 491 492 if ($session_id = get_option('wooms_session_id')) { 493 $variation->update_meta_data('wooms_session_id', $session_id); 494 } 495 496 $variation->save(); 497 498 do_action( 499 'wooms_logger', 500 __CLASS__, 501 sprintf( 502 'Сохранена вариация: %s (%s), для продукта %s (%s)', 503 $variation->get_name(), 504 $variation_id, 505 $product_parent->get_name(), 506 $product_id 507 ) 508 ); 509 510 do_action('wooms_variation_id', $variation_id, $variant_data); 511 } 512 513 514 /** 515 * Get product parent ID 516 */ 517 public static function get_variation_by_wooms_id($parent_id, $id) 518 { 519 $posts = get_posts(array( 520 'post_type' => 'product_variation', 521 'post_parent' => $parent_id, 522 'meta_key' => 'wooms_id', 523 'meta_value' => $id, 524 )); 525 526 if (empty($posts)) { 527 return false; 528 } 529 530 return $posts[0]->ID; 531 } 532 533 534 /** 535 * Add variables from product 536 */ 537 public static function add_variation($product_id, $value) 538 { 539 $variation = new \WC_Product_Variation(); 540 $variation->set_parent_id(absint($product_id)); 541 $variation->set_status('publish'); 542 $variation->set_stock_status('instock'); 543 $r = $variation->save(); 544 545 $variation_id = $variation->get_id(); 546 if (empty($variation_id)) { 547 return false; 548 } 549 550 update_post_meta($variation_id, 'wooms_id', $value['id']); 551 552 do_action('wooms_add_variation', $variation_id, $product_id, $value); 553 554 return $variation_id; 555 } 556 557 558 /** 559 * Start import manually 560 */ 561 public static function start_manually() 562 { 563 delete_transient(self::$state_transient_key); 564 self::add_schedule_hook(); 565 wp_redirect(admin_url('admin.php?page=moysklad')); 566 } 567 568 569 /** 570 * Stopping walker imports from MoySklad 571 */ 572 public static function walker_finish() 573 { 574 self::set_state('end_timestamp', time()); 575 self::set_state('lock', 0); 576 577 do_action('wooms_wakler_variations_finish'); 578 579 do_action( 580 'wooms_logger', 581 __CLASS__, 582 'Вариации. Обработчик финишировал' 583 ); 584 585 return true; 586 } 587 588 /** 589 * Stop import manually 590 */ 591 public static function stop_manually() 592 { 593 as_unschedule_all_actions(self::$walker_hook_name); 594 595 self::walker_finish(); 596 597 wp_redirect(admin_url('admin.php?page=moysklad')); 598 } 599 600 /** 601 * Get attribute id by label 602 * or false 603 */ 604 public static function get_attribute_id_by_label($label = '') 605 { 606 if (empty($label)) { 607 return false; 608 } 609 610 $attr_taxonomies = wc_get_attribute_taxonomies(); 611 if (empty($attr_taxonomies)) { 612 return false; 613 } 614 615 if (!is_array($attr_taxonomies)) { 616 return false; 617 } 618 619 foreach ($attr_taxonomies as $attr) { 620 if ($attr->attribute_label == $label) { 621 return (int) $attr->attribute_id; 622 } 623 } 624 625 return false; 626 } 627 628 629 public static function is_wait() 630 { 631 //check run main walker 632 if (as_next_scheduled_action('wooms_products_walker_batch')) { 633 return true; 634 } 635 636 //check end pause 637 if (!empty(self::get_state('end_timestamp'))) { 638 return true; 639 } 640 641 return false; 642 } 643 644 645 /** 646 * Add schedule hook 647 */ 648 public static function add_schedule_hook($force = false) 649 { 650 if (!self::is_enable()) { 651 return; 652 } 653 654 if (self::is_wait()) { 655 return; 656 } 657 658 if (as_next_scheduled_action(self::$walker_hook_name) && ! $force) { 659 return; 660 } 661 662 if ($force) { 663 self::set_state('force', 1); 664 } else { 665 self::set_state('force', 0); 666 } 667 668 // Adding schedule hook 669 as_schedule_single_action(time() + 5, self::$walker_hook_name, self::get_state(), 'WooMS'); 670 } 671 672 673 /** 674 * display_state 675 */ 676 public static function display_state() 677 { 678 679 if (!self::is_enable()) { 680 return; 681 } 682 683 echo '<h2>Вариации (Модификации)</h2>'; 684 685 echo "<p>Нажмите на кнопку ниже, чтобы запустить синхронизацию данных о вариативных товарах вручную</p>"; 686 687 if (as_next_scheduled_action(self::$walker_hook_name)) { 688 printf( 689 '<a href="%s" class="button button-secondary">Остановить синхронизацию вариативных продуктов</a>', 690 add_query_arg('a', 'wooms_import_variations_manual_stop', admin_url('admin.php?page=moysklad')) 691 ); 692 } else { 693 printf( 694 '<a href="%s" class="button button-primary">Запустить синхронизацию вариативных продуктов</a>', 695 add_query_arg('a', 'wooms_import_variations_manual_start', admin_url('admin.php?page=moysklad')) 696 ); 697 } 698 699 $strings = []; 700 701 if (as_next_scheduled_action(self::$walker_hook_name)) { 702 $strings[] = sprintf('<strong>Статус:</strong> %s', 'Выполняется очередями в фоне'); 703 } else { 704 $strings[] = sprintf('<strong>Статус:</strong> %s', 'в ожидании задач'); 705 } 706 707 if ($end_timestamp = self::get_state('end_timestamp')) { 708 $end_timestamp = date('Y-m-d H:i:s', $end_timestamp); 709 $strings[] = sprintf('Последняя успешная синхронизация (отметка времени UTC): %s', $end_timestamp); 710 } 711 712 $strings[] = sprintf('Очередь задач: <a href="%s">открыть</a>', admin_url('admin.php?page=wc-status&tab=action-scheduler&s=wooms_variables_walker_batch&orderby=schedule&order=desc')); 713 714 715 if (defined('WC_LOG_HANDLER') && 'WC_Log_Handler_DB' == WC_LOG_HANDLER) { 716 $strings[] = sprintf('Журнал обработки: <a href="%s">открыть</a>', admin_url('admin.php?page=wc-status&tab=logs&source=WooMS-ProductVariable')); 717 } else { 718 $strings[] = sprintf('Журнал обработки: <a href="%s">открыть</a>', admin_url('admin.php?page=wc-status&tab=logs')); 719 } 720 721 $strings[] = sprintf('Количество обработанных записей: %s', empty(self::get_state('count')) ? 0 : self::get_state('count')); 470 $variation = apply_filters('wooms_save_variation', $variation, $variant_data, $product_id); 471 472 $variation = apply_filters('wooms_variation_save', $variation, $variant_data, $product_id); 473 474 $variation->save(); 475 476 do_action( 477 'wooms_logger', 478 __CLASS__, 479 sprintf( 480 'Сохранена вариация: %s (%s), для продукта %s (%s)', 481 $variation->get_name(), 482 $variation_id, 483 $product_parent->get_name(), 484 $product_id 485 ) 486 ); 487 488 do_action('wooms_variation_id', $variation_id, $variant_data); 489 } 490 491 public static function get_session_id(){ 492 return \WooMS\Products\get_session_id(); 493 } 494 /** 495 * Get product parent ID 496 */ 497 public static function get_variation_by_wooms_id($parent_id, $id) 498 { 499 $posts = get_posts( 500 array( 501 'post_type' => 'product_variation', 502 'post_parent' => $parent_id, 503 'meta_key' => 'wooms_id', 504 'meta_value' => $id, 505 ) 506 ); 507 508 if (empty($posts)) { 509 return false; 510 } 511 512 return $posts[0]->ID; 513 } 514 515 516 /** 517 * Add variables from product 518 */ 519 public static function add_variation($product_id, $value) 520 { 521 $variation = new \WC_Product_Variation(); 522 $variation->set_parent_id(absint($product_id)); 523 $variation->set_status('publish'); 524 $variation->set_stock_status('instock'); 525 $r = $variation->save(); 526 527 $variation_id = $variation->get_id(); 528 if (empty($variation_id)) { 529 return false; 530 } 531 532 update_post_meta($variation_id, 'wooms_id', $value['id']); 533 534 do_action('wooms_add_variation', $variation_id, $product_id, $value); 535 536 return $variation_id; 537 } 538 539 540 /** 541 * Start import manually 542 */ 543 public static function start_manually() 544 { 545 as_schedule_single_action(time() + 5, self::$walker_hook_name, [], 'WooMS'); 546 wp_redirect(admin_url('admin.php?page=moysklad')); 547 } 548 549 550 /** 551 * Stopping walker imports from MoySklad 552 */ 553 public static function walker_finish() 554 { 555 self::set_state('end_timestamp', time()); 556 self::set_state('lock', 0); 557 558 do_action('wooms_wakler_variations_finish'); 559 560 do_action( 561 'wooms_logger', 562 __CLASS__, 563 'Вариации. Обработчик финишировал' 564 ); 565 566 return true; 567 } 568 569 /** 570 * Stop import manually 571 */ 572 public static function stop_manually() 573 { 574 as_unschedule_all_actions(self::$walker_hook_name); 575 576 self::walker_finish(); 577 578 wp_redirect(admin_url('admin.php?page=moysklad')); 579 } 580 581 /** 582 * Get attribute id by label 583 * or false 584 */ 585 public static function get_attribute_id_by_label($label = '') 586 { 587 if (empty($label)) { 588 return false; 589 } 590 591 $attr_taxonomies = wc_get_attribute_taxonomies(); 592 if (empty($attr_taxonomies)) { 593 return false; 594 } 595 596 if (!is_array($attr_taxonomies)) { 597 return false; 598 } 599 600 foreach ($attr_taxonomies as $attr) { 601 if ($attr->attribute_label == $label) { 602 return (int) $attr->attribute_id; 603 } 604 } 605 606 return false; 607 } 608 609 610 public static function is_wait() 611 { 612 //check run main walker 613 if (as_next_scheduled_action('wooms_products_walker_batch')) { 614 return true; 615 } 616 617 //check end pause 618 if (!empty(self::get_state('end_timestamp'))) { 619 return true; 620 } 621 622 return false; 623 } 624 625 626 627 /** 628 * display_state 629 */ 630 public static function display_state() 631 { 632 633 if (!self::is_enable()) { 634 return; 635 } 636 637 echo '<h2>Вариации и Модификации</h2>'; 638 639 if (as_next_scheduled_action(self::$walker_hook_name)) { 640 printf( 641 '<a href="%s" class="button button-secondary">Остановить синхронизацию вариативных продуктов</a>', 642 add_query_arg('a', 'wooms_import_variations_manual_stop', admin_url('admin.php?page=moysklad')) 643 ); 644 } else { 645 printf( 646 '<a href="%s" class="button button-primary">Запустить синхронизацию вариативных продуктов</a>', 647 add_query_arg('a', 'wooms_import_variations_manual_start', admin_url('admin.php?page=moysklad')) 648 ); 649 } 650 651 $strings = []; 652 653 if (as_next_scheduled_action(self::$walker_hook_name)) { 654 $strings[] = sprintf('<strong>Статус:</strong> %s', 'Выполняется очередями в фоне'); 655 656 } else { 657 $strings[] = sprintf('<strong>Статус:</strong> %s', 'в ожидании задач'); 658 $strings[] = sprintf('Последняя успешная синхронизация: %s', wooms_get_timestamp_last_job_by_hook(self::$walker_hook_name)); 659 } 660 661 662 $strings[] = sprintf('Очередь задач: <a href="%s">открыть</a>', admin_url('admin.php?page=wc-status&tab=action-scheduler&s=wooms_variables_walker_batch&orderby=schedule&order=desc')); 663 664 665 if (defined('WC_LOG_HANDLER') && 'WC_Log_Handler_DB' == WC_LOG_HANDLER) { 666 $strings[] = sprintf('Журнал обработки: <a href="%s">открыть</a>', admin_url('admin.php?page=wc-status&tab=logs&source=WooMS-ProductVariable')); 667 } else { 668 $strings[] = sprintf('Журнал обработки: <a href="%s">открыть</a>', admin_url('admin.php?page=wc-status&tab=logs')); 669 } 670 671 $strings[] = sprintf('Количество обработанных записей: %s', empty(self::get_state('count')) ? 0 : self::get_state('count')); 722 672 723 673 ?> 724 <div class="wrap"> 725 <div id="message" class="notice notice-warning"> 726 <?php 727 foreach ($strings as $string) { 728 printf('<p>%s</p>', $string); 729 } 730 ?> 731 </div> 732 </div> 674 <div> 675 <?php 676 foreach ($strings as $string) { 677 printf('<p>%s</p>', $string); 678 } 679 ?> 680 </div> 733 681 <?php 734 } 735 736 737 /** 738 * Settings import variations 739 */ 740 public static function add_settings() 741 { 742 $option_name = 'woomss_variations_sync_enabled'; 743 register_setting('mss-settings', $option_name); 744 add_settings_field( 745 $id = $option_name, 746 $title = 'Включить синхронизацию вариаций', 747 $callback = function ($args) { 748 printf('<input type="checkbox" name="%s" value="1" %s />', $args['name'], checked(1, $args['value'], false)); 749 printf('<p><strong>%s</strong></p>', 'Тестовый режим. Не включайте эту функцию на реальном сайте, пока не проверите ее на тестовой копии сайта.'); 750 }, 751 $page = 'mss-settings', 752 $section = 'woomss_section_other', 753 $args = [ 754 'name' => $option_name, 755 'value' => get_option($option_name), 756 ] 757 ); 758 } 759 760 761 /** 762 * Получаем данные таксономии по id глобального артибута 763 */ 764 public static function get_attribute_taxonomy_by_id($id = 0) 765 { 766 767 if (empty($id)) { 768 return false; 769 } 770 771 $taxonomy = null; 772 $attribute_taxonomies = wc_get_attribute_taxonomies(); 773 774 foreach ($attribute_taxonomies as $key => $tax) { 775 if ($id == $tax->attribute_id) { 776 $taxonomy = $tax; 777 $taxonomy->slug = 'pa_' . $tax->attribute_name; 778 779 break; 780 } 781 } 782 783 return $taxonomy; 784 } 785 786 787 /** 788 * checking is enable 789 */ 790 public static function is_enable() 791 { 792 if (empty(get_option('woomss_variations_sync_enabled'))) { 793 return false; 794 } 795 796 return true; 797 } 798 799 800 /** 801 * Update product from source data 802 */ 803 public static function update_product($product, $data_api) 804 { 805 $item = $data_api; 806 807 if (!self::is_enable()) { 808 if ($product->is_type('variable')) { 809 $product = new \WC_Product_Simple($product); 810 } 811 812 return $product; 813 } 814 815 if (empty($item['variantsCount'])) { 816 if ($product->is_type('variable')) { 817 $product = new \WC_Product_Simple($product); 818 } 819 820 return $product; 821 } 822 823 $product_id = $product->get_id(); 824 825 if (!$product->is_type('variable')) { 826 $product = new \WC_Product_Variable($product); 827 828 do_action( 829 'wooms_logger', 830 __CLASS__, 831 sprintf('Продукт изменен как вариативный %s', $product_id) 832 ); 833 } 834 835 return $product; 836 } 837 838 839 840 /** 841 * get state data 842 */ 843 public static function get_state($key = '') 844 { 845 if (!$state = get_transient(self::$state_transient_key)) { 846 $state = []; 847 set_transient(self::$state_transient_key, $state); 848 } 849 850 if (empty($key)) { 851 return $state; 852 } 853 854 if (empty($state[$key])) { 855 return null; 856 } 857 858 return $state[$key]; 859 } 860 861 /** 862 * set state data 863 */ 864 public static function set_state($key, $value) 865 { 866 867 if (!$state = get_transient(self::$state_transient_key)) { 868 $state = []; 869 } 870 871 if (is_array($state)) { 872 $state[$key] = $value; 873 } else { 874 $state = []; 875 $state[$key] = $value; 876 } 877 878 set_transient(self::$state_transient_key, $state); 879 } 880 881 /** 882 * show wooms_id for variation in admin 883 */ 884 public static function variation_sync_id($variation) { 885 $wooms_id = get_post_meta($variation->ID, 'wooms_id', true); 886 if ($wooms_id) { 887 echo 'wooms_id: ' . $wooms_id; 888 } 889 } 682 } 683 684 685 /** 686 * Settings import variations 687 */ 688 public static function add_settings() 689 { 690 $option_name = 'woomss_variations_sync_enabled'; 691 register_setting('mss-settings', $option_name); 692 add_settings_field( 693 $id = $option_name, 694 $title = 'Вариации и модификации', 695 $callback = function ($args) { 696 printf('<input type="checkbox" name="%s" value="1" %s />', $args['name'], checked(1, $args['value'], false)); 697 printf('<p><strong>%s</strong></p>', 'Синхронизация модификаций продуктов из МойСклад на Сайт'); 698 }, 699 $page = 'mss-settings', 700 $section = 'woomss_section_other', 701 $args = [ 702 'name' => $option_name, 703 'value' => get_option($option_name), 704 ] 705 ); 706 } 707 708 709 /** 710 * Получаем данные таксономии по id глобального артибута 711 */ 712 public static function get_attribute_taxonomy_by_id($id = 0) 713 { 714 715 if (empty($id)) { 716 return false; 717 } 718 719 $taxonomy = null; 720 $attribute_taxonomies = wc_get_attribute_taxonomies(); 721 722 foreach ($attribute_taxonomies as $key => $tax) { 723 if ($id == $tax->attribute_id) { 724 $taxonomy = $tax; 725 $taxonomy->slug = 'pa_' . $tax->attribute_name; 726 727 break; 728 } 729 } 730 731 return $taxonomy; 732 } 733 734 735 /** 736 * checking is enable 737 */ 738 public static function is_enable() 739 { 740 if (empty(get_option('woomss_variations_sync_enabled'))) { 741 return false; 742 } 743 744 return true; 745 } 746 747 748 /** 749 * Update product from source data 750 */ 751 public static function update_product($product, $data_api) 752 { 753 $item = $data_api; 754 755 if (!self::is_enable()) { 756 if ($product->is_type('variable')) { 757 $product = new \WC_Product_Simple($product); 758 } 759 760 return $product; 761 } 762 763 if (empty($item['variantsCount'])) { 764 if ($product->is_type('variable')) { 765 $product = new \WC_Product_Simple($product); 766 } 767 768 return $product; 769 } 770 771 $product_id = $product->get_id(); 772 773 if (!$product->is_type('variable')) { 774 $product = new \WC_Product_Variable($product); 775 776 do_action( 777 'wooms_logger', 778 __CLASS__, 779 sprintf('Продукт изменен как вариативный %s', $product_id) 780 ); 781 } 782 783 return $product; 784 } 785 786 787 788 /** 789 * get state data 790 */ 791 public static function get_state($key = '') 792 { 793 if (!$state = get_option(self::$state_transient_key)) { 794 $state = []; 795 update_option(self::$state_transient_key, $state); 796 } 797 798 if (empty($key)) { 799 return $state; 800 } 801 802 if (empty($state[$key])) { 803 return null; 804 } 805 806 return $state[$key]; 807 } 808 809 /** 810 * set state data 811 */ 812 public static function set_state($key, $value = null) 813 { 814 if ($value === null && is_array($key)) { 815 update_option(self::$state_transient_key, $key, false); 816 return; 817 } 818 819 if (!$state = get_option(self::$state_transient_key)) { 820 $state = []; 821 } 822 823 if (is_array($state)) { 824 $state[$key] = $value; 825 } else { 826 $state = []; 827 $state[$key] = $value; 828 } 829 830 update_option(self::$state_transient_key, $state, false); 831 } 832 833 /** 834 * show wooms_id for variation in admin 835 */ 836 public static function variation_sync_id($variation) 837 { 838 $wooms_id = get_post_meta($variation->ID, 'wooms_id', true); 839 if ($wooms_id) { 840 echo 'wooms_id: ' . $wooms_id; 841 } 842 } 890 843 } 891 844 -
wooms/tags/9.0.1/includes/Products.php
r2826440 r2826597 97 97 */ 98 98 set_state('session_id', null); 99 100 //backwards compatible - to delete101 delete_option('wooms_session_id');102 99 103 100 do_action('wooms_logger_error', __NAMESPACE__, 'Главный обработчик завершился с ошибкой... ' . $e->getMessage()); … … 163 160 * issue https://github.com/wpcraft-ru/wooms/issues/305 164 161 */ 165 // delete_option('wooms_session_id');166 162 set_state('session_id', null); 167 163 … … 170 166 } 171 167 168 function get_session_id(){ 169 return get_state('session_id'); 170 } 171 172 172 /** 173 173 * Update product from source data … … 176 176 { 177 177 $data_of_source = $data_api; 178 $product_id = $product->get_id();179 178 180 179 //Set session id for product … … 460 459 { 461 460 462 // backward compatibility - need delete after all updates463 // update_option('wooms_session_id', $now, 'no'); //set id session sync464 465 461 $batch_size = get_option('wooms_batch_size', 20); 466 462 $query_arg_default = [ -
wooms/tags/9.0.1/includes/ProductsHiding.php
r2826440 r2826597 44 44 45 45 if ($product->get_type() == 'variable') { 46 $product->set_manage_stock('yes');46 // $product->set_manage_stock('yes'); 47 47 } 48 48 … … 103 103 104 104 $args = array( 105 'post_type' => 'product',105 'post_type' => ['product', 'product_variation'], 106 106 'numberposts' => 30, 107 107 'fields' => 'ids', -
wooms/tags/9.0.1/includes/ProductsServices.php
r2826440 r2826597 16 16 /** 17 17 * Save state in DB 18 * 18 * 19 19 * @var string 20 20 */ … … 139 139 self::set_state('count', self::get_state('count') + $i); 140 140 141 //update offset 141 //update offset 142 142 $query_arg['offset'] = $query_arg['offset'] + count($data['rows']); 143 143 … … 258 258 /** 259 259 * update_product 260 * 261 * @param \WC_Product $product 262 * @param array $api_data 260 263 */ 261 264 public static function update_product($product, $api_data) -
wooms/tags/9.0.1/readme.txt
r2826440 r2826597 80 80 81 81 == Changelog == 82 83 = 9.0.1 = 84 - исправлена ошибка синхронизации вариаций 82 85 83 86 = 9.0 = -
wooms/tags/9.0.1/wooms.php
r2826440 r2826597 20 20 * WC tested up to: 7.1 21 21 * 22 * Version: 9.0 22 * Version: 9.0.1 23 23 */ 24 24 -
wooms/trunk/includes/OrderNumber.php
r2826440 r2826597 7 7 /** 8 8 * Get and save order number from MoySklad 9 * 9 * 10 10 * issue https://github.com/wpcraft-ru/wooms/issues/319 11 11 */ … … 19 19 add_filter('wooms_update_order_from_moysklad', array(__CLASS__, 'set_order_number'), 10, 2); 20 20 21 add_action('admin_init', array(__CLASS__, 'add_settings'), 50);21 add_action('admin_init', array(__CLASS__, 'add_settings'), 30); 22 22 add_action('pre_get_posts', array(__CLASS__, 'search_by_number_from_moysklad')); 23 23 } … … 25 25 /** 26 26 * set_order_number 27 * 27 * 28 28 * use hook $order = apply_filters('wooms_order_update', $order, $result); 29 29 */ … … 56 56 57 57 /** 58 * 58 * 59 59 * use hook $data = apply_filters('wooms_order_data', $data, $order_id); 60 60 */ … … 147 147 /** 148 148 * Если используются номера заказов из Мой Склад, чиним поиску по номеру заказа 149 * 149 * 150 150 * issue https://github.com/wpcraft-ru/wooms/issues/331 151 151 */ … … 167 167 return; 168 168 } 169 169 170 170 $custom_order_id = $query->query['s']; 171 171 $query->query_vars['post__in']=array(); -
wooms/trunk/includes/Orders.php
r2826440 r2826597 60 60 add_action('wooms_order_metabox_controls', array(__CLASS__, 'add_controle_for_sync')); 61 61 62 add_action('admin_init', array(__CLASS__, 'add_settings'), 40);62 add_action('admin_init', array(__CLASS__, 'add_settings'), 10); 63 63 64 64 add_action( 'woocommerce_order_item_meta_start', function () { … … 449 449 if (empty($result['id']) || !isset($result['id']) || isset($result['errors'])) { 450 450 update_post_meta($order_id, 'wooms_send_timestamp', date("Y-m-d H:i:s")); 451 // $errors = "\n\r" . 'Код ошибки:' . $result['errors'][0]['code'] . "\n\r"; 452 // $errors .= 'Параметр:' . $result['errors'][0]['parameter'] . "\n\r"; 453 // $errors .= $result['errors'][0]['error']; 451 delete_post_meta( $order_id, 'wooms_order_sync' ); 454 452 455 453 do_action( -
wooms/trunk/includes/ProductVariable.php
r2826440 r2826597 11 11 class ProductVariable 12 12 { 13 /** 14 * Save state in DB 15 * 16 * @var string 17 */ 18 public static $state_transient_key = 'wooms_variables_walker_state'; 19 20 /** 21 * Hookd and key for ActionSheduler 22 * 23 * @var string 24 */ 25 public static $walker_hook_name = 'wooms_variables_walker_batch'; 26 27 28 /** 29 * The init 30 */ 31 public static function init() 32 { 33 34 //walker 35 add_action('wooms_variables_walker_batch', array(__CLASS__, 'walker')); 36 37 add_filter('wooms_product_save', array(__CLASS__, 'update_product'), 20, 3); 38 39 add_filter('wooms_save_variation', array(__CLASS__, 'save_attributes_for_variation'), 10, 3); 40 41 //Other 42 add_action('admin_init', array(__CLASS__, 'add_settings'), 150); 43 add_action('woomss_tool_actions_wooms_import_variations_manual_start', array(__CLASS__, 'start_manually')); 44 add_action('woomss_tool_actions_wooms_import_variations_manual_stop', array(__CLASS__, 'stop_manually')); 45 add_action('wooms_main_walker_finish', array(__CLASS__, 'reset_after_main_walker_finish')); 46 add_action('wooms_main_walker_started', array(__CLASS__, 'set_wait')); 47 48 add_action('woomss_tool_actions_btns', array(__CLASS__, 'display_state'), 15); 49 50 add_action('woocommerce_variation_header', array(__CLASS__, 'variation_sync_id'), 10); 51 } 52 53 54 /** 55 * Walker for data variant product from MoySklad 56 */ 57 public static function walker($state = []) 58 { 59 //reset state if new session 60 if (empty($state)) { 61 62 $state = [ 63 'timestamp' => date("YmdHis"), 64 'end_timestamp' => 0, 65 'count' => 0, 66 'query_arg' => [ 67 'offset' => 0, 68 'limit' => apply_filters('wooms_variant_iteration_size', 30), 69 ] 70 ]; 71 72 self::set_state($state); 73 } 74 13 75 /** 14 * Save state in DB 15 * 16 * @var string 76 * issue https://github.com/wpcraft-ru/wooms/issues/296 17 77 */ 18 public static $state_transient_key = 'wooms_variables_walker_state'; 78 $url = 'https://online.moysklad.ru/api/remap/1.2/entity/variant'; 79 80 $url = add_query_arg($state['query_arg'], $url); 81 82 $filters = []; 83 84 $filters = apply_filters('wooms_url_get_variants_filter', $filters); 85 86 $url = add_query_arg('filter', implode(';', $filters), $url); 87 88 $url = apply_filters('wooms_url_get_variants', $url); 89 90 try { 91 92 do_action( 93 'wooms_logger', 94 __CLASS__, 95 sprintf('Вариации. Отправлен запрос: %s', $url), 96 $state 97 ); 98 99 $data = wooms_request($url); 100 101 //Check for errors and send message to UI 102 if (isset($data['errors'][0]["error"])) { 103 throw new \Exception($data['errors'][0]["error"]); 104 } 105 106 //If no rows, that send 'end' and stop walker 107 if (isset($data['rows']) && empty($data['rows'])) { 108 109 self::walker_finish(); 110 return true; 111 } 112 113 $i = self::process_rows($data['rows']); 114 115 $state['count'] += $i; 116 $state['query_arg']['offset'] += count($data['rows']); 117 self::set_state($state); 118 119 do_action('wooms_variations_batch_end'); 120 121 as_schedule_single_action(time() + 1, self::$walker_hook_name, [$state], 'WooMS'); 122 123 return true; 124 } catch (\Exception $e) { 125 self::set_state('lock', 0); 126 do_action( 127 'wooms_logger_error', 128 __CLASS__, 129 $e->getMessage() 130 ); 131 return false; 132 } 133 } 134 135 /** 136 * process rows from api 137 */ 138 public static function process_rows($rows) 139 { 140 141 $i = 0; 142 foreach ($rows as $key => $item) { 143 144 if ($item["meta"]["type"] != 'variant') { 145 continue; 146 } 147 148 $i++; 149 150 self::load_data_variant($item); 151 do_action('wooms_products_variations_item', $item); 152 153 } 154 155 return $i; 156 } 157 158 /** 159 * If started main walker - set wait 160 */ 161 public static function set_wait() 162 { 163 as_unschedule_all_actions(self::$walker_hook_name); 164 self::set_state('end_timestamp', time()); 165 } 166 167 168 /** 169 * Resetting state after completing the main walker 170 * And restart schedules for sync variations 171 */ 172 public static function reset_after_main_walker_finish() 173 { 174 as_schedule_single_action(time() + 5, self::$walker_hook_name, [], 'WooMS'); 175 } 176 177 178 /** 179 * Set attributes for variables 180 */ 181 public static function set_product_attributes_for_variation($product_id, $data_api) 182 { 183 $product = wc_get_product($product_id); 184 185 $ms_attributes = []; 186 foreach ($data_api['characteristics'] as $key => $characteristic) { 187 188 $attribute_label = $characteristic["name"]; 189 190 $ms_attributes[$attribute_label] = [ 191 'name' => $characteristic["name"], 192 'values' => [], 193 ]; 194 } 195 196 $values = array(); 197 foreach ($data_api['characteristics'] as $key => $characteristic) { 198 $attribute_label = $characteristic["name"]; 199 200 if ($attribute_taxonomy_id = self::get_attribute_id_by_label($characteristic['name'])) { 201 $taxonomy_name = wc_attribute_taxonomy_name_by_id((int) $attribute_taxonomy_id); 202 $current_values = $product->get_attribute($taxonomy_name); 203 204 if ($current_values) { 205 $current_values = explode(', ', $current_values); 206 $current_values = array_map('trim', $current_values); 207 } 208 } else { 209 $current_values = $product->get_attribute($characteristic['name']); 210 $current_values = explode(' | ', $current_values); 211 } 212 213 if (empty($current_values)) { 214 $values[] = $characteristic['value']; 215 } else { 216 $values = $current_values; 217 $values[] = $characteristic['value']; 218 } 219 220 $values = apply_filters( 221 'wooms_product_attribute_save_values', 222 $values, 223 $product, 224 $characteristic 225 ); 226 $ms_attributes[$attribute_label]['values'] = $values; 227 } 19 228 20 229 /** 21 * Hookd and key for ActionSheduler 22 * 23 * @var string 230 * check unique for values 24 231 */ 25 public static $walker_hook_name = 'wooms_variables_walker_batch'; 26 232 foreach ($ms_attributes as $key => $value) { 233 $ms_attributes[$key]['values'] = array_unique($value['values']); 234 } 235 236 $attributes = $product->get_attributes('edit'); 237 238 if (empty($attributes)) { 239 $attributes = array(); 240 } 241 242 foreach ($ms_attributes as $key => $value) { 243 $attribute_taxonomy_id = self::get_attribute_id_by_label($value['name']); 244 $attribute_slug = sanitize_title($value['name']); 245 246 if (empty($attribute_taxonomy_id)) { 247 $attribute_object = new \WC_Product_Attribute(); 248 $attribute_object->set_name($value['name']); 249 $attribute_object->set_options($value['values']); 250 $attribute_object->set_position(0); 251 $attribute_object->set_visible(0); 252 $attribute_object->set_variation(1); 253 $attributes[$attribute_slug] = $attribute_object; 254 } else { 255 //Очищаем индивидуальный атрибут с таким именем если есть 256 if (isset($attributes[$attribute_slug])) { 257 unset($attributes[$attribute_slug]); 258 } 259 $taxonomy_name = wc_attribute_taxonomy_name_by_id((int) $attribute_taxonomy_id); 260 $attribute_object = new \WC_Product_Attribute(); 261 $attribute_object->set_id($attribute_taxonomy_id); 262 $attribute_object->set_name($taxonomy_name); 263 $attribute_object->set_options($value['values']); 264 $attribute_object->set_position(0); 265 $attribute_object->set_visible(0); 266 $attribute_object->set_variation(1); 267 $attributes[$taxonomy_name] = $attribute_object; 268 } 269 } 270 271 $attributes = apply_filters('wooms_product_attributes', $attributes, $data_api, $product); 272 273 $product->set_attributes($attributes); 274 275 $product->save(); 276 277 do_action( 278 'wooms_logger', 279 __CLASS__, 280 sprintf( 281 'Сохранены атрибуты для продукта: %s (%s)', 282 $product->get_name(), 283 $product_id 284 ), 285 $attributes 286 ); 287 } 288 289 290 /** 291 * Set attributes and value for variation 292 * 293 * @param $variation_id 294 * @param $characteristics 295 */ 296 public static function save_attributes_for_variation(\WC_Product_Variation $variation, $data_api, $product_id) 297 { 298 $variant_data = $data_api; 299 300 $variation_id = $variation->get_id(); 301 $parent_id = $variation->get_parent_id(); 302 303 $characteristics = $variant_data['characteristics']; 304 305 $attributes = array(); 306 307 foreach ($characteristics as $key => $characteristic) { 308 $attribute_label = $characteristic["name"]; 309 $attribute_slug = sanitize_title($attribute_label); 310 311 if ($attribute_taxonomy_id = self::get_attribute_id_by_label($attribute_label)) { 312 $taxonomy_name = wc_attribute_taxonomy_name_by_id($attribute_taxonomy_id); 313 if (isset($attributes[$attribute_slug])) { 314 unset($attributes[$attribute_slug]); 315 } 316 317 $attribute_value = $characteristic['value']; 318 319 $term = get_term_by('name', $attribute_value, $taxonomy_name); 320 321 if ($term && !is_wp_error($term)) { 322 $attribute_value = $term->slug; 323 } else { 324 $attribute_value = sanitize_title($attribute_value); 325 } 326 327 $attributes[$taxonomy_name] = $attribute_value; 328 } else { 329 $attributes[$attribute_slug] = $characteristic['value']; 330 } 331 } 332 333 $attributes = apply_filters('wooms_variation_attributes', $attributes, $data_api, $variation); 334 335 $variation->set_attributes($attributes); 336 337 do_action( 338 'wooms_logger', 339 __CLASS__, 340 sprintf('Сохранены атрибуты для вариации %s (продукт: %s)', $variation_id, $product_id), 341 wc_print_r($attributes, true) 342 ); 343 344 return $variation; 345 } 346 347 348 /** 349 * Installation of variations for variable product 350 */ 351 public static function load_data_variant($variant) 352 { 353 if (!empty($variant['archived'])) { 354 return; 355 } 356 357 $product_href = $variant['product']['meta']['href']; 358 $product_id = self::get_product_id_by_uuid($product_href); 359 360 if (empty($product_id)) { 361 362 /** 363 * придумать подход при котором вариации будут фильтроваться с учетом уже доступных продуктов на сайте 364 * до этого момента, эта ошибка будет возникать постоянно 365 */ 366 do_action( 367 'wooms_logger_error', 368 __CLASS__, 369 sprintf('Ошибка получения product_id для url %s', $product_href), 370 $variant 371 ); 372 373 return; 374 } 375 376 377 self::update_variant_for_product($product_id, $variant); 27 378 28 379 /** 29 * The init380 * deprecated 30 381 */ 31 public static function init() 32 { 33 34 //walker 35 add_action('wooms_variables_walker_batch', array(__CLASS__, 'batch_handler')); 36 37 add_filter('wooms_product_save', array(__CLASS__, 'update_product'), 20, 3); 38 39 add_filter('wooms_save_variation', array(__CLASS__, 'save_attributes_for_variation'), 10, 3); 40 add_action('wooms_products_variations_item', array(__CLASS__, 'load_data_variant'), 15); 41 42 //Other 43 add_action('admin_init', array(__CLASS__, 'add_settings'), 150); 44 add_action('woomss_tool_actions_wooms_import_variations_manual_start', array(__CLASS__, 'start_manually')); 45 add_action('woomss_tool_actions_wooms_import_variations_manual_stop', array(__CLASS__, 'stop_manually')); 46 add_action('wooms_main_walker_finish', array(__CLASS__, 'reset_after_main_walker_finish')); 47 add_action('wooms_main_walker_started', array(__CLASS__, 'set_wait')); 48 49 add_action('init', array(__CLASS__, 'add_schedule_hook')); 50 51 add_action('woomss_tool_actions_btns', array(__CLASS__, 'display_state'), 15); 52 53 add_action('woocommerce_variation_header', array(__CLASS__, 'variation_sync_id'), 10); 54 } 55 382 do_action('wooms_product_variant', $product_id, $variant); 383 } 384 385 386 /** 387 * Get product variant ID 388 * 389 * @param $uuid 390 */ 391 public static function get_product_id_by_uuid($uuid) 392 { 393 if (strpos($uuid, 'http') !== false) { 394 $uuid = str_replace('https://online.moysklad.ru/api/remap/1.1/entity/product/', '', $uuid); 395 $uuid = str_replace('https://online.moysklad.ru/api/remap/1.2/entity/product/', '', $uuid); 396 } 397 398 $posts = get_posts('post_type=product&meta_key=wooms_id&meta_value=' . $uuid); 399 if (empty($posts[0]->ID)) { 400 return false; 401 } 402 403 return $posts[0]->ID; 404 } 405 406 407 /** 408 * Update and add variables from product 409 * 410 * @param $product_id 411 * @param $value 412 */ 413 public static function update_variant_for_product($product_id, $variant_data) 414 { 415 if (empty($variant_data)) { 416 return; 417 } 418 419 if (!empty($variant_data['archived'])) { 420 return; 421 } 422 423 //добавление атрибутов к основному продукту с пометкой для вариаций 424 self::set_product_attributes_for_variation($product_id, $variant_data); 425 426 if (!$variation_id = self::get_variation_by_wooms_id($product_id, $variant_data['id'])) { 427 $variation_id = self::add_variation($product_id, $variant_data); 428 } 429 430 $variation = wc_get_product($variation_id); 431 $variation->set_name($variant_data['name']); 432 433 $variation->set_stock_status('instock'); 434 435 if (!empty($variant_data["salePrices"][0]['value'])) { 436 $price = $variant_data["salePrices"][0]['value']; 437 } else { 438 $price = 0; 439 } 440 441 $price = floatval($price) / 100; 442 $variation->set_price($price); 443 $variation->set_regular_price($price); 444 445 do_action( 446 'wooms_logger', 447 __CLASS__, 448 sprintf('Цена %s сохранена (для вариации %s продукта %s)', $price, $variation_id, $product_id) 449 ); 450 451 $product_parent = wc_get_product($product_id); 452 if (!$product_parent->is_type('variable')) { 453 $product_parent = new \WC_Product_Variable($product_parent); 454 $product_parent->save(); 455 456 do_action( 457 'wooms_logger_error', 458 __CLASS__, 459 sprintf('Снова сохранили продукт как вариативный %s', $product_id) 460 ); 461 } 462 463 if ($session_id = self::get_session_id()) { 464 $variation->update_meta_data('wooms_session_id', $session_id); 465 } 56 466 57 467 /** 58 * Walker for data variant product from MoySklad468 * deprecated 59 469 */ 60 public static function batch_handler($args = []) 61 { 62 63 $state = self::get_state(); 64 65 if (!empty($state['lock'])) { 66 // return; // блокировка состояни гонки 67 } 68 69 // dd($state); 70 71 self::set_state('lock', 1); 72 73 //reset state if new session 74 if (empty($state['timestamp'])) { 75 76 self::set_state('timestamp', date("YmdHis")); 77 self::set_state('end_timestamp', 0); 78 self::set_state('count', 0); 79 80 $query_arg_default = [ 81 'offset' => 0, 82 'limit' => apply_filters('wooms_variant_iteration_size', 30), 83 ]; 84 85 self::set_state('query_arg', $query_arg_default); 86 } 87 88 89 $query_arg = self::get_state('query_arg'); 90 91 /** 92 * issue https://github.com/wpcraft-ru/wooms/issues/296 93 */ 94 $url = 'https://online.moysklad.ru/api/remap/1.2/entity/variant'; 95 96 $url = add_query_arg($query_arg, $url); 97 98 $filters = [ 99 // 'productid=4dc138a7-d532-11e7-7a69-8f55000890d1', 100 // 'productid=2d0310cd-9194-11e7-7a6c-d2a9002dc49e', 101 ]; 102 103 $filters = apply_filters('wooms_url_get_variants_filter', $filters); 104 105 $url = add_query_arg('filter', implode(';', $filters), $url); 106 107 $url = apply_filters('wooms_url_get_variants', $url); 108 109 try { 110 111 do_action( 112 'wooms_logger', 113 __CLASS__, 114 sprintf('Вариации. Отправлен запрос: %s', $url), 115 $state 116 ); 117 118 $data = wooms_request($url); 119 120 //Check for errors and send message to UI 121 if (isset($data['errors'][0]["error"])) { 122 throw new \Exception($data['errors'][0]["error"]); 123 } 124 125 //If no rows, that send 'end' and stop walker 126 if (isset($data['rows']) && empty($data['rows'])) { 127 128 self::set_state('lock', 0); 129 self::walker_finish(); 130 return true; 131 } 132 133 $i = 0; 134 foreach ($data['rows'] as $key => $item) { 135 136 if ($item["meta"]["type"] != 'variant') { 137 continue; 138 } 139 140 $i++; 141 142 do_action('wooms_products_variations_item', $item); 143 144 /** 145 * deprecated 146 */ 147 do_action('wooms_product_variant_import_row', $item, $key, $data); 148 } 149 150 //update count 151 self::set_state('count', self::get_state('count') + $i); 152 153 //update offset 154 $query_arg['offset'] = $query_arg['offset'] + count($data['rows']); 155 156 self::set_state('query_arg', $query_arg); 157 158 self::set_state('lock', 0); 159 160 self::add_schedule_hook(true); 161 162 do_action('wooms_variations_batch_end'); 163 164 return true; 165 } catch (\Exception $e) { 166 self::set_state('lock', 0); 167 do_action( 168 'wooms_logger_error', 169 __CLASS__, 170 $e->getMessage() 171 ); 172 return false; 173 } 174 } 175 176 177 /** 178 * If started main walker - set wait 179 */ 180 public static function set_wait() 181 { 182 as_unschedule_all_actions(self::$walker_hook_name); 183 self::set_state('end_timestamp', time()); 184 } 185 186 187 /** 188 * Resetting state after completing the main walker 189 * And restart schedules for sync variations 190 */ 191 public static function reset_after_main_walker_finish() 192 { 193 self::set_state('timestamp', 0); 194 self::set_state('count', 0); 195 self::set_state('lock', 0); 196 self::set_state('end_timestamp', 0); 197 self::add_schedule_hook(); 198 } 199 200 201 /** 202 * Set attributes for variables 203 */ 204 public static function set_product_attributes_for_variation($product_id, $data_api) 205 { 206 $product = wc_get_product($product_id); 207 208 $ms_attributes = []; 209 foreach ($data_api['characteristics'] as $key => $characteristic) { 210 211 $attribute_label = $characteristic["name"]; 212 213 $ms_attributes[$attribute_label] = [ 214 'name' => $characteristic["name"], 215 'values' => [], 216 ]; 217 } 218 219 $values = array(); 220 foreach ($data_api['characteristics'] as $key => $characteristic) { 221 $attribute_label = $characteristic["name"]; 222 223 if ($attribute_taxonomy_id = self::get_attribute_id_by_label($characteristic['name'])) { 224 $taxonomy_name = wc_attribute_taxonomy_name_by_id((int) $attribute_taxonomy_id); 225 $current_values = $product->get_attribute($taxonomy_name); 226 227 if ($current_values) { 228 $current_values = explode(', ', $current_values); 229 $current_values = array_map('trim', $current_values); 230 } 231 } else { 232 $current_values = $product->get_attribute($characteristic['name']); 233 $current_values = explode(' | ', $current_values); 234 } 235 236 if (empty($current_values)) { 237 $values[] = $characteristic['value']; 238 } else { 239 $values = $current_values; 240 $values[] = $characteristic['value']; 241 } 242 243 $values = apply_filters( 244 'wooms_product_attribute_save_values', 245 $values, 246 $product, 247 $characteristic 248 ); 249 $ms_attributes[$attribute_label]['values'] = $values; 250 } 251 252 /** 253 * check unique for values 254 */ 255 foreach ($ms_attributes as $key => $value) { 256 $ms_attributes[$key]['values'] = array_unique($value['values']); 257 } 258 259 $attributes = $product->get_attributes('edit'); 260 261 if (empty($attributes)) { 262 $attributes = array(); 263 } 264 265 foreach ($ms_attributes as $key => $value) { 266 $attribute_taxonomy_id = self::get_attribute_id_by_label($value['name']); 267 $attribute_slug = sanitize_title($value['name']); 268 269 if (empty($attribute_taxonomy_id)) { 270 $attribute_object = new \WC_Product_Attribute(); 271 $attribute_object->set_name($value['name']); 272 $attribute_object->set_options($value['values']); 273 $attribute_object->set_position(0); 274 $attribute_object->set_visible(0); 275 $attribute_object->set_variation(1); 276 $attributes[$attribute_slug] = $attribute_object; 277 } else { 278 //Очищаем индивидуальный атрибут с таким именем если есть 279 if (isset($attributes[$attribute_slug])) { 280 unset($attributes[$attribute_slug]); 281 } 282 $taxonomy_name = wc_attribute_taxonomy_name_by_id((int) $attribute_taxonomy_id); 283 $attribute_object = new \WC_Product_Attribute(); 284 $attribute_object->set_id($attribute_taxonomy_id); 285 $attribute_object->set_name($taxonomy_name); 286 $attribute_object->set_options($value['values']); 287 $attribute_object->set_position(0); 288 $attribute_object->set_visible(0); 289 $attribute_object->set_variation(1); 290 $attributes[$taxonomy_name] = $attribute_object; 291 } 292 } 293 294 $attributes = apply_filters('wooms_product_attributes', $attributes, $data_api, $product); 295 296 $product->set_attributes($attributes); 297 298 $product->save(); 299 300 do_action( 301 'wooms_logger', 302 __CLASS__, 303 sprintf( 304 'Сохранены атрибуты для продукта: %s (%s)', 305 $product->get_name(), 306 $product_id 307 ), 308 $attributes 309 ); 310 } 311 312 313 /** 314 * Set attributes and value for variation 315 * 316 * @param $variation_id 317 * @param $characteristics 318 */ 319 public static function save_attributes_for_variation(\WC_Product_Variation $variation, $data_api, $product_id) 320 { 321 $variant_data = $data_api; 322 323 $variation_id = $variation->get_id(); 324 $parent_id = $variation->get_parent_id(); 325 326 $characteristics = $variant_data['characteristics']; 327 328 $attributes = array(); 329 330 foreach ($characteristics as $key => $characteristic) { 331 $attribute_label = $characteristic["name"]; 332 $attribute_slug = sanitize_title($attribute_label); 333 334 if ($attribute_taxonomy_id = self::get_attribute_id_by_label($attribute_label)) { 335 $taxonomy_name = wc_attribute_taxonomy_name_by_id($attribute_taxonomy_id); 336 if (isset($attributes[$attribute_slug])) { 337 unset($attributes[$attribute_slug]); 338 } 339 340 $attribute_value = $characteristic['value']; 341 342 $term = get_term_by('name', $attribute_value, $taxonomy_name); 343 344 if ($term && !is_wp_error($term)) { 345 $attribute_value = $term->slug; 346 } else { 347 $attribute_value = sanitize_title($attribute_value); 348 } 349 350 $attributes[$taxonomy_name] = $attribute_value; 351 } else { 352 $attributes[$attribute_slug] = $characteristic['value']; 353 } 354 } 355 356 $attributes = apply_filters('wooms_variation_attributes', $attributes, $data_api, $variation); 357 358 $variation->set_attributes($attributes); 359 360 do_action( 361 'wooms_logger', 362 __CLASS__, 363 sprintf('Сохранены атрибуты для вариации %s (продукт: %s)', $variation_id, $product_id), 364 wc_print_r($attributes, true) 365 ); 366 367 return $variation; 368 } 369 370 371 /** 372 * Installation of variations for variable product 373 */ 374 public static function load_data_variant($variant) 375 { 376 if (!empty($variant['archived'])) { 377 return; 378 } 379 380 $product_href = $variant['product']['meta']['href']; 381 $product_id = self::get_product_id_by_uuid($product_href); 382 383 if (empty($product_id)) { 384 385 /** 386 * придумать подход при котором вариации будут фильтроваться с учетом уже доступных продуктов на сайте 387 * до этого момента, эта ошибка будет возникать постоянно 388 */ 389 do_action( 390 'wooms_logger_error', 391 __CLASS__, 392 sprintf('Ошибка получения product_id для url %s', $product_href), 393 $variant 394 ); 395 396 return; 397 } 398 399 400 self::update_variant_for_product($product_id, $variant); 401 402 /** 403 * deprecated 404 */ 405 do_action('wooms_product_variant', $product_id, $variant); 406 } 407 408 409 /** 410 * Get product variant ID 411 * 412 * @param $uuid 413 */ 414 public static function get_product_id_by_uuid($uuid) 415 { 416 if (strpos($uuid, 'http') !== false) { 417 $uuid = str_replace('https://online.moysklad.ru/api/remap/1.1/entity/product/', '', $uuid); 418 $uuid = str_replace('https://online.moysklad.ru/api/remap/1.2/entity/product/', '', $uuid); 419 } 420 421 $posts = get_posts('post_type=product&meta_key=wooms_id&meta_value=' . $uuid); 422 if (empty($posts[0]->ID)) { 423 return false; 424 } 425 426 return $posts[0]->ID; 427 } 428 429 430 /** 431 * Update and add variables from product 432 * 433 * @param $product_id 434 * @param $value 435 */ 436 public static function update_variant_for_product($product_id, $data_api) 437 { 438 $variant_data = $data_api; 439 if (empty($data_api)) { 440 return; 441 } 442 443 //добавление атрибутов к основному продукту с пометкой для вариаций 444 self::set_product_attributes_for_variation($product_id, $variant_data); 445 446 if (!$variation_id = self::get_variation_by_wooms_id($product_id, $variant_data['id'])) { 447 $variation_id = self::add_variation($product_id, $variant_data); 448 } 449 450 $variation = wc_get_product($variation_id); 451 $variation->set_name($variant_data['name']); 452 453 $variation->set_stock_status('instock'); 454 455 if (!empty($variant_data["salePrices"][0]['value'])) { 456 $price = $variant_data["salePrices"][0]['value']; 457 } else { 458 $price = 0; 459 } 460 461 // $price = apply_filters('wooms_product_price', $price, $data_api, $variation_id); 462 463 $price = floatval($price) / 100; 464 $variation->set_price($price); 465 $variation->set_regular_price($price); 466 467 do_action( 468 'wooms_logger', 469 __CLASS__, 470 sprintf('Цена %s сохранена (для вариации %s продукта %s)', $price, $variation_id, $product_id) 471 ); 472 473 $product_parent = wc_get_product($product_id); 474 if (!$product_parent->is_type('variable')) { 475 $product_parent = new \WC_Product_Variable($product_parent); 476 $product_parent->save(); 477 478 do_action( 479 'wooms_logger_error', 480 __CLASS__, 481 sprintf('Снова сохранили продукт как вариативный %s', $product_id) 482 ); 483 } 484 485 /** 486 * deprecated 487 */ 488 $variation = apply_filters('wooms_save_variation', $variation, $variant_data, $product_id); 489 490 $variation = apply_filters('wooms_variation_save', $variation, $variant_data, $product_id); 491 492 if ($session_id = get_option('wooms_session_id')) { 493 $variation->update_meta_data('wooms_session_id', $session_id); 494 } 495 496 $variation->save(); 497 498 do_action( 499 'wooms_logger', 500 __CLASS__, 501 sprintf( 502 'Сохранена вариация: %s (%s), для продукта %s (%s)', 503 $variation->get_name(), 504 $variation_id, 505 $product_parent->get_name(), 506 $product_id 507 ) 508 ); 509 510 do_action('wooms_variation_id', $variation_id, $variant_data); 511 } 512 513 514 /** 515 * Get product parent ID 516 */ 517 public static function get_variation_by_wooms_id($parent_id, $id) 518 { 519 $posts = get_posts(array( 520 'post_type' => 'product_variation', 521 'post_parent' => $parent_id, 522 'meta_key' => 'wooms_id', 523 'meta_value' => $id, 524 )); 525 526 if (empty($posts)) { 527 return false; 528 } 529 530 return $posts[0]->ID; 531 } 532 533 534 /** 535 * Add variables from product 536 */ 537 public static function add_variation($product_id, $value) 538 { 539 $variation = new \WC_Product_Variation(); 540 $variation->set_parent_id(absint($product_id)); 541 $variation->set_status('publish'); 542 $variation->set_stock_status('instock'); 543 $r = $variation->save(); 544 545 $variation_id = $variation->get_id(); 546 if (empty($variation_id)) { 547 return false; 548 } 549 550 update_post_meta($variation_id, 'wooms_id', $value['id']); 551 552 do_action('wooms_add_variation', $variation_id, $product_id, $value); 553 554 return $variation_id; 555 } 556 557 558 /** 559 * Start import manually 560 */ 561 public static function start_manually() 562 { 563 delete_transient(self::$state_transient_key); 564 self::add_schedule_hook(); 565 wp_redirect(admin_url('admin.php?page=moysklad')); 566 } 567 568 569 /** 570 * Stopping walker imports from MoySklad 571 */ 572 public static function walker_finish() 573 { 574 self::set_state('end_timestamp', time()); 575 self::set_state('lock', 0); 576 577 do_action('wooms_wakler_variations_finish'); 578 579 do_action( 580 'wooms_logger', 581 __CLASS__, 582 'Вариации. Обработчик финишировал' 583 ); 584 585 return true; 586 } 587 588 /** 589 * Stop import manually 590 */ 591 public static function stop_manually() 592 { 593 as_unschedule_all_actions(self::$walker_hook_name); 594 595 self::walker_finish(); 596 597 wp_redirect(admin_url('admin.php?page=moysklad')); 598 } 599 600 /** 601 * Get attribute id by label 602 * or false 603 */ 604 public static function get_attribute_id_by_label($label = '') 605 { 606 if (empty($label)) { 607 return false; 608 } 609 610 $attr_taxonomies = wc_get_attribute_taxonomies(); 611 if (empty($attr_taxonomies)) { 612 return false; 613 } 614 615 if (!is_array($attr_taxonomies)) { 616 return false; 617 } 618 619 foreach ($attr_taxonomies as $attr) { 620 if ($attr->attribute_label == $label) { 621 return (int) $attr->attribute_id; 622 } 623 } 624 625 return false; 626 } 627 628 629 public static function is_wait() 630 { 631 //check run main walker 632 if (as_next_scheduled_action('wooms_products_walker_batch')) { 633 return true; 634 } 635 636 //check end pause 637 if (!empty(self::get_state('end_timestamp'))) { 638 return true; 639 } 640 641 return false; 642 } 643 644 645 /** 646 * Add schedule hook 647 */ 648 public static function add_schedule_hook($force = false) 649 { 650 if (!self::is_enable()) { 651 return; 652 } 653 654 if (self::is_wait()) { 655 return; 656 } 657 658 if (as_next_scheduled_action(self::$walker_hook_name) && ! $force) { 659 return; 660 } 661 662 if ($force) { 663 self::set_state('force', 1); 664 } else { 665 self::set_state('force', 0); 666 } 667 668 // Adding schedule hook 669 as_schedule_single_action(time() + 5, self::$walker_hook_name, self::get_state(), 'WooMS'); 670 } 671 672 673 /** 674 * display_state 675 */ 676 public static function display_state() 677 { 678 679 if (!self::is_enable()) { 680 return; 681 } 682 683 echo '<h2>Вариации (Модификации)</h2>'; 684 685 echo "<p>Нажмите на кнопку ниже, чтобы запустить синхронизацию данных о вариативных товарах вручную</p>"; 686 687 if (as_next_scheduled_action(self::$walker_hook_name)) { 688 printf( 689 '<a href="%s" class="button button-secondary">Остановить синхронизацию вариативных продуктов</a>', 690 add_query_arg('a', 'wooms_import_variations_manual_stop', admin_url('admin.php?page=moysklad')) 691 ); 692 } else { 693 printf( 694 '<a href="%s" class="button button-primary">Запустить синхронизацию вариативных продуктов</a>', 695 add_query_arg('a', 'wooms_import_variations_manual_start', admin_url('admin.php?page=moysklad')) 696 ); 697 } 698 699 $strings = []; 700 701 if (as_next_scheduled_action(self::$walker_hook_name)) { 702 $strings[] = sprintf('<strong>Статус:</strong> %s', 'Выполняется очередями в фоне'); 703 } else { 704 $strings[] = sprintf('<strong>Статус:</strong> %s', 'в ожидании задач'); 705 } 706 707 if ($end_timestamp = self::get_state('end_timestamp')) { 708 $end_timestamp = date('Y-m-d H:i:s', $end_timestamp); 709 $strings[] = sprintf('Последняя успешная синхронизация (отметка времени UTC): %s', $end_timestamp); 710 } 711 712 $strings[] = sprintf('Очередь задач: <a href="%s">открыть</a>', admin_url('admin.php?page=wc-status&tab=action-scheduler&s=wooms_variables_walker_batch&orderby=schedule&order=desc')); 713 714 715 if (defined('WC_LOG_HANDLER') && 'WC_Log_Handler_DB' == WC_LOG_HANDLER) { 716 $strings[] = sprintf('Журнал обработки: <a href="%s">открыть</a>', admin_url('admin.php?page=wc-status&tab=logs&source=WooMS-ProductVariable')); 717 } else { 718 $strings[] = sprintf('Журнал обработки: <a href="%s">открыть</a>', admin_url('admin.php?page=wc-status&tab=logs')); 719 } 720 721 $strings[] = sprintf('Количество обработанных записей: %s', empty(self::get_state('count')) ? 0 : self::get_state('count')); 470 $variation = apply_filters('wooms_save_variation', $variation, $variant_data, $product_id); 471 472 $variation = apply_filters('wooms_variation_save', $variation, $variant_data, $product_id); 473 474 $variation->save(); 475 476 do_action( 477 'wooms_logger', 478 __CLASS__, 479 sprintf( 480 'Сохранена вариация: %s (%s), для продукта %s (%s)', 481 $variation->get_name(), 482 $variation_id, 483 $product_parent->get_name(), 484 $product_id 485 ) 486 ); 487 488 do_action('wooms_variation_id', $variation_id, $variant_data); 489 } 490 491 public static function get_session_id(){ 492 return \WooMS\Products\get_session_id(); 493 } 494 /** 495 * Get product parent ID 496 */ 497 public static function get_variation_by_wooms_id($parent_id, $id) 498 { 499 $posts = get_posts( 500 array( 501 'post_type' => 'product_variation', 502 'post_parent' => $parent_id, 503 'meta_key' => 'wooms_id', 504 'meta_value' => $id, 505 ) 506 ); 507 508 if (empty($posts)) { 509 return false; 510 } 511 512 return $posts[0]->ID; 513 } 514 515 516 /** 517 * Add variables from product 518 */ 519 public static function add_variation($product_id, $value) 520 { 521 $variation = new \WC_Product_Variation(); 522 $variation->set_parent_id(absint($product_id)); 523 $variation->set_status('publish'); 524 $variation->set_stock_status('instock'); 525 $r = $variation->save(); 526 527 $variation_id = $variation->get_id(); 528 if (empty($variation_id)) { 529 return false; 530 } 531 532 update_post_meta($variation_id, 'wooms_id', $value['id']); 533 534 do_action('wooms_add_variation', $variation_id, $product_id, $value); 535 536 return $variation_id; 537 } 538 539 540 /** 541 * Start import manually 542 */ 543 public static function start_manually() 544 { 545 as_schedule_single_action(time() + 5, self::$walker_hook_name, [], 'WooMS'); 546 wp_redirect(admin_url('admin.php?page=moysklad')); 547 } 548 549 550 /** 551 * Stopping walker imports from MoySklad 552 */ 553 public static function walker_finish() 554 { 555 self::set_state('end_timestamp', time()); 556 self::set_state('lock', 0); 557 558 do_action('wooms_wakler_variations_finish'); 559 560 do_action( 561 'wooms_logger', 562 __CLASS__, 563 'Вариации. Обработчик финишировал' 564 ); 565 566 return true; 567 } 568 569 /** 570 * Stop import manually 571 */ 572 public static function stop_manually() 573 { 574 as_unschedule_all_actions(self::$walker_hook_name); 575 576 self::walker_finish(); 577 578 wp_redirect(admin_url('admin.php?page=moysklad')); 579 } 580 581 /** 582 * Get attribute id by label 583 * or false 584 */ 585 public static function get_attribute_id_by_label($label = '') 586 { 587 if (empty($label)) { 588 return false; 589 } 590 591 $attr_taxonomies = wc_get_attribute_taxonomies(); 592 if (empty($attr_taxonomies)) { 593 return false; 594 } 595 596 if (!is_array($attr_taxonomies)) { 597 return false; 598 } 599 600 foreach ($attr_taxonomies as $attr) { 601 if ($attr->attribute_label == $label) { 602 return (int) $attr->attribute_id; 603 } 604 } 605 606 return false; 607 } 608 609 610 public static function is_wait() 611 { 612 //check run main walker 613 if (as_next_scheduled_action('wooms_products_walker_batch')) { 614 return true; 615 } 616 617 //check end pause 618 if (!empty(self::get_state('end_timestamp'))) { 619 return true; 620 } 621 622 return false; 623 } 624 625 626 627 /** 628 * display_state 629 */ 630 public static function display_state() 631 { 632 633 if (!self::is_enable()) { 634 return; 635 } 636 637 echo '<h2>Вариации и Модификации</h2>'; 638 639 if (as_next_scheduled_action(self::$walker_hook_name)) { 640 printf( 641 '<a href="%s" class="button button-secondary">Остановить синхронизацию вариативных продуктов</a>', 642 add_query_arg('a', 'wooms_import_variations_manual_stop', admin_url('admin.php?page=moysklad')) 643 ); 644 } else { 645 printf( 646 '<a href="%s" class="button button-primary">Запустить синхронизацию вариативных продуктов</a>', 647 add_query_arg('a', 'wooms_import_variations_manual_start', admin_url('admin.php?page=moysklad')) 648 ); 649 } 650 651 $strings = []; 652 653 if (as_next_scheduled_action(self::$walker_hook_name)) { 654 $strings[] = sprintf('<strong>Статус:</strong> %s', 'Выполняется очередями в фоне'); 655 656 } else { 657 $strings[] = sprintf('<strong>Статус:</strong> %s', 'в ожидании задач'); 658 $strings[] = sprintf('Последняя успешная синхронизация: %s', wooms_get_timestamp_last_job_by_hook(self::$walker_hook_name)); 659 } 660 661 662 $strings[] = sprintf('Очередь задач: <a href="%s">открыть</a>', admin_url('admin.php?page=wc-status&tab=action-scheduler&s=wooms_variables_walker_batch&orderby=schedule&order=desc')); 663 664 665 if (defined('WC_LOG_HANDLER') && 'WC_Log_Handler_DB' == WC_LOG_HANDLER) { 666 $strings[] = sprintf('Журнал обработки: <a href="%s">открыть</a>', admin_url('admin.php?page=wc-status&tab=logs&source=WooMS-ProductVariable')); 667 } else { 668 $strings[] = sprintf('Журнал обработки: <a href="%s">открыть</a>', admin_url('admin.php?page=wc-status&tab=logs')); 669 } 670 671 $strings[] = sprintf('Количество обработанных записей: %s', empty(self::get_state('count')) ? 0 : self::get_state('count')); 722 672 723 673 ?> 724 <div class="wrap"> 725 <div id="message" class="notice notice-warning"> 726 <?php 727 foreach ($strings as $string) { 728 printf('<p>%s</p>', $string); 729 } 730 ?> 731 </div> 732 </div> 674 <div> 675 <?php 676 foreach ($strings as $string) { 677 printf('<p>%s</p>', $string); 678 } 679 ?> 680 </div> 733 681 <?php 734 } 735 736 737 /** 738 * Settings import variations 739 */ 740 public static function add_settings() 741 { 742 $option_name = 'woomss_variations_sync_enabled'; 743 register_setting('mss-settings', $option_name); 744 add_settings_field( 745 $id = $option_name, 746 $title = 'Включить синхронизацию вариаций', 747 $callback = function ($args) { 748 printf('<input type="checkbox" name="%s" value="1" %s />', $args['name'], checked(1, $args['value'], false)); 749 printf('<p><strong>%s</strong></p>', 'Тестовый режим. Не включайте эту функцию на реальном сайте, пока не проверите ее на тестовой копии сайта.'); 750 }, 751 $page = 'mss-settings', 752 $section = 'woomss_section_other', 753 $args = [ 754 'name' => $option_name, 755 'value' => get_option($option_name), 756 ] 757 ); 758 } 759 760 761 /** 762 * Получаем данные таксономии по id глобального артибута 763 */ 764 public static function get_attribute_taxonomy_by_id($id = 0) 765 { 766 767 if (empty($id)) { 768 return false; 769 } 770 771 $taxonomy = null; 772 $attribute_taxonomies = wc_get_attribute_taxonomies(); 773 774 foreach ($attribute_taxonomies as $key => $tax) { 775 if ($id == $tax->attribute_id) { 776 $taxonomy = $tax; 777 $taxonomy->slug = 'pa_' . $tax->attribute_name; 778 779 break; 780 } 781 } 782 783 return $taxonomy; 784 } 785 786 787 /** 788 * checking is enable 789 */ 790 public static function is_enable() 791 { 792 if (empty(get_option('woomss_variations_sync_enabled'))) { 793 return false; 794 } 795 796 return true; 797 } 798 799 800 /** 801 * Update product from source data 802 */ 803 public static function update_product($product, $data_api) 804 { 805 $item = $data_api; 806 807 if (!self::is_enable()) { 808 if ($product->is_type('variable')) { 809 $product = new \WC_Product_Simple($product); 810 } 811 812 return $product; 813 } 814 815 if (empty($item['variantsCount'])) { 816 if ($product->is_type('variable')) { 817 $product = new \WC_Product_Simple($product); 818 } 819 820 return $product; 821 } 822 823 $product_id = $product->get_id(); 824 825 if (!$product->is_type('variable')) { 826 $product = new \WC_Product_Variable($product); 827 828 do_action( 829 'wooms_logger', 830 __CLASS__, 831 sprintf('Продукт изменен как вариативный %s', $product_id) 832 ); 833 } 834 835 return $product; 836 } 837 838 839 840 /** 841 * get state data 842 */ 843 public static function get_state($key = '') 844 { 845 if (!$state = get_transient(self::$state_transient_key)) { 846 $state = []; 847 set_transient(self::$state_transient_key, $state); 848 } 849 850 if (empty($key)) { 851 return $state; 852 } 853 854 if (empty($state[$key])) { 855 return null; 856 } 857 858 return $state[$key]; 859 } 860 861 /** 862 * set state data 863 */ 864 public static function set_state($key, $value) 865 { 866 867 if (!$state = get_transient(self::$state_transient_key)) { 868 $state = []; 869 } 870 871 if (is_array($state)) { 872 $state[$key] = $value; 873 } else { 874 $state = []; 875 $state[$key] = $value; 876 } 877 878 set_transient(self::$state_transient_key, $state); 879 } 880 881 /** 882 * show wooms_id for variation in admin 883 */ 884 public static function variation_sync_id($variation) { 885 $wooms_id = get_post_meta($variation->ID, 'wooms_id', true); 886 if ($wooms_id) { 887 echo 'wooms_id: ' . $wooms_id; 888 } 889 } 682 } 683 684 685 /** 686 * Settings import variations 687 */ 688 public static function add_settings() 689 { 690 $option_name = 'woomss_variations_sync_enabled'; 691 register_setting('mss-settings', $option_name); 692 add_settings_field( 693 $id = $option_name, 694 $title = 'Вариации и модификации', 695 $callback = function ($args) { 696 printf('<input type="checkbox" name="%s" value="1" %s />', $args['name'], checked(1, $args['value'], false)); 697 printf('<p><strong>%s</strong></p>', 'Синхронизация модификаций продуктов из МойСклад на Сайт'); 698 }, 699 $page = 'mss-settings', 700 $section = 'woomss_section_other', 701 $args = [ 702 'name' => $option_name, 703 'value' => get_option($option_name), 704 ] 705 ); 706 } 707 708 709 /** 710 * Получаем данные таксономии по id глобального артибута 711 */ 712 public static function get_attribute_taxonomy_by_id($id = 0) 713 { 714 715 if (empty($id)) { 716 return false; 717 } 718 719 $taxonomy = null; 720 $attribute_taxonomies = wc_get_attribute_taxonomies(); 721 722 foreach ($attribute_taxonomies as $key => $tax) { 723 if ($id == $tax->attribute_id) { 724 $taxonomy = $tax; 725 $taxonomy->slug = 'pa_' . $tax->attribute_name; 726 727 break; 728 } 729 } 730 731 return $taxonomy; 732 } 733 734 735 /** 736 * checking is enable 737 */ 738 public static function is_enable() 739 { 740 if (empty(get_option('woomss_variations_sync_enabled'))) { 741 return false; 742 } 743 744 return true; 745 } 746 747 748 /** 749 * Update product from source data 750 */ 751 public static function update_product($product, $data_api) 752 { 753 $item = $data_api; 754 755 if (!self::is_enable()) { 756 if ($product->is_type('variable')) { 757 $product = new \WC_Product_Simple($product); 758 } 759 760 return $product; 761 } 762 763 if (empty($item['variantsCount'])) { 764 if ($product->is_type('variable')) { 765 $product = new \WC_Product_Simple($product); 766 } 767 768 return $product; 769 } 770 771 $product_id = $product->get_id(); 772 773 if (!$product->is_type('variable')) { 774 $product = new \WC_Product_Variable($product); 775 776 do_action( 777 'wooms_logger', 778 __CLASS__, 779 sprintf('Продукт изменен как вариативный %s', $product_id) 780 ); 781 } 782 783 return $product; 784 } 785 786 787 788 /** 789 * get state data 790 */ 791 public static function get_state($key = '') 792 { 793 if (!$state = get_option(self::$state_transient_key)) { 794 $state = []; 795 update_option(self::$state_transient_key, $state); 796 } 797 798 if (empty($key)) { 799 return $state; 800 } 801 802 if (empty($state[$key])) { 803 return null; 804 } 805 806 return $state[$key]; 807 } 808 809 /** 810 * set state data 811 */ 812 public static function set_state($key, $value = null) 813 { 814 if ($value === null && is_array($key)) { 815 update_option(self::$state_transient_key, $key, false); 816 return; 817 } 818 819 if (!$state = get_option(self::$state_transient_key)) { 820 $state = []; 821 } 822 823 if (is_array($state)) { 824 $state[$key] = $value; 825 } else { 826 $state = []; 827 $state[$key] = $value; 828 } 829 830 update_option(self::$state_transient_key, $state, false); 831 } 832 833 /** 834 * show wooms_id for variation in admin 835 */ 836 public static function variation_sync_id($variation) 837 { 838 $wooms_id = get_post_meta($variation->ID, 'wooms_id', true); 839 if ($wooms_id) { 840 echo 'wooms_id: ' . $wooms_id; 841 } 842 } 890 843 } 891 844 -
wooms/trunk/includes/Products.php
r2826440 r2826597 97 97 */ 98 98 set_state('session_id', null); 99 100 //backwards compatible - to delete101 delete_option('wooms_session_id');102 99 103 100 do_action('wooms_logger_error', __NAMESPACE__, 'Главный обработчик завершился с ошибкой... ' . $e->getMessage()); … … 163 160 * issue https://github.com/wpcraft-ru/wooms/issues/305 164 161 */ 165 // delete_option('wooms_session_id');166 162 set_state('session_id', null); 167 163 … … 170 166 } 171 167 168 function get_session_id(){ 169 return get_state('session_id'); 170 } 171 172 172 /** 173 173 * Update product from source data … … 176 176 { 177 177 $data_of_source = $data_api; 178 $product_id = $product->get_id();179 178 180 179 //Set session id for product … … 460 459 { 461 460 462 // backward compatibility - need delete after all updates463 // update_option('wooms_session_id', $now, 'no'); //set id session sync464 465 461 $batch_size = get_option('wooms_batch_size', 20); 466 462 $query_arg_default = [ -
wooms/trunk/includes/ProductsHiding.php
r2826440 r2826597 44 44 45 45 if ($product->get_type() == 'variable') { 46 $product->set_manage_stock('yes');46 // $product->set_manage_stock('yes'); 47 47 } 48 48 … … 103 103 104 104 $args = array( 105 'post_type' => 'product',105 'post_type' => ['product', 'product_variation'], 106 106 'numberposts' => 30, 107 107 'fields' => 'ids', -
wooms/trunk/includes/ProductsServices.php
r2826440 r2826597 16 16 /** 17 17 * Save state in DB 18 * 18 * 19 19 * @var string 20 20 */ … … 139 139 self::set_state('count', self::get_state('count') + $i); 140 140 141 //update offset 141 //update offset 142 142 $query_arg['offset'] = $query_arg['offset'] + count($data['rows']); 143 143 … … 258 258 /** 259 259 * update_product 260 * 261 * @param \WC_Product $product 262 * @param array $api_data 260 263 */ 261 264 public static function update_product($product, $api_data) -
wooms/trunk/readme.txt
r2826440 r2826597 80 80 81 81 == Changelog == 82 83 = 9.0.1 = 84 - исправлена ошибка синхронизации вариаций 82 85 83 86 = 9.0 = -
wooms/trunk/wooms.php
r2826440 r2826597 20 20 * WC tested up to: 7.1 21 21 * 22 * Version: 9.0 22 * Version: 9.0.1 23 23 */ 24 24
Note: See TracChangeset
for help on using the changeset viewer.