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

Yoast / wordpress-seo / abba4d5bc97ae5733ba89412cc79bb357e5d7f21

22 Oct 2024 07:57AM UTC coverage: 54.556% (+0.06%) from 54.494%
abba4d5bc97ae5733ba89412cc79bb357e5d7f21

push

github

YoastBot
Bump version to 23.7 on free

7539 of 13559 branches covered (55.6%)

Branch coverage included in aggregate %.

29669 of 54642 relevant lines covered (54.3%)

41714.3 hits per line

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

0.0
/src/integrations/admin/workouts-integration.php
1
<?php
2

3
namespace Yoast\WP\SEO\Integrations\Admin;
4

5
use WPSEO_Addon_Manager;
6
use WPSEO_Admin_Asset_Manager;
7
use Yoast\WP\SEO\Conditionals\Admin_Conditional;
8
use Yoast\WP\SEO\Conditionals\New_Dashboard_Ui_Conditional;
9
use Yoast\WP\SEO\Helpers\Options_Helper;
10
use Yoast\WP\SEO\Helpers\Product_Helper;
11
use Yoast\WP\SEO\Integrations\Integration_Interface;
12
use Yoast\WP\SEO\Presenters\Admin\Notice_Presenter;
13

14
/**
15
 * WorkoutsIntegration class
16
 */
17
class Workouts_Integration implements Integration_Interface {
18

19
        /**
20
         * The admin asset manager.
21
         *
22
         * @var WPSEO_Admin_Asset_Manager
23
         */
24
        private $admin_asset_manager;
25

26
        /**
27
         * The addon manager.
28
         *
29
         * @var WPSEO_Addon_Manager
30
         */
31
        private $addon_manager;
32

33
        /**
34
         * The options helper.
35
         *
36
         * @var Options_Helper
37
         */
38
        private $options_helper;
39

40
        /**
41
         * The product helper.
42
         *
43
         * @var Product_Helper
44
         */
45
        private $product_helper;
46

47
        /**
48
         * The New Dashboard UI conditional.
49
         *
50
         * @var New_Dashboard_Ui_Conditional
51
         */
52
        private $new_dashboard_ui_conditional;
53

54
        /**
55
         * {@inheritDoc}
56
         */
57
        public static function get_conditionals() {
×
58
                return [ Admin_Conditional::class ];
×
59
        }
60

61
        /**
62
         * Workouts_Integration constructor.
63
         *
64
         * @param WPSEO_Addon_Manager          $addon_manager                The addon manager.
65
         * @param WPSEO_Admin_Asset_Manager    $admin_asset_manager          The admin asset manager.
66
         * @param Options_Helper               $options_helper               The options helper.
67
         * @param Product_Helper               $product_helper               The product helper.
68
         * @param New_Dashboard_Ui_Conditional $new_dashboard_ui_conditional The new dashboard UI conditional.
69
         */
70
        public function __construct(
×
71
                WPSEO_Addon_Manager $addon_manager,
72
                WPSEO_Admin_Asset_Manager $admin_asset_manager,
73
                Options_Helper $options_helper,
74
                Product_Helper $product_helper,
75
                New_Dashboard_Ui_Conditional $new_dashboard_ui_conditional
76
        ) {
77
                $this->addon_manager                = $addon_manager;
×
78
                $this->admin_asset_manager          = $admin_asset_manager;
×
79
                $this->options_helper               = $options_helper;
×
80
                $this->product_helper               = $product_helper;
×
81
                $this->new_dashboard_ui_conditional = $new_dashboard_ui_conditional;
×
82
        }
83

84
        /**
85
         * {@inheritDoc}
86
         */
87
        public function register_hooks() {
×
88
                \add_filter( 'wpseo_submenu_pages', [ $this, 'add_submenu_page' ], 8 );
×
89
                \add_filter( 'wpseo_submenu_pages', [ $this, 'remove_old_submenu_page' ], 10 );
×
90
                \add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ], 11 );
×
91
        }
92

93
        /**
94
         * Adds the workouts submenu page.
95
         *
96
         * @param array $submenu_pages The Yoast SEO submenu pages.
97
         *
98
         * @return array The filtered submenu pages.
99
         */
100
        public function add_submenu_page( $submenu_pages ) {
×
101
                $submenu_pages[] = [
×
102
                        'wpseo_dashboard',
×
103
                        '',
×
104
                        \__( 'Workouts', 'wordpress-seo' ) . ' <span class="yoast-badge yoast-premium-badge"></span>',
×
105
                        'edit_others_posts',
×
106
                        'wpseo_workouts',
×
107
                        [ $this, 'render_target' ],
×
108
                ];
109

110
                return $submenu_pages;
×
111
        }
112

113
        /**
114
         * Removes the workouts submenu page from older Premium versions
115
         *
116
         * @param array $submenu_pages The Yoast SEO submenu pages.
117
         *
118
         * @return array The filtered submenu pages.
119
         */
120
        public function remove_old_submenu_page( $submenu_pages ) {
×
121
                if ( ! $this->should_update_premium() ) {
×
122
                        return $submenu_pages;
×
123
                }
124

125
                // Copy only the Workouts page item that comes first in the array.
126
                $result_submenu_pages      = [];
×
127
                $workouts_page_encountered = false;
×
128
                foreach ( $submenu_pages as $item ) {
×
129
                        if ( $item[4] !== 'wpseo_workouts' || ! $workouts_page_encountered ) {
×
130
                                $result_submenu_pages[] = $item;
×
131
                        }
132
                        if ( $item[4] === 'wpseo_workouts' ) {
×
133
                                $workouts_page_encountered = true;
×
134
                        }
135
                }
136

137
                return $result_submenu_pages;
×
138
        }
139

140
        /**
141
         * Enqueue the workouts app.
142
         *
143
         * @return void
144
         */
145
        public function enqueue_assets() {
×
146
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Date is not processed or saved.
147
                if ( ! isset( $_GET['page'] ) || $_GET['page'] !== 'wpseo_workouts' ) {
×
148
                        return;
×
149
                }
150

151
                if ( $this->should_update_premium() ) {
×
152
                        \wp_dequeue_script( 'yoast-seo-premium-workouts' );
×
153
                }
154

155
                $this->admin_asset_manager->enqueue_style( 'workouts' );
×
156

157
                $workouts_option = $this->get_workouts_option();
×
158
                $ftc_url         = ( $this->new_dashboard_ui_conditional->is_met() ) ? \esc_url( \admin_url( 'admin.php?page=wpseo_dashboard#/first-time-configuration' ) ) : \esc_url( \admin_url( 'admin.php?page=wpseo_dashboard#top#first-time-configuration' ) );
×
159

160
                $this->admin_asset_manager->enqueue_script( 'workouts' );
×
161
                $this->admin_asset_manager->localize_script(
×
162
                        'workouts',
×
163
                        'wpseoWorkoutsData',
×
164
                        [
165
                                'workouts'                  => $workouts_option,
×
166
                                'homeUrl'                   => \home_url(),
×
167
                                'pluginUrl'                 => \esc_url( \plugins_url( '', \WPSEO_FILE ) ),
×
168
                                'toolsPageUrl'              => \esc_url( \admin_url( 'admin.php?page=wpseo_tools' ) ),
×
169
                                'usersPageUrl'              => \esc_url( \admin_url( 'users.php' ) ),
×
170
                                'firstTimeConfigurationUrl' => $ftc_url,
×
171
                                'isPremium'                 => $this->product_helper->is_premium(),
×
172
                                'upsellText'                => $this->get_upsell_text(),
×
173
                                'upsellLink'                => $this->get_upsell_link(),
×
174
                        ]
175
                );
176
        }
177

178
        /**
179
         * Renders the target for the React to mount to.
180
         *
181
         * @return void
182
         */
183
        public function render_target() {
×
184
                if ( $this->should_update_premium() ) {
×
185
                        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in get_update_premium_notice.
186
                        echo $this->get_update_premium_notice();
×
187
                }
188

189
                echo '<div id="wpseo-workouts-container-free" class="yoast"></div>';
×
190
        }
