When the WordPress language / locale is configured to nl_NL
the MeprSubscription->total
value is calculated / stored incorrect. This is due to the incorrect handling in MeprSubscriptionsCtrl->create_or_update( $sub )
and MeprUtils::format_currency_us_float( $number, $num_decimals = 2 )
.
app/lib/MeprUtils.php#L381-L408
/**
* Converts number to US format
*
* @param mixed $number
* @param mixed $num_decimals
* @return void
*/
public static function format_currency_us_float($number, $num_decimals = 2) {
global $wp_locale;
if ( ! isset( $wp_locale ) || false === function_exists('number_format_i18n') ) {
return self::format_float($number, $num_decimals);
}
$decimal_point = $wp_locale->number_format['decimal_point'];
$thousands_sep = $wp_locale->number_format['thousands_sep'];
// Remove thousand separator
$number = str_replace ($thousands_sep, '' , $number);
// Replaces decimal separator
$index = strrpos( $number, $decimal_point );
if( $index !== FALSE ){
$number[ $index ] = '.';
}
return (float) $number;
}
When the WordPress language / locale is configured to nl_NL
this function will work with the following values:
// In `nl_NL` this will be a comma character: ','.
$decimal_point = $wp_locale->number_format['decimal_point'];
// In `nl_NL` this will be a full stop (period) character: '.'.
$thousands_sep = $wp_locale->number_format['thousands_sep'];
When a Dutch user enters for example a price of 9,99
this means 9
euros and 99
cents. It should be stored a 9.99
in the database, but it's stored as 999
. This is due to the following code:
app/controllers/MeprSubscriptionsCtrl.php#L137-L172
private function create_or_update($sub) {
check_admin_referer( 'mepr_create_or_update_subscription', 'mepr_subscriptions_nonce' );
extract($_POST, EXTR_SKIP);
$user = new MeprUser();
$user->load_user_data_by_login($user_login);
$sub->user_id = $user->ID;
$sub->subscr_id = wp_unslash($subscr_id);
$sub->product_id = $product_id;
$product = new MeprProduct($product_id);
$sub->price = isset($price) ? MeprUtils::format_currency_us_float( $price ) : MeprUtils::format_currency_us_float( $product->price );
$sub->period = isset($period) ? (int) $period : (int) $product->period;
$sub->period_type = isset($period_type) ? (string) $period_type : (string) $product->period_type;
$sub->limit_cycles = isset($limit_cycles) ? (boolean) $limit_cycles : $product->limit_cycles;
$sub->limit_cycles_num = isset($limit_cycles_num) ? (int) $limit_cycles_num : (int) $product->limit_cycles_num;
$sub->limit_cycles_action = isset($limit_cycles_action) ? $limit_cycles_action : $product->limit_cycles_action;
$sub->limit_cycles_expires_after = isset($limit_cycles_expires_after) ? (int) $limit_cycles_expires_after : (int) $product->limit_cycles_expires_after;
$sub->limit_cycles_expires_type = isset($limit_cycles_expires_type) ? (string) $limit_cycles_expires_type : (string) $product->limit_cycles_expires_type;
$sub->tax_amount = MeprUtils::format_currency_us_float( $tax_amount );
$sub->tax_rate = MeprUtils::format_currency_us_float( $tax_rate );
$sub->total = MeprUtils::format_currency_us_float( $sub->price + $sub->tax_amount );
$sub->status = $status;
$sub->gateway = $gateway;
$sub->trial = isset($trial) ? (boolean) $trial : false;
$sub->trial_days = (int) $trial_days;
$sub->trial_amount = MeprUtils::format_currency_us_float( $trial_amount );
$sub->trial_tax_amount = (isset($trial_tax_amount) ? (float) $trial_tax_amount : 0.0);
$sub->trial_total = (isset($trial_total) ? (float) $trial_total : 0.0);
if(isset($created_at) && (empty($created_at) || is_null($created_at))) {
$sub->created_at = MeprUtils::ts_to_mysql_date(time());
}
else {
$sub->created_at = MeprUtils::ts_to_mysql_date(strtotime($created_at));
}
return $sub->store();
}
On app/controllers/MeprSubscriptionsCtrl.php#L147
the submitted $_POST['price']
of 9,99
is converted to 9.99
and stored in $sub->price
. On app/controllers/MeprSubscriptionsCtrl.php#L157
this value is passed to the MeprUtils::format_currency_us_float( )
function again and then it goes wrong. The $thousands_sep = '.'
is replaced by an empty string ''
and this will convert 9.99
to 999
.