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/admin/views/meta-boxes/course/settings.php +769 -769 4.3.94.4.8 View file →
@@ -1,769 +1,769 @@
1 -<?php
2 -
3 -use LearnPress\Helpers\Config;
4 -use LearnPress\Models\CourseModel;
5 -use LearnPress\Models\CoursePostModel;
6 -use LearnPress\TemplateHooks\Course\AdminEditCurriculumTemplate;
7 -use LearnPress\TemplateHooks\TemplateAJAX;
8 -
9 -class LP_Meta_Box_Course extends LP_Meta_Box {
10 - /**
11 - * Instance
12 - *
13 - * @var null|LP_Meta_Box_Course
14 - */
15 - private static $instance = null;
16 -
17 - public $post_type = LP_COURSE_CPT;
18 -
19 - /**
20 - * @param WP_Post $post
21 - *
22 - * @return void
23 - */
24 - public function add_meta_boxes( $post ) {
25 - $course = CourseModel::find( $post->ID, true );
26 - $is_enable_offline_course = false;
27 - if ( $course instanceof CourseModel ) {
28 - $is_enable_offline_course = $course->get_meta_value_by_key( CoursePostModel::META_KEY_OFFLINE_COURSE, 'no' ) === 'yes';
29 - }
30 -
31 - add_meta_box(
32 - 'course-settings',
33 - esc_html__( 'Course Settings', 'learnpress' ),
34 - array( $this, 'output' ),
35 - $this->post_type,
36 - 'normal',
37 - 'high'
38 - );
39 -
40 - if ( ! $is_enable_offline_course ) {
41 - add_meta_box(
42 - 'course-editor',
43 - esc_html__( 'Curriculum', 'learnpress' ),
44 - array( $this, 'admin_editor' ),
45 - $this->post_type,
46 - 'normal',
47 - 'high'
48 - );
49 - }
50 - }
51 -
52 - public function metabox( $post_id ) {
53 - $tabs = apply_filters(
54 - 'lp_course_data_settings_tabs',
55 - array(
56 - 'general' => array(
57 - 'label' => esc_html__( 'General', 'learnpress' ),
58 - 'target' => 'general_course_data',
59 - 'icon' => 'dashicons-admin-tools',
60 - 'priority' => 10,
61 - 'content' => $this->general( $post_id ),
62 - ),
63 - 'offline' => array(
64 - 'label' => esc_html__( 'Offline Course', 'learnpress' ),
65 - 'target' => 'offline_course_data',
66 - 'icon' => 'dashicons-welcome-view-site',
67 - 'priority' => 10,
68 - 'content' => $this->tab_offline( $post_id ),
69 - ),
70 - 'price' => array(
71 - 'label' => esc_html__( 'Pricing', 'learnpress' ),
72 - 'target' => 'price_course_data',
73 - 'icon' => 'dashicons-cart',
74 - 'priority' => 20,
75 - 'content' => $this->lp_price( $post_id ),
76 - ),
77 - 'extra' => array(
78 - 'label' => esc_html__( 'Extra Information', 'learnpress' ),
79 - 'target' => 'extra_course_data',
80 - 'icon' => 'dashicons-excerpt-view',
81 - 'priority' => 30,
82 - 'content' => $this->extra( $post_id ),
83 - ),
84 - 'assessment' => array(
85 - 'label' => esc_html__( 'Assessment', 'learnpress' ),
86 - 'target' => 'assessment_course_data',
87 - 'icon' => 'dashicons-awards',
88 - 'priority' => 40,
89 - 'content' => $this->assessment( $post_id ),
90 - ),
91 - 'author' => array(
92 - 'label' => esc_html__( 'Author', 'learnpress' ),
93 - 'target' => 'author_course_data',
94 - 'icon' => 'dashicons-businessman',
95 - 'priority' => 50,
96 - 'content' => $this->author( $post_id ),
97 - ),
98 - 'material' => array(
99 - 'label' => esc_html__( 'Downloadable Materials', 'learnpress' ),
100 - 'target' => 'downloadable_material_data',
101 - 'icon' => 'dashicons-download',
102 - 'priority' => 60,
103 - 'content' => $this->lp_material( $post_id ),
104 - ),
105 - )
106 - );
107 -
108 - $tabs = apply_filters( 'learnpress/course/metabox/tabs', $tabs, $post_id );
109 -
110 - uasort( $tabs, array( __CLASS__, 'data_tabs_sort' ) );
111 -
112 - return $tabs;
113 - }
114 -
115 - public function general( $post_id ) {
116 - $course = CourseModel::find( $post_id, true );
117 - $repurchase_option_desc = sprintf(
118 - '1. %s',
119 - __(
120 - 'Reset course progress: The course progress and results of student will be removed.',
121 - 'learnpress'
122 - )
123 - );
124 - $repurchase_option_desc .= '<br/>' . sprintf(
125 - '2. %s',
126 - __(
127 - 'Keep course progress: The course progress and results of student will remain.',
128 - 'learnpress'
129 - )
130 - );
131 - $repurchase_option_desc .= '<br/>' . sprintf(
132 - '3. %s',
133 - __(
134 - 'Open popup: The student can decide whether their course progress will be reset with the confirm popup.',
135 - 'learnpress'
136 - )
137 - );
138 - $max_students_desc = esc_html__(
139 - 'The maximum number of students that can join a course. Set 0 for unlimited.',
140 - 'learnpress'
141 - );
142 - $max_students_desc .= '<br/>' . esc_html__( 'Not apply for case "No enroll requirement".', 'learnpress' );
143 -
144 - $is_enable_allow_course_repurchase = false;
145 - if ( $course instanceof CourseModel ) {
146 - $is_enable_allow_course_repurchase = $course->get_meta_value_by_key( CoursePostModel::META_KEY_ALLOW_COURSE_REPURCHASE, 'no' ) === 'yes';
147 - }
148 -
149 - $fake_students_desc = esc_html__( 'Fake students enrolled for the course.', 'learnpress' );
150 - $fake_students_desc .= '<br>' . esc_html__( 'It only to display, not calculate', 'learnpress' );
151 -
152 - return apply_filters(
153 - 'lp/course/meta-box/fields/general',
154 - array(
155 - '_lp_duration' => new LP_Meta_Box_Duration_Field(
156 - esc_html__( 'Duration', 'learnpress' ),
157 - esc_html__( 'Set to 0 for the lifetime access.', 'learnpress' ),
158 - '10 week',
159 - array(
160 - 'default_time' => 'week',
161 - 'custom_attributes' => array(
162 - 'min' => '0',
163 - 'step' => '1',
164 - ),
165 - )
166 - ),
167 - '_lp_block_expire_duration' => new LP_Meta_Box_Checkbox_Field(
168 - esc_html__( 'Block content', 'learnpress' ),
169 - esc_html__( 'When the duration expires, the course is blocked.', 'learnpress' ),
170 - 'no'
171 - ),
172 - '_lp_block_finished' => new LP_Meta_Box_Checkbox_Field(
173 - '',
174 - esc_html__( 'Block the course after the student finished this course.', 'learnpress' ),
175 - 'yes'
176 - ),
177 - '_lp_allow_course_repurchase' => new LP_Meta_Box_Checkbox_Field(
178 - __( 'Allow Repurchase', 'learnpress' ),
179 - 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' ),
180 - 'no'
181 - ),
182 - '_lp_course_repurchase_option' => new LP_Meta_Box_Select_Field(
183 - esc_html__( 'Repurchase action', 'learnpress' ),
184 - $repurchase_option_desc,
185 - 'reset',
186 - array(
187 - 'options' => array(
188 - 'reset' => esc_html__( 'Reset course progress', 'learnpress' ),
189 - 'keep' => esc_html__( 'Keep course progress', 'learnpress' ),
190 - 'popup' => esc_html__( 'Open popup', 'learnpress' ),
191 - ),
192 - 'dependency' => [
193 - 'name' => '_lp_allow_course_repurchase',
194 - 'is_disable' => ! $is_enable_allow_course_repurchase,
195 - ],
196 - //'show' => array( '_lp_allow_course_repurchase', '=', 'yes' ), // use 'show' or 'hide'
197 - )
198 - ),
199 - '_lp_level' => new LP_Meta_Box_Select_Field(
200 - esc_html__( 'Level', 'learnpress' ),
201 - esc_html__( 'Choose a difficulty level.', 'learnpress' ),
202 - 'all',
203 - array(
204 - 'options' => lp_course_level(),
205 - )
206 - ),
207 - '_lp_students' => new LP_Meta_Box_Text_Field(
208 - esc_html__( 'Fake Students Enrolled', 'learnpress' ),
209 - $fake_students_desc,
210 - 0,
211 - array(
212 - 'type_input' => 'number',
213 - 'custom_attributes' => array(
214 - 'min' => '0',
215 - 'step' => '1',
216 - ),
217 - 'style' => 'width: 70px;',
218 - )
219 - ),
220 - '_lp_max_students' => new LP_Meta_Box_Text_Field(
221 - esc_html__( 'Max student', 'learnpress' ),
222 - $max_students_desc,
223 - 0,
224 - array(
225 - 'type_input' => 'number',
226 - 'custom_attributes' => array(
227 - 'min' => '0',
228 - 'step' => '1',
229 - ),
230 - 'style' => 'width: 70px;',
231 - )
232 - ),
233 - '_lp_retake_count' => new LP_Meta_Box_Text_Field(
234 - esc_html__( 'Re-take Course', 'learnpress' ),
235 - esc_html__( 'The number of times a user can learn again from this course. To disable, set to 0.', 'learnpress' ),
236 - 0,
237 - array(
238 - 'type_input' => 'number',
239 - 'custom_attributes' => array(
240 - 'min' => '0',
241 - 'step' => '1',
242 - ),
243 - 'style' => 'width: 70px;',
244 - )
245 - ),
246 - '_lp_has_finish' => new LP_Meta_Box_Checkbox_Field(
247 - esc_html__( 'Finish button', 'learnpress' ),
248 - esc_html__( 'Allow showing the finish button when the student has completed all items but has not passed the course assessment yet.', 'learnpress' ),
249 - 'yes'
250 - ),
251 - '_lp_featured' => new LP_Meta_Box_Checkbox_Field(
252 - esc_html__( 'Featured list', 'learnpress' ),
253 - esc_html__( 'Add the course to the Featured List.', 'learnpress' ),
254 - 'no'
255 - ),
256 - '_lp_featured_review' => new LP_Meta_Box_Textarea_Field(
257 - esc_html__( 'Featured review', 'learnpress' ),
258 - esc_html__( 'A good review to promote the course.', 'learnpress' )
259 - ),
260 - '_lp_external_link_buy_course' => new LP_Meta_Box_Text_Field(
261 - esc_html__( 'External link', 'learnpress' ),
262 - esc_html__( 'Normally used for offline classes. Ex: link to a contact page. Format: https://google.com', 'learnpress' ),
263 - '',
264 - array(
265 - 'desc_tip' => 'You can apply for case: user register form.<br> You accept for user can learn courses by add manual order on backend',
266 - )
267 - ),
268 - ),
269 - $post_id
270 - );
271 - }
272 -
273 - /**
274 - * Tab setting offline course
275 - *
276 - * @param $post_id
277 - *
278 - * @return array
279 - * @since 4.2.7
280 - * @version 1.0.0
281 - */
282 - public function tab_offline( $post_id ): array {
283 - $course = CourseModel::find( $post_id, true );
284 -
285 - $is_offline_course = false;
286 - if ( $course instanceof CourseModel ) {
287 - $is_offline_course = $course->is_offline();
288 - }
289 -
290 - return apply_filters(
291 - 'lp/course/meta-box/fields/offline',
292 - array(
293 - CoursePostModel::META_KEY_OFFLINE_COURSE => new LP_Meta_Box_Checkbox_Field(
294 - esc_html__( 'Enable offline course', 'learnpress' ),
295 - esc_html__(
296 - '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.',
297 - 'learnpress'
298 - ),
299 - 'no'
300 - ),
301 - CoursePostModel::META_KEY_OFFLINE_LESSON_COUNT => new LP_Meta_Box_Text_Field(
302 - esc_html__( 'Lessons', 'learnpress' ),
303 - esc_html__( 'Total lessons of the course.', 'learnpress' ),
304 - 10,
305 - [
306 - 'type_input' => 'number',
307 - 'custom_attributes' => array(
308 - 'min' => '0',
309 - 'step' => '1',
310 - ),
311 - 'dependency' => [
312 - 'name' => '_lp_offline_course',
313 - 'is_disable' => ! $is_offline_course,
314 - ],
315 - ]
316 - ),
317 - CoursePostModel::META_KEY_DELIVER => new LP_Meta_Box_Select_Field(
318 - esc_html__( 'Delivery Type', 'learnpress' ),
319 - esc_html__( 'How your content is conveyed to students.', 'learnpress' ),
320 - 'private_1_1',
321 - [
322 - 'options' => Config::instance()->get( 'course-deliver-type' ),
323 - 'dependency' => [
324 - 'name' => '_lp_offline_course',
325 - 'is_disable' => ! $is_offline_course,
326 - ],
327 - ]
328 - ),
329 - CoursePostModel::META_KEY_ADDRESS => new LP_Meta_Box_Text_Field(
330 - esc_html__( 'Address', 'learnpress' ),
331 - esc_html__( 'You can enter the physical address of your class or specify the meeting method (e.g., Zoom, Google Meet, etc.).', 'learnpress' ),
332 - '',
333 - [
334 - 'dependency' => [
335 - 'name' => '_lp_offline_course',
336 - 'is_disable' => ! $is_offline_course,
337 - ],
338 - ]
339 - ),
340 - ),
341 - $post_id
342 - );
343 - }
344 -
345 - /**
346 - * Setting course price
347 - *
348 - * @param $post_id
349 - *
350 - * @return array
351 - * @since 4.1.5
352 - * @version 1.0.0
353 - * @author tungnx
354 - */
355 - public function lp_price( $post_id ): array {
356 - $key_exists = LP_Database::getInstance()->check_key_postmeta_exists( $post_id, '_lp_regular_price' );
357 - $price = get_post_meta( $post_id, '_lp_price', true );
358 - $regular_price = $key_exists ? get_post_meta( $post_id, '_lp_regular_price', true ) : $price;
359 - $sale_price = get_post_meta( $post_id, '_lp_sale_price', true );
360 -
361 - $is_enable_no_required_enroll = get_post_meta( $post_id, '_lp_no_required_enroll', true ) === 'yes' ? 1 : 0;
362 -
363 - return apply_filters(
364 - 'lp/course/meta-box/fields/price',
365 - array(
366 - '_lp_regular_price' => new LP_Meta_Box_Text_Field(
367 - esc_html__( 'Regular price', 'learnpress' ),
368 - sprintf( __( 'Set a regular price (<strong>%s</strong>). Leave it blank for <strong>Free</strong>.', 'learnpress' ), learn_press_get_currency() ),
369 - $regular_price,
370 - array(
371 - 'type_input' => 'text',
372 - 'custom_attributes' => array(
373 - 'min' => '0',
374 - 'step' => '0.01',
375 - ),
376 - 'style' => 'width: 150px;',
377 - 'class' => 'lp_meta_box_regular_price',
378 - 'dependency' => [
379 - 'name' => '_lp_no_required_enroll',
380 - 'is_disable' => $is_enable_no_required_enroll,
381 - ],
382 - )
383 - ),
384 - '_lp_sale_price' => new LP_Meta_Box_Text_Field(
385 - esc_html__( 'Sale price', 'learnpress' ),
386 - '<a href="#" class="lp_sale_price_schedule">' . esc_html__( 'Schedule', 'learnpress' ) . '</a>',
387 - $sale_price,
388 - array(
389 - 'type_input' => 'text',
390 - 'custom_attributes' => array(
391 - 'min' => '0',
392 - 'step' => '0.01',
393 - ),
394 - 'style' => 'width: 150px;',
395 - 'class' => 'lp_meta_box_sale_price',
396 - 'dependency' => [
397 - 'name' => '_lp_no_required_enroll',
398 - 'is_disable' => $is_enable_no_required_enroll,
399 - ],
400 - )
401 - ),
402 - '_lp_sale_start' => new LP_Meta_Box_Date_Field(
403 - esc_html__( 'Sale start dates', 'learnpress' ),
404 - '',
405 - '',
406 - array(
407 - 'wrapper_class' => 'lp_sale_start_dates_fields',
408 - 'placeholder' => _x( 'From&hellip;', 'placeholder', 'learnpress' ),
409 - 'dependency' => [
410 - 'name' => '_lp_no_required_enroll',
411 - 'is_disable' => $is_enable_no_required_enroll,
412 - ],
413 - )
414 - ),
415 - '_lp_sale_end' => new LP_Meta_Box_Date_Field(
416 - esc_html__( 'Sale end dates', 'learnpress' ),
417 - '',
418 - '',
419 - array(
420 - 'wrapper_class' => 'lp_sale_end_dates_fields',
421 - 'placeholder' => _x( 'To&hellip;', 'placeholder', 'learnpress' ),
422 - 'cancel' => true,
423 - 'dependency' => [
424 - 'name' => '_lp_no_required_enroll',
425 - 'is_disable' => $is_enable_no_required_enroll,
426 - ],
427 - )
428 - ),
429 - '_lp_price_prefix' => new LP_Meta_Box_Text_Field(
430 - esc_html__( 'Price prefix', 'learnpress' ),
431 - esc_html__( 'Show additional information placed before the price such as: Only, From, Up to...', 'learnpress' ),
432 - ''
433 - ),
434 - '_lp_price_suffix' => new LP_Meta_Box_Text_Field(
435 - esc_html__( 'Price Suffix', 'learnpress' ),
436 - esc_html__( 'Show additional information placed after the price such as: Included Tax, Per Hour, (Per Week)...', 'learnpress' ),
437 - ''
438 - ),
439 - '_lp_no_required_enroll' => new LP_Meta_Box_Checkbox_Field(
440 - esc_html__( 'There is no enrollment requirement', 'learnpress' ),
441 - esc_html__( 'Students can see the content of all course items and take the quiz without logging in.', 'learnpress' ),
442 - 'no'
443 - ),
444 - ),
445 - $post_id
446 - );
447 - }
448 -
449 - public function author( $thepostid ) {
450 - $post = get_post( $thepostid );
451 -
452 - $author_id = $post ? $post->post_author : get_current_user_id();
453 -
454 - $options = array();
455 - // Code old only use for addon Frontend Editor v4.0.4
456 - // Code old only use for addon Co-Instructor v4.0.2
457 - $can_get_options_users = false;
458 - if ( class_exists( 'LP_Addon_Frontend_Editor_Preload' )
459 - && defined( 'LP_ADDON_FRONTEND_EDITOR_VER' )
460 - && version_compare( LP_ADDON_FRONTEND_EDITOR_VER, '4.0.5', '<' ) ) {
461 - $can_get_options_users = true;
462 - }
463 -
464 - if ( $can_get_options_users ) {
465 - $author_roles = array( ADMIN_ROLE, LP_TEACHER_ROLE );
466 - $author_roles = apply_filters( 'learn_press_course_author_role_meta_box', $author_roles );
467 - $authors = get_users( [ 'role__in' => $author_roles ] );
468 -
469 - /**
470 - * @var WP_User $author
471 - */
472 - foreach ( $authors as $author ) {
473 - $options[ $author->ID ] = $author->display_name . ' (#' . $author->ID . ')';
474 - }
475 - }
476 - // Code old only use for addon Frontend Editor v4.0.4
477 -
478 - $data_struct = [
479 - 'urlApi' => get_rest_url( null, 'lp/v1/admin/tools/search-user' ),
480 - 'dataSendApi' => [
481 - 'role_in' => ADMIN_ROLE . ',' . LP_TEACHER_ROLE,
482 - ],
483 - 'dataType' => 'users',
484 - 'keyGetValue' => [
485 - 'value' => 'ID',
486 - 'text' => '{{display_name}}(#{{ID}})',
487 - 'key_render' => [
488 - 'display_name' => 'display_name',
489 - 'user_email' => 'user_email',
490 - 'ID' => 'ID',
491 - ],
492 - ],
493 - 'setting' => [
494 - 'plugins' => array(),
495 - ],
496 - ];
497 -
498 - return apply_filters(
499 - 'lp/course/meta-box/fields/author',
500 - array(
501 - // Not use key 'post_author' on single edit course, it special key of WP, Gutenberg save will not submit this key.
502 - '_post_author' => new LP_Meta_Box_Select_Field(
503 - esc_html__( 'Author', 'learnpress' ),
504 - '',
505 - $author_id,
506 - array(
507 - 'options' => $options,
508 - 'style' => 'min-width:200px;',
509 - 'tom_select' => true,
510 - 'custom_attributes' => [
511 - 'data-struct' => htmlentities2( json_encode( $data_struct ) ),
512 - ],
513 - )
514 - ),
515 - )
516 - );
517 - }
518 -
519 - public function lp_material( $thepostid ) {
520 - return apply_filters(
521 - 'lp/course/meta-box/fields/material',
522 - array(
523 - '_lp_course_material' => new LP_Meta_Box_Material_Fields(),
524 - )
525 - );
526 - }
527 -
528 - public function assessment( $thepostid ) {
529 - $post = get_post( $thepostid );
530 -
531 - $course_result_desc = '';
532 - $course_results = get_post_meta( $thepostid, '_lp_course_result', true );
533 -
534 - $course_result_desc .= __( 'The method of evaluating a student\'s performance in a course.', 'learnpress' );
535 - $course_result_desc .= sprintf(
536 - '<br/><i style="color: red">%s</i>',
537 - __( 'Note: changing the evaluation type will affect the assessment results of student learning.', 'learnpress' )
538 - );
539 -
540 - if ( $course_results == 'evaluate_final_quiz' && ! get_post_meta( $thepostid, '_lp_final_quiz', true ) ) {
541 - $course_result_desc .= __( '<br /><strong>Note! </strong>There is no final quiz in the course. Please add a final quiz.', 'learnpress' );
542 - }
543 -
544 - $final_quizz_passing = '';
545 -
546 - $course = learn_press_get_course( $thepostid );
547 -
548 - if ( $course ) {
549 - $passing_grade = $url = '';
550 -
551 - $final_quiz = $course->get_final_quiz();
552 -
553 - if ( $final_quiz ) {
554 - $passing_grade = get_post_meta( $final_quiz, '_lp_passing_grade', true );
555 - if ( '' === (string) $passing_grade ) {
556 - $quiz_model = \LearnPress\Models\QuizPostModel::find( absint( $final_quiz ), true );
557 - if ( $quiz_model ) {
558 - $passing_grade = $quiz_model->get_passing_grade();
559 - } else {
560 - $passing_grade = 80;
561 - }
562 - }
563 -
564 - $url = get_edit_post_link( $final_quiz ) . '#_lp_passing_grade';
565 - $url = apply_filters(
566 - 'learn-press/course/meta-box/assessment/final-quiz/edit-link',
567 - $url,
568 - $final_quiz,
569 - $thepostid
570 - );
571 -
572 - $final_quizz_passing = '
573 - <div class="lp-metabox-evaluate-final_quiz">
574 - <div class="lp-metabox-evaluate-final_quiz__message">'
575 - . sprintf( esc_html__( 'Passing Grade: %s', 'learpress' ), $passing_grade . '%' ) .
576 - ' - '
577 - . sprintf( esc_html__( 'Edit: %s', 'learnpress' ), '<a href="' . esc_url_raw( $url ) . '">' . get_the_title( $final_quiz ) . '</a>' ) .
578 - '</div>
579 - </div>
580 - ';
581 - }
582 - }
583 -
584 - return apply_filters(
585 - 'lp/course/meta-box/fields/assessment',
586 - array(
587 - '_lp_course_result' => new LP_Meta_Box_Radio_Field(
588 - esc_html__( 'Evaluation', 'learnpress' ),
589 - $course_result_desc,
590 - 'evaluate_lesson',
591 - array(
592 - 'options' => learn_press_course_evaluation_methods( $thepostid, '', $final_quizz_passing ),
593 - )
594 - ),
595 - '_lp_passing_condition' => new LP_Meta_Box_Text_Field(
596 - esc_html__( 'Passing Grade(%)', 'learnpress' ),
597 - esc_html__( 'The conditions that must be achieved to finish the course.', 'learnpress' ),
598 - '80',
599 - array(
600 - 'type_input' => 'number',
601 - 'custom_attributes' => array(
602 - 'min' => '0',
603 - 'step' => '0.01',
604 - 'max' => '100',
605 - ),
606 - 'style' => 'width: 60px;',
607 - )
608 - ),
609 - )
610 - );
611 - }
612 -
613 - public function extra( $thepostid ) {
614 - return apply_filters(
615 - 'lp/course/meta-box/fields/extra',
616 - array(
617 - '_lp_requirements' => new LP_Meta_Box_Extra_Field(
618 - esc_html__( 'Requirements', 'learnpress' ),
619 - '',
620 - array()
621 - ),
622 - '_lp_target_audiences' => new LP_Meta_Box_Extra_Field(
623 - esc_html__( 'Target Audience', 'learnpress' ),
624 - '',
625 - array()
626 - ),
627 - '_lp_key_features' => new LP_Meta_Box_Extra_Field(
628 - esc_html__( 'Key Features', 'learnpress' ),
629 - '',
630 - array()
631 - ),
632 - '_lp_faqs' => new LP_Meta_Box_Extra_Faq_Field(
633 - esc_html__( 'FAQs', 'learnpress' ),
634 - '',
635 - array()
636 - ),
637 - )
638 - );
639 - }
640 -
641 - public function output( $post ) {
642 - parent::output( $post );
643 -
644 - $course_id = $post->ID;
645 - $courseModel = CourseModel::find( $course_id, true );
646 - if ( ! $courseModel instanceof CourseModel ) {
647 - return;
648 - }
649 -
650 - do_action( 'learn-press/admin/course/edit-setting/layout', $courseModel->ID );
651 - }
652 -
653 - /**
654 - * Template Editor Curriculum.
655 - *
656 - * @return void
657 - */
658 - public function admin_editor() {
659 - global $post;
660 -
661 - $course_id = $post->ID;
662 - $courseModel = CourseModel::find( $course_id, true );
663 - if ( ! $courseModel instanceof CourseModel ) {
664 - return;
665 - }
666 -
667 - do_action( 'learn-press/admin/edit-curriculum/layout', $courseModel );
668 - }
669 -
670 - /*public function save( $post_id ) {
671 - if ( ! empty( $this->metabox( $post_id ) ) ) {
672 - foreach ( $this->metabox( $post_id ) as $key => $tab_content ) {
673 - if ( isset( $tab_content['content'] ) ) {
674 - foreach ( $tab_content['content'] as $meta_key => $object ) {
675 - if ( is_a( $object, 'LP_Meta_Box_Field' ) ) {
676 - $object->id = $meta_key;
677 - $object->save( $post_id );
678 - }
679 - }
680 - }
681 - }
682 - }
683 -
684 - $course = learn_press_get_course( $post_id );
685 -
686 - // Check price is valid.
687 - $price_regular = LP_Request::get( '_lp_regular_price', 0, 'float' );
688 - $price_sale = LP_Request::get( '_lp_sale_price', 0, 'float' );
689 - if ( $price_regular <= 0 ) {
690 - $price_sale = 0;
691 - update_post_meta( $post_id, '_lp_regular_price', '' );
692 - }
693 -
694 - if ( $price_sale >= $price_regular || $price_sale < 0 ) {
695 - update_post_meta( $post_id, '_lp_sale_price', '' );
696 - }
697 - // End check price.
698 -
699 - $evaluation = LP_Request::get_param( '_lp_course_result', '', 'text', 'post' );
700 - //$passing_condition = isset( $_POST['_lp_passing_condition'] ) ? absint( wp_unslash( $_POST['_lp_passing_condition'] ) ) : 0;
701 -
702 - // Update Final Quiz. - Nhamdv
703 - if ( $evaluation == 'evaluate_final_quiz' ) {
704 - $items = $course->get_item_ids();
705 -
706 - if ( $items ) {
707 - foreach ( $items as $item ) {
708 - if ( learn_press_get_post_type( $item ) === LP_QUIZ_CPT ) {
709 - $final_quiz = $item;
710 - }
711 - }
712 - }
713 -
714 - if ( isset( $final_quiz ) ) {
715 - update_post_meta( $post_id, '_lp_final_quiz', $final_quiz );
716 - } else {
717 - delete_post_meta( $post_id, '_lp_final_quiz' );
718 - }
719 - } else {
720 - delete_post_meta( $post_id, '_lp_final_quiz' );
721 - }
722 -
723 - $author = isset( $_POST['_lp_course_author'] ) ? wp_unslash( $_POST['_lp_course_author'] ) : '';
724 - if ( ! empty( $author ) ) {
725 - global $wpdb;
726 -
727 - $wpdb->update( $wpdb->posts, array( 'post_author' => $author ), array( 'ID' => $post_id ) );
728 - }
729 - }*/
730 -
731 - private static function data_tabs_sort( $a, $b ) {
732 - if ( ! isset( $a['priority'], $b['priority'] ) ) {
733 - return - 1;
734 - }
735 -
736 - if ( $a['priority'] === $b['priority'] ) {
737 - return 0;
738 - }
739 -
740 - return $a['priority'] < $b['priority'] ? - 1 : 1;
741 - }
742 -
743 - public static function save_eduma_child_metabox_v3( $post_id ) {
744 - $general = apply_filters( 'learn_press_course_settings_meta_box_args', array( 'fields' => array() ) );
745 -
746 - if ( ! empty( $general['fields'] ) ) {
747 - foreach ( $general['fields'] as $field ) {
748 - $value = isset( $_POST[ $field['id'] ] ) ? wp_unslash( $_POST[ $field['id'] ] ) : '';
749 -
750 - update_post_meta( $post_id, $field['id'], $value );
751 - }
752 - }
753 - }
754 -
755 - /**
756 - * Get instance
757 - *
758 - * @return LP_Meta_Box_Course
759 - */
760 - public static function instance(): LP_Meta_Box_Course {
761 - if ( ! self::$instance ) {
762 - self::$instance = new self();
763 - }
764 -
765 - return self::$instance;
766 - }
767 -}
768 -
769 -LP_Meta_Box_Course::instance();
1 +<?php
2 +
3 +use LearnPress\Helpers\Config;
4 +use LearnPress\Models\CourseModel;
5 +use LearnPress\Models\CoursePostModel;
6 +use LearnPress\TemplateHooks\Course\AdminEditCurriculumTemplate;
7 +use LearnPress\TemplateHooks\TemplateAJAX;
8 +
9 +class LP_Meta_Box_Course extends LP_Meta_Box {
10 + /**
11 + * Instance
12 + *
13 + * @var null|LP_Meta_Box_Course
14 + */
15 + private static $instance = null;
16 +
17 + public $post_type = LP_COURSE_CPT;
18 +
19 + /**
20 + * @param WP_Post $post
21 + *
22 + * @return void
23 + */
24 + public function add_meta_boxes( $post ) {
25 + $course = CourseModel::find( $post->ID, true );
26 + $is_enable_offline_course = false;
27 + if ( $course instanceof CourseModel ) {
28 + $is_enable_offline_course = $course->get_meta_value_by_key( CoursePostModel::META_KEY_OFFLINE_COURSE, 'no' ) === 'yes';
29 + }
30 +
31 + add_meta_box(
32 + 'course-settings',
33 + esc_html__( 'Course Settings', 'learnpress' ),
34 + array( $this, 'output' ),
35 + $this->post_type,
36 + 'normal',
37 + 'high'
38 + );
39 +
40 + if ( ! $is_enable_offline_course ) {
41 + add_meta_box(
42 + 'course-editor',
43 + esc_html__( 'Curriculum', 'learnpress' ),
44 + array( $this, 'admin_editor' ),
45 + $this->post_type,
46 + 'normal',
47 + 'high'
48 + );
49 + }
50 + }
51 +
52 + public function metabox( $post_id ) {
53 + $tabs = apply_filters(
54 + 'lp_course_data_settings_tabs',
55 + array(
56 + 'general' => array(
57 + 'label' => esc_html__( 'General', 'learnpress' ),
58 + 'target' => 'general_course_data',
59 + 'icon' => 'dashicons-admin-tools',
60 + 'priority' => 10,
61 + 'content' => $this->general( $post_id ),
62 + ),
63 + 'offline' => array(
64 + 'label' => esc_html__( 'Offline Course', 'learnpress' ),
65 + 'target' => 'offline_course_data',
66 + 'icon' => 'dashicons-welcome-view-site',
67 + 'priority' => 10,
68 + 'content' => $this->tab_offline( $post_id ),
69 + ),
70 + 'price' => array(
71 + 'label' => esc_html__( 'Pricing', 'learnpress' ),
72 + 'target' => 'price_course_data',
73 + 'icon' => 'dashicons-cart',
74 + 'priority' => 20,
75 + 'content' => $this->lp_price( $post_id ),
76 + ),
77 + 'extra' => array(
78 + 'label' => esc_html__( 'Extra Information', 'learnpress' ),
79 + 'target' => 'extra_course_data',
80 + 'icon' => 'dashicons-excerpt-view',
81 + 'priority' => 30,
82 + 'content' => $this->extra( $post_id ),
83 + ),
84 + 'assessment' => array(
85 + 'label' => esc_html__( 'Assessment', 'learnpress' ),
86 + 'target' => 'assessment_course_data',
87 + 'icon' => 'dashicons-awards',
88 + 'priority' => 40,
89 + 'content' => $this->assessment( $post_id ),
90 + ),
91 + 'author' => array(
92 + 'label' => esc_html__( 'Author', 'learnpress' ),
93 + 'target' => 'author_course_data',
94 + 'icon' => 'dashicons-businessman',
95 + 'priority' => 50,
96 + 'content' => $this->author( $post_id ),
97 + ),
98 + 'material' => array(
99 + 'label' => esc_html__( 'Downloadable Materials', 'learnpress' ),
100 + 'target' => 'downloadable_material_data',
101 + 'icon' => 'dashicons-download',
102 + 'priority' => 60,
103 + 'content' => $this->lp_material( $post_id ),
104 + ),
105 + )
106 + );
107 +
108 + $tabs = apply_filters( 'learnpress/course/metabox/tabs', $tabs, $post_id );
109 +
110 + uasort( $tabs, array( __CLASS__, 'data_tabs_sort' ) );
111 +
112 + return $tabs;
113 + }
114 +
115 + public function general( $post_id ) {
116 + $course = CourseModel::find( $post_id, true );
117 + $repurchase_option_desc = sprintf(
118 + '1. %s',
119 + __(
120 + 'Reset course progress: The course progress and results of student will be removed.',
121 + 'learnpress'
122 + )
123 + );
124 + $repurchase_option_desc .= '<br/>' . sprintf(
125 + '2. %s',
126 + __(
127 + 'Keep course progress: The course progress and results of student will remain.',
128 + 'learnpress'
129 + )
130 + );
131 + $repurchase_option_desc .= '<br/>' . sprintf(
132 + '3. %s',
133 + __(
134 + 'Open popup: The student can decide whether their course progress will be reset with the confirm popup.',
135 + 'learnpress'
136 + )
137 + );
138 + $max_students_desc = esc_html__(
139 + 'The maximum number of students that can join a course. Set 0 for unlimited.',
140 + 'learnpress'
141 + );
142 + $max_students_desc .= '<br/>' . esc_html__( 'Not apply for case "No enroll requirement".', 'learnpress' );
143 +
144 + $is_enable_allow_course_repurchase = false;
145 + if ( $course instanceof CourseModel ) {
146 + $is_enable_allow_course_repurchase = $course->get_meta_value_by_key( CoursePostModel::META_KEY_ALLOW_COURSE_REPURCHASE, 'no' ) === 'yes';
147 + }
148 +
149 + $fake_students_desc = esc_html__( 'Fake students enrolled for the course.', 'learnpress' );
150 + $fake_students_desc .= '<br>' . esc_html__( 'It only to display, not calculate', 'learnpress' );
151 +
152 + return apply_filters(
153 + 'lp/course/meta-box/fields/general',
154 + array(
155 + '_lp_duration' => new LP_Meta_Box_Duration_Field(
156 + esc_html__( 'Duration', 'learnpress' ),
157 + esc_html__( 'Set to 0 for the lifetime access.', 'learnpress' ),
158 + '10 week',
159 + array(
160 + 'default_time' => 'week',
161 + 'custom_attributes' => array(
162 + 'min' => '0',
163 + 'step' => '1',
164 + ),
165 + )
166 + ),
167 + '_lp_block_expire_duration' => new LP_Meta_Box_Checkbox_Field(
168 + esc_html__( 'Block content', 'learnpress' ),
169 + esc_html__( 'When the duration expires, the course is blocked.', 'learnpress' ),
170 + 'no'
171 + ),
172 + '_lp_block_finished' => new LP_Meta_Box_Checkbox_Field(
173 + '',
174 + esc_html__( 'Block the course after the student finished this course.', 'learnpress' ),
175 + 'yes'
176 + ),
177 + '_lp_allow_course_repurchase' => new LP_Meta_Box_Checkbox_Field(
178 + __( 'Allow Repurchase', 'learnpress' ),
179 + 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' ),
180 + 'no'
181 + ),
182 + '_lp_course_repurchase_option' => new LP_Meta_Box_Select_Field(
183 + esc_html__( 'Repurchase action', 'learnpress' ),
184 + $repurchase_option_desc,
185 + 'reset',
186 + array(
187 + 'options' => array(
188 + 'reset' => esc_html__( 'Reset course progress', 'learnpress' ),
189 + 'keep' => esc_html__( 'Keep course progress', 'learnpress' ),
190 + 'popup' => esc_html__( 'Open popup', 'learnpress' ),
191 + ),
192 + 'dependency' => [
193 + 'name' => '_lp_allow_course_repurchase',
194 + 'is_disable' => ! $is_enable_allow_course_repurchase,
195 + ],
196 + //'show' => array( '_lp_allow_course_repurchase', '=', 'yes' ), // use 'show' or 'hide'
197 + )
198 + ),
199 + '_lp_level' => new LP_Meta_Box_Select_Field(
200 + esc_html__( 'Level', 'learnpress' ),
201 + esc_html__( 'Choose a difficulty level.', 'learnpress' ),
202 + 'all',
203 + array(
204 + 'options' => lp_course_level(),
205 + )
206 + ),
207 + '_lp_students' => new LP_Meta_Box_Text_Field(
208 + esc_html__( 'Fake Students Enrolled', 'learnpress' ),
209 + $fake_students_desc,
210 + 0,
211 + array(
212 + 'type_input' => 'number',
213 + 'custom_attributes' => array(
214 + 'min' => '0',
215 + 'step' => '1',
216 + ),
217 + 'style' => 'width: 70px;',
218 + )
219 + ),
220 + '_lp_max_students' => new LP_Meta_Box_Text_Field(
221 + esc_html__( 'Max student', 'learnpress' ),
222 + $max_students_desc,
223 + 0,
224 + array(
225 + 'type_input' => 'number',
226 + 'custom_attributes' => array(
227 + 'min' => '0',
228 + 'step' => '1',
229 + ),
230 + 'style' => 'width: 70px;',
231 + )
232 + ),
233 + '_lp_retake_count' => new LP_Meta_Box_Text_Field(
234 + esc_html__( 'Re-take Course', 'learnpress' ),
235 + esc_html__( 'The number of times a user can learn again from this course. To disable, set to 0.', 'learnpress' ),
236 + 0,
237 + array(
238 + 'type_input' => 'number',
239 + 'custom_attributes' => array(
240 + 'min' => '0',
241 + 'step' => '1',
242 + ),
243 + 'style' => 'width: 70px;',
244 + )
245 + ),
246 + '_lp_has_finish' => new LP_Meta_Box_Checkbox_Field(
247 + esc_html__( 'Finish button', 'learnpress' ),
248 + esc_html__( 'Allow showing the finish button when the student has completed all items but has not passed the course assessment yet.', 'learnpress' ),
249 + 'yes'
250 + ),
251 + '_lp_featured' => new LP_Meta_Box_Checkbox_Field(
252 + esc_html__( 'Featured list', 'learnpress' ),
253 + esc_html__( 'Add the course to the Featured List.', 'learnpress' ),
254 + 'no'
255 + ),
256 + '_lp_featured_review' => new LP_Meta_Box_Textarea_Field(
257 + esc_html__( 'Featured review', 'learnpress' ),
258 + esc_html__( 'A good review to promote the course.', 'learnpress' )
259 + ),
260 + '_lp_external_link_buy_course' => new LP_Meta_Box_Text_Field(
261 + esc_html__( 'External link', 'learnpress' ),
262 + esc_html__( 'Normally used for offline classes. Ex: link to a contact page. Format: https://google.com', 'learnpress' ),
263 + '',
264 + array(
265 + 'desc_tip' => 'You can apply for case: user register form.<br> You accept for user can learn courses by add manual order on backend',
266 + )
267 + ),
268 + ),
269 + $post_id
270 + );
271 + }
272 +
273 + /**
274 + * Tab setting offline course
275 + *
276 + * @param $post_id
277 + *
278 + * @return array
279 + * @since 4.2.7
280 + * @version 1.0.0
281 + */
282 + public function tab_offline( $post_id ): array {
283 + $course = CourseModel::find( $post_id, true );
284 +
285 + $is_offline_course = false;
286 + if ( $course instanceof CourseModel ) {
287 + $is_offline_course = $course->is_offline();
288 + }
289 +
290 + return apply_filters(
291 + 'lp/course/meta-box/fields/offline',
292 + array(
293 + CoursePostModel::META_KEY_OFFLINE_COURSE => new LP_Meta_Box_Checkbox_Field(
294 + esc_html__( 'Enable offline course', 'learnpress' ),
295 + esc_html__(
296 + '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.',
297 + 'learnpress'
298 + ),
299 + 'no'
300 + ),
301 + CoursePostModel::META_KEY_OFFLINE_LESSON_COUNT => new LP_Meta_Box_Text_Field(
302 + esc_html__( 'Lessons', 'learnpress' ),
303 + esc_html__( 'Total lessons of the course.', 'learnpress' ),
304 + 10,
305 + [
306 + 'type_input' => 'number',
307 + 'custom_attributes' => array(
308 + 'min' => '0',
309 + 'step' => '1',
310 + ),
311 + 'dependency' => [
312 + 'name' => '_lp_offline_course',
313 + 'is_disable' => ! $is_offline_course,
314 + ],
315 + ]
316 + ),
317 + CoursePostModel::META_KEY_DELIVER => new LP_Meta_Box_Select_Field(
318 + esc_html__( 'Delivery Type', 'learnpress' ),
319 + esc_html__( 'How your content is conveyed to students.', 'learnpress' ),
320 + 'private_1_1',
321 + [
322 + 'options' => Config::instance()->get( 'course-deliver-type' ),
323 + 'dependency' => [
324 + 'name' => '_lp_offline_course',
325 + 'is_disable' => ! $is_offline_course,
326 + ],
327 + ]
328 + ),
329 + CoursePostModel::META_KEY_ADDRESS => new LP_Meta_Box_Text_Field(
330 + esc_html__( 'Address', 'learnpress' ),
331 + esc_html__( 'You can enter the physical address of your class or specify the meeting method (e.g., Zoom, Google Meet, etc.).', 'learnpress' ),
332 + '',
333 + [
334 + 'dependency' => [
335 + 'name' => '_lp_offline_course',
336 + 'is_disable' => ! $is_offline_course,
337 + ],
338 + ]
339 + ),
340 + ),
341 + $post_id
342 + );
343 + }
344 +
345 + /**
346 + * Setting course price
347 + *
348 + * @param $post_id
349 + *
350 + * @return array
351 + * @since 4.1.5
352 + * @version 1.0.0
353 + * @author tungnx
354 + */
355 + public function lp_price( $post_id ): array {
356 + $key_exists = LP_Database::getInstance()->check_key_postmeta_exists( $post_id, '_lp_regular_price' );
357 + $price = get_post_meta( $post_id, '_lp_price', true );
358 + $regular_price = $key_exists ? get_post_meta( $post_id, '_lp_regular_price', true ) : $price;
359 + $sale_price = get_post_meta( $post_id, '_lp_sale_price', true );
360 +
361 + $is_enable_no_required_enroll = get_post_meta( $post_id, '_lp_no_required_enroll', true ) === 'yes' ? 1 : 0;
362 +
363 + return apply_filters(
364 + 'lp/course/meta-box/fields/price',
365 + array(
366 + '_lp_regular_price' => new LP_Meta_Box_Text_Field(
367 + esc_html__( 'Regular price', 'learnpress' ),
368 + sprintf( __( 'Set a regular price (<strong>%s</strong>). Leave it blank for <strong>Free</strong>.', 'learnpress' ), learn_press_get_currency() ),
369 + $regular_price,
370 + array(
371 + 'type_input' => 'text',
372 + 'custom_attributes' => array(
373 + 'min' => '0',
374 + 'step' => '0.01',
375 + ),
376 + 'style' => 'width: 150px;',
377 + 'class' => 'lp_meta_box_regular_price',
378 + 'dependency' => [
379 + 'name' => '_lp_no_required_enroll',
380 + 'is_disable' => $is_enable_no_required_enroll,
381 + ],
382 + )
383 + ),
384 + '_lp_sale_price' => new LP_Meta_Box_Text_Field(
385 + esc_html__( 'Sale price', 'learnpress' ),
386 + '<a href="#" class="lp_sale_price_schedule">' . esc_html__( 'Schedule', 'learnpress' ) . '</a>',
387 + $sale_price,
388 + array(
389 + 'type_input' => 'text',
390 + 'custom_attributes' => array(
391 + 'min' => '0',
392 + 'step' => '0.01',
393 + ),
394 + 'style' => 'width: 150px;',
395 + 'class' => 'lp_meta_box_sale_price',
396 + 'dependency' => [
397 + 'name' => '_lp_no_required_enroll',
398 + 'is_disable' => $is_enable_no_required_enroll,
399 + ],
400 + )
401 + ),
402 + '_lp_sale_start' => new LP_Meta_Box_Date_Field(
403 + esc_html__( 'Sale start dates', 'learnpress' ),
404 + '',
405 + '',
406 + array(
407 + 'wrapper_class' => 'lp_sale_start_dates_fields',
408 + 'placeholder' => _x( 'From&hellip;', 'placeholder', 'learnpress' ),
409 + 'dependency' => [
410 + 'name' => '_lp_no_required_enroll',
411 + 'is_disable' => $is_enable_no_required_enroll,
412 + ],
413 + )
414 + ),
415 + '_lp_sale_end' => new LP_Meta_Box_Date_Field(
416 + esc_html__( 'Sale end dates', 'learnpress' ),
417 + '',
418 + '',
419 + array(
420 + 'wrapper_class' => 'lp_sale_end_dates_fields',
421 + 'placeholder' => _x( 'To&hellip;', 'placeholder', 'learnpress' ),
422 + 'cancel' => true,
423 + 'dependency' => [
424 + 'name' => '_lp_no_required_enroll',
425 + 'is_disable' => $is_enable_no_required_enroll,
426 + ],
427 + )
428 + ),
429 + '_lp_price_prefix' => new LP_Meta_Box_Text_Field(
430 + esc_html__( 'Price prefix', 'learnpress' ),
431 + esc_html__( 'Show additional information placed before the price such as: Only, From, Up to...', 'learnpress' ),
432 + ''
433 + ),
434 + '_lp_price_suffix' => new LP_Meta_Box_Text_Field(
435 + esc_html__( 'Price Suffix', 'learnpress' ),
436 + esc_html__( 'Show additional information placed after the price such as: Included Tax, Per Hour, (Per Week)...', 'learnpress' ),
437 + ''
438 + ),
439 + '_lp_no_required_enroll' => new LP_Meta_Box_Checkbox_Field(
440 + esc_html__( 'There is no enrollment requirement', 'learnpress' ),
441 + esc_html__( 'Students can see the content of all course items and take the quiz without logging in.', 'learnpress' ),
442 + 'no'
443 + ),
444 + ),
445 + $post_id
446 + );
447 + }
448 +
449 + public function author( $thepostid ) {
450 + $post = get_post( $thepostid );
451 +
452 + $author_id = $post ? $post->post_author : get_current_user_id();
453 +
454 + $options = array();
455 + // Code old only use for addon Frontend Editor v4.0.4
456 + // Code old only use for addon Co-Instructor v4.0.2
457 + $can_get_options_users = false;
458 + if ( class_exists( 'LP_Addon_Frontend_Editor_Preload' )
459 + && defined( 'LP_ADDON_FRONTEND_EDITOR_VER' )
460 + && version_compare( LP_ADDON_FRONTEND_EDITOR_VER, '4.0.5', '<' ) ) {
461 + $can_get_options_users = true;
462 + }
463 +
464 + if ( $can_get_options_users ) {
465 + $author_roles = array( ADMIN_ROLE, LP_TEACHER_ROLE );
466 + $author_roles = apply_filters( 'learn_press_course_author_role_meta_box', $author_roles );
467 + $authors = get_users( [ 'role__in' => $author_roles ] );
468 +
469 + /**
470 + * @var WP_User $author
471 + */
472 + foreach ( $authors as $author ) {
473 + $options[ $author->ID ] = $author->display_name . ' (#' . $author->ID . ')';
474 + }
475 + }
476 + // Code old only use for addon Frontend Editor v4.0.4
477 +
478 + $data_struct = [
479 + 'urlApi' => get_rest_url( null, 'lp/v1/admin/tools/search-user' ),
480 + 'dataSendApi' => [
481 + 'role_in' => ADMIN_ROLE . ',' . LP_TEACHER_ROLE,
482 + ],
483 + 'dataType' => 'users',
484 + 'keyGetValue' => [
485 + 'value' => 'ID',
486 + 'text' => '{{display_name}}(#{{ID}})',
487 + 'key_render' => [
488 + 'display_name' => 'display_name',
489 + 'user_email' => 'user_email',
490 + 'ID' => 'ID',
491 + ],
492 + ],
493 + 'setting' => [
494 + 'plugins' => array(),
495 + ],
496 + ];
497 +
498 + return apply_filters(
499 + 'lp/course/meta-box/fields/author',
500 + array(
501 + // Not use key 'post_author' on single edit course, it special key of WP, Gutenberg save will not submit this key.
502 + '_post_author' => new LP_Meta_Box_Select_Field(
503 + esc_html__( 'Author', 'learnpress' ),
504 + '',
505 + $author_id,
506 + array(
507 + 'options' => $options,
508 + 'style' => 'min-width:200px;',
509 + 'tom_select' => true,
510 + 'custom_attributes' => [
511 + 'data-struct' => htmlentities2( json_encode( $data_struct ) ),
512 + ],
513 + )
514 + ),
515 + )
516 + );
517 + }
518 +
519 + public function lp_material( $thepostid ) {
520 + return apply_filters(
521 + 'lp/course/meta-box/fields/material',
522 + array(
523 + '_lp_course_material' => new LP_Meta_Box_Material_Fields(),
524 + )
525 + );
526 + }
527 +
528 + public function assessment( $thepostid ) {
529 + $post = get_post( $thepostid );
530 +
531 + $course_result_desc = '';
532 + $course_results = get_post_meta( $thepostid, '_lp_course_result', true );
533 +
534 + $course_result_desc .= __( 'The method of evaluating a student\'s performance in a course.', 'learnpress' );
535 + $course_result_desc .= sprintf(
536 + '<br/><i style="color: red">%s</i>',
537 + __( 'Note: changing the evaluation type will affect the assessment results of student learning.', 'learnpress' )
538 + );
539 +
540 + if ( $course_results == 'evaluate_final_quiz' && ! get_post_meta( $thepostid, '_lp_final_quiz', true ) ) {
541 + $course_result_desc .= __( '<br /><strong>Note! </strong>There is no final quiz in the course. Please add a final quiz.', 'learnpress' );
542 + }
543 +
544 + $final_quizz_passing = '';
545 +
546 + $course = learn_press_get_course( $thepostid );
547 +
548 + if ( $course ) {
549 + $passing_grade = $url = '';
550 +
551 + $final_quiz = $course->get_final_quiz();
552 +
553 + if ( $final_quiz ) {
554 + $passing_grade = get_post_meta( $final_quiz, '_lp_passing_grade', true );
555 + if ( '' === (string) $passing_grade ) {
556 + $quiz_model = \LearnPress\Models\QuizPostModel::find( absint( $final_quiz ), true );
557 + if ( $quiz_model ) {
558 + $passing_grade = $quiz_model->get_passing_grade();
559 + } else {
560 + $passing_grade = 80;
561 + }
562 + }
563 +
564 + $url = get_edit_post_link( $final_quiz ) . '#_lp_passing_grade';
565 + $url = apply_filters(
566 + 'learn-press/course/meta-box/assessment/final-quiz/edit-link',
567 + $url,
568 + $final_quiz,
569 + $thepostid
570 + );
571 +
572 + $final_quizz_passing = '
573 + <div class="lp-metabox-evaluate-final_quiz">
574 + <div class="lp-metabox-evaluate-final_quiz__message">'
575 + . sprintf( esc_html__( 'Passing Grade: %s', 'learpress' ), $passing_grade . '%' ) .
576 + ' - '
577 + . sprintf( esc_html__( 'Edit: %s', 'learnpress' ), '<a href="' . esc_url_raw( $url ) . '">' . get_the_title( $final_quiz ) . '</a>' ) .
578 + '</div>
579 + </div>
580 + ';
581 + }
582 + }
583 +
584 + return apply_filters(
585 + 'lp/course/meta-box/fields/assessment',
586 + array(
587 + '_lp_course_result' => new LP_Meta_Box_Radio_Field(
588 + esc_html__( 'Evaluation', 'learnpress' ),
589 + $course_result_desc,
590 + 'evaluate_lesson',
591 + array(
592 + 'options' => learn_press_course_evaluation_methods( $thepostid, '', $final_quizz_passing ),
593 + )
594 + ),
595 + '_lp_passing_condition' => new LP_Meta_Box_Text_Field(
596 + esc_html__( 'Passing Grade(%)', 'learnpress' ),
597 + esc_html__( 'The conditions that must be achieved to finish the course.', 'learnpress' ),
598 + '80',
599 + array(
600 + 'type_input' => 'number',
601 + 'custom_attributes' => array(
602 + 'min' => '0',
603 + 'step' => '0.01',
604 + 'max' => '100',
605 + ),
606 + 'style' => 'width: 60px;',
607 + )
608 + ),
609 + )
610 + );
611 + }
612 +
613 + public function extra( $thepostid ) {
614 + return apply_filters(
615 + 'lp/course/meta-box/fields/extra',
616 + array(
617 + '_lp_requirements' => new LP_Meta_Box_Extra_Field(
618 + esc_html__( 'Requirements', 'learnpress' ),
619 + '',
620 + array()
621 + ),
622 + '_lp_target_audiences' => new LP_Meta_Box_Extra_Field(
623 + esc_html__( 'Target Audience', 'learnpress' ),
624 + '',
625 + array()
626 + ),
627 + '_lp_key_features' => new LP_Meta_Box_Extra_Field(
628 + esc_html__( 'Key Features', 'learnpress' ),
629 + '',
630 + array()
631 + ),
632 + '_lp_faqs' => new LP_Meta_Box_Extra_Faq_Field(
633 + esc_html__( 'FAQs', 'learnpress' ),
634 + '',
635 + array()
636 + ),
637 + )
638 + );
639 + }
640 +
641 + public function output( $post ) {
642 + parent::output( $post );
643 +
644 + $course_id = $post->ID;
645 + $courseModel = CourseModel::find( $course_id, true );
646 + if ( ! $courseModel instanceof CourseModel ) {
647 + return;
648 + }
649 +
650 + do_action( 'learn-press/admin/course/edit-setting/layout', $courseModel->ID );
651 + }
652 +
653 + /**
654 + * Template Editor Curriculum.
655 + *
656 + * @return void
657 + */
658 + public function admin_editor() {
659 + global $post;
660 +
661 + $course_id = $post->ID;
662 + $courseModel = CourseModel::find( $course_id, true );
663 + if ( ! $courseModel instanceof CourseModel ) {
664 + return;
665 + }
666 +
667 + do_action( 'learn-press/admin/edit-curriculum/layout', $courseModel );
668 + }
669 +
670 + /*public function save( $post_id ) {
671 + if ( ! empty( $this->metabox( $post_id ) ) ) {
672 + foreach ( $this->metabox( $post_id ) as $key => $tab_content ) {
673 + if ( isset( $tab_content['content'] ) ) {
674 + foreach ( $tab_content['content'] as $meta_key => $object ) {
675 + if ( is_a( $object, 'LP_Meta_Box_Field' ) ) {
676 + $object->id = $meta_key;
677 + $object->save( $post_id );
678 + }
679 + }
680 + }
681 + }
682 + }
683 +
684 + $course = learn_press_get_course( $post_id );
685 +
686 + // Check price is valid.
687 + $price_regular = LP_Request::get( '_lp_regular_price', 0, 'float' );
688 + $price_sale = LP_Request::get( '_lp_sale_price', 0, 'float' );
689 + if ( $price_regular <= 0 ) {
690 + $price_sale = 0;
691 + update_post_meta( $post_id, '_lp_regular_price', '' );
692 + }
693 +
694 + if ( $price_sale >= $price_regular || $price_sale < 0 ) {
695 + update_post_meta( $post_id, '_lp_sale_price', '' );
696 + }
697 + // End check price.
698 +
699 + $evaluation = LP_Request::get_param( '_lp_course_result', '', 'text', 'post' );
700 + //$passing_condition = isset( $_POST['_lp_passing_condition'] ) ? absint( wp_unslash( $_POST['_lp_passing_condition'] ) ) : 0;
701 +
702 + // Update Final Quiz. - Nhamdv
703 + if ( $evaluation == 'evaluate_final_quiz' ) {
704 + $items = $course->get_item_ids();
705 +
706 + if ( $items ) {
707 + foreach ( $items as $item ) {
708 + if ( learn_press_get_post_type( $item ) === LP_QUIZ_CPT ) {
709 + $final_quiz = $item;
710 + }
711 + }
712 + }
713 +
714 + if ( isset( $final_quiz ) ) {
715 + update_post_meta( $post_id, '_lp_final_quiz', $final_quiz );
716 + } else {
717 + delete_post_meta( $post_id, '_lp_final_quiz' );
718 + }
719 + } else {
720 + delete_post_meta( $post_id, '_lp_final_quiz' );
721 + }
722 +
723 + $author = isset( $_POST['_lp_course_author'] ) ? wp_unslash( $_POST['_lp_course_author'] ) : '';
724 + if ( ! empty( $author ) ) {
725 + global $wpdb;
726 +
727 + $wpdb->update( $wpdb->posts, array( 'post_author' => $author ), array( 'ID' => $post_id ) );
728 + }
729 + }*/
730 +
731 + private static function data_tabs_sort( $a, $b ) {
732 + if ( ! isset( $a['priority'], $b['priority'] ) ) {
733 + return - 1;
734 + }
735 +
736 + if ( $a['priority'] === $b['priority'] ) {
737 + return 0;
738 + }
739 +
740 + return $a['priority'] < $b['priority'] ? - 1 : 1;
741 + }
742 +
743 + public static function save_eduma_child_metabox_v3( $post_id ) {
744 + $general = apply_filters( 'learn_press_course_settings_meta_box_args', array( 'fields' => array() ) );
745 +
746 + if ( ! empty( $general['fields'] ) ) {
747 + foreach ( $general['fields'] as $field ) {
748 + $value = isset( $_POST[ $field['id'] ] ) ? wp_unslash( $_POST[ $field['id'] ] ) : '';
749 +
750 + update_post_meta( $post_id, $field['id'], $value );
751 + }
752 + }
753 + }
754 +
755 + /**
756 + * Get instance
757 + *
758 + * @return LP_Meta_Box_Course
759 + */
760 + public static function instance(): LP_Meta_Box_Course {
761 + if ( ! self::$instance ) {
762 + self::$instance = new self();
763 + }
764 +
765 + return self::$instance;
766 + }
767 +}
768 +
769 +LP_Meta_Box_Course::instance();