You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
5.4 KiB

<?php
/**
* Class AMP_Admin_Pointer
*
* @package AMP
* @since 1.2
*/
/**
* Class representing a single admin pointer.
*
* @since 1.2
*/
class AMP_Admin_Pointer {
/**
* Unique pointer slug.
*
* @since 1.2
* @var string
*/
private $slug;
/**
* Pointer arguments.
*
* @since 1.2
* @var array
*/
private $args;
/**
* Internal storage for dismissed pointers, to prevent repeated parsing.
*
* @since 1.2
* @static
* @var array|null
*/
private static $dismissed_pointers;
/**
* Constructor.
*
* @since 1.2
*
* @param string $slug Unique pointer slug.
* @param array $args {
* Associative array of pointer arguments.
*
* @type string $selector Required DOM selector for the element to point at.
* @type string $description Required pointer description. May contain inline HTML tags.
* @type string $heading Pointer heading. May contain inline HTML tags. Default empty string.
* @type string $subheading Pointer subheading. May contain inline HTML tags. Default empty string.
* @type array $position Position information for the pointer. Must be an array with keys
* 'edge' and 'align'. Default is 'edge' set to 'left' and 'align' set
* to 'bottom'.
* @type string $class Additional CSS class for the pointer. Default empty string.
* @type callable $active_callback Callback function to determine whether the pointer is active in the
* current context. The current admin screen's hook suffix is passed to
* the callback. Default is that the pointer is active unconditionally.
* }
*/
public function __construct( $slug, array $args ) {
$default_position = [
'edge' => is_rtl() ? 'right' : 'left',
'align' => 'bottom',
];
if ( isset( $args['position'] ) ) {
$args['position'] = wp_parse_args( (array) $args['position'], $default_position );
}
$this->slug = $slug;
$this->args = wp_parse_args(
$args,
[
'selector' => '',
'description' => '',
'heading' => '',
'subheading' => '',
'position' => $default_position,
'class' => '',
'active_callback' => null,
]
);
}
/**
* Gets the pointer slug.
*
* @since 1.2
*
* @return string Unique pointer slug.
*/
public function get_slug() {
return $this->slug;
}
/**
* Checks whether the pointer is active.
*
* This method executes the active callback and looks at whether the pointer has been dismissed in order to
* determine whether the pointer should be active or not.
*
* @since 1.2
*
* @param string $hook_suffix The current admin screen hook suffix.
* @return bool True if the pointer is active, false otherwise.
*/
public function is_active( $hook_suffix ) {
if ( ! $this->args['selector'] || ! $this->args['description'] ) {
return false;
}
if ( ! $this->args['active_callback'] ) {
return true;
}
if ( ! call_user_func( $this->args['active_callback'], $hook_suffix ) ) {
return false;
}
// Populate dismissed pointers list only once.
if ( null === self::$dismissed_pointers ) {
// Use array_flip() for more performant lookup.
self::$dismissed_pointers = array_flip( explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) ) );
}
return ! isset( self::$dismissed_pointers[ $this->slug ] );
}
/**
* Enqueues the script for the pointer.
*
* @since 1.2
*/
public function enqueue() {
wp_enqueue_style( 'wp-pointer' );
wp_enqueue_script( 'wp-pointer' );
wp_enqueue_style(
'amp-validation-tooltips',
amp_get_asset_url( 'css/amp-validation-tooltips.css' ),
[ 'wp-pointer' ],
AMP__VERSION
);
wp_styles()->add_data( 'amp-validation-tooltips', 'rtl', 'replace' );
add_action(
'admin_print_footer_scripts',
function() {
$this->print_js();
}
);
}
/**
* Prints the script for the pointer inline.
*
* Requires the 'wp-pointer' script to be loaded.
*
* @since 1.2
*/
private function print_js() {
$content = '<p>' . wp_kses( $this->args['description'], 'amp_admin_pointer' ) . '</p>';
if ( $this->args['subheading'] ) {
$content = '<p><strong>' . wp_kses( $this->args['subheading'], 'amp_admin_pointer' ) . '</strong></p>' . $content;
}
if ( $this->args['heading'] ) {
$content = '<h3>' . wp_kses( $this->args['heading'], 'amp_admin_pointer' ) . '</h3>' . $content;
}
$args = [
'content' => $content,
'position' => $this->args['position'],
'pointerClass' => 'wp-pointer wp-amp-pointer' . ( ! empty( $this->args['class'] ) ? ' ' . $this->args['class'] : '' ),
];
?>
<script type="text/javascript">
( function( $ ) {
var options = <?php echo wp_json_encode( $args ); ?>;
if ( ! options ) {
return;
}
options = $.extend( options, {
close: function() {
$.post( ajaxurl, {
pointer: '<?php echo esc_js( $this->slug ); ?>',
action: 'dismiss-wp-pointer'
});
}
});
function setup() {
$( '<?php echo esc_js( $this->args['selector'] ); ?>' ).first().pointer( options ).pointer( 'open' );
}
if ( options.position && options.position.defer_loading ) {
$( window ).bind( 'load.wp-pointers', setup );
} else {
$( document ).ready( setup );
}
} )( jQuery );
</script>
<?php
}
}