Skip to content

Conversation

@Konamiman
Copy link
Contributor

@Konamiman Konamiman commented Sep 8, 2022

All Submissions:

Changes proposed in this Pull Request:

Background

In this context we define a feature as a major piece of the WooCommerce functionality that can be turned on or off via code API or via admin UI. Each feature has a unique alphanumeric identifier and a standardized name for the option that turns it on or off: woocommerce_feature_{id}_enabled (the value of the option is either yes or no like any other settings related option).

A feature can be mature or experimental, the later means that the feature either is still in development or is part of an experiment that could end up being successful or not; so the idea is that ultimately all the features that at one point are marked experimental eventually either become mature or are removed.

WooCommerce plugins may declare positive compatibility or negative compatibility with any of the existing features. Positive means that to the best of the plugin authors knowledge, the plugin will continue to work as expected when the feature is enabled. Negative means that there are known issues that will arise when the plugin is used with the feature enabled.

WooCommerce had already two "features" that were provided by the Admin code: enable analytics, and enable the new navigation. In this pull request these have been repurposed as part of the new "features engine"; as an exceptional case, the old enabling option name is used for those, instead of woocommerce_feature_{id}_enabled.

New classes

This pull request introduces two new classes:

  • An internal FeaturesController class. This class has methods to:

    • Get the list of the existing features. This list is hardcoded into the class.
    • Enable or disable a given feature by id (although normally this will be done via settings UI).
    • Declare compatibility (positive or negative) of a given plugin with a given feature.
    • Get a list of the plugins that have declared compatibility with a given feature.
    • Get a list of the features for which a given plugin has declared compatibility.
    • Render the feature settings UI page (Settings - Advanced - Features), replacing the rendering that was previously done by Admin code.
  • A public FeaturesUtil class with static methods that are proxies to FeaturesController.

FeaturesController is to be retrieved via the dependency injection container as usual, FeaturesUtil can be used directly.

Declaring feature compatibility

Both FeaturesController and FeaturesUtil have a declare_compatibility method that accepts a feature id, a plugin identifier and a boolean indicating positive or negative compatibility. It's mandatory to invoke these methods from inside the before_woocommerce_init action, so that by the time woocommerce_init is fired any plugin willing to declare feature compatibility has done so already. Plugins must use the method from FeaturesUtil and not the method from FeaturesController.

The plugin identifier to be passed to FeaturesUtil::declare_compatibility must be the path of the main plugin file, this will be converted to directory/file.php which is the format used by the keys in the array returned by the WordPress get_plugins function. The FeaturesController::declare_compatibility method assumes that the plugin identifier it receives is already in this format.

Thus this is the snippet that a plugin can use to declare compatibility with a feature (assuming it runs from the main plugin file):

 add_action('before_woocommerce_init', function() {
     \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility('custom_order_tables', __FILE__, true);
 });

The feature settings UI

This is how the settings page for the features looks now:

image

At first sight it might look like the only change is the addition of the "Experimental" section, but actually the changes are deeper: now the entire settings page is rendered by the FeaturesController class, and additionally, all the rendered settings are tied to options with the format woocommerce_feature_{id}_enabled. The analytics and new navigation options were previously rendered by Admin code (they keep their old names for the enabling options).

This new settings page is still compatible with the woocommerce_settings_features filter. Any settings added there will be rendered in the "mature" settings section, right after the built-in WooCommerce settings.

Compatibility with the woocommerce_admin_disabled filter is also maintained. This is how the settings page will render if this filter returns true:

image

Enabling the custom orders table feature

Previously the custom orders table feature had to be enabled via the CustomOrdersTableController::show_feature method. This is no longer the case (the new features engine is used instead), and to make this extra clear, that show_feature method will throw an exception. This method (and the companion, hide_feature) will eventually be removed once the custom orders table feature becomes mature.

Compatibility with the old Admin settings

The FeaturesController class still uses the old option names for enabling/disabling the legacy features:

  • woocommerce_analytics_enabled for enabling analytics
  • woocommerce_navigation_enabled for enabling the new navigation

The Admin code related to the features settings page rendering has been modified: the hookings to woocommerce_get_sections_advanced and woocommerce_get_settings_advanced have been removed, and the methods that were the target of those have been turned into no-ops and marked as deprecated.

The feature enabled changed action

Last but not least, a new woocommerce_feature_enabled_changed action is introduced. This is fired whenever the enabled status for a feature changes and provides the feature id and whether it has been enabled or disabled.

What's missing

Apart from the revamped settings page there are no UI changes. An indication of which plugins are compatible with which features will be introduced in a separate pull request.

Closes #34419.

How to test the changes in this Pull Request:

