Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Admin Notification for database permission ALTER TABLE, enable error log by default, retrieve failed submission #2544

Merged
merged 6 commits into from
May 16, 2024
123 changes: 122 additions & 1 deletion mlw_quizmaster2.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,14 @@ public function __construct() {
$this->add_hooks();
}

//Check admin capabilities
/**
* Check admin capabilities.
*
* @since 9.0.0
* @param string $check_permission permission type
*
* @return boolean current user has permission
*/
public function qsm_is_admin( $check_permission = 'manage_options' ) {
if ( ! function_exists( 'wp_get_current_user' ) && file_exists( ABSPATH . "wp-includes/pluggable.php" ) ) {
require_once( ABSPATH . "wp-includes/pluggable.php" );
Expand All @@ -172,6 +179,63 @@ public function qsm_is_admin( $check_permission = 'manage_options' ) {
return ( function_exists( 'wp_get_current_user' ) && function_exists( 'current_user_can' ) && current_user_can( $check_permission ) );
}

/**
* Get failed alter qmn table query list.
*
* @since 9.0.2
* @return array alter qmn table query list
*/
private function get_failed_alter_table_queries() {
$failed_queries = get_option( 'qmn_failed_alter_table_queries', array() );
return is_array( $failed_queries ) ? $failed_queries: array();
}

/**
* Execute WP db query and save query if failed to execute
*
* @since 9.0.2
* @param string $query SQL Query
*
* @return boolean query executed or not
*/
public function wpdb_alter_table_query( $query ) {
// Check if admin or empty query.
if ( empty( $query ) || ! function_exists( 'is_admin' ) || ! is_admin() ) {
return false;
}

global $wpdb;
$query = trim( $query );

// check if a query for qsm tables alter only.
if ( empty( $wpdb ) || 0 != stripos( $query, 'ALTER TABLE' ) || false === stripos( $query, 'mlw_' ) ) {
return false;
}

// Execute query.
$res = $wpdb->query( $query );

// Get failed alter table query list.
$failed_queries = $this->get_failed_alter_table_queries();

if ( ! empty( $res ) ) {
if ( ! empty( $failed_queries ) && in_array( $query, $failed_queries ) ) {
// Remove failed query from list.
$failed_queries = array_diff( $failed_queries, array( $query ) );
// Update failed queries list.
update_option( 'qmn_failed_alter_table_queries', $failed_queries );
}
return true;
} else if ( empty( $failed_queries ) || ! in_array( $query, $failed_queries ) ) {
// Add query to the list.
$failed_queries[] = $query;
// Update failed queries list.
update_option( 'qmn_failed_alter_table_queries', $failed_queries );
}

return false;
}

/**
* Load File Dependencies
*
Expand Down Expand Up @@ -272,6 +336,28 @@ private function add_hooks() {
add_action( 'admin_init', array( $this, 'qsm_overide_old_setting_options' ) );
add_action( 'admin_notices', array( $this, 'qsm_admin_notices' ) );
add_filter( 'manage_edit-qsm_category_columns', array( $this, 'modify_qsm_category_columns' ) );
add_action( 'admin_init', array( $this, 'has_alter_table_issue_solved' ), 999 );
}

/**
* Check if alter table issue has been solved by trying failed alter table query
*
* @since 9.0.2
*
* @return void
*/
public function has_alter_table_issue_solved() {
// Get failed alter table query list.
$failed_queries = $this->get_failed_alter_table_queries();
if ( ! empty( $failed_queries ) ) {
foreach ( $failed_queries as $failed_query ) {
$failed_query = $this->wpdb_alter_table_query( $failed_query );
// exit loop if query failed to execute
if ( false === $failed_query ) {
break;
}
}
}
}

/**
Expand Down Expand Up @@ -656,6 +742,10 @@ public function setup_admin_menu() {
}
add_submenu_page( 'options.php', __( 'Settings', 'quiz-master-next' ), __( 'Settings', 'quiz-master-next' ), 'edit_posts', 'mlw_quiz_options', 'qsm_generate_quiz_options' );
add_submenu_page( 'qsm_dashboard', __( 'Results', 'quiz-master-next' ), __( 'Results', 'quiz-master-next' ), 'moderate_comments', 'mlw_quiz_results', 'qsm_generate_admin_results_page' );

// Failed Submission.
add_submenu_page( 'qsm_dashboard', __( 'Failed Submission', 'quiz-master-next' ), __( 'Failed Submission', 'quiz-master-next' ), 'moderate_comments', 'mlw_quiz_failed_submission', array( $this,'admin_failed_submission_page' ) );

add_submenu_page( 'options.php', __( 'Result Details', 'quiz-master-next' ), __( 'Result Details', 'quiz-master-next' ), 'moderate_comments', 'qsm_quiz_result_details', 'qsm_generate_result_details' );
add_submenu_page( 'qsm_dashboard', __( 'Settings', 'quiz-master-next' ), __( 'Settings', 'quiz-master-next' ), 'manage_options', 'qmn_global_settings', array( 'QMNGlobalSettingsPage', 'display_page' ) );
add_submenu_page( 'qsm_dashboard', __( 'Tools', 'quiz-master-next' ), __( 'Tools', 'quiz-master-next' ), 'manage_options', 'qsm_quiz_tools', 'qsm_generate_quiz_tools' );
Expand All @@ -671,6 +761,26 @@ public function setup_admin_menu() {
}
}

/**
* Failed Submission Table
*
* Display failed submission table.
*
* @since 9.0.2
* @return void
*/
public function admin_failed_submission_page() {
$file_path = trailingslashit( plugin_dir_path( __FILE__ ) ) . 'php/admin/class-failed-submission.php';
if ( file_exists( $file_path ) ) {
include_once $file_path;
if ( ! class_exists( 'QmnFailedSubmissions' ) ) {
return;
}
$QmnFailedSubmissions = new QmnFailedSubmissions();
$QmnFailedSubmissions->render_list_table();
}
}

/**
* Removes Unnecessary Admin Page
*
Expand Down Expand Up @@ -740,6 +850,17 @@ public function qsm_admin_notices() {
</div>
<?php
}

// Get failed alter table query list.
$failed_queries = $this->get_failed_alter_table_queries();
if ( ! empty( $failed_queries ) && 0 < count( $failed_queries ) ) {
?>
<div class="notice notice-warning is-dismissible qmn-database-user-incorrect-permission">
<p><?php esc_html_e( "It seems your database user doesn't have permission to ALTER TABLE. Please ensure the necessary permissions are in place or contact your hosting provider.", "quiz-master-next" ); ?></p>
</div>
<?php
}

}


Expand Down
199 changes: 199 additions & 0 deletions php/admin/class-failed-submission.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
<?php
/**
* Creates the failed submission page within the admin area
*
* @package QSM
* @since 9.0.2
*/

if ( ! defined( 'ABSPATH' ) ) {
exit;
}

/**
* Abort if the class is already exists.
*/
if ( ! class_exists( 'QmnFailedSubmissions' ) && class_exists( 'WP_List_Table' ) ) {
/**
* This class display failed submission list table
*
* @since 9.0.2
*/
class QmnFailedSubmissions extends WP_List_Table {

/**
* Holds meta_key name
*
* @var object
* @since 9.0.2
*/
public $meta_key = '_qmn_log_result_insert_data';

/**
* Holds table_data
*
* @var object
* @since 9.0.2
*/
private $table_data = array();

public function __construct() {
parent::__construct(
array(
'plural' => 'submissions',
'singular' => 'submission',
'ajax' => false,
)
);
}

/**
* Prepares the list of items for displaying.
*/
public function prepare_items() {
// QMN Error log.
$posts = get_posts(
array(
'post_type' => 'qmn_log',
'meta_key' => $this->meta_key,
'post_status' => 'publish',
'fields' => 'ids',
'posts_per_page' => -1,
)
);

$posts = empty( $posts ) ? array() : $posts;
$per_page = 20;
if ( ! empty( $posts ) ) {
$current_page = intval( $this->get_pagenum() ) - 1;
$post_start_postion = $per_page * $current_page;

foreach ( $posts as $index => $postID ) {
if ( $post_start_postion > $index || $index >= ( $post_start_postion + $per_page ) ) {
continue;
}
$data = get_post_meta( $postID, $this->meta_key, true );
if ( empty( $data ) ) {
continue;
}
$data = maybe_unserialize( $data );
if ( ! is_array( $data ) || ! empty( $data['deleted'] ) || empty( $data['qmn_array_for_variables'] ) ) {
continue;
}
$data['qmn_array_for_variables']['post_id'] = $postID;
$this->table_data[] = $data['qmn_array_for_variables'];
}
}

// pagination.
$this->set_pagination_args(
array(
'total_items' => count( $posts ),
'per_page' => $per_page,
)
);

// table data.
$this->items = $this->table_data;

// table headers.
$this->_column_headers = array(
$this->get_columns(),
$this->get_hidden_columns(),
array(), // Sortable column
'cb', // Primary column
);
}

/**
* Gets a list of columns.
*
* @return array
*/
public function get_columns() {
return array(
'cb' => '<input type="checkbox" />',
'post_id' => __( 'ID', 'quiz-master-next' ),
'quiz_name' => __( 'Quiz Name', 'quiz-master-next' ),
'user_name' => __( 'Name', 'quiz-master-next' ),
'user_email' => __( 'Email', 'quiz-master-next' ),
'submission_action' => __( 'Action', 'quiz-master-next' ),
);
}

/**
* Gets a list of hidden columns.
*
* @return array
*/
public function get_hidden_columns() {
return array(
'post_id',
);
}

public function column_cb( $submission ) {
return sprintf(
'<input type="checkbox" name="post_id[]" value="%d" /> ',
$submission['post_id']
);
}

public function column_default( $submission, $column_name ) {
$column_value = '';
switch ( $column_name ) {
case 'post_id':
$column_value = $submission['post_id'];
break;
case 'quiz_name':
$column_value = $submission['quiz_name'];
break;
case 'user_name':
$column_value = $submission['user_name'];
break;
case 'user_email':
$column_value = $submission['user_email'];
break;
case 'submission_action':
$column_value = '<a href="' . esc_url( admin_url( 'admin.php?action=retrieve&post_id=' . esc_attr( $submission['post_id'] ) . '&qmnnonce=' . wp_create_nonce( 'qmn_failed_submission' ) ) ) . '" class="qmn-delete-failed-submission" >' . __( 'Retrieve', 'quiz-master-next' ) . '</a>';
break;
default:
break;
}

return $column_value;
}

public function get_bulk_actions() {
return array(
'retrieve' => __( 'Retrieve', 'quiz-master-next' ),
'trash' => __( 'Delete', 'quiz-master-next' ),
);
}

/**
* Render page with this table
*
* @param class $store
*/
public function render_list_table() {

$this->prepare_items();
// header.
echo '<div class="qmn-failed-submission wrap">';
// heading.
echo '<h2 id="result_details" >' . esc_html__( 'Failed Submissions', 'quiz-master-next' ) . '</h2>';
// body.
echo '<div class="qmn-body">';
echo "<form method='post' name='search_form' action='" . esc_url( admin_url( 'admin.php?page=mlw_quiz_failed_submission' ) ) . "'>";
echo '<div class="submission-filter-wrapper" >';
$this->views();
echo '</div>';
echo '<input type="hidden" name="qmnnonce" value="' . wp_create_nonce( 'qmn_failed_submission' ) . '" />';
$this->display();
echo '</form>';
echo '</div>';
echo '</div>';
}
}
}
Loading
Loading