0 ) { printf( '

%s

', esc_html( sprintf( /* translators: %d: number of updated items */ _n( 'Priority updated for %d item.', 'Priority updated for %d items.', $count, '4wp-seo-helper' ), $count ) ) ); } } if ( isset( $_GET['forwp_priority_error'] ) ) { echo '

' . esc_html__( 'Could not update priority.', '4wp-seo-helper' ) . '

'; } if ( isset( $_GET['forwp_type_excluded'] ) ) { $slug = sanitize_key( wp_unslash( (string) $_GET['forwp_type_excluded'] ) ); $label = self::post_type_label( $slug ); $undo = self::include_type_url( $slug ); printf( '

%s %s

', esc_html( sprintf( /* translators: %s: post type label */ __( '“%s” is excluded from SEO Inventory. This is saved for next time.', '4wp-seo-helper' ), $label ) ), '' . esc_html__( 'Undo', '4wp-seo-helper' ) . '' ); } if ( isset( $_GET['forwp_type_included'] ) ) { $slug = sanitize_key( wp_unslash( (string) $_GET['forwp_type_included'] ) ); printf( '

%s

', esc_html( sprintf( /* translators: %s: post type label */ __( '“%s” is shown in SEO Inventory again.', '4wp-seo-helper' ), self::post_type_label( $slug ) ) ) ); } // phpcs:enable WordPress.Security.NonceVerification.Recommended } private static function render_tabs( string $active, string $export_url = '' ): void { $tabs = [ 'inventory' => __( 'Inventory', '4wp-seo-helper' ), 'queue' => __( 'Priority queue', '4wp-seo-helper' ), ]; ?>
get_languages(); $show_lang = count( $languages ) > 1; // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Read-only admin inventory filters. $jump_post_id = isset( $_GET['forwp_post'] ) ? absint( wp_unslash( $_GET['forwp_post'] ) ) : 0; $filters = [ 'page' => isset( $_GET['paged'] ) ? max( 1, absint( wp_unslash( $_GET['paged'] ) ) ) : 1, 'post_type' => self::get_requested_post_type(), 'taxonomy' => self::get_requested_taxonomy(), 'term' => self::get_requested_term(), 'lang' => sanitize_key( wp_unslash( (string) ( $_GET['lang'] ?? '' ) ) ), 'status' => sanitize_key( wp_unslash( (string) ( $_GET['status'] ?? 'publish' ) ) ), 'missing' => sanitize_key( wp_unslash( (string) ( $_GET['missing'] ?? '' ) ) ), 'max_score' => isset( $_GET['max_score'] ) ? absint( wp_unslash( $_GET['max_score'] ) ) : 0, 'search' => sanitize_text_field( wp_unslash( (string) ( $_GET['s'] ?? '' ) ) ), // Never isolate to a single row — toolbar jump highlights inside the full list. 'post_id' => 0, ]; // phpcs:enable WordPress.Security.NonceVerification.Recommended $taxonomy_rows = TaxonomyDiscovery::get_labeled( '' === $filters['post_type'] ? [] : [ $filters['post_type'] ] ); $taxonomy_slugs = array_column( $taxonomy_rows, 'slug' ); if ( '' !== $filters['taxonomy'] && ! in_array( $filters['taxonomy'], $taxonomy_slugs, true ) ) { $filters['taxonomy'] = ''; $filters['term'] = 0; } $term_rows = '' !== $filters['taxonomy'] ? TaxonomyDiscovery::get_terms( $filters['taxonomy'] ) : []; if ( $filters['term'] > 0 ) { $term_ids = array_column( $term_rows, 'id' ); if ( ! in_array( $filters['term'], $term_ids, true ) ) { $filters['term'] = 0; } } if ( $jump_post_id > 0 ) { $per_page = (int) get_user_option( Menu::INVENTORY_PER_PAGE_OPTION ); if ( $per_page < 1 ) { $per_page = Menu::INVENTORY_PER_PAGE_DEFAULT; } $filters['page'] = $repository->find_page_for_post( $jump_post_id, [ 'post_type' => $filters['post_type'], 'taxonomy' => $filters['taxonomy'], 'term' => $filters['term'], 'lang' => $filters['lang'], 'status' => $filters['status'], 'missing' => $filters['missing'], 'max_score' => ! empty( $filters['max_score'] ) ? $filters['max_score'] : null, 'search' => $filters['search'], ], $per_page ); } $table = new InventoryListTable( $repository ); $table->set_show_language( $show_lang ); $table->set_show_gsc_metrics( self::should_show_gsc_metrics() ); $table->set_show_gsc_indexing( self::should_show_gsc_indexing() ); $table->set_filters( $filters ); $table->set_redirect_base( add_query_arg( array_filter( [ 'page' => Menu::INVENTORY_PAGE_SLUG, 'view' => 'inventory', Menu::INVENTORY_POST_TYPE_ARG => $filters['post_type'], Menu::INVENTORY_TAXONOMY_ARG => $filters['taxonomy'], Menu::INVENTORY_TERM_ARG => $filters['term'] > 0 ? (string) $filters['term'] : '', 'lang' => $filters['lang'], 'status' => $filters['status'], 'missing' => $filters['missing'], 'max_score' => ! empty( $filters['max_score'] ) ? (string) $filters['max_score'] : '', 's' => $filters['search'], 'paged' => $filters['page'] > 1 ? (string) $filters['page'] : '', 'orderby' => self::request_orderby(), 'order' => self::request_order(), ] ), admin_url( 'admin.php' ) ) ); $table->prepare_items(); $export_url = wp_nonce_url( add_query_arg( array_filter( [ 'action' => 'forwp_seo_inventory_export', Menu::INVENTORY_POST_TYPE_ARG => $filters['post_type'], Menu::INVENTORY_TAXONOMY_ARG => $filters['taxonomy'], Menu::INVENTORY_TERM_ARG => $filters['term'] > 0 ? (string) $filters['term'] : '', 'lang' => $filters['lang'], 'status' => $filters['status'], 'missing' => $filters['missing'], 'max_score' => ! empty( $filters['max_score'] ) ? (string) $filters['max_score'] : '', 's' => $filters['search'], ] ), admin_url( 'admin-post.php' ) ), 'forwp_seo_inventory_export' ); ?>

is_enabled() ) : ?>

is_connected() || '' === GscAdmin::get_site_property() ) ) : ?>

