Большие цены в Drupal Commerce

В Drupal Commerce имеется одна неприятная особенность, с которой может столкнуться каждый. Проблема заключается в том, что в базе данных у цен размер равен int(11). Но существует ряд стран, например Беларусь, где цена 30 000 000.00 и больше - вполне нормальное явление. И тут начинаются проблемы, при попытке оформить заказ с такой ценой - система безотказно будет информировать нас о том, что цена выходит за границы размера поля.

Чтобы исправить эту проблему, имплементируем хук hook_field_create_field():

<?php

/**
 * Implements hook_field_create_field().
 */
function example_field_create_field($field) {
  if ($field['module'] == 'commerce_price'
    && $field['type'] == 'commerce_price'
    && isset($field['columns']['amount']['type'])
    && $field['columns']['amount']['type'] == 'int'
    && (!isset($field['columns']['amount']['type']) || $field['columns']['amount']['type'] != 'big')) {

    $spec = $field['columns']['amount'];
    $spec['size'] = 'big';
    foreach (array('field_data_', 'field_revision_') as $prefix) {
      $table = $prefix . $field['field_name'];
      $column = $field['field_name'] . '_amount';
      db_change_field($table, $column, $column, $spec);
    }
  }
}

Теперь при создании новых "commerce_price" полей, их размер будет изменен на big. Модуль с этим хуком необходимо включить до того, как будет установлен Drupal Commerce.

Для обновления всех существующих полей, необходимо открыть консоль и воспользоваться командой:

drush eval 'foreach (field_info_fields() as $field) { example_field_create_field($field); }'

Update

С момента написания урока, прошло немало времени и код, который работал в момент написания вдруг перестал работать. Вооружившись дебагером я посмотрел, что же пошло не так и как оказалось, что каждый раз, когда мы сохраняем настройки поля, вызвается функция field_update_field(), которая обновляет схему поля на дефолтную. Что ж, немного модифицируем наш модуль.

Для начала напишем новую функцию, которая будет изменять схему поля:

/**
 * Updates a size of "amount" column for commerce_price field.
 *
 * @param array $field
 *   A field structure. $field['field_name'] must provided; it identifies the
 *   field that will be updated to match this structure. Any other properties
 *   of the field that are not specified in $field will be left unchanged,
 *   so it is not necessary to pass in a fully populated $field structure.
 */
function _example_commerce_price_update_field($field) {
  if ($field['module'] == 'commerce_price'
    && $field['type'] == 'commerce_price'
    && isset($field['columns']['amount']['type'])
    && $field['columns']['amount']['type'] == 'int'
    && (!isset($field['columns']['amount']['type']) || $field['columns']['amount']['type'] != 'big')) {

    $spec = $field['columns']['amount'];
    $spec['size'] = 'big';
    foreach (array('field_data_', 'field_revision_') as $prefix) {
      $table = $prefix . $field['field_name'];
      if (db_table_exists($table)) {
        $column = $field['field_name'] . '_amount';
        db_change_field($table, $column, $column, $spec);
      }
    }
  }
}

Далее имплементируем хуки hook_field_create_field() и hook_field_update_field():

/**
 * Implements hook_field_create_field().
 */
function example_field_create_field($field) {
  _example_commerce_price_update_field($field);
}

/**
 * Implements hook_field_update_field().
 */
function example_field_update_field($field, $prior_field, $has_data) {
  _example_commerce_price_update_field($field);
}
Benya