Completed
Pull Request — master (#986)
by Rami
20:36
created

Give_License   D

Complexity

Total Complexity 89

Size/Duplication

Total Lines 841
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 0%

Importance

Changes 19
Bugs 0 Features 1
Metric Value
dl 0
loc 841
ccs 0
cts 155
cp 0
rs 4.4444
c 19
b 0
f 1
wmc 89
lcom 1
cbo 1

17 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 19 5
A includes() 0 5 2
A hooks() 0 22 1
A auto_updater() 0 18 2
A settings() 0 22 1
A license_settings_content() 0 13 1
C activate_license() 0 88 11
B deactivate_license() 0 60 7
B weekly_license_check() 0 43 5
C weekly_subscription_check() 0 71 10
B __single_subscription_check() 0 55 8
D notices() 0 94 20
B is_valid_license() 0 7 5
A __is_third_party_addon() 0 3 1
B __remove_license_key_from_subscriptions() 0 25 5
B __remove_license_notices_show_blocker() 0 27 1
A __is_notice_dismissed() 0 16 4

How to fix   Complexity   

Complex Class

Complex classes like Give_License often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Give_License, and based on these observations, apply Extract Interface, too.

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 20 and the first side effect is on line 12.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Give License handler
4
 *
5
 * This class simplifies the process of adding license information to new Give add-ons.
6
 *
7
 * @version 1.0
8
 */
9
10
// Exit if accessed directly
11
if ( ! defined( 'ABSPATH' ) ) {
12
	exit;
13
}
14
15
if ( ! class_exists( 'Give_License' ) ) :
16
17
	/**
18
	 * Give_License Class
19
	 */
20
	class Give_License {
21
22
		/**
23
		 * File
24
		 *
25
		 * @access private
26
		 *
27
		 * @var    string
28
		 */
29
		private $file;
30
31
		/**
32
		 * License
33
		 *
34
		 * @access private
35
		 *
36
		 * @var    string
37
		 */
38
		private $license;
39
40
		/**
41
		 * Item name
42
		 *
43
		 * @access private
44
		 *
45
		 * @var    string
46
		 */
47
		private $item_name;
48
49
		/**
50
		 * License Information object.
51
		 *
52
		 * @access private
53
		 *
54
		 * @var    object
55
		 */
56
		private $license_data;
57
58
		/**
59
		 * Item shortname
60
		 *
61
		 * @access private
62
		 *
63
		 * @var    string
64
		 */
65
		private $item_shortname;
66
67
		/**
68
		 * Version
69
		 *
70
		 * @access private
71
		 *
72
		 * @var    string
73
		 */
74
		private $version;
75
76
		/**
77
		 * Author
78
		 *
79
		 * @access private
80
		 *
81
		 * @var    string
82
		 */
83
		private $author;
84
85
		/**
86
		 * API URL
87
		 *
88
		 * @access private
89
		 *
90
		 * @var    string
91
		 */
92
		private $api_url      = 'https://givewp.com/edd-sl-api/';
93
		private $account_url  = 'http://givewp.com/my-account/';
94
		private $checkout_url = 'http://givewp.com/checkout/';
95
96
		/**
97
		 * Class Constructor
98
		 *
99
		 * Set up the Give License Class.
100
		 *
101
		 * @access public
102
		 * @param string  $_file
103
		 * @param string  $_item_name
104
		 * @param string  $_version
105
		 * @param string  $_author
106
		 * @param string  $_optname
107
		 * @param string  $_api_url
108
		 * @param string  $_checkout_url
109
		 * @param string  $_account_url
110
		 */
111
		public function __construct( $_file, $_item_name, $_version, $_author, $_optname = null, $_api_url = null, $_checkout_url = null, $_account_url = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $_optname is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
112
			global $give_options;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
113
114
			$this->file           = $_file;
115
			$this->item_name      = $_item_name;
116
			$this->item_shortname = 'give_' . preg_replace( '/[^a-zA-Z0-9_\s]/', '', str_replace( ' ', '_', strtolower( $this->item_name ) ) );
117
			$this->version        = $_version;
118
			$this->license        = isset( $give_options[ $this->item_shortname . '_license_key' ] ) ? trim( $give_options[ $this->item_shortname . '_license_key' ] ) : '';
119
			$this->license_data   = get_option( $this->item_shortname . '_license_active' );
120
			$this->author         = $_author;
121
			$this->api_url        = is_null( $_api_url ) ? $this->api_url : $_api_url;
122
			$this->checkout_url   = is_null( $_checkout_url ) ? $this->checkout_url : $_checkout_url;
123
			$this->account_url    = is_null( $_account_url ) ? $this->account_url : $_account_url;
124
125
			// Setup hooks
126
			$this->includes();
127
			$this->hooks();
128
			//$this->auto_updater();
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% 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...
129
		}
130
131
		/**
132
		 * Includes
133
		 *
134
		 * Include the updater class.
135
		 *
136
		 * @access private
137
		 *
138
		 * @return void
139
		 */
140
		private function includes() {
141
			if ( ! class_exists( 'EDD_SL_Plugin_Updater' ) ) {
142
				require_once 'admin/EDD_SL_Plugin_Updater.php';
143
			}
144
		}
145
146
		/**
147
		 * Hooks
148
		 *
149
		 * Setup license hooks.
150
		 *
151
		 * @access private
152
		 *
153
		 * @return void
154
		 */
155
		private function hooks() {
156
157
			// Register settings
158
			add_filter( 'give_settings_licenses', array( $this, 'settings' ), 1 );
159
160
			// Activate license key on settings save
161
			add_action( 'admin_init', array( $this, 'activate_license' ) );
162
163
			// Deactivate license key
164
			add_action( 'admin_init', array( $this, 'deactivate_license' ) );
165
166
			// Updater
167
			add_action( 'admin_init', array( $this, 'auto_updater' ), 0 );
168
169
			add_action( 'admin_notices', array( $this, 'notices' ) );
170
171
			// Check license weekly.
172
			add_action( 'give_weekly_scheduled_events', array( $this, 'weekly_license_check' ) );
173
174
			// Check subscription weekly.
175
			add_action( 'give_weekly_scheduled_events', array( $this, 'weekly_subscription_check' ) );
176
		}
177
178
		/**
179
		 * Auto Updater
180
		 *
181
		 * @access  private
182
		 * @global  array $give_options
183
		 * @return  bool
184
		 */
185
		public function auto_updater() {
186
187
			if ( ! $this->is_valid_license() ) {
188
				return false;
189
			}
190
191
			// Setup the updater
192
			$give_updater = new EDD_SL_Plugin_Updater(
193
				$this->api_url,
194
				$this->file,
195
				array(
196
					'version'   => $this->version,
197
					'license'   => $this->license,
198
					'item_name' => $this->item_name,
199
					'author'    => $this->author
200
				)
201
			);
202
		}
203
204
		/**
205
		 * License Settings
206
		 *
207
		 * Add license field to settings.
208
		 *
209
		 * @access public
210
		 *
211
		 * @param  array $settings License settings.
212
		 *
213
		 * @return array           License settings.
214
		 */
215
		public function settings( $settings ) {
216
217
			$give_license_settings = array(
218
				array(
219
					'name'    => $this->item_name,
220
					'id'      => $this->item_shortname . '_license_key',
221
					'desc'    => '',
222
					'type'    => 'license_key',
223
					'options' => array(
224
						'license'       => get_option( $this->item_shortname . '_license_active' ),
225
						'shortname'     => $this->item_shortname,
226
						'item_name'     => $this->item_name,
227
						'api_url'       => $this->api_url,
228
						'checkout_url'  => $this->checkout_url,
229
						'account_url'   => $this->account_url
230
					),
231
					'size'    => 'regular'
232
				)
233
			);
234
235
			return array_merge( $settings, $give_license_settings );
236
		}
237
238
		/**
239
		 * License Settings Content
240
		 *
241
		 * Add Some Content to the Licensing Settings.
242
		 *
243
		 * @access public
244
		 *
245
		 * @param  array $settings License settings content.
246
		 *
247
		 * @return array           License settings content.
248
		 */
249
		public function license_settings_content( $settings ) {
250
251
			$give_license_settings = array(
252
				array(
253
					'name' => esc_html__( 'Add-on Licenses', 'give' ),
254
					'desc' => '<hr>',
255
					'type' => 'give_title',
256
					'id'   => 'give_title'
257
				),
258
			);
259
260
			return array_merge( $settings, $give_license_settings );
261
		}
262
263
		/**
264
		 * Activate License
265
		 *
266
		 * Activate the license key.
267
		 *
268
		 * @access public
269
		 *
270
		 * @return void
271
		 */
272
		public function activate_license() {
273
			// Bailout: Check if license key set of not.
274
			if ( ! isset( $_POST[ $this->item_shortname . '_license_key' ] ) ) {
275
				return;
276
			}
277
278
			// Security check.
279
			if ( ! wp_verify_nonce( $_REQUEST[ $this->item_shortname . '_license_key-nonce' ], $this->item_shortname . '_license_key-nonce' ) ) {
280
281
				wp_die( esc_html__( 'Nonce verification failed.', 'give' ), esc_html__( 'Error', 'give' ), array( 'response' => 403 ) );
282
283
			}
284
285
			// Check if user have correct permissions.
286
			if ( ! current_user_can( 'manage_give_settings' ) ) {
287
				return;
288
			}
289
290
			// Allow third party addon developers to handle license activation.
291
			if( $this->__is_third_party_addon() ){
292
				do_action( 'give_activate_license', $this );
293
				return;
294
			}
295
296
			// Delete previous license setting if a empty license key submitted.
297
			if ( empty( $_POST[ $this->item_shortname . '_license_key' ] ) ) {
298
				delete_option( $this->item_shortname . '_license_active' );
299
				return;
300
			}
301
302
			// Do not simultaneously activate any addon if user want to deactivate any addon.
303
			foreach ( $_POST as $key => $value ) {
304
				if ( false !== strpos( $key, 'license_key_deactivate' ) ) {
305
					// Don't activate a key when deactivating a different key
306
					return;
307
				}
308
			}
309
310
311
			// Check if plugin previously installed.
312
			if ( $this->is_valid_license() ) {
313
				return;
314
			}
315
316
			// Get license key.
317
			$license = sanitize_text_field( $_POST[ $this->item_shortname . '_license_key' ] );
318
319
			// Bailout.
320
			if( empty( $license ) ) {
321
				return;
322
			}
323
324
			// Delete previous license key from subscription if previously added.
325
			$this->__remove_license_key_from_subscriptions();
326
327
			// Data to send to the API
328
			$api_params = array(
329
				'edd_action' => 'activate_license', //never change from "edd_" to "give_"!
330
				'license'    => $license,
331
				'item_name'  => urlencode( $this->item_name ),
332
				'url'        => home_url()
333
			);
334
335
			// Call the API
336
			$response = wp_remote_post(
337
				$this->api_url,
338
				array(
339
					'timeout'   => 15,
340
					'sslverify' => false,
341
					'body'      => $api_params
342
				)
343
			);
344
345
			// Make sure there are no errors
346
			if ( is_wp_error( $response ) ) {
347
				return;
348
			}
349
350
			// Tell WordPress to look for updates
351
			set_site_transient( 'update_plugins', null );
352
353
			// Decode license data
354
			$license_data = json_decode( wp_remote_retrieve_body( $response ) );
355
			update_option( $this->item_shortname . '_license_active', $license_data );
356
357
			// Check subscription for license key and store this to db (if any).
358
			$this->__single_subscription_check();
359
		}
360
361
		/**
362
		 * Deactivate License
363
		 *
364
		 * Deactivate the license key.
365
		 *
366
		 * @access public
367
		 *
368
		 * @return void
369
		 */
370
		public function deactivate_license() {
371
372
			if ( ! isset( $_POST[ $this->item_shortname . '_license_key' ] ) ) {
373
				return;
374
			}
375
376
			if ( ! wp_verify_nonce( $_REQUEST[ $this->item_shortname . '_license_key-nonce' ], $this->item_shortname . '_license_key-nonce' ) ) {
377
378
				wp_die( esc_html__( 'Nonce verification failed.', 'give' ), esc_html__( 'Error', 'give' ), array( 'response' => 403 ) );
379
380
			}
381
382
			if ( ! current_user_can( 'manage_give_settings' ) ) {
383
				return;
384
			}
385
386
			// Allow third party addon developers to handle license deactivation.
387
			if( $this->__is_third_party_addon() ){
388
				do_action( 'give_deactivate_license', $this );
389
				return;
390
			}
391
392
			// Run on deactivate button press
393
			if ( isset( $_POST[ $this->item_shortname . '_license_key_deactivate' ] ) ) {
394
395
				// Data to send to the API
396
				$api_params = array(
397
					'edd_action' => 'deactivate_license', //never change from "edd_" to "give_"!
398
					'license'    => $this->license,
399
					'item_name'  => urlencode( $this->item_name ),
400
					'url'        => home_url()
401
				);
402
403
				// Call the API
404
				$response = wp_remote_post(
405
					$this->api_url,
406
					array(
407
						'timeout'   => 15,
408
						'sslverify' => false,
409
						'body'      => $api_params
410
					)
411
				);
412
413
414
				// Make sure there are no errors
415
				if ( is_wp_error( $response ) ) {
416
					return;
417
				}
418
419
				// Decode the license data
420
				$license_data = json_decode( wp_remote_retrieve_body( $response ) );
421
422
423
				// Remove license data.
424
				delete_option( $this->item_shortname . '_license_active' );
425
426
				// Remove license key from subscriptions if exist.
427
				$this->__remove_license_key_from_subscriptions();
428
			}
429
		}
430
431
432
		/**
433
		 * Check if license key is valid once per week
434
		 *
435
		 * @access  public
436
		 * @since   1.7
437
		 *
438
		 * @return  bool/void
0 ignored issues
show
Documentation introduced by
The doc-type bool/void could not be parsed: Unknown type name "bool/void" 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...
439
		 */
440
		public function weekly_license_check() {
441
442
			if( ! empty( $_POST['give_settings'] ) ) {
443
				// Don't fire when saving settings
444
				return false;
445
			}
446
447
			if( empty( $this->license ) ) {
448
				return false;
449
			}
450
451
			// Allow third party addon developers to handle there license check.
452
			if( $this->__is_third_party_addon() ){
453
				do_action( 'give_weekly_license_check', $this );
454
				return false;
455
			}
456
457
			// Data to send in our API request.
458
			$api_params = array(
459
				'edd_action'=> 'check_license',
460
				'license' 	=> $this->license,
461
				'item_name' => urlencode( $this->item_name ),
462
				'url'       => home_url()
463
			);
464
465
			// Call the API
466
			$response = wp_remote_post(
467
				$this->api_url,
468
				array(
469
					'timeout'   => 15,
470
					'sslverify' => false,
471
					'body'      => $api_params
472
				)
473
			);
474
475
			// Make sure the response came back okay.
476
			if ( is_wp_error( $response ) ) {
477
				return false;
478
			}
479
480
			$license_data = json_decode( wp_remote_retrieve_body( $response ) );
481
			update_option( $this->item_shortname . '_license_active', $license_data );
482
		}
483
484
485
		/**
486
		 * Check subscription validation once per week
487
		 *
488
		 * @access  public
489
		 * @since   1.7
490
		 *
491
		 * @return  bool/void
0 ignored issues
show
Documentation introduced by
The doc-type bool/void could not be parsed: Unknown type name "bool/void" 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...
492
		 */
493
		public function weekly_subscription_check() {
494
495
			if( ! empty( $_POST['give_settings'] ) ) {
496
				// Don't fire when saving settings
497
				return false;
498
			}
499
500
			// Remove old subscription data.
501
			if( absint( get_option( '_give_subscriptions_edit_last', true ) ) < current_time( 'timestamp' , 1 ) ){
502
				delete_option( 'give_subscriptions' );
503
				update_option( '_give_subscriptions_edit_last', strtotime( '+ 1 day', current_time( 'timestamp' , 1 ) ) );
504
			}
505
506
			if( empty( $this->license ) ) {
507
				return false;
508
			}
509
510
			// Allow third party addon developers to handle there subscription check.
511
			if( $this->__is_third_party_addon() ){
512
				do_action( 'give_weekly_subscription_check', $this );
513
				return false;
514
			}
515
516
			// Delete subscription notices show blocker.
517
			$this->__remove_license_notices_show_blocker();
518
519
			// Data to send in our API request.
520
			$api_params = array(
521
				// Do not get confuse with edd_action check_subscription.
522
				// By default edd software licensing api does not have api to check subscription.
523
				// This is custom feature to check subscriptions.
524
				'edd_action'=> 'check_subscription',
525
				'license' 	=> $this->license,
526
				'item_name' => urlencode( $this->item_name ),
527
				'url'       => home_url()
528
			);
529
530
			// Call the API
531
			$response = wp_remote_post(
532
				$this->api_url,
533
				array(
534
					'timeout'   => 15,
535
					'sslverify' => false,
536
					'body'      => $api_params
537
				)
538
			);
539
540
			// Make sure the response came back okay.
541
			if ( is_wp_error( $response ) ) {
542
				return false;
543
			}
544
545
			$subscription_data = json_decode( wp_remote_retrieve_body( $response ), true );
546
547
			if( ! empty( $subscription_data['success'] ) && absint( $subscription_data['success'] ) ) {
548
				$subscriptions = get_option( 'give_subscriptions', array() );
549
550
				// Update subscription data only if subscription does not exist already.
551
				if( ! array_key_exists( $subscription_data['id'], $subscriptions ) ) {
552
					$subscriptions[ $subscription_data['id'] ] = $subscription_data;
553
					$subscriptions[ $subscription_data['id'] ]['licenses'] = array();
554
				}
555
556
				// Store licenses for subscription.
557
				if( ! in_array( $this->license, $subscriptions[ $subscription_data['id'] ]['licenses'] ) ) {
558
					$subscriptions[ $subscription_data['id'] ]['licenses'][] = $this->license;
559
				}
560
561
				update_option( 'give_subscriptions', $subscriptions );
562
			}
563
		}
564
565
		/**
566
		 * Check if license key is part of subscription or not
567
		 *
568
		 * @since   1.7
569
		 * @access  private
570
		 *
571
		 * @return  bool/void
0 ignored issues
show
Documentation introduced by
The doc-type bool/void could not be parsed: Unknown type name "bool/void" 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...
572
		 *
573
		 */
574
		private function __single_subscription_check() {
575
			// Do not fire if license key is not set.
576
			if ( ! isset( $_POST[ $this->item_shortname . '_license_key' ] ) ) {
577
				return false;
578
			}
579
580
			if( empty( $this->license ) ) {
581
				return false;
582
			}
583
584
			// Data to send in our API request.
585
			$api_params = array(
586
				// Do not get confuse with edd_action check_subscription.
587
				// By default edd software licensing api does not have api to check subscription.
588
				// This is custom feature to check subscriptions.
589
				'edd_action'=> 'check_subscription',
590
				'license' 	=> $this->license,
591
				'item_name' => urlencode( $this->item_name ),
592
				'url'       => home_url()
593
			);
594
595
			// Call the API
596
			$response = wp_remote_post(
597
				$this->api_url,
598
				array(
599
					'timeout'   => 15,
600
					'sslverify' => false,
601
					'body'      => $api_params
602
				)
603
			);
604
605
			// Make sure the response came back okay.
606
			if ( is_wp_error( $response ) ) {
607
				return false;
608
			}
609
610
			$subscription_data = json_decode( wp_remote_retrieve_body( $response ), true );
611
612
			if( ! empty( $subscription_data['success'] ) && absint( $subscription_data['success'] ) ) {
613
				$subscriptions = get_option( 'give_subscriptions', array() );
614
615
				// Update subscription data only if subscription does not exist already.
616
				if( ! array_key_exists( $subscription_data['id'], $subscriptions ) ) {
617
					$subscriptions[ $subscription_data['id'] ] = $subscription_data;
618
					$subscriptions[ $subscription_data['id'] ]['licenses'] = array();
619
				}
620
621
				// Store licenses for subscription.
622
				if( ! in_array( $this->license, $subscriptions[ $subscription_data['id'] ]['licenses'] ) ) {
623
					$subscriptions[ $subscription_data['id'] ]['licenses'][] = $this->license;
624
				}
625
626
				update_option( 'give_subscriptions', $subscriptions );
627
			}
628
		}
629
630
631
		/**
632
		 * Admin notices for errors
633
		 *
634
		 * @access  public
635
		 * @return  void
636
		 */
637
		public function notices() {
638
			global $current_user;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
639
			static $showed_invalid_message;
640
			static $showed_subscriptions_message;
641
			static $addon_license_key_in_subscriptions;
642
643
			// Set default value.
644
			$addon_license_key_in_subscriptions = ! empty( $addon_license_key_in_subscriptions ) ? $addon_license_key_in_subscriptions : array();
645
646
			if( empty( $this->license ) ) {
647
				return;
648
			}
649
650
			if( ! current_user_can( 'manage_shop_settings' ) ) {
651
				return;
652
			}
653
654
			// Do not show licenses notices on license tab.
655
			if( ! empty( $_GET['tab'] ) && 'licenses' === $_GET['tab'] ) {
656
				return;
657
			}
658
659
			$messages = array();
660
661
			// Get subscriptions.
662
			$subscriptions = get_option( 'give_subscriptions' );
663
664
665
			// Show subscription messages.
666
			if( ! empty( $subscriptions ) && ! $showed_subscriptions_message ) {
667
668
				foreach ( $subscriptions as $subscription ) {
669
					// Subscription expires timestamp.
670
					$subscription_expires = strtotime( $subscription['expires'] );
671
672
					// Start showing subscriptions message before one week of renewal date.
673
					if( strtotime( '- 7 days', $subscription_expires ) > current_time( 'timestamp', 1 ) ) {
674
						continue;
675
					}
676
677
					// Check if subscription message already exist in messages.
678
					if( array_key_exists( $subscription['id'], $messages ) ) {
679
						continue;
680
					}
681
682
					if( ( ! $this->__is_notice_dismissed( $subscription['id'] ) && 'active' !== $subscription['status'] ) ) {
683
684
						if( strtotime( $subscription['expires'] ) < current_time( 'timestamp', 1 ) ) {// Check if license already expired.
685
							$messages[$subscription['id']] = sprintf(
686
								__( 'You Give addon license expired for payment <a href="%s" target="_blank">#%d</a>. <a href="%s" target="_blank">Click to renew an existing license</a> or <a href="%s">Click here if already renewed</a>.', 'give' ),
687
								urldecode( $subscription['invoice_url'] ),
688
								$subscription['payment_id'],
689
								"{$this->checkout_url}?edd_license_key={$subscription['license_key']}&utm_campaign=admin&utm_source=licenses&utm_medium=expired",
690
								esc_url( add_query_arg( '_give_hide_license_notices_permanently', $subscription['id'], $_SERVER['REQUEST_URI'] ) )
691
							);
692
						}else{
693
							$messages[$subscription['id']] = sprintf(
694
								__( 'You Give addon license will expire in %s for payment <a href="%s" target="_blank">#%d</a>. <a href="%s" target="_blank">Click to renew an existing license</a> or <a href="%s">Click here if already renewed</a>.', 'give' ),
695
								human_time_diff( current_time( 'timestamp', 1 ), strtotime( $subscription['expires'] ) ),
696
								urldecode( $subscription['invoice_url'] ),
697
								$subscription['payment_id'],
698
								"{$this->checkout_url}?edd_license_key={$subscription['license_key']}&utm_campaign=admin&utm_source=licenses&utm_medium=expired",
699
								esc_url( add_query_arg( '_give_hide_license_notices_permanently', $subscription['id'], $_SERVER['REQUEST_URI'] ) )
700
							);
701
						}
702
					}
703
704
					// Stop validation for these licencse keys.
705
					$addon_license_key_in_subscriptions = array_merge( $addon_license_key_in_subscriptions, $subscription['licenses'] );
706
				}
707
				$showed_subscriptions_message = true;
708
			}
709
710
711
			// Show non subscription addon messages.
712
			if( ! in_array( $this->license, $addon_license_key_in_subscriptions ) && ! $this->__is_notice_dismissed( 'general' ) && ! $this->is_valid_license() && empty( $showed_invalid_message ) ) {
713
714
				$messages['general'] = sprintf(
715
					__( 'You have invalid or expired license keys for Give Addon. Please go to the <a href="%s">Licenses page</a> to correct this issue.', 'give' ),
716
					admin_url( 'edit.php?post_type=give_forms&page=give-settings&tab=licenses' )
717
				);
718
				$showed_invalid_message = true;
719
720
			}
721
722
			// Print messages.
723
			if( ! empty( $messages ) ) {
724
				foreach( $messages as $notice_id => $message ) {
725
					echo '<div class="notice notice-error is-dismissible give-license-notice" data-dismiss-notice-shortly="' . esc_url( add_query_arg( '_give_hide_license_notices_shortly', $notice_id, $_SERVER['REQUEST_URI'] ) ) . '">';
726
					echo '<p>' . $message . '</p>';
727
					echo '</div>';
728
				}
729
			}
730
		}
731
732
733
		/**
734
		 * Check if license is valid or not.
735
		 *
736
		 * @since 1.7
737
		 *
738
		 * @return bool
739
		 */
740
		public function is_valid_license() {
741
			if( apply_filters( 'give_is_valid_license' , ( is_object( $this->license_data ) && ! empty( $this->license_data ) &&  property_exists( $this->license_data, 'license' )&& 'valid' === $this->license_data->license ) ) ) {
742
				return true;
743
			}
744
745
			return false;
746
		}
747
748
		/**
749
		 * Check if license is valid or not.
750
		 *
751
		 * @since  1.7
752
		 * @access private
753
		 *
754
		 * @return bool
755
		 */
756
		private function __is_third_party_addon() {
757
			return ( false === strpos( $this->api_url, 'givewp.com/' ) );
758
		}
759
760
761
		/**
762
		 * Remove license keyy from subscription
763
		 *
764
		 * This function mainly uses when admin user deactivate license key,
765
		 * then we do not need subscription information for that license key.
766
		 *
767
		 * @since  1.7
768
		 * @access private
769
		 *
770
		 * @return void|bool
771
		 */
772
		private function __remove_license_key_from_subscriptions(){
773
			$subscriptions = get_option( 'give_subscriptions', array() );
774
775
			// Bailout.
776
			if( empty( $this->license ) ) {
777
				return false;
778
			}
779
780
			if( ! empty( $subscriptions ) ) {
781
				foreach ( $subscriptions as $subscription_id => $subscription ) {
782
					$license_index = array_search( $this->license, $subscription['licenses'] );
783
					if( false !== $license_index ) {
784
						// Remove license key.
785
						unset( $subscriptions[ $subscription_id ]['licenses'][$license_index] );
786
787
						// Rearrange license keys.
788
						$subscriptions[ $subscription_id ]['licenses'] = array_values( $subscriptions[ $subscription_id ]['licenses'] );
789
790
						// Update subscription information.
791
						update_option( 'give_subscriptions', $subscriptions );
792
						break;
793
					}
794
				}
795
			}
796
		}
797
798
		/**
799
		 * Remove license notices show blocker.
800
		 *
801
		 * @since 1.7
802
		 * @access private
803
		 *
804
		 * @return void
805
		 */
806
		private function __remove_license_notices_show_blocker(){
807
			global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
808
809
			// Delete permanent notice blocker.
810
			$wpdb->query(
811
				$wpdb->prepare(
812
					"
813
					DELETE FROM $wpdb->usermeta
814
					WHERE meta_key
815
					LIKE '%%%s%%'
816
					",
817
					'_give_hide_license_notices_permanently'
818
				)
819
			);
820
821
			// Delete short notice blocker.
822
			$wpdb->query(
823
				$wpdb->prepare(
824
					"
825
					DELETE FROM $wpdb->options
826
					WHERE option_name
827
					LIKE '%%%s%%'
828
					",
829
					'__give_hide_license_notices_shortly_'
830
				)
831
			);
832
		}
833
834
		/**
835
		 * Check if notice dismissed by admin user or not.
836
		 *
837
		 * @since  1.7
838
		 * @access private
839
		 *
840
		 * @param int $notice_id notice ID.
841
		 *
842
		 * @return bool
843
		 */
844
		private function __is_notice_dismissed( $notice_id ){
845
			global $current_user;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
846
			$is_notice_dismissed = false;
847
848
			// Ge is notice dismissed permanently.
849
			$already_dismiss_notices = ( $already_dismiss_notices = get_user_meta( $current_user->ID, '_give_hide_license_notices_permanently', true ) )
850
				? $already_dismiss_notices
851
				: array();
852
853
854
			if( in_array( $notice_id, $already_dismiss_notices ) || get_transient( "_give_hide_license_notices_shortly_{$current_user->ID}_{$notice_id}" ) ) {
855
				$is_notice_dismissed =  true;
856
			}
857
858
			return $is_notice_dismissed;
859
		}
860
	}
861
862
endif; // end class_exists check
863