[РЕШЕНО] Как преобразовать запятую в точку перед дробной частью в поле "Количество"

Главные вкладки

Аватар пользователя fox72 fox72 19 сентября 2015 в 11:33

Некоторые пользователи вводят в поле количество в качестве разделителя дробной и целой части запятую.
При добавлении товара в корзину, если введено значение типа "1,5" получаю следующее сообщение об ошибке
"Вы должны указать правильное значение количества для добавления в корзину."
А значение "1.5" проходит на ура.
Вопрос: Что можно сделать, чтобы злосчастная запятая преобразовывалась в точку?
Настроек для поля quantity (Line items) я не нашел.
Или может это вопрос локализации и я не туда копаю?

Комментарии

Аватар пользователя fox72 fox72 19 сентября 2015 в 19:49

"orion76" wrote:

Возможно это подойдет(Ввод значений по шаблону):
https://www.drupal.org/project/masked_input

Нет не действует на quantity этот чудесный модуль. Он хорош, когда создается новое поле и там можно выбрать виджет "ввод по маске" вместо "текстовое поле". Поле количество "quantity" вшито намертво его ни изменить ни удалить нельзя. А так бы было действительно неплохо

UPD. Обнаружил, что созданное таким макаром поле увеличивает введенное значение в 10 раз. Это чей глюк?

Аватар пользователя fox72 fox72 19 сентября 2015 в 20:19

"sasha_gar" wrote:
javascriptom подменяйте. либо хуком форму перехватывайте

Я малознаком с хуками Drupal, тем более не знаю какое поле в форме "перехватывать" и какой функцией его обрабатывать

javascript вообще не знаю.

Может поделитесь секретами?

Аватар пользователя fox72 fox72 19 сентября 2015 в 21:55

Хорошо, задам вопрос по другому:
Как можно реализовать хук, проверяющий ввод дробного значения в поле quantity (Количество) на наличие запятой и преобразующий ее в точку

Аватар пользователя Orion76 Orion76 20 сентября 2015 в 0:34

"fox72" wrote:
Может поделитесь секретами?

Это не секреты - это основы..

Судя по постановке вопроса, пинок в нужную сторону, как владеющего основами, Вам не подходит.

"fox72" wrote:
Хорошо, задам вопрос по другому:

Попробуйте еще раз..

Аватар пользователя fox72 fox72 20 сентября 2015 в 10:05

"orion76" wrote:
Попробуйте еще раз..

Да не вопрос... Smile

Где лежит тот заветный ман, в котором понятно описаны основы.

Для следующего кода пришлось перерыть полинтернета

<?php
function myhooksmodule_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state$form_id) {
    
$line_item $form_state['line_item'];
    
$product commerce_product_load($line_item->commerce_product[LANGUAGE_NONE][0]['product_id']);
    
dpm($product);
    if (
$product->type == 'hity_prodag' || $product->type == 'metallocherepica') {
    
// Change the submit button text to more appropriate "Pay Now"
    
$form['submit']['#value'] = t('Pay Now');
    
$form['#after_build'][] = 'myhooksmodule_after_build';

    }
}

function 

myhooksmodule_after_build($form, &$form_state) {
    
// Change the quantity title text to more appropriate "Area, square meters"
    
$form['quantity']['#title'] = t('Area, square meters');
    return 
$form;
}
?>

Взято из этой дискуссии

https://drupalcommerce.org/questions/7518/how-do-i-change-quantity-widge...

К данной теме этот код не относится и по правде говоря я не совсем вкурил, то что написал, но это сработало.
Но где там искать, какие элементы массива за ввод отвечают?
Это похоже секрет.

Аватар пользователя Orion76 Orion76 20 сентября 2015 в 10:09

ПРиведенный Вами выше хук ..._form_alter (hook_form_alter) "отвечает" за вывод формы.
А вам необходимо обрабатывать валидацию формы (проверку введенных пользователем данных).

Можно добавить функцию-валидатор как к самой форме:
https://api.drupal.org/api/drupal/developer!topics!forms_api_reference.h...

Так и к конкретному элементу формы:
https://api.drupal.org/api/drupal/developer!topics!forms_api_reference.h...

Введенные пользователем данные находятся в &$form_state['values'], а так как $form_state передается в обработчик по ссылке, то можно подкорректировать введенные пользователем данные.

Главное, чтоб один из этих хуков сработал до проверки(валидации) поля quantity на правильность "формата"(разделители разрядов) введенного пользователем числа.

ЗЫ.. И никаких секретов..
при написании коммента использовались, исключительно, ссылки на официальную документацию Drupal.

Аватар пользователя fox72 fox72 20 сентября 2015 в 11:01

