Completed
Push — master ( d51ce1...80c0ca )
by Dwain
05:52
created

Sensei_Frontend::sensei_show_admin_bar()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 9
rs 9.6667
cc 2
eloc 3
nc 2
nop 0
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
4
/**
5
 * Sensei Frontend Class
6
 *
7
 * All functionality pertaining to the frontend of Sensei.
8
 *
9
 * @package WordPress
10
 * @subpackage Sensei
11
 * @category Frontend
12
 * @author WooThemes
13
 * @since 1.0.0
14
 */
15
class Sensei_Frontend {
16
17
	public $messages;
18
	public $data;
19
20
	/**
21
	 * Constructor.
22
	 * @since  1.0.0
23
	 */
24
	public function __construct () {
25
26
		// Template output actions
27
		add_action( 'sensei_before_main_content', array( $this, 'sensei_output_content_wrapper' ), 10 );
28
		add_action( 'sensei_after_main_content', array( $this, 'sensei_output_content_wrapper_end' ), 10 );
29
		add_action( 'sensei_lesson_archive_lesson_title', array( $this, 'sensei_lesson_archive_lesson_title' ), 10 );
30
31
		// 1.2.1
32
		add_action( 'sensei_complete_lesson', array( $this, 'sensei_complete_lesson' ) );
33
		add_action( 'init', array( $this, 'sensei_complete_course' ), 5 );
34
		add_action( 'sensei_frontend_messages', array( $this, 'sensei_frontend_messages' ) );
35
		add_action( 'sensei_lesson_video', array( $this, 'sensei_lesson_video' ), 10, 1 );
36
		add_action( 'sensei_complete_lesson_button', array( $this, 'sensei_complete_lesson_button' ) );
37
		add_action( 'sensei_reset_lesson_button', array( $this, 'sensei_reset_lesson_button' ) );
38
39
		add_action( 'sensei_course_archive_meta', array( $this, 'sensei_course_archive_meta' ) );
40
41
		add_action( 'sensei_lesson_tag_main_content', array( $this, 'sensei_lesson_archive_main_content' ), 10 );
42
		add_action( 'sensei_no_permissions_main_content', array( $this, 'sensei_no_permissions_main_content' ), 10 );
43
44
		add_action( 'sensei_lesson_meta', array( $this, 'sensei_lesson_meta' ), 10 );
45
		add_action( 'sensei_single_course_content_inside_before', array( $this, 'sensei_course_start' ), 10 );
46
47
		// add_filter( 'get_comments_number', array( $this, 'sensei_lesson_comment_count' ), 1 );
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
48
		add_filter( 'the_title', array( $this, 'sensei_lesson_preview_title' ), 10, 2 );
49
50
		//1.6.2
51
		add_filter( 'wp_login_failed', array( $this, 'sensei_login_fail_redirect' ), 10 );
52
		add_filter( 'init', array( $this, 'sensei_handle_login_request' ), 10 );
53
		//1.6.3
54
		add_action( 'init', array( $this, 'sensei_process_registration' ), 2 );
55
		//1.7.0
56
		add_action( 'sensei_pagination', array( $this, 'sensei_breadcrumb' ), 80, 1 );
57
58
		// Fix pagination for course archive pages when filtering by course type
59
		add_filter( 'pre_get_posts', array( $this, 'sensei_course_archive_pagination' ) );
60
61
		// Scripts and Styles
62
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ) );
63
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
64
65
		// Custom Menu Item filters
66
		add_filter( 'wp_setup_nav_menu_item', array( $this, 'sensei_setup_nav_menu_item' ) );
67
		add_filter( 'wp_nav_menu_objects', array( $this, 'sensei_wp_nav_menu_objects' ) );
68
		// Search Results filters
69
		add_filter( 'post_class', array( $this, 'sensei_search_results_classes' ), 10 );
70
		// Only show course & lesson excerpts in search results
71
		add_filter( 'the_content', array( $this, 'sensei_search_results_excerpt' ) );
72
73
        //Use WooCommerce filter to show admin bar to Teachers.
74
        add_action( 'init', array( $this, 'sensei_show_admin_bar') );
75
76
        // Remove course from active courses if an order is cancelled or refunded
77
		add_action( 'woocommerce_order_status_processing_to_cancelled', array( $this, 'remove_active_course' ), 10, 1 );
78
		add_action( 'woocommerce_order_status_completed_to_cancelled', array( $this, 'remove_active_course' ), 10, 1 );
79
		add_action( 'woocommerce_order_status_on-hold_to_cancelled', array( $this, 'remove_active_course' ), 10, 1 );
80
		add_action( 'woocommerce_order_status_processing_to_refunded', array( $this, 'remove_active_course' ), 10, 1 );
81
		add_action( 'woocommerce_order_status_completed_to_refunded', array( $this, 'remove_active_course' ), 10, 1 );
82
		add_action( 'woocommerce_order_status_on-hold_to_refunded', array( $this, 'remove_active_course' ), 10, 1 );
83
84
		// Make sure correct courses are marked as active for users
85
		add_action( 'sensei_before_my_courses', array( $this, 'activate_purchased_courses' ), 10, 1 );
86
		add_action( 'sensei_single_course_content_inside_before', array( $this, 'activate_purchased_single_course' ), 10 );
87
88
		// Lesson tags
89
		add_action( 'sensei_lesson_meta_extra', array( $this, 'lesson_tags_display' ), 10, 1 );
90
		add_action( 'pre_get_posts', array( $this, 'lesson_tag_archive_filter' ), 10, 1 );
91
		add_filter( 'sensei_lessons_archive_text', array( $this, 'lesson_tag_archive_header' ) );
92
		add_action( 'sensei_loop_lesson_inside_before', array( $this, 'lesson_tag_archive_description' ), 11 );
93
94
		// Hide Sensei activity comments from lesson and course pages
95
		add_filter( 'wp_list_comments_args', array( $this, 'hide_sensei_activity' ) );
96
	} // End __construct()
97
98
	/**
99
	 * Graceful fallback for course and lesson variables on Frontend object
100
	 *
101
	 * @param string $key Key to get.
102
	 * @since  1.7.3
103
	 * @return array|mixed
104
	 */
105
	public function __get( $key ) {
106
107
		if ( 'lesson' == $key || 'course' == $key ) {
108
			if ( WP_DEBUG ) {
109
				trigger_error( sprintf( 'Sensei()->frontend->%1$s has been <strong>deprecated</strong> since version %2$s! Please use Sensei()->%1$s to access the instance.', $key, '1.7.3' ) );
110
			}
111
			return Sensei()->$key;
112
		}
113
114
		return null;
115
	}
116
117
	/**
118
	 * Enqueue frontend JavaScripts.
119
	 * @since  1.0.0
120
	 * @return void
121
	 */
122
	public function enqueue_scripts () {
123
124
		$disable_js = false;
125
		if ( isset( Sensei()->settings->settings[ 'js_disable' ] ) ) {
126
			$disable_js = Sensei()->settings->settings[ 'js_disable' ];
127
		} // End If Statement
128
		if ( ! $disable_js ) {
129
130
			$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
131
132
			// My Courses tabs script
133
			wp_register_script( Sensei()->token . '-user-dashboard', esc_url( Sensei()->plugin_url . 'assets/js/user-dashboard' . $suffix . '.js' ), array( 'jquery-ui-tabs' ), Sensei()->version, true );
134
			wp_enqueue_script( Sensei()->token . '-user-dashboard' );
135
136
137
            // Course Archive javascript
138
            if( is_post_type_archive( 'course' ) ){
139
140
                wp_register_script( 'sensei-course-archive-js', esc_url( Sensei()->plugin_url . 'assets/js/frontend/course-archive' . $suffix . '.js' ), array( 'jquery' ), '1', true );
141
                wp_enqueue_script( 'sensei-course-archive-js' );
142
143
            }
144
145
146
			// Allow additional scripts to be loaded
147
			do_action( 'sensei_additional_scripts' );
148
149
		} // End If Statement
150
151
	} // End enqueue_scripts()
152
153
	/**
154
	 * Enqueue frontend CSS files.
155
	 * @since  1.0.0
156
	 * @return void
157
	 */
158
	public function enqueue_styles () {
159
160
161
		$disable_styles = false;
162
		if ( isset( Sensei()->settings->settings[ 'styles_disable' ] ) ) {
163
			$disable_styles = Sensei()->settings->settings[ 'styles_disable' ];
164
		} // End If Statement
165
166
		// Add filter for theme overrides
167
		$disable_styles = apply_filters( 'sensei_disable_styles', $disable_styles );
168
169
		if ( ! $disable_styles ) {
170
171
			wp_register_style( Sensei()->token . '-frontend', Sensei()->plugin_url . 'assets/css/frontend/sensei.css', '', Sensei()->version, 'screen' );
172
			wp_enqueue_style( Sensei()->token . '-frontend' );
173
174
			// Allow additional stylesheets to be loaded
175
			do_action( 'sensei_additional_styles' );
176
177
		} // End If Statement
178
179
	} // End enqueue_styles()
180
181
182
	/**
183
	 * sensei_get_template_part function.
184
	 *
185
     * @deprecated sine 1.9.0
186
	 * @access public
187
	 * @param mixed $slug
188
	 * @param string $name (default: '')
189
	 * @return void
190
	 */
