Drupal Migrate: Webform Submission Example

In a previous blog post I described a project I was working and how to migrate a FieldCollection into a Student Node. Another requirement of this project is that after References (people) have submitted Webform results to the website — staff edits through the CSV upload of applicant data should trickle down to the Submission information.

webform-views-example1

The project Migrate Extras contains a MigrateDestinationWebformSubmission Destination Handler (thank god!).

We again write a migration class to perform UPDATES to submissions from changed CSV source values — eg. we’re only overwriting the submissions with edited CSV content.

class UpdateSubmittedWebformSubmissionsMigration extends Migration {

  public function __construct($arguments) {
    parent::__construct($arguments);

    $this->description = 'This migration examines the created and updated Relations and pushes any changes to the already submitted webform.';

    // This migration needs to run after the Relations have been created or
    // updated.
    $this->dependencies = array('ReferenceToWebformRelations',);

    /**
     * Indicate whether the primary system of record for this migration is the
     * source, or the destination (Drupal). In the source case, migration of
     * an existing object will completely replace the Drupal object with data
     * from the source side. In the destination case, the existing Drupal
     * object will be loaded, then changes from the source applied; also,
     * rollback will not be supported.
     */
    $this->systemOfRecord = Migration::DESTINATION;

    // These are the form_key values from webform_component
    $fields = array(
      'reference_name' => 'reference_name',
      'academic_teachers_name' => 'academic_teachers_name',
      'ref_e_mail' => 'ref_e_mail',
      'ref_school' => 'ref_school',
    );

    $this->source = new MigrateSourceSQL($this->query(), $fields, NULL,
      array('map_joinable' => FALSE));

    // Find the destination webform by title
    $nodes = node_load_multiple(array(), array('type' => 'page',
      'title' => 'Submit a Reference'));
    $node = reset($nodes);
    $this->destination = new MigrateDestinationWebformSubmission($node);

    $this->map = new MigrateSQLMap($this->machineName,
       array(
         'sid' => array('type' => 'int',
                        'unsigned' => TRUE,
                        'not null' => TRUE,
                        'description' => 'Webform submission ID',
                        'alias' => 's',
                       ),
       ),
       MigrateDestinationWebformSubmission::getKeySchema()
    );

    // DEST -> SOURCE
    $this->addFieldMapping(
      'data_academic_teachers_name', 'ref_name'
    );
    $this->addFieldMapping(
      'data_reference_name', 'ref_name'
    );
    $this->addFieldMapping(
      'data_ref_e_mail', 'ref_email'
    );
    $this->addFieldMapping(
      'data_ref_school', 'institution'
    );
    #$this->addFieldMapping('', 'field_rel_app_ref_type_ref_type');
    #$this->addFieldMapping('', 'field_rel_app_address_address');
    #$this->addFieldMapping('', 'field_rel_app_academic_year_academic_year');
    $this->addUnmigratedDestinations(array(
      'sid',
      'uid',
      'submitted',
      'remote_addr',
      'is_draft',

      // Webform components.
      'data_reference_regarding',
      'data_students_name',
      'data_intro001',
      'data_subject_area',
      'data_quality_ratings',
      'data_in_which_grade_levels_was_the_sutdent_enrolled_when_you_taught_him_her',
      'data_question_002',
      'data_question_044',
      'data_question055',
      'data_question099',
      'data_reference_details',
      'data_ref_work_phone_number',
      'data_webform_rid',
      'data_reference_email_address',
    ));

    $this->addUnmigratedSources(array(
      'reference_name',
      'academic_teachers_name',
      'ref_e_mail',
      'ref_school',
      'entity_type',
      'entity_id',
      'revision_id',
      'bundle',
      'sid',
      'ref_type',
      'app_last_name',
      'app_first_name',
      'institution_url',
      'app_email',
      'app_address',
      'academic_year',
    ), t('DNM'));
  }

  protected function query() {
    return _mymodule_submitted_webform_relations_query();
  }

  public function prepareRow($row) {
    $fields = array('ref_name', 'ref_email', 'institution');
    foreach ($fields as $f) {
      $val = trim($row->{$f});
      if (empty($val)) {
        unset($row->{$f});
      }
    }
  }
}

Noteworthy Code Details

This Migration makes use of, $this->systemOfRecord = Migration::DESTINATION;, which as described in the comments basically says Drupal is the authoritative source on this data — never delete what Drupal has, only perform an SQL update to the content.

Also of note is how the Webform Submission object requires the parent Drupal Node Object to be able to find the Webform Submission IDs (SIDs) of submitted webforms. We do this by looking up the NID using node_load_multiple. This approach is actually depercated now and you should use an EntityFieldQuery, but I was in a hurry!

Also some of the fields in the Destination have the word data_ in them. This is how Webform functions when processing submission Components.

Beyond that this is a fairly typical migrations — I’m also glossing the biggest ugliest SQL query to find the already submitted Submission records in Drupal. I use the Relation module and ton of attached Fields to a Relation to track submissions; it’s a truly daunting SQL query.

Looking for quality Drupal Web Hosting? Look no further than Arvixe Web Hosting!

Tags: , , , , , , , , , , , | Posted under Drupal | RSS 2.0

Author Spotlight

David Gurba

David Gurba

I am a web programmer currently employed at UCSB. I have been developing web applications professionally for 8+ years now. For the last 5 years I’ve been actively developing websites primarily in PHP using Drupal. I have experience using LAMP and developing data driven websites for clients in aviation, higher education and e-commerce. If you’d like to contact me I can be reached at david.gurba@arvixe.com

Leave a Reply

Your email address will not be published. Required fields are marked *


4 + 5 =

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>