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