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/AdminEditWithAITemplate.php +971 -971 4.3.9 → 4.4.9 View file →
@@ -1,971 +1,971 @@
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 AdminEditWithAITemplate
15 - *
16 - * @since 4.2.9
17 - * @version 1.1.0
18 - */
19 -class AdminEditWithAITemplate {
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 - public function layout_popup() {
35 - try {
36 - if ( ! function_exists( 'get_current_screen' ) ) {
37 - return;
38 - }
39 -
40 - $screen = get_current_screen();
41 - $screens = [
42 - LP_COURSE_CPT,
43 - ];
44 - if ( ! $screen || in_array( $screen, $screens ) ) {
45 - return;
46 - }
47 -
48 - $this->config = Config::instance()->get( 'open-ai-modal', 'settings' );
49 - echo $this->html_edit_title_via_ai();
50 - echo $this->html_edit_description_via_ai();
51 - echo $this->html_edit_image_via_ai();
52 - echo $this->html_edit_curriculum_via_ai();
53 - } catch ( Throwable $e ) {
54 - LP_Debug::error_log( $e );
55 - }
56 - }
57 -
58 - /**
59 - * Render AI templates for frontend contexts (e.g. Course Builder).
60 - *
61 - * @param array $template_types Supported: title, description, image, curriculum.
62 - *
63 - * @return string
64 - * @since 4.3.0
65 - */
66 - public function render_for_frontend( array $template_types = [ 'title', 'description' ] ): string {
67 - try {
68 - $this->config = Config::instance()->get( 'open-ai-modal', 'settings' );
69 -
70 - $template_map = [
71 - 'title' => 'html_edit_title_via_ai',
72 - 'description' => 'html_edit_description_via_ai',
73 - 'image' => 'html_edit_image_via_ai',
74 - 'curriculum' => 'html_edit_curriculum_via_ai',
75 - ];
76 -
77 - $output = '';
78 - foreach ( $template_types as $template_type ) {
79 - $method = $template_map[ $template_type ] ?? '';
80 - if ( ! $method || ! method_exists( $this, $method ) ) {
81 - continue;
82 - }
83 -
84 - $output .= $this->{$method}();
85 - }
86 -
87 - return $output;
88 - } catch ( Throwable $e ) {
89 - LP_Debug::error_log( $e );
90 - }
91 -
92 - return '';
93 - }
94 -
95 - /**
96 - * HTML generate title with AI.
97 - *
98 - * @return string
99 - */
100 - public function html_edit_title_via_ai(): string {
101 - $components = [
102 - 'wrap-script-template' => '<script type="text/template" id="lp-tmpl-edit-title-ai">',
103 - 'wrap' => '<div class="lp-generate-data-ai-wrap">',
104 - 'btn-close' =>
105 - '<button type="button" class="lp-btn-close-ai-popup">
106 - <i class="lp-icon-remove"></i>
107 - </button>',
108 - 'h2' => sprintf(
109 - '<div class="content-title">%s</div>',
110 - esc_html__( 'Generate Course Title', 'learnpress' )
111 - ),
112 - 'header' => $this->html_title_step_header(),
113 - 'form' => '<form class="lp-form-generate-data-ai">',
114 - 'wrap-fields' => '<div class="lp-form-fields">',
115 - 'step_1' => $this->html_title_step_1(),
116 - 'step_2' => $this->html_title_step_2(),
117 - 'step_3' => $this->html_title_step_3(),
118 - 'step_4' => $this->html_title_step_4(),
119 - 'wrap-fields-end' => '</div>',
120 - 'buttons' => sprintf(
121 - '<div class="button-actions" data-step="1" data-step-max="4">
122 - <button class="btn btn-secondary lp-btn-step lp-hidden"
123 - data-step-show="2,3,4"
124 - data-action="prev" type="button">&larr; %s
125 - </button>
126 - <button class="btn btn-primary lp-btn-step"
127 - data-step-show="1"
128 - data-action="next" type="button">%s &rarr;
129 - </button>
130 - <button class="lp-button btn-primary lp-btn-generate-prompt lp-hidden"
131 - data-step-show="2"
132 - data-send="%s" type="button">%s
133 - </button>
134 - <button class="lp-button btn-primary lp-btn-call-open-ai lp-hidden"
135 - data-step-show="3"
136 - data-send="%s" type="button">%s
137 - </button>
138 - </div>',
139 - esc_html__( 'Previous', 'learnpress' ),
140 - esc_html__( 'Next', 'learnpress' ),
141 - Template::convert_data_to_json(
142 - [
143 - 'action' => 'openai_generate_prompt',
144 - 'lp-prompt-type' => 'course-title', // define type prompt to generate title.
145 - 'id_url' => 'generate_prompt_openai',
146 - ]
147 - ),
148 - esc_html__( 'Generate Prompt', 'learnpress' ),
149 - Template::convert_data_to_json(
150 - [
151 - 'action' => 'openai_generate_data',
152 - 'lp-prompt-type' => 'course-title', // define type prompt to generate title.
153 - 'target-apply' => 'set-wp-title', // Click apply to apply title to this field.
154 - 'id_url' => 'submit_to_openai',
155 - ]
156 - ),
157 - esc_html__( 'Generate Title Course', 'learnpress' ),
158 - ),
159 - 'form-end' => '</form>',
160 - 'wrap-end' => '</div>',
161 - 'wrap-script-template-end' => '</script>',
162 - ];
163 -
164 - return Template::combine_components( $components );
165 - }
166 -
167 - public function html_title_step_header(): string {
168 - $components = [
169 - 'wrap' => '<div class="step-header">',
170 - 'step_1' => sprintf(
171 - '<div class="step-item active" data-step="1"><span class="step-number">1</span><span class="step-text">%s</span></div>',
172 - esc_html__( 'Course Goal', 'learnpress' )
173 - ),
174 - 'step_2' => sprintf(
175 - '<div class="step-item" data-step="2"><span class="step-number">2</span><span class="step-text">%s</span></div>',
176 - esc_html__( 'AI Settings', 'learnpress' )
177 - ),
178 - 'step_3' => sprintf(
179 - '<div class="step-item" data-step="3"><span class="step-number">3</span><span class="step-text">%s</span></div>',
180 - esc_html__( 'Prompt', 'learnpress' )
181 - ),
182 - 'step_4' => sprintf(
183 - '<div class="step-item" data-step="4"><span class="step-number">4</span><span class="step-text">%s</span></div>',
184 - esc_html__( 'Result', 'learnpress' )
185 - ),
186 - 'wrap-end' => '</div>',
187 - ];
188 -
189 - return Template::combine_components( $components );
190 - }
191 -
192 - public function html_title_step_1(): string {
193 - $options = $this->config;
194 -
195 - $components = [
196 - 'step' => '<div class="step-content active" data-step="1">',
197 - 'title' => sprintf(
198 - '<div class="step-title">%s</div>',
199 - esc_html__( 'Step 1 — Configure Course Title', 'learnpress' ),
200 - ),
201 - 'description' => sprintf(
202 - '<p class="step-description">%s</p>',
203 - esc_html__( 'Provide the basic information to generate your course title.', 'learnpress' )
204 - ),
205 - 'describe-topic' => sprintf(
206 - '<div class="form-group">
207 - <label>%s</label>
208 - <textarea type="text" name="topic" placeholder="%s"></textarea>
209 - </div>',
210 - esc_html__( 'Describe what your course is about', 'learnpress' ),
211 - esc_html__( 'Provide a short explanation of the subject or skills your course covers. This helps AI understand the overall direction of your title.', 'learnpress' )
212 - ),
213 - 'describe-goals' => sprintf(
214 - '<div class="form-group">
215 - <label>%s</label>
216 - <textarea type="text" name="goals" placeholder="%s"></textarea>
217 - </div>',
218 - esc_html__( 'Describe the main goals of your course', 'learnpress' ),
219 - esc_html__( 'Summarize what learners will achieve. AI uses this to make the title more accurate and meaningful.', 'learnpress' )
220 - ),
221 - 'length' => sprintf(
222 - '<div class="form-group">
223 - <label>%s</label>
224 - <input type="text" name="length" value="60" />
225 - <p class="field-description">%s</p>
226 - </div>',
227 - esc_html__( 'Title Length (characters)', 'learnpress' ),
228 - esc_html__( 'Set the maximum number of characters for the generated course title. Ideal for SEO and platform display constraints.', 'learnpress' )
229 - ),
230 - 'step_close' => '</div>',
231 - ];
232 -
233 - return Template::combine_components( $components );
234 - }
235 -
236 - public function html_title_step_2(): string {
237 - $options = $this->config;
238 -
239 - $components = [
240 - 'step' => '<div class="step-content" data-step="2">',
241 - 'title' => sprintf(
242 - '<div class="step-title">%s</div>',
243 - esc_html__( 'Step 2 — AI Settings', 'learnpress' ),
244 - ),
245 - 'description' => sprintf(
246 - '<p class="step-description">%s</p>',
247 - esc_html__( 'Configure content quality controls for ChatGPT output.', 'learnpress' )
248 - ),
249 - 'form-grid' => '<div class="form-grid">',
250 - 'audience' => sprintf(
251 - '<div class="form-group">
252 - <label>%s</label>%s
253 - <p class="field-description">%s</p>
254 - </div>',
255 - esc_html__( 'Target Audience', 'learnpress' ),
256 - AdminTemplate::html_tom_select(
257 - [
258 - 'name' => 'target_audience',
259 - 'class_name' => '',
260 - 'options' => $options['audience'] ?? [],
261 - 'default_value' => 'Students',
262 - 'multiple' => true,
263 - ]
264 - ),
265 - esc_html__( 'Identifies who will take the course so the content matches their background and skill level.', 'learnpress' ),
266 - ),
267 - 'tone' => sprintf(
268 - '<div class="form-group">
269 - <label for="swal-tone">%s</label>%s
270 - <p class="field-description">%s</p>
271 - </div>',
272 - esc_html__( 'Tone', 'learnpress' ),
273 - AdminTemplate::html_tom_select(
274 - [
275 - 'name' => 'tone',
276 - 'options' => $options['tone'] ?? [],
277 - 'multiple' => true,
278 - 'default_value' => [ 'Analytical' ],
279 - ]
280 - ),
281 - esc_html__( 'Controls the writing style (e.g., friendly, formal, story-telling) so the content matches your brand and audience.', 'learnpress' )
282 - ),
283 - 'language' => sprintf(
284 - '<div class="form-group">
285 - <label>%s</label>%s
286 - <p class="field-description">%s</p>
287 - </div>',
288 - esc_html__( 'Language', 'learnpress' ),
289 - AdminTemplate::html_tom_select(
290 - [
291 - 'name' => 'language',
292 - 'options' => $options['language'] ?? [],
293 - ]
294 - ),
295 - esc_html__( 'Sets the output language for all generated course content.', 'learnpress' )
296 - ),
297 - 'outputs' => sprintf(
298 - '<div class="form-group">
299 - <label>%s</label>%s
300 - <p class="field-description">%s</p>
301 - </div>',
302 - esc_html__( 'Outputs', 'learnpress' ),
303 - '<input name="outputs" value="2" />',
304 - esc_html__( 'Select how many title options the system will generate for you.', 'learnpress' )
305 - ),
306 - 'form-grid-end' => '</div>',
307 - 'step_close' => '</div>',
308 - ];
309 -
310 - return Template::combine_components( $components );
311 - }
312 -
313 - public function html_title_step_3(): string {
314 - $options = $this->config;
315 -
316 - $components = [
317 - 'step' => '<div class="step-content" data-step="3">',
318 - 'title' => sprintf(
319 - '<div class="step-title">%s</div>',
320 - esc_html__( 'Step 3 — Prompt Generated', 'learnpress' ),
321 - ),
322 - 'prompt' => sprintf(
323 - '<div class="form-group">
324 - <label>%s</label>%s
325 - <i>%s</i>
326 - </div>',
327 - esc_html__( 'Generated Prompt', 'learnpress' ),
328 - '<textarea name="lp-openai-prompt-generated-field"></textarea>',
329 - __( 'Shows the auto-generated AI prompt, allowing further adjustments before submission.', 'learnpress' )
330 - ),
331 - 'step_close' => '</div>',
332 - ];
333 -
334 - return Template::combine_components( $components );
335 - }
336 -
337 - public function html_title_step_4(): string {
338 - $options = $this->config;
339 -
340 - $components = [
341 - 'step' => '<div class="step-content" data-step="4">',
342 - 'title' => sprintf(
343 - '<div class="step-title">%s</div>',
344 - esc_html__( 'Step 4 — Result', 'learnpress' ),
345 - ),
346 - 'results' => '<div class="lp-ai-generated-results"></div>',
347 - 'step_close' => '</div>',
348 - ];
349 -
350 - return Template::combine_components( $components );
351 - }
352 -
353 - /**
354 - * HTML list results openAI returned.
355 - *
356 - * @param array $args
357 - *
358 - * @return string
359 - */
360 - public function html_list_results( array $args ): string {
361 - $index = $args['index'] ?? 0;
362 - $value = $args['value'] ?? '';
363 - // Target is element html to apply value.
364 - $target = $args['target-apply'] ?? '';
365 -
366 - $section = [
367 - 'wrap' => '<div class="lp-ai-generated-result-item form-group">',
368 - 'label' => sprintf(
369 - '<label>%s</label>',
370 - sprintf( __( 'Result %d', 'learnpress' ), $index + 1 )
371 - ),
372 - 'textarea' => sprintf(
373 - '<textarea class="lp-ai-string-result" cols="3">%s</textarea>',
374 - esc_attr( $value )
375 - ),
376 - 'copy_button' => sprintf(
377 - '<button class="button lp-btn-copy" data-copy="%s" type="button">%s</button>',
378 - esc_attr( $value ),
379 - __( 'Copy', 'learnpress' )
380 - ),
381 - 'apply_button' => sprintf(
382 - '<button class="button lp-btn-apply button-primary"
383 - data-apply="%s" type="button" data-target="%s">%s
384 - </button>',
385 - esc_attr( $value ),
386 - esc_attr( $target ),
387 - __( 'Apply', 'learnpress' )
388 - ),
389 - 'wrap_end' => '</div>',
390 - ];
391 -
392 - return Template::combine_components( $section );
393 - }
394 -
395 - /***************** Description *****************/
396 - /**
397 - * HTML generate title with AI.
398 - *
399 - * @return string
400 - */
401 - public function html_edit_description_via_ai(): string {
402 - $components = [
403 - 'wrap-script-template' => '<script type="text/template" id="lp-tmpl-edit-description-ai">',
404 - 'wrap' => '<div class="lp-generate-data-ai-wrap">',
405 - 'btn-close' =>
406 - '<button type="button" class="lp-btn-close-ai-popup">
407 - <i class="lp-icon-remove"></i>
408 - </button>',
409 - 'h2' => sprintf(
410 - '<div class="content-title">%s</div>',
411 - esc_html__( 'Generate Course Description', 'learnpress' )
412 - ),
413 - 'header' => $this->html_description_step_header(),
414 - 'form' => '<form class="lp-form-generate-data-ai">',
415 - 'wrap-fields' => '<div class="lp-form-fields">',
416 - 'step_1' => $this->html_description_step_1(),
417 - 'step_2' => $this->html_description_step_2(),
418 - 'step_3' => $this->html_description_step_3(),
419 - 'step_4' => $this->html_description_step_4(),
420 - 'wrap-fields-end' => '</div>',
421 - 'buttons' => sprintf(
422 - '<div class="button-actions" data-step="1" data-step-max="4">
423 - <button class="btn btn-secondary lp-btn-step lp-hidden"
424 - data-step-show="2,3,4"
425 - data-action="prev" type="button">&larr; %s
426 - </button>
427 - <button class="btn btn-primary lp-btn-step"
428 - data-step-show="1"
429 - data-action="next" type="button">%s &rarr;
430 - </button>
431 - <button class="lp-button btn-primary lp-btn-generate-prompt lp-hidden"
432 - data-step-show="2"
433 - data-send="%s" type="button">%s
434 - </button>
435 - <button class="lp-button btn-primary lp-btn-call-open-ai lp-hidden"
436 - data-step-show="3"
437 - data-send="%s" type="button">%s
438 - </button>
439 - </div>',
440 - esc_html__( 'Previous', 'learnpress' ),
441 - esc_html__( 'Next', 'learnpress' ),
442 - Template::convert_data_to_json(
443 - [
444 - 'action' => 'openai_generate_prompt',
445 - 'lp-prompt-type' => 'course-description',
446 - 'id_url' => 'generate_prompt_openai',
447 - ]
448 - ),
449 - esc_html__( 'Generate Prompt', 'learnpress' ),
450 - Template::convert_data_to_json(
451 - [
452 - 'action' => 'openai_generate_data',
453 - 'lp-prompt-type' => 'course-description',
454 - 'target-apply' => 'set-wp-editor-content', // Click apply to apply title to this field.
455 - 'id_url' => 'submit_to_openai',
456 - ]
457 - ),
458 - esc_html__( 'Generate Description Course', 'learnpress' ),
459 - ),
460 - 'form-end' => '</form>',
461 - 'wrap-end' => '</div>',
462 - 'wrap-script-template-end' => '</script>',
463 - ];
464 -
465 - return Template::combine_components( $components );
466 - }
467 -
468 - public function html_description_step_header(): string {
469 - $components = [
470 - 'wrap' => '<div class="step-header">',
471 - 'step_1' => sprintf(
472 - '<div class="step-item active" data-step="1"><span class="step-number">1</span><span class="step-text">%s</span></div>',
473 - esc_html__( 'Course Goal', 'learnpress' )
474 - ),
475 - 'step_2' => sprintf(
476 - '<div class="step-item" data-step="2"><span class="step-number">2</span><span class="step-text">%s</span></div>',
477 - esc_html__( 'AI Settings', 'learnpress' )
478 - ),
479 - 'step_3' => sprintf(
480 - '<div class="step-item" data-step="3"><span class="step-number">3</span><span class="step-text">%s</span></div>',
481 - esc_html__( 'Prompt', 'learnpress' )
482 - ),
483 - 'step_4' => sprintf(
484 - '<div class="step-item" data-step="4"><span class="step-number">4</span><span class="step-text">%s</span></div>',
485 - esc_html__( 'Result', 'learnpress' )
486 - ),
487 - 'wrap-end' => '</div>',
488 - ];
489 -
490 - return Template::combine_components( $components );
491 - }
492 -
493 - public function html_description_step_1(): string {
494 - $options = $this->config;
495 -
496 - $components = [
497 - 'step' => '<div class="step-content active" data-step="1">',
498 - 'title' => sprintf(
499 - '<div class="step-title">%s</div>',
500 - esc_html__( 'Step 1 — Configure Course Description', 'learnpress' ),
501 - ),
502 - 'description' => sprintf(
503 - '<p class="step-description">%s</p>',
504 - esc_html__( 'Provide the information needed to generate your course description.', 'learnpress' )
505 - ),
506 - 'refer-title' => sprintf(
507 - '<div class="form-group">
508 - <label>%s</label>
509 - <input class="title-refer" type="text" name="post-title" readonly />
510 - <p class="lp-ai-warning-refer lp-hidden"><i class="lp-icon-warning"></i>%s</p>
511 - <p class="field-description">%s</p>
512 - </div>',
513 - esc_html__( 'Title refer', 'learnpress' ),
514 - esc_html__( 'The title refer to generate a relevant course description. Please enter title first', 'learnpress' ),
515 - esc_html__( 'The course title is automatically imported from the previous step. It will guide the AI to build a structured curriculum.', 'learnpress' )
516 - ),
517 - 'describe-topic' => sprintf(
518 - '<div class="form-group">
519 - <label>%s</label>
520 - <textarea type="text" name="topic" placeholder="%s"></textarea>
521 - </div>',
522 - esc_html__( 'Describe what makes this course stand out?', 'learnpress' ),
523 - esc_html__( 'Provide the main strengths or unique selling points to help the system build a compelling course description.', 'learnpress' )
524 - ),
525 - 'length' => sprintf(
526 - '<div class="form-group">
527 - <label>%s</label>
528 - <input type="text" name="length" value="1000" />
529 - <p class="field-description">%s</p>
530 - </div>',
531 - esc_html__( 'Description Length (words)', 'learnpress' ),
532 - esc_html__( 'Set the maximum number of characters for the generated description.', 'learnpress' )
533 - ),
534 - 'step_close' => '</div>',
535 - ];
536 -
537 - return Template::combine_components( $components );
538 - }
539 -
540 - public function html_description_step_2(): string {
541 - $options = $this->config;
542 -
543 - $components = [
544 - 'step' => '<div class="step-content" data-step="2">',
545 - 'title' => sprintf(
546 - '<div class="step-title">%s</div>',
547 - esc_html__( 'Step 2 — AI Settings', 'learnpress' ),
548 - ),
549 - 'description' => sprintf(
550 - '<p class="step-description">%s</p>',
551 - esc_html__( 'Configure content quality controls for ChatGPT output.', 'learnpress' )
552 - ),
553 - 'form-grid' => '<div class="form-grid">',
554 - 'audience' => sprintf(
555 - '<div class="form-group">
556 - <label>%s</label>%s
557 - <p class="field-description">%s</p>
558 - </div>',
559 - esc_html__( 'Target Audience', 'learnpress' ),
560 - AdminTemplate::html_tom_select(
561 - [
562 - 'name' => 'target_audience',
563 - 'class_name' => '',
564 - 'options' => $options['audience'] ?? [],
565 - 'default_value' => 'Students',
566 - 'multiple' => true,
567 - ]
568 - ),
569 - esc_html__( 'Identifies who will take the course so the content matches their background and skill level.', 'learnpress' ),
570 - ),
571 - 'tone' => sprintf(
572 - '<div class="form-group">
573 - <label for="swal-tone">%s</label>%s
574 - <p class="field-description">%s</p>
575 - </div>',
576 - esc_html__( 'Tone', 'learnpress' ),
577 - AdminTemplate::html_tom_select(
578 - [
579 - 'name' => 'tone',
580 - 'options' => $options['tone'] ?? [],
581 - 'multiple' => true,
582 - 'default_value' => [ 'Analytical' ],
583 - ]
584 - ),
585 - esc_html__( 'Controls the writing style (e.g., friendly, formal, story-telling) so the content matches your brand and audience.', 'learnpress' )
586 - ),
587 - 'language' => sprintf(
588 - '<div class="form-group">
589 - <label>%s</label>%s
590 - <p class="field-description">%s</p>
591 - </div>',
592 - esc_html__( 'Language', 'learnpress' ),
593 - AdminTemplate::html_tom_select(
594 - [
595 - 'name' => 'language',
596 - 'options' => $options['language'] ?? [],
597 - ]
598 - ),
599 - esc_html__( 'Sets the output language for all generated course content.', 'learnpress' )
600 - ),
601 - 'outputs' => sprintf(
602 - '<div class="form-group">
603 - <label>%s</label>%s
604 - </div>',
605 - esc_html__( 'Outputs', 'learnpress' ),
606 - '<input name="outputs" value="2" />'
607 - ),
608 - 'form-grid-end' => '</div>',
609 - 'step_close' => '</div>',
610 - ];
611 -
612 - return Template::combine_components( $components );
613 - }
614 -
615 - public function html_description_step_3(): string {
616 - $options = $this->config;
617 -
618 - $components = [
619 - 'step' => '<div class="step-content" data-step="3">',
620 - 'title' => sprintf(
621 - '<div class="step-title">%s</div>',
622 - esc_html__( 'Step 3 — Prompt Generated', 'learnpress' ),
623 - ),
624 - 'prompt' => sprintf(
625 - '<div class="form-group">
626 - <label>%s</label>%s
627 - <i>%s</i>
628 - </div>',
629 - esc_html__( 'Generated Prompt', 'learnpress' ),
630 - '<textarea name="lp-openai-prompt-generated-field"></textarea>',
631 - __( 'Shows the auto-generated AI prompt, allowing further adjustments before submission.', 'learnpress' )
632 - ),
633 - 'step_close' => '</div>',
634 - ];
635 -
636 - return Template::combine_components( $components );
637 - }
638 -
639 - public function html_description_step_4(): string {
640 - $options = $this->config;
641 -
642 - $components = [
643 - 'step' => '<div class="step-content" data-step="4">',
644 - 'title' => sprintf(
645 - '<div class="step-title">%s</div>',
646 - esc_html__( 'Step 4 — Result', 'learnpress' ),
647 - ),
648 - 'results' => '<div class="lp-ai-generated-results"></div>',
649 - 'step_close' => '</div>',
650 - ];
651 -
652 - return Template::combine_components( $components );
653 - }
654 -
655 - /***************** Image *****************/
656 - public function html_edit_image_via_ai(): string {
657 - $components = [
658 - 'wrap-script-template' => '<script type="text/template" id="lp-tmpl-edit-image-ai">',
659 - 'wrap' => '<div class="lp-generate-data-ai-wrap">',
660 - 'btn-close' =>
661 - '<button type="button" class="lp-btn-close-ai-popup">
662 - <i class="lp-icon-remove"></i>
663 - </button>',
664 - 'h2' => sprintf(
665 - '<div class="content-title">%s</div>',
666 - esc_html__( 'Generate Course Image', 'learnpress' )
667 - ),
668 - 'header' => $this->html_image_step_header(), // You can add header if needed.
669 - 'form' => '<form class="lp-form-generate-data-ai">',
670 - 'wrap-fields' => '<div class="lp-form-fields">',
671 - 'step-1' => $this->html_image_step_1(),
672 - 'step-2' => $this->html_image_step_2(),
673 - 'step-3' => $this->html_image_step_3(),
674 - 'wrap-fields-end' => '</div>',
675 - 'buttons' => sprintf(
676 - '<div class="button-actions" data-step="1" data-step-max="3">
677 - <button class="btn btn-secondary lp-btn-step lp-hidden"
678 - data-step-show="2,3"
679 - data-action="prev" type="button">&larr; %s
680 - </button>
681 - <button class="btn btn-primary lp-btn-step lp-hidden"
682 - data-step-show="0"
683 - data-action="next" type="button">%s &rarr;
684 - </button>
685 - <button class="lp-button btn-primary lp-btn-generate-prompt"
686 - data-step-show="1"
687 - data-send="%s" type="button">%s
688 - </button>
689 - <button class="lp-button btn-primary lp-btn-call-open-ai lp-hidden"
690 - data-step-show="2"
691 - data-send="%s" type="button">%s
692 - </button>
693 - </div>',
694 - esc_html__( 'Previous', 'learnpress' ),
695 - esc_html__( 'Next', 'learnpress' ),
696 - Template::convert_data_to_json(
697 - [
698 - 'action' => 'openai_generate_prompt',
699 - 'lp-prompt-type' => 'course-image',
700 - 'id_url' => 'generate_prompt_openai',
701 - ]
702 - ),
703 - esc_html__( 'Generate Prompt', 'learnpress' ),
704 - Template::convert_data_to_json(
705 - [
706 - 'action' => 'openai_generate_image',
707 - 'lp-prompt-type' => 'course-image',
708 - 'target-apply' => 'set-wp-editor-content', // Click apply to apply title to this field.
709 - 'id_url' => 'submit_to_openai',
710 - ]
711 - ),
712 - esc_html__( 'Generate Image Course', 'learnpress' ),
713 - ),
714 - 'post-id' => sprintf(
715 - '<input type="hidden" name="post-id" value="%d" />',
716 - get_the_ID()
717 - ),
718 - 'form-end' => '</form>',
719 - 'wrap-end' => '</div>',
720 - 'wrap-script-template-end' => '</script>',
721 - ];
722 -
723 - return Template::combine_components( $components );
724 - }
725 -
726 - public function html_image_step_header(): string {
727 - $components = [
728 - 'wrap' => '<div class="step-header">',
729 - 'step_1' => sprintf(
730 - '<div class="step-item active" data-step="1"><span class="step-number">1</span><span class="step-text">%s</span></div>',
731 - esc_html__( 'Course Image config', 'learnpress' )
732 - ),
733 - 'step_2' => sprintf(
734 - '<div class="step-item" data-step="2"><span class="step-number">2</span><span class="step-text">%s</span></div>',
735 - esc_html__( 'Prompt', 'learnpress' )
736 - ),
737 - 'step_3' => sprintf(
738 - '<div class="step-item" data-step="3"><span class="step-number">3</span><span class="step-text">%s</span></div>',
739 - esc_html__( 'Result', 'learnpress' )
740 - ),
741 - 'wrap-end' => '</div>',
742 - ];
743 -
744 - return Template::combine_components( $components );
745 - }
746 -
747 - public function html_image_step_1(): string {
748 - $model_type = LP_Settings::instance()->get( 'open_ai_image_model_type' );
749 - $options = $this->config;
750 - $size_opts = $options[ "image-size-$model_type" ] ?? [];
751 - $quality_opts = $options[ "image-quality-$model_type" ] ?? $options['image-quality'] ?? [];
752 -
753 - $components = [
754 - 'step' => '<div class="step-content active" data-step="1">',
755 - 'title' => sprintf(
756 - '<div class="step-title">%s</div>',
757 - esc_html__( 'Step 1 — Config Image', 'learnpress' ),
758 - ),
759 - 'description' => sprintf(
760 - '<p class="step-description">%s</p>',
761 - esc_html__( 'Config your image you want, data will refer course title, course description to generate image.', 'learnpress' )
762 - ),
763 - 'from-title' => sprintf(
764 - '<div class="form-group">
765 - <label>%s</label>
766 - <input class="title-refer" type="text" name="post-title" readonly />
767 - <p class="lp-ai-warning-refer lp-hidden"><i class="lp-icon-warning"></i>%s</p>
768 - <p class="field-description">%s</p>
769 - </div>',
770 - esc_html__( 'Title Refer', 'learnpress' ),
771 - esc_html__( 'The title refer to generate a relevant course image. Please enter title first', 'learnpress' ),
772 - esc_html__( 'The current course title that will be used as reference during image generation.', 'learnpress' )
773 - ),
774 - 'goal' => sprintf(
775 - '<div class="form-group">
776 - <label>%s</label>
777 - <textarea type="text" name="goal" placeholder="%s"></textarea>
778 - </div>',
779 - esc_html__( 'Goal', 'learnpress' ),
780 - esc_html__( 'A brief description of the image you want to generate.', 'learnpress' )
781 - ),
782 - 'form-grid' => '<div class="form-grid">',
783 - 'style' => sprintf(
784 - '<div class="form-group">
785 - <label>%s</label>
786 - %s
787 - <p class="field-description">%s</p>
788 - </div>',
789 - esc_html__( 'Style', 'learnpress' ),
790 - AdminTemplate::html_tom_select(
791 - [
792 - 'name' => 'style',
793 - 'options' => $options['image-style'] ?? [],
794 - 'default_value' => 'Realistic',
795 - ]
796 - ),
797 - esc_html__( 'Select the visual style such as modern, minimalist, illustration, 3D, etc.', 'learnpress' )
798 - ),
799 - /*'write-requirement' => sprintf(
800 - '<div class="form-group">
801 - <label>%s</label>
802 - <input type="text" name="topic" placeholder="%s" />
803 - <p class="field-description">%s</p>
804 - </div>',
805 - esc_html__( 'Images or icons should be include', 'learnpress' ),
806 - esc_html__( 'e.g., books, laptop, graduation cap', 'learnpress' ),
807 - esc_html__( 'List the specific elements or icons that should appear in the generated image.', 'learnpress' )
808 - ),*/
809 - 'size' => sprintf(
810 - '<div class="form-group">
811 - <label>%s</label>
812 - %s
813 - <p class="field-description">%s</p>
814 - </div>',
815 - esc_html__( 'Size', 'learnpress' ),
816 - AdminTemplate::html_tom_select(
817 - [
818 - 'name' => 'size',
819 - 'options' => $size_opts,
820 - ]
821 - ),
822 - esc_html__( 'Set the output.', 'learnpress' )
823 - ),
824 - 'quality' => sprintf(
825 - '<div class="form-group">
826 - <label>%s</label>
827 - %s
828 - <p class="field-description">%s</p>
829 - </div>',
830 - esc_html__( 'Quality', 'learnpress' ),
831 - AdminTemplate::html_tom_select(
832 - [
833 - 'name' => 'quality',
834 - 'options' => $quality_opts,
835 - ]
836 - ),
837 - esc_html__( 'Select the desired image quality such as standard, high, or premium.', 'learnpress' )
838 - ),
839 - 'outputs' => sprintf(
840 - '<div class="form-group">
841 - <label>%s</label>
842 - <input name="outputs" value="2" type="number" />
843 - <p class="field-description">%s</p>
844 - </div>',
845 - esc_html__( 'Outputs', 'learnpress' ),
846 - esc_html__( 'Number of images you want the system to generate (model dall-e-3 only 1 supported).', 'learnpress' )
847 - ),
848 - 'form-grid-end' => '</div>',
849 - 'step_close' => '</div>',
850 - ];
851 -
852 - return Template::combine_components( $components );
853 - }
854 -
855 - public function html_image_step_2(): string {
856 - $options = $this->config;
857 -
858 - $components = [
859 - 'step' => '<div class="step-content" data-step="2">',
860 - 'title' => sprintf(
861 - '<div class="step-title">%s</div>',
862 - esc_html__( 'Step 2 — Prompt Generated', 'learnpress' ),
863 - ),
864 - 'prompt' => sprintf(
865 - '<div class="form-group">
866 - <label>%s</label>%s
867 - <i>%s</i>
868 - </div>',
869 - esc_html__( 'Generated Prompt', 'learnpress' ),
870 - '<textarea name="lp-openai-prompt-generated-field"></textarea>',
871 - __( 'Shows the auto-generated AI prompt, allowing further adjustments before submission.', 'learnpress' )
872 - ),
873 - 'step_close' => '</div>',
874 - ];
875 -
876 - return Template::combine_components( $components );
877 - }
878 -
879 - public function html_image_step_3(): string {
880 - $options = $this->config;
881 -
882 - $components = [
883 - 'step' => '<div class="step-content" data-step="3">',
884 - 'title' => sprintf(
885 - '<div class="step-title">%s</div>',
886 - esc_html__( 'Step 3 — Result', 'learnpress' ),
887 - ),
888 - 'description' => sprintf(
889 - '<p class="step-description">%s</p>',
890 - esc_html__( 'Note: when applying an image, the process can be very slow (about 1 minute or more), depends on the image size. Please wait until it finishes.', 'learnpress' )
891 - ),
892 - 'results' => '<div class="lp-ai-generated-results"></div>',
893 - 'step_close' => '</div>',
894 - ];
895 -
896 - return Template::combine_components( $components );
897 - }
898 -
899 - public function html_feature_image_created( $args ): string {
900 - $src = $args['src'] ?? '';
901 - $post_id = $args['post-id'] ?? '';
902 - $attachment_id = $args['attachment-id'] ?? '';
903 -
904 - $section = [
905 - 'wrap' => '<div class="inside">',
906 - 'preview' => sprintf(
907 - '<p class="hide-if-no-js">
908 - <a href="%s" id="set-post-thumbnail" aria-describedby="set-post-thumbnail-desc" class="thickbox">
909 - <img width="266" height="266" src="%s" alt="" />
910 - </a>
911 - </p>',
912 - admin_url( "media-upload.php?post_id=$post_id&amp;type=image&amp;TB_iframe=1" ),
913 - $src
914 - ),
915 - 'desc' => '<p class="hide-if-no-js howto" id="set-post-thumbnail-desc">Click the image to edit or update</p>',
916 - 'remove' => sprintf(
917 - '<p class="hide-if-no-js"><a href="#" id="remove-post-thumbnail">%s</a></p>',
918 - __( 'Remove featured image' )
919 - ),
920 - 'input' => sprintf(
921 - '<input type="hidden" id="_thumbnail_id" name="_thumbnail_id" value="%d" />',
922 - $attachment_id
923 - ),
924 - 'wrap_end' => '</div>',
925 - ];
926 -
927 - return Template::combine_components( $section );
928 - }
929 -
930 - /***************** Curriculum *****************/
931 - public function html_edit_curriculum_via_ai(): string {
932 - $components = [
933 - 'wrap-script-template' => '<script type="text/template" id="lp-tmpl-edit-curriculum-ai">',
934 - 'wrap' => '<div class="lp-generate-data-ai-wrap">',
935 - 'h2' => sprintf(
936 - '<div class="content-title">%s</div>',
937 - esc_html__( 'Generate Course Curriculum', 'learnpress' )
938 - ),
939 - 'header' => '', // You can add header if needed.
940 - 'form' => '<form class="lp-form-generate-data-ai">',
941 - 'wrap-fields' => '<div class="lp-form-fields">',
942 - // Add steps for curriculum generation here.
943 - 'wrap-fields-end' => '</div>',
944 - 'buttons' => sprintf(
945 - '<div class="button-actions" data-step="1" data-step-max="1">
946 - <button class="lp-button btn-primary lp-btn-call-open-ai lp-hidden"
947 - data-send="%s" type="button">%s
948 - </button>
949 - </div>',
950 - Template::convert_data_to_json(
951 - [
952 - 'action' => 'openai_generate_data',
953 - 'lp-prompt-type' => 'course-curriculum',
954 - 'target-apply' => 'set-course-curriculum', // Click apply to apply curriculum to this field.
955 - 'id_url' => 'submit_to_openai',
956 - ]
957 - ),
958 - esc_html__( 'Generate Course Curriculum', 'learnpress' ),
959 - ),
960 - 'post-id' => sprintf(
961 - '<input type="hidden" name="post-id" value="%d" />',
962 - get_the_ID()
963 - ),
964 - 'form-end' => '</form>',
965 - 'wrap-end' => '</div>',
966 - 'wrap-script-template-end' => '</script>',
967 - ];
968 -
969 - return Template::combine_components( $components );
970 - }
971 -}
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 AdminEditWithAITemplate
15 + *
16 + * @since 4.2.9
17 + * @version 1.1.0
18 + */
19 +class AdminEditWithAITemplate {
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 + public function layout_popup() {
35 + try {
36 + if ( ! function_exists( 'get_current_screen' ) ) {
37 + return;
38 + }
39 +
40 + $screen = get_current_screen();
41 + $screens = [
42 + LP_COURSE_CPT,
43 + ];
44 + if ( ! $screen || in_array( $screen, $screens ) ) {
45 + return;
46 + }
47 +
48 + $this->config = Config::instance()->get( 'open-ai-modal', 'settings' );
49 + echo $this->html_edit_title_via_ai();
50 + echo $this->html_edit_description_via_ai();
51 + echo $this->html_edit_image_via_ai();
52 + echo $this->html_edit_curriculum_via_ai();
53 + } catch ( Throwable $e ) {
54 + LP_Debug::error_log( $e );
55 + }
56 + }
57 +
58 + /**
59 + * Render AI templates for frontend contexts (e.g. Course Builder).
60 + *
61 + * @param array $template_types Supported: title, description, image, curriculum.
62 + *
63 + * @return string
64 + * @since 4.3.0
65 + */
66 + public function render_for_frontend( array $template_types = [ 'title', 'description' ] ): string {
67 + try {
68 + $this->config = Config::instance()->get( 'open-ai-modal', 'settings' );
69 +
70 + $template_map = [
71 + 'title' => 'html_edit_title_via_ai',
72 + 'description' => 'html_edit_description_via_ai',
73 + 'image' => 'html_edit_image_via_ai',
74 + 'curriculum' => 'html_edit_curriculum_via_ai',
75 + ];
76 +
77 + $output = '';
78 + foreach ( $template_types as $template_type ) {
79 + $method = $template_map[ $template_type ] ?? '';
80 + if ( ! $method || ! method_exists( $this, $method ) ) {
81 + continue;
82 + }
83 +
84 + $output .= $this->{$method}();
85 + }
86 +
87 + return $output;
88 + } catch ( Throwable $e ) {
89 + LP_Debug::error_log( $e );
90 + }
91 +
92 + return '';
93 + }
94 +
95 + /**
96 + * HTML generate title with AI.
97 + *
98 + * @return string
99 + */
100 + public function html_edit_title_via_ai(): string {
101 + $components = [
102 + 'wrap-script-template' => '<script type="text/template" id="lp-tmpl-edit-title-ai">',
103 + 'wrap' => '<div class="lp-generate-data-ai-wrap">',
104 + 'btn-close' =>
105 + '<button type="button" class="lp-btn-close-ai-popup">
106 + <i class="lp-icon-remove"></i>
107 + </button>',
108 + 'h2' => sprintf(
109 + '<div class="content-title">%s</div>',
110 + esc_html__( 'Generate Course Title', 'learnpress' )
111 + ),
112 + 'header' => $this->html_title_step_header(),
113 + 'form' => '<form class="lp-form-generate-data-ai">',
114 + 'wrap-fields' => '<div class="lp-form-fields">',
115 + 'step_1' => $this->html_title_step_1(),
116 + 'step_2' => $this->html_title_step_2(),
117 + 'step_3' => $this->html_title_step_3(),
118 + 'step_4' => $this->html_title_step_4(),
119 + 'wrap-fields-end' => '</div>',
120 + 'buttons' => sprintf(
121 + '<div class="button-actions" data-step="1" data-step-max="4">
122 + <button class="btn btn-secondary lp-btn-step lp-hidden"
123 + data-step-show="2,3,4"
124 + data-action="prev" type="button">&larr; %s
125 + </button>
126 + <button class="btn btn-primary lp-btn-step"
127 + data-step-show="1"
128 + data-action="next" type="button">%s &rarr;
129 + </button>
130 + <button class="lp-button btn-primary lp-btn-generate-prompt lp-hidden"
131 + data-step-show="2"
132 + data-send="%s" type="button">%s
133 + </button>
134 + <button class="lp-button btn-primary lp-btn-call-open-ai lp-hidden"
135 + data-step-show="3"
136 + data-send="%s" type="button">%s
137 + </button>
138 + </div>',
139 + esc_html__( 'Previous', 'learnpress' ),
140 + esc_html__( 'Next', 'learnpress' ),
141 + Template::convert_data_to_json(
142 + [
143 + 'action' => 'openai_generate_prompt',
144 + 'lp-prompt-type' => 'course-title', // define type prompt to generate title.
145 + 'id_url' => 'generate_prompt_openai',
146 + ]
147 + ),
148 + esc_html__( 'Generate Prompt', 'learnpress' ),
149 + Template::convert_data_to_json(
150 + [
151 + 'action' => 'openai_generate_data',
152 + 'lp-prompt-type' => 'course-title', // define type prompt to generate title.
153 + 'target-apply' => 'set-wp-title', // Click apply to apply title to this field.
154 + 'id_url' => 'submit_to_openai',
155 + ]
156 + ),
157 + esc_html__( 'Generate Title Course', 'learnpress' ),
158 + ),
159 + 'form-end' => '</form>',
160 + 'wrap-end' => '</div>',
161 + 'wrap-script-template-end' => '</script>',
162 + ];
163 +
164 + return Template::combine_components( $components );
165 + }
166 +
167 + public function html_title_step_header(): string {
168 + $components = [
169 + 'wrap' => '<div class="step-header">',
170 + 'step_1' => sprintf(
171 + '<div class="step-item active" data-step="1"><span class="step-number">1</span><span class="step-text">%s</span></div>',
172 + esc_html__( 'Course Goal', 'learnpress' )
173 + ),
174 + 'step_2' => sprintf(
175 + '<div class="step-item" data-step="2"><span class="step-number">2</span><span class="step-text">%s</span></div>',
176 + esc_html__( 'AI Settings', 'learnpress' )
177 + ),
178 + 'step_3' => sprintf(
179 + '<div class="step-item" data-step="3"><span class="step-number">3</span><span class="step-text">%s</span></div>',
180 + esc_html__( 'Prompt', 'learnpress' )
181 + ),
182 + 'step_4' => sprintf(
183 + '<div class="step-item" data-step="4"><span class="step-number">4</span><span class="step-text">%s</span></div>',
184 + esc_html__( 'Result', 'learnpress' )
185 + ),
186 + 'wrap-end' => '</div>',
187 + ];
188 +
189 + return Template::combine_components( $components );
190 + }
191 +
192 + public function html_title_step_1(): string {
193 + $options = $this->config;
194 +
195 + $components = [
196 + 'step' => '<div class="step-content active" data-step="1">',
197 + 'title' => sprintf(
198 + '<div class="step-title">%s</div>',
199 + esc_html__( 'Step 1 — Configure Course Title', 'learnpress' ),
200 + ),
201 + 'description' => sprintf(
202 + '<p class="step-description">%s</p>',
203 + esc_html__( 'Provide the basic information to generate your course title.', 'learnpress' )
204 + ),
205 + 'describe-topic' => sprintf(
206 + '<div class="form-group">
207 + <label>%s</label>
208 + <textarea type="text" name="topic" placeholder="%s"></textarea>
209 + </div>',
210 + esc_html__( 'Describe what your course is about', 'learnpress' ),
211 + esc_html__( 'Provide a short explanation of the subject or skills your course covers. This helps AI understand the overall direction of your title.', 'learnpress' )
212 + ),
213 + 'describe-goals' => sprintf(
214 + '<div class="form-group">
215 + <label>%s</label>
216 + <textarea type="text" name="goals" placeholder="%s"></textarea>
217 + </div>',
218 + esc_html__( 'Describe the main goals of your course', 'learnpress' ),
219 + esc_html__( 'Summarize what learners will achieve. AI uses this to make the title more accurate and meaningful.', 'learnpress' )
220 + ),
221 + 'length' => sprintf(
222 + '<div class="form-group">
223 + <label>%s</label>
224 + <input type="text" name="length" value="60" />
225 + <p class="field-description">%s</p>
226 + </div>',
227 + esc_html__( 'Title Length (characters)', 'learnpress' ),
228 + esc_html__( 'Set the maximum number of characters for the generated course title. Ideal for SEO and platform display constraints.', 'learnpress' )
229 + ),
230 + 'step_close' => '</div>',
231 + ];
232 +
233 + return Template::combine_components( $components );
234 + }
235 +
236 + public function html_title_step_2(): string {
237 + $options = $this->config;
238 +
239 + $components = [
240 + 'step' => '<div class="step-content" data-step="2">',
241 + 'title' => sprintf(
242 + '<div class="step-title">%s</div>',
243 + esc_html__( 'Step 2 — AI Settings', 'learnpress' ),
244 + ),
245 + 'description' => sprintf(
246 + '<p class="step-description">%s</p>',
247 + esc_html__( 'Configure content quality controls for ChatGPT output.', 'learnpress' )
248 + ),
249 + 'form-grid' => '<div class="form-grid">',
250 + 'audience' => sprintf(
251 + '<div class="form-group">
252 + <label>%s</label>%s
253 + <p class="field-description">%s</p>
254 + </div>',
255 + esc_html__( 'Target Audience', 'learnpress' ),
256 + AdminTemplate::html_tom_select(
257 + [
258 + 'name' => 'target_audience',
259 + 'class_name' => '',
260 + 'options' => $options['audience'] ?? [],
261 + 'default_value' => 'Students',
262 + 'multiple' => true,
263 + ]
264 + ),
265 + esc_html__( 'Identifies who will take the course so the content matches their background and skill level.', 'learnpress' ),
266 + ),
267 + 'tone' => sprintf(
268 + '<div class="form-group">
269 + <label for="swal-tone">%s</label>%s
270 + <p class="field-description">%s</p>
271 + </div>',
272 + esc_html__( 'Tone', 'learnpress' ),
273 + AdminTemplate::html_tom_select(
274 + [
275 + 'name' => 'tone',
276 + 'options' => $options['tone'] ?? [],
277 + 'multiple' => true,
278 + 'default_value' => [ 'Analytical' ],
279 + ]
280 + ),
281 + esc_html__( 'Controls the writing style (e.g., friendly, formal, story-telling) so the content matches your brand and audience.', 'learnpress' )
282 + ),
283 + 'language' => sprintf(
284 + '<div class="form-group">
285 + <label>%s</label>%s
286 + <p class="field-description">%s</p>
287 + </div>',
288 + esc_html__( 'Language', 'learnpress' ),
289 + AdminTemplate::html_tom_select(
290 + [
291 + 'name' => 'language',
292 + 'options' => $options['language'] ?? [],
293 + ]
294 + ),
295 + esc_html__( 'Sets the output language for all generated course content.', 'learnpress' )
296 + ),
297 + 'outputs' => sprintf(
298 + '<div class="form-group">
299 + <label>%s</label>%s
300 + <p class="field-description">%s</p>
301 + </div>',
302 + esc_html__( 'Outputs', 'learnpress' ),
303 + '<input name="outputs" value="2" />',
304 + esc_html__( 'Select how many title options the system will generate for you.', 'learnpress' )
305 + ),
306 + 'form-grid-end' => '</div>',
307 + 'step_close' => '</div>',
308 + ];
309 +
310 + return Template::combine_components( $components );
311 + }
312 +
313 + public function html_title_step_3(): string {
314 + $options = $this->config;
315 +
316 + $components = [
317 + 'step' => '<div class="step-content" data-step="3">',
318 + 'title' => sprintf(
319 + '<div class="step-title">%s</div>',
320 + esc_html__( 'Step 3 — Prompt Generated', 'learnpress' ),
321 + ),
322 + 'prompt' => sprintf(
323 + '<div class="form-group">
324 + <label>%s</label>%s
325 + <i>%s</i>
326 + </div>',
327 + esc_html__( 'Generated Prompt', 'learnpress' ),
328 + '<textarea name="lp-openai-prompt-generated-field"></textarea>',
329 + __( 'Shows the auto-generated AI prompt, allowing further adjustments before submission.', 'learnpress' )
330 + ),
331 + 'step_close' => '</div>',
332 + ];
333 +
334 + return Template::combine_components( $components );
335 + }
336 +
337 + public function html_title_step_4(): string {
338 + $options = $this->config;
339 +
340 + $components = [
341 + 'step' => '<div class="step-content" data-step="4">',
342 + 'title' => sprintf(
343 + '<div class="step-title">%s</div>',
344 + esc_html__( 'Step 4 — Result', 'learnpress' ),
345 + ),
346 + 'results' => '<div class="lp-ai-generated-results"></div>',
347 + 'step_close' => '</div>',
348 + ];
349 +
350 + return Template::combine_components( $components );
351 + }
352 +
353 + /**
354 + * HTML list results openAI returned.
355 + *
356 + * @param array $args
357 + *
358 + * @return string
359 + */
360 + public function html_list_results( array $args ): string {
361 + $index = $args['index'] ?? 0;
362 + $value = $args['value'] ?? '';
363 + // Target is element html to apply value.
364 + $target = $args['target-apply'] ?? '';
365 +
366 + $section = [
367 + 'wrap' => '<div class="lp-ai-generated-result-item form-group">',
368 + 'label' => sprintf(
369 + '<label>%s</label>',
370 + sprintf( __( 'Result %d', 'learnpress' ), $index + 1 )
371 + ),
372 + 'textarea' => sprintf(
373 + '<textarea class="lp-ai-string-result" cols="3">%s</textarea>',
374 + esc_attr( $value )
375 + ),
376 + 'copy_button' => sprintf(
377 + '<button class="button lp-btn-copy" data-copy="%s" type="button">%s</button>',
378 + esc_attr( $value ),
379 + __( 'Copy', 'learnpress' )
380 + ),
381 + 'apply_button' => sprintf(
382 + '<button class="button lp-btn-apply button-primary"
383 + data-apply="%s" type="button" data-target="%s">%s
384 + </button>',
385 + esc_attr( $value ),
386 + esc_attr( $target ),
387 + __( 'Apply', 'learnpress' )
388 + ),
389 + 'wrap_end' => '</div>',
390 + ];
391 +
392 + return Template::combine_components( $section );
393 + }
394 +
395 + /***************** Description *****************/
396 + /**
397 + * HTML generate title with AI.
398 + *
399 + * @return string
400 + */
401 + public function html_edit_description_via_ai(): string {
402 + $components = [
403 + 'wrap-script-template' => '<script type="text/template" id="lp-tmpl-edit-description-ai">',
404 + 'wrap' => '<div class="lp-generate-data-ai-wrap">',
405 + 'btn-close' =>
406 + '<button type="button" class="lp-btn-close-ai-popup">
407 + <i class="lp-icon-remove"></i>
408 + </button>',
409 + 'h2' => sprintf(
410 + '<div class="content-title">%s</div>',
411 + esc_html__( 'Generate Course Description', 'learnpress' )
412 + ),
413 + 'header' => $this->html_description_step_header(),
414 + 'form' => '<form class="lp-form-generate-data-ai">',
415 + 'wrap-fields' => '<div class="lp-form-fields">',
416 + 'step_1' => $this->html_description_step_1(),
417 + 'step_2' => $this->html_description_step_2(),
418 + 'step_3' => $this->html_description_step_3(),
419 + 'step_4' => $this->html_description_step_4(),
420 + 'wrap-fields-end' => '</div>',
421 + 'buttons' => sprintf(
422 + '<div class="button-actions" data-step="1" data-step-max="4">
423 + <button class="btn btn-secondary lp-btn-step lp-hidden"
424 + data-step-show="2,3,4"
425 + data-action="prev" type="button">&larr; %s
426 + </button>
427 + <button class="btn btn-primary lp-btn-step"
428 + data-step-show="1"
429 + data-action="next" type="button">%s &rarr;
430 + </button>
431 + <button class="lp-button btn-primary lp-btn-generate-prompt lp-hidden"
432 + data-step-show="2"
433 + data-send="%s" type="button">%s
434 + </button>
435 + <button class="lp-button btn-primary lp-btn-call-open-ai lp-hidden"
436 + data-step-show="3"
437 + data-send="%s" type="button">%s
438 + </button>
439 + </div>',
440 + esc_html__( 'Previous', 'learnpress' ),
441 + esc_html__( 'Next', 'learnpress' ),
442 + Template::convert_data_to_json(
443 + [
444 + 'action' => 'openai_generate_prompt',
445 + 'lp-prompt-type' => 'course-description',
446 + 'id_url' => 'generate_prompt_openai',
447 + ]
448 + ),
449 + esc_html__( 'Generate Prompt', 'learnpress' ),
450 + Template::convert_data_to_json(
451 + [
452 + 'action' => 'openai_generate_data',
453 + 'lp-prompt-type' => 'course-description',
454 + 'target-apply' => 'set-wp-editor-content', // Click apply to apply title to this field.
455 + 'id_url' => 'submit_to_openai',
456 + ]
457 + ),
458 + esc_html__( 'Generate Description Course', 'learnpress' ),
459 + ),
460 + 'form-end' => '</form>',
461 + 'wrap-end' => '</div>',
462 + 'wrap-script-template-end' => '</script>',
463 + ];
464 +
465 + return Template::combine_components( $components );
466 + }
467 +
468 + public function html_description_step_header(): string {
469 + $components = [
470 + 'wrap' => '<div class="step-header">',
471 + 'step_1' => sprintf(
472 + '<div class="step-item active" data-step="1"><span class="step-number">1</span><span class="step-text">%s</span></div>',
473 + esc_html__( 'Course Goal', 'learnpress' )
474 + ),
475 + 'step_2' => sprintf(
476 + '<div class="step-item" data-step="2"><span class="step-number">2</span><span class="step-text">%s</span></div>',
477 + esc_html__( 'AI Settings', 'learnpress' )
478 + ),
479 + 'step_3' => sprintf(
480 + '<div class="step-item" data-step="3"><span class="step-number">3</span><span class="step-text">%s</span></div>',
481 + esc_html__( 'Prompt', 'learnpress' )
482 + ),
483 + 'step_4' => sprintf(
484 + '<div class="step-item" data-step="4"><span class="step-number">4</span><span class="step-text">%s</span></div>',
485 + esc_html__( 'Result', 'learnpress' )
486 + ),
487 + 'wrap-end' => '</div>',
488 + ];
489 +
490 + return Template::combine_components( $components );
491 + }
492 +
493 + public function html_description_step_1(): string {
494 + $options = $this->config;
495 +
496 + $components = [
497 + 'step' => '<div class="step-content active" data-step="1">',
498 + 'title' => sprintf(
499 + '<div class="step-title">%s</div>',
500 + esc_html__( 'Step 1 — Configure Course Description', 'learnpress' ),
501 + ),
502 + 'description' => sprintf(
503 + '<p class="step-description">%s</p>',
504 + esc_html__( 'Provide the information needed to generate your course description.', 'learnpress' )
505 + ),
506 + 'refer-title' => sprintf(
507 + '<div class="form-group">
508 + <label>%s</label>
509 + <input class="title-refer" type="text" name="post-title" readonly />
510 + <p class="lp-ai-warning-refer lp-hidden"><i class="lp-icon-warning"></i>%s</p>
511 + <p class="field-description">%s</p>
512 + </div>',
513 + esc_html__( 'Title refer', 'learnpress' ),
514 + esc_html__( 'The title refer to generate a relevant course description. Please enter title first', 'learnpress' ),
515 + esc_html__( 'The course title is automatically imported from the previous step. It will guide the AI to build a structured curriculum.', 'learnpress' )
516 + ),
517 + 'describe-topic' => sprintf(
518 + '<div class="form-group">
519 + <label>%s</label>
520 + <textarea type="text" name="topic" placeholder="%s"></textarea>
521 + </div>',
522 + esc_html__( 'Describe what makes this course stand out?', 'learnpress' ),
523 + esc_html__( 'Provide the main strengths or unique selling points to help the system build a compelling course description.', 'learnpress' )
524 + ),
525 + 'length' => sprintf(
526 + '<div class="form-group">
527 + <label>%s</label>
528 + <input type="text" name="length" value="1000" />
529 + <p class="field-description">%s</p>
530 + </div>',
531 + esc_html__( 'Description Length (words)', 'learnpress' ),
532 + esc_html__( 'Set the maximum number of characters for the generated description.', 'learnpress' )
533 + ),
534 + 'step_close' => '</div>',
535 + ];
536 +
537 + return Template::combine_components( $components );
538 + }
539 +
540 + public function html_description_step_2(): string {
541 + $options = $this->config;
542 +
543 + $components = [
544 + 'step' => '<div class="step-content" data-step="2">',
545 + 'title' => sprintf(
546 + '<div class="step-title">%s</div>',
547 + esc_html__( 'Step 2 — AI Settings', 'learnpress' ),
548 + ),
549 + 'description' => sprintf(
550 + '<p class="step-description">%s</p>',
551 + esc_html__( 'Configure content quality controls for ChatGPT output.', 'learnpress' )
552 + ),
553 + 'form-grid' => '<div class="form-grid">',
554 + 'audience' => sprintf(
555 + '<div class="form-group">
556 + <label>%s</label>%s
557 + <p class="field-description">%s</p>
558 + </div>',
559 + esc_html__( 'Target Audience', 'learnpress' ),
560 + AdminTemplate::html_tom_select(
561 + [
562 + 'name' => 'target_audience',
563 + 'class_name' => '',
564 + 'options' => $options['audience'] ?? [],
565 + 'default_value' => 'Students',
566 + 'multiple' => true,
567 + ]
568 + ),
569 + esc_html__( 'Identifies who will take the course so the content matches their background and skill level.', 'learnpress' ),
570 + ),
571 + 'tone' => sprintf(
572 + '<div class="form-group">
573 + <label for="swal-tone">%s</label>%s
574 + <p class="field-description">%s</p>
575 + </div>',
576 + esc_html__( 'Tone', 'learnpress' ),
577 + AdminTemplate::html_tom_select(
578 + [
579 + 'name' => 'tone',
580 + 'options' => $options['tone'] ?? [],
581 + 'multiple' => true,
582 + 'default_value' => [ 'Analytical' ],
583 + ]
584 + ),
585 + esc_html__( 'Controls the writing style (e.g., friendly, formal, story-telling) so the content matches your brand and audience.', 'learnpress' )
586 + ),
587 + 'language' => sprintf(
588 + '<div class="form-group">
589 + <label>%s</label>%s
590 + <p class="field-description">%s</p>
591 + </div>',
592 + esc_html__( 'Language', 'learnpress' ),
593 + AdminTemplate::html_tom_select(
594 + [
595 + 'name' => 'language',
596 + 'options' => $options['language'] ?? [],
597 + ]
598 + ),
599 + esc_html__( 'Sets the output language for all generated course content.', 'learnpress' )
600 + ),
601 + 'outputs' => sprintf(
602 + '<div class="form-group">
603 + <label>%s</label>%s
604 + </div>',
605 + esc_html__( 'Outputs', 'learnpress' ),
606 + '<input name="outputs" value="2" />'
607 + ),
608 + 'form-grid-end' => '</div>',
609 + 'step_close' => '</div>',
610 + ];
611 +
612 + return Template::combine_components( $components );
613 + }
614 +
615 + public function html_description_step_3(): string {
616 + $options = $this->config;
617 +
618 + $components = [
619 + 'step' => '<div class="step-content" data-step="3">',
620 + 'title' => sprintf(
621 + '<div class="step-title">%s</div>',
622 + esc_html__( 'Step 3 — Prompt Generated', 'learnpress' ),
623 + ),
624 + 'prompt' => sprintf(
625 + '<div class="form-group">
626 + <label>%s</label>%s
627 + <i>%s</i>
628 + </div>',
629 + esc_html__( 'Generated Prompt', 'learnpress' ),
630 + '<textarea name="lp-openai-prompt-generated-field"></textarea>',
631 + __( 'Shows the auto-generated AI prompt, allowing further adjustments before submission.', 'learnpress' )
632 + ),
633 + 'step_close' => '</div>',
634 + ];
635 +
636 + return Template::combine_components( $components );
637 + }
638 +
639 + public function html_description_step_4(): string {
640 + $options = $this->config;
641 +
642 + $components = [
643 + 'step' => '<div class="step-content" data-step="4">',
644 + 'title' => sprintf(
645 + '<div class="step-title">%s</div>',
646 + esc_html__( 'Step 4 — Result', 'learnpress' ),
647 + ),
648 + 'results' => '<div class="lp-ai-generated-results"></div>',
649 + 'step_close' => '</div>',
650 + ];
651 +
652 + return Template::combine_components( $components );
653 + }
654 +
655 + /***************** Image *****************/
656 + public function html_edit_image_via_ai(): string {
657 + $components = [
658 + 'wrap-script-template' => '<script type="text/template" id="lp-tmpl-edit-image-ai">',
659 + 'wrap' => '<div class="lp-generate-data-ai-wrap">',
660 + 'btn-close' =>
661 + '<button type="button" class="lp-btn-close-ai-popup">
662 + <i class="lp-icon-remove"></i>
663 + </button>',
664 + 'h2' => sprintf(
665 + '<div class="content-title">%s</div>',
666 + esc_html__( 'Generate Course Image', 'learnpress' )
667 + ),
668 + 'header' => $this->html_image_step_header(), // You can add header if needed.
669 + 'form' => '<form class="lp-form-generate-data-ai">',
670 + 'wrap-fields' => '<div class="lp-form-fields">',
671 + 'step-1' => $this->html_image_step_1(),
672 + 'step-2' => $this->html_image_step_2(),
673 + 'step-3' => $this->html_image_step_3(),
674 + 'wrap-fields-end' => '</div>',
675 + 'buttons' => sprintf(
676 + '<div class="button-actions" data-step="1" data-step-max="3">
677 + <button class="btn btn-secondary lp-btn-step lp-hidden"
678 + data-step-show="2,3"
679 + data-action="prev" type="button">&larr; %s
680 + </button>
681 + <button class="btn btn-primary lp-btn-step lp-hidden"
682 + data-step-show="0"
683 + data-action="next" type="button">%s &rarr;
684 + </button>
685 + <button class="lp-button btn-primary lp-btn-generate-prompt"
686 + data-step-show="1"
687 + data-send="%s" type="button">%s
688 + </button>
689 + <button class="lp-button btn-primary lp-btn-call-open-ai lp-hidden"
690 + data-step-show="2"
691 + data-send="%s" type="button">%s
692 + </button>
693 + </div>',
694 + esc_html__( 'Previous', 'learnpress' ),
695 + esc_html__( 'Next', 'learnpress' ),
696 + Template::convert_data_to_json(
697 + [
698 + 'action' => 'openai_generate_prompt',
699 + 'lp-prompt-type' => 'course-image',
700 + 'id_url' => 'generate_prompt_openai',
701 + ]
702 + ),
703 + esc_html__( 'Generate Prompt', 'learnpress' ),
704 + Template::convert_data_to_json(
705 + [
706 + 'action' => 'openai_generate_image',
707 + 'lp-prompt-type' => 'course-image',
708 + 'target-apply' => 'set-wp-editor-content', // Click apply to apply title to this field.
709 + 'id_url' => 'submit_to_openai',
710 + ]
711 + ),
712 + esc_html__( 'Generate Image Course', 'learnpress' ),
713 + ),
714 + 'post-id' => sprintf(
715 + '<input type="hidden" name="post-id" value="%d" />',
716 + get_the_ID()
717 + ),
718 + 'form-end' => '</form>',
719 + 'wrap-end' => '</div>',
720 + 'wrap-script-template-end' => '</script>',
721 + ];
722 +
723 + return Template::combine_components( $components );
724 + }
725 +
726 + public function html_image_step_header(): string {
727 + $components = [
728 + 'wrap' => '<div class="step-header">',
729 + 'step_1' => sprintf(
730 + '<div class="step-item active" data-step="1"><span class="step-number">1</span><span class="step-text">%s</span></div>',
731 + esc_html__( 'Course Image config', 'learnpress' )
732 + ),
733 + 'step_2' => sprintf(
734 + '<div class="step-item" data-step="2"><span class="step-number">2</span><span class="step-text">%s</span></div>',
735 + esc_html__( 'Prompt', 'learnpress' )
736 + ),
737 + 'step_3' => sprintf(
738 + '<div class="step-item" data-step="3"><span class="step-number">3</span><span class="step-text">%s</span></div>',
739 + esc_html__( 'Result', 'learnpress' )
740 + ),
741 + 'wrap-end' => '</div>',
742 + ];
743 +
744 + return Template::combine_components( $components );
745 + }
746 +
747 + public function html_image_step_1(): string {
748 + $model_type = LP_Settings::instance()->get( 'open_ai_image_model_type' );
749 + $options = $this->config;
750 + $size_opts = $options[ "image-size-$model_type" ] ?? [ 'auto' ];
751 + $quality_opts = $options[ "image-quality-$model_type" ] ?? $options['image-quality'] ?? [ 'auto' ];
752 +
753 + $components = [
754 + 'step' => '<div class="step-content active" data-step="1">',
755 + 'title' => sprintf(
756 + '<div class="step-title">%s</div>',
757 + esc_html__( 'Step 1 — Config Image', 'learnpress' ),
758 + ),
759 + 'description' => sprintf(
760 + '<p class="step-description">%s</p>',
761 + esc_html__( 'Config your image you want, data will refer course title, course description to generate image.', 'learnpress' )
762 + ),
763 + 'from-title' => sprintf(
764 + '<div class="form-group">
765 + <label>%s</label>
766 + <input class="title-refer" type="text" name="post-title" readonly />
767 + <p class="lp-ai-warning-refer lp-hidden"><i class="lp-icon-warning"></i>%s</p>
768 + <p class="field-description">%s</p>
769 + </div>',
770 + esc_html__( 'Title Refer', 'learnpress' ),
771 + esc_html__( 'The title refer to generate a relevant course image. Please enter title first', 'learnpress' ),
772 + esc_html__( 'The current course title that will be used as reference during image generation.', 'learnpress' )
773 + ),
774 + 'goal' => sprintf(
775 + '<div class="form-group">
776 + <label>%s</label>
777 + <textarea type="text" name="goal" placeholder="%s"></textarea>
778 + </div>',
779 + esc_html__( 'Goal', 'learnpress' ),
780 + esc_html__( 'A brief description of the image you want to generate.', 'learnpress' )
781 + ),
782 + 'form-grid' => '<div class="form-grid">',
783 + 'style' => sprintf(
784 + '<div class="form-group">
785 + <label>%s</label>
786 + %s
787 + <p class="field-description">%s</p>
788 + </div>',
789 + esc_html__( 'Style', 'learnpress' ),
790 + AdminTemplate::html_tom_select(
791 + [
792 + 'name' => 'style',
793 + 'options' => $options['image-style'] ?? [],
794 + 'default_value' => 'Realistic',
795 + ]
796 + ),
797 + esc_html__( 'Select the visual style such as modern, minimalist, illustration, 3D, etc.', 'learnpress' )
798 + ),
799 + /*'write-requirement' => sprintf(
800 + '<div class="form-group">
801 + <label>%s</label>
802 + <input type="text" name="topic" placeholder="%s" />
803 + <p class="field-description">%s</p>
804 + </div>',
805 + esc_html__( 'Images or icons should be include', 'learnpress' ),
806 + esc_html__( 'e.g., books, laptop, graduation cap', 'learnpress' ),
807 + esc_html__( 'List the specific elements or icons that should appear in the generated image.', 'learnpress' )
808 + ),*/
809 + 'size' => sprintf(
810 + '<div class="form-group">
811 + <label>%s</label>
812 + %s
813 + <p class="field-description">%s</p>
814 + </div>',
815 + esc_html__( 'Size', 'learnpress' ),
816 + AdminTemplate::html_tom_select(
817 + [
818 + 'name' => 'size',
819 + 'options' => $size_opts,
820 + ]
821 + ),
822 + esc_html__( 'Set the output.', 'learnpress' )
823 + ),
824 + 'quality' => sprintf(
825 + '<div class="form-group">
826 + <label>%s</label>
827 + %s
828 + <p class="field-description">%s</p>
829 + </div>',
830 + esc_html__( 'Quality', 'learnpress' ),
831 + AdminTemplate::html_tom_select(
832 + [
833 + 'name' => 'quality',
834 + 'options' => $quality_opts,
835 + ]
836 + ),
837 + esc_html__( 'Select the desired image quality such as standard, high, or premium.', 'learnpress' )
838 + ),
839 + 'outputs' => sprintf(
840 + '<div class="form-group">
841 + <label>%s</label>
842 + <input name="outputs" value="2" type="number" />
843 + <p class="field-description">%s</p>
844 + </div>',
845 + esc_html__( 'Outputs', 'learnpress' ),
846 + esc_html__( 'Number of images you want the system to generate.', 'learnpress' )
847 + ),
848 + 'form-grid-end' => '</div>',
849 + 'step_close' => '</div>',
850 + ];
851 +
852 + return Template::combine_components( $components );
853 + }
854 +
855 + public function html_image_step_2(): string {
856 + $options = $this->config;
857 +
858 + $components = [
859 + 'step' => '<div class="step-content" data-step="2">',
860 + 'title' => sprintf(
861 + '<div class="step-title">%s</div>',
862 + esc_html__( 'Step 2 — Prompt Generated', 'learnpress' ),
863 + ),
864 + 'prompt' => sprintf(
865 + '<div class="form-group">
866 + <label>%s</label>%s
867 + <i>%s</i>
868 + </div>',
869 + esc_html__( 'Generated Prompt', 'learnpress' ),
870 + '<textarea name="lp-openai-prompt-generated-field"></textarea>',
871 + __( 'Shows the auto-generated AI prompt, allowing further adjustments before submission.', 'learnpress' )
872 + ),
873 + 'step_close' => '</div>',
874 + ];
875 +
876 + return Template::combine_components( $components );
877 + }
878 +
879 + public function html_image_step_3(): string {
880 + $options = $this->config;
881 +
882 + $components = [
883 + 'step' => '<div class="step-content" data-step="3">',
884 + 'title' => sprintf(
885 + '<div class="step-title">%s</div>',
886 + esc_html__( 'Step 3 — Result', 'learnpress' ),
887 + ),
888 + 'description' => sprintf(
889 + '<p class="step-description">%s</p>',
890 + esc_html__( 'Note: when applying an image, the process can be very slow (about 1 minute or more), depends on the image size. Please wait until it finishes.', 'learnpress' )
891 + ),
892 + 'results' => '<div class="lp-ai-generated-results"></div>',
893 + 'step_close' => '</div>',
894 + ];
895 +
896 + return Template::combine_components( $components );
897 + }
898 +
899 + public function html_feature_image_created( $args ): string {
900 + $src = $args['src'] ?? '';
901 + $post_id = $args['post-id'] ?? '';
902 + $attachment_id = $args['attachment-id'] ?? '';
903 +
904 + $section = [
905 + 'wrap' => '<div class="inside">',
906 + 'preview' => sprintf(
907 + '<p class="hide-if-no-js">
908 + <a href="%s" id="set-post-thumbnail" aria-describedby="set-post-thumbnail-desc" class="thickbox">
909 + <img width="266" height="266" src="%s" alt="" />
910 + </a>
911 + </p>',
912 + admin_url( "media-upload.php?post_id=$post_id&amp;type=image&amp;TB_iframe=1" ),
913 + $src
914 + ),
915 + 'desc' => '<p class="hide-if-no-js howto" id="set-post-thumbnail-desc">Click the image to edit or update</p>',
916 + 'remove' => sprintf(
917 + '<p class="hide-if-no-js"><a href="#" id="remove-post-thumbnail">%s</a></p>',
918 + __( 'Remove featured image' )
919 + ),
920 + 'input' => sprintf(
921 + '<input type="hidden" id="_thumbnail_id" name="_thumbnail_id" value="%d" />',
922 + $attachment_id
923 + ),
924 + 'wrap_end' => '</div>',
925 + ];
926 +
927 + return Template::combine_components( $section );
928 + }
929 +
930 + /***************** Curriculum *****************/
931 + public function html_edit_curriculum_via_ai(): string {
932 + $components = [
933 + 'wrap-script-template' => '<script type="text/template" id="lp-tmpl-edit-curriculum-ai">',
934 + 'wrap' => '<div class="lp-generate-data-ai-wrap">',
935 + 'h2' => sprintf(
936 + '<div class="content-title">%s</div>',
937 + esc_html__( 'Generate Course Curriculum', 'learnpress' )
938 + ),
939 + 'header' => '', // You can add header if needed.
940 + 'form' => '<form class="lp-form-generate-data-ai">',
941 + 'wrap-fields' => '<div class="lp-form-fields">',
942 + // Add steps for curriculum generation here.
943 + 'wrap-fields-end' => '</div>',
944 + 'buttons' => sprintf(
945 + '<div class="button-actions" data-step="1" data-step-max="1">
946 + <button class="lp-button btn-primary lp-btn-call-open-ai lp-hidden"
947 + data-send="%s" type="button">%s
948 + </button>
949 + </div>',
950 + Template::convert_data_to_json(
951 + [
952 + 'action' => 'openai_generate_data',
953 + 'lp-prompt-type' => 'course-curriculum',
954 + 'target-apply' => 'set-course-curriculum', // Click apply to apply curriculum to this field.
955 + 'id_url' => 'submit_to_openai',
956 + ]
957 + ),
958 + esc_html__( 'Generate Course Curriculum', 'learnpress' ),
959 + ),
960 + 'post-id' => sprintf(
961 + '<input type="hidden" name="post-id" value="%d" />',
962 + get_the_ID()
963 + ),
964 + 'form-end' => '</form>',
965 + 'wrap-end' => '</div>',
966 + 'wrap-script-template-end' => '</script>',
967 + ];
968 +
969 + return Template::combine_components( $components );
970 + }
971 +}