"orion76" wrote:

ПРиведенный Вами выше хук ..._form_alter (hook_form_alter) "отвечает" за вывод формы.
А вам необходимо обрабатывать валидацию формы (проверку введенных пользователем данных).

Большое спасибо за подсказку. Пошел копать в нужном направлении. Smile

Аватар пользователя fox72 fox72 20 сентября 2015 в 13:33

Чего-то не выходит хук.
Нашел функцию commerce_cart_add_to_cart_form_validate
в модуле commerce_cart.module

Скоприровал ее код в свой модуль myhooksmodule

перименовал как положено.

Изменил немного - добавил "Use dot as decimal point" в сообщение об ошибке.

Получилось вот что:

<?php

function myhooksmodule_commerce_cart_add_to_cart_form_validate($form, &$form_state) {
  
// Check to ensure the quantity is valid.
  
if (!is_numeric($form_state['values']['quantity']) || $form_state['values']['quantity'] <= 0) {
    
form_set_error('quantity't('You must specify a valid quantity to add to the cart. Use dot as decimal point'));
  }

  

// If the custom data type attribute of the quantity element is integer,
  // ensure we only accept whole number values.
  
if ($form['quantity']['#datatype'] == 'integer' &&
    (int) 
$form_state['values']['quantity'] != $form_state['values']['quantity']) {
    
form_set_error('quantity't('You must specify a whole number for the quantity.'));
  }

  

// If the attributes matching product selector was used, set the value of the
  // product_id field to match; this will be fixed on rebuild when the actual
  // default product will be selected based on the product selector value.
  
if (!empty($form_state['values']['attributes']['product_select'])) {
    
form_set_value($form['product_id'], $form_state['values']['attributes']['product_select'], $form_state);
  }

  

// Validate any line item fields that may have been included on the form.
  
field_attach_form_validate('commerce_line_item'$form_state['line_item'], $form['line_item_fields'], $form_state);
}

?>

Даже очистил кэш. И ничего не произошло.

Если добавляю эту строчку непосредственно в оригинальный код функции, то срабатывает.

"Ничего не понимаю" (©, Колобок младший)

Аватар пользователя Orion76 Orion76 20 сентября 2015 в 14:56

Это не хук, а просто функция..
Чтобы она сработала для формы, ее надо "объявить" в хуке form_alter

$form['#validate'][]='myhooksmodule_commerce_cart_add_to_cart_form_validate';

Аватар пользователя fox72 fox72 20 сентября 2015 в 19:34

Безуспешно пытался впихнуть таким вот образом в myhooksmodule.module следующий код


<?php
function myhooksmodule_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state$form_id) {
    
$line_item $form_state['line_item'];
    
$product commerce_product_load($line_item->commerce_product[LANGUAGE_NONE][0]['product_id']);
    
dpm($product);
    if (
$product->type == 'hity_prodag' || $product->type == 'metallocherepica') {
    
// Change the submit button text to more appropriate "Pay Now"
        
$form['#validate'][] = 'myhooksmodule_commerce_cart_add_to_cart_form_validate';
    
$form['submit']['#value'] = t('Pay Now');
    
$form['#after_build'][] = 'myhooksmodule_after_build';
    }

}

function 

myhooksmodule_after_build($form, &$form_state) {
    
// Change the quantity title text to more appropriate "Area, square meters"
    
$form['quantity']['#title'] = t('Area, square meters. Use dot as decimal point');
    return 
$form;
    
}

function 

myhooksmodule_commerce_cart_add_to_cart_form_validate($form, &$form_state) {
  
// Check to ensure the quantity is valid.
  
if (!is_numeric($form_state['values']['quantity']) || $form_state['values']['quantity'] <= 0) {
    
form_set_error('quantity't('You must specify a valid quantity to add to the cart. Use dot as decimal point'));
  }

  

// If the custom data type attribute of the quantity element is integer,
  // ensure we only accept whole number values.
  
if ($form['quantity']['#datatype'] == 'integer' &&
    (int) 
$form_state['values']['quantity'] != $form_state['values']['quantity']) {
    
form_set_error('quantity't('You must specify a whole number for the quantity.'));
  }

  

// If the attributes matching product selector was used, set the value of the
  // product_id field to match; this will be fixed on rebuild when the actual
  // default product will be selected based on the product selector value.
  
if (!empty($form_state['values']['attributes']['product_select'])) {
    
form_set_value($form['product_id'], $form_state['values']['attributes']['product_select'], $form_state);
  }

  

// Validate any line item fields that may have been included on the form.
  
field_attach_form_validate('commerce_line_item'$form_state['line_item'], $form['line_item_fields'], $form_state);
}

