From 4f136b32222989e5155d69e897f2bd05e9ff0e6b Mon Sep 17 00:00:00 2001 From: Ruben Ramirez Date: Thu, 3 Apr 2025 22:07:16 -0500 Subject: [PATCH] feat: Add Assessment Builder AJAX handler and initialization --- quiztech-assessment-platform.php | 3 + .../Ajax/AssessmentBuilderAjaxHandler.php | 151 ++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 src/Includes/Ajax/AssessmentBuilderAjaxHandler.php diff --git a/quiztech-assessment-platform.php b/quiztech-assessment-platform.php index 2d0dc68..9f3565e 100644 --- a/quiztech-assessment-platform.php +++ b/quiztech-assessment-platform.php @@ -190,6 +190,9 @@ function quiztech_init() { // Initialize AJAX handler for assessment interactions \Quiztech\AssessmentPlatform\Includes\Ajax\AssessmentAjaxHandler::init(); + // Initialize AJAX handler for assessment builder interactions + new \Quiztech\AssessmentPlatform\Includes\Ajax\AssessmentBuilderAjaxHandler(); + // Initialize Admin-specific features if ( is_admin() ) { $admin_list_tables = new \Quiztech\AssessmentPlatform\Admin\AdminListTables(); diff --git a/src/Includes/Ajax/AssessmentBuilderAjaxHandler.php b/src/Includes/Ajax/AssessmentBuilderAjaxHandler.php new file mode 100644 index 0000000..5d5f5a3 --- /dev/null +++ b/src/Includes/Ajax/AssessmentBuilderAjaxHandler.php @@ -0,0 +1,151 @@ + esc_html__( 'Insufficient permissions.', 'quiztech' ) ], 403 ); + } + + // 3. Get Filters/Search (TODO: Implement filtering/pagination) + $search_term = isset( $_POST['search'] ) ? sanitize_text_field( wp_unslash( $_POST['search'] ) ) : ''; + $page = isset( $_POST['page'] ) ? absint( $_POST['page'] ) : 1; + $posts_per_page = 10; // Or make configurable + + // 4. Query Questions + $args = [ + 'post_type' => 'question', + 'post_status' => 'publish', // Or allow selecting other statuses? + 'posts_per_page' => $posts_per_page, + 'paged' => $page, + 's' => $search_term, // Basic search + // TODO: Add filtering by category (taxonomy) if needed + ]; + $query = new \WP_Query( $args ); + + $questions = []; + if ( $query->have_posts() ) { + while ( $query->have_posts() ) { + $query->the_post(); + $question_id = get_the_ID(); + // TODO: Get question type and credit cost from meta + $questions[] = [ + 'id' => $question_id, + 'title' => get_the_title(), + 'type' => get_post_meta( $question_id, '_quiztech_question_type', true ) ?: 'N/A', // Placeholder + 'cost' => get_post_meta( $question_id, '_quiztech_question_credits', true ) ?: 0, // Placeholder + ]; + } + wp_reset_postdata(); + } + + // 5. Send Response + wp_send_json_success( [ + 'questions' => $questions, + 'pagination' => [ // TODO: Add pagination details + 'current_page' => $page, + 'total_pages' => $query->max_num_pages, + 'total_results' => $query->found_posts + ] + ] ); + } + + /** + * AJAX handler to save or update an assessment. + * + * Expects assessment data (title, question IDs) via $_POST. + * Returns JSON success or error message. + */ + public function save_assessment() { + // 1. Verify Nonce (TODO: Add nonce check) + // check_ajax_referer( 'quiztech_assessment_builder_nonce', 'nonce' ); + + // 2. Check Capabilities + if ( ! current_user_can( 'manage_options' ) ) { // TODO: Use specific capability + wp_send_json_error( [ 'message' => esc_html__( 'Insufficient permissions.', 'quiztech' ) ], 403 ); + } + + // 3. Sanitize Input + $assessment_id = isset( $_POST['assessment_id'] ) ? absint( $_POST['assessment_id'] ) : 0; // 0 for new assessment + $assessment_title = isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : ''; + $question_ids = isset( $_POST['question_ids'] ) && is_array( $_POST['question_ids'] ) + ? array_map( 'absint', $_POST['question_ids'] ) + : []; + + if ( empty( $assessment_title ) ) { + wp_send_json_error( [ 'message' => esc_html__( 'Assessment title cannot be empty.', 'quiztech' ) ], 400 ); + } + + // 4. Prepare Post Data + $post_data = [ + 'post_title' => $assessment_title, + 'post_type' => 'assessment', + 'post_status' => 'publish', // Or 'draft'? + 'post_author' => get_current_user_id(), + ]; + + if ( $assessment_id > 0 ) { + // Update existing assessment + $post_data['ID'] = $assessment_id; + // Optional: Check if post exists and belongs to user before updating + $existing_post = get_post( $assessment_id ); + if ( ! $existing_post || $existing_post->post_type !== 'assessment' || $existing_post->post_author != get_current_user_id() ) { + wp_send_json_error( [ 'message' => esc_html__( 'Invalid assessment ID or permission denied.', 'quiztech' ) ], 403 ); + } + $result = wp_update_post( $post_data, true ); + } else { + // Insert new assessment + $result = wp_insert_post( $post_data, true ); + } + + // 5. Handle Result & Update Meta + if ( is_wp_error( $result ) ) { + wp_send_json_error( [ 'message' => $result->get_error_message() ], 500 ); + } else { + $saved_assessment_id = $result; + // Update the list of associated question IDs in post meta + // Use a simple comma-separated list or serialized array. Serialized is more flexible. + update_post_meta( $saved_assessment_id, '_quiztech_assessment_questions', $question_ids ); // Using array directly + + // TODO: Calculate and save total credit cost? Or calculate dynamically? + + wp_send_json_success( [ + 'message' => esc_html__( 'Assessment saved successfully.', 'quiztech' ), + 'assessment_id' => $saved_assessment_id + ] ); + } + } +} \ No newline at end of file