/**
  * Sets up the object course query
  * that will be used int he render method.
  *
  * @since 1.9.0
  */
 protected function setup_course_query()
 {
     $status_query = array('user_id' => get_current_user_id(), 'type' => 'sensei_course_status');
     $course_statuses = WooThemes_Sensei_Utils::sensei_check_for_activity($status_query, true);
     // User may only be on 1 Course
     if (!is_array($course_statuses)) {
         $course_statuses = array($course_statuses);
     }
     $completed_ids = $active_ids = array();
     foreach ($course_statuses as $course_status) {
         if (WooThemes_Sensei_Utils::user_completed_course($course_status, get_current_user_id())) {
             $completed_ids[] = $course_status->comment_post_ID;
         } else {
             $active_ids[] = $course_status->comment_post_ID;
         }
     }
     if ('completed' == $this->status) {
         $included_courses = $completed_ids;
     } elseif ('active' == $this->status) {
         $included_courses = $active_ids;
     } else {
         $included_courses = array_merge($active_ids, $completed_ids);
     }
     // course query parameters
     $query_args = array('post_type' => 'course', 'post_status' => 'publish', 'orderby' => $this->orderby, 'order' => $this->order, 'posts_per_page' => $this->number, 'post__in' => $included_courses);
     $this->query = new WP_Query($query_args);
 }
 /**
  * Return array of course statuses
  * @since  1.7.0
  * @return array statuses
  */
 private function get_course_statuses($args)
 {
     $activity_args = array('post_id' => $this->course_id, 'type' => 'sensei_course_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_course_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_course_filter_statuses', $activity_args);
     // WP_Comment_Query doesn't support SQL_CALC_FOUND_ROWS, so instead do this twice
     $this->total_items = WooThemes_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 = WooThemes_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;
 }
 /**
  * Prepare the table with different parameters, pagination, columns and table elements
  * @since  1.7.0
  * @return void
  */
 public function prepare_items()
 {
     global $woothemes_sensei, $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'] = $woothemes_sensei->post_types->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 = WooThemes_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 = WooThemes_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));
 }
    /**
     * 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 $woothemes_sensei, $current_user;
        get_currentuserinfo();
        $course_ids = array();
        if ('activecourses' == esc_attr($instance['component'])) {
            $courses = WooThemes_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 = WooThemes_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 = $woothemes_sensei->post_types->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 {
                $posts_array = $woothemes_sensei->post_types->course->course_query(intval($instance['limit']), esc_attr($instance['component']));
            }
        }
        // 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($woothemes_sensei->settings->settings['course_author']) && $woothemes_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 $woothemes_sensei->post_types->course->course_lesson_count($post_id) . '&nbsp;' . apply_filters('sensei_lessons_text', __('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($woothemes_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.
            $course_status = substr(esc_attr($instance['component']), 0, -7);
            echo sprintf(__('You have no %1s courses.', 'woothemes-sensei'), $course_status);
        }
        // End If Statement
    }
 public function sensei_course_preview_titles($title, $lesson_id)
 {
     global $post, $current_user, $woothemes_sensei;
     $course_id = $post->ID;
     $title_text = '';
     if (method_exists('WooThemes_Sensei_Utils', 'is_preview_lesson') && WooThemes_Sensei_Utils::is_preview_lesson($lesson_id)) {
         $is_user_taking_course = WooThemes_Sensei_Utils::sensei_check_for_activity(array('post_id' => $course_id, 'user_id' => $current_user->ID, 'type' => 'sensei_course_status'));
         if (!$is_user_taking_course) {
             if (method_exists('WooThemes_Sensei_Frontend', 'sensei_lesson_preview_title_text')) {
                 $title_text = $woothemes_sensei->frontend->sensei_lesson_preview_title_text($course_id);
                 // Remove brackets for display here
                 $title_text = str_replace('(', '', $title_text);
                 $title_text = str_replace(')', '', $title_text);
                 $title_text = '<span class="preview-label">' . $title_text . '</span>';
             }
             $title .= ' ' . $title_text;
         }
     }
     return $title;
 }
 /**
  * Return array of Course statuses
  * @since  1.7.0
  * @return array statuses
  */
 private function get_course_statuses($args)
 {
     $activity_args = array('user_id' => $this->user_id, 'type' => 'sensei_course_status', 'number' => $args['number'], 'offset' => $args['offset'], 'orderby' => $args['orderby'], 'order' => $args['order'], 'status' => 'any');
     $activity_args = apply_filters('sensei_analysis_user_profile_filter_statuses', $activity_args);
     // WP_Comment_Query doesn't support SQL_CALC_FOUND_ROWS, so instead do this twice
     $this->total_items = WooThemes_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 = WooThemes_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;
 }
 /**
  * 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 = WooThemes_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;
 }
    /**
     * display output to the admin view
     * @since  1.3.0
     * @return html
     */
    public function display()
    {
        // Get data for the user
        $questions = $this->build_data_array();
        $count = 0;
        $graded_count = 0;
        $user_quiz_grade_total = 0;
        $quiz_grade_total = 0;
        $quiz_grade = 0;
        ?>
<form name="<?php 
        esc_attr_e('quiz_' . $this->quiz_id);
        ?>
" action="" method="post">
			<?php 
        wp_nonce_field('sensei_manual_grading', '_wp_sensei_manual_grading_nonce');
        ?>
			<input type="hidden" name="sensei_manual_grade" value="<?php 
        esc_attr_e($this->quiz_id);
        ?>
" />
			<input type="hidden" name="sensei_grade_next_learner" value="<?php 
        esc_attr_e($this->user_id);
        ?>
" />
			<div class="total_grade_display">
				<span><?php 
        esc_attr_e(__('Grade:', 'woothemes-sensei'));
        ?>
</span>
				<span class="total_grade_total"><?php 
        echo $user_quiz_grade_total;
        ?>
</span> / <span class="quiz_grade_total"><?php 
        echo $quiz_grade_total;
        ?>
</span> (<span class="total_grade_percent"><?php 
        echo $quiz_grade;
        ?>
</span>%)
			</div>
			<div class="buttons">
				<input type="submit" value="<?php 
        esc_attr_e(__('Save', 'woothemes-sensei'));
        ?>
" class="grade-button button-primary" title="Saves grades as currently marked on this page" />
				<input type="button" value="<?php 
        esc_attr_e(__('Auto grade', 'woothemes-sensei'));
        ?>
" class="autograde-button button-secondary" title="Where possible, automatically grades questions that have not yet been graded" />
				<input type="reset" value="<?php 
        esc_attr_e(__('Reset', 'woothemes-sensei'));
        ?>
" class="reset-button button-secondary" title="Resets all questions to ungraded and total grade to 0" />
			</div>
			<div class="clear"></div><br/><?php 
        $lesson_status_id = WooThemes_Sensei_Utils::sensei_get_activity_value(array('post_id' => $this->lesson_id, 'user_id' => $this->user_id, 'type' => 'sensei_lesson_status', 'field' => 'comment_ID'));
        $user_quiz_grade = get_comment_meta($lesson_status_id, 'grade', true);
        $correct_answers = 0;
        foreach ($questions as $question) {
            $question_id = $question->ID;
            ++$count;
            $type = false;
            $type_name = '';
            $types = wp_get_post_terms($question_id, 'question-type');
            foreach ($types as $t) {
                $type = $t->name;
                break;
            }
            if (!$type) {
                $type = 'multiple-choice';
            }
            $user_answer = WooThemes_Sensei_Utils::sensei_check_for_activity(array('post_id' => $question_id, 'user_id' => $this->user_id, 'type' => 'sensei_user_answer'), true);
            $question_answer_notes = WooThemes_Sensei_Utils::sensei_get_user_question_answer_notes($user_answer);
            $question_grade_total = get_post_meta($question_id, '_question_grade', true);
            if (!$question_grade_total || 0 == intval($question_grade_total)) {
                $question_grade_total = 1;
            }
            $quiz_grade_total += $question_grade_total;
            $right_answer = get_post_meta($question_id, '_question_right_answer', true);
            $user_answer_content = maybe_unserialize(base64_decode($user_answer->comment_content));
            $type_name = __('Multiple Choice', 'woothemes-sensei');
            $grade_type = 'manual-grade';
            switch ($type) {
                case 'boolean':
                    $type_name = __('True/False', 'woothemes-sensei');
                    $right_answer = ucfirst($right_answer);
                    $user_answer_content = ucfirst($user_answer_content);
                    $grade_type = 'auto-grade';
                    break;
                case 'multiple-choice':
                    $type_name = __('Multiple Choice', 'woothemes-sensei');
                    $grade_type = 'auto-grade';
                    break;
                case 'gap-fill':
                    $type_name = __('Gap Fill', 'woothemes-sensei');
                    $right_answer_array = explode('||', $right_answer);
                    if (isset($right_answer_array[0])) {
                        $gapfill_pre = $right_answer_array[0];
                    } else {
                        $gapfill_pre = '';
                    }
                    if (isset($right_answer_array[1])) {
                        $gapfill_gap = $right_answer_array[1];
                    } else {
                        $gapfill_gap = '';
                    }
                    if (isset($right_answer_array[2])) {
                        $gapfill_post = $right_answer_array[2];
                    } else {
                        $gapfill_post = '';
                    }
                    if (!$user_answer_content) {
                        $user_answer_content = '______';
                    }
                    $right_answer = $gapfill_pre . ' <span class="highlight">' . $gapfill_gap . '</span> ' . $gapfill_post;
                    $user_answer_content = $gapfill_pre . ' <span class="highlight">' . $user_answer_content . '</span> ' . $gapfill_post;
                    $grade_type = 'auto-grade';
                    break;
                case 'multi-line':
                    $type_name = __('Multi Line', 'woothemes-sensei');
                    $grade_type = 'manual-grade';
                    break;
                case 'single-line':
                    $type_name = __('Single Line', 'woothemes-sensei');
                    $grade_type = 'manual-grade';
                    break;
                case 'file-upload':
                    $type_name = __('File Upload', 'woothemes-sensei');
                    $grade_type = 'manual-grade';
                    // Get uploaded file
                    if ($user_answer_content) {
                        $attachment_id = $user_answer_content;
                        $answer_media_url = $answer_media_filename = '';
                        if (0 < intval($attachment_id)) {
                            $answer_media_url = wp_get_attachment_url($attachment_id);
                            $answer_media_filename = basename($answer_media_url);
                            if ($answer_media_url && $answer_media_filename) {
                                $user_answer_content = sprintf(__('Submitted file: %1$s', 'woothemes-sensei'), '<a href="' . esc_url($answer_media_url) . '" target="_blank">' . esc_html($answer_media_filename) . '</a>');
                            }
                        }
                    } else {
                        $user_answer_content = '';
                    }
                    break;
                default:
                    // Nothing
                    break;
            }
            $user_answer_content = (array) $user_answer_content;
            $right_answer = (array) $right_answer;
            $question_title = sprintf(__('Question %d: ', 'woothemes-sensei'), $count) . $type_name;
            $graded_class = '';
            $user_question_grade = get_comment_meta($user_answer->comment_ID, 'user_grade', true);
            $graded_class = 'ungraded';
            if (intval($user_question_grade) > 0) {
                $graded_class = 'user_right';
                ++$correct_answers;
                $user_quiz_grade_total += $user_question_grade;
                ++$graded_count;
            } else {
                if (!is_string($user_question_grade) && intval($user_question_grade) == 0) {
                    $graded_class = 'user_wrong';
                    ++$graded_count;
                }
                $user_question_grade = 0;
            }
            ?>
<div class="postbox question_box <?php 
            esc_attr_e($type);
            ?>
 <?php 
            esc_attr_e($grade_type);
            ?>
 <?php 
            esc_attr_e($graded_class);
            ?>
" id="<?php 
            esc_attr_e('question_' . $question_id . '_box');
            ?>
">
				<div class="handlediv" title="Click to toggle"><br></div>
				<h3 class="hndle"><span><?php 
            echo $question_title;
            ?>
</span></h3>
				<div class="inside">
					<div class="sensei-grading-actions">
						<div class="actions">
							<input type="hidden" class="question_id" value="<?php 
            esc_attr_e($question_id);
            ?>
" />
							<input type="hidden" class="question_total_grade" name="question_total_grade" value="<?php 
            echo $question_grade_total;
            ?>
" />
							<span class="grading-mark icon_right"><input type="radio" class="<?php 
            esc_attr_e('question_' . $question_id . '_right_option');
            ?>
" name="<?php 
            esc_attr_e('question_' . $question_id);
            ?>
" value="right" <?php 
            checked($graded_class, 'user_right', true);
            ?>
 /></span>
							<span class="grading-mark icon_wrong"><input type="radio" class="<?php 
            esc_attr_e('question_' . $question_id . '_wrong_option');
            ?>
" name="<?php 
            esc_attr_e('question_' . $question_id);
            ?>
" value="wrong" <?php 
            checked($graded_class, 'user_wrong', true);
            ?>
 /></span>
							<input type="number" class="question-grade" name="<?php 
            esc_attr_e('question_' . $question_id . '_grade');
            ?>
" id="<?php 
            esc_attr_e('question_' . $question_id . '_grade');
            ?>
" value="<?php 
            esc_attr_e($user_question_grade);
            ?>
" min="0" max="<?php 
            esc_attr_e($question_grade_total);
            ?>
" />
							<span class="question-grade-total"><?php 
            echo $question_grade_total;
            ?>
</span>
						</div>
					</div>
					<div class="sensei-grading-answer">
						<h4><?php 
            echo apply_filters('sensei_question_title', $question->post_title);
            ?>
</h4>
						<?php 
            echo apply_filters('the_content', $question->post_content);
            ?>
						<p class="user-answer"><?php 
            foreach ($user_answer_content as $_user_answer) {
                echo apply_filters('sensei_answer_text', $_user_answer) . "<br>";
            }
            ?>
</p>
						<div class="right-answer">
							<h5><?php 
            _e('Correct answer', 'woothemes-sensei');
            ?>
</h5>
							<span class="correct-answer"><?php 
            foreach ($right_answer as $_right_answer) {
                echo apply_filters('sensei_answer_text', $_right_answer) . "<br>";
            }
            ?>
</span>
						</div>
						<div class="answer-notes">
							<h5><?php 
            _e('Grading Notes', 'woothemes-sensei');
            ?>
</h5>
							<textarea class="correct-answer" name="<?php 
            esc_attr_e('question_' . $question_id . '_notes');
            ?>
" placeholder="<?php 
            _e('Add notes here...', 'woothemes-sensei');
            ?>
"><?php 
            echo $question_answer_notes;
            ?>
</textarea>
						</div>
					</div>
				</div>
			</div><?php 
        }
        $quiz_grade = intval($user_quiz_grade);
        $all_graded = 'no';
        if (intval($count) == intval($graded_count)) {
            $all_graded = 'yes';
        }
        ?>
  <input type="hidden" name="total_grade" id="total_grade" value="<?php 
        esc_attr_e($user_quiz_grade_total);
        ?>
" />
			<input type="hidden" name="total_questions" id="total_questions" value="<?php 
        esc_attr_e($count);
        ?>
" />
			<input type="hidden" name="quiz_grade_total" id="quiz_grade_total" value="<?php 
        esc_attr_e($quiz_grade_total);
        ?>
" />
			<input type="hidden" name="total_graded_questions" id="total_graded_questions" value="<?php 
        esc_attr_e($graded_count);
        ?>
" />
			<input type="hidden" name="all_questions_graded" id="all_questions_graded" value="<?php 
        esc_attr_e($all_graded);
        ?>
" />
			<div class="total_grade_display">
				<span><?php 
        esc_attr_e(__('Grade:', 'woothemes-sensei'));
        ?>
</span>
				<span class="total_grade_total"><?php 
        echo $user_quiz_grade_total;
        ?>
</span> / <span class="quiz_grade_total"><?php 
        echo $quiz_grade_total;
        ?>
</span> (<span class="total_grade_percent"><?php 
        echo $quiz_grade;
        ?>
</span>%)
			</div>
			<div class="buttons">
				<input type="submit" value="<?php 
        esc_attr_e('Save');
        ?>
" class="grade-button button-primary" title="Saves grades as currently marked on this page" />
				<input type="button" value="<?php 
        esc_attr_e(__('Auto grade', 'woothemes-sensei'));
        ?>
" class="autograde-button button-secondary" title="Where possible, automatically grades questions that have not yet been graded" />
				<input type="reset" value="<?php 
        esc_attr_e(__('Reset', 'woothemes-sensei'));
        ?>
" class="reset-button button-secondary" title="Resets all questions to ungraded and total grade to 0" />
			</div>
			<div class="clear"></div>
			<script type="text/javascript">
				jQuery( window ).load( function() {
					// Calculate total grade on page load to make sure everything is set up correctly
					jQuery.fn.autoGrade();
				});
			</script>
		</form><?php 
    }
