| @@ -4,11 +4,17 @@ | ||
| 4 | 4 | if ( ! defined( 'ABSPATH' ) ) |
| 5 | 5 | exit; |
| 6 | 6 | |
| 7 | 7 | class Course extends Tutor_Base { |
| 8 | + | |
| 9 | + private $additional_meta=array( | |
| 10 | + '_tutor_disable_qa', | |
| 11 | + '_tutor_is_public_course' | |
| 12 | + ); | |
| 13 | + | |
| 8 | 14 | public function __construct() { |
| 9 | 15 | parent::__construct(); |
| 10 | - | |
| 16 | + | |
| 11 | 17 | add_action( 'add_meta_boxes', array($this, 'register_meta_box') ); |
| 12 | 18 | add_action('save_post_'.$this->course_post_type, array($this, 'save_course_meta'), 10, 2); |
| 13 | 19 | add_action('wp_ajax_tutor_add_course_topic', array($this, 'tutor_add_course_topic')); |
| 14 | 20 | add_action('wp_ajax_tutor_update_topic', array($this, 'tutor_update_topic')); |
| @@ -27,40 +33,200 @@ | ||
| 27 | 33 | //Modal Perform |
| 28 | 34 | add_action('wp_ajax_tutor_load_instructors_modal', array($this, 'tutor_load_instructors_modal')); |
| 29 | 35 | add_action('wp_ajax_tutor_add_instructors_to_course', array($this, 'tutor_add_instructors_to_course')); |
| 30 | 36 | add_action('wp_ajax_detach_instructor_from_course', array($this, 'detach_instructor_from_course')); |
| 37 | + | |
| 38 | + /** | |
| 39 | + * Frontend Dashboard | |
| 40 | + */ | |
| 41 | + add_action('wp_ajax_tutor_delete_dashboard_course', array($this, 'tutor_delete_dashboard_course')); | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * Gutenberg author support | |
| 45 | + */ | |
| 46 | + add_filter('wp_insert_post_data', array($this, 'tutor_add_gutenberg_author'), '99', 2); | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * Frontend metabox supports for course builder | |
| 50 | + * @since v.1.3.4 | |
| 51 | + */ | |
| 52 | + add_action('tutor/dashboard_course_builder_form_field_after', array($this, 'register_meta_box_in_frontend')); | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * Do Stuff for the course save from frontend | |
| 56 | + */ | |
| 57 | + add_action('save_tutor_course', array($this, 'attach_product_with_course'), 10, 2); | |
| 58 | + | |
| 59 | + /** | |
| 60 | + * Add course level to course settings | |
| 61 | + * @since v.1.4.1 | |
| 62 | + */ | |
| 63 | + add_action('tutor_course/settings_tab_content/after/general', array($this, 'add_course_level_to_settings')); | |
| 64 | + | |
| 65 | + /** | |
| 66 | + * Enable Disable Course Details Page Feature | |
| 67 | + * @since v.1.4.8 | |
| 68 | + */ | |
| 69 | + $this->course_elements_enable_disable(); | |
| 70 | + | |
| 71 | + /** | |
| 72 | + * @since v.1.4.8 | |
| 73 | + * Check if course starting, set meta if starting | |
| 74 | + */ | |
| 75 | + add_action('tutor_lesson_load_before', array($this, 'tutor_lesson_load_before')); | |
| 76 | + | |
| 77 | + /** | |
| 78 | + * @since v.1.4.9 | |
| 79 | + * Filter product in shop page | |
| 80 | + */ | |
| 81 | + $this->filter_product_in_shop_page(); | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * Remove the course price if enrolled | |
| 85 | + * @since 1.5.8 | |
| 86 | + */ | |
| 87 | + add_filter('tutor_course_price', array($this, 'remove_price_if_enrolled')); | |
| 88 | + | |
| 89 | + /** | |
| 90 | + * Remove course complete button if course completion is strict mode | |
| 91 | + * @since v.1.6.1 | |
| 92 | + */ | |
| 93 | + add_filter('tutor_course/single/complete_form', array($this, 'tutor_lms_hide_course_complete_btn')); | |
| 94 | + add_filter('get_gradebook_generate_form_html', array($this, 'get_generate_greadbook')); | |
| 95 | + | |
| 96 | + /** | |
| 97 | + * Add social share content in header | |
| 98 | + * @since v.1.6.3 | |
| 99 | + */ | |
| 100 | + add_action('wp_head', array($this, 'social_share_content')); | |
| 101 | + | |
| 102 | + /** | |
| 103 | + * Delete course data after deleted course | |
| 104 | + * @since v.1.6.6 | |
| 105 | + */ | |
| 106 | + add_action('deleted_post', array($this, 'delete_tutor_course_data')); | |
| 107 | + add_action('tutor/dashboard_course_builder_form_field_after', array($this, 'tutor_course_setting_metabox_frontend')); | |
| 108 | + | |
| 109 | + /** | |
| 110 | + * Delete course data after deleted course | |
| 111 | + * @since v.1.8.2 | |
| 112 | + */ | |
| 113 | + add_action('before_delete_post', array($this, 'delete_associated_enrollment')); | |
| 114 | + | |
| 115 | + /** | |
| 116 | + * Show only own uploads in media library if user is instructor | |
| 117 | + * @since v1.8.9 | |
| 118 | + */ | |
| 119 | + add_filter('posts_where', array($this, 'restrict_media' ) ); | |
| 31 | 120 | } |
| 121 | + | |
| 122 | + function restrict_media( $where ){ | |
| 123 | + | |
| 124 | + if( isset( $_POST['action'] ) && $_POST['action'] == 'query-attachments' && tutor_utils()->is_instructor()){ | |
| 125 | + if(!tutor_utils()->has_user_role(array('administrator', 'editor'))) { | |
| 126 | + $where .= ' AND post_author=' . get_current_user_id(); | |
| 127 | + } | |
| 128 | + } | |
| 129 | + | |
| 130 | + return $where; | |
| 131 | + } | |
| 132 | + | |
| 32 | 133 | /** |
| 33 | 134 | * Registering metabox |
| 34 | 135 | */ |
| 35 | 136 | public function register_meta_box(){ |
| 36 | 137 | $coursePostType = tutor()->course_post_type; |
| 37 | - | |
| 138 | + $course_marketplace = tutor_utils()->get_option('enable_course_marketplace'); | |
| 139 | + //add_meta_box( 'tutor-course-levels', __( 'Course Level', 'tutor' ), array($this, 'course_level_metabox'), $coursePostType ); | |
| 38 | 140 | add_meta_box( 'tutor-course-topics', __( 'Course Builder', 'tutor' ), array($this, 'course_meta_box'), $coursePostType ); |
| 39 | 141 | add_meta_box( 'tutor-course-additional-data', __( 'Additional Data', 'tutor' ), array($this, 'course_additional_data_meta_box'), $coursePostType ); |
| 40 | 142 | add_meta_box( 'tutor-course-videos', __( 'Video', 'tutor' ), array($this, 'video_metabox'), $coursePostType ); |
| 41 | - add_meta_box( 'tutor-instructors', __( 'Instructors', 'tutor' ), array($this, 'instructors_metabox'), $coursePostType ); | |
| 42 | - add_meta_box( 'tutor-announcements', __( 'Announcements', 'tutor' ), array($this, 'announcements_metabox'), $coursePostType ); | |
| 143 | + if ($course_marketplace) { | |
| 144 | + add_meta_box( 'tutor-instructors', __( 'Instructors', 'tutor' ), array( $this, 'instructors_metabox' ), $coursePostType ); | |
| 145 | + } | |
| 146 | + | |
| 147 | + /** | |
| 148 | + * Tutor course sidebar settings metabox | |
| 149 | + * @since v.1.7.0 | |
| 150 | + */ | |
| 151 | + add_meta_box( 'tutor-course-sidebar-settings', __( 'Tutor Settings', 'tutor' ), array($this, 'tutor_course_setting_metabox'), $coursePostType, 'side' ); | |
| 43 | 152 | } |
| 44 | - public function course_meta_box(){ | |
| 153 | + | |
| 154 | + public function course_meta_box($echo = true){ | |
| 155 | + ob_start(); | |
| 45 | 156 | include tutor()->path.'views/metabox/course-topics.php'; |
| 157 | + $content = ob_get_clean(); | |
| 158 | + | |
| 159 | + if ($echo){ | |
| 160 | + echo $content; | |
| 161 | + }else{ | |
| 162 | + return $content; | |
| 163 | + } | |
| 46 | 164 | } |
| 47 | - public function course_additional_data_meta_box(){ | |
| 165 | + | |
| 166 | + public function course_additional_data_meta_box($echo = true){ | |
| 167 | + | |
| 168 | + ob_start(); | |
| 48 | 169 | include tutor()->path.'views/metabox/course-additional-data.php'; |
| 170 | + $content = ob_get_clean(); | |
| 171 | + | |
| 172 | + if ($echo){ | |
| 173 | + echo $content; | |
| 174 | + }else{ | |
| 175 | + return $content; | |
| 176 | + } | |
| 49 | 177 | } |
| 50 | - public function video_metabox(){ | |
| 178 | + | |
| 179 | + public function video_metabox($echo = true){ | |
| 180 | + ob_start(); | |
| 51 | 181 | include tutor()->path.'views/metabox/video-metabox.php'; |
| 182 | + $content = ob_get_clean(); | |
| 183 | + | |
| 184 | + if ($echo){ | |
| 185 | + echo $content; | |
| 186 | + }else{ | |
| 187 | + return $content; | |
| 188 | + } | |
| 52 | 189 | } |
| 53 | 190 | |
| 54 | - public function announcements_metabox(){ | |
| 55 | - include tutor()->path.'views/metabox/announcements-metabox.php'; | |
| 191 | + public function course_level_metabox($echo = true){ | |
| 192 | + ob_start(); | |
| 193 | + include tutor()->path.'views/metabox/course-level-metabox.php'; | |
| 194 | + $content = ob_get_clean(); | |
| 195 | + | |
| 196 | + if ($echo){ | |
| 197 | + echo $content; | |
| 198 | + }else{ | |
| 199 | + return $content; | |
| 200 | + } | |
| 56 | 201 | } |
| 57 | 202 | |
| 58 | - public function instructors_metabox(){ | |
| 59 | - include tutor()->path.'views/metabox/instructors-metabox.php'; | |
| 203 | + public function instructors_metabox($echo = true){ | |
| 204 | + ob_start(); | |
| 205 | + include tutor()->path . 'views/metabox/instructors-metabox.php'; | |
| 206 | + $content = ob_get_clean(); | |
| 207 | + | |
| 208 | + if ($echo){ | |
| 209 | + echo $content; | |
| 210 | + }else{ | |
| 211 | + return $content; | |
| 212 | + } | |
| 60 | 213 | } |
| 61 | 214 | |
| 62 | 215 | /** |
| 216 | + * Register metabox in course builder tutor | |
| 217 | + * @since v.1.3.4 | |
| 218 | + */ | |
| 219 | + public function register_meta_box_in_frontend(){ | |
| 220 | + do_action('tutor_course_builder_metabox_before', get_the_ID()); | |
| 221 | + course_builder_section_wrap($this->video_metabox($echo = false), __( 'Video', 'tutor' ) ); | |
| 222 | + course_builder_section_wrap($this->course_meta_box($echo = false), __( 'Course Builder', 'tutor' ) ); | |
| 223 | + course_builder_section_wrap($this->instructors_metabox($echo = false), __( 'Instructors', 'tutor' ) ); | |
| 224 | + course_builder_section_wrap($this->course_additional_data_meta_box($echo = false), __( 'Additional Data', 'tutor' ) ); | |
| 225 | + do_action('tutor_course_builder_metabox_after', get_the_ID()); | |
| 226 | + } | |
| 227 | + | |
| 228 | + /** | |
| 63 | 229 | * @param $post_ID |
| 64 | 230 | * |
| 65 | 231 | * Insert Topic and attached it with Course |
| 66 | 232 | */ |
| @@ -65,29 +231,22 @@ | ||
| 65 | 231 | * Insert Topic and attached it with Course |
| 66 | 232 | */ |
| 67 | 233 | public function save_course_meta($post_ID, $post){ |
| 68 | 234 | global $wpdb; |
| 235 | + | |
| 236 | + do_action( "tutor_save_course", $post_ID, $post); | |
| 237 | + | |
| 69 | 238 | /** |
| 70 | - * Insert Topic | |
| 239 | + * Save course price type | |
| 71 | 240 | */ |
| 72 | - if ( ! empty($_POST['topic_title'])) { | |
| 73 | - $topic_title = sanitize_text_field( $_POST['topic_title'] ); | |
| 74 | - $topic_summery = wp_kses_post( $_POST['topic_summery'] ); | |
| 75 | - | |
| 76 | - $post_arr = array( | |
| 77 | - 'post_type' => 'topics', | |
| 78 | - 'post_title' => $topic_title, | |
| 79 | - 'post_content' => $topic_summery, | |
| 80 | - 'post_status' => 'publish', | |
| 81 | - 'post_author' => get_current_user_id(), | |
| 82 | - 'post_parent' => $post_ID, | |
| 83 | - ); | |
| 84 | - wp_insert_post( $post_arr ); | |
| 241 | + $price_type = tutils()->array_get('tutor_course_price_type', $_POST); | |
| 242 | + if ($price_type){ | |
| 243 | + update_post_meta($post_ID, '_tutor_course_price_type', $price_type); | |
| 85 | 244 | } |
| 86 | 245 | |
| 87 | 246 | //Course Duration |
| 88 | 247 | if ( ! empty($_POST['course_duration'])){ |
| 89 | - $video = tutor_utils()->sanitize_array($_POST['course_duration']); | |
| 248 | + $video = tutils()->sanitize_array($_POST['course_duration']); | |
| 90 | 249 | update_post_meta($post_ID, '_course_duration', $video); |
| 91 | 250 | } |
| 92 | 251 | |
| 93 | 252 | if ( ! empty($_POST['course_level'])){ |
| @@ -94,27 +253,40 @@ | ||
| 94 | 253 | $course_level = sanitize_text_field($_POST['course_level']); |
| 95 | 254 | update_post_meta($post_ID, '_tutor_course_level', $course_level); |
| 96 | 255 | } |
| 97 | 256 | |
| 98 | - if ( ! empty($_POST['course_benefits'])){ | |
| 99 | - $course_benefits = wp_kses_post($_POST['course_benefits']); | |
| 100 | - update_post_meta($post_ID, '_tutor_course_benefits', $course_benefits); | |
| 101 | - } | |
| 257 | + $additional_data_edit = tutils()->avalue_dot('_tutor_course_additional_data_edit', $_POST); | |
| 258 | + if ($additional_data_edit) { | |
| 259 | + if (!empty($_POST['course_benefits'])) { | |
| 260 | + $course_benefits = wp_kses_post($_POST['course_benefits']); | |
| 261 | + update_post_meta($post_ID, '_tutor_course_benefits', $course_benefits); | |
| 262 | + } else { | |
| 263 | + delete_post_meta($post_ID, '_tutor_course_benefits'); | |
| 264 | + } | |
| 102 | 265 | |
| 103 | - if ( ! empty($_POST['course_requirements'])){ | |
| 104 | - $requirements = wp_kses_post($_POST['course_requirements']); | |
| 105 | - update_post_meta($post_ID, '_tutor_course_requirements', $requirements); | |
| 266 | + if (!empty($_POST['course_requirements'])) { | |
| 267 | + $requirements = wp_kses_post($_POST['course_requirements']); | |
| 268 | + update_post_meta($post_ID, '_tutor_course_requirements', $requirements); | |
| 269 | + } else { | |
| 270 | + delete_post_meta($post_ID, '_tutor_course_requirements'); | |
| 271 | + } | |
| 272 | + | |
| 273 | + if (!empty($_POST['course_target_audience'])) { | |
| 274 | + $target_audience = wp_kses_post($_POST['course_target_audience']); | |
| 275 | + update_post_meta($post_ID, '_tutor_course_target_audience', $target_audience); | |
| 276 | + } else { | |
| 277 | + delete_post_meta($post_ID, '_tutor_course_target_audience'); | |
| 278 | + } | |
| 279 | + | |
| 280 | + if (!empty($_POST['course_material_includes'])) { | |
| 281 | + $material_includes = wp_kses_post($_POST['course_material_includes']); | |
| 282 | + update_post_meta($post_ID, '_tutor_course_material_includes', $material_includes); | |
| 283 | + } else { | |
| 284 | + delete_post_meta($post_ID, '_tutor_course_material_includes'); | |
| 285 | + } | |
| 106 | 286 | } |
| 107 | 287 | |
| 108 | - if ( ! empty($_POST['course_target_audience'])){ | |
| 109 | - $target_audience = wp_kses_post($_POST['course_target_audience']); | |
| 110 | - update_post_meta($post_ID, '_tutor_course_target_audience', $target_audience); | |
| 111 | - } | |
| 112 | 288 | |
| 113 | - if ( ! empty($_POST['course_material_includes'])){ | |
| 114 | - $material_includes = wp_kses_post($_POST['course_material_includes']); | |
| 115 | - update_post_meta($post_ID, '_tutor_course_material_includes', $material_includes); | |
| 116 | - } | |
| 117 | 289 | /** |
| 118 | 290 | * Sorting Topics and lesson |
| 119 | 291 | */ |
| 120 | 292 | if ( ! empty($_POST['tutor_topics_lessons_sorting'])){ |
| @@ -161,14 +333,16 @@ | ||
| 161 | 333 | } |
| 162 | 334 | } |
| 163 | 335 | } |
| 164 | 336 | } |
| 165 | - | |
| 166 | - | |
| 167 | - //Video | |
| 168 | - if ( ! empty($_POST['video']['source'])){ | |
| 169 | - $video = tutor_utils()->sanitize_array($_POST['video']); | |
| 170 | - update_post_meta($post_ID, '_video', $video); | |
| 337 | + | |
| 338 | + if ($additional_data_edit) { | |
| 339 | + if ( ! empty($_POST['video']['source'])) { //Video | |
| 340 | + $video = tutor_utils()->array_get('video', $_POST); | |
| 341 | + update_post_meta($post_ID, '_video', $video); | |
| 342 | + }else{ | |
| 343 | + delete_post_meta($post_ID, '_video'); | |
| 344 | + } | |
| 171 | 345 | } |
| 172 | 346 | |
| 173 | 347 | /** |
| 174 | 348 | * Adding author to instructor automatically |
| @@ -174,29 +348,27 @@ | ||
| 174 | 348 | * Adding author to instructor automatically |
| 175 | 349 | */ |
| 176 | 350 | |
| 177 | 351 | $author_id = $post->post_author; |
| 178 | - $attached = (int) $wpdb->get_var(" SELECT COUNT(umeta_id) FROM {$wpdb->usermeta} WHERE user_id = {$author_id} AND meta_key = '_tutor_instructor_course_id' AND meta_value = {$post_ID} "); | |
| 352 | + $attached = (int) $wpdb->get_var($wpdb->prepare( | |
| 353 | + "SELECT COUNT(umeta_id) FROM {$wpdb->usermeta} | |
| 354 | + WHERE user_id = %d AND meta_key = '_tutor_instructor_course_id' AND meta_value = %d ", $author_id, $post_ID)); | |
| 355 | + | |
| 179 | 356 | if ( ! $attached){ |
| 180 | 357 | add_user_meta($author_id, '_tutor_instructor_course_id', $post_ID); |
| 181 | 358 | } |
| 182 | 359 | |
| 183 | - //Announcements | |
| 184 | - $announcement_title = tutor_utils()->avalue_dot('announcements.title', $_POST ); | |
| 185 | - if ( ! empty($announcement_title)){ | |
| 186 | - $title = sanitize_text_field(tutor_utils()->avalue_dot('announcements.title', $_POST )); | |
| 187 | - $content = wp_kses_post(tutor_utils()->avalue_dot('announcements.content', $_POST )); | |
| 360 | + /** | |
| 361 | + * Disable question and answer for this course | |
| 362 | + * @since 1.7.0 | |
| 363 | + */ | |
| 364 | + if ($additional_data_edit) { | |
| 365 | + foreach($this->additional_meta as $key){ | |
| 366 | + update_post_meta($post_ID, $key, (isset($_POST[$key]) ? 'yes' : 'no')); | |
| 367 | + } | |
| 368 | + } | |
| 188 | 369 | |
| 189 | - $post_arr = array( | |
| 190 | - 'post_type' => 'tutor_announcements', | |
| 191 | - 'post_title' => $title, | |
| 192 | - 'post_content' => $content, | |
| 193 | - 'post_status' => 'publish', | |
| 194 | - 'post_author' => get_current_user_id(), | |
| 195 | - 'post_parent' => $post_ID, | |
| 196 | - ); | |
| 197 | - wp_insert_post( $post_arr ); | |
| 198 | - } | |
| 370 | + do_action( "tutor_save_course_after", $post_ID, $post); | |
| 199 | 371 | } |
| 200 | 372 | |
| 201 | 373 | /** |
| 202 | 374 | * Tutor add course topic |
| @@ -201,13 +373,19 @@ | ||
| 201 | 373 | /** |
| 202 | 374 | * Tutor add course topic |
| 203 | 375 | */ |
| 204 | 376 | public function tutor_add_course_topic(){ |
| 205 | - if (empty($_POST['topic_title'])) { | |
| 377 | + tutils()->checking_nonce(); | |
| 378 | + | |
| 379 | + if (empty($_POST['topic_title']) ) { | |
| 206 | 380 | wp_send_json_error(); |
| 207 | 381 | } |
| 208 | 382 | $course_id = (int) tutor_utils()->avalue_dot('tutor_topic_course_ID', $_POST); |
| 209 | 383 | $next_topic_order_id = tutor_utils()->get_next_topic_order_id($course_id); |
| 384 | + | |
| 385 | + if(!tutils()->can_user_manage('course', $course_id)) { | |
| 386 | + wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) ); | |
| 387 | + } | |
| 210 | 388 | |
| 211 | 389 | $topic_title = sanitize_text_field( $_POST['topic_title'] ); |
| 212 | 390 | $topic_summery = wp_kses_post( $_POST['topic_summery'] ); |
| 213 | 391 | |
| @@ -232,12 +410,18 @@ | ||
| 232 | 410 | /** |
| 233 | 411 | * Update the topic |
| 234 | 412 | */ |
| 235 | 413 | public function tutor_update_topic(){ |
| 414 | + tutils()->checking_nonce(); | |
| 415 | + | |
| 236 | 416 | $topic_id = (int) sanitize_text_field($_POST['topic_id']); |
| 237 | 417 | $topic_title = sanitize_text_field($_POST['topic_title']); |
| 238 | 418 | $topic_summery = wp_kses_post($_POST['topic_summery']); |
| 239 | 419 | |
| 420 | + if(!tutils()->can_user_manage('topic', $topic_id)) { | |
| 421 | + wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) ); | |
| 422 | + } | |
| 423 | + | |
| 240 | 424 | $topic_attr = array( |
| 241 | 425 | 'ID' => $topic_id, |
| 242 | 426 | 'post_title' => $topic_title, |
| 243 | 427 | 'post_content' => $topic_summery, |
| @@ -254,9 +438,8 @@ | ||
| 254 | 438 | * @return mixed |
| 255 | 439 | * |
| 256 | 440 | * Add Lesson column |
| 257 | 441 | */ |
| 258 | - | |
| 259 | 442 | public function add_column($columns){ |
| 260 | 443 | $date_col = $columns['date']; |
| 261 | 444 | unset($columns['date']); |
| 262 | 445 | $columns['lessons'] = __('Lessons', 'tutor'); |
| @@ -282,17 +465,17 @@ | ||
| 282 | 465 | } |
| 283 | 466 | |
| 284 | 467 | if ($column === 'price'){ |
| 285 | 468 | $price = tutor_utils()->get_course_price($post_id); |
| 286 | - | |
| 287 | 469 | if ($price){ |
| 288 | - if (function_exists('wc_price')){ | |
| 470 | + $monetize_by = tutils()->get_option('monetize_by'); | |
| 471 | + if (function_exists('wc_price') && $monetize_by === 'wc'){ | |
| 289 | 472 | echo '<span class="tutor-label-success">'.wc_price($price).'</span>'; |
| 290 | 473 | }else{ |
| 291 | 474 | echo '<span class="tutor-label-success">'.$price.'</span>'; |
| 292 | 475 | } |
| 293 | 476 | }else{ |
| 294 | - echo 'free'; | |
| 477 | + echo apply_filters('tutor-loop-default-price', 'free'); | |
| 295 | 478 | } |
| 296 | 479 | } |
| 297 | 480 | } |
| 298 | 481 | |
| @@ -297,15 +480,13 @@ | ||
| 297 | 480 | } |
| 298 | 481 | |
| 299 | 482 | |
| 300 | 483 | public function tutor_delete_topic(){ |
| 301 | - if (!isset($_GET[tutor()->nonce]) || !wp_verify_nonce($_GET[tutor()->nonce], tutor()->nonce_action)) { | |
| 302 | - exit(); | |
| 303 | - } | |
| 304 | - if ( ! isset($_GET['topic_id'])){ | |
| 305 | - exit(); | |
| 306 | - } | |
| 307 | 484 | |
| 485 | + tutils()->checking_nonce('get'); | |
| 486 | + | |
| 487 | + !isset($_GET['topic_id']) ? exit() : 0; | |
| 488 | + | |
| 308 | 489 | global $wpdb; |
| 309 | 490 | |
| 310 | 491 | $topic_id = (int) sanitize_text_field($_GET['topic_id']); |
| 311 | 492 | $wpdb->update( |
| @@ -332,10 +513,11 @@ | ||
| 332 | 513 | wp_safe_redirect(wp_get_referer()); |
| 333 | 514 | } |
| 334 | 515 | |
| 335 | 516 | public function enroll_now(){ |
| 517 | + | |
| 336 | 518 | //Checking if action comes from Enroll form |
| 337 | - if ( ! isset($_POST['tutor_course_action']) || $_POST['tutor_course_action'] !== '_tutor_course_enroll_now' || ! isset($_POST['tutor_course_id']) ){ | |
| 519 | + if (tutor_utils()->array_get('tutor_course_action', $_POST) !== '_tutor_course_enroll_now' || ! isset($_POST['tutor_course_id']) ){ | |
| 338 | 520 | return; |
| 339 | 521 | } |
| 340 | 522 | //Checking Nonce |
| 341 | 523 | tutor_utils()->checking_nonce(); |
| @@ -401,14 +583,17 @@ | ||
| 401 | 583 | */ |
| 402 | 584 | |
| 403 | 585 | global $wpdb; |
| 404 | 586 | |
| 405 | - $date = date("Y-m-d H:i:s"); | |
| 587 | + $date = date("Y-m-d H:i:s", tutor_time()); | |
| 406 | 588 | |
| 407 | 589 | //Making sure that, hash is unique |
| 408 | 590 | do{ |
| 409 | 591 | $hash = substr(md5(wp_generate_password(32).$date.$course_id.$user_id), 0, 16); |
| 410 | - $hasHash = (int) $wpdb->get_var("SELECT COUNT(comment_ID) from {$wpdb->comments} WHERE comment_agent = 'TutorLMSPlugin' AND comment_type = 'course_completed' AND comment_content = '{$hash}' "); | |
| 592 | + $hasHash = (int) $wpdb->get_var($wpdb->prepare( | |
| 593 | + "SELECT COUNT(comment_ID) from {$wpdb->comments} | |
| 594 | + WHERE comment_agent = 'TutorLMSPlugin' AND comment_type = 'course_completed' AND comment_content = %s ", $hash)); | |
| 595 | + | |
| 411 | 596 | }while($hasHash > 0); |
| 412 | 597 | |
| 413 | 598 | $data = array( |
| 414 | 599 | 'comment_post_ID' => $course_id, |
| @@ -423,9 +608,9 @@ | ||
| 423 | 608 | ); |
| 424 | 609 | |
| 425 | 610 | $wpdb->insert($wpdb->comments, $data); |
| 426 | 611 | |
| 427 | - do_action('tutor_course_complete_after', $course_id); | |
| 612 | + do_action('tutor_course_complete_after', $course_id, $user_id); | |
| 428 | 613 | |
| 429 | 614 | wp_redirect(get_the_permalink($course_id)); |
| 430 | 615 | } |
| 431 | 616 | |
| @@ -430,18 +615,22 @@ | ||
| 430 | 615 | } |
| 431 | 616 | |
| 432 | 617 | |
| 433 | 618 | public function tutor_load_instructors_modal(){ |
| 619 | + tutils()->checking_nonce(); | |
| 620 | + | |
| 434 | 621 | global $wpdb; |
| 435 | 622 | |
| 436 | 623 | $course_id = (int) sanitize_text_field($_POST['course_id']); |
| 437 | 624 | $search_terms = sanitize_text_field(tutor_utils()->avalue_dot('search_terms', $_POST)); |
| 438 | 625 | |
| 626 | + if(!tutils()->can_user_manage('course', $course_id)) { | |
| 627 | + wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) ); | |
| 628 | + } | |
| 629 | + | |
| 439 | 630 | $saved_instructors = tutor_utils()->get_instructors_by_course($course_id); |
| 440 | - | |
| 441 | 631 | $instructors = array(); |
| 442 | 632 | |
| 443 | - | |
| 444 | 633 | $not_in_sql = apply_filters('tutor_instructor_query_when_exists', " AND ID <1 "); |
| 445 | 634 | |
| 446 | 635 | if ($saved_instructors){ |
| 447 | 636 | $saved_instructors_ids = wp_list_pluck($saved_instructors, 'ID'); |
| @@ -450,14 +639,14 @@ | ||
| 450 | 639 | } |
| 451 | 640 | |
| 452 | 641 | $search_sql = ''; |
| 453 | 642 | if ($search_terms){ |
| 454 | - $search_sql = "AND user_login like '%{$search_terms}%' or user_nicename like '%{$search_terms}%' or display_name like '%{$search_terms}%' "; | |
| 643 | + $search_sql = "AND (user_login like '%{$search_terms}%' or user_nicename like '%{$search_terms}%' or display_name like '%{$search_terms}%') "; | |
| 455 | 644 | } |
| 456 | 645 | |
| 457 | 646 | $instructors = $wpdb->get_results("select ID, display_name from {$wpdb->users} |
| 458 | 647 | INNER JOIN {$wpdb->usermeta} ON ID = user_id AND meta_key = '_tutor_instructor_status' AND meta_value = 'approved' |
| 459 | - WHERE ID > 0 {$not_in_sql} {$search_sql} limit 10 "); | |
| 648 | + WHERE 1=1 {$not_in_sql} {$search_sql} limit 10 "); | |
| 460 | 649 | |
| 461 | 650 | $output = ''; |
| 462 | 651 | if (is_array($instructors) && count($instructors)){ |
| 463 | 652 | $instructor_output = ''; |
| @@ -465,12 +654,11 @@ | ||
| 465 | 654 | $instructor_output .= "<p><label><input type='radio' name='tutor_instructor_ids[]' value='{$instructor->ID}' > {$instructor->display_name} </label></p>"; |
| 466 | 655 | } |
| 467 | 656 | |
| 468 | 657 | $output .= apply_filters('tutor_course_instructors_html', $instructor_output, $instructors); |
| 469 | - $output .= '<p class="quiz-search-suggest-text">'.__('Search to get the specific instructors', 'tutor').'</p>'; | |
| 470 | 658 | |
| 471 | 659 | }else{ |
| 472 | - $output .= __('No instructor available or you have already added maximum instructors', 'tutor'); | |
| 660 | + $output .= __('<p>No instructor available or you have already added maximum instructors</p>', 'tutor'); | |
| 473 | 661 | } |
| 474 | 662 | |
| 475 | 663 | |
| 476 | 664 | if ( ! defined('TUTOR_MT_VERSION')){ |
| @@ -480,10 +668,16 @@ | ||
| 480 | 668 | wp_send_json_success(array('output' => $output)); |
| 481 | 669 | } |
| 482 | 670 | |
| 483 | 671 | public function tutor_add_instructors_to_course(){ |
| 672 | + tutils()->checking_nonce(); | |
| 673 | + | |
| 484 | 674 | $course_id = (int) sanitize_text_field($_POST['course_id']); |
| 485 | 675 | $instructor_ids = tutor_utils()->avalue_dot('tutor_instructor_ids', $_POST); |
| 676 | + | |
| 677 | + if(!tutils()->can_user_manage('course', $course_id)) { | |
| 678 | + wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) ); | |
| 679 | + } | |
| 486 | 680 | |
| 487 | 681 | if (is_array($instructor_ids) && count($instructor_ids)){ |
| 488 | 682 | foreach ($instructor_ids as $instructor_id){ |
| 489 | 683 | add_user_meta($instructor_id, '_tutor_instructor_course_id', $course_id); |
| @@ -499,9 +693,9 @@ | ||
| 499 | 693 | $output .= '<div id="added-instructor-id-'.$t->ID.'" class="added-instructor-item added-instructor-item-'.$t->ID.'" data-instructor-id="'.$t->ID.'"> |
| 500 | 694 | <span class="instructor-icon">'.get_avatar($t->ID, 30).'</span> |
| 501 | 695 | <span class="instructor-name"> '.$t->display_name.' </span> |
| 502 | 696 | <span class="instructor-control"> |
| 503 | - <a href="javascript:;" class="tutor-instructor-delete-btn"><i class="tutor-icon-garbage"></i></a> | |
| 697 | + <a href="javascript:;" class="tutor-instructor-delete-btn"><i class="tutor-icon-line-cross"></i></a> | |
| 504 | 698 | </span> |
| 505 | 699 | </div>'; |
| 506 | 700 | } |
| 507 | 701 | } |
| @@ -509,15 +703,595 @@ | ||
| 509 | 703 | wp_send_json_success(array('output' => $output)); |
| 510 | 704 | } |
| 511 | 705 | |
| 512 | 706 | public function detach_instructor_from_course(){ |
| 707 | + tutils()->checking_nonce(); | |
| 708 | + | |
| 513 | 709 | global $wpdb; |
| 514 | 710 | |
| 515 | 711 | $instructor_id = (int) sanitize_text_field($_POST['instructor_id']); |
| 516 | 712 | $course_id = (int) sanitize_text_field($_POST['course_id']); |
| 517 | 713 | |
| 714 | + if(!tutils()->can_user_manage('course', $course_id)) { | |
| 715 | + wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) ); | |
| 716 | + } | |
| 717 | + | |
| 518 | 718 | $wpdb->delete($wpdb->usermeta, array('user_id' => $instructor_id, 'meta_key' => '_tutor_instructor_course_id', 'meta_value' => $course_id) ); |
| 519 | 719 | wp_send_json_success(); |
| 520 | 720 | } |
| 521 | 721 | |
| 722 | + public function tutor_delete_dashboard_course(){ | |
| 723 | + tutils()->checking_nonce(); | |
| 522 | 724 | |
| 725 | + $course_id = intval(sanitize_text_field($_POST['course_id'])); | |
| 726 | + | |
| 727 | + if(!tutils()->can_user_manage('course', $course_id)) { | |
| 728 | + wp_send_json_error( array('message'=>__('Access Denied', 'tutor')) ); | |
| 729 | + } | |
| 730 | + | |
| 731 | + wp_trash_post($course_id); | |
| 732 | + wp_send_json_success(['element'=>'course']); | |
| 733 | + } | |
| 734 | + | |
| 735 | + | |
| 736 | + public function tutor_add_gutenberg_author($data , $postarr){ | |
| 737 | + global $wpdb; | |
| 738 | + | |
| 739 | + $courses_post_type = tutor()->course_post_type; | |
| 740 | + $post_type = tutils()->array_get('post_type', $postarr); | |
| 741 | + | |
| 742 | + if ($courses_post_type === $post_type){ | |
| 743 | + $post_ID = (int) tutor_utils()->avalue_dot('ID', $postarr); | |
| 744 | + $post_author = (int) $wpdb->get_var($wpdb->prepare("SELECT post_author FROM {$wpdb->posts} WHERE ID = %d ", $post_ID)); | |
| 745 | + | |
| 746 | + if ($post_author > 0){ | |
| 747 | + $data['post_author'] = $post_author; | |
| 748 | + }else{ | |
| 749 | + $data['post_author'] = get_current_user_id(); | |
| 750 | + } | |
| 751 | + } | |
| 752 | + | |
| 753 | + return $data; | |
| 754 | + } | |
| 755 | + | |
| 756 | + | |
| 757 | + /** | |
| 758 | + * @param $post_ID | |
| 759 | + * @param $postData | |
| 760 | + * | |
| 761 | + * Attach product during save course from the frontend course dashboard. | |
| 762 | + * | |
| 763 | + * @return string | |
| 764 | + * | |
| 765 | + * @since v.1.3.4 | |
| 766 | + */ | |
| 767 | + public function attach_product_with_course($post_ID, $postData){ | |
| 768 | + $attached_product_id = tutor_utils()->get_course_product_id($post_ID); | |
| 769 | + $course_price = sanitize_text_field(tutor_utils()->array_get('course_price', $_POST)); | |
| 770 | + | |
| 771 | + if ( ! $course_price){ | |
| 772 | + return; | |
| 773 | + } | |
| 774 | + | |
| 775 | + $monetize_by = tutor_utils()->get_option('monetize_by'); | |
| 776 | + $course = get_post($post_ID); | |
| 777 | + | |
| 778 | + if ($monetize_by === 'wc'){ | |
| 779 | + | |
| 780 | + $is_update = false; | |
| 781 | + if ($attached_product_id){ | |
| 782 | + $wc_product = get_post_meta($attached_product_id, '_product_version', true); | |
| 783 | + if ($wc_product){ | |
| 784 | + $is_update = true; | |
| 785 | + } | |
| 786 | + } | |
| 787 | + | |
| 788 | + if ($is_update) { | |
| 789 | + $productObj = wc_get_product($attached_product_id); | |
| 790 | + $productObj->set_price($course_price); // set product price | |
| 791 | + $productObj->set_regular_price($course_price); // set product regular price | |
| 792 | + $product_id = $productObj->save(); | |
| 793 | + if($productObj->is_type('subscription')) { | |
| 794 | + update_post_meta( $attached_product_id, '_subscription_price', $course_price ); | |
| 795 | + } | |
| 796 | + } else { | |
| 797 | + $productObj = new \WC_Product(); | |
| 798 | + $productObj->set_name($course->post_title); | |
| 799 | + $productObj->set_status('publish'); | |
| 800 | + $productObj->set_price($course_price); // set product price | |
| 801 | + $productObj->set_regular_price($course_price); // set product regular price | |
| 802 | + | |
| 803 | + $product_id = $productObj->save(); | |
| 804 | + if ($product_id) { | |
| 805 | + update_post_meta( $post_ID, '_tutor_course_product_id', $product_id ); | |
| 806 | + //Mark product for woocommerce | |
| 807 | + update_post_meta( $product_id, '_virtual', 'yes' ); | |
| 808 | + update_post_meta( $product_id, '_tutor_product', 'yes' ); | |
| 809 | + | |
| 810 | + $coursePostThumbnail = get_post_meta( $post_ID, '_thumbnail_id', true ); | |
| 811 | + if ( $coursePostThumbnail ) { | |
| 812 | + set_post_thumbnail( $product_id, $coursePostThumbnail ); | |
| 813 | + } | |
| 814 | + } | |
| 815 | + } | |
| 816 | + | |
| 817 | + }elseif ($monetize_by === 'edd'){ | |
| 818 | + | |
| 819 | + $is_update = false; | |
| 820 | + | |
| 821 | + if ($attached_product_id){ | |
| 822 | + $edd_price = get_post_meta($attached_product_id, 'edd_price', true); | |
| 823 | + if ($edd_price){ | |
| 824 | + $is_update = true; | |
| 825 | + } | |
| 826 | + } | |
| 827 | + | |
| 828 | + if ($is_update){ | |
| 829 | + //Update the product | |
| 830 | + update_post_meta( $attached_product_id, 'edd_price', $course_price ); | |
| 831 | + }else{ | |
| 832 | + //Create new product | |
| 833 | + | |
| 834 | + $post_arr = array( | |
| 835 | + 'post_type' => 'download', | |
| 836 | + 'post_title' => $course->post_title, | |
| 837 | + 'post_status' => 'publish', | |
| 838 | + 'post_author' => get_current_user_id(), | |
| 839 | + ); | |
| 840 | + $download_id = wp_insert_post( $post_arr ); | |
| 841 | + if ($download_id ) { | |
| 842 | + //edd_price | |
| 843 | + update_post_meta( $download_id, 'edd_price', $course_price ); | |
| 844 | + | |
| 845 | + update_post_meta( $post_ID, '_tutor_course_product_id', $download_id ); | |
| 846 | + //Mark product for EDD | |
| 847 | + update_post_meta( $download_id, '_tutor_product', 'yes' ); | |
| 848 | + | |
| 849 | + $coursePostThumbnail = get_post_meta( $post_ID, '_thumbnail_id', true ); | |
| 850 | + if ( $coursePostThumbnail ) { | |
| 851 | + set_post_thumbnail( $download_id, $coursePostThumbnail ); | |
| 852 | + } | |
| 853 | + | |
| 854 | + } | |
| 855 | + | |
| 856 | + } | |
| 857 | + | |
| 858 | + | |
| 859 | + } | |
| 860 | + | |
| 861 | + } | |
| 862 | + | |
| 863 | + | |
| 864 | + /** | |
| 865 | + * Add Course level to course settings | |
| 866 | + * @since v.1.4.1 | |
| 867 | + */ | |
| 868 | + public function add_course_level_to_settings(){ | |
| 869 | + include tutor()->path.'views/metabox/course-level-metabox.php'; | |
| 870 | + } | |
| 871 | + | |
| 872 | + /** | |
| 873 | + * Check if course starting | |
| 874 | + * | |
| 875 | + * @since v.1.4.8 | |
| 876 | + */ | |
| 877 | + public function tutor_lesson_load_before(){ | |
| 878 | + $course_id = tutils()->get_course_id_by_content(get_the_ID()); | |
| 879 | + $completed_lessons = tutor_utils()->get_completed_lesson_count_by_course($course_id); | |
| 880 | + if (is_user_logged_in()){ | |
| 881 | + $is_course_started = get_post_meta($course_id, '_tutor_course_started', true); | |
| 882 | + if ( ! $completed_lessons && ! $is_course_started){ | |
| 883 | + update_post_meta($course_id, '_tutor_course_started', tutor_time()); | |
| 884 | + do_action('tutor/course/started', $course_id); | |
| 885 | + } | |
| 886 | + } | |
| 887 | + } | |
| 888 | + | |
| 889 | + /** | |
| 890 | + * Add Course level to course settings | |
| 891 | + * @since v.1.4.8 | |
| 892 | + */ | |
| 893 | + public function course_elements_enable_disable(){ | |
| 894 | + add_filter('tutor_course/single/completing-progress-bar', array($this, 'enable_disable_course_progress_bar') ); | |
| 895 | + add_filter('tutor_course/single/material_includes', array($this, 'enable_disable_material_includes') ); | |
| 896 | + add_filter('tutor_course/single/content', array($this, 'enable_disable_course_content') ); | |
| 897 | + add_filter('tutor_course/single/benefits_html', array($this, 'enable_disable_course_benefits') ); | |
| 898 | + add_filter('tutor_course/single/requirements_html', array($this, 'enable_disable_course_requirements') ); | |
| 899 | + add_filter('tutor_course/single/audience_html', array($this, 'enable_disable_course_target_audience') ); | |
| 900 | + add_filter('tutor_course/single/enrolled/nav_items', array($this, 'enable_disable_course_nav_items') ); | |
| 901 | + } | |
| 902 | + | |
| 903 | + /** | |
| 904 | + * Enable disable course progress bar | |
| 905 | + * @since v.1.4.8 | |
| 906 | + */ | |
| 907 | + public function enable_disable_course_progress_bar($html){ | |
| 908 | + $disable_option = (bool) get_tutor_option('disable_course_progress_bar'); | |
| 909 | + if($disable_option){ | |
| 910 | + return ''; | |
| 911 | + } | |
| 912 | + return $html; | |
| 913 | + } | |
| 914 | + | |
| 915 | + /** | |
| 916 | + * Enable disable material includes | |
| 917 | + * @since v.1.4.8 | |
| 918 | + */ | |
| 919 | + public function enable_disable_material_includes($html){ | |
| 920 | + $disable_option = (bool) get_tutor_option('disable_course_material'); | |
| 921 | + if($disable_option){ | |
| 922 | + return ''; | |
| 923 | + } | |
| 924 | + return $html; | |
| 925 | + } | |
| 926 | + | |
| 927 | + /** | |
| 928 | + * Enable disable course content | |
| 929 | + * @since v.1.4.8 | |
| 930 | + */ | |
| 931 | + public function enable_disable_course_content($html){ | |
| 932 | + $disable_option = (bool) get_tutor_option('disable_course_description'); | |
| 933 | + if($disable_option){ | |
| 934 | + return ''; | |
| 935 | + } | |
| 936 | + return $html; | |
| 937 | + } | |
| 938 | + | |
| 939 | + /** | |
| 940 | + * Enable disable course benefits | |
| 941 | + * @since v.1.4.8 | |
| 942 | + */ | |
| 943 | + public function enable_disable_course_benefits($html){ | |
| 944 | + $disable_option = (bool) get_tutor_option('disable_course_benefits'); | |
| 945 | + if($disable_option){ | |
| 946 | + return ''; | |
| 947 | + } | |
| 948 | + return $html; | |
| 949 | + } | |
| 950 | + | |
| 951 | + /** | |
| 952 | + * Enable disable course requirements | |
| 953 | + * @since v.1.4.8 | |
| 954 | + */ | |
| 955 | + public function enable_disable_course_requirements($html){ | |
| 956 | + $disable_option = (bool) get_tutor_option('disable_course_requirements'); | |
| 957 | + if($disable_option){ | |
| 958 | + return ''; | |
| 959 | + } | |
| 960 | + return $html; | |
| 961 | + } | |
| 962 | + | |
| 963 | + /** | |
| 964 | + * Enable disable course target audience | |
| 965 | + * @since v.1.4.8 | |
| 966 | + */ | |
| 967 | + public function enable_disable_course_target_audience($html){ | |
| 968 | + $disable_option = (bool) get_tutor_option('disable_course_target_audience'); | |
| 969 | + if($disable_option){ | |
| 970 | + return ''; | |
| 971 | + } | |
| 972 | + return $html; | |
| 973 | + } | |
| 974 | + | |
| 975 | + /** | |
| 976 | + * Enable disable course nav items | |
| 977 | + * @since v.1.4.8 | |
| 978 | + */ | |
| 979 | + public function enable_disable_course_nav_items($items){ | |
| 980 | + global $wp_query, $post; | |
| 981 | + $enable_q_and_a_on_course = (bool) get_tutor_option('enable_q_and_a_on_course'); | |
| 982 | + $disable_course_announcements = (bool) get_tutor_option('disable_course_announcements'); | |
| 983 | + | |
| 984 | + $disable_qa_for_this_course = ($wp_query->is_single && !empty($post)) ? get_post_meta($post->ID, '_tutor_disable_qa', true) : ''; | |
| 985 | + | |
| 986 | + if(!$enable_q_and_a_on_course || $disable_qa_for_this_course == 'yes') { | |
| 987 | + if(tutils()->array_get('questions', $items)) { | |
| 988 | + unset($items['questions']); | |
| 989 | + } | |
| 990 | + } | |
| 991 | + if($disable_course_announcements){ | |
| 992 | + if(tutils()->array_get('announcements', $items)) { | |
| 993 | + unset($items['announcements']); | |
| 994 | + } | |
| 995 | + } | |
| 996 | + return $items; | |
| 997 | + } | |
| 998 | + | |
| 999 | + /** | |
| 1000 | + * Filter product in shop page | |
| 1001 | + * @since v.1.4.9 | |
| 1002 | + */ | |
| 1003 | + public function filter_product_in_shop_page(){ | |
| 1004 | + $hide_course_from_shop_page = (bool) get_tutor_option('hide_course_from_shop_page'); | |
| 1005 | + if(!$hide_course_from_shop_page){ | |
| 1006 | + return; | |
| 1007 | + } | |
| 1008 | + add_action('woocommerce_product_query', array($this, 'filter_woocommerce_product_query')); | |
| 1009 | + add_filter('edd_downloads_query', array($this, 'filter_edd_downloads_query'), 10, 2); | |
| 1010 | + add_action('pre_get_posts', array($this, 'filter_archive_meta_query'), 1); | |
| 1011 | + } | |
| 1012 | + | |
| 1013 | + /** | |
| 1014 | + * Tutor product meta query | |
| 1015 | + * @since v.1.4.9 | |
| 1016 | + */ | |
| 1017 | + public function tutor_product_meta_query(){ | |
| 1018 | + $meta_query = array( | |
| 1019 | + 'key' => '_tutor_product', | |
| 1020 | + 'compare' => 'NOT EXISTS' | |
| 1021 | + ); | |
| 1022 | + return $meta_query; | |
| 1023 | + } | |
| 1024 | + | |
| 1025 | + /** | |
| 1026 | + * Filter product in woocommerce shop page | |
| 1027 | + * @since v.1.4.9 | |
| 1028 | + */ | |
| 1029 | + public function filter_woocommerce_product_query($wp_query){ | |
| 1030 | + $wp_query->set('meta_query', array($this->tutor_product_meta_query())); | |
| 1031 | + return $wp_query; | |
| 1032 | + } | |
| 1033 | + | |
| 1034 | + /** | |
| 1035 | + * Filter product in edd downloads shortcode page | |
| 1036 | + * @since v.1.4.9 | |
| 1037 | + */ | |
| 1038 | + public function filter_edd_downloads_query($query){ | |
| 1039 | + $query['meta_query'][] = $this->tutor_product_meta_query(); | |
| 1040 | + return $query; | |
| 1041 | + } | |
| 1042 | + | |
| 1043 | + /** | |
| 1044 | + * Filter product in edd downloads archive page | |
| 1045 | + * @since v.1.4.9 | |
| 1046 | + */ | |
| 1047 | + public function filter_archive_meta_query($wp_query){ | |
| 1048 | + if(!is_admin() && $wp_query->is_archive && $wp_query->get('post_type') === 'download'){ | |
| 1049 | + $wp_query->set('meta_query', array($this->tutor_product_meta_query())); | |
| 1050 | + } | |
| 1051 | + return $wp_query; | |
| 1052 | + } | |
| 1053 | + | |
| 1054 | + /** | |
| 1055 | + * @param $html | |
| 1056 | + * @return string | |
| 1057 | + * | |
| 1058 | + * Removed course price if already enrolled at single course | |
| 1059 | + * | |
| 1060 | + * @since v.1.5.8 | |
| 1061 | + */ | |
| 1062 | + public function remove_price_if_enrolled($html){ | |
| 1063 | + $should_removed = apply_filters('should_remove_price_if_enrolled', true); | |
| 1064 | + | |
| 1065 | + if ($should_removed){ | |
| 1066 | + $course_id = get_the_ID(); | |
| 1067 | + $enrolled = tutils()->is_enrolled($course_id); | |
| 1068 | + if ($enrolled){ | |
| 1069 | + $html = ''; | |
| 1070 | + } | |
| 1071 | + } | |
| 1072 | + return $html; | |
| 1073 | + } | |
| 1074 | + | |
| 1075 | + /** | |
| 1076 | + * @param $html | |
| 1077 | + * @return string | |
| 1078 | + * | |
| 1079 | + * Check if all lessons and quizzes done before mark course complete. | |
| 1080 | + */ | |
| 1081 | + function tutor_lms_hide_course_complete_btn($html){ | |
| 1082 | + | |
| 1083 | + $completion_mode = tutils()->get_option('course_completion_process'); | |
| 1084 | + if ($completion_mode !== 'strict'){ | |
| 1085 | + return $html; | |
| 1086 | + } | |
| 1087 | + | |
| 1088 | + $completed_lesson = tutils()->get_completed_lesson_count_by_course(); | |
| 1089 | + $lesson_count = tutils()->get_lesson_count_by_course(); | |
| 1090 | + | |
| 1091 | + if ($completed_lesson < $lesson_count){ | |
| 1092 | + return '<p class="suggestion-before-course-complete">'.__('complete all lessons to mark this course as complete', 'tutor').'</p>'; | |
| 1093 | + } | |
| 1094 | + | |
| 1095 | + $quizzes = array(); | |
| 1096 | + | |
| 1097 | + $course_contents = tutils()->get_course_contents_by_id(); | |
| 1098 | + if (tutils()->count($course_contents)){ | |
| 1099 | + foreach ($course_contents as $content){ | |
| 1100 | + if ($content->post_type === 'tutor_quiz'){ | |
| 1101 | + $quizzes[] = $content; | |
| 1102 | + } | |
| 1103 | + } | |
| 1104 | + } | |
| 1105 | + | |
| 1106 | + $is_pass = true; | |
| 1107 | + $required_quiz_pass = 0; | |
| 1108 | + | |
| 1109 | + if (tutils()->count($quizzes)){ | |
| 1110 | + foreach ($quizzes as $quiz){ | |
| 1111 | + | |
| 1112 | + $attempt = tutils()->get_quiz_attempt($quiz->ID); | |
| 1113 | + if ($attempt) { | |
| 1114 | + $passing_grade = tutor_utils()->get_quiz_option($quiz->ID, 'passing_grade', 0); | |
| 1115 | + $earned_percentage = $attempt->earned_marks > 0 ? (number_format(($attempt->earned_marks * 100) / $attempt->total_marks)) : 0; | |
| 1116 | + | |
| 1117 | + if ($earned_percentage < $passing_grade) { | |
| 1118 | + $required_quiz_pass++; | |
| 1119 | + $is_pass = false; | |
| 1120 | + } | |
| 1121 | + }else{ | |
| 1122 | + $required_quiz_pass++; | |
| 1123 | + $is_pass = false; | |
| 1124 | + } | |
| 1125 | + } | |
| 1126 | + } | |
| 1127 | + | |
| 1128 | + if ( ! $is_pass){ | |
| 1129 | + return '<p class="suggestion-before-course-complete">'.sprintf(__('You have to pass %s quizzes to complete this course.', 'tutor'), $required_quiz_pass).'</p>'; | |
| 1130 | + } | |
| 1131 | + | |
| 1132 | + return $html; | |
| 1133 | + } | |
| 1134 | + | |
| 1135 | + public function get_generate_greadbook($html){ | |
| 1136 | + if ( ! tutils()->is_completed_course()){ | |
| 1137 | + return ''; | |
| 1138 | + } | |
| 1139 | + return $html; | |
| 1140 | + } | |
| 1141 | + | |
| 1142 | + /** | |
| 1143 | + * Add social share content in header | |
| 1144 | + * @since v.1.6.3 | |
| 1145 | + */ | |
| 1146 | + public function social_share_content(){ | |
| 1147 | + global $wp_query, $post; | |
| 1148 | + if ($wp_query->is_single && ! empty($wp_query->query_vars['post_type']) && $wp_query->query_vars['post_type'] === $this->course_post_type) { ?> | |
| 1149 | + <!--Facebook--> | |
| 1150 | + <meta property="og:type" content="website"/> | |
| 1151 | + <meta property="og:image" content="<?php echo get_tutor_course_thumbnail_src(); ?>" /> | |
| 1152 | + <meta property="og:description" content="<?php echo esc_html($post->post_content); ?>" /> | |
| 1153 | + <!--Twitter--> | |
| 1154 | + <meta name="twitter:image" content="<?php echo get_tutor_course_thumbnail_src(); ?>"> | |
| 1155 | + <meta name="twitter:description" content="<?php echo esc_html($post->post_content); ?>"> | |
| 1156 | + <!--Google+--> | |
| 1157 | + <meta itemprop="image" content="<?php echo get_tutor_course_thumbnail_src(); ?>"> | |
| 1158 | + <meta itemprop="description" content="<?php echo esc_html($post->post_content); ?>"> <?php | |
| 1159 | + } | |
| 1160 | + } | |
| 1161 | + | |
| 1162 | + /** | |
| 1163 | + * Get posts by type and parent | |
| 1164 | + * @since v.1.6.6 | |
| 1165 | + */ | |
| 1166 | + public function tutor_get_post_ids($post_type, $post_parent) { | |
| 1167 | + $args = array( | |
| 1168 | + 'fields' => 'ids', | |
| 1169 | + 'post_type' => $post_type, | |
| 1170 | + 'post_parent' => $post_parent, | |
| 1171 | + 'post_status' => 'any', | |
| 1172 | + 'posts_per_page' => -1, | |
| 1173 | + ); | |
| 1174 | + return get_posts($args); | |
| 1175 | + } | |
| 1176 | + | |
| 1177 | + /** | |
| 1178 | + * Delete course data when permanently deleting a course. | |
| 1179 | + * @since v.1.6.6 | |
| 1180 | + */ | |
| 1181 | + function delete_tutor_course_data( $post_id ) { | |
| 1182 | + $course_post_type = tutor()->course_post_type; | |
| 1183 | + $lesson_post_type = tutor()->lesson_post_type; | |
| 1184 | + | |
| 1185 | + if (get_post_type($post_id) == $course_post_type) { | |
| 1186 | + global $wpdb; | |
| 1187 | + $topic_ids = $this->tutor_get_post_ids('topics', $post_id); | |
| 1188 | + if ( !empty($topic_ids) ) { | |
| 1189 | + foreach ($topic_ids as $topic_id) { | |
| 1190 | + $content_post_type = apply_filters('tutor_course_contents_post_types', array($lesson_post_type, 'tutor_quiz')); | |
| 1191 | + $topic_content_ids = $this->tutor_get_post_ids($content_post_type, $topic_id); | |
| 1192 | + | |
| 1193 | + foreach ($topic_content_ids as $content_id) { | |
| 1194 | + if( get_post_type($content_id) == 'tutor_quiz') { | |
| 1195 | + $wpdb->delete($wpdb->prefix.'tutor_quiz_attempts', array('quiz_id' => $content_id)); | |
| 1196 | + $wpdb->delete($wpdb->prefix.'tutor_quiz_attempt_answers', array('quiz_id' => $content_id)); | |
| 1197 | + | |
| 1198 | + $questions_ids = $wpdb->get_col($wpdb->prepare("SELECT question_id FROM {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = %d ", $content_id)); | |
| 1199 | + if (is_array($questions_ids) && count($questions_ids)){ | |
| 1200 | + $in_question_ids = "'".implode("','", $questions_ids)."'"; | |
| 1201 | + $wpdb->query("DELETE FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id IN({$in_question_ids}) "); | |
| 1202 | + } | |
| 1203 | + $wpdb->delete($wpdb->prefix.'tutor_quiz_questions', array('quiz_id' => $content_id)); | |
| 1204 | + } | |
| 1205 | + wp_delete_post($content_id, true); | |
| 1206 | + } | |
| 1207 | + wp_delete_post($topic_id, true); | |
| 1208 | + } | |
| 1209 | + } | |
| 1210 | + $child_post_ids = $this->tutor_get_post_ids(array('tutor_announcements', 'tutor_enrolled'), $post_id); | |
| 1211 | + if ( !empty($child_post_ids) ) { | |
| 1212 | + foreach ($child_post_ids as $child_post_id) { | |
| 1213 | + wp_delete_post($child_post_id, true); | |
| 1214 | + } | |
| 1215 | + } | |
| 1216 | + } | |
| 1217 | + } | |
| 1218 | + | |
| 1219 | + /** | |
| 1220 | + * tutor course setting metabox | |
| 1221 | + * @since v.1.7.0 | |
| 1222 | + */ | |
| 1223 | + function tutor_course_setting_metabox( $post ) { | |
| 1224 | + | |
| 1225 | + $disable_qa = $this->additional_meta[0]; | |
| 1226 | + $is_public = $this->additional_meta[1]; | |
| 1227 | + | |
| 1228 | + $disable_qa_checked = get_post_meta($post->ID, $disable_qa, true)=='yes' ? 'checked="checked"' : ''; | |
| 1229 | + $is_public_checked = get_post_meta($post->ID, $is_public, true)=='yes' ? 'checked="checked"' : ''; | |
| 1230 | + | |
| 1231 | + do_action('tutor_before_course_sidebar_settings_metabox', $post); | |
| 1232 | + ?> | |
| 1233 | + <div class="tutor-course-sidebar-settings-item" id="_tutor_is_course_public_meta_checkbox" style="display:none"> | |
| 1234 | + <label for="<?php echo $is_public; ?>"> | |
| 1235 | + <input id="<?php echo $is_public; ?>" type="checkbox" name="<?php echo $is_public; ?>" value="yes" <?php echo $is_public_checked; ?> /> | |
| 1236 | + <?php _e('Make This Course Public', 'tutor'); ?> | |
| 1237 | + <small style="display:block;padding-left:24px"> | |
| 1238 | + <?php _e('No enrollment required.', 'tutor'); ?> | |
| 1239 | + </small> | |
| 1240 | + </label> | |
| 1241 | + </div> | |
| 1242 | + <div class="tutor-course-sidebar-settings-item"> | |
| 1243 | + <label for="<?php echo $disable_qa; ?>"> | |
| 1244 | + <input type="hidden" name="_tutor_course_additional_data_edit" value="true" /> | |
| 1245 | + <input id="<?php echo $disable_qa; ?>" type="checkbox" name="<?php echo $disable_qa; ?>" value="yes" <?php echo $disable_qa_checked; ?> /> | |
| 1246 | + <?php _e('Disable Q&A', 'tutor'); ?> | |
| 1247 | + </label> | |
| 1248 | + </div> | |
| 1249 | + <?php | |
| 1250 | + do_action('tutor_after_course_sidebar_settings_metabox', $post); | |
| 1251 | + } | |
| 1252 | + | |
| 1253 | + function tutor_course_setting_metabox_frontend( $post ){ | |
| 1254 | + ?> | |
| 1255 | + <div class="tutor-course-builder-section tutor-course-builder-info"> | |
| 1256 | + <div class="tutor-course-builder-section-title"> | |
| 1257 | + <h3><i class="tutor-icon-down"></i><span><?php esc_html_e('Tutor Settings', 'tutor'); ?></span></h3> | |
| 1258 | + </div> | |
| 1259 | + <div class="tutor-course-builder-section-content"> | |
| 1260 | + <div class="tutor-frontend-builder-item-scope"> | |
| 1261 | + <div class="tutor-form-group"> | |
| 1262 | + <?php $this->tutor_course_setting_metabox($post); ?> | |
| 1263 | + </div> | |
| 1264 | + </div> | |
| 1265 | + </div> | |
| 1266 | + </div> | |
| 1267 | + <?php | |
| 1268 | + } | |
| 1269 | + | |
| 1270 | + /** | |
| 1271 | + * Delete associated enrollment | |
| 1272 | + * @since v.1.8.2 | |
| 1273 | + */ | |
| 1274 | + public function delete_associated_enrollment($post_id) { | |
| 1275 | + global $wpdb; | |
| 1276 | + | |
| 1277 | + $enroll_id = $wpdb->get_var( $wpdb->prepare( | |
| 1278 | + "SELECT | |
| 1279 | + post_id | |
| 1280 | + FROM | |
| 1281 | + {$wpdb->postmeta} | |
| 1282 | + WHERE | |
| 1283 | + meta_key='_tutor_enrolled_by_order_id' | |
| 1284 | + AND meta_value = %d | |
| 1285 | + ", | |
| 1286 | + $post_id | |
| 1287 | + ) ); | |
| 1288 | + | |
| 1289 | + if(is_numeric($enroll_id) && $enroll_id>0) { | |
| 1290 | + | |
| 1291 | + $course_id = get_post_field('post_parent', $enroll_id); | |
| 1292 | + $user_id = get_post_field('post_author', $enroll_id); | |
| 1293 | + | |
| 1294 | + tutils()->cancel_course_enrol($course_id, $user_id); | |
| 1295 | + } | |
| 1296 | + } | |
| 523 | 1297 | } |