1: <?php
2: if ( ! defined( 'ABSPATH' ) ) exit;
3:
4: 5: 6: 7: 8: 9: 10: 11: 12:
13: class Sensei_Course {
14:
15: 16: 17:
18: public $token;
19:
20: 21: 22:
23: public $meta_fields;
24:
25: 26: 27: 28:
29: public $my_courses_page;
30:
31: 32: 33: 34:
35: public function __construct () {
36:
37: $this->token = 'course';
38:
39:
40: $this->meta_fields = array( 'course_prerequisite', 'course_featured', 'course_video_embed', 'course_woocommerce_product' );
41:
42: if ( is_admin() ) {
43:
44: add_action( 'add_meta_boxes', array( $this, 'meta_box_setup' ), 20 );
45: add_action( 'save_post', array( $this, 'meta_box_save' ) );
46:
47: add_filter( 'manage_edit-course_columns', array( $this, 'add_column_headings' ), 10, 1 );
48: add_action( 'manage_posts_custom_column', array( $this, 'add_column_data' ), 10, 2 );
49: } else {
50: $this->my_courses_page = false;
51: }
52:
53:
54: add_action( 'sensei_user_lesson_end', array( $this, 'update_status_after_lesson_change' ), 10, 2 );
55:
56: add_action( 'sensei_user_lesson_reset', array( $this, 'update_status_after_lesson_change' ), 10, 2 );
57:
58: add_action( 'sensei_user_quiz_grade', array( $this, 'update_status_after_quiz_submission' ), 10, 2 );
59:
60:
61: add_action( 'sensei_single_course_content_inside_before' , array( $this, 'the_progress_statement' ), 15 );
62: add_action( 'sensei_single_course_content_inside_before' , array( $this, 'the_progress_meter' ), 16 );
63:
64:
65: add_filter( 'sensei_send_emails', array( $this, 'block_notification_emails' ) );
66: add_action( 'save_post', array( $this, 'save_course_notification_meta_box' ) );
67:
68:
69: add_action( 'sensei_course_content_inside_after',array( $this, 'the_course_free_lesson_preview' ) );
70:
71:
72: add_action('sensei_course_content_inside_before', array( $this, 'the_course_meta' ) );
73:
74:
75: add_action('sensei_course_content_inside_before', array( $this, 'content_before_backwards_compatibility_hooks' ));
76: add_action('sensei_loop_course_before', array( $this,'loop_before_backwards_compatibility_hooks' ) );
77:
78:
79: add_filter('post_class', array( __CLASS__ , 'add_course_user_status_class' ), 20, 3 );
80:
81:
82: add_filter( 'pre_get_posts', array( __CLASS__, 'course_query_filter' ) );
83:
84:
85: add_action ( 'sensei_archive_before_course_loop' , array( 'Sensei_Course', 'course_archive_sorting' ) );
86:
87:
88: add_action ( 'sensei_archive_before_course_loop' , array( 'Sensei_Course', 'course_archive_filters' ) );
89:
90:
91: add_filter( 'pre_get_posts', array( __CLASS__, 'course_archive_featured_filter'));
92:
93:
94: add_filter( 'pre_get_posts', array( __CLASS__, 'course_archive_order_by_title'));
95:
96:
97: add_filter( 'pre_get_posts', array( __CLASS__, 'alter_course_category_order'));
98:
99:
100: add_action('save_post', array( 'Sensei_Course', 'flush_rewrite_rules' ) );
101:
102:
103: add_action( 'pre_get_posts', array( $this, 'allow_course_archive_on_front_page' ) );
104:
105: }
106:
107: 108: 109: 110: 111: 112:
113: public function update_status_after_quiz_submission( $user_id, $quiz_id ) {
114: if ( intval( $user_id ) > 0 && intval( $quiz_id ) > 0 ) {
115: $lesson_id = get_post_meta( $quiz_id, '_quiz_lesson', true );
116: $this->update_status_after_lesson_change( $user_id, $lesson_id );
117: }
118: }
119:
120: 121: 122: 123: 124: 125:
126: public function update_status_after_lesson_change( $user_id, $lesson_id ) {
127: if ( intval( $user_id ) > 0 && intval( $lesson_id ) > 0 ) {
128: $course_id = get_post_meta( $lesson_id, '_lesson_course', true );
129: if ( intval( $course_id ) > 0 ) {
130:
131: Sensei_Utils::user_complete_course( $course_id, $user_id );
132: }
133: }
134: }
135:
136: 137: 138: 139: 140: 141:
142: public function meta_box_setup () {
143:
144: if ( Sensei_WC::is_woocommerce_active() ) {
145:
146: add_meta_box( 'course-wc-product', __( 'WooCommerce Product', 'woothemes-sensei' ), array( $this, 'course_woocommerce_product_meta_box_content' ), $this->token, 'side', 'default' );
147: }
148:
149: add_meta_box( 'course-prerequisite', __( 'Course Prerequisite', 'woothemes-sensei' ), array( $this, 'course_prerequisite_meta_box_content' ), $this->token, 'side', 'default' );
150:
151: add_meta_box( 'course-featured', __( 'Featured Course', 'woothemes-sensei' ), array( $this, 'course_featured_meta_box_content' ), $this->token, 'side', 'default' );
152:
153: add_meta_box( 'course-video', __( 'Course Video', 'woothemes-sensei' ), array( $this, 'course_video_meta_box_content' ), $this->token, 'normal', 'default' );
154:
155: add_meta_box( 'course-lessons', __( 'Course Lessons', 'woothemes-sensei' ), array( $this, 'course_lessons_meta_box_content' ), $this->token, 'normal', 'default' );
156:
157: add_meta_box( 'course-manage', __( 'Course Management', 'woothemes-sensei' ), array( $this, 'course_manage_meta_box_content' ), $this->token, 'side', 'default' );
158:
159: remove_meta_box( 'woothemes-settings', $this->token, 'normal' );
160:
161:
162: add_meta_box( 'course-notifications', __( 'Course Notifications', 'woothemes-sensei' ), array( $this, 'course_notification_meta_box_content' ), 'course', 'normal', 'default' );
163:
164: }
165:
166: 167: 168: 169: 170: 171:
172: public function course_woocommerce_product_meta_box_content () {
173: global $post;
174:
175: $select_course_woocommerce_product = get_post_meta( $post->ID, '_course_woocommerce_product', true );
176:
177: $post_args = array( 'post_type' => array( 'product', 'product_variation' ),
178: 'posts_per_page' => -1,
179: 'orderby' => 'title',
180: 'order' => 'DESC',
181: 'exclude' => $post->ID,
182: 'post_status' => array( 'publish', 'private', 'draft' ),
183: 'tax_query' => array(
184: array(
185: 'taxonomy' => 'product_type',
186: 'field' => 'slug',
187: 'terms' => array( 'variable', 'grouped' ),
188: 'operator' => 'NOT IN'
189: )
190: ),
191: 'suppress_filters' => 0
192: );
193: $posts_array = get_posts( $post_args );
194:
195: $html = '';
196:
197: $html .= '<input type="hidden" name="' . esc_attr( 'woo_' . $this->token . '_noonce' ) . '" id="' . esc_attr( 'woo_' . $this->token . '_noonce' ) . '" value="' . esc_attr( wp_create_nonce( plugin_basename(__FILE__) ) ) . '" />';
198:
199: if ( count( $posts_array ) > 0 ) {
200:
201: $html .= '<select id="course-woocommerce-product-options" name="course_woocommerce_product" class="chosen_select widefat">' . "\n";
202: $html .= '<option value="-">' . __( 'None', 'woothemes-sensei' ) . '</option>';
203: $prev_parent_id = 0;
204: foreach ( $posts_array as $post_item ) {
205:
206: if ( 'product_variation' == $post_item->post_type ) {
207:
208: $product_object = get_product( $post_item->ID );
209: $parent_id = wp_get_post_parent_id( $post_item->ID );
210:
211: if( sensei_check_woocommerce_version( '2.1' ) ) {
212: $formatted_variation = wc_get_formatted_variation( $product_object->variation_data, true );
213:
214: } else {
215:
216: $formatted_variation = woocommerce_get_formatted_variation( $product_object->variation_data, true );
217:
218: }
219:
220: $product_name = ucwords( $formatted_variation );
221: if( empty( $product_name ) ){
222:
223: $product_name = __( 'Variation #', 'woothemes-sensei' ) . $product_object->variation_id;
224:
225: }
226:
227: } else {
228:
229: $parent_id = false;
230: $prev_parent_id = 0;
231: $product_name = $post_item->post_title;
232:
233: }
234:
235:
236: if( $parent_id && $parent_id != $prev_parent_id ) {
237:
238: if( 0 != $prev_parent_id ) {
239:
240: $html .= '</optgroup>';
241:
242: }
243: $html .= '<optgroup label="' . get_the_title( $parent_id ) . '">';
244: $prev_parent_id = $parent_id;
245:
246: } elseif( ! $parent_id && 0 == $prev_parent_id ) {
247:
248: $html .= '</optgroup>';
249:
250: }
251:
252: $html .= '<option value="' . esc_attr( absint( $post_item->ID ) ) . '"' . selected( $post_item->ID, $select_course_woocommerce_product, false ) . '>' . esc_html( $product_name ) . '</option>' . "\n";
253:
254: }
255:
256: $html .= '</select>' . "\n";
257: if ( current_user_can( 'publish_product' )) {
258:
259: $html .= '<p>' . "\n";
260: $html .= '<a href="' . admin_url( 'post-new.php?post_type=product' ) . '" title="' . esc_attr( __( 'Add a Product', 'woothemes-sensei' ) ) . '">' . __( 'Add a Product', 'woothemes-sensei' ) . '</a>' . "\n";
261: $html .= '</p>'."\n";
262:
263: }
264:
265: } else {
266:
267: if ( current_user_can( 'publish_product' )) {
268:
269: $html .= '<p>' . "\n";
270: $html .= esc_html( __( 'No products exist yet.', 'woothemes-sensei' ) ) . ' <a href="' . admin_url( 'post-new.php?post_type=product' ) . '" title="' . esc_attr( __( 'Add a Product', 'woothemes-sensei' ) ) . '">' . __( 'Please add some first', 'woothemes-sensei' ) . '</a>' . "\n";
271: $html .= '</p>'."\n";
272:
273: } else {
274:
275: $html .= '<p>' . "\n";
276: $html .= esc_html( __( 'No products exist yet.', 'woothemes-sensei' ) ) . "\n";
277: $html .= '</p>'."\n";
278:
279: }
280:
281: }
282:
283: echo $html;
284:
285: }
286:
287: 288: 289: 290: 291: 292:
293: public function course_prerequisite_meta_box_content () {
294: global $post;
295:
296: $select_course_prerequisite = get_post_meta( $post->ID, '_course_prerequisite', true );
297:
298: $post_args = array( 'post_type' => 'course',
299: 'posts_per_page' => -1,
300: 'orderby' => 'title',
301: 'order' => 'DESC',
302: 'exclude' => $post->ID,
303: 'suppress_filters' => 0
304: );
305: $posts_array = get_posts( $post_args );
306:
307: $html = '';
308:
309: $html .= '<input type="hidden" name="' . esc_attr( 'woo_' . $this->token . '_noonce' ) . '" id="' . esc_attr( 'woo_' . $this->token . '_noonce' ) . '" value="' . esc_attr( wp_create_nonce( plugin_basename(__FILE__) ) ) . '" />';
310:
311: if ( count( $posts_array ) > 0 ) {
312: $html .= '<select id="course-prerequisite-options" name="course_prerequisite" class="chosen_select widefat">' . "\n";
313: $html .= '<option value="">' . __( 'None', 'woothemes-sensei' ) . '</option>';
314: foreach ($posts_array as $post_item){
315: $html .= '<option value="' . esc_attr( absint( $post_item->ID ) ) . '"' . selected( $post_item->ID, $select_course_prerequisite, false ) . '>' . esc_html( $post_item->post_title ) . '</option>' . "\n";
316: }
317: $html .= '</select>' . "\n";
318: } else {
319: $html .= '<p>' . esc_html( __( 'No courses exist yet. Please add some first.', 'woothemes-sensei' ) ) . '</p>';
320: }
321:
322: echo $html;
323:
324: }
325:
326: 327: 328: 329: 330: 331:
332: public function course_featured_meta_box_content () {
333: global $post;
334:
335: $course_featured = get_post_meta( $post->ID, '_course_featured', true );
336:
337: $html = '';
338:
339: $html .= '<input type="hidden" name="' . esc_attr( 'woo_' . $this->token . '_noonce' ) . '" id="' . esc_attr( 'woo_' . $this->token . '_noonce' ) . '" value="' . esc_attr( wp_create_nonce( plugin_basename(__FILE__) ) ) . '" />';
340:
341: $checked = '';
342: if ( isset( $course_featured ) && ( '' != $course_featured ) ) {
343: $checked = checked( 'featured', $course_featured, false );
344: }
345:
346: $html .= '<input type="checkbox" name="course_featured" value="featured" ' . $checked . '> ' . __( 'Feature this course', 'woothemes-sensei' ) . '<br>';
347:
348: echo $html;
349:
350: }
351:
352: 353: 354: 355: 356: 357:
358: public function course_video_meta_box_content () {
359: global $post;
360:
361: $course_video_embed = get_post_meta( $post->ID, '_course_video_embed', true );
362:
363: $html = '';
364:
365: $html .= '<label class="screen-reader-text" for="course_video_embed">' . __( 'Video Embed Code', 'woothemes-sensei' ) . '</label>';
366: $html .= '<textarea rows="5" cols="50" name="course_video_embed" tabindex="6" id="course-video-embed">' . $course_video_embed . '</textarea>';
367: $html .= '<p>' . __( 'Paste the embed code for your video (e.g. YouTube, Vimeo etc.) in the box above.', 'woothemes-sensei' ) . '</p>';
368:
369: echo $html;
370:
371: }
372:
373: 374: 375: 376: 377: 378: 379: 380: 381:
382: public function meta_box_save ( $post_id ) {
383: global $post;
384:
385:
386: if ( ( get_post_type() != $this->token ) || ! wp_verify_nonce( $_POST['woo_' . $this->token . '_noonce'], plugin_basename(__FILE__) ) ) {
387: return $post_id;
388: }
389:
390:
391: $post_type = get_post_type_object( $post->post_type );
392:
393:
394: if ( !current_user_can( $post_type->cap->edit_post, $post_id ) ) {
395: return $post_id;
396: }
397:
398: if ( 'page' == $_POST['post_type'] ) {
399: if ( ! current_user_can( 'edit_page', $post_id ) ) {
400: return $post_id;
401: }
402: } else {
403: if ( ! current_user_can( 'edit_post', $post_id ) ) {
404: return $post_id;
405: }
406: }
407:
408:
409: if ( isset($this->meta_fields) && is_array($this->meta_fields) ) {
410: foreach ( $this->meta_fields as $meta_key ) {
411: $this->save_post_meta( $meta_key, $post_id );
412: }
413: }
414:
415: }
416:
417:
418: 419: 420: 421: 422: 423: 424: 425: 426: 427:
428: private function save_post_meta( $post_key = '', $post_id = 0 ) {
429:
430: $meta_key = '_' . $post_key;
431:
432: if ( 'course_video_embed' == $post_key) {
433: $new_meta_value = esc_html( $_POST[$post_key] );
434: } else {
435: $new_meta_value = ( isset( $_POST[$post_key] ) ? sanitize_html_class( $_POST[$post_key] ) : '' );
436: }
437:
438:
439: return update_post_meta( $post_id, $meta_key, $new_meta_value );
440:
441: }
442:
443: 444: 445: 446: 447: 448:
449: public function course_lessons_meta_box_content () {
450:
451: global $post;
452:
453:
454: $posts_array = array();
455: if ( 0 < $post->ID ) {
456:
457: $posts_array = $this->course_lessons( $post->ID, 'any' );
458:
459: }
460:
461: $html = '';
462: $html .= '<input type="hidden" name="' . esc_attr( 'woo_' . $this->token . '_noonce' ) . '" id="'
463: . esc_attr( 'woo_' . $this->token . '_noonce' )
464: . '" value="' . esc_attr( wp_create_nonce( plugin_basename(__FILE__) ) ) . '" />';
465:
466: if ( count( $posts_array ) > 0 ) {
467:
468: foreach ($posts_array as $post_item){
469:
470: $html .= '<p>'."\n";
471:
472: $html .= $post_item->post_title."\n";
473: $html .= '<a href="' . esc_url( get_edit_post_link( $post_item->ID ) ) . '" title="' . esc_attr( sprintf( __( 'Edit %s', 'woothemes-sensei' ), $post_item->post_title ) ) . '" class="edit-lesson-action">' . __( 'Edit this lesson', 'woothemes-sensei' ) . '</a>';
474:
475: $html .= '</p>'."\n";
476:
477: }
478:
479: } else {
480: $course_id = '';
481: if ( 0 < $post->ID ) { $course_id = '&course_id=' . $post->ID; }
482: $html .= '<p>' . esc_html( __( 'No lessons exist yet for this course.', 'woothemes-sensei' ) ) . "\n";
483:
484: $html .= '<a href="' . admin_url( 'post-new.php?post_type=lesson' . $course_id )
485: . '" title="' . esc_attr( __( 'Add a Lesson', 'woothemes-sensei' ) ) . '">'
486: . __( 'Please add some.', 'woothemes-sensei' ) . '</a>' . "\n";
487:
488: $html .= '</p>'."\n";
489: }
490:
491: echo $html;
492:
493: }
494:
495: 496: 497: 498: 499: 500: 501:
502:
503: public function course_manage_meta_box_content () {
504: global $post;
505:
506: $manage_url = esc_url( add_query_arg( array( 'page' => 'sensei_learners', 'course_id' => $post->ID, 'view' => 'learners' ), admin_url( 'admin.php') ) );
507:
508: $grading_url = esc_url( add_query_arg( array( 'page' => 'sensei_grading', 'course_id' => $post->ID, 'view' => 'learners' ), admin_url( 'admin.php') ) );
509:
510:
511: echo "<ul><li><a href='$manage_url'>".__("Manage Learners", 'woothemes-sensei')."</a></li>";
512:
513: echo "<li><a href='$grading_url'>".__("Manage Grading", 'woothemes-sensei')."</a></li></ul>";
514:
515:
516:
517: }
518:
519: 520: 521: 522: 523: 524: 525:
526: public function add_column_headings ( $defaults ) {
527: $new_columns['cb'] = '<input type="checkbox" />';
528:
529: $new_columns['title'] = _x( 'Course Title', 'column name', 'woothemes-sensei' );
530: $new_columns['course-prerequisite'] = _x( 'Pre-requisite Course', 'column name', 'woothemes-sensei' );
531: if ( Sensei_WC::is_woocommerce_active() ) {
532: $new_columns['course-woocommerce-product'] = _x( 'WooCommerce Product', 'column name', 'woothemes-sensei' );
533: }
534: $new_columns['course-category'] = _x( 'Category', 'column name', 'woothemes-sensei' );
535: if ( isset( $defaults['date'] ) ) {
536: $new_columns['date'] = $defaults['date'];
537: }
538:
539: return $new_columns;
540: }
541:
542: 543: 544: 545: 546: 547: 548: 549:
550: public function add_column_data ( $column_name, $id ) {
551: global $wpdb, $post;
552:
553: switch ( $column_name ) {
554: case 'id':
555: echo $id;
556: break;
557:
558: case 'course-prerequisite':
559: $course_prerequisite_id = get_post_meta( $id, '_course_prerequisite', true);
560: if ( 0 < absint( $course_prerequisite_id ) ) { echo '<a href="' . esc_url( get_edit_post_link( absint( $course_prerequisite_id ) ) ) . '" title="' . esc_attr( sprintf( __( 'Edit %s', 'woothemes-sensei' ), get_the_title( absint( $course_prerequisite_id ) ) ) ) . '">' . get_the_title( absint( $course_prerequisite_id ) ) . '</a>'; }
561:
562: break;
563:
564: case 'course-woocommerce-product':
565: if ( Sensei_WC::is_woocommerce_active() ) {
566: $course_woocommerce_product_id = get_post_meta( $id, '_course_woocommerce_product', true);
567: if ( 0 < absint( $course_woocommerce_product_id ) ) {
568: if ( 'product_variation' == get_post_type( $course_woocommerce_product_id ) ) {
569: $product_object = get_product( $course_woocommerce_product_id );
570: if( sensei_check_woocommerce_version( '2.1' ) ) {
571: $formatted_variation = wc_get_formatted_variation( $product_object->variation_data, true );
572: } else {
573: $formatted_variation = woocommerce_get_formatted_variation( $product_object->variation_data, true );
574: }
575: $course_woocommerce_product_id = $product_object->parent->post->ID;
576: $product_name = $product_object->parent->post->post_title . '<br/> ' . ucwords( $formatted_variation );
577: } else {
578: $product_name = get_the_title( absint( $course_woocommerce_product_id ) );
579: }
580: echo '<a href="' . esc_url( get_edit_post_link( absint( $course_woocommerce_product_id ) ) ) . '" title="' . esc_attr( sprintf( __( 'Edit %s', 'woothemes-sensei' ), $product_name ) ) . '">' . $product_name . '</a>';
581: }
582: }
583: break;
584:
585: case 'course-category':
586: $output = get_the_term_list( $id, 'course-category', '', ', ', '' );
587: if ( '' == $output ) {
588: $output = __( 'None', 'woothemes-sensei' );
589: }
590: echo $output;
591: break;
592:
593: default:
594: break;
595: }
596: }
597:
598:
599: 600: 601: 602: 603: 604: 605: 606: 607:
608: public function course_query( $amount = 0, $type = 'default', $includes = array(), $excludes = array() ) {
609: global $my_courses_page ;
610:
611: $results_array = array();
612:
613: if( $my_courses_page ) { add_action( 'pre_get_posts', array( $this, 'filter_my_courses' ) ); }
614:
615: $post_args = $this->get_archive_query_args( $type, $amount, $includes, $excludes );
616:
617:
618: if( empty( $post_args ) ) {
619:
620: return $results_array;
621:
622: }else{
623:
624:
625: $post_args['paged'] = 1;
626: $results_array = get_posts( $post_args );
627:
628: }
629:
630: if( $my_courses_page ) { remove_action( 'pre_get_posts', array( $this, 'filter_my_courses' ) ); }
631:
632: return $results_array;
633:
634: }
635:
636:
637: 638: 639: 640: 641: 642: 643: 644: 645:
646: public function get_archive_query_args( $type = '', $amount = 0 , $includes = array(), $excludes = array() ) {
647:
648: global $wp_query;
649:
650: if ( 0 == $amount && ( isset( Sensei()->settings->settings[ 'course_archive_amount' ] ) && 'usercourses' != $type && ( 0 < absint( Sensei()->settings->settings[ 'course_archive_amount' ] ) ) ) ) {
651: $amount = absint( Sensei()->settings->settings[ 'course_archive_amount' ] );
652: } else {
653: if ( 0 == $amount) {
654: $amount = $wp_query->get( 'posts_per_page' );
655: }
656: }
657:
658: $stored_order = get_option( 'sensei_course_order', '' );
659: $order = 'ASC';
660: $orderby = 'menu_order';
661: if( empty( $stored_order ) ){
662:
663: $order = 'DESC';
664: $orderby = 'date';
665:
666: }
667:
668: switch ($type) {
669:
670: case 'usercourses':
671: $post_args = array( 'post_type' => 'course',
672: 'orderby' => $orderby,
673: 'order' => $order,
674: 'post_status' => 'publish',
675: 'include' => $includes,
676: 'exclude' => $excludes,
677: 'suppress_filters' => 0
678: );
679: break;
680: case 'freecourses':
681:
682: $post_args = array(
683: 'post_type' => 'course',
684: 'orderby' => $orderby,
685: 'order' => $order,
686: 'post_status' => 'publish',
687: 'exclude' => $excludes,
688: 'suppress_filters' => 0
689: );
690:
691: $post_args['meta_query'] = Sensei_WC::get_free_courses_meta_query_args();
692:
693: break;
694:
695: case 'paidcourses':
696:
697: $post_args = array(
698: 'post_type' => 'course',
699: 'orderby' => $orderby,
700: 'order' => $order,
701: 'post_status' => 'publish',
702: 'exclude' => $excludes,
703: 'suppress_filters' => 0
704: );
705:
706:
707: $post_args['meta_query'] = Sensei_WC::get_paid_courses_meta_query_args();
708:
709: break;
710:
711: case 'featuredcourses':
712: $post_args = array( 'post_type' => 'course',
713: 'orderby' => $orderby,
714: 'order' => $order,
715: 'post_status' => 'publish',
716: 'meta_value' => 'featured',
717: 'meta_key' => '_course_featured',
718: 'meta_compare' => '=',
719: 'exclude' => $excludes,
720: 'suppress_filters' => 0
721: );
722: break;
723: default:
724: $post_args = array( 'post_type' => 'course',
725: 'orderby' => $orderby,
726: 'order' => $order,
727: 'post_status' => 'publish',
728: 'exclude' => $excludes,
729: 'suppress_filters' => 0
730: );
731: break;
732:
733: }
734:
735: $post_args['posts_per_page'] = $amount;
736: $paged = $wp_query->get( 'paged' );
737: $post_args['paged'] = empty( $paged) ? 1 : $paged;
738:
739: if( 'newcourses' == $type ){
740:
741: $post_args[ 'orderby' ] = 'date';
742: $post_args[ 'order' ] = 'DESC';
743: }
744:
745: return $post_args;
746: }
747:
748:
749: 750: 751: 752: 753: 754: 755: 756: 757: 758: 759: 760: 761: 762: 763:
764: public function course_image( $course_id = 0, $width = '100', $height = '100', $return = false ) {
765:
766: if ( is_a( $course_id, 'WP_Post' ) ) {
767:
768: $course_id = $course_id->ID;
769:
770: }
771:
772: if ( 'course' !== get_post_type( $course_id ) ){
773:
774: return;
775:
776: }
777:
778: $html = '';
779:
780:
781: if ( ( $width == '100' ) && ( $height == '100' ) ) {
782:
783: if ( is_singular( 'course' ) ) {
784:
785: if ( !Sensei()->settings->settings[ 'course_single_image_enable' ] ) {
786: return '';
787: }
788: $image_thumb_size = 'course_single_image';
789: $dimensions = Sensei()->get_image_size( $image_thumb_size );
790: $width = $dimensions['width'];
791: $height = $dimensions['height'];
792:
793: } else {
794:
795: if ( !Sensei()->settings->settings[ 'course_archive_image_enable' ] ) {
796: return '';
797: }
798:
799: $image_thumb_size = 'course_archive_image';
800: $dimensions = Sensei()->get_image_size( $image_thumb_size );
801: $width = $dimensions['width'];
802: $height = $dimensions['height'];
803:
804: }
805:
806: }
807:
808: $img_url = '';
809: if ( has_post_thumbnail( $course_id ) ) {
810:
811: $img_url = get_the_post_thumbnail( $course_id, array( $width, $height ), array( 'class' => 'woo-image thumbnail alignleft') );
812: } else {
813:
814:
815: $course_lessons = $this->course_lessons( $course_id );
816:
817: foreach ($course_lessons as $lesson_item){
818: if ( has_post_thumbnail( $lesson_item->ID ) ) {
819:
820: $img_url = get_the_post_thumbnail( $lesson_item->ID, array( $width, $height ), array( 'class' => 'woo-image thumbnail alignleft') );
821: if ( '' != $img_url ) {
822: break;
823: }
824:
825: }
826: }
827:
828: if ( '' == $img_url ) {
829:
830:
831: if ( Sensei()->settings->get( 'placeholder_images_enable' ) ) {
832:
833: $img_url = apply_filters( 'sensei_course_placeholder_image_url', '<img src="http://placehold.it/' . $width . 'x' . $height . '" class="woo-image thumbnail alignleft" />' );
834:
835: }
836:
837: }
838:
839: }
840:
841: if ( '' != $img_url ) {
842:
843: $html .= '<a href="' . get_permalink( $course_id ) . '" title="' . esc_attr( get_post_field( 'post_title', $course_id ) ) . '">' . $img_url .'</a>';
844:
845: }
846:
847: if( $return ){
848:
849: return $html;
850:
851: }else{
852:
853: echo $html;
854:
855: }
856:
857: }
858:
859:
860: 861: 862: 863: 864: 865: 866: 867:
868: public function course_count( $post_status = 'publish' ) {
869:
870: $post_args = array( 'post_type' => 'course',
871: 'posts_per_page' => -1,
872:
873:
874: 'post_status' => $post_status,
875: 'suppress_filters' => 0,
876: 'fields' => 'ids',
877: );
878:
879:
880:
881: $courses_query = new WP_Query( apply_filters( 'sensei_course_count', $post_args ) );
882:
883:
884: return count( $courses_query->posts );
885: }
886:
887:
888: 889: 890: 891: 892: 893: 894: 895: 896:
897: public function course_lessons( $course_id = 0, $post_status = 'publish', $fields = 'all' ) {
898:
899: if( is_a( $course_id, 'WP_Post' ) ){
900: $course_id = $course_id->ID;
901: }
902:
903: $post_args = array( 'post_type' => 'lesson',
904: 'posts_per_page' => -1,
905: 'orderby' => 'date',
906: 'order' => 'ASC',
907: 'meta_query' => array(
908: array(
909: 'key' => '_lesson_course',
910: 'value' => intval( $course_id ),
911: ),
912: ),
913: 'post_status' => $post_status,
914: 'suppress_filters' => 0,
915: );
916: $query_results = new WP_Query( $post_args );
917: $lessons = $query_results->posts;
918:
919:
920:
921:
922:
923: if( count( $lessons) > 1 ){
924:
925: foreach( $lessons as $lesson ){
926:
927: $order = intval( get_post_meta( $lesson->ID, '_order_'. $course_id, true ) );
928:
929: $lesson->course_order = $order ? $order : 100000;
930: }
931:
932: uasort( $lessons, array( $this, '_short_course_lessons_callback' ) );
933: }
934:
935: 936: 937: 938: 939: 940: 941: 942:
943: $lessons = apply_filters( 'sensei_course_get_lessons', $lessons, $course_id );
944:
945:
946:
947:
948: if( 'ids' == $fields ) {
949: $lesson_objects = $lessons;
950: $lessons = array();
951:
952: foreach ($lesson_objects as $lesson) {
953: $lessons[] = $lesson->ID;
954: }
955: }
956:
957: return $lessons;
958:
959: }
960:
961: 962: 963: 964: 965: 966: 967: 968: 969:
970: protected function _short_course_lessons_callback( $lesson_1, $lesson_2 ){
971:
972: if ( $lesson_1->course_order == $lesson_2->course_order ) {
973: return 0;
974: }
975:
976: return ($lesson_1->course_order < $lesson_2->course_order) ? -1 : 1;
977: }
978:
979: 980: 981: 982: 983: 984: 985:
986: public function course_quizzes( $course_id = 0, $boolean_check = false ) {
987:
988:
989: $course_quizzes = array();
990:
991: if( $course_id ) {
992: $lesson_ids = Sensei()->course->course_lessons( $course_id, 'any', 'ids' );
993:
994: foreach( $lesson_ids as $lesson_id ) {
995: $has_questions = get_post_meta( $lesson_id, '_quiz_has_questions', true );
996: if ( $has_questions && $boolean_check ) {
997: return true;
998: }
999: elseif ( $has_questions ) {
1000: $quiz_id = Sensei()->lesson->lesson_quizzes( $lesson_id );
1001:
1002:
1003: $course_quizzes[] = $quiz_id;
1004:
1005: }
1006: }
1007: }
1008: if ( $boolean_check && empty($course_quizzes) ) {
1009: $course_quizzes = false;
1010: }
1011: return $course_quizzes;
1012: }
1013:
1014:
1015: 1016: 1017: 1018: 1019: 1020: 1021: 1022:
1023: public function course_lessons_completed( $course_id = 0, $post_status = 'publish' ) {
1024:
1025: return $this->course_lessons( $course_id, $post_status );
1026:
1027: }
1028:
1029:
1030: 1031: 1032: 1033: 1034: 1035: 1036: 1037:
1038: public function course_author_lesson_count( $author_id = 0, $course_id = 0 ) {
1039:
1040: $lesson_args = array( 'post_type' => 'lesson',
1041: 'posts_per_page' => -1,
1042: 'author' => $author_id,
1043: 'meta_key' => '_lesson_course',
1044: 'meta_value' => $course_id,
1045: 'post_status' => 'publish',
1046: 'suppress_filters' => 0,
1047: 'fields' => 'ids',
1048: );
1049: $lessons_array = get_posts( $lesson_args );
1050: $count = count( $lessons_array );
1051: return $count;
1052:
1053: }
1054:
1055: 1056: 1057: 1058: 1059: 1060: 1061:
1062: public function course_lesson_count( $course_id = 0 ) {
1063:
1064: $lesson_args = array( 'post_type' => 'lesson',
1065: 'posts_per_page' => -1,
1066: 'meta_key' => '_lesson_course',
1067: 'meta_value' => $course_id,
1068: 'post_status' => 'publish',
1069: 'suppress_filters' => 0,
1070: 'fields' => 'ids',
1071: );
1072: $lessons_array = get_posts( $lesson_args );
1073:
1074: $count = count( $lessons_array );
1075:
1076: return $count;
1077:
1078: }
1079:
1080: 1081: 1082: 1083: 1084: 1085: 1086:
1087: public function course_lesson_preview_count( $course_id = 0 ) {
1088:
1089: $lesson_args = array( 'post_type' => 'lesson',
1090: 'posts_per_page' => -1,
1091: 'post_status' => 'publish',
1092: 'suppress_filters' => 0,
1093: 'meta_query' => array(
1094: array(
1095: 'key' => '_lesson_course',
1096: 'value' => $course_id
1097: ),
1098: array(
1099: 'key' => '_lesson_preview',
1100: 'value' => 'preview'
1101: )
1102: ),
1103: 'fields' => 'ids',
1104: );
1105: $lessons_array = get_posts( $lesson_args );
1106:
1107: $count = count( $lessons_array );
1108:
1109: return $count;
1110:
1111: }
1112:
1113: 1114: 1115: 1116: 1117: 1118: 1119:
1120: public function get_product_courses( $product_id = 0 ) {
1121:
1122: if ( ! Sensei_WC::is_woocommerce_active() || empty( $product_id ) ) {
1123: return array();
1124: }
1125:
1126:
1127: $product = wc_get_product( $product_id );
1128:
1129: if ( in_array( $product->get_type(), array( 'variable-subscription', 'variable' ) ) ) {
1130:
1131: $variations = $product->get_available_variations();
1132: $courses = array();
1133:
1134:
1135: $variation_parent_courses = get_posts( self::get_product_courses_query_args( $product_id ) );
1136:
1137: if ( ! empty( $variation_parent_courses ) ) {
1138: $courses = array_merge( $courses, $variation_parent_courses );
1139: }
1140:
1141: foreach ( $variations as $variation ) {
1142:
1143: $variation_courses = get_posts( self::get_product_courses_query_args( $variation['variation_id'] ) );
1144: $courses = array_merge( $courses, $variation_courses );
1145:
1146: }
1147:
1148: return $courses;
1149:
1150: } else {
1151:
1152: return get_posts( self::get_product_courses_query_args( $product->get_id() ) );
1153:
1154: }
1155:
1156: }
1157:
1158: 1159: 1160: 1161: 1162:
1163: public static function get_product_courses_query_args ( $product_id ) {
1164:
1165: return array( 'post_type' => 'course',
1166: 'posts_per_page' => -1,
1167: 'meta_key' => '_course_woocommerce_product',
1168: 'meta_value' => $product_id,
1169: 'post_status' => 'publish',
1170: 'suppress_filters' => 0,
1171: 'orderby' => 'menu_order date',
1172: 'order' => 'ASC',
1173: );
1174:
1175: }
1176:
1177: 1178: 1179: 1180: 1181:
1182: public function filter_my_courses( $query ) {
1183: global $my_courses_section;
1184:
1185: if ( isset( Sensei()->settings->settings[ 'my_course_amount' ] ) && ( 0 < absint( Sensei()->settings->settings[ 'my_course_amount' ] ) ) ) {
1186: $amount = absint( Sensei()->settings->settings[ 'my_course_amount' ] );
1187: $query->set( 'posts_per_page', $amount );
1188: }
1189:
1190: if( isset( $_GET[ $my_courses_section . '_page' ] ) && 0 < intval( $_GET[ $my_courses_section . '_page' ] ) ) {
1191: $page = intval( $_GET[ $my_courses_section . '_page' ] );
1192: $query->set( 'paged', $page );
1193: }
1194: }
1195:
1196: 1197: 1198: 1199: 1200: 1201: 1202: 1203: 1204: 1205:
1206: public function load_user_courses_content( $user = false ) {
1207: global $course, $my_courses_page, $my_courses_section;
1208:
1209: if( ! isset( Sensei()->settings->settings[ 'learner_profile_show_courses' ] )
1210: || ! Sensei()->settings->settings[ 'learner_profile_show_courses' ] ) {
1211:
1212:
1213: return;
1214:
1215: }
1216:
1217: $manage = ( $user->ID == get_current_user_id() ) ? true : false;
1218:
1219: do_action( 'sensei_before_learner_course_content', $user );
1220:
1221:
1222: $complete_html = $active_html = '';
1223:
1224: if( is_a( $user, 'WP_User' ) ) {
1225:
1226: $my_courses_page = true;
1227:
1228:
1229: do_action( 'sensei_before_my_courses', $user->ID );
1230:
1231:
1232: $per_page = 20;
1233: if ( isset( Sensei()->settings->settings[ 'my_course_amount' ] )
1234: && ( 0 < absint( Sensei()->settings->settings[ 'my_course_amount' ] ) ) ) {
1235:
1236: $per_page = absint( Sensei()->settings->settings[ 'my_course_amount' ] );
1237:
1238: }
1239:
1240: $course_statuses = Sensei_Utils::sensei_check_for_activity( array( 'user_id' => $user->ID, 'type' => 'sensei_course_status' ), true );
1241:
1242: if ( !is_array($course_statuses) ) {
1243: $course_statuses = array( $course_statuses );
1244: }
1245: $completed_ids = $active_ids = array();
1246: foreach( $course_statuses as $course_status ) {
1247: if ( Sensei_Utils::user_completed_course( $course_status, $user->ID ) ) {
1248: $completed_ids[] = $course_status->comment_post_ID;
1249: } else {
1250: $active_ids[] = $course_status->comment_post_ID;
1251: }
1252: }
1253:
1254: $active_count = $completed_count = 0;
1255:
1256: $active_courses = array();
1257: if ( 0 < intval( count( $active_ids ) ) ) {
1258: $my_courses_section = 'active';
1259: $active_courses = Sensei()->course->course_query( $per_page, 'usercourses', $active_ids );
1260: $active_count = count( $active_ids );
1261: }
1262:
1263: $completed_courses = array();
1264: if ( 0 < intval( count( $completed_ids ) ) ) {
1265: $my_courses_section = 'completed';
1266: $completed_courses = Sensei()->course->course_query( $per_page, 'usercourses', $completed_ids );
1267: $completed_count = count( $completed_ids );
1268: }
1269:
1270: foreach ( $active_courses as $course_item ) {
1271:
1272: $course_lessons = Sensei()->course->course_lessons( $course_item->ID );
1273: $lessons_completed = 0;
1274: foreach ( $course_lessons as $lesson ) {
1275: if ( Sensei_Utils::user_completed_lesson( $lesson->ID, $user->ID ) ) {
1276: ++$lessons_completed;
1277: }
1278: }
1279:
1280:
1281: $category_output = get_the_term_list( $course_item->ID, 'course-category', '', ', ', '' );
1282:
1283: $active_html .= '<article class="' . esc_attr( join( ' ', get_post_class( array( 'course', 'post' ), $course_item->ID ) ) ) . '">';
1284:
1285:
1286: $active_html .= Sensei()->course->course_image( absint( $course_item->ID ), '100','100', true );
1287:
1288:
1289: $active_html .= '<header>';
1290:
1291: $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>';
1292:
1293: $active_html .= '</header>';
1294:
1295: $active_html .= '<section class="entry">';
1296:
1297: $active_html .= '<p class="sensei-course-meta">';
1298:
1299:
1300: $user_info = get_userdata( absint( $course_item->post_author ) );
1301: if ( isset( Sensei()->settings->settings[ 'course_author' ] )
1302: && ( Sensei()->settings->settings[ 'course_author' ] ) ) {
1303:
1304: $active_html .= '<span class="course-author">'
1305: . __( 'by ', 'woothemes-sensei' )
1306: . '<a href="' . esc_url( get_author_posts_url( absint( $course_item->post_author ) ) )
1307: . '" title="' . esc_attr( $user_info->display_name ) . '">'
1308: . esc_html( $user_info->display_name )
1309: . '</a></span>';
1310:
1311: }
1312:
1313:
1314: $lesson_count = Sensei()->course->course_lesson_count( absint( $course_item->ID ) );
1315:
1316: if ( 0 == $lesson_count ) {
1317:
1318: $lesson_count = 1;
1319:
1320: }
1321: $active_html .= '<span class="course-lesson-count">' . $lesson_count . ' ' . __( 'Lessons', 'woothemes-sensei' ) . '</span>';
1322:
1323: if ( '' != $category_output ) {
1324:
1325: $active_html .= '<span class="course-category">' . sprintf( __( 'in %s', 'woothemes-sensei' ), $category_output ) . '</span>';
1326:
1327: }
1328: $active_html .= '<span class="course-lesson-progress">' . sprintf( __( '%1$d of %2$d lessons completed', 'woothemes-sensei' ) , $lessons_completed, $lesson_count ) . '</span>';
1329:
1330: $active_html .= '</p>';
1331:
1332: $active_html .= '<p class="course-excerpt">' . $course_item->post_excerpt . '</p>';
1333:
1334:
1335:
1336: $progress_percentage = abs( round( ( doubleval( $lessons_completed ) * 100 ) / ( $lesson_count ), 0 ) );
1337:
1338: $active_html .= $this->get_progress_meter( $progress_percentage );
1339:
1340: $active_html .= '</section>';
1341:
1342: if( is_user_logged_in() ) {
1343:
1344: $active_html .= '<section class="entry-actions">';
1345:
1346: $active_html .= '<form method="POST" action="' . esc_url( remove_query_arg( array( 'active_page', 'completed_page' ) ) ) . '">';
1347:
1348: $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' ) ) . '" />';
1349:
1350: $active_html .= '<input type="hidden" name="course_complete_id" id="course-complete-id" value="' . esc_attr( absint( $course_item->ID ) ) . '" />';
1351:
1352: if ( 0 < absint( count( $course_lessons ) )
1353: && Sensei()->settings->settings['course_completion'] == 'complete' ){
1354:
1355: $active_html .= '<span><input name="course_complete" type="submit" class="course-complete" value="'
1356: . __( 'Mark as Complete', 'woothemes-sensei' ) . '"/> </span>';
1357:
1358: }
1359:
1360: $course_purchased = false;
1361: if ( Sensei_WC::is_woocommerce_active() ) {
1362:
1363:
1364: $wc_post_id = get_post_meta( absint( $course_item->ID ), '_course_woocommerce_product', true );
1365: if ( 0 < $wc_post_id ) {
1366:
1367: $course_purchased = Sensei_WC::has_customer_bought_product( $user->ID, $wc_post_id );
1368:
1369: }
1370:
1371: }
1372:
1373: 1374: 1375:
1376: $show_delete_course_button = apply_filters( 'sensei_show_delete_course_button', false );
1377:
1378: if ( false == $course_purchased && $show_delete_course_button ) {
1379:
1380: $active_html .= '<span><input name="course_complete" type="submit" class="course-delete" value="'
1381: . __( 'Delete Course', 'woothemes-sensei' ) . '"/></span>';
1382:
1383: }
1384:
1385: $active_html .= '</form>';
1386:
1387: $active_html .= '</section>';
1388: }
1389:
1390: $active_html .= '</article>';
1391: }
1392:
1393:
1394: if( $active_count > $per_page ) {
1395:
1396: $current_page = 1;
1397: if( isset( $_GET['active_page'] ) && 0 < intval( $_GET['active_page'] ) ) {
1398: $current_page = $_GET['active_page'];
1399: }
1400:
1401: $active_html .= '<nav class="pagination woo-pagination">';
1402: $total_pages = ceil( $active_count / $per_page );
1403:
1404: if( $current_page > 1 ) {
1405: $prev_link = add_query_arg( 'active_page', $current_page - 1 );
1406: $active_html .= '<a class="prev page-numbers" href="' . esc_url( $prev_link ) . '">' . __( 'Previous' , 'woothemes-sensei' ) . '</a> ';
1407: }
1408:
1409: for ( $i = 1; $i <= $total_pages; $i++ ) {
1410: $link = add_query_arg( 'active_page', $i );
1411:
1412: if( $i == $current_page ) {
1413: $active_html .= '<span class="page-numbers current">' . $i . '</span> ';
1414: } else {
1415: $active_html .= '<a class="page-numbers" href="' . esc_url( $link ). '">' . $i . '</a> ';
1416: }
1417: }
1418:
1419: if( $current_page < $total_pages ) {
1420: $next_link = add_query_arg( 'active_page', $current_page + 1 );
1421: $active_html .= '<a class="next page-numbers" href="' . esc_url( $next_link ) . '">' . __( 'Next' , 'woothemes-sensei' ) . '</a> ';
1422: }
1423:
1424: $active_html .= '</nav>';
1425: }
1426:
1427: foreach ( $completed_courses as $course_item ) {
1428: $course = $course_item;
1429:
1430:
1431: $category_output = get_the_term_list( $course_item->ID, 'course-category', '', ', ', '' );
1432:
1433: $complete_html .= '<article class="' . join( ' ', get_post_class( array( 'course', 'post' ), $course_item->ID ) ) . '">';
1434:
1435:
1436: $complete_html .= Sensei()->course->course_image( absint( $course_item->ID ),100, 100, true );
1437:
1438:
1439: $complete_html .= '<header>';
1440:
1441: $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>';
1442:
1443: $complete_html .= '</header>';
1444:
1445: $complete_html .= '<section class="entry">';
1446:
1447: $complete_html .= '<p class="sensei-course-meta">';
1448:
1449:
1450: $user_info = get_userdata( absint( $course_item->post_author ) );
1451: if ( isset( Sensei()->settings->settings[ 'course_author' ] ) && ( Sensei()->settings->settings[ 'course_author' ] ) ) {
1452: $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>';
1453: }
1454:
1455:
1456: $complete_html .= '<span class="course-lesson-count">'
1457: . Sensei()->course->course_lesson_count( absint( $course_item->ID ) )
1458: . ' ' . __( 'Lessons', 'woothemes-sensei' )
1459: . '</span>';
1460:
1461:
1462: if ( '' != $category_output ) {
1463:
1464: $complete_html .= '<span class="course-category">' . sprintf( __( 'in %s', 'woothemes-sensei' ), $category_output ) . '</span>';
1465:
1466: }
1467:
1468: $complete_html .= '</p>';
1469:
1470: $complete_html .= '<p class="course-excerpt">' . $course_item->post_excerpt . '</p>';
1471:
1472: $complete_html .= $this->get_progress_meter( 100 );
1473:
1474: if( $manage ) {
1475: $has_quizzes = Sensei()->course->course_quizzes( $course_item->ID, true );
1476:
1477: if ( has_filter( 'sensei_results_links' ) || $has_quizzes ) {
1478:
1479:
1480: $complete_html .= '<p class="sensei-results-links">';
1481: $results_link = '';
1482: if( $has_quizzes ) {
1483:
1484: $results_link = '<a class="button view-results" href="'
1485: . Sensei()->course_results->get_permalink( $course_item->ID )
1486: . '">' . __( 'View results', 'woothemes-sensei' )
1487: . '</a>';
1488: }
1489: 1490: 1491:
1492: $complete_html .= apply_filters( 'sensei_results_links', $results_link, $course_item->ID );
1493: $complete_html .= '</p>';
1494:
1495: }
1496: }
1497:
1498: $complete_html .= '</section>';
1499:
1500: $complete_html .= '</article>';
1501: }
1502:
1503:
1504: if( $completed_count > $per_page ) {
1505:
1506: $current_page = 1;
1507: if( isset( $_GET['completed_page'] ) && 0 < intval( $_GET['completed_page'] ) ) {
1508: $current_page = $_GET['completed_page'];
1509: }
1510:
1511: $complete_html .= '<nav class="pagination woo-pagination">';
1512: $total_pages = ceil( $completed_count / $per_page );
1513:
1514:
1515: if( $current_page > 1 ) {
1516: $prev_link = add_query_arg( 'completed_page', $current_page - 1 );
1517: $complete_html .= '<a class="prev page-numbers" href="' . esc_url( $prev_link ) . '">' . __( 'Previous' , 'woothemes-sensei' ) . '</a> ';
1518: }
1519:
1520: for ( $i = 1; $i <= $total_pages; $i++ ) {
1521: $link = add_query_arg( 'completed_page', $i );
1522:
1523: if( $i == $current_page ) {
1524: $complete_html .= '<span class="page-numbers current">' . $i . '</span> ';
1525: } else {
1526: $complete_html .= '<a class="page-numbers" href="' . esc_url( $link ) . '">' . $i . '</a> ';
1527: }
1528: }
1529:
1530: if( $current_page < $total_pages ) {
1531: $next_link = add_query_arg( 'completed_page', $current_page + 1 );
1532: $complete_html .= '<a class="next page-numbers" href="' . esc_url( $next_link ) . '">' . __( 'Next' , 'woothemes-sensei' ) . '</a> ';
1533: }
1534:
1535: $complete_html .= '</nav>';
1536: }
1537:
1538: }
1539:
1540: if( $manage ) {
1541: $no_active_message = __( 'You have no active courses.', 'woothemes-sensei' );
1542: $no_complete_message = __( 'You have not completed any courses yet.', 'woothemes-sensei' );
1543: } else {
1544: $no_active_message = __( 'This learner has no active courses.', 'woothemes-sensei' );
1545: $no_complete_message = __( 'This learner has not completed any courses yet.', 'woothemes-sensei' );
1546: }
1547:
1548: ob_start();
1549: ?>
1550:
1551: <?php do_action( 'sensei_before_user_courses' ); ?>
1552:
1553: <?php
1554: if( $manage && ( ! isset( Sensei()->settings->settings['messages_disable'] ) || ! Sensei()->settings->settings['messages_disable'] ) ) {
1555: ?>
1556: <p class="my-messages-link-container">
1557: <a class="my-messages-link" href="<?php echo get_post_type_archive_link( 'sensei_message' ); ?>"
1558: title="<?php _e( 'View & reply to private messages sent to your course & lesson teachers.', 'woothemes-sensei' ); ?>">
1559: <?php _e( 'My Messages', 'woothemes-sensei' ); ?>
1560: </a>
1561: </p>
1562: <?php
1563: }
1564: ?>
1565: <div id="my-courses">
1566:
1567: <ul>
1568: <li><a href="#active-courses"><?php _e( 'Active Courses', 'woothemes-sensei' ); ?></a></li>
1569: <li><a href="#completed-courses"><?php _e( 'Completed Courses', 'woothemes-sensei' ); ?></a></li>
1570: </ul>
1571:
1572: <?php do_action( 'sensei_before_active_user_courses' ); ?>
1573:
1574: <?php
1575: $course_page_url = Sensei_Course::get_courses_page_url();
1576: ?>
1577:
1578: <div id="active-courses">
1579:
1580: <?php if ( '' != $active_html ) {
1581:
1582: echo $active_html;
1583:
1584: } else { ?>
1585:
1586: <div class="sensei-message info">
1587:
1588: <?php echo $no_active_message; ?>
1589:
1590: <a href="<?php echo $course_page_url; ?>">
1591:
1592: <?php _e( 'Start a Course!', 'woothemes-sensei' ); ?>
1593:
1594: </a>
1595:
1596: </div>
1597:
1598: <?php }
1599:
1600: </div>
1601:
1602: <?php do_action( 'sensei_after_active_user_courses' ); ?>
1603:
1604: <?php do_action( 'sensei_before_completed_user_courses' ); ?>
1605:
1606: <div id="completed-courses">
1607:
1608: <?php if ( '' != $complete_html ) {
1609:
1610: echo $complete_html;
1611:
1612: } else { ?>
1613:
1614: <div class="sensei-message info">
1615:
1616: <?php echo $no_complete_message; ?>
1617:
1618: </div>
1619:
1620: <?php }
1621:
1622: </div>
1623:
1624: <?php do_action( 'sensei_after_completed_user_courses' ); ?>
1625:
1626: </div>
1627:
1628: <?php do_action( 'sensei_after_user_courses' ); ?>
1629:
1630: <?php
1631: echo ob_get_clean();
1632:
1633: do_action( 'sensei_after_learner_course_content', $user );
1634:
1635: }
1636:
1637: 1638: 1639: 1640: 1641: 1642: 1643: 1644:
1645: public static function get_all_courses(){
1646:
1647: $args = array(
1648: 'post_type' => 'course',
1649: 'posts_per_page' => -1,
1650: 'orderby' => 'title',
1651: 'order' => 'ASC',
1652: 'post_status' => 'any',
1653: 'suppress_filters' => 0,
1654: );
1655:
1656: $wp_query_obj = new WP_Query( $args );
1657:
1658: 1659: 1660: 1661: 1662: 1663: 1664: 1665: 1666: 1667:
1668: return apply_filters( 'sensei_get_all_courses' , $wp_query_obj->posts );
1669:
1670: }
1671:
1672: 1673: 1674: 1675: 1676: 1677: 1678:
1679: public function get_progress_meter( $progress_percentage ){
1680:
1681: if ( 50 < $progress_percentage ) {
1682: $class = ' green';
1683: } elseif ( 25 <= $progress_percentage && 50 >= $progress_percentage ) {
1684: $class = ' orange';
1685: } else {
1686: $class = ' red';
1687: }
1688: $progress_bar_html = '<div class="meter' . esc_attr( $class ) . '"><span style="width: ' . $progress_percentage . '%">' . round( $progress_percentage ) . '%</span></div>';
1689:
1690: return $progress_bar_html;
1691:
1692: }
1693:
1694: 1695: 1696: 1697: 1698: 1699: 1700: 1701: 1702:
1703: public function get_progress_statement( $course_id, $user_id ){
1704:
1705: if( empty( $course_id ) || empty( $user_id )
1706: || ! Sensei_Utils::user_started_course( $course_id, $user_id ) ){
1707: return '';
1708: }
1709:
1710: $completed = count( $this->get_completed_lesson_ids( $course_id, $user_id ) );
1711: $total_lessons = count( $this->course_lessons( $course_id ) );
1712:
1713: $statement = sprintf( _n('Currently completed %s lesson of %s in total', 'Currently completed %s lessons of %s in total', $completed, 'woothemes-sensei'), $completed, $total_lessons );
1714:
1715: 1716: 1717: 1718: 1719: 1720:
1721: return apply_filters( 'sensei_course_completion_statement', $statement );
1722:
1723: }
1724:
1725: 1726: 1727: 1728: 1729: 1730:
1731: public function the_progress_statement( $course_id = 0, $user_id = 0 ){
1732: if( empty( $course_id ) ){
1733: global $post;
1734: $course_id = $post->ID;
1735: }
1736:
1737: if( empty( $user_id ) ){
1738: $user_id = get_current_user_id();
1739: }
1740:
1741: $progress_statement = $this->get_progress_statement( $course_id, $user_id );
1742: if( ! empty( $progress_statement ) ){
1743:
1744: echo '<span class="progress statement course-completion-rate">' . $progress_statement . '</span>';
1745:
1746: }
1747:
1748: }
1749:
1750: 1751: 1752: 1753: 1754: 1755:
1756: public function the_progress_meter( $course_id = 0, $user_id = 0 ){
1757:
1758: if( empty( $course_id ) ){
1759: global $post;
1760: $course_id = $post->ID;
1761: }
1762:
1763: if( empty( $user_id ) ){
1764: $user_id = get_current_user_id();
1765: }
1766:
1767: if( 'course' != get_post_type( $course_id ) || ! get_userdata( $user_id )
1768: || ! Sensei_Utils::user_started_course( $course_id ,$user_id ) ){
1769: return;
1770: }
1771: $percentage_completed = $this->get_completion_percentage( $course_id, $user_id );
1772:
1773: echo $this->get_progress_meter( $percentage_completed );
1774:
1775: }
1776:
1777: 1778: 1779: 1780: 1781: 1782: 1783: 1784: 1785:
1786: public function get_completed_lesson_ids( $course_id, $user_id = 0 ){
1787:
1788: if( !( intval( $user_id ) ) > 0 ){
1789: $user_id = get_current_user_id();
1790: }
1791:
1792: $completed_lesson_ids = array();
1793:
1794: $course_lessons = $this->course_lessons( $course_id );
1795:
1796: foreach( $course_lessons as $lesson ){
1797:
1798: $is_lesson_completed = Sensei_Utils::user_completed_lesson( $lesson->ID, $user_id );
1799: if( $is_lesson_completed ){
1800: $completed_lesson_ids[] = $lesson->ID;
1801: }
1802:
1803: }
1804:
1805: return $completed_lesson_ids;
1806:
1807: }
1808:
1809: 1810: 1811: 1812: 1813: 1814: 1815: 1816: 1817:
1818: public function get_completion_percentage( $course_id, $user_id = 0 ){
1819:
1820: if( !( intval( $user_id ) ) > 0 ){
1821: $user_id = get_current_user_id();
1822: }
1823:
1824: $completed = count( $this->get_completed_lesson_ids( $course_id, $user_id ) );
1825:
1826: if( ! ( $completed > 0 ) ){
1827: return 0;
1828: }
1829:
1830: $total_lessons = count( $this->course_lessons( $course_id ) );
1831: $percentage = $completed / $total_lessons * 100;
1832:
1833: 1834: 1835: 1836: 1837: 1838: 1839: 1840: 1841:
1842: return apply_filters( 'sensei_course_completion_percentage', $percentage, $course_id, $user_id );
1843:
1844: }
1845:
1846: 1847: 1848: 1849: 1850: 1851: 1852: 1853:
1854: public function block_notification_emails( $should_send ){
1855: global $sensei_email_data;
1856: $email = $sensei_email_data;
1857:
1858: $course_id = '';
1859:
1860: if( isset( $email['course_id'] ) ){
1861:
1862: $course_id = $email['course_id'];
1863:
1864: }elseif( isset( $email['lesson_id'] ) ){
1865:
1866: $course_id = Sensei()->lesson->get_course_id( $email['lesson_id'] );
1867:
1868: }elseif( isset( $email['quiz_id'] ) ){
1869:
1870: $lesson_id = Sensei()->quiz->get_lesson_id( $email['quiz_id'] );
1871: $course_id = Sensei()->lesson->get_course_id( $lesson_id );
1872:
1873: }
1874:
1875: if( !empty( $course_id ) && 'course'== get_post_type( $course_id ) ) {
1876:
1877: $course_emails_disabled = get_post_meta($course_id, 'disable_notification', true);
1878:
1879: if ($course_emails_disabled) {
1880:
1881: return false;
1882:
1883: }
1884:
1885: }
1886:
1887: return $should_send;
1888: }
1889:
1890: 1891: 1892: 1893: 1894: 1895:
1896: public function course_notification_meta_box_content( $course ){
1897:
1898: $checked = get_post_meta( $course->ID , 'disable_notification', true );
1899:
1900:
1901: $checked_html = '';
1902: if( $checked ){
1903: $checked_html = 'checked="checked"';
1904: }
1905: wp_nonce_field( 'update-course-notification-setting','_sensei_course_notification' );
1906:
1907: echo '<input id="disable_sensei_course_notification" '.$checked_html .' type="checkbox" name="disable_sensei_course_notification" >';
1908: echo '<label for="disable_sensei_course_notification">'.__('Disable notifications on this course ?', 'woothemes-sensei'). '</label>';
1909:
1910: }
1911:
1912: 1913: 1914: 1915: 1916: 1917: 1918: 1919:
1920: public function save_course_notification_meta_box( $course_id ){
1921:
1922: if( !isset( $_POST['_sensei_course_notification'] )
1923: || ! wp_verify_nonce( $_POST['_sensei_course_notification'], 'update-course-notification-setting' ) ){
1924: return;
1925: }
1926:
1927: if( isset( $_POST['disable_sensei_course_notification'] ) && 'on'== $_POST['disable_sensei_course_notification'] ) {
1928: $new_val = true;
1929: }else{
1930: $new_val = false;
1931: }
1932:
1933: update_post_meta( $course_id , 'disable_notification', $new_val );
1934:
1935: }
1936:
1937: 1938: 1939: 1940: 1941: 1942: 1943: 1944: 1945: 1946:
1947: public function content_before_backwards_compatibility_hooks( $post_id ){
1948:
1949: sensei_do_deprecated_action( 'sensei_course_image','1.9.0','sensei_course_content_inside_before' );
1950: sensei_do_deprecated_action( 'sensei_course_archive_course_title','1.9.0','sensei_course_content_inside_before' );
1951:
1952: }
1953:
1954: 1955: 1956: 1957: 1958: 1959: 1960: 1961: 1962:
1963: public function loop_before_backwards_compatibility_hooks( ){
1964:
1965: global $post;
1966: sensei_do_deprecated_action( 'sensei_course_archive_header','1.9.0','sensei_course_content_inside_before', $post->post_type );
1967:
1968: }
1969:
1970: 1971: 1972: 1973: 1974: 1975: 1976: 1977: 1978:
1979: public function the_course_free_lesson_preview( $course_id ){
1980:
1981: $course = get_post( $course_id );
1982: $preview_lesson_count = intval( Sensei()->course->course_lesson_preview_count( $course->ID ) );
1983: $is_user_taking_course = Sensei_Utils::user_started_course( $course->ID, get_current_user_id() );
1984:
1985: if ( 0 < $preview_lesson_count && !$is_user_taking_course ) {
1986: ?>
1987: <p class="sensei-free-lessons">
1988: <a href="<?php echo get_permalink(); ?>">
1989: <?php _e( 'Preview this course', 'woothemes-sensei' ) ?>
1990: </a>
1991: - <?php echo sprintf( __( '(%d preview lessons)', 'woothemes-sensei' ), $preview_lesson_count ) ; ?>
1992: </p>
1993:
1994: <?php
1995: }
1996: }
1997:
1998: 1999: 2000: 2001: 2002: 2003:
2004: public function the_course_meta( $course_id ){
2005: echo '<p class="sensei-course-meta">';
2006:
2007: $course = get_post( $course_id );
2008: $category_output = get_the_term_list( $course->ID, 'course-category', '', ', ', '' );
2009: $author_display_name = get_the_author_meta( 'display_name', $course->post_author );
2010:
2011: if ( isset( Sensei()->settings->settings[ 'course_author' ] ) && ( Sensei()->settings->settings[ 'course_author' ] ) ) {?>
2012:
2013: <span class="course-author"><?php _e( 'by ', 'woothemes-sensei' ); ?>
2014:
2015: <a href="<?php esc_attr_e( get_author_posts_url( $course->post_author ) ); ?>" title="<?php esc_attr_e( $author_display_name ); ?>"><?php esc_attr_e( $author_display_name ); ?></a>
2016:
2017: </span>
2018:
2019: <?php }
2020:
2021: <span class="course-lesson-count"><?php echo Sensei()->course->course_lesson_count( $course->ID ) . ' ' . __( 'Lessons', 'woothemes-sensei' ); ?></span>
2022:
2023: <?php if ( '' != $category_output ) { ?>
2024:
2025: <span class="course-category"><?php echo sprintf( __( 'in %s', 'woothemes-sensei' ), $category_output ); ?></span>
2026:
2027: <?php }
2028:
2029:
2030: if( Sensei_Utils::user_started_course( $course->ID, get_current_user_id() )
2031: || Sensei_Utils::user_completed_course( $course->ID, get_current_user_id() ) ){
2032:
2033: $completed = count( $this->get_completed_lesson_ids( $course->ID, get_current_user_id() ) );
2034: $lesson_count = count( $this->course_lessons( $course->ID ) );
2035: echo '<span class="course-lesson-progress">' . sprintf( __( '%1$d of %2$d lessons completed', 'woothemes-sensei' ) , $completed, $lesson_count ) . '</span>';
2036:
2037: }
2038:
2039: sensei_simple_course_price( $course->ID );
2040:
2041: echo '</p>';
2042: }
2043:
2044: 2045: 2046: 2047: 2048: 2049: 2050: 2051: 2052: 2053:
2054: public static function add_course_user_status_class( $classes, $class, $course_id ){
2055:
2056: if( 'course' == get_post_type( $course_id ) && is_user_logged_in() ){
2057:
2058: if( Sensei_Utils::user_completed_course( $course_id, get_current_user_id() ) ){
2059:
2060: $classes[] = 'user-status-completed';
2061:
2062: }else{
2063:
2064: $classes[] = 'user-status-active';
2065:
2066: }
2067:
2068: }
2069:
2070: return $classes;
2071:
2072: }
2073:
2074: 2075: 2076: 2077: 2078: 2079: 2080: 2081:
2082: public static function the_course_action_buttons( $course ){
2083:
2084: if( is_user_logged_in() ) { ?>
2085:
2086: <section class="entry-actions">
2087: <form method="POST" action="<?php echo esc_url( remove_query_arg( array( 'active_page', 'completed_page' ) ) ); ?>">
2088:
2089: <input type="hidden"
2090: name="<?php esc_attr_e( 'woothemes_sensei_complete_course_noonce' ) ?>"
2091: id="<?php esc_attr_e( 'woothemes_sensei_complete_course_noonce' ); ?>"
2092: value="<?php esc_attr_e( wp_create_nonce( 'woothemes_sensei_complete_course_noonce' ) ); ?>"
2093: />
2094:
2095: <input type="hidden" name="course_complete_id" id="course-complete-id" value="<?php esc_attr_e( intval( $course->ID ) ); ?>" />
2096:
2097: <?php if ( 0 < absint( count( Sensei()->course->course_lessons( $course->ID ) ) )
2098: && Sensei()->settings->settings['course_completion'] == 'complete'
2099: && ! Sensei_Utils::user_completed_course( $course, get_current_user_id() )) { ?>
2100:
2101: <span><input name="course_complete" type="submit" class="course-complete" value="<?php _e( 'Mark as Complete', 'woothemes-sensei' ); ?>" /></span>
2102:
2103: <?php }
2104:
2105: $course_purchased = false;
2106: if ( Sensei_WC::is_woocommerce_active() ) {
2107:
2108: $wc_post_id = get_post_meta( intval( $course->ID ), '_course_woocommerce_product', true );
2109: if ( 0 < $wc_post_id ) {
2110:
2111: $user = wp_get_current_user();
2112: $course_purchased = Sensei_Utils::sensei_customer_bought_product( $user->user_email, $user->ID, $wc_post_id );
2113:
2114: }
2115: }
2116:
2117: 2118: 2119: 2120: 2121: 2122: 2123: 2124: 2125:
2126: $show_delete_course_button = apply_filters( 'sensei_show_delete_course_button', false );
2127:
2128: if ( ! $course_purchased
2129: && ! Sensei_Utils::user_completed_course( $course->ID, get_current_user_id() )
2130: && $show_delete_course_button ) { ?>
2131:
2132: <span><input name="course_complete" type="submit" class="course-delete" value="<?php echo __( 'Delete Course', 'woothemes-sensei' ); ?>"/></span>
2133:
2134: <?php }
2135:
2136: $has_quizzes = Sensei()->course->course_quizzes( $course->ID, true );
2137: $results_link = '';
2138: if( $has_quizzes ){
2139: $results_link = '<a class="button view-results" href="' . Sensei()->course_results->get_permalink( $course->ID ) . '">' . __( 'View results', 'woothemes-sensei' ) . '</a>';
2140: }
2141:
2142:
2143: if ( has_filter( 'sensei_results_links' ) || $has_quizzes ) { ?>
2144:
2145: <p class="sensei-results-links">
2146: <?php
2147: 2148: 2149: 2150: 2151: 2152:
2153: echo apply_filters( 'sensei_results_links', $results_link, $course->ID );
2154: ?>
2155: </p>
2156:
2157: <?php }
2158: </form>
2159: </section>
2160:
2161: <?php }
2162:
2163: }
2164:
2165: 2166: 2167: 2168: 2169: 2170: 2171: 2172: 2173: 2174: 2175: 2176: 2177: 2178:
2179: public static function course_query_filter( $query ){
2180:
2181:
2182: if( is_admin( ) || 'course' != $query->get( 'post_type' ) ){
2183: return $query;
2184: }
2185:
2186: global $post;
2187:
2188:
2189: if( $query->is_main_query() && is_post_type_archive('course') )
2190: {
2191: 2192: 2193: 2194: 2195: 2196: 2197: 2198: 2199:
2200: $query->set( 'posts_per_page', apply_filters( 'sensei_archive_courses_per_page', get_option( 'posts_per_page' ) ) );
2201:
2202: }
2203:
2204: elseif( is_page() && Sensei()->settings->get( 'my_course_page' ) == $post->ID )
2205: {
2206: 2207: 2208: 2209: 2210: 2211: 2212: 2213: 2214:
2215: $query->set( 'posts_per_page', apply_filters( 'sensei_my_courses_per_page', 10 ) );
2216:
2217: }
2218:
2219: return $query;
2220:
2221: }
2222:
2223: 2224: 2225: 2226: 2227: 2228: 2229: 2230:
2231: public static function get_course_loop_content_class ()
2232: {
2233:
2234: global $sensei_course_loop;
2235:
2236:
2237: if( !isset( $sensei_course_loop ) ){
2238: $sensei_course_loop = array();
2239: }
2240:
2241: if (!isset($sensei_course_loop['counter'])) {
2242: $sensei_course_loop['counter'] = 0;
2243: }
2244:
2245: if (!isset($sensei_course_loop['columns'])) {
2246: $sensei_course_loop['columns'] = self::get_loop_number_of_columns();
2247: }
2248:
2249:
2250: $sensei_course_loop['counter']++;
2251:
2252: $extra_classes = array();
2253: if( 0 == ( $sensei_course_loop['counter'] - 1 ) % $sensei_course_loop['columns'] || 1 == $sensei_course_loop['columns'] ){
2254: $extra_classes[] = 'first';
2255: }
2256:
2257: if( 0 == $sensei_course_loop['counter'] % $sensei_course_loop['columns'] ){
2258: $extra_classes[] = 'last';
2259: }
2260:
2261:
2262: $extra_classes[] = 'loop-item-number-'. $sensei_course_loop['counter'];
2263:
2264: 2265: 2266: 2267: 2268: 2269: 2270: 2271: 2272:
2273: return apply_filters( 'sensei_course_loop_content_class', $extra_classes ,get_post() );
2274:
2275: }
2276:
2277: 2278: 2279: 2280: 2281: 2282:
2283: public static function get_loop_number_of_columns(){
2284:
2285: 2286: 2287: 2288: 2289: 2290:
2291: return apply_filters('sensei_course_loop_number_of_columns', 1);
2292:
2293: }
2294:
2295: 2296: 2297: 2298: 2299: 2300: 2301: 2302:
2303: public static function course_archive_sorting( $query ){
2304:
2305:
2306: if( ! is_archive( 'course ') || is_tax('course-category') ){
2307: return;
2308: }
2309:
2310: 2311: 2312: 2313: 2314: 2315: 2316: 2317: 2318:
2319: $course_order_by_options = apply_filters( 'sensei_archive_course_order_by_options', array(
2320: "newness" => __( "Sort by newest first", "woothemes-sensei"),
2321: "title" => __( "Sort by title A-Z", "woothemes-sensei" ),
2322: ));
2323:
2324:
2325: $selected = 'newness';
2326: if( isset( $_GET['orderby'] ) ){
2327:
2328: $selected = $_GET[ 'orderby' ];
2329:
2330: }
2331:
2332: ?>
2333:
2334: <form class="sensei-ordering" name="sensei-course-order" action="<?php echo esc_attr( Sensei_Utils::get_current_url() ) ; ?>" method="POST">
2335: <select name="course-orderby" class="orderby">
2336: <?php
2337: foreach( $course_order_by_options as $value => $text ){
2338:
2339: echo '<option value="'. $value . ' "' . selected( $selected, $value, false ) . '>'. $text. '</option>';
2340:
2341: }
2342: ?>
2343: </select>
2344: </form>
2345:
2346: <?php
2347: }
2348:
2349: 2350: 2351: 2352: 2353: 2354: 2355: 2356:
2357: public static function course_archive_filters( $query ){
2358:
2359:
2360: if( is_tax('course-category') ){
2361: return;
2362: }
2363:
2364: 2365: 2366: 2367: 2368: 2369: 2370: 2371: 2372:
2373: $filters = apply_filters( 'sensei_archive_course_filter_by_options', array(
2374: array( 'id' => 'all', 'url' => self::get_courses_page_url(), 'title'=> __( 'All', 'woothemes-sensei' ) ),
2375: array( 'id' => 'featured', 'url' => add_query_arg( array( 'course_filter'=>'featured'), self::get_courses_page_url() ), 'title'=> __( 'Featured', 'woothemes-sensei' ) ),
2376: ));
2377:
2378:
2379: ?>
2380: <ul class="sensei-course-filters clearfix" >
2381: <?php
2382:
2383:
2384: $current_url = Sensei_Utils::get_current_url();
2385:
2386: foreach( $filters as $filter ) {
2387:
2388: $active_class = $current_url == $filter['url'] ? ' class="active" ' : '';
2389:
2390: echo '<li><a '. $active_class .' id="'. $filter['id'] .'" href="'. esc_url( $filter['url'] ).'" >'. $filter['title'] .'</a></li>';
2391:
2392: }
2393: ?>
2394:
2395: </ul>
2396:
2397: <?php
2398:
2399: }
2400:
2401: 2402: 2403: 2404: 2405: 2406: 2407: 2408: 2409: 2410:
2411: public static function course_archive_featured_filter( $query ){
2412:
2413: if( isset ( $_GET[ 'course_filter' ] ) && 'featured'== $_GET['course_filter'] && $query->is_main_query() ){
2414:
2415: $query->set( 'meta_value', 'featured' );
2416: $query->set( 'meta_key', '_course_featured' );
2417: $query->set( 'meta_compare', '=' );
2418: }
2419:
2420: return $query;
2421: }
2422:
2423: 2424: 2425: 2426: 2427: 2428: 2429: 2430: 2431:
2432: public static function course_archive_order_by_title( $query ){
2433:
2434: if( isset ( $_POST[ 'course-orderby' ] ) && 'title '== $_POST['course-orderby']
2435: && 'course'== $query->get('post_type') && $query->is_main_query() ){
2436:
2437: $query->set( 'orderby', 'title' );
2438: $query->set( 'order', 'ASC' );
2439: }
2440:
2441: return $query;
2442: }
2443:
2444:
2445: 2446: 2447: 2448: 2449: 2450: 2451:
2452: public static function get_courses_page_url(){
2453:
2454: $course_page_id = intval( Sensei()->settings->settings[ 'course_page' ] );
2455: $course_page_url = empty( $course_page_id ) ? get_post_type_archive_link('course') : get_permalink( $course_page_id );
2456:
2457: return $course_page_url;
2458:
2459: }
2460:
2461: 2462: 2463: 2464: 2465: 2466: 2467: 2468: 2469: 2470: 2471:
2472: public static function archive_header( $query_type ='' , $before_html='', $after_html ='' ){
2473:
2474: if( ! is_post_type_archive('course') ){
2475: return;
2476: }
2477:
2478:
2479: sensei_do_deprecated_action('sensei_archive_title','1.9.0','sensei_archive_before_course_loop');
2480:
2481: $html = '';
2482:
2483: if( empty( $before_html ) ){
2484:
2485: $before_html = '<header class="archive-header"><h1>';
2486:
2487: }
2488:
2489: if( empty( $after_html ) ){
2490:
2491: $after_html = '</h1></header>';
2492:
2493: }
2494:
2495: if ( is_tax( 'course-category' ) ) {
2496:
2497: global $wp_query;
2498:
2499: $taxonomy_obj = $wp_query->get_queried_object();
2500: $taxonomy_short_name = $taxonomy_obj->taxonomy;
2501: $taxonomy_raw_obj = get_taxonomy( $taxonomy_short_name );
2502: $title = sprintf( __( '%1$s Archives: %2$s', 'woothemes-sensei' ), $taxonomy_raw_obj->labels->name, $taxonomy_obj->name );
2503: echo apply_filters( 'course_category_archive_title', $before_html . $title . $after_html );
2504: return;
2505:
2506: }
2507:
2508: switch ( $query_type ) {
2509: case 'newcourses':
2510: $html .= $before_html . __( 'New Courses', 'woothemes-sensei' ) . $after_html;
2511: break;
2512: case 'featuredcourses':
2513: $html .= $before_html . __( 'Featured Courses', 'woothemes-sensei' ) . $after_html;
2514: break;
2515: case 'freecourses':
2516: $html .= $before_html . __( 'Free Courses', 'woothemes-sensei' ) . $after_html;
2517: break;
2518: case 'paidcourses':
2519: $html .= $before_html . __( 'Paid Courses', 'woothemes-sensei' ) . $after_html;
2520: break;
2521: default:
2522: $html .= $before_html . __( 'Courses', 'woothemes-sensei' ) . $after_html;
2523: break;
2524: }
2525:
2526: echo apply_filters( 'course_archive_title', $html );
2527:
2528: }
2529:
2530:
2531: 2532: 2533: 2534: 2535: 2536: 2537: 2538: 2539:
2540: public static function single_course_content( $content ){
2541:
2542: if( ! is_singular('course') ){
2543:
2544: return $content;
2545:
2546: }
2547:
2548:
2549: $access_permission = false;
2550:
2551: if ( ! Sensei()->settings->get('access_permission') || sensei_all_access() ) {
2552:
2553: $access_permission = true;
2554:
2555: }
2556:
2557:
2558: $is_user_taking_course = Sensei_Utils::user_started_course( get_the_ID(), get_current_user_id() );
2559:
2560: if(Sensei_WC::is_woocommerce_active()) {
2561:
2562: $wc_post_id = get_post_meta( get_the_ID(), '_course_woocommerce_product', true );
2563: $product = Sensei()->sensei_get_woocommerce_product_object( $wc_post_id );
2564:
2565: $has_product_attached = isset ( $product ) && is_object ( $product );
2566:
2567: } else {
2568:
2569: $has_product_attached = false;
2570:
2571: }
2572:
2573: if ( ( is_user_logged_in() && $is_user_taking_course )
2574: || ( $access_permission && !$has_product_attached)
2575: || 'full' == Sensei()->settings->get( 'course_single_content_display' ) ) {
2576:
2577:
2578:
2579: if( empty( $content ) ){
2580: remove_filter( 'the_content', array( 'Sensei_Course', 'single_course_content') );
2581: $course = get_post( get_the_ID() );
2582:
2583: $content = apply_filters( 'the_content', $course->post_content );
2584:
2585: }
2586:
2587: return $content;
2588:
2589: } else {
2590:
2591: return '<p class="course-excerpt">' . get_post( get_the_ID() )->post_excerpt . '</p>';
2592:
2593: }
2594:
2595: }
2596:
2597: 2598: 2599: 2600: 2601:
2602: public static function the_course_lessons_title(){
2603:
2604: if ( ! is_singular( 'course' ) ) {
2605: return;
2606: }
2607:
2608: global $post;
2609: $none_module_lessons = Sensei()->modules->get_none_module_lessons( $post->ID );
2610: $course_lessons = Sensei()->course->course_lessons( $post->ID );
2611:
2612:
2613: $title = __('Other Lessons', 'woothemes-sensei');
2614:
2615:
2616: if( count( $course_lessons ) == count( $none_module_lessons ) ){
2617:
2618: $title = __('Lessons', 'woothemes-sensei');
2619:
2620: }elseif( empty( $none_module_lessons ) ){
2621:
2622: $title = '';
2623: }
2624:
2625: 2626: 2627:
2628: $title = apply_filters( 'sensei_single_title', $title, $post->post_type );
2629:
2630: ob_start();
2631:
2632: ?>
2633:
2634: <header>
2635: <h2> <?php echo $title; ?> </h2>
2636: </header>
2637:
2638: <?php
2639:
2640: 2641: 2642: 2643: 2644: 2645: 2646:
2647: echo apply_filters('the_course_lessons_title', ob_get_clean() );
2648:
2649: }
2650:
2651: 2652: 2653: 2654: 2655: 2656: 2657: 2658: 2659: 2660: 2661:
2662: public static function load_single_course_lessons_query(){
2663:
2664: global $post, $wp_query;
2665:
2666: $course_id = $post->ID;
2667:
2668: if( 'course' != get_post_type( $course_id ) ){
2669: return;
2670: }
2671:
2672: $course_lesson_query_args = array(
2673: 'post_status' => 'publish',
2674: 'post_type' => 'lesson',
2675: 'posts_per_page' => 500,
2676: 'orderby' => 'date',
2677: 'order' => 'ASC',
2678: 'meta_query' => array(
2679: array(
2680: 'key' => '_lesson_course',
2681: 'value' => intval( $course_id ),
2682: ),
2683: ),
2684: 'suppress_filters' => 0,
2685: );
2686:
2687:
2688: $modules = Sensei()->modules->get_course_modules( $course_id );
2689: if( !is_wp_error( $modules ) && ! empty( $modules ) && is_array( $modules ) ){
2690:
2691: $terms_ids = array();
2692: foreach( $modules as $term ){
2693:
2694: $terms_ids[] = $term->term_id;
2695:
2696: }
2697:
2698: $course_lesson_query_args[ 'tax_query'] = array(
2699: array(
2700: 'taxonomy' => 'module',
2701: 'field' => 'id',
2702: 'terms' => $terms_ids,
2703: 'operator' => 'NOT IN',
2704: ),
2705: );
2706: }
2707:
2708:
2709: $course_lesson_order = get_post_meta( $course_id, '_lesson_order', true);
2710: if( !empty( $course_lesson_order ) ){
2711:
2712: $course_lesson_query_args['post__in'] = explode( ',', $course_lesson_order );
2713: $course_lesson_query_args['orderby']= 'post__in' ;
2714: unset( $course_lesson_query_args['order'] );
2715:
2716: }
2717:
2718: $wp_query = new WP_Query( $course_lesson_query_args );
2719:
2720: }
2721:
2722: 2723: 2724: 2725: 2726: 2727: 2728:
2729: public static function flush_rewrite_rules( $post_id ){
2730:
2731: if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE){
2732:
2733: return;
2734:
2735: }
2736:
2737:
2738: if( 'course' == get_post_type( $post_id ) ){
2739:
2740: Sensei()->initiate_rewrite_rules_flush();
2741:
2742: }
2743:
2744: }
2745:
2746: 2747: 2748: 2749: 2750: 2751: 2752: 2753:
2754: public static function full_content_excerpt_override( $excerpt ){
2755:
2756: if ( is_singular('course') &&
2757: 'full' == Sensei()->settings->get( 'course_single_content_display' ) ){
2758:
2759: return get_the_content();
2760:
2761: } else {
2762:
2763: return $excerpt;
2764:
2765: }
2766:
2767: }
2768:
2769: 2770: 2771: 2772: 2773:
2774: public static function the_course_enrolment_actions(){
2775:
2776: global $post;
2777:
2778: if ( 'course' != $post->post_type ) {
2779: return;
2780: }
2781:
2782: ?>
2783: <section class="course-meta course-enrolment">
2784: <?php
2785: global $post, $current_user;
2786: $is_user_taking_course = Sensei_Utils::user_started_course( $post->ID, $current_user->ID );
2787:
2788: if ( is_user_logged_in() && ! $is_user_taking_course ) {
2789:
2790:
2791: if ( Sensei_WC::is_woocommerce_active() && Sensei_WC::is_course_purchasable( $post->ID ) ) {
2792:
2793:
2794: Sensei_WC::the_add_to_cart_button_html($post->ID );
2795:
2796: } else {
2797:
2798: sensei_start_course_form($post->ID);
2799:
2800: }
2801:
2802: } elseif ( is_user_logged_in() ) {
2803:
2804:
2805: $user_course_status = Sensei_Utils::user_course_status( $post->ID, $current_user->ID );
2806: $completed_course = Sensei_Utils::user_completed_course( $user_course_status );
2807:
2808: if ( $completed_course ) { ?>
2809: <div class="status completed"><?php _e( 'Completed', 'woothemes-sensei' ); ?></div>
2810: <?php
2811: $has_quizzes = Sensei()->course->course_quizzes( $post->ID, true );
2812: if( has_filter( 'sensei_results_links' ) || $has_quizzes ) { ?>
2813: <p class="sensei-results-links">
2814: <?php
2815: $results_link = '';
2816: if( $has_quizzes ) {
2817: $results_link = '<a class="view-results" href="' . Sensei()->course_results->get_permalink( $post->ID ) . '">' . __( 'View results', 'woothemes-sensei' ) . '</a>';
2818: }
2819: 2820: 2821:
2822: $results_link = apply_filters( 'sensei_results_links', $results_link, $post->ID );
2823: echo $results_link;
2824: ?></p>
2825: <?php } ?>
2826: <?php } else { ?>
2827: <div class="status in-progress"><?php echo __( 'In Progress', 'woothemes-sensei' ); ?></div>
2828: <?php }
2829:
2830: } else {
2831:
2832:
2833: if ( Sensei_WC::is_woocommerce_active() && Sensei_WC::is_course_purchasable( $post->ID ) ) {
2834:
2835: $login_link = '<a href="' . sensei_user_login_url() . '">' . __( 'log in', 'woothemes-sensei' ) . '</a>';
2836: $message = sprintf( __( 'Or %1$s to access your purchased courses', 'woothemes-sensei' ), $login_link );
2837: Sensei()->notices->add_notice( $message, 'info' ) ;
2838: Sensei_WC::the_add_to_cart_button_html( $post->ID );
2839:
2840: } else {
2841:
2842: if( get_option( 'users_can_register') ) {
2843:
2844:
2845: $anchor_before = '<a href="' . esc_url( sensei_user_login_url() ) . '" >';
2846: $anchor_after = '</a>';
2847: $notice = sprintf(
2848: __('or %slog in%s to view this course.', 'woothemes-sensei'),
2849: $anchor_before,
2850: $anchor_after
2851: );
2852:
2853:
2854: if( Sensei()->settings->get( 'access_permission' ) ){
2855: Sensei()->notices->add_notice( $notice, 'info' ) ;
2856: }
2857:
2858:
2859: $my_courses_page_id = '';
2860:
2861: 2862: 2863: 2864: 2865: 2866: 2867:
2868:
2869: $wp_register_link = apply_filters('sensei_use_wp_register_link', false);
2870:
2871: $settings = Sensei()->settings->get_settings();
2872: if( isset( $settings[ 'my_course_page' ] )
2873: && 0 < intval( $settings[ 'my_course_page' ] ) ){
2874:
2875: $my_courses_page_id = $settings[ 'my_course_page' ];
2876:
2877: }
2878:
2879:
2880:
2881: if( !empty( $my_courses_page_id ) && $my_courses_page_id && !$wp_register_link){
2882:
2883: $my_courses_url = get_permalink( $my_courses_page_id );
2884: $register_link = '<a href="'.$my_courses_url. '">' . __('Register', 'woothemes-sensei') .'</a>';
2885: echo '<div class="status register">' . $register_link . '</div>' ;
2886:
2887: } else{
2888:
2889: wp_register( '<div class="status register">', '</div>' );
2890:
2891: }
2892:
2893: }
2894:
2895: }
2896:
2897: }
2898:
2899: </section><?php
2900:
2901: }
2902:
2903: 2904: 2905: 2906: 2907:
2908: public static function the_course_video(){
2909:
2910: global $post;
2911:
2912: if ( ! is_singular( 'course' ) ) {
2913: return;
2914: }
2915:
2916: $course_video_embed = get_post_meta( $post->ID, '_course_video_embed', true );
2917:
2918: if ( 'http' == substr( $course_video_embed, 0, 4) ) {
2919:
2920: $course_video_embed = wp_oembed_get( esc_url( $course_video_embed ) );
2921:
2922: }
2923:
2924: if ( '' != $course_video_embed ) { ?>
2925:
2926: <div class="course-video">
2927: <?php echo do_shortcode( html_entity_decode( $course_video_embed ) ); ?>
2928: </div>
2929:
2930: <?php }
2931: }
2932:
2933: 2934: 2935: 2936: 2937: 2938:
2939: public static function the_title(){
2940:
2941: if( ! is_singular( 'course' ) ){
2942: return;
2943: }
2944: global $post;
2945:
2946: ?>
2947: <header>
2948:
2949: <h1>
2950:
2951: <?php
2952: 2953: 2954:
2955: echo apply_filters( 'sensei_single_title', get_the_title( $post ), $post->post_type );
2956: ?>
2957:
2958: </h1>
2959:
2960: </header>
2961:
2962: <?php
2963:
2964: }
2965:
2966: 2967: 2968: 2969: 2970:
2971: public static function course_category_title(){
2972:
2973: if( ! is_tax( 'course-category' ) ){
2974: return;
2975: }
2976:
2977: $category_slug = get_query_var('course-category');
2978: $term = get_term_by('slug',$category_slug,'course-category');
2979:
2980: if( ! empty($term) ){
2981:
2982: $title = __('Category') . ' ' . $term->name;
2983:
2984: }else{
2985:
2986: $title = 'Course Category';
2987:
2988: }
2989:
2990: $html = '<h2 class="sensei-category-title">';
2991: $html .= $title;
2992: $html .= '</h2>';
2993:
2994: echo apply_filters( 'course_category_title', $html , $term->term_id );
2995:
2996: }
2997:
2998: 2999: 3000: 3001: 3002: 3003: 3004: 3005: 3006:
3007: public static function alter_course_category_order( $query ){
3008:
3009: if( ! is_tax( 'course-category' ) || ! $query->is_main_query() ){
3010: return $query;
3011: }
3012:
3013: $order = get_option( 'sensei_course_order', '' );
3014: if( !empty( $order ) ){
3015: $query->set('orderby', 'menu_order' );
3016: $query->set('order', 'ASC' );
3017: }
3018:
3019: return $query;
3020:
3021: }
3022:
3023: 3024: 3025: 3026: 3027: 3028: 3029: 3030: 3031: 3032: 3033: 3034: 3035: 3036:
3037: public static function get_default_query_args(){
3038: return array(
3039: 'post_type' => 'course',
3040: 'posts_per_page' => 1000,
3041: 'orderby' => 'date',
3042: 'order' => 'DESC',
3043: 'suppress_filters' => 0
3044: );
3045: }
3046:
3047: 3048: 3049: 3050: 3051: 3052: 3053: 3054:
3055: public static function is_prerequisite_complete( $course_id ){
3056:
3057: $course_prerequisite_id = get_post_meta( $course_id, '_course_prerequisite', true );
3058:
3059:
3060: if( ! empty( $course_prerequisite_id ) ){
3061:
3062: return Sensei_Utils::user_completed_course( $course_prerequisite_id, get_current_user_id() );
3063:
3064: }
3065:
3066: return true;
3067:
3068: }
3069:
3070: 3071: 3072: 3073: 3074: 3075:
3076: function allow_course_archive_on_front_page( $query ) {
3077:
3078: global $wp;
3079:
3080: if ( ! is_page() ){
3081: return;
3082: }
3083:
3084:
3085: remove_action( 'pre_get_posts', array( $this, 'allow_course_archive_on_front_page' ) );
3086:
3087: $query_check = clone $query;
3088: $posts = $query_check->get_posts();
3089: $possible_home_page = array_shift( $posts );
3090:
3091:
3092: $not_a_valid_static_front_page = 0 == intval( get_option( 'page_on_front' ) )
3093: || is_admin()
3094: || ! $query->is_main_query()
3095: || ! empty( $wp->query_string )
3096: || ! isset( $possible_home_page->ID )
3097: || 'page' !=$possible_home_page->post_type
3098: || $possible_home_page->ID != get_option( 'page_on_front' ) ;
3099:
3100: if ( $not_a_valid_static_front_page ) {
3101:
3102: add_action( 'pre_get_posts', array( $this, 'allow_course_archive_on_front_page' ) );
3103: return;
3104:
3105: }
3106:
3107:
3108:
3109: $settings_course_page = get_post( Sensei()->settings->get( 'course_page' ) );
3110: if( ! is_a( $settings_course_page, 'WP_Post')
3111: || Sensei()->post_types->has_old_shortcodes( $settings_course_page->post_content )
3112: || $settings_course_page->ID != get_option( 'page_on_front' ) ){
3113:
3114: return;
3115:
3116: }
3117:
3118:
3119: $query->set( 'post_type', 'course' );
3120: $query->set( 'page_id', '' );
3121:
3122:
3123: $query->is_page = 0;
3124: $query->is_singular = 0;
3125: $query->is_post_type_archive = 1;
3126: $query->is_archive = 1;
3127: }
3128:
3129:
3130: }
3131:
3132: 3133: 3134: 3135: 3136:
3137: class WooThemes_Sensei_Course extends Sensei_Course{}
3138: