PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.1
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.1
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 4.2.1 All 138 releases
learnpress / inc / custom-post-types / abstract.php

abstract.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.1, at inc/custom-post-types/abstract.php

1,151 lines 28.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class LP_Abstract_Post_Type
5 *
6 * @author ThimPress
7 * @package LearnPress/Classes
8 * @version 1.0
9 */
10
11 use LearnPress\Models\CourseModel;
12 use LearnPress\Models\UserModel;
13 use LearnPress\TemplateHooks\UserTemplate;
14
15 defined( 'ABSPATH' ) || exit();
16
17 abstract class LP_Abstract_Post_Type {
18 /**
19 * Type of post
20 *
21 * @var string
22 */
23 protected $_post_type = '';
24
25 /**
26 * Screen list post type
27 * Ex: edit-{post_type}
28 *
29 * @var string
30 */
31 protected $_screen_list = '';
32
33 /**
34 * Metaboxes registered
35 *
36 * @var array
37 */
38 protected $_meta_boxes = array();
39
40 /**
41 * @var null
42 */
43 protected $_current_meta_box = null;
44
45 /**
46 * Columns display on list table
47 *
48 * @var array
49 */
50 protected $_columns = array();
51
52 /**
53 * Sortable columns
54 *
55 * @var array
56 */
57 protected $_sortable_columns = array();
58
59 /**
60 * Map default method to a new method
61 *
62 * @var array
63 */
64 // protected $_map_methods = array();
65
66 /**
67 * @var array
68 */
69 protected $_default_metas = array();
70
71 /**
72 * @var array
73 */
74 protected $_remove_features = array();
75
76 /**
77 * Constructor
78 *
79 * @param string
80 * @param mixed
81 */
82 public function __construct( $post_type = '', $args = '' ) {
83
84 if ( ! empty( $post_type ) ) {
85 $this->_post_type = $post_type;
86 }
87
88 $this->_do_register();
89
90 add_filter( 'wp_list_table_class_name', [ $this, 'wp_list_table_class_name' ], 10, 2 );
91 add_action( 'save_post', array( $this, '_do_save_post' ), - 1, 3 );
92 add_action( 'wp_after_insert_post', [ $this, 'wp_after_insert_post' ], - 1, 3 );
93 add_action( 'before_delete_post', array( $this, '_before_delete_post' ) );
94 add_action( 'deleted_post', array( $this, '_deleted_post' ) );
95 add_action( 'wp_trash_post', array( $this, '_before_trash_post' ) );
96 add_action( 'trashed_post', array( $this, '_trashed_post' ) );
97
98 //add_filter( 'manage_posts_columns', array( $this, '_manage_columns_head_title' ), 11, 2 );
99 //add_action( 'manage_posts_custom_column', array( $this, '_manage_column_value' ), 11, 2 );
100 add_filter( 'manage_edit-' . $this->_post_type . '_sortable_columns', array( $this, 'sortable_columns' ) );
101 add_filter( 'manage_' . $this->_post_type . '_posts_columns', array( $this, 'columns_head' ) );
102 add_filter( 'manage_' . $this->_post_type . '_posts_custom_column', array( $this, 'columns_content' ), 10, 2 );
103
104 add_filter( 'posts_fields', array( $this, '_posts_fields' ) );
105 add_filter( 'posts_join_paged', array( $this, '_posts_join_paged' ) );
106 add_filter( 'posts_where_paged', array( $this, '_posts_where_paged' ) );
107 add_filter( 'posts_orderby', array( $this, '_posts_orderby' ) );
108
109 // Show actions link on list post admin.
110 add_filter( 'post_row_actions', array( $this, '_post_row_actions' ), 10, 2 );
111
112 // New metabox: Nhamdv
113 add_action( 'add_meta_boxes', array( $this, 'render_meta_box' ), 0 );
114
115 // After update h5p and withdraw will remove it.
116 add_action( 'load-post.php', array( $this, 'add_meta_boxes' ), 0 );
117 add_action( 'load-post-new.php', array( $this, 'add_meta_boxes' ), 0 );
118 // End
119
120 // Comment by tungnx
121 // add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
122 // add_action( 'admin_enqueue_scripts', array( $this, 'admin_styles' ) );
123
124 // Comment by tungnx
125 // add_action( 'admin_footer-post.php', array( $this, 'print_js_template' ) );
126 // add_action( 'admin_footer-post-new.php', array( $this, 'print_js_template' ) );
127
128 // Comment by tungnx - not use
129 // add_action( 'pre_get_posts', array( $this, 'update_default_meta' ) );
130 add_action( 'admin_footer', array( $this, 'admin_footer_scripts' ) );
131
132 //add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
133 add_action( 'admin_print_scripts', array( $this, 'remove_auto_save_script' ) );
134
135 // Remove wp-auth-check and heartbeat script on post type of LearnPress
136 add_action(
137 'admin_enqueue_scripts',
138 function ( $page ) {
139 if ( $page !== 'post.php' && $page !== 'post-new.php' ) {
140 return;
141 }
142
143 if ( get_post_type() !== $this->_post_type ) {
144 return;
145 }
146
147 wp_deregister_script( 'wp-auth-check' );
148 wp_deregister_script( 'heartbeat' );
149 },
150 1
151 );
152 }
153
154 /**
155 * This function is invoked along with 'init' action to register
156 * new post type with WP.
157 *
158 * @editor tungnx
159 * @since modify 4.1.0
160 */
161 public function _do_register() {
162 $args = $this->args_register_post_type();
163
164 /*
165 * Todo: This is function old, still has on some addons, so need replace "register" function to args_register_post_type
166 * When replace all will delete this function - long ago will delete, for some user didn't updated new addon version fix
167 */
168 if ( method_exists( $this, 'register' ) ) {
169 $args = $this->register();
170 }
171
172 if ( $args ) {
173 register_post_type( $this->_post_type, $args );
174
175 // Todo: tungnx review this code.
176 //flush_rewrite_rules();
177 }
178 }
179
180 /**
181 * Args to register custom post type.
182 *
183 * @return array
184 */
185 public function args_register_post_type(): array {
186 return array();
187 }
188
189 /**
190 * Check screen list post type
191 *
192 * @param WP_Screen|null $screen
193 *
194 * @return bool
195 */
196 public function check_class_name_handle_table( $screen ): bool {
197 if ( $screen instanceof WP_Screen
198 && $screen->id === $this->_screen_list ) {
199 return true;
200 }
201
202 return false;
203 }
204
205 /**
206 * Declare class name of table
207 *
208 * @param $class_name
209 * @param $args
210 *
211 * @return mixed
212 */
213 public function wp_list_table_class_name( $class_name, $args ) {
214 return $class_name;
215 }
216
217 /**
218 * Hook save post of WP
219 *
220 * In child-class use function save()
221 *
222 * @param int $post_id
223 * @param WP_Post|null|mixed $post
224 * @param bool $is_update
225 *
226 * @editor tungnx
227 * @since modify 4.0.9
228 * @version 4.0.3
229 */
230 final public function _do_save_post( int $post_id = 0, ?WP_Post $post = null, bool $is_update = false ) {
231 // Maybe remove
232 $this->maybe_remove_assigned( $post );
233
234 if ( ! $this->check_post( $post_id ) ) {
235 return;
236 }
237
238 $this->save( $post_id, $post );
239 $this->save_post( $post_id, $post, $is_update );
240 }
241
242 /**
243 * Function for child class handle when post has just saved
244 *
245 * @editor tungnx
246 * @docs Class post type extend need override this function if want to handle when save
247 */
248 public function save( int $post_id, WP_Post $post ) {
249 // Implement from child
250 }
251
252 /**
253 * Function for child class handle when post has just saved
254 * This function provides the argument `$update` to determine whether a post is updated or new.
255 * Replace for function save only has two args
256 *
257 * @param int $post_id
258 * @param WP_Post|null $post
259 * @param bool $is_update
260 *
261 * @since 4.2.6.9
262 * @version 1.0.1
263 */
264 public function save_post( int $post_id, ?WP_Post $post = null, bool $is_update = false ) {
265 // Implement from child
266 }
267
268 /**
269 * Callback hook 'wp_after_insert_post'
270 *
271 * @param $post_id
272 * @param $post
273 * @param $update
274 *
275 * @return void
276 * @since 4.2.6.9
277 * @version 1.0.1
278 */
279 final public function wp_after_insert_post( $post_id, $post, $update ) {
280 if ( ! $this->check_post( $post_id ) ) {
281 return;
282 }
283
284 $this->after_insert_post( $post_id, $post, $update );
285 }
286
287 /**
288 * Function for child class handle when post has just saved
289 *
290 * @param int $post_id
291 * @param WP_Post|null $post
292 * @param bool $update
293 */
294 public function after_insert_post( int $post_id, ?WP_Post $post = null, bool $update = false ) {
295 // Implement from child
296 }
297
298 /**
299 * Hook before delete post
300 * Only on receiver 1 param $post_id, can't get param $post - don't know why
301 *
302 * @param int $post_id
303 * @param WP_Post|null $post
304 *
305 * @editor tungnx
306 * @since modify 4.0.9
307 */
308 final public function _before_delete_post( int $post_id, ?WP_Post $post = null ) {
309 try {
310 // Todo: check is pages of LP
311 if ( 'page' === get_post_type( $post_id ) ) {
312 // Clear cache LP settings
313 $lp_settings_cache = new LP_Settings_Cache( true );
314 $lp_settings_cache->clean_lp_settings();
315 }
316
317 if ( ! $this->check_post( $post_id ) ) {
318 return;
319 }
320
321 $this->before_delete( $post_id );
322 } catch ( Throwable $e ) {
323 error_log( __METHOD__ . ': ' . $e->getMessage() );
324 }
325 }
326
327 /**
328 * Function for child class handle before post deleted
329 *
330 * @param int $post_id
331 *
332 * @editor tungnx
333 * @since modify 4.0.9
334 */
335 public function before_delete( int $post_id ) {
336 // Implement from child
337 }
338
339 /**
340 * Hook deleted post
341 *
342 * @param int $post_id
343 */
344 final public function _deleted_post( int $post_id ) {
345 $this->deleted_post( $post_id );
346 }
347
348 /**
349 * Function for child class handle when post has just deleted
350 *
351 * @editor tungnx
352 * @docs Class post type extend need override this function if want to handle when post deleted
353 */
354 public function deleted_post( int $post_id ) {
355 // Implement from child
356 }
357
358 protected $course_of_item_trashed = 0;
359
360 /**
361 * Hook before delete post
362 *
363 * @param int $post_id
364 *
365 * @author tungnx
366 * @since 4.1.6.9
367 * @version 1.0.1
368 */
369 final public function _before_trash_post( int $post_id ) {
370 if ( ! $this->check_post( $post_id ) ) {
371 return;
372 }
373
374 $this->before_trash_post( $post_id );
375 }
376
377 /**
378 * Before trash post
379 *
380 * @param int $post_id
381 *
382 * @return void
383 * @author tungnx
384 * @since 4.1.6.9
385 * @version 1.0.1
386 */
387 public function before_trash_post( int $post_id ) {
388 try {
389 // Case move item's course to trash
390 $course_item_types = CourseModel::item_types_support();
391 if ( ! in_array( get_post_type( $post_id ), $course_item_types ) ) {
392 return;
393 }
394
395 // Set course id of item when item assign on course is trashed
396 $course_of_item = LP_Course_DB::getInstance()->get_course_by_item_id( $post_id );
397 if ( $course_of_item ) {
398 $this->course_of_item_trashed = $course_of_item;
399 }
400 } catch ( Throwable $e ) {
401 error_log( $e->getMessage() );
402 }
403 }
404
405 /**
406 * Hook Trashed post
407 *
408 * @param int $post_id
409 *
410 * @return void
411 * @author tungnx
412 * @since 4.1.6.9
413 * @version 1.0.1
414 */
415 final public function _trashed_post( int $post_id ) {
416 if ( ! $this->check_post( $post_id ) ) {
417 return;
418 }
419
420 $this->trashed_post( $post_id );
421 }
422
423 /**
424 * Method handle Trashed post
425 *
426 * @param int $post_id
427 *
428 * @return void
429 * @since 4.1.6.9
430 * @version 1.0.0
431 * @author tungnx
432 */
433 public function trashed_post( int $post_id ) {
434 // Implement from child
435 // Check is item type of course
436 $course_item_types = learn_press_get_course_item_types();
437 if ( ! in_array( get_post_type( $post_id ), $course_item_types ) ) {
438 return;
439 }
440
441 if ( $this->course_of_item_trashed ) {
442 // Save course when item assign on course is trashed
443 $course_id = $this->course_of_item_trashed;
444 LP_Course_Post_Type::instance()->save_post( $course_id, null, true );
445 $this->course_of_item_trashed = 0;
446 }
447 }
448
449 public function column_instructor( $post_id = 0 ) {
450 $post = get_post( $post_id );
451 $user_id = $post->post_author;
452
453 $user = UserModel::find( $user_id, true );
454 if ( ! $user ) {
455 return;
456 }
457
458 $args = array(
459 'post_type' => $post->post_type,
460 'author' => $user_id,
461 );
462
463 $author_link = esc_url_raw( add_query_arg( $args, 'edit.php' ) );
464 $userTemplate = new UserTemplate();
465 echo sprintf(
466 '<span class="post-author">%s<a href="%s">%s</a></span>',
467 $userTemplate->html_avatar(
468 $user,
469 [
470 'width' => 32,
471 'height' => 32,
472 ]
473 ),
474 $author_link,
475 get_the_author()
476 );
477 }
478
479 /**
480 * Get column author
481 *
482 * @param $post
483 *
484 * @return void
485 * @since 4.2.9.5
486 * @version 1.0.0
487 */
488 public static function column_author( $post ) {
489 if ( ! $post instanceof WP_Post ) {
490 return;
491 }
492
493 $user_id = $post->post_author;
494 $userModel = UserModel::find( $user_id, true );
495 if ( ! $userModel ) {
496 return;
497 }
498
499 $args = array(
500 'post_type' => $post->post_type,
501 'author' => $user_id,
502 );
503
504 $author_link = esc_url_raw( add_query_arg( $args, 'edit.php' ) );
505 $userTemplate = new UserTemplate();
506 echo sprintf(
507 '<span class="post-author">%s<a href="%s">%s</a></span>',
508 $userTemplate->html_avatar(
509 $userModel,
510 [
511 'width' => 32,
512 'height' => 32,
513 ]
514 ),
515 $author_link,
516 $userModel->get_display_name()
517 );
518 }
519
520 public function get_post_type() {
521 $post_type = get_post_type();
522 if ( ! $post_type ) {
523 $post_type = LP_Request::get_string( 'post_type' );
524 }
525
526 return $post_type;
527 }
528
529 public function admin_footer_scripts() {
530
531 global $pagenow;
532
533 if ( $this->get_post_type() !== $this->_post_type ) {
534 return;
535 }
536
537 $user = learn_press_get_current_user();
538
539 if ( ! $user->is_admin() ) {
540 return;
541 }
542
543 // Comment by tungnx - not use on here, wrote on js
544 /*
545 if ( $pagenow === 'edit.php' ) {
546 $option = sprintf( '<option value="">%s</option>', __( 'Search by user', 'learnpress' ) );
547 $user = get_user_by( 'id', LP_Request::get_int( 'author' ) );
548
549 if ( $user ) {
550 $option = sprintf( '<option value="%d" selected="selected">%s</option>', $user->ID, $user->user_login );
551 }
552 }*/
553
554 // Todo: write this code on file js
555 if ( $pagenow === 'post.php' ) {
556 ?>
557 <script>
558 jQuery(function ($) {
559 var isAssigned = '<?php echo esc_js( $this->is_assigned() ); ?>',
560 $postStatus = $('#post_status'),
561 $message = $('<p class="learn-press-notice-assigned-item"></p>').html(isAssigned),
562 currentStatus = $postStatus.val();
563
564 (currentStatus === 'publish') && isAssigned && $postStatus.on('change', function () {
565 if (this.value !== 'publish') {
566 $message.insertBefore($('#post-status-select'));
567 } else {
568 $message.remove();
569 }
570 });
571
572 })
573 </script>
574 <?php
575 }
576 }
577
578 public function is_assigned() {
579 global $wpdb;
580 $post_type = $this->get_post_type();
581 if ( learn_press_is_support_course_item_type( $post_type ) ) {
582 $query = $wpdb->prepare(
583 "
584 SELECT s.section_course_id
585 FROM {$wpdb->learnpress_section_items} si
586 INNER JOIN {$wpdb->learnpress_sections} s ON s.section_id = si.section_id
587 INNER JOIN {$wpdb->posts} p ON p.ID = si.item_id
588 WHERE p.ID = %d
589 ",
590 get_the_ID()
591 );
592
593 $course_id = $wpdb->get_var( $query );
594 if ( $course_id ) {
595 return __( 'This item has already been assigned to the course. It will be removed from the course if it is not published.', 'learnpress' );
596 }
597 } elseif ( LP_QUESTION_CPT === $post_type ) {
598 $query = $wpdb->prepare(
599 "
600 SELECT p.ID
601 FROM {$wpdb->posts} p
602 INNER JOIN {$wpdb->learnpress_quiz_questions} qq ON p.ID = qq.quiz_id
603 WHERE qq.question_id = %d
604 ",
605 get_the_ID()
606 );
607
608 $quiz_id = $wpdb->get_var( $query );
609 if ( $quiz_id ) {
610 return __( 'This question has already been assigned to the quiz. It will be removed from the quiz if it is not published.', 'learnpress' );
611 }
612 }
613
614 return 0;
615 }
616
617 public function remove_auto_save_script() {
618 global $post;
619 if ( ! $post ) {
620 return;
621 }
622
623 if ( $this->check_post( $post->ID ) ) {
624 wp_dequeue_script( 'autosave' );
625 }
626 }
627
628 /**
629 * Maybe remove assigned item
630 *
631 * @param WP_Post $post
632 *
633 * @editor tungnx
634 * @todo Review and move to place correct
635 */
636 public function maybe_remove_assigned( $post = null ) {
637 global $wpdb;
638
639 if ( ! $post ) {
640 return;
641 }
642
643 $post_type = $post->post_type;
644 $post_status = $post->post_status;
645
646 // If we are updating question
647 if ( LP_QUESTION_CPT === $post_type ) {
648
649 // If question is not published then delete it from quizzes
650 if ( $post_status !== 'publish' ) {
651 $query = $wpdb->prepare(
652 "
653 DELETE FROM {$wpdb->learnpress_quiz_questions}
654 WHERE question_id = %d
655 ",
656 $post->ID
657 );
658 $wpdb->query( $query );
659 }
660 } elseif ( learn_press_is_support_course_item_type( $post_type ) ) {
661
662 // If item is not published then delete it from courses
663 if ( $post_status !== 'publish' ) {
664 $query = $wpdb->prepare(
665 "
666 DELETE FROM {$wpdb->learnpress_section_items}
667 WHERE item_id = %d
668 ",
669 $post->ID
670 );
671 $wpdb->query( $query );
672 }
673 }
674 }
675
676 /**
677 * @deprecated v4.2.9.4
678 */
679 protected function _get_quizzes_by_question( $question_id ) {
680 _deprecated_function( __METHOD__, '4.2.9.4' );
681 return [];
682
683 global $wpdb;
684 $query = $wpdb->prepare(
685 "
686 SELECT quiz_id
687 FROM {$wpdb->learnpress_quiz_questions}
688 WHERE question_id = %d
689 ",
690 $question_id
691 );
692
693 return $wpdb->get_col( $query );
694 }
695
696 /**
697 * @deprecated v4.2.9.4
698 */
699 protected function _get_courses_by_item( $item_id ) {
700 _deprecated_function( __METHOD__, '4.2.9.4' );
701 return [];
702
703 global $wpdb;
704 $query = $wpdb->prepare(
705 "
706 SELECT section_course_id
707 FROM {$wpdb->learnpress_sections} s
708 INNER JOIN {$wpdb->learnpress_section_items} si ON s.section_id = si.section_id
709 WHERE si.item_id = %d
710 ",
711 $item_id
712 );
713
714 return $wpdb->get_col( $query );
715 }
716
717 /**
718 * Ouput meta boxes.
719 *
720 * @param WP_Post $post
721 * @param mixed $box
722 */
723 public function _do_output_meta_box( $post, $box ) {
724 $callback = $this->_meta_boxes[ $box['id'] ][2];
725 if ( is_array( $callback ) ) {
726 if ( $callback[0] instanceof LP_Abstract_Post_Type ) {
727 if ( $callback[1] != __FUNCTION__ ) {
728 call_user_func_array( $callback, array( $post, $box ) );
729 }
730 } else {
731 call_user_func_array( $callback, array( $post, $box ) );
732 }
733 } else {
734 if ( is_callable( array( $this, $callback ) ) ) {
735 call_user_func_array( array( $this, $callback ), array( $post, $box ) );
736 } else {
737 call_user_func_array( $callback, array( $post, $box ) );
738 }
739 }
740 }
741
742 /**
743 * @editor tungnx
744 * @reason not use
745 */
746 /*
747 private function _is_archive() {
748 global $pagenow, $post_type;
749 if ( ! is_admin() || ( $pagenow != 'edit.php' ) || ( $this->_post_type != LP_Request::get_string( 'post_type' ) ) ) {
750 return false;
751 }
752
753 return true;
754 }*/
755
756 protected function _flush_cache() {
757 // LP_Hard_Cache::flush();
758 // wp_cache_flush();
759 }
760
761 public function _posts_fields( $fields ) {
762 if ( ! $this->_check_post() ) {
763 return $fields;
764 }
765
766 return $this->posts_fields( $fields );
767 }
768
769 public function _posts_join_paged( $join ) {
770 if ( ! $this->_check_post() ) {
771 return $join;
772 }
773
774 return $this->posts_join_paged( $join );
775 }
776
777 public function posts_join_paged( $join ) {
778 return $join;
779 }
780
781 final public function _posts_where_paged( $where ) {
782 if ( ! $this->_check_post() ) {
783 return $where;
784 }
785
786 return $this->posts_where_paged( $where );
787 }
788
789 public function posts_where_paged( $where ) {
790 return $where;
791 }
792
793 public function _posts_orderby( $orderby ) {
794 if ( ! $this->_check_post() ) {
795 return $orderby;
796 }
797
798 return $this->posts_orderby( $orderby );
799 }
800
801 public function posts_orderby( $orderby ) {
802 return $orderby;
803 }
804
805 /**
806 * Check post valid
807 *
808 * @return bool
809 */
810 public function _check_post(): bool {
811 global $pagenow, $post_type;
812
813 if ( ! is_admin() || ( ! in_array(
814 $pagenow,
815 array(
816 'edit.php',
817 'post.php',
818 )
819 ) ) || ( $this->_post_type != $post_type ) ) {
820 return false;
821 }
822
823 return true;
824 }
825
826 /**
827 * Check post is valid to handle
828 *
829 * @param int $post_id
830 *
831 * @return bool
832 * @since 4.1.6.9
833 * @version 1.0.1
834 */
835 public function check_post( int $post_id = 0 ): bool {
836 $can_save = true;
837
838 try {
839 $post = get_post( $post_id );
840 if ( ! $post ) {
841 return false;
842 }
843
844 if ( $this->_post_type !== $post->post_type ) {
845 //throw new Exception( 'Post type is invalid' );
846 return false;
847 }
848
849 if ( ! current_user_can( ADMIN_ROLE ) &&
850 get_current_user_id() !== (int) $post->post_author ) {
851 $can_save = false;
852 }
853
854 $can_save = apply_filters( 'lp/custom-post-type/can-save', $can_save, $post );
855 } catch ( Throwable $e ) {
856 $can_save = false;
857 }
858
859 return $can_save;
860 }
861
862 /**
863 * Check is page list posts valid
864 *
865 * @return bool
866 */
867 protected function is_page_list_posts_on_backend(): bool {
868 global $pagenow, $post_type;
869
870 if ( ! is_admin() || $pagenow != 'edit.php' || ( $this->_post_type != $post_type ) ) {
871 return false;
872 }
873
874 return true;
875 }
876
877 /**
878 * New Metabox instance
879 *
880 * @return array
881 * @author Nhamdv
882 */
883 public function meta_boxes() {
884 return array();
885 }
886
887 /**
888 * Render Metabox.
889 *
890 * @return void
891 * @author Nhamdv
892 */
893 public function render_meta_box() {
894 $add_meta_box = $this->meta_boxes();
895 $metaboxes = ! empty( $add_meta_box ) && is_array( $add_meta_box ) ? $add_meta_box : array();
896
897 $metaboxes = apply_filters( 'learnpress/custom-post-type/add-meta-box', $metaboxes, $this->_post_type );
898
899 if ( ! empty( $metaboxes ) ) {
900 foreach ( $metaboxes as $metabox_id => $metabox ) {
901 if ( isset( $metabox['callback'] ) ) {
902 add_meta_box( $metabox_id, $metabox['title'] ?? esc_html__( 'Unknown', 'learnpress' ), $metabox['callback'], $metabox['post_type'] ?? $this->_post_type, $metabox['context'] ?? 'normal', $metabox['priority'] ?? 'high' );
903 }
904 }
905 }
906 }
907
908 // Todo: after update metabox in h5p and withdraw will remove this function
909 public function add_meta_box( $id, $title, $callback = null, $context = 'advanced', $priority = 'default', $callback_args = null ) {
910 $this->_meta_boxes[ $id ] = func_get_args();
911
912 return $this;
913 }
914
915 // Todo: after update metabox in h5p and withdraw will remove this function
916 public function add_meta_boxes() {
917 if ( $this->_post_type != learn_press_get_requested_post_type() ) {
918 return;
919 }
920
921 do_action( 'learn_press_add_meta_boxes', $this->_post_type, $this );
922 do_action( "learn_press_{$this->_post_type}_add_meta_boxes", $this );
923
924 if ( ! $this->_meta_boxes ) {
925 return;
926 }
927
928 foreach ( $this->_meta_boxes as $k => $meta_box ) {
929 $size = sizeof( $meta_box );
930
931 if ( ( $size == 2 ) || ( $size == 3 && ! $meta_box[2] ) ) {
932 $func = 'output_' . preg_replace( '/[-]+/', '_', $meta_box[0] );
933 $meta_box[2] = array( $this, $func );
934 }
935 array_splice( $meta_box, 3, 0, array( $this->_post_type ) );
936 $this->_meta_boxes[ $k ] = $meta_box;
937
938 $meta_box[2] = array( $this, '_do_output_meta_box' );
939 call_user_func_array( 'add_meta_box', $meta_box );
940 }
941 }
942
943 /**
944 * Filter item by the course selected.
945 *
946 * @return bool|int
947 * @Todo move to course LP_Course_Post_Type
948 * @since 3.0.7
949 */
950 protected function _filter_items_by_course() {
951 $course_id = ! empty( $_REQUEST['course'] ) ? absint( $_REQUEST['course'] ) : false;
952
953 if ( ! $course_id ) {
954 global $post_type;
955 if ( ! learn_press_is_support_course_item_type( $post_type ) ) {
956 $course_id = false;
957 }
958 }
959
960 return $course_id;
961 }
962
963 /**
964 * @return mixed
965 * @Todo move to course LP_Course_Post_Type
966 */
967 protected function _get_course_column_title() {
968 global $post_type;
969
970 if ( ! learn_press_is_support_course_item_type( $post_type ) ) {
971 return false;
972 }
973
974 $title = esc_html__( 'Course', 'learnpress' );
975 $course_id = $this->_filter_items_by_course();
976
977 if ( $course_id ) {
978 $course = learn_press_get_course( $course_id );
979
980 if ( $course ) {
981 $count = $course->count_items( $this->_post_type );
982 $post_object = get_post_type_object( $post_type );
983 $title = sprintf( _n( 'Course (%1$d %2$s)', 'Course (%1$d %2$s)', $count, 'learnpress' ), $count, $count > 1 ? $post_object->label : $post_object->labels->singular_name );
984 }
985 }
986
987 return $title;
988 }
989
990 /**
991 * Get course that the items is contained.
992 *
993 * @param $post_id
994 */
995 protected function _get_item_course( $post_id ) {
996 $courses = learn_press_get_item_courses( $post_id );
997 if ( $courses ) {
998 foreach ( $courses as $course ) {
999 echo '<div><a href="' . esc_url_raw( remove_query_arg( 'orderby', add_query_arg( array( 'course' => $course->ID ) ) ) ) . '">' . get_the_title( $course->ID ) . '</a>';
1000 echo '<div class="row-actions">';
1001 printf( '<a href="%s">%s</a>', admin_url( sprintf( 'post.php?post=%d&action=edit', $course->ID ) ), __( 'Edit', 'learnpress' ) );
1002 echo '&nbsp;|&nbsp;';
1003 printf( '<a href="%s">%s</a>', get_the_permalink( $course->ID ), __( 'View', 'learnpress' ) );
1004
1005 if ( $this->_filter_items_by_course() ) {
1006 echo '&nbsp;|&nbsp;';
1007 printf(
1008 '<a href="%s">%s</a>',
1009 esc_url_raw( remove_query_arg( array( 'course', 'orderby' ) ) ),
1010 __( 'Remove Filter', 'learnpress' )
1011 );
1012 }
1013 echo '</div></div>';
1014 }
1015 } else {
1016 _e( 'Not assigned yet', 'learnpress' );
1017 }
1018 }
1019
1020 /**
1021 * @param string $fields
1022 *
1023 * @return mixed
1024 */
1025 public function posts_fields( $fields ) {
1026 return $fields;
1027 }
1028
1029 /**
1030 * Get sortable columns for list table
1031 *
1032 * @return mixed
1033 */
1034 public function sortable_columns( $columns ) {
1035 return $columns;
1036 }
1037
1038 public function columns_head( $columns ) {
1039 return $columns;
1040 }
1041
1042 public function columns_content( $column, $post_id = 0 ) {
1043 // Implement from child
1044 }
1045
1046 /**
1047 * Get string for searching
1048 *
1049 * @return string
1050 */
1051 protected function get_search(): string {
1052 return LP_Request::get( 's' );
1053 }
1054
1055 /**
1056 * @return string
1057 */
1058 protected function get_order_sort(): string {
1059 return strtolower( LP_Request::get_param( 'order' ) ) === 'desc' ? 'DESC' : 'ASC';
1060 }
1061
1062 /**
1063 * @return mixed
1064 */
1065 protected function get_order_by(): string {
1066 return LP_Request::get_param( 'orderby' );
1067 }
1068
1069 /**
1070 * Show actions on list post
1071 *
1072 * @param string[] $actions
1073 * @param WP_Post $post
1074 *
1075 * @return array|false|mixed
1076 */
1077 public function _post_row_actions( $actions, $post ) {
1078 if ( ! $this->_check_post() ) {
1079 return $actions;
1080 }
1081
1082 return $this->row_actions( $actions, $post );
1083 }
1084
1085 public function row_actions( $actions, $post ) {
1086 return $actions;
1087 }
1088
1089 /**
1090 * @deprecated 4.1.6.9
1091 */
1092 public function updated_messages( $messages ) {
1093 $post = get_post();
1094 $post_type = get_post_type( $post );
1095 $post_type_object = get_post_type_object( $this->_post_type );
1096 if ( $this->_post_type !== $post_type ) {
1097 return $messages;
1098 }
1099 $messages[ $this->_post_type ] = array(
1100 0 => '', // Unused. Messages start at index 1.
1101 1 => sprintf( '%s %s', $post_type_object->labels->singular_name, __( 'updated.', 'learnpress' ) ),
1102 2 => __( 'Custom field updated.', 'learnpress' ),
1103 3 => __( 'Custom field deleted.', 'learnpress' ),
1104 4 => sprintf( '%s %s', $post_type_object->labels->singular_name, __( 'updated.', 'learnpress' ) ),
1105 /* translators: %s: date and time of the revision */
1106 5 => isset( $_GET['revision'] ) ? sprintf( __( 'The lesson has been restored to revision from %s', 'learnpress' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
1107 6 => sprintf( '%s %s', $post_type_object->labels->singular_name, __( 'published.', 'learnpress' ) ),
1108 7 => sprintf( '%s %s', $post_type_object->labels->singular_name, __( 'saved.', 'learnpress' ) ),
1109 8 => sprintf( '%s %s', $post_type_object->labels->singular_name, __( 'submitted.', 'learnpress' ) ),
1110 9 => sprintf(
1111 sprintf( '%s %s', $post_type_object->labels->singular_name, __( 'scheduled for: <strong>%1$s</strong>.', 'learnpress' ) ),
1112 // translators: Publish box date format, see http://php.net/date
1113 date_i18n( __( 'M j, Y @ G:i', 'learnpress' ), strtotime( $post->post_date ) )
1114 ),
1115 10 => sprintf( '%s %s', $post_type_object->labels->singular_name, __( 'draft updated.', 'learnpress' ) ),
1116 );
1117
1118 if ( $post_type_object->publicly_queryable ) {
1119 $permalink = get_permalink( $post->ID );
1120
1121 $view_link = sprintf( ' <a href="%s">%s</a>', esc_url_raw( $permalink ), sprintf( '%s %s', __( 'View', 'learnpress' ), $post_type_object->labels->singular_name ) );
1122 switch ( $this->_post_type ) {
1123 case LP_LESSON_CPT:
1124 case LP_QUIZ_CPT:
1125 //$view_link = learn_press_get_item_course_id( $post->ID, $post->post_type ) ? $view_link : '';
1126 $view_link = LP_Course_DB::getInstance()->get_course_by_item_id( $post->ID ) ? $view_link : '';
1127 break;
1128 case LP_ORDER_CPT:
1129 $order = learn_press_get_order( $post->ID );
1130 $view_link = $order->get_view_order_url();
1131 $view_link = sprintf( ' <a href="%s">%s</a>', esc_url_raw( $view_link ), sprintf( '%s %s', __( 'View', 'learnpress' ), $post_type_object->labels->singular_name ) );
1132 break;
1133 case LP_QUESTION_CPT:
1134 $view_link = '';
1135 break;
1136 }
1137 $messages[ $this->_post_type ][1] .= $view_link;
1138 $messages[ $this->_post_type ][6] .= $view_link;
1139 $messages[ $this->_post_type ][9] .= $view_link;
1140
1141 $preview_permalink = learn_press_get_preview_url( $post->ID );
1142
1143 $preview_link = sprintf( ' <a target="_blank" href="%s">%s</a>', esc_url_raw( $preview_permalink ), sprintf( '%s %s', __( 'Preview', 'learnpress' ), $post_type_object->labels->singular_name ) );
1144 $messages[ $this->_post_type ][8] .= $preview_link;
1145 $messages[ $this->_post_type ][10] .= $preview_link;
1146 }
1147
1148 return $messages;
1149 }
1150 }
1151