Completed
Push — master ( d3c307...d2b88c )
by Dwain
05:56
created

activate_purchased_single_course()   D

Complexity

Conditions 14
Paths 13

Size

Total Lines 82
Code Lines 41

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 82
rs 4.955
cc 14
eloc 41
nc 13
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 Core
10
 * @author Automattic
11
 *
12
 * @since 1.0.0
13
 */
14
class Sensei_Frontend {
15
16
	public $messages;
17
	public $data;
18
19
	/**
20
	 * Constructor.
21
	 * @since  1.0.0
22
	 */
23
	public function __construct () {
24
25
		// Template output actions
26
		add_action( 'sensei_before_main_content', array( $this, 'sensei_output_content_wrapper' ), 10 );
27
		add_action( 'sensei_after_main_content', array( $this, 'sensei_output_content_wrapper_end' ), 10 );
28
		add_action( 'sensei_lesson_archive_lesson_title', array( $this, 'sensei_lesson_archive_lesson_title' ), 10 );
29
30
		// 1.2.1
31
		add_action( 'sensei_complete_lesson', array( $this, 'sensei_complete_lesson' ) );
32
		add_action( 'init', array( $this, 'sensei_complete_course' ), 5 );
33
		add_action( 'sensei_frontend_messages', array( $this, 'sensei_frontend_messages' ) );
34
		add_action( 'sensei_lesson_video', array( $this, 'sensei_lesson_video' ), 10, 1 );
35
		add_action( 'sensei_complete_lesson_button', array( $this, 'sensei_complete_lesson_button' ) );
36
		add_action( 'sensei_reset_lesson_button', array( $this, 'sensei_reset_lesson_button' ) );
37
38
		add_action( 'sensei_course_archive_meta', array( $this, 'sensei_course_archive_meta' ) );
39
40
		add_action( 'sensei_lesson_tag_main_content', array( $this, 'sensei_lesson_archive_main_content' ), 10 );
41
		add_action( 'sensei_no_permissions_main_content', array( $this, 'sensei_no_permissions_main_content' ), 10 );
42
43
		add_action( 'sensei_lesson_meta', array( $this, 'sensei_lesson_meta' ), 10 );
44
		add_action( 'sensei_single_course_content_inside_before', array( $this, 'sensei_course_start' ), 10 );
45
46
		// 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...
47
		add_filter( 'the_title', array( $this, 'sensei_lesson_preview_title' ), 10, 2 );
48
49
		//1.6.2
50
		add_filter( 'wp_login_failed', array( $this, 'sensei_login_fail_redirect' ), 10 );
51
		add_filter( 'init', array( $this, 'sensei_handle_login_request' ), 10 );
52
		//1.6.3
53
		add_action( 'init', array( $this, 'sensei_process_registration' ), 2 );
54
		//1.7.0
55
		add_action( 'sensei_pagination', array( $this, 'sensei_breadcrumb' ), 80, 1 );
56
57
		// Fix pagination for course archive pages when filtering by course type
58
		add_filter( 'pre_get_posts', array( $this, 'sensei_course_archive_pagination' ) );
59
60
		// Scripts and Styles
61
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ) );
62
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
63
64
		// Custom Menu Item filters
65
		add_filter( 'wp_setup_nav_menu_item', array( $this, 'sensei_setup_nav_menu_item' ) );
66
		add_filter( 'wp_nav_menu_objects', array( $this, 'sensei_wp_nav_menu_objects' ) );
67
		// Search Results filters
68
		add_filter( 'post_class', array( $this, 'sensei_search_results_classes' ), 10 );
69
		// Only show course & lesson excerpts in search results
70
		add_filter( 'the_content', array( $this, 'sensei_search_results_excerpt' ) );
71
72
        //Use WooCommerce filter to show admin bar to Teachers.
73
        add_action( 'init', array( $this, 'sensei_show_admin_bar') );
74
75
        // Remove course from active courses if an order is cancelled or refunded
76
		add_action( 'woocommerce_order_status_processing_to_cancelled', array( $this, 'remove_active_course' ), 10, 1 );
77
		add_action( 'woocommerce_order_status_completed_to_cancelled', array( $this, 'remove_active_course' ), 10, 1 );
78
		add_action( 'woocommerce_order_status_on-hold_to_cancelled', array( $this, 'remove_active_course' ), 10, 1 );
79
		add_action( 'woocommerce_order_status_processing_to_refunded', array( $this, 'remove_active_course' ), 10, 1 );
80
		add_action( 'woocommerce_order_status_completed_to_refunded', array( $this, 'remove_active_course' ), 10, 1 );
81
		add_action( 'woocommerce_order_status_on-hold_to_refunded', array( $this, 'remove_active_course' ), 10, 1 );
82
83
		// Make sure correct courses are marked as active for users
84
		add_action( 'sensei_before_my_courses', array( $this, 'activate_purchased_courses' ), 10, 1 );
85
		add_action( 'sensei_single_course_content_inside_before', array( $this, 'activate_purchased_single_course' ), 10 );
86
87
		// Lesson tags
88
		add_action( 'sensei_lesson_meta_extra', array( $this, 'lesson_tags_display' ), 10, 1 );
89
		add_action( 'pre_get_posts', array( $this, 'lesson_tag_archive_filter' ), 10, 1 );
90
		add_filter( 'sensei_lessons_archive_text', array( $this, 'lesson_tag_archive_header' ) );
91
		add_action( 'sensei_loop_lesson_inside_before', array( $this, 'lesson_tag_archive_description' ), 11 );
92
93
		// Hide Sensei activity comments from lesson and course pages
94
		add_filter( 'wp_list_comments_args', array( $this, 'hide_sensei_activity' ) );
95
	} // End __construct()
96
97
	/**
98
	 * Graceful fallback for course and lesson variables on Frontend object
99
	 *
100
	 * @param string $key Key to get.
101
	 * @since  1.7.3
102
	 * @return array|mixed
103
	 */
104
	public function __get( $key ) {
105
106
		if ( 'lesson' == $key || 'course' == $key ) {
107
			if ( WP_DEBUG ) {
108
				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' ) );
109
			}
110
			return Sensei()->$key;
111
		}
112
113
		return null;
114
	}
115
116
	/**
117
	 * Enqueue frontend JavaScripts.
118
	 * @since  1.0.0
119
	 * @return void
120
	 */
121
	public function enqueue_scripts () {
122
123
		$disable_js = false;
124
		if ( isset( Sensei()->settings->settings[ 'js_disable' ] ) ) {
125
			$disable_js = Sensei()->settings->settings[ 'js_disable' ];
126
		} // End If Statement
127
		if ( ! $disable_js ) {
128
129
			$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
130
131
			// My Courses tabs script
132
			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 );
133
			wp_enqueue_script( Sensei()->token . '-user-dashboard' );
134
135
136
            // Course Archive javascript
137
            if( is_post_type_archive( 'course' ) ){
138
139
                wp_register_script( 'sensei-course-archive-js', esc_url( Sensei()->plugin_url . 'assets/js/frontend/course-archive' . $suffix . '.js' ), array( 'jquery' ), '1', true );
140
                wp_enqueue_script( 'sensei-course-archive-js' );
141
142
            }
143
144
145
			// Allow additional scripts to be loaded
146
			do_action( 'sensei_additional_scripts' );
147
148
		} // End If Statement
149
150
	} // End enqueue_scripts()
151
152
	/**
153
	 * Enqueue frontend CSS files.
154
	 * @since  1.0.0
155
	 * @return void
156
	 */
157
	public function enqueue_styles () {
158
159
		$disable_styles = false;
160
		if ( isset( Sensei()->settings->settings[ 'styles_disable' ] ) ) {
161
			$disable_styles = Sensei()->settings->settings[ 'styles_disable' ];
162
		} // End If Statement
163
164
		// Add filter for theme overrides
165
		$disable_styles = apply_filters( 'sensei_disable_styles', $disable_styles );
166
167
		if ( ! $disable_styles ) {
168
169
			wp_register_style( Sensei()->token . '-frontend', Sensei()->plugin_url . 'assets/css/frontend/sensei.css', '', Sensei()->version, 'screen' );
170
			wp_enqueue_style( Sensei()->token . '-frontend' );
171
172
			// Allow additional stylesheets to be loaded
173
			do_action( 'sensei_additional_styles' );
174
175
		} // End If Statement
176
177
	} // End enqueue_styles()
178
179
180
	/**
181
	 * sensei_get_template_part function.
182
	 *
183
     * @deprecated sine 1.9.0
184
	 * @access public
185
	 * @param mixed $slug
186
	 * @param string $name (default: '')
187
	 * @return void
188
	 */
