diff --git a/salsa_entity.drush.inc b/salsa_entity.drush.inc index 21a6782..b164bc0 100644 --- a/salsa_entity.drush.inc +++ b/salsa_entity.drush.inc @@ -13,19 +13,22 @@ 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( - 'types' => dt('The salsa types (comma separated), e.g. supporter,donate_page.'), + 'types' => dt('The salsa types (comma separated), e.g. supporter,donate_page to be exported.'), ), 'options' => array( 'paging' => dt('Number of records per file.'), - 'directory' => dt('Destination folder for the exported files.'), + 'directory' => dt('Destination folder where to export the files.'), ) ); $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.'), + ), + 'options' => array( + 'directory' => dt('Source folder from where to import the files.'), ) ); return $items; @@ -34,29 +37,31 @@ function salsa_entity_drush_command() { /** * Export salsa entities. * - * @param string $types The salsa type, e.g. donate_page. + * @param array $types The salsa type, e.g. donate_page. * * @return mixed */ -function drush_salsa_entity_export($types = NULL) { - if (!$types) { - // @todo If types attribute is not specified, try to get all (in use) Salsa tables or display error message. - } - $types = array_filter(explode(',', $types), 'trim'); +function drush_salsa_entity_export($types = array()) { + // Export all salsa tables or just specified if types attribute is submitted. + $salsa_types = salsa_entity_object_types(); + $types = empty($types) ? array_keys($salsa_types) : explode(',', $types); + // Prepare destination directory. $directory = drush_get_option('directory', 'public://salsa'); if (!file_prepare_directory($directory)) { return drush_set_error(dt('You need to create and set writable permissions manually for @directory directory.', array('@directory' => $directory))); } + // Check paging, salsa can not export more than 500 records per chunk. $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.')); } - $entity_info = entity_get_info(); + // Prepare sub-directories and export objects into .csv files. foreach ($types as $type) { - if (array_key_exists('salsa_' . $type, $entity_info)) { + // This check is necessary because of manually entered types. + if (array_key_exists($type, $salsa_types)) { $subdirectory = $directory . '/' . $type; if (!file_prepare_directory($subdirectory)) { return drush_set_error(dt('You need to create and set writable permissions manually for @subdirectory directory.', array('@subdirectory' => $subdirectory))); @@ -79,6 +84,8 @@ function drush_salsa_entity_export($types = NULL) { $destination = $subdirectory . '/' . $type . '_' . $sequence . '.csv'; $fp = fopen($destination, 'w'); + // Decided to store fields in KEY|VALUE format because after array_filter() call + // do not have all records the same number of columns (depends on values). foreach ($entities as $entity) { $entity = array_filter(get_object_vars($entity)); foreach ($entity as $key => &$value) { @@ -103,68 +110,71 @@ function drush_salsa_entity_export($types = NULL) { } } -function drush_salsa_entity_import($file = NULL) { - if (!$file) { - return drush_set_error(dt('You need to provide a file to import from.')); - } +/** + * Import salsa entities. + * + * @param array $types The salsa type, e.g. donate_page. + * + * @return mixed + */ +function drush_salsa_entity_import($types = array()) { + $salsa_types = salsa_entity_object_types(); - 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; - } + // Make sure import directory exists. + $dir = drush_get_option('directory', 'public://salsa'); + if (!file_exists($dir)) { + return drush_set_error(dt('Sorry, import is not possible because directory @directory does not exists.', array('@directory' => $dir))); } - include $file; - if (empty($entities)) { - return drush_set_error(dt('Provided file is not valid')); + // Scan and collect all files. + $sub_dirs = scandir($dir); + foreach ($sub_dirs as $sub_dir) { + $sub_dir_path = $dir . '/' . $sub_dir; + if (is_dir($sub_dir_path) && array_key_exists($sub_dir, $salsa_types)) { + $files[$sub_dir] = scandir($sub_dir_path); + } } - $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; - } - else { - drush_log(dt('Entity @id is new.', array('@id' => $id))); - // Save as a new entity. - unset($values[$type . '_KEY']); - unset($values['key']); + // If types attribute has been submitted, remove all other files and import only preferred tables. + $types = explode(',', $types); + if (!empty($types)) { + foreach ($files as $key => $value) { + if (!in_array($key, $types)) { + unset($files[$key]); } + } + } - // Remove the organization_KEY - unset($values['organization_KEY']); - - $entity = entity_create('salsa_' . $type, $values); - $entity->save(); - - drush_log(dt('Saved entity with id @id.', array('@id' => $entity->identifier())), 'success'); + // Go through each file and import one by one record. + if (!empty($files)) { + foreach ($files as $type => $sequences) { + drush_print(dt('Starting to process @type.', array('@type' => $type))); + foreach ($sequences as $file) { + if ($file != '.' && $file != '..' && ($handle = fopen($dir . '/' . $type . '/' . $file, 'r')) !== FALSE) { + drush_print(dt('Importing file @file', array('@file' => $file))); + while(($values = fgetcsv($handle)) !== FALSE) { + + $entity = entity_create('salsa_' . $type, array()); + foreach ($values as $value) { + $field = explode('|', $value); + if (!in_array($field[0], array('key', 'organization_KEY', $type . '_KEY'))) { + $entity->$field[0] = $field[1]; + } + } + $entity->save(); - // 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() . ';'; + // @todo Implement mapping. + // @todo Is it important the order in which objects are imported? If objects getting new KEYs on import, then for example donation import will depends on supporter, we should import supporters first, to store their mapping somewhere in order to connect donation to proper supporter later. + // @todo Where to store mapping definitions. Is local.settings.php appropriate solution? Maybe to generate file that will be located in the root of the source folder? + // @todo Do better file check, what if we get a file like this one ".~lock.donation_0.csv#" or any others which is not .csv and does not follow TYPE_SEQUENCE.csv pattern. + } + } } } } - 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)); + else { + drush_set_error(dt('No files to import. Please check that files exist in @directory directory or you have requested import of non-existent table.', array('@directory' => $dir))); + } } /**