Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/tutor-pro/classes/General.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + <?php
2 + /**
3 + * General class for hook logic
4 + *
5 + * @package TutorPro
6 + *
7 + * @since 2.0.0
8 + */
9 +
10 + namespace TUTOR_PRO;
11 +
12 + use Tutor\Helpers\PluginInstaller;
13 + use Tutor\Helpers\HttpHelper;
14 +
15 + use TUTOR\Input;
16 + use Tutor\Models\CourseModel;
17 + use Tutor\Traits\JsonResponse;
18 + use TUTOR\User;
19 + use WP_Error;
20 +
21 + if ( ! defined( 'ABSPATH' ) ) {
22 + exit;
23 + }
24 +
25 + /**
26 + * Class General
27 + *
28 + * @since 2.0.0
29 + */
30 + class General {
31 +
32 + use JsonResponse;
33 +
34 + /**
35 + * Register hooks
36 + *
37 + * @return void
38 + */
39 + public function __construct() {
40 + add_action( 'tutor_action_tutor_add_course_builder', array( $this, 'tutor_add_course_builder' ) );
41 + add_filter( 'frontend_course_create_url', array( $this, 'frontend_course_create_url' ) );
42 + add_filter( 'template_include', array( $this, 'fs_course_builder' ), 99 );
43 +
44 + add_filter( 'tutor/options/extend/attr', array( $this, 'extend_settings_option' ) );
45 + add_filter( 'tutor_course_builder_logo_src', array( $this, 'tutor_course_builder_logo_src' ) );
46 + add_filter( 'tutor_email_logo_src', array( $this, 'tutor_email_logo_src' ) );
47 + add_filter( 'tutor_pages', array( $this, 'add_login_page' ), 10, 1 );
48 +
49 + add_action( 'tutor_after_lesson_completion_button', array( $this, 'add_course_completion_button' ), 10, 4 );
50 +
51 + add_action( 'tutor_is_error_before_course_update', array( $this, 'tutor_is_error_before_course_update' ), 10, 2 );
52 + add_action( 'wp_ajax_tutor_install_plugin', array( $this, 'ajax_tutor_install_plugin' ) );
53 +
54 + add_filter( 'tutor_addons_lists_config', array( $this, 'manage_addon_depend_plugins' ), PHP_INT_MAX );
55 +
56 + add_filter( 'init', array( $this, 'disable_author_support_for_instructors' ), 10, 2 );
57 + }
58 +
59 + /**
60 + * Show course completion button after all course content done.
61 + *
62 + * @since 2.4.0
63 + *
64 + * @param int $course_id course id.
65 + * @param int $user_id user id.
66 + * @param bool $is_course_completed course completed or not.
67 + * @param array $course_stats course progress stats.
68 + *
69 + * @return void
70 + */
71 + public function add_course_completion_button( $course_id, $user_id, $is_course_completed, $course_stats ) {
72 + if ( false === $is_course_completed
73 + && $course_stats['completed_count'] === $course_stats['total_count']
74 + && CourseModel::can_complete_course( $course_id, $user_id ) ) {
75 + ?>
76 + <div class="tutor-topbar-complete-btn tutor-mr-20">
77 + <form method="post">
78 + <?php wp_nonce_field( tutor()->nonce_action, tutor()->nonce, false ); ?>
79 + <input type="hidden" name="course_id" value="<?php echo esc_attr( $course_id ); ?>"/>
80 + <input type="hidden" name="tutor_action" value="tutor_complete_course"/>
81 + <button type="submit" class="tutor-topbar-mark-btn tutor-btn tutor-btn-primary tutor-ws-nowrap" name="complete_course" value="complete_course">
82 + <span class="tutor-icon-circle-mark-line tutor-mr-8" area-hidden="true"></span>
83 + <span><?php esc_html_e( 'Complete Course', 'tutor-pro' ); ?></span>
84 + </button>
85 + </form>
86 + </div>
87 + <?php
88 + }
89 + }
90 +
91 + /**
92 + * Add login page
93 + *
94 + * @since 2.1.0
95 + *
96 + * @param array $pages page list.
97 + *
98 + * @return array
99 + */
100 + public function add_login_page( array $pages ) {
101 + return array( 'tutor_login_page' => __( 'Tutor Login', 'tutor-pro' ) ) + $pages;
102 + }
103 +
104 + /**
105 + * Process course submission from frontend course builder
106 + *
107 + * @since v.1.3.4
108 + *
109 + * @return void
110 + */
111 + public function tutor_add_course_builder() {
112 + tutor_utils()->checking_nonce();
113 +
114 + $user_id = get_current_user_id();
115 + $course_post_type = tutor()->course_post_type;
116 +
117 + //phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
118 + $course_ID = Input::post( 'course_ID', 0, Input::TYPE_INT );
119 + $post_ID = Input::post( 'post_ID', 0, Input::TYPE_INT );
120 +
121 + if ( ! tutor_utils()->can_user_edit_course( $user_id, $post_ID ) ) {
122 + wp_send_json_error( array( 'message' => __( 'Access Denied', 'tutor-pro' ) ) );
123 + }
124 +
125 + $post = get_post( $post_ID );
126 + $update = true;
127 +
128 + /**
129 + * Update the post
130 + */
131 +
132 + $content = Input::post( 'content', '', Input::TYPE_KSES_POST );
133 + $title = Input::post( 'title', '' );
134 + $tax_input = tutor_utils()->array_get( 'tax_input', $_POST ); //phpcs:ignore
135 + $slug = Input::post( 'post_name', '' );
136 +
137 + $post_data = array(
138 + 'ID' => $post_ID,
139 + 'post_title' => $title,
140 + 'post_content' => $content,
141 + 'post_name' => $slug,
142 + );
143 +
144 + // Publish or Pending...
145 + $message = null;
146 + $show_modal = true;
147 + $submit_action = Input::post( 'course_submit_btn', '' );
148 +
149 + if ( 'save_course_as_draft' === $submit_action ) {
150 + $post_data['post_status'] = 'draft';
151 + $message = __( 'Course has been saved as a draft.', 'tutor-pro' );
152 + $show_modal = false;
153 + } elseif ( 'submit_for_review' === $submit_action ) {
154 + $post_data['post_status'] = 'pending';
155 + $message = __( 'Course has been submitted for review.', 'tutor-pro' );
156 + } elseif ( 'publish_course' === $submit_action ) {
157 + $can_publish_course = (bool) tutor_utils()->get_option( 'instructor_can_publish_course' );
158 + if ( $can_publish_course || current_user_can( 'administrator' ) ) {
159 + $post_data['post_status'] = 'publish';
160 + $message = __( 'Course has been published.', 'tutor-pro' );
161 + } else {
162 + $post_data['post_status'] = 'pending';
163 + $message = __( 'Course has been submitted for review.', 'tutor-pro' );
164 + }
165 + }
166 +
167 + if ( $message ) {
168 + update_user_meta( $user_id, 'tutor_frontend_course_message_expires', time() + 5 );
169 + update_user_meta(
170 + $user_id,
171 + 'tutor_frontend_course_action_message',
172 + array(
173 + 'message' => $message,
174 + 'show_modal' => $show_modal,
175 + )
176 + );
177 + }
178 + wp_update_post( $post_data );
179 +
180 + /**
181 + * Setting Thumbnail
182 + */
183 + $_thumbnail_id = Input::post( 'tutor_course_thumbnail_id', 0, Input::TYPE_INT );
184 + self::update_post_thumbnail( $post_ID, $_thumbnail_id );
185 +
186 + /**
187 + * Adding taxonomy
188 + */
189 + if ( tutor_utils()->count( $tax_input ) ) {
190 + foreach ( $tax_input as $taxonomy => $tags ) {
191 + $taxonomy_obj = get_taxonomy( $taxonomy );
192 + if ( ! $taxonomy_obj ) {
193 + /* translators: %s: taxonomy name */
194 + _doing_it_wrong( __FUNCTION__, sprintf( __( 'Invalid taxonomy: %s.' ), $taxonomy ), '4.4.0' );//phpcs:ignore
195 + continue;
196 + }
197 +
198 + // array = hierarchical, string = non-hierarchical.
199 + if ( is_array( $tags ) ) {
200 + $tags = array_filter( $tags );
201 + }
202 + wp_set_post_terms( $post_ID, $tags, $taxonomy );
203 + }
204 + }
205 +
206 + do_action( 'save_tutor_course', $post_ID, $post_data );
207 +
208 + if ( wp_doing_ajax() ) {
209 + wp_send_json_success();
210 + } else {
211 +
212 + /**
213 + * If update request not comes from edit page, redirect it to edit page
214 + */
215 + $edit_mode = Input::get( 'course_ID', 0, Input::TYPE_INT );
216 + if ( ! $edit_mode ) {
217 + $edit_page_url = add_query_arg( array( 'course_ID' => $post_ID ) );
218 + wp_redirect( $edit_page_url );
219 + die();
220 + }
221 +
222 + /**
223 + * Finally redirect it to previous page to avoid multiple post request
224 + */
225 + $redirect_option_enabled = (bool) tutor_utils()->get_option( 'enable_redirect_on_course_publish_from_frontend' );
226 + if ( 'publish_course' === $submit_action && true === $redirect_option_enabled ) {
227 + $target_url = tutor_utils()->tutor_dashboard_url( 'my-courses' );
228 + wp_safe_redirect( $target_url );
229 + } else {
230 + wp_safe_redirect( tutor_utils()->referer() );
231 + }
232 +
233 + die();
234 + }
235 + die();
236 + }
237 +
238 +
239 + /**
240 + * Frontend Course builder url
241 + *
242 + * @return string
243 + */
244 + public function frontend_course_create_url() {
245 + return tutor_utils()->get_tutor_dashboard_page_permalink( 'create-course' );
246 + }
247 +
248 +
249 + /**
250 + * Include Dashboard
251 + *
252 + * @param string $template template.
253 + *
254 + * @return bool|string
255 + */
256 + public function fs_course_builder( $template ) {
257 + global $wp_query;
258 +
259 + if ( $wp_query->is_page ) {
260 + $student_dashboard_page_id = (int) tutor_utils()->get_option( 'tutor_dashboard_page_id' );
261 + if ( get_the_ID() === $student_dashboard_page_id ) {
262 + if ( tutor_utils()->array_get( 'tutor_dashboard_page', $wp_query->query_vars ) === 'create-course' ) {
263 + if ( is_user_logged_in() ) {
264 + $template = tutor_get_template( 'dashboard.create-course' );
265 + } else {
266 + $template = tutor_get_template( 'login' );
267 + }
268 + }
269 + }
270 + }
271 +
272 + return $template;
273 + }
274 +
275 +
276 + /**
277 + * Extend settings options.
278 + *
279 + * @param array $attr settings options.
280 + *
281 + * @return array
282 + */
283 + public function extend_settings_option( $attr ) {
284 +
285 + $pages = tutor_utils()->get_pages();
286 +
287 + array_unshift(
288 + $attr['design']['blocks']['block_course']['fields'],
289 + array(
290 + 'key' => 'tutor_frontend_course_page_logo_id',
291 + 'type' => 'upload_full',
292 + 'label' => __( 'Course Builder Page Logo', 'tutor-pro' ),
293 + 'desc' => array(
294 + 'file_size' => __( '700x430 pixels', 'tutor-pro' ),
295 + 'file_support' => __( '.jpg, .jpeg, or .png', 'tutor-pro' ),
296 + ),
297 + )
298 + );
299 +
300 + $attr['advanced']['blocks'][0]['fields'][] = array(
301 + 'key' => 'hide_admin_bar_for_users',
302 + 'type' => 'toggle_switch',
303 + 'label' => __( 'Hide Admin Bar and Restrict Access to WP Admin for Instructors', 'tutor-pro' ),
304 + 'label_title' => '',
305 + 'default' => 'off',
306 + 'desc' => __( 'Enable to hide WordPress Admin Bar from frontend and prevent instructors from accessing WP Admin panel.', 'tutor-pro' ),
307 + );
308 +
309 + /**
310 + * Settings option added in Course > Course section.
311 + *
312 + * @since 2.0.6
313 + */
314 + $attr['course']['blocks']['block_course']['fields'][] = array(
315 + 'key' => 'enable_redirect_on_course_publish_from_frontend',
316 + 'type' => 'toggle_switch',
317 + 'label' => __( 'Redirect Instructor to "My Courses" once Publish button is Clicked', 'tutor-pro' ),
318 + 'default' => 'off',
319 + 'label_title' => '',
320 + 'desc' => __( 'Enable to Redirect an Instructor to the "My Courses" Page once he clicks on the "Publish" button', 'tutor-pro' ),
321 + );
322 +
323 + /**
324 + * Hide quiz attempts details from frontend
325 + *
326 + * @since 2.0.7
327 + */
328 + $attr['course']['blocks']['block_quiz']['fields'][] = array(
329 + 'key' => 'hide_quiz_details',
330 + 'type' => 'toggle_switch',
331 + 'label' => __( 'Hide Quiz Details From Students', 'tutor-pro' ),
332 + 'default' => 'off',
333 + 'desc' => __( 'If enabled, the students will not be able to see their quiz attempts details', 'tutor-pro' ),
334 + );
335 +
336 + /**
337 + * Show enrollment box on top of page when mobile view
338 + *
339 + * @since 2.0.9
340 + */
341 + $attr['design']['blocks']['course-details']['fields'][] = array(
342 + 'key' => 'enrollment_box_position_in_mobile',
343 + 'type' => 'select',
344 + 'label' => __( 'Position of the Enrollment Box in Mobile View', 'tutor-pro' ),
345 + 'default' => 'bottom',
346 + 'options' => array(
347 + 'top' => __( 'On Page Top', 'tutor-pro' ),
348 + 'bottom' => __( 'On Page Bottom', 'tutor-pro' ),
349 + ),
350 + 'desc' => __( 'You can decide where you want to show Enrollment Box on your Course Details page by selecting an option from here', 'tutor-pro' ),
351 + );
352 +
353 + /**
354 + * Login page option
355 + *
356 + * @since 2.1.0
357 + */
358 + $login_option = array(
359 + 'key' => 'tutor_login_page',
360 + 'type' => 'select',
361 + 'label' => __( 'Login Page', 'tutor-pro' ),
362 + 'default' => '0',
363 + 'options' => $pages,
364 + 'desc' => __( 'This page will be used as the login page for both the students and the instructors.', 'tutor-pro' ),
365 + 'searchable' => true,
366 + );
367 + /**
368 + * Invoice generate settings for manual enrollment
369 + *
370 + * @since 2.1.4
371 + */
372 + $invoice_options = array(
373 + 'key' => 'tutor_woocommerce_invoice',
374 + 'type' => 'toggle_switch',
375 + 'label' => __( 'Generate WooCommerce Order', 'tutor-pro' ),
376 + 'label_title' => '',
377 + 'default' => 'off',
378 + 'desc' => __( 'If you want to create an WooCommerce Order to keep Track of your Sales Report for Manual Enrolment', 'tutor-pro' ),
379 + );
380 +
381 + tutor_utils()->add_option_after(
382 + 'enable_tutor_native_login',
383 + $attr['advanced']['blocks'][1]['fields'],
384 + $login_option
385 + );
386 + tutor_utils()->add_option_after(
387 + 'tutor_woocommerce_order_auto_complete',
388 + $attr['monetization']['blocks']['block_woocommerce']['fields'],
389 + $invoice_options
390 + );
391 +
392 + $attr['design']['blocks']['course-details']['fields'][0]['group_options'][] = array(
393 + 'key' => 'enable_sticky_sidebar',
394 + 'type' => 'toggle_single',
395 + 'label' => __( 'Sticky Sidebar', 'tutor-pro' ),
396 + 'label_title' => __( 'Disable', 'tutor-pro' ),
397 + 'default' => 'off',
398 + 'desc' => __( 'Enable sticky sidebar on course details on scroll', 'tutor-pro' ),
399 + );
400 +
401 + // TODO implement later.
402 + /**
403 + * $attr['design']['blocks']['course-details']['fields'][0]['group_options'][] = array(
404 + * 'key' => 'enable_sticky_topbar',
405 + * 'type' => 'toggle_single',
406 + * 'label' => __( 'Sticky Topbar', 'tutor-pro' ),
407 + * 'label_title' => __( 'Disable', 'tutor-pro' ),
408 + * 'default' => 'off',
409 + * 'desc' => __( 'Enable sticky topbar on course details on scroll', 'tutor-pro' ),
410 + * );
411 + */
412 +
413 + /**
414 + * Lesson video completion control.
415 + *
416 + * @since 2.2.4
417 + */
418 + tutor_utils()->add_option_after(
419 + 'enable_lesson_classic_editor',
420 + $attr['course']['blocks']['block_lesson']['fields'],
421 + array(
422 + 'key' => 'control_video_lesson_completion',
423 + 'type' => 'toggle_switch',
424 + 'label' => __( 'Video Lesson Completion Control', 'tutor-pro' ),
425 + 'default' => 'off',
426 + 'desc' => __( 'Enable to set the minimum video watch % for lesson completion, only works with Tutor Player.', 'tutor-pro' ),
427 + 'toggle_fields' => 'required_percentage_to_complete_video_lesson',
428 + )
429 + );
430 +
431 + tutor_utils()->add_option_after(
432 + 'control_video_lesson_completion',
433 + $attr['course']['blocks']['block_lesson']['fields'],
434 + array(
435 + 'key' => 'required_percentage_to_complete_video_lesson',
436 + 'type' => 'number',
437 + 'number_type' => 'integer',
438 + 'label' => __( 'Set Required Percentage', 'tutor-pro' ),
439 + 'default' => 80,
440 + 'max' => 100,
441 + 'desc' => __( 'Specify the minimum video watch % learners must watch to mark the lesson as complete.', 'tutor-pro' ),
442 + )
443 + );
444 +
445 + /**
446 + * New option added to restrict instructors from changing author
447 + *
448 + * @since 3.2.0
449 + */
450 + $attr['general']['blocks'][3]['fields'][] = array(
451 + 'key' => 'instructor_can_change_course_author',
452 + 'type' => 'toggle_switch',
453 + 'label' => __( 'Allow Instructors to Change Course Author', 'tutor-pro' ),
454 + 'label_title' => '',
455 + 'default' => 'on',
456 + 'desc' => __( 'If enabled, instructors can change the course author for their courses.', 'tutor-pro' ),
457 + );
458 +
459 + return $attr;
460 + }
461 +
462 + /**
463 + * Course builder logo src
464 + *
465 + * @param string $url url.
466 + *
467 + * @return string
468 + */
469 + public function tutor_course_builder_logo_src( $url ) {
470 + $media_id = (int) get_tutor_option( 'tutor_frontend_course_page_logo_id' );
471 + if ( $media_id ) {
472 + return wp_get_attachment_url( $media_id );
473 + }
474 + return $url;
475 + }
476 +
477 + /**
478 + * Email logo src
479 + *
480 + * @param string $url url.
481 + * @param mixed $size size.
482 + *
483 + * @return string
484 + */
485 + public function tutor_email_logo_src( $url = null, $size = null ) {
486 + $hotlink_protection = (bool) get_tutor_option( ContentSecurity::HOTLINKING_OPTION );
487 + $media_id_or_url = get_tutor_option( 'tutor_email_template_logo_id' );
488 +
489 + if ( $hotlink_protection ) {
490 + return esc_url( $media_id_or_url );
491 + }
492 +
493 + if ( (int) $media_id_or_url ) {
494 + return wp_get_attachment_image_url( $media_id_or_url, 'full' );
495 + }
496 +
497 + return $url;
498 + }
499 +
500 + /**
501 + * Update post thumbnail
502 + *
503 + * It will update post thumbnail meta if thumbnail_id is set
504 + * otherwise it will remove existing meta
505 + *
506 + * Used from frontend course & bundle builder
507 + *
508 + * @since 2.2.0
509 + *
510 + * @param int $post_id required post id.
511 + * @param int $thumbnail_id thumbnail id.
512 + *
513 + * @return void
514 + */
515 + public static function update_post_thumbnail( int $post_id, int $thumbnail_id = 0 ) {
516 + $thumbnail_id = (int) sanitize_text_field( $thumbnail_id );
517 + $product_id = tutor_utils()->get_course_product_id( $post_id );
518 +
519 + if ( $thumbnail_id ) {
520 + update_post_meta( $post_id, '_thumbnail_id', $thumbnail_id );
521 +
522 + // Update product thumbnail.
523 + set_post_thumbnail( $product_id, $thumbnail_id );
524 + } else {
525 + delete_post_meta( $post_id, '_thumbnail_id' );
526 + }
527 + }
528 +
529 + /**
530 + * Restriction added for instructors to change author
531 + *
532 + * @param mixed $is_error error.
533 + *
534 + * @param array $params course params.
535 + *
536 + * @since 3.2.0
537 + */
538 + public function tutor_is_error_before_course_update( $is_error, $params ) {
539 + if ( ! isset( $params['course_id'] ) ) {
540 + return $is_error;
541 + }
542 +
543 + $course_id = (int) $params['course_id'];
544 + $course = get_post( $course_id );
545 + $is_course_author_modified = $course->post_author !== $params['post_author'];
546 + $can_instructors_change_course_author = (bool) tutor_utils()->get_option( 'instructor_can_change_course_author', true );
547 + if ( $is_course_author_modified && User::is_only_instructor() && ! $can_instructors_change_course_author ) {
548 + $is_error = new WP_Error( '401', __( 'You don\'t have permission to change author.', 'tutor-pro' ) );
549 + }
550 + return $is_error;
551 + }
552 +
553 + /**
554 + * Checks if a plugin is available, installed, and active.
555 + *
556 + * @return void
557 + *
558 + * @since 3.2.0
559 + */
560 + public function ajax_tutor_install_plugin() {
561 +
562 + tutor_utils()->checking_nonce();
563 + tutor_utils()->check_current_user_capability();
564 +
565 + $plugin_slug = sanitize_text_field( Input::post( 'plugin_slug', '' ) );
566 +
567 + if ( empty( $plugin_slug ) ) {
568 + $this->json_response( __( 'Plugin slug is required', 'tutor-pro' ), '', HttpHelper::STATUS_BAD_REQUEST );
569 + }
570 +
571 + // If Plugin doesn't exist, install it.
572 + if ( ! file_exists( WP_PLUGIN_DIR . '/' . $plugin_slug ) ) {
573 +
574 + list( $is_successful, $response ) = array_values( PluginInstaller::get_downloadable_url( $plugin_slug ) );
575 +
576 + if ( ! $is_successful ) {
577 + $this->json_response( $response, '', HttpHelper::STATUS_BAD_REQUEST );
578 + }
579 +
580 + if ( PluginInstaller::install_or_upgrade_plugin( $response ) ) {
581 + $this->json_response( __( 'Plugin installed successfully', 'tutor-pro' ), '', HttpHelper::STATUS_OK );
582 + }
583 +
584 + $this->json_response( __( 'Plugin installation failed', 'tutor-pro' ), '', HttpHelper::STATUS_BAD_REQUEST );
585 + }
586 +
587 + // If plugin exists but not activated, activate it.
588 + if ( ! is_plugin_active( $plugin_slug ) ) {
589 +
590 + $activate = activate_plugin( $plugin_slug, '', false, true );
591 +
592 + if ( is_wp_error( $activate ) ) {
593 + $this->json_response( $activate->get_error_message(), '', HttpHelper::STATUS_BAD_REQUEST );
594 + }
595 +
596 + $this->json_response( __( 'Plugin activated successfully', 'tutor-pro' ), '', HttpHelper::STATUS_OK );
597 + }
598 +
599 + $this->json_response( __( 'Plugin is already activated', 'tutor-pro' ), '', HttpHelper::STATUS_OK );
600 + }
601 +
602 + /**
603 + * Set depend_plugins empty if required plugin already active
604 + *
605 + * @since 3.2.0
606 + *
607 + * @param array $addons Addon config array.
608 + *
609 + * @return array Addon config array
610 + */
611 + public function manage_addon_depend_plugins( $addons ) {
612 + $addons = array_map(
613 + function( $addon ) {
614 + if ( ! empty( $addon['depend_plugins'] ) ) {
615 + $addon['is_dependents_installed'] = true;
616 +
617 + $dependent_plugins = $addon['depend_plugins'];
618 + foreach ( $dependent_plugins as $basename => $value ) {
619 + $depended_plugin_dir = WP_PLUGIN_DIR . '/' . $basename;
620 + if ( ! file_exists( $depended_plugin_dir ) ) {
621 + $addon['is_dependents_installed'] = false;
622 + }
623 +
624 + if ( is_plugin_active( $basename ) ) {
625 + unset( $addon['depend_plugins'][ $basename ] );
626 + }
627 + }
628 + }
629 +
630 + return $addon;
631 + },
632 + $addons
633 + );
634 +
635 + return $addons;
636 + }
637 +
638 + /**
639 + * Restriction added for instructors to change course author,
640 + *
641 + * @since 3.2.0
642 + */
643 + public function disable_author_support_for_instructors() {
644 + $can_instructors_change_course_author = (bool) tutor_utils()->get_option( 'instructor_can_change_course_author', true );
645 + if ( User::is_only_instructor() && ! $can_instructors_change_course_author ) {
646 + remove_post_type_support( 'courses', 'author' );
647 + }
648 + }
649 + }
650 +