WP_REST_Server::READABLE, 'callback' => array( $this, 'preview' ), 'permission_callback' => '__return_true', 'args' => array( 'product_id' => array( 'type' => 'integer', 'required' => true, 'minimum' => 1, 'sanitize_callback' => 'absint', ), 'quantities' => array( 'description' => __( 'Comma-separated quantities, up to 10. Defaults to the product’s quantity breaks.', 'joinery-core' ), 'type' => 'string', 'default' => '', 'pattern' => '^[0-9,]{0,60}$', ), ), ) ); } /** * Prices for the product. * * @param WP_REST_Request $request Request. * @phpstan-param WP_REST_Request> $request * @return WP_REST_Response|WP_Error */ public function preview( WP_REST_Request $request ) { $product = wc_get_product( (int) $request['product_id'] ); if ( ! $product || 'publish' !== get_post_status( $product->get_parent_id() ? $product->get_parent_id() : $product->get_id() ) || ! $product->is_purchasable() ) { return new WP_Error( 'joinery_product_not_found', __( 'No product with that ID is for sale.', 'joinery-core' ), array( 'status' => 404 ) ); } $requested = array_slice( array_filter( array_map( 'absint', explode( ',', (string) $request['quantities'] ) ) ), 0, 10 ); if ( array() === $requested ) { $prices = $this->preview->breaks( $product ); } else { $prices = array_map( fn( int $quantity ): array => array( 'min_quantity' => min( $quantity, 100000 ), 'price' => $this->preview->unit_price( $product, min( $quantity, 100000 ) ), ), $requested ); } $regular = (float) $product->get_price( 'edit' ); return new WP_REST_Response( array( 'product_id' => $product->get_id(), 'currency_code' => get_woocommerce_currency(), 'currency_minor_unit' => wc_get_price_decimals(), 'regular_price' => Preview::minor_units( $regular ), 'prices' => array_map( static fn( array $row ): array => array( 'quantity' => $row['min_quantity'], 'price' => Preview::minor_units( $row['price'] ), 'percent_saving' => $regular > 0 ? round( ( 1 - $row['price'] / $regular ) * 100, 2 ) : 0, ), $prices ), ) ); } }