/**
  * Update question answers to use new data structure
  *
  * @since 1.3.0
  * @access public
  * @return void
  */
 public function update_question_answer_data($n = 50, $offset = 0)
 {
     // Get Total Number of Updates to run
     $quiz_count_object = wp_count_posts('quiz');
     $quiz_count_published = $quiz_count_object->publish;
     // Calculate if this is the last page
     if (0 == $offset) {
         $current_page = 1;
     } else {
         $current_page = intval($offset / $n);
     }
     // End If Statement
     $total_pages = intval($quiz_count_published / $n);
     $args = array('post_type' => 'quiz', 'numberposts' => $n, 'offset' => $offset, 'post_status' => 'publish', 'suppress_filters' => 0);
     $quizzes = get_posts($args);
     $old_answers = array();
     $right_answers = array();
     $old_user_answers = array();
     if (is_array($quizzes)) {
         foreach ($quizzes as $quiz) {
             $quiz_id = $quiz->ID;
             // Get current user answers
             $comments = WooThemes_Sensei_Utils::sensei_check_for_activity(array('post_id' => $quiz_id, 'type' => 'sensei_quiz_answers'), true);
             // Need to always return an array, even with only 1 item
             if (!is_array($comments)) {
                 $comments = array($comments);
             }
             foreach ($comments as $comment) {
                 $user_id = $comment->user_id;
                 $content = maybe_unserialize(base64_decode($comment->comment_content));
                 $old_user_answers[$quiz_id][$user_id] = $content;
             }
             // Get correct answers
             $questions = WooThemes_Sensei_Utils::sensei_get_quiz_questions($quiz_id);
             if (is_array($questions)) {
                 foreach ($questions as $question) {
                     $right_answer = get_post_meta($question->ID, '_question_right_answer', true);
                     $right_answers[$quiz_id][$question->ID] = $right_answer;
                 }
             }
         }
     }
     if (is_array($right_answers)) {
         foreach ($right_answers as $quiz_id => $question) {
             $count = 0;
             if (is_array($question)) {
                 foreach ($question as $question_id => $answer) {
                     ++$count;
                     if (isset($old_user_answers[$quiz_id])) {
                         $answers_linkup[$quiz_id][$count] = $question_id;
                     }
                 }
             }
         }
     }
     if (is_array($old_user_answers)) {
         foreach ($old_user_answers as $quiz_id => $user_answers) {
             foreach ($user_answers as $user_id => $answers) {
                 foreach ($answers as $answer_id => $user_answer) {
                     $question_id = $answers_linkup[$quiz_id][$answer_id];
                     $new_user_answers[$question_id] = $user_answer;
                     WooThemes_Sensei_Utils::sensei_grade_question_auto($question_id, '', $user_answer, $user_id);
                 }
                 $lesson_id = get_post_meta($quiz_id, '_quiz_lesson', true);
                 WooThemes_Sensei_Utils::sensei_start_lesson($lesson_id, $user_id);
                 WooThemes_Sensei_Utils::sensei_save_quiz_answers($new_user_answers, $user_id);
             }
         }
     }
     if ($current_page == $total_pages) {
         return true;
     } else {
         return false;
     }
     // End If Statement
 }
 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 = WooThemes_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) {
                     WooThemes_Sensei_Utils::sensei_start_lesson($id, $user_id, true);
                 }
                 // Updates the Course status and it's meta data
                 WooThemes_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 = WooThemes_Sensei_Utils::sensei_start_lesson($lesson_id, $user_id, $complete);
             // Updates the Course status and it's meta data
             WooThemes_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;
 }
 public function sensei_complete_course()
 {
     global $post, $woothemes_sensei, $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 apply_filters('sensei_mark_as_complete_text', __('Mark as Complete', 'woothemes-sensei')):
                 // Add user to course
                 $course_metadata = array('start' => current_time('mysql'), 'percent' => 0, 'complete' => 0);
                 $activity_logged = WooThemes_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 = $woothemes_sensei->post_types->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 = WooThemes_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 = WooThemes_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 apply_filters('sensei_delete_course_text', __('Delete Course', 'woothemes-sensei')):
                 WooThemes_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
 }
    public function sensei_complete_quiz()
    {
        global $post, $woothemes_sensei, $current_user;
        // Default grade
        $grade = 0;
        // Get Quiz Questions
        $lesson_quiz_questions = $woothemes_sensei->post_types->lesson->lesson_quiz_questions($post->ID);
        $quiz_lesson_id = absint(get_post_meta($post->ID, '_quiz_lesson', true));
        // Get quiz grade type
        $quiz_grade_type = get_post_meta($post->ID, '_quiz_grade_type', true);
        // Get quiz pass setting
        $pass_required = get_post_meta($post->ID, '_pass_required', true);
        // Get quiz pass mark
        $quiz_passmark = abs(round(doubleval(get_post_meta($post->ID, '_quiz_passmark', true)), 2));
        // Handle Quiz Completion
        if (isset($_POST['quiz_complete']) && wp_verify_nonce($_POST['woothemes_sensei_complete_quiz_noonce'], 'woothemes_sensei_complete_quiz_noonce')) {
            $sanitized_submit = esc_html($_POST['quiz_complete']);
            $questions_asked = array_filter(array_map('absint', $_POST['questions_asked']));
            $questions_asked_string = implode(',', $questions_asked);
            switch ($sanitized_submit) {
                case apply_filters('sensei_complete_quiz_text', __('Complete Quiz', 'woothemes-sensei')):
                    // Mark the Lesson as in-progress (if it isn't already), the entry is needed for WooThemes_Sensei_Utils::sensei_grade_quiz_auto() (optimise at some point?)
                    $activity_logged = WooThemes_Sensei_Utils::sensei_start_lesson($quiz_lesson_id);
                    $lesson_status = 'ungraded';
                    // Default when completing a quiz
                    // Save questions that were asked in this quiz
                    if (!empty($questions_asked_string)) {
                        update_comment_meta($activity_logged, 'questions_asked', $questions_asked_string);
                    }
                    // Save Quiz Answers
                    if (isset($_POST['sensei_question'])) {
                        WooThemes_Sensei_Utils::sensei_save_quiz_answers($_POST['sensei_question']);
                    }
                    // Grade quiz
                    // 3rd arg is count of total number of questions but it's not used by sensei_grade_quiz_auto()
                    $grade = WooThemes_Sensei_Utils::sensei_grade_quiz_auto($post->ID, $_POST['sensei_question'], count($lesson_quiz_questions), $quiz_grade_type);
                    $lesson_metadata = array();
                    // Get Lesson Grading Setting
                    if (is_wp_error($grade) || 'auto' != $quiz_grade_type) {
                        $lesson_status = 'ungraded';
                        // Quiz is manually graded and this was a user submission
                    } else {
                        // Quiz has been automatically Graded
                        if ($pass_required) {
                            // Student has reached the pass mark and lesson is complete
                            if ($quiz_passmark <= $grade) {
                                $lesson_status = 'passed';
                            } else {
                                $lesson_status = 'failed';
                            }
                            // End If Statement
                        } else {
                            $lesson_status = 'graded';
                        }
                        $lesson_metadata['grade'] = $grade;
                        // Technically already set as part of "WooThemes_Sensei_Utils::sensei_grade_quiz_auto()" above
                    }
                    WooThemes_Sensei_Utils::update_lesson_status($current_user->ID, $quiz_lesson_id, $lesson_status, $lesson_metadata);
                    switch ($lesson_status) {
                        case 'passed':
                        case 'graded':
                            do_action('sensei_user_lesson_end', $current_user->ID, $quiz_lesson_id);
                            break;
                    }
                    do_action('sensei_user_quiz_submitted', $current_user->ID, $post->ID, $grade, $quiz_passmark, $quiz_grade_type);
                    break;
                case apply_filters('sensei_save_quiz_text', __('Save Quiz', 'woothemes-sensei')):
                    $activity_logged = WooThemes_Sensei_Utils::sensei_start_lesson($quiz_lesson_id);
                    if ($activity_logged) {
                        // Save questions that were asked in this quiz
                        if (!empty($questions_asked_string)) {
                            update_comment_meta($activity_logged, 'questions_asked', $questions_asked_string);
                        }
                        if (isset($_POST['sensei_question'])) {
                            WooThemes_Sensei_Utils::sensei_save_quiz_answers($_POST['sensei_question']);
                        }
                    }
                    // Need message in case the data wasn't saved?
                    $this->messages = '<div class="sensei-message note">' . apply_filters('sensei_quiz_saved_text', __('Quiz Saved Successfully.', 'woothemes-sensei')) . '</div>';
                    break;
                case apply_filters('sensei_reset_quiz_text', __('Reset Quiz', 'woothemes-sensei')):
                    // Don't want to remove the lesson status (such as start meta data etc), just remove the answers, the questions asked meta and any grade meta
                    // Delete quiz answers, this auto deletes the corresponding meta data, such as the question/answer grade
                    WooThemes_Sensei_Utils::sensei_delete_quiz_answers($post->ID, $user_id);
                    WooThemes_Sensei_Utils::update_lesson_status($current_user->ID, $quiz_lesson_id, 'in-progress', array('questions_asked' => '', 'grade' => ''));
                    // 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', $current_user->ID, $quiz_lesson_id);
                    $this->messages = '<div class="sensei-message note">' . apply_filters('sensei_quiz_reset_text', __('Quiz Reset Successfully.', 'woothemes-sensei')) . '</div>';
                    break;
                default:
                    // Nothing
                    break;
            }
            // End Switch Statement
            // Refresh page to avoid re-posting
            ?>
			<script type="text/javascript"> window.location = '<?php 
            echo get_permalink($post->ID);
            ?>
'; </script>
			<?php 
        }
        // End If Statement, submission of quiz
        $this->data = new stdClass();
        // Get latest quiz answers and grades
        $user_quizzes = $this->sensei_get_user_quiz_answers($post->ID);
        $user_lesson_status = WooThemes_Sensei_Utils::user_lesson_status($quiz_lesson_id, $current_user->ID);
        $user_quiz_grade = 0;
        if (isset($user_lesson_status->comment_ID)) {
            $user_quiz_grade = get_comment_meta($user_lesson_status->comment_ID, 'grade', true);
        }
        if (!is_array($user_quizzes)) {
            $user_quizzes = array();
        }
        // Check again that the lesson is complete
        $user_lesson_end = WooThemes_Sensei_Utils::user_completed_lesson($user_lesson_status);
        $user_lesson_complete = false;
        if ($user_lesson_end) {
            $user_lesson_complete = true;
        }
        // End If Statement
        $reset_allowed = get_post_meta($post->ID, '_enable_quiz_reset', true);
        // Build frontend data object
        $this->data->user_quizzes = $user_quizzes;
        $this->data->user_quiz_grade = $user_quiz_grade;
        $this->data->quiz_passmark = $quiz_passmark;
        $this->data->quiz_lesson = $quiz_lesson_id;
        $this->data->quiz_grade_type = $quiz_grade_type;
        $this->data->user_lesson_end = $user_lesson_end;
        $this->data->user_lesson_complete = $user_lesson_complete;
        $this->data->lesson_quiz_questions = $lesson_quiz_questions;
        $this->data->reset_quiz_allowed = $reset_allowed;
    }
