芝麻web文件管理V1.00
编辑当前文件:/home/sditechnicalteam/socialdigivlms.com/wp-content/plugins/tutor/classes/Instructors_List.php
* @link https://themeum.com * @since 1.0.0 */ namespace TUTOR; if ( ! defined( 'ABSPATH' ) ) { exit; } use TUTOR\Students_List; use TUTOR\Backend_Page_Trait; use Tutor\Cache\TutorCache; use Tutor\Helpers\QueryHelper; /** * Instructors_List class * * @since 1.0.0 */ class Instructors_List { const INSTRUCTOR_LIST_PAGE = 'tutor-instructors'; const INSTRUCTOR_LIST_CACHE_KEY = 'tutor-instructors-list'; const INSTRUCTOR_COUNT_CACHE_KEY = 'tutor-instructors-count'; /** * Trait for utilities * * @var $page_title */ use Backend_Page_Trait; /** * Page Title * * @var $page_title */ public $page_title; /** * Bulk Action * * @var $bulk_action */ public $bulk_action = true; /** * Constructor * * @since 1.0.0 * @return void */ public function __construct() { $this->page_title = __( 'Instructor', 'tutor' ); /** * Handle bulk action * * @since 2.0.0 */ add_action( 'wp_ajax_tutor_instructor_bulk_action', array( $this, 'instructor_bulk_action' ) ); } /** * Available tabs that will visible on the right side of page navbar * * @since 2.0.0 * * @param string $search instructor search | optional. * @param string $course_id course id that belong to instructor | optional. * @param string $date user registered date | optional. * * @return array */ public function tabs_key_value( $search = '', $course_id = '', $date = '' ): array { $url = apply_filters( 'tutor_data_tab_base_url', get_pagenum_link() ); $approve = self::count_total_instructors( array( 'approved' ), $search, $course_id, $date, 'approved' ); $pending = self::count_total_instructors( array( 'pending' ), $search, $course_id, $date, 'pending' ); $blocked = self::count_total_instructors( array( 'blocked' ), $search, $course_id, $date, 'blocked' ); $tabs = array( array( 'key' => 'all', 'title' => __( 'All', 'tutor' ), 'value' => $approve + $pending + $blocked, 'url' => $url . '&data=all', ), array( 'key' => 'approved', 'title' => __( 'Approve', 'tutor' ), 'value' => $approve, 'url' => $url . '&data=approved', ), array( 'key' => 'pending', 'title' => __( 'Pending', 'tutor' ), 'value' => $pending, 'url' => $url . '&data=pending', ), array( 'key' => 'blocked', 'title' => __( 'Block', 'tutor' ), 'value' => $blocked, 'url' => $url . '&data=blocked', ), ); return $tabs; } /** * Prepare bulk actions that will show on dropdown options * * @since 2.0.0 * @return array */ public function prpare_bulk_actions(): array { $actions = array( $this->bulk_action_default(), $this->bulk_action_approved(), $this->bulk_action_pending(), $this->bulk_action_blocked(), ); return $actions; } /** * Handle bulk action for instructor delete * * @since 2.0.0 * @return string JSON response. */ public function instructor_bulk_action() { tutor_utils()->checking_nonce(); // Check if user is privileged. if ( ! current_user_can( 'administrator' ) ) { wp_send_json_error( tutor_utils()->error_message() ); } $action = Input::post( 'bulk-action', '' ); $bulk_ids = Input::post( 'bulk-ids', '' ); Input::has( 'bulkIds' ) ? $bulk_ids = Input::post( 'bulkIds' ) : 0; if ( '' === $action || '' === $bulk_ids ) { return wp_send_json_error(); } if ( 'delete' === $action ) { // Delete user from student_list class. do_action( 'tutor_before_instructor_delete', $bulk_ids ); $response = Students_List::delete_students( $bulk_ids ); do_action( 'tutor_after_instructor_delete', $bulk_ids ); } else { do_action( 'tutor_before_instructor_update', $bulk_ids ); $response = self::update_instructors( $action, $bulk_ids ); do_action( 'tutor_after_instructor_delete', $bulk_ids ); } $message = 'Instructor status updated'; return true === $response ? wp_send_json_success( array( 'status' => $message ) ) : wp_send_json_error(); } /** * Execute bulk action for enrollment list ex: complete | cancel * * @since 2.0.0 * * @param string $status hold status for updating. * @param string $user_ids comma seperated user ids. * * @return bool */ public static function update_instructors( $status, $user_ids ): bool { global $wpdb; $status = sanitize_text_field( $status ); $instructor_table = $wpdb->usermeta; $ids = array_map( 'intval', explode( ',', $user_ids ) ); $in_clause = QueryHelper::prepare_in_clause( $ids ); //phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared $update = $wpdb->query( $wpdb->prepare( "UPDATE {$instructor_table} SET meta_value = %s WHERE user_id IN ($in_clause) AND meta_key = %s", $status, '_tutor_instructor_status' ) ); //phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared // Remove role. if ( 'pending' === $status || 'blocked' === $status ) { $arr = explode( ',', $user_ids ); foreach ( $arr as $instructor_id ) { $instructor_id = (int) sanitize_text_field( $instructor_id ); if ( 'pending' === $status ) { self::remove_instructor_role( $instructor_id, $status ); } else { self::instructor_blockage( $instructor_id ); } } } if ( 'reject' === $status ) { $arr = explode( ',', $user_ids ); foreach ( $arr as $instructor_id ) { $instructor_id = (int) sanitize_text_field( $instructor_id ); self::instructor_rejection( $instructor_id ); } } if ( 'approved' === $status ) { $arr = explode( ',', $user_ids ); foreach ( $arr as $instructor_id ) { $instructor_id = (int) sanitize_text_field( $instructor_id ); self::add_instructor_role( $instructor_id, $status ); } } return false === $update ? false : true; } /** * Get total course. * * @since 1.0.0 * * @param object $item item. * @return void */ public function column_total_course( $item ) { global $wpdb; $course_post_type = tutor()->course_post_type; $total_course = (int) $wpdb->get_var( $wpdb->prepare( "SELECT count(ID) from {$wpdb->posts} WHERE post_author=%d AND post_type=%s ", $item->ID, $course_post_type ) ); echo esc_html( $total_course ); } /** * Initialize instructor_role to a user * * @since 1.0.0 * * @param integer $instructor_id | user id that need to add role. * @param string $status | status that will added with role (approved). * * @return void */ protected static function add_instructor_role( int $instructor_id, string $status ) { $instructor_id = sanitize_text_field( $instructor_id ); $status = sanitize_text_field( $status ); do_action( 'tutor_before_approved_instructor', $instructor_id ); update_user_meta( $instructor_id, '_tutor_instructor_status', $status ); update_user_meta( $instructor_id, '_tutor_instructor_approved', tutor_time() ); $instructor = new \WP_User( $instructor_id ); $instructor->add_role( tutor()->instructor_role ); // TODO: send E-Mail to this user about instructor approval, should via hook. do_action( 'tutor_after_approved_instructor', $instructor_id ); } /** * Initialize instructor_role to a user * * @since 1.0.0 * * @param int $instructor_id | user id that need to add role. * @param string $status | status that will added with role (approved). * * @return void */ protected static function remove_instructor_role( int $instructor_id, string $status ) { $instructor_id = sanitize_text_field( $instructor_id ); $status = sanitize_text_field( $status ); update_user_meta( $instructor_id, '_tutor_instructor_status', $status ); $instructor = new \WP_User( $instructor_id ); $instructor->remove_role( tutor()->instructor_role ); } /** * Instructor blocking function * * @since 2.5.0 * * @param int $instructor_id | user id that need to add role. * @return void */ protected static function instructor_blockage( int $instructor_id ) { $instructor_id = sanitize_text_field( $instructor_id ); do_action( 'tutor_before_blocked_instructor', $instructor_id ); self::remove_instructor_role( $instructor_id, 'blocked' ); do_action( 'tutor_after_blocked_instructor', $instructor_id ); } /** * Instructor rejection function * * @since 2.5.0 * * @param int $instructor_id | user id that need to add role. * @return void */ protected static function instructor_rejection( int $instructor_id ) { $instructor_id = sanitize_text_field( $instructor_id ); do_action( 'tutor_before_rejected_instructor', $instructor_id ); /** * Removed tutor_instructor role and set `try_again` status * for apply again as instructor with show message to applier in frontend. */ self::remove_instructor_role( $instructor_id, 'try_again' ); delete_user_meta( $instructor_id, '_is_tutor_instructor' ); do_action( 'tutor_after_rejected_instructor', $instructor_id ); } /** * Get instructors list * * @since 2.1.7 * * @param array $status instructor status: approved, pending, block. * @param int $offset offset for pagination. * @param int $per_page per page limit. * @param string $search search keyword. * @param string $course_id course id. * @param string $date instructor registration date. * @param string $order sorting order. * * @return wpdb::results */ public static function get_instructors( array $status, $offset, $per_page, $search = '', $course_id = '', $date = '', $order = 'DESC' ) { global $wpdb; $wild = '%'; $search_clause = $wild . $wpdb->esc_like( $search ) . $wild; $course_clause = ''; if ( '' !== $course_id ) { $course_id = (int) $course_id; $course_clause = "AND umeta.meta_value = {$course_id}"; } $order_clause = ''; if ( '' !== $order ) { $is_valid_sql = sanitize_sql_orderby( $order ); if ( $is_valid_sql ) { $order_clause = "ORDER BY user.ID {$order}"; } } $date_clause = '' !== $date ? "AND DATE(user.user_registered) = CAST('$date' AS DATE )" : ''; $in_clause = QueryHelper::prepare_in_clause( $status ); $query = "SELECT DISTINCT user.*, ins_status.meta_value AS status, ( SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_author = user.ID AND post_type = 'courses' ) total_courses FROM {$wpdb->users} AS user INNER JOIN {$wpdb->usermeta} AS ins_status ON ( user.ID = ins_status.user_id ) AND ins_status.meta_key = '_tutor_instructor_status' LEFT JOIN {$wpdb->usermeta} AS umeta ON umeta.user_id = user.ID AND umeta.meta_key = '_tutor_instructor_course_id' WHERE ins_status.meta_value IN ($in_clause) AND (user.user_email LIKE %s OR user.display_name LIKE %s) {$course_clause} {$date_clause} {$order_clause} LIMIT %d, %d; "; $result = TutorCache::get( self::INSTRUCTOR_LIST_CACHE_KEY ); if ( false === $result ) { TutorCache::set( self::INSTRUCTOR_LIST_CACHE_KEY, //phpcs:disable $result = $wpdb->get_results( $wpdb->prepare( $query, $search_clause, $search_clause, $offset, $per_page ) ) //phpcs:enable ); } return $result; } /** * Count total instructors * * @since 2.1.7 * * @param array $status instructor status: approved, pending, block. * @param string $search search keyword. * @param string $course_id course id. * @param string $date instructor registration date. * @param string $unique_cache_key unique key will be append with * self::INSTRUCTOR_COUNT_CACHE_KEY so that multiple count value could be * stored as unique data. * * @return int count value of instructors */ public static function count_total_instructors( array $status, $search = '', $course_id = '', $date = '', $unique_cache_key = '' ) { global $wpdb; $wild = '%'; $search_clause = $wild . $wpdb->esc_like( $search ) . $wild; $course_clause = ''; if ( '' !== $course_id ) { $course_id = (int) $course_id; $course_clause = "AND umeta.meta_value = {$course_id}"; } $date_clause = '' !== $date ? "AND DATE(user.user_registered) = CAST('$date' AS DATE )" : ''; $in_clause = QueryHelper::prepare_in_clause( $status ); $query = "SELECT COUNT(DISTINCT user.ID) FROM {$wpdb->users} AS user INNER JOIN {$wpdb->usermeta} AS ins_status ON ( user.ID = ins_status.user_id ) AND ins_status.meta_key = '_tutor_instructor_status' LEFT JOIN {$wpdb->usermeta} AS umeta ON umeta.user_id = user.ID AND umeta.meta_key = '_tutor_instructor_course_id' WHERE ins_status.meta_value IN ($in_clause) AND (user.user_email LIKE %s OR user.display_name LIKE %s) {$course_clause} {$date_clause} "; $result = TutorCache::get( self::INSTRUCTOR_COUNT_CACHE_KEY . $unique_cache_key ); if ( false === $result ) { TutorCache::set( self::INSTRUCTOR_COUNT_CACHE_KEY, //phpcs:disable $result = $wpdb->get_var( $wpdb->prepare( $query, $search_clause, $search_clause ) ) //phpcs:enable ); } return $result; } }