plugin install

This commit is contained in:
Tony Volpe
2024-06-18 17:29:05 -04:00
parent e1aaedd1ae
commit 41f50eacc4
5880 changed files with 1057631 additions and 39681 deletions

View File

@@ -0,0 +1,257 @@
<?php
/**
* NOTE: this is a temporary class and can be replaced by jetpack-abtest after
* https://github.com/Automattic/jetpack/issues/19596 has been fixed.
*
* A class that interacts with Explat A/B tests.
*
* This class is experimental. It is a fork of the jetpack-abtest package and
* updated for use with ExPlat. These changes are planned to be contributed
* back to the upstream Jetpack package. If accepted, this class should then
* be superseded by the Jetpack class using Composer.
*
* This class should not be used externally.
*
* @package WooCommerce\Admin
* @link https://packagist.org/packages/automattic/jetpack-abtest
*/
namespace WooCommerce\Admin;
use Automattic\Jetpack\Connection\Manager as Jetpack_Connection_Manager;
use Automattic\Jetpack\Connection\Client as Jetpack_Connection_client;
use Automattic\WooCommerce\Admin\WCAdminHelper;
/**
* This class provides an interface to the Explat A/B tests.
*
* Usage:
*
* $anon_id = isset( $_COOKIE['tk_ai'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['tk_ai'] ) ) : '';
* $allow_tracking = 'yes' === get_option( 'woocommerce_allow_tracking' );
* $abtest = new \WooCommerce\Admin\Experimental_Abtest(
* $anon_id,
* 'woocommerce',
* $allow_tracking
* );
*
* OR use the helper function:
*
* WooCommerce\Admin\Experimental_Abtest::in_treatment('experiment_name');
*
*
* $isTreatment = $abtest->get_variation('your-experiment-name') === 'treatment';
*
* @internal This class is experimental and should not be used externally due to planned breaking changes.
*/
final class Experimental_Abtest {
/**
* A variable to hold the tests we fetched, and their variations for the current user.
*
* @var array
*/
private $tests = array();
/**
* ExPlat Anonymous ID.
*
* @var string
*/
private $anon_id = null;
/**
* ExPlat Platform name.
*
* @var string
*/
private $platform = 'woocommerce';
/**
* Whether trcking consent is given.
*
* @var bool
*/
private $consent = false;
/**
* Request variation as a auth wpcom user or not.
*
* @var boolean
*/
private $as_auth_wpcom_user = false;
/**
* Constructor.
*
* @param string $anon_id ExPlat anonymous ID.
* @param string $platform ExPlat platform name.
* @param bool $consent Whether tracking consent is given.
* @param bool $as_auth_wpcom_user Request variation as a auth wp user or not.
*/
public function __construct( string $anon_id, string $platform, bool $consent, bool $as_auth_wpcom_user = false ) {
$this->anon_id = $anon_id;
$this->platform = $platform;
$this->consent = $consent;
$this->as_auth_wpcom_user = $as_auth_wpcom_user;
}
/**
* Returns true if the current user is in the treatment group of the given experiment.
*
* @param string $experiment_name Name of the experiment.
* @param bool $as_auth_wpcom_user Request variation as a auth wp user or not.
* @return bool
*/
public static function in_treatment( string $experiment_name, bool $as_auth_wpcom_user = false ) {
$anon_id = isset( $_COOKIE['tk_ai'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['tk_ai'] ) ) : '';
$allow_tracking = 'yes' === get_option( 'woocommerce_allow_tracking' );
$abtest = new self(
$anon_id,
'woocommerce',
$allow_tracking,
$as_auth_wpcom_user
);
return $abtest->get_variation( $experiment_name ) === 'treatment';
}
/**
* Retrieve the test variation for a provided A/B test.
*
* @param string $test_name Name of the A/B test.
* @return mixed|null A/B test variation, or null on failure.
* @throws \Exception If there is an error retrieving the variation and the environment is not production.
*/
public function get_variation( $test_name ) {
// Default to the control variation when users haven't consented to tracking.
if ( ! $this->consent ) {
return 'control';
}
$variation = $this->fetch_variation( $test_name );
// If there was an error retrieving a variation, conceal the error for the consumer.
// If there was an error retrieving a variation, throw an exception in non-production environments.
if ( is_wp_error( $variation ) ) {
if ( 'production' !== wp_get_environment_type() ) {
throw new \Exception( $variation->get_error_message() );
}
return 'control';
}
return $variation;
}
/**
* Perform the request for a experiment assignment of a provided A/B test from WP.com.
*
* @param array $args Arguments to pass to the request for A/B test.
* @return array|\WP_Error A/B test variation error on failure.
*/
public function request_assignment( $args ) {
// Request as authenticated wp user.
if ( $this->as_auth_wpcom_user && class_exists( Jetpack_Connection_Manager::class ) ) {
$jetpack_connection_manager = new Jetpack_Connection_Manager();
if ( $jetpack_connection_manager->is_user_connected() ) {
$response = Jetpack_Connection_client::wpcom_json_api_request_as_user(
'/experiments/0.1.0/assignments/' . $this->platform,
'2',
$args
);
}
}
// Request as anonymous user.
if ( ! isset( $response ) ) {
if ( ! isset( $args['anon_id'] ) || empty( $args['anon_id'] ) ) {
return new \WP_Error( 'invalid_anon_id', 'anon_id must be an none empty string.' );
}
$url = add_query_arg(
$args,
sprintf(
'https://public-api.wordpress.com/wpcom/v2/experiments/0.1.0/assignments/%s',
$this->platform
)
);
$response = wp_remote_get( $url );
}
return $response;
}
/**
* Fetch and cache the test variation for a provided A/B test from WP.com.
*
* ExPlat returns a null value when the assigned variation is control or
* an assignment has not been set. In these instances, this method returns
* a value of "control".
*
* @param string $test_name Name of the A/B test.
* @return array|\WP_Error A/B test variation, or error on failure.
*/
protected function fetch_variation( $test_name ) {
// Make sure test name exists.
if ( ! $test_name ) {
return new \WP_Error( 'test_name_not_provided', 'A/B test name has not been provided.' );
}
// Make sure test name is a valid one.
if ( ! preg_match( '/^[a-z0-9_]+$/', $test_name ) ) {
return new \WP_Error( 'invalid_test_name', 'Invalid A/B test name.' );
}
// Return internal-cached test variations.
if ( isset( $this->tests[ $test_name ] ) ) {
return $this->tests[ $test_name ];
}
// Return external-cached test variations.
if ( ! empty( get_transient( 'abtest_variation_' . $test_name ) ) ) {
return get_transient( 'abtest_variation_' . $test_name );
}
// Make the request to the WP.com API.
$args = array(
'experiment_name' => $test_name,
'anon_id' => rawurlencode( $this->anon_id ),
'woo_country_code' => rawurlencode( get_option( 'woocommerce_default_country', 'US:CA' ) ),
'woo_wcadmin_install_timestamp' => rawurlencode( get_option( WCAdminHelper::WC_ADMIN_TIMESTAMP_OPTION ) ),
);
/**
* Get additional request args.
*
* @since 6.5.0
*/
$args = apply_filters( 'woocommerce_explat_request_args', $args );
$response = $this->request_assignment( $args );
// Bail if there was an error or malformed response.
if ( is_wp_error( $response ) || ! is_array( $response ) || ! isset( $response['body'] ) ) {
return new \WP_Error( 'failed_to_fetch_data', 'Unable to fetch the requested data.' );
}
// Decode the results.
$results = json_decode( $response['body'], true );
// Bail if there were no resultsreturned.
if ( ! is_array( $results ) ) {
return new \WP_Error( 'unexpected_data_format', 'Data was not returned in the expected format.' );
}
// Store the variation in our internal cache.
$this->tests[ $test_name ] = $results['variations'][ $test_name ] ?? null;
$variation = $results['variations'][ $test_name ] ?? 'control';
// Store the variation in our external cache.
if ( ! empty( $results['ttl'] ) ) {
set_transient( 'abtest_variation_' . $test_name, $variation, $results['ttl'] );
}
return $variation;
}
}

