Snippets

Oleksiy Kalinichenko drush migration_filepath

Created by Oleksiy Kalinichenko
<?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;
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.