is_activation_mode()) { return; } // Recorded before redirecting rather than on completion, so a wizard that is // skipped, closed or abandoned halfway does not reopen on every visit. The // admin notice below is what invites the user back after that. update_option(self::OFFERED_OPTION, 1, false); wp_safe_redirect(admin_url('admin.php?page=rankify-setup')); exit(); } /** * A dismissible prompt for anyone who did not land on the wizard — a bulk * activation, or an install done over WP-CLI. */ public function renderNotice() { if (self::isComplete() || !current_user_can('manage_options')) { return; } $screen = get_current_screen(); if ($screen && false !== strpos((string) $screen->id, 'rankify')) { return; } ?>

'POST', 'permission_callback' => function () { return current_user_can('manage_options'); }, 'callback' => [$this, 'handleComplete'], ]); } public function handleComplete(\WP_REST_Request $request) { if (!wp_verify_nonce($request->get_header('X-WP-Nonce'), 'wp_rest')) { return new \WP_Error('invalid_nonce', __('Invalid nonce', 'crownify'), ['status' => 403]); } update_option(self::DONE_OPTION, current_time('mysql', true), false); return new \WP_REST_Response(['complete' => true], 200); } /** * The one thing the wizard cannot ask about honestly without checking first: * a site set to discourage search engines will not be indexed no matter what * Crownify emits, and saying nothing about it would waste the user's time. */ public static function siteIsDiscouraged() { return '0' === (string) get_option('blog_public'); } /** * Post types worth offering, with the labels a person recognises. * * @return array */ public static function postTypes() { $types = []; foreach (get_post_types(['public' => true, 'show_ui' => true], 'objects') as $type) { if ('attachment' === $type->name) { continue; } $types[$type->name] = $type->labels->name; } return $types; } /** * Whether this site looks like a personal blog or an organisation. * * A guess, offered as a default the user can change — with one author and no * company name configured, "person" is right far more often than not. */ public static function guessSiteType() { $current = Utils::getSetting('schemaSiteType'); if (is_string($current) && '' !== $current) { return $current; } $authors = get_users(['who' => 'authors', 'number' => 2, 'fields' => 'ID']); return count($authors) > 1 ? 'organization' : 'person'; } }