Home / Disable / WPForms Quiz — Save results as Entry Note
Duplicate Snippet

Embed Snippet on Your Site

WPForms Quiz — Save results as Entry Note

This PHP snippet lets you save quiz results in Entry Notes

Ralden Souza PRO
<10
Code Preview
php
<?php
/**
 * WPForms Quiz — Save results as Entry Note
 * Supports all three quiz types: graded, personality, weighted
 *
 * Set $target_form_id = 0 to run on ALL quiz forms.
 */
add_action( 'wpforms_process_entry_saved', function( $fields, $entry, $form_data, $entry_id, $payment_id ) {
    // ── 1. Guard: target form(s) — set to 0 for all quiz forms ──────────────
    $target_form_id = 0; // 0 = all quiz forms
    if ( $target_form_id !== 0 && ( empty( $form_data['id'] ) || (int) $form_data['id'] !== $target_form_id ) ) {
        return;
    }
    // ── 2. Guard: only quiz forms ────────────────────────────────────────────
    if ( empty( $form_data['settings']['quiz']['enabled'] ) || $form_data['settings']['quiz']['enabled'] !== '1' ) {
        return;
    }
    // ── 3. entry_id is the 4th parameter directly ────────────────────────────
    $entry_id  = (int) $entry_id;
    $quiz_type = $form_data['settings']['quiz']['type'] ?? '';
    if ( ! $entry_id || ! $quiz_type ) {
        return;
    }
    // ── 4. Resolve a valid user_id for the note ──────────────────────────────
    $user_id = get_current_user_id();
    if ( ! $user_id ) {
        $admins  = get_users( [ 'role' => 'administrator', 'number' => 1, 'fields' => 'ID' ] );
        $user_id = ! empty( $admins ) ? (int) $admins[0] : 1;
    }
    // ── 5. Build note content based on quiz type ─────────────────────────────
    $note_content = '';
    if ( $quiz_type === 'graded' ) {
        $note_content = wpforms_quiz_note_graded( $fields, $form_data );
    } elseif ( $quiz_type === 'personality' ) {
        $note_content = wpforms_quiz_note_personality( $fields, $form_data, $entry_id );
    } elseif ( $quiz_type === 'weighted' ) {
        $note_content = wpforms_quiz_note_weighted( $fields, $form_data, $entry_id );
    }
    if ( ! $note_content ) {
        error_log( '[QUIZ NOTE] No note content for quiz_type=' . $quiz_type . ' entry_id=' . $entry_id );
        return;
    }
    // ── 6. Save as entry note ────────────────────────────────────────────────
    $entry_meta = wpforms()->obj( 'entry_meta' );
    if ( ! $entry_meta ) {
        error_log( '[QUIZ NOTE] entry_meta object not available.' );
        return;
    }
    $meta_id = $entry_meta->add(
        [
            'entry_id' => $entry_id,
            'form_id'  => (int) $form_data['id'],
            'user_id'  => $user_id,
            'type'     => 'note',
            'data'     => $note_content,
        ],
        'entry_meta'
    );
    if ( $meta_id ) {
        error_log( '[QUIZ NOTE] Saved — form_id=' . $form_data['id'] . ' | entry_id=' . $entry_id . ' | quiz_type=' . $quiz_type );
    } else {
        error_log( '[QUIZ NOTE] Failed to save note for entry_id=' . $entry_id );
    }
}, 20, 5 );
/**
 * Build note content for Graded quizzes.
 *
 * Calculates score from field quiz_result = 'correct' / 'incorrect'.
 * Resolves grade from form_data grading scale.
 *
 * @param array $fields    Entry fields.
 * @param array $form_data Form data.
 * @return string
 */
function wpforms_quiz_note_graded( array $fields, array $form_data ): string {
    $correct   = 0;
    $incorrect = 0;
    $total     = 0;
    foreach ( $fields as $field ) {
        if ( empty( $field['quiz_result'] ) || ! is_string( $field['quiz_result'] ) ) {
            continue;
        }
        $total++;
        if ( $field['quiz_result'] === 'correct' ) {
            $correct++;
        } else {
            $incorrect++;
        }
    }
    $percentage  = $total > 0 ? (int) round( ( $correct / $total ) * 100 ) : 0;
    $grade       = 'N/A';
    $grade_scale = $form_data['settings']['quiz']['grades'] ?? [];
    foreach ( $grade_scale as $row ) {
        if ( $percentage >= (int) $row['min'] && $percentage <= (int) $row['max'] ) {
            $grade = $row['grade'];
            break;
        }
    }
    return wpautop( sprintf(
        "Quiz Results (Graded)\n" .
        "Score: %d%% — Grade: %s\n" .
        "Correct: %d / %d — Incorrect: %d",
        $percentage,
        $grade,
        $correct,
        $total,
        $incorrect
    ) );
}
/**
 * Build note content for Personality quizzes.
 *
 * Reads the personality type from entry_meta quiz_outcome (already saved at
 * this hook's priority 20). Also counts votes per personality from field
 * quiz_result = [[personality_index]] to show the breakdown.
 *
 * @param array  $fields    Entry fields.
 * @param array  $form_data Form data.
 * @param int    $entry_id  Entry ID.
 * @return string
 */
