initial commit
This commit is contained in:
@ -0,0 +1,176 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* This class provides an interface to the Explat A/B tests.
|
||||
*
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $anon_id ExPlat anonymous ID.
|
||||
* @param string $platform ExPlat platform name.
|
||||
* @param bool $consent Whether tracking consent is given.
|
||||
*/
|
||||
public function __construct( string $anon_id, string $platform, bool $consent ) {
|
||||
$this->anon_id = $anon_id;
|
||||
$this->platform = $platform;
|
||||
$this->consent = $consent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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 ( is_wp_error( $variation ) ) {
|
||||
return 'control';
|
||||
}
|
||||
|
||||
return $variation;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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-Za-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.
|
||||
$response = $this->request_variation( $test_name );
|
||||
|
||||
// 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 results or there is no test variation returned.
|
||||
if ( ! is_array( $results ) || empty( $results['variations'] ) ) {
|
||||
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 ];
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the request for a variation of a provided A/B test from WP.com.
|
||||
*
|
||||
* @param string $test_name Name of the A/B test.
|
||||
* @return array|\WP_Error A/B test variation error on failure.
|
||||
*/
|
||||
protected function request_variation( $test_name ) {
|
||||
$args = array(
|
||||
'experiment_name' => $test_name,
|
||||
'anon_id' => $this->anon_id,
|
||||
);
|
||||
|
||||
$url = add_query_arg(
|
||||
$args,
|
||||
sprintf(
|
||||
'https://public-api.wordpress.com/wpcom/v2/experiments/0.1.0/assignments/%s',
|
||||
$this->platform
|
||||
)
|
||||
);
|
||||
|
||||
$get = wp_remote_get( $url );
|
||||
|
||||
return $get;
|
||||
}
|
||||
}
|
||||
|
306
packages/woocommerce-admin/includes/connect-existing-pages.php
Normal file
306
packages/woocommerce-admin/includes/connect-existing-pages.php
Normal file
@ -0,0 +1,306 @@
|
||||
<?php
|
||||
/**
|
||||
* Connect existing WooCommerce pages to WooCommerce Admin.
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Admin\PageController;
|
||||
use Automattic\WooCommerce\Admin\Features\Features;
|
||||
|
||||
/**
|
||||
* 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' => __( 'Marketplace', '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() ),
|
||||
),
|
||||
'wc-status' => array(
|
||||
'title' => __( 'Status', 'woocommerce' ),
|
||||
'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' ),
|
||||
)
|
||||
);
|
||||
|
||||
// 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' ),
|
||||
)
|
||||
);
|
||||
|
||||
// WooCommerce > My Subscriptions.
|
||||
wc_admin_connect_page(
|
||||
array(
|
||||
'id' => 'wc-subscriptions',
|
||||
'screen_id' => 'woocommerce_page_wc-addons-browse-extensions-helper',
|
||||
'title' => __( 'My Subscriptions', 'woocommerce' ),
|
||||
'path' => 'admin.php?page=wc-addons§ion=helper',
|
||||
)
|
||||
);
|
72
packages/woocommerce-admin/includes/core-functions.php
Normal file
72
packages/woocommerce-admin/includes/core-functions.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
/**
|
||||
* Core Functions
|
||||
*
|
||||
* Holds core functions for wc-admin.
|
||||
*
|
||||
* @package WooCommerce\Admin\Functions
|
||||
*/
|
||||
|
||||
use \Automattic\WooCommerce\Admin\Loader;
|
||||
|
||||
/**
|
||||
* 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 = Loader::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 );
|
||||
}
|
@ -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 );
|
@ -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 );
|
@ -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' ) ) );
|
@ -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' ) ) );
|
29
packages/woocommerce-admin/includes/feature-config.php
Normal file
29
packages/woocommerce-admin/includes/feature-config.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?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,
|
||||
'coupons' => true,
|
||||
'customer-effort-score-tracks' => true,
|
||||
'homescreen' => true,
|
||||
'marketing' => true,
|
||||
'minified-js' => false,
|
||||
'mobile-app-banner' => true,
|
||||
'navigation' => false,
|
||||
'onboarding' => true,
|
||||
'remote-inbox-notifications' => true,
|
||||
'remote-free-extensions' => true,
|
||||
'payment-gateway-suggestions' => true,
|
||||
'settings' => false,
|
||||
'shipping-label-banner' => true,
|
||||
'subscriptions' => true,
|
||||
'store-alerts' => true,
|
||||
'tasks' => false,
|
||||
'transient-notices' => true,
|
||||
'wc-pay-promotion' => true,
|
||||
);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
@ -0,0 +1,296 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce Admin Updates
|
||||
*
|
||||
* Functions for updating data, used by the background updater.
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
*/
|
||||
|
||||
use \Automattic\WooCommerce\Admin\Install as Installer;
|
||||
use \Automattic\WooCommerce\Admin\Notes\Notes;
|
||||
use \Automattic\WooCommerce\Admin\Notes\UnsecuredReportFiles;
|
||||
use \Automattic\WooCommerce\Admin\Notes\DeactivatePlugin;
|
||||
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 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update DB Version.
|
||||
*/
|
||||
function wc_admin_update_0201_db_version() {
|
||||
Installer::update_db_version( '0.20.1' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update DB Version.
|
||||
*/
|
||||
function wc_admin_update_0230_db_version() {
|
||||
Installer::update_db_version( '0.23.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update DB Version.
|
||||
*/
|
||||
function wc_admin_update_0251_db_version() {
|
||||
Installer::update_db_version( '0.25.1' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Facebook Extension note.
|
||||
*/
|
||||
function wc_admin_update_110_remove_facebook_note() {
|
||||
Notes::delete_notes_with_name( 'wc-admin-facebook-extension' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update DB Version.
|
||||
*/
|
||||
function wc_admin_update_110_db_version() {
|
||||
Installer::update_db_version( '1.1.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the deactivate plugin note type to 'info'.
|
||||
*/
|
||||
function wc_admin_update_140_change_deactivate_plugin_note_type() {
|
||||
global $wpdb;
|
||||
|
||||
$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}wc_admin_notes SET type = 'info' WHERE name = %s", DeactivatePlugin::NOTE_NAME ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update DB Version.
|
||||
*/
|
||||
function wc_admin_update_160_db_version() {
|
||||
Installer::update_db_version( '1.6.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update DB Version.
|
||||
*/
|
||||
function wc_admin_update_170_db_version() {
|
||||
Installer::update_db_version( '1.7.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 DB Version.
|
||||
*/
|
||||
function wc_admin_update_270_db_version() {
|
||||
Installer::update_db_version( '2.7.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 DB Version.
|
||||
*/
|
||||
function wc_admin_update_271_db_version() {
|
||||
Installer::update_db_version( '2.7.1' );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 DB Version.
|
||||
*/
|
||||
function wc_admin_update_280_db_version() {
|
||||
Installer::update_db_version( '2.8.0' );
|
||||
}
|
Reference in New Issue
Block a user