OK, I've been trying several different alternatives, combination of modules, tweaks to existing modules, but now I'm LOST.

The core upload module has many deficiencies that are well documented (flat file system, etc.). We've installed the following modules that seem to mitigate many of our core issues.
http://drupal.org/project/filefield_paths
http://drupal.org/project/file_aliases

NOTE: We also have http://drupal.org/project/filefield installed and both the above modules seem to work well together.

Now to the issue at hand...
Both of the core upload and filefield modules have one very frustrating behavior: (I directly copied this statement from markDrupal's upload_replace module) If you have a file called "mydoc.doc" upload it to a node, then make changes to "mydoc.doc" and upload the newer version, the newer version will be renamed to "mydoc_0.doc" because at the time of upload the old file was blocking the desired path name.

This behavior is not intuitive to users used to dealing with document management systems. The name of the latest-and-greatest revision should not be augmented. The http://drupal.org/project/upload_replace module attempts to work around this shortcoming; however, it doesn't seem to play well with the filefield_paths and file_aliases modules.

I'm not sure if I'm "barking up the right tree", but the filefield module seems like the best place to start this conversation.

Also, I wanted to point out that the http://drupal.org/project/webfm module has a very nice method of dealing with this circumstance. (see attached screenshot). Unfortunately, that module has it's own set of issues and is not a good fit for our needs.

Can anyone point us in the right direction?

Many thanks in advance.

Comments

stacysimpson’s picture

StatusFileSize
new12.09 KB

And now the screenshot

stacysimpson’s picture

Project: FileField » Upload File Replace (for filefield CCK)
Version: 6.x-3.2 » 6.x-1.2

Moving to the upload_replace module

tommyk’s picture

Title: Need help with attachment / file management in D6 » integration with File Aliases module

I made a note on #792760: Old aliases left behind after deleting revisions to try and bring these two issues together because I think there is potential for a solution to this issue between these two modules.

TripleEmcoder’s picture

Subscribing.

ajagadees’s picture

Hi,

Am having the same problem above, I am using the http://drupal.org/project/filefield_paths for the folder structure. Please help me to solve the above issue (file gets renaming)

j d ess’s picture

Same problem. Integration with filefield_paths would be great. I really need to retain the file name and cannot rely on users to do it for me.

My workaround is:
Create node/Upload file > (...time passes) > Remove/Upload updated file > Save Node (file used at this point name_#.ext, i.e. the old version) > Save Node again (file is name.ext, i.e. the right version).

I can't really pass this on to an editor, though, since it is counter-intuitive.

attheshow’s picture

I haven't been able to get this working yet, but it's looking like we might be able to take advantage of hooks within the filefield_paths module to trigger the main function in upload_replace. Something like:

/**
 * Implementation of hook_filefield_paths_process_file()
 * In case user has filefield_paths module installed.
 */
function upload_replace_filefield_paths_process_file($file1, $file2, $ffp, $node, $update) {
  $fid = $file2['field']['fid'];
  if (!empty($fid)) {
    $file = field_file_load($fid);
    upload_replace_file_update($file);
  }
}

I'll let everyone know if I can get this working correctly.

attheshow’s picture

Status: Active » Needs review
StatusFileSize
new3.9 KB

The function below is working for me. Replace the code from #7 above with this. I've also attached a patch that includes this code.

/**
 * Implementation of hook_filefield_paths_process_file()
 * In case user has filefield_paths module installed.
 */
function upload_replace_filefield_paths_process_file($new, &$file, $settings, &$node, &$update) {
  // Copied from filefield_paths.module function filefield_paths_filefield_paths_process_file()
  if ($new) {
    // Process filename
    $file['filename']['old'] = $file['field']['filename'];
    if (($file['filename']['new'] = $settings['filename']['value']) != '') {
      $file['filename']['new'] = filefield_paths_process_string($file['filename']['new'], 'node', $node, $settings['filename']);
      $file['filename']['new'] = filefield_paths_process_string($file['filename']['new'], 'field', array(0 => $file['field']), $settings['filename']);
    }
    else {
      $file['filename']['new'] = $file['field']['filename'];
    }
  
    // Process filepath
    $file['filepath']['old'] = $file['field']['filepath'];
    $file['filepath']['new'] = filefield_paths_process_string(file_directory_path() . '/' . $settings['filepath']['value'] . '/' . $file['filename']['new'], 'node', $node, $settings['filepath']);
    $file['filepath']['new'] = filefield_paths_process_string($file['filepath']['new'], 'field', array(0 => $file['field']), $settings['filepath']);

    // Finalize files if necessary
    if (dirname($file['filepath']['new']) != dirname($file['field']['filepath']) || $file['filename']['new'] != $file['field']['filename']) {
      if (filefield_paths_file_move($file)) {

        // Fix reference to old paths.
        if (isset($node->body) || module_exists('content')) {
          $file['filepath']['new'] = str_replace($file['filename']['old'], $file['filename']['new'], $file['filepath']['new']);
          $file_directory_path = variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC ? file_directory_path() : 'system/files';

          // Regular expression to replace old file reference.
          $pattern = array(
            'regex' => str_replace('/', '\/', $file_directory_path) . '([^"]*?)' . str_replace('/', '\/', str_replace(file_directory_path(), '', $file['filepath']['old'])),
            'regex_enc' => str_replace('/', '\/', drupal_urlencode($file_directory_path)) . '([^"]*?)' . str_replace('/', '\/', str_replace(drupal_urlencode(file_directory_path()), '', drupal_urlencode($file['filepath']['old']))),
            'replace' => $file_directory_path . '$1' . str_replace(file_directory_path(), '', $file['filepath']['new']),
          );

          // Process regular expression.
          _filefield_paths_replace_pattern($pattern, $node, $update);
        }

        // Store new filename in file Array
        $file['field']['filename'] = $file['filename']['new'];
      }
    }
  }
  // End copied code from filefield_paths.module function filefield_paths_filefield_paths_process_file()
  
  // Send file object data to the basic upload_replace_file_update function.
  if ($new) {
    $file_obj = field_file_load($file['field']['fid']);
    // Cast to object since core functions use objects.
    $file_obj = (object)$file_obj;

    // Set some values for the upcoming function from what's available.
    $file_obj->filename = $file['field']['filename'];
    $file_obj->filepath = $file['field']['filepath'];
    upload_replace_file_update($file_obj);
  }
}
greenskunk’s picture

@attheshow ... wooooohoooooo!!!
For Drupal 6, your patch works to integrate filefield_paths with upload_replace! Two months ago, I had tried upload replace and only had a little time to see what could be conflicting or overriding another behavior. I've spent about 35 minutes testing, going through logs, different modules and then back to the upload_replace issue queue.

@everyone using this patch please post any issues here. I will be testing it more thoroughly in the next few days.

@markDrupal Would you add this as a known issue to the Upload Replace page and that there is currently a patch available for review?

endiku’s picture

#8 patch works great. Haven't encountered any problems.

traviscarden’s picture

Title: integration with File Aliases module » Add support for File (Field) Paths module
Version: 6.x-1.2 » 7.x-1.x-dev
StatusFileSize
new779 bytes

Great job, @attheshow! I didn't test your patch for 6.x, but I adapted the approach for 7.x where I needed it, and it works great. I'm bumping the version here. We can backport later.* Here's a patch.

* For when we come back to it, I suspect you don't actually need to duplicate filefield_paths_filefield_paths_process_file() in your patch. (I didn't have to in 7.x) But even if you do, you can just call it instead of copying its contents.

tyler-durden’s picture

I added the patch in #11 to D7 and it works (no _0 files are being created and I verified the file is deleted/written over), but I get this error after saving.

Warning: Parameter 1 to upload_replace_file_update() expected to be a reference, value given in module_invoke_all() (line 850 of includes/module.inc)

I did not have this error before applying the patch.

traviscarden’s picture

@tyler-durden: I believe that's a distinct issue that the patch exposes but does not cause: See #1115484: Parameter 1 to upload_replace_file_update() expected to be a reference, value given in module_invoke_all() . I have successfully eliminated the message on my site with the patch there in #13.

tyler-durden’s picture

TravisCarden, thanks. That patch removed the error for me also.

lias’s picture

edited - removed

mogwaay’s picture

Hi all,

I've tried to get both filefield_path and upload_replace modules to work nicely together, and applied #11 ontop of #20 from https://drupal.org/node/1115484 and they don't play nicely together.

I've included a patch that I used which combines

https://drupal.org/files/upload_replace-code-1115484-20.patch https://drupal.org/files/upload_replace-code-1115484-20.patch

in one.

I can upload the same file to a node a couple of times, but after that, I start getting duplicates files in the sites/defaults/files folder with the filefield_path name and the original name, both with _0 and not the actual path on the node - causing a 404. All the while I get SQL errors like:

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'public://test-resouces-document-15779.docx' for key 'uri': UPDATE {file_managed} SET uid=:db_update_placeholder_0, filename=:db_update_placeholder_1, uri=:db_update_placeholder_2, filemime=:db_update_placeholder_3, filesize=:db_update_placeholder_4, status=:db_update_placeholder_5, timestamp=:db_update_placeholder_6, origname=:db_update_placeholder_7 WHERE (fid = :db_condition_placeholder_0) ; Array ( [:db_update_placeholder_0] => 69 [:db_update_placeholder_1] => test-resouces-document-15779.docx [:db_update_placeholder_2] => public://test-resouces-document-15779.docx [:db_update_placeholder_3] => application/vnd.openxmlformats-officedocument.wordprocessingml.document [:db_update_placeholder_4] => 12688 [:db_update_placeholder_5] => 1 [:db_update_placeholder_6] => 1384527933 [:db_update_placeholder_7] => Test Resources Document.docx [:db_condition_placeholder_0] => 6199 ) in drupal_write_record() (line 7173 of /vagrant/docroot/includes/common.inc).

Either on uploading the new file (ie, clicking Upload button after Browsing) or on Saving the node after uploading. If you get the error on the AJAX upload, you can submit again and it'll go through, if you get the error on edit, you can submit again and it'll go through - but every second time you Save the node the file link will break and your sites/defualt/files will show 2 sets of the file with the filefield_path name and the original file with _X at the end of each - but no version without!

Does anyone have this setup working?

(PS this is the first time I've uploaded a patch here and I'm not sure how to add it to this thread, please bear with me...)

PSS Ah, it gets added as a separate comment, sorry if the numbers confuse anyone...

mogwaay’s picture

mogwaay’s picture

btw: I've given up using this module (upload_replace) to fix my problem and instead I just patched filefield_paths so that for one content type (foe_downloadables) it will remove any previous file with the same URI - my patch looks like this if anyone else is interested (sorry for the mad comment lines!):

diff --git a/modules/filefield_paths.inc b/modules/filefield_paths.inc
index 42016fc..6c81a75 100644
--- a/modules/filefield_paths.inc
+++ b/modules/filefield_paths.inc
@@ -64,6 +64,26 @@ function filefield_paths_filefield_paths_process_file($type, $entity, $field, $i
         // Process filepath.
         $file['uri'] = "{$field['settings']['uri_scheme']}://" . ltrim(filefield_paths_process_string($settings['file_path']['value'], $token_data, $settings['file_path']['options']) . "/{$file['filename']}", '/');
 
+       /* 
+       IF this is a foe_downloadables file AND the desired URI destination is taken, delete the file first THEN proceed with the file_move...
+       I want to NOT use the FILE_EXISTS_REPLACE flag on the file_move command as that had it's own problems... SO...
+       I want the destination of file_move to always be free to use our preferred destination by removing the any currently managed one
+
+       For this to work:
+        - Need to make sure MySQL can create a new record with the desired URI (DB row be gone..)
+        - Need to make sure that file_create_filename never needs to create a _X filename (file_exists($destination) == FALSE)
+        */
+
+        if($entity->type == 'foe_downloadables') {
+          $blocking_files = file_load_multiple(array(), array('uri' => $file['uri']));
+          $blocking_file = reset($blocking_files);
+
+          if($blocking_file) {
+            // Forcing the delete - this does mean that it will remove a file stored somewhere else in Drupal with the same name (unlikely)
+            file_delete($blocking_file, TRUE);
+          }
+        }
+
         // Finalize file if necessary.
         if ($file !== $old_file) {
           $dirname = drupal_dirname($file['uri']);

If I had more time I would've added a new checkbox per-file-field that specified that it will delete any file that is parked on the URL that we want.

Hope it's useful for someone else struggling to maintain URLs and not having the _X added to the end of it.