*/ const IDS = array( 'wporg-addons', 'req-missing-elementor', 'req-old-elementor', 'req-atomic-classes', 'req-experiment', ); /** * @var bool */ private static $script_queued = false; /** * @return void */ public static function init() { add_action( 'wp_ajax_' . self::AJAX_ACTION, array( __CLASS__, 'ajax_dismiss' ) ); add_action( 'admin_post_' . self::POST_ACTION, array( __CLASS__, 'post_dismiss' ) ); add_action( 'admin_footer', array( __CLASS__, 'print_script' ) ); } /** * @param string $id Notice id. * @return bool */ public static function is_dismissed( $id ) { $id = sanitize_key( (string) $id ); if ( ! in_array( $id, self::IDS, true ) || ! is_user_logged_in() ) { return false; } return '1' === (string) get_user_meta( get_current_user_id(), self::meta_key( $id ), true ); } /** * URL that stores the dismissal without JavaScript. * * @param string $id Notice id. * @return string */ public static function dismiss_url( $id ) { $url = add_query_arg( array( 'action' => self::POST_ACTION, 'notice' => sanitize_key( (string) $id ), ), admin_url( 'admin-post.php' ) ); return wp_nonce_url( $url, self::NONCE_ACTION ); } /** * Print the small dismiss script in the admin footer when a notice was rendered. * * @return void */ public static function queue_script() { self::$script_queued = true; } /** * @return void */ public static function print_script() { if ( ! self::$script_queued || ! is_admin() ) { return; } $payload = array( 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'action' => self::AJAX_ACTION, 'nonce' => wp_create_nonce( self::NONCE_ACTION ), ); $json = Script_Json::encode( $payload ); if ( '' === $json ) { return; } $js = 'window.reactwooAtomicAdminNotices=' . $json . ';' . <<<'JS' (function () { var cfg = window.reactwooAtomicAdminNotices || {}; document.addEventListener('click', function (event) { var el = event.target; if (!el || !el.closest) { return; } var btn = el.closest('.rw-atomic-admin-notice .notice-dismiss'); if (!btn || !cfg.ajaxUrl || !cfg.nonce) { return; } var box = btn.closest('.rw-atomic-admin-notice'); var id = box ? box.getAttribute('data-reactwoo-atomic-notice') : ''; if (!id || !window.fetch || !window.FormData) { return; } var body = new window.FormData(); body.append('action', cfg.action || ''); body.append('_ajax_nonce', cfg.nonce); body.append('notice', id); window.fetch(cfg.ajaxUrl, { method: 'POST', credentials: 'same-origin', body: body }); }); })(); JS; wp_print_inline_script_tag( $js ); } /** * @return void */ public static function ajax_dismiss() { check_ajax_referer( self::NONCE_ACTION ); $id = isset( $_POST['notice'] ) ? sanitize_key( wp_unslash( (string) $_POST['notice'] ) ) : ''; if ( ! self::can_dismiss() ) { wp_send_json_error( array( 'message' => __( 'Permission denied.', 'reactwoo-atomic' ) ), 403 ); } if ( ! self::remember( $id ) ) { wp_send_json_error( array( 'message' => __( 'Unknown notice.', 'reactwoo-atomic' ) ), 400 ); } wp_send_json_success(); } /** * @return void */ public static function post_dismiss() { check_admin_referer( self::NONCE_ACTION ); $id = isset( $_GET['notice'] ) ? sanitize_key( wp_unslash( (string) $_GET['notice'] ) ) : ''; if ( ! self::can_dismiss() ) { wp_die( esc_html__( 'Permission denied.', 'reactwoo-atomic' ), '', array( 'response' => 403 ) ); } if ( ! self::remember( $id ) ) { wp_die( esc_html__( 'Unknown notice.', 'reactwoo-atomic' ), '', array( 'response' => 400 ) ); } $back = wp_get_referer(); wp_safe_redirect( $back ? $back : admin_url() ); exit; } /** * Read a flash flag only when its nonce matches. * * @param string $key Query arg. * @return string */ public static function verified_flag( $key ) { $key = sanitize_key( (string) $key ); if ( '' === $key || ! isset( $_GET[ $key ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- verified on the next lines. return ''; } $nonce = isset( $_GET['reactwoo_atomic_notice_nonce'] ) ? sanitize_text_field( wp_unslash( (string) $_GET['reactwoo_atomic_notice_nonce'] ) ) : ''; if ( ! wp_verify_nonce( $nonce, 'reactwoo_atomic_notice_' . $key ) ) { return ''; } return sanitize_key( (string) wp_unslash( $_GET[ $key ] ) ); } /** * Redirect back to an admin screen with a nonce-protected flash flag. * * @param string $url Destination. * @param string $key Query arg. * @param string $value Flag value. * @return void */ public static function redirect_with_flag( $url, $key, $value ) { $key = sanitize_key( (string) $key ); wp_safe_redirect( add_query_arg( array( $key => sanitize_key( (string) $value ), 'reactwoo_atomic_notice_nonce' => wp_create_nonce( 'reactwoo_atomic_notice_' . $key ), ), $url ) ); exit; } /** * @return bool */ private static function can_dismiss() { return current_user_can( 'manage_options' ) || current_user_can( 'activate_plugins' ); } /** * @param string $id Notice id. * @return bool */ private static function remember( $id ) { if ( ! in_array( $id, self::IDS, true ) ) { return false; } update_user_meta( get_current_user_id(), self::meta_key( $id ), '1' ); return true; } /** * @param string $id Notice id. * @return string */ public static function meta_key( $id ) { if ( 'wporg-addons' === $id ) { return Wporg_Upsell::DISMISS_META; } return 'reactwoo_atomic_dismiss_' . str_replace( '-', '_', sanitize_key( (string) $id ) ); } }