Plugin Directory

Changeset 2826597


Ignore:
Timestamp:
11/30/2022 03:52:25 PM (3 years ago)
Author:
casepress
Message:

Update to version 9.0.1 from GitHub

Location:
wooms
Files:
2 deleted
16 edited
1 copied

Legend:

Unmodified
Added
Removed
  • wooms/tags/9.0.1/includes/OrderNumber.php

    r2826440 r2826597  
    77/**
    88 * Get and save order number from MoySklad
    9  * 
     9 *
    1010 * issue https://github.com/wpcraft-ru/wooms/issues/319
    1111 */
     
    1919        add_filter('wooms_update_order_from_moysklad', array(__CLASS__, 'set_order_number'), 10, 2);
    2020
    21         add_action('admin_init', array(__CLASS__, 'add_settings'), 50);
     21        add_action('admin_init', array(__CLASS__, 'add_settings'), 30);
    2222        add_action('pre_get_posts', array(__CLASS__, 'search_by_number_from_moysklad'));
    2323    }
     
    2525    /**
    2626     * set_order_number
    27      * 
     27     *
    2828     * use hook $order = apply_filters('wooms_order_update', $order, $result);
    2929     */
     
    5656
    5757    /**
    58      * 
     58     *
    5959     * use hook $data = apply_filters('wooms_order_data', $data, $order_id);
    6060     */
     
    147147    /**
    148148     *  Если используются номера заказов из Мой Склад, чиним поиску по номеру заказа
    149      * 
     149     *
    150150     *  issue https://github.com/wpcraft-ru/wooms/issues/331
    151151     */
     
    167167            return;
    168168        }
    169        
     169
    170170        $custom_order_id = $query->query['s'];
    171171        $query->query_vars['post__in']=array();
  • wooms/tags/9.0.1/includes/Orders.php

    r2826440 r2826597  
    6060        add_action('wooms_order_metabox_controls', array(__CLASS__, 'add_controle_for_sync'));
    6161
    62         add_action('admin_init', array(__CLASS__, 'add_settings'), 40);
     62        add_action('admin_init', array(__CLASS__, 'add_settings'), 10);
    6363
    6464        add_action( 'woocommerce_order_item_meta_start', function () {
     
    449449        if (empty($result['id']) || !isset($result['id']) || isset($result['errors'])) {
    450450            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' );
    454452
    455453            do_action(
  • wooms/tags/9.0.1/includes/ProductVariable.php

    r2826440 r2826597  
    1111class ProductVariable
    1212{
     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
    1375    /**
    14      * Save state in DB
    15      *
    16      * @var string
     76     * issue https://github.com/wpcraft-ru/wooms/issues/296
    1777     */
    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    }
    19228
    20229    /**
    21      * Hookd and key for ActionSheduler
    22      *
    23      * @var string
     230     * check unique for values
    24231     */
    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);
    27378
    28379    /**
    29      * The init
     380     * deprecated
    30381     */
    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    }
    56466
    57467    /**
    58      * Walker for data variant product from MoySklad
     468     * deprecated
    59469     */
    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'));
    722672
    723673?>
    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>
    733681<?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  }
    890843}
    891844
  • wooms/tags/9.0.1/includes/Products.php

    r2826440 r2826597  
    9797     */
    9898    set_state('session_id', null);
    99 
    100     //backwards compatible - to delete
    101     delete_option('wooms_session_id');
    10299
    103100    do_action('wooms_logger_error', __NAMESPACE__, 'Главный обработчик завершился с ошибкой... ' . $e->getMessage());
     
    163160   * issue https://github.com/wpcraft-ru/wooms/issues/305
    164161   */
    165   // delete_option('wooms_session_id');
    166162  set_state('session_id', null);
    167163
     
    170166}
    171167
     168function get_session_id(){
     169  return get_state('session_id');
     170}
     171
    172172/**
    173173 * Update product from source data
     
    176176{
    177177  $data_of_source = $data_api;
    178   $product_id = $product->get_id();
    179178
    180179  //Set session id for product
     
    460459{
    461460
    462   // backward compatibility - need delete after all updates
    463   // update_option('wooms_session_id', $now, 'no'); //set id session sync
    464 
    465461  $batch_size = get_option('wooms_batch_size', 20);
    466462  $query_arg_default = [
  • wooms/tags/9.0.1/includes/ProductsHiding.php

    r2826440 r2826597  
    4444
    4545    if ($product->get_type() == 'variable') {
    46       $product->set_manage_stock('yes');
     46      // $product->set_manage_stock('yes');
    4747    }
    4848
     
    103103
    104104  $args = array(
    105     'post_type' => 'product',
     105    'post_type' => ['product', 'product_variation'],
    106106    'numberposts' => 30,
    107107    'fields' => 'ids',
  • wooms/tags/9.0.1/includes/ProductsServices.php

    r2826440 r2826597  
    1616    /**
    1717     * Save state in DB
    18      * 
     18     *
    1919     * @var string
    2020     */
     
    139139            self::set_state('count', self::get_state('count') + $i);
    140140
    141             //update offset 
     141            //update offset
    142142            $query_arg['offset'] = $query_arg['offset'] + count($data['rows']);
    143143
     
    258258    /**
    259259     * update_product
     260     *
     261     * @param \WC_Product $product
     262     * @param array $api_data
    260263     */
    261264    public static function update_product($product, $api_data)
  • wooms/tags/9.0.1/readme.txt

    r2826440 r2826597  
    8080
    8181== Changelog ==
     82
     83= 9.0.1 =
     84- исправлена ошибка синхронизации вариаций
    8285
    8386= 9.0 =
  • wooms/tags/9.0.1/wooms.php

    r2826440 r2826597  
    2020 * WC tested up to: 7.1
    2121 *
    22  * Version: 9.0
     22 * Version: 9.0.1
    2323 */
    2424
  • wooms/trunk/includes/OrderNumber.php

    r2826440 r2826597  
    77/**
    88 * Get and save order number from MoySklad
    9  * 
     9 *
    1010 * issue https://github.com/wpcraft-ru/wooms/issues/319
    1111 */
     
    1919        add_filter('wooms_update_order_from_moysklad', array(__CLASS__, 'set_order_number'), 10, 2);
    2020
    21         add_action('admin_init', array(__CLASS__, 'add_settings'), 50);
     21        add_action('admin_init', array(__CLASS__, 'add_settings'), 30);
    2222        add_action('pre_get_posts', array(__CLASS__, 'search_by_number_from_moysklad'));
    2323    }
     
    2525    /**
    2626     * set_order_number
    27      * 
     27     *
    2828     * use hook $order = apply_filters('wooms_order_update', $order, $result);
    2929     */
     
    5656
    5757    /**
    58      * 
     58     *
    5959     * use hook $data = apply_filters('wooms_order_data', $data, $order_id);
    6060     */
     
    147147    /**
    148148     *  Если используются номера заказов из Мой Склад, чиним поиску по номеру заказа
    149      * 
     149     *
    150150     *  issue https://github.com/wpcraft-ru/wooms/issues/331
    151151     */
     
    167167            return;
    168168        }
    169        
     169
    170170        $custom_order_id = $query->query['s'];
    171171        $query->query_vars['post__in']=array();
  • wooms/trunk/includes/Orders.php

    r2826440 r2826597  
    6060        add_action('wooms_order_metabox_controls', array(__CLASS__, 'add_controle_for_sync'));
    6161
    62         add_action('admin_init', array(__CLASS__, 'add_settings'), 40);
     62        add_action('admin_init', array(__CLASS__, 'add_settings'), 10);
    6363
    6464        add_action( 'woocommerce_order_item_meta_start', function () {
     
    449449        if (empty($result['id']) || !isset($result['id']) || isset($result['errors'])) {
    450450            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' );
    454452
    455453            do_action(
  • wooms/trunk/includes/ProductVariable.php

    r2826440 r2826597  
    1111class ProductVariable
    1212{
     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
    1375    /**
    14      * Save state in DB
    15      *
    16      * @var string
     76     * issue https://github.com/wpcraft-ru/wooms/issues/296
    1777     */
    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    }
    19228
    20229    /**
    21      * Hookd and key for ActionSheduler
    22      *
    23      * @var string
     230     * check unique for values
    24231     */
    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);
    27378
    28379    /**
    29      * The init
     380     * deprecated
    30381     */
    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    }
    56466
    57467    /**
    58      * Walker for data variant product from MoySklad
     468     * deprecated
    59469     */
    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'));
    722672
    723673?>
    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>
    733681<?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  }
    890843}
    891844
  • wooms/trunk/includes/Products.php

    r2826440 r2826597  
    9797     */
    9898    set_state('session_id', null);
    99 
    100     //backwards compatible - to delete
    101     delete_option('wooms_session_id');
    10299
    103100    do_action('wooms_logger_error', __NAMESPACE__, 'Главный обработчик завершился с ошибкой... ' . $e->getMessage());
     
    163160   * issue https://github.com/wpcraft-ru/wooms/issues/305
    164161   */
    165   // delete_option('wooms_session_id');
    166162  set_state('session_id', null);
    167163
     
    170166}
    171167
     168function get_session_id(){
     169  return get_state('session_id');
     170}
     171
    172172/**
    173173 * Update product from source data
     
    176176{
    177177  $data_of_source = $data_api;
    178   $product_id = $product->get_id();
    179178
    180179  //Set session id for product
     
    460459{
    461460
    462   // backward compatibility - need delete after all updates
    463   // update_option('wooms_session_id', $now, 'no'); //set id session sync
    464 
    465461  $batch_size = get_option('wooms_batch_size', 20);
    466462  $query_arg_default = [
  • wooms/trunk/includes/ProductsHiding.php

    r2826440 r2826597  
    4444
    4545    if ($product->get_type() == 'variable') {
    46       $product->set_manage_stock('yes');
     46      // $product->set_manage_stock('yes');
    4747    }
    4848
     
    103103
    104104  $args = array(
    105     'post_type' => 'product',
     105    'post_type' => ['product', 'product_variation'],
    106106    'numberposts' => 30,
    107107    'fields' => 'ids',
  • wooms/trunk/includes/ProductsServices.php

    r2826440 r2826597  
    1616    /**
    1717     * Save state in DB
    18      * 
     18     *
    1919     * @var string
    2020     */
     
    139139            self::set_state('count', self::get_state('count') + $i);
    140140
    141             //update offset 
     141            //update offset
    142142            $query_arg['offset'] = $query_arg['offset'] + count($data['rows']);
    143143
     
    258258    /**
    259259     * update_product
     260     *
     261     * @param \WC_Product $product
     262     * @param array $api_data
    260263     */
    261264    public static function update_product($product, $api_data)
  • wooms/trunk/readme.txt

    r2826440 r2826597  
    8080
    8181== Changelog ==
     82
     83= 9.0.1 =
     84- исправлена ошибка синхронизации вариаций
    8285
    8386= 9.0 =
  • wooms/trunk/wooms.php

    r2826440 r2826597  
    2020 * WC tested up to: 7.1
    2121 *
    22  * Version: 9.0
     22 * Version: 9.0.1
    2323 */
    2424
Note: See TracChangeset for help on using the changeset viewer.