Created
September 25, 2017 15:30
-
-
Save gormus/3141f4f7d591f9cba3eacbaff67382f8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Implements of hook_drush_command(). | |
*/ | |
function migration_filepath_drush_command() { | |
$items = array(); | |
$items['migration_filepath'] = array( | |
'description' => "Move files to subdirectories", | |
'callback' => 'drush_migration_filepath', | |
// We are using options rather than arguments so the source can be omitted | |
// if needed (e.g. files are just directly under sites/default/files). | |
'options' => array( | |
'source' => array( | |
'description' => 'The directory under files where the to be relocated files are.', | |
'example_value' => 'field/image', | |
), | |
'target' => array( | |
'description' => 'The target directory where the files will be moved to and restructured.', | |
'example_value' => 'pictures', | |
), | |
), | |
'examples' => array( | |
'drush migration_filepath' => 'Moves all files located in the public file directory to YYYY/MM/DD style subdirectory.', | |
), | |
'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL | |
); | |
return $items; | |
} | |
/** | |
* Command callback to perform the file migration. | |
* | |
* The two optional options are the source and target directories. By default | |
* assumes that these are under the default path, e.g. sites/default/files. | |
*/ | |
function drush_migration_filepath() { | |
// Source directory to be cleaned up. All images in this directory will be relocated. | |
$source_directory = rtrim(drush_get_option('source', ''), '/'); | |
// Directory to place the new structure under. If does not exist will be created. | |
$target_directory = rtrim(drush_get_option('target', ''), '/'); | |
// Regular expression to find files in the source directory. | |
// For now assume public files only. | |
// public://field/image/imagefield_hENvtS.png | |
$extensions = array('jpeg', 'jpg', 'gif', 'png'); | |
// Construct a expression to find images located in the source directory. | |
$file_pattern = "[^\/]*"; // Finds anything that does not contain "/", should be fine. | |
// Append the trailing slash for the regular expression. | |
// Note, in some instances drupal places under public:/// (three slashes) | |
// even when no folder specified. Reason for this is not known yet. | |
$source_pattern = $source_directory ? $source_directory . "\/" : ''; | |
$regex = "^public:\/\/" . $source_pattern . "(" . $file_pattern . ")\.(" . implode($extensions, '|') . ")$"; | |
// Query the database for files that match this pattern. | |
$filetypes = array('image/jpeg', 'image/jpg', 'image/gif', 'image/png'); | |
$query = db_select('file_managed', 'f') | |
->condition('filemime', $filetypes , 'IN') | |
->condition('uri', $regex, 'REGEXP'); | |
$total_count = $query->countQuery()->execute()->fetchField(); | |
drush_print(dt('@count entries are to be moved.', array('@count' => $total_count))); | |
// Select the files to be moved. | |
$files = $query->fields('f', array('fid', 'filename', 'uri', 'timestamp')) | |
->execute() | |
->fetchAll(); | |
$count = 1; | |
foreach ($files as $file) { | |
preg_match_all("/$regex/i", $file->uri, $matches); // Note, $file->filename can be the SAME for different uri-s! | |
$filename = $matches[1][0] . "." . $matches[2][0]; | |
$old_file_wrapper = file_stream_wrapper_get_instance_by_uri($file->uri); | |
// If the file has already been moved, or does not exist in the filesystem, move on. | |
if (FALSE === ($status = $old_file_wrapper->url_stat($file->uri, STREAM_URL_STAT_QUIET))) { | |
drush_log("File entry in the database does not exist on the filesystem.", 'notice'); | |
continue; | |
} | |
// Each file should go to the directory based on its timestamp. | |
$target_directory_for_file = $target_directory . '/' . generate_directory_name($file->timestamp); | |
// Construct a dummy URI for it so we can use the stream wrappers. | |
$new_directory = file_build_uri($target_directory_for_file); | |
$wrapper = file_stream_wrapper_get_instance_by_uri($new_directory); | |
// Make sure that the new directory exists. | |
$wrapper->mkdir($new_directory, 0755, TRUE); | |
// Construct the new directory. | |
$wrapper = file_stream_wrapper_get_instance_by_uri($file->uri); | |
$new_uri = file_build_uri($target_directory_for_file . '/' . $filename); | |
$wrapper->rename($file->uri, $new_uri); | |
$progress = round(($count / $total_count) * 100); | |
drush_print($progress . '%'); | |
$query = db_update('file_managed') | |
->fields(array('uri' => $new_uri)) | |
->condition('fid', $file->fid) | |
->execute(); | |
$count++; | |
} | |
} | |
/** | |
* Generate the new file structure based on the timestamp. | |
*/ | |
function generate_directory_name($timestamp) { | |
$year = date('Y', $timestamp); | |
$month = date('m', $timestamp); | |
$day = date('d', $timestamp); | |
return $year . '/' .$month . '/' . $day; | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment