Allow address comparison rules to check multiple values in one condition

When setting up shipping I have a need to be able to change flat rate shipping based upon a list of countries or post codes in a country.

Using rules and working with 'Order address component comparison' unless I'm missing something you have to make a separate condition for each country/postcode when it would be much easier to include a list of values in one condition.

I've noticed a number of threads asking similar questions but I've found no published solution to this so I've written my own using hook_rules_condition_info_alter that adds 'is one of' and 'begins with one of'.

However it strikes me that it may be useful to others and in my opinion it would be worth altering the commerce_order.rules.inc file. What is the best way to suggest a change to the commerce core?

The only changes needed are to commerce_order.rules.inc and the changes are

Old code
<?php
function commerce_order_address_comparison_operator_options_list() {
return array(
'equals' => t('equals'),
'begins with' => t('begins with'),
'contains' => t('contains'),
);
}
?>

New code
<?php
function commerce_order_address_comparison_operator_options_list() {
return array(
'equals' => t('equals'),
'begins with' => t('begins with'),
'contains' => t('contains'),
'is one of' => t('is one of'),
'begins with one of' => t('begins with one of'),
);
}
?>

Old code
<?php
function commerce_order_rules_compare_address($order, $address_field, $component, $operator, $value) {
list($field_name, $address_field_name) = explode('|', $address_field);
// If we actually received a valid order...
if (!empty($order)) {
$wrapper = entity_metadata_wrapper('commerce_order', $order);
// And if we can actually find the requested address data...
if (!empty($wrapper->{$field_name}) && !empty($wrapper->{$field_name}->{$address_field_name})) {
$address = $wrapper->{$field_name}->{$address_field_name}->value();
// Make a comparison based on the operator.
switch ($operator) {
case 'equals':
return $address[$component] == $value;
case 'begins with':
return strpos($address[$component], $value) === 0;
case 'contains':
return strpos($address[$component], $value) !== FALSE;
}
}
}
return FALSE;
}
?>

New code
<?php
function commerce_order_rules_compare_address($order, $address_field, $component, $operator, $value) {
list($field_name, $address_field_name) = explode('|', $address_field);
// If we actually received a valid order...
if (!empty($order)) {
$wrapper = entity_metadata_wrapper('commerce_order', $order);
// And if we can actually find the requested address data...
if (!empty($wrapper->{$field_name}) && !empty($wrapper->{$field_name}->{$address_field_name})) {
$address = $wrapper->{$field_name}->{$address_field_name}->value();
// Make a comparison based on the operator.
switch ($operator) {
case 'equals':
return $address[$component] == $value;
case 'begins with':
return strpos($address[$component], $value) === 0;
case 'contains':
return strpos($address[$component], $value) !== FALSE;
case 'is one of':
$list = preg_split('/[\n\r]+/', $value);
return array_search($address[$component], $list) !== FALSE;
case 'begins with one of':
$list = preg_split('/[\n\r]+/', $value);
foreach ($list as $item) {
if(stripos($address[$component], $item) !== FALSE) {
return true;
}
}
}
}
}
return FALSE;
}
?>

Sorry it's not in the form of a patch but I'm not set up to produce them at the moment but hopefully the above will help someone else.

It only adds a couple off array elements and small switch statements but I've found the changes very helpful.

An example of my usage is I want to exclude free delivery to the UK post codes PO30 - PO41 so instead of entering multiple condition I can make one condition with 'begins with one of' and put the multiple values in it with each one separated with a new line.