get_host(), self::REPORTS_PATH ); if ( $path ) { $url .= '/' . ltrim( $path, '/' ); } return apply_filters( 'code_snippets_feedback_endpoint_url', $url, $path ); } /** * Retrieve the credential issued to this site. * * @return array Empty when this site has not enrolled. */ public function get_credentials(): array { $stored = get_option( self::CREDENTIALS_OPTION, [] ); return is_array( $stored ) ? $stored : []; } /** * Store the credential issued to this site. * * @param array $credentials Credential to store. * * @return void */ public function save_credentials( array $credentials ): void { update_option( self::CREDENTIALS_OPTION, $credentials, false ); } /** * Discard the credential issued to this site. * * @return void */ public function delete_credentials(): void { delete_option( self::CREDENTIALS_OPTION ); } /** * Determine whether a credential has the shape the cloud issues. * * @param array $credentials Credential to check. * * @return bool */ public function is_valid_credentials( array $credentials ): bool { return ! empty( $credentials['public_id'] ) && ! empty( $credentials['secret'] ) && preg_match( self::PUBLIC_ID_PATTERN, (string) $credentials['public_id'] ) && preg_match( self::SECRET_PATTERN, (string) $credentials['secret'] ); } /** * Create the headers common to every reporting request. * * @return array */ public function get_request_headers(): array { $headers = [ 'Content-Type' => 'application/json; charset=utf-8', 'Accept' => 'application/json', 'X-CS-Site' => site_url(), 'X-CS-Edition' => System_Info::get_edition(), ]; $key = $this->get_key(); if ( $key ) { $headers['Authorization'] = 'Bearer ' . $key; } return $headers; } /** * Create the headers proving a request came from this site. * * @param array $credentials Credential issued to this site. * @param string $method HTTP method. * @param string $uri Request path, including any query string. * @param string $body Raw request body, empty for a GET. * * @return array */ public function get_signature_headers( array $credentials, string $method, string $uri, string $body ): array { $offset = isset( $credentials['offset'] ) ? (int) $credentials['offset'] : 0; $timestamp = (string) ( time() + $offset ); $payload = $timestamp . '.' . strtoupper( $method ) . '.' . $uri . '.' . hash( 'sha256', $body ); return [ 'X-CS-Site-Id' => (string) $credentials['public_id'], 'X-CS-Timestamp' => $timestamp, 'X-CS-Signature' => hash_hmac( 'sha256', $payload, (string) $credentials['secret'] ), ]; } /** * Reduce a URL to the part a signature covers. * * @param string $url Absolute URL. * * @return string Path, followed by the query string when there is one. */ public static function get_request_uri( string $url ): string { $path = (string) wp_parse_url( $url, PHP_URL_PATH ); $query = wp_parse_url( $url, PHP_URL_QUERY ); return $query ? $path . '?' . $query : $path; } }