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

Sensei_Main::load_hooks()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 36
rs 8.8571
cc 1
eloc 20
nc 1
nop 0
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
4
/**
5
 * Sensei_Main
6
 *
7
 * The main class for sensei.
8
 *
9
 * @package WordPress
10
 * @subpackage Sensei
11
 * @category Core
12
 * @author WooThemes
13
 * @since 1.0.0
14
 */
15
class Sensei_Main {
16
17
    /**
18
     * @var string
19
     * Reference to the main plugin file
20
     */
21
    private $file;
22
23
    /**
24
     * @var Sensei_Main $_instance to the the main and only instance of the Sensei class.
25
     * @since 1.8.0
26
     */
27
    protected static $_instance = null;
28
29
    /**
30
     * Main reference to the plugins current version
31
     */
32
    public $version;
33
34
    /**
35
     * Public token, referencing for the text domain.
36
     */
37
    public $token = 'woothemes-sensei';
38
39
    /**
40
     * Plugin url and path for use when access resources.
41
     */
42
    public $plugin_url;
43
    public $plugin_path;
44
    public $template_url;
45
46
    /**
47
     * @var Sensei_PostTypes
48
     * All Sensei sub classes. Currently used to access functionality contained within
49
     * within Sensei sub classes e.g. Sensei()->course->all_courses()
50
     */
51
    public $post_types;
52
53
    /**
54
     * @var WooThemes_Sensei_Settings
55
     */
56
    public $settings;
57
58
    /**
59
     * @var WooThemes_Sensei_Course_Results
60
     */
61
    public $course_results;
62
63
    /**
64
     * @var Sensei_Updates
65
     */
66
    public $updates;
67
    /**
68
     * @var WooThemes_Sensei_Course
69
     */
70
    public $course;
71
72
    /**
73
     * @var WooThemes_Sensei_Lesson
74
     */
75
    public $lesson;
76
77
    /**
78
     * @var WooThemes_Sensei_Quiz
79
     */
80
    public $quiz;
81
82
    /**
83
     * @var WooThemes_Sensei_Question
84
     */
85
    public $question;
86
87
    /**
88
     * @var WooThemes_Sensei_Admin
89
     */
90
    public $admin;
91
92
    /**
93
     * @var WooThemes_Sensei_Frontend
94
     */
95
    public $frontend;
96
97
    /**
98
     * @var Sensei_Notices
99
     */
100
    public $notices;
101
102
    /**
103
     * @var WooThemes_Sensei_Grading
104
     */
105
    public $grading;
106
107
    /**
108
     * @var WooThemes_Sensei_Emails
109
     */
110
    public $emails;
111
112
    /**
113
     * @var WooThemes_Sensei_Learner_Profiles
114
     */
115
    public $learner_profiles;
116
117
    /**
118
     * @var Sensei_Teacher
119
     */
120
    public $teacher;
121
122
    /**
123
     * @var WooThemes_Sensei_Learners
124
     */
125
    public $learners;
126
127
    /**
128
     * @var array
129
     * Global instance for access to the permissions message shown
130
     * when users do not have the right privileges to access resources.
131
     */
132
    public $permissions_message;
133
134
    /**
135
     * @var Sensei_Core_Modules Sensei Modules functionality
136
     */
137
    public $modules;
138
139
    /**
140
     * @var Sensei_Analysis
141
     */
142
    public $analysis;
143
144
    /**
145
     * Constructor method.
146
     * @param  string $file The base file of the plugin.
147
     * @since  1.0.0
148
     */
149
    public function __construct ( $file ) {
150
151
        // Setup object data
152
        $this->file = $file;
153
        $this->plugin_url = trailingslashit( plugins_url( '', $plugin = $file ) );
154
        $this->plugin_path = trailingslashit( dirname( $file ) );
155
        $this->template_url	= apply_filters( 'sensei_template_url', 'sensei/' );
156
        $this->permissions_message = array( 'title' => __( 'Permission Denied', 'woothemes-sensei' ), 'message' => __( 'Unfortunately you do not have permissions to access this page.', 'woothemes-sensei' ) );
157
158
        // Initialize the core Sensei functionality
159
        $this->init();
160
161
        // Installation
162
        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) $this->install();
163
164
        // Run this on activation.
165
        register_activation_hook( $this->file, array( $this, 'activation' ) );
166
167
        // load the classes need throughout sensei
168
        $this->initialize_global_objects();
169
170
        // Image Sizes
171
        $this->init_image_sizes();
172
173
        // Force WooCommerce Required Settings
174
        $this->set_woocommerce_functionality();
175
176
        // load all hooks
177
        $this->load_hooks();
178
179
    } // End __construct()
180
181
    /**
182
     * Load the foundations of Sensei.
183
     * @since 1.9.0
184
     */
185
    protected function init(){
186
187
        // Localisation
188
        $this->load_plugin_textdomain();
189
        add_action( 'init', array( $this, 'load_localisation' ), 0 );
190
191
        // load the shortcode loader into memory, so as to listen to all for
192
        // all shortcodes on the front end
193
        new Sensei_Shortcode_Loader();
194
195
    }
196
197
    /**
198
     * Global Sensei Instance
199
     *
200
     * Ensure that only one instance of the main Sensei class can be loaded.
201
     *
202
     * @since 1.8.0
203
     * @static
204
     * @see WC()
205
     * @return WooThemes_Sensei Instance.
206
     */
207
    public static function instance() {
208
209
        if ( is_null( self::$_instance ) ) {
210
211
            //Sensei requires a reference to the main Sensei plugin file
212
            $sensei_main_plugin_file = dirname ( dirname( __FILE__ ) ) . '/woothemes-sensei.php';
213
214
            self::$_instance = new self( $sensei_main_plugin_file  );
215
216
        }
217
218
        return self::$_instance;
219
220
    } // end instance()
221
222
    /**
223
     * This function is linked into the activation
224
     * hook to reset flush the urls to ensure Sensei post types show up.
225
     *
226
     * @since 1.9.0
227
     *
228
     * @param $plugin
229
     */
230
    public static function activation_flush_rules( $plugin ){
231
232
        if( strpos( $plugin, '/woothemes-sensei.php' ) > 0  ){
233
234
            flush_rewrite_rules(true);
235
236
        }
237
238
    }
239
240
    /**
241
     * Cloning is forbidden.
242
     * @since 1.8.0
243
     */
244
    public function __clone() {
245
        _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'woothemes-sensei' ), '2.1' );
246
    }
247
248
    /**
249
     * Unserializing instances of this class is forbidden.
250
     * @since 1.8.0
251
     */
252
    public function __wakeup() {
253
        _doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'woothemes-sensei' ), '2.1' );
254
    }
255
256
    /**
257
     * Load the properties for the main Sensei object
258
     *
259
     * @since 1.9.0
260
     */
