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

Yoast / wordpress-seo / 6642005804

25 Oct 2023 02:34PM UTC coverage: 49.112%. Remained the same
6642005804

push

github

pls78
Revert "Avoid storing the full WP_User object in db."

This reverts commit f26657d62.

4 of 6 new or added lines in 1 file covered. (66.67%)

11 existing lines in 1 file now uncovered.

13135 of 26745 relevant lines covered (49.11%)

3.96 hits per line

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

56.41
/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
        const MATCH_ALL = 'all';
20

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

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

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

42
        /**
43
         * Notification type.
44
         *
45
         * @var string
46
         */
47
        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'             => 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
         */
98
        public function __construct( $message, $options = [] ) {
99
                $this->message = $message;
64✔
100
                $this->options = $this->normalize_options( $options );
64✔
101
        }
32✔
102

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

112
        /**
113
         * Retrieve the user to show the notification for.
114
         *
115
         * @return WP_User The user to show this notification for.
116
         */
117
        public function get_user() {
NEW
118
                return $this->options['user'];
×
119
        }
120

121
        /**
122
         * Retrieve the id of the user to show the notification for.
123
         *
124
         * Returns the id of the current user if not user has been sent.
125
         *
126
         * @return int The user id
127
         */
128
        public function get_user_id() {
129
                if ( $this->get_user() !== null ) {
×
NEW
130
                        return $this->get_user()->ID;
×
131
                }
132
                return get_current_user_id();
×
133
        }
134

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

145
                return $this->options['nonce'];
8✔
146
        }
147

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

157
        /**
158
         * Get the type of the notification.
159
         *
160
         * @return string
161
         */
162
        public function get_type() {
163
                return $this->options['type'];
8✔
164
        }
165

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

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

187
                return $this->options['dismissal_key'];
4✔
188
        }
189

190
        /**
191
         * Is this Notification persistent.
192
         *
193
         * @return bool True if persistent, False if fire and forget.
194
         */
195
        public function is_persistent() {
196
                $id = $this->get_id();
28✔
197

198
                return ! empty( $id );
28✔
199
        }
200

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

212
                // If the current user doesn't match capabilities.
213
                return $this->match_capabilities();
20✔
214
        }
215

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

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

239
                // Should be an array.
240
                if ( ! is_array( $capabilities ) ) {
20✔
241
                        $capabilities = (array) $capabilities;
4✔
242
                }
243

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

256
                if ( ! in_array( $capability_check, [ self::MATCH_ALL, self::MATCH_ANY ], true ) ) {
20✔
257
                        $capability_check = self::MATCH_ALL;
×
258
                }
259

260
                if ( ! empty( $capabilities ) ) {
20✔
261

262
                        $has_capabilities = array_filter( $capabilities, [ $this, 'has_capability' ] );
20✔
263

264
                        switch ( $capability_check ) {
10✔
265
                                case self::MATCH_ALL:
266
                                        return $has_capabilities === $capabilities;
12✔
267
                                case self::MATCH_ANY:
268
                                        return ! empty( $has_capabilities );
8✔
269
                        }
270
                }
271

272
                return true;
×
273
        }
274

275
        /**
276
         * Array filter function to find matched capabilities.
277
         *
278
         * @param string $capability Capability to test.
279
         *
280
         * @return bool
281
         */
282
        private function has_capability( $capability ) {
283
                $user = $this->options['user'];
20✔
284
                return $user->has_cap( $capability );
20✔
285
        }
286

287
        /**
288
         * Return the object properties as an array.
289
         *
290
         * @return array
291
         */
292
        public function to_array() {
293
                return [
4✔
294
                        'message' => $this->message,
8✔
295
                        'options' => $this->options,
8✔
296
                ];
4✔
297
        }
298

299
        /**
300
         * Adds string (view) behaviour to the notification.
301
         *
302
         * @return string
303
         */
304
        public function __toString() {
UNCOV
305
                return $this->render();
×
306
        }
