array('administer site configuration'), 'page callback' => 'drupal_get_form', 'page arguments' => array('uuid_features_settings'), 'title' => 'UUID Features Integration', 'description' => 'Configure the settings for UUID Features Integration.', ); return $items; } /** * Implements hook_features_api(). */ function uuid_features_features_api() { $components = array(); $components['uuid_node'] = array( 'name' => t('Content'), 'feature_source' => TRUE, 'default_hook' => 'uuid_features_default_content', 'default_file' => FEATURES_DEFAULTS_INCLUDED, 'file' => drupal_get_path('module', 'uuid_features') . '/includes/uuid_node.features.inc', ); if (module_exists('taxonomy')) { $components['uuid_term'] = array( 'name' => t('Taxonomy Term'), 'feature_source' => TRUE, 'default_hook' => 'uuid_features_default_terms', 'default_file' => FEATURES_DEFAULTS_INCLUDED, 'file' => drupal_get_path('module', 'uuid_features') . '/includes/uuid_term.features.inc', ); } // Depends on http://drupal.org/node/808690 if (function_exists('uuid_file_insert')) { $components['uuid_file'] = array( 'name' => t('File'), 'default_hook' => 'uuid_features_default_files', 'default_file' => FEATURES_DEFAULTS_INCLUDED, 'file' => drupal_get_path('module', 'uuid_features') . '/includes/uuid_file.features.inc', ); } return $components; } /** * Load all include files for enabled modules that this module provides * on-behalf-of functionality for. */ function uuid_features_load_module_includes() { static $loaded = FALSE; if (!$loaded) { $inc_path = drupal_get_path('module', 'uuid_features') . '/includes/modules'; foreach (module_list() as $module) { $file = "$inc_path/$module.inc"; if (file_exists($file)) { include_once DRUPAL_ROOT . '/' . $file; } } $loaded = TRUE; } } /** * Implements hook_features_pipe_COMPONENT_alter(). * * When exporting a vocabulary, include its terms. */ function uuid_features_features_pipe_taxonomy_alter($pipe, $data, $export) { if ($vocab = taxonomy_vocabulary_machine_name_load($data)) { foreach (taxonomy_get_tree($vocab->vid) as $term) { uuid_term_features_get_dependencies($export, $term->uuid); } $pipe['uuid_term'] = $export['features']['uuid_term']; } } /** * Menu callback to configure module settings. */ function uuid_features_settings($form, &$form_state) { $vocabularies = array(); foreach (taxonomy_vocabulary_get_names() as $machine_name => $properties) { $vocabularies[$machine_name] = $properties->name; } $form['file']['uuid_features_file_types'] = array( '#type' => 'checkboxes', '#title' => t('Files exported for vocabularies'), '#default_value' => variable_get('uuid_features_file_types', array()), '#options' => $vocabularies, '#description' => t('Which vocabularies should export file fields?'), ); $form['file']['uuid_features_file_mode'] = array( '#type' => 'radios', '#title' => t('File export mode'), '#default_value' => variable_get('uuid_features_file_mode', 'inline'), '#options' => array( 'inline' => t('Inline Base64'), 'local' => t('Local file export'), 'remote' => t('Remote file export, URL') ), '#description' => t('Should file exports be inline inside the export code, a local path to the file, or a URL? Inline Base64 is the easiest option to use but can sometimes exceed PHP post limits, local and remote modes are more useful for power users. NOTE: Remote mode only works with a public files directory.'), ); $form['file']['uuid_features_file_assets_path'] = array( '#type' => 'textfield', '#title' => t('Local file field assets path'), '#size' => 60, '#maxlength' => 255, '#default_value' => variable_get('uuid_features_file_assets_path', ''), '#description' => t( 'Optionally, copy files to this path when the node is exported. The primary advantage of this is to divert exported files into a safe location so they can be committed to source control (eg: SVN, CVS, Git). Tip: For install profile developers, setting this path to profiles/my_profile/uuid_features_assets may be useful.' ), '#required' => FALSE, '#states' => array( 'visible' => array( ':input[name=uuid_features_file_mode]' => array('value' => 'local'), ), ), ); $form['file']['uuid_features_file_supported_fields'] = array( '#type' => 'textfield', '#title' => t('Supported file field types'), '#default_value' => variable_get('uuid_features_file_supported_fields', 'file, image'), '#maxlength' => 512, '#description' => t('Comma seperated list of file field types to detect for export/import.'), ); return system_settings_form($form); } /** * Detects remote and local file exports and imports accordingly. * * @param &$file * The file, passed by reference. * @return TRUE or FALSE * Depending on success or failure. On success the $file object will * have a valid $file->fid attribute. */ function _uuid_features_file_field_import_file(&$file) { // This is here for historical reasons to support older exports. It can be // removed in the next major version. $file->uri = strtr($file->uri, array('#FILES_DIRECTORY_PATH#' => 'public:/')); // The file is already in the right location AND either the // uuid_features_file_path is not set or the uuid_features_file_path and filepath // contain the same file if (is_file($file->uri) && ( (!isset($file->uuid_features_file_path) || !is_file($file->uuid_features_file_path)) || ( is_file($file->uuid_features_file_path) && filesize($file->uri) == filesize($file->uuid_features_file_path) && strtoupper(dechex(crc32(file_get_contents($file->uri)))) == strtoupper(dechex(crc32(file_get_contents($file->uuid_features_file_path)))) ) ) ) { // Keep existing file if it exists already at this uri (see also #1023254) // Issue #1058750. $query = db_select('file_managed', 'f') ->fields('f', array('fid')) ->condition('uri', $file->uri) ->execute() ->fetchCol(); if (!empty($query)) { watchdog('uuid_features', 'kept existing managed file at uri "%uri"', array('%uri' => $file->uri), WATCHDOG_NOTICE); $file = file_load(array_shift($query)); } $file = file_save($file); } elseif (isset($file->uuid_features_file_data)) { $directory = drupal_dirname($file->uri); if (file_prepare_directory($directory, FILE_CREATE_DIRECTORY)) { if (file_put_contents($file->uri, base64_decode($file->uuid_features_file_data))) { $file = file_save($file); } } } // The file is in a local location, move it to the // destination then finish the save elseif (isset($file->uuid_features_file_path) && is_file($file->uuid_features_file_path)) { $directory = drupal_dirname($file->uri); if (file_prepare_directory($directory, FILE_CREATE_DIRECTORY)) { // The $file->uuid_features_file_path is passed to reference, and modified // by file_unmanaged_copy(). Making a copy to avoid tainting the original. $uuid_features_file_path = $file->uuid_features_file_path; file_unmanaged_copy($uuid_features_file_path, $directory, FILE_EXISTS_REPLACE); // At this point the $file->uuid_features_file_path will contain the // destination of the copied file //$file->uri = $uuid_features_file_path; $file = file_save($file); } } // The file is in a remote location, attempt to download it elseif (isset($file->uuid_features_file_url)) { // Need time to do the download ini_set('max_execution_time', 900); $temp_path = file_directory_temp() . '/' . md5(mt_rand()) . '.txt'; if (($source = fopen($file->uuid_features_file_url, 'r')) == FALSE) { drupal_set_message(t("Could not open '@file' for reading.", array('@file' => $file->uuid_features_file_url))); return FALSE; } elseif (($dest = fopen($temp_path, 'w')) == FALSE) { drupal_set_message(t("Could not open '@file' for writing.", array('@file' => $file->uri))); return FALSE; } else { // PHP5 specific, downloads the file and does buffering // automatically. $bytes_read = @stream_copy_to_stream($source, $dest); // Flush all buffers and wipe the file statistics cache @fflush($source); @fflush($dest); clearstatcache(); if ($bytes_read != filesize($temp_path)) { drupal_set_message(t("Remote export '!url' could not be fully downloaded, '@file' to temporary location '!temp'.", array('!url' => $file->uuid_features_file_url, '@file' => $file->uri, '!temp' => $temp_path))); return FALSE; } // File was downloaded successfully! else { if (!@copy($temp_path, $file->uri)) { unlink($temp_path); drupal_set_message(t("Could not move temporary file '@temp' to '@file'.", array('@temp' => $temp_path, '@file' => $file->uri))); return FALSE; } unlink($temp_path); $file->filesize = filesize($file->uri); $file->filemime = file_get_mimetype($file->uri); } } fclose($source); fclose($dest); $file = file_save($file); } // Unknown error else { drupal_set_message(t("Unknown error occurred attempting to import file: @filepath", array('@filepath' => $file->uri)), 'error'); return FALSE; } return TRUE; }