261
    public function initialize_global_objects(){
262
263
        // Setup post types.
264
        $this->post_types = new Sensei_PostTypes();
265
266
        // Lad the updates class
267
        $this->updates = new Sensei_Updates( $this );
0 ignored issues
show
Documentation introduced by
$this is of type this<Sensei_Main>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
268
269
        // Setup settings
270
        $this->settings = new Sensei_Settings();
271
272
        // Load Course Results Class
273
        $this->course_results = new Sensei_Course_Results();
274
275
        // Load the teacher role
276
        $this->teacher = new Sensei_Teacher();
277
278
        // Add the Course class
279
        $this->course = $this->post_types->course;
0 ignored issues
show
Documentation Bug introduced by
$this->post_types->course is of type object<Sensei_Course>, but the property $course was declared to be of type object<WooThemes_Sensei_Course>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
280
281
        // Add the lesson class
282
        $this->lesson = $this->post_types->lesson;
0 ignored issues
show
Documentation Bug introduced by
$this->post_types->lesson is of type object<Sensei_Lesson>, but the property $lesson was declared to be of type object<WooThemes_Sensei_Lesson>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
283
284
        // Add the question class
285
        $this->question = $this->post_types->question;
0 ignored issues
show
Documentation Bug introduced by
$this->post_types->question is of type object<Sensei_Question>, but the property $question was declared to be of type object<WooThemes_Sensei_Question>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
286
287
        //Add the quiz class
288
        $this->quiz = $this->post_types->quiz;
0 ignored issues
show
Documentation Bug introduced by
$this->post_types->quiz is of type object<Sensei_Quiz>, but the property $quiz was declared to be of type object<WooThemes_Sensei_Quiz>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
289
290
        // load the modules class after all plugsin are loaded
291
        add_action( 'plugins_loaded', array( $this, 'load_modules_class' ) );
292
293
        // Load Learner Management Functionality
294
        $this->learners = new Sensei_Learner_Management( $this->file );
295
296
        // Differentiate between administration and frontend logic.
297
        if ( is_admin() ) {
298
299
            // Load Admin Welcome class
300
            new Sensei_Welcome();
301
302
            // Load Admin Class
303
            $this->admin = new Sensei_Admin( $this->file );
0 ignored issues
show
Unused Code introduced by
The call to Sensei_Admin::__construct() has too many arguments starting with $this->file.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
304
305
            // Load Analysis Reports
306
            $this->analysis = new Sensei_Analysis( $this->file );
307
308
        } else {
309
310
            // Load Frontend Class
311
            $this->frontend = new Sensei_Frontend();
312
313
            // Load notice Class
314
            $this->notices = new Sensei_Notices();
315
316
        }
317
318
        // Load Grading Functionality
319
        $this->grading = new Sensei_Grading( $this->file );
320
321
        // Load Email Class
322
        $this->emails = new Sensei_Emails( $this->file );
323
324
        // Load Learner Profiles Class
325
        $this->learner_profiles = new Sensei_Learner_Profiles();
326
327
    }
328
329
    /**
330
     * Initialize all Sensei hooks
331
     *
332
     * @since 1.9.0
333
     */
334
    public function load_hooks(){
335
336
        add_action( 'widgets_init', array( $this, 'register_widgets' ) );
337
        add_action( 'after_setup_theme', array( $this, 'ensure_post_thumbnails_support' ) );
338
339
        // WooCommerce Payment Actions
340
        add_action( 'woocommerce_payment_complete' , array( $this, 'sensei_woocommerce_complete_order' ) );
341
        add_action( 'woocommerce_thankyou' , array( $this, 'sensei_woocommerce_complete_order' ) );
342
        add_action( 'woocommerce_order_status_completed' , array( $this, 'sensei_woocommerce_complete_order' ) );
343
        add_action( 'woocommerce_order_status_processing' , array( $this, 'sensei_woocommerce_complete_order' ) );
344
        add_action( 'woocommerce_order_status_cancelled' , array( $this, 'sensei_woocommerce_cancel_order' ) );
345
        add_action( 'woocommerce_order_status_refunded' , array( $this, 'sensei_woocommerce_cancel_order' ) );
346
        add_action( 'subscriptions_activated_for_order', array( $this, 'sensei_activate_subscription' ) );
347
348
        // WooCommerce Subscriptions Actions
349
        add_action( 'reactivated_subscription', array( $this, 'sensei_woocommerce_reactivate_subscription' ), 10, 2 );
350
        add_action( 'subscription_expired' , array( $this, 'sensei_woocommerce_subscription_ended' ), 10, 2 );
351
        add_action( 'subscription_end_of_prepaid_term' , array( $this, 'sensei_woocommerce_subscription_ended' ), 10, 2 );
352
        add_action( 'cancelled_subscription' , array( $this, 'sensei_woocommerce_subscription_ended' ), 10, 2 );
353
        add_action( 'subscription_put_on-hold' , array( $this, 'sensei_woocommerce_subscription_ended' ), 10, 2 );
354
355
        // Add Email link to course orders
356
        add_action( 'woocommerce_email_after_order_table', array( $this, 'sensei_woocommerce_email_course_details' ), 10, 1 );
357
358
        // Filter comment counts
359
        add_filter( 'wp_count_comments', array( $this, 'sensei_count_comments' ), 10, 2 );
360
361
        add_action( 'body_class', array( $this, 'body_class' ) );
362
363
        // Check for and activate JetPack LaTeX support
364
        add_action( 'plugins_loaded', array( $this, 'jetpack_latex_support'), 200 ); // Runs after Jetpack has loaded it's modules
365
366
        // check flush the rewrite rules if the option sensei_flush_rewrite_rules option is 1
367
        add_action( 'init', array( $this, 'flush_rewrite_rules'), 101 );
368
369
    }
370
371
    /**
372
     * Run Sensei updates.
373
     * @access  public
374
     * @since   1.1.0
375
     * @return  void
376
     */
377
    public function run_updates() {
378
        // Run updates if administrator
379
        if ( current_user_can( 'manage_options' ) || current_user_can( 'manage_sensei' ) ) {
380
381
            $this->updates->update();
382
383
        } // End If Statement
384
    } // End run_updates()
385
386
387
388
    /**
389
     * Setup required WooCommerce settings.
390
     * @access  public
391
     * @since   1.1.0
392
     * @return  void
393
     */
394
    public function set_woocommerce_functionality() {
395
        // Disable guest checkout if a course is in the cart as we need a valid user to store data for
396
        add_filter( 'pre_option_woocommerce_enable_guest_checkout', array( $this, 'disable_guest_checkout' ) );
397
398
        // Mark orders with virtual products as complete rather then stay processing
399
        add_filter( 'woocommerce_payment_complete_order_status', array( $this, 'virtual_order_payment_complete' ), 10, 2 );
400
401
    } // End set_woocommerce_functionality()
402
403
    /**
404
     * Disable guest checkout if a course product is in the cart
405
     * @param  boolean $guest_checkout Current guest checkout setting
406
     * @return boolean                 Modified guest checkout setting
407
     */
