status = $status; $this->validation = $validation; } /** * Builds the exception from a marketplace error body. * * Marketplaces use shapes such as: {"error":{"status","title","detail","validation":[...]}} for API errors * and {"error":"invalid_grant","error_description":"..."} for OAuth errors. * * @param int $status HTTP status. * @param array|null $data Decoded body. */ public static function from_response( int $status, ?array $data ): self { $message = 'HTTP ' . $status; $validation = array(); $error = $data['error'] ?? null; if ( is_array( $error ) ) { $parts = array_filter( array( $error['title'] ?? '', $error['detail'] ?? '' ) ); $message = $parts ? implode( ': ', array_unique( $parts ) ) : $message; foreach ( (array) ( $error['validation'] ?? array() ) as $item ) { $validation[] = array( 'field' => (string) ( $item['field'] ?? '' ), 'title' => (string) ( $item['title'] ?? ( $item['detail'] ?? '' ) ), ); } } elseif ( is_string( $error ) ) { $message = $error . ( isset( $data['error_description'] ) ? ': ' . $data['error_description'] : '' ); } return new self( $status, $message, $validation ); } /** * HTTP status. */ public function status(): int { return $this->status; } /** * Validation errors. */ public function validation(): array { return $this->validation; } }