View File

@@ -0,0 +1,310 @@
<?php
/**
* Connect existing WooCommerce pages to WooCommerce Admin.
*
* @package WooCommerce\Admin
*/
use Automattic\WooCommerce\Admin\PageController;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Utilities\OrderUtil;
/**
* Returns core WC pages to connect to WC-Admin.
*
* @return array
*/
function wc_admin_get_core_pages_to_connect() {
$all_reports = WC_Admin_Reports::get_reports();
$report_tabs = array();
foreach ( $all_reports as $report_id => $report_data ) {
$report_tabs[ $report_id ] = $report_data['title'];
}
return array(
'wc-addons' => array(
'title' => __( 'Extensions', 'woocommerce' ),
'tabs' => array(),
),
'wc-reports' => array(
'title' => __( 'Reports', 'woocommerce' ),
'tabs' => $report_tabs,
),
'wc-settings' => array(
'title' => __( 'Settings', 'woocommerce' ),
'tabs' => apply_filters( 'woocommerce_settings_tabs_array', array() ), // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
),
'wc-status' => array(
'title' => __( 'Status', 'woocommerce' ),
// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
'tabs' => apply_filters(
'woocommerce_admin_status_tabs',
array(
'status' => __( 'System status', 'woocommerce' ),
'tools' => __( 'Tools', 'woocommerce' ),
'logs' => __( 'Logs', 'woocommerce' ),
)
),
),
);
}
/**
* Filter breadcrumbs for core pages that aren't explicitly connected.
*
* @param array $breadcrumbs Breadcrumb pieces.
* @return array Filtered breadcrumb pieces.
*/
function wc_admin_filter_core_page_breadcrumbs( $breadcrumbs ) {
$screen_id = PageController::get_instance()->get_current_screen_id();
$pages_to_connect = wc_admin_get_core_pages_to_connect();
$woocommerce_breadcrumb = array(
'admin.php?page=wc-admin',
__( 'WooCommerce', 'woocommerce' ),
);
foreach ( $pages_to_connect as $page_id => $page_data ) {
if ( preg_match( "/^woocommerce_page_{$page_id}\-/", $screen_id ) ) {
if ( empty( $page_data['tabs'] ) ) {
$new_breadcrumbs = array(
$woocommerce_breadcrumb,
$page_data['title'],
);
} else {
$new_breadcrumbs = array(
$woocommerce_breadcrumb,
array(
add_query_arg( 'page', $page_id, 'admin.php' ),
$page_data['title'],
),
);
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( isset( $_GET['tab'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$current_tab = wc_clean( wp_unslash( $_GET['tab'] ) );
} else {
$current_tab = key( $page_data['tabs'] );
}
$new_breadcrumbs[] = $page_data['tabs'][ $current_tab ];
}
return $new_breadcrumbs;
}
}
return $breadcrumbs;
}
/**
* Render the WC-Admin header bar on all WooCommerce core pages.
*
* @param bool $is_connected Whether the current page is connected.
* @param bool $current_page The current page, if connected.
* @return bool Whether to connect the page.
*/
function wc_admin_connect_core_pages( $is_connected, $current_page ) {
if ( false === $is_connected && false === $current_page ) {
$screen_id = PageController::get_instance()->get_current_screen_id();
$pages_to_connect = wc_admin_get_core_pages_to_connect();
foreach ( $pages_to_connect as $page_id => $page_data ) {
if ( preg_match( "/^woocommerce_page_{$page_id}\-/", $screen_id ) ) {
add_filter( 'woocommerce_navigation_get_breadcrumbs', 'wc_admin_filter_core_page_breadcrumbs' );
return true;
}
}
}
return $is_connected;
}
add_filter( 'woocommerce_navigation_is_connected_page', 'wc_admin_connect_core_pages', 10, 2 );
$posttype_list_base = 'edit.php';
// WooCommerce > Orders.
wc_admin_connect_page(
array(
'id' => 'woocommerce-orders',
'screen_id' => 'edit-shop_order',
'title' => __( 'Orders', 'woocommerce' ),
'path' => add_query_arg( 'post_type', 'shop_order', $posttype_list_base ),
)
);
// WooCommerce > Orders > Add New.
wc_admin_connect_page(
array(
'id' => 'woocommerce-add-order',
'parent' => 'woocommerce-orders',
'screen_id' => 'shop_order-add',
'title' => __( 'Add New', 'woocommerce' ),
)
);
// WooCommerce > Orders > Edit Order.
wc_admin_connect_page(
array(
'id' => 'woocommerce-edit-order',
'parent' => 'woocommerce-orders',
'screen_id' => 'shop_order',
'title' => __( 'Edit Order', 'woocommerce' ),
)
);
if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
// WooCommerce > Orders (COT).
wc_admin_connect_page(
array(
'id' => 'woocommerce-custom-orders',
'screen_id' => wc_get_page_screen_id( 'shop-order' ),
'title' => __( 'Orders', 'woocommerce' ),
'path' => 'admin.php?page=wc-orders',
)
);
}
// WooCommerce > Coupons.
wc_admin_connect_page(
array(
'id' => 'woocommerce-coupons',
'parent' => Features::is_enabled( 'coupons' ) ? 'woocommerce-marketing' : null,
'screen_id' => 'edit-shop_coupon',
'title' => __( 'Coupons', 'woocommerce' ),
'path' => add_query_arg( 'post_type', 'shop_coupon', $posttype_list_base ),
)
);
// WooCommerce > Coupons > Add New.
wc_admin_connect_page(
array(
'id' => 'woocommerce-add-coupon',
'parent' => 'woocommerce-coupons',
'screen_id' => 'shop_coupon-add',
'title' => __( 'Add New', 'woocommerce' ),
)
);
// WooCommerce > Coupons > Edit Coupon.
wc_admin_connect_page(
array(
'id' => 'woocommerce-edit-coupon',
'parent' => 'woocommerce-coupons',
'screen_id' => 'shop_coupon',
'title' => __( 'Edit Coupon', 'woocommerce' ),
)
);
// WooCommerce > Products.
wc_admin_connect_page(
array(
'id' => 'woocommerce-products',
'screen_id' => 'edit-product',
'title' => __( 'Products', 'woocommerce' ),
'path' => add_query_arg( 'post_type', 'product', $posttype_list_base ),
)
);
// WooCommerce > Products > Add New.
wc_admin_connect_page(
array(
'id' => 'woocommerce-add-product',
'parent' => 'woocommerce-products',
'screen_id' => 'product-add',
'title' => __( 'Add New', 'woocommerce' ),
)
);
// WooCommerce > Products > Edit Order.
wc_admin_connect_page(
array(
'id' => 'woocommerce-edit-product',
'parent' => 'woocommerce-products',
'screen_id' => 'product',
'title' => __( 'Edit Product', 'woocommerce' ),
)
);
// WooCommerce > Products > Import Products.
wc_admin_connect_page(
array(
'id' => 'woocommerce-import-products',
'parent' => 'woocommerce-products',
'screen_id' => 'product_page_product_importer',
'title' => __( 'Import Products', 'woocommerce' ),
)
);
// WooCommerce > Products > Export Products.
wc_admin_connect_page(
array(
'id' => 'woocommerce-export-products',
'parent' => 'woocommerce-products',
'screen_id' => 'product_page_product_exporter',
'title' => __( 'Export Products', 'woocommerce' ),
)
);
// WooCommerce > Products > Product categories.
wc_admin_connect_page(
array(
'id' => 'woocommerce-product-categories',
'parent' => 'woocommerce-products',
'screen_id' => 'edit-product_cat',
'title' => __( 'Product categories', 'woocommerce' ),
)
);
// WooCommerce > Products > Edit category.
wc_admin_connect_page(
array(
'id' => 'woocommerce-product-edit-category',
'parent' => 'woocommerce-products',
'screen_id' => 'product_cat',
'title' => __( 'Edit category', 'woocommerce' ),
)
);
// WooCommerce > Products > Product tags.
wc_admin_connect_page(
array(
'id' => 'woocommerce-product-tags',
'parent' => 'woocommerce-products',
'screen_id' => 'edit-product_tag',
'title' => __( 'Product tags', 'woocommerce' ),
)
);
// WooCommerce > Products > Edit tag.
wc_admin_connect_page(
array(
'id' => 'woocommerce-product-edit-tag',
'parent' => 'woocommerce-products',
'screen_id' => 'product_tag',
'title' => __( 'Edit tag', 'woocommerce' ),
)
);
// WooCommerce > Products > Attributes.
wc_admin_connect_page(
array(
'id' => 'woocommerce-product-attributes',
'parent' => 'woocommerce-products',
'screen_id' => 'product_page_product_attributes',
'title' => __( 'Attributes', 'woocommerce' ),
)
);
// WooCommerce > Products > Edit attribute.
wc_admin_connect_page(
array(
'id' => 'woocommerce-product-edit-attribute',
'parent' => 'woocommerce-products',
'screen_id' => 'product_page_product_attribute-edit',
'title' => __( 'Edit attribute', 'woocommerce' ),
)
);

View File

@@ -0,0 +1,72 @@
<?php
/**
* Core Functions
*
* Holds core functions for wc-admin.
*
* @package WooCommerce\Admin\Functions
*/
use Automattic\WooCommerce\Internal\Admin\Settings;
/**
* Format a number using the decimal and thousands separator settings in WooCommerce.
*
* @param mixed $number Number to be formatted.
* @return string
*/
function wc_admin_number_format( $number ) {
$currency_settings = Settings::get_currency_settings();
return number_format(
$number,
0,
$currency_settings['decimalSeparator'],
$currency_settings['thousandSeparator']
);
}
/**
* Retrieves a URL to relative path inside WooCommerce admin with
* the provided query parameters.
*
* @param string $path Relative path of the desired page.
* @param array $query Query parameters to append to the path.
*
* @return string Fully qualified URL pointing to the desired path.
*/
function wc_admin_url( $path = null, $query = array() ) {
if ( ! empty( $query ) ) {
$query_string = http_build_query( $query );
$path = $path ? '&path=' . $path . '&' . $query_string : '';
}
return admin_url( 'admin.php?page=wc-admin' . $path, dirname( __FILE__ ) );
}
/**
* Record an event using Tracks.
*
* @internal WooCommerce core only includes Tracks in admin, not the REST API, so we need to include it.
* @param string $event_name Event name for tracks.
* @param array $properties Properties to pass along with event.
*/
function wc_admin_record_tracks_event( $event_name, $properties = array() ) {
// WC post types must be registered first for WC_Tracks to work.
if ( ! post_type_exists( 'product' ) ) {
return;
}
if ( ! class_exists( 'WC_Tracks' ) ) {
if ( ! defined( 'WC_ABSPATH' ) || ! file_exists( WC_ABSPATH . 'includes/tracks/class-wc-tracks.php' ) ) {
return;
}
include_once WC_ABSPATH . 'includes/tracks/class-wc-tracks.php';
include_once WC_ABSPATH . 'includes/tracks/class-wc-tracks-event.php';
include_once WC_ABSPATH . 'includes/tracks/class-wc-tracks-client.php';
include_once WC_ABSPATH . 'includes/tracks/class-wc-tracks-footer-pixel.php';
include_once WC_ABSPATH . 'includes/tracks/class-wc-site-tracking.php';
}
WC_Tracks::record_event( $event_name, $properties );
}

View File

@@ -0,0 +1,26 @@
<?php
/**
* Admin report export download
*
* @package WooCommerce\Admin\Templates\Emails\HTML
*/
defined( 'ABSPATH' ) || exit;
/*
* @hooked WC_Emails::email_header() Output the email header
*/
do_action( 'woocommerce_email_header', $email_heading, $email );
?>
<a href="<?php echo esc_url( $download_url ); ?>">
<?php
/* translators: %s: report name */
echo esc_html( sprintf( __( 'Download your %s Report', 'woocommerce' ), $report_name ) );
?>
</a>
<?php
/*
* @hooked WC_Emails::email_footer() Output the email footer
*/
do_action( 'woocommerce_email_footer', $email );

View File

@@ -0,0 +1,69 @@
<?php
/**
* Merchant notification email
*
* @package WooCommerce\Admin\Templates\Emails\HTML
*/
defined( 'ABSPATH' ) || exit;
/*
* @hooked WC_Emails::email_header() Output the email header
*/
do_action( 'woocommerce_email_header', $email_heading, $email );
?>
<?php if ( isset( $email_image ) ) { ?>
<div>
<img src="<?php echo esc_url( $email_image ); ?>" style="display: block; margin-bottom: 24px; width: 180px;"/>
</div>
<?php } ?>
<?php
echo wp_kses(
$email_content,
array(
'a' => array(
'href' => array(),
'title' => array(),
),
'br' => array(),
'em' => array(),
'strong' => array(),
)
);
$base_color = get_option( 'woocommerce_email_base_color' );
$base_text = wc_light_or_dark( $base_color, '#202020', '#ffffff' );
$container_styles = 'margin-top: 25px;';
$buttons_styles = "
font-style: normal;
font-weight: normal;
font-size: 13px;
line-height: 18px;
text-align: center;
color: {$base_text};
margin-right: 15px;
text-decoration: none;
background: {$base_color};
border: 1px solid {$base_color};
border-radius: 3px;
padding: 6px 15px;";
?>
<div style="<?php echo esc_attr( $container_styles ); ?>">
<?php foreach ( $email_actions as $an_action ) : ?>
<a href="<?php echo esc_url( $trigger_note_action_url . $an_action->id ); ?>" style="<?php echo esc_attr( $buttons_styles ); ?>">
<?php
echo esc_html( $an_action->label );
?>
</a>
<?php endforeach; ?>
</div>
<div style="opacity: 0;">
<img src="<?php echo esc_url( $opened_tracking_url ); ?>" />
</div>
<?php
/*
* @hooked WC_Emails::email_footer() Output the email footer
*/
do_action( 'woocommerce_email_footer', $email );

View File

@@ -0,0 +1,19 @@
<?php
/**
* Admin report export download email (plain text)
*
* @package WooCommerce\Admin\Templates\Emails\HTML
*/
defined( 'ABSPATH' ) || exit;
echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n";
echo esc_html( wp_strip_all_tags( $email_heading ) );
echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n";
/* translators: %1$s: report name, %2$s: download URL */
echo wp_kses_post( sprintf( __( 'Download your %1$s Report: %2$s', 'woocommerce' ), $report_name, $download_url ) );
echo "\n\n----------------------------------------\n\n";
echo wp_kses_post( apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ) );

