I understand that node_clone does not support file attachments. But, how difficult would it be to get it to support file attachments? What would need to be done if I wanted to try it?

Thanks!

Comments

pwolanin’s picture

I'm told it would be very difficult (or impossible)- at least for Drupal 5.

somebodysysop’s picture

It is not impossible, but it is problematic. What I did:

I used hook_prepare() to copy the $node->files object to the cloned node:

/**
 * Implementation of hook_prepare().
 */
function agenda_prepare(&$node) {
  if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'clone') {
    $orig_agenda = node_load(arg(1));
    $node->files = $orig_agenda->files;
  }
}

Now, the files appear on the submission form for the cloned node. However, I noticed that when I clicked "submit", the file attachments weren't saved to the cloned node. This is because I needed some file handling when the new node is saved, which I created using hook_insert():

/**
 * Implementation of hook_insert().
 */
function agenda_insert(&$node) {

  // Continue processing if this is a cloned agenda item;
  // Need some sort of if statement here.
    if (!is_array($node->files)) {
      return;
    }
    foreach ($node->files as $fid => $file) {
      // Convert file to object for compatibility
      $file = (object)$file;

      // New file upload 
	  if ($file = file_save_upload($file, $file->filename)) {
        $file->fid = db_next_id('{files}_fid');
        db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize) VALUES (%d, %d, '%s', '%s', '%s', %d)", $file->fid, $node->nid, $file->filename, $file->filepath, $file->filemime, $file->filesize);
        db_query("INSERT INTO {file_revisions} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $file->fid, $node->vid, $file->list, $file->description);
        // Tell other modules where the file was stored.
        $node->files[$fid] = $file;
      }
    }
}

OK, so now the file attachments are saved to the new cloned node. However, a couple of problems remain:

1. Can't figure out how to make sure that this hook_insert() code is ONLY executed for "cloned" nodes (NOT new original nodes).
2. If a person deletes the original or cloned node, the physical file is also deleted, so the node which remains can no longer access it.

Anybody have any suggestions on this?

pwolanin’s picture

I think #2 was the most problematic.

Perhaps you can use PHP functions to actually duplicate the file? Maybe: http://www.php.net/manual/en/function.copy.php

somebodysysop’s picture

Figured out how to make copy of file attachment(s). In hook_insert():

  // Continue processing if this is a cloned agenda item;
  // Need some sort of if statement here.
    if (!is_array($node->files)) {
      return;
    }
    foreach ($node->files as $fid => $file) {
      // Convert file to object for compatibility
      $file = (object)$file;

      // New file upload 
	  if ($file = file_save_upload($file, $file->filename)) {
        $file->fid = db_next_id('{files}_fid');
        // Make copy of these files
         $file_temp = file_get_contents($file->filepath);
         $new_filepath = file_save_data($file_temp, $file->filepath, FILE_EXISTS_RENAME);
         $file->filepath = $new_filepath;  
        // write to database
        db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize) VALUES (%d, %d, '%s', '%s', '%s', %d)", $file->fid, $node->nid, $file->filename, $file->filepath, $file->filemime, $file->filesize);
        db_query("INSERT INTO {file_revisions} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $file->fid, $node->vid, $file->list, $file->description);
        // Tell other modules where the file was stored.
        $node->files[$fid] = $file;
      }
    }

What I need some help with is figuring out how to NOT execute this bit of code UNLESS this is a node clone. Any suggestions?

Leeteq’s picture

Subscribing.

pwolanin’s picture

see new alter hooks - you can set a flag on the node

shawnpetriw’s picture

subscribe

Anonymous’s picture

Maybe that helps: At least with 6.x, it does work with webfm where attached files aren't physical attachments but just kind of soflinks to the real files in the webfm file tree. Those webfm attachments are cloned (while the file on the hard disk in the webfm folder isn't cloned, of course :-)).

Leeteq’s picture

Hmmm. Ref. #8: "Those webfm attachments are cloned (while the file on the hard disk in the webfm folder isn't cloned, of course"

How should that be handled when either an original node or a clone of it is deleted? Which criterias should be used by the system - and how - to figure out when the file in the file system should be deleted?

Sounds like that function should be handled by file API/core and only used by other modules, not reside in a contributed module. I think I have seen another issue or discussion related to this, but dont remember where.

Anonymous’s picture

The view is different: webfm just handles folders with files in it, completely independent of nodes. It's just a file manager, more or less. You can href files in a page without attaching it to the node, because webfm provides a referencable path for every file it manages.

Attaching files to a node with webfm is really like creating symbolic links in a Unix file systems. It just makes it possible for you to automatically provide a table of attachments in a page, or makes it easier to view which files you referenced on a page. But you don't need to attach them to a node unless you want to provide the attachment table.

Thus, when you delete a page or its clone and the page has files attached, you just delete the symbolic link that his page had to the file. You never delete the file. File deletion can only be done in the webfm manager.

It's really a completely different view which doesn't generate problems with cloning nodes. Think of a unix directory containing a symbolic link to a file. When you copy this directory with "cp -a", you just duplicate the symbolic link, not the file. Thats what happens when cloning a node with a webfm file attachment.

Leeteq’s picture

Yes, so what about the user expectations when performing a clone, and later deleting either the clone or the original?

I think the symlink analogy is good and also a desired function. But it should be customizeable by the admin.

I guess that most users would expect that cloning means a new entity that is a copy of - and then independent of - the original. Meaning that when deleting the original with its files, the clone and its attachments will not be affected. If deleting the clone, only the file copies are affected, not the files attached to the original version.

So I think that it would be practical with both variants with a logical UI.

pwolanin’s picture

The most robust approach might be to just remove all imagefields (for example) from $node, the way I already do for files.

you could find them like this: $content_type = content_types('your content type'), you can then find all CCK fields in $content_type['fields']

(including all metadata)

paulnem’s picture

Is there any possibility this will be a feature in the 5.x version of the module?

I like the usability that #11 mentions, it seems reasonable.

__
I've put a request into the paid services forum :

http://drupal.org/node/257316

Hopefully something can be put together and supplied as a patch.

pwolanin’s picture

I'm not likely to implement this myself for 5.x - we'll see how this module gets along with CCK in 6.x.

basicmagic.net’s picture

Title: File Attachments? » subscribe

subscribe

paulnem’s picture

Title: subscribe » Image attachment issues
pwolanin’s picture

Status: Active » Needs review
StatusFileSize
new1.47 KB

Here's what seems to be a working patch for 5.x-2.x which simply removes any CCK image or file attachments. This should at least allow the module to work without corrupting/confusing existing data.

Please test.

pwolanin’s picture

StatusFileSize
new1.62 KB

And essentially the same patch for 5.x-1.x

pwolanin’s picture

StatusFileSize
new4.86 KB

And now for the good stuff. Here's a patch that adds an additional helper module. I have just done some basic testing so far with PHP 5.2 on Darwin, but it seems to work to copy imagefield attachments for both the 5.x-2.x and 5.x-1.x Clone module. Testing on Windows, linux, with PHP 4.4, etc would be helpful so that any bugs are ironed out before this is released.

This patch should be applied TOGETHER WITH the patch from either #17 or #18, depending on which version of the Clone module you are using.

paulnem’s picture

I've applied the patches to a Drupal 5.7 (Node Clone 2.4) system, running on Centos with PHP 5.2.

As far as my testing has gone everything looks good, it does the job it is intended to do and I haven't run into any problems in general or with images being deleted, added, readded or with newly recreated nodes.

It would be great to see some others test this patch out and let us know how it goes.

pwolanin’s picture

StatusFileSize
new5.01 KB

simplified the code from #18, edited the README, committed this patch to 5.x-1.x

pwolanin’s picture

StatusFileSize
new3.94 KB

simplified the code from #17, edited the README, committed this patch to 5.x-2.x

pwolanin’s picture

StatusFileSize
new6.87 KB

attached patch is the new Clone Imagefield module committed to 5x-1x.

pwolanin’s picture

StatusFileSize
new5.98 KB

committed the attached to 5.x-2.x. If you don't want to use the patch, within about ~12 hours, this code will be available in the "Development snapshots" tarballs

pwolanin’s picture

Assigned: Unassigned » pwolanin
Status: Needs review » Fixed
Anonymous’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.