get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i WHERE status = %s', Notifications::table(), $status ) ) : 0; } $oldest = self::exists( Notifications::table() ) ? $wpdb->get_var( $wpdb->prepare( "SELECT MIN(next_at) FROM %i WHERE status IN ('pending','sending')", Notifications::table() ) ) : null; // An add-on's verification method may need keys before it can work. $ready = Extensions::filter( 'accessible_forms_verification_ready', true, Spam::provider() ); $failure = get_option( 'accessible_forms_extension_failure', array() ); $failure = is_array( $failure ) ? $failure : array(); $storage = self::storage(); return array( 'verification_ready' => (bool) $ready, // ALTCHA needs HTTPS (or localhost) in the visitor's browser. 'verification_secure' => Spam::provider_usable(), 'oldest_pending' => $oldest ?: '', 'queue_delayed' => $oldest && strtotime( $oldest . ' UTC' ) < time() - 15 * MINUTE_IN_SECONDS, 'plugin' => VERSION, 'extension_api' => API_VERSION, 'database_version' => (int) get_option( 'accessible_forms_db_version', 0 ), 'add_ons' => Extensions::filter( 'accessible_forms_health_versions', array() ), 'extension_failure' => array( 'hook' => sanitize_key( $failure['hook'] ?? '' ), 'at' => preg_match( '/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/D', (string) ( $failure['at'] ?? '' ) ) ? $failure['at'] : '', ), 'wordpress' => get_bloginfo( 'version' ), 'php' => PHP_VERSION, 'environment' => wp_get_environment_type(), 'https' => is_ssl(), 'multisite' => is_multisite(), 'storage' => $storage, 'cleanup_last' => (int) get_option( 'accessible_forms_last_cleanup', 0 ), 'cleanup_next' => wp_next_scheduled( 'accessible_forms_purge' ), 'notifications_next' => wp_next_scheduled( 'accessible_forms_notifications' ), 'notifications' => $counts, 'spam_provider' => Spam::provider(), 'mail_transport' => Mailer::transport(), 'test_delivery' => ! empty( Settings::get()['test_delivery'] ), 'historical_dates' => $storage ? TimeMigration::pending() : null, ); } private static function storage() { // Add-ons list the tables they own. $tables = (array) Extensions::filter( 'accessible_forms_health_tables', array( Entries::table_name(), Notifications::table(), Audit::table(), ) ); foreach ( $tables as $table ) { if ( ! self::exists( $table ) ) { return false; } } global $wpdb; $required = array( Entries::table_name() => array( 'id', 'snapshot', 'request_key', 'payload_hash', 'workflow', 'assignee', 'notes', 'expires_at', 'retention_days', 'resolved_at', 'first_reply_at', 'time_version', 'time_original' ), Notifications::table() => array( 'id', 'entry_id', 'status', 'next_at' ), Audit::table() => array( 'id', 'entry_id', 'created_at' ), ); foreach ( $required as $table => $columns ) { $actual = $wpdb->get_col( $wpdb->prepare( 'SHOW COLUMNS FROM %i', $table ) ); if ( array_diff( $columns, $actual ?: array() ) ) { return false; } } return (int) get_option( 'accessible_forms_db_version' ) >= DB_VERSION && (bool) Extensions::filter( 'accessible_forms_storage_ready', true ); } private static function exists( $table ) { global $wpdb; return $table === $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table ) ) ); } public static function site_tests( $tests ) { $tests['direct']['accessible_forms'] = array( 'label' => __( 'Accessible Forms', 'accessible-forms-by-accessible-org' ), 'test' => array( self::class, 'site_test' ), ); $tests['direct']['accessible_forms_live_check'] = array( 'label' => __( 'Accessible Forms live page checks', 'accessible-forms-by-accessible-org' ), 'test' => array( LiveCheck::class, 'site_test' ), ); return $tests; } public static function site_test() { $report = self::report(); $problem = $report['queue_delayed'] || ! $report['verification_ready'] || ! $report['verification_secure'] || ! $report['storage'] || ! $report['cleanup_next'] || $report['notifications']['failed'] || $report['notifications']['uncertain']; $problem = $problem || ! empty( $report['historical_dates'] ); return array( 'label' => $problem ? __( 'Accessible Forms needs attention', 'accessible-forms-by-accessible-org' ) : __( 'Accessible Forms storage and scheduling are available', 'accessible-forms-by-accessible-org' ), 'status' => $problem ? 'recommended' : 'good', 'badge' => array( 'label' => __( 'Forms', 'accessible-forms-by-accessible-org' ), 'color' => 'blue', ), 'description' => '
' . esc_html__( 'Check saved submissions, background notifications and retention from the form health screen.', 'accessible-forms-by-accessible-org' ) . '
', 'actions' => '' . esc_html__( 'Review form health', 'accessible-forms-by-accessible-org' ) . '
', 'test' => 'accessible_forms', ); } }