Compatibility with the old settings and the custom order tables feature

  1. Go to WooCommerce - Settings - Advanced - Features and verify that enabling and disabling "Analytics" and "New navigation" continues to work as expected.

  2. Also verify that the custom orders table feature is properly enabled and disabled from that page (a quite immediate indication is that the "Custom data stores" section appears or disappears from the same settings page).

Declaring compatibility

  1. Create a dummy plugin and add compatibility (positive or negative) with the custom orders table, as in the snippet shown above in "Declaring feature compatibility".

  2. From the command line, verify that you can check compatibility either by plugin name...

$ wp eval 'print_r(Automattic\WooCommerce\Utilities\FeaturesUtil::get_compatible_features_for_plugin("foobar/foobar.php"));'

Array
(
    [compatible] => Array
        (
            [0] => custom_order_tables
        )

    [incompatible] => Array
        (
        )

)

...or by feature id:

$ wp eval 'print_r(Automattic\WooCommerce\Utilities\FeaturesUtil::get_compatible_plugins_for_feature("custom_order_tables"));'

Array
(
    [compatible] => Array
        (
            [0] => foobar/foobar.php
        )

    [incompatible] => Array
        (
        )

)

Others

  1. Verify that any settings added via the woocommerce_settings_features filter are still rendered, e.g. add the following to your dummy plugin:
add_filter('woocommerce_settings_features', function($features) {
    $features[] = [
        'title' => 'Foobar',
        'desc' => 'Fizzbuzz',
        'type' => 'checkbox',
        'id' => 'woocommerce_foobuzz',
        'desc_tip' => 'Fooes the bars and fizzes the buzzs'
    ];
    return $features;
}, 10, 1);
  1. Verify that the old Admin settings are disabled when you use the woocommerce_admin_disabled filter:
add_filter('woocommerce_admin_disabled', '__return_true');

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully run tests with your changes locally?
  • Have you created a changelog file for each project being changed, ie pnpm changelog add --filter=<project>?

FOR PR REVIEWER ONLY:

  • I have reviewed that everything is sanitized/escaped appropriately for any SQL or XSS injection possibilities. I made sure Linting is not ignored or disabled.

@github-actions github-actions bot added focus: react admin plugin: woocommerce Issues related to the WooCommerce Core plugin. labels Sep 8, 2022
@Konamiman Konamiman requested review from a team and vedanshujain and removed request for a team September 8, 2022 15:21
@github-actions
Copy link
Contributor

github-actions bot commented Sep 8, 2022

Test Results Summary

Commit SHA: 9b922e2

Test 🧪Passed ✅Failed 🚨Broken 🚧Skipped ⏭️Unknown ❔Total 📊Duration ⏱️
API Tests01180201200m 17s
E2E Tests000000NaNm NaNs
To view the full API test report, click here.
To view the full E2E test report, click here.
To view all test reports, visit the WooCommerce Test Reports Dashboard.

Copy link
Contributor

@vedanshujain vedanshujain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work as always! I have added couple of minor comments.

@github-actions github-actions bot added the release: highlight Issues that have a high user impact and need to be discussed/paid attention to. label Sep 13, 2022
vedanshujain
vedanshujain previously approved these changes Sep 13, 2022
Copy link
Contributor

@vedanshujain vedanshujain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Subjected to CI passing

@github-actions github-actions bot removed the release: highlight Issues that have a high user impact and need to be discussed/paid attention to. label Sep 13, 2022
@vedanshujain
Copy link
Contributor

Note that some API tests are failing, but I manually verified and they seem to be working fine.

@Konamiman Konamiman merged commit f65c775 into trunk Sep 16, 2022
@Konamiman Konamiman deleted the add/features-controller-with-plugin-compatibility-declaration branch September 16, 2022 07:17
@github-actions github-actions bot added this to the 7.1.0 milestone Sep 16, 2022
@github-actions
Copy link
Contributor

Hi @Konamiman, thanks for merging this pull request. Please take a look at these follow-up tasks you may need to perform:

  • Add the release: add testing instructions label

@Konamiman Konamiman mentioned this pull request Sep 16, 2022
8 tasks
vedanshujain added a commit that referenced this pull request Sep 16, 2022
barryhughes pushed a commit that referenced this pull request Sep 16, 2022
Revert "Add the WooCommerce features engine (#34616)"

This reverts commit f65c775.
@vedanshujain vedanshujain restored the add/features-controller-with-plugin-compatibility-declaration branch September 23, 2022 09:03
@kalessil kalessil deleted the add/features-controller-with-plugin-compatibility-declaration branch September 24, 2024 06:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

plugin: woocommerce Issues related to the WooCommerce Core plugin.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[COT] Implement compatibility API for plugins to declare incompatibility with COT

3 participants