MarkitMall:

'; } /** * Apply a catalog product (from a webhook) to the local product: stock per * variant, and prices raised to the minimum if MarkitMall raised it. The * reseller's own title, description and higher prices are left alone. */ public static function apply_remote_product( WC_Product $product, array $remote ) { $by_variant = array(); foreach ( (array) $remote['variants'] as $v ) { $by_variant[ $v['id'] ] = $v; } $targets = $product->is_type( 'variable' ) ? array_map( 'wc_get_product', $product->get_children() ) : array( $product ); foreach ( $targets as $target ) { if ( ! $target ) { continue; } $vid = $target->get_meta( MARKITMALL_DS_META_VARIANT ); if ( ! $vid ) { continue; } if ( ! isset( $by_variant[ $vid ] ) ) { // The option was removed upstream. $target->set_stock_quantity( 0 ); $target->save(); continue; } $v = $by_variant[ $vid ]; $target->set_manage_stock( true ); $target->set_stock_quantity( max( 0, (int) $v['stock'] ) ); self::raise_to_floor( $target, isset( $v['minResalePrice'] ) ? (int) $v['minResalePrice'] : 0 ); MarkitMall_DS_Catalog::set_cost( $target, isset( $v['wholesalePrice'] ) ? $v['wholesalePrice'] : null ); $target->save(); } // MarkitMall started or stopped delivering it free. if ( isset( $remote['shipping'] ) ) { $free = MarkitMall_DS_Delivery::is_free( $remote ) ? 'yes' : 'no'; if ( $product->get_meta( MarkitMall_DS_Delivery::META_FREE ) !== $free ) { $product->update_meta_data( MarkitMall_DS_Delivery::META_FREE, $free ); $product->save(); } } if ( $product->is_type( 'variable' ) ) { WC_Product_Variable::sync( $product->get_id() ); } } /** Raise a price that fell below MarkitMall's minimum (never lower one). */ private static function raise_to_floor( WC_Product $target, $floor ) { if ( $floor > 0 && (float) $target->get_regular_price() < $floor ) { $target->set_regular_price( (string) $floor ); self::flag( sprintf( 'The minimum price of ā€œ%sā€ rose to Rs %s; your price was raised to match.', $target->get_name(), number_format_i18n( $floor ) ) ); return true; } return false; } /** Every product and variation carrying a MarkitMall variant id. */ private static function mapped_items() { global $wpdb; // Product meta is still post meta (HPOS moves orders only). $rows = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery $wpdb->prepare( "SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s", MARKITMALL_DS_META_VARIANT ) ); $map = array(); foreach ( (array) $rows as $row ) { $map[ (int) $row->post_id ] = (string) $row->meta_value; } return $map; } public static function reconcile() { if ( ! MarkitMall_DS_API::is_configured() ) { return; } $map = self::mapped_items(); $parents = array(); foreach ( array_chunk( $map, 100, true ) as $chunk ) { $result = MarkitMall_DS_API::get( '/inventory?ids=' . rawurlencode( implode( ',', array_unique( array_values( $chunk ) ) ) ) ); if ( is_wp_error( $result ) ) { return; // Try again at the next run. } $by_variant = array(); foreach ( (array) $result['data'] as $row ) { $by_variant[ $row['variantId'] ] = $row; } foreach ( $chunk as $post_id => $variant_id ) { $item = wc_get_product( $post_id ); if ( ! $item || ! isset( $by_variant[ $variant_id ] ) ) { continue; } $row = $by_variant[ $variant_id ]; $parent_id = $item->get_parent_id() ? $item->get_parent_id() : $item->get_id(); // A null productId: MarkitMall no longer has the product at all. $gone = empty( $row['productId'] ); $parents[ $parent_id ] = isset( $parents[ $parent_id ] ) ? $parents[ $parent_id ] && $gone : $gone; $stock = ! empty( $row['available'] ) ? max( 0, (int) $row['stock'] ) : 0; $changed = false; if ( (int) $item->get_stock_quantity() !== $stock || ! $item->get_manage_stock() ) { $item->set_manage_stock( true ); $item->set_stock_quantity( $stock ); $changed = true; } if ( ! $gone ) { $changed = self::raise_to_floor( $item, isset( $row['minResalePrice'] ) ? (int) $row['minResalePrice'] : 0 ) || $changed; $changed = MarkitMall_DS_Catalog::set_cost( $item, isset( $row['wholesalePrice'] ) ? $row['wholesalePrice'] : null ) || $changed; } if ( $changed ) { $item->save(); } } } foreach ( $parents as $parent_id => $gone ) { $product = wc_get_product( $parent_id ); if ( ! $product ) { continue; } if ( $gone && 'publish' === $product->get_status() ) { // No longer for sale: take it off the store rather than sell what cannot ship. $product->set_status( 'draft' ); $product->save(); self::flag( sprintf( 'ā€œ%sā€ is no longer available from MarkitMall and was unpublished.', $product->get_name() ) ); } elseif ( $product->is_type( 'variable' ) ) { WC_Product_Variable::sync( $parent_id ); } } self::backfill_free_delivery(); } /** * Products imported before free delivery was recorded: look each up on * MarkitMall once, 25 a run, so MarkitMall delivery charges them right. */ public static function backfill_free_delivery() { $ids = wc_get_products( array( 'limit' => 25, 'return' => 'ids', 'status' => array( 'publish', 'draft', 'pending', 'private' ), 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery array( 'key' => MARKITMALL_DS_META_PRODUCT, 'compare' => 'EXISTS', ), array( 'key' => MarkitMall_DS_Delivery::META_FREE, 'compare' => 'NOT EXISTS', ), ), ) ); foreach ( $ids as $id ) { $product = wc_get_product( $id ); $remote = MarkitMall_DS_API::get( '/catalog/products/' . rawurlencode( (string) $product->get_meta( MARKITMALL_DS_META_PRODUCT ) ) ); if ( is_wp_error( $remote ) ) { if ( 'not_found' !== $remote->get_error_code() ) { return; // MarkitMall unreachable: carry on next run. } $remote = array(); } $product->update_meta_data( MarkitMall_DS_Delivery::META_FREE, MarkitMall_DS_Delivery::is_free( $remote ) ? 'yes' : 'no' ); $product->save(); } } }