Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
4.26% covered (danger)
4.26%
26 / 611
14.29% covered (danger)
14.29%
7 / 49
CRAP
n/a
0 / 0
wpcom_launchpad_get_task_list_definitions
0.00% covered (danger)
0.00%
0 / 333
0.00% covered (danger)
0.00%
0 / 1
2
wpcom_launchpad_get_task_list
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
wpcom_launchpad_get_task_lists
18.18% covered (danger)
18.18%
2 / 11
0.00% covered (danger)
0.00%
0 / 1
18.69
wpcom_register_default_launchpad_checklists
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
wpcom_launchpad_get_retired_site_intents
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
wpcom_launchpad_clear_retired_site_intents
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
wpcom_launchpad_clear_retired_site_intents_on_correct_action
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
wpcom_add_active_task_listener_hooks_to_correct_action
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
wpcom_launchpad_add_active_task_listeners
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
wpcom_can_update_design_selected_task
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
20
wpcom_is_checklist_task_complete
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
wpcom_get_launchpad_checklist_by_checklist_slug
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
wpcom_register_launchpad_task_list
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
wpcom_launchpad_get_required_tasks
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
wpcom_launchpad_get_launch_tasks
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
wpcom_launchpad_are_all_tasks_completed
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
wpcom_default_launchpad_task_list_completed
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
42
wpcom_launchpad_is_task_list_completed
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
wpcom_register_launchpad_tasks
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
wpcom_register_launchpad_task
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
wpcom_launchpad_checklists
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
wpcom_hacky_track_video_uploaded_task
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
wpcom_maybe_disable_for_difm
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
wpcom_maybe_preview_with_no_interactions
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
wpcom_log_launchpad_being_enabled_for_test_sites
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
12
wpcom_launchpad_get_fullscreen_enabled
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
wpcom_get_launchpad_task_list_is_enabled
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
wpcom_launchpad_is_task_list_dismissed
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
wpcom_launchpad_is_task_list_dismissible
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
wpcom_launchpad_task_list_dismissed_until
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
wpcom_launchpad_set_task_list_dismissed
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
wpcom_launchpad_is_fse_next_steps_modal_hidden
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
20
wpcom_launchpad_set_fse_next_steps_modal_hidden
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
110
wpcom_launchpad_navigator_get_checklists
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
20
wpcom_launchpad_navigator_update_checklists
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
wpcom_launchpad_navigator_remove_checklist
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
30
wpcom_launchpad_navigator_add_checklist
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
wpcom_launchpad_get_active_checklist
77.78% covered (warning)
77.78%
7 / 9
0.00% covered (danger)
0.00%
0 / 1
5.27
wpcom_launchpad_set_current_active_checklist
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
110
wpcom_launchpad_is_keep_building_enabled
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
wpcom_launchpad_is_hosting_flow_enabled
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
wpcom_launchpad_is_intent_write_enabled
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
wpcom_launchpad_is_free_newsletter_enabled
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
wpcom_launchpad_is_paid_newsletter_enabled
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
wpcom_launchpad_is_newsletter_goal_enabled
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
add_launchpad_options_to_jetpack_sync
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
20
wpcom_get_launchpad_checklist_title_by_checklist_slug
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
wpcom_get_launchpad_config_option
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
wpcom_set_launchpad_config_option
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Launchpad Helpers
4 *
5 * @package automattic/jetpack-mu-wpcom
6 * @since 1.4.0
7 */
8
9/**
10 * This file provides helpers that return the appropriate Launchpad
11 * checklist and tasks for a given checklist id.
12 *
13 * @package automattic/jetpack-mu-wpcom
14 * @since 1.4.0
15 */
16
17// Type aliases used in a bunch of places in this file. Unfortunately Phan doesn't have a way to set these more globally than copy-pasting them into each file needing them.
18<<<'PHAN'
19@phan-type Task_List = array{id:string, task_ids:string[], required_task_ids?:string[], visible_tasks_callback?:callable, require_last_task_completion?:bool, get_title?:callable, is_dismissible?:bool, is_enabled_callback?:callable}
20@phan-type Task = array{id:string, title?:string, get_title?:callable, id_map?:string, add_listener_callback?:callable, badge_text_callback?:callable, extra_data_callback?:callable, get_calypso_path?:callable, is_complete_callback?:callable, is_disabled_callback?:callable, isLaunchTask?:bool, is_visible_callback?:callable, target_repetitions?:int, repetition_count_callback?:callable, subtitle?:callable, completed?:bool}
21PHAN;
22
23require_once __DIR__ . '/../../utils.php';
24require_once __DIR__ . '/class-launchpad-task-lists.php';
25require_once __DIR__ . '/launchpad-task-definitions.php';
26
27/**
28 * Registers all default launchpad checklists
29 *
30 * @return Task[]
31 */
32function wpcom_launchpad_get_task_list_definitions() {
33    $core_task_list_definitions = array(
34        'build'                   => array(
35            'get_title'           => function () {
36                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
37            },
38            'task_ids'            => array(
39                'plan_selected',
40                'site_theme_selected',
41                'domain_upsell',
42                'mobile_app_installed',
43                'site_launched',
44            ),
45            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
46        ),
47        'free'                    => array(
48            'get_title'           => function () {
49                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
50            },
51            'task_ids'            => array(
52                'plan_selected',
53                'setup_free',
54                'design_completed',
55                'site_theme_selected',
56                'domain_upsell',
57                'first_post_published',
58                'site_launched',
59            ),
60            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
61        ),
62        'link-in-bio'             => array(
63            'get_title'           => function () {
64                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
65            },
66            'task_ids'            => array(
67                'design_selected',
68                'plan_selected',
69                'links_added',
70                'link_in_bio_launched',
71            ),
72            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
73        ),
74        'link-in-bio-tld'         => array(
75            'get_title'           => function () {
76                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
77            },
78            'task_ids'            => array(
79                'design_selected',
80                'plan_selected',
81                'links_added',
82                'link_in_bio_launched',
83            ),
84            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
85        ),
86        'newsletter'              => array(
87            'get_title'           => function () {
88                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
89            },
90            'task_ids'            => array(
91                'setup_newsletter',
92                'plan_selected',
93                'verify_email',
94                'migrate_content',
95                'subscribers_added',
96                'set_up_payments',
97                'newsletter_plan_created',
98                'first_post_published_newsletter',
99            ),
100            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
101        ),
102        'intent-newsletter-goal'  => array(
103            'get_title'           => function () {
104                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
105            },
106            'task_ids'            => array(
107                'verify_email',
108                'site_title',
109                'start_building_your_audience',
110                'customize_welcome_message',
111                'first_post_published',
112                'site_launched',
113            ),
114            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
115        ),
116        'create-course-goal'      => array(
117            'get_title'           => function () {
118                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
119            },
120            'task_ids'            => array(
121                'site_title',
122                'verify_email',
123                'domain_customize',
124                'site_launched',
125            ),
126            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
127        ),
128        'videopress'              => array(
129            'get_title'           => function () {
130                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
131            },
132            'task_ids'            => array(
133                'videopress_setup',
134                'plan_selected',
135                'videopress_upload',
136                'videopress_launched',
137            ),
138            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
139        ),
140        'write'                   => array(
141            'get_title'           => function () {
142                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
143            },
144            'task_ids'            => array(
145                'verify_email',
146                'site_title',
147                'start_building_your_audience',
148                'complete_profile',
149                'first_post_published',
150                'site_launched',
151            ),
152            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
153        ),
154        'design-first'            => array(
155            'get_title'           => function () {
156                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
157            },
158            'task_ids'            => array(
159                'design_completed',
160                'setup_blog',
161                'domain_upsell',
162                'plan_completed',
163                'first_post_published',
164                'blog_launched',
165            ),
166            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
167        ),
168        'intent-build'            => array(
169            'get_title'           => function () {
170                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
171            },
172            'task_ids'            => array(
173                'site_title',
174                'domain_claim',
175                'verify_email',
176                'domain_customize',
177                'add_new_page',
178                'drive_traffic',
179                'edit_page',
180                'share_site',
181                'update_about_page',
182            ),
183            'is_enabled_callback' => 'wpcom_launchpad_is_keep_building_enabled',
184        ),
185        'intent-write'            => array(
186            'get_title'           => function () {
187                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
188            },
189            'task_ids'            => array(
190                'site_title',
191                'domain_claim',
192                'verify_email',
193                'domain_customize',
194                'drive_traffic',
195                'write_3_posts',
196            ),
197            'is_enabled_callback' => 'wpcom_launchpad_is_intent_write_enabled',
198        ),
199        'intent-free-newsletter'  => array(
200            'get_title'           => function () {
201                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
202            },
203            'task_ids'            => array(
204                'enable_subscribers_modal',
205                'verify_email',
206                'migrate_content',
207                'subscribers_added',
208                'share_site',
209                'manage_subscribers',
210                'update_about_page',
211                'add_about_page',
212            ),
213            'is_enabled_callback' => 'wpcom_launchpad_is_free_newsletter_enabled',
214        ),
215        'intent-paid-newsletter'  => array(
216            'get_title'           => function () {
217                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
218            },
219            'task_ids'            => array(
220                'enable_subscribers_modal',
221                'verify_email',
222                'migrate_content',
223                'subscribers_added',
224                'share_site',
225                'set_up_payments',
226                'manage_subscribers',
227                'manage_paid_newsletter_plan',
228                'update_about_page',
229                'add_about_page',
230            ),
231            'is_enabled_callback' => 'wpcom_launchpad_is_paid_newsletter_enabled',
232        ),
233        'earn'                    => array(
234            'task_ids'            => array(
235                'stripe_connected',
236                'paid_offer_created',
237            ),
238            'is_enabled_callback' => '__return_true',
239        ),
240        'host-site'               => array(
241            'task_ids'            => array(
242                'site_theme_selected',
243                'install_custom_plugin',
244                'setup_ssh',
245                'verify_email',
246                'site_monitoring_page',
247                'site_launched',
248            ),
249            'is_enabled_callback' => 'wpcom_launchpad_is_hosting_flow_enabled',
250        ),
251        'subscribers'             => array(
252            'task_ids' => array(
253                'import_subscribers',
254                'add_subscribe_block',
255                'share_site',
256            ),
257        ),
258        'assembler-first'         => array(
259            'get_title'           => function () {
260                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
261            },
262            'task_ids'            => array(
263                'verify_domain_email',
264                'plan_completed',
265                'setup_free',
266                'design_selected',
267                'site_theme_selected',
268                'domain_upsell',
269                'first_post_published',
270                'site_launched',
271            ),
272            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
273        ),
274        'readymade-template'      => array(
275            'get_title'           => function () {
276                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
277            },
278            'task_ids'            => array(
279                'verify_domain_email',
280                'design_selected',
281                'setup_general',
282                'generate_content',
283                'plan_completed',
284                'site_theme_selected',
285                'domain_upsell',
286                'site_launched',
287            ),
288            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
289        ),
290        'ai-assembler'            => array(
291            'get_title'           => function () {
292                return __( 'Next steps for your site', 'jetpack-mu-wpcom' );
293            },
294            'task_ids'            => array(
295                'verify_domain_email',
296                'plan_completed',
297                'setup_free',
298                'design_selected',
299                'site_theme_selected',
300                'domain_upsell',
301                'site_launched',
302            ),
303            'is_enabled_callback' => 'wpcom_launchpad_get_fullscreen_enabled',
304        ),
305        'legacy-site-setup'       => array(
306            'get_title'      => function () {
307                return __( 'Site setup', 'jetpack-mu-wpcom' );
308            },
309            'is_dismissible' => true,
310            'task_ids'       => array(
311                'woocommerce_setup',
312                'sensei_setup',
313                'site_title',
314                'front_page_updated',
315                'verify_domain_email',
316                'verify_email',
317                'mobile_app_installed',
318                'post_sharing_enabled',
319                'site_launched',
320            ),
321        ),
322        'sell'                    => array(
323            'get_title'      => function () {
324                return __( 'Site setup', 'jetpack-mu-wpcom' );
325            },
326            'is_dismissible' => true,
327            'task_ids'       => array(
328                'woocommerce_setup',
329                'sensei_setup',
330                'site_title',
331                'front_page_updated',
332                'verify_domain_email',
333                'verify_email',
334                'mobile_app_installed',
335                'post_sharing_enabled',
336                'site_launched',
337            ),
338        ),
339        'entrepreneur-site-setup' => array(
340            'task_ids' => array(
341                'woo_customize_store',
342                'woo_products',
343                'woo_woocommerce_payments',
344                'woo_tax',
345                'woo_marketing',
346                'woo_add_domain',
347                'woo_launch_site',
348            ),
349        ),
350        'post-migration'          => array(
351            'get_title' => function () {
352                return __( 'Site migration', 'jetpack-mu-wpcom' );
353            },
354            'task_ids'  => array(
355                'migrating_site',
356                'review_site',
357                'review_plugins',
358                'connect_migration_domain',
359                'domain_dns_mapped',
360                'check_ssl_status',
361            ),
362        ),
363    );
364
365    $extended_task_list_definitions = apply_filters( 'wpcom_launchpad_extended_task_list_definitions', array() );
366
367    // As for tasks, we can decide what overrides we allow later.
368    return array_merge( $extended_task_list_definitions, $core_task_list_definitions );
369}
370
371/**
372 * Get a registered task list.
373 *
374 * @param string $checklist_slug The checklist slug to get the task list for.
375 *
376 * @return Task_List
377 */
378function wpcom_launchpad_get_task_list( $checklist_slug = null ) {
379    // If we don't have a checklist slug, fall back to the site intent option.
380    $checklist_slug = $checklist_slug ? $checklist_slug : get_option( 'site_intent' );
381    if ( ! $checklist_slug ) {
382        return array();
383    }
384
385    return wpcom_launchpad_checklists()->get_task_list( $checklist_slug );
386}
387
388/**
389 * Register all tasks and task lists from definitions
390 *
391 * @param bool $rebuild Whether to rebuild the task lists or not.
392 *
393 * @return Task_List[]
394 */
395function wpcom_launchpad_get_task_lists( $rebuild = false ) {
396    // If we already have task lists registered and we don't want to rebuild, return all task lists.
397    if ( ! $rebuild && wpcom_launchpad_checklists()->has_task_lists() ) {
398        return wpcom_launchpad_checklists()->get_all_task_lists();
399    }
400
401    $task_definitions = wpcom_launchpad_get_task_definitions();
402
403    // Register all tasks.
404    foreach ( $task_definitions as $task_id => $task_definition ) {
405        $task_data = array_merge( $task_definition, array( 'id' => $task_id ) );
406        wpcom_register_launchpad_task( $task_data );
407    }
408
409    $task_list_definitions = wpcom_launchpad_get_task_list_definitions();
410
411    // Register all task lists.
412    foreach ( $task_list_definitions as $task_list_id => $task_list_definition ) {
413        $task_list_data = array_merge( $task_list_definition, array( 'id' => $task_list_id ) );
414        wpcom_register_launchpad_task_list( $task_list_data );
415    }
416
417    // Assuming the reference is good, just return all checklists.
418    return wpcom_launchpad_checklists()->get_all_task_lists();
419}
420
421/**
422 * Register all tasks and task lists on init.
423 */
424function wpcom_register_default_launchpad_checklists() {
425    wpcom_launchpad_get_task_lists();
426    wpcom_add_active_task_listener_hooks_to_correct_action();
427}
428add_action( 'init', 'wpcom_register_default_launchpad_checklists', 11 );
429
430/**
431 * The site intents of retired onboarding flows.
432 *
433 * These no longer have a checklist, but sites created under them still carry
434 * the value, and clients still pass it to the launchpad endpoint as a checklist
435 * slug. The endpoint keeps accepting these so such a request degrades to an
436 * empty checklist rather than a 400. Empty this list once no site carries one.
437 *
438 * @return string[] Retired site intents.
439 */
440function wpcom_launchpad_get_retired_site_intents() {
441    return array( 'start-writing' );
442}
443
444/**
445 * Clears the site intent for a retired onboarding flow.
446 *
447 * A retired flow no longer accepts new sites, so the sites left on one sit in
448 * an onboarding they can never be guided through. Clearing the intent returns
449 * them to the same state as a site that never picked one: no Launchpad, and no
450 * onboarding email campaign.
451 *
452 * Writes once per site, since the intent stops matching afterwards. Delete this
453 * once no site carries one of these values.
454 */
455function wpcom_launchpad_clear_retired_site_intents() {
456    if ( ! in_array( get_option( 'site_intent' ), wpcom_launchpad_get_retired_site_intents(), true ) ) {
457        return;
458    }
459
460    update_option( 'site_intent', '' );
461    update_option( 'launchpad_screen', 'off' );
462}
463
464/**
465 * Clears the retired site intent once the target site's options are readable.
466 *
467 * On `public-api.wordpress.com`, `init` fires before the request switches to
468 * the blog, so reading `site_intent` there would read the wrong site.
469 *
470 * Runs ahead of the checklist registration, on both paths, so that the active
471 * task listeners are never registered for an intent that is about to be gone.
472 *
473 * @return void
474 */
475function wpcom_launchpad_clear_retired_site_intents_on_correct_action() {
476    if ( wp_parse_url( home_url(), PHP_URL_HOST ) === 'public-api.wordpress.com' ) {
477        add_action( 'rest_api_switched_to_blog', 'wpcom_launchpad_clear_retired_site_intents' );
478        return;
479    }
480
481    wpcom_launchpad_clear_retired_site_intents();
482}
483add_action( 'init', 'wpcom_launchpad_clear_retired_site_intents_on_correct_action', 10 );
484
485/**
486 * Adds hooks to the correct action to add active task listeners.
487 * Handles REST API requests vs non-REST API requests.
488 *
489 * @return null
490 */
491function wpcom_add_active_task_listener_hooks_to_correct_action() {
492    $url = wp_parse_url( home_url(), PHP_URL_HOST );
493    if ( $url === 'public-api.wordpress.com' ) {
494        return add_action( 'rest_api_switched_to_blog', 'wpcom_launchpad_add_active_task_listeners' );
495    }
496
497    // If we're not deferring to REST API blog switch, just run now
498    return wpcom_launchpad_add_active_task_listeners();
499}
500
501/**
502 * Adds task-defined `add_listener_callback` hooks for incomplete tasks.
503 *
504 * @return void
505 */
506function wpcom_launchpad_add_active_task_listeners() {
507    wpcom_launchpad_checklists()->add_hooks_for_active_tasks();
508}
509
510/**
511 * Determines whether or not design selected task is enabled
512 *
513 * @return boolean True if design selected task is enabled
514 */
515function wpcom_can_update_design_selected_task() {
516    $site_intent = get_option( 'site_intent' );
517    return $site_intent === 'free' || $site_intent === 'build' || $site_intent === 'write' || $site_intent === 'design-first';
518}
519
520/**
521 * Returns launchpad checklist task by task id.
522 *
523 * @param string $task_id Task id.
524 *
525 * @return array Associative array with task data
526 *               or false if task id is not found.
527 */
528function wpcom_is_checklist_task_complete( $task_id ) {
529    return wpcom_launchpad_checklists()->is_task_id_complete( $task_id );
530}
531
532/**
533 * Returns launchpad checklist by checklist slug.
534 *
535 * @param string      $checklist_slug Checklist slug.
536 * @param string|null $launchpad_context Optional. Screen where Launchpad is loading.
537 *
538 * @return Task[] Collection of tasks for a given checklist
539 */
540function wpcom_get_launchpad_checklist_by_checklist_slug( $checklist_slug, $launchpad_context = null ) {
541    if ( ! $checklist_slug ) {
542        return array();
543    }
544
545    return wpcom_launchpad_checklists()->build( $checklist_slug, $launchpad_context );
546}
547
548// TODO: Write code p2 post or dotcom post
549/**
550 * Wrapper that registers a launchpad checklist.
551 *
552 * @param Task_List $task_list Task list definition.
553 *
554 * @return bool True if successful, false otherwise.
555 */
556function wpcom_register_launchpad_task_list( $task_list ) {
557    return wpcom_launchpad_checklists()->register_task_list( $task_list );
558}
559
560/**
561 * Retrieves the required tasks from a given set of tasks.
562 *
563 * This function filters the provided tasks array and returns only the tasks that are marked as required,
564 * based on the specified array of required task IDs. It's worth noting that some tasks may not be
565 * visible to the user, so we are going to return all tasks that are marked as required, regardless
566 *
567 * @param array  $required_task_ids An array of task IDs that are considered required.
568 * @param Task[] $tasks An array of tasks to filter.
569 * @return array An array containing only the required tasks from the provided task list.
570 */
571function wpcom_launchpad_get_required_tasks( $required_task_ids, $tasks ) {
572    return array_filter(
573        $tasks,
574        function ( $task ) use ( $required_task_ids ) {
575            return in_array( $task['id'], $required_task_ids, true );
576        }
577    );
578}
579
580/**
581 * Get all tasks that are marked as launch tasks.
582 *
583 * @param Task[] $tasks Array of tasks.
584 * @return Task[] Array of launch tasks.
585 */
586function wpcom_launchpad_get_launch_tasks( $tasks ) {
587    return array_filter(
588        $tasks,
589        function ( $task ) {
590            if ( isset( $task['isLaunchTask'] ) ) {
591                return $task['isLaunchTask'];
592            }
593            return false;
594        }
595    );
596}
597
598/**
599 * Check if all the given tasks are completed.
600 *
601 * @param Task[] $tasks Array of tasks to check if they are completed.
602 * @return bool True if all tasks are completed, false otherwise.
603 */
604function wpcom_launchpad_are_all_tasks_completed( $tasks ) {
605    return array_reduce(
606        $tasks,
607        function ( $carry, $launch_task ) {
608            return $carry && $launch_task['completed'];
609        },
610        true
611    );
612}
613
614/**
615 * Determine the completion status of a task list based on its tasks.
616 *
617 * This function identifies any required tasks within the task list. If there are required tasks, the task list is considered complete
618 * only if all required tasks are completed. In the absence of required tasks, a secondary check is performed on tasks flagged with
619 * "isLaunchTask" to determine completion based on whether all of those tasks are complete. If there are no required tasks and no
620 * launch tasks, the task list's completion is determined by checking whether all tasks are complete. However, if there are incomplete
621 * tasks in this scenario, the completion status is based on whether the last task was completed. It is possible to control this behavior
622 * using a flag, as the default approach might be confusing for task lists where the steps may not be sequential. By default, the task
623 * list is marked as incomplete to align with most use cases that focus on user guidance and next steps rather than a specific end goal.
624 *
625 * @param Task_List $task_list Task list.
626 * @return bool True if the task list is considered complete, false otherwise.
627 */
628function wpcom_default_launchpad_task_list_completed( $task_list ) {
629    $task_list_id      = $task_list['id'];
630    $required_task_ids = wpcom_launchpad_checklists()->get_required_task_ids( $task_list_id );
631    $all_visible_tasks = wpcom_launchpad_checklists()->build( $task_list_id );
632
633    // If there are required tasks, check if they are all completed.
634    if ( ! empty( $required_task_ids ) ) {
635        $required_tasks = wpcom_launchpad_get_required_tasks( $required_task_ids, $all_visible_tasks );
636        return wpcom_launchpad_are_all_tasks_completed( $required_tasks );
637    }
638
639    // If there are no required tasks, check if there are any launch tasks.
640    $launch_tasks = wpcom_launchpad_get_launch_tasks( $all_visible_tasks );
641    if ( ! empty( $launch_tasks ) ) {
642        return wpcom_launchpad_are_all_tasks_completed( $launch_tasks );
643    }
644
645    // If there are no required tasks and no launch tasks, check if all tasks are completed.
646    if ( wpcom_launchpad_are_all_tasks_completed( $all_visible_tasks ) ) {
647        return true;
648    }
649
650    // If there are incomplete tasks, check if the last task was completed.
651    $require_last_task_completion = wpcom_launchpad_checklists()->get_require_last_task_completion( $task_list_id );
652    $last_task                    = end( $all_visible_tasks );
653    if ( $require_last_task_completion && $last_task['completed'] ) {
654        return true;
655    }
656
657    return false;
658}
659
660/**
661 * Callback to determine the completion status of a task list.
662 *
663 * @param string $task_list_id The task list ID.
664 * @return bool True if the task list is considered complete, false otherwise.
665 */
666function wpcom_launchpad_is_task_list_completed( $task_list_id ) {
667    return wpcom_launchpad_checklists()->is_task_list_completed( $task_list_id );
668}
669
670/**
671 * Wrapper that registers a launchpad checklist.
672 *
673 * @param Task $tasks Collection of Task definitions.
674 *
675 * @return bool True if successful, false otherwise.
676 */
677function wpcom_register_launchpad_tasks( $tasks ) {
678    return wpcom_launchpad_checklists()->register_tasks( $tasks );
679}
680
681/**
682 * Wrapper that registers a launchpad checklist.
683 *
684 * @param Task $task Task definition.
685 *
686 * @return bool True if successful, false otherwise.
687 */
688function wpcom_register_launchpad_task( $task ) {
689    return wpcom_launchpad_checklists()->register_task( $task );
690}
691
692/**
693 * Helper function to return a `Launchpad_Task_Lists` instance.
694 *
695 * @return object Launchpad_Task_Lists instance.
696 */
697function wpcom_launchpad_checklists() {
698    return Launchpad_Task_Lists::get_instance();
699}
700
701/**
702 * The `/rest/v1.1/video-uploads` endpoint operates without calling the `rest_api_switched_to_blog` hook.
703 * Which prevents our listeners from being added.
704 * This mimics the legacy mu-plugin logic of always adding the listener.
705 *
706 * @param int $post_id The attachment ID.
707 * @return void
708 */
709function wpcom_hacky_track_video_uploaded_task( $post_id ) {
710    if ( get_option( 'site_intent' ) !== 'videopress' ) {
711        return;
712    }
713    if ( get_option( 'launchpad_screen' ) !== 'full' ) {
714        return;
715    }
716    if ( has_action( 'add_attachment', 'wpcom_launchpad_track_video_uploaded_task' ) ) {
717        return;
718    }
719
720    wpcom_launchpad_track_video_uploaded_task( $post_id );
721}
722add_action( 'add_attachment', 'wpcom_hacky_track_video_uploaded_task' );
723
724//
725// Misc other Launchpad-related functionality below.
726//
727
728/**
729 * A filter for `get_option( 'launchpad_screen' )`
730 *
731 * @param mixed $value The filterable option value, retrieved from the DB.
732 * @return mixed       false if DIFM is active, the unaltered value otherwise.
733 */
734function wpcom_maybe_disable_for_difm( $value ) {
735    // If it's already false I don't care
736    if ( $value === false ) {
737        return $value;
738    }
739
740    // We want to disable for Built By Express aka DIFM, in case they've
741    // 1) Entered the Launchpad during signup, then 2) Purchased DIFM
742    if ( has_blog_sticker( 'difm-lite-in-progress' ) ) {
743        return false;
744    }
745    // Just in case, always return from a filter!
746    return $value;
747}
748// only WPCOM has blog stickers.
749if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
750    add_filter( 'option_launchpad_screen', 'wpcom_maybe_disable_for_difm' );
751}
752
753add_action( 'wp_head', 'wpcom_maybe_preview_with_no_interactions', PHP_INT_MAX );
754/**
755 * Add CSS that disallows interaction with the Launchpad preview.
756 *
757 * @return void|string
758 */
759function wpcom_maybe_preview_with_no_interactions() {
760    // phpcs:ignore
761    if ( empty( $_GET['do_preview_no_interactions'] ) || $_GET['do_preview_no_interactions'] !== 'true' ) {
762        return;
763    }
764
765    ?>
766        <style type="text/css">
767                body {
768                    pointer-events: none !important;
769                }
770        </style>
771    <?php
772}
773
774// Temporarily log information to debug intermittent launchpad errors for e2e tests
775if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
776    add_action( 'add_option_launchpad_screen', 'wpcom_log_launchpad_being_enabled_for_test_sites', 10, 2 );
777}
778
779/**
780 * Logs data when e2eflowtesting5.wordpress.com has launchpad enabled
781 *
782 * @param string $option The previous option value.
783 * @param string $value The new option value.
784 * @return void
785 */
786function wpcom_log_launchpad_being_enabled_for_test_sites( $option, $value ) {
787    // e2eflowtesting5.wordpress.com
788    if ( get_current_blog_id() !== 208860881 || $value !== 'full' ) {
789        return;
790    }
791
792    require_once WP_CONTENT_DIR . '/lib/log2logstash/log2logstash.php';
793    require_once WP_CONTENT_DIR . '/admin-plugins/wpcom-billing.php';
794    $current_plan = WPCOM_Store_API::get_current_plan( get_current_blog_id() );
795    $extra        = array(
796        'is_free'     => $current_plan['is_free'],
797        'site_intent' => get_option( 'site_intent' ),
798    );
799
800    log2logstash(
801        array(
802            'feature' => 'launchpad',
803            'message' => 'Launchpad enabled for e2e test site.',
804            'extra'   => wp_json_encode( $extra, JSON_UNESCAPED_SLASHES ),
805        )
806    );
807}
808
809/**
810 * Checks if the overall launchpad is enabled. Used with `is_enabled_callback`
811 * for backwards compatibility with established task lists
812 * that relied on the old `launchpad_screen` option.
813 *
814 * @return bool True if the launchpad is enabled, false otherwise.
815 */
816function wpcom_launchpad_get_fullscreen_enabled() {
817    return wpcom_launchpad_checklists()->is_fullscreen_launchpad_enabled();
818}
819
820/**
821 * Checks if a specific launchpad task list is enabled.
822 *
823 * @param string $checklist_slug The slug of the launchpad task list to check.
824 * @return bool True if the task list is enabled, false otherwise.
825 */
826function wpcom_get_launchpad_task_list_is_enabled( $checklist_slug ) {
827    if ( false !== $checklist_slug ) {
828        return wpcom_launchpad_checklists()->is_task_list_enabled( $checklist_slug );
829    }
830
831    return false;
832}
833
834/**
835 * Checks if a specific task list is dismissed.
836 *
837 * @param string $checklist_slug The slug of the launchpad task list to check.
838 * @return bool True if the task list is dismissed, false otherwise.
839 */
840function wpcom_launchpad_is_task_list_dismissed( $checklist_slug ) {
841    return wpcom_launchpad_checklists()->is_task_list_dismissed( $checklist_slug );
842}
843
844/**
845 * Checks if the Launchpad is dismissible.
846 *
847 * @param string $checklist_slug The slug of the launchpad task list to check.
848 * @return bool True if the Launchpad is dismissible, false otherwise.
849 */
850function wpcom_launchpad_is_task_list_dismissible( $checklist_slug ) {
851    if ( false === $checklist_slug ) {
852        return false;
853    }
854    return wpcom_launchpad_checklists()->is_task_list_dismissible( $checklist_slug );
855}
856
857/**
858 * Returns the the temporary dismissed timestamps for a specific task list.
859 *
860 * @param string $checklist_slug The slug of the launchpad task list to check.
861 * @return int The timestamp until which the task list is dismissed.
862 */
863function wpcom_launchpad_task_list_dismissed_until( $checklist_slug ) {
864    return wpcom_launchpad_checklists()->get_task_list_dismissed_until( $checklist_slug );
865}
866
867/**
868 * Sets a specific task list dismissed state.
869 *
870 * @param string        $checklist_slug The slug of the launchpad task list to check.
871 * @param bool          $is_dismissed True if the task list is dismissed, false otherwise.
872 * @param string | null $dismissed_until The date until which the task list is dismissed.
873 */
874function wpcom_launchpad_set_task_list_dismissed( $checklist_slug, $is_dismissed, $dismissed_until ) {
875
876    if ( isset( $dismissed_until ) ) {
877        wpcom_launchpad_checklists()->set_task_list_dismissed_until( $checklist_slug, $dismissed_until );
878    } else {
879        wpcom_launchpad_checklists()->set_task_list_dismissed( $checklist_slug, $is_dismissed );
880    }
881}
882
883/**
884 * Helper function to indicate whether the Next Steps modal in
885 * the Full Site Editor should be hidden.
886 *
887 * @return bool
888 */
889function wpcom_launchpad_is_fse_next_steps_modal_hidden() {
890    $wpcom_launchpad_config = get_option( 'wpcom_launchpad_config' );
891
892    if ( ! $wpcom_launchpad_config || ! is_array( $wpcom_launchpad_config ) ) {
893        return false;
894    }
895
896    if ( ! isset( $wpcom_launchpad_config['hide_fse_next_steps_modal'] ) ) {
897        return false;
898    }
899
900    return true === $wpcom_launchpad_config['hide_fse_next_steps_modal'];
901}
902
903/**
904 * Helper function to hide and show the Next Steps modal we show in the
905 * Full Site Editor.
906 *
907 * @param bool $should_hide Should the modal be hidden (true) or displayed (false).
908 * @return bool Whether the option update succeeded.
909 */
910function wpcom_launchpad_set_fse_next_steps_modal_hidden( $should_hide ) {
911    $wpcom_launchpad_config = get_option( 'wpcom_launchpad_config' );
912
913    // If we want to show the modal, we don't need to do anything if either the main
914    // wpcom_launchpad_config option OR the hide sub-option aren't set.
915    if ( ! $should_hide ) {
916        if ( ! $wpcom_launchpad_config || ! is_array( $wpcom_launchpad_config ) ) {
917            return true;
918        }
919
920        if ( ! isset( $wpcom_launchpad_config['hide_fse_next_steps_modal'] ) ) {
921            return true;
922        }
923
924        unset( $wpcom_launchpad_config['hide_fse_next_steps_modal'] );
925    } else {
926        // Make sure we have an array for the main option.
927        if ( ! $wpcom_launchpad_config || ! is_array( $wpcom_launchpad_config ) ) {
928            $wpcom_launchpad_config = array();
929        }
930
931        // If we already have the option set, we can return early.
932        if ( isset( $wpcom_launchpad_config['hide_fse_next_steps_modal'] ) && true === $wpcom_launchpad_config['hide_fse_next_steps_modal'] ) {
933            return true;
934        }
935
936        $wpcom_launchpad_config['hide_fse_next_steps_modal'] = true;
937    }
938
939    if ( empty( $wpcom_launchpad_config ) ) {
940        return delete_option( 'wpcom_launchpad_config' );
941    }
942
943    return update_option( 'wpcom_launchpad_config', $wpcom_launchpad_config );
944}
945
946/**
947 * Returns a list of all the checklists that are currently available for the navigator.
948 *
949 * @return array Array of strings representing the checklist slugs.
950 */
951function wpcom_launchpad_navigator_get_checklists() {
952    $wpcom_launchpad_config = get_option( 'wpcom_launchpad_config', array() );
953
954    if ( ! isset( $wpcom_launchpad_config['navigator_checklists'] ) ) {
955        return array();
956    }
957    $all_checklists  = wpcom_launchpad_checklists()->get_all_task_lists();
958    $checklist_slugs = $wpcom_launchpad_config['navigator_checklists'];
959
960    $results = array();
961    foreach ( $checklist_slugs as $slug ) {
962        if ( ! isset( $all_checklists[ $slug ] ) ) {
963            continue;
964        }
965
966        $results[ $slug ] = array(
967            'slug'  => $slug,
968            'title' => $all_checklists[ $slug ]['title'],
969        );
970    }
971
972    return $results;
973}
974
975/**
976 * Updates the list of checklists that are currently available for the navigator.
977 *
978 * @param array $new_checklists Array of strings representing the checklist slugs.
979 * @return bool Whether the option update succeeded.
980 */
981function wpcom_launchpad_navigator_update_checklists( $new_checklists ) {
982    if ( ! is_array( $new_checklists ) ) {
983        return false;
984    }
985
986    $wpcom_launchpad_config = get_option( 'wpcom_launchpad_config', array() );
987
988    $wpcom_launchpad_config['navigator_checklists'] = $new_checklists;
989
990    return update_option( 'wpcom_launchpad_config', $wpcom_launchpad_config );
991}
992
993/**
994 * Removes a checklist from the list of checklists that are currently available for the navigator.
995 *
996 * @param string $checklist_slug The slug of the checklist to remove.
997 * @return array Array with two values: whether the option update succeeded, and the new active checklist slug.
998 */
999function wpcom_launchpad_navigator_remove_checklist( $checklist_slug ) {
1000    $wpcom_launchpad_config = get_option( 'wpcom_launchpad_config', array() );
1001
1002    if ( ! isset( $wpcom_launchpad_config['navigator_checklists'] ) ) {
1003        return array(
1004            'updated'              => false,
1005            'new_active_checklist' => null,
1006        );
1007    }
1008
1009    $current_active_checklist = wpcom_launchpad_get_active_checklist();
1010
1011    $checklists = $wpcom_launchpad_config['navigator_checklists'];
1012    // Find if $checklist_slug is in the checklists array. If it is, remove it.
1013    $key = array_search( $checklist_slug, $checklists, true );
1014    if ( $key === false ) {
1015        return array(
1016            'updated'              => false,
1017            'new_active_checklist' => $current_active_checklist,
1018        );
1019    }
1020
1021    unset( $checklists[ $key ] );
1022
1023    $new_active_checklist = $current_active_checklist;
1024    if ( $current_active_checklist === $checklist_slug ) {
1025        // get last item on $checklists array, if there is one; otherwise set to null
1026        $new_active_checklist = end( $checklists ) ? end( $checklists ) : null;
1027        wpcom_launchpad_set_current_active_checklist( $new_active_checklist );
1028    }
1029
1030    return array(
1031        'updated'              => wpcom_launchpad_navigator_update_checklists( $checklists ),
1032        'new_active_checklist' => $new_active_checklist,
1033    );
1034}
1035
1036/**
1037 * Adds a new checklist to the list of checklists that are currently available for the navigator.
1038 *
1039 * @param string $new_checklist_slug The slug of the launchpad task list to add.
1040 */
1041function wpcom_launchpad_navigator_add_checklist( $new_checklist_slug ) {
1042    $wpcom_launchpad_config = get_option( 'wpcom_launchpad_config', array() );
1043    $checklists             = array();
1044
1045    if ( isset( $wpcom_launchpad_config['navigator_checklists'] ) ) {
1046        $checklists = $wpcom_launchpad_config['navigator_checklists'];
1047    }
1048
1049    // add the new_checklist_slug to the checklists array if it's not already there.
1050    if ( ! in_array( $new_checklist_slug, $checklists, true ) ) {
1051        $checklists[] = $new_checklist_slug;
1052    }
1053
1054    wpcom_launchpad_navigator_update_checklists( $checklists );
1055}
1056
1057/**
1058 * Helper function to indicate what's the current active checklist
1059 * in the context of the navigator.
1060 * It will try to read the key 'active_checklist_slug' from the 'wpcom_launchpad_config' option.
1061 *
1062 * @return string|null The active checklist slug, null if none is set.
1063 */
1064function wpcom_launchpad_get_active_checklist() {
1065    $wpcom_launchpad_config = get_option( 'wpcom_launchpad_config' );
1066
1067    if ( ! $wpcom_launchpad_config || ! is_array( $wpcom_launchpad_config ) ) {
1068        return null;
1069    }
1070
1071    if ( ! isset( $wpcom_launchpad_config['active_checklist_slug'] ) ) {
1072        return null;
1073    }
1074
1075    $active_checklist_slug = $wpcom_launchpad_config['active_checklist_slug'];
1076
1077    // A retired checklist can linger here from before it was unregistered. Treat it
1078    // as unset, matching how the available list drops unregistered slugs and how the
1079    // setter refuses them, so the Navigator never reports a checklist that is gone.
1080    if ( ! array_key_exists( $active_checklist_slug, wpcom_launchpad_checklists()->get_all_task_lists() ) ) {
1081        return null;
1082    }
1083
1084    return $active_checklist_slug;
1085}
1086
1087/**
1088 * Helper function to set the current active checklist in the navigator context.
1089 *
1090 * @param string $checklist_slug The slug of the launchpad task list to mark as active.
1091 * @return bool Whether the option update succeeded.
1092 */
1093function wpcom_launchpad_set_current_active_checklist( $checklist_slug ) {
1094    $wpcom_launchpad_config = get_option( 'wpcom_launchpad_config' );
1095
1096    if ( null !== $checklist_slug ) {
1097        $checklists = wpcom_launchpad_checklists()->get_all_task_lists();
1098        if ( ! array_key_exists( $checklist_slug, $checklists ) ) {
1099            return false;
1100        }
1101    }
1102
1103    if ( ! $wpcom_launchpad_config || ! is_array( $wpcom_launchpad_config ) ) {
1104        $wpcom_launchpad_config = array();
1105    }
1106
1107    if ( null === $checklist_slug ) {
1108        if ( ! isset( $wpcom_launchpad_config['active_checklist_slug'] ) ) {
1109            return true;
1110        }
1111        unset( $wpcom_launchpad_config['active_checklist_slug'] );
1112    } else {
1113        if ( isset( $wpcom_launchpad_config['active_checklist_slug'] ) && $checklist_slug === $wpcom_launchpad_config['active_checklist_slug'] ) {
1114            return true;
1115        }
1116        $wpcom_launchpad_config['active_checklist_slug'] = $checklist_slug;
1117    }
1118
1119    $return_value = update_option( 'wpcom_launchpad_config', $wpcom_launchpad_config );
1120    // add to available checklists if not null
1121    if ( $checklist_slug !== null ) {
1122        wpcom_launchpad_navigator_add_checklist( $checklist_slug );
1123    }
1124
1125    return $return_value;
1126}
1127
1128/**
1129 * Checks if the Keep building task list is enabled.
1130 *
1131 * @return bool True if the task list is enabled, false otherwise.
1132 */
1133function wpcom_launchpad_is_keep_building_enabled() {
1134    $intent  = get_option( 'site_intent', false );
1135    $blog_id = get_current_blog_id();
1136
1137    if ( 'build' === $intent && $blog_id > 220443356 ) {
1138        return true;
1139    }
1140
1141    return false;
1142}
1143
1144/**
1145 * Checks if the hosting flow task list is enabled.
1146 *
1147 * @return bool True if the task list is enabled, false otherwise.
1148 */
1149function wpcom_launchpad_is_hosting_flow_enabled() {
1150    return apply_filters( 'is_launchpad_intent_hosting_enabled', false );
1151}
1152
1153/**
1154 * Checks if the Blog flow task list is enabled.
1155 *
1156 * @return bool True if the task list is enabled, false otherwise.
1157 */
1158function wpcom_launchpad_is_intent_write_enabled() {
1159    return apply_filters( 'is_launchpad_intent_write_enabled', false );
1160}
1161
1162/**
1163 * Checks if the Free Newsletter flow task list is enabled.
1164 *
1165 * @return bool True if the task list is enabled, false otherwise.
1166 */
1167function wpcom_launchpad_is_free_newsletter_enabled() {
1168    $intent = get_option( 'site_intent', false );
1169    if ( 'newsletter' !== $intent ) {
1170        return false;
1171    }
1172
1173    return ! wpcom_launchpad_has_goal_paid_subscribers() && apply_filters( 'wpcom_launchpad_intent_free_newsletter_enabled', false );
1174}
1175
1176/**
1177 * Checks if the Paid Newsletter flow task list is enabled.
1178 *
1179 * @return bool True if the task list is enabled, false otherwise.
1180 */
1181function wpcom_launchpad_is_paid_newsletter_enabled() {
1182    $intent = get_option( 'site_intent', false );
1183    if ( 'newsletter' !== $intent ) {
1184        return false;
1185    }
1186
1187    return wpcom_launchpad_has_goal_paid_subscribers() && apply_filters( 'wpcom_launchpad_intent_paid_newsletter_enabled', false );
1188}
1189
1190/**
1191 * Checks if the Newsletter goal flow task list is enabled.
1192 *
1193 * @return bool True if the task list is enabled, false otherwise.
1194 */
1195function wpcom_launchpad_is_newsletter_goal_enabled() {
1196    $intent = get_option( 'site_intent', false );
1197    if ( 'intent-newsletter-goal' !== $intent ) {
1198        return false;
1199    }
1200
1201    return apply_filters( 'wpcom_launchpad_intent_newsletter_goal_enabled', false );
1202}
1203/**
1204 * Add launchpad options to Jetpack Sync.
1205 *
1206 * @param array $allowed_options The allowed options.
1207 */
1208function add_launchpad_options_to_jetpack_sync( $allowed_options ) {
1209    // We are not either in Simple or Atomic
1210    if ( ! class_exists( 'Automattic\Jetpack\Status\Host' ) ) {
1211        return $allowed_options;
1212    }
1213
1214    if ( ! ( new Automattic\Jetpack\Status\Host() )->is_woa_site() ) {
1215        return $allowed_options;
1216    }
1217
1218    if ( ! is_array( $allowed_options ) ) {
1219        return $allowed_options;
1220    }
1221
1222    $launchpad_options = array(
1223        'site_intent',
1224        'launchpad_checklist_tasks_statuses',
1225        'site_goals',
1226        'sm_enabled',
1227    );
1228
1229    return array_merge( $allowed_options, $launchpad_options );
1230}
1231add_filter( 'jetpack_sync_options_whitelist', 'add_launchpad_options_to_jetpack_sync', 10, 1 );
1232
1233/**
1234 * Get the title of a checklist by its slug.
1235 *
1236 * @param string $checklist_slug The slug of the checklist.
1237 * @return string The title of the checklist.
1238 */
1239function wpcom_get_launchpad_checklist_title_by_checklist_slug( $checklist_slug ) {
1240    if ( ! $checklist_slug ) {
1241        return array();
1242    }
1243
1244    return wpcom_launchpad_checklists()->get_task_list_title( $checklist_slug );
1245}
1246
1247/**
1248 * Gets a launchpad config option.
1249 *
1250 * @param string $option The option to get.
1251 * @param mixed  $default The default value to return if the option is not set.
1252 */
1253function wpcom_get_launchpad_config_option( $option, $default = null ) {
1254    $wpcom_launchpad_config = get_option( 'wpcom_launchpad_config', array() );
1255
1256    if ( ! is_array( $wpcom_launchpad_config ) || ! isset( $wpcom_launchpad_config[ $option ] ) ) {
1257        return $default;
1258    }
1259
1260    return $wpcom_launchpad_config[ $option ];
1261}
1262
1263/**
1264 * Sets a launchpad config option.
1265 *
1266 * @param string $option The option to set.
1267 * @param mixed  $value The value to set.
1268 */
1269function wpcom_set_launchpad_config_option( $option, $value ) {
1270    $wpcom_launchpad_config = get_option( 'wpcom_launchpad_config', array() );
1271
1272    $wpcom_launchpad_config[ $option ] = $value;
1273
1274    return update_option( 'wpcom_launchpad_config', $wpcom_launchpad_config );
1275}