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

Yoast / wordpress-seo / 5794075026

pending completion
5794075026

Pull #20546

github

web-flow
Merge 6c13efa36 into b0de79e54
Pull Request #20546: Introduce the Introductions functionality

135 of 148 new or added lines in 20 files covered. (91.22%)

681 existing lines in 5 files now uncovered.

12419 of 26427 relevant lines covered (46.99%)

3.46 hits per line

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

0.0
/src/integrations/admin/first-time-configuration-integration.php
1
<?php
2

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

5
use WP_User;
6
use WPSEO_Addon_Manager;
7
use WPSEO_Admin_Asset_Manager;
8
use WPSEO_Option_Tab;
9
use WPSEO_Shortlinker;
10
use WPSEO_Utils;
11
use Yoast\WP\SEO\Conditionals\Admin_Conditional;
12
use Yoast\WP\SEO\Context\Meta_Tags_Context;
13
use Yoast\WP\SEO\Helpers\Options_Helper;
14
use Yoast\WP\SEO\Helpers\Product_Helper;
15
use Yoast\WP\SEO\Helpers\Social_Profiles_Helper;
16
use Yoast\WP\SEO\Integrations\Integration_Interface;
17
use Yoast\WP\SEO\Routes\Indexing_Route;
18

19
/**
20
 * First_Time_Configuration_Integration class
21
 */
