LearnPress – WordPress LMS Plugin - Version 3.0.2

Version Description

~ Fixed PHP non-numeric cast type ~ Improved admin ajax for course/quiz/question editor ~ Fixed error when extending method from parent ~ Fixed invalid course progress label ~ Fixed invalid filter to course passing grade ~ Fixed empty course item class for other post types

Download this release

Release Info

Developer tunnhn
Plugin Icon 128x128 LearnPress – WordPress LMS Plugin
Version 3.0.2
Comparing to
See all releases

Code changes from version 3.0.1 to 3.0.2

assets/js/admin/course-editor.js CHANGED
@@ -593,7 +593,7 @@ var LP_Choose_Items_Modal_Store = (function (exports, Vue, helpers, data) {
593
  autoDraft: function (state) {
594
  return state.auto_draft;
595
  },
596
- disable_curriculum: function(state){
597
  return state.disable_curriculum;
598
  },
599
  status: function (state) {
@@ -656,7 +656,7 @@ var LP_Choose_Items_Modal_Store = (function (exports, Vue, helpers, data) {
656
  Vue.http.LPRequest({
657
  type: 'draft-course',
658
  course: JSON.stringify(payload)
659
- }).then(function(response) {
660
  var result = response.body;
661
 
662
  if (!result.success) {
@@ -732,6 +732,11 @@ var LP_Choose_Items_Modal_Store = (function (exports, Vue, helpers, data) {
732
  $store.dispatch('newRequest');
733
 
734
  next(function (response) {
 
 
 
 
 
735
  var body = response.body;
736
  var result = body.success || false;
737
 
593
  autoDraft: function (state) {
594
  return state.auto_draft;
595
  },
596
+ disable_curriculum: function (state) {
597
  return state.disable_curriculum;
598
  },
599
  status: function (state) {
656
  Vue.http.LPRequest({
657
  type: 'draft-course',
658
  course: JSON.stringify(payload)
659
+ }).then(function (response) {
660
  var result = response.body;
661
 
662
  if (!result.success) {
732
  $store.dispatch('newRequest');
733
 
734
  next(function (response) {
735
+
736
+ if (!jQuery.isPlainObject(response.body)) {
737
+ response.body = LP.parseJSON(response.body);
738
+ }
739
+
740
  var body = response.body;
741
  var result = body.success || false;
742
 
assets/js/admin/question-editor.js CHANGED
@@ -251,6 +251,11 @@
251
  $store.dispatch('newRequest');
252
 
253
  next(function (response) {
 
 
 
 
 
254
  var body = response.body;
255
  var result = body.success || false;
256
 
251
  $store.dispatch('newRequest');
252
 
253
  next(function (response) {
254
+
255
+ if (!jQuery.isPlainObject(response.body)) {
256
+ response.body = LP.parseJSON(response.body);
257
+ }
258
+
259
  var body = response.body;
260
  var result = body.success || false;
261
 
assets/js/admin/quiz-editor.js CHANGED
@@ -875,6 +875,11 @@ var LP_List_Quiz_Questions_Store = (function (Vue, helpers, data, $) {
875
  $store.dispatch('newRequest');
876
 
877
  next(function (response) {
 
 
 
 
 
878
  var body = response.body,
879
  result = body.success || false;
880
 
875
  $store.dispatch('newRequest');
876
 
877
  next(function (response) {
878
+
879
+ if (!jQuery.isPlainObject(response.body)) {
880
+ response.body = LP.parseJSON(response.body);
881
+ }
882
+
883
  var body = response.body,
884
  result = body.success || false;
885
 
inc/admin/class-lp-admin-ajax.php CHANGED
@@ -111,297 +111,8 @@ if ( ! class_exists( 'LP_Admin_Ajax' ) ) {
111
  * @since 3.0.0
112
  */
113
  public static function admin_course_editor() {
114
-
115
- check_ajax_referer( 'learnpress_update_curriculum', 'nonce' );
116
-
117
- $args = wp_parse_args( $_REQUEST, array( 'id' => false, 'type' => '' ) );
118
-
119
- $course_id = $args['id'];
120
- $course = learn_press_get_course( $course_id );
121
-
122
- if ( ! $course ) {
123
- wp_send_json_error();
124
- }
125
-
126
- // course curd
127
- $course_curd = new LP_Course_CURD();
128
- // section curd
129
- $section_curd = new LP_Section_CURD( $course_id );
130
-
131
- $result = $args['type'];
132
-
133
- switch ( $args['type'] ) {
134
-
135
- case 'heartbeat':
136
- $result = true;
137
- break;
138
-
139
- case 'draft-course':
140
- $new_course = ! empty( $args['course'] ) ? $args['course'] : false;
141
- $new_course = json_decode( wp_unslash( $new_course ), true );
142
-
143
- if ( ! $new_course ) {
144
- break;
145
- }
146
-
147
- $title = $new_course['title'] ? $new_course['title'] : __( 'New Course', 'learnpress' );
148
- $content = $new_course['content'] ? $new_course['content'] : '';
149
-
150
- $args = array(
151
- 'id' => $course_id,
152
- 'status' => 'draft',
153
- 'title' => $title,
154
- 'content' => $content
155
- );
156
-
157
- $course_curd->create( $args );
158
- break;
159
-
160
- case 'hidden-sections':
161
- // get hidden sections id
162
- $hidden = ! empty( $args['hidden'] ) ? $args['hidden'] : false;
163
- // update course post meta
164
- update_post_meta( $course_id, '_admin_hidden_sections', $hidden );
165
- break;
166
-
167
- case 'sort-sections':
168
- $order = ! empty( $args['order'] ) ? $args['order'] : false;
169
- $order = json_decode( wp_unslash( $order ), true );
170
-
171
- if ( ! $order ) {
172
- break;
173
- }
174
-
175
- $result = $section_curd->sort_sections( $order );
176
-
177
- // last section
178
- $last_section_id = end( $order );
179
- // update final quiz
180
- $section_curd->update_final_quiz( $last_section_id );
181
- break;
182
-
183
- case 'update-section':
184
- $section = ! empty( $args['section'] ) ? $args['section'] : false;
185
- $section = json_decode( wp_unslash( $section ), true );
186
-
187
- if ( ! $section ) {
188
- break;
189
- }
190
-
191
- $update = array(
192
- 'section_id' => $section['id'],
193
- 'section_name' => $section['title'],
194
- 'section_description' => $section['description'],
195
- 'section_order' => $section['order'],
196
- 'section_course_id' => $section['course_id'],
197
- );
198
-
199
- $result = $section_curd->update( $update );
200
- break;
201
-
202
- case 'remove-section':
203
- $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
204
-
205
- if ( ! $section_id ) {
206
- break;
207
- }
208
-
209
- $section_curd->delete( $section_id );
210
- break;
211
-
212
- case 'new-section':
213
- $section_name = ! empty( $args['section_name'] ) ? $args['section_name'] : false;
214
-
215
- $args = array(
216
- 'section_course_id' => $course_id,
217
- 'section_description' => '',
218
- 'section_name' => $section_name,
219
- 'items' => array(),
220
- );
221
-
222
- // create section
223
- $section = $section_curd->create( $args );
224
-
225
- $result = array(
226
- 'id' => $section['section_id'],
227
- 'items' => $section['items'],
228
- 'title' => $section['section_name'],
229
- 'description' => $section['section_description'],
230
- 'course_id' => $section['section_course_id'],
231
- 'order' => $section['section_order'],
232
- );
233
- break;
234
-
235
- case 'update-section-item':
236
- $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
237
- $item = ! empty( $args['item'] ) ? $args['item'] : false;
238
- $item = json_decode( wp_unslash( $item ), true );
239
-
240
- if ( ! ( $section_id && $item ) ) {
241
- break;
242
- }
243
-
244
- // update lesson, quiz title
245
- $result = $section_curd->update_item( $item );
246
- break;
247
-
248
- case 'remove-section-item':
249
- $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
250
- $item_id = ! empty( $args['item_id'] ) ? $args['item_id'] : false;
251
-
252
- if ( ! ( $section_id && $item_id ) ) {
253
- break;
254
- }
255
-
256
- // remove item from course
257
- $course_curd->remove_item( $item_id );
258
- break;
259
-
260
- case 'delete-section-item':
261
- $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
262
- $item_id = ! empty( $args['item_id'] ) ? $args['item_id'] : false;
263
-
264
- if ( ! ( $section_id && $item_id ) ) {
265
- break;
266
- }
267
-
268
- $result = wp_delete_post( $item_id );
269
- break;
270
-
271
- case 'new-section-item':
272
- $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
273
- $item = ! empty( $args['item'] ) ? $args['item'] : false;
274
- $item = json_decode( wp_unslash( $item ), true );
275
-
276
- if ( ! ( $section_id && $item ) ) {
277
- break;
278
- }
279
-
280
- // create new lesson, quiz and add to course
281
- $result = $section_curd->new_item( $section_id, $item );
282
- break;
283
-
284
- case 'update-section-items':
285
- $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
286
- $last_section = ! empty( $args['last_section'] ) ? $args['last_section'] : false;
287
- $items = ! empty( $args['items'] ) ? $args['items'] : false;
288
- $items = json_decode( wp_unslash( $items ), true );
289
-
290
- if ( ! ( $section_id && $items ) ) {
291
- break;
292
- }
293
-
294
- $result = $section_curd->update_section_items( $section_id, $items );
295
-
296
- if ( $last_section ) {
297
- $section_curd->update_final_quiz( $section_id );
298
- }
299
- break;
300
-
301
- case 'search-items':
302
- $query = isset( $args['query'] ) ? $args['query'] : '';
303
- $type = isset( $args['item_type'] ) ? $args['item_type'] : '';
304
- $page = ! empty( $args['page'] ) ? $args['page'] : 1;
305
- $exclude = ! empty( $args['exclude'] ) ? $args['exclude'] : '';
306
-
307
- if ( $exclude ) {
308
- $exclude = json_decode( $exclude, true );
309
- }
310
-
311
- $ids_exclude = array();
312
-
313
- if ( is_array( $exclude ) ) {
314
- foreach ( $exclude as $item ) {
315
- $ids_exclude[] = $item['id'];
316
- }
317
- }
318
-
319
- $search = new LP_Modal_Search_Items( array(
320
- 'type' => $type,
321
- 'context' => 'course',
322
- 'context_id' => $course_id,
323
- 'term' => $query,
324
- 'limit' => apply_filters( 'learn-press/course-editor/choose-items-limit', 10 ),
325
- 'paged' => $page,
326
- 'exclude' => $ids_exclude,
327
- ) );
328
-
329
- $id_items = $search->get_items();
330
-
331
- $items = array();
332
- foreach ( $id_items as $id ) {
333
- $post = get_post( $id );
334
-
335
- $items[] = array(
336
- 'id' => $post->ID,
337
- 'title' => $post->post_title,
338
- 'type' => $post->post_type,
339
- );
340
- }
341
-
342
- $result = array(
343
- 'items' => $items,
344
- 'pagination' => $search->get_pagination( false )
345
- );
346
- break;
347
-
348
- case 'add-items-to-section':
349
- $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
350
- $items = ! empty( $args['items'] ) ? $args['items'] : false;
351
- $items = json_decode( wp_unslash( $items ), true );
352
-
353
- if ( ! $items || ! $section_id ) {
354
- break;
355
- }
356
-
357
- $result = $section_curd->add_items_section( $section_id, $items );
358
- break;
359
-
360
- default:
361
- break;
362
-
363
- }
364
-
365
- if ( is_wp_error( $result ) ) {
366
- wp_send_json_error( $result->get_error_message() );
367
- }
368
-
369
- wp_send_json_success( $result );
370
- }
371
-
372
- /**
373
- * Draft question.
374
- *
375
- * @since 3.0.0
376
- *
377
- * @param $question_id
378
- * @param array $args
379
- *
380
- * @return bool|int|LP_Question
381
- */
382
- private static function draft_question( $question_id, $args = array() ) {
383
-
384
- if ( get_post_status( $question_id ) != 'auto-draft' ) {
385
- return false;
386
- }
387
-
388
- $curd = new LP_Question_CURD();
389
-
390
- $args = wp_parse_args( $args, array(
391
- 'id' => $question_id,
392
- 'title' => __( 'New Question', 'learnpress' ),
393
- 'content' => '',
394
- 'status' => 'draft',
395
- 'create_answers' => false
396
- ) );
397
-
398
- $question = $curd->create( $args );
399
-
400
- if ( ! $question ) {
401
- return false;
402
- }
403
-
404
- return $question;
405
  }
406
 
407
  /**
@@ -410,127 +121,8 @@ if ( ! class_exists( 'LP_Admin_Ajax' ) ) {
410
  * @since 3.0.0
411
  */
412
  public static function admin_question_editor() {
413
-
414
- check_ajax_referer( 'learnpress_admin_question_editor', 'nonce' );
415
-
416
- $args = wp_parse_args( $_REQUEST, array( 'id' => false, 'type' => '' ) );
417
-
418
- // question id
419
- $question_id = $args['id'];
420
- $question = LP_Question::get_question( $question_id );
421
-
422
- if ( ! $question ) {
423
- wp_send_json_error();
424
- }
425
-
426
- $curd = new LP_Question_CURD();
427
- $result = array();
428
- $result['status'] = false;
429
-
430
- switch ( $args['type'] ) {
431
-
432
- case 'change-question-type':
433
- $type = ! empty( $args['question_type'] ) ? $args['question_type'] : false;
434
-
435
- if ( ! $type ) {
436
- break;
437
- }
438
-
439
- // draft question args
440
- $args = $args['draft_question'] ? $args['draft_question'] : '';
441
-
442
- if ( $args ) {
443
- $args = (array) ( json_decode( wp_unslash( $args ), '' ) );
444
- $draft = self::draft_question( $question_id, $args );
445
-
446
- // check if draft question false or question exist
447
- if ( $draft ) {
448
- $question = $draft;
449
- }
450
- }
451
-
452
- // change question type
453
- $question = $curd->change_question_type( $question, $type );
454
-
455
- if ( $question ) {
456
- $result = LP_Admin_Ajax::get_question_data_to_question_editor( $question, true );
457
- }
458
- break;
459
-
460
- case 'sort-answer' :
461
- // answers order
462
- $order = ! empty( $args['order'] ) ? $args['order'] : false;
463
-
464
- if ( ! $order ) {
465
- break;
466
- }
467
-
468
- // sort answers
469
- $question = $curd->sort_answers( $question_id, $order );
470
-
471
- $result = array_values( $question->get_data( 'answer_options' ) );
472
- break;
473
-
474
- case 'update-answer-title':
475
- // answers
476
- $answer = ! empty( $args['answer'] ) ? $args['answer'] : false;
477
- $answer = json_decode( wp_unslash( $answer ), true );
478
-
479
- if ( ! $answer ) {
480
- break;
481
- }
482
-
483
- // update answer title
484
- $result = $curd->update_answer_title( $question_id, $answer );
485
- break;
486
-
487
- case 'change-correct':
488
- // correct answer
489
- $correct = ! empty( $args['correct'] ) ? $args['correct'] : false;
490
- $correct = json_decode( wp_unslash( $correct ), true );
491
-
492
- if ( ! $correct ) {
493
- break;
494
- }
495
-
496
- // update correct answer
497
- $question = $curd->change_correct_answer( $question, $correct );
498
-
499
- $result = $question->get_data( 'answer_options' );
500
- break;
501
-
502
- case 'delete-answer' :
503
- // answer id
504
- $answer_id = ! empty( $args['answer_id'] ) ? $args['answer_id'] : false;
505
-
506
- if ( ! $answer_id ) {
507
- break;
508
- }
509
-
510
- // delete answer
511
- $curd->delete_answer( $question_id, $answer_id );
512
-
513
- $result = $question->get_data( 'answer_options' );
514
- break;
515
-
516
- case 'new-answer' :
517
- // new answer
518
- $answer = LP_Question::get_default_answer();
519
- // add new
520
- $curd->new_answer( $question_id, $answer );
521
-
522
- $result = $question->get_data( 'answer_options' );
523
- break;
524
-
525
- default:
526
- break;
527
- }
528
-
529
- if ( is_wp_error( $result ) ) {
530
- wp_send_json_error( $result->get_error_message() );
531
- }
532
-
533
- wp_send_json_success( $result );
534
  }
535
 
536
  /**
@@ -539,393 +131,25 @@ if ( ! class_exists( 'LP_Admin_Ajax' ) ) {
539
  * @since 3.0.0
540
  */
541
  public static function admin_quiz_editor() {
 
 
 
542
 
543
- check_ajax_referer( 'learnpress_admin_quiz_editor', 'nonce' );
544
-
545
- $args = wp_parse_args( $_REQUEST, array( 'id' => false, 'type' => '' ) );
546
-
547
- // get quiz
548
- $quiz_id = $args['id'];
549
- $quiz = learn_press_get_quiz( $quiz_id );
550
-
551
- if ( ! $quiz ) {
552
- wp_send_json_error();
553
- }
554
-
555
- $quiz_curd = new LP_Quiz_CURD();
556
- $question_curd = new LP_Question_CURD();
557
-
558
- $result = array();
559
- $result['status'] = false;
560
-
561
- switch ( $args['type'] ) {
562
- case 'heartbeat' :
563
- $result = true;
564
- break;
565
-
566
- case 'hidden-questions':
567
- $hidden = ! empty( $args['hidden'] ) ? $args['hidden'] : false;
568
- update_post_meta( $quiz_id, '_lp_hidden_questions', $hidden );
569
- break;
570
-
571
- case 'new-question':
572
- // new question
573
- $question = ! empty( $args['question'] ) ? $args['question'] : false;
574
- $question = json_decode( wp_unslash( $question ), true );
575
-
576
- if ( ! $question ) {
577
- break;
578
- }
579
-
580
- // draft quiz
581
- if ( get_post_status( $quiz_id ) == 'auto-draft' ) {
582
-
583
- $draft_quiz = ! empty( $args['draft_quiz'] ) ? $args['draft_quiz'] : '';
584
- $draft_quiz = (array) ( json_decode( wp_unslash( $draft_quiz ), '' ) );
585
-
586
- $quiz_args = array(
587
- 'id' => $quiz_id,
588
- 'title' => $draft_quiz['title'] ? $draft_quiz['title'] : __( 'New Quiz', 'learnpress' ),
589
- 'content' => $draft_quiz['content'],
590
- 'status' => 'draft'
591
- );
592
-
593
- $quiz_id = $quiz_curd->create( $quiz_args );
594
- }
595
-
596
- if ( ! $quiz_id ) {
597
- $result = new WP_Error( __( 'Quiz creation failed.', 'learnpress' ) );
598
- break;
599
- }
600
-
601
- $args = array(
602
- 'quiz_id' => $quiz_id,
603
- 'title' => $question['title'],
604
- 'type' => $question['type'],
605
- );
606
-
607
- $new_question = $question_curd->create( $args );
608
-
609
- if ( ! is_wp_error( $new_question ) ) {
610
-
611
- // update hidden questions in quiz meta
612
- $quiz = LP_Quiz::get_quiz( $quiz_id );
613
- $hidden_questions = $quiz->get_questions();
614
- if ( $hidden_questions ) {
615
- unset( $hidden_questions[ $new_question->get_id() ] );
616
- $hidden_questions = array_keys( $hidden_questions );
617
- }
618
- update_post_meta( $quiz_id, '_lp_hidden_questions', $hidden_questions );
619
-
620
- // get new question data
621
- $result = LP_Admin_Ajax::get_question_data_to_quiz_editor( $new_question, true, array( 'open' => true ) );
622
- }
623
- break;
624
-
625
- case 'sort-questions':
626
- $order = ! empty( $args['order'] ) ? $args['order'] : false;
627
- $order = json_decode( wp_unslash( $order ), true );
628
-
629
- if ( ! $order ) {
630
- break;
631
- }
632
-
633
- $result = $quiz_curd->sort_questions( $order );
634
- break;
635
-
636
- case 'update-question-title':
637
- $question = ! empty( $args['question'] ) ? $args['question'] : false;
638
- $question = json_decode( wp_unslash( $question ), true );
639
-
640
- if ( ! $question ) {
641
- break;
642
- }
643
-
644
- wp_update_post( array( 'ID' => $question['id'], 'post_title' => $question['title'] ) );
645
-
646
- $result['status'] = true;
647
- break;
648
-
649
- case 'change-question-type':
650
- $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
651
- $type = ! empty( $args['question_type'] ) ? $args['question_type'] : false;
652
-
653
- if ( ! ( $question_id || $type ) ) {
654
- break;
655
- }
656
-
657
- $question = LP_Question::get_question( $question_id );
658
-
659
- // change question type
660
- $question = $question_curd->change_question_type( $question, $type );
661
-
662
- $result = LP_Admin_Ajax::get_question_data_to_quiz_editor( $question, true );
663
- break;
664
-
665
- case 'clone-question':
666
- $question = ! empty( $args['question'] ) ? $args['question'] : false;
667
- $question = json_decode( wp_unslash( $question ), true );
668
-
669
- if ( ! $question ) {
670
- break;
671
- }
672
-
673
- // duplicate question
674
- $new_question_id = $question_curd->duplicate( $question['id'], array( 'post_status' => 'publish' ) );
675
-
676
- if ( ! is_wp_error( $new_question_id ) ) {
677
-
678
- // add question to hidden questions in quiz meta
679
- $hidden_questions = get_post_meta( $quiz_id, '_lp_hidden_questions', true );
680
- if ( ! $hidden_questions ) {
681
- $hidden_questions = array();
682
- }
683
- $hidden_questions[] = $new_question_id;// add question to hidden questions in quiz meta
684
- update_post_meta( $quiz_id, '_lp_hidden_questions', $hidden_questions );
685
-
686
- // add question to quiz
687
- $quiz_curd->add_question( $quiz_id, $new_question_id );
688
-
689
- $result = LP_Admin_Ajax::get_question_data_to_quiz_editor( $new_question_id );
690
- }
691
- break;
692
-
693
- case 'remove-question':
694
- $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
695
-
696
- if ( ! $question_id ) {
697
- break;
698
- }
699
-
700
- $result = $quiz_curd->remove_questions( $quiz_id, $question_id );
701
- break;
702
-
703
- case 'delete-question':
704
- $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
705
-
706
- if ( ! $question_id ) {
707
- break;
708
- }
709
-
710
- $result = wp_delete_post( $question_id );
711
- break;
712
-
713
- case 'sort-question-answers':
714
- $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
715
-
716
- $order = ! empty( $args['order'] ) ? $args['order'] : false;
717
- $order = json_decode( wp_unslash( $order ), true );
718
-
719
-
720
- if ( ! ( $question_id && $order ) ) {
721
- break;
722
- }
723
-
724
- // sort answer
725
- $result = $question_curd->sort_answers( $question_id, $order );
726
- break;
727
-
728
- case 'update-question-answer-title':
729
- // question id
730
- $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
731
-
732
- // answers
733
- $answer = ! empty( $args['answer'] ) ? $args['answer'] : false;
734
- $answer = json_decode( wp_unslash( $answer ), true );
735
-
736
- if ( ! ( $question_id && $answer ) ) {
737
- break;
738
- }
739
-
740
- // update answer title
741
- $result = $question_curd->update_answer_title( $question_id, $answer );
742
- break;
743
-
744
- case 'change-question-correct-answer':
745
- $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
746
-
747
- // correct answer
748
- $correct = ! empty( $args['correct'] ) ? $args['correct'] : false;
749
- $correct = json_decode( wp_unslash( $correct ), true );
750
-
751
- if ( ! ( $question_id && $correct ) ) {
752
- break;
753
- }
754
-
755
- $question = LP_Question::get_question( $question_id );
756
- // update correct answer, get new question
757
- $question = $question_curd->change_correct_answer( $question, $correct );
758
-
759
- $result = LP_Admin_Ajax::get_question_data_to_quiz_editor( $question, true );
760
- break;
761
-
762
- case 'delete-question-answer':
763
- $question_id = isset( $_POST['question_id'] ) ? $_POST['question_id'] : false;
764
- $answer_id = isset( $_POST['answer_id'] ) ? intval( $_POST['answer_id'] ) : false;
765
-
766
- if ( ! ( $question_id && $answer_id ) ) {
767
- break;
768
- }
769
-
770
- $result = $question_curd->delete_answer( $question_id, $answer_id );
771
- break;
772
-
773
- case 'new-question-answer':
774
- $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
775
-
776
- if ( ! $question_id ) {
777
- break;
778
- }
779
-
780
- // new answer
781
- $answer = LP_Question::get_default_answer();
782
- // add new
783
- $new_answer_id = $question_curd->new_answer( $question_id, $answer );
784
-
785
- $question = LP_Question::get_question( $question_id );
786
-
787
- if ( $new_answer_id ) {
788
- $result = array_merge( $answer, array(
789
- 'question_answer_id' => $new_answer_id,
790
- 'question_id' => $question_id,
791
- 'answer_order' => count( $question->get_data( 'answer_options' ) )
792
- ) );
793
- }
794
- break;
795
-
796
- case 'update-question-content':
797
- $question = ! empty( $args['question'] ) ? $args['question'] : false;
798
- $question = json_decode( wp_unslash( $question ), true );
799
-
800
- if ( ! $question ) {
801
- break;
802
- }
803
-
804
- wp_update_post( array(
805
- 'ID' => $question['id'],
806
- 'post_content' => $question['settings']['content']
807
- ) );
808
-
809
- $result['status'] = true;
810
- break;
811
-
812
- case 'update-question-meta':
813
- $question = ! empty( $args['question'] ) ? $args['question'] : false;
814
- $question = json_decode( wp_unslash( $question ), true );
815
-
816
- $meta_key = ! empty( $args['meta_key'] ) ? $args['meta_key'] : false;
817
-
818
- if ( ! ( $question && $meta_key ) ) {
819
- break;
820
- }
821
-
822
- update_post_meta( $question['id'], '_lp_' . $meta_key, $question['settings'][ $meta_key ] );
823
-
824
- $result['status'] = true;
825
- break;
826
-
827
- case 'search-items':
828
- $query = ! empty( $args['query'] ) ? $args['query'] : '';
829
- $page = ! empty( $args['page'] ) ? intval( $args['page'] ) : 1;
830
- $exclude = ! empty( $args['exclude'] ) ? intval( $args['exclude'] ) : '';
831
-
832
- if ( $exclude ) {
833
- $exclude = json_decode( $exclude, true );
834
- }
835
-
836
- $ids_exclude = array();
837
- if ( is_array( $exclude ) ) {
838
- foreach ( $exclude as $item ) {
839
- $ids_exclude[] = $item['id'];
840
- }
841
- }
842
-
843
- $search = new LP_Modal_Search_Items( array(
844
- 'type' => 'lp_question',
845
- 'context' => 'quiz',
846
- 'context_id' => $quiz_id,
847
- 'term' => $query,
848
- 'limit' => apply_filters( 'learn-press/quiz-editor/choose-items-limit', 10 ),
849
- 'paged' => $page,
850
- 'exclude' => $ids_exclude
851
- ) );
852
-
853
- $ids_item = $search->get_items();
854
-
855
- $items = array();
856
- foreach ( $ids_item as $id ) {
857
- $post = get_post( $id );
858
-
859
- $items[] = array(
860
- 'id' => $post->ID,
861
- 'title' => $post->post_title,
862
- 'type' => $post->post_type
863
- );
864
- }
865
-
866
- $result = array(
867
- 'items' => $items,
868
- 'pagination' => $search->get_pagination( false )
869
- );
870
- break;
871
-
872
- case 'add-questions-to-quiz':
873
- // added questions
874
- $questions = isset( $_POST['items'] ) ? $_POST['items'] : false;
875
- $questions = json_decode( wp_unslash( $questions ), true );
876
-
877
- if ( ! $questions ) {
878
- break;
879
- }
880
-
881
- // draft quiz
882
- if ( get_post_status( $quiz_id ) == 'auto-draft' ) {
883
-
884
- $draft_quiz = ! empty( $args['draft_quiz'] ) ? $args['draft_quiz'] : '';
885
- $draft_quiz = (array) ( json_decode( wp_unslash( $draft_quiz ), '' ) );
886
-
887
- $quiz_args = array(
888
- 'id' => $quiz_id,
889
- 'title' => $draft_quiz['title'],
890
- 'content' => $draft_quiz['content'],
891
- 'status' => 'draft'
892
- );
893
-
894
- $quiz_id = $quiz_curd->create( $quiz_args );
895
- }
896
-
897
- if ( ! $quiz_id ) {
898
- $result = new WP_Error( __( 'Quiz creation failed.', 'learnpress' ) );
899
- break;
900
- }
901
-
902
- if ( $questions ) {
903
- // add question to hidden questions in quiz meta
904
- $hidden_questions = get_post_meta( $quiz_id, '_lp_hidden_questions', true );
905
- if ( ! $hidden_questions ) {
906
- $hidden_questions = array();
907
- }
908
-
909
- foreach ( $questions as $key => $question ) {
910
- // add question to hidden questions in quiz meta
911
- $hidden_questions[] = $question['id'];
912
- update_post_meta( $quiz_id, '_lp_hidden_questions', $hidden_questions );
913
- // add question to quiz
914
- $quiz_curd->add_question( $quiz_id, $question['id'] );
915
- }
916
- $result = $quiz->quiz_editor_get_questions();
917
- }
918
- break;
919
-
920
- default:
921
- break;
922
- }
923
 
924
  if ( is_wp_error( $result ) ) {
925
- wp_send_json_error( $result->get_error_message() );
 
 
926
  }
927
 
928
- wp_send_json_success( $result );
929
  }
930
 
931
  /**
@@ -977,91 +201,6 @@ if ( ! class_exists( 'LP_Admin_Ajax' ) ) {
977
  }
978
  }
979
 
980
- /**
981
- * Get question data in admin question editor.
982
- *
983
- * @since 3.0.0
984
- *
985
- * @param $question
986
- * @param $object | if true, input in question object, do not need init LP_Question::get_question()
987
- *
988
- * @return array
989
- */
990
- public static function get_question_data_to_question_editor( $question, $object = false ) {
991
-
992
- if ( ! $object ) {
993
- if ( get_post_type( $question ) !== LP_QUESTION_CPT ) {
994
- return array();
995
- }
996
-
997
- // get question
998
- $question = LP_Question::get_question( $question );
999
- }
1000
-
1001
- // question id
1002
- $question_id = $question->get_id();
1003
-
1004
- $data = array(
1005
- 'id' => $question_id,
1006
- 'open' => false,
1007
- 'title' => get_the_title( $question_id ),
1008
- 'type' => array(
1009
- 'key' => $question->get_type(),
1010
- 'label' => $question->get_type_label()
1011
- ),
1012
- 'answers' => is_array( $question->get_data( 'answer_options' ) ) ? array_values( $question->get_data( 'answer_options' ) ) : array()
1013
- );
1014
-
1015
- return $data;
1016
- }
1017
-
1018
- /**
1019
- * Get question data in admin quiz editor.
1020
- *
1021
- * @since 3.0.0
1022
- *
1023
- * @param $question
1024
- * @param $object | if true, input in question object, do not need init LP_Question::get_question()
1025
- * @param array $args
1026
- *
1027
- * @return array
1028
- */
1029
- public static function get_question_data_to_quiz_editor( $question, $object = false, $args = array() ) {
1030
-
1031
- if ( ! $object ) {
1032
- if ( get_post_type( $question ) !== LP_QUESTION_CPT ) {
1033
- return array();
1034
- }
1035
-
1036
- // get question
1037
- $question = LP_Question::get_question( $question );
1038
- }
1039
-
1040
- // question id
1041
- $question_id = $question->get_id();
1042
- // question answer
1043
- $answers = array_values( $question->get_data( 'answer_options' ) );
1044
-
1045
- $data = wp_parse_args( $args, array(
1046
- 'id' => $question_id,
1047
- 'open' => false,
1048
- 'title' => get_the_title( $question_id ),
1049
- 'type' => array(
1050
- 'key' => $question->get_type(),
1051
- 'label' => $question->get_type_label()
1052
- ),
1053
- 'answers' => $answers,
1054
- 'settings' => array(
1055
- 'mark' => get_post_meta( $question_id, '_lp_mark', true ),
1056
- 'explanation' => get_post_meta( $question_id, '_lp_explanation', true ),
1057
- 'hint' => get_post_meta( $question_id, '_lp_hint', true )
1058
- ),
1059
- 'order' => count( $answers )
1060
- ) );
1061
-
1062
- return $data;
1063
- }
1064
-
1065
  /**
1066
  * Update ordering of payments when user changing.
1067
  *
111
  * @since 3.0.0
112
  */
113
  public static function admin_course_editor() {
114
+ $editor = LP_Admin_Editor::get_editor_course();
115
+ self::admin_editor( $editor );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  }
117
 
118
  /**
121
  * @since 3.0.0
122
  */
123
  public static function admin_question_editor() {
124
+ $editor = LP_Admin_Editor::get_editor_question();
125
+ self::admin_editor( $editor );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  }
127
 
128
  /**
131
  * @since 3.0.0
132
  */
133
  public static function admin_quiz_editor() {
134
+ $editor = LP_Admin_Editor::get_editor_quiz();
135
+ self::admin_editor( $editor );
136
+ }
137
 
138
+ /**
139
+ * @since 3.0.2
140
+ *
141
+ * @param LP_Admin_Editor $editor
142
+ */
143
+ public static function admin_editor( &$editor ) {
144
+ $result = $editor->dispatch();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
 
146
  if ( is_wp_error( $result ) ) {
147
+ learn_press_send_json_error( $result->get_error_message() );
148
+ } elseif ( ! $result ) {
149
+ learn_press_send_json_error();
150
  }
151
 
152
+ learn_press_send_json_success( $result );
153
  }
154
 
155
  /**
201
  }
202
  }
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  /**
205
  * Update ordering of payments when user changing.
206
  *
inc/admin/class-lp-admin.php CHANGED
@@ -706,6 +706,7 @@ if ( ! class_exists( 'LP_Admin' ) ) {
706
  include_once 'class-lp-admin-dashboard.php';
707
  include_once 'class-lp-admin-tools.php';
708
  include_once 'class-lp-admin-ajax.php';
 
709
  include_once 'class-lp-admin-menu.php';
710
  include_once 'class-lp-meta-box-tabs.php';
711
  include_once 'helpers/class-lp-outdated-template-helper.php';
706
  include_once 'class-lp-admin-dashboard.php';
707
  include_once 'class-lp-admin-tools.php';
708
  include_once 'class-lp-admin-ajax.php';
709
+ include_once 'editor/class-lp-admin-editor.php';
710
  include_once 'class-lp-admin-menu.php';
711
  include_once 'class-lp-meta-box-tabs.php';
712
  include_once 'helpers/class-lp-outdated-template-helper.php';
inc/admin/editor/class-lp-admin-editor-course.php ADDED
@@ -0,0 +1,363 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class LP_Admin_Editor_Course
5
+ *
6
+ * @since 3.0.2
7
+ */
8
+ class LP_Admin_Editor_Course extends LP_Admin_Editor {
9
+
10
+ /**
11
+ * @var LP_Course_CURD
12
+ */
13
+ protected $course_curd = null;
14
+
15
+ /**
16
+ * @var LP_Section_CURD
17
+ */
18
+ protected $section_curd = null;
19
+
20
+ /**
21
+ * @var LP_Course
22
+ */
23
+ protected $course = null;
24
+
25
+ /**
26
+ * LP_Admin_Editor_Course constructor.
27
+ */
28
+ public function __construct() {
29
+
30
+ }
31
+
32
+ /**
33
+ * Do the action depending on ajax calls with params
34
+ *
35
+ * @return bool|WP_Error
36
+ */
37
+ public function dispatch() {
38
+ check_ajax_referer( 'learnpress_update_curriculum', 'nonce' );
39
+
40
+ $args = wp_parse_args( $_REQUEST, array( 'id' => false, 'type' => '' ) );
41
+ $course_id = $args['id'];
42
+ $course = learn_press_get_course( $course_id );
43
+
44
+ if ( ! $course ) {
45
+ return false;
46
+ }
47
+
48
+ $this->course = $course;
49
+ $this->course_curd = new LP_Course_CURD();
50
+ $this->section_curd = new LP_Section_CURD( $course_id );
51
+ $this->result = array( $args['type'] );
52
+
53
+ $this->call( $args['type'], array( $args ) );
54
+
55
+ return $this->get_result();
56
+ }
57
+
58
+ /**
59
+ * @param array $args
60
+ *
61
+ * @return bool
62
+ */
63
+ public function draft_course( $args = array() ) {
64
+ $new_course = ! empty( $args['course'] ) ? $args['course'] : false;
65
+ $new_course = json_decode( wp_unslash( $new_course ), true );
66
+
67
+ if ( ! $new_course ) {
68
+ return false;
69
+ }
70
+
71
+ $title = $new_course['title'] ? $new_course['title'] : __( 'New Course', 'learnpress' );
72
+ $content = $new_course['content'] ? $new_course['content'] : '';
73
+
74
+ $args = array(
75
+ 'id' => $this->course->get_id(),
76
+ 'status' => 'draft',
77
+ 'title' => $title,
78
+ 'content' => $content
79
+ );
80
+
81
+ $this->course_curd->create( $args );
82
+
83
+ return true;
84
+ }
85
+
86
+ /**
87
+ * @param array $args
88
+ */
89
+ public function hide_sections( $args ) {
90
+ // get hidden sections id
91
+ $hidden = ! empty( $args['hidden'] ) ? $args['hidden'] : false;
92
+ // update course post meta
93
+ update_post_meta( $this->course->get_id(), '_admin_hidden_sections', $hidden );
94
+ }
95
+
96
+ /**
97
+ * Sort sections
98
+ *
99
+ * @param array $args
100
+ */
101
+ public function sort_sections( $args = array() ) {
102
+ $order = ! empty( $args['order'] ) ? $args['order'] : false;
103
+ $order = json_decode( wp_unslash( $order ), true );
104
+
105
+ if ( ! $order ) {
106
+ return;
107
+ }
108
+
109
+ $this->result = $this->section_curd->sort_sections( $order );
110
+
111
+ // last section
112
+ $last_section_id = end( $order );
113
+ // update final quiz
114
+ $this->section_curd->update_final_quiz( $last_section_id );
115
+ }
116
+
117
+ /**
118
+ * @param array $args
119
+ *
120
+ * @return mixed
121
+ */
122
+ public function update_section( $args = array() ) {
123
+ $section = ! empty( $args['section'] ) ? $args['section'] : false;
124
+ $section = json_decode( wp_unslash( $section ), true );
125
+
126
+ if ( ! $section ) {
127
+ return false;
128
+ }
129
+
130
+ $update = array(
131
+ 'section_id' => $section['id'],
132
+ 'section_name' => $section['title'],
133
+ 'section_description' => $section['description'],
134
+ 'section_order' => $section['order'],
135
+ 'section_course_id' => $section['course_id'],
136
+ );
137
+
138
+ $this->result = $this->section_curd->update( $update );
139
+
140
+ return true;
141
+ }
142
+
143
+ /**
144
+ * @param array $args
145
+ *
146
+ * @return mixed
147
+ */
148
+ public function remove_section( $args = array() ) {
149
+ $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
150
+
151
+ if ( ! $section_id ) {
152
+ return false;
153
+ }
154
+
155
+ $this->section_curd->delete( $section_id );
156
+
157
+ return true;
158
+ }
159
+
160
+ /**
161
+ * @param array $args
162
+ *
163
+ * @return mixed
164
+ */
165
+ public function new_section( $args = array() ) {
166
+ $section_name = ! empty( $args['section_name'] ) ? $args['section_name'] : false;
167
+
168
+ $args = array(
169
+ 'section_course_id' => $this->course->get_id(),
170
+ 'section_description' => '',
171
+ 'section_name' => $section_name,
172
+ 'items' => array(),
173
+ );
174
+
175
+ // create section
176
+ $section = $this->section_curd->create( $args );
177
+
178
+ $this->result = array(
179
+ 'id' => $section['section_id'],
180
+ 'items' => $section['items'],
181
+ 'title' => $section['section_name'],
182
+ 'description' => $section['section_description'],
183
+ 'course_id' => $section['section_course_id'],
184
+ 'order' => $section['section_order'],
185
+ );
186
+
187
+ return true;
188
+ }
189
+
190
+ /**
191
+ * @param array $args
192
+ *
193
+ * @return mixed
194
+ */
195
+ public function update_section_item( $args = array() ) {
196
+ $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
197
+ $item = ! empty( $args['item'] ) ? $args['item'] : false;
198
+ $item = json_decode( wp_unslash( $item ), true );
199
+
200
+ if ( ! ( $section_id && $item ) ) {
201
+ return func_get_args();
202
+ }
203
+
204
+ // update lesson, quiz title
205
+ $this->result = $this->section_curd->update_item( $item );
206
+
207
+ return true;
208
+ }
209
+
210
+ /**
211
+ * @param array $args
212
+ *
213
+ * @return mixed
214
+ */
215
+ public function remove_section_item( $args = array() ) {
216
+ $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
217
+ $item_id = ! empty( $args['item_id'] ) ? $args['item_id'] : false;
218
+
219
+ if ( ! ( $section_id && $item_id ) ) {
220
+ return false;
221
+ }
222
+
223
+ // remove item from course
224
+ $this->course_curd->remove_item( $item_id );
225
+
226
+ return true;
227
+ }
228
+
229
+ /**
230
+ * @param array $args
231
+ *
232
+ * @return mixed
233
+ */
234
+ public function delete_section_item( $args = array() ) {
235
+ $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
236
+ $item_id = ! empty( $args['item_id'] ) ? $args['item_id'] : false;
237
+
238
+ if ( ! ( $section_id && $item_id ) ) {
239
+ return false;
240
+ }
241
+
242
+ $this->result = wp_delete_post( $item_id );
243
+
244
+ return true;
245
+ }
246
+
247
+ /**
248
+ * @param array $args
249
+ *
250
+ * @return array|bool
251
+ */
252
+ public function new_section_item( $args = array() ) {
253
+ $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
254
+ $item = ! empty( $args['item'] ) ? $args['item'] : false;
255
+ $item = json_decode( wp_unslash( $item ), true );
256
+
257
+ if ( ! ( $section_id && $item ) ) {
258
+ return false;
259
+ }
260
+
261
+ // create new lesson, quiz and add to course
262
+ $this->result = $this->section_curd->new_item( $section_id, $item );
263
+
264
+ return true;
265
+ }
266
+
267
+ /**
268
+ * @param array $args
269
+ *
270
+ * @return mixed
271
+ */
272
+ public function update_section_items( $args = array() ) {
273
+ $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
274
+ $last_section = ! empty( $args['last_section'] ) ? $args['last_section'] : false;
275
+ $items = ! empty( $args['items'] ) ? $args['items'] : false;
276
+ $items = json_decode( wp_unslash( $items ), true );
277
+
278
+ if ( ! ( $section_id && $items ) ) {
279
+ return false;
280
+ }
281
+
282
+ $this->result = $this->section_curd->update_section_items( $section_id, $items );
283
+
284
+ if ( $last_section ) {
285
+ $this->section_curd->update_final_quiz( $section_id );
286
+ }
287
+
288
+ return true;
289
+ }
290
+
291
+ /**
292
+ * @param array $args
293
+ *
294
+ * @return mixed
295
+ */
296
+ public function search_items( $args = array() ) {
297
+ $query = isset( $args['query'] ) ? $args['query'] : '';
298
+ $type = isset( $args['item_type'] ) ? $args['item_type'] : '';
299
+ $page = ! empty( $args['page'] ) ? $args['page'] : 1;
300
+ $exclude = ! empty( $args['exclude'] ) ? $args['exclude'] : '';
301
+
302
+ if ( $exclude ) {
303
+ $exclude = json_decode( $exclude, true );
304
+ }
305
+
306
+ $ids_exclude = array();
307
+
308
+ if ( is_array( $exclude ) ) {
309
+ foreach ( $exclude as $item ) {
310
+ $ids_exclude[] = $item['id'];
311
+ }
312
+ }
313
+
314
+ $search = new LP_Modal_Search_Items( array(
315
+ 'type' => $type,
316
+ 'context' => 'course',
317
+ 'context_id' => $this->course->get_id(),
318
+ 'term' => $query,
319
+ 'limit' => apply_filters( 'learn-press/course-editor/choose-items-limit', 10 ),
320
+ 'paged' => $page,
321
+ 'exclude' => $ids_exclude,
322
+ ) );
323
+
324
+ $id_items = $search->get_items();
325
+
326
+ $items = array();
327
+ foreach ( $id_items as $id ) {
328
+ $post = get_post( $id );
329
+
330
+ $items[] = array(
331
+ 'id' => $post->ID,
332
+ 'title' => $post->post_title,
333
+ 'type' => $post->post_type,
334
+ );
335
+ }
336
+
337
+ $this->result = array(
338
+ 'items' => $items,
339
+ 'pagination' => $search->get_pagination( false )
340
+ );
341
+
342
+ return true;
343
+ }
344
+
345
+ /**
346
+ * @param array $args
347
+ *
348
+ * @return mixed
349
+ */
350
+ public function add_items_to_section( $args = array() ) {
351
+ $section_id = ! empty( $args['section_id'] ) ? $args['section_id'] : false;
352
+ $items = ! empty( $args['items'] ) ? $args['items'] : false;
353
+ $items = json_decode( wp_unslash( $items ), true );
354
+
355
+ if ( ! $items || ! $section_id ) {
356
+ return false;
357
+ }
358
+
359
+ $this->result = $this->section_curd->add_items_section( $section_id, $items );
360
+
361
+ return true;
362
+ }
363
+ }
inc/admin/editor/class-lp-admin-editor-question.php ADDED
@@ -0,0 +1,255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class LP_Admin_Editor_Question
5
+ *
6
+ * @since 3.0.2
7
+ */
8
+ class LP_Admin_Editor_Question extends LP_Admin_Editor {
9
+
10
+ /**
11
+ * @var LP_Question
12
+ */
13
+ protected $question = null;
14
+
15
+ /**
16
+ * @var LP_Question_CURD
17
+ */
18
+ protected $question_curd = null;
19
+
20
+ /**
21
+ * LP_Admin_Editor_Question constructor.
22
+ */
23
+ public function __construct() {
24
+ }
25
+
26
+ public function dispatch() {
27
+ check_ajax_referer( 'learnpress_admin_question_editor', 'nonce' );
28
+
29
+ $args = wp_parse_args( $_REQUEST, array( 'id' => false, 'type' => '' ) );
30
+ $question_id = $args['id'];
31
+ $question = LP_Question::get_question( $question_id );
32
+
33
+ if ( ! $question ) {
34
+ return false;
35
+ }
36
+
37
+ $this->question = $question;
38
+ $this->question_curd = new LP_Question_CURD();
39
+ $this->result = array( 'status' => false );
40
+
41
+ $this->call( $args['type'], array( $args ) );
42
+
43
+ return $this->get_result();
44
+ }
45
+
46
+ /**
47
+ * Get question data in admin question editor.
48
+ *
49
+ * @since 3.0.0
50
+ *
51
+ * @param $question
52
+ * @param $object | if true, input in question object, do not need init LP_Question::get_question()
53
+ *
54
+ * @return array
55
+ */
56
+ public function get_question_data_to_question_editor( $question, $object = false ) {
57
+
58
+ if ( ! $object ) {
59
+ if ( get_post_type( $question ) !== LP_QUESTION_CPT ) {
60
+ return array();
61
+ }
62
+
63
+ // get question
64
+ $question = LP_Question::get_question( $question );
65
+ }
66
+
67
+ // question id
68
+ $question_id = $question->get_id();
69
+
70
+ $data = array(
71
+ 'id' => $question_id,
72
+ 'open' => false,
73
+ 'title' => get_the_title( $question_id ),
74
+ 'type' => array(
75
+ 'key' => $question->get_type(),
76
+ 'label' => $question->get_type_label()
77
+ ),
78
+ 'answers' => is_array( $question->get_data( 'answer_options' ) ) ? array_values( $question->get_data( 'answer_options' ) ) : array()
79
+ );
80
+
81
+ return $data;
82
+ }
83
+
84
+ /**
85
+ * Draft question.
86
+ *
87
+ * @since 3.0.0
88
+ *
89
+ * @param $question_id
90
+ * @param array $args
91
+ *
92
+ * @return bool|int|LP_Question
93
+ */
94
+ private function draft_question( $question_id, $args = array() ) {
95
+
96
+ if ( get_post_status( $question_id ) != 'auto-draft' ) {
97
+ return false;
98
+ }
99
+
100
+ $curd = new LP_Question_CURD();
101
+
102
+ $args = wp_parse_args( $args, array(
103
+ 'id' => $question_id,
104
+ 'title' => __( 'New Question', 'learnpress' ),
105
+ 'content' => '',
106
+ 'status' => 'draft',
107
+ 'create_answers' => false
108
+ ) );
109
+
110
+ $question = $curd->create( $args );
111
+
112
+ if ( ! $question ) {
113
+ return false;
114
+ }
115
+
116
+ return $question;
117
+ }
118
+
119
+ /**
120
+ * @param array $args
121
+ *
122
+ * @return bool
123
+ */
124
+ public function change_question_type( $args = array() ) {
125
+ $type = ! empty( $args['question_type'] ) ? $args['question_type'] : false;
126
+
127
+ if ( ! $type ) {
128
+ return false;
129
+ }
130
+
131
+ $question = $this->question;
132
+ // draft question args
133
+ $args = $args['draft_question'] ? $args['draft_question'] : '';
134
+
135
+ if ( $args ) {
136
+ $args = (array) ( json_decode( wp_unslash( $args ), '' ) );
137
+ $draft = $this->draft_question( $this->question->get_id(), $args );
138
+
139
+ // check if draft question false or question exist
140
+ if ( $draft ) {
141
+ $question = $draft;
142
+ }
143
+ }
144
+
145
+ if ( isset( $question ) ) {
146
+ // change question type
147
+ $question = $this->question_curd->change_question_type( $question, $type );
148
+ $this->result = $this->get_question_data_to_question_editor( $question, true );
149
+
150
+ return true;
151
+ }
152
+
153
+ return false;
154
+ }
155
+
156
+ /**
157
+ * @param array $args
158
+ *
159
+ * @return bool
160
+ */
161
+ public function sort_answer( $args = array() ) {
162
+ // answers order
163
+ $order = ! empty( $args['order'] ) ? $args['order'] : false;
164
+
165
+ if ( ! $order ) {
166
+ return false;
167
+ }
168
+
169
+ // sort answers
170
+ $this->question = $this->question_curd->sort_answers( $this->question->get_id(), $order );
171
+
172
+ $this->result = array_values( $this->question->get_data( 'answer_options' ) );
173
+
174
+ return true;
175
+ }
176
+
177
+ /**
178
+ * @param array $args
179
+ *
180
+ * @return bool
181
+ */
182
+ public function update_answer_title( $args = array() ) {
183
+ // answers
184
+ $answer = ! empty( $args['answer'] ) ? $args['answer'] : false;
185
+ $answer = json_decode( wp_unslash( $answer ), true );
186
+
187
+ if ( ! $answer ) {
188
+ return false;
189
+ }
190
+
191
+ // update answer title
192
+ $this->result = $this->question_curd->update_answer_title( $this->question->get_id(), $answer );
193
+
194
+ return true;
195
+ }
196
+
197
+ /**
198
+ * @param array $args
199
+ *
200
+ * @return bool
201
+ */
202
+ public function change_correct( $args = array() ) {
203
+ // correct answer
204
+ $correct = ! empty( $args['correct'] ) ? $args['correct'] : false;
205
+ $correct = json_decode( wp_unslash( $correct ), true );
206
+
207
+ if ( ! $correct ) {
208
+ return false;
209
+ }
210
+
211
+ // update correct answer
212
+ $this->question = $this->question_curd->change_correct_answer( $this->question, $correct );
213
+
214
+ $this->result = $this->question->get_data( 'answer_options' );
215
+
216
+ return true;
217
+ }
218
+
219
+ /**
220
+ * @param array $args
221
+ *
222
+ * @return bool
223
+ */
224
+ public function delete_answer( $args = array() ) {
225
+ // answer id
226
+ $answer_id = ! empty( $args['answer_id'] ) ? $args['answer_id'] : false;
227
+
228
+ if ( ! $answer_id ) {
229
+ return false;
230
+ }
231
+
232
+ // delete answer
233
+ $this->question_curd->delete_answer( $this->question->get_id(), $answer_id );
234
+
235
+ $this->result = $this->question->get_data( 'answer_options' );
236
+
237
+ return true;
238
+ }
239
+
240
+ /**
241
+ * @param array $args
242
+ *
243
+ * @return bool
244
+ */
245
+ public function new_answer( $args = array() ) {
246
+ // new answer
247
+ $answer = LP_Question::get_default_answer();
248
+ // add new
249
+ $this->question_curd->new_answer( $this->question->get_id(), $answer );
250
+
251
+ $this->result = $this->question->get_data( 'answer_options' );
252
+
253
+ return true;
254
+ }
255
+ }
inc/admin/editor/class-lp-admin-editor-quiz.php ADDED
@@ -0,0 +1,594 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class LP_Admin_Editor_Quiz
5
+ *
6
+ * @since 3.0.2
7
+ */
8
+ class LP_Admin_Editor_Quiz extends LP_Admin_Editor {
9
+
10
+ /**
11
+ * @var LP_Quiz_CURD
12
+ */
13
+ protected $quiz_curd = null;
14
+
15
+ /**
16
+ * @var LP_Question_CURD
17
+ */
18
+ protected $question_curd = null;
19
+
20
+ /**
21
+ * @var LP_Quiz
22
+ */
23
+ protected $quiz = null;
24
+
25
+ /**
26
+ * LP_Admin_Editor_Quiz constructor.
27
+ */
28
+ public function __construct() {
29
+ }
30
+
31
+ /**
32
+ * Do the action depending on ajax calls with params
33
+ *
34
+ * @return bool|mixed|WP_Error
35
+ */
36
+ public function dispatch() {
37
+ check_ajax_referer( 'learnpress_admin_quiz_editor', 'nonce' );
38
+ $args = wp_parse_args( $_REQUEST, array( 'id' => false, 'type' => '' ) );
39
+
40
+ // get quiz
41
+ $quiz_id = $args['id'];
42
+ $quiz = learn_press_get_quiz( $quiz_id );
43
+
44
+ if ( ! $quiz ) {
45
+ return new WP_Error( 'INVALID_QUIZ', __( 'Invalid quiz', 'learnpress' ) );
46
+ }
47
+
48
+ $this->quiz = $quiz;
49
+ $this->quiz_curd = new LP_Quiz_CURD();
50
+ $this->question_curd = new LP_Question_CURD();
51
+ $this->result = array( 'status' => false );
52
+
53
+ $this->call( $args['type'], array( $args ) );
54
+
55
+ return $this->get_result();
56
+ }
57
+
58
+ /**
59
+ * Get question data in admin quiz editor.
60
+ *
61
+ * @since 3.0.0
62
+ *
63
+ * @param $question
64
+ * @param $object | if true, input in question object, do not need init LP_Question::get_question()
65
+ * @param array $args
66
+ *
67
+ * @return array
68
+ */
69
+ public function get_question_data_to_quiz_editor( $question, $object = false, $args = array() ) {
70
+
71
+ if ( ! $object ) {
72
+ if ( get_post_type( $question ) !== LP_QUESTION_CPT ) {
73
+ return array();
74
+ }
75
+
76
+ // get question
77
+ $question = LP_Question::get_question( $question );
78
+ }
79
+
80
+ // question id
81
+ $question_id = $question->get_id();
82
+ // question answer
83
+ $answers = array_values( $question->get_data( 'answer_options' ) );
84
+
85
+ $data = wp_parse_args( $args, array(
86
+ 'id' => $question_id,
87
+ 'open' => false,
88
+ 'title' => get_the_title( $question_id ),
89
+ 'type' => array(
90
+ 'key' => $question->get_type(),
91
+ 'label' => $question->get_type_label()
92
+ ),
93
+ 'answers' => $answers,
94
+ 'settings' => array(
95
+ 'mark' => get_post_meta( $question_id, '_lp_mark', true ),
96
+ 'explanation' => get_post_meta( $question_id, '_lp_explanation', true ),
97
+ 'hint' => get_post_meta( $question_id, '_lp_hint', true )
98
+ ),
99
+ 'order' => count( $answers )
100
+ ) );
101
+
102
+ return $data;
103
+ }
104
+
105
+ /**
106
+ * @param array $args
107
+ *
108
+ * @return bool
109
+ */
110
+ public function hidden_questions( $args = array() ) {
111
+ $hidden = ! empty( $args['hidden'] ) ? $args['hidden'] : false;
112
+ update_post_meta( $this->quiz->get_id(), '_lp_hidden_questions', $hidden );
113
+
114
+ return true;
115
+ }
116
+
117
+ /**
118
+ * @param array $args
119
+ *
120
+ * @return bool
121
+ */
122
+ public function new_question( $args = array() ) {
123
+ // new question
124
+ $question = ! empty( $args['question'] ) ? $args['question'] : false;
125
+ $question = json_decode( wp_unslash( $question ), true );
126
+
127
+ if ( ! $question ) {
128
+ return false;
129
+ }
130
+
131
+ $quiz_id = $this->quiz->get_id();
132
+
133
+ // draft quiz
134
+ if ( get_post_status( $quiz_id ) == 'auto-draft' ) {
135
+
136
+ $draft_quiz = ! empty( $args['draft_quiz'] ) ? $args['draft_quiz'] : '';
137
+ $draft_quiz = (array) ( json_decode( wp_unslash( $draft_quiz ), '' ) );
138
+
139
+ $quiz_args = array(
140
+ 'id' => $this->quiz->get_id(),
141
+ 'title' => $draft_quiz['title'] ? $draft_quiz['title'] : __( 'New Quiz', 'learnpress' ),
142
+ 'content' => $draft_quiz['content'],
143
+ 'status' => 'draft'
144
+ );
145
+
146
+ $quiz_id = $this->quiz_curd->create( $quiz_args );
147
+ }
148
+
149
+ if ( ! isset( $quiz_id ) ) {
150
+ $this->result = new WP_Error( 'CREATE_QUIZ_FAILED', __( 'Quiz creation failed.', 'learnpress' ) );
151
+
152
+ return false;
153
+ }
154
+
155
+ $args = array(
156
+ 'quiz_id' => $quiz_id,
157
+ 'title' => $question['title'],
158
+ 'type' => $question['type'],
159
+ );
160
+
161
+ $new_question = $this->question_curd->create( $args );
162
+
163
+ if ( ! is_wp_error( $new_question ) ) {
164
+
165
+ // update hidden questions in quiz meta
166
+ $quiz = LP_Quiz::get_quiz( $quiz_id );
167
+ $hidden_questions = $quiz->get_questions();
168
+
169
+ if ( $hidden_questions ) {
170
+ unset( $hidden_questions[ $new_question->get_id() ] );
171
+ $hidden_questions = array_keys( $hidden_questions );
172
+ }
173
+
174
+ update_post_meta( $quiz_id, '_lp_hidden_questions', $hidden_questions );
175
+
176
+ // get new question data
177
+ $this->result = $this->get_question_data_to_quiz_editor( $new_question, true, array( 'open' => true ) );
178
+
179
+ return true;
180
+ }
181
+
182
+ return false;
183
+ }
184
+
185
+ /**
186
+ * @param array $args
187
+ *
188
+ * @return bool
189
+ */
190
+ public function sort_questions( $args = array() ) {
191
+ $order = ! empty( $args['order'] ) ? $args['order'] : false;
192
+ $order = json_decode( wp_unslash( $order ), true );
193
+
194
+ if ( ! $order ) {
195
+ return false;
196
+ }
197
+
198
+ $this->result = $this->quiz_curd->sort_questions( $order );
199
+
200
+ return true;
201
+ }
202
+
203
+ /**
204
+ * @param array $args
205
+ *
206
+ * @return bool
207
+ */
208
+ public function update_question_title( $args = array() ) {
209
+ $question = ! empty( $args['question'] ) ? $args['question'] : false;
210
+ $question = json_decode( wp_unslash( $question ), true );
211
+
212
+ if ( ! $question ) {
213
+ return false;
214
+ }
215
+
216
+ wp_update_post( array( 'ID' => $question['id'], 'post_title' => $question['title'] ) );
217
+
218
+ $this->result['status'] = true;
219
+
220
+ return true;
221
+ }
222
+
223
+ /**
224
+ * @param array $args
225
+ *
226
+ * @return bool
227
+ */
228
+ public function change_question_type( $args = array() ) {
229
+ $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
230
+ $type = ! empty( $args['question_type'] ) ? $args['question_type'] : false;
231
+
232
+ if ( ! ( $question_id || $type ) ) {
233
+ return false;
234
+ }
235
+
236
+ $question = LP_Question::get_question( $question_id );
237
+
238
+ // change question type
239
+ $question = $this->question_curd->change_question_type( $question, $type );
240
+
241
+ $this->result = $this->get_question_data_to_quiz_editor( $question, true );
242
+
243
+ return true;
244
+ }
245
+
246
+ /**
247
+ * @param array $args
248
+ *
249
+ * @return bool
250
+ */
251
+ public function clone_question( $args = array() ) {
252
+ $question = ! empty( $args['question'] ) ? $args['question'] : false;
253
+ $question = json_decode( wp_unslash( $question ), true );
254
+
255
+ if ( ! $question ) {
256
+ return false;
257
+ }
258
+
259
+ // duplicate question
260
+ $new_question_id = $this->question_curd->duplicate( $question['id'], array( 'post_status' => 'publish' ) );
261
+
262
+ if ( ! is_wp_error( $new_question_id ) ) {
263
+
264
+ // add question to hidden questions in quiz meta
265
+ $hidden_questions = get_post_meta( $this->quiz->get_id(), '_lp_hidden_questions', true );
266
+ if ( ! $hidden_questions ) {
267
+ $hidden_questions = array();
268
+ }
269
+ $hidden_questions[] = $new_question_id;// add question to hidden questions in quiz meta
270
+ update_post_meta( $this->quiz->get_id(), '_lp_hidden_questions', $hidden_questions );
271
+
272
+ // add question to quiz
273
+ $this->quiz_curd->add_question( $this->quiz->get_id(), $new_question_id );
274
+
275
+ $this->result = $this->get_question_data_to_quiz_editor( $new_question_id );
276
+
277
+ return true;
278
+ }
279
+
280
+ return false;
281
+ }
282
+
283
+ /**
284
+ * @param array $args
285
+ *
286
+ * @return bool
287
+ */
288
+ public function remove_question( $args = array() ) {
289
+ $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
290
+
291
+ if ( ! $question_id ) {
292
+ return false;
293
+ }
294
+
295
+ $this->result = $this->quiz_curd->remove_questions( $this->quiz->get_id(), $question_id );
296
+
297
+ return true;
298
+ }
299
+
300
+ /**
301
+ * @param array $args
302
+ *
303
+ * @return bool
304
+ */
305
+ public function delete_question( $args = array() ) {
306
+ $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
307
+
308
+ if ( ! $question_id ) {
309
+ return false;
310
+ }
311
+
312
+ $this->result = wp_delete_post( $question_id );
313
+
314
+ return true;
315
+ }
316
+
317
+ /**
318
+ * @param array $args
319
+ *
320
+ * @return bool
321
+ */
322
+ public function sort_question_answers( $args = array() ) {
323
+ $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
324
+
325
+ $order = ! empty( $args['order'] ) ? $args['order'] : false;
326
+ $order = json_decode( wp_unslash( $order ), true );
327
+
328
+
329
+ if ( ! ( $question_id && $order ) ) {
330
+ return false;
331
+ }
332
+
333
+ // sort answer
334
+ $this->result = $this->question_curd->sort_answers( $question_id, $order );
335
+
336
+ return true;
337
+ }
338
+
339
+ /**
340
+ * @param array $args
341
+ *
342
+ * @return bool
343
+ */
344
+ public function update_question_answer_title( $args = array() ) {
345
+ // question id
346
+ $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
347
+
348
+ // answers
349
+ $answer = ! empty( $args['answer'] ) ? $args['answer'] : false;
350
+ $answer = json_decode( wp_unslash( $answer ), true );
351
+
352
+ if ( ! ( $question_id && $answer ) ) {
353
+ return false;
354
+ }
355
+
356
+ // update answer title
357
+ $this->result = $this->question_curd->update_answer_title( $question_id, $answer );
358
+
359
+ return true;
360
+ }
361
+
362
+ /**
363
+ * @param array $args
364
+ *
365
+ * @return bool
366
+ */
367
+ public function change_question_correct_answer( $args = array() ) {
368
+ $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
369
+
370
+ // correct answer
371
+ $correct = ! empty( $args['correct'] ) ? $args['correct'] : false;
372
+ $correct = json_decode( wp_unslash( $correct ), true );
373
+
374
+ if ( ! ( $question_id && $correct ) ) {
375
+ return false;
376
+ }
377
+
378
+ $question = LP_Question::get_question( $question_id );
379
+ // update correct answer, get new question
380
+ $question = $this->question_curd->change_correct_answer( $question, $correct );
381
+
382
+ $this->result = $this->get_question_data_to_quiz_editor( $question, true );
383
+
384
+ return true;
385
+ }
386
+
387
+ /**
388
+ * @param array $args
389
+ *
390
+ * @return bool
391
+ */
392
+ public function delete_question_answer( $args = array() ) {
393
+ $question_id = isset( $_POST['question_id'] ) ? $_POST['question_id'] : false;
394
+ $answer_id = isset( $_POST['answer_id'] ) ? intval( $_POST['answer_id'] ) : false;
395
+
396
+ if ( ! ( $question_id && $answer_id ) ) {
397
+ return false;
398
+ }
399
+
400
+ $this->result = $this->question_curd->delete_answer( $question_id, $answer_id );
401
+
402
+ return true;
403
+ }
404
+
405
+ /**
406
+ * @param array $args
407
+ *
408
+ * @return bool
409
+ */
410
+ public function new_question_answer( $args = array() ) {
411
+ $question_id = ! empty( $args['question_id'] ) ? $args['question_id'] : false;
412
+
413
+ if ( ! $question_id ) {
414
+ return false;
415
+ }
416
+
417
+ // new answer
418
+ $answer = LP_Question::get_default_answer();
419
+ // add new
420
+ $new_answer_id = $this->question_curd->new_answer( $question_id, $answer );
421
+
422
+ $question = LP_Question::get_question( $question_id );
423
+
424
+ if ( $new_answer_id ) {
425
+ $this->result = array_merge( $answer, array(
426
+ 'question_answer_id' => $new_answer_id,
427
+ 'question_id' => $question_id,
428
+ 'answer_order' => count( $question->get_data( 'answer_options' ) )
429
+ ) );
430
+
431
+ return true;
432
+ }
433
+
434
+ return false;
435
+ }
436
+
437
+ /**
438
+ * @param array $args
439
+ *
440
+ * @return bool
441
+ */
442
+ public function update_question_content( $args = array() ) {
443
+ $question = ! empty( $args['question'] ) ? $args['question'] : false;
444
+ $question = json_decode( wp_unslash( $question ), true );
445
+
446
+ if ( ! $question ) {
447
+ return false;
448
+ }
449
+
450
+ wp_update_post( array(
451
+ 'ID' => $question['id'],
452
+ 'post_content' => $question['settings']['content']
453
+ ) );
454
+
455
+ $this->result['status'] = true;
456
+
457
+ return true;
458
+ }
459
+
460
+ /**
461
+ * @param array $args
462
+ *
463
+ * @return bool
464
+ */
465
+ public function update_question_meta( $args = array() ) {
466
+ $question = ! empty( $args['question'] ) ? $args['question'] : false;
467
+ $question = json_decode( wp_unslash( $question ), true );
468
+
469
+ $meta_key = ! empty( $args['meta_key'] ) ? $args['meta_key'] : false;
470
+
471
+ if ( ! ( $question && $meta_key ) ) {
472
+ return false;
473
+ }
474
+
475
+ update_post_meta( $question['id'], '_lp_' . $meta_key, $question['settings'][ $meta_key ] );
476
+
477
+ $this->result['status'] = true;
478
+
479
+ return true;
480
+ }
481
+
482
+ /**
483
+ * @param array $args
484
+ *
485
+ * @return bool
486
+ */
487
+ public function search_items( $args = array() ) {
488
+ $query = ! empty( $args['query'] ) ? $args['query'] : '';
489
+ $page = ! empty( $args['page'] ) ? intval( $args['page'] ) : 1;
490
+ $exclude = ! empty( $args['exclude'] ) ? intval( $args['exclude'] ) : '';
491
+
492
+ if ( $exclude ) {
493
+ $exclude = json_decode( $exclude, true );
494
+ }
495
+
496
+ $ids_exclude = array();
497
+ if ( is_array( $exclude ) ) {
498
+ foreach ( $exclude as $item ) {
499
+ $ids_exclude[] = $item['id'];
500
+ }
501
+ }
502
+
503
+ $search = new LP_Modal_Search_Items( array(
504
+ 'type' => 'lp_question',
505
+ 'context' => 'quiz',
506
+ 'context_id' => $this->quiz->get_id(),
507
+ 'term' => $query,
508
+ 'limit' => apply_filters( 'learn-press/quiz-editor/choose-items-limit', 10 ),
509
+ 'paged' => $page,
510
+ 'exclude' => $ids_exclude
511
+ ) );
512
+
513
+ $ids_item = $search->get_items();
514
+
515
+ $items = array();
516
+ foreach ( $ids_item as $id ) {
517
+ $post = get_post( $id );
518
+
519
+ $items[] = array(
520
+ 'id' => $post->ID,
521
+ 'title' => $post->post_title,
522
+ 'type' => $post->post_type
523
+ );
524
+ }
525
+
526
+ $this->result = array(
527
+ 'items' => $items,
528
+ 'pagination' => $search->get_pagination( false )
529
+ );
530
+
531
+ return true;
532
+ }
533
+
534
+ /**
535
+ * @param array $args
536
+ *
537
+ * @return bool
538
+ */
539
+ public function add_questions_to_quiz( $args = array() ) {
540
+ // added questions
541
+ $questions = isset( $_POST['items'] ) ? $_POST['items'] : false;
542
+ $questions = json_decode( wp_unslash( $questions ), true );
543
+
544
+ if ( ! $questions ) {
545
+ return false;
546
+ }
547
+
548
+ $quiz_id = $this->quiz->get_id();
549
+
550
+ // draft quiz
551
+ if ( get_post_status( $quiz_id ) == 'auto-draft' ) {
552
+
553
+ $draft_quiz = ! empty( $args['draft_quiz'] ) ? $args['draft_quiz'] : '';
554
+ $draft_quiz = (array) ( json_decode( wp_unslash( $draft_quiz ), '' ) );
555
+
556
+ $quiz_args = array(
557
+ 'id' => $quiz_id,
558
+ 'title' => $draft_quiz['title'],
559
+ 'content' => $draft_quiz['content'],
560
+ 'status' => 'draft'
561
+ );
562
+
563
+ $quiz_id = $this->quiz_curd->create( $quiz_args );
564
+ }
565
+
566
+ if ( ! isset( $quiz_id ) ) {
567
+ $this->result = new WP_Error( __( 'Quiz creation failed.', 'learnpress' ) );
568
+
569
+ return false;
570
+ }
571
+
572
+ if ( $questions ) {
573
+ // add question to hidden questions in quiz meta
574
+ $hidden_questions = get_post_meta( $quiz_id, '_lp_hidden_questions', true );
575
+
576
+ if ( ! $hidden_questions ) {
577
+ $hidden_questions = array();
578
+ }
579
+
580
+ foreach ( $questions as $key => $question ) {
581
+ // add question to hidden questions in quiz meta
582
+ $hidden_questions[] = $question['id'];
583
+ update_post_meta( $quiz_id, '_lp_hidden_questions', $hidden_questions );
584
+ // add question to quiz
585
+ $this->quiz_curd->add_question( $quiz_id, $question['id'] );
586
+ }
587
+ $this->result = $this->quiz->quiz_editor_get_questions();
588
+
589
+ return true;
590
+ }
591
+
592
+ return false;
593
+ }
594
+ }
inc/admin/editor/class-lp-admin-editor.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class LP_Admin_Editor
5
+ *
6
+ * @since 3.0.2
7
+ */
8
+ class LP_Admin_Editor {
9
+
10
+ /**
11
+ * @var array
12
+ */
13
+ protected static $editors = array();
14
+
15
+ /**
16
+ * @var bool
17
+ */
18
+ protected $result = false;
19
+
20
+ /**
21
+ * Get admin editor type
22
+ *
23
+ * @param string $type
24
+ *
25
+ * @return bool|mixed
26
+ */
27
+ public static function get( $type ) {
28
+
29
+ if ( empty( self::$editors[ $type ] ) ) {
30
+ $suffix = preg_replace( '~\s+~', '_', ucfirst( str_replace( '-', ' ', $type ) ) );
31
+ $class = "LP_Admin_Editor_{$suffix}";
32
+
33
+ if ( ! class_exists( $class ) ) {
34
+ $file = "class-lp-admin-editor-{$type}.php";
35
+ include_once $file;
36
+ }
37
+
38
+ if ( class_exists( $class ) ) {
39
+ self::$editors[ $type ] = new $class();
40
+ }
41
+ }
42
+
43
+ return ! empty( self::$editors[ $type ] ) ? self::$editors[ $type ] : false;
44
+ }
45
+
46
+ public function call( $type, $args = array() ) {
47
+ $func = str_replace( '-', '_', $type );
48
+ $callback = array( $this, $func );
49
+ if ( is_callable( $callback ) ) {
50
+ return call_user_func_array( $callback, $args );
51
+ }
52
+
53
+ return false;
54
+ }
55
+
56
+ public function heartbeat( $args = array() ) {
57
+ $this->result = true;
58
+ }
59
+
60
+ /**
61
+ * @return mixed|WP_Error
62
+ */
63
+ public function get_result() {
64
+ return $this->result;
65
+ }
66
+
67
+ /**
68
+ * @return bool|WP_Error
69
+ */
70
+ public function dispatch() {
71
+ return false;
72
+ }
73
+
74
+ /**
75
+ * @return LP_Admin_Editor_Course
76
+ */
77
+ public static function get_editor_course() {
78
+ return self::get( 'course' );
79
+ }
80
+
81
+ /**
82
+ * @return LP_Admin_Editor_Quiz
83
+ */
84
+ public static function get_editor_quiz() {
85
+ return self::get( 'quiz' );
86
+ }
87
+
88
+ /**
89
+ * @return LP_Admin_Editor_Question
90
+ */
91
+ public static function get_editor_question() {
92
+ return self::get( 'question' );
93
+ }
94
+ }
inc/course/abstract-course.php CHANGED
@@ -469,7 +469,9 @@ if ( ! function_exists( 'LP_Abstract_Course' ) ) {
469
  * @return int
470
  */
471
  public function get_fake_students() {
472
- return $this->get_data( 'fake_students' );
 
 
473
  }
474
 
475
  /**
@@ -845,7 +847,11 @@ if ( ! function_exists( 'LP_Abstract_Course' ) ) {
845
  }
846
 
847
  /**
848
- * @return mixed
 
 
 
 
849
  */
850
  public function count_students() {
851
  $count_in_order = $this->count_in_order( array( 'completed', 'processing' ) );
@@ -853,7 +859,7 @@ if ( ! function_exists( 'LP_Abstract_Course' ) ) {
853
  $append_students = LP()->settings()->get( 'enrolled_students_number' );// get_post_meta( $this->get_id(), '_lp_append_students', true );
854
 
855
  if ( ( 'yes' == $append_students ) || ! in_array( $append_students, array( 'yes', 'no' ) ) ) {
856
- $count_in_order += intval($this->get_fake_students());
857
  }
858
 
859
  return $count_in_order;
@@ -918,12 +924,12 @@ if ( ! function_exists( 'LP_Abstract_Course' ) ) {
918
  * @return array|mixed|string
919
  */
920
  public function get_passing_condition( $format = false, $context = '' ) {
921
- $value = $this->get_data( 'passing_condition' );
922
  if ( $format ) {
923
  $value = "{$value}%";
924
  }
925
 
926
- return 'edit' === $context ? $value : apply_filters( 'learn-press/course-passing-condition', $value, $this->get_id() );
927
  }
928
 
929
  /**
@@ -1651,7 +1657,7 @@ if ( ! function_exists( 'LP_Abstract_Course' ) ) {
1651
  $duration = $this->get_duration();
1652
  $user = learn_press_get_user( $user_id );
1653
  $course_info = $user->get_course_info( $this->get_id() );
1654
- $start_time = array_key_exists( 'start_time', $args ) ? $args['start_time'] : ( is_array($course_info) && array_key_exists('start', $course_info) ? intval( strtotime( $course_info['start'] ) ) : 0 );
1655
  if ( $duration == 0 ) {
1656
  $duration = DAY_IN_SECONDS * 365 * 100;
1657
  }
469
  * @return int
470
  */
471
  public function get_fake_students() {
472
+ $count = $this->get_data( 'fake_students' );
473
+
474
+ return is_numeric( $count ) ? absint( $count ) : 0;
475
  }
476
 
477
  /**
847
  }
848
 
849
  /**
850
+ * Count number of students enrolled course.
851
+ * Check global settings `enrolled_students_number`
852
+ * and add the fake value if both are set.
853
+ *
854
+ * @return int
855
  */
856
  public function count_students() {
857
  $count_in_order = $this->count_in_order( array( 'completed', 'processing' ) );
859
  $append_students = LP()->settings()->get( 'enrolled_students_number' );// get_post_meta( $this->get_id(), '_lp_append_students', true );
860
 
861
  if ( ( 'yes' == $append_students ) || ! in_array( $append_students, array( 'yes', 'no' ) ) ) {
862
+ $count_in_order += $this->get_fake_students();
863
  }
864
 
865
  return $count_in_order;
924
  * @return array|mixed|string
925
  */
926
  public function get_passing_condition( $format = false, $context = '' ) {
927
+ $value = absint( $this->get_data( 'passing_condition' ) );
928
  if ( $format ) {
929
  $value = "{$value}%";
930
  }
931
 
932
+ return 'edit' === $context ? $value : apply_filters( 'learn-press/course-passing-condition', $value, $format, $this->get_id() );
933
  }
934
 
935
  /**
1657
  $duration = $this->get_duration();
1658
  $user = learn_press_get_user( $user_id );
1659
  $course_info = $user->get_course_info( $this->get_id() );
1660
+ $start_time = array_key_exists( 'start_time', $args ) ? $args['start_time'] : ( is_array( $course_info ) && array_key_exists( 'start', $course_info ) ? intval( strtotime( $course_info['start'] ) ) : 0 );
1661
  if ( $duration == 0 ) {
1662
  $duration = DAY_IN_SECONDS * 365 * 100;
1663
  }
inc/course/lp-course-functions.php CHANGED
@@ -961,16 +961,20 @@ function learn_press_get_course_results_tooltip( $course_id ) {
961
  return $tooltip;
962
  }
963
 
964
- function learn_press_course_passing_condition( $value, $course_id ) {
965
  if ( $quiz_id = learn_press_get_final_quiz( $course_id ) ) {
966
  $quiz = learn_press_get_quiz( $quiz_id );
967
  $value = absint( $quiz->get_passing_grade() );
 
 
 
 
968
  }
969
 
970
  return $value;
971
  }
972
 
973
- add_filter( 'learn-press/course-passing-condition', 'learn_press_course_passing_condition', 10, 2 );
974
 
975
  /**
976
  * Cache static pages
961
  return $tooltip;
962
  }
963
 
964
+ function learn_press_course_passing_condition( $value, $format, $course_id ) {
965
  if ( $quiz_id = learn_press_get_final_quiz( $course_id ) ) {
966
  $quiz = learn_press_get_quiz( $quiz_id );
967
  $value = absint( $quiz->get_passing_grade() );
968
+
969
+ if($format){
970
+ $value = "{$value}%";
971
+ }
972
  }
973
 
974
  return $value;
975
  }
976
 
977
+ add_filter( 'learn-press/course-passing-condition', 'learn_press_course_passing_condition', 10, 3 );
978
 
979
  /**
980
  * Cache static pages
inc/curds/class-lp-course-curd.php CHANGED
@@ -700,7 +700,6 @@ if ( ! class_exists( 'LP_Course_CURD' ) ) {
700
  */
701
  public function count_by_orders( $course_id, $statuses = 'completed' ) {
702
  global $wpdb;
703
- LP_Debug::log_function( __CLASS__ . '::' . __FUNCTION__ );
704
 
705
  settype( $statuses, 'array' );
706
  foreach ( $statuses as $k => $v ) {
@@ -730,7 +729,6 @@ if ( ! class_exists( 'LP_Course_CURD' ) ) {
730
 
731
  wp_cache_set( 'course-' . $course_id . '-' . $cache_key, $count, 'lp-course-orders' );
732
  }
733
- LP_Debug::log_function( __CLASS__ . '::' . __FUNCTION__ );
734
 
735
  return $count;
736
  }
700
  */
701
  public function count_by_orders( $course_id, $statuses = 'completed' ) {
702
  global $wpdb;
 
703
 
704
  settype( $statuses, 'array' );
705
  foreach ( $statuses as $k => $v ) {
729
 
730
  wp_cache_set( 'course-' . $course_id . '-' . $cache_key, $count, 'lp-course-orders' );
731
  }
 
732
 
733
  return $count;
734
  }
inc/curds/class-lp-question-curd.php CHANGED
@@ -201,7 +201,7 @@ if ( ! class_exists( 'LP_Question_CURD' ) ) {
201
  /**
202
  * Duplicate answer question.
203
  *
204
- * @param $question_id | origin question
205
  * @param $new_question_id | new question
206
  */
207
  public function duplicate_answer( $question_id, $new_question_id ) {
@@ -615,7 +615,13 @@ if ( ! class_exists( 'LP_Question_CURD' ) ) {
615
  $new_answer['question_answer_id'] = $wpdb->insert_id;
616
  $new_answer['question_id'] = $question_id;
617
  $new_answer['answer_order'] = $number + 1;
618
- $question->set_data( 'answer_options', array_merge( $answers, array( $new_answer ) ) );
 
 
 
 
 
 
619
  }
620
 
621
  return $wpdb->insert_id;
@@ -748,7 +754,7 @@ if ( ! class_exists( 'LP_Question_CURD' ) ) {
748
  * @since 3.0.0
749
  *
750
  * @param string $question_type
751
- * @param array $args
752
  *
753
  * @return array|bool
754
  */
201
  /**
202
  * Duplicate answer question.
203
  *
204
+ * @param $question_id | origin question
205
  * @param $new_question_id | new question
206
  */
207
  public function duplicate_answer( $question_id, $new_question_id ) {
615
  $new_answer['question_answer_id'] = $wpdb->insert_id;
616
  $new_answer['question_id'] = $question_id;
617
  $new_answer['answer_order'] = $number + 1;
618
+
619
+ if ( is_array( $answers ) ) {
620
+ $answers = array_merge( $answers, array( $new_answer ) );
621
+ } else {
622
+ $answers = array( $new_answer );
623
+ }
624
+ $question->set_data( 'answer_options', $answers );
625
  }
626
 
627
  return $wpdb->insert_id;
754
  * @since 3.0.0
755
  *
756
  * @param string $question_type
757
+ * @param array $args
758
  *
759
  * @return array|bool
760
  */
inc/curds/class-lp-section-curd.php CHANGED
@@ -65,11 +65,11 @@ class LP_Section_CURD extends LP_Object_Data_CURD implements LP_Interface_CURD {
65
  *
66
  * @since 3.0.0
67
  *
68
- * @param $args array
69
  *
70
  * @return mixed
71
  */
72
- public function update( &$args = array() ) {
73
 
74
  $section = $this->parse( $args );
75
 
@@ -323,7 +323,7 @@ class LP_Section_CURD extends LP_Object_Data_CURD implements LP_Interface_CURD {
323
  } else {
324
  $item['id'] = apply_filters( 'learn-press/new-section-item', $item, $args );
325
  }
326
-
327
  if ( is_wp_error( $item['id'] ) || ! $item['id'] ) {
328
  return false;
329
  }
65
  *
66
  * @since 3.0.0
67
  *
68
+ * @param $args
69
  *
70
  * @return mixed
71
  */
72
+ public function update( &$args ) {
73
 
74
  $section = $this->parse( $args );
75
 
323
  } else {
324
  $item['id'] = apply_filters( 'learn-press/new-section-item', $item, $args );
325
  }
326
+
327
  if ( is_wp_error( $item['id'] ) || ! $item['id'] ) {
328
  return false;
329
  }
inc/lp-constants.php CHANGED
@@ -4,7 +4,7 @@
4
  */
5
  $upload_dir = wp_upload_dir();
6
  // version
7
- define( 'LEARNPRESS_VERSION', '3.0.0' );
8
 
9
  define( 'LP_WP_CONTENT', basename( WP_CONTENT_DIR ) );
10
 
4
  */
5
  $upload_dir = wp_upload_dir();
6
  // version
7
+ define( 'LEARNPRESS_VERSION', '3.0.2' );
8
 
9
  define( 'LP_WP_CONTENT', basename( WP_CONTENT_DIR ) );
10
 
inc/lp-core-functions.php CHANGED
@@ -1694,17 +1694,62 @@ if ( ! function_exists( 'learn_press_send_json' ) ) {
1694
  /**
1695
  * Convert an object|array to json format and send it to the browser.
1696
  *
1697
- * @param $data
1698
  */
1699
  function learn_press_send_json( $data ) {
1700
  echo '<-- LP_AJAX_START -->';
1701
- @header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
1702
  echo wp_json_encode( $data );
1703
  echo '<-- LP_AJAX_END -->';
1704
  die;
1705
  }
1706
  }
1707
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1708
  /**
1709
  * Check if ajax is calling then send json data.
1710
  *
1694
  /**
1695
  * Convert an object|array to json format and send it to the browser.
1696
  *
1697
+ * @param object|array $data
1698
  */
1699
  function learn_press_send_json( $data ) {
1700
  echo '<-- LP_AJAX_START -->';
1701
+ //@header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
1702
  echo wp_json_encode( $data );
1703
  echo '<-- LP_AJAX_END -->';
1704
  die;
1705
  }
1706
  }
1707
 
1708
+ /**
1709
+ * Send json with success signal to browser.
1710
+ *
1711
+ * @since 3.0.1
1712
+ *
1713
+ * @param array|object|WP_Error $data
1714
+ */
1715
+ function learn_press_send_json_error( $data = '' ) {
1716
+ $response = array( 'success' => false );
1717
+
1718
+ if ( isset( $data ) ) {
1719
+ if ( is_wp_error( $data ) ) {
1720
+ $result = array();
1721
+ foreach ( $data->errors as $code => $messages ) {
1722
+ foreach ( $messages as $message ) {
1723
+ $result[] = array( 'code' => $code, 'message' => $message );
1724
+ }
1725
+ }
1726
+
1727
+ $response['data'] = $result;
1728
+ } else {
1729
+ $response['data'] = $data;
1730
+ }
1731
+ }
1732
+
1733
+ learn_press_send_json( $response );
1734
+ }
1735
+
1736
+ /**
1737
+ * Send json with error signal to browser.
1738
+ *
1739
+ * @since 3.0.0
1740
+ *
1741
+ * @param array|object|WP_Error $data
1742
+ */
1743
+ function learn_press_send_json_success( $data = '' ) {
1744
+ $response = array( 'success' => true );
1745
+
1746
+ if ( isset( $data ) ) {
1747
+ $response['data'] = $data;
1748
+ }
1749
+
1750
+ learn_press_send_json( $response );
1751
+ }
1752
+
1753
  /**
1754
  * Check if ajax is calling then send json data.
1755
  *
inc/user-item/class-lp-user-item.php CHANGED
@@ -351,12 +351,13 @@ class LP_User_Item extends LP_Abstract_Object_Data {
351
 
352
  public function get_status_label( $status = '' ) {
353
  $statuses = array(
354
- 'enrolled' => __( 'In Progress', 'learnpress' ),
355
- 'started' => __( 'In Progress', 'learnpress' ),
356
- 'completed' => __( 'Completed', 'learnpress' ),
357
- 'finished' => __( 'Finished', 'learnpress' ),
358
- 'passed' => __( 'Passed', 'learnpress' ),
359
- 'failed' => __( 'Failed', 'learnpress' )
 
360
  );
361
 
362
  if ( ! $status ) {
351
 
352
  public function get_status_label( $status = '' ) {
353
  $statuses = array(
354
+ 'enrolled' => __( 'In Progress', 'learnpress' ),
355
+ 'started' => __( 'In Progress', 'learnpress' ),
356
+ 'in-progress' => __( 'In Progress', 'learnpress' ),
357
+ 'completed' => __( 'Completed', 'learnpress' ),
358
+ 'finished' => __( 'Finished', 'learnpress' ),
359
+ 'passed' => __( 'Passed', 'learnpress' ),
360
+ 'failed' => __( 'Failed', 'learnpress' )
361
  );
362
 
363
  if ( ! $status ) {
learnpress.php CHANGED
@@ -4,10 +4,10 @@ Plugin Name: LearnPress
4
  Plugin URI: http://thimpress.com/learnpress
5
  Description: LearnPress is a WordPress complete solution for creating a Learning Management System (LMS). It can help you to create courses, lessons and quizzes.
6
  Author: ThimPress
7
- Version: 3.0.1
8
  Author URI: http://thimpress.com
9
  Requires at least: 3.8
10
- Tested up to: 4.7
11
 
12
  Text Domain: learnpress
13
  Domain Path: /languages/
4
  Plugin URI: http://thimpress.com/learnpress
5
  Description: LearnPress is a WordPress complete solution for creating a Learning Management System (LMS). It can help you to create courses, lessons and quizzes.
6
  Author: ThimPress
7
+ Version: 3.0.2
8
  Author URI: http://thimpress.com
9
  Requires at least: 3.8
10
+ Tested up to: 4.9.4
11
 
12
  Text Domain: learnpress
13
  Domain Path: /languages/
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link:
4
  Tags: WordPress LMS, LMS, eLearning, e-Learning, Learning Management System, LMS WordPress, Course, Courses, Quiz, Quizzes, Training, Guru, Sell Courses
5
  Requires at least: 3.8
6
  Tested up to: 4.9.4
7
- Stable tag: 3.0.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -198,6 +198,14 @@ https://www.transifex.com/projects/p/learnpress/
198
  8. Add-ons of LearnPress.
199
 
200
  == Changelog ==
 
 
 
 
 
 
 
 
201
  = 3.0.1 =
202
  ~ Improved 'External link' button if user has enrolled course
203
  ~ Fixed category does not display courses (SO)
4
  Tags: WordPress LMS, LMS, eLearning, e-Learning, Learning Management System, LMS WordPress, Course, Courses, Quiz, Quizzes, Training, Guru, Sell Courses
5
  Requires at least: 3.8
6
  Tested up to: 4.9.4
7
+ Stable tag: 3.0.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
198
  8. Add-ons of LearnPress.
199
 
200
  == Changelog ==
201
+ = 3.0.2 =
202
+ ~ Fixed PHP non-numeric cast type
203
+ ~ Improved admin ajax for course/quiz/question editor
204
+ ~ Fixed error when extending method from parent
205
+ ~ Fixed invalid course progress label
206
+ ~ Fixed invalid filter to course passing grade
207
+ ~ Fixed empty course item class for other post types
208
+
209
  = 3.0.1 =
210
  ~ Improved 'External link' button if user has enrolled course
211
  ~ Fixed category does not display courses (SO)