• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / dd6e866a9e6d253114633104d9e3858d807178ba

19 Jun 2024 10:03AM UTC coverage: 48.628% (-4.3%) from 52.936%
dd6e866a9e6d253114633104d9e3858d807178ba

push

github

web-flow
Merge pull request #21431 from Yoast/21429-update-copy-in-the-introduction-and-consent-modals

Updates the copy for the introduction and consent modals

7441 of 13454 branches covered (55.31%)

Branch coverage included in aggregate %.

0 of 3 new or added lines in 2 files covered. (0.0%)

3718 existing lines in 107 files now uncovered.

25100 of 53464 relevant lines covered (46.95%)

62392.47 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/admin/class-yoast-notification.php
1
<?php
2
/**
3
 * WPSEO plugin file.
4
 *
5
 * @package WPSEO\Admin\Notifications
6
 * @since   1.5.3
7
 */
8

9
/**
10
 * Implements individual notification.
11
 */
12
class Yoast_Notification {
13

14
        /**
15
         * Type of capability check.
16
         *
17
         * @var string
18
         */
19
        public const MATCH_ALL = 'all';
20

21
        /**
22
         * Type of capability check.
23
         *
24
         * @var string
25
         */
26
        public const MATCH_ANY = 'any';
27

28
        /**
29
         * Notification type.
30
         *
31
         * @var string
32
         */
33
        public const ERROR = 'error';
34

35
        /**
36
         * Notification type.
37
         *
38
         * @var string
39
         */
40
        public const WARNING = 'warning';
41

42
        /**
43
         * Notification type.
44
         *
45
         * @var string
46
         */
47
        public const UPDATED = 'updated';
48

49
        /**
50
         * Options of this Notification.
51
         *
52
         * Contains optional arguments:
53
         *
54
         * -             type: The notification type, i.e. 'updated' or 'error'
55
         * -               id: The ID of the notification
56
         * -            nonce: Security nonce to use in case of dismissible notice.
57
         * -         priority: From 0 to 1, determines the order of Notifications.
58
         * -    dismissal_key: Option name to save dismissal information in, ID will be used if not supplied.
59
         * -     capabilities: Capabilities that a user must have for this Notification to show.
60
         * - capability_check: How to check capability pass: all or any.
61
         * -  wpseo_page_only: Only display on wpseo page or on every page.
62
         *
63
         * @var array
64
         */
65
        private $options = [];
66

67
        /**
68
         * Contains default values for the optional arguments.
69
         *
70
         * @var array
71
         */
72
        private $defaults = [
73
                'type'             => self::UPDATED,
74
                'id'               => '',
75
                'user_id'          => null,
76
                'nonce'            => null,
77
                'priority'         => 0.5,
78
                'data_json'        => [],
79
                'dismissal_key'    => null,
80
                'capabilities'     => [],
81
                'capability_check' => self::MATCH_ALL,
82
                'yoast_branding'   => false,
83
        ];
84

85
        /**
86
         * The message for the notification.
87
         *
88
         * @var string
89
         */
90
        private $message;
91

92
        /**
93
         * Notification class constructor.
94
         *
95
         * @param string $message Message string.
96
         * @param array  $options Set of options.
97
         */
UNCOV
98
        public function __construct( $message, $options = [] ) {
×
UNCOV
99
                $this->message = $message;
×
UNCOV
100
                $this->options = $this->normalize_options( $options );
×
101
        }
102

103
        /**
104
         * Retrieve notification ID string.
105
         *
106
         * @return string
107
         */
UNCOV
108
        public function get_id() {
×
UNCOV
109
                return $this->options['id'];
×
110
        }
111

112
        /**
113
         * Retrieve the user to show the notification for.
114
         *
115
         * @deprecated 21.6
116
         * @codeCoverageIgnore
117
         *
118
         * @return WP_User The user to show this notification for.
119
         */
120
        public function get_user() {
121
                _deprecated_function( __METHOD__, 'Yoast SEO 21.6' );
122
                return null;
123
        }
124

125
        /**
126
         * Retrieve the id of the user to show the notification for.
127
         *
128
         * Returns the id of the current user if not user has been sent.
129
         *
130
         * @return int The user id
131
         */
132
        public function get_user_id() {
×
133
                return ( $this->options['user_id'] ?? get_current_user_id() );
×
134
        }
135

136
        /**
137
         * Retrieve nonce identifier.
138
         *
139
         * @return string|null Nonce for this Notification.
140
         */
UNCOV
141
        public function get_nonce() {
×
UNCOV
142
                if ( $this->options['id'] && empty( $this->options['nonce'] ) ) {
×
UNCOV
143
                        $this->options['nonce'] = wp_create_nonce( $this->options['id'] );
×
144
                }
145

UNCOV
146
                return $this->options['nonce'];
×
147
        }
148

149
        /**
150
         * Make sure the nonce is up to date.
151
         *
152
         * @return void
153
         */
154
        public function refresh_nonce() {
×
155
                if ( $this->options['id'] ) {
×
156
                        $this->options['nonce'] = wp_create_nonce( $this->options['id'] );
×
157
                }
158
        }
159

160
        /**
161
         * Get the type of the notification.
162
         *
163
         * @return string
164
         */
UNCOV
165
        public function get_type() {
×
UNCOV
166
                return $this->options['type'];
×
167
        }
168

169
        /**
170
         * Priority of the notification.
171
         *
172
         * Relative to the type.
173
         *
174
         * @return float Returns the priority between 0 and 1.
175
         */
UNCOV
176
        public function get_priority() {
×
UNCOV
177
                return $this->options['priority'];
×
178
        }
179

180
        /**
181
         * Get the User Meta key to check for dismissal of notification.
182
         *
183
         * @return string User Meta Option key that registers dismissal.
184
         */
UNCOV
185
        public function get_dismissal_key() {
×
UNCOV
186
                if ( empty( $this->options['dismissal_key'] ) ) {
×
UNCOV
187
                        return $this->options['id'];
×
188
                }
189

UNCOV
190
                return $this->options['dismissal_key'];
×
191
        }
192

193
        /**
194
         * Is this Notification persistent.
195
         *
196
         * @return bool True if persistent, False if fire and forget.
197
         */
UNCOV
198
        public function is_persistent() {
×
UNCOV
199
                $id = $this->get_id();
×
200

UNCOV
201
                return ! empty( $id );
×
202
        }
203

204
        /**
205
         * Check if the notification is relevant for the current user.
206
         *
207
         * @return bool True if a user needs to see this notification, false if not.
208
         */
UNCOV
209
        public function display_for_current_user() {
×
210
                // If the notification is for the current page only, always show.
UNCOV
211
                if ( ! $this->is_persistent() ) {
×
UNCOV
212
                        return true;
×
213
                }
214

215
                // If the current user doesn't match capabilities.
UNCOV
216
                return $this->match_capabilities();
×
217
        }
218

219
        /**
220
         * Does the current user match required capabilities.
221
         *
222
         * @return bool
223
         */
UNCOV
224
        public function match_capabilities() {
×
225
                // Super Admin can do anything.
UNCOV
226
                if ( is_multisite() && is_super_admin( $this->options['user_id'] ) ) {
×
227
                        return true;
×
228
                }
229

230
                /**
231
                 * Filter capabilities that enable the displaying of this notification.
232
                 *
233
                 * @param array              $capabilities The capabilities that must be present for this notification.
234
                 * @param Yoast_Notification $notification The notification object.
235
                 *
236
                 * @return array Array of capabilities or empty for no restrictions.
237
                 *
238
                 * @since 3.2
239
                 */
UNCOV
240
                $capabilities = apply_filters( 'wpseo_notification_capabilities', $this->options['capabilities'], $this );
×
241

242
                // Should be an array.
UNCOV
243
                if ( ! is_array( $capabilities ) ) {
×
UNCOV
244
                        $capabilities = (array) $capabilities;
×
245
                }
246

247
                /**
248
                 * Filter capability check to enable all or any capabilities.
249
                 *
250
                 * @param string             $capability_check The type of check that will be used to determine if an capability is present.
251
                 * @param Yoast_Notification $notification     The notification object.
252
                 *
253
                 * @return string self::MATCH_ALL or self::MATCH_ANY.
254
                 *
255
                 * @since 3.2
256
                 */
UNCOV
257
                $capability_check = apply_filters( 'wpseo_notification_capability_check', $this->options['capability_check'], $this );
×
258

UNCOV
259
                if ( ! in_array( $capability_check, [ self::MATCH_ALL, self::MATCH_ANY ], true ) ) {
×
260
                        $capability_check = self::MATCH_ALL;
×
261
                }
262

UNCOV
263
                if ( ! empty( $capabilities ) ) {
×
264

UNCOV
265
                        $has_capabilities = array_filter( $capabilities, [ $this, 'has_capability' ] );
×
266

267
                        switch ( $capability_check ) {
268
                                case self::MATCH_ALL:
UNCOV
269
                                        return $has_capabilities === $capabilities;
×
270
                                case self::MATCH_ANY:
UNCOV
271
                                        return ! empty( $has_capabilities );
×
272
                        }
273
                }
274

275
                return true;
×
276
        }
277

278
        /**
279
         * Array filter function to find matched capabilities.
280
         *
281
         * @param string $capability Capability to test.
282
         *
283
         * @return bool
284
         */
UNCOV
285
        private function has_capability( $capability ) {
×
UNCOV
286
                $user_id = $this->options['user_id'];
×
UNCOV
287
                if ( ! is_numeric( $user_id ) ) {
×
288
                        return false;
×
289
                }
UNCOV
290
                $user = get_user_by( 'id', $user_id );
×
UNCOV
291
                if ( ! $user ) {
×
292
                        return false;
×
293
                }
294

UNCOV
295
                return $user->has_cap( $capability );
×
296
        }
297

298
        /**
299
         * Return the object properties as an array.
300
         *
301
         * @return array
302
         */
UNCOV
303
        public function to_array() {
×
304
                return [
UNCOV
305
                        'message' => $this->message,
×
UNCOV
306
                        'options' => $this->options,
×
307
                ];
308
        }
309

310
        /**
311
         * Adds string (view) behaviour to the notification.
312
         *
313
         * @return string
314
         */
315
        public function __toString() {
×
316
                return $this->render();
×
317
        }
318

319
        /**
320
         * Renders the notification as a string.
321
         *
322
         * @return string The rendered notification.
323
         */
324
        public function render() {
×
325
                $attributes = [];
×
326

327
                // Default notification classes.
328
                $classes = [
329
                        'yoast-notification',
×
330
                ];
331

332
                // Maintain WordPress visualisation of notifications when they are not persistent.
333
                if ( ! $this->is_persistent() ) {
×
334
                        $classes[] = 'notice';
×
335
                        $classes[] = $this->get_type();
×
336
                }
337

338
                if ( ! empty( $classes ) ) {
×
339
                        $attributes['class'] = implode( ' ', $classes );
×
340
                }
341

342
                // Combined attribute key and value into a string.
343
                array_walk( $attributes, [ $this, 'parse_attributes' ] );
×
344

345
                $message = null;
×
346
                if ( $this->options['yoast_branding'] ) {
×
347
                        $message = $this->wrap_yoast_seo_icon( $this->message );
×
348
                }
349

350
                if ( $message === null ) {
×
351
                        $message = wpautop( $this->message );
×
352
                }
353

354
                // Build the output DIV.
355
                return '<div ' . implode( ' ', $attributes ) . '>' . $message . '</div>' . PHP_EOL;
×
356
        }
357

358
        /**
359
         * Wraps the message with a Yoast SEO icon.
360
         *
361
         * @param string $message The message to wrap.
362
         *
363
         * @return string The wrapped message.
364
         */
365
        private function wrap_yoast_seo_icon( $message ) {
×
366
                $out  = sprintf(
×
367
                        '<img src="%1$s" height="%2$d" width="%3$d" class="yoast-seo-icon" />',
×
368
                        esc_url( plugin_dir_url( WPSEO_FILE ) . 'packages/js/images/Yoast_SEO_Icon.svg' ),
×
369
                        60,
×
370
                        60
×
371
                );
372
                $out .= '<div class="yoast-seo-icon-wrap">';
×
373
                $out .= $message;
×
374
                $out .= '</div>';
×
375

376
                return $out;
×
377
        }
378

379
        /**
380
         * Get the JSON if provided.
381
         *
382
         * @return false|string
383
         */
UNCOV
384
        public function get_json() {
×
UNCOV
385
                if ( empty( $this->options['data_json'] ) ) {
×
UNCOV
386
                        return '';
×
387
                }
388

UNCOV
389
                return WPSEO_Utils::format_json_encode( $this->options['data_json'] );
×
390
        }
391

392
        /**
393
         * Make sure we only have values that we can work with.
394
         *
395
         * @param array $options Options to normalize.
396
         *
397
         * @return array
398
         */
UNCOV
399
        private function normalize_options( $options ) {
×
UNCOV
400
                $options = wp_parse_args( $options, $this->defaults );
×
401

402
                // Should not exceed 0 or 1.
UNCOV
403
                $options['priority'] = min( 1, max( 0, $options['priority'] ) );
×
404

405
                // Set default capabilities when not supplied.
UNCOV
406
                if ( empty( $options['capabilities'] ) || $options['capabilities'] === [] ) {
×
UNCOV
407
                        $options['capabilities'] = [ 'wpseo_manage_options' ];
×
408
                }
409

410
                // Set to the id of the current user if not supplied.
UNCOV
411
                if ( $options['user_id'] === null ) {
×
UNCOV
412
                        $options['user_id'] = get_current_user_id();
×
413
                }
414

UNCOV
415
                return $options;
×
416
        }
417

418
        /**
419
         * Format HTML element attributes.
420
         *
421
         * @param string $value Attribute value.
422
         * @param string $key   Attribute name.
423
         *
424
         * @return void
425
         */
426
        private function parse_attributes( &$value, $key ) {
×
427
                $value = sprintf( '%s="%s"', sanitize_key( $key ), esc_attr( $value ) );
×
428
        }
429
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc