download_order_csv_file(); // Override title of LP Order on Admin if ( is_admin() ) { $can_override_title_order = false; $current_url = LP_Helper::getUrlCurrent(); $post_id = LP_Helper::sanitize_params_submitted( $_GET['post'] ?? '' ); if ( ! empty( $post_id ) ) { $post = get_post( $post_id ); if ( $post && $post->post_type == LP_ORDER_CPT ) { $can_override_title_order = true; } } elseif ( strpos( $current_url, 'post_type=lp_order' ) !== false ) { $can_override_title_order = true; } if ( $can_override_title_order ) { add_filter( 'the_title', array( $this, 'order_title' ), 5, 2 ); } } parent::__construct(); } /** * Declare class name of table list orders. * * @param string $class_name * @param array $args * * @return string * @since 4.2.9.5 */ public function wp_list_table_class_name( $class_name, $args ) { if ( $this->check_class_name_handle_table( $args['screen'] ) ) { $class_name = OrdersTable::class; } return $class_name; } /** * Unset value in 'mine' key in views of LP Orders. * The 'mine' is present in some case when 'user_posts_count' * is not the same with total posts then wp add it to the views * of WP Posts List table. * * @param array $views * * @return mixed */ public function filter_views( $views ) { if ( isset( $views['mine'] ) ) { unset( $views['mine'] ); } return $views; } /** * Filter to hide orders are created by one order for multiple users. * * @param string $where * * @return string */ public function filter_orders( string $where ): string { if ( ! $this->is_page_list_posts_on_backend() ) { return $where; } global $wpdb; if ( isset( $_REQUEST['parent'] ) ) { $where .= sprintf( ' AND post_parent = %d ', absint( $_REQUEST['parent'] ) ); } else { // $where .= $wpdb->prepare( " AND (post_parent = 0 OR {$wpdb->posts}.ID IN( SELECT post_parent FROM {$wpdb->posts} X WHERE X.post_parent <> 0 AND X.post_type = %s) )", LP_ORDER_CPT ); $where .= ' AND post_parent = 0 '; } return $where; } public function enqueue_scripts() { if ( get_post_type() != $this->_post_type ) { return; } wp_enqueue_script( 'user-suggest' ); } /** * Restore user course item when the order is stored (usually from trash). * * @param string $new_status * @param int $post_id * @param string $previous_status * * @return string */ public function restore_status_order( string $new_status, int $post_id, string $previous_status ): string { if ( LP_ORDER_CPT != get_post_type( $post_id ) ) { return $new_status; } return $previous_status; } /** * Save order post. * * @param int $post_id * @param WP_Post $post * @param bool $is_update * * @editor tungnx * @version 1.0.6 */ public function save_post( int $post_id, ?WP_Post $post = null, bool $is_update = false ) { try { $backtrace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); if ( isset( $backtrace[6]['class'] ) && $backtrace[6]['class'] === LP_Order_CURD::class ) { return; } if ( wp_is_post_revision( $post_id ) ) { return; } // For create LP Order manual on Backend $order = learn_press_get_order( $post_id ); if ( ! $order ) { return; } $created_via = $order->get_created_via(); if ( empty( $created_via ) ) { $created_via = LP_ORDER_CREATED_VIA_MANUAL; $order->set_created_via( $created_via ); } if ( isset( $_POST['order-customer'] ) && $order->is_manual() ) { $user_id = LP_Request::get_param( 'order-customer' ); $order->set_user_id( $user_id ); } $status = LP_Request::get_param( 'order-status' ); if ( ! empty( $status ) ) { $order->update_status( $status ); } elseif ( $post->post_status === 'auto-draft' ) { $order->update_status( 'pending' ); } $order->save(); } catch ( Throwable $e ) { error_log( __METHOD__ . ':' . $e->getMessage() ); } } /** * Remove unused boxes */ public function remove_box() { remove_post_type_support( LP_ORDER_CPT, 'title' ); remove_post_type_support( LP_ORDER_CPT, 'editor' ); } public function admin_footer() { if ( ! $this->is_page_list_posts_on_backend() ) { return; } ?> post_type = LP_ORDER_CPT; $lp_filter_post->post_status = [ 'lp-trash' ]; $orders_trash = LP_Post_DB::getInstance()->get_posts( $lp_filter_post ); if ( $orders_trash ) { foreach ( $orders_trash as $order_trash ) { $order = learn_press_get_order( $order_trash->ID ); if ( $order ) { $order->update_status( 'trash' ); } } } // Change status course from lp_trash to trash. // End code temporary global $wpdb, $wp_query; $lp_db = LP_Database::getInstance(); if ( is_admin() && $this->is_page_list_posts_on_backend() ) { $where = ' '; $where .= $wpdb->prepare( " AND {$lp_db->tb_posts}.post_type = %s", LP_ORDER_CPT ); } // Search by keyword if ( ! empty( $wp_query->get( 's' ) ) ) { $s = $wp_query->get( 's' ); // Check search LP Order ID with format #000[ID] or 000[ID] $pattern = '/^#\d+$/'; if ( preg_match( $pattern, $s ) ) { $s = str_replace( '#', '', $s ); } $pattern2 = '#^0+.*\d+$#'; if ( preg_match( $pattern2, $s ) ) { $s = (int) $s; } $s = trim( $s ); $where .= $wpdb->prepare( " AND {$lp_db->tb_posts}.ID = %d", $s ); $where .= $wpdb->prepare( ' OR lpori.order_item_name like %s', '%' . $wpdb->esc_like( $s ) . '%' ); } // Search by author id if ( ! empty( $wp_query->get( 'author' ) ) ) { $user_id = absint( $wp_query->get( 'author' ) ); //$where .= $wpdb->prepare( ' AND uu.ID like %s ', $user_id ); $where .= " AND ( pm1.meta_value like '%\"$user_id\"%' OR pm1.meta_value = $user_id ) "; } if ( ! empty( $wp_query->get( 'm' ) ) ) { $month = $wp_query->get( 'm' ); $where .= " AND YEAR({$lp_db->tb_posts}.post_date)=" . substr( $month, 0, 4 ); if ( strlen( $month ) > 5 ) { $where .= " AND MONTH({$lp_db->tb_posts}.post_date)=" . substr( $month, 4, 2 ); } } // Filter by order status if ( ! empty( $wp_query->get( 'post_status' ) ) ) { $status = $wp_query->get( 'post_status' ); $where .= $wpdb->prepare( " AND {$lp_db->tb_posts}.post_status = %s", $status ); } else { $where .= $wpdb->prepare( " AND {$lp_db->tb_posts}.post_status NOT IN (%s, %s, %s)", LP_ORDER_TRASH_DB, LP_ORDER_TRASH, 'auto-draft' ); } return $where; }*/ // public function posts_orderby( $orderby ) { // global $wpdb; // // $order = $this->get_order_sort(); // // switch ( $this->get_order_by() ) { // case 'title': // $orderby = "{$wpdb->posts}.ID {$order}"; // break; // *case 'student': // $orderby = "uu.user_login {$order}"; // break;*/ // case 'date': // $orderby = "{$wpdb->posts}.post_date {$order}"; // break; // case 'order_total': // $orderby = "CAST(pm2.meta_value AS UNSIGNED) {$order}"; // break; // } // // return $orderby; // } /* public function posts_join_paged( $join ) { global $wpdb, $wp_query; $lp_db = LP_Database::getInstance(); // Search by keyword if ( ! empty( $wp_query->get( 's' ) ) ) { $join .= " INNER JOIN {$lp_db->tb_lp_order_items} lpori ON {$wpdb->posts}.ID = lpori.order_id"; } if ( ! empty( $wp_query->get( 'author' ) ) ) { $author_id = $wp_query->get( 'author' ); $join .= " INNER JOIN {$lp_db->tb_postmeta} pm1 ON {$wpdb->posts}.ID = pm1.post_id AND pm1.meta_key = '_user_id'"; $join .= " LEFT JOIN {$lp_db->tb_users} uu ON uu.ID = $author_id"; } if ( $this->get_order_by() === 'order_total' ) { $join .= " INNER JOIN {$lp_db->tb_postmeta} pm2 ON {$wpdb->posts}.ID = pm2.post_id AND pm2.meta_key = '_order_total'"; } return $join; }*/ public function update_status() { $order_id = ! empty( $_REQUEST['order_id'] ) ? absint( $_REQUEST['order_id'] ) : 0; $status = ! empty( $_REQUEST['status'] ) ? LP_Helper::sanitize_params_submitted( $_REQUEST['status'] ) : 'Pending'; learn_press_update_order_status( $order_id, $status ); wp_send_json( array( 'status' => $status, 'class' => sanitize_title( $status ), ) ); } /** * Custom row's actions. * * @param array $actions * @param WP_Post $post * * @return mixed * @since 2.1.7 * @deprecated 4.2.6.4 */ /* public function row_actions( $actions, $post ) { if ( ! empty( $actions['inline hide-if-no-js'] ) ) { unset( $actions['inline hide-if-no-js'] ); } if ( ! empty( $actions['edit'] ) ) { $actions['edit'] = preg_replace( '/>(.*?)<\/a>/', '>' . __( 'View Order', 'learnpress' ) . '', $actions['edit'] ); } return $actions; }*/ /** * re-order the orders by newest * * @param WP_Query $wp_query * * @editor tungnx * @reason comment this function - because default sort by id * * @return mixed */ public function pre_get_posts( $wp_query ) { if ( ! is_admin() ) { return $wp_query; } $post_type = $wp_query->get( 'post_type' ); if ( empty( $post_type ) || $post_type != LP_ORDER_CPT ) { return $wp_query; } if ( is_admin() ) { $wp_query->set( 'orderby', 'date' ); $wp_query->set( 'order', 'desc' ); } $post_status = $wp_query->get( 'post_status' ); if ( empty( $post_status ) || $post_status == 'all' ) { $wp_query->set( 'post_status', array( LP_ORDER_COMPLETED_DB, LP_ORDER_PROCESSING_DB, LP_ORDER_PENDING_DB, LP_ORDER_FAILED_DB, LP_ORDER_CANCELLED_DB, LP_ORDER_REFUNDED_DB, ) ); } // Search by author id /* if ( ! empty( $wp_query->get( 'author' ) ) ) { $user_id = absint( $wp_query->get( 'author' ) ); //$where .= $wpdb->prepare( ' AND uu.ID like %s ', $user_id ); $where .= " AND ( pm1.meta_value like '%\"$user_id\"%' OR pm1.meta_value = $user_id ) "; }*/ $post_author = $wp_query->get( 'author' ); if ( ! empty( $post_author ) ) { $user_id = absint( $post_author ); $meta_query = array( // 'relation' => 'OR', array( 'key' => '_user_id', 'value' => '%"' . $user_id . '"%', 'compare' => 'LIKE', ), // array( // 'key' => '_user_id', // 'value' => $user_id, // 'compare' => '=', // ), ); $wp_query->set( 'meta_query', $meta_query ); } return $wp_query; } /** * Query lp orders in admin via Post DB * * @param array $posts * @param WP_Query $wp_query * * @return array|WP_Query */ public function posts_pre_query( $posts, $wp_query ) { try { if ( ! is_admin() ) { return $posts; } $post_type = $wp_query->get( 'post_type' ); if ( empty( $post_type ) || $post_type != LP_ORDER_CPT ) { return $posts; } // Convert params from WP_Query to PostFilter $posts_per_page = get_user_option( "edit_{$post_type}_per_page", get_current_user_id() ); if ( empty( $posts_per_page ) ) { $posts_per_page = 20; } $paged = max( 1, get_query_var( 'paged' ) ); $user_of_order = $wp_query->get( 'author' ); $status = $wp_query->get( 'post_status' ); $key = $wp_query->get( 's' ); $month = $wp_query->get( 'm' ); $refund_request_status = LP_Request::get_param( 'refund_request_status', '', 'key', 'get' ); $filter = new OrderPostFilter(); $param = array( 'paged' => $paged, 'posts_per_page' => $posts_per_page, 'author' => $user_of_order, 'post_status' => $status, 's' => $key, 'm' => $month, 'refund_request_status' => $refund_request_status, 'orderby' => $wp_query->get( 'orderby' ), 'order' => $wp_query->get( 'order' ), ); LP_Order::handle_params_query_list_orders( $filter, $param ); // Get lp orders $post_db = PostDB::getInstance(); $total_rows = 0; $lp_orders = $post_db->get_posts( $filter, $total_rows ); $wp_query->post_count = $total_rows; $wp_query->found_posts = $total_rows; $posts = $lp_orders; } catch ( Throwable $e ) { LP_Debug::error_log( $e ); } return $posts; } public function order_title( $title, $post_id ) { if ( get_post_type( $post_id ) != LP_ORDER_CPT ) { return $title; } return learn_press_transaction_order_number( $post_id ); } /** * Register order post type */ public function args_register_post_type(): array { return array( 'labels' => array( 'name' => __( 'Orders', 'learnpress' ), 'menu_name' => __( 'Orders', 'learnpress' ), 'singular_name' => __( 'Order', 'learnpress' ), 'add_new_item' => __( 'Add A New Order', 'learnpress' ), 'edit_item' => __( 'Order Details', 'learnpress' ), 'all_items' => __( 'Orders', 'learnpress' ), 'view_item' => __( 'View Order', 'learnpress' ), 'add_new' => __( 'Add New', 'learnpress' ), 'update_item' => __( 'Update Order', 'learnpress' ), 'search_items' => __( 'Search Orders', 'learnpress' ), 'not_found' => __( 'No order found', 'learnpress' ), 'not_found_in_trash' => __( 'There was no order found in the trash', 'learnpress' ), ), 'public' => false, 'show_ui' => true, 'show_in_nav_menus' => false, 'show_in_admin_bar' => false, 'publicly_queryable' => false, 'show_in_menu' => 'learn_press', 'map_meta_cap' => true, 'capability_type' => LP_ORDER_CPT, 'hierarchical' => false, 'rewrite' => array( 'slug' => LP_ORDER_CPT, 'hierarchical' => true, 'with_front' => true, ), 'supports' => array( 'title', 'custom-fields', ), 'exclude_from_search' => true, ); } /** * Register new post status for order * * @Todo when rewrite API, will remove this function * will be not use learn_press_get_register_order_statuses */ public function register_post_statues() { $statuses = learn_press_get_register_order_statuses(); foreach ( $statuses as $status => $args ) { register_post_status( $status, $args ); } } public static function instance() { if ( ! self::$_instance ) { self::$_instance = new self(); } return self::$_instance; } /** * Before post deleted * * @author tungnx * @since 4.1.4 * @version 1.0.1 */ public function before_delete( int $order_id ) { $lp_order_db = LP_Order_DB::getInstance(); $lp_user_items_db = LP_User_Items_DB::getInstance(); try { ini_set( 'max_execution_time', 0 ); $order = learn_press_get_order( $order_id ); if ( ! $order ) { return; } $items = $order->get_all_items(); if ( empty( $items ) ) { return; } $order_item_ids = array(); $user_ids = $order->get_users(); foreach ( $user_ids as $user_id ) { // delete_user_meta( $user_id, 'orders' ); foreach ( $items as $itemArr ) { $order_item_ids[] = $itemArr['order_item_id'] ?? 0; $item_type = $itemArr['item_type'] ?? ''; $userItemModel = UserItemModel::find_user_item( $user_id, $itemArr['item_id'] ?? 0, $item_type ?? '', $order_id, LP_ORDER_CPT ); if ( $userItemModel ) { if ( $item_type === LP_COURSE_CPT ) { $userCourseModel = new UserCourseModel( $userItemModel ); $userCourseModel->delete(); } else { $userItemModel->delete(); } } } do_action( 'learn-press/order/before-delete', $order, $user_id ); } // Delete lp_order_item, lp_order_itemmeta $filter_delete = new LP_Order_Filter(); $filter_delete->order_item_ids = $order_item_ids; $lp_order_db->delete_order_item( $filter_delete ); $lp_order_db->delete_order_itemmeta( $filter_delete ); // End ini_set( 'max_execution_time', LearnPress::$time_limit_default_of_sever ); } catch ( Throwable $e ) { error_log( $e->getMessage() . '>' . __FILE__ ); } } /** * Action delete Order * * @param int $order_id * * @author tungnx * @since 4.1.4 * @version 1.0.0 */ public function deleted_post( int $order_id ) { } public function meta_boxes() { return array( 'order_details' => array( 'title' => esc_html__( 'Order Details', 'learnpress' ), 'callback' => function ( $post ) { learn_press_admin_view( 'meta-boxes/order/details.php', array( 'order' => new LP_Order( $post ) ) ); }, 'context' => 'normal', 'priority' => 'high', ), 'submitdiv' => array( 'title' => esc_html__( 'Order Actions', 'learnpress' ), 'callback' => function ( $post ) { learn_press_admin_view( 'meta-boxes/order/actions.php', array( 'order' => new LP_Order( $post ) ) ); }, 'context' => 'side', 'priority' => 'high', ), 'order_exports' => array( 'title' => esc_html__( 'Order Exports', 'learnpress' ), 'callback' => function ( $post ) { learn_press_admin_view( 'meta-boxes/order/exports-invoice.php', array( 'order' => new LP_Order( $post ) ) ); }, 'context' => 'side', 'priority' => 'high', ), ); } /** * Download order CSV file and delete it after download * * @return void * @since 4.3.2.8 * @version 1.0.1 */ public function download_order_csv_file() { $export_id = LP_Request::get_param( 'export_id', '', 'key' ); if ( ! isset( $_GET['lp_download_order'] ) || empty( $export_id ) ) { return; } // Check permission if ( ! current_user_can( UserModel::ROLE_ADMINISTRATOR ) ) { return; } $file = ExportOrderCSVAjax::get_export_csv_path( $export_id ); if ( ! file_exists( $file ) ) { wp_die( __( 'File not found', 'learnpress' ) ); } elseif ( ! realpath( $file ) ) { wp_die( __( 'Invalid file path', 'learnpress' ) ); } $filename = basename( $file ); header( 'Content-Type: text/csv; charset=UTF-8' ); header( 'Content-Disposition: attachment; filename="' . $filename . '"' ); header( 'Content-Length: ' . filesize( $file ) ); readfile( $file ); unlink( $file ); exit; } } // end LP_Order_Post_Type $order_post_type = LP_Order_Post_Type::instance(); }