prefix . 'affcf_forms'; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix $count = $wpdb->get_var( "SELECT COUNT(*) FROM {$table}" ); $next_number = $count + 1; while ( self::shortcode_exists( "shortcode_{$next_number}" ) ) { ++$next_number; } return "shortcode_{$next_number}"; } /** * Check if shortcode exists * * @param string $shortcode The shortcode to check. * @return bool True if shortcode exists, false otherwise. */ public static function shortcode_exists( $shortcode ) { global $wpdb; $table = $wpdb->prefix . 'affcf_forms'; // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix, plugin-controlled $exists = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$table} WHERE shortcode = %s", $shortcode ) ); // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter return $exists > 0; } /** * Get default page URL * * @param string $page_type The page type (dashboard, submit, edit). * @return string|null Page URL or null if not found. */ public static function get_default_page_url( $page_type ) { $pages = get_option( 'affcf_default_pages', array() ); $custom_key = 'custom_' . $page_type . '_page_id'; if ( ! empty( $pages[ $custom_key ] ) ) { return get_permalink( $pages[ $custom_key ] ); } $default_key = $page_type . '_page_id'; if ( ! empty( $pages[ $default_key ] ) ) { return get_permalink( $pages[ $default_key ] ); } return null; } /** * Format file size * * @param int $bytes The file size in bytes. * @return string Formatted file size with unit. */ public static function format_file_size( $bytes ) { $units = array( 'B', 'KB', 'MB', 'GB', 'TB' ); for ( $i = 0; $bytes > 1024; $i++ ) { $bytes /= 1024; } return round( $bytes, 2 ) . ' ' . $units[ $i ]; } /** * Clean old drafts * * @param int $days Number of days after which drafts are considered old. * @return int|false Number of rows deleted, or false on error. */ public static function clean_old_drafts( $days = 30 ) { global $wpdb; $table = $wpdb->prefix . 'affcf_drafts'; $date = gmdate( 'Y-m-d H:i:s', strtotime( "-{$days} days" ) ); // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix, plugin-controlled $result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE last_saved < %s", $date ) ); // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter return $result; } /** * Get error message * * @param string $key The error message key. * @param string $default_value Default value if key not found. * @return string The error message. */ public static function get_error_message( $key, $default_value = '' ) { $messages = get_option( 'affcf_error_messages', array() ); return $messages[ $key ] ?? $default_value; } }