View File

@@ -0,0 +1,23 @@
<?php
/**
* Merchant notification email (plain text)
*
* @package WooCommerce\Admin\Templates\Emails\HTML
*/
defined( 'ABSPATH' ) || exit;
echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n";
echo esc_html( wp_strip_all_tags( $email_heading ) );
echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n";
echo wp_kses_post( $email_content );
foreach ( $email_actions as $an_action ) {
echo "\n";
/* translators: %1$s: action label, %2$s: action URL */
echo wp_kses_post( sprintf( __( '%1$s: %2$s', 'woocommerce' ), $an_action->label, $trigger_note_action_url . $an_action->id ) );
}
echo "\n\n----------------------------------------\n\n";
echo wp_kses_post( apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ) );

View File

@@ -0,0 +1,45 @@
<?php
// WARNING: Do not directly edit this file.
// This file is auto-generated as part of the build process and things may break.
if ( ! function_exists( 'wc_admin_get_feature_config' ) ) {
function wc_admin_get_feature_config() {
return array(
'activity-panels' => true,
'analytics' => true,
'product-block-editor' => true,
'coupons' => true,
'core-profiler' => true,
'customize-store' => true,
'customer-effort-score-tracks' => true,
'import-products-task' => true,
'experimental-fashion-sample-products' => true,
'shipping-smart-defaults' => true,
'shipping-setting-tour' => true,
'homescreen' => true,
'marketing' => true,
'minified-js' => false,
'mobile-app-banner' => true,
'navigation' => true,
'new-product-management-experience' => false,
'onboarding' => true,
'onboarding-tasks' => true,
'pattern-toolkit-full-composability' => false,
'product-pre-publish-modal' => false,
'product-custom-fields' => true,
'remote-inbox-notifications' => true,
'remote-free-extensions' => true,
'payment-gateway-suggestions' => true,
'settings' => false,
'shipping-label-banner' => true,
'subscriptions' => true,
'store-alerts' => true,
'transient-notices' => true,
'woo-mobile-welcome' => true,
'wc-pay-promotion' => true,
'wc-pay-welcome-page' => true,
'async-product-editor-category-field' => false,
'launch-your-store' => false,
'product-editor-template-system' => false,
);
}
}

