# woocommerce-pos/1.10.17/includes/API/V1/Bulk_ID_Fast_Path.php

WCPOS – Point of Sale (POS) plugin for WooCommerce, version 1.10.17. 263 lines.

- Page: https://pluginprobe.com/plugins/woocommerce-pos/1.10.17/code/includes/API/V1/Bulk_ID_Fast_Path.php
- Raw: https://pluginprobe.com/plugins/woocommerce-pos/1.10.17/raw/includes/API/V1/Bulk_ID_Fast_Path.php
- Modified: 2026-08-25T07:52:20+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/woocommerce-pos/1.10.17/code/includes/API/V1/Bulk_ID_Fast_Path.php#L10-L20`.

```php
<?php
/**
 * Bulk ID fast path helpers.
 *
 * @package WCPOS\WooCommercePOS
 */

namespace WCPOS\WooCommercePOS\API\V1;

\defined( 'ABSPATH' ) || die;

use WCPOS\WooCommercePOS\Logger;
use WP_Error;
use WP_REST_Request;

/**
 * Shared mechanics for the POS offline-sync bulk-ID fast path.
 *
 * Controllers still own the entity-specific data source. This class owns the
 * shallow mechanics that were duplicated across those implementations: request
 * shape detection, id-list filtering, modified-after parsing, and response
 * headers.
 */
class Bulk_ID_Fast_Path {
	/**
	 * Determine whether the request is the supported bulk-ID fast-path shape.
	 *
	 * @param WP_REST_Request $request Request object.
	 *
	 * @return bool
	 */
	public static function supports_request( WP_REST_Request $request ): bool {
		if ( -1 !== (int) $request->get_param( 'posts_per_page' ) ) {
			return false;
		}

		$fields = $request->get_param( 'fields' );

		return 'id' === $fields
			|| (
				\is_array( $fields )
				&& ( array( 'id' ) === $fields || array( 'id', 'date_modified_gmt' ) === $fields )
			);
	}

	/**
	 * Determine whether the caller requested date_modified_gmt.
	 *
	 * @param WP_REST_Request $request Request object.
	 *
	 * @return bool
	 */
	public static function wants_modified_date( WP_REST_Request $request ): bool {
		return array( 'id', 'date_modified_gmt' ) === $request->get_param( 'fields' );
	}

	/**
	 * Build a select list for an id column and optional modified-date column.
	 *
	 * @param WP_REST_Request $request         Request object.
	 * @param string          $id_column       SQL id column/expression.
	 * @param string|null     $modified_column SQL modified-date column/expression.
	 *
	 * @return string
	 */
	public static function select_fields( WP_REST_Request $request, string $id_column, ?string $modified_column = null ): string {
		if ( self::wants_modified_date( $request ) && null !== $modified_column ) {
			return "{$id_column} as id, {$modified_column} as date_modified_gmt";
		}

		return "{$id_column} as id";
	}

	/**
	 * Append wcpos_include/wcpos_exclude filters to a SQL statement.
	 *
	 * @param string          $sql       Existing SQL statement.
	 * @param WP_REST_Request $request   Request object.
	 * @param string          $id_column SQL id column/expression.
	 *
	 * @return string
	 */
	public static function append_id_filters_sql( string $sql, WP_REST_Request $request, string $id_column ): string {
		global $wpdb;

		$include_ids = self::id_list_from_request( $request, 'wcpos_include' );
		if ( ! empty( $include_ids ) ) {
			$ids_format = implode( ',', array_fill( 0, \count( $include_ids ), '%d' ) );
			$sql       .= self::sql_conjunction( $sql ) . $wpdb->prepare( "{$id_column} IN ($ids_format)", $include_ids ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- placeholders are generated by array_fill and the column is caller-owned SQL.
		}

		$exclude_ids = self::id_list_from_request( $request, 'wcpos_exclude' );
		if ( ! empty( $exclude_ids ) ) {
			$ids_format = implode( ',', array_fill( 0, \count( $exclude_ids ), '%d' ) );
			$sql       .= self::sql_conjunction( $sql ) . $wpdb->prepare( "{$id_column} NOT IN ($ids_format)", $exclude_ids ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- placeholders are generated by array_fill and the column is caller-owned SQL.
		}

		return $sql;
	}

	/**
	 * Apply wcpos_include/wcpos_exclude to WP query arguments that support include/exclude.
	 *
	 * @param array           $args    Query arguments.
	 * @param WP_REST_Request $request Request object.
	 *
	 * @return array
	 */
	public static function apply_id_filters_to_args( array $args, WP_REST_Request $request ): array {
		$include_ids = self::id_list_from_request( $request, 'wcpos_include' );
		$exclude_ids = self::id_list_from_request( $request, 'wcpos_exclude' );
		if ( ! empty( $include_ids ) ) {
			$args['include'] = ! empty( $exclude_ids )
				? array_values( array_diff( $include_ids, $exclude_ids ) )
				: $include_ids;
			if ( empty( $args['include'] ) ) {
				$args['include'] = array( 0 );
			}
		} elseif ( ! empty( $exclude_ids ) ) {
			$args['exclude'] = $exclude_ids;
		}

		return $args;
	}

	/**
	 * Get the modified_after value as a Unix timestamp.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @param bool            $strict  Whether invalid dates should return a WP_Error.
	 *
	 * @return int|null|WP_Error
	 */
	public static function modified_after_timestamp( WP_REST_Request $request, bool $strict = false ) {
		$modified_after = $request->get_param( 'modified_after' );
		if ( ! $modified_after ) {
			return null;
		}

		$timestamp = strtotime( $modified_after );
		if ( false === $timestamp ) {
			if ( $strict ) {
				return new WP_Error(
					'woocommerce_pos_rest_invalid_modified_after',
					'Invalid modified_after parameter.',
					array( 'status' => 400 )
				);
			}

			return 0;
		}

		return $timestamp;
	}

	/**
	 * Get the modified_after value in MySQL GMT datetime format.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @param bool            $strict  Whether invalid dates should return a WP_Error.
	 *
	 * @return string|null|WP_Error
	 */
	public static function modified_after_gmt( WP_REST_Request $request, bool $strict = false ) {
		$timestamp = self::modified_after_timestamp( $request, $strict );
		if ( null === $timestamp || is_wp_error( $timestamp ) ) {
			return $timestamp;
		}

		return gmdate( 'Y-m-d H:i:s', (int) $timestamp );
	}

	/**
	 * Convert a list of ids into fast-path response rows.
	 *
	 * @param array $ids ID list.
	 *
	 * @return array
	 */
	public static function rows_from_ids( array $ids ): array {
		return array_map(
			static function ( $id ): array {
				return array( 'id' => (int) $id );
			},
			$ids
		);
	}

	/**
	 * Build a REST response with the fast-path headers.
	 *
	 * @param object $controller Controller that uses WCPOS_REST_API.
	 * @param array  $results    Response rows.
	 * @param float  $start_time Request start time.
	 * @param bool   $format     Whether to run wcpos_format_all_posts_response().
	 *
	 * @return \WP_REST_Response
	 */
	public static function response( $controller, array $results, float $start_time, bool $format = true ) {
		$formatted_results = $format ? $controller->wcpos_format_all_posts_response( $results ) : $results;
		$total             = \count( $formatted_results );
		$execution_time    = microtime( true ) - $start_time;
		$execution_time_ms = number_format( $execution_time * 1000, 2 );
		$server_load       = $controller->get_server_load();

		$response = rest_ensure_response( $formatted_results );
		$response->header( 'X-WP-Total', (string) $total );
		$response->header( 'X-Execution-Time', $execution_time_ms . ' ms' );
		$response->header( 'X-Server-Load', json_encode( $server_load ) );

		return $response;
	}

	/**
	 * Build the common fast-path fetch failure response.
	 *
	 * @param string $log_message    Message to write to the logger.
	 * @param string $public_message Message returned to API clients.
	 *
	 * @return WP_Error
	 */
	public static function fetch_error( string $log_message, string $public_message ): WP_Error {
		Logger::log( $log_message );

		return new WP_Error(
			'woocommerce_pos_rest_cannot_fetch',
			$public_message,
			array( 'status' => 500 )
		);
	}

	/**
	 * Parse a request id-list parameter.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @param string          $param   Parameter name.
	 *
	 * @return array<int,int>
	 */
	private static function id_list_from_request( WP_REST_Request $request, string $param ): array {
		$value = $request->get_param( $param );
		if ( empty( $value ) ) {
			return array();
		}

		$ids = \is_array( $value ) ? $value : explode( ',', (string) $value );
		$ids = array_filter( array_map( 'absint', $ids ) );

		return array_values( array_unique( $ids ) );
	}

	/**
	 * Return the next SQL conjunction for appending where predicates.
	 *
	 * @param string $sql Existing SQL statement.
	 *
	 * @return string
	 */
	private static function sql_conjunction( string $sql ): string {
		return false === stripos( $sql, ' where ' ) ? ' WHERE ' : ' AND ';
	}
}

```
