7 system.install system_update_7061(&$sandbox)

Migrate upload.module data to the newly created file field.

Related topics

File

modules/system/system.install, line 2762
Install, update and uninstall functions for the system module.

Code

function system_update_7061(&$sandbox) {
  if (!db_table_exists('upload')) {
    return;
  }

  if (!isset($sandbox ['progress'])) {
    // Delete stale rows from {upload} where the fid is not in the {files} table.
    db_delete('upload')
      ->notExists(
      db_select('files', 'f')
        ->fields('f', array('fid'))
        ->where('f.fid = {upload}.fid')
        )
      ->execute();

    // Delete stale rows from {upload} where the vid is not in the
    // {node_revision} table. The table has already been renamed in
    // node_update_7001().
    db_delete('upload')
      ->notExists(
      db_select('node_revision', 'nr')
        ->fields('nr', array('vid'))
        ->where('nr.vid = {upload}.vid')
        )
      ->execute();

    // Retrieve a list of node revisions that have uploaded files attached.
    // DISTINCT queries are expensive, especially when paged, so we store the
    // data in its own table for the duration of the update.
    if (!db_table_exists('system_update_7061')) {
      $table = array(
        'description' => t('Stores temporary data for system_update_7061.'),
        'fields' => array('vid' => array('type' => 'int')),
        'primary key' => array('vid'),
      );
      db_create_table('system_update_7061', $table);
    }
    $query = db_select('upload', 'u');
    $query->distinct();
    $query->addField('u', 'vid');
    db_insert('system_update_7061')
      ->from($query)
      ->execute();

    // Initialize batch update information.
    $sandbox ['progress'] = 0;
    $sandbox ['last_vid_processed'] = -1;
    $sandbox ['max'] = db_query("SELECT COUNT(*) FROM {system_update_7061}")->fetchField();
  }

  // Determine vids for this batch.
  // Process all files attached to a given revision during the same batch.
  $limit = variable_get('upload_update_batch_size', 100);
  $vids = db_query_range('SELECT vid FROM {system_update_7061} WHERE vid > :lastvid ORDER BY vid', 0, $limit, array(':lastvid' => $sandbox ['last_vid_processed']))
    ->fetchCol();

  // Retrieve information on all the files attached to these revisions.
  if (!empty($vids)) {
    $node_revisions = array();
    $result = db_query('SELECT u.fid, u.vid, u.list, u.description, n.nid, n.type, u.weight FROM {upload} u INNER JOIN {node_revision} nr ON u.vid = nr.vid INNER JOIN {node} n ON n.nid = nr.nid WHERE u.vid IN (:vids) ORDER BY u.vid, u.weight, u.fid', array(':vids' => $vids));
    foreach ($result as $record) {
      // For each uploaded file, retrieve the corresponding data from the old
      // files table (since upload doesn't know about the new entry in the
      // file_managed table).
      $file = db_select('files', 'f')
        ->fields('f', array('fid', 'uid', 'filename', 'filepath', 'filemime', 'filesize', 'status', 'timestamp'))
        ->condition('f.fid', $record->fid)
        ->execute()
        ->fetchAssoc();
      if (!$file) {
        continue;
      }

      // Add in the file information from the upload table.
      $file ['description'] = $record->description;
      $file ['display'] = $record->list;

      // Create one record for each revision that contains all the uploaded
      // files.
      $node_revisions [$record->vid]['nid'] = $record->nid;
      $node_revisions [$record->vid]['vid'] = $record->vid;
      $node_revisions [$record->vid]['type'] = $record->type;
      $node_revisions [$record->vid]['file'][LANGUAGE_NONE][] = $file;
    }

    // Now that we know which files belong to which revisions, update the
    // files'// database entries, and save a reference to each file in the
    // upload field on their node revisions.
    $basename = variable_get('file_directory_path', conf_path() . '/files');
    $scheme = file_default_scheme() . '://';
    foreach ($node_revisions as $vid => $revision) {
      foreach ($revision ['file'][LANGUAGE_NONE] as $delta => $file) {
        // We will convert filepaths to URI using the default scheme
        // and stripping off the existing file directory path.
        $file ['uri'] = $scheme . preg_replace('!^' . preg_quote($basename) . '!', '', $file ['filepath']);
        // Normalize the URI but don't call file_stream_wrapper_uri_normalize()
        // directly, since that is a higher-level API function which invokes
        // hooks while validating the scheme, and those will not work during
        // the upgrade. Instead, use a simpler version that just assumes the
        // scheme from above is already valid.
        if (($file_uri_scheme = file_uri_scheme($file ['uri'])) && ($file_uri_target = file_uri_target($file ['uri']))) {
          $file ['uri'] = $file_uri_scheme . '://' . $file_uri_target;
        }
        unset($file ['filepath']);
        // Insert into the file_managed table.
        // Each fid should only be stored once in file_managed.
        db_merge('file_managed')
          ->key(array(
            'fid' => $file ['fid'],
          ))
          ->fields(array(
            'uid' => $file ['uid'],
            'filename' => $file ['filename'],
            'uri' => $file ['uri'],
            'filemime' => $file ['filemime'],
            'filesize' => $file ['filesize'],
            'status' => $file ['status'],
            'timestamp' => $file ['timestamp'],
          ))
          ->execute();

        // Add the usage entry for the file.
        $file = (object) $file;
        file_usage_add($file, 'file', 'node', $revision ['nid']);

        // Update the node revision's upload file field with the file data.
        $revision ['file'][LANGUAGE_NONE][$delta] = array('fid' => $file->fid, 'display' => $file->display, 'description' => $file->description);
      }

      // Write the revision's upload field data into the field_upload tables.
      $node = (object) $revision;
      _update_7000_field_sql_storage_write('node', $node->type, $node->nid, $node->vid, 'upload', $node->file);

      // Update our progress information for the batch update.
      $sandbox ['progress'];
      ++$sandbox ['last_vid_processed'] = $vid;
    }
  }

  // If less than limit node revisions were processed, the update process is
  // finished.
  if (count($vids) < $limit) {
    $finished = TRUE;
  }

  // If there's no max value then there's nothing to update and we're finished.
  if (empty($sandbox ['max']) || isset($finished)) {
    db_drop_table('upload');
    db_drop_table('system_update_7061');
    return t('Upload module has been migrated to File module.');
  }
  else {
    // Indicate our current progress to the batch update system.
    $sandbox ['#finished'] = $sandbox ['progress'] / $sandbox ['max'];
  }
}