1: <?php
2:
3: if ( ! defined( 'ABSPATH' ) ) exit;
4:
5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: class Sensei_Core_Modules
16: {
17: private $dir;
18: private $file;
19: private $assets_dir;
20: private $assets_url;
21: private $order_page_slug;
22: public $taxonomy;
23:
24: public function __construct( $file )
25: {
26: $this->file = $file;
27: $this->dir = dirname($this->file);
28: $this->assets_dir = trailingslashit($this->dir) . 'assets';
29: $this->assets_url = esc_url(trailingslashit(plugins_url('/assets/', $this->file)));
30: $this->taxonomy = 'module';
31: $this->order_page_slug = 'module-order';
32:
33:
34: add_action( 'init', array( $this, 'setup_modules_taxonomy' ), 10 );
35:
36:
37: add_action('add_meta_boxes', array($this, 'modules_metaboxes'), 20, 2 );
38:
39:
40: add_action('save_post', array($this, 'save_lesson_module'), 10, 1);
41:
42:
43: add_action( 'save_post', array( 'Sensei_Core_Modules', 'reset_none_modules_transient' ) );
44:
45:
46: add_action('wp_enqueue_scripts', array($this, 'enqueue_styles'));
47:
48:
49: add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_styles'));
50: add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'), 20 , 2 );
51:
52:
53: add_action('sensei_lesson_status_updated', array($this, 'update_lesson_status_module_progress'), 10, 3);
54: add_action('sensei_user_lesson_reset', array($this, 'save_lesson_module_progress'), 10, 2);
55: add_action('wp', array($this, 'save_module_progress'), 10);
56:
57:
58: add_action('admin_menu', array($this, 'register_modules_admin_menu_items'), 30 );
59: add_filter('manage_edit-course_columns', array($this, 'course_columns'), 11, 1);
60: add_action('manage_posts_custom_column', array($this, 'course_column_content'), 11, 2);
61:
62:
63: add_action( 'admin_menu', array( $this, 'remove_lessons_menu_model_taxonomy' ) , 10 );
64: add_action( 'admin_menu', array( $this, 'remove_courses_menu_model_taxonomy' ) , 10 );
65: add_action( 'admin_menu', array( $this, 'redirect_to_lesson_module_taxonomy_to_course' ) , 20 );
66:
67:
68: add_action($this->taxonomy . '_add_form_fields', array($this, 'add_module_fields'), 50, 1);
69: add_action($this->taxonomy . '_edit_form_fields', array($this, 'edit_module_fields'), 1, 1);
70: add_action('edited_' . $this->taxonomy, array($this, 'save_module_course'), 10, 2);
71: add_action('created_' . $this->taxonomy, array($this, 'save_module_course'), 10, 2);
72: add_action('wp_ajax_sensei_json_search_courses', array($this, 'search_courses_json'));
73:
74:
75: add_filter('template_include', array($this, 'module_archive_template'), 10);
76: add_action('pre_get_posts', array($this, 'module_archive_filter'), 10, 1);
77: add_filter('sensei_lessons_archive_text', array($this, 'module_archive_title') );
78: add_action('sensei_loop_lesson_inside_before', array($this, 'module_archive_description'), 30 );
79: add_action('sensei_pagination', array($this, 'module_navigation_links'), 11);
80: add_filter('body_class', array($this, 'module_archive_body_class'));
81:
82:
83: add_action( 'sensei_single_course_content_inside_after', array($this, 'load_course_module_content_template') , 8 );
84:
85:
86: add_action('sensei_single_course_modules_before',array( $this,'course_modules_title' ), 20);
87:
88:
89: add_filter('sensei_breadcrumb_output', array($this, 'module_breadcrumb_link'), 10, 2);
90:
91:
92: add_filter('sensei_analysis_overview_columns', array($this, 'analysis_overview_column_title'), 10, 2);
93: add_filter('sensei_analysis_overview_column_data', array($this, 'analysis_overview_column_data'), 10, 3);
94: add_filter('sensei_analysis_course_columns', array($this, 'analysis_course_column_title'), 10, 2);
95: add_filter('sensei_analysis_course_column_data', array($this, 'analysis_course_column_data'), 10, 3);
96:
97:
98: add_filter('manage_edit-' . $this->taxonomy . '_columns', array($this, 'taxonomy_column_headings'), 1, 1);
99: add_filter('manage_' . $this->taxonomy . '_custom_column', array($this, 'taxonomy_column_content'), 1, 3);
100: add_filter('sensei_module_lesson_list_title', array($this, 'sensei_course_preview_titles'), 10, 2);
101:
102:
103: add_action( 'wp_ajax_sensei_add_new_module_term', array( 'Sensei_Core_Modules','add_new_module_term' ) );
104:
105:
106: add_filter('get_terms', array( $this, 'filter_module_terms' ), 20, 3 );
107: add_filter('get_object_terms', array( $this, 'filter_course_selected_terms' ), 20, 3 );
108:
109:
110: add_filter('get_terms', array( $this, 'append_teacher_name_to_module' ), 70, 3 );
111:
112:
113: add_action('admin_init',array( 'Sensei_Core_Modules' , 'remove_default_modules_box' ));
114:
115: }
116:
117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129:
130: public function change_module_term_slug( $term_id, $tt_id, $taxonomy ){
131:
132: _deprecated_function('change_module_term_slug', '1.9.0' );
133:
134: }
135:
136: 137: 138: 139: 140: 141: 142: 143: 144: 145:
146: public function modules_metaboxes( $post_type, $post )
147: {
148: if ('lesson' == $post_type ) {
149:
150:
151: remove_meta_box($this->taxonomy . 'div', 'lesson', 'side');
152:
153:
154: add_meta_box($this->taxonomy . '_select', __('Lesson Module', 'woothemes-sensei'), array($this, 'lesson_module_metabox'), 'lesson', 'side', 'default');
155: }
156:
157: if( 'course' == $post_type ){
158:
159: add_meta_box( $this->taxonomy . '_course_mb', __('Course Modules', 'woothemes-sensei'), array( $this, 'course_module_metabox'), 'course', 'side', 'core');
160: }
161: }
162:
163: 164: 165: 166: 167: 168: 169:
170: public function lesson_module_metabox($post)
171: {
172:
173:
174: $lesson_course = get_post_meta($post->ID, '_lesson_course', true);
175:
176: $html = '';
177:
178:
179: if ($lesson_course && $lesson_course > 0) {
180:
181:
182: $lesson_module = 0;
183: $lesson_module_list = wp_get_post_terms($post->ID, $this->taxonomy);
184: if (is_array($lesson_module_list) && count($lesson_module_list) > 0) {
185: foreach ($lesson_module_list as $single_module) {
186: $lesson_module = $single_module->term_id;
187: break;
188: }
189: }
190:
191:
192: $modules = $this->get_course_modules($lesson_course);
193:
194:
195: $html .= '<input type="hidden" name="' . esc_attr('woo_lesson_' . $this->taxonomy . '_nonce') . '" id="' . esc_attr('woo_lesson_' . $this->taxonomy . '_nonce') . '" value="' . esc_attr(wp_create_nonce(plugin_basename($this->file))) . '" />';
196: if (is_array($modules) && count($modules) > 0) {
197: $html .= '<select id="lesson-module-options" name="lesson_module" class="widefat">' . "\n";
198: $html .= '<option value="">' . __('None', 'woothemes-sensei') . '</option>';
199: foreach ($modules as $module) {
200: $html .= '<option value="' . esc_attr(absint($module->term_id)) . '"' . selected($module->term_id, $lesson_module, false) . '>' . esc_html($module->name) . '</option>' . "\n";
201: }
202: $html .= '</select>' . "\n";
203: } else {
204: $course_url = admin_url('post.php?post=' . urlencode($lesson_course) . '&action=edit');
205: $html .= '<p>' . sprintf(__('No modules are available for this lesson yet. %1$sPlease add some to %3$sthe course%4$s.%2$s', 'woothemes-sensei'), '<em>', '</em>', '<a href="' . esc_url($course_url) . '">', '</a>') . '</p>';
206: }
207:
208: } else {
209: $html .= '<p>' . sprintf(__('No modules are available for this lesson yet. %1$sPlease select a course first.%2$s', 'woothemes-sensei'), '<em>', '</em>') . '</p>';
210: }
211:
212:
213: echo $html;
214: }
215:
216: 217: 218: 219: 220: 221: 222:
223: public function save_lesson_module($post_id)
224: {
225: global $post;
226:
227:
228: if ((get_post_type() != 'lesson') || !isset($_POST['woo_lesson_' . $this->taxonomy . '_nonce'] )
229: ||!wp_verify_nonce($_POST['woo_lesson_' . $this->taxonomy . '_nonce'], plugin_basename($this->file))) {
230: return $post_id;
231: }
232:
233:
234: $post_type = get_post_type_object($post->post_type);
235: if (!current_user_can($post_type->cap->edit_post, $post_id)) {
236: return $post_id;
237: }
238:
239:
240: if (!current_user_can('edit_post', $post_id)) {
241: return $post_id;
242: }
243:
244:
245: if ( isset( $_POST['lesson_module'] ) ) {
246:
247: if( empty ( $_POST['lesson_module'] ) ){
248: wp_delete_object_term_relationships($post_id, $this->taxonomy );
249: return true;
250: }
251:
252: $module_id = intval( $_POST['lesson_module'] );
253:
254:
255: wp_set_object_terms($post_id, $module_id, $this->taxonomy, false);
256:
257:
258: if (!get_post_meta($post_id, '_order_module_' . $module_id, true)) {
259: update_post_meta($post_id, '_order_module_' . $module_id, 0);
260: }
261: }
262:
263: return true;
264: }
265:
266: 267: 268: 269: 270: 271: 272:
273: public function add_module_fields($taxonomy)
274: {
275: ?>
276: <div class="form-field">
277: <label for="module_courses"><?php _e('Course(s)', 'woothemes-sensei'); ?></label>
278: <input type="hidden" id="module_courses" name="module_courses" class="ajax_chosen_select_courses"
279: placeholder="<?php esc_attr_e('Search for courses', 'woothemes-sensei'); ?>" />
280: <span
281: class="description"><?php _e('Search for and select the courses that this module will belong to.', 'woothemes-sensei'); ?></span>
282: </div>
283: <?php
284: }
285:
286: 287: 288: 289: 290: 291: 292:
293: public function edit_module_fields($module)
294: {
295:
296: $module_id = $module->term_id;
297:
298:
299: $args = array(
300: 'post_type' => 'course',
301: 'post_status' => array('publish', 'draft', 'future', 'private'),
302: 'posts_per_page' => -1,
303: 'tax_query' => array(
304: array(
305: 'taxonomy' => $this->taxonomy,
306: 'field' => 'id',
307: 'terms' => $module_id
308: )
309: )
310: );
311: $courses = get_posts($args);
312:
313:
314: $module_courses = array();
315: if (isset($courses) && is_array($courses)) {
316: foreach ($courses as $course) {
317: $module_courses[] = array( 'id' =>$course->ID, 'details'=>$course->post_title );
318: }
319: }
320:
321: ?>
322: <tr class="form-field">
323: <th scope="row" valign="top"><label
324: for="module_courses"><?php _e('Course(s)', 'woothemes-sensei'); ?></label></th>
325: <td>
326: <input type="hidden"
327: data-defaults="<?php echo esc_attr( json_encode($module_courses)); ?>"
328: value="<?php echo esc_attr( json_encode($module_courses) ); ?>"
329: id="module_courses" name="module_courses"
330: class="ajax_chosen_select_courses"
331: placeholder="<?php esc_attr_e('Search for courses...', 'woothemes-sensei'); ?>"
332: />
333: <span
334: class="description"><?php _e('Search for and select the courses that this module will belong to.', 'woothemes-sensei'); ?></span>
335: </td>
336: </tr>
337: <?php
338: }
339:
340: 341: 342: 343: 344: 345: 346:
347: public function save_module_course($module_id)
348: {
349:
350: if( isset( $_POST['action'] ) && 'inline-save-tax' == $_POST['action'] ) {
351: return;
352: }
353:
354: $args = array(
355: 'post_type' => 'course',
356: 'post_status' => array('publish', 'draft', 'future', 'private'),
357: 'posts_per_page' => -1,
358: 'tax_query' => array(
359: array(
360: 'taxonomy' => $this->taxonomy,
361: 'field' => 'id',
362: 'terms' => $module_id
363: )
364: )
365: );
366: $courses = get_posts($args);
367:
368:
369: if (isset($courses) && is_array($courses)) {
370: foreach ($courses as $course) {
371: wp_remove_object_terms($course->ID, $module_id, $this->taxonomy);
372: }
373: }
374:
375:
376: if ( isset( $_POST['module_courses'] ) && ! empty( $_POST['module_courses'] ) ) {
377:
378: $course_ids = explode( ",", $_POST['module_courses'] );
379:
380: foreach ( $course_ids as $course_id ) {
381:
382: wp_set_object_terms($course_id, $module_id, $this->taxonomy, true);
383:
384: }
385: }
386: }
387:
388: 389: 390: 391: 392: 393:
394: public function search_courses_json()
395: {
396:
397:
398: check_ajax_referer('search-courses', 'security');
399:
400:
401: header('Content-Type: application/json; charset=utf-8');
402:
403:
404: $term = urldecode(stripslashes($_GET['term']));
405:
406:
407: if (empty($term))
408: die();
409:
410:
411: $default = isset($_GET['default']) ? $_GET['default'] : __('No course', 'woothemes-sensei');
412:
413:
414: $found_courses = array('' => $default);
415:
416:
417: $args = array(
418: 'post_type' => 'course',
419: 'post_status' => array('publish', 'draft', 'future', 'private'),
420: 'posts_per_page' => -1,
421: 'orderby' => 'title',
422: 's' => $term
423: );
424: $courses = get_posts($args);
425:
426:
427: if ($courses) {
428: foreach ($courses as $course) {
429: $found_courses[$course->ID] = $course->post_title;
430: }
431: }
432:
433:
434: echo json_encode($found_courses);
435: die();
436: }
437:
438: 439: 440: 441: 442: 443:
444: public function single_course_modules(){
445:
446: _deprecated_function('Sensei_Modules->single_course_modules','Sensei 1.9.0', 'Sensei()->modules->load_course_module_content_template');
447:
448: if( is_singular( 'course' ) && has_term( '', 'module' ) ) {
449:
450: $this->load_course_module_content_template();
451:
452: }
453:
454: }
455:
456: public function sensei_course_preview_titles($title, $lesson_id)
457: {
458: global $post, $current_user;
459:
460: $course_id = $post->ID;
461: $title_text = '';
462:
463: if (method_exists('Sensei_Utils', 'is_preview_lesson') && Sensei_Utils::is_preview_lesson($lesson_id)) {
464: $is_user_taking_course = Sensei_Utils::sensei_check_for_activity(array('post_id' => $course_id, 'user_id' => $current_user->ID, 'type' => 'sensei_course_status'));
465: if (!$is_user_taking_course) {
466: if (method_exists('WooThemes_Sensei_Frontend', 'sensei_lesson_preview_title_text')) {
467: $title_text = Sensei()->frontend->sensei_lesson_preview_title_text($course_id);
468:
469: $title_text = str_replace('(', '', $title_text);
470: $title_text = str_replace(')', '', $title_text);
471: $title_text = '<span class="preview-label">' . $title_text . '</span>';
472: }
473: $title .= ' ' . $title_text;
474: }
475: }
476:
477: return $title;
478: }
479:
480: public function module_breadcrumb_link($html, $separator)
481: {
482: global $post;
483:
484: if (is_singular('lesson')) {
485: if (has_term('', $this->taxonomy, $post->ID)) {
486: $module = $this->get_lesson_module($post->ID);
487: if( $module ) {
488: $html .= ' ' . $separator . ' <a href="' . esc_url($module->url) . '" title="' . __('Back to the module', 'woothemes-sensei') . '">' . $module->name . '</a>';
489: }
490: }
491: }
492:
493: if (is_tax($this->taxonomy)) {
494: if (isset($_GET['course_id']) && 0 < intval($_GET['course_id'])) {
495: $course_id = intval($_GET['course_id']);
496: $html .= '<a href="' . esc_url(get_permalink($course_id)) . '" title="' . __('Back to the course', 'woothemes-sensei') . '">' . get_the_title($course_id) . '</a>';
497: }
498: }
499: return $html;
500: }
501:
502: 503: 504: 505: 506: 507: 508:
509: public function module_archive_template($template) {
510:
511: if ( ! is_tax($this->taxonomy) ) {
512: return $template;
513: }
514:
515: $file = 'archive-lesson.php';
516: $find = array( $file, Sensei()->template_url . $file );
517:
518:
519: $template = locate_template($find);
520: if (!$template) {
521:
522: $template = Sensei()->plugin_path() . 'templates/' . $file;
523:
524: }
525:
526:
527: return $template;
528: }
529:
530: 531: 532: 533: 534: 535: 536:
537: public function module_archive_filter($query)
538: {
539: if (is_tax($this->taxonomy) && $query->is_main_query()) {
540:
541:
542:
543: $query->set('post_type', 'lesson');
544:
545:
546: if (version_compare(Sensei()->version, '1.6.0', '>=')) {
547: $module_id = $query->queried_object_id;
548: $query->set('meta_key', '_order_module_' . $module_id);
549: $query->set('orderby', 'meta_value_num date');
550: } else {
551: $query->set('orderby', 'menu_order');
552: }
553: $query->set('order', 'ASC');
554:
555:
556: if (isset($_GET['course_id']) && 0 < intval($_GET['course_id'])) {
557: $course_id = intval($_GET['course_id']);
558: $meta_query[] = array(
559: 'key' => '_lesson_course',
560: 'value' => intval($course_id)
561: );
562: $query->set('meta_query', $meta_query);
563: }
564:
565: }
566: }
567:
568: 569: 570: 571: 572: 573: 574:
575: public function module_archive_title($title)
576: {
577: if (is_tax($this->taxonomy)) {
578: $title = apply_filters('sensei_module_archive_title', get_queried_object()->name);
579: }
580: return $title;
581: }
582:
583: 584: 585: 586: 587: 588:
589: public function module_archive_description()
590: {
591:
592: remove_action( 'sensei_loop_lesson_before', array( $this,'module_archive_description' ), 30 );
593:
594: if (is_tax($this->taxonomy)) {
595:
596: $module = get_queried_object();
597:
598: $module_progress = false;
599: if (is_user_logged_in() && isset($_GET['course_id']) && intval($_GET['course_id']) > 0) {
600: global $current_user;
601: wp_get_current_user();
602: $module_progress = $this->get_user_module_progress($module->term_id, $_GET['course_id'], $current_user->ID);
603: }
604:
605: if ($module_progress && $module_progress > 0) {
606: $status = __('Completed', 'woothemes-sensei');
607: $class = 'completed';
608: if ($module_progress < 100) {
609: $status = __('In progress', 'woothemes-sensei');
610: $class = 'in-progress';
611: }
612: echo '<p class="status ' . esc_attr($class) . '">' . $status . '</p>';
613: }
614:
615: echo '<p class="archive-description module-description">' . apply_filters('sensei_module_archive_description', nl2br($module->description), $module->term_id) . '</p>';
616: }
617: }
618:
619: public function module_archive_body_class($classes)
620: {
621: if (is_tax($this->taxonomy)) {
622: $classes[] = 'module-archive';
623: }
624: return $classes;
625: }
626:
627: 628: 629: 630: 631: 632:
633: public function module_navigation_links()
634: {
635: if (is_tax($this->taxonomy) && isset($_GET['course_id'])) {
636:
637: $queried_module = get_queried_object();
638: $course_modules = $this->get_course_modules($_GET['course_id']);
639:
640: $prev_module = false;
641: $next_module = false;
642: $on_current = false;
643: foreach ($course_modules as $module) {
644: $this_module = $module;
645: if ($on_current) {
646: $next_module = $this_module;
647: break;
648: }
649: if ($this_module == $queried_module) {
650: $on_current = true;
651: } else {
652: $prev_module = $module;
653: }
654: }
655:
656: ?>
657: <div id="post-entries" class="post-entries module-navigation fix">
658: <?php if ($next_module) {
659: $module_link = add_query_arg('course_id', intval($_GET['course_id']), get_term_link($next_module, $this->taxonomy));
660: ?>
661: <div class="nav-next fr"><a href="<?php echo esc_url($module_link); ?>"
662: title="<?php esc_attr_e('Next module', 'woothemes-sensei'); ?>"><?php echo $next_module->name; ?>
663: <span class="meta-nav"></span></a></div>
664: <?php } ?>
665: <?php if ($prev_module) {
666: $module_link = add_query_arg('course_id', intval($_GET['course_id']), get_term_link($prev_module, $this->taxonomy));
667: ?>
668: <div class="nav-prev fl"><a href="<?php echo esc_url($module_link); ?>"
669: title="<?php _e('Previous module', 'woothemes-sensei'); ?>"><span
670: class="meta-nav"></span> <?php echo $prev_module->name; ?></a></div>
671: <?php } ?>
672: </div>
673: <?php
674: }
675: }
676:
677: 678: 679: 680: 681: 682: 683: 684: 685:
686: public function update_lesson_status_module_progress($status = '', $user_id = 0, $lesson_id = 0)
687: {
688: $this->save_lesson_module_progress($user_id, $lesson_id);
689: }
690:
691: 692: 693: 694: 695: 696: 697: 698:
699: public function save_lesson_module_progress($user_id = 0, $lesson_id = 0)
700: {
701: $module = $this->get_lesson_module($lesson_id);
702: $course_id = get_post_meta($lesson_id, '_lesson_course', true);
703: if ($module && $course_id) {
704: $this->save_user_module_progress(intval($module->term_id), intval($course_id), intval($user_id));
705: }
706: }
707:
708: 709: 710: 711: 712: 713:
714: public function save_module_progress()
715: {
716: if (is_tax($this->taxonomy) && is_user_logged_in() && isset($_GET['course_id']) && 0 < intval($_GET['course_id'])) {
717: global $current_user;
718: wp_get_current_user();
719: $user_id = $current_user->ID;
720:
721: $module = get_queried_object();
722:
723: $this->save_user_module_progress(intval($module->term_id), intval($_GET['course_id']), intval($user_id));
724: }
725: }
726:
727: 728: 729: 730: 731: 732: 733: 734: 735: 736:
737: public function save_user_module_progress($module_id = 0, $course_id = 0, $user_id = 0)
738: {
739: $module_progress = $this->calculate_user_module_progress($user_id, $module_id, $course_id);
740: update_user_meta(intval($user_id), '_module_progress_' . intval($course_id) . '_' . intval($module_id), intval($module_progress));
741:
742: do_action('sensei_module_save_user_progress', $course_id, $module_id, $user_id, $module_progress);
743: }
744:
745: 746: 747: 748: 749: 750: 751: 752: 753: 754:
755: public function get_user_module_progress($module_id = 0, $course_id = 0, $user_id = 0)
756: {
757: $module_progress = get_user_meta(intval($user_id), '_module_progress_' . intval($course_id) . '_' . intval($module_id), true);
758: if ($module_progress) {
759: return (float)$module_progress;
760: }
761: return false;
762: }
763:
764: 765: 766: 767: 768: 769: 770: 771: 772: 773:
774: public function calculate_user_module_progress($user_id = 0, $module_id = 0, $course_id = 0)
775: {
776:
777: $args = array(
778: 'post_type' => 'lesson',
779: 'post_status' => 'publish',
780: 'posts_per_page' => -1,
781: 'tax_query' => array(
782: array(
783: 'taxonomy' => $this->taxonomy,
784: 'field' => 'id',
785: 'terms' => $module_id
786: )
787: ),
788: 'meta_query' => array(
789: array(
790: 'key' => '_lesson_course',
791: 'value' => $course_id
792: )
793: ),
794: 'fields' => 'ids'
795: );
796: $lessons = get_posts($args);
797:
798: if (is_wp_error($lessons) || 0 >= count($lessons)) return 0;
799:
800: $completed = false;
801: $lesson_count = 0;
802: $completed_count = 0;
803: foreach ($lessons as $lesson_id) {
804: $completed = Sensei_Utils::user_completed_lesson($lesson_id, $user_id);
805: ++$lesson_count;
806: if ($completed) {
807: ++$completed_count;
808: }
809: }
810: $module_progress = ($completed_count / $lesson_count) * 100;
811:
812: return (float)$module_progress;
813: }
814:
815: 816: 817: 818: 819: 820: 821:
822: public function register_modules_admin_menu_items()
823: {
824:
825: add_submenu_page('edit.php?post_type=course', __('Modules', 'woothemes-sensei'), __('Modules', 'woothemes-sensei'), 'manage_categories', 'edit-tags.php?taxonomy=module','' );
826:
827:
828: $hook = add_submenu_page('edit.php?post_type=course', __('Order Modules', 'woothemes-sensei'), __('Order Modules', 'woothemes-sensei'), 'edit_lessons', $this->order_page_slug, array($this, 'module_order_screen'));
829:
830: }
831:
832: 833: 834: 835: 836: 837: 838:
839: public function module_order_screen()
840: {
841: ?>
842: <div id="<?php echo esc_attr($this->order_page_slug); ?>"
843: class="wrap <?php echo esc_attr($this->order_page_slug); ?>">
844: <h2><?php _e('Order Modules', 'woothemes-sensei'); ?></h2><?php
845:
846: $html = '';
847:
848: if (isset($_POST['module-order']) && 0 < strlen($_POST['module-order'])) {
849: $ordered = $this->save_course_module_order(esc_attr($_POST['module-order']), esc_attr($_POST['course_id']));
850:
851: if ($ordered) {
852: $html .= '<div class="updated fade">' . "\n";
853: $html .= '<p>' . __('The module order has been saved for this course.', 'woothemes-sensei') . '</p>' . "\n";
854: $html .= '</div>' . "\n";
855: }
856: }
857:
858: $courses = Sensei()->course->get_all_courses();
859:
860: $html .= '<form action="' . admin_url('edit.php') . '" method="get">' . "\n";
861: $html .= '<input type="hidden" name="post_type" value="course" />' . "\n";
862: $html .= '<input type="hidden" name="page" value="' . esc_attr($this->order_page_slug) . '" />' . "\n";
863: $html .= '<select id="module-order-course" name="course_id">' . "\n";
864: $html .= '<option value="">' . __('Select a course', 'woothemes-sensei') . '</option>' . "\n";
865:
866: foreach ($courses as $course) {
867: if (has_term('', $this->taxonomy, $course->ID)) {
868: $course_id = '';
869: if (isset($_GET['course_id'])) {
870: $course_id = intval($_GET['course_id']);
871: }
872: $html .= '<option value="' . esc_attr(intval($course->ID)) . '" ' . selected($course->ID, $course_id, false) . '>' . get_the_title($course->ID) . '</option>' . "\n";
873: }
874: }
875:
876: $html .= '</select>' . "\n";
877: $html .= '<input type="submit" class="button-primary module-order-select-course-submit" value="' . __('Select', 'woothemes-sensei') . '" />' . "\n";
878: $html .= '</form>' . "\n";
879:
880: if (isset($_GET['course_id'])) {
881: $course_id = intval($_GET['course_id']);
882: if ($course_id > 0) {
883: $modules = $this->get_course_modules($course_id);
884: $modules = $this->append_teacher_name_to_module( $modules, array( 'module' ), array() );
885: if ($modules) {
886:
887: $order = $this->get_course_module_order($course_id);
888:
889: $order_string='';
890: if ($order) {
891: $order_string = implode(',', $order);
892: }
893:
894: $html .= '<form id="editgrouping" method="post" action="" class="validate">' . "\n";
895: $html .= '<ul class="sortable-module-list">' . "\n";
896: $count = 0;
897: foreach ($modules as $module) {
898: $count++;
899: $class = $this->taxonomy;
900: if ($count == 1) {
901: $class .= ' first';
902: }
903: if ($count == count($module)) {
904: $class .= ' last';
905: }
906: if ($count % 2 != 0) {
907: $class .= ' alternate';
908: }
909: $html .= '<li class="' . esc_attr($class) . '"><span rel="' . esc_attr($module->term_id) . '" style="width: 100%;"> ' . $module->name . '</span></li>' . "\n";
910: }
911: $html .= '</ul>' . "\n";
912:
913: $html .= '<input type="hidden" name="module-order" value="' . $order_string . '" />' . "\n";
914: $html .= '<input type="hidden" name="course_id" value="' . $course_id . '" />' . "\n";
915: $html .= '<input type="submit" class="button-primary" value="' . __('Save module order', 'woothemes-sensei') . '" />' . "\n";
916: $html .= '<a href="' . admin_url('post.php?post=' . $course_id . '&action=edit') . '" class="button-secondary">' . __('Edit course', 'woothemes-sensei') . '</a>' . "\n";
917: }
918: }
919: }
920:
921: echo $html;
922:
923: ?></div><?php
924: }
925:
926: 927: 928: 929: 930: 931: 932: 933:
934: public function course_columns($columns = array())
935: {
936: $columns['module_order'] = __('Module order', 'woothemes-sensei');
937: return $columns;
938: }
939:
940: 941: 942: 943: 944: 945: 946: 947: 948:
949: public function course_column_content($column = '', $course_id = 0)
950: {
951: if ($column == 'module_order') {
952: if (has_term('', $this->taxonomy, $course_id)) {
953: echo '<a class="button-secondary" href="' . admin_url('edit.php?post_type=course&page=module-order&course_id=' . urlencode(intval($course_id))) . '">' . __('Order modules', 'woothemes-sensei') . '</a>';
954: }
955: }
956: }
957:
958: 959: 960: 961: 962: 963: 964: 965: 966:
967: private function save_course_module_order($order_string = '', $course_id = 0)
968: {
969: if ($order_string && $course_id) {
970: $order = explode(',', $order_string);
971: update_post_meta(intval($course_id), '_module_order', $order);
972: return true;
973: }
974: return false;
975: }
976:
977: 978: 979: 980: 981: 982: 983: 984:
985: public function get_course_module_order($course_id = 0)
986: {
987: if ($course_id) {
988: $order = get_post_meta(intval($course_id), '_module_order', true);
989: return $order;
990: }
991: return false;
992: }
993:
994: 995: 996: 997: 998: 999: 1000: 1001:
1002: public function taxonomy_column_headings($columns)
1003: {
1004:
1005: unset($columns['posts']);
1006:
1007: $columns['lessons'] = __('Lessons', 'woothemes-sensei');
1008:
1009: return $columns;
1010: }
1011:
1012: 1013: 1014: 1015: 1016: 1017: 1018: 1019: 1020: 1021:
1022: public function taxonomy_column_content($column_data, $column_name, $term_id)
1023: {
1024:
1025: $args = array(
1026: 'post_status' => 'publish',
1027: 'posts_per_page' => -1,
1028: 'tax_query' => array(
1029: array(
1030: 'taxonomy' => $this->taxonomy,
1031: 'field' => 'id',
1032: 'terms' => intval($term_id)
1033: )
1034: )
1035: );
1036:
1037: $module = get_term($term_id, $this->taxonomy);
1038:
1039: switch ($column_name) {
1040:
1041: case 'lessons':
1042: $args['post_type'] = 'lesson';
1043: $lessons = get_posts($args);
1044: $total_lessons = count($lessons);
1045: $column_data = '<a href="' . admin_url('edit.php?module=' . urlencode($module->slug) . '&post_type=lesson') . '">' . intval($total_lessons) . '</a>';
1046: break;
1047: }
1048:
1049: return $column_data;
1050: }
1051:
1052: 1053: 1054: 1055: 1056: 1057: 1058: 1059:
1060: public function analysis_overview_column_title($columns)
1061: {
1062:
1063: if ( isset( $_GET['view'] ) && 'lessons' == $_GET['view'] ) {
1064: $new_columns = array();
1065: if (is_array($columns) && 0 < count($columns)) {
1066: foreach ($columns as $column => $title) {
1067: $new_columns[$column] = $title;
1068: if ($column == 'title') {
1069: $new_columns['lesson_module'] = __('Module', 'woothemes-sensei');
1070: }
1071: }
1072: }
1073:
1074: if (0 < count($new_columns)) {
1075: return $new_columns;
1076: }
1077: }
1078:
1079: return $columns;
1080: }
1081:
1082: 1083: 1084: 1085: 1086: 1087: 1088: 1089: 1090:
1091: public function analysis_overview_column_data($columns, $lesson )
1092: {
1093:
1094: if ( isset( $_GET['view'] ) && 'lessons' == $_GET['view'] ) {
1095: $lesson_module = '';
1096: $lesson_module_list = wp_get_post_terms($lesson->ID, $this->taxonomy);
1097: if (is_array($lesson_module_list) && count($lesson_module_list) > 0) {
1098: foreach ($lesson_module_list as $single_module) {
1099: $lesson_module = '<a href="' . esc_url(admin_url('edit-tags.php?action=edit&taxonomy=' . urlencode($this->taxonomy) . '&tag_ID=' . urlencode($single_module->term_id))) . '">' . $single_module->name . '</a>';
1100: break;
1101: }
1102: }
1103:
1104: $columns['lesson_module'] = $lesson_module;
1105: }
1106:
1107: return $columns;
1108: }
1109:
1110: 1111: 1112: 1113: 1114: 1115: 1116: 1117:
1118: public function analysis_course_column_title($columns)
1119: {
1120: if ( isset( $_GET['view'] ) && 'lessons' == $_GET['view'] ) {
1121: $columns['lesson_module'] = __('Module', 'woothemes-sensei');
1122: }
1123: return $columns;
1124: }
1125:
1126: 1127: 1128: 1129: 1130: 1131: 1132: 1133: 1134:
1135: public function analysis_course_column_data($columns, $lesson )
1136: {
1137:
1138: if ( isset( $_GET['course_id'] ) ) {
1139: $lesson_module = '';
1140: $lesson_module_list = wp_get_post_terms($lesson->ID, $this->taxonomy);
1141: if (is_array($lesson_module_list) && count($lesson_module_list) > 0) {
1142: foreach ($lesson_module_list as $single_module) {
1143: $lesson_module = '<a href="' . esc_url(admin_url('edit-tags.php?action=edit&taxonomy=' . urlencode($this->taxonomy) . '&tag_ID=' . urlencode($single_module->term_id))) . '">' . $single_module->name . '</a>';
1144: break;
1145: }
1146: }
1147:
1148: $columns['lesson_module'] = $lesson_module;
1149: }
1150:
1151: return $columns;
1152: }
1153:
1154: 1155: 1156: 1157: 1158: 1159: 1160: 1161: 1162: 1163: 1164: 1165: 1166:
1167: public function get_lesson_module($lesson_id = 0)
1168: {
1169: $lesson_id = intval($lesson_id);
1170: if ( ! ( intval( $lesson_id > 0) ) ) {
1171: return false;
1172: }
1173:
1174:
1175: $modules = wp_get_post_terms($lesson_id, $this->taxonomy);
1176:
1177:
1178: if( empty( $modules )
1179: || is_wp_error( $modules )
1180: || isset( $modules['errors'] ) ){
1181:
1182: return false;
1183:
1184: }
1185:
1186:
1187:
1188: foreach( $modules as $module ){
1189: break;
1190: }
1191:
1192: if ( ! isset($module) || ! is_object($module) || is_wp_error($module)) {
1193: return false;
1194: }
1195:
1196: $module->url = get_term_link($module, $this->taxonomy);
1197: $course_id = intval(get_post_meta(intval($lesson_id), '_lesson_course', true));
1198: if (isset($course_id) && 0 < $course_id) {
1199:
1200:
1201: if( ! has_term( $module, $this->taxonomy, $course_id)){
1202: return false;
1203: }
1204:
1205: $module->url = esc_url(add_query_arg('course_id', intval($course_id), $module->url));
1206: }
1207: return $module;
1208:
1209: }
1210:
1211: 1212: 1213: 1214: 1215: 1216: 1217: 1218:
1219: public function get_course_modules($course_id = 0) {
1220:
1221: $course_id = intval($course_id);
1222: if ( empty( $course_id ) ) {
1223: return array();
1224: }
1225:
1226:
1227: $modules = wp_get_post_terms( $course_id, $this->taxonomy );
1228:
1229:
1230: $order = $this->get_course_module_order($course_id);
1231:
1232: if ( ! $order) {
1233: return $modules;
1234: }
1235:
1236:
1237: $ordered_modules = array();
1238: $unordered_modules = array();
1239: foreach ( $modules as $module ) {
1240: $order_key = array_search($module->term_id, $order);
1241: if ($order_key !== false) {
1242: $ordered_modules[$order_key] = $module;
1243: } else {
1244: $unordered_modules[] = $module;
1245: }
1246: }
1247:
1248:
1249: ksort( $ordered_modules );
1250:
1251:
1252: if ( count($unordered_modules) > 0 ) {
1253: $ordered_modules = array_merge($ordered_modules, $unordered_modules);
1254: }
1255:
1256:
1257: $ordered_modules_with_keys_in_sequence = array();
1258: foreach ( $ordered_modules as $key => $module ) {
1259:
1260: $ordered_modules_with_keys_in_sequence[] = $module;
1261:
1262: }
1263:
1264: return $ordered_modules_with_keys_in_sequence;
1265:
1266: }
1267:
1268: 1269: 1270: 1271: 1272: 1273: 1274:
1275: public function enqueue_styles() {
1276:
1277: wp_register_style($this->taxonomy . '-frontend', esc_url($this->assets_url) . 'css/modules-frontend.css', Sensei()->version );
1278: wp_enqueue_style($this->taxonomy . '-frontend');
1279:
1280: }
1281:
1282: 1283: 1284: 1285: 1286: 1287: 1288:
1289: public function admin_enqueue_scripts( $hook ) {
1290:
1291: 1292: 1293: 1294: 1295:
1296: $script_on_pages_white_list = apply_filters( 'sensei_module_admin_script_page_white_lists', array(
1297: 'edit-tags.php',
1298: 'course_page_module-order',
1299: 'post-new.php',
1300: 'post.php',
1301: 'term.php',
1302:
1303: ) );
1304:
1305: if ( ! in_array( $hook, $script_on_pages_white_list ) ) {
1306: return;
1307: }
1308:
1309: $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
1310:
1311: wp_enqueue_script( 'sensei-chosen', Sensei()->plugin_url . 'assets/chosen/chosen.jquery' . $suffix . '.js', array( 'jquery' ), Sensei()->version , true);
1312: wp_enqueue_script( 'sensei-chosen-ajax', Sensei()->plugin_url . 'assets/chosen/ajax-chosen.jquery' . $suffix . '.js', array( 'jquery', 'sensei-chosen' ), Sensei()->version , true );
1313: wp_enqueue_script( $this->taxonomy . '-admin', esc_url( $this->assets_url ) . 'js/modules-admin' . $suffix . '.js', array( 'jquery', 'sensei-chosen', 'sensei-chosen-ajax', 'jquery-ui-sortable', 'sensei-core-select2' ), Sensei()->version, true );
1314:
1315:
1316: $localize_modulesAdmin = array(
1317: 'search_courses_nonce' => wp_create_nonce( 'search-courses' ),
1318: 'selectPlaceholder' => __( 'Search for courses', 'woothemes-sensei' )
1319: );
1320:
1321: wp_localize_script( $this->taxonomy . '-admin' ,'modulesAdmin', $localize_modulesAdmin );
1322: }
1323:
1324: 1325: 1326: 1327: 1328: 1329: 1330:
1331: public function admin_enqueue_styles() {
1332:
1333: wp_register_style($this->taxonomy . '-sortable', esc_url($this->assets_url) . 'css/modules-admin.css','',Sensei()->version );
1334: wp_enqueue_style($this->taxonomy . '-sortable');
1335:
1336: }
1337:
1338: 1339: 1340: 1341: 1342: 1343: 1344: 1345:
1346: public function course_modules_title( ) {
1347:
1348: if( sensei_module_has_lessons() ){
1349:
1350: echo '<header><h2>' . __('Modules', 'woothemes-sensei') . '</h2></header>';
1351:
1352: }
1353:
1354: }
1355:
1356: 1357: 1358: 1359: 1360: 1361: 1362:
1363: public function load_course_module_content_template(){
1364:
1365:
1366: $located_template= locate_template( Sensei()->template_url . 'single-course/course-modules.php' );
1367: if( $located_template ){
1368:
1369: Sensei_Templates::get_template( 'single-course/course-modules.php' );
1370: return;
1371:
1372: }
1373:
1374: Sensei_Templates::get_template( 'single-course/modules.php' );
1375:
1376: }
1377:
1378: 1379: 1380: 1381: 1382: 1383: 1384: 1385: 1386:
1387: public function get_lessons( $course_id , $term_id ){
1388:
1389: $lesson_query = $this->get_lessons_query( $course_id, $term_id );
1390:
1391: if( isset( $lesson_query->posts ) ){
1392:
1393: return $lesson_query->posts;
1394:
1395: }else{
1396:
1397: return array();
1398:
1399: }
1400:
1401: }
1402:
1403: 1404: 1405: 1406: 1407: 1408: 1409: 1410: 1411:
1412: public function get_lessons_query( $course_id , $term_id ){
1413:
1414: if( empty( $term_id ) || empty( $course_id ) ){
1415:
1416: return array();
1417:
1418: }
1419:
1420: $args = array(
1421: 'post_type' => 'lesson',
1422: 'post_status' => 'publish',
1423: 'posts_per_page' => -1,
1424: 'meta_query' => array(
1425: array(
1426: 'key' => '_lesson_course',
1427: 'value' => intval($course_id),
1428: 'compare' => '='
1429: )
1430: ),
1431: 'tax_query' => array(
1432: array(
1433: 'taxonomy' => 'module',
1434: 'field' => 'id',
1435: 'terms' => intval( $term_id )
1436: )
1437: ),
1438: 'orderby' => 'menu_order',
1439: 'order' => 'ASC',
1440: 'suppress_filters' => 0
1441: );
1442:
1443: if (version_compare( Sensei()->version, '1.6.0', '>=')) {
1444: $args['meta_key'] = '_order_module_' . intval( $term_id );
1445: $args['orderby'] = 'meta_value_num date';
1446: }
1447:
1448: $lessons_query = new WP_Query( $args );
1449:
1450: return $lessons_query;
1451:
1452: }
1453:
1454: 1455: 1456: 1457: 1458: 1459: 1460: 1461: 1462:
1463: public function get_none_module_lessons( $course_id ){
1464:
1465: $non_module_lessons = array();
1466:
1467:
1468: if( empty( $course_id ) || 'course' != get_post_type( $course_id ) ) {
1469:
1470: return $non_module_lessons;
1471: }
1472:
1473:
1474: if( get_transient( 'sensei_'. $course_id .'_none_module_lessons') ){
1475:
1476: return get_transient( 'sensei_'. $course_id .'_none_module_lessons');
1477:
1478: }
1479:
1480:
1481: $course_modules = $this->get_course_modules( $course_id );
1482:
1483:
1484: if( empty( $course_modules ) || ! is_array( $course_modules ) ){
1485:
1486: return Sensei()->course->course_lessons( $course_id );
1487:
1488: }
1489:
1490: $terms = array();
1491: foreach( $course_modules as $module ){
1492:
1493: array_push( $terms , $module->term_id );
1494:
1495: }
1496:
1497: $args = array(
1498: 'post_type' => 'lesson',
1499: 'post_status' => 'publish',
1500: 'posts_per_page' => -1,
1501: 'meta_query' => array(
1502: array(
1503: 'key' => '_lesson_course',
1504: 'value' => intval( $course_id ),
1505: 'compare' => '='
1506: )
1507: ),
1508: 'tax_query' => array(
1509: array(
1510: 'taxonomy' => 'module',
1511: 'field' => 'id',
1512: 'terms' => $terms,
1513: 'operator' => 'NOT IN'
1514: )
1515: ),
1516: 'orderby' => 'menu_order',
1517: 'order' => 'ASC',
1518: 'suppress_filters' => 0
1519: );
1520:
1521: $wp_lessons_query = new WP_Query( $args );
1522:
1523: if( isset( $wp_lessons_query->posts) && count( $wp_lessons_query->posts ) > 0 ){
1524: $non_module_lessons = $wp_lessons_query->get_posts();
1525: set_transient( 'sensei_'. $course_id .'_none_module_lessons', $non_module_lessons, 10 * DAY_IN_SECONDS );
1526: }
1527:
1528: return $non_module_lessons;
1529: }
1530:
1531: 1532: 1533: 1534: 1535:
1536: public function setup_modules_taxonomy(){
1537:
1538: $labels = array(
1539: 'name' => __('Modules', 'woothemes-sensei'),
1540: 'singular_name' => __('Module', 'woothemes-sensei'),
1541: 'search_items' => __('Search Modules', 'woothemes-sensei'),
1542: 'all_items' => __('All Modules', 'woothemes-sensei'),
1543: 'parent_item' => __('Parent Module', 'woothemes-sensei'),
1544: 'parent_item_colon' => __('Parent Module:', 'woothemes-sensei'),
1545: 'edit_item' => __('Edit Module', 'woothemes-sensei'),
1546: 'update_item' => __('Update Module', 'woothemes-sensei'),
1547: 'add_new_item' => __('Add New Module', 'woothemes-sensei'),
1548: 'new_item_name' => __('New Module Name', 'woothemes-sensei'),
1549: 'menu_name' => __('Modules', 'woothemes-sensei'),
1550: );
1551:
1552: 1553: 1554: 1555: 1556: 1557:
1558: $modules_rewrite_slug = apply_filters('sensei_module_slug', 'modules');
1559:
1560: $args = array(
1561: 'public' => true,
1562: 'hierarchical' => true,
1563: 'show_admin_column' => true,
1564: 'capabilities' => array(
1565: 'manage_terms' => 'manage_categories',
1566: 'edit_terms' => 'edit_courses',
1567: 'delete_terms' => 'manage_categories',
1568: 'assign_terms' => 'edit_courses'
1569: ),
1570: 'show_in_nav_menus' => false,
1571: 'show_in_quick_edit' => false,
1572: 'show_ui' => true,
1573: 'rewrite' => array('slug' => $modules_rewrite_slug ),
1574: 'labels' => $labels
1575: );
1576:
1577: register_taxonomy( 'module' , array('course', 'lesson'), $args);
1578:
1579: }
1580:
1581: 1582: 1583: 1584: 1585: 1586: 1587: 1588:
1589: function redirect_to_lesson_module_taxonomy_to_course( ){
1590:
1591: global $typenow , $taxnow;
1592:
1593: if( 'lesson'== $typenow && 'module'==$taxnow ){
1594: wp_safe_redirect( esc_url_raw( 'edit-tags.php?taxonomy=module&post_type=course' ) );
1595: }
1596:
1597: }
1598:
1599: 1600: 1601: 1602: 1603: 1604: 1605: 1606:
1607: public function remove_lessons_menu_model_taxonomy(){
1608: global $submenu;
1609:
1610: if( ! isset( $submenu['edit.php?post_type=lesson'] ) || !is_array( $submenu['edit.php?post_type=lesson'] ) ){
1611: return;
1612: }
1613:
1614: $lesson_main_menu = $submenu['edit.php?post_type=lesson'];
1615: foreach( $lesson_main_menu as $index => $sub_item ){
1616:
1617: if( 'edit-tags.php?taxonomy=module&post_type=lesson' == $sub_item[2] ){
1618: unset( $submenu['edit.php?post_type=lesson'][ $index ]);
1619: }
1620: }
1621:
1622: }
1623:
1624: 1625: 1626: 1627: 1628: 1629: 1630: 1631:
1632: public function remove_courses_menu_model_taxonomy(){
1633: global $submenu;
1634:
1635: if( ! isset( $submenu['edit.php?post_type=course'] ) || !is_array( $submenu['edit.php?post_type=course'] ) ){
1636: return;
1637: }
1638:
1639: $course_main_menu = $submenu['edit.php?post_type=course'];
1640: foreach( $course_main_menu as $index => $sub_item ){
1641:
1642: if( 'edit-tags.php?taxonomy=module&post_type=course' == $sub_item[2] ){
1643: unset( $submenu['edit.php?post_type=course'][ $index ]);
1644: }
1645: }
1646:
1647: }
1648:
1649: 1650: 1651: 1652: 1653: 1654: 1655: 1656: 1657: 1658:
1659: public static function get_term_authors( $term_name ){
1660:
1661: $terms = get_terms( array( 'module') , array( 'name__like'=>$term_name, 'hide_empty' => false ) );
1662:
1663: $owners = array();
1664: if( empty( $terms ) ){
1665:
1666: return $owners;
1667:
1668: }
1669:
1670:
1671:
1672:
1673:
1674: foreach( $terms as $term){
1675: if( $term->name == $term_name ){
1676:
1677:
1678: $owners[] = Sensei_Core_Modules::get_term_author( $term->slug );
1679:
1680: }
1681:
1682: }
1683:
1684: return $owners;
1685:
1686: }
1687:
1688: 1689: 1690: 1691: 1692: 1693: 1694: 1695: 1696: 1697: 1698:
1699: public static function get_term_author( $slug='' ){
1700:
1701: $term_owner = get_user_by( 'email', get_bloginfo( 'admin_email' ) );
1702:
1703: if( empty( $slug ) ){
1704:
1705: return $term_owner;
1706:
1707: }
1708:
1709:
1710: $slug_parts = explode( '-', $slug );
1711:
1712: if( count( $slug_parts ) > 1 ){
1713:
1714:
1715: $possible_user_id = $slug_parts[0];
1716: $author = get_userdata( $possible_user_id );
1717:
1718:
1719:
1720: if( is_a( $author, 'WP_User' ) ){
1721:
1722: $term_owner = $author;
1723:
1724: }
1725: }
1726:
1727: return $term_owner;
1728: }
1729:
1730: 1731: 1732: 1733: 1734: 1735: 1736: 1737: 1738:
1739: public function course_module_metabox( $post ) {
1740:
1741: $tax_name = 'module';
1742: $taxonomy = get_taxonomy( 'module' );
1743:
1744: ?>
1745: <div id="taxonomy-<?php echo $tax_name; ?>" class="categorydiv">
1746: <ul id="<?php echo $tax_name; ?>-tabs" class="category-tabs">
1747: <li class="tabs"><a href="#<?php echo $tax_name; ?>-all"><?php echo $taxonomy->labels->all_items; ?></a></li>
1748: <li class="hide-if-no-js"><a href="#<?php echo $tax_name; ?>-pop"><?php _e( 'Most Used' ); ?></a></li>
1749: </ul>
1750:
1751: <div id="<?php echo $tax_name; ?>-pop" class="tabs-panel" style="display: none;">
1752: <ul id="<?php echo $tax_name; ?>checklist-pop" class="categorychecklist form-no-clear" >
1753: <?php $popular_ids = wp_popular_terms_checklist( $tax_name ); ?>
1754: </ul>
1755: </div>
1756:
1757: <div id="<?php echo $tax_name; ?>-all" class="tabs-panel">
1758: <?php
1759: $name = ( $tax_name == 'category' ) ? 'post_category' : 'tax_input[' . $tax_name . ']';
1760: echo "<input type='hidden' name='{$name}[]' value='0' />";
1761: ?>
1762: <ul id="<?php echo $tax_name; ?>checklist" data-wp-lists="list:<?php echo $tax_name; ?>" class="categorychecklist form-no-clear">
1763: <?php wp_terms_checklist( $post->ID, array( 'taxonomy'=>$tax_name , 'popular_cats' => $popular_ids ) ); ?>
1764: </ul>
1765: </div>
1766: <?php if ( current_user_can( $taxonomy->cap->edit_terms ) ) : ?>
1767: <div id="<?php echo $tax_name; ?>-adder" class="wp-hidden-children">
1768: <h4>
1769: <a id="sensei-<?php echo $tax_name; ?>-add-toggle" href="#<?php echo $tax_name; ?>-add" class="hide-if-no-js">
1770: <?php
1771:
1772: printf( __( '+ %s' ), $taxonomy->labels->add_new_item );
1773: ?>
1774: </a>
1775: </h4>
1776: <p id="sensei-<?php echo $tax_name; ?>-add" class="category-add wp-hidden-child">
1777: <label class="screen-reader-text" for="new<?php echo $tax_name; ?>"><?php echo $taxonomy->labels->add_new_item; ?></label>
1778: <input type="text" name="new<?php echo $tax_name; ?>" id="new<?php echo $tax_name; ?>" class="form-required form-input-tip" value="<?php echo esc_attr( $taxonomy->labels->new_item_name ); ?>" aria-required="true"/>
1779: <a class="button" id="sensei-<?php echo $tax_name; ?>-add-submit" class="button category-add-submit"><?php echo esc_attr( $taxonomy->labels->add_new_item ); ?></a>
1780: <?php wp_nonce_field( '_ajax_nonce-add-' . $tax_name, 'add_module_nonce' ); ?>
1781: <span id="<?php echo $tax_name; ?>-ajax-response"></span>
1782: </p>
1783: </div>
1784: <?php endif; ?>
1785: </div>
1786: <?php
1787:
1788: }
1789:
1790:
1791: 1792: 1793: 1794: 1795: 1796:
1797: public static function add_new_module_term( ) {
1798:
1799:
1800: if( ! isset( $_POST[ 'security' ] ) || ! wp_verify_nonce( $_POST[ 'security' ], '_ajax_nonce-add-module' ) ){
1801: wp_send_json_error( array('error'=> 'wrong security nonce') );
1802: }
1803:
1804:
1805: $term_name = sanitize_text_field( $_POST['newTerm'] );
1806:
1807: if( current_user_can('manage_options' ) ) {
1808:
1809: $term_slug = str_ireplace(' ', '-', trim( $term_name ) );
1810:
1811: } else {
1812:
1813: $term_slug = get_current_user_id() . '-' . str_ireplace(' ', '-', trim( $term_name ) );
1814:
1815: }
1816:
1817: $course_id = sanitize_text_field( $_POST['course_id'] );
1818:
1819:
1820: $slug = wp_insert_term( $term_name,'module', array('slug'=> $term_slug) );
1821:
1822:
1823: if( is_wp_error( $slug ) ){
1824:
1825:
1826: $term_data = array();
1827:
1828:
1829: if( isset( $slug->errors['term_exists'] ) ){
1830:
1831: $term = get_term_by( 'slug', $term_slug, 'module');
1832: $term_data['name'] = $term_name;
1833: $term_data['id'] = $term->term_id;
1834:
1835:
1836: wp_set_object_terms( $course_id, $term->term_id, 'module', true );
1837: }
1838:
1839: wp_send_json_error(array( 'errors'=>$slug->errors , 'term'=> $term_data ) );
1840:
1841: }
1842:
1843:
1844:
1845: wp_set_object_terms( $course_id, $slug['term_id'], 'module', true );
1846:
1847:
1848: wp_send_json_success( array( 'termId' => $slug['term_id'], 'termName' => $term_name ) );
1849:
1850: }
1851:
1852: 1853: 1854: 1855: 1856: 1857: 1858: 1859:
1860: public function filter_module_terms( $terms, $taxonomies, $args ){
1861:
1862:
1863: if( current_user_can( 'manage_options' ) || !in_array( 'module', $taxonomies ) || ! is_admin() ){
1864: return $terms;
1865: }
1866:
1867:
1868: remove_filter('get_terms', array( $this, 'filter_module_terms' ), 20, 3 );
1869:
1870:
1871: if( isset( $args['fields'] ) && 'id=>parent' == $args['fields'] ){
1872:
1873: $terms = array_keys( $terms );
1874: }
1875:
1876: $teachers_terms = $this->filter_terms_by_owner( $terms, get_current_user_id() );
1877:
1878:
1879: add_filter('get_terms', array( $this, 'filter_module_terms' ), 20, 3 );
1880:
1881: return $teachers_terms;
1882: }
1883:
1884: 1885: 1886: 1887: 1888: 1889: 1890: 1891:
1892: public function filter_course_selected_terms( $terms, $course_ids_array, $taxonomies ){
1893:
1894:
1895: if( current_user_can( 'manage_options' ) || ! is_admin() || empty( $terms )
1896:
1897: || count( $taxonomies ) > 1 || !in_array( 'module', $taxonomies ) ){
1898: return $terms;
1899: }
1900:
1901: $term_objects = $this->filter_terms_by_owner( $terms, get_current_user_id() );
1902:
1903:
1904:
1905: if( is_object( $terms[0] ) ){
1906: return $term_objects;
1907: }
1908:
1909: $terms = array();
1910: foreach( $term_objects as $term_object ){
1911: $terms[] = $term_object->term_id;
1912: }
1913:
1914: return $terms;
1915:
1916:
1917: }
1918:
1919: 1920: 1921: 1922: 1923: 1924: 1925: 1926: 1927:
1928: public function filter_terms_by_owner( $terms, $user_id ){
1929:
1930: $users_terms = array();
1931:
1932: foreach( $terms as $index => $term ){
1933:
1934: if( is_numeric( $term ) ){
1935:
1936: $term = get_term( $term, 'module' );
1937: }
1938:
1939: $author = Sensei_Core_Modules::get_term_author( $term->slug );
1940:
1941: if ( $user_id == $author->ID ) {
1942:
1943: $users_terms[] = $term;
1944: }
1945:
1946: }
1947:
1948: return $users_terms;
1949:
1950: }
1951:
1952: 1953: 1954: 1955: 1956: 1957: 1958: 1959:
1960: public function append_teacher_name_to_module( $terms, $taxonomies, $args )
1961: {
1962:
1963:
1964: if ( empty( $terms ) || !current_user_can('manage_options') || !in_array('module', $taxonomies) || !is_admin()) {
1965: return $terms;
1966: }
1967:
1968:
1969:
1970: if (isset( $args['fields'] ) && 'id=>parent' == $args['fields']) {
1971:
1972: return $terms;
1973:
1974: }
1975:
1976:
1977: foreach( $terms as $index => $term ){
1978:
1979: if( is_numeric( $term ) ){
1980:
1981: $term = get_term( $term, 'module' );
1982: }
1983:
1984: $author = Sensei_Core_Modules::get_term_author( $term->slug );
1985:
1986: if( ! user_can( $author, 'manage_options' ) && isset( $term->name ) ) {
1987: $term->name = $term->name . ' (' . $author->display_name . ') ';
1988: }
1989:
1990:
1991: $users_terms[] = $term;
1992:
1993: }
1994:
1995: return $users_terms;
1996: }
1997:
1998: 1999: 2000: 2001: 2002:
2003: public static function remove_default_modules_box() {
2004:
2005: remove_meta_box('modulediv', 'course', 'side');
2006:
2007: }
2008:
2009: 2010: 2011: 2012: 2013: 2014: 2015:
2016: public static function reset_none_modules_transient ( $post_id ){
2017:
2018:
2019: if( in_array( get_post_type( $post_id ), array( 'course', 'lesson' ) ) ){
2020:
2021: $course_id = '';
2022:
2023: if( 'lesson' == get_post_type( $post_id ) ){
2024:
2025: $course_id = Sensei()->lesson->get_course_id( $post_id );
2026:
2027: }
2028:
2029:
2030: if( !empty( $course_id ) ){
2031:
2032: delete_transient( 'sensei_'. $course_id .'_none_module_lessons' );
2033:
2034: }
2035:
2036: }
2037:
2038: }
2039:
2040: 2041: 2042: 2043: 2044: 2045: 2046:
2047: public static function deprecate_sensei_single_course_modules_content(){
2048:
2049: sensei_do_deprecated_action( 'sensei_single_course_modules_content','1.9.0','sensei_single_course_modules_before or sensei_single_course_modules_after' );
2050:
2051: }
2052:
2053: 2054: 2055: 2056: 2057: 2058: 2059:
2060: public static function setup_single_course_module_loop(){
2061:
2062: global $sensei_modules_loop, $post;
2063: $course_id = $post->ID;
2064:
2065: $modules = Sensei()->modules->get_course_modules( $course_id );
2066:
2067:
2068: $sensei_modules_loop['total'] = 0;
2069: $sensei_modules_loop['modules'] = array();
2070: $sensei_modules_loop['current'] = -1;
2071:
2072:
2073: if( !$modules || empty( $modules ) ){
2074: return;
2075: }
2076:
2077:
2078: $lessons_in_all_modules = array();
2079: foreach( $modules as $term ){
2080:
2081: $lessons_in_this_module = Sensei()->modules->get_lessons( $course_id , $term->term_id);
2082: $lessons_in_all_modules = array_merge( $lessons_in_all_modules, $lessons_in_this_module );
2083:
2084: }
2085:
2086:
2087:
2088: $sensei_modules_loop['total'] = count( $modules );
2089: $sensei_modules_loop['modules'] = $modules;
2090: $sensei_modules_loop['current'] = -1;
2091: $sensei_modules_loop['course_id'] = $course_id;
2092:
2093: }
2094:
2095: 2096: 2097: 2098: 2099: 2100:
2101: public static function teardown_single_course_module_loop(){
2102:
2103: global $sensei_modules_loop, $wp_query, $post;
2104:
2105:
2106: $sensei_modules_loop['total'] = 0;
2107: $sensei_modules_loop['modules'] = array();
2108: $sensei_modules_loop['current'] = -1;
2109:
2110:
2111: wp_reset_query();
2112: $post = $wp_query->post;
2113: }
2114:
2115: }
2116: