View source
<?php
use Doctrine\Common\Cache\FilesystemCache;
use Guzzle\Cache\DoctrineCacheAdapter;
class S3fsException extends Exception {
}
function s3fs_stream_wrappers() {
return array(
's3' => array(
'name' => 'S3 File System',
'class' => 'S3fsStreamWrapper',
'description' => t('Amazon Simple Storage Service'),
'type' => STREAM_WRAPPERS_NORMAL,
),
);
}
function s3fs_stream_wrappers_alter(&$wrappers) {
$config = _s3fs_get_config();
if (!empty($config['use_s3_for_public'])) {
$wrappers['public'] = array(
'name' => t('Public files (s3fs)'),
'class' => 'S3fsStreamWrapper',
'description' => t('Public files served from Amazon S3.'),
'type' => STREAM_WRAPPERS_NORMAL,
);
}
if (!empty($config['use_s3_for_private'])) {
$wrappers['private'] = array(
'name' => t('Private files (s3fs)'),
'class' => 'S3fsStreamWrapper',
'description' => t('Private files served from Amazon S3.'),
'type' => STREAM_WRAPPERS_NORMAL,
'private' => TRUE,
);
}
}
function s3fs_libraries_info() {
return array(
'awssdk2' => array(
'title' => 'AWS SDK for PHP',
'vendor url' => 'http://docs.aws.amazon.com/aws-sdk-php/guide/latest/index.html',
'download url' => 'https://github.com/aws/aws-sdk-php/releases',
'version arguments' => array(
'file' => 'Aws/Common/Aws.php',
'pattern' => "/const VERSION = '(.*)';/",
'lines' => 200,
),
'files' => array(
'php' => array(
'aws-autoloader.php',
),
),
),
);
}
function s3fs_menu() {
$items = array();
$items['admin/config/media/s3fs'] = array(
'title' => 'S3 File System',
'description' => 'Configure S3 File System.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
's3fs_settings',
),
'access arguments' => array(
'administer s3fs',
),
'file' => 's3fs.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
$items['admin/config/media/s3fs/settings'] = array(
'title' => 'Settings',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => 0,
);
$items['admin/config/media/s3fs/actions'] = array(
'title' => 'Actions',
'description' => 'Actions for S3 File System.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
's3fs_actions',
),
'access arguments' => array(
'administer s3fs',
),
'file' => 's3fs.admin.inc',
'type' => MENU_LOCAL_TASK,
'weight' => 10,
);
$items['admin/config/media/s3fs/actions/copy-images'] = array(
'title' => 'Copy System Images to S3',
'description' => 'Copy system image files from modules, themes, and libraries to S3.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
's3fs_copy_system_images_confirm_form',
),
'access arguments' => array(
'administer s3fs',
),
'file' => 's3fs.admin.inc',
'type' => MENU_LOCAL_TASK,
);
$items['s3/files/styles/%image_style'] = array(
'title' => 'Generate image style in S3',
'page callback' => '_s3fs_image_style_deliver',
'page arguments' => array(
3,
),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $items;
}
function s3fs_permission() {
return array(
'administer s3fs' => array(
'title' => t('Administer S3 File System'),
),
);
}
function s3fs_help($path, $arg) {
$actions = 'admin/config/media/s3fs/actions';
$settings = 'admin/config/media/s3fs';
if ($path == $settings) {
$msg = t('To perform actions such as refreshing the metadata cache, visit the !link.<br>
Disabled fields have been hard-coded in settings.php, and cannot be changed here. See the !README for details.', array(
'!link' => l(t('actions page'), $actions),
'!README' => l('README', drupal_get_path('module', 's3fs') . '/README.txt'),
));
return "<p>{$msg}</p>";
}
elseif ($path == $actions) {
$msg = t('These are the actions that you can perform upon S3 File System.');
$msg .= '<br>' . t('To change your settings, visit the !link.', array(
'!link' => l(t('settings page'), $settings),
));
return "<p>{$msg}</p>";
}
}
function s3fs_form_system_file_system_settings_alter(&$form, &$form_state, $form_id) {
$config = _s3fs_get_config();
if (!empty($config['use_s3_for_public'])) {
$form['file_public_path']['#attributes'] = array(
'disabled' => 'disabled',
);
$form['file_public_path']['#description'] = 'S3 File System has taken control of the public:// filesystem, making this setting irrelevent for typical use.';
}
if (!empty($config['use_s3_for_private'])) {
$form['file_private_path']['#attributes'] = array(
'disabled' => 'disabled',
);
$form['file_private_path']['#description'] = 'S3 File System has taken control of the private:// filesystem, making this setting irrelevent for typical use.';
}
}
function _s3fs_image_style_deliver() {
$args = func_get_args();
$style = array_shift($args);
$scheme = array_shift($args);
$filename = implode('/', $args);
$valid = !empty($style) && file_stream_wrapper_valid_scheme($scheme);
if (!variable_get('image_allow_insecure_derivatives', FALSE) || strpos(ltrim($filename, '\\/'), 'styles/') === 0) {
$valid = $valid && isset($_GET[IMAGE_DERIVATIVE_TOKEN]) && $_GET[IMAGE_DERIVATIVE_TOKEN] === image_style_path_token($style['name'], "{$scheme}://{$filename}");
}
if (!$valid) {
return MENU_ACCESS_DENIED;
}
$image_uri = "{$scheme}://{$filename}";
$derivative_uri = image_style_path($style['name'], $image_uri);
if (!is_file($image_uri)) {
watchdog('s3fs', 'Source image at %source_image_path not found while trying to generate derivative image at %derivative_path.', array(
'%source_image_path' => $image_uri,
'%derivative_path' => $derivative_uri,
));
return MENU_NOT_FOUND;
}
$lock_name = "_s3fs_image_style_deliver:{$style['name']}:" . drupal_hash_base64($image_uri);
if (!file_exists($derivative_uri)) {
$lock_acquired = lock_acquire($lock_name);
if (!$lock_acquired) {
drupal_add_http_header('Status', '503 Service Unavailable');
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
drupal_add_http_header('Retry-After', 3);
print t('Image generation in progress. Try again shortly.');
drupal_exit();
}
}
$success = file_exists($derivative_uri);
if (!$success) {
$success = image_style_create_derivative($style, $image_uri, $derivative_uri) && file_stream_wrapper_get_instance_by_scheme('s3')
->waitUntilFileExists($derivative_uri);
}
if (!empty($lock_acquired)) {
lock_release($lock_name);
}
if ($success) {
if (_s3fs_get_setting('no_redirect_derivatives', False)) {
$image = image_load($derivative_uri);
$settings = array(
'Content-Type' => $image->info['mime_type'],
'Content-Length' => $image->info['file_size'],
);
file_transfer($image->source, $settings);
}
else {
drupal_goto(file_create_url($derivative_uri));
}
}
else {
watchdog('S3 File System', 'Unable to generate an image derivative at %path.', array(
'%path' => $derivative_uri,
));
drupal_add_http_header('Status', '500 Internal Server Error');
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
print t('Error generating image.');
drupal_exit();
}
}
function _s3fs_validate_config($config) {
if (!empty($config['use_customhost']) && empty($config['hostname'])) {
form_set_error('s3fs_hostname', 'You must specify a Hostname to use the Custom Host feature.');
return FALSE;
}
if (!empty($config['use_cname']) && empty($config['domain'])) {
form_set_error('s3fs_domain', 'You must specify a CDN Domain Name to use the CNAME feature.');
return FALSE;
}
switch ($config['domain_root']) {
case 'root':
if (empty($config['root_folder'])) {
form_set_error('s3fs_root_folder', 'You must specify a Root folder to map the Domain Name to it.');
return FALSE;
}
break;
case 'public':
if (empty($config['public_folder'])) {
form_set_error('s3fs_public_folder', 'You must specify a Public folder to map the Domain Name to it.');
return FALSE;
}
elseif (!empty($config['root_folder'])) {
form_set_error('s3fs_root_folder', 'For the Public folder option, the Root folder must be blank. Otherwise, use the "Root & Public folders" option.');
return FALSE;
}
break;
case 'root_public':
if (empty($config['root_folder']) || empty($config['public_folder'])) {
form_set_error('s3fs_domain_root', 'You must specify both Root and Public folders to map the Domain Name to it.');
return FALSE;
}
break;
}
try {
$s3 = _s3fs_get_amazons3_client($config);
} catch (S3fsException $e) {
form_set_error('form', $e
->getMessage());
return FALSE;
}
try {
$list_obj_args = array(
'Bucket' => $config['bucket'],
'MaxKeys' => 1,
);
if (!empty($config['root_folder'])) {
$list_obj_args['Prefix'] = "{$config['root_folder']}/";
}
$s3
->listObjects($list_obj_args);
} catch (Aws\S3\Exception\InvalidAccessKeyIdException $e) {
form_set_error('s3fs_awssdk2_access_key', t('The Access Key in your AWS credentials is invalid.'));
return FALSE;
} catch (Aws\S3\Exception\SignatureDoesNotMatchException $e) {
form_set_error('s3fs_awssdk2_secret_key', t('The Secret Key in your AWS credentials is invalid.'));
return FALSE;
} catch (Aws\S3\Exception\NoSuchBucketException $e) {
form_set_error('s3fs_bucket', t('The specified bucket does not exist.'));
return FALSE;
} catch (Aws\S3\Exception\PermanentRedirectException $e) {
form_set_error('s3fs_region', t('This bucket exists, but it is not in the specified region.'));
return FALSE;
} catch (Exception $e) {
form_set_error('form', t('An unexpected %exception occured, with the following error message:<br>%error', array(
'%exception' => get_class($e),
'%error' => $e
->getMessage(),
)));
return FALSE;
}
return TRUE;
}
function _s3fs_refresh_cache($config) {
if (!_s3fs_validate_config($config)) {
form_set_error('s3fs_refresh_cache][refresh', t('Unable to validate S3 configuration settings.'));
return;
}
if (function_exists('drush_log')) {
drush_log('Getting Amazon S3 client...');
}
$s3 = _s3fs_get_amazons3_client($config);
$file_metadata_list = array();
$iterator_args = array(
'Bucket' => $config['bucket'],
);
if (!empty($config['root_folder'])) {
$iterator_args['Prefix'] = "{$config['root_folder']}/";
}
if (_s3fs_get_setting('use_versioning')) {
$iterator = $s3
->getIterator('ListObjectVersions', $iterator_args);
}
else {
$iterator = $s3
->getIterator('ListObjects', $iterator_args);
}
$iterator
->setPageSize(1000);
if (function_exists('drush_log')) {
drush_log('Creating temporary tables...');
}
module_load_install('s3fs');
$schema = s3fs_schema();
try {
db_create_table('s3fs_file_temp', $schema['s3fs_file']);
} catch (DatabaseSchemaObjectExistsException $e) {
db_truncate('s3fs_file_temp')
->execute();
}
try {
$folder_schema = $schema['s3fs_file'];
unset($folder_schema['primary key'], $folder_schema['indexes']);
db_create_table('s3fs_folder_temp', $folder_schema);
$options = Database::getConnectionInfo('default');
switch ($options['default']['driver']) {
case 'pgsql':
break;
case 'sqlite':
break;
case 'mysql':
db_query('ALTER TABLE {s3fs_folder_temp} CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin');
break;
}
} catch (DatabaseSchemaObjectExistsException $e) {
db_truncate('s3fs_folder_temp')
->execute();
}
$file_metadata_list = $folders = array();
$existing_folders = db_select('s3fs_file', 's')
->fields('s', array(
'uri',
))
->condition('dir', 1, '=');
$folder_counter = 0;
foreach ($existing_folders
->execute()
->fetchCol(0) as $folder_uri) {
$folders[$folder_uri] = TRUE;
if ($folder_counter++ % 1000 == 0) {
_s3fs_write_metadata($file_metadata_list, $folders);
}
}
$dispatcher = $iterator
->getEventDispatcher();
$dispatcher
->addListener('resource_iterator.before_send', function ($event) use (&$file_metadata_list, &$folders) {
_s3fs_write_metadata($file_metadata_list, $folders);
});
if (function_exists('drush_log')) {
$dispatcher
->addListener('resource_iterator.after_send', function ($event) use ($iterator) {
drush_log(dt('Request #@request_count, @records record(s) recieved in total.', array(
'@request_count' => $iterator
->getRequestCount(),
'@records' => $iterator
->count(),
)));
});
}
foreach ($iterator as $s3_metadata) {
$key = $s3_metadata['Key'];
if (!empty($config['root_folder'])) {
$key = str_replace("{$config['root_folder']}/", '', $key);
}
$public_folder_name = !empty($config['public_folder']) ? $config['public_folder'] : 's3fs-public';
$private_folder_name = !empty($config['private_folder']) ? $config['private_folder'] : 's3fs-private';
if (strpos($key, "{$public_folder_name}/") === 0) {
$key = str_replace("{$public_folder_name}/", '', $key);
$uri = "public://{$key}";
}
elseif (strpos($key, "{$private_folder_name}/") === 0) {
$key = str_replace("{$private_folder_name}/", '', $key);
$uri = "private://{$key}";
}
else {
$uri = "s3://{$key}";
}
$max_uri_length = $schema['s3fs_file']['fields']['uri']['length'];
if (strlen($uri) >= $max_uri_length) {
watchdog('s3fs', 'URI "@uri" is too long, ignoring', array(
'@uri' => $uri,
), WATCHDOG_WARNING);
continue;
}
if ($uri[strlen($uri) - 1] == '/') {
$folders[rtrim($uri, '/')] = TRUE;
}
else {
if (isset($s3_metadata['IsLatest']) && !$s3_metadata['IsLatest']) {
continue;
}
if (!isset($s3_metadata['StorageClass'])) {
continue;
}
if (isset($s3_metadata['VersionId']) && $s3_metadata['VersionId'] == 'null') {
unset($s3_metadata['VersionId']);
}
$file_metadata_list[] = _s3fs_convert_metadata($uri, $s3_metadata);
}
}
_s3fs_write_metadata($file_metadata_list, $folders);
$query = db_select('s3fs_folder_temp')
->distinct();
$query
->fields('s3fs_folder_temp');
$folder_counter = 0;
$result = $query
->execute();
$insert_query = db_insert('s3fs_file_temp')
->fields(array(
'uri',
'filesize',
'timestamp',
'dir',
'version',
));
foreach ($result as $record) {
$insert_query
->values((array) $record);
if ($folder_counter++ % 1000 == 0) {
$insert_query
->execute();
}
}
$insert_query
->execute();
if (function_exists('drush_log')) {
drush_log(dt('Flushed @folders folders to the file table.', array(
'@folders' => $folder_counter,
)));
}
db_drop_table('s3fs_folder_temp');
db_rename_table('s3fs_file', 's3fs_file_old');
db_rename_table('s3fs_file_temp', 's3fs_file');
db_drop_table('s3fs_file_old');
if (function_exists('drush_log')) {
drush_log(dt('S3 File System cache refreshed.'));
}
else {
drupal_set_message(t('S3 File System cache refreshed.'));
}
}
function _s3fs_write_metadata(&$file_metadata_list, &$folders) {
if (!empty($file_metadata_list)) {
$insert_query = db_insert('s3fs_file_temp')
->fields(array(
'uri',
'filesize',
'timestamp',
'dir',
'version',
));
foreach ($file_metadata_list as $key => $metadata) {
$uri = drupal_dirname($metadata['uri']);
if (!$metadata['dir']) {
$insert_query
->values($metadata);
}
else {
$folders[$uri] = $metadata;
unset($file_metadata_list[$key]);
}
$root = file_uri_scheme($uri) . '://';
while ($uri != $root) {
$folders[rtrim($uri, '/')] = TRUE;
$uri = drupal_dirname($uri);
}
}
$insert_query
->execute();
if (function_exists('drush_log')) {
drush_log(' ' . dt('Wrote @files file(s).', array(
'@files' => count($file_metadata_list),
)));
}
$file_metadata_list = array();
}
if (!empty($folders)) {
$insert_query = db_insert('s3fs_folder_temp')
->fields(array(
'uri',
'filesize',
'timestamp',
'dir',
'version',
));
foreach ($folders as $folder_name => $folder_data) {
if (is_bool($folder_data)) {
$insert_query
->values(_s3fs_convert_metadata($folder_name, array()));
}
else {
$insert_query
->values($folder_data);
}
}
$insert_query
->execute();
if (function_exists('drush_log')) {
drush_log(' ' . dt('Wrote @folders folder(s).', array(
'@folders' => count($folders),
)));
}
$folders = array();
}
}
function _s3fs_convert_metadata($uri, $s3_metadata) {
$metadata = array(
'uri' => $uri,
'filesize' => 0,
'timestamp' => REQUEST_TIME,
'dir' => 0,
'version' => '',
);
if (empty($s3_metadata)) {
$metadata['dir'] = 1;
}
else {
if (isset($s3_metadata['ContentLength'])) {
$metadata['filesize'] = $s3_metadata['ContentLength'];
}
elseif (isset($s3_metadata['Size'])) {
$metadata['filesize'] = $s3_metadata['Size'];
}
if (isset($s3_metadata['LastModified'])) {
$metadata['timestamp'] = date('U', strtotime($s3_metadata['LastModified']));
}
if (isset($s3_metadata['VersionId']) && $s3_metadata['VersionId'] != 'null') {
$metadata['version'] = $s3_metadata['VersionId'];
}
}
return $metadata;
}
function _s3fs_get_amazons3_client($config) {
static $s3;
static $static_config;
if (!isset($s3) || $static_config != $config) {
$access_key = _s3fs_get_setting('awssdk2_access_key');
if (isset($config['awssdk2_access_key'])) {
$access_key = $config['awssdk2_access_key'];
}
$secret_key = _s3fs_get_setting('awssdk2_secret_key');
if (isset($config['awssdk2_secret_key'])) {
$secret_key = $config['awssdk2_secret_key'];
}
$use_instance_profile = _s3fs_get_setting('awssdk2_use_instance_profile');
if (isset($config['awssdk2_use_instance_profile'])) {
$use_instance_profile = $config['awssdk2_use_instance_profile'];
}
$default_cache_config = _s3fs_get_setting('awssdk2_default_cache_config');
if (isset($config['awssdk2_default_cache_config'])) {
$default_cache_config = $config['awssdk2_default_cache_config'];
}
$library = _s3fs_load_awssdk2_library();
if (!$library['loaded']) {
throw new S3fsException(t('Unable to load the AWS SDK. Please ensure that the awssdk2 library is installed correctly.'));
}
elseif (!class_exists('Aws\\S3\\S3Client')) {
throw new S3fsException(t('Cannot load Aws\\S3\\S3Client class. Please ensure that the awssdk2 library is installed correctly.'));
}
elseif (!$use_instance_profile && (!$secret_key || !$access_key)) {
throw new S3fsException(t("Your AWS credentials have not been properly configured.\n Please set them on the S3 File System !settings_page or\n set \$conf['awssdk2_access_key'] and \$conf['awssdk2_secret_key'] in settings.php.", array(
'!settings_page' => l(t('settings page'), 'admin/config/media/s3fs/settings'),
)));
}
elseif ($use_instance_profile && (empty($default_cache_config) || !(is_writable($default_cache_config) && is_readable($default_cache_config)))) {
throw new s3fsException(t("Your AWS credentials have not been properly configured.\n You are attempting to use instance profile credentials but you have not set a valid default cache location.\n Please set it on the !settings_page or set \$conf['awssdk2_default_cache_config'] in settings.php.\n Note that this cache location must be an existing folder that can be read and written by your webserver.\n It should also be writable by whichever user you run drush commands under.", array(
'!settings_page' => l(t('settings page'), 'admin/config/media/s3fs/settings'),
)));
}
if ($use_instance_profile) {
$cache_adapter = new DoctrineCacheAdapter(new FilesystemCache($default_cache_config));
$client_config = array(
'credentials.cache' => $cache_adapter,
);
}
else {
$client_config = array(
'key' => $access_key,
'secret' => $secret_key,
);
}
if (!empty($config['region'])) {
$client_config['region'] = $config['region'];
$client_config['signature'] = 'v4';
}
if (!empty($config['use_customhost']) && !empty($config['hostname'])) {
$client_config['base_url'] = $config['hostname'];
}
$s3 = Aws\S3\S3Client::factory($client_config);
}
$static_config = $config;
return $s3;
}
function _s3fs_get_config($reset = FALSE) {
$config =& drupal_static('_s3fs_get_config');
if ($config === NULL || $reset) {
global $conf;
$config = array();
foreach ($conf as $key => $value) {
if (substr($key, 0, 5) == 's3fs_') {
$config[substr($key, 5)] = $value;
}
}
foreach ($conf as $key => $value) {
if (substr($key, 0, 8) == 'awssdk2_') {
$config[$key] = $value;
}
}
if (!empty($config['root_folder'])) {
$config['root_folder'] = trim($config['root_folder'], '\\/');
}
if (!empty($config['public_folder'])) {
$config['public_folder'] = trim($config['public_folder'], '\\/');
}
if (!empty($config['private_folder'])) {
$config['private_folder'] = trim($config['private_folder'], '\\/');
}
}
return $config;
}
function _s3fs_get_setting($setting, $default = '') {
$config = _s3fs_get_config();
return !empty($config[$setting]) ? $config[$setting] : $default;
}
function _s3fs_load_awssdk2_library() {
$library = libraries_load('awssdk2');
if (!empty($library['loaded'])) {
return $library;
}
cache_clear_all('awssdk2', 'cache_libraries');
drupal_static_reset('libraries_load');
return libraries_load('awssdk2');
}
function _s3fs_copy_file_system_to_s3($scheme) {
$config = _s3fs_get_config();
if ($scheme == 'public') {
$source_folder = realpath(variable_get('file_public_path', conf_path() . '/files'));
}
elseif ($scheme == 'private') {
$source_folder = variable_get('file_private_path', '');
$source_folder_real = realpath($source_folder);
if (empty($source_folder) || empty($source_folder_real)) {
drupal_set_message('Private file system base path is unknown. Unable to perform S3 copy.', 'error');
return;
}
}
$file_paths = _s3fs_recursive_dir_scan($source_folder);
foreach ($file_paths as $path) {
$relative_path = str_replace($source_folder . '/', '', $path);
print "Copying {$scheme}://{$relative_path} into S3...\n";
copy($path, "{$scheme}://{$relative_path}");
}
drupal_set_message(t('Copied all local %scheme files to S3.', array(
'%scheme' => $scheme,
)), 'status');
}
function _s3fs_recursive_dir_scan($dir) {
$output = array();
$files = scandir($dir);
foreach ($files as $file) {
$path = "{$dir}/{$file}";
if ($file != '.' && $file != '..') {
if ($path == realpath(variable_get('file_private_path'))) {
continue;
}
if (is_dir($path)) {
$output = array_merge($output, _s3fs_recursive_dir_scan($path));
}
else {
$output[] = $path;
}
}
}
return $output;
}
function s3fs_copy_system_images_confirm_form($form, &$form_state) {
if (!variable_get('s3fs_no_rewrite_cssjs', FALSE)) {
drupal_goto('admin/config/media/s3fs/actions');
}
$wrapper = variable_get('file_default_scheme', 'public') . '://';
$directories = s3fs_copy_system_images_directories();
if (!empty($directories['root_dirs'])) {
$description = t('<h2><strong><span class="warning">Warning: Unrelated files may be deleted. Proceed with caution.</span></strong></h2>');
$description .= t('
<p>All files located in the S3 directories shown below will be deleted as part of this copy process. If you have stored files in
one of these locations that is not related to S3 system images, <strong>cancel this process immediately and resolve the conflicts
before proceeding.</strong> If a large number of modules are installed, this process can take several minutes to complete.</p>');
$description .= t('<h3>!count images to be copied to S3:</h3>', array(
'!count' => $directories['total'],
));
$description .= t('<h4>Summary</h4>');
$description .= '<ul>';
foreach ($directories['root_dirs'] as $root_dir => $root_count) {
$description .= '<li>' . $wrapper . $root_dir . ' (' . $root_count . ')</li>';
}
$description .= '</ul><br>';
$description .= t('<h3>Details</h3>');
$description .= '<ul>';
foreach ($directories['dirs'] as $dir => $count) {
$description .= '<li>' . $wrapper . $dir . ' (' . $count . ')</li>';
}
$description .= '</ul><br>';
}
else {
$description = t('<p>Copy system images from modules, themes, and libraries to the S3 File System.</p>
<p>If a large number of modules are installed, this process can take several minutes to complete.</p>');
}
$form = confirm_form($form, t('Copy System Images to S3'), array(
'path' => 'admin/config/media/s3fs/actions',
), $description);
$form_state['build_info']['system_stream_wrapper'] = $wrapper;
$form_state['build_info']['system_image_directories'] = $directories;
$form['actions']['submit']['#submit'] = array(
's3fs_copy_system_images_confirm_form_submit',
);
return $form;
}
function s3fs_copy_system_images_confirm_form_submit($form, &$form_state) {
$wrapper = $form_state['build_info']['system_stream_wrapper'];
$directories = $form_state['build_info']['system_image_directories'];
s3fs_copy_system_images_batch_set($wrapper, $directories);
drupal_set_message(t('Copying of system images from modules, themes, and libraries to S3 is complete.'));
$form_state['redirect'] = array(
'path' => 'admin/config/media/s3fs/actions',
);
}
function s3fs_copy_system_images_batch_set($wrapper, $directories) {
$operations = array();
foreach ($directories['root_dirs'] as $directory => $count) {
$operations[] = array(
's3fs_copy_system_images_delete_batch',
array(
$wrapper,
$directory,
),
);
}
foreach ($directories['dirs'] as $directory => $count) {
$operations[] = array(
's3fs_copy_system_images_save_batch',
array(
$wrapper,
$directory,
),
);
}
$batch = array(
'title' => t('Copying system images to S3'),
'operations' => $operations,
'init_message' => t('Starting process of copying system files to S3.'),
'error_message' => t('Copying system files to S3 has encountered an error.'),
);
batch_set($batch);
}
function s3fs_copy_system_images_directories() {
$dirs = array(
'misc',
'modules',
);
foreach (libraries_get_libraries() as $library_name => $library_path) {
$dirs[] = $library_path;
}
foreach (module_list() as $module_name => $module) {
$dirs[] = drupal_get_path('module', $module_name);
}
foreach (list_themes() as $theme_name => $theme) {
$dirs[] = drupal_get_path('theme', $theme_name);
}
$dirs = array_values(array_unique($dirs));
$image_dirs = array();
foreach ($dirs as $dir) {
if ($files = file_scan_directory($dir, '/^.*\\.(png|gif|jpe?g|svg|bmp)$/')) {
$image_dirs[$dir] = count($files);
}
}
$root_image_dirs = array();
foreach ($image_dirs as $image_dir => $image_count) {
$dir_split = explode('/', $image_dir);
if (array_key_exists($dir_split[0], $root_image_dirs)) {
$root_image_dirs[$dir_split[0]] = $root_image_dirs[$dir_split[0]] + $image_count;
}
else {
$root_image_dirs[$dir_split[0]] = $image_count;
}
}
ksort($image_dirs);
ksort($root_image_dirs);
return array(
'total' => array_sum($image_dirs),
'dirs' => $image_dirs,
'root_dirs' => $root_image_dirs,
);
}
function s3fs_copy_system_images_delete_batch($wrapper, $directory) {
file_unmanaged_delete_recursive($wrapper . $directory);
}
function s3fs_copy_system_images_save_batch($wrapper, $directory) {
$local_files = file_scan_directory($directory, '/^.*\\.(png|gif|jpe?g|svg|bmp)$/');
foreach ($local_files as $local_file_uri => $local_file) {
$remote_file_path = str_replace('/' . $local_file->filename, '', $local_file_uri);
if (!is_dir($wrapper . $remote_file_path)) {
drupal_mkdir($wrapper . $remote_file_path, NULL, TRUE, NULL);
}
file_unmanaged_copy($local_file_uri, $wrapper . $local_file_uri, FILE_EXISTS_REPLACE);
}
}
function s3fs_field_default_field_bases_alter(&$fields) {
if ($uri_scheme = variable_get('s3fs_file_uri_scheme_override', FALSE)) {
foreach ($fields as $key => $item) {
if (isset($item['settings']['uri_scheme'])) {
$fields[$key]['settings']['uri_scheme'] = $uri_scheme;
}
}
}
}