diff --git a/README.txt b/README.txt
index bff37fd..bfa71ab 100644
--- a/README.txt
+++ b/README.txt
@@ -61,6 +61,8 @@ FEATURES
  allows listing, sorting, and filtering of Salsa data such as supporters,
  events, etc.
 
+ * Supports migration through export / import drush scripts.
+
 
 REQUIREMENTS
 ------------
@@ -97,6 +99,35 @@ and enable the mollom module and add the forms you want to protect. For detailed
 instructions, please check the mollom module.
 
 
+DRUSH MIGRATION SCRIPT
+----------------------
+
+Before start using drush migration scripts, it is necessary to set the query
+timeout to at least 60 sec (/admin/config/services/salsa), so that script has
+enough time to draw up to 500 records what is the maximum number of records that
+Salsa API can return.
+
+To export data, use 'drush salsa-entity-export' script. Arguments type and directory
+are required. Type argument represents Salsa objects / tables that you want to export,
+tables can be comma-separated or 'all' can be used to export all tables. Directory
+argument represents the location where the exported files will be stored. Sub-directory
+will be created for each table and files will be splitted into chunks of 500 records.
+
+Example: drush salsa-entity-export donation public://salsa
+
+In addition, you can specify a --paging option if you want to split files into smaller
+chunks.
+
+Example: drush salsa-entity-export donation public://salsa --paging=100
+
+Importing is also easy, it is enough to run 'drush salsa-entity-import' script,
+with the same required arguments as for export script, type and directory, where type
+represents objects / tables that you want to import and directory represents location
+from where to import the exported files.
+
+Example: drush salsa-entity-import all public://salsa
+
+
 FOR MORE INFORMATION
 --------------------
 
diff --git a/salsa_entity.drush.inc b/salsa_entity.drush.inc
index 433a38c..6ea4018 100644
--- a/salsa_entity.drush.inc
+++ b/salsa_entity.drush.inc
@@ -13,105 +13,678 @@ function salsa_entity_drush_command() {
     'description' => dt('Generates a file with all translatable strings.'),
   );
   $items['salsa-entity-export'] = array(
-    'description' => dt('Export all objects of the given type'),
+    'description' => dt('Export salsa entities of the given types.'),
     'arguments' => array(
-      'type' => dt('The salsa type, e.g. donate_page'),
-    )
+      'types' => dt('The salsa types (comma separated), e.g. supporter,donate_page to be exported.'),
+      'directory' => dt('Destination folder where to export the files.'),
+    ),
+    'options' => array(
+      'paging' => dt('Number of records per file (max and default value is 500 records, how much salsa otherwise allows).'),
+    ),
+    'required-arguments' => TRUE,
   );
   $items['salsa-entity-import'] = array(
-    'description' => dt('Import all salsa entities from the provided export'),
+    'description' => dt('Import salsa entities from the provided export.'),
     'arguments' => array(
-      'file' => dt('The file that should be imported.'),
-    )
+      'types' => dt('The salsa types (comma separated), e.g. supporter,donate_page to be imported.'),
+      'directory' => dt('Source folder from where to import the files.'),
+    ),
+    'required-arguments' => TRUE,
   );
   return $items;
 }
 
 /**
- * Export salsa entities.
+ * Drush callback: Exports salsa entities.
+ *
+ * @param array $types
+ *   The salsa type, e.g. donate_page.
+ *
+ * @param string $directory
+ *   Destination folder where to export the files.
+ *
+ * @return string
+ *   Error messages if any, otherwise function provides output as JSON file.
  */
-function drush_salsa_entity_export($type = NULL) {
-  if (!$type) {
-    return drush_set_error(dt('You need to provide a salsa type.'));
+function drush_salsa_entity_export($types, $directory) {
+  static $exported = array();
+  static $called = array();
+
+  try {
+    // Make sure export directory exists.
+    $iterator = drush_salsa_entity_directory_iterator($directory);
+    if (!$iterator->isWritable()) {
+      return drush_set_error(dt('Please check the path and permissions of the destination directory.'));
+    }
+  } catch(RuntimeException $e) {
+    return drush_set_error(dt('The directory you entered could not be opened.'));
   }
 
-  $entities[$type] = array();
-  foreach (entity_load('salsa_' . $type) as $entity) {
-    // Extract all relevant properties, filter out empty ones.
-    $entities[$type][$entity->identifier()] = array_filter(get_object_vars($entity));
+  // Check paging option.
+  $paging = drush_get_option('paging', 500);
+  if ($paging > 500) {
+    return drush_set_error(dt('Number of records per file can not be bigger than 500.'));
   }
 
-  $header = '<?php
-// Exported Salsa entities for ' . $type . "\n\n";
+  // Get all salsa types / tables.
+  $salsa_types = array();
+  drush_salsa_entity_array_flattener(drush_salsa_entity_mapping_dependencies(), $salsa_types);
+  $salsa_types = array_unique($salsa_types);
 
-  drush_print($header);
+  // Export objects into .json files.
+  $types = $types == 'all' ? $salsa_types : explode(',', $types);
 
-  // Export data.
-  drush_print('$entities = ' . var_export($entities, TRUE) . ';');
-}
+  // Always export custom fields regardless of what objects are requested.
+  array_unshift($salsa_types, 'custom_column', 'custom_column_option');
+  array_unshift($types, 'custom_column', 'custom_column_option');
+  $types = array_unique($types);
+  foreach ($types as $type) {
+    $called[] = $type;
 
-function drush_salsa_entity_import($file = NULL) {
-  if (!$file) {
-    return drush_set_error(dt('You need to provide a file to import from.'));
-  }
+    // This check is necessary because of manually entered types (entry may be invalid type).
+    // Also, different types can have the same dependencies, skip exporting if records already exported.
+    if (in_array($type, $salsa_types) && !in_array($type, $exported)) {
 
-  if (!file_exists($file)) {
-    // Drush changes the current working directory to the drupal root directory.
-    // Also check the current directory.
-    if (!file_exists(drush_cwd() . '/' . $file)) {
-      return drush_set_error(dt('@name does not exists or is not accessible.', array('@name' => $file)));
-    }
-    else {
-      // The path is relative to the current directory, update the variable.
-      $file = drush_cwd() . '/' . $file;
+      // Check whether there are dependencies, if so, export that tables first (recursively).
+      $dependencies = drush_salsa_entity_mapping_dependencies($type);
+      if (!empty($dependencies)) {
+        foreach ($dependencies as $dependent_type) {
+          if (!in_array($dependent_type, $called)) {
+            drush_salsa_entity_export($dependent_type, NULL);
+          }
+        }
+      }
+
+      // Prepare sub-directory.
+      $subdirectory = $iterator->getPath() . '/' . $type;
+      if (!file_prepare_directory($subdirectory, FILE_CREATE_DIRECTORY)) {
+        return drush_set_error(dt('You need to create and set writable permissions manually for @subdirectory directory.', array('@subdirectory' => $subdirectory)));
+      }
+
+      try {
+        // Count total number of records that need to be exported.
+        $counts = salsa_api()->getCounts($type);
+        if ($counts['count'] > 0) {
+          drush_log(dt('Starting to export @type (@count records)', array('@type' => $type, '@count' => $counts['count'])), 'ok');
+        }
+        else {
+          // Skip current type if there is no records to be exported.
+          continue;
+        }
+      }
+      catch (SalsaQueryException $e) {
+        drush_log(dt('Received exception during execution getCounts() method for type @type, with message: @message', array('@type' => $type, '@message' => $e->getMessage())), 'warning');
+        continue;
+      }
+
+      $sequence = 0;
+      do {
+        $query   = [];
+        $query[] = 'object=' . rawurldecode($type);
+        $query[] = 'limit=' . rawurldecode($sequence * $paging . ',' . $paging);
+
+        $entities = json_decode(salsa_api()->query('/api/getObjects.sjs?json', implode('&', $query)));
+        if (!is_array($entities)) {
+          drush_log(dt('Missing results from /api/getObjects.sjs script for sequence @sequence', array('@sequence' => $sequence)));
+          continue;
+        }
+
+        // Print error message if an error occurs.
+        $error = reset($entities);
+        if (property_exists('stdClass', 'result') && $error->result == 'error') {
+          drush_set_error($error->messages);
+        }
+
+        // Get out of the loop if $entities empty, otherwise put data into JSON file.
+        if (empty($entities)) {
+          $exported[] = $type;
+          continue;
+        }
+
+        $destination = $subdirectory . '/' . $type . '_' . $sequence . '.json';
+        file_put_contents($destination, json_encode($entities));
+
+        $exported[] = $type;
+        $sequence++;
+
+        drush_log(dt('Successfully created @destination file.', array('@destination' => $destination)), 'ok');
+
+        // For custom fields some kind of report / listing would be useful.
+        if ($type == 'custom_column') {
+          drush_salsa_entity_custom_fields_listing($entities, $iterator);
+        }
+
+      } while (count($entities) == $paging);
     }
   }
+}
+
+/**
+ * Drush callback: Imports salsa entities.
+ *
+ * @param string $types
+ *   The salsa type, e.g. donate_page.
+ *
+ * @param string $directory
+ *   Source folder from where to import the files.
+ *
+ * @return string
+ *   Error messages if any.
+ */
+function drush_salsa_entity_import($types, $directory) {
+  static $imported = array();
+  static $called = array();
 
-  include $file;
-  if (empty($entities)) {
-    return drush_set_error(dt('Provided file is not valid'));
+  try {
+    // Make sure import directory exists.
+    $iterator = drush_salsa_entity_directory_iterator($directory);
+    if (!$iterator->isReadable()) {
+      return drush_set_error(dt('Please check the path and permissions of the destination directory.'));
+    }
+  } catch(RuntimeException $e) {
+    return drush_set_error(dt('The directory you entered could not be opened.'));
   }
 
-  $mappings = variable_get('salsa_entity_id_mappings', array());
-  $new_mapping_definitions = array();
-
-  foreach ($entities as $type => $entities_type) {
-    drush_log(dt('Starting to process @type.', array('@type' => $type)));
-    foreach ($entities_type as $id => $values) {
-      // Check if this is a new entity.
-      $existing = FALSE;
-      $old_key = NULL;
-      if (isset($mappings[$type][$id])) {
-        drush_log(dt('Entity @id exists already with local mapped id @local_id.', array('@id' => $id, '@local_id' => $mappings[$type][$id])));
-
-        // Replace key with local mapping to update the existing record.
-        $values[$type . '_KEY'] = $mappings[$type][$id];
-        $values['key'] = $mappings[$type][$id];
-        $existing = TRUE;
+  // Get all salsa types / tables.
+  $salsa_types = array();
+  drush_salsa_entity_array_flattener(drush_salsa_entity_mapping_dependencies(), $salsa_types);
+  $salsa_types = array_unique($salsa_types);
+
+  $types = $types == 'all' ? $salsa_types : array_unique(explode(',', $types));
+
+  $salsa_entity_types = array_keys(salsa_entity_object_types());
+  foreach ($types as $type) {
+    $called[] = $type;
+
+    if (!in_array($type, $imported)) {
+
+      // Validate types, only salsa types can be imported.
+      if (!in_array($type, $salsa_entity_types)) {
+        drush_log(dt('@type can not be imported because there is no such registered salsa entity type.', array('@type' => $type)), 'warning');
+        continue;
       }
-      else {
-        drush_log(dt('Entity @id is new.', array('@id' => $id)));
-        // Save as a new entity.
-        unset($values[$type . '_KEY']);
-        unset($values['key']);
+
+      // Check whether there are dependencies, if so, import that tables first.
+      $dependencies = drush_salsa_entity_mapping_dependencies($type);
+      if (!empty($dependencies)) {
+        foreach ($dependencies as $dependent_type) {
+          if (!in_array($dependent_type, $called)) {
+            drush_salsa_entity_import($dependent_type, NULL);
+          }
+        }
       }
 
-      // Remove the organization_KEY
-      unset($values['organization_KEY']);
+      // Scan files.
+      foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($iterator->getPath() . '/' . $type, RecursiveDirectoryIterator::KEY_AS_PATHNAME), RecursiveIteratorIterator::CHILD_FIRST) as $file => $info) {
+        if ($info->isFile() && $info->getExtension() == 'json') {
+          drush_log(dt('Importing file @file', array('@file' => $file)), 'ok');
+
+          $json = json_decode(file_get_contents($file), TRUE);
+          foreach ($json as $record) {
+
+            // Check whether the record is already imported, if so, continue.
+            if (drush_salsa_entity_sync_map_key($type, $record['key'])) {
+              continue;
+            }
+
+            $source_key = $record['key'];
+            $type_key = $type . '_KEY';
+
+            unset($record[$type_key]);
+            unset($record['key']);
+            unset($record['organization_KEY']);
+
+            $entity = entity_create('salsa_' . $type, $record);
+
+            // Update references (foreign keys).
+            foreach ($salsa_types as $salsa_type) {
+              $property = $salsa_type . '_KEY';
+              if (property_exists($entity, $property)) {
+                $entity->$property = drush_salsa_entity_sync_map_key($salsa_type, $entity->$property);
+              }
+            }
+
+            // Update target_key.
+            if (property_exists($entity, 'target_key')) {
+              $entity->target_key = drush_salsa_entity_sync_map_key('recipient', $entity->target_key);
+            }
+
+            // Update target_KEYS.
+            if (property_exists($entity, 'target_KEYS')) {
+              $entity->target_KEYS = drush_salsa_entity_KEYS_update($entity, 'target_KEYS', 'recipient');
+            }
 
-      $entity = entity_create('salsa_' . $type, $values);
-      $entity->save();
+            // Update groups_KEYS.
+            if (property_exists($entity, 'groups_KEYS')) {
+              $entity->groups_KEYS = drush_salsa_entity_KEYS_update($entity, 'groups_KEYS', 'groups');
+            }
 
-      drush_log(dt('Saved entity with id @id.', array('@id' => $entity->identifier())), 'success');
+            // Update required$groups_KEYS.
+            if (property_exists($entity, 'required$groups_KEYS')) {
+              $required_groups_KEYS = 'required$groups_KEYS';
+              $entity->$required_groups_KEYS = drush_salsa_entity_KEYS_update($entity, 'required$groups_KEYS', 'groups');
+            }
 
-      // Add a new mapping line if this is a new object.
-      if (!$existing) {
-        $new_mapping_definitions[] = "\$conf['salsa_entity_id_mappings']['$type'][$id] = " . $entity->identifier() . ';';
+            // Update add_to_groups_KEYS.
+            if (property_exists($entity, 'add_to_groups_KEYS')) {
+              $entity->add_to_groups_KEYS = drush_salsa_entity_KEYS_update($entity, 'add_to_groups_KEYS', 'groups');
+            }
+
+            // Update optionally_add_to_groups_KEYS.
+            if (property_exists($entity, 'optionally_add_to_groups_KEYS')) {
+              $entity->optionally_add_to_groups_KEYS = drush_salsa_entity_KEYS_update($entity, 'optionally_add_to_groups_KEYS', 'groups');
+            }
+
+            // Update email_trigger_KEYS.
+            if (property_exists($entity, 'email_trigger_KEYS')) {
+              $entity->email_trigger_KEYS = drush_salsa_entity_KEYS_update($entity, 'email_trigger_KEYS', 'email_trigger');
+            }
+
+            // Update join_email_trigger_KEYS.
+            if (property_exists($entity, 'join_email_trigger_KEYS')) {
+              $entity->join_email_trigger_KEYS = drush_salsa_entity_KEYS_update($entity, 'join_email_trigger_KEYS', 'email_trigger');
+            }
+
+            // Update event$email_trigger_KEYS.
+            if (property_exists($entity, 'event$email_trigger_KEYS')) {
+              $event_email_trigger_KEYS = 'event$email_trigger_KEYS';
+              $entity->$event_email_trigger_KEYS = drush_salsa_entity_KEYS_update($entity, 'event$email_trigger_KEYS', 'event_email_trigger');
+            }
+
+            // Update waiting_list$email_trigger_KEYS.
+            if (property_exists($entity, 'waiting_list$email_trigger_KEYS')) {
+              $waiting_list_email_trigger_KEYS = 'waiting_list$email_trigger_KEYS';
+              $entity->$waiting_list_email_trigger_KEYS = drush_salsa_entity_KEYS_update($entity, 'waiting_list$email_trigger_KEYS', 'email_trigger');
+            }
+
+            // Update upgrade_$email_trigger_KEYS.
+            if (property_exists($entity, 'upgrade_$email_trigger_KEYS')) {
+              $upgrade_email_trigger_KEYS = 'upgrade_$email_trigger_KEYS';
+              $entity->$upgrade_email_trigger_KEYS = drush_salsa_entity_KEYS_update($entity, 'upgrade_$email_trigger_KEYS', 'email_trigger');
+            }
+
+            // Update reminder_$email_trigger_KEYS.
+            if (property_exists($entity, 'reminder_$email_trigger_KEYS')) {
+              $reminder_email_trigger_KEYS = 'reminder_$email_trigger_KEYS';
+              $entity->$reminder_email_trigger_KEYS = drush_salsa_entity_KEYS_update($entity, 'reminder_$email_trigger_KEYS', 'email_trigger');
+            }
+
+            // Update donor$email_trigger_KEYS.
+            if (property_exists($entity, 'donor$email_trigger_KEYS')) {
+              $donor_email_trigger_KEYS = 'donor$email_trigger_KEYS';
+              $entity->$donor_email_trigger_KEYS = drush_salsa_entity_KEYS_update($entity, 'donor$email_trigger_KEYS', 'email_trigger');
+            }
+
+            try {
+              // Save entity.
+              $entity->save();
+            }
+            catch (SalsaQueryException $e) {
+              drush_log(dt('Received exception during execution save() method while importing @type record, with message: \'@message\' for record ID: @source_key', array('@type' => $type, '@message' => $e->getMessage(), '@source_key' => $source_key)), 'warning');
+            }
+
+            drush_salsa_entity_sync_map_key($type, $source_key, $entity->key);
+          }
+
+          // Save mapping.
+          drush_salsa_entity_sync_map_key(NULL, NULL, NULL, TRUE);
+        }
       }
+
+      // Type is imported here.
+      $imported[] = $type;
+    }
+  }
+}
+
+/**
+ * Returns DirectoryIterator class or FALSE if directory does not exist.
+ *
+ * @param string $directory
+ *   Destination folder where to export the files.
+ *
+ * @return \DirectoryIterator
+ */
+function drush_salsa_entity_directory_iterator($directory = NULL) {
+  static $iterator = FALSE;
+
+  if (!$iterator) {
+    $iterator = new DirectoryIterator($directory);
+  }
+
+  return $iterator;
+}
+
+/**
+ * Maps salsa source <-> target keys.
+ *
+ * @param string $table
+ *   The salsa type (table), e.g. donate_page.
+ *
+ * @param string $source_key
+ *   Source KEY, record ID from the old database.
+ *
+ * @param string $target_key
+ *   Target KEY, record ID in the new database.
+ *
+ * @param bool $save
+ *   Flag, indicates whether to preserve the mapping array or not.
+ *
+ * @return array
+ *   Mapping array (source <-> target key pairs).
+ */
+function drush_salsa_entity_sync_map_key($table, $source_key, $target_key = NULL, $save = FALSE) {
+  static $mapping = array();
+
+  // Load default values on first call.
+  $mapping_file = drush_salsa_entity_directory_iterator()->getPath() . '/mapping.json';
+  if (empty($mapping) && file_exists($mapping_file)) {
+    $mapping = json_decode(file_get_contents($mapping_file), TRUE);
+  }
+
+  // Save call is triggered.
+  if ($save) {
+    if (file_put_contents($mapping_file, json_encode($mapping))) {
+      drush_log(dt('Mapping has been successfully preserved in @mapping_file', array('@mapping_file' => $mapping_file)), 'ok');
     }
+
+    return;
+  }
+
+  // 'Read' call.
+  if (is_null($target_key)) {
+    return $mapping[$table][$source_key];
   }
-  drush_log(dt('Created @count new objects, add the following mapping definitions to local.settings.php', array('@count' => count($new_mapping_definitions))), 'success');
-  drush_print(implode("\n", $new_mapping_definitions));
+
+  // 'Set' call.
+  $mapping[$table][$source_key] = $target_key;
+}
+
+/**
+ * Creates custom fields listing.
+ *
+ * @param array $custom_fields
+ *   Custom fields.
+ *
+ * @param object $iterator
+ *   Directory iterator, destination where to store custom fields listing.
+ *
+ * @return string
+ *   Error messages if any, otherwise function provides output as TXT file.
+ */
+function drush_salsa_entity_custom_fields_listing($custom_fields, $iterator) {
+  $i = 1;
+  $string = "";
+  foreach ($custom_fields as $custom_field) {
+    $string .= $i . '. ' . $custom_field->name . " (" . $custom_field->label . "), " . $custom_field->type . ", " . $custom_field->data_table . "\n";
+    $i++;
+  }
+
+  $destination = $iterator->getPath() . '/custom_fields_listing.txt';
+  file_put_contents($destination, $string);
+}
+
+/**
+ * Defines mapping dependencies.
+ *
+ * @param string $type
+ *   The salsa type (table), e.g. donate_page.
+ *
+ * @return array
+ *   Dependent tables for the requested type.
+ */
+function drush_salsa_entity_mapping_dependencies($type = NULL) {
+  $dependencies = array(
+    'action' => array(
+      'email_trigger', // Not supported by salsa_entity module.
+      'template', // Not supported by salsa_entity module.
+      'groups',
+    ),
+    'action_target' => array(
+      'action',
+      'action_content',
+      'recipient',
+      // 'excluded_KEYS', @todo How to handle excluded keys?
+    ),
+    'action_content' => array(
+      'action',
+    ),
+    'action_content_detail' => array(
+      'action_content',
+    ),
+    'supporter_action' => array(
+      'action',
+      'supporter',
+      'supporter_action_comment',
+    ),
+    'supporter_action_comment' => array(
+      'action',
+    ),
+    'supporter_action_target' => array(
+      'action',
+      'supporter',
+      'supporter_action',
+      'supporter_action_content', // Not supported by salsa_entity module.
+      'action_result', // Not supported by salsa_entity module.
+      'recipient',
+    ),
+    'recipient' => array(
+      'webform', // Not supported by salsa_entity module.
+      // 'chapter_KEY', // @todo Implement this case if possible at all to migrate chapter table.
+    ),
+    'donate_page' => array(
+      'email_trigger', // Not supported by salsa_entity module.
+      'event',
+      'groups',
+      // 'donation_amount_KEYS', // @todo It is not clear how to handle this reference.
+    ),
+    'donation' => array(
+      'supporter',
+      'event',
+      'donate_page',
+      'recurring_donation',
+      'event_fee',
+      // 'membership_invoice_KEY', // @todo It is not clear how to handle this case.
+      // 'referral_supporter_KEY', // @todo It is not clear how to handle this case (probably reference to supporter table).
+    ),
+    'recurring_donation' => array(
+      'supporter',
+      'donation',
+      'donate_page',
+      // 'source_donation_KEY', // @todo It is not clear how to handle this case (probably reference to donation table).
+      // 'current_reference_donation_KEY', // @todo It is not clear how to handle this case.
+    ),
+    'supporter' => array(),
+    'supporter_groups' => array(
+      'supporter',
+      'groups',
+    ),
+    // This table is supported by salsa_entity module, but commented out because it is not used by us.
+    /*'distributed_event' => array(
+      // 'merchant_account_KEY',
+      // 'signup_$email_trigger_KEYS',
+      // 'attend_$email_trigger_KEYS',
+      'template', // Not supported by salsa_entity module.
+    ),*/
+    'groups' => array(
+        // 'parent_KEY', @todo If this field references to groups table (YES), should be treated as a special case.
+      'query', // Not supported by salsa_entity module.
+      'email_trigger', // Not supported by salsa_entity module.
+      // 'add_to_chapter_KEY', @todo Implement this case if possible at all to migrate chapter table.
+    ),
+    // Contains internal metadata, not something we can import.
+    // Maybe will be needed when importing tag / tag_data, not for importing,
+    // but for lookup up the ID's (left for overview).
+    /*'database_table' => array(
+      'package', // Not supported by salsa_entity module.
+    ),*/
+    // Supported by salsa_entity module, but not something we can import (left for overview).
+    /*'publish' => array(
+      'database_table',
+      // 'table_KEY', // Reference to a non-existent table.
+      'template', // Not supported by salsa_entity module.
+      // 'feed_archetype',
+    ),*/
+    'event' => array(
+      'supporter',
+      'supporter_my_donate_page',
+      'groups',
+      // 'national_event_KEY', // @todo It is not clear how to handle this case.
+      // 'distributed_event_KEY', // Reference to distributed_event table which is not used by us.
+      // 'merchant_account_KEY', // Reference to merchant_account table that we can not import.
+      'event_email_trigger',
+      'email_trigger', // Not supported by salsa_entity module.
+      // 'supporter_picture_KEY', // Reference to supporter_picture table which is not used by us.
+    ),
+    'event_fee' => array(
+      'event',
+      'event_fee_group', // Not supported by salsa_entity module.
+      'membership_level', // Not supported by salsa_entity module.
+    ),
+    'event_email_trigger' => array(
+      'event',
+      'email_trigger', // Not supported by salsa_entity module.
+    ),
+    'supporter_event' => array(
+      'supporter',
+      'event',
+      'donation',
+      'event_fee',
+    ),
+    'supporter_invite' => array(
+      'supporter',
+      'tell_a_friend',
+      'event',
+      'supporter_event',
+      'event_fee',
+    ),
+    'my_donate_page' => array(
+      'email_trigger', // Not supported by salsa_entity module.
+      'groups',
+      // 'donor_groups_KEYS', @todo It is not clear how to handle this case.
+    ),
+    'supporter_my_donate_page' => array(
+      'supporter',
+      'my_donate_page',
+    ),
+    'supporter_my_donate_page_donation' => array(
+      'supporter',
+      'donation',
+      'recurring_donation',
+      'supporter_my_donate_page'
+    ),
+    'questionnaire' => array(
+      'groups',
+      'email_trigger', // Not supported by salsa_entity module.
+    ),
+    'questionnaire_page' => array(
+      'supporter',
+      'questionnaire',
+    ),
+    'questionnaire_question' => array(
+      'questionnaire',
+      'questionnaire_page',
+    ),
+    'questionnaire_question_option' => array(
+      'questionnaire_question',
+    ),
+    'supporter_questionnaire_question' => array(
+      'supporter',
+      'questionnaire_question',
+    ),
+    'signup_page' => array(
+      'event',
+      'groups',
+      'email_trigger', // Not supported by salsa_entity module.
+      // 'tag_KEYS', @todo Implement tags support.
+      // 'interest_KEYS', @todo Not clear how to handle this case. Not supported by salsa_entity module.
+      // 'use_new_groups_KEYS', @todo Is this reference to groups table, how to handle?
+    ),
+    // tag/tag_data is special, I'm not sure if we can just save that, needs to be tested.
+    // Maybe we need to import tags differently (usually done as a special element on saving
+    // an entity: $form_state['supporter']->additional['tag'] = implode(',', $form_state['values']['tags']);.
+    // We might want to load them first and then add them to saved objects like that.
+    // We however need to database_table names to do that, so we might actually need that table,
+    // but not for importing again, just for lookup up the ID's in that table.
+    'tag' => array(),
+    'tag_data' => array(
+      'database_table',
+      // 'tag',
+      // 'table_key',
+    ),
+    'tell_a_friend' => array(
+      'photo', // Not supported by salsa_entity module.
+    ),
+    'unsubscribe_page' => array(
+      'groups',
+      'email_trigger', // Not supported by salsa_entity module.
+      // 'tag_KEYS', @todo Implement tags support.
+      // 'chapter_KEYS', @todo Implement this case if possible at all to migrate chapter table.
+    ),
+    'unsubscribe' => array(
+      'supporter',
+      'email_blast', // Not supported by salsa_entity module.
+    ),
+  );
+
+  if (is_null($type)) {
+    return $dependencies;
+  }
+
+  if (array_key_exists($type, $dependencies)) {
+    return $dependencies[$type];
+  }
+
+  return array();
+}
+
+/**
+ * Converts multidimensional array in one-dimensional.
+ *
+ * @param array $input
+ *    Multidimensional array as input.
+ *
+ * @param array $output
+ *    One-dimensional array as output.
+ */
+function drush_salsa_entity_array_flattener($input = array(), &$output = array()) {
+  foreach ($input as $key => $value) {
+    if (is_string($key)) {
+      $output[] = $key;
+    }
+    if (is_array($value)) {
+      drush_salsa_entity_array_flattener($value, $output);
+    }
+    else {
+      $output[] = $value;
+    }
+  }
+}
+
+/**
+ * Updates keys for properties such as groups_KEYS, join_email_trigger_KEYS...
+ *
+ * @param array $entity
+ *    Salsa entity.
+ *
+ * @param string $property
+ *    Property which containing KEYS.
+ *
+ * @param string $source_table
+ *    Source table name.
+ *
+ * @return array
+ *    Updated groups KEYS.
+ */
+function drush_salsa_entity_KEYS_update($entity, $property, $source_table) {
+  $new_keys = array();
+  $keys = explode(',', $entity->$property);
+  foreach ($keys as $key) {
+    if ($key > 0) {
+      $new_keys[] = drush_salsa_entity_sync_map_key($source_table, $key);
+    }
+  }
+  return implode(',', $new_keys);
 }
 
 /**
@@ -145,23 +718,23 @@ function drush_salsa_entity_generate_translatables() {
       }
     }
     foreach ($salsa_info[$name]['item'] as $item) {
-     // Skip some internal/technical things.
-     foreach (array('READONLY', 'PRIVATE', 'KEY') as $ignore_pattern) {
-       if (strpos($item['name'], $ignore_pattern) !== FALSE) {
-         continue 2;
-       }
-     }
-     fwrite($file, "t('" . $item['label'] . "');\n");
-
-     // Write out enum values.
-     if ((strpos($item['type'], 'enum') === 0 || strpos($item['type'], 'set') === 0) && !empty($item['values'])) {
-       foreach (explode(',', $item['values']) as $value) {
-         // Ignore empty values, those with underscores and uppercase values.
-         if (!empty($value) && strpos($value, '_') === FALSE && $value != strtoupper($value)) {
-           fwrite($file, "t('" . $value . "');\n");
-         }
-       }
-     }
+      // Skip some internal/technical things.
+      foreach (array('READONLY', 'PRIVATE', 'KEY') as $ignore_pattern) {
+        if (strpos($item['name'], $ignore_pattern) !== FALSE) {
+          continue 2;
+        }
+      }
+      fwrite($file, "t('" . $item['label'] . "');\n");
+
+      // Write out enum values.
+      if ((strpos($item['type'], 'enum') === 0 || strpos($item['type'], 'set') === 0) && !empty($item['values'])) {
+        foreach (explode(',', $item['values']) as $value) {
+          // Ignore empty values, those with underscores and uppercase values.
+          if (!empty($value) && strpos($value, '_') === FALSE && $value != strtoupper($value)) {
+            fwrite($file, "t('" . $value . "');\n");
+          }
+        }
+      }
     }
     fwrite($file, "\n");
   }