$user_quiz_grade = $woothemes_sensei->frontend->data->user_quiz_grade;
$lesson_complete = $woothemes_sensei->frontend->data->user_lesson_complete;
$reset_quiz_allowed = $woothemes_sensei->frontend->data->reset_quiz_allowed;
// Question Meta
$question_id = $question_item->ID;
$question_right_answer = get_post_meta($question_id, '_question_right_answer', true);
$question_wrong_answers = get_post_meta($question_id, '_question_wrong_answers', true);
$question_helptext = '';
if (isset($question_wrong_answers[0])) {
    $question_helptext = $question_wrong_answers[0];
}
$question_grade = get_post_meta($question_id, '_question_grade', true);
if (!$question_grade || $question_grade == '') {
    $question_grade = 1;
}
$user_answer_entry = WooThemes_Sensei_Utils::sensei_check_for_activity(array('post_id' => $question_id, 'user_id' => $current_user->ID, 'type' => 'sensei_user_answer'), true);
$user_question_grade = WooThemes_Sensei_Utils::sensei_get_user_question_grade($user_answer_entry);
// Get uploaded file
$attachment_id = $user_quizzes[$question_id];
$answer_media_url = $answer_media_filename = '';
if (0 < intval($attachment_id)) {
    $answer_media_url = wp_get_attachment_url($attachment_id);
    $answer_media_filename = basename($answer_media_url);
}
// Get max upload file size, formatted for display
// Code copied from wp-admin/includes/media.php:1515
$upload_size_unit = $max_upload_size = wp_max_upload_size();
$sizes = array('KB', 'MB', 'GB');
for ($u = -1; $upload_size_unit > 1024 && $u < count($sizes) - 1; $u++) {
    $upload_size_unit /= 1024;
}
    /**
     * load_user_courses_content generates HTML for user's active & completed courses
     * @since  1.4.0
     * @param  object  $user   Queried user object
     * @param  boolean $manage Whether the user has permission to manage the courses
     * @return string          HTML displayng course data
     */
    public function load_user_courses_content($user = false, $manage = false)
    {
        global $woothemes_sensei, $post, $wp_query, $course, $my_courses_page, $my_courses_section;
        // Build Output HTML
        $complete_html = $active_html = '';
        if ($user) {
            $my_courses_page = true;
            // Allow action to be run before My Courses content has loaded
            do_action('sensei_before_my_courses', $user->ID);
            // Logic for Active and Completed Courses
            $per_page = 20;
            if (isset($woothemes_sensei->settings->settings['my_course_amount']) && 0 < absint($woothemes_sensei->settings->settings['my_course_amount'])) {
                $per_page = absint($woothemes_sensei->settings->settings['my_course_amount']);
            }
            $course_statuses = WooThemes_Sensei_Utils::sensei_check_for_activity(array('user_id' => $user->ID, 'type' => 'sensei_course_status'), true);
            // User may only be on 1 Course
            if (!is_array($course_statuses)) {
                $course_statuses = array($course_statuses);
            }
            $completed_ids = $active_ids = array();
            foreach ($course_statuses as $course_status) {
                if (WooThemes_Sensei_Utils::user_completed_course($course_status, $user->ID)) {
                    $completed_ids[] = $course_status->comment_post_ID;
                } else {
                    $active_ids[] = $course_status->comment_post_ID;
                }
            }
            $active_count = $completed_count = 0;
            $active_courses = array();
            if (0 < intval(count($active_ids))) {
                $my_courses_section = 'active';
                $active_courses = $woothemes_sensei->post_types->course->course_query($per_page, 'usercourses', $active_ids);
                $active_count = count($active_ids);
            }
            // End If Statement
            $completed_courses = array();
            if (0 < intval(count($completed_ids))) {
                $my_courses_section = 'completed';
                $completed_courses = $woothemes_sensei->post_types->course->course_query($per_page, 'usercourses', $completed_ids);
                $completed_count = count($completed_ids);
            }
            // End If Statement
            $lesson_count = 1;
            $active_page = 1;
            if (isset($_GET['active_page']) && 0 < intval($_GET['active_page'])) {
                $active_page = $_GET['active_page'];
            }
            $completed_page = 1;
            if (isset($_GET['completed_page']) && 0 < intval($_GET['completed_page'])) {
                $completed_page = $_GET['completed_page'];
            }
            foreach ($active_courses as $course_item) {
                $course_lessons = $woothemes_sensei->post_types->course->course_lessons($course_item->ID);
                $lessons_completed = 0;
                foreach ($course_lessons as $lesson) {
                    if (WooThemes_Sensei_Utils::user_completed_lesson($lesson->ID, $user->ID)) {
                        ++$lessons_completed;
                    }
                }
                // Get Course Categories
                $category_output = get_the_term_list($course_item->ID, 'course-category', '', ', ', '');
                $active_html .= '<article class="' . esc_attr(join(' ', get_post_class(array('course', 'post'), $course_item->ID))) . '">';
                // Image
                $active_html .= $woothemes_sensei->post_types->course->course_image(absint($course_item->ID));
                // Title
                $active_html .= '<header>';
                $active_html .= '<h2><a href="' . esc_url(get_permalink(absint($course_item->ID))) . '" title="' . esc_attr($course_item->post_title) . '">' . esc_html($course_item->post_title) . '</a></h2>';
                $active_html .= '</header>';
                $active_html .= '<section class="entry">';
                $active_html .= '<p class="sensei-course-meta">';
                // Author
                $user_info = get_userdata(absint($course_item->post_author));
                if (isset($woothemes_sensei->settings->settings['course_author']) && $woothemes_sensei->settings->settings['course_author']) {
                    $active_html .= '<span class="course-author">' . __('by ', 'woothemes-sensei') . '<a href="' . esc_url(get_author_posts_url(absint($course_item->post_author))) . '" title="' . esc_attr($user_info->display_name) . '">' . esc_html($user_info->display_name) . '</a></span>';
                }
                // End If Statement
                // Lesson count for this author
                $lesson_count = $woothemes_sensei->post_types->course->course_lesson_count(absint($course_item->ID));
                // Handle Division by Zero
                if (0 == $lesson_count) {
                    $lesson_count = 1;
                }
                // End If Statement
                $active_html .= '<span class="course-lesson-count">' . $lesson_count . '&nbsp;' . apply_filters('sensei_lessons_text', __('Lessons', 'woothemes-sensei')) . '</span>';
                // Course Categories
                if ('' != $category_output) {
                    $active_html .= '<span class="course-category">' . sprintf(__('in %s', 'woothemes-sensei'), $category_output) . '</span>';
                }
                // End If Statement
                $active_html .= '<span class="course-lesson-progress">' . sprintf(__('%1$d of %2$d lessons completed', 'woothemes-sensei'), $lessons_completed, $lesson_count) . '</span>';
                $active_html .= '</p>';
                $active_html .= '<p class="course-excerpt">' . apply_filters('get_the_excerpt', $course_item->post_excerpt) . '</p>';
                $progress_percentage = abs(round(doubleval($lessons_completed) * 100 / $lesson_count, 0));
                $active_html .= $this->get_progress_meter($progress_percentage);
                $active_html .= '</section>';
                if ($manage) {
                    $active_html .= '<section class="entry-actions">';
                    $active_html .= '<form method="POST" action="' . esc_url(remove_query_arg(array('active_page', 'completed_page'))) . '">';
                    $active_html .= '<input type="hidden" name="' . esc_attr('woothemes_sensei_complete_course_noonce') . '" id="' . esc_attr('woothemes_sensei_complete_course_noonce') . '" value="' . esc_attr(wp_create_nonce('woothemes_sensei_complete_course_noonce')) . '" />';
                    $active_html .= '<input type="hidden" name="course_complete_id" id="course-complete-id" value="' . esc_attr(absint($course_item->ID)) . '" />';
                    if (0 < absint(count($course_lessons)) && $woothemes_sensei->settings->settings['course_completion'] == 'complete') {
                        $active_html .= '<span><input name="course_complete" type="submit" class="course-complete" value="' . apply_filters('sensei_mark_as_complete_text', __('Mark as Complete', 'woothemes-sensei')) . '"/></span>';
                    }
                    // End If Statement
                    $course_purchased = false;
                    if (WooThemes_Sensei_Utils::sensei_is_woocommerce_activated()) {
                        // Get the product ID
                        $wc_post_id = get_post_meta(absint($course_item->ID), '_course_woocommerce_product', true);
                        if (0 < $wc_post_id) {
                            $course_purchased = WooThemes_Sensei_Utils::sensei_customer_bought_product($user->user_email, $user->ID, $wc_post_id);
                        }
                        // End If Statement
                    }
                    // End If Statement
                    if (!$course_purchased) {
                        $active_html .= '<span><input name="course_complete" type="submit" class="course-delete" value="' . apply_filters('sensei_delete_course_text', __('Delete Course', 'woothemes-sensei')) . '"/></span>';
                    }
                    // End If Statement
                    $active_html .= '</form>';
                    $active_html .= '</section>';
                }
                $active_html .= '</article>';
            }
            // Active pagination
            if ($active_count > $per_page) {
                $current_page = 1;
                if (isset($_GET['active_page']) && 0 < intval($_GET['active_page'])) {
                    $current_page = $_GET['active_page'];
                }
                $active_html .= '<nav class="pagination woo-pagination">';
                $total_pages = ceil($active_count / $per_page);
                $link = '';
                if ($current_page > 1) {
                    $prev_link = add_query_arg('active_page', $current_page - 1);
                    $active_html .= '<a class="prev page-numbers" href="' . esc_url($prev_link) . '">' . __('Previous', 'woothemes-sensei') . '</a> ';
                }
                for ($i = 1; $i <= $total_pages; $i++) {
                    $link = add_query_arg('active_page', $i);
                    if ($i == $current_page) {
                        $active_html .= '<span class="page-numbers current">' . $i . '</span> ';
                    } else {
                        $active_html .= '<a class="page-numbers" href="' . esc_url($link) . '">' . $i . '</a> ';
                    }
                }
                if ($current_page < $total_pages) {
                    $next_link = add_query_arg('active_page', $current_page + 1);
                    $active_html .= '<a class="next page-numbers" href="' . esc_url($next_link) . '">' . __('Next', 'woothemes-sensei') . '</a> ';
                }
                $active_html .= '</nav>';
            }
            foreach ($completed_courses as $course_item) {
                $course = $course_item;
                // Get Course Categories
                $category_output = get_the_term_list($course_item->ID, 'course-category', '', ', ', '');
                $complete_html .= '<article class="' . join(' ', get_post_class(array('course', 'post'), $course_item->ID)) . '">';
                // Image
                $complete_html .= $woothemes_sensei->post_types->course->course_image(absint($course_item->ID));
                // Title
                $complete_html .= '<header>';
                $complete_html .= '<h2><a href="' . esc_url(get_permalink(absint($course_item->ID))) . '" title="' . esc_attr($course_item->post_title) . '">' . esc_html($course_item->post_title) . '</a></h2>';
                $complete_html .= '</header>';
                $complete_html .= '<section class="entry">';
                $complete_html .= '<p class="sensei-course-meta">';
                // Author
                $user_info = get_userdata(absint($course_item->post_author));
                if (isset($woothemes_sensei->settings->settings['course_author']) && $woothemes_sensei->settings->settings['course_author']) {
                    $complete_html .= '<span class="course-author">' . __('by ', 'woothemes-sensei') . '<a href="' . esc_url(get_author_posts_url(absint($course_item->post_author))) . '" title="' . esc_attr($user_info->display_name) . '">' . esc_html($user_info->display_name) . '</a></span>';
                }
                // End If Statement
                // Lesson count for this author
                $complete_html .= '<span class="course-lesson-count">' . $woothemes_sensei->post_types->course->course_lesson_count(absint($course_item->ID)) . '&nbsp;' . apply_filters('sensei_lessons_text', __('Lessons', 'woothemes-sensei')) . '</span>';
                // Course Categories
                if ('' != $category_output) {
                    $complete_html .= '<span class="course-category">' . sprintf(__('in %s', 'woothemes-sensei'), $category_output) . '</span>';
                }
                // End If Statement
                $complete_html .= '</p>';
                $complete_html .= '<p class="course-excerpt">' . apply_filters('get_the_excerpt', $course_item->post_excerpt) . '</p>';
                $complete_html .= $this->get_progress_meter(100);
                if ($manage) {
                    $has_quizzes = $woothemes_sensei->post_types->course->course_quizzes($course_item->ID, true);
                    // Output only if there is content to display
                    if (has_filter('sensei_results_links') || $has_quizzes) {
                        $complete_html .= '<p class="sensei-results-links">';
                        $results_link = '';
                        if ($has_quizzes) {
                            $results_link = '<a class="button view-results" href="' . $woothemes_sensei->course_results->get_permalink($course_item->ID) . '">' . apply_filters('sensei_view_results_text', __('View results', 'woothemes-sensei')) . '</a>';
                        }
                        $complete_html .= apply_filters('sensei_results_links', $results_link);
                        $complete_html .= '</p>';
                    }
                }
                $complete_html .= '</section>';
                $complete_html .= '</article>';
            }
            // Active pagination
            if ($completed_count > $per_page) {
                $current_page = 1;
                if (isset($_GET['completed_page']) && 0 < intval($_GET['completed_page'])) {
                    $current_page = $_GET['completed_page'];
                }
                $complete_html .= '<nav class="pagination woo-pagination">';
                $total_pages = ceil($completed_count / $per_page);
                $link = '';
                if ($current_page > 1) {
                    $prev_link = add_query_arg('completed_page', $current_page - 1);
                    $complete_html .= '<a class="prev page-numbers" href="' . esc_url($prev_link) . '">' . __('Previous', 'woothemes-sensei') . '</a> ';
                }
                for ($i = 1; $i <= $total_pages; $i++) {
                    $link = add_query_arg('completed_page', $i);
                    if ($i == $current_page) {
                        $complete_html .= '<span class="page-numbers current">' . $i . '</span> ';
                    } else {
                        $complete_html .= '<a class="page-numbers" href="' . esc_url($link) . '">' . $i . '</a> ';
                    }
                }
                if ($current_page < $total_pages) {
                    $next_link = add_query_arg('completed_page', $current_page + 1);
                    $complete_html .= '<a class="next page-numbers" href="' . esc_url($next_link) . '">' . __('Next', 'woothemes-sensei') . '</a> ';
                }
                $complete_html .= '</nav>';
            }
        }
        // End If Statement
        if ($manage) {
            $no_active_message = apply_filters('sensei_no_active_courses_user_text', __('You have no active courses.', 'woothemes-sensei'));
            $no_complete_message = apply_filters('sensei_no_complete_courses_user_text', __('You have not completed any courses yet.', 'woothemes-sensei'));
        } else {
            $no_active_message = apply_filters('sensei_no_active_courses_learner_text', __('This learner has no active courses.', 'woothemes-sensei'));
            $no_complete_message = apply_filters('sensei_no_complete_courses_learner_text', __('This learner has not completed any courses yet.', 'woothemes-sensei'));
        }
        ob_start();
        ?>

		<?php 
        do_action('sensei_before_user_courses');
        ?>

		<?php 
        if ($manage && (!isset($woothemes_sensei->settings->settings['messages_disable']) || !$woothemes_sensei->settings->settings['messages_disable'])) {
            ?>
			<p class="my-messages-link-container"><a class="my-messages-link" href="<?php 
            echo get_post_type_archive_link('sensei_message');
            ?>
" title="<?php 
            _e('View & reply to private messages sent to your course & lesson teachers.', 'woothemes-sensei');
            ?>
"><?php 
            _e('My Messages', 'woothemes-sensei');
            ?>
</a></p>
			<?php 
        }
        ?>
		<div id="my-courses">

		    <ul>
		    	<li><a href="#active-courses"><?php 
        echo apply_filters('sensei_active_courses_text', __('Active Courses', 'woothemes-sensei'));
        ?>
</a></li>
		    	<li><a href="#completed-courses"><?php 
        echo apply_filters('sensei_completed_courses_text', __('Completed Courses', 'woothemes-sensei'));
        ?>
</a></li>
		    </ul>

		    <?php 
        do_action('sensei_before_active_user_courses');
        ?>

		    <?php 
        $course_page_id = intval($woothemes_sensei->settings->settings['course_page']);
        if (0 < $course_page_id) {
            $course_page_url = get_permalink($course_page_id);
        } elseif (0 == $course_page_id) {
            $course_page_url = get_post_type_archive_link('course');
        }
        ?>

		    <div id="active-courses">

		    	<?php 
        if ('' != $active_html) {
            echo $active_html;
        } else {
            ?>
		    		<div class="sensei-message info"><?php 
            echo $no_active_message;
            ?>
 <a href="<?php 
            echo $course_page_url;
            ?>
"><?php 
            apply_filters('sensei_start_a_course_text', _e('Start a Course!', 'woothemes-sensei'));
            ?>
</a></div>
		    	<?php 
        }
        // End If Statement
        ?>

		    </div>

		    <?php 
        do_action('sensei_after_active_user_courses');
        ?>

		    <?php 
        do_action('sensei_before_completed_user_courses');
        ?>

		    <div id="completed-courses">

		    	<?php 
        if ('' != $complete_html) {
            echo $complete_html;
        } else {
            ?>
		    		<div class="sensei-message info"><?php 
            echo $no_complete_message;
            ?>
</div>
		    	<?php 
        }
        // End If Statement
        ?>

		    </div>

		    <?php 
        do_action('sensei_after_completed_user_courses');
        ?>

		</div>

		<?php 
        do_action('sensei_after_user_courses');
        ?>

		<?php 
        return ob_get_clean();
    }
 /**
  * Returns the requested lesson status
  *
  * @since 1.7.0
  * @param int $lesson_id
  * @param int $user_id
  * @return object | bool
  */
 public static function user_lesson_status($lesson_id = 0, $user_id = 0)
 {
     global $woothemes_sensei;
     if ($lesson_id) {
         if (!$user_id) {
             $user_id = get_current_user_id();
         }
         $user_lesson_status = WooThemes_Sensei_Utils::sensei_check_for_activity(array('post_id' => $lesson_id, 'user_id' => $user_id, 'type' => 'sensei_lesson_status'), true);
         return $user_lesson_status;
     }
     return false;
 }
