Webform Addressfield Migration

Specs

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

Summary

Oft müssen die Struktur der Dinge wie Inhaltstypen oder Webformulare geändert werden, nachdem bereits Daten für sie auf einer Produktionsstätte besteht. In diesem Beispiel wurde eine addressfield Komponente zu einem Webformular hinzugefügt, um eine Reihe von regelmäßigen Textfelder zu ersetzen, verwendet, um die Adresse zu erfassen.

Dieses Beispiel zeigt, wie addressfield Komponenten zu einer bestehenden Web-Formular hinzuzufügen und zu aktualisieren, all das Webformular Vorbringen von Kartendaten von den ursprünglichen Textfelder auf die neue addressfield Komponente. Dies wird nicht eine genaue Passform für die Projekt jemand anderem sein und ist nur als Beispiel gemeint, auf denen die eigene Arbeit zu stützen.

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.