hooks(); } /** * WP Hooks. * * @since 1.12.0 * * @return void */ private function hooks() { add_action( 'current_screen', [ $this, 'init'] ); add_action( 'admin_notices', [ $this, 'display_migration_notice' ] ); add_action( 'admin_notices', [ $this, 'display_migration_result' ] ); add_action( 'wp_mail_logging_admin_tab_content_before', [ $this, 'display_migration_section'] ); add_action( 'wp_ajax_wp_mail_logging_dismiss_db_upgrade_notice', [ $this, 'ajax_dismiss_migration_notice' ] ); add_filter( 'wp_mail_logging_jquery_confirm_localized_strings', [ $this, 'jquery_confirm_localized_string' ] ); } /** * Init the migration UI and process if requested. * * @since 1.12.0 * * @return void */ public function init() { if ( ! $this->is_wp_mail_logging_admin_page() || ! $this->is_migration_needed() ) { return; } // Check if migration is requested. if ( ! empty( $_GET['migration'] ) && check_admin_referer( self::MIGRATION_NONCE, 'nonce' ) && current_user_can( 'manage_options' ) ) { $this->run( self::VERSION ); } } /** * Whether we are WP Mail Logging admin pages. * * @since 1.12.0 * * @return bool */ private function is_wp_mail_logging_admin_page() { global $wp_logging_list_page; $current_screen = get_current_screen(); return $current_screen->id === $wp_logging_list_page; } /** * Whether or not the migration is needed. * * @since 1.12.0 * * @return bool */ private function is_migration_needed() { if ( ! is_null( $this->is_migration_needed ) ) { return $this->is_migration_needed; } if ( version_compare( $this->get_current_version(), self::VERSION, '<' ) && ! get_option( self::MIGRATION_NOTICE_DISMISS_DB_KEY, false ) ) { $this->is_migration_needed = true; } else { $this->is_migration_needed = false; } return $this->is_migration_needed; } /** * Get current DB version. * * @since 1.12.0 * * @return int */ private function get_current_version() { if ( is_null( $this->current_version ) ) { $this->current_version = (int) get_option( self::OPTION_NAME, 0 ); } return $this->current_version; } /** * AJAX handler when DB upgrade notice is dismissed. * * @since 1.12.0 * * @return void */ public function ajax_dismiss_migration_notice() { if ( empty( $_POST['nonce'] ) || ! check_admin_referer( self::MIGRATION_NOTICE_DISMISS_NONCE, 'nonce' ) || ! current_user_can( 'manage_options' ) ) { wp_send_json_error(); } if ( ! empty( $_POST['type'] ) && $_POST['type'] === 'admin-notice' ) { update_option( self::MIGRATION_ADMIN_NOTICE_DISMISS_DB_KEY, true, false ); } else { $this->dismiss_db_upgrade_banner(); } wp_send_json_success(); } /** * Dismiss the DB upgrade banner. * * Check if the user already performed migration's 1 and 2 manually * and if so, add the option that tracks the completed migration. * * @since 1.12.0 * * @return void */ private function dismiss_db_upgrade_banner() { global $wpdb; // Get the existing charset of the table. $charset = $wpdb->get_var( $wpdb->prepare( 'SELECT CHARACTER_SET_NAME FROM information_schema.columns WHERE TABLE_NAME = %s AND COLUMN_NAME = "subject";', WPML_Plugin::getTablename( 'mails' ) ) ); if ( ! empty( $charset ) && strpos( $charset, 'utf8mb4' ) !== false && defined( 'DB_NAME' ) ) { // If we're here then migration_1() is already done. $message_index = $wpdb->get_results( $wpdb->prepare( 'SHOW INDEX FROM `%1$s`.`%2$s` WHERE Column_name = "message";', DB_NAME, WPML_Plugin::getTablename( 'mails' ) ) ); if ( ! empty( $message_index ) ) { // If we're here then migration_2() is already done. update_option( self::OPTION_NAME, 2, false ); } } update_option( self::MIGRATION_NOTICE_DISMISS_DB_KEY, true, false ); } /** * Run the migrations. * * @since 1.12.0 * * @param int $version The version of migration to run. * * @return void */ private function run( $version ) { if ( method_exists( $this, "migrate_to_{$version}" ) ) { $this->{"migrate_to_{$version}"}(); return; } $this->error = "Unable to find migration to version {$version}."; } /** * Display the migration-related notices. * * @since 1.12.0 * * @return void */ public function display_migration_notice() { if ( ! $this->is_wp_mail_logging_admin_page() || ( ! empty( $_GET['tab'] ) && $_GET['tab'] === 'settings' ) || ! $this->is_migration_needed() || get_option( self::MIGRATION_ADMIN_NOTICE_DISMISS_DB_KEY, false ) ) { return; } ?>

here to learn more.', 'wp-mail-logging' ), [ 'a' => [ 'href' => [] ], ] ), esc_url( add_query_arg( 'tab', 'settings', WPML_Utils::get_admin_page_url() ) ) ); ?>

is_wp_mail_logging_admin_page() || ( ! empty( $_GET['tab'] ) && $_GET['tab'] !== 'settings' ) ) { return; } if ( ! empty( $this->error ) && ! $this->is_success ) { ?>

error ); ?>

