* @copyright 2022 Nilambar Sharma
* @package WPAdminNotice
*/
namespace Nilambar\AdminNotice;
defined( 'WPINC' ) || die;
/**
* Class Notice.
*/
class Notice {
/**
* Prefix.
*
* @var string $prefix
*
* @since 1.0.0
*/
private $prefix = '';
/**
* Name.
*
* @var string $name
*
* @since 1.0.0
*/
private $name = '';
/**
* Type.
*
* @var string $type
*
* @since 1.0.0
*/
private $type = '';
/**
* Slug.
*
* @var string $slug
*
* @since 1.0.0
*/
private $slug = '';
/**
* Number of days to show the notice after.
*
* @var int $days
*
* @since 1.0.0
*/
private $days = 7;
/**
* WP admin page screens to show notice.
*
* @var array $screens
*
* @since 1.0.0
*/
private $screens = array();
/**
* Notice classes.
*
* @var array $classes
*
* @since 1.0.0
*/
private $classes = array( 'notice', 'notice-info' );
/**
* Actions link texts.
*
* @var array $action_labels
*
* @since 1.0.0
*/
private $action_labels = array();
/**
* Message.
*
* @var string $message
*
* @since 1.0.0
*/
private $message = '';
/**
* Minimum capability for the user to see and dismiss notice.
*
* @var string $capability
*
* @since 1.0.0
*/
private $capability = 'manage_options';
/**
* Constructor.
*
* @param array $args Arguments.
*
* @since 1.0.0
*
* @return void
*/
private function __construct( $args ) {
if ( is_admin() ) {
$this->configure( $args );
$this->hooks();
$this->process_actions();
}
}
/**
* Create and get new Notice instance.
*
* @param array $args Arguments array.
*
* @since 1.0.0
*
* @return Notice
*/
public static function init( $args ) {
static $notices = array();
$slug = ( isset( $args['slug'] ) && ! empty( $args['slug'] ) ) ? $args['slug'] : '';
if ( '' === $slug ) {
return;
}
if ( ! isset( $notices[ $slug ] ) || ! $notices[ $slug ] instanceof Notice ) {
$notices[ $slug ] = new self( $args );
}
return $notices[ $slug ];
}
public function hooks() {
add_action('admin_notices', array( $this, 'hook_notice' ) );
}
public function hook_notice() {
$this->render();
}
/**
* Return review URL.
*
* @since 1.0.0
*
* @return string Review URL.
*/
public function get_review_url() {
$url = '';
switch ( $this->type ) {
case 'plugin':
$url = 'https://wordpress.org/support/plugin/' . $this->slug . '/reviews/#new-post';
break;
case 'theme':
$url = 'https://wordpress.org/support/theme/' . $this->slug . '/reviews/#new-post';
break;
default:
break;
}
return $url;
}
/**
* Render links.
*
* @since 1.0.0
*/
public function render_links() {
// Review link.
if ( ! empty( $this->action_labels['review'] ) ) {
echo '
' . esc_html( $this->action_labels['review'] ) . '
';
}
// Later link.
if ( ! empty( $this->action_labels['later'] ) ) {
echo '' . esc_html( $this->action_labels['later'] ) . '
';
}
// Dismiss link.
if ( ! empty( $this->action_labels['dismiss'] ) ) {
echo '' . esc_html( $this->action_labels['dismiss'] ) . '
';
}
}
/**
* Render the notice.
*
* @since 1.0.0
*/
public function render() {
// Bail if not valid.
if ( ! $this->can_show() && ! empty( $this->message ) ) {
return;
}
?>
message; ?>
render_links(); ?>
key( 'time' ) );
// If not set, set now and bail.
if ( empty( $time ) ) {
$time = time() + ( $this->days * DAY_IN_SECONDS );
// Set to future.
update_site_option( $this->key( 'time' ), $time );
return false;
}
// Check if time passed or reached.
return (int) $time <= time();
}
/**
* Check if the notice is already dismissed.
*
* @since 1.0.0
*
* @return bool
*/
protected function is_dismissed() {
// Get current user.
$current_user = wp_get_current_user();
// Check if current item is dismissed.
return (bool) get_user_meta(
$current_user->ID,
$this->key( 'dismissed' ),
true
);
}
/**
* Check if current user has the capability.
*
* @since 1.0.0
*
* @return bool
*/
protected function is_capable() {
return current_user_can( $this->capability );
}
/**
* Check if the current screen is allowed.
*
* @since 1.0.0
*
* @return bool
*/
protected function in_screen() {
// If not screen ID is set, show everywhere.
if ( empty( $this->screens ) ) {
return true;
}
if ( ! function_exists( 'get_current_screen' ) ) {
return true;
}
// Get current screen.
$screen = get_current_screen();
// Check if current screen id is allowed.
return ! empty( $screen->id ) && in_array( $screen->id, $this->screens, true );
}
/**
* Get the class names for notice div.
*
* @since 1.0.0
*
* @return string
*/
protected function get_classes() {
// Required classes.
$classes = array( 'notice', 'notice-info' );
// Add extra classes.
if ( ! empty( $this->classes ) && is_array( $this->classes ) ) {
$classes = array_merge( $classes, $this->classes );
$classes = array_unique( $classes );
}
return implode( ' ', $classes );
}
/**
* Get the default notice message.
*
* @since 1.0.0
*
* @return string
*/
protected function get_message() {
$message = sprintf(
// translators: %1$s Name, %2$s days.
esc_html__( 'Hello! Seems like you have been using %1$s for more than %2$d days – that’s awesome! Could you please do us a BIG favor and give it a 5-star rating on WordPress? This would boost our motivation and help us spread the word.', 'wp-admin-notice' ),
'' . esc_html( $this->name ) . '',
(int) $this->days
);
return $message;
}
/**
* Check if we can show the notice.
*/
protected function can_show() {
// return true;
return (
$this->in_screen() &&
$this->is_capable() &&
$this->is_time() &&
! $this->is_dismissed()
);
}
/**
* Process the notice actions.
*
* If current user is capable process actions.
* > Later: Extend the time to show the notice.
* > Dismiss: Hide the notice to current user.
*
* @since 1.0.0
*
* @return void
*/
protected function process_actions() {
// Only if required.
if ( ! $this->in_screen() || ! $this->is_capable() ) {
return;
}
$action_list = array( 'later', 'dismiss' );
$action = '';
if ( isset( $_REQUEST[ $this->key( 'action' ) ] ) && ! empty( $_REQUEST[ $this->key( 'action' ) ] ) && in_array( $_REQUEST[ $this->key( 'action' ) ], $action_list, true ) ) {
$action = $_REQUEST[ $this->key( 'action' ) ];
}
switch ( $action ) {
case 'later':
// Show after 7 days.
$time = time() + ( $this->days * DAY_IN_SECONDS + 7 * DAY_IN_SECONDS );
update_site_option( $this->key( 'time' ), $time );
break;
case 'dismiss':
// Do not show again to this user.
update_user_meta( get_current_user_id(), $this->key( 'dismissed' ), true );
break;
}
}
/**
* Configure notice.
*
* @param array $args Arguments.
*
* @since 1.0.0
*
* @return void
*/
private function configure( $args ) {
$slug = ( isset( $args['slug'] ) && ! empty( $args['slug'] ) ) ? $args['slug'] : '';
if ( empty( $slug ) ) {
return;
}
// Default arguments.
$args = wp_parse_args(
$args,
array(
'days' => 7,
'name' => ucwords( str_replace( '-', ' ', $slug ) ),
'capability' => 'manage_options',
'type' => 'plugin',
'screens' => array(),
'classes' => array(),
'action_labels' => array(),
)
);
// Action button/link labels.
$this->action_labels = wp_parse_args(
(array) $args['action_labels'],
array(
'review' => esc_html__( 'Ok, you deserve it', 'wp-admin-notice' ),
'later' => esc_html__( 'Nope, maybe later', 'wp-admin-notice' ),
'dismiss' => esc_html__( 'I already did', 'wp-admin-notice' ),
)
);
if ( ! in_array( $args['type'], array( 'plugin', 'theme' ), true ) ) {
$args['type'] = 'plugin';
}
$this->slug = (string) $slug;
$this->name = (string) $args['name'];
$this->type = (string) $args['type'];
$this->capability = (string) $args['capability'];
$this->days = (int) $args['days'];
$this->screens = (array) $args['screens'];
$this->classes = (array) $args['classes'];
$this->prefix = str_replace( '-', '_', $this->slug );
$this->message = empty( $args['message'] ) ? $this->get_message() : (string) $args['message'];
}
/**
* Create prefixed key.
*
* @param string $key Key.
*
* @since 1.0.0
*
* @return string
*/
private function key( $key ) {
return $this->prefix . '_wpan_' . $key;
}
}