Hello everyone. On one of my Drupal sites, I am usinng the upload module in conjunction with the book module to essentially serve as a download directory. Some of my nodes have large numbers of attachments (fifty or so). The setup is working fairly well so far, but lately, as I continue to upload stuff, my lists are becoming disorganized.

The upload module currently sorts the attachments (on the "view node" page) by upload date, I believe. I think this is the relevant code from upload.module

    case 'view':
      if ($node->files && user_access('view uploaded files')) {
        $header = array(t('Attachment'), t('Size'));
        $rows = array();
        $previews = array();

        // Build list of attached files
        foreach ($node->files as $file) {
          if ($file->list) {
            $rows[] = array(
              '<a href="'. check_url(($file->fid ? file_create_url($file->filepath) : url(file_create_filename($file->filename, file_create_path())))) .'">'. check_plain($file->filename) .'</a>',
              format_size($file->filesize)
            );
            // We save the list of files still in preview for later
            if (!$file->fid) {
              $previews[] = $file;
            }
          }
        }

Does anyone know how I might get the module to sort the uploads by NAME (alphabetically) rather than by upload date? I think there are PHP functions to sort arrays, but I am way out of my league there.

Thanks.

Kenny

Comments

coreyp_1’s picture

This is an easy thing to change, just remember that you're hacking core to do it.

The files are not listed by upload date. They are listed in the order that they are pulled from the database (which just happens to be the order in which they were uploaded.

If you want to change the upload order, then change the order in which the files are pulled from the database. Specifically, change line 393 of upload.module from this:

    $result = db_query("SELECT * FROM {files} WHERE nid = %d", $node->nid);

to this:

    $result = db_query("SELECT * FROM {files} WHERE nid = %d ORDER BY filename", $node->nid);

I personally think it would be better to be able to assign a weight to each file for sorting, and then have the alphabetical order secondary, which would be consistent with Drupal's current ordering scheme. Then again, maybe this is in 4.7 (or being planned for a later release) and I don't know it yet.

kyouens’s picture

That worked perfectly and your explanation was very clear. Thank you.

bermin’s picture

If you are interested in doing the same for the Drupal 4.6 ver of Attachment module, look for the db_query on line 323 and and the Order BY query like this:

$result = db_query("SELECT aid, title, description, fid, filename, size, hidden FROM {attachment} WHERE nid = %d ORDER BY title", $node->nid);

parkview’s picture

Hi,

The listing by coreyp_1 above might work for 4.6, but the upload.module seems to have changed quite a bit in 4.7, and the display of the attachments are now done in: http://api.drupal.org/api/4.7/function/theme_upload_attachments, however I can't find the relevant SELECT statement (that needs modifying in the upload.module that generates the file list.

I am running 4.7, but looking to upgrade to 5.1, so might as well cover it as well ;-)

Thanks

Paul

coreyp_1’s picture

I shouldn't do this, but I'm posting this code without testing it. Let me know if you get any errors. ;o)

// All of the following code should go into your template.php file
// in your theme folder, assuming you are using phptemplate as your
// theme engine.

// This is our comparison function

function _upload_attachments_compare($a, $b) {
  return ($a > $b) ? 1 : (($a < $b) ? -1 : 0);
}

// This is the theme function that we are overriding.  We are using
// the override technique discussed here: http://drupal.org/node/11811

