'GET', 'callback' => array( $this, 'show' ), 'permission_callback' => static fn(): bool => current_user_can( Capabilities::VIEW_FINDINGS ), ) ); register_rest_route( Api::NAMESPACE, '/speed/key', array( 'methods' => 'POST', 'callback' => array( $this, 'save_key' ), 'permission_callback' => static fn(): bool => current_user_can( Capabilities::MANAGE_SETTINGS ), 'args' => array( 'key' => array( 'type' => 'string', 'default' => '', ), ), ) ); } /** * The owner's own key, '' when none is saved. */ public static function own_key(): string { $locked = get_option( self::KEY, '' ); return is_string( $locked ) && '' !== $locked ? Vault::default()->unlock( $locked ) : ''; } /** * Whether the text looks like a Google API key. * * @param string $key Key. */ public static function valid_key( string $key ): bool { return 1 === preg_match( '/^[A-Za-z0-9_-]{30,60}$/', $key ); } /** * How the browser runs a test: the own key, or the address to send it to on forensix.digital. * * @return array */ public static function present(): array { $key = self::own_key(); $proxy = array( 'url' => self::PROXY, 'site' => home_url( '/' ), 'key' => '', ); /** * Filters where the Speed test runs when there is no own key. The Pro add-on sends licensed * sites to its licence route. Return null to ask Google without a key. * * @param array|null $proxy url, site and licence key ('' for free sites). */ $proxy = apply_filters( 'forensix_speed_proxy', $proxy ); return array( 'hasKey' => '' !== $key, 'key' => current_user_can( Capabilities::MANAGE_SETTINGS ) ? $key : '', 'canEdit' => current_user_can( Capabilities::MANAGE_SETTINGS ), 'proxy' => is_array( $proxy ) && isset( $proxy['url'] ) ? $proxy : null, ); } /** * GET /speed. */ public function show(): \WP_REST_Response { return new \WP_REST_Response( self::present(), 200 ); } /** * POST /speed/key: an empty key removes it. * * @param \WP_REST_Request $request Request. * @phpstan-param \WP_REST_Request> $request * @return \WP_REST_Response|\WP_Error */ public function save_key( \WP_REST_Request $request ) { $key = trim( (string) $request['key'] ); if ( '' === $key ) { delete_option( self::KEY ); return new \WP_REST_Response( self::present(), 200 ); } if ( ! self::valid_key( $key ) ) { return new \WP_Error( 'forensix_bad_key', __( 'This does not look like a Google API key.', 'forensix-digital' ), array( 'status' => 400 ) ); } update_option( self::KEY, Vault::default()->lock( $key ), false ); return new \WP_REST_Response( self::present(), 200 ); } }