191

192
        /**
193
         * Gets the workouts option.
194
         *
195
         * @return mixed|null Returns workouts option if found, null if not.
196
         */
197
        private function get_workouts_option() {
×
198
                $workouts_option = $this->options_helper->get( 'workouts_data' );
×
199

200
                // This filter is documented in src/routes/workouts-route.php.
201
                return \apply_filters( 'Yoast\WP\SEO\workouts_options', $workouts_option );
×
202
        }
203

204
        /**
205
         * Returns the notification to show when Premium needs to be updated.
206
         *
207
         * @return string The notification to update Premium.
208
         */
209
        private function get_update_premium_notice() {
×
210
                $url = $this->get_upsell_link();
×
211

212
                if ( $this->has_premium_subscription_expired() ) {
×
213
                        /* translators: %s: expands to 'Yoast SEO Premium'. */
214
                        $title = \sprintf( \__( 'Renew your subscription of %s', 'wordpress-seo' ), 'Yoast SEO Premium' );
×
215
                        $copy  = \sprintf(
×
216
                                /* translators: %s: expands to 'Yoast SEO Premium'. */
217
                                \esc_html__(
×
218
                                        'Accessing the latest workouts requires an updated version of %s (at least 17.7), but it looks like your subscription has expired. Please renew your subscription to update and gain access to all the latest features.',
×
219
                                        'wordpress-seo'
×
220
                                ),
221
                                'Yoast SEO Premium'
×
222
                        );
223
                        $button = '<a class="yoast-button yoast-button-upsell yoast-button--small" href="' . \esc_url( $url ) . '" target="_blank">'
×
224
                                        . \esc_html__( 'Renew your subscription', 'wordpress-seo' )
×
225
                                        /* translators: Hidden accessibility text. */
226
                                        . '<span class="screen-reader-text">' . \__( '(Opens in a new browser tab)', 'wordpress-seo' ) . '</span>'
×
227
                                        . '<span aria-hidden="true" class="yoast-button-upsell__caret"></span>'
×
228
                                        . '</a>';
×
229
                }
230
                elseif ( $this->has_premium_subscription_activated() ) {
×
231
                        /* translators: %s: expands to 'Yoast SEO Premium'. */
232
                        $title = \sprintf( \__( 'Update to the latest version of %s', 'wordpress-seo' ), 'Yoast SEO Premium' );
×
233
                        $copy  = \sprintf(
×
234
                                /* translators: 1: expands to 'Yoast SEO Premium', 2: Link start tag to the page to update Premium, 3: Link closing tag. */
235
                                \esc_html__( 'It looks like you\'re running an outdated version of %1$s, please %2$supdate to the latest version (at least 17.7)%3$s to gain access to our updated workouts section.', 'wordpress-seo' ),
×
236
                                'Yoast SEO Premium',
×
237
                                '<a href="' . \esc_url( $url ) . '">',
×
238
                                '</a>'
×
239
                        );
240
                        $button = null;
×
241
                }
242
                else {
243
                        /* translators: %s: expands to 'Yoast SEO Premium'. */
244
                        $title      = \sprintf( \__( 'Activate your subscription of %s', 'wordpress-seo' ), 'Yoast SEO Premium' );
×
245
                        $url_button = 'https://yoa.st/workouts-activate-notice-help';
×
246
                        $copy       = \sprintf(
×
247
                                /* translators: 1: expands to 'Yoast SEO Premium', 2: Link start tag to the page to update Premium, 3: Link closing tag. */
248
                                \esc_html__( 'It looks like you’re running an outdated and unactivated version of %1$s, please activate your subscription in %2$sMyYoast%3$s and update to the latest version (at least 17.7) to gain access to our updated workouts section.', 'wordpress-seo' ),
×
249
                                'Yoast SEO Premium',
×
250
                                '<a href="' . \esc_url( $url ) . '">',
×
251
                                '</a>'
×
252
                        );
253
                        $button = '<a class="yoast-button yoast-button--primary yoast-button--small" href="' . \esc_url( $url_button ) . '" target="_blank">'
×
254
                                        . \esc_html__( 'Get help activating your subscription', 'wordpress-seo' )
×
255
                                        /* translators: Hidden accessibility text. */
256
                                        . '<span class="screen-reader-text">' . \__( '(Opens in a new browser tab)', 'wordpress-seo' ) . '</span>'
×
257
                                        . '</a>';
×
258
                }
259

260
                $notice = new Notice_Presenter(
×
261
                        $title,
×
262
                        $copy,
×
263
                        null,
×
264
                        $button
×
265
                );
266

267
                return $notice->present();
×
268
        }
