ld-quiz-migration.php000066600000025005152142404260010637 0ustar00 'sfwd-quiz', 'post_status' => 'any', 'posts_per_page' => -1, ) ); } set_time_limit( 300 ); global $wpdb; foreach ( $posts as $post ) { $quizdata = get_post_meta( $post->ID, '_quizdata', true ); if ( ! empty( $_GET['force_learndash_quiz_migration'] ) && ( empty( $quizdata['workingJson'] ) || $quizdata['workingJson'] == 'false') ) { $quizdata = get_post_meta( $post->ID, '_quizdata_migrated', true ); } if ( empty( $quizdata['workingJson'] ) || $quizdata['workingJson'] == 'false' ) { continue; } $simple_quiz_data = json_decode( $quizdata['workingJson'] ); $LearnDash_Quiz_Migration = new LearnDash_Quiz_Migration(); $xml = $LearnDash_Quiz_Migration->get_xml( $simple_quiz_data ); if ( ! empty( $xml ) ) { $import = new WpProQuiz_Helper_ImportXml(); $import->setString( $xml ); $getImportData = $import->getImportData(); $pro_quiz_id = $import->saveImportSingle(); learndash_update_setting( $post, 'quiz_pro', $pro_quiz_id ); } $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->postmeta SET meta_key = '_quizdata_migrated' WHERE meta_key = '_quizdata' AND post_id = '%d' LIMIT 1", $post->ID ) ); } update_option( 'learndash_quiz_migration_completed', 1 ); } add_action( 'admin_init', 'learndash_quiz_migration' ); /** * Creates a quiz for each advanced quiz * * @since 2.1.0 */ function learndash_create_quiz_for_all_adv_quiz() { $quizMapper = new WpProQuiz_Model_QuizMapper(); $quizzes = $quizMapper->fetchAll(); foreach ( $quizzes as $key => $quiz ) { $quizId = $quiz->getId(); //error_log('quizId['. $quizId .']'); if ( empty( $quizId ) ) { continue; } $post_id = learndash_get_quiz_id_by_pro_quiz_id( $quizId ); //error_log('post_id['. $post_id .']'); //die(); if ( empty( $post_id ) ) { $post_id = learndash_create_quiz_for_adv_quiz( $quizId ); } else { learndash_migrate_content_from_pro_quiz_to_custom_post_type( $quiz, $post_id ); } } } /** * Migrates the content from a pro quiz object to a custom post type * * @param object $quiz Pro Quiz to be migrated * @param int $post_id */ function learndash_migrate_content_from_pro_quiz_to_custom_post_type( $quiz, $post_id ) { $quiz_desc = $quiz->getText(); if ( ! empty( $quiz_desc ) && $quiz_desc != 'AAZZAAZZ' && ! empty( $post_id ) ) { $quiz_post = get_post( $post_id ); $update_post['ID'] = $post_id; $update_post['post_content'] = $quiz_post->post_content . '
' . $quiz_desc; wp_update_post( $update_post ); global $wpdb; $wpdb->query( $wpdb->prepare( 'UPDATE ' . LDLMS_DB::get_table_name( 'quiz_master' ) . " SET text = 'AAZZAAZZ' WHERE id = '%d'", $quiz->getId() ) ); } } /** * Create a post type of sfwd-quiz for the input pro quiz ID * * @param int $quizId Quiz ID * @return int Quiz Post ID */ function learndash_create_quiz_for_adv_quiz( $quizId ) { $quizMapper = new WpProQuiz_Model_QuizMapper(); $quizzes = $quizMapper->fetchAll(); $quiz = $quizMapper->fetch( $quizId ); $quizId = $quiz->getId(); if ( empty( $quizId ) ) { return; } global $wpdb; $user_id = get_current_user_id(); $quiz_post_id = wp_insert_post( array( 'post_title' => $quiz->getName(), 'post_type' => 'sfwd-quiz', 'post_status' => 'publish', 'post_author' => $user_id, ) ); if ( ! empty( $quiz_post_id ) ) { learndash_update_setting( $quiz_post_id, 'quiz_pro', $quiz->getId() ); } return $quiz_post_id; } /** * Object that handles LearnDash Quiz Migrations */ class LearnDash_Quiz_Migration { /** * Retrieves an XML representation of a simple quiz object * * @since 2.1.0 * * @param object $simple_quiz_data * @return String XML representation of the simple quiz object */ public function get_xml( $simple_quiz_data ) { $title = $simple_quiz_data->info->name; $maincopy = $simple_quiz_data->info->main; $resultcopy = $simple_quiz_data->info->results; $questions = $simple_quiz_data->questions; if ( empty( $title ) || empty( $questions ) || ! is_array( $questions ) ) { return ''; } $questions_xml = ''; $qno = 1; foreach ( $questions as $question ) { $questionText = $question->q; $correct = $question->correct; $incorrect = $question->incorrect; $answers = $question->a; if ( empty( $answers) || ! is_array( $answers ) ) { return ''; } $answers_xml = ''; $correct_count = 0; foreach ( $answers as $answer ) { $answerText = $answer->option; $is_correct = ! empty( $answer->correct ) ? 'true' : 'false'; if ( ! empty( $answer->correct) ) { $correct_count++; } $answers_xml .= $this->answer( $answerText, $is_correct ); } $type = ( $correct_count > 1 ) ? 'multiple' : 'single'; $questions_xml .= $this->question( $qno++, $questionText, $correct, $incorrect, $answers_xml, $type ); } return $this->template( $title, $maincopy, $resultcopy, $questions_xml ); } /** * Uses the input string variables to fill an XML template. * * @since 2.1.0 * * @param string $title XML text * @param string $maincopy XML text * @param string $resultcopy XML text * @param string $questions_xml XML text * @return string XML string */ public function template( $title, $maincopy, $resultcopy, $questions_xml ) { if ( empty( $maincopy ) ) { $maincopy = 'AAZZAAZZ'; } return '
<![CDATA[' . $title . ']]> false false false false 0 false false false false false false 1 1 false 1 1 0 false false false false false false false 0 false false false false false false false false false false false 0 false ' . $questions_xml . ' '; } /** * Returns the XML representation of the question based off of the input string variables * * @since 2.1.0 * * @param string $qno * @param string $questionText * @param string $correct * @param string $incorrect * @param string $answers_xml * @param string $type * @return string XML string */ public function question( $qno, $questionText, $correct, $incorrect, $answers_xml, $type = 'single' ) { return ' <![CDATA[Question: ' . $qno . ']]> 1 false false false false false ' . $answers_xml . ' '; } /** * Returns the XML representation of an answer based off of the input string variables * * @since 2.1.0 * * @param String $answerText * @param String $is_correct * @return String XML string */ public function answer( $answerText, $is_correct) { return ' '; } }ld-quiz-pro.php000066600000147541152142404260007460 0ustar00add_cap( 'wpProQuiz_show' ); $role->add_cap( 'wpProQuiz_add_quiz' ); $role->add_cap( 'wpProQuiz_edit_quiz' ); $role->add_cap( 'wpProQuiz_delete_quiz' ); $role->add_cap( 'wpProQuiz_show_statistics' ); $role->add_cap( 'wpProQuiz_reset_statistics' ); $role->add_cap( 'wpProQuiz_import' ); $role->add_cap( 'wpProQuiz_export' ); $role->add_cap( 'wpProQuiz_change_settings' ); $role->add_cap( 'wpProQuiz_toplist_edit' ); $role->add_cap( 'wpProQuiz_toplist_edit' ); } } add_action( 'wp_ajax_ld_adv_quiz_pro_ajax', array( $this, 'ld_adv_quiz_pro_ajax' ) ); add_action( 'wp_ajax_nopriv_ld_adv_quiz_pro_ajax', array( $this, 'ld_adv_quiz_pro_ajax' ) ); add_action( 'learndash_quiz_completed', array( $this, 'set_quiz_status_meta' ), 1, 2 ); } /** * Submit quiz and echo JSON representation of the checked quiz answers * * @since 2.1.0 * */ function ld_adv_quiz_pro_ajax() { // First we unpack the $_POST['results'] string if ( ( isset( $_POST['data']['responses'] ) ) && ( !empty( $_POST['data']['responses'] ) ) && ( is_string( $_POST['data']['responses'] ) ) ) { $_POST['data']['responses'] = json_decode( stripslashes( $_POST['data']['responses'] ), true ); } //error_log('in '. __FUNCTION__ ); //error_log('_POST
'. print_r($_POST, true) .'
'); $func = isset( $_POST['func'] ) ? $_POST['func'] : ''; $data = isset( $_POST['data'] ) ? (array)$_POST['data'] : null; switch ( $func ) { case 'checkAnswers': echo $this->checkAnswers( $data ); break; } exit; } /** * Check answers for submitted quiz * * @since 2.1.0 * * @param array $data Quiz information and answers to be checked * @return string JSON representation of checked answers */ function checkAnswers( $data ) { //error_log('in '. __FUNCTION__ ); //error_log('_POST
'. print_r($_POST, true) .'
'); if ( is_user_logged_in() ) { $user_id = get_current_user_id(); } else { $user_id = 0; } if ( isset( $data['quizId'] ) ) { $id = absint( $data['quizId'] ); } else { $id = 0; } if ( isset( $data['quiz'] ) ) { $quiz_post_id = absint( $data['quiz'] ); } else { $quiz_post_id = 0; } if ( ( ! isset( $data['quiz_nonce'] ) ) || ( ! wp_verify_nonce( $data['quiz_nonce'], 'sfwd-quiz-nonce-' . $quiz_post_id . '-' . $id . '-' . $user_id ) ) ) { //wp_send_json_error(); die(); } $view = new WpProQuiz_View_FrontQuiz(); $quizMapper = new WpProQuiz_Model_QuizMapper(); $quiz = $quizMapper->fetch( $id ); if ( $quiz_post_id !== absint( $quiz->getPostId() ) ) { $quiz->setPostId( $quiz_post_id ); } $questionMapper = new WpProQuiz_Model_QuestionMapper(); $categoryMapper = new WpProQuiz_Model_CategoryMapper(); $formMapper = new WpProQuiz_Model_FormMapper(); $questionModels = $questionMapper->fetchAll( $quiz ); $view->quiz = $quiz; $view->question = $questionModels; $view->category = $categoryMapper->fetchByQuiz( $quiz ); $question_count = count( $questionModels ); ob_start(); $quizData = $view->showQuizBox( $question_count ); ob_get_clean(); $json = $quizData['json']; $results = array(); $question_index = 0; foreach ( $data['responses'] as $question_id => $info ) { if (isset( $questionModel ) ) unset( $questionModel ); foreach ( $questionModels as $questionModel ) { if ( $questionModel->getId() == intval( $question_id ) ) { $userResponse = $info['response']; if ( ( is_array( $userResponse ) ) && ( !empty( $userResponse ) ) ) { foreach ( $userResponse as $key => $value ) { if ( ( $value != 0) && ($value != 1) ) { if ( $value == "false" ) { $userResponse[ $key ] = false; } else if ( $value == "true" ) { $userResponse[ $key ] = true; } } } } $questionData = $json[ $question_id ]; $correct = false; $points = 0; $statisticsData = new stdClass(); $extra = array(); $extra['type'] = $questionData['type']; $questionData['points'] = isset( $questionData['points'] ) ? $questionData['points'] : $questionData['globalPoints']; $question_index++; $answer_pointed_activated = $questionModel->isAnswerPointsActivated(); switch ( $questionData['type'] ) { case 'free_answer': //$correct = (strtolower( $userResponse ) == strtolower( $questionData['correct'][0] )); $correct = false; foreach($questionData['correct'] as $questionData_correct) { if ( stripslashes( strtolower( trim( $userResponse ) ) ) == stripslashes( strtolower( trim( $questionData_correct ) ) ) ) { $correct = true; break; } } $points = ( $correct) ? $questionData['points'] : 0; $points = apply_filters( 'learndash_ques_free_answer_pts', $points, $questionData, $userResponse ); $correct = apply_filters( 'learndash_ques_free_answer_correct', $correct, $questionData, $userResponse ); $extra['r'] = $userResponse; if ( ! $quiz->isDisabledAnswerMark() && empty( $questionData['disCorrect'] ) ) { $extra['c'] = $questionData['correct']; } break; case 'multiple': $correct = true; $r = array(); foreach ( $questionData['correct'] as $answerIndex => $correctAnswer ) { //$checked = $questionData['correct'][ $userResponse[ $answerIndex ] ]; if ( $answer_pointed_activated ){ /** * Points are calculated per answer, add up all the points the user marked correctly */ /* if ( ! empty( $correctAnswer ) && ! empty( $userResponse[ $answerIndex ] ) ) { $r[ $answerIndex ] = true; $correct = true; $points += $questionData['points'][ $answerIndex ]; } else { $r[ $answerIndex ] = false; $correct = false; } //if ( $userResponse != $questionData['correct'] ) { // $correct = false; //} $points = apply_filters( 'learndash_ques_multiple_answer_pts_each', $points, $questionData, $answerIndex, $correctAnswer, $userResponse ); $correct = apply_filters( 'learndash_ques_multiple_answer_correct_each', $correct, $questionData, $answerIndex, $correctAnswer, $userResponse ); */ if ( ( isset( $userResponse[ $answerIndex ] ) ) && ( $userResponse[ $answerIndex ] == $correctAnswer ) ) { $r[ $answerIndex ] = $userResponse[ $answerIndex ]; $correct_this_item = true; if ( $userResponse[ $answerIndex ] == true ) $points += $questionData['points'][ $answerIndex ]; } else { $r[ $answerIndex ] = false; $correct_this_item = false; } if ( has_filter( 'learndash_ques_multiple_answer_pts_each' ) ) { $points = apply_filters( 'learndash_ques_multiple_answer_pts_each', $points, $questionData, $answerIndex, $correctAnswer, $userResponse ); } else { /** * Added logic to subtract points on selected incorrect answers. * * @since 2.5.7 */ if ( $questionData['correct'][ $answerIndex ] == 0 ) { if ( $correct_this_item == false ) { if ( intval( $questionData['points'][ $answerIndex ] ) > 0 ) { $points -= intval( $questionData['points'][ $answerIndex ] ); } //else { // $points -= 1; //} } end( $questionData['correct'] ); $last_key = key( $questionData['correct'] ); // If we are at the last index and the points is less than zero we keep it from being negative. if ( ( $last_key == $answerIndex ) && ( $points < 0 ) ) { $points = 0; } } } $correct_this_item = apply_filters( 'learndash_ques_multiple_answer_correct_each', $correct_this_item, $questionData, $answerIndex, $correctAnswer, $userResponse ); if ( ( $correct_this_item != true ) && ( $correct == true ) ) $correct = false; } else { /** * Points are allocated for the entire question if the user selects all the correct answers and none of * the incorrect answers * * if the user selects an answer that is marked as correct, mark the question true and let the * foreach loop check the next answer * * if they select an incorrect answer, or fail to select a correct answer, mark it false and break * the foreach * * we don't want to break the foreach if the user did not select an incorrect answer */ if ( ! empty( $correctAnswer ) && ! empty( $userResponse[ $answerIndex ] ) ) { $correct = true; $r[ $answerIndex ] = true; $points = $questionData['points']; } elseif ( empty( $correctAnswer ) && ! empty( $userResponse[ $answerIndex ] ) ) { $correct = false; $r[ $answerIndex ] = false; $points = 0; break; } elseif ( ! empty( $correctAnswer ) && empty( $userResponse[ $answerIndex ] ) ) { $correct = false; $r[ $answerIndex ] = false; $points = 0; break; } // See https://bitbucket.org/snippets/learndash/aKdpz for examples of this filter. $points = apply_filters( 'learndash_ques_multiple_answer_pts_whole', $points, $questionData, $answerIndex, $correctAnswer, $userResponse ); $correct = apply_filters( 'learndash_ques_multiple_answer_correct_whole', $correct, $questionData, $answerIndex, $correctAnswer, $userResponse ); } } $extra['r'] = $userResponse; if ( ! $quiz->isDisabledAnswerMark() ) { $extra['c'] = $questionData['correct']; } break; case 'single': foreach ( $questionData['correct'] as $answerIndex => $correctAnswer ) { if ($userResponse[ $answerIndex ] == true) { if ( ( ( isset( $questionData['diffMode'] ) ) && ( ! empty( $questionData['diffMode'] ) ) ) || ( !empty( $correctAnswer ) ) ) { //DiffMode or Correct if ( is_array( $questionData['points'] ) ) { $points = $questionData['points'][ $answerIndex ]; } else { $points = $questionData['points']; } } if ( ! empty( $correctAnswer) || ! empty( $questionData['disCorrect'] ) ) { //Correct $correct = true; } // See https://bitbucket.org/snippets/learndash/aKdpz for examples of this filter. $points = apply_filters( 'learndash_ques_single_answer_pts', $points, $questionData, $answerIndex, $correctAnswer, $userResponse ); $correct = apply_filters( 'learndash_ques_single_answer_correct', $correct, $questionData, $answerIndex, $correctAnswer, $userResponse ); } } $extra['r'] = $userResponse; if ( ! $quiz->isDisabledAnswerMark() && empty( $questionData['disCorrect'] ) ) { $extra['c'] = $questionData['correct']; } break; case 'sort_answer': case 'matrix_sort_answer': $correct = true; $questionData['correct'] = LD_QuizPro::datapos_array( $question_id, count( $questionData['correct'] ) ); foreach ( $questionData['correct'] as $answerIndex => $answer ) { if ( ! isset( $userResponse[ $answerIndex ] ) || $userResponse[ $answerIndex ] != $answer ) { $correct = false; } else { if ( is_array( $questionData['points'] ) ) { $points += $questionData['points'][ $answerIndex ]; } } $statisticsData->{$answerIndex} = @$userResponse[ $answerIndex ]; } if ( $correct ) { if ( ! is_array( $questionData['points'] ) ) { $points = $questionData['points']; } } else { $statisticsData = new stdClass(); } $extra['r'] = $userResponse; if ( ! $quiz->isDisabledAnswerMark() && empty( $questionData['disCorrect'] ) ) { $extra['c'] = $questionData['correct']; } else { $statisticsData = new stdClass(); } break; case 'cloze_answer': $answerData = array(); foreach ( $questionData['correct'] as $answerIndex => $correctArray ) { $answerData[$answerIndex] = false; if ( ! isset( $userResponse[ $answerIndex ] ) ) $answerData[$answerIndex] = false; $userResponse[ $answerIndex ] = stripslashes( trim( $userResponse[ $answerIndex ] ) ); if ( apply_filters('learndash_quiz_question_cloze_answers_to_lowercase', true ) ) { if ( function_exists( 'mb_strtolower' ) ) { $user_answer_formatted = mb_strtolower( $userResponse[ $answerIndex ] ); } else { $user_answer_formatted = strtolower( $userResponse[ $answerIndex ] ); } } else { $user_answer_formatted = $userResponse[ $answerIndex ]; } $answerData[$answerIndex] = in_array( $user_answer_formatted, $correctArray ); $answerData[$answerIndex] = apply_filters( 'learndash_quiz_check_answer', $answerData[$answerIndex], $questionData['type'], $userResponse[ $answerIndex ], $correctArray, $answerIndex, $questionModel ); $statisticsData->{$answerIndex} = $answerData[$answerIndex]; if ( $answerData[$answerIndex] === true ) { if ( ( $questionModel->isAnswerPointsActivated() ) && ( is_array( $questionData['points'] ) ) ) { $points += $questionData['points'][ $answerIndex ]; } else { $points = $questionData['points']; } } } // If we have one wrong answer if ( in_array( false, $answerData ) === true ) { $correct = false; // If we are NOT using individual points and there is at least one wrong answer // then we clear the points. if ( !$questionModel->isAnswerPointsActivated() ) { $points = 0; } } else { // If all the fields are correct then the points stand and we set the correct to true $correct = true; } $extra['r'] = $userResponse; if ( ! $quiz->isDisabledAnswerMark() && empty( $questionData['disCorrect'] ) ) { $extra['c'] = $questionData['correct']; } break; case 'assessment_answer': $correct = true; $points = intVal( $userResponse ); $extra['r'] = $userResponse; break; case 'essay': $essay_data = $questionModel->getAnswerData(); $essay_data = array_shift( $essay_data ); switch ( $essay_data->getGradingProgression() ) { case '': case 'not-graded-none': $points = 0; $correct = false; $extra['graded_status'] = 'not_graded'; break; case 'not-graded-full': $points = $essay_data->getPoints(); $correct = false; $extra['graded_status'] = 'not_graded'; break; case 'graded-full' : $points = $essay_data->getPoints(); $correct = true; $extra['graded_status'] = 'graded'; break; default: $points = 0; $correct = false; $extra['graded_status'] = 'not_graded'; } $essay_id = learndash_add_new_essay_response( $userResponse, $questionModel, $quiz, $data ); $extra['graded_id'] = $essay_id; break; default: break; } if ( ! $quiz->isHideAnswerMessageBox() ) { foreach ( $questionModels as $key => $value ) { if ( $value->getId() == $question_id ) { if ( $correct || $value->isCorrectSameText() ) { //$extra['AnswerMessage'] = do_shortcode( apply_filters( 'comment_text', $value->getCorrectMsg() ) ); $extra['AnswerMessage'] = do_shortcode( apply_filters( 'the_content', $value->getCorrectMsg() ) ); } else { //$extra['AnswerMessage'] = do_shortcode( apply_filters( 'comment_text', $value->getIncorrectMsg() ) ); $extra['AnswerMessage'] = do_shortcode( apply_filters( 'the_content', $value->getIncorrectMsg() ) ); } break; } } } $extra['possiblePoints'] = $questionModel->getPoints(); $results[ $question_id ] = array( 'c' => $correct, 'p' => $points, 's' => $statisticsData, 'e' => $extra ); break; } } } do_action( 'ldadvquiz_answered', $results, $quiz, $questionModels); $total_points = 0; foreach( $results as $r_idx => $result ) { if ( ( isset( $result['e'] ) ) && ( !empty( $result['e'] ) ) ) { if ( ( isset( $result['e']['type'] ) ) && ( !empty( $result['e']['type'] ) ) ) { $response_str = ''; switch( $result['e']['type'] ) { case 'essay': if ( ( isset( $result['e']['graded_id'] ) ) && ( !empty( $result['e']['graded_id'] ) ) ) { $response_str = maybe_serialize( array( 'graded_id' => $result['e']['graded_id'] ) ); } break; case 'free_answer': if ( ( isset( $result['e']['r'] ) ) && ( !empty( $result['e']['r'] ) ) ) { $response_str = maybe_serialize( array( $result['e']['r'] ) ); } break; case 'assessment_answer': if ( isset( $result['p'] ) ) { $response_str = maybe_serialize( array( (string)$result['p'] ) ); } break; case 'multiple': case 'single': default: if ( ( isset( $result['e']['r'] ) ) && ( !empty( $result['e']['r'] ) ) ) { $result_array = array(); foreach( $result['e']['r'] as $ri_idx => $ri ) { if ( $ri === true ) $ri = 1; else if ( $ri === false ) $ri = 0; $result_array[$ri_idx] = $ri; } $response_str = maybe_serialize( $result_array ); } break; break; } if ( !empty( $response_str ) ) { $answers_nonce = wp_create_nonce( 'ld_quiz_anonce'. $user_id .'_'. $id .'_'. $quiz_post_id .'_'. $r_idx .'_'. $response_str ); $results[$r_idx]['a_nonce'] = $answers_nonce; } } } $points_array = array( 'points' => intval( $result['p'] ), 'correct' => intval( $result['c'] ), 'possiblePoints' => intval( $result['e']['possiblePoints'] ) ); if ( $points_array['correct'] === false ) $points_array['correct'] = 0; else if ( $points_array['correct'] === true ) $points_array['correct'] = 1; $points_str = maybe_serialize( $points_array ); $points_nonce = wp_create_nonce( 'ld_quiz_pnonce'. $user_id .'_'. $id .'_'. $quiz_post_id .'_'. $r_idx .'_'. $points_str ); $results[$r_idx]['p_nonce'] = $points_nonce; } return json_encode( $results ); } /** * Redirect from the Advanced Quiz edit or add link to the Quiz edit or add link * * @since 2.1.0 */ function quiz_edit_redirect() { if ( ! empty( $_GET['page'] ) && $_GET['page'] == 'ldAdvQuiz' && empty( $_GET['module'] ) && ! empty( $_GET['action'] ) && $_GET['action'] == 'addEdit' ) { if ( ! empty( $_GET['post_id'] ) ) { header( 'Location: ' . admin_url( 'post.php?action=edit&post=' . $_GET['post_id'] ) ); exit; } else if ( ! empty( $_GET['quizId'] ) ) { $post_id = learndash_get_quiz_id_by_pro_quiz_id( $_GET['quizId'] ); if ( ! empty( $post_id ) ) { header( 'Location: ' . admin_url( 'post.php?action=edit&post=' . $post_id ) ); } else { header( 'Location: ' . admin_url( 'edit.php?post_type=sfwd-quiz' ) ); } exit; } header( 'Location: ' . admin_url( 'post-new.php?post_type=sfwd-quiz' ) ); exit; } } /** * Echoes quiz content * * @since 2.1.0 * * @param int $pro_quiz_id */ static function showQuizContent( $pro_quiz_id ) { global $post; if ( empty( $post) || $post->post_type == 'sfwd-quiz' ) { return ''; } echo LD_QuizPro::get_description( $pro_quiz_id ); } /** * Returns the HTML representation of the quiz description * * @since 2.1.0 * * @param int $pro_quiz_id * @return string HTML representation of quiz description */ static function get_description( $pro_quiz_id ) { $post_id = learndash_get_quiz_id_by_pro_quiz_id( $pro_quiz_id ); if ( empty( $post_id ) ) { return ''; } $quiz = get_post( $post_id ); if ( empty( $quiz->post_content) ) { return ''; } /** * Filter the description of the quiz * * @param string $quiz->post_content */ $content = apply_filters( 'ldadvquiz_the_content', $quiz->post_content ); /** * Added call to do_shortcode to process any shortcodes within the quiz content. * * @since 2.6.0 */ $content = do_shortcode( $content ); $content = str_replace( ']]>', ']]>', $content ); return "
" . $content . '
'; } /** * Outputs the debugging message to the error log file * * @since 2.1.0 * * @param string $msg Debugging message */ function debug( $msg ) { } /** * Does the list of questions for this quiz have a graded question in it * Dataset used is not the quizdata saved to user meta, but follows the * Question Model of WpProQuiz * * @since 2.1.0 * * @param array $questions * * @return bool */ static function quiz_has_graded_question( $questions ) { $graded_question_types = array( 'essay' ); foreach ( $questions as $question ) { if ( ! is_a( $question, 'WpProQuiz_Model_Question' ) ) { continue; } if ( in_array( $question->getAnswerType(), $graded_question_types ) ){ // found one! halt foreach and return true; return true; } } // foreach completed without finding any, return false return false; } /** * Checks a users submitted quiz attempt to see if that quiz * has graded questions and if all of them have been graded * */ static function quiz_attempt_has_ungraded_question( $quiz_attempt ) { if (isset( $quiz_attempt['graded'] ) ) { foreach( $quiz_attempt['graded'] as $graded ) { if ( 'not_graded' == $graded['status'] ) { return true; } } } return false; } /** * This function runs when a quiz is started and is used to set the quiz start timestamp * * @since 2.3 */ function set_quiz_status_meta( $quizdata, $user ) { if (empty( $quizdata ) ) return; if ( !( $user instanceof WP_User ) ) return; if ( isset( $quizdata['questions'] ) ) unset( $quizdata['questions'] ); if ( ( isset( $quizdata['quiz'] ) ) && ( $quizdata['quiz'] instanceof WP_Post ) ) { $quiz_post = $quizdata['quiz']; unset( $quizdata['quiz'] ); $quizdata['quiz'] = intval($quiz_post->ID); } $course_id = 0; $lesson_id = 0; $topic_id = 0; if ( ( isset( $quizdata['course'] ) ) && ( $quizdata['course'] instanceof WP_Post ) ) { $course_post = $quizdata['course']; unset( $quizdata['course'] ); $quizdata['course'] = intval($course_post->ID); $course_id = $quizdata['course']; } if ( ( isset( $quizdata['lesson'] ) ) && ( $quizdata['lesson'] instanceof WP_Post ) ) { $lesson_post = $quizdata['lesson']; unset( $quizdata['lesson'] ); $quizdata['lesson'] = intval($lesson_post->ID); $lesson_id = $quizdata['lesson']; } if ( ( isset( $quizdata['topic'] ) ) && ( $quizdata['topic'] instanceof WP_Post ) ) { $topic_post = $quizdata['topic']; unset( $quizdata['topic'] ); $quizdata['topic'] = intval($topic_post->ID); $topic_id = $quizdata['topic']; } if ( ( isset( $quizdata['course'] ) ) && ( ! empty( $quizdata['course'] ) ) ) { $quizdata['steps_completed'] = learndash_course_get_completed_steps($user->ID, $quizdata['course']); // Update the Course if this quiz has. $course_args = array( 'course_id' => $quizdata['course'], 'user_id' => $user->ID, 'post_id' => $quizdata['course'], 'activity_type' => 'course', 'activity_started' => time(), 'activity_meta' => array( 'steps_completed' => $quizdata['steps_completed'], 'steps_last_id' => $quizdata['quiz'] ) ); $course_activity = learndash_get_user_activity( $course_args ); if ( !$course_activity ) { learndash_update_user_activity( $course_args ); } } if ( ( isset( $quizdata['started'] ) ) && ( !empty( $quizdata['started'] ) ) && ( isset( $quizdata['completed'] ) ) && ( !empty( $quizdata['completed'] ) ) ) { if ( $quizdata['pass'] == true ) $quizdata_pass = true; else $quizdata_pass = false; learndash_update_user_activity( array( 'course_id' => $course_id, 'user_id' => $user->ID, 'post_id' => $quizdata['quiz'], 'activity_type' => 'quiz', 'activity_action' => 'insert', 'activity_status' => $quizdata_pass, 'activity_started' => $quizdata['started'], 'activity_completed' => $quizdata['completed'], 'activity_meta' => $quizdata ) ); } } /** * This function runs when a quiz is completed, and does the action 'wp_pro_quiz_completed_quiz' * * @since 2.1.0 */ function wp_pro_quiz_completed( $statistic_ref_id = 0) { //error_log('_POST
'. print_r($_POST, true) .'
'); $results = array(); $quiz_pro_id = isset( $_POST['quizId'] ) ? absint( $_POST['quizId'] ) : null; $quiz_post_id = isset( $_POST['quiz'] ) ? absint( $_POST['quiz'] ) : null; $score = isset( $_POST['results']['comp']['correctQuestions'] ) ? $_POST['results']['comp']['correctQuestions'] : null; $points = isset( $_POST['results']['comp']['points'] ) ? absint( $_POST['results']['comp']['points'] ) : null; $result = isset( $_POST['results']['comp']['result'] ) ? $_POST['results']['comp']['result'] : null; $timespent = isset( $_POST['timespent'] ) ? floatval( $_POST['timespent'] ) : null; if ( ( is_null( $quiz_post_id ) ) || ( is_null( $quiz_pro_id ) ) || ( is_null( $points ) ) ) { return json_encode( $results ); } $course_id = ( ( isset( $_POST['course_id'] ) ) && ( intval( $_POST['course_id'] ) > 0 ) ) ? intval( $_POST['course_id'] ) : learndash_get_course_id( $quiz_pro_id ); $lesson_id = ( ( isset( $_POST['lesson_id'] ) ) && ( intval( $_POST['lesson_id'] ) > 0 ) ) ? intval( $_POST['lesson_id'] ) : 0; $topic_id = ( ( isset( $_POST['topic_id'] ) ) && ( intval( $_POST['topic_id'] ) > 0 ) ) ? intval( $_POST['topic_id'] ) : 0; if (is_user_logged_in() ) $user_id = get_current_user_id(); else $user_id = 0; $quizMapper = new WpProQuiz_Model_QuizMapper(); $quiz_pro = $quizMapper->fetch( $quiz_pro_id ); if ( ( ! $quiz_pro ) || ( ! is_a( $quiz_pro, 'WpProQuiz_Model_Quiz' ) ) ) { return json_encode( $results ); } $quiz_pro->setPostId( $quiz_post_id ); $questionMapper = new WpProQuiz_Model_QuestionMapper(); $questions = $questionMapper->fetchAll( $quiz_pro ); if ( is_array( $questions ) ) { $questions_count = count( $questions ); } // check if these set of questions has questions that need to be graded $has_graded = LD_QuizPro::quiz_has_graded_question( $questions ); // store the id's of the graded question to be saved in usermeta $graded = array(); foreach ( $_POST['results'] as $question_id => $individual_result ) { if ( 'comp' == $question_id ) continue; if ( isset( $individual_result['graded_id'] ) && ! empty( $individual_result['graded_id'] ) ) { $graded[ $question_id ] = array( 'post_id' => intval( $individual_result['graded_id'] ), 'status' => esc_html( $individual_result['graded_status'] ), 'points_awarded' => intval( $individual_result['points'] ), ); } } if ( empty( $result) ) { $total_points = 0; //foreach ( $questions as $q ) { // $q_points = $q->getPoints(); // error_log('q_points['. $q_points .']'); // $total_points += $q->getPoints(); //} // Rewrote logic here to only count points for the questions shown to the user. // For example I might have a Quiz showing only 5 of 10 questions. In the above code // the points counted inlcude ALL 10 questions. Not correct. // Insead we do the logic below and only process the 5 shown questions. foreach ( $_POST['results'] as $question_id => $q_result ) { if ( 'comp' == $question_id ) continue; if ( ( isset( $q_result['possiblePoints'] ) ) && ( !empty( $q_result['possiblePoints'] ) ) ) { $total_points += intval( $q_result['possiblePoints'] ); } } } else { $total_points = round( $points * 100 / $result ); } $questions_shown_count = count( $_POST['results'] ) - 1; if ( ( isset( $_POST['quiz_nonce'] ) ) && ( isset( $_POST['quizId'] ) ) && ( isset( $_POST['quizId'] ) ) && ( !empty( $user_id ) ) ) { if ( ! wp_verify_nonce( $_POST['quiz_nonce'], 'sfwd-quiz-nonce-' . absint( $_POST['quiz'] ) . '-'. absint( $_POST['quizId'] ) .'-' . $user_id ) ) { return; } } else if ( empty( $_SERVER['HTTP_REFERER'] ) ) { return; } $user_quiz_meta = get_user_meta( $user_id, '_sfwd-quizzes', true ); $user_quiz_meta = maybe_unserialize( $user_quiz_meta ); if ( ! is_array( $user_quiz_meta ) ) { $user_quiz_meta = array(); } $quiz_post_settings = learndash_get_setting( $quiz_post_id ); if ( ! is_array( $quiz_post_settings ) ) { $quiz_post_settings = array(); } if ( ! isset( $quiz_post_settings['passingpercentage'] ) ) { $quiz_post_settings['passingpercentage'] = 0; } $passingpercentage = absint( $quiz_post_settings['passingpercentage'] ); $pass = ( $result >= $passingpercentage) ? 1 : 0; $quiz_post = get_post( $quiz_post_id ); $quizdata = array( 'quiz' => $quiz_post_id, 'score' => $score, 'count' => $questions_count, 'question_show_count' => $questions_shown_count, 'pass' => $pass, 'rank' => '-', 'time' => time(), 'pro_quizid' => $quiz_pro_id, 'course' => $course_id, 'lesson' => $lesson_id, 'topic' => $topic_id, 'points' => absint( $points ), 'total_points' => absint( $total_points ), 'percentage' => $result, 'timespent' => $timespent, 'has_graded' => ( $has_graded ) ? true : false, 'statistic_ref_id' => absint( $statistic_ref_id ) ); //On the timestamps below we divide against 1000 because they were generated via JavaScript which uses milliseconds. if ( isset( $_POST['results']['comp']['quizStartTimestamp'] ) ) $quizdata['started'] = intval( $_POST['results']['comp']['quizStartTimestamp'] / 1000 ); if ( isset( $_POST['results']['comp']['quizEndTimestamp'] ) ) $quizdata['completed'] = intval( $_POST['results']['comp']['quizEndTimestamp'] / 1000 ); if ( $graded ) { $quizdata['graded'] = $graded; } $user_quiz_meta[] = $quizdata; $quizdata['quiz'] = $quiz_post; update_user_meta( $user_id, '_sfwd-quizzes', $user_quiz_meta ); if ( ! empty( $course_id ) ) { $quizdata['course'] = get_post( $course_id ); } else { $quizdata['course'] = 0; } if ( ! empty( $lesson_id ) ) { $quizdata['lesson'] = get_post( $lesson_id ); } else { $quizdata['lesson'] = 0; } if ( ! empty( $topic_id ) ) { $quizdata['topic'] = get_post( $topic_id ); } else { $quizdata['topic'] = 0; } $quizdata['questions'] = $questions; /** * Does the action 'learndash_quiz_submitted' * * @since 3.0 * * @param array $quizdata * @param object $current_user */ do_action( 'learndash_quiz_submitted', $quizdata, get_user_by( 'id', $user_id ) ); /** * Does the action 'learndash_quiz_completed' * * @since 2.1.0 * * @param array $quizdata * @param object $current_user */ /** * Changed in 2.6.0. If the quiz has essay type questions that are not * auto-graded we don't send out the 'learndash_quiz_completed' action. */ $send_quiz_completed = true; if ( ( isset( $quizdata['has_graded'] ) ) && ( true === $quizdata['has_graded'] ) ) { if ( ( isset( $quizdata['graded'] ) ) && ( ! empty( $quizdata['graded'] ) ) ) { foreach ( $quizdata['graded'] as $grade_item ) { if ( ( isset( $grade_item['status'] ) ) && ( $grade_item['status'] !== 'graded' ) ) { $send_quiz_completed = false; } } } } if ( true === $send_quiz_completed ) { if ( ! empty( $course_id ) ) { learndash_process_mark_complete( $user_id, $quiz_post_id, false, $course_id ); } do_action( 'learndash_quiz_completed', $quizdata, get_user_by( 'id', $user_id ) ); } else if ( defined( 'LEARNDASH_QUIZ_ESSAY_SUBMIT_COMPLETED' ) && LEARNDASH_QUIZ_ESSAY_SUBMIT_COMPLETED === true ) { do_action( 'learndash_quiz_completed', $quizdata, get_user_by( 'id', $user_id ) ); } $results[ $quiz_pro_id ]['quiz_result_settings'] = array( 'showAverageResult' => $quiz_pro->isShowAverageResult() ? 1 : 0, 'showCategoryScore' => $quiz_pro->isShowCategoryScore() ? 1 : 0, 'showRestartQuizButton' => $quiz_pro->isBtnRestartQuizHidden() ? 0 : 1 , 'showResultPoints' => $quiz_pro->isHideResultPoints() ? 0 : 1, //'showResultCorrectQuestion' => $quiz_pro->isHideResultCorrectQuestion() ? 0 : 1, 'showResultQuizTime' => $quiz_pro->isHideResultQuizTime() ? 0 : 1, //'showAnswerMessageBox' => $quiz_pro->isHideAnswerMessageBox() ? 0 : 1, 'showViewQuestionButton' => $quiz_pro->isBtnViewQuestionHidden() ? 0 : 1, ); $results[ $quiz_pro_id ]['showContinueButton'] = apply_filters( 'show_quiz_continue_buttom_on_fail', false, $quizdata['quiz'] ) ? 1 : 0; $results[ $quiz_pro_id ]['quiz_result_settings'] = apply_filters( 'learndash_quiz_completed_result_settings', $results[ $quiz_pro_id ]['quiz_result_settings'], $quizdata ); //$results[ $quiz_pro_id ]['quiz_result_settings']['showViewQuestionButton'] = 0; //$results[ $quiz_pro_id ]['quiz_result_settings']['showRestartQuizButton'] = 0; //$results[ $quiz_pro_id ]['quiz_result_settings']['showContinueButton'] = 0; echo json_encode( $results ); exit(); } /** * Returns the Quiz ID when submitting the Pro Quiz ID * * @since 2.1.0 * * @param int $pro_quizid * @return int quiz ID */ function get_ld_quiz_id( $pro_quizid ) { $quizzes = SFWD_SlickQuiz::get_all_quizzes(); foreach ( $quizzes as $quiz ) { $quizmeta = get_post_meta( $quiz->ID, '_sfwd-quiz', true ); if ( ! empty( $quizmeta['sfwd-quiz_quiz_pro'] ) && $quizmeta['sfwd-quiz_quiz_pro'] == $pro_quizid ) { return $quiz->ID; } } } /** * Returns an array of quizes in the string format of "$quiz_id - $quiz_name" * * @since 2.1.0 * * @return array $list String of $q->getId() . ' - ' . $q->getName() */ static function get_quiz_list() { $quizzes_list = array(); /* $transient_key = "learndash_quizzes_list"; $quizzes_list = LDLMS_Transients::get( $transient_key ); if ( $quizzes_list === false ) { $quiz = new WpProQuiz_Model_QuizMapper(); $quizzes = $quiz->fetchAll(); if ( ! empty( $quizzes ) ) { foreach ( $quizzes as $q ) { $quizzes_list[ $q->getId() ] = $q->getId() . ' - ' . $q->getName(); } } LDLMS_Transients::set( $transient_key, $quizzes_list, MINUTE_IN_SECONDS ); } return $quizzes_list; */ /** * Logic rewrite * The above logic was abondoned as being to heave for sites running over a few hundred quizzes. This function is only used on the * single Quix admin editor form and only used to show a select box with the quiz title. So don't need to ever overhead of the * MVC object loading. * * * @since 2.2.0.2 * */ global $wpdb; $quiz_items = $wpdb->get_results( $wpdb->prepare( "SELECT id, name FROM " . LDLMS_DB::get_table_name( 'quiz_master' ) . " ORDER BY %s ", 'id' ) ); if ( ! empty( $quiz_items ) ) { foreach ( $quiz_items as $q ) { $quizzes_list[ $q->id ] = $q->id . ' - ' . $q->name; } } return $quizzes_list; } /** * Echoes the HTML with inline javascript that contains the JSON representation of the certificate details and continue link details * * @since 2.1.0 */ static function certificate_details( $pro_quiz_id = null ) { $quiz_post_id = 0; if ( is_null( $pro_quiz_id ) ) { global $post; if ( ( $post instanceof WP_Post ) && ( $post->post_type == 'sfwd-quiz' ) ) { $pro_quiz_id = $post->ID; } } else { if ( is_a( $pro_quiz_id, 'WpProQuiz_Model_Quiz' ) ) { $pro_quiz = $pro_quiz_id; $pro_quiz_id = $pro_quiz->getId(); $quiz_post_id = $pro_quiz->getPostId(); } else { $quiz_post_id = learndash_get_quiz_id_by_pro_quiz_id( $pro_quiz_id ); } if ( !empty( $quiz_post_id ) ) { $quiz_post = get_post( $quiz_post_id ); if ( ( $quiz_post instanceof WP_Post ) && ( $quiz_post->post_type == 'sfwd-quiz' ) ) { $quiz_post_id = $quiz_post->ID; } } } if ( !empty( $quiz_post_id ) ) { $continue_link = learndash_quiz_continue_link( $quiz_post_id ); echo ''; echo ''; /** Continue link will appear through javascript **/ echo ''; } } /** * Returns the certificate link appended to input HTML content if the Post ID is set, else it only returns the input HTML content * * @since 2.1.0 * * @param string $content HTML * @param mixed $pro_quiz (integer) WPProQuixz ID, (object) WpProQuiz_Model_Quiz * @return string HTML $content or $content concatenated with the certificate link */ static function certificate_link( $content, $pro_quiz = null ) { $quiz_post_id = null; $pro_quiz_id = null; if ( ! is_null( $pro_quiz ) ) { if ( is_a( $pro_quiz, 'WpProQuiz_Model_Quiz') ) { $pro_quiz_id = $pro_quiz->getId(); $quiz_post_id = $pro_quiz->getPostId(); } else { $pro_quiz_id = absint( $pro_quiz ); } } if ( empty( $quiz_post_id ) ) { if ( empty( $pro_quiz_id ) ) { //global $post; //if ( ( $post instanceof WP_Post ) && ( $post->post_type == 'sfwd-quiz' ) ) { // $quiz_post_id = $post->ID; //} $post_id = get_the_ID(); if ( !empty( $post_id ) ) { $quiz_post = get_post( $post_id ); if ( ( $quiz_post instanceof WP_Post ) && ( $quiz_post->post_type == 'sfwd-quiz' ) ) { $quiz_post_id = $quiz_post->ID; } } } if ( empty( $quiz_post_id ) ) { $quiz_post_id = learndash_get_quiz_id_by_pro_quiz_id( $pro_quiz_id ); if ( !empty( $quiz_post_id ) ) { $quiz_post = get_post( $quiz_post_id ); if ( ( $quiz_post instanceof WP_Post ) && ( $quiz_post->post_type == 'sfwd-quiz' ) ) { $quiz_post_id = $quiz_post->ID; } } } } else { $quiz_post = get_post( $quiz_post_id ); if ( ( $quiz_post instanceof WP_Post ) && ( $quiz_post->post_type == 'sfwd-quiz' ) ) { $quiz_post_id = $quiz_post->ID; } else { $quiz_post_id = 0; } } if ( !empty( $quiz_post_id ) ) { $cd = learndash_certificate_details( $quiz_post_id ); if ( ( !empty( $cd ) ) && ( isset( $cd['certificateLink'] ) ) && ( !empty( $cd['certificateLink'] ) ) ) { $user_id = get_current_user_id(); $ret = "" . apply_filters('ld_certificate_link_label', SFWD_LMS::get_template( 'learndash_quiz_messages', array( 'quiz_post_id' => $quiz_post_id, 'context' => 'quiz_certificate_button_label', 'message' => esc_html__( 'PRINT YOUR CERTIFICATE', 'learndash' ) ) ), $user_id, $quiz_post_id ) . ''; $content .= $ret; } } return $content; } /** * Returns the HTML of the add or edit page for the current quiz. If advanced quizes are disabled, it returns an empty string. * * @since 2.1.0 * * @return string */ static function edithtml() { global $pagenow, $post; $_post = array( '1' ); if ( ! empty( $_GET['templateLoadId'] ) ) { $_post = $_GET; } if ( $pagenow == 'post-new.php' && @$_GET['post_type'] == 'sfwd-quiz' || $pagenow == 'post.php' && ! empty( $_GET['post'] ) && @get_post( $_GET['post'] )->post_type == 'sfwd-quiz' ) { //To fix issues with plugins using get_current_screen $screen_file = ABSPATH . '/wp-admin/includes/screen.php'; require_once( $screen_file ); //To fix issues with plugins using get_current_screen $quizId = 0; $post_id = 0; if ( ! empty( $_GET['post'] ) ) { $post_id = intval( $_GET['post'] ); $quizId = intval( learndash_get_setting( $post_id, 'quiz_pro', true ) ); /** * Filter whether advance quiz is disabled or not * * @param bool */ if ( apply_filters( 'learndash_disable_advance_quiz', false, $post_id ) ) { return ''; } } else { global $post; if ( ( is_a( $post, 'WP_Post' ) ) && ( $post->post_type == 'sfwd-quiz' ) ) { //error_log('post
'. print_r($post, true) .'
'); $post_id = $post->ID; } } $pro_quiz = new WpProQuiz_Controller_Quiz(); ob_start(); $pro_quiz->route( array( 'action' => 'addEdit', 'quizId' => $quizId, 'post_id' => $post_id, ), $_post ); $return = ob_get_clean(); return $return; } } /** * Routes to the WpProQuiz_Controller_Quiz controller to output the add or edit page for quizes if not autosaving, post id is set, * and the current user has permissions to add or edit quizes. If there is an available template to load, wordpress redirects to * the proper URL. * * @since 2.1.0 * * @param int $post_id */ static function edit_process( $post_id ) { if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } if ( empty( $post_id) || empty( $_POST['post_type'] ) ) { return ''; } // Check permissions if ( 'page' == $_POST['post_type'] ) { if ( ! current_user_can( 'edit_page', $post_id ) ) { return; } } else { if ( ! current_user_can( 'edit_post', $post_id ) ) { return; } } $post = get_post( $post_id ); /** * Filter whether advance quiz is disabled or not * * @param bool */ if ( 'sfwd-quiz' != $post->post_type || empty( $_POST['form'] ) || ! empty( $_POST['disable_advance_quiz_save'] ) || apply_filters( 'learndash_disable_advance_quiz', false, $post ) ) { return; } $quizId = intval( learndash_get_setting( $post_id, 'quiz_pro', true ) ); $pro_quiz = new WpProQuiz_Controller_Quiz(); //ob_start(); //$pro_quiz->route( array( 'action' => 'addEdit', 'quizId' => $quizId, 'post_id' => $post_id) ); //ob_get_clean(); $pro_quiz->route( array( 'action' => 'addUpdateQuiz', 'quizId' => $quizId, 'post_id' => $post_id) ); if ( ! empty( $_POST['templateLoad'] ) && ! empty( $_POST['templateLoadId'] ) ) { $url = admin_url( 'post.php?post=' . $post_id . '&action=edit' ) . '&templateLoad=' . rawurlencode( $_POST['templateLoad'] ) . '&templateLoadId=' . $_POST['templateLoadId']; wp_redirect( $url ); exit; } } /** * Returns a MD5 checksum on a concatenated string comprised of user id, question id, and pos * * @since 2.1.0 * * @param int $question_id * @param int $pos * @return string MD5 Checksum */ static function datapos( $question_id, $pos ) { $pos = intval( $pos );; return md5( get_current_user_id() . $question_id . $pos ); } /** * Returns an array of MD5 Checksums on a concatenated string comprised of user id, question id, and i, where the array size is count and i is incremented from 0 for each array element * * @since 2.1.0 * * @param int $question_id * @param int $count * @return array Array of MD5 checksum strings */ static function datapos_array( $question_id, $count ) { $datapos_array = array(); $user_id = get_current_user_id(); for ( $i = 0; $i < $count; $i++ ) { $datapos_array[ $i] = md5( $user_id . $question_id . $i ); } return $datapos_array; } static function showModalWindow() { static $show_only_once = false; /** * Added for LEARNDASH-2754 to prevent loading the inline CSS when inside * the Gutenberg editor publish/update. Need a better way to handle this. */ if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { return false; } if ( ! $show_only_once ) { $show_only_once = true; ?> '. print_r($post, true) .''); //$user_quiz_progress = get_user_meta( 1, '_sfwd-quizzes', true); //error_log('user_quiz_progress
'. print_r($user_quiz_progress, true) .'
'); // First we get the wp_pro_quiz_id from the post meta for this $wp_pro_quiz_id = get_post_meta( $quiz_post->ID, 'quiz_pro_id', true); //error_log('wp_pro_quiz_id['. $wp_pro_quiz_id .']'); $user_id = get_current_user_id(); if ( ( !empty( $wp_pro_quiz_id ) ) && ( !empty( $user_id ) ) ) { global $wpdb; $sql_str = $wpdb->prepare( "SELECT statistic_ref_id FROM ". LDLMS_DB::get_table_name( 'quiz_statistic_ref' ) . " WHERE quiz_id=%d AND user_id=%d ORDER BY create_time DESC", $wp_pro_quiz_id, $user_id ); $quiz_post_id_statistic_ref_id = $wpdb->get_var( $sql_str ); if ( !empty( $quiz_post_id_statistic_ref_id ) ) { $sql_str = $wpdb->prepare( "SELECT * FROM ". LDLMS_DB::get_table_name( 'quiz_statistic' ) . " WHERE statistic_ref_id=%d", $quiz_post_id_statistic_ref_id ); //error_log('sql_str['. $sql_str .']'); $quiz_post_id_statistics = $wpdb->get_results( $sql_str ); //error_log('quiz_post_id_statistics
'. print_r($quiz_post_id_statistics, true) .'
'); if ( !empty( $quiz_post_id_statistics ) ) { $quiz_statistics_data = array(); $quiz_statistics_data['data'] = $quiz_post_id_statistics; $quiz_statistics_data['button'] = ''; $quiz_content .= '
'; } } } return $quiz_content; } } new LD_QuizPro(); /** * LearnDash return all global Quizzes. * * This function will query and return all global. * A GLOBAL Quizzes is: * 1. Quizzes not associated with a Course. * * @since 2.6 * * @param boolean $bypass_transient Force By Pass of transient caching. * @return array Quiz ids. */ function learndash_get_non_course_qizzes( $bypass_transient = false ) { global $wpdb; $global_quiz_ids = array(); $transient_key = 'learndash_global_quiz_ids'; if ( ! $bypass_transient ) { $global_quiz_ids_transient = LDLMS_Transients::get( $transient_key ); } else { $global_quiz_ids_transient = false; } if ( false === $global_quiz_ids_transient ) { $global_quiz_ids_query_str = "SELECT posts.ID FROM {$wpdb->posts} as posts LEFT JOIN {$wpdb->postmeta} as postmeta1 ON posts.ID = postmeta1.post_id AND postmeta1.meta_key LIKE 'ld_course%' LEFT JOIN {$wpdb->postmeta} as postmeta2 ON posts.ID = postmeta2.post_id AND postmeta2.meta_key = 'course_id' WHERE posts.post_type = 'sfwd-quiz' AND ( postmeta1.post_id IS NULL AND postmeta2.post_id IS NULL )"; $global_quiz_ids = $wpdb->get_col( $global_quiz_ids_query_str ); LDLMS_Transients::set( $transient_key, $global_quiz_ids, MINUTE_IN_SECONDS ); } else { $global_quiz_ids = $global_quiz_ids_transient; } return $global_quiz_ids; } /** * LearnDash return all open Quizzes. * * This function will query and return all open Quizzes. * An OPEN Quiz is: * 1. Not associated with a Course. * 2. The Quiz settiing "Only registered users are allowed to start the quiz" is NOT set. * * @since 2.6 * * @param boolean $bypass_transient Force By Pass of transient caching. * @return array Quiz ids. */ function learndash_get_open_quizzes( $bypass_transient = false ) { global $wpdb; $open_quiz_ids = array(); $transient_key = 'learndash_global_quiz_ids'; if ( ! $bypass_transient ) { $open_quiz_ids_transient = LDLMS_Transients::get( $transient_key ); } else { $open_quiz_ids_transient = false; } if ( false === $open_quiz_ids_transient ) { $global_quiz_ids = learndash_get_non_course_qizzes(); if ( ! empty( $global_quiz_ids ) ) { $open_quiz_ids_query_str = "SELECT posts.ID FROM {$wpdb->posts} as posts LEFT JOIN {$wpdb->postmeta} as postmeta1 ON posts.ID = postmeta1.post_id AND postmeta1.meta_key = 'quiz_pro_id' LEFT JOIN ". LDLMS_DB::get_table_name( 'quiz_master' ) ." as quiz_master ON postmeta1.meta_value = quiz_master.id WHERE posts.post_type = 'sfwd-quiz' AND posts.ID IN (" . implode( ',', $global_quiz_ids) . ") AND quiz_master.start_only_registered_user = 0"; $open_quiz_ids = $wpdb->get_col( $open_quiz_ids_query_str ); LDLMS_Transients::set( $transient_key, $open_quiz_ids, MINUTE_IN_SECONDS ); } } else { $open_quiz_ids = $open_quiz_ids_transient; } return $open_quiz_ids; } ld-quiz-info-shortcode.php000066600000045020152142404260011570 0ustar00 '', // [score], [count], [pass], [rank], [timestamp], [pro_quizid], [points], [total_points], [percentage], [timespent] 'user_id' => '', 'quiz' => '', 'time' => '', 'field_id' => '', 'format' => 'F j, Y, g:i a', ), $attr ); extract( $shortcode_atts ); $time = ( empty( $time ) && isset( $_REQUEST['time'] ) ) ? $_REQUEST['time'] : $time; $show = ( empty( $show ) && isset( $_REQUEST['show'] ) ) ? $_REQUEST['show'] : $show; $quiz = ( empty( $quiz ) && isset( $_REQUEST['quiz'] ) ) ? $_REQUEST['quiz'] : $quiz; $user_id = ( empty( $user_id ) && isset( $_REQUEST['user_id'] ) ) ? $_REQUEST['user_id'] : $user_id; $course_id = ( empty( $course_id ) && isset( $_REQUEST['course_id'] ) ) ? $_REQUEST['course_id'] : null; $field_id = ( empty( $field_id ) && isset( $_REQUEST['field_id'] ) ) ? $_REQUEST['field_id'] : $field_id; if ( empty( $user_id ) ) { $user_id = get_current_user_id(); /** * Added logic to allow admin and group_leader to view certificate from other users. * * @since 2.3 */ $post_type = ''; if ( get_query_var( 'post_type' ) ) { $post_type = get_query_var( 'post_type' ); } if ( $post_type == 'sfwd-certificates' ) { if ( ( ( learndash_is_admin_user() ) || ( learndash_is_group_leader_user() ) ) && ( ( isset( $_GET['user'] ) ) && ( ! empty( $_GET['user'] ) ) ) ) { $user_id = intval( $_GET['user'] ); } } } if ( empty( $quiz ) || empty( $user_id ) || empty( $show ) ) { return ''; } $shortcode_atts['time'] = $time; $shortcode_atts['show'] = $show; $shortcode_atts['quiz'] = $quiz; $shortcode_atts['user_id'] = $user_id; $shortcode_atts['course_id'] = $course_id; $shortcode_atts['field_id'] = $field_id; $quizinfo = get_user_meta( $user_id, '_sfwd-quizzes', true ); $selected_quizinfo = ''; $selected_quizinfo2 = ''; foreach ( $quizinfo as $quiz_i ) { if ( isset( $quiz_i['time'] ) && $quiz_i['time'] == $time && $quiz_i['quiz'] == $quiz ) { $selected_quizinfo = $quiz_i; break; } if ( $quiz_i['quiz'] == $quiz ) { $selected_quizinfo2 = $quiz_i; } } $selected_quizinfo = empty( $selected_quizinfo ) ? $selected_quizinfo2 : $selected_quizinfo; switch ( $show ) { case 'timestamp': // date_default_timezone_set( get_option( 'timezone_string' ) ); // $selected_quizinfo['timestamp'] = date_i18n( $format, $selected_quizinfo['time'] ); $selected_quizinfo['timestamp'] = learndash_adjust_date_time_display( $selected_quizinfo['time'], $format ); break; case 'percentage': if ( empty( $selected_quizinfo['percentage'] ) ) { $selected_quizinfo['percentage'] = empty( $selected_quizinfo['count'] ) ? 0 : $selected_quizinfo['score'] * 100 / $selected_quizinfo['count']; } break; case 'pass': $selected_quizinfo['pass'] = ! empty( $selected_quizinfo['pass'] ) ? esc_html__( 'Yes', 'learndash' ) : esc_html__( 'No', 'learndash' ); break; case 'quiz_title': $quiz_post = get_post( $quiz ); if ( ! empty( $quiz_post->post_title ) ) { $selected_quizinfo['quiz_title'] = $quiz_post->post_title; } break; case 'course_title': if ( ( isset( $selected_quizinfo['course'] ) ) && ( ! empty( $selected_quizinfo['course'] ) ) ) { $course_id = intval( $selected_quizinfo['course'] ); } else { $course_id = learndash_get_setting( $quiz, 'course' ); } if ( ! empty( $course_id ) ) { $course = get_post( $course_id ); if ( ( is_a( $course, 'WP_Post' ) ) && ( ! empty( $course->post_title ) ) ) { $selected_quizinfo['course_title'] = $course->post_title; } } break; case 'timespent': $selected_quizinfo['timespent'] = isset( $selected_quizinfo['timespent'] ) ? learndash_seconds_to_time( $selected_quizinfo['timespent'] ) : ''; break; case 'field': if ( ! empty( $field_id ) ) { if ( ( isset( $selected_quizinfo['pro_quizid'] ) ) && ( ! empty( $selected_quizinfo['pro_quizid'] ) ) ) { $formMapper = new WpProQuiz_Model_FormMapper(); $quiz_form_elements = $formMapper->fetch( $selected_quizinfo['pro_quizid'] ); if ( ! empty( $quiz_form_elements ) ) { foreach ( $quiz_form_elements as $quiz_form_element ) { if ( absint( $field_id ) == absint( $quiz_form_element->getFormId() ) ) { $selected_quizinfo[ $show ] = ''; if ( ( isset( $selected_quizinfo['statistic_ref_id'] ) ) && ( ! empty( $selected_quizinfo['statistic_ref_id'] ) ) ) { $statisticRefMapper = new WpProQuiz_Model_StatisticRefMapper(); $statisticRefData = $statisticRefMapper->fetchAllByRef( $selected_quizinfo['statistic_ref_id'] ); if ( ( $statisticRefData ) && ( is_a( $statisticRefData, 'WpProQuiz_Model_StatisticRefModel' ) ) ) { $form_data = $statisticRefData->getFormData(); if ( isset( $form_data[ $field_id ] ) ) { $selected_quizinfo[ $show ] = $quiz_form_element->getValue( $form_data[ $field_id ] ); } } } break; } } } } } break; } /** * Filter for quizinfo shortcode output. * * @since 2.1.0 * @since 3.1.4 Added $selected_quizinfo param. * * @param mixed Value of 'show' paramter. * @param array $shortcode_atts Array of shortcode attributed. * @param array $selected_quizinfo Quiz item array used for processing. */ if ( isset( $selected_quizinfo[ $show ] ) ) { return apply_filters( 'learndash_quizinfo', $selected_quizinfo[ $show ], $shortcode_atts, $selected_quizinfo ); } else { return apply_filters( 'learndash_quizinfo', '', $shortcode_atts, $selected_quizinfo ); } } add_shortcode( 'quizinfo', 'learndash_quizinfo' ); /** * Shortcode that displays the requested course information * * @since 2.1.0 * * @param array $attr shortcode attributes. * * @return string shortcode output */ function learndash_courseinfo( $attr ) { global $learndash_shortcode_used; $learndash_shortcode_used = true; $shortcode_atts = shortcode_atts( array( 'show' => 'course_title', 'user_id' => '', 'course_id' => '', 'format' => 'F j, Y, g:i a', 'seconds_format' => 'time', 'decimals' => 2, ), $attr ); $shortcode_atts['course_id'] = ! empty( $shortcode_atts['course_id'] ) ? $shortcode_atts['course_id'] : ''; if ( '' === $shortcode_atts['course_id'] ) { if ( ( isset( $_GET['course_id'] ) ) && ( ! empty( $_GET['course_id'] ) ) ) { $shortcode_atts['course_id'] = intval( $_GET['course_id'] ); } else { $shortcode_atts['course_id'] = learndash_get_course_id(); } } $shortcode_atts['user_id'] = ! empty( $shortcode_atts['user_id'] ) ? $shortcode_atts['user_id'] : ''; if ( '' === $shortcode_atts['user_id'] ) { if ( ( isset( $_GET['user_id'] ) ) && ( ! empty( $_GET['user_id'] ) ) ) { $shortcode_atts['user_id'] = intval( $_GET['user_id'] ); } } if ( empty( $shortcode_atts['user_id'] ) ) { $shortcode_atts['user_id'] = get_current_user_id(); /** * Added logic to allow admin and group_leader to view certificate from other users. * * @since 2.3 */ $post_type = ''; if ( get_query_var( 'post_type' ) ) { $post_type = get_query_var( 'post_type' ); } if ( 'sfwd-certificates' == $post_type ) { if ( ( ( learndash_is_admin_user() ) || ( learndash_is_group_leader_user() ) ) && ( ( isset( $_GET['user'] ) ) && ( ! empty( $_GET['user'] ) ) ) ) { $shortcode_atts['user_id'] = intval( $_GET['user'] ); } } } if ( empty( $shortcode_atts['course_id'] ) || empty( $shortcode_atts['user_id'] ) ) { return apply_filters( 'learndash_courseinfo', '', $shortcode_atts ); } $shortcode_atts['show'] = strtolower( $shortcode_atts['show'] ); switch ( $shortcode_atts['show'] ) { case 'course_title': $shortcode_atts[ $shortcode_atts['show'] ] = ''; $course = get_post( $shortcode_atts['course_id'] ); if ( ( $course ) && ( is_a( $course, 'WP_Post' ) ) ) { $shortcode_atts[ $shortcode_atts['show'] ] = $course->post_title; } return apply_filters( 'learndash_courseinfo', $shortcode_atts[ $shortcode_atts['show'] ], $shortcode_atts ); break; case 'course_url': $shortcode_atts[ $shortcode_atts['show'] ] = ''; $course = get_post( $shortcode_atts['course_id'] ); if ( ( $course ) && ( is_a( $course, 'WP_Post' ) ) ) { $shortcode_atts[ $shortcode_atts['show'] ] = get_permalink( $shortcode_atts['course_id'] ); } return apply_filters( 'learndash_courseinfo', $shortcode_atts[ $shortcode_atts['show'] ], $shortcode_atts ); break; case 'course_price_type': $shortcode_atts[ $shortcode_atts['show'] ] = ''; $course = get_post( $shortcode_atts['course_id'] ); if ( ( $course ) && ( is_a( $course, 'WP_Post' ) ) ) { $shortcode_atts[ $shortcode_atts['show'] ] = learndash_get_setting( $shortcode_atts['course_id'], 'course_price_type' ); } return apply_filters( 'learndash_courseinfo', $shortcode_atts[ $shortcode_atts['show'] ], $shortcode_atts ); break; case 'course_price': $shortcode_atts[ $shortcode_atts['show'] ] = ''; $course = get_post( $shortcode_atts['course_id'] ); if ( ( $course ) && ( is_a( $course, 'WP_Post' ) ) ) { $shortcode_atts[ $shortcode_atts['show'] ] = learndash_get_setting( $shortcode_atts['course_id'], 'course_price' ); } return apply_filters( 'learndash_courseinfo', $shortcode_atts[ $shortcode_atts['show'] ], $shortcode_atts ); break; case 'user_course_time': $shortcode_atts[ $shortcode_atts['show'] ] = 0; if ( ! empty( $shortcode_atts['user_id'] ) ) { $activity_query_args = array( 'post_types' => learndash_get_post_type_slug( 'course' ), 'activity_types' => 'course', 'per_page' => 1, 'page' => 1, ); $activity_query_args['user_ids'] = $shortcode_atts['user_id']; $activity_query_args['post_ids'] = $shortcode_atts['course_id']; $user_courses_reports = learndash_reports_get_activity( $activity_query_args ); if ( ! empty( $user_courses_reports['results'] ) ) { $activity_started = 0; $activity_completed = 0; foreach ( $user_courses_reports['results'] as $course_activity ) { if ( ( property_exists( $course_activity, 'activity_started' ) ) && ( ! empty( $course_activity->activity_started ) ) ) { $activity_started = $course_activity->activity_started; } if ( ( property_exists( $course_activity, 'activity_completed' ) ) && ( ! empty( $course_activity->activity_completed ) ) ) { $activity_completed = $course_activity->activity_completed; } elseif ( ( property_exists( $course_activity, 'activity_updated' ) ) && ( ! empty( $course_activity->activity_updated ) ) ) { $activity_completed = $course_activity->activity_updated; } // There should only be one user+course entry. But just in case we break out of our loop here. break; } if ( ( ! empty( $activity_started ) ) && ( ! empty( $activity_completed ) ) ) { $shortcode_atts[ $shortcode_atts['show'] ] = absint( $activity_completed ) - absint( $activity_started ); } } } if ( 'time' === $shortcode_atts['seconds_format'] ) { return apply_filters( 'learndash_courseinfo', learndash_seconds_to_time( $shortcode_atts[ $shortcode_atts['show'] ] ), $shortcode_atts ); } else { return apply_filters( 'learndash_courseinfo', $shortcode_atts[ $shortcode_atts['show'] ], $shortcode_atts ); } break; case 'cumulative_score': case 'cumulative_points': case 'cumulative_total_points': case 'cumulative_percentage': case 'cumulative_timespent': case 'cumulative_count': $shortcode_atts[ $shortcode_atts['show'] ] = ''; $field = str_replace( 'cumulative_', '', $shortcode_atts['show'] ); $quizdata = get_user_meta( $shortcode_atts['user_id'], '_sfwd-quizzes', true ); $quizzes = learndash_course_get_steps_by_type( intval( $shortcode_atts['course_id'] ), 'sfwd-quiz' ); if ( empty( $quizzes ) ) { return apply_filters( 'learndash_courseinfo', 0, $shortcode_atts ); } /** * Filters Quizzes to be included in calculations. * * @since 3.1.2 * @param array $quizzes Array of Quiz IDs to be processed. * @param array $shortcode_atts Array of shortcode attributes. * @return array of Quiz IDs. */ $quizzes = apply_filters( 'learndash_courseinfo_quizzes', $quizzes, $shortcode_atts ); $scores = array(); if ( ( ! empty( $quizdata ) ) && ( is_array( $quizdata ) ) ) { foreach ( $quizdata as $data ) { if ( ( is_array( $quizzes ) ) && ( ( in_array( $data['quiz'], $quizzes ) ) ) ) { if ( ( ! isset( $data['course'] ) ) || ( intval( $data['course'] ) == intval( $shortcode_atts['course_id'] ) ) ) { if ( empty( $scores[ $data['quiz'] ] ) || $scores[ $data['quiz'] ] < $data[ $field ] ) { $scores[ $data['quiz'] ] = $data[ $field ]; } } } } } if ( empty( $scores ) || ! count( $scores ) ) { return apply_filters( 'learndash_courseinfo', 0, $shortcode_atts ); } $sum = 0; foreach ( $scores as $score ) { $sum += $score; } $return = number_format( $sum / count( $scores ), $shortcode_atts['decimals'] ); $shortcode_atts[ $shortcode_atts['show'] ] = $return; if ( 'timespent' == $field ) { if ( 'time' === $shortcode_atts['seconds_format'] ) { return apply_filters( 'learndash_courseinfo', learndash_seconds_to_time( $shortcode_atts[ $shortcode_atts['show'] ] ), $shortcode_atts ); } else { return apply_filters( 'learndash_courseinfo', $shortcode_atts[ $shortcode_atts['show'] ], $shortcode_atts ); } } else { return apply_filters( 'learndash_courseinfo', $shortcode_atts[ $shortcode_atts['show'] ], $shortcode_atts ); } break; case 'aggregate_percentage': case 'aggregate_score': case 'aggregate_points': case 'aggregate_total_points': case 'aggregate_timespent': case 'aggregate_count': $shortcode_atts[ $shortcode_atts['show'] ] = ''; $field = substr_replace( $shortcode_atts['show'], '', 0, 10 ); $quizdata = get_user_meta( $shortcode_atts['user_id'], '_sfwd-quizzes', true ); $quizzes = learndash_course_get_steps_by_type( intval( $shortcode_atts['course_id'] ), 'sfwd-quiz' ); if ( empty( $quizzes ) ) { return apply_filters( 'learndash_courseinfo', 0, $shortcode_atts ); } /** * Filters Quizzes to be included in calculations. * * @since 3.1.2 * @param array $quizzes Array of Quiz IDs to be processed. * @param array $shortcode_atts Array of shortcode attributes. * @return array of Quiz IDs. */ $quizzes = apply_filters( 'learndash_courseinfo_quizzes', $quizzes, $shortcode_atts ); $scores = array(); if ( ( ! empty( $quizdata ) ) && ( is_array( $quizdata ) ) ) { foreach ( $quizdata as $data ) { if ( ( is_array( $quizzes ) ) && ( ( in_array( $data['quiz'], $quizzes ) ) ) ) { if ( ( empty( $scores[ $data['quiz'] ] ) || $scores[ $data['quiz'] ] < $data[ $field ] ) ) { if ( ( ! isset( $data['course'] ) ) || ( intval( $data['course'] ) == intval( $shortcode_atts['course_id'] ) ) ) { $scores[ $data['quiz'] ] = $data[ $field ]; } } } } } if ( empty( $scores ) || ! count( $scores ) ) { return apply_filters( 'learndash_courseinfo', 0, $shortcode_atts ); } $sum = 0; foreach ( $scores as $score ) { $sum += $score; } $return = number_format( $sum, $shortcode_atts['decimals'] ); $shortcode_atts[ $shortcode_atts['show'] ] = $return; if ( 'timespent' == $field ) { if ( 'time' === $shortcode_atts['seconds_format'] ) { return apply_filters( 'learndash_courseinfo', learndash_seconds_to_time( $shortcode_atts[ $shortcode_atts['show'] ] ), $shortcode_atts['show'] ); } else { return apply_filters( 'learndash_courseinfo', $shortcode_atts[ $shortcode_atts['show'] ], $shortcode_atts['show'] ); } } else { return apply_filters( 'learndash_courseinfo', $shortcode_atts[ $shortcode_atts['show'] ], $shortcode_atts ); } case 'completed_on': $shortcode_atts[ $shortcode_atts['show'] ] = ''; $completed_on = get_user_meta( $shortcode_atts['user_id'], 'course_completed_' . $shortcode_atts['course_id'], true ); if ( empty( $completed_on ) ) { $completed_on = learndash_user_get_course_completed_date( $shortcode_atts['user_id'], $shortcode_atts['course_id'] ); if ( empty( $completed_on ) ) { return apply_filters( 'learndash_courseinfo', '-', $shortcode_atts ); } } $shortcode_atts[ $shortcode_atts['show'] ] = $completed_on; return apply_filters( 'learndash_courseinfo', learndash_adjust_date_time_display( $completed_on, $shortcode_atts['format'] ), $shortcode_atts ); break; case 'enrolled_on': $shortcode_atts[ $shortcode_atts['show'] ] = ''; $enrolled_on = get_user_meta( $shortcode_atts['user_id'], 'course_' . $shortcode_atts['course_id'] . '_access_from', true ); if ( empty( $enrolled_on ) ) { return apply_filters( 'learndash_courseinfo', '-', $shortcode_atts ); } $shortcode_atts[ $shortcode_atts['show'] ] = $enrolled_on; return apply_filters( 'learndash_courseinfo', learndash_adjust_date_time_display( $enrolled_on, $shortcode_atts['format'] ), $shortcode_atts ); break; case 'course_points': $shortcode_atts[ $shortcode_atts['show'] ] = ''; $course_points = learndash_get_course_points( $shortcode_atts['course_id'], $shortcode_atts['decimals'] ); $course_points = number_format( $course_points, $shortcode_atts['decimals'] ); $shortcode_atts[ $shortcode_atts['show'] ] = $course_points; return apply_filters( 'learndash_courseinfo', $course_points, $shortcode_atts ); break; case 'user_course_points': $shortcode_atts[ $shortcode_atts['show'] ] = ''; $user_course_points = learndash_get_user_course_points( $shortcode_atts['user_id'] ); $user_course_points = number_format( $user_course_points, $shortcode_atts['decimals'] ); $shortcode_atts[ $shortcode_atts['show'] ] = $user_course_points; return apply_filters( 'learndash_courseinfo', $user_course_points, $shortcode_atts ); break; default: return apply_filters( 'learndash_courseinfo', '', $shortcode_atts ); } } add_shortcode( 'courseinfo', 'learndash_courseinfo' ); ld-quiz-essays.php000066600000166324152142404260010167 0ustar00 esc_html_x( 'Submitted Essays', 'Post Type General Name', 'learndash' ), 'singular_name' => esc_html_x( 'Submitted Essay', 'Post Type Singular Name', 'learndash' ), 'menu_name' => esc_html__( 'Submitted Essays', 'learndash' ), 'name_admin_bar' => esc_html__( 'Submitted Essays', 'learndash' ), 'parent_item_colon' => esc_html__( 'Parent Submitted Essay:', 'learndash' ), 'all_items' => esc_html__( 'All Submitted Essays', 'learndash' ), 'add_new_item' => esc_html__( 'Add New Submitted Essay', 'learndash' ), 'add_new' => esc_html__( 'Add New', 'learndash' ), 'new_item' => esc_html__( 'New Submitted Essay', 'learndash' ), 'edit_item' => esc_html__( 'Edit Submitted Essay', 'learndash' ), 'update_item' => esc_html__( 'Update Submitted Essay', 'learndash' ), 'view_item' => esc_html__( 'View Submitted Essay', 'learndash' ), 'view_items' => esc_html__( 'View Submitted Essays', 'learndash' ), 'search_items' => esc_html__( 'Search Submitted Essays', 'learndash' ), 'not_found' => esc_html__( 'Submitted Essay Not found', 'learndash' ), 'not_found_in_trash' => esc_html__( 'Submitted Essay Not found in Trash', 'learndash' ), 'item_published' => esc_html__( 'Submitted Essay Published', 'learndash' ), 'item_published_privately' => esc_html__( 'Submitted Essay Published Privately', 'learndash' ), 'item_reverted_to_draft' => esc_html__( 'Submitted Essay Reverted to Draft', 'learndash' ), 'item_scheduled' => esc_html__( 'Submitted Essay Scheduled', 'learndash' ), 'item_updated' => esc_html__( 'Submitted Essay Updated', 'learndash' ), ); $capabilities = array( 'edit_essay' => 'edit_essay', 'read_essay' => 'read_essay', 'delete_essay' => 'delete_essay', 'edit_essays' => 'edit_essays', 'edit_others_essays' => 'edit_others_essays', 'publish_essays' => 'publish_essays', 'read_private_essays' => 'read_private_essays', ); if ( learndash_is_admin_user() ) { $show_in_admin_bar = false; } else if ( learndash_is_group_leader_user() ) { $show_in_admin_bar = false; } else { $show_in_admin_bar = false; } $args = array( 'label' => esc_html__( 'sfwd-essays', 'learndash' ), 'description' => esc_html__( 'Submitted essays via a quiz question.', 'learndash' ), 'labels' => $labels, 'supports' => array( 'title', 'editor', 'comments', 'author'), 'hierarchical' => false, 'public' => true, 'show_ui' => true, 'show_in_menu' => false, 'show_in_admin_bar' => $show_in_admin_bar, 'query_var' => true, 'rewrite' => array( 'slug' => 'essay' ), 'menu_position' => 5, 'show_in_admin_bar' => false, 'show_in_nav_menus' => false, 'can_export' => true, 'has_archive' => false, 'show_in_rest' => false, 'exclude_from_search' => true, 'publicly_queryable' => true, 'capability_type' => 'essay', 'capabilities' => $capabilities, 'map_meta_cap' => true, ); $args = apply_filters( 'learndash-cpt-options', $args, 'sfwd-essays' ); register_post_type( 'sfwd-essays', $args ); } add_action( 'init', 'learndash_register_essay_post_type' ); /** * Essay post type capabilities * * Add essay capabilities to administrators and group leaders * * @since 2.2.0 */ function learndash_add_essay_caps() { $admin_role = get_role( 'administrator' ); if ( ( $admin_role ) && ( $admin_role instanceof WP_Role ) ) { $cap = $admin_role->has_cap( 'delete_others_essays' ); if ( empty( $cap ) ) { $admin_role->add_cap( 'edit_essays' ); $admin_role->add_cap( 'edit_others_essays' ); $admin_role->add_cap( 'publish_essays' ); $admin_role->add_cap( 'read_essays' ); $admin_role->add_cap( 'read_private_essays' ); $admin_role->add_cap( 'delete_essays' ); $admin_role->add_cap( 'edit_published_essays' ); $admin_role->add_cap( 'delete_others_essays' ); $admin_role->add_cap( 'delete_published_essays' ); } } $group_leader_role = get_role( 'group_leader' ); if ( ( $group_leader_role ) && ( $group_leader_role instanceof WP_Role ) ) { $group_leader_role->add_cap( 'edit_essays' ); $group_leader_role->add_cap( 'edit_others_essays' ); $group_leader_role->add_cap( 'publish_essays' ); $group_leader_role->add_cap( 'read_essays' ); $group_leader_role->add_cap( 'read_private_essays' ); $group_leader_role->add_cap( 'delete_essays' ); $group_leader_role->add_cap( 'edit_published_essays' ); $group_leader_role->add_cap( 'delete_others_essays' ); $group_leader_role->add_cap( 'delete_published_essays' ); } } add_action( 'admin_init', 'learndash_add_essay_caps' ); /** * Map meta capabilities * * @since 2.2.0 * * @param $caps * @param $cap * @param $user_id * @param $args * * @return array */ function learndash_map_metacap_essays( $caps, $cap, $user_id, $args = array() ) { if ( !is_string( $cap ) ) return $caps; /* If editing, deleting, or reading a essays, get the post and post type object. */ if ( 'edit_essay' == $cap || 'delete_essay' == $cap || 'read_essay' == $cap ) { // Ensure $args is valid if ( ( !is_array( $args ) ) || ( !isset( $args[0] ) ) ) { return $caps; } $post = get_post( $args[0] ); if ( ! is_a( $post, 'WP_Post' ) ) { return $caps; } $post_type = get_post_type_object( $post->post_type ); /* Set an empty array for the caps. */ $caps = array(); } /* If editing a essay, assign the required capability. */ if ( 'edit_essay' == $cap ) { if ( $user_id == $post->post_author ) { $caps[] = $post_type->cap->edit_posts; } else { $caps[] = $post_type->cap->edit_others_posts; } } /* If deleting a essay, assign the required capability. */ elseif ( 'delete_essay' == $cap ) { if ( $user_id == $post->post_author ) { $caps[] = $post_type->cap->delete_posts; } else { $caps[] = $post_type->cap->delete_others_posts; } } /* If reading a private essay, assign the required capability. */ elseif ( 'read_essay' == $cap ) { if ( 'private' != $post->post_status ) { $caps[] = 'read'; } elseif ( $user_id == $post->post_author ) { $caps[] = 'read'; } else { $caps[] = $post_type->cap->read_private_posts; } } /* Return the capabilities required by the user. */ return $caps; } add_filter( 'map_meta_cap', 'learndash_map_metacap_essays', 10, 4 ); /** * Create 'Graded' and 'Not Graded' post status * * @since 2.2.0 */ function learndash_register_essay_post_status() { register_post_status( 'graded', array( 'label' => esc_html_x( 'Graded', 'Custom Essay post type status: Graded', 'learndash' ), 'public' => true, 'exclude_from_search' => true, 'show_in_admin_all_list' => true, 'show_in_admin_status_list' => true, 'label_count' => _n_noop( 'Graded (%s)', 'Graded (%s)', 'learndash' ), ) ); register_post_status( 'not_graded', array( 'label' => esc_html_x( 'Not Graded', 'Custom Essay post type status: Not Graded', 'learndash' ), 'public' => true, 'exclude_from_search' => true, 'show_in_admin_all_list' => true, 'show_in_admin_status_list' => true, 'label_count' => _n_noop( 'Not Graded (%s)', 'Not Graded (%s)', 'learndash' ), ) ); } add_action( 'init', 'learndash_register_essay_post_status' ); /** * Only allow admins, group leaders, and essay owners to see assignment * * @since 2.1.0 */ function learndash_essay_permissions() { global $post; if ( ! empty( $post->post_type ) && $post->post_type == 'sfwd-essays' && is_singular() ) { $user_id = get_current_user_id(); $can_view_file = false; if ( ( learndash_is_admin_user( $user_id ) ) || ( $post->post_author == $user_id ) ) { $can_view_file = true; } else if ( ( learndash_is_group_leader_user( $user_id ) ) && ( learndash_is_group_leader_of_user( $user_id, $post->post_author ) ) ) { $can_view_file = true; } if ( $can_view_file == true ) { $uploaded_file = get_post_meta( $post->ID, 'upload', true ); if ( ( !empty( $uploaded_file ) ) && ( !strstr( $post->post_content, $uploaded_file ) ) ) { $post->post_content .= apply_filters( 'learndash-quiz-essay-upload-link', '

'. esc_html__('View uploaded file', 'learndash' ) .'

' ); } return; } else { wp_redirect( apply_filters('learndash_essay_permissions_redirect_url', get_bloginfo( 'url' ) ) ); exit; } } } add_action( 'wp', 'learndash_essay_permissions' ); //, 0, 3 ); /** * Add custom columns to the Essays post type * * @since 2.1.0 * * @param array $cols admin columns for post type * @return array $cols admin columns for post type */ function add_essays_data_columns( $cols ) { $cols_new = array(); foreach( $cols as $col_key => $col_label ) { if ($col_key == 'title') { $cols_new[$col_key] = esc_html__( 'Essay Question Title', 'learndash' ); } else if ($col_key == 'author') { $cols_new[$col_key] = esc_html__( 'Submitted By', 'learndash' ); // We add all out own columns after 'author' $cols_new['approval_status'] = esc_html__('Status', 'learndash' ); $cols_new['approval_points'] = esc_html__('Points', 'learndash' ); $cols_new['course'] = sprintf( esc_html_x( 'Assigned %s', 'Assigned Course Label', 'learndash' ), LearnDash_Custom_Label::get_label( 'course' ) ); $cols_new['lesson'] = sprintf( esc_html_x( 'Assigned %s', 'Assigned Lesson', 'learndash' ), LearnDash_Custom_Label::get_label( 'lesson' ) ); $cols_new['quiz'] = sprintf( esc_html_x( 'Assigned %s', 'Assigned Quiz', 'learndash' ), LearnDash_Custom_Label::get_label( 'quiz' ) ); } else { $cols_new[$col_key] = $col_label; } } return $cols_new; } /** * Populate Essay post type columns in the admin * * Columns are can be filtered by Quiz, Lesson, and Course * * @since 2.2.0 * * @param $column * @param $post_id */ function learndash_populate_essay_cpt_columns( $column, $post_id ) { $essay = get_post( $post_id ); switch ( $column ) { case 'approval_status': $post_status_object = get_post_status_object($essay->post_status); if ( ( !empty( $post_status_object ) ) && ( is_object( $post_status_object ) ) && ( property_exists( $post_status_object, 'label' ) ) ) { echo $post_status_object->label; } $essay = get_post( $post_id ); if ( $essay->post_status == 'not_graded' ) { ?>fetchById( intval( $question_id ), null ); if ( $question instanceof WpProQuiz_Model_Question ) { $submitted_essay_data = learndash_get_submitted_essay_data( $quiz_id, $question_id, $essay ); $max_points = $question->getPoints(); $current_points = 0; if ( isset( $submitted_essay_data['points_awarded'] ) ) $current_points = intval( $submitted_essay_data['points_awarded'] ); if ( $essay->post_status == 'not_graded' ) { $current_points = ''; echo sprintf( _x( '%1$s / %2$d', 'placeholders: input points / maximum point for essay', 'learndash' ), $current_points, $max_points ); } else { echo sprintf( esc_html_x( '%1$d / %2$d', 'placeholders: current awarded points / maximum point for essay', 'learndash'), $current_points, $max_points ); } } else { echo '-'; } } break; case 'quiz': $quiz_id = get_post_meta( $post_id, 'quiz_id', true ); if ( !empty( $quiz_id ) ) { $quiz_post_id = learndash_get_quiz_id_by_pro_quiz_id( $quiz_id ); if ( empty( $quiz_post_id ) ) { $quizMapper = new WpProQuiz_Model_QuizMapper(); $quiz = $quizMapper->fetch( $quiz_id ); if ( ( !empty( $quiz ) ) && ( $quiz instanceof WpProQuiz_Model_Quiz ) ) { $quiz_title = $quiz->getName(); echo $quiz_title; } else { echo '—'; } } else { $quiz_title = get_the_title( $quiz_post_id ); $edit_url = get_edit_post_link( intval( $quiz_post_id ) ); $filter_url = add_query_arg( array( 'post_type' => 'sfwd-essays', 'quiz_id' => $quiz_id ), admin_url( 'edit.php' ) ); $course_id = get_post_meta( $post_id, 'course_id', true ); if ( ! empty( $course_id ) ) { $edit_url = add_query_arg('course_id', $course_id, $edit_url ); $filter_url = add_query_arg('course_id', $course_id, $filter_url ); } $lesson_id = get_post_meta( $post_id, 'lesson_id', true ); if ( ! empty( $lesson_id ) ) { $edit_url = add_query_arg('lesson_id', $lesson_id, $edit_url ); $filter_url = add_query_arg('lesson_id', $lesson_id, $filter_url ); } //echo sprintf( '%s', $edit_url, $quiz_title ); echo ''. $quiz_title .''; $row_actions['edit'] = '' . esc_html__('edit', 'learndash' ) .''; $row_actions['filter_post'] = '' . esc_html__('filter', 'learndash' ) .''; echo learndash_list_table_row_actions( $row_actions ); } } break; case 'lesson': $quiz_post_id = get_post_meta( $post_id, 'quiz_post_id', true ); if ( !empty( $quiz_post_id ) ) $lesson_id = get_post_meta( $quiz_post_id, 'lesson_id', true ); else $lesson_id = get_post_meta( $post_id, 'lesson_id', true ); if ( !empty( $lesson_id ) ) { $lesson = get_post( $lesson_id ); if ( ( !empty( $lesson ) ) && ( $lesson instanceof WP_Post ) ) { $edit_url = get_edit_post_link( $lesson_id ); $filter_url = add_query_arg( array( 'post_type' => 'sfwd-essays', 'lesson_id' => $lesson_id ), admin_url( 'edit.php' ) ); if ( LearnDash_Settings_Section::get_section_setting('LearnDash_Settings_Courses_Builder', 'shared_steps' ) == 'yes' ) { $course_id = get_post_meta( $post_id, 'course_id', true ); if ( ! empty( $course_id ) ) { $edit_url = add_query_arg('course_id', $course_id, $edit_url ); $filter_url = add_query_arg('course_id', $course_id, $filter_url ); } } echo ''. get_the_title( $lesson_id ) .''; $row_actions['edit'] = '' . esc_html__('edit', 'learndash' ) .''; $row_actions['filter_post'] = '' . esc_html__('filter', 'learndash' ) .''; echo learndash_list_table_row_actions( $row_actions ); } } else { echo '—'; } break; case 'course': $quiz_post_id = get_post_meta( $post_id, 'quiz_post_id', true ); if ( !empty( $quiz_post_id ) ) $course_id = get_post_meta( $quiz_post_id, 'course_id', true ); else $course_id = get_post_meta( $post_id, 'course_id', true ); if ( !empty( $course_id ) ) { $edit_url = get_edit_post_link( $course_id ); $filter_url = add_query_arg( array( 'post_type' => 'sfwd-essays', 'course_id' => $course_id ), admin_url( 'edit.php' ) ); echo ''. get_the_title( $course_id ) .''; $row_actions['edit'] = '' . esc_html__('edit', 'learndash' ) .''; $row_actions['filter_post'] = '' . esc_html__('filter', 'learndash' ) .''; echo learndash_list_table_row_actions( $row_actions ); } else { echo '—'; } break; } } add_action( 'manage_sfwd-essays_posts_custom_column', 'learndash_populate_essay_cpt_columns', 10, 2 ); /** * Add 'Approve' next to certain selects on Essay edit screen in admin * * @todo check if needed, jQuery selector seems incorrect * * @since 2.3 */ function learndash_essay_bulk_actions() { global $post; if ( ! empty( $post->post_type ) && $post->post_type == 'sfwd-essays' ) { $approve_text = esc_html__('Approve', 'learndash'); ?> post_type == 'sfwd-essays' ) { $upload = get_post_meta( $post->ID, 'upload', true ); if ( ! empty( $upload ) ) { $actions['download_essay'] = '' . esc_html__( 'Download', 'learndash' ) . ''; } /* if ($post->post_status == 'not_graded') { $approve_link = ''; $actions['approve_essay'] = "" . esc_html__( 'Approve', 'learndash' ) . ''; } */ } return $actions; } add_filter( 'post_row_actions', 'learndash_essay_inline_actions', 10, 2 ); /** * Adjust Essay post type query in admin * * Essay query should only include essays with a 'graded' and 'not_graded' post status * * @since 2.2.0 * * @param $essay_query */ function learndash_modify_admin_essay_listing_query( $essay_query ) { if ( is_admin() && $essay_query->is_main_query() && 'sfwd-essays' == $essay_query->query['post_type'] && ( ( ! isset( $_GET['post_status'] ) ) || ( isset( $_GET['post_status'] ) && 'all' == $_GET['post_status'] ) ) ) { $essay_query->set( 'post_status', array( 'graded', 'not_graded' ) ); } } add_action( 'pre_get_posts', 'learndash_modify_admin_essay_listing_query' ); /** * Add a new essay response * * Called from LD_QuizPro::checkAnswers via AJAX * * @since 2.2.0 * * @param string $response * @param WpProQuiz_Model_Question $this_question * @param WpProQuiz_Model_Quiz $quiz * @param array $post_data * * @return bool|int|WP_Error */ function learndash_add_new_essay_response( $response, $this_question, $quiz, $post_data = null ) { if ( ! is_a( $this_question, 'WpProQuiz_Model_Question' ) || ! is_a ( $quiz, 'WpProQuiz_Model_Quiz' ) ) { return false; } $user = wp_get_current_user(); // essay args defaults $essay_args = array( 'post_title' => $this_question->getTitle(), 'post_status' => 'not_graded', 'post_type' => 'sfwd-essays', 'post_author' => $user->ID, ); $essay_data = $this_question->getAnswerData(); $essay_data = array_shift( $essay_data ); // switch on grading progression in order to set post status switch ( $essay_data->getGradingProgression() ) { case '': case 'not-graded-none': $essay_args['post_status'] = 'not_graded'; break; case 'not-graded-full': $essay_args['post_status'] = 'not_graded'; break; case 'graded-full' : $essay_args['post_status'] = 'graded'; break; } // switch on graded type to handle the response // used a switch in case we add more types switch( $essay_data->getGradedType() ) { case 'text' : $essay_args['post_content'] = wp_kses( $response, apply_filters('learndash_essay_new_allowed_html', wp_kses_allowed_html( 'post' ) ) ); break; case 'upload' : $essay_args['post_content'] = esc_html__( 'See upload below.', 'learndash' ); } /** * Filter a new essays arguments */ $essay_args = apply_filters( 'learndash_new_essay_submission_args', $essay_args ); $essay_id = wp_insert_post( $essay_args ); if ( ! empty( $essay_id ) ) { if ( ( isset( $post_data['quiz_id'] ) ) && ( ! empty( $post_data['quiz_id'] ) ) ) { $quiz_id = absint( $post_data['quiz_id'] ); } else { $quiz_id = learndash_get_quiz_id_by_pro_quiz_id( $this_question->getQuizId() ); } if ( isset( $post_data['course_id'] ) ) { $course_id = intval( $post_data['course_id'] ); if ( !empty( $course_id ) ) { $lesson_id = learndash_course_get_single_parent_step( $course_id, $quiz_id ); } else { $lesson_id = 0; } } else { $course_id = learndash_get_course_id( $quiz_id ); $lesson_id = learndash_get_lesson_id( $quiz_id ); } update_post_meta( $essay_id, 'question_id', $this_question->getId() ); update_post_meta( $essay_id, 'quiz_pro_id', $this_question->getQuizId() ); update_post_meta( $essay_id, 'quiz_id', $this_question->getQuizId() ); update_post_meta( $essay_id, 'course_id', $course_id ); update_post_meta( $essay_id, 'lesson_id', $lesson_id ); if ( 'upload' == $essay_data->getGradedType() ){ update_post_meta( $essay_id, 'upload', esc_url( $response ) ); } } do_action( 'learndash_new_essay_submitted', $essay_id, $essay_args ); return $essay_id; } /** * Remove the default submitdiv metabox from the Essay post type admin edit screen * * @since 2.2.0 */ function learndash_essays_remove_subbmitdiv_metabox() { remove_meta_box( 'submitdiv', 'sfwd-essays', 'side' ); } add_action( 'admin_menu', 'learndash_essays_remove_subbmitdiv_metabox' ); /** * Register Essay Upload metabox * * @since 2.2.0 */ function learndash_register_essay_upload_metabox() { add_meta_box( 'learndash_essay_upload_div', esc_html__( 'Essay Upload', 'learndash' ), 'learndash_essay_upload_meta_box', 'sfwd-essays', 'normal', 'high' ); // This is added here because we wanted the inline comments ability on the single edit post type form. But since // This post type uses custom post statuses the default logic in WP was failing. add_meta_box( 'commentsdiv', esc_html__( 'Comments', 'learndash' ), 'post_comment_meta_box', null, 'normal', 'core' ); } add_action( 'add_meta_boxes_sfwd-essays', 'learndash_register_essay_upload_metabox' ); /** * Display metabox for essay upload * * @since 2.2.0 * * @param WP_Post $essay */ function learndash_essay_upload_meta_box( $essay ) { $upload = get_post_meta( $essay->ID, 'upload', true ); if ( ! empty( $upload ) ) { echo sprintf( '%s', esc_url( $upload ) ); } else { esc_html_e( 'Upload was not provided for this question', 'learndash' ); } } /** * Register Essay Grading Response metabox * * @since 2.2.0 * * Used for when a grader wants to respond to a users submitted essay */ function learndash_register_essay_grading_response_metabox() { add_meta_box( 'learndash_essay_grading_response_div', esc_html__( 'Your Response to Submitted Essay (optional)', 'learndash' ), 'learndash_essay_grading_response_meta_box', 'sfwd-essays', 'normal', 'high' ); } //add_action( 'add_meta_boxes_sfwd-essays', 'learndash_register_essay_grading_response_metabox' ); /** * Display metabox for grading response * * @since 2.2.0 * * @param WP_Post $essay */ function learndash_essay_grading_response_meta_box( $essay ) { $grading_response = get_post_meta( $essay->ID, 'ld_essay_grading_response', true ); $grading_response = ( ! empty( $grading_response ) ) ? wp_kses( $grading_response, apply_filters('learndash_essay_grading_response_meta_box_allowed_html', wp_kses_allowed_html( 'post' ) ) ) : ''; $grading_response = apply_filters( 'learndash_grading_response', $grading_response ); ?> post_type; $post_type_object = get_post_type_object( $post_type ); $can_publish = current_user_can( $post_type_object->cap->publish_posts ); $quiz_id = get_post_meta( $essay->ID, 'quiz_id', true ); $question_id = get_post_meta( $essay->ID, 'question_id', true ); if ( ! empty( $quiz_id ) ) { $questionMapper = new WpProQuiz_Model_QuestionMapper(); $question = $questionMapper->fetchById( intval( $question_id ), null ); } if ( $question && is_a( $question, 'WpProQuiz_Model_Question' ) ) { $submitted_essay_data = learndash_get_submitted_essay_data( $quiz_id, $question->getId(), $essay ); } ?>
post_status || 'graded' == $essay->post_status || $can_publish ) : ?>

