Enable Gutenberg editor in WooCommerce
Tags: wordpress, woocommerce, gutenberg, webdev
Published: 2021-02-12 08:55:12

WooCommerce 5.0 has recently been released with new features and improvements but sill no support for Gutenberg, WordPress block editor, while creating products. It is ironic since WooCommerce provides a number of good blocks that can be added to pages and posts but not in products.

In this quick tutorial I will show you how to activate Gutenberg for products and resolve some of the issues that occur with this activation.

> **_NOTE:_** All code here can be added to functions.php file in your theme.

&nbsp;
# Enable block editor

To enable Gutenberg you can use 'use_block_editor_for_post_type' filter by simply adding these lines:
```php
function activate_gutenberg_product( $can_edit, $post_type ) {

	if ( $post_type == 'product' ) {
		$can_edit = true;
	}
	return $can_edit;
}
add_filter( 'use_block_editor_for_post_type', 'activate_gutenberg_product', 10, 2 );
```

The above code will enable the new editor for product post type but you will notice that categories and tags have disappeared.

&nbsp;
# Enable taxonomies

WordPress custom post types have a argument 'show_in_rest' (available since 4.7.0) which enables the retrieval and modification of post type using REST API.

Using 'woocommerce_taxonomy_args_product_cat' and 'woocommerce_taxonomy_args_product_tag' filters we can enable REST.

```php
function enable_taxonomy_rest( $args ) {
	$args['show_in_rest'] = true;
	return $args;
}
add_filter( 'woocommerce_taxonomy_args_product_cat', 'enable_taxonomy_rest' );
add_filter( 'woocommerce_taxonomy_args_product_tag', 'enable_taxonomy_rest' );

```
&nbsp;

