$query The query arguments to send to the remote API. * @throws UnexpectedValueException If the endpoint constant is not defined. * @throws UnexpectedValueException If the query filter constant is not defined. * @return string */ public function get_api_url( array $query ): string { $this->validate_required_constraints(); $query['apikey'] = $this->parsely->get_site_id(); if ( $this->parsely->api_secret_is_set() ) { $query['secret'] = $this->parsely->get_api_secret(); } $query = array_filter( $query ); // Sort by key so the query args are in alphabetical order. ksort( $query ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound -- Hook names are defined in child classes. $query = apply_filters( static::QUERY_FILTER, $query ); return add_query_arg( $query, static::API_BASE_URL . static::ENDPOINT ); } /** * Gets items from the specified endpoint. * * @since 3.2.0 * @since 3.7.0 Added $associative param. * * @param array $query The query arguments to send to the remote API. * @param bool $associative When TRUE, returned objects will be converted into associative arrays. * @return array|object|WP_Error */ public function get_items( array $query, bool $associative = false ) { $full_api_url = $this->get_api_url( $query ); /** * GET request options. * * @var WP_HTTP_Request_Args $options */ $options = $this->get_request_options(); $response = wp_safe_remote_get( $full_api_url, $options ); if ( is_wp_error( $response ) ) { return $response; } $body = wp_remote_retrieve_body( $response ); $decoded = json_decode( $body ); if ( ! is_object( $decoded ) ) { return new WP_Error( 400, __( 'Unable to decode upstream API response', 'wp-parsely' ) ); } if ( ! property_exists( $decoded, 'data' ) ) { return new WP_Error( $decoded->code ?? 400, $decoded->message ?? __( 'Unable to read data from upstream API', 'wp-parsely' ) ); } if ( ! is_array( $decoded->data ) ) { return new WP_Error( 400, __( 'Unable to parse data from upstream API', 'wp-parsely' ) ); } $data = $decoded->data; return $associative ? convert_to_associative_array( $data ) : $data; } /** * Returns the request's options for the remote API call. * * @since 3.9.0 * * @return array The array of options. */ public function get_request_options(): array { return array(); } /** * Validates that required constants are defined. * * @since 3.14.0 * * @throws UnexpectedValueException If any required constant is not defined. */ protected function validate_required_constraints(): void { if ( static::ENDPOINT === '' ) { throw new UnexpectedValueException( 'ENDPOINT constant must be defined in child class.' ); } if ( static::QUERY_FILTER === '' ) { throw new UnexpectedValueException( 'QUERY_FILTER constant must be defined in child class.' ); } } }