Программно изменять пользовательские панели оформления заказа в зависимости от количества в корзине


В процессе оформления заказа мне нужно собрать дополнительные данные в зависимости от количества в корзине.

О чем это?

  • Клиенты бронируют поездки
  • Для аргументации предположим, что 2 пары влюбленных бронируют неделю в Венеции: они добавят 4 "поездки в Венецию" в корзину
  • Во время оформления заказа я собираю обычные данные клиента, а также дополнительную информацию (имя, паспорт, день рождения...) для каждого другого участника в динамическая настраиваемая панель.

Моя текущая работа:

  1. Настройте пользовательскую панель с Панелями коммерческих групп полей , отключенными по умолчанию
  2. Добавьте правило с Дополнительными правилами торговли , которое включает панель, если кол-во > 1 для определенного типа продукта
  3. Затем с помощью MYMODULE_form_FORM_ID_alter я попробовал 2 разных способа добавления соответствующих полей:

Первый: дублируйте всю пользовательскую панель на странице оформления заказа :

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

  $order = $form_state['build_info']['args'][0];
  //load line item
  $line_item = commerce_line_item_load($order->commerce_line_items['und'][0]['line_item_id']);
  //get quantity
  $qty = round($line_item->quantity);

  //duplicate the pane for each participant (minus the customer user) 
  for($n=1; $n<$qty; $n++) {
    $form['commerce_fieldgroup_pane__group_pax_sup_'.$n] = array_merge(array(), $form['commerce_fieldgroup_pane__group_pax_sup']);
  }
}

В панель дублируется нормально, но поля дублированных панелей не сохраняются и не отображаются на следующем шаге. Может быть, потому, что я должен сообщить системе, что эти ЯВЛЯЮТСЯ областями проверки, +последующие обратные вызовы (как в модуле checkout_pane_example) ?

Если это так, я не нахожу , как объявить добавленные панели контрольными внутри этого цикла.


Второе: дублируйте каждое поле пользовательской панели внутри самой панели оформления заказа :

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

  $order = $form_state['build_info']['args'][0];
  //load line item
  $line_item = commerce_line_item_load($order->commerce_line_items['und'][0]['line_item_id']);
  //get quantity
  $qty = round($line_item->quantity);

  //duplicate the pane for each participant (minus the customer user) 
  for($n = 1; $n<$qty; $n++) {

    foreach ($form['commerce_fieldgroup_pane__group_pax_sup'] as $key => $value) {

      //searching fields into the fieldgroup array
      if(substr($key, 0, 5) == 'field') {

        //we duplicate the field
        $form['commerce_fieldgroup_pane__group_pax_sup'][$key.'_'.$n] = array_merge(array(), $form['commerce_fieldgroup_pane__group_pax_sup'][$key]);
        //rename field to have it unique
        $form['commerce_fieldgroup_pane__group_pax_sup'][$key.'_'.$n]['und'][0]['#field_name'] = $form['commerce_fieldgroup_pane__group_pax_sup'][$key.'_'.$n]['und'][0]['#field_name'].'_'.$n;
        //add it to the fieldgroup : NOT SURE WHICH IS THE RIGHT ONE OR IF I MUST LEAVE ALL
        $group_pax_sup = $form['commerce_fieldgroup_pane__group_pax_sup']['#groups']['group_pax_sup'];
        $group_pax_sup->children[] = $key.'_'.$n;  
        $form['commerce_fieldgroup_pane__group_pax_sup']['#group_children'][$key.'_'.$n] = 'group_pax_sup' ;
      }
    }
  }

Это правильное добавление полей, но опять же ничего не сохраняется и не отображается на следующих шагах. Здесь кажется, что мне не удается правильно добавить поля в группу полей?

Как я мог этого добиться? Большое вам спасибо!

 1
Author: Kojo, 2014-07-30

2 answers