189
	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...
190
191
        _deprecated_function( 'class-woothemes-sensei-frontend.php', '1.9.0', 'Sensei_Templates::get_part' );
192
        Sensei_Templates::get_part( $slug, $name );
193
194
	} // End sensei_get_template_part()
195
196
	/**
197
	 * sensei_get_template function.
198
	 *
199
     * @deprecated since 1.9.0
200
	 * @access public
201
	 * @param mixed $template_name
202
	 * @param array $args (default: array())
203
	 * @param string $template_path (default: '')
204
	 * @param string $default_path (default: '')
205
	 * @return void
206
	 */
207
	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...
208
209
        _deprecated_function( 'sensei_get_template', '1.9.0', 'Sensei_Templates::get_template' );
210
        Sensei_Templates::get_template($template_name, $args, $template_path, $default_path  );
211
212
	} // End sensei_get_template()
213
214
215
	/**
216
	 * sensei_locate_template function.
217
	 *
218
	 * @access public
219
	 * @param mixed $template_name
220
	 * @param string $template_path (default: '')
221
	 * @param string $default_path (default: '')
222
	 * @return void
223
	 */
224
	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...
225
226
        _deprecated_function( 'sensei_locate_template', '1.9.0', 'Sensei_Templates::locate_template' );
227
        Sensei_Templates::locate_template( $template_name, $template_path, $default_path );
228
229
	} // End sensei_locate_template()
230
231
232
	/**
233
	 * sensei_output_content_wrapper function.
234
     *
235
	 * @access public
236
	 * @return void
237
	 */
238 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...
239
240
	    // backwards compatibility check for old location under the wrappers directory of the active theme
241
        $backwards_compatible_wrapper_location =   array(
242
            Sensei()->template_url . 'wrappers/wrapper-start.php',
243
            'wrappers/wrapper-start.php'
244
        );
245
246
        $template = locate_template( $backwards_compatible_wrapper_location );
247
        if( !empty( $template ) ){
248
249
            Sensei_Templates::get_template( 'wrappers/wrapper-start.php' );
250
            return;
251
252
        }
253
254
		Sensei_Templates::get_template( 'globals/wrapper-start.php' );
255
256
	} // End sensei_output_content_wrapper()
257
258
259
	/**
260
	 * sensei_output_content_wrapper_end function.
261
     *
262
	 * @access public
263
	 * @return void
264
	 */
265 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...
266
267
	    // backwards compatibility check for old location under the wrappers directory of the active theme
268
        $backwards_compatible_wrapper_location =   array(
269
            Sensei()->template_url . 'wrappers/wrapper-end.php',
270
            'wrappers/wrapper-end.php'
271
        );
272
273
        $backwards_compatible_template = locate_template( $backwards_compatible_wrapper_location );
274
        if( !empty( $backwards_compatible_template ) ){
275
276
            Sensei_Templates::get_template( 'wrappers/wrapper-end.php' );
277
            return;
278
279
        }
280
281
282
		Sensei_Templates::get_template( 'globals/wrapper-end.php' );
283
284
	} // End sensei_output_content_wrapper_end()
285
286
287
	/**
288
	 * sensei_output_content_pagination function.
289
	 *
290
	 * @access public
291
	 * @return void
292
	 */
293
	public static function load_content_pagination() {
294
295
        if( is_singular('course') ) {
296
297
            // backwards compatibility check for old location under the wrappers directory of the active theme
298
            $template = locate_template( array( Sensei()->template_url . 'wrappers/pagination-posts.php' ) );
299
            if( !empty( $template ) ){
300
301
                Sensei_Templates::get_template( 'wrappers/pagination-posts.php' );
302
                return;
303
304
            }
305
306
			Sensei_Templates::get_template( 'globals/pagination-posts.php' );
307
308 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...
309
310
		    // backwards compatibility check for old location under the wrappers directory of the active theme
311
		    $template = locate_template( array( Sensei()->template_url . 'wrappers/pagination-lesson.php' ) );
312
            if( !empty( $template ) ){
313
314
                Sensei_Templates::get_template( 'wrappers/pagination-lesson.php' );
315
                return;
316
317
            }
318
319
			Sensei_Templates::get_template( 'globals/pagination-lesson.php' );
320
321
		} elseif( is_singular('quiz') ) {
322
323
		    // backwards compatibility check for old location under the wrappers directory of the active theme
324
		    $template = locate_template( array( Sensei()->template_url . 'wrappers/pagination-quiz.php' ) );
325
            if( !empty( $template ) ){
326
327
                Sensei_Templates::get_template( 'wrappers/pagination-quiz.php' );
328
                return;
329
330
            }
331
332
			Sensei_Templates::get_template( 'globals/pagination-quiz.php' );
333
334 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...
335
336
            // backwards compatibility check for old location under the wrappers directory of the active theme
337
            $template = locate_template( array( Sensei()->template_url . 'wrappers/pagination.php' ) );
338
            if( !empty( $template ) ){
339
340
                Sensei_Templates::get_template( 'wrappers/pagination.php' );
341
                return;
342
343
            }
344
345
			Sensei_Templates::get_template( 'globals/pagination.php' );
346
347
		} // End If Statement
348
349
	} // End sensei_output_content_pagination()
350
351
	/**
352
	 * outputs comments for the specified pages
353
	 * @deprecated
354
	 * @return void
355
	 */
356
	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...
357
358
		Sensei_Lesson::output_comments();
359
360
	} // End sensei_output_comments()
361
362
	/**
363
	 * sensei_setup_nav_menu_item function.
364
	 *
365
	 * Generate the urls for Sensei custom menu items.
366
	 *
367
	 * @access public
368
	 * @param object $item
369
	 * @return object $item
370
	 */
371
	public function sensei_setup_nav_menu_item( $item ) {
372
		global $pagenow, $wp_rewrite;
373
374
		if( 'nav-menus.php' != $pagenow && !defined('DOING_AJAX') && isset( $item->url ) && 'custom' == $item->type ) {
375
376
			// Set up Sensei menu links
377
			$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...
378
			$my_account_page_id = intval( Sensei()->settings->settings[ 'my_course_page' ] );
379
380
			$course_page_url = Sensei_Course::get_courses_page_url();
381
			$lesson_archive_url = get_post_type_archive_link( 'lesson' );
382
			$my_courses_url = get_permalink( $my_account_page_id );
383
			$my_messages_url = get_post_type_archive_link( 'sensei_message' );
384
385
			switch ( $item->url ) {
386
				case '#senseicourses':
387
					$item->url = $course_page_url;
388
					break;
389
390
				case '#senseilessons':
391
					$item->url = $lesson_archive_url;
392
					break;
393
394
				case '#senseimycourses':
395
					$item->url = $my_courses_url;
396
					break;
397
398
				case '#senseimymessages':
399
					$item->url = $my_messages_url;
400
                    // if no archive link exist for sensei_message
401
                    // set it back to the place holder
402
                    if( ! $item->url ){
403
404
                        $item->url = '#senseimymessages';
405
406
                    }
407
					break;
408
409
				case '#senseilearnerprofile':
410
					$item->url = esc_url( Sensei()->learner_profiles->get_permalink() );
411
					break;
412
413
				case '#senseiloginlogout':
414
						$logout_url = wp_logout_url( home_url() );
415
						// Login link links to the My Courses page, to avoid the WP dashboard.
416
						$login_url = $my_courses_url;
417
418
						$item->url = ( is_user_logged_in() ? $logout_url : $login_url );
419
420
						// determine the menu title login or logout
421
						if ( is_user_logged_in() ) {
422
							$menu_title =  __( 'Logout'  ,'woothemes-sensei');
423
						} else {
424
							$menu_title =  __( 'Login'  ,'woothemes-sensei');
425
						}
426
427
						/**
428
						 * Action Filter: login/logout menu title
429
						 *
430
						 * With this filter you can alter the login / login menu item title string
431
						 *
432
						 * @param $menu_title
433
						 */
434
						$item->title = apply_filters( 'sensei_login_logout_menu_title', $menu_title );
435
436
					break;
437
438
				default:
439
					break;
440
			}
441
442
			$_root_relative_current = untrailingslashit( $_SERVER['REQUEST_URI'] );
443
			$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_root_relative_current );
444
			$item_url = untrailingslashit( $item->url );
445
			$_indexless_current = untrailingslashit( preg_replace( '/' . preg_quote( $wp_rewrite->index, '/' ) . '$/', '', $current_url ) );
446
			// Highlight current menu item
447
			if ( $item_url && in_array( $item_url, array( $current_url, $_indexless_current, $_root_relative_current ) ) ) {
448
				$item->classes[] = 'current-menu-item current_page_item';
449
			}
450
451
		} // endif nav
452
453
		return $item;
454
455
	} // End sensei_setup_nav_menu_item()
456
457
	/**
458
	 * sensei_wp_nav_menu_objects function.
459
	 *
460
	 * Remove Sensei custom menu items depending on settings and logged in status.
461
	 *
462
	 * @access public
463
	 * @param object $sorted_menu_items
464
	 * @return object $sorted_menu_items
465
	 */
466
	public function sensei_wp_nav_menu_objects( $sorted_menu_items ) {
467
468
		foreach( $sorted_menu_items as $k=>$item ) {
469
470
			// Remove the My Messages link for logged out users or if Private Messages are disabled
471 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...
472
                && '#senseimymessages' == $item->url ) {
473
474
				if ( !is_user_logged_in() || ( isset( Sensei()->settings->settings['messages_disable'] ) && Sensei()->settings->settings['messages_disable'] ) ) {
475
476
					unset( $sorted_menu_items[$k] );
477
478
				}
479
			}
480
			// Remove the My Profile link for logged out users.
481 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...
482
483
				if ( !is_user_logged_in() || ! ( isset( Sensei()->settings->settings[ 'learner_profile_enable' ] ) && Sensei()->settings->settings[ 'learner_profile_enable' ] ) ) {
484
485
					unset( $sorted_menu_items[$k] );
486
487
				}
488
			}
489
		}
490
		return $sorted_menu_items;
491
	} // End sensei_wp_nav_menu_objects
492
493
	// add category nicenames in body and post class
494
	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...
495
	    global $post;
496
	    // Handle Search Classes for Courses, Lessons, and WC Products
497
	    if ( isset( $post->post_type ) && ( ( 'course' == $post->post_type ) || ( 'lesson' == $post->post_type ) || ( 'product' == $post->post_type ) ) ) {
498
	    	$classes[] = 'post';
499
		} // End If Statement
500
	    return $classes;
501
	} // End sensei_search_results_classes()
502
503
    /**
504
     * sensei_single_title output for single page title
505
     * @since  1.1.0
506
     * @return void
507
     * @deprecated
508
     */
509
    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...
510
511
        _deprecated_function(' WooThemes_Sensei_Frontend::the_single_title', '1.9.0');
512
513
    } // End sensei_single_title()
514
515
	/**
516
	 * sensei_course_image output for course image Please use Sensei()->course->course_image instead.
517
     *
518
     * @deprecated since 1.9.0
519
     * @param $course_id
520
     * @param string $width
521
     * @param string $height
522
     * @param bool|false $return
523
     * @return string|void
524
	 */
525
	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...
526
527
    	if ( ! $return ) {
528
529
			echo Sensei()->course->course_image( $course_id, $width, $height );
530
            return '';
531
532
		} // End If Statement
533
534
		return Sensei()->course->course_image( $course_id, $width, $height );
535
536
	} // End sensei_course_image()
537
538
	/**
539
	 * sensei_lesson_image output for lesson image
540
	 * @since  1.2.0
541
     * @deprecated since 1.9.0
542
     * @param $lesson_id
543
     * @param string $width
544
     * @param string $height
545
     * @param bool|false $return
546
     * @param bool|false $widget
547
     * @return string
548
	 */
549
	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...
550
551
        if( ! $return ){
552
553
            echo Sensei()->lesson->lesson_image( $lesson_id, $width, $height, $widget );
554
            return '';
555
        }
556
557
        return Sensei()->lesson->lesson_image( $lesson_id, $width, $height, $widget );
558
559
	} // End sensei_lesson_image()
560
561
    /**
562
     * @since 1.0.0
563
     * @param WP_Query $query
564
     */
565
    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...
566
567
		if( ! is_admin() && $query->is_main_query() && isset( $_GET['action'] ) && in_array( $_GET['action'], array( 'newcourses', 'featuredcourses', 'freecourses', 'paidcourses' ) ) ) {
568
569
			$amount = 0;
570
			if ( isset( Sensei()->settings->settings[ 'course_archive_amount' ] ) && ( 0 < absint( Sensei()->settings->settings[ 'course_archive_amount' ] ) ) ) {
571
				$amount = absint( Sensei()->settings->settings[ 'course_archive_amount' ] );
572
			}
573
574
			if( $amount ) {
575
				$query->set( 'posts_per_page', $amount );
576
			}
577
578
			$query->set( 'orderby', 'menu_order date' );
579
580
		}
581
	}
582
583
	/**
584
	 * sensei_course_archive_header function.
585
	 *
586
	 * @access public
587
	 * @since  1.2.0
588
     * @deprecated since 1.9.0 use WooThemes_Sensei_Course::archive_header
589
	 * @return void
590
	 */
591
	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...
592
593
        trigger_error('This function sensei_course_archive_header has been depricated. Please use: WooThemes_Sensei_Course::course_archive_header ');
594
        WooThemes_Sensei_Course::archive_header( '', '<header class="archive-header"><h1>', '</h1></header>' );
595
596
	} // sensei_course_archive_header()
597
598
	/**
599
	 * sensei_lesson_archive_header function.
600
	 *
601
     * @deprecated since 1.9.0
602
	 * @access public
603
	 * @since  1.2.1
604
	 * @return void
605
	 */
606
	public function sensei_lesson_archive_header( ) {
607
        _deprecated_function( 'WooThemes_Sensei_Frontend::sensei_lesson_archive_header', '1.9.0', 'WooThemes_Sensei_Lesson::the_archive_header' );
608
        Sensei()->lesson->the_archive_header();
609
	} // sensei_course_archive_header()
610
611
    /**
612
     * @deprecated since 1.9.0
613
     */
614
	public function sensei_message_archive_header( ){
615
        _deprecated_function('Sensei_Frontend::sensei_message_archive_header','Please use: Sense');
616
        Sensei_Messages::the_archive_header();
617
	} // sensei_message_archive_header()
618
619
	/**
620
	 * sensei_course_archive_course_title output for course archive page individual course title
621
	 * @since  1.2.0
622
     * @param WP_Post $post_item
623
	 * @return void
624
	 */
625
	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...
626
		if ( isset( $post_item->ID ) && ( 0 < $post_item->ID ) ) {
627
			$post_id = absint( $post_item->ID );
628
    		$post_title = $post_item->post_title;
629
		} else {
630
			$post_id = get_the_ID();
631
    		$post_title = get_the_title();
632
		} // End If Statement
633
		?><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
634
	} // End sensei_course_archive_course_title()
635
636
	/**
637
	 * sensei_lesson_archive_lesson_title output for course archive page individual course title
638
	 * @since  1.2.1
639
	 * @return void
640
	 */
641
	public function sensei_lesson_archive_lesson_title() {
642
		$post_id = get_the_ID();
643
    	$post_title = get_the_title();
644
		?><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
645
	} // End sensei_lesson_archive_lesson_title()
646
647
	/**
648
	 * sensei_breadcrumb outputs Sensei breadcrumb trail on lesson & quiz pages
649
	 * @since  1.7.0
650
	 * @param  integer $id course, lesson or quiz id
651
	 * @return void
652
	 */
653
	public function sensei_breadcrumb( $id = 0 ) {
654
655
		// Only output on lesson, quiz and taxonomy (module) pages
656
		if( ! ( is_tax( 'module' ) || is_singular( 'lesson' ) || is_singular( 'quiz' ) ) ) return;
657
658
		if( empty( $id )  ){
659
660
            $id = get_the_ID();
661
662
        }
663
664
		$sensei_breadcrumb_prefix = __( 'Back to: ', 'woothemes-sensei' );
665
		$separator = apply_filters( 'sensei_breadcrumb_separator', '&gt;' );
666
667
		$html = '<section class="sensei-breadcrumb">' . $sensei_breadcrumb_prefix;
668
		// Lesson
669 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...
670
			$course_id = intval( get_post_meta( $id, '_lesson_course', true ) );
671
			if( ! $course_id ) {
672
				return;
673
			}
674
			$html .= '<a href="' . esc_url( get_permalink( $course_id ) ) . '" title="' . __( 'Back to the course', 'woothemes-sensei' ) . '">' . get_the_title( $course_id ) . '</a>';
675
    	} // End If Statement
676
    	// Quiz
677 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...
678
			$lesson_id = intval( get_post_meta( $id, '_quiz_lesson', true ) );
679
			if( ! $lesson_id ) {
680
				return;
681
			}
682
			 $html .= '<a href="' . esc_url( get_permalink( $lesson_id ) ) . '" title="' .  __( 'Back to the lesson', 'woothemes-sensei' ) . '">' . get_the_title( $lesson_id ) . '</a>';
683
    	} // End If Statement
684
685
    	// Allow other plugins to filter html
686
    	$html = apply_filters ( 'sensei_breadcrumb_output', $html, $separator );
687
    	$html .= '</section>';
688
689
    	echo $html;
690
	} // End sensei_breadcrumb()
691
692
693
    /**
694
     * @deprecated since 1.9.0 use WooThemes_Sensei_Lesson::course_signup_link instead
695
     */
696
	public function sensei_lesson_course_signup_link( ) {
697
698
        _deprecated_function('sensei_lesson_course_signup_link', '1.9.0', 'WooThemes_Sensei_Lesson::course_signup_link' );
699
        WooThemes_Sensei_Lesson::course_signup_link();
700
	}
701
702
	public function lesson_tags_display( $lesson_id = 0 ) {
703
		if( $lesson_id ) {
704
			$tags = wp_get_post_terms( $lesson_id, 'lesson-tag' );
705
			if( $tags && count( $tags ) > 0 ) {
706
				$tag_list = '';
707
				foreach( $tags as $tag ) {
708
					$tag_link = get_term_link( $tag, 'lesson-tag' );
709
					if( ! is_wp_error( $tag_link ) ) {
710
						if( $tag_list ) { $tag_list .= ', '; }
711
						$tag_list .= '<a href="' . $tag_link . '">' . $tag->name . '</a>';
712
					}
713
				}
714
				if( $tag_list ) {
715
					?><section class="lesson-tags">
716
		    			<?php printf( __( 'Lesson tags: %1$s', 'woothemes-sensei' ), $tag_list ); ?>
717
		    		</section><?php
718
		    	}
719
	    	}
720
		}
721
	}
722
723
    /**
724
     * @param WP_Query $query
725
     */
726
	public function lesson_tag_archive_filter( $query ) {
727
    	if( is_tax( 'lesson-tag' ) && $query->is_main_query() ) {
728
    		// Limit to lessons only
729
    		$query->set( 'post_type', 'lesson' );
730
731
    		// Set order of lessons
732
    		$query->set( 'orderby', 'menu_order' );
733
    		$query->set( 'order', 'ASC' );
734
735
    	}
736
    }
737
738
    public function lesson_tag_archive_header( $title ) {
739
		if( is_tax( 'lesson-tag' ) ) {
740
			$title = sprintf( __( 'Lesson tag: %1$s', 'woothemes-sensei' ), apply_filters( 'sensei_lesson_tag_archive_title', get_queried_object()->name ) );
741
		}
742
		return $title;
743
	}
744
745
	public function lesson_tag_archive_description() {
746
		if( is_tax( 'lesson-tag' ) ) {
747
			$tag = get_queried_object();
748
			echo '<p class="archive-description lesson-description">' . apply_filters( 'sensei_lesson_tag_archive_description', nl2br( $tag->description ), $tag->term_id ) . '</p>';
749
		}
750
	}
751
752
	public function sensei_complete_lesson() {
753
		global $post,  $current_user;
754
		// Handle Quiz Completion
755
		if ( isset( $_POST['quiz_action'] ) && wp_verify_nonce( $_POST[ 'woothemes_sensei_complete_lesson_noonce' ], 'woothemes_sensei_complete_lesson_noonce' ) ) {
756
757
			$sanitized_submit = esc_html( $_POST['quiz_action'] );
758
759
			switch ($sanitized_submit) {
760
                case 'lesson-complete':
761
762
					Sensei_Utils::sensei_start_lesson( $post->ID, $current_user->ID, $complete = true );
763
764
					break;
765
766
                case 'lesson-reset':
767
768
					Sensei_Utils::sensei_remove_user_from_lesson( $post->ID, $current_user->ID );
769
770
					$this->messages = '<div class="sensei-message note">' .  __( 'Lesson Reset Successfully.', 'woothemes-sensei' ) . '</div>';
771
					break;
772
773
				default:
774
					// Nothing
775
					break;
776
777
			} // End Switch Statement
778
779
		} // End If Statement
780
781
	} // End sensei_complete_lesson()
782
783
	public function sensei_complete_course() {
784
		global $post,  $current_user, $wp_query;
785
		if ( isset( $_POST['course_complete'] ) && wp_verify_nonce( $_POST[ 'woothemes_sensei_complete_course_noonce' ], 'woothemes_sensei_complete_course_noonce' ) ) {
786
787
			$sanitized_submit = esc_html( $_POST['course_complete'] );
788
			$sanitized_course_id = absint( esc_html( $_POST['course_complete_id'] ) );
789
			// Handle submit data
790
			switch ($sanitized_submit) {
791
				case __( 'Mark as Complete', 'woothemes-sensei' ):
792
793
					// Add user to course
794
					$course_metadata = array(
795
						'start' => current_time('mysql'),
796
						'percent' => 0, // No completed lessons yet
797
						'complete' => 0,
798
					);
799
					$activity_logged = Sensei_Utils::update_course_status( $current_user->ID, $sanitized_course_id, 'in-progress', $course_metadata );
800
801
					if ( $activity_logged ) {
802
						// Get all course lessons
803
						$course_lesson_ids = Sensei()->course->course_lessons( $sanitized_course_id, 'any', 'ids' );
804
						// Mark all quiz user meta lessons as complete
805
						foreach ( $course_lesson_ids as $lesson_item_id ){
806
							// Mark lesson as complete
807
							$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...
808
						} // End For Loop
809
810
						// Update with final stats
811
						$course_metadata = array(
812
							'percent' => 100,
813
							'complete' => count($course_lesson_ids),
814
						);
815
						$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...
816
817
						do_action( 'sensei_user_course_end', $current_user->ID, $sanitized_course_id );
818
819
						// Success message
820
						$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>';
821
					} // End If Statement
822
823
					break;
824
825
				case __( 'Delete Course', 'woothemes-sensei' ):
826
827
					Sensei_Utils::sensei_remove_user_from_course( $sanitized_course_id, $current_user->ID );
828
829
					// Success message
830
					$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>';
831
					break;
832
833
				default:
834
					// Nothing
835
					break;
836
			} // End Switch Statement
837
838
		} // End If Statement
839
	} // End sensei_complete_course()
840
841
	/**
842
	 * @deprecated use WooThemes_Sensei_Quiz::get_user_answers
843
	 * @param int $lesson_id
844
	 * @return array
845
	 */
846
	public function sensei_get_user_quiz_answers( $lesson_id = 0 ) {
847
		global $current_user;
848
849
		$user_answers = array();
850
851
		if ( 0 < intval( $lesson_id ) ) {
852
			$lesson_quiz_questions = Sensei()->lesson->lesson_quiz_questions( $lesson_id );
853
			foreach( $lesson_quiz_questions as $question ) {
854
				$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' ) ) ) );
855
				$user_answers[ $question->ID ] = $answer;
856
			}
857
		}
858
859
		return $user_answers;
860
	} // End sensei_get_user_quiz_answers()
861
862
	public function sensei_has_user_completed_lesson( $post_id = 0, $user_id = 0 ) {
863
		_deprecated_function( __FUNCTION__, '1.7', "WooThemes_Sensei_Utils::user_completed_lesson()" );
864
		return Sensei_Utils::user_completed_lesson( $post_id, $user_id );
865
	} // End sensei_has_user_completed_lesson()
866
867
/**
868
*
869
 */
870
	public function sensei_frontend_messages() {
871
		Sensei()->notices->print_notices();
872
	} // End sensei_frontend_messages()
873
874
	public function sensei_lesson_video( $post_id = 0 ) {
875
		if ( 0 < intval( $post_id ) ) {
876
			$lesson_video_embed = get_post_meta( $post_id, '_lesson_video_embed', true );
877
			if ( 'http' == substr( $lesson_video_embed, 0, 4) ) {
878
        		// V2 - make width and height a setting for video embed
879
        		$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...
880
        	} // End If Statement
881
        	if ( '' != $lesson_video_embed ) {
882
        	?><div class="video"><?php echo html_entity_decode($lesson_video_embed); ?></div><?php
883
        	} // End If Statement
884
        } // End If Statement
885
	} // End sensei_lesson_video()
886
887
	public function sensei_complete_lesson_button() {
888
		global  $post;
889
890
		$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...
891
892
		// Lesson quizzes
893
		$quiz_id = Sensei()->lesson->lesson_quizzes( $post->ID );
894
		$pass_required = true;
895
		if( $quiz_id ) {
896
			// Get quiz pass setting
897
	    	$pass_required = get_post_meta( $quiz_id, '_pass_required', true );
898
	    }
899
		if( ! $quiz_id || ( $quiz_id && ! $pass_required ) ) {
900
			?>
901
			<form class="lesson_button_form" method="POST" action="<?php echo esc_url( get_permalink() ); ?>">
902
	            <input type="hidden"
903
                       name="woothemes_sensei_complete_lesson_noonce"
904
                       id="woothemes_sensei_complete_lesson_noonce"
905
                       value="<?php echo esc_attr( wp_create_nonce( 'woothemes_sensei_complete_lesson_noonce' ) ); ?>"
906
                />
907
908
	            <input type="hidden" name="quiz_action" value="lesson-complete" />
909
910
                <input type="submit"
911
                       name="quiz_complete"
912
                       class="quiz-submit complete"
913
                       value="<?php _e( 'Complete Lesson', 'woothemes-sensei' ); ?>"/>
914
915
	        </form>
916
			<?php
917
		} // End If Statement
918
	} // End sensei_complete_lesson_button()
919
920
	public function sensei_reset_lesson_button() {
921
		global  $post;
922
923
		$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...
924
925
		// Lesson quizzes
926
		$quiz_id = Sensei()->lesson->lesson_quizzes( $post->ID );
927
		$reset_allowed = true;
928
		if( $quiz_id ) {
929
			// Get quiz pass setting
930
			$reset_allowed = get_post_meta( $quiz_id, '_enable_quiz_reset', true );
931
		}
932 View Code Duplication
		if ( ! $quiz_id || !empty($reset_allowed) ) {
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...
933
		?>
934
		<form method="POST" action="<?php echo esc_url( get_permalink() ); ?>">
935
936
            <input
937
            type="hidden"
938
            name="<?php echo esc_attr( 'woothemes_sensei_complete_lesson_noonce' ); ?>"
939
            id="<?php echo esc_attr( 'woothemes_sensei_complete_lesson_noonce' ); ?>"
940
            value="<?php echo esc_attr( wp_create_nonce( 'woothemes_sensei_complete_lesson_noonce' ) ); ?>" />
941
942
            <input type="hidden" name="quiz_action" value="lesson-reset" />
943
944
            <input type="submit" name="quiz_complete" class="quiz-submit reset" value="<?php _e( 'Reset Lesson', 'woothemes-sensei' ); ?>"/>
945
946
        </form>
947
		<?php
948
		} // End If Statement
949
	} // End sensei_reset_lesson_button()
950
951
    /**
952
     * @deprecated since 1.9.0
953
     */
954
    public function sensei_lesson_quiz_meta( ) {
955
956
        Sensei_Lesson::footer_quiz_call_to_action();
957
958
	} // End sensei_lesson_quiz_meta()
959
960
	public function sensei_course_archive_meta() {
961
		global  $post;
962
		// Meta data
963
		$post_id = get_the_ID();
964
		$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...
965
		$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...
966
		$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...
967
		$category_output = get_the_term_list( $post_id, 'course-category', '', ', ', '' );
968
		$free_lesson_count = intval( Sensei()->course->course_lesson_preview_count( $post_id ) );
969
		?><section class="entry">
970
        	<p class="sensei-course-meta">
971 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...
972
		   	<span class="course-author"><?php _e( 'by ', 'woothemes-sensei' ); ?><?php the_author_link(); ?></span>
973
		   	<?php } // End If Statement ?>
974
		   	<span class="course-lesson-count"><?php echo Sensei()->course->course_lesson_count( $post_id ) . '&nbsp;' . __( 'Lessons', 'woothemes-sensei' ); ?></span>
975
		   	<?php if ( '' != $category_output ) { ?>
976
		   	<span class="course-category"><?php echo sprintf( __( 'in %s', 'woothemes-sensei' ), $category_output ); ?></span>
977
		   	<?php } // End If Statement ?>
978
		   	<?php sensei_simple_course_price( $post_id ); ?>
979
        	</p>
980
        	<p class="course-excerpt"><?php the_excerpt(); ?></p>
981 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...
982
                $free_lessons = sprintf( __( 'You can access %d of this course\'s lessons for free', 'woothemes-sensei' ), $free_lesson_count ); ?>
983
                <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>
984
            <?php } ?>
985
		</section><?php
986
	} // End sensei_course_archive_meta()
987
988
    /**
989
     * @deprecated since 1.9.0
990
     */
991
	public function sensei_single_main_content() {
992
	    _deprecated_function('Woothemes_Sensei_Frontend::sensei_single_main_content', '1.9.0');
993
	} // End sensei_single_main_content()
994
995
    /**
996
    * @deprecated since 1.9.0
997
    */
998
	public function sensei_lesson_archive_main_content() {
999
        _deprecated_function('Sensei_Frontend::sensei_lesson_archive_main_content', '1.9.0', 'Please include loop-lesson.php directly');
1000
	} // End sensei_lesson_archive_main_content()
1001
1002
    /**
1003
    * @deprecated since 1.9.0
1004
    */
1005
	public function sensei_message_archive_main_content() {
1006
		_deprecated_function( 'Sensei_Frontend::sensei_message_archive_main_content', 'This method is no longer needed' );
1007
	} // End sensei_lesson_archive_main_content()
1008
1009
    /**
1010
    * @deprecated since 1.9.0
1011
    */
1012
	public function sensei_no_permissions_main_content() {
1013
        _deprecated_function( 'Sensei_Frontend::sensei_no_permissions_main_content', 'This method is no longer needed' );
1014
	} // End sensei_no_permissions_main_content()
1015
1016
	public function sensei_course_category_main_content() {
1017
		global $post;
1018
		if ( have_posts() ) { ?>
1019
1020
			<section id="main-course" class="course-container">
1021
1022
                <?php do_action( 'sensei_course_archive_header' ); ?>
1023
1024
                <?php while ( have_posts() ) { the_post(); ?>
1025
1026
                    <article class="<?php echo join( ' ', get_post_class( array( 'course', 'post' ), get_the_ID() ) ); ?>">
1027
1028
	    			    <?php sensei_do_deprecated_action('sensei_course_image','1.9.0', 'sensei_single_course_content_inside_before', get_the_ID() ); ?>
1029
1030
	    			    <?php sensei_do_deprecated_action( 'sensei_course_archive_course_title','1.9.0','sensei_course_content_inside_before', $post ); ?>
1031
1032
	    			    <?php do_action( 'sensei_course_archive_meta' ); ?>
1033
1034
	    		    </article>
1035
1036
                <?php } // End While Loop ?>
1037
1038
	    	</section>
1039
1040
		<?php } else { ?>
1041
1042
			<p>
1043
1044
                <?php _e( 'No courses found that match your selection.', 'woothemes-sensei' ); ?>
1045
1046
            </p>
1047
1048
		<?php } // End If Statement
1049
1050
	} // End sensei_course_category_main_content()
1051
1052
	public function sensei_login_form() {
1053
		?>
1054
		<div id="my-courses">
1055
			<?php Sensei()->notices->print_notices(); ?>
1056
			<div class="col2-set" id="customer_login">
1057
1058
				<div class="col-1">
1059
					<?php
1060
					// output the actual form markup
1061
                    Sensei_Templates::get_template( 'user/login-form.php');
1062
					?>
1063
				</div>
1064
1065
			<?php
1066
			if ( get_option('users_can_register') ) {
1067
1068
				// get current url
1069
				$action_url = get_permalink();
1070
1071
				?>
1072
1073
				<div class="col-2">
1074
					<h2><?php _e( 'Register', 'woothemes-sensei' ); ?></h2>
1075
1076
					<form method="post" class="register"  action="<?php echo esc_url( $action_url ); ?>" >
1077
1078
						<?php do_action( 'sensei_register_form_start' ); ?>
1079
1080
						<p class="form-row form-row-wide">
1081
							<label for="sensei_reg_username"><?php _e( 'Username', 'woothemes-sensei' ); ?> <span class="required">*</span></label>
1082
							<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'] ); ?>" />
1083
						</p>
1084
1085
						<p class="form-row form-row-wide">
1086
							<label for="sensei_reg_email"><?php _e( 'Email address', 'woothemes-sensei' ); ?> <span class="required">*</span></label>
1087
							<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'] ); ?>" />
1088
						</p>
1089
1090
						<p class="form-row form-row-wide">
1091
							<label for="sensei_reg_password"><?php _e( 'Password', 'woothemes-sensei' ); ?> <span class="required">*</span></label>
1092
							<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'] ); ?>" />
1093
						</p>
1094
1095
						<!-- Spam Trap -->
1096
						<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>
1097
1098
						<?php do_action( 'sensei_register_form_fields' ); ?>
1099
						<?php do_action( 'register_form' ); ?>
1100
1101
						<p class="form-row">
1102
							<input type="submit" class="button" name="register" value="<?php _e( 'Register', 'woothemes-sensei' ); ?>" />
1103
						</p>
1104
1105
						<?php do_action( 'sensei_register_form_end' ); ?>
1106
1107
					</form>
1108
				</div>
1109
				<?php
1110
			}
1111
			?>
1112
			</div>
1113
		</div>
1114
1115
		<?php
1116
	} // End sensei_login_form()
