PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.6
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.6
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
learnpress / inc / Ajax / AI / AIAssistantAjax.php

AIAssistantAjax.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.6, at inc/Ajax/AI/AIAssistantAjax.php

106 lines 3.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace LearnPress\Ajax\AI;
4
5 use LearnPress\Ajax\AbstractAjax;
6 use LearnPress\AI\Assistant\AIAssistantController;
7 use LP_Debug;
8 use LP_Helper;
9 use LP_Request;
10 use LP_REST_Response;
11 use Exception;
12 use Throwable;
13
14 /**
15 * Class AIAssistantAjax
16 *
17 * Handles student-facing AJAX requests for the LP AI Assistant.
18 *
19 * Intentionally separate from OpenAiAjax — every method in OpenAiAjax
20 * enforces ROLE_ADMINISTRATOR || ROLE_INSTRUCTOR. Mixing student-facing
21 * methods into the same class creates conflicting permission models.
22 *
23 * Transport: lp-load-ajax (same AbstractAjax mechanic as all other LP AJAX classes).
24 *
25 * @package LearnPress\Ajax\AI
26 * @since 4.3.5
27 */
28 class AIAssistantAjax extends AbstractAjax {
29
30 /**
31 * Handle assistant chat request from a logged-in learner.
32 *
33 * Nonce is verified by AbstractAjax::catch_lp_ajax() and is CSRF protection only —
34 * never authorization. Login is checked here; per-item authorization is the
35 * controller's job, via AIAssistantController::resolve_item_access().
36 *
37 * Request data (JSON-encoded in 'data' param). A course item is addressed by the
38 * full tuple (course_id, item_type, item_id); all three are required.
39 * {
40 * "message": string,
41 * "course_id": int,
42 * "item_type": string, // lp_lesson | lp_quiz — validated against the curriculum
43 * "item_id": int,
44 * "history": [{role, content}, ...],
45 * "active_quiz_questions": {},
46 * "action_hint": string
47 * }
48 *
49 * Response shape:
50 * { "status": "success", "message": "", "data": { "type": "text|quiz", "message": "...", "quiz": {} } }
51 */
52 public function openai_assistant_chat() {
53 $response = new LP_REST_Response();
54
55 try {
56 if ( ! is_user_logged_in() ) {
57 throw new Exception( __( 'You must be logged in to use the AI Assistant.', 'learnpress' ) );
58 }
59
60 if ( ! AIAssistantController::is_enabled() ) {
61 throw new Exception( __( 'AI Assistant is not available.', 'learnpress' ) );
62 }
63
64 $data_str = LP_Request::get_param( 'data' );
65 $data = LP_Helper::json_decode( $data_str, true );
66
67 if ( ! is_array( $data ) ) {
68 throw new Exception( __( 'Invalid request data.', 'learnpress' ) );
69 }
70
71 $controller = new AIAssistantController();
72 $result = $controller->handle_chat( $data );
73 $result = $this->normalize_response_data( $result );
74
75 $response->status = 'success';
76 $response->data = $result;
77 } catch ( Throwable $e ) {
78 $response->message = __( 'The AI Assistant is unavailable right now. Please try again later.', 'learnpress' );
79 $response->data = $this->normalize_response_data( array() );
80 }
81
82 wp_send_json( $response );
83 }
84
85 /**
86 * Normalize controller result to required frontend contract.
87 *
88 * @param array $result
89 *
90 * @return array{type:string,message:string,quiz:array|null}
91 */
92 private function normalize_response_data( array $result ): array {
93 $type = $result['type'] ?? 'text';
94
95 if ( ! in_array( $type, array( 'text', 'quiz' ), true ) ) {
96 $type = 'text';
97 }
98
99 return array(
100 'type' => $type,
101 'message' => isset( $result['message'] ) ? (string) $result['message'] : '',
102 'quiz' => is_array( $result['quiz'] ?? null ) ? $result['quiz'] : null,
103 );
104 }
105 }
106