WC_Abstract_Order::save_items │ protected │ WC 1.0

Save all order items which are part of this order.

Method of the class: WC_Abstract_Order{}

Hooks from the method

Returns

void. Nothing (null).

Usage

// protected - for code of main (parent) or child class
$result = $this->save_items();

WC_Abstract_Order::save_items() code WC 11.2.2

protected function save_items() {
	$items_changed = false;

	if ( $this->bulk_delete_all_items_pending ) {
		$this->delete_items_by_ids( $this->item_ids_to_bulk_delete );
		$this->bulk_delete_all_items_pending   = false;
		$this->item_ids_to_bulk_delete_by_type = array();
		$this->item_ids_to_bulk_delete         = array();
		$this->item_types_to_bulk_delete       = array();
		$items_changed                         = true;

		/**
		 * Trigger action after removing all order line items from the database.
		 *
		 * @param  WC_Order  $this  The current order object.
		 * @param  string|null $type Order item type. Default null.
		 *
		 * @since 7.8.0
		 */
		do_action( 'woocommerce_removed_order_items', $this, null );
	} elseif ( ! empty( $this->item_types_to_bulk_delete ) ) {
		// Drain the queue one type at a time, dropping each entry only after item deletion succeeds.
		// If a delete or hook callback throws, save()'s catch handles it and any types that have not
		// yet been processed remain queued for the next save() rather than being silently lost.
		foreach ( array_values( array_unique( $this->item_types_to_bulk_delete ) ) as $type ) {
			$item_ids = $this->item_ids_to_bulk_delete_by_type[ $type ] ?? array();
			$this->delete_items_by_ids( $item_ids );
			unset( $this->item_ids_to_bulk_delete_by_type[ $type ] );
			$items_changed                   = true;
			$this->item_types_to_bulk_delete = array_values(
				array_filter(
					$this->item_types_to_bulk_delete,
					static function ( $pending ) use ( $type ) {
						return $pending !== $type;
					}
				)
			);

			/**
			 * This action is documented above.
			 *
			 * @since 7.8.0
			 */
			do_action( 'woocommerce_removed_order_items', $this, $type );
		}//end foreach
	}//end if

	foreach ( $this->items_to_delete as $item ) {
		$item->delete();
		$items_changed = true;
	}
	$this->items_to_delete = array();

	// Add/save items.
	foreach ( $this->items as $item_group => $items ) {
		if ( is_array( $items ) ) {
			$items = array_filter( $items );
			foreach ( $items as $item_key => $item ) {
				$item->set_order_id( $this->get_id() );

				$item_id = $item->save();

				// If ID changed (new item saved to DB)...
				if ( $item_id !== $item_key ) {
					$this->items[ $item_group ][ $item_id ] = $item;

					unset( $this->items[ $item_group ][ $item_key ] );

					$items_changed = true;
				}
			}
		}
	}

	if ( $items_changed ) {
		wp_cache_delete( 'order-needs-processing-' . $this->get_id(), 'orders' );

		// Invalidate the order cache to prevent stale item data.
		// This fixes a race condition where get_items() may have been called
		// before items were saved, caching empty items arrays.
		// See https://github.com/woocommerce/woocommerce/issues/62173.
		if ( OrderUtil::orders_cache_usage_is_enabled() ) {
			wc_get_container()->get( OrderCache::class )->remove( $this->get_id() );
		}
	}
}