408
    public function disable_guest_checkout( $guest_checkout ) {
409
        global $woocommerce;
410
411
        if( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
412
413
            if( isset( $woocommerce->cart->cart_contents ) && count( $woocommerce->cart->cart_contents ) > 0 ) {
414
                foreach( $woocommerce->cart->cart_contents as $cart_key => $product ) {
415
                    if( isset( $product['product_id'] ) ) {
416
                        $args = array(
417
                            'posts_per_page' => -1,
418
                            'post_type' => 'course',
419
                            'meta_query' => array(
420
                                array(
421
                                    'key' => '_course_woocommerce_product',
422
                                    'value' => $product['product_id']
423
                                )
424
                            )
425
                        );
426
                        $posts = get_posts( $args );
427
                        if( $posts && count( $posts ) > 0 ) {
428
                            foreach( $posts as $course ) {
429
                                $guest_checkout = '';
430
                                break;
431
                            }
432
                        }
433
                    }
434
                }
435
            }
436
        }
437
438
        return $guest_checkout;
439
    }
440
441
    /**
442
     * Change order status with virtual products to completed
443
     * @since  1.1.0
444
     * @param string $order_status
445
     * @param int $order_id
446
     * @return string
447
     **/
448
    public function virtual_order_payment_complete( $order_status, $order_id ) {
449
        $order = new WC_Order( $order_id );
450
        if ( ! isset ( $order ) ) return '';
451
        if ( $order_status == 'wc-processing' && ( $order->post_status == 'wc-on-hold' || $order->post_status == 'wc-pending' || $order->post_status == 'wc-failed' ) ) {
452
            $virtual_order = true;
453
454
            if ( count( $order->get_items() ) > 0 ) {
455
                foreach( $order->get_items() as $item ) {
456
                    if ( $item['product_id'] > 0 ) {
457
                        $_product = $order->get_product_from_item( $item );
458
                        if ( ! $_product->is_virtual() ) {
459
                            $virtual_order = false;
460
                            break;
461
                        } // End If Statement
462
                    } // End If Statement
463
                } // End For Loop
464
            } // End If Statement
465
466
            // virtual order, mark as completed
467
            if ( $virtual_order ) {
468
                return 'completed';
469
            } // End If Statement
470
        } // End If Statement
471
        return $order_status;
472
    }
473
474
    /**
475
     * Register the widgets.
476
     * @access public
477
     * @since  1.0.0
478
     * @return void
479
     */
480
    public function register_widgets () {
481
        // Widget List (key => value is filename => widget class).
482
        $widget_list = apply_filters( 'sensei_registered_widgets_list', array( 	'course-component' 	=> 'Course_Component',
483
                'lesson-component' 	=> 'Lesson_Component',
484
                'course-categories' => 'Course_Categories',
485
                'category-courses' 	=> 'Category_Courses' )
486
        );
487
        foreach ( $widget_list as $key => $value ) {
488
            if ( file_exists( $this->plugin_path . 'widgets/widget-woothemes-sensei-' . $key  . '.php' ) ) {
489
                require_once( $this->plugin_path . 'widgets/widget-woothemes-sensei-' . $key  . '.php' );
490
                register_widget( 'WooThemes_Sensei_' . $value . '_Widget' );
491
            }
492
        } // End For Loop
493
494
        do_action( 'sensei_register_widgets' );
495
496
    } // End register_widgets()
497
498
    /**
499
     * Load the plugin's localisation file.
500
     * @access public
501
     * @since  1.0.0
502
     * @return void
503
     */
504
    public function load_localisation () {
505
        load_plugin_textdomain( 'woothemes-sensei', false, dirname( plugin_basename( $this->file ) ) . '/lang/' );
506
    } // End load_localisation()
507
508
    /**
509
     * Load the plugin textdomain from the main WordPress "languages" folder.
510
     * @access  public
511
     * @since   1.0.0
512
     * @return  void
513
     */
514
    public function load_plugin_textdomain () {
515
        $domain = 'woothemes-sensei';
516
        // The "plugin_locale" filter is also used in load_plugin_textdomain()
517
        $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
518
        load_textdomain( $domain, WP_LANG_DIR . '/' . $domain . '/' . $domain . '-' . $locale . '.mo' );
519
        load_plugin_textdomain( $domain, FALSE, dirname( plugin_basename( $this->file ) ) . '/lang/' );
520
    } // End load_plugin_textdomain()
521
522
    /**
523
     * Run on activation.
524
     * @access public
525
     * @since  1.0.0
526
     * @return void
527
     */
528
    public function activation () {
529
        $this->register_plugin_version();
530
    } // End activation()
531
532
533
    /**
534
     * Register activation hooks.
535
     * @access public
536
     * @since  1.0.0
537
     * @return void
538
     */
539
    public function install () {
540
        register_activation_hook( $this->file, array( $this, 'activate_sensei' ) );
541
        register_activation_hook( $this->file, 'flush_rewrite_rules' );
542
    } // End install()
543
544
545
    /**
546
     * Run on activation of the plugin.
547
     * @access public
548
     * @since  1.0.0
549
     * @return void
550
     */
551
    public function activate_sensei () {
552
        update_option( 'skip_install_sensei_pages', 0 );
553
        update_option( 'sensei_installed', 1 );
554
    } // End activate_sensei()
555
556
    /**
557
     * Register the plugin's version.
558
     * @access public
559
     * @since  1.0.0
560
     * @return void
561
     */
562
    private function register_plugin_version () {
563
        if ( $this->version != '' ) {
564
565
            // Check previous version to see if forced updates must run
566
            // $old_version = get_option( 'woothemes-sensei-version', false );
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% 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...
567
            // if( $old_version && version_compare( $old_version, '1.7.0', '<' )  ) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% 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...
568
            // 	update_option( 'woothemes-sensei-force-updates', $this->version );
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% 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...
569
            // } else {
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
570
            // 	delete_option( 'woothemes-sensei-force-updates' );
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
571
            // }
572
573
            update_option( 'woothemes-sensei-version', $this->version );
574
        }
575
    } // End register_plugin_version()
576
577
    /**
578
     * Ensure that "post-thumbnails" support is available for those themes that don't register it.
579
     * @access  public
580
     * @since   1.0.1
581
     * @return  void
582
     */
583
    public function ensure_post_thumbnails_support () {
584
        if ( ! current_theme_supports( 'post-thumbnails' ) ) { add_theme_support( 'post-thumbnails' ); }
585
    } // End ensure_post_thumbnails_support()
586
587
588
    /**
589
     * template_loader function.
590
     *
591
     * @access public
592
     * @param mixed $template
593
     * @return void
594
     * @deprecated
595
     */
596
    public function template_loader ( $template = '' ) {
597
598
        _deprecated_function( 'Sensei()->template_loader', '1.9.0', 'Use Sensei_Templates::template_loader( $template ) instead' );
599
        Sensei_Templates::template_loader( $template );
600
601
    } // End template_loader()
602
603
    /**
604
     * Determine the relative path to the plugin's directory.
605
     * @access public
606
     * @since  1.0.0
607
     * @return string $sensei_plugin_path
608
     */
609
    public function plugin_path () {
610
611
        if ( $this->plugin_path ) {
612
613
            $sensei_plugin_path =  $this->plugin_path;
614
615
        }else{
616
617
            $sensei_plugin_path = plugin_dir_path( __FILE__ );
618
619
        }
620
621
        return $sensei_plugin_path;
622
623
    } // End plugin_path()
