$id, 'status' => $status, ); } /** * @return array{product: array, variations: array, seo: array{title: string, description: string, source: string}} * @throws \RuntimeException When WooCommerce does not answer 200 for the product or its variations. */ public static function build( int $id, SeoAdapter $seo ): array { $product = array( 'data' => self::product( $id ) ); $variations = array(); if ( ! empty( $product['data']['variations'] ) ) { $page = 1; do { $response = self::get( '/wc/v3/products/' . $id . '/variations', array( 'per_page' => self::VARIATIONS_PER_PAGE, 'page' => $page, ) ); $variations = array_merge( $variations, array_values( (array) $response['data'] ) ); $pages = (int) ( $response['headers']['X-WP-TotalPages'] ?? 1 ); ++$page; } while ( $page <= $pages ); } $fields = $seo->get( $id ); return array( 'product' => (array) $product['data'], 'variations' => $variations, 'seo' => array( 'title' => $fields['title'], 'description' => $fields['description'], 'source' => $seo->id(), ), ); } /** * The product as the catalog push sends it: wc/v3, view context, as the current user. * * @return array * @throws \RuntimeException When WooCommerce does not answer 200. */ public static function product( int $id ): array { return (array) self::get( '/wc/v3/products/' . $id, array() )['data']; } /** * @param array $query Query params. * @return array{data: mixed, headers: array} * @throws \RuntimeException When the answer is not 200. */ private static function get( string $route, array $query ): array { $request = new \WP_REST_Request( 'GET', $route ); $request->set_query_params( $query ); $response = rest_do_request( $request ); if ( 200 !== $response->get_status() ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception message for logs, not rendered output. throw new \RuntimeException( sprintf( 'GET %s answered HTTP %d', $route, $response->get_status() ) ); } return array( 'data' => rest_get_server()->response_to_data( $response, false ), 'headers' => $response->get_headers(), ); } }