Closed (won't fix)
Project:
Migrate
Version:
7.x-2.4
Component:
Code
Priority:
Normal
Category:
Bug report
Assigned:
Unassigned
Reporter:
Created:
29 Jun 2012 at 10:53 UTC
Updated:
2 Apr 2013 at 18:06 UTC
i haven't been able to find any references to 'file_link' in the new migrate. so far this works, but how to I make it a link instead of copying the file?
$this->addFieldMapping('field_migrate_example_image', 'url');
$this->addFieldMapping('field_migrate_example_image:file_replace')
->defaultValue(FILE_EXISTS_REPLACE);
$this->addFieldMapping('field_migrate_example_image:alt', 'image_alt');
$this->addFieldMapping('field_migrate_example_image:title', 'image_title');
Comments
Comment #1
mikeryanTry
Comment #2
farse commentedsorry, that didn't work. let me explain a little better
all our source images are stored in public://rightmove/rm_images/unique folder for each collection of images/image00.jpg
where $image_path = unique folder/image.jpg
this code:
along with prepareRow() worked to create a link to the source images without the need to copy them (as we have A LOT of images [500GB])
since I couldn't find any reference to 'file_link' in the new version I was trying to get around this by setting the source path to the destination path still preserving the original file structure.
I have gotten to the point of:
but the 'destination_file' doesn't seem to work (the destination_dir is only returned) and when I take it out, it doesn't preserve the original file structure (which is the whole point of what I'm trying to do to not create two copies of every image).
tried all sorts of permutations of the above, but nothing seems to get it as it worked before!
thanks in advance for help
Comment #3
farse commentedComment #4
farse commentedComment #5
joeyda3rd commentedI'm having difficulty figuring this out too.
Would like to just link to existing picture in a directory (or even external URL for that matter) for displaying an image rather than copying the image. Purpose is to save time on migrate and file space due to massive amounts of images.
Do you have any examples of this for 2.4?
Edit:
I found the following in http://drupal.org/node/1540106
@farse: 'public://rightmove/rm_images' is a symlink? Have you tried setting preserve_files to true? Not sure if that would help.
Also, did you have your 'image_path' relative to the 'source_dir'?
Also from http://drupal.org/node/1540106
Maybe try removing the mapping for the file value:
and see if it will use the primary value from 'image_path'
Let me know if any of this works
Comment #6
farse commentedmy example is from 2.4, the snippet before that (with file_link) was what was working in 2.3
I am wanting to do the same thing to just link to files in my existing directory , but thought a way around this would be to just copy (actually not copying, by setting $this->addFieldMapping('field_migrate_example_image:file_replace')
->defaultValue(MigrateFile::FILE_EXISTS_REUSE); just reuses the existing file there) the files setting source = destination.
and yes i also tried using preserve_files, but it didn't really do anything other than not delete the files on rollback (which was ok because it copied the file into the wrong place so don't matter if it got deleted on rollback).
and yes, image_path is relative to source_dir, getting the images isn't a problem.
and if i get rid of destination_dir and just leave destination_file it doesn't pick up the unique folder that i want to save it in either way, it just takes the filename and puts in in the default public://, which is not what I want.
I tried picking through http://drupal.org/node/1540106 all day last week to figure out some way to get it to work, but no luck yet.
Comment #7
mikeryanSorry for the silence so far - it's tough to see why it's not working without a good test bed - a real-life file migration to work with. As it happens, I'm just starting a new Drupal-to-Drupal migration migration project, and now that I have my source file dump which I'll be symlinking from the destination files directory, I'll be ready to implement my file migration - I should have an answer (whether it's a better set of parameters, or a code fix) within a few days.
Thanks.
Comment #8
joeyda3rd commented@mikeryan: Thanks for looking into this for us!
@farse: In the mean time, could you maybe try hard coding in the directory structure you want to keep?
Comment #9
farse commentedthanks mikeryan, looking forward to your reply
and thanks joeyda3rd, I tried a slight variation of that:
just results in a directory of 'public://rightmove/rm_images///' (as the variable doesn't seem to be there outside the function, when it does exist in prepareRow())....
Comment #10
mikeryanOK, here's my scenario and how I configured the migration to make it work:
ln -s /data/dumps/files/ legacyMy migration (D7-to-D7, so source fields are from the file_managed table) looks more-or-less like:
Is this helpful? If so I'll add an example to the documentation.
Comment #11
mikeryanI should point out that source_dir only matters if the file is actually copied, in this scenario it's irrelevant - the incoming uri to appended to the destination_dir, and since destination_dir/uri exists, all that's done is the creation of the file entity, no copy is attempted.
Comment #12
mikeryanNo, wait a minute, it's not working right, got a bogus uri in the destination file_managed table (I was looking at the wrong db), continuing to investigate...
Comment #13
mikeryanOK, I thought there was something wrong with setting destination_dir to legacy instead of public://legacy... The latter is right, the problem is file_exists() on the filespec with the stream wrapper (public://) fails when the files are symbolically linked - when I made a parallel legacy2 directory with a copy of my physical target file, that worked. Trying various solutions involving is_file(), drupal_realpath(), etc., but still can't verify the existence of the linked file.
Comment #14
mikeryanSee #1008402: Allow the use of symlinks within the files directory. - I find I'm already following that issue, so I guess I've run into this before;).
What I need to do here to support symbolic links is to reproduce the logic of DrupalLocalStreamWrapper::getLocalPath(), without the bit that bails on symlinks... Then the resulting path should pass file_exists with flying colors.
Comment #15
mikeryanNo luck on that - or rather, I solved the immediate (file_exists) problem, but ran into more trouble deep within the File API (i.e., getting filesize on the linked files from file_save()).
For now, I've confirmed that the patch at http://drupal.org/node/1008402#comment-6118996 works. But, not wanting to kill any kittens, I'm replacing the symlink with a mount:
Comment #16
farse commentedso will/should
work the same as
with the added 'field_prop_images:'?
and does your uri have a folder inside and is this file structure preserved? and i need to install the patch for this to work (it says its for core v8?? )?
the main problem with me is that when i use 'destination_file' the file structure isn't preserved and just returns the filename.
if so, maybe be on a way to a solution!
Comment #17
mikeryanYes, the field version should treat destination_file the same - if your uri has a full path, that should be preserved.
The issue is for Drupal 8, but the patch I pointed to is for Drupal 7. An alternative to the patch, as I pointed out, is using mount --rlink instead of symlinks to tie the files into your files directory.
Comment #18
farse commentedfor example, this is what i am getting in my file_managed folder:
filename uri
36516_61014_IMG_01.jpg public://rightmove/rm_images/36516_61014_IMG_01.jpg
36516_61014_IMG_00.jpg public://rightmove/rm_images/36516_61014_IMG_00.jpg
36516_187881_IMG_00.jpg public://rightmove/rm_images/36516_187881_IMG_00.jpg
36516_187881_IMG_01.jpg public://rightmove/rm_images/36516_187881_IMG_01.jpg
when i do
where image_path=36516_61014/36516_61014_IMG_01.jpg, etc...
where I want it as:
36516_61014_IMG_01.jpg public://rightmove/rm_images/36516_61014/36516_61014_IMG_01.jpg
36516_61014_IMG_00.jpg public://rightmove/rm_images/36516_61014/36516_61014_IMG_00.jpg
36516_187881_IMG_00.jpg public://rightmove/rm_images/36516_1878811/36516_187881_IMG_00.jpg
36516_187881_IMG_01.jpg public://rightmove/rm_images/36516_187881/36516_187881_IMG_01.jpg
which would be equal to my source directory.
and when i try:
the migration doesn't seem to pick it up as it tries to put 'rm_images' as the filename and 'public://rightmove/' as the uri...
Comment #19
farse commentednot sure if the mount solves any of my problems as my files are already where i want them, just trying to solve the problem above. will apply the patch and see what happens..
installed the patch, same thing happened...
Comment #20
mikeryanYou mean your files are physically under the files folder, not linked in? OK, most of what I've been talking about is irrelevant to you, but the basic setup in comment #10 should work, something like:
If you can't tweak that to work, all I can suggest doing is what I did - debug MigrateFileUri::processFile() and MigrateFile::processFile(), printing out the key paths as they're constructed and deconstructed...
Comment #21
farse commentedi have all the above and
seems to be the only part that is causing me trouble, as it seems to ignore it and just returns the destination_dir. i'll have a look at the two classes and see if i notice anything else.
i just noticed something in my code that isn't quite the same as yours..
i have
instead of
as I have other fields I am mapping to the same node as in 'WineWineMigration', in case that makes any difference.
Comment #22
farse commentedone step closer...
in
MigrateFile::processFile() i printed out
to see what was happening.
turns out that $this->destinationFile is an array (of which I already knew), it printed 'public://rightmove/rm_imagesArray', but thought that was ok since i'm dealing with an array of images for the node and $this->addFieldMapping('field_prop_images', 'image_path'); seems to be ok with arrays. now the next question. how would i deal with a destination file array as the source file seems to be ok with them?
as the winewinemigration example also uses image arrays, but has 'field_migrate_example_image:source_dir', 'field_migrate_example_image:destination_dir',
'field_migrate_example_image:destination_file' as unmigrated destinations, so not able to figure out what to do!
Comment #23
mikeryanWith the new array angle here, cross-referencing #1673956: Migrating multiple files.
Comment #24
mikeryanA note on your observation that I'm using MigrateDestinationFile while you're using MigrateDestinationNode: you can migrate image fields in two ways - directly into the field as you are doing, or you can migrate the files separately (MigrateDestinationFile) then map the results of that migration to your image field using MigrateFileFid. I prefer the latter - I find it cleaner to have the file migration separate from the node migration. And, it probably works better in the array case...
Comment #25
mikeryanOK, your scenario is definitely not going to work - the loop in MigrateFileFieldBaseHandler that iterates over the image values does not iterate over destinationFile in parallel, and there isn't a way to pass distinct destinationFile values to processFile(). Trying to think of a non-hacky way to deal with this...
Comment #26
mikeryanReviewing this, the "bug" remaining is that the linking behavior doesn't work when files are symbolically linked into the Drupal files directory - this is due to core issue #1008402: Allow the use of symlinks within the files directory., and I'm not going to pursue working around it in Migrate.
Comment #26.0
mikeryanforgot to include intro text