Automattic\WooCommerce\Internal\Products

ProductsOrderingMoveService::move │ public │ WC 11.2.0

Moves a product to the position between $previous_id and $next_id, triggering a full reindex first if positions are uninitialized or colliding. Indexed positions start at 1; menu_order = 0 is the sentinel for an unindexed product.

Designed for an HVM with 500K+ products catalog operating in a clustered environment. To satisfy this setup:

  • if on-the-spot re-indexing is triggered: see design notes in \Automattic\WooCommerce\Internal\Products\ProductsOrderingReindexService::reindex_products
  • otherwise, the move takes 5 SQLs for any catalog size (4 of them PK-driven, hence nearly instant; operating on the targeted range of positions)

Метод класса: ProductsOrderingMoveService{}

Хуков нет.

Возвращает

object{ moved:array<int,int>, reindexed:array<int,int> }.

Использование

$ProductsOrderingMoveService = new ProductsOrderingMoveService();
$ProductsOrderingMoveService->move( $previous_id, $product_id, $next_id ): object;
$previous_id(int) (обязательный)
ID of the product immediately before the target position, or 0 when moving to the start.
$product_id(int) (обязательный)
ID of the product being repositioned.
$next_id(int) (обязательный)
ID of the product immediately after the target position, or 0 when moving to the end.

Список изменений

С версии 11.2.0 Введена.

Код ProductsOrderingMoveService::move() WC 11.2.2

public function move( int $previous_id, int $product_id, int $next_id ): object {
	$result = array(
		'moved'     => array(),
		'reindexed' => array(),
	);

	$anchor_positions = $this->compose_anchor_positions( $previous_id, $product_id, $next_id );
	if ( ! $this->has_moved( $anchor_positions, $previous_id, $product_id, $next_id ) ) {
		return (object) $result;
	}

	// Re-indexing is required when: a position collision is detected or moving between groups one of which is unindexed.
	$map              = $this->compose_move_map( $previous_id, $product_id, $next_id, $anchor_positions );
	$needs_reindexing = $map->old_position === $map->new_position || 0 === $map->new_position || 0 === $map->old_position;
	$needs_reindexing = $needs_reindexing || count( array_unique( $anchor_positions ) ) !== count( $anchor_positions );
	if ( $needs_reindexing ) {
		$result['reindexed'] = $this->reindex_service->reindex_products();

		$anchor_positions = $this->compose_anchor_positions( $previous_id, $product_id, $next_id );
		$map              = $this->compose_move_map( $previous_id, $product_id, $next_id, $anchor_positions );
		if ( ! $this->has_moved( $anchor_positions, $previous_id, $product_id, $next_id ) ) {
			return (object) $result;
		}
	}

	$result['moved'] = $this->apply( $map, $result['reindexed'] );
	// Deduct the move related modification from re-indexing to de-duplicate change events in outside workflow.
	foreach ( $result['moved'] as $id => $position ) {
		unset( $result['reindexed'][ $id ] );
	}

	return (object) $result;
}