View File

@@ -0,0 +1,63 @@
<?php
/**
* Convenience functions for PageController.
*
* @package WooCommerce\Admin
*/
use Automattic\WooCommerce\Admin\PageController;
/**
* Connect an existing page to WooCommerce Admin.
* Passthrough to PageController::connect_page().
*
* @param array $options Options for PageController::connect_page().
*/
function wc_admin_connect_page( $options ) {
$controller = PageController::get_instance();
$controller->connect_page( $options );
}
/**
* Register JS-powered WooCommerce Admin Page.
* Passthrough to PageController::register_page().
*
* @param array $options Options for PageController::register_page().
*/
function wc_admin_register_page( $options ) {
$controller = PageController::get_instance();
$controller->register_page( $options );
}
/**
* Is this page connected to WooCommerce Admin?
* Passthrough to PageController::is_connected_page().
*
* @return boolean True if the page is connected to WooCommerce Admin.
*/
function wc_admin_is_connected_page() {
$controller = PageController::get_instance();
return $controller->is_connected_page();
}
/**
* Is this a WooCommerce Admin Page?
* Passthrough to PageController::is_registered_page().
*
* @return boolean True if the page is a WooCommerce Admin page.
*/
function wc_admin_is_registered_page() {
$controller = PageController::get_instance();
return $controller->is_registered_page();
}
/**
* Get breadcrumbs for WooCommerce Admin Page navigation.
* Passthrough to PageController::get_breadcrumbs().
*
* @return array Navigation pieces (breadcrumbs).
*/
function wc_admin_get_breadcrumbs() {
$controller = PageController::get_instance();
return $controller->get_breadcrumbs();
}

View File

@@ -0,0 +1,285 @@
<?php
/**
* WooCommerce Admin Updates
*
* Functions for updating data, used by the background updater.
*
* @package WooCommerce\Admin
*/
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
use Automattic\WooCommerce\Admin\Notes\Notes;
use Automattic\WooCommerce\Internal\Admin\Notes\UnsecuredReportFiles;
use Automattic\WooCommerce\Admin\ReportExporter;
/**
* Update order stats `status` index length.
* See: https://github.com/woocommerce/woocommerce-admin/issues/2969.
*/
function wc_admin_update_0201_order_status_index() {
global $wpdb;
// Max DB index length. See wp_get_db_schema().
$max_index_length = 191;
$index = $wpdb->get_row( "SHOW INDEX FROM {$wpdb->prefix}wc_order_stats WHERE key_name = 'status'" );
if ( property_exists( $index, 'Sub_part' ) ) {
// The index was created with the right length. Time to bail.
if ( $max_index_length === $index->Sub_part ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
return;
}
// We need to drop the index so it can be recreated.
$wpdb->query( "DROP INDEX `status` ON {$wpdb->prefix}wc_order_stats" );
}
// Recreate the status index with a max length.
$wpdb->query( $wpdb->prepare( "ALTER TABLE {$wpdb->prefix}wc_order_stats ADD INDEX status (status(%d))", $max_index_length ) );
}
/**
* Rename "gross_total" to "total_sales".
* See: https://github.com/woocommerce/woocommerce-admin/issues/3175
*/
function wc_admin_update_0230_rename_gross_total() {
global $wpdb;
// We first need to drop the new `total_sales` column, since dbDelta() will have created it.
$wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_order_stats DROP COLUMN `total_sales`" );
// Then we can rename the existing `gross_total` column.
$wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_order_stats CHANGE COLUMN `gross_total` `total_sales` double DEFAULT 0 NOT NULL" );
}
/**
* Remove the note unsnoozing scheduled action.
*/
function wc_admin_update_0251_remove_unsnooze_action() {
as_unschedule_action( Notes::UNSNOOZE_HOOK, null, 'wc-admin-data' );
as_unschedule_action( Notes::UNSNOOZE_HOOK, null, 'wc-admin-notes' );
}
/**
* Remove Facebook Extension note.
*/
function wc_admin_update_110_remove_facebook_note() {
Notes::delete_notes_with_name( 'wc-admin-facebook-extension' );
}
/**
* Remove Dismiss action from tracking opt-in admin note.
*/
function wc_admin_update_130_remove_dismiss_action_from_tracking_opt_in_note() {
global $wpdb;
$wpdb->query( "DELETE actions FROM {$wpdb->prefix}wc_admin_note_actions actions INNER JOIN {$wpdb->prefix}wc_admin_notes notes USING (note_id) WHERE actions.name = 'tracking-dismiss' AND notes.name = 'wc-admin-usage-tracking-opt-in'" );
}
/**
* Update DB Version.
*/
function wc_admin_update_130_db_version() {
Installer::update_db_version( '1.3.0' );
}
/**
* Update DB Version.
*/
function wc_admin_update_140_db_version() {
Installer::update_db_version( '1.4.0' );
}
/**
* Remove Facebook Experts note.
*/
function wc_admin_update_160_remove_facebook_note() {
Notes::delete_notes_with_name( 'wc-admin-facebook-marketing-expert' );
}
/**
* Set "two column" homescreen layout as default for existing stores.
*/
function wc_admin_update_170_homescreen_layout() {
add_option( 'woocommerce_default_homepage_layout', 'two_columns', '', 'no' );
}
/**
* Delete the preexisting export files.
*/
function wc_admin_update_270_delete_report_downloads() {
$upload_dir = wp_upload_dir();
$base_dir = trailingslashit( $upload_dir['basedir'] );
$failed_files = array();
$exports_status = get_option( ReportExporter::EXPORT_STATUS_OPTION, array() );
$has_failure = false;
if ( ! is_array( $exports_status ) ) {
// This is essentially the same path as files failing deletion. Handle as such.
return;
}
// Delete all export files based on the status option values.
foreach ( $exports_status as $key => $progress ) {
list( $report_type, $export_id ) = explode( ':', $key );
if ( ! $export_id ) {
continue;
}
$file = "{$base_dir}wc-{$report_type}-report-export-{$export_id}.csv";
$header = $file . '.headers';
// phpcs:ignore
if ( @file_exists( $file ) && false === @unlink( $file ) ) {
array_push( $failed_files, $file );
}
// phpcs:ignore
if ( @file_exists( $header ) && false === @unlink( $header ) ) {
array_push( $failed_files, $header );
}
}
// If the status option was missing or corrupt, there will be files left over.
$potential_exports = glob( $base_dir . 'wc-*-report-export-*.csv' );
$reports_pattern = '(revenue|products|variations|orders|categories|coupons|taxes|stock|customers|downloads)';
/**
* Look for files we can be reasonably sure were created by the report export.
*
* Export files we created will match the 'wc-*-report-export-*.csv' glob, with
* the first wildcard being one of the exportable report slugs, and the second
* being an integer with 11-14 digits (from microtime()'s output) that represents
* a time in the past.
*/
foreach ( $potential_exports as $potential_export ) {
$matches = array();
// See if the filename matches an unfiltered export pattern.
if ( ! preg_match( "/wc-{$reports_pattern}-report-export-(?P<export_id>\d{11,14})\.csv\$/", $potential_export, $matches ) ) {
$has_failure = true;
continue;
}
// Validate the timestamp (anything in the past).
$timestamp = (int) substr( $matches['export_id'], 0, 10 );
if ( ! $timestamp || $timestamp > time() ) {
$has_failure = true;
continue;
}
// phpcs:ignore
if ( false === @unlink( $potential_export ) ) {
array_push( $failed_files, $potential_export );
}
}
// Try deleting failed files once more.
foreach ( $failed_files as $failed_file ) {
// phpcs:ignore
if ( false === @unlink( $failed_file ) ) {
$has_failure = true;
}
}
if ( $has_failure ) {
UnsecuredReportFiles::possibly_add_note();
}
}
/**
* Update the old task list options.
*/
function wc_admin_update_271_update_task_list_options() {
$hidden_lists = get_option( 'woocommerce_task_list_hidden_lists', array() );
$setup_list_hidden = get_option( 'woocommerce_task_list_hidden', 'no' );
$extended_list_hidden = get_option( 'woocommerce_extended_task_list_hidden', 'no' );
if ( 'yes' === $setup_list_hidden ) {
$hidden_lists[] = 'setup';
}
if ( 'yes' === $extended_list_hidden ) {
$hidden_lists[] = 'extended';
}
update_option( 'woocommerce_task_list_hidden_lists', array_unique( $hidden_lists ) );
delete_option( 'woocommerce_task_list_hidden' );
delete_option( 'woocommerce_extended_task_list_hidden' );
}
/**
* Update order stats `status`.
*/
function wc_admin_update_280_order_status() {
global $wpdb;
$wpdb->query(
"UPDATE {$wpdb->prefix}wc_order_stats refunds
INNER JOIN {$wpdb->prefix}wc_order_stats orders
ON orders.order_id = refunds.parent_id
SET refunds.status = orders.status
WHERE refunds.parent_id != 0"
);
}
/**
* Update the old task list options.
*/
function wc_admin_update_290_update_apperance_task_option() {
$is_actioned = get_option( 'woocommerce_task_list_appearance_complete', false );
$task = TaskLists::get_task( 'appearance' );
if ( $task && $is_actioned ) {
$task->mark_actioned();
}
delete_option( 'woocommerce_task_list_appearance_complete' );
}
/**
* Delete the old woocommerce_default_homepage_layout option.
*/
function wc_admin_update_290_delete_default_homepage_layout_option() {
delete_option( 'woocommerce_default_homepage_layout' );
}
/**
* Use woocommerce_admin_activity_panel_inbox_last_read from the user meta to set wc_admin_notes.is_read col.
*/
function wc_admin_update_300_update_is_read_from_last_read() {
global $wpdb;
$meta_key = 'woocommerce_admin_activity_panel_inbox_last_read';
// phpcs:ignore
$users = get_users( "meta_key={$meta_key}&orderby={$meta_key}&fields=all_with_meta&number=1" );
if ( count( $users ) ) {
$last_read = current( $users )->{$meta_key};
$date_in_utc = gmdate( 'Y-m-d H:i:s', intval( $last_read ) / 1000 );
$wpdb->query(
$wpdb->prepare(
"
update {$wpdb->prefix}wc_admin_notes set is_read = 1
where
date_created <= %s",
$date_in_utc
)
);
$wpdb->query( $wpdb->prepare( "delete from {$wpdb->usermeta} where meta_key=%s", $meta_key ) );
}
}
/**
* Delete "is_primary" column from the wc_admin_notes table.
*/
function wc_admin_update_340_remove_is_primary_from_note_action() {
global $wpdb;
$wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_admin_note_actions DROP COLUMN `is_primary`" );
}
/**
* Delete the deprecated remote inbox notifications option since transients are now used.
*/
function wc_update_670_delete_deprecated_remote_inbox_notifications_option() {
delete_option( 'wc_remote_inbox_notifications_specs' );
}