Right now, to a field mapping you can add
->callbacks('html_entity_decode', array($this, 'myMigrationMember'));
It takes multiple arguments, each one a PHP callback type which takes a single argument (the source field value) and returns a value that will become the new source field value. But, what if you wanted to pass additional arguments to the callback, such as a character set to html_entity_decode? You would have to do it in prepareRow() or prepare(), not through a callback. So, I'd like to implement a new callback mechanism:
->callback('html_entity_decode', ENT_QUOTES, 'ISO8859-1')
->callback(array($this, 'myMigrationMember'));
First argument is the function/member to call, further arguments get passed after the source value when calling it. It would also be nice to be able to pass values from source data, as we do with arguments():
->callback('html_entity_decode', ENT_QUOTES, array('source_field' => 'charset'));
Upon implementing this, callbacks() will be deprecated.
| Comment | File | Size | Author |
|---|---|---|---|
| #14 | migrate-callback_args-1406802-14.patch | 2.17 KB | joelstein |
| #13 | 1406802-migrate_callback_support-13.patch | 2.17 KB | joelstein |
| #9 | 1406802-migrate_callback_support-9.patch | 2.46 KB | pcambra |
| #8 | 1406802-migrate_callback_support-8.patch | 560 bytes | pcambra |
Comments
Comment #1
drewish commentedI'm kind meh on this, mostly because I hate that whole array('source_field') aspect. I think it's the most cumbersome aspect of the arguments API so I'd love to see if there was a more elegant way to proceed.
Comment #2
mikeryanI'm open to suggestions on the source_field thing - how can we pass row values instead of hard-coded values to either arguments or callbacks?
Comment #3
drewish commentedI wonder if we could use something like a class name... I guess if I actually spent sometime allowing subfields it would get past the wart that is the arguments. One thing that would be really cool would be the ability to use PHP 5.3's anonymous functions. So we could pass in the $row and $fieldname so the 5.3 code could look like:
So if you needed to do something crazy you could go pull other values from the row. Maybe we give this a slightly different signature callbackAnon() or something so it's not conflicting with the 5.2 and below way of doing things.
I guess what'd like is for it to look more like straight PHP than strange arrays.
Comment #4
mikeryanI'd like to address the original idea for Migrate 2.4 (the source_field digression has been rendered obsolete by the subfield support already implemented).
Comment #5
mikeryanDeprioritizing - there doesn't seem to be much demand, and I haven't actually had a use case myself.
Comment #6
eddie_c commentedI'd really like to see this feature and would be happy to help out. I have a use case whereby I need to build a URL alias based on three different fields from the source.
I could handle them in prepare or prepareRow but I think this could get messy because all the source fields are mapped individually to different destination fields besides the URL alias.
I think being able to fetch multiple source values in a callback would make the solution a lot neater.
Comment #7
vacilando commentedI also think this is very much needed. I have a situation where a source field needs to be split and fed into several Drupal fields. I can use the current callbacks system but have to create a private function per task, which is inefficient and inelegant. If there were an option to specify additional arguments I would be able to dynamically specify which Drupal field is being processed and so one single callback function could do the splitting on the basis of the argument.
Comment #8
pcambraI've just found a use case of dependant fields that need the value from another field to fill a yes/no
I'll try to post this done properly, but for the moment the patch attached just adds the $mapping context to the callback which was what I needed in case someone else finds it useful.
Comment #9
pcambraWhat about this?
Comment #9.0
pcambraProper quotes
Comment #10
mikeryanWe can't simply remove callbacks(), it'll break too much existing migration code. The new callback() should be additive, with callbacks() being deprecated (see arguments(), just a couple functions down).
That being said, I'm concerned that introducing a new method with such a similar name would cause more confusion than it's worth - any ideas on a clearly distinguishable name?
Comment #11
wonder95 commentedAs an added note to this, I started to use this callbacks functionality for the first time in a custom class, and I couldn't figure out why I was getting an error saying that my callback couldn't be found. After looking at the code that calls the callbacks, I figured out that since it uses call_user_func() (and call_user_func_array() in the latest patch above) instead of something like $this->{$callback}, my callback had to be outside of the class (e.g. in the .module file or another included file). Looking at the example on the doc page, it's not apparent that the callbacks need to be outside of the class.
Is there any reason the callback shouldn't be in the migration class itself? To me, this makes sense, since the addition of the callback is done in the class constructor anyway (I'm no OOP guru, so there very well could be a good reason). If not, I would suggest that the docs page be updated to indicate that the callbacks need to be outside of the migration class in order to be found. I'll be happy to change the docs myself, but I want to make sure it's the correct thing to do first.
Comment #12
wonder95 commentedSigh, ignore that last comment. I misread the docs.
Back to my hole...
Comment #13
joelstein commentedI like the idea of the additive approach. See the attached patch which adds
callback()and keeps backwards compatibility withcallbacks().Thus, you can do something like this:
Comment #14
joelstein commentedRenamed the patch.
Comment #15
joelstein commentedFYI, I'm using this solution heavily on a big site migration, chaining both
callback()andcallbacks(). It improves the DX quite a bit.Mike, it was great to meet you at DrupalCamp STL. Thanks for the great presentation, and for all your hard work on the Migrate module.
Comment #16
osopolarThis is awesome and works fantastic.
Comment #18
mikeryanCommitted, thanks!