Creating a loop condition in Rules for Commerce Line items Certain products on the site can't be shipped using a certain shipping service as they are classified as dangerous goods.

So I need to be able to loop through all the items in the cart, check to see if the product has is marked as dangerous (field_dangerous_goods on the commerce_product entity), if any of the products in the order are marked as dangerous goods then that shipping service shouldn't be shown to the user.

I've tried with various different rule components to try and create what I need with not even a glimmer of hope.
Figured it out.

Firstly, you'll need Conditional Rules.

Create a new rule component.

For the variables, add Commerce Line Item as a Parameter and add a Integer as Provided.

Under Conditions, add Entity has field, select commerce_product. Then add another Entity has field and select your field_dangerous_goods field from line-item:commerce-product. Lastly add a data comparison to check the status of the dangerous goods field. In my case I just had a checkbox, so I used Data value is empty and checked the Negate box.

This makes the condition return TRUE if the current line item is a dangerous item.

Under Actions, choose Add action and select the Set a data value option. For this set the parameter to the variable you created when you set up the component. Set the value to 1.

{ "rules_dangerous_goods" : {
    "LABEL" : "Dangerous goods",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "USES VARIABLES" : {
      "line_item" : { "label" : "Line Item", "type" : "commerce_line_item" },
      "dangerous_goods" : { "label" : "Dangerous Goods", "type" : "integer", "parameter" : false }
    },
    "IF" : [
      { "entity_has_field" : { "entity" : [ "line-item" ], "field" : "commerce_product" } },
      { "entity_has_field" : {
          "entity" : [ "line-item:commerce-product" ],
          "field" : "field_dangerous_goods"
        }
      },
      { "NOT data_is_empty" : { "data" : [ "line-item:commerce-product:field-dangerous-goods" ] } }
    ],
    "DO" : [ { "data_set" : { "data" : [ "dangerous-goods" ], "value" : "1" } } ],
    "PROVIDES VARIABLES" : [ "dangerous_goods" ]
  }
}


Then for your shipping service rule, under Actions, choose Add action. Select Add a variable, I called mine Contains Dangerous Goods (contains_dangerous_goods). Set the value to 0.

Add a loop.

Then Add action to the loop. Select your component. You'll need to set the variable name, this has to be different to the Contains Dangerous Goods variable from before, I just called mine Dangerous Good (dangerous_good).

Now choose Add conditional to the loop. Then for the conditional, choose Add if. Select the *dangerous_good* which we just set in the loop in the component action. Set the value to 1.

Within the If, choose Add action. Select Set a data value. For the field, choose the contains_dangerous_goods value. This is the initial variable we set for the shipping service rule. Set the value to 1.

Now outside of the loop, Add conditional. Then Add if. Choose the *contains_dangerous_goods* field and set the value to 0.

Then within the If, add your shipping rate.

{ "commerce_shipping_service_standard_up_to_0_5kg" : {
    "LABEL" : "Rate Standard - Up to 0.5kg",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "REQUIRES" : [
      "commerce_order",
      "commerce_physical",
      "rules",
      "rules_conditional",
      "commerce_shipping"
    ],
    "USES VARIABLES" : { "commerce_order" : { "label" : "Order", "type" : "commerce_order" } },
    "IF" : [],
    "DO" : [
      { "variable_add" : {
          "USING" : { "type" : "integer", "value" : "0" },
          "PROVIDE" : { "variable_added" : { "contains_dangerous_goods" : "Contains Dangerous Goods" } }
        }
      },
      { "LOOP" : {
          "USING" : { "list" : [ "commerce-order:commerce-line-items" ] },
          "ITEM" : { "list_item" : "Current list item" },
          "DO" : [
            { "component_rules_dangerous_goods" : {
                "USING" : { "line_item" : [ "list-item" ] },
                "PROVIDE" : { "dangerous_good" : { "dangerous_good" : "Dangerous Goods" } }
              }
            },
            { "CONDITIONAL" : [
                {
                  "IF" : { "data_is" : { "data" : [ "dangerous-good" ], "value" : "1" } },
                  "DO" : [
                    { "data_set" : { "data" : [ "contains-dangerous-goods" ], "value" : "1" } }
                  ]
                }
              ]
            }
          ]
        }
      },
      { "CONDITIONAL" : [
          {
            "IF" : { "data_is" : { "data" : [ "contains-dangerous-goods" ], "value" : "0" } },
            "DO" : [
              { "commerce_shipping_service_rate_order" : {
                  "shipping_service_name" : "standard_up_to_0_5kg",
                  "commerce_order" : [ "commerce-order" ]
                }
              }
            ]
          }
        ]
      }
    ]
  }
}