global_settings = $global_settings; $this->ai_settings = $ai_settings; $this->ai_bots = $ai_bots; $this->robots_txt = $robots_txt; $this->integrations = $integrations; $this->onboarding = $onboarding; } /** * @return array{ * percent: int, * steps: array, * next_incomplete_step: ?int * } */ public function report(): array { $onboarding_state = $this->onboarding->get(); $steps = array( array( 'step' => 1, 'label' => __( 'Organization', 'acez-seo' ), 'done' => $this->organization_done(), ), array( 'step' => 3, 'label' => __( 'AI assistant', 'acez-seo' ), 'done' => $this->ai_settings->is_ready(), ), array( 'step' => 4, 'label' => __( 'SEO for the AI era', 'acez-seo' ), 'done' => $this->ai_crawlers_done( $onboarding_state ), ), array( 'step' => 5, 'label' => __( 'Visibility & GSC', 'acez-seo' ), 'done' => $this->visibility_done( $onboarding_state ), ), ); $done_count = count( array_filter( $steps, static fn( array $step ): bool => $step['done'] ) ); $percent = (int) ( 25 * $done_count ); $next_incomplete = null; foreach ( $steps as $step ) { if ( ! $step['done'] ) { $next_incomplete = $step['step']; break; } } return array( 'percent' => $percent, 'steps' => $steps, 'next_incomplete_step' => $next_incomplete, ); } private function organization_done(): bool { return '' !== trim( (string) $this->global_settings->get()['organization_name'] ); } /** * @param array{status: string, last_step: int, site_type: string} $onboarding_state */ private function ai_crawlers_done( array $onboarding_state ): bool { if ( $onboarding_state['last_step'] >= 4 ) { return true; } if ( null === $this->ai_bots ) { return false; } $ai_bots_settings = $this->ai_bots->get(); if ( (bool) $ai_bots_settings['llms_enabled'] || (bool) $ai_bots_settings['noai'] ) { return true; } $ai_bot_agents = wp_list_pluck( OnboardingTab::ai_bot_choices(), 'agent' ); $blocked_bots = (array) $this->robots_txt->get()['blocked_bots']; return array() !== array_intersect( $blocked_bots, $ai_bot_agents ); } /** * @param array{status: string, last_step: int, site_type: string} $onboarding_state */ private function visibility_done( array $onboarding_state ): bool { // last_step reaches 5 only via `save_step_5()`, which always finishes // the wizard — the same "reached this screen" signal as Step 4, kept // consistent rather than also special-casing status=skipped (skipping // the WHOLE wizard early says nothing about this specific step). if ( $onboarding_state['last_step'] >= 5 ) { return true; } return '' !== trim( (string) $this->integrations->get()['gsc_verification_code'] ); } }