Getting to Know Woo: Extensibility in the New Product Editor

For the past few months, we have been busy building out a brand-new product creation experience. You may have read about it previously, and hopefully even tried it out yourself. If not, don’t worry… we will explain how to do so later in this post!

The product creation process has been redesigned from the ground up to focus on commerce, providing users with a seamless experience for crafting a wide range of products, from simple ones to highly customized options. This experience is still under active development, and we aim to reach feature parity early in 2024. Built with extensibility as a core principle, the new product editor provides developers with straightforward tools to integrate their unique features into the product creation process.

In fact, we are using these mechanisms to develop the new product editor itself!

We are approaching this project with the following guiding principles:

  • Provide a low complexity API that can be used via PHP, as we have heard from many developers that this is preferred.
  • Provide tooling to help set up the development environment.
  • Provide backwards compatibility when possible.
  • Use GitHub Discussions for brainstorming and decision-making, inviting contributions and feedback from the development community.

About Product Editor Extensibility

The design

The new product editor is organized into clearly defined tabs and sections, reflecting our research that finds that merchants think in terms of tasks and goals while creating new products in WooCommerce. 

The new product editor

You can help ensure your extension makes the most of this new design by reading our extensibility guidelines, which will help you determine where you should add new features to the product editor.

The implementation

The new product editor is implemented using the same Blocks API that powers the post and site editors in WordPress. However, whereas a “regular” block editor allows the end user to add blocks anywhere and rearrange those blocks, the product editor offers a more familiar, structured form-based experience, which is more suitable for the data entry and modification that is at the heart of product management.

As such, we have developed a simple PHP-based API, targeting our PHP developers in the WooCommerce community, which allows developers to easily extend the product editor’s form.

Extensibility features

Through a PHP-based API, developers are able to:

  • Add new blocks to the form; we supply a number of generic blocks that can be used out of the box, including:
    • Checkbox
    • Pricing
    • Radio
    • Text
    • Toggle
  • Remove blocks from the form
  • Conditionally hide and disable blocks on the form based on properties of the edited product, such as the product type

If an extension requires interactivity not available via our generic blocks, developers can easily implement a custom block using JavaScript and React.

Getting started

Try out the new product editor

Note: Since WooCommerce 7.9 (mid-July 2023), a subset of new stores have the new product editor auto-enabled as part of tests that Woo is running to help shape the new product creation experience. Users can easily opt-out of the new product editor and return to the classic product editor if they need functionality and extensions that are not yet available in the new product editor.

If you haven’t already, try out the new product editor so you can become familiar with how the new experience feels.

Go to WooCommerce > Settings > Advanced > Features and enable Try the new product editor (Beta).

Enabling the new product editor

Next, go to Products > Add New to try out the new editor.

The new product editor

Try adding a new block to the editor

There are a number of examples in the documentation on how to use the PHP-based API. Here is a simple example that adds a new field after the product name field. Add this to a test plugin and reload the product editor page.

<pre class="wp-block-syntaxhighlighter-code"><?php
use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
if ( ! function_exists( 'YOUR_PREFIX_add_block' ) ) {
	/**
	 * Add a new block to the template after the product name field.
	 *
	 * @param BlockInterface $product_name_field The product name block.
	 */
	function YOUR_PREFIX_add_block( BlockInterface $product_name_field ) {
		$parent = $product_name_field->get_parent();
		if ( ! method_exists( $parent, 'add_block' ) ) {
			return;
		}
		$parent->add_block(
			[
				'id'         => 'example-block',
				'order'      => $product_name_field->get_order() + 5,
				'blockName'  => 'woocommerce/product-text-field',
				'attributes' => [
					'property' => 'meta_data.example_block_property',
					'label'    => __( 'Example block', 'YOUR_TEXT_DOMAIN' ),
				],
			]
		);
	}
	add_action(
		'woocommerce_block_template_area_product-form_after_add_block_product-name',
		'YOUR_PREFIX_add_block'
	);
}
</pre>

Here is the result:

The new “Example block” field appears under the “Name” field