?>

Собственно myhooksmodule_commerce_cart_add_to_cart_form_validate должна переопределять
аналогичную функцию commerce_cart_add_to_cart_form_validate в модуле commerce_cart.module
Но по неведомым мне причинам этого не происходит.
Хотя если в commerce_cart.module заменить строчку

<?php  $form['#validate'][] = 'commerce_cart_add_to_cart_form_validate';?>

на

<?php $form['#validate'][] = 'myhooksmodule_commerce_cart_add_to_cart_form_validate';?>

то это срабатывает.

Вопрос: Как мне переопределить эту функцию?

Аватар пользователя fox72 fox72 23 сентября 2015 в 22:44

Дальше еще интереснее.
В переводах встроенного интерфейса нижеприведенная строчка присутствует аж два раза.
You must specify a valid quantity to add to the cart. Use dot as decimal point.
И ниже под ней указывается для какого типа вариации товара
/content/proflist-c-8h1150-ocinkovannyy
А вылазит все равно старый перевод.O_o

Аватар пользователя fox72 fox72 28 сентября 2015 в 22:31

Путем блужданий в непролазной тьме,
И в окруженьи равнодушной тишины,
была обретена незыблемая нить,
Что к горизонту истины приблизила меня немного...

Ну это лирика...

Мною был установлен модуль Devel.
Ниже по коду видно, где были сделаны вставки отладочных функций

<?php
function myhooksmodule_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state$form_id) {
    
$form['#validate'][] = 'myhooksmodule_decimal_quantities_validate';
    
$line_item $form_state['line_item'];
    
$product commerce_product_load($line_item->commerce_product[LANGUAGE_NONE][0]['product_id']);
    
ddebug_backtrace();
    
dpm($product);
    if (
$product->type == 'hity_prodag' || $product->type == 'metallocherepica') {
    
$form['#validate'][0] = 'myhooksmodule_decimal_quantities_validate';
    
// Change the submit button text to more appropriate "Pay Now"
    
$form['submit']['#value'] = t('Pay Now');
    
$form['#after_build'][] = 'myhooksmodule_after_build';
    }
    
dpm($form);
}

function 

myhooksmodule_after_build($form, &$form_state) {
    
// Change the quantity title text to more appropriate "Area, square meters"
    
$form['quantity']['#title'] = t('Area, square meters. Use dot as decimal point');
    return 
$form;
    
}

function 

myhooksmodule_decimal_quantities_validate($form, &$form_state) {
  
// Check to ensure the quantity is valid.
  
if (!is_numeric($form_state['values']['quantity']) || $form_state['values']['quantity'] <= 0) {
    
form_set_error('quantity't('You must specify a valid quantity to add to the cart. Use dot as decimal point'));
  }

  

// If the custom data type attribute of the quantity element is integer,
  // ensure we only accept whole number values.
  
if ($form['quantity']['#datatype'] == 'integer' &&
    (int) 
$form_state['values']['quantity'] != $form_state['values']['quantity']) {
    
form_set_error('quantity't('You must specify a whole number for the quantity.'));
  }

  

// If the attributes matching product selector was used, set the value of the
  // product_id field to match; this will be fixed on rebuild when the actual
  // default product will be selected based on the product selector value.
  
if (!empty($form_state['values']['attributes']['product_select'])) {
    
form_set_value($form['product_id'], $form_state['values']['attributes']['product_select'], $form_state);
  }

  

// Validate any line item fields that may have been included on the form.
  
field_attach_form_validate('commerce_line_item'$form_state['line_item'], $form['line_item_fields'], $form_state);
  
}
?>

Экспериментальным путем было установлено, что массив #validate содержит такие значения переменных

#validate (Array, 3 elements)

0 (String, 39 characters) commerce_cart_add_to_cart_form_validate (Callback) commerce_cart_add_to_cart_form_validate();
$...['#validate'][0]
1 (String, 41 characters) myhooksmodule_decimal_quantities_validate (Callback) myhooksmodule_decimal_quantities_validate();
$...['#validate'][1]
2 (String, 41 characters) myhooksmodule_decimal_quantities_validate (Callback) myhooksmodule_decimal_quantities_validate();
$...['#validate'][2]

После этого было предположено, что в нулевой ячейке массива должна быть строковое значение 'myhooksmodule_decimal_quantities_validate', что собственно и проделано в коде указаном выше.

Это сработало.
Вопрос к старому следопыту —
Насколько верно взят след корректно, то что я сотворил с кодом?
Сомнения возникают потому, что теперь массив #validate содержит две строки одинакового содержания

