<?php
/**
 * Persist Admin notices Dismissal
 *
 * Based on Persist Admin notices Dismissal
 * Copyright (C) 2016 Collins Agbonghama <https://w3guy.com>
 *
 * The class is renamed with the theme's own prefix rather than reusing the upstream
 * `PAnD` name. Several plugins bundle the upstream library, and a `class_exists( 'PAnD' )`
 * guard around renamed methods means the theme's copy is skipped while its calls still
 * expect the renamed methods, producing a fatal error on every admin screen.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @package Euphony_Blocks
 * @author  Collins Agbonghama, Andy Fragen
 * @license http://www.gnu.org/licenses GNU General Public License
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'Euphony_Blocks_PAnD' ) ) {
	/**
	 * Class Euphony_Blocks_PAnD
	 */
	class Euphony_Blocks_PAnD {

		/**
		 * Init hooks.
		 *
		 * @return void
		 */
		public static function init() {
			add_action( 'wp_ajax_euphony_blocks_dismiss_admin_notice', array( __CLASS__, 'euphony_blocks_dismiss_admin_notice' ) );
			add_action( 'admin_enqueue_scripts', array( __CLASS__, 'euphony_blocks_enqueue_script' ) );
		}

		/**
		 * Enqueue the script that sends the dismissal to the server.
		 *
		 * Without this the data-dismissible notice is only hidden for the current page view
		 * and reappears on the next admin screen.
		 *
		 * @return void
		 */
		public static function euphony_blocks_enqueue_script() {
			if ( ! current_user_can( 'edit_theme_options' ) ) {
				return;
			}

			$theme_version = wp_get_theme( get_template() )->get( 'Version' );
			$version       = is_string( $theme_version ) ? $theme_version : false;

			wp_enqueue_script(
				'euphony-blocks-dismiss-notice',
				get_template_directory_uri() . '/assets/js/dismiss-notice.js',
				array( 'jquery' ),
				$version,
				true
			);

			wp_localize_script(
				'euphony-blocks-dismiss-notice',
				'euphonyBlocksPAnD',
				array(
					'ajaxUrl' => admin_url( 'admin-ajax.php' ),
					'action'  => 'euphony_blocks_dismiss_admin_notice',
					'nonce'   => wp_create_nonce( 'dismissible-notice' ),
				)
			);
		}

		/**
		 * Handles the Ajax request to persist a notice dismissal.
		 *
		 * @return void
		 */
		public static function euphony_blocks_dismiss_admin_notice() {
			// Verify the nonce and capability before reading any request data.
			check_ajax_referer( 'dismissible-notice', 'nonce' );

			if ( ! current_user_can( 'edit_theme_options' ) ) {
				wp_send_json_error( esc_html__( 'You are not allowed to dismiss this notice.', 'euphony-blocks' ), 403 );
			}

			$option_name        = isset( $_POST['option_name'] ) ? sanitize_text_field( wp_unslash( $_POST['option_name'] ) ) : '';
			$dismissible_length = isset( $_POST['dismissible_length'] ) ? sanitize_text_field( wp_unslash( $_POST['dismissible_length'] ) ) : '0';

			if ( '' === $option_name ) {
				wp_send_json_error( esc_html__( 'Missing notice identifier.', 'euphony-blocks' ) );
			}

			if ( 'forever' !== $dismissible_length ) {
				// If $dismissible_length is not a positive integer, default to 1 day.
				$days               = absint( $dismissible_length );
				$days               = ( 0 === $days ) ? 1 : $days;
				$dismissible_length = strtotime( $days . ' days' );
			}

			self::euphony_blocks_set_admin_notice_cache( $option_name, $dismissible_length );

			wp_send_json_success();
		}

		/**
		 * Is admin notice active?
		 *
		 * @param string $arg data-dismissible content of notice.
		 *
		 * @return bool
		 */
		public static function euphony_blocks_is_admin_notice_active( $arg ) {
			$array       = explode( '-', $arg );
			$length      = array_pop( $array );
			$option_name = implode( '-', $array );
			$db_record   = self::euphony_blocks_get_admin_notice_cache( $option_name );

			unset( $length );

			if ( 'forever' === $db_record ) {
				return false;
			} elseif ( absint( $db_record ) >= time() ) {
				return false;
			} else {
				return true;
			}
		}

		/**
		 * Returns admin notice cached timeout.
		 *
		 * @access public
		 *
		 * @param string|bool $id admin notice name or false.
		 *
		 * @return string|bool The timeout. False if expired.
		 */
		public static function euphony_blocks_get_admin_notice_cache( $id = false ) {
			if ( ! $id ) {
				return false;
			}
			$cache_key = 'pand-' . md5( $id );
			$timeout   = get_site_option( $cache_key );
			$timeout   = 'forever' === $timeout ? time() + 60 : $timeout;

			if ( empty( $timeout ) || time() > $timeout ) {
				return false;
			}

			return $timeout;
		}

		/**
		 * Sets admin notice timeout in site option.
		 *
		 * @access public
		 *
		 * @param string      $id      Data Identifier.
		 * @param string|bool $timeout Timeout for admin notice.
		 *
		 * @return bool
		 */
		public static function euphony_blocks_set_admin_notice_cache( $id, $timeout ) {
			$cache_key = 'pand-' . md5( $id );
			update_site_option( $cache_key, $timeout );

			return true;
		}
	}
}
