settings = $settings; $this->history = $history; } /** * Registers hooks. * * @return void */ public function register(): void { add_action( 'init', array( $this, 'add_rewrite_rule' ) ); add_filter( 'query_vars', array( $this, 'add_query_var' ) ); add_action( 'parse_request', array( $this, 'maybe_serve' ) ); add_action( 'wp_head', array( $this, 'print_meta' ), 1 ); add_filter( 'wp_headers', array( $this, 'add_headers' ) ); } /** * Whether the reservation is switched on. * * @return bool True when rights are reserved. */ public function is_enabled(): bool { return ! aiblackout_is_disabled() && (bool) $this->settings->get_declaration( 'tdm_reservation', false ); } /** * Returns the configured TDM policy URL. * * @return string Policy URL, or an empty string when none is set. */ public function get_policy_url(): string { $url = (string) $this->settings->get_declaration( 'tdm_policy_url', '' ); return '' !== $url ? esc_url_raw( $url ) : ''; } /** * Adds the rewrite rule for the well-known file. * * @return void */ public function add_rewrite_rule(): void { add_rewrite_rule( '^\.well-known/tdmrep\.json$', 'index.php?' . self::QUERY_VAR . '=1', 'top' ); } /** * Registers the query variable. * * @param array $vars Registered query variables. * @return array Filtered query variables. */ public function add_query_var( $vars ): array { $vars = is_array( $vars ) ? $vars : array(); $vars[] = self::QUERY_VAR; return $vars; } /** * Serves the well-known file when it is requested. * * @param \WP $wp Current WordPress environment. * @return void */ public function maybe_serve( $wp ): void { $requested = isset( $wp->query_vars[ self::QUERY_VAR ] ); if ( ! $requested && ! $this->is_tdmrep_request() ) { return; } if ( ! $this->is_enabled() ) { status_header( 404 ); nocache_headers(); exit; } status_header( 200 ); header( 'Content-Type: application/json; charset=utf-8' ); header( 'X-Robots-Tag: noindex' ); echo wp_json_encode( $this->build_document(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ); exit; } /** * Whether the current request is for the well-known file. * * @return bool True when the path matches. */ private function is_tdmrep_request(): bool { if ( empty( $_SERVER['REQUEST_URI'] ) ) { return false; } $uri = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ); $path = (string) wp_parse_url( $uri, PHP_URL_PATH ); if ( '' === $path ) { return false; } $expected = (string) wp_parse_url( $this->get_url(), PHP_URL_PATH ); return '' !== $expected && untrailingslashit( $path ) === untrailingslashit( $expected ); } /** * Returns the URL the well-known file is published at. * * @return string Absolute URL. */ public function get_url(): string { return home_url( '/' . self::PATH ); } /** * Builds the tdmrep.json document. * * @return array The document, ready to encode. */ public function build_document(): array { $entry = array( 'location' => '/', 'tdm-reservation' => 1, ); $policy = $this->get_policy_url(); if ( '' !== $policy ) { $entry['tdm-policy'] = $policy; } return array( $entry ); } /** * Returns the document as it would be served. * * @return string JSON, or an empty string when the reservation is off. */ public function preview(): string { if ( ! $this->is_enabled() ) { return ''; } return (string) wp_json_encode( $this->build_document(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ); } /** * Prints the meta tags on front-end pages. * * @return void */ public function print_meta(): void { if ( ! $this->is_enabled() || is_admin() ) { return; } echo '' . "\n"; $policy = $this->get_policy_url(); if ( '' !== $policy ) { printf( '' . "\n", esc_url( $policy ) ); } } /** * Adds the HTTP headers to front-end responses. * * @param array $headers Response headers. * @return array Filtered headers. */ public function add_headers( $headers ): array { $headers = is_array( $headers ) ? $headers : array(); if ( ! $this->is_enabled() || is_admin() ) { return $headers; } $headers['tdm-reservation'] = '1'; $policy = $this->get_policy_url(); if ( '' !== $policy ) { $headers['tdm-policy'] = $policy; } return $headers; } /** * Records the current declaration in the history log. * * @return void */ public function record(): void { if ( ! $this->is_enabled() ) { $this->history->record( self::TYPE, __( 'Text and data mining reservation withdrawn.', 'ai-blackout' ), array( 'tdm-reservation' => 0 ) ); return; } $this->history->record( self::TYPE, __( 'Reserved text and data mining rights site-wide under EU Directive 2019/790 Article 4.', 'ai-blackout' ), $this->build_document() ); } }