Add product image by SKU (#40076)
* add matching image by sku exp feature * attach featured image in rest api * add CSV import support * include changelog * update from feedback- move to products advanced settings * address phpcs * bump @since to 8.5.0 --------- Co-authored-by: Ron Rennick <ronald.rennick@automattic.com>
This commit is contained in:
parent
ce7572c8c5
commit
de774715bc
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Feature: set product image when image filename matches a product sku
|
|
@ -16,6 +16,7 @@ use Automattic\WooCommerce\Internal\Features\FeaturesController;
|
|||
use Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator;
|
||||
use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore;
|
||||
use Automattic\WooCommerce\Internal\ProductDownloads\ApprovedDirectories\Register as ProductDownloadDirectories;
|
||||
use Automattic\WooCommerce\Internal\ProductImage\MatchImageBySKU;
|
||||
use Automattic\WooCommerce\Internal\RegisterHooksInterface;
|
||||
use Automattic\WooCommerce\Internal\RestockRefundedItemsAdjuster;
|
||||
use Automattic\WooCommerce\Internal\Settings\OptionSanitizer;
|
||||
|
@ -256,6 +257,7 @@ final class WooCommerce {
|
|||
$container->get( AssignDefaultCategory::class );
|
||||
$container->get( DataRegenerator::class );
|
||||
$container->get( LookupDataStore::class );
|
||||
$container->get( MatchImageBySKU::class );
|
||||
$container->get( RestockRefundedItemsAdjuster::class );
|
||||
$container->get( CustomOrdersTableController::class );
|
||||
$container->get( OptionSanitizer::class );
|
||||
|
|
|
@ -302,7 +302,9 @@ abstract class WC_Product_Importer implements WC_Importer_Interface {
|
|||
protected function set_image_data( &$product, $data ) {
|
||||
// Image URLs need converting to IDs before inserting.
|
||||
if ( isset( $data['raw_image_id'] ) ) {
|
||||
$product->set_image_id( $this->get_attachment_id_from_url( $data['raw_image_id'], $product->get_id() ) );
|
||||
$attachment_id = $this->get_attachment_id_from_url( $data['raw_image_id'], $product->get_id() );
|
||||
$product->set_image_id( $attachment_id );
|
||||
wc_product_attach_featured_image( $attachment_id, $product );
|
||||
}
|
||||
|
||||
// Gallery image URLs need converting to IDs before inserting.
|
||||
|
|
|
@ -333,6 +333,7 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
|
|||
|
||||
if ( 0 === $index ) {
|
||||
$product->set_image_id( $attachment_id );
|
||||
wc_product_attach_featured_image( $attachment_id, $product );
|
||||
} else {
|
||||
$gallery[] = $attachment_id;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ use Automattic\Jetpack\Constants;
|
|||
use Automattic\WooCommerce\Proxies\LegacyProxy;
|
||||
use Automattic\WooCommerce\Utilities\ArrayUtil;
|
||||
use Automattic\WooCommerce\Utilities\NumberUtil;
|
||||
use Automattic\WooCommerce\Internal\ProductImage\MatchImageBySKU;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
|
@ -1656,3 +1657,45 @@ function wc_update_product_lookup_tables_rating_count_batch( $offset = 0, $limit
|
|||
}
|
||||
}
|
||||
add_action( 'wc_update_product_lookup_tables_rating_count_batch', 'wc_update_product_lookup_tables_rating_count_batch', 10, 2 );
|
||||
|
||||
/**
|
||||
* Attach product featured image. Use image filename to match a product sku when product is not provided.
|
||||
*
|
||||
* @since 8.5.0
|
||||
* @param int $attachment_id Media attachment ID.
|
||||
* @param WC_Product $product Optional product object.
|
||||
* @return void
|
||||
*/
|
||||
function wc_product_attach_featured_image( $attachment_id, $product = null ) {
|
||||
$attachment_post = get_post( $attachment_id );
|
||||
if ( ! $attachment_post ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( null === $product && wc_get_container()->get( MatchImageBySKU::class )->is_enabled() ) {
|
||||
// On upload the attachment post title is the uploaded file's filename.
|
||||
$file_name = pathinfo( $attachment_post->post_title, PATHINFO_FILENAME );
|
||||
if ( ! $file_name ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$product_id = wc_get_product_id_by_sku( $file_name );
|
||||
$product = wc_get_product( $product_id );
|
||||
}
|
||||
|
||||
if ( ! $product ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$product->set_image_id( $attachment_id );
|
||||
$product->save();
|
||||
if ( 0 === $attachment_post->post_parent ) {
|
||||
wp_update_post(
|
||||
array(
|
||||
'ID' => $attachment_id,
|
||||
'post_parent' => $product->get_id(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
add_action( 'add_attachment', 'wc_product_attach_featured_image' );
|
||||
|
|
|
@ -22,6 +22,7 @@ use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\Option
|
|||
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\OrderAttributionServiceProvider;
|
||||
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\ProductAttributesLookupServiceProvider;
|
||||
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\ProductDownloadsServiceProvider;
|
||||
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\ProductImageBySKUServiceProvider;
|
||||
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\ProductReviewsServiceProvider;
|
||||
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\ProxiesServiceProvider;
|
||||
use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\RestockRefundedItemsAdjusterServiceProvider;
|
||||
|
@ -59,6 +60,7 @@ final class Container {
|
|||
OrdersDataStoreServiceProvider::class,
|
||||
ProductAttributesLookupServiceProvider::class,
|
||||
ProductDownloadsServiceProvider::class,
|
||||
ProductImageBySKUServiceProvider::class,
|
||||
ProductReviewsServiceProvider::class,
|
||||
ProxiesServiceProvider::class,
|
||||
RestockRefundedItemsAdjusterServiceProvider::class,
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/**
|
||||
* ProductImageBySKUServiceProvider class file.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders;
|
||||
|
||||
use Automattic\WooCommerce\Internal\DependencyManagement\AbstractServiceProvider;
|
||||
use Automattic\WooCommerce\Internal\ProductImage\MatchImageBySKU;
|
||||
|
||||
/**
|
||||
* Service provider for the ProductImageBySKUServiceProvider namespace.
|
||||
*/
|
||||
class ProductImageBySKUServiceProvider extends AbstractServiceProvider {
|
||||
|
||||
/**
|
||||
* The classes/interfaces that are serviced by this service provider.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $provides = array(
|
||||
MatchImageBySKU::class,
|
||||
);
|
||||
|
||||
/**
|
||||
* Register the classes.
|
||||
*/
|
||||
public function register() {
|
||||
$this->share( MatchImageBySKU::class );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
/**
|
||||
* MatchImageBySKU class file.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Internal\ProductImage;
|
||||
|
||||
use Automattic\WooCommerce\Internal\Traits\AccessiblePrivateMethods;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Class for the product image matching by SKU.
|
||||
*/
|
||||
class MatchImageBySKU {
|
||||
|
||||
use AccessiblePrivateMethods;
|
||||
|
||||
/**
|
||||
* The name of the setting for this feature.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $setting_name = 'woocommerce_product_match_featured_image_by_sku';
|
||||
|
||||
/**
|
||||
* MatchImageBySKU constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->init_hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the hooks used by the class.
|
||||
*/
|
||||
private function init_hooks() {
|
||||
self::add_filter( 'woocommerce_get_settings_products', array( $this, 'add_product_image_sku_setting' ), 110, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this feature enabled.
|
||||
*
|
||||
* @since 8.3.0
|
||||
* @return bool
|
||||
*/
|
||||
public function is_enabled() {
|
||||
return wc_string_to_bool( get_option( $this->setting_name ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for 'woocommerce_get_settings_products', adds the settings related to the product image SKU matching table.
|
||||
*
|
||||
* @param array $settings Original settings configuration array.
|
||||
* @param string $section_id Settings section identifier.
|
||||
* @return array New settings configuration array.
|
||||
*/
|
||||
private function add_product_image_sku_setting( array $settings, string $section_id ): array {
|
||||
if ( 'advanced' !== $section_id ) {
|
||||
return $settings;
|
||||
}
|
||||
|
||||
$settings[] = array(
|
||||
'title' => __( 'Product image matching by SKU', 'woocommerce' ),
|
||||
'type' => 'title',
|
||||
);
|
||||
|
||||
$settings[] = array(
|
||||
'title' => __( 'Match images', 'woocommerce' ),
|
||||
'desc' => __( 'Set product featured image when uploaded image file name matches product SKU.', 'woocommerce' ),
|
||||
'id' => $this->setting_name,
|
||||
'default' => 'no',
|
||||
'type' => 'checkbox',
|
||||
'checkboxgroup' => 'start',
|
||||
);
|
||||
|
||||
$settings[] = array( 'type' => 'sectionend' );
|
||||
|
||||
return $settings;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue