Issues (1282)

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/class-notices.php (5 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
 * Admin Notices Class.
4
 *
5
 * @package     Give
6
 * @subpackage  Admin/Notices
7
 * @copyright   Copyright (c) 2016, GiveWP
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.8.9
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Give_Notices Class
19
 *
20
 * @since 1.8.9
21
 */
22
class Give_Notices {
23
	/**
24
	 * List of notices
25
	 * @var array
26
	 * @since  1.8.9
27
	 * @access private
28
	 */
29
	private static $notices = array();
30
31
32
	/**
33
	 * Flag to check if any notice auto dismissible among all notices
34
	 *
35
	 * @since  1.8.9
36
	 * @access private
37
	 * @var bool
38
	 */
39
	private static $has_auto_dismissible_notice = false;
40
41
	/**
42
	 * Flag to check if any notice has dismiss interval among all notices
43
	 *
44
	 * @since  1.8.9
45
	 * @access private
46
	 * @var bool
47
	 */
48
	private static $has_dismiss_interval_notice = false;
49
50
	/**
51
	 * Get things started.
52
	 *
53
	 * @since 1.8.9
54
	 */
55
	public function __construct() {
56
		add_action( 'admin_notices', array( $this, 'render_admin_notices' ), 999 );
57
		add_action( 'admin_footer', array( $this, '__reveal_notices' ) );
58
		add_action( 'give_dismiss_notices', array( $this, 'dismiss_notices' ) );
59
60
		add_action( 'give_frontend_notices', array( $this, 'render_frontend_notices' ), 999 );
61
		add_action( 'give_pre_form_output', array( $this, 'render_frontend_form_notices' ), 10, 1 );
62
		add_action( 'give_ajax_donation_errors', array( $this, 'render_frontend_notices' ) );
63
64
		/**
65
		 * Backward compatibility for deprecated params.
66
		 *
67
		 * @since 1.8.14
68
		 */
69
		add_filter( 'give_register_notice_args', array( $this, 'bc_deprecated_params' ) );
70
		add_filter( 'give_frontend_errors_args', array( $this, 'bc_deprecated_params' ) );
71
		add_filter( 'give_frontend_notice_args', array( $this, 'bc_deprecated_params' ) );
72
	}
73
74
	/**
75
	 * Add backward compatibility to deprecated params.
76
	 *
77
	 * @since  1.8.14
78
	 * @access public
79
	 *
80
	 * @param array $args Array of notice params
81
	 *
82
	 * @return array
83
	 */
84
	public function bc_deprecated_params( $args ) {
85
		/**
86
		 *  Param: auto_dismissible
87
		 *  deprecated in 1.8.14
88
		 *
89
		 *  Check if auto_dismissible is set and it true then unset and change dismissible parameter value to auto
90
		 */
91
		if ( isset( $args['auto_dismissible'] ) ) {
92
			if ( ! empty( $args['auto_dismissible'] ) ) {
93
				$args['dismissible'] = 'auto';
94
			}
95
			// unset auto_dismissible as it has been deprecated.
96
			unset( $args['auto_dismissible'] );
97
		}
98
99
		return $args;
100
	}
101
102
	/**
103
	 * Register notice.
104
	 *
105
	 * @since  1.8.9
106
	 * @access public
107
	 *
108
	 * @param $notice_args
109
	 *
110
	 * @return bool
111
	 */
112
	public function register_notice( $notice_args ) {
113
		// Bailout.
114
		if ( empty( $notice_args['id'] ) || array_key_exists( $notice_args['id'], self::$notices ) ) {
115
			return false;
116
		}
117
118
		$notice_args = wp_parse_args(
119
			$notice_args,
120
			array(
121
				'id'                    => '',
122
				'description'           => '',
123
124
				/*
125
				 * Add custom notice html
126
				 * Note: This param has more priority then description, so if you have  both param then this one will be use
127
				 *       for generating notice html. Most of feature of notice attach to core generated html, so if you set
128
				 *       custom html then please add required classes and data attribute which help to apply feature on notice.
129
				 *
130
				 * @since 1.8.16
131
				 */
132
				'description_html'      => '',
133
134
				/*
135
				 * Add New Parameter and remove the auto_dismissible parameter.
136
				 * Value: auto/true/false
137
				 *
138
				 * @since 1.8.14
139
				 */
140
				'dismissible'           => true,
141
142
				// Value: error/warning/success/info/updated
143
				'type'                  => 'error',
144
145
				// Value: null/user/all
146
				'dismissible_type'      => null,
147
148
				// Value: shortly/permanent/null/custom
149
				'dismiss_interval'      => null,
150
151
				// Only set it when custom is defined.
152
				'dismiss_interval_time' => null,
153
154
155
			)
156
		);
157
158
		/**
159
		 * Filter to modify Notice args before it get add
160
		 *
161
		 * @since 1.8.14
162
		 */
163
		$notice_args = apply_filters( 'give_register_notice_args', $notice_args );
164
165
		// Set extra dismiss links if any.
166
		if ( false !== strpos( $notice_args['description'], 'data-dismiss-interval' ) ) {
167
168
			preg_match_all( "/data-([^\"]*)=\"([^\"]*)\"/", $notice_args['description'], $extra_notice_dismiss_link );
169
170
			if ( ! empty( $extra_notice_dismiss_link ) ) {
171
				$extra_notice_dismiss_links = array_chunk( current( $extra_notice_dismiss_link ), 3 );
172
				foreach ( $extra_notice_dismiss_links as $extra_notice_dismiss_link ) {
173
					// Create array og key ==> value by parsing query string created after renaming data attributes.
174
					$data_attribute_query_str = str_replace( array( 'data-', '-', '"' ), array(
175
						'',
176
						'_',
177
						'',
178
					), implode( '&', $extra_notice_dismiss_link ) );
179
180
					$notice_args['extra_links'][] = wp_parse_args( $data_attribute_query_str );
181
				}
182
			}
183
		}
184
185
186
		self::$notices[ $notice_args['id'] ] = $notice_args;
187
188
		// Auto set show param if not already set.
189
		if ( ! isset( self::$notices[ $notice_args['id'] ]['show'] ) ) {
190
			self::$notices[ $notice_args['id'] ]['show'] = $this->is_notice_dismissed( $notice_args ) ? false : true;
191
		}
192
193
		// Auto set time interval for shortly.
194
		if ( 'shortly' === self::$notices[ $notice_args['id'] ]['dismiss_interval'] ) {
195
			self::$notices[ $notice_args['id'] ]['dismiss_interval_time'] = DAY_IN_SECONDS;
196
		}
197
198
		return true;
199
	}
200
201
	/**
202
	 * Display notice.
203
	 *
204
	 * @since 1.8.9
205
	 *
206
	 */
207
	public function render_admin_notices() {
208
		/* @var WP_Screen $wp_screen */
209
		$wp_screen = get_current_screen();
210
211
		// Bailout.
212
		if ( empty( self::$notices ) ) {
213
			return;
214
		}
215
216
		// Do not render notices on Gutenberg editor page.
217
		if (
218
			method_exists( $wp_screen, 'is_block_editor' )
219
			&& $wp_screen->is_block_editor()
220
		) {
221
			return;
222
		}
223
224
		// Do not render notices on these pages as well.
225
		// We don't want to annoy admins with notices on important screens like WP or GiveWP updates, etc.
226
		if (
227
			'update-core' === $wp_screen->id
228
			|| 'give_forms_page_give-addons' === $wp_screen->id
229
			|| 'give_forms_page_give-updates' === $wp_screen->id
230
		) {
231
			return;
232
		}
233
234
		$output = '';
235
236
		foreach ( self::$notices as $notice_id => $notice ) {
237
			// Check flag set to true to show notice.
238
			if ( ! $notice['show'] ) {
239
				continue;
240
			}
241
242
243
			// Render custom html.
244
			if( ! empty( $notice['description_html'] ) ) {
245
				$output .= "{$notice['description_html']} \n";
246
				continue;
247
			}
248
249
			// Check if notice dismissible or not.
250
			if ( ! self::$has_auto_dismissible_notice ) {
251
				self::$has_auto_dismissible_notice = ( 'auto' === $notice['dismissible'] );
252
			}
253
254
			// Check if notice dismissible or not.
255
			if ( ! self::$has_dismiss_interval_notice ) {
256
				self::$has_dismiss_interval_notice = $notice['dismiss_interval'];
257
			}
258
259
			$css_id = ( false === strpos( $notice['id'], 'give' ) ? "give-{$notice['id']}" : $notice['id'] );
260
261
			$css_class = 'give-notice notice ' . ( empty( $notice['dismissible'] ) ? 'non' : 'is' ) . "-dismissible {$notice['type']} notice-{$notice['type']}";
262
			$output    .= sprintf(
263
				'<div id="%1$s" class="%2$s" data-dismissible="%3$s" data-dismissible-type="%4$s" data-dismiss-interval="%5$s" data-notice-id="%6$s" data-security="%7$s" data-dismiss-interval-time="%8$s" style="display: none">' . " \n",
264
				$css_id,
265
				$css_class,
266
				give_clean( $notice['dismissible'] ),
267
				$notice['dismissible_type'],
268
				$notice['dismiss_interval'],
269
				$notice['id'],
270
				empty( $notice['dismissible_type'] ) ? '' : wp_create_nonce( "give_edit_{$notice_id}_notice" ),
271
				$notice['dismiss_interval_time']
272
			);
273
274
			$output .= ( 0 === strpos( $notice['description'], '<div' ) || 0 === strpos( $notice['description'], '<p' ) ? $notice['description'] : "<p>{$notice['description']}</p>" );
275
			$output .= "</div> \n";
276
		}
277
278
		echo $output;
279
280
		$this->print_js();
281
	}
282
283
284
	/**
285
	 * Render give frontend notices.
286
	 *
287
	 * @since  1.8.9
288
	 * @access public
289
	 *
290
	 * @param int $form_id
291
	 */
292
	public function render_frontend_notices( $form_id = 0 ) {
293
		$errors = give_get_errors();
294
295
		$request_form_id = isset( $_REQUEST['form-id'] ) ? absint( $_REQUEST['form-id'] ) : 0;
296
297
		// Sanity checks first: Ensure that gateway returned errors display on the appropriate form.
298
		if ( ! isset( $_POST['give_ajax'] ) && $request_form_id !== $form_id ) {
299
			return;
300
		}
301
302
		if ( $errors ) {
303
			self::print_frontend_errors( $errors );
0 ignored issues
show
It seems like $errors defined by give_get_errors() on line 293 can also be of type string; however, Give_Notices::print_frontend_errors() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
304
305
			give_clear_errors();
306
		}
307
	}
308
309
	/**
310
	 * Renders notices for different actions depending on
311
	 * the type of form display option.
312
	 *
313
	 * @since 2.2
314
	 * @access public
315
	 *
316
	 * @param int $form_id Form ID.
317
	 *
318
	 * @return void
319
	 */
320
	public function render_frontend_form_notices( $form_id ) {
321
		$display_option = give_get_meta( $form_id, '_give_payment_display', true );
322
323
		if ( 'modal' === $display_option ) {
324
			add_action( 'give_payment_mode_top', array( $this, 'render_frontend_notices' ) );
325
		} else {
326
			add_action( 'give_pre_form', array( $this, 'render_frontend_notices' ), 11 );
327
		}
328
	}
329
330
	/**
331
	 * Print notice js.
332
	 *
333
	 * @since  1.8.9
334
	 * @access private
335
	 */
336
	private function print_js() {
337
		if ( self::$has_auto_dismissible_notice ) :
338
			?>
339
			<script>
340
				jQuery(document).ready(function () {
341
					// auto hide setting message in 5 seconds.
342
					window.setTimeout(
343
						function () {
344
							jQuery('.give-notice[data-dismissible="auto"]').slideUp();
345
						},
346
						5000
347
					);
348
				})
349
			</script>
350
			<?php
351
		endif;
352
353
		if ( self::$has_dismiss_interval_notice ) :
354
			?>
355
			<script>
356
				jQuery(document).ready(function () {
357
					var $body = jQuery('body');
358
359
					$body.on('click', '.give_dismiss_notice', function (e) {
360
						var $parent            = jQuery(this).parents('.give-notice'),
361
							custom_notice_data = {
362
								'dismissible_type': jQuery(this).data('dismissible-type'),
363
								'dismiss_interval': jQuery(this).data('dismiss-interval'),
364
								'dismiss_interval_time': jQuery(this).data('dismiss-interval-time')
365
							};
366
367
						$parent.find('button.notice-dismiss').trigger('click', [custom_notice_data]);
368
						return false;
369
					});
370
371
					$body.on('click', 'button.notice-dismiss', function (e, custom_notice_data) {
372
						var $parent            = jQuery(this).parents('.give-notice'),
373
							custom_notice_data = custom_notice_data || {};
374
375
						e.preventDefault();
376
377
						var data = {
378
							'give-action': 'dismiss_notices',
379
							'notice_id': $parent.data('notice-id'),
380
							'dismissible_type': $parent.data('dismissible-type'),
381
							'dismiss_interval': $parent.data('dismiss-interval'),
382
							'dismiss_interval_time': $parent.data('dismiss-interval-time'),
383
							'_wpnonce': $parent.data('security')
384
						};
385
386
						if (Object.keys(custom_notice_data).length) {
387
							jQuery.extend(data, custom_notice_data);
388
						}
389
390
						// Bailout.
391
						if (
392
							!data.dismiss_interval ||
393
							!data.dismissible_type
394
						) {
395
							return false;
396
						}
397
398
						jQuery.post(
399
							'<?php echo admin_url(); ?>admin-ajax.php',
400
							data,
401
							function (response) {
402
403
							})
404
					})
405
				});
406
			</script>
407
			<?php
408
		endif;
409
	}
410
411
	/**
412
	 * Show notices
413
	 * Note: only for internal use
414
	 *
415
	 * @since 2.3.0
416
	 */
417
	public function __reveal_notices(){
418
		?>
419
		<script>
420
			jQuery(document).ready(function($){
421
				// Fix notice appearance issue.
422
				window.setTimeout(
423
					function(){
424
						var give_notices = $('.give-notice');
425
426
						if( give_notices.length ) {
427
							give_notices.slideDown();
428
						}
429
					},
430
					1000
431
				);
432
			});
433
		</script>
434
		<?php
435
	}
436
437
438
	/**
439
	 * Hide notice.
440
	 *
441
	 * @since  1.8.9
442
	 * @access public
443
	 */
444
	public function dismiss_notices() {
445
		$_post     = give_clean( $_POST );
446
		$notice_id = esc_attr( $_post['notice_id'] );
447
448
		// Bailout.
449
		if (
450
			empty( $notice_id ) ||
451
			empty( $_post['dismissible_type'] ) ||
452
			empty( $_post['dismiss_interval'] ) ||
453
			! check_ajax_referer( "give_edit_{$notice_id}_notice", '_wpnonce' )
454
		) {
455
			wp_send_json_error();
456
		}
457
458
		$notice_key = Give()->notices->get_notice_key( $notice_id, $_post['dismiss_interval'] );
459 View Code Duplication
		if ( 'user' === $_post['dismissible_type'] ) {
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...
460
			$current_user = wp_get_current_user();
461
			$notice_key   = Give()->notices->get_notice_key( $notice_id, $_post['dismiss_interval'], $current_user->ID );
462
		}
463
464
		$notice_dismiss_time = ! empty( $_post['dismiss_interval_time'] ) ? $_post['dismiss_interval_time'] : null;
465
466
		// Save option to hide notice.
467
		Give_Cache::set( $notice_key, true, $notice_dismiss_time, true );
468
469
		/**
470
		 * Fire the action when notice dismissed
471
		 *
472
		 * @since 2.2.0
473
		 */
474
		do_action( 'give_notice_dismissed', $_post );
475
476
		wp_send_json_success();
477
	}
478
479
480
	/**
481
	 * Get notice key.
482
	 *
483
	 * @since  1.8.9
484
	 * @access public
485
	 *
486
	 * @param string $notice_id
487
	 * @param string $dismiss_interval
488
	 * @param int    $user_id
489
	 *
490
	 * @return string
491
	 */
492
	public function get_notice_key( $notice_id, $dismiss_interval = null, $user_id = 0 ) {
493
		$notice_key = "_give_notice_{$notice_id}";
494
495
		if ( ! empty( $dismiss_interval ) ) {
496
			$notice_key .= "_{$dismiss_interval}";
497
		}
498
499
		if ( $user_id ) {
500
			$notice_key .= "_{$user_id}";
501
		}
502
503
		$notice_key = sanitize_key( $notice_key );
504
505
		return $notice_key;
506
	}
507
508
509
	/**
510
	 * Get notice dismiss link.
511
	 *
512
	 * @param $notice_args
513
	 *
514
	 * @return string
515
	 */
516
	public function get_dismiss_link( $notice_args ) {
517
		$notice_args = wp_parse_args(
518
			$notice_args,
519
			array(
520
				'title'                 => __( 'Click here', 'give' ),
521
				'dismissible_type'      => '',
522
				'dismiss_interval'      => '',
523
				'dismiss_interval_time' => null,
524
			)
525
		);
526
527
		return sprintf(
528
			'<a href="#" class="give_dismiss_notice" data-dismissible-type="%1$s" data-dismiss-interval="%2$s" data-dismiss-interval-time="%3$s">%4$s</a>',
529
			$notice_args['dismissible_type'],
530
			$notice_args['dismiss_interval'],
531
			$notice_args['dismiss_interval_time'],
532
			$notice_args['title']
533
		);
534
	}
535
536
537
	/**
538
	 * Check if notice dismissed or not
539
	 *
540
	 * @since  1.8.9
541
	 * @access public
542
	 *
543
	 * @param array $notice
544
	 *
545
	 * @return bool|null
546
	 */
547
	public function is_notice_dismissed( $notice ) {
548
		$notice_key          = $this->get_notice_key( $notice['id'], $notice['dismiss_interval'] );
549
		$is_notice_dismissed = false;
0 ignored issues
show
$is_notice_dismissed 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...
550
551 View Code Duplication
		if ( 'user' === $notice['dismissible_type'] ) {
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...
552
			$current_user = wp_get_current_user();
553
			$notice_key   = Give()->notices->get_notice_key( $notice['id'], $notice['dismiss_interval'], $current_user->ID );
554
		}
555
556
		$notice_data = Give_Cache::get( $notice_key, true );
557
558
		// Find notice dismiss link status if notice has extra dismissible links.
559
		if ( ( empty( $notice_data ) || is_wp_error( $notice_data ) ) && ! empty( $notice['extra_links'] ) ) {
560
561
			foreach ( $notice['extra_links'] as $extra_link ) {
562
				$new_notice_data = wp_parse_args( $extra_link, $notice );
563
				unset( $new_notice_data['extra_links'] );
564
565
				if ( $is_notice_dismissed = $this->is_notice_dismissed( $new_notice_data ) ) {
566
					return $is_notice_dismissed;
567
				}
568
			}
569
		}
570
571
		$is_notice_dismissed = ! empty( $notice_data ) && ! is_wp_error( $notice_data );
572
573
		return $is_notice_dismissed;
574
	}
575
576
577
	/**
578
	 * Print frontend errors.
579
	 *
580
	 * @since  1.8.9
581
	 * @access public
582
	 *
583
	 * @param array $errors
584
	 */
585
	public static function print_frontend_errors( $errors ) {
586
		// Bailout.
587
		if ( ! $errors ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $errors 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...
588
			return;
589
		}
590
591
		/**
592
		 * Change auto_dismissible to dismissible and set the value to true
593
		 *
594
		 * @since 1.8.14
595
		 */
596
		$default_notice_args = array(
597
			'dismissible'      => true,
598
			'dismiss_interval' => 5000,
599
		);
600
601
		// Note: we will remove give_errors class in future.
602
		$classes = apply_filters( 'give_error_class', array( 'give_notices', 'give_errors' ) );
603
604
		echo sprintf( '<div class="%s">', implode( ' ', $classes ) );
605
606
		// Loop error codes and display errors.
607
		foreach ( $errors as $error_id => $error ) {
608
			// Backward compatibility v<1.8.11
609
			if ( is_string( $error ) ) {
610
				$error = array(
611
					'message'     => $error,
612
					'notice_args' => array(),
613
				);
614
			}
615
616
			$notice_args = wp_parse_args( $error['notice_args'], $default_notice_args );
617
618
			/**
619
			 * Filter to modify Frontend Errors args before errors is display.
620
			 *
621
			 * @since 1.8.14
622
			 */
623
			$notice_args = apply_filters( 'give_frontend_errors_args', $notice_args );
624
625
			echo sprintf(
626
				'<div class="give_error give_notice" id="give_error_%1$s" data-dismissible="%2$s" data-dismiss-interval="%3$d">
627
						<p><strong>%4$s</strong>: %5$s</p>
628
					</div>',
629
				$error_id,
630
				give_clean( $notice_args['dismissible'] ),
631
				absint( $notice_args['dismiss_interval'] ),
632
				esc_html__( 'Error', 'give' ),
633
				$error['message']
634
			);
635
		}
636
637
		echo '</div>';
638
	}
639
640
	/**
641
	 * Print frontend notice.
642
	 * Notice: notice type can be success/error/warning
643
	 *
644
	 * @since  1.8.9
645
	 * @access public
646
	 *
647
	 * @param string $message
648
	 * @param bool   $echo
649
	 * @param string $notice_type
650
	 * @param array  $notice_args
651
	 *
652
	 * @return  string
653
	 */
654
	public static function print_frontend_notice( $message, $echo = true, $notice_type = 'warning', $notice_args = array() ) {
655
		if ( empty( $message ) ) {
656
			return '';
657
		}
658
659
		/**
660
		 * Change auto_dismissible to dismissible and set the value to true
661
		 *
662
		 * @since 1.8.14
663
		 */
664
		$default_notice_args = array(
665
			'dismissible'      => false,
666
			'dismiss_type'     => 'auto',
667
			'dismiss_interval' => 5000,
668
		);
669
670
		$notice_args = wp_parse_args( $notice_args, $default_notice_args );
671
672
		// Notice dismissible must be true for dismiss type.
673
		$notice_args['dismiss_type'] = ! $notice_args['dismissible'] ? '' : $notice_args['dismiss_type'];
674
675
		/**
676
		 * Filter to modify Frontend notice args before notices is display.
677
		 *
678
		 * @since 1.8.14
679
		 */
680
		$notice_args = apply_filters( 'give_frontend_notice_args', $notice_args );
681
682
		$close_icon = 'manual' === $notice_args['dismiss_type'] ?
683
			sprintf(
684
				'<img class="notice-dismiss give-notice-close" src="%s" />',
685
				esc_url( GIVE_PLUGIN_URL . 'assets/dist/images/close.svg' )
686
687
			) :
688
			'';
689
690
		// Note: we will remove give_errors class in future.
691
		$error = sprintf(
692
			'<div class="give_notices give_errors" id="give_error_%1$s">
693
						<p class="give_notice give_%1$s" data-dismissible="%2$s" data-dismiss-interval="%3$d" data-dismiss-type="%4$s">
694
							%5$s
695
						</p>
696
						%6$s
697
					</div>',
698
			$notice_type,
699
			give_clean( $notice_args['dismissible'] ),
700
			absint( $notice_args['dismiss_interval'] ),
701
			give_clean( $notice_args['dismiss_type'] ),
702
			$message,
703
			$close_icon
704
705
		);
706
707
		if ( ! $echo ) {
708
			return $error;
709
		}
710
711
		echo $error;
712
	}
713
714
	/**
715
	 * Print Inline Notice.
716
	 * Note: dismissible feature will note work if notice will add to dom by javascript after document load.
717
	 *
718
	 * @param array $notice_args An array of notice arguments.
719
	 *
720
	 * @todo   Implement render_admin_notices function within this function in future.
721
	 *
722
	 * @access public
723
	 * @since  1.8.17
724
	 *
725
	 * @return string
726
	 */
727
	public function print_admin_notices( $notice_args = array() ) {
728
		// Bailout.
729
		if ( empty( $notice_args['description'] ) ) {
730
			return '';
731
		}
732
733
		$defaults    = array(
734
			'id'          => '',
735
			'echo'        => true,
736
			'notice_type' => 'warning',
737
			'dismissible' => true,
738
		);
739
		$notice_args = wp_parse_args( $notice_args, $defaults );
740
741
		$output    = '';
742
		$css_id    = ! empty( $notice_args['id'] ) ? $notice_args['id'] : uniqid( 'give-inline-notice-' );
743
		$css_class = "notice-{$notice_args['notice_type']} give-notice notice inline";
744
		$css_class .= ( $notice_args['dismissible'] ) ? ' is-dismissible' : '';
745
		$output    .= sprintf(
746
			'<div id="%1$s" class="%2$s"><p>%3$s</p></div>',
747
			$css_id,
748
			$css_class,
749
			$notice_args['description']
750
		);
751
752
		if ( ! $notice_args['echo'] ) {
753
			return $output;
754
		}
755
756
		echo $output;
757
	}
758
}
759