WC_Admin_Duplicate_Product::generate_unique_skuprivateWC 10.5.0

Generates a unique sku for a given product.

Method of the class: WC_Admin_Duplicate_Product{}

Returns

null. Nothing (null).

Usage

// private - for code of main (parent) class only
$result = $this->generate_unique_sku( $product );
$product(WC_Product) (required)
The product to generate a sku for.

Changelog

Since 10.5.0 Introduced.

WC_Admin_Duplicate_Product::generate_unique_sku() code WC 10.7.0

private function generate_unique_sku( $product ) {
	global $wpdb;

	// We want to remove the suffix from the sku so that we can find the maximum suffix using this root sku.
	// This will allow us to find the next-highest suffix that is unique. While this does not support gap
	// filling, this shouldn't matter for our use-case.
	$root_sku = preg_replace( '/-[0-9]+$/', '', $product->get_sku() );

	// If the parent product has no SKU, don't do anything.
	if ( ! $root_sku ) {
		return;
	}

	$existing_skus = $wpdb->get_col(
		$wpdb->prepare(
			"SELECT lookup.sku
				FROM {$wpdb->posts} as posts
				INNER JOIN {$wpdb->wc_product_meta_lookup} AS lookup ON posts.ID = lookup.product_id
				WHERE posts.post_type IN ( 'product', 'product_variation' )
				AND lookup.sku LIKE %s",
			$wpdb->esc_like( $root_sku ) . '%'
		)
	);

	// The sku is already unique!
	if ( empty( $existing_skus ) ) {
		$product->set_sku( $root_sku );
		return;
	}

	// Find the maximum suffix so we can ensure uniqueness.
	$max_suffix = 0;
	foreach ( $existing_skus as $existing_sku ) {
		// Pull a numerical suffix off the sku after the last hyphen.
		$suffix = intval( substr( $existing_sku, strrpos( $existing_sku, '-', -1 ) + 1 ) );
		if ( $suffix > $max_suffix ) {
			$max_suffix = $suffix;
		}
	}

	// We set a limit of SKUs to try in order to avoid infinite loops.
	$limit      = $max_suffix + 100;
	$product_id = $product->get_id();

	while ( $max_suffix < $limit ) {
		$new_sku = $root_sku . '-' . ( $max_suffix + 1 );

		/**
		 * Gives plugins an opportunity to verify SKU uniqueness themselves. Filter added to keep backwards
		 * compatibility with `wc_product_has_unique_sku()`.
		 * See: https://github.com/woocommerce/woocommerce/pull/62628
		 *
		 * @since 10.5.0
		 *
		 * @param bool|null $has_unique_sku Set to a boolean value to short-circuit the default SKU check.
		 * @param int $product_id The ID of the current product.
		 * @param string $sku The SKU to check for uniqueness.
		 */
		$pre_has_unique_sku = apply_filters( 'wc_product_pre_has_unique_sku', true, $product_id, $new_sku );

		if ( $pre_has_unique_sku ) {
			/**
			 * Gives plugins an opportunity to verify SKU uniqueness themselves. Filter added to keep backwards
			 * compatibility with `wc_product_has_unique_sku()`.
			 * See: https://github.com/woocommerce/woocommerce/pull/62628
			 *
			 * @since 10.5.0
			 *
			 * @param bool|null $sku_found Set to a boolean value to short-circuit the default SKU check.
			 * @param int $product_id The ID of the current product.
			 * @param string $sku The SKU to check for uniqueness.
			 */
			$sku_found = apply_filters( 'wc_product_has_unique_sku', false, $product_id, $new_sku );

			if ( ! $sku_found ) {
				$product->set_sku( $new_sku );
				return;
			}
		}
		++$max_suffix;
	}
}