settings = $settings; $this->policy = $policy; $this->registry = $registry; } /** * Registers hooks. * * @return void */ public function register(): void { add_action( 'admin_init', array( $this, 'maybe_redirect' ) ); } /** * Sends a freshly activated site to the screen, once. * * @return void */ public function maybe_redirect(): void { if ( ! get_transient( self::REDIRECT_TRANSIENT ) ) { return; } delete_transient( self::REDIRECT_TRANSIENT ); if ( ! current_user_can( self::CAPABILITY ) || wp_doing_ajax() ) { return; } // Never redirect out of a bulk activation. // the results for every other plugin in the batch. // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading the core plugins screen's own request, to stay out of its way. if ( isset( $_GET['activate-multi'] ) ) { return; } wp_safe_redirect( $this->get_screen_url() ); exit; } /** * Whether setup has been completed. * * @return bool True when a choice has been applied. */ public function is_complete(): bool { return (bool) $this->settings->get( 'onboarding_complete', false ); } /** * Returns the answer currently in force. * * @return string One of the CHOICE_* constants. */ public function current_choice(): string { $stored = (string) $this->settings->get( 'onboarding_choice', '' ); return in_array( $stored, array( self::CHOICE_EVERYTHING, self::CHOICE_TRAINING, self::CHOICE_DECLARE ), true ) ? $stored : self::CHOICE_TRAINING; } /** * Returns the URL of the screen this used to be a page of its own for. * * @param array $args Optional query arguments to add. * @return string Admin URL. */ public function get_screen_url( array $args = array() ): string { return MainScreen::url( $args ); } /** * Whether every search-affecting crawler has already been confirmed. * * @return bool True when the confirmation has been given. */ public function has_accepted_search_loss(): bool { $found = false; foreach ( $this->registry->get_agents() as $agent ) { if ( 'none' === $agent['search_impact'] ) { continue; } $found = true; if ( ! $this->settings->has_search_impact_ack( $agent['ua'] ) ) { return false; } } return $found; } /** * Applies a quick-choice preset. * * @param string $choice One of the CHOICE_* constants. * @param bool $accepts_search_loss Whether search-impact loss was confirmed. * @return string[] Messages for anything the model refused. */ public function apply_choice( string $choice, bool $accepts_search_loss ): array { if ( ! in_array( $choice, array( self::CHOICE_EVERYTHING, self::CHOICE_TRAINING, self::CHOICE_DECLARE ), true ) ) { return array(); } foreach ( $this->registry->get_agents() as $agent ) { if ( 'none' === $agent['search_impact'] ) { continue; } if ( $accepts_search_loss ) { $this->settings->add_search_impact_ack( $agent['ua'] ); } else { $this->settings->remove_search_impact_ack( $agent['ua'] ); } } // A preset clears any per-crawler choices made earlier. $this->settings->set( 'policies', array( 'groups' => array(), 'agents' => array(), ) ); $refusals = $this->apply_purposes( $choice ); $this->apply_declarations(); $this->settings->set( 'onboarding_complete', true ); $this->settings->set( 'onboarding_choice', $choice ); return $refusals; } /** * Writes the purpose defaults a choice implies. * * @param string $choice One of the CHOICE_* constants. * @return string[] Messages for anything the model refused. */ private function apply_purposes( string $choice ): array { $presets = array( self::CHOICE_EVERYTHING => array( 'training' => Policy::BLOCK, 'dataset' => Policy::BLOCK, 'scraping-tool' => Policy::BLOCK, 'search' => Policy::BLOCK, 'user-fetch' => Policy::BLOCK, ), self::CHOICE_TRAINING => array( 'training' => Policy::BLOCK, 'dataset' => Policy::BLOCK, 'scraping-tool' => Policy::BLOCK, 'search' => Policy::ALLOW, 'user-fetch' => Policy::ALLOW, ), self::CHOICE_DECLARE => array( 'training' => Policy::SIGNAL_ONLY, 'dataset' => Policy::SIGNAL_ONLY, 'scraping-tool' => Policy::SIGNAL_ONLY, 'search' => Policy::ALLOW, 'user-fetch' => Policy::ALLOW, ), ); $refusals = array(); foreach ( $presets[ $choice ] as $purpose => $policy ) { $result = $this->policy->set_purpose_default( $purpose, $policy ); if ( ! is_wp_error( $result ) ) { continue; } $refusals[] = $result->get_error_message(); $this->policy->set_purpose_default( $purpose, Policy::ALLOW ); } return $refusals; } /** * Publishes the declarations. * * @return void */ private function apply_declarations(): void { $declarations = $this->settings->get( 'declarations', array() ); $declarations = is_array( $declarations ) ? $declarations : array(); $this->settings->set( 'declarations', array_merge( $declarations, array( 'tdm_reservation' => true, 'content_signals' => true, 'signal_search' => Settings::SIGNAL_YES, 'signal_ai_input' => Settings::SIGNAL_NO, 'signal_ai_train' => Settings::SIGNAL_NO, 'noai' => true, 'noimageai' => true, ) ) ); } }