function phptemplate_upload_attachments($files) {
 
  // First, we need to build an array where the filename is the key,
  // and the value is the file id.
  // This is a temporary array for use in the uksort() function.
  // usort() cannot be used, since it does not retain the keys.
  
  $temp_array = array();
  
  foreach ($files as $key => $val) {
    $val = (object)$val;
    $temp_array[$val->filename] = $key;
  }
  
  $temp_array = uksort($temp_array, '_upload_attachments_compare');
  
  // now we use the sorted array to build a new file array
  
  $new_file_list = array();
  
  foreach ($temp_array as $val) {
    $new_file_list[$val] = $files[$val];
  }
  
  $files = $new_file_list;
  
  // continuing happily...
  
  $header = array(t('Attachment'), t('Size'));
  $rows = array();
  
  foreach ($files as $file) {
    $file = (object)$file;
    if ($file->list && !$file->remove) {
      // Generate valid URL for both existing attachments and preview of new attachments (these have 'upload' in fid)
      $href = file_create_url((strpos($file->fid, 'upload') === FALSE ? $file->filepath : file_create_filename($file->filename, file_create_path())));
      $text = $file->description ? $file->description : $file->filename;
      $rows[] = array(l($text, $href), format_size($file->filesize));
    }
  }
  if (count($rows)) {
    return theme('table', $header, $rows, array('id' => 'attachments'));
  }
} 

This method should work for 4.7 and 5.x alike.

Usual warnings apply: This is untested code, so syntax and/or logical errors may exist. Backup your files first (you're doing that anyway, right?). Not guaranteed against data loss. No pets were harmed in the making of this snippet.

- Corey

evelien’s picture

this code makes the file attachment table to disappear.

Don't have time to find the error in the code. Will try next week, hopefully

evelien

coreyp_1’s picture

I mis-applied the uksort() function.

// All of the following code should go into your template.php file
// in your theme folder, assuming you are using phptemplate as your
// theme engine.

// This is our comparison function

function _upload_attachments_compare($a, $b) {
  return ($a > $b) ? 1 : (($a < $b) ? -1 : 0);
}

// This is the theme function that we are overriding.  We are using
// the override technique discussed here: http://drupal.org/node/11811

function phptemplate_upload_attachments($files) {

  // First, we need to build an array where the filename is the key,
  // and the value is the file id.
  // This is a temporary array for use in the uksort() function.
  // usort() cannot be used, since it does not retain the keys.
 
  $temp_array = array();
 
  foreach ($files as $key => $val) {
    $val = (object)$val;
    $temp_array[$val->filename] = $key;
  }
 
  uksort($temp_array, '_upload_attachments_compare');
 
  // now we use the sorted array to build a new file array
 
  $new_file_list = array();
 
  foreach ($temp_array as $val) {
    $new_file_list[$val] = $files[$val];
  }
 
  $files = $new_file_list;
 
  // continuing happily...
 
  $header = array(t('Attachment'), t('Size'));
  $rows = array();
 
  foreach ($files as $file) {
    $file = (object)$file;
    if ($file->list && !$file->remove) {
      // Generate valid URL for both existing attachments and preview of new attachments (these have 'upload' in fid)
      $href = file_create_url((strpos($file->fid, 'upload') === FALSE ? $file->filepath : file_create_filename($file->filename, file_create_path())));
      $text = $file->description ? $file->description : $file->filename;
      $rows[] = array(l($text, $href), format_size($file->filesize));
    }
  }
  if (count($rows)) {
    return theme('table', $header, $rows, array('id' => 'attachments'));
  }
}

- Corey

evelien’s picture

it works, thanks!

evelien

parkview’s picture

Thanks for the code Corey.

I cut and pasted the above code into a newly created template.php file, that was placed into my current theme directory. I replaced the word: phptemplate with my theme name, to create a function now called: mytheme_upload_attachments($files)

Viewing a sample page with attachments, they where still listed non-alphabetically, however I realsied, they are being sorted on something, as the the list is now not date-time sorted. I then realised that it was sorting on the filename, not the description that I was seeing on the page, so I took out 'filename' and replaced it with 'description' so that line 27 of your code now read: $temp_array[$val->description] = $key;

One thing I did notice, is that if two files are uploaded with the same name (but different descriptions), that your code will only display one of the listings. If I turn off the template.php code they both display again.

Things will get interesting when the needed 'Unified Document Management' proposal comes into fruition.

Cheers,

Paul