Edit File by line
/home/zeestwma/richards.../wp-conte.../plugins/woocomme.../src/Admin/Features
File: LaunchYourStore.php
<?php declare( strict_types = 1 );
[0] Fix | Delete
[1] Fix | Delete
namespace Automattic\WooCommerce\Admin\Features;
[2] Fix | Delete
[3] Fix | Delete
use Automattic\WooCommerce\Admin\PluginsHelper;
[4] Fix | Delete
use Automattic\WooCommerce\Admin\WCAdminHelper;
[5] Fix | Delete
use Automattic\WooCommerce\Internal\Admin\WCAdminUser;
[6] Fix | Delete
[7] Fix | Delete
[8] Fix | Delete
/**
[9] Fix | Delete
* Takes care of Launch Your Store related actions.
[10] Fix | Delete
*/
[11] Fix | Delete
class LaunchYourStore {
[12] Fix | Delete
const BANNER_DISMISS_USER_META_KEY = 'coming_soon_banner_dismissed';
[13] Fix | Delete
/**
[14] Fix | Delete
* Constructor.
[15] Fix | Delete
*/
[16] Fix | Delete
public function __construct() {
[17] Fix | Delete
add_action( 'woocommerce_update_options_site-visibility', array( $this, 'save_site_visibility_options' ) );
[18] Fix | Delete
add_filter( 'woocommerce_admin_shared_settings', array( $this, 'preload_settings' ) );
[19] Fix | Delete
add_action( 'wp_footer', array( $this, 'maybe_add_coming_soon_banner_on_frontend' ) );
[20] Fix | Delete
add_action( 'init', array( $this, 'register_launch_your_store_user_meta_fields' ) );
[21] Fix | Delete
add_filter( 'woocommerce_tracks_event_properties', array( $this, 'append_coming_soon_global_tracks' ), 10, 2 );
[22] Fix | Delete
add_action( 'wp_login', array( $this, 'reset_woocommerce_coming_soon_banner_dismissed' ), 10, 2 );
[23] Fix | Delete
add_filter( 'woocommerce_admin_get_user_data_fields', array( $this, 'add_user_data_fields' ) );
[24] Fix | Delete
if ( Features::is_enabled( 'coming-soon-newsletter-template' ) ) {
[25] Fix | Delete
add_action( 'admin_enqueue_scripts', array( $this, 'load_newsletter_scripts' ) );
[26] Fix | Delete
add_action( 'save_post_wp_template', array( $this, 'maybe_track_template_change' ), 10, 3 );
[27] Fix | Delete
}
[28] Fix | Delete
}
[29] Fix | Delete
[30] Fix | Delete
/**
[31] Fix | Delete
* Save values submitted from WooCommerce -> Settings -> General.
[32] Fix | Delete
*
[33] Fix | Delete
* @return void
[34] Fix | Delete
*/
[35] Fix | Delete
public function save_site_visibility_options() {
[36] Fix | Delete
$nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : '';
[37] Fix | Delete
// New Settings API uses wp_rest nonce.
[38] Fix | Delete
$nonce_string = Features::is_enabled( 'settings' ) ? 'wp_rest' : 'woocommerce-settings';
[39] Fix | Delete
if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, $nonce_string ) ) {
[40] Fix | Delete
return;
[41] Fix | Delete
}
[42] Fix | Delete
[43] Fix | Delete
// options to allowed update and their allowed values.
[44] Fix | Delete
$options = array(
[45] Fix | Delete
'woocommerce_coming_soon' => array( 'yes', 'no' ),
[46] Fix | Delete
'woocommerce_store_pages_only' => array( 'yes', 'no' ),
[47] Fix | Delete
'woocommerce_private_link' => array( 'yes', 'no' ),
[48] Fix | Delete
);
[49] Fix | Delete
[50] Fix | Delete
$event_data = array();
[51] Fix | Delete
[52] Fix | Delete
foreach ( $options as $name => $allowed_values ) {
[53] Fix | Delete
$current_value = get_option( $name, 'not set' );
[54] Fix | Delete
$new_value = $current_value;
[55] Fix | Delete
[56] Fix | Delete
if ( isset( $_POST[ $name ] ) ) {
[57] Fix | Delete
$input_value = sanitize_text_field( wp_unslash( $_POST[ $name ] ) );
[58] Fix | Delete
[59] Fix | Delete
// no-op if input value is invalid.
[60] Fix | Delete
if ( in_array( $input_value, $allowed_values, true ) ) {
[61] Fix | Delete
update_option( $name, $input_value );
[62] Fix | Delete
$new_value = $input_value;
[63] Fix | Delete
[64] Fix | Delete
// log the transition if there is one.
[65] Fix | Delete
if ( $current_value !== $new_value ) {
[66] Fix | Delete
$enabled_or_disabled = 'yes' === $new_value ? 'enabled' : 'disabled';
[67] Fix | Delete
$event_data[ $name . '_toggled' ] = $enabled_or_disabled;
[68] Fix | Delete
}
[69] Fix | Delete
}
[70] Fix | Delete
}
[71] Fix | Delete
$event_data[ $name ] = $new_value;
[72] Fix | Delete
}
[73] Fix | Delete
wc_admin_record_tracks_event( 'site_visibility_saved', $event_data );
[74] Fix | Delete
}
[75] Fix | Delete
[76] Fix | Delete
/**
[77] Fix | Delete
* Append coming soon prop tracks globally.
[78] Fix | Delete
*
[79] Fix | Delete
* @param array $event_properties Event properties array.
[80] Fix | Delete
*
[81] Fix | Delete
* @return array
[82] Fix | Delete
*/
[83] Fix | Delete
public function append_coming_soon_global_tracks( $event_properties ) {
[84] Fix | Delete
if ( is_array( $event_properties ) ) {
[85] Fix | Delete
$coming_soon = 'no';
[86] Fix | Delete
if ( 'yes' === get_option( 'woocommerce_coming_soon', 'no' ) ) {
[87] Fix | Delete
if ( 'yes' === get_option( 'woocommerce_store_pages_only', 'no' ) ) {
[88] Fix | Delete
$coming_soon = 'store';
[89] Fix | Delete
} else {
[90] Fix | Delete
$coming_soon = 'site';
[91] Fix | Delete
}
[92] Fix | Delete
}
[93] Fix | Delete
$event_properties['coming_soon'] = $coming_soon;
[94] Fix | Delete
}
[95] Fix | Delete
return $event_properties;
[96] Fix | Delete
}
[97] Fix | Delete
[98] Fix | Delete
[99] Fix | Delete
/**
[100] Fix | Delete
* Preload settings for Site Visibility.
[101] Fix | Delete
*
[102] Fix | Delete
* @param array $settings settings array.
[103] Fix | Delete
*
[104] Fix | Delete
* @return mixed
[105] Fix | Delete
*/
[106] Fix | Delete
public function preload_settings( $settings ) {
[107] Fix | Delete
if ( ! is_admin() ) {
[108] Fix | Delete
return $settings;
[109] Fix | Delete
}
[110] Fix | Delete
[111] Fix | Delete
$current_screen = get_current_screen();
[112] Fix | Delete
$is_setting_page = $current_screen && 'woocommerce_page_wc-settings' === $current_screen->id;
[113] Fix | Delete
[114] Fix | Delete
// phpcs:disable WordPress.Security.NonceVerification.Recommended
[115] Fix | Delete
$is_woopayments_connect = isset( $_GET['path'] ) &&
[116] Fix | Delete
isset( $_GET['page'] ) &&
[117] Fix | Delete
( '/payments/connect' === sanitize_text_field( wp_unslash( $_GET['path'] ) ) || '/payments/onboarding' === sanitize_text_field( wp_unslash( $_GET['path'] ) ) ) &&
[118] Fix | Delete
'wc-admin' === $_GET['page'];
[119] Fix | Delete
// phpcs:enable
[120] Fix | Delete
[121] Fix | Delete
if ( $is_setting_page || $is_woopayments_connect ) {
[122] Fix | Delete
// Regnerate the share key if it's not set.
[123] Fix | Delete
add_option( 'woocommerce_share_key', wp_generate_password( 32, false ) );
[124] Fix | Delete
[125] Fix | Delete
$settings['siteVisibilitySettings'] = array(
[126] Fix | Delete
'shop_permalink' => get_permalink( wc_get_page_id( 'shop' ) ),
[127] Fix | Delete
'woocommerce_coming_soon' => get_option( 'woocommerce_coming_soon' ),
[128] Fix | Delete
'woocommerce_store_pages_only' => get_option( 'woocommerce_store_pages_only' ),
[129] Fix | Delete
'woocommerce_private_link' => get_option( 'woocommerce_private_link' ),
[130] Fix | Delete
'woocommerce_share_key' => get_option( 'woocommerce_share_key' ),
[131] Fix | Delete
);
[132] Fix | Delete
}
[133] Fix | Delete
[134] Fix | Delete
return $settings;
[135] Fix | Delete
}
[136] Fix | Delete
[137] Fix | Delete
/**
[138] Fix | Delete
* User must be an admin or editor.
[139] Fix | Delete
*
[140] Fix | Delete
* @return bool
[141] Fix | Delete
*/
[142] Fix | Delete
private function is_manager_or_admin() {
[143] Fix | Delete
// phpcs:ignore
[144] Fix | Delete
if ( ! current_user_can( 'shop_manager' ) && ! current_user_can( 'administrator' ) ) {
[145] Fix | Delete
return false;
[146] Fix | Delete
}
[147] Fix | Delete
[148] Fix | Delete
return true;
[149] Fix | Delete
}
[150] Fix | Delete
[151] Fix | Delete
/**
[152] Fix | Delete
* Add 'coming soon' banner on the frontend when the following conditions met.
[153] Fix | Delete
*
[154] Fix | Delete
* - User must be either an admin or store editor (must be logged in).
[155] Fix | Delete
* - 'woocommerce_coming_soon' option value must be 'yes'
[156] Fix | Delete
* - The page must not be the Coming soon page itself.
[157] Fix | Delete
*/
[158] Fix | Delete
public function maybe_add_coming_soon_banner_on_frontend() {
[159] Fix | Delete
// Do not show the banner if the site is being previewed.
[160] Fix | Delete
if ( isset( $_GET['site-preview'] ) ) { // @phpcs:ignore
[161] Fix | Delete
return false;
[162] Fix | Delete
}
[163] Fix | Delete
[164] Fix | Delete
$current_user_id = get_current_user_id();
[165] Fix | Delete
if ( ! $current_user_id ) {
[166] Fix | Delete
return false;
[167] Fix | Delete
}
[168] Fix | Delete
[169] Fix | Delete
$has_dismissed_banner = WCAdminUser::get_user_data_field( $current_user_id, self::BANNER_DISMISS_USER_META_KEY )
[170] Fix | Delete
// Remove this check in WC 9.4.
[171] Fix | Delete
|| get_user_meta( $current_user_id, 'woocommerce_' . self::BANNER_DISMISS_USER_META_KEY, true ) === 'yes';
[172] Fix | Delete
if ( $has_dismissed_banner ) {
[173] Fix | Delete
return false;
[174] Fix | Delete
}
[175] Fix | Delete
[176] Fix | Delete
if ( ! $this->is_manager_or_admin() ) {
[177] Fix | Delete
return false;
[178] Fix | Delete
}
[179] Fix | Delete
[180] Fix | Delete
// 'woocommerce_coming_soon' must be 'yes'
[181] Fix | Delete
if ( get_option( 'woocommerce_coming_soon', 'no' ) !== 'yes' ) {
[182] Fix | Delete
return false;
[183] Fix | Delete
}
[184] Fix | Delete
[185] Fix | Delete
$store_pages_only = get_option( 'woocommerce_store_pages_only' ) === 'yes';
[186] Fix | Delete
if ( $store_pages_only && ! WCAdminHelper::is_current_page_store_page() ) {
[187] Fix | Delete
return false;
[188] Fix | Delete
}
[189] Fix | Delete
[190] Fix | Delete
$link = admin_url( 'admin.php?page=wc-settings&tab=site-visibility' );
[191] Fix | Delete
$rest_url = rest_url( 'wp/v2/users/' . $current_user_id );
[192] Fix | Delete
$rest_nonce = wp_create_nonce( 'wp_rest' );
[193] Fix | Delete
[194] Fix | Delete
$text = sprintf(
[195] Fix | Delete
// translators: no need to translate it. It's a link.
[196] Fix | Delete
__(
[197] Fix | Delete
"
[198] Fix | Delete
This page is in \"Coming soon\" mode and is only visible to you and those who have permission. To make it public to everyone,&nbsp;<a href='%s'>change visibility settings</a>
[199] Fix | Delete
",
[200] Fix | Delete
'woocommerce'
[201] Fix | Delete
),
[202] Fix | Delete
$link
[203] Fix | Delete
);
[204] Fix | Delete
// phpcs:ignore
[205] Fix | Delete
echo "<div id='coming-soon-footer-banner'><div class='coming-soon-footer-banner__content'>$text</div><a class='coming-soon-footer-banner-dismiss' data-rest-url='$rest_url' data-rest-nonce='$rest_nonce'></a></div>";
[206] Fix | Delete
}
[207] Fix | Delete
[208] Fix | Delete
/**
[209] Fix | Delete
* Register user meta fields for Launch Your Store.
[210] Fix | Delete
*
[211] Fix | Delete
* This should be removed in WC 9.4.
[212] Fix | Delete
*/
[213] Fix | Delete
public function register_launch_your_store_user_meta_fields() {
[214] Fix | Delete
if ( ! $this->is_manager_or_admin() ) {
[215] Fix | Delete
return;
[216] Fix | Delete
}
[217] Fix | Delete
[218] Fix | Delete
register_meta(
[219] Fix | Delete
'user',
[220] Fix | Delete
'woocommerce_launch_your_store_tour_hidden',
[221] Fix | Delete
array(
[222] Fix | Delete
'type' => 'string',
[223] Fix | Delete
'description' => 'Indicate whether the user has dismissed the site visibility tour on the home screen.',
[224] Fix | Delete
'single' => true,
[225] Fix | Delete
'show_in_rest' => true,
[226] Fix | Delete
)
[227] Fix | Delete
);
[228] Fix | Delete
[229] Fix | Delete
register_meta(
[230] Fix | Delete
'user',
[231] Fix | Delete
'woocommerce_coming_soon_banner_dismissed',
[232] Fix | Delete
array(
[233] Fix | Delete
'type' => 'string',
[234] Fix | Delete
'description' => 'Indicate whether the user has dismissed the coming soon notice or not.',
[235] Fix | Delete
'single' => true,
[236] Fix | Delete
'show_in_rest' => true,
[237] Fix | Delete
)
[238] Fix | Delete
);
[239] Fix | Delete
}
[240] Fix | Delete
[241] Fix | Delete
/**
[242] Fix | Delete
* Register user meta fields for Launch Your Store.
[243] Fix | Delete
*
[244] Fix | Delete
* @param array $user_data_fields user data fields.
[245] Fix | Delete
* @return array
[246] Fix | Delete
*/
[247] Fix | Delete
public function add_user_data_fields( $user_data_fields ) {
[248] Fix | Delete
return array_merge(
[249] Fix | Delete
$user_data_fields,
[250] Fix | Delete
array(
[251] Fix | Delete
'launch_your_store_tour_hidden',
[252] Fix | Delete
self::BANNER_DISMISS_USER_META_KEY,
[253] Fix | Delete
)
[254] Fix | Delete
);
[255] Fix | Delete
}
[256] Fix | Delete
[257] Fix | Delete
/**
[258] Fix | Delete
* Reset 'woocommerce_coming_soon_banner_dismissed' user meta to 'no'.
[259] Fix | Delete
*
[260] Fix | Delete
* Runs when a user logs-in successfully.
[261] Fix | Delete
*
[262] Fix | Delete
* @param string $user_login user login.
[263] Fix | Delete
* @param object $user user object.
[264] Fix | Delete
*/
[265] Fix | Delete
public function reset_woocommerce_coming_soon_banner_dismissed( $user_login, $user ) {
[266] Fix | Delete
$existing_meta = WCAdminUser::get_user_data_field( $user->ID, self::BANNER_DISMISS_USER_META_KEY );
[267] Fix | Delete
if ( 'yes' === $existing_meta ) {
[268] Fix | Delete
WCAdminUser::update_user_data_field( $user->ID, self::BANNER_DISMISS_USER_META_KEY, 'no' );
[269] Fix | Delete
}
[270] Fix | Delete
}
[271] Fix | Delete
[272] Fix | Delete
/**
[273] Fix | Delete
* Check if the Mailpoet is connected.
[274] Fix | Delete
*
[275] Fix | Delete
* @return bool true if Mailpoet is fully connected, meaning the API key is valid and approved.
[276] Fix | Delete
*/
[277] Fix | Delete
private function is_mailpoet_connected() {
[278] Fix | Delete
if ( ! class_exists( '\MailPoet\DI\ContainerWrapper' ) || ! class_exists( '\MailPoet\Settings\SettingsController' ) ) {
[279] Fix | Delete
return false;
[280] Fix | Delete
}
[281] Fix | Delete
[282] Fix | Delete
$container = \MailPoet\DI\ContainerWrapper::getInstance( WP_DEBUG );
[283] Fix | Delete
[284] Fix | Delete
// SettingController retrieves data from wp_mailpoet_settings table.
[285] Fix | Delete
$settings = $container->get( \MailPoet\Settings\SettingsController::class );
[286] Fix | Delete
[287] Fix | Delete
if ( false === $settings instanceof \MailPoet\Settings\SettingsController ) {
[288] Fix | Delete
return false;
[289] Fix | Delete
}
[290] Fix | Delete
[291] Fix | Delete
$mta = $settings->get( 'mta' );
[292] Fix | Delete
$api_state = $mta['mailpoet_api_key_state'] ?? null;
[293] Fix | Delete
[294] Fix | Delete
if ( ! $api_state || ! isset( $api_state['state'], $api_state['code'] ) ) {
[295] Fix | Delete
return false;
[296] Fix | Delete
}
[297] Fix | Delete
[298] Fix | Delete
return 'valid' === $api_state['state'] && 200 === $api_state['code'];
[299] Fix | Delete
}
[300] Fix | Delete
[301] Fix | Delete
/**
[302] Fix | Delete
* Track when coming soon template is changed.
[303] Fix | Delete
*
[304] Fix | Delete
* @param int $post_id The post ID.
[305] Fix | Delete
* @param WP_Post $post The post object.
[306] Fix | Delete
* @param bool $update Whether the post is being updated.
[307] Fix | Delete
*/
[308] Fix | Delete
public function maybe_track_template_change( $post_id, $post, $update ) {
[309] Fix | Delete
if ( ! $post instanceof \WP_Post || ! isset( $post->post_name, $post->post_title ) ) {
[310] Fix | Delete
return;
[311] Fix | Delete
}
[312] Fix | Delete
[313] Fix | Delete
// Check multiple fields to avoid false matches with non-WooCommerce templates.
[314] Fix | Delete
if ( 'coming-soon' === $post->post_name && 'Page: Coming soon' === $post->post_title ) {
[315] Fix | Delete
$matches = array();
[316] Fix | Delete
$content = $post->post_content;
[317] Fix | Delete
preg_match( '/"comingSoonPatternId":"([^"]+)"/', $content, $matches );
[318] Fix | Delete
[319] Fix | Delete
if ( isset( $matches[1] ) ) {
[320] Fix | Delete
wc_admin_record_tracks_event(
[321] Fix | Delete
'coming_soon_template_saved',
[322] Fix | Delete
array(
[323] Fix | Delete
'pattern_id' => $matches[1],
[324] Fix | Delete
'is_update' => $update,
[325] Fix | Delete
)
[326] Fix | Delete
);
[327] Fix | Delete
}
[328] Fix | Delete
}
[329] Fix | Delete
}
[330] Fix | Delete
[331] Fix | Delete
/**
[332] Fix | Delete
* Load slotfill script and JS variables for the newsletter.
[333] Fix | Delete
* The comingSoonNewsletter is used in client/wp-admin-scripts/coming-soon-newsletter-panel
[334] Fix | Delete
*
[335] Fix | Delete
* @return void
[336] Fix | Delete
*/
[337] Fix | Delete
public function load_newsletter_scripts() {
[338] Fix | Delete
$screen = get_current_screen();
[339] Fix | Delete
if ( ! $screen instanceof \WP_Screen ) {
[340] Fix | Delete
return;
[341] Fix | Delete
}
[342] Fix | Delete
[343] Fix | Delete
if ( 'site-editor' !== $screen->id ) {
[344] Fix | Delete
return;
[345] Fix | Delete
}
[346] Fix | Delete
[347] Fix | Delete
$mailpoet = array(
[348] Fix | Delete
'mailpoet_installed' => PluginsHelper::is_plugin_installed( 'mailpoet' ),
[349] Fix | Delete
'mailpoet_connected' => $this->is_mailpoet_connected(),
[350] Fix | Delete
);
[351] Fix | Delete
[352] Fix | Delete
// phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion, WordPress.WP.EnqueuedResourceParameters.NotInFooter
[353] Fix | Delete
wp_register_script( 'coming-soon-newsletter-mailpoet', '' );
[354] Fix | Delete
wp_enqueue_script( 'coming-soon-newsletter-mailpoet' );
[355] Fix | Delete
wp_add_inline_script( 'coming-soon-newsletter-mailpoet', 'var comingSoonNewsletter = ' . wp_json_encode( $mailpoet, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ';' );
[356] Fix | Delete
}
[357] Fix | Delete
}
[358] Fix | Delete
[359] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function