307

308
        /**
309
         * Renders the notification as a string.
310
         *
311
         * @return string The rendered notification.
312
         */
313
        public function render() {
314
                $attributes = [];
×
315

316
                // Default notification classes.
317
                $classes = [
318
                        'yoast-notification',
×
319
                ];
320

321
                // Maintain WordPress visualisation of notifications when they are not persistent.
UNCOV
322
                if ( ! $this->is_persistent() ) {
×
323
                        $classes[] = 'notice';
×
324
                        $classes[] = $this->get_type();
×
325
                }
326

UNCOV
327
                if ( ! empty( $classes ) ) {
×
328
                        $attributes['class'] = implode( ' ', $classes );
×
329
                }
330

331
                // Combined attribute key and value into a string.
332
                array_walk( $attributes, [ $this, 'parse_attributes' ] );
×
333

UNCOV
334
                $message = null;
×
335
                if ( $this->options['yoast_branding'] ) {
×
336
                        $message = $this->wrap_yoast_seo_icon( $this->message );
×
337
                }
338

UNCOV
339
                if ( $message === null ) {
×
340
                        $message = wpautop( $this->message );
×
341
                }
342

343
                // Build the output DIV.
UNCOV
344
                return '<div ' . implode( ' ', $attributes ) . '>' . $message . '</div>' . PHP_EOL;
×
345
        }
346

347
        /**
348
         * Wraps the message with a Yoast SEO icon.
349
         *
350
         * @param string $message The message to wrap.
351
         *
352
         * @return string The wrapped message.
353
         */
354
        private function wrap_yoast_seo_icon( $message ) {
355
                $out  = sprintf(
×
UNCOV
356
                        '<img src="%1$s" height="%2$d" width="%3$d" class="yoast-seo-icon" />',
×
357
                        esc_url( plugin_dir_url( WPSEO_FILE ) . 'packages/js/images/Yoast_SEO_Icon.svg' ),
×
358
                        60,
×
359
                        60
×
360
                );
361
                $out .= '<div class="yoast-seo-icon-wrap">';
×
UNCOV
362
                $out .= $message;
×
UNCOV
363
                $out .= '</div>';
×
364

UNCOV
365
                return $out;
×
366
        }
367

368
        /**
369
         * Get the JSON if provided.
370
         *
371
         * @return false|string
372
         */
373
        public function get_json() {
374
                if ( empty( $this->options['data_json'] ) ) {
4✔
375
                        return '';
4✔
376
                }
377

378
                return WPSEO_Utils::format_json_encode( $this->options['data_json'] );
4✔
379
        }
380

381
        /**
382
         * Make sure we only have values that we can work with.
383
         *
384
         * @param array $options Options to normalize.
385
         *
386
         * @return array
387
         */
388
        private function normalize_options( $options ) {
389
                $options = wp_parse_args( $options, $this->defaults );
64✔
390

391
                // Should not exceed 0 or 1.
392
                $options['priority'] = min( 1, max( 0, $options['priority'] ) );
64✔
393

394
                // Set default capabilities when not supplied.
395
                if ( empty( $options['capabilities'] ) || $options['capabilities'] === [] ) {
64✔
396
                        $options['capabilities'] = [ 'wpseo_manage_options' ];
44✔
397
                }
398

399
                // Set to the current user if not supplied.
400
                if ( $options['user'] === null ) {
64✔
401
                        $options['user'] = wp_get_current_user();
64✔
402
                }
403

404
                return $options;
64✔
405
        }
406

407
        /**
408
         * Format HTML element attributes.
409
         *
410
         * @param string $value Attribute value.
411
         * @param string $key   Attribute name.
412
         */
413
        private function parse_attributes( &$value, $key ) {
UNCOV
414
                $value = sprintf( '%s="%s"', sanitize_key( $key ), esc_attr( $value ) );
×
415
        }
416
}
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

© 2026 Coveralls, Inc