PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.9
4.4.9 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 All 140 releases
← All changes | inc/TemplateHooks/Admin/AI/AdminEditCourseCurriculumWithAITemplate.php +473 -473 4.3.9.1 → 4.4.9 View file →
@@ -1,473 +1,473 @@
1 -<?php
2 -
3 -namespace LearnPress\TemplateHooks\Admin\AI;
4 -
5 -use LearnPress\Helpers\Config;
6 -use LearnPress\Helpers\Singleton;
7 -use LearnPress\Helpers\Template;
8 -use LearnPress\TemplateHooks\Admin\AdminTemplate;
9 -use LP_Debug;
10 -use LP_Settings;
11 -use Throwable;
12 -
13 -/**
14 - * Class AdminEditCourseCurriculumWithAITemplate
15 - *
16 - * @since 4.2.9
17 - * @version 1.1.0
18 - */
19 -class AdminEditCourseCurriculumWithAITemplate {
20 - use Singleton;
21 -
22 - /**
23 - * @var array|null
24 - */
25 - private ?array $config;
26 -
27 - /**
28 - * Init hooks.
29 - */
30 - public function init() {
31 - add_action( 'admin_footer', [ $this, 'layout_popup' ] );
32 - }
33 -
34 - /**
35 - * Layout popup to generate course curriculum with AI
36 - */
37 - public function layout_popup() {
38 - try {
39 - if ( ! function_exists( 'get_current_screen' ) ) {
40 - return;
41 - }
42 -
43 - $screen = get_current_screen();
44 - $screens = [
45 - LP_COURSE_CPT,
46 - ];
47 - if ( ! $screen || in_array( $screen, $screens ) ) {
48 - return;
49 - }
50 -
51 - echo $this->render_for_frontend();
52 - } catch ( Throwable $e ) {
53 - LP_Debug::error_log( $e );
54 - }
55 - }
56 -
57 - /**
58 - * Render curriculum AI popup template for frontend contexts (e.g. Course Builder).
59 - *
60 - * @return string
61 - * @since 4.3.0
62 - */
63 - public function render_for_frontend(): string {
64 - try {
65 - $this->config = Config::instance()->get( 'open-ai-modal', 'settings' );
66 -
67 - $components = [
68 - 'wrap-script-template' => '<script type="text/template" id="lp-tmpl-edit-course-curriculum-ai">',
69 - 'wrap' => '<div class="lp-generate-data-ai-wrap">',
70 - 'btn-close' =>
71 - '<button type="button" class="lp-btn-close-ai-popup">
72 - <i class="lp-icon-remove"></i>
73 - </button>',
74 - 'h2' => sprintf(
75 - '<div class="content-title">%s</div>',
76 - esc_html__( 'Generate Course Sections Curriculum', 'learnpress' )
77 - ),
78 - 'header' => $this->html_step_header(),
79 - 'form' => '<form class="lp-form-generate-data-ai">',
80 - 'wrap-fields' => '<div class="lp-form-fields">',
81 - 'step_1' => $this->html_step_1(),
82 - 'step_2' => $this->html_step_2(),
83 - 'step_3' => $this->html_step_3(),
84 - 'step_4' => $this->html_step_4(),
85 - 'wrap-fields-end' => '</div>',
86 - 'buttons' => sprintf(
87 - '<div class="button-actions" data-step="1" data-step-max="4">
88 - <button class="btn btn-secondary lp-btn-step lp-hidden"
89 - data-step-show="2,3,4"
90 - data-action="prev" type="button">&larr; %s
91 - </button>
92 - <button class="btn btn-primary lp-btn-step"
93 - data-step-show="1"
94 - data-action="next" type="button">%s &rarr;
95 - </button>
96 - <button class="lp-button btn-primary lp-btn-generate-prompt lp-hidden"
97 - data-step-show="2"
98 - data-send="%s" type="button">%s
99 - </button>
100 - <button class="lp-button btn-primary lp-btn-call-open-ai lp-hidden"
101 - data-step-show="3"
102 - data-send="%s" type="button">%s
103 - </button>
104 - <button class="lp-button btn-primary lp-btn-apply-curriculum lp-hidden"
105 - data-step-show="4"
106 - data-send="%s" type="button">%s
107 - </button>
108 - </div>',
109 - esc_html__( 'Previous', 'learnpress' ),
110 - esc_html__( 'Next', 'learnpress' ),
111 - Template::convert_data_to_json(
112 - [
113 - 'action' => 'openai_generate_prompt',
114 - 'lp-prompt-type' => 'course-curriculum', // define type prompt to generate title.
115 - 'id_url' => 'generate_prompt_openai',
116 - ]
117 - ),
118 - esc_html__( 'Generate Prompt', 'learnpress' ),
119 - Template::convert_data_to_json(
120 - [
121 - 'action' => 'openai_generate_data',
122 - 'lp-prompt-type' => 'course-curriculum', // define type prompt to generate title.
123 - 'id_url' => 'submit_to_openai',
124 - ]
125 - ),
126 - esc_html__( 'Generate Sections Course', 'learnpress' ),
127 - Template::convert_data_to_json(
128 - [
129 - 'action' => 'openai_create_course_sections',
130 - 'id_url' => 'openai_create_course_sections',
131 - ]
132 - ),
133 - esc_html__( 'Apply Sections Data To Curriculum', 'learnpress' ),
134 - ),
135 - 'form-end' => '</form>',
136 - 'wrap-end' => '</div>',
137 - 'wrap-script-template-end' => '</script>',
138 - ];
139 -
140 - return Template::combine_components( $components );
141 - } catch ( Throwable $e ) {
142 - LP_Debug::error_log( $e );
143 - }
144 -
145 - return '';
146 - }
147 -
148 - public function html_step_header(): string {
149 - $components = [
150 - 'wrap' => '<div class="step-header">',
151 - 'step_1' => sprintf(
152 - '<div class="step-item active" data-step="1"><span class="step-number">1</span><span class="step-text">%s</span></div>',
153 - esc_html__( 'Curriculum Goal', 'learnpress' )
154 - ),
155 - 'step_2' => sprintf(
156 - '<div class="step-item" data-step="2"><span class="step-number">2</span><span class="step-text">%s</span></div>',
157 - esc_html__( 'AI Settings', 'learnpress' )
158 - ),
159 - 'step_3' => sprintf(
160 - '<div class="step-item" data-step="3"><span class="step-number">3</span><span class="step-text">%s</span></div>',
161 - esc_html__( 'Prompt', 'learnpress' )
162 - ),
163 - 'step_4' => sprintf(
164 - '<div class="step-item" data-step="4"><span class="step-number">4</span><span class="step-text">%s</span></div>',
165 - esc_html__( 'Result', 'learnpress' )
166 - ),
167 - 'wrap-end' => '</div>',
168 - ];
169 -
170 - return Template::combine_components( $components );
171 - }
172 -
173 - public function html_step_1(): string {
174 - $options = $this->config;
175 -
176 - $components = [
177 - 'step' => '<div class="step-content active" data-step="1">',
178 - 'title' => sprintf(
179 - '<div class="step-title">%s</div>',
180 - esc_html__( 'Step 1 — Curriculum Goal', 'learnpress' ),
181 - ),
182 - 'description' => sprintf(
183 - '<p class="step-description">%s</p>',
184 - esc_html__( 'Provide the main goal for the curriculum so the system can generate aligned sections and lessons.', 'learnpress' )
185 - ),
186 - 'post-title' => sprintf(
187 - '<div class="form-group">
188 - <label>%s</label>
189 - <input class="title-refer" type="text" name="post-title" readonly />
190 - <p class="lp-ai-warning-refer lp-hidden"><i class="lp-icon-warning"></i>%s</p>
191 - <p class="field-description">%s</p>
192 - </div>',
193 - esc_html__( 'Title refer', 'learnpress' ),
194 - esc_html__( 'You can edit the course title to better suit the curriculum generation.', 'learnpress' ),
195 - esc_html__( 'The course title is automatically imported from the previous step. It will guide the AI to build a structured curriculum.', 'learnpress' ),
196 - ),
197 - 'post-content' => sprintf(
198 - '<div class="form-group">
199 - <label>%s</label>
200 - <textarea class="description-refer" type="text" name="post-content" readonly></textarea>
201 - <p class="lp-ai-warning-refer lp-hidden"><i class="lp-icon-warning"></i>%s</p>
202 - <p class="field-description">%s</p>
203 - </div>',
204 - esc_html__( 'Description refer', 'learnpress' ),
205 - esc_html__( 'You can edit the course description to better suit the curriculum generation.', 'learnpress' ),
206 - esc_html__( 'The course description is automatically imported from the previous step. It will guide the AI to build a structured curriculum.', 'learnpress' )
207 - ),
208 - 'goal' => sprintf(
209 - '<div class="form-group">
210 - <label>%s</label>
211 - <textarea type="text" name="goal" placeholder="%s"></textarea>
212 - </div>',
213 - esc_html__( 'Goal', 'learnpress' ),
214 - esc_html__( 'Defines the main objective of your curriculum. This helps the AI generate course sections and lessons that align with the intended learning outcomes.', 'learnpress' )
215 - ),
216 - 'form-grid' => '<div class="form-grid">',
217 - 'sections-number' => sprintf(
218 - '<div class="form-group">
219 - <label>%s</label>
220 - <input type="number" name="section_number" value="2" min="0">
221 - </div>',
222 - esc_html__( 'Sections number', 'learnpress' )
223 - ),
224 - /*'sections-title-length' => sprintf(
225 - '<div class="form-group">
226 - <label>%s</label>
227 - <input type="number" name="section_title_length" value="60" min="0">
228 - </div>',
229 - esc_html__( 'Each section title length', 'learnpress' )
230 - ),
231 - 'sections-des-length' => sprintf(
232 - '<div class="form-group">
233 - <label>%s</label>
234 - <input type="number" name="section_description_length" value="50" min="0">
235 - </div>',
236 - esc_html__( 'Each section description length', 'learnpress' )
237 - ),*/
238 - 'lesson-number' => sprintf(
239 - '<div class="form-group">
240 - <label>%s</label>
241 - <input type="number" name="lessons_per_section" value="2" min="0">
242 - </div>',
243 - esc_html__( 'Lessons per Section', 'learnpress' )
244 - ),
245 - /*'lesson-title-length' => sprintf(
246 - '<div class="form-group">
247 - <label>%s</label>
248 - <input type="number" name="lessons_title_length" value="60" min="0">
249 - </div>',
250 - esc_html__( 'Each lesson title length', 'learnpress' )
251 - ),*/
252 - 'quizzes' => sprintf(
253 - '<div class="form-group">
254 - <label>%s</label>
255 - <input type="number" name="quizzes_per_section" value="2" min="0">
256 - </div>',
257 - esc_html__( 'Quizzes per Section', 'learnpress' )
258 - ),
259 - /*'quiz-title-length' => sprintf(
260 - '<div class="form-group">
261 - <label>%s</label>
262 - <input type="number" name="quiz_title_length" value="60" min="0">
263 - </div>',
264 - esc_html__( 'Each quiz title length', 'learnpress' )
265 - ),*/
266 - 'form-grid-end' => '</div>',
267 - 'step_close' => '</div>',
268 - ];
269 -
270 - return Template::combine_components( $components );
271 - }
272 -
273 - public function html_step_2(): string {
274 - $options = $this->config;
275 -
276 - $components = [
277 - 'step' => '<div class="step-content" data-step="2">',
278 - 'title' => sprintf(
279 - '<div class="step-title">%s</div>',
280 - esc_html__( 'Step 2 — AI Settings', 'learnpress' ),
281 - ),
282 - 'description' => sprintf(
283 - '<p class="step-description">%s</p>',
284 - esc_html__( 'Configure content quality controls for ChatGPT output.', 'learnpress' )
285 - ),
286 - 'form-grid' => '<div class="form-grid">',
287 - 'audience' => sprintf(
288 - '<div class="form-group">
289 - <label>%s</label>%s
290 - <p class="field-description">%s</p>
291 - </div>',
292 - esc_html__( 'Target Audience', 'learnpress' ),
293 - AdminTemplate::html_tom_select(
294 - [
295 - 'name' => 'target_audience',
296 - 'class_name' => '',
297 - 'options' => $options['audience'] ?? [],
298 - 'default_value' => 'Students',
299 - 'multiple' => true,
300 - ]
301 - ),
302 - esc_html__( 'Identifies who will take the course so the content matches their background and skill level.', 'learnpress' )
303 - ),
304 - 'tone' => sprintf(
305 - '<div class="form-group">
306 - <label for="swal-tone">%s</label>%s
307 - <p class="field-description">%s</p>
308 - </div>',
309 - esc_html__( 'Tone', 'learnpress' ),
310 - AdminTemplate::html_tom_select(
311 - [
312 - 'name' => 'tone',
313 - 'options' => $options['tone'] ?? [],
314 - 'multiple' => true,
315 - 'default_value' => [ 'Analytical' ],
316 - ]
317 - ),
318 - esc_html__( 'Controls the writing style (e.g., friendly, formal, story-telling) so the content matches your brand and audience.', 'learnpress' )
319 - ),
320 - 'language' => sprintf(
321 - '<div class="form-group">
322 - <label>%s</label>%s
323 - <p class="field-description">%s</p>
324 - </div>',
325 - esc_html__( 'Language', 'learnpress' ),
326 - AdminTemplate::html_tom_select(
327 - [
328 - 'name' => 'language',
329 - 'options' => $options['language'] ?? [],
330 - ]
331 - ),
332 - esc_html__( 'Sets the output language for all generated course content.', 'learnpress' )
333 - ),
334 - 'form-grid-end' => '</div>',
335 - 'step_close' => '</div>',
336 - ];
337 -
338 - return Template::combine_components( $components );
339 - }
340 -
341 - public function html_step_3(): string {
342 - $options = $this->config;
343 -
344 - $components = [
345 - 'step' => '<div class="step-content" data-step="3">',
346 - 'title' => sprintf(
347 - '<div class="step-title">%s</div>',
348 - esc_html__( 'Step 3 — Prompt Generated', 'learnpress' ),
349 - ),
350 - 'prompt' => sprintf(
351 - '<div class="form-group">
352 - <label>%s</label>%s
353 - <i>%s</i>
354 - </div>',
355 - esc_html__( 'Generated Prompt', 'learnpress' ),
356 - '<textarea name="lp-openai-prompt-generated-field"></textarea>',
357 - __( 'Shows the auto-generated AI prompt, allowing further adjustments before submission.', 'learnpress' )
358 - ),
359 - 'step_close' => '</div>',
360 - ];
361 -
362 - return Template::combine_components( $components );
363 - }
364 -
365 - public function html_step_4(): string {
366 - $options = $this->config;
367 -
368 - $components = [
369 - 'step' => '<div class="step-content" data-step="4">',
370 - 'title' => sprintf(
371 - '<div class="step-title">%s</div>',
372 - esc_html__( 'Step 4 — Result', 'learnpress' ),
373 - ),
374 - 'results' => '<div class="lp-ai-generated-results lp-ai-course-data-preview-wrap"></div>',
375 - 'step_close' => '</div>',
376 - ];
377 -
378 - return Template::combine_components( $components );
379 - }
380 -
381 - /**
382 - * HTML preview with data received from OpenAI
383 - *
384 - * @param array $data_received
385 - *
386 - * @return string
387 - */
388 - public static function html_preview_with_data( array $data_received ): string {
389 - $sections = $data_received['sections'] ?? [];
390 -
391 - $html_section = '';
392 - foreach ( $sections as $section ) {
393 - $section_title = $section['section_title'] ?? '';
394 - $section_des = $section['section_description'] ?? '';
395 - $lessons = $section['lessons'] ?? [];
396 - $quizzes = $section['quizzes'] ?? [];
397 -
398 - $html_lessons = '';
399 - foreach ( $lessons as $lesson ) {
400 - $lesson_title = $lesson['lesson_title'] ?? '';
401 - $lesson_des = $lesson['lesson_description'] ?? '';
402 -
403 - $arr_lesson_components = [
404 - 'wrap' => '<li class="course-lesson-item">',
405 - 'title' => sprintf( '<div class="lesson-title">%s</div>', esc_html( $lesson_title ) ),
406 - 'des' => sprintf( '<div class="lesson-description">%s</div>', esc_html( $lesson_des ) ),
407 - 'wrap-end' => '</li>',
408 - ];
409 -
410 - $html_lessons .= Template::combine_components( $arr_lesson_components );
411 - }
412 -
413 - // Quizzes
414 - $html_quizzes = '';
415 - foreach ( $quizzes as $quiz ) {
416 - $quiz_title = $quiz['quiz_title'] ?? '';
417 - $quiz_des = $quiz['quiz_description'] ?? '';
418 - $questions = $quiz['questions'] ?? [];
419 -
420 - $html_questions = '';
421 - foreach ( $questions as $question ) {
422 - $question_title = $question['question_title'] ?? '';
423 - $question_des = $question['question_description'] ?? '';
424 - $options = $question['options'] ?? [];
425 -
426 - $html_options = '';
427 - foreach ( $options as $option ) {
428 - $html_options .= sprintf( '<li class="question-option">%s</li>', esc_html( $option ) );
429 - }
430 -
431 - $arr_question_components = [
432 - 'wrap' => '<li class="quiz-question-item">',
433 - 'title' => sprintf( '<div class="question-title">%s</div>', esc_html( $question_title ) ),
434 - 'desc' => sprintf( '<div class="question-desc">%s</div>', esc_html( $question_des ) ),
435 - 'options' => sprintf( '<ul class="course-question-options">%s</ul>', $html_options ),
436 - 'wrap-end' => '</li>',
437 - ];
438 -
439 - $html_questions .= Template::combine_components( $arr_question_components );
440 - }
441 -
442 - $arr_quiz_components = [
443 - 'wrap' => '<div class="course-quiz-item">',
444 - 'title' => sprintf( '<div class="quiz-title">%s</div>', esc_html( $quiz_title ) ),
445 - 'des' => sprintf( '<div class="quiz-description">%s</div>', esc_html( $quiz_des ) ),
446 - 'questions' => sprintf( '<ul class="course-questions">%s</ul>', $html_questions ),
447 - 'wrap-end' => '</div>',
448 - ];
449 -
450 - $html_quizzes .= Template::combine_components( $arr_quiz_components );
451 - }
452 -
453 - $arr_section_components = [
454 - 'wrap' => '<li class="course-section-item">',
455 - 'title' => sprintf( '<div class="section-title">%s</div>', esc_html( $section_title ) ),
456 - 'des' => sprintf( '<div class="section-description">%s</div>', esc_html( $section_des ) ),
457 - 'lessons' => sprintf( '<ul class="course-section-items">%s</ul>', $html_lessons ),
458 - 'quizzes' => sprintf( '<ul class="course-section-items">%s</ul>', $html_quizzes ),
459 - 'wrap-end' => '</li>',
460 - ];
461 -
462 - $html_section .= Template::combine_components( $arr_section_components );
463 - }
464 -
465 - $section = [
466 - 'wrap' => '<div class="lp-ai-course-data-preview">',
467 - 'sections' => sprintf( '<ul class="course-sections">%s</ul>', $html_section ),
468 - 'wrap-end' => '</div>',
469 - ];
470 -
471 - return Template::combine_components( $section );
472 - }
473 -}
1 +<?php
2 +
3 +namespace LearnPress\TemplateHooks\Admin\AI;
4 +
5 +use LearnPress\Helpers\Config;
6 +use LearnPress\Helpers\Singleton;
7 +use LearnPress\Helpers\Template;
8 +use LearnPress\TemplateHooks\Admin\AdminTemplate;
9 +use LP_Debug;
10 +use LP_Settings;
11 +use Throwable;
12 +
13 +/**
14 + * Class AdminEditCourseCurriculumWithAITemplate
15 + *
16 + * @since 4.2.9
17 + * @version 1.1.0
18 + */
19 +class AdminEditCourseCurriculumWithAITemplate {
20 + use Singleton;
21 +
22 + /**
23 + * @var array|null
24 + */
25 + private ?array $config;
26 +
27 + /**
28 + * Init hooks.
29 + */
30 + public function init() {
31 + add_action( 'admin_footer', [ $this, 'layout_popup' ] );
32 + }
33 +
34 + /**
35 + * Layout popup to generate course curriculum with AI
36 + */
37 + public function layout_popup() {
38 + try {
39 + if ( ! function_exists( 'get_current_screen' ) ) {
40 + return;
41 + }
42 +
43 + $screen = get_current_screen();
44 + $screens = [
45 + LP_COURSE_CPT,
46 + ];
47 + if ( ! $screen || in_array( $screen, $screens ) ) {
48 + return;
49 + }
50 +
51 + echo $this->render_for_frontend();
52 + } catch ( Throwable $e ) {
53 + LP_Debug::error_log( $e );
54 + }
55 + }
56 +
57 + /**
58 + * Render curriculum AI popup template for frontend contexts (e.g. Course Builder).
59 + *
60 + * @return string
61 + * @since 4.3.0
62 + */
63 + public function render_for_frontend(): string {
64 + try {
65 + $this->config = Config::instance()->get( 'open-ai-modal', 'settings' );
66 +
67 + $components = [
68 + 'wrap-script-template' => '<script type="text/template" id="lp-tmpl-edit-course-curriculum-ai">',
69 + 'wrap' => '<div class="lp-generate-data-ai-wrap">',
70 + 'btn-close' =>
71 + '<button type="button" class="lp-btn-close-ai-popup">
72 + <i class="lp-icon-remove"></i>
73 + </button>',
74 + 'h2' => sprintf(
75 + '<div class="content-title">%s</div>',
76 + esc_html__( 'Generate Course Sections Curriculum', 'learnpress' )
77 + ),
78 + 'header' => $this->html_step_header(),
79 + 'form' => '<form class="lp-form-generate-data-ai">',
80 + 'wrap-fields' => '<div class="lp-form-fields">',
81 + 'step_1' => $this->html_step_1(),
82 + 'step_2' => $this->html_step_2(),
83 + 'step_3' => $this->html_step_3(),
84 + 'step_4' => $this->html_step_4(),
85 + 'wrap-fields-end' => '</div>',
86 + 'buttons' => sprintf(
87 + '<div class="button-actions" data-step="1" data-step-max="4">
88 + <button class="btn btn-secondary lp-btn-step lp-hidden"
89 + data-step-show="2,3,4"
90 + data-action="prev" type="button">&larr; %s
91 + </button>
92 + <button class="btn btn-primary lp-btn-step"
93 + data-step-show="1"
94 + data-action="next" type="button">%s &rarr;
95 + </button>
96 + <button class="lp-button btn-primary lp-btn-generate-prompt lp-hidden"
97 + data-step-show="2"
98 + data-send="%s" type="button">%s
99 + </button>
100 + <button class="lp-button btn-primary lp-btn-call-open-ai lp-hidden"
101 + data-step-show="3"
102 + data-send="%s" type="button">%s
103 + </button>
104 + <button class="lp-button btn-primary lp-btn-apply-curriculum lp-hidden"
105 + data-step-show="4"
106 + data-send="%s" type="button">%s
107 + </button>
108 + </div>',
109 + esc_html__( 'Previous', 'learnpress' ),
110 + esc_html__( 'Next', 'learnpress' ),
111 + Template::convert_data_to_json(
112 + [
113 + 'action' => 'openai_generate_prompt',
114 + 'lp-prompt-type' => 'course-curriculum', // define type prompt to generate title.
115 + 'id_url' => 'generate_prompt_openai',
116 + ]
117 + ),
118 + esc_html__( 'Generate Prompt', 'learnpress' ),
119 + Template::convert_data_to_json(
120 + [
121 + 'action' => 'openai_generate_data',
122 + 'lp-prompt-type' => 'course-curriculum', // define type prompt to generate title.
123 + 'id_url' => 'submit_to_openai',
124 + ]
125 + ),
126 + esc_html__( 'Generate Sections Course', 'learnpress' ),
127 + Template::convert_data_to_json(
128 + [
129 + 'action' => 'openai_create_course_sections',
130 + 'id_url' => 'openai_create_course_sections',
131 + ]
132 + ),
133 + esc_html__( 'Apply Sections Data To Curriculum', 'learnpress' ),
134 + ),
135 + 'form-end' => '</form>',
136 + 'wrap-end' => '</div>',
137 + 'wrap-script-template-end' => '</script>',
138 + ];
139 +
140 + return Template::combine_components( $components );
141 + } catch ( Throwable $e ) {
142 + LP_Debug::error_log( $e );
143 + }
144 +
145 + return '';
146 + }
147 +
148 + public function html_step_header(): string {
149 + $components = [
150 + 'wrap' => '<div class="step-header">',
151 + 'step_1' => sprintf(
152 + '<div class="step-item active" data-step="1"><span class="step-number">1</span><span class="step-text">%s</span></div>',
153 + esc_html__( 'Curriculum Goal', 'learnpress' )
154 + ),
155 + 'step_2' => sprintf(
156 + '<div class="step-item" data-step="2"><span class="step-number">2</span><span class="step-text">%s</span></div>',
157 + esc_html__( 'AI Settings', 'learnpress' )
158 + ),
159 + 'step_3' => sprintf(
160 + '<div class="step-item" data-step="3"><span class="step-number">3</span><span class="step-text">%s</span></div>',
161 + esc_html__( 'Prompt', 'learnpress' )
162 + ),
163 + 'step_4' => sprintf(
164 + '<div class="step-item" data-step="4"><span class="step-number">4</span><span class="step-text">%s</span></div>',
165 + esc_html__( 'Result', 'learnpress' )
166 + ),
167 + 'wrap-end' => '</div>',
168 + ];
169 +
170 + return Template::combine_components( $components );
171 + }
172 +
173 + public function html_step_1(): string {
174 + $options = $this->config;
175 +
176 + $components = [
177 + 'step' => '<div class="step-content active" data-step="1">',
178 + 'title' => sprintf(
179 + '<div class="step-title">%s</div>',
180 + esc_html__( 'Step 1 — Curriculum Goal', 'learnpress' ),
181 + ),
182 + 'description' => sprintf(
183 + '<p class="step-description">%s</p>',
184 + esc_html__( 'Provide the main goal for the curriculum so the system can generate aligned sections and lessons.', 'learnpress' )
185 + ),
186 + 'post-title' => sprintf(
187 + '<div class="form-group">
188 + <label>%s</label>
189 + <input class="title-refer" type="text" name="post-title" readonly />
190 + <p class="lp-ai-warning-refer lp-hidden"><i class="lp-icon-warning"></i>%s</p>
191 + <p class="field-description">%s</p>
192 + </div>',
193 + esc_html__( 'Title refer', 'learnpress' ),
194 + esc_html__( 'You can edit the course title to better suit the curriculum generation.', 'learnpress' ),
195 + esc_html__( 'The course title is automatically imported from the previous step. It will guide the AI to build a structured curriculum.', 'learnpress' ),
196 + ),
197 + 'post-content' => sprintf(
198 + '<div class="form-group">
199 + <label>%s</label>
200 + <textarea class="description-refer" type="text" name="post-content" readonly></textarea>
201 + <p class="lp-ai-warning-refer lp-hidden"><i class="lp-icon-warning"></i>%s</p>
202 + <p class="field-description">%s</p>
203 + </div>',
204 + esc_html__( 'Description refer', 'learnpress' ),
205 + esc_html__( 'You can edit the course description to better suit the curriculum generation.', 'learnpress' ),
206 + esc_html__( 'The course description is automatically imported from the previous step. It will guide the AI to build a structured curriculum.', 'learnpress' )
207 + ),
208 + 'goal' => sprintf(
209 + '<div class="form-group">
210 + <label>%s</label>
211 + <textarea type="text" name="goal" placeholder="%s"></textarea>
212 + </div>',
213 + esc_html__( 'Goal', 'learnpress' ),
214 + esc_html__( 'Defines the main objective of your curriculum. This helps the AI generate course sections and lessons that align with the intended learning outcomes.', 'learnpress' )
215 + ),
216 + 'form-grid' => '<div class="form-grid">',
217 + 'sections-number' => sprintf(
218 + '<div class="form-group">
219 + <label>%s</label>
220 + <input type="number" name="section_number" value="2" min="0">
221 + </div>',
222 + esc_html__( 'Sections number', 'learnpress' )
223 + ),
224 + /*'sections-title-length' => sprintf(
225 + '<div class="form-group">
226 + <label>%s</label>
227 + <input type="number" name="section_title_length" value="60" min="0">
228 + </div>',
229 + esc_html__( 'Each section title length', 'learnpress' )
230 + ),
231 + 'sections-des-length' => sprintf(
232 + '<div class="form-group">
233 + <label>%s</label>
234 + <input type="number" name="section_description_length" value="50" min="0">
235 + </div>',
236 + esc_html__( 'Each section description length', 'learnpress' )
237 + ),*/
238 + 'lesson-number' => sprintf(
239 + '<div class="form-group">
240 + <label>%s</label>
241 + <input type="number" name="lessons_per_section" value="2" min="0">
242 + </div>',
243 + esc_html__( 'Lessons per Section', 'learnpress' )
244 + ),
245 + /*'lesson-title-length' => sprintf(
246 + '<div class="form-group">
247 + <label>%s</label>
248 + <input type="number" name="lessons_title_length" value="60" min="0">
249 + </div>',
250 + esc_html__( 'Each lesson title length', 'learnpress' )
251 + ),*/
252 + 'quizzes' => sprintf(
253 + '<div class="form-group">
254 + <label>%s</label>
255 + <input type="number" name="quizzes_per_section" value="2" min="0">
256 + </div>',
257 + esc_html__( 'Quizzes per Section', 'learnpress' )
258 + ),
259 + /*'quiz-title-length' => sprintf(
260 + '<div class="form-group">
261 + <label>%s</label>
262 + <input type="number" name="quiz_title_length" value="60" min="0">
263 + </div>',
264 + esc_html__( 'Each quiz title length', 'learnpress' )
265 + ),*/
266 + 'form-grid-end' => '</div>',
267 + 'step_close' => '</div>',
268 + ];
269 +
270 + return Template::combine_components( $components );
271 + }
272 +
273 + public function html_step_2(): string {
274 + $options = $this->config;
275 +
276 + $components = [
277 + 'step' => '<div class="step-content" data-step="2">',
278 + 'title' => sprintf(
279 + '<div class="step-title">%s</div>',
280 + esc_html__( 'Step 2 — AI Settings', 'learnpress' ),
281 + ),
282 + 'description' => sprintf(
283 + '<p class="step-description">%s</p>',
284 + esc_html__( 'Configure content quality controls for ChatGPT output.', 'learnpress' )
285 + ),
286 + 'form-grid' => '<div class="form-grid">',
287 + 'audience' => sprintf(
288 + '<div class="form-group">
289 + <label>%s</label>%s
290 + <p class="field-description">%s</p>
291 + </div>',
292 + esc_html__( 'Target Audience', 'learnpress' ),
293 + AdminTemplate::html_tom_select(
294 + [
295 + 'name' => 'target_audience',
296 + 'class_name' => '',
297 + 'options' => $options['audience'] ?? [],
298 + 'default_value' => 'Students',
299 + 'multiple' => true,
300 + ]
301 + ),
302 + esc_html__( 'Identifies who will take the course so the content matches their background and skill level.', 'learnpress' )
303 + ),
304 + 'tone' => sprintf(
305 + '<div class="form-group">
306 + <label for="swal-tone">%s</label>%s
307 + <p class="field-description">%s</p>
308 + </div>',
309 + esc_html__( 'Tone', 'learnpress' ),
310 + AdminTemplate::html_tom_select(
311 + [
312 + 'name' => 'tone',
313 + 'options' => $options['tone'] ?? [],
314 + 'multiple' => true,
315 + 'default_value' => [ 'Analytical' ],
316 + ]
317 + ),
318 + esc_html__( 'Controls the writing style (e.g., friendly, formal, story-telling) so the content matches your brand and audience.', 'learnpress' )
319 + ),
320 + 'language' => sprintf(
321 + '<div class="form-group">
322 + <label>%s</label>%s
323 + <p class="field-description">%s</p>
324 + </div>',
325 + esc_html__( 'Language', 'learnpress' ),
326 + AdminTemplate::html_tom_select(
327 + [
328 + 'name' => 'language',
329 + 'options' => $options['language'] ?? [],
330 + ]
331 + ),
332 + esc_html__( 'Sets the output language for all generated course content.', 'learnpress' )
333 + ),
334 + 'form-grid-end' => '</div>',
335 + 'step_close' => '</div>',
336 + ];
337 +
338 + return Template::combine_components( $components );
339 + }
340 +
341 + public function html_step_3(): string {
342 + $options = $this->config;
343 +
344 + $components = [
345 + 'step' => '<div class="step-content" data-step="3">',
346 + 'title' => sprintf(
347 + '<div class="step-title">%s</div>',
348 + esc_html__( 'Step 3 — Prompt Generated', 'learnpress' ),
349 + ),
350 + 'prompt' => sprintf(
351 + '<div class="form-group">
352 + <label>%s</label>%s
353 + <i>%s</i>
354 + </div>',
355 + esc_html__( 'Generated Prompt', 'learnpress' ),
356 + '<textarea name="lp-openai-prompt-generated-field"></textarea>',
357 + __( 'Shows the auto-generated AI prompt, allowing further adjustments before submission.', 'learnpress' )
358 + ),
359 + 'step_close' => '</div>',
360 + ];
361 +
362 + return Template::combine_components( $components );
363 + }
364 +
365 + public function html_step_4(): string {
366 + $options = $this->config;
367 +
368 + $components = [
369 + 'step' => '<div class="step-content" data-step="4">',
370 + 'title' => sprintf(
371 + '<div class="step-title">%s</div>',
372 + esc_html__( 'Step 4 — Result', 'learnpress' ),
373 + ),
374 + 'results' => '<div class="lp-ai-generated-results lp-ai-course-data-preview-wrap"></div>',
375 + 'step_close' => '</div>',
376 + ];
377 +
378 + return Template::combine_components( $components );
379 + }
380 +
381 + /**
382 + * HTML preview with data received from OpenAI
383 + *
384 + * @param array $data_received
385 + *
386 + * @return string
387 + */
388 + public static function html_preview_with_data( array $data_received ): string {
389 + $sections = $data_received['sections'] ?? [];
390 +
391 + $html_section = '';
392 + foreach ( $sections as $section ) {
393 + $section_title = $section['section_title'] ?? '';
394 + $section_des = $section['section_description'] ?? '';
395 + $lessons = $section['lessons'] ?? [];
396 + $quizzes = $section['quizzes'] ?? [];
397 +
398 + $html_lessons = '';
399 + foreach ( $lessons as $lesson ) {
400 + $lesson_title = $lesson['lesson_title'] ?? '';
401 + $lesson_des = $lesson['lesson_description'] ?? '';
402 +
403 + $arr_lesson_components = [
404 + 'wrap' => '<li class="course-lesson-item">',
405 + 'title' => sprintf( '<div class="lesson-title">%s</div>', esc_html( $lesson_title ) ),
406 + 'des' => sprintf( '<div class="lesson-description">%s</div>', esc_html( $lesson_des ) ),
407 + 'wrap-end' => '</li>',
408 + ];
409 +
410 + $html_lessons .= Template::combine_components( $arr_lesson_components );
411 + }
412 +
413 + // Quizzes
414 + $html_quizzes = '';
415 + foreach ( $quizzes as $quiz ) {
416 + $quiz_title = $quiz['quiz_title'] ?? '';
417 + $quiz_des = $quiz['quiz_description'] ?? '';
418 + $questions = $quiz['questions'] ?? [];
419 +
420 + $html_questions = '';
421 + foreach ( $questions as $question ) {
422 + $question_title = $question['question_title'] ?? '';
423 + $question_des = $question['question_description'] ?? '';
424 + $options = $question['options'] ?? [];
425 +
426 + $html_options = '';
427 + foreach ( $options as $option ) {
428 + $html_options .= sprintf( '<li class="question-option">%s</li>', esc_html( $option ) );
429 + }
430 +
431 + $arr_question_components = [
432 + 'wrap' => '<li class="quiz-question-item">',
433 + 'title' => sprintf( '<div class="question-title">%s</div>', esc_html( $question_title ) ),
434 + 'desc' => sprintf( '<div class="question-desc">%s</div>', esc_html( $question_des ) ),
435 + 'options' => sprintf( '<ul class="course-question-options">%s</ul>', $html_options ),
436 + 'wrap-end' => '</li>',
437 + ];
438 +
439 + $html_questions .= Template::combine_components( $arr_question_components );
440 + }
441 +
442 + $arr_quiz_components = [
443 + 'wrap' => '<div class="course-quiz-item">',
444 + 'title' => sprintf( '<div class="quiz-title">%s</div>', esc_html( $quiz_title ) ),
445 + 'des' => sprintf( '<div class="quiz-description">%s</div>', esc_html( $quiz_des ) ),
446 + 'questions' => sprintf( '<ul class="course-questions">%s</ul>', $html_questions ),
447 + 'wrap-end' => '</div>',
448 + ];
449 +
450 + $html_quizzes .= Template::combine_components( $arr_quiz_components );
451 + }
452 +
453 + $arr_section_components = [
454 + 'wrap' => '<li class="course-section-item">',
455 + 'title' => sprintf( '<div class="section-title">%s</div>', esc_html( $section_title ) ),
456 + 'des' => sprintf( '<div class="section-description">%s</div>', esc_html( $section_des ) ),
457 + 'lessons' => sprintf( '<ul class="course-section-items">%s</ul>', $html_lessons ),
458 + 'quizzes' => sprintf( '<ul class="course-section-items">%s</ul>', $html_quizzes ),
459 + 'wrap-end' => '</li>',
460 + ];
461 +
462 + $html_section .= Template::combine_components( $arr_section_components );
463 + }
464 +
465 + $section = [
466 + 'wrap' => '<div class="lp-ai-course-data-preview">',
467 + 'sections' => sprintf( '<ul class="course-sections">%s</ul>', $html_section ),
468 + 'wrap-end' => '</div>',
469 + ];
470 +
471 + return Template::combine_components( $section );
472 + }
473 +}