Created
August 14, 2018 15:14
-
-
Save joelworsham/dd1eee7f28a3b935e2ce59080457815e to your computer and use it in GitHub Desktop.
LearnDash Gradebook User Grade @ 1.3.6
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Contains the grade for a given user. | |
* | |
* @since 1.0.0 | |
* | |
* @package LearnDash_Gradebook | |
* @subpackage LearnDash_Gradebook/includes | |
*/ | |
defined( 'ABSPATH' ) || die(); | |
/** | |
* Class LD_GB_UserGrade | |
* | |
* Contains the grade for a given user's course. | |
* | |
* @since 1.0.0 | |
* | |
* @package LearnDash_Gradebook | |
* @subpackage LearnDash_Gradebook/includes | |
*/ | |
class LD_GB_UserGrade { | |
/** | |
* The Gradebook post. | |
* | |
* @since 1.2.0 | |
* @access private | |
* | |
* @var WP_Post | |
*/ | |
private $gradebook; | |
/** | |
* The user object for the grade. | |
* | |
* @since 1.0.0 | |
* @access private | |
* | |
* @var WP_User | |
*/ | |
private $user; | |
/** | |
* Arguments for the grade. | |
* | |
* @since 1.0.0 | |
* @access private | |
* | |
* @var array | |
*/ | |
private $args; | |
/** | |
* All of the components that go into the grade. | |
* | |
* @since 1.0.0 | |
* @access private | |
* | |
* @var array | |
*/ | |
private $components = array(); | |
/** | |
* Quizzes for this user and course. | |
* | |
* @since 1.0.0 | |
* @access private | |
* | |
* @var array | |
*/ | |
private $quizzes = array(); | |
/** | |
* Assignments for this user and course. | |
* | |
* @since 1.0.0 | |
* @access private | |
* | |
* @var array | |
*/ | |
private $assignments = array(); | |
/** | |
* Manually entered grades for htis user and course. | |
* | |
* @since 1.0.0 | |
* @access private | |
* | |
* @var array | |
*/ | |
private $manual_grades = array(); | |
/** | |
* The overal user grade. | |
* | |
* @since 1.0.0 | |
* @access private | |
* | |
* @var int|bool | |
*/ | |
private $user_grade = false; | |
/** | |
* Quizzes this user has taken. | |
* | |
* @since 1.0.0 | |
* @access private | |
* | |
* @var array|null | |
*/ | |
private $user_quizzes; | |
/** | |
* LD_GB_UserGrade constructor. | |
* | |
* @since 1.0.0 | |
* | |
* @param int|WP_User|bool $user The user or user ID to get the grade for. | |
* @param int||bool $gradebook The Gradebook ID. | |
* @param array $args Arguments for the object. | |
*/ | |
public function __construct( $user = false, $gradebook = false, $args = array() ) { | |
$this->gradebook = get_post( $gradebook ); | |
if ( ! $this->gradebook ) { | |
return; | |
} | |
$this->args = $this->setup_args( $args ); | |
$this->user = $this->setup_user( $user ); | |
if ( $this->user === false || $this->user->ID === 0 ) { | |
return; | |
} | |
$this->components = $this->build_components(); | |
$this->user_grade = $this->build_final_grade(); | |
} | |
/** | |
* Sets up the default args. | |
* | |
* @since 1.0.0 | |
* | |
* @param array $args The supplied args. | |
* | |
* @return array | |
*/ | |
private function setup_args( $args ) { | |
return wp_parse_args( $args, array( | |
'weight_type' => ld_gb_get_field( 'gradebook_weighting_enable', $this->gradebook->ID ) ? 'weighted' : 'equal', | |
'grade_precision' => ld_gb_get_option_field( 'grade_precision', 0 ), | |
'grade_round_mode' => ld_gb_get_option_field( 'grade_round_mode', 'ceil' ), | |
) ); | |
} | |
/** | |
* Sets up the user for the grade. | |
* | |
* @since 1.0.0 | |
* | |
* @param int|WP_User|false $_user The user or user ID to get the grade for. | |
* | |
* @return WP_User|false | |
*/ | |
private function setup_user( $_user ) { | |
if ( $_user === false ) { | |
$user = wp_get_current_user(); | |
} elseif ( $_user instanceof WP_User ) { | |
$user = $_user; | |
} elseif ( ! ( $user = get_user_by( 'id', $_user ) ) ) { | |
return false; | |
} | |
/** | |
* Filters the user to get the grade for. | |
* | |
* @since 1.0.0 | |
*/ | |
$user = apply_filters( 'ld_gb_user_grade_user', $user, $this->args ); | |
return $user; | |
} | |
/** | |
* Gets the various components and retrieves the grades. | |
* | |
* @since 1.0.0 | |
* | |
* @return array | |
*/ | |
private function build_components() { | |
// Get components | |
$components = ld_gb_get_field( 'components', $this->gradebook->ID ); | |
if ( ! $components ) { | |
return array(); | |
} | |
$course = ld_gb_get_field( 'course', $this->gradebook->ID ); | |
$course_progress = false; | |
$completion_grading_mode = ld_gb_get_field( 'completion_grading_mode', $this->gradebook->ID ); | |
if ( $course ) { | |
$all_progress = get_user_meta( $this->user->ID, '_sfwd-course_progress', true ); | |
if ( isset( $all_progress[ (int) $course ] ) ) { | |
$course_progress = $all_progress[ (int) $course ]; | |
} | |
} | |
$component_ordering = wp_parse_args( array_filter( array( | |
'orderby' => ld_gb_get_field( 'component_orderby', $this->gradebook->ID ), | |
'order' => ld_gb_get_field( 'component_order', $this->gradebook->ID ), | |
) ), array( | |
'orderby' => 'title', | |
'order' => 'asc', | |
) ); | |
/** | |
* How the component resources are ordered for the user grade. | |
* | |
* @since 1.3.0 | |
* | |
* @param array $component_ordering | |
* @param WP_Post $gradebook | |
*/ | |
$component_ordering = apply_filters( 'ld_gb_user_grade_ordering', $component_ordering, $this->gradebook ); | |
// If set to grade, remove, because this is custom ordering. | |
$orderby_grade = false; | |
if ( $component_ordering['orderby'] === 'grade' ) { | |
$orderby_grade = true; | |
$component_ordering['orderby'] = 'title'; | |
} | |
// Component overrides | |
$component_overrides = get_user_meta( $this->user->ID, "ld_gb_component_grades_{$this->gradebook->ID}", true ); | |
// Grab various grades | |
foreach ( $components as &$component ) { | |
$grades = array(); | |
// Quizzes | |
$quizzes = array(); | |
$quiz_args = array( | |
'post_type' => 'sfwd-quiz', | |
'numberposts' => - 1, | |
'orderby' => $component_ordering['orderby'], | |
'order' => $component_ordering['order'], | |
); | |
if ( $component['quizzes_all'] === '1' ) { | |
if ( $course ) { | |
$quiz_ids = learndash_course_get_steps_by_type( $course, 'sfwd-quiz' ); | |
foreach ( $quiz_ids as $quiz_id ) { | |
$quizzes[] = get_post( $quiz_id ); | |
} | |
} else { | |
$quizzes = get_posts( $quiz_args ); | |
} | |
} elseif ( isset( $component['quizzes'] ) && ! empty( $component['quizzes'] ) ) { | |
$quiz_args['post__in'] = $component['quizzes']; | |
$quizzes = get_posts( $quiz_args ); | |
} | |
$quiz_grades = array(); | |
if ( $quizzes ) { | |
foreach ( $quizzes as $quiz ) { | |
if ( $quiz_grade = $this->get_quiz_grade( $quiz ) ) { | |
$quiz_grades[] = $quiz_grade; | |
} | |
} | |
} | |
// Sort by grade if set | |
if ( $orderby_grade ) { | |
usort( | |
$quiz_grades, | |
array( | |
__CLASS__, | |
$component_ordering['order'] === 'asc' ? 'sort_by_score_asc' : 'sort_by_score_desc' | |
) | |
); | |
} | |
$grades = $grades + $quiz_grades; | |
// Assignments | |
$assignments = array(); | |
$assignment_args = array( | |
'post_type' => 'sfwd-assignment', | |
'numberposts' => - 1, | |
'orderby' => $component_ordering['orderby'], | |
'order' => $component_ordering['order'], | |
'meta_query' => array( | |
array( | |
'key' => 'approval_status', | |
'value' => '1', | |
), | |
), | |
); | |
if ( $component['assignments_all'] === '1' ) { | |
if ( $course ) { | |
$assignment_args['meta_key'] = 'course_id'; | |
$assignment_args['meta_value'] = $course; | |
} | |
$assignments = get_posts( $assignment_args ); | |
} elseif ( ( isset( $component['assignment_lessons'] ) && ! empty( $component['assignment_lessons'] ) ) || | |
( isset( $component['assignment_topics'] ) && ! empty( $component['assignment_topics'] ) ) ) { | |
$assignment_query = array( | |
'relation' => 'OR', | |
); | |
// NOTE: LearnDash uses "lesson_id" for both Lessons AND Topics (I know...). That's why you see it used | |
// in both queries here. | |
if ( isset( $component['assignment_lessons'] ) && ! empty( $component['assignment_lessons'] ) ) { | |
$assignment_query[] = array( | |
'key' => 'lesson_id', | |
'value' => $component['assignment_lessons'], | |
'compare' => 'IN', | |
); | |
} | |
if ( isset( $component['assignment_topics'] ) && ! empty( $component['assignment_topics'] ) ) { | |
$assignment_query[] = array( | |
'key' => 'lesson_id', | |
'value' => $component['assignment_topics'], | |
'compare' => 'IN', | |
); | |
} | |
$assignment_args['meta_query'][] = $assignment_query; | |
$assignments = get_posts( $assignment_args ); | |
} elseif ( isset( $component['assignments'] ) && ! empty( $component['assignments'] ) ) { | |
$assignment_args['post__in'] = $component['assignments']; | |
$assignments = get_posts( $assignment_args ); | |
} | |
$assignment_grades = array(); | |
if ( $assignments ) { | |
foreach ( $assignments as $assignment ) { | |
if ( $assignment_grade = $this->get_assignment_grade( $assignment ) ) { | |
$assignment_grades[] = $assignment_grade; | |
} | |
} | |
} | |
// Sort by grade if set | |
if ( $orderby_grade ) { | |
usort( | |
$assignment_grades, | |
array( | |
__CLASS__, | |
$component_ordering['order'] === 'asc' ? 'sort_by_score_asc' : 'sort_by_score_desc' | |
) | |
); | |
} | |
$grades = $grades + $assignment_grades; | |
if ( $course ) { | |
// Lessons | |
$lessons = array(); | |
$lesson_args = array( | |
'post_type' => 'sfwd-lessons', | |
'numberposts' => - 1, | |
'orderby' => $component_ordering['orderby'], | |
'order' => $component_ordering['order'], | |
); | |
if ( $component['lessons_all'] === '1' ) { | |
if ( $course ) { | |
$lesson_args['meta_key'] = 'course_id'; | |
$lesson_args['meta_value'] = $course; | |
} | |
$lessons = get_posts( $lesson_args ); | |
} elseif ( isset( $component['lessons'] ) && ! empty( $component['lessons'] ) ) { | |
$lesson_args['post__in'] = $component['lessons']; | |
$lessons = get_posts( $lesson_args ); | |
} | |
$lesson_grades = array(); | |
if ( $lessons ) { | |
foreach ( $lessons as $lesson ) { | |
if ( $lesson_grade = $this->get_lesson_grade( $lesson, $course_progress, $completion_grading_mode ) ) { | |
$lesson_grades[] = $lesson_grade; | |
} | |
} | |
} | |
// Sort by grade if set | |
if ( $orderby_grade ) { | |
usort( | |
$lesson_grades, | |
array( | |
__CLASS__, | |
$component_ordering['order'] === 'asc' ? 'sort_by_score_asc' : 'sort_by_score_desc' | |
) | |
); | |
} | |
$grades = $grades + $lesson_grades; | |
// Topics | |
$topics = array(); | |
$topic_args = array( | |
'post_type' => 'sfwd-topic', | |
'numberposts' => - 1, | |
'orderby' => $component_ordering['orderby'], | |
'order' => $component_ordering['order'], | |
); | |
if ( $component['topics_all'] === '1' ) { | |
if ( $course ) { | |
$topic_args['meta_key'] = 'course_id'; | |
$topic_args['meta_value'] = $course; | |
} | |
$topics = get_posts( $topic_args ); | |
} elseif ( isset( $component['topics'] ) && ! empty( $component['topics'] ) ) { | |
$topic_args['post__in'] = $component['topics']; | |
$topics = get_posts( $topic_args ); | |
} | |
$topic_grades = array(); | |
if ( $topics ) { | |
foreach ( $topics as $topic ) { | |
if ( $topic_grade = $this->get_topic_grade( $topic, $course_progress, $completion_grading_mode ) ) { | |
$grades[] = $topic_grade; | |
} | |
} | |
} | |
// Sort by grade if set | |
if ( $orderby_grade ) { | |
usort( | |
$topic_grades, | |
array( | |
__CLASS__, | |
$component_ordering['order'] === 'asc' ? 'sort_by_score_asc' : 'sort_by_score_desc' | |
) | |
); | |
} | |
$grades = $grades + $topic_grades; | |
} | |
if ( $user_manual_grades = $this->get_manual_grades( $component['id'] ) ) { | |
// Sort by grade if set | |
if ( $orderby_grade ) { | |
usort( | |
$user_manual_grades, | |
array( | |
__CLASS__, | |
$component_ordering['order'] === 'asc' ? 'sort_by_score_asc' : 'sort_by_score_desc' | |
) | |
); | |
} | |
$grades = $grades + $user_manual_grades; | |
} | |
$component['grades'] = $grades; | |
if ( ! isset( $component_overrides[ $component['id'] ] ) ) { | |
$component['averaged_score'] = $this::average_grades( $grades ); | |
$component['overridden'] = false; | |
} else { | |
$component['averaged_score'] = (int) $component_overrides[ $component['id'] ]; | |
$component['overridden'] = true; | |
} | |
} | |
/** | |
* Filter the user grade components. | |
* | |
* @since 1.0.0 | |
* | |
* @hooked LD_GB_QuickStart->mock_user_grades() 10 | |
*/ | |
$components = apply_filters( 'ld_gb_user_grade_components', $components, $this->gradebook->ID, $this->user->ID ); | |
return $components; | |
} | |
/** | |
* Gets the quiz grade based on the quiz post. | |
* | |
* @since 1.0.0 | |
* | |
* @param WP_Post $quiz The quiz post. | |
* | |
* @return array The quiz grade. | |
*/ | |
private function get_quiz_grade( $quiz_post ) { | |
static $quiz_score_type; | |
if ( $this->user_quizzes === null ) { | |
$this->user_quizzes = get_user_meta( $this->user->ID, '_sfwd-quizzes', true ); | |
} | |
if ( ! $this->user_quizzes ) { | |
return array(); | |
} | |
$quizzes = array(); | |
foreach ( $this->user_quizzes as $quiz ) { | |
if ( $quiz['quiz'] == $quiz_post->ID ) { | |
$quizzes[] = $quiz; | |
} | |
} | |
// This user has not taken this quiz | |
if ( ! $quizzes ) { | |
return false; | |
} | |
if ( $quiz_score_type === null ) { | |
$quiz_score_type = ld_gb_get_option_field( 'quiz_score_type', 'best' ); | |
} | |
$time = 0; | |
$score = 0; | |
foreach ( $quizzes as $quiz ) { | |
if ( ( $quiz_score_type == 'recent' && $quiz['completed'] > $time ) || | |
( $quiz_score_type == 'best' && (float) $quiz['percentage'] > $score ) | |
) { | |
$score = (float) $quiz['percentage']; | |
} | |
} | |
// Rounding | |
$score = ld_gb_round_grade( | |
$score, | |
$this->args['grade_precision'], | |
$this->args['grade_round_mode'] | |
); | |
$status = get_user_meta( $this->user->ID, "ld_gb_grade_status_{$this->gradebook->ID}_{$quiz_post->ID}", true ); | |
$grade = self::modify_grade_by_status( array( | |
'type' => 'quiz', | |
'name' => get_the_title( $quiz_post->ID ), | |
'score' => $score, | |
'status' => $status, | |
'post_id' => $quiz_post->ID, | |
) ); | |
return $grade; | |
} | |
/** | |
* Gets the assignment grade based on the assignment post. | |
* | |
* @since 1.0.0 | |
* | |
* @param WP_Post $assignment_post Assignment post object. | |
* | |
* return array The Grade | |
*/ | |
private function get_assignment_grade( $assignment_post ) { | |
// Make sure it belongs to the current user | |
$assignment_user = get_post_meta( $assignment_post->ID, 'user_id', true ); | |
if ( ! $assignment_user || (int) $assignment_user !== $this->user->ID ) { | |
return false; | |
} | |
$lesson_ID = get_post_meta( $assignment_post->ID, 'lesson_id', true ); | |
$points_enabled = learndash_get_setting( $lesson_ID, 'lesson_assignment_points_enabled' ); | |
if ( $points_enabled === 'on' ) { | |
$points_amount = (int) learndash_get_setting( $lesson_ID, 'lesson_assignment_points_amount' ); | |
$points_earned = (int) get_post_meta( $assignment_post->ID, 'points', true ); | |
if ( $points_amount > 0 && $points_amount >= $points_earned ) { | |
$assignment_grade = $points_earned / $points_amount * 100; | |
} | |
} | |
// Default to 100 if not set | |
$assignment_grade = isset( $assignment_grade ) ? $assignment_grade : 100; | |
$status = get_user_meta( $this->user->ID, "ld_gb_grade_status_{$this->gradebook->ID}_{$assignment_post->ID}", true ); | |
$score = (float) $assignment_grade; | |
// Rounding | |
$score = ld_gb_round_grade( | |
$score, | |
$this->args['grade_precision'], | |
$this->args['grade_round_mode'] | |
); | |
$grade = self::modify_grade_by_status( array( | |
'type' => 'assignment', | |
'name' => get_the_title( $assignment_post->ID ), | |
'score' => $score, | |
'status' => $status, | |
'post_id' => $assignment_post->ID, | |
) ); | |
return $grade; | |
} | |
/** | |
* Gets the lesson grade based on the assignment post. | |
* | |
* @since 1.2.0 | |
* | |
* @param WP_Post $lesson_post Lesson post object. | |
* @param array $course_progress User course progress pertaining to Lesson. | |
* @param string $mode Grading mode for non-completed Lessons. | |
* | |
* return array The Grade | |
*/ | |
private function get_lesson_grade( $lesson_post, $course_progress, $mode = 'completion' ) { | |
if ( isset( $course_progress['lessons'][ $lesson_post->ID ] ) && | |
$course_progress['lessons'][ $lesson_post->ID ] === 1 | |
) { | |
$lesson_grade = 100; | |
} else { | |
$lesson_grade = $mode === 'completion' ? false : 0; | |
} | |
$status = get_user_meta( $this->user->ID, "ld_gb_grade_status_{$this->gradebook->ID}_{$lesson_post->ID}", true ); | |
$score = $lesson_grade; | |
$grade = self::modify_grade_by_status( array( | |
'type' => 'lesson', | |
'name' => get_the_title( $lesson_post->ID ), | |
'score' => $score, | |
'status' => $status, | |
'post_id' => $lesson_post->ID, | |
) ); | |
return $grade; | |
} | |
/** | |
* Gets the topic grade based on the assignment post. | |
* | |
* @since 1.2.0 | |
* | |
* @param WP_Post $topic_post Topic post object. | |
* @param array $course_progress User course progress pertaining to Topic. | |
* @param string $mode Grading mode for non-completed Topics. | |
* | |
* return array The Grade | |
*/ | |
private function get_topic_grade( $topic_post, $course_progress, $mode = 'completion' ) { | |
$topic_grade = $mode === 'completion' ? false : 0; | |
if ( isset( $course_progress['topics'] ) ) { | |
foreach ( $course_progress['topics'] as $lesson_ID => $topics ) { | |
if ( isset( $topics[ $topic_post->ID ] ) && $topics[ $topic_post->ID ] === 1 ) { | |
$topic_grade = 100; | |
} | |
} | |
} | |
$status = get_user_meta( $this->user->ID, "ld_gb_grade_status_{$this->gradebook->ID}_{$topic_post->ID}", true ); | |
$score = $topic_grade; | |
$grade = self::modify_grade_by_status( array( | |
'type' => 'topic', | |
'name' => get_the_title( $topic_post->ID ), | |
'score' => $score, | |
'status' => $status, | |
'post_id' => $topic_post->ID, | |
) ); | |
return $grade; | |
} | |
/** | |
* Gets all manual grades. | |
* | |
* @since 1.0.0 | |
* | |
* @param int $component Component to get manual scores from. | |
* | |
* @return array The grades. | |
*/ | |
private function get_manual_grades( $component ) { | |
if ( ! ( $manual_grades = get_user_meta( $this->user->ID, "ld_gb_manual_grades_{$this->gradebook->ID}_{$component}", true ) ) ) { | |
return array(); | |
} | |
$grade_statuses = ld_gb_get_grade_statuses(); | |
$grades = array(); | |
foreach ( $manual_grades as $grade ) { | |
$grade['type'] = 'manual'; | |
// Rounding | |
$grade['score'] = ld_gb_round_grade( | |
$grade['score'], | |
$this->args['grade_precision'], | |
$this->args['grade_round_mode'] | |
); | |
$grades[] = self::modify_grade_by_status( $grade ); | |
} | |
return $grades; | |
} | |
/** | |
* Used in usort() for sorting component resources by scores ascending. | |
* | |
* @since 1.3.0 | |
* | |
* @param int $a | |
* @param int $b | |
* | |
* @return int | |
*/ | |
public static function sort_by_score_asc( $a, $b ) { | |
return self::sort_by_score( $a, $b, 'asc' ); | |
} | |
/** | |
* Used in usort() for sorting component resources by scores descending. | |
* | |
* @since 1.3.0 | |
* | |
* @param int $a | |
* @param int $b | |
* | |
* @return int | |
*/ | |
public static function sort_by_score_desc( $a, $b ) { | |
return self::sort_by_score( $a, $b, 'desc' ); | |
} | |
/** | |
* Used in usort() for sorting component resources by scores. | |
* | |
* @since 1.3.0 | |
* | |
* @param int $a | |
* @param int $b | |
* | |
* @return int | |
*/ | |
public static function sort_by_score( $a, $b, $order ) { | |
$a = $a['score']; | |
$b = $b['score']; | |
if ( $a === $b ) { | |
return 0; | |
} | |
if ( $order === 'asc' ) { | |
return $a < $b ? - 1 : 1; | |
} else { | |
return $a > $b ? - 1 : 1; | |
} | |
} | |
/** | |
* Modifies a grade based on its status. | |
* | |
* @since 1.0.1 | |
* | |
* @param array $grade | |
*/ | |
public static function modify_grade_by_status( $grade ) { | |
static $grade_statuses; | |
if ( $grade_statuses === null ) { | |
$grade_statuses = ld_gb_get_grade_statuses(); | |
} | |
$original_score = $grade['score']; | |
if ( $grade['status'] && isset( $grade_statuses[ $grade['status'] ] ) ) { | |
$score = $grade_statuses[ $grade['status'] ]['score']; | |
$display = $grade_statuses[ $grade['status'] ]['label']; | |
} | |
$score = isset( $score ) ? $score : $original_score; | |
if ( ! isset( $display ) ) { | |
$display = $score !== false ? "{$score}%" : ''; | |
} | |
$grade['original_score'] = $original_score; | |
$grade['score'] = $score; | |
$grade['score_display'] = $display; | |
return $grade; | |
} | |
/** | |
* Averages an array of grades. | |
* | |
* @since 1.0.0 | |
* | |
* @param array $grades Grades to be averaged. | |
* | |
* @return int The averaged grade. | |
*/ | |
public static function average_grades( $grades ) { | |
// Remove any set to false | |
foreach ( $grades as $i => $grade ) { | |
if ( $grade['score'] === false ) { | |
unset( $grades[ $i ] ); | |
} | |
} | |
if ( ! $grades ) { | |
return false; | |
} | |
$scores = wp_list_pluck( $grades, 'score' ); | |
return self::average_scores( $scores ); | |
} | |
/** | |
* Averages scores. | |
* | |
* @since 1.0.0 | |
* | |
* @param array $scores | |
* | |
* @return float | |
*/ | |
public static function average_scores( $scores ) { | |
return round( (int) array_sum( $scores ) / count( $scores ) ); | |
} | |
/** | |
* Calculates and returns the final course grade. | |
* | |
* @return int The final grade. | |
*/ | |
private function build_final_grade() { | |
switch ( $this->args['weight_type'] ) { | |
case 'weighted': | |
$final_grade = $this->calculate_weighted_grade(); | |
break; | |
case 'equal': | |
default: | |
$final_grade = $this->calculate_equal_grade(); | |
break; | |
} | |
/** | |
* Filters the final grade. | |
* | |
* @since 1.0.0 | |
*/ | |
$final_grade = apply_filters( 'ld_gb_user_grade_final_grade', $final_grade, $this->args['weight_type'] ); | |
return $final_grade; | |
} | |
/** | |
* Calculates the weighted final grade. | |
* | |
* @since 1.0.0 | |
* @access private | |
* | |
* @return bool|int | |
*/ | |
private function calculate_weighted_grade() { | |
// Check that weights equal 100 | |
if ( array_sum( wp_list_pluck( $this->components, 'weight' ) ) !== 100 ) { | |
return false; | |
} | |
// If no components graded, don't give grade | |
if ( count( array_filter( wp_list_pluck( $this->components, 'averaged_score' ) ) ) === 0 ) { | |
return false; | |
} | |
$final_grade = 0; | |
foreach ( $this->components as $component ) { | |
$score = $component['averaged_score'] !== false ? $component['averaged_score'] : 100; | |
$final_grade += $score * ( (int) $component['weight'] / 100 ); | |
} | |
return round( $final_grade ); | |
} | |
/** | |
* Calculates the equally weighted final grade. | |
* | |
* @since 1.0.0 | |
* @access private | |
* | |
* @return bool|int | |
*/ | |
private function calculate_equal_grade() { | |
$final_grade = 0; | |
$components = $this->components; | |
foreach ( $components as $i => $component ) { | |
// If no score, this component is incomplete, do not factor into final grade | |
if ( $component['averaged_score'] === false ) { | |
unset( $components[ $i ] ); | |
continue; | |
} | |
$final_grade += $component['averaged_score']; | |
} | |
if ( count( $components ) <= 0 ) { | |
$final_grade = false; | |
} else { | |
$final_grade = $final_grade / count( $components ); | |
} | |
return $final_grade !== false ? round( $final_grade ) : false; | |
} | |
/** | |
* Returns the grade as a letter grade. | |
* | |
* @since 1.0.0 | |
* | |
* @param int $numeric_grade Value of grade. | |
* | |
* @return string | |
*/ | |
public static function get_letter_grade( $numeric_grade ) { | |
/** | |
* Filters the letter grade map. | |
* | |
* @since 1.0.0 | |
*/ | |
$letter_scale = apply_filters( 'ld_gb_letter_grade_scale', | |
get_option( 'ld_gb_letter_grade_scale', ld_gb_get_default_letter_grade_scale() ) ); | |
$letter_grade = ''; | |
foreach ( $letter_scale as $cutoff => $grade ) { | |
if ( $numeric_grade >= $cutoff ) { | |
$letter_grade = $grade; | |
break; | |
} | |
} | |
return $letter_grade; | |
} | |
/** | |
* Returns the grade color for styling. | |
* | |
* @since 1.0.0 | |
* | |
* @param int $numeric_grade Value of grade. | |
* | |
* @return string | |
*/ | |
public static function get_grade_color( $numeric_grade ) { | |
if ( $numeric_grade === false ) { | |
return ''; | |
} | |
/** | |
* Filters the grade color map. | |
* | |
* This is used as a class for styling the grade output. | |
* | |
* @since 1.0.0 | |
*/ | |
$color_scale = apply_filters( 'ld_gb_grade_color_scale', | |
get_option( 'ld_gb_grade_color_scale', ld_gb_get_default_grade_color_scale() ) ); | |
$final_color = ''; | |
foreach ( $color_scale as $cutoff => $color ) { | |
if ( $numeric_grade >= $cutoff ) { | |
$final_color = $color; | |
break; | |
} | |
} | |
return $final_color; | |
} | |
/** | |
* Gets the Gradebook post. | |
* | |
* @since 1.2.0 | |
* | |
* @return false|WP_Post | |
*/ | |
public function get_gradebook() { | |
return $this->gradebook; | |
} | |
/** | |
* Gets the user. | |
* | |
* @since 1.1.0 | |
* | |
* @return false|WP_User | |
*/ | |
public function get_user() { | |
return $this->user; | |
} | |
/** | |
* Gets the weight type. | |
* | |
* @since 1.1.0 | |
* | |
* @return string | |
*/ | |
public function get_weight_type() { | |
return $this->args['weight_type']; | |
} | |
/** | |
* Gets components. | |
* | |
* @since 1.0.0 | |
* | |
* @param int $ID The Component ID. | |
* | |
* @return array|false Component if found, false if not found. | |
*/ | |
public function get_component( $ID ) { | |
foreach ( $this->components as $component ) { | |
if ( (int) $component['id'] === (int) $ID ) { | |
return $component; | |
} | |
} | |
return false; | |
} | |
/** | |
* Gets components. | |
* | |
* @since 1.0.0 | |
* | |
* @return array | |
*/ | |
public function get_components() { | |
return $this->components; | |
} | |
/** | |
* Gets args. | |
* | |
* @since 1.1.0 | |
* | |
* @return array | |
*/ | |
public function get_args() { | |
return $this->args; | |
} | |
/** | |
* Gets the course grade value. | |
* | |
* @since 1.0.0 | |
* | |
* @return bool|int | |
*/ | |
public function get_user_grade() { | |
return $this->user_grade; | |
} | |
/** | |
* Displays the final user grade. | |
* | |
* @since 1.0.0 | |
*/ | |
public function display_user_grade() { | |
self::display_grade( $this->user_grade ); | |
} | |
/** | |
* Displays the final user grade color. | |
* | |
* @since 1.0.0 | |
*/ | |
public function display_user_grade_color() { | |
self::display_grade_color( $this->user_grade ); | |
} | |
/** | |
* Gets the display grade. | |
* | |
* @since 1.0.0 | |
* | |
* @return string | |
* | |
* @param int $score The final score | |
* @param string $format How to display grade | |
*/ | |
public static function get_display_grade( $score, $format = 'letter' ) { | |
$format = ld_gb_get_option_field( 'grade_display_mode', $format ); | |
/** | |
* How to display the grade. | |
* | |
* @since 1.0.0 | |
*/ | |
$format = apply_filters( 'ld_gb_display_course_grade_format', $format ); | |
switch ( $format ) { | |
case 'letter': | |
if ( $score === false ) { | |
$grade_display = ''; | |
} else { | |
$grade_display = self::get_letter_grade( $score ); | |
} | |
break; | |
case 'percentage': | |
if ( $score === false ) { | |
$grade_display = ''; | |
} else { | |
$grade_display = "$score%"; | |
} | |
break; | |
default: | |
/** | |
* Allows a custom callback to get the display grade. | |
* | |
* @since 1.0.0 | |
*/ | |
$grade_display = apply_filters( 'ld_gb_display_course_grade', $score ); | |
break; | |
} | |
return $grade_display; | |
} | |
/** | |
* Displays the grade. | |
* | |
* @since 1.0.0 | |
* | |
* @param string $score The final score | |
* @param string|false $format How to display grade | |
*/ | |
public static function display_grade( $score, $format = false ) { | |
if ( ! $format ) { | |
$format = get_option( 'ld_gb_grade_format', 'letter' ); | |
} | |
echo self::get_display_grade( $score, $format ); | |
} | |
/** | |
* Returns the grade color for styling. | |
* | |
* @since 1.0.0 | |
* | |
* @param int $score | |
* | |
* @return string | |
*/ | |
public static function get_display_grade_color( $score ) { | |
return self::get_grade_color( $score ); | |
} | |
/** | |
* Displays the grade color for styling. | |
* | |
* @since 1.0.0 | |
* | |
* @param int $score | |
*/ | |
public static function display_grade_color( $score ) { | |
echo self::get_display_grade_color( $score ); | |
} | |
/** | |
* Returns the grade html for output. | |
* | |
* @since 1.1.0 | |
* | |
* @param int $score | |
* | |
* @return string | |
*/ | |
public static function get_display_grade_html( $score ) { | |
return '<span class="ld-gb-grade" style="background-color: ' . self::get_grade_color( $score ) . '";>' . | |
self::get_display_grade( $score ) . '</span>'; | |
} | |
/** | |
* Echos the grade html for output. | |
* | |
* @since 1.1.0 | |
* | |
* @param int $score | |
* | |
* @return string | |
*/ | |
public static function display_grade_html( $score ) { | |
echo self::get_display_grade_html( $score ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment