From 0efa62d67fc9ac326c4639c9586da4acd352ed0c Mon Sep 17 00:00:00 2001 From: Antony I <1852897+uptimizt@users.noreply.github.com> Date: Sun, 31 Mar 2024 19:34:15 +0300 Subject: [PATCH] release 9.11 (#535) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * Несовместим с включенной функцией WooCommerce #539 * readme and wf gh * Bug: Не синхронизируются товары #524 * log data for sync stock * updates ProductStocks * add Helper trait * Helper remake as class * clean code * improved ProductStocks * improved ProductStocks * improved reports * added wooms_updated_timestamp to product widget * logger * small fixes * small fixes * remove deprecated hook filter - wooms_product_save * small fixes * улучшен лог - Сохранены атрибуты для вариации * small fixes * code clean * add Settings - get_config_name * clean code * Журнал обработки - ProductsHider * clean code * clean code * readme updated * readme updated * update links * small updates --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- includes/Helper.php | 111 ++++++++++ includes/MenuTools.php | 151 +++++++------- includes/ProductStocks.php | 342 +++++++++++++++++-------------- includes/ProductVariable.php | 159 ++++---------- includes/Products.php | 126 ++++-------- includes/ProductsHiding.php | 20 +- includes/Settings.php | 166 ++++++++------- readme.txt | 12 +- wooms.php | 273 ++++++++++++------------ 10 files changed, 701 insertions(+), 661 deletions(-) create mode 100644 includes/Helper.php diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 34a86ce..3fa722d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,5 +9,5 @@ ## Чек лист - [ ] проверка локально -- [ ] тест на стенде https://wmstst.wpcraft.ru/ +- [ ] тест на стенде https://wooms.wpcraft.ru/ - [ ] В changelog добавлено описание изменений diff --git a/includes/Helper.php b/includes/Helper.php new file mode 100644 index 0000000..e5d3289 --- /dev/null +++ b/includes/Helper.php @@ -0,0 +1,111 @@ + [ 'product', 'product_variation' ], + 'meta_key' => 'wooms_id_' . $uuid, + ] ); + + if ( isset( $posts[0]->ID ) ) { + return $posts[0]->ID; + } + + $posts = get_posts( [ + 'post_type' => [ 'product', 'product_variation' ], + 'meta_key' => 'wooms_id', + 'meta_value' => $uuid + ] ); + + if ( empty( $posts[0]->ID ) ) { + return false; + } else { + return $posts[0]->ID; + } + } + + public static function log( string $message, $class = 'WooMS', array $data = [] ) { + if ( ! Logger::is_enable() ) { + return; + } + + if ( ! empty( $data ) ) { + + if ( is_array( $data ) ) { + $data = json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ); + } else { + $data = wc_print_r( $data, true ); + } + + $data = wp_trim_words( $data, 300 ); + $message .= PHP_EOL . '-' . PHP_EOL . $data; + } + + $source = str_replace( '\\', '-', $class ); + + $logger = wc_get_logger(); + $context = array( 'source' => $source ); + $logger->info( $message, $context ); + } + + public static function log_error( string $message, $class = 'WooMS', array $data = [] ) { + + if ( ! Logger::is_enable() ) { + return; + } + + if ( ! empty( $data ) ) { + + if ( is_array( $data ) ) { + $data = json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ); + } else { + $data = wc_print_r( $data, true ); + } + + $data = wp_trim_words( $data, 300 ); + $message .= PHP_EOL . '-' . PHP_EOL . $data; + } + + $source = str_replace( '\\', '-', $class ); + + $logger = wc_get_logger(); + $context = array( 'source' => $source ); + $logger->error( $message, $context ); + + } + + + public static function get_timestamp_last_job_by_hook($hook){ + $store = \ActionScheduler::store(); + $data = $store->query_actions([ + 'hook' => $hook, + 'orderby' => 'date', + 'order' => 'DESC', + ]); + + if(empty($data[0])){ + return null; + } + + $date = $store->get_date($data[0]); + $date->setTimezone(new \DateTimeZone(wp_timezone_string())); + return $date->format('Y-m-d H:i:s'); + } +} diff --git a/includes/MenuTools.php b/includes/MenuTools.php index 41fdb38..4f6d097 100644 --- a/includes/MenuTools.php +++ b/includes/MenuTools.php @@ -1,85 +1,88 @@ %s', 'Управление МойСклад'); - $items = [ - ' - Начало работы - ', - sprintf('Настройки', admin_url("admin.php?page=mss-settings") ), - 'Вход в МойСклад', - sprintf('Диагностика проблем', admin_url("site-health.php") ), - 'Рекомендуемые хостинги', - 'Контакты', - ]; - - printf( '
%s
', implode(' | ', $items) ); - - if(empty(get_option('woomss_pass'))){ - printf('Укажите логин и пароль на странице настроек
', admin_url('admin.php?page=mss-settings')); - } else { - if( empty($_GET['a']) ){ - - do_action('wooms_tools_sections'); - - // deprecated - do_action('woomss_tool_actions_btns'); - - } else { - - printf('Вернуться...', remove_query_arg( 'a', self::$url)); - do_action('woomss_tool_actions'); - do_action('woomss_tool_actions_' . $_GET['a']); - - } - } - - - } + /** + * URL action + */ + public static $url; + + /** + * The Init + */ + public static function init() { + + self::$url = $_SERVER['REQUEST_URI']; + + add_action( + 'admin_menu', + function () { + + if ( current_user_can( 'manage_woocommerce' ) ) { + add_menu_page( + $page_title = 'МойСклад', + $menu_title = 'МойСклад', + $capability = 'manage_woocommerce', + $menu_slug = 'moysklad', + $function = array ( __CLASS__, 'display_ui' ), + $icon = 'dashicons-forms', + '57.5' + ); + } + + } + ); + + + } + + /** + * Display UI + */ + public static function display_ui() { + printf( ''; + // var_dump( $meta ); + // exit; + // } ); + + add_filter( 'wooms_stock_product_save', [ __CLASS__, 'update_manage_stock' ], 10, 2 ); + add_action( 'wooms_assortment_sync', [ __CLASS__, 'batch_handler' ] ); add_filter( 'wooms_product_update', array( __CLASS__, 'update_product' ), 30, 2 ); @@ -36,22 +55,17 @@ public static function init() { add_action( 'wooms_variations_batch_end', [ __CLASS__, 'restart_after_batch' ] ); add_action( 'wooms_products_batch_end', [ __CLASS__, 'restart_after_batch' ] ); - add_action( 'wooms_main_walker_started', [ __CLASS__, 'restart' ] ); - add_action( 'admin_init', [__CLASS__, 'add_settings'], 30 ); + add_action( 'admin_init', [ __CLASS__, 'add_settings' ], 30 ); add_action( 'wooms_tools_sections', array( __CLASS__, 'display_state' ), 17 ); - add_filter( 'wooms_stock_type', array( __CLASS__, 'select_type_stock' ) ); + // add_filter( 'wooms_stock_type', array( __CLASS__, 'select_type_stock' ) ); - //need for disable reset state for base plugin - add_filter( 'wooms_reset_state_products', function ($reset) { - return false; - } ); } - public static function batch_handler($state = []) { - if(empty($state)){ + public static function batch_handler( $state = [] ) { + if ( empty( $state ) ) { $state = [ 'count' => 0 ]; @@ -73,17 +87,21 @@ public static function batch_handler($state = []) { ); $products = get_posts( $args ); - if ( empty($products) ) { - self::set_state( 'finish_timestamp', time() ); + + if ( empty( $products ) ) { return false; } - $filters = []; + $filters_by_id = []; foreach ( $products as $product ) { - $filters[] = 'id=' . get_post_meta( $product->ID, 'wooms_id', true ); + $filters_by_id[] = 'id=' . get_post_meta( $product->ID, 'wooms_id', true ); + delete_post_meta( $product->ID, self::$walker_hook_name ); } - // todo - переписать это как то лучше + $filters = [ + implode( ';', $filters_by_id ) + ]; + $url = 'https://api.moysklad.ru/api/remap/1.2/entity/assortment'; $filters = apply_filters( 'wooms_assortment_sync_filters', $filters ); @@ -100,39 +118,42 @@ public static function batch_handler($state = []) { $data = request( $url ); + // var_dump($data); exit; + if ( empty( $data['rows'] ) ) { return false; } - - $ids = self::process_rows($data['rows']); - if($ids){ + $ids = self::process_rows( $data['rows'] ); + if ( $ids ) { $state['last_ids'] = $ids; } - $state['count'] += count($data['rows']); + $state['count'] += count( $data['rows'] ); - return as_schedule_single_action( time(), self::$walker_hook_name, [$state], 'WooMS' ); + return as_schedule_single_action( time(), self::$walker_hook_name, [ $state ], 'WooMS' ); } - public static function process_rows($rows){ + public static function process_rows( $rows ) { $ids = []; foreach ( $rows as $row ) { - if ( ! $product_id = self::get_product_id_by_uuid( $row['id'] ) ) { + if ( ! $product_id = Helper::get_product_id_by_uuid( $row['id'] ) ) { + Helper::log_error( 'Не нашли продукт по uuid', __CLASS__, $row ); continue; } if ( ! $product = wc_get_product( $product_id ) ) { + Helper::log_error( 'Не нашли продукт по $product_id', __CLASS__, $row ); continue; } $product = self::update_stock( $product, $row ); $product->update_meta_data( 'wooms_assortment_data', self::get_stock_data_log( $row, $product_id ) ); - $product->delete_meta_data( self::$walker_hook_name ); + /** * manage stock save @@ -141,6 +162,7 @@ public static function process_rows($rows){ */ $product = apply_filters( 'wooms_stock_product_save', $product, $row ); + $ids[] = $product->save(); } @@ -148,112 +170,144 @@ public static function process_rows($rows){ } - /** - * get_stock_data_log - * for save log data to product meta - */ - public static function get_stock_data_log( $row = [], $product_id = 0 ) { - $data = [ - "stock" => $row['stock'], - "reserve" => $row['reserve'], - "inTransit" => $row['inTransit'], - "quantity" => $row['quantity'], - ]; - - $data = apply_filters( 'wooms_stock_log_data', $data, $product_id, $row ); - $data = json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ); - - return $data; - } + public static function update_stock( WC_Product $product, $data_api ): WC_Product { - public static function update_stock( $product, $data_api ) { - $product = wc_get_product( $product ); - - $product_id = $product->get_id(); + //если продукт вариативный, то его наличие определяется его вариациями и это отдельный поток хуков + if ( $product->get_type() === 'variable' ) { + return $product; + } /** * Поле по которому берем остаток? * quantity = это доступные остатки за вычетом резервов * stock = это все остатки без уета резерва */ - $stock_type = apply_filters( 'wooms_stock_type', 'quantity' ); - - $stock = 0; - - if ( empty( $data_api[ $stock_type ] ) ) { - $stock = 0; + if(get_config('stock_and_reserve')){ + $stock = (int) $data_api['quantity'] ?? 0; } else { - $stock = (int) $data_api[ $stock_type ]; + $stock = (int) $data_api['stock'] ?? 0; } - if ( get_option( 'wooms_stock_empty_backorder' ) ) { - $product->set_backorders( 'notify' ); + if ( $stock > 0 ) { + $product->set_stock_quantity( $stock ); + $product->set_stock_status( 'instock' ); } else { - $product->set_backorders( 'no' ); + $product->set_stock_quantity( 0 ); + $product->set_stock_status( 'outofstock' ); } - if ( empty( get_option( 'wooms_warehouse_count' ) ) ) { - $product->set_manage_stock( false ); - } else { - if ( $product->is_type( 'variable' ) ) { - //для вариативных товаров доступность определяется наличием вариаций - $product->set_manage_stock( false ); - } else { - $product->set_manage_stock( true ); - } - } + $log_data = [ + 'stock' => $data_api['stock'], + 'quantity' => $data_api['quantity'], + 'type' => $product->get_type(), + ]; - if ( $stock <= 0 ) { - if ( ! $product->is_type( 'variable' ) ) { - $product->set_stock_quantity( 0 ); - $product->set_stock_status( 'outofstock' ); - } - } else { - $product->set_stock_quantity( $stock ); - $product->set_stock_status( 'instock' ); + if ( $product->get_type() === 'variation' ) { + $log_data['product_parent'] = $product->get_parent_id(); } - do_action( - 'wooms_logger', + Helper::log( sprintf( + 'Остатки для продукта "%s" (ИД %s) = %s', $product->get_name(), $product->get_id(), $product->get_stock_quantity() ), __CLASS__, - sprintf( 'Остатки для продукта "%s" = %s (ИД %s)', $product->get_name(), $stock, $product_id ), - sprintf( 'stock %s, quantity %s', $data_api['stock'], $data_api['quantity'] ) + $log_data ); return $product; } + /** - * restart walker after added tast to queue + * Если у сайта включена опция управление остатками - установить остатки для товара + * + * @todo вероятно опция типа wooms_warehouse_count - более не нужна */ - public static function restart() { - self::set_state( 'finish_timestamp', 0 ); - self::set_state( 'count_all', 0 ); - self::set_state( 'count_save', 0 ); - } + public static function update_manage_stock( WC_Product $product, $data_api ): WC_Product { + if ( ! get_option( 'woocommerce_manage_stock' ) ) { + return $product; + } - public static function restart_after_batch() { - if(as_has_scheduled_action(self::$walker_hook_name)){ - return; + if ( ! $product->get_manage_stock() ) { + $product->set_manage_stock( true ); + Helper::log( sprintf( + 'Включили управление запасами для продукта: %s (ИД %s)', $product->get_name(), $product->get_id() ), + __CLASS__ + ); } - as_schedule_single_action( time(), self::$walker_hook_name, [], 'WooMS' ); - } + //для вариативных товаров доступность определяется наличием вариаций + if ( $product->get_type() === 'variation' ) { + + $parent_id = $product->get_parent_id(); + $parent_product = wc_get_product( $parent_id ); + if ( empty( $parent_product ) ) { + Helper::log_error( "Не нашли родительский продукт: {$parent_id}, вариация: {$product->get_id()}", + __CLASS__ + ); + return $product; + } + if ( $parent_product->get_manage_stock() ) { + + Helper::log( sprintf( + 'У основного продукта отключили управление остатками: %s (ИД %s)', $parent_product->get_name(), $parent_id ), + __CLASS__ + ); + $parent_product->set_manage_stock( false ); + + $parent_product->save(); + } + + } + + /** + * это похоже надо выпилить + * + * потому что это не относится к синку МС и должно управляться как то иначе + * + * если это тут оставлять, то эта отметка должна быть на стороне МС + */ + // if ( get_option( 'wooms_stock_empty_backorder' ) ) { + // $product->set_backorders( 'notify' ); + // } else { + // $product->set_backorders( 'no' ); + // } + return $product; + } /** - * check is wait + * get_stock_data_log + * for save log data to product meta */ - public static function is_wait() { - if ( self::get_state( 'finish_timestamp' ) ) { - return true; + public static function get_stock_data_log( $row = [], $product_id = 0 ) { + $data = [ + "stock" => $row['stock'], + "reserve" => $row['reserve'], + "inTransit" => $row['inTransit'], + "quantity" => $row['quantity'], + ]; + + $data = apply_filters( 'wooms_stock_log_data', $data, $product_id, $row ); + + $data = json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ); + + return $data; + } + + + public static function restart_after_batch() { + if ( ! self::is_enable() ) { + return; } - return false; + if ( as_has_scheduled_action( self::$walker_hook_name ) ) { + return; + } + + as_schedule_single_action( time(), self::$walker_hook_name, [], 'WooMS' ); } @@ -278,11 +332,6 @@ public static function get_state( $key = '' ) { } - - - /** - * set state data - */ public static function set_state( $key, $value ) { if ( ! $state = get_transient( self::$state_transient_key ) ) { @@ -372,27 +421,17 @@ public static function assortment_add_filter_by_warehouse_id( $filter ) { return $filter; } - /** - * Select type stock - */ - public static function select_type_stock( $type_stock ) { - if ( get_option( 'wooms_stocks_without_reserve' ) ) { - $type_stock = 'stock'; - } - - return $type_stock; - } /** * Update stock for variation */ - public static function update_variation( $variation, $data_api ) { + public static function update_variation( \WC_Product_Variation $variation, $data_api ) { if ( self::is_enable() ) { $variation->update_meta_data( self::$walker_hook_name, 1 ); } else { $variation->set_catalog_visibility( 'visible' ); $variation->set_stock_status( 'instock' ); - $variation->set_manage_stock( 'no' ); + $variation->set_manage_stock( false ); $variation->set_status( 'publish' ); } @@ -409,7 +448,7 @@ public static function update_product( $product, $data_api ) { } else { $product->set_catalog_visibility( 'visible' ); $product->set_stock_status( 'instock' ); - $product->set_manage_stock( 'no' ); + $product->set_manage_stock( false ); $product->set_status( 'publish' ); } @@ -437,32 +476,38 @@ public static function add_settings() { $section = 'woomss_section_warehouses' ); - register_setting( 'mss-settings', 'wooms_stocks_without_reserve' ); add_settings_field( - $id = 'wooms_stocks_without_reserve', - $title = 'Остатки без резерва', - $callback = array( __CLASS__, 'display_field_wooms_stocks_without_reserve' ), - $page = 'mss-settings', - $section = 'woomss_section_warehouses' - ); + $id = 'stock_and_reserve', + $title = 'Учитывать остатки с резервом', + $callback = function ($args) { + printf( '', $args['name'], $args['value'] ); - register_setting( 'mss-settings', 'wooms_warehouse_count' ); - add_settings_field( - $id = 'wooms_warehouse_count', - $title = 'Управление запасами на уровне товаров', - $callback = array( __CLASS__, 'display_wooms_warehouse_count' ), + }, $page = 'mss-settings', - $section = 'woomss_section_warehouses' + $section, + $args = [ + 'name' => get_config_name( 'stock_and_reserve' ), + 'value' => checked( 1, get_config( 'stock_and_reserve' ) ), + ] ); - register_setting( 'mss-settings', 'wooms_stock_empty_backorder' ); - add_settings_field( - $id = 'wooms_stock_empty_backorder', - $title = 'Разрешать предзаказ при 0 остатке', - $callback = array( __CLASS__, 'display_wooms_stock_empty_backorder' ), - $page = 'mss-settings', - $section = 'woomss_section_warehouses' - ); + // register_setting( 'mss-settings', 'wooms_warehouse_count' ); + // add_settings_field( + // $id = 'wooms_warehouse_count', + // $title = 'Управление запасами на уровне товаров', + // $callback = array( __CLASS__, 'display_wooms_warehouse_count' ), + // $page = 'mss-settings', + // $section = 'woomss_section_warehouses' + // ); + + // register_setting( 'mss-settings', 'wooms_stock_empty_backorder' ); + // add_settings_field( + // $id = 'wooms_stock_empty_backorder', + // $title = 'Разрешать предзаказ при 0 остатке', + // $callback = array( __CLASS__, 'display_wooms_stock_empty_backorder' ), + // $page = 'mss-settings', + // $section = 'woomss_section_warehouses' + // ); self::add_setting_warehouse_id(); } @@ -481,7 +526,7 @@ public static function add_setting_warehouse_id() { $url = 'entity/store'; $data = request( $url ); - if ( empty( $data['rows'] ) ) { + if ( empty ( $data['rows'] ) ) { echo 'Система не смогла получить список складов из МойСклад'; return; } @@ -546,14 +591,6 @@ public static function display_wooms_stock_empty_backorder() { echo 'Если включить опцию то система будет разрешать предзаказ при 0 остатках
'; } - /** - * display_field_wooms_stocks_without_reserve - */ - public static function display_field_wooms_stocks_without_reserve() { - $option = 'wooms_stocks_without_reserve'; - printf( '', $option, checked( 1, get_option( $option ), false ) ); - echo 'Если включить опцию то на сайте будут учитываться остатки без учета резерва
'; - } /** * Display field @@ -593,30 +630,23 @@ public static function display_state() { $strings[] = sprintf( 'Статус: %s', 'в ожидании задач' ); } - if ( $end_timestamp = self::get_state( 'finish_timestamp' ) ) { - $end_timestamp = date( 'Y-m-d H:i:s', $end_timestamp ); - $strings[] = sprintf( 'Последняя успешная синхронизация (отметка времени UTC): %s', $end_timestamp ); - } - $strings[] = sprintf( 'Очередь задач: открыть', admin_url( 'admin.php?page=wc-status&tab=action-scheduler&s=wooms_assortment_sync&orderby=schedule&order=desc' ) ); + $strings[] = sprintf( 'Последняя успешная синхронизация: %s', Helper::get_timestamp_last_job_by_hook( self::$walker_hook_name ) ) ?? 'Нет данных'; + $strings[] = sprintf( 'Очередь задач: открыть', admin_url( 'admin.php?page=wc-status&tab=action-scheduler&s=wooms_assortment_sync&orderby=schedule&order=desc' ) ); - if ( defined( 'WC_LOG_HANDLER' ) && 'WC_Log_Handler_DB' == WC_LOG_HANDLER ) { - $strings[] = sprintf( 'Журнал обработки: открыть', admin_url( 'admin.php?page=wc-status&tab=logs&source=WooMS-ProductStocks' ) ); - } else { - $strings[] = sprintf( 'Журнал обработки: открыть', admin_url( 'admin.php?page=wc-status&tab=logs' ) ); - } + $strings[] = sprintf( 'Журнал обработки: открыть', admin_url( 'admin.php?page=wc-status&tab=logs&source=WooMS-ProductStocks' ) ); ?>Остатки
-getMessage() - ); + + Helper::log_error( $e->getMessage(), __CLASS__ ); return false; } } @@ -141,13 +136,19 @@ public static function process_rows( $rows ) { $i = 0; foreach ( $rows as $key => $row ) { - if ( $row["meta"]["type"] != 'variant' ) { - continue; - } + try { + if ( $row["meta"]["type"] != 'variant' ) { + continue; + } + + $i++; - $i++; + self::update_variation( $row ); - self::update_variation( $row ); + } catch (\Exception $e) { + Helper::log_error( $e->getMessage(), __CLASS__ ); + continue; + } } @@ -159,7 +160,7 @@ public static function process_rows( $rows ) { */ public static function set_wait() { as_unschedule_all_actions( self::$walker_hook_name ); - self::set_state( 'end_timestamp', time() ); + } @@ -329,12 +330,12 @@ public static function save_attributes_for_variation( \WC_Product_Variation $var $variation->set_attributes( $attributes ); - do_action( - 'wooms_logger', - __CLASS__, - sprintf( 'Сохранены атрибуты для вариации %s (продукт: %s)', $variation_id, $product_id ), - wc_print_r( $attributes, true ) - ); + Helper::log('Сохранены атрибуты для вариации', __CLASS__, [ + 'name' => $variation->get_name(), + 'variation_id' => $variation_id, + 'product_id' => $product_id, + 'attributes' => $attributes, + ]); return $variation; } @@ -349,7 +350,7 @@ public static function update_variation( $row ) { } if ( ! empty( $row['archived'] ) ) { - return null; + return; } if(empty($row['product']['meta']['href'])){ @@ -357,29 +358,24 @@ public static function update_variation( $row ) { } $product_href = $row['product']['meta']['href']; - $product_id = self::get_product_id_by_uuid( $product_href ); + $product_id = Helper::get_product_id_by_uuid( $product_href ); $product_parent = wc_get_product( $product_id ); if(empty($product_parent)){ - do_action( - 'wooms_logger_error', - __CLASS__, - sprintf( 'Нет базового продукта для вариации. %s', json_encode( ['product_id' => $product_id, '$row id' => $row ] ) ) - ); - - return null; - + /** + * так бывает + * мы получаем вариации всей пачкой и для каких то может не быть базового продукта + * чаще всего это не ошибка, но может быть и она + */ + Helper::log('Нет базового продукта для вариации', __CLASS__, $row); + return; } if ( ! $product_parent->is_type( 'variable' ) ) { $product_parent = new \WC_Product_Variable( $product_parent ); $product_parent->save(); - do_action( - 'wooms_logger_error', - __CLASS__, - sprintf( 'Снова сохранили продукт как вариативный %s', $product_id ) - ); + Helper::log(sprintf( 'Снова сохранили продукт как вариативный %s', $product_id ), __CLASS__); } if ( empty( $product_id ) ) { @@ -432,6 +428,7 @@ public static function update_variation( $row ) { } $variation = apply_filters( 'wooms_variation_save', $variation, $row, $product_id ); + $variation = apply_filters( 'wooms_variation_update', $variation, $row, $product_id ); $variation_id = $variation->save(); @@ -545,8 +542,7 @@ public static function start_manually() { * Stopping walker imports from MoySklad */ public static function walker_finish() { - self::set_state( 'end_timestamp', time() ); - self::set_state( 'lock', 0 ); + do_action( 'wooms_wakler_variations_finish' ); @@ -597,26 +593,6 @@ public static function get_attribute_id_by_label( $label = '' ) { return false; } - - public static function is_wait() { - //check run main walker - if ( as_next_scheduled_action( 'wooms_products_walker_batch' ) ) { - return true; - } - - //check end pause - if ( ! empty( self::get_state( 'end_timestamp' ) ) ) { - return true; - } - - return false; - } - - - - /** - * display_state - */ public static function display_state() { if ( ! self::is_enable() ) { @@ -643,19 +619,13 @@ public static function display_state() { $strings[] = sprintf( 'Статус: %s', 'Выполняется очередями в фоне' ); } else { - $strings[] = sprintf( 'Статус: %s', 'в ожидании задач' ); - $strings[] = sprintf( 'Последняя успешная синхронизация: %s', wooms_get_timestamp_last_job_by_hook( self::$walker_hook_name ) ); + $strings[] = sprintf( 'Статус: %s', 'Завершено' ); + $strings[] = sprintf( 'Последняя успешная синхронизация: %s', Helper::get_timestamp_last_job_by_hook( self::$walker_hook_name ) ) ?? 'Нет данных'; } - $strings[] = sprintf( 'Очередь задач: открыть', admin_url( 'admin.php?page=wc-status&tab=action-scheduler&s=wooms_variables_walker_batch&orderby=schedule&order=desc' ) ); - - if ( defined( 'WC_LOG_HANDLER' ) && 'WC_Log_Handler_DB' == WC_LOG_HANDLER ) { - $strings[] = sprintf( 'Журнал обработки: открыть', admin_url( 'admin.php?page=wc-status&tab=logs&source=WooMS-ProductVariable' ) ); - } else { - $strings[] = sprintf( 'Журнал обработки: открыть', admin_url( 'admin.php?page=wc-status&tab=logs' ) ); - } + $strings[] = sprintf( 'Журнал обработки: открыть', admin_url( 'admin.php?page=wc-status&tab=logs&source=WooMS-ProductVariable' ) ); ?>- %s', $string ); - } - ?> -+ + %s', $string ); + } + ?> +@@ -766,51 +736,6 @@ public static function update_product( $product, $data_api ) { return $product; } - - - /** - * get state data - */ - public static function get_state( $key = '' ) { - if ( ! $state = get_option( self::$state_transient_key ) ) { - $state = []; - update_option( self::$state_transient_key, $state ); - } - - if ( empty( $key ) ) { - return $state; - } - - if ( empty( $state[ $key ] ) ) { - return null; - } - - return $state[ $key ]; - } - - /** - * set state data - */ - public static function set_state( $key, $value = null ) { - if ( $value === null && is_array( $key ) ) { - update_option( self::$state_transient_key, $key, false ); - return; - } - - if ( ! $state = get_option( self::$state_transient_key ) ) { - $state = []; - } - - if ( is_array( $state ) ) { - $state[ $key ] = $value; - } else { - $state = []; - $state[ $key ] = $value; - } - - update_option( self::$state_transient_key, $state, false ); - } - /** * show wooms_id for variation in admin */ diff --git a/includes/Products.php b/includes/Products.php index 891f07d..5167cc8 100644 --- a/includes/Products.php +++ b/includes/Products.php @@ -4,7 +4,7 @@ use function WooMS\request; use function Testeroid\ddcli; -use Error, Throwable, WC_Product; +use Error, Throwable, WC_Product, WooMS\Helper; defined( 'ABSPATH' ) || exit; @@ -60,7 +60,7 @@ function walker( $args = [] ) { $url = apply_filters( 'wooms_url_get_products', $url ); $filters = [ - // 'pathName~=Диваны', + 'archived=false' ]; $filters = apply_filters( 'wooms_url_get_products_filters', $filters ); @@ -103,46 +103,26 @@ function walker( $args = [] ) { } function process_rows( $rows = [] ) { + $ids = []; + foreach ( $rows as $row ) { + $ids[] = $row['id']; - try { - - if ( empty( $rows ) ) { - throw new Error('$rows is empty'); + if ( apply_filters( 'wooms_skip_product_import', false, $row ) ) { + continue; } - $ids = []; - foreach ( $rows as $row ) { - $ids[] = $row['id']; - - if ( apply_filters( 'wooms_skip_product_import', false, $row ) ) { - continue; - } - - /** - * в выдаче могут быть не только товары, но и вариации и мб что-то еще - * птм нужна проверка что это точно продукт - */ - if ( 'variant' == $row["meta"]["type"] ) { - continue; - } - - $data = apply_filters( 'wooms_product_data', [], $row ); - - product_update( $row, $data ); + /** + * в выдаче могут быть не только товары, но и вариации и мб что-то еще + * птм нужна проверка что это точно продукт + */ + if ( 'variant' == $row["meta"]["type"] ) { + continue; } + $data = apply_filters( 'wooms_product_data', [], $row ); - return true; - } catch (Throwable $e) { - - $message = sprintf("wooms process fails: %s, ids: %s, code: %s", $e->getMessage(), json_encode($ids), $e->getCode()); - do_action( 'wooms_logger_error', __NAMESPACE__, $message ); - error_log($message); - - return false; + product_update( $row, $data ); } - - } @@ -222,7 +202,7 @@ function product_update( array $row, array $data = [] ) { $product_id = 0; - $product_id = get_product_id_by_uuid( $row['id'] ); + $product_id = Helper::get_product_id_by_uuid( $row['id'] ); if ( ! empty( $row['archived'] ) ) { if ( $product_id ) { @@ -247,12 +227,8 @@ function product_update( array $row, array $data = [] ) { if ( empty( intval( $product_id ) ) ) { - do_action( - 'wooms_logger_error', - __NAMESPACE__, - 'Ошибка определения и добавления ИД продукта', - $row - ); + Helper::log_error('Ошибка определения и добавления ИД продукта', __NAMESPACE__, $row); + return false; } @@ -263,16 +239,6 @@ function product_update( array $row, array $data = [] ) { */ $data_api = $row; - $product->update_meta_data( 'wooms_id_' . $row['id'], 1 ); - - /** - * Хук позволяет работать с методами WC_Product - * Сохраняет в БД все изменения за 1 раз - * Снижает нагрузку на БД - * - * DEPRECATED - */ - $product = apply_filters( 'wooms_product_save', $product, $data_api, $product_id ); //save data of source if ( apply_filters( 'wooms_logger_enable', false ) ) { @@ -289,9 +255,6 @@ function product_update( array $row, array $data = [] ) { } $product->update_meta_data( 'wooms_updated_timestamp', date( "Y-m-d H:i:s" ) ); - - $product->update_meta_data( 'wooms_id', $data_api['id'] ); - $product->update_meta_data( 'wooms_updated_from_api', $data_api['updated'] ); //update title @@ -336,24 +299,22 @@ function product_update( array $row, array $data = [] ) { $product->set_regular_price( $price ); } - // issue https://github.com/wpcraft-ru/wooms/issues/302 - $product->set_catalog_visibility( 'visible' ); + $product->update_meta_data( 'wooms_id', $data_api['id'] ); + $product->update_meta_data( 'wooms_id_' . $data_api['id'], 1 ); - if ( apply_filters( 'wooms_reset_state_products', true ) ) { - $product->set_stock_status( 'instock' ); - $product->set_manage_stock( false ); - $product->set_status( 'publish' ); - } + /** + * reset state product + * + * @issue https://github.com/wpcraft-ru/wooms/issues/302 + */ + $product->set_catalog_visibility( 'visible' ); + $product->set_status( 'publish' ); $product = apply_filters( 'wooms_product_update', $product, $row, $data ); $product_id = $product->save(); - do_action( - 'wooms_logger', - __NAMESPACE__, - sprintf( 'Продукт: %s (%s) сохранен', $product->get_title(), $product_id ) - ); + Helper::log(sprintf( 'Продукт: %s (%s) сохранен', $product->get_title(), $product_id ), __NAMESPACE__); return $product_id; @@ -474,7 +435,6 @@ function walker_started() { 'session_id' => $now, 'timestamp' => $now, 'query_arg' => $query_arg_default, - 'end_timestamp' => 0, ]; set_state( $state ); @@ -483,29 +443,9 @@ function walker_started() { do_action( 'wooms_logger', __NAMESPACE__, 'Старт основного волкера: ' . $now ); } -// function auto_start() { - -// $end_timestamp = get_state( 'end_timestamp' ); -// if( empty($end_timestamp)){ -// return false; -// } - -// if ( empty( get_option( 'woomss_pass' ) ) ) { -// return false; -// } - -// if ( as_next_scheduled_action( HOOK_NAME ) ) { -// return; -// } - - - -// return as_schedule_single_action( time(), HOOK_NAME, [], 'WooMS' ); -// } - function render_ui() { - printf( '%s
', 'Каталог' ); + printf( '%s
', 'Каталог и базовые продукты' ); $strings = []; if ( as_next_scheduled_action( HOOK_NAME ) ) { @@ -515,7 +455,7 @@ function render_ui() { } else { $strings[] = sprintf( 'Статус: %s', 'Завершено' ); - $strings[] = sprintf( 'Время последнего завершения: %s', wooms_get_timestamp_last_job_by_hook( HOOK_NAME ) ); + $strings[] = sprintf( 'Последняя успешная синхронизация: %s', Helper::get_timestamp_last_job_by_hook( HOOK_NAME ) ) ?? 'Нет данных'; printf( 'Запустить синхронизацию продуктов вручную', add_query_arg( 'a', 'wooms_products_start_import', admin_url( 'admin.php?page=moysklad' ) ) @@ -524,6 +464,7 @@ function render_ui() { } $strings[] = sprintf( 'Очередь задач: открыть', admin_url( 'admin.php?page=wc-status&tab=action-scheduler&s=wooms_products_walker&orderby=schedule&order=desc' ) ); + foreach ( $strings as $string ) { printf( '%s
', $string ); } @@ -568,6 +509,7 @@ function display_metabox_for_product() { $data_id = get_post_meta( $post->ID, 'wooms_id', true ); $data_meta = get_post_meta( $post->ID, 'wooms_meta', true ); $data_updated = get_post_meta( $post->ID, 'wooms_updated', true ); + $wooms_updated_timestamp = get_post_meta( $post->ID, 'wooms_updated_timestamp', true ); if ( $data_id ) { printf( 'ID товара в МойСклад:', $data_id ); } else { @@ -582,5 +524,9 @@ function display_metabox_for_product() { printf( '%sДата последнего обновления товара в МойСклад: %s', $data_updated ); } + if ( $data_updated ) { + printf( 'Дата последнего обновления из API МойСклад: %s', $wooms_updated_timestamp ); + } + do_action( 'wooms_display_product_metabox', $post->ID ); } diff --git a/includes/ProductsHiding.php b/includes/ProductsHiding.php index ee961e2..348e6c1 100644 --- a/includes/ProductsHiding.php +++ b/includes/ProductsHiding.php @@ -2,6 +2,8 @@ namespace WooMS\ProductsHider; +use WooMS\Helper; + const HOOK_NAME = 'wooms_schedule_clear_old_products_walker'; add_action('init', function () { @@ -42,18 +44,13 @@ function walker($state = []) $product = wc_get_product($product_id); $ids[] = $product_id; - if ($product->get_type() == 'variable') { - // $product->set_manage_stock('yes'); - } + $product->set_status('draft'); $product->set_catalog_visibility('hidden'); $product->save(); - do_action( - 'wooms_logger', - __NAMESPACE__, - sprintf('Скрытие продукта: %s', $product_id) - ); + Helper::log(sprintf('Скрытие продукта: %s', $product_id), __NAMESPACE__); + } $state['ids'] = $ids; @@ -101,10 +98,13 @@ function get_products_old_session() return false; } + $args = array( - 'post_type' => ['product', 'product_variation'], + 'post_type' => ['product'], + 'post_status' => 'publish', 'numberposts' => 30, 'fields' => 'ids', + 'tax_query' => array( array( 'taxonomy' => 'product_visibility', @@ -161,6 +161,8 @@ function display_state() $strings[] = sprintf('Очередь задач: открыть', admin_url('admin.php?page=wc-status&tab=action-scheduler&s=wooms_schedule_clear_old_products_walker&orderby=schedule&order=desc')); + $strings[] = sprintf( 'Журнал обработки: открыть', admin_url( 'admin.php?page=wc-status&tab=logs&source=WooMS-ProductsHider' ) ); + echo 'Скрытие продуктов
'; foreach ($strings as $string) { printf('%s
', $string); diff --git a/includes/Settings.php b/includes/Settings.php index 5792993..0edf96a 100644 --- a/includes/Settings.php +++ b/includes/Settings.php @@ -2,39 +2,45 @@ namespace WooMS; -if (!defined('ABSPATH')) { +if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } const OPTION_KEY = 'wooms_config'; const OPTIONS_PAGE = 'mss-settings'; -function get_config($key = null){ - $config = get_option(OPTION_KEY, []); - if(empty($key)){ - return $config; - } - return $config[$key] ?? null; +function get_config( $key = null ) { + $config = get_option( OPTION_KEY, [] ); + if ( empty( $key ) ) { + return $config; + } + return $config[ $key ] ?? null; +} + +/** + * Get name of form field by key + */ +function get_config_name( $key ) { + + return OPTION_KEY . '[' . $key . ']'; } -function set_config($key, $value){ - $config = get_option(OPTION_KEY, []); - $config[$key] = $value; - return update_option(OPTION_KEY, $config, false); +function set_config( $key, $value ) { + $config = get_option( OPTION_KEY, [] ); + $config[ $key ] = $value; + return update_option( OPTION_KEY, $config, false ); } /** * Settings */ -class Settings -{ +class Settings { /** * The Init */ - public static function init() - { + public static function init() { add_action( 'admin_menu', @@ -53,30 +59,40 @@ function () { 'Настройки', 'manage_options', 'mss-settings', - array(__CLASS__, 'display_settings') + array ( __CLASS__, 'display_settings' ) ); }, 30 ); - add_action('admin_init', array(__CLASS__, 'settings_general'), $priority = 5, $accepted_args = 1); - add_action('admin_init', array(__CLASS__, 'settings_other'), $priority = 100, $accepted_args = 1); + add_action( 'admin_init', array( __CLASS__, 'settings_general' ), $priority = 5, $accepted_args = 1 ); + add_action( 'admin_init', array( __CLASS__, 'settings_other' ), $priority = 100, $accepted_args = 1 ); - add_action('wooms_settings_after_header', [__CLASS__, 'render_nav_menu']); + add_action( 'wooms_settings_after_header', [ __CLASS__, 'render_nav_menu' ] ); } - public static function render_nav_menu(){ + public static function render_nav_menu() { $nav_items = [ - 'getting-started' => sprintf('%s', 'https://github.com/wpcraft-ru/wooms/wiki/GettingStarted', 'С чего начать?'), - 'diagnostic' => sprintf('%s', admin_url('site-health.php'), 'Диагностика проблем'), - 'ms' => sprintf('%s', 'https://online.moysklad.ru/', 'Вход в МойСклад'), + 'dev' => sprintf( '%s', 'https://github.com/wpcraft-ru/wooms/', 'Разработка и решение проблем' ), + 'docs' => sprintf( '%s', 'https://github.com/wpcraft-ru/wooms/wiki', 'Документация' ), + + 'ms' => sprintf( '%s', 'https://online.moysklad.ru/', 'Вход в МойСклад' ), ]; - $nav_items = apply_filters('wooms_settings_nav_items', $nav_items); + $nav_items = apply_filters( 'wooms_settings_nav_items', $nav_items ); + + ?> + + ', get_option('woomss_pass')); + public static function display_form_pass() { + printf( '', get_option( 'woomss_pass' ) ); } /** * display_form_login */ - public static function display_form_login() - { - printf('', get_option('woomss_login')); + public static function display_form_login() { + printf( '', get_option( 'woomss_login' ) ); - printf('%s
', 'Вводить нужно только логин и пароль здесь. На стороне МойСклад ничего настраивать не нужно.'); + printf( '%s
', 'Вводить нужно только логин и пароль здесь. На стороне МойСклад ничего настраивать не нужно.' ); } /** * Settings - Other */ - public static function settings_other() - { - add_settings_section('woomss_section_other', 'Прочие настройки', null, 'mss-settings'); + public static function settings_other() { + add_settings_section( 'woomss_section_other', 'Прочие настройки', null, 'mss-settings' ); - register_setting('mss-settings', 'wooms_use_uuid'); + register_setting( 'mss-settings', 'wooms_use_uuid' ); add_settings_field( $id = 'wooms_use_uuid', $title = 'Использование UUID', - $callback = array(__CLASS__, 'display_field_wooms_use_uuid'), + $callback = array( __CLASS__, 'display_field_wooms_use_uuid' ), $page = 'mss-settings', $section = 'woomss_section_other' ); - register_setting('mss-settings', 'wooms_replace_title'); + register_setting( 'mss-settings', 'wooms_replace_title' ); add_settings_field( $id = 'wooms_replace_title', $title = 'Замена заголовка при обновлении', - $callback = array(__CLASS__, 'display_wooms_replace_title'), + $callback = array( __CLASS__, 'display_wooms_replace_title' ), $page = 'mss-settings', $section = 'woomss_section_other' ); - register_setting('mss-settings', 'wooms_replace_description'); + register_setting( 'mss-settings', 'wooms_replace_description' ); add_settings_field( $id = 'wooms_replace_description', $title = 'Замена описания при обновлении', - $callback = array(__CLASS__, 'display_wooms_replace_desc'), + $callback = array( __CLASS__, 'display_wooms_replace_desc' ), $page = 'mss-settings', $section = 'woomss_section_other' ); @@ -166,85 +178,81 @@ public static function settings_other() /** * display_wooms_replace_desc */ - public static function display_wooms_replace_desc() - { + public static function display_wooms_replace_desc() { $option_name = 'wooms_replace_description'; - printf('', $option_name, checked(1, get_option($option_name), false)); -?> + printf( '', $option_name, checked( 1, get_option( $option_name ), false ) ); + ?>Если включить опцию, то плагин будет обновлять описание продукта из МойСклад всегда.
- ', $option_name, checked(1, get_option($option_name), false)); - ?> + printf( '', $option_name, checked( 1, get_option( $option_name ), false ) ); + ?>- Если включить опцию, то плагин будет обновлять заголовки продукта из МойСклад. Иначе при наличии заголовока он не будет обновлен. + Если включить опцию, то плагин будет обновлять заголовки продукта из МойСклад. Иначе при наличии заголовока + он не будет обновлен.
- ', $option_name, checked(1, get_option($option_name), false)); - ?> + printf( '', $option_name, checked( 1, get_option( $option_name ), false ) ); + ?>Если товары не попадают из МойСклад на сайт - попробуйте включить эту опцию.
- По умолчанию используется связь продуктов по артикулу. Это позволяет обеспечить синхронизацию без удаления всех продуктов с сайта при их наличии. Но без артикула - товары не будут синхронизироваться. Если товаров на сайте нет, либо их можно удалить без вреда, то можно включить синхронизацию по UUID. В этом случае артикулы + По умолчанию используется связь продуктов по артикулу. Это позволяет обеспечить синхронизацию без удаления + всех продуктов с сайта при их наличии. Но без артикула + товары не будут синхронизироваться. Если товаров на сайте нет, либо их можно удалить без вреда, то можно + включить синхронизацию по UUID. В этом случае артикулы будут не нужны.
- + ?> -Управление синхронизацией', admin_url('admin.php?page=moysklad')); - printf('', "https://github.com/topics/wooms"); - printf('
При создании записи о продукте произойдет связка по UUID (meta_key = wooms_id)Предложения по улучшению и запросы на доработку
', "https://github.com/wpcraft-ru/wooms/issues"); - printf('', "https://wpcraft.ru/hosting-wordpress-woocommerce/"); - printf('', "https://wpcraft.ru/wooms/"); + printf( '', admin_url( 'admin.php?page=moysklad' ) ); + printf( '', "https://wpcraft.ru/wooms/?utm_source=wooms_plugin_settings_page" ); } } diff --git a/readme.txt b/readme.txt index ec4ba9b..c836b77 100644 --- a/readme.txt +++ b/readme.txt @@ -1,6 +1,6 @@ === WooMS === Contributors: casepress -Donate link: https://wpcraft.ru/product/wooms-extra/ +Donate link: https://wpcraft.ru/pay/ Tags: moysklad, woocommerce, sync, integration Requires at least: 6.0 Tested up to: 6.4.2 @@ -23,7 +23,7 @@ Integration WooCommerce & MoySklad http://moysklad.ru (for Russia) * Загрузка картинок * Гибкие настройки -[Руководство по быстрому началу работы](https://github.com/wpcraft-ru/wooms/wiki/GettingStarted) +[Руководство по быстрому началу работы](https://wpcraft.ru/wooms/) Исходники для желающих принять участие в разработке: [https://github.com/wpcraft-ru/wooms/](https://github.com/wpcraft-ru/wooms/) @@ -76,9 +76,15 @@ PHP 7.0 == Changelog == += 9.11 = +- Тест совместимости WooCommerce 8.7.0 +- Улучшена синхронизация остатков +- Не обновляются остатки по товарам https://github.com/wpcraft-ru/wooms/issues/544 https://github.com/wpcraft-ru/wooms/issues/524 +- Совместимость: 'Высокопроизводительное хранилище заказов' https://github.com/wpcraft-ru/wooms/issues/539 + = 9.10 = - Исправлена ошибка с версией -- Обновдены авто тесты +- Обновлены авто тесты = 9.9 = - Исправление RC 2: Перестала работать синхронизация на версии 9.6 https://github.com/wpcraft-ru/wooms/issues/522 diff --git a/wooms.php b/wooms.php index bff310d..0d4892e 100644 --- a/wooms.php +++ b/wooms.php @@ -19,90 +19,89 @@ * WC requires at least: 7.0 * WC tested up to: 8.4.0 * - * Version: 9.10 + * Version: 9.11 */ namespace WooMS; // Exit if accessed directly -defined('ABSPATH') || exit; +defined( 'ABSPATH' ) || exit; /** * Add hook for activate plugin */ -register_activation_hook(__FILE__, function () { - do_action('wooms_activate'); -}); +register_activation_hook( __FILE__, function () { + do_action( 'wooms_activate' ); +} ); -register_deactivation_hook(__FILE__, function () { - do_action('wooms_deactivate'); -}); +register_deactivation_hook( __FILE__, function () { + do_action( 'wooms_deactivate' ); +} ); require_once __DIR__ . '/includes/functions.php'; -add_action('plugins_loaded', function () { - if (!wooms_can_start()) { - return; - } +add_action( 'plugins_loaded', function () { + if ( ! wooms_can_start() ) { + return; + } - $files = glob(__DIR__ . '/includes/*.php'); - foreach ($files as $file) { - require_once $file; - } - add_action('admin_enqueue_scripts', __NAMESPACE__ . '\\' . 'admin_styles'); - add_action('save_post', 'wooms_id_check_if_unique', 10, 3); -}); + $files = glob( __DIR__ . '/includes/*.php' ); + foreach ( $files as $file ) { + require_once $file; + } + add_action( 'admin_enqueue_scripts', __NAMESPACE__ . '\\' . 'admin_styles' ); + add_action( 'save_post', 'wooms_id_check_if_unique', 10, 3 ); +} ); -add_filter('plugin_row_meta', __NAMESPACE__ . '\\add_wooms_plugin_row_meta', 10, 2); +add_filter( 'plugin_row_meta', __NAMESPACE__ . '\\add_wooms_plugin_row_meta', 10, 2 ); -add_filter( "plugin_action_links_" . plugin_basename(__FILE__), function($links){ +add_filter( "plugin_action_links_" . plugin_basename( __FILE__ ), function ($links) { $mng_link = 'Управление'; $settings_link = 'Настройки'; - array_unshift($links, $mng_link); - array_unshift($links, $settings_link); - return $links; -}); + array_unshift( $links, $mng_link ); + array_unshift( $links, $settings_link ); + return $links; +} ); /** * сообщяем про то что Extra плагин более не актуален */ -add_action('after_plugin_row_wooms-extra/wooms-extra.php', function($data, $response){ +add_action( 'after_plugin_row_wooms-extra/wooms-extra.php', function ($data, $response) { - $wp_list_table = _get_list_table('WP_Plugins_List_Table'); + $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' ); printf( - '+ ' ', - $wp_list_table->get_column_count() + $wp_list_table->get_column_count() ); -}, 10, 2); -add_filter('wooms_xt_load', '__return_false'); +}, 10, 2 ); +add_filter( 'wooms_xt_load', '__return_false' ); /** * Add GettingStarted link in row meta at pligins list */ -function add_wooms_plugin_row_meta($links, $file) -{ - if (strpos($file, 'wooms.php') !== false) { - $new_links = array( - ' Руководство по началу работы', - 'Консультации', - 'Задачи', - ); - - $links = array_merge($links, $new_links); - } - - return $links; +function add_wooms_plugin_row_meta( $links, $file ) { + if ( strpos( $file, 'wooms.php' ) !== false ) { + $new_links = array( + 'Руководство по началу работы', + 'Консультации', + 'Задачи', + ); + + $links = array_merge( $links, $new_links ); + } + + return $links; } @@ -111,103 +110,113 @@ function add_wooms_plugin_row_meta($links, $file) * * @return void */ -function admin_styles() -{ - $admin_style = plugin_dir_url(__FILE__) . 'css/admin.css'; +function admin_styles() { + $admin_style = plugin_dir_url( __FILE__ ) . 'css/admin.css'; - wp_enqueue_style('wooms_styles', $admin_style, array()); + wp_enqueue_style( 'wooms_styles', $admin_style, array() ); } -function get_api_url($path){ +function get_api_url( $path ) { return $url = 'https://api.moysklad.ru/api/remap/1.2/' . $path; } -function request($path = '', $data = array(), $type = 'GET'){ - // https://api.moysklad.ru/api/remap/1.2/ - - - if (empty($path)) { - return false; - } - - if(str_contains($path, 'https://api.moysklad.ru/api/remap/1.2/')){ - $url = $path; - } else { - $url = 'https://api.moysklad.ru/api/remap/1.2/' . $path; - } - - - - //@link https://github.com/wpcraft-ru/wooms/issues/177 - $url = str_replace('product_id', 'product.id', $url); - $url = str_replace('store_id', 'store.id', $url); - $url = str_replace('consignment_id', 'consignment.id', $url); - $url = str_replace('variant_id', 'variant.id', $url); - $url = str_replace('productFolder_id', 'productFolder.id', $url); - - if (!empty($data) && 'GET' == $type) { - $type = 'POST'; - } - if ('GET' == $type) { - $data = null; - } else { - $data = json_encode($data); - } - - $args = array( - 'method' => $type, - 'timeout' => 45, - 'redirection' => 5, - 'headers' => array( - "Content-Type" => 'application/json;charset=utf-8', - "Accept-Encoding" => "gzip", - 'Authorization' => 'Basic ' . - base64_encode(get_option('woomss_login') . ':' . get_option('woomss_pass')), - ), - 'body' => $data, - ); - - $request = wp_remote_request($url, $args); - if (is_wp_error($request)) { - do_action( - 'wooms_logger_error', - $type = 'WooMS-Request', - $title = 'Ошибка REST API WP Error', - $desc = $request->get_error_message() - ); - - return false; - } - - if (empty($request['body'])) { - do_action( - 'wooms_logger_error', - $type = 'WooMS-Request', - $title = 'REST API вернулся без требуемых данных' - ); - - return false; - } - - $response = json_decode($request['body'], true); - - if (!empty($response["errors"]) and is_array($response["errors"])) { - foreach ($response["errors"] as $error) { - do_action( - 'wooms_logger_error', - $type = 'WooMS-Request', - $title = $url, - $response - ); - } - } - - return $response; +function request( $path = '', $data = array(), $type = 'GET' ) { + // https://api.moysklad.ru/api/remap/1.2/ + + + if ( empty ( $path ) ) { + return false; + } + + if ( str_contains( $path, 'https://api.moysklad.ru/api/remap/1.2/' ) ) { + $url = $path; + } else { + $url = 'https://api.moysklad.ru/api/remap/1.2/' . $path; + } + + + + //@link https://github.com/wpcraft-ru/wooms/issues/177 + $url = str_replace( 'product_id', 'product.id', $url ); + $url = str_replace( 'store_id', 'store.id', $url ); + $url = str_replace( 'consignment_id', 'consignment.id', $url ); + $url = str_replace( 'variant_id', 'variant.id', $url ); + $url = str_replace( 'productFolder_id', 'productFolder.id', $url ); + + if ( ! empty ( $data ) && 'GET' == $type ) { + $type = 'POST'; + } + if ( 'GET' == $type ) { + $data = null; + } else { + $data = json_encode( $data ); + } + + $args = array( + 'method' => $type, + 'timeout' => 45, + 'redirection' => 5, + 'headers' => array( + "Content-Type" => 'application/json;charset=utf-8', + "Accept-Encoding" => "gzip", + 'Authorization' => 'Basic ' . + base64_encode( get_option( 'woomss_login' ) . ':' . get_option( 'woomss_pass' ) ), + ), + 'body' => $data, + ); + + $request = wp_remote_request( $url, $args ); + if ( is_wp_error( $request ) ) { + do_action( + 'wooms_logger_error', + $type = 'WooMS-Request', + $title = 'Ошибка REST API WP Error', + $desc = $request->get_error_message() + ); + + return false; + } + + if ( empty ( $request['body'] ) ) { + do_action( + 'wooms_logger_error', + $type = 'WooMS-Request', + $title = 'REST API вернулся без требуемых данных' + ); + + return false; + } + + $response = json_decode( $request['body'], true ); + + if ( ! empty ( $response["errors"] ) and is_array( $response["errors"] ) ) { + foreach ( $response["errors"] as $error ) { + do_action( + 'wooms_logger_error', + $type = 'WooMS-Request', + $title = $url, + $response + ); + } + } + + return $response; } -function get_session_id(){ - return \WooMS\Products\get_session_id(); +function get_session_id() { + return \WooMS\Products\get_session_id(); } + +/** + * doc https://github.com/woocommerce/woocommerce/wiki/High-Performance-Order-Storage-Upgrade-Recipe-Book + * doc https://woo.com/document/high-performance-order-storage/ + * issue https://github.com/wpcraft-ru/wooms/issues/539 + */ +add_action( 'before_woocommerce_init', function () { + if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class) ) { + \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true ); + } +} );