Issues (4296)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/admin/class-addon-activation-banner.php (17 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Give Activation Banner
4
 *
5
 * @author  WordImpress
6
 * @version 1.0
7
 */
8
9
// Exit if accessed directly.
10
if ( ! defined( 'ABSPATH' ) ) {
11
	exit;
12
}
13
14
global $give_addons;
15
16
/**
17
 * Class Give_Addon_Activation_Banner
18
 *
19
 * @since  2.1.0 Added pleasing interface when multiple add-ons are activated.
20
 */
21
class Give_Addon_Activation_Banner {
22
23
	/**
24
	 * Class constructor.
25
	 *
26
	 * @since  1.0
27
	 * @access public
28
	 *
29
	 * @param array $_banner_details {
30
	 *                               'file'              => __FILE__, // (required) Directory path to the main plugin file
31
	 *                               'name'              => __( 'Authorize.net Gateway', 'give-authorize' ), // (required) Name of the Add-on
32
	 *                               'version'           => GIVE_AUTHORIZE_VERSION, // (required)The most current version
33
	 *                               'documentation_url' => 'http://docs.givewp.com/addon-authorize',// (required)
34
	 *                               'support_url'       => 'https://givewp.com/support/', // (required)Location of Add-on settings page, leave blank to hide
35
	 *                               'testing'           => false, // (required) Never leave as "true" in production!!!
36
	 *                               }
37
	 */
38
	function __construct( $_banner_details ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

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

Loading history...
39
		global $give_addons, $pagenow;
40
41
		// Append add-on information to the global variable.
42
		$give_addons[] = $_banner_details;
43
44
		if ( 'plugins.php' === $pagenow ) {
45
46
			// Get the current user.
47
			$current_user  = wp_get_current_user();
48
			$this->user_id = $current_user->ID;
49
50
			// Set up hooks.
51
			$this->init();
52
53
			// Store user id who activated plugin.
54
			$this->add_addon_activate_meta();
55
56
			// Check if notice callback is already hooked.
57
			if ( ! $this->is_banner_notice_hooked() ) {
58
				// If multiple add-on are activated then show activation banner in tab view.
59
				add_action( 'admin_notices', array( $this, 'addon_activation_banner_notices' ), 10 );
60
			}
61
		}
62
	}
63
64
	/**
65
	 * Get the meta key name.
66
	 *
67
	 * @since 2.1
68
	 * @param string $addon_banner_key
69
	 *
70
	 * @return string
71
	 */
72
	public static function get_banner_user_meta_key( $addon_banner_key ) {
73
		$addon_slug = sanitize_text_field( $addon_banner_key );
74
75
		return "give_addon_{$addon_slug}_active_by_user";
76
	}
77
78
	/**
79
	 * Set up WordPress filters to hook into WP's update process.
80
	 *
81
	 * @since  1.0
82
	 * @access public
83
	 *
84
	 * @return void
85
	 */
86
	public function init() {
87
		// Get the current page to add the notice to
88
		add_action( 'current_screen', array( $this, 'give_addon_notice_ignore' ) );
89
90
		// Get the Give add-ons.
91
		$give_addons = $this->get_plugin_file_names();
92
93
		if ( ! empty( $give_addons ) ) {
94
95
			// Go through each of the add-on and hook deactivate action.
96
			foreach ( $give_addons as $addon_name => $give_addon ) {
97
98
				// Testing?
99
				if ( true === $give_addon['testing'] ) {
100
					$nag_meta_key = 'give_addon_activation_ignore_' . $addon_name;
101
					delete_user_meta( $this->user_id, $nag_meta_key );
0 ignored issues
show
delete_user_meta() usage is highly discouraged, check VIP documentation on "Working with wp_users"
Loading history...
102
				}
103
104
				// Add deactivate hook.
105
				add_action( 'deactivate_' . $give_addon['plugin_main_file'], array( $this, 'remove_addon_activate_meta' ) );
106
			}
107
		}
108
	}
109
110
	/**
111
	 * Get plugin file name.
112
	 *
113
	 * @since   1.8
114
	 * @access  private
115
	 * @return mixed
116
	 */
117
	private function get_plugin_file_names() {
118
		global $give_addons;
119
120
		// Get recently activated plugins.
121
		$active_plugins = get_option( 'active_plugins' );
122
123
		$file_names = array();
124
125
		if ( empty( $give_addons ) ) {
126
			return $file_names;
127
		}
128
129
		// Go through each addon and get the plugin file url.
130
		foreach ( $give_addons as $give_addon ) {
131
			$file_name = '';
132
			$file_path = explode( '/plugins/', $give_addon['file'] );
133
			if ( $file_path ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $file_path of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
134
				$file_path = array_pop( $file_path );
135
				$file_name = current( explode( '/', $file_path ) );
136
			}
137
138
			if ( ! empty( $file_name ) ) {
139
				foreach ( $active_plugins as $plugin ) {
140
					if ( false !== strpos( $plugin, $file_name ) ) {
141
						$add_on_key                     = sanitize_title( $give_addon['name'] );
142
						$give_addon['plugin_main_file'] = $plugin; // Include plugin file.
143
						$file_names[ $add_on_key ]      = $give_addon;
144
						break;
145
					}
146
				}
147
			}
148
		}
149
150
		return $file_names;
151
	}
152
153
	/**
154
	 * Setup user id to option
155
	 *
156
	 * @since  1.8
157
	 * @access private
158
	 */
159
	private function add_addon_activate_meta() {
160
		// Get all activated add-ons.
161
		$give_addons = $this->get_plugin_file_names();
162
163
		if ( ! empty( $give_addons ) ) {
164
165
			// Go through rach add-ons and add meta data.
166
			foreach ( $give_addons as $banner_addon_name => $addon ) {
167
168
				// User meta key.
169
				$user_id = __give_get_active_by_user_meta( $banner_addon_name );
170
171
				if ( ! $user_id ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $user_id of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
172
					update_option( self::get_banner_user_meta_key( $banner_addon_name ), $this->user_id, false );
173
				}
174
			}
175
		}
176
	}
177
178
	/**
179
	 * Check if the addon_activation_banner_notices function has already been hooked to admin_notice.
180
	 *
181
	 * @since 2.1.0
182
	 *
183
	 * @return bool
184
	 */
185
	public function is_banner_notice_hooked() {
186
		global $wp_filter;
187
		$notice_already_hooked = false;
188
189
		if ( isset( $wp_filter['admin_notices']->callbacks[10] ) ) {
190
			// Get all of the hooks.
191
			$admin_notice_callbacks = array_keys( $wp_filter['admin_notices']->callbacks[10] );
192
193
			if ( ! empty( $admin_notice_callbacks ) ) {
194
				foreach ( $admin_notice_callbacks as $key ) {
195
					//If the key is found in your string, set $found to true
196
					if ( false !== strpos( $key, 'addon_activation_banner_notices' ) ) {
197
						$notice_already_hooked = true;
198
					}
199
				}
200
			}
201
		}
202
203
		return $notice_already_hooked;
204
	}
205
206
	/**
207
	 * Get the add-on banner notices.
208
	 *
209
	 * @since 2.1.0
210
	 */
211
	public function addon_activation_banner_notices() {
212
		global $pagenow, $give_addons;
213
214
		// Bailout.
215
		if ( 'plugins.php' !== $pagenow ) {
216
			return false;
217
		}
218
219
		// Store the add-ons of which activation banner should be shown.
220
		$addon_to_display = array();
221
222
		// Get recently activated add-ons.
223
		$recent_activated = $this->get_recently_activated_addons();
224
		$latest_addon     = array();
225
226
		// Get the plugin folder name, because many give-addon not sending proper plugin_file.
227
		if ( ! empty( $recent_activated ) ) {
228
			foreach ( $recent_activated as $recent_addon ) {
229
				// Get the add-on folder name.
230
				$latest_addon[] = substr( $recent_addon, 0, strpos( $recent_addon, '/' ) );
231
			}
232
		}
233
234
		// Go through each of the give add-on.
235
		foreach ( $give_addons as $addon ) {
236
			$addon_sanitized_name = sanitize_title( $addon['name'] );
237
238
			// Get the add-on dismiss status.
239
			$add_on_state = get_user_meta( $this->user_id, "give_addon_activation_ignore_{$addon_sanitized_name}", true );
0 ignored issues
show
get_user_meta() usage is highly discouraged, check VIP documentation on "Working with wp_users"
Loading history...
240
241
			// Get the option key.
242
			$activate_by_user = (int) __give_get_active_by_user_meta( $addon_sanitized_name );
243
244
			// Remove plugin file and get the Add-on's folder name only.
245
			$file_path = $this->get_plugin_folder_name( $addon['file'] );
246
247
			// If add-on were never dismissed.
248
			if ( 'true' !== $add_on_state && $this->user_id === $activate_by_user ) {
249
				if ( ! empty( $latest_addon ) && ( in_array( $file_path, $latest_addon, true ) || empty( $latest_addon ) ) ) {
250
					$addon_to_display[] = $addon;
251
				}
252
			}
253
		}
254
255
		if ( ! empty( $addon_to_display ) ) {
256
			ob_start();
257
258
			// Output inline styles here because there's no reason
259
			// to enqueued them after the alert is dismissed.
260
			$this->print_css_js();
0 ignored issues
show
The call to the method Give_Addon_Activation_Banner::print_css_js() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
261
			?>
262
			<div class="<?php echo ( 1 !== count( $addon_to_display ) ) ? 'give-alert-tab-wrapper' : ''; ?> updated give-addon-alert give-notice">
0 ignored issues
show
Expected next thing to be a escaping function, not '('
Loading history...
263
				<?php
264
				// If multiple add-on are activated.
265
				if ( 1 !== count( $addon_to_display ) ) {
266
					?>
267
					<div class="give-vertical-tab">
268
						<div class="give-addon-tab-list">
269
							<ul class="give-alert-addon-list">
270
								<?php
271
								$is_first = true;
272 View Code Duplication
								foreach ( $addon_to_display as $banner ) {
0 ignored issues
show
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...
273
									?>
274
									<li class="give-tab-list<?php echo ( true === $is_first ) ? ' active' : ''; ?>" id="give-addon-<?php echo esc_attr( basename( $banner['file'], '.php' ) ); ?>">
0 ignored issues
show
Expected next thing to be a escaping function, not '('
Loading history...
275
										<a href="#"><?php echo esc_html( $banner['name'] ); ?></a>
276
									</li>
277
									<?php
278
									$is_first = false;
279
								}
280
								$is_first = true;
281
								?>
282
							</ul>
283
						</div>
284
						<div class="give-right-side-block">
285 View Code Duplication
							<?php foreach ( $addon_to_display as $banner ) : ?>
0 ignored issues
show
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...
286
								<div class="give-tab-details <?php echo ( true === $is_first ) ? ' active' : ''; ?> " id="give-addon-<?php echo esc_attr( basename( $banner['file'], '.php' ) ); ?>">
0 ignored issues
show
Expected next thing to be a escaping function, not '('
Loading history...
287
									<?php
288
										// Render single add banner.
289
										$this->render_single_addon_banner( $banner, false );
290
										$is_first = false;
291
									?>
292
								</div>
293
							<?php endforeach; ?>
294
						</div>
295
					</div>
296
					<?php
297
				} else {
298
					$this->render_single_addon_banner( $addon_to_display[0], true );
299
				}
300
				?>
301
			</div>
302
			<?php
303
			$notice_html = ob_get_clean();
304
305
			// Register notice.
306
			Give()->notices->register_notice( array(
307
				'id'               => 'give_add_on_activation_notice',
308
				'type'             => 'updated',
309
				'description_html' => $notice_html,
310
				'show'             => true,
311
			) );
312
		}
313
	}
314
315
	/**
316
	 * Render single banner activation
317
	 *
318
	 * @since 2.1.0
319
	 *
320
	 * @param array $banner_arr Banner options.
321
	 * @param bool  $is_single  Is single.
322
	 */
323
	private function render_single_addon_banner( $banner_arr, $is_single ) {
324
		// Get all give add-on.
325
		$give_addons = give_get_plugins();
326
327
		// Plugin main file.
328
		$plugin_file = $banner_arr['file'];
329
330
		// Get the plugin main file.
331
		foreach ( $give_addons as $main_file => $addon ) {
332
			// Plugin should be activated.
333
			if ( ! is_plugin_active( $main_file ) ) {
334
				continue;
335
			}
336
337
			if (
338
				isset( $banner_arr['name'] )
339
				&& 'add-on' === $addon['Type']
340
				&& $this->get_plugin_folder_name( $main_file ) === $this->get_plugin_folder_name( $plugin_file )
341
			) {
342
				$plugin_file = WP_PLUGIN_DIR . '/' . $main_file;
343
				break;
344
			}
345
		}
346
347
		// Create dismiss URL.
348
		$dismiss_url = $is_single
349
			? admin_url( 'plugins.php?give_addon_activation_ignore=1&give_addon=' . sanitize_title( $banner_arr['name'] ) )
350
			: admin_url( 'plugins.php?give_addon_activation_ignore=1&give_addon=all' );
351
352
		// Get the add-on details.
353
		$plugin_data = get_plugin_data( $plugin_file );
354
		?>
355
		<img src="<?php echo esc_url( GIVE_PLUGIN_URL . 'assets/dist/images/give-icon-full-circle.svg' ); ?>" class="give-logo" />
356
		<div class="give-alert-message">
357
			<h3>
358
				<?php
359
				printf(
360
					/* translators: %s: Add-on name */
361
					'%s<span>%s</span>',
362
					__( 'New Give Add-on Activated: ', 'give' ),
363
					esc_html( $banner_arr['name'] )
364
				);
365
				?>
366
			</h3>
367
			<a href="<?php echo esc_url( $dismiss_url ); ?>" class="dismiss">
368
				<span class="dashicons dashicons-dismiss"></span>
369
			</a>
370
			<div class="alert-actions">
371
				<?php
372
				//Point them to your settings page.
373
				if ( ! empty( $plugin_data['Description'] ) ) {
374
					?>
375
					<span class="give-addon-description">
376
					<em><?php echo esc_html( strip_tags( $plugin_data['Description'] ) ); ?></em></span><br />
377
					<?php
378
				}
379 View Code Duplication
				if ( isset( $banner_arr['settings_url'] ) ) {
0 ignored issues
show
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...
380
					printf(
381
						'<a href="%s"><span class="dashicons dashicons-admin-settings"></span>%s</a>',
382
						esc_url( $banner_arr['settings_url'] ),
383
						esc_html__( 'Go to Settings', 'give' )
384
					);
385
				}
386
				// Show them how to configure the Addon.
387
				if ( isset( $banner_arr['documentation_url'] ) ) {
388
					printf(
389
						'<a href="%s" target="_blank"><span class="dashicons dashicons-media-text"></span>%s</a>',
390
						esc_url( $banner_arr['documentation_url'] ),
391
						sprintf(
392
							/* translators: %s: Add-on name */
393
							esc_html__( 'Documentation: %s Add-on', 'give' ),
394
							esc_html( $banner_arr['name'] )
395
						)
396
					);
397
				}
398
399
				//Let them signup for plugin updates
400 View Code Duplication
				if ( isset( $banner_arr['support_url'] ) ) {
0 ignored issues
show
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...
401
					printf(
402
						'<a href="%s" target="_blank"><span class="dashicons dashicons-sos"></span>%s</a>',
403
						esc_url( $banner_arr['support_url'] ),
404
						esc_html__( 'Get Support', 'give' )
405
					);
406
				}
407
				?>
408
			</div>
409
		</div>
410
		<?php
411
	}
412
413
	/**
414
	 * Ignore Nag.
415
	 *
416
	 * This is the action that allows the user to dismiss the banner it basically sets a tag to their user meta data
417
	 *
418
	 * @since  1.0
419
	 * @access public
420
	 */
421
	public function give_addon_notice_ignore() {
422
		/**
423
		 * If user clicks to ignore the notice, add that to their user meta the banner then checks whether this tag exists already or not.
424
		 * See here: http://codex.wordpress.org/Function_Reference/add_user_meta
425
		 */
426
		if (
427
			isset( $_GET['give_addon'], $_GET['give_addon_activation_ignore'] )
428
			&& '1' === $_GET['give_addon_activation_ignore']
429
		) {
430
			// Get the value of the 'give_addon' query string.
431
			$addon_query_arg    = sanitize_text_field( wp_unslash( $_GET['give_addon'] ) );
0 ignored issues
show
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
Detected usage of a non-sanitized input variable: $_GET
Loading history...
432
			$deactivated_addons = array();
433
434
			// If All add-on requested to dismiss.
435
			if ( 'all' === $addon_query_arg ) {
436
				// Get all activated add-ons.
437
				$give_addons = $this->get_plugin_file_names();
438
439
				if ( ! empty( $give_addons ) ) {
440
					$deactivated_addons = array_keys( $give_addons );
441
				}
442
			} else {
443
				// Store the addon to deactivate.
444
				$deactivated_addons[] = $addon_query_arg;
445
			}
446
447
			if ( ! empty( $deactivated_addons ) ) {
448
				foreach ( $deactivated_addons as $addon ) {
449
					// Record it user meta.
450
					add_user_meta( $this->user_id, "give_addon_activation_ignore_{$addon}", 'true', true );
0 ignored issues
show
add_user_meta() usage is highly discouraged, check VIP documentation on "Working with wp_users"
Loading history...
451
				}
452
			}
453
		}
454
	}
455
456
	/**
457
	 * Delete user id from option if plugin deactivated.
458
	 *
459
	 * @since  1.8
460
	 * @since  2.1.0 Added support for multiple addons.
461
	 * @access public
462
	 */
463
	public function remove_addon_activate_meta() {
464
		// Get the hook name and then grab the plugin file from it.
465
		$plugin_file = str_replace( 'deactivate_', '', current_action() );
466
467
		// Get all activated add-ons.
468
		$give_addons = $this->get_plugin_file_names();
469
470
		if ( ! empty( $give_addons ) ) {
471
			foreach ( $give_addons as $banner_addon_name => $addon ) {
472
				if ( $plugin_file === $addon['plugin_main_file'] ) {
473
474
					// Get the user meta key.
475
					$user_id = (int) __give_get_active_by_user_meta( $banner_addon_name );
476
477
					if ( $user_id ) {
478
						// Get user meta for this add-on.
479
						$nag_meta_key = "give_addon_activation_ignore_{$banner_addon_name}";
480
481
						// Delete plugin activation option key.
482
						delete_option( self::get_banner_user_meta_key( $banner_addon_name ) );
483
						// Delete user meta of plugin activation.
484
						delete_user_meta( $user_id, $nag_meta_key );
0 ignored issues
show
delete_user_meta() usage is highly discouraged, check VIP documentation on "Working with wp_users"
Loading history...
485
					}
486
				}
487
			}
488
		}
489
	}
490
491
	/**
492
	 * Get list of add-on last activated.
493
	 *
494
	 * @since 2.1.0
495
	 *
496
	 * @return mixed|array
497
	 */
498
	public function get_recently_activated_addons() {
499
		return give_get_recently_activated_addons();
500
	}
501
502
	/**
503
	 * Get the addon's folder name.
504
	 *
505
	 * @since 2.1.0
506
	 *
507
	 * @param string $main_file Plugin Main File.
508
	 *
509
	 * @return bool|mixed|string
510
	 */
511
	public function get_plugin_folder_name( $main_file ) {
512
		// Remove plugin file and get the Add-on's folder name only.
513
		$file_path       = explode( '/plugins/', $main_file );
514
		$addon_file_path = array_pop( $file_path );
515
		$addon_file_path = substr( $addon_file_path, 0, strpos( $addon_file_path, '/' ) );
516
517
		return $addon_file_path;
518
	}
519
520
	/**
521
	 * Add activation banner css and js .
522
	 *
523
	 * @since  1.8.16
524
	 * @since  2.1.0 Added JS code for multiple add-on.
525
	 * @access private
526
	 */
527
	private function print_css_js() {
528
		?>
529
		<style>
530
			div.give-addon-alert.updated {
531
				padding: 20px;
532
				position: relative;
533
				border-color: #66BB6A;
534
				min-height: 85px;
535
			}
536
537
			div.give-alert-message {
538
				margin-left: 108px;
539
			}
540
541
			div.give-addon-alert img.give-logo {
542
				max-width: 85px;
543
				float: left;
544
			}
545
546
			div.give-addon-alert h3 {
547
				margin: -5px 0 10px;
548
				font-size: 22px;
549
				font-weight: 400;
550
				line-height: 30px;
551
			}
552
553
			div.give-addon-alert h3 span {
554
				font-weight: 700;
555
				color: #66BB6A;
556
			}
557
558
			div.give-addon-alert a {
559
				color: #66BB6A;
560
			}
561
562
			div.give-addon-alert .alert-actions a {
563
				margin-right: 2em;
564
			}
565
566
			div.give-addon-alert .alert-actions a {
567
				text-decoration: underline;
568
			}
569
570
			div.give-addon-alert .alert-actions a:hover {
571
				color: #555555;
572
			}
573
574
			div.give-addon-alert .alert-actions a span {
575
				text-decoration: none;
576
				margin-right: 5px;
577
			}
578
579
			div.give-addon-alert .dismiss {
580
				position: absolute;
581
				right: 0px;
582
				height: 99%;
583
				top: 23%;
584
				margin-top: -10px;
585
				outline: none;
586
				box-shadow: none;
587
				text-decoration: none;
588
				color: #AAA;
589
			}
590
591
			div.give-addon-alert .dismiss {
592
				position: absolute;
593
				right: 20px;
594
				height: 100%;
595
				top: 50%;
596
				margin-top: -10px;
597
				outline: none;
598
				box-shadow: none;
599
				text-decoration: none;
600
				color: #AAA;
601
			}
602
603
			div.give-alert-tab-wrapper .dismiss {
604
				right: 0px !important;
605
				height: 99% !important;
606
				top: 23% !important;
607
			}
608
609
			div.give-addon-alert .dismiss:hover {
610
				color: #333;
611
			}
612
613
			ul.give-alert-addon-list {
614
				min-width: 220px;
615
				display: inline-block;
616
				float: left;
617
				max-width: 250px;
618
				padding: 0;
619
				margin: 0;
620
				max-height: 146px;
621
				overflow: hidden;
622
			}
623
624
			div.give-addon-alert .give-addon-description {
625
				padding: 1px;
626
				display: inline-block;
627
				color: #777;
628
				margin-bottom: 12px;
629
			}
630
631
			div.give-alert-tab-wrapper .give-right-side-block {
632
				width: calc(100% - 250px);
633
				display: inline-block;
634
				float: left;
635
				background: #fff;
636
				position: relative;
637
			}
638
639
			div.give-vertical-tab {
640
				width: 100%;
641
			}
642
643
			ul.give-alert-addon-list li {
644
				display: block;
645
				border: 1px solid #d1d1d18f;
646
				border-width: 1px 0px 0px 0px;
647
				margin: 0;
648
			}
649
650
			ul.give-alert-addon-list li a.inactivate {
651
				cursor: default;
652
			}
653
654
			ul.give-alert-addon-list li a {
655
				display: block;
656
				font-weight: bold;
657
				color: #a3a3a3;
658
				text-decoration: none;
659
				padding: 15px 10px 15px;
660
				box-shadow: inset -6px 0px 18px 0px rgba(204, 204, 204, 0.36);
661
				-moz-box-shadow: inset -6px 0px 18px 0px rgba(204, 204, 204, 0.36);
662
				-webkit-box-shadow: inset -6px 0px 18px 0px rgba(204, 204, 204, 0.36);
663
				-ms-box-shadow: inset -6px 0px 18px 0px rgba(204, 204, 204, 0.36);
664
				-o-box-shadow: inset -6px 0px 18px 0px rgba(204, 204, 204, 0.36);
665
			}
666
667
			ul.give-alert-addon-list li.give-tab-list.active a {
668
				color: #5f6c74;
669
				box-shadow: none;
670
			}
671
672
			div.updated.give-addon-alert.give-notice.give-alert-tab-wrapper {
673
				display: inline-block;
674
				width: 100%;
675
			}
676
677
			.give-alert-tab-wrapper .give-tab-details {
678
				display: none;
679
				min-height: 100px;
680
				position: absolute;
681
				top: 0;
682
				left: 0;
683
				padding: 20px 20px 20px 40px;
684
			}
685
686
			.give-alert-tab-wrapper .give-tab-details.active {
687
				display: block;
688
				z-index: 1;
689
				position: relative;
690
			}
691
692
			.give-alert-tab-wrapper.give-addon-alert img.give-logo {
693
				max-width: 80px;
694
			}
695
696
			.give-alert-tab-wrapper .give-alert-message {
697
				margin-left: 100px;
698
				padding-top: 10px;
699
			}
700
701
			ul.give-alert-addon-list li.give-tab-list.active {
702
				background: #fff;
703
			}
704
705
			ul.give-alert-addon-list li.give-tab-list:last-child {
706
				border-bottom: 0px solid #ccc;
707
			}
708
709
			ul.give-alert-addon-list li.give-tab-list:first-child {
710
				border-top: 0 none;
711
			}
712
713
			.give-alert-tab-wrapper {
714
				padding: 0 !important;
715
			}
716
717
			ul.give-alert-addon-list::-webkit-scrollbar {
718
				height: 10px;
719
				width: 10px;
720
				border-radius: 4px;
721
				transition: all 0.3s ease;
722
				background: rgba(158, 158, 158, 0.15);
723
			}
724
725
			ul.give-alert-addon-list::-webkit-scrollbar-thumb {
726
				background: #939395;
727
				border-radius: 4px;
728
			}
729
730
			/** Responsiveness */
731
			@media screen and (max-width: 767px) {
732
				.give-alert-tab-wrapper .give-tab-details {
733
					padding: 20px 40px 20px 20px;
734
				}
735
736
				.give-alert-tab-wrapper .give-right-side-block {
737
					width: 100%;
738
				}
739
740
				.give-alert-tab-wrapper ul.give-alert-addon-list {
741
					min-width: 100%;
742
				}
743
			}
744
		</style>
745
746
		<!-- Start of the Give Add-on tab JS -->
747
		<script type="text/javascript">
748
					jQuery( document ).ready( function( $ ) {
749
						$( '.give-alert-tab-wrapper' ).on( 'click', '.give-tab-list', function() {
750
							if ( $( this ).find( 'a' ).hasClass( 'inactivate' ) ) {
751
								return false;
752
							}
753
754
							var
755
								clicked_tab = $( this ).attr( 'id' ),
756
								addon_tab_wrapper = $( this ).closest( '.give-alert-tab-wrapper' );
757
758
							// Remove 'active' class from all tab list.
759
							$( '.give-alert-addon-list li' ).removeClass( 'active' );
760
							// Add active class to the selected tab.
761
							$( this ).addClass( 'active' );
762
							// Remove 'active' class from the details.
763
							addon_tab_wrapper.find( '.give-tab-details' ).removeClass( 'active' );
764
							addon_tab_wrapper.find( '.give-right-side-block .give-tab-details#' + clicked_tab ).addClass( 'active' );
765
766
							return false;
767
						} );
768
769
						var add_on_tabs = $( '.give-alert-addon-list' );
770
771
						add_on_tabs
772
							.mouseout( function() {
773
								$( this ).css( 'overflow', 'hidden' );
774
							} )
775
							.mouseover( function() {
776
								$( this ).css( 'overflow', 'auto' );
777
							} );
778
779
						// Prevent default click event of the add-on.
780
						add_on_tabs.find( 'li a' ).on( 'click', function( e ) {
781
							e.preventDefault();
782
						} );
783
784
						// If total length of the add-on is 2.
785
						if ( 2 === add_on_tabs.find( 'li' ).length ) {
786
							var li = $( 'li.give-tab-list' );
787
							li.last().clone().prependTo( 'ul.give-alert-addon-list' );
788
							li.last().removeAttr( 'id' ).find( 'a' ).addClass( 'inactivate' ).html( '&nbsp;' );
789
							$( '.give-tab-list:first' ).trigger( 'click' );
790
						}
791
					} );
792
		</script>
793
		<!-- End of the Give Add-on tab JS -->
794
		<?php
795
	}
796
}
797