_x( 'Courses', 'Post Type General Name', 'learnpress' ), 'singular_name' => _x( 'Course', 'Post Type Singular Name', 'learnpress' ), 'menu_name' => __( 'Courses', 'learnpress' ), 'parent_item_colon' => __( 'Parent Item:', 'learnpress' ), 'all_items' => __( 'Courses', 'learnpress' ), 'view_item' => __( 'View Course', 'learnpress' ), 'add_new_item' => __( 'Add a New Course', 'learnpress' ), 'add_new' => __( 'Add New', 'learnpress' ), 'edit_item' => __( 'Edit Course', 'learnpress' ), 'update_item' => __( 'Update Course', 'learnpress' ), 'search_items' => __( 'Search Courses', 'learnpress' ), 'not_found' => sprintf( __( 'You have not had any courses yet. Click Add new to start', 'learnpress' ), admin_url( 'post-new.php?post_type=lp_course' ) ), 'not_found_in_trash' => __( 'There was no course found in the trash', 'learnpress' ), ); $course_base = LP_Settings::get_option( 'course_base', 'courses' ); $course_permalink = empty( $course_base ) ? 'courses' : $course_base; // Set to $has_archive return link to courses page, is_archive will check is true $courses_page_id = learn_press_get_page_id( 'courses' ); $has_archive = $courses_page_id ? urldecode( get_page_uri( $courses_page_id ) ) : 'courses'; $args = array( 'labels' => $labels, 'public' => true, 'query_var' => true, 'publicly_queryable' => true, 'show_ui' => true, 'has_archive' => $has_archive, 'capability_type' => $this->_post_type, 'map_meta_cap' => true, 'show_in_menu' => 'learn_press', 'show_in_admin_bar' => true, 'show_in_nav_menus' => true, 'show_in_rest' => true, 'taxonomies' => array( 'course_category', 'course_tag' ), 'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'comments', 'excerpt' ), 'hierarchical' => false, 'rewrite' => ! empty( $course_permalink ) ? array( 'slug' => untrailingslashit( $course_permalink ), 'with_front' => false, ) : false, ); return $args; } /** * Register course taxonomy. */ public function register_taxonomy() { $category_base = LP_Settings::get_option( 'course_category_base' ); register_taxonomy( 'course_category', array( LP_COURSE_CPT ), array( 'label' => __( 'Course Categories', 'learnpress' ), 'labels' => array( 'name' => __( 'Course Categories', 'learnpress' ), 'menu_name' => __( 'Course Category', 'learnpress' ), 'singular_name' => __( 'Category', 'learnpress' ), 'add_new_item' => __( 'Add A New Course Category', 'learnpress' ), 'all_items' => __( 'All Categories', 'learnpress' ), ), 'query_var' => true, 'public' => true, 'hierarchical' => true, 'show_ui' => true, 'show_in_menu' => 'learn_press', 'show_admin_column' => true, 'show_in_admin_bar' => true, 'show_in_nav_menus' => true, 'show_in_rest' => true, 'rewrite' => array( 'slug' => empty( $category_base ) ? 'course-category' : $category_base, 'hierarchical' => true, 'with_front' => false, ), ) ); $tag_base = LP_Settings::get_option( 'course_tag_base' ); register_taxonomy( 'course_tag', array( LP_COURSE_CPT ), array( 'labels' => array( 'name' => __( 'Course Tags', 'learnpress' ), 'singular_name' => __( 'Tag', 'learnpress' ), 'search_items' => __( 'Search Course Tags', 'learnpress' ), 'popular_items' => __( 'Popular Course Tags', 'learnpress' ), 'all_items' => __( 'All Course Tags', 'learnpress' ), 'parent_item' => null, 'parent_item_colon' => null, 'edit_item' => __( 'Edit Course Tag', 'learnpress' ), 'update_item' => __( 'Update Course Tag', 'learnpress' ), 'add_new_item' => __( 'Add A New Course Tag', 'learnpress' ), 'new_item_name' => __( 'New Course Tag Name', 'learnpress' ), 'separate_items_with_commas' => __( 'Separate tags with commas', 'learnpress' ), 'add_or_remove_items' => __( 'Add or remove tags', 'learnpress' ), 'choose_from_most_used' => __( 'Choose from the most used tags', 'learnpress' ), 'menu_name' => __( 'Course Tags', 'learnpress' ), ), 'public' => true, 'hierarchical' => false, 'show_ui' => true, 'show_in_menu' => 'learn_press', 'update_count_callback' => '_update_post_term_count', 'query_var' => true, 'show_in_rest' => true, 'rewrite' => array( 'slug' => empty( $tag_base ) ? 'course-tag' : $tag_base, 'with_front' => false, ), ) ); } /** * Declare class name of table list courses. * * @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 = CoursesTable::class; } return $class_name; } /** * Delete course sections before delete course. * * @param int $post_id * * @throws Exception * @since modify 4.0.9 * @since 3.0.0 * @editor tungnx */ public function before_delete( int $post_id ) { // Delete course from table learnpress_courses $courseModel = CourseModel::find( $post_id, true ); if ( $courseModel ) { $courseModel->delete(); } $course = learn_press_get_course( $post_id ); if ( ! $course ) { return; } $course->delete_relate_data_when_delete_course(); } /** * @param string $fields * * @return string */ public function posts_fields( $fields ): string { if ( ! $this->is_page_list_posts_on_backend() ) { return $fields; } $fields = ' DISTINCT ' . $fields; if ( $this->get_order_by() == 'price' ) { $fields .= ', pm_price.meta_value as course_price'; } return $fields; } public function _posts_join_paged_course_items( $join ) { global $wpdb; $course_id = $this->_filter_items_by_course(); if ( $course_id || LP_Request::get_param( 'orderby' ) === 'course-name' ) { $join .= " LEFT JOIN {$wpdb->prefix}learnpress_section_items si ON {$wpdb->posts}.ID = si.item_id"; $join .= " LEFT JOIN {$wpdb->prefix}learnpress_sections s ON s.section_id = si.section_id"; $join .= " LEFT JOIN {$wpdb->posts} c ON c.ID = s.section_course_id"; } return $join; } public function _posts_where_paged_course_items( $where ) { global $wpdb; $course_id = $this->_filter_items_by_course(); if ( $course_id ) { $where .= $wpdb->prepare( ' AND (c.ID = %d)', $course_id ); $where .= $wpdb->prepare( " AND {$wpdb->posts}.post_status = %s", 'publish' ); } return $where; } /** * @param $join * * @return string */ public function posts_join_paged( $join ) { global $wpdb; if ( ! $this->is_page_list_posts_on_backend() ) { return $join; } if ( ! isset( $_GET['orderby'] ) || $_GET['orderby'] !== 'price' ) { return $join; } $join .= " LEFT JOIN {$wpdb->postmeta} pm_price ON pm_price.post_id = {$wpdb->posts}.ID AND pm_price.meta_key = '_lp_price'"; return $join; } /** * @param $where * * @return mixed|string */ public function posts_where_paged( $where ) { global $wpdb; if ( ! $this->is_page_list_posts_on_backend() ) { return $where; } $filter_price = LP_Helper::sanitize_params_submitted( $_REQUEST['filter_price'] ?? 0 ); if ( array_key_exists( 'filter_price', $_REQUEST ) ) { if ( $filter_price == 0 ) { $where .= ' AND ( pm_price.meta_value IS NULL || pm_price.meta_value = 0 )'; } else { $where .= $wpdb->prepare( ' AND ( pm_price.meta_value = %s )', $filter_price ); } } /*$not_in = $wpdb->prepare( " SELECT ID FROM {$wpdb->posts} p INNER JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID AND pm.meta_key = %s WHERE pm.meta_value = %s ", '_lp_preview_course', 'yes' ); $where .= " AND {$wpdb->posts}.ID NOT IN( {$not_in} )";*/ return $where; } /** * @param $orderby * * @return string */ public function posts_orderby( $orderby ) { if ( ! $this->is_page_list_posts_on_backend() ) { return $orderby; } $order = $this->get_order_sort(); switch ( $this->get_order_by() ) { case 'price': $orderby = "CAST(pm_price.meta_value AS UNSIGNED) {$order}"; } return $orderby; } /** * Save course post * * @param int $post_id * @param WP_Post|null $post * @param bool $is_update * * @since 4.2.6.9 * @version 1.0.2 */ public function save_post( int $post_id, ?WP_Post $post = null, bool $is_update = false ) { try { $wp_screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; // Save to table learnpress_courses LP_Install::instance()->create_table_courses(); if ( empty( $post ) ) { $post = get_post( $post_id ); } /*if ( $post->post_status === 'auto-draft' ) { return; }*/ $courseModel = CourseModel::find( $post_id, true ); if ( ! $courseModel ) { $courseModel = new CourseModel( $post ); } // Merge object post and courseModel $new_obj = (array) $post; $old_obj = (array) $courseModel; $old_now = array_merge( $old_obj, $new_obj ); $courseModel = new CourseModel( $old_now ); // Get all metadata of course if ( $is_update && empty( $wp_screen ) ) { $coursePost = new CoursePostModel( $courseModel ); $coursePost->get_all_metadata(); // Temporary unset _elementor_page_assets of El, reason by method get_all_metadata get not use maybe_unserialize, make save invalid serialize $coursePost->meta_data->_elementor_page_assets = []; $courseModel->meta_data = $coursePost->meta_data; } // Save option single course include_once LP_PLUGIN_PATH . 'inc/admin/class-lp-admin.php'; $lp_meta_box_course = new LP_Meta_Box_Course(); $ground_fields = $lp_meta_box_course->metabox( $courseModel->ID ); // Save meta fields foreach ( $ground_fields as $fields ) { if ( ! isset( $fields['content'] ) ) { continue; } foreach ( $fields['content'] as $meta_key => $option ) { $option->id = $meta_key; if ( ! $option instanceof LP_Meta_Box_Field ) { continue; } if ( isset( $_POST[ $meta_key ] ) && ! empty( $wp_screen ) && LP_COURSE_CPT === $wp_screen->id ) { $value_saved = $option->save( $courseModel->ID ); if ( ! empty( $value_saved ) ) { $courseModel->meta_data->{$meta_key} = $value_saved; } else { $courseModel->meta_data->{$meta_key} = maybe_unserialize( get_post_meta( $courseModel->ID, $meta_key, true ) ); } } elseif ( ! $is_update ) { $courseModel->meta_data->{$meta_key} = $option->default ?? ''; } elseif ( ! empty( $wp_screen ) && LP_COURSE_CPT === $wp_screen->id ) { $value_saved = $option->save( $courseModel->ID ); $courseModel->meta_data->{$meta_key} = $value_saved; } } } // For case bulk edit multiple courses change author $bulk_edit = LP_Request::get_param( 'bulk_edit', false ); if ( ! empty( $bulk_edit ) ) { $post_author = LP_Request::get_param( 'post_author', 0, 'int' ); if ( $post_author != -1 ) { // -1 is for no change author $courseModel->post_author = $post_author; } } elseif ( ! empty( $_REQUEST['_post_author'] ) ) { // Not use key 'post_author' on single edit course, it special key of WP, Gutenberg save will not submit this key. $courseModel->post_author = LP_Request::get_param( '_post_author', 0, 'int' ); /** * Save author to post table * Not use PostModel::save() or CoursePostModel::save() here * because it calls wp_update_post(), has hook 'save_post', it will cause infinite loop */ $lp_db = LP_Database::getInstance(); $filter_update = new LP_Post_Type_Filter(); $filter_update->collection = $lp_db->tb_posts; $filter_update->set[] = "post_author = {$courseModel->post_author}"; $filter_update->where[] = $lp_db->wpdb->prepare( 'AND ID = %d', $courseModel->ID ); $lp_db->update_execute( $filter_update ); clean_post_cache( $post->ID ); } elseif ( isset( $_POST['post_author'] ) && isset( $_POST['screen'] ) && $_POST['screen'] === 'edit-' . LP_COURSE_CPT ) { // For case quick edit change author. $courseModel->post_author = LP_Request::get_param( 'post_author', 0, 'int' ); } $this->save_price( $courseModel ); $courseModel->save(); // End save to table learnpress_courses // Save extra info course // Save in background. $bg = LP_Background_Single_Course::instance(); $bg->data( array( 'handle_name' => 'save_post', 'course_id' => $post_id, 'data' => $_POST ?? [], ) )->dispatch(); } catch ( Throwable $e ) { LP_Debug::error_log( $e ); } } /** * Save price course * * @return void * @throws Exception */ protected function save_price( CourseModel &$courseObj ) { $coursePost = new CoursePostModel( $courseObj ); $regular_price = $courseObj->get_regular_price(); $sale_price = $courseObj->get_sale_price(); if ( (float) $regular_price < 0 ) { $courseObj->meta_data->{CoursePostModel::META_KEY_REGULAR_PRICE} = ''; $regular_price = $courseObj->get_regular_price(); } if ( $sale_price !== '' && (float) $sale_price > (float) $regular_price ) { $courseObj->meta_data->{CoursePostModel::META_KEY_SALE_PRICE} = ''; $sale_price = $courseObj->get_sale_price(); } // Save sale regular price and sale price to table postmeta $coursePost->save_meta_value_by_key( CoursePostModel::META_KEY_REGULAR_PRICE, $regular_price ); $coursePost->save_meta_value_by_key( CoursePostModel::META_KEY_SALE_PRICE, $sale_price ); $has_sale = $courseObj->has_sale_price(); if ( $has_sale ) { $courseObj->is_sale = 1; $coursePost->save_meta_value_by_key( CoursePostModel::META_KEY_IS_SALE, 1 ); } else { $courseObj->is_sale = 0; delete_post_meta( $courseObj->get_id(), CoursePostModel::META_KEY_IS_SALE ); } // Set price to sort on lists. $courseObj->price_to_sort = $courseObj->get_price(); $coursePost->save_meta_value_by_key( CoursePostModel::META_KEY_PRICE, $courseObj->price_to_sort ); } /** * Instance LP_Course_Post_Type. * * @return LP_Course_Post_Type|null */ public static function instance() { if ( ! self::$_instance ) { self::$_instance = new self(); } return self::$_instance; } } $course_post_type = LP_Course_Post_Type::instance(); }