Мне пришло в голову, что может быть хороший способ сделать это с помощью contrib, поэтому я опущу его, но для этого требуется, чтобы разные части хорошо сочетались, что не всегда происходит (:

Я вижу два три чистых подхода.

Использование API поля и contrib

Если вы хотите использовать API полей для создания/обновления/удаления полей, то я все еще думаю, что вам следует использовать пользовательские продукты линейки. Я немного удивлен, что у него нет возможности отображение встроенной формы при оформлении заказа. Возможно, для добавления этого будет создан модуль, он должен быть относительно простым. Но в то же время это может помочь вам с существующим контентом:

  1. Установка редактируемые поля и Панель представлений коммерции.
  2. Создайте настраиваемый тип позиции для настраиваемого продукта. Добавьте необходимые поля, но не настраивайте их так, чтобы они отображались в форме добавления в корзину. Также убедитесь, что позиции не могут быть объединены.
  3. Создать представление позиции, которое принимает идентификатор заказа в качестве аргумента, и добавляет поля, которые вы хотите отредактировать (и предоставляет им редактируемый формат). Добавьте фильтр, чтобы убедиться, что он отображает только позиции правильного пакета. Вы можете протестировать представление в режиме предварительного просмотра, создав новый заказ с несколькими настраиваемыми продуктами, найти идентификатор заказа (например, на странице оформления заказа) и передать этот идентификатор заказа в предварительный просмотр представлений. Он должен показать вам строку для каждой настраиваемой строки. Я бы не стал пытаться заставить панель представлений работать пока он не заработает в режиме предварительного просмотра.
  4. Добавьте это представление в качестве области оформления заказа.
  5. Сделайте круг из соли вокруг сервера и прошепчите молитву.

Использование API полей и комбинированных позиций (включает код)

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

  1. Создайте коллекцию полей с нужными вам полями.
  2. Добавьте коллекцию многозначных полей этого введите соответствующий тип позиции (убедитесь, что он не будет отображаться в форме добавления в корзину).
  3. Создайте собственную панель оформления заказа, в которой отображается форма редактирования поля. Вы бы прочитали количество из позиции и отобразили только это количество полей (поскольку это поле с несколькими значениями, оно сохранится нормально, сколько бы их ни было).

Создание пользовательской панели и хранение данных, упорядоченных по порядку (включает код)

У этого есть недостатки, которые вы не можете использовать API полей для настраивайте, изменяйте или считывайте поля (так что никаких представлений). checkout_pane_example.модуль показывает, как это сделать, добавив псевдоним и второе поле электронной почты и сохранив данные вместе с заказом.

Уродливый метод

Я думаю, что вы, вероятно, могли бы сделать это с помощью панелей Commerce Fieldgroup, если создадите коллекцию полей с нужными вам полями, а затем добавите ее в качестве многозначного поля в объект заказа. Вам понадобится некоторый код, чтобы гарантировать, что только правильное количество коллекций полей показано (чтобы соответствовать количеству позиций, которые необходимо настроить). Этот метод кажется грязным и имеет два конкретных недостатка, о которых я могу подумать:

  1. По мере добавления новых настраиваемых продуктов объект заказа будет получать все больше и больше полей.
  2. Вы не можете связать настройки с определенной позицией (что делать, если я хочу, чтобы на моем красном свитере было одно сообщение, а на синем свитере - другое - какое сообщение идет с какой позицией?).
 1
Author: Andy, 2014-08-05 11:48:46

Я закончил использовать 2-е решение Энди, используя API полей и комбинированные позиции.

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

Поскольку я некоторое время боролся с некоторыми аспектами API, особенно с коллекцией полей , вот мой полный панель оформления заказа .module, может быть, это кому-нибудь поможет.

/**
 * Implements hook_commerce_checkout_pane_info().
 */
function vts_commerce_checkout_pane_info() {

  $panes['paxsup_pane'] = array(
    'title' => t('Other Participants'),
    'base' => 'vts_pane',
    'name' => t('Other Participants'),
    'page' => 'checkout',
    'weight' => -5,
  );

  return $panes;
}

/**
 * Implements hook_pane_checkout_form().
 */
function vts_pane_checkout_form($form, &$form_state, $checkout_pane, $order) { 

  //load the current line item.
  $line_item = commerce_line_item_load($order->commerce_line_items['und'][0]['line_item_id']);

  $pane_form = array();

  if ($checkout_pane['pane_id'] == 'paxsup_pane') {
    field_attach_form('commerce_line_item', $line_item, $pane_form, $form_state, NULL, array('field_name' => 'field_paxsup'));
  }
  return $pane_form;
}

/*
 * Change general GUI edit field cardinality range from 1->1 to 1->20
 */
function vts_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
  // Increase the max cardinality to 20
  $range = drupal_map_assoc(range(1, 20));
  $new_options =  array(FIELD_CARDINALITY_UNLIMITED => t('Unlimited')) + $range;

  // Change the options
  $form['field']['cardinality']['#options'] = $new_options;
}

