1

I am trying to import from a csv that has multiple files in the same column, e.g.

title,gallery,tag
node1,img1.jpg|img2.jpg|img3.jpg,2
node2,img4.jpg,2
node3,img5.jpg|img6.jpg,3

I need to prepend the path to these file names to get something of the form /path/to/file/img4.jpg.

I have written a process pipeline similar to the following (which doesn't work):

source:
  constants:
    file_source: '/import/images/'
    file_destination: '/path/to/file/'
process:
  title: title
  field_gallery:
    -
      plugin: explode
      source: gallery
      delimiter: '|'
    -
      plugin: concat
      source:
        - constants/file_source
        -
    -
      plugin: image_import
      destination: constants/file_destination

The failure comes because the Concat plugin implodes the array containing a string and an array to give an output in the form /path/to/file/Array.

I suspect there is a process plugin that I can insert between explode and concat that will solve this, but I can't work out what it is.

I have tried combinations of the plugins single_value and multiple_values from the Migrate Plus module, but that has not worked either.

For now I have written a custom process plugin to replace concat, but I would prefer a pipeline using pre-existing plugins.

2 Answers 2

1

I don't think this is possible with concat in a single pipe, because you need to define two sources for concat, and AFAIK you can't fill the source partly with the result from the previous section and partly with a completely new value.

Workaround: Use the str_replace plugin instead, which is a wrapper for PHP's preg_replace.

preg_replace will detect if source respectively $subject is an string or an array. If the $subject is an array, all elements will be updated, so you can replace all beginnings of a string ^ with /some/path/

Something like this:

  field_gallery:
    -
      plugin: str_replace
      regex: true
      source: gallery
      search: '/^/'
      replace: '/some/path/'

(Note that the slashes in search are not path delimiters, they are the enclosing symbol for the regex pattern)

2
  • Thanks @Hudri, I definitely prefer using the str_replace process plugin over a custom plugin. Can you think of a way to use a source constant, i.e. constants/file_source rather than hard-coding the value of replace to '/some/path/'?
    – jofitz
    Oct 21, 2021 at 18:11
  • Not really, this is by design of the Migrate module. Only the source: is treated like a reference, all other keys are config and used like a value.
    – Hudri
    Nov 24, 2021 at 15:45
0

Here are the highlights of the process plugin I wrote, in case anyone is interested in a custom solution:

class Prepend extends ProcessPluginBase {

  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    $return = [];
    foreach ($value as $item) {
      $return[] = implode($item);
    }
    return $return;
  }

  public function multiple() {
    return TRUE;
  }

}

Note: an important difference between this and the concat process plugin is the addition of the multiple() function that returns TRUE.

It can be used as follows:

field_gallery:
  -
    plugin: explode
    source: gallery_images
    delimiter: '|'
  -
    plugin: prepend
    source:
      - constants/file_source
      -
  -
    plugin: image_import
    destination: constants/file_destination
    uid: '@uid'
    skip_on_missing_source: true

EDIT: FWIW I have chosen to use the solution suggested by @Hudri.

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.