Exemple #1
0
 /**
  * Checks if a user has completed a course by checking every lesson status
  *
  * @since  1.7.0
  * @param  integer $course_id Course ID
  * @param  integer $user_id   User ID
  * @return int
  */
 public static function user_complete_course($course_id = 0, $user_id = 0)
 {
     global $wp_version;
     if ($course_id) {
         if (!$user_id) {
             $user_id = get_current_user_id();
         }
         $course_status = 'in-progress';
         $course_metadata = array();
         $course_completion = Sensei()->settings->settings['course_completion'];
         $lessons_completed = $total_lessons = 0;
         $lesson_status_args = array('user_id' => $user_id, 'status' => 'any', 'type' => 'sensei_lesson_status');
         // Grab all of this Courses' lessons, looping through each...
         $lesson_ids = Sensei()->course->course_lessons($course_id, 'any', 'ids');
         $total_lessons = count($lesson_ids);
         // ...if course completion not set to 'passed', and all lessons are complete or graded,
         // ......then all lessons are 'passed'
         // ...else if course completion is set to 'passed', check if each lesson has questions...
         // ......if no questions yet the status is 'complete'
         // .........then the lesson is 'passed'
         // ......else if questions check the lesson status has a grade and that the grade is greater than the lesson passmark
         // .........then the lesson is 'passed'
         // ...if all lessons 'passed' then update the course status to complete
         // The below checks if a lesson is fully completed, though maybe should be Utils::user_completed_lesson()
         $all_lesson_statuses = array();
         // In WordPress 4.1 get_comments() allows a single query to cover multiple comment_post_IDs
         if (version_compare($wp_version, '4.1', '>=')) {
             $lesson_status_args['post__in'] = $lesson_ids;
             $all_lesson_statuses = Sensei_Utils::sensei_check_for_activity($lesson_status_args, true);
             // Need to always return an array, even with only 1 item
             if (!is_array($all_lesson_statuses)) {
                 $all_lesson_statuses = array($all_lesson_statuses);
             }
         } else {
             foreach ($lesson_ids as $lesson_id) {
                 $lesson_status_args['post_id'] = $lesson_id;
                 $each_lesson_status = Sensei_Utils::sensei_check_for_activity($lesson_status_args, true);
                 // Check for valid return before using
                 if (!empty($each_lesson_status->comment_approved)) {
                     $all_lesson_statuses[] = $each_lesson_status;
                 }
             }
         }
         foreach ($all_lesson_statuses as $lesson_status) {
             // If lessons are complete without needing quizzes to be passed
             if ('passed' != $course_completion) {
                 switch ($lesson_status->comment_approved) {
                     // A user cannot 'complete' a course if a lesson...
                     case 'in-progress':
                         // ...is still in progress
                     // ...is still in progress
                     case 'ungraded':
                         // ...hasn't yet been graded
                         break;
                     default:
                         $lessons_completed++;
                         break;
                 }
             } else {
                 switch ($lesson_status->comment_approved) {
                     case 'complete':
                         // Lesson has no quiz/questions
                     // Lesson has no quiz/questions
                     case 'graded':
                         // Lesson has quiz, but it's not important what the grade was
                     // Lesson has quiz, but it's not important what the grade was
                     case 'passed':
                         // Lesson has quiz and the user passed
                         $lessons_completed++;
                         break;
                         // A user cannot 'complete' a course if on a lesson...
                     // A user cannot 'complete' a course if on a lesson...
                     case 'failed':
                         // ...a user failed the passmark on a quiz
                     // ...a user failed the passmark on a quiz
                     default:
                         break;
                 }
             }
         }
         // Each lesson
         if ($lessons_completed == $total_lessons) {
             $course_status = 'complete';
         }
         // Update meta data on how many lessons have been completed
         $course_metadata['complete'] = $lessons_completed;
         // update the overall percentage of the course lessons complete (or graded) compared to 'in-progress' regardless of the above
         $course_metadata['percent'] = abs(round(doubleval($lessons_completed) * 100 / $total_lessons, 0));
         $activity_logged = Sensei_Utils::update_course_status($user_id, $course_id, $course_status, $course_metadata);
         // Allow further actions
         if ('complete' == $course_status) {
             do_action('sensei_user_course_end', $user_id, $course_id);
         }
         return $activity_logged;
     }
     return false;
 }
