plugin = $plugin; } /** * Whether the current user wants simple explanations. * * @return bool */ public static function simple_mode() { return '1' === get_user_meta( get_current_user_id(), 'orbitstem_seo_simple', true ); } /** * One plain sentence per issue: what it is, why it matters, what to do. * * @param string $id Issue id. * @return string */ public static function plain( $id ) { $texts = array( 'broken_internal_links' => __( 'Some links on your site lead to pages that do not exist. Visitors hit a dead end; point the links at the right page or add a redirect.', 'orbitstem-seo' ), 'broken_images' => __( 'Some images on your pages are missing, so visitors see an empty box. Upload the image again or remove it from the post.', 'orbitstem-seo' ), 'broken_external_links' => __( 'Some links to other websites no longer work. Update or remove them so readers are not sent nowhere.', 'orbitstem-seo' ), 'redirected_links' => __( 'Some links go to an old address and get forwarded. They work, but are a little slower; the Repair Center can point them straight at the new address.', 'orbitstem-seo' ), 'orphaned_content' => __( 'Nothing on your site links to these pages, so readers and Google rarely find them. Link to them from related posts; the Repair Center can suggest where.', 'orbitstem-seo' ), 'redirect_chains' => __( 'Some redirects send visitors to another redirect before they arrive. One step is faster; the Repair Center fixes this in one click.', 'orbitstem-seo' ), 'redirect_loops' => __( 'Some redirects send visitors in a circle, so the page never loads. Delete or change one of them.', 'orbitstem-seo' ), 'sitemap_unavailable' => __( 'Your sitemap (the list of pages you give to Google) cannot be opened. Check that sitemaps are on in Settings.', 'orbitstem-seo' ), 'sitemap_errors' => __( 'Your sitemap lists pages that do not work. Google wastes time on them; fix or remove those pages.', 'orbitstem-seo' ), 'sitemap_noindex' => __( 'Your sitemap lists pages that ask not to be shown in Google. That sends mixed signals; usually the page settings need a look.', 'orbitstem-seo' ), 'sitemap_canonical' => __( 'Your sitemap lists pages that say another page is the real one. List the real page instead.', 'orbitstem-seo' ), 'missing_from_sitemap' => __( 'Some pages that should be found in Google are not in your sitemap, so Google may find them later. Check their sitemap settings.', 'orbitstem-seo' ), 'missing_title' => __( 'Some pages have no title for search results. Google then makes one up; give each page a title.', 'orbitstem-seo' ), 'regressions' => __( 'Something changed what your pages tell Google, and no edit here explains it. A theme or plugin update is the usual cause; check it soon.', 'orbitstem-seo' ), 'update_guard' => __( 'Right after a theme, plugin or WordPress update, some key pages got worse for search. Check the update that just happened.', 'orbitstem-seo' ), 'cannibals' => __( 'Several of your pages compete for the same search, so Google has to pick one and both rank lower. Merge them or give each its own topic.', 'orbitstem-seo' ), 'other_sitemaps' => __( 'Another sitemap was found (often from an old SEO plugin). Two sitemaps can confuse search engines; remove the old one.', 'orbitstem-seo' ), ); if ( isset( $texts[ $id ] ) ) { return $texts[ $id ]; } if ( 0 === strpos( $id, 'head_' ) ) { return __( 'Your pages print the same SEO tag more than once, usually because the theme or another plugin adds its own. Search engines may pick the wrong one; turn off the duplicate in that theme or plugin.', 'orbitstem-seo' ); } return ''; } /** * Registers hooks. */ public function register() { add_action( 'admin_menu', array( $this, 'menu' ), 15 ); add_action( 'admin_post_' . self::ACTION, array( $this, 'handle' ) ); } /** * Adds the submenu page. */ public function menu() { add_submenu_page( Admin::SLUG, __( 'Issues', 'orbitstem-seo' ), __( 'Issues', 'orbitstem-seo' ), Admin::capability(), self::SLUG, array( $this, 'render' ) ); } /** * Starts a scan or processes a time slice now. */ public function handle() { if ( ! current_user_can( Admin::capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'orbitstem-seo' ), 403 ); } check_admin_referer( self::ACTION ); $task = isset( $_POST['task'] ) ? sanitize_key( wp_unslash( $_POST['task'] ) ) : ''; $notice = 'error'; if ( 'simple' === $task ) { update_user_meta( get_current_user_id(), 'orbitstem_seo_simple', self::simple_mode() ? '0' : '1' ); wp_safe_redirect( admin_url( 'admin.php?page=' . self::SLUG ) ); exit; } if ( 'start' === $task && $this->plugin->scanner->start() ) { $notice = 'started'; } elseif ( 'process' === $task ) { $this->plugin->jobs->tick( 20 ); $notice = 'processed'; } wp_safe_redirect( add_query_arg( 'notice', $notice, admin_url( 'admin.php?page=' . self::SLUG ) ) ); exit; } /** * Renders the page: scan status, severity filter, one collapsed card per issue. */ public function render() { if ( ! current_user_can( Admin::capability() ) ) { wp_die( esc_html__( 'You do not have permission to view this page.', 'orbitstem-seo' ) ); } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display of a notice after redirect. $notice = isset( $_GET['notice'] ) ? sanitize_key( wp_unslash( $_GET['notice'] ) ) : ''; $messages = array( 'started' => __( 'Scan started. It runs in the background in small steps; reload this page to follow it, or use "Process now".', 'orbitstem-seo' ), 'processed' => __( 'Processed the scan for up to 20 seconds.', 'orbitstem-seo' ), 'error' => __( 'The scan could not be started. It may already be running.', 'orbitstem-seo' ), ); $state = $this->plugin->scanner->status(); $running = $state && 'running' === $state['status']; $last = $this->plugin->scanner->last(); $issues = $running ? array() : $this->plugin->issues->all(); $labels = array( 'error' => __( 'Error', 'orbitstem-seo' ), 'warning' => __( 'Warning', 'orbitstem-seo' ), 'notice' => __( 'Notice', 'orbitstem-seo' ), ); $counts = array_fill_keys( array_keys( $labels ), 0 ); foreach ( $issues as $issue ) { ++$counts[ $issue['severity'] ]; } ob_start(); $this->button( 'start', __( 'Run scan', 'orbitstem-seo' ), $running, true ); if ( $running ) { $this->button( 'process', __( 'Process now', 'orbitstem-seo' ), false, false ); } $actions = ob_get_clean(); Ui::open( self::SLUG, __( 'SEO Issues', 'orbitstem-seo' ), __( 'Problems found on this site, with evidence and how to fix each one.', 'orbitstem-seo' ), $actions ); ?>
| cell( $key, isset( $row[ $key ] ) ? $row[ $key ] : '' ); ?> |
$visible ) : ?> $total ) : ?>
%s', esc_url( $link ), esc_html( $name ) ); } else { echo esc_html( $name ); } } return; } if ( in_array( $key, array( 'url', 'redirect_to' ), true ) && is_string( $value ) && preg_match( '#^https?://#', $value ) ) { printf( '%2$s', esc_url( $value ), esc_html( $value ) ); return; } echo esc_html( (string) $value ); } /** * A POST button. * * @param string $task Task. * @param string $label Label. * @param bool $disabled Disabled. * @param bool $primary Primary style. */ private function button( $task, $label, $disabled, $primary ) { ?>