woothemes /
sensei
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly |
||
| 3 | |||
| 4 | /** |
||
| 5 | * Sensei Teacher class |
||
| 6 | * |
||
| 7 | * All functionality pertaining to the teacher role. |
||
| 8 | * |
||
| 9 | * @package Users |
||
| 10 | * @author Automattic |
||
| 11 | * @since 1.0.0 |
||
| 12 | */ |
||
| 13 | class Sensei_Teacher { |
||
| 14 | |||
| 15 | /** |
||
| 16 | * $teacher_role |
||
| 17 | * |
||
| 18 | * Keeps a reference to the teacher role object |
||
| 19 | * |
||
| 20 | * @access protected |
||
| 21 | * @since 1.8.0 |
||
| 22 | */ |
||
| 23 | protected $teacher_role; |
||
| 24 | |||
| 25 | /** |
||
| 26 | * $token |
||
| 27 | * |
||
| 28 | * Keeps a reference to the global sensei token |
||
| 29 | * |
||
| 30 | * @access protected |
||
| 31 | * @since 1.8.0 |
||
| 32 | */ |
||
| 33 | public $token; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * Sensei_Teacher::__constructor |
||
| 37 | * |
||
| 38 | * Constructor Function |
||
| 39 | * |
||
| 40 | * @since 1.8.0 |
||
| 41 | * @access public |
||
| 42 | */ |
||
| 43 | public function __construct ( ) { |
||
| 44 | |||
| 45 | add_action( 'add_meta_boxes', array( $this , 'add_teacher_meta_boxes' ) , 10, 2 ); |
||
| 46 | add_action( 'save_post', array( $this, 'save_teacher_meta_box' ) ); |
||
| 47 | add_filter( 'parse_query', array( $this, 'limit_teacher_edit_screen_post_types' )); |
||
| 48 | add_filter( 'pre_get_posts', array( $this, 'course_analysis_teacher_access_limit' ) ); |
||
| 49 | add_filter( 'wp_count_posts', array( $this, 'list_table_counts' ), 10, 3 ); |
||
| 50 | |||
| 51 | add_action( 'pre_get_posts', array( $this, 'filter_queries' ) ); |
||
| 52 | |||
| 53 | //filter the quiz submissions |
||
| 54 | add_filter( 'sensei_check_for_activity' , array( $this, 'filter_grading_activity_queries') ); |
||
| 55 | |||
| 56 | //grading totals count only those belonging to the teacher |
||
| 57 | add_filter('sensei_count_statuses_args', array( $this, 'limit_grading_totals' ) ); |
||
| 58 | |||
| 59 | // show the courses owned by a user on his author archive page |
||
| 60 | add_filter( 'pre_get_posts', array( $this, 'add_courses_to_author_archive' ) ); |
||
| 61 | |||
| 62 | // notify admin when a teacher creates a course |
||
| 63 | add_action( 'transition_post_status',array( $this, 'notify_admin_teacher_course_creation' ), 10, 3 ); |
||
| 64 | |||
| 65 | // limit the analysis view to only the users taking courses belong to this teacher |
||
| 66 | add_filter( 'sensei_analysis_overview_filter_users',array( $this, 'limit_analysis_learners' ) , 5, 1 ); |
||
| 67 | |||
| 68 | // give teacher access to question post type |
||
| 69 | add_filter( 'sensei_lesson_quiz_questions', array( $this, 'allow_teacher_access_to_questions' ), 20, 2 ); |
||
| 70 | |||
| 71 | // Teacher column on the courses list on the admin edit screen |
||
| 72 | add_filter('manage_edit-course_columns' , array( $this, 'course_column_heading'), 10,1 ); |
||
| 73 | add_filter('manage_course_posts_custom_column' , array( $this, 'course_column_data'), 10,2 ); |
||
| 74 | |||
| 75 | //admin edit messages query limit teacher |
||
| 76 | add_filter( 'pre_get_posts', array( $this, 'limit_edit_messages_query' ) ); |
||
| 77 | |||
| 78 | //add filter by teacher on courses list |
||
| 79 | add_action( 'restrict_manage_posts', array( $this, 'course_teacher_filter_options' ) ); |
||
| 80 | add_filter( 'request', array( $this, 'teacher_filter_query_modify' ) ); |
||
| 81 | |||
| 82 | // Handle media library restrictions |
||
| 83 | add_filter( 'request', array( $this, 'restrict_media_library' ), 10, 1 ); |
||
| 84 | add_filter( 'ajax_query_attachments_args', array( $this, 'restrict_media_library_modal' ), 10, 1 ); |
||
| 85 | |||
| 86 | // update lesson owner to course teacher when saved |
||
| 87 | add_action( 'save_post', array( $this, 'update_lesson_teacher' ) ); |
||
| 88 | |||
| 89 | // If a Teacher logs in, redirect to /wp-admin/ |
||
| 90 | add_filter( 'wp_login', array( $this, 'teacher_login_redirect') , 10, 2 ); |
||
| 91 | |||
| 92 | |||
| 93 | add_action( 'admin_menu', array( $this, 'restrict_posts_menu_page'), 10); |
||
| 94 | add_filter('pre_get_comments', array ($this, 'restrict_comment_moderation'), 10, 1); |
||
| 95 | |||
| 96 | |||
| 97 | } // end __constructor() |
||
| 98 | |||
| 99 | /** |
||
| 100 | * Sensei_Teacher::create_teacher_role |
||
| 101 | * |
||
| 102 | * This function checks if the role exist, if not it creates it. |
||
| 103 | * for the teacher role |
||
| 104 | * |
||
| 105 | * @since 1.8.0 |
||
| 106 | * @access public |
||
| 107 | * @return void |
||
| 108 | */ |
||
| 109 | public function create_role ( ) { |
||
| 110 | |||
| 111 | // check if the role exists |
||
| 112 | $this->teacher_role = get_role( 'teacher' ); |
||
| 113 | |||
| 114 | // if the the teacher is not a valid WordPress role create it |
||
| 115 | if ( ! is_a( $this->teacher_role, 'WP_Role' ) ) { |
||
| 116 | // create the role |
||
| 117 | $this->teacher_role = add_role( 'teacher', __( 'Teacher', 'woothemes-sensei' ) ); |
||
| 118 | } |
||
| 119 | |||
| 120 | // add the capabilities before returning |
||
| 121 | $this->add_capabilities(); |
||
| 122 | |||
| 123 | }// end create_teacher_role |
||
| 124 | |||
| 125 | /** |
||
| 126 | * Sensei_Teacher::add_capabilities |
||
| 127 | * |
||
| 128 | * @since 1.8.0 |
||
| 129 | * @access protected |
||
| 130 | */ |
||
| 131 | protected function add_capabilities ( ) { |
||
| 132 | |||
| 133 | // if this is not a valid WP_Role object exit without adding anything |
||
| 134 | if( ! is_a( $this->teacher_role, 'WP_Role' ) || empty( $this->teacher_role ) ) { |
||
| 135 | return; |
||
| 136 | } |
||
| 137 | |||
| 138 | /** |
||
| 139 | * Sensei teachers capabilities array filter |
||
| 140 | * |
||
| 141 | * These capabilities will be applied to the teacher role |
||
| 142 | * @param array $capabilities |
||
| 143 | * keys: (string) $cap_name => (bool) $grant |
||
| 144 | */ |
||
| 145 | $caps = apply_filters( 'sensei_teacher_role_capabilities', array( |
||
| 146 | // General access rules |
||
| 147 | 'read' => true, |
||
| 148 | 'manage_sensei_grades' => true, |
||
| 149 | 'moderate_comments'=> true, |
||
| 150 | 'upload_files' => true, |
||
| 151 | 'edit_files' => true, |
||
| 152 | |||
| 153 | //Lessons |
||
| 154 | 'publish_lessons' => true, |
||
| 155 | 'manage_lesson_categories' => true, |
||
| 156 | 'edit_lessons' => true, |
||
| 157 | 'edit_published_lessons' => true, |
||
| 158 | 'edit_private_lessons' => true, |
||
| 159 | 'read_private_lessons' => true, |
||
| 160 | 'delete_published_lessons' => true, |
||
| 161 | |||
| 162 | // Courses |
||
| 163 | 'create_courses' => true, |
||
| 164 | 'publish_courses' => false, |
||
| 165 | 'manage_course_categories' => true, |
||
| 166 | 'edit_courses' => true, |
||
| 167 | 'edit_published_courses' => true, |
||
| 168 | 'edit_private_courses' => true, |
||
| 169 | 'read_private_courses' => true, |
||
| 170 | 'delete_published_courses' => true, |
||
| 171 | |||
| 172 | // Quiz |
||
| 173 | 'publish_quizzes' => true, |
||
| 174 | 'edit_quizzes' => true, |
||
| 175 | 'edit_published_quizzes' => true, |
||
| 176 | 'edit_private_quizzes' => true, |
||
| 177 | 'read_private_quizzes' => true, |
||
| 178 | |||
| 179 | // Questions |
||
| 180 | 'publish_questions' => true, |
||
| 181 | 'edit_questions' => true, |
||
| 182 | 'edit_published_questions' => true, |
||
| 183 | 'edit_private_questions' => true, |
||
| 184 | 'read_private_questions' => true, |
||
| 185 | |||
| 186 | //messages |
||
| 187 | 'publish_sensei_messages' => true, |
||
| 188 | 'edit_sensei_messages' => true, |
||
| 189 | 'edit_published_sensei_messages' => true, |
||
| 190 | 'edit_private_sensei_messages' => true, |
||
| 191 | 'read_private_sensei_messages' => true, |
||
| 192 | |||
| 193 | // Comments - |
||
| 194 | // Necessary cap so Teachers can moderate comments |
||
| 195 | // on their own lessons. We restrict access to other |
||
| 196 | // post types in $this->restrict_posts_menu_page() |
||
| 197 | |||
| 198 | 'edit_posts' => true, |
||
| 199 | |||
| 200 | )); |
||
| 201 | |||
| 202 | foreach ( $caps as $cap => $grant ) { |
||
| 203 | |||
| 204 | // load the capability on to the teacher role |
||
| 205 | $this->teacher_role->add_cap($cap, $grant); |
||
| 206 | |||
| 207 | } // end for each |
||
| 208 | |||
| 209 | }// end add_cap |
||
| 210 | |||
| 211 | /** |
||
| 212 | * Sensei_Teacher::teacher_meta_box |
||
| 213 | * |
||
| 214 | * Add the teacher metabox to the course post type edit screen |
||
| 215 | * |
||
| 216 | * @since 1.8.0 |
||
| 217 | * @access public |
||
| 218 | * @parameter string $post_type |
||
| 219 | * @parameter WP_Post $post |
||
| 220 | * @return void |
||
| 221 | */ |
||
| 222 | public function add_teacher_meta_boxes ( $post ) { |
||
| 223 | |||
| 224 | if( !current_user_can('manage_options') ){ |
||
| 225 | return; |
||
| 226 | } |
||
| 227 | add_meta_box( 'sensei-teacher', __( 'Teacher' , 'woothemes-sensei'), array( $this , 'teacher_meta_box_content' ), |
||
| 228 | 'course', |
||
| 229 | 'side', |
||
| 230 | 'core' |
||
| 231 | ); |
||
| 232 | |||
| 233 | } // end teacher_meta_box() |
||
| 234 | |||
| 235 | /** |
||
| 236 | * Sensei_Teacher::teacher_meta_box_content |
||
| 237 | * |
||
| 238 | * Render the teacher meta box markup |
||
| 239 | * |
||
| 240 | * @since 1.8.0 |
||
| 241 | * @access public |
||
| 242 | * @parameters |
||
| 243 | */ |
||
| 244 | public function teacher_meta_box_content ( $post ) { |
||
| 245 | |||
| 246 | // get the current author |
||
| 247 | $current_author = $post->post_author; |
||
| 248 | |||
| 249 | //get the users authorised to author courses |
||
| 250 | $users = $this->get_teachers_and_authors(); |
||
| 251 | |||
| 252 | ?> |
||
| 253 | <select name="sensei-course-teacher-author" class="sensei course teacher"> |
||
| 254 | |||
| 255 | <?php foreach ( $users as $user_id ) { ?> |
||
| 256 | |||
| 257 | <?php |
||
| 258 | $user = get_user_by('id', $user_id); |
||
| 259 | ?> |
||
| 260 | <option <?php selected( $current_author , $user_id , true ); ?> value="<?php echo $user_id; ?>" > |
||
| 261 | <?php echo $user->display_name; ?> |
||
| 262 | </option> |
||
| 263 | |||
| 264 | <?php }// end for each ?> |
||
| 265 | |||
| 266 | </select> |
||
| 267 | |||
| 268 | <?php |
||
| 269 | |||
| 270 | } // end render_teacher_meta_box() |
||
| 271 | |||
| 272 | /** |
||
| 273 | * Sensei_Teacher::get_teachers_and_authors |
||
| 274 | * |
||
| 275 | * Get a list of users who can author courses, lessons and quizes. |
||
| 276 | * |
||
| 277 | * @since 1.8.0 |
||
| 278 | * @access public |
||
| 279 | * @parameters |
||
| 280 | * @return array $users user id array |
||
| 281 | */ |
||
| 282 | public function get_teachers_and_authors ( ){ |
||
| 283 | |||
| 284 | $author_query_args = array( |
||
| 285 | 'blog_id' => $GLOBALS['blog_id'], |
||
| 286 | 'fields' => 'any', |
||
| 287 | 'who' => 'authors' |
||
| 288 | ); |
||
| 289 | |||
| 290 | $authors = get_users( $author_query_args ); |
||
| 291 | |||
| 292 | $teacher_query_args = array( |
||
| 293 | 'blog_id' => $GLOBALS['blog_id'], |
||
| 294 | 'fields' => 'any', |
||
| 295 | 'role' => 'teacher', |
||
| 296 | ); |
||
| 297 | |||
| 298 | $teachers = get_users( $teacher_query_args ); |
||
| 299 | |||
| 300 | return array_unique( array_merge( $teachers, $authors ) ); |
||
| 301 | |||
| 302 | }// end get_teachers_and_authors |
||
| 303 | |||
| 304 | /** |
||
| 305 | * Sensei_Teacher::save_teacher_meta_box |
||
| 306 | * |
||
| 307 | * Save the new teacher / author to course and all lessons |
||
| 308 | * |
||
| 309 | * Hooked into admin_init |
||
| 310 | * |
||
| 311 | * @since 1.8.0 |
||
| 312 | * @access public |
||
| 313 | * @parameters |
||
| 314 | * @return array $users user id array |
||
| 315 | */ |
||
| 316 | public function save_teacher_meta_box ( $course_id ){ |
||
| 317 | |||
| 318 | // check if this is a post from saving the teacher, if not exit early |
||
| 319 | if(! isset( $_POST[ 'sensei-course-teacher-author' ] ) || ! isset( $_POST['post_ID'] ) ){ |
||
| 320 | return; |
||
| 321 | } |
||
| 322 | |||
| 323 | //don't fire this hook again |
||
| 324 | remove_action('save_post', array( $this, 'save_teacher_meta_box' ) ); |
||
| 325 | |||
| 326 | // get the current post object |
||
| 327 | $post = get_post( $course_id ); |
||
| 328 | |||
| 329 | // get the current teacher/author |
||
| 330 | $current_author = absint( $post->post_author ); |
||
| 331 | $new_author = absint( $_POST[ 'sensei-course-teacher-author' ] ); |
||
| 332 | |||
| 333 | // loop through all post lessons to update their authors as well |
||
| 334 | $this->update_course_lessons_author( $course_id , $new_author ); |
||
| 335 | |||
| 336 | // do not do any processing if the selected author is the same as the current author |
||
| 337 | if( $current_author == $new_author ){ |
||
| 338 | return; |
||
| 339 | } |
||
| 340 | |||
| 341 | // save the course author |
||
| 342 | $post_updates = array( |
||
| 343 | 'ID' => $post->ID , |
||
| 344 | 'post_author' => $new_author |
||
| 345 | ); |
||
| 346 | wp_update_post( $post_updates ); |
||
| 347 | |||
| 348 | // ensure the the modules are update so that then new teacher has access to them |
||
| 349 | Sensei_Teacher::update_course_modules_author( $course_id, $new_author ); |
||
| 350 | |||
| 351 | // notify the new teacher |
||
| 352 | $this->teacher_course_assigned_notification( $new_author, $course_id ); |
||
| 353 | |||
| 354 | } // end save_teacher_meta_box |
||
| 355 | |||
| 356 | /** |
||
| 357 | * Update all the course terms set(selected) on the given course. Moving course term ownership to |
||
| 358 | * the new author. Making sure the course terms are maintained. |
||
| 359 | * |
||
| 360 | * This function also checks if terms are shared, with other courses |
||
| 361 | * |
||
| 362 | * @param $course_id |
||
| 363 | * @param $new_teacher_id |
||
| 364 | * @return void |
||
| 365 | */ |
||
| 366 | public static function update_course_modules_author( $course_id ,$new_teacher_id ){ |
||
| 367 | |||
| 368 | if( empty( $course_id ) || empty( $new_teacher_id ) ){ |
||
| 369 | return; |
||
| 370 | } |
||
| 371 | |||
| 372 | $terms_selected_on_course = wp_get_object_terms( $course_id, 'module' ); |
||
| 373 | |||
| 374 | if( empty( $terms_selected_on_course ) ){ |
||
| 375 | return; |
||
| 376 | } |
||
| 377 | |||
| 378 | foreach( $terms_selected_on_course as $term ){ |
||
| 379 | |||
| 380 | $term_author = Sensei_Core_Modules::get_term_author( $term->slug ); |
||
| 381 | if( $new_teacher_id != $term_author->ID ){ |
||
| 382 | |||
| 383 | $new_term = ''; |
||
| 384 | |||
| 385 | //if the new teacher is admin first check to see if the term with this name already exists |
||
| 386 | if( user_can( $new_teacher_id, 'manage_options' ) ){ |
||
| 387 | |||
| 388 | $slug_without_teacher_id = str_ireplace(' ', '-', trim( $term->name ) ); |
||
| 389 | $term_args = array( 'slug'=> $slug_without_teacher_id, 'hide_empty' => false, ); |
||
| 390 | $existing_admin_terms = get_terms( 'module', $term_args ); |
||
| 391 | if( !empty( $existing_admin_terms ) ){ |
||
| 392 | // insert it even if it exists |
||
| 393 | $new_term = get_term( $existing_admin_terms[0]->term_id, 'module', ARRAY_A ); |
||
| 394 | } |
||
| 395 | } |
||
| 396 | |||
| 397 | if( empty ( $new_term ) ){ |
||
| 398 | |||
| 399 | //setup the new slug |
||
| 400 | $new_author_term_slug = $new_teacher_id . '-' . str_ireplace(' ', '-', trim( $term->name ) ); |
||
| 401 | |||
| 402 | // create new term and set it |
||
| 403 | $new_term = wp_insert_term( $term->name,'module', array('slug'=> $new_author_term_slug ) ); |
||
| 404 | |||
| 405 | } |
||
| 406 | |||
| 407 | |||
| 408 | |||
| 409 | // if term exists |
||
| 410 | if( is_wp_error( $new_term ) && isset( $new_term->errors['term_exists'] ) ){ |
||
| 411 | |||
| 412 | $existing_term = get_term_by( 'slug', $new_author_term_slug, 'module'); |
||
| 413 | $term_id = $existing_term->term_id; |
||
| 414 | |||
| 415 | }else{ |
||
| 416 | |||
| 417 | // for a new term simply get the term from the returned value |
||
| 418 | $term_id = $new_term['term_id']; |
||
| 419 | |||
| 420 | } // end if term exist |
||
| 421 | |||
| 422 | // set the terms selected on the course |
||
| 423 | wp_set_object_terms( $course_id, $term_id , 'module', true ); |
||
| 424 | |||
| 425 | // remove old term |
||
| 426 | wp_remove_object_terms( $course_id, $term->term_id, 'module' ); |
||
| 427 | |||
| 428 | // update the lessons within the current module term |
||
| 429 | $lessons = Sensei()->course->course_lessons( $course_id ); |
||
| 430 | foreach( $lessons as $lesson ){ |
||
| 431 | |||
| 432 | if( has_term( $term->slug, 'module', $lesson ) ){ |
||
| 433 | |||
| 434 | // add the new term, the false at the end says to replace all terms on this module |
||
| 435 | // with the new term. |
||
| 436 | wp_set_object_terms( $lesson->ID, $term_id , 'module', false ); |
||
| 437 | update_post_meta( $lesson->ID, '_order_module_' . intval( $term_id ), 0 ); |
||
| 438 | } |
||
| 439 | |||
| 440 | }// end for each |
||
| 441 | |||
| 442 | } |
||
| 443 | } |
||
| 444 | |||
| 445 | }// end update_course_module_terms_author |
||
| 446 | |||
| 447 | /** |
||
| 448 | * Sensei_Teacher::update_course_lessons_author |
||
| 449 | * |
||
| 450 | * Update all course lessons and their quiz with a new author |
||
| 451 | * |
||
| 452 | * @since 1.8.0 |
||
| 453 | * @access public |
||
| 454 | * @parameters |
||
| 455 | * @return array $users user id array |
||
| 456 | */ |
||
| 457 | public function update_course_lessons_author ( $course_id, $new_author ){ |
||
| 458 | |||
| 459 | |||
| 460 | if( empty( $course_id ) || empty( $new_author ) ){ |
||
| 461 | return false; |
||
| 462 | } |
||
| 463 | |||
| 464 | //get a list of course lessons |
||
| 465 | $lessons = Sensei()->course->course_lessons( $course_id ); |
||
| 466 | |||
| 467 | if( empty( $lessons ) || ! is_array( $lessons ) ){ |
||
| 468 | return false; |
||
| 469 | } |
||
| 470 | |||
| 471 | // update each lesson and quiz author |
||
| 472 | foreach( $lessons as $lesson ){ |
||
| 473 | |||
| 474 | // don't update if the author is tha same as the new author |
||
| 475 | if( $new_author == $lesson->post_author ){ |
||
| 476 | continue; |
||
| 477 | } |
||
| 478 | |||
| 479 | // update lesson author |
||
| 480 | wp_update_post( array( |
||
| 481 | 'ID'=> $lesson->ID, |
||
| 482 | 'post_author' => $new_author |
||
| 483 | ) ); |
||
| 484 | |||
| 485 | // update quiz author |
||
| 486 | //get the lessons quiz |
||
| 487 | $lesson_quizzes = Sensei()->lesson->lesson_quizzes( $lesson->ID ); |
||
| 488 | if( is_array( $lesson_quizzes ) ){ |
||
| 489 | foreach ( $lesson_quizzes as $quiz_id ) { |
||
| 490 | // update quiz with new author |
||
| 491 | wp_update_post( array( |
||
| 492 | 'ID' => $quiz_id, |
||
| 493 | 'post_author' => $new_author |
||
| 494 | ) ); |
||
| 495 | } |
||
| 496 | }else{ |
||
| 497 | wp_update_post( array( |
||
| 498 | 'ID' => $lesson_quizzes, |
||
| 499 | 'post_author' => $new_author |
||
| 500 | ) ); |
||
| 501 | } |
||
| 502 | |||
| 503 | } // end for each lessons |
||
| 504 | |||
| 505 | return true; |
||
| 506 | |||
| 507 | }// end update_course_lessons_author |
||
| 508 | |||
| 509 | |||
| 510 | |||
| 511 | /** |
||
| 512 | * Sensei_Teacher::course_analysis_teacher_access_limit |
||
| 513 | * |
||
| 514 | * Alter the query so that users can only see their courses on the analysis page |
||
| 515 | * |
||
| 516 | * @since 1.8.0 |
||
| 517 | * @access public |
||
| 518 | * @parameters $query |
||
| 519 | * @return array $users user id array |
||
| 520 | */ |
||
| 521 | public function course_analysis_teacher_access_limit ( $query ) { |
||
| 522 | |||
| 523 | if( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) { |
||
| 524 | return $query; |
||
| 525 | } |
||
| 526 | |||
| 527 | if ( ! function_exists( 'get_current_screen' ) ) { |
||
| 528 | return $query; |
||
| 529 | } |
||
| 530 | |||
| 531 | $screen = get_current_screen(); |
||
| 532 | $sensei_post_types = array('course', 'lesson', 'question' ); |
||
| 533 | |||
| 534 | // exit early for the following conditions |
||
| 535 | $limit_screen_ids = array( 'sensei_page_sensei_analysis', 'course_page_module-order' ); |
||
| 536 | |||
| 537 | if( ! $this->is_admin_teacher() || empty( $screen ) || ! in_array( $screen->id ,$limit_screen_ids ) |
||
| 538 | || ! in_array( $query->query['post_type'], $sensei_post_types ) ){ |
||
| 539 | return $query; |
||
| 540 | } |
||
| 541 | |||
| 542 | global $current_user; |
||
| 543 | // set the query author to the current user to only show those those posts |
||
| 544 | $query->set( 'author', $current_user->ID ); |
||
| 545 | return $query; |
||
| 546 | |||
| 547 | }// end course_analysis_teacher_access_limit |
||
| 548 | |||
| 549 | |||
| 550 | /** |
||
| 551 | * Sensei_Teacher::limit_teacher_edit_screen_post_types |
||
| 552 | * |
||
| 553 | * Determine if we're in admin and the current logged in use is a teacher |
||
| 554 | * |
||
| 555 | * @since 1.8.0 |
||
| 556 | * @access public |
||
| 557 | * @parameters array $wp_query |
||
| 558 | * @return bool $is_admin_teacher |
||
| 559 | */ |
||
| 560 | public function is_admin_teacher ( ){ |
||
| 561 | |||
| 562 | if( ! is_user_logged_in()){ |
||
| 563 | return false; |
||
| 564 | } |
||
| 565 | $is_admin_teacher = false; |
||
| 566 | |||
| 567 | if( is_admin() && Sensei_Teacher::is_a_teacher( get_current_user_id() ) ){ |
||
| 568 | |||
| 569 | $is_admin_teacher = true; |
||
| 570 | |||
| 571 | } |
||
| 572 | |||
| 573 | return $is_admin_teacher; |
||
| 574 | |||
| 575 | } // end is_admin_teacher |
||
| 576 | |||
| 577 | /** |
||
| 578 | * Show correct post counts on list table for Sensei post types |
||
| 579 | * |
||
| 580 | * @since 1.8.0 |
||
| 581 | * |
||
| 582 | * @param object $counts Default status counts |
||
| 583 | * @param string $type Current post type |
||
| 584 | * @param string $perm User permission level |
||
| 585 | * @return object Modified status counts |
||
| 586 | */ |
||
| 587 | public function list_table_counts( $counts, $type, $perm ) { |
||
| 588 | global $current_user; |
||
| 589 | |||
| 590 | if( ! in_array( $type, array( 'course', 'lesson', 'question' ) ) ) { |
||
| 591 | return $counts; |
||
| 592 | } |
||
| 593 | |||
| 594 | if( ! $this->is_admin_teacher() ) { |
||
| 595 | return $counts; |
||
| 596 | } |
||
| 597 | |||
| 598 | $args = array( |
||
| 599 | 'post_type' => $type, |
||
| 600 | 'author' => $current_user->ID, |
||
| 601 | 'posts_per_page' => -1 |
||
| 602 | ); |
||
| 603 | |||
| 604 | // Get all available statuses |
||
| 605 | $stati = get_post_stati(); |
||
| 606 | |||
| 607 | // Update count object |
||
| 608 | foreach( $stati as $status ) { |
||
| 609 | $args['post_status'] = $status; |
||
| 610 | $posts = get_posts( $args ); |
||
| 611 | $counts->$status = count( $posts ); |
||
| 612 | } |
||
| 613 | |||
| 614 | return $counts; |
||
| 615 | } |
||
| 616 | |||
| 617 | /** |
||
| 618 | * Filter the post queries to show |
||
| 619 | * only lesson /course and users that belong |
||
| 620 | * to the current logged teacher. |
||
| 621 | * |
||
| 622 | * @since 1.8.0 |
||
| 623 | * |
||
| 624 | */ |
||
| 625 | public function filter_queries ( $query ) { |
||
| 626 | global $current_user; |
||
| 627 | |||
| 628 | if( ! $this->is_admin_teacher() ) { |
||
| 629 | return; |
||
| 630 | } |
||
| 631 | |||
| 632 | if ( ! function_exists( 'get_current_screen' ) ) { |
||
| 633 | return; |
||
| 634 | } |
||
| 635 | |||
| 636 | $screen = get_current_screen(); |
||
| 637 | if( empty( $screen ) ) { |
||
| 638 | return $query; |
||
| 639 | } |
||
| 640 | switch( $screen->id ) { |
||
| 641 | case 'sensei_page_sensei_grading': |
||
| 642 | case 'sensei_page_sensei_analysis': |
||
| 643 | case 'sensei_page_sensei_learners': |
||
| 644 | case 'lesson': |
||
| 645 | case 'course': |
||
| 646 | case 'question': |
||
| 647 | case 'lesson_page_module-order': |
||
| 648 | |||
| 649 | /** |
||
| 650 | * sensei_filter_queries_set_author |
||
| 651 | * Filter the author Sensei set for queries |
||
| 652 | * |
||
| 653 | * @since 1.8.0 |
||
| 654 | * |
||
| 655 | * @param int $user_id |
||
| 656 | * @param string $screen_id |
||
| 657 | * |
||
| 658 | */ |
||
| 659 | $query->set( 'author', apply_filters( 'sensei_filter_queries_set_author', $current_user->ID, $screen->id ) ); |
||
| 660 | break; |
||
| 661 | } |
||
| 662 | } |
||
| 663 | |||
| 664 | /** |
||
| 665 | * Limit grading quizzes to only those within courses belonging to the current teacher |
||
| 666 | * . This excludes the admin user. |
||
| 667 | * |
||
| 668 | * @since 1.8.0 |
||
| 669 | * @hooked into the_comments |
||
| 670 | * @param array $comments |
||
| 671 | * |
||
| 672 | * @return array $comments |
||
| 673 | */ |
||
| 674 | public function filter_grading_activity_queries( $comments ){ |
||
| 675 | |||
| 676 | if( !is_admin() || ! $this->is_admin_teacher() || is_numeric( $comments ) || ! is_array( $comments ) ){ |
||
| 677 | return $comments ; |
||
| 678 | } |
||
| 679 | |||
| 680 | //check if we're on the grading screen |
||
| 681 | $screen = get_current_screen(); |
||
| 682 | |||
| 683 | if( empty( $screen ) || 'sensei_page_sensei_grading' != $screen->id ){ |
||
| 684 | return $comments; |
||
| 685 | } |
||
| 686 | |||
| 687 | // get the course and determine if the current teacher is the owner |
||
| 688 | // if not remove it from the list of comments to be returned |
||
| 689 | foreach( $comments as $key => $comment){ |
||
| 690 | $lesson = get_post( $comment->comment_post_ID ); |
||
| 691 | $course_id = Sensei()->lesson->get_course_id( $lesson->ID ); |
||
| 692 | $course = get_post( $course_id ); |
||
| 693 | if( ! isset( $course->post_author ) || intval( $course->post_author) != intval( get_current_user_id() ) ){ |
||
| 694 | //remove this as the teacher should see this. |
||
| 695 | unset( $comments[ $key ] ); |
||
| 696 | } |
||
| 697 | } |
||
| 698 | return $comments ; |
||
| 699 | |||
| 700 | }// end function filter grading |
||
| 701 | |||
| 702 | /** |
||
| 703 | * Limit the grading screen totals to only show lessons in the course |
||
| 704 | * belonging to the currently logged in teacher. This only applies to |
||
| 705 | * the teacher role. |
||
| 706 | * |
||
| 707 | * @since 1.8.0 |
||
| 708 | * |
||
| 709 | * @hooked into sensei_count_statuses_args |
||
| 710 | * @param array $args |
||
| 711 | * |
||
| 712 | * @return array $args |
||
| 713 | */ |
||
| 714 | public function limit_grading_totals( $args ){ |
||
| 715 | |||
| 716 | if( !is_admin() || ! $this->is_admin_teacher() || ! is_array( $args ) ){ |
||
| 717 | return $args ; |
||
| 718 | } |
||
| 719 | |||
| 720 | //get the teachers courses |
||
| 721 | // the query is already filtered to only the teacher |
||
| 722 | $courses = Sensei()->course->get_all_courses(); |
||
| 723 | |||
| 724 | if( empty( $courses ) || ! is_array( $courses ) ){ |
||
| 725 | return $args; |
||
| 726 | } |
||
| 727 | |||
| 728 | //setup the lessons quizzes to limit the grading totals to |
||
| 729 | $quiz_scope = array(); |
||
| 730 | foreach( $courses as $course ){ |
||
| 731 | |||
| 732 | $course_lessons = Sensei()->course->course_lessons( $course->ID ); |
||
| 733 | |||
| 734 | if( ! empty( $course_lessons ) && is_array( $course_lessons ) ){ |
||
| 735 | |||
| 736 | foreach( $course_lessons as $lesson ){ |
||
| 737 | |||
| 738 | $quiz_id = Sensei()->lesson->lesson_quizzes( $lesson->ID ); |
||
| 739 | if( !empty( $quiz_id ) ) { |
||
| 740 | |||
| 741 | array_push( $quiz_scope, $quiz_id ); |
||
| 742 | |||
| 743 | } |
||
| 744 | |||
| 745 | } |
||
| 746 | |||
| 747 | } |
||
| 748 | |||
| 749 | } |
||
| 750 | |||
| 751 | $args['post__in'] = $quiz_scope; |
||
| 752 | |||
| 753 | return $args; |
||
| 754 | } |
||
| 755 | |||
| 756 | /** |
||
| 757 | * It ensures that the author archive shows course by the current user. |
||
| 758 | * |
||
| 759 | * This function is hooked into the pre_get_posts filter |
||
| 760 | * |
||
| 761 | * @param WP_Query $query |
||
| 762 | * @return WP_Query $query |
||
| 763 | */ |
||
| 764 | public function add_courses_to_author_archive( $query ) { |
||
| 765 | |||
| 766 | if ( is_admin() || ! $query->is_author() ){ |
||
| 767 | return $query; |
||
| 768 | } |
||
| 769 | |||
| 770 | // this should only apply to users with the teacher role |
||
| 771 | $current_page_user = get_user_by('login', $query->get('author_name') ); |
||
| 772 | if( ! $current_page_user || ! in_array('teacher', $current_page_user->roles ) ) { |
||
| 773 | |||
| 774 | return $query; |
||
| 775 | |||
| 776 | } |
||
| 777 | |||
| 778 | // Change post types depending on what is set already |
||
| 779 | $current_post_types = $query->get( 'post_type' ); |
||
| 780 | if( empty( $current_post_types ) ){ |
||
| 781 | |||
| 782 | // if empty it means post by default, so add post so that it also includes that for now |
||
| 783 | $new_post_types = array( 'post', 'course' ); |
||
| 784 | |||
| 785 | } elseif( is_array( $current_post_types ) ) { |
||
| 786 | |||
| 787 | // merge the post types instead of overwriting it |
||
| 788 | $new_post_types = array_merge( $current_post_types, array( 'course' ) ); |
||
| 789 | |||
| 790 | }else{ |
||
| 791 | |||
| 792 | // in this instance it is probably just one post type in string format |
||
| 793 | $new_post_types = array( $current_post_types , 'course'); |
||
| 794 | |||
| 795 | } |
||
| 796 | |||
| 797 | // change the query before returning it |
||
| 798 | $query->set('post_type', $new_post_types ); |
||
| 799 | |||
| 800 | /** |
||
| 801 | * Change the query on the teacher author archive template |
||
| 802 | * |
||
| 803 | * @since 1.8.4 |
||
| 804 | * @param WP_Query $query |
||
| 805 | */ |
||
| 806 | return apply_filters( 'sensei_teacher_archive_query', $query ); |
||
| 807 | |||
| 808 | } |
||
| 809 | |||
| 810 | /** |
||
| 811 | * Notify teacher when someone assigns a course to their account. |
||
| 812 | * |
||
| 813 | * @since 1.8.0 |
||
| 814 | * |
||
| 815 | * @param $teacher_id |
||
| 816 | * @param $course_id |
||
| 817 | * @return bool |
||
| 818 | */ |
||
| 819 | public function teacher_course_assigned_notification( $teacher_id, $course_id ){ |
||
| 820 | |||
| 821 | if( 'course' != get_post_type( $course_id ) || ! get_userdata( $teacher_id ) ){ |
||
| 822 | return false; |
||
| 823 | } |
||
| 824 | |||
| 825 | // if new user is the same as the current logged user, they don't need an email |
||
| 826 | if( $teacher_id == get_current_user_id() ){ |
||
| 827 | return true; |
||
| 828 | } |
||
| 829 | |||
| 830 | // load the email class |
||
| 831 | include('emails/class-sensei-email-teacher-new-course-assignment.php'); |
||
| 832 | $email = new Sensei_Email_Teacher_New_Course_Assignment(); |
||
| 833 | $email->trigger( $teacher_id, $course_id ); |
||
| 834 | |||
| 835 | return true; |
||
| 836 | } // end teacher_course_assigned_notification |
||
| 837 | |||
| 838 | /** |
||
| 839 | * Email the admin when a teacher creates a new course |
||
| 840 | * |
||
| 841 | * This function hooks into wp_insert_post |
||
| 842 | * |
||
| 843 | * @since 1.8.0 |
||
| 844 | * @param int $course_id |
||
| 845 | * @return bool |
||
| 846 | */ |
||
| 847 | public function notify_admin_teacher_course_creation( $new_status, $old_status, $post ){ |
||
| 848 | |||
| 849 | $course_id = $post->ID; |
||
| 850 | |||
| 851 | if( 'publish'== $old_status || 'course' != get_post_type( $course_id ) || 'auto-draft' == get_post_status( $course_id ) |
||
| 852 | || 'trash' == get_post_status( $course_id ) || 'draft' == get_post_status( $course_id ) ) { |
||
| 853 | |||
| 854 | return false; |
||
| 855 | |||
| 856 | } |
||
| 857 | |||
| 858 | /** |
||
| 859 | * Filter the option to send admin notification emails when teachers creation |
||
| 860 | * course. |
||
| 861 | * |
||
| 862 | * @since 1.8.0 |
||
| 863 | * |
||
| 864 | * @param bool $on default true |
||
| 865 | */ |
||
| 866 | if( ! apply_filters('sensei_notify_admin_new_course_creation', true ) ){ |
||
| 867 | return false; |
||
| 868 | } |
||
| 869 | |||
| 870 | // setting up the data needed by the email template |
||
| 871 | global $sensei_email_data; |
||
| 872 | $template = 'admin-teacher-new-course-created'; |
||
| 873 | $course = get_post( $course_id ); |
||
| 874 | $teacher = new WP_User( $course->post_author ); |
||
| 875 | $recipient = get_option('admin_email', true); |
||
| 876 | |||
| 877 | // don't send if the course is created by admin |
||
| 878 | if( $recipient == $teacher->user_email || current_user_can( 'manage_options' )){ |
||
| 879 | return false; |
||
| 880 | } |
||
| 881 | |||
| 882 | /** |
||
| 883 | * Filter the email Header for the admin-teacher-new-course-created template |
||
| 884 | * |
||
| 885 | * @since 1.8.0 |
||
| 886 | * @param string $template |
||
| 887 | */ |
||
| 888 | $heading = apply_filters( 'sensei_email_heading', __( 'New course created.', 'woothemes-sensei' ), $template ); |
||
| 889 | |||
| 890 | /** |
||
| 891 | * Filter the email subject for the the |
||
| 892 | * admin-teacher-new-course-created template |
||
| 893 | * |
||
| 894 | * @since 1.8.0 |
||
| 895 | * @param string $subject default New course assigned to you |
||
| 896 | * @param string $template |
||
| 897 | */ |
||
| 898 | $subject = apply_filters('sensei_email_subject', |
||
| 899 | '['. get_bloginfo( 'name', 'display' ) .'] '. __( 'New course created by', 'woothemes-sensei' ) . ' ' . $teacher->display_name , |
||
| 900 | $template ); |
||
| 901 | |||
| 902 | //course edit link |
||
| 903 | $course_edit_link = admin_url('post.php?post=' . $course_id . '&action=edit' ); |
||
| 904 | |||
| 905 | // Construct data array |
||
| 906 | $email_data = array( |
||
| 907 | 'template' => $template, |
||
| 908 | 'heading' => $heading, |
||
| 909 | 'teacher' => $teacher, |
||
| 910 | 'course_id' => $course_id, |
||
| 911 | 'course_name' => $course->post_title, |
||
| 912 | 'course_edit_link' => $course_edit_link, |
||
| 913 | ); |
||
| 914 | |||
| 915 | /** |
||
| 916 | * Filter the sensei email data for the admin-teacher-new-course-created template |
||
| 917 | * |
||
| 918 | * @since 1.8.0 |
||
| 919 | * @param array $email_data |
||
| 920 | * @param string $template |
||
| 921 | */ |
||
| 922 | $sensei_email_data = apply_filters( 'sensei_email_data', $email_data , $template ); |
||
| 923 | |||
| 924 | // Send mail |
||
| 925 | Sensei()->emails->send( $recipient, $subject , Sensei()->emails->get_content( $template ) ); |
||
| 926 | |||
| 927 | }// end notify admin of course creation |
||
| 928 | |||
| 929 | /** |
||
| 930 | * Limit the analysis view to only the users taking courses belong to this teacher |
||
| 931 | * |
||
| 932 | * Hooked into sensei_analysis_get_learners |
||
| 933 | * @param array $args WP_User_Query arguments |
||
| 934 | * @return array $learners_query_results |
||
| 935 | */ |
||
| 936 | public function limit_analysis_learners( $args ){ |
||
| 937 | |||
| 938 | // show default for none teachers |
||
| 939 | if( ! Sensei()->teacher->is_admin_teacher() ) { |
||
| 940 | return $args; |
||
| 941 | } |
||
| 942 | |||
| 943 | // for teachers all courses only return those which belong to the teacher |
||
| 944 | // as they don't have access to course belonging to other users |
||
| 945 | $teacher_courses = Sensei()->course->get_all_courses(); |
||
| 946 | |||
| 947 | // if the user has no courses they should see no users |
||
| 948 | if( empty( $teacher_courses ) || ! is_array( $teacher_courses ) ){ |
||
| 949 | // tell the query to return 0 students |
||
| 950 | $args[ 'include'] = array( 0 ); |
||
| 951 | return $args; |
||
| 952 | |||
| 953 | } |
||
| 954 | |||
| 955 | $learner_ids_for_teacher_courses = array(); |
||
| 956 | foreach( $teacher_courses as $course ){ |
||
| 957 | |||
| 958 | $course_learner_ids = array(); |
||
| 959 | $activity_comments = Sensei_Utils::sensei_check_for_activity( array( 'post_id' => $course->ID, 'type' => 'sensei_course_status', 'field' => 'user_id' ), true ); |
||
| 960 | |||
| 961 | if( empty( $activity_comments ) || ( is_array( $activity_comments ) && ! ( count( $activity_comments ) > 0 ) ) ){ |
||
| 962 | continue; // skip to the next course as there are no users on this course |
||
| 963 | } |
||
| 964 | |||
| 965 | // it could be an array of comments or a single comment |
||
| 966 | if( is_array( $activity_comments ) ){ |
||
| 967 | |||
| 968 | foreach( $activity_comments as $comment ){ |
||
| 969 | |||
| 970 | $user = get_userdata( $comment->user_id ); |
||
| 971 | |||
| 972 | if( empty( $user ) ){ |
||
| 973 | // next comment in this array |
||
| 974 | continue; |
||
| 975 | } |
||
| 976 | |||
| 977 | $course_learner_ids[] = $user->ID; |
||
| 978 | } |
||
| 979 | |||
| 980 | }else{ |
||
| 981 | |||
| 982 | $user = get_userdata( $activity_comments->user_id ); |
||
| 983 | $course_learner_ids[] = $user->ID; |
||
| 984 | |||
| 985 | } |
||
| 986 | |||
| 987 | // add learners on this course to the all courses learner list |
||
| 988 | $learner_ids_for_teacher_courses = array_merge( $learner_ids_for_teacher_courses, $course_learner_ids ); |
||
| 989 | |||
| 990 | } |
||
| 991 | |||
| 992 | // if there are no students taking the courses by this teacher don't show them any of the other users |
||
| 993 | if( empty( $learner_ids_for_teacher_courses ) ){ |
||
| 994 | |||
| 995 | $args[ 'include'] = array( 0 ); |
||
| 996 | |||
| 997 | }else{ |
||
| 998 | |||
| 999 | $args[ 'include'] = $learner_ids_for_teacher_courses; |
||
| 1000 | |||
| 1001 | } |
||
| 1002 | |||
| 1003 | // return the WP_Use_Query arguments |
||
| 1004 | return $args; |
||
| 1005 | |||
| 1006 | }// end limit_analysis_learners |
||
| 1007 | |||
| 1008 | /** |
||
| 1009 | * Give teacher full admin access to the question post type |
||
| 1010 | * in certain cases. |
||
| 1011 | * |
||
| 1012 | * @since 1.8.0 |
||
| 1013 | * @param $questions |
||
| 1014 | * @return mixed |
||
| 1015 | */ |
||
| 1016 | public function allow_teacher_access_to_questions( $questions, $quiz_id ){ |
||
| 1017 | |||
| 1018 | if( ! $this->is_admin_teacher() ){ |
||
| 1019 | return $questions; |
||
| 1020 | } |
||
| 1021 | |||
| 1022 | $screen = get_current_screen(); |
||
| 1023 | |||
| 1024 | // don't run this filter within this functions call to Sensei()->lesson->lesson_quiz_questions |
||
| 1025 | remove_filter( 'sensei_lesson_quiz_questions', array( $this, 'allow_teacher_access_to_questions' ), 20 ); |
||
| 1026 | |||
| 1027 | if( ! empty( $screen ) && 'lesson'== $screen->post_type ){ |
||
| 1028 | |||
| 1029 | $admin_user = get_user_by('email', get_bloginfo('admin_email')); |
||
| 1030 | if( ! empty($admin_user) ){ |
||
| 1031 | |||
| 1032 | $current_teacher_id = get_current_user_id(); |
||
| 1033 | |||
| 1034 | // set current user to admin so teacher can view all questions |
||
| 1035 | wp_set_current_user( $admin_user->ID ); |
||
| 1036 | $questions = Sensei()->lesson->lesson_quiz_questions( $quiz_id ); |
||
| 1037 | |||
| 1038 | // set the teacher as the current use again |
||
| 1039 | wp_set_current_user( $current_teacher_id ); |
||
| 1040 | } |
||
| 1041 | |||
| 1042 | } |
||
| 1043 | // attach the filter again for other funtion calls to Sensei()->lesson->lesson_quiz_questions |
||
| 1044 | add_filter( 'sensei_lesson_quiz_questions', array( $this, 'allow_teacher_access_to_questions' ), 20,2 ); |
||
| 1045 | |||
| 1046 | return $questions; |
||
| 1047 | } |
||
| 1048 | |||
| 1049 | /** |
||
| 1050 | * Give the teacher role access to questions from the question bank |
||
| 1051 | * |
||
| 1052 | * @since 1.8.0 |
||
| 1053 | * @param $wp_query |
||
| 1054 | * @return mixed |
||
| 1055 | */ |
||
| 1056 | public function give_access_to_all_questions( $wp_query ){ |
||
| 1057 | |||
| 1058 | if( ! $this->is_admin_teacher() || !function_exists( 'get_current_screen') || 'question' != $wp_query->get('post_type') ){ |
||
| 1059 | |||
| 1060 | return $wp_query; |
||
| 1061 | } |
||
| 1062 | |||
| 1063 | $screen = get_current_screen(); |
||
| 1064 | if( ( isset($screen->id) && 'lesson' == $screen->id ) |
||
| 1065 | || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ){ |
||
| 1066 | |||
| 1067 | $admin_user = get_user_by('email', get_bloginfo('admin_email')); |
||
| 1068 | if( ! empty($admin_user) ){ |
||
| 1069 | |||
| 1070 | $current_teacher_id = get_current_user_id(); |
||
| 1071 | |||
| 1072 | // set current user to admin so teacher can view all questions |
||
| 1073 | wp_set_current_user( $admin_user->ID ); |
||
| 1074 | |||
| 1075 | //run new query as admin |
||
| 1076 | $wp_query = new WP_Query( $wp_query->query ); |
||
| 1077 | |||
| 1078 | //set the teache as current use again |
||
| 1079 | wp_set_current_user( $current_teacher_id ); |
||
| 1080 | |||
| 1081 | } |
||
| 1082 | } |
||
| 1083 | |||
| 1084 | return $wp_query; |
||
| 1085 | }// end give_access_to_all_questions |
||
| 1086 | |||
| 1087 | /** |
||
| 1088 | * Add new column heading to the course admin edit list |
||
| 1089 | * |
||
| 1090 | * @since 1.8.0 |
||
| 1091 | * @param $columns |
||
| 1092 | * @return array |
||
| 1093 | */ |
||
| 1094 | public function course_column_heading($columns) { |
||
| 1095 | |||
| 1096 | if( $this->is_admin_teacher() ){ |
||
| 1097 | return $columns; |
||
| 1098 | } |
||
| 1099 | $new_columns = array( |
||
| 1100 | 'teacher' => __('Teacher', 'woothemes-sensei'), |
||
| 1101 | ); |
||
| 1102 | return array_merge($columns, $new_columns); |
||
| 1103 | |||
| 1104 | }// end teacher column add |
||
| 1105 | |||
| 1106 | /** |
||
| 1107 | * Print out teacher column data |
||
| 1108 | * |
||
| 1109 | * @since 1.8.0 |
||
| 1110 | * @param $column |
||
| 1111 | * @param $course_id |
||
| 1112 | */ |
||
| 1113 | public function course_column_data( $column, $course_id ){ |
||
| 1114 | |||
| 1115 | if( $this->is_admin_teacher() || 'teacher' != $column ){ |
||
| 1116 | return; |
||
| 1117 | } |
||
| 1118 | |||
| 1119 | $course = get_post( $course_id ); |
||
| 1120 | $teacher = get_userdata( $course->post_author ); |
||
| 1121 | |||
| 1122 | if( !$teacher ){ |
||
| 1123 | return; |
||
| 1124 | } |
||
| 1125 | |||
| 1126 | echo '<a href="'. get_edit_user_link( $teacher->ID ) .'" >'. $teacher->display_name.'</a>'; |
||
| 1127 | |||
| 1128 | }// end course_column_ data |
||
| 1129 | |||
| 1130 | /** |
||
| 1131 | * Return only courses belonging to the given teacher. |
||
| 1132 | * |
||
| 1133 | * |
||
| 1134 | * @since 1.8.0 |
||
| 1135 | * |
||
| 1136 | * @param int $teacher_id |
||
| 1137 | * @param bool $return_ids_only |
||
| 1138 | * |
||
| 1139 | * @return array $teachers_courses |
||
| 1140 | */ |
||
| 1141 | public function get_teacher_courses( $teacher_id, $return_ids_only= false){ |
||
| 1142 | |||
| 1143 | $teachers_courses = array(); |
||
| 1144 | |||
| 1145 | if( empty( $teacher_id ) ){ |
||
| 1146 | $teacher_id = get_current_user_id(); |
||
| 1147 | } |
||
| 1148 | |||
| 1149 | $all_courses = Sensei()->course->get_all_courses(); |
||
| 1150 | |||
| 1151 | if( empty( $all_courses ) ){ |
||
| 1152 | return $all_courses; |
||
| 1153 | } |
||
| 1154 | |||
| 1155 | foreach( $all_courses as $course ){ |
||
| 1156 | |||
| 1157 | if( $course->post_author != $teacher_id ){ |
||
| 1158 | continue; |
||
| 1159 | } |
||
| 1160 | |||
| 1161 | if( $return_ids_only ){ |
||
| 1162 | |||
| 1163 | $teachers_courses[] = $course->ID; |
||
| 1164 | |||
| 1165 | }else{ |
||
| 1166 | |||
| 1167 | $teachers_courses[] = $course; |
||
| 1168 | |||
| 1169 | } |
||
| 1170 | |||
| 1171 | } |
||
| 1172 | |||
| 1173 | return $teachers_courses; |
||
| 1174 | |||
| 1175 | } |
||
| 1176 | |||
| 1177 | /** |
||
| 1178 | * Limit the message display to only those sent to the current teacher |
||
| 1179 | * |
||
| 1180 | * @since 1.8.0 |
||
| 1181 | * |
||
| 1182 | * @param $query |
||
| 1183 | * @return mixed |
||
| 1184 | */ |
||
| 1185 | public function limit_edit_messages_query( $query ){ |
||
| 1186 | if( ! $this->is_admin_teacher() || 'sensei_message' != $query->get('post_type') ){ |
||
| 1187 | return $query; |
||
| 1188 | } |
||
| 1189 | |||
| 1190 | $teacher = wp_get_current_user(); |
||
| 1191 | |||
| 1192 | $query->set( 'meta_key', '_receiver' ); |
||
| 1193 | $meta_query_args = array( |
||
| 1194 | 'key' => '_receiver', |
||
| 1195 | 'value' => $teacher->get('user_login') , |
||
| 1196 | 'compare' => '=' |
||
| 1197 | ); |
||
| 1198 | |||
| 1199 | $query->set('meta_query', $meta_query_args ); |
||
| 1200 | |||
| 1201 | return $query; |
||
| 1202 | } |
||
| 1203 | |||
| 1204 | |||
| 1205 | /** |
||
| 1206 | * Add options to filter courses by teacher |
||
| 1207 | * |
||
| 1208 | * @since 1.8.0 |
||
| 1209 | * |
||
| 1210 | * @return void |
||
| 1211 | */ |
||
| 1212 | public function course_teacher_filter_options() { |
||
| 1213 | global $typenow; |
||
| 1214 | |||
| 1215 | if( ! is_admin() || 'course' != $typenow || ! current_user_can('manage_sensei') ) { |
||
| 1216 | return; |
||
| 1217 | } |
||
| 1218 | |||
| 1219 | // get all roles |
||
| 1220 | $roles = get_editable_roles(); |
||
| 1221 | |||
| 1222 | // get roles with the course edit capability |
||
| 1223 | // and then get the users with those roles |
||
| 1224 | $users_who_can_edit_courses = array(); |
||
| 1225 | foreach( $roles as $role_item ){ |
||
| 1226 | |||
| 1227 | $role = get_role( strtolower( $role_item['name'] ) ); |
||
| 1228 | |||
| 1229 | if( is_a( $role, 'WP_Role' ) && $role->has_cap('edit_courses') ){ |
||
| 1230 | |||
| 1231 | $user_query_args = array( 'role' => $role->name, 'fields' => array( 'ID', 'display_name' ) ); |
||
| 1232 | $role_users_who_can_edit_courses = get_users( $user_query_args ); |
||
| 1233 | |||
| 1234 | // add user from the current $user_role to all users |
||
| 1235 | $users_who_can_edit_courses = array_merge( $users_who_can_edit_courses, $role_users_who_can_edit_courses ); |
||
| 1236 | |||
| 1237 | } |
||
| 1238 | |||
| 1239 | } |
||
| 1240 | |||
| 1241 | // Create the select element with the given users who can edit course |
||
| 1242 | $selected = isset( $_GET['course_teacher'] ) ? $_GET['course_teacher'] : ''; |
||
| 1243 | $course_options = ''; |
||
| 1244 | foreach( $users_who_can_edit_courses as $user ) { |
||
| 1245 | $course_options .= '<option value="' . esc_attr( $user->ID ) . '" ' . selected( $selected, $user->ID, false ) . '>' . $user->display_name . '</option>'; |
||
| 1246 | } |
||
| 1247 | |||
| 1248 | $output = '<select name="course_teacher" id="dropdown_course_teachers">'; |
||
| 1249 | $output .= '<option value="">'.__( 'Show all teachers', 'woothemes-sensei' ).'</option>'; |
||
| 1250 | $output .= $course_options; |
||
| 1251 | $output .= '</select>'; |
||
| 1252 | |||
| 1253 | echo $output; |
||
| 1254 | } |
||
| 1255 | |||
| 1256 | /** |
||
| 1257 | * Modify the main query on the admin course list screen |
||
| 1258 | * |
||
| 1259 | * @since 1.8.0 |
||
| 1260 | * |
||
| 1261 | * @param $query |
||
| 1262 | * @return $query |
||
|
0 ignored issues
–
show
|
|||
| 1263 | */ |
||
| 1264 | public function teacher_filter_query_modify( $query ){ |
||
| 1265 | global $typenow; |
||
| 1266 | |||
| 1267 | if( ! is_admin() && 'course' != $typenow || ! current_user_can('manage_sensei') ) { |
||
| 1268 | return $query; |
||
| 1269 | } |
||
| 1270 | $course_teacher = isset( $_GET['course_teacher'] ) ? $_GET['course_teacher'] : ''; |
||
| 1271 | |||
| 1272 | if( empty( $course_teacher ) ) { |
||
| 1273 | return $query; |
||
| 1274 | } |
||
| 1275 | |||
| 1276 | $query['author'] = $course_teacher; |
||
| 1277 | return $query; |
||
| 1278 | } |
||
| 1279 | |||
| 1280 | /** |
||
| 1281 | * Only show current teacher's media in the media library |
||
| 1282 | * @param array $request Default request arguments |
||
| 1283 | * @return array Modified request arguments |
||
| 1284 | */ |
||
| 1285 | public function restrict_media_library( $request = array() ) { |
||
| 1286 | |||
| 1287 | if( ! is_admin() ) { |
||
| 1288 | return $request; |
||
| 1289 | } |
||
| 1290 | |||
| 1291 | if( ! $this->is_admin_teacher() ) { |
||
| 1292 | return $request; |
||
| 1293 | } |
||
| 1294 | |||
| 1295 | $screen = get_current_screen(); |
||
| 1296 | |||
| 1297 | if( in_array( $screen->id, array( 'upload', 'course', 'lesson', 'question' ) ) ) { |
||
| 1298 | $teacher = intval( get_current_user_id() ); |
||
| 1299 | |||
| 1300 | if( $teacher ) { |
||
| 1301 | $request['author__in'] = array( $teacher ); |
||
| 1302 | } |
||
| 1303 | } |
||
| 1304 | |||
| 1305 | return $request; |
||
| 1306 | } // End restrict_media_library() |
||
| 1307 | |||
| 1308 | /** |
||
| 1309 | * Only show current teacher's media in the media library modal on the course/lesson/quesion edit screen |
||
| 1310 | * @param array $query Default query arguments |
||
| 1311 | * @return array Modified query arguments |
||
| 1312 | */ |
||
| 1313 | public function restrict_media_library_modal( $query = array() ) { |
||
| 1314 | |||
| 1315 | if( ! is_admin() ) { |
||
| 1316 | return $query; |
||
| 1317 | } |
||
| 1318 | |||
| 1319 | if( ! $this->is_admin_teacher() ) { |
||
| 1320 | return $query; |
||
| 1321 | } |
||
| 1322 | |||
| 1323 | $teacher = intval( get_current_user_id() ); |
||
| 1324 | |||
| 1325 | if( $teacher ) { |
||
| 1326 | $query['author__in'] = array( $teacher ); |
||
| 1327 | } |
||
| 1328 | |||
| 1329 | return $query; |
||
| 1330 | } // End restrict_media_library_modal() |
||
| 1331 | |||
| 1332 | /** |
||
| 1333 | * When saving the lesson, update the teacher if the lesson belongs to a course |
||
| 1334 | * |
||
| 1335 | * @since 1.8.0 |
||
| 1336 | * |
||
| 1337 | * @param int $lesson_id |
||
| 1338 | */ |
||
| 1339 | public function update_lesson_teacher( $lesson_id ){ |
||
| 1340 | |||
| 1341 | if( 'lesson'!= get_post_type() ){ |
||
| 1342 | return; |
||
| 1343 | } |
||
| 1344 | |||
| 1345 | // this should only run once per request cycle |
||
| 1346 | remove_action( 'save_post', array( $this, 'update_lesson_teacher' ) ); |
||
| 1347 | |||
| 1348 | $course_id = Sensei()->lesson->get_course_id( $lesson_id ); |
||
| 1349 | |||
| 1350 | if( empty( $course_id ) || ! $course_id ){ |
||
| 1351 | return; |
||
| 1352 | } |
||
| 1353 | |||
| 1354 | $course = get_post( $course_id ); |
||
| 1355 | |||
| 1356 | $lesson_update_args= array( |
||
| 1357 | 'ID' => $lesson_id , |
||
| 1358 | 'post_author' => $course->post_author |
||
| 1359 | ); |
||
| 1360 | wp_update_post( $lesson_update_args ); |
||
| 1361 | |||
| 1362 | } // end update_lesson_teacher |
||
| 1363 | |||
| 1364 | /** |
||
| 1365 | * Sensei_Teacher::limit_teacher_edit_screen_post_types |
||
| 1366 | * |
||
| 1367 | * Limit teachers to only see their courses, lessons and questions |
||
| 1368 | * |
||
| 1369 | * @since 1.8.0 |
||
| 1370 | * @access public |
||
| 1371 | * @parameters array $wp_query |
||
| 1372 | * @return WP_Query $wp_query |
||
| 1373 | */ |
||
| 1374 | public function limit_teacher_edit_screen_post_types( $wp_query ) { |
||
| 1375 | global $current_user; |
||
| 1376 | |||
| 1377 | //exit early |
||
| 1378 | if( ! $this->is_admin_teacher() ){ |
||
| 1379 | return $wp_query; |
||
| 1380 | } |
||
| 1381 | |||
| 1382 | if ( ! function_exists( 'get_current_screen' ) ) { |
||
| 1383 | return $wp_query; |
||
| 1384 | } |
||
| 1385 | |||
| 1386 | $screen = get_current_screen(); |
||
| 1387 | |||
| 1388 | if( empty( $screen ) ){ |
||
| 1389 | return $wp_query; |
||
| 1390 | } |
||
| 1391 | |||
| 1392 | // for any of these conditions limit what the teacher will see |
||
| 1393 | $limit_screens = array( |
||
| 1394 | 'edit-lesson', |
||
| 1395 | 'edit-course', |
||
| 1396 | 'edit-question', |
||
| 1397 | 'course_page_course-order', |
||
| 1398 | 'lesson_page_lesson-order', |
||
| 1399 | ); |
||
| 1400 | |||
| 1401 | if( in_array($screen->id , $limit_screens ) ) { |
||
| 1402 | |||
| 1403 | // set the query author to the current user to only show those those posts |
||
| 1404 | $wp_query->set( 'author', $current_user->ID ); |
||
| 1405 | } |
||
| 1406 | |||
| 1407 | return $wp_query; |
||
| 1408 | |||
| 1409 | } // end limit_teacher_edit_screen_post_types() |
||
| 1410 | |||
| 1411 | |||
| 1412 | /** |
||
| 1413 | * Sensei_Teacher::teacher_login_redirect |
||
| 1414 | * |
||
| 1415 | * Redirect teachers to /wp-admin/ after login |
||
| 1416 | * |
||
| 1417 | * @since 1.8.7 |
||
| 1418 | * @access public |
||
| 1419 | * @param string $user_login |
||
| 1420 | * @param object $user |
||
| 1421 | * @return void |
||
| 1422 | */ |
||
| 1423 | |||
| 1424 | public function teacher_login_redirect( $user_login, $user ) { |
||
| 1425 | |||
| 1426 | if (user_can($user, 'edit_courses')) { |
||
| 1427 | |||
| 1428 | if (isset($_POST['redirect_to'])) { |
||
| 1429 | |||
| 1430 | wp_redirect($_POST['redirect_to'], 303); |
||
| 1431 | |||
| 1432 | exit; |
||
| 1433 | |||
| 1434 | } else { |
||
| 1435 | |||
| 1436 | wp_redirect(admin_url(), 303); |
||
| 1437 | |||
| 1438 | exit; |
||
| 1439 | |||
| 1440 | } |
||
| 1441 | } |
||
| 1442 | |||
| 1443 | } // end teacher_login_redirect() |
||
| 1444 | |||
| 1445 | |||
| 1446 | |||
| 1447 | /** |
||
| 1448 | * Sensei_Teacher::restrict_posts_menu_page() |
||
| 1449 | * |
||
| 1450 | * Remove the Posts menu page for teachers and restrict access to it. |
||
| 1451 | * We have to do this because we give teachers the 'edit_posts' cap |
||
| 1452 | * so they can 'moderate_comments' as well. |
||
| 1453 | * |
||
| 1454 | * @since 1.8.7 |
||
| 1455 | * @access public |
||
| 1456 | * @parameters void |
||
| 1457 | * @return void |
||
| 1458 | */ |
||
| 1459 | |||
| 1460 | public function restrict_posts_menu_page() { |
||
| 1461 | |||
| 1462 | global $pagenow, $typenow; |
||
| 1463 | |||
| 1464 | $user = wp_get_current_user(); |
||
| 1465 | |||
| 1466 | /** |
||
| 1467 | * Filter the option to hide the Posts menu page. |
||
| 1468 | * |
||
| 1469 | * @since 1.8.7 |
||
| 1470 | * |
||
| 1471 | * @param bool $restrict default true |
||
| 1472 | */ |
||
| 1473 | |||
| 1474 | $restrict = apply_filters('sensei_restrict_posts_menu_page', true ); |
||
| 1475 | |||
| 1476 | if ( in_array( 'teacher', (array) $user->roles ) && !current_user_can('delete_posts') && $restrict) { |
||
| 1477 | |||
| 1478 | remove_menu_page('edit.php'); |
||
| 1479 | |||
| 1480 | if ($pagenow == "edit.php" || $pagenow == "post-new.php") { |
||
| 1481 | |||
| 1482 | if ($typenow == '' || $typenow == 'post' || $typenow == 'page') { |
||
| 1483 | |||
| 1484 | wp_die('You do not have sufficient permissions to access this page.'); |
||
| 1485 | |||
| 1486 | } |
||
| 1487 | |||
| 1488 | } |
||
| 1489 | |||
| 1490 | } |
||
| 1491 | |||
| 1492 | } // end restrict_posts_menu_page() |
||
| 1493 | |||
| 1494 | /** |
||
| 1495 | * Sensei_Teacher::restrict_comment_moderation() |
||
| 1496 | * |
||
| 1497 | * Restrict commendation moderation for teachers |
||
| 1498 | * so they can only moderate comments made to posts they own. |
||
| 1499 | * |
||
| 1500 | * @since 1.8.7 |
||
| 1501 | * @access public |
||
| 1502 | * @parameters obj $clauses |
||
| 1503 | * @return WP_Comment_Query $clauses |
||
| 1504 | */ |
||
| 1505 | |||
| 1506 | public function restrict_comment_moderation ( $clauses ) { |
||
| 1507 | |||
| 1508 | global $pagenow; |
||
| 1509 | |||
| 1510 | if( self::is_a_teacher( get_current_user_id() ) && $pagenow == "edit-comments.php") { |
||
| 1511 | |||
| 1512 | $clauses->query_vars['post_author'] = get_current_user_id(); |
||
| 1513 | |||
| 1514 | } |
||
| 1515 | |||
| 1516 | return $clauses; |
||
| 1517 | |||
| 1518 | } // end restrict_comment_moderation() |
||
| 1519 | |||
| 1520 | /** |
||
| 1521 | * Determine if a user is a teacher by ID |
||
| 1522 | * |
||
| 1523 | * @param int $user_id |
||
| 1524 | * |
||
| 1525 | * @return bool |
||
| 1526 | */ |
||
| 1527 | public static function is_a_teacher( $user_id ){ |
||
| 1528 | |||
| 1529 | $user = get_user_by('id', $user_id); |
||
| 1530 | |||
| 1531 | if( isset( $user->roles ) && in_array( 'teacher', $user->roles ) ){ |
||
| 1532 | |||
| 1533 | return true; |
||
| 1534 | |||
| 1535 | }else{ |
||
| 1536 | |||
| 1537 | return false; |
||
| 1538 | |||
| 1539 | } |
||
| 1540 | |||
| 1541 | }// end is_a_teacher |
||
| 1542 | |||
| 1543 | /** |
||
| 1544 | * The archive title on the teacher archive filter |
||
| 1545 | * |
||
| 1546 | * @since 1.9.0 |
||
| 1547 | */ |
||
| 1548 | public static function archive_title(){ |
||
| 1549 | |||
| 1550 | $author = get_user_by( 'id', get_query_var( 'author' ) ); |
||
| 1551 | $author_name = $author->display_name; |
||
| 1552 | ?> |
||
| 1553 | <h2 class="teacher-archive-title"> |
||
| 1554 | |||
| 1555 | <?php echo sprintf( __( 'All courses by %s', 'woothemes-sensei') , $author_name ); ?> |
||
| 1556 | |||
| 1557 | </h2> |
||
| 1558 | <?php |
||
| 1559 | |||
| 1560 | }// archive title |
||
| 1561 | |||
| 1562 | /** |
||
| 1563 | * Removing course meta on the teacher archive page |
||
| 1564 | * |
||
| 1565 | * @since 1.9.0 |
||
| 1566 | */ |
||
| 1567 | public static function remove_course_meta_on_teacher_archive(){ |
||
| 1568 | |||
| 1569 | remove_action('sensei_course_content_inside_before', array( Sensei()->course, 'the_course_meta' ) ); |
||
| 1570 | |||
| 1571 | } |
||
| 1572 | |||
| 1573 | } // End Class |
||
| 1574 |
This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.