Exemple #2
0
 /**
  * Reset user submitted questions
  *
  * This function resets the quiz data for a user that has been submitted fro grading already. It is different to
  * the save_user_answers as currently the saved and submitted answers are stored differently.
  *
  * @since 1.7.4
  * @access public
  *
  * @return bool $reset_success
  * @param int $user_id
  * @param int $lesson_id
  */
 public function reset_user_lesson_data($lesson_id, $user_id = 0)
 {
     //make sure the parameters are valid
     if (empty($lesson_id) || empty($user_id) || 'lesson' != get_post_type($lesson_id) || !get_userdata($user_id)) {
         return false;
     }
     //get the users lesson status to make
     $user_lesson_status = Sensei_Utils::user_lesson_status($lesson_id, $user_id);
     if (!isset($user_lesson_status->comment_ID)) {
         // this user is not taking this lesson so this process is not needed
         return false;
     }
     //get the lesson quiz and course
     $quiz_id = Sensei()->lesson->lesson_quizzes($lesson_id);
     $course_id = Sensei()->lesson->get_course_id($lesson_id);
     // reset the transients
     $answers_transient_key = 'sensei_answers_' . $user_id . '_' . $lesson_id;
     $grades_transient_key = 'quiz_grades_' . $user_id . '_' . $lesson_id;
     $answers_feedback_transient_key = 'sensei_answers_feedback_' . $user_id . '_' . $lesson_id;
     delete_transient($answers_transient_key);
     delete_transient($grades_transient_key);
     delete_transient($answers_feedback_transient_key);
     // reset the quiz answers and feedback notes
     $deleted_answers = Sensei_Utils::delete_user_data('quiz_answers', $lesson_id, $user_id);
     $deleted_grades = Sensei_Utils::delete_user_data('quiz_grades', $lesson_id, $user_id);
     $deleted_user_feedback = Sensei_Utils::delete_user_data('quiz_answers_feedback', $lesson_id, $user_id);
     // Delete quiz answers, this auto deletes the corresponding meta data, such as the question/answer grade
     Sensei_Utils::sensei_delete_quiz_answers($quiz_id, $user_id);
     Sensei_Utils::update_lesson_status($user_id, $lesson_id, 'in-progress', array('questions_asked' => '', 'grade' => ''));
     // Update course completion
     Sensei_Utils::update_course_status($user_id, $course_id);
     // Run any action on quiz/lesson reset (previously this didn't occur on resetting a quiz, see resetting a lesson in sensei_complete_lesson()
     do_action('sensei_user_lesson_reset', $user_id, $lesson_id);
     Sensei()->frontend->messages = '<div class="sensei-message note">' . __('Quiz Reset Successfully.', 'woothemes-sensei') . '</div>';
     return $deleted_answers && $deleted_grades;
 }
 public function sensei_complete_course()
 {
     global $post, $current_user, $wp_query;
     if (isset($_POST['course_complete']) && wp_verify_nonce($_POST['woothemes_sensei_complete_course_noonce'], 'woothemes_sensei_complete_course_noonce')) {
         $sanitized_submit = esc_html($_POST['course_complete']);
         $sanitized_course_id = absint(esc_html($_POST['course_complete_id']));
         // Handle submit data
         switch ($sanitized_submit) {
             case __('Mark as Complete', 'woothemes-sensei'):
                 // Add user to course
                 $course_metadata = array('start' => current_time('mysql'), 'percent' => 0, 'complete' => 0);
                 $activity_logged = Sensei_Utils::update_course_status($current_user->ID, $sanitized_course_id, 'in-progress', $course_metadata);
                 if ($activity_logged) {
                     // Get all course lessons
                     $course_lesson_ids = Sensei()->course->course_lessons($sanitized_course_id, 'any', 'ids');
                     // Mark all quiz user meta lessons as complete
                     foreach ($course_lesson_ids as $lesson_item_id) {
                         // Mark lesson as complete
                         $activity_logged = Sensei_Utils::sensei_start_lesson($lesson_item_id, $current_user->ID, $complete = true);
                     }
                     // End For Loop
                     // Update with final stats
                     $course_metadata = array('percent' => 100, 'complete' => count($course_lesson_ids));
                     $activity_logged = Sensei_Utils::update_course_status($current_user->ID, $sanitized_course_id, 'complete', $course_metadata);
                     do_action('sensei_user_course_end', $current_user->ID, $sanitized_course_id);
                     // Success message
                     $this->messages = '<header class="archive-header"><div class="sensei-message tick">' . sprintf(__('%1$s marked as complete.', 'woothemes-sensei'), get_the_title($sanitized_course_id)) . '</div></header>';
                 }
                 // End If Statement
                 break;
             case __('Delete Course', 'woothemes-sensei'):
                 Sensei_Utils::sensei_remove_user_from_course($sanitized_course_id, $current_user->ID);
                 // Success message
                 $this->messages = '<header class="archive-header"><div class="sensei-message tick">' . sprintf(__('%1$s deleted.', 'woothemes-sensei'), get_the_title($sanitized_course_id)) . '</div></header>';
                 break;
             default:
                 // Nothing
                 break;
         }
         // End Switch Statement
     }
     // End If Statement
 }
 /**
  * Force the re-calculation of all Course statuses working from all Lesson statuses
  *
  * @global type $woothemes_sensei
  * @global type $wpdb
  * @param type $n
  * @param type $offset
  * @return boolean
  */
 function status_changes_repair_course_statuses($n = 50, $offset = 0)
 {
     global $wpdb;
     $count_object = wp_count_posts('lesson');
     $count_published = $count_object->publish;
     if (0 == $count_published) {
         return true;
     }
     // Calculate if this is the last page
     if (0 == $offset) {
         $current_page = 1;
     } else {
         $current_page = intval($offset / $n);
     }
     $total_pages = ceil($count_published / $n);
     $course_lesson_ids = $lesson_user_statuses = array();
     // Get all Lesson => Course relationships
     $meta_list = $wpdb->get_results("SELECT {$wpdb->postmeta}.post_id, {$wpdb->postmeta}.meta_value FROM {$wpdb->postmeta} INNER JOIN {$wpdb->posts} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id) WHERE {$wpdb->posts}.post_type = 'lesson' AND {$wpdb->postmeta}.meta_key = '_lesson_course' LIMIT {$n} OFFSET {$offset} ", ARRAY_A);
     if (!empty($meta_list)) {
         foreach ($meta_list as $metarow) {
             $lesson_id = $metarow['post_id'];
             $course_id = $metarow['meta_value'];
             $course_lesson_ids[$course_id][] = $lesson_id;
         }
     }
     // Get all Lesson => Course relationships
     $status_list = $wpdb->get_results("SELECT user_id, comment_post_ID, comment_approved FROM {$wpdb->comments} WHERE comment_type = 'sensei_lesson_status' GROUP BY user_id, comment_post_ID ", ARRAY_A);
     if (!empty($status_list)) {
         foreach ($status_list as $status) {
             $lesson_user_statuses[$status['comment_post_ID']][$status['user_id']] = $status['comment_approved'];
         }
     }
     $course_completion = Sensei()->settings->settings['course_completion'];
     $per_page = 40;
     $comment_id_offset = $count = 0;
     $course_sql = "SELECT * FROM {$wpdb->comments} WHERE comment_type = 'sensei_course_status' AND comment_ID > %d LIMIT {$per_page}";
     // $per_page users at a time
     while ($course_statuses = $wpdb->get_results($wpdb->prepare($course_sql, $comment_id_offset))) {
         foreach ($course_statuses as $course_status) {
             $user_id = $course_status->user_id;
             $course_id = $course_status->comment_post_ID;
             $total_lessons = count($course_lesson_ids[$course_id]);
             if ($total_lessons <= 0) {
                 $total_lessons = 1;
                 // Fix division of zero error, some courses have no lessons
             }
             $lessons_completed = 0;
             $status = 'in-progress';
             // Some Courses have no lessons... (can they ever be complete?)
             if (!empty($course_lesson_ids[$course_id])) {
                 foreach ($course_lesson_ids[$course_id] as $lesson_id) {
                     $lesson_status = $lesson_user_statuses[$lesson_id][$user_id];
                     // If lessons are complete without needing quizzes to be passed
                     if ('passed' != $course_completion) {
                         switch ($lesson_status) {
                             // A user cannot 'complete' a course if a lesson...
                             case 'in-progress':
                                 // ...is still in progress
                             // ...is still in progress
                             case 'ungraded':
                                 // ...hasn't yet been graded
                                 break;
                             default:
                                 $lessons_completed++;
                                 break;
                         }
                     } else {
                         switch ($lesson_status) {
                             case 'complete':
                                 // Lesson has no quiz/questions
                             // Lesson has no quiz/questions
                             case 'graded':
                                 // Lesson has quiz, but it's not important what the grade was
                             // Lesson has quiz, but it's not important what the grade was
                             case 'passed':
                                 // Lesson has quiz and the user passed
                                 $lessons_completed++;
                                 break;
                                 // A user cannot 'complete' a course if on a lesson...
                             // A user cannot 'complete' a course if on a lesson...
                             case 'failed':
                                 // ...a user failed the passmark on a quiz
                             // ...a user failed the passmark on a quiz
                             default:
                                 break;
                         }
                     }
                 }
                 // Each lesson
             }
             // Check for lessons
             if ($lessons_completed == $total_lessons) {
                 $status = 'complete';
             }
             // update the overall percentage of the course lessons complete (or graded) compared to 'in-progress' regardless of the above
             $metadata = array('complete' => $lessons_completed, 'percent' => abs(round(doubleval($lessons_completed) * 100 / $total_lessons, 0)));
             Sensei_Utils::update_course_status($user_id, $course_id, $status, $metadata);
             $count++;
         }
         // per course status
         $comment_id_offset = $course_status->comment_ID;
     }
     // all course statuses
     if ($current_page == $total_pages) {
         return true;
     } else {
         return false;
     }
 }