1117
1118
	public function sensei_lesson_meta( $post_id = 0 ) {
1119
		global $post;
1120
		if ( 0 < intval( $post_id ) ) {
1121
		$lesson_course_id = absint( get_post_meta( $post_id, '_lesson_course', true ) );
1122
		?><section class="entry">
1123
            <p class="sensei-course-meta">
1124 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...
1125
			    <span class="course-author"><?php _e( 'by ', 'woothemes-sensei' ); ?><?php the_author_link(); ?></span>
1126
			    <?php } ?>
1127
                <?php if ( 0 < intval( $lesson_course_id ) ) { ?>
1128
                <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>
1129
                <?php } ?>
1130
            </p>
1131
            <p class="lesson-excerpt"><?php the_excerpt( ); ?></p>
1132
		</section><?php
1133
		} // End If Statement
1134
	} // sensei_lesson_meta()
1135
1136
	public function sensei_lesson_preview_title_text( $course_id ) {
1137
1138
		$preview_text = __( ' (Preview)', 'woothemes-sensei' );
1139
1140
		//if this is a paid course
1141
		if ( Sensei_WC::is_woocommerce_active() ) {
1142
    	    $wc_post_id = get_post_meta( $course_id, '_course_woocommerce_product', true );
1143
    	    if ( 0 < $wc_post_id ) {
1144
    	    	$preview_text = __( ' (Free Preview)', 'woothemes-sensei' );
1145
    	    } // End If Statement
1146
    	}
1147
    	return $preview_text;
1148
	}
1149
1150
	public function sensei_lesson_preview_title( $title = '', $id = 0 ) {
1151
		global $post, $current_user;
1152
1153
		// Limit to lessons and check if lesson ID matches filtered post ID
1154
		// @see https://github.com/woothemes/sensei/issues/574
1155
		if( isset( $post->ID ) && $id == $post->ID && 'lesson' == get_post_type( $post ) ) {
1156
1157
			// Limit to main query only
1158
			if( is_main_query() ) {
1159
1160
				// Get the course ID
1161
				$course_id = get_post_meta( $post->ID, '_lesson_course', true );
1162
1163
				// Check if the user is taking the course
1164
				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...
1165
					$title .= ' ' . $this->sensei_lesson_preview_title_text( $course_id );
1166
				}
1167
			}
1168
		}
1169
		return $title;
1170
	} // sensei_lesson_preview_title
1171
1172
	public function sensei_course_start() {
1173
		global $post, $current_user;
1174
1175
		// Check if the user is taking the course
1176
		$is_user_taking_course = Sensei_Utils::user_started_course( $post->ID, $current_user->ID );
1177
		// Handle user starting the course
1178
		if ( isset( $_POST['course_start'] )
1179
		    && wp_verify_nonce( $_POST[ 'woothemes_sensei_start_course_noonce' ], 'woothemes_sensei_start_course_noonce' )
1180
		    && !$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...
1181
1182
			// Start the course
1183
			$activity_logged = Sensei_Utils::user_start_course( $current_user->ID, $post->ID );
1184
			$this->data = new stdClass();
1185
			$this->data->is_user_taking_course = false;
1186
			if ( $activity_logged ) {
1187
				$this->data->is_user_taking_course = true;
1188
1189
				// Refresh page to avoid re-posting
1190
				?>
1191
1192
			    <script type="text/javascript"> window.location = '<?php echo get_permalink( $post->ID ); ?>'; </script>
1193
1194
			    <?php
1195
			} // End If Statement
1196
		} // End If Statement
1197
	} // End sensei_course_start()
1198
1199
    /**
1200
     * @deprecated since 1.9.0
1201
     */
1202
	public function sensei_course_meta() {
1203
        _deprecated_function( 'Sensei_Frontend::sensei_course_meta', '1.9.0' , 'Sensei_Course::the_course_meta()' );
1204
        Sensei()->course->the_course_meta( get_post() );
1205
	} // End sensei_course_meta()
1206
1207
    /**
1208
     * @deprecated since 1.9.0
1209
     */
1210
	public function sensei_course_meta_video() {
1211
        _deprecated_function( 'Sensei_Frontend::sensei_course_meta_video', '1.9.0' , 'Sensei_Course::the_course_video()' );
1212
        Sensei_Course::the_course_video();
1213
	} // End sensei_course_meta_video()
1214
1215
    /**
1216
     * This function shows the WooCommerce cart notice if the user has
1217
     * added the current course to cart. It does not show if the user is already taking
1218
     * the course.
1219
     *
1220
     * @since 1.0.2
1221
     * @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...
1222
     */
1223
    public function sensei_woocommerce_in_cart_message() {
1224
		global $post, $woocommerce;
1225
1226
		$wc_post_id = absint( get_post_meta( $post->ID, '_course_woocommerce_product', true ) );
1227
        $user_course_status_id = Sensei_Utils::user_started_course($post->ID , get_current_user_id() );
1228
		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...
1229
1230
			if ( Sensei_WC::is_product_in_cart( $wc_post_id ) ) {
1231
				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>' );
1232
			} // End If Statement
1233
1234
		} // End If Statement
1235
1236
	} // End sensei_woocommerce_in_cart_message()
1237
1238
	// Deprecated
1239
	public function sensei_lesson_comment_count( $count ) {
1240
		return $count;
1241
	} // End sensei_lesson_comment_count()
1242
1243
	/**
1244
	 * Only show excerpts for lessons and courses in search results
1245
	 * @param  string $content Original content
1246
	 * @return string          Modified content
1247
	 */
1248
	public function sensei_search_results_excerpt( $content ) {
1249
		global $post;
1250
1251
		if( is_search() && in_array( $post->post_type, array( 'course', 'lesson' ) ) ) {
1252
			$content = '<p class="course-excerpt">' . the_excerpt( ) . '</p>';
1253
		}
1254
1255
		return $content;
1256
	} // End sensei_search_results_excerpt()
1257
1258
	/**
1259
	 * Remove active course when an order is refunded or cancelled
1260
	 * @param  integer $order_id ID of order
1261
	 * @return void
1262
	 */
1263
	public function remove_active_course( $order_id ) {
1264
		$order = new WC_Order( $order_id );
1265
1266
		foreach ( $order->get_items() as $item ) {
1267
			if ( isset( $item['variation_id'] ) && ( 0 < $item['variation_id'] ) ) {
1268
				// If item has variation_id then its a variation of the product
1269
				$item_id = $item['variation_id'];
1270
			} else {
1271
				// Than its real product set it's id to item_id
1272
				$item_id = $item['product_id'];
1273
			} 
1274
1275
            if ( $item_id > 0 ) {
1276
1277
				$user_id = get_post_meta( $order_id, '_customer_user', true );
1278
1279
				if( $user_id ) {
1280
1281
					// Get all courses for product
1282
					$args = array(
1283
						'posts_per_page' => -1,
1284
						'post_type' => 'course',
1285
						'meta_query' => array(
1286
							array(
1287
								'key' => '_course_woocommerce_product',
1288
								'value' => $item_id
1289
							)
1290
						),
1291
						'orderby' => 'menu_order date',
1292
						'order' => 'ASC',
1293
						'fields' => 'ids',
1294
					);
1295
					$course_ids = get_posts( $args );
1296
1297
					if( $course_ids && count( $course_ids ) > 0 ) {
1298
						foreach( $course_ids as $course_id ) {
1299
1300
							// Remove all course user meta
1301
							Sensei_Utils::sensei_remove_user_from_course( $course_id, $user_id );
1302
1303
						} // End For Loop
1304
					} // End If Statement
1305
				} // End If Statement
1306
			} // End If Statement
1307
		} // End For Loop
1308
	} // End remove_active_course()
