validator_internal_base() . '/health/live'; $r = wp_remote_get( $url, [ 'timeout' => 5 ] ); if ( is_wp_error( $r ) ) { return $this->probe_result( 'validator_health_live', false, $r->get_error_message() ); } $code = (int) wp_remote_retrieve_response_code( $r ); return $this->probe_result( 'validator_health_live', 200 === $code, "HTTP {$code} — " . wp_remote_retrieve_body( $r ) ); } public function probe_validator_health_ready(): array { $url = $this->validator_internal_base() . '/health/ready'; $r = wp_remote_get( $url, [ 'timeout' => 5 ] ); if ( is_wp_error( $r ) ) { return $this->probe_result( 'validator_health_ready', false, $r->get_error_message() ); } $code = (int) wp_remote_retrieve_response_code( $r ); return $this->probe_result( 'validator_health_ready', 200 === $code, "HTTP {$code} — " . wp_remote_retrieve_body( $r ) ); } public function probe_pds_handshake(): array { $client = new Prweb_Pds_Client(); $balance = $client->get_funder_balance(); if ( is_wp_error( $balance ) ) { // Configuration error — distinct from a transient probe failure. // Lets the diagnostics screen point operators at wp-config.php // instead of telling them to "check pds_api_base or network". return $this->probe_result( 'pds_handshake', false, $balance->get_error_message() ); } return $this->probe_result( 'pds_handshake', $balance > 0, $balance > 0 ? "Funder reachable; balance {$balance} Żetons" : 'PDS API did not return a balance — check pds_api_base or network reachability.' ); } public function probe_robots_txt(): array { $url = $this->rewrite_for_container( home_url( '/robots.txt' ) ); $r = wp_remote_get( $url, [ 'timeout' => 5 ] ); if ( is_wp_error( $r ) ) { return $this->probe_result( 'robots_txt', false, $r->get_error_message() ); } $body = (string) wp_remote_retrieve_body( $r ); $ok = false !== stripos( $body, 'License:' ); return $this->probe_result( 'robots_txt', $ok, $ok ? 'License: directive present' : 'robots.txt missing License: directive' ); } public function probe_rsl_xml(): array { $url = $this->rewrite_for_container( get_rest_url( null, 'pds/v1/rsl' ) ); $r = wp_remote_get( $url, [ 'timeout' => 5 ] ); if ( is_wp_error( $r ) ) { return $this->probe_result( 'rsl_xml', false, $r->get_error_message() ); } $body = (string) wp_remote_retrieve_body( $r ); libxml_use_internal_errors( true ); $sxe = simplexml_load_string( $body ); libxml_clear_errors(); if ( false === $sxe ) { return $this->probe_result( 'rsl_xml', false, 'Document is not well-formed XML' ); } $count = count( $sxe->children( self::RSL_NAMESPACE_URI ) ); if ( $count === 0 ) { return $this->probe_result( 'rsl_xml', false, 'Well-formed, but no entries are published.' ); } return $this->probe_result( 'rsl_xml', true, "Well-formed; {$count} entries" ); } // ------------------------------------------------------------------------- // Shared utilities (public — used by Ajax_Assets::ajax_test_license) // ------------------------------------------------------------------------- /** * Probes run from inside the WordPress container, where `localhost` is the * container itself. The configured pds_validator_url is the public address * embedded in rsl.xml (`server=`) — bots reach it from the host. For * server-to-server probes we rewrite `localhost`/`127.0.0.1` to * `host.docker.internal` so the WP container can reach the host validator. * Override with `PRWEB_VALIDATOR_INTERNAL_URL` if needed — a wp-config.php * constant or an environment variable, same dual-read every other * operator-configured value in this plugin honours (Prweb_Brand::config()). * Prweb_Config::report() (Settings → Required configuration / the * onboarding wizard) resolves this key the same way — use config(), not * defined_value(), or the report can say "configured" for an env-only * override that this probe would then silently ignore. */ public function validator_internal_base(): string { $override = Prweb_Brand::config( 'VALIDATOR_INTERNAL_URL' ); if ( null !== $override ) { return rtrim( (string) $override, '/' ); } $public = rtrim( (string) get_option( Prweb_Brand::option( 'validator_url' ), 'http://localhost:16160' ), '/' ); return $this->rewrite_for_container( $public ); } public function rewrite_for_container( string $url ): string { return (string) preg_replace( '#//(localhost|127\.0\.0\.1)([:/]|$)#', '//host.docker.internal$2', $url ); } // ------------------------------------------------------------------------- // Internal helpers // ------------------------------------------------------------------------- private function probe_result( string $name, bool $ok, string $detail ): array { return [ 'name' => $name, 'ok' => $ok, 'detail' => $detail ]; } }