is_success ) { ?>

is_migration_needed() || $tab !== 'settings' || $this->is_success ) { return; } ?>

Important! By performing this upgrade, ALL your existing logs will be deleted.', 'wp-mail-logging' ), [ 'strong' => [], ] ) ?>

If you wish to keep all email logs and get the above improvements as well, please read our manual upgrade guide for more information.', 'wp-mail-logging' ), [ 'i' => [], 'a' => [ 'href' => [], 'target' => [], ], ] ) ?>

get_current_version(), $version, '<' ) ) { $this->run( $version ); } } /** * Migration from 0 to 1. * Convert the columns charset to utf8mb4. * * @since 1.12.0 * * @return void */ private function migrate_to_1() { global $wpdb; if ( strpos( $wpdb->collate, 'utf8mb4' ) !== false ) { $query = $wpdb->prepare( 'ALTER TABLE %1$s MODIFY `host` VARCHAR(200) CHARACTER SET utf8mb4 COLLATE %2$s NOT NULL DEFAULT "0", MODIFY `receiver` VARCHAR(200) CHARACTER SET utf8mb4 COLLATE %3$s NOT NULL DEFAULT "0", MODIFY `subject` VARCHAR(200) CHARACTER SET utf8mb4 COLLATE %4$s NOT NULL DEFAULT "0", MODIFY `message` TEXT CHARACTER SET utf8mb4 COLLATE %5$s, MODIFY `headers` TEXT CHARACTER SET utf8mb4 COLLATE %6$s, MODIFY `attachments` VARCHAR(800) CHARACTER SET utf8mb4 COLLATE %7$s NOT NULL DEFAULT "0", MODIFY `error` VARCHAR(400) CHARACTER SET utf8mb4 COLLATE %8$s NULL DEFAULT "", MODIFY `plugin_version` VARCHAR(200) CHARACTER SET utf8mb4 COLLATE %9$s NOT NULL DEFAULT "0";', WPML_Mail::get_table(), $wpdb->collate, $wpdb->collate, $wpdb->collate, $wpdb->collate, $wpdb->collate, $wpdb->collate, $wpdb->collate, $wpdb->collate ); if ( $wpdb->query( $query ) === false ) { $this->set_error_msg( $wpdb->last_error, 1 ); return; } $this->is_success = true; // Update the DB version. update_option( self::OPTION_NAME, 1, false ); } } /** * Migration from 1 to 2. * * This migration alters the table to add a FULL TEXT index on `message` column. * For optimization reason, we truncate (delete all the existing logs) the table before adding the index. * * @since 1.12.0 * * @return void */ private function migrate_to_2() { $this->maybe_run_older_migration( 1 ); global $wpdb; $wpdb->query( $wpdb->prepare( 'TRUNCATE TABLE `%1$s`;', WPML_Mail::get_table() ) ); // Add the FULLTEXT INDEX. $query = $wpdb->query( $wpdb->prepare( 'ALTER TABLE `%1$s` ADD FULLTEXT INDEX `idx_message` (`message`);', WPML_Mail::get_table() ) ); if ( $query === false ) { $this->set_error_msg( $wpdb->last_error, 2 ); return; } $this->is_success = true; // Update the DB version. update_option( self::OPTION_NAME, 2, false ); } /** * Set the error message. * * @since 1.12.0 * * @param string $error Error occured during migration. * @param int $version Version of migration. * * @return void */ private function set_error_msg( $error, $version ) { $this->error = "Unable to complete migration to version {$version}. Error: {$error}"; } /** * The localised strings for the jQuery confirm dialog. * * @since 1.12.0 * * @param array $strings Localized strings. * * @return mixed */ public function jquery_confirm_localized_string( $strings ) { $strings['db_upgrade_message'] = esc_html__( 'This upgrade will delete all of your existings logs. Are you sure you want to proceed?', 'wp-mail-logging' ); $strings['db_upgrade_url'] = esc_url( add_query_arg( [ 'tab' => 'settings', 'migration' => '1', 'nonce' => wp_create_nonce( self::MIGRATION_NONCE ), ], WPML_Utils::get_admin_page_url() ) ); return $strings; } }