Exemple #5
0
 /**
  * This test Woothemes_Sensei()->quiz->get_user_answers_feedback transients only
  *
  * @group transient
  */
 function testGetUserFeedbackTransients()
 {
     // setup the test data
     global $woothemes_sensei;
     $test_user_id = wp_create_user('studFBTransientsGet', 'studFBTransientsGet', '*****@*****.**');
     $test_lesson_id = $this->factory->get_random_lesson_id();
     $transient_key = 'sensei_answers_feedback_' . $test_user_id . '_' . $test_lesson_id;
     $transient_get_test = array(base64_encode('studFBTransientsGet'));
     $transient_get_test_decoded = array('studFBTransientsGet');
     set_transient($transient_key, $transient_get_test, 10 * DAY_IN_SECONDS);
     $users_retrieved_answers = $woothemes_sensei->quiz->get_user_answers_feedback($test_lesson_id, $test_user_id);
     // test if the answer is taken from the transient
     $this->assertEquals($transient_get_test_decoded, $users_retrieved_answers, 'The transient was not used before proceeding to get the users answers from DB');
     //setup next assertion
     $test_quiz_id = $woothemes_sensei->lesson->lesson_quizzes($test_lesson_id);
     $test_user_answers_feedback = $this->factory->generate_user_answers_feedback($test_quiz_id);
     WooThemes_Sensei_Utils::sensei_start_lesson($test_lesson_id, $test_user_id);
     $woothemes_sensei->quiz->save_user_answers_feedback($test_user_answers_feedback, $test_lesson_id, $test_user_id);
     delete_site_transient($transient_key);
     $woothemes_sensei->quiz->get_user_answers_feedback($test_lesson_id, $test_user_id);
     $transient_data_after_get_call = get_transient($transient_key);
     // test if a transient is created when one does not exist
     // in this test we first delete the transient after it is been added in the save_user_answers
     // function above, then we get the data again and test if the function added the transient
     $this->assertNotFalse($transient_data_after_get_call, ' The get_user_answers function does not set the transient after retrieving the data ');
     // make sure the one of the keys passed in is in the transient
     $random_key = array_rand($test_user_answers_feedback);
     $this->assertArrayHasKey($random_key, $transient_data_after_get_call, 'The transient does not contain the same elements that we passed in');
     //make sure the number of elements passes in is the same as what is in the new transient cache
     $this->assertEquals(count($test_user_answers_feedback), count($transient_data_after_get_call), 'The number of elements in the transient does not match those the user submitted');
 }
 /**
  * Save the user's answers feedback
  *
  * For this function you must supply all three parameters. If will return false one is left out.
  * The data will be saved on the lesson ID supplied.
  *
  * @since 1.7.5
  * @access public
  *
  * @param array $answers_feedback{
  *  $type int $question_id
  *  $type string $question_feedback
  * }
  * @param int $lesson_id
  * @param int $user_id
  *
  * @return false or int $feedback_saved
  */
 public function save_user_answers_feedback($answers_feedback, $lesson_id, $user_id = 0)
 {
     // make sure the parameters are valid before continuing
     if (empty($lesson_id) || empty($user_id) || 'lesson' != get_post_type($lesson_id) || !get_userdata($user_id) || !is_array($answers_feedback)) {
         return false;
     }
     global $woothemes_sensei;
     // check if the lesson is started before saving, if not start the lesson for the user
     if (!(0 < intval(WooThemes_Sensei_Utils::user_started_lesson($lesson_id, $user_id)))) {
         WooThemes_Sensei_Utils::sensei_start_lesson($lesson_id, $user_id);
     }
     // encode the feedback
     $encoded_answers_feedback = array();
     foreach ($answers_feedback as $question_id => $feedback) {
         $encoded_answers_feedback[$question_id] = base64_encode($feedback);
     }
     // save the user data
     $feedback_saved = WooThemes_Sensei_Utils::add_user_data('quiz_answers_feedback', $lesson_id, $encoded_answers_feedback, $user_id);
     //Were the the question feedback save correctly?
     if (intval($feedback_saved) > 0) {
         // save transient to make retrieval faster in future
         $transient_key = 'sensei_answers_feedback_' . $user_id . '_' . $lesson_id;
         set_transient($transient_key, $encoded_answers_feedback, 10 * DAY_IN_SECONDS);
     }
     return $feedback_saved;
 }