myyoast_connection_conditional = $myyoast_connection_conditional; $this->oauth_strategy = $oauth_strategy; $this->token_strategy = $token_strategy; $this->logger = new NullLogger(); } /** * Returns the sender configured to authenticate AI requests for the given user. * * @param WP_User $user The WP user. * * @return AI_Request_Sender The configured sender. */ public function create( WP_User $user ): AI_Request_Sender { $forced = $this->get_filter_override( $user ); switch ( $forced ) { case Auth_Method::OAUTH: $this->logger->debug( 'AI auth: wpseo_ai_auth_method filter pinned oauth.' ); $sender = new AI_Request_Sender( $this->oauth_strategy ); break; case Auth_Method::TOKEN: $this->logger->debug( 'AI auth: wpseo_ai_auth_method filter pinned token.' ); $sender = new AI_Request_Sender( $this->token_strategy ); break; default: if ( $this->myyoast_connection_conditional->is_met() ) { $this->logger->debug( 'AI auth: routing to oauth strategy (feature flag on) with a fallback to legacy token auth.' ); $sender = new AI_Request_Sender( $this->oauth_strategy, $this->token_strategy ); } else { $this->logger->debug( 'AI auth: routing to token strategy (MYYOAST_CONNECTION feature flag is off).' ); $sender = new AI_Request_Sender( $this->token_strategy ); } break; } // Logger_Aware_Pass only auto-wires container-registered services; the sender is hand-built // here so its logger must be propagated explicitly, otherwise its fallback warning is dropped. $sender->setLogger( $this->logger ); return $sender; } /** * Returns the strategy forced by the wpseo_ai_auth_method filter, or null when not pinned. * * @param WP_User $user The WP user. * * @return string|null One of the Auth_Method constants, or null. */ private function get_filter_override( WP_User $user ): ?string { /** * Filter: 'wpseo_ai_auth_method' - Pin a specific AI auth strategy for QA / staged rollout. * * Return 'oauth' to force MyYoast OAuth. * Return 'token' to force the legacy access_jwt flow. * Return any other value (including the default null) to let the factory's normal selection logic run: * If OAuth is available, it will be the primary strategy with a fallback to the legacy token flow. * If OAuth is unavailable, the legacy token flow will be used exclusively. * * @internal * * @param string|null $method The forced strategy, or null for default selection. * @param WP_User $user The WP user the request is on behalf of. */ $forced = \apply_filters( 'wpseo_ai_auth_method', null, $user ); if ( $forced === Auth_Method::OAUTH || $forced === Auth_Method::TOKEN ) { return $forced; } return null; } }