624
625
626
    /**
627
     * Retrieve the ID of a specified page setting.
628
     * @access public
629
     * @since  1.0.0
630
     * @param  string $page
631
     * @return int
632
     */
633
    public function get_page_id ( $page ) {
634
        $page = apply_filters( 'sensei_get_' . esc_attr( $page ) . '_page_id', get_option( 'sensei_' . esc_attr( $page ) . '_page_id' ) );
635
        return ( $page ) ? $page : -1;
636
    } // End get_page_id()
637
638
639
    /**
640
     * If WooCommerce is activated and the customer has purchased the course, update Sensei to indicate that they are taking the course.
641
     * @access public
642
     * @since  1.0.0
643
     * @param  int 			$course_id  (default: 0)
644
     * @param  array/Object $order_user (default: array()) Specific user's data.
0 ignored issues
show
Documentation introduced by
The doc-type array/Object could not be parsed: Unknown type name "array/Object" at position 0. (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...
645
     * @return bool|int
646
     */
647
    public function woocommerce_course_update ( $course_id = 0, $order_user = array()  ) {
648
        global $current_user;
649
650
        if ( ! isset( $current_user ) || !$current_user->ID > 0 ) return false;
651
652
        $data_update = false;
0 ignored issues
show
Unused Code introduced by
$data_update 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...
653
654
        // Get the product ID
655
        $wc_post_id = get_post_meta( intval( $course_id ), '_course_woocommerce_product', true );
656
657
        // Check if in the admin
658
        if ( is_admin() ) {
659
            $user_login = $order_user['user_login'];
0 ignored issues
show
Unused Code introduced by
$user_login 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...
660
            $user_email = $order_user['user_email'];
661
            $user_url = $order_user['user_url'];
0 ignored issues
show
Unused Code introduced by
$user_url 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...
662
            $user_id = $order_user['ID'];
663
        } else {
664
            $user_login = $current_user->user_login;
0 ignored issues
show
Unused Code introduced by
$user_login 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...
665
            $user_email = $current_user->user_email;
666
            $user_url = $current_user->user_url;
0 ignored issues
show
Unused Code introduced by
$user_url 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...
667
            $user_id = $current_user->ID;
668
        } // End If Statement
669
670
        // This doesn't appear to be purely WooCommerce related. Should it be in a separate function?
671
        $course_prerequisite_id = (int) get_post_meta( $course_id, '_course_prerequisite', true );
672
        if( 0 < absint( $course_prerequisite_id ) ) {
673
            $prereq_course_complete = Sensei_Utils::user_completed_course( $course_prerequisite_id, intval( $user_id ) );
674
            if ( ! $prereq_course_complete ) {
675
                // Remove all course user meta
676
                return Sensei_Utils::sensei_remove_user_from_course( $course_id, $user_id );
677
            }
678
        }
679
680
        $is_user_taking_course = Sensei_Utils::user_started_course( intval( $course_id ), intval( $user_id ) );
681
682
        if( ! $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...
683
684
            if ( Sensei_WC::is_woocommerce_active() && Sensei_Utils::sensei_customer_bought_product( $user_email, $user_id, $wc_post_id ) && ( 0 < $wc_post_id ) ) {
0 ignored issues
show
Deprecated Code introduced by
The method Sensei_Utils::sensei_customer_bought_product() has been deprecated with message: since 1.9.0 use Sensei_WC::has_customer_bought_product($user_id, $product_id)

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
685
686
                $activity_logged = Sensei_Utils::user_start_course( intval( $user_id), intval( $course_id ) );
687
688
                $is_user_taking_course = false;
689
                if ( true == $activity_logged ) {
690
                    $is_user_taking_course = true;
691
                } // End If Statement
692
            } // End If Statement
693
        }
694
695
        return $is_user_taking_course;
696
    } // End woocommerce_course_update()
697
698
699
    /**
700
     * check_user_permissions function.
701
     *
702
     * @access public
703
     * @param string $page (default: '')
704
     *
705
     * @return bool
706
     */