22
class First_Time_Configuration_Integration implements Integration_Interface {
23

24
        /**
25
         * The admin asset manager.
26
         *
27
         * @var WPSEO_Admin_Asset_Manager
28
         */
29
        private $admin_asset_manager;
30

31
        /**
32
         * The addon manager.
33
         *
34
         * @var WPSEO_Addon_Manager
35
         */
36
        private $addon_manager;
37

38
        /**
39
         * The shortlinker.
40
         *
41
         * @var WPSEO_Shortlinker
42
         */
43
        private $shortlinker;
44

45
        /**
46
         * The options' helper.
47
         *
48
         * @var Options_Helper
49
         */
50
        private $options_helper;
51

52
        /**
53
         * The social profiles helper.
54
         *
55
         * @var Social_Profiles_Helper
56
         */
57
        private $social_profiles_helper;
58

59
        /**
60
         * The product helper.
61
         *
62
         * @var Product_Helper
63
         */
64
        private $product_helper;
65

66
        /**
67
         * The meta tags context helper.
68
         *
69
         * @var Meta_Tags_Context
70
         */
71
        private $meta_tags_context;
72

73
        /**
74
         * {@inheritDoc}
75
         */
76
        public static function get_conditionals() {
77
                return [ Admin_Conditional::class ];
×
78
        }
79

80
        /**
81
         * First_Time_Configuration_Integration constructor.
82
         *
83
         * @param WPSEO_Admin_Asset_Manager $admin_asset_manager    The admin asset manager.
84
         * @param WPSEO_Addon_Manager       $addon_manager          The addon manager.
85
         * @param WPSEO_Shortlinker         $shortlinker            The shortlinker.
86
         * @param Options_Helper            $options_helper         The options helper.
87
         * @param Social_Profiles_Helper    $social_profiles_helper The social profile helper.
88
         * @param Product_Helper            $product_helper         The product helper.
89
         * @param Meta_Tags_Context         $meta_tags_context      The meta tags context helper.
90
         */
91
        public function __construct(
92
                WPSEO_Admin_Asset_Manager $admin_asset_manager,
93
                WPSEO_Addon_Manager $addon_manager,
94
                WPSEO_Shortlinker $shortlinker,
95
                Options_Helper $options_helper,
96
                Social_Profiles_Helper $social_profiles_helper,
97
                Product_Helper $product_helper,
98
                Meta_Tags_Context $meta_tags_context
99
        ) {
100
                $this->admin_asset_manager    = $admin_asset_manager;
×
101
                $this->addon_manager          = $addon_manager;
×
102
                $this->shortlinker            = $shortlinker;
×
103
                $this->options_helper         = $options_helper;
×
104
                $this->social_profiles_helper = $social_profiles_helper;
×
105
                $this->product_helper         = $product_helper;
×
106
                $this->meta_tags_context      = $meta_tags_context;
×
107
        }
108

109
        /**
110
         * {@inheritDoc}
111
         */
112
        public function register_hooks() {
113
                \add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
×
114
                \add_action( 'wpseo_settings_tabs_dashboard', [ $this, 'add_first_time_configuration_tab' ] );
×
115
        }
116

117
        /**
118
         * Adds a dedicated tab in the General sub-page.
119
         *
120
         * @param WPSEO_Options_Tabs $dashboard_tabs Object representing the tabs of the General sub-page.
121
         */
122
        public function add_first_time_configuration_tab( $dashboard_tabs ) {
123
                $dashboard_tabs->add_tab(
×
124
                        new WPSEO_Option_Tab(
×
125
                                'first-time-configuration',
×
126
                                \__( 'First-time configuration', 'wordpress-seo' ),
×
127
                                [ 'save_button' => false ]
×
128
                        )
129
                );
130
        }
131

132
        /**
133
         * Adds the data for the first-time configuration to the wpseoFirstTimeConfigurationData object.
134
         */
135
        public function enqueue_assets() {
136
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Date is not processed or saved.
137
                if ( ! isset( $_GET['page'] ) || $_GET['page'] !== 'wpseo_dashboard' || \is_network_admin() ) {
×
138
                        return;
×
139
                }
140

141
                $this->admin_asset_manager->enqueue_script( 'indexation' );
×
142
                $this->admin_asset_manager->enqueue_script( 'first-time-configuration' );
×
NEW
143
                $this->admin_asset_manager->enqueue_style( 'first-time-configuration' );
×
144
                $this->admin_asset_manager->enqueue_style( 'admin-css' );
×
145
                $this->admin_asset_manager->enqueue_style( 'monorepo' );
×
146

147
                $data = [
148
                        'disabled'     => ! \YoastSEO()->helpers->indexable->should_index_indexables(),
×
149
                        'amount'       => \YoastSEO()->helpers->indexing->get_filtered_unindexed_count(),
×
150
                        'firstTime'    => ( \YoastSEO()->helpers->indexing->is_initial_indexing() === true ),
×
151
                        'errorMessage' => '',
×
152
                        'restApi'      => [
153
                                'root'               => \esc_url_raw( \rest_url() ),
×
154
                                'indexing_endpoints' => $this->get_endpoints(),
×
155
                                'nonce'              => \wp_create_nonce( 'wp_rest' ),
×
156
                        ],
157
                ];
158

159
                /**
160
                 * Filter: 'wpseo_indexing_data' Filter to adapt the data used in the indexing process.
161
                 *
162
                 * @param array $data The indexing data to adapt.
163
                 */
164
                $data = \apply_filters( 'wpseo_indexing_data', $data );
×
165

166
                $this->admin_asset_manager->localize_script( 'indexation', 'yoastIndexingData', $data );
×
167

168
                $person_id       = $this->get_person_id();
×
169
                $social_profiles = $this->get_social_profiles();
×
170

171
                // This filter is documented in admin/views/tabs/metas/paper-content/general/knowledge-graph.php.
172
                $knowledge_graph_message = \apply_filters( 'wpseo_knowledge_graph_setting_msg', '' );
×
173

174
                $finished_steps        = $this->get_finished_steps();
×
175
                $options               = $this->get_company_or_person_options();
×
176
                $selected_option_label = '';
×
177
                $filtered_options      = \array_filter(
×
178
                        $options,
×
179
                        function ( $item ) {
180
                                return $item['value'] === $this->is_company_or_person();
×
181
                        }
182
                );
183
                $selected_option       = \reset( $filtered_options );
×
184
                if ( \is_array( $selected_option ) ) {
×
185
                        $selected_option_label = $selected_option['label'];
186
                }
187

188
                $this->admin_asset_manager->add_inline_script(
×
189
                        'first-time-configuration',
×
190
                        \sprintf(
×
191
                                'window.wpseoFirstTimeConfigurationData = {
192
                                        "canEditUser": %d,
193
                                        "companyOrPerson": "%s",
194
                                        "companyOrPersonLabel": "%s",
195
                                        "companyName": "%s",
196
                                        "fallbackCompanyName": "%s",
197
                                        "websiteName": "%s",
198
                                        "fallbackWebsiteName": "%s",
199
                                        "companyLogo": "%s",
200
                                        "companyLogoFallback": "%s",
201
                                        "companyLogoId": %d,
202
                                        "finishedSteps": %s,
203
                                        "personId": %d,
204
                                        "personName": "%s",
205
                                        "personLogo": "%s",
206
                                        "personLogoFallback": "%s",
207
                                        "personLogoId": %d,
208
                                        "siteTagline": "%s",
209
                                        "socialProfiles": {
210
                                                "facebookUrl": "%s",
211
                                                "twitterUsername": "%s",
212
                                                "otherSocialUrls": %s,
213
                                        },
214
                                        "isPremium": %d,
215
                                        "tracking": %d,
216
                                        "isTrackingAllowedMultisite": %d,
217
                                        "isMainSite": %d,
218
                                        "companyOrPersonOptions": %s,
219
                                        "shouldForceCompany": %d,
220
                                        "knowledgeGraphMessage": "%s",
221
                                        "shortlinks": {
222
                                                "gdpr": "%s",
223
                                                "configIndexables": "%s",
224
                                                "configIndexablesBenefits": "%s",
225
                                        },
226
                                };',
227
                                $this->can_edit_profile( $person_id ),
×
228
                                $this->is_company_or_person(),
×
229
                                $selected_option_label,
×
230
                                $this->get_company_name(),
×
231
                                $this->get_fallback_company_name( $this->get_company_name() ),
×
232
                                $this->get_website_name(),
×
233
                                $this->get_fallback_website_name( $this->get_website_name() ),
×
234
                                $this->get_company_logo(),
×
235
                                $this->get_company_fallback_logo( $this->get_company_logo() ),
×
236
                                $this->get_company_logo_id(),
×
237
                                WPSEO_Utils::format_json_encode( $finished_steps ),
×
238
                                $person_id,
×
239
                                $this->get_person_name(),
×
240
                                $this->get_person_logo(),
×
241
                                $this->get_person_fallback_logo( $this->get_person_logo() ),
×
242
                                $this->get_person_logo_id(),
×
243
                                $this->get_site_tagline(),
×
244
                                $social_profiles['facebook_site'],
×
245
                                $social_profiles['twitter_site'],
×
246
                                WPSEO_Utils::format_json_encode( $social_profiles['other_social_urls'] ),
×
247
                                $this->product_helper->is_premium(),
×
248
                                $this->has_tracking_enabled(),
×
249
                                $this->is_tracking_enabled_multisite(),
×
250
                                $this->is_main_site(),
×
251
                                WPSEO_Utils::format_json_encode( $options ),
×
252
                                $this->should_force_company(),
×
253
                                $knowledge_graph_message,
×
254
                                $this->shortlinker->build_shortlink( 'https://yoa.st/gdpr-config-workout' ),
×
255
                                $this->shortlinker->build_shortlink( 'https://yoa.st/config-indexables' ),
×
256
                                $this->shortlinker->build_shortlink( 'https://yoa.st/config-indexables-benefits' )
257
                        ),
258
                        'before'
259
                );
260
        }
