2

I'm working on a D6 -> D8 migration, and my destination has a custom video upload field (field_video_upload) that contains three pieces of data: video, thumbnail, and poster (field_video_upload_video, field_video_upload_thumbnail, field_video_upload_poster respectively in the db). I'm attempting to migrate that data from my source table (actually a MySQL view) that has the data in a serialized format, and I'm using a custom source plugin to get the data.

  public function prepareRow(Row $row) {
    //TODO: Extract url from video_data field and video_thumb from thumbnail_data.
    $video_data = get_object_vars(unserialize($row->getSourceProperty('video_data')));
    $thumbnail_data = unserialize($row->getSourceProperty('thumbnail_data'));
    // Get the array values. Seems to be the best way to work around having an
    // array key of 0000000.
    $video_data = reset($video_data);
    $video_url = $video_data->url;
    $video_thumb = $thumbnail_data['video_thumb'];

    // Set the source properties.
    $row->setSourceProperty('video_url', $video_url);
    $row->setSourceProperty('video_thumb', $video_thumb);
  }
}

Here is the relevant portion of the migration configuration .yml file:

  field_video_upload:
    plugin: video_upload
    source:
      - video_url
      - video_thumb

and here is the custom process plugin video_upload to get the data:

namespace Drupal\migrate_mrctv\Plugin\migrate\process;

use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row;


/**
 * This plugin gets values for the video upload field.
 *
 * @MigrateProcessPlugin(
 *   id = "video_upload"
 * )
 */
class videoUpload extends ProcessPluginBase {

  /**
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    $video = array();

    list($video_url, $video_thumb)  = $value;

    $video['video'] = $video_url;
    // Use the same source thumb value for poster and thumb.
    $video['thumbnail'] = $video_thumb;
    $video['poster'] = $video_thumb;

    return $video;
  }
}

The source plugin works fine, and the data from the plugin is available in $value in videoUpload::transform(). However, none of the data is getting into this field in the node itself. The main node data is there, but no data for this field.

What do I need to change to get the data to import into my custom field?

Thanks.

UPDATE: In stepping through the Migrate code, I came across this line in Row->setDestinationProperty:

NestedArray::setValue($this->destination, explode(static::PROPERTY_SEPARATOR, $property), $value, TRUE);

and since PROPERTY_SEPARATOR = '/', I tried this in my configuration:

'field_video_upload/video': video_url
'field_video_upload/thumbnail': video_thumb
'field_video_upload/poster': video_thumb

but no difference.

UPDATE 2: Based on the answer from @heddn below, I'm using the iterator plugin as part of a pipeline, since this is a multivalue field, even though it's set to only allow one value.

  field_video_upload:
    -
      plugin: video_upload
      source:
        - video_url
        - video_thumb
    -
      plugin: iterator
      process:
        video: video
        thumbnail: thumbnail
        poster: thumbnail

and modifying my plugin:

  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    $video = array();

    list($video_url, $video_thumb)  = $value;

    $video[] = array(
      'video' => $video_url,
    // Use the same source thumb value for poster and thumb.
      'thumbnail' => $video_thumb,
       'poster' => $video_thumb
    );

    return $video;
  }
}

This appears to work in that I the array from the video_upload plugin is passed as $value to the iterator plugin, but I'm still not getting values in field_video_upload. What else am I missing?

2

That last part where you are doing the mapping like:

'field_video_upload/video': video_url 'field_video_upload/thumbnail': video_thumb 'field_video_upload/poster': video_thumb

is probably the closest. Is the destination field a multi-valued field? Then you'll need to follow the pattern as espoused in https://www.mtech-llc.com/blog/charlotte-leon/migration-csv-data-paragraphs

You need to create an array of data, then iterator over it and insert each record into the destination.

Namely (this is completely untested, but the idea of it should work if the destination is multi-valued):

   combination:
    plugin: get
    source:
      - video_url
      - video_thumb
  field_video_upload:
    plugin: iterator
    source: @combination
    process:
      video: video_url
      thumbnail: video_thumb
      poster: video_thumb
  • No, this is a single value field. It's a custom field for uploading a video file with a UI that allows you to drag/drop a file or choose the file. The columns I'm trying to migrate store the data for the video file. – wonder95 Dec 15 '16 at 17:14
  • So combination is just a pseudo field that stores the video_url and video_thumb in an array for the iterator plugin. So that should be the source for field_video_upload, correct? – wonder95 Dec 15 '16 at 23:43
1

It turns out that the problem with this was that the field schema had a couple of other subfields required, even though the db columns weren't required. This, combined with the fact that the error message gave no indication that this was the problem, made it very hard to track down.

My final field settings in the migrate config look like this:

  field_video_upload:
    -
      plugin: video_upload
      source:
        - video_url
        - video_thumb
        - vid
        - shows_ads
    -
      plugin: iterator
      process:
        video: video
        thumbnail: thumbnail
        poster: thumbnail
        vid: vid
        show_ads: show_ads

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.