Drupal Commerce, ajouter un pane custom dans votre checkout

Drupal Commerce, ajouter un pane custom dans votre checkout

01 Sep 2014 |  Drupal

Comme nous avons pu le voir dans l’article précédent, il est simple de configurer le checkout de Drupal Commerce de façon à créer l’expérience utilisateur que vous désirez.

Dans cet article nous allons voir comment avec du code, ajouter et modifier des panes. Pour rappel, les panes sont les éléments qui composent les différentes pages du checkout. On y retrouve par exemple, le pane de paiement, d’adresse ou encore de choix de solution de transport.

Histoire d’illustrer cela, je vous propose de créer un module Drupal afin d’ajouter un pane permettant à vos clients de choisir parmi plusieurs emballages cadeaux. Ce simple module est accessible sur Github pour plus de compréhension.

Déclaration de notre nouveau Pane

La première chose à faire consiste à déclarer au système notre nouveau pane en utilisant le
hook_commerce_checkout_pane_info()

sandbox.module
function sandbox_commerce_checkout_pane_info() {
  $panes['paper_gift'] = array(
    'title' => t('Paper gifts'),
    'base' => 'paper_gift_pane',
    'page' => 'checkout',
  );

  return $panes;
}

Notre pane sera alors reconnu par Drupal et disponible dans le checkout. Dès à présent, vous pouvez activer le module et voir le pane apparaitre sur la page d’administration du checkout.

Comme à la manière des hooks de Drupal, le code qui génère l’affichage des panes va faire de l’introspection dans le code, de façon à chercher toutes les fonctions qui commenceront par la “base” que vous avez définie dans le hook_commerce_checkout_pane_info().

Ainsi le code sera à la recherche des fonctions suivantes :

  • BASE_settings_form()
  • BASE_checkout_form()
  • BASE_checkout_form_validate()
  • BASE_checkout_form_submit()
  • BASE_review()

Implémentation du formulaire d’administration du Pane

L’intérêt du pane est d’être affiché sur une page du checkout, néanmoins vous pouvez créer un formulaire de configuration pour celui-ci. Pour y accéder, rendez-vous sur l’interface d’administration du checkout. Notez qu’il n’y a pas de table dans laquelle les informations seront stockées, il vous faudra utiliser les méthodes variable_get() et variable_set() pour sauvegarder vos réglages.

sandbox.module

/**
 * Pane: settings form callback.
 */
function paper_gift_pane_settings_form($checkout_pane) {
  $form['paper_gifts'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Ship this item in a gift box'),
    '#default_value' => variable_get('paper_gifts', array()),
    '#options' => paper_gift_pane_default_paper_gifts(),
  );

  return $form;
}

/**
 * Defines a list of default paper gifts to use.
 */
function paper_gift_pane_default_paper_gifts() {
  return array(
    'boy' => t('Boys'),
    'girl' => t('Girls'),
    'christmas' => t('Christmas'),
    'birthday' => t('Birthday'),
    'none' => t('None'),
  );
}

Dans le code ci-dessus, j’ai créé un formulaire d’administration et ajouté un champ texte, permettant au webmaster de modifier le texte qui sera affiché à l’utilisateur.

Création du Pane

Un pane n’est ni plus, ni moins qu’un formulaire dans le formulaire de checkout. Comme à l’habitude, vous y retrouverez le form, le form_validate et le form_submit.

Form

Le form contiendra ce qui sera affiché à l’utilisateur. Dans le cas de notre exemple, l’utilisateur pourra choisir entre plusieurs papiers cadeaux ou pas d’emballage.

sandbox.module

/**
 * Pane: form callback.
 */
