Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Sensei_Course often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Sensei_Course, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 15 | class Sensei_Course { | 
            ||
| 16 | /**  | 
            ||
| 17 | * @var $token  | 
            ||
| 18 | */  | 
            ||
| 19 | public $token;  | 
            ||
| 20 | |||
| 21 | /**  | 
            ||
| 22 | * @var array $meta_fields  | 
            ||
| 23 | */  | 
            ||
| 24 | public $meta_fields;  | 
            ||
| 25 | |||
| 26 | /**  | 
            ||
| 27 | * @var string|bool $my_courses_page reference to the sites  | 
            ||
| 28 | * my courses page, false if none was set  | 
            ||
| 29 | */  | 
            ||
| 30 | public $my_courses_page;  | 
            ||
| 31 | |||
| 32 | /**  | 
            ||
| 33 | * Constructor.  | 
            ||
| 34 | * @since 1.0.0  | 
            ||
| 35 | */  | 
            ||
| 36 | 	public function __construct () { | 
            ||
| 101 | |||
| 102 | /**  | 
            ||
| 103 | * Fires when a quiz has been graded to check if the Course status needs changing  | 
            ||
| 104 | *  | 
            ||
| 105 | * @param type $user_id  | 
            ||
| 106 | * @param type $quiz_id  | 
            ||
| 107 | */  | 
            ||
| 108 | 	public function update_status_after_quiz_submission( $user_id, $quiz_id ) { | 
            ||
| 114 | |||
| 115 | /**  | 
            ||
| 116 | * Fires when a lesson has changed to check if the Course status needs changing  | 
            ||
| 117 | *  | 
            ||
| 118 | * @param int $user_id  | 
            ||
| 119 | * @param int $lesson_id  | 
            ||
| 120 | */  | 
            ||
| 121 | 	public function update_status_after_lesson_change( $user_id, $lesson_id ) { | 
            ||
| 130 | |||
| 131 | /**  | 
            ||
| 132 | * meta_box_setup function.  | 
            ||
| 133 | *  | 
            ||
| 134 | * @access public  | 
            ||
| 135 | * @return void  | 
            ||
| 136 | */  | 
            ||
| 137 | 	public function meta_box_setup () { | 
            ||
| 160 | |||
| 161 | /**  | 
            ||
| 162 | * course_woocommerce_product_meta_box_content function.  | 
            ||
| 163 | *  | 
            ||
| 164 | * @access public  | 
            ||
| 165 | * @return void  | 
            ||
| 166 | */  | 
            ||
| 167 | 	public function course_woocommerce_product_meta_box_content () { | 
            ||
| 281 | |||
| 282 | /**  | 
            ||
| 283 | * course_prerequisite_meta_box_content function.  | 
            ||
| 284 | *  | 
            ||
| 285 | * @access public  | 
            ||
| 286 | * @return void  | 
            ||
| 287 | */  | 
            ||
| 288 | 	public function course_prerequisite_meta_box_content () { | 
            ||
| 320 | |||
| 321 | /**  | 
            ||
| 322 | * course_featured_meta_box_content function.  | 
            ||
| 323 | *  | 
            ||
| 324 | * @access public  | 
            ||
| 325 | * @return void  | 
            ||
| 326 | */  | 
            ||
| 327 | 	public function course_featured_meta_box_content () { | 
            ||
| 346 | |||
| 347 | /**  | 
            ||
| 348 | * course_video_meta_box_content function.  | 
            ||
| 349 | *  | 
            ||
| 350 | * @access public  | 
            ||
| 351 | * @return void  | 
            ||
| 352 | */  | 
            ||
| 353 | 	public function course_video_meta_box_content () { | 
            ||
| 367 | |||
| 368 | /**  | 
            ||
| 369 | * meta_box_save function.  | 
            ||
| 370 | *  | 
            ||
| 371 | * Handles saving the meta data  | 
            ||
| 372 | *  | 
            ||
| 373 | * @access public  | 
            ||
| 374 | * @param int $post_id  | 
            ||
| 375 | * @return void  | 
            ||
| 376 | */  | 
            ||
| 377 | 	public function meta_box_save ( $post_id ) { | 
            ||
| 411 | |||
| 412 | |||
| 413 | /**  | 
            ||
| 414 | * save_post_meta function.  | 
            ||
| 415 | *  | 
            ||
| 416 | * Does the save  | 
            ||
| 417 | *  | 
            ||
| 418 | * @access private  | 
            ||
| 419 | * @param string $post_key (default: '')  | 
            ||
| 420 | * @param int $post_id (default: 0)  | 
            ||
| 421 | * @return int new meta id | bool meta value saved status  | 
            ||
| 422 | */  | 
            ||
| 423 | 	private function save_post_meta( $post_key = '', $post_id = 0 ) { | 
            ||
| 437 | |||
| 438 | /**  | 
            ||
| 439 | * course_lessons_meta_box_content function.  | 
            ||
| 440 | *  | 
            ||
| 441 | * @access public  | 
            ||
| 442 | * @return void  | 
            ||
| 443 | */  | 
            ||
| 444 | 	public function course_lessons_meta_box_content () { | 
            ||
| 489 | |||
| 490 | /**  | 
            ||
| 491 | * course_manage_meta_box_content function.  | 
            ||
| 492 | *  | 
            ||
| 493 | * @since 1.9.0  | 
            ||
| 494 | * @access public  | 
            ||
| 495 | * @return void  | 
            ||
| 496 | */  | 
            ||
| 497 | |||
| 498 |     public function course_manage_meta_box_content () { | 
            ||
| 513 | |||
| 514 | /**  | 
            ||
| 515 | * Add column headings to the "lesson" post list screen.  | 
            ||
| 516 | * @access public  | 
            ||
| 517 | * @since 1.0.0  | 
            ||
| 518 | * @param array $defaults  | 
            ||
| 519 | * @return array $new_columns  | 
            ||
| 520 | */  | 
            ||
| 521 | 	public function add_column_headings ( $defaults ) { | 
            ||
| 536 | |||
| 537 | /**  | 
            ||
| 538 | * Add data for our newly-added custom columns.  | 
            ||
| 539 | * @access public  | 
            ||
| 540 | * @since 1.0.0  | 
            ||
| 541 | * @param string $column_name  | 
            ||
| 542 | * @param int $id  | 
            ||
| 543 | * @return void  | 
            ||
| 544 | */  | 
            ||
| 545 | 	public function add_column_data ( $column_name, $id ) { | 
            ||
| 592 | |||
| 593 | |||
| 594 | /**  | 
            ||
| 595 | * course_query function.  | 
            ||
| 596 | *  | 
            ||
| 597 | * @access public  | 
            ||
| 598 | * @param int $amount (default: 0)  | 
            ||
| 599 | * @param string $type (default: 'default')  | 
            ||
| 600 | * @param array $includes (default: array())  | 
            ||
| 601 | * @return array  | 
            ||
| 602 | */  | 
            ||
| 603 | 	public function course_query( $amount = 0, $type = 'default', $includes = array(), $excludes = array() ) { | 
            ||
| 630 | |||
| 631 | |||
| 632 | /**  | 
            ||
| 633 | * get_archive_query_args function.  | 
            ||
| 634 | *  | 
            ||
| 635 | * @access public  | 
            ||
| 636 | * @param string $type (default: '')  | 
            ||
| 637 | * @param int $amount (default: 0)  | 
            ||
| 638 | * @param array $includes (default: array())  | 
            ||
| 639 | * @return array  | 
            ||
| 640 | */  | 
            ||
| 641 | 	public function get_archive_query_args( $type = '', $amount = 0 , $includes = array(), $excludes = array() ) { | 
            ||
| 742 | |||
| 743 | |||
| 744 | /**  | 
            ||
| 745 | * course_image function.  | 
            ||
| 746 | *  | 
            ||
| 747 | * Outputs the courses image, or first image from a lesson within a course  | 
            ||
| 748 | *  | 
            ||
| 749 | * Will echo the image unless return true is specified.  | 
            ||
| 750 | *  | 
            ||
| 751 | * @access public  | 
            ||
| 752 | * @param int | WP_Post $course_id (default: 0)  | 
            ||
| 753 | * @param string $width (default: '100')  | 
            ||
| 754 | * @param string $height (default: '100')  | 
            ||
| 755 | * @param bool $return default false  | 
            ||
| 756 | *  | 
            ||
| 757 | * @return string | void  | 
            ||
| 758 | */  | 
            ||
| 759 | 	public function course_image( $course_id = 0, $width = '100', $height = '100', $return = false ) { | 
            ||
| 845 | |||
| 846 | |||
| 847 | /**  | 
            ||
| 848 | * course_count function.  | 
            ||
| 849 | *  | 
            ||
| 850 | * @access public  | 
            ||
| 851 | * @param array $exclude (default: array())  | 
            ||
| 852 | * @param string $post_status (default: 'publish')  | 
            ||
| 853 | * @return int  | 
            ||
| 854 | */  | 
            ||
| 855 | 	public function course_count( $post_status = 'publish' ) { | 
            ||
| 873 | |||
| 874 | |||
| 875 | /**  | 
            ||
| 876 | * course_lessons function.  | 
            ||
| 877 | *  | 
            ||
| 878 | * @access public  | 
            ||
| 879 | * @param int $course_id (default: 0)  | 
            ||
| 880 | * @param string $post_status (default: 'publish')  | 
            ||
| 881 | * @param string $fields (default: 'all'). WP only allows 3 types, but we will limit it to only 'ids' or 'all'  | 
            ||
| 882 | 	 * @return array{ type WP_Post }  $posts_array | 
            ||
| 883 | */  | 
            ||
| 884 | 	public function course_lessons( $course_id = 0, $post_status = 'publish', $fields = 'all' ) { | 
            ||
| 947 | |||
| 948 | /**  | 
            ||
| 949 | * Used for the uasort in $this->course_lessons()  | 
            ||
| 950 | * @since 1.8.0  | 
            ||
| 951 | * @access protected  | 
            ||
| 952 | *  | 
            ||
| 953 | * @param array $lesson_1  | 
            ||
| 954 | * @param array $lesson_2  | 
            ||
| 955 | * @return int  | 
            ||
| 956 | */  | 
            ||
| 957 |     protected function _short_course_lessons_callback( $lesson_1, $lesson_2 ){ | 
            ||
| 965 | |||
| 966 | /**  | 
            ||
| 967 | * Fetch all quiz ids in a course  | 
            ||
| 968 | * @since 1.5.0  | 
            ||
| 969 | * @param integer $course_id ID of course  | 
            ||
| 970 | * @param boolean $boolean_check True if a simple yes/no is required  | 
            ||
| 971 | * @return array Array of quiz post objects  | 
            ||
| 972 | */  | 
            ||
| 973 | 	public function course_quizzes( $course_id = 0, $boolean_check = false ) { | 
            ||
| 1000 | |||
| 1001 | |||
| 1002 | /**  | 
            ||
| 1003 | * course_lessons_completed function. Appears to be completely unused and a duplicate of course_lessons()!  | 
            ||
| 1004 | *  | 
            ||
| 1005 | * @access public  | 
            ||
| 1006 | * @param int $course_id (default: 0)  | 
            ||
| 1007 | * @param string $post_status (default: 'publish')  | 
            ||
| 1008 | * @return array  | 
            ||
| 1009 | */  | 
            ||
| 1010 | 	public function course_lessons_completed( $course_id = 0, $post_status = 'publish' ) { | 
            ||
| 1015 | |||
| 1016 | |||
| 1017 | /**  | 
            ||
| 1018 | * course_author_lesson_count function.  | 
            ||
| 1019 | *  | 
            ||
| 1020 | * @access public  | 
            ||
| 1021 | * @param int $author_id (default: 0)  | 
            ||
| 1022 | * @param int $course_id (default: 0)  | 
            ||
| 1023 | * @return int  | 
            ||
| 1024 | */  | 
            ||
| 1025 | View Code Duplication | 	public function course_author_lesson_count( $author_id = 0, $course_id = 0 ) { | 
            |
| 1041 | |||
| 1042 | /**  | 
            ||
| 1043 | * course_lesson_count function.  | 
            ||
| 1044 | *  | 
            ||
| 1045 | * @access public  | 
            ||
| 1046 | * @param int $course_id (default: 0)  | 
            ||
| 1047 | * @return int  | 
            ||
| 1048 | */  | 
            ||
| 1049 | View Code Duplication | 	public function course_lesson_count( $course_id = 0 ) { | 
            |
| 1066 | |||
| 1067 | /**  | 
            ||
| 1068 | * course_lesson_preview_count function.  | 
            ||
| 1069 | *  | 
            ||
| 1070 | * @access public  | 
            ||
| 1071 | * @param int $course_id (default: 0)  | 
            ||
| 1072 | * @return int  | 
            ||
| 1073 | */  | 
            ||
| 1074 | View Code Duplication | 	public function course_lesson_preview_count( $course_id = 0 ) { | 
            |
| 1099 | |||
| 1100 | /**  | 
            ||
| 1101 | * get_product_courses function.  | 
            ||
| 1102 | *  | 
            ||
| 1103 | * @access public  | 
            ||
| 1104 | * @param int $product_id (default: 0)  | 
            ||
| 1105 | * @return array  | 
            ||
| 1106 | */  | 
            ||
| 1107 | View Code Duplication | 	public function get_product_courses( $product_id = 0 ) { | 
            |
| 1126 | |||
| 1127 | /**  | 
            ||
| 1128 | * single_course_lesson_data sets up frontend data for single course lesson output  | 
            ||
| 1129 | * @since 1.2.1  | 
            ||
| 1130 | * @return void  | 
            ||
| 1131 | */  | 
            ||
| 1132 | 	public function single_course_lesson_data() { | 
            ||
| 1135 | |||
| 1136 | /**  | 
            ||
| 1137 | * Fix posts_per_page for My Courses page  | 
            ||
| 1138 | * @param WP_Query $query  | 
            ||
| 1139 | * @return void  | 
            ||
| 1140 | */  | 
            ||
| 1141 | 	public function filter_my_courses( $query ) { | 
            ||
| 1154 | |||
| 1155 | /**  | 
            ||
| 1156 | * load_user_courses_content generates HTML for user's active & completed courses  | 
            ||
| 1157 | *  | 
            ||
| 1158 | * This function also ouputs the html so no need to echo the content.  | 
            ||
| 1159 | *  | 
            ||
| 1160 | * @since 1.4.0  | 
            ||
| 1161 | * @param object $user Queried user object  | 
            ||
| 1162 | * @param boolean $manage Whether the user has permission to manage the courses  | 
            ||
| 1163 | * @return string HTML displayng course data  | 
            ||
| 1164 | */  | 
            ||
| 1165 | 	public function load_user_courses_content( $user = false ) { | 
            ||
| 1166 | global $course, $my_courses_page, $my_courses_section;  | 
            ||
| 1167 | |||
| 1168 | if( ! isset( Sensei()->settings->settings[ 'learner_profile_show_courses' ] )  | 
            ||
| 1169 |             || ! Sensei()->settings->settings[ 'learner_profile_show_courses' ] ) { | 
            ||
| 1170 | |||
| 1171 | // do not show the content if the settings doesn't allow for it  | 
            ||
| 1172 | return;  | 
            ||
| 1173 | |||
| 1174 | }  | 
            ||
| 1175 | |||
| 1176 | $manage = ( $user->ID == get_current_user_id() ) ? true : false;  | 
            ||
| 1177 | |||
| 1178 | do_action( 'sensei_before_learner_course_content', $user );  | 
            ||
| 1179 | |||
| 1180 | // Build Output HTML  | 
            ||
| 1181 | $complete_html = $active_html = '';  | 
            ||
| 1182 | |||
| 1183 | 		if( is_a( $user, 'WP_User' ) ) { | 
            ||
| 1184 | |||
| 1185 | $my_courses_page = true;  | 
            ||
| 1186 | |||
| 1187 | // Allow action to be run before My Courses content has loaded  | 
            ||
| 1188 | do_action( 'sensei_before_my_courses', $user->ID );  | 
            ||
| 1189 | |||
| 1190 | // Logic for Active and Completed Courses  | 
            ||
| 1191 | $per_page = 20;  | 
            ||
| 1192 | if ( isset( Sensei()->settings->settings[ 'my_course_amount' ] )  | 
            ||
| 1193 |                 && ( 0 < absint( Sensei()->settings->settings[ 'my_course_amount' ] ) ) ) { | 
            ||
| 1194 | |||
| 1195 | $per_page = absint( Sensei()->settings->settings[ 'my_course_amount' ] );  | 
            ||
| 1196 | |||
| 1197 | }  | 
            ||
| 1198 | |||
| 1199 | $course_statuses = WooThemes_Sensei_Utils::sensei_check_for_activity( array( 'user_id' => $user->ID, 'type' => 'sensei_course_status' ), true );  | 
            ||
| 1200 | // User may only be on 1 Course  | 
            ||
| 1201 | 			if ( !is_array($course_statuses) ) { | 
            ||
| 1202 | $course_statuses = array( $course_statuses );  | 
            ||
| 1203 | }  | 
            ||
| 1204 | $completed_ids = $active_ids = array();  | 
            ||
| 1205 | 			foreach( $course_statuses as $course_status ) { | 
            ||
| 1206 | 				if ( WooThemes_Sensei_Utils::user_completed_course( $course_status, $user->ID ) ) { | 
            ||
| 1207 | $completed_ids[] = $course_status->comment_post_ID;  | 
            ||
| 1208 | 				} else { | 
            ||
| 1209 | $active_ids[] = $course_status->comment_post_ID;  | 
            ||
| 1210 | }  | 
            ||
| 1211 | }  | 
            ||
| 1212 | |||
| 1213 | $active_count = $completed_count = 0;  | 
            ||
| 1214 | |||
| 1215 | $active_courses = array();  | 
            ||
| 1216 | View Code Duplication | 			if ( 0 < intval( count( $active_ids ) ) ) { | 
            |
| 1217 | $my_courses_section = 'active';  | 
            ||
| 1218 | $active_courses = Sensei()->course->course_query( $per_page, 'usercourses', $active_ids );  | 
            ||
| 1219 | $active_count = count( $active_ids );  | 
            ||
| 1220 | } // End If Statement  | 
            ||
| 1221 | |||
| 1222 | $completed_courses = array();  | 
            ||
| 1223 | View Code Duplication | 			if ( 0 < intval( count( $completed_ids ) ) ) { | 
            |
| 1224 | $my_courses_section = 'completed';  | 
            ||
| 1225 | $completed_courses = Sensei()->course->course_query( $per_page, 'usercourses', $completed_ids );  | 
            ||
| 1226 | $completed_count = count( $completed_ids );  | 
            ||
| 1227 | } // End If Statement  | 
            ||
| 1228 | |||
| 1229 | 			foreach ( $active_courses as $course_item ) { | 
            ||
| 1230 | |||
| 1231 | $course_lessons = Sensei()->course->course_lessons( $course_item->ID );  | 
            ||
| 1232 | $lessons_completed = 0;  | 
            ||
| 1233 | 				foreach ( $course_lessons as $lesson ) { | 
            ||
| 1234 | 					if ( WooThemes_Sensei_Utils::user_completed_lesson( $lesson->ID, $user->ID ) ) { | 
            ||
| 1235 | ++$lessons_completed;  | 
            ||
| 1236 | }  | 
            ||
| 1237 | }  | 
            ||
| 1238 | |||
| 1239 | // Get Course Categories  | 
            ||
| 1240 | $category_output = get_the_term_list( $course_item->ID, 'course-category', '', ', ', '' );  | 
            ||
| 1241 | |||
| 1242 | $active_html .= '<article class="' . esc_attr( join( ' ', get_post_class( array( 'course', 'post' ), $course_item->ID ) ) ) . '">';  | 
            ||
| 1243 | |||
| 1244 | // Image  | 
            ||
| 1245 | $active_html .= Sensei()->course->course_image( absint( $course_item->ID ), '100','100', true );  | 
            ||
| 1246 | |||
| 1247 | // Title  | 
            ||
| 1248 | $active_html .= '<header>';  | 
            ||
| 1249 | |||
| 1250 | $active_html .= '<h2><a href="' . esc_url( get_permalink( absint( $course_item->ID ) ) ) . '" title="' . esc_attr( $course_item->post_title ) . '">' . esc_html( $course_item->post_title ) . '</a></h2>';  | 
            ||
| 1251 | |||
| 1252 | $active_html .= '</header>';  | 
            ||
| 1253 | |||
| 1254 | $active_html .= '<section class="entry">';  | 
            ||
| 1255 | |||
| 1256 | $active_html .= '<p class="sensei-course-meta">';  | 
            ||
| 1257 | |||
| 1258 | // Author  | 
            ||
| 1259 | $user_info = get_userdata( absint( $course_item->post_author ) );  | 
            ||
| 1260 | View Code Duplication | if ( isset( Sensei()->settings->settings[ 'course_author' ] )  | 
            |
| 1261 |                     && ( Sensei()->settings->settings[ 'course_author' ] ) ) { | 
            ||
| 1262 | |||
| 1263 | $active_html .= '<span class="course-author">'  | 
            ||
| 1264 | . __( 'by ', 'woothemes-sensei' )  | 
            ||
| 1265 | . '<a href="' . esc_url( get_author_posts_url( absint( $course_item->post_author ) ) )  | 
            ||
| 1266 | . '" title="' . esc_attr( $user_info->display_name ) . '">'  | 
            ||
| 1267 | . esc_html( $user_info->display_name )  | 
            ||
| 1268 | . '</a></span>';  | 
            ||
| 1269 | |||
| 1270 | } // End If Statement  | 
            ||
| 1271 | |||
| 1272 | // Lesson count for this author  | 
            ||
| 1273 | $lesson_count = Sensei()->course->course_lesson_count( absint( $course_item->ID ) );  | 
            ||
| 1274 | // Handle Division by Zero  | 
            ||
| 1275 |                 if ( 0 == $lesson_count ) { | 
            ||
| 1276 | |||
| 1277 | $lesson_count = 1;  | 
            ||
| 1278 | |||
| 1279 | } // End If Statement  | 
            ||
| 1280 | $active_html .= '<span class="course-lesson-count">' . $lesson_count . ' ' . __( 'Lessons', 'woothemes-sensei' ) . '</span>';  | 
            ||
| 1281 | // Course Categories  | 
            ||
| 1282 |                 if ( '' != $category_output ) { | 
            ||
| 1283 | |||
| 1284 | $active_html .= '<span class="course-category">' . sprintf( __( 'in %s', 'woothemes-sensei' ), $category_output ) . '</span>';  | 
            ||
| 1285 | |||
| 1286 | } // End If Statement  | 
            ||
| 1287 | $active_html .= '<span class="course-lesson-progress">' . sprintf( __( '%1$d of %2$d lessons completed', 'woothemes-sensei' ) , $lessons_completed, $lesson_count ) . '</span>';  | 
            ||
| 1288 | |||
| 1289 | $active_html .= '</p>';  | 
            ||
| 1290 | |||
| 1291 | $active_html .= '<p class="course-excerpt">' . $course_item->post_excerpt . '</p>';  | 
            ||
| 1292 | |||
| 1293 | |||
| 1294 | |||
| 1295 | $progress_percentage = abs( round( ( doubleval( $lessons_completed ) * 100 ) / ( $lesson_count ), 0 ) );  | 
            ||
| 1296 | |||
| 1297 | $active_html .= $this->get_progress_meter( $progress_percentage );  | 
            ||
| 1298 | |||
| 1299 | $active_html .= '</section>';  | 
            ||
| 1300 | |||
| 1301 |                 if( is_user_logged_in() ) { | 
            ||
| 1302 | |||
| 1303 | $active_html .= '<section class="entry-actions">';  | 
            ||
| 1304 | |||
| 1305 | $active_html .= '<form method="POST" action="' . esc_url( remove_query_arg( array( 'active_page', 'completed_page' ) ) ) . '">';  | 
            ||
| 1306 | |||
| 1307 | $active_html .= '<input type="hidden" name="' . esc_attr( 'woothemes_sensei_complete_course_noonce' ) . '" id="' . esc_attr( 'woothemes_sensei_complete_course_noonce' ) . '" value="' . esc_attr( wp_create_nonce( 'woothemes_sensei_complete_course_noonce' ) ) . '" />';  | 
            ||
| 1308 | |||
| 1309 | $active_html .= '<input type="hidden" name="course_complete_id" id="course-complete-id" value="' . esc_attr( absint( $course_item->ID ) ) . '" />';  | 
            ||
| 1310 | |||
| 1311 |                     if ( 0 < absint( count( $course_lessons ) ) && Sensei()->settings->settings['course_completion'] == 'complete' ) { | 
            ||
| 1312 | |||
| 1313 | $active_html .= '<span><input name="course_complete" type="submit" class="course-complete" value="'  | 
            ||
| 1314 | . __( 'Mark as Complete', 'woothemes-sensei' ) . '"/> </span>';  | 
            ||
| 1315 | |||
| 1316 | } // End If Statement  | 
            ||
| 1317 | |||
| 1318 | $course_purchased = false;  | 
            ||
| 1319 |                     if ( Sensei_WC::is_woocommerce_active() ) { | 
            ||
| 1320 | |||
| 1321 | // Get the product ID  | 
            ||
| 1322 | $wc_post_id = get_post_meta( absint( $course_item->ID ), '_course_woocommerce_product', true );  | 
            ||
| 1323 |                         if ( 0 < $wc_post_id ) { | 
            ||
| 1324 | |||
| 1325 | $course_purchased = Sensei_WC::has_customer_bought_product( $user->ID, $wc_post_id );  | 
            ||
| 1326 | |||
| 1327 | } // End If Statement  | 
            ||
| 1328 | |||
| 1329 | } // End If Statement  | 
            ||
| 1330 | |||
| 1331 |                     if ( false == $course_purchased ) { | 
            ||
| 1332 | |||
| 1333 | $active_html .= '<span><input name="course_complete" type="submit" class="course-delete" value="'  | 
            ||
| 1334 | . __( 'Delete Course', 'woothemes-sensei' ) . '"/></span>';  | 
            ||
| 1335 | |||
| 1336 | } // End If Statement  | 
            ||
| 1337 | |||
| 1338 | $active_html .= '</form>';  | 
            ||
| 1339 | |||
| 1340 | $active_html .= '</section>';  | 
            ||
| 1341 | }  | 
            ||
| 1342 | |||
| 1343 | $active_html .= '</article>';  | 
            ||
| 1344 | }  | 
            ||
| 1345 | |||
| 1346 | // Active pagination  | 
            ||
| 1347 | View Code Duplication | 			if( $active_count > $per_page ) { | 
            |
| 1348 | |||
| 1349 | $current_page = 1;  | 
            ||
| 1350 | 				if( isset( $_GET['active_page'] ) && 0 < intval( $_GET['active_page'] ) ) { | 
            ||
| 1351 | $current_page = $_GET['active_page'];  | 
            ||
| 1352 | }  | 
            ||
| 1353 | |||
| 1354 | $active_html .= '<nav class="pagination woo-pagination">';  | 
            ||
| 1355 | $total_pages = ceil( $active_count / $per_page );  | 
            ||
| 1356 | |||
| 1357 | 				if( $current_page > 1 ) { | 
            ||
| 1358 | $prev_link = add_query_arg( 'active_page', $current_page - 1 );  | 
            ||
| 1359 | $active_html .= '<a class="prev page-numbers" href="' . esc_url( $prev_link ) . '">' . __( 'Previous' , 'woothemes-sensei' ) . '</a> ';  | 
            ||
| 1360 | }  | 
            ||
| 1361 | |||
| 1362 | 				for ( $i = 1; $i <= $total_pages; $i++ ) { | 
            ||
| 1363 | $link = add_query_arg( 'active_page', $i );  | 
            ||
| 1364 | |||
| 1365 | 					if( $i == $current_page ) { | 
            ||
| 1366 | $active_html .= '<span class="page-numbers current">' . $i . '</span> ';  | 
            ||
| 1367 | 					} else { | 
            ||
| 1368 | $active_html .= '<a class="page-numbers" href="' . esc_url( $link ). '">' . $i . '</a> ';  | 
            ||
| 1369 | }  | 
            ||
| 1370 | }  | 
            ||
| 1371 | |||
| 1372 | 				if( $current_page < $total_pages ) { | 
            ||
| 1373 | $next_link = add_query_arg( 'active_page', $current_page + 1 );  | 
            ||
| 1374 | $active_html .= '<a class="next page-numbers" href="' . esc_url( $next_link ) . '">' . __( 'Next' , 'woothemes-sensei' ) . '</a> ';  | 
            ||
| 1375 | }  | 
            ||
| 1376 | |||
| 1377 | $active_html .= '</nav>';  | 
            ||
| 1378 | }  | 
            ||
| 1379 | |||
| 1380 | 			foreach ( $completed_courses as $course_item ) { | 
            ||
| 1381 | $course = $course_item;  | 
            ||
| 1382 | |||
| 1383 | // Get Course Categories  | 
            ||
| 1384 | $category_output = get_the_term_list( $course_item->ID, 'course-category', '', ', ', '' );  | 
            ||
| 1385 | |||
| 1386 | $complete_html .= '<article class="' . join( ' ', get_post_class( array( 'course', 'post' ), $course_item->ID ) ) . '">';  | 
            ||
| 1387 | |||
| 1388 | // Image  | 
            ||
| 1389 | $complete_html .= Sensei()->course->course_image( absint( $course_item->ID ),100, 100, true );  | 
            ||
| 1390 | |||
| 1391 | // Title  | 
            ||
| 1392 | $complete_html .= '<header>';  | 
            ||
| 1393 | |||
| 1394 | $complete_html .= '<h2><a href="' . esc_url( get_permalink( absint( $course_item->ID ) ) ) . '" title="' . esc_attr( $course_item->post_title ) . '">' . esc_html( $course_item->post_title ) . '</a></h2>';  | 
            ||
| 1395 | |||
| 1396 | $complete_html .= '</header>';  | 
            ||
| 1397 | |||
| 1398 | $complete_html .= '<section class="entry">';  | 
            ||
| 1399 | |||
| 1400 | $complete_html .= '<p class="sensei-course-meta">';  | 
            ||
| 1401 | |||
| 1402 | // Author  | 
            ||
| 1403 | $user_info = get_userdata( absint( $course_item->post_author ) );  | 
            ||
| 1404 | View Code Duplication | 		    		    	if ( isset( Sensei()->settings->settings[ 'course_author' ] ) && ( Sensei()->settings->settings[ 'course_author' ] ) ) { | 
            |
| 1405 | $complete_html .= '<span class="course-author">' . __( 'by ', 'woothemes-sensei' ) . '<a href="' . esc_url( get_author_posts_url( absint( $course_item->post_author ) ) ) . '" title="' . esc_attr( $user_info->display_name ) . '">' . esc_html( $user_info->display_name ) . '</a></span>';  | 
            ||
| 1406 | } // End If Statement  | 
            ||
| 1407 | |||
| 1408 | // Lesson count for this author  | 
            ||
| 1409 | $complete_html .= '<span class="course-lesson-count">'  | 
            ||
| 1410 | . Sensei()->course->course_lesson_count( absint( $course_item->ID ) )  | 
            ||
| 1411 | . ' ' . __( 'Lessons', 'woothemes-sensei' )  | 
            ||
| 1412 | . '</span>';  | 
            ||
| 1413 | |||
| 1414 | // Course Categories  | 
            ||
| 1415 | 		    		    	if ( '' != $category_output ) { | 
            ||
| 1416 | |||
| 1417 | $complete_html .= '<span class="course-category">' . sprintf( __( 'in %s', 'woothemes-sensei' ), $category_output ) . '</span>';  | 
            ||
| 1418 | |||
| 1419 | } // End If Statement  | 
            ||
| 1420 | |||
| 1421 | $complete_html .= '</p>';  | 
            ||
| 1422 | |||
| 1423 | $complete_html .= '<p class="course-excerpt">' . $course_item->post_excerpt . '</p>';  | 
            ||
| 1424 | |||
| 1425 | $complete_html .= $this->get_progress_meter( 100 );  | 
            ||
| 1426 | |||
| 1427 | 						if( $manage ) { | 
            ||
| 1428 | $has_quizzes = Sensei()->course->course_quizzes( $course_item->ID, true );  | 
            ||
| 1429 | // Output only if there is content to display  | 
            ||
| 1430 | 							if ( has_filter( 'sensei_results_links' ) || $has_quizzes ) { | 
            ||
| 1431 | |||
| 1432 | |||
| 1433 | $complete_html .= '<p class="sensei-results-links">';  | 
            ||
| 1434 | $results_link = '';  | 
            ||
| 1435 | View Code Duplication | 								if( $has_quizzes ) { | 
            |
| 1436 | |||
| 1437 | $results_link = '<a class="button view-results" href="'  | 
            ||
| 1438 | . Sensei()->course_results->get_permalink( $course_item->ID )  | 
            ||
| 1439 | . '">' . __( 'View results', 'woothemes-sensei' )  | 
            ||
| 1440 | . '</a>';  | 
            ||
| 1441 | }  | 
            ||
| 1442 | $complete_html .= apply_filters( 'sensei_results_links', $results_link );  | 
            ||
| 1443 | $complete_html .= '</p>';  | 
            ||
| 1444 | |||
| 1445 | }  | 
            ||
| 1446 | }  | 
            ||
| 1447 | |||
| 1448 | $complete_html .= '</section>';  | 
            ||
| 1449 | |||
| 1450 | $complete_html .= '</article>';  | 
            ||
| 1451 | }  | 
            ||
| 1452 | |||
| 1453 | // Active pagination  | 
            ||
| 1454 | View Code Duplication | 			if( $completed_count > $per_page ) { | 
            |
| 1455 | |||
| 1456 | $current_page = 1;  | 
            ||
| 1457 | 				if( isset( $_GET['completed_page'] ) && 0 < intval( $_GET['completed_page'] ) ) { | 
            ||
| 1458 | $current_page = $_GET['completed_page'];  | 
            ||
| 1459 | }  | 
            ||
| 1460 | |||
| 1461 | $complete_html .= '<nav class="pagination woo-pagination">';  | 
            ||
| 1462 | $total_pages = ceil( $completed_count / $per_page );  | 
            ||
| 1463 | |||
| 1464 | |||
| 1465 | 				if( $current_page > 1 ) { | 
            ||
| 1466 | $prev_link = add_query_arg( 'completed_page', $current_page - 1 );  | 
            ||
| 1467 | $complete_html .= '<a class="prev page-numbers" href="' . esc_url( $prev_link ) . '">' . __( 'Previous' , 'woothemes-sensei' ) . '</a> ';  | 
            ||
| 1468 | }  | 
            ||
| 1469 | |||
| 1470 | 				for ( $i = 1; $i <= $total_pages; $i++ ) { | 
            ||
| 1471 | $link = add_query_arg( 'completed_page', $i );  | 
            ||
| 1472 | |||
| 1473 | 					if( $i == $current_page ) { | 
            ||
| 1474 | $complete_html .= '<span class="page-numbers current">' . $i . '</span> ';  | 
            ||
| 1475 | 					} else { | 
            ||
| 1476 | $complete_html .= '<a class="page-numbers" href="' . esc_url( $link ) . '">' . $i . '</a> ';  | 
            ||
| 1477 | }  | 
            ||
| 1478 | }  | 
            ||
| 1479 | |||
| 1480 | 				if( $current_page < $total_pages ) { | 
            ||
| 1481 | $next_link = add_query_arg( 'completed_page', $current_page + 1 );  | 
            ||
| 1482 | $complete_html .= '<a class="next page-numbers" href="' . esc_url( $next_link ) . '">' . __( 'Next' , 'woothemes-sensei' ) . '</a> ';  | 
            ||
| 1483 | }  | 
            ||
| 1484 | |||
| 1485 | $complete_html .= '</nav>';  | 
            ||
| 1486 | }  | 
            ||
| 1487 | |||
| 1488 | } // End If Statement  | 
            ||
| 1489 | |||
| 1490 | 		if( $manage ) { | 
            ||
| 1491 | $no_active_message = __( 'You have no active courses.', 'woothemes-sensei' );  | 
            ||
| 1492 | $no_complete_message = __( 'You have not completed any courses yet.', 'woothemes-sensei' );  | 
            ||
| 1493 | 		} else { | 
            ||
| 1494 | $no_active_message = __( 'This learner has no active courses.', 'woothemes-sensei' );  | 
            ||
| 1495 | $no_complete_message = __( 'This learner has not completed any courses yet.', 'woothemes-sensei' );  | 
            ||
| 1496 | }  | 
            ||
| 1497 | |||
| 1498 | ob_start();  | 
            ||
| 1499 | ?>  | 
            ||
| 1500 | |||
| 1501 | <?php do_action( 'sensei_before_user_courses' ); ?>  | 
            ||
| 1502 | |||
| 1503 | <?php  | 
            ||
| 1504 | 		if( $manage && ( ! isset( Sensei()->settings->settings['messages_disable'] ) || ! Sensei()->settings->settings['messages_disable'] ) ) { | 
            ||
| 1505 | ?>  | 
            ||
| 1506 | <p class="my-messages-link-container">  | 
            ||
| 1507 | <a class="my-messages-link" href="<?php echo get_post_type_archive_link( 'sensei_message' ); ?>"  | 
            ||
| 1508 | title="<?php _e( 'View & reply to private messages sent to your course & lesson teachers.', 'woothemes-sensei' ); ?>">  | 
            ||
| 1509 | <?php _e( 'My Messages', 'woothemes-sensei' ); ?>  | 
            ||
| 1510 | </a>  | 
            ||
| 1511 | </p>  | 
            ||
| 1512 | <?php  | 
            ||
| 1513 | }  | 
            ||
| 1514 | ?>  | 
            ||
| 1515 | <div id="my-courses">  | 
            ||
| 1516 | |||
| 1517 | <ul>  | 
            ||
| 1518 | <li><a href="#active-courses"><?php _e( 'Active Courses', 'woothemes-sensei' ); ?></a></li>  | 
            ||
| 1519 | <li><a href="#completed-courses"><?php _e( 'Completed Courses', 'woothemes-sensei' ); ?></a></li>  | 
            ||
| 1520 | </ul>  | 
            ||
| 1521 | |||
| 1522 | <?php do_action( 'sensei_before_active_user_courses' ); ?>  | 
            ||
| 1523 | |||
| 1524 | <?php  | 
            ||
| 1525 | $course_page_url = Sensei_Course::get_courses_page_url();  | 
            ||
| 1526 | ?>  | 
            ||
| 1527 | |||
| 1528 | <div id="active-courses">  | 
            ||
| 1529 | |||
| 1530 | 		    	<?php if ( '' != $active_html ) { | 
            ||
| 1531 | |||
| 1532 | echo $active_html;  | 
            ||
| 1533 | |||
| 1534 | 		    	} else { ?> | 
            ||
| 1535 | |||
| 1536 | <div class="sensei-message info">  | 
            ||
| 1537 | |||
| 1538 | <?php echo $no_active_message; ?>  | 
            ||
| 1539 | |||
| 1540 | <a href="<?php echo $course_page_url; ?>">  | 
            ||
| 1541 | |||
| 1542 | <?php _e( 'Start a Course!', 'woothemes-sensei' ); ?>  | 
            ||
| 1543 | |||
| 1544 | </a>  | 
            ||
| 1545 | |||
| 1546 | </div>  | 
            ||
| 1547 | |||
| 1548 | <?php } // End If Statement ?>  | 
            ||
| 1549 | |||
| 1550 | </div>  | 
            ||
| 1551 | |||
| 1552 | <?php do_action( 'sensei_after_active_user_courses' ); ?>  | 
            ||
| 1553 | |||
| 1554 | <?php do_action( 'sensei_before_completed_user_courses' ); ?>  | 
            ||
| 1555 | |||
| 1556 | <div id="completed-courses">  | 
            ||
| 1557 | |||
| 1558 | 		    	<?php if ( '' != $complete_html ) { | 
            ||
| 1559 | |||
| 1560 | echo $complete_html;  | 
            ||
| 1561 | |||
| 1562 | 		    	} else { ?> | 
            ||
| 1563 | |||
| 1564 | <div class="sensei-message info">  | 
            ||
| 1565 | |||
| 1566 | <?php echo $no_complete_message; ?>  | 
            ||
| 1567 | |||
| 1568 | </div>  | 
            ||
| 1569 | |||
| 1570 | <?php } // End If Statement ?>  | 
            ||
| 1571 | |||
| 1572 | </div>  | 
            ||
| 1573 | |||
| 1574 | <?php do_action( 'sensei_after_completed_user_courses' ); ?>  | 
            ||
| 1575 | |||
| 1576 | </div>  | 
            ||
| 1577 | |||
| 1578 | <?php do_action( 'sensei_after_user_courses' ); ?>  | 
            ||
| 1579 | |||
| 1580 | <?php  | 
            ||
| 1581 | echo ob_get_clean();  | 
            ||
| 1582 | |||
| 1583 | do_action( 'sensei_after_learner_course_content', $user );  | 
            ||
| 1584 | |||
| 1585 | } // end load_user_courses_content  | 
            ||
| 1586 | |||
| 1587 | /**  | 
            ||
| 1588 | * Returns a list of all courses  | 
            ||
| 1589 | *  | 
            ||
| 1590 | * @since 1.8.0  | 
            ||
| 1591 |      * @return array $courses{ | 
            ||
| 1592 | * @type $course WP_Post  | 
            ||
| 1593 | * }  | 
            ||
| 1594 | */  | 
            ||
| 1595 |     public static function get_all_courses(){ | 
            ||
| 1621 | |||
| 1622 | /**  | 
            ||
| 1623 | * Generate the course meter component  | 
            ||
| 1624 | *  | 
            ||
| 1625 | * @since 1.8.0  | 
            ||
| 1626 | * @param int $progress_percentage 0 - 100  | 
            ||
| 1627 | * @return string $progress_bar_html  | 
            ||
| 1628 | */  | 
            ||
| 1629 |     public function get_progress_meter( $progress_percentage ){ | 
            ||
| 1643 | |||
| 1644 | /**  | 
            ||
| 1645 | * Generate a statement that tells users  | 
            ||
| 1646 | * how far they are in the course.  | 
            ||
| 1647 | *  | 
            ||
| 1648 | * @param int $course_id  | 
            ||
| 1649 | * @param int $user_id  | 
            ||
| 1650 | *  | 
            ||
| 1651 | * @return string $statement_html  | 
            ||
| 1652 | */  | 
            ||
| 1653 |     public function get_progress_statement( $course_id, $user_id ){ | 
            ||
| 1674 | |||
| 1675 | /**  | 
            ||
| 1676 | * Output the course progress statement  | 
            ||
| 1677 | *  | 
            ||
| 1678 | * @param $course_id  | 
            ||
| 1679 | * @return void  | 
            ||
| 1680 | */  | 
            ||
| 1681 |     public function the_progress_statement( $course_id = 0, $user_id = 0 ){ | 
            ||
| 1693 | |||
| 1694 | /**  | 
            ||
| 1695 | * Output the course progress bar  | 
            ||
| 1696 | *  | 
            ||
| 1697 | * @param $course_id  | 
            ||
| 1698 | * @return void  | 
            ||
| 1699 | */  | 
            ||
| 1700 |     public function the_progress_meter( $course_id = 0, $user_id = 0 ){ | 
            ||
| 1720 | |||
| 1721 | /**  | 
            ||
| 1722 | * Checks how many lessons are completed  | 
            ||
| 1723 | *  | 
            ||
| 1724 | * @since 1.8.0  | 
            ||
| 1725 | *  | 
            ||
| 1726 | * @param int $course_id  | 
            ||
| 1727 | * @param int $user_id  | 
            ||
| 1728 | * @return array $completed_lesson_ids  | 
            ||
| 1729 | */  | 
            ||
| 1730 |     public function get_completed_lesson_ids( $course_id, $user_id = 0 ){ | 
            ||
| 1752 | |||
| 1753 | /**  | 
            ||
| 1754 | * Calculate the perceantage completed in the course  | 
            ||
| 1755 | *  | 
            ||
| 1756 | * @since 1.8.0  | 
            ||
| 1757 | *  | 
            ||
| 1758 | * @param int $course_id  | 
            ||
| 1759 | * @param int $user_id  | 
            ||
| 1760 | * @return int $percentage  | 
            ||
| 1761 | */  | 
            ||
| 1762 |     public function get_completion_percentage( $course_id, $user_id = 0 ){ | 
            ||
| 1789 | |||
| 1790 | /**  | 
            ||
| 1791 | * Block email notifications for the specific courses  | 
            ||
| 1792 | * that the user disabled the notifications.  | 
            ||
| 1793 | *  | 
            ||
| 1794 | * @since 1.8.0  | 
            ||
| 1795 | * @param $should_send  | 
            ||
| 1796 | * @return bool  | 
            ||
| 1797 | */  | 
            ||
| 1798 |     public function block_notification_emails( $should_send ){ | 
            ||
| 1833 | |||
| 1834 | /**  | 
            ||
| 1835 | * Render the course notification setting meta box  | 
            ||
| 1836 | *  | 
            ||
| 1837 | * @since 1.8.0  | 
            ||
| 1838 | * @param $course  | 
            ||
| 1839 | */  | 
            ||
| 1840 |     public function course_notification_meta_box_content( $course ){ | 
            ||
| 1855 | |||
| 1856 | /**  | 
            ||
| 1857 | * Store the setting for the course notification setting.  | 
            ||
| 1858 | *  | 
            ||
| 1859 | * @hooked int save_post  | 
            ||
| 1860 | * @since 1.8.0  | 
            ||
| 1861 | *  | 
            ||
| 1862 | * @param $course_id  | 
            ||
| 1863 | */  | 
            ||
| 1864 |     public function save_course_notification_meta_box( $course_id ){ | 
            ||
| 1880 | |||
| 1881 | /**  | 
            ||
| 1882 | * Backwards compatibility hooks added to ensure that  | 
            ||
| 1883 | * plugins and other parts of sensei still works.  | 
            ||
| 1884 | *  | 
            ||
| 1885 | * This function hooks into `sensei_course_content_inside_before`  | 
            ||
| 1886 | *  | 
            ||
| 1887 | * @since 1.9  | 
            ||
| 1888 | *  | 
            ||
| 1889 | * @param WP_Post $post  | 
            ||
| 1890 | */  | 
            ||
| 1891 |     public function content_before_backwards_compatibility_hooks( $post ){ | 
            ||
| 1908 | |||
| 1909 | /**  | 
            ||
| 1910 | * Backwards compatibility hooks that should be hooked into sensei_loop_course_before  | 
            ||
| 1911 | *  | 
            ||
| 1912 | * hooked into 'sensei_loop_course_before'  | 
            ||
| 1913 | *  | 
            ||
| 1914 | * @since 1.9  | 
            ||
| 1915 | *  | 
            ||
| 1916 | * @global WP_Post $post  | 
            ||
| 1917 | */  | 
            ||
| 1918 |     public  function loop_before_backwards_compatibility_hooks( ){ | 
            ||
| 1924 | |||
| 1925 | /**  | 
            ||
| 1926 | * Output a link to view course. The button text is different depending on the amount of preview lesson available.  | 
            ||
| 1927 | *  | 
            ||
| 1928 | * hooked into 'sensei_course_content_inside_after'  | 
            ||
| 1929 | *  | 
            ||
| 1930 | * @since 1.9.0  | 
            ||
| 1931 | *  | 
            ||
| 1932 | * @param WP_Post $course  | 
            ||
| 1933 | */  | 
            ||
| 1934 |     public function the_course_free_lesson_preview( $course ){ | 
            ||
| 1951 | |||
| 1952 | /**  | 
            ||
| 1953 | * Add course mata to the course meta hook  | 
            ||
| 1954 | *  | 
            ||
| 1955 | * @since 1.9.0  | 
            ||
| 1956 | * @param WP_Post $course  | 
            ||
| 1957 | */  | 
            ||
| 1958 |     public function the_course_meta( $course ){ | 
            ||
| 1993 | |||
| 1994 | /**  | 
            ||
| 1995 | * Filter the classes attached to a post types for courses  | 
            ||
| 1996 | * and add a status class for when the user is logged in.  | 
            ||
| 1997 | *  | 
            ||
| 1998 | * @param $classes  | 
            ||
| 1999 | * @param $class  | 
            ||
| 2000 | * @param $post_id  | 
            ||
| 2001 | *  | 
            ||
| 2002 | * @return array $classes  | 
            ||
| 2003 | */  | 
            ||
| 2004 |     public static function add_course_user_status_class( $classes, $class, $course_id ){ | 
            ||
| 2023 | |||
| 2024 | /**  | 
            ||
| 2025 | * Prints out the course action buttons links  | 
            ||
| 2026 | *  | 
            ||
| 2027 | * - complete course  | 
            ||
| 2028 | * - delete course  | 
            ||
| 2029 | *  | 
            ||
| 2030 | * @param WP_Post $course  | 
            ||
| 2031 | */  | 
            ||
| 2032 |     public static function the_course_action_buttons( $course ){ | 
            ||
| 2033 | |||
| 2034 |         if( is_user_logged_in() ) { ?> | 
            ||
| 2035 | |||
| 2036 | <section class="entry-actions">  | 
            ||
| 2037 | <form method="POST" action="<?php echo esc_url( remove_query_arg( array( 'active_page', 'completed_page' ) ) ); ?>">  | 
            ||
| 2038 | |||
| 2039 | <input type="hidden"  | 
            ||
| 2040 | name="<?php esc_attr_e( 'woothemes_sensei_complete_course_noonce' ) ?>"  | 
            ||
| 2041 | id="<?php esc_attr_e( 'woothemes_sensei_complete_course_noonce' ); ?>"  | 
            ||
| 2042 | value="<?php esc_attr_e( wp_create_nonce( 'woothemes_sensei_complete_course_noonce' ) ); ?>"  | 
            ||
| 2043 | />  | 
            ||
| 2044 | |||
| 2045 | <input type="hidden" name="course_complete_id" id="course-complete-id" value="<?php esc_attr_e( intval( $course->ID ) ); ?>" />  | 
            ||
| 2046 | |||
| 2047 |                     <?php if ( 0 < absint( count( Sensei()->course->course_lessons( $course->ID ) ) ) && Sensei()->settings->settings['course_completion'] == 'complete' ) { ?> | 
            ||
| 2048 | |||
| 2049 | <span><input name="course_complete" type="submit" class="course-complete" value="<?php _e( 'Mark as Complete', 'woothemes-sensei' ); ?>" /></span>  | 
            ||
| 2050 | |||
| 2051 | <?php } // End If Statement  | 
            ||
| 2052 | |||
| 2053 | $course_purchased = false;  | 
            ||
| 2054 |                     if ( WooThemes_Sensei_Utils::sensei_is_woocommerce_activated() ) { | 
            ||
| 2055 | // Get the product ID  | 
            ||
| 2056 | $wc_post_id = get_post_meta( intval( $course->ID ), '_course_woocommerce_product', true );  | 
            ||
| 2057 |                         if ( 0 < $wc_post_id ) { | 
            ||
| 2058 | |||
| 2059 | $user = wp_get_current_user();  | 
            ||
| 2060 | $course_purchased = WooThemes_Sensei_Utils::sensei_customer_bought_product( $user->user_email, $user->ID, $wc_post_id );  | 
            ||
| 2061 | |||
| 2062 | } // End If Statement  | 
            ||
| 2063 | } // End If Statement  | 
            ||
| 2064 | |||
| 2065 |                     if ( ! $course_purchased && ! WooThemes_Sensei_Utils::user_completed_course( $course->ID, get_current_user_id() ) ) {?> | 
            ||
| 2066 | |||
| 2067 | <span><input name="course_complete" type="submit" class="course-delete" value="<?php echo __( 'Delete Course', 'woothemes-sensei' ); ?>"/></span>  | 
            ||
| 2068 | |||
| 2069 | <?php } // End If Statement  | 
            ||
| 2070 | |||
| 2071 | $has_quizzes = Sensei()->course->course_quizzes( $course->ID, true );  | 
            ||
| 2072 | $results_link = '';  | 
            ||
| 2073 | View Code Duplication |                     if( $has_quizzes ){ | 
            |
| 2074 | $results_link = '<a class="button view-results" href="' . Sensei()->course_results->get_permalink( $course->ID ) . '">' . __( 'View results', 'woothemes-sensei' ) . '</a>';  | 
            ||
| 2075 | }  | 
            ||
| 2076 | |||
| 2077 | // Output only if there is content to display  | 
            ||
| 2078 |                     if ( has_filter( 'sensei_results_links' ) || $has_quizzes ) { ?> | 
            ||
| 2079 | |||
| 2080 | <p class="sensei-results-links">  | 
            ||
| 2081 | <?php echo apply_filters( 'sensei_results_links', $results_link ); ?>  | 
            ||
| 2082 | </p>  | 
            ||
| 2083 | |||
| 2084 | <?php } // end if has filter ?>  | 
            ||
| 2085 | </form>  | 
            ||
| 2086 | </section>  | 
            ||
| 2087 | |||
| 2088 | <?php }// end if is user logged in  | 
            ||
| 2089 | |||
| 2090 | }// end the_course_action_buttons  | 
            ||
| 2091 | |||
| 2092 | /**  | 
            ||
| 2093 | * This function alter the main query on the course archive page.  | 
            ||
| 2094 | * This also gives Sensei specific filters that allows variables to be altered specifically on the course archive.  | 
            ||
| 2095 | *  | 
            ||
| 2096 | * This function targets only the course archives and the my courses page. Shortcodes can set their own  | 
            ||
| 2097 | * query parameters via the arguments.  | 
            ||
| 2098 | *  | 
            ||
| 2099 | * This function is hooked into pre_get_posts filter  | 
            ||
| 2100 | *  | 
            ||
| 2101 | * @since 1.9.0  | 
            ||
| 2102 | *  | 
            ||
| 2103 | * @param WP_Query $query  | 
            ||
| 2104 | * @return WP_Query $query  | 
            ||
| 2105 | */  | 
            ||
| 2106 |     public static function course_query_filter( $query ){ | 
            ||
| 2133 | |||
| 2134 | /**  | 
            ||
| 2135 | * Determine the class of the course loop  | 
            ||
| 2136 | *  | 
            ||
| 2137 | * This will output .first or .last and .course-item-number-x  | 
            ||
| 2138 | *  | 
            ||
| 2139 | * @return array $extra_classes  | 
            ||
| 2140 | * @since 1.9.0  | 
            ||
| 2141 | */  | 
            ||
| 2142 | public static function get_course_loop_content_class ()  | 
            ||
| 2187 | |||
| 2188 | /**  | 
            ||
| 2189 | * Get the number of columns set for Sensei courses  | 
            ||
| 2190 | *  | 
            ||
| 2191 | * @since 1.9.0  | 
            ||
| 2192 | * @return mixed|void  | 
            ||
| 2193 | */  | 
            ||
| 2194 |     public static function get_loop_number_of_columns(){ | 
            ||
| 2205 | |||
| 2206 | /**  | 
            ||
| 2207 | * Output the course archive filter markup  | 
            ||
| 2208 | *  | 
            ||
| 2209 | * hooked into sensei_loop_course_before  | 
            ||
| 2210 | *  | 
            ||
| 2211 | * @since 1.9.0  | 
            ||
| 2212 | * @param  | 
            ||
| 2213 | */  | 
            ||
| 2214 |     public static function course_archive_sorting( $query ){ | 
            ||
| 2259 | |||
| 2260 | /**  | 
            ||
| 2261 | * Output the course archive filter markup  | 
            ||
| 2262 | *  | 
            ||
| 2263 | * hooked into sensei_loop_course_before  | 
            ||
| 2264 | *  | 
            ||
| 2265 | * @since 1.9.0  | 
            ||
| 2266 | * @param  | 
            ||
| 2267 | */  | 
            ||
| 2268 |     public static function course_archive_filters( $query ){ | 
            ||
| 2311 | |||
| 2312 | /**  | 
            ||
| 2313 | * if the featured link is clicked on the course archive page  | 
            ||
| 2314 | * filter the courses returned to only show those featured  | 
            ||
| 2315 | *  | 
            ||
| 2316 | * Hooked into pre_get_posts  | 
            ||
| 2317 | *  | 
            ||
| 2318 | * @since 1.9.0  | 
            ||
| 2319 | * @param WP_Query $query  | 
            ||
| 2320 | * @return WP_Query $query  | 
            ||
| 2321 | */  | 
            ||
| 2322 |     public static function course_archive_featured_filter( $query ){ | 
            ||
| 2333 | |||
| 2334 | /**  | 
            ||
| 2335 | * if the course order drop down is changed  | 
            ||
| 2336 | *  | 
            ||
| 2337 | * Hooked into pre_get_posts  | 
            ||
| 2338 | *  | 
            ||
| 2339 | * @since 1.9.0  | 
            ||
| 2340 | * @param WP_Query $query  | 
            ||
| 2341 | * @return WP_Query $query  | 
            ||
| 2342 | */  | 
            ||
| 2343 |     public static function course_archive_order_by_title( $query ){ | 
            ||
| 2354 | |||
| 2355 | |||
| 2356 | /**  | 
            ||
| 2357 | * Get the link to the courses page. This will be the course post type archive  | 
            ||
| 2358 | * page link or the page the user set in their settings  | 
            ||
| 2359 | *  | 
            ||
| 2360 | * @since 1.9.0  | 
            ||
| 2361 | * @return string $course_page_url  | 
            ||
| 2362 | */  | 
            ||
| 2363 |     public static function get_courses_page_url(){ | 
            ||
| 2371 | |||
| 2372 | /**  | 
            ||
| 2373 | * Output the headers on the course archive page  | 
            ||
| 2374 | *  | 
            ||
| 2375 | * Hooked into the sensei_archive_title  | 
            ||
| 2376 | *  | 
            ||
| 2377 | * @since 1.9.0  | 
            ||
| 2378 | * @param string $query_type  | 
            ||
| 2379 | * @param string $before_html  | 
            ||
| 2380 | * @param string $after_html  | 
            ||
| 2381 | * @return void  | 
            ||
| 2382 | */  | 
            ||
| 2383 |     public static function archive_header( $query_type ='' , $before_html='', $after_html =''  ){ | 
            ||
| 2440 | |||
| 2441 | |||
| 2442 | /**  | 
            ||
| 2443 | * Filter the single course content  | 
            ||
| 2444 | * taking into account if the user has access.  | 
            ||
| 2445 | *  | 
            ||
| 2446 | * @1.9.0  | 
            ||
| 2447 | *  | 
            ||
| 2448 | * @param string $content  | 
            ||
| 2449 | * @return string $content or $excerpt  | 
            ||
| 2450 | */  | 
            ||
| 2451 |     public static function single_course_content( $content ){ | 
            ||
| 2497 | |||
| 2498 | /**  | 
            ||
| 2499 | * Output the the single course lessons title with markup.  | 
            ||
| 2500 | *  | 
            ||
| 2501 | * @since 1.9.0  | 
            ||
| 2502 | */  | 
            ||
| 2503 |     public static function the_course_lessons_title(){ | 
            ||
| 2541 | |||
| 2542 | /**  | 
            ||
| 2543 | * This function loads the global wp_query object with with lessons  | 
            ||
| 2544 | * of the current course. It is designed to be used on the single-course template  | 
            ||
| 2545 | * and expects the global post to be a singular course.  | 
            ||
| 2546 | *  | 
            ||
| 2547 | * This function excludes lessons belonging to modules as they are  | 
            ||
| 2548 | * queried separately.  | 
            ||
| 2549 | *  | 
            ||
| 2550 | * @since 1.9.0  | 
            ||
| 2551 | * @global $wp_query  | 
            ||
| 2552 | */  | 
            ||
| 2553 |     public static function load_single_course_lessons_query(){ | 
            ||
| 2602 | |||
| 2603 | /**  | 
            ||
| 2604 | * Flush the rewrite rules for a course post type  | 
            ||
| 2605 | *  | 
            ||
| 2606 | * @since 1.9.0  | 
            ||
| 2607 | *  | 
            ||
| 2608 | * @param $post_id  | 
            ||
| 2609 | */  | 
            ||
| 2610 | View Code Duplication |     public static function flush_rewrite_rules( $post_id ){ | 
            |
| 2626 | |||
| 2627 | /**  | 
            ||
| 2628 | * Optionally return the full content on the single course pages  | 
            ||
| 2629 | * depending on the users course_single_content_display setting  | 
            ||
| 2630 | *  | 
            ||
| 2631 | * @since 1.9.0  | 
            ||
| 2632 | * @param $excerpt  | 
            ||
| 2633 | * @return string  | 
            ||
| 2634 | */  | 
            ||
| 2635 |     public static function full_content_excerpt_override( $excerpt ){ | 
            ||
| 2649 | |||
| 2650 | /**  | 
            ||
| 2651 | * Output the course actions like start taking course, register, add to cart etc.  | 
            ||
| 2652 | *  | 
            ||
| 2653 | * @since 1.9.0  | 
            ||
| 2654 | */  | 
            ||
| 2655 |     public static function the_course_enrolment_actions(){ | 
            ||
| 2754 | |||
| 2755 | /**  | 
            ||
| 2756 | * Output the course video inside the loop.  | 
            ||
| 2757 | *  | 
            ||
| 2758 | * @since 1.9.0  | 
            ||
| 2759 | */  | 
            ||
| 2760 |     public static function the_course_video(){ | 
            ||
| 2780 | |||
| 2781 | /**  | 
            ||
| 2782 | * Output the title for the single lesson page  | 
            ||
| 2783 | *  | 
            ||
| 2784 | * @global $post  | 
            ||
| 2785 | * @since 1.9.0  | 
            ||
| 2786 | */  | 
            ||
| 2787 |     public static function the_title(){ | 
            ||
| 2810 | |||
| 2811 | /**  | 
            ||
| 2812 | * Show the title on the course category pages  | 
            ||
| 2813 | *  | 
            ||
| 2814 | * @since 1.9.0  | 
            ||
| 2815 | */  | 
            ||
| 2816 |     public static function course_category_title(){ | 
            ||
| 2842 | |||
| 2843 | /**  | 
            ||
| 2844 | * Alter the course query to respect the order set for courses and apply  | 
            ||
| 2845 | * this on the course-category pages.  | 
            ||
| 2846 | *  | 
            ||
| 2847 | * @since 1.9.0  | 
            ||
| 2848 | *  | 
            ||
| 2849 | * @param WP_Query $query  | 
            ||
| 2850 | * @return WP_Query  | 
            ||
| 2851 | */  | 
            ||
| 2852 |     public static function alter_course_category_order( $query ){ | 
            ||
| 2867 | |||
| 2868 | /**  | 
            ||
| 2869 | * The very basic course query arguments  | 
            ||
| 2870 | * so we don't have to repeat this througout  | 
            ||
| 2871 | * the code base.  | 
            ||
| 2872 | *  | 
            ||
| 2873 | * Usage:  | 
            ||
| 2874 | * $args = Sensei_Course::get_default_query_args();  | 
            ||
| 2875 | * $args['custom_arg'] ='custom value';  | 
            ||
| 2876 | * $courses = get_posts( $args )  | 
            ||
| 2877 | *  | 
            ||
| 2878 | * @since 1.9.0  | 
            ||
| 2879 | *  | 
            ||
| 2880 | * @return array  | 
            ||
| 2881 | */  | 
            ||
| 2882 |     public static function get_default_query_args(){ | 
            ||
| 2891 | |||
| 2892 | /**  | 
            ||
| 2893 | * Check if the prerequisite course is completed  | 
            ||
| 2894 | * Courses with no pre-requisite should always return true  | 
            ||
| 2895 | *  | 
            ||
| 2896 | * @since 1.9.0  | 
            ||
| 2897 | * @param $course_id  | 
            ||
| 2898 | * @return bool  | 
            ||
| 2899 | */  | 
            ||
| 2900 |     public static function is_prerequisite_complete( $course_id ){ | 
            ||
| 2914 | |||
| 2915 | |||
| 2916 | }// End Class  | 
            ||
| 2917 | |||
| 2924 | 
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.