PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
← All changes | inc/admin/class-lp-admin.php +1001 -996 4.3.94.4.8 View file →
@@ -1,996 +1,1001 @@
1 -<?php
2 -/**
3 - * @author ThimPress
4 - * @package LearnPress/Admin/Classes
5 - * @version 1.0.2
6 - */
7 -
8 -use LearnPress\Background\LPBackgroundAjax;
9 -use LearnPress\Models\CourseModel;
10 -use LearnPress\TemplateHooks\CourseBuilder\Course\BuilderCourseTemplate;
11 -
12 -defined( 'ABSPATH' ) || exit;
13 -
14 -if ( ! class_exists( 'LP_Admin' ) ) {
15 - /**
16 - * Class LP_Admin
17 - */
18 - class LP_Admin {
19 - protected static $instance;
20 -
21 - protected $pages = [];
22 -
23 - /**
24 - * Constructor
25 - */
26 - protected function __construct() {
27 - $this->pages = [
28 - 'courses' => __( 'Courses', 'learnpress' ),
29 - 'instructors' => __( 'Instructors', 'learnpress' ),
30 - 'single_instructor' => __( 'Single Instructors', 'learnpress' ),
31 - 'profile' => __( 'Profile', 'learnpress' ),
32 - 'checkout' => __( 'Checkout', 'learnpress' ),
33 - 'become_a_teacher' => __( 'Become an Instructor', 'learnpress' ),
34 - ];
35 - $this->includes();
36 - add_action( 'delete_user', array( $this, 'delete_user_data' ) );
37 - //add_action( 'delete_user_form', array( $this, 'delete_user_form' ) );
38 - add_action( 'all_admin_notices', array( $this, 'admin_notices' ), - 1 );
39 - add_action( 'admin_enqueue_scripts', array( $this, 'load_modal' ) );
40 - add_filter( 'admin_body_class', array( $this, 'body_class' ) );
41 - //add_filter( 'manage_users_custom_column', array( $this, 'users_custom_column' ), 10, 3 );
42 - //add_filter( 'manage_pages_columns', array( $this, 'page_columns_head' ) );
43 - //add_filter( 'manage_pages_custom_column', array( $this, 'page_columns_content' ), 10, 2 );
44 - add_filter( 'views_edit-page', array( $this, 'views_pages' ), 10 );
45 - add_filter( 'views_users', array( $this, 'views_users' ), 10, 1 );
46 - add_filter( 'user_row_actions', array( $this, 'user_row_actions' ), 10, 2 );
47 - add_filter( 'get_pages', array( $this, 'add_empty_page' ), 1000, 2 );
48 - add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1 );
49 - add_filter( 'views_plugins', array( $this, 'views_plugins' ) );
50 -
51 - LP_Request::register( 'lp-action', array( $this, 'filter_users' ) );
52 -
53 - add_filter( 'learn-press/modal-search-items-args', array( $this, 'filter_modal_search' ) );
54 -
55 - /*add_filter(
56 - 'learn-press/dismissed-notice-response',
57 - array(
58 - $this,
59 - 'on_dismissed_notice_response',
60 - ),
61 - 10,
62 - 2
63 - );*/
64 -
65 - // get list items course of user | tungnx
66 - add_action( 'pre_get_posts', array( $this, 'get_course_items_of_user_backend' ), 10 );
67 - add_action( 'pre_get_posts', array( $this, 'get_pages_of_lp' ), 10 );
68 -
69 - // Set link item course when edit on Backend | tungnx
70 - add_filter( 'get_sample_permalink_html', array( $this, 'lp_course_set_link_item_backend' ), 10, 5 );
71 -
72 - // Add "Edit with Course Builder" button below title area for courses
73 - add_action( 'edit_form_after_title', array( $this, 'add_course_builder_button' ) );
74 -
75 - /*add_action(
76 - 'admin_init',
77 - function () {
78 - // From LP v4.2.3 temporary run create pages to add page instructors, single instructor for client upgrade LP.
79 - // After a long time, will remove this code.
80 - if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
81 - LP_Install::create_pages();
82 - }
83 - }
84 - );*/
85 -
86 - add_filter( 'users_list_table_query_args', [ $this, 'exclude_temp_users' ] );
87 -
88 - // Show label 'LearnPress Page' for page of LearnPress.
89 - //add_filter('post_states_html');
90 - add_filter( 'display_post_states', [ $this, 'show_label_page_type' ], 10, 2 );
91 - }
92 -
93 - /**
94 - * @since 3.2.6
95 - */
96 - public function load_modal() {
97 - // Now only add item(s) when create new Order is using.
98 - if ( in_array( get_post_type(), array( LP_ORDER_CPT ) ) ) {
99 - LP_Modal_Search_Items::instance();
100 - }
101 -
102 - /*if ( in_array( get_post_type(), array( LP_ORDER_CPT ) ) ) {
103 - LP_Modal_Search_Users::instance();
104 - }*/
105 - }
106 -
107 - /**
108 - * @param $options
109 - *
110 - * @return array
111 - */
112 - public function filter_modal_search( $options ) {
113 - $options = wp_parse_args( array( 'title' => __( 'Available Courses', 'learnpress' ) ), $options );
114 -
115 - return $options;
116 - }
117 -
118 - public function add_empty_page( $pages, $args ) {
119 - if ( empty( $pages ) && ! empty( $args['class'] ) && strpos( $args['class'], 'lp-list-pages' ) !== false ) {
120 - $empty_page = get_default_post_to_edit( 'page' );
121 - $empty_page->ID = '00000';
122 - $pages[] = $empty_page;
123 - }
124 -
125 - return $pages;
126 - }
127 -
128 - /**
129 - * Add 'LearnPress' tab into views of plugins manage.
130 - *
131 - * @param array $views
132 - *
133 - * @return array
134 - * @since 3.0.0
135 - */
136 - public function views_plugins( $views ) {
137 - global $s;
138 -
139 - $search = $this->get_addons();
140 - $count_activated = 0;
141 -
142 - $active_plugins = get_option( 'active_plugins' );
143 -
144 - if ( $active_plugins ) {
145 - if ( $search ) {
146 - foreach ( $search as $k => $v ) {
147 - if ( in_array( $k, $active_plugins ) ) {
148 - ++ $count_activated;
149 - }
150 - }
151 - }
152 - }
153 -
154 - if ( $s && false !== stripos( $s, 'learnpress' ) ) {
155 - $views['learnpress'] = sprintf(
156 - '<a href="%s" class="current">%s <span class="count">(%d/%d)</span></a>',
157 - admin_url( 'plugins.php?s=learnpress' ),
158 - __( 'LearnPress', 'learnpress' ),
159 - $count_activated,
160 - sizeof( $search )
161 - );
162 - } else {
163 - $views['learnpress'] = sprintf(
164 - '<a href="%s">%s <span class="count">(%d/%d)</span></a>',
165 - admin_url( 'plugins.php?s=learnpress' ),
166 - __( 'LearnPress', 'learnpress' ),
167 - $count_activated,
168 - sizeof( $search )
169 - );
170 - }
171 -
172 - return $views;
173 - }
174 -
175 - public function get_addons() {
176 - $all_plugins = apply_filters( 'all_plugins', get_plugins() );
177 -
178 - return array_filter( $all_plugins, array( $this, '_search_callback' ) );
179 - }
180 -
181 - /**
182 - * Callback function for searching plugins have 'learnpress' inside.
183 - *
184 - * @param array $plugin
185 - *
186 - * @return bool
187 - * @since 3.0.0
188 - */
189 - public function _search_callback( $plugin ) {
190 - foreach ( $plugin as $value ) {
191 - if ( is_string( $value ) && false !== stripos( strip_tags( $value ), 'learnpress' ) ) {
192 - return true;
193 - }
194 - }
195 -
196 - return false;
197 - }
198 -
199 - /**
200 - * Check if a page is set for WooCommerce.
201 - *
202 - * @param int $id
203 - *
204 - * @return bool
205 - */
206 - /*protected function _is_wc_page( $id ) {
207 - if ( class_exists( 'WooCommerce' ) ) {
208 - if ( ! class_exists( 'WC_Admin_Post_Types' ) ) {
209 - include_once dirname( WC_PLUGIN_FILE ) . '/includes/admin/class-wc-admin-post-types.php';
210 - }
211 -
212 - $wc_admin_post_types = new WC_Admin_Post_Types();
213 - if ( is_callable( array( $wc_admin_post_types, 'add_display_post_states' ) ) ) {
214 - $a = $wc_admin_post_types->add_display_post_states( array(), get_post( $id ) );
215 - } else {
216 - $a = $this->wc_add_display_post_states( array(), get_post( $id ) );
217 - }
218 - $wc_pages = array(
219 - 'wc_page_for_shop',
220 - 'wc_page_for_cart',
221 - 'wc_page_for_checkout',
222 - 'wc_page_for_myaccount',
223 - 'wc_page_for_terms',
224 - );
225 - foreach ( $wc_pages as $for_page ) {
226 - if ( isset( $a[ $for_page ] ) ) {
227 - return $a[ $for_page ];
228 - }
229 - }
230 - }
231 -
232 - return false;
233 - }*/
234 -
235 - /*public function wc_add_display_post_states( $post_states, $post ) {
236 - if ( wc_get_page_id( 'shop' ) === $post->ID ) {
237 - $post_states['wc_page_for_shop'] = __( 'Shop Page', 'learnpress' );
238 - }
239 -
240 - if ( wc_get_page_id( 'cart' ) === $post->ID ) {
241 - $post_states['wc_page_for_cart'] = __( 'Cart Page', 'learnpress' );
242 - }
243 -
244 - if ( wc_get_page_id( 'checkout' ) === $post->ID ) {
245 - $post_states['wc_page_for_checkout'] = __( 'Checkout Page', 'learnpress' );
246 - }
247 -
248 - if ( wc_get_page_id( 'myaccount' ) === $post->ID ) {
249 - $post_states['wc_page_for_myaccount'] = __( 'My Account Page', 'learnpress' );
250 - }
251 -
252 - if ( wc_get_page_id( 'terms' ) === $post->ID ) {
253 - $post_states['wc_page_for_terms'] = __( 'Terms and Conditions Page', 'learnpress' );
254 - }
255 -
256 - return $post_states;
257 - }*/
258 -
259 - /**
260 - * Check if a page is set for Paid Membership Pro.
261 - *
262 - * @param int $id
263 - *
264 - * @return bool|mixed
265 - */
266 - /*protected function _is_pmpro_page( $id ) {
267 - global $pmpro_pages;
268 - if ( $pmpro_pages ) {
269 - $pages = array(
270 - 'account' => __( 'Account', 'learnpress' ),
271 - 'billing' => __( 'Billing', 'learnpress' ),
272 - 'cancel' => __( 'Cancel', 'learnpress' ),
273 - 'checkout' => __( 'Checkout', 'learnpress' ),
274 - 'confirmation' => __( 'Confirmation', 'learnpress' ),
275 - 'invoice' => __( 'Invoice', 'learnpress' ),
276 - 'levels' => __( 'Levels', 'learnpress' ),
277 - );
278 -
279 - foreach ( $pages as $name => $text ) {
280 - if ( $pmpro_pages[ $name ] == $id ) {
281 - return $text;
282 - }
283 - }
284 - }
285 -
286 - return false;
287 - }*/
288 -
289 - /**
290 - * Check if a page is set for Paid Membership Pro.
291 - *
292 - * @param int $id
293 - *
294 - * @return bool|mixed
295 - */
296 - /*protected function _is_bp_page( $id ) {
297 - if ( function_exists( 'buddypress' ) ) {
298 - $bp_pages = get_option( 'bp-pages' );
299 - if ( ! $bp_pages ) {
300 - return false;
301 - }
302 -
303 - $pages = array(
304 - 'members' => __( 'Members', 'learnpress' ),
305 - 'activity' => __( 'Activity', 'learnpress' ),
306 - 'register' => __( 'Register', 'learnpress' ),
307 - 'activate' => __( 'Activate', 'learnpress' ),
308 - );
309 -
310 - foreach ( $pages as $name => $text ) {
311 - if ( isset( $bp_pages[ $name ] ) && $bp_pages[ $name ] == $id ) {
312 - return $text;
313 - }
314 - }
315 - }
316 -
317 - return false;
318 - }*/
319 -
320 - /**
321 - * Get pages is publish set by LearnPress.
322 - *
323 - * @return array
324 - */
325 - protected function _get_static_pages(): array {
326 - $static_pages = [];
327 - foreach ( $this->pages as $name => $title ) {
328 - $page_id = learn_press_get_page_id( $name );
329 -
330 - if ( $page_id && 'publish' === get_post_status( $page_id ) ) {
331 - $static_pages[ $page_id ] = $title;
332 - }
333 - }
334 -
335 - return $static_pages;
336 - }
337 -
338 - /**
339 - * Show label LearnPress Page for pages set by LearnPress.
340 - *
341 - * @param array $post_states
342 - * @param WP_Post $post
343 - *
344 - * @return array
345 - * @since 4.3.2.6
346 - * @version 1.0.0
347 - */
348 - public function show_label_page_type( $post_states, $post ) {
349 - $post_type = get_post_type( $post );
350 - if ( $post_type !== 'page' ) {
351 - return $post_states;
352 - }
353 -
354 - $page_id_compare = $post->ID;
355 - foreach ( $this->_get_static_pages() as $page_id => $title ) {
356 - if ( $page_id == $page_id_compare ) {
357 - $post_states['lp_page'] = sprintf(
358 - '<span class="is-lp-page">%s</span>',
359 - 'LearnPress ' . $title . ' Page'
360 - );
361 - break;
362 - }
363 - }
364 -
365 - return $post_states;
366 - }
367 -
368 - /**
369 - * Add new column to WP Pages manage to show what page is assigned to.
370 - *
371 - * @param array $columns
372 - *
373 - * @return array
374 - */
375 - /*public function page_columns_head( $columns ) {
376 -
377 - $_columns = $columns;
378 - $columns = array();
379 -
380 - foreach ( $_columns as $name => $text ) {
381 - if ( $name === 'date' ) {
382 - $columns['lp-page'] = __( 'LearnPress Page', 'learnpress' );
383 - }
384 - $columns[ $name ] = $text;
385 - }
386 -
387 - return $columns;
388 - }*/
389 -
390 - /**
391 - * Display the page is assigned to LP Page.
392 - *
393 - * @param string $column_name
394 - * @param int $post
395 - */
396 - /*public function page_columns_content( $column_name, $post ) {
397 - $pages = $this->_get_static_pages();
398 - switch ( $column_name ) {
399 - case 'lp-page':
400 - if ( ! empty( $pages['learnpress'][ $post ] ) ) {
401 - echo wp_kses_post( $pages['learnpress'][ $post ] );
402 - }
403 -
404 - foreach ( $pages as $plugin => $plugin_pages ) {
405 - if ( $plugin === 'learnpress' ) {
406 - continue;
407 - }
408 -
409 - if ( ! empty( $pages[ $plugin ][ $post ] ) ) {
410 - echo sprintf(
411 - '<p class="for-plugin-page">(%s - %s)</p>',
412 - $plugin,
413 - $pages[ $plugin ][ $post ]
414 - );
415 - }
416 - }
417 - }
418 - }*/
419 -
420 - /**
421 - * @param $actions
422 - *
423 - * @return mixed
424 - */
425 - public function views_pages( $actions ) {
426 - $pages = $this->_get_static_pages();
427 -
428 - if ( $pages ) {
429 - $text = sprintf( __( 'LearnPress Pages (%d)', 'learnpress' ), sizeof( $pages ) );
430 - if ( 'yes' !== LP_Request::get_param( 'lp-page' ) ) {
431 - $actions['lp-page'] = sprintf(
432 - '<a href="%s">%s</a>',
433 - admin_url( 'edit.php?post_type=page&lp-page=yes' ),
434 - $text
435 - );
436 - } else {
437 - $actions['lp-page'] = $text;
438 - }
439 - }
440 -
441 - return $actions;
442 - }
443 -
444 - /**
445 - * Get pages set by LP with param url lp-page=yes
446 - *
447 - * @param WP_Query $q
448 - *
449 - * @return mixed
450 - */
451 - public function get_pages_of_lp( $q ) {
452 - if ( ! is_admin() || ! $q->is_main_query() ) {
453 - return $q;
454 - }
455 -
456 - if ( 'page' == LP_Request::get_param( 'post_type' ) && 'yes' == LP_Request::get_param( 'lp-page' ) ) {
457 - $ids = $this->_get_static_pages();
458 -
459 - if ( ! empty( $ids ) ) {
460 - $ids = array_keys( $ids );
461 - $q->set( 'post__in', $ids );
462 - }
463 - }
464 -
465 - return $q;
466 - }
467 -
468 - /**
469 - * Add actions to users list
470 - *
471 - * @param array $actions
472 - * @param WP_User $user
473 - *
474 - * @return mixed
475 - */
476 - public function user_row_actions( $actions, $user ) {
477 - $pending_request = self::get_pending_requests();
478 - if ( LP_Request::get_param( 'lp-action' ) == 'pending-request' && $pending_request ) {
479 - $actions = array();
480 - $nonce = 'nonce=' . wp_create_nonce( 'lp-action-permit-role-teacher' );
481 - if ( in_array( $user->ID, $pending_request ) ) {
482 - $actions['accept'] = sprintf(
483 - '<a href="%s">%s</a>',
484 - admin_url( "users.php?lp-action=accept-request&user_id={$user->ID}&{$nonce}" ),
485 - _x( 'Accept', 'pending-request', 'learnpress' )
486 - );
487 - $actions['delete deny'] = sprintf(
488 - '<a class="submitdelete" href="%s">%s</a>',
489 - admin_url( "users.php?lp-action=deny-request&user_id={$user->ID}&{$nonce}" ),
490 - _x( 'Deny', 'pending-request', 'learnpress' )
491 - );
492 - }
493 - }
494 -
495 - return $actions;
496 - }
497 -
498 - public function exclude_temp_users( $args ) {
499 - if ( LP_Request::get_param( 'lp-action' ) == 'pending-request' ) {
500 - $args['include'] = self::get_pending_requests();
501 - }
502 -
503 - return $args;
504 - }
505 -
506 - /**
507 - * Get pending requests be come a Teacher.
508 - *
509 - * @return array
510 - */
511 - public static function get_pending_requests() {
512 - global $wpdb;
513 - $query = $wpdb->prepare(
514 - "
515 - SELECT ID
516 - FROM {$wpdb->users} u
517 - INNER JOIN {$wpdb->usermeta} um ON um.user_id = u.ID AND um.meta_key = %s
518 - WHERE um.meta_value = %s
519 - ",
520 - '_requested_become_teacher',
521 - 'yes'
522 - );
523 -
524 - return $wpdb->get_col( $query );
525 - }
526 -
527 - /**
528 - * Filter user by custom param
529 - *
530 - * @param string $action
531 - */
532 - public function filter_users( $action ) {
533 - if ( ! current_user_can( 'administrator' ) ) {
534 - return;
535 - }
536 -
537 - $user_id = LP_Request::get_param( 'user_id', 'int' );
538 - if ( ! $user_id || ! get_user_by( 'id', $user_id ) ) {
539 - return;
540 - }
541 -
542 - $nonce = LP_Request::get_param( 'nonce' );
543 - if ( ! wp_verify_nonce( $nonce, 'lp-action-permit-role-teacher' ) ) {
544 - return;
545 - }
546 -
547 - $user_data = get_userdata( $user_id );
548 - if ( in_array( $action, array( 'accept-request', 'deny-request' ) ) ) {
549 - delete_user_meta( $user_id, '_requested_become_teacher' );
550 - }
551 -
552 - switch ( $action ) {
553 - case 'accept-request':
554 - $be_teacher = new WP_User( $user_id );
555 - $be_teacher->set_role( LP_TEACHER_ROLE );
556 -
557 - /**
558 - * Send email to user when admin accept user become a teacher
559 - * @use SendEmailAjax::send_mail_become_a_teacher_accept
560 - */
561 - $data_send = [
562 - 'params' => [ $user_data->user_email ],
563 - 'lp-load-ajax' => 'send_mail_become_a_teacher_accept',
564 - ];
565 - LPBackgroundAjax::handle( $data_send );
566 -
567 - do_action( 'learn-press/user-become-a-teacher-accept', $user_data->user_email );
568 - wp_redirect( admin_url( 'users.php?lp-action=accepted-request&user_id=' . $user_id ) );
569 - exit();
570 - case 'deny-request':
571 - /**
572 - * Send email to user when admin accept user become a teacher
573 - * @use SendEmailAjax::send_mail_become_a_teacher_deny
574 - */
575 - $data_send = [
576 - 'params' => [ $user_data->user_email ],
577 - 'lp-load-ajax' => 'send_mail_become_a_teacher_deny',
578 - ];
579 - LPBackgroundAjax::handle( $data_send );
580 -
581 - do_action( 'learn-press/user-become-a-teacher-deny', $user_data->user_email );
582 - wp_redirect( admin_url( 'users.php?lp-action=denied-request&user_id=' . $user_id ) );
583 - exit();
584 - }
585 - }
586 -
587 - public function users_custom_column( $content, $column_name, $user_id ) {
588 - }
589 -
590 - /**
591 - * Add new view to users views for filtering user by "pending request" of "become a teacher".
592 - *
593 - * @param array $views
594 - *
595 - * @return mixed
596 - */
597 - public function views_users( $views ) {
598 - $pending_request = self::get_pending_requests();
599 -
600 - if ( $pending_request ) {
601 - if ( LP_Request::get_param( 'lp-action' ) == 'pending-request' ) {
602 - $class = ' class="current"';
603 - foreach ( $views as $k => $view ) {
604 - $views[ $k ] = preg_replace( '!class="current"!', '', $view );
605 - }
606 - } else {
607 - $class = '';
608 - }
609 - $views['pending-request'] = '<a href="' . admin_url( 'users.php?lp-action=pending-request' ) . '"' . $class . '>' . sprintf(
610 - __(
611 - 'Pending Request %s',
612 - 'learnpress'
613 - ),
614 - '<span class="count">(' . count( $pending_request ) . ')</span>'
615 - ) . '</a>';
616 - }
617 -
618 - return $views;
619 - }
620 -
621 - /**
622 - * Custom admin body classes.
623 - *
624 - * @param array $classes
625 - *
626 - * @return array|string
627 - */
628 - public function body_class( $classes ) {
629 - $post_type = get_post_type();
630 -
631 - if ( preg_match( '~^lp_~', $post_type ) ) {
632 - if ( $classes ) {
633 - $classes = explode( ' ', $classes );
634 - } else {
635 - $classes = array();
636 - }
637 -
638 - $classes[] = 'learnpress';
639 - $classes = array_filter( $classes );
640 - $classes = array_unique( $classes );
641 - $classes = join( ' ', $classes );
642 - }
643 -
644 - return $classes;
645 - }
646 -
647 - /**
648 - * Display notices on Backend.
649 - */
650 - public function admin_notices() {
651 - if ( function_exists( 'get_current_screen' ) ) {
652 - $wp_screen = get_current_screen();
653 - // Not run on course edit screen, it slows, can affect performance edit course.
654 - if ( $wp_screen->id === LP_COURSE_CPT ) {
655 - return;
656 - }
657 - }
658 -
659 - // Show template file templates override.
660 - $page = LP_Request::get_param( 'page' );
661 - $tab = LP_Request::get_param( 'tab' );
662 - if ( $page == 'learn-press-tools' && $tab == 'templates' ) {
663 - if ( LP_Outdated_Template_Helper::detect_outdated_template() ) {
664 - learn_press_admin_view( 'html-admin-notice-templates' );
665 - }
666 - }
667 -
668 - // Request accept/denied user can become a teacher.
669 - $action_become_teacher = LP_Request::get_param( 'lp-action' );
670 - $user_id = LP_Request::get_param( 'user_id', 0, 'int' );
671 - $type_action_become_teacher = array( 'accepted-request', 'denied-request' );
672 - if ( in_array( $action_become_teacher, $type_action_become_teacher ) && $user_id && get_user_by( 'id', $user_id ) ) {
673 - ?>
674 - <div class="updated notice">
675 - <p>
676 - <?php
677 - echo sprintf(
678 - __( 'A user has %s to become a teacher.', 'learnpress' ),
679 - $action_become_teacher == 'accepted-request' ? 'accepted' : 'denied'
680 - );
681 - ?>
682 - </p>
683 - </div>
684 - <?php
685 - }
686 -
687 - learn_press_admin_view( 'admin-notices.php', [], true );
688 - }
689 -
690 - /**
691 - * Admin footer add review.
692 - *
693 - * @param $footer_text
694 - *
695 - * @return string
696 - */
697 - public function admin_footer_text( $footer_text ) {
698 - $current_screen = get_current_screen();
699 - $pages = learn_press_get_screens();
700 -
701 - if ( isset( $current_screen->id ) && apply_filters(
702 - 'learn_press_display_admin_footer_text',
703 - in_array( $current_screen->id, $pages )
704 - ) ) {
705 - if ( ! get_option( 'learn_press_message_user_rated' ) ) {
706 - $footer_text = sprintf(
707 - __(
708 - 'If you like <strong>LearnPress</strong> please leave us a %1$s&#9733;&#9733;&#9733;&#9733;&#9733;%2$s rating. A huge thanks from the LearnPress team for your generosity.',
709 - 'learnpress'
710 - ),
711 - '<a href="https://wordpress.org/support/plugin/learnpress/reviews/?filter=5#postform" target="_blank" class="lp-rating-link" data-rated="' . esc_attr__(
712 - 'Thanks :)',
713 - 'learnpress'
714 - ) . '">',
715 - '</a>'
716 - );
717 - }
718 - }
719 -
720 - return $footer_text;
721 - }
722 -
723 - /*function delete_user_form() {
724 - // What should be displayed here?
725 - }*/
726 -
727 - /**
728 - * Delete records related user being deleted in other tables
729 - *
730 - * @param int $user_id
731 - */
732 - function delete_user_data( $user_id ) {
733 - learn_press_delete_user_data( $user_id );
734 - }
735 -
736 - /**
737 - * Send data to join newsletter or dismiss.
738 - *
739 - * @param array $data
740 - * @param string $notice
741 - *
742 - * @return array
743 - * @since 3.0.10
744 - * @deprecated 4.2.3.1
745 - */
746 - /*public function on_dismissed_notice_response( $data, $notice ) {
747 - switch ( $notice ) {
748 - case 'skip-setup-wizard':
749 - delete_option( 'learn_press_install' );
750 - break;
751 - case 'newsletter-button':
752 - $context = LP_Request::get_string( 'context' );
753 - if ( ! $context || $context != 'newsletter' ) {
754 - break;
755 - }
756 -
757 - $user = learn_press_get_current_user();
758 - if ( ! $user || $user->get_email() == '' ) {
759 - $data['error'] = __( 'Failed while joining the newsletter! Please try again!', 'learnpress' );
760 - }
761 -
762 - $url = 'https://thimpress.com/mailster/subscribe';
763 - $response = wp_remote_post(
764 - $url,
765 - array(
766 - 'method' => 'POST',
767 - 'timeout' => 45,
768 - 'redirection' => 5,
769 - 'httpversion' => '1.0',
770 - 'blocking' => true,
771 - 'headers' => array(),
772 - 'body' => array(
773 - '_referer' => 'extern',
774 - '_nonce' => '4b266caf7b',
775 - 'formid' => '19',
776 - 'email' => $user->get_email(),
777 - 'website' => site_url(),
778 - ),
779 - 'cookies' => array(),
780 - )
781 - );
782 -
783 - if ( is_wp_error( $response ) ) {
784 - $error_message = $response->get_error_message();
785 - $data['message'] = __( 'Something went wrong: ', 'learnpress' ) . $error_message;
786 - } else {
787 - $data['message'] = __(
788 - 'Thank you for subscribing! Please check and click the confirmation link from the email that we\'ve just sent to your inbox.',
789 - 'learnpress'
790 - );
791 - }
792 - }
793 -
794 - return $data;
795 - }*/
796 -
797 - /**
798 - * Include all classes and functions used for admin
799 - */
800 - public function includes() {
801 - // Common function used in admin
802 - include_once 'lp-admin-functions.php';
803 - include_once 'lp-admin-actions.php';
804 - require_once LP_PLUGIN_PATH . 'inc/background-process/class-lp-background-query-items.php';
805 - include_once 'class-lp-admin-assets.php';
806 - LP_Admin_Assets::instance();
807 - include_once 'class-lp-admin-mcp-api-keys.php';
808 - LP_Admin_MCP_API_Keys::instance();
809 - include_once 'class-lp-admin-dashboard.php';
810 - // include_once 'class-lp-admin-tools.php';
811 - include_once 'class-lp-admin-ajax.php';
812 - include_once 'editor/class-lp-admin-editor.php';
813 - include_once 'class-lp-admin-menu.php';
814 - include_once 'helpers/class-lp-outdated-template-helper.php';
815 - include_once 'helpers/class-lp-plugins-helper.php';
816 - include_once 'class-lp-modal-search-items.php';
817 - //include_once 'class-lp-modal-search-users.php';
818 - include_once 'class-lp-setup-wizard.php';
819 - // include_once 'class-lp-updater.php';
820 - include_once 'class-lp-install-sample-data.php';
821 - include_once 'class-lp-reset-data.php';
822 - include_once LP_PLUGIN_PATH . 'inc/admin/views/meta-boxes/course/settings.php';
823 - include_once LP_PLUGIN_PATH . 'inc/admin/views/meta-boxes/course/class-lp-meta-box-course-offline.php';
824 - include_once LP_PLUGIN_PATH . 'inc/admin/views/meta-boxes/quiz/settings.php';
825 - include_once LP_PLUGIN_PATH . 'inc/admin/views/meta-boxes/lesson/settings.php';
826 - //include_once LP_PLUGIN_PATH . 'inc/admin/views/meta-boxes/question/settings.php';
827 - }
828 -
829 - /**
830 - * Get courses, item's courses on Backend page post_type
831 - *
832 - * @param WP_Query $query
833 - */
834 - public function get_course_items_of_user_backend( WP_Query $query ) {
835 - if ( ! $query->is_main_query() ) {
836 - return;
837 - }
838 -
839 - global $post_type, $pagenow;
840 -
841 - if ( current_user_can( ADMIN_ROLE ) ) {
842 - return;
843 - }
844 -
845 - if ( ! current_user_can( LP_TEACHER_ROLE ) || ( $pagenow != 'edit.php' ) ) {
846 - return;
847 - }
848 -
849 - $post_type_valid = apply_filters(
850 - 'learn-press/filter-user-access-types',
851 - array( LP_COURSE_CPT, LP_LESSON_CPT, LP_QUIZ_CPT, LP_QUESTION_CPT )
852 - );
853 -
854 - if ( ! in_array( $post_type, $post_type_valid ) ) {
855 - return;
856 - }
857 -
858 - // $query->set( 'author', get_current_user_id() );
859 -
860 - $query = apply_filters( 'learnpress/get-post-type-lp-on-backend', $query );
861 -
862 - //add_filter( 'views_edit-' . $post_type . '', '_learn_press_restrict_view_items', 10 );
863 - //remove_filter( 'pre_get_posts', array( $this, 'get_course_items_of_user_backend' ), 10 );
864 - }
865 -
866 - /**
867 - * Set link item of course when edit item on Backend
868 - *
869 - * @param string $post_link
870 - * @param int $post_id
871 - * @param string $new_title
872 - * @param string $new_slug
873 - * @param WP_Post|null $post
874 - *
875 - * @return string
876 - * @author tungnx
877 - * @since 3.2.7.5
878 - * @version 4.0.1
879 - */
880 - public function lp_course_set_link_item_backend( $post_link = '', $post_id = 0, $new_title = '', $new_slug = '', $post = null ) {
881 - try {
882 - if ( in_array( $post->post_type, CourseModel::item_types_support() ) ) {
883 - $course_id_of_item = LP_Course_DB::getInstance()->get_course_by_item_id( $post->ID );
884 - if ( $course_id_of_item ) {
885 - $course = learn_press_get_course( $course_id_of_item );
886 - if ( $course ) {
887 - $link_item = urldecode( $course->get_item_link( $post->ID ) );
888 - $post_slug = $post->post_name;
889 - $link_item_edit_slug = preg_replace( '/' . $post_slug . '$/', '', $link_item );
890 -
891 - // For update new slug
892 - if ( $new_slug ) {
893 - $post_slug = $new_slug;
894 - }
895 - $post_slug = urldecode( $post_slug );
896 -
897 - $slug_arr = explode( '/', $link_item_edit_slug );
898 - $count_slug = count( $slug_arr );
899 - unset( $slug_arr[ $count_slug - 2 ] );
900 - $link_item_edit_slug = implode( '/', $slug_arr );
901 -
902 - $post_link = '<strong>Permalink: </strong>';
903 - $post_link .= '<span id="sample-permalink">';
904 - $post_link .= '<a href="' . $link_item . '">' . $link_item_edit_slug . '<span id="editable-post-name">' . $post_slug . '</span>/</a>';
905 - $post_link .= '</span>';
906 - $post_link .= '&lrm;<span id="edit-slug-buttons">';
907 - $post_link .= '<button type="button" class="edit-slug button button-small hide-if-no-js" aria-label="Edit permalink">Edit</button>';
908 - $post_link .= '</span>';
909 - $post_link .= '<span id="editable-post-name-full">' . $post_slug . '</span>';
910 - }
911 - } else {
912 - $post_link_message = '<span>' . __(
913 - 'Permalink is only available if the item is already assigned to a course.',
914 - 'learnpress'
915 - ) . '</span>';
916 - $post_link = sprintf( '<div id="learn-press-box-edit-slug">%s</div>', $post_link_message );
917 - }
918 - } elseif ( LP_COURSE_CPT === get_post_type( $post ) ) {
919 - $post_link = LP_Helper::handle_lp_permalink_structure( $post_link, $post );
920 - }
921 - } catch ( Throwable $e ) {
922 - error_log( $e->getMessage() );
923 - }
924 -
925 - return $post_link;
926 - }
927 -
928 - /**
929 - * Add "Edit with Course Builder" button below title area for courses
930 - *
931 - * @param WP_Post $post
932 - *
933 - * @since 4.3.0
934 - */
935 - public function add_course_builder_button( $post ) {
936 - if ( ! $post || LP_COURSE_CPT !== $post->post_type ) {
937 - return;
938 - }
939 -
940 - // Only show for existing courses (not new)
941 - if ( 'auto-draft' === $post->post_status ) {
942 - return;
943 - }
944 -
945 - $course_builder_url = BuilderCourseTemplate::instance()->get_link_edit( $post->ID ) ?? '';
946 - ?>
947 - <div class="lp-edit-with-course-builder" style="margin: 10px 0 20px 0;">
948 - <a href="<?php echo esc_url( $course_builder_url ); ?>" class="button button-primary button-large" style="background: #7067ED; border-color: #7067ED; display: inline-flex; align-items: center; gap: 6px; padding: 0 16px; font-size: 14px; border-radius: 3px; line-height: 3;">
949 - <svg width="26" height="18" viewBox="0 0 69 48" fill="none" xmlns="http://www.w3.org/2000/svg">
950 - <path d="M50.9291 24.84L50.2591 21.69C50.5491 21.47 50.7391 21.11 50.7391 20.71C50.7391 20.03 50.1891 19.48 49.4991 19.48C48.8091 19.48 48.2591 20.03 48.2591 20.71C48.2591 21.11 48.4491 21.46 48.7391 21.69L48.0691 24.84C47.9891 25.21 48.1791 25.56 48.4791 25.56H50.5091C50.8091 25.56 50.9991 25.21 50.9191 24.84H50.9291Z" fill="white"></path>
951 - <path d="M50.8892 13.24H50.0092V20.92H48.9892V13.21L46.2992 13.18C43.3992 8.47 38.1692 5.34 32.2192 5.34C30.8292 5.34 29.4792 5.51 28.1892 5.83L24.9492 2.53C24.7992 2.38 24.8892 2.14 25.0992 2.11L40.7292 0L48.5492 9.68L49.7592 11.17L51.0992 12.83C51.2292 12.99 51.1092 13.24 50.8992 13.23L50.8892 13.24Z" fill="white"></path>
952 - <path d="M44.7392 13.1701L43.1392 17.1401C40.7292 13.1101 36.3092 10.4101 31.2592 10.4101C29.9992 10.4101 28.7892 10.5801 27.6292 10.8901L29.2292 6.93014C30.1992 6.74014 31.1992 6.64014 32.2192 6.64014C37.4092 6.64014 41.9892 9.22014 44.7392 13.1701Z" fill="white"></path>
953 - <path d="M25.4692 23.6899V23.8499C25.4692 23.9599 25.4592 24.0699 25.4592 24.1899C25.4592 24.0199 25.4592 23.8499 25.4692 23.6899Z" fill="white"></path>
954 - <path d="M43.3692 24.2601C43.3692 25.2901 43.2392 26.2901 42.9892 27.2501C42.3892 29.5401 41.1192 31.5601 39.4092 33.1001C37.9992 34.3601 36.2892 35.2901 34.3892 35.7701C33.4492 36.0101 32.4592 36.1401 31.4392 36.1401H27.9692V35.8001C27.9692 35.6601 27.9792 35.5301 27.9992 35.3901C28.2092 33.2201 29.5592 31.3901 31.4492 30.4901C31.6092 30.4101 31.7692 30.3401 31.9292 30.2801C32.1692 30.1901 32.4192 30.1201 32.6692 30.0601C32.7292 30.0501 32.7992 30.0301 32.8592 30.0201C35.4892 29.4101 37.4492 27.0601 37.4492 24.2501C37.4492 21.2701 35.2392 18.8001 32.3592 18.3901C32.0792 18.3501 31.7892 18.3301 31.4992 18.3301C31.2392 18.3301 30.9992 18.3501 30.7492 18.3801C28.2992 18.6901 26.2592 20.4801 25.6492 22.8201C25.5292 23.2901 25.4792 23.7701 25.4792 24.2401V42.7601C25.1492 45.6001 22.8092 47.8301 19.9092 47.9901H19.5592H16.4792C18.3092 46.6501 19.5092 44.5001 19.5092 42.0701V23.7001C19.5092 23.5601 19.5192 23.4301 19.5392 23.3001C19.6292 22.2301 19.8492 21.1901 20.2092 20.2201C20.4592 19.5401 20.7692 18.8801 21.1292 18.2501C21.7592 17.1801 22.5492 16.2201 23.4692 15.4001C24.6192 14.3701 25.9792 13.5601 27.4692 13.0401C28.7092 12.6001 30.0492 12.3701 31.4392 12.3701C32.4792 12.3701 33.4792 12.5001 34.4392 12.7501C36.6892 13.3301 38.6792 14.5401 40.2092 16.1901C40.2592 16.2401 40.3092 16.3001 40.3592 16.3501C40.3592 16.3501 40.3592 16.3501 40.3692 16.3601C41.9592 18.1401 43.0192 20.4101 43.2992 22.9001C43.3293 23.1701 43.3492 23.4501 43.3692 23.7201C43.3692 23.8901 43.3692 24.0601 43.3692 24.2401V24.2601Z" fill="white"></path>
955 - <path d="M25.4692 23.6899V23.8499C25.4692 23.9599 25.4592 24.0699 25.4592 24.1899C25.4592 24.0199 25.4592 23.8499 25.4692 23.6899Z" fill="white"></path>
956 - <path d="M6.13917 42.0799H18.0692C18.0592 45.3499 15.3792 47.9999 12.0892 47.9999H6.11917C2.83917 47.9999 0.16917 45.3499 0.14917 42.0799V12.3799H0.18917C3.46917 12.3799 6.13917 15.0299 6.13917 18.2999V42.0799Z" fill="white"></path>
957 - <path d="M67.6736 23.2845L63.9566 19.5676C63.1998 18.8108 61.9757 18.8108 61.219 19.5676L59.0266 21.7599L65.4812 28.2145L67.6736 26.0222C68.4303 25.2654 68.4303 24.0413 67.6736 23.2845Z" fill="white"></path>
958 - <path d="M45.4722 45.0411L46.3513 45.9203L42.078 46.7883C42.078 46.7883 42.0557 46.3432 41.477 45.7534C40.8983 45.1747 40.442 45.1524 40.442 45.1524L41.3101 40.879L42.1892 41.7582L59.817 24.1305L58.2256 22.5391L40.5979 40.1668L39.2513 46.7883C39.1066 47.4894 39.7298 48.1126 40.4309 47.968L47.0525 46.6214L64.6802 28.9937L63.0888 27.4023L45.4611 45.03L45.4722 45.0411Z" fill="white"></path>
959 - <path d="M60.6182 24.9316L42.9905 42.5594L44.6932 44.2621L62.3209 26.6343L60.6182 24.9316Z" fill="white"></path>
960 - </svg>
961 - <?php esc_html_e( 'Edit with Course Builder', 'learnpress' ); ?>
962 - </a>
963 - </div>
964 - <?php
965 - }
966 -
967 - /**
968 - * @return false|string
969 - * @since 3.2.8
970 - * @editor tungnx
971 - */
972 - public function get_screen_id() {
973 - global $current_screen;
974 -
975 - return $current_screen ? $current_screen->id : false;
976 - }
977 -
978 - /**
979 - * Get single instance of self
980 - *
981 - * @return bool|LP_Admin
982 - * @return bool|LP_Admin
983 - * @since 3.0.0
984 - *
985 - */
986 - public static function instance() {
987 - if ( ! self::$instance ) {
988 - self::$instance = new self();
989 - }
990 -
991 - return self::$instance;
992 - }
993 - }
994 -}
995 -
996 -return LP_Admin::instance();
1 +<?php
2 +/**
3 + * @author ThimPress
4 + * @package LearnPress/Admin/Classes
5 + * @version 1.0.2
6 + */
7 +
8 +use LearnPress\Background\LPBackgroundAjax;
9 +use LearnPress\Models\CourseModel;
10 +use LearnPress\TemplateHooks\CourseBuilder\Course\BuilderCourseTemplate;
11 +
12 +defined( 'ABSPATH' ) || exit;
13 +
14 +if ( ! class_exists( 'LP_Admin' ) ) {
15 + /**
16 + * Class LP_Admin
17 + */
18 + class LP_Admin {
19 + protected static $instance;
20 +
21 + protected $pages = [];
22 +
23 + /**
24 + * Constructor
25 + */
26 + protected function __construct() {
27 + $this->pages = [
28 + 'courses' => __( 'Courses', 'learnpress' ),
29 + 'instructors' => __( 'Instructors', 'learnpress' ),
30 + 'single_instructor' => __( 'Single Instructors', 'learnpress' ),
31 + 'profile' => __( 'Profile', 'learnpress' ),
32 + 'checkout' => __( 'Checkout', 'learnpress' ),
33 + 'become_a_teacher' => __( 'Become an Instructor', 'learnpress' ),
34 + ];
35 + $this->includes();
36 + add_action( 'delete_user', array( $this, 'delete_user_data' ) );
37 + //add_action( 'delete_user_form', array( $this, 'delete_user_form' ) );
38 + add_action( 'all_admin_notices', array( $this, 'admin_notices' ), - 1 );
39 + add_action( 'admin_enqueue_scripts', array( $this, 'load_modal' ) );
40 + add_filter( 'admin_body_class', array( $this, 'body_class' ) );
41 + //add_filter( 'manage_users_custom_column', array( $this, 'users_custom_column' ), 10, 3 );
42 + //add_filter( 'manage_pages_columns', array( $this, 'page_columns_head' ) );
43 + //add_filter( 'manage_pages_custom_column', array( $this, 'page_columns_content' ), 10, 2 );
44 + add_filter( 'views_edit-page', array( $this, 'views_pages' ), 10 );
45 + add_filter( 'views_users', array( $this, 'views_users' ), 10, 1 );
46 + add_filter( 'user_row_actions', array( $this, 'user_row_actions' ), 10, 2 );
47 + add_filter( 'get_pages', array( $this, 'add_empty_page' ), 1000, 2 );
48 + add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1 );
49 + add_filter( 'views_plugins', array( $this, 'views_plugins' ) );
50 +
51 + LP_Request::register( 'lp-action', array( $this, 'filter_users' ) );
52 +
53 + add_filter( 'learn-press/modal-search-items-args', array( $this, 'filter_modal_search' ) );
54 +
55 + /*add_filter(
56 + 'learn-press/dismissed-notice-response',
57 + array(
58 + $this,
59 + 'on_dismissed_notice_response',
60 + ),
61 + 10,
62 + 2
63 + );*/
64 +
65 + // get list items course of user | tungnx
66 + add_action( 'pre_get_posts', array( $this, 'get_course_items_of_user_backend' ), 10 );
67 + add_action( 'pre_get_posts', array( $this, 'get_pages_of_lp' ), 10 );
68 +
69 + // Set link item course when edit on Backend | tungnx
70 + add_filter( 'get_sample_permalink_html', array( $this, 'lp_course_set_link_item_backend' ), 10, 5 );
71 +
72 + // Add "Edit with Course Builder" button below title area for courses
73 + add_action( 'edit_form_after_title', array( $this, 'add_course_builder_button' ) );
74 +
75 + /*add_action(
76 + 'admin_init',
77 + function () {
78 + // From LP v4.2.3 temporary run create pages to add page instructors, single instructor for client upgrade LP.
79 + // After a long time, will remove this code.
80 + if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
81 + LP_Install::create_pages();
82 + }
83 + }
84 + );*/
85 +
86 + add_filter( 'users_list_table_query_args', [ $this, 'exclude_temp_users' ] );
87 +
88 + // Show label 'LearnPress Page' for page of LearnPress.
89 + //add_filter('post_states_html');
90 + add_filter( 'display_post_states', [ $this, 'show_label_page_type' ], 10, 2 );
91 + }
92 +
93 + /**
94 + * @since 3.2.6
95 + */
96 + public function load_modal() {
97 + // Now only add item(s) when create new Order is using.
98 + if ( in_array( get_post_type(), array( LP_ORDER_CPT ) ) ) {
99 + LP_Modal_Search_Items::instance();
100 + }
101 +
102 + /*if ( in_array( get_post_type(), array( LP_ORDER_CPT ) ) ) {
103 + LP_Modal_Search_Users::instance();
104 + }*/
105 + }
106 +
107 + /**
108 + * @param $options
109 + *
110 + * @return array
111 + */
112 + public function filter_modal_search( $options ) {
113 + $options = wp_parse_args( array( 'title' => __( 'Available Courses', 'learnpress' ) ), $options );
114 +
115 + return $options;
116 + }
117 +
118 + public function add_empty_page( $pages, $args ) {
119 + if ( empty( $pages ) && ! empty( $args['class'] ) && strpos( $args['class'], 'lp-list-pages' ) !== false ) {
120 + $empty_page = get_default_post_to_edit( 'page' );
121 + $empty_page->ID = '00000';
122 + $pages[] = $empty_page;
123 + }
124 +
125 + return $pages;
126 + }
127 +
128 + /**
129 + * Add 'LearnPress' tab into views of plugins manage.
130 + *
131 + * @param array $views
132 + *
133 + * @return array
134 + * @since 3.0.0
135 + */
136 + public function views_plugins( $views ) {
137 + global $s;
138 +
139 + $search = $this->get_addons();
140 + $count_activated = 0;
141 +
142 + $active_plugins = get_option( 'active_plugins' );
143 +
144 + if ( $active_plugins ) {
145 + if ( $search ) {
146 + foreach ( $search as $k => $v ) {
147 + if ( in_array( $k, $active_plugins ) ) {
148 + ++ $count_activated;
149 + }
150 + }
151 + }
152 + }
153 +
154 + if ( $s && false !== stripos( $s, 'learnpress' ) ) {
155 + $views['learnpress'] = sprintf(
156 + '<a href="%s" class="current">%s <span class="count">(%d/%d)</span></a>',
157 + admin_url( 'plugins.php?s=learnpress' ),
158 + __( 'LearnPress', 'learnpress' ),
159 + $count_activated,
160 + sizeof( $search )
161 + );
162 + } else {
163 + $views['learnpress'] = sprintf(
164 + '<a href="%s">%s <span class="count">(%d/%d)</span></a>',
165 + admin_url( 'plugins.php?s=learnpress' ),
166 + __( 'LearnPress', 'learnpress' ),
167 + $count_activated,
168 + sizeof( $search )
169 + );
170 + }
171 +
172 + return $views;
173 + }
174 +
175 + public function get_addons() {
176 + $all_plugins = apply_filters( 'all_plugins', get_plugins() );
177 +
178 + return array_filter( $all_plugins, array( $this, '_search_callback' ) );
179 + }
180 +
181 + /**
182 + * Callback function for searching plugins have 'learnpress' inside.
183 + *
184 + * @param array $plugin
185 + *
186 + * @return bool
187 + * @since 3.0.0
188 + */
189 + public function _search_callback( $plugin ) {
190 + foreach ( $plugin as $value ) {
191 + if ( is_string( $value ) && false !== stripos( strip_tags( $value ), 'learnpress' ) ) {
192 + return true;
193 + }
194 + }
195 +
196 + return false;
197 + }
198 +
199 + /**
200 + * Check if a page is set for WooCommerce.
201 + *
202 + * @param int $id
203 + *
204 + * @return bool
205 + */
206 + /*protected function _is_wc_page( $id ) {
207 + if ( class_exists( 'WooCommerce' ) ) {
208 + if ( ! class_exists( 'WC_Admin_Post_Types' ) ) {
209 + include_once dirname( WC_PLUGIN_FILE ) . '/includes/admin/class-wc-admin-post-types.php';
210 + }
211 +
212 + $wc_admin_post_types = new WC_Admin_Post_Types();
213 + if ( is_callable( array( $wc_admin_post_types, 'add_display_post_states' ) ) ) {
214 + $a = $wc_admin_post_types->add_display_post_states( array(), get_post( $id ) );
215 + } else {
216 + $a = $this->wc_add_display_post_states( array(), get_post( $id ) );
217 + }
218 + $wc_pages = array(
219 + 'wc_page_for_shop',
220 + 'wc_page_for_cart',
221 + 'wc_page_for_checkout',
222 + 'wc_page_for_myaccount',
223 + 'wc_page_for_terms',
224 + );
225 + foreach ( $wc_pages as $for_page ) {
226 + if ( isset( $a[ $for_page ] ) ) {
227 + return $a[ $for_page ];
228 + }
229 + }
230 + }
231 +
232 + return false;
233 + }*/
234 +
235 + /*public function wc_add_display_post_states( $post_states, $post ) {
236 + if ( wc_get_page_id( 'shop' ) === $post->ID ) {
237 + $post_states['wc_page_for_shop'] = __( 'Shop Page', 'learnpress' );
238 + }
239 +
240 + if ( wc_get_page_id( 'cart' ) === $post->ID ) {
241 + $post_states['wc_page_for_cart'] = __( 'Cart Page', 'learnpress' );
242 + }
243 +
244 + if ( wc_get_page_id( 'checkout' ) === $post->ID ) {
245 + $post_states['wc_page_for_checkout'] = __( 'Checkout Page', 'learnpress' );
246 + }
247 +
248 + if ( wc_get_page_id( 'myaccount' ) === $post->ID ) {
249 + $post_states['wc_page_for_myaccount'] = __( 'My Account Page', 'learnpress' );
250 + }
251 +
252 + if ( wc_get_page_id( 'terms' ) === $post->ID ) {
253 + $post_states['wc_page_for_terms'] = __( 'Terms and Conditions Page', 'learnpress' );
254 + }
255 +
256 + return $post_states;
257 + }*/
258 +
259 + /**
260 + * Check if a page is set for Paid Membership Pro.
261 + *
262 + * @param int $id
263 + *
264 + * @return bool|mixed
265 + */
266 + /*protected function _is_pmpro_page( $id ) {
267 + global $pmpro_pages;
268 + if ( $pmpro_pages ) {
269 + $pages = array(
270 + 'account' => __( 'Account', 'learnpress' ),
271 + 'billing' => __( 'Billing', 'learnpress' ),
272 + 'cancel' => __( 'Cancel', 'learnpress' ),
273 + 'checkout' => __( 'Checkout', 'learnpress' ),
274 + 'confirmation' => __( 'Confirmation', 'learnpress' ),
275 + 'invoice' => __( 'Invoice', 'learnpress' ),
276 + 'levels' => __( 'Levels', 'learnpress' ),
277 + );
278 +
279 + foreach ( $pages as $name => $text ) {
280 + if ( $pmpro_pages[ $name ] == $id ) {
281 + return $text;
282 + }
283 + }
284 + }
285 +
286 + return false;
287 + }*/
288 +
289 + /**
290 + * Check if a page is set for Paid Membership Pro.
291 + *
292 + * @param int $id
293 + *
294 + * @return bool|mixed
295 + */
296 + /*protected function _is_bp_page( $id ) {
297 + if ( function_exists( 'buddypress' ) ) {
298 + $bp_pages = get_option( 'bp-pages' );
299 + if ( ! $bp_pages ) {
300 + return false;
301 + }
302 +
303 + $pages = array(
304 + 'members' => __( 'Members', 'learnpress' ),
305 + 'activity' => __( 'Activity', 'learnpress' ),
306 + 'register' => __( 'Register', 'learnpress' ),
307 + 'activate' => __( 'Activate', 'learnpress' ),
308 + );
309 +
310 + foreach ( $pages as $name => $text ) {
311 + if ( isset( $bp_pages[ $name ] ) && $bp_pages[ $name ] == $id ) {
312 + return $text;
313 + }
314 + }
315 + }
316 +
317 + return false;
318 + }*/
319 +
320 + /**
321 + * Get pages is publish set by LearnPress.
322 + *
323 + * @return array
324 + */
325 + protected function _get_static_pages(): array {
326 + $static_pages = [];
327 + foreach ( $this->pages as $name => $title ) {
328 + $page_id = learn_press_get_page_id( $name );
329 +
330 + if ( $page_id && 'publish' === get_post_status( $page_id ) ) {
331 + $static_pages[ $page_id ] = $title;
332 + }
333 + }
334 +
335 + return $static_pages;
336 + }
337 +
338 + /**
339 + * Show label LearnPress Page for pages set by LearnPress.
340 + *
341 + * @param array $post_states
342 + * @param WP_Post $post
343 + *
344 + * @return array
345 + * @since 4.3.2.6
346 + * @version 1.0.0
347 + */
348 + public function show_label_page_type( $post_states, $post ) {
349 + $post_type = get_post_type( $post );
350 + if ( $post_type !== 'page' ) {
351 + return $post_states;
352 + }
353 +
354 + $page_id_compare = $post->ID;
355 + foreach ( $this->_get_static_pages() as $page_id => $title ) {
356 + if ( $page_id == $page_id_compare ) {
357 + $post_states['lp_page'] = sprintf(
358 + '<span class="is-lp-page">%s</span>',
359 + 'LearnPress ' . $title . ' Page'
360 + );
361 + break;
362 + }
363 + }
364 +
365 + return $post_states;
366 + }
367 +
368 + /**
369 + * Add new column to WP Pages manage to show what page is assigned to.
370 + *
371 + * @param array $columns
372 + *
373 + * @return array
374 + */
375 + /*public function page_columns_head( $columns ) {
376 +
377 + $_columns = $columns;
378 + $columns = array();
379 +
380 + foreach ( $_columns as $name => $text ) {
381 + if ( $name === 'date' ) {
382 + $columns['lp-page'] = __( 'LearnPress Page', 'learnpress' );
383 + }
384 + $columns[ $name ] = $text;
385 + }
386 +
387 + return $columns;
388 + }*/
389 +
390 + /**
391 + * Display the page is assigned to LP Page.
392 + *
393 + * @param string $column_name
394 + * @param int $post
395 + */
396 + /*public function page_columns_content( $column_name, $post ) {
397 + $pages = $this->_get_static_pages();
398 + switch ( $column_name ) {
399 + case 'lp-page':
400 + if ( ! empty( $pages['learnpress'][ $post ] ) ) {
401 + echo wp_kses_post( $pages['learnpress'][ $post ] );
402 + }
403 +
404 + foreach ( $pages as $plugin => $plugin_pages ) {
405 + if ( $plugin === 'learnpress' ) {
406 + continue;
407 + }
408 +
409 + if ( ! empty( $pages[ $plugin ][ $post ] ) ) {
410 + echo sprintf(
411 + '<p class="for-plugin-page">(%s - %s)</p>',
412 + $plugin,
413 + $pages[ $plugin ][ $post ]
414 + );
415 + }
416 + }
417 + }
418 + }*/
419 +
420 + /**
421 + * @param $actions
422 + *
423 + * @return mixed
424 + */
425 + public function views_pages( $actions ) {
426 + $pages = $this->_get_static_pages();
427 +
428 + if ( $pages ) {
429 + $text = sprintf( __( 'LearnPress Pages (%d)', 'learnpress' ), sizeof( $pages ) );
430 + if ( 'yes' !== LP_Request::get_param( 'lp-page' ) ) {
431 + $actions['lp-page'] = sprintf(
432 + '<a href="%s">%s</a>',
433 + admin_url( 'edit.php?post_type=page&lp-page=yes' ),
434 + $text
435 + );
436 + } else {
437 + $actions['lp-page'] = $text;
438 + }
439 + }
440 +
441 + return $actions;
442 + }
443 +
444 + /**
445 + * Get pages set by LP with param url lp-page=yes
446 + *
447 + * @param WP_Query $q
448 + *
449 + * @return mixed
450 + */
451 + public function get_pages_of_lp( $q ) {
452 + if ( ! is_admin() || ! $q->is_main_query() ) {
453 + return $q;
454 + }
455 +
456 + if ( 'page' == LP_Request::get_param( 'post_type' ) && 'yes' == LP_Request::get_param( 'lp-page' ) ) {
457 + $ids = $this->_get_static_pages();
458 +
459 + if ( ! empty( $ids ) ) {
460 + $ids = array_keys( $ids );
461 + $q->set( 'post__in', $ids );
462 + }
463 + }
464 +
465 + return $q;
466 + }
467 +
468 + /**
469 + * Add actions to users list
470 + *
471 + * @param array $actions
472 + * @param WP_User $user
473 + *
474 + * @return mixed
475 + */
476 + public function user_row_actions( $actions, $user ) {
477 + $pending_request = self::get_pending_requests();
478 + if ( LP_Request::get_param( 'lp-action' ) == 'pending-request' && $pending_request ) {
479 + $actions = array();
480 + $nonce = 'nonce=' . wp_create_nonce( 'lp-action-permit-role-teacher' );
481 + if ( in_array( $user->ID, $pending_request ) ) {
482 + $actions['accept'] = sprintf(
483 + '<a href="%s">%s</a>',
484 + admin_url( "users.php?lp-action=accept-request&user_id={$user->ID}&{$nonce}" ),
485 + _x( 'Accept', 'pending-request', 'learnpress' )
486 + );
487 + $actions['delete deny'] = sprintf(
488 + '<a class="submitdelete" href="%s">%s</a>',
489 + admin_url( "users.php?lp-action=deny-request&user_id={$user->ID}&{$nonce}" ),
490 + _x( 'Deny', 'pending-request', 'learnpress' )
491 + );
492 + }
493 + }
494 +
495 + return $actions;
496 + }
497 +
498 + public function exclude_temp_users( $args ) {
499 + if ( LP_Request::get_param( 'lp-action' ) == 'pending-request' ) {
500 + $args['include'] = self::get_pending_requests();
501 + }
502 +
503 + return $args;
504 + }
505 +
506 + /**
507 + * Get pending requests be come a Teacher.
508 + *
509 + * @return array
510 + */
511 + public static function get_pending_requests() {
512 + global $wpdb;
513 + $query = $wpdb->prepare(
514 + "
515 + SELECT ID
516 + FROM {$wpdb->users} u
517 + INNER JOIN {$wpdb->usermeta} um ON um.user_id = u.ID AND um.meta_key = %s
518 + WHERE um.meta_value = %s
519 + ",
520 + '_requested_become_teacher',
521 + 'yes'
522 + );
523 +
524 + return $wpdb->get_col( $query );
525 + }
526 +
527 + /**
528 + * Filter user by custom param
529 + *
530 + * @param string $action
531 + */
532 + public function filter_users( $action ) {
533 + if ( ! current_user_can( 'administrator' ) ) {
534 + return;
535 + }
536 +
537 + $user_id = LP_Request::get_param( 'user_id', 'int' );
538 + if ( ! $user_id || ! get_user_by( 'id', $user_id ) ) {
539 + return;
540 + }
541 +
542 + $nonce = LP_Request::get_param( 'nonce' );
543 + if ( ! wp_verify_nonce( $nonce, 'lp-action-permit-role-teacher' ) ) {
544 + return;
545 + }
546 +
547 + $user_data = get_userdata( $user_id );
548 + if ( in_array( $action, array( 'accept-request', 'deny-request' ) ) ) {
549 + delete_user_meta( $user_id, '_requested_become_teacher' );
550 + }
551 +
552 + switch ( $action ) {
553 + case 'accept-request':
554 + $be_teacher = new WP_User( $user_id );
555 + $be_teacher->set_role( LP_TEACHER_ROLE );
556 +
557 + /**
558 + * Send email to user when admin accept user become a teacher
559 + * @use SendEmailAjax::send_mail_become_a_teacher_accept
560 + */
561 + $data_send = [
562 + 'params' => [ $user_data->user_email ],
563 + 'lp-load-ajax' => 'send_mail_become_a_teacher_accept',
564 + ];
565 + LPBackgroundAjax::handle( $data_send );
566 +
567 + do_action( 'learn-press/user-become-a-teacher-accept', $user_data->user_email );
568 + wp_redirect( admin_url( 'users.php?lp-action=accepted-request&user_id=' . $user_id ) );
569 + exit();
570 + case 'deny-request':
571 + /**
572 + * Send email to user when admin accept user become a teacher
573 + * @use SendEmailAjax::send_mail_become_a_teacher_deny
574 + */
575 + $data_send = [
576 + 'params' => [ $user_data->user_email ],
577 + 'lp-load-ajax' => 'send_mail_become_a_teacher_deny',
578 + ];
579 + LPBackgroundAjax::handle( $data_send );
580 +
581 + do_action( 'learn-press/user-become-a-teacher-deny', $user_data->user_email );
582 + wp_redirect( admin_url( 'users.php?lp-action=denied-request&user_id=' . $user_id ) );
583 + exit();
584 + }
585 + }
586 +
587 + public function users_custom_column( $content, $column_name, $user_id ) {
588 + }
589 +
590 + /**
591 + * Add new view to users views for filtering user by "pending request" of "become a teacher".
592 + *
593 + * @param array $views
594 + *
595 + * @return mixed
596 + */
597 + public function views_users( $views ) {
598 + $pending_request = self::get_pending_requests();
599 +
600 + if ( $pending_request ) {
601 + if ( LP_Request::get_param( 'lp-action' ) == 'pending-request' ) {
602 + $class = ' class="current"';
603 + foreach ( $views as $k => $view ) {
604 + $views[ $k ] = preg_replace( '!class="current"!', '', $view );
605 + }
606 + } else {
607 + $class = '';
608 + }
609 + $views['pending-request'] = '<a href="' . admin_url( 'users.php?lp-action=pending-request' ) . '"' . $class . '>' . sprintf(
610 + __(
611 + 'Pending Request %s',
612 + 'learnpress'
613 + ),
614 + '<span class="count">(' . count( $pending_request ) . ')</span>'
615 + ) . '</a>';
616 + }
617 +
618 + return $views;
619 + }
620 +
621 + /**
622 + * Custom admin body classes.
623 + *
624 + * @param array $classes
625 + *
626 + * @return array|string
627 + */
628 + public function body_class( $classes ) {
629 + $post_type = get_post_type();
630 +
631 + if ( preg_match( '~^lp_~', $post_type ) ) {
632 + if ( $classes ) {
633 + $classes = explode( ' ', $classes );
634 + } else {
635 + $classes = array();
636 + }
637 +
638 + $classes[] = 'learnpress';
639 + $classes = array_filter( $classes );
640 + $classes = array_unique( $classes );
641 + $classes = join( ' ', $classes );
642 + }
643 +
644 + return $classes;
645 + }
646 +
647 + /**
648 + * Display notices on Backend.
649 + */
650 + public function admin_notices() {
651 + if ( function_exists( 'get_current_screen' ) ) {
652 + $wp_screen = get_current_screen();
653 + // Not run on course edit screen, it slows, can affect performance edit course.
654 + if ( $wp_screen->id === LP_COURSE_CPT ) {
655 + return;
656 + }
657 + }
658 +
659 + // Show template file templates override.
660 + $page = LP_Request::get_param( 'page' );
661 + $tab = LP_Request::get_param( 'tab' );
662 + if ( $page == 'learn-press-tools' && $tab == 'templates' ) {
663 + if ( LP_Outdated_Template_Helper::detect_outdated_template() ) {
664 + learn_press_admin_view( 'html-admin-notice-templates' );
665 + }
666 + }
667 +
668 + // Request accept/denied user can become a teacher.
669 + $action_become_teacher = LP_Request::get_param( 'lp-action' );
670 + $user_id = LP_Request::get_param( 'user_id', 0, 'int' );
671 + $type_action_become_teacher = array( 'accepted-request', 'denied-request' );
672 + if ( in_array( $action_become_teacher, $type_action_become_teacher ) && $user_id && get_user_by( 'id', $user_id ) ) {
673 + ?>
674 + <div class="updated notice">
675 + <p>
676 + <?php
677 + echo sprintf(
678 + __( 'A user has %s to become a teacher.', 'learnpress' ),
679 + $action_become_teacher == 'accepted-request' ? 'accepted' : 'denied'
680 + );
681 + ?>
682 + </p>
683 + </div>
684 + <?php
685 + }
686 +
687 + learn_press_admin_view( 'admin-notices.php', [], true );
688 + }
689 +
690 + /**
691 + * Admin footer add review.
692 + *
693 + * @param $footer_text
694 + *
695 + * @return string
696 + */
697 + public function admin_footer_text( $footer_text ) {
698 + $current_screen = get_current_screen();
699 + $pages = learn_press_get_screens();
700 +
701 + if ( isset( $current_screen->id ) && apply_filters(
702 + 'learn_press_display_admin_footer_text',
703 + in_array( $current_screen->id, $pages )
704 + ) ) {
705 + if ( ! get_option( 'learn_press_message_user_rated' ) ) {
706 + $footer_text = sprintf(
707 + __(
708 + 'If you like <strong>LearnPress</strong> please leave us a %1$s&#9733;&#9733;&#9733;&#9733;&#9733;%2$s rating. A huge thanks from the LearnPress team for your generosity.',
709 + 'learnpress'
710 + ),
711 + '<a href="https://wordpress.org/support/plugin/learnpress/reviews/?filter=5#postform" target="_blank" class="lp-rating-link" data-rated="' . esc_attr__(
712 + 'Thanks :)',
713 + 'learnpress'
714 + ) . '">',
715 + '</a>'
716 + );
717 + }
718 + }
719 +
720 + return $footer_text;
721 + }
722 +
723 + /*function delete_user_form() {
724 + // What should be displayed here?
725 + }*/
726 +
727 + /**
728 + * Delete records related user being deleted in other tables
729 + *
730 + * @param int $user_id
731 + */
732 + function delete_user_data( $user_id ) {
733 + learn_press_delete_user_data( $user_id );
734 + }
735 +
736 + /**
737 + * Send data to join newsletter or dismiss.
738 + *
739 + * @param array $data
740 + * @param string $notice
741 + *
742 + * @return array
743 + * @since 3.0.10
744 + * @deprecated 4.2.3.1
745 + */
746 + /*public function on_dismissed_notice_response( $data, $notice ) {
747 + switch ( $notice ) {
748 + case 'skip-setup-wizard':
749 + delete_option( 'learn_press_install' );
750 + break;
751 + case 'newsletter-button':
752 + $context = LP_Request::get_string( 'context' );
753 + if ( ! $context || $context != 'newsletter' ) {
754 + break;
755 + }
756 +
757 + $user = learn_press_get_current_user();
758 + if ( ! $user || $user->get_email() == '' ) {
759 + $data['error'] = __( 'Failed while joining the newsletter! Please try again!', 'learnpress' );
760 + }
761 +
762 + $url = 'https://thimpress.com/mailster/subscribe';
763 + $response = wp_remote_post(
764 + $url,
765 + array(
766 + 'method' => 'POST',
767 + 'timeout' => 45,
768 + 'redirection' => 5,
769 + 'httpversion' => '1.0',
770 + 'blocking' => true,
771 + 'headers' => array(),
772 + 'body' => array(
773 + '_referer' => 'extern',
774 + '_nonce' => '4b266caf7b',
775 + 'formid' => '19',
776 + 'email' => $user->get_email(),
777 + 'website' => site_url(),
778 + ),
779 + 'cookies' => array(),
780 + )
781 + );
782 +
783 + if ( is_wp_error( $response ) ) {
784 + $error_message = $response->get_error_message();
785 + $data['message'] = __( 'Something went wrong: ', 'learnpress' ) . $error_message;
786 + } else {
787 + $data['message'] = __(
788 + 'Thank you for subscribing! Please check and click the confirmation link from the email that we\'ve just sent to your inbox.',
789 + 'learnpress'
790 + );
791 + }
792 + }
793 +
794 + return $data;
795 + }*/
796 +
797 + /**
798 + * Include all classes and functions used for admin
799 + */
800 + public function includes() {
801 + // Common function used in admin
802 + include_once 'lp-admin-functions.php';
803 + include_once 'lp-admin-actions.php';
804 + include_once 'class-lp-admin-assets.php';
805 + LP_Admin_Assets::instance();
806 + // For MCP
807 + if ( learn_press_is_mcp_available() ) {
808 + include_once 'class-lp-admin-mcp-api-keys.php';
809 + LP_Admin_MCP_API_Keys::instance();
810 + }
811 + // End MCP
812 + include_once 'class-lp-admin-webhooks.php';
813 + LP_Admin_Webhooks::instance();
814 + include_once 'class-lp-admin-dashboard.php';
815 + // include_once 'class-lp-admin-tools.php';
816 + include_once 'class-lp-admin-ajax.php';
817 + include_once 'editor/class-lp-admin-editor.php';
818 + include_once 'class-lp-admin-menu.php';
819 + include_once 'helpers/class-lp-outdated-template-helper.php';
820 + include_once 'class-lp-modal-search-items.php';
821 + //include_once 'class-lp-modal-search-users.php';
822 + include_once 'class-lp-setup-wizard.php';
823 + // include_once 'class-lp-updater.php';
824 + // include_once 'class-lp-install-sample-data.php'; // Replaced by LearnPress\Ajax\SampleDataAJAX.
825 + // include_once 'class-lp-reset-data.php'; // Deprecated: replaced by CourseToolsAjax::reset_progress_items_course.
826 + include_once LP_PLUGIN_PATH . 'inc/admin/views/meta-boxes/course/settings.php';
827 + include_once LP_PLUGIN_PATH . 'inc/admin/views/meta-boxes/course/class-lp-meta-box-course-offline.php';
828 + include_once LP_PLUGIN_PATH . 'inc/admin/views/meta-boxes/quiz/settings.php';
829 + include_once LP_PLUGIN_PATH . 'inc/admin/views/meta-boxes/lesson/settings.php';
830 + //include_once LP_PLUGIN_PATH . 'inc/admin/views/meta-boxes/question/settings.php';
831 + }
832 +
833 + /**
834 + * Get courses, item's courses on Backend page post_type
835 + *
836 + * @param WP_Query $query
837 + */
838 + public function get_course_items_of_user_backend( WP_Query $query ) {
839 + if ( ! $query->is_main_query() ) {
840 + return;
841 + }
842 +
843 + /*global $post_type, $pagenow;
844 +
845 + if ( current_user_can( ADMIN_ROLE ) ) {
846 + return;
847 + }
848 +
849 + if ( ! current_user_can( LP_TEACHER_ROLE ) || ( $pagenow != 'edit.php' ) ) {
850 + return;
851 + }
852 +
853 + $post_type_valid = apply_filters(
854 + 'learn-press/filter-user-access-types',
855 + array( LP_COURSE_CPT, LP_LESSON_CPT, LP_QUIZ_CPT, LP_QUESTION_CPT )
856 + );
857 +
858 + if ( ! in_array( $post_type, $post_type_valid ) ) {
859 + return;
860 + }*/
861 +
862 + // $query->set( 'author', get_current_user_id() );
863 +
864 + // Hook only Co-instructor using.
865 + return apply_filters( 'learnpress/get-post-type-lp-on-backend', $query );
866 +
867 + //add_filter( 'views_edit-' . $post_type . '', '_learn_press_restrict_view_items', 10 );
868 + //remove_filter( 'pre_get_posts', array( $this, 'get_course_items_of_user_backend' ), 10 );
869 + }
870 +
871 + /**
872 + * Set link item of course when edit item on Backend
873 + *
874 + * @param string $post_link
875 + * @param int $post_id
876 + * @param string $new_title
877 + * @param string $new_slug
878 + * @param WP_Post|null $post
879 + *
880 + * @return string
881 + * @author tungnx
882 + * @since 3.2.7.5
883 + * @version 4.0.1
884 + */
885 + public function lp_course_set_link_item_backend( $post_link = '', $post_id = 0, $new_title = '', $new_slug = '', $post = null ) {
886 + try {
887 + if ( in_array( $post->post_type, CourseModel::item_types_support() ) ) {
888 + $course_id_of_item = LP_Course_DB::getInstance()->get_course_by_item_id( $post->ID );
889 + if ( $course_id_of_item ) {
890 + $course = learn_press_get_course( $course_id_of_item );
891 + if ( $course ) {
892 + $link_item = urldecode( $course->get_item_link( $post->ID ) );
893 + $post_slug = $post->post_name;
894 + $link_item_edit_slug = preg_replace( '/' . $post_slug . '$/', '', $link_item );
895 +
896 + // For update new slug
897 + if ( $new_slug ) {
898 + $post_slug = $new_slug;
899 + }
900 + $post_slug = urldecode( $post_slug );
901 +
902 + $slug_arr = explode( '/', $link_item_edit_slug );
903 + $count_slug = count( $slug_arr );
904 + unset( $slug_arr[ $count_slug - 2 ] );
905 + $link_item_edit_slug = implode( '/', $slug_arr );
906 +
907 + $post_link = '<strong>Permalink: </strong>';
908 + $post_link .= '<span id="sample-permalink">';
909 + $post_link .= '<a href="' . $link_item . '">' . $link_item_edit_slug . '<span id="editable-post-name">' . $post_slug . '</span>/</a>';
910 + $post_link .= '</span>';
911 + $post_link .= '&lrm;<span id="edit-slug-buttons">';
912 + $post_link .= '<button type="button" class="edit-slug button button-small hide-if-no-js" aria-label="Edit permalink">Edit</button>';
913 + $post_link .= '</span>';
914 + $post_link .= '<span id="editable-post-name-full">' . $post_slug . '</span>';
915 + }
916 + } else {
917 + $post_link_message = '<span>' . __(
918 + 'Permalink is only available if the item is already assigned to a course.',
919 + 'learnpress'
920 + ) . '</span>';
921 + $post_link = sprintf( '<div id="learn-press-box-edit-slug">%s</div>', $post_link_message );
922 + }
923 + } elseif ( LP_COURSE_CPT === get_post_type( $post ) ) {
924 + $post_link = LP_Helper::handle_lp_permalink_structure( $post_link, $post );
925 + }
926 + } catch ( Throwable $e ) {
927 + error_log( $e->getMessage() );
928 + }
929 +
930 + return $post_link;
931 + }
932 +
933 + /**
934 + * Add "Edit with Course Builder" button below title area for courses
935 + *
936 + * @param WP_Post $post
937 + *
938 + * @since 4.3.0
939 + */
940 + public function add_course_builder_button( $post ) {
941 + if ( ! $post || LP_COURSE_CPT !== $post->post_type ) {
942 + return;
943 + }
944 +
945 + // Only show for existing courses (not new)
946 + if ( 'auto-draft' === $post->post_status ) {
947 + return;
948 + }
949 +
950 + $course_builder_url = BuilderCourseTemplate::instance()->get_link_edit( $post->ID ) ?? '';
951 + ?>
952 + <div class="lp-edit-with-course-builder" style="margin: 10px 0 20px 0;">
953 + <a href="<?php echo esc_url( $course_builder_url ); ?>" class="button button-primary button-large" style="background: #7067ED; border-color: #7067ED; display: inline-flex; align-items: center; gap: 6px; padding: 0 16px; font-size: 14px; border-radius: 3px; line-height: 3;">
954 + <svg width="26" height="18" viewBox="0 0 69 48" fill="none" xmlns="http://www.w3.org/2000/svg">
955 + <path d="M50.9291 24.84L50.2591 21.69C50.5491 21.47 50.7391 21.11 50.7391 20.71C50.7391 20.03 50.1891 19.48 49.4991 19.48C48.8091 19.48 48.2591 20.03 48.2591 20.71C48.2591 21.11 48.4491 21.46 48.7391 21.69L48.0691 24.84C47.9891 25.21 48.1791 25.56 48.4791 25.56H50.5091C50.8091 25.56 50.9991 25.21 50.9191 24.84H50.9291Z" fill="white"></path>
956 + <path d="M50.8892 13.24H50.0092V20.92H48.9892V13.21L46.2992 13.18C43.3992 8.47 38.1692 5.34 32.2192 5.34C30.8292 5.34 29.4792 5.51 28.1892 5.83L24.9492 2.53C24.7992 2.38 24.8892 2.14 25.0992 2.11L40.7292 0L48.5492 9.68L49.7592 11.17L51.0992 12.83C51.2292 12.99 51.1092 13.24 50.8992 13.23L50.8892 13.24Z" fill="white"></path>
957 + <path d="M44.7392 13.1701L43.1392 17.1401C40.7292 13.1101 36.3092 10.4101 31.2592 10.4101C29.9992 10.4101 28.7892 10.5801 27.6292 10.8901L29.2292 6.93014C30.1992 6.74014 31.1992 6.64014 32.2192 6.64014C37.4092 6.64014 41.9892 9.22014 44.7392 13.1701Z" fill="white"></path>
958 + <path d="M25.4692 23.6899V23.8499C25.4692 23.9599 25.4592 24.0699 25.4592 24.1899C25.4592 24.0199 25.4592 23.8499 25.4692 23.6899Z" fill="white"></path>
959 + <path d="M43.3692 24.2601C43.3692 25.2901 43.2392 26.2901 42.9892 27.2501C42.3892 29.5401 41.1192 31.5601 39.4092 33.1001C37.9992 34.3601 36.2892 35.2901 34.3892 35.7701C33.4492 36.0101 32.4592 36.1401 31.4392 36.1401H27.9692V35.8001C27.9692 35.6601 27.9792 35.5301 27.9992 35.3901C28.2092 33.2201 29.5592 31.3901 31.4492 30.4901C31.6092 30.4101 31.7692 30.3401 31.9292 30.2801C32.1692 30.1901 32.4192 30.1201 32.6692 30.0601C32.7292 30.0501 32.7992 30.0301 32.8592 30.0201C35.4892 29.4101 37.4492 27.0601 37.4492 24.2501C37.4492 21.2701 35.2392 18.8001 32.3592 18.3901C32.0792 18.3501 31.7892 18.3301 31.4992 18.3301C31.2392 18.3301 30.9992 18.3501 30.7492 18.3801C28.2992 18.6901 26.2592 20.4801 25.6492 22.8201C25.5292 23.2901 25.4792 23.7701 25.4792 24.2401V42.7601C25.1492 45.6001 22.8092 47.8301 19.9092 47.9901H19.5592H16.4792C18.3092 46.6501 19.5092 44.5001 19.5092 42.0701V23.7001C19.5092 23.5601 19.5192 23.4301 19.5392 23.3001C19.6292 22.2301 19.8492 21.1901 20.2092 20.2201C20.4592 19.5401 20.7692 18.8801 21.1292 18.2501C21.7592 17.1801 22.5492 16.2201 23.4692 15.4001C24.6192 14.3701 25.9792 13.5601 27.4692 13.0401C28.7092 12.6001 30.0492 12.3701 31.4392 12.3701C32.4792 12.3701 33.4792 12.5001 34.4392 12.7501C36.6892 13.3301 38.6792 14.5401 40.2092 16.1901C40.2592 16.2401 40.3092 16.3001 40.3592 16.3501C40.3592 16.3501 40.3592 16.3501 40.3692 16.3601C41.9592 18.1401 43.0192 20.4101 43.2992 22.9001C43.3293 23.1701 43.3492 23.4501 43.3692 23.7201C43.3692 23.8901 43.3692 24.0601 43.3692 24.2401V24.2601Z" fill="white"></path>
960 + <path d="M25.4692 23.6899V23.8499C25.4692 23.9599 25.4592 24.0699 25.4592 24.1899C25.4592 24.0199 25.4592 23.8499 25.4692 23.6899Z" fill="white"></path>
961 + <path d="M6.13917 42.0799H18.0692C18.0592 45.3499 15.3792 47.9999 12.0892 47.9999H6.11917C2.83917 47.9999 0.16917 45.3499 0.14917 42.0799V12.3799H0.18917C3.46917 12.3799 6.13917 15.0299 6.13917 18.2999V42.0799Z" fill="white"></path>
962 + <path d="M67.6736 23.2845L63.9566 19.5676C63.1998 18.8108 61.9757 18.8108 61.219 19.5676L59.0266 21.7599L65.4812 28.2145L67.6736 26.0222C68.4303 25.2654 68.4303 24.0413 67.6736 23.2845Z" fill="white"></path>
963 + <path d="M45.4722 45.0411L46.3513 45.9203L42.078 46.7883C42.078 46.7883 42.0557 46.3432 41.477 45.7534C40.8983 45.1747 40.442 45.1524 40.442 45.1524L41.3101 40.879L42.1892 41.7582L59.817 24.1305L58.2256 22.5391L40.5979 40.1668L39.2513 46.7883C39.1066 47.4894 39.7298 48.1126 40.4309 47.968L47.0525 46.6214L64.6802 28.9937L63.0888 27.4023L45.4611 45.03L45.4722 45.0411Z" fill="white"></path>
964 + <path d="M60.6182 24.9316L42.9905 42.5594L44.6932 44.2621L62.3209 26.6343L60.6182 24.9316Z" fill="white"></path>
965 + </svg>
966 + <?php esc_html_e( 'Edit with Course Builder', 'learnpress' ); ?>
967 + </a>
968 + </div>
969 + <?php
970 + }
971 +
972 + /**
973 + * @return false|string
974 + * @since 3.2.8
975 + * @editor tungnx
976 + */
977 + public function get_screen_id() {
978 + global $current_screen;
979 +
980 + return $current_screen ? $current_screen->id : false;
981 + }
982 +
983 + /**
984 + * Get single instance of self
985 + *
986 + * @return bool|LP_Admin
987 + * @return bool|LP_Admin
988 + * @since 3.0.0
989 + *
990 + */
991 + public static function instance() {
992 + if ( ! self::$instance ) {
993 + self::$instance = new self();
994 + }
995 +
996 + return self::$instance;
997 + }
998 + }
999 +}
1000 +
1001 +return LP_Admin::instance();