Webform Addressfield Migration

Specs

Version
Drupal 7
Tools
Drush
Webform
Created
28 Feb 2016
Sections
  1. Drush Command

Summary

Muchas veces, la estructura de las cosas como tipos de contenido o formularios web necesitan ser cambiados después de datos ya existen para ellos en un lugar de producción. En este ejemplo, un componente addressfield se añadió a un formulario web para reemplazar un conjunto de campos de texto regulares utilizadas para capturar la dirección.

Este ejemplo muestra cómo agregar componentes addressfield a un formulario web existente, y actualizar todas las pretensiones de esta WebForm por los datos de mapeo de los campos de texto original al nuevo componente addressfield. Esto no será un ajuste exacto para el proyecto de otra persona y se entiende sólo como un ejemplo en la que basar su propio trabajo.

Code

1. Drush Command

MODULE_NAME.drush.inc
          
/**
 * Implements hook_drush_command().
 */
function MODULE_NAME_drush_command() {

  $items['update1'] = array(
    'description' => t('Process update 1'),
    'aliases' => array('updr'),
    'callback' => 'MODULE_NAME_drush_update_1',
    'options' => array(
      'number' => t('The update number to run.'),
    ),
  );

  return $items;
}

/*
 * 
 */
function MODULE_NAME_drush_update_1() {

  // nids of webforms to add addressfield component to
  $nids = array(1, 2, 3);
    
  // first add address component to webforms
  foreach ($nids as $nid) {
    $node = node_load($nid);
    $addressfield_exists = FALSE;
    $address_weight = 2; // best guess at weight if it can't be pulled from address_1 component about 6 lines down
    foreach ($node->webform['components'] as $key => $data) {
      if (($data['type'] == 'addressfield') || ($data['form_key'] == 'address')) {
        $addressfield_exists = TRUE;
      }
      if (($data['name'] == 'Address 1') || ($data['name'] == 'Address line 1')) {
        $address_weight = $data['weight']; // put address field in same place as old address 1 field by mapping its weight
      }
    }
    
    // only add the component if it does not already exist on the webform
    if ($addressfield_exists == FALSE) {
      $node->webform['components'][] = array(
        'nid' => $node->nid,
        'pid' => 0,
        'form_key' => 'address',
        'name' => t('Address'),
        'type' => 'addressfield',
        'value' => '',
        'extra' => array(
          'available_countries' => array(
            'CA' => 'CA',
            'US' => 'US',
          ),
          'csv_separate' => 1,
          'private' => 0,
          'wrapper_classes' => '',
          'css_classes' => '',
          'title_display' => 0,
          'attributes' => array(),
          'description' => '',
        ),
        'required' => 1,
        'weight' => $address_weight,
        'page_num' => 1,
      );
      node_save($node);
    }
  }
  
  // now migrate old submission data to new addressfield component
  module_load_include('inc', 'webform', 'includes/webform.submissions');
  $submissions = webform_get_submissions(array('nid' => $nids));
  
  foreach ($submissions as $submission) {
    // first find CID of address field
    $node = node_load($submission->nid);
    
    // Get component IDs based on field types and labels
    $cids = array();
    foreach ($node->webform['components'] as $cid => $component) {
      if ($component['name'] == 'Address') {
        $cids['address'] = $component['cid'];
      }
      if (($component['name'] == 'Address 1') || ($component['name'] == 'Address line 1')) {
        $cids['address_1'] = $component['cid'];
      }
      if (($component['name'] == 'Address 2') || ($component['name'] == 'Address line 2')) {
        $cids['address_2'] = $component['cid'];
      }
      if ($component['name'] == 'Address 3') {
        $cids['address_3'] = $component['cid'];
      }
      if ($component['name'] == 'City') {
        $cids['city'] = $component['cid'];
      }
      if (($component['name'] == 'State/Province') || ($component['name'] == 'State')) {
        $cids['state'] = $component['cid'];
      }
      if (($component['name'] == 'Zip/Postal Code')) {
        $cids['zip'] = $component['cid'];
      }
    }
    
    // $cids is an array of component IDs for the old address text/select fields, and of the new
    // addressfield.
    if (empty($submission->data[$cids['address']][0]['thoroughfare']) && empty($submission->data[$cids['address']][0]['administrative_area']) && empty($submission->data[$cids['address']][0]['country'])) {
      $submission->data[$cids['address']][0]['thoroughfare'] = $submission->data[$cids['address_1']][0]; // address 1
      $submission->data[$cids['address']][0]['premise'] = $submission->data[$cids['address_2']][0]; // address 2
      // add address 3 field conditionally if it exists
      if (!empty($cids['address_3']) && !empty($submission->data[$cids['address_3']][0])) {
        $submission->data[$cids['address']][0]['premise'] .= $submission->data[$cids['address_3']][0];
      }
      $submission->data[$cids['address']][0]['locality'] = $submission->data[$cids['city']][0]; // city
      $submission->data[$cids['address']][0]['administrative_area'] = $submission->data[$cids['state']][0]; // state
      $submission->data[$cids['address']][0]['postal_code'] = $submission->data[$cids['zip']][0]; // zip
      $submission->data[$cids['address']][0]['country'] = 'US'; // 2 digit country code
      $submission->data[$cids['address']][0] = serialize($submission->data[$cids['address']][0]);
     
      db_delete('webform_submitted_data')
            ->condition('sid', $submission->sid)
            ->execute();
     
      foreach ($submission->data as $cid => $values) {
        foreach ($values as $delta => $value) {
          $data = array(
            'nid' => $node->webform['nid'],
            'sid' => $submission->sid,
            'cid' => $cid,
            'no' => $delta,
            'data' => is_null($value) ? '' : $value,
          );
          drupal_write_record('webform_submitted_data', $data);
        }
      }
      
    }
  }
}
          
          

Comments

Placeholder: I'll extend node comments with ajax and other functionality here.