#validate (Array, 2 elements)

0 (String, 41 characters) myhooksmodule_decimal_quantities_validate (Callback) myhooksmodule_decimal_quantities_validate();
$...['#validate'][0]
1 (String, 41 characters) myhooksmodule_decimal_quantities_validate (Callback) myhooksmodule_decimal_quantities_validate();
$...['#validate'][1]

И еще. А возможно ли здесь применить какую-либо функцию php для работы с регулярными выражениями?

Аватар пользователя fox72 fox72 29 сентября 2015 в 22:28

пока вот как-то так

Изменил следующим образом стандартую функцию commerce_cart_add_to_cart_form_validate из commerce_cart.module

<?phpfunction myhooksmodule_decimal_quantities_validate($form, &$form_state) {
  // Check to ensure the quantity is valid.
  if (preg_match("/\d+[!,&?]\d+$/", $form_state['values']['quantity'])) {
    $form_state['values']['quantity']=preg_replace("/[!,&?]/", ".", $form_state['values']['quantity']);
   // form_set_error('quantity', t('You must specify a valid quantity to add to the cart. Use dot as decimal point'));
  }
  if (!is_numeric($form_state['values']['quantity']) || $form_state['values']['quantity'] <= 0) {
    form_set_error('quantity', t('You must specify a valid quantity to add to the cart. Use dot as decimal point'));
  }
  
  // If the custom data type attribute of the quantity element is integer,
  // ensure we only accept whole number values.
  if ($form['quantity']['#datatype'] == 'integer' &&
    (int) $form_state['values']['quantity'] != $form_state['values']['quantity']) {
    form_set_error('quantity', t('You must specify a whole number for the quantity.'));
  }

  // If the attributes matching product selector was used, set the value of the
  // product_id field to match; this will be fixed on rebuild when the actual
  // default product will be selected based on the product selector value.
  if (!empty($form_state['values']['attributes']['product_select'])) {
    form_set_value($form['product_id'], $form_state['values']['attributes']['product_select'], $form_state);
  }

  // Validate any line item fields that may have been included on the form.
  field_attach_form_validate('commerce_line_item', $form_state['line_item'], $form['line_item_fields'], $form_state);
  
}?>

Думаю, что такого сотворил.
Слава php?

Аватар пользователя fox72 fox72 1 октября 2015 в 23:46

В общем содержимое файла myhooksmodule.module приобрело следующий вид

<?phpfunction myhooksmodule_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state, $form_id) {
    $form['#validate'][] = 'myhooksmodule_decimal_quantities_validate';
    $line_item = $form_state['line_item'];
    $product = commerce_product_load($line_item->commerce_product[LANGUAGE_NONE][0]['product_id']);
    // Присвоение quantity нулевого значения по умолчанию
    $form['quantity']['#default_value'] = 0.0;
    if ($product->type == 'hity_prodag' || $product->type == 'metallocherepica') {
    $form['#validate'][0] = 'myhooksmodule_decimal_quantities_validate';
    // Change the submit button text to more appropriate "Pay Now"
    $form['submit']['#value'] = t('Pay Now');
    $form['#after_build'][] = 'myhooksmodule_after_build';
    }
}

function myhooksmodule_after_build($form, &$form_state) {
    // Change the quantity title text to more appropriate "Area, square meters"
    $form['quantity']['#title'] = t('Area, square meters. Use dot as decimal point');
    return $form;
    
}

function myhooksmodule_decimal_quantities_validate($form, &$form_state) {
  // Проверка для поля quantity ошибок ввода знака десятичного делителя и замена на точку .
  if (preg_match("/\d+[!,&?]\d+$/", $form_state['values']['quantity'])) {
    $form_state['values']['quantity']=preg_replace("/[!,&?]/", ".", $form_state['values']['quantity']);
  }
     // Если введенное в поле quantity значение не является числом или отрицательное, 
     //то присваивается значение по умолчанию.
  if (!is_numeric($form_state['values']['quantity']) || $form_state['values']['quantity'] < 0) {
      $form_state['values']['quantity']=$form['quantity']['#default_value'];
  }

  
  // If the custom data type attribute of the quantity element is integer,
  // ensure we only accept whole number values.
  if ($form['quantity']['#datatype'] == 'integer' &&
    (int) $form_state['values']['quantity'] != $form_state['values']['quantity']) {
    form_set_error('quantity', t('You must specify a whole number for the quantity.'));
  }

  // If the attributes matching product selector was used, set the value of the
  // product_id field to match; this will be fixed on rebuild when the actual
  // default product will be selected based on the product selector value.
  if (!empty($form_state['values']['attributes']['product_select'])) {
    form_set_value($form['product_id'], $form_state['values']['attributes']['product_select'], $form_state);
  }

  // Validate any line item fields that may have been included on the form.
  field_attach_form_validate('commerce_line_item', $form_state['line_item'], $form['line_item_fields'], $form_state);
  
}

