Publishing product in classic editor redirects back to new editor (#38551)

* Changes the feature given it's id and a toggle value as a query param

* Swap classic editor and new product block editor url when product_block_editor feature changes

* Turn off the product_block_editor feature when user choose to use the classic editor

* Add changelog files

* Fix linter errors

* Add nonce to each feature change request

* Change the hooks name for better readability

* Use get_current_screen function to better identify if the current screen is the product creation or edition

* Add wp_die if the nonce verification failed

* Change regex for explode/parse_url for better reading
This commit is contained in:
Maikel David Pérez Gómez 2023-06-09 11:18:40 -04:00 committed by GitHub
parent 55faf9dcda
commit 72f7e6ebbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 125 additions and 12 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Turn off the product_block_editor feature when user choose to use the classic editor

View File

@ -5,7 +5,7 @@ import { useDispatch, useSelect } from '@wordpress/data';
import { createElement } from '@wordpress/element';
import { STORE_KEY } from '@woocommerce/customer-effort-score';
import { recordEvent } from '@woocommerce/tracks';
import { getAdminLink } from '@woocommerce/settings';
import { getAdminLink, getSetting } from '@woocommerce/settings';
import { useFormContext } from '@woocommerce/components';
import { Product } from '@woocommerce/data';
@ -28,9 +28,18 @@ export const ProductMVPFeedbackModalContainer: React.FC< {
const productId = _productId ?? values.id;
const { _feature_nonce } = getSetting< { _feature_nonce: string } >(
'admin',
{}
);
const classicEditorUrl = productId
? getAdminLink( `post.php?post=${ productId }&action=edit` )
: getAdminLink( 'post-new.php?post_type=product' );
? getAdminLink(
`post.php?post=${ productId }&action=edit&product_block_editor=0&_feature_nonce=${ _feature_nonce }`
)
: getAdminLink(
`post-new.php?post_type=product&product_block_editor=0&_feature_nonce=${ _feature_nonce }`
);
const recordScore = ( checked: string[], comments: string ) => {
recordEvent( 'product_mvp_feedback', {

View File

@ -10,12 +10,12 @@ import {
ALLOW_TRACKING_OPTION_NAME,
STORE_KEY as CES_STORE_KEY,
} from '@woocommerce/customer-effort-score';
import { NEW_PRODUCT_MANAGEMENT_ENABLED_OPTION_NAME } from '@woocommerce/product-editor';
/**
* Internal dependencies
*/
import { ClassicEditorIcon } from '../../images/classic-editor-icon';
import { getAdminSetting } from '~/utils/admin-settings';
export const ClassicEditorMenuItem = ( {
onClose,
@ -25,7 +25,6 @@ export const ClassicEditorMenuItem = ( {
onClose: () => void;
} ) => {
const { showProductMVPFeedbackModal } = useDispatch( CES_STORE_KEY );
const { updateOptions } = useDispatch( OPTIONS_STORE_NAME );
const { allowTracking, resolving: isLoading } = useSelect( ( select ) => {
const { getOption, hasFinishedResolution } =
@ -44,9 +43,15 @@ export const ClassicEditorMenuItem = ( {
};
} );
const { _feature_nonce } = getAdminSetting( '_feature_nonce' );
const classicEditorUrl = productId
? getAdminLink( `post.php?post=${ productId }&action=edit` )
: getAdminLink( 'post-new.php?post_type=product' );
? getAdminLink(
`post.php?post=${ productId }&action=edit&product_block_editor=0&_feature_nonce=${ _feature_nonce }`
)
: getAdminLink(
`post-new.php?post_type=product&product_block_editor=0&_feature_nonce=${ _feature_nonce }`
);
if ( isLoading ) {
return null;
@ -56,15 +61,11 @@ export const ClassicEditorMenuItem = ( {
<MenuItem
onClick={ () => {
if ( allowTracking ) {
updateOptions( {
[ NEW_PRODUCT_MANAGEMENT_ENABLED_OPTION_NAME ]: 'no',
} );
showProductMVPFeedbackModal();
onClose();
} else {
window.location.href = classicEditorUrl;
onClose();
}
onClose();
} }
icon={ <ClassicEditorIcon /> }
iconPosition="right"

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add support to change features through the url as query parameters

View File

@ -37,6 +37,56 @@ class Init {
$block_registry = new BlockRegistry();
$block_registry->init();
}
add_action( 'current_screen', array( $this, 'maybe_redirect_to_new_editor' ), 30, 0 );
add_action( 'current_screen', array( $this, 'maybe_redirect_to_old_editor' ), 30, 0 );
}
/**
* Redirects from old product form to the new product form if the
* feature `product_block_editor` is enabled.
*/
public function maybe_redirect_to_new_editor(): void {
if ( \Automattic\WooCommerce\Utilities\FeaturesUtil::feature_is_enabled( 'product_block_editor' ) ) {
$screen = get_current_screen();
if ( 'post' === $screen->base && 'product' === $screen->post_type ) {
if ( 'add' === $screen->action ) {
wp_safe_redirect( admin_url( 'admin.php?page=wc-admin&path=/add-product' ) );
exit();
}
if ( isset( $_GET['post'] ) && isset( $_GET['action'] ) && 'edit' === $_GET['action'] ) {
$product_id = absint( $_GET['post'] );
wp_safe_redirect( admin_url( 'admin.php?page=wc-admin&path=/product/' . $product_id ) );
exit();
}
}
}
}
/**
* Redirects from new product form to the old product form if the
* feature `product_block_editor` is enabled.
*/
public function maybe_redirect_to_old_editor(): void {
if ( ! \Automattic\WooCommerce\Utilities\FeaturesUtil::feature_is_enabled( 'product_block_editor' ) ) {
if ( \Automattic\WooCommerce\Admin\PageController::is_admin_page() && isset( $_GET['path'] ) ) {
$path = esc_url_raw( wp_unslash( $_GET['path'] ) );
$parsed_path = explode( '/', wp_parse_url( $path, PHP_URL_PATH ) );
if ( 'add-product' === $parsed_path[1] ) {
wp_safe_redirect( admin_url( 'post-new.php?post_type=product' ) );
exit();
}
if ( 'product' === $parsed_path[1] ) {
$product_id = absint( $parsed_path[2] );
wp_safe_redirect( admin_url( 'post.php?post=' . $product_id . '&action=edit' ) );
exit();
}
}
}
}
/**

View File

@ -137,6 +137,8 @@ class FeaturesController {
self::add_action( 'after_plugin_row', array( $this, 'handle_plugin_list_rows' ), 10, 2 );
self::add_action( 'current_screen', array( $this, 'enqueue_script_to_fix_plugin_list_html' ), 10, 1 );
self::add_filter( 'views_plugins', array( $this, 'handle_plugins_page_views_list' ), 10, 1 );
self::add_filter( 'woocommerce_admin_shared_settings', array( $this, 'set_change_feature_enable_nonce' ), 20, 1 );
self::add_action( 'admin_init', array( $this, 'change_feature_enable_from_query_params' ), 20, 0 );
}
/**
@ -1086,4 +1088,47 @@ class FeaturesController {
'incompatible_with_feature' => $incompatible_link,
);
}
/**
* Set the feature nonce to be sent from client side.
*
* @param array $settings Component settings.
*
* @return array
*/
public function set_change_feature_enable_nonce( $settings ) {
$settings['_feature_nonce'] = wp_create_nonce( 'change_feature_enable' );
return $settings;
}
/**
* Changes the feature given it's id, a toggle value and nonce as a query param.
*
* `/wp-admin/post.php?product_block_editor=1&_feature_nonce=1234`, 1 for on
* `/wp-admin/post.php?product_block_editor=0&_feature_nonce=1234`, 0 for off
*/
private function change_feature_enable_from_query_params(): void {
if ( ! current_user_can( 'manage_woocommerce' ) ) {
return;
}
$is_feature_nonce_invalid = ( ! isset( $_GET['_feature_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_feature_nonce'] ) ), 'change_feature_enable' ) );
foreach ( array_keys( $this->features ) as $feature_id ) {
if ( isset( $_GET[ $feature_id ] ) && is_numeric( $_GET[ $feature_id ] ) ) {
$value = absint( $_GET[ $feature_id ] );
if ( $is_feature_nonce_invalid ) {
wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
return;
}
if ( 1 === $value ) {
$this->change_feature_enable( $feature_id, true );
} elseif ( 0 === $value ) {
$this->change_feature_enable( $feature_id, false );
}
}
}
}
}