*/ class Wp_Database_Tools_Database_General extends Wp_Database_Tools_Database { /** * The general data of database. * * @since 1.0.0 * @access protected * @var array $data The general data of database. */ protected $data; public function __construct() { require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wp-database-tools-logger.php'; } public function check_data( $detail_post ) { global $wpdb; $this->data = array(); $detail_page = ( isset( $_GET['details'] ) ) ? $_GET['details'] : null; if ( $detail_page == null ) { $detail_page = ( $detail_post != null ) ? $detail_post : null; } // REVISIONS $key = 'revision'; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; $revisions = parent::execute_simple_query( 'posts', "post_type = 'revision'", $key, 'Revisions', true, $query ); $this->data[ $key ] = $revisions[ $key ]; // Autodrafts $key = 'autodraft'; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; $autodrafts = parent::execute_simple_query( 'posts', "post_status = 'auto-draft'", $key, 'Autodrafts', true, $query ); $this->data[ $key ] = $autodrafts[ $key ]; // Trashed posts $key = 'trash-posts'; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; $trash_posts = parent::execute_simple_query( 'posts', "post_status = 'trash'", $key, 'Trashed posts', true, $query ); $this->data[ $key ] = $trash_posts[ $key ]; // Pending Comments $key = 'pending-comments'; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; $pending_comments = parent::execute_simple_query( 'comments', "comment_approved = '0'", $key, 'Pending Comments', true, $query ); $this->data[ $key ] = $pending_comments[ $key ]; // Spam comments $key = 'span-comments'; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; $span_comments = parent::execute_simple_query( 'comments', "comment_approved = 'spam'", $key, 'Spam Comments', true, $query ); $this->data[ $key ] = $span_comments[ $key ]; // Trashed comments $key = 'trash-comments'; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; $trash_comments = parent::execute_simple_query( 'comments', "comment_approved = 'trash'", $key, 'Trashed comments', true, $query ); $this->data[ $key ] = $trash_comments[ $key ]; // Pingback comments $key = 'pingback-comments'; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; $pingback = parent::execute_simple_query( 'comments', "comment_type = 'pingback'", $key, 'Pingback comments', true, $query ); $this->data[ $key ] = $pingback[ $key ]; // Trackback comments $key = 'trackback-comments'; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; $trackback = parent::execute_simple_query( 'comments', "comment_type = 'trackback'", $key, 'Trackback comments', true, $query ); $this->data[ $key ] = $trackback[ $key ]; // Orphaned post meta $key = 'orphaned-post-meta'; $table = 'postmeta'; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; // TODO: $wpdb->prepare $orphaned_post_meta = parent::execute_complex_complex_query( $table, $query . ' FROM ' . $wpdb->prefix . $table . " pm LEFT JOIN {$wpdb->prefix}posts p ON p.ID = pm.post_id WHERE p.ID IS NULL", $key, 'Orphaned post meta', false, ); $this->data[ $key ] = $orphaned_post_meta[ $key ]; // Orphaned comment meta $key = 'orphaned-comment-meta'; $table = 'commentmeta'; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; // TODO: $wpdb->prepare $orphaned_comment_meta = parent::execute_complex_complex_query( $table, $query . ' FROM ' . $wpdb->prefix . $table . " cm LEFT JOIN {$wpdb->prefix}comments c ON c.comment_id = cm.comment_id WHERE c.comment_id IS NULL", $key, 'Orphaned comment meta', false, ); $this->data[ $key ] = $orphaned_comment_meta[ $key ]; // Orphaned user meta $key = 'orphaned-user-meta'; $table = 'usermeta'; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; // TODO: $wpdb->prepare $orphaned_user_meta = parent::execute_complex_complex_query( $table, $query . ' FROM ' . $wpdb->prefix . $table . " WHERE user_id NOT IN (SELECT ID FROM {$wpdb->prefix}users)", $key, 'Orphaned user meta', false, ); $this->data[ $key ] = $orphaned_user_meta[ $key ]; // Orphaned term meta $key = 'orphaned-term-meta'; $table = 'termmeta'; $table_name = $wpdb->prefix . $table; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; // TODO: $wpdb->prepare $orphaned_term_meta = parent::execute_complex_complex_query( $table, $query . ' FROM ' . $wpdb->prefix . $table . " WHERE term_id NOT IN (SELECT term_id FROM {$wpdb->prefix}terms)", 'orphaned-term-meta', 'Orphaned term meta', false, ); $this->data[ $key ] = $orphaned_term_meta[ $key ]; // Orphaned relationships $key = 'orphaned-relationships-meta'; $table = 'term_relationships'; $table_name = $wpdb->prefix . $table; $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; $sql = $wpdb->prepare( '%1s FROM %1s WHERE term_taxonomy_id = %d AND object_id NOT IN (SELECT id FROM %1s)', $query, $table_name, 1, $wpdb->prefix . 'posts' ); $orphaned_relationships = parent::execute_complex_complex_query( $table, $sql, $key, 'Orphaned relationships meta', false, ); $this->data[ $key ] = $orphaned_relationships[ $key ]; // Expired transients $key = 'expired-transients'; $table = 'options'; $table_name = $wpdb->prefix . $table; $time = isset( $_SERVER['REQUEST_TIME'] ) ? (int) $_SERVER['REQUEST_TIME'] : time(); $query = ( $detail_page == $key ) ? 'SELECT *' : 'SELECT COUNT(*) as total'; $sql = $wpdb->prepare( "%1s FROM %1s WHERE option_name LIKE ('%\_transient_timeout\_%') AND option_value < %s ", $query, $table_name, $time ); $expired_transients = parent::execute_complex_complex_query( $table, $sql, $key, 'Expired transients', false, ); $this->data[ $key ] = $expired_transients[ $key ]; } /** * Call a specific method depending on the action to be performed. * * @since 1.0.0 */ public function action_form() { // TODO: nonce verification. switch ( $_POST['action-type'] ) { case 'edit': $this->edit(); break; case 'delete': $this->delete(); break; } wp_redirect( $_POST['current-url'] . '&' . WPDBT_PREFIX . 'notice=general' ); } public function loop_delete_data( $detele_array, $table, $is_days, $index_key, $delete_action ) { $ids_array = array(); $meta_keys_array = array(); foreach ( $detele_array as $key => $row ) { if ( $delete_action != 'all' ) { if ( ! parent::can_delete( $is_days, $table, $index_key, $row ) ) { set_transient( WPDBT_PREFIX . 'warning', true ); continue; } } // Get data to call execute delete array_push( $ids_array, parent::get_ID( $table, $row ) ); } return array( 'ids' => $ids_array, 'meta_keys' => $meta_keys_array, ); } /** * Deletes the records that are indicated in $POST through keys. * These keys are used in a query. The result is stored in a transient, * which is then returned as a warning to the user.. * * @since 1.0.0 */ public function delete() { // TODO: nonce verification. $action_keys = $_POST['action-keys']; $details = $_POST['action-is-details']; $this->check_data( $details ); $action_keys = explode( '↕', $action_keys ); $delete_action = $_POST['action-delete']; if ( 'no' !== $details ) { // Prepare data. $table = $this->data[ $details ]['table']; $is_days = false; $index_key = $details; $array_data = $this->data[ $details ]['data']; $allowed_keys = $action_keys; $detele_array = array_intersect_key( $array_data, array_flip( $allowed_keys ) ); // Execute delete. $info_for_delete = $this->loop_delete_data( $detele_array, $table, $is_days, $index_key, $delete_action ); parent::execute_delete( $table, $info_for_delete['ids'], $info_for_delete['meta_keys'] ); } else { foreach ( $action_keys as $action_key ) { $this->check_data( $action_key ); // Prepare data. $table = $this->data[ $action_key ]['table']; $is_days = $this->data[ $action_key ]['is-days']; $index_key = $action_key; $detele_array = $this->data[ $action_key ]['data']; // Execute delete. $info_for_delete = $this->loop_delete_data( $detele_array, $table, $is_days, $index_key, $delete_action ); if ( ! empty( $info_for_delete['ids'] ) ) { parent::execute_delete( $table, $info_for_delete['ids'], $info_for_delete['meta_keys'] ); } unset( $action_key ); } } } /** * Edit the records that are indicated in $POST through keys. * These keys are used in a query. The result is stored in a transient, * which is then returned as a warning to the user.. * * @since 1.0.0 */ public function edit() { // TODO: nonce verification. // Save options days keep $current_options = get_option( WPDBT_PREFIX . 'user_options_general' ); if ( ! $current_options ) { $current_options = array(); } // Current days selected. $current_days_selected = $_POST['action-days']; // Prepare data. $action_keys = $_POST['action-keys']; $action_keys = explode( '↕', $action_keys ); $action_days = $_POST['action-is-days']; $action_days = explode( '↕', $action_days ); foreach ( $action_keys as $key => $value ) { if ( $action_days[ $key ] == 'yes' ) { $current_options[ $value ]['days'] = $current_days_selected; } } update_option( WPDBT_PREFIX . 'user_options_general', $current_options ); } /** * The array of data of general database. * * @since 1.0.0 * @return array The array of data. */ public function get_data() { return $this->data; } }