function myhooksmodule_form_alter(&$form, &$form_state, $form_id) {

  // Fix order total translation
  if (isset($form['cart_contents'])){
    $form['cart_contents']['cart_contents_view']['#markup'] = str_replace('Order total', t('Order total'), $form['cart_contents']['cart_contents_view']['#markup']);

    
  }
  // Fix translation on checkout form
  if ($form['#id'] == 'commerce-checkout-form-checkout'){
    if(isset($form['customer_profile_billing'])){
      $form['customer_profile_billing']['#title'] = t('Billing information');
    }
    if (isset($form['customer_profile_shipping'])){
      $form['customer_profile_shipping']['#title'] = t('Shipping information');
    }
  }
  // Fix translation on checkout review
  if ($form['#id'] == 'commerce-checkout-form-review'){
    if (isset($form['checkout_review']['review']['#data']['customer_profile_billing'])){
      $form['checkout_review']['review']['#data']['customer_profile_billing']['title'] = t('Billing information');
    }
    if (isset($form['checkout_review']['review']['#data']['customer_profile_shipping'])){
      $form['checkout_review']['review']['#data']['customer_profile_shipping']['title'] = t('Shipping information');
    }
    //Исправление перевода Order total на странице проверки данных перед отправкой заказа  
    if (isset($form['checkout_review']['review']['#data']['cart_contents'])){
      $form['checkout_review']['review']['#data']['cart_contents']['data'] = str_replace('Order total', t('Order total'), $form['checkout_review']['review']['#data']['cart_contents']['data']);
    }
  }
}?>

Тему можно считать закрытой. Вопрос решен. Правда не знаю насколько корректно.

Аватар пользователя fox72 fox72 4 октября 2015 в 10:18

Оказывается, похожая проблема вылезает при просмотре позиций заказа
и изменении количества непосредственно в самой корзине.
При вводе в поле "Количество" невалидного значения вылезает сообщение
«Вы должны указать положительное значение количества»
или на ангельском
«You must specify a positive number for the quantity»
Прочесав директорию commerce выяснил что функция views_form_validate
которая генерирует это сообщение входит в состав
класса commerce_line_item_handler_field_edit_quantity
из файла
commerce/modules/line_item/includes/views/handlers/commerce_line_item_handler_field_edit_quantity.inc

Если переписать функцию непосредственно в этом файле как описано ниже, то все работает

<?php  function views_form_validate($form, &$form_state) {
    
$field_name $this->options['id'];
    foreach (
element_children($form[$field_name]) as $row_id) {
      
// Ensure the quantity is actually a numeric value.

      

if (preg_match("/\d+[!,&?]\d+$/"$form_state['values'][$field_name][$row_id])) {
    
$form_state['values'][$field_name][$row_id]=preg_replace("/[!,&?]/""."$form_state['values'][$field_name][$row_id]);
      }
      
      if (!
is_numeric($form_state['values'][$field_name][$row_id]) || $form_state['values'][$field_name][$row_id] < 0) {
        
form_set_error($field_name '][' $row_idt('You must specify a positive number for the quantity'));
      }

      

// If the custom data type attribute of the quantity element is integer,
      // ensure we only accept whole number values.
      
if ($form[$field_name][$row_id]['#datatype'] == 'integer' &&
        (int) 
$form_state['values'][$field_name][$row_id] != $form_state['values'][$field_name][$row_id]) {
        
form_set_error($field_name '][' $row_idt('You must specify a whole number for the quantity.'));
      }
    }
  }
?>

Вопрос: Как теперь ее переписать в myhooksmodule? Ну не переписывать же весь класс?

Аватар пользователя fox72 fox72 4 октября 2015 в 12:11

Кхм.
Если полностью запихнуть класс commerce_line_item_handler_field_edit_quantity в myhooksmodule и переписать в нем функцию views_form_validate как в предыдущем моем посте, а потом добавить функцию

<?phpfunction myhooksmodule_form_views_form_commerce_cart_form_default_alter(&$form, &$form_state, $form_id) {
    $form['#validate'][] = 'views_form_views_form_validate';
}?>

то все как бы ОК.

Что-то мне подсказывает, что сие не кошерно. Но попытка создать расширенный класс
myhooksmodule_commerce_line_item_handler_field_edit_quantity
с переписанной функцией views_form_validate должного эффекта не возымела.

Когда же уже дно?