isBlocked = $isBlocked; $this->streamingEnabled = $streamingEnabled; $this->intercepted = $intercepted; } /** The policy wired to the running WordPress. */ public static function forWordPress(): self { return new self( static fn(string $url): bool => class_exists('WP_Http') && (new \WP_Http())->block_request($url), static fn(string $url): bool => function_exists('apply_filters') ? (bool) apply_filters('aiwend_streaming_enabled', true, $url) : true, static function (string $url): bool { if (!function_exists('apply_filters')) { return false; } // Same arguments shape as wp_remote_post() would pass, without headers or body (those hold the credential and the visitor's text). $args = ['method' => 'POST', 'redirection' => 0, 'blocking' => true, 'sslverify' => true, 'aiwend_streaming' => true]; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WordPress core hook, not ours return apply_filters('pre_http_request', false, $args, $url) !== false; }, ); } /** * Refuses a request this site's rules do not allow. * * @throws ProviderException kind unavailable, never dispatched, no credentials in the message */ public function prepare(string $url): void { if (!($this->streamingEnabled)($url)) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- exception messages go to logs and callers, never echoed; public errors are fixed codes throw new ProviderException(ProviderException::UNAVAILABLE, false, 'Streaming requests to the AI provider are switched off on this site.'); } if (($this->isBlocked)($url) || ($this->intercepted)($url)) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- exception messages go to logs and callers, never echoed; public errors are fixed codes throw new ProviderException(ProviderException::UNAVAILABLE, false, 'This site\'s HTTP settings block requests to the AI provider. Allow the provider host in WP_ACCESSIBLE_HOSTS or lift WP_HTTP_BLOCK_EXTERNAL.'); } } }