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