# Catalog visibility
![image](https://dev-to-uploads.s3.amazonaws.com/i/sg0y1aadqwh96ydysn2d.png)
 
Once you enable Gutenberg editor, catalog visibility will not appear. This is because 'post_submitbox_misc_actions' action [is not supported in Gutenberg editor](https://github.com/WordPress/gutenberg/issues/12764).

One way to resolve is to hook into Gutenberg slots like [PluginPostStatusInfo](https://developer.wordpress.org/block-editor/developers/slotfills/plugin-post-status-info/) but that is a rocky road and which will require spending long hours and might not get you the required results.

The easy way is to utilize WooCommerce built in functions to add this feature. And since WooCommerce JavaScript files are already loaded we don't have to do add any scripts, only the PHP part.

First add a metabox:
```php
function register_catalog_meta_boxes() {
	global $current_screen;
	// Make sure gutenberg is loaded before adding the metabox
	if ( method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor() ) {
		add_meta_box( 'catalog-visibility', __( 'Catalog visibility', 'textdomain' ), 'product_data_visibility', 'product', 'side' );
	}
}
add_action( 'add_meta_boxes', 'register_catalog_meta_boxes' );
```

Then we take add the function 'product_data_visibility' from [WooCommerce source](https://github.com/woocommerce/woocommerce/blob/master/includes/admin/class-wc-admin-post-types.php#L656) with few changes:

```php
function product_data_visibility( $post ) {

	$thepostid          = $post->ID;
	$product_object     = $thepostid ? wc_get_product( $thepostid ) : new WC_Product();
	$current_visibility = $product_object->get_catalog_visibility();
	$current_featured   = wc_bool_to_string( $product_object->get_featured() );
	$visibility_options = wc_get_product_visibility_options();
	?>
<div class="misc-pub-section" id="catalog-visibility">
	<?php esc_html_e( 'Catalog visibility:', 'woocommerce' ); ?>
	<strong id="catalog-visibility-display">
		<?php

		echo isset( $visibility_options[ $current_visibility ] ) ? esc_html( $visibility_options[ $current_visibility ] ) : esc_html( $current_visibility );

		if ( 'yes' === $current_featured ) {
			echo ', ' . esc_html__( 'Featured', 'woocommerce' );
		}
		?>
	</strong>

	<a href="#catalog-visibility"
	   class="edit-catalog-visibility hide-if-no-js"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a>

	<div id="catalog-visibility-select" class="hide-if-js">

		<input type="hidden" name="current_visibility" id="current_visibility"
			   value="<?php echo esc_attr( $current_visibility ); ?>" />
		<input type="hidden" name="current_featured" id="current_featured"
			   value="<?php echo esc_attr( $current_featured ); ?>" />

		<?php
		echo '<p>' . esc_html__( 'This setting determines which shop pages products will be listed on.', 'woocommerce' ) . '</p>';

		foreach ( $visibility_options as $name => $label ) {
			echo '<input type="radio" name="_visibility" id="_visibility_' . esc_attr( $name ) . '" value="' . esc_attr( $name ) . '" ' . checked( $current_visibility, $name, false ) . ' data-label="' . esc_attr( $label ) . '" /> <label for="_visibility_' . esc_attr( $name ) . '" class="selectit">' . esc_html( $label ) . '</label><br />';
		}

		echo '<br /><input type="checkbox" name="_featured" id="_featured" ' . checked( $current_featured, 'yes', false ) . ' /> <label for="_featured">' . esc_html__( 'This is a featured product', 'woocommerce' ) . '</label><br />';
		?>
		<p>
			<a href="#catalog-visibility"
			   class="save-post-visibility hide-if-no-js button"><?php esc_html_e( 'OK', 'woocommerce' ); ?></a>
			<a href="#catalog-visibility"
			   class="cancel-post-visibility hide-if-no-js"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></a>
		</p>
	</div>
</div>
<?php
}
```

&nbsp;
# Reverting back to classic editor (temporarily) 
If you want to revert back to the classic editor, for any reason, here is a trick.

Change 'activate_gutenberg_product' function to this:
```php
function activate_gutenberg_product( $can_edit, $post_type ) {
	$disable = in_array( 'classic-editor', array_keys( $_GET ) );
	if ( $post_type == 'product' && $disable != true ) {
		$can_edit = true;
	}
	return $can_edit;
}
```

Now if you include `&classic-editor` in WordPress admin url the classic editor will be loaded.


&nbsp;
# Full code
```php
function activate_gutenberg_product( $can_edit, $post_type ) {

	if ( $post_type == 'product' ) {
		$can_edit = true;
	}
	return $can_edit;
}
add_filter( 'use_block_editor_for_post_type', 'activate_gutenberg_product', 10, 2 );

function enable_taxonomy_rest( $args ) {
	$args['show_in_rest'] = true;
	return $args;
}
add_filter( 'woocommerce_taxonomy_args_product_cat', 'enable_taxonomy_rest' );
add_filter( 'woocommerce_taxonomy_args_product_tag', 'enable_taxonomy_rest' );


function register_catalog_meta_boxes() {
	global $current_screen;
	// Make sure gutenberg is loaded before adding the metabox
	if ( method_exists( $current_screen, 'is_block_editor' ) && $current_screen->is_block_editor() ) {
		add_meta_box( 'catalog-visibility', __( 'Catalog visibility', 'textdomain' ), 'product_data_visibility', 'product', 'side' );
	}
}
add_action( 'add_meta_boxes', 'register_catalog_meta_boxes' );


function product_data_visibility( $post ) {

	$thepostid          = $post->ID;
	$product_object     = $thepostid ? wc_get_product( $thepostid ) : new WC_Product();
	$current_visibility = $product_object->get_catalog_visibility();
	$current_featured   = wc_bool_to_string( $product_object->get_featured() );
	$visibility_options = wc_get_product_visibility_options();
	?>
<div class="misc-pub-section" id="catalog-visibility">
	<?php esc_html_e( 'Catalog visibility:', 'woocommerce' ); ?>
	<strong id="catalog-visibility-display">
		<?php

		echo isset( $visibility_options[ $current_visibility ] ) ? esc_html( $visibility_options[ $current_visibility ] ) : esc_html( $current_visibility );

		if ( 'yes' === $current_featured ) {
			echo ', ' . esc_html__( 'Featured', 'woocommerce' );
		}
		?>
	</strong>

	<a href="#catalog-visibility"
	   class="edit-catalog-visibility hide-if-no-js"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a>

	<div id="catalog-visibility-select" class="hide-if-js">

		<input type="hidden" name="current_visibility" id="current_visibility"
			   value="<?php echo esc_attr( $current_visibility ); ?>" />
		<input type="hidden" name="current_featured" id="current_featured"
			   value="<?php echo esc_attr( $current_featured ); ?>" />

		<?php
		echo '<p>' . esc_html__( 'This setting determines which shop pages products will be listed on.', 'woocommerce' ) . '</p>';

		foreach ( $visibility_options as $name => $label ) {
			echo '<input type="radio" name="_visibility" id="_visibility_' . esc_attr( $name ) . '" value="' . esc_attr( $name ) . '" ' . checked( $current_visibility, $name, false ) . ' data-label="' . esc_attr( $label ) . '" /> <label for="_visibility_' . esc_attr( $name ) . '" class="selectit">' . esc_html( $label ) . '</label><br />';
		}

		echo '<br /><input type="checkbox" name="_featured" id="_featured" ' . checked( $current_featured, 'yes', false ) . ' /> <label for="_featured">' . esc_html__( 'This is a featured product', 'woocommerce' ) . '</label><br />';
		?>
		<p>
			<a href="#catalog-visibility"
			   class="save-post-visibility hide-if-no-js button"><?php esc_html_e( 'OK', 'woocommerce' ); ?></a>
			<a href="#catalog-visibility"
			   class="cancel-post-visibility hide-if-no-js"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></a>
		</p>
	</div>
</div>
<?php
}
```

Hopefully this was an easy and useful tutorial.