Exemple #12
0
 /**
  * This tests Sensei()->quiz->save_user_answers_feedback
  */
 public function testSaveUserAnswersFeedback()
 {
     // setup the data and objects needed for this test
     global $woothemes_sensei;
     $test_user_id = wp_create_user('studentFeedbackSave', 'studentFeedbackSave', '*****@*****.**');
     $test_lesson_id = $this->factory->get_random_lesson_id();
     $test_quiz_id = $woothemes_sensei->lesson->lesson_quizzes($test_lesson_id);
     // does the save_user_answers function exist?
     $this->assertTrue(method_exists($woothemes_sensei->quiz, 'save_user_answers_feedback'), 'The quiz class function `save_user_answers_feedback` does not exist ');
     // does this save_user_answers return false for bogus data
     $this->assertFalse($woothemes_sensei->quiz->save_user_answers_feedback(array(), array(), -1000, -200), 'save_user_answers_feedback does not return false for no existent users and lesson ');
     $this->assertFalse($woothemes_sensei->quiz->save_user_answers_feedback('', array(), '', ''), 'save_user_answers_feedback does not return false for empty parameters');
     // does the function return the correct information when a user doesn't exist?
     $this->assertFalse($woothemes_sensei->quiz->save_user_answers_feedback('', array(), '', $test_lesson_id), 'save_user_answers_feedback does not return false for empty user');
     $this->assertFalse($woothemes_sensei->quiz->save_user_answers_feedback('', array(), -500, $test_lesson_id), 'save_user_answers_feedback does not return false for a non existant user');
     // Test the answers_array parameter
     $this->assertFalse($woothemes_sensei->quiz->save_user_answers_feedback('Answers Text', array(), $test_lesson_id, $test_user_id), 'save_user_answers_feedback does not return false if answers is not passed in as an array');
     $this->assertFalse($woothemes_sensei->quiz->save_user_answers_feedback('', array(), $test_lesson_id, $test_user_id), 'save_user_answers_feedback does not return false for empty answer array');
     $this->assertFalse($woothemes_sensei->quiz->save_user_answers_feedback('', array(), '', ''), 'save_user_answers_feedback does not return false incorrectly formatted answers');
     // Test a case that is setup correctly which should return a positive result
     $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);
     $lesson_data_saved = $woothemes_sensei->quiz->save_user_answers_feedback($test_user_answers_feedback, $test_lesson_id, $test_user_id);
     // did the correct data return a valid comment id on the lesson as a result?
     $this->assertTrue(intval($lesson_data_saved) > 0, 'The comment id returned after saving the quiz feedback does not represent a valid comment ');
     //setup for the next group of assertions
     $sensei_activity_logged = WooThemes_Sensei_Utils::sensei_check_for_activity(array('post_id' => $test_lesson_id, 'user_id' => $test_user_id));
     $status_comment = WooThemes_Sensei_Utils::user_lesson_status($test_lesson_id, $test_user_id);
     $saved_feedback = get_comment_meta($status_comment->comment_ID, 'quiz_answers_feedback', true);
     // was the data that was just stored stored correctly ? Check the comment meta on the lesson id
     $this->assertTrue((bool) $sensei_activity_logged, 'The saved answers feedback was not stored correctly on the Lesson');
     $this->assertFalse(empty($saved_feedback), 'The saved feedback was not stored correctly on the Quiz');
     $this->assertTrue(is_array(maybe_unserialize($saved_feedback)), 'The saved feedback was not stored correctly on the Lesson');
     // can you retrieve data and is it the same as what was stored?
     //compare every single answer
     $retrieved_feedback_array = maybe_unserialize($saved_feedback);
     foreach ($test_user_answers_feedback as $question_id => $feedback) {
         $saved_single_answer = $retrieved_feedback_array[$question_id];
         $assert_message = 'The saved feedback does not correspond to what was passed into the save_user_answers_feedback function ';
         $this->assertEquals($feedback, base64_decode($saved_single_answer), $assert_message);
     }
     // end for each
 }
 /**
  * Get the user's answer feedback for a specific question.
  *
  * This function gives you a single answer note/feedback string
  * for the user on the given question.
  *
  * @since 1.7.5
  * @access public
  *
  * @param int $lesson_id
  * @param int $question_id
  * @param int $user_id
  *
  * @return string $feedback or bool if false
  */
 public function get_user_question_feedback($lesson_id, $question_id, $user_id = 0)
 {
     $feedback = false;
     // parameter validation
     if (empty($lesson_id) || empty($question_id) || !(intval($lesson_id) > 0) || !(intval($question_id) > 0) || 'lesson' != get_post_type($lesson_id) || 'question' != get_post_type($question_id)) {
         return false;
     }
     // get all the feedback for the user on the given lesson
     $all_feedback = $this->get_user_answers_feedback($lesson_id, $user_id);
     if (!$all_feedback || empty($all_feedback) || !is_array($all_feedback) || !isset($all_feedback[$question_id])) {
         //fallback to data pre 1.7.4
         // setup the sensei data query
         $args = array('post_id' => $question_id, 'user_id' => $user_id, 'type' => 'sensei_user_answer');
         $question_activity = WooThemes_Sensei_Utils::sensei_check_for_activity($args, true);
         // set the default to false and return that if no old data is available.
         if (isset($question_activity->comment_ID)) {
             $feedback = base64_decode(get_comment_meta($question_activity->comment_ID, 'answer_note', true));
         }
         // finally use the default question feedback
         if (empty($feedback)) {
             $feedback = get_post_meta($question_id, '_answer_feedback', true);
         }
         return $feedback;
     }
     return $all_feedback[$question_id];
 }
 /**
  * Sets the stats boxes to render
  * @since  1.2.0
  * @return $stats_to_render array of stats boxes and values
  */
 public function stats_boxes()
 {
     global $woothemes_sensei;
     // Get the data required
     $user_count = count_users();
     $user_count = apply_filters('sensei_analysis_total_users', $user_count['total_users'], $user_count);
     $total_courses = $woothemes_sensei->post_types->course->course_count(array('publish', 'private'));
     $total_lessons = $woothemes_sensei->post_types->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 = WooThemes_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 = WooThemes_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 = WooThemes_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);
 }
 /**
  * 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
 }
 /**
  * Return array of learners
  * @since  1.7.0
  * @return array learners
  */
 private function get_learners($args)
 {
     $user_ids = false;
     $post_id = 0;
     $activity = '';
     if ($this->lesson_id) {
         $post_id = intval($this->lesson_id);
         $activity = 'sensei_lesson_status';
     } elseif ($this->course_id) {
         $post_id = intval($this->course_id);
         $activity = 'sensei_course_status';
     }
     if (!$post_id || !$activity) {
         $this->total_items = 0;
         return array();
     }
     $activity_args = array('post_id' => $post_id, 'type' => $activity, 'status' => 'any', 'number' => $args['per_page'], 'offset' => $args['offset'], 'orderby' => $args['orderby'], 'order' => $args['order']);
     // Searching users on statuses requires sub-selecting the statuses by user_ids
     if ($args['search']) {
         $user_args = array('search' => '*' . $args['search'] . '*', 'fields' => 'ID');
         // Filter for extending
         $user_args = apply_filters('sensei_learners_search_users', $user_args);
         if (!empty($user_args)) {
             $learners_search = new WP_User_Query($user_args);
             $activity_args['user_id'] = $learners_search->get_results();
         }
     }
     $activity_args = apply_filters('sensei_learners_filter_users', $activity_args);
     // WP_Comment_Query doesn't support SQL_CALC_FOUND_ROWS, so instead do this twice
     $total_learners = WooThemes_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_learners < $activity_args['offset']) {
         $new_paged = floor($total_learners / $activity_args['number']);
         $activity_args['offset'] = $new_paged * $activity_args['number'];
     }
     $learners = WooThemes_Sensei_Utils::sensei_check_for_activity($activity_args, true);
     // Need to always return an array, even with only 1 item
     if (!is_array($learners)) {
         $learners = array($learners);
     }
     $this->total_items = $total_learners;
     return $learners;
 }
 *
 * @author 		WooThemes
 * @package 	Sensei/Templates
 * @version     1.0.0
 */
if (!defined('ABSPATH')) {
    exit;
}
global $post, $woothemes_sensei, $current_user;
$html = '';
// Get Course Lessons
$lessons_completed = 0;
$course_lessons = $woothemes_sensei->post_types->course->course_lessons($post->ID);
$total_lessons = count($course_lessons);
// Check if the user is taking the course
$is_user_taking_course = WooThemes_Sensei_Utils::sensei_check_for_activity(array('post_id' => $post->ID, 'user_id' => $current_user->ID, 'type' => 'sensei_course_status'));
// Get User Meta
get_currentuserinfo();
if (0 < $total_lessons) {
    $html .= '<section class="course-lessons">';
    $html .= '<header>';
    $html .= '<h2>' . apply_filters('sensei_lessons_text', __('Lessons', 'woothemes-sensei')) . '</h2>';
    if (is_user_logged_in() && $is_user_taking_course) {
        $html .= '<span class="course-completion-rate">' . sprintf(__('Currently completed %1$s of %2$s in total', 'woothemes-sensei'), '######', $total_lessons) . '</span>';
        $html .= '<div class="meter+++++"><span style="width: @@@@@%">@@@@@%</span></div>';
    }
    // End If Statement
    $html .= '</header>';
    $lesson_count = 1;
    $lessons_completed = 0;
    $show_lesson_numbers = false;