/*
 * Implements hook_form_FORM_ID_alter().
 */
function vts_form_commerce_checkout_form_checkout_alter(&$form, &$form_state, $form_id) {

  //Load line item to get pax number
  $line_item = commerce_line_item_load($form_state['build_info']['args'][0]->commerce_line_items['und'][0]['line_item_id']);
  $paxsup_nb = $line_item->quantity -1;
  if($paxsup_nb > 0){

    //Unset unnecessary items of paxsup field
    for($n=19; $n > $paxsup_nb-1; $n--){
      unset($form['paxsup_pane']['field_paxsup']['und'][$n]);
    }

    //Fill in paxsup with session values
    for($n=0; $n<$paxsup_nb; $n++){ 

      $form['paxsup_pane']['field_paxsup']['und'][$n]['field_paxsup_foo']['und']['#default_value'][0]            = isset($_SESSION['paxsup_foo_'.$n])? $_SESSION['paxsup_foo_'.$n]:'';
      $form['paxsup_pane']['field_paxsup']['und'][$n]['field_paxsup_bar']['und'][0]['value']['#default_value']        = isset($_SESSION['paxsup_bar_'.$n])? $_SESSION['paxsup_bar_'.$n]:'';
      $form['paxsup_pane']['field_paxsup']['und'][$n]['field_paxsup_date_of_birth']['und'][0]['#default_value']['value']  = isset($_SESSION['paxsup_date_of_birth_'.$n])? $_SESSION['paxsup_date_of_birth_'.$n]:'';

    }

  }
  else {
    unset($form['paxsup_pane']);
  }
}

/**
 * Implements hook_pane_checkout_form_validate().
 */
function vts_pane_checkout_form_validate($form, &$form_state, $checkout_pane, $order) {

  $line_item = commerce_line_item_load($order->commerce_line_items['und'][0]['line_item_id']);
  $paxsup_nb = $line_item->quantity -1;
  if($paxsup_nb > 0){

    for($n=0; $n<$paxsup_nb;$n++) {
      if(empty($form_state['values']['field_paxsup']['und'][$n]['field_paxsup_foo']['und'][0]['value'])
        || empty($form_state['values']['field_paxsup']['und'][$n]['field_paxsup_bar']['und'][0]['value']) 
        || empty($form_state['values']['field_paxsup']['und'][$n]['field_paxsup_date_of_birth']['und'][0]['value']) ) {

        return FALSE;
      }
    }
  }

  return TRUE;
}

/**
 * Implements hook_pane_checkout_form_submit().
 */