269

270
        /**
271
         * Check whether Premium should be updated.
272
         *
273
         * @return bool Returns true when Premium is enabled and the version is below 17.7.
274
         */
275
        private function should_update_premium() {
×
276
                $premium_version = $this->product_helper->get_premium_version();
×
277
                return $premium_version !== null && \version_compare( $premium_version, '17.7-RC1', '<' );
×
278
        }
279

280
        /**
281
         * Check whether the Premium subscription has expired.
282
         *
283
         * @return bool Returns true when Premium subscription has expired.
284
         */
285
        private function has_premium_subscription_expired() {
×
286
                $subscription = $this->addon_manager->get_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG );
×
287

288
                return ( isset( $subscription->expiry_date ) && ( \strtotime( $subscription->expiry_date ) - \time() ) < 0 );
×
289
        }
290

291
        /**
292
         * Check whether the Premium subscription is activated.
293
         *
294
         * @return bool Returns true when Premium subscription is activated.
295
         */
296
        private function has_premium_subscription_activated() {
×
297
                return $this->addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG );
×
298
        }
299

300
        /**
301
         * Returns the upsell/update copy to show in the card buttons.
302
         *
303
         * @return string Returns a string with the upsell/update copy for the card buttons.
304
         */
305
        private function get_upsell_text() {
×
306
                if ( ! $this->product_helper->is_premium() || ! $this->should_update_premium() ) {
×
307
                        // Use the default defined in the component.
308
                        return '';
×
309
                }
310
                if ( $this->has_premium_subscription_expired() ) {
×
311
                        return \sprintf(
×
312
                                /* translators: %s: expands to 'Yoast SEO Premium'. */
313
                                \__( 'Renew %s', 'wordpress-seo' ),
×
314
                                'Yoast SEO Premium'
×
315
                        );
316
                }
317
                if ( $this->has_premium_subscription_activated() ) {
×
318
                        return \sprintf(
×
319
                                /* translators: %s: expands to 'Yoast SEO Premium'. */
320
                                \__( 'Update %s', 'wordpress-seo' ),
×
321
                                'Yoast SEO Premium'
×
322
                        );
323
                }
324
                return \sprintf(
×
325
                        /* translators: %s: expands to 'Yoast SEO Premium'. */
326
                        \__( 'Activate %s', 'wordpress-seo' ),
×
327
                        'Yoast SEO Premium'
×
328
                );
329
        }
330

331
        /**
332
         * Returns the upsell/update link to show in the card buttons.
333
         *
334
         * @return string Returns a string with the upsell/update link for the card buttons.
335
         */
336
        private function get_upsell_link() {
×
337
                if ( ! $this->product_helper->is_premium() || ! $this->should_update_premium() ) {
×
338
                        // Use the default defined in the component.
339
                        return '';
×
340
                }
341
                if ( $this->has_premium_subscription_expired() ) {
×
342
                        return 'https://yoa.st/workout-renew-notice';
×
343
                }
344
                if ( $this->has_premium_subscription_activated() ) {
×
345
                        return \wp_nonce_url( \self_admin_url( 'update.php?action=upgrade-plugin&plugin=wordpress-seo-premium/wp-seo-premium.php' ), 'upgrade-plugin_wordpress-seo-premium/wp-seo-premium.php' );
×
346
                }
347
                return 'https://yoa.st/workouts-activate-notice-myyoast';
×
348
        }
349
}
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