261

262
        /**
263
         * Retrieves a list of the endpoints to use.
264
         *
265
         * @return array The endpoints.
266
         */
267
        protected function get_endpoints() {
268
                $endpoints = [
269
                        'prepare'            => Indexing_Route::FULL_PREPARE_ROUTE,
270
                        'terms'              => Indexing_Route::FULL_TERMS_ROUTE,
271
                        'posts'              => Indexing_Route::FULL_POSTS_ROUTE,
272
                        'archives'           => Indexing_Route::FULL_POST_TYPE_ARCHIVES_ROUTE,
273
                        'general'            => Indexing_Route::FULL_GENERAL_ROUTE,
274
                        'indexablesComplete' => Indexing_Route::FULL_INDEXABLES_COMPLETE_ROUTE,
275
                        'post_link'          => Indexing_Route::FULL_POST_LINKS_INDEXING_ROUTE,
276
                        'term_link'          => Indexing_Route::FULL_TERM_LINKS_INDEXING_ROUTE,
277
                ];
278

279
                $endpoints = \apply_filters( 'wpseo_indexing_endpoints', $endpoints );
280

281
                $endpoints['complete'] = Indexing_Route::FULL_COMPLETE_ROUTE;
282

283
                return $endpoints;
284
        }
285

286
        // ** Private functions ** //