1309
1310
1311
	/**
1312
	 * Activate all purchased courses for user
1313
	 * @since  1.4.8
1314
	 * @param  integer $user_id User ID
1315
	 * @return void
1316
	 */
1317
	public function activate_purchased_courses( $user_id = 0 ) {
1318
1319
		if( $user_id ) {
1320
1321
			if( Sensei_WC::is_woocommerce_active() ) {
1322
1323
				// Get all user's orders
1324
				$order_args = array(
1325
					'post_type' => 'shop_order',
1326
					'post_status' =>  array( 'wc-processing', 'wc-completed' ),
1327
					'posts_per_page' => -1,
1328
					'meta_query' => array(
1329
						array(
1330
							'key' => '_customer_user',
1331
							'value' => $user_id
1332
						)
1333
					),
1334
				);
1335
1336
				$orders = get_posts( $order_args );
1337
1338
				$product_ids = array();
1339
				$order_ids = array();
1340
1341
				foreach( $orders as $post_id ) {
1342
1343
					// Only process each order once
1344
					$processed = get_post_meta( $post_id, 'sensei_products_processed', true );
1345
1346
					if( $processed && $processed == 'processed' ) {
1347
						continue;
1348
					}
1349
1350
					// Get course product IDs from order
1351
					$order = new WC_Order( $post_id );
1352
1353
					$items = $order->get_items();
1354
					foreach( $items as $item ) {
1355
                                            if (isset($item['variation_id']) && $item['variation_id'] > 0) {
1356
                                                $item_id = $item['variation_id'];
1357
                                                $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...
1358
                                            } else {
1359
                                                $item_id = $item['product_id'];
1360
                                            }
1361
1362
                                            $product_ids[] = $item_id;
1363
                                            }
1364
1365
					$order_ids[] = $post_id;
1366
				}
1367
1368
				if( count( $product_ids ) > 0 ) {
1369
1370
					// Get all courses from user's orders
1371
					$course_args = array(
1372
						'post_type' => 'course',
1373
						'posts_per_page' => -1,
1374
						'meta_query' => array(
1375
							array(
1376
								'key' => '_course_woocommerce_product',
1377
								'value' => $product_ids,
1378
								'compare' => 'IN'
1379
							)
1380
						),
1381
						'orderby' => 'menu_order date',
1382
						'order' => 'ASC',
1383
						'fields' => 'ids',
1384
					);
1385
					$course_ids = get_posts( $course_args );
1386
1387
					foreach( $course_ids as $course_id ) {
1388
1389
						$user_course_status = Sensei_Utils::user_course_status( intval($course_id), $user_id );
1390
1391
						// Ignore course if already completed
1392
						if( Sensei_Utils::user_completed_course( $user_course_status ) ) {
1393
							continue;
1394
						}
1395
1396
						// Ignore course if already started
1397
						if( $user_course_status ) {
1398
							continue;
1399
						}
1400
1401
						// Mark course as started by user
1402
						Sensei_Utils::user_start_course( $user_id, $course_id );
1403
					}
1404
				}
1405
1406
				if( count( $order_ids ) > 0 ) {
1407
					foreach( $order_ids as $order_id ) {
1408
						// Mark order as processed
1409
						update_post_meta( $order_id, 'sensei_products_processed', 'processed' );
1410
					}
1411
				}
1412
			}
1413
		}
1414
	} // End activate_purchased_courses()
1415
1416
	/**
1417
	 * Activate single course if already purchases
1418
	 * @return void
1419
	 */
1420
	public function activate_purchased_single_course() {
1421
		global $post, $current_user;
1422
1423
		if( Sensei_WC::is_woocommerce_active() ) {
1424
1425
			if( ! is_user_logged_in() ) return;
1426
			if( ! isset( $post->ID ) ) return;
1427
1428
			$user_id = $current_user->ID;
1429
			$course_id = $post->ID;
1430
			$course_product_id = (int) get_post_meta( $course_id, '_course_woocommerce_product', true );
1431
			if( ! $course_product_id ) {
1432
				return;
1433
			}
1434
1435
			$user_course_status = Sensei_Utils::user_course_status( intval($course_id), $user_id );
1436
1437
			// Ignore course if already completed
1438
			if( Sensei_Utils::user_completed_course( $user_course_status ) ) {
1439
1440
				return;
1441
			}
1442
1443
			// Ignore course if already started
1444
			if( $user_course_status ) {
1445
				return;
1446
			}
1447
1448
			// Get all user's orders
1449
			$order_args = array(
1450
				'post_type' => 'shop_order',
1451
				'posts_per_page' => -1,
1452
				'post_status' => array( 'wc-processing', 'wc-completed' ),
1453
				'meta_query' => array(
1454
					array(
1455
						'key' => '_customer_user',
1456
						'value' => $user_id
1457
					)
1458
				),
1459
				'fields' => 'ids',
1460
			);
1461
			$orders = get_posts( $order_args );
1462
1463
			foreach( $orders as $order_post_id ) {
1464
1465
				// Get course product IDs from order
1466
				$order = new WC_Order( $order_post_id );
1467
1468
				$items = $order->get_items();
1469
				foreach( $items as $item ) {
1470
1471
                    $product = wc_get_product( $item['product_id'] );
1472
1473
                    // handle product bundles
1474
                    if( is_object( $product ) &&  $product->is_type('bundle') ){
1475
1476
                        $bundled_product = new WC_Product_Bundle( $product->id );
1477
                        $bundled_items = $bundled_product->get_bundled_items();
1478
1479
                        foreach( $bundled_items as $bundled_item ){
1480
1481
                            if( $bundled_item->product_id == $course_product_id ) {
1482
                                Sensei_Utils::user_start_course( $user_id, $course_id );
1483
                                return;
1484
                            }
1485
1486
                        }
1487
1488
                    } else {
1489
1490
                    // handle regular products
1491
                        if( $item['product_id'] == $course_product_id ) {
1492
                            Sensei_Utils::user_start_course( $user_id, $course_id );
1493
                            return;
1494
                        }
1495
1496
                    }
1497
				}
1498
			}
1499
1500
		}
1501
	} // End activate_purchased_single_course()
1502
1503
	/**
1504
	 * Hide Sensei activity comments from frontend (requires WordPress 4.0+)
1505
	 * @param  array  $args Default arguments
1506
	 * @return array        Modified arguments
1507
	 */
1508
	public function hide_sensei_activity( $args = array() ) {
1509
1510
		if( is_singular( 'lesson' ) || is_singular( 'course' ) ) {
1511
			$args['type'] = 'comment';
1512
		}
1513
1514
		return $args;
1515
	} // End hide_sensei_activity()
1516
1517
	/**
1518
	 * Redirect failed login attempts to the front end login page
1519
	 * in the case where the login fields are not left empty
1520
	 *
1521
	 * @return void redirect
1522
	 */
1523
	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...
1524
1525
		//if not posted from the sensei login form let
1526
		// WordPress or any other party handle the failed request
1527
	    if( ! isset( $_REQUEST['form'] ) || 'sensei-login' != $_REQUEST['form']  ){
1528
1529
	    	return ;
1530
1531
	    }
1532
1533
    	// Get the reffering page, where did the post submission come from?
1534
    	$referrer = add_query_arg('login', false, $_SERVER['HTTP_REFERER']);
1535
1536
   		 // if there's a valid referrer, and it's not the default log-in screen
1537
	    if(!empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin')){
1538
	        // let's append some information (login=failed) to the URL for the theme to use
1539
	        wp_redirect( esc_url_raw( add_query_arg('login', 'failed',  $referrer) ) );
1540
	    	exit;
1541
    	}
1542
	}// End sensei_login_fail_redirect_to_front_end_login
1543
1544
	/**
1545
	 * Handle the login reques from all sensei intiated login forms.
1546
	 *
1547
	 * @return void redirect
1548
	 */
1549
	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...
1550
1551
		// Check that it is a sensei login request and if it has a valid nonce
