/** * Testing the is lesson pre-requisite completed function. * * @since 1.9.0 */ public function testIsPreRequisiteComplete() { // does this function add_user_data exist? $this->assertTrue(method_exists('WooThemes_Sensei_Lesson', 'is_prerequisite_complete'), 'The lesson class function `is_prerequisite_complete` does not exist '); // falsy state $user_id = 0; $lesson_id = 0; $this->assertFalse(WooThemes_Sensei_Lesson::is_prerequisite_complete($lesson_id, $user_id), 'None existing lesson or user should return false'); $test_user_id = wp_create_user('studentPrerequisite', 'studentPrerequisite', '*****@*****.**'); $test_lesson = $this->factory->get_lessons(); $test_lesson_id = $test_lesson[0]; // truthy state $course_id = $this->factory->get_random_course_id(); $lessons = $this->factory->get_lessons(); $test_lesson_prerequisite_id = $lessons[1]; // add lesson to random course update_post_meta($test_lesson_prerequisite_id, '_lesson_course', $course_id); update_post_meta($test_lesson_id, '_lesson_course', $course_id); // setup prerequisite update_post_meta($test_lesson_id, '_lesson_prerequisite', $test_lesson_prerequisite_id); Sensei_Utils::user_start_lesson($test_user_id, $test_lesson_prerequisite_id); $this->assertFalse(WooThemes_Sensei_Lesson::is_prerequisite_complete($test_lesson_id, $test_user_id), 'Users that has NOT completeded prerequisite should return false.'); Sensei_Utils::user_start_lesson($test_user_id, $test_lesson_prerequisite_id, true); $this->assertTrue(Sensei_Lesson::is_prerequisite_complete($test_lesson_id, $test_user_id), 'Users that has completeded prerequisite should return true.'); }
/** * trigger function. * * @access public * * @param int $user_id * @param int $course_id * * @return void */ function trigger($user_id = 0, $course_id = 0) { global $sensei_email_data; // Get learner user object $this->user = new WP_User($user_id); // Get passed status $passed = __('passed', 'woothemes-sensei'); if (!Sensei_Utils::sensei_user_passed_course($course_id, $user_id)) { $passed = __('failed', 'woothemes-sensei'); } // Construct data array $sensei_email_data = apply_filters('sensei_email_data', array('template' => $this->template, 'heading' => $this->heading, 'user_id' => $user_id, 'course_id' => $course_id, 'passed' => $passed), $this->template); // Set recipient (learner) $this->recipient = stripslashes($this->user->user_email); // Send mail Sensei()->emails->send($this->recipient, $this->subject, Sensei()->emails->get_content($this->template)); }
/** * Sets up the object course query * that will be used int he render method. * * @since 1.9.0 */ protected function setup_course_query() { // course query parameters to be used for all courses $query_args = array('post_type' => 'course', 'post_status' => 'publish', 'posts_per_page' => 1000, 'orderby' => $this->orderby, 'order' => $this->order); // get all the courses that has a product attached $all_courses_query = new WP_Query($query_args); $paid_courses_not_taken = array(); // look through all course and find the purchasable ones that user has not purchased foreach ($all_courses_query->posts as $course) { // only keep the courses with a product including only courses that the user not taking $course_product_id = get_post_meta($course->ID, '_course_woocommerce_product', true); if (is_numeric($course_product_id) && !Sensei_Utils::user_started_course($course->ID, get_current_user_id())) { $paid_courses_not_taken[] = $course->ID; } } // end foreach // setup the course query again and only use the course the user has not purchased. // this query will be loaded into the global WP_Query in the render function. $query_args['post__in'] = $paid_courses_not_taken; $query_args['posts_per_page'] = $this->number; $this->query = new WP_Query($query_args); }
/** * Print a single course markup * * @param $course_id */ public static function the_course($course_id) { // Get meta data $course = get_post($course_id); $user_info = get_userdata(absint($course->post_author)); $author_link = get_author_posts_url(absint($course->post_author)); $author_display_name = $user_info->display_name; $author_id = $course->post_author; $category_output = get_the_term_list($course_id, 'course-category', '', ', ', ''); $preview_lesson_count = intval(Sensei()->course->course_lesson_preview_count($course_id)); $is_user_taking_course = Sensei_Utils::user_started_course($course_id, get_current_user_id()); ?> <article class="<?php echo esc_attr(join(' ', get_post_class(array('course', 'post'), $course_id))); ?> "> <?php // so that legacy shortcodes work with the party plugins that wants to hook in do_action('sensei_course_content_before', $course->ID); ?> <div class="course-content"> <?php Sensei()->course->course_image($course_id); ?> <header> <h2><a href="<?php echo get_permalink($course_id); ?> " title="<?php echo $course->post_title; ?> "><?php echo $course->post_title; ?> </a></h2> </header> <section class="entry"> <p class="sensei-course-meta"> <?php if (isset(Sensei()->settings->settings['course_author']) && Sensei()->settings->settings['course_author']) { ?> <span class="course-author"><?php _e('by ', 'woothemes-sensei'); ?> <a href="<?php echo $author_link; ?> " title="<?php echo esc_attr($author_display_name); ?> "><?php echo esc_html($author_display_name); ?> </a></span> <?php } // End If Statement ?> <span class="course-lesson-count"> <?php echo Sensei()->course->course_lesson_count($course_id) . ' ' . __('Lessons', 'woothemes-sensei'); ?> </span> <?php if ('' != $category_output) { ?> <span class="course-category"><?php echo sprintf(__('in %s', 'woothemes-sensei'), $category_output); ?> </span> <?php } // End If Statement ?> <?php sensei_simple_course_price($course_id); ?> </p> <p class="course-excerpt"><?php echo $course->post_excerpt; ?> </p> <?php if (0 < $preview_lesson_count && !$is_user_taking_course) { $preview_lessons = sprintf(__('(%d preview lessons)', 'woothemes-sensei'), $preview_lesson_count); ?> <p class="sensei-free-lessons"> <a href="<?php echo get_permalink($course_id); ?> "><?php _e('Preview this course', 'woothemes-sensei'); ?> </a> - <?php echo $preview_lessons; ?> </p> <?php } ?> </section> </div> <?php // so that legacy shortcodes work with thir party plugins that wants to hook in do_action('sensei_course_content_after', $course->ID); ?> </article> <?php }
/** * Limit the analysis view to only the users taking courses belong to this teacher * * Hooked into sensei_analysis_get_learners * @param array $args WP_User_Query arguments * @return array $learners_query_results */ public function limit_analysis_learners($args) { // show default for none teachers if (!Sensei()->teacher->is_admin_teacher()) { return $args; } // for teachers all courses only return those which belong to the teacher // as they don't have access to course belonging to other users $teacher_courses = Sensei()->course->get_all_courses(); // if the user has no courses they should see no users if (empty($teacher_courses) || !is_array($teacher_courses)) { // tell the query to return 0 students $args['include'] = array(0); return $args; } $learner_ids_for_teacher_courses = array(); foreach ($teacher_courses as $course) { $course_learner_ids = array(); $activity_comments = Sensei_Utils::sensei_check_for_activity(array('post_id' => $course->ID, 'type' => 'sensei_course_status', 'field' => 'user_id'), true); if (empty($activity_comments) || is_array($activity_comments) && !(count($activity_comments) > 0)) { continue; // skip to the next course as there are no users on this course } // it could be an array of comments or a single comment if (is_array($activity_comments)) { foreach ($activity_comments as $comment) { $user = get_userdata($comment->user_id); if (empty($user)) { // next comment in this array continue; } $course_learner_ids[] = $user->ID; } } else { $user = get_userdata($activity_comments->user_id); $course_learner_ids[] = $user->ID; } // add learners on this course to the all courses learner list $learner_ids_for_teacher_courses = array_merge($learner_ids_for_teacher_courses, $course_learner_ids); } // if there are no students taking the courses by this teacher don't show them any of the other users if (empty($learner_ids_for_teacher_courses)) { $args['include'] = array(0); } else { $args['include'] = $learner_ids_for_teacher_courses; } // return the WP_Use_Query arguments return $args; }
/** * Runs when an order is cancelled. * @since 1.2.0 * @access public * @param integer $order_id order ID * @return void */ public function sensei_woocommerce_cancel_order($order_id) { // Get order object $order = new WC_Order($order_id); // Run through each product ordered if (0 < sizeof($order->get_items())) { // Get order user $user_id = $order->__get('user_id'); foreach ($order->get_items() as $item) { $product_type = ''; if (isset($item['variation_id']) && 0 < $item['variation_id']) { $item_id = $item['variation_id']; $product_type = 'variation'; } else { $item_id = $item['product_id']; } // End If Statement $_product = $this->sensei_get_woocommerce_product_object($item_id, $product_type); // Get courses that use the WC product $courses = array(); $courses = $this->post_types->course->get_product_courses($item_id); // Loop and update those courses foreach ($courses as $course_item) { // Check and Remove course from courses user meta $dataset_changes = Sensei_Utils::sensei_remove_user_from_course($course_item->ID, $user_id); } // End For Loop } // End For Loop } // End If Statement }
/** * This hook fire inside learner-profile.php inside directly before the content * * @since 1.9.0 * * @param integer $course_id * * @hooked Sensei_Course_Results::course_info() - 20 */ do_action('sensei_course_results_content_inside_before_lessons', $course->ID); ?> <section class="course-results-lessons"> <?php $started_course = Sensei_Utils::user_started_course($course->ID, get_current_user_id()); if ($started_course) { sensei_the_course_results_lessons(); } ?> </section> <?php } ?> <?php /** * This hook fire inside learner-profile.php inside directly after the content * * @since 1.9.0
/** * Add text to the certificate * * @access public * @since 1.0.0 * @return void */ public function certificate_text($pdf_certificate, $fpdf) { $show_border = apply_filters('woothemes_sensei_certificates_show_border', 0); $start_position = 200; // Find certificate based on hash $args = array('post_type' => 'certificate', 'meta_key' => 'certificate_hash', 'meta_value' => $pdf_certificate->hash); $query = new WP_Query($args); $certificate_id = 0; if ($query->have_posts()) { $query->the_post(); $certificate_id = $query->posts[0]->ID; } // End If Statement wp_reset_query(); if (0 < intval($certificate_id)) { // Get Student Data $user_id = get_post_meta($certificate_id, 'learner_id', true); $student = get_userdata($user_id); $student_name = $student->display_name; $fname = $student->first_name; $lname = $student->last_name; if ('' != $fname && '' != $lname) { $student_name = $fname . ' ' . $lname; } // Get Course Data $course_id = get_post_meta($certificate_id, 'course_id', true); $course = Sensei()->course->course_query(-1, 'usercourses', $course_id); $course = $course[0]; $course_end = Sensei_Utils::sensei_check_for_activity(array('post_id' => intval($course_id), 'user_id' => intval($user_id), 'type' => 'sensei_course_status'), true); $course_end_date = $course_end->comment_date; // Get the certificate template $certificate_template_id = get_post_meta($course_id, '_course_certificate_template', true); $certificate_template_custom_fields = get_post_custom($certificate_template_id); // Define the data we're going to load: Key => Default value $load_data = array('certificate_font_style' => array(), 'certificate_font_color' => array(), 'certificate_font_size' => array(), 'certificate_font_family' => array(), 'image_ids' => array(), 'certificate_template_fields' => array()); // Load the data from the custom fields foreach ($load_data as $key => $default) { // set value from db (unserialized if needed) or use default $this->{$key} = isset($certificate_template_custom_fields['_' . $key][0]) && '' !== $certificate_template_custom_fields['_' . $key][0] ? is_array($default) ? maybe_unserialize($certificate_template_custom_fields['_' . $key][0]) : $certificate_template_custom_fields['_' . $key][0] : $default; } // End For Loop // Set default fonts if (isset($this->certificate_font_color) && '' != $this->certificate_font_color) { $pdf_certificate->certificate_pdf_data['font_color'] = $this->certificate_font_color; } if (isset($this->certificate_font_size) && '' != $this->certificate_font_size) { $pdf_certificate->certificate_pdf_data['font_size'] = $this->certificate_font_size; } if (isset($this->certificate_font_family) && '' != $this->certificate_font_family) { $pdf_certificate->certificate_pdf_data['font_family'] = $this->certificate_font_family; } if (isset($this->certificate_font_style) && '' != $this->certificate_font_style) { $pdf_certificate->certificate_pdf_data['font_style'] = $this->certificate_font_style; } // Set default fonts setlocale(LC_TIME, get_locale()); if (false !== strpos(get_locale(), 'en')) { $date_format = apply_filters('sensei_certificate_date_format', 'jS F Y'); $date = date($date_format, strtotime($course_end_date)); } else { $date_format = apply_filters('sensei_certificate_date_format', '%Y %B %e'); $date = strftime($date_format, strtotime($course_end_date)); } $certificate_heading = __('Certificate of Completion', 'sensei-certificates'); // Certificate of Completion if (isset($this->certificate_template_fields['certificate_heading']['text']) && '' != $this->certificate_template_fields['certificate_heading']['text']) { $certificate_heading = $this->certificate_template_fields['certificate_heading']['text']; $certificate_heading = str_replace(array('{{learner}}', '{{course_title}}', '{{completion_date}}', '{{course_place}}'), array($student_name, $course->post_title, $date, get_bloginfo('name')), $certificate_heading); } // End If Statement $certificate_message = __('This is to certify that', 'sensei-certificates') . " \r\n\r\n" . $student_name . " \r\n\r\n" . __('has completed the course', 'sensei-certificates'); // This is to certify that {{learner}} has completed the course if (isset($this->certificate_template_fields['certificate_message']['text']) && '' != $this->certificate_template_fields['certificate_message']['text']) { $certificate_message = $this->certificate_template_fields['certificate_message']['text']; $certificate_message = str_replace(array('{{learner}}', '{{course_title}}', '{{completion_date}}', '{{course_place}}'), array($student_name, $course->post_title, $date, get_bloginfo('name')), $certificate_message); } // End If Statement $certificate_course = $course->post_title; // {{course_title}} if (isset($this->certificate_template_fields['certificate_course']['text']) && '' != $this->certificate_template_fields['certificate_course']['text']) { $certificate_course = $this->certificate_template_fields['certificate_course']['text']; $certificate_course = str_replace(array('{{learner}}', '{{course_title}}', '{{completion_date}}', '{{course_place}}'), array($student_name, $course->post_title, $date, get_bloginfo('name')), $certificate_course); } // End If Statement $certificate_completion = $date; // {{completion_date}} if (isset($this->certificate_template_fields['certificate_completion']['text']) && '' != $this->certificate_template_fields['certificate_completion']['text']) { $certificate_completion = $this->certificate_template_fields['certificate_completion']['text']; $certificate_completion = str_replace(array('{{learner}}', '{{course_title}}', '{{completion_date}}', '{{course_place}}'), array($student_name, $course->post_title, $date, get_bloginfo('name')), $certificate_completion); } // End If Statement $certificate_place = sprintf(__('At %s', 'sensei-certificates'), get_bloginfo('name')); // At {{course_place}} if (isset($this->certificate_template_fields['certificate_place']['text']) && '' != $this->certificate_template_fields['certificate_place']['text']) { $certificate_place = $this->certificate_template_fields['certificate_place']['text']; $certificate_place = str_replace(array('{{learner}}', '{{course_title}}', '{{completion_date}}', '{{course_place}}'), array($student_name, $course->post_title, $date, get_bloginfo('name')), $certificate_place); } // End If Statement $output_fields = array('certificate_heading' => 'text_field', 'certificate_message' => 'textarea_field', 'certificate_course' => 'text_field', 'certificate_completion' => 'text_field', 'certificate_place' => 'text_field'); foreach ($output_fields as $meta_key => $function_name) { // Check if the field has a set position if (isset($this->certificate_template_fields[$meta_key]['position']['x1'])) { $font_settings = $this->get_certificate_font_settings($meta_key); call_user_func_array(array($pdf_certificate, $function_name), array($fpdf, ${$meta_key}, $show_border, array($this->certificate_template_fields[$meta_key]['position']['x1'], $this->certificate_template_fields[$meta_key]['position']['y1'], $this->certificate_template_fields[$meta_key]['position']['width'], $this->certificate_template_fields[$meta_key]['position']['height']), $font_settings)); } // End If Statement } // End For Loop } else { wp_die(__('The certificate you are searching for does not exist.', 'sensei-certificates'), __('Certificate Error', 'sensei-certificates')); } // End If Statement }
/** * Checks the cart to see if a course is in the cart. * * @param $course_id * @return bool */ public static function is_course_in_cart($course_id) { $wc_post_id = absint(get_post_meta($course_id, '_course_woocommerce_product', true)); $user_course_status_id = Sensei_Utils::user_started_course($course_id, get_current_user_id()); if (0 < intval($wc_post_id) && !$user_course_status_id) { if (self::is_product_in_cart($wc_post_id)) { return true; } } return false; }
/** * Sets the stats boxes to render * @since 1.2.0 * @return array $stats_to_render of stats boxes and values */ public function stats_boxes() { // Get the data required $user_count = count_users(); $user_count = apply_filters('sensei_analysis_total_users', $user_count['total_users'], $user_count); $total_courses = Sensei()->course->course_count(array('publish', 'private')); $total_lessons = Sensei()->lesson->lesson_count(array('publish', 'private')); /** * filter the analysis tot grades query args */ $grade_args = apply_filters('sensei_analysis_total_quiz_grades', array('type' => 'sensei_lesson_status', 'status' => 'any', 'meta_key' => 'grade')); $total_grade_count = Sensei_Grading::get_graded_lessons_count(); $total_grade_total = Sensei_Grading::get_graded_lessons_sum(); $total_average_grade = 0; if ($total_grade_total > 0 && $total_grade_count > 0) { $total_average_grade = abs(round(doubleval($total_grade_total / $total_grade_count), 2)); } $course_args = array('type' => 'sensei_course_status', 'status' => 'any'); $total_courses_started = Sensei_Utils::sensei_check_for_activity(apply_filters('sensei_analysis_total_courses_started', $course_args)); $course_args = array('type' => 'sensei_course_status', 'status' => 'complete'); $total_courses_ended = Sensei_Utils::sensei_check_for_activity(apply_filters('sensei_analysis_total_courses_ended', $course_args)); $average_courses_per_learner = abs(round(doubleval($total_courses_started / $user_count), 2)); // Setup the boxes to render $stats_to_render = array(__('Total Courses', 'woothemes-sensei') => $total_courses, __('Total Lessons', 'woothemes-sensei') => $total_lessons, __('Total Learners', 'woothemes-sensei') => $user_count, __('Average Courses per Learner', 'woothemes-sensei') => $average_courses_per_learner, __('Average Grade', 'woothemes-sensei') => $total_average_grade . '%', __('Total Completed Courses', 'woothemes-sensei') => $total_courses_ended); return apply_filters('sensei_analysis_stats_boxes', $stats_to_render); }
/** * Check if the prerequisite course is completed * Courses with no pre-requisite should always return true * * @since 1.9.0 * @param $course_id * @return bool */ public static function is_prerequisite_complete($course_id) { $course_prerequisite_id = get_post_meta($course_id, '_course_prerequisite', true); // if it has a pre requisite course check it if (!empty($course_prerequisite_id)) { return Sensei_Utils::user_completed_course($course_prerequisite_id, get_current_user_id()); } return true; }
/** * check_user_permissions function. * * @access public * @param string $page (default: '') * * @return bool */ public function check_user_permissions($page = '') { global $current_user, $post; // if user is not logged in skipped for single lesson if (empty($current_user->caps) && Sensei()->settings->get('access_permission') && 'lesson-single' != $page) { $this->permissions_message['title'] = __('Restricted Access:', 'woothemes-sensei'); $this->permissions_message['message'] = sprintf(__('You must be logged in to view this %s'), get_post_type()); return false; } $user_allowed = false; switch ($page) { case 'course-single': // check for prerequisite course or lesson, $course_prerequisite_id = (int) get_post_meta($post->ID, '_course_prerequisite', true); $update_course = Sensei_WC::course_update($post->ID); // Count completed lessons if (0 < absint($course_prerequisite_id)) { $prerequisite_complete = Sensei_Utils::user_completed_course($course_prerequisite_id, $current_user->ID); } else { $prerequisite_complete = true; } // End If Statement // Handles restrictions if (!$prerequisite_complete && 0 < absint($course_prerequisite_id)) { $this->permissions_message['title'] = get_the_title($post->ID) . ': ' . __('Restricted Access', 'woothemes-sensei'); $course_link = '<a href="' . esc_url(get_permalink($course_prerequisite_id)) . '">' . __('course', 'woothemes-sensei') . '</a>'; $this->permissions_message['message'] = sprintf(__('Please complete the previous %1$s before taking this course.', 'woothemes-sensei'), $course_link); } else { $user_allowed = true; } // End If Statement break; case 'lesson-single': // Check for WC purchase $lesson_course_id = get_post_meta($post->ID, '_lesson_course', true); $update_course = Sensei_WC::course_update($lesson_course_id); $is_preview = Sensei_Utils::is_preview_lesson($post->ID); if ($this->access_settings() && Sensei_Utils::user_started_course($lesson_course_id, $current_user->ID)) { $user_allowed = true; } elseif ($this->access_settings() && false == $is_preview) { $user_allowed = true; } else { $this->permissions_message['title'] = get_the_title($post->ID) . ': ' . __('Restricted Access', 'woothemes-sensei'); $course_link = '<a href="' . esc_url(get_permalink($lesson_course_id)) . '">' . __('course', 'woothemes-sensei') . '</a>'; $wc_post_id = get_post_meta($lesson_course_id, '_course_woocommerce_product', true); if (Sensei_WC::is_woocommerce_active() && 0 < $wc_post_id) { if ($is_preview) { $this->permissions_message['message'] = sprintf(__('This is a preview lesson. Please purchase the %1$s to access all lessons.', 'woothemes-sensei'), $course_link); } else { $this->permissions_message['message'] = sprintf(__('Please purchase the %1$s before starting this Lesson.', 'woothemes-sensei'), $course_link); } } else { if ($is_preview) { $this->permissions_message['message'] = sprintf(__('This is a preview lesson. Please sign up for the %1$s to access all lessons.', 'woothemes-sensei'), $course_link); } else { /** This filter is documented in class-woothemes-sensei-frontend.php */ $this->permissions_message['message'] = sprintf(__('Please sign up for the %1$s before starting the lesson.', 'woothemes-sensei'), $course_link); } } // End If Statement } // End If Statement break; case 'quiz-single': $lesson_id = get_post_meta($post->ID, '_quiz_lesson', true); $lesson_course_id = get_post_meta($lesson_id, '_lesson_course', true); $update_course = Sensei_WC::course_update($lesson_course_id); if ($this->access_settings() && Sensei_Utils::user_started_course($lesson_course_id, $current_user->ID) || sensei_all_access()) { // Check for prerequisite lesson for this quiz $lesson_prerequisite_id = (int) get_post_meta($lesson_id, '_lesson_prerequisite', true); $user_lesson_prerequisite_complete = Sensei_Utils::user_completed_lesson($lesson_prerequisite_id, $current_user->ID); // Handle restrictions if (sensei_all_access()) { $user_allowed = true; } else { if (0 < absint($lesson_prerequisite_id) && !$user_lesson_prerequisite_complete) { $this->permissions_message['title'] = get_the_title($post->ID) . ': ' . __('Restricted Access', 'woothemes-sensei'); $lesson_link = '<a href="' . esc_url(get_permalink($lesson_prerequisite_id)) . '">' . __('lesson', 'woothemes-sensei') . '</a>'; $this->permissions_message['message'] = sprintf(__('Please complete the previous %1$s before taking this Quiz.', 'woothemes-sensei'), $lesson_link); } else { $user_allowed = true; } // End If Statement } // End If Statement } elseif ($this->access_settings()) { // Check if the user has started the course if (is_user_logged_in() && !Sensei_Utils::user_started_course($lesson_course_id, $current_user->ID) && (isset($this->settings->settings['access_permission']) && true == $this->settings->settings['access_permission'])) { $user_allowed = false; $this->permissions_message['title'] = get_the_title($post->ID) . ': ' . __('Restricted Access', 'woothemes-sensei'); $course_link = '<a href="' . esc_url(get_permalink($lesson_course_id)) . '">' . __('course', 'woothemes-sensei') . '</a>'; $wc_post_id = get_post_meta($lesson_course_id, '_course_woocommerce_product', true); if (Sensei_WC::is_woocommerce_active() && 0 < $wc_post_id) { $this->permissions_message['message'] = sprintf(__('Please purchase the %1$s before starting this Quiz.', 'woothemes-sensei'), $course_link); } else { $this->permissions_message['message'] = sprintf(__('Please sign up for the %1$s before starting this Quiz.', 'woothemes-sensei'), $course_link); } // End If Statement } else { $user_allowed = true; } // End If Statement } else { $this->permissions_message['title'] = get_the_title($post->ID) . ': ' . __('Restricted Access', 'woothemes-sensei'); $course_link = '<a href="' . esc_url(get_permalink(get_post_meta(get_post_meta($post->ID, '_quiz_lesson', true), '_lesson_course', true))) . '">' . __('course', 'woothemes-sensei') . '</a>'; $this->permissions_message['message'] = sprintf(__('Please sign up for the %1$s before taking this Quiz.', 'woothemes-sensei'), $course_link); } // End If Statement break; default: $user_allowed = true; break; } // End Switch Statement /** * filter the permissions message shown on sensei post types. * * @since 1.8.7 * * @param array $permissions_message{ * * @type string $title * @type string $message * * } * @param string $post_id */ $this->permissions_message = apply_filters('sensei_permissions_message', $this->permissions_message, $post->ID); if (sensei_all_access() || Sensei_Utils::is_preview_lesson($post->ID)) { $user_allowed = true; } /** * Filter the permissions check final result. Which determines if the user has * access to the given page. * * @since 1.0 * * @param boolean $user_allowed * @param integer $user_id * */ return apply_filters('sensei_access_permissions', $user_allowed, $current_user->ID); }
/** * Add a the user status class for the given course. * * @since 1.9 * * @param array $classes * @param WP_Post $course * @return array $classes */ public function course_status_class_tagging($classes, $course) { if (Sensei_Utils::user_completed_course($course, get_current_user_id())) { $classes[] = 'user-completed'; } else { $classes[] = 'user-active'; } return $classes; }
/** * Test the array zip utility function * @since 1.9.0 */ public function testArrayZipMerge() { $this->assertTrue(method_exists('Sensei_Utils', 'array_zip_merge'), 'Sensei_Utils::array_zip_merge does not exist.'); // test if the function works $array_1 = array(1, 2, 3); $array_2 = array(5, 6, 7, 8, 9); $array_zipped = Sensei_Utils::array_zip_merge($array_1, $array_2); $expected = array(1, 5, 2, 6, 3, 7, 8, 9); $this->assertEquals($expected, $array_zipped); }
public function add_new_learners() { $result = false; if (!isset($_POST['add_learner_submit'])) { return $result; } if (!isset($_POST['add_learner_nonce']) || !wp_verify_nonce($_POST['add_learner_nonce'], 'add_learner_to_sensei')) { return $result; } if (!isset($_POST['add_user_id']) || '' == $_POST['add_user_id'] || !isset($_POST['add_post_type']) || !isset($_POST['add_course_id']) || !isset($_POST['add_lesson_id'])) { return $result; } $post_type = $_POST['add_post_type']; $user_id = absint($_POST['add_user_id']); $course_id = absint($_POST['add_course_id']); switch ($post_type) { case 'course': $result = Sensei_Utils::user_start_course($user_id, $course_id); // Complete each lesson if course is set to be completed if (isset($_POST['add_complete_course']) && 'yes' == $_POST['add_complete_course']) { $lesson_ids = Sensei()->course->course_lessons($course_id, 'any', 'ids'); foreach ($lesson_ids as $id) { Sensei_Utils::sensei_start_lesson($id, $user_id, true); } // Updates the Course status and it's meta data Sensei_Utils::user_complete_course($course_id, $user_id); do_action('sensei_user_course_end', $user_id, $course_id); } break; case 'lesson': $lesson_id = absint($_POST['add_lesson_id']); $complete = false; if (isset($_POST['add_complete_lesson']) && 'yes' == $_POST['add_complete_lesson']) { $complete = true; } $result = Sensei_Utils::sensei_start_lesson($lesson_id, $user_id, $complete); // Updates the Course status and it's meta data Sensei_Utils::user_complete_course($course_id, $user_id); break; } // Set redirect URL after adding user to course/lesson $query_args = array('page' => $this->page_slug, 'view' => 'learners'); if ($result) { if ($course_id) { $query_args['course_id'] = $course_id; } if ($lesson_id) { $query_args['lesson_id'] = $lesson_id; } $query_args['message'] = 'success'; } else { $query_args['message'] = 'error'; } $redirect_url = apply_filters('sensei_learners_add_learner_redirect_url', add_query_arg($query_args, admin_url('admin.php'))); wp_safe_redirect(esc_url_raw($redirect_url)); exit; }
/** * Sets the stats boxes to render * @since 1.2.0 * @return array $stats_to_render of stats boxes and values */ public function stats_boxes() { // Get the data required $user_count = count_users(); $user_count = apply_filters('sensei_analysis_total_users', $user_count['total_users'], $user_count); $total_courses = Sensei()->course->course_count(array('publish', 'private')); $total_lessons = Sensei()->lesson->lesson_count(array('publish', 'private')); $grade_args = array('type' => 'sensei_lesson_status', 'status' => 'any', 'meta_key' => 'grade'); add_filter('comments_clauses', array('WooThemes_Sensei_Utils', 'comment_total_sum_meta_value_filter')); $total_quiz_grades = Sensei_Utils::sensei_check_for_activity(apply_filters('sensei_analysis_total_quiz_grades', $grade_args), true); remove_filter('comments_clauses', array('WooThemes_Sensei_Utils', 'comment_total_sum_meta_value_filter')); $total_grade_count = !empty($total_quiz_grades->total) ? $total_quiz_grades->total : 1; $total_grade_total = !empty($total_quiz_grades->meta_sum) ? doubleval($total_quiz_grades->meta_sum) : 0; $total_average_grade = abs(round(doubleval($total_grade_total / $total_grade_count), 2)); $course_args = array('type' => 'sensei_course_status', 'status' => 'any'); $total_courses_started = Sensei_Utils::sensei_check_for_activity(apply_filters('sensei_analysis_total_courses_started', $course_args)); $course_args = array('type' => 'sensei_course_status', 'status' => 'complete'); $total_courses_ended = Sensei_Utils::sensei_check_for_activity(apply_filters('sensei_analysis_total_courses_ended', $course_args)); $average_courses_per_learner = abs(round(doubleval($total_courses_started / $user_count), 2)); // Setup the boxes to render $stats_to_render = array(__('Total Courses', 'woothemes-sensei') => $total_courses, __('Total Lessons', 'woothemes-sensei') => $total_lessons, __('Total Learners', 'woothemes-sensei') => $user_count, __('Average Courses per Learner', 'woothemes-sensei') => $average_courses_per_learner, __('Average Grade', 'woothemes-sensei') => $total_average_grade . '%', __('Total Completed Courses', 'woothemes-sensei') => $total_courses_ended); return apply_filters('sensei_analysis_stats_boxes', $stats_to_render); }
/** * Return array of lesson statuses * @since 1.7.0 * @return array statuses */ private function get_lesson_statuses($args) { $activity_args = array('post_id' => $this->lesson_id, 'type' => 'sensei_lesson_status', 'number' => $args['number'], 'offset' => $args['offset'], 'orderby' => $args['orderby'], 'order' => $args['order'], 'status' => 'any'); // Searching users on statuses requires sub-selecting the statuses by user_ids if ($this->search) { $user_args = array('search' => '*' . $this->search . '*', 'fields' => 'ID'); // Filter for extending $user_args = apply_filters('sensei_analysis_lesson_search_users', $user_args); if (!empty($user_args)) { $learners_search = new WP_User_Query($user_args); // Store for reuse on counts $activity_args['user_id'] = (array) $learners_search->get_results(); } } // End If Statement $activity_args = apply_filters('sensei_analysis_lesson_filter_statuses', $activity_args); // WP_Comment_Query doesn't support SQL_CALC_FOUND_ROWS, so instead do this twice $this->total_items = Sensei_Utils::sensei_check_for_activity(array_merge($activity_args, array('count' => true, 'offset' => 0, 'number' => 0))); // Ensure we change our range to fit (in case a search threw off the pagination) - Should this be added to all views? if ($this->total_items < $activity_args['offset']) { $new_paged = floor($total_statuses / $activity_args['number']); $activity_args['offset'] = $new_paged * $activity_args['number']; } $statuses = Sensei_Utils::sensei_check_for_activity($activity_args, true); // Need to always return an array, even with only 1 item if (!is_array($statuses)) { $statuses = array($statuses); } return $statuses; }
/** * Load course results info * @since 1.4.0 * @return void */ public function course_info() { global $course; $course_status = Sensei_Utils::sensei_user_course_status_message($course->ID, get_current_user_id()); echo '<div class="sensei-message ' . $course_status['box_class'] . '">' . $course_status['message'] . '</div>'; sensei_do_deprecated_action('sensei_course_results_lessons', '1.9.', 'sensei_course_results_content_inside_after', $course); sensei_do_deprecated_action('sensei_course_results_bottom', '1.9.', 'sensei_course_results_content_inside_after', $course->ID); }
/** * Activate single course if already purchases * @return void */ public function activate_purchased_single_course() { global $post, $current_user; if (Sensei_WC::is_woocommerce_active()) { if (!is_user_logged_in()) { return; } if (!isset($post->ID)) { return; } $user_id = $current_user->ID; $course_id = $post->ID; $course_product_id = (int) get_post_meta($course_id, '_course_woocommerce_product', true); if (!$course_product_id) { return; } $user_course_status = Sensei_Utils::user_course_status(intval($course_id), $user_id); // Ignore course if already completed if (Sensei_Utils::user_completed_course($user_course_status)) { return; } // Ignore course if already started if ($user_course_status) { return; } // Get all user's orders $order_args = array('post_type' => 'shop_order', 'posts_per_page' => -1, 'post_status' => array('wc-processing', 'wc-completed'), 'meta_query' => array(array('key' => '_customer_user', 'value' => $user_id)), 'fields' => 'ids'); $orders = get_posts($order_args); foreach ($orders as $order_post_id) { // Get course product IDs from order $order = new WC_Order($order_post_id); $items = $order->get_items(); foreach ($items as $item) { $product = wc_get_product($item['product_id']); // handle product bundles if (is_object($product) && $product->is_type('bundle')) { $bundled_product = new WC_Product_Bundle($product->id); $bundled_items = $bundled_product->get_bundled_items(); foreach ($bundled_items as $bundled_item) { if ($bundled_item->product_id == $course_product_id) { Sensei_Utils::user_start_course($user_id, $course_id); return; } } } else { // handle regular products if ($item['product_id'] == $course_product_id) { Sensei_Utils::user_start_course($user_id, $course_id); return; } } } } } }
/** * Load the desired component, if a method is available for it. * @param string $component The component to potentially be loaded. * * @since 1.0.0 * @return void */ protected function load_component($instance) { global $current_user; $course_ids = array(); if ('activecourses' == esc_attr($instance['component'])) { $courses = Sensei_Utils::sensei_check_for_activity(array('user_id' => $current_user->ID, 'type' => 'sensei_course_status', 'status' => 'in-progress'), true); // Need to always return an array, even with only 1 item if (!is_array($courses)) { $courses = array($courses); } foreach ($courses as $course) { $course_ids[] = $course->comment_post_ID; } } elseif ('completedcourses' == esc_attr($instance['component'])) { $courses = Sensei_Utils::sensei_check_for_activity(array('user_id' => $current_user->ID, 'type' => 'sensei_course_status', 'status' => 'complete'), true); // Need to always return an array, even with only 1 item if (!is_array($courses)) { $courses = array($courses); } foreach ($courses as $course) { $course_ids[] = $course->comment_post_ID; } } // End If Statement $posts_array = array(); // course_query() is buggy, it doesn't honour the 1st arg if includes are provided, so instead slice the includes if (!empty($instance['limit']) && intval($instance['limit']) >= 1 && intval($instance['limit']) < count($course_ids)) { $course_ids = array_slice($course_ids, 0, intval($instance['limit'])); // This does mean the order by is effectively ignored } if (!empty($course_ids)) { $posts_array = Sensei()->course->course_query(intval($instance['limit']), esc_attr($instance['component']), $course_ids); } else { if ('activecourses' == esc_attr($instance['component']) || 'completedcourses' == esc_attr($instance['component'])) { $posts_array = array(); } else { $course_args = array('post_type' => 'course', 'orderby' => 'date', 'order' => 'DESC', 'post_status' => 'publish', 'posts_per_page' => $instance['limit']); $posts_array = get_posts($course_args); } } // End If Statement if (count($posts_array) > 0) { ?> <ul> <?php foreach ($posts_array as $post_item) { $post_id = absint($post_item->ID); $post_title = $post_item->post_title; $user_info = get_userdata(absint($post_item->post_author)); $author_link = get_author_posts_url(absint($post_item->post_author)); $author_display_name = $user_info->display_name; $author_id = $post_item->post_author; ?> <li class="fix"> <?php do_action('sensei_course_image', $post_id); ?> <a href="<?php echo esc_url(get_permalink($post_id)); ?> " title="<?php echo esc_attr($post_title); ?> "><?php echo $post_title; ?> </a> <br /> <?php if (isset(Sensei()->settings->settings['course_author']) && Sensei()->settings->settings['course_author']) { ?> <span class="course-author"><?php _e('by ', 'woothemes-sensei'); ?> <a href="<?php echo esc_url($author_link); ?> " title="<?php echo esc_attr($author_display_name); ?> "><?php echo esc_html($author_display_name); ?> </a></span> <br /> <?php } // End If Statement ?> <span class="course-lesson-count"><?php echo Sensei()->course->course_lesson_count($post_id) . ' ' . __('Lessons', 'woothemes-sensei'); ?> </span> <br /> <?php sensei_simple_course_price($post_id); ?> </li> <?php } // End For Loop ?> <?php if ('activecourses' == esc_attr($instance['component']) || 'completedcourses' == esc_attr($instance['component'])) { $my_account_page_id = intval(Sensei()->settings->settings['my_course_page']); echo '<li class="my-account fix"><a href="' . esc_url(get_permalink($my_account_page_id)) . '">' . __('My Courses', 'woothemes-sensei') . ' <span class="meta-nav"></span></a></li>'; } // End If Statement ?> </ul> <?php } else { // No posts returned. This means the user either has no active or no completed courses. if (isset($instance['component'])) { if ('featuredcourses' == $instance['component']) { _e('You have no featured courses.', 'woothemes-sensei'); } elseif ('activecourses' == $instance['component']) { _e('You have no active courses.', 'woothemes-sensei'); } elseif ('completedcourses' == $instance['component']) { _e('You have no completed courses.', 'woothemes-sensei'); } else { _e('You have no courses.', 'woothemes-sensei'); } } // end if compoenetn status instance } // End If Statement }
/** * Deprecate the hook sensei_lesson_course_signup. * * The hook content will be linked directly on the recommended * sensei_single_lesson_content_inside_after * * @deprecated since 1.9.0 */ public static function deprecate_sensei_lesson_course_signup_hook() { $lesson_course_id = get_post_meta(get_the_ID(), '_lesson_course', true); $user_taking_course = Sensei_Utils::user_started_course($lesson_course_id, get_current_user_id()); if (!$user_taking_course) { sensei_do_deprecated_action('sensei_lesson_course_signup', '1.9.0', 'sensei_single_lesson_content_inside_after', $lesson_course_id); } }
/** * Display the leeson quiz status if it should be shown * * @param int $lesson_id defaults to the global lesson id * @param int $user_id defaults to the current user id * * @since 1.9.0 */ public static function user_lesson_quiz_status_message($lesson_id = 0, $user_id = 0) { $lesson_id = empty($lesson_id) ? get_the_ID() : $lesson_id; $user_id = empty($lesson_id) ? get_current_user_id() : $user_id; $lesson_course_id = (int) get_post_meta($lesson_id, '_lesson_course', true); $quiz_id = Sensei()->lesson->lesson_quizzes($lesson_id); $has_user_completed_lesson = Sensei_Utils::user_completed_lesson(intval($lesson_id), $user_id); if ($quiz_id && is_user_logged_in() && Sensei_Utils::user_started_course($lesson_course_id, $user_id)) { $no_quiz_count = 0; $has_quiz_questions = get_post_meta($lesson_id, '_quiz_has_questions', true); // Display lesson quiz status message if ($has_user_completed_lesson || $has_quiz_questions) { $status = Sensei_Utils::sensei_user_quiz_status_message($lesson_id, $user_id, true); echo '<div class="sensei-message ' . $status['box_class'] . '">' . $status['message'] . '</div>'; if ($has_quiz_questions) { // echo $status['extra']; } // End If Statement } // End If Statement } }
/** * Grade quiz automatically * * This function grades each question automatically if there all questions are auto gradable. If not * the quiz will not be auto gradable. * * @since 1.7.4 * * @param integer $quiz_id ID of quiz * @param array $submitted questions id ans answers { * @type int $question_id * @type mixed $answer * } * @param integer $total_questions Total questions in quiz (not used) * @param string $quiz_grade_type Optional defaults to auto * * @return int $quiz_grade total sum of all question grades */ public static function grade_quiz_auto($quiz_id = 0, $submitted = array(), $total_questions = 0, $quiz_grade_type = 'auto') { if (!(intval($quiz_id) > 0) || !$submitted || $quiz_grade_type != 'auto') { return false; // exit early } $user_id = get_current_user_id(); $lesson_id = Sensei()->quiz->get_lesson_id($quiz_id); $quiz_autogradable = true; /** * Filter the types of question types that can be automatically graded. * * This filter fires inside the auto grade quiz function and provides you with the default list. * * @param array { * 'multiple-choice', * 'boolean', * 'gap-fill'. * } */ $autogradable_question_types = apply_filters('sensei_autogradable_question_types', array('multiple-choice', 'boolean', 'gap-fill')); $grade_total = 0; $all_question_grades = array(); foreach ($submitted as $question_id => $answer) { // check if the question is autogradable, either by type, or because the grade is 0 $question_type = Sensei()->question->get_question_type($question_id); $achievable_grade = Sensei()->question->get_question_grade($question_id); // Question has a zero grade, so skip grading if (0 == $achievable_grade) { $all_question_grades[$question_id] = $achievable_grade; } elseif (in_array($question_type, $autogradable_question_types)) { // Get user question grade $question_grade = Sensei_Utils::sensei_grade_question_auto($question_id, $question_type, $answer, $user_id); $all_question_grades[$question_id] = $question_grade; $grade_total += $question_grade; } else { // There is a question that cannot be autograded $quiz_autogradable = false; } // end if in_array( $question_type... } // end for each question // Only if the whole quiz was autogradable do we set a grade if ($quiz_autogradable) { $quiz_total = Sensei_Utils::sensei_get_quiz_total($quiz_id); // Check for zero total from grades if (0 < $quiz_total) { $grade = abs(round(doubleval($grade_total) * 100 / $quiz_total, 2)); } else { $grade = 0; } Sensei_Utils::sensei_grade_quiz($quiz_id, $grade, $user_id, $quiz_grade_type); } else { $grade = new WP_Error('autograde', __('This quiz is not able to be automatically graded.', 'woothemes-sensei')); } // store the auto gradable grades. If the quiz is not auto gradable the grades can be use as the default // when doing manual grading. Sensei()->quiz->set_user_grades($all_question_grades, $lesson_id, $user_id); return $grade; }
/** * Delete all user activity when user is deleted * @param integer $user_id User ID * @return void */ public function delete_user_activity($user_id = 0) { if ($user_id) { Sensei_Utils::delete_all_user_activity($user_id); } }
/** * Sets the statuses for the Course * * @access public * @since 1.7.0 * @param int $user_id * @param int $course_id * @param string $status * @param array $metadata * @return mixed false or comment_ID */ public static function update_course_status($user_id, $course_id, $status = 'in-progress', $metadata = array()) { $comment_id = false; if (!empty($status)) { $args = array('user_id' => $user_id, 'post_id' => $course_id, 'status' => $status, 'type' => 'sensei_course_status', 'action' => 'update', 'keep_time' => true); if ('in-progress' == $status) { unset($args['keep_time']); // Keep updating what's happened } $comment_id = Sensei_Utils::sensei_log_activity($args); if ($comment_id && !empty($metadata)) { foreach ($metadata as $key => $value) { update_comment_meta($comment_id, $key, $value); } } do_action('sensei_course_status_updated', $status, $user_id, $course_id, $comment_id); } return $comment_id; }
/** * Returns the lesson status class * * must be used in the loop. * @since 1.9.0 * * @return string $status_class */ function get_the_lesson_status_class() { $status_class = ''; $lesson_completed = Sensei_Utils::user_completed_lesson(get_the_ID(), get_current_user_id()); if ($lesson_completed) { $status_class = 'completed'; } return $status_class; }
/** * Calculate module progess for user * * @since 1.8.0 * * @param integer $user_id ID of user * @param integer $module_id ID of module * @param integer $course_id ID of course * @return integer Module progress percentage */ public function calculate_user_module_progress($user_id = 0, $module_id = 0, $course_id = 0) { $args = array('post_type' => 'lesson', 'post_status' => 'publish', 'posts_per_page' => -1, 'tax_query' => array(array('taxonomy' => $this->taxonomy, 'field' => 'id', 'terms' => $module_id)), 'meta_query' => array(array('key' => '_lesson_course', 'value' => $course_id)), 'fields' => 'ids'); $lessons = get_posts($args); if (is_wp_error($lessons) || 0 >= count($lessons)) { return 0; } $completed = false; $lesson_count = 0; $completed_count = 0; foreach ($lessons as $lesson_id) { $completed = Sensei_Utils::user_completed_lesson($lesson_id, $user_id); ++$lesson_count; if ($completed) { ++$completed_count; } } $module_progress = $completed_count / $lesson_count * 100; return (double) $module_progress; }
/** * Prepare the table with different parameters, pagination, columns and table elements * @since 1.7.0 * @return void */ public function prepare_items() { global $per_page, $wp_version; // Handle orderby $orderby = ''; if (!empty($_GET['orderby'])) { if (array_key_exists(esc_html($_GET['orderby']), $this->get_sortable_columns())) { $orderby = esc_html($_GET['orderby']); } // End If Statement } // Handle order $order = 'DESC'; if (!empty($_GET['order'])) { $order = 'ASC' == strtoupper($_GET['order']) ? 'ASC' : 'DESC'; } // Handle search $search = false; if (!empty($_GET['s'])) { $search = esc_html($_GET['s']); } // End If Statement $this->search = $search; // Searching users on statuses requires sub-selecting the statuses by user_ids if ($this->search) { $user_args = array('search' => '*' . $this->search . '*', 'fields' => 'ID'); // Filter for extending $user_args = apply_filters('sensei_grading_search_users', $user_args); if (!empty($user_args)) { $learners_search = new WP_User_Query($user_args); // Store for reuse on counts $this->user_ids = $learners_search->get_results(); } } // End If Statement $per_page = $this->get_items_per_page('sensei_comments_per_page'); $per_page = apply_filters('sensei_comments_per_page', $per_page, 'sensei_comments'); $paged = $this->get_pagenum(); $offset = 0; if (!empty($paged)) { $offset = $per_page * ($paged - 1); } // End If Statement $activity_args = array('type' => 'sensei_lesson_status', 'number' => $per_page, 'offset' => $offset, 'orderby' => $orderby, 'order' => $order, 'status' => 'any'); if ($this->lesson_id) { $activity_args['post_id'] = $this->lesson_id; } elseif ($this->course_id) { // Currently not possible to restrict to a single Course, as that requires WP_Comment to support multiple // post_ids (i.e. every lesson within the Course), WP 4.1 ( https://core.trac.wordpress.org/changeset/29808 ) if (version_compare($wp_version, '4.1', '>=')) { $activity_args['post__in'] = Sensei()->course->course_lessons($this->course_id, 'any', 'ids'); } } // Sub select to group of learners if ($this->user_ids) { $activity_args['user_id'] = (array) $this->user_ids; } // Restrict to a single Learner if ($this->user_id) { $activity_args['user_id'] = $this->user_id; } switch ($this->view) { case 'in-progress': $activity_args['status'] = 'in-progress'; break; case 'ungraded': $activity_args['status'] = 'ungraded'; break; case 'graded': $activity_args['status'] = array('graded', 'passed', 'failed'); break; case 'all': default: $activity_args['status'] = 'any'; break; } // End switch $activity_args = apply_filters('sensei_grading_filter_statuses', $activity_args); // WP_Comment_Query doesn't support SQL_CALC_FOUND_ROWS, so instead do this twice $total_statuses = Sensei_Utils::sensei_check_for_activity(array_merge($activity_args, array('count' => true, 'offset' => 0, 'number' => 0))); // Ensure we change our range to fit (in case a search threw off the pagination) - Should this be added to all views? if ($total_statuses < $activity_args['offset']) { $new_paged = floor($total_statuses / $activity_args['number']); $activity_args['offset'] = $new_paged * $activity_args['number']; } $statuses = Sensei_Utils::sensei_check_for_activity($activity_args, true); // Need to always return an array, even with only 1 item if (!is_array($statuses)) { $statuses = array($statuses); } $this->total_items = $total_statuses; $this->items = $statuses; $total_items = $this->total_items; $total_pages = ceil($total_items / $per_page); $this->set_pagination_args(array('total_items' => $total_items, 'total_pages' => $total_pages, 'per_page' => $per_page)); }
<?php } // lessons count > 0 ?> <h2 class="total-grade"> <?php _e('Total Grade', 'woothemes-sensei'); ?> <span class="lesson-grade"> <?php $course_user_grade = Sensei_Utils::sensei_course_user_grade($course->ID, get_current_user_id()); echo $course_user_grade . '%'; ?> </span> </h2> </article> <?php /** * Fires inside course-results/lessons.php after the * is uer logged check, at the bottom of all lessons. * * @since 1.4.0
/** * Compare the user's subscriptions end date with the date * the user was added to the course. If the user was added after * the subscription ended they were manually added and this will return * true. * * Important to note that all subscriptions for the user is compared. * * @since 1.9.0 * * @param $user_id * @param $product_id * @param $course_id * * @return bool */ public static function was_user_added_without_subscription($user_id, $product_id, $course_id) { $course_start_date = ''; $subscription_start_date = ''; $is_a_subscription = ''; $was_user_added_without_subscription = true; // if user is not on the course they were not added if (!Sensei_Utils::user_started_course($course_id, $user_id)) { return false; } // if user doesn't have a subscription and is taking the course // they were added manually if (!wcs_user_has_subscription($user_id, $product_id) && Sensei_Utils::user_started_course($course_id, get_current_user_id())) { return true; } $course_status = Sensei_Utils::user_course_status($course_id, $user_id); // comparing dates setup data $course_start_date = date_create($course_status->comment_date); $subscriptions = wcs_get_users_subscriptions($user_id); // comparing every subscription foreach ($subscriptions as $subscription) { // for the following statuses we know the user was not added // manually $status = $subscription->get_status(); if (in_array($status, array('pending-canceled', 'active', 'on-hold', 'pending'))) { continue; } $current_subscription_start_date = date_create($subscription->modified_date); // is the last updated subscription date newer than course start date if ($current_subscription_start_date > $course_start_date) { return false; } } return $was_user_added_without_subscription; }