Problem/Motivation
I recently had to import availability data from an external source with Migrate. I propose to integrate this capability in the Availability Calendars module.
Proposed resolution
Integration with Migrate for contrib modules used to be in a separate module called Migrate Extras, but this has been deprecated:
The best place to implement migration support for a contributed module is in that module, not in the Migrate or Migrate Extras modules. That way, the migration support is always self-consistent with the current module implementation.
I propose to embed a field handler directly in the Availability Calendars module.
Remaining tasks
Review the patch proposed in #2.
User interface changes
None.
API changes
Developers will now be able to migrate availability data to a field of type "availability_calendar", provided they use the correct format, as described in README.txt.
Data model changes
None.

| Comment | File | Size | Author |
|---|---|---|---|
| #9 | interdiff-8-9.txt | 3.53 KB | fmb |
| #9 | allow_import_availability_data_with_migrate-2658754-9.patch | 24.12 KB | fmb |
Comments
Comment #2
fmb commentedComment #3
fmb commentedComment #4
fmb commentedComment #5
fietserwinThanks for posting this patch. I had a quick look at it and found the points below. Reading your blog made some things clear, but let's ensure the code is readable stand alone, so adding some additional comments would be nice.
Regarding the hybrid approach:
It started as a field, and a complex one. So complex that I had to store the "real" data outside the field storage. Only later I discovered that it would be handier to (also) define it as an entity as that would facilitate integration with Views and Search API. So I defined it as an entity, but only on the reading side, thus no C,U, and D out of crud, via the entity API as that served my purposes. If I am going to create a D8 version it will be an entity only and the field should be replaced by an entity reference field.
Regarding the code you are reusing:
This code was so specific for the communication with the edit form that I could not envisage any use elsewhere and as such did not nbother to abstract it into a decent API method. However, I can do so now by moving the code you are using out of the widget code into the .inc where most of the API functions are living. In doing so, I can add parameters for the period to accept or even push that to a separate validator.
On the other hand, you can easily create your own array to pass directly to availability_calendar_update_multiple_availability() by adding 1 line per day, using a lookup to convert your source state to the destination state and a DateTime that you advance with a day on each character. In doing so, there's no need for the very strict validation, the need to convert to a string and back, nor for the date restrictions. Moreover, just passing NULL as $cid to availability_calendar_update_multiple_availability() ensures that a new calendar will be created and its cid returned, so exit $cid_unique and $new_cid_count. You can even "optimize" that array later:
Due to the hybrid approach of A.C. I'm not sure whether this registers the entity or field :)
not sure about this sentence, perhaps something like:
Creates and populates an availability entity/field.
Add @param and @return
trim($line) before checking for empty
use ===.
Comment #6
fmb commentedThanks fietserwin for your review and explanations! I considered the use of availability_calendar_field_widget_month_form_validate() vs directly calling availability_calendar_update_multiple_availability() and I think we should still call the validation function because:
1) We need a common input format: the one you're using for that is perfectly fine in my opinion, and it comes really handy that availability_calendar_field_widget_month_form_validate() is able to convert it into the "internal" format needed in availability_calendar_update_multiple_availability().
2) It is nice for the developer of a migration class to know his data can't be imported properly because they're not formatted as expected and thus don't pass the validation.
Now, we could, as you say, decouple this validation function from the widget, and maybe add a parameter to allow for less restrictive validation (allow to import past availability dates, for instance, even though I'm not entirely sure this might actually be of any use). As you can see, I don't have much contrib time, but if you open an issue for that, I'd be glad to work on a patch.
As for $cid_unique and such, I have to confess I'm not sure I understood entirely this mechanism, maybe some of the code I wrote is superfluous...
Comment #7
fietserwinI was more thinking about going the direct way (using availability_calendar_update_multiple_availability() directly), but think that this solution that accepts both ways is better.
I Also made some other (small) changes. Can you review (and test?)? Will this work in a real migrate situation?
Comment #8
fmb commentedI integrated your changes, and not only tested them, but wrote a test! I hope you will be OK with this approach. That works with the included test data, but I think I am going to work a little bit on availability_calendar_field_widget_month_form_validate_line(), so it is able to accept intervals that begin in the past.
Comment #9
fmb commentedI made a small change in this function as announced.
Comment #10
fmb commentedComment #11
fietserwinNice, however I can't get the test to work, it fails on the last assertion.
- hook_migrate_api in availability_calendar.migrate.inc gets called
- I see the XML mapper at work
- But the resulting string does not get "prepared". It gets set as the field value and after that the node gets saved with that incorrect field value ("2,2016-04-01,2016-05-31\n ...")
Where should AvailabilityCalendarFieldHandler enter the stage (getting constructed) and when should its prepare() method gets called?
I'm running the test via the UI on my local install.
Comment #13
fietserwinI committed the code, including the tests, even if I can't get them to run locally. Can you have another look? Maybe my latest changes contain a bug after all.
Do you want to be listed as a sponsor/contributor to this module on the project page? If so, under what name and link?
Comment #14
fmb commentedI was a bit busy, sorry for not answering lately ^^;
That's strange, I ran it using the Simpletest UI in a new Drupal installation and the latest Git version of Availability Calendars, and it worked (see attached screenshot)... Does Simpletest display some kind of message?
Thanks a lot for committing the patch! It would indeed be really kind of you to list me in the sponsor/contributor section on the project page under "Felip Manyer i Ballester" and link to my user page.
Comment #15
fmb commented