: getQuestion(); ?> getId() ); if ( ! empty( $question_post_id ) ) { $question_edit_url = get_edit_post_link( $question_post_id ); } } if ( empty( $question_edit_url ) ) { $question_edit_url = add_query_arg( array( 'page' => 'ldAdvQuiz', 'module' => 'question', 'action' => 'addEdit', 'quiz_id' => $quiz_id, 'questionId' => $question->getId(), ), admin_url( 'admin.php' ) ); } ?> ()

: getPoints(); ?>

:

ID, 'quiz_post_id', true ); if ( empty( $essay_quiz_post_id ) ) { $essay_quiz_query_args = array( 'post_type' => 'sfwd-quiz', 'post_status' => 'publish', 'meta_key' => 'quiz_pro_id_' . intval( $quiz_id ), 'meta_value' => intval( $quiz_id ), 'meta_compare' => '=', 'fields' => 'ids', 'orderby' => 'title', 'order' => 'ASC' ); $essay_quiz_query = new WP_Query( $essay_quiz_query_args ); if ( count( $essay_quiz_query->posts ) > 1 ) { ?>

:

posts[0]; } } if ( !empty( $essay_quiz_post_id ) ) { $essay_quiz_edit_link = get_edit_post_link( $essay_quiz_post_id ); ?>

: ()

: ()

: ()

ID ) : $stamp = wp_kses_post( __( 'Submitted on: %1$s', 'learndash' ) ); $date = date_i18n( $datef, strtotime( $essay->post_date ) ); endif; if ( $can_publish ) : // Contributors don't get to choose the date of publish ?>
ID ) ) : if ( ! EMPTY_TRASH_DAYS ) : $delete_text = esc_html__( 'Delete Permanently', 'learndash' ); else : $delete_text = esc_html__( 'Move to Trash', 'learndash' ); endif; ?>
post_author, '_sfwd-quizzes', true ); if ( ( !empty( $users_quiz_data ) ) && ( is_array( $users_quiz_data ) ) ) { if ( ( $essay ) && ( is_a( $essay, 'WP_Post' ) ) ) { $essay_quiz_time = get_post_meta( $essay->ID, 'quiz_time', true ); } else { $essay_quiz_time = null; } foreach ( $users_quiz_data as $quiz_data ) { // We check for a match on the quiz time from the essay postmeta first. // If the essay_quiz_time is not empty and does NOT match then continue; if ( ( absint( $essay_quiz_time ) ) && ( isset( $quiz_data['time'] ) ) && ( absint( $essay_quiz_time ) !== absint( $quiz_data['time'] ) ) ) { continue; } if (empty($quiz_data['pro_quizid']) || $quiz_id != $quiz_data['pro_quizid'] || ! isset( $quiz_data['has_graded'] ) || false == $quiz_data['has_graded'] ) { continue; } if ((isset($quiz_data['graded'])) && (!empty($quiz_data['graded']))) { foreach ( $quiz_data['graded'] as $key => $graded_question ) { if ( ( $key == $question_id ) && ( $essay->ID == $graded_question['post_id'] ) ) { return $quiz_data['graded'][ $key ]; } } } } } } /** * Update a users essay and quiz data on save post * * @since 2.2.0 * * @param int $essay_id * @param WP_Post $essay * @param bool $update */ function learndash_save_essay_status_metabox_data( $essay_id, $essay, $update ) { if ( ! isset( $_POST['question_id'] ) || empty( $_POST['question_id'] ) ) { return; } $quiz_id = intval( $_POST['quiz_id'] ); $question_id = intval( $_POST['question_id'] ); $submitted_essay = learndash_get_submitted_essay_data( $quiz_id, $question_id, $essay ); if ( ( isset( $_POST['essay_quiz_post_id'] ) ) && ( !empty( $_POST['essay_quiz_post_id'] ) ) ) { $essay_quiz_post_id = intval( $_POST['essay_quiz_post_id'] ); update_post_meta( $essay_id, 'quiz_post_id', $essay_quiz_post_id ); } $quiz_score_difference = 0; if ( isset( $_POST['post_status'] ) ) { if ( ( $_POST['post_status'] != $submitted_essay['status'] ) ) { if ( $_POST['post_status'] == 'graded' ) $quiz_score_difference = 1; else if ( $_POST['post_status'] == 'not_graded' ) $quiz_score_difference = -1; } } $submitted_essay['status'] = esc_html( $_POST['post_status'] ); $submitted_essay['points_awarded'] = intval( $_POST['points_awarded'] ); /** * Filter essay status data */ $submitted_essay = apply_filters( 'learndash_essay_status_data', $submitted_essay ); learndash_update_submitted_essay_data( $quiz_id, $question_id, $essay, $submitted_essay ); $original_points_awarded = isset( $_POST['original_points_awarded'] ) ? intval( $_POST['original_points_awarded'] ) : null; $points_awarded = isset( $_POST['points_awarded'] ) ? intval( $_POST['points_awarded'] ) : null; if ( ! is_null( $original_points_awarded ) && ! is_null( $points_awarded ) ) { if ( $points_awarded > $original_points_awarded ) { $points_awarded_difference = intval( $points_awarded ) - intval( $original_points_awarded ); } else { $points_awarded_difference = ( intval( $original_points_awarded ) - intval( $points_awarded ) ) * -1; } $updated_scoring = array( 'updated_question_score' => $points_awarded, 'points_awarded_difference' => $points_awarded_difference, 'score_difference' => $quiz_score_difference ); /** * Filter updated scoring data */ $updated_scoring = apply_filters( 'learndash_updated_essay_scoring', $updated_scoring ); learndash_update_quiz_data( $quiz_id, $question_id, $updated_scoring, $essay ); /** * Perform action after all the quiz data is updated */ do_action( 'learndash_essay_all_quiz_data_updated', $quiz_id, $question_id, $updated_scoring, $essay ); } } add_action( 'save_post_sfwd-essays', 'learndash_save_essay_status_metabox_data', 10, 3 ); /** * Updates a users submitted essay data * * Finds the essay in this particular quiz attempt in the users meta and updates its data * * @since 2.2.0 * * @param int $quiz_id * @param int $question_id * @param WP_Post $essay * @param array $submitted_essay */ function learndash_update_submitted_essay_data( $quiz_id, $question_id, $essay, $submitted_essay ) { $users_quiz_data = get_user_meta( $essay->post_author, '_sfwd-quizzes', true ); if ( ( $essay ) && ( is_a( $essay, 'WP_Post' ) ) ) { $essay_quiz_time = get_post_meta( $essay->ID, 'quiz_time', true ); } else { $essay_quiz_time = null; } $quizdata_changed = array(); foreach ( $users_quiz_data as $quiz_key => $quiz_data ) { // We check for a match on the quiz time from the essay postmeta first. // If the essay_quiz_time is not empty and does NOT match then continue; if ( ( absint( $essay_quiz_time ) ) && ( isset( $quiz_data['time'] ) ) && ( absint( $essay_quiz_time ) !== absint( $quiz_data['time'] ) ) ) { continue; } if ( $quiz_id != $quiz_data['pro_quizid'] || ! isset( $quiz_data['has_graded'] ) || false == $quiz_data['has_graded'] ) { continue; } foreach ( $quiz_data['graded'] as $question_key => $graded_question ) { if ( ( $question_key == $question_id ) && ( $essay->ID == $graded_question['post_id'] ) ) { $users_quiz_data[ $quiz_key ]['graded'][ $question_key ] = $submitted_essay; if ( ( isset( $submitted_essay['status'] ) ) && ( 'graded' === $submitted_essay['status'] ) ) { $quizdata_changed[] = $users_quiz_data[ $quiz_key ]; } } } } update_user_meta( $essay->post_author, '_sfwd-quizzes', $users_quiz_data ); /** * Perform action after essay response data is updated */ do_action( 'learndash_essay_response_data_updated', $quiz_id, $question_id, $essay, $submitted_essay ); } /** * Updates a users quiz data * * Finds this particular quiz attempt in the users meta and updates its data * * @since 2.2.0 * * @param int $quiz_id * @param int $question_id * @param array $updated_scoring * @param WP_Post $essay */ function learndash_update_quiz_data( $quiz_id, $question_id, $updated_scoring, $essay ) { $affected_quiz_keys = array(); $users_quiz_data = get_user_meta( $essay->post_author, '_sfwd-quizzes', true ); if ( ( $essay ) && ( is_a( $essay, 'WP_Post' ) ) ) { $essay_quiz_time = get_post_meta( $essay->ID, 'quiz_time', true ); } else { $essay_quiz_time = null; } // We need to find the user meta quiz to matches the essay being scored. foreach ( $users_quiz_data as $quiz_key => $quiz_data ) { // We check for a match on the quiz time from the essay postmeta first. // If the essay_quiz_time is not empty and does NOT match then continue; if ( ( absint( $essay_quiz_time ) ) && ( isset( $quiz_data['time'] ) ) && ( absint( $essay_quiz_time ) !== absint( $quiz_data['time'] ) ) ) { continue; } if ( ( $quiz_id != $quiz_data['pro_quizid'] ) || ( !isset( $quiz_data['has_graded'] ) ) || ( false == $quiz_data['has_graded'] ) ) continue; if ( ( !isset( $quiz_data['graded'][$question_id]['post_id'] ) ) || ( $quiz_data['graded'][$question_id]['post_id'] != $essay->ID ) ) continue; $affected_quiz_keys[] = $quiz_key; // update total score $users_quiz_data[ $quiz_key ]['score'] = $users_quiz_data[ $quiz_key ]['score'] + $updated_scoring['score_difference']; // update total points $users_quiz_data[ $quiz_key ]['points'] = $users_quiz_data[ $quiz_key ]['points'] + $updated_scoring['points_awarded_difference']; // update total score percentage $updated_percentage = ( $users_quiz_data[ $quiz_key ]['points'] / $users_quiz_data[ $quiz_key ]['total_points'] ) * 100; $users_quiz_data[ $quiz_key ]['percentage'] = round( $updated_percentage, 2 ); // update passing score $quizmeta = get_post_meta( $quiz_data['quiz'], '_sfwd-quiz', true ); $passingpercentage = intVal( $quizmeta['sfwd-quiz_passingpercentage'] ); $users_quiz_data[ $quiz_key ]['pass'] = ( $users_quiz_data[ $quiz_key ]['percentage'] >= $passingpercentage ) ? 1 : 0; learndash_update_quiz_statistics( $quiz_id, $question_id, $updated_scoring, $essay, $users_quiz_data[ $quiz_key ] ); learndash_update_quiz_activity( $essay->post_author, $users_quiz_data[ $quiz_key ] ); } update_user_meta( $essay->post_author, '_sfwd-quizzes', $users_quiz_data ); if ( !empty( $affected_quiz_keys ) ) { foreach( $affected_quiz_keys as $quiz_key ) { if ( isset( $users_quiz_data[ $quiz_key ] ) ) { $send_quiz_completed = true; if ( ( isset( $users_quiz_data[ $quiz_key ]['has_graded'] ) ) && ( true === $users_quiz_data[ $quiz_key ]['has_graded'] ) ) { if ( ( isset( $users_quiz_data[ $quiz_key ]['graded'] ) ) && ( ! empty( $users_quiz_data[ $quiz_key ]['graded'] ) ) ) { foreach ( $users_quiz_data[ $quiz_key ]['graded'] as $grade_item ) { if ( ( isset( $grade_item['status'] ) ) && ( $grade_item['status'] !== 'graded' ) ) { $send_quiz_completed = false; } } } } if ( true === $send_quiz_completed ) { if ( isset( $users_quiz_data[ $quiz_key ]['course'] ) ) $course_id = intval( $users_quiz_data[ $quiz_key ]['course'] ); else $course_id = learndash_get_course_id( $essay->ID ); learndash_process_mark_complete( $essay->post_author, $users_quiz_data[ $quiz_key ]['quiz'], false, $course_id ); do_action( 'learndash_quiz_completed', $users_quiz_data[ $quiz_key ], get_user_by( 'ID', $essay->post_author ) ); /* if ( ( isset( $users_quiz_data[ $quiz_key ]['topic'] ) ) && ( ! empty( $users_quiz_data[ $quiz_key ]['topic'] ) ) ) { learndash_process_mark_complete( $essay->post_author, absint( $users_quiz_data[ $quiz_key ]['topic'] ), false, $course_id ); } */ /* if ( ( isset( $users_quiz_data[ $quiz_key ]['lesson'] ) ) && ( ! empty( $users_quiz_data[ $quiz_key ]['lesson'] ) ) ) { learndash_process_mark_complete( $essay->post_author, absint( $users_quiz_data[ $quiz_key ]['lesson'] ), false, $course_id ); } */ } } } } /** * Perform action after essay quiz data is updated */ do_action( 'learndash_essay_quiz_data_updated', $quiz_id, $question_id, $updated_scoring, $essay ); } function learndash_update_quiz_activity( $user_id = 0, $quiz_data = array() ) { if ( ( !empty( $user_id ) ) && ( !empty( $quiz_data ) ) ) { $quiz_data_meta = $quiz_data; // Remove many fields that we either don't need or are duplicate of the main table columns unset($quiz_data_meta['quiz']); unset($quiz_data_meta['pro_quizid']); unset($quiz_data_meta['time']); unset($quiz_data_meta['completed']); unset($quiz_data_meta['started']); //unset($quiz_data_meta['graded']); if ($quiz_data_meta['rank'] == '-') unset($quiz_data_meta['rank']); if ( $quiz_data['pass'] == true ) $quiz_data_pass = true; else $quiz_data_pass = false; learndash_update_user_activity( array( 'course_id' => (isset( $quiz_data['course'] ) ) ? intval( $quiz_data['course'] ) : 0, 'post_id' => $quiz_data['quiz'], 'user_id' => $user_id, 'activity_type' => 'quiz', 'activity_status' => $quiz_data_pass, 'activity_started' => $quiz_data['started'], 'activity_completed' => $quiz_data['completed'], 'activity_meta' => $quiz_data_meta, ) ); } } /** * Update the quiz statistics for this quiz attempt * * Updates the score when the essay grading is adjusted, I ran this through manual SQL queries * because WpProQuiz doesn't offer an elegant way to grab a particular question and update it. * * @since 2.2.0 * * @param int $quiz_id * @param int $question_id * @param array $updated_quiz_data * @param WP_Post $essay */ function learndash_update_quiz_statistics( $quiz_id, $question_id, $updated_quiz_data, $essay, $users_quiz_data ) { global $wpdb; if ( ( isset( $users_quiz_data['statistic_ref_id'] ) ) && ( ! empty( $users_quiz_data['statistic_ref_id'] ) ) ) { $refId = absint( $users_quiz_data['statistic_ref_id'] ); } else { $refId = $wpdb->get_var( $wpdb->prepare(" SELECT statistic_ref_id FROM ". LDLMS_DB::get_table_name( 'quiz_statistic_ref' ) ." WHERE quiz_id = %d AND user_id = %d ", $quiz_id, $essay->post_author) ); $refId = absint( $refId ); } $row = $wpdb->get_results( $wpdb->prepare(" SELECT * FROM ". LDLMS_DB::get_table_name( 'quiz_statistic' ) ." WHERE statistic_ref_id = %d AND question_id = %d ", $refId, $question_id) ); if ( empty( $row ) ) { return; } if ( $updated_quiz_data['updated_question_score'] > 0 ) { $correct_count = 1; $incorrect_count = 0; } else { $correct_count = 0; $incorrect_count = 1; } $update = $wpdb->update( LDLMS_DB::get_table_name( 'quiz_statistic' ), array( 'correct_count' => $correct_count, 'incorrect_count' => $incorrect_count, 'points' => $updated_quiz_data['updated_question_score'], ), array( 'statistic_ref_id' => $refId, 'question_id' => $question_id, ), array( '%d', '%d', '%d' ), array( '%d', '%d' ) ); do_action( 'learndash_essay_question_stats_updated' ); } /** * Restrict assignment listings view to group leader only * * @since 2.2.0 * * @param object $query WP_Query * @return object $query WP_Query */ function learndash_restrict_essay_listings_for_group_admins( $query ) { global $pagenow, $typenow; if ( !is_admin() ) return; if ( $pagenow != 'edit.php' ) return; if ( !$query->is_main_query() ) return; if ( empty( $typenow ) ) return; if ( $typenow != 'sfwd-essays' ) return; $q_vars = & $query->query_vars; $user_id = get_current_user_id(); if ( learndash_is_group_leader_user( $user_id ) ) { $group_ids = learndash_get_administrators_group_ids( $user_id ); $course_ids = array(); $user_ids = array(); if ( ! empty( $group_ids ) && is_array( $group_ids ) ) { foreach( $group_ids as $group_id ) { $group_course_ids = learndash_group_enrolled_courses( $group_id ); if ( ! empty( $group_course_ids ) && is_array( $group_course_ids ) ) { $course_ids = array_merge( $course_ids, $group_course_ids ); } $group_users = learndash_get_groups_user_ids( $group_id ); if ( ! empty( $group_users ) && is_array( $group_users ) ) { foreach( $group_users as $group_user_id ) { $user_ids[ $group_user_id ] = $group_user_id; } } } } if ( ! empty( $course_ids ) && count( $course_ids ) ) { if (!isset( $q_vars['meta_query'] ) ) $q_vars['meta_query'] = array(); $q_vars['meta_query'][] = array( 'key' => 'course_id', 'value' => $course_ids, 'compare' => 'IN', ); } if ( ! empty( $user_ids ) && count( $user_ids ) ) { $q_vars['author__in'] = $user_ids; } else { $q_vars['author__in'] = - 2; } } } add_filter( 'parse_query', 'learndash_restrict_essay_listings_for_group_admins' ); /** * AJAX callback for Uploading a file for an essay quesiton * * @since 2.2.0 * * Runs checks for needing information, or will die and send an error back to browser */ function learndash_upload_essay() { if ( ! isset( $_POST['nonce'] ) || ! isset( $_POST['question_id'] ) || ! isset( $_FILES['essayUpload'] ) ) { wp_send_json_error(); die(); } $nonce = $_POST['nonce']; $question_id = intval( $_POST['question_id'] ); if ( empty( $question_id ) ) { wp_send_json_error(); die(); } /** * Changes in v2.5.4 to include the question_id as part of the nonce */ if ( ! wp_verify_nonce( $nonce, 'learndash-upload-essay-'. $question_id ) ) { wp_send_json_error(); die( 'Security check' ); } else { if ( !is_user_logged_in() ) { if ( !apply_filters('learndash_essay_upload_user_check', false, $question_id ) ) { wp_send_json_error(); die(); } } $file_desc = learndash_essay_fileupload_process( $_FILES['essayUpload'], $question_id ); if ( ! empty( $file_desc ) ) { wp_send_json_success( $file_desc ); } else { wp_send_json_error(); } die(); } } add_action( 'wp_ajax_learndash_upload_essay', 'learndash_upload_essay' ); add_action( 'wp_ajax_nopriv_learndash_upload_essay', 'learndash_upload_essay' ); /** * Upload files for essays * * @since 2.2.0 * * @param array $uploadfiles * @param int $question_id * * @return array file description * @internal param int $post_id assignment id */ function learndash_essay_fileupload_process( $uploadfiles, $question_id ) { if ( is_array( $uploadfiles ) ) { // look only for uploded files if ( $uploadfiles['error'] == 0 ) { $filetmp = $uploadfiles['tmp_name']; //clean filename $filename = learndash_clean_filename( $uploadfiles['name'] ); //extract extension if ( ! function_exists( 'wp_get_current_user' ) ) { include ABSPATH . 'wp-includes/pluggable.php'; } //current user $user = get_current_user_id(); // get file info // @fixme: wp checks the file extension.... $filetype = wp_check_filetype( basename( $filename ), null ); if ( ( empty( $filetype ) ) || ( empty( $filetype['ext'] ) ) || ( empty( $filetype['type'] ) ) ) { wp_send_json_error( esc_html__( 'Invalid essay uploaded file type.', 'learndash' ) ); die(); } //$filetitle = preg_replace( '/\.[^.]+$/', '', basename( $filename ) ); $filetitle = pathinfo( $filename, PATHINFO_FILENAME ); $filename = sprintf( 'question_%d_%s.%s', $question_id, $filetitle, $filetype['ext'] ); $filename = apply_filters( 'learndash_essay_upload_filename', $filename, $question_id, $filetitle, $filetype['ext'] ); $upload_dir = wp_upload_dir(); $upload_dir_base = str_replace( '\\', '/', $upload_dir['basedir'] ); $upload_url_base = $upload_dir['baseurl']; $upload_dir_path = $upload_dir_base . apply_filters( 'learndash_essay_upload_dirbase', '/essays', $filename, $upload_dir ); $upload_url_path = $upload_url_base . apply_filters( 'learndash_essay_upload_urlbase', '/essays/', $filename, $upload_dir ); if ( ! file_exists( $upload_dir_path ) ) { if ( is_writable( dirname( $upload_dir_path ) ) ) { wp_mkdir_p( $upload_dir_path ); } else { die( esc_html__( 'Unable to write to UPLOADS directory. Is this directory writable by the server?', 'learndash' ) ); return; } } // Add an index.php file to prevent directory browesing $_index = trailingslashit( $upload_dir_path ) . 'index.php'; if ( !file_exists( $_index ) ) { file_put_contents ( $_index , '//LearnDash is THE Best LMS' ); } /** * Check if the filename already exist in the directory and rename the * file if necessary */ $i = 0; while ( file_exists( $upload_dir_path . '/' . $filename ) ) { $i++; $filename = sprintf( 'question_%d_%s_%d.%s', $question_id, $filetitle, $i, $filetype['ext'] ); $filename = apply_filters( 'learndash_essay_upload_filename_dup', $filename, $question_id, $filetitle, $i, $filetype['ext'] ); } $filedest = $upload_dir_path . '/' . $filename; $destination = $upload_url_path . $filename; /** * Check write permissions */ if ( ! is_writeable( $upload_dir_path ) ) { wp_send_json_error( esc_html__( 'Unable to write to directory. Is this directory writable by the server?', 'learndash' ) ); die(); } /** * Save temporary file to uploads dir */ if ( ! @move_uploaded_file( $filetmp, $filedest ) ) { wp_send_json_error( "Error, the file $filetmp could not moved to : $filedest " ); die(); } $file_desc = array(); $file_desc['filename'] = $filename; $file_desc['filelink'] = $destination; return $file_desc; } } } /** * Handle approval of essay in bulk * * @since 2.3 */ function learndash_essay_bulk_actions_approve() { if ( ( ( isset( $_REQUEST['post'] ) ) && ( ! empty( $_REQUEST['post'] ) ) && (is_array( $_REQUEST['post'] ) ) ) && ( ( isset( $_REQUEST['post_type'] ) ) && ( $_REQUEST['post_type'] == 'sfwd-essays' ) ) ) { $action = ''; if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] ) $action = esc_attr( $_REQUEST['action'] ); else if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] ) $action = esc_attr( $_REQUEST['action2'] ); else if ( ( isset( $_REQUEST['ld_action'] ) ) && ( $_REQUEST['ld_action'] == 'approve_essay') ) $action = 'approve_essay'; if ( $action == 'approve_essay' ) { if ( ( isset( $_REQUEST['post'] ) ) && ( !empty( $_REQUEST['post'] ) ) ) { if ( !is_array( $_REQUEST['post'] ) ) $essays = array($_REQUEST['post']); else $essays = $_REQUEST['post']; foreach( $essays as $essay_id ) { if ( ( !isset( $_REQUEST['essay_points'][$essay_id] ) ) || ( $_REQUEST['essay_points'][$essay_id] == '' ) ) continue; // get the new assigned points. $submitted_essay['points_awarded'] = intval( $_REQUEST['essay_points'][$essay_id] ); $essay_post = get_post( $essay_id ); if ( ( !empty( $essay_post ) ) && ( $essay_post instanceof WP_Post ) && ( $essay_post->post_type == 'sfwd-essays' ) ) { if ( $essay_post->post_status != 'graded' ) $quiz_score_difference = 1; // First we update the essat post with the new post_status $essay_post->post_status = 'graded'; wp_update_post( $essay_post ); $user_id = $essay_post->post_author; $quiz_id = get_post_meta( $essay_post->ID, 'quiz_id', true ); $question_id = get_post_meta( $essay_post->ID, 'question_id', true ); // Stole the following section ot code from learndash_save_essay_status_metabox_data(); $submitted_essay_data = learndash_get_submitted_essay_data( $quiz_id, $question_id, $essay_post ); if ( isset( $submitted_essay_data['points_awarded'] ) ) $original_points_awarded = intval( $submitted_essay_data['points_awarded'] ); else $original_points_awarded = 0; $submitted_essay_data['status'] = 'graded'; // get the new assigned points. $submitted_essay_data['points_awarded'] = intval( $_REQUEST['essay_points'][$essay_id] ); /** * Filter essay status data */ $submitted_essay_data = apply_filters( 'learndash_essay_status_data', $submitted_essay_data ); learndash_update_submitted_essay_data( $quiz_id, $question_id, $essay_post, $submitted_essay_data ); if ( ! is_null( $original_points_awarded ) && ! is_null( $submitted_essay_data['points_awarded'] ) ) { if ( $submitted_essay_data['points_awarded'] > $original_points_awarded ) { $points_awarded_difference = intval( $submitted_essay_data['points_awarded'] ) - intval( $original_points_awarded ); } else { $points_awarded_difference = ( intval( $original_points_awarded ) - intval( $submitted_essay_data['points_awarded'] ) ) * -1; } $updated_scoring_data = array( 'updated_question_score' => $submitted_essay_data['points_awarded'], 'points_awarded_difference' => $points_awarded_difference, 'score_difference' => $quiz_score_difference ); /** * Filter updated scoring data */ $updated_scoring = apply_filters( 'learndash_updated_essay_scoring', $updated_scoring_data ); learndash_update_quiz_data( $quiz_id, $question_id, $updated_scoring_data, $essay_post ); /** * Perform action after all the quiz data is updated */ do_action( 'learndash_essay_all_quiz_data_updated', $quiz_id, $question_id, $updated_scoring_data, $essay_post ); } } } } } } } add_action( 'load-edit.php', 'learndash_essay_bulk_actions_approve' ); /** * Delete uploaded file when essay post is deleted * * @since 2.5.0 * * @param int $post_id */ function learndash_before_delete_essay( $post_id ) { if ( ( !empty( $post_id ) ) && ( 'sfwd-essays' == get_post_type( $post_id ) ) ) { $file_path = get_post_meta( $post_id, 'upload', true ); if ( !empty( $file_path ) ) { $file_path = basename( $file_path ); $url_link_arr = wp_upload_dir(); $file_path = trailingslashit( str_replace('\\', '/', $url_link_arr['basedir'] ) ) . 'essays/' . basename( $file_path ); if ( file_exists( $file_path ) ) { unlink( $file_path ); } } } } add_action( 'before_delete_post', 'learndash_before_delete_essay' ); /** * Update the Essays post meta with a reference to the quiz attempt user meta. * * @since 3.1 * @param array $quizdata Collection of quiz attempt data. * @param object $user WP User object. */ function learndash_quiz_submitted_update_essay( $quizdata = array(), $user ) { if ( ( isset( $quizdata['time'] ) ) && ( ! empty( $quizdata['time'] ) ) ) { if ( ( isset( $quizdata['has_graded'] ) ) && ( true === $quizdata['has_graded'] ) ) { if ( ( isset( $quizdata['graded'] ) ) && ( ! empty( $quizdata['graded'] ) ) ) { foreach( $quizdata['graded'] as $question_id => $graded_data ) { if ( isset( $graded_data['post_id'] ) ) { $essay_post_id = absint( $graded_data['post_id'] ); if ( ! empty( $essay_post_id ) ) { $quiz_time = get_post_meta( $essay_post_id, 'quiz_time', true ); if ( ! $quiz_time ) { update_post_meta( $essay_post_id, 'quiz_time', $quizdata['time'] ); } } } } } } } } add_action( 'learndash_quiz_submitted', 'learndash_quiz_submitted_update_essay', 1, 2 );ld-quiz-metaboxes.php000066600000002515152142404260010636 0ustar00id ) { return; } add_meta_box( 'sfwd-quiz-questions', sprintf( '%s', \LearnDash_Custom_Label::get_label( 'questions' ) ), 'LearnDash\Quiz\Metaboxes\meta_box_questions_callback', null, 'side' ); /* add_meta_box( 'learndash_admin_quiz_navigation', sprintf( // translators: placeholders: Quiz, Questions. esc_html_x( '%1$s %2$s', 'placeholders: Quiz, Questions', 'learndash' ), \LearnDash_Custom_Label::get_label( 'quiz' ), \LearnDash_Custom_Label::get_label( 'questions' ) ), 'learndash_quiz_navigation_admin_box_content', null, 'side' ); */ } add_action( 'add_meta_boxes_sfwd-quiz', 'LearnDash\Quiz\Metaboxes\add_meta_boxes' ); add_action( 'learndash_add_meta_boxes', 'LearnDash\Quiz\Metaboxes\add_meta_boxes' ); /** * Callback to render questions metabox. * * @return void */ function meta_box_questions_callback() { ?>
$shortcode_atts ) { if ( in_array( $shortcode_tag, array('LDAdvQuiz', 'ld_quiz' ) ) ) { if ( ( isset( $shortcode_atts['quiz_post_id'] ) ) && ( ! empty( $shortcode_atts['quiz_post_id'] ) ) ) { $quiz_post_ids[ $quiz_pro_id ] = absint( $shortcode_atts['quiz_post_id'] ); return $quiz_post_ids[ $quiz_pro_id ]; } elseif ( ( isset( $shortcode_atts['quiz_id'] ) ) && ( ! empty( $shortcode_atts['quiz_id'] ) ) ) { $quiz_post_ids[ $quiz_pro_id ] = absint( $shortcode_atts['quiz_id'] ); return $quiz_post_ids[ $quiz_pro_id ]; } elseif ( ( isset( $shortcode_atts['quiz'] ) ) && ( ! empty( $shortcode_atts['quiz'] ) ) ) { $quiz_post_ids[ $quiz_pro_id ] = absint( $shortcode_atts['quiz'] ); return $quiz_post_ids[ $quiz_pro_id ]; } } } } // Before we run all the queries we check the global $post and see if we are showing a Quiz Post. $queried_object = get_queried_object(); if ( ( is_a( $queried_object, 'WP_Post' ) ) && ( learndash_get_post_type_slug( 'quiz' ) === $queried_object->post_type ) ) { $quiz_post_ids[ $quiz_pro_id ] = absint( $queried_object->ID ); return $quiz_post_ids[ $quiz_pro_id ]; } /* $post_id = get_the_ID(); if ( ! empty( $post_id ) ) { $quiz_post = get_post( $post_id ); if ( ( $quiz_post instanceof WP_Post ) && ( $quiz_post->post_type == 'sfwd-quiz' ) ) { //$quiz_post_id = $quiz_post->ID; $quiz_pro_id_tmp = learndash_get_setting( $quiz_post->ID, 'quiz_pro' ); if ( ( $quiz_pro_id_tmp ) && ( absint( $quiz_pro_id_tmp ) === $quiz_pro_id ) ) { $quiz_post_ids[ $quiz_pro_id ] = absint( $quiz_pro_id_tmp ); return $quiz_post_ids[ $quiz_pro_id ]; } } } */ $sql_str = $wpdb->prepare( "SELECT post_id FROM " . $wpdb->postmeta . " as postmeta INNER JOIN " . $wpdb->posts . " as posts ON posts.ID=postmeta.post_id WHERE posts.post_type = %s AND posts.post_status = %s AND postmeta.meta_key = %s", 'sfwd-quiz', 'publish', 'quiz_pro_id_' . absint( $quiz_pro_id ) ); $quiz_post_id = $wpdb->get_var( $sql_str ); if ( ! empty( $quiz_post_id ) ) { $quiz_post_ids[ $quiz_pro_id ] = absint( $quiz_post_id ); return $quiz_post_ids[ $quiz_pro_id ]; } $sql_str = $wpdb->prepare( "SELECT post_id FROM " . $wpdb->postmeta . " as postmeta INNER JOIN " . $wpdb->posts . " as posts ON posts.ID=postmeta.post_id WHERE posts.post_type = %s AND posts.post_status = %s AND meta_key = %s AND meta_value = %d", 'sfwd-quiz', 'publish', 'quiz_pro_id', absint( $quiz_pro_id )); $quiz_post_id = $wpdb->get_var( $sql_str ); if ( ! empty( $quiz_post_id ) ) { update_post_meta( absint( $quiz_post_id ), 'quiz_pro_id_' . absint( $quiz_pro_id ), absint( $quiz_pro_id ) ); $quiz_post_ids[ $quiz_pro_id ] = absint( $quiz_post_id ); return $quiz_post_ids[ $quiz_pro_id ]; } // Because we seem to have a mix of int and string values when these are serialized the format to look for end up being somewhat kludge-y. $quiz_pro_id_str = sprintf( '%s', absint( $quiz_pro_id ) ); $quiz_pro_id_len = strlen( $quiz_pro_id_str ); $like_i = 'sfwd-quiz_quiz_pro";i:' . absint( $quiz_pro_id ) . ';'; $like_s = '"sfwd-quiz_quiz_pro";s:' . $quiz_pro_id_len . ':"' . $quiz_pro_id_str . '"'; // Using REGEX because it is slightly faster then OR on text fields pattern search. $sql_str = $wpdb->prepare( "SELECT post_id FROM " . $wpdb->postmeta . " as postmeta INNER JOIN " . $wpdb->posts . " as posts ON posts.ID=postmeta.post_id WHERE posts.post_type = %s AND posts.post_status = %s AND postmeta.meta_key=%s AND postmeta.meta_value REGEXP '" . $like_i . "|" . $like_s . "'", 'sfwd-quiz', 'publish', '_sfwd-quiz' ); $quiz_post_id = $wpdb->get_var( $sql_str ); if ( ! empty( $quiz_post_id ) ) { $quiz_post_id = absint( $quiz_post_id ); update_post_meta( $quiz_post_id, 'quiz_pro_id_' . absint( $quiz_pro_id ), absint( $quiz_pro_id ) ); update_post_meta( $quiz_post_id, 'quiz_pro_id', absint( $quiz_pro_id ) ); $quiz_post_ids[ $quiz_pro_id ] = $quiz_post_id; return $quiz_post_ids[ $quiz_pro_id ]; } } } /** * Get a Question Post ID from the Proquiz ID * * @since 2.6.0 * * @param int $question_pro_id ProQuiz Question id. * @return int quiz post id */ function learndash_get_question_post_by_pro_id( $question_pro_id = 0 ) { global $wpdb; if ( empty( $question_pro_id ) ) { return; } $question_pro_args = array( 'post_type' => learndash_get_post_type_slug( 'question' ), 'posts_per_page' => 1, 'post_status' => 'any', 'fields' => 'ids', 'meta_query' => array( array( 'key' => 'question_pro_id', 'value' => $question_pro_id, 'compare' => '=', 'type' => 'NUMERIC', ), ), ); $question_pro_query = new WP_Query( $question_pro_args ); if ( ( is_a( $question_pro_query, 'WP_Query' ) ) && ( property_exists( $question_pro_query, 'posts' ) ) ) { if ( ( ! empty( $question_pro_query->posts ) ) && ( isset( $question_pro_query->posts[0] ) ) ) { return $question_pro_query->posts[0]; } } } /** * Action hook called when a Question (sfwd-question) is moved to trash or untrashed. * * @since 2.6.0 * * @param string $new_status New post_status value. * @param string $old_status Old post_status value. * @param Object $post WP_Post object instance. */ function learndash_transition_quiz_question_post_status( $new_status, $old_status, $post ) { global $wpdb; if ( $new_status !== $old_status ) { if ( ( ! empty( $post ) ) && ( is_a( $post, 'WP_Post' ) ) && ( in_array( $post->post_type, array( 'sfwd-question' ) ) ) === true ) { $sql_str = "SELECT meta_value FROM " . $wpdb->postmeta . " WHERE post_id = " . $post->ID . " AND (meta_key = 'quiz_id' OR meta_key LIKE 'ld_quiz_%')"; $quiz_ids = $wpdb->get_col( $sql_str ); if ( ! empty( $quiz_ids ) ) { $quiz_ids = array_unique( $quiz_ids ); foreach ( $quiz_ids as $quiz_id ) { learndash_set_quiz_questions_dirty( $quiz_id ); } } } } } add_action( 'transition_post_status', 'learndash_transition_quiz_question_post_status', 10, 3 ); /** * Interface function to set the Quiz 'dirty' flag for questions. * This 'dirty' flag is used to trigger the Quiz logic to relod the questions * via queries instead of using the stored questions post meta. This generally * means something changed with the questions. * * @since 2.6.0 * @param integer $quiz_id Quiz ID to change dirty flag. */ function learndash_set_quiz_questions_dirty( $quiz_id = 0 ) { if ( ! empty( $quiz_id ) ) { $quiz_questions_object = LDLMS_Factory_Post::quiz_questions( absint( $quiz_id ) ); if ( is_a( $quiz_questions_object, 'LDLMS_Quiz_Questions' ) ) { $quiz_questions_object->set_questions_dirty(); } } } /** * For a given Question post gather all the quiz posts and set each as * questions dirty. * * @since 2.6.0 * @param integer $question_post_id Question Post ID. */ function learndash_set_question_quizzes_dirty( $question_post_id = 0 ) { $question_post_id = absint( $question_post_id ); if ( ! empty( $question_post_id ) ) { $question_quiz_ids = learndash_get_quizzes_for_question( $question_post_id, true ); if ( ! empty( $question_quiz_ids ) ) { foreach ( $question_quiz_ids as $question_quiz_id => $quiz_title ) { learndash_set_quiz_questions_dirty( $question_quiz_id ); } } } } /** * Adds a WPProQuiz question to mirror a Question post (sfwd-question). * * @since 2.6.0 * @param integer $question_pro_id Post ID of Question (sfwd-question). * @param array $post_data Post Data containing post_title and post_content. * @return integer new question pro id. */ function learndash_update_pro_question( $question_pro_id = 0, $post_data = array() ) { $question_pro_id = absint( $question_pro_id ); $question_mapper = new WpProQuiz_Model_QuestionMapper(); if ( isset( $post_data['action'] ) ) { switch ( $post_data['action'] ) { case 'editpost': $proquiz_controller_question = new WpProQuiz_Controller_Question(); $question_model = $proquiz_controller_question->getPostQuestionModel( 0, $question_pro_id ); break; case 'new_step': $proquiz_controller_question = new WpProQuiz_Controller_Question(); $question_model = $proquiz_controller_question->getPostQuestionModel( 0, $question_pro_id ); break; case 'edit_title': $question_model = $question_mapper->fetchById( absint( $question_pro_id ) ); break; default: break; } } if ( ( isset( $question_model ) ) && ( is_a( $question_model, 'WpProQuiz_Model_Question' ) ) ) { if ( ( isset( $post_data['post_type'] ) ) && ( $post_data['post_type'] === learndash_get_post_type_slug( 'question' ) ) ) { if ( isset( $post_data['post_title'] ) ) { $question_model->setTitle( $post_data['post_title'] ); } if ( isset( $post_data['post_content'] ) ) { $question_model->setQuestion( $post_data['post_content'] ); } if ( ( isset( $post_data['post_ID'] ) ) && ( ! empty( $post_data['post_ID'] ) ) ) { $quiz_post_id = learndash_get_setting( $post_data['post_ID'], 'quiz' ); if ( ! empty( $quiz_post_id ) ) { $quiz_post_id = absint( $quiz_post_id ); $quiz_pro_id = learndash_get_setting( $quiz_post_id, 'quiz_pro' ); if ( ! empty( $quiz_pro_id ) ) { $question_model->setQuizId( $quiz_pro_id ); } } } } $question = $question_mapper->save( $question_model, true ); learndash_update_question_template( $question, $post_data ); // After the save we check the question ID in case WPProQuiz changed it. $question_pro_id = $question->getId(); return $question_pro_id; } } /** * Handle the Question Save Template logic. * * @since 2.6.0 * @param object $question WpProQuiz_Model_Question instance. * @param array $post_data $_POST data to process the templated related fields. * @return mixed on success WpProQuiz_Model_Template instance. */ function learndash_update_question_template( $question = null, $post_data = array() ) { if ( ( ! empty( $post_data ) ) && ( ! empty( $question ) ) ) { $template_mapper = new WpProQuiz_Model_TemplateMapper(); if ( ( isset( $post_data['templateName'] ) ) && ( ! empty( $post_data['templateName'] ) ) ) { $template = new WpProQuiz_Model_Template(); $template->setType( WpProQuiz_Model_Template::TEMPLATE_TYPE_QUESTION ); $template->setName( trim( $post_data['templateName'] ) ); } else if ( ( isset( $post_data['templateSaveList'] ) ) && ( ! empty( $post_data['templateSaveList'] ) ) ) { $template = $template_mapper->fetchById( absint( $post_data['templateSaveList'] ), false ); } if ( ( isset( $template ) ) && ( is_a( $template, 'WpProQuiz_Model_Template' ) ) ) { $template->setData( array( 'question' => $question, ) ); return $template_mapper->save( $template ); } } } /** * Gets an array of Quiz IDS where the question is used. * * @since 2.6.0 * @param integer $question_post_id Question Post ID. * @param boolean $return_flat_array Default is false and will return primary and secondary sub-array sets. * @return array of Quiz post IDs. */ function learndash_get_quizzes_for_question( $question_post_id = 0, $return_flat_array = false ) { global $wpdb; $quiz_ids = array(); if ( true !== $return_flat_array ) { $course_ids['primary'] = array(); $course_ids['secondary'] = array(); } if ( ! empty( $question_post_id ) ) { $sql_str = $wpdb->prepare( "SELECT postmeta.meta_value as quiz_id, posts.post_title as quiz_title FROM " . $wpdb->postmeta . " AS postmeta INNER JOIN " . $wpdb->posts . " AS posts ON postmeta.meta_value = posts.ID WHERE postmeta.post_id = " . $question_post_id . " AND postmeta.meta_key LIKE %s ORDER BY quiz_title ASC", 'quiz_id' ); $quiz_ids_primary = $wpdb->get_results( $sql_str ); if ( ! empty( $quiz_ids_primary ) ) { foreach ( $quiz_ids_primary as $quiz_set ) { if ( true === $return_flat_array ) { $quiz_ids[ $quiz_set->quiz_id ] = $quiz_set->quiz_title; } else { $quiz_ids['primary'][ $quiz_set->quiz_id ] = $quiz_set->quiz_title; } } } $sql_str = "SELECT postmeta.meta_value as quiz_id, posts.post_title as quiz_title FROM " . $wpdb->postmeta . " AS postmeta INNER JOIN " . $wpdb->posts . " AS posts ON postmeta.meta_value = posts.ID WHERE postmeta.post_id = " . $question_post_id . " AND postmeta.meta_key LIKE 'ld_quiz_%' ORDER BY quiz_title ASC" ; $quiz_ids_secondary = $wpdb->get_results( $sql_str ); if ( ! empty( $quiz_ids_secondary ) ) { foreach ( $quiz_ids_secondary as $quiz_set ) { if ( true === $return_flat_array ) { if ( ! isset( $quiz_ids[ $quiz_set->quiz_id ] ) ) { $quiz_ids[ $quiz_set->quiz_id ] = $quiz_set->quiz_title; } } else { if ( ( ! isset( $quiz_ids['primary'][ $quiz_set->quiz_id ] ) ) && ( ! isset( $quiz_ids['secondary'][ $quiz_set->quiz_id ] ) ) ) { $quiz_ids['secondary'][ $quiz_set->quiz_id ] = $quiz_set->quiz_title; } } } } return $quiz_ids; } } /** * Determine the Quiz ID based on the global post being viewed. * * @since 2.6.0 * @param integer $id Post ID being viewed. * @return integer The found quiz ID or false. */ function learndash_get_quiz_id( $id = null ) { global $post; if ( is_object( $id ) && $id->ID ) { $p = $id; $id = $p->ID; } elseif ( is_numeric( $id ) ) { $p = get_post( $id ); } if ( empty( $id ) ) { if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { //return false; } else { if ( is_admin() ) { global $parent_file, $post_type, $pagenow; if ( ( ! in_array( $pagenow, array( 'post.php', 'post-new.php' ) ) ) || ( ! in_array( $post_type, array( 'sfwd-question' ) ) ) ) { return false; } } else if ( ! is_single() || is_home() ) { return false; } } if ( ( $post ) && ( $post instanceof WP_Post ) ) { $id = $post->ID; $p = $post; } else { return false; } } if ( empty( $p->ID ) ) { return 0; } if ( learndash_get_post_type_slug( 'quiz' ) === $p->post_type ) { return $p->ID; } if ( ( isset( $_GET['quiz_id'] ) ) && ( ! empty( $_GET['quiz_id'] ) ) ) { return absint( $_GET['quiz_id'] ); } elseif ( ( isset( $_GET['quiz'] ) ) && ( ! empty( $_GET['quiz'] ) ) ) { return absint( $_GET['quiz'] ); } elseif ( ( isset( $_POST['quiz_id'] ) ) && ( ! empty( $_POST['quiz_id'] ) ) ) { return absint( $_POST['quiz_id'] ); } else if ( ( isset( $_POST['quiz'] ) ) && ( ! empty( $_POST['quiz'] ) ) ) { return intval( $_POST['quiz'] ); } else if ( ( isset( $_GET['post'] ) ) && ( ! empty( $_GET['post'] ) ) ) { if ( learndash_get_post_type_slug( 'quiz' ) === get_post_type( intval( $_GET['post'] ) ) ) { return intval( $_GET['post'] ); } } return (int) get_post_meta( $id, 'quiz_id', true ); } /** * Add content to quiz navigation meta box for admin * * @since 2.6.0 */ function learndash_quiz_navigation_admin_box_content() { global $typenow; $quiz_id = 0; $current_post = false; if ( ( isset( $_GET['post'] ) ) && ( ! empty( $_GET['post'] ) ) ) { $quiz_id = learndash_get_quiz_id( absint( $_GET['post'] ) ); $current_post = get_post( intval( $_GET['post'] ) ); } if ( ( empty( $quiz_id ) ) && ( isset( $_GET['quiz_id'] ) ) ) { $quiz_id = absint( $_GET['quiz_id'] ); } if ( ! empty( $quiz_id ) ) { $instance = array(); $instance['show_widget_wrapper'] = true; $instance['quiz_id'] = $quiz_id; $instance['current_question_id'] = 0; $instance['current_type'] = $typenow; $question_query_args = array(); $question_query_args['pagination'] = 'true'; $question_query_args['paged'] = 1; if ( ( is_a( $current_post, 'WP_Post' ) ) && ( in_array( $current_post->post_type, array( 'sfwd-quiz', 'sfwd-question' ) ) ) ) { if ( in_array( $current_post->post_type, array( 'sfwd-question' ) ) ) { $instance['current_question_id'] = $current_post->ID; } } learndash_quiz_navigation_admin( $quiz_id, $instance, $question_query_args ); if ( LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Quizzes_Builder', 'shared_questions' ) == 'yes' ) { learndash_quiz_switcher_admin( $quiz_id ); } } else { echo sprintf( // translators: placeholders: Questions. esc_html_x( 'No associated %s', 'placeholder: Questions', 'learndash' ), LearnDash_Custom_Label::get_label( 'questions' ) ); echo sprintf( '
', esc_attr( $quiz_id ) ); } } /** * Utility function to get the questions associated with a Quiz * * @since 2.6.0 * @param integer $quiz_id The Quiz Post ID. * @return array of quiz question (sfwd-question) post ids. */ function learndash_get_quiz_questions( $quiz_id = 0 ) { if ( ! empty( $quiz_id ) ) { $ld_quiz_questions_object = LDLMS_Factory_Post::quiz_questions( absint( $quiz_id ) ); if ( $ld_quiz_questions_object ) { $ld_quiz_questions = $ld_quiz_questions_object->get_questions(); return $ld_quiz_questions; } } } /** * Outputs quiz navigation admin template for widget * * @since 2.6.0 * * @param integer $quiz_id Quiz Post ID. * @param array $instance Widget instance array. * @param array $question_query_args array of query options for pagnination etc. * * @return string quiz navigation output */ function learndash_quiz_navigation_admin( $quiz_id = 0, $instance = array(), $question_query_args = array() ) { if ( empty( $quiz_id ) ) { return; } $quiz = get_post( absint( $quiz_id ) ); if ( ( ! $quiz ) || ( ! is_a( $quiz, 'WP_Post' ) ) || ( learndash_get_post_type_slug( 'quiz' ) !== $quiz->post_type ) ) { return; } if ( is_user_logged_in() ) { $user_id = get_current_user_id(); } else { $user_id = 0; } $instance['nonce'] = wp_create_nonce( 'ld_quiz_navigation_admin_pager_nonce_' . $quiz->ID . '_' . get_current_user_id() ); $quiz_navigation_admin_pager = array(); global $quiz_navigation_admin_pager; $question_start_idx = 0; $question_list = learndash_get_quiz_questions( $quiz_id ); if ( ! empty( $question_list ) ) { //$course_lessons_per_page = learndash_get_course_lessons_per_page( $quiz_id ); $quiz_questions_per_page = LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Section_General_Per_Page', 'question_num' ); if ( ( $quiz_questions_per_page > 0 ) && ( count( $question_list ) > $quiz_questions_per_page ) ) { $quiz_navigation_admin_pager['per_page'] = absint( $quiz_questions_per_page ); $quiz_navigation_admin_pager['total_items'] = count( $question_list ); $questions_page_chunks = array_chunk( $question_list, $quiz_navigation_admin_pager['per_page'], true ); $quiz_navigation_admin_pager['total_pages'] = count( $questions_page_chunks ); $quiz_navigation_admin_pager['paged'] = 1; if ( ( isset( $_POST['paged'] ) ) && ( ! empty( $_POST['paged'] ) ) ) { $quiz_navigation_admin_pager['paged'] = absint( $_POST['paged'] ); } else { foreach( $questions_page_chunks as $paged_idx => $paged_set ) { if ( isset( $paged_set[ $instance['current_question_id'] ] ) ) { $quiz_navigation_admin_pager['paged'] = $paged_idx + 1; break; } } } $chunks_paged = $quiz_navigation_admin_pager['paged'] - 1; if ( isset( $questions_page_chunks[ $chunks_paged ] ) ) { $question_list = $questions_page_chunks[ $chunks_paged ]; } else { $question_list = $questions_page_chunks[0]; } } } else { echo sprintf( // translators: placeholders: Questions. esc_html_x( 'No associated %s', 'placeholder: Questions', 'learndash' ), LearnDash_Custom_Label::get_label( 'questions' ) ); } SFWD_LMS::get_template( 'quiz_navigation_admin', array( 'user_id' => $user_id, 'quiz_id' => $quiz_id, 'widget' => $instance, 'questions_list' => $question_list, ), true ); } /** * Show the Quiz Switcher within the Quiz Questions Admin metabox. * * @since 2.6.0 * @param integer $quiz_id Quiz Post ID. */ function learndash_quiz_switcher_admin( $quiz_id ) { $template_file = SFWD_LMS::get_template( 'quiz_navigation_switcher_admin', array(), null, true ); if ( ! empty( $template_file ) ) { include $template_file; } } /** * Quiz Questions Navigation AJAX Pager handler function * * @since 2.5.4 */ function learndash_wp_ajax_ld_quiz_navigation_admin_pager() { $reply_data = array(); if ( ( isset( $_POST['paged'] ) ) && ( ! empty( $_POST['paged'] ) ) ) { $paged = intval( $_POST['paged'] ); } else { $paged = 1; } if ( ( isset( $_POST['widget_data'] ) ) && ( ! empty( $_POST['widget_data'] ) ) ) { $widget_data = $_POST['widget_data']; } else { $widget_data = array(); } if ( ( isset( $widget_data['quiz_id'] ) ) && ( ! empty( $widget_data['quiz_id'] ) ) ) { $quiz_id = intval( $widget_data['quiz_id'] ); } else { $quiz_id = 0; } if ( ( ! empty( $quiz_id ) ) && ( ! empty( $widget_data ) ) ) { if ( ( isset( $_POST['widget_data']['nonce'] ) ) && ( ! empty( $_POST['widget_data']['nonce'] ) ) && ( wp_verify_nonce( $_POST['widget_data']['nonce'], 'ld_quiz_navigation_admin_pager_nonce_' . $quiz_id . '_' . get_current_user_id() ) ) ) { $questions_query_args = array(); //$course_lessons_per_page = learndash_get_course_lessons_per_page( $course_id ); //if ( $course_lessons_per_page > 0 ) { $questions_query_args['pagination'] = 'true'; $questions_query_args['paged'] = $paged; //} $widget_data['show_widget_wrapper'] = false; $level = ob_get_level(); ob_start(); learndash_quiz_navigation_admin( $quiz_id, $widget_data, $questions_query_args ); $reply_data['content'] = learndash_ob_get_clean( $level ); } } echo json_encode( $reply_data ); die(); } add_action( 'wp_ajax_ld_quiz_navigation_admin_pager', 'learndash_wp_ajax_ld_quiz_navigation_admin_pager' ); /** * This function will copy the WPProQuiz Question Category to the LearnDadh Question taxonomy * * @since 2.6.0 * @param integer $question_post_id WP_Post Question ID. * @param integer $question_pro_id WpProQuiz_Model_Question object or ID. */ function learndash_proquiz_sync_question_fields( $question_post_id = 0, $question_pro_id = 0 ) { if ( ( empty( $question_post_id ) ) || ( empty( $question_pro_id ) ) ) { return; } if ( is_a( $question_pro_id, 'WpProQuiz_Model_Question' ) ) { $question_pro = $question_pro_id; } else { $question_pro_mapper = new WpProQuiz_Model_QuestionMapper(); $question_pro = $question_pro_mapper->fetch( absint( $question_pro_id ) ); } if ( is_a( $question_pro, 'WpProQuiz_Model_Question' ) ) { update_post_meta( $question_post_id, 'question_points', intval( $question_pro->getPoints() ) ); update_post_meta( $question_post_id, 'question_type', $question_pro->getAnswerType() ); update_post_meta( $question_post_id, 'question_pro_id', intval( $question_pro->getId() ) ); update_post_meta( $question_post_id, 'question_pro_category', intval( $question_pro->getCategoryId() ) ); // Not sure why this is here. /* $update_post = array( 'ID' => $question_post_id, 'post_title' => $question_pro->getTitle(), 'post_content' => $question_pro->getQuestion(), 'menu_order' => absint( $question_pro->getSort() ), ); wp_update_post( $update_post ); */ /* $quiz_post_ids = learndash_get_quiz_post_ids( $question_pro->getQuizId() ); if ( ! empty( $quiz_post_ids ) ) { foreach ( $quiz_post_ids as $idx => $quiz_post_id ) { if ( 0 === $idx ) { learndash_update_setting( $question_post_id, 'quiz', absint( $quiz_post_id ) ); } //if ( LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Quizzes_Builder', 'shared_questions' ) === 'yes' ) { add_post_meta( $question_post_id, 'ld_quiz_id', intval( $quiz_post_id ), true ); //} } } */ } } /** * This function will copy the WPProQuiz Question Category to the LearnDadh Question taxonomy * * @since 2.6.0 * @param integer $question_post_id WP_Post Question ID. * @param integer $question_pro_id WpProQuiz_Model_Question object or ID. * @return object WP_Term object. */ function learndash_proquiz_sync_question_category( $question_post_id = 0, $question_pro_id = 0 ) { if ( ( empty( $question_post_id ) ) || ( empty( $question_pro_id ) ) ) { return; } if ( is_a( $question_pro_id, 'WpProQuiz_Model_Question' ) ) { $question_pro = $question_pro_id; } else { $question_pro_mapper = new WpProQuiz_Model_QuestionMapper(); $question_pro = $question_pro_mapper->fetch( absint( $question_pro_id ) ); } if ( is_a( $question_pro, 'WpProQuiz_Model_Question' ) ) { // Sync the Question category with the LD Question Category. if ( LearnDash_Settings_Section::get_section_setting( 'LearnDash_Settings_Questions_Taxonomies', 'ld_question_category' ) == 'yes' ) { $question_pro_category_id = $question_pro->getCategoryId(); $question_pro_category_name = $question_pro->getCategoryName(); if ( ( ! empty( $question_pro_category_id ) ) && ( ! empty( $question_pro_category_name ) ) ) { $category_query_args = array( 'taxonomy' => array( 'ld_question_category' ), 'hide_empty' => false, 'name' => $question_pro_category_name, ); $category_terms = get_terms( $category_query_args ); if ( ! is_wp_error( $category_terms ) ) { if ( ! empty( $category_terms ) ) { foreach ( $category_terms as $category_term ) { wp_set_object_terms( $question_post_id, $category_term->term_id, 'ld_question_category' ); } return $category_terms; } else { $new_term = wp_insert_term( $question_pro_category_name, 'ld_question_category' ); if ( isset( $new_term['term_id'] ) ) { add_term_meta( absint( $new_term['term_id'] ), 'category_pro_id', $question_pro_category_id ); wp_set_object_terms( $question_post_id, intval( $new_term['term_id'] ), 'ld_question_category' ); return $new_term; } } } } } } } /** * Utility function to return all the quiz posts IDs based on the quiz pro id. * This is similar to the function learndash_get_quiz_id_by_pro_quiz_id() but returns * an array instead of a single post ID. * * @since 2.6.0 * @param integer $quiz_pro_id ID of WPProQuiz Quiz. * @return array of quiz post IDs. */ function learndash_get_quiz_post_ids( $quiz_pro_id = 0 ) { static $quiz_post_ids = array(); $quiz_pro_id = absint( $quiz_pro_id ); if ( ! empty( $quiz_pro_id ) ) { if ( ! isset( $quiz_post_ids[ $quiz_pro_id ] ) ) { $quiz_post_ids[ $quiz_pro_id ] = array(); if ( ! empty( $quiz_pro_id ) ) { $quiz_query_args = array( 'post_type' => learndash_get_post_type_slug( 'quiz' ), 'posts_per_page' => -1, 'fields' => 'ids', 'orderby' => 'ID', 'order' => 'ASC', 'meta_query' => array( array( 'key' => 'quiz_pro_id', 'value' => absint( $quiz_pro_id ), 'compare' => '=', ), ), ); $quiz_query = new WP_Query( $quiz_query_args ); if ( ( $quiz_query instanceof WP_Query ) && ( property_exists( $quiz_query, 'posts' ) ) ) { $quiz_post_ids[ $quiz_pro_id ] = array_merge( $quiz_post_ids[ $quiz_pro_id ], $quiz_query->posts ); } } } return $quiz_post_ids[ $quiz_pro_id ]; } } /** * This function retreives the WPProQuiz Question row column by field. * * @since 2.6.0 * @param integer $question_pro_id WPProQuiz Question ID. * @param mixed $fields Array or string of fields to return. * @return array of field values. */ function leandash_get_question_pro_fields( $question_pro_id = 0, $fields = null ) { $values = array(); if ( ( ! empty( $question_pro_id ) ) && ( ! empty( $fields ) ) ) { if ( is_string( $fields ) ) { $fields = explode( ',', $fields ); } if ( is_array( $fields ) ) { $fields = array_map( 'trim', $fields ); } $question_mapper = new WpProQuiz_Model_QuestionMapper(); $question_pro = $question_mapper->fetch( $question_pro_id ); foreach ( $fields as $field ) { $function = 'get' . str_replace( ' ', '', ucwords( str_replace( '_', ' ', $field ) ) ); if ( method_exists( $question_pro, $function ) ) { $values[ $field ] = $question_pro->$function(); } else { $values[ $field ] = null; } } return $values; } return $values; } /** * This function retreives the WPProQuiz Quiz row column by field. * * @since 2.6.0 * @param integer $question_pro_id WPProQuiz Question ID. * @param mixed $fields Array or string of fields to return. * @return array of field values. */ function leandash_get_quiz_pro_fields( $quiz_pro_id = 0, $fields = null ) { $values = array(); if ( ( ! empty( $quiz_pro_id ) ) && ( ! empty( $fields ) ) ) { if ( is_string( $fields ) ) { $fields = explode( ',', $fields ); } if ( is_array( $fields ) ) { $fields = array_map( 'trim', $fields ); } $quiz_mapper = new WpProQuiz_Model_QuizMapper(); $quiz_pro = $quiz_mapper->fetch( $quiz_pro_id ); foreach ( $fields as $field ) { $function = 'get' . str_replace( ' ', '', ucwords( str_replace( '_', ' ', $field ) ) ); if ( method_exists( $quiz_pro, $function ) ) { $values[ $field ] = $quiz_pro->$function(); } else { $values[ $field ] = null; } } return $values; } return $values; } /** * This function accepts a list of Quiz posts. It is assumed quiz posts * all share the same ProQuiz Quiz ID. This function will determine which * is the 'primary' quiz post. If one is not found the first in the array * will be set as the primary. * * @since 2.6.0 * @param integer $quiz_pro_id ProQuiz Quiz ID. * @param boolean $set_first If true will take first quiz post fount and use as primary. * @return integer Primary Quiz Post ID. */ function learndash_get_quiz_primary_shared( $quiz_pro_id = 0, $set_first = true ) { static $quiz_primary_post_ids = array(); $quiz_pro_id = absint( $quiz_pro_id ); if ( ! empty( $quiz_pro_id ) ) { if ( ( ! isset( $quiz_primary_post_ids[ $quiz_pro_id ] ) ) || ( empty( $quiz_primary_post_ids[ $quiz_pro_id ] ) ) ) { $quiz_primary_post_ids[ $quiz_pro_id ] = 0; $quiz_post_ids = learndash_get_quiz_post_ids( $quiz_pro_id ); if ( ! empty( $quiz_post_ids ) ) { $quiz_query_args = array( 'post_type' => learndash_get_post_type_slug( 'quiz' ), 'posts_per_page' => -1, 'fields' => 'ids', 'orderby' => 'ID', 'order' => 'ASC', 'post__in' => $quiz_post_ids, 'meta_query' => array( array( 'key' => 'quiz_pro_primary_' . $quiz_pro_id, 'compare' => 'EXISTS', ), ), ); $quiz_query = new WP_Query( $quiz_query_args ); if ( ( is_a( $quiz_query, 'WP_Query' ) ) && ( property_exists( $quiz_query, 'posts' ) ) && ( ! empty( $quiz_query->posts ) ) ) { $quiz_primary_post_ids[ $quiz_pro_id ] = $quiz_query->posts[0]; if ( count( $quiz_query->posts ) > 1 ) { foreach ( $quiz_query->posts as $quiz_post_idx => $quiz_post_id ) { if ( 0 !== $quiz_post_idx ) { delete_post_meta( $quiz_post_id, 'quiz_pro_primary_' . $quiz_pro_id ); } } } } else { if ( true === $set_first ) { $quiz_primary_post_ids[ $quiz_pro_id ] = $quiz_post_ids[0]; update_post_meta( $quiz_primary_post_ids[ $quiz_pro_id ], 'quiz_pro_primary_' . $quiz_pro_id, $quiz_pro_id ); } } } } return $quiz_primary_post_ids[ $quiz_pro_id ]; } } function learndash_quiz_result_message_sort( $messages = array() ) { $sorted = array(); if ( ( isset( $messages ) ) && ( ! empty( $messages ) ) ) { $activ_bypass = false; if ( ! isset( $messages['activ'] ) ) { $activ_bypass = true; } for ( $i = 0; $i < LEARNDASH_QUIZ_RESULT_MESSAGE_MAX; $i++ ) { if ( true === $activ_bypass ) { $activ = 1; } else { $activ = null; if ( isset( $messages['activ'][$i] ) ) { $activ = absint( $messages['activ'][$i] ); } } $prozent = null; if ( isset( $messages['prozent'][$i] ) ) { $prozent = (float)str_replace(',', '.', $messages['prozent'][$i] ); } $text = null; if ( isset( $messages['text'][$i] ) ) { $text = $messages['text'][$i]; if ( ! empty( $text ) ) { $text = wp_check_invalid_utf8( $text ); if ( ! empty( $text ) ) { $text = sanitize_post_field( 'post_content', $text, 0, 'display' ); $text = stripslashes( $text ); } } else { $activ = null; } } if ( ( ! is_null( $activ ) ) && ( ! empty( $activ ) ) && ( ! is_null( $prozent ) ) && ( ! is_null( $text ) ) ) { if ( ! isset( $sorted[ $prozent ] ) ) { $sorted[ $prozent ] = array( 'prozent' => $prozent, 'activ' => $activ, 'text' => $text, ); } } } } if ( ! isset( $sorted[0] ) ) { $sorted[0] = array( 'prozent' => 0, 'activ' => 1, 'text' => '', ); } $result = array(); if ( ! empty( $sorted ) ) { ksort( $sorted ); foreach ( $sorted as $item ) { $result['text'][] = $item['text']; $result['prozent'][] = $item['prozent']; $result['activ'][] = $item['activ']; } } return $result; }partials/attempt.php000066600000007151152142407630010566 0ustar00post_title ) ? $quiz_attempt['post']->post_title : @$quiz_attempt['quiz_title']; $quiz_link = ! empty( $quiz_attempt['post']->ID ) ? learndash_get_step_permalink( intval( $quiz_attempt['post']->ID ), $course_id ) : '#'; /** * Only display the quiz if we've found a title * * @var [string] $quiz_title */ if ( ! empty( $quiz_title ) ) : ?>
ID, '_viewProfileStatistics', true ), $user_id, $quiz_attempt, basename( __FILE__ ) ) ) : ?>
ID ); if ( ! empty( $quiz_essays ) ) : foreach ( $quiz_essays as $essay ) : SFWD_LMS::get_template( 'quiz/partials/essay-row.php', array( 'essay' => $essay, 'context' => $context, ) ); endforeach; endif; ?>
partials/row.php000066600000004310152142407630007711 0ustar00ID, $course_id, $user_id ); ?> ID, $course_id, $user_id ); listing.php000066600000005650152142407630006744 0ustar00
*/ ?>
$quiz, 'course_id' => $course_id, 'user_id' => $user_id, 'context' => $context, ), true ); endforeach; ?>