191
	function sensei_get_template_part( $slug, $name = '' ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
192
193
        _deprecated_function( 'class-woothemes-sensei-frontend.php', '1.9.0', 'Sensei_Templates::get_part' );
194
        Sensei_Templates::get_part( $slug, $name );
195
196
	} // End sensei_get_template_part()
197
198
	/**
199
	 * sensei_get_template function.
200
	 *
201
     * @deprecated since 1.9.0
202
	 * @access public
203
	 * @param mixed $template_name
204
	 * @param array $args (default: array())
205
	 * @param string $template_path (default: '')
206
	 * @param string $default_path (default: '')
207
	 * @return void
208
	 */
209
	function sensei_get_template( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
210
211
        _deprecated_function( 'sensei_get_template', '1.9.0', 'Sensei_Templates::get_template' );
212
        Sensei_Templates::get_template($template_name, $args, $template_path, $default_path  );
213
214
	} // End sensei_get_template()
215
216
217
	/**
218
	 * sensei_locate_template function.
219
	 *
220
	 * @access public
221
	 * @param mixed $template_name
222
	 * @param string $template_path (default: '')
223
	 * @param string $default_path (default: '')
224
	 * @return void
225
	 */
226
	function sensei_locate_template( $template_name, $template_path = '', $default_path = '' ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
227
228
        _deprecated_function( 'sensei_locate_template', '1.9.0', 'Sensei_Templates::locate_template' );
229
        Sensei_Templates::locate_template( $template_name, $template_path, $default_path );
230
231
	} // End sensei_locate_template()
232
233
234
	/**
235
	 * sensei_output_content_wrapper function.
236
     *
237
	 * @access public
238
	 * @return void
239
	 */
240 View Code Duplication
	function sensei_output_content_wrapper() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
241
242
	    // backwards compatibility check for old location under the wrappers directory of the active theme
243
        $backwards_compatible_wrapper_location =   array(
244
            Sensei()->template_url . 'wrappers/wrapper-start.php',
245
            'wrappers/wrapper-start.php'
246
        );
247
248
        $template = locate_template( $backwards_compatible_wrapper_location );
249
        if( !empty( $template ) ){
250
251
            Sensei_Templates::get_template( 'wrappers/wrapper-start.php' );
252
            return;
253
254
        }
255
256
		Sensei_Templates::get_template( 'globals/wrapper-start.php' );
257
258
	} // End sensei_output_content_wrapper()
259
260
261
	/**
262
	 * sensei_output_content_wrapper_end function.
263
     *
264
	 * @access public
265
	 * @return void
266
	 */
267 View Code Duplication
	function sensei_output_content_wrapper_end() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
268
269
	    // backwards compatibility check for old location under the wrappers directory of the active theme
270
        $backwards_compatible_wrapper_location =   array(
271
            Sensei()->template_url . 'wrappers/wrapper-end.php',
272
            'wrappers/wrapper-end.php'
273
        );
274
275
        $backwards_compatible_template = locate_template( $backwards_compatible_wrapper_location );
276
        if( !empty( $backwards_compatible_template ) ){
277
278
            Sensei_Templates::get_template( 'wrappers/wrapper-end.php' );
279
            return;
280
281
        }
282
283
284
		Sensei_Templates::get_template( 'globals/wrapper-end.php' );
285
286
	} // End sensei_output_content_wrapper_end()
287
288
289
	/**
290
	 * sensei_output_content_pagination function.
291
	 *
292
	 * @access public
293
	 * @return void
294
	 */
295
	public static function load_content_pagination() {
296
297
        if( is_singular('course') ) {
298
299
            // backwards compatibility check for old location under the wrappers directory of the active theme
300
            $template = locate_template( array( Sensei()->template_url . 'wrappers/pagination-posts.php' ) );
301
            if( !empty( $template ) ){
302
303
                Sensei_Templates::get_template( 'wrappers/pagination-posts.php' );
304
                return;
305
306
            }
307
308
			Sensei_Templates::get_template( 'globals/pagination-posts.php' );
309
310 View Code Duplication
		} elseif( is_singular('lesson') ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
311
312
		    // backwards compatibility check for old location under the wrappers directory of the active theme
313
		    $template = locate_template( array( Sensei()->template_url . 'wrappers/pagination-lesson.php' ) );
314
            if( !empty( $template ) ){
315
316
                Sensei_Templates::get_template( 'wrappers/pagination-lesson.php' );
317
                return;
318
319
            }
320
321
			Sensei_Templates::get_template( 'globals/pagination-lesson.php' );
322
323
		} elseif( is_singular('quiz') ) {
324
325
		    // backwards compatibility check for old location under the wrappers directory of the active theme
326
		    $template = locate_template( array( Sensei()->template_url . 'wrappers/pagination-quiz.php' ) );
327
            if( !empty( $template ) ){
328
329
                Sensei_Templates::get_template( 'wrappers/pagination-quiz.php' );
330
                return;
331
332
            }
333
334
			Sensei_Templates::get_template( 'globals/pagination-quiz.php' );
335
336 View Code Duplication
		} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
337
338
            // backwards compatibility check for old location under the wrappers directory of the active theme
339
            $template = locate_template( array( Sensei()->template_url . 'wrappers/pagination.php' ) );
340
            if( !empty( $template ) ){
341
342
                Sensei_Templates::get_template( 'wrappers/pagination.php' );
343
                return;
344
345
            }
346
347
			Sensei_Templates::get_template( 'globals/pagination.php' );
348
349
		} // End If Statement
350
351
	} // End sensei_output_content_pagination()
352
353
	/**
354
	 * outputs comments for the specified pages
355
	 * @deprecated
356
	 * @return void
357
	 */
358
	function sensei_output_comments() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
359
360
		Sensei_Lesson::output_comments();
361
362
	} // End sensei_output_comments()
363
364
	/**
365
	 * sensei_setup_nav_menu_item function.
366
	 *
367
	 * Generate the urls for Sensei custom menu items.
368
	 *
369
	 * @access public
370
	 * @param object $item
371
	 * @return object $item
372
	 */
373
	public function sensei_setup_nav_menu_item( $item ) {
374
		global $pagenow, $wp_rewrite;
375
376
		if( 'nav-menus.php' != $pagenow && !defined('DOING_AJAX') && isset( $item->url ) && 'custom' == $item->type ) {
377
378
			// Set up Sensei menu links
379
			$course_page_id = intval( Sensei()->settings->settings[ 'course_page' ] );
0 ignored issues
show
Unused Code introduced by
$course_page_id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
380
			$my_account_page_id = intval( Sensei()->settings->settings[ 'my_course_page' ] );
381
382
			$course_page_url = Sensei_Course::get_courses_page_url();
383
			$lesson_archive_url = get_post_type_archive_link( 'lesson' );
384
			$my_courses_url = get_permalink( $my_account_page_id );
385
			$my_messages_url = get_post_type_archive_link( 'sensei_message' );
386
387
			switch ( $item->url ) {
388
				case '#senseicourses':
389
					$item->url = $course_page_url;
390
					break;
391
392
				case '#senseilessons':
393
					$item->url = $lesson_archive_url;
394
					break;
395
396
				case '#senseimycourses':
397
					$item->url = $my_courses_url;
398
					break;
399
400
				case '#senseimymessages':
401
					$item->url = $my_messages_url;
402
                    // if no archive link exist for sensei_message
403
                    // set it back to the place holder
404
                    if( ! $item->url ){
405
406
                        $item->url = '#senseimymessages';
407
408
                    }
409
					break;
410
411
				case '#senseilearnerprofile':
412
					$item->url = esc_url( Sensei()->learner_profiles->get_permalink() );
413
					break;
414
415
				case '#senseiloginlogout':
416
						$logout_url = wp_logout_url( home_url() );
417
						// Login link links to the My Courses page, to avoid the WP dashboard.
418
						$login_url = $my_courses_url;
419
420
						$item->url = ( is_user_logged_in() ? $logout_url : $login_url );
421
422
						// determine the menu title login or logout
423
						if ( is_user_logged_in() ) {
424
							$menu_title =  __( 'Logout'  ,'woothemes-sensei');
425
						} else {
426
							$menu_title =  __( 'Login'  ,'woothemes-sensei');
427
						}
428
429
						/**
430
						 * Action Filter: login/logout menu title
431
						 *
432
						 * With this filter you can alter the login / login menu item title string
433
						 *
434
						 * @param $menu_title
435
						 */
436
						$item->title = apply_filters( 'sensei_login_logout_menu_title', $menu_title );
437
438
					break;
439
440
				default:
441
					break;
442
			}
443
444
			$_root_relative_current = untrailingslashit( $_SERVER['REQUEST_URI'] );
445
			$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_root_relative_current );
446
			$item_url = untrailingslashit( $item->url );
447
			$_indexless_current = untrailingslashit( preg_replace( '/' . preg_quote( $wp_rewrite->index, '/' ) . '$/', '', $current_url ) );
448
			// Highlight current menu item
449
			if ( $item_url && in_array( $item_url, array( $current_url, $_indexless_current, $_root_relative_current ) ) ) {
450
				$item->classes[] = 'current-menu-item current_page_item';
451
			}
452
453
		} // endif nav
454
455
		return $item;
456
457
	} // End sensei_setup_nav_menu_item()
458
459
	/**
460
	 * sensei_wp_nav_menu_objects function.
461
	 *
462
	 * Remove Sensei custom menu items depending on settings and logged in status.
463
	 *
464
	 * @access public
465
	 * @param object $sorted_menu_items
466
	 * @return object $sorted_menu_items
467
	 */
468
	public function sensei_wp_nav_menu_objects( $sorted_menu_items ) {
469
470
		foreach( $sorted_menu_items as $k=>$item ) {
471
472
			// Remove the My Messages link for logged out users or if Private Messages are disabled
473 View Code Duplication
			if( ! get_post_type_archive_link( 'sensei_message' )
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
474
                && '#senseimymessages' == $item->url ) {
475
476
				if ( !is_user_logged_in() || ( isset( Sensei()->settings->settings['messages_disable'] ) && Sensei()->settings->settings['messages_disable'] ) ) {
477
478
					unset( $sorted_menu_items[$k] );
479
480
				}
481
			}
482
			// Remove the My Profile link for logged out users.
483 View Code Duplication
			if( Sensei()->learner_profiles->get_permalink() == $item->url ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
484
485
				if ( !is_user_logged_in() || ! ( isset( Sensei()->settings->settings[ 'learner_profile_enable' ] ) && Sensei()->settings->settings[ 'learner_profile_enable' ] ) ) {
486
487
					unset( $sorted_menu_items[$k] );
488
489
				}
490
			}
491
		}
492
		return $sorted_menu_items;
493
	} // End sensei_wp_nav_menu_objects
494
495
	// add category nicenames in body and post class
496
	function sensei_search_results_classes($classes) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
497
	    global $post;
498
	    // Handle Search Classes for Courses, Lessons, and WC Products
499
	    if ( isset( $post->post_type ) && ( ( 'course' == $post->post_type ) || ( 'lesson' == $post->post_type ) || ( 'product' == $post->post_type ) ) ) {
500
	    	$classes[] = 'post';
501
		} // End If Statement
502
	    return $classes;
503
	} // End sensei_search_results_classes()
504
505
    /**
506
     * sensei_single_title output for single page title
507
     * @since  1.1.0
508
     * @return void
509
     * @deprecate
510
     */
511
    function the_single_title() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
512
513
        _deprecated_function(' WooThemes_Sensei_Frontend::the_single_title', '1.9.0');
514
515
    } // End sensei_single_title()
516
517
	/**
518
	 * sensei_course_image output for course image Please use Sensei()->course->course_image instead.
519
     *
520
     * @deprecated since 1.9.0
521
     * @param $course_id
522
     * @param string $width
523
     * @param string $height
524
     * @param bool|false $return
525
     * @return string|void
526
	 */
527
	function sensei_course_image( $course_id, $width = '100', $height = '100', $return = false ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
528
529
        trigger_error( 'Sensei Deprecated function: sensei_course_image since 1.9.0 . Please use Sensei()->course->course_image instead.');
530
531
    	if ( ! $return ) {
532
533
			echo Sensei()->course->course_image( $course_id, $width, $height );
534
            return '';
535
536
		} // End If Statement
537
538
		return Sensei()->course->course_image( $course_id, $width, $height );
539
540
	} // End sensei_course_image()
541
542
	/**
543
	 * sensei_lesson_image output for lesson image
544
	 * @since  1.2.0
545
     * @deprecated since 1.9.0
546
     * @param $lesson_id
547
     * @param string $width
548
     * @param string $height
549
     * @param bool|false $return
550
     * @param bool|false $widget
551
     * @return string
552
	 */
553
	function sensei_lesson_image( $lesson_id, $width = '100', $height = '100', $return = false, $widget = false ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
554
555
        if( ! $return ){
556
557
            echo Sensei()->lesson->lesson_image( $lesson_id, $width, $height, $widget );
558
            return '';
559
        }
560
561
        return Sensei()->lesson->lesson_image( $lesson_id, $width, $height, $widget );
562
563
	} // End sensei_lesson_image()
564
565
    /**
566
     * @since 1.0.0
567
     * @param WP_Query $query
568
     */
569
    function sensei_course_archive_pagination( $query ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
570
571
		if( ! is_admin() && $query->is_main_query() && isset( $_GET['action'] ) && in_array( $_GET['action'], array( 'newcourses', 'featuredcourses', 'freecourses', 'paidcourses' ) ) ) {
572
573
			$amount = 0;
574
			if ( isset( Sensei()->settings->settings[ 'course_archive_amount' ] ) && ( 0 < absint( Sensei()->settings->settings[ 'course_archive_amount' ] ) ) ) {
575
				$amount = absint( Sensei()->settings->settings[ 'course_archive_amount' ] );
576
			}
577
578
			if( $amount ) {
579
				$query->set( 'posts_per_page', $amount );
580
			}
581
582
			$query->set( 'orderby', 'menu_order date' );
583
584
		}
585
	}
586
587
	/**
588
	 * sensei_course_archive_header function.
589
	 *
590
	 * @access public
591
	 * @since  1.2.0
592
     * @deprecated since 1.9.0 use WooThemes_Sensei_Course::archive_header
593
	 * @return void
594
	 */
595
	function sensei_course_archive_header(  ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
596
597
        trigger_error('This function sensei_course_archive_header has been depricated. Please use: WooThemes_Sensei_Course::course_archive_header ');
598
        WooThemes_Sensei_Course::archive_header( '', '<header class="archive-header"><h1>', '</h1></header>' );
599
600
	} // sensei_course_archive_header()
601
602
	/**
603
	 * sensei_lesson_archive_header function.
604
	 *
605
     * @deprecated since 1.9.0
606
	 * @access public
607
	 * @since  1.2.1
608
	 * @return void
609
	 */
610
	public function sensei_lesson_archive_header( ) {
611
        _deprecated_function( 'WooThemes_Sensei_Frontend::sensei_lesson_archive_header', '1.9.0', 'WooThemes_Sensei_Lesson::the_archive_header' );
612
        Sensei()->lesson->the_archive_header();
613
	} // sensei_course_archive_header()
614
615
    /**
616
     * @deprecated since 1.9.0
617
     */
618
	public function sensei_message_archive_header( ){
619
        _deprecated_function('Sensei_Frontend::sensei_message_archive_header','Please use: Sense');
620
        Sensei_Messages::the_archive_header();
621
	} // sensei_message_archive_header()
622
623
	/**
624
	 * sensei_course_archive_course_title output for course archive page individual course title
625
	 * @since  1.2.0
626
     * @param WP_Post $post_item
627
	 * @return void
628
	 */
629
	function sensei_course_archive_course_title( $post_item ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
630
		if ( isset( $post_item->ID ) && ( 0 < $post_item->ID ) ) {
631
			$post_id = absint( $post_item->ID );
632
    		$post_title = $post_item->post_title;
633
		} else {
634
			$post_id = get_the_ID();
635
    		$post_title = get_the_title();
636
		} // End If Statement
637
		?><header><h2><a href="<?php echo get_permalink( $post_id ); ?>" title="<?php echo esc_attr( $post_title ); ?>"><?php echo $post_title; ?></a></h2></header><?php
638
	} // End sensei_course_archive_course_title()
639
640
	/**
641
	 * sensei_lesson_archive_lesson_title output for course archive page individual course title
642
	 * @since  1.2.1
643
	 * @return void
644
	 */
645
	public function sensei_lesson_archive_lesson_title() {
646
		$post_id = get_the_ID();
647
    	$post_title = get_the_title();
648
		?><header><h2><a href="<?php echo get_permalink( $post_id ); ?>" title="<?php echo esc_attr( $post_title ); ?>"><?php echo $post_title; ?></a></h2></header><?php
649
	} // End sensei_lesson_archive_lesson_title()
650
651
	/**
652
	 * sensei_breadcrumb outputs Sensei breadcrumb trail on lesson & quiz pages
653
	 * @since  1.7.0
654
	 * @param  integer $id course, lesson or quiz id
655
	 * @return void
656
	 */
