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