287

288
        /**
289
         * Returns the finished steps array.
290
         *
291
         * @return array An array with the finished steps.
292
         */
293
        private function get_finished_steps() {
294
                return $this->options_helper->get( 'configuration_finished_steps', [] );
295
        }
296

297
        /**
298
         * Returns the entity represented by the site.
299
         *
300
         * @return string The entity represented by the site.
301
         */
302
        private function is_company_or_person() {
303
                return $this->options_helper->get( 'company_or_person', '' );
304
        }
305

306
        /**
307
         * Gets the company name from the option in the database.
308
         *
309
         * @return string The company name.
310
         */
311
        private function get_company_name() {
312
                return $this->options_helper->get( 'company_name', '' );
313
        }
314

315
        /**
316
         * Gets the fallback company name from the option in the database if there is no company name.
317
         *
318
         * @param string $company_name The given company name by the user, default empty string.
319
         *
320
         * @return string|false The company name.
321
         */
322
        private function get_fallback_company_name( $company_name ) {
323
                if ( $company_name ) {
×
324
                        return false;
325
                }
326

327
                return \get_bloginfo( 'name' );
328
        }
329

330
        /**
331
         * Gets the website name from the option in the database.
332
         *
333
         * @return string The website name.
334
         */
335
        private function get_website_name() {
336
                return $this->options_helper->get( 'website_name', '' );
337
        }
338

339
        /**
340
         * Gets the fallback website name from the option in the database if there is no website name.
341
         *
342
         * @param string $website_name The given website name by the user, default empty string.
343
         *
344
         * @return string|false The website name.
345
         */
346
        private function get_fallback_website_name( $website_name ) {
347
                if ( $website_name ) {
×
348
                        return false;
349
                }
350

351
                return \get_bloginfo( 'name' );
352
        }
353

354
        /**
355
         * Gets the company logo from the option in the database.
356
         *
357
         * @return string The company logo.
358
         */
359
        private function get_company_logo() {
360
                return $this->options_helper->get( 'company_logo', '' );
361
        }
362

363
        /**
364
         * Gets the company logo id from the option in the database.
365
         *
366
         * @return string The company logo id.
367
         */
368
        private function get_company_logo_id() {
369
                return $this->options_helper->get( 'company_logo_id', '' );
370
        }
371

372
        /**
373
         * Gets the company logo url from the option in the database.
374
         *
375
         * @param string $company_logo The given company logo by the user, default empty.
376
         *
377
         * @return string|false The company logo URL.
378
         */
379
        private function get_company_fallback_logo( $company_logo ) {
380
                if ( $company_logo ) {
×
381
                        return false;
382
                }
383
                $logo_id = $this->meta_tags_context->fallback_to_site_logo();
384

385
                return \esc_url( \wp_get_attachment_url( $logo_id ) );
386
        }
387

388
        /**
389
         * Gets the person id from the option in the database.
390
         *
391
         * @return int|null The person id, null if empty.
392
         */
393
        private function get_person_id() {
394
                return $this->options_helper->get( 'company_or_person_user_id' );
395
        }
396

397
        /**
398
         * Gets the person id from the option in the database.
399
         *
400
         * @return int|null The person id, null if empty.
401
         */
402
        private function get_person_name() {
403
                $user = \get_userdata( $this->get_person_id() );
×
404
                if ( $user instanceof WP_User ) {
×
405
                        return $user->get( 'display_name' );
406
                }
407

408
                return '';
409
        }
410

411
        /**
412
         * Gets the person avatar from the option in the database.
413
         *
414
         * @return string The person logo.
415
         */
