123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- <?php
- /**
- * WPSEO plugin file.
- *
- * @package WPSEO\Admin\Notifications
- * @since 1.5.3
- */
- /**
- * Implements individual notification.
- */
- class Yoast_Notification {
- /**
- * Type of capability check.
- *
- * @var string
- */
- const MATCH_ALL = 'all';
- /**
- * Type of capability check.
- *
- * @var string
- */
- const MATCH_ANY = 'any';
- /**
- * Notification type.
- *
- * @var string
- */
- const ERROR = 'error';
- /**
- * Notification type.
- *
- * @var string
- */
- const WARNING = 'warning';
- /**
- * Notification type.
- *
- * @var string
- */
- const UPDATED = 'updated';
- /**
- * Options of this Notification.
- *
- * Contains optional arguments:
- *
- * - type: The notification type, i.e. 'updated' or 'error'
- * - id: The ID of the notification
- * - nonce: Security nonce to use in case of dismissible notice.
- * - priority: From 0 to 1, determines the order of Notifications.
- * - dismissal_key: Option name to save dismissal information in, ID will be used if not supplied.
- * - capabilities: Capabilities that a user must have for this Notification to show.
- * - capability_check: How to check capability pass: all or any.
- * - wpseo_page_only: Only display on wpseo page or on every page.
- *
- * @var array
- */
- private $options = [];
- /**
- * Contains default values for the optional arguments.
- *
- * @var array
- */
- private $defaults = [
- 'type' => self::UPDATED,
- 'id' => '',
- 'nonce' => null,
- 'priority' => 0.5,
- 'data_json' => [],
- 'dismissal_key' => null,
- 'capabilities' => [],
- 'capability_check' => self::MATCH_ALL,
- 'yoast_branding' => false,
- ];
- /**
- * The message for the notification.
- *
- * @var string
- */
- private $message;
- /**
- * Notification class constructor.
- *
- * @param string $message Message string.
- * @param array $options Set of options.
- */
- public function __construct( $message, $options = [] ) {
- $this->message = $message;
- $this->options = $this->normalize_options( $options );
- }
- /**
- * Retrieve notification ID string.
- *
- * @return string
- */
- public function get_id() {
- return $this->options['id'];
- }
- /**
- * Retrieve nonce identifier.
- *
- * @return null|string Nonce for this Notification.
- */
- public function get_nonce() {
- if ( $this->options['id'] && empty( $this->options['nonce'] ) ) {
- $this->options['nonce'] = wp_create_nonce( $this->options['id'] );
- }
- return $this->options['nonce'];
- }
- /**
- * Make sure the nonce is up to date.
- */
- public function refresh_nonce() {
- if ( $this->options['id'] ) {
- $this->options['nonce'] = wp_create_nonce( $this->options['id'] );
- }
- }
- /**
- * Get the type of the notification.
- *
- * @return string
- */
- public function get_type() {
- return $this->options['type'];
- }
- /**
- * Priority of the notification.
- *
- * Relative to the type.
- *
- * @return float Returns the priority between 0 and 1.
- */
- public function get_priority() {
- return $this->options['priority'];
- }
- /**
- * Get the User Meta key to check for dismissal of notification.
- *
- * @return string User Meta Option key that registers dismissal.
- */
- public function get_dismissal_key() {
- if ( empty( $this->options['dismissal_key'] ) ) {
- return $this->options['id'];
- }
- return $this->options['dismissal_key'];
- }
- /**
- * Is this Notification persistent.
- *
- * @return bool True if persistent, False if fire and forget.
- */
- public function is_persistent() {
- $id = $this->get_id();
- return ! empty( $id );
- }
- /**
- * Check if the notification is relevant for the current user.
- *
- * @return bool True if a user needs to see this notification, false if not.
- */
- public function display_for_current_user() {
- // If the notification is for the current page only, always show.
- if ( ! $this->is_persistent() ) {
- return true;
- }
- // If the current user doesn't match capabilities.
- return $this->match_capabilities();
- }
- /**
- * Does the current user match required capabilities.
- *
- * @return bool
- */
- public function match_capabilities() {
- // Super Admin can do anything.
- if ( is_multisite() && is_super_admin() ) {
- return true;
- }
- /**
- * Filter capabilities that enable the displaying of this notification.
- *
- * @param array $capabilities The capabilities that must be present for this notification.
- * @param Yoast_Notification $notification The notification object.
- *
- * @return array Array of capabilities or empty for no restrictions.
- *
- * @since 3.2
- */
- $capabilities = apply_filters( 'wpseo_notification_capabilities', $this->options['capabilities'], $this );
- // Should be an array.
- if ( ! is_array( $capabilities ) ) {
- $capabilities = (array) $capabilities;
- }
- /**
- * Filter capability check to enable all or any capabilities.
- *
- * @param string $capability_check The type of check that will be used to determine if an capability is present.
- * @param Yoast_Notification $notification The notification object.
- *
- * @return string self::MATCH_ALL or self::MATCH_ANY.
- *
- * @since 3.2
- */
- $capability_check = apply_filters( 'wpseo_notification_capability_check', $this->options['capability_check'], $this );
- if ( ! in_array( $capability_check, [ self::MATCH_ALL, self::MATCH_ANY ], true ) ) {
- $capability_check = self::MATCH_ALL;
- }
- if ( ! empty( $capabilities ) ) {
- $has_capabilities = array_filter( $capabilities, [ $this, 'has_capability' ] );
- switch ( $capability_check ) {
- case self::MATCH_ALL:
- return $has_capabilities === $capabilities;
- case self::MATCH_ANY:
- return ! empty( $has_capabilities );
- }
- }
- return true;
- }
- /**
- * Array filter function to find matched capabilities.
- *
- * @param string $capability Capability to test.
- *
- * @return bool
- */
- private function has_capability( $capability ) {
- return current_user_can( $capability );
- }
- /**
- * Return the object properties as an array.
- *
- * @return array
- */
- public function to_array() {
- return [
- 'message' => $this->message,
- 'options' => $this->options,
- ];
- }
- /**
- * Adds string (view) behaviour to the notification.
- *
- * @return string
- */
- public function __toString() {
- return $this->render();
- }
- /**
- * Renders the notification as a string.
- *
- * @return string The rendered notification.
- */
- public function render() {
- $attributes = [];
- // Default notification classes.
- $classes = [
- 'yoast-alert',
- ];
- // Maintain WordPress visualisation of alerts when they are not persistent.
- if ( ! $this->is_persistent() ) {
- $classes[] = 'notice';
- $classes[] = $this->get_type();
- }
- if ( ! empty( $classes ) ) {
- $attributes['class'] = implode( ' ', $classes );
- }
- // Combined attribute key and value into a string.
- array_walk( $attributes, [ $this, 'parse_attributes' ] );
- $message = null;
- if ( $this->options['yoast_branding'] ) {
- $message = $this->wrap_yoast_seo_icon( $this->message );
- }
- if ( $message === null ) {
- $message = wpautop( $this->message );
- }
- // Build the output DIV.
- return '<div ' . implode( ' ', $attributes ) . '>' . $message . '</div>' . PHP_EOL;
- }
- /**
- * Wraps the message with a Yoast SEO icon.
- *
- * @param string $message The message to wrap.
- *
- * @return string The wrapped message.
- */
- private function wrap_yoast_seo_icon( $message ) {
- $out = sprintf(
- '<img src="%1$s" height="%2$d" width="%3$d" class="yoast-seo-icon" />',
- esc_url( plugin_dir_url( WPSEO_FILE ) . 'images/Yoast_SEO_Icon.svg' ),
- 60,
- 60
- );
- $out .= '<div class="yoast-seo-icon-wrap">';
- $out .= $message;
- $out .= '</div>';
- return $out;
- }
- /**
- * Get the JSON if provided.
- *
- * @return false|string
- */
- public function get_json() {
- if ( empty( $this->options['data_json'] ) ) {
- return '';
- }
- return WPSEO_Utils::format_json_encode( $this->options['data_json'] );
- }
- /**
- * Make sure we only have values that we can work with.
- *
- * @param array $options Options to normalize.
- *
- * @return array
- */
- private function normalize_options( $options ) {
- $options = wp_parse_args( $options, $this->defaults );
- // Should not exceed 0 or 1.
- $options['priority'] = min( 1, max( 0, $options['priority'] ) );
- // Set default capabilities when not supplied.
- if ( empty( $options['capabilities'] ) || [] === $options['capabilities'] ) {
- $options['capabilities'] = [ 'wpseo_manage_options' ];
- }
- return $options;
- }
- /**
- * Format HTML element attributes.
- *
- * @param string $value Attribute value.
- * @param string $key Attribute name.
- */
- private function parse_attributes( &$value, $key ) {
- $value = sprintf( '%s="%s"', sanitize_key( $key ), esc_attr( $value ) );
- }
- }
|