function vts_pane_checkout_form_submit($form, &$form_state, $checkout_pane, $order) {

  $line_item = commerce_line_item_load($order->commerce_line_items['und'][0]['line_item_id']);
  $paxsup_nb = $line_item->quantity -1;
  if($paxsup_nb > 0){

    //Set paxsup SESSION values
    for($n=0; $n<$paxsup_nb;$n++) { //
      $_SESSION['paxsup_foo_'.$n] = $form_state['values']['field_paxsup']['und'][$n]['field_paxsup_foo']['und'][0]['value'];
      $_SESSION['paxsup_bar_'.$n] = $form_state['values']['field_paxsup']['und'][$n]['field_paxsup_bar']['und'][0]['value']; 
      $_SESSION['paxsup_date_of_birth_'.$n] = $form_state['values']['field_paxsup']['und'][$n]['field_paxsup_date_of_birth']['und'][0]['value']; 
    }

    // Add the paxsup values to the line_item fields 
    if (!empty($form_state['values']['field_paxsup'])) {

      if(0 == count($line_item->field_paxsup)){
        //CREATE A NEW PAXSUP SET
        $entity = entity_load_single('commerce_line_item', $line_item->line_item_id);
        $wrapper = entity_metadata_wrapper('commerce_line_item', $entity);
        $collections = array();        

        for($n=0; $n<$paxsup_nb;$n++) { //
          $fc = entity_create('field_collection_item',  array('field_name' => 'field_paxsup'));
          $fc->setHostEntity('commerce_line_item', $line_item, LANGUAGE_NONE, FALSE);

          $fc->field_paxsup_foo['und'][0] = array('value'=> $form_state['values']['field_paxsup']['und'][$n]['field_paxsup_foo']['und'][0]['value']); 
          $fc->field_paxsup_bar['und'][0] = array('value'=> $form_state['values']['field_paxsup']['und'][$n]['field_paxsup_bar']['und'][0]['value']); 
          $fc->field_paxsup_date_of_birth['und'][0] = array('value'=> $form_state['values']['field_paxsup']['und'][$n]['field_paxsup_date_of_birth']['und'][0]['value']); 

          $fc->save(TRUE);
          $collections[] = $fc;
        }
        //Set the field collection items via the wrapper.
        $wrapper->field_paxsup->set($collections);
        $wrapper->save();

      }
      else {
        //UPDATE FIELD COLLECTION
        for($n=0; $n<$paxsup_nb;$n++) { //

          $fc = entity_load_single('field_collection_item', $line_item->field_paxsup['und'][$n]['value'] );
          $fc->field_paxsup_foo['und'][0] = array('value'=> $form_state['values']['field_paxsup']['und'][$n]['field_paxsup_foo']['und'][0]['value']); 
          $fc->field_paxsup_bar['und'][0] = array('value'=> $form_state['values']['field_paxsup']['und'][$n]['field_paxsup_bar']['und'][0]['value']); 
          $fc->field_paxsup_date_of_birth['und'][0] = array('value'=> $form_state['values']['field_paxsup']['und'][$n]['field_paxsup_date_of_birth']['und'][0]['value']); 
          $fc->save(TRUE);

        }
      }
    }
  }
}

/**
 * Implements hook_pane_review().
 * 
 */
function vts_pane_review($form, $form_state, $checkout_pane, $order) {

  $line_item = commerce_line_item_load($order->commerce_line_items['und'][0]['line_item_id']);
  $paxsup_nb = $line_item->quantity -1;
  if (!empty($line_item->field_paxsup['und'][0])) {

    $view = '';
    for($n=0; $n<$paxsup_nb;$n++) {

      $paxsup = entity_load_single('field_collection_item', $line_item->field_paxsup['und'][$n]['value'] );

      $display = array('label' => 'hidden');
      $foo = field_view_field('field_collection_item', $paxsup, 'field_paxsup_foo', $display);
      $bar = field_view_field('field_collection_item', $paxsup, 'field_paxsup_bar', $display);
      $date = field_view_field('field_collection_item', $paxsup, 'field_paxsup_date_of_birth', $display);

      $view .= '<p>'.$foo[0]['#markup'] .' '. $bar[0]['#markup'] .' '. $prenom[0]['#markup'] .t(', né(e) le '). $date[0]['#markup'] .'</p>';
    }

    return $view;
  } 
}
 0
Author: Kojo, 2014-08-28 14:27:34