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 |
||
0 ignored issues
–
show
|
|||
2 | if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly |
||
3 | |||
4 | /** |
||
5 | * Sensei Utilities Class |
||
6 | * |
||
7 | * Common utility functions for Sensei. |
||
8 | * |
||
9 | * @package Core |
||
10 | * @author Automattic |
||
11 | * |
||
12 | * @since 1.0.0 |
||
13 | */ |
||
14 | class Sensei_Utils { |
||
15 | /** |
||
16 | * Get the placeholder thumbnail image. |
||
17 | * @access public |
||
18 | * @since 1.0.0 |
||
19 | * @return string The URL to the placeholder thumbnail image. |
||
20 | */ |
||
21 | public static function get_placeholder_image () { |
||
22 | |||
23 | return esc_url( apply_filters( 'sensei_placeholder_thumbnail', Sensei()->plugin_url . 'assets/images/placeholder.png' ) ); |
||
24 | } // End get_placeholder_image() |
||
25 | |||
26 | /** |
||
27 | * Check if WooCommerce is present. |
||
28 | * |
||
29 | * @deprecated since 1.9.0 use Sensei_WC::is_woocommerce_present() |
||
30 | * @access public |
||
31 | * @since 1.0.2 |
||
32 | * @static |
||
33 | * @return bool |
||
34 | */ |
||
35 | public static function sensei_is_woocommerce_present () { |
||
36 | |||
37 | return Sensei_WC::is_woocommerce_present(); |
||
38 | |||
39 | } // End sensei_is_woocommerce_present() |
||
40 | |||
41 | /** |
||
42 | * Check if WooCommerce is active. |
||
43 | * |
||
44 | * @deprecated since 1.9.0 use Sensei_WC::is_woocommerce_active |
||
45 | * @access public |
||
46 | * @since 1.0.2 |
||
47 | * @static |
||
48 | * @return boolean |
||
49 | */ |
||
50 | public static function sensei_is_woocommerce_activated () { |
||
51 | |||
52 | return Sensei_WC::is_woocommerce_active(); |
||
53 | |||
54 | } // End sensei_is_woocommerce_activated() |
||
55 | |||
56 | /** |
||
57 | * Log an activity item. |
||
58 | * @access public |
||
59 | * @since 1.0.0 |
||
60 | * @param array $args (default: array()) |
||
61 | * @return bool | int |
||
62 | */ |
||
63 | public static function sensei_log_activity ( $args = array() ) { |
||
64 | global $wpdb; |
||
65 | |||
66 | // Args, minimum data required for WP |
||
67 | $data = array( |
||
68 | 'comment_post_ID' => intval( $args['post_id'] ), |
||
69 | 'comment_author' => '', // Not needed |
||
70 | 'comment_author_email' => '', // Not needed |
||
71 | 'comment_author_url' => '', // Not needed |
||
72 | 'comment_content' => !empty($args['data']) ? esc_html( $args['data'] ) : '', |
||
73 | 'comment_type' => esc_attr( $args['type'] ), |
||
74 | 'user_id' => intval( $args['user_id'] ), |
||
75 | 'comment_approved' => !empty($args['status']) ? esc_html( $args['status'] ) : 'log', // 'log' == 'sensei_user_answer' |
||
76 | ); |
||
77 | // Allow extra data |
||
78 | if ( !empty($args['username']) ) { |
||
79 | $data['comment_author'] = sanitize_user( $args['username'] ); |
||
80 | } |
||
81 | if ( !empty($args['user_email']) ) { |
||
82 | $data['comment_author_email'] = sanitize_email( $args['user_email'] ); |
||
83 | } |
||
84 | if ( !empty($args['user_url']) ) { |
||
85 | $data['comment_author_url'] = esc_url( $args['user_url'] ); |
||
86 | } |
||
87 | if ( !empty($args['parent']) ) { |
||
88 | $data['comment_parent'] = $args['parent']; |
||
89 | } |
||
90 | // Sanity check |
||
91 | if ( empty($args['user_id']) ) { |
||
92 | _deprecated_argument( __FUNCTION__, '1.0', __('At no point should user_id be equal to 0.', 'woothemes-sensei') ); |
||
93 | return false; |
||
94 | } |
||
95 | |||
96 | do_action( 'sensei_log_activity_before', $args, $data ); |
||
97 | |||
98 | $flush_cache = false; |
||
99 | |||
100 | // Custom Logic |
||
101 | // Check if comment exists first |
||
102 | $comment_id = $wpdb->get_var( $wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = %d AND user_id = %d AND comment_type = %s ", $args['post_id'], $args['user_id'], $args['type'] ) ); |
||
103 | if ( ! $comment_id ) { |
||
104 | // Add the comment |
||
105 | $comment_id = wp_insert_comment( $data ); |
||
106 | |||
107 | $flush_cache = true; |
||
108 | } elseif ( isset( $args['action'] ) && 'update' == $args['action'] ) { |
||
109 | // Update the comment if an update was requested |
||
110 | $data['comment_ID'] = $comment_id; |
||
111 | // By default update the timestamp of the comment |
||
112 | if ( empty($args['keep_time']) ) { |
||
113 | $data['comment_date'] = current_time('mysql'); |
||
114 | } |
||
115 | wp_update_comment( $data ); |
||
116 | $flush_cache = true; |
||
117 | } // End If Statement |
||
118 | |||
119 | // Manually Flush the Cache |
||
120 | if ( $flush_cache ) { |
||
121 | wp_cache_flush(); |
||
122 | } |
||
123 | |||
124 | do_action( 'sensei_log_activity_after', $args, $data, $comment_id ); |
||
125 | |||
126 | if ( 0 < $comment_id ) { |
||
127 | // Return the ID so that it can be used for meta data storage |
||
128 | return $comment_id; |
||
129 | } else { |
||
130 | return false; |
||
131 | } // End If Statement |
||
132 | } // End sensei_log_activity() |
||
133 | |||
134 | |||
135 | /** |
||
136 | * Check for Sensei activity. |
||
137 | * @access public |
||
138 | * @since 1.0.0 |
||
139 | * @param array $args (default: array()) |
||
140 | * @param bool $return_comments (default: false) |
||
141 | * @return mixed | int |
||
142 | */ |
||
143 | public static function sensei_check_for_activity ( $args = array(), $return_comments = false ) { |
||
144 | |||
145 | global $wp_version; |
||
146 | if ( !$return_comments ) { |
||
147 | $args['count'] = true; |
||
148 | } |
||
149 | |||
150 | // Are we only retrieving a single entry, or not care about the order... |
||
151 | if ( isset( $args['count'] ) || isset( $args['post_id'] ) ){ |
||
152 | |||
153 | // ...then we don't need to ask the db to order the results, this overrides WP default behaviour |
||
154 | if ( version_compare( $wp_version, '4.1', '>=' ) ) { |
||
155 | $args['order'] = false; |
||
156 | $args['orderby'] = false; |
||
157 | } |
||
158 | } |
||
159 | |||
160 | // A user ID of 0 is in valid, so shortcut this |
||
161 | if ( isset( $args['user_id'] ) && 0 == intval ( $args['user_id'] ) ) { |
||
162 | _deprecated_argument( __FUNCTION__, '1.0', __('At no point should user_id be equal to 0.', 'woothemes-sensei') ); |
||
163 | return false; |
||
164 | } |
||
165 | // Check for legacy code |
||
166 | if ( isset($args['type']) && in_array($args['type'], array('sensei_course_start', 'sensei_course_end', 'sensei_lesson_start', 'sensei_lesson_end', 'sensei_quiz_asked', 'sensei_user_grade', 'sensei_quiz_grade', 'sense_answer_notes') ) ) { |
||
167 | _deprecated_argument( __FUNCTION__, '1.7', sprintf( __('Sensei activity type %s is no longer used.', 'woothemes-sensei'), $args['type'] ) ); |
||
168 | return false; |
||
169 | } |
||
170 | // Are we checking for specific comment_approved statuses? |
||
171 | if ( isset($args['status']) ) { |
||
172 | // Temporarily store as a custom status if requesting an array... |
||
173 | View Code Duplication | if ( is_array( $args['status'] ) && version_compare($wp_version, '4.1', '<') ) { |
|
174 | // Encode now, decode later |
||
175 | $args['status'] = implode( ",", $args['status'] ); |
||
176 | // ...use a filter to switch the encoding back |
||
177 | add_filter( 'comments_clauses', array( __CLASS__, 'comment_multiple_status_filter' ) ); |
||
178 | } |
||
179 | } |
||
180 | else { |
||
181 | $args['status'] = 'any'; // 'log' == 'sensei_user_answer' |
||
182 | } |
||
183 | |||
184 | // Take into account WP < 4.1 will automatically add ' comment_approved = 1 OR comment_approved = 0 ' |
||
185 | View Code Duplication | if ( ( is_array( $args['status'] ) || 'any' == $args['status'] ) && version_compare($wp_version, '4.1', '<') ) { |
|
186 | add_filter( 'comments_clauses', array( __CLASS__, 'comment_any_status_filter' ) ); |
||
187 | } |
||
188 | |||
189 | //Get the comments |
||
190 | /** |
||
191 | * This filter runs inside Sensei_Utils::sensei_check_for_activity |
||
192 | * |
||
193 | * It runs while getting the comments for the given request. |
||
194 | * |
||
195 | * @param int|array $comments |
||
196 | */ |
||
197 | $comments = apply_filters('sensei_check_for_activity', get_comments( $args ) ); |
||
198 | |||
199 | remove_filter( 'comments_clauses', array( __CLASS__, 'comment_multiple_status_filter' ) ); |
||
200 | remove_filter( 'comments_clauses', array( __CLASS__, 'comment_any_status_filter' ) ); |
||
201 | // Return comments |
||
202 | if ( $return_comments ) { |
||
203 | // Could check for array of 1 and just return the 1 item? |
||
204 | if ( is_array($comments) && 1 == count($comments) ) { |
||
205 | $comments = array_shift($comments); |
||
206 | } |
||
207 | |||
208 | return $comments; |
||
209 | } // End If Statement |
||
210 | // Count comments |
||
211 | return intval($comments); // This is the count, check the return from WP_Comment_Query |
||
212 | } // End sensei_check_for_activity() |
||
213 | |||
214 | |||
215 | /** |
||
216 | * Get IDs of Sensei activity items. |
||
217 | * @access public |
||
218 | * @since 1.0.0 |
||
219 | * @param array $args (default: array()) |
||
220 | * @return array |
||
221 | */ |
||
222 | public static function sensei_activity_ids ( $args = array() ) { |
||
223 | |||
224 | |||
225 | $comments = Sensei_Utils::sensei_check_for_activity( $args, true ); |
||
226 | // Need to always use an array, even with only 1 item |
||
227 | if ( !is_array($comments) ) { |
||
228 | $comments = array( $comments ); |
||
229 | } |
||
230 | |||
231 | $post_ids = array(); |
||
232 | // Count comments |
||
233 | if ( is_array( $comments ) && ( 0 < intval( count( $comments ) ) ) ) { |
||
234 | foreach ( $comments as $key => $value ) { |
||
235 | // Add matches to id array |
||
236 | if ( isset( $args['field'] ) && 'comment' == $args['field'] ) { |
||
237 | array_push( $post_ids, $value->comment_ID ); |
||
238 | } elseif( isset( $args['field'] ) && 'user_id' == $args['field'] ) { |
||
239 | array_push( $post_ids, $value->user_id ); |
||
240 | } else { |
||
241 | array_push( $post_ids, $value->comment_post_ID ); |
||
242 | } // End If Statement |
||
243 | } // End For Loop |
||
244 | // Reset array indexes |
||
245 | $post_ids = array_unique( $post_ids ); |
||
246 | $post_ids = array_values( $post_ids ); |
||
247 | } // End If Statement |
||
248 | |||
249 | return $post_ids; |
||
250 | } // End sensei_activity_ids() |
||
251 | |||
252 | |||
253 | /** |
||
254 | * Delete Sensei activities. |
||
255 | * @access public |
||
256 | * @since 1.0.0 |
||
257 | * @param array $args (default: array()) |
||
258 | * @return boolean |
||
259 | */ |
||
260 | public static function sensei_delete_activities ( $args = array() ) { |
||
261 | |||
262 | $dataset_changes = false; |
||
263 | |||
264 | // If activity exists remove activity from log |
||
265 | $comments = Sensei_Utils::sensei_check_for_activity( array( 'post_id' => intval( $args['post_id'] ), 'user_id' => intval( $args['user_id'] ), 'type' => esc_attr( $args['type'] ) ), true ); |
||
266 | if( $comments ) { |
||
267 | // Need to always return an array, even with only 1 item |
||
268 | if ( !is_array( $comments ) ) { |
||
269 | $comments = array( $comments ); |
||
270 | } |
||
271 | foreach ( $comments as $key => $value ) { |
||
272 | if ( isset( $value->comment_ID ) && 0 < $value->comment_ID ) { |
||
273 | $dataset_changes = wp_delete_comment( intval( $value->comment_ID ), true ); |
||
274 | } // End If Statement |
||
275 | } // End For Loop |
||
276 | // Manually flush the cache |
||
277 | wp_cache_flush(); |
||
278 | } // End If Statement |
||
279 | return $dataset_changes; |
||
280 | } // End sensei_delete_activities() |
||
281 | |||
282 | /** |
||
283 | * Delete all activity for specified user |
||
284 | * @access public |
||
285 | * @since 1.5.0 |
||
286 | * @param integer $user_id User ID |
||
287 | * @return boolean |
||
288 | */ |
||
289 | public static function delete_all_user_activity( $user_id = 0 ) { |
||
290 | |||
291 | $dataset_changes = false; |
||
292 | |||
293 | if( $user_id ) { |
||
294 | |||
295 | $activities = Sensei_Utils::sensei_check_for_activity( array( 'user_id' => $user_id ), true ); |
||
296 | |||
297 | if( $activities ) { |
||
298 | |||
299 | // Need to always return an array, even with only 1 item |
||
300 | if ( ! is_array( $activities ) ) { |
||
301 | $activities = array( $activities ); |
||
302 | } |
||
303 | |||
304 | foreach( $activities as $activity ) { |
||
305 | if( '' == $activity->comment_type ) continue; |
||
306 | if( strpos( 'sensei_', $activity->comment_type ) != 0 ) continue; |
||
307 | $dataset_changes = wp_delete_comment( intval( $activity->comment_ID ), true ); |
||
308 | wp_cache_flush(); |
||
309 | } |
||
310 | } |
||
311 | } |
||
312 | |||
313 | return $dataset_changes; |
||
314 | } // Edn delete_all_user_activity() |
||
315 | |||
316 | |||
317 | /** |
||
318 | * Get value for a specified activity. |
||
319 | * @access public |
||
320 | * @since 1.0.0 |
||
321 | * @param array $args (default: array()) |
||
322 | * @return string |
||
323 | */ |
||
324 | public static function sensei_get_activity_value ( $args = array() ) { |
||
325 | |||
326 | $activity_value = false; |
||
327 | if ( !empty($args['field']) ) { |
||
328 | $comment = Sensei_Utils::sensei_check_for_activity( $args, true ); |
||
329 | |||
330 | if ( isset( $comment->{$args['field']} ) && '' != $comment->{$args['field']} ) { |
||
331 | $activity_value = $comment->{$args['field']}; |
||
332 | } // End If Statement |
||
333 | } |
||
334 | return $activity_value; |
||
335 | } // End sensei_get_activity_value() |
||
336 | |||
337 | /** |
||
338 | * Checks if a user (by email) has bought an item. |
||
339 | * |
||
340 | * @deprecated since 1.9.0 use Sensei_WC::has_customer_bought_product($user_id, $product_id) |
||
341 | * @access public |
||
342 | * @since 1.0.0 |
||
343 | * @param string $customer_email |
||
344 | * @param int $user_id |
||
345 | * @param int $product_id |
||
346 | * @return bool |
||
347 | */ |
||
348 | public static function sensei_customer_bought_product ( $customer_email, $user_id, $product_id ) { |
||
349 | |||
350 | $emails = array(); |
||
351 | |||
352 | if ( $user_id ) { |
||
353 | $user = get_user_by( 'id', intval( $user_id ) ); |
||
354 | $emails[] = $user->user_email; |
||
355 | } |
||
356 | |||
357 | if ( is_email( $customer_email ) ) |
||
358 | $emails[] = $customer_email; |
||
359 | |||
360 | if ( sizeof( $emails ) == 0 ) |
||
361 | return false; |
||
362 | |||
363 | return Sensei_WC::has_customer_bought_product( $user_id, $product_id ); |
||
364 | |||
365 | } // End sensei_customer_bought_product() |
||
366 | |||
367 | /** |
||
368 | * Load the WordPress rich text editor |
||
369 | * @param string $content Initial content for editor |
||
370 | * @param string $editor_id ID of editor (only lower case characters - no spaces, underscores, hyphens, etc.) |
||
371 | * @param string $input_name Name for text area form element |
||
372 | * @return void |
||
373 | */ |
||
374 | public static function sensei_text_editor( $content = '', $editor_id = 'senseitexteditor', $input_name = '' ) { |
||
375 | |||
376 | if( ! $input_name ) $input_name = $editor_id; |
||
377 | |||
378 | $buttons = 'bold,italic,underline,strikethrough,blockquote,bullist,numlist,justifyleft,justifycenter,justifyright,undo,redo,pastetext'; |
||
379 | |||
380 | $settings = array( |
||
381 | 'media_buttons' => false, |
||
382 | 'wpautop' => true, |
||
383 | 'textarea_name' => $input_name, |
||
384 | 'editor_class' => 'sensei_text_editor', |
||
385 | 'teeny' => false, |
||
386 | 'dfw' => false, |
||
387 | 'tinymce' => array( |
||
388 | 'theme_advanced_buttons1' => $buttons, |
||
389 | 'theme_advanced_buttons2' => '' |
||
390 | ), |
||
391 | 'quicktags' => false |
||
392 | ); |
||
393 | |||
394 | wp_editor( $content, $editor_id, $settings ); |
||
395 | |||
396 | } // End sensei_text_editor() |
||
397 | |||
398 | /** |
||
399 | * Save quiz answers submitted by users |
||
400 | * @param array $submitted User's quiz answers |
||
401 | * @param int $user_id |
||
402 | * @return boolean Whether the answers were saved or not |
||
403 | */ |
||
404 | public static function sensei_save_quiz_answers( $submitted = array(), $user_id = 0 ) { |
||
405 | |||
406 | if( intval( $user_id ) == 0 ) { |
||
407 | $user_id = get_current_user_id(); |
||
408 | } |
||
409 | |||
410 | $answers_saved = false; |
||
411 | |||
412 | if( $submitted && intval( $user_id ) > 0 ) { |
||
413 | |||
414 | foreach( $submitted as $question_id => $answer ) { |
||
415 | |||
416 | // Get question type |
||
417 | $question_type = Sensei()->question->get_question_type( $question_id ); |
||
418 | |||
419 | // Sanitise answer |
||
420 | if( 0 == get_magic_quotes_gpc() ) { |
||
421 | $answer = wp_unslash( $answer ); |
||
422 | } |
||
423 | switch( $question_type ) { |
||
424 | case 'multi-line': $answer = nl2br( $answer ); break; |
||
425 | case 'single-line': break; |
||
426 | case 'gap-fill': break; |
||
427 | default: $answer = maybe_serialize( $answer ); break; |
||
428 | } |
||
429 | $args = array( |
||
430 | 'post_id' => $question_id, |
||
431 | 'data' => base64_encode( $answer ), |
||
432 | 'type' => 'sensei_user_answer', /* FIELD SIZE 20 */ |
||
433 | 'user_id' => $user_id, |
||
434 | 'action' => 'update' |
||
435 | ); |
||
436 | $answers_saved = Sensei_Utils::sensei_log_activity( $args ); |
||
437 | } |
||
438 | |||
439 | // Handle file upload questions |
||
440 | if( isset( $_FILES ) ) { |
||
441 | foreach( $_FILES as $field => $file ) { |
||
442 | if( strpos( $field, 'file_upload_' ) !== false ) { |
||
443 | $question_id = str_replace( 'file_upload_', '', $field ); |
||
444 | if( $file && $question_id ) { |
||
445 | $attachment_id = self::upload_file( $file ); |
||
446 | if( $attachment_id ) { |
||
447 | $args = array( |
||
448 | 'post_id' => $question_id, |
||
449 | 'data' => base64_encode( $attachment_id ), |
||
450 | 'type' => 'sensei_user_answer', /* FIELD SIZE 20 */ |
||
451 | 'user_id' => $user_id, |
||
452 | 'action' => 'update' |
||
453 | ); |
||
454 | $answers_saved = Sensei_Utils::sensei_log_activity( $args ); |
||
455 | } |
||
456 | } |
||
457 | } |
||
458 | } |
||
459 | } |
||
460 | } |
||
461 | |||
462 | return $answers_saved; |
||
463 | |||
464 | } // End sensei_save_quiz_answers() |
||
465 | |||
466 | public static function upload_file( $file = array() ) { |
||
467 | |||
468 | require_once( ABSPATH . 'wp-admin/includes/admin.php' ); |
||
469 | |||
470 | /** |
||
471 | * Filter the data array for the Sensei wp_handle_upload function call |
||
472 | * |
||
473 | * This filter was mainly added for Unit Testing purposes. |
||
474 | * |
||
475 | * @since 1.7.4 |
||
476 | * |
||
477 | * @param array $file_upload_args { |
||
478 | * array of current values |
||
479 | * |
||
480 | * @type string test_form set to false by default |
||
481 | * } |
||
482 | */ |
||
483 | $file_upload_args = apply_filters( 'sensei_file_upload_args', array('test_form' => false ) ); |
||
484 | |||
485 | $file_return = wp_handle_upload( $file, $file_upload_args ); |
||
486 | |||
487 | if( isset( $file_return['error'] ) || isset( $file_return['upload_error_handler'] ) ) { |
||
488 | return false; |
||
489 | } else { |
||
490 | |||
491 | $filename = $file_return['file']; |
||
492 | |||
493 | $attachment = array( |
||
494 | 'post_mime_type' => $file_return['type'], |
||
495 | 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ), |
||
496 | 'post_content' => '', |
||
497 | 'post_status' => 'inherit', |
||
498 | 'guid' => $file_return['url'] |
||
499 | ); |
||
500 | |||
501 | $attachment_id = wp_insert_attachment( $attachment, $filename ); |
||
502 | |||
503 | require_once(ABSPATH . 'wp-admin/includes/image.php'); |
||
504 | $attachment_data = wp_generate_attachment_metadata( $attachment_id, $filename ); |
||
505 | wp_update_attachment_metadata( $attachment_id, $attachment_data ); |
||
506 | |||
507 | if( 0 < intval( $attachment_id ) ) { |
||
508 | return $attachment_id; |
||
509 | } |
||
510 | } |
||
511 | |||
512 | return false; |
||
513 | } |
||
514 | |||
515 | /** |
||
516 | * Grade quiz automatically |
||
517 | * |
||
518 | * This function grades each question automatically if the are auto gradable. |
||
519 | * It store all question grades. |
||
520 | * |
||
521 | * @deprecated since 1.7.4 use WooThemes_Sensei_Grading::grade_quiz_auto instead |
||
522 | * |
||
523 | * @param integer $quiz_id ID of quiz |
||
524 | * @param array $submitted questions id ans answers { |
||
525 | * @type int $question_id |
||
526 | * @type mixed $answer |
||
527 | * } |
||
528 | * @param integer $total_questions Total questions in quiz (not used) |
||
529 | * @param string $quiz_grade_type Optional defaults to auto |
||
530 | * |
||
531 | * @return int $quiz_grade total sum of all question grades |
||
532 | */ |
||
533 | public static function sensei_grade_quiz_auto( $quiz_id = 0, $submitted = array(), $total_questions = 0, $quiz_grade_type = 'auto' ) { |
||
534 | |||
535 | return Sensei_Grading::grade_quiz_auto( $quiz_id, $submitted, $total_questions, $quiz_grade_type ); |
||
536 | |||
537 | } // End sensei_grade_quiz_auto() |
||
538 | |||
539 | /** |
||
540 | * Grade quiz |
||
541 | * @param integer $quiz_id ID of quiz |
||
542 | * @param integer $grade Grade received |
||
543 | * @param integer $user_id ID of user being graded |
||
544 | * @param string $quiz_grade_type default 'auto' |
||
545 | * @return boolean |
||
546 | */ |
||
547 | public static function sensei_grade_quiz( $quiz_id = 0, $grade = 0, $user_id = 0, $quiz_grade_type = 'auto' ) { |
||
548 | if( intval( $user_id ) == 0 ) { |
||
549 | $user_id = get_current_user_id(); |
||
550 | } |
||
551 | |||
552 | $activity_logged = false; |
||
553 | if( intval( $quiz_id ) > 0 && intval( $user_id ) > 0 ) { |
||
554 | $lesson_id = get_post_meta( $quiz_id, '_quiz_lesson', true ); |
||
555 | $user_lesson_status = Sensei_Utils::user_lesson_status( $lesson_id, $user_id ); |
||
556 | $activity_logged = update_comment_meta( $user_lesson_status->comment_ID, 'grade', $grade ); |
||
557 | |||
558 | $quiz_passmark = absint( get_post_meta( $quiz_id, '_quiz_passmark', true ) ); |
||
559 | |||
560 | do_action( 'sensei_user_quiz_grade', $user_id, $quiz_id, $grade, $quiz_passmark, $quiz_grade_type ); |
||
561 | } |
||
562 | |||
563 | return $activity_logged; |
||
564 | } |
||
565 | |||
566 | /** |
||
567 | * Grade question automatically |
||
568 | * |
||
569 | * This function checks the question typ and then grades it accordingly. |
||
570 | * |
||
571 | * @deprecated since 1.7.4 use WooThemes_Sensei_Grading::grade_question_auto instead |
||
572 | * |
||
573 | * @param integer $question_id |
||
574 | * @param string $question_type of the standard Sensei question types |
||
575 | * @param string $answer |
||
576 | * @param int $user_id |
||
577 | * |
||
578 | * @return int $question_grade |
||
579 | */ |
||
580 | public static function sensei_grade_question_auto( $question_id = 0, $question_type = '', $answer = '', $user_id = 0 ) { |
||
581 | |||
582 | return WooThemes_Sensei_Grading::grade_question_auto( $question_id, $question_type, $answer, $user_id ); |
||
583 | |||
584 | } // end sensei_grade_question_auto |
||
585 | |||
586 | /** |
||
587 | * Grade question |
||
588 | * @param integer $question_id ID of question |
||
589 | * @param integer $grade Grade received |
||
590 | * @param int $user_id |
||
591 | * @return boolean |
||
592 | */ |
||
593 | public static function sensei_grade_question( $question_id = 0, $grade = 0, $user_id = 0 ) { |
||
594 | if( intval( $user_id ) == 0 ) { |
||
595 | $user_id = get_current_user_id(); |
||
596 | } |
||
597 | |||
598 | $activity_logged = false; |
||
599 | if( intval( $question_id ) > 0 && intval( $user_id ) > 0 ) { |
||
600 | |||
601 | $user_answer_id = Sensei_Utils::sensei_get_activity_value( array( 'post_id' => $question_id, 'user_id' => $user_id, 'type' => 'sensei_user_answer', 'field' => 'comment_ID' ) ); |
||
602 | $activity_logged = update_comment_meta( $user_answer_id, 'user_grade', $grade ); |
||
603 | |||
604 | $answer_notes = get_post_meta( $question_id, '_answer_feedback', true ); |
||
605 | if ( !empty($answer_notes) ) { |
||
606 | update_comment_meta( $user_answer_id, 'answer_note', base64_encode( $answer_notes ) ); |
||
607 | } |
||
608 | |||
609 | } |
||
610 | |||
611 | return $activity_logged; |
||
612 | } |
||
613 | |||
614 | public static function sensei_delete_question_grade( $question_id = 0, $user_id = 0 ) { |
||
615 | if( intval( $user_id ) == 0 ) { |
||
616 | $user_id = get_current_user_id(); |
||
617 | } |
||
618 | |||
619 | $activity_logged = false; |
||
620 | if( intval( $question_id ) > 0 ) { |
||
621 | $user_answer_id = Sensei_Utils::sensei_get_activity_value( array( 'post_id' => $question_id, 'user_id' => $user_id, 'type' => 'sensei_user_answer', 'field' => 'comment_ID' ) ); |
||
622 | $activity_logged = delete_comment_meta( $user_answer_id, 'user_grade' ); |
||
623 | } |
||
624 | |||
625 | return $activity_logged; |
||
626 | } |
||
627 | |||
628 | |||
629 | /** |
||
630 | * Alias to Woothemes_Sensei_Utils::sensei_start_lesson |
||
631 | * |
||
632 | * @since 1.7.4 |
||
633 | * |
||
634 | * @param integer $user_id |
||
635 | * @param integer $lesson_id |
||
636 | * @param bool $complete |
||
637 | * |
||
638 | * @return mixed boolean or comment_ID |
||
639 | */ |
||
640 | public static function user_start_lesson( $user_id = 0, $lesson_id = 0, $complete = false ) { |
||
641 | |||
642 | return self::sensei_start_lesson( $lesson_id, $user_id, $complete ); |
||
643 | |||
644 | }// end user_start_lesson() |
||
645 | |||
646 | /** |
||
647 | * Mark a lesson as started for user |
||
648 | * |
||
649 | * Will also start the lesson course for the user if the user hans't started taking it already. |
||
650 | * |
||
651 | * @since 1.6.0 |
||
652 | * |
||
653 | * @param integer $lesson_id ID of lesson |
||
654 | * @param int| string $user_id default 0 |
||
655 | * @param bool $complete default false |
||
656 | * |
||
657 | * @return mixed boolean or comment_ID |
||
658 | */ |
||
659 | public static function sensei_start_lesson( $lesson_id = 0, $user_id = 0, $complete = false ) { |
||
660 | |||
661 | |||
662 | if( intval( $user_id ) == 0 ) { |
||
663 | $user_id = get_current_user_id(); |
||
664 | } |
||
665 | |||
666 | $activity_logged = false; |
||
667 | |||
668 | if( intval( $lesson_id ) > 0 ) { |
||
669 | |||
670 | $course_id = get_post_meta( $lesson_id, '_lesson_course', true ); |
||
671 | if( $course_id ) { |
||
672 | $is_user_taking_course = Sensei_Utils::user_started_course( $course_id, $user_id ); |
||
673 | if( ! $is_user_taking_course ) { |
||
674 | Sensei_Utils::user_start_course( $user_id, $course_id ); |
||
675 | } |
||
676 | } |
||
677 | |||
678 | $metadata = array(); |
||
679 | $status = 'in-progress'; |
||
680 | |||
681 | // Note: When this action runs the lesson status may not yet exist |
||
682 | do_action( 'sensei_user_lesson_start', $user_id, $lesson_id ); |
||
683 | |||
684 | if( $complete ) { |
||
685 | |||
686 | $has_questions = get_post_meta( $lesson_id, '_quiz_has_questions', true ); |
||
687 | if ( $has_questions ) { |
||
688 | $status = 'passed'; // Force a pass |
||
689 | $metadata['grade'] = 0; |
||
690 | } |
||
691 | else { |
||
692 | $status = 'complete'; |
||
693 | } |
||
694 | } |
||
695 | |||
696 | // Check if user is already taking the lesson |
||
697 | $activity_logged = Sensei_Utils::user_started_lesson( $lesson_id, $user_id ); |
||
698 | if( ! $activity_logged ) { |
||
699 | |||
700 | $metadata['start'] = current_time('mysql'); |
||
701 | $activity_logged = Sensei_Utils::update_lesson_status( $user_id, $lesson_id, $status, $metadata ); |
||
702 | |||
703 | } else { |
||
704 | |||
705 | // if users is already taking the lesson and the status changes to complete update it |
||
706 | $current_user_activity = get_comment($activity_logged); |
||
707 | if( $status=='complete' && |
||
708 | $status != $current_user_activity->comment_approved ){ |
||
709 | |||
710 | $comment = array(); |
||
711 | $comment['comment_ID'] = $activity_logged; |
||
712 | $comment['comment_approved'] = $status; |
||
713 | wp_update_comment( $comment ); |
||
714 | |||
715 | } |
||
716 | |||
717 | } |
||
718 | |||
719 | if ( $complete ) { |
||
720 | // Run this *after* the lesson status has been created/updated |
||
721 | do_action( 'sensei_user_lesson_end', $user_id, $lesson_id ); |
||
722 | } |
||
723 | |||
724 | } |
||
725 | |||
726 | return $activity_logged; |
||
727 | } |
||
728 | |||
729 | /** |
||
730 | * Remove user from lesson, deleting all data from the corresponding quiz |
||
731 | * |
||
732 | * @param int $lesson_id |
||
733 | * @param int $user_id |
||
734 | * @return boolean |
||
735 | */ |
||
736 | public static function sensei_remove_user_from_lesson( $lesson_id = 0, $user_id = 0, $from_course = false ) { |
||
737 | |||
738 | if( ! $lesson_id ) return false; |
||
739 | |||
740 | if( intval( $user_id ) == 0 ) { |
||
741 | $user_id = get_current_user_id(); |
||
742 | } |
||
743 | |||
744 | // Process quiz |
||
745 | $lesson_quiz_id = Sensei()->lesson->lesson_quizzes( $lesson_id ); |
||
746 | |||
747 | // Delete quiz answers, this auto deletes the corresponding meta data, such as the question/answer grade |
||
748 | Sensei_Utils::sensei_delete_quiz_answers( $lesson_quiz_id, $user_id ); |
||
749 | |||
750 | |||
751 | // Delete quiz saved answers |
||
752 | Sensei()->quiz->reset_user_lesson_data( $lesson_id, $user_id ); |
||
753 | |||
754 | // Delete lesson status |
||
755 | $args = array( |
||
756 | 'post_id' => $lesson_id, |
||
757 | 'type' => 'sensei_lesson_status', |
||
758 | 'user_id' => $user_id, |
||
759 | ); |
||
760 | // This auto deletes the corresponding meta data, such as the quiz grade, and questions asked |
||
761 | Sensei_Utils::sensei_delete_activities( $args ); |
||
762 | |||
763 | if( ! $from_course ) { |
||
764 | do_action( 'sensei_user_lesson_reset', $user_id, $lesson_id ); |
||
765 | } |
||
766 | |||
767 | return true; |
||
768 | } |
||
769 | |||
770 | /** |
||
771 | * Remove a user from a course, deleting all activities across all lessons |
||
772 | * |
||
773 | * @param int $course_id |
||
774 | * @param int $user_id |
||
775 | * @return boolean |
||
776 | */ |
||
777 | public static function sensei_remove_user_from_course( $course_id = 0, $user_id = 0 ) { |
||
778 | |||
779 | |||
780 | if( ! $course_id ) return false; |
||
781 | |||
782 | if( intval( $user_id ) == 0 ) { |
||
783 | $user_id = get_current_user_id(); |
||
784 | } |
||
785 | |||
786 | $lesson_ids = Sensei()->course->course_lessons( $course_id, 'any', 'ids' ); |
||
787 | |||
788 | foreach( $lesson_ids as $lesson_id ) { |
||
789 | Sensei_Utils::sensei_remove_user_from_lesson( $lesson_id, $user_id, true ); |
||
790 | } |
||
791 | |||
792 | // Delete course status |
||
793 | $args = array( |
||
794 | 'post_id' => $course_id, |
||
795 | 'type' => 'sensei_course_status', |
||
796 | 'user_id' => $user_id, |
||
797 | ); |
||
798 | |||
799 | Sensei_Utils::sensei_delete_activities( $args ); |
||
800 | |||
801 | do_action( 'sensei_user_course_reset', $user_id, $course_id ); |
||
802 | |||
803 | return true; |
||
804 | } |
||
805 | |||
806 | public static function sensei_get_quiz_questions( $quiz_id = 0 ) { |
||
807 | |||
808 | |||
809 | $questions = array(); |
||
810 | |||
811 | if( intval( $quiz_id ) > 0 ) { |
||
812 | $questions = Sensei()->lesson->lesson_quiz_questions( $quiz_id ); |
||
813 | $questions = Sensei_Utils::array_sort_reorder( $questions ); |
||
814 | } |
||
815 | |||
816 | return $questions; |
||
817 | } |
||
818 | |||
819 | public static function sensei_get_quiz_total( $quiz_id = 0 ) { |
||
820 | |||
821 | |||
822 | $quiz_total = 0; |
||
823 | |||
824 | if( $quiz_id > 0 ) { |
||
825 | $questions = Sensei_Utils::sensei_get_quiz_questions( $quiz_id ); |
||
826 | $question_grade = 0; |
||
827 | foreach( $questions as $question ) { |
||
828 | $question_grade = Sensei()->question->get_question_grade( $question->ID ); |
||
829 | $quiz_total += $question_grade; |
||
830 | } |
||
831 | } |
||
832 | |||
833 | return $quiz_total; |
||
834 | } |
||
835 | |||
836 | /** |
||
837 | * Returns the user_grade for a specific question and user, or sensei_user_answer entry |
||
838 | * |
||
839 | * @param mixed $question |
||
840 | * @param int $user_id |
||
841 | * @return string |
||
842 | */ |
||
843 | View Code Duplication | public static function sensei_get_user_question_grade( $question = 0, $user_id = 0 ) { |
|
844 | $question_grade = false; |
||
845 | if( $question ) { |
||
846 | if ( is_object( $question ) ) { |
||
847 | $user_answer_id = $question->comment_ID; |
||
848 | } |
||
849 | else { |
||
850 | if( intval( $user_id ) == 0 ) { |
||
851 | $user_id = get_current_user_id(); |
||
852 | } |
||
853 | $user_answer_id = Sensei_Utils::sensei_get_activity_value( array( 'post_id' => intval($question), 'user_id' => $user_id, 'type' => 'sensei_user_answer', 'field' => 'comment_ID' ) ); |
||
854 | } |
||
855 | if ( $user_answer_id ) { |
||
856 | $question_grade = get_comment_meta( $user_answer_id, 'user_grade', true ); |
||
857 | } |
||
858 | } |
||
859 | |||
860 | return $question_grade; |
||
861 | } |
||
862 | |||
863 | /** |
||
864 | * Returns the answer_notes for a specific question and user, or sensei_user_answer entry |
||
865 | * |
||
866 | * @deprecated since 1.7.5 use Sensei()->quiz->get_user_question_feedback instead |
||
867 | * @param mixed $question |
||
868 | * @param int $user_id |
||
869 | * @return string |
||
870 | */ |
||
871 | View Code Duplication | public static function sensei_get_user_question_answer_notes( $question = 0, $user_id = 0 ) { |
|
872 | $answer_notes = false; |
||
873 | if( $question ) { |
||
874 | if ( is_object( $question ) ) { |
||
875 | $user_answer_id = $question->comment_ID; |
||
876 | } |
||
877 | else { |
||
878 | if( intval( $user_id ) == 0 ) { |
||
879 | $user_id = get_current_user_id(); |
||
880 | } |
||
881 | $user_answer_id = Sensei_Utils::sensei_get_activity_value( array( 'post_id' => intval($question), 'user_id' => $user_id, 'type' => 'sensei_user_answer', 'field' => 'comment_ID' ) ); |
||
882 | } |
||
883 | if ( $user_answer_id ) { |
||
884 | $answer_notes = base64_decode( get_comment_meta( $user_answer_id, 'answer_note', true ) ); |
||
885 | } |
||
886 | } |
||
887 | |||
888 | return $answer_notes; |
||
889 | } |
||
890 | |||
891 | public static function sensei_delete_quiz_answers( $quiz_id = 0, $user_id = 0 ) { |
||
892 | if( intval( $user_id ) == 0 ) { |
||
893 | $user_id = get_current_user_id(); |
||
894 | } |
||
895 | |||
896 | $delete_answers = false; |
||
897 | if( intval( $quiz_id ) > 0 ) { |
||
898 | $questions = Sensei_Utils::sensei_get_quiz_questions( $quiz_id ); |
||
899 | foreach( $questions as $question ) { |
||
900 | $delete_answers = Sensei_Utils::sensei_delete_activities( array( 'post_id' => $question->ID, 'user_id' => $user_id, 'type' => 'sensei_user_answer' ) ); |
||
901 | } |
||
902 | } |
||
903 | |||
904 | return $delete_answers; |
||
905 | } |
||
906 | |||
907 | public static function sensei_delete_quiz_grade( $quiz_id = 0, $user_id = 0 ) { |
||
908 | if( intval( $user_id ) == 0 ) { |
||
909 | $user_id = get_current_user_id(); |
||
910 | } |
||
911 | |||
912 | $delete_grade = false; |
||
913 | if( intval( $quiz_id ) > 0 ) { |
||
914 | $lesson_id = get_post_meta( $quiz_id, '_quiz_lesson', true ); |
||
915 | $user_lesson_status = Sensei_Utils::user_lesson_status( $lesson_id, $user_id ); |
||
916 | $delete_grade = delete_comment_meta( $user_lesson_status->comment_ID, 'grade' ); |
||
917 | } |
||
918 | |||
919 | return $delete_grade; |
||
920 | } |
||
921 | |||
922 | /** |
||
923 | * Add answer notes to question |
||
924 | * @param integer $question_id ID of question |
||
925 | * @param integer $user_id ID of user |
||
926 | * @param string $notes |
||
927 | * @return boolean |
||
928 | */ |
||
929 | public static function sensei_add_answer_notes( $question_id = 0, $user_id = 0, $notes = '' ) { |
||
930 | if( intval( $user_id ) == 0 ) { |
||
931 | $user_id = get_current_user_id(); |
||
932 | } |
||
933 | |||
934 | $activity_logged = false; |
||
935 | |||
936 | if( intval( $question_id ) > 0 ) { |
||
937 | $notes = base64_encode( $notes ); |
||
938 | |||
939 | // Don't store empty values, no point |
||
940 | if ( !empty($notes) ) { |
||
941 | $user_lesson_id = Sensei_Utils::sensei_get_activity_value( array( 'post_id' => $question_id, 'user_id' => $user_id, 'type' => 'sensei_user_answer', 'field' => 'comment_ID' ) ); |
||
942 | $activity_logged = update_comment_meta( $user_lesson_id, 'answer_note', $notes ); |
||
943 | } |
||
944 | else { |
||
945 | $activity_logged = true; |
||
946 | } |
||
947 | } |
||
948 | |||
949 | return $activity_logged; |
||
950 | } |
||
951 | |||
952 | /** |
||
953 | * array_sort_reorder handle sorting of table data |
||
954 | * @since 1.3.0 |
||
955 | * @param array $return_array data to be ordered |
||
956 | * @return array $return_array ordered data |
||
957 | */ |
||
958 | public static function array_sort_reorder( $return_array ) { |
||
959 | if ( isset( $_GET['orderby'] ) && '' != esc_html( $_GET['orderby'] ) ) { |
||
960 | $sort_key = ''; |
||
961 | // if ( array_key_exists( esc_html( $_GET['orderby'] ), $this->sortable_columns ) ) { |
||
962 | // $sort_key = esc_html( $_GET['orderby'] ); |
||
963 | // } // End If Statement |
||
964 | if ( '' != $sort_key ) { |
||
965 | Sensei_Utils::sort_array_by_key($return_array,$sort_key); |
||
966 | if ( isset( $_GET['order'] ) && 'desc' == esc_html( $_GET['order'] ) ) { |
||
967 | $return_array = array_reverse( $return_array, true ); |
||
968 | } // End If Statement |
||
969 | } // End If Statement |
||
970 | return $return_array; |
||
971 | } else { |
||
972 | return $return_array; |
||
973 | } // End If Statement |
||
974 | } // End array_sort_reorder() |
||
975 | |||
976 | /** |
||
977 | * sort_array_by_key sorts array by key |
||
978 | * @since 1.3.0 |
||
979 | * @param array $array by ref |
||
980 | * @param $key string column name in array |
||
981 | * @return void |
||
982 | */ |
||
983 | public static function sort_array_by_key( $array, $key ) { |
||
984 | $sorter = array(); |
||
985 | $ret = array(); |
||
986 | reset( $array ); |
||
987 | foreach ( $array as $ii => $va ) { |
||
988 | $sorter[$ii] = $va[$key]; |
||
989 | } // End For Loop |
||
990 | asort( $sorter ); |
||
991 | foreach ( $sorter as $ii => $va ) { |
||
992 | $ret[$ii] = $array[$ii]; |
||
993 | } // End For Loop |
||
994 | $array = $ret; |
||
995 | } // End sort_array_by_key() |
||
996 | |||
997 | /** |
||
998 | * This function returns an array of lesson quiz questions |
||
999 | * @since 1.3.2 |
||
1000 | * @param integer $quiz_id |
||
1001 | * @return array of quiz questions |
||
1002 | */ |
||
1003 | View Code Duplication | public static function lesson_quiz_questions( $quiz_id = 0 ) { |
|
1004 | $questions_array = array(); |
||
1005 | if ( 0 < $quiz_id ) { |
||
1006 | $question_args = array( 'post_type' => 'question', |
||
1007 | 'posts_per_page' => -1, |
||
1008 | 'orderby' => 'ID', |
||
1009 | 'order' => 'ASC', |
||
1010 | 'meta_query' => array( |
||
1011 | array( |
||
1012 | 'key' => '_quiz_id', |
||
1013 | 'value' => $quiz_id, |
||
1014 | ) |
||
1015 | ), |
||
1016 | 'post_status' => 'any', |
||
1017 | 'suppress_filters' => 0 |
||
1018 | ); |
||
1019 | $questions_array = get_posts( $question_args ); |
||
1020 | } // End If Statement |
||
1021 | return $questions_array; |
||
1022 | } // End lesson_quiz_questions() |
||
1023 | |||
1024 | /** |
||
1025 | * Get pass mark for course |
||
1026 | * @param integer $course_id ID of course |
||
1027 | * @return integer Pass mark for course |
||
1028 | */ |
||
1029 | public static function sensei_course_pass_grade( $course_id = 0 ) { |
||
1030 | |||
1031 | |||
1032 | $course_passmark = 0; |
||
1033 | |||
1034 | if( $course_id > 0 ) { |
||
1035 | $lessons = Sensei()->course->course_lessons( $course_id ); |
||
1036 | $lesson_count = 0; |
||
1037 | $total_passmark = 0; |
||
1038 | foreach( $lessons as $lesson ) { |
||
1039 | |||
1040 | // Get Quiz ID |
||
1041 | $quiz_id = Sensei()->lesson->lesson_quizzes( $lesson->ID ); |
||
1042 | |||
1043 | // Check for a pass being required |
||
1044 | $pass_required = get_post_meta( $quiz_id, '_pass_required', true ); |
||
1045 | if ( $pass_required ) { |
||
1046 | // Get quiz passmark |
||
1047 | $quiz_passmark = absint( get_post_meta( $quiz_id, '_quiz_passmark', true ) ); |
||
1048 | |||
1049 | // Add up total passmark |
||
1050 | $total_passmark += $quiz_passmark; |
||
1051 | |||
1052 | ++$lesson_count; |
||
1053 | } |
||
1054 | } |
||
1055 | // Might be a case of no required lessons |
||
1056 | if ( $lesson_count ) { |
||
1057 | $course_passmark = ( $total_passmark / $lesson_count ); |
||
1058 | } |
||
1059 | } |
||
1060 | |||
1061 | return Sensei_Utils::round( $course_passmark ); |
||
1062 | } |
||
1063 | |||
1064 | /** |
||
1065 | * Get user total grade for course |
||
1066 | * @param integer $course_id ID of course |
||
1067 | * @param integer $user_id ID of user |
||
1068 | * @return integer User's total grade |
||
1069 | */ |
||
1070 | public static function sensei_course_user_grade( $course_id = 0, $user_id = 0 ) { |
||
1071 | |||
1072 | |||
1073 | if( intval( $user_id ) == 0 ) { |
||
1074 | $user_id = get_current_user_id(); |
||
1075 | } |
||
1076 | |||
1077 | $total_grade = 0; |
||
1078 | |||
1079 | if( $course_id > 0 && $user_id > 0 ) { |
||
1080 | $lessons = Sensei()->course->course_lessons( $course_id ); |
||
1081 | $lesson_count = 0; |
||
1082 | $total_grade = 0; |
||
1083 | foreach( $lessons as $lesson ) { |
||
1084 | |||
1085 | // Check for lesson having questions, thus a quiz, thus having a grade |
||
1086 | $has_questions = get_post_meta( $lesson->ID, '_quiz_has_questions', true ); |
||
1087 | if ( $has_questions ) { |
||
1088 | $user_lesson_status = Sensei_Utils::user_lesson_status( $lesson->ID, $user_id ); |
||
1089 | |||
1090 | if( empty( $user_lesson_status ) ){ |
||
1091 | continue; |
||
1092 | } |
||
1093 | // Get user quiz grade |
||
1094 | $quiz_grade = get_comment_meta( $user_lesson_status->comment_ID, 'grade', true ); |
||
1095 | |||
1096 | // Add up total grade |
||
1097 | $total_grade += $quiz_grade; |
||
1098 | |||
1099 | ++$lesson_count; |
||
1100 | } |
||
1101 | } |
||
1102 | |||
1103 | // Might be a case of no lessons with quizzes |
||
1104 | if ( $lesson_count ) { |
||
1105 | $total_grade = ( $total_grade / $lesson_count ); |
||
1106 | } |
||
1107 | |||
1108 | } |
||
1109 | |||
1110 | return Sensei_Utils::round( $total_grade ); |
||
1111 | } |
||
1112 | |||
1113 | /** |
||
1114 | * Check if user has passed a course |
||
1115 | * @param integer $course_id ID of course |
||
1116 | * @param integer $user_id ID of user |
||
1117 | * @return boolean |
||
1118 | */ |
||
1119 | public static function sensei_user_passed_course( $course_id = 0, $user_id = 0 ) { |
||
1120 | if( intval( $user_id ) == 0 ) { |
||
1121 | $user_id = get_current_user_id(); |
||
1122 | } |
||
1123 | |||
1124 | $pass = false; |
||
1125 | |||
1126 | if( $course_id > 0 && $user_id > 0 ) { |
||
1127 | $passmark = Sensei_Utils::sensei_course_pass_grade( $course_id ); |
||
1128 | $user_grade = Sensei_Utils::sensei_course_user_grade( $course_id, $user_id ); |
||
1129 | |||
1130 | if( $user_grade >= $passmark ) { |
||
1131 | $pass = true; |
||
1132 | } |
||
1133 | } |
||
1134 | |||
1135 | return $pass; // Should add the $passmark and $user_grade as part of the return! |
||
1136 | |||
1137 | } |
||
1138 | |||
1139 | /** |
||
1140 | * Set the status message displayed to the user for a course |
||
1141 | * @param integer $course_id ID of course |
||
1142 | * @param integer $user_id ID of user |
||
1143 | */ |
||
1144 | public static function sensei_user_course_status_message( $course_id = 0, $user_id = 0 ) { |
||
1145 | if( intval( $user_id ) == 0 ) { |
||
1146 | $user_id = get_current_user_id(); |
||
1147 | } |
||
1148 | |||
1149 | $status = 'not_started'; |
||
1150 | $box_class = 'info'; |
||
1151 | $message = __( 'You have not started this course yet.', 'woothemes-sensei' ); |
||
1152 | |||
1153 | if( $course_id > 0 && $user_id > 0 ) { |
||
1154 | |||
1155 | $started_course = Sensei_Utils::user_started_course( $course_id, $user_id ); |
||
1156 | |||
1157 | if( $started_course ) { |
||
1158 | $passmark = Sensei_Utils::sensei_course_pass_grade( $course_id ); // This happens inside sensei_user_passed_course()! |
||
1159 | $user_grade = Sensei_Utils::sensei_course_user_grade( $course_id, $user_id ); // This happens inside sensei_user_passed_course()! |
||
1160 | if( $user_grade >= $passmark ) { |
||
1161 | $status = 'passed'; |
||
1162 | $box_class = 'tick'; |
||
1163 | $message = sprintf( __( 'You have passed this course with a grade of %1$d%%.', 'woothemes-sensei' ), $user_grade ); |
||
1164 | } else { |
||
1165 | $status = 'failed'; |
||
1166 | $box_class = 'alert'; |
||
1167 | $message = sprintf( __( 'You require %1$d%% to pass this course. Your grade is %2$s%%.', 'woothemes-sensei' ), $passmark, $user_grade ); |
||
1168 | } |
||
1169 | } |
||
1170 | |||
1171 | } |
||
1172 | |||
1173 | $message = apply_filters( 'sensei_user_course_status_' . $status, $message ); |
||
1174 | Sensei()->notices->add_notice( $message, $box_class ); |
||
1175 | } |
||
1176 | |||
1177 | /** |
||
1178 | * Set the status message displayed to the user for a quiz |
||
1179 | * @param integer $lesson_id ID of quiz lesson |
||
1180 | * @param integer $user_id ID of user |
||
1181 | * @param bool $is_lesson |
||
1182 | * @return array Status code and message |
||
1183 | */ |
||
1184 | public static function sensei_user_quiz_status_message( $lesson_id = 0, $user_id = 0, $is_lesson = false ) { |
||
1185 | global $current_user; |
||
1186 | if( intval( $user_id ) == 0 ) { |
||
1187 | $user_id = $current_user->ID; |
||
1188 | } |
||
1189 | |||
1190 | $status = 'not_started'; |
||
1191 | $box_class = 'info'; |
||
1192 | $message = __( "You have not taken this lesson's quiz yet", 'woothemes-sensei' ); |
||
1193 | $extra = ''; |
||
1194 | |||
1195 | if( $lesson_id > 0 && $user_id > 0 ) { |
||
1196 | |||
1197 | // Prerequisite lesson |
||
1198 | $prerequisite = get_post_meta( $lesson_id, '_lesson_prerequisite', true ); |
||
1199 | |||
1200 | // Course ID |
||
1201 | $course_id = absint( get_post_meta( $lesson_id, '_lesson_course', true ) ); |
||
1202 | |||
1203 | // Has user started course |
||
1204 | $started_course = Sensei_Utils::user_started_course( $course_id, $user_id ); |
||
1205 | |||
1206 | // Has user completed lesson |
||
1207 | $user_lesson_status = Sensei_Utils::user_lesson_status( $lesson_id, $user_id ); |
||
1208 | $lesson_complete = Sensei_Utils::user_completed_lesson( $user_lesson_status ); |
||
1209 | |||
1210 | // Quiz ID |
||
1211 | $quiz_id = Sensei()->lesson->lesson_quizzes( $lesson_id ); |
||
1212 | |||
1213 | // Quiz grade |
||
1214 | $quiz_grade = 0; |
||
1215 | if ( $user_lesson_status ) { |
||
1216 | $quiz_grade = get_comment_meta( $user_lesson_status->comment_ID, 'grade', true ); |
||
1217 | } |
||
1218 | |||
1219 | // Quiz passmark |
||
1220 | $quiz_passmark = absint( get_post_meta( $quiz_id, '_quiz_passmark', true ) ); |
||
1221 | $quiz_passmark_float = (float) $quiz_passmark; |
||
1222 | |||
1223 | // Pass required |
||
1224 | $pass_required = get_post_meta( $quiz_id, '_pass_required', true ); |
||
1225 | |||
1226 | // Quiz questions |
||
1227 | $has_quiz_questions = get_post_meta( $lesson_id, '_quiz_has_questions', true ); |
||
1228 | |||
1229 | if ( ! $started_course ) { |
||
1230 | |||
1231 | $status = 'not_started_course'; |
||
1232 | $box_class = 'info'; |
||
1233 | $message = sprintf( __( 'Please sign up for %1$sthe course%2$s before taking this quiz', 'woothemes-sensei' ), '<a href="' . esc_url( get_permalink( $course_id ) ) . '" title="' . esc_attr( __( 'Sign Up', 'woothemes-sensei' ) ) . '">', '</a>' ); |
||
1234 | |||
1235 | } elseif ( ! is_user_logged_in() ) { |
||
1236 | |||
1237 | $status = 'login_required'; |
||
1238 | $box_class = 'info'; |
||
1239 | $message = __( 'You must be logged in to take this quiz', 'woothemes-sensei' ); |
||
1240 | |||
1241 | } |
||
1242 | // Lesson/Quiz is marked as complete thus passing any quiz restrictions |
||
1243 | elseif ( $lesson_complete ) { |
||
1244 | |||
1245 | $status = 'passed'; |
||
1246 | $box_class = 'tick'; |
||
1247 | // Lesson status will be "complete" (has no Quiz) |
||
1248 | if ( ! $has_quiz_questions ) { |
||
1249 | $message = sprintf( __( 'Congratulations! You have passed this lesson.', 'woothemes-sensei' ) ); |
||
1250 | } |
||
1251 | // Lesson status will be "graded" (no passmark required so might have failed all the questions) |
||
1252 | elseif ( empty( $quiz_grade ) ) { |
||
1253 | $message = sprintf( __( 'Congratulations! You have completed this lesson.', 'woothemes-sensei' ) ); |
||
1254 | } |
||
1255 | // Lesson status will be "passed" (passmark reached) |
||
1256 | elseif ( ! empty( $quiz_grade ) && abs( $quiz_grade ) >= 0 ) { |
||
1257 | View Code Duplication | if( $is_lesson ) { |
|
1258 | $message = sprintf( __( 'Congratulations! You have passed this lesson\'s quiz achieving %s%%', 'woothemes-sensei' ), Sensei_Utils::round( $quiz_grade ) ); |
||
1259 | } else { |
||
1260 | $message = sprintf( __( 'Congratulations! You have passed this quiz achieving %s%%', 'woothemes-sensei' ), Sensei_Utils::round( $quiz_grade ) ); |
||
1261 | } |
||
1262 | } |
||
1263 | |||
1264 | // add next lesson button |
||
1265 | $nav_id_array = sensei_get_prev_next_lessons( $lesson_id ); |
||
1266 | $next_lesson_id = absint( $nav_id_array['next_lesson'] ); |
||
1267 | |||
1268 | // Output HTML |
||
1269 | if ( ( 0 < $next_lesson_id ) ) { |
||
1270 | $message .= ' ' . '<a class="next-lesson" href="' . esc_url( get_permalink( $next_lesson_id ) ) |
||
1271 | . '" rel="next"><span class="meta-nav"></span>'. __( 'Next Lesson' ,'woothemes-sensei') |
||
1272 | .'</a>'; |
||
1273 | |||
1274 | } |
||
1275 | |||
1276 | } |
||
1277 | // Lesson/Quiz not complete |
||
1278 | else { |
||
1279 | // Lesson/Quiz isn't "complete" instead it's ungraded (previously this "state" meant that it *was* complete) |
||
1280 | if ( isset( $user_lesson_status->comment_approved ) && 'ungraded' == $user_lesson_status->comment_approved ) { |
||
1281 | $status = 'complete'; |
||
1282 | $box_class = 'info'; |
||
1283 | if( $is_lesson ) { |
||
1284 | $message = sprintf( __( 'You have completed this lesson\'s quiz and it will be graded soon. %1$sView the lesson quiz%2$s', 'woothemes-sensei' ), '<a href="' . esc_url( get_permalink( $quiz_id ) ) . '" title="' . esc_attr( get_the_title( $quiz_id ) ) . '">', '</a>' ); |
||
1285 | } else { |
||
1286 | $message = sprintf( __( 'You have completed this quiz and it will be graded soon. You require %1$s%% to pass.', 'woothemes-sensei' ), Sensei_Utils::round( $quiz_passmark ) ); |
||
1287 | } |
||
1288 | } |
||
1289 | // Lesson status must be "failed" |
||
1290 | elseif ( isset( $user_lesson_status->comment_approved ) && 'failed' == $user_lesson_status->comment_approved ) { |
||
1291 | $status = 'failed'; |
||
1292 | $box_class = 'alert'; |
||
1293 | if( $is_lesson ) { |
||
1294 | $message = sprintf( __( 'You require %1$d%% to pass this lesson\'s quiz. Your grade is %2$s%%', 'woothemes-sensei' ), Sensei_Utils::round( $quiz_passmark ), Sensei_Utils::round( $quiz_grade ) ); |
||
1295 | } else { |
||
1296 | $message = sprintf( __( 'You require %1$d%% to pass this quiz. Your grade is %2$s%%', 'woothemes-sensei' ), Sensei_Utils::round( $quiz_passmark ), Sensei_Utils::round( $quiz_grade ) ); |
||
1297 | } |
||
1298 | } |
||
1299 | // Lesson/Quiz requires a pass |
||
1300 | elseif( $pass_required ) { |
||
1301 | $status = 'not_started'; |
||
1302 | $box_class = 'info'; |
||
1303 | View Code Duplication | if( $is_lesson ) { |
|
1304 | $message = sprintf( __( 'You require %1$d%% to pass this lesson\'s quiz.', 'woothemes-sensei' ), Sensei_Utils::round( $quiz_passmark ) ); |
||
1305 | } else { |
||
1306 | $message = sprintf( __( 'You require %1$d%% to pass this quiz.', 'woothemes-sensei' ), Sensei_Utils::round( $quiz_passmark ) ); |
||
1307 | } |
||
1308 | } |
||
1309 | } |
||
1310 | |||
1311 | }else{ |
||
1312 | |||
1313 | $course_id = Sensei()->lesson->get_course_id( $lesson_id ); |
||
1314 | $a_element = '<a href="' . esc_url( get_permalink( $course_id ) ) . '" title="' . __( 'Sign Up', 'woothemes-sensei' ) . '">'; |
||
1315 | $a_element .= __( 'course', 'woothemes-sensei' ); |
||
1316 | $a_element .= '</a>'; |
||
1317 | |||
1318 | if ( Sensei_WC::is_course_purchasable( $course_id ) ){ |
||
1319 | |||
1320 | $message = sprintf( __( 'Please purchase the %1$s before taking this quiz.', 'woothemes-sensei' ), $a_element ); |
||
1321 | |||
1322 | } else { |
||
1323 | |||
1324 | $message = sprintf( __( 'Please sign up for the %1$s before taking this quiz.', 'woothemes-sensei' ), $a_element ); |
||
1325 | |||
1326 | } |
||
1327 | |||
1328 | |||
1329 | } |
||
1330 | |||
1331 | // Legacy filter |
||
1332 | $message = apply_filters( 'sensei_user_quiz_status_' . $status, $message ); |
||
1333 | |||
1334 | if( $is_lesson && ! in_array( $status, array( 'login_required', 'not_started_course' ) ) ) { |
||
1335 | $quiz_id = Sensei()->lesson->lesson_quizzes( $lesson_id ); |
||
1336 | $extra = '<p><a class="button" href="' . esc_url( get_permalink( $quiz_id ) ) . '" title="' . __( 'View the lesson quiz', 'woothemes-sensei' ) . '">' . __( 'View the lesson quiz', 'woothemes-sensei' ) . '</a></p>'; |
||
1337 | } |
||
1338 | |||
1339 | // Filter of all messages |
||
1340 | return apply_filters( 'sensei_user_quiz_status', array( 'status' => $status, 'box_class' => $box_class, 'message' => $message, 'extra' => $extra ), $lesson_id, $user_id, $is_lesson ); |
||
1341 | } |
||
1342 | |||
1343 | /** |
||
1344 | * Start course for user |
||
1345 | * @since 1.4.8 |
||
1346 | * @param integer $user_id User ID |
||
1347 | * @param integer $course_id Course ID |
||
1348 | * @return mixed boolean or comment_ID |
||
1349 | */ |
||
1350 | public static function user_start_course( $user_id = 0, $course_id = 0 ) { |
||
1351 | |||
1352 | $activity_logged = false; |
||
1353 | |||
1354 | if( $user_id && $course_id ) { |
||
1355 | // Check if user is already on the Course |
||
1356 | $activity_logged = Sensei_Utils::user_started_course( $course_id, $user_id ); |
||
1357 | if ( ! $activity_logged ) { |
||
1358 | |||
1359 | // Add user to course |
||
1360 | $course_metadata = array( |
||
1361 | 'start' => current_time('mysql'), |
||
1362 | 'percent' => 0, // No completed lessons yet |
||
1363 | 'complete' => 0, |
||
1364 | ); |
||
1365 | |||
1366 | $activity_logged = Sensei_Utils::update_course_status( $user_id, $course_id, $course_status = 'in-progress', $course_metadata ); |
||
1367 | |||
1368 | // Allow further actions |
||
1369 | if ( $activity_logged ) { |
||
1370 | do_action( 'sensei_user_course_start', $user_id, $course_id ); |
||
1371 | } |
||
1372 | } |
||
1373 | } |
||
1374 | |||
1375 | return $activity_logged; |
||
1376 | } |
||
1377 | |||
1378 | /** |
||
1379 | * Check if a user has started a course or not |
||
1380 | * |
||
1381 | * @since 1.7.0 |
||
1382 | * @param int $course_id |
||
1383 | * @param int $user_id |
||
1384 | * @return mixed false or comment_ID |
||
1385 | */ |
||
1386 | public static function user_started_course( $course_id = 0, $user_id = 0 ) { |
||
1387 | |||
1388 | $user_started_course = false; |
||
1389 | |||
1390 | if( $course_id ) { |
||
1391 | |||
1392 | if( ! $user_id ) { |
||
1393 | $user_id = get_current_user_id(); |
||
1394 | } |
||
1395 | |||
1396 | View Code Duplication | if ( ! $user_id > 0 ) { |
|
1397 | |||
1398 | $user_started_course = false; |
||
1399 | |||
1400 | } else { |
||
1401 | |||
1402 | $activity_args = array( |
||
1403 | 'post_id' => $course_id, |
||
1404 | 'user_id' => $user_id, |
||
1405 | 'type' => 'sensei_course_status', |
||
1406 | 'field' => 'comment_ID' |
||
1407 | ); |
||
1408 | |||
1409 | $user_course_status_id = Sensei_Utils::sensei_get_activity_value( $activity_args ); |
||
1410 | |||
1411 | if ( $user_course_status_id ) { |
||
1412 | |||
1413 | $user_started_course = $user_course_status_id; |
||
1414 | |||
1415 | } |
||
1416 | } |
||
1417 | } |
||
1418 | |||
1419 | /** |
||
1420 | * Filter the user started course value |
||
1421 | * |
||
1422 | * @since 1.9.3 |
||
1423 | * |
||
1424 | * @param bool $user_started_course |
||
1425 | * @param integer $course_id |
||
1426 | */ |
||
1427 | return apply_filters( 'sensei_user_started_course', $user_started_course, $course_id, $user_id ); |
||
1428 | |||
1429 | } |
||
1430 | |||
1431 | /** |
||
1432 | * Checks if a user has completed a course by checking every lesson status |
||
1433 | * |
||
1434 | * @since 1.7.0 |
||
1435 | * @param integer $course_id Course ID |
||
1436 | * @param integer $user_id User ID |
||
1437 | * @return int |
||
1438 | */ |
||
1439 | public static function user_complete_course( $course_id = 0, $user_id = 0 ) { |
||
1440 | global $wp_version; |
||
1441 | |||
1442 | if( $course_id ) { |
||
1443 | if( ! $user_id ) { |
||
1444 | $user_id = get_current_user_id(); |
||
1445 | } |
||
1446 | |||
1447 | $course_status = 'in-progress'; |
||
1448 | $course_metadata = array(); |
||
1449 | $course_completion = Sensei()->settings->settings[ 'course_completion' ]; |
||
1450 | $lessons_completed = $total_lessons = 0; |
||
1451 | $lesson_status_args = array( |
||
1452 | 'user_id' => $user_id, |
||
1453 | 'status' => 'any', |
||
1454 | 'type' => 'sensei_lesson_status', /* FIELD SIZE 20 */ |
||
1455 | ); |
||
1456 | |||
1457 | // Grab all of this Courses' lessons, looping through each... |
||
1458 | $lesson_ids = Sensei()->course->course_lessons( $course_id, 'any', 'ids' ); |
||
1459 | $total_lessons = count( $lesson_ids ); |
||
1460 | // ...if course completion not set to 'passed', and all lessons are complete or graded, |
||
1461 | // ......then all lessons are 'passed' |
||
1462 | // ...else if course completion is set to 'passed', check if each lesson has questions... |
||
1463 | // ......if no questions yet the status is 'complete' |
||
1464 | // .........then the lesson is 'passed' |
||
1465 | // ......else if questions check the lesson status has a grade and that the grade is greater than the lesson passmark |
||
1466 | // .........then the lesson is 'passed' |
||
1467 | // ...if all lessons 'passed' then update the course status to complete |
||
1468 | |||
1469 | // The below checks if a lesson is fully completed, though maybe should be Utils::user_completed_lesson() |
||
1470 | $all_lesson_statuses = array(); |
||
1471 | // In WordPress 4.1 get_comments() allows a single query to cover multiple comment_post_IDs |
||
1472 | if ( version_compare($wp_version, '4.1', '>=') ) { |
||
1473 | $lesson_status_args['post__in'] = $lesson_ids; |
||
1474 | $all_lesson_statuses = Sensei_Utils::sensei_check_for_activity( $lesson_status_args, true ); |
||
1475 | // Need to always return an array, even with only 1 item |
||
1476 | if ( !is_array($all_lesson_statuses) ) { |
||
1477 | $all_lesson_statuses = array( $all_lesson_statuses ); |
||
1478 | } |
||
1479 | } |
||
1480 | // ...otherwise check each one |
||
1481 | else { |
||
1482 | foreach( $lesson_ids as $lesson_id ) { |
||
1483 | $lesson_status_args['post_id'] = $lesson_id; |
||
1484 | $each_lesson_status = Sensei_Utils::sensei_check_for_activity( $lesson_status_args, true ); |
||
1485 | // Check for valid return before using |
||
1486 | if ( !empty($each_lesson_status->comment_approved) ) { |
||
1487 | $all_lesson_statuses[] = $each_lesson_status; |
||
1488 | } |
||
1489 | } |
||
1490 | } |
||
1491 | foreach( $all_lesson_statuses as $lesson_status ) { |
||
1492 | // If lessons are complete without needing quizzes to be passed |
||
1493 | View Code Duplication | if ( 'passed' != $course_completion ) { |
|
1494 | switch ( $lesson_status->comment_approved ) { |
||
1495 | // A user cannot 'complete' a course if a lesson... |
||
1496 | case 'in-progress': // ...is still in progress |
||
1497 | case 'ungraded': // ...hasn't yet been graded |
||
1498 | break; |
||
1499 | |||
1500 | default: |
||
1501 | $lessons_completed++; |
||
1502 | break; |
||
1503 | } |
||
1504 | } |
||
1505 | else { |
||
1506 | switch ( $lesson_status->comment_approved ) { |
||
1507 | case 'complete': // Lesson has no quiz/questions |
||
1508 | case 'graded': // Lesson has quiz, but it's not important what the grade was |
||
1509 | case 'passed': // Lesson has quiz and the user passed |
||
1510 | $lessons_completed++; |
||
1511 | break; |
||
1512 | |||
1513 | // A user cannot 'complete' a course if on a lesson... |
||
1514 | case 'failed': // ...a user failed the passmark on a quiz |
||
1515 | default: |
||
1516 | break; |
||
1517 | } |
||
1518 | } |
||
1519 | } // Each lesson |
||
1520 | if ( $lessons_completed == $total_lessons ) { |
||
1521 | $course_status = 'complete'; |
||
1522 | } |
||
1523 | |||
1524 | // Update meta data on how many lessons have been completed |
||
1525 | $course_metadata['complete'] = $lessons_completed; |
||
1526 | // update the overall percentage of the course lessons complete (or graded) compared to 'in-progress' regardless of the above |
||
1527 | $course_metadata['percent'] = abs( round( ( doubleval( $lessons_completed ) * 100 ) / ( $total_lessons ), 0 ) ); |
||
1528 | |||
1529 | $activity_logged = Sensei_Utils::update_course_status( $user_id, $course_id, $course_status, $course_metadata ); |
||
1530 | |||
1531 | // Allow further actions |
||
1532 | if ( 'complete' == $course_status ) { |
||
1533 | do_action( 'sensei_user_course_end', $user_id, $course_id ); |
||
1534 | } |
||
1535 | return $activity_logged; |
||
1536 | } |
||
1537 | |||
1538 | return false; |
||
1539 | } |
||
1540 | |||
1541 | /** |
||
1542 | * Check if a user has completed a course or not |
||
1543 | * |
||
1544 | * @param int | WP_Post | WP_Comment $course course_id or sensei_course_status entry |
||
1545 | * |
||
1546 | * @param int $user_id |
||
1547 | * @return boolean |
||
1548 | */ |
||
1549 | public static function user_completed_course( $course , $user_id = 0 ) { |
||
1550 | |||
1551 | if( $course ) { |
||
1552 | if ( is_object( $course ) && is_a( $course,'WP_Comment') ) { |
||
1553 | $user_course_status = $course->comment_approved; |
||
1554 | } |
||
1555 | elseif ( !is_numeric( $course ) && ! is_a( $course,'WP_Post') ) { |
||
1556 | $user_course_status = $course; |
||
1557 | } |
||
1558 | else { |
||
1559 | |||
1560 | // check the user_id |
||
1561 | if( ! $user_id ) { |
||
1562 | |||
1563 | $user_id = get_current_user_id(); |
||
1564 | |||
1565 | if( empty( $user_id ) ){ |
||
1566 | |||
1567 | return false; |
||
1568 | |||
1569 | } |
||
1570 | } |
||
1571 | |||
1572 | if( is_a( $course, 'WP_Post' ) ){ |
||
1573 | $course = $course->ID; |
||
1574 | } |
||
1575 | |||
1576 | $user_course_status = Sensei_Utils::user_course_status( $course , $user_id ); |
||
1577 | if( isset( $user_course_status->comment_approved ) ){ |
||
1578 | $user_course_status = $user_course_status->comment_approved; |
||
1579 | } |
||
1580 | |||
1581 | } |
||
1582 | if( $user_course_status && 'complete' == $user_course_status ) { |
||
1583 | return true; |
||
1584 | } |
||
1585 | } |
||
1586 | return false; |
||
1587 | } |
||
1588 | |||
1589 | /** |
||
1590 | * Check if a user has started a lesson or not |
||
1591 | * |
||
1592 | * @since 1.7.0 |
||
1593 | * @param int $lesson_id |
||
1594 | * @param int $user_id |
||
1595 | * @return mixed false or comment_ID |
||
1596 | */ |
||
1597 | public static function user_started_lesson( $lesson_id = 0, $user_id = 0 ) { |
||
1598 | |||
1599 | View Code Duplication | if( $lesson_id ) { |
|
1600 | if( ! $user_id ) { |
||
1601 | $user_id = get_current_user_id(); |
||
1602 | } |
||
1603 | |||
1604 | $activity_args = array( |
||
1605 | 'post_id' => $lesson_id, |
||
1606 | 'user_id' => $user_id, |
||
1607 | 'type' => 'sensei_lesson_status', |
||
1608 | 'field' => 'comment_ID' ); |
||
1609 | |||
1610 | $user_lesson_status_id = Sensei_Utils::sensei_get_activity_value( $activity_args ); |
||
1611 | if( $user_lesson_status_id ) { |
||
1612 | return $user_lesson_status_id; |
||
1613 | } |
||
1614 | } |
||
1615 | return false; |
||
1616 | } |
||
1617 | |||
1618 | /** |
||
1619 | * Check if a user has completed a lesson or not |
||
1620 | * |
||
1621 | * @uses Sensei() |
||
1622 | * @param mixed $lesson lesson_id or sensei_lesson_status entry |
||
1623 | * @param int $user_id |
||
1624 | * @return boolean |
||
1625 | */ |
||
1626 | public static function user_completed_lesson( $lesson = 0, $user_id = 0 ) { |
||
1627 | |||
1628 | if( $lesson ) { |
||
1629 | $lesson_id = 0; |
||
1630 | if ( is_object( $lesson ) ) { |
||
1631 | $user_lesson_status = $lesson->comment_approved; |
||
1632 | $lesson_id = $lesson->comment_post_ID; |
||
1633 | } |
||
1634 | elseif ( ! is_numeric( $lesson ) ) { |
||
1635 | $user_lesson_status = $lesson; |
||
1636 | } |
||
1637 | else { |
||
1638 | if( ! $user_id ) { |
||
1639 | $user_id = get_current_user_id(); |
||
1640 | } |
||
1641 | |||
1642 | // the user is not logged in |
||
1643 | if( ! $user_id > 0 ){ |
||
1644 | return false; |
||
1645 | } |
||
1646 | $_user_lesson_status = Sensei_Utils::user_lesson_status( $lesson, $user_id ); |
||
1647 | |||
1648 | if ( $_user_lesson_status ) { |
||
1649 | $user_lesson_status = $_user_lesson_status->comment_approved; |
||
1650 | } |
||
1651 | else { |
||
1652 | return false; // No status means not complete |
||
1653 | } |
||
1654 | $lesson_id = $lesson; |
||
1655 | } |
||
1656 | if ( 'in-progress' != $user_lesson_status ) { |
||
1657 | // Check for Passed or Completed Setting |
||
1658 | // Should we be checking for the Course completion setting? Surely that should only affect the Course completion, not bypass each Lesson setting |
||
1659 | // $course_completion = Sensei()->settings->settings[ 'course_completion' ]; |
||
1660 | // if ( 'passed' == $course_completion ) { |
||
1661 | switch( $user_lesson_status ) { |
||
1662 | case 'complete': |
||
1663 | case 'graded': |
||
1664 | case 'passed': |
||
1665 | return true; |
||
1666 | break; |
||
1667 | |||
1668 | case 'failed': |
||
1669 | // This may be 'completed' depending on... |
||
1670 | if ( $lesson_id ) { |
||
1671 | // Get Quiz ID, this won't be needed once all Quiz meta fields are stored on the Lesson |
||
1672 | $lesson_quiz_id = Sensei()->lesson->lesson_quizzes( $lesson_id ); |
||
1673 | if ( $lesson_quiz_id ) { |
||
1674 | // ...the quiz pass setting |
||
1675 | $pass_required = get_post_meta( $lesson_quiz_id, '_pass_required', true ); |
||
1676 | if ( empty($pass_required) ) { |
||
1677 | // We just require the user to have done the quiz, not to have passed |
||
1678 | return true; |
||
1679 | } |
||
1680 | } |
||
1681 | } |
||
1682 | return false; |
||
1683 | break; |
||
1684 | } |
||
1685 | } // End If Statement |
||
1686 | } |
||
1687 | |||
1688 | return false; |
||
1689 | } |
||
1690 | |||
1691 | /** |
||
1692 | * Returns the requested course status |
||
1693 | * |
||
1694 | * @since 1.7.0 |
||
1695 | * @param int $course_id |
||
1696 | * @param int $user_id |
||
1697 | * @return object |
||
1698 | */ |
||
1699 | public static function user_course_status( $course_id = 0, $user_id = 0 ) { |
||
1700 | |||
1701 | |||
1702 | if( $course_id ) { |
||
1703 | if( ! $user_id ) { |
||
1704 | $user_id = get_current_user_id(); |
||
1705 | } |
||
1706 | |||
1707 | $user_course_status = Sensei_Utils::sensei_check_for_activity( array( 'post_id' => $course_id, 'user_id' => $user_id, 'type' => 'sensei_course_status' ), true ); |
||
1708 | return $user_course_status; |
||
1709 | } |
||
1710 | |||
1711 | return false; |
||
1712 | } |
||
1713 | |||
1714 | /** |
||
1715 | * Returns the requested lesson status |
||
1716 | * |
||
1717 | * @since 1.7.0 |
||
1718 | * @param int $lesson_id |
||
1719 | * @param int $user_id |
||
1720 | * @return object | bool |
||
1721 | */ |
||
1722 | public static function user_lesson_status( $lesson_id = 0, $user_id = 0 ) { |
||
1723 | |||
1724 | if( ! $user_id ) { |
||
1725 | $user_id = get_current_user_id(); |
||
1726 | } |
||
1727 | |||
1728 | if( $lesson_id > 0 && $user_id > 0 ) { |
||
1729 | |||
1730 | $user_lesson_status = Sensei_Utils::sensei_check_for_activity( array( 'post_id' => $lesson_id, 'user_id' => $user_id, 'type' => 'sensei_lesson_status' ), true ); |
||
1731 | return $user_lesson_status; |
||
1732 | } |
||
1733 | |||
1734 | return false; |
||
1735 | } |
||
1736 | |||
1737 | public static function is_preview_lesson( $lesson_id ) { |
||
1738 | $is_preview = false; |
||
1739 | |||
1740 | if( 'lesson' == get_post_type( $lesson_id ) ) { |
||
1741 | $lesson_preview = get_post_meta( $lesson_id, '_lesson_preview', true ); |
||
1742 | if ( isset( $lesson_preview ) && '' != $lesson_preview ) { |
||
1743 | $is_preview = true; |
||
1744 | } |
||
1745 | } |
||
1746 | |||
1747 | return $is_preview; |
||
1748 | } |
||
1749 | |||
1750 | public static function user_passed_quiz( $quiz_id = 0, $user_id = 0 ) { |
||
1751 | |||
1752 | if( ! $quiz_id ) return false; |
||
1753 | |||
1754 | if( ! $user_id ) { |
||
1755 | $user_id = get_current_user_id(); |
||
1756 | } |
||
1757 | $lesson_id = get_post_meta( $quiz_id, '_quiz_lesson', true ); |
||
1758 | |||
1759 | // Quiz Grade |
||
1760 | $lesson_status = Sensei_Utils::user_lesson_status( $lesson_id, $user_id ); |
||
1761 | $quiz_grade = get_comment_meta( $lesson_status->comment_ID, 'grade', true ); |
||
1762 | |||
1763 | // Check if Grade is greater than or equal to pass percentage |
||
1764 | $quiz_passmark = abs( round( doubleval( get_post_meta( $quiz_id, '_quiz_passmark', true ) ), 2 ) ); |
||
1765 | if ( $quiz_passmark <= intval( $quiz_grade ) ) { |
||
1766 | return true; |
||
1767 | } |
||
1768 | |||
1769 | return false; |
||
1770 | |||
1771 | } |
||
1772 | |||
1773 | /** |
||
1774 | * Sets the status for the lesson |
||
1775 | * |
||
1776 | * @since 1.7.0 |
||
1777 | * |
||
1778 | * @param int|string $user_id |
||
1779 | * @param int|string $lesson_id |
||
1780 | * @param string $status |
||
1781 | * @param array $metadata |
||
1782 | * |
||
1783 | * @return mixed false or comment_ID |
||
1784 | */ |
||
1785 | View Code Duplication | public static function update_lesson_status( $user_id, $lesson_id, $status = 'in-progress', $metadata = array() ) { |
|
1786 | $comment_id = false; |
||
1787 | if ( !empty($status) ) { |
||
1788 | $args = array( |
||
1789 | 'user_id' => $user_id, |
||
1790 | 'post_id' => $lesson_id, |
||
1791 | 'status' => $status, |
||
1792 | 'type' => 'sensei_lesson_status', /* FIELD SIZE 20 */ |
||
1793 | 'action' => 'update', // Update the existing status... |
||
1794 | 'keep_time' => true, // ...but don't change the existing timestamp |
||
1795 | ); |
||
1796 | if( 'in-progress' == $status ) { |
||
1797 | unset( $args['keep_time'] ); // Keep updating what's happened |
||
1798 | } |
||
1799 | |||
1800 | $comment_id = Sensei_Utils::sensei_log_activity( $args ); |
||
1801 | if ( $comment_id && !empty($metadata) ) { |
||
1802 | foreach( $metadata as $key => $value ) { |
||
1803 | update_comment_meta( $comment_id, $key, $value ); |
||
1804 | } |
||
1805 | } |
||
1806 | |||
1807 | do_action( 'sensei_lesson_status_updated', $status, $user_id, $lesson_id, $comment_id ); |
||
1808 | } |
||
1809 | return $comment_id; |
||
1810 | } |
||
1811 | |||
1812 | /** |
||
1813 | * Sets the statuses for the Course |
||
1814 | * |
||
1815 | * @access public |
||
1816 | * @since 1.7.0 |
||
1817 | * @param int $user_id |
||
1818 | * @param int $course_id |
||
1819 | * @param string $status |
||
1820 | * @param array $metadata |
||
1821 | * @return mixed false or comment_ID |
||
1822 | */ |
||
1823 | View Code Duplication | public static function update_course_status( $user_id, $course_id, $status = 'in-progress', $metadata = array() ) { |
|
1824 | $comment_id = false; |
||
1825 | if ( !empty($status) ) { |
||
1826 | $args = array( |
||
1827 | 'user_id' => $user_id, |
||
1828 | 'post_id' => $course_id, |
||
1829 | 'status' => $status, |
||
1830 | 'type' => 'sensei_course_status', /* FIELD SIZE 20 */ |
||
1831 | 'action' => 'update', // Update the existing status... |
||
1832 | 'keep_time' => true, // ...but don't change the existing timestamp |
||
1833 | ); |
||
1834 | if( 'in-progress' == $status ) { |
||
1835 | unset( $args['keep_time'] ); // Keep updating what's happened |
||
1836 | } |
||
1837 | |||
1838 | $comment_id = Sensei_Utils::sensei_log_activity( $args ); |
||
1839 | if ( $comment_id && !empty($metadata) ) { |
||
1840 | foreach( $metadata as $key => $value ) { |
||
1841 | update_comment_meta( $comment_id, $key, $value ); |
||
1842 | } |
||
1843 | } |
||
1844 | do_action( 'sensei_course_status_updated', $status, $user_id, $course_id, $comment_id ); |
||
1845 | } |
||
1846 | return $comment_id; |
||
1847 | } |
||
1848 | |||
1849 | /** |
||
1850 | * Remove the orderby for comments |
||
1851 | * @access public |
||
1852 | * @since 1.7.0 |
||
1853 | * @param array $pieces (default: array()) |
||
1854 | * @return array |
||
1855 | */ |
||
1856 | public static function single_comment_filter( $pieces ) { |
||
1857 | unset( $pieces['orderby'] ); |
||
1858 | unset( $pieces['order'] ); |
||
1859 | |||
1860 | return $pieces; |
||
1861 | } |
||
1862 | |||
1863 | /** |
||
1864 | * Allow retrieving comments with any comment_approved status, little bypass to WP_Comment. Required only for WP < 4.1 |
||
1865 | * @access public |
||
1866 | * @since 1.7.0 |
||
1867 | * @param array $pieces (default: array()) |
||
1868 | * @return array |
||
1869 | */ |
||
1870 | public static function comment_any_status_filter( $pieces ) { |
||
1871 | |||
1872 | $pieces['where'] = str_replace( array( "( comment_approved = '0' OR comment_approved = '1' ) AND", "comment_approved = 'any' AND" ), '', $pieces['where'] ); |
||
1873 | |||
1874 | return $pieces; |
||
1875 | } |
||
1876 | |||
1877 | /** |
||
1878 | * Allow retrieving comments within multiple statuses, little bypass to WP_Comment. Required only for WP < 4.1 |
||
1879 | * @access public |
||
1880 | * @since 1.7.0 |
||
1881 | * @param array $pieces (default: array()) |
||
1882 | * @return array |
||
1883 | */ |
||
1884 | public static function comment_multiple_status_filter( $pieces ) { |
||
1885 | |||
1886 | preg_match( "/^comment_approved = '([a-z\-\,]+)'/", $pieces['where'], $placeholder ); |
||
1887 | if ( !empty($placeholder[1]) ) { |
||
1888 | $statuses = explode( ',', $placeholder[1] ); |
||
1889 | $pieces['where'] = str_replace( "comment_approved = '" . $placeholder[1] . "'", "comment_approved IN ('". implode( "', '", $statuses ) . "')", $pieces['where'] ); |
||
1890 | } |
||
1891 | |||
1892 | return $pieces; |
||
1893 | } |
||
1894 | |||
1895 | /** |
||
1896 | * Adjust the comment query to be faster on the database, used by Analysis admin |
||
1897 | * @since 1.7.0 |
||
1898 | * @param array $pieces |
||
1899 | * @return array $pieces |
||
1900 | */ |
||
1901 | View Code Duplication | public static function comment_total_sum_meta_value_filter( $pieces ) { |
|
1902 | global $wpdb, $wp_version; |
||
1903 | |||
1904 | $pieces['fields'] = " COUNT(*) AS total, SUM($wpdb->commentmeta.meta_value) AS meta_sum "; |
||
1905 | unset( $pieces['groupby'] ); |
||
1906 | if ( version_compare($wp_version, '4.1', '>=') ) { |
||
1907 | $args['order'] = false; |
||
1908 | $args['orderby'] = false; |
||
1909 | } |
||
1910 | |||
1911 | return $pieces; |
||
1912 | } |
||
1913 | |||
1914 | /** |
||
1915 | * Shifts counting of posts to the database where it should be. Likely not to be used due to knock on issues. |
||
1916 | * @access public |
||
1917 | * @since 1.7.0 |
||
1918 | * @param array $pieces (default: array()) |
||
1919 | * @return array |
||
1920 | */ |
||
1921 | View Code Duplication | public static function get_posts_count_only_filter( $pieces ) { |
|
1922 | global $wp_version; |
||
1923 | |||
1924 | $pieces['fields'] = " COUNT(*) AS total "; |
||
1925 | unset( $pieces['groupby'] ); |
||
1926 | if ( version_compare($wp_version, '4.1', '>=') ) { |
||
1927 | $args['order'] = false; |
||
1928 | $args['orderby'] = false; |
||
1929 | } |
||
1930 | return $pieces; |
||
1931 | } |
||
1932 | |||
1933 | /** |
||
1934 | * |
||
1935 | * Alias to Woothemes_Sensei_Utils::update_user_data |
||
1936 | * @since 1.7.4 |
||
1937 | * |
||
1938 | * @param string $data_key maximum 39 characters allowed |
||
1939 | * @param int $post_id |
||
1940 | * @param mixed $value |
||
1941 | * @param int $user_id |
||
1942 | * |
||
1943 | * @return bool $success |
||
1944 | */ |
||
1945 | public static function add_user_data( $data_key, $post_id , $value = '' , $user_id = 0 ){ |
||
1946 | |||
1947 | return self::update_user_data( $data_key, $post_id, $value , $user_id ); |
||
1948 | |||
1949 | }// end add_user_data |
||
1950 | |||
1951 | /** |
||
1952 | * add user specific data to the passed in sensei post type id |
||
1953 | * |
||
1954 | * This function saves comment meta on the users current status. If no status is available |
||
1955 | * status will be created. It only operates on the available sensei Post types: course, lesson, quiz. |
||
1956 | * |
||
1957 | * @since 1.7.4 |
||
1958 | * |
||
1959 | * @param string $data_key maximum 39 characters allowed |
||
1960 | * @param int $post_id |
||
1961 | * @param mixed $value |
||
1962 | * @param int $user_id |
||
1963 | * |
||
1964 | * @return bool $success |
||
1965 | */ |
||
1966 | public static function update_user_data( $data_key, $post_id, $value = '' , $user_id = 0 ){ |
||
1967 | |||
1968 | if( ! ( $user_id > 0 ) ){ |
||
1969 | $user_id = get_current_user_id(); |
||
1970 | } |
||
1971 | |||
1972 | $supported_post_types = array( 'course', 'lesson' ); |
||
1973 | $post_type = get_post_type( $post_id ); |
||
1974 | if( empty( $post_id ) || empty( $data_key ) |
||
1975 | || ! is_int( $post_id ) || ! ( intval( $post_id ) > 0 ) || ! ( intval( $user_id ) > 0 ) |
||
1976 | || !get_userdata( $user_id ) |
||
1977 | || ! in_array( $post_type, $supported_post_types ) ){ |
||
1978 | |||
1979 | return false; |
||
1980 | } |
||
1981 | |||
1982 | // check if there and existing Sensei status on this post type if not create it |
||
1983 | // and get the activity ID |
||
1984 | $status_function = 'user_'.$post_type.'_status'; |
||
1985 | $sensei_user_status = self::$status_function( $post_id ,$user_id ); |
||
1986 | if( ! isset( $sensei_user_status->comment_ID ) ){ |
||
1987 | |||
1988 | $start_function = 'user_start_'.$post_type; |
||
1989 | $sensei_user_activity_id = self::$start_function( $user_id, $post_id ); |
||
1990 | |||
1991 | }else{ |
||
1992 | |||
1993 | $sensei_user_activity_id = $sensei_user_status->comment_ID; |
||
1994 | |||
1995 | } |
||
1996 | |||
1997 | // store the data |
||
1998 | $success = update_comment_meta( $sensei_user_activity_id, $data_key, $value ); |
||
1999 | |||
2000 | return $success; |
||
2001 | |||
2002 | }//update_user_data |
||
2003 | |||
2004 | /** |
||
2005 | * Get the user data stored on the passed in post type |
||
2006 | * |
||
2007 | * This function gets the comment meta on the lesson or course status |
||
2008 | * |
||
2009 | * @since 1.7.4 |
||
2010 | * |
||
2011 | * @param $data_key |
||
2012 | * @param $post_id |
||
2013 | * @param int $user_id |
||
2014 | * |
||
2015 | * @return mixed $user_data_value |
||
2016 | */ |
||
2017 | View Code Duplication | public static function get_user_data( $data_key, $post_id, $user_id = 0 ){ |
|
2018 | |||
2019 | $user_data_value = true; |
||
2020 | |||
2021 | if( ! ( $user_id > 0 ) ){ |
||
2022 | $user_id = get_current_user_id(); |
||
2023 | } |
||
2024 | |||
2025 | $supported_post_types = array( 'course', 'lesson' ); |
||
2026 | $post_type = get_post_type( $post_id ); |
||
2027 | if( empty( $post_id ) || empty( $data_key ) |
||
2028 | || ! ( intval( $post_id ) > 0 ) || ! ( intval( $user_id ) > 0 ) |
||
2029 | || ! get_userdata( $user_id ) |
||
2030 | || !in_array( $post_type, $supported_post_types ) ){ |
||
2031 | |||
2032 | return false; |
||
2033 | } |
||
2034 | |||
2035 | // check if there and existing Sensei status on this post type if not create it |
||
2036 | // and get the activity ID |
||
2037 | $status_function = 'user_'.$post_type.'_status'; |
||
2038 | $sensei_user_status = self::$status_function( $post_id ,$user_id ); |
||
2039 | if( ! isset( $sensei_user_status->comment_ID ) ){ |
||
2040 | return false; |
||
2041 | } |
||
2042 | |||
2043 | $sensei_user_activity_id = $sensei_user_status->comment_ID; |
||
2044 | $user_data_value = get_comment_meta( $sensei_user_activity_id , $data_key, true ); |
||
2045 | |||
2046 | return $user_data_value; |
||
2047 | |||
2048 | }// end get_user_data |
||
2049 | |||
2050 | /** |
||
2051 | * Delete the Sensei user data for the given key, Sensei post type and user combination. |
||
2052 | * |
||
2053 | * @param int $data_key |
||
2054 | * @param int $post_id |
||
2055 | * @param int $user_id |
||
2056 | * |
||
2057 | * @return bool $deleted |
||
2058 | */ |
||
2059 | View Code Duplication | public static function delete_user_data( $data_key, $post_id , $user_id ){ |
|
2060 | $deleted = true; |
||
2061 | |||
2062 | if( ! ( $user_id > 0 ) ){ |
||
2063 | $user_id = get_current_user_id(); |
||
2064 | } |
||
2065 | |||
2066 | $supported_post_types = array( 'course', 'lesson' ); |
||
2067 | $post_type = get_post_type( $post_id ); |
||
2068 | if( empty( $post_id ) || empty( $data_key ) |
||
2069 | || ! is_int( $post_id ) || ! ( intval( $post_id ) > 0 ) || ! ( intval( $user_id ) > 0 ) |
||
2070 | || ! get_userdata( $user_id ) |
||
2071 | || !in_array( $post_type, $supported_post_types ) ){ |
||
2072 | |||
2073 | return false; |
||
2074 | } |
||
2075 | |||
2076 | // check if there and existing Sensei status on this post type if not create it |
||
2077 | // and get the activity ID |
||
2078 | $status_function = 'user_'.$post_type.'_status'; |
||
2079 | $sensei_user_status = self::$status_function( $post_id ,$user_id ); |
||
2080 | if( ! isset( $sensei_user_status->comment_ID ) ){ |
||
2081 | return false; |
||
2082 | } |
||
2083 | |||
2084 | $sensei_user_activity_id = $sensei_user_status->comment_ID; |
||
2085 | $deleted = delete_comment_meta( $sensei_user_activity_id , $data_key ); |
||
2086 | |||
2087 | return $deleted; |
||
2088 | |||
2089 | }// end delete_user_data |
||
2090 | |||
2091 | |||
2092 | /** |
||
2093 | * The function creates a drop down. Never write up a Sensei select statement again. |
||
2094 | * |
||
2095 | * @since 1.8.0 |
||
2096 | * |
||
2097 | * @param string $selected_value |
||
2098 | * @param $options{ |
||
2099 | * @type string $value the value saved in the database |
||
2100 | * @type string $option what the user will see in the list of items |
||
2101 | * } |
||
2102 | * @param array $attributes{ |
||
2103 | * @type string $attribute type such name or id etc. |
||
2104 | * @type string $value |
||
2105 | * } |
||
2106 | * @param bool $enable_none_option |
||
2107 | * |
||
2108 | * @return string $drop_down_element |
||
2109 | */ |
||
2110 | public static function generate_drop_down( $selected_value, $options = array() , $attributes = array(), $enable_none_option = true ) { |
||
2111 | |||
2112 | $drop_down_element = ''; |
||
2113 | |||
2114 | // setup the basic attributes |
||
2115 | View Code Duplication | if( !isset( $attributes['name'] ) || empty( $attributes['name'] ) ) { |
|
2116 | |||
2117 | $attributes['name'] = 'sensei-options'; |
||
2118 | |||
2119 | } |
||
2120 | |||
2121 | View Code Duplication | if( !isset( $attributes['id'] ) || empty( $attributes['id'] ) ) { |
|
2122 | |||
2123 | $attributes['id'] = 'sensei-options'; |
||
2124 | |||
2125 | } |
||
2126 | |||
2127 | if( !isset( $attributes['class'] ) || empty( $attributes['class'] ) ) { |
||
2128 | |||
2129 | $attributes['class'] ='chosen_select widefat'; |
||
2130 | |||
2131 | } |
||
2132 | |||
2133 | // create element attributes |
||
2134 | $combined_attributes = ''; |
||
2135 | foreach( $attributes as $attribute => $value ){ |
||
2136 | |||
2137 | $combined_attributes .= $attribute . '="'.$value.'"' . ' '; |
||
2138 | |||
2139 | }// end for each |
||
2140 | |||
2141 | |||
2142 | // create the select element |
||
2143 | $drop_down_element .= '<select '. $combined_attributes . ' >' . "\n"; |
||
2144 | |||
2145 | // show the none option if the client requested |
||
2146 | if( $enable_none_option ) { |
||
2147 | $drop_down_element .= '<option value="">' . __('None', 'woothemes-sensei') . '</option>'; |
||
2148 | } |
||
2149 | |||
2150 | if ( count( $options ) > 0 ) { |
||
2151 | |||
2152 | foreach ($options as $value => $option ){ |
||
2153 | |||
2154 | $element = ''; |
||
2155 | $element.= '<option value="' . esc_attr( $value ) . '"'; |
||
2156 | $element .= selected( $value, $selected_value, false ) . '>'; |
||
2157 | $element .= esc_html( $option ) . '</option>' . "\n"; |
||
2158 | |||
2159 | // add the element to the select html |
||
2160 | $drop_down_element.= $element; |
||
2161 | } // End For Loop |
||
2162 | |||
2163 | } // End If Statement |
||
2164 | |||
2165 | $drop_down_element .= '</select>' . "\n"; |
||
2166 | |||
2167 | return $drop_down_element; |
||
2168 | |||
2169 | }// generate_drop_down |
||
2170 | |||
2171 | /** |
||
2172 | * Wrapper for the default php round() function. |
||
2173 | * This allows us to give more control to a user on how they can round Sensei |
||
2174 | * decimals passed through this function. |
||
2175 | * |
||
2176 | * @since 1.8.5 |
||
2177 | * |
||
2178 | * @param double $val |
||
2179 | * @param int $precision |
||
2180 | * @param $mode |
||
2181 | * @param string $context |
||
2182 | * |
||
2183 | * @return double $val |
||
2184 | */ |
||
2185 | public static function round( $val, $precision = 0, $mode = PHP_ROUND_HALF_UP, $context = '' ){ |
||
2186 | |||
2187 | /**Ã¥ |
||
2188 | * Change the precision for the Sensei_Utils::round function. |
||
2189 | * the precision given will be passed into the php round function |
||
2190 | * @since 1.8.5 |
||
2191 | */ |
||
2192 | $precision = apply_filters( 'sensei_round_precision', $precision , $val, $context, $mode ); |
||
2193 | |||
2194 | /** |
||
2195 | * Change the mode for the Sensei_Utils::round function. |
||
2196 | * the mode given will be passed into the php round function |
||
2197 | * |
||
2198 | * This applies only to PHP version 5.3.0 and greater |
||
2199 | * |
||
2200 | * @since 1.8.5 |
||
2201 | */ |
||
2202 | $mode = apply_filters( 'sensei_round_mode', $mode , $val, $context, $precision ); |
||
2203 | |||
2204 | if ( version_compare(PHP_VERSION, '5.3.0') >= 0 ) { |
||
2205 | |||
2206 | return round( $val, $precision, $mode ); |
||
2207 | |||
2208 | }else{ |
||
2209 | |||
2210 | return round( $val, $precision ); |
||
2211 | |||
2212 | } |
||
2213 | |||
2214 | } |
||
2215 | |||
2216 | /** |
||
2217 | * Returns the current url with all the query vars |
||
2218 | * |
||
2219 | * @since 1.9.0 |
||
2220 | * @return string $url |
||
2221 | */ |
||
2222 | public static function get_current_url(){ |
||
2223 | |||
2224 | global $wp; |
||
2225 | $current_url = trailingslashit( home_url( $wp->request ) ); |
||
2226 | if ( isset( $_GET ) ) { |
||
2227 | |||
2228 | foreach ($_GET as $param => $val ) { |
||
2229 | |||
2230 | $current_url = add_query_arg( $param, $val , $current_url ); |
||
2231 | |||
2232 | } |
||
2233 | } |
||
2234 | |||
2235 | return $current_url; |
||
2236 | } |
||
2237 | |||
2238 | /** |
||
2239 | * Restore the global WP_Query |
||
2240 | * |
||
2241 | * @since 1.9.0 |
||
2242 | */ |
||
2243 | public static function restore_wp_query() { |
||
2244 | |||
2245 | wp_reset_query(); |
||
2246 | |||
2247 | } |
||
2248 | |||
2249 | /** |
||
2250 | * Merge two arrays in a zip like fashion. |
||
2251 | * If one array is longer than the other the elements will be apended |
||
2252 | * to the end of the resulting array. |
||
2253 | * |
||
2254 | * @since 1.9.0 |
||
2255 | * |
||
2256 | * @param array $array_a |
||
2257 | * @param array $array_b |
||
2258 | * @return array $merged_array |
||
2259 | */ |
||
2260 | public static function array_zip_merge( $array_a, $array_b ){ |
||
2261 | |||
2262 | if( ! is_array( $array_a ) || ! is_array( $array_b ) ){ |
||
2263 | trigger_error('array_zip_merge requires both arrays to be indexed arrays '); |
||
2264 | } |
||
2265 | |||
2266 | $merged_array = array(); |
||
2267 | $total_elements = count( $array_a ) + count( $array_b ); |
||
2268 | |||
2269 | // Zip arrays |
||
2270 | for ( $i = 0; $i < $total_elements; $i++) { |
||
2271 | |||
2272 | // if has an element at current index push a on top |
||
2273 | if( isset( $array_a[ $i ] ) ){ |
||
2274 | $merged_array[] = $array_a[ $i ] ; |
||
2275 | } |
||
2276 | |||
2277 | // next if $array_b has an element at current index push a on top of the element |
||
2278 | // from a if there was one, if not the element before that. |
||
2279 | if( isset( $array_b[ $i ] ) ){ |
||
2280 | $merged_array[] = $array_b[ $i ] ; |
||
2281 | } |
||
2282 | |||
2283 | } |
||
2284 | |||
2285 | return $merged_array; |
||
2286 | } |
||
2287 | |||
2288 | } // End Class |
||
2289 | |||
2290 | /** |
||
2291 | * Class WooThemes_Sensei_Utils |
||
2292 | * @ignore only for backward compatibility |
||
2293 | * @since 1.9.0 |
||
2294 | */ |
||
2295 | class WooThemes_Sensei_Utils extends Sensei_Utils{} |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.