Note that the block’s input will also be persisted automatically in the metadata of the product. There is no other configuration necessary!

Explore the extensibility guidelines

Now that you have a feel for the new product editor, start thinking about how to best bring your extension’s functionality to merchants using it. Read the extensibility guidelines for tips and best practices.

Let us know what you think

Are there things you love about extending the new product editor? We sure hope so! Let us know.

Even more importantly, let us know what documentation and functionality is missing that you need in order to successfully bring your extension to the new product editor.

Share your thoughts with us in our discussion forum and in Slack:

Where to find more information

We are actively working on providing documentation for new product editor development:


Keep yourself in the loop!

Sign up for the WooCommerce developer newsletter:
Hidden
Hidden
Hidden


29 responses to “Getting to Know Woo: Extensibility in the New Product Editor”

  1. This is absolutely going in the right direction! Thanks team!

    I wish this sort of extensibility was considered for Cart/Checkout blocks as well, but… our team is super happy we have this coming in the new product editing experience.

    What would be great is the ability to also add a new tab of our own as well, via this PHP extensibility API.

    I sincerely hope that can make it in before launch as we’ll use it for sure 🙂

    1. Hey Josh!

      I wish this sort of extensibility was considered for Cart/Checkout blocks as well

      We’re following a path where any extensibility API that make sense to be PHP would be in PHP, but I’d still love to hear what you had in mind existing APIs, are non of them meeting your demand, or do you think some of them are needlessly JS?

      1. Hey Senadir,

        I think Cart/Checkout blocks did reinvent a few things that didn’t need reinventing.

        Just two examples off the top of my head:
        – Printing of notices (yes, it picks up registered notices but wp_print_notice was something 3rd party devs often used adhoc)
        – woocommerce_form_field for third party fields we wanted to register
        – Ability to filter and remove fields conditionally and easily via a PHP filter

        But we’ve made do and nearly fully adapted.

        Don’t get me wrong, I definitely wasn’t having a dig at Cart/Checkout blocks, the implementation is great and works beautifully now that we’re past most of the teething issues.

        But I’m just saying there’s a lot of PHP devs in the community being left behind and could have been made a lot easier on those not so deeply familiar with React. Some things (custom fields in particular) are a lot harder these days unless you have that deep React/JS knowledge.

        1. Thank you for the reply Josh 😀

          But I’m just saying there’s a lot of PHP devs in the community being left behind and could have been made a lot easier on those not so deeply familiar with React. Some things (custom fields in particular) are a lot harder these days unless you have that deep React/JS knowledge.

          I understand that and our goal isn’t to make life harder, is that just sometimes, not all existing extensibility methods make sense for Checkout, either because it’s a new flow, or because it’s a single page, SPA model.

          To answer some of your points:

          Printing of notices (yes, it picks up registered notices but wp_print_notice was something 3rd party devs often used adhoc)

          I’m not sure I fully understand this. Checkout operates via a JSON API, it doesn’t make sense to all printing functions to run in such requests, still, if you’re printing notices at page load, they should work fine with the notice block that’s added by default.

          Calling wc_print_notices in a life cycle request isn’t ideal and you should use wc_add_notice which also supports minimal HTML and can be sent back via a request and rendered, this would be the same as throwing an exception.

          woocommerce_form_field for third party fields we wanted to register

          Because there’s more than just rendering a field (it has to be picked up by our JS and sent and persisted somewhere in backend), we didn’t launch with this.

          But you might be delighted to know that a PHP API to add additional fields is actively being worked on, which should come with much greater power than what comes with woocommerce_checkout_fields and make the devex easier to manage.

          You can read the discussion here.

          https://github.com/woocommerce/woocommerce-blocks/discussions/11173

          And you can follow the main issue here
          https://github.com/woocommerce/woocommerce-blocks/issues/11584

          Ability to filter and remove fields conditionally and easily via a PHP filter

          This is still somehow doable using locale filters, but for me, it doesn’t make sense to give much power to a third party plugin, as the default fields are needed and expected in a lot of places, and are most importantly, locale dependent. So you can use the woocommerce_get_country_locale filter and it should work fine in hiding a field for a country, but we’re unlikely to allow general deletion of address fields from all countries at once.

          Do please let us know with anything you have in mind regarding extensibility, as we’re working toward closing the gap there and bringing sensible, stable extensibility points.

          You can also read our approach about extensibility here:
          https://github.com/woocommerce/woocommerce/discussions/41304#top

    2. Matt Sherman Avatar
      Matt Sherman

      Hi Josh,

      What would be great is the ability to also add a new tab of our own as well, via this PHP extensibility API.

      This is actually possible already! Adding a new top-level group (tab) is something that should be carefully considered, as things can quickly get out of control if a merchant has a few extensions installed that all decide to create new groups for their options.

      For a custom product types (support coming soon), creating new groups will be necessary. If extending a built-in product type (such as simple products), I would encourage you to think about whether your extension’s options would better fit into one of the existing built-in groups.

      Please reach out to us (here or in the Slack or GH discussions linked above) and we can help you to determine where your extension’s options best fit. Determining the best practices for extensibility in the new product editor is something we are still working through and use cases like your extension will help us and the entire community come up with clear guidelines.

      All that said, here is example code to add a new group to any product form that has the general group!

      <?php
      
      use Automattic\WooCommerce\Admin\BlockTemplates\BlockInterface;
      use Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates\GroupInterface;
      use Automattic\WooCommerce\Admin\Features\ProductBlockEditor\ProductTemplates\ProductFormTemplateInterface;
      
      add_action(
      	'woocommerce_block_template_area_product-form_after_add_block_general',
      	function ( BlockInterface $general_group ) {
      		$template = $general_group->get_root_template();
      
      		/*
      		 * Why is this check necessary?
      		 * - Allow VSCode to provide autocomplete for the specific product form template methods
      		 */
      		if ( ! $template instanceof ProductFormTemplateInterface ) {
      			return;
      		}
      
      		$my_group = $template->add_group(
      			array(
      				'id'         => 'your-prefix-example-group',
      				'attributes' => array(
      					'title' => __( 'My Group', 'YOUR_TEXT_DOMAIN' ),
      				),
      			)
      		);
      
      		/*
      		 * Why is this check necessary?
      		 * - Because of current bug in the add_group() docblock (https://github.com/woocommerce/woocommerce/issues/41587)
      		 */
      		if ( ! $my_group instanceof GroupInterface ) {
      			return;
      		}
      
      		$section_1 = $my_group->add_section(
      			array(
      				'id'         => 'your-prefix-example-section-1',
      				'attributes' => array(
      					'title' => __( 'My Section One', 'YOUR_TEXT_DOMAIN' ),
      				),
      			)
      		);
      
      		$section_1->add_block(
      			array(
      				'id'         => 'your-prefix-example-block-1',
      				'blockName'  => 'woocommerce/product-text-field',
      				'attributes' => array(
      					'label'    => __( 'My Block One', 'YOUR_TEXT_DOMAIN' ),
      					'property' => 'meta_data.your_prefix_example_field_1',
      				),
      			)
      		);
      
      		$section_2 = $my_group->add_section(
      			array(
      				'id'         => 'your-prefix-example-section-2',
      				'attributes' => array(
      					'title' => __( 'My Section Two', 'YOUR_TEXT_DOMAIN' ),
      				),
      			)
      		);
      
      		$section_2->add_block(
      			array(
      				'id'         => 'your-prefix-example-block-2',
      				'blockName'  => 'woocommerce/product-checkbox-field',
      				'attributes' => array(
      					'label'    => __( 'My Block Two', 'YOUR_TEXT_DOMAIN' ),
      					'property' => 'meta_data.your_prefix_example_field_2',
      				),
      			)
      		);
      	}
      );

      1. This is fantastic Matt! Thank you for sharing the full code snippet 🙂

  2. Thanks, happy to see the extensibility via PHP for those of use that don’t use React.

  3. backcourtdev Avatar
    backcourtdev

    If an extension requires interactivity not available via our generic blocks, developers can easily implement a custom block using JavaScript and React.

    I’m not sure I would call this “Easy” 🙂 when there’s no docu for it yet. Looking forward to that example soon…. and also hoping you will make the Grouped product’s product selector block re-usable.

    1. Matt Sherman Avatar
      Matt Sherman

      Hi backcourtdev,

      > I’m not sure I would call this “Easy” 🙂 when there’s no docu for it yet. Looking forward to that example soon

      In case you haven’t seen it yet, we recently published the second post in the new product editor development series, which covers creating a custom block.

      https://developer.woocommerce.com/2024/01/17/getting-to-know-woo-extending-the-new-product-editor-with-react/

      > and also hoping you will make the Grouped product’s product selector block re-usable.

      I have added this to our development backlog so that we can consider this.

  4. backcourtdev Avatar
    backcourtdev

    If an extension requires interactivity not available via our generic blocks, developers can easily implement a custom block using JavaScript and React.

    I am not sure I would refer to this as easy where there isn’t any docu on it yet 🙂 I look forward to that addition to the tutorial.

  5. This is interesting. A couple of questions come to mind:
    1. How does one add a row with multiple fields, like this one? https://prnt.sc/689zgM88wjCz. Or this, for subscriptions: https://prnt.sc/Keq98IssrGwe.
    2. How does the editor work with variations? The question above applies to them as well.
    3. Is there an action, or filter, to intercept the save and load operations? The main issue I need to face is that, for backward compatibility, I need some meta to be saved not as separate entries, but as a single meta, with a specific structure. That is, not separate meta like “my_field_1”, “my_field_2”, but just “my_field”, with the meta structured in a certain way. The data can then be “unpacked” on load. I know, it’s not a database normal form, but that has to work for the moment.
    4. The guide mentions “hiding blocks conditionally”, but it doesn’t explain how. For example, some blocks apply to Simple products, others to Subscriptions, other to variations. How does one handle that? Your documentation shows some examples with something like “editedProduct.regular_price < 10”, but it doesn’t describe what editedProduct is (it looks like a JavaScript variable), nor how it can be used, apart from the two examples.

  6. It looks like my comment was removed again, because it contained a link. Unfortunately, there’s no other way to illustrate an issue other than adding a link to a screenshot. The antispam filter should be relaxed quite a bit.

  7. Matt Sherman Avatar
    Matt Sherman

    1. How does one add a row with multiple fields, like this one? https://prnt.sc/689zgM88wjCz. Or this, for subscriptions: https://prnt.sc/Keq98IssrGwe.

    You can use the `core/columns` and `core/column` blocks to create a row with multiple fields.

    You can find an example where we do this in the implementation of the core layout template for simple products.

    https://github.com/woocommerce/woocommerce/blob/0064abbd0fc0380807080b8d9ee899e4c108f453/plugins/woocommerce/src/Internal/Features/ProductBlockEditor/ProductTemplates/SimpleProductTemplate.php#L244

    2. How does the editor work with variations? The question above applies to them as well.

    Variations have their form defined with a separate layout template: `product-variation`.

    You can see the implementation of this layout template here:

    https://github.com/woocommerce/woocommerce/blob/0064abbd0fc0380807080b8d9ee899e4c108f453/plugins/woocommerce/src/Internal/Features/ProductBlockEditor/ProductTemplates/ProductVariationTemplate.php

    3. Is there an action, or filter, to intercept the save and load operations? The main issue I need to face is that, for backward compatibility, I need some meta to be saved not as separate entries, but as a single meta, with a specific structure. That is, not separate meta like “my_field_1”, “my_field_2”, but just “my_field”, with the meta structured in a certain way. The data can then be “unpacked” on load. I know, it’s not a database normal form, but that has to work for the moment.

    When using the property attribute to link blocks to the underlying product data, the blocks assume/require that the product data object returned from the REST API has those properties on it.

    If you wanted to customize/configure the saving and retrieval of custom product properties, you would want to use hooks to accomplish that. The two hooks that are used are:

    woocommerce_rest_prepare_product_object
    woocommerce_rest_insert_product_object

    I’m not finding any documentation on these right now (I’m making a note that we need documentation for these), but you can see where the hooks are applied in https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/includes/rest-api/Controllers/Version2/class-wc-rest-products-v2-controller.php

    4. The guide mentions “hiding blocks conditionally”, but it doesn’t explain how. For example, some blocks apply to Simple products, others to Subscriptions, other to variations. How does one handle that? Your documentation shows some examples with something like “editedProduct.regular_price < 10”, but it doesn’t describe what editedProduct is (it looks like a JavaScript variable), nor how it can be used, apart from the two examples.

    editedProduct is a simple object that contains the product data that is being edited.

    I agree that the documentation is lacking here.

    You can see what the editedProduct object looks like running the following code in the browser console:

    wp.data
    .select('core')
    .getEditedEntityRecord('postType', 'product', PRODUCT_ID_GOES_HERE);

    Note that if dealing with a variation, you will need to use `product_variation` instead of `product` in the above code.

    On all non-variation products, there is a `type` property that can be used to conditionally hide blocks. For example you could do something like:

    editedProduct.type === 'simple'

    In addition to editedProduct, you can also use postType in expressions. For all non-variation products, the postType is product. For variations, the postType is product_variation.

    We have’t documented it yet, since it is very bare-bones, but if you install the WooCommerce Beta Tester, you will find a new “Show developer tools” option in the product editor’s more menu (…) that will allow you to inspect blocks and the edited product data.

    Note that the WooCommerce Beta Tester should only be installed on non-production development sites.

    https://github.com/woocommerce/woocommerce/releases/tag/wc-beta-tester-2.3.0

    1. I’m not sure I understand the following:
      > When using the property attribute to link blocks to the underlying product data, the blocks assume/require that the product data object returned from the REST API has those properties on it.

      We’re talking about fields to edit custom meta, which is not part of the product attributes. Due to that, there isn’t going to be a `$product->get_some_custom_meta()` method to fetch that data. Besides, as I mentioned originally, the custom meta is “packed” due to a legacy design choice. A single custom meta contains multiple values, which have to be spread across multiple fields. For example, a product could have extra fields “custom_regular_price_1”, “custom_regular_price_2”, “custom_regular_price_3”, which are stored in the database as a single meta, called “_custom_regular_prices”. The content of the meta could be a serialised array, a JSON object, or something like that. A REST API response could possibly contain that data (if WooCommerce returns it, that I don’t know), in a packed format (i.e. not “exploded” for each field), in the “meta_data” attribute. How will your blocks fetch and save that?

      For comparison, the existing editor works fine, as follows:
      On load (Edit Product)
      1. Fetch the custom meta by calling `$product->get_meta()`.
      2. Extract the values from the custom meta.
      3. Render the fields with each value.

      **On save**
      1. Fetch the POSTed values.
      2. Build the meta data.
      3. Save the meta data by calling `$product->update_meta_data()`.

      That would be it. This takes ten lines of code at most. I need to keep this exact behaviour, without having to code a full custom block, with all the JS stuff, for such a simple operation.

      1. Matt Sherman Avatar
        Matt Sherman

        Here’s a link to example code that shows how you can map values stored in a “packed” meta field to properties exposed in the REST API, and then easily hook them up to generic blocks, avoiding the need to code a custom block…

        https://gist.github.com/mattsherman/8b3e67068d247f9825a4b1ca5caf2602

        1. Diego Avatar

          You wouldn’t believe it. I had not looked at the code yet (busy with a lot of other tasks), but I wrote a flow on paper that matches the one you described almost exactly. 😮

          1. Matt Sherman Avatar
            Matt Sherman

            Great minds think alike! 😄

    2. Based on your example, I’m afraid that this code from your core won’t work:

      $pricing_column_1->add_block(
      array(
      ‘id’ => ‘product-regular-price’,
      ‘blockName’ => ‘woocommerce/product-regular-price-field’,
      ‘order’ => 10,
      ‘attributes’ => array(
      ‘name’ => ‘regular_price’,
      ‘label’ => __( ‘List price’, ‘woocommerce’ ),
      /* translators: PricingTab: This is a link tag to the pricing tab. */
      ‘help’ => __( ‘Manage more settings in Pricing.’, ‘woocommerce’ ),
      ),
      )
      );

      The “attribute” won’t be a product attribute. The product will not have the custom meta as additional attributes. The values will remain in custom meta, not accessible with a $product->get_ methods, nor will they be part of the returned product object. Due to that, giving an attribute name won’t work.

      Besides, it’s important that the custom fields aren’t automatically “dumped” into the database when the product is saved. Since these fields are part of a on object, the logic has to be symmetrical:
      1. On load -> unpack the object, populate each separate field.
      2. On save -> collect the field values, prepare the object, save the object. Do not save each field separately.

      This is very easy to do with the existing editor, I still can’t understand how to do it with the new one.

      1. Matt Sherman Avatar
        Matt Sherman

        The `attributes` in the `add_block()` API function are attributes of the client-side block used to show a field in the editor.

        To add new product properties, you need to use `woocommerce_rest_prepare_product_object` and `woocommerce_rest_insert_product_object`, as I showed in the example I just shared in response to your other question (https://developer.woocommerce.com/2023/11/17/getting-to-know-woo-extensibility-in-the-new-product-editor/#comment-20723).

        Let me know if that example helps you understand things or whether there are still details that you are unsure of.

        The only time we automatically “dump” custom fields in the DB is if you use the `meta_data.foo` property name format, as that has automatic handling to create new meta fields on the fly, as a convenience. You certainly don’t need to use it.

        1. Diego Avatar

          I think I figured out where the confusion lies. What you call “product properties” are actually “REST response object properties”. The REST response object is actually a JS object, separate and independent from a WC_Product instance.

          Although it’s not possible to “tack” properties to a WC_Product, due to PHP restrictions, it IS possible to add them to a JS object. The flow does therefore become something like the following (very simplified, for brevity):

          READ PHASE

          // PHP
          $response_object[‘custom_property’] = ‘ABC’;

          which translates to JS as

          const response_object = ;
          // This shows “ABC” in the console log. The property is the one that was
          // added to the response object (array) before it’s send by the REST API endpoint
          console.log(response_object[‘custom_property’]);

          To make it short:
          1. In PHP, a product object is a WC_Product instance. This cannot have additional properties
          2. In JS, a product object is a plain(ish) JS object. This can have any custom additional properties, which are attached to it when the REST response is prepared by the server.
          3. The “property” attribute in the add_block() call tells the rendering logic the name of the property IN THE JS OBJECT that should be used to populate the custom field (i.e. the response_object[‘custom_property’] mentioned earlier).

          SAVE PHASE

          When the form is saved, the JS object gets all the extra properties attached to it. The object is then send to the server, and the PHP code does the following:
          1. Save all the known object properties, i.e. the ones that belong to the WC_Product class (and children).
          2. Save all the custom meta data, i.e. the JS object properties named “meta_data.”.
          3. Ignore any additional properties that were passed with the REST object. These can be handled in the woocommerce_rest_insert_product_object event (which, unless I’m mistaken, also covers the UPDATE case.

          Would this be correct?

          1. Matt Sherman Avatar
            Matt Sherman

            Yes, that is correct. Sorry for the confusion over what a “product property”.

  8. As for the hiding blocks conditionally, I’m afraid that I couldn’t follow the explanation. I’m not fond of JS, and I only find it confusing. Due to that, I avoid debugging scripts on the browser, because I’m rarely able to get anything from it (reason why I haven’t written any blocks yet).

    All I need to do is showing the custom fields for specific product and variation types. Your code shows how to use $block->add_disable_condition(), but you mentioned that

    “On all non-variation products, there is a `type` property that can be used to conditionally hide blocks”

    I would also need to handle variation product types, and I need to distinguish the exact type. That is, a normal product variation and a subscription product variation must be handled differently. How should I do that?

    1. Matt Sherman Avatar
      Matt Sherman

      To hide or disable blocks conditionally, you do not need to write JS. You only need to provide the hide conditions in an expression format that is similar to JS and PHP.

      https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/src/Admin/Features/ProductBlockEditor/ProductTemplates/README.md/#conditionally-hiding-a-block-in-product-editor-templates

      In the expressions, you can access product properties like `type` via the `editedProduct.type` syntax.

      To access the `postType` variable in an expression, like I mentioned previously, you can do `postType === ‘product_variation’`.

      Unfortunately, I do not see a way currently, with the expression support, to distinguish between a product variation and a subscription product variation, since they are both `postType === ‘product_variation’`. I’ll dig into this more and follow up.

      1. Diego Avatar

        Thanks for this reply as well. The challenge, in my case, is that a product variation can have two extra prices (regular and sale), whereas a subscription product variation can have three (regular, sale and sign up fee). I need to distinguish those cases, as the interface must be different for them.

        Due to that, “product_variation” is not sufficient. Subscription variations have the type “subscription_variation”, and I need to be able to distinguish that.

        1. Matt Sherman Avatar
          Matt Sherman

          You could insert your custom fields conditionally by only inserting them after another existing field was added. This is how the woocommerce_block_template_area_{template_area}_after_add_block_{block_id} hook works…

          For example, if you added a hook to the woocommerce_block_template_area_product-form_after_add_block_sign-up-fee (just making that sign-up-fee block ID up, since we don’t have variable subscriptions support yet in the new product editor, so I don’t know what the ID will be), your hook would only be called when the sign-up-fee block was added.

          If you can point to an existing plugin that extends that classic editor, it would help me to better understand exactly what you need to do so that we can make sure the necessary support is available in the new product editor.

          Subscription variations have the type “subscription_variation”, and I need to be able to distinguish that.

          How did you determine this? From my investigation, I saw that subscription variations had the product_variation post type. Perhaps I missed something!

          1. Diego Avatar

            A plugin that extends the product editor is my own. It also extends the product editor for subscriptions. The authors of that plugin were supposed to do that “out of the box” in version 2.0 (I still have the conversation), but they never got around to actually implementing it, so I had to do that myself for about 10 years now.

            As for the type of subscription variations, the code is below:

            class WC_Product_Subscription_Variation_Legacy extends WC_Product_Subscription_Variation {

            /**
            * Set default array value for WC 3.0's data property.
            * @var array
            */
            protected $data = array();

            /**
            * Create a simple subscription product object.
            *
            * @access public
            * @param mixed $product
            */
            public function __construct( $product, $args = array() ) {

            parent::__construct( $product, $args = array() );

            $this->parent_product_type = $this->product_type;

            $this->product_type = 'subscription_variation';

            $this->subscription_variation_level_meta_data = array(
            'subscription_price' => 0,
            'subscription_period' => '',
            'subscription_period_interval' => 'day',
            'subscription_length' => 0,
            'subscription_trial_length' => 0,
            'subscription_trial_period' => 'day',
            'subscription_sign_up_fee' => 0,
            'subscription_payment_sync_date' => 0,
            );

            $this->variation_level_meta_data = array_merge( $this->variation_level_meta_data, $this->subscription_variation_level_meta_data );
            }

          2. Diego Avatar

            I forgot to mention, we can continue the conversation on Slack, if it’s more convenient. I can’t share my plugins here, anyway.

          3. Matt Sherman Avatar
            Matt Sherman

            $this->product_type = ‘subscription_variation’;

            Ah, I see… I was referring to the product’s post type, which is product_variation for all variations.

            In the REST API, variations do not have a product type returned (type in the REST API response for a product; product_type/get_type() in the PHP WC_Product subclass). I’m not honestly sure why this is the case, and perhaps it can simply be added to the REST API response. I’ll look into this further.

    2. Matt Sherman Avatar
      Matt Sherman

      I have started a GitHub discussion above distinguishing product variation types (the discussion also has a link to a proposed PR that implements support for this):

      Distinguishing product variation types in REST API responses #47420

Leave a Reply

Your email address will not be published. Required fields are marked *