0 ) : ?>

display(); ?>
get_lanes_with_items()['lanes']; ?>

Menu::INVENTORY_PAGE_SLUG, 'view' => 'queue', 'priority' => $lane_id, ], admin_url( 'admin.php' ) ); ?>
3 ) : ?>
$item */ private static function render_compact_lane_item( array $item ): void { $no_focus = ! empty( $item['seo_no_focus'] ); $seo = $item['seo_score'] ?? null; if ( $no_focus && ( null === $seo || 0 === (int) $seo ) ) { $score_label = (string) ( $item['seo_score_label'] ?? __( 'No focus', '4wp-seo-helper' ) ); $class = 'na'; } else { $score_label = (string) ( null !== $seo ? (int) $seo : (int) ( $item['completeness'] ?? 0 ) ); $class = (int) $score_label >= 71 ? 'good' : ( (int) $score_label >= 41 ? 'medium' : 'low' ); } $title = (string) ( $item['wp_title'] ?? '' ); ?>
__( 'All queued', '4wp-seo-helper' ), '1' => PriorityLabels::get_formatted( 1 ), '2' => PriorityLabels::get_formatted( 2 ), '3' => PriorityLabels::get_formatted( 3 ), ]; ?> get_languages() ) > 1; // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Read-only admin queue page. $paged = isset( $_GET['paged'] ) ? max( 1, absint( wp_unslash( $_GET['paged'] ) ) ) : 1; // phpcs:enable WordPress.Security.NonceVerification.Recommended $table = new InventoryListTable( $repository ); $table->set_show_language( $show_lang ); $table->set_show_gsc_metrics( self::should_show_gsc_metrics() ); $table->set_show_gsc_indexing( self::should_show_gsc_indexing() ); $table->set_filters( [] ); $table->set_redirect_base( add_query_arg( array_filter( [ 'page' => Menu::INVENTORY_PAGE_SLUG, 'view' => 'queue', 'priority' => $active_priority ? (string) $active_priority : '', 'paged' => $paged > 1 ? (string) $paged : '', 'orderby' => self::request_orderby(), 'order' => self::request_order(), ] ), admin_url( 'admin.php' ) ) ); $table->set_priority_filter( $active_priority ?? 'queued' ); $table->prepare_items(); ?>