1552
	    if(  isset( $_REQUEST['form'] ) && 'sensei-login' == $_REQUEST['form'] ) {
1553
1554
	    	// Validate the login request nonce
1555
		    if( !wp_verify_nonce( $_REQUEST['_wpnonce'], 'sensei-login' ) ){
1556
		    	return;
1557
		    }
1558
1559
		    //get the page where the sensei log form is located
1560
		    $referrer = $_REQUEST['_wp_http_referer'];
1561
		    //$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...
1562
1563
		    if ( ( isset( $_REQUEST['log'] ) && !empty( $_REQUEST['log'] ) )
1564
		    	 && ( isset( $_REQUEST['pwd'] ) && !empty( $_REQUEST['pwd'] ) ) ){
1565
1566
		    	// when the user has entered a password or username do the sensei login
1567
		    	$creds = array();
1568
1569
		    	// check if the requests login is an email address
1570
		    	if( is_email(  trim( $_REQUEST['log'] ) )  ){
1571
		    		// query wordpress for the users details
1572
		    		$user =	get_user_by( 'email', sanitize_email( $_REQUEST['log'] )  );
1573
1574
		    		// validate the user object
1575
		    		if( !$user ){
1576
1577
		    			// the email doesnt exist
1578
                        wp_redirect( esc_url_raw( add_query_arg('login', 'failed', $referrer) ) );
1579
		        		exit;
1580
1581
		    		}
1582
1583
		    		//assigne the username to the creds array for further processing
1584
		    		$creds['user_login'] =  $user->user_login ;
1585
1586
		    	}else{
1587
1588
		    		// process this as a default username login
1589
		    		$creds['user_login'] = sanitize_text_field( $_REQUEST['log'] ) ;
1590
1591
		    	}
1592
1593
				// get setup the rest of the creds array
1594
				$creds['user_password'] = sanitize_text_field( $_REQUEST['pwd'] );
1595
				$creds['remember'] = isset( $_REQUEST['rememberme'] ) ? true : false ;
1596
1597
				//attempt logging in with the given details
1598
				$user = wp_signon( $creds, false );
1599
1600
				if ( is_wp_error($user) ){ // on login failure
1601
                    wp_redirect( esc_url_raw( add_query_arg('login', 'failed', $referrer) ) );
1602
                    exit;
1603
				}else{ // on login success
1604
1605
					/**
1606
					* change the redirect url programatically
1607
					*
1608
					* @since 1.6.1
1609
					*
1610
					* @param string $referrer the page where the current url wheresensei login form was posted from
1611
					*/
1612
1613
					$success_redirect_url = apply_filters('sesei_login_success_redirect_url', remove_query_arg( 'login', $referrer ) );
1614
1615
					wp_redirect( esc_url_raw( $success_redirect_url ) );
1616
		        	exit;
1617
1618
				}	// 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...
1619
1620
		    }else{ // if username or password is empty
1621
1622
                wp_redirect( esc_url_raw( add_query_arg('login', 'emptyfields', $referrer) ) );
1623
		        exit;
1624
1625
		    } // 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...
1626
1627
	    }elseif( ( isset( $_GET['login'] ) ) ) {
1628
	    	// else if this request is a redircect from a previously faile login request
1629
	    	$this->login_message_process();
1630
1631
			//exit the handle login request function
1632
			return;
1633
	    }
1634
1635
	    // if none of the above
1636
	    return;
1637
1638
	} // End  sensei_login_fail_redirect_to_front_end_login
1639
1640
	/**
1641
	 * handle sensei specific registration requests
1642
	 *
1643
	 * @return void redirect
1644
	 *
1645
	 */
1646
	public function sensei_process_registration(){
1647
		global 	 $current_user;
1648
		// check the for the sensei specific registration requests
1649
		if( !isset( $_POST['sensei_reg_username'] ) && ! isset( $_POST['sensei_reg_email'] ) && !isset( $_POST['sensei_reg_password'] )){
1650
			// exit if this is not a sensei registration request
1651
			return ;
1652
		}
1653
		// check for spam throw cheating huh
1654
		if( isset( $_POST['email_2'] ) &&  '' !== $_POST['email_2']   ){
1655
			$message = 'Error:  The spam field should be empty';
1656
			Sensei()->notices->add_notice( $message, 'alert');
1657
			return;
1658
		}
1659
1660
		// retreive form variables
1661
		$new_user_name		= sanitize_user( $_POST['sensei_reg_username'] );
1662
		$new_user_email		= $_POST['sensei_reg_email'];
1663
		$new_user_password	= $_POST['sensei_reg_password'];
1664
1665
		// Check the username
1666
		$username_error_notice = '';
1667
		if ( $new_user_name == '' ) {
1668
			$username_error_notice =  __( '<strong>ERROR</strong>: Please enter a username.' );
1669
		} elseif ( ! validate_username( $new_user_name ) ) {
1670
			$username_error_notice =  __( '<strong>ERROR</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' );
1671
		} elseif ( username_exists( $new_user_name ) ) {
1672
			$username_error_notice =  __( '<strong>ERROR</strong>: This username is already registered. Please choose another one.' );
1673
		}
1674
1675
		// exit on username error
1676
		if( '' !== $username_error_notice ){
1677
			Sensei()->notices->add_notice( $username_error_notice , 'alert');
1678
			return;
1679
		}
1680
1681
		// Check the e-mail address
1682
		$email_error_notice = '';
1683
		if ( $new_user_email == '' ) {
1684
			$email_error_notice = __( '<strong>ERROR</strong>: Please type your e-mail address.' );
1685
		} elseif ( ! is_email( $new_user_email ) ) {
1686
			$email_error_notice = __( '<strong>ERROR</strong>: The email address isn&#8217;t correct.' );
1687
		} elseif ( email_exists( $new_user_email ) ) {
1688
			$email_error_notice = __( '<strong>ERROR</strong>: This email is already registered, please choose another one.' );
1689
		}
1690
1691
		// exit on email address error
1692
		if( '' !== $email_error_notice ){
1693
			Sensei()->notices->add_notice( $email_error_notice , 'alert');
1694
			return;
1695
		}
1696
1697
		//check user password
1698
1699
		// exit on email address error
1700
		if( empty( $new_user_password ) ){
1701
			Sensei()->notices->add_notice(  __( '<strong>ERROR</strong>: The password field may not be empty, please enter a secure password.' )  , 'alert');
1702
			return;
1703
		}
1704
1705
		// register user
1706
		$user_id = wp_create_user( $new_user_name, $new_user_password, $new_user_email );
1707
		if ( ! $user_id || is_wp_error( $user_id ) ) {
1708
			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');
1709
		}
1710
1711
		// notify the user
1712
		wp_new_user_notification( $user_id, $new_user_password );
1713
1714
		// set global current user aka log the user in
1715
		$current_user = get_user_by( 'id', $user_id );
1716
		wp_set_auth_cookie( $user_id, true );
1717
1718
		// Redirect
1719
		global $wp;
1720
		if ( wp_get_referer() ) {
1721
			$redirect = esc_url( wp_get_referer() );
1722
		} else {
1723
			$redirect = esc_url( home_url( $wp->request ) );
1724
		}
1725
1726
		wp_redirect( apply_filters( 'sensei_registration_redirect', $redirect ) );
1727
		exit;
1728
1729
	} // 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...
1730
1731
	/**
1732
	 * login_message_process(). handle the login message displayed on faile login
1733
	 *
1734
	 * @return void redirect
1735
	 * @since 1.7.0
1736
	 */
1737
	public function login_message_process(){
1738
1739
            // setup the message variables
1740
			$message = '';
1741
1742
			//only output message if the url contains login=failed and login=emptyfields
1743
1744
			if( $_GET['login'] == 'failed' ){
1745
1746
				$message = __('Incorrect login details', 'woothemes-sensei' );
1747
1748
			}elseif( $_GET['login'] == 'emptyfields'  ){
1749
1750
				$message= __('Please enter your username and password', 'woothemes-sensei' );
1751
			}
1752
1753
			Sensei()->notices->add_notice( $message, 'alert');
1754
1755
	}// end login_message_process
1756
1757
1758
    /**
1759
     * sensei_show_admin_bar(). Use WooCommerce filter
1760
     * to show admin bar to Teachers as well.
1761
     *
1762
     * @return void redirect
1763
     *
1764
     */
1765
    public function sensei_show_admin_bar () {
1766
1767
        if (current_user_can('edit_courses')) {
1768
1769
            add_filter( 'woocommerce_disable_admin_bar', '__return_false', 10, 1);
1770
1771
        }
1772
1773
    }
1774
1775
} // End Class
1776
1777
/**
1778
 * Class WooThemes_Sensei_Frontend
1779
 * @ignore only for backward compatibility
1780
 * @since 1.9.0
1781
 */
1782
class WooThemes_Sensei_Frontend extends Sensei_Frontend{}
1783