PluginProbe
Tutor LMS – eLearning and online course solution / 1.7.0
Tutor LMS – eLearning and online course solution v1.7.0
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 All 191 releases
← All changes | classes/Admin.php +484 -988 trunk1.7.0 View file →
@@ -1,988 +1,484 @@
1 -<?php
2 -/**
3 - * Manage admin menu and plugin related logic
4 - *
5 - * @package Tutor
6 - * @author Themeum <support@themeum.com>
7 - * @link https://themeum.com
8 - * @since 1.0.0
9 - */
10 -
11 -namespace TUTOR;
12 -
13 -defined( 'ABSPATH' ) || exit;
14 -
15 -use Tutor\Ecommerce\OrderController;
16 -use Tutor\Helpers\HttpHelper;
17 -use TUTOR\Input;
18 -use Tutor\Models\CourseModel;
19 -use Tutor\Traits\JsonResponse;
20 -
21 -/**
22 - * Admin Class
23 - *
24 - * @since 1.0.0
25 - */
26 -class Admin {
27 - use JsonResponse;
28 -
29 - /**
30 - * Constructor
31 - *
32 - * @since 1.0.0
33 - *
34 - * @return void
35 - */
36 - public function __construct() {
37 - add_action( 'admin_notices', array( $this, 'show_unstable_version_admin_notice' ) );
38 -
39 - add_action( 'admin_menu', array( $this, 'register_menu' ) );
40 - // Force activate menu for necessary.
41 - add_filter( 'parent_file', array( $this, 'parent_menu_active' ) );
42 - add_filter( 'submenu_file', array( $this, 'submenu_file_active' ), 10, 2 );
43 -
44 - add_action( 'admin_init', array( $this, 'filter_posts_for_instructors' ) );
45 - add_action( 'admin_init', array( $this, 'redirect_to_welcome_page' ) );
46 - add_action( 'load-post.php', array( $this, 'check_if_current_users_post' ) );
47 -
48 - add_filter( 'plugin_action_links_' . plugin_basename( TUTOR_FILE ), array( $this, 'plugin_action_links' ) );
49 -
50 - // Plugin Row Meta.
51 - add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 2 );
52 -
53 - // Admin Footer Text.
54 - add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1 );
55 - // Register Course Widget.
56 - add_action( 'widgets_init', array( $this, 'register_course_widget' ) );
57 -
58 - // Handle flash toast message for redirect_to util helper.
59 - add_action( 'admin_head', array( new Utils(), 'handle_flash_message' ), 999 );
60 -
61 - add_action( 'admin_bar_menu', array( $this, 'add_toolbar_items' ), 100 );
62 -
63 - add_action( 'wp_ajax_tutor_do_not_show_feature_page', array( $this, 'handle_do_not_show_feature_page' ) );
64 -
65 - add_action( 'upgrader_process_complete', array( $this, 'set_permalink_flag_on_upgrade' ), 10, 2 );
66 -
67 - add_action( 'admin_notices', array( $this, 'show_offer_notice' ) );
68 - add_action( 'wp_ajax_tutor_dismiss_offer_notice', array( $this, 'ajax_dismiss_offer_notice' ) );
69 - }
70 -
71 - /**
72 - * Flush Tutor permalink rewrite rules after updates.
73 - *
74 - * @since 4.0.0
75 - *
76 - * @param mixed $upgrader_object Upgrader instance.
77 - * @param array $options Extra arguments passed to the hook.
78 - *
79 - * @return void
80 - */
81 - public function set_permalink_flag_on_upgrade( $upgrader_object, $options ) {
82 - Permalink::set_permalink_reset_flag( $upgrader_object, $options );
83 - }
84 -
85 - /**
86 - * Check offer notice is dismissed.
87 - *
88 - * @since 4.0.0
89 - *
90 - * @return bool
91 - */
92 - private function is_offer_notice_dismissed() {
93 - return '4.0.0' === get_transient( 'tutor_offer_notice_dismissed' );
94 - }
95 -
96 - /**
97 - * Show offer notice
98 - *
99 - * @since 4.0.0
100 - *
101 - * @return void
102 - */
103 - public function show_offer_notice() {
104 - if ( ! User::is_admin() || Input::has( 'welcome', Input::GET_REQUEST ) ) {
105 - return;
106 - }
107 -
108 - $is_free_user = ! tutor()->has_pro;
109 - $cta_label = __( 'Claim 30% OFF', 'tutor' );
110 - $cta_link = 'https://tutorlms.com/pricing/?utm_source=tutor-plugin&utm_medium=notice&utm_campaign=tutor-lms-pro-offer';
111 -
112 - $now = new \DateTimeImmutable( 'now', wp_timezone() );
113 - $expiration_dt = '2026-07-15 23:59:59';
114 - $expiration = new \DateTimeImmutable( $expiration_dt, wp_timezone() );
115 -
116 - $remaining = max( 0, $expiration->getTimestamp() - $now->getTimestamp() );
117 -
118 - $days = floor( $remaining / DAY_IN_SECONDS );
119 - $hours = floor( ( $remaining % DAY_IN_SECONDS ) / HOUR_IN_SECONDS );
120 - $minutes = floor( ( $remaining % HOUR_IN_SECONDS ) / MINUTE_IN_SECONDS );
121 - $seconds = $remaining % MINUTE_IN_SECONDS;
122 -
123 - $expire_in = sprintf(
124 - '%dd:%02dh:%02d:%02d',
125 - $days,
126 - $hours,
127 - $minutes,
128 - $seconds
129 - );
130 -
131 - if ( $is_free_user && $remaining > 0 && ! self::is_offer_notice_dismissed() ) {
132 - ?>
133 - <div class="tutor-offer-notice">
134 - <div class="tutor-offer-notice-wrapper">
135 - <div class="tutor-offer-notice-left">
136 - <div data-subheader><?php esc_html_e( '4.0 launch offer', 'tutor' ); ?></div>
137 - <div data-header><?php esc_html_e( '30% OFF', 'tutor' ); ?></div>
138 - <div data-subtext><?php esc_html_e( 'on all annual plans', 'tutor' ); ?></div>
139 - </div>
140 - <div class="tutor-offer-notice-right">
141 - <div class="tutor-offer-notice-text"><?php esc_html_e( 'Offer ends by', 'tutor' ); ?> <span class="tutor-offer-notice-timer" data-expiry="<?php echo esc_attr( $expiration->getTimestamp() ); ?>"><?php echo esc_html( $expire_in ); ?></span></div>
142 - <a class="tutor-offer-notice-cta" href="<?php echo esc_url( $cta_link ); ?>" target="_blank">
143 - <?php echo esc_html( $cta_label ); ?>
144 - <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="#fff" d="M13.938 6.937a.55.55 0 0 0-.786 0 .555.555 0 0 0 0 .778l3.338 3.34H5.243a.55.55 0 0 0-.55.551c0 .305.242.558.55.558h11.246l-3.337 3.334a.563.563 0 0 0 0 .785.55.55 0 0 0 .786 0L18.217 12a.543.543 0 0 0 0-.78z"/></svg>
145 - </a>
146 - </div>
147 - </div>
148 - <button type="button" class="tutor-offer-notice-dismiss"><span class="tutor-icon-times"></span></button>
149 - </div>
150 - <?php
151 - }
152 - }
153 -
154 - /**
155 - * Dismiss offer notice.
156 - *
157 - * @since 4.0.0
158 - *
159 - * @return void JSON response.
160 - */
161 - public function ajax_dismiss_offer_notice() {
162 - if ( ! User::is_admin() ) {
163 - $this->response_bad_request( tutor_utils()->error_message() );
164 - }
165 -
166 - if ( self::is_offer_notice_dismissed() ) {
167 - $this->response_bad_request( __( 'You have already dismissed the offer notice.', 'tutor' ) );
168 - }
169 -
170 - // Set expiry until next day.
171 - $expiration = strtotime( 'tomorrow' ) - time();
172 - set_transient( 'tutor_offer_notice_dismissed', '4.0.0', $expiration );
173 - $this->json_response( __( 'Notice dismissed', 'tutor' ) );
174 - }
175 -
176 - /**
177 - * Show unstable version notice.
178 - *
179 - * @since 3.0.0
180 - *
181 - * @return void
182 - */
183 - public function show_unstable_version_admin_notice() {
184 - $version = tutor_utils()->extract_version_details( TUTOR_VERSION );
185 - if ( ! $version->is_stable ) {
186 - /* translators: %s: version name */
187 - $message = sprintf( __( 'You\'re currently using Tutor LMS %s. To ensure stability, please do not use it on a live site.', 'tutor' ), '<strong>' . $version->version . '</strong>' );
188 - ?>
189 - <div class="notice notice-warning">
190 - <p><strong><?php esc_html_e( 'Warning!', 'tutor' ); ?></strong></p>
191 - <p><?php echo wp_kses_post( $message ); ?></p>
192 - </div>
193 - <?php
194 - }
195 - }
196 -
197 - /**
198 - * Register admin menus
199 - *
200 - * @since 1.0.0
201 - * @since 3.8.0 re-organize admin menu.
202 - *
203 - * @return void
204 - */
205 - public function register_menu() {
206 - $has_pro = tutor()->has_pro;
207 -
208 - $unanswered_questions = tutor_utils()->unanswered_question_count();
209 - $unanswered_bubble = '';
210 - if ( $unanswered_questions ) {
211 - $unanswered_bubble = '<span class="update-plugins count-' . $unanswered_questions . '"><span class="plugin-count">' . $unanswered_questions . '</span></span>';
212 - }
213 -
214 - $course_post_type = tutor()->course_post_type;
215 -
216 - $pro_text = '';
217 - if ( $has_pro ) {
218 - $pro_text = ' ' . apply_filters( 'tutor_pro_flag', __( 'Pro', 'tutor' ) );
219 - }
220 -
221 - $enable_course_marketplace = (bool) tutor_utils()->get_option( 'enable_course_marketplace' );
222 -
223 - $welcome = Tutor_Setup::is_welcome_page_visited();
224 -
225 - $root_page = array( $this, 'tutor_course_list' );
226 - if ( false === $welcome && Input::has( 'page' ) && 'tutor' === Input::get( 'page' ) && Input::has( 'welcome' ) ) {
227 - $root_page = array( $this, 'welcome_page' );
228 - }
229 -
230 - $icon_base64_uri = 'data:image/svg+xml;base64,' . base64_encode( '<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1139"><defs/><path fill-rule="evenodd" clip-rule="evenodd" d="M341.652 622.4c-23.412 0-43.222-19.8-43.222-43.2v-99c0-23.4 19.81-43.2 43.222-43.2 23.412 0 43.222 19.8 43.222 43.2v99c0 23.4-18.009 43.2-43.222 43.2 1.801 0 1.801 0 0 0zM655.01 622.4c-23.412 0-43.222-18-43.222-43.2v-99c0-23.4 19.81-43.2 43.222-43.2 23.412 0 43.222 19.8 43.222 43.2v99c0 25.2-19.81 43.2-43.222 43.2z" fill="#9DA2A8"/><path fill-rule="evenodd" clip-rule="evenodd" d="M255.204 406.4c18.009-37.8 54.028-63 95.449-63 61.231 1.8 108.055 52.2 106.254 113.4v203.4c3.602 21.6 23.412 37.8 45.023 34.2 18.009-1.8 32.416-16.2 34.217-34.2V455c-1.801-61.2 46.824-111.6 106.254-113.4 39.621 0 75.639 21.6 93.648 59.4 68.435 133.2 14.407 295.2-117.06 363.6C487.523 833 325.44 779 258.806 647.6c-39.62-75.6-39.62-165.6-3.602-241.2zM426.291 140h151.277v59.4c-25.212-5.4-52.226-9-77.439-9-25.213 0-50.426 3.6-75.639 7.2l1.801-57.6zm414.211 388.8c0-122.4-66.634-235.8-172.888-295.2V140h64.833c25.213 0 45.023-19.8 45.023-45s-21.611-45-45.023-45H271.413C246.2 51.8 226.39 71.6 226.39 96.8c0 25.2 19.81 45 45.023 45h66.633v91.8c-163.883 90-230.517 298.8-135.068 459 3.602 5.4-3.602-5.4 0 0C338.046 930.2 687.424 948.2 802.683 950c10.805 0 19.81-3.6 27.014-10.8 7.203-7.2 10.805-18 10.805-27V528.8z" fill="#9DA2A8"/></svg>' );
231 - $menu_position = 2;
232 -
233 - add_menu_page(
234 - __( 'Tutor LMS', 'tutor' ) . $pro_text,
235 - __( 'Tutor LMS', 'tutor' ) . $pro_text,
236 - 'manage_tutor_instructor',
237 - 'tutor',
238 - $root_page,
239 - $icon_base64_uri,
240 - $menu_position
241 - );
242 -
243 - new WhatsNew();
244 -
245 - $admin_menu = apply_filters(
246 - 'tutor_admin_menu',
247 - array(
248 - 'group_one' => array(
249 - 'courses' => array(
250 - 'parent_slug' => 'tutor',
251 - 'page_title' => __( 'Courses', 'tutor' ),
252 - 'menu_title' => __( 'Courses', 'tutor' ),
253 - 'capability' => 'manage_tutor_instructor',
254 - 'menu_slug' => 'tutor',
255 - 'callback' => array( $this, 'tutor_course_list' ),
256 - ),
257 - 'content_bank' => null,
258 - 'course_builder' => array(
259 - 'parent_slug' => 'tutor',
260 - 'page_title' => __( 'Course Builder', 'tutor' ),
261 - 'menu_title' => '<span class="tutor-create-course">Create Course</span>',
262 - 'capability' => 'manage_tutor_instructor',
263 - 'menu_slug' => 'create-course',
264 - 'callback' => array( new Course( false ), 'load_course_builder' ),
265 - ),
266 - 'categories' => array(
267 - 'parent_slug' => 'tutor',
268 - 'page_title' => __( 'Categories', 'tutor' ),
269 - 'menu_title' => __( 'Categories', 'tutor' ),
270 - 'capability' => 'manage_tutor',
271 - 'menu_slug' => 'edit-tags.php?taxonomy=course-category&post_type=' . $course_post_type,
272 - ),
273 - 'tags' => array(
274 - 'parent_slug' => 'tutor',
275 - 'page_title' => __( 'Tags', 'tutor' ),
276 - 'menu_title' => __( 'Tags', 'tutor' ),
277 - 'capability' => 'manage_tutor',
278 - 'menu_slug' => 'edit-tags.php?taxonomy=course-tag&post_type=' . $course_post_type,
279 - ),
280 - ),
281 - 'group_two' => array(
282 - 'orders' => null,
283 - 'subscriptions' => null,
284 - 'coupons' => null,
285 - 'students' => array(
286 - 'parent_slug' => 'tutor',
287 - 'page_title' => __( 'Students', 'tutor' ),
288 - 'menu_title' => __( 'Students', 'tutor' ),
289 - 'capability' => 'manage_tutor',
290 - 'menu_slug' => Students_List::STUDENTS_LIST_PAGE,
291 - 'callback' => array( $this, 'tutor_students' ),
292 -
293 - ),
294 - 'announcements' => array(
295 - 'parent_slug' => 'tutor',
296 - 'page_title' => __( 'Announcements', 'tutor' ),
297 - 'menu_title' => __( 'Announcements', 'tutor' ),
298 - 'capability' => 'manage_tutor_instructor',
299 - 'menu_slug' => 'tutor_announcements',
300 - 'callback' => array( $this, 'tutor_announcements' ),
301 -
302 - ),
303 - 'assignments' => null,
304 - 'quiz_attempts' => array(
305 - 'parent_slug' => 'tutor',
306 - 'page_title' => __( 'Quiz Attempts', 'tutor' ),
307 - 'menu_title' => __( 'Quiz Attempts', 'tutor' ),
308 - 'capability' => 'manage_tutor_instructor',
309 - 'menu_slug' => Quiz_Attempts_List::QUIZ_ATTEMPT_PAGE,
310 - 'callback' => array( $this, 'quiz_attempts' ),
311 - ),
312 - 'q_and_a' => array(
313 - 'parent_slug' => 'tutor',
314 - 'page_title' => __( 'Q&A', 'tutor' ),
315 - 'menu_title' => __( 'Q&A ', 'tutor' ) . $unanswered_bubble,
316 - 'capability' => 'manage_tutor_instructor',
317 - 'menu_slug' => Question_Answers_List::QUESTION_ANSWER_PAGE,
318 - 'callback' => array( $this, 'question_answer' ),
319 - ),
320 - 'enrollments' => null,
321 - 'reports' => null,
322 - 'gradebook' => null,
323 - 'instructors' => $enable_course_marketplace ? array(
324 - 'parent_slug' => 'tutor',
325 - 'page_title' => __( 'Instructors', 'tutor' ),
326 - 'menu_title' => __( 'Instructors', 'tutor' ),
327 - 'capability' => 'manage_tutor',
328 - 'menu_slug' => Instructors_List::INSTRUCTOR_LIST_PAGE,
329 - 'callback' => array( $this, 'tutor_instructors' ),
330 - ) : null,
331 - 'withdraw_requests' => $enable_course_marketplace ? array(
332 - 'parent_slug' => 'tutor',
333 - 'page_title' => __( 'Withdraw Requests', 'tutor' ),
334 - 'menu_title' => __( 'Withdraw Requests', 'tutor' ),
335 - 'capability' => 'manage_tutor',
336 - 'menu_slug' => Withdraw_Requests_List::WITHDRAW_REQUEST_LIST_PAGE,
337 - 'callback' => array( $this, 'withdraw_requests' ),
338 - ) : null,
339 - ),
340 - 'group_three' => array(
341 - 'google_classroom' => null,
342 - 'zoom' => null,
343 - 'google_meet' => null,
344 - 'h5p' => null,
345 - 'addons' => array(
346 - 'parent_slug' => 'tutor',
347 - 'page_title' => __( 'Addons', 'tutor' ),
348 - 'menu_title' => __( 'Addons', 'tutor' ),
349 - 'capability' => 'manage_tutor',
350 - 'menu_slug' => 'tutor-addons',
351 - 'callback' => array( $this, 'enable_disable_addons' ),
352 - ),
353 - 'tools' => array(
354 - 'parent_slug' => 'tutor',
355 - 'page_title' => __( 'Tools', 'tutor' ),
356 - 'menu_title' => __( 'Tools', 'tutor' ),
357 - 'capability' => 'manage_tutor',
358 - 'menu_slug' => 'tutor-tools',
359 - 'callback' => array( new Tools_V2(), 'load_tools_page' ),
360 - ),
361 - 'settings' => array(
362 - 'parent_slug' => 'tutor',
363 - 'page_title' => __( 'Settings', 'tutor' ),
364 - 'menu_title' => __( 'Settings', 'tutor' ),
365 - 'capability' => 'manage_tutor',
366 - 'menu_slug' => 'tutor_settings',
367 - 'callback' => array( new Options_V2(), 'load_settings_page' ),
368 - ),
369 - 'license' => null,
370 - 'whats_new' => null,
371 - 'upgrade_to_pro' => $has_pro ? null : array(
372 - 'parent_slug' => 'tutor',
373 - 'page_title' => __( 'Upgrade to Pro', 'tutor' ),
374 - 'menu_title' => sprintf( '<span class="tutor-get-pro-text">%s</span>', __( 'Upgrade to Pro', 'tutor' ) ),
375 - 'capability' => 'manage_options',
376 - 'menu_slug' => 'tutor-get-pro',
377 - 'callback' => array( $this, 'tutor_get_pro' ),
378 - ),
379 - ),
380 - )
381 - );
382 -
383 - foreach ( $admin_menu as $group => $menu ) {
384 - foreach ( $menu as $name => $args ) {
385 - if ( empty( $args ) ) {
386 - continue;
387 - }
388 -
389 - // Backward compatibility hook.
390 - if ( 'addons' === $name ) {
391 - do_action( 'tutor_admin_register' );
392 - }
393 -
394 - // Backward compatibility hook.
395 - do_action( "tutor_before_{$name}_admin_menu" );
396 -
397 - do_action( "tutor_before_{$name}_menu" );
398 - add_submenu_page( $args['parent_slug'], $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['callback'] ?? '', $args['position'] ?? null );
399 -
400 - // Backward compatibility hook.
401 - do_action( "tutor_after_{$name}_menu" );
402 -
403 - do_action( "tutor_after_{$name}_admin_menu" );
404 - }
405 -
406 - if ( 'group_three' !== $group ) {
407 - if ( 'group_two' === $group && ! current_user_can( 'manage_options' ) ) {
408 - continue;
409 - }
410 -
411 - add_submenu_page( 'tutor', '', '<span class="tutor-admin-menu-separator"></span>', 'manage_tutor_instructor', '#' );
412 - }
413 - }
414 - }
415 -
416 - /**
417 - * Welcome page opt-out
418 - *
419 - * @since 3.0.0
420 - */
421 - public function handle_do_not_show_feature_page() {
422 - tutor_utils()->check_nonce();
423 -
424 - if ( ! User::is_admin() ) {
425 - $this->json_response(
426 - tutor_utils()->error_message(),
427 - null,
428 - HttpHelper::STATUS_BAD_REQUEST
429 - );
430 - }
431 -
432 - update_option( 'tutor-new-feature', '3.0.0' );
433 - $this->json_response( __( 'Success', 'tutor' ) );
434 - }
435 -
436 - /**
437 - * Show Feature Promotion Page for Free User.
438 - *
439 - * @since 2.2.0
440 - *
441 - * @return void
442 - */
443 - public function feature_promotion_page() {
444 - include tutor()->path . 'views/pages/welcome.php';
445 - }
446 -
447 - /**
448 - * Show students page
449 - *
450 - * @since 1.0.0
451 - *
452 - * @return void
453 - */
454 - public function tutor_students() {
455 - include tutor()->path . 'views/pages/students.php';
456 - }
457 -
458 - /**
459 - * Show instructor page
460 - *
461 - * @since 1.0.0
462 - *
463 - * @return void
464 - */
465 - public function tutor_instructors() {
466 - include tutor()->path . 'views/pages/instructors.php';
467 - }
468 -
469 - /**
470 - * Show announcements page
471 - *
472 - * @since 1.0.0
473 - *
474 - * @return void
475 - */
476 - public function tutor_announcements() {
477 - include tutor()->path . 'views/pages/announcements.php';
478 - }
479 -
480 - /**
481 - * Show Q&A page
482 - *
483 - * @since 1.0.0
484 - *
485 - * @return void
486 - */
487 - public function question_answer() {
488 - include tutor()->path . 'views/pages/question_answer.php';
489 - }
490 -
491 - /**
492 - * Show quiz attempts page
493 - *
494 - * @since 1.0.0
495 - *
496 - * @return void
497 - */
498 - public function quiz_attempts() {
499 - include tutor()->path . 'views/pages/quiz_attempts.php';
500 - }
501 -
502 - /**
503 - * Show the withdraw requests table
504 - *
505 - * @since 1.2.0
506 - *
507 - * @return void
508 - */
509 - public function withdraw_requests() {
510 - include tutor()->path . 'views/pages/withdraw_requests.php';
511 - }
512 -
513 - /**
514 - * Enable or disable addons
515 - *
516 - * @since 1.0.0
517 - *
518 - * @return void
519 - */
520 - public function enable_disable_addons() {
521 - include tutor()->path . 'views/pages/enable_disable_addons.php';
522 - }
523 -
524 - /**
525 - * Tutor tools page (OLD)
526 - *
527 - * @since 1.0.0
528 - *
529 - * @return void
530 - */
531 - public function tutor_tools_old() {
532 - $tutor_admin_tools_page = Input::get( 'tutor_admin_tools_page' );
533 - if ( $tutor_admin_tools_page ) {
534 - include apply_filters( 'tutor_admin_tools_page', tutor()->path . "views/pages/{$tutor_admin_tools_page}.php", $tutor_admin_tools_page );
535 - } else {
536 - $pages = apply_filters(
537 - 'tutor_tool_pages',
538 - array(
539 - 'tutor_pages' => array( 'title' => __( 'Tutor Pages', 'tutor' ) ),
540 - 'status' => __( 'Status', 'tutor' ),
541 - )
542 - );
543 -
544 - $current_page = 'tutor_pages';
545 - $requested_page = Input::get( 'sub_page' );
546 - if ( $requested_page ) {
547 - $current_page = $requested_page;
548 - }
549 -
550 - $current_page = str_replace( '/', '', $current_page );
551 - $current_page = str_replace( '.', '', $current_page );
552 - $current_page = str_replace( '\\', '', $current_page );
553 - $current_page = trim( $current_page );
554 -
555 - include tutor()->path . 'views/pages/tools.php';
556 - }
557 - }
558 -
559 - /**
560 - * Show pro upgrade page
561 - *
562 - * @since 1.0.0
563 - *
564 - * @return void
565 - */
566 - public function tutor_get_pro() {
567 - include tutor()->path . 'views/pages/get-pro.php';
568 - }
569 -
570 - /**
571 - * Parent menu active
572 - *
573 - * @since 1.0.0
574 - *
575 - * @param string $parent_file parent file.
576 - *
577 - * @return string
578 - */
579 - public function parent_menu_active( $parent_file ) {
580 - $taxonomy = Input::get( 'taxonomy' );
581 - if ( CourseModel::COURSE_CATEGORY === $taxonomy || CourseModel::COURSE_TAG === $taxonomy ) {
582 - return 'tutor';
583 - }
584 -
585 - return $parent_file;
586 - }
587 -
588 - /**
589 - * Sub-menu active
590 - *
591 - * @since 1.0.0
592 - *
593 - * @param string $submenu_file submenu file.
594 - * @param string $parent_file parent file.
595 - *
596 - * @return string
597 - */
598 - public function submenu_file_active( $submenu_file, $parent_file ) {
599 - $taxonomy = Input::get( 'taxonomy' );
600 - $course_post_type = tutor()->course_post_type;
601 -
602 - if ( CourseModel::COURSE_CATEGORY === $taxonomy ) {
603 - return 'edit-tags.php?taxonomy=course-category&post_type=' . $course_post_type;
604 - }
605 - if ( CourseModel::COURSE_TAG === $taxonomy ) {
606 - return 'edit-tags.php?taxonomy=course-tag&post_type=' . $course_post_type;
607 - }
608 -
609 - return $submenu_file;
610 - }
611 -
612 - /**
613 - * Filter posts for instructor
614 - *
615 - * @since 1.0.0
616 - *
617 - * @return void
618 - */
619 - public function filter_posts_for_instructors() {
620 - if ( ! current_user_can( 'administrator' ) && current_user_can( tutor()->instructor_role ) ) {
621 - @remove_menu_page( 'edit-comments.php' ); // Comments.
622 - add_filter( 'posts_clauses_request', array( $this, 'posts_clauses_request' ) );
623 - }
624 - }
625 -
626 - /**
627 - * Request for posts clauses
628 - *
629 - * @since 1.0.0
630 - *
631 - * @param mixed $clauses clauses.
632 - *
633 - * @return mixed
634 - */
635 - public function posts_clauses_request( $clauses ) {
636 -
637 - if ( ! is_admin() || ( ! Input::has( 'post_type' ) || Input::get( 'post_type' ) != tutor()->course_post_type ) || tutor_utils()->has_user_role( array( 'administrator', 'editor' ) ) ) {
638 - return $clauses;
639 - }
640 -
641 - // Need multi instructor check.
642 - global $wpdb;
643 -
644 - $user_id = get_current_user_id();
645 -
646 - $get_assigned_courses_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_value from {$wpdb->usermeta} WHERE meta_key = '_tutor_instructor_course_id' AND user_id = %d", $user_id ) );
647 - $own_courses = is_array( $get_assigned_courses_ids ) ? $get_assigned_courses_ids : array();
648 -
649 - $in_query_pre = count( $own_courses ) ? implode( ',', $own_courses ) : null;
650 - $in_query_where = $in_query_pre ? " OR {$wpdb->posts}.ID IN({$in_query_pre})" : '';
651 -
652 - $course_post_type = tutor()->course_post_type;
653 - $custom_author_query = " AND ({$wpdb->posts}.post_type!='{$course_post_type}' OR {$wpdb->posts}.post_author = {$user_id}) {$in_query_where}";
654 -
655 - $clauses['where'] .= $custom_author_query;
656 -
657 - return $clauses;
658 - }
659 -
660 - /**
661 - * Prevent unauthorised course/lesson edit page by direct URL
662 - *
663 - * @since 1.0.0
664 - *
665 - * @return void
666 - */
667 - public function check_if_current_users_post() {
668 - if ( current_user_can( 'administrator' ) || ! current_user_can( tutor()->instructor_role ) ) {
669 - return;
670 - }
671 -
672 - if ( ! empty( Input::get( 'post' ) ) ) {
673 - $get_post_id = Input::get( 'post', Input::TYPE_INT );
674 - $get_post = get_post( $get_post_id );
675 - $tutor_post_types = array( tutor()->course_post_type, tutor()->lesson_post_type );
676 -
677 - $current_user = get_current_user_id();
678 -
679 - if ( in_array( $get_post->post_type, $tutor_post_types ) && $get_post->post_author != $current_user ) {
680 - global $wpdb;
681 -
682 - $get_assigned_courses_ids = (int) $wpdb->get_var(
683 - $wpdb->prepare(
684 - "SELECT user_id
685 - from {$wpdb->usermeta}
686 - WHERE user_id = %d AND meta_key = '_tutor_instructor_course_id' AND meta_value = %d ",
687 - $current_user,
688 - $get_post_id
689 - )
690 - );
691 -
692 - if ( ! $get_assigned_courses_ids ) {
693 - wp_die( esc_html__( 'Permission Denied', 'tutor' ) );
694 - }
695 - }
696 - }
697 - }
698 -
699 - /**
700 - * Scan template files
701 - *
702 - * @since 1.0.0
703 - *
704 - * @param string $template_path template file path.
705 - *
706 - * @return array
707 - */
708 - public static function scan_template_files( $template_path = null ) {
709 - if ( ! $template_path ) {
710 - $template_path = tutor()->path . 'templates/';
711 - }
712 -
713 - $files = @scandir($template_path); // @codingStandardsIgnoreLine.
714 - $result = array();
715 -
716 - if ( ! empty( $files ) ) {
717 - foreach ( $files as $key => $value ) {
718 - if ( ! in_array( $value, array( '.', '..', '.DS_Store' ), true ) ) {
719 - if ( is_dir( $template_path . DIRECTORY_SEPARATOR . $value ) ) {
720 - $sub_files = self::scan_template_files( $template_path . DIRECTORY_SEPARATOR . $value );
721 - foreach ( $sub_files as $sub_file ) {
722 - $result[] = $value . DIRECTORY_SEPARATOR . $sub_file;
723 - }
724 - } else {
725 - $result[] = $value;
726 - }
727 - }
728 - }
729 - }
730 - return $result;
731 - }
732 -
733 - /**
734 - * Get Template overridden files
735 - *
736 - * @since 1.0.0
737 - *
738 - * @return array
739 - */
740 - public static function template_overridden_files() {
741 - $template_files = self::scan_template_files();
742 -
743 - $override_files = array();
744 - foreach ( $template_files as $file ) {
745 - $file_path = null;
746 - if ( file_exists( trailingslashit( get_stylesheet_directory() ) . tutor()->template_path . $file ) ) {
747 - $file_path = $file;
748 - } elseif ( file_exists( trailingslashit( get_template_directory() ) . tutor()->template_path . $file ) ) {
749 - $file_path = $file;
750 - }
751 -
752 - if ( $file_path ) {
753 - $override_files[] = str_replace( WP_CONTENT_DIR . '/themes/', '', $file_path );
754 - }
755 - }
756 -
757 - return $override_files;
758 - }
759 -
760 - /**
761 - * Plugin activation link
762 - *
763 - * @since 1.0.0
764 - *
765 - * @param array $actions action list.
766 - *
767 - * @return array
768 - */
769 - public function plugin_action_links( $actions ) {
770 - $has_pro = tutor()->has_pro;
771 -
772 - if ( ! $has_pro ) {
773 - $actions['tutor_pro_link'] =
774 - '<a href="https://tutorlms.com/pricing?utm_source=tutor_plugin_action_link&utm_medium=wordpress_dashboard&utm_campaign=go_premium" target="_blank">
775 - <span style="color: #ff7742; font-weight: bold;">' .
776 - __( 'Upgrade to Pro', 'tutor' ) .
777 - '</span>
778 - </a>';
779 - }
780 -
781 - $actions['settings'] = '<a href="admin.php?page=tutor_settings">' . __( 'Settings', 'tutor' ) . '</a>';
782 -
783 - return $actions;
784 - }
785 -
786 - /**
787 - * Add plugin meta data in WP plugins list page
788 - *
789 - * @since 1.0.0
790 - *
791 - * @param array $plugin_meta plugin meta data.
792 - * @param string $plugin_file plugin file.
793 - *
794 - * @return array
795 - */
796 - public function plugin_row_meta( $plugin_meta, $plugin_file ) {
797 -
798 - if ( tutor()->basename === $plugin_file ) {
799 - $plugin_meta[] = sprintf(
800 - '<a href="%s"><strong style="color: #03bd24">%s</strong></a>',
801 - esc_url( 'https://tutorlms.com/docs/?utm_source=tutor&utm_medium=plugins_installation_list&utm_campaign=plugin_docs_link' ),
802 - esc_html__( 'Documentation', 'tutor' )
803 - );
804 - $plugin_meta[] = sprintf(
805 - '<a href="%s"><strong style="color: #03bd24">%s</strong></a>',
806 - esc_url( 'https://tutorlms.com/support/?utm_source=tutor&utm_medium=plugins_installation_list&utm_campaign=plugin_support_link' ),
807 - esc_html__( 'Get Support', 'tutor' )
808 - );
809 - }
810 -
811 - return $plugin_meta;
812 - }
813 -
814 - /**
815 - * Add footer text only on tutor pages
816 - *
817 - * @since 1.0.0
818 - *
819 - * @param string $footer_text footer text.
820 - *
821 - * @return string
822 - */
823 - public function admin_footer_text( $footer_text ) {
824 - $current_screen = get_current_screen();
825 -
826 - /**
827 - * We are making sure that this message will be only on Tutor Admin page
828 - */
829 - if ( apply_filters( 'tutor_display_admin_footer_text', ( tutor_utils()->array_get( 'parent_base', $current_screen ) === 'tutor' ) ) ) {
830 - $footer_text = sprintf(
831 - /* translators: %s: plugin name */
832 - __( 'If you like %1$s please leave us a %2$s rating. A huge thanks in advance!', 'tutor' ),
833 - sprintf( '<strong>%s</strong>', esc_html__( 'Tutor LMS', 'tutor' ) ),
834 - '<a href="https://wordpress.org/support/plugin/tutor/reviews?rate=5#new-post" target="_blank" class="tutor-rating-link">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
835 - );
836 - }
837 -
838 - return $footer_text;
839 - }
840 -
841 - /**
842 - * Register course widget
843 - *
844 - * @since 1.0.0
845 - * @return void
846 - */
847 - public function register_course_widget() {
848 - register_widget( Course_Widget::class );
849 - }
850 -
851 - /**
852 - * Tutor Course List
853 - *
854 - * @since 2.0.0
855 - *
856 - * @return void
857 - */
858 - public function tutor_course_list() {
859 - include tutor()->path . 'views/pages/course-list.php';
860 - }
861 -
862 - /**
863 - * Orders view page
864 - *
865 - * @since 3.0.0
866 - *
867 - * @return void
868 - */
869 - public function orders_view() {
870 - $current_page = Input::get( 'page' );
871 - $action = Input::get( 'action' );
872 -
873 - if ( OrderController::PAGE_SLUG === $current_page && 'edit' === $action ) {
874 - ?>
875 - <div class="tutor-admin-wrap tutor-order-details-wrapper">
876 - <div id="tutor-order-details-root">
877 - </div>
878 - </div>
879 - <?php
880 - return;
881 - }
882 -
883 - include tutor()->path . 'views/pages/ecommerce/order-list.php';
884 - }
885 -
886 - /**
887 - * Coupons view page
888 - *
889 - * @since 3.0.0
890 - *
891 - * @return void
892 - */
893 - public function coupons_view() {
894 - $action = Input::get( 'action' );
895 - if ( in_array( $action, array( 'add_new', 'edit' ) ) ) {
896 - ?>
897 - <div class="tutor-admin-wrap">
898 - <div id="tutor-coupon-root">
899 - </div>
900 - </div>
901 - <?php
902 - return;
903 - }
904 - include tutor()->path . 'views/pages/ecommerce/coupon-list.php';
905 - }
906 -
907 - /**
908 - * Show welcome page
909 - *
910 - * @since 1.0.0
911 - *
912 - * @return void
913 - */
914 - public function welcome_page() {
915 - Tutor_Setup::mark_as_visited();
916 - include tutor()->path . 'views/pages/welcome.php';
917 - exit;
918 - }
919 -
920 - /**
921 - * Add toolbar items
922 - *
923 - * @since 1.4.6
924 - *
925 - * @param \WP_Admin_Bar $admin_bar admin bar object.
926 - *
927 - * @return mixed
928 - */
929 - public function add_toolbar_items( \WP_Admin_Bar $admin_bar ) {
930 - global $post;
931 -
932 - $course_id = Input::get( 'post', 0, Input::TYPE_INT );
933 - $course_post_type = tutor()->course_post_type;
934 -
935 - if ( $admin_bar->get_node( 'new-courses' ) ) {
936 - $args = $admin_bar->get_node( 'new-courses' );
937 - $args->href = '#';
938 - $args->meta['class'] = 'tutor-create-new-course';
939 - $admin_bar->add_node( $args );
940 - }
941 -
942 - if ( ! tutor_utils()->can_user_edit_course( get_current_user_id(), $course_id ) ) {
943 - return $admin_bar;
944 - }
945 -
946 - if (
947 - ( is_admin() && $post && $course_id && $post->post_type === $course_post_type ) ||
948 - ( ! is_admin() && is_single() && $post && $course_post_type === $post->post_type )
949 - ) {
950 -
951 - $admin_bar->add_menu(
952 - array(
953 - 'id' => 'edit',
954 - 'title' => __( 'Edit with Course Builder', 'tutor' ),
955 - 'href' => tutor_utils()->course_edit_link( $post->ID ),
956 - 'meta' => array(
957 - 'title' => __( 'Edit with Course Builder', 'tutor' ),
958 - 'target' => '_blank',
959 - ),
960 - )
961 - );
962 - }
963 -
964 - return $admin_bar;
965 - }
966 -
967 - /**
968 - * Redirect to welcome page if user is not logged in.
969 - *
970 - * @since 4.0.0
971 - *
972 - * @return void
973 - */
974 - public function redirect_to_welcome_page() {
975 - // Skip for fresh installs, during the setup wizard, or during AJAX.
976 - if ( ! get_option( 'tutor_wizard' ) || 'tutor-setup' === Input::get( 'page' ) || wp_doing_ajax() ) {
977 - return;
978 - }
979 -
980 - $tutor_new_feature = get_option( 'tutor-new-feature' );
981 - if ( version_compare( $tutor_new_feature, '4.0.0-rc.2', '>=' ) ) {
982 - return;
983 - }
984 -
985 - wp_safe_redirect( admin_url( 'admin.php?page=tutor&welcome=1' ) );
986 - update_option( 'tutor-new-feature', TUTOR_VERSION );
987 - }
988 -}
1 +<?php
2 +namespace TUTOR;
3 +
4 +/**
5 + * Class Admin
6 + * @package TUTOR
7 + *
8 + * @since v.1.0.0
9 + */
10 +
11 +if ( ! defined( 'ABSPATH' ) )
12 + exit;
13 +
14 +class Admin{
15 + public function __construct() {
16 + add_action('admin_menu', array($this, 'register_menu'));
17 + //Force activate menu for necessary
18 + add_filter('parent_file', array($this, 'parent_menu_active'));
19 + add_filter('submenu_file', array($this, 'submenu_file_active'), 10, 2);
20 +
21 + add_action('admin_init', array($this, 'filter_posts_for_instructors'));
22 + add_action('load-post.php', array($this, 'check_if_current_users_post') );
23 +
24 + add_action('admin_action_uninstall_tutor_and_erase', array($this, 'erase_tutor_data'));
25 + add_filter('plugin_action_links_' . plugin_basename(TUTOR_FILE), array( $this, 'plugin_action_links' ) );
26 +
27 + //Plugin Row Meta
28 + add_filter('plugin_row_meta', array($this, 'plugin_row_meta'), 10, 2);
29 +
30 + //Admin Footer Text
31 + add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1 );
32 + //Register Course Widget
33 + add_action( 'widgets_init', array($this, 'register_course_widget') );
34 + }
35 +
36 + public function register_menu(){
37 + $hasPro = tutor()->has_pro;
38 +
39 + $unanswered_questions = tutor_utils()->unanswered_question_count();
40 + $unanswered_bubble = '';
41 + if ($unanswered_questions){
42 + $unanswered_bubble = '<span class="update-plugins count-'.$unanswered_questions.'"><span class="plugin-count">'.$unanswered_questions.'</span></span>';
43 + }
44 +
45 + $course_post_type = tutor()->course_post_type;
46 +
47 + $pro_text = '';
48 + if ($hasPro){
49 + $pro_text = ' '.__('Pro', 'tutor');
50 + }
51 +
52 + $enable_course_marketplace = (bool) tutils()->get_option('enable_course_marketplace');
53 +
54 + add_menu_page(__('Tutor LMS', 'tutor').$pro_text, __('Tutor LMS', 'tutor').$pro_text, 'manage_tutor_instructor', 'tutor', null,
55 + 'dashicons-welcome-learn-more', 2);
56 + add_submenu_page('tutor', __('Categories', 'tutor'), __('Categories', 'tutor'), 'manage_tutor', 'edit-tags.php?taxonomy=course-category&post_type='.$course_post_type, null );
57 +
58 + add_submenu_page('tutor', __('Tags', 'tutor'), __('Tags', 'tutor'), 'manage_tutor', 'edit-tags.php?taxonomy=course-tag&post_type='.$course_post_type, null );
59 +
60 + add_submenu_page('tutor', __('Students', 'tutor'), __('Students', 'tutor'), 'manage_tutor', 'tutor-students', array($this, 'tutor_students') );
61 +
62 + if ($enable_course_marketplace) {
63 + add_submenu_page('tutor', __('Instructors', 'tutor'), __('Instructors', 'tutor'), 'manage_tutor', 'tutor-instructors', array($this, 'tutor_instructors'));
64 + }
65 +
66 + add_submenu_page('tutor', __('Q & A', 'tutor'), __('Q & A '.$unanswered_bubble, 'tutor'), 'manage_tutor_instructor', 'question_answer', array($this, 'question_answer') );
67 +
68 + add_submenu_page('tutor', __('Quiz Attempts', 'tutor'), __('Quiz Attempts', 'tutor'), 'manage_tutor_instructor', 'tutor_quiz_attempts',array($this, 'quiz_attempts') );
69 +
70 + if ($enable_course_marketplace){
71 + add_submenu_page('tutor', __('Withdraw Requests', 'tutor'), __('Withdraw Requests', 'tutor'), 'manage_tutor_instructor', 'tutor_withdraw_requests', array($this, 'withdraw_requests') );
72 + }
73 +
74 + //add_submenu_page('tutor', __('Add-ons', 'tutor'), __('Add-ons', 'tutor'), 'manage_tutor', 'tutor-addons', array(new Addons(),'addons_page') );
75 + add_submenu_page( 'tutor', __( 'Add-ons', 'tutor' ), __( 'Add-ons', 'tutor' ), 'manage_tutor', 'tutor-addons', array( $this, 'enable_disable_addons' ) );
76 +
77 + do_action('tutor_admin_register');
78 +
79 + add_submenu_page('tutor', __('Settings', 'tutor'), __('Settings', 'tutor'), 'manage_tutor', 'tutor_settings', array($this, 'tutor_page') );
80 +
81 + add_submenu_page('tutor', __('Tools', 'tutor'), __('Tools', 'tutor'), 'manage_tutor', 'tutor-tools', array($this, 'tutor_tools') );
82 +
83 + if ( ! $hasPro){
84 + add_submenu_page( 'tutor', __( 'Get Pro', 'tutor' ), __( '<span class="dashicons dashicons-awards tutor-get-pro-text"></span> Get Pro', 'tutor' ), 'manage_options', 'tutor-get-pro', array($this, 'tutor_get_pro') );
85 + }
86 + }
87 +
88 + public function tutor_page(){
89 + $tutor_option = new Options();
90 + echo apply_filters('tutor/options/generated-html', $tutor_option->generate());
91 + }
92 +
93 + public function tutor_students(){
94 + include tutor()->path.'views/pages/students.php';
95 + }
96 +
97 + public function tutor_instructors(){
98 + include tutor()->path.'views/pages/instructors.php';
99 + }
100 +
101 + public function question_answer(){
102 + include tutor()->path.'views/pages/question_answer.php';
103 + }
104 +
105 + public function quiz_attempts(){
106 + include tutor()->path.'views/pages/quiz_attempts.php';
107 + }
108 +
109 + /**
110 + * Show the withdraw requests table
111 + *
112 + * @since v.1.2.0
113 + */
114 + public function withdraw_requests(){
115 + include tutor()->path.'views/pages/withdraw_requests.php';
116 + }
117 +
118 + public function enable_disable_addons(){
119 +
120 + if (defined('TUTOR_PRO_VERSION')) {
121 + include tutor()->path.'views/pages/enable_disable_addons.php';
122 + }else{
123 + include tutor()->path.'views/pages/tutor-pro-addons.php';
124 + }
125 + }
126 +
127 + public function tutor_tools(){
128 + $tutor_admin_tools_page = tutils()->array_get('tutor_admin_tools_page', $_GET);
129 + if ($tutor_admin_tools_page){
130 + include apply_filters('tutor_admin_tools_page', tutor()->path."views/pages/{$tutor_admin_tools_page}.php", $tutor_admin_tools_page);
131 + }else{
132 + $pages = apply_filters('tutor_tool_pages', array(
133 + 'tutor_pages' => array('title' => __('Tutor Pages', 'tutor') ),
134 + 'status' => __('Status', 'tutor'),
135 + ));
136 +
137 + $current_page = 'tutor_pages';
138 + $requested_page = sanitize_text_field(tutils()->array_get('sub_page', $_GET));
139 + if ($requested_page){
140 + $current_page = $requested_page;
141 + }
142 +
143 + include tutor()->path.'views/pages/tools.php';
144 + }
145 + }
146 +
147 + public function tutor_get_pro(){
148 + include tutor()->path.'views/pages/get-pro.php';
149 + }
150 +
151 + public function parent_menu_active( $parent_file ){
152 + $taxonomy = tutor_utils()->avalue_dot('taxonomy', $_GET);
153 + if ($taxonomy === 'course-category' || $taxonomy === 'course-tag'){
154 + return 'tutor';
155 + }
156 +
157 + return $parent_file;
158 + }
159 +
160 + public function submenu_file_active($submenu_file, $parent_file){
161 + $taxonomy = tutor_utils()->avalue_dot('taxonomy', $_GET);
162 + $course_post_type = tutor()->course_post_type;
163 +
164 + if ($taxonomy === 'course-category'){
165 + return 'edit-tags.php?taxonomy=course-category&post_type='.$course_post_type;
166 + }
167 + if ($taxonomy === 'course-tag'){
168 + return 'edit-tags.php?taxonomy=course-tag&post_type='.$course_post_type;
169 + }
170 +
171 +
172 + return $submenu_file;
173 + }
174 +
175 + /**
176 + * Filter posts for instructor
177 + */
178 + public function filter_posts_for_instructors(){
179 + if ( ! current_user_can('administrator') && current_user_can(tutor()->instructor_role)){
180 + remove_menu_page( 'edit-comments.php' ); //Comments
181 + add_filter( 'posts_clauses_request', array($this, 'posts_clauses_request') );
182 + }
183 + }
184 +
185 + public function posts_clauses_request($clauses){
186 + global $wpdb;
187 +
188 + $user_id = get_current_user_id();
189 +
190 + $get_assigned_courses_ids = $wpdb->get_col("SELECT meta_value from {$wpdb->usermeta} WHERE meta_key = '_tutor_instructor_course_id' AND user_id = {$user_id} ");
191 +
192 + $custom_author_query = "AND {$wpdb->posts}.post_author = {$user_id}";
193 + if (is_array($get_assigned_courses_ids) && count($get_assigned_courses_ids)){
194 + $in_query_pre = implode(',', $get_assigned_courses_ids);
195 + $custom_author_query = " AND ( {$wpdb->posts}.post_author = {$user_id} OR {$wpdb->posts}.ID IN({$in_query_pre}) ) ";
196 + }
197 +
198 + $clauses['where'] .= $custom_author_query;
199 +
200 + return $clauses;
201 + }
202 +
203 + /**
204 + * Prevent unauthorised course/lesson edit page by direct URL
205 + *
206 + * @since v.1.0.0
207 + */
208 + public function check_if_current_users_post(){
209 + if (current_user_can('administrator') || ! current_user_can(tutor()->instructor_role)) {
210 + return;
211 + }
212 +
213 + if (! empty($_GET['post']) ) {
214 + $get_post_id = (int) sanitize_text_field($_GET['post']);
215 + $get_post = get_post($get_post_id);
216 + $tutor_post_types = array(tutor()->course_post_type, tutor()->lesson_post_type);
217 +
218 + $current_user = get_current_user_id();
219 +
220 + if (in_array($get_post->post_type, $tutor_post_types) && $get_post->post_author != $current_user){
221 + global $wpdb;
222 +
223 + $get_assigned_courses_ids = (int) $wpdb->get_var("SELECT user_id from {$wpdb->usermeta} WHERE user_id = {$current_user} AND meta_key = '_tutor_instructor_course_id' AND meta_value = {$get_post_id} ");
224 +
225 + if ( ! $get_assigned_courses_ids){
226 + wp_die(__('Permission Denied', 'tutor'));
227 + }
228 +
229 + }
230 + }
231 + }
232 +
233 + /**
234 + * Status
235 + */
236 +
237 + public static function scan_template_files( $template_path = null ) {
238 + if ( ! $template_path){
239 + $template_path = tutor()->path.'templates/';
240 + }
241 +
242 + $files = @scandir( $template_path ); // @codingStandardsIgnoreLine.
243 + $result = array();
244 +
245 + if ( ! empty( $files ) ) {
246 + foreach ( $files as $key => $value ) {
247 + if ( ! in_array( $value, array( '.', '..', '.DS_Store' ), true ) ) {
248 + if ( is_dir( $template_path . DIRECTORY_SEPARATOR . $value ) ) {
249 + $sub_files = self::scan_template_files( $template_path . DIRECTORY_SEPARATOR . $value );
250 + foreach ( $sub_files as $sub_file ) {
251 + $result[] = $value . DIRECTORY_SEPARATOR . $sub_file;
252 + }
253 + } else {
254 + $result[] = $value;
255 + }
256 + }
257 + }
258 + }
259 + return $result;
260 + }
261 +
262 + /**
263 + * @return array
264 + *
265 + *
266 + */
267 + public static function template_overridden_files(){
268 + $template_files = self::scan_template_files();
269 +
270 + $override_files = array();
271 + foreach ($template_files as $file){
272 + $file_path = null;
273 + if (file_exists(trailingslashit(get_stylesheet_directory()).tutor()->template_path.$file)){
274 + $file_path = $file;
275 + }elseif (file_exists(trailingslashit(get_template_directory()).tutor()->template_path.$file)){
276 + $file_path = $file;
277 + }
278 +
279 + if ($file_path){
280 + $override_files[] = str_replace( WP_CONTENT_DIR.'/themes/', '', $file_path );
281 + }
282 + }
283 +
284 + return $override_files;
285 + }
286 +
287 + public static function get_environment_info(){
288 +
289 + // Figure out cURL version, if installed.
290 + $curl_version = '';
291 + if ( function_exists( 'curl_version' ) ) {
292 + $curl_version = curl_version();
293 + $curl_version = $curl_version['version'] . ', ' . $curl_version['ssl_version'];
294 + }
295 +
296 +
297 + // WP memory limit.
298 + $wp_memory_limit = tutor_utils()->let_to_num(WP_MEMORY_LIMIT);
299 + if ( function_exists( 'memory_get_usage' ) ) {
300 + $wp_memory_limit = max( $wp_memory_limit, tutor_utils()->let_to_num( @ini_get( 'memory_limit' ) ) );
301 + }
302 +
303 + $database_version = tutor_utils()->get_db_version();
304 +
305 + return array(
306 + 'home_url' => get_option( 'home' ),
307 + 'site_url' => get_option( 'siteurl' ),
308 + 'version' => tutor()->version,
309 + 'wp_version' => get_bloginfo( 'version' ),
310 + 'wp_multisite' => is_multisite(),
311 + 'wp_memory_limit' => $wp_memory_limit,
312 + 'wp_debug_mode' => ( defined( 'WP_DEBUG' ) && WP_DEBUG ),
313 + 'wp_cron' => ! ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ),
314 + 'language' => get_locale(),
315 + 'external_object_cache' => wp_using_ext_object_cache(),
316 + 'server_info' => isset( $_SERVER['SERVER_SOFTWARE'] ) ? wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) : '',
317 + 'php_version' => phpversion(),
318 + 'php_post_max_size' => tutor_utils()->let_to_num( ini_get( 'post_max_size' ) ),
319 + 'php_max_execution_time' => ini_get( 'max_execution_time' ),
320 + 'php_max_input_vars' => ini_get( 'max_input_vars' ),
321 + 'curl_version' => $curl_version,
322 + 'suhosin_installed' => extension_loaded( 'suhosin' ),
323 + 'max_upload_size' => wp_max_upload_size(),
324 + 'mysql_version' => $database_version['number'],
325 + 'mysql_version_string' => $database_version['string'],
326 + 'default_timezone' => date_default_timezone_get(),
327 + 'fsockopen_or_curl_enabled' => ( function_exists( 'fsockopen' ) || function_exists( 'curl_init' ) ),
328 + 'soapclient_enabled' => class_exists( 'SoapClient' ),
329 + 'domdocument_enabled' => class_exists( 'DOMDocument' ),
330 + 'gzip_enabled' => is_callable( 'gzopen' ),
331 + 'mbstring_enabled' => extension_loaded( 'mbstring' ),
332 + );
333 + }
334 +
335 +
336 + public function erase_tutor_data(){
337 + global $wpdb;
338 +
339 + $is_erase_data = tutor_utils()->get_option('delete_on_uninstall');
340 + /**D*/ //=> Deleting Data
341 +
342 + $plugin_file = tutor()->basename;
343 + if ($is_erase_data && current_user_can( 'deactivate_plugin', $plugin_file )) {
344 + /**
345 + * Deleting Post Type, Meta Data, taxonomy
346 + */
347 + $course_post_type = tutor()->course_post_type;
348 + $lesson_post_type = tutor()->lesson_post_type;
349 +
350 + $post_types = array(
351 + $course_post_type,
352 + $lesson_post_type,
353 + 'tutor_quiz',
354 + 'tutor_enrolled',
355 + 'topics',
356 + 'tutor_enrolled',
357 + 'tutor_announcements',
358 + );
359 +
360 + $post_type_strings = "'".implode("','", $post_types)."'";
361 + $tutor_posts = $wpdb->get_col("SELECT ID from {$wpdb->posts} WHERE post_type in({$post_type_strings}) ;");
362 +
363 + if (is_array($tutor_posts) && count($tutor_posts)){
364 + foreach ($tutor_posts as $post_id){
365 + //Delete categories
366 + $terms = wp_get_object_terms( $post_id, 'course-category' );
367 + foreach( $terms as $term ){
368 + /**D*/ wp_remove_object_terms( $post_id, array( $term->term_id ), 'course-category' );
369 + }
370 +
371 + //Delete tags if available
372 + $terms = wp_get_object_terms( $post_id, 'course-tag' );
373 + foreach( $terms as $term ){
374 + /**D*/ wp_remove_object_terms( $post_id, array( $term->term_id ), 'course-tag' );
375 + }
376 +
377 + //Delete All Meta
378 + /**D*/ $wpdb->delete($wpdb->postmeta, array('post_id' => $post_id) );
379 + /**D*/ $wpdb->delete($wpdb->posts, array('ID' => $post_id) );
380 + }
381 + }
382 +
383 + /**
384 + * Deleting Comments (reviews, questions, quiz_answers, etc)
385 + */
386 + $tutor_comments = $wpdb->get_col("SELECT comment_ID from {$wpdb->comments} WHERE comment_agent = 'comment_agent' ;");
387 + $comments_ids_strings = "'".implode("','", $tutor_comments)."'";
388 + if (is_array($tutor_comments) && count($tutor_comments)){
389 + /**D*/ $wpdb->query("DELETE from {$wpdb->commentmeta} WHERE comment_ID in({$comments_ids_strings}) ");
390 + }
391 + /**D*/ $wpdb->delete($wpdb->comments, array('comment_agent' => 'comment_agent'));
392 +
393 + /**
394 + * Delete Options
395 + */
396 +
397 + /**D*/ delete_option('tutor_option');
398 + /**D*/ $wpdb->delete($wpdb->usermeta, array('meta_key' => '_is_tutor_student'));
399 + /**D*/ $wpdb->delete($wpdb->usermeta, array('meta_key' => '_tutor_instructor_approved'));
400 + /**D*/ $wpdb->delete($wpdb->usermeta, array('meta_key' => '_tutor_instructor_status'));
401 + /**D*/ $wpdb->delete($wpdb->usermeta, array('meta_key' => '_is_tutor_instructor'));
402 + /**D*/ $wpdb->query("DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE '%_tutor_completed_lesson_id_%' ");
403 +
404 + //Deleting Table
405 + $prefix = $wpdb->prefix;
406 + /**D*/ $wpdb->query("DROP TABLE IF EXISTS {$prefix}tutor_quiz_attempts, {$prefix}tutor_quiz_attempt_answers, {$prefix}tutor_quiz_questions, {$prefix}tutor_quiz_question_answers, {$prefix}tutor_earnings, {$prefix}tutor_withdraws ");
407 +
408 + deactivate_plugins($plugin_file);
409 + }
410 +
411 + wp_redirect('plugins.php');
412 + die();
413 + }
414 +
415 + public function plugin_action_links($actions){
416 + $hasPro = tutor()->has_pro;
417 +
418 + if(!$hasPro){
419 + $actions['tutor_pro_link'] = '<a href="https://www.themeum.com/product/tutor-lms/#pricing?utm_source=tutor_plugin_action_link&utm_medium=wordpress_dashboard&utm_campaign=go_premium" target="_blank"><span
420 + style="color: #ff7742; font-weight: bold;">' . __('Upgrade to Pro', 'wp-megamenu') . '</span></a>';
421 + }
422 +
423 + $is_erase_data = tutor_utils()->get_option('delete_on_uninstall');
424 +
425 + if ($is_erase_data) {
426 + $plugin_file = tutor()->basename;
427 + if ( current_user_can( 'deactivate_plugin', $plugin_file ) ) {
428 + if ( isset( $actions['deactivate'] ) ) {
429 + $actions['deactivate'] = '<a href="admin.php?page=tutor-tools&tutor_admin_tools_page=uninstall">' . __('Uninstall', 'tutor') . '</a>';
430 + }
431 + }
432 + }
433 +
434 + $actions['settings'] = '<a href="admin.php?page=tutor_settings">' . __('Settings', 'tutor') . '</a>';
435 + return $actions;
436 + }
437 +
438 + public function plugin_row_meta($plugin_meta, $plugin_file){
439 +
440 + if ($plugin_file === tutor()->basename) {
441 + $plugin_meta[] = sprintf( '<a href="%s">%s</a>',
442 + esc_url( 'https://docs.themeum.com/tutor-lms/?utm_source=tutor&utm_medium=plugins_installation_list&utm_campaign=plugin_docs_link' ),
443 + __( '<strong style="color: #03bd24">Documentation</strong>', 'tutor' )
444 + );
445 + $plugin_meta[] = sprintf( '<a href="%s">%s</a>',
446 + esc_url( 'https://www.themeum.com/support-forums/?utm_source=tutor&utm_medium=plugins_installation_list&utm_campaign=plugin_support_link' ),
447 + __( '<strong style="color: #03bd24">Get Support</strong>', 'tutor' )
448 + );
449 + }
450 +
451 + return $plugin_meta;
452 + }
453 +
454 + /**
455 + * @param $footer_text
456 + *
457 + * @return string
458 + *
459 + * Add footer text only on tutor pages
460 + */
461 + public function admin_footer_text( $footer_text ) {
462 + $current_screen = get_current_screen();
463 +
464 + /**
465 + * We are making sure that this message will be only on Tutor Admin page
466 + */
467 + if ( apply_filters( 'tutor_display_admin_footer_text', (tutor_utils()->array_get('parent_base', $current_screen) === 'tutor' ) ) ) {
468 + $footer_text = sprintf(
469 + __( 'If you like %1$s please leave us a %2$s rating. A huge thanks in advance!', 'tutor' ),
470 + sprintf( '<strong>%s</strong>', esc_html__( 'Tutor LMS', 'tutor' ) ),
471 + '<a href="https://wordpress.org/support/plugin/tutor/reviews?rate=5#new-post" target="_blank" class="tutor-rating-link">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
472 + );
473 + }
474 +
475 + return $footer_text;
476 + }
477 +
478 +
479 + public function register_course_widget(){
480 + register_widget( 'Tutor\Course_Widget' );
481 + }
482 +
483 +
484 +}