Некоторые пользователи вводят в поле количество в качестве разделителя дробной и целой части запятую.
При добавлении товара в корзину, если введено значение типа "1,5" получаю следующее сообщение об ошибке
"Вы должны указать правильное значение количества для добавления в корзину."
А значение "1.5" проходит на ура.
Вопрос: Что можно сделать, чтобы злосчастная запятая преобразовывалась в точку?
Настроек для поля quantity (Line items) я не нашел.
Или может это вопрос локализации и я не туда копаю?
Комментарии
Возможно это подойдет(Ввод значений по шаблону):
https://www.drupal.org/project/masked_input
javascriptom подменяйте. либо хуком форму перехватывайте
Нет не действует на quantity этот чудесный модуль. Он хорош, когда создается новое поле и там можно выбрать виджет "ввод по маске" вместо "текстовое поле". Поле количество "quantity" вшито намертво его ни изменить ни удалить нельзя. А так бы было действительно неплохо
UPD. Обнаружил, что созданное таким макаром поле увеличивает введенное значение в 10 раз. Это чей глюк?
Я малознаком с хуками Drupal, тем более не знаю какое поле в форме "перехватывать" и какой функцией его обрабатывать
javascript вообще не знаю.
Может поделитесь секретами?
Хорошо, задам вопрос по другому:
Как можно реализовать хук, проверяющий ввод дробного значения в поле quantity (Количество) на наличие запятой и преобразующий ее в точку
Это не секреты - это основы..
Судя по постановке вопроса, пинок в нужную сторону, как владеющего основами, Вам не подходит.
Попробуйте еще раз..
Да не вопрос...
Где лежит тот заветный ман, в котором понятно описаны основы.
Для следующего кода пришлось перерыть полинтернета
<?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...
К данной теме этот код не относится и по правде говоря я не совсем вкурил, то что написал, но это сработало.
Но где там искать, какие элементы массива за ввод отвечают?
Это похоже секрет.
ПРиведенный Вами выше хук ..._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.
Большое спасибо за подсказку. Пошел копать в нужном направлении.
Чего-то не выходит хук.
Нашел функцию 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) {
// If the custom data type attribute of the quantity element is integer,
// If the attributes matching product selector was used, set the value of the
// Validate any line item fields that may have been included on the form.
// 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'));
}
// 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.'));
}
// 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);
}
field_attach_form_validate('commerce_line_item', $form_state['line_item'], $form['line_item_fields'], $form_state);
} ?>
Даже очистил кэш. И ничего не произошло.
Если добавляю эту строчку непосредственно в оригинальный код функции, то срабатывает.
"Ничего не понимаю" (©, Колобок младший)
Это не хук, а просто функция..
Чтобы она сработала для формы, ее надо "объявить" в хуке form_alter
$form['#validate'][]='myhooksmodule_commerce_cart_add_to_cart_form_validate';
Безуспешно пытался впихнуть таким вот образом в 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'));
}
// 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.'));
}
// 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);
}
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';?>
то это срабатывает.
Вопрос: Как мне переопределить эту функцию?
Дальше еще интереснее.
В переводах встроенного интерфейса нижеприведенная строчка присутствует аж два раза.
You must specify a valid quantity to add to the cart. Use dot as decimal point.
И ниже под ней указывается для какого типа вариации товара
/content/proflist-c-8h1150-ocinkovannyy
А вылазит все равно старый перевод.O_o
Путем блужданий в непролазной тьме,
И в окруженьи равнодушной тишины,
была обретена незыблемая нить,
Что к горизонту истины приблизила меня немного...
Ну это лирика...
Мною был установлен модуль Devel.
Ниже по коду видно, где были сделаны вставки отладочных функций
<?php
// If the custom data type attribute of the quantity element is integer,
// If the attributes matching product selector was used, set the value of the
// Validate any line item fields that may have been included on the form.
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'));
}
// 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.'));
}
// 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);
}
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 для работы с регулярными выражениями?
пока вот как-то так
Изменил следующим образом стандартую функцию 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?
В общем содержимое файла 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']);
}
}
}?>
Тему можно считать закрытой. Вопрос решен. Правда не знаю насколько корректно.
И еще...
Модуль Devel и Search Krumo - это сила!
Оказывается, похожая проблема вылезает при просмотре позиций заказа
и изменении количества непосредственно в самой корзине.
При вводе в поле "Количество" невалидного значения вылезает сообщение
«Вы должны указать положительное значение количества»
или на ангельском
«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) {
if (preg_match("/\d+[!,&?]\d+$/", $form_state['values'][$field_name][$row_id])) {
// If the custom data type attribute of the quantity element is integer,
$field_name = $this->options['id'];
foreach (element_children($form[$field_name]) as $row_id) {
// Ensure the quantity is actually a numeric value.
$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_id, t('You must specify a positive number for the quantity'));
}
// 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_id, t('You must specify a whole number for the quantity.'));
}
}
}?>
Вопрос: Как теперь ее переписать в myhooksmodule? Ну не переписывать же весь класс?
Кхм.
Если полностью запихнуть класс 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 должного эффекта не возымела.
Когда же уже дно?