707
    public function check_user_permissions ( $page = '' ) {
708
        // REFACTOR
709
        global $current_user, $post;
710
711
        // if use is not logged in
712
        if ( empty( $current_user->caps ) && Sensei()->settings->get('access_permission') ){
713
            $this->permissions_message['title'] = __('Restricted Access', 'woothemes-sensei' );
714
            $this->permissions_message['message'] = sprintf( __('You must be logged in to view this %s'), get_post_type() );
715
            return false;
716
        }
717
718
719
        // Get User Meta
720
        get_currentuserinfo();
721
722
        $user_allowed = false;
723
724
        switch ( $page ) {
725
            case 'course-single':
726
                // check for prerequisite course or lesson,
727
                $course_prerequisite_id = (int) get_post_meta( $post->ID, '_course_prerequisite', true);
728
                $update_course = $this->woocommerce_course_update( $post->ID );
0 ignored issues
show
Unused Code introduced by
$update_course 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...
729
                // Count completed lessons
730
                if ( 0 < absint( $course_prerequisite_id ) ) {
731
732
                    $prerequisite_complete = Sensei_Utils::user_completed_course( $course_prerequisite_id, $current_user->ID );
733
734
                }
735
                else {
736
                    $prerequisite_complete = true;
737
                } // End If Statement
738
                // Handles restrictions
739 View Code Duplication
                if ( !$prerequisite_complete && 0 < absint( $course_prerequisite_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...
740
                    $this->permissions_message['title'] = get_the_title( $post->ID ) . ': ' . __('Restricted Access', 'woothemes-sensei' );
741
                    $course_link = '<a href="' . esc_url( get_permalink( $course_prerequisite_id ) ) . '">' . __( 'course', 'woothemes-sensei' ) . '</a>';
742
                    $this->permissions_message['message'] = sprintf( __('Please complete the previous %1$s before taking this course.', 'woothemes-sensei' ), $course_link );
743
                } else {
744
                    $user_allowed = true;
745
                } // End If Statement
746
                break;
747
            case 'lesson-single':
748
                // Check for WC purchase
749
                $lesson_course_id = get_post_meta( $post->ID, '_lesson_course',true );
750
751
                $update_course = $this->woocommerce_course_update( $lesson_course_id );
0 ignored issues
show
Unused Code introduced by
$update_course 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...
752
                $is_preview = Sensei_Utils::is_preview_lesson( $post->ID );
753
                if ( $this->access_settings() && Sensei_Utils::user_started_course( $lesson_course_id, $current_user->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 true; 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...
754
                    $user_allowed = true;
755
                } elseif( $this->access_settings() && false == $is_preview ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
756
757
                    $user_allowed = true;
758
                } else {
759
                    $this->permissions_message['title'] = get_the_title( $post->ID ) . ': ' . __('Restricted Access', 'woothemes-sensei' );
760
                    $course_link = '<a href="' . esc_url( get_permalink( $lesson_course_id ) ) . '">' . __( 'course', 'woothemes-sensei' ) . '</a>';
761
                    $wc_post_id = get_post_meta( $lesson_course_id, '_course_woocommerce_product',true );
762
                    if ( Sensei_WC::is_woocommerce_active() && ( 0 < $wc_post_id ) ) {
763 View Code Duplication
                        if ( $is_preview ) {
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...
764
                            $this->permissions_message['message'] = sprintf( __('This is a preview lesson. Please purchase the %1$s to access all lessons.', 'woothemes-sensei' ), $course_link );
765
                        } else {
766
                            $this->permissions_message['message'] =  sprintf( __('Please purchase the %1$s before starting this Lesson.', 'woothemes-sensei' ), $course_link );
767
                        }
768 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...
769
                        if ( $is_preview ) {
770
                            $this->permissions_message['message'] = sprintf( __('This is a preview lesson. Please sign up for the %1$s to access all lessons.', 'woothemes-sensei' ), $course_link );
771
                        } else {
772
                            /** This filter is documented in class-woothemes-sensei-frontend.php */
773
                            $this->permissions_message['message'] =  sprintf( __( 'Please sign up for the %1$s before starting the lesson.', 'woothemes-sensei' ), $course_link );
774
                        }
775
                    } // End If Statement
776
                } // End If Statement
777
                break;
778
            case 'quiz-single':
779
                $lesson_id = get_post_meta( $post->ID, '_quiz_lesson',true );
780
                $lesson_course_id = get_post_meta( $lesson_id, '_lesson_course',true );
781
782
                $update_course = $this->woocommerce_course_update( $lesson_course_id );
0 ignored issues
show
Unused Code introduced by
$update_course 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...
783
                if ( ( $this->access_settings() && Sensei_Utils::user_started_course( $lesson_course_id, $current_user->ID ) ) || sensei_all_access() ) {
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 true; 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...
784
785
                    // Check for prerequisite lesson for this quiz
786
                    $lesson_prerequisite_id = (int) get_post_meta( $lesson_id, '_lesson_prerequisite', true);
787
                    $user_lesson_prerequisite_complete = Sensei_Utils::user_completed_lesson( $lesson_prerequisite_id, $current_user->ID);
788
789
                    // Handle restrictions
790
                    if( sensei_all_access() ) {
791
                        $user_allowed = true;
792 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...
793
                        if ( 0 < absint( $lesson_prerequisite_id ) && ( !$user_lesson_prerequisite_complete ) ) {
794
                            $this->permissions_message['title'] = get_the_title( $post->ID ) . ': ' . __('Restricted Access', 'woothemes-sensei' );
795
                            $lesson_link = '<a href="' . esc_url( get_permalink( $lesson_prerequisite_id ) ) . '">' . __( 'lesson', 'woothemes-sensei' ) . '</a>';
796
                            $this->permissions_message['message'] = sprintf( __('Please complete the previous %1$s before taking this Quiz.', 'woothemes-sensei' ), $lesson_link );
797
                        } else {
798
                            $user_allowed = true;
799
                        } // End If Statement
800
                    } // End If Statement
801
                } elseif( $this->access_settings() ) {
802
                    // Check if the user has started the course
803
804
                    if ( is_user_logged_in() && ! Sensei_Utils::user_started_course( $lesson_course_id, $current_user->ID ) && ( isset( $this->settings->settings['access_permission'] ) && ( true == $this->settings->settings['access_permission'] ) ) ) {
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...
805
806
                        $user_allowed = false;
807
                        $this->permissions_message['title'] = get_the_title( $post->ID ) . ': ' . __('Restricted Access', 'woothemes-sensei' );
808
                        $course_link = '<a href="' . esc_url( get_permalink( $lesson_course_id ) ) . '">' . __( 'course', 'woothemes-sensei' ) . '</a>';
809
                        $wc_post_id = get_post_meta( $lesson_course_id, '_course_woocommerce_product',true );
810 View Code Duplication
                        if ( Sensei_WC::is_woocommerce_active() && ( 0 < $wc_post_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...
811
                            $this->permissions_message['message'] = sprintf( __('Please purchase the %1$s before starting this Quiz.', 'woothemes-sensei' ), $course_link );
812
                        } else {
813
                            $this->permissions_message['message'] = sprintf( __('Please sign up for the %1$s before starting this Quiz.', 'woothemes-sensei' ), $course_link );
814
                        } // End If Statement
815
                    } else {
816
                        $user_allowed = true;
817
                    } // End If Statement
818
                } else {
819
                    $this->permissions_message['title'] = get_the_title( $post->ID ) . ': ' . __('Restricted Access', 'woothemes-sensei' );
820
                    $course_link = '<a href="' . esc_url( get_permalink( get_post_meta( get_post_meta( $post->ID, '_quiz_lesson', true ), '_lesson_course', true ) ) ) . '">' . __( 'course', 'woothemes-sensei' ) . '</a>';
821
                    $this->permissions_message['message'] = sprintf( __('Please sign up for the %1$s before taking this Quiz.', 'woothemes-sensei' ), $course_link );
822
                } // End If Statement
823
                break;
824
            default:
825
                $user_allowed = true;
826
                break;
827
828
        } // End Switch Statement
829
830
        /**
831
         * filter the permissions message shown on sensei post types.
832
         *
833
         * @since 1.8.7
834
         *
835
         * @param array $permissions_message{
836
         *
837
         *   @type string $title
838
         *   @type string $message
839
         *
840
         * }
841
         * @param string $post_id
842
         */
843
        $this->permissions_message = apply_filters( 'sensei_permissions_message', $this->permissions_message, $post->ID );
844
845
846
        if( sensei_all_access() || Sensei_Utils::is_preview_lesson( $post->ID ) ) {
847
            $user_allowed = true;
848
        }
849
850
        return apply_filters( 'sensei_access_permissions', $user_allowed );
851
    } // End get_placeholder_image()
852
853
854
    /**
855
     * Check if visitors have access permission. If the "access_permission" setting is active, do a log in check.
856
     * @since  1.0.0
857
     * @access public
858
     * @return bool
859
     */
860
    public function access_settings () {
861
862
        if( sensei_all_access() ) return true;
863
864
        if ( isset( $this->settings->settings['access_permission'] ) && ( true == $this->settings->settings['access_permission'] ) ) {
865
            if ( is_user_logged_in() ) {
866
                return true;
867
            } else {
868
                return false;
869
            } // End If Statement
870
        } else {
871
            return true;
872
        } // End If Statement
873
    } // End access_settings()
874
875
    /**
876
     * sensei_woocommerce_complete_order description
877
     * @since   1.0.3
878
     * @access  public
879
     * @param   int $order_id WC order ID
880
     * @return  void
881
     */
882
    public function sensei_woocommerce_complete_order ( $order_id = 0 ) {
883
        $order_user = array();
884
        // Check for WooCommerce
885
        if ( Sensei_WC::is_woocommerce_active() && ( 0 < $order_id ) ) {
886
            // Get order object
887
            $order = new WC_Order( $order_id );
888
            $user = get_user_by( 'id', $order->get_user_id() );
889
            $order_user['ID'] = $user->ID;
890
            $order_user['user_login'] = $user->user_login;
891
            $order_user['user_email'] = $user->user_email;
892
            $order_user['user_url'] = $user->user_url;
893
            // Run through each product ordered
894
            if ( 0 < sizeof( $order->get_items() ) ) {
895 View Code Duplication
                foreach( $order->get_items() as $item ) {
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...
896
                    $product_type = '';
897
                    if ( isset( $item['variation_id'] ) && ( 0 < $item['variation_id'] ) ) {
898
                        $item_id = $item['variation_id'];
899
                        $product_type = 'variation';
900
                    } else {
901
                        $item_id = $item['product_id'];
902
                    } // End If Statement
903
                    $_product = $this->sensei_get_woocommerce_product_object( $item_id, $product_type );
904
                    // Get courses that use the WC product
905
                    $courses = $this->post_types->course->get_product_courses( $_product->id );
906
                    // Loop and update those courses
907
                    foreach ( $courses as $course_item ) {
908
                        $update_course = $this->woocommerce_course_update( $course_item->ID, $order_user );
0 ignored issues
show
Unused Code introduced by
$update_course 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...
909
                    } // End For Loop
910
                } // End For Loop
911
            } // End If Statement
912
            // Add meta to indicate that payment has been completed successfully
913
            update_post_meta( $order_id, 'sensei_payment_complete', '1' );
914
        } // End If Statement
915
    } // End sensei_woocommerce_complete_order()
916
917
    /**
918
     * Runs when an order is cancelled.
919
     * @since   1.2.0
920
     * @access  public
921
     * @param   integer $order_id order ID
922
     * @return  void
923
     */
924
    public function sensei_woocommerce_cancel_order ( $order_id ) {
925
926
        // Get order object
927
        $order = new WC_Order( $order_id );
928
929
        // Run through each product ordered
930
        if ( 0 < sizeof( $order->get_items() ) ) {
931
932
            // Get order user
933
            $user_id = $order->__get( 'user_id' );
934
935 View Code Duplication
            foreach( $order->get_items() as $item ) {
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...
936
937
                $product_type = '';
938
                if ( isset( $item['variation_id'] ) && ( 0 < $item['variation_id'] ) ) {
939
                    $item_id = $item['variation_id'];
940
                    $product_type = 'variation';
941
                } else {
942
                    $item_id = $item['product_id'];
943
                } // End If Statement
944
                $_product = $this->sensei_get_woocommerce_product_object( $item_id, $product_type );
0 ignored issues
show
Unused Code introduced by
$_product 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...
945
946
                // Get courses that use the WC product
947
                $courses = array();
0 ignored issues
show
Unused Code introduced by
$courses 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...
948
                $courses = $this->post_types->course->get_product_courses( $item_id );
949
950
                // Loop and update those courses
951
                foreach ($courses as $course_item){
952
                    // Check and Remove course from courses user meta
953
                    $dataset_changes = Sensei_Utils::sensei_remove_user_from_course( $course_item->ID, $user_id );
0 ignored issues
show
Unused Code introduced by
$dataset_changes 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...
954
                } // End For Loop
955
            } // End For Loop
956
        } // End If Statement
957
    } // End sensei_woocommerce_cancel_order()
958
959
    /**
960
     * Runs when an subscription is cancelled or expires.
961
     * @since   1.3.3
962
     * @access  public
963
     * @param   integer $user_id User ID
964
     * @param   integer $subscription_key Subscription Unique Key
965
     * @return  void
966
     */
967
    public function sensei_woocommerce_subscription_ended( $user_id, $subscription_key ) {
968
        $subscription = WC_Subscriptions_Manager::get_users_subscription( $user_id, $subscription_key );
969
        self::sensei_woocommerce_cancel_order( $subscription['order_id'] );
970
    }
971
972
    /**
973
     * Runs when an subscription is re-activated after suspension.
974
     * @since   1.3.3
975
     * @access  public
976
     * @param   integer $user_id User ID
977
     * @param   integer $subscription_key Subscription Unique Key
978
     * @return  void
979
     */
980
    public function sensei_woocommerce_reactivate_subscription( $user_id, $subscription_key ) {
981
        $subscription = WC_Subscriptions_Manager::get_users_subscription( $user_id, $subscription_key );
982
        $order = new WC_Order( $subscription['order_id'] );
983
        $user = get_user_by( 'id', $order->get_user_id() );
984
        $order_user = array();
985
        $order_user['ID'] = $user->ID;
986
        $order_user['user_login'] = $user->user_login;
987
        $order_user['user_email'] = $user->user_email;
988
        $order_user['user_url'] = $user->user_url;
989
        $courses = $this->post_types->course->get_product_courses( $subscription['product_id'] );
990
        foreach ( $courses as $course_item ){
991
            $update_course = $this->woocommerce_course_update( $course_item->ID, $order_user );
0 ignored issues
show
Unused Code introduced by
$update_course 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...
992
        } // End For Loop
993
    } // End sensei_woocommerce_reactivate_subscription
994
995
    /**
996
     * Returns the WooCommerce Product Object
997
     *
998
     * The code caters for pre and post WooCommerce 2.2 installations.
999
     *
1000
     * @since   1.1.1
1001
     * @access  public
1002
     * @param   integer $wc_product_id Product ID or Variation ID
1003
     * @param   string  $product_type  '' or 'variation'
1004
     * @return   WC_Product $wc_product_object
1005
     */
1006
    public function sensei_get_woocommerce_product_object ( $wc_product_id = 0, $product_type = '' ) {
1007
1008
        $wc_product_object = false;
1009
        if ( 0 < intval( $wc_product_id ) ) {
1010
1011
            // Get the product
1012
            if ( function_exists( 'wc_get_product' ) ) {
1013
1014
                $wc_product_object = wc_get_product( $wc_product_id ); // Post WC 2.3
1015
1016
            } elseif ( function_exists( 'get_product' ) ) {
1017
1018
                $wc_product_object = get_product( $wc_product_id ); // Post WC 2.0
1019
1020
            } else {
1021
1022
                // Pre WC 2.0
1023
                if ( 'variation' == $product_type || 'subscription_variation' == $product_type ) {
1024
1025
                    $wc_product_object = new WC_Product_Variation( $wc_product_id );
1026
1027
                } else {
1028
1029
                    $wc_product_object = new WC_Product( $wc_product_id );
1030
1031
                } // End If Statement
1032
1033
            } // End If Statement
1034
1035
        } // End If Statement
1036
1037
        return $wc_product_object;
1038
1039
    } // End sensei_get_woocommerce_product_object()
1040
1041
    /**
1042
     * load_class loads in class files
1043
     * @since   1.2.0
1044
     * @access  public
1045
     * @return  void
1046
     */
1047
    public function load_class ( $class_name = '' ) {
1048
        if ( '' != $class_name && '' != $this->token ) {
1049
            require_once( 'class-' . esc_attr( $this->token ) . '-' . esc_attr( $class_name ) . '.php' );
1050
        } // End If Statement
1051
    } // End load_class()
1052
1053
    /**
1054
     * sensei_activate_subscription runs when a subscription product is purchased
1055
     * @since   1.2.0
1056
     * @access  public
1057
     * @param   integer $order_id order ID
1058
     * @return  void
1059
     */
1060
    public function sensei_activate_subscription(  $order_id = 0 ) {
1061
        if ( 0 < intval( $order_id ) ) {
1062
            $order = new WC_Order( $order_id );
1063
            $user = get_user_by('id', $order->user_id);
1064
            $order_user['ID'] = $user->ID;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$order_user was never initialized. Although not strictly required by PHP, it is generally a good practice to add $order_user = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1065
            $order_user['user_login'] = $user->user_login;
1066
            $order_user['user_email'] = $user->user_email;
1067
            $order_user['user_url'] = $user->user_url;
1068
            // Run through each product ordered
1069
            if (sizeof($order->get_items())>0) {
1070
                foreach($order->get_items() as $item) {
1071
                    $product_type = '';
1072
                    if (isset($item['variation_id']) && $item['variation_id'] > 0) {
1073
                        $item_id = $item['variation_id'];
1074
                        $product_type = 'subscription_variation';
1075
                    } else {
1076
                        $item_id = $item['product_id'];
1077
                    } // End If Statement
1078
                    $_product = $this->sensei_get_woocommerce_product_object( $item_id, $product_type );
0 ignored issues
show
Unused Code introduced by
$_product 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...
1079
                    // Get courses that use the WC product
1080
                    $courses = array();
1081
                    if ( $product_type == 'subscription_variation' ) {
1082
                        $courses = $this->post_types->course->get_product_courses( $item_id );
1083
                    } // End If Statement
1084
                    // Loop and update those courses
1085
                    foreach ($courses as $course_item){
1086
                        $update_course = $this->woocommerce_course_update( $course_item->ID, $order_user );
0 ignored issues
show
Unused Code introduced by
$update_course 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...
1087
                    } // End For Loop
1088
                } // End For Loop
1089
            } // End If Statement
1090
        } // End If Statement
1091
    } // End sensei_activate_subscription()
1092
1093
    /**
1094
     * sensei_woocommerce_email_course_details adds detail to email
1095
     * @since   1.4.5
1096
     * @access  public
1097
     * @param   WC_Order $order
1098
     * @return  void
1099
     */
1100
    public function sensei_woocommerce_email_course_details( $order ) {
1101
        global $woocommerce;
1102
1103
        // exit early if not wc-completed or wc-processing
1104
        if( 'wc-completed' != $order->post_status
1105
            && 'wc-processing' != $order->post_status  ) {
1106
            return;
1107
        }
1108
1109
        $order_items = $order->get_items();
1110
        $order_id = $order->id;
1111
1112
        //If object have items go through them all to find course
1113
        if ( 0 < sizeof( $order_items ) ) {
1114
1115
        echo '<h2>' . __( 'Course details', 'woothemes-sensei' ) . '</h2>';
1116
1117
        foreach ( $order_items as $item ) {
1118
1119
                $product_type = '';
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...
1120
                if ( isset( $item['variation_id'] ) && ( 0 < $item['variation_id'] ) ) {
1121
                    // If item has variation_id then its from variation
1122
                    $item_id = $item['variation_id'];
1123
                    $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...
1124
                } else {
1125
                    // If not its real product set its id to item_id
1126
                    $item_id = $item['product_id'];
1127
                } // End If Statement
1128
1129
                $user_id = get_post_meta( $order_id, '_customer_user', true );
1130
1131
                if( $user_id ) {
1132
1133
                    // Get all courses for product
1134
                    $args = array(
1135
                        'posts_per_page' => -1,
1136
                        'post_type' => 'course',
1137
                        'meta_query' => array(
1138
                            array(
1139
                                'key' => '_course_woocommerce_product',
1140
                                'value' => $item_id
1141
                            )
1142
                        ),
1143
                        'orderby' => 'menu_order date',
1144
                        'order' => 'ASC',
1145
                    );
1146
                    $courses = get_posts( $args );
1147
1148
                    if( $courses && count( $courses ) > 0 ) {
1149
1150
                        foreach( $courses as $course ) {
1151
1152
                            $title = $course->post_title;
1153
                            $permalink = get_permalink( $course->ID );
1154
1155
                            echo '<p><strong>' . sprintf( __( 'View course: %1$s', 'woothemes-sensei' ), '</strong><a href="' . esc_url( $permalink ) . '">' . $title . '</a>' ) . '</p>';
1156
                        }
1157
                    }
1158
                }
1159
            }
1160
        }
1161
    }
1162
1163
    /**
1164
     * Filtering wp_count_comments to ensure that Sensei comments are ignored
1165
     * @since   1.4.0
1166
     * @access  public
1167
     * @param  array   $comments
1168
     * @param  integer $post_id
1169
     * @return array
1170
     */
1171
    public function sensei_count_comments( $comments, $post_id ) {
1172
        global $wpdb;
1173
1174
        $post_id = (int) $post_id;
1175
1176
        $count = wp_cache_get("comments-{$post_id}", 'counts');
1177
1178
        if ( false !== $count ) {
1179
            return $count;
1180
        }
1181
1182
        $statuses = array( '' ); // Default to the WP normal comments
1183
        $stati = $wpdb->get_results( "SELECT comment_type FROM {$wpdb->comments} GROUP BY comment_type", ARRAY_A );
1184
        foreach ( (array) $stati AS $status ) {
1185
            if ( 'sensei_' != substr($status['comment_type'], 0, 7 ) ) {
1186
                $statuses[] = $status['comment_type'];
1187
            }
1188
        }
1189
        $where = "WHERE comment_type IN ('" . join("', '", array_unique( $statuses ) ) . "')";
1190
1191
        if ( $post_id > 0 )
1192
            $where .= $wpdb->prepare( " AND comment_post_ID = %d", $post_id );
1193
1194
        $count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} {$where} GROUP BY comment_approved", ARRAY_A );
1195
1196
        $total = 0;
1197
        $approved = array('0' => 'moderated', '1' => 'approved', 'spam' => 'spam', 'trash' => 'trash', 'post-trashed' => 'post-trashed');
1198
        foreach ( (array) $count as $row ) {
1199
            // Don't count post-trashed toward totals
1200
            if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] )
1201
                $total += $row['num_comments'];
1202
            if ( isset( $approved[$row['comment_approved']] ) )
1203
                $stats[$approved[$row['comment_approved']]] = $row['num_comments'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$stats was never initialized. Although not strictly required by PHP, it is generally a good practice to add $stats = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
1204
        }
1205
1206
        $stats['total_comments'] = $total;
0 ignored issues
show
Bug introduced by
The variable $stats does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1207
        foreach ( $approved as $key ) {
1208
            if ( empty($stats[$key]) )
1209
                $stats[$key] = 0;
1210
        }
1211
1212
        $stats = (object) $stats;
1213
        wp_cache_set("comments-{$post_id}", $stats, 'counts');
1214
1215
        return $stats;
1216
    }
1217
1218
    /**
1219
     * Init images.
1220
     *
1221
     * @since 1.4.5
1222
     * @access public
1223
     * @return void
1224
     */
1225
    public function init_image_sizes() {
1226
        $course_archive_thumbnail 	= $this->get_image_size( 'course_archive_image' );
1227
        $course_single_thumbnail	= $this->get_image_size( 'course_single_image' );
1228
        $lesson_archive_thumbnail 	= $this->get_image_size( 'lesson_archive_image' );
1229
        $lesson_single_thumbnail	= $this->get_image_size( 'lesson_single_image' );
1230
1231
        add_image_size( 'course_archive_thumbnail', $course_archive_thumbnail['width'], $course_archive_thumbnail['height'], $course_archive_thumbnail['crop'] );
1232
        add_image_size( 'course_single_thumbnail', $course_single_thumbnail['width'], $course_single_thumbnail['height'], $course_single_thumbnail['crop'] );
1233
        add_image_size( 'lesson_archive_thumbnail', $lesson_archive_thumbnail['width'], $lesson_archive_thumbnail['height'], $lesson_archive_thumbnail['crop'] );
1234
        add_image_size( 'lesson_single_thumbnail', $lesson_single_thumbnail['width'], $lesson_single_thumbnail['height'], $lesson_single_thumbnail['crop'] );
1235
    }
1236
1237
    /**
1238
     * Get an image size.
1239
     *
1240
     * Variable is filtered by sensei_get_image_size_{image_size}
1241
     *
1242
     * @since 1.4.5
1243
     * @access public
1244
     * @param mixed $image_size
1245
     * @return string
1246
     */
1247
    public function get_image_size( $image_size ) {
1248
1249
        // Only return sizes we define in settings
1250
        if ( ! in_array( $image_size, array( 'course_archive_image', 'course_single_image', 'lesson_archive_image', 'lesson_single_image' ) ) )
1251
            return apply_filters( 'sensei_get_image_size_' . $image_size, '' );
1252
1253
        if( ! isset( $this->settings->settings[ $image_size . '_width' ] ) ) {
1254
            $this->settings->settings[ $image_size . '_width' ] = false;
1255
        }
1256
        if( ! isset( $this->settings->settings[ $image_size . '_height' ] ) ) {
1257
            $this->settings->settings[ $image_size . '_height' ] = false;
1258
        }
1259
        if( ! isset( $this->settings->settings[ $image_size . '_hard_crop' ] ) ) {
1260
            $this->settings->settings[ $image_size . '_hard_crop' ] = false;
1261
        }
1262
1263
        $size = array_filter( array(
1264
            'width' => $this->settings->settings[ $image_size . '_width' ],
1265
            'height' => $this->settings->settings[ $image_size . '_height' ],
1266
            'crop' => $this->settings->settings[ $image_size . '_hard_crop' ]
1267
        ) );
1268
1269
        $size['width'] 	= isset( $size['width'] ) ? $size['width'] : '100';
1270
        $size['height'] = isset( $size['height'] ) ? $size['height'] : '100';
1271
        $size['crop'] 	= isset( $size['crop'] ) ? $size['crop'] : 0;
1272
1273
        return apply_filters( 'sensei_get_image_size_' . $image_size, $size );
1274
    }
1275
1276
    public function body_class( $classes ) {
1277
        if( is_sensei() ) {
1278
            $classes[] = 'sensei';
1279
        }
1280
        return $classes;
1281
    }
1282
1283
    /**
1284
     * Checks that the Jetpack Beautiful Maths module has been activated to support LaTeX within question titles and answers
1285
     *
1286
     * @return null
1287
     * @since 1.7.0
1288
     */
1289
    public function jetpack_latex_support() {
1290
        if ( function_exists( 'latex_markup') ) {
1291
            add_filter( 'sensei_question_title', 'latex_markup' );
1292
            add_filter( 'sensei_answer_text', 'latex_markup' );
1293
        }
1294
    }
1295
1296
    /**
1297
     * Load the module functionality.
1298
     *
1299
     * This function is hooked into plugins_loaded to avoid conflicts with
1300
     * the retired modules extension.
1301
     *
1302
     * @since 1.8.0
1303
     */
1304
    public function load_modules_class(){
1305
        global $sensei_modules;
1306
1307
        if( !class_exists( 'Sensei_Modules' )
1308
            &&  'Sensei_Modules' != get_class( $sensei_modules ) ) {
1309
1310
            //Load the modules class
1311
            require_once( 'class-sensei-modules.php');
1312
            Sensei()->modules = new Sensei_Core_Modules( $this->file );
1313
1314
        }else{
1315
            // fallback for people still using the modules extension.
1316
            global $sensei_modules;
1317
            Sensei()->modules = $sensei_modules;
1318
            add_action( 'admin_notices', array( $this, 'disable_sensei_modules_extension'), 30 );
1319
        }
1320
    }
1321
1322
    /**
1323
     * Tell the user to that the modules extension is no longer needed.
1324
     *
1325
     * @since 1.8.0
1326
     */
1327
    public function disable_sensei_modules_extension(){ ?>
1328
        <div class="notice updated fade">
1329
            <p>
1330
                <?php
1331
                $plugin_manage_url = admin_url().'plugins.php#sensei-modules';
1332
                $plugin_link_element = '<a href="' . $plugin_manage_url . '" >plugins page</a> ';
1333
                ?>
1334
                <strong> Modules are now included in Sensei,</strong> so you no longer need the Sensei Modules extension.
1335
                Please deactivate and delete it from your <?php echo $plugin_link_element; ?>. (This will not affect your existing modules).
1336
            </p>
1337
        </div>
1338
1339
    <?php }// end function
1340
1341
    /**
1342
     * Sensei wide rewrite flush call.
1343
     *
1344
     * To use this simply update the option 'sensei_flush_rewrite_rules' to 1
1345
     *
1346
     * After the option is one the Rules will be flushed.
1347
     *
1348
     * @since 1.9.0
1349
     */
1350
    public function flush_rewrite_rules(){
1351
1352
        // ensures that the rewrite rules are flushed on the second
1353
        // attempt. This ensure that the settings for any other process
1354
        // have been completed and saved to the database before we refresh the
1355
        // rewrite rules.
1356
        $option =  get_option('sensei_flush_rewrite_rules');
1357
        if( '1' == $option ) {
1358
1359
            update_option('sensei_flush_rewrite_rules', '2');
1360
1361
        }elseif( '2' == $option ) {
1362
1363
            flush_rewrite_rules();
1364
            update_option('sensei_flush_rewrite_rules', '0');
1365
1366
        }
1367
1368
    } // end flush_rewrite_rules
1369
1370
    /**
1371
     * Calling this function will tell Sensei to flush rewrite
1372
     * rules on the next load.
1373
     *
1374
     * @since 1.9.0
1375
     */
1376
    public function initiate_rewrite_rules_flush(){
1377
1378
        update_option('sensei_flush_rewrite_rules', '1');
1379
1380
    }
1381
1382
} // End Class
1383
1384
/**
1385
 * Class Woothemes_Sensei
1386
 * for backward compatibility
1387
 * @since 1.9.0
1388
 */
1389
class Woothemes_Sensei extends Sensei_Main{ }
1390