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 +316 -282 4.1.74.4.8 View file →
@@ -1,6 +1,12 @@
1 1 <?php
2 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 +
3 9 class LP_Meta_Box_Course extends LP_Meta_Box {
4 10 /**
5 11 * Instance
6 12 *
@@ -9,10 +15,39 @@
9 15 private static $instance = null;
10 16
11 17 public $post_type = LP_COURSE_CPT;
12 18
13 - public function add_meta_box() {
14 - add_meta_box( 'course-settings', esc_html__( 'Course Settings', 'learnpress' ), array( $this, 'output' ), $this->post_type, 'normal', 'high' );
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 + }
15 50 }
16 51
17 52 public function metabox( $post_id ) {
18 53 $tabs = apply_filters(
@@ -24,8 +59,15 @@
24 59 'icon' => 'dashicons-admin-tools',
25 60 'priority' => 10,
26 61 'content' => $this->general( $post_id ),
27 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 + ),
28 70 'price' => array(
29 71 'label' => esc_html__( 'Pricing', 'learnpress' ),
30 72 'target' => 'price_course_data',
31 73 'icon' => 'dashicons-cart',
@@ -52,8 +94,15 @@
52 94 'icon' => 'dashicons-businessman',
53 95 'priority' => 50,
54 96 'content' => $this->author( $post_id ),
55 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 + ),
56 105 )
57 106 );
58 107
59 108 $tabs = apply_filters( 'learnpress/course/metabox/tabs', $tabs, $post_id );
@@ -62,20 +111,52 @@
62 111
63 112 return $tabs;
64 113 }
65 114
66 - public function general( $thepostid ) {
67 - $repurchase_option_desc = sprintf( '1. %s', __( 'Reset course progress: The course progress and results of student will be removed.' ) );
68 - $repurchase_option_desc .= '<br/>' . sprintf( '2. %s', __( 'Keep course progress: The course progress and results of student will remain.' ) );
69 - $repurchase_option_desc .= '<br/>' . sprintf( '3. %s', __( 'Open popup: The student can decide whether their course progress will be reset with the confirm popup.' ) );
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' );
70 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 +
71 152 return apply_filters(
72 153 'lp/course/meta-box/fields/general',
73 154 array(
74 155 '_lp_duration' => new LP_Meta_Box_Duration_Field(
75 156 esc_html__( 'Duration', 'learnpress' ),
76 - esc_html__( 'Set 0 for lifetime access.', 'learnpress' ),
77 - '10',
157 + esc_html__( 'Set to 0 for the lifetime access.', 'learnpress' ),
158 + '10 week',
78 159 array(
79 160 'default_time' => 'week',
80 161 'custom_attributes' => array(
81 162 'min' => '0',
@@ -84,19 +165,19 @@
84 165 )
85 166 ),
86 167 '_lp_block_expire_duration' => new LP_Meta_Box_Checkbox_Field(
87 168 esc_html__( 'Block content', 'learnpress' ),
88 - esc_html__( 'Block course when duration expires.', 'learnpress' ),
169 + esc_html__( 'When the duration expires, the course is blocked.', 'learnpress' ),
89 170 'no'
90 171 ),
91 172 '_lp_block_finished' => new LP_Meta_Box_Checkbox_Field(
92 173 '',
93 - esc_html__( 'Block course after student finished this course.', 'learnpress' ),
174 + esc_html__( 'Block the course after the student finished this course.', 'learnpress' ),
94 175 'yes'
95 176 ),
96 177 '_lp_allow_course_repurchase' => new LP_Meta_Box_Checkbox_Field(
97 178 __( 'Allow Repurchase', 'learnpress' ),
98 - esc_html__( 'Allow users to repurchase this course after course finished or blocked ( Do not apply to free courses ).', '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' ),
99 180 'no'
100 181 ),
101 182 '_lp_course_repurchase_option' => new LP_Meta_Box_Select_Field(
102 183 esc_html__( 'Repurchase action', 'learnpress' ),
@@ -102,20 +183,24 @@
102 183 esc_html__( 'Repurchase action', 'learnpress' ),
103 184 $repurchase_option_desc,
104 185 'reset',
105 186 array(
106 - 'options' => array(
187 + 'options' => array(
107 188 'reset' => esc_html__( 'Reset course progress', 'learnpress' ),
108 189 'keep' => esc_html__( 'Keep course progress', 'learnpress' ),
109 190 'popup' => esc_html__( 'Open popup', 'learnpress' ),
110 191 ),
111 - 'show' => array( '_lp_allow_course_repurchase', '=', 'yes' ), // use 'show' or 'hide'
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'
112 197 )
113 198 ),
114 199 '_lp_level' => new LP_Meta_Box_Select_Field(
115 200 esc_html__( 'Level', 'learnpress' ),
116 201 esc_html__( 'Choose a difficulty level.', 'learnpress' ),
117 - '',
202 + 'all',
118 203 array(
119 204 'options' => lp_course_level(),
120 205 )
121 206 ),
@@ -120,9 +205,9 @@
120 205 )
121 206 ),
122 207 '_lp_students' => new LP_Meta_Box_Text_Field(
123 208 esc_html__( 'Fake Students Enrolled', 'learnpress' ),
124 - esc_html__( 'How many students have taken this course', 'learnpress' ),
209 + $fake_students_desc,
125 210 0,
126 211 array(
127 212 'type_input' => 'number',
128 213 'custom_attributes' => array(
@@ -133,9 +218,9 @@
133 218 )
134 219 ),
135 220 '_lp_max_students' => new LP_Meta_Box_Text_Field(
136 221 esc_html__( 'Max student', 'learnpress' ),
137 - esc_html__( 'Maximum students can join the course. Set 0 for unlimited.', 'learnpress' ),
222 + $max_students_desc,
138 223 0,
139 224 array(
140 225 'type_input' => 'number',
141 226 'custom_attributes' => array(
@@ -146,9 +231,9 @@
146 231 )
147 232 ),
148 233 '_lp_retake_count' => new LP_Meta_Box_Text_Field(
149 234 esc_html__( 'Re-take Course', 'learnpress' ),
150 - esc_html__( 'The number of times a user can learn again this course. Set 0 to disable.', 'learnpress' ),
235 + esc_html__( 'The number of times a user can learn again from this course. To disable, set to 0.', 'learnpress' ),
151 236 0,
152 237 array(
153 238 'type_input' => 'number',
154 239 'custom_attributes' => array(
@@ -159,14 +244,14 @@
159 244 )
160 245 ),
161 246 '_lp_has_finish' => new LP_Meta_Box_Checkbox_Field(
162 247 esc_html__( 'Finish button', 'learnpress' ),
163 - esc_html__( 'Allow show finish button when the student has completed all items but has not passed the course assessment.', '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' ),
164 249 'yes'
165 250 ),
166 251 '_lp_featured' => new LP_Meta_Box_Checkbox_Field(
167 252 esc_html__( 'Featured list', 'learnpress' ),
168 - esc_html__( 'Add the course to Featured List.', 'learnpress' ),
253 + esc_html__( 'Add the course to the Featured List.', 'learnpress' ),
169 254 'no'
170 255 ),
171 256 '_lp_featured_review' => new LP_Meta_Box_Textarea_Field(
172 257 esc_html__( 'Featured review', 'learnpress' ),
@@ -173,98 +258,90 @@
173 258 esc_html__( 'A good review to promote the course.', 'learnpress' )
174 259 ),
175 260 '_lp_external_link_buy_course' => new LP_Meta_Box_Text_Field(
176 261 esc_html__( 'External link', 'learnpress' ),
177 - esc_html__( 'Normally use for offline classes, Ex: link to a contact page. Format: https://google.com', 'learnpress' ),
262 + esc_html__( 'Normally used for offline classes. Ex: link to a contact page. Format: https://google.com', 'learnpress' ),
178 263 '',
179 264 array(
180 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',
181 266 )
182 267 ),
183 - )
268 + ),
269 + $post_id
184 270 );
185 271 }
186 272
187 273 /**
188 - * @editor tungnx
189 - * @modify 4.1.5 - replace to lp_price function
274 + * Tab setting offline course
275 + *
276 + * @param $post_id
277 + *
278 + * @return array
279 + * @since 4.2.7
280 + * @version 1.0.0
190 281 */
191 - /*public function price( $thepostid ) {
192 - $post = get_post( $thepostid );
282 + public function tab_offline( $post_id ): array {
283 + $course = CourseModel::find( $post_id, true );
193 284
194 - $thepostid = ! empty( $thepostid ) ? $thepostid : absint( $post->ID );
195 -
196 - $message = '';
197 - $price = get_post_meta( $thepostid, '_lp_price', true );
198 - $payment = get_post_meta( $thepostid, '_lp_payment', true );
199 - $sale_price = '';
200 - $start_date = '';
201 - $end_date = '';
202 -
203 - if ( $payment != 'free' ) {
204 - $sale_price = get_post_meta( $thepostid, '_lp_sale_price', true );
205 - $start_date = get_post_meta( $thepostid, '_lp_sale_start', true );
206 - $end_date = get_post_meta( $thepostid, '_lp_sale_end', true );
285 + $is_offline_course = false;
286 + if ( $course instanceof CourseModel ) {
287 + $is_offline_course = $course->is_offline();
207 288 }
208 289
209 290 return apply_filters(
210 - 'lp/course/meta-box/fields/price',
291 + 'lp/course/meta-box/fields/offline',
211 292 array(
212 - '_lp_price' => new LP_Meta_Box_Text_Field(
213 - esc_html__( 'Regular price', 'learnpress' ),
214 - sprintf( __( 'Set a regular price (<strong>%s</strong>). Leave it blank for <strong>Free</strong>.', 'learnpress' ), learn_press_get_currency() ),
215 - $price,
216 - array(
217 - 'type_input' => 'number',
218 - 'custom_attributes' => array(
219 - 'min' => '0',
220 - 'step' => '0.01',
221 - ),
222 - 'style' => 'width: 70px;',
223 - 'class' => 'lp_meta_box_regular_price',
224 - )
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'
225 300 ),
226 - '_lp_sale_price' => new LP_Meta_Box_Text_Field(
227 - esc_html__( 'Sale price', 'learnpress' ),
228 - '<a href="#" class="lp_sale_price_schedule">' . esc_html__( 'Schedule', 'learnpress' ) . '</a>',
229 - $sale_price,
230 - array(
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 + [
231 306 'type_input' => 'number',
232 307 'custom_attributes' => array(
233 308 'min' => '0',
234 - 'step' => '0.01',
309 + 'step' => '1',
235 310 ),
236 - 'style' => 'width: 70px;',
237 - 'class' => 'lp_meta_box_sale_price',
238 - )
311 + 'dependency' => [
312 + 'name' => '_lp_offline_course',
313 + 'is_disable' => ! $is_offline_course,
314 + ],
315 + ]
239 316 ),
240 - '_lp_sale_start' => new LP_Meta_Box_Date_Field(
241 - esc_html__( 'Sale start dates', 'learnpress' ),
242 - '',
243 - '',
244 - array(
245 - 'wrapper_class' => 'lp_sale_start_dates_fields',
246 - 'placeholder' => _x( 'From&hellip;', 'placeholder', 'learnpress' ),
247 - )
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 + ]
248 328 ),
249 - '_lp_sale_end' => new LP_Meta_Box_Date_Field(
250 - esc_html__( 'Sale end dates', 'learnpress' ),
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' ),
251 332 '',
252 - '',
253 - array(
254 - 'wrapper_class' => 'lp_sale_end_dates_fields',
255 - 'placeholder' => _x( 'To&hellip;', 'placeholder', 'learnpress' ),
256 - 'cancel' => true,
257 - )
333 + [
334 + 'dependency' => [
335 + 'name' => '_lp_offline_course',
336 + 'is_disable' => ! $is_offline_course,
337 + ],
338 + ]
258 339 ),
259 - '_lp_no_required_enroll' => new LP_Meta_Box_Checkbox_Field(
260 - esc_html__( 'No requirement enroll', 'learnpress' ),
261 - esc_html__( 'Students can see the content of all course items and do the quiz without login.', 'learnpress' ),
262 - 'no'
263 - ),
264 - )
340 + ),
341 + $post_id
265 342 );
266 - }*/
343 + }
267 344
268 345 /**
269 346 * Setting course price
270 347 *
@@ -269,12 +346,12 @@
269 346 * Setting course price
270 347 *
271 348 * @param $post_id
272 349 *
273 - * @author tungnx
350 + * @return array
274 351 * @since 4.1.5
275 352 * @version 1.0.0
276 - * @return array
353 + * @author tungnx
277 354 */
278 355 public function lp_price( $post_id ): array {
279 356 $key_exists = LP_Database::getInstance()->check_key_postmeta_exists( $post_id, '_lp_regular_price' );
280 357 $price = get_post_meta( $post_id, '_lp_price', true );
@@ -280,8 +357,10 @@
280 357 $price = get_post_meta( $post_id, '_lp_price', true );
281 358 $regular_price = $key_exists ? get_post_meta( $post_id, '_lp_regular_price', true ) : $price;
282 359 $sale_price = get_post_meta( $post_id, '_lp_sale_price', true );
283 360
361 + $is_enable_no_required_enroll = get_post_meta( $post_id, '_lp_no_required_enroll', true ) === 'yes' ? 1 : 0;
362 +
284 363 return apply_filters(
285 364 'lp/course/meta-box/fields/price',
286 365 array(
287 366 '_lp_regular_price' => new LP_Meta_Box_Text_Field(
@@ -288,15 +367,19 @@
288 367 esc_html__( 'Regular price', 'learnpress' ),
289 368 sprintf( __( 'Set a regular price (<strong>%s</strong>). Leave it blank for <strong>Free</strong>.', 'learnpress' ), learn_press_get_currency() ),
290 369 $regular_price,
291 370 array(
292 - 'type_input' => 'number',
371 + 'type_input' => 'text',
293 372 'custom_attributes' => array(
294 373 'min' => '0',
295 374 'step' => '0.01',
296 375 ),
297 - 'style' => 'width: 70px;',
376 + 'style' => 'width: 150px;',
298 377 'class' => 'lp_meta_box_regular_price',
378 + 'dependency' => [
379 + 'name' => '_lp_no_required_enroll',
380 + 'is_disable' => $is_enable_no_required_enroll,
381 + ],
299 382 )
300 383 ),
301 384 '_lp_sale_price' => new LP_Meta_Box_Text_Field(
302 385 esc_html__( 'Sale price', 'learnpress' ),
@@ -302,15 +385,19 @@
302 385 esc_html__( 'Sale price', 'learnpress' ),
303 386 '<a href="#" class="lp_sale_price_schedule">' . esc_html__( 'Schedule', 'learnpress' ) . '</a>',
304 387 $sale_price,
305 388 array(
306 - 'type_input' => 'number',
389 + 'type_input' => 'text',
307 390 'custom_attributes' => array(
308 391 'min' => '0',
309 392 'step' => '0.01',
310 393 ),
311 - 'style' => 'width: 70px;',
394 + 'style' => 'width: 150px;',
312 395 'class' => 'lp_meta_box_sale_price',
396 + 'dependency' => [
397 + 'name' => '_lp_no_required_enroll',
398 + 'is_disable' => $is_enable_no_required_enroll,
399 + ],
313 400 )
314 401 ),
315 402 '_lp_sale_start' => new LP_Meta_Box_Date_Field(
316 403 esc_html__( 'Sale start dates', 'learnpress' ),
@@ -318,8 +405,12 @@
318 405 '',
319 406 array(
320 407 'wrapper_class' => 'lp_sale_start_dates_fields',
321 408 'placeholder' => _x( 'From&hellip;', 'placeholder', 'learnpress' ),
409 + 'dependency' => [
410 + 'name' => '_lp_no_required_enroll',
411 + 'is_disable' => $is_enable_no_required_enroll,
412 + ],
322 413 )
323 414 ),
324 415 '_lp_sale_end' => new LP_Meta_Box_Date_Field(
325 416 esc_html__( 'Sale end dates', 'learnpress' ),
@@ -328,16 +419,31 @@
328 419 array(
329 420 'wrapper_class' => 'lp_sale_end_dates_fields',
330 421 'placeholder' => _x( 'To&hellip;', 'placeholder', 'learnpress' ),
331 422 'cancel' => true,
423 + 'dependency' => [
424 + 'name' => '_lp_no_required_enroll',
425 + 'is_disable' => $is_enable_no_required_enroll,
426 + ],
332 427 )
333 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 + ),
334 439 '_lp_no_required_enroll' => new LP_Meta_Box_Checkbox_Field(
335 - esc_html__( 'No requirement enroll', 'learnpress' ),
336 - esc_html__( 'Students can see the content of all course items and do the quiz without login.', 'learnpress' ),
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' ),
337 442 'no'
338 443 ),
339 - )
444 + ),
445 + $post_id
340 446 );
341 447 }
342 448
343 449 public function author( $thepostid ) {
@@ -342,35 +448,69 @@
342 448
343 449 public function author( $thepostid ) {
344 450 $post = get_post( $thepostid );
345 451
346 - $author = $post ? $post->post_author : get_current_user_id();
452 + $author_id = $post ? $post->post_author : get_current_user_id();
347 453
348 454 $options = array();
349 - $role = array( 'administrator', 'lp_teacher' );
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 + }
350 463
351 - $role = apply_filters( 'learn_press_course_author_role_meta_box', $role );
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 ] );
352 468
353 - foreach ( $role as $_role ) {
354 - $users_by_role = get_users( array( 'role' => $_role ) );
355 -
356 - if ( $users_by_role ) {
357 - foreach ( $users_by_role as $user ) {
358 - $options[ $user->get( 'ID' ) ] = $user->user_login;
359 - }
469 + /**
470 + * @var WP_User $author
471 + */
472 + foreach ( $authors as $author ) {
473 + $options[ $author->ID ] = $author->display_name . ' (#' . $author->ID . ')';
360 474 }
361 475 }
476 + // Code old only use for addon Frontend Editor v4.0.4
362 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 +
363 498 return apply_filters(
364 499 'lp/course/meta-box/fields/author',
365 500 array(
366 - '_lp_course_author' => new LP_Meta_Box_Select_Field(
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(
367 503 esc_html__( 'Author', 'learnpress' ),
368 504 '',
369 - $author,
505 + $author_id,
370 506 array(
371 - 'options' => $options,
372 - 'style' => 'min-width:200px;',
507 + 'options' => $options,
508 + 'style' => 'min-width:200px;',
509 + 'tom_select' => true,
510 + 'custom_attributes' => [
511 + 'data-struct' => htmlentities2( json_encode( $data_struct ) ),
512 + ],
373 513 )
374 514 ),
375 515 )
376 516 );
@@ -375,8 +515,17 @@
375 515 )
376 516 );
377 517 }
378 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 +
379 528 public function assessment( $thepostid ) {
380 529 $post = get_post( $thepostid );
381 530
382 531 $course_result_desc = '';
@@ -381,12 +530,16 @@
381 530
382 531 $course_result_desc = '';
383 532 $course_results = get_post_meta( $thepostid, '_lp_course_result', true );
384 533
385 - $course_result_desc .= __( 'The method to assess the result of a student for a course.', 'learnpress' );
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 + );
386 539
387 540 if ( $course_results == 'evaluate_final_quiz' && ! get_post_meta( $thepostid, '_lp_final_quiz', true ) ) {
388 - $course_result_desc .= __( '<br /><strong>Note! </strong>No final quiz in course, please add a final quiz', 'learnpress' );
541 + $course_result_desc .= __( '<br /><strong>Note! </strong>There is no final quiz in the course. Please add a final quiz.', 'learnpress' );
389 542 }
390 543
391 544 $final_quizz_passing = '';
392 545
@@ -398,10 +551,24 @@
398 551 $final_quiz = $course->get_final_quiz();
399 552
400 553 if ( $final_quiz ) {
401 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 + }
402 563
403 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 + );
404 571
405 572 $final_quizz_passing = '
406 573 <div class="lp-metabox-evaluate-final_quiz">
407 574 <div class="lp-metabox-evaluate-final_quiz__message">'
@@ -426,15 +593,15 @@
426 593 )
427 594 ),
428 595 '_lp_passing_condition' => new LP_Meta_Box_Text_Field(
429 596 esc_html__( 'Passing Grade(%)', 'learnpress' ),
430 - esc_html__( 'The condition that must be achieved to finish the course.', 'learnpress' ),
597 + esc_html__( 'The conditions that must be achieved to finish the course.', 'learnpress' ),
431 598 '80',
432 599 array(
433 600 'type_input' => 'number',
434 601 'custom_attributes' => array(
435 602 'min' => '0',
436 - 'step' => '1',
603 + 'step' => '0.01',
437 604 'max' => '100',
438 605 ),
439 606 'style' => 'width: 60px;',
440 607 )
@@ -472,74 +639,36 @@
472 639 }
473 640
474 641 public function output( $post ) {
475 642 parent::output( $post );
476 - ?>
477 643
478 - <div class="lp-meta-box lp-meta-box--course">
479 - <div class="lp-meta-box__inner">
480 - <div class="lp-meta-box__course-tab">
481 - <ul class="lp-meta-box__course-tab__tabs">
482 - <?php
483 - foreach ( $this->metabox( $post->ID ) as $key => $tab ) {
484 - if ( $key === 'author' && ! is_super_admin() ) {
485 - continue;
486 - }
644 + $course_id = $post->ID;
645 + $courseModel = CourseModel::find( $course_id, true );
646 + if ( ! $courseModel instanceof CourseModel ) {
647 + return;
648 + }
487 649
488 - $class_tab = '';
650 + do_action( 'learn-press/admin/course/edit-setting/layout', $courseModel->ID );
651 + }
489 652
490 - if ( isset( $tab['class'] ) ) {
491 - $class_tab = implode( ' ', (array) $tab['class'] );
492 - }
493 - ?>
494 - <li class="<?php echo esc_attr( $key ); ?>_options <?php echo esc_attr( $key ); ?>_tab <?php echo esc_attr( $class_tab ); ?>">
495 - <a href="#<?php echo esc_attr( $tab['target'] ); ?>">
496 - <?php if ( isset( $tab['icon'] ) ) : ?>
497 - <i class="<?php echo esc_attr( $tab['icon'] ); ?>"></i>
498 - <?php endif; ?>
499 - <span><?php echo esc_html( $tab['label'] ); ?></span>
500 - </a>
501 - </li>
502 - <?php } ?>
503 - </ul>
653 + /**
654 + * Template Editor Curriculum.
655 + *
656 + * @return void
657 + */
658 + public function admin_editor() {
659 + global $post;
504 660
505 - <div class="lp-meta-box__course-tab__content">
506 - <?php foreach ( $this->metabox( $post->ID ) as $key => $tab_content ) { ?>
507 - <?php
508 - if ( $key === 'author' && ! is_super_admin() ) {
509 - continue;
510 - }
511 - ?>
512 - <?php if ( isset( $tab_content['content'] ) ) { ?>
513 - <div id="<?php echo esc_attr( $tab_content['target'] ); ?>" class="lp-meta-box-course-panels">
514 - <?php
515 - do_action( 'learnpress/course-settings/before-' . $key );
661 + $course_id = $post->ID;
662 + $courseModel = CourseModel::find( $course_id, true );
663 + if ( ! $courseModel instanceof CourseModel ) {
664 + return;
665 + }
516 666
517 - foreach ( $tab_content['content'] as $meta_key => $object ) {
518 - if ( is_a( $object, 'LP_Meta_Box_Field' ) ) {
519 - $object->id = $meta_key;
520 - echo wp_kses_post( $object->output( $post->ID ) );
521 - }
522 - }
523 -
524 - do_action( 'learnpress/course-settings/after-' . $key );
525 - ?>
526 - </div>
527 - <?php
528 - }
529 - }
530 -
531 - do_action( 'lp_course_data_setting_tab_content', $post );
532 - ?>
533 - </div>
534 - </div>
535 - </div>
536 - </div>
537 -
538 - <?php
667 + do_action( 'learn-press/admin/edit-curriculum/layout', $courseModel );
539 668 }
540 669
541 - public function save( $post_id ) {
670 + /*public function save( $post_id ) {
542 671 if ( ! empty( $this->metabox( $post_id ) ) ) {
543 672 foreach ( $this->metabox( $post_id ) as $key => $tab_content ) {
544 673 if ( isset( $tab_content['content'] ) ) {
545 674 foreach ( $tab_content['content'] as $meta_key => $object ) {
@@ -553,13 +682,26 @@
553 682 }
554 683
555 684 $course = learn_press_get_course( $post_id );
556 685
557 - $evalution = isset( $_POST['_lp_course_result'] ) ? LP_Helper::sanitize_params_submitted( $_POST['_lp_course_result'] ) : '';
558 - $passing_condition = isset( $_POST['_lp_passing_condition'] ) ? absint( wp_unslash( $_POST['_lp_passing_condition'] ) ) : 0;
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 + }
559 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 +
560 702 // Update Final Quiz. - Nhamdv
561 - if ( $evalution == 'evaluate_final_quiz' ) {
703 + if ( $evaluation == 'evaluate_final_quiz' ) {
562 704 $items = $course->get_item_ids();
563 705
564 706 if ( $items ) {
565 707 foreach ( $items as $item ) {
@@ -578,15 +720,14 @@
578 720 delete_post_meta( $post_id, '_lp_final_quiz' );
579 721 }
580 722
581 723 $author = isset( $_POST['_lp_course_author'] ) ? wp_unslash( $_POST['_lp_course_author'] ) : '';
582 -
583 724 if ( ! empty( $author ) ) {
584 725 global $wpdb;
585 726
586 727 $wpdb->update( $wpdb->posts, array( 'post_author' => $author ), array( 'ID' => $post_id ) );
587 728 }
588 - }
729 + }*/
589 730
590 731 private static function data_tabs_sort( $a, $b ) {
591 732 if ( ! isset( $a['priority'], $b['priority'] ) ) {
592 733 return - 1;
@@ -596,115 +737,8 @@
596 737 return 0;
597 738 }
598 739
599 740 return $a['priority'] < $b['priority'] ? - 1 : 1;
600 - }
601 -
602 - /**
603 - * In child theme use metabox in v3,
604 - * so need use for child theme.
605 - * function in child: thim_add_course_meta.
606 - *
607 - * @return void
608 - */
609 - public static function eduma_child_metabox_v3( $meta_boxes ) {
610 - if ( ! empty( $meta_boxes['fields'] ) ) {
611 - foreach ( $meta_boxes['fields'] as $setting ) {
612 - $field = wp_parse_args(
613 - $setting,
614 - array(
615 - 'id' => '',
616 - 'name' => '',
617 - 'desc' => '',
618 - 'std' => '',
619 - )
620 - );
621 -
622 - switch ( $field['type'] ) {
623 - case 'text':
624 - case 'number':
625 - lp_meta_box_text_input_field(
626 - array(
627 - 'id' => $field['id'],
628 - 'label' => isset( $field['label'] ) ? $field['label'] : $field['name'],
629 - 'description' => isset( $field['description'] ) ? $field['description'] : $field['desc'],
630 - 'type' => $field['type'],
631 - 'default' => isset( $field['default'] ) ? $field['default'] : $field['std'],
632 - 'custom_attributes' => isset( $field['custom_attributes'] ) ? $field['custom_attributes'] : '',
633 - )
634 - );
635 - break;
636 -
637 - case 'textarea':
638 - lp_meta_box_textarea_field(
639 - array(
640 - 'id' => $field['id'],
641 - 'label' => isset( $field['label'] ) ? $field['label'] : $field['name'],
642 - 'description' => isset( $field['description'] ) ? $field['description'] : $field['desc'],
643 - 'default' => isset( $field['default'] ) ? $field['default'] : $field['std'],
644 - 'custom_attributes' => isset( $field['custom_attributes'] ) ? $field['custom_attributes'] : '',
645 - )
646 - );
647 - break;
648 -
649 - case 'checkbox':
650 - lp_meta_box_checkbox_field(
651 - array(
652 - 'id' => $field['id'],
653 - 'label' => isset( $field['label'] ) ? $field['label'] : $field['name'],
654 - 'description' => isset( $field['description'] ) ? $field['description'] : $field['desc'],
655 - 'default' => isset( $field['default'] ) ? $field['default'] : $field['std'],
656 - )
657 - );
658 - break;
659 -
660 - case 'duration':
661 - lp_meta_box_duration_field(
662 - array(
663 - 'id' => $field['id'],
664 - 'label' => isset( $field['label'] ) ? $field['label'] : $field['name'],
665 - 'default_time' => $field['default_time'],
666 - 'default' => isset( $field['default'] ) ? $field['default'] : $field['std'],
667 - 'description' => isset( $field['description'] ) ? $field['description'] : $field['desc'],
668 - 'default' => isset( $field['default'] ) ? $field['default'] : $field['std'],
669 - 'custom_attributes' => isset( $field['custom_attributes'] ) ? $field['custom_attributes'] : '',
670 - )
671 - );
672 - break;
673 -
674 - case 'select':
675 - lp_meta_box_select_field(
676 - array(
677 - 'id' => $field['id'],
678 - 'label' => isset( $field['label'] ) ? $field['label'] : $field['name'],
679 - 'default' => isset( $field['default'] ) ? $field['default'] : $field['std'],
680 - 'description' => isset( $field['description'] ) ? $field['description'] : $field['desc'],
681 - 'options' => $field['options'],
682 - 'default' => isset( $field['default'] ) ? $field['default'] : $field['std'],
683 - 'custom_attributes' => isset( $field['custom_attributes'] ) ? $field['custom_attributes'] : '',
684 - )
685 - );
686 - break;
687 -
688 - case 'select_advanced':
689 - lp_meta_box_select_field(
690 - array(
691 - 'id' => $field['id'],
692 - 'label' => isset( $field['label'] ) ? $field['label'] : $field['name'],
693 - 'default' => isset( $field['default'] ) ? $field['default'] : $field['std'],
694 - 'description' => isset( $field['description'] ) ? $field['description'] : $field['desc'],
695 - 'options' => $field['options'],
696 - 'multiple' => true,
697 - 'default' => isset( $field['default'] ) ? $field['default'] : $field['std'],
698 - 'wrapper_class' => 'lp-select-2',
699 - 'style' => 'min-width: 200px',
700 - 'custom_attributes' => isset( $field['custom_attributes'] ) ? $field['custom_attributes'] : '',
701 - )
702 - );
703 - break;
704 - }
705 - }
706 - }
707 741 }
708 742
709 743 public static function save_eduma_child_metabox_v3( $post_id ) {
710 744 $general = apply_filters( 'learn_press_course_settings_meta_box_args', array( 'fields' => array() ) );