Currently a webform report node is cannot be succesfully exported/imported using node_export and features.

I have identified three problems that prevent export/import working successfully. The node_export api provides some hooks that allow the problems to be address failrly easily.

Use uuid not nid to reference the webform

No good exporting nids, they will be different on target installation. We must use the webform uuid to maintain the relationship.

/**
 * Manipulate a node on export.
 *
 * We need to include the uuid of the referenced webform.
 *
 * @param &$node
 *   The node to alter.
 * @param $original_node
 *   The unaltered node.
 */
function webform_report_node_export_node_alter(&$node, $original_node) {

  // Ignore all but webform_report nodes.
  if ($node->type != 'webform_report') {
    return;
  }

  // Get the uuid of the webform that this report references.
  $uuid = uuid_get_uuid('node', 'nid', $node->wnid);
  if (!$uuid) {
    $msg = t(
      'Webform report !wrt references webform with nid !wfn. This ' .
      'webform does not have a UUID. Import will fail.',
      array(
        '!wrt' => $node->title,
        '!wfn' => $node->wnid,
      )
    );
    watchdog('Node export', $msg, WATCHDOG_ERROR);
    drupal_set_message($msg, 'error');
    return;
  }

  // Set the uuid and remove the nid.
  $node->wuuid = $uuid;
  unset($node->wnid);
}


/**
 * Manipulate a node on import.
 *
 * Establish the nid of the webform referenced by a webform report node.
 *
 * @param $node
 * @param $original_node
 * @param $save
 */
function webform_report_node_export_node_import_alter(&$node, $original_node, $save) {

  // Ignore all but webform_report nodes.
  if ($node->type != 'webform_report') {
    return;
  }

  // Get the nid of the webform this report references.
  $nids = entity_get_id_by_uuid('node', array($node->wuuid));
  if (!isset($nids[$node->wuuid])) {
    $msg = t(
      'Webform report !wrt references webform with uuid !wfu. This ' .
      'webform does not exist on this installation. Import of node ' .
      'will fail.',
      array(
        '!wrt' => $node->title,
        '!wfu' => $node->wuuid,
      )
    );
    watchdog('Node export', $msg, WATCHDOG_ERROR);
    drupal_set_message($msg, 'error');
    return;
  }

  // Set the nid and remove the uuid.
  $node->wnid = $nids[$node->wuuid];
  unset($node->wuuid);
}

Report criteria are discarded on import

The report criteria are being successfully exported but get discared in webform_report_insert(). Need to change:

function webform_report_insert($node) {

  $node->columns = array();
  $node->sorton = array();
  $node->filters = array();
  $node->options = array();

for:

function webform_report_insert($node) {

  if (!isset($node->columns)) {
    $node->columns = array();
  }
  if (!isset($node->sorton)) {
    $node->sorton = array();
  }
  if (!isset($node->filters)) {
    $node->filters = array();
  }
  if (!isset($node->options)) {
    $node->options = array();
  }

Import webforms before webform reports

When importing a webform node and dependant webform report nodes from the same feature module the webform node must be imported first in order to have its assigned nid available when importing the webform report nodes.

/**
 * Implements hook_node_export_alter().
 *
 * We need to order exported nodes so that webform nodes are imported before
 * webform_report nodes so that the parent webform nid is available to
 * plug into the webform_report nodes wnid field.
 *
 * @param $nodes
 * @param $format
 */
function webform_report_node_export_alter(&$nodes, $format) {
  usort($nodes, '_webform_report_node_export_sort_compare');
}

/**
 * Comparison function for sorting exported nodes.
 *
 * Final order to be; weform_report nodes last, preceeded by webform nodes,
 * preceeded by any other nodes.
 *
 * @param $a
 * @param $b
 * @return int
 */
function _webform_report_node_export_sort_compare($a, $b) {

  $ary = array('webform', 'webform_report');
  if (!in_array($a->type, $ary) && in_array($b->type, $ary)) {
    return -1;
  }
  if (in_array($a->type, $ary) && !in_array($b->type, $ary)) {
    return +1;
  }
  if ($a->type == 'webform' && $b->type == 'webform_report') {
    return -1;
  }
  if ($a->type == 'webform_report' && $b->type == 'webform') {
    return +1;
  }
  return 0;
}

I'm just doing some final testing on these changes and I will then provide a patch.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

RogerB’s picture

Patch containing code from above.