/** * 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) . ' ' . 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 . ' ' . 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)) . ' ' . 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; }
/** * 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;