fields = array_merge( $filter->all_fields, $filter->fields ); if ( empty( $filter->collection ) ) { $filter->collection = $this->tb_lp_courses; } if ( empty( $filter->collection_alias ) ) { $filter->collection_alias = 'c'; } $ca = $filter->collection_alias; // Find ID if ( ! empty( $filter->ID ) ) { $filter->where[] = $this->wpdb->prepare( "AND $ca.ID = %d", $filter->ID ); } // Status $filter->post_status = (array) $filter->post_status; if ( ! empty( $filter->post_status ) ) { $post_status_format = LP_Helper::db_format_array( $filter->post_status, '%s' ); $filter->where[] = $this->wpdb->prepare( "AND $ca.post_status IN (" . $post_status_format . ')', $filter->post_status ); } // Exclude status auto-draft, because Admin of WP not show auto-draft in list post, so all front-end and back-end of LP also not show auto-draft if ( ! in_array( 'auto-draft', $filter->post_status, true ) ) { $filter->where[] = $this->wpdb->prepare( "AND $ca.post_status != %s", 'auto-draft' ); } // Term ids if ( ! empty( $filter->term_ids ) ) { // Sanitize term ids $filter->term_ids = array_map( 'absint', $filter->term_ids ); $term_ids_format = join( ',', $filter->term_ids ); $filter->join[] = "INNER JOIN $this->tb_term_relationships AS r_term_p ON $ca.ID = r_term_p.object_id"; $filter->join[] = "INNER JOIN $this->tb_term_taxonomy AS tx_p ON r_term_p.term_taxonomy_id = tx_p.term_taxonomy_id"; $filter->where[] = "AND r_term_p.term_taxonomy_id IN ($term_ids_format)"; $filter->where[] = $this->wpdb->prepare( 'AND tx_p.taxonomy = %s', $filter->taxonomy ); } // Course ids if ( ! empty( $filter->ids ) ) { $ids = array_map( 'absint', $filter->ids ); $ids_format = join( ',', $ids ); $filter->where[] = "AND $ca.ID IN ($ids_format)"; } // Title if ( ! empty( $filter->post_title ) ) { $filter->where[] = $this->wpdb->prepare( "AND $ca.post_title LIKE %s", '%' . $filter->post_title . '%' ); } // Name(slug) if ( ! empty( $filter->post_name ) ) { $filter->where[] = $this->wpdb->prepare( "AND $ca.post_name = %s", $filter->post_name ); } // Author if ( ! empty( $filter->post_author ) ) { $filter->where[] = $this->wpdb->prepare( "AND $ca.post_author = %d", $filter->post_author ); } // Authors if ( ! empty( $filter->post_authors ) ) { $post_authors_format = LP_Helper::db_format_array( $filter->post_authors, '%d' ); $filter->where[] = $this->wpdb->prepare( "AND $ca.post_author IN (" . $post_authors_format . ')', $filter->post_authors ); } /** * Type price * * if 'free' and 'paid' are not in the array or not null, we will filter the price */ if ( ! empty( $filter->type_price ) && ( ! in_array( 'free', $filter->type_price ) && ! in_array( 'paid', $filter->type_price ) ) ) { foreach ( $filter->type_price as $type_price ) { switch ( $type_price ) { case 'free': $filter->where[] = 'AND price_to_sort = 0'; break; case 'paid': $filter->where[] = 'AND price_to_sort > 0'; break; } } } // Is sale if ( ! empty( $filter->is_sale ) ) { $filter->where[] = 'AND is_sale = 1'; } // Is feature if ( ! empty( $filter->is_feature ) ) { $filter = $this->get_courses_in_feature( $filter ); } // Levels if ( ! empty( $filter->levels ) ) { $filter->join[] = "INNER JOIN $this->tb_postmeta AS pml ON c.ID = pml.post_id"; $filter->where[] = $this->wpdb->prepare( 'AND pml.meta_key = %s', '_lp_level' ); $levels_format = LP_Helper::db_format_array( $filter->levels, '%s' ); $filter->where[] = $this->wpdb->prepare( 'AND pml.meta_value IN (' . $levels_format . ')', $filter->levels ); } // Course type if ( ! empty( $filter->type ) && $filter->type !== 'all' ) { if ( $filter->type === 'offline' ) { $filter->join[] = "INNER JOIN $this->tb_postmeta AS pm_off ON c.ID = pm_off.post_id"; $filter->where[] = $this->wpdb->prepare( 'AND pm_off.meta_key = %s', '_lp_offline_course' ); $filter->where[] = $this->wpdb->prepare( 'AND pm_off.meta_value = %s', 'yes' ); } else { $filter->where[] = $this->wpdb->prepare( "AND c.ID NOT IN ( SELECT id FROM $this->tb_posts as p1 INNER JOIN $this->tb_postmeta as pm_ol on p1.ID = pm_ol.post_id WHERE pm_ol.meta_key = %s AND pm_ol.meta_value = %s )", '_lp_offline_course', 'yes' ); } } $filter = apply_filters( 'lp/courses-json/query/filter', $filter ); return $this->execute( $filter, $total_rows ); } /** * Get list courses is on popular * Use "UNION" to merge 2 query * * @param CourseJsonFilter $filter * * @return CourseJsonFilter * @throws Exception * @version 1.0.9 * @since 4.3.2.3 */ public function get_courses_order_by_popular( CourseJsonFilter &$filter ): CourseJsonFilter { // Set list name columns get //$columns_table_posts = $this->get_cols_of_table( $this->tb_posts ); //$filter->fields = array_merge( $columns_table_posts, $filter->fields ); $db = CourseJsonDB::getInstance(); $filter_user_course = clone $filter; $filter_course_not_attend = clone $filter; // Query get users total attend courses $fields_user_course_require = [ 'c.ID', 'COUNT(c.ID) AS total' ]; $filter_user_course->fields = array( 'c.ID', 'COUNT(c.ID) AS total' ); if ( ! empty( $filter_user_course->only_fields ) ) { $pattern = '#ID.*#'; foreach ( $filter_user_course->only_fields as $k => $field ) { if ( preg_match( $pattern, $field ) ) { unset( $filter_user_course->only_fields[ $k ] ); } } $filter_user_course->only_fields = array_unique( array_merge( $filter_user_course->only_fields, $fields_user_course_require ) ); } $filter_user_course->join[] = "INNER JOIN {$this->tb_lp_user_items} AS ui ON c.ID = ui.item_id"; $filter_user_course->where[] = $this->wpdb->prepare( 'AND ui.item_type = %s', LP_COURSE_CPT ); $filter_user_course->where[] = $this->wpdb->prepare( 'AND (status = %s OR status = %s OR status = %s)', LP_COURSE_ENROLLED, LP_COURSE_PURCHASED, LP_COURSE_FINISHED ); $filter_user_course->group_by = 'c.ID'; $filter_user_course->order_by = ''; $filter_user_course->return_string_query = true; $query_user_course = $db->get_courses( $filter_user_course ); // Query get courses not attend $filter_user_course_cl = clone $filter_user_course; $filter_user_course_cl->only_fields = array( 'c.ID' ); $query_user_course_for_not_in = $db->get_courses( $filter_user_course_cl ); $fields_user_course_not_attend_require = [ 'c.ID', '0 AS total' ]; $filter_course_not_attend->fields = [ 'c.ID', '0 AS total' ]; if ( ! empty( $filter_course_not_attend->only_fields ) ) { $pattern = '#ID.*#'; foreach ( $filter_course_not_attend->only_fields as $k => $field ) { if ( preg_match( $pattern, $field ) ) { unset( $filter_course_not_attend->only_fields[ $k ] ); } } $filter_course_not_attend->only_fields = array_unique( array_merge( $filter_course_not_attend->only_fields, $fields_user_course_not_attend_require ) ); } $filter_course_not_attend->where[] = 'AND c.ID NOT IN(' . $query_user_course_for_not_in . ')'; $filter_course_not_attend->order_by = ''; $filter_course_not_attend->return_string_query = true; $query_course_not_attend = $db->get_courses( $filter_course_not_attend ); $filter->union[] = $query_user_course; $filter->union[] = $query_course_not_attend; $filter->order_by = 'total'; $filter->order = 'DESC'; return $filter; } /** * Get list courses is on feature * * @param CourseJsonFilter $filter * * @return CourseJsonFilter * @author tungnx * @version 1.0.0 * @since 4.1.5 */ public function get_courses_in_feature( CourseJsonFilter &$filter ): CourseJsonFilter { $filter->join[] = "INNER JOIN $this->tb_postmeta AS pmf ON c.ID = pmf.post_id"; $filter->where[] = $this->wpdb->prepare( 'AND pmf.meta_key = %s', '_lp_featured' ); $filter->where[] = $this->wpdb->prepare( 'AND pmf.meta_value = %s', 'yes' ); return $filter; } /** * Get total courses of Author * * @param int $author_id * @param array $status * * @return CourseJsonFilter * @since 4.3.4 Clone from LP_Course_DB::count_courses_of_author * @version 1.0.0 */ public function count_courses_of_author( int $author_id, array $status = [] ): CourseJsonFilter { $filter = new CourseJsonFilter(); $filter->only_fields = array( 'ID' ); $filter->post_author = $author_id; $filter->post_status = $status; if ( empty( $status ) ) { $filter->post_status = []; } $filter->field_count = 'ID'; $filter->query_count = true; return apply_filters( 'lp/user/course/query/filter/count-courses-of-author', $filter ); } }