prefix . 'guardforge_integrity'; $guardforge_last_scan_id = (int) get_option( GUARDFORGE_Integrity::SCAN_ID_OPTION, 0 ); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- plugin-owned table ($wpdb->prefix + a literal) that no WordPress API reads; every value is a prepare placeholder or a fragment prepared on its own. $guardforge_file_total = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$guardforge_table} WHERE scan_id = %d", $guardforge_last_scan_id ) ); $guardforge_last = GUARDFORGE_Options::get( 'integrity_last_scan' ); $guardforge_scanned = isset( $_GET['scanned'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display-only: a result our own redirect carries back from a nonce-checked action; it is only printed, escaped. $guardforge_changed = ( isset( $_GET['changed'] ) ? absint( wp_unslash( $_GET['changed'] ) ) : 0 ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display-only: a result our own redirect carries back from a nonce-checked action; it is only printed, escaped. $guardforge_removed = ( isset( $_GET['removed'] ) ? absint( wp_unslash( $_GET['removed'] ) ) : 0 ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display-only: a result our own redirect carries back from a nonce-checked action; it is only printed, escaped. // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- plugin-owned table ($wpdb->prefix + a literal) that no WordPress API reads; every value is a prepare placeholder or a fragment prepared on its own. $guardforge_rows = $guardforge_last_scan_id ? $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$guardforge_table} WHERE scan_id = %d ORDER BY file_path ASC LIMIT 200", $guardforge_last_scan_id ) ) : []; // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared // What the last scan actually flagged. The 200-row table further down is every // file that was verified, and deliberately gets no buttons: an unchanged file // has nothing to explain, and two hundred spend controls on one screen is a // trap rather than a feature. $guardforge_summary = (array) get_option( GUARDFORGE_Integrity::LAST_RESULT_OPTION, [] ); $guardforge_explainer = class_exists( 'GUARDFORGE_Event_Explainer' ) ? GUARDFORGE_Event_Explainer::instance() : null; $guardforge_findings = $guardforge_explainer ? $guardforge_explainer->scan_findings() : []; if ( $guardforge_explainer ) { $guardforge_explainer->prime( $guardforge_findings ); } // What the published hashes made of the last scan. Every class is present at // nought, so nothing below has to test for a key. $guardforge_classes = array_merge( GUARDFORGE_Integrity::empty_counts(), (array) ( $guardforge_summary['classes'] ?? [] ) ); $guardforge_flagged = (array) ( $guardforge_summary['flagged'] ?? [] ); $guardforge_shown = count( $guardforge_flagged ); $guardforge_total = (int) ( $guardforge_summary['flagged_total'] ?? $guardforge_shown ); $guardforge_scopes = (array) ( $guardforge_summary['unreferenced'] ?? [] ); $guardforge_queued = (array) ( $guardforge_summary['queued'] ?? [] ); $guardforge_restored = isset( $_GET['restored'] ) ? absint( wp_unslash( $_GET['restored'] ) ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display-only: a result our own redirect carries back from a nonce-checked action; it is only printed, escaped. $guardforge_reason = isset( $_GET['reason'] ) ? sanitize_text_field( wp_unslash( $_GET['reason'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display-only: a result our own redirect carries back from a nonce-checked action; it is only printed, escaped. $guardforge_file = isset( $_GET['file'] ) ? sanitize_text_field( wp_unslash( $_GET['file'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display-only: a result our own redirect carries back from a nonce-checked action; it is only printed, escaped. $guardforge_unexpected = ( isset( $_GET['unexpected'] ) ? absint( wp_unslash( $_GET['unexpected'] ) ) : 0 ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- display-only: a result our own redirect carries back from a nonce-checked action; it is only printed, escaped. $guardforge_class_label = [ 'official' => __( 'Official', 'guardforge' ), 'modified' => __( 'Modified', 'guardforge' ), 'unexpected' => __( 'Not in the official build', 'guardforge' ), 'missing' => __( 'Missing', 'guardforge' ), 'unreferenced' => __( 'No reference', 'guardforge' ), ]; ?>
✓ ' . esc_html( $guardforge_file ) . '' ); ?>
⚠
⚠ ⚠ ✓

$guardforge_label ) : ?>

' . esc_html( implode( ', ', array_map( 'strval', $guardforge_queued ) ) ) . '' ); ?>

' . esc_html__( 'Dashboard → Updates', 'guardforge' ) . '' ); ?> ' . esc_html__( 'Plugins', 'guardforge' ) . '' ); ?>
$guardforge_shown ) : ?>

$guardforge_event ) : ?> render_explanation_row( $guardforge_event, 3 ); } ?>
render_control( 'integrity', $guardforge_event ); } ?>
$guardforge_listed ) : ?>
render_settings_card(); ?>

file_path ) ); ?> scope ); ?> file_hash, 0, 20 ) ) . '…'; ?> scanned_at ); ?>
200 ) : ?>