display(); ?>
Menu::INVENTORY_PAGE_SLUG, 'view' => 'inventory', 'forwp_type_excluded' => $slug, ] ), admin_url( 'admin.php' ) ) ); exit; } public static function handle_include_type(): void { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'Insufficient permissions.', '4wp-seo-helper' ) ); } check_admin_referer( 'forwp_seo_inventory_include_type' ); $slug = self::get_requested_post_type(); if ( '' !== $slug ) { ExcludedPostTypes::remove( $slug ); } wp_safe_redirect( add_query_arg( array_filter( [ 'page' => Menu::INVENTORY_PAGE_SLUG, 'view' => 'inventory', 'forwp_type_included' => $slug, Menu::INVENTORY_POST_TYPE_ARG => $slug, ] ), admin_url( 'admin.php' ) ) ); exit; } private static function exclude_type_url( string $slug ): string { return wp_nonce_url( add_query_arg( [ 'action' => 'forwp_seo_inventory_exclude_type', Menu::INVENTORY_POST_TYPE_ARG => $slug, ], admin_url( 'admin-post.php' ) ), 'forwp_seo_inventory_exclude_type' ); } private static function include_type_url( string $slug ): string { return wp_nonce_url( add_query_arg( [ 'action' => 'forwp_seo_inventory_include_type', Menu::INVENTORY_POST_TYPE_ARG => $slug, ], admin_url( 'admin-post.php' ) ), 'forwp_seo_inventory_include_type' ); } private static function post_type_label( string $slug ): string { $object = get_post_type_object( $slug ); if ( $object instanceof \WP_Post_Type ) { return (string) $object->labels->singular_name; } return $slug; } private static function render_excluded_types_note(): void { $excluded = ExcludedPostTypes::get(); if ( [] === $excluded ) { return; } $parts = []; foreach ( $excluded as $slug ) { $parts[] = sprintf( '%2$s', esc_url( self::include_type_url( $slug ) ), esc_html( self::post_type_label( $slug ) ) ); } echo '

'; echo esc_html__( 'Excluded post types:', '4wp-seo-helper' ); echo ' '; echo wp_kses_post( implode( ', ', $parts ) ); echo ' — '; echo ''; echo esc_html__( 'manage in Settings', '4wp-seo-helper' ); echo ''; echo '

'; } public static function url_for_post( int $post_id ): string { $post_id = absint( $post_id ); $url = add_query_arg( [ 'page' => Menu::INVENTORY_PAGE_SLUG, 'view' => 'inventory', 'forwp_post' => $post_id, ], admin_url( 'admin.php' ) ); return $url . '#forwp-seo-row-' . $post_id; } public static function get_requested_post_type(): string { // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Read-only inventory type filter. if ( isset( $_GET[ Menu::INVENTORY_POST_TYPE_ARG ] ) ) { $raw = (string) wp_unslash( $_GET[ Menu::INVENTORY_POST_TYPE_ARG ] ); } elseif ( isset( $_GET['post_type'] ) ) { $raw = (string) wp_unslash( $_GET['post_type'] ); } else { $raw = ''; } // phpcs:enable WordPress.Security.NonceVerification.Recommended return sanitize_key( $raw ); } public static function get_requested_taxonomy(): string { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only inventory taxonomy filter. $raw = isset( $_GET[ Menu::INVENTORY_TAXONOMY_ARG ] ) ? (string) wp_unslash( $_GET[ Menu::INVENTORY_TAXONOMY_ARG ] ) : ''; return sanitize_key( $raw ); } public static function get_requested_term(): int { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only inventory term filter. if ( ! isset( $_GET[ Menu::INVENTORY_TERM_ARG ] ) ) { return 0; } return absint( wp_unslash( $_GET[ Menu::INVENTORY_TERM_ARG ] ) ); } private static function request_orderby(): string { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only list table sort. $orderby = isset( $_GET['orderby'] ) ? sanitize_key( wp_unslash( (string) $_GET['orderby'] ) ) : ''; return 'gsc_index_status' === $orderby ? 'gsc_index_status' : ''; } private static function request_order(): string { if ( '' === self::request_orderby() ) { return ''; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only list table sort. $order = isset( $_GET['order'] ) ? strtolower( sanitize_key( wp_unslash( (string) $_GET['order'] ) ) ) : 'asc'; return 'desc' === $order ? 'desc' : 'asc'; } public static function should_show_gsc_metrics(): bool { if ( ! Release::is_module_public( Release::MODULE_GSC ) || ! GscModule::get_instance()->is_enabled() ) { return false; } $admin = GscAdmin::get_instance(); if ( ! $admin->is_menu_visible() ) { return false; } $property = GscAdmin::get_site_property(); if ( '' === $property ) { return false; } return ( new GscRepository() )->has_fact_period( $property, 'web', ReportPeriod::period_key_current() ); } public static function should_show_gsc_indexing(): bool { return Release::is_module_public( Release::MODULE_GSC ) && GscModule::get_instance()->is_enabled(); } }