PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
← All changes | inc/TemplateHooks/Course/AdminEditSettingTemplate.php +692 -692 4.3.9.14.4.8 View file →
@@ -1,692 +1,692 @@
1 -<?php
2 -
3 -namespace LearnPress\TemplateHooks\Course;
4 -
5 -use LearnPress\Helpers\Config;
6 -use LearnPress\Helpers\Singleton;
7 -use LearnPress\Helpers\Template;
8 -use LearnPress\Models\CourseModel;
9 -use LearnPress\Models\CoursePostModel;
10 -use LearnPress\Models\QuizPostModel;
11 -use LP_Database;
12 -use LP_Meta_Box_Checkbox_Field;
13 -use LP_Meta_Box_Course;
14 -use LP_Meta_Box_Date_Field;
15 -use LP_Meta_Box_Duration_Field;
16 -use LP_Meta_Box_Extra_Faq_Field;
17 -use LP_Meta_Box_Extra_Field;
18 -use LP_Meta_Box_Field;
19 -use LP_Meta_Box_Material_Fields;
20 -use LP_Meta_Box_Radio_Field;
21 -use LP_Meta_Box_Select_Field;
22 -use LP_Meta_Box_Text_Field;
23 -use LP_Meta_Box_Textarea_Field;
24 -use WP_Post;
25 -use WP_User;
26 -
27 -/**
28 - * Template hooks Admin Edit Course Settings.
29 - *
30 - * @since 4.3.0
31 - * @version 1.0.0
32 - */
33 -class AdminEditSettingTemplate {
34 - use Singleton;
35 -
36 - public function init() {
37 - add_action( 'learn-press/admin/course/edit-setting/layout', [ $this, 'render_settings' ] );
38 - // add_filter( 'lp/rest/ajax/allow_callback', [ $this, 'allow_callback' ] );
39 - }
40 -
41 -
42 - /**
43 - * Render edit course settings html.
44 - *
45 - * @param int $post_id
46 - *
47 - * @return string
48 - */
49 - public static function render_settings( int $post_id = 0 ) {
50 - if ( ! $post_id ) {
51 - global $post;
52 - $post_id = $post->ID;
53 - }
54 -
55 - wp_enqueue_style( 'lp-edit-curriculum' );
56 - wp_enqueue_script( 'lp-edit-course' );
57 -
58 - echo self::instance()->html_course_settings( $post_id );
59 - }
60 -
61 - /**
62 - * HTML for course settings metabox.
63 - *
64 - * @param int $post_id
65 - *
66 - * @return string
67 - */
68 - public function html_course_settings( int $post_id ): string {
69 - $tabs_data = LP_Meta_Box_Course::instance()->metabox( $post_id );
70 - $nav_items = '';
71 - $panels = '';
72 -
73 - foreach ( $tabs_data as $key => $tab ) {
74 - if ( $key === 'author' && ! is_super_admin() ) {
75 - continue;
76 - }
77 -
78 - $class_tab = isset( $tab['class'] ) ? implode( ' ', (array) $tab['class'] ) : '';
79 - $icon = isset( $tab['icon'] ) ? sprintf( '<i class="%s"></i>', esc_attr( $tab['icon'] ) ) : '';
80 -
81 - $nav_items .= sprintf(
82 - '<li class="%s_options %s_tab %s"><a href="#%s">%s<span>%s</span></a></li>',
83 - esc_attr( $key ),
84 - esc_attr( $key ),
85 - esc_attr( $class_tab ),
86 - esc_attr( $tab['target'] ),
87 - $icon,
88 - esc_html( $tab['label'] )
89 - );
90 -
91 - if ( isset( $tab['content'] ) ) {
92 - ob_start();
93 - do_action( 'learnpress/course-settings/before-' . $key );
94 -
95 - foreach ( $tab['content'] as $meta_key => $object ) {
96 - if ( is_a( $object, LP_Meta_Box_Field::class ) ) {
97 - $object->id = $meta_key;
98 - $output = $object->output( $post_id );
99 - if ( ! empty( $output ) ) {
100 - echo wp_kses_post( $output );
101 - }
102 - }
103 - }
104 -
105 - do_action( 'learnpress/course-settings/after-' . $key );
106 - $panel_html = ob_get_clean();
107 -
108 - $panels .= sprintf(
109 - '<div id="%s" class="lp-meta-box-course-panels">%s</div>',
110 - esc_attr( $tab['target'] ),
111 - $panel_html
112 - );
113 - }
114 - }
115 -
116 - $wrapper = [
117 - 'wrap' => '<div class="lp-meta-box lp-meta-box--course"><div class="lp-meta-box__inner"><div class="lp-meta-box__course-tab">',
118 - 'ul_tabs' => '<ul class="lp-meta-box__course-tab__tabs">' . $nav_items . '</ul>',
119 - 'content_div' => '<div class="lp-meta-box__course-tab__content">',
120 - 'panels' => $panels,
121 - 'hook_cb' => $this->capture_course_builder_hook_content( $post_id ),
122 - 'hook_extra' => $this->capture_hook_content( 'lp_course_data_setting_tab_content', $post_id ),
123 - 'content_end' => '</div>',
124 - 'inner_end' => '</div></div></div>',
125 - ];
126 -
127 - return Template::combine_components( $wrapper );
128 - }
129 -
130 - /**
131 - * Helper to capture do_action output
132 - *
133 - * @param string $hook
134 - * @param int $post_id
135 - * @param bool $allow_course_builder_context
136 - *
137 - * @return string
138 - */
139 - private function capture_hook_content( string $hook, int $post_id, bool $allow_course_builder_context = false ): string {
140 - if ( ! $allow_course_builder_context && $this->is_course_builder_context() ) {
141 - return '';
142 - }
143 -
144 - ob_start();
145 - $post = get_post( $post_id );
146 - do_action( $hook, $post );
147 - return ob_get_clean();
148 - }
149 -
150 - /**
151 - * Render Course Builder-only hook content for course settings.
152 - * This keeps admin behavior unchanged while exposing a safe extension point for builder.
153 - *
154 - * @param int $post_id
155 - *
156 - * @return string
157 - */
158 - private function capture_course_builder_hook_content( int $post_id ): string {
159 - if ( ! $this->is_course_builder_context() ) {
160 - return '';
161 - }
162 -
163 - return $this->capture_hook_content(
164 - 'learn-press/course-builder/edit-course/settings/tab/content',
165 - $post_id,
166 - true
167 - );
168 - }
169 -
170 - /**
171 - * Check current request is Course Builder page.
172 - *
173 - * @return bool
174 - */
175 - private function is_course_builder_context(): bool {
176 - if ( ! class_exists( '\\LP_Page_Controller' ) ) {
177 - return false;
178 - }
179 -
180 - return \LP_Page_Controller::is_page_course_builder();
181 - }
182 -
183 - public function tab_general( $post_id ) {
184 - $course = CourseModel::find( $post_id, true );
185 - $repurchase_option_desc = sprintf(
186 - '1. %s',
187 - __(
188 - 'Reset course progress: The course progress and results of student will be removed.',
189 - 'learnpress'
190 - )
191 - );
192 - $repurchase_option_desc .= '<br/>' . sprintf(
193 - '2. %s',
194 - __(
195 - 'Keep course progress: The course progress and results of student will remain.',
196 - 'learnpress'
197 - )
198 - );
199 - $repurchase_option_desc .= '<br/>' . sprintf(
200 - '3. %s',
201 - __(
202 - 'Open popup: The student can decide whether their course progress will be reset with the confirm popup.',
203 - 'learnpress'
204 - )
205 - );
206 - $max_students_desc = esc_html__(
207 - 'The maximum number of students that can join a course. Set 0 for unlimited.',
208 - 'learnpress'
209 - );
210 - $max_students_desc .= '<br/>' . esc_html__( 'Not apply for case "No enroll requirement".', 'learnpress' );
211 -
212 - $is_enable_allow_course_repurchase = false;
213 - if ( $course instanceof CourseModel ) {
214 - $is_enable_allow_course_repurchase = $course->get_meta_value_by_key( CoursePostModel::META_KEY_ALLOW_COURSE_REPURCHASE, 'no' ) === 'yes';
215 - }
216 -
217 - $fake_students_desc = esc_html__( 'Fake students enrolled for the course.', 'learnpress' );
218 - $fake_students_desc .= '<br>' . esc_html__( 'It only to display, not calculate', 'learnpress' );
219 -
220 - return apply_filters(
221 - 'lp/course/meta-box/fields/general',
222 - array(
223 - '_lp_duration' => new LP_Meta_Box_Duration_Field(
224 - esc_html__( 'Duration', 'learnpress' ),
225 - esc_html__( 'Set to 0 for the lifetime access.', 'learnpress' ),
226 - '10 week',
227 - array(
228 - 'default_time' => 'week',
229 - 'custom_attributes' => array(
230 - 'min' => '0',
231 - 'step' => '1',
232 - ),
233 - )
234 - ),
235 - '_lp_block_expire_duration' => new LP_Meta_Box_Checkbox_Field(
236 - esc_html__( 'Block content', 'learnpress' ),
237 - esc_html__( 'When the duration expires, the course is blocked.', 'learnpress' ),
238 - 'no'
239 - ),
240 - '_lp_block_finished' => new LP_Meta_Box_Checkbox_Field(
241 - '',
242 - esc_html__( 'Block the course after the student finished this course.', 'learnpress' ),
243 - 'yes'
244 - ),
245 - '_lp_allow_course_repurchase' => new LP_Meta_Box_Checkbox_Field(
246 - __( 'Allow Repurchase', 'learnpress' ),
247 - esc_html__( 'Allow users to repurchase this course after it has been finished or blocked (Do not apply to free courses or Create Order manual).', 'learnpress' ),
248 - 'no'
249 - ),
250 - '_lp_course_repurchase_option' => new LP_Meta_Box_Select_Field(
251 - esc_html__( 'Repurchase action', 'learnpress' ),
252 - $repurchase_option_desc,
253 - 'reset',
254 - array(
255 - 'options' => array(
256 - 'reset' => esc_html__( 'Reset course progress', 'learnpress' ),
257 - 'keep' => esc_html__( 'Keep course progress', 'learnpress' ),
258 - 'popup' => esc_html__( 'Open popup', 'learnpress' ),
259 - ),
260 - 'dependency' => [
261 - 'name' => '_lp_allow_course_repurchase',
262 - 'is_disable' => ! $is_enable_allow_course_repurchase,
263 - ],
264 - )
265 - ),
266 - '_lp_level' => new LP_Meta_Box_Select_Field(
267 - esc_html__( 'Level', 'learnpress' ),
268 - esc_html__( 'Choose a difficulty level.', 'learnpress' ),
269 - 'all',
270 - array(
271 - 'options' => lp_course_level(),
272 - )
273 - ),
274 - '_lp_students' => new LP_Meta_Box_Text_Field(
275 - esc_html__( 'Fake Students Enrolled', 'learnpress' ),
276 - $fake_students_desc,
277 - 0,
278 - array(
279 - 'type_input' => 'number',
280 - 'custom_attributes' => array(
281 - 'min' => '0',
282 - 'step' => '1',
283 - ),
284 - 'style' => 'width: 70px;',
285 - )
286 - ),
287 - '_lp_max_students' => new LP_Meta_Box_Text_Field(
288 - esc_html__( 'Max student', 'learnpress' ),
289 - $max_students_desc,
290 - 0,
291 - array(
292 - 'type_input' => 'number',
293 - 'custom_attributes' => array(
294 - 'min' => '0',
295 - 'step' => '1',
296 - ),
297 - 'style' => 'width: 70px;',
298 - )
299 - ),
300 - '_lp_retake_count' => new LP_Meta_Box_Text_Field(
301 - esc_html__( 'Re-take Course', 'learnpress' ),
302 - esc_html__( 'The number of times a user can learn again from this course. To disable, set to 0.', 'learnpress' ),
303 - 0,
304 - array(
305 - 'type_input' => 'number',
306 - 'custom_attributes' => array(
307 - 'min' => '0',
308 - 'step' => '1',
309 - ),
310 - 'style' => 'width: 70px;',
311 - )
312 - ),
313 - '_lp_has_finish' => new LP_Meta_Box_Checkbox_Field(
314 - esc_html__( 'Finish button', 'learnpress' ),
315 - esc_html__( 'Allow showing the finish button when the student has completed all items but has not passed the course assessment yet.', 'learnpress' ),
316 - 'yes'
317 - ),
318 - '_lp_featured' => new LP_Meta_Box_Checkbox_Field(
319 - esc_html__( 'Featured list', 'learnpress' ),
320 - esc_html__( 'Add the course to the Featured List.', 'learnpress' ),
321 - 'no'
322 - ),
323 - '_lp_featured_review' => new LP_Meta_Box_Textarea_Field(
324 - esc_html__( 'Featured review', 'learnpress' ),
325 - esc_html__( 'A good review to promote the course.', 'learnpress' )
326 - ),
327 - '_lp_external_link_buy_course' => new LP_Meta_Box_Text_Field(
328 - esc_html__( 'External link', 'learnpress' ),
329 - esc_html__( 'Normally used for offline classes. Ex: link to a contact page. Format: https://google.com', 'learnpress' ),
330 - '',
331 - array(
332 - 'desc_tip' => 'You can apply for case: user register form.<br> You accept for user can learn courses by add manual order on backend',
333 - )
334 - ),
335 - ),
336 - $post_id
337 - );
338 - }
339 -
340 - public function tab_offline( $post_id ): array {
341 - $course = CourseModel::find( $post_id, true );
342 -
343 - $is_offline_course = false;
344 - if ( $course instanceof CourseModel ) {
345 - $is_offline_course = $course->is_offline();
346 - }
347 -
348 - return apply_filters(
349 - 'lp/course/meta-box/fields/offline',
350 - array(
351 - CoursePostModel::META_KEY_OFFLINE_COURSE => new LP_Meta_Box_Checkbox_Field(
352 - esc_html__( 'Enable offline course', 'learnpress' ),
353 - esc_html__(
354 - 'When you enable the offline course feature, the system will disable certain online course functions, such as curriculum, finish button, re-take course, block content, repurchase. After checking the checkbox, make sure to click the "Update" button to apply the changes successfully.',
355 - 'learnpress'
356 - ),
357 - 'no'
358 - ),
359 - CoursePostModel::META_KEY_OFFLINE_LESSON_COUNT => new LP_Meta_Box_Text_Field(
360 - esc_html__( 'Lessons', 'learnpress' ),
361 - esc_html__( 'Total lessons of the course.', 'learnpress' ),
362 - 10,
363 - [
364 - 'type_input' => 'number',
365 - 'custom_attributes' => array(
366 - 'min' => '0',
367 - 'step' => '1',
368 - ),
369 - 'dependency' => [
370 - 'name' => '_lp_offline_course',
371 - 'is_disable' => ! $is_offline_course,
372 - ],
373 - ]
374 - ),
375 - CoursePostModel::META_KEY_DELIVER => new LP_Meta_Box_Select_Field(
376 - esc_html__( 'Delivery Type', 'learnpress' ),
377 - esc_html__( 'How your content is conveyed to students.', 'learnpress' ),
378 - 'private_1_1',
379 - [
380 - 'options' => Config::instance()->get( 'course-deliver-type' ),
381 - 'dependency' => [
382 - 'name' => '_lp_offline_course',
383 - 'is_disable' => ! $is_offline_course,
384 - ],
385 - ]
386 - ),
387 - CoursePostModel::META_KEY_ADDRESS => new LP_Meta_Box_Text_Field(
388 - esc_html__( 'Address', 'learnpress' ),
389 - esc_html__( 'You can enter the physical address of your class or specify the meeting method (e.g., Zoom, Google Meet, etc.).', 'learnpress' ),
390 - '',
391 - [
392 - 'dependency' => [
393 - 'name' => '_lp_offline_course',
394 - 'is_disable' => ! $is_offline_course,
395 - ],
396 - ]
397 - ),
398 - ),
399 - $post_id
400 - );
401 - }
402 -
403 - public function tab_price( $post_id ): array {
404 - $key_exists = LP_Database::getInstance()->check_key_postmeta_exists( $post_id, '_lp_regular_price' );
405 - $price = get_post_meta( $post_id, '_lp_price', true );
406 - $regular_price = $key_exists ? get_post_meta( $post_id, '_lp_regular_price', true ) : $price;
407 - $sale_price = get_post_meta( $post_id, '_lp_sale_price', true );
408 -
409 - $is_enable_no_required_enroll = get_post_meta( $post_id, '_lp_no_required_enroll', true ) === 'yes' ? 1 : 0;
410 -
411 - return apply_filters(
412 - 'lp/course/meta-box/fields/price',
413 - array(
414 - '_lp_regular_price' => new LP_Meta_Box_Text_Field(
415 - esc_html__( 'Regular price', 'learnpress' ),
416 - sprintf( __( 'Set a regular price (<strong>%s</strong>). Leave it blank for <strong>Free</strong>.', 'learnpress' ), learn_press_get_currency() ),
417 - $regular_price,
418 - array(
419 - 'type_input' => 'text',
420 - 'custom_attributes' => array(
421 - 'min' => '0',
422 - 'step' => '0.01',
423 - ),
424 - 'style' => 'width: 150px;',
425 - 'class' => 'lp_meta_box_regular_price',
426 - 'dependency' => [
427 - 'name' => '_lp_no_required_enroll',
428 - 'is_disable' => $is_enable_no_required_enroll,
429 - ],
430 - )
431 - ),
432 - '_lp_sale_price' => new LP_Meta_Box_Text_Field(
433 - esc_html__( 'Sale price', 'learnpress' ),
434 - '<a href="#" class="lp_sale_price_schedule">' . esc_html__( 'Schedule', 'learnpress' ) . '</a>',
435 - $sale_price,
436 - array(
437 - 'type_input' => 'text',
438 - 'custom_attributes' => array(
439 - 'min' => '0',
440 - 'step' => '0.01',
441 - ),
442 - 'style' => 'width: 150px;',
443 - 'class' => 'lp_meta_box_sale_price',
444 - 'dependency' => [
445 - 'name' => '_lp_no_required_enroll',
446 - 'is_disable' => $is_enable_no_required_enroll,
447 - ],
448 - )
449 - ),
450 - '_lp_sale_start' => new LP_Meta_Box_Date_Field(
451 - esc_html__( 'Sale start dates', 'learnpress' ),
452 - '',
453 - '',
454 - array(
455 - 'wrapper_class' => 'lp_sale_start_dates_fields',
456 - 'placeholder' => _x( 'From&hellip;', 'placeholder', 'learnpress' ),
457 - 'dependency' => [
458 - 'name' => '_lp_no_required_enroll',
459 - 'is_disable' => $is_enable_no_required_enroll,
460 - ],
461 - )
462 - ),
463 - '_lp_sale_end' => new LP_Meta_Box_Date_Field(
464 - esc_html__( 'Sale end dates', 'learnpress' ),
465 - '',
466 - '',
467 - array(
468 - 'wrapper_class' => 'lp_sale_end_dates_fields',
469 - 'placeholder' => _x( 'To&hellip;', 'placeholder', 'learnpress' ),
470 - 'cancel' => true,
471 - 'dependency' => [
472 - 'name' => '_lp_no_required_enroll',
473 - 'is_disable' => $is_enable_no_required_enroll,
474 - ],
475 - )
476 - ),
477 - '_lp_price_prefix' => new LP_Meta_Box_Text_Field(
478 - esc_html__( 'Price prefix', 'learnpress' ),
479 - esc_html__( 'Show additional information placed before the price such as: Only, From, Up to...', 'learnpress' ),
480 - ''
481 - ),
482 - '_lp_price_suffix' => new LP_Meta_Box_Text_Field(
483 - esc_html__( 'Price Suffix', 'learnpress' ),
484 - esc_html__( 'Show additional information placed after the price such as: Included Tax, Per Hour, (Per Week)...', 'learnpress' ),
485 - ''
486 - ),
487 - '_lp_no_required_enroll' => new LP_Meta_Box_Checkbox_Field(
488 - esc_html__( 'There is no enrollment requirement', 'learnpress' ),
489 - esc_html__( 'Students can see the content of all course items and take the quiz without logging in.', 'learnpress' ),
490 - 'no'
491 - ),
492 - ),
493 - $post_id
494 - );
495 - }
496 -
497 - public function tab_author( $thepostid ) {
498 - $post = get_post( $thepostid );
499 -
500 - $author_id = $post ? $post->post_author : get_current_user_id();
501 -
502 - $options = array();
503 - // Code old only use for addon Frontend Editor v4.0.4
504 - // Code old only use for addon Co-Instructor v4.0.2
505 - $can_get_options_users = false;
506 - if ( class_exists( 'LP_Addon_Frontend_Editor_Preload' )
507 - && defined( 'LP_ADDON_FRONTEND_EDITOR_VER' )
508 - && version_compare( LP_ADDON_FRONTEND_EDITOR_VER, '4.0.5', '<' ) ) {
509 - $can_get_options_users = true;
510 - }
511 -
512 - if ( $can_get_options_users ) {
513 - $author_roles = array( ADMIN_ROLE, LP_TEACHER_ROLE );
514 - $author_roles = apply_filters( 'learn_press_course_author_role_meta_box', $author_roles );
515 - $authors = get_users( [ 'role__in' => $author_roles ] );
516 -
517 - /**
518 - * @var WP_User $author
519 - */
520 - foreach ( $authors as $author ) {
521 - $options[ $author->ID ] = $author->display_name . ' (#' . $author->ID . ')';
522 - }
523 - }
524 - // Code old only use for addon Frontend Editor v4.0.4
525 -
526 - $data_struct = [
527 - 'urlApi' => get_rest_url( null, 'lp/v1/admin/tools/search-user' ),
528 - 'dataSendApi' => [
529 - 'role_in' => ADMIN_ROLE . ',' . LP_TEACHER_ROLE,
530 - ],
531 - 'dataType' => 'users',
532 - 'keyGetValue' => [
533 - 'value' => 'ID',
534 - 'text' => '{{display_name}}(#{{ID}})',
535 - 'key_render' => [
536 - 'display_name' => 'display_name',
537 - 'user_email' => 'user_email',
538 - 'ID' => 'ID',
539 - ],
540 - ],
541 - 'setting' => [
542 - 'plugins' => array(),
543 - ],
544 - ];
545 -
546 - return apply_filters(
547 - 'lp/course/meta-box/fields/author',
548 - array(
549 - // Not use key 'post_author' on single edit course, it special key of WP, Gutenberg save will not submit this key.
550 - '_post_author' => new LP_Meta_Box_Select_Field(
551 - esc_html__( 'Author', 'learnpress' ),
552 - '',
553 - $author_id,
554 - array(
555 - 'options' => $options,
556 - 'style' => 'min-width:200px;',
557 - 'tom_select' => true,
558 - 'custom_attributes' => [ 'data-struct' => htmlentities2( json_encode( $data_struct ) ) ],
559 - )
560 - ),
561 - )
562 - );
563 - }
564 -
565 - public function tab_material( $thepostid ) {
566 - return apply_filters(
567 - 'lp/course/meta-box/fields/material',
568 - array(
569 - '_lp_course_material' => new LP_Meta_Box_Material_Fields(),
570 - )
571 - );
572 - }
573 -
574 - public function tab_assessment( $thepostid ) {
575 - $post = get_post( $thepostid );
576 -
577 - $course_result_desc = '';
578 - $course_results = get_post_meta( $thepostid, '_lp_course_result', true );
579 -
580 - $course_result_desc .= __( 'The method of evaluating a student\'s performance in a course.', 'learnpress' );
581 - $course_result_desc .= sprintf(
582 - '<br/><i style="color: red">%s</i>',
583 - __( 'Note: changing the evaluation type will affect the assessment results of student learning.', 'learnpress' )
584 - );
585 -
586 - if ( $course_results == 'evaluate_final_quiz' && ! get_post_meta( $thepostid, '_lp_final_quiz', true ) ) {
587 - $course_result_desc .= __( '<br /><strong>Note! </strong>There is no final quiz in the course. Please add a final quiz.', 'learnpress' );
588 - }
589 -
590 - $final_quizz_passing = '';
591 -
592 - $course = learn_press_get_course( $thepostid );
593 -
594 - if ( $course ) {
595 - $passing_grade = $url = '';
596 -
597 - $final_quiz = $course->get_final_quiz();
598 -
599 - if ( $final_quiz ) {
600 - $passing_grade = get_post_meta( $final_quiz, '_lp_passing_grade', true );
601 - if ( '' === (string) $passing_grade ) {
602 - $quiz_model = QuizPostModel::find( absint( $final_quiz ), true );
603 - if ( $quiz_model ) {
604 - $passing_grade = $quiz_model->get_passing_grade();
605 - } else {
606 - $passing_grade = 80;
607 - }
608 - }
609 -
610 - $url = get_edit_post_link( $final_quiz ) . '#_lp_passing_grade';
611 -
612 - $final_quizz_passing = '
613 - <div class="lp-metabox-evaluate-final_quiz">
614 - <div class="lp-metabox-evaluate-final_quiz__message">'
615 - . sprintf( esc_html__( 'Passing Grade: %s', 'learpress' ), $passing_grade . '%' ) .
616 - ' - '
617 - . sprintf( esc_html__( 'Edit: %s', 'learnpress' ), '<a href="' . esc_url_raw( $url ) . '">' . get_the_title( $final_quiz ) . '</a>' ) .
618 - '</div>
619 - </div>
620 - ';
621 - }
622 - }
623 -
624 - return apply_filters(
625 - 'lp/course/meta-box/fields/assessment',
626 - array(
627 - '_lp_course_result' => new LP_Meta_Box_Radio_Field(
628 - esc_html__( 'Evaluation', 'learnpress' ),
629 - $course_result_desc,
630 - 'evaluate_lesson',
631 - array(
632 - 'options' => learn_press_course_evaluation_methods( $thepostid, '', $final_quizz_passing ),
633 - )
634 - ),
635 - '_lp_passing_condition' => new LP_Meta_Box_Text_Field(
636 - esc_html__( 'Passing Grade(%)', 'learnpress' ),
637 - esc_html__( 'The conditions that must be achieved to finish the course.', 'learnpress' ),
638 - '80',
639 - array(
640 - 'type_input' => 'number',
641 - 'custom_attributes' => array(
642 - 'min' => '0',
643 - 'step' => '0.01',
644 - 'max' => '100',
645 - ),
646 - 'style' => 'width: 60px;',
647 - )
648 - ),
649 - )
650 - );
651 - }
652 -
653 - public function tab_extra( $thepostid ) {
654 - return apply_filters(
655 - 'lp/course/meta-box/fields/extra',
656 - array(
657 - '_lp_requirements' => new LP_Meta_Box_Extra_Field(
658 - esc_html__( 'Requirements', 'learnpress' ),
659 - '',
660 - array()
661 - ),
662 - '_lp_target_audiences' => new LP_Meta_Box_Extra_Field(
663 - esc_html__( 'Target Audience', 'learnpress' ),
664 - '',
665 - array()
666 - ),
667 - '_lp_key_features' => new LP_Meta_Box_Extra_Field(
668 - esc_html__( 'Key Features', 'learnpress' ),
669 - '',
670 - array()
671 - ),
672 - '_lp_faqs' => new LP_Meta_Box_Extra_Faq_Field(
673 - esc_html__( 'FAQs', 'learnpress' ),
674 - '',
675 - array()
676 - ),
677 - )
678 - );
679 - }
680 -
681 - public function data_tabs_sort( $a, $b ) {
682 - if ( ! isset( $a['priority'], $b['priority'] ) ) {
683 - return - 1;
684 - }
685 -
686 - if ( $a['priority'] === $b['priority'] ) {
687 - return 0;
688 - }
689 -
690 - return $a['priority'] < $b['priority'] ? - 1 : 1;
691 - }
692 -}
1 +<?php
2 +
3 +namespace LearnPress\TemplateHooks\Course;
4 +
5 +use LearnPress\Helpers\Config;
6 +use LearnPress\Helpers\Singleton;
7 +use LearnPress\Helpers\Template;
8 +use LearnPress\Models\CourseModel;
9 +use LearnPress\Models\CoursePostModel;
10 +use LearnPress\Models\QuizPostModel;
11 +use LP_Database;
12 +use LP_Meta_Box_Checkbox_Field;
13 +use LP_Meta_Box_Course;
14 +use LP_Meta_Box_Date_Field;
15 +use LP_Meta_Box_Duration_Field;
16 +use LP_Meta_Box_Extra_Faq_Field;
17 +use LP_Meta_Box_Extra_Field;
18 +use LP_Meta_Box_Field;
19 +use LP_Meta_Box_Material_Fields;
20 +use LP_Meta_Box_Radio_Field;
21 +use LP_Meta_Box_Select_Field;
22 +use LP_Meta_Box_Text_Field;
23 +use LP_Meta_Box_Textarea_Field;
24 +use WP_Post;
25 +use WP_User;
26 +
27 +/**
28 + * Template hooks Admin Edit Course Settings.
29 + *
30 + * @since 4.3.0
31 + * @version 1.0.0
32 + */
33 +class AdminEditSettingTemplate {
34 + use Singleton;
35 +
36 + public function init() {
37 + add_action( 'learn-press/admin/course/edit-setting/layout', [ $this, 'render_settings' ] );
38 + // add_filter( 'lp/rest/ajax/allow_callback', [ $this, 'allow_callback' ] );
39 + }
40 +
41 +
42 + /**
43 + * Render edit course settings html.
44 + *
45 + * @param int $post_id
46 + *
47 + * @return string
48 + */
49 + public static function render_settings( int $post_id = 0 ) {
50 + if ( ! $post_id ) {
51 + global $post;
52 + $post_id = $post->ID;
53 + }
54 +
55 + wp_enqueue_style( 'lp-edit-curriculum' );
56 + wp_enqueue_script( 'lp-edit-course' );
57 +
58 + echo self::instance()->html_course_settings( $post_id );
59 + }
60 +
61 + /**
62 + * HTML for course settings metabox.
63 + *
64 + * @param int $post_id
65 + *
66 + * @return string
67 + */
68 + public function html_course_settings( int $post_id ): string {
69 + $tabs_data = LP_Meta_Box_Course::instance()->metabox( $post_id );
70 + $nav_items = '';
71 + $panels = '';
72 +
73 + foreach ( $tabs_data as $key => $tab ) {
74 + if ( $key === 'author' && ! is_super_admin() ) {
75 + continue;
76 + }
77 +
78 + $class_tab = isset( $tab['class'] ) ? implode( ' ', (array) $tab['class'] ) : '';
79 + $icon = isset( $tab['icon'] ) ? sprintf( '<i class="%s"></i>', esc_attr( $tab['icon'] ) ) : '';
80 +
81 + $nav_items .= sprintf(
82 + '<li class="%s_options %s_tab %s"><a href="#%s">%s<span>%s</span></a></li>',
83 + esc_attr( $key ),
84 + esc_attr( $key ),
85 + esc_attr( $class_tab ),
86 + esc_attr( $tab['target'] ),
87 + $icon,
88 + esc_html( $tab['label'] )
89 + );
90 +
91 + if ( isset( $tab['content'] ) ) {
92 + ob_start();
93 + do_action( 'learnpress/course-settings/before-' . $key, $post_id );
94 +
95 + foreach ( $tab['content'] as $meta_key => $object ) {
96 + if ( is_a( $object, LP_Meta_Box_Field::class ) ) {
97 + $object->id = $meta_key;
98 + $output = $object->output( $post_id );
99 + if ( ! empty( $output ) ) {
100 + echo wp_kses_post( $output );
101 + }
102 + }
103 + }
104 +
105 + do_action( 'learnpress/course-settings/after-' . $key, $post_id );
106 + $panel_html = ob_get_clean();
107 +
108 + $panels .= sprintf(
109 + '<div id="%s" class="lp-meta-box-course-panels">%s</div>',
110 + esc_attr( $tab['target'] ),
111 + $panel_html
112 + );
113 + }
114 + }
115 +
116 + $wrapper = [
117 + 'wrap' => '<div class="lp-meta-box lp-meta-box--course"><div class="lp-meta-box__inner"><div class="lp-meta-box__course-tab">',
118 + 'ul_tabs' => '<ul class="lp-meta-box__course-tab__tabs">' . $nav_items . '</ul>',
119 + 'content_div' => '<div class="lp-meta-box__course-tab__content">',
120 + 'panels' => $panels,
121 + 'hook_cb' => $this->capture_course_builder_hook_content( $post_id ),
122 + 'hook_extra' => $this->capture_hook_content( 'lp_course_data_setting_tab_content', $post_id ),
123 + 'content_end' => '</div>',
124 + 'inner_end' => '</div></div></div>',
125 + ];
126 +
127 + return Template::combine_components( $wrapper );
128 + }
129 +
130 + /**
131 + * Helper to capture do_action output
132 + *
133 + * @param string $hook
134 + * @param int $post_id
135 + * @param bool $allow_course_builder_context
136 + *
137 + * @return string
138 + */
139 + private function capture_hook_content( string $hook, int $post_id, bool $allow_course_builder_context = false ): string {
140 + if ( ! $allow_course_builder_context && $this->is_course_builder_context() ) {
141 + return '';
142 + }
143 +
144 + ob_start();
145 + $post = get_post( $post_id );
146 + do_action( $hook, $post );
147 + return ob_get_clean();
148 + }
149 +
150 + /**
151 + * Render Course Builder-only hook content for course settings.
152 + * This keeps admin behavior unchanged while exposing a safe extension point for builder.
153 + *
154 + * @param int $post_id
155 + *
156 + * @return string
157 + */
158 + private function capture_course_builder_hook_content( int $post_id ): string {
159 + if ( ! $this->is_course_builder_context() ) {
160 + return '';
161 + }
162 +
163 + return $this->capture_hook_content(
164 + 'learn-press/course-builder/edit-course/settings/tab/content',
165 + $post_id,
166 + true
167 + );
168 + }
169 +
170 + /**
171 + * Check current request is Course Builder page.
172 + *
173 + * @return bool
174 + */
175 + private function is_course_builder_context(): bool {
176 + if ( ! class_exists( '\\LP_Page_Controller' ) ) {
177 + return false;
178 + }
179 +
180 + return \LP_Page_Controller::is_page_course_builder();
181 + }
182 +
183 + public function tab_general( $post_id ) {
184 + $course = CourseModel::find( $post_id, true );
185 + $repurchase_option_desc = sprintf(
186 + '1. %s',
187 + __(
188 + 'Reset course progress: The course progress and results of student will be removed.',
189 + 'learnpress'
190 + )
191 + );
192 + $repurchase_option_desc .= '<br/>' . sprintf(
193 + '2. %s',
194 + __(
195 + 'Keep course progress: The course progress and results of student will remain.',
196 + 'learnpress'
197 + )
198 + );
199 + $repurchase_option_desc .= '<br/>' . sprintf(
200 + '3. %s',
201 + __(
202 + 'Open popup: The student can decide whether their course progress will be reset with the confirm popup.',
203 + 'learnpress'
204 + )
205 + );
206 + $max_students_desc = esc_html__(
207 + 'The maximum number of students that can join a course. Set 0 for unlimited.',
208 + 'learnpress'
209 + );
210 + $max_students_desc .= '<br/>' . esc_html__( 'Not apply for case "No enroll requirement".', 'learnpress' );
211 +
212 + $is_enable_allow_course_repurchase = false;
213 + if ( $course instanceof CourseModel ) {
214 + $is_enable_allow_course_repurchase = $course->get_meta_value_by_key( CoursePostModel::META_KEY_ALLOW_COURSE_REPURCHASE, 'no' ) === 'yes';
215 + }
216 +
217 + $fake_students_desc = esc_html__( 'Fake students enrolled for the course.', 'learnpress' );
218 + $fake_students_desc .= '<br>' . esc_html__( 'It only to display, not calculate', 'learnpress' );
219 +
220 + return apply_filters(
221 + 'lp/course/meta-box/fields/general',
222 + array(
223 + '_lp_duration' => new LP_Meta_Box_Duration_Field(
224 + esc_html__( 'Duration', 'learnpress' ),
225 + esc_html__( 'Set to 0 for the lifetime access.', 'learnpress' ),
226 + '10 week',
227 + array(
228 + 'default_time' => 'week',
229 + 'custom_attributes' => array(
230 + 'min' => '0',
231 + 'step' => '1',
232 + ),
233 + )
234 + ),
235 + '_lp_block_expire_duration' => new LP_Meta_Box_Checkbox_Field(
236 + esc_html__( 'Block content', 'learnpress' ),
237 + esc_html__( 'When the duration expires, the course is blocked.', 'learnpress' ),
238 + 'no'
239 + ),
240 + '_lp_block_finished' => new LP_Meta_Box_Checkbox_Field(
241 + '',
242 + esc_html__( 'Block the course after the student finished this course.', 'learnpress' ),
243 + 'yes'
244 + ),
245 + '_lp_allow_course_repurchase' => new LP_Meta_Box_Checkbox_Field(
246 + __( 'Allow Repurchase', 'learnpress' ),
247 + esc_html__( 'Allow users to repurchase this course after it has been finished or blocked (Do not apply to free courses or Create Order manual).', 'learnpress' ),
248 + 'no'
249 + ),
250 + '_lp_course_repurchase_option' => new LP_Meta_Box_Select_Field(
251 + esc_html__( 'Repurchase action', 'learnpress' ),
252 + $repurchase_option_desc,
253 + 'reset',
254 + array(
255 + 'options' => array(
256 + 'reset' => esc_html__( 'Reset course progress', 'learnpress' ),
257 + 'keep' => esc_html__( 'Keep course progress', 'learnpress' ),
258 + 'popup' => esc_html__( 'Open popup', 'learnpress' ),
259 + ),
260 + 'dependency' => [
261 + 'name' => '_lp_allow_course_repurchase',
262 + 'is_disable' => ! $is_enable_allow_course_repurchase,
263 + ],
264 + )
265 + ),
266 + '_lp_level' => new LP_Meta_Box_Select_Field(
267 + esc_html__( 'Level', 'learnpress' ),
268 + esc_html__( 'Choose a difficulty level.', 'learnpress' ),
269 + 'all',
270 + array(
271 + 'options' => lp_course_level(),
272 + )
273 + ),
274 + '_lp_students' => new LP_Meta_Box_Text_Field(
275 + esc_html__( 'Fake Students Enrolled', 'learnpress' ),
276 + $fake_students_desc,
277 + 0,
278 + array(
279 + 'type_input' => 'number',
280 + 'custom_attributes' => array(
281 + 'min' => '0',
282 + 'step' => '1',
283 + ),
284 + 'style' => 'width: 70px;',
285 + )
286 + ),
287 + '_lp_max_students' => new LP_Meta_Box_Text_Field(
288 + esc_html__( 'Max student', 'learnpress' ),
289 + $max_students_desc,
290 + 0,
291 + array(
292 + 'type_input' => 'number',
293 + 'custom_attributes' => array(
294 + 'min' => '0',
295 + 'step' => '1',
296 + ),
297 + 'style' => 'width: 70px;',
298 + )
299 + ),
300 + '_lp_retake_count' => new LP_Meta_Box_Text_Field(
301 + esc_html__( 'Re-take Course', 'learnpress' ),
302 + esc_html__( 'The number of times a user can learn again from this course. To disable, set to 0.', 'learnpress' ),
303 + 0,
304 + array(
305 + 'type_input' => 'number',
306 + 'custom_attributes' => array(
307 + 'min' => '0',
308 + 'step' => '1',
309 + ),
310 + 'style' => 'width: 70px;',
311 + )
312 + ),
313 + '_lp_has_finish' => new LP_Meta_Box_Checkbox_Field(
314 + esc_html__( 'Finish button', 'learnpress' ),
315 + esc_html__( 'Allow showing the finish button when the student has completed all items but has not passed the course assessment yet.', 'learnpress' ),
316 + 'yes'
317 + ),
318 + '_lp_featured' => new LP_Meta_Box_Checkbox_Field(
319 + esc_html__( 'Featured list', 'learnpress' ),
320 + esc_html__( 'Add the course to the Featured List.', 'learnpress' ),
321 + 'no'
322 + ),
323 + '_lp_featured_review' => new LP_Meta_Box_Textarea_Field(
324 + esc_html__( 'Featured review', 'learnpress' ),
325 + esc_html__( 'A good review to promote the course.', 'learnpress' )
326 + ),
327 + '_lp_external_link_buy_course' => new LP_Meta_Box_Text_Field(
328 + esc_html__( 'External link', 'learnpress' ),
329 + esc_html__( 'Normally used for offline classes. Ex: link to a contact page. Format: https://google.com', 'learnpress' ),
330 + '',
331 + array(
332 + 'desc_tip' => 'You can apply for case: user register form.<br> You accept for user can learn courses by add manual order on backend',
333 + )
334 + ),
335 + ),
336 + $post_id
337 + );
338 + }
339 +
340 + public function tab_offline( $post_id ): array {
341 + $course = CourseModel::find( $post_id, true );
342 +
343 + $is_offline_course = false;
344 + if ( $course instanceof CourseModel ) {
345 + $is_offline_course = $course->is_offline();
346 + }
347 +
348 + return apply_filters(
349 + 'lp/course/meta-box/fields/offline',
350 + array(
351 + CoursePostModel::META_KEY_OFFLINE_COURSE => new LP_Meta_Box_Checkbox_Field(
352 + esc_html__( 'Enable offline course', 'learnpress' ),
353 + esc_html__(
354 + 'When you enable the offline course feature, the system will disable certain online course functions, such as curriculum, finish button, re-take course, block content, repurchase. After checking the checkbox, make sure to click the "Update" button to apply the changes successfully.',
355 + 'learnpress'
356 + ),
357 + 'no'
358 + ),
359 + CoursePostModel::META_KEY_OFFLINE_LESSON_COUNT => new LP_Meta_Box_Text_Field(
360 + esc_html__( 'Lessons', 'learnpress' ),
361 + esc_html__( 'Total lessons of the course.', 'learnpress' ),
362 + 10,
363 + [
364 + 'type_input' => 'number',
365 + 'custom_attributes' => array(
366 + 'min' => '0',
367 + 'step' => '1',
368 + ),
369 + 'dependency' => [
370 + 'name' => '_lp_offline_course',
371 + 'is_disable' => ! $is_offline_course,
372 + ],
373 + ]
374 + ),
375 + CoursePostModel::META_KEY_DELIVER => new LP_Meta_Box_Select_Field(
376 + esc_html__( 'Delivery Type', 'learnpress' ),
377 + esc_html__( 'How your content is conveyed to students.', 'learnpress' ),
378 + 'private_1_1',
379 + [
380 + 'options' => Config::instance()->get( 'course-deliver-type' ),
381 + 'dependency' => [
382 + 'name' => '_lp_offline_course',
383 + 'is_disable' => ! $is_offline_course,
384 + ],
385 + ]
386 + ),
387 + CoursePostModel::META_KEY_ADDRESS => new LP_Meta_Box_Text_Field(
388 + esc_html__( 'Address', 'learnpress' ),
389 + esc_html__( 'You can enter the physical address of your class or specify the meeting method (e.g., Zoom, Google Meet, etc.).', 'learnpress' ),
390 + '',
391 + [
392 + 'dependency' => [
393 + 'name' => '_lp_offline_course',
394 + 'is_disable' => ! $is_offline_course,
395 + ],
396 + ]
397 + ),
398 + ),
399 + $post_id
400 + );
401 + }
402 +
403 + public function tab_price( $post_id ): array {
404 + $key_exists = LP_Database::getInstance()->check_key_postmeta_exists( $post_id, '_lp_regular_price' );
405 + $price = get_post_meta( $post_id, '_lp_price', true );
406 + $regular_price = $key_exists ? get_post_meta( $post_id, '_lp_regular_price', true ) : $price;
407 + $sale_price = get_post_meta( $post_id, '_lp_sale_price', true );
408 +
409 + $is_enable_no_required_enroll = get_post_meta( $post_id, '_lp_no_required_enroll', true ) === 'yes' ? 1 : 0;
410 +
411 + return apply_filters(
412 + 'lp/course/meta-box/fields/price',
413 + array(
414 + '_lp_regular_price' => new LP_Meta_Box_Text_Field(
415 + esc_html__( 'Regular price', 'learnpress' ),
416 + sprintf( __( 'Set a regular price (<strong>%s</strong>). Leave it blank for <strong>Free</strong>.', 'learnpress' ), learn_press_get_currency() ),
417 + $regular_price,
418 + array(
419 + 'type_input' => 'text',
420 + 'custom_attributes' => array(
421 + 'min' => '0',
422 + 'step' => '0.01',
423 + ),
424 + 'style' => 'width: 150px;',
425 + 'class' => 'lp_meta_box_regular_price',
426 + 'dependency' => [
427 + 'name' => '_lp_no_required_enroll',
428 + 'is_disable' => $is_enable_no_required_enroll,
429 + ],
430 + )
431 + ),
432 + '_lp_sale_price' => new LP_Meta_Box_Text_Field(
433 + esc_html__( 'Sale price', 'learnpress' ),
434 + '<a href="#" class="lp_sale_price_schedule">' . esc_html__( 'Schedule', 'learnpress' ) . '</a>',
435 + $sale_price,
436 + array(
437 + 'type_input' => 'text',
438 + 'custom_attributes' => array(
439 + 'min' => '0',
440 + 'step' => '0.01',
441 + ),
442 + 'style' => 'width: 150px;',
443 + 'class' => 'lp_meta_box_sale_price',
444 + 'dependency' => [
445 + 'name' => '_lp_no_required_enroll',
446 + 'is_disable' => $is_enable_no_required_enroll,
447 + ],
448 + )
449 + ),
450 + '_lp_sale_start' => new LP_Meta_Box_Date_Field(
451 + esc_html__( 'Sale start dates', 'learnpress' ),
452 + '',
453 + '',
454 + array(
455 + 'wrapper_class' => 'lp_sale_start_dates_fields',
456 + 'placeholder' => _x( 'From&hellip;', 'placeholder', 'learnpress' ),
457 + 'dependency' => [
458 + 'name' => '_lp_no_required_enroll',
459 + 'is_disable' => $is_enable_no_required_enroll,
460 + ],
461 + )
462 + ),
463 + '_lp_sale_end' => new LP_Meta_Box_Date_Field(
464 + esc_html__( 'Sale end dates', 'learnpress' ),
465 + '',
466 + '',
467 + array(
468 + 'wrapper_class' => 'lp_sale_end_dates_fields',
469 + 'placeholder' => _x( 'To&hellip;', 'placeholder', 'learnpress' ),
470 + 'cancel' => true,
471 + 'dependency' => [
472 + 'name' => '_lp_no_required_enroll',
473 + 'is_disable' => $is_enable_no_required_enroll,
474 + ],
475 + )
476 + ),
477 + '_lp_price_prefix' => new LP_Meta_Box_Text_Field(
478 + esc_html__( 'Price prefix', 'learnpress' ),
479 + esc_html__( 'Show additional information placed before the price such as: Only, From, Up to...', 'learnpress' ),
480 + ''
481 + ),
482 + '_lp_price_suffix' => new LP_Meta_Box_Text_Field(
483 + esc_html__( 'Price Suffix', 'learnpress' ),
484 + esc_html__( 'Show additional information placed after the price such as: Included Tax, Per Hour, (Per Week)...', 'learnpress' ),
485 + ''
486 + ),
487 + '_lp_no_required_enroll' => new LP_Meta_Box_Checkbox_Field(
488 + esc_html__( 'There is no enrollment requirement', 'learnpress' ),
489 + esc_html__( 'Students can see the content of all course items and take the quiz without logging in.', 'learnpress' ),
490 + 'no'
491 + ),
492 + ),
493 + $post_id
494 + );
495 + }
496 +
497 + public function tab_author( $thepostid ) {
498 + $post = get_post( $thepostid );
499 +
500 + $author_id = $post ? $post->post_author : get_current_user_id();
501 +
502 + $options = array();
503 + // Code old only use for addon Frontend Editor v4.0.4
504 + // Code old only use for addon Co-Instructor v4.0.2
505 + $can_get_options_users = false;
506 + if ( class_exists( 'LP_Addon_Frontend_Editor_Preload' )
507 + && defined( 'LP_ADDON_FRONTEND_EDITOR_VER' )
508 + && version_compare( LP_ADDON_FRONTEND_EDITOR_VER, '4.0.5', '<' ) ) {
509 + $can_get_options_users = true;
510 + }
511 +
512 + if ( $can_get_options_users ) {
513 + $author_roles = array( ADMIN_ROLE, LP_TEACHER_ROLE );
514 + $author_roles = apply_filters( 'learn_press_course_author_role_meta_box', $author_roles );
515 + $authors = get_users( [ 'role__in' => $author_roles ] );
516 +
517 + /**
518 + * @var WP_User $author
519 + */
520 + foreach ( $authors as $author ) {
521 + $options[ $author->ID ] = $author->display_name . ' (#' . $author->ID . ')';
522 + }
523 + }
524 + // Code old only use for addon Frontend Editor v4.0.4
525 +
526 + $data_struct = [
527 + 'urlApi' => get_rest_url( null, 'lp/v1/admin/tools/search-user' ),
528 + 'dataSendApi' => [
529 + 'role_in' => ADMIN_ROLE . ',' . LP_TEACHER_ROLE,
530 + ],
531 + 'dataType' => 'users',
532 + 'keyGetValue' => [
533 + 'value' => 'ID',
534 + 'text' => '{{display_name}}(#{{ID}})',
535 + 'key_render' => [
536 + 'display_name' => 'display_name',
537 + 'user_email' => 'user_email',
538 + 'ID' => 'ID',
539 + ],
540 + ],
541 + 'setting' => [
542 + 'plugins' => array(),
543 + ],
544 + ];
545 +
546 + return apply_filters(
547 + 'lp/course/meta-box/fields/author',
548 + array(
549 + // Not use key 'post_author' on single edit course, it special key of WP, Gutenberg save will not submit this key.
550 + '_post_author' => new LP_Meta_Box_Select_Field(
551 + esc_html__( 'Author', 'learnpress' ),
552 + '',
553 + $author_id,
554 + array(
555 + 'options' => $options,
556 + 'style' => 'min-width:200px;',
557 + 'tom_select' => true,
558 + 'custom_attributes' => [ 'data-struct' => htmlentities2( json_encode( $data_struct ) ) ],
559 + )
560 + ),
561 + )
562 + );
563 + }
564 +
565 + public function tab_material( $thepostid ) {
566 + return apply_filters(
567 + 'lp/course/meta-box/fields/material',
568 + array(
569 + '_lp_course_material' => new LP_Meta_Box_Material_Fields(),
570 + )
571 + );
572 + }
573 +
574 + public function tab_assessment( $thepostid ) {
575 + $post = get_post( $thepostid );
576 +
577 + $course_result_desc = '';
578 + $course_results = get_post_meta( $thepostid, '_lp_course_result', true );
579 +
580 + $course_result_desc .= __( 'The method of evaluating a student\'s performance in a course.', 'learnpress' );
581 + $course_result_desc .= sprintf(
582 + '<br/><i style="color: red">%s</i>',
583 + __( 'Note: changing the evaluation type will affect the assessment results of student learning.', 'learnpress' )
584 + );
585 +
586 + if ( $course_results == 'evaluate_final_quiz' && ! get_post_meta( $thepostid, '_lp_final_quiz', true ) ) {
587 + $course_result_desc .= __( '<br /><strong>Note! </strong>There is no final quiz in the course. Please add a final quiz.', 'learnpress' );
588 + }
589 +
590 + $final_quizz_passing = '';
591 +
592 + $course = learn_press_get_course( $thepostid );
593 +
594 + if ( $course ) {
595 + $passing_grade = $url = '';
596 +
597 + $final_quiz = $course->get_final_quiz();
598 +
599 + if ( $final_quiz ) {
600 + $passing_grade = get_post_meta( $final_quiz, '_lp_passing_grade', true );
601 + if ( '' === (string) $passing_grade ) {
602 + $quiz_model = QuizPostModel::find( absint( $final_quiz ), true );
603 + if ( $quiz_model ) {
604 + $passing_grade = $quiz_model->get_passing_grade();
605 + } else {
606 + $passing_grade = 80;
607 + }
608 + }
609 +
610 + $url = get_edit_post_link( $final_quiz ) . '#_lp_passing_grade';
611 +
612 + $final_quizz_passing = '
613 + <div class="lp-metabox-evaluate-final_quiz">
614 + <div class="lp-metabox-evaluate-final_quiz__message">'
615 + . sprintf( esc_html__( 'Passing Grade: %s', 'learpress' ), $passing_grade . '%' ) .
616 + ' - '
617 + . sprintf( esc_html__( 'Edit: %s', 'learnpress' ), '<a href="' . esc_url_raw( $url ) . '">' . get_the_title( $final_quiz ) . '</a>' ) .
618 + '</div>
619 + </div>
620 + ';
621 + }
622 + }
623 +
624 + return apply_filters(
625 + 'lp/course/meta-box/fields/assessment',
626 + array(
627 + '_lp_course_result' => new LP_Meta_Box_Radio_Field(
628 + esc_html__( 'Evaluation', 'learnpress' ),
629 + $course_result_desc,
630 + 'evaluate_lesson',
631 + array(
632 + 'options' => learn_press_course_evaluation_methods( $thepostid, '', $final_quizz_passing ),
633 + )
634 + ),
635 + '_lp_passing_condition' => new LP_Meta_Box_Text_Field(
636 + esc_html__( 'Passing Grade(%)', 'learnpress' ),
637 + esc_html__( 'The conditions that must be achieved to finish the course.', 'learnpress' ),
638 + '80',
639 + array(
640 + 'type_input' => 'number',
641 + 'custom_attributes' => array(
642 + 'min' => '0',
643 + 'step' => '0.01',
644 + 'max' => '100',
645 + ),
646 + 'style' => 'width: 60px;',
647 + )
648 + ),
649 + )
650 + );
651 + }
652 +
653 + public function tab_extra( $thepostid ) {
654 + return apply_filters(
655 + 'lp/course/meta-box/fields/extra',
656 + array(
657 + '_lp_requirements' => new LP_Meta_Box_Extra_Field(
658 + esc_html__( 'Requirements', 'learnpress' ),
659 + '',
660 + array()
661 + ),
662 + '_lp_target_audiences' => new LP_Meta_Box_Extra_Field(
663 + esc_html__( 'Target Audience', 'learnpress' ),
664 + '',
665 + array()
666 + ),
667 + '_lp_key_features' => new LP_Meta_Box_Extra_Field(
668 + esc_html__( 'Key Features', 'learnpress' ),
669 + '',
670 + array()
671 + ),
672 + '_lp_faqs' => new LP_Meta_Box_Extra_Faq_Field(
673 + esc_html__( 'FAQs', 'learnpress' ),
674 + '',
675 + array()
676 + ),
677 + )
678 + );
679 + }
680 +
681 + public function data_tabs_sort( $a, $b ) {
682 + if ( ! isset( $a['priority'], $b['priority'] ) ) {
683 + return - 1;
684 + }
685 +
686 + if ( $a['priority'] === $b['priority'] ) {
687 + return 0;
688 + }
689 +
690 + return $a['priority'] < $b['priority'] ? - 1 : 1;
691 + }
692 +}