Skip to content

Instantly share code, notes, and snippets.

@scottrigby
Last active February 16, 2016 23:22
Show Gist options
  • Save scottrigby/0e664684e99dadaab6d2 to your computer and use it in GitHub Desktop.
Save scottrigby/0e664684e99dadaab6d2 to your computer and use it in GitHub Desktop.
Drush script shortens files with names that would be too long with s3 bucket added to uri.
#!/usr/bin/env drush
/**
* Shortens files with names that would be too long with s3 bucket added to uri.
*
* Problem:
* - In order to migrate existing files to s3 we must replace existing public://
* and private:// schemes to to s3://BUCKET_NAME/ in the uri column of the
* {file_managed} and {file_managed_revisions} tables.
* - However, some files that previously fit in these uri columns would now be
* too long with the BUCKET_NAME added.
* - Depending on the replace method used, those rows would either fail or skip
* (example MySQL IGNORE REPLACE).
* - In either case, the s3 scheme would not be added, so fields configured to
* use s3 for upload would render these existing files as broken images.
*
* Solution:
* - Shorten actual file names to fit the longest BUCKET_NAME in their full URI.
* - Update value in uri column of {file_managed} and {file_managed_revisions}
* tables to match the newly renamed file.
*
* Drush options (required):
* - max_len: Number of characters the uri column in {file_managed} table may
* have before the filename is shortened.
* - op: May be one of:
* - count: Returns a the number of records that will be effected.
* - list: Lists the URI for records that will be effected.
* - move: Performs file shortening operation, moving from old to new name.
*
* @see system_schema()
* @see file_entity_revisions_schema()
*/
$max_len = drush_get_option('max_len');
$op = drush_get_option('op');
if (empty($max_len) || !is_numeric($max_len)) {
drush_set_error('NO_MAX_LENGTH', dt('The "max" option is required. Must be numeric.'));
$missing = TRUE;
}
if (empty($op) || !in_array($op, array('count', 'list', 'move'))) {
drush_set_error('NO_OP', dt('The "op" option is required. Must be one of "count", "list", or "move".'));
$missing = TRUE;
}
if ($missing) {
return;
}
// Note do not use :max or :public placeholders, as they are reserved.
$query = "SELECT fid, uri
FROM {file_managed}
WHERE LENGTH (uri) > :max_len
AND (uri LIKE :scheme1 OR uri LIKE :scheme2)";
$args = array(
':max_len' => $max_len,
':scheme1' => 'public://%',
':scheme2' => 'private://%',
);
$records = db_query($query, $args);
if ('count' == $op) {
$count = $records->rowCount();
drush_print($count);
}
else {
foreach ($records as $record) {
if ('list' == $op) {
drush_print($record->uri);
}
elseif ('move' == $op) {
// Shorten each actual file name, and update the file and DB accordingly.
$file = file_load($record->fid);
// Use md5 to get a unique shortened file name.
$pathinfo = pathinfo($record->uri);
$destination = $pathinfo['dirname'] . '/' . md5($pathinfo['filename']) . '.' . $pathinfo['extension'];
file_move($file, $destination, FILE_EXISTS_ERROR);
drush_print("Moving from $record->uri to {$destination}.");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment