This serves as a tracking and patch testing issue for porting D7 Ubercart Rules Components to D8. I am also using this to document the process, because currently Rules has very little documentation for D8 and no information about porting between the two very different major versions.

Rules Components are reusable, stand-alone pre-configured sets of Rules conditions and actions that can be used by Rules and other modules on your site. Components are for example useful if you want to use the same conditions, actions or rules in multiple places, or call them from your custom module.

These are the steps in the process:

Tasks

  1. Make a list of Rules Components that Ubercart generates. Publish that here!
  2. Ubercart Rules Components are defined in D7 in hook_default_rules_configuration() and altered in hook_default_rules_configuration_alter(), by creating an instance of rules_reaction_rule() and programmatically adding pre-existing conditions, and/or actions to it. These hooks may be found in <modulename>/<modulename>.rules_defaults.inc. Refer to the D7 version of these files to ensure that you port ALL the Rules components that were in D7 Ubercart.
  3. Create configuration files for these components in D8. Configuration files should go into <modulename>/config/optional/ and be named rules.component.<rule machine name>.yml You can do this by using the Rules UI in D8 to recreate the rules components you see in D7, then go to /admin/config/development/configuration and export the configuration file for the rule you just made.
  4. Manually test, in the Rules UI, that each rules component shows up and has the same arguments as it did in D7.
  5. Install https://www.drupal.org/project/issues/config_inspector then go to /admin/config/development/configuration/inspect and verify the configuration agrees with the schema. Fix it if it doesn't.
  6. Manually test the rules components by performing Ubercart operations that should invoke the rules and seeing if the expected action took place.
  7. Write SimpleTest test cases for each rules component. Many of these already exist, but have the Rules functionality commented out. These tests simulate a browser session and check to see that the expected actions occur - e.g. an order confirmation e-mail was received.

Remaining tasks

Task 1 has been performed. Help with the remaining tasks is appreciated. NOTE that the procedure in step 3 REQUIRES ALL EVENTS, CONDITIONS, and ACTIONS to work properly.

  1. Ubercart Rules Components are defined in D7 in hook_default_rules_configuration() and altered in hook_default_rules_configuration_alter(), by creating an instance of rules_reaction_rule() and programmatically adding pre-existing conditions, and/or actions to it. These hooks may be found in <modulename>/<modulename>.rules_defaults.inc. Refer to the D7 version of these files to ensure that you port ALL the Rules components that were in D7 Ubercart.
  2. Create configuration files for these components in D8. Configuration files should go into <modulename>/config/optional/ and be named rules.component.<rule machine name>.yml You can do this by using the Rules UI in D8 to recreate the rules components you see in D7, then go to /admin/config/development/configuration and export the configuration file for the rule you just made.
  3. Manually test, in the Rules UI, that each rules component shows up and has the same arguments as it did in D7.
  4. Install https://www.drupal.org/project/issues/config_inspector then go to /admin/config/development/configuration/inspect and verify the configuration agrees with the schema. Fix it if it doesn't.
  5. Manually test the rules components by performing Ubercart operations that should invoke the rules and seeing if the expected action took place.
  6. Write SimpleTest test cases for each rules component. Many of these already exist, but have the Rules functionality commented out. These tests simulate a browser session and check to see that the expected actions occur - e.g. an order confirmation e-mail was received.

Comments

TR created an issue. See original summary.

TR’s picture

In D7, Ubercart programmatically defines Rules Components based on the following patterns:

  • uc_payment_method_<payment_methodname>
  • get_quote_from_<shipping_quote_methodname>
  • uc_taxes_<tax_methodname>

So in D7 you will have a get_quote_from_xxx component for each shipping method you configure (each flatrate, each weightquote, etc. gets its own Rules Component).

Likewise, you will have a uc_payment_method_xxx component for each payment method you configure and a uc_tax_xxx component for each tax rate you configure.

The problem is there is not a 1-to-1 correspondence between modules and configurations for D8. For example, you can have many different flat rates defined, and Ubercart doesn't know ahead of time what those will be on any site, so Ubercart can't provide pre-built configurations for all the possibilities. Same for payment methods and tax rates.

I suppose we could provide a default configuration for each module (e.g. flatrate) then trigger on a new shipping quote added / a new payment method added / a new tax rate defined in order to copy this default configuration and save a customized new configuration for the added method ...

I will have to think on this and try some things out.

TR’s picture

Issue summary: View changes

In D7, we use Rules components like this example from uc_quote:

  $quote_data = array();
  foreach ($methods as $method) {
    $set = rules_config_load('get_quote_from_' . $method['id']);
    if (!$set || $set->execute($order)) {
      $data = uc_quote_action_get_quote($order, $method);

      foreach ($data as &$quote) {
        if (isset($quote['rate'])) {
          $quote['format'] = uc_currency_format($quote['rate']);
        }
      }
      $quote_data[$method['id']] = $data;
    }
  }

So the rules component is executed, then if the conditions defined by that component are satisfied we use the quote method, otherwise we skip it. In this case, we're using the component just to check conditions (e.g. that the delivery address is in a certain country/sate/zone, etc.) - we're not associating any rules actions with this component. The default definition of the get_quote_from_ component does nothing - it is just a rules_and() condition container which holds the $order object as context. Its utility is that once the component is defined, the site admin may use the Rules UI to customize the default component by adding conditions for each individual quote method. This makes the quote method configurable without programming.

In D8, we can do this by programmatically creating a RulesComponentConfig configuration entity for each quote method when that quote method (which is also a configuration entity) is created. Then load and execute() the RulesComponentConfig in the same way as the above.

This means step 3) above is irrelevant - we will never need to have configuration files provided for our components. But we will need the code to create and use these components. That looks like a very small amount of code to accomplish this task.