function paper_gift_pane_checkout_form($form, &$form_state, $checkout_pane, $order) {
  $paper_gifts = array();
  $default_paper_gifts = paper_gift_pane_default_paper_gifts();

  foreach ($default_paper_gifts as $name => $title) {
    $image = array(
      'path' => drupal_get_path('module', 'sandbox') . '/images/' . $name . '.jpg',
      'title' => $title,
      'alt' => $title,
    );
    $paper_gifts[$name] = theme('image', $image);
  }

  $pane_form['paper_gift'] = array(
    '#type' => 'radios',
    '#default_value' => 'none',
    '#title' => t('Select your paper gift'),
    '#description' => t('Your items will be shipped in a gift box.'),
    '#options' => $paper_gifts,
    '#attributes' => array('class' => array('paper-gift-pane-selection')),
  );

  $pane_form['paper_gift']['#attached']['css'] = array(
    drupal_get_path('module', 'sandbox') . '/css/sandbox.css',
  );

  return $pane_form;
}

Form validate

Le form_validate permet d’effectuer des opérations de validation sur les champs saisis par l’utilisateur.

sandbox.module

/**
 * Pane: form validation callback.
 */
function paper_gift_pane_checkout_form_validate($form, &$form_state, $checkout_pane, $order) {
  // Validate the given value or set to none if null.
  if (!empty($form_state['values'][$checkout_pane['pane_id']])) {
    $pane_values = $form_state['values'][$checkout_pane['pane_id']];

    if (empty($pane_values['paper_gift'])) {
      $pane_values['paper_gift'] = 'none';
    }
  }
  return TRUE;
}

Ici, on regarde simplement s’il y a une valeur, sinon on définit que l’utilisateur ne veut pas d’emballage.

Form submit

La sauvegarde des informations intervient dans le form_submit une fois que l’on a passé la validation.

sandbox.module

/**
 * Pane: form submission callback.
 */
function paper_gift_pane_checkout_form_submit($form, &$form_state, $checkout_pane, $order) {
  if (!empty($form_state['values'][$checkout_pane['pane_id']])) {
    $pane_values = $form_state['values'][$checkout_pane['pane_id']];
    if (!empty($pane_values['paper_gift'])) {
      $order->data['paper_gift'] = $pane_values['paper_gift'];
    }
  }
}

Remarquez que vous avez accès à l’objet $order et que vous pouvez faire ce que vous en voulez. Pour l’exercice j’aurais pu créer un nouveau line item, mais pour faire simple le choix de l’utilisateur résidera comme simple information dans la commande.

Form review

Une fois l’information attachée à la commande, il ne nous reste plus qu’à la faire paraitre sur le pane de review afin que l’utilisateur puisse la voir.

Pour cela il suffit d’implémenter le form_review

sandbox.module

/**
 * Pane: Review
 */
function paper_gift_pane_review($form, $form_state, $checkout_pane, $order) {
  if ($order->data['paper_gift'] && $order->data['paper_gift']  != 'none') {
    $content['paper_gift'] = array(
      '#type' => 'item',
      '#markup' => t('Items in your order will be wrapped with the %paper paper gift', array('%paper' => $order->data['paper_gift'])),
    );
    return drupal_render($content);
  }
}

Modification d’un Pane existant

Comme mentionné précédemment, les panes ne sont que des forms et comme tout form vous avez la possibilité de les alterer via un hook_form_alter() ou encore mieux un hook_form_ID_alter().

Dans le cas ou vous voudriez modifier les paramètres d’un pane, vous implémentez la fonction hook_commerce_checkout_pane_info_alter()

Le mot de la fin

Au final, ce n’était pas si compliqué que cela ? En plus du fait d’avoir maintenant un pane pour offrir un emballage papier cadeau à vos clients, vous savez maintenant qu’il y a 3 grandes étapes dans la vie d’un pane. Le formulaire de settings pour l’admin, le formulaire destiné aux clients et le formulaire de review. Je serais curieux de savoir pourquoi vous avez besoin d’ajouter un pane dans votre checkout… Comme mentionné au début de ce post, le code est accéssible sur Github.

Julien Dubreuil

Vous avez une idée, un projet web à réaliser ?

Ensemble, mettons en oeuvre sa réussite. Je vous accompagne dans vos projets, depuis l'élaboration du cahier des charges jusqu'à la mise en production. Pour plus d'information n'hésitez pas à me contacter.

Contactez-moi