WC_Cart_Session::populate_cart_from_orderprivateWC 3.5.0

Get a cart from an order, if user has permission.

Method of the class: WC_Cart_Session{}

Returns

Array.

Usage

// private - for code of main (parent) class only
$result = $this->populate_cart_from_order( $order_id, $cart );
$order_id(int) (required)
Order ID to try to load.
$cart(array) (required)
Current cart array.

Changelog

Since 3.5.0 Introduced.

WC_Cart_Session::populate_cart_from_order() code WC 10.7.0

private function populate_cart_from_order( $order_id, $cart ) {
	$order = wc_get_order( $order_id );

	/**
	 * Filter the valid order statuses for reordering.
	 *
	 * @since 3.6.0
	 *
	 * @param array $valid_statuses Array of valid order statuses.
	 */
	$valid_statuses = apply_filters( 'woocommerce_valid_order_statuses_for_order_again', array( OrderStatus::COMPLETED ) );
	if ( ! $order->get_id() || ! $order->has_status( $valid_statuses ) || ! current_user_can( 'order_again', $order->get_id() ) ) {
		return;
	}

	if ( apply_filters( 'woocommerce_empty_cart_when_order_again', true ) ) {
		$cart = array();
	}

	$inital_cart_size = count( $cart );
	$order_items      = $order->get_items();

	foreach ( $order_items as $item ) {
		$product_id     = (int) apply_filters( 'woocommerce_add_to_cart_product_id', $item->get_product_id() );
		$quantity       = $item->get_quantity();
		$variation_id   = (int) $item->get_variation_id();
		$variations     = array();
		$cart_item_data = apply_filters( 'woocommerce_order_again_cart_item_data', array(), $item, $order );
		$product        = $item->get_product();

		if ( ! $product ) {
			continue;
		}

		// Prevent reordering variable products if no selected variation.
		if ( ! $variation_id && $product->is_type( ProductType::VARIABLE ) ) {
			continue;
		}

		// Prevent reordering items specifically out of stock.
		if ( ! $product->is_in_stock() ) {
			continue;
		}

		foreach ( $item->get_meta_data() as $meta ) {
			if ( taxonomy_is_product_attribute( $meta->key ) || meta_is_product_attribute( $meta->key, $meta->value, $product_id ) ) {
				$attribute_key = 'attribute_' . sanitize_title( $meta->key );
				if ( taxonomy_is_product_attribute( $meta->key ) ) {
					$variations[ $attribute_key ] = sanitize_title( $meta->value );
				} else {
					$variations[ $attribute_key ] = html_entity_decode( wc_clean( $meta->value ), ENT_QUOTES, get_bloginfo( 'charset' ) );
				}
			}
		}

		if ( ! apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variations, $cart_item_data ) ) {
			continue;
		}

		$product_data = wc_get_product( $variation_id ? $variation_id : $product_id );
		if ( $product_data instanceof WC_Product && $product_data->is_sold_individually() ) {
			// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment -- Filter documented in CartController::validate_add_to_cart().
			$quantity = apply_filters( 'woocommerce_add_to_cart_sold_individually_quantity', 1, $quantity, $product_id, $variation_id, $cart_item_data );

			$cart_id = WC()->cart->generate_cart_id( $product_id, $variation_id, $variations, $cart_item_data );
			// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment -- Filter first added in WC_Cart::add_to_cart(), add documentation there.
			$found_in_cart = apply_filters( 'woocommerce_add_to_cart_sold_individually_found_in_cart', isset( $cart[ $cart_id ] ) && isset( $cart[ $cart_id ]['quantity'] ) && $cart[ $cart_id ]['quantity'] > 0, $product_id, $variation_id, $cart_item_data, $cart_id );
			if ( $found_in_cart ) {
				/* translators: %s: product name */
				$message = sprintf( __( 'You cannot add another "%s" to your cart.', 'woocommerce' ), $product_data->get_name() );
				// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment -- Filter documented in WC_Cart::add_to_cart().
				$message         = apply_filters( 'woocommerce_cart_product_cannot_add_another_message', $message, $product_data );
				$wp_button_class = wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '';
				$message         = sprintf( '%s <a href="%s" class="button wc-forward%s">%s</a>', $message, esc_url( wc_get_cart_url() ), esc_attr( $wp_button_class ), __( 'View cart', 'woocommerce' ) );
				wc_add_notice( $message, 'error' );
				continue;
			}
		}

		// Add to cart directly.
		$cart_id          = WC()->cart->generate_cart_id( $product_id, $variation_id, $variations, $cart_item_data );
		$product_data     = wc_get_product( $variation_id ? $variation_id : $product_id );
		$cart[ $cart_id ] = apply_filters(
			'woocommerce_add_order_again_cart_item',
			array_merge(
				$cart_item_data,
				array(
					'key'          => $cart_id,
					'product_id'   => $product_id,
					'variation_id' => $variation_id,
					'variation'    => $variations,
					'quantity'     => $quantity,
					'data'         => $product_data,
					'data_hash'    => wc_get_cart_item_data_hash( $product_data ),
				)
			),
			$cart_id
		);
	}

	do_action_ref_array( 'woocommerce_ordered_again', array( $order->get_id(), $order_items, &$cart ) );

	$num_items_in_cart           = count( $cart );
	$num_items_in_original_order = count( $order_items );
	$num_items_added             = $num_items_in_cart - $inital_cart_size;

	if ( $num_items_in_original_order > $num_items_added ) {
		wc_add_notice(
			sprintf(
				/* translators: %d item count */
				_n(
					'%d item from your previous order is currently unavailable and could not be added to your cart.',
					'%d items from your previous order are currently unavailable and could not be added to your cart.',
					$num_items_in_original_order - $num_items_added,
					'woocommerce'
				),
				$num_items_in_original_order - $num_items_added
			),
			'error'
		);
	}

	if ( 0 < $num_items_added ) {
		wc_add_notice( __( 'The cart has been filled with the items from your previous order.', 'woocommerce' ) );
	}

	return $cart;
}