function wpforms_quiz_note_personality( array $fields, array $form_data, int $entry_id ): string {
    // Read the winning personality type from entry_meta.
    $meta           = wpforms()->obj( 'entry_meta' )->get_meta( [
        'entry_id' => $entry_id,
        'type'     => 'quiz_outcome',
    ] );
    $personality_type = isset( $meta[0]->data ) ? sanitize_text_field( $meta[0]->data ) : 'N/A';
    // Count votes per personality from field quiz_result.
    // Structure: quiz_result = [[personality_index]] (0-based index into personalities array).
    $personalities = $form_data['settings']['quiz']['personalities'] ?? [];
    $vote_counts   = [];
    foreach ( $fields as $field ) {
        if ( empty( $field['quiz_result'] ) || ! is_array( $field['quiz_result'] ) ) {
            continue;
        }
        // quiz_result = [ 0 => [ 0 => personality_index ] ]
        $personality_index = $field['quiz_result'][0][0] ?? null;
        if ( $personality_index === null ) {
            continue;
        }
        $label = $personalities[ $personality_index ] ?? 'Personality ' . ( $personality_index + 1 );
        if ( ! isset( $vote_counts[ $label ] ) ) {
            $vote_counts[ $label ] = 0;
        }
        $vote_counts[ $label ]++;
    }
    // Build breakdown string.
    $breakdown = '';
    if ( ! empty( $vote_counts ) ) {
        arsort( $vote_counts );
        $parts = [];
        foreach ( $vote_counts as $label => $count ) {
            $parts[] = $label . ': ' . $count;
        }
        $breakdown = "\nBreakdown: " . implode( ' — ', $parts );
    }
    return wpautop( sprintf(
        "Quiz Results (Personality)\n" .
        "Result: %s%s",
        $personality_type,
        $breakdown
    ) );
}
/**
 * Build note content for Weighted quizzes.
 *
 * Reads the total weight percentage from entry_meta quiz_outcome.
 * Also calculates raw total weight from field quiz_result values
 * to show the actual score alongside the percentage.
 *
 * @param array  $fields    Entry fields.
 * @param array  $form_data Form data.
 * @param int    $entry_id  Entry ID.
 * @return string
 */
function wpforms_quiz_note_weighted( array $fields, array $form_data, int $entry_id ): string {
    // Read the percentage from entry_meta (e.g. '66.67').
    $meta       = wpforms()->obj( 'entry_meta' )->get_meta( [
        'entry_id' => $entry_id,
        'type'     => 'quiz_outcome',
    ] );
    $percentage = isset( $meta[0]->data ) ? (float) $meta[0]->data : 0.0;
    // Calculate total weight and max possible weight from field quiz_result.
    // Structure: quiz_result = [ 0 => weight_value ] (numeric weight of chosen option).
    $total_weight = 0;
    $max_weight   = 0;
    $question_count = 0;
    foreach ( $fields as $field ) {
        if ( empty( $field['quiz_result'] ) || ! is_array( $field['quiz_result'] ) ) {
            continue;
        }
        // quiz_result = [ 0 => chosen_weight ]
        $chosen_weight = (int) ( $field['quiz_result'][0] ?? 0 );
        $total_weight += $chosen_weight;
        $question_count++;
        // Determine max possible weight for this field from form_data choices.
        $field_id      = $field['id'] ?? null;
        $field_choices = $field_id !== null ? ( $form_data['fields'][ $field_id ]['choices'] ?? [] ) : [];
        $field_max     = 0;
        foreach ( $field_choices as $choice ) {
            $weight    = isset( $choice['value'] ) ? (int) $choice['value'] : 0;
            $field_max = max( $field_max, $weight );
        }
        $max_weight += $field_max;
    }
    $max_display = $max_weight > 0 ? ' / ' . $max_weight : '';
    return wpautop( sprintf(
        "Quiz Results (Weighted)\n" .
        "Score: %.2f%%\n" .
        "Total Weight: %d%s — Questions: %d",
        $percentage,
        $total_weight,
        $max_display,
        $question_count
    ) );
}

Comments

Add a Comment