# post-carousel/4.0.8/includes/Admin/Admin_Notices.php

Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog &amp; News, version 4.0.8. 579 lines.

- Page: https://pluginprobe.com/plugins/post-carousel/4.0.8/code/includes/Admin/Admin_Notices.php
- Raw: https://pluginprobe.com/plugins/post-carousel/4.0.8/raw/includes/Admin/Admin_Notices.php
- Modified: 2026-09-02T10:51:28+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/post-carousel/4.0.8/code/includes/Admin/Admin_Notices.php#L10-L20`.

```php
<?php
/**
 * The admin notices file.
 *
 * @package    Smart_Post_Show
 * @subpackage Smart_Post_Show/Admin
 * @author     ShapedPlugin<support@shapedplugin.com>
 */

namespace SmartPostShow\Admin;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * This class is responsible for all kinds of admin facing notices.
 */
class Admin_Notices {

	/**
	 * Initialize the class and set its properties.
	 */
	public function __construct() {
		add_action( 'admin_notices', array( $this, 'render_all_admin_notices' ) );
		add_action( 'in_admin_header', array( $this, 'render_blocks_promo_modal' ) );
		add_action( 'wp_ajax_spsp_dismiss_blocks_promo_notice', array( $this, 'dismiss_blocks_promo_notice' ) );
		add_action( 'wp_ajax_spsp_dismiss_blocks_promo_modal', array( $this, 'dismiss_blocks_promo_modal' ) );
		add_action( 'wp_ajax_check_sp_post_carousel_posts', array( $this, 'check_sp_post_carousel_posts' ) );
	}

	/**
	 * Display all admin notice for backend.
	 *
	 * @return void
	 */
	public function render_all_admin_notices() {
		$this->render_blocks_promo_notice();
	}

	/**
	 * Render the "Meet the new Smart Post" promo banner that surfaces
	 * the block editor + ready patterns on the classic sp_post_carousel edit
	 * screens. Dismissed per-user via user_meta.
	 *
	 * @return void
	 */
	public function render_blocks_promo_notice() {
		if ( ! current_user_can( 'edit_posts' ) ) {
			return;
		}

		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		if ( ! $screen || 'sp_post_carousel' !== $screen->post_type ) {
			return;
		}
		if ( 'post' !== $screen->base ) {
			return;
		}

		if ( get_option( 'spsp_blocks_promo_notice_dismissed' ) ) {
			return;
		}

		$block_editor_url = admin_url( 'post-new.php?post_type=page&spblock_inserter=true' );
		$nonce            = wp_create_nonce( 'spsp_blocks_promo_notice' );
		?>
		<div class="notice spsp-blocks-promo-notice" data-spsp-nonce="<?php echo esc_attr( $nonce ); ?>">
			<div class="spsp-blocks-promo-notice__text">
				<?php
				$highlight_open   = '<a class="spsp-blocks-promo-notice__highlight" href="https://wpsmartpost.com/patterns/" target="_blank" rel="noopener">';
				$highlight_blocks = '<a class="spsp-blocks-promo-notice__highlight" href="https://wpsmartpost.com/blocks/" target="_blank" rel="noopener">';
				echo wp_kses(
					sprintf(
						/* translators: 1: opening strong, 2: closing strong, 3: opening anchor to block editor, 4: closing anchor. */
						__( '%1$sMeet the new Smart Post%2$s — gives you %3$s60+ Gutenberg Blocks%4$s and %5$s250+ Ready Patterns%6$s to design visually — see every change live.', 'post-carousel' ),
						'<strong>',
						'</strong>',
						$highlight_blocks,
						'</a>',
						$highlight_open,
						'</a>'
					),
					array(
						'strong' => array(),
						'a'      => array(
							'class'  => array(),
							'href'   => array(),
							'target' => array(),
							'rel'    => array(),
						),
					)
				);
				?>
			</div>
			<div class="spsp-blocks-promo-notice__actions">
				<a class="spsp-blocks-promo-notice__cta" href="<?php echo esc_url( $block_editor_url ); ?>">
					<?php esc_html_e( 'Try Block Editor', 'post-carousel' ); ?>
					<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
						<path d="M2.25 6h7.5M6.75 2.25 10.5 6 6.75 9.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
					</svg>
				</a>
				<button type="button" class="spsp-blocks-promo-notice__dismiss" aria-label="<?php esc_attr_e( 'Dismiss this notice', 'post-carousel' ); ?>">
					<span class="dashicons dashicons-no-alt"></span>
				</button>
			</div>
		</div>
		<style>
			.spsp-blocks-promo-notice {
				display: flex;
				align-items: center;
				gap: 24px;
				margin: 16px 20px 16px 0;
				padding: 12px 20px 12px 24px;
				background: #fff3cd;
				border: 1px solid #f0c040;
				border-left-width: 4px;
				border-radius: 4px;
				box-shadow: none;
				color: #473400;
			}
			.spsp-blocks-promo-notice__text {
				flex: 1 1 auto;
				font: 400 15px/20px Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
				color: #473400;
			}
			.spsp-blocks-promo-notice__text strong {
				font-weight: 600;
				color: #473400;
			}
			.spsp-blocks-promo-notice .spsp-blocks-promo-notice__highlight{
				color: #473400;
				font-weight: 600;
				text-decoration: underline;
			}
			.spsp-blocks-promo-notice .spsp-blocks-promo-notice__highlight:hover,
			.spsp-blocks-promo-notice .spsp-blocks-promo-notice__highlight:focus {
				color: #1a74e4;
				box-shadow: none;
				outline: none;
			}
			.spsp-blocks-promo-notice__actions {
				display: flex;
				align-items: center;
				gap: 12px;
				flex-shrink: 0;
			}
			.spsp-blocks-promo-notice .spsp-blocks-promo-notice__cta {
				display: inline-flex;
				align-items: center;
				gap: 5px;
				padding: 8px 12px;
				background: #1a74e4;
				border: 1px solid #1a74e4;
				border-radius: 2px;
				color: #fff;
				font: 600 13px/18px Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
				text-decoration: none;
				box-shadow: none;
			}
			.spsp-blocks-promo-notice .spsp-blocks-promo-notice__cta:hover,
			.spsp-blocks-promo-notice .spsp-blocks-promo-notice__cta:focus {
				background: #1565c0;
				border-color: #1565c0;
				color: #fff;
				outline: none;
			}
			.spsp-blocks-promo-notice__cta svg {
				flex-shrink: 0;
			}
			.spsp-blocks-promo-notice__dismiss {
				display: inline-flex;
				align-items: center;
				justify-content: center;
				width: 24px;
				height: 24px;
				padding: 0;
				background: transparent;
				border: 0;
				color: #473400;
				cursor: pointer;
			}
			.spsp-blocks-promo-notice__dismiss:hover,
			.spsp-blocks-promo-notice__dismiss:focus {
				color: #000;
				outline: none;
			}
			.spsp-blocks-promo-notice__dismiss .dashicons {
				font-size: 20px;
				width: 20px;
				height: 20px;
			}
		</style>
		<script>
			( function() {
				document.addEventListener( 'click', function( event ) {
					var dismiss = event.target.closest( '.spsp-blocks-promo-notice__dismiss' );
					if ( ! dismiss ) {
						return;
					}
					var notice = dismiss.closest( '.spsp-blocks-promo-notice' );
					if ( ! notice ) {
						return;
					}
					notice.style.display = 'none';
					var data = new FormData();
					data.append( 'action', 'spsp_dismiss_blocks_promo_notice' );
					data.append( 'nonce', notice.getAttribute( 'data-spsp-nonce' ) || '' );
					if ( window.fetch && window.ajaxurl ) {
						fetch( window.ajaxurl, { method: 'POST', credentials: 'same-origin', body: data } );
					}
				} );
			} )();
		</script>
		<?php
	}

	/**
	 * Render a one-time welcome modal on the Add New Post Carousel screen pointing
	 * users at the block editor. Stored dismissal lives in wp_options so the
	 * popup never appears twice for the site.
	 *
	 * @return void
	 */
	public function render_blocks_promo_modal() {
		if ( ! current_user_can( 'edit_posts' ) ) {
			return;
		}

		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		if ( ! $screen || 'sp_post_carousel' !== $screen->post_type || 'add' !== $screen->action ) {
			return;
		}

		if ( get_option( 'spsp_blocks_promo_modal_choice' ) ) {
			return;
		}

		$block_editor_url = admin_url( 'post-new.php?post_type=page&spblock_inserter=true' );
		$nonce            = wp_create_nonce( 'spsp_blocks_promo_modal' );
		$modal_video_url  = 'https://wpsmartpost.com/wp-content/uploads/2026/06/SP-Popup-V01_1.mp4';
		?>
		<div class="spsp-blocks-promo-modal" data-spsp-nonce="<?php echo esc_attr( $nonce ); ?>" role="dialog" aria-modal="true" aria-labelledby="spsp-blocks-promo-modal__title">
			<div class="spsp-blocks-promo-modal__backdrop" data-spsp-modal-close="1"></div>
			<div class="spsp-blocks-promo-modal__dialog">
				<div class="spsp-blocks-promo-modal__header">
					<div class="spsp-blocks-promo-modal__heading">
						<h2 id="spsp-blocks-promo-modal__title" class="spsp-blocks-promo-modal__title">
							<?php esc_html_e( 'How would you like to create your post showcase?', 'post-carousel' ); ?>
						</h2>
						<p class="spsp-blocks-promo-modal__subtitle">
							<?php esc_html_e( 'Choose the workflow that suits you best — you can always switch later.', 'post-carousel' ); ?>
						</p>
					</div>
					<button type="button" class="spsp-blocks-promo-modal__close" data-spsp-modal-close="1" aria-label="<?php esc_attr_e( 'Close', 'post-carousel' ); ?>">
						<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
							<path fill="currentColor" d="M12 13.06l3.712 3.713 1.061-1.06L13.061 12l3.712-3.712-1.06-1.06L12 10.938 8.288 7.227l-1.061 1.06L10.939 12l-3.712 3.712 1.06 1.061L12 13.061z"/>
						</svg>
					</button>
				</div>
				<div class="spsp-blocks-promo-modal__body">
					<div class="spsp-blocks-promo-modal__preview" aria-hidden="true">
						<video class="spsp-blocks-promo-modal__video" src="<?php echo esc_url( $modal_video_url ); ?>" autoplay loop muted playsinline preload="metadata"></video>
					</div>
					<div class="spsp-blocks-promo-modal__actions">
						<a class="spsp-blocks-promo-modal__cta" href="<?php echo esc_url( $block_editor_url ); ?>">
							<?php esc_html_e( 'Start with Block Editor', 'post-carousel' ); ?>
							<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
								<path d="M2.625 7h8.75M7.875 2.625 12.25 7l-4.375 4.375" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
							</svg>
						</a>
						<button type="button" class="spsp-blocks-promo-modal__skip" data-spsp-modal-close="1">
							<?php esc_html_e( 'Continue with Classic Shortcode', 'post-carousel' ); ?>
						</button>
					</div>
				</div>
				<div class="spsp-blocks-promo-modal__footer">
					<label class="spsp-blocks-promo-modal__checkbox">
						<input type="checkbox" class="spsp-blocks-promo-modal__checkbox-input" />
						<span class="spsp-blocks-promo-modal__checkbox-label">
							<?php esc_html_e( 'Remember this choice and skip this step next time.', 'post-carousel' ); ?>
						</span>
					</label>
				</div>
			</div>
		</div>
		<style>
			#wpcontent:has(.spsp-blocks-promo-modal) {
				position: relative;
			}
			.spsp-blocks-promo-modal {
				position: absolute;
				inset: 0;
				min-height: calc(100vh - 32px);
				z-index: 99998;
			}
			@media screen and (max-width: 782px) {
				.spsp-blocks-promo-modal {
					min-height: calc(100vh - 46px);
				}
			}
			.spsp-blocks-promo-modal__backdrop {
				position: absolute;
				inset: 0;
				background: rgba(0, 0, 0, 0.85);
			}
			.spsp-blocks-promo-modal__dialog {
				position: fixed;
				top: 50%;
				left: 50%;
				transform: translate(-50%, -50%);
				display: flex;
				flex-direction: column;
				width: calc(100% - 48px);
				max-width: 660px;
				background: #fff;
				border-radius: 12px;
				overflow: hidden;
				box-shadow: 0 24px 48px rgba(0, 0, 0, 0.18);
				font: 400 13px/20px Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
				color: #3d434b;
			}
			.spsp-blocks-promo-modal__header {
				display: flex;
				align-items: center;
				gap: 5px;
				padding: 18px 32px;
				background: #f6f7f7;
				border-bottom: 1px solid #ddd;
			}
			.spsp-blocks-promo-modal__heading {
				flex: 1 1 auto;
				display: flex;
				flex-direction: column;
				gap: 5px;
			}
			.spsp-blocks-promo-modal__title {
				margin: 0;
				font: 600 20px/24px Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
				color: #1d2327;
			}
			.spsp-blocks-promo-modal__subtitle {
				margin: 0;
				font: 400 12px/16px Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
				color: #3d434b;
			}
			.spsp-blocks-promo-modal__close {
				display: inline-flex;
				align-items: center;
				justify-content: center;
				width: 32px;
				height: 32px;
				padding: 0;
				background: #fff;
				border: 1px solid #c3c4c7;
				border-radius: 999px;
				color: #1d2327;
				cursor: pointer;
				flex-shrink: 0;
			}
			.spsp-blocks-promo-modal__close:hover,
			.spsp-blocks-promo-modal__close:focus {
				background: #f6f7f7;
				outline: none;
			}
			.spsp-blocks-promo-modal__body {
				display: flex;
				flex-direction: column;
				gap: 23px;
				padding: 28px 32px;
			}
			.spsp-blocks-promo-modal__preview {
				width: 100%;
				height: 356px;
				background: #d9d9d9;
				border-radius: 6px;
				border: 1px solid #DFDFDF;
				overflow: hidden;
			}
			.spsp-blocks-promo-modal__video {
				display: block;
				width: 100%;
				height: 100%;
				object-fit: cover;
				border-radius: inherit;
			}
			.spsp-blocks-promo-modal__actions {
				display: flex;
				gap: 10px;
				align-items: center;
			}
			.spsp-blocks-promo-modal .spsp-blocks-promo-modal__cta {
				display: inline-flex;
				align-items: center;
				gap: 5px;
				padding: 13px 18px;
				background: #1a74e4;
				border: 1px solid #1a74e4;
				border-radius: 4px;
				color: #fff;
				font: 600 13px/18px Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
				text-decoration: none;
				box-shadow: none;
			}
			.spsp-blocks-promo-modal .spsp-blocks-promo-modal__cta:hover,
			.spsp-blocks-promo-modal .spsp-blocks-promo-modal__cta:focus {
				background: #1565c0;
				border-color: #1565c0;
				color: #fff;
				outline: none;
			}
			.spsp-blocks-promo-modal__skip {
				display: inline-flex;
				align-items: center;
				gap: 5px;
				padding: 13px 18px;
				background: #fff;
				border: 1px solid #c3c4c7;
				border-radius: 4px;
				color: #1d2327;
				font: 600 13px/18px Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
				cursor: pointer;
			}
			.spsp-blocks-promo-modal__skip:hover,
			.spsp-blocks-promo-modal__skip:focus {
				background: #f6f7f7;
				outline: none;
			}
			.spsp-blocks-promo-modal__footer {
				padding: 8px 32px;
				background: #f6f7f7;
			}
			.spsp-blocks-promo-modal__checkbox {
				display: inline-flex;
				align-items: center;
				gap: 10px;
				cursor: pointer;
			}
			.spsp-blocks-promo-modal__checkbox .spsp-blocks-promo-modal__checkbox-input {
				width: 16px;
				height: 16px;
				margin: 0;
				background: #fff;
				border: 1px solid #949494;
				border-radius: 2px;
			}
			.spsp-blocks-promo-modal__checkbox-label {
				font: 400 13px/20px Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
				color: #3d434b;
			}
		</style>
		<script>
			( function() {
				var modal = document.querySelector( '.spsp-blocks-promo-modal' );
				if ( ! modal ) {
					return;
				}
				var checkbox = modal.querySelector( '.spsp-blocks-promo-modal__checkbox-input' );
				function persistChoice( choice ) {
					if ( ! checkbox || ! checkbox.checked || ! window.ajaxurl ) {
						return;
					}
					var data = new FormData();
					data.append( 'action', 'spsp_dismiss_blocks_promo_modal' );
					data.append( 'nonce', modal.getAttribute( 'data-spsp-nonce' ) || '' );
					data.append( 'choice', choice );
					if ( navigator.sendBeacon ) {
						navigator.sendBeacon( window.ajaxurl, data );
					} else if ( window.fetch ) {
						fetch( window.ajaxurl, {
							method: 'POST',
							credentials: 'same-origin',
							body: data,
							keepalive: true,
						} );
					}
				}
				function close() {
					modal.style.display = 'none';
				}
				var skip = modal.querySelector( '.spsp-blocks-promo-modal__skip' );
				if ( skip ) {
					skip.addEventListener( 'click', function() {
						persistChoice( 'classic_shortcode' );
					} );
				}
				var cta = modal.querySelector( '.spsp-blocks-promo-modal__cta' );
				if ( cta ) {
					cta.addEventListener( 'click', function() {
						persistChoice( 'block_editor' );
					} );
				}
				modal.addEventListener( 'click', function( event ) {
					var target = event.target.closest( '[data-spsp-modal-close]' );
					if ( target ) {
						event.preventDefault();
						close();
					}
				} );
				document.addEventListener( 'keydown', function( event ) {
					if ( event.key === 'Escape' && modal.style.display !== 'none' ) {
						close();
					}
				} );
			} )();
		</script>
		<?php
	}

	/**
	 * Persist dismissal of the blocks promo notice site-wide.
	 *
	 * @return void
	 */
	public function dismiss_blocks_promo_notice() {
		$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
		if ( ! wp_verify_nonce( $nonce, 'spsp_blocks_promo_notice' ) ) {
			wp_send_json_error();
		}
		update_option( 'spsp_blocks_promo_notice_dismissed', 1, false );
		wp_send_json_success();
	}

	/**
	 * Persist the user's workflow choice from the Add New Post Carousel welcome modal.
	 *
	 * Only fires when the "Remember this choice" checkbox is ticked. The stored
	 * value records which button the user picked so the modal can be skipped
	 * on subsequent visits.
	 *
	 * @return void
	 */
	public function dismiss_blocks_promo_modal() {
		$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
		if ( ! wp_verify_nonce( $nonce, 'spsp_blocks_promo_modal' ) ) {
			wp_send_json_error();
		}
		$choice  = isset( $_POST['choice'] ) ? sanitize_text_field( wp_unslash( $_POST['choice'] ) ) : '';
		$allowed = array( 'block_editor', 'classic_shortcode' );
		if ( ! in_array( $choice, $allowed, true ) ) {
			wp_send_json_error();
		}
		update_option( 'spsp_blocks_promo_modal_choice', $choice, false );
		wp_send_json_success();
	}

	/**
	 * Check if there are any sp_post_carousel posts.
	 *
	 * AJAX handler for checking if the sp_post_carousel post type has any posts.
	 *
	 * @return void
	 */
	public function check_sp_post_carousel_posts() {
		$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
		if ( ! wp_verify_nonce( $nonce, 'sp-update-block-settings-nonce' ) ) {
			wp_send_json_error();
		}

		$args = array(
			'post_type'      => 'sp_post_carousel',
			'posts_per_page' => 1,
			'fields'         => 'ids',
			'post_status'    => array( 'publish', 'draft', 'pending', 'private' ),
		);

		$posts             = get_posts( $args );
		$has_posts         = count( $posts ) > 0;
		$editor_preference = get_option( 'spsp_blocks_promo_modal_choice', '' );
		$is_block_editor   = 'block-editor' === $editor_preference;
		wp_send_json_success(
			array(
				'has_posts'       => $has_posts,
				'is_block_editor' => $is_block_editor,
			)
		);
	}
}

```
