Current File : /home/kelaby89/jrncommunityhousing.charity/wp-content/plugins/give/includes/class-notices.php |
<?php
/**
* Admin Notices Class.
*
* @package Give
* @subpackage Admin/Notices
* @copyright Copyright (c) 2016, GiveWP
* @license https://opensource.org/licenses/gpl-license GNU Public License
* @since 1.8.9
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Give_Notices Class
*
* @since 1.8.9
*/
class Give_Notices {
/**
* List of notices
*
* @var array
* @since 1.8.9
* @access private
*/
private static $notices = [];
/**
* Flag to check if any notice auto dismissible among all notices
*
* @since 1.8.9
* @access private
* @var bool
*/
private static $has_auto_dismissible_notice = false;
/**
* Flag to check if any notice has dismiss interval among all notices
*
* @since 1.8.9
* @access private
* @var bool
*/
private static $has_dismiss_interval_notice = false;
/**
* Get things started.
*
* @since 1.8.9
*/
public function __construct() {
add_action( 'admin_notices', [ $this, 'render_admin_notices' ], 999 );
add_action( 'admin_footer', [ $this, '__reveal_notices' ] );
add_action( 'give_dismiss_notices', [ $this, 'dismiss_notices' ] );
add_action( 'give_frontend_notices', [ $this, 'render_frontend_notices' ], 999 );
add_action( 'give_pre_form_output', [ $this, 'render_frontend_form_notices' ], 10, 1 );
add_action( 'give_ajax_donation_errors', [ $this, 'render_frontend_notices' ] );
/**
* Backward compatibility for deprecated params.
*
* @since 1.8.14
*/
add_filter( 'give_register_notice_args', [ $this, 'bc_deprecated_params' ] );
add_filter( 'give_frontend_errors_args', [ $this, 'bc_deprecated_params' ] );
add_filter( 'give_frontend_notice_args', [ $this, 'bc_deprecated_params' ] );
}
/**
* Add backward compatibility to deprecated params.
*
* @since 1.8.14
* @access public
*
* @param array $args Array of notice params
*
* @return array
*/
public function bc_deprecated_params( $args ) {
/**
* Param: auto_dismissible
* deprecated in 1.8.14
*
* Check if auto_dismissible is set and it true then unset and change dismissible parameter value to auto
*/
if ( isset( $args['auto_dismissible'] ) ) {
if ( ! empty( $args['auto_dismissible'] ) ) {
$args['dismissible'] = 'auto';
}
// unset auto_dismissible as it has been deprecated.
unset( $args['auto_dismissible'] );
}
return $args;
}
/**
* Register notice.
*
* @since 1.8.9
* @access public
*
* @param $notice_args
*
* @return bool
*/
public function register_notice( $notice_args ) {
// Bailout.
if ( empty( $notice_args['id'] ) || array_key_exists( $notice_args['id'], self::$notices ) ) {
return false;
}
$notice_args = wp_parse_args(
$notice_args,
[
'id' => '',
'description' => '',
/*
* Add custom notice html
* Note: This param has more priority than description, so if you use both params then this one will be used
* for generating notice html. Most features of the notice attach to core generated html, so if you set
* custom html then please add required classes and data attribute which help to apply features on notice.
*
* @since 1.8.16
*/
'description_html' => '',
/*
* Add New Parameter and remove the auto_dismissible parameter.
* Value: auto/true/false
*
* @since 1.8.14
*/
'dismissible' => true,
// Value: error/warning/success/info/updated
'type' => 'error',
// Value: null/user/all
'dismissible_type' => null,
// Value: shortly/permanent/null/custom
'dismiss_interval' => null,
// Only set it when custom is defined.
'dismiss_interval_time' => null,
]
);
/**
* Filter to modify Notice args before it get add
*
* @since 1.8.14
*/
$notice_args = apply_filters( 'give_register_notice_args', $notice_args );
// Set extra dismiss links if any.
if ( false !== strpos( $notice_args['description'], 'data-dismiss-interval' ) ) {
preg_match_all( '/data-([^"]*)="([^"]*)"/', $notice_args['description'], $extra_notice_dismiss_link );
if ( ! empty( $extra_notice_dismiss_link ) ) {
$extra_notice_dismiss_links = array_chunk( current( $extra_notice_dismiss_link ), 3 );
foreach ( $extra_notice_dismiss_links as $extra_notice_dismiss_link ) {
// Create array of key ==> value by parsing query string created after renaming data attributes.
$data_attribute_query_str = str_replace(
[ 'data-', '-', '"' ],
[
'',
'_',
'',
],
implode( '&', $extra_notice_dismiss_link )
);
$notice_args['extra_links'][] = wp_parse_args( $data_attribute_query_str );
}
}
}
self::$notices[ $notice_args['id'] ] = $notice_args;
// Auto set show param if not already set.
if ( ! isset( self::$notices[ $notice_args['id'] ]['show'] ) ) {
self::$notices[ $notice_args['id'] ]['show'] = $this->is_notice_dismissed( $notice_args ) ? false : true;
}
// Auto set time interval for shortly.
if ( 'shortly' === self::$notices[ $notice_args['id'] ]['dismiss_interval'] ) {
self::$notices[ $notice_args['id'] ]['dismiss_interval_time'] = DAY_IN_SECONDS;
}
return true;
}
/**
* Display notice.
*
* @since 1.8.9
*/
public function render_admin_notices() {
/* @var WP_Screen $wp_screen */
$wp_screen = get_current_screen();
// Bailout.
if ( empty( self::$notices ) ) {
return;
}
// Do not render notices on Gutenberg editor page.
if (
method_exists( $wp_screen, 'is_block_editor' )
&& $wp_screen->is_block_editor()
) {
return;
}
// Do not render notices on these pages as well.
// We don't want to annoy admins with notices on important screens like WP or GiveWP updates, etc.
if (
'update-core' === $wp_screen->id
|| 'give_forms_page_give-addons' === $wp_screen->id
|| 'give_forms_page_give-updates' === $wp_screen->id
) {
return;
}
$output = '';
foreach ( self::$notices as $notice_id => $notice ) {
// Check flag set to true to show notice.
if ( ! $notice['show'] ) {
continue;
}
// Render custom html.
if ( ! empty( $notice['description_html'] ) ) {
$output .= "{$notice['description_html']} \n";
continue;
}
// Check if notice dismissible or not.
if ( ! self::$has_auto_dismissible_notice ) {
self::$has_auto_dismissible_notice = ( 'auto' === $notice['dismissible'] );
}
// Check if notice dismissible or not.
if ( ! self::$has_dismiss_interval_notice ) {
self::$has_dismiss_interval_notice = $notice['dismiss_interval'];
}
$css_id = ( false === strpos( $notice['id'], 'give' ) ? "give-{$notice['id']}" : $notice['id'] );
$css_class = 'give-notice notice ' . ( empty( $notice['dismissible'] ) ? 'non' : 'is' ) . "-dismissible {$notice['type']} notice-{$notice['type']}";
$output .= sprintf(
'<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",
$css_id,
$css_class,
give_clean( $notice['dismissible'] ),
$notice['dismissible_type'],
$notice['dismiss_interval'],
$notice['id'],
empty( $notice['dismissible_type'] ) ? '' : wp_create_nonce( "give_edit_{$notice_id}_notice" ),
$notice['dismiss_interval_time']
);
$output .= ( 0 === strpos( $notice['description'], '<div' ) || 0 === strpos( $notice['description'], '<p' ) ? $notice['description'] : "<p>{$notice['description']}</p>" );
$output .= "</div> \n";
}
echo $output;
$this->print_js();
}
/**
* Render give frontend notices.
*
* @since 3.1.0 Render errors on Ajax request (Donation form validation - v2 forms)
* @since 2.32.0 Display registered error on donation form.
* @since 1.8.9
* @access public
*
* @param int $form_id
*/
public function render_frontend_notices($form_id = 0)
{
$errors = give_get_errors();
$request_form_id = isset($_REQUEST['form-id']) ? absint($_REQUEST['form-id']) : 0;
// Sanity checks first:
// - Ensure that gateway returned errors display on the appropriate form.
// - Error should exist.
if (! $errors || ($request_form_id && $request_form_id !== $form_id)) {
return;
}
self::print_frontend_errors($errors);
give_clear_errors();
}
/**
* Renders notices for different actions depending on
* the type of form display option.
*
* @since 2.2
* @access public
*
* @param int $form_id Form ID.
*
* @return void
*/
public function render_frontend_form_notices( $form_id ) {
$display_option = give_get_meta( $form_id, '_give_payment_display', true );
if ( 'modal' === $display_option ) {
add_action( 'give_payment_mode_top', [ $this, 'render_frontend_notices' ] );
} else {
add_action( 'give_pre_form', [ $this, 'render_frontend_notices' ], 11 );
}
}
/**
* Print notice js.
*
* @since 1.8.9
* @access private
*/
private function print_js() {
if ( self::$has_auto_dismissible_notice ) :
?>
<script>
jQuery(document).ready(function () {
// auto hide setting message in 5 seconds.
window.setTimeout(
function () {
jQuery('.give-notice[data-dismissible="auto"]').slideUp();
},
5000
);
})
</script>
<?php
endif;
if ( self::$has_dismiss_interval_notice ) :
?>
<script>
jQuery(document).ready(function () {
var $body = jQuery('body');
$body.on('click', '.give_dismiss_notice', function (e) {
var $parent = jQuery(this).parents('.give-notice'),
custom_notice_data = {
'dismissible_type': jQuery(this).data('dismissible-type'),
'dismiss_interval': jQuery(this).data('dismiss-interval'),
'dismiss_interval_time': jQuery(this).data('dismiss-interval-time')
};
$parent.find('button.notice-dismiss').trigger('click', [custom_notice_data]);
return false;
});
$body.on('click', 'button.notice-dismiss', function (e, custom_notice_data) {
var $parent = jQuery(this).parents('.give-notice'),
custom_notice_data = custom_notice_data || {};
e.preventDefault();
var data = {
'give-action': 'dismiss_notices',
'notice_id': $parent.data('notice-id'),
'dismissible_type': $parent.data('dismissible-type'),
'dismiss_interval': $parent.data('dismiss-interval'),
'dismiss_interval_time': $parent.data('dismiss-interval-time'),
'_wpnonce': $parent.data('security')
};
if (Object.keys(custom_notice_data).length) {
jQuery.extend(data, custom_notice_data);
}
// Bailout.
if (
!data.dismiss_interval ||
!data.dismissible_type
) {
return false;
}
jQuery.post(
'<?php echo admin_url(); ?>admin-ajax.php',
data,
function (response) {
})
})
});
</script>
<?php
endif;
}
/**
* Show notices
* Note: only for internal use
*
* @since 2.3.0
*/
public function __reveal_notices() {
?>
<script>
jQuery(document).ready(function($){
// Fix notice appearance issue.
var give_notices = $('.give-notice');
if( give_notices.length ) {
give_notices.show();
}
});
</script>
<?php
}
/**
* Hide notice.
*
* @since 1.8.9
* @access public
*/
public function dismiss_notices() {
$_post = give_clean( $_POST );
$notice_id = esc_attr( $_post['notice_id'] );
// Bailout.
if (
empty( $notice_id ) ||
empty( $_post['dismissible_type'] ) ||
empty( $_post['dismiss_interval'] ) ||
! check_ajax_referer( "give_edit_{$notice_id}_notice", '_wpnonce' )
) {
wp_send_json_error();
}
$notice_key = Give()->notices->get_notice_key( $notice_id, $_post['dismiss_interval'] );
if ( 'user' === $_post['dismissible_type'] ) {
$current_user = wp_get_current_user();
$notice_key = Give()->notices->get_notice_key( $notice_id, $_post['dismiss_interval'], $current_user->ID );
}
$notice_dismiss_time = ! empty( $_post['dismiss_interval_time'] ) ? $_post['dismiss_interval_time'] : null;
// Save option to hide notice.
Give_Cache::set( $notice_key, true, $notice_dismiss_time, true );
/**
* Fire the action when notice dismissed
*
* @since 2.2.0
*/
do_action( 'give_notice_dismissed', $_post );
wp_send_json_success();
}
/**
* Get notice key.
*
* @since 1.8.9
* @access public
*
* @param string $notice_id
* @param string $dismiss_interval
* @param int $user_id
*
* @return string
*/
public function get_notice_key( $notice_id, $dismiss_interval = null, $user_id = 0 ) {
$notice_key = "_give_notice_{$notice_id}";
if ( ! empty( $dismiss_interval ) ) {
$notice_key .= "_{$dismiss_interval}";
}
if ( $user_id ) {
$notice_key .= "_{$user_id}";
}
$notice_key = sanitize_key( $notice_key );
return $notice_key;
}
/**
* Get notice dismiss link.
*
* @param $notice_args
*
* @return string
*/
public function get_dismiss_link( $notice_args ) {
$notice_args = wp_parse_args(
$notice_args,
[
'title' => __( 'Click here', 'give' ),
'dismissible_type' => '',
'dismiss_interval' => '',
'dismiss_interval_time' => null,
]
);
return sprintf(
'<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>',
$notice_args['dismissible_type'],
$notice_args['dismiss_interval'],
$notice_args['dismiss_interval_time'],
$notice_args['title']
);
}
/**
* Check if notice dismissed or not
*
* @since 1.8.9
* @access public
*
* @param array $notice
*
* @return bool|null
*/
public function is_notice_dismissed( $notice ) {
$notice_key = $this->get_notice_key( $notice['id'], $notice['dismiss_interval'] );
$is_notice_dismissed = false;
if ( 'user' === $notice['dismissible_type'] ) {
$current_user = wp_get_current_user();
$notice_key = Give()->notices->get_notice_key( $notice['id'], $notice['dismiss_interval'], $current_user->ID );
}
$notice_data = Give_Cache::get( $notice_key, true );
// Find notice dismiss link status if notice has extra dismissible links.
if ( ( empty( $notice_data ) || is_wp_error( $notice_data ) ) && ! empty( $notice['extra_links'] ) ) {
foreach ( $notice['extra_links'] as $extra_link ) {
$new_notice_data = wp_parse_args( $extra_link, $notice );
unset( $new_notice_data['extra_links'] );
if ( $is_notice_dismissed = $this->is_notice_dismissed( $new_notice_data ) ) {
return $is_notice_dismissed;
}
}
}
$is_notice_dismissed = ! empty( $notice_data ) && ! is_wp_error( $notice_data );
return $is_notice_dismissed;
}
/**
* Print frontend errors.
*
* @since 1.8.9
* @access public
*
* @param array $errors
*/
public static function print_frontend_errors( $errors ) {
// Bailout.
if ( ! $errors ) {
return;
}
/**
* Change auto_dismissible to dismissible and set the value to true
*
* @since 1.8.14
*/
$default_notice_args = [
'dismissible' => true,
'dismiss_interval' => 5000,
];
// Note: we will remove give_errors class in future.
$classes = apply_filters( 'give_error_class', [ 'give_notices', 'give_errors' ] );
echo sprintf( '<div class="%s">', implode( ' ', $classes ) );
// Loop error codes and display errors.
foreach ( $errors as $error_id => $error ) {
// Backward compatibility v<1.8.11
if ( is_string( $error ) ) {
$error = [
'message' => $error,
'notice_args' => [],
];
}
$notice_args = wp_parse_args( $error['notice_args'], $default_notice_args );
/**
* Filter to modify Frontend Errors args before errors is display.
*
* @since 1.8.14
*/
$notice_args = apply_filters( 'give_frontend_errors_args', $notice_args );
echo sprintf(
'<div class="give_error give_notice" id="give_error_%1$s" data-dismissible="%2$s" data-dismiss-interval="%3$d">
<p><strong>%4$s</strong>: %5$s</p>
</div>',
$error_id,
give_clean( $notice_args['dismissible'] ),
absint( $notice_args['dismiss_interval'] ),
esc_html__( 'Error', 'give' ),
$error['message']
);
}
echo '</div>';
}
/**
* Print frontend notice.
* Notice: notice type can be success/error/warning
*
* @since 3.7.0 Escape attributes
* @since 1.8.9
* @access public
*
* @param string $message
* @param bool $echo
* @param string $notice_type
* @param array $notice_args
*
* @return string
*/
public static function print_frontend_notice( $message, $echo = true, $notice_type = 'warning', $notice_args = [] ) {
if ( empty( $message ) ) {
return '';
}
/**
* Change auto_dismissible to dismissible and set the value to true
*
* @since 1.8.14
*/
$default_notice_args = [
'dismissible' => false,
'dismiss_type' => 'auto',
'dismiss_interval' => 5000,
];
$notice_args = wp_parse_args( $notice_args, $default_notice_args );
// Notice dismissible must be true for dismiss type.
$notice_args['dismiss_type'] = ! $notice_args['dismissible'] ? '' : $notice_args['dismiss_type'];
/**
* Filter to modify Frontend notice args before notices is display.
*
* @since 1.8.14
*/
$notice_args = apply_filters( 'give_frontend_notice_args', $notice_args );
$close_icon = 'manual' === $notice_args['dismiss_type'] ?
sprintf(
'<img class="notice-dismiss give-notice-close" src="%s" />',
esc_url( GIVE_PLUGIN_URL . 'build/assets/dist/images/close.svg' )
) :
'';
// Note: we will remove give_errors class in future.
$error = sprintf(
'<div class="give_notices give_errors" id="give_error_%1$s">
<p class="give_notice give_%1$s" data-dismissible="%2$s" data-dismiss-interval="%3$d" data-dismiss-type="%4$s">
%5$s
</p>
%6$s
</div>',
esc_attr($notice_type),
esc_attr( $notice_args['dismissible'] ),
esc_attr( $notice_args['dismiss_interval'] ),
esc_attr( $notice_args['dismiss_type'] ),
esc_html($message),
$close_icon
);
if ( ! $echo ) {
return $error;
}
echo $error;
}
/**
* Print Inline Notice.
* Note: dismissible feature will note work if notice will add to dom by javascript after document load.
*
* @param array $notice_args An array of notice arguments.
*
* @todo Implement render_admin_notices function within this function in future.
*
* @access public
* @since 1.8.17
*
* @return string
*/
public function print_admin_notices( $notice_args = [] ) {
// Bailout.
if ( empty( $notice_args['description'] ) ) {
return '';
}
$defaults = [
'id' => '',
'echo' => true,
'notice_type' => 'warning',
'dismissible' => true,
];
$notice_args = wp_parse_args( $notice_args, $defaults );
$output = '';
$css_id = ! empty( $notice_args['id'] ) ? $notice_args['id'] : uniqid( 'give-inline-notice-' );
$css_class = "notice-{$notice_args['notice_type']} give-notice notice inline";
$css_class .= ( $notice_args['dismissible'] ) ? ' is-dismissible' : '';
$output .= sprintf(
'<div id="%1$s" class="%2$s"><p>%3$s</p></div>',
$css_id,
$css_class,
$notice_args['description']
);
if ( ! $notice_args['echo'] ) {
return $output;
}
echo $output;
}
}