null, 'notices' => null, ); /** * Dismiss action link is available or not. * * @var bool */ private $dismiss = true; /** * */ public function __construct( $args ) { parent::__construct( $args ); add_action( 'admin_notices', array( $this, 'admin_notices' ) ); add_action( 'wp_ajax_stateless_notice_dismiss', array( $this, 'dismiss_notices' ) ); add_action( 'wp_ajax_stateless_enable_notice_button_action', array( $this, 'stateless_enable_notice_button_action' ) ); } /** * Prevents adding duplicating messages * Some triggers may happen few times during site load (like 'switch_blog' hook) * adding the same message several times is not necessary * * @param string $collection * @param string $message */ private function add_message( &$collection, $message ) { $exiting_keys = array_column($collection, 'key'); if ( in_array( $message['key'], $exiting_keys ) ) { return; } $collection[] = $message; } /** * Add new message for admin notices * * @param string $message * @param string $type Values: 'error', 'message', 'warning' * @param string $translate Values: true, false * @author peshkov@UD */ public function add( $message, $type = 'error', $translate = true ) { switch( $type ) { case 'error': $this->add_message($this->errors, $message); break; case 'message': case 'warning': case 'notice': if(!is_array($message)){ $title = $translate ? sprintf( __( '%s has the following notice:', $this->domain ), esc_html($this->name) ) : sprintf( '%s has the following notice:', esc_html($this->name) ); $message = array( 'title' => $title, 'message' => $message, 'button' => null, ); } if(empty($message['key'])){ $message['key'] = md5( $message['title'] ); } $this->add_message($this->notices, $message); break; } } /** * Add footer link to specific ( errors|messages|wanrnings ) block * * @author peshkov@UD */ public function add_action_link( $link, $type = 'error' ) { switch( $type ) { case 'error': $this->action_links[ 'errors' ][] = $link; break; case 'message': case 'warning': case 'notice': $this->action_links[ 'notices' ][] = $link; break; } } /** * Determine if errors exist * * @author peshkov@UD */ public function has_errors() { return !empty( $this->errors ) ? true : false; } /** * Renders admin notes in case there are errors or notices on bootstrap init * * @author peshkov@UD */ public function admin_notices() { global $wp_version; wp_enqueue_style("stateless-error-style", ud_get_stateless_media()->path('static/styles/error-notice.css')); //enqueue dismiss js for ajax requests $script_path = \UsabilityDynamics\WP\Utility::path( 'static/scripts/ud-dismiss.js', 'url' ); wp_enqueue_script( "sateless-error-notice-js", ud_get_stateless_media()->path( 'static/scripts/error-notice.js', 'url' ), array( 'jquery' ) ); wp_enqueue_script( "ud-dismiss", $script_path, array( 'jquery' ) ); wp_localize_script( "ud-dismiss", "_ud_vars", array( "ajaxurl" => admin_url( 'admin-ajax.php' ), )); wp_localize_script( "sateless-error-notice-js", "stateless_error_notice_vars", array( "dismiss_nonce" => wp_create_nonce( 'stateless_notice_dismiss' ), "enable_action_nonce" => wp_create_nonce( 'stateless_enable_notice_button_action' ), )); //** Don't show the message if the user has no enough permissions. */ if ( ! function_exists( 'wp_get_current_user' ) ) { require_once( ABSPATH . 'wp-includes/pluggable.php' ); } $default_show = true; if ( empty( $this->args['type'] ) || ( $this->args['type'] == 'plugin' && !current_user_can( 'activate_plugins' ) ) || ( $this->args['type'] == 'theme' && !current_user_can( 'switch_themes' ) ) ) { $default_show = false; } //** Don't show the message if on a multisite and the user isn't a super user. */ if ( is_multisite() && ! is_super_admin() ) { $default_show = false; } $errors = apply_filters( 'ud:errors:admin_notices', $this->errors, $this->args ); $notices = apply_filters( 'stateless:notices:admin_notices', $this->notices, $this->args ); //** Errors Block */ if( $default_show && !empty( $errors ) && is_array( $errors ) ) { $message = ''; $data = array( 'title' => sprintf( __( '%s is not active due to following errors:', $this->domain ), esc_html($this->name) ), 'class' => 'error', 'message' => $message, 'action_links' => !empty($this->action_links[ 'errors' ])?$this->action_links[ 'errors' ]:null, ); include ud_get_stateless_media()->path( '/static/views/error-notice.php', 'dir' ); } $has_notice = false; //** Determine if warning has been dismissed */ if ( ! empty( $notices ) && is_array( $notices ) ) { //** Warnings Block */ foreach ($notices as $notice ) { if ( get_option( 'dismissed_notice_' . $notice['key'] )){ continue; } // Check additional capabilities $capability = isset( $notice['capability'] ) && !empty( $notice['capability'] ) ? $notice['capability'] : null; if ( ( !$default_show && empty($capability) ) || ( !empty($capability) && !current_user_can($capability) ) ) { continue; } // Additional HTML classes $classes = []; if ( isset($notice['classes']) ) { $classes = $notice['classes']; if ( !is_array($classes) ) { $classes = [$classes]; } } $classes[] = 'notice'; $data = wp_parse_args($notice, array( 'title' => '', 'class' => implode(' ', $classes), 'message' => '', 'button' => '', 'button_link' => '#', 'key' => '', 'action_links' => $this->action_links[ 'notices' ], 'dismiss' => true, )); $button_capability = isset( $notice['button_capability'] ) && !empty( $notice['button_capability'] ) ? $notice['button_capability'] : null; if ( !empty($button_capability) && !current_user_can($button_capability) ) { $data['button'] = ''; } include ud_get_stateless_media()->path( '/static/views/error-notice.php', 'dir' ); $has_notice = true; } } } /** * dismiss the notice ajax callback * @throws \Exception */ public function dismiss_notices() { check_ajax_referer('stateless_notice_dismiss'); if ( !is_user_logged_in() ) { wp_send_json_error( array( 'error' => __( 'You are not allowed to do this action.', $this->domain ) ) ); } $response = array( 'success' => '0', 'error' => __( 'There was an error in request.', $this->domain ), ); $error = false; $option_key = isset($_POST['key']) ? sanitize_key($_POST['key']) : ''; if ( strpos($option_key, 'dismissed_') !== 0 ) { $response['error'] = __( 'Invalid key', $this->domain ); $error = true; } if ( !$error && update_option( $option_key, time() ) ) { do_action('wp_stateless_notice_dismissed', $option_key); $response['success'] = '1'; $response['error'] = null; } wp_send_json( $response ); } /** * Action for the stateless_enable_notice_button_action ajax callback * @throws \Exception */ public function stateless_enable_notice_button_action(){ check_ajax_referer('stateless_enable_notice_button_action'); if ( !is_user_logged_in() ) { wp_send_json_error( array( 'error' => __( 'You are not allowed to do this action.', $this->domain ) ) ); } $response = array( 'success' => '1', ); $error = false; if( empty($_POST['key']) ) { $response['success'] = '0'; $response['error'] = __( 'Invalid key', $this->domain ); } else{ $option_key = sanitize_key($_POST['key']); $compatibility = Module::get_module($option_key); if(!empty($compatibility['self']) && is_callable(array($compatibility['self'], 'enable_compatibility'))){ $response['success'] = $compatibility['self']->enable_compatibility(); } } wp_send_json( $response ); } /** * Check dismiss notice timestamp if greater than 24 hrs * * @param string $time * * @return bool */ public function check_dismiss_time( $time = '' ) { if( empty( $time ) ) { return true; } $current_time = time(); $diff = $current_time - 86400; if ( $diff > (int)$time ) { return true; } return false; } } } }