657
	public function sensei_breadcrumb( $id = 0 ) {
658
659
		// Only output on lesson, quiz and taxonomy (module) pages
660
		if( ! ( is_tax( 'module' ) || is_singular( 'lesson' ) || is_singular( 'quiz' ) ) ) return;
661
662
		if( empty( $id )  ){
663
664
            $id = get_the_ID();
665
666
        }
667
668
		$sensei_breadcrumb_prefix = __( 'Back to: ', 'woothemes-sensei' );
669
		$separator = apply_filters( 'sensei_breadcrumb_separator', '&gt;' );
670
671
		$html = '<section class="sensei-breadcrumb">' . $sensei_breadcrumb_prefix;
672
		// Lesson
673 View Code Duplication
		if ( is_singular( 'lesson' ) && 0 < intval( $id ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
674
			$course_id = intval( get_post_meta( $id, '_lesson_course', true ) );
675
			if( ! $course_id ) {
676
				return;
677
			}
678
			$html .= '<a href="' . esc_url( get_permalink( $course_id ) ) . '" title="' . __( 'Back to the course', 'woothemes-sensei' ) . '">' . get_the_title( $course_id ) . '</a>';
679
    	} // End If Statement
680
    	// Quiz
681 View Code Duplication
		if ( is_singular( 'quiz' ) && 0 < intval( $id ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
682
			$lesson_id = intval( get_post_meta( $id, '_quiz_lesson', true ) );
683
			if( ! $lesson_id ) {
684
				return;
685
			}
686
			 $html .= '<a href="' . esc_url( get_permalink( $lesson_id ) ) . '" title="' .  __( 'Back to the lesson', 'woothemes-sensei' ) . '">' . get_the_title( $lesson_id ) . '</a>';
687
    	} // End If Statement
688
689
    	// Allow other plugins to filter html
690
    	$html = apply_filters ( 'sensei_breadcrumb_output', $html, $separator );
691
    	$html .= '</section>';
692
693
    	echo $html;
694
	} // End sensei_breadcrumb()
695
696
697
    /**
698
     * @deprecated since 1.9.0 use WooThemes_Sensei_Lesson::course_signup_link instead
699
     */
700
	public function sensei_lesson_course_signup_link( ) {
701
702
        _deprecated_function('sensei_lesson_course_signup_link', '1.9.0', 'WooThemes_Sensei_Lesson::course_signup_link' );
703
        WooThemes_Sensei_Lesson::course_signup_link();
704
	}
705
706
	public function lesson_tags_display( $lesson_id = 0 ) {
707
		if( $lesson_id ) {
708
			$tags = wp_get_post_terms( $lesson_id, 'lesson-tag' );
709
			if( $tags && count( $tags ) > 0 ) {
710
				$tag_list = '';
711
				foreach( $tags as $tag ) {
712
					$tag_link = get_term_link( $tag, 'lesson-tag' );
713
					if( ! is_wp_error( $tag_link ) ) {
714
						if( $tag_list ) { $tag_list .= ', '; }
715
						$tag_list .= '<a href="' . $tag_link . '">' . $tag->name . '</a>';
716
					}
717
				}
718
				if( $tag_list ) {
719
					?><section class="lesson-tags">
720
		    			<?php printf( __( 'Lesson tags: %1$s', 'woothemes-sensei' ), $tag_list ); ?>
721
		    		</section><?php
722
		    	}
723
	    	}
724
		}
725
	}
726
727
    /**
728
     * @param WP_Query $query
729
     */
730
	public function lesson_tag_archive_filter( $query ) {
731
    	if( is_tax( 'lesson-tag' ) && $query->is_main_query() ) {
732
    		// Limit to lessons only
733
    		$query->set( 'post_type', 'lesson' );
734
735
    		// Set order of lessons
736
    		$query->set( 'orderby', 'menu_order' );
737
    		$query->set( 'order', 'ASC' );
738
739
    	}
740
    }
741
742
    public function lesson_tag_archive_header( $title ) {
743
		if( is_tax( 'lesson-tag' ) ) {
744
			$title = sprintf( __( 'Lesson tag: %1$s', 'woothemes-sensei' ), apply_filters( 'sensei_lesson_tag_archive_title', get_queried_object()->name ) );
745
		}
746
		return $title;
747
	}
748
749
	public function lesson_tag_archive_description() {
750
		if( is_tax( 'lesson-tag' ) ) {
751
			$tag = get_queried_object();
752
			echo '<p class="archive-description lesson-description">' . apply_filters( 'sensei_lesson_tag_archive_description', nl2br( $tag->description ), $tag->term_id ) . '</p>';
753
		}
754
	}
755
756
	public function sensei_complete_lesson() {
757
		global $post,  $current_user;
758
		// Handle Quiz Completion
759
		if ( isset( $_POST['quiz_action'] ) && wp_verify_nonce( $_POST[ 'woothemes_sensei_complete_lesson_noonce' ], 'woothemes_sensei_complete_lesson_noonce' ) ) {
760
761
			$sanitized_submit = esc_html( $_POST['quiz_action'] );
762
763
			switch ($sanitized_submit) {
764
                case 'lesson-complete':
765
766
					Sensei_Utils::sensei_start_lesson( $post->ID, $current_user->ID, $complete = true );
767
768
					break;
769
770
                case 'lesson-reset':
771
772
					Sensei_Utils::sensei_remove_user_from_lesson( $post->ID, $current_user->ID );
773
774
					$this->messages = '<div class="sensei-message note">' .  __( 'Lesson Reset Successfully.', 'woothemes-sensei' ) . '</div>';
775
					break;
776
777
				default:
778
					// Nothing
779
					break;
780
781
			} // End Switch Statement
782
783
		} // End If Statement
784
785
	} // End sensei_complete_lesson()
786
787
	public function sensei_complete_course() {
788
		global $post,  $current_user, $wp_query;
789
		if ( isset( $_POST['course_complete'] ) && wp_verify_nonce( $_POST[ 'woothemes_sensei_complete_course_noonce' ], 'woothemes_sensei_complete_course_noonce' ) ) {
790
791
			$sanitized_submit = esc_html( $_POST['course_complete'] );
792
			$sanitized_course_id = absint( esc_html( $_POST['course_complete_id'] ) );
793
			// Handle submit data
794
			switch ($sanitized_submit) {
795
				case __( 'Mark as Complete', 'woothemes-sensei' ):
796
797
					// Add user to course
798
					$course_metadata = array(
799
						'start' => current_time('mysql'),
800
						'percent' => 0, // No completed lessons yet
801
						'complete' => 0,
802
					);
803
					$activity_logged = Sensei_Utils::update_course_status( $current_user->ID, $sanitized_course_id, 'in-progress', $course_metadata );
804
805
					if ( $activity_logged ) {
806
						// Get all course lessons
807
						$course_lesson_ids = Sensei()->course->course_lessons( $sanitized_course_id, 'any', 'ids' );
808
						// Mark all quiz user meta lessons as complete
809
						foreach ( $course_lesson_ids as $lesson_item_id ){
810
							// Mark lesson as complete
811
							$activity_logged = Sensei_Utils::sensei_start_lesson( $lesson_item_id, $current_user->ID, $complete = true );
0 ignored issues
show
Unused Code introduced by
$activity_logged is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
812
						} // End For Loop
813
814
						// Update with final stats
815
						$course_metadata = array(
816
							'percent' => 100,
817
							'complete' => count($course_lesson_ids),
818
						);
819
						$activity_logged = Sensei_Utils::update_course_status( $current_user->ID, $sanitized_course_id, 'complete', $course_metadata );
0 ignored issues
show
Unused Code introduced by
$activity_logged is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
820
821
						do_action( 'sensei_user_course_end', $current_user->ID, $sanitized_course_id );
822
823
						// Success message
824
						$this->messages = '<header class="archive-header"><div class="sensei-message tick">' . sprintf( __( '%1$s marked as complete.', 'woothemes-sensei' ), get_the_title( $sanitized_course_id ) ) . '</div></header>';
825
					} // End If Statement
826
827
					break;
828
829
				case __( 'Delete Course', 'woothemes-sensei' ):
830
831
					Sensei_Utils::sensei_remove_user_from_course( $sanitized_course_id, $current_user->ID );
832
833
					// Success message
834
					$this->messages = '<header class="archive-header"><div class="sensei-message tick">' . sprintf( __( '%1$s deleted.', 'woothemes-sensei' ), get_the_title( $sanitized_course_id ) ) . '</div></header>';
835
					break;
836
837
				default:
838
					// Nothing
839
					break;
840
			} // End Switch Statement
841
842
		} // End If Statement
843
	} // End sensei_complete_course()
844
845
	/**
846
	 * @deprecated use WooThemes_Sensei_Quiz::get_user_answers
847
	 * @param int $lesson_id
848
	 * @return array
849
	 */
850
	public function sensei_get_user_quiz_answers( $lesson_id = 0 ) {
851
		global $current_user;
852
853
		$user_answers = array();
854
855
		if ( 0 < intval( $lesson_id ) ) {
856
			$lesson_quiz_questions = Sensei()->lesson->lesson_quiz_questions( $lesson_id );
857
			foreach( $lesson_quiz_questions as $question ) {
858
				$answer = maybe_unserialize( base64_decode( Sensei_Utils::sensei_get_activity_value( array( 'post_id' => $question->ID, 'user_id' => $current_user->ID, 'type' => 'sensei_user_answer', 'field' => 'comment_content' ) ) ) );
859
				$user_answers[ $question->ID ] = $answer;
860
			}
861
		}
862
863
		return $user_answers;
864
	} // End sensei_get_user_quiz_answers()
865
866
	public function sensei_has_user_completed_lesson( $post_id = 0, $user_id = 0 ) {
867
		_deprecated_function( __FUNCTION__, '1.7', "WooThemes_Sensei_Utils::user_completed_lesson()" );
868
		return Sensei_Utils::user_completed_lesson( $post_id, $user_id );
869
	} // End sensei_has_user_completed_lesson()
870
871
/**
872
*
873
 */
874
	public function sensei_frontend_messages() {
875
		Sensei()->notices->print_notices();
876
	} // End sensei_frontend_messages()
877
878
	public function sensei_lesson_video( $post_id = 0 ) {
879
		if ( 0 < intval( $post_id ) ) {
880
			$lesson_video_embed = get_post_meta( $post_id, '_lesson_video_embed', true );
881
			if ( 'http' == substr( $lesson_video_embed, 0, 4) ) {
882
        		// V2 - make width and height a setting for video embed
883
        		$lesson_video_embed = wp_oembed_get( esc_url( $lesson_video_embed )/*, array( 'width' => 100 , 'height' => 100)*/ );
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
884
        	} // End If Statement
885
        	if ( '' != $lesson_video_embed ) {
886
        	?><div class="video"><?php echo html_entity_decode($lesson_video_embed); ?></div><?php
887
        	} // End If Statement
888
        } // End If Statement
889
	} // End sensei_lesson_video()
890
891
	public function sensei_complete_lesson_button() {
892
		global  $post;
893
894
		$quiz_id = 0;
0 ignored issues
show
Unused Code introduced by
$quiz_id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
895
896
		// Lesson quizzes
897
		$quiz_id = Sensei()->lesson->lesson_quizzes( $post->ID );
898
		$pass_required = true;
899
		if( $quiz_id ) {
900
			// Get quiz pass setting
901
	    	$pass_required = get_post_meta( $quiz_id, '_pass_required', true );
902
	    }
903
		if( ! $quiz_id || ( $quiz_id && ! $pass_required ) ) {
904
			?>
905
			<form class="lesson_button_form" method="POST" action="<?php echo esc_url( get_permalink() ); ?>">
906
	            <input type="hidden"
907
                       name="woothemes_sensei_complete_lesson_noonce"
908
                       id="woothemes_sensei_complete_lesson_noonce"
909
                       value="<?php echo esc_attr( wp_create_nonce( 'woothemes_sensei_complete_lesson_noonce' ) ); ?>"
910
                />
911
912
	            <input type="hidden" name="quiz_action" value="lesson-complete" />
913
914
                <input type="submit"
915
                       name="quiz_complete"
916
                       class="quiz-submit complete"
917
                       value="<?php _e( 'Complete Lesson', 'woothemes-sensei' ); ?>"/>
918
919
	        </form>
920
			<?php
921
		} // End If Statement
922
	} // End sensei_complete_lesson_button()
923
924
	public function sensei_reset_lesson_button() {
925
		global  $post;
926
927
		$quiz_id = 0;
0 ignored issues
show
Unused Code introduced by
$quiz_id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
928
929
		// Lesson quizzes
930
		$quiz_id = Sensei()->lesson->lesson_quizzes( $post->ID );
931
		$reset_allowed = true;
932
		if( $quiz_id ) {
933
			// Get quiz pass setting
934
			$reset_allowed = get_post_meta( $quiz_id, '_enable_quiz_reset', true );
935
		}
936
		if ( ! $quiz_id || !empty($reset_allowed) ) {
937
		?>
938
		<form method="POST" action="<?php echo esc_url( get_permalink() ); ?>">
939
940
            <input
941
            type="hidden"
942
            name="<?php echo esc_attr( 'woothemes_sensei_complete_lesson_noonce' ); ?>"
943
            id="<?php echo esc_attr( 'woothemes_sensei_complete_lesson_noonce' ); ?>"
944
            value="<?php echo esc_attr( wp_create_nonce( 'woothemes_sensei_complete_lesson_noonce' ) ); ?>" />
945
946
            <input type="hidden" name="quiz_action" value="lesson-reset" />
947
948
            <input type="submit" name="quiz_complete" class="quiz-submit reset" value="<?php _e( 'Reset Lesson', 'woothemes-sensei' ); ?>"/>
949
950
        </form>
951
		<?php
952
		} // End If Statement
953
	} // End sensei_reset_lesson_button()
954
955
    /**
956
     * @deprecated since 1.9.0
957
     */
958
    public function sensei_lesson_quiz_meta( ) {
959
960
        Sensei_Lesson::footer_quiz_call_to_action();
961
962
	} // End sensei_lesson_quiz_meta()
963
964
	public function sensei_course_archive_meta() {
965
		global  $post;
966
		// Meta data
967
		$post_id = get_the_ID();
968
		$post_title = get_the_title();
0 ignored issues
show
Unused Code introduced by
$post_title is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
969
		$author_display_name = get_the_author();
0 ignored issues
show
Unused Code introduced by
$author_display_name is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
970
		$author_id = get_the_author_meta('ID');
0 ignored issues
show
Unused Code introduced by
$author_id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
971
		$category_output = get_the_term_list( $post_id, 'course-category', '', ', ', '' );
972
		$free_lesson_count = intval( Sensei()->course->course_lesson_preview_count( $post_id ) );
973
		?><section class="entry">
974
        	<p class="sensei-course-meta">
975 View Code Duplication
           	<?php if ( isset( Sensei()->settings->settings[ 'course_author' ] ) && ( Sensei()->settings->settings[ 'course_author' ] ) ) { ?>
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
976
		   	<span class="course-author"><?php _e( 'by ', 'woothemes-sensei' ); ?><?php the_author_link(); ?></span>
977
		   	<?php } // End If Statement ?>
978
		   	<span class="course-lesson-count"><?php echo Sensei()->course->course_lesson_count( $post_id ) . '&nbsp;' . __( 'Lessons', 'woothemes-sensei' ); ?></span>
979
		   	<?php if ( '' != $category_output ) { ?>
980
		   	<span class="course-category"><?php echo sprintf( __( 'in %s', 'woothemes-sensei' ), $category_output ); ?></span>
981
		   	<?php } // End If Statement ?>
982
		   	<?php sensei_simple_course_price( $post_id ); ?>
983
        	</p>
984
        	<p class="course-excerpt"><?php the_excerpt(); ?></p>
985 View Code Duplication
        	<?php if ( 0 < $free_lesson_count ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
986
                $free_lessons = sprintf( __( 'You can access %d of this course\'s lessons for free', 'woothemes-sensei' ), $free_lesson_count ); ?>
987
                <p class="sensei-free-lessons"><a href="<?php echo get_permalink( $post_id ); ?>"><?php _e( 'Preview this course', 'woothemes-sensei' ) ?></a> - <?php echo $free_lessons; ?></p>
988
            <?php } ?>
989
		</section><?php
990
	} // End sensei_course_archive_meta()
991
992
    /**
993
     * @deprecated since 1.9.0
994
     */
995
	public function sensei_single_main_content() {
996
	    _deprecated_function('Woothemes_Sensei_Frontend::sensei_single_main_content', '1.9.0');
997
	} // End sensei_single_main_content()
998
999
    /**
1000
    * @deprecated since 1.9.0
1001
    */
1002
	public function sensei_lesson_archive_main_content() {
1003
        _deprecated_function('Sensei_Frontend::sensei_lesson_archive_main_content', '1.9.0', 'Please include loop-lesson.php directly');
1004
	} // End sensei_lesson_archive_main_content()
1005
1006
    /**
1007
    * @deprecated since 1.9.0
1008
    */
1009
	public function sensei_message_archive_main_content() {
1010
		_deprecated_function( 'Sensei_Frontend::sensei_message_archive_main_content', 'This method is no longer needed' );
1011
	} // End sensei_lesson_archive_main_content()
1012
1013
    /**
1014
    * @deprecated since 1.9.0
1015
    */
1016
	public function sensei_no_permissions_main_content() {
1017
        _deprecated_function( 'Sensei_Frontend::sensei_no_permissions_main_content', 'This method is no longer needed' );
1018
	} // End sensei_no_permissions_main_content()
1019
1020
	public function sensei_course_category_main_content() {
1021
		global $post;
1022
		if ( have_posts() ) { ?>
1023
1024
			<section id="main-course" class="course-container">
1025
1026
                <?php do_action( 'sensei_course_archive_header' ); ?>
1027
1028
                <?php while ( have_posts() ) { the_post(); ?>
1029
1030
                    <article class="<?php echo join( ' ', get_post_class( array( 'course', 'post' ), get_the_ID() ) ); ?>">
1031
1032
	    			    <?php do_action( 'sensei_course_image', get_the_ID() ); ?>
1033
1034
	    			    <?php do_action( 'sensei_course_archive_course_title', $post ); ?>
1035
1036
	    			    <?php do_action( 'sensei_course_archive_meta' ); ?>
1037
1038
	    		    </article>
1039
1040
                <?php } // End While Loop ?>
1041
1042
	    	</section>
1043
1044
		<?php } else { ?>
1045
1046
			<p>
1047
1048
                <?php _e( 'No courses found that match your selection.', 'woothemes-sensei' ); ?>
1049
1050
            </p>
1051
1052
		<?php } // End If Statement
1053
1054
	} // End sensei_course_category_main_content()
1055
1056
	public function sensei_login_form() {
1057
		?>
1058
		<div id="my-courses">
1059
			<?php Sensei()->notices->print_notices(); ?>
1060
			<div class="col2-set" id="customer_login">
1061
1062
				<div class="col-1">
1063
					<?php
1064
					// output the actual form markup
1065
                    Sensei_Templates::get_template( 'user/login-form.php');
1066
					?>
1067
				</div>
1068
1069
			<?php
1070
			if ( get_option('users_can_register') ) {
1071
1072
				// get current url
1073
				$action_url = get_permalink();
1074
1075
				?>
1076
1077
				<div class="col-2">
1078
					<h2><?php _e( 'Register', 'woothemes-sensei' ); ?></h2>
1079
1080
					<form method="post" class="register"  action="<?php echo esc_url( $action_url ); ?>" >
1081
1082
						<?php do_action( 'sensei_register_form_start' ); ?>
1083
1084
						<p class="form-row form-row-wide">
1085
							<label for="sensei_reg_username"><?php _e( 'Username', 'woothemes-sensei' ); ?> <span class="required">*</span></label>
1086
							<input type="text" class="input-text" name="sensei_reg_username" id="sensei_reg_username" value="<?php if ( ! empty( $_POST['sensei_reg_username'] ) ) esc_attr_e( $_POST['sensei_reg_username'] ); ?>" />
1087
						</p>
1088
1089
						<p class="form-row form-row-wide">
1090
							<label for="sensei_reg_email"><?php _e( 'Email address', 'woothemes-sensei' ); ?> <span class="required">*</span></label>
1091
							<input type="email" class="input-text" name="sensei_reg_email" id="sensei_reg_email" value="<?php if ( ! empty( $_POST['sensei_reg_email'] ) ) esc_attr_e( $_POST['sensei_reg_email'] ); ?>" />
1092
						</p>
1093
1094
						<p class="form-row form-row-wide">
1095
							<label for="sensei_reg_password"><?php _e( 'Password', 'woothemes-sensei' ); ?> <span class="required">*</span></label>
1096
							<input type="password" class="input-text" name="sensei_reg_password" id="sensei_reg_password" value="<?php if ( ! empty( $_POST['sensei_reg_password'] ) ) esc_attr_e( $_POST['sensei_reg_password'] ); ?>" />
1097
						</p>
1098
1099
						<!-- Spam Trap -->
1100
						<div style="left:-999em; position:absolute;"><label for="trap"><?php _e( 'Anti-spam', 'woothemes-sensei' ); ?></label><input type="text" name="email_2" id="trap" tabindex="-1" /></div>
1101
1102
						<?php do_action( 'sensei_register_form_fields' ); ?>
1103
						<?php do_action( 'register_form' ); ?>
1104
1105
						<p class="form-row">
1106
							<input type="submit" class="button" name="register" value="<?php _e( 'Register', 'woothemes-sensei' ); ?>" />
1107
						</p>
1108
1109
						<?php do_action( 'sensei_register_form_end' ); ?>
1110
1111
					</form>
1112
				</div>
1113
				<?php
1114
			}
1115
			?>
1116
			</div>
1117
		</div>
1118
1119
		<?php
1120
	} // End sensei_login_form()
1121
1122
	public function sensei_lesson_meta( $post_id = 0 ) {
1123
		global $post;
1124
		if ( 0 < intval( $post_id ) ) {
1125
		$lesson_course_id = absint( get_post_meta( $post_id, '_lesson_course', true ) );
1126
		?><section class="entry">
1127
            <p class="sensei-course-meta">
1128 View Code Duplication
			    <?php if ( isset( Sensei()->settings->settings[ 'lesson_author' ] ) && ( Sensei()->settings->settings[ 'lesson_author' ] ) ) { ?>
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1129
			    <span class="course-author"><?php _e( 'by ', 'woothemes-sensei' ); ?><?php the_author_link(); ?></span>
1130
			    <?php } ?>
1131
                <?php if ( 0 < intval( $lesson_course_id ) ) { ?>
1132
                <span class="lesson-course"><?php echo '&nbsp;' . sprintf( __( 'Part of: %s', 'woothemes-sensei' ), '<a href="' . esc_url( get_permalink( $lesson_course_id ) ) . '" title="' . __( 'View course', 'woothemes-sensei' ) . '"><em>' . get_the_title( $lesson_course_id ) . '</em></a>' ); ?></span>
1133
                <?php } ?>
1134
            </p>
1135
            <p class="lesson-excerpt"><?php the_excerpt( ); ?></p>
1136
		</section><?php
1137
		} // End If Statement
1138
	} // sensei_lesson_meta()
1139
1140
	public function sensei_lesson_preview_title_text( $course_id ) {
1141
1142
		$preview_text = __( ' (Preview)', 'woothemes-sensei' );
1143
1144
		//if this is a paid course
1145
		if ( Sensei_WC::is_woocommerce_active() ) {
1146
    	    $wc_post_id = get_post_meta( $course_id, '_course_woocommerce_product', true );
1147
    	    if ( 0 < $wc_post_id ) {
1148
    	    	$preview_text = __( ' (Free Preview)', 'woothemes-sensei' );
1149
    	    } // End If Statement
1150
    	}
1151
    	return $preview_text;
1152
	}
1153
1154
	public function sensei_lesson_preview_title( $title = '', $id = 0 ) {
1155
		global $post, $current_user;
1156
1157
		// Limit to lessons and check if lesson ID matches filtered post ID
1158
		// @see https://github.com/woothemes/sensei/issues/574
1159
		if( isset( $post->ID ) && $id == $post->ID && 'lesson' == get_post_type( $post ) ) {
1160
1161
			// Limit to main query only
1162
			if( is_main_query() ) {
1163
1164
				// Get the course ID
1165
				$course_id = get_post_meta( $post->ID, '_lesson_course', true );
1166
1167
				// Check if the user is taking the course
1168
				if( is_singular( 'lesson' ) && Sensei_Utils::is_preview_lesson( $post->ID ) && ! Sensei_Utils::user_started_course( $course_id, $current_user->ID ) && $post->ID == $id ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression \Sensei_Utils::user_star..._id, $current_user->ID) of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1169
					$title .= ' ' . $this->sensei_lesson_preview_title_text( $course_id );
1170
				}
1171
			}
1172
		}
1173
		return $title;
1174
	} // sensei_lesson_preview_title
1175
1176
	public function sensei_course_start() {
1177
		global $post, $current_user;
1178
1179
		// Check if the user is taking the course
1180
		$is_user_taking_course = Sensei_Utils::user_started_course( $post->ID, $current_user->ID );
1181
		// Handle user starting the course
1182
		if ( isset( $_POST['course_start'] )
1183
		    && wp_verify_nonce( $_POST[ 'woothemes_sensei_start_course_noonce' ], 'woothemes_sensei_start_course_noonce' )
1184
		    && !$is_user_taking_course ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $is_user_taking_course of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1185
1186
			// Start the course
1187
			$activity_logged = Sensei_Utils::user_start_course( $current_user->ID, $post->ID );
1188
			$this->data = new stdClass();
1189
			$this->data->is_user_taking_course = false;
1190
			if ( $activity_logged ) {
1191
				$this->data->is_user_taking_course = true;
1192
1193
				// Refresh page to avoid re-posting
1194
				?>
1195
1196
			    <script type="text/javascript"> window.location = '<?php echo get_permalink( $post->ID ); ?>'; </script>
1197
1198
			    <?php
1199
			} // End If Statement
1200
		} // End If Statement
1201
	} // End sensei_course_start()
1202
1203
    /**
1204
     * @deprecated since 1.9.0
1205
     */
1206
	public function sensei_course_meta() {
1207
        _deprecated_function( 'Sensei_Frontend::sensei_course_meta', '1.9.0' , 'Sensei_Course::the_course_meta()' );
1208
        Sensei()->course->the_course_meta( get_post() );
1209
	} // End sensei_course_meta()
1210
1211
    /**
1212
     * @deprecated since 1.9.0
1213
     */
1214
	public function sensei_course_meta_video() {
1215
        _deprecated_function( 'Sensei_Frontend::sensei_course_meta_video', '1.9.0' , 'Sensei_Course::the_course_video()' );
1216
        Sensei_Course::the_course_video();
1217
	} // End sensei_course_meta_video()
1218
1219
    /**
1220
     * This function shows the WooCommerce cart notice if the user has
1221
     * added the current course to cart. It does not show if the user is already taking
1222
     * the course.
1223
     *
1224
     * @since 1.0.2
1225
     * @return void;
0 ignored issues
show
Documentation introduced by
The doc-type void; could not be parsed: Expected "|" or "end of type", but got ";" at position 4. (view supported doc-types)

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.

Loading history...
1226
     */
1227
    public function sensei_woocommerce_in_cart_message() {
1228
		global $post, $woocommerce;
1229
1230
		$wc_post_id = absint( get_post_meta( $post->ID, '_course_woocommerce_product', true ) );
1231
        $user_course_status_id = Sensei_Utils::user_started_course($post->ID , get_current_user_id() );
1232
		if ( 0 < intval( $wc_post_id ) && ! $user_course_status_id ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $user_course_status_id of type false|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1233
1234
			if ( Sensei_WC::is_product_in_cart( $wc_post_id ) ) {
1235
				echo '<div class="sensei-message info">' . sprintf(  __('You have already added this Course to your cart. Please %1$s to access the course.', 'woothemes-sensei') . '</div>', '<a class="cart-complete" href="' . $woocommerce->cart->get_checkout_url() . '" title="' . __('complete the purchase', 'woothemes-sensei') . '">' . __('complete the purchase', 'woothemes-sensei') . '</a>' );
1236
			} // End If Statement
1237
1238
		} // End If Statement
1239
1240
	} // End sensei_woocommerce_in_cart_message()
1241
1242
	// Deprecated
1243
	public function sensei_lesson_comment_count( $count ) {
1244
		return $count;
1245
	} // End sensei_lesson_comment_count()
1246
1247
	/**
1248
	 * Only show excerpts for lessons and courses in search results
1249
	 * @param  string $content Original content
1250
	 * @return string          Modified content
1251
	 */
1252
	public function sensei_search_results_excerpt( $content ) {
1253
		global $post;
1254
1255
		if( is_search() && in_array( $post->post_type, array( 'course', 'lesson' ) ) ) {
1256
			$content = '<p class="course-excerpt">' . the_excerpt( ) . '</p>';
1257
		}
1258
1259
		return $content;
1260
	} // End sensei_search_results_excerpt()
1261
1262
	/**
1263
	 * Remove active course when an order is refunded or cancelled
1264
	 * @param  integer $order_id ID of order
1265
	 * @return void
1266
	 */
1267
	public function remove_active_course( $order_id ) {
1268
		$order = new WC_Order( $order_id );
1269
1270
		foreach ( $order->get_items() as $item ) {
1271
			if ( isset( $item['variation_id'] ) && ( 0 < $item['variation_id'] ) ) {
1272
				// If item has variation_id then its a variation of the product
1273
				$item_id = $item['variation_id'];
1274
			} else {
1275
				// Than its real product set it's id to item_id
1276
				$item_id = $item['product_id'];
1277
			} 
1278
1279
            if ( $item_id > 0 ) {
1280
1281
				$user_id = get_post_meta( $order_id, '_customer_user', true );
1282
1283
				if( $user_id ) {
1284
1285
					// Get all courses for product
1286
					$args = array(
1287
						'posts_per_page' => -1,
1288
						'post_type' => 'course',
1289
						'meta_query' => array(
1290
							array(
1291
								'key' => '_course_woocommerce_product',
1292
								'value' => $item_id
1293
							)
1294
						),
1295
						'orderby' => 'menu_order date',
1296
						'order' => 'ASC',
1297
						'fields' => 'ids',
1298
					);
1299
					$course_ids = get_posts( $args );
1300
1301
					if( $course_ids && count( $course_ids ) > 0 ) {
1302
						foreach( $course_ids as $course_id ) {
1303
1304
							// Remove all course user meta
1305
							Sensei_Utils::sensei_remove_user_from_course( $course_id, $user_id );
1306
1307
						} // End For Loop
1308
					} // End If Statement
1309
				} // End If Statement
1310
			} // End If Statement
1311
		} // End For Loop
1312
	} // End remove_active_course()
1313
1314
1315
	/**
1316
	 * Activate all purchased courses for user
1317
	 * @since  1.4.8
1318
	 * @param  integer $user_id User ID
1319
	 * @return void
1320
	 */
1321
	public function activate_purchased_courses( $user_id = 0 ) {
1322
1323
		if( $user_id ) {
1324
1325
			if( Sensei_WC::is_woocommerce_active() ) {
1326
1327
				// Get all user's orders
1328
				$order_args = array(
1329
					'post_type' => 'shop_order',
1330
					'post_status' =>  array( 'wc-processing', 'wc-completed' ),
1331
					'posts_per_page' => -1,
1332
					'meta_query' => array(
1333
						array(
1334
							'key' => '_customer_user',
1335
							'value' => $user_id
1336
						)
1337
					),
1338
				);
1339
1340
				$orders = get_posts( $order_args );
1341
1342
				$product_ids = array();
1343
				$order_ids = array();
1344
1345
				foreach( $orders as $post_id ) {
1346
1347
					// Only process each order once
1348
					$processed = get_post_meta( $post_id, 'sensei_products_processed', true );
1349
1350
					if( $processed && $processed == 'processed' ) {
1351
						continue;
1352
					}
1353
1354
					// Get course product IDs from order
1355
					$order = new WC_Order( $post_id );
1356
1357
					$items = $order->get_items();
1358
					foreach( $items as $item ) {
1359
                                            if (isset($item['variation_id']) && $item['variation_id'] > 0) {
1360
                                                $item_id = $item['variation_id'];
1361
                                                $product_type = 'variation';
0 ignored issues
show
Unused Code introduced by
$product_type is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1362
                                            } else {
1363
                                                $item_id = $item['product_id'];
1364
                                            }
1365
1366
                                            $product_ids[] = $item_id;
1367
                                            }
1368
1369
					$order_ids[] = $post_id;
1370
				}
1371
1372
				if( count( $product_ids ) > 0 ) {
1373
1374
					// Get all courses from user's orders
1375
					$course_args = array(
1376
						'post_type' => 'course',
1377
						'posts_per_page' => -1,
1378
						'meta_query' => array(
1379
							array(
1380
								'key' => '_course_woocommerce_product',
1381
								'value' => $product_ids,
1382
								'compare' => 'IN'
1383
							)
1384
						),
1385
						'orderby' => 'menu_order date',
1386
						'order' => 'ASC',
1387
						'fields' => 'ids',
1388
					);
1389
					$course_ids = get_posts( $course_args );
1390
1391
					foreach( $course_ids as $course_id ) {
1392
1393
						$user_course_status = Sensei_Utils::user_course_status( intval($course_id), $user_id );
1394
1395
						// Ignore course if already completed
1396
						if( Sensei_Utils::user_completed_course( $user_course_status ) ) {
1397
							continue;
1398
						}
1399
1400
						// Ignore course if already started
1401
						if( $user_course_status ) {
1402
							continue;
1403
						}
1404
1405
						// Mark course as started by user
1406
						Sensei_Utils::user_start_course( $user_id, $course_id );
1407
					}
1408
				}
1409
1410
				if( count( $order_ids ) > 0 ) {
1411
					foreach( $order_ids as $order_id ) {
1412
						// Mark order as processed
1413
						update_post_meta( $order_id, 'sensei_products_processed', 'processed' );
1414
					}
1415
				}
1416
			}
1417
		}
1418
	} // End activate_purchased_courses()
1419
1420
	/**
1421
	 * Activate single course if already purchases
1422
	 * @return void
1423
	 */
1424
	public function activate_purchased_single_course() {
1425
		global $post, $current_user;
1426
1427
		if( Sensei_WC::is_woocommerce_active() ) {
1428
1429
			if( ! is_user_logged_in() ) return;
1430
			if( ! isset( $post->ID ) ) return;
1431
1432
			$user_id = $current_user->ID;
1433
			$course_id = $post->ID;
1434
			$course_product_id = (int) get_post_meta( $course_id, '_course_woocommerce_product', true );
1435
			if( ! $course_product_id ) {
1436
				return;
1437
			}
1438
1439
			$user_course_status = Sensei_Utils::user_course_status( intval($course_id), $user_id );
1440
1441
			// Ignore course if already completed
1442
			if( Sensei_Utils::user_completed_course( $user_course_status ) ) {
1443
1444
				return;
1445
			}
1446
1447
			// Ignore course if already started
1448
			if( $user_course_status ) {
1449
				return;
1450
			}
1451
1452
			// Get all user's orders
1453
			$order_args = array(
1454
				'post_type' => 'shop_order',
1455
				'posts_per_page' => -1,
1456
				'post_status' => array( 'wc-processing', 'wc-completed' ),
1457
				'meta_query' => array(
1458
					array(
1459
						'key' => '_customer_user',
1460
						'value' => $user_id
1461
					)
1462
				),
1463
				'fields' => 'ids',
1464
			);
1465
			$orders = get_posts( $order_args );
1466
1467
			foreach( $orders as $order_post_id ) {
1468
1469
				// Get course product IDs from order
1470
				$order = new WC_Order( $order_post_id );
1471
1472
				$items = $order->get_items();
1473
				foreach( $items as $item ) {
1474
                    $product = wc_get_product( $item['product_id'] );
1475
1476
                    // handle product bundles
1477
                    if( $product->is_type('bundle') ){
1478
1479
                        $bundled_product = new WC_Product_Bundle( $product->id );
1480
                        $bundled_items = $bundled_product->get_bundled_items();
1481
1482
                        foreach( $bundled_items as $bundled_item ){
1483
1484
                            if( $bundled_item->product_id == $course_product_id ) {
1485
                                Sensei_Utils::user_start_course( $user_id, $course_id );
1486
                                return;
1487
                            }
1488
1489
                        }
1490
1491
                    } else {
1492
1493
                    // handle regular products
1494
                        if( $item['product_id'] == $course_product_id ) {
1495
                            Sensei_Utils::user_start_course( $user_id, $course_id );
1496
                            return;
1497
                        }
1498
1499
                    }
1500
				}
1501
			}
1502
1503
		}
1504
	} // End activate_purchased_single_course()
1505
1506
	/**
1507
	 * Hide Sensei activity comments from frontend (requires WordPress 4.0+)
1508
	 * @param  array  $args Default arguments
1509
	 * @return array        Modified arguments
1510
	 */
1511
	public function hide_sensei_activity( $args = array() ) {
1512
1513
		if( is_singular( 'lesson' ) || is_singular( 'course' ) ) {
1514
			$args['type'] = 'comment';
1515
		}
1516
1517
		return $args;
1518
	} // End hide_sensei_activity()
1519
1520
	/**
1521
	 * Redirect failed login attempts to the front end login page
1522
	 * in the case where the login fields are not left empty
1523
	 *
1524
	 * @return void redirect
1525
	 */
1526
	function sensei_login_fail_redirect( ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1527
1528
		//if not posted from the sensei login form let
1529
		// WordPress or any other party handle the failed request
1530
	    if( ! isset( $_REQUEST['form'] ) || 'sensei-login' != $_REQUEST['form']  ){
1531
1532
	    	return ;
1533
1534
	    }
1535
1536
    	// Get the reffering page, where did the post submission come from?
1537
    	$referrer = add_query_arg('login', false, $_SERVER['HTTP_REFERER']);
1538
1539
   		 // if there's a valid referrer, and it's not the default log-in screen
1540
	    if(!empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin')){
1541
	        // let's append some information (login=failed) to the URL for the theme to use
1542
	        wp_redirect( esc_url_raw( add_query_arg('login', 'failed',  $referrer) ) );
1543
	    	exit;
1544
    	}
1545
	}// End sensei_login_fail_redirect_to_front_end_login
1546
1547
	/**
1548
	 * Handle the login reques from all sensei intiated login forms.
1549
	 *
1550
	 * @return void redirect
1551
	 */
1552
	function sensei_handle_login_request( ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1553
1554
1555
		// Check that it is a sensei login request and if it has a valid nonce
1556
	    if(  isset( $_REQUEST['form'] ) && 'sensei-login' == $_REQUEST['form'] ) {
1557
1558
	    	// Validate the login request nonce
1559
		    if( !wp_verify_nonce( $_REQUEST['_wpnonce'], 'sensei-login' ) ){
1560
		    	return;
1561
		    }
1562
1563
1564
		    //get the page where the sensei log form is located
1565
		    $referrer = $_REQUEST['_wp_http_referer'];
1566
		    //$redirect = $_REQUEST['_sensei_redirect'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1567
1568
		    if ( ( isset( $_REQUEST['log'] ) && !empty( $_REQUEST['log'] ) )
1569
		    	 && ( isset( $_REQUEST['pwd'] ) && !empty( $_REQUEST['pwd'] ) ) ){
1570
1571
		    	// when the user has entered a password or username do the sensei login
1572
		    	$creds = array();
1573
1574
		    	// check if the requests login is an email address
1575
		    	if( is_email(  trim( $_REQUEST['log'] ) )  ){
1576
		    		// query wordpress for the users details
1577
		    		$user =	get_user_by( 'email', sanitize_email( $_REQUEST['log'] )  );
1578
1579
		    		// validate the user object
1580
		    		if( !$user ){
1581
1582
		    			// the email doesnt exist
1583
                        wp_redirect( esc_url_raw( add_query_arg('login', 'failed', $referrer) ) );
1584
		        		exit;
1585
1586
		    		}
1587
1588
		    		//assigne the username to the creds array for further processing
1589
		    		$creds['user_login'] =  $user->user_login ;
1590
1591
		    	}else{
1592
1593
		    		// process this as a default username login
1594
		    		$creds['user_login'] = sanitize_text_field( $_REQUEST['log'] ) ;
1595
1596
		    	}
1597
1598
				// get setup the rest of the creds array
1599
				$creds['user_password'] = sanitize_text_field( $_REQUEST['pwd'] );
1600
				$creds['remember'] = isset( $_REQUEST['rememberme'] ) ? true : false ;
1601
1602
				//attempt logging in with the given details
1603
				$user = wp_signon( $creds, false );
1604
1605
				if ( is_wp_error($user) ){ // on login failure
1606
                    wp_redirect( esc_url_raw( add_query_arg('login', 'failed', $referrer) ) );
1607
                    exit;
1608
				}else{ // on login success
1609
1610
					/**
1611
					* change the redirect url programatically
1612
					*
1613
					* @since 1.6.1
1614
					*
1615
					* @param string $referrer the page where the current url wheresensei login form was posted from
1616
					*/
1617
1618
					$success_redirect_url = apply_filters('sesei_login_success_redirect_url', remove_query_arg( 'login', $referrer ) );
1619
1620
					wp_redirect( esc_url_raw( $success_redirect_url ) );
1621
		        	exit;
1622
1623
				}	// end is_wp_error($user)
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1624
1625
		    }else{ // if username or password is empty
1626
1627
                wp_redirect( esc_url_raw( add_query_arg('login', 'emptyfields', $referrer) ) );
1628
		        exit;
1629
1630
		    } // end if username $_REQUEST['log']  and password $_REQUEST['pwd'] is empty
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1631
1632
	    }elseif( ( isset( $_GET['login'] ) ) ) {
1633
	    	// else if this request is a redircect from a previously faile login request
1634
	    	$this->login_message_process();
1635
1636
			//exit the handle login request function
1637
			return;
1638
	    }
1639
1640
	    // if none of the above
1641
	    return;
1642
1643
	} // End  sensei_login_fail_redirect_to_front_end_login
1644
1645
	/**
1646
	 * handle sensei specific registration requests
1647
	 *
1648
	 * @return void redirect
1649
	 *
1650
	 */
1651
	public function sensei_process_registration(){
1652
		global 	 $current_user;
1653
		// check the for the sensei specific registration requests
1654
		if( !isset( $_POST['sensei_reg_username'] ) && ! isset( $_POST['sensei_reg_email'] ) && !isset( $_POST['sensei_reg_password'] )){
1655
			// exit functionas this is not a sensei registration request
1656
			return ;
1657
		}
1658
		// check for spam throw cheating huh
1659
		if( isset( $_POST['email_2'] ) &&  '' !== $_POST['email_2']   ){
1660
			$message = 'Error:  The spam field should be empty';
1661
			Sensei()->notices->add_notice( $message, 'alert');
1662
			return;
1663
		}
1664
1665
		// retreive form variables
1666
		$new_user_name		= sanitize_user( $_POST['sensei_reg_username'] );
1667
		$new_user_email		= $_POST['sensei_reg_email'];
1668
		$new_user_password	= $_POST['sensei_reg_password'];
1669
1670
		// Check the username
1671
		$username_error_notice = '';
1672
		if ( $new_user_name == '' ) {
1673
			$username_error_notice =  __( '<strong>ERROR</strong>: Please enter a username.' );
1674
		} elseif ( ! validate_username( $new_user_name ) ) {
1675
			$username_error_notice =  __( '<strong>ERROR</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' );
1676
		} elseif ( username_exists( $new_user_name ) ) {
1677
			$username_error_notice =  __( '<strong>ERROR</strong>: This username is already registered. Please choose another one.' );
1678
		}
1679
1680
		// exit on username error
1681
		if( '' !== $username_error_notice ){
1682
			Sensei()->notices->add_notice( $username_error_notice , 'alert');
1683
			return;
1684
		}
1685
1686
		// Check the e-mail address
1687
		$email_error_notice = '';
1688
		if ( $new_user_email == '' ) {
1689
			$email_error_notice = __( '<strong>ERROR</strong>: Please type your e-mail address.' );
1690
		} elseif ( ! is_email( $new_user_email ) ) {
1691
			$email_error_notice = __( '<strong>ERROR</strong>: The email address isn&#8217;t correct.' );
1692
		} elseif ( email_exists( $new_user_email ) ) {
1693
			$email_error_notice = __( '<strong>ERROR</strong>: This email is already registered, please choose another one.' );
1694
		}
1695
1696
		// exit on email address error
1697
		if( '' !== $email_error_notice ){
1698
			Sensei()->notices->add_notice( $email_error_notice , 'alert');
1699
			return;
1700
		}
1701
1702
		//check user password
1703
1704
		// exit on email address error
1705
		if( empty( $new_user_password ) ){
1706
			Sensei()->notices->add_notice(  __( '<strong>ERROR</strong>: The password field may not be empty, please enter a secure password.' )  , 'alert');
1707
			return;
1708
		}
1709
1710
		// register user
1711
		$user_id = wp_create_user( $new_user_name, $new_user_password, $new_user_email );
1712
		if ( ! $user_id || is_wp_error( $user_id ) ) {
1713
			Sensei()->notices->add_notice( sprintf( __( '<strong>ERROR</strong>: Couldn\'t register you&hellip; please contact the <a href="mailto:%s">webmaster</a> !' ), get_option( 'admin_email' ) ), 'alert');
1714
		}
1715
1716
		// notify the user
1717
		wp_new_user_notification( $user_id, $new_user_password );
1718
1719
		// set global current user aka log the user in
1720
		$current_user = get_user_by( 'id', $user_id );
1721
		wp_set_auth_cookie( $user_id, true );
1722
1723
		// Redirect
1724
		global $wp;
1725
		if ( wp_get_referer() ) {
1726
			$redirect = esc_url( wp_get_referer() );
1727
		} else {
1728
			$redirect = esc_url( home_url( $wp->request ) );
1729
		}
1730
1731
		wp_redirect( apply_filters( 'sensei_registration_redirect', $redirect ) );
1732
		exit;
1733
1734
	} // end  sensei_process_registration)()
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1735
1736
	/**
1737
	 * login_message_process(). handle the login message displayed on faile login
1738
	 *
1739
	 * @return void redirect
1740
	 * @since 1.7.0
1741
	 */
1742
	public function login_message_process(){
1743
1744
1745
		    // setup the message variables
1746
			$message = '';
1747
1748
			//only output message if the url contains login=failed and login=emptyfields
1749
1750
			if( $_GET['login'] == 'failed' ){
1751
1752
				$message = __('Incorrect login details', 'woothemes-sensei' );
1753
1754
			}elseif( $_GET['login'] == 'emptyfields'  ){
1755
1756
				$message= __('Please enter your username and password', 'woothemes-sensei' );
1757
			}
1758
1759
			Sensei()->notices->add_notice( $message, 'alert');
1760
1761
	}// end login_message_process
1762
1763
1764
    /**
1765
     * sensei_show_admin_bar(). Use WooCommerce filter
1766
     * to show admin bar to Teachers as well.
1767
     *
1768
     * @return void redirect
1769
     *
1770
     */
1771
    public function sensei_show_admin_bar () {
1772
1773
        if (current_user_can('edit_courses')) {
1774
1775
            add_filter( 'woocommerce_disable_admin_bar', '__return_false', 10, 1);
1776
1777
        }
1778
1779
    }
1780
1781
} // End Class
1782
1783
/**
1784
 * Class WooThemes_Sensei_Frontend
1785
 * for backward compatibility
1786
 * @since 1.9.0
1787
 */
1788
class WooThemes_Sensei_Frontend extends Sensei_Frontend{}
1789