416
        private function get_person_logo() {
417
                return $this->options_helper->get( 'person_logo', '' );
418
        }
419

420
        /**
421
         * Gets the person logo url from the option in the database.
422
         *
423
         * @param string $person_logo The given person logo by the user, default empty.
424
         *
425
         * @return string|false The person logo URL.
426
         */
427
        private function get_person_fallback_logo( $person_logo ) {
428
                if ( $person_logo ) {
×
429
                        return false;
430
                }
431
                $logo_id = $this->meta_tags_context->fallback_to_site_logo();
432

433
                return \esc_url( \wp_get_attachment_url( $logo_id ) );
434
        }
435

436
        /**
437
         * Gets the person logo id from the option in the database.
438
         *
439
         * @return string The person logo id.
440
         */
441
        private function get_person_logo_id() {
442
                return $this->options_helper->get( 'person_logo_id', '' );
443
        }
444

445
        /**
446
         * Gets the site tagline.
447
         *
448
         * @return string The site tagline.
449
         */
450
        private function get_site_tagline() {
451
                return \get_bloginfo( 'description' );
452
        }
453

454
        /**
455
         * Gets the social profiles stored in the database.
456
         *
457
         * @return string[] The social profiles.
458
         */
459
        private function get_social_profiles() {
460
                return $this->social_profiles_helper->get_organization_social_profiles();
461
        }
462

463
        /**
464
         * Checks whether tracking is enabled.
465
         *
466
         * @return bool True if tracking is enabled, false otherwise, null if in Free and conf. workout step not finished.
467
         */
468
        private function has_tracking_enabled() {
469
                $default = false;
470

471
                if ( $this->product_helper->is_premium() ) {
×
472
                        $default = true;
473
                }
474

475
                return $this->options_helper->get( 'tracking', $default );
476
        }
477

478
        /**
479
         * Checks whether tracking option is allowed at network level.
480
         *
481
         * @return bool True if option change is allowed, false otherwise.
482
         */
483
        private function is_tracking_enabled_multisite() {
484
                $default = true;
485

486
                if ( ! \is_multisite() ) {
×
487
                        return $default;
488
                }
489

490
                return $this->options_helper->get( 'allow_tracking', $default );
491
        }
492

493
        /**
494
         * Checks whether we are in a main site.
495
         *
496
         * @return bool True if it's the main site or a single site, false if it's a subsite.
497
         */
498
        private function is_main_site() {
499
                return \is_main_site();
500
        }
501

502
        /**
503
         * Gets the options for the Company or Person select.
504
         * Returns only the company option if it is forced (by Local SEO), otherwise returns company and person option.
505
         *
506
         * @return array The options for the company-or-person select.
507
         */
508
        private function get_company_or_person_options() {
509
                $options = [
510
                        [
511
                                'label' => \__( 'Organization', 'wordpress-seo' ),
×
512
                                'value' => 'company',
×
513
                                'id'    => 'company',
514
                        ],
515
                        [
516
                                'label' => \__( 'Person', 'wordpress-seo' ),
×
517
                                'value' => 'person',
×
518
                                'id'    => 'person',
519
                        ],
520
                ];
521
                if ( $this->should_force_company() ) {
522
                        $options = [
523
                                [
524
                                        'label' => \__( 'Organization', 'wordpress-seo' ),
×
525
                                        'value' => 'company',
×
526
                                        'id'    => 'company',
527
                                ],
528
                        ];
529
                }
530

531
                return $options;
532
        }
533

534
        /**
535
         * Checks whether we should force "Organization".
536
         *
537
         * @return bool
538
         */
539
        private function should_force_company() {
540
                return $this->addon_manager->is_installed( WPSEO_Addon_Manager::LOCAL_SLUG );
541
        }
542

543
        /**
544
         * Checks if the current user has the capability to edit a specific user.
545
         *
546
         * @param int $person_id The id of the person to edit.
547
         *
548
         * @return bool
549
         */
550
        private function can_edit_profile( $person_id ) {
551
                return \current_user_can( 'edit_user', $person_id );
552
        }
553
}
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