diff --git a/mlw_quizmaster2.php b/mlw_quizmaster2.php index 2b6a65ad5..e05014e5a 100644 --- a/mlw_quizmaster2.php +++ b/mlw_quizmaster2.php @@ -348,6 +348,9 @@ private function add_hooks() { add_action( 'admin_menu', array( $this, 'setup_admin_menu' ) ); add_action( 'admin_head', array( $this, 'admin_head' ), 900 ); add_action( 'init', array( $this, 'register_quiz_post_types' ) ); + if ( empty( get_option('qsm_check_database_structure') ) || ! empty($_GET['qsm_check_database_structure']) ) { + add_action( 'admin_init', array( $this, 'qsm_check_database_structure' ) ); + } add_filter( 'parent_file', array( &$this, 'parent_file' ), 9999, 1 ); add_action( 'plugins_loaded', array( &$this, 'qsm_load_textdomain' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'qsm_admin_scripts_style' ), 10 ); @@ -784,6 +787,222 @@ public function admin_failed_submission_page() { $QmnFailedSubmissions->render_list_table(); } } + /** + * Check database structure + * + * @since 9.0.6 + * @return void + */ + public function qsm_check_database_structure() { + global $wpdb; + + // Define the table names + $quiz_table_name = $wpdb->prefix . 'mlw_quizzes'; + $question_table_name = $wpdb->prefix . 'mlw_questions'; + $results_table_name = $wpdb->prefix . 'mlw_results'; + $audit_table_name = $wpdb->prefix . 'mlw_qm_audit_trail'; + $themes_table_name = $wpdb->prefix . 'mlw_themes'; + $quiz_themes_settings_table_name = $wpdb->prefix . 'mlw_quiz_theme_settings'; + $question_terms_table_name = $wpdb->prefix . 'mlw_question_terms'; + + // List of tables and their columns + $tables = [ + $quiz_table_name => [ + 'quiz_id', + 'quiz_name', + 'message_before', + 'message_after', + 'message_comment', + 'message_end_template', + 'user_email_template', + 'admin_email_template', + 'submit_button_text', + 'name_field_text', + 'business_field_text', + 'email_field_text', + 'phone_field_text', + 'comment_field_text', + 'email_from_text', + 'question_answer_template', + 'leaderboard_template', + 'quiz_system', + 'randomness_order', + 'loggedin_user_contact', + 'show_score', + 'send_user_email', + 'send_admin_email', + 'contact_info_location', + 'user_name', + 'user_comp', + 'user_email', + 'user_phone', + 'admin_email', + 'comment_section', + 'question_from_total', + 'total_user_tries', + 'total_user_tries_text', + 'certificate_template', + 'social_media', + 'social_media_text', + 'pagination', + 'pagination_text', + 'timer_limit', + 'quiz_stye', + 'question_numbering', + 'quiz_settings', + 'theme_selected', + 'last_activity', + 'require_log_in', + 'require_log_in_text', + 'limit_total_entries', + 'limit_total_entries_text', + 'scheduled_timeframe', + 'scheduled_timeframe_text', + 'disable_answer_onselect', + 'ajax_show_correct', + 'quiz_views', + 'quiz_taken', + 'deleted', + 'quiz_author_id', + ], + $question_table_name => [ + 'question_id', + 'quiz_id', + 'question_name', + 'answer_array', + 'answer_one', + 'answer_one_points', + 'answer_two', + 'answer_two_points', + 'answer_three', + 'answer_three_points', + 'answer_four', + 'answer_four_points', + 'answer_five', + 'answer_five_points', + 'answer_six', + 'answer_six_points', + 'correct_answer', + 'question_answer_info', + 'comments', + 'hints', + 'question_order', + 'question_type', + 'question_type_new', + 'question_settings', + 'category', + 'deleted', + 'deleted_question_bank', + ], + $results_table_name => [ + 'result_id', + 'quiz_id', + 'quiz_name', + 'quiz_system', + 'point_score', + 'correct_score', + 'correct', + 'total', + 'name', + 'business', + 'email', + 'phone', + 'user', + 'user_ip', + 'time_taken', + 'time_taken_real', + 'quiz_results', + 'deleted', + 'unique_id', + 'form_type', + 'page_name', + 'page_url', + ], + $audit_table_name => [ + 'trail_id', + 'action_user', + 'action', + 'quiz_id', + 'quiz_name', + 'form_data', + 'time', + ], + $themes_table_name => [ + 'id', + 'theme', + 'theme_name', + 'default_settings', + 'theme_active', + ], + $quiz_themes_settings_table_name => [ + 'id', + 'theme_id', + 'quiz_id', + 'quiz_theme_settings', + 'active_theme', + ], + $question_terms_table_name => [ + 'id', + 'question_id', + 'quiz_id', + 'term_id', + 'taxonomy', + ], + ]; + $response['message'] = ""; + // Check all tables + $errors = []; + foreach ( $tables as $table_name => $columns ) { + $error = $this->qsm_check_table_structure($table_name, $columns); + if ( $error ) { + $errors[] = $error; + } + } + if ( ! empty($errors) ) { + $response['message'] .= esc_html__("Incorrect database structure!", "quiz-master-next") . "
"; + foreach ( $errors as $error ) { + $response['status'] = "error"; + $response['message'] .= esc_html($error) . "
"; + } + update_option('qsm_check_database_structure', "error"); + } else { + update_option('qsm_check_database_structure', "success"); + $response['status'] = "success"; + $response['message'] = esc_html__("All tables have the correct structure.", "quiz-master-next"); + } + if ( ! empty( $_GET['qsm_check_database_structure'] ) ) { + $this->alertManager->newAlert( $response['message'], $response['status'] ); + }else { + return $response; + } + } + + /** + * Check if table and columns exist + * + * @since 9.0.6 + * @param string $table_name + * @param array $expected_columns + * @return string|null + */ + public function qsm_check_table_structure( $table_name, $expected_columns ) { + global $wpdb; + $columns = $wpdb->get_results("SHOW COLUMNS FROM $table_name"); + if ( ! $columns ) { + return esc_html__("Table ", "quiz-master-next") . $table_name . esc_html__(" does not exist.", "quiz-master-next"); + } + $existing_columns = array_column($columns, 'Field'); + $missing_columns = []; + foreach ( $expected_columns as $column ) { + if ( ! in_array($column, $existing_columns, true) ) { + $missing_columns[] = $column; + } + } + if ( ! empty($missing_columns) ) { + return esc_html__("Table ", "quiz-master-next") . $table_name . esc_html__(" is missing columns: ", "quiz-master-next") . implode(', ', $missing_columns); + } + return null; + } /** * Failed Database queries diff --git a/php/classes/class-qmn-quiz-manager.php b/php/classes/class-qmn-quiz-manager.php index 4b3303164..97817780d 100644 --- a/php/classes/class-qmn-quiz-manager.php +++ b/php/classes/class-qmn-quiz-manager.php @@ -1872,7 +1872,7 @@ public function qsm_get_quiz_to_reload() { */ private function add_quiz_results( $data ) { global $wpdb; - if ( empty( $wpdb ) || empty( $data['qmn_array_for_variables'] ) || empty( $data['results_array'] ) || empty( $data['unique_id'] ) || empty( $data['http_referer'] ) || ! isset( $data['form_type'] ) ) { + if ( empty( $wpdb ) || empty( $data['qmn_array_for_variables'] ) || empty( $data['results_array'] ) || empty( $data['unique_id'] ) || ! isset( $data['http_referer'] ) || ! isset( $data['form_type'] ) ) { return false; } diff --git a/php/template-variables.php b/php/template-variables.php index b1c22ce30..ae207d466 100644 --- a/php/template-variables.php +++ b/php/template-variables.php @@ -134,7 +134,7 @@ function qsm_variable_single_answer( $content, $mlw_quiz_array ) { $ser_answer = $wpdb->get_row( $wpdb->prepare( "SELECT question_settings FROM {$wpdb->prefix}mlw_questions WHERE question_id = %d", $question_id ), ARRAY_A ); $question_settings = qmn_sanitize_input_data( $ser_answer['question_settings'] ); $answerstr = ""; - if ( isset($answers['user_answer']) ) { + if ( isset( $answers['user_answer'] ) && is_array( $answers['user_answer'] ) ) { if ( 13 === intval( $answers['question_type'] ) ) { $answerstr .= $answers['points']; }elseif ( 12 === intval( $answers['question_type'] ) ) { @@ -510,15 +510,15 @@ function qsm_contact_field_variable( $content, $results_array ) { function qsm_all_contact_fields_variable( $content, $results ) { global $mlwQuizMasterNext; $contact_form = $mlwQuizMasterNext->pluginHelper->get_quiz_setting( 'contact_form' ); - + $return = ''; if ( isset( $results['contact'] ) && ( is_array( $results['contact'] ) || is_object( $results['contact'] ) ) ) { foreach ( $results['contact'] as $results_contact ) { $options = qsm_get_options_of_contact_fields($contact_form, $results_contact['label'], $results_contact['type'] ); - $isRadioOrSelect = in_array($results_contact['type'], ['radio', 'select']); - $hasOptions = !empty(trim($options)); + $isRadioOrSelect = in_array($results_contact['type'], [ 'radio', 'select' ]); + $hasOptions = ! empty(trim($options)); - if (($isRadioOrSelect && $hasOptions) || !$isRadioOrSelect) { + if ( ($isRadioOrSelect && $hasOptions) || ! $isRadioOrSelect ) { $return .= $results_contact['label'] . ': ' . $results_contact['value'] . '
'; } } @@ -526,9 +526,9 @@ function qsm_all_contact_fields_variable( $content, $results ) { $content = str_replace( '%CONTACT_ALL%', $return, $content ); return $content; } -function qsm_get_options_of_contact_fields($data, $label, $type) { - foreach ($data as $item) { - if ($item['label'] === $label && $item['type'] === $type) { +function qsm_get_options_of_contact_fields( $data, $label, $type ) { + foreach ( $data as $item ) { + if ( $item['label'] === $label && $item['type'] === $type ) { return $item['options']; } }