plugin updates
This commit is contained in:
@@ -100,11 +100,6 @@ class Init {
|
||||
'Automattic\WooCommerce\Admin\API\ShippingPartnerSuggestions',
|
||||
);
|
||||
|
||||
$product_form_controllers = array();
|
||||
if ( Features::is_enabled( 'new-product-management-experience' ) ) {
|
||||
$product_form_controllers[] = 'Automattic\WooCommerce\Admin\API\ProductForm';
|
||||
}
|
||||
|
||||
if ( Features::is_enabled( 'launch-your-store' ) ) {
|
||||
$controllers[] = 'Automattic\WooCommerce\Admin\API\LaunchYourStore';
|
||||
}
|
||||
@@ -138,7 +133,7 @@ class Init {
|
||||
|
||||
// The performance indicators controller must be registered last, after other /stats endpoints have been registered.
|
||||
$analytics_controllers[] = 'Automattic\WooCommerce\Admin\API\Reports\PerformanceIndicators\Controller';
|
||||
$controllers = array_merge( $controllers, $analytics_controllers, $product_form_controllers );
|
||||
$controllers = array_merge( $controllers, $analytics_controllers );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,6 +65,42 @@ class LaunchYourStore {
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/survey-completed',
|
||||
array(
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
'callback' => array( $this, 'has_survey_completed' ),
|
||||
'permission_callback' => array( $this, 'must_be_shop_manager_or_admin' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/woopayments/test-orders/count',
|
||||
array(
|
||||
array(
|
||||
'methods' => 'GET',
|
||||
'callback' => array( $this, 'get_woopay_test_orders_count' ),
|
||||
'permission_callback' => array( $this, 'must_be_shop_manager_or_admin' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/woopayments/test-orders',
|
||||
array(
|
||||
array(
|
||||
'methods' => 'DELETE',
|
||||
'callback' => array( $this, 'delete_woopay_test_orders' ),
|
||||
'permission_callback' => array( $this, 'must_be_shop_manager_or_admin' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,6 +150,55 @@ class LaunchYourStore {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the test orders created during Woo Payments test mode.
|
||||
*
|
||||
* @return \WP_REST_Response
|
||||
*/
|
||||
public function get_woopay_test_orders_count() {
|
||||
$return = function ( $count ) {
|
||||
return new \WP_REST_Response( array( 'count' => $count ) );
|
||||
};
|
||||
|
||||
$orders = wc_get_orders(
|
||||
array(
|
||||
// phpcs:ignore
|
||||
'meta_key' => '_wcpay_mode',
|
||||
// phpcs:ignore
|
||||
'meta_value' => 'test',
|
||||
'return' => 'ids',
|
||||
)
|
||||
);
|
||||
|
||||
return $return( count( $orders ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete WooPayments test orders.
|
||||
*
|
||||
* @return \WP_REST_Response
|
||||
*/
|
||||
public function delete_woopay_test_orders() {
|
||||
$return = function ( $status = 204 ) {
|
||||
return new \WP_REST_Response( null, $status );
|
||||
};
|
||||
|
||||
$orders = wc_get_orders(
|
||||
array(
|
||||
// phpcs:ignore
|
||||
'meta_key' => '_wcpay_mode',
|
||||
// phpcs:ignore
|
||||
'meta_value' => 'test',
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $orders as $order ) {
|
||||
$order->delete();
|
||||
}
|
||||
|
||||
return $return();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update woocommerce_admin_launch_your_store_survey_completed to yes or no
|
||||
*
|
||||
@@ -125,4 +210,13 @@ class LaunchYourStore {
|
||||
update_option( 'woocommerce_admin_launch_your_store_survey_completed', $request->get_param( 'status' ) );
|
||||
return new \WP_REST_Response();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return woocommerce_admin_launch_your_store_survey_completed option.
|
||||
*
|
||||
* @return \WP_REST_Response
|
||||
*/
|
||||
public function has_survey_completed() {
|
||||
return new \WP_REST_Response( get_option( 'woocommerce_admin_launch_your_store_survey_completed', 'no' ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +255,8 @@ class OnboardingThemes extends \WC_REST_Data_Controller {
|
||||
$core_themes = array(
|
||||
array(
|
||||
'name' => 'Twenty Twenty-Four',
|
||||
'price' => 'Free',
|
||||
'price' => __( 'Free', 'woocommerce' ),
|
||||
'is_free' => true,
|
||||
'color_palettes' => array(
|
||||
array(
|
||||
'title' => 'Black and white',
|
||||
@@ -285,7 +286,9 @@ class OnboardingThemes extends \WC_REST_Data_Controller {
|
||||
),
|
||||
array(
|
||||
'name' => 'Highline',
|
||||
'price' => '$79/year',
|
||||
/* translators: %d: price */
|
||||
'price' => sprintf( __( '$%d/year', 'woocommerce' ), 79 ),
|
||||
'is_free' => false,
|
||||
'color_palettes' => array(
|
||||
array(
|
||||
'title' => 'Primary',
|
||||
@@ -315,7 +318,9 @@ class OnboardingThemes extends \WC_REST_Data_Controller {
|
||||
),
|
||||
array(
|
||||
'name' => 'Luminate',
|
||||
'price' => '$79/year',
|
||||
/* translators: %d: price */
|
||||
'price' => sprintf( __( '$%d/year', 'woocommerce' ), 79 ),
|
||||
'is_free' => false,
|
||||
'color_palettes' => array(
|
||||
array(
|
||||
'title' => 'Primary',
|
||||
@@ -345,7 +350,9 @@ class OnboardingThemes extends \WC_REST_Data_Controller {
|
||||
),
|
||||
array(
|
||||
'name' => 'Nokul',
|
||||
'price' => '$79/year',
|
||||
/* translators: %d: price */
|
||||
'price' => sprintf( __( '$%d/year', 'woocommerce' ), 79 ),
|
||||
'is_free' => false,
|
||||
'color_palettes' => array(
|
||||
array(
|
||||
'title' => 'Foreground and background',
|
||||
@@ -380,7 +387,8 @@ class OnboardingThemes extends \WC_REST_Data_Controller {
|
||||
$default_themes = array(
|
||||
array(
|
||||
'name' => 'Tsubaki',
|
||||
'price' => 'Free',
|
||||
'price' => __( 'Free', 'woocommerce' ),
|
||||
'is_free' => true,
|
||||
'color_palettes' => array(),
|
||||
'total_palettes' => 0,
|
||||
'slug' => 'tsubaki',
|
||||
@@ -389,7 +397,8 @@ class OnboardingThemes extends \WC_REST_Data_Controller {
|
||||
),
|
||||
array(
|
||||
'name' => 'Tazza',
|
||||
'price' => 'Free',
|
||||
'price' => __( 'Free', 'woocommerce' ),
|
||||
'is_free' => true,
|
||||
'color_palettes' => array(),
|
||||
'total_palettes' => 0,
|
||||
'slug' => 'tazza',
|
||||
@@ -398,7 +407,8 @@ class OnboardingThemes extends \WC_REST_Data_Controller {
|
||||
),
|
||||
array(
|
||||
'name' => 'Amulet',
|
||||
'price' => 'Free',
|
||||
'price' => __( 'Free', 'woocommerce' ),
|
||||
'is_free' => true,
|
||||
'color_palettes' => array(
|
||||
array(
|
||||
'title' => 'Default',
|
||||
@@ -428,7 +438,8 @@ class OnboardingThemes extends \WC_REST_Data_Controller {
|
||||
),
|
||||
array(
|
||||
'name' => 'Zaino',
|
||||
'price' => 'Free',
|
||||
'price' => __( 'Free', 'woocommerce' ),
|
||||
'is_free' => true,
|
||||
'color_palettes' => array(
|
||||
array(
|
||||
'title' => 'Default',
|
||||
@@ -578,6 +589,10 @@ class OnboardingThemes extends \WC_REST_Data_Controller {
|
||||
'type' => 'string',
|
||||
'description' => 'Price',
|
||||
),
|
||||
'is_free' => array(
|
||||
'type' => 'boolean',
|
||||
'description' => 'Whether theme is free',
|
||||
),
|
||||
'is_active' => array(
|
||||
'type' => 'boolean',
|
||||
'description' => 'Whether theme is active',
|
||||
|
||||
@@ -168,21 +168,17 @@ class Options extends \WC_REST_Data_Controller {
|
||||
'woocommerce_shipping_dismissed_timestamp',
|
||||
'woocommerce_allow_tracking',
|
||||
'woocommerce_task_list_keep_completed',
|
||||
'woocommerce_task_list_prompt_shown',
|
||||
'woocommerce_default_homepage_layout',
|
||||
'woocommerce_setup_jetpack_opted_in',
|
||||
'woocommerce_no_sales_tax',
|
||||
'woocommerce_calc_taxes',
|
||||
'woocommerce_bacs_settings',
|
||||
'woocommerce_bacs_accounts',
|
||||
'woocommerce_task_list_prompt_shown',
|
||||
'woocommerce_settings_shipping_recommendations_hidden',
|
||||
'woocommerce_task_list_dismissed_tasks',
|
||||
'woocommerce_setting_payments_recommendations_hidden',
|
||||
'woocommerce_navigation_favorites_tooltip_hidden',
|
||||
'woocommerce_admin_transient_notices_queue',
|
||||
'woocommerce_task_list_welcome_modal_dismissed',
|
||||
'woocommerce_welcome_from_calypso_modal_dismissed',
|
||||
'woocommerce_task_list_hidden',
|
||||
'woocommerce_task_list_complete',
|
||||
'woocommerce_extended_task_list_hidden',
|
||||
@@ -198,6 +194,7 @@ class Options extends \WC_REST_Data_Controller {
|
||||
'woocommerce_admin_reviewed_store_location_settings',
|
||||
'woocommerce_ces_product_feedback_shown',
|
||||
'woocommerce_marketing_overview_multichannel_banner_dismissed',
|
||||
'woocommerce_manage_stock',
|
||||
'woocommerce_dimension_unit',
|
||||
'woocommerce_weight_unit',
|
||||
'woocommerce_product_editor_show_feedback_bar',
|
||||
|
||||
@@ -39,7 +39,6 @@ class Features {
|
||||
*/
|
||||
protected static $beta_features = array(
|
||||
'navigation',
|
||||
'new-product-management-experience',
|
||||
'settings',
|
||||
);
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ class LaunchYourStore {
|
||||
$link
|
||||
);
|
||||
// phpcs:ignore
|
||||
echo "<div id='coming-soon-footer-banner'>$text<a class='coming-soon-footer-banner-dismiss' data-rest-url='$rest_url' data-rest-nonce='$rest_nonce'></a></div>";
|
||||
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>";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -213,17 +213,6 @@ class CoreMenu {
|
||||
);
|
||||
}
|
||||
|
||||
$add_product_mvp = array();
|
||||
if ( Features::is_enabled( 'new-product-management-experience' ) ) {
|
||||
$add_product_mvp = array(
|
||||
'id' => 'woocommerce-add-product-mbp',
|
||||
'title' => __( 'Add New (MVP)', 'woocommerce' ),
|
||||
'url' => 'admin.php?page=wc-admin&path=/add-product',
|
||||
'parent' => 'woocommerce-products',
|
||||
'order' => 50,
|
||||
);
|
||||
}
|
||||
|
||||
return array_merge(
|
||||
array(
|
||||
$home_item,
|
||||
@@ -253,7 +242,6 @@ class CoreMenu {
|
||||
'menuId' => 'secondary',
|
||||
'order' => 10,
|
||||
),
|
||||
$add_product_mvp,
|
||||
),
|
||||
// Tools category.
|
||||
self::get_tool_items(),
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce New Product Management Experience
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\Features;
|
||||
|
||||
use Automattic\WooCommerce\Admin\Features\TransientNotices;
|
||||
use Automattic\WooCommerce\Admin\PageController;
|
||||
use Automattic\WooCommerce\Internal\Admin\Loader;
|
||||
use WP_Block_Editor_Context;
|
||||
|
||||
/**
|
||||
* Loads assets related to the new product management experience page.
|
||||
*/
|
||||
class NewProductManagementExperience {
|
||||
|
||||
/**
|
||||
* Option name used to toggle this feature.
|
||||
*/
|
||||
const TOGGLE_OPTION_NAME = 'woocommerce_new_product_management_enabled';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->maybe_show_disabled_notice();
|
||||
if ( ! Features::is_enabled( 'new-product-management-experience' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
|
||||
add_action( 'get_edit_post_link', array( $this, 'update_edit_product_link' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe show disabled notice.
|
||||
*/
|
||||
public function maybe_show_disabled_notice() {
|
||||
$new_product_experience_param = 'new-product-experience-disabled';
|
||||
if ( isset( $_GET[ $new_product_experience_param ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
TransientNotices::add(
|
||||
array(
|
||||
'user_id' => get_current_user_id(),
|
||||
'id' => 'new-product-experience-disbled',
|
||||
'status' => 'success',
|
||||
'content' => __( '🌟 Thanks for the feedback. We’ll put it to good use!', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
||||
$url = isset( $_SERVER['REQUEST_URI'] ) ? wc_clean( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
|
||||
$url = remove_query_arg( 'new-product-experience-disabled', $url );
|
||||
wp_safe_redirect( $url );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue styles needed for the rich text editor.
|
||||
*/
|
||||
public function enqueue_styles() {
|
||||
if ( ! PageController::is_admin_or_embed_page() ) {
|
||||
return;
|
||||
}
|
||||
wp_enqueue_style( 'wp-edit-blocks' );
|
||||
wp_enqueue_style( 'wp-format-library' );
|
||||
wp_enqueue_editor();
|
||||
/**
|
||||
* Enqueue any block editor related assets.
|
||||
*
|
||||
* @since 7.1.0
|
||||
*/
|
||||
do_action( 'enqueue_block_editor_assets' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the edit product links when the new experience is enabled.
|
||||
*
|
||||
* @param string $link The edit link.
|
||||
* @param int $post_id Post ID.
|
||||
* @return string
|
||||
*/
|
||||
public function update_edit_product_link( $link, $post_id ) {
|
||||
$product = wc_get_product( $post_id );
|
||||
|
||||
if ( ! $product ) {
|
||||
return $link;
|
||||
}
|
||||
|
||||
if ( $product->get_type() === 'simple' ) {
|
||||
return admin_url( 'admin.php?page=wc-admin&path=/product/' . $product->get_id() );
|
||||
}
|
||||
|
||||
return $link;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor;
|
||||
|
||||
use Automattic\WooCommerce\LayoutTemplates\LayoutTemplateRegistry;
|
||||
|
||||
/**
|
||||
* Utils for block templates.
|
||||
*/
|
||||
class BlockTemplateUtils {
|
||||
/**
|
||||
* Directory which contains all templates
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TEMPLATES_ROOT_DIR = 'templates';
|
||||
|
||||
/**
|
||||
* Directory names.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
const DIRECTORY_NAMES = array(
|
||||
'TEMPLATES' => 'product-form',
|
||||
'TEMPLATE_PARTS' => 'product-form/parts',
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets the directory where templates of a specific template type can be found.
|
||||
*
|
||||
* @param string $template_type wp_template or wp_template_part.
|
||||
* @return string
|
||||
*/
|
||||
private static function get_templates_directory( $template_type = 'wp_template' ) {
|
||||
$root_path = dirname( __DIR__, 4 ) . '/' . self::TEMPLATES_ROOT_DIR . DIRECTORY_SEPARATOR;
|
||||
$templates_directory = $root_path . self::DIRECTORY_NAMES['TEMPLATES'];
|
||||
$template_parts_directory = $root_path . self::DIRECTORY_NAMES['TEMPLATE_PARTS'];
|
||||
|
||||
if ( 'wp_template_part' === $template_type ) {
|
||||
return $template_parts_directory;
|
||||
}
|
||||
|
||||
return $templates_directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path to a block template file.
|
||||
* Otherwise, False.
|
||||
*
|
||||
* @param string $slug - Template slug.
|
||||
* @return string|bool Path to the template file or false.
|
||||
*/
|
||||
public static function get_block_template_path( $slug ) {
|
||||
$directory = self::get_templates_directory();
|
||||
$path = trailingslashit( $directory ) . $slug . '.php';
|
||||
|
||||
if ( ! file_exists( $path ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the template data from the headers.
|
||||
*
|
||||
* @param string $file_path - File path.
|
||||
* @return array Template data.
|
||||
*/
|
||||
public static function get_template_file_data( $file_path ) {
|
||||
if ( ! file_exists( $file_path ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$file_data = get_file_data(
|
||||
$file_path,
|
||||
array(
|
||||
'title' => 'Title',
|
||||
'slug' => 'Slug',
|
||||
'description' => 'Description',
|
||||
'product_types' => 'Product Types',
|
||||
),
|
||||
);
|
||||
|
||||
$file_data['product_types'] = explode( ',', trim( $file_data['product_types'] ) );
|
||||
|
||||
return $file_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the template content from the file.
|
||||
*
|
||||
* @param string $file_path - File path.
|
||||
* @return string Content.
|
||||
*/
|
||||
public static function get_template_content( $file_path ) {
|
||||
if ( ! file_exists( $file_path ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
ob_start();
|
||||
include $file_path;
|
||||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ use Automattic\WooCommerce\LayoutTemplates\LayoutTemplateRegistry;
|
||||
|
||||
use Automattic\WooCommerce\Internal\Features\ProductBlockEditor\ProductTemplates\SimpleProductTemplate;
|
||||
use Automattic\WooCommerce\Internal\Features\ProductBlockEditor\ProductTemplates\ProductVariationTemplate;
|
||||
|
||||
use WC_Meta_Data;
|
||||
use WP_Block_Editor_Context;
|
||||
|
||||
/**
|
||||
@@ -56,11 +56,10 @@ class Init {
|
||||
$this->redirection_controller = new RedirectionController();
|
||||
|
||||
if ( \Automattic\WooCommerce\Utilities\FeaturesUtil::feature_is_enabled( 'product_block_editor' ) ) {
|
||||
if ( ! Features::is_enabled( 'new-product-management-experience' ) ) {
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'dequeue_conflicting_styles' ), 100 );
|
||||
add_action( 'get_edit_post_link', array( $this, 'update_edit_product_link' ), 10, 2 );
|
||||
}
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'dequeue_conflicting_styles' ), 100 );
|
||||
add_action( 'get_edit_post_link', array( $this, 'update_edit_product_link' ), 10, 2 );
|
||||
|
||||
add_filter( 'woocommerce_admin_get_user_data_fields', array( $this, 'add_user_data_fields' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
||||
add_filter( 'woocommerce_register_post_type_product_variation', array( $this, 'enable_rest_api_for_product_variation' ) );
|
||||
@@ -73,6 +72,9 @@ class Init {
|
||||
add_filter( 'register_block_type_args', array( $this, 'register_metadata_attribute' ) );
|
||||
add_filter( 'woocommerce_get_block_types', array( $this, 'get_block_types' ), 999, 1 );
|
||||
|
||||
add_filter( 'woocommerce_rest_prepare_product_object', array( $this, 'possibly_add_template_id' ), 10, 2 );
|
||||
add_filter( 'woocommerce_rest_prepare_product_variation_object', array( $this, 'possibly_add_template_id' ), 10, 2 );
|
||||
|
||||
// Make sure the block registry is initialized so that core blocks are registered.
|
||||
BlockRegistry::get_instance();
|
||||
|
||||
@@ -83,6 +85,37 @@ class Init {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the product template ID to the product if it doesn't exist.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param WC_Product $product The product.
|
||||
*/
|
||||
public function possibly_add_template_id( $response, $product ) {
|
||||
if ( ! $product ) {
|
||||
return $response;
|
||||
}
|
||||
if ( ! $product->meta_exists( '_product_template_id' ) ) {
|
||||
/**
|
||||
* Experimental: Allows to determine a product template id based on the product data.
|
||||
*
|
||||
* @ignore
|
||||
* @since 9.1.0
|
||||
*/
|
||||
$product_template_id = apply_filters( 'experimental_woocommerce_product_editor_product_template_id_for_product', '', $product );
|
||||
if ( $product_template_id ) {
|
||||
$response->data['meta_data'][] = new WC_Meta_Data(
|
||||
array(
|
||||
'key' => '_product_template_id',
|
||||
'value' => $product_template_id,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue scripts needed for the product form block editor.
|
||||
*/
|
||||
@@ -377,6 +410,12 @@ class Init {
|
||||
);
|
||||
|
||||
$this->redirection_controller->set_product_templates( $this->product_templates );
|
||||
|
||||
// PFT: Initialize the product form controller.
|
||||
if ( Features::is_enabled( 'product-editor-template-system' ) ) {
|
||||
$product_form_controller = new ProductFormsController();
|
||||
$product_form_controller->init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
/**
|
||||
* WooCommerce Product Forms Controller
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\Features\ProductBlockEditor;
|
||||
|
||||
/**
|
||||
* Handle retrieval of product forms.
|
||||
*/
|
||||
class ProductFormsController {
|
||||
|
||||
/**
|
||||
* Product form templates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $product_form_templates = array(
|
||||
'simple',
|
||||
);
|
||||
|
||||
/**
|
||||
* Set up the product forms controller.
|
||||
*/
|
||||
public function init() { // phpcs:ignore WooCommerce.Functions.InternalInjectionMethod.MissingFinal, WooCommerce.Functions.InternalInjectionMethod.MissingInternalTag -- Not an injection.
|
||||
add_action( 'upgrader_process_complete', array( $this, 'migrate_templates_when_plugin_updated' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate form templates after WooCommerce plugin update.
|
||||
*
|
||||
* @param \WP_Upgrader $upgrader The WP_Upgrader instance.
|
||||
* @param array $hook_extra Extra arguments passed to hooked filters.
|
||||
* @return void
|
||||
*/
|
||||
public function migrate_templates_when_plugin_updated( \WP_Upgrader $upgrader, array $hook_extra ) {
|
||||
// If it is not a plugin hook type, bail early.
|
||||
$type = isset( $hook_extra['type'] ) ? $hook_extra['type'] : '';
|
||||
if ( 'plugin' !== $type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If it is not the WooCommerce plugin, bail early.
|
||||
$plugins = isset( $hook_extra['plugins'] ) ? $hook_extra['plugins'] : array();
|
||||
if (
|
||||
! in_array( 'woocommerce/woocommerce.php', $plugins, true )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the action is not install or update, bail early.
|
||||
$action = isset( $hook_extra['action'] ) ? $hook_extra['action'] : '';
|
||||
if ( 'install' !== $action && 'update' !== $action ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger the migration process.
|
||||
$this->migrate_product_form_posts( $action );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create ot update a product_form post for each product form template.
|
||||
* If the post already exists, it will be updated.
|
||||
* If the post does not exist, it will be created even if the action is `update`.
|
||||
*
|
||||
* @param string $action - The action to perform. `insert` | `update`.
|
||||
* @return void
|
||||
*/
|
||||
public function migrate_product_form_posts( $action ) {
|
||||
/**
|
||||
* Allow extend the list of templates that should be auto-generated.
|
||||
*
|
||||
* @since 9.1.0
|
||||
* @param array $templates List of templates to auto-generate.
|
||||
*/
|
||||
$templates = apply_filters(
|
||||
'woocommerce_product_form_templates',
|
||||
$this->product_form_templates
|
||||
);
|
||||
|
||||
foreach ( $templates as $slug ) {
|
||||
$file_path = BlockTemplateUtils::get_block_template_path( $slug );
|
||||
|
||||
if ( ! $file_path ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$file_data = BlockTemplateUtils::get_template_file_data( $file_path );
|
||||
|
||||
$posts = get_posts(
|
||||
array(
|
||||
'name' => $slug,
|
||||
'post_type' => 'product_form',
|
||||
'post_status' => 'any',
|
||||
'posts_per_page' => 1,
|
||||
)
|
||||
);
|
||||
|
||||
/*
|
||||
* Update the the CPT post if it already exists,
|
||||
* and the action is `update`.
|
||||
*/
|
||||
if ( 'update' === $action ) {
|
||||
$post = $posts[0] ?? null;
|
||||
|
||||
if ( ! empty( $post ) ) {
|
||||
wp_update_post(
|
||||
array(
|
||||
'ID' => $post->ID,
|
||||
'post_title' => $file_data['title'],
|
||||
'post_content' => BlockTemplateUtils::get_template_content( $file_path ),
|
||||
'post_excerpt' => $file_data['description'],
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip the post creation if the post already exists.
|
||||
*/
|
||||
if ( ! empty( $posts ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$post = wp_insert_post(
|
||||
array(
|
||||
'post_title' => $file_data['title'],
|
||||
'post_name' => $slug,
|
||||
'post_status' => 'publish',
|
||||
'post_type' => 'product_form',
|
||||
'post_content' => BlockTemplateUtils::get_template_content( $file_path ),
|
||||
'post_excerpt' => $file_data['description'],
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,28 +59,28 @@ class DefaultShippingPartners {
|
||||
array(
|
||||
'icon' => $check_icon,
|
||||
'description' => __(
|
||||
'Print labels from Royal Mail, Parcel Force, DPD, and many more',
|
||||
'Discounted labels from top global carriers',
|
||||
'woocommerce'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'icon' => $check_icon,
|
||||
'description' => __(
|
||||
'Shop for the best rates, in real-time',
|
||||
'Sync all your selling channels in one place',
|
||||
'woocommerce'
|
||||
),
|
||||
),
|
||||
array(
|
||||
'icon' => $check_icon,
|
||||
'description' => __( 'Connect selling channels easily', 'woocommerce' ),
|
||||
'description' => __( 'Advanced automated workflows and customs', 'woocommerce' ),
|
||||
),
|
||||
array(
|
||||
'icon' => $check_icon,
|
||||
'description' => __( 'Advance automated workflows', 'woocommerce' ),
|
||||
'description' => __( 'Instantly send tracking to your customers', 'woocommerce' ),
|
||||
),
|
||||
array(
|
||||
'icon' => $check_icon,
|
||||
'description' => __( '30-days free trial', 'woocommerce' ),
|
||||
'description' => __( '30-day free trial', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -821,6 +821,35 @@ class PluginsHelper {
|
||||
|
||||
$total_expiring_subscriptions = count( $expiring_subscriptions );
|
||||
|
||||
// When payment method is missing on WooCommerce.com.
|
||||
$helper_notices = WC_Helper::get_notices();
|
||||
if ( ! empty( $helper_notices['missing_payment_method_notice'] ) ) {
|
||||
$description = $allowed_link
|
||||
? sprintf(
|
||||
/* translators: %s: WooCommerce.com URL to add payment method */
|
||||
_n(
|
||||
'Your WooCommerce extension subscription is missing a payment method for renewal. <a href="%s">Add a payment method</a> to ensure you continue receiving updates and streamlined support.',
|
||||
'Your WooCommerce extension subscriptions are missing a payment method for renewal. <a href="%s">Add a payment method</a> to ensure you continue receiving updates and streamlined support.',
|
||||
$total_expiring_subscriptions,
|
||||
'woocommerce'
|
||||
),
|
||||
'https://woocommerce.com/my-account/add-payment-method/'
|
||||
)
|
||||
: _n(
|
||||
'Your WooCommerce extension subscription is missing a payment method for renewal. Add a payment method to ensure you continue receiving updates and streamlined support.',
|
||||
'Your WooCommerce extension subscriptions are missing a payment method for renewal. Add a payment method to ensure you continue receiving updates and streamlined support.',
|
||||
$total_expiring_subscriptions,
|
||||
'woocommerce'
|
||||
);
|
||||
|
||||
return array(
|
||||
'description' => $description,
|
||||
'button_text' => __( 'Add payment method', 'woocommerce' ),
|
||||
'button_link' => 'https://woocommerce.com/my-account/add-payment-method/',
|
||||
);
|
||||
}
|
||||
|
||||
// Payment method is available but there are expiring subscriptions.
|
||||
$notice_data = self::get_subscriptions_notice_data(
|
||||
$subscriptions,
|
||||
$expiring_subscriptions,
|
||||
|
||||
@@ -133,7 +133,7 @@ class AsyncPluginsInstallLogger implements PluginsInstallLogger {
|
||||
'coreprofiler_store_extension_installed_and_activated',
|
||||
array(
|
||||
'success' => false,
|
||||
'extension' => $plugin_name,
|
||||
'extension' => $this->get_plugin_track_key( $plugin_name ),
|
||||
'error_message' => $error_message,
|
||||
)
|
||||
);
|
||||
@@ -173,37 +173,37 @@ class AsyncPluginsInstallLogger implements PluginsInstallLogger {
|
||||
* @return string - Time frame.
|
||||
*/
|
||||
function get_timeframe( $timeInMs ) {
|
||||
$time_frames = [
|
||||
[
|
||||
$time_frames = array(
|
||||
array(
|
||||
'name' => '0-2s',
|
||||
'max' => 2,
|
||||
],
|
||||
[
|
||||
),
|
||||
array(
|
||||
'name' => '2-5s',
|
||||
'max' => 5,
|
||||
],
|
||||
[
|
||||
),
|
||||
array(
|
||||
'name' => '5-10s',
|
||||
'max' => 10,
|
||||
],
|
||||
[
|
||||
),
|
||||
array(
|
||||
'name' => '10-15s',
|
||||
'max' => 15,
|
||||
],
|
||||
[
|
||||
),
|
||||
array(
|
||||
'name' => '15-20s',
|
||||
'max' => 20,
|
||||
],
|
||||
[
|
||||
),
|
||||
array(
|
||||
'name' => '20-30s',
|
||||
'max' => 30,
|
||||
],
|
||||
[
|
||||
),
|
||||
array(
|
||||
'name' => '30-60s',
|
||||
'max' => 60,
|
||||
],
|
||||
[ 'name' => '>60s' ],
|
||||
];
|
||||
),
|
||||
array( 'name' => '>60s' ),
|
||||
);
|
||||
|
||||
foreach ( $time_frames as $time_frame ) {
|
||||
if ( ! isset( $time_frame['max'] ) ) {
|
||||
@@ -219,7 +219,7 @@ class AsyncPluginsInstallLogger implements PluginsInstallLogger {
|
||||
$track_data = array(
|
||||
'success' => true,
|
||||
'installed_extensions' => array_map(
|
||||
function( $extension ) {
|
||||
function ( $extension ) {
|
||||
return $this->get_plugin_track_key( $extension );
|
||||
},
|
||||
$data['installed']
|
||||
|
||||
@@ -168,6 +168,18 @@ class WCAdminHelper {
|
||||
*/
|
||||
$store_pages = apply_filters( 'woocommerce_store_pages', $store_pages );
|
||||
|
||||
// If the shop page is not set, we will still show the product archive page.
|
||||
// Therefore, we need to check if the URL is a product archive page when the shop page is not set.
|
||||
if ( $store_pages['shop'] <= 0 ) {
|
||||
$product_post_archive_link = get_post_type_archive_link( 'product' );
|
||||
|
||||
if ( is_string( $product_post_archive_link ) &&
|
||||
0 === strpos( $normalized_path, self::get_normalized_url_path( $product_post_archive_link ) )
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( $store_pages as $page => $page_id ) {
|
||||
if ( 0 >= $page_id ) {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user