SubProcess.php

Same filename and directory in other branches
  1. 9 core/modules/migrate/src/Plugin/migrate/process/SubProcess.php
  2. 8.9.x core/modules/migrate/src/Plugin/migrate/process/SubProcess.php
  3. 10 core/modules/migrate/src/Plugin/migrate/process/SubProcess.php

Namespace

Drupal\migrate\Plugin\migrate\process

File

core/modules/migrate/src/Plugin/migrate/process/SubProcess.php

View source
<?php

namespace Drupal\migrate\Plugin\migrate\process;

use Drupal\migrate\Attribute\MigrateProcess;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateSkipRowException;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row;

/**
 * Runs an array of arrays through its own process pipeline.
 *
 * The sub_process plugin accepts an array of associative arrays and runs each
 * one through its own process pipeline, producing a newly keyed associative
 * array of transformed values.
 *
 * Available configuration keys:
 *   - process: the plugin(s) that will process each element of the source.
 *   - key: runs the process pipeline for the key to determine a new dynamic
 *     name. If the new dynamic name is NULL then the result of the sub_process
 *     pipeline is ignored.
 *   - include_source: (optional) If TRUE, all source plugin configuration and
 *     values will be copied into the sub-processed row in a new property named
 *     for the source_key configuration value (see below). Defaults to FALSE.
 *   - source_key: (optional) If include_source is TRUE, this
 *     is the name of the property of the sub-processed row which will contain
 *     the source configuration and values. Ignored if include_source is
 *     FALSE. Defaults to 'source' if no value is provided.
 *
 * Example 1:
 *
 * This example demonstrates how migration_lookup process plugin can be applied
 * on the following source data.
 * @code
 * source: Array
 * (
 *   [upload] => Array
 *     (
 *       [0] => Array
 *         (
 *           [fid] => 1
 *           [list] => 0
 *           [description] => "File number 1"
 *         )
 *       [1] => Array
 *         (
 *           [fid] => 2
 *           [list] => 1
 *           [description] => "File number 2"
 *         )
 *     )
 * )
 * ...
 * @endcode
 * The sub_process process plugin will take these arrays one at a time and run
 * its own process for each of them:
 * @code
 * process:
 *   upload:
 *     plugin: sub_process
 *     source: upload
 *     process:
 *       target_id:
 *         plugin: migration_lookup
 *         migration: d6_file
 *         source: fid
 *       display: list
 *       description: description
 * @endcode
 * In this case, each item in the upload array will be processed by the
 * sub_process process plugin. The target_id will be found by looking up the
 * destination value from a previous migration using the migration_lookup
 * process plugin. The display and description fields will be mapped directly.
 *
 * Example 2.
 *
 * Drupal 6 filter formats contain a list of filters belonging to that format
 * identified by a numeric delta. A delta of 1 indicates automatic linebreaks,
 * delta of 2 indicates the URL filter and so on. This example demonstrates how
 * static_map process plugin can be applied on the following source data.
 * @code
 * source: Array
 * (
 *   [format] => 1
 *   [name] => Filtered HTML
 * ...
 *   [filters] => Array
 *     (
 *       [0] => Array
 *         (
 *           [module] => filter
 *           [delta] => 2
 *           [weight] => 0
 *         )
 *       [1] => Array
 *         (
 *           [module] => filter
 *           [delta] => 0
 *           [weight] => 1
 *         )
 *    )
 * )
 * ...
 * @endcode
 * The sub_process will take these arrays one at a time and run its own process
 * for each of them:
 * @code
 * process:
 *   filters:
 *     plugin: sub_process
 *     source: filters
 *     process:
 *       id:
 *         plugin: static_map
 *         source:
 *           - module
 *           - delta
 *         map:
 *           filter:
 *             0: filter_html_escape
 *             1: filter_autop
 *             2: filter_url
 *             3: filter_htmlcorrector
 *             4: filter_html_escape
 *           php:
 *             0: php_code
 * @endcode
 * The example above means that we take each array element ([0], [1], etc.) from
 * the source filters field and apply the static_map plugin on it. Let's have a
 * closer look at the first array at index 0:
 * @code
 * Array
 * (
 *    [module] => filter
 *    [delta] => 2
 *    [weight] => 0
 * )
 * @endcode
 * The static_map process plugin results to value 'filter_url' for this input
 * based on the 'module' and 'delta' map.
 *
 * Example 3.
 *
 * Normally the array returned from sub_process will have its original keys. If
 * you need to change the key, it is possible for the returned array to be keyed
 * by one of the transformed values in the sub-array. For the same source data
 * used in the previous example, the migration below would result to keys
 * 'filter_2' and 'filter_0'. If the value for 'id' is NULL the result of the
 * sub_process pipeline is ignored.
 * @code
 * process:
 *   filters:
 *     plugin: sub_process
 *     source: filters
 *     key: "@id"
 *     process:
 *       id:
 *         plugin: concat
 *         source:
 *           - module
 *           - delta
 *         delimiter: _
 * @endcode
 *
 * @see \Drupal\migrate\Plugin\migrate\process\MigrationLookup
 * @see \Drupal\migrate\Plugin\migrate\process\StaticMap
 * @see \Drupal\migrate\Plugin\MigrateProcessInterface
 */
class SubProcess extends ProcessPluginBase {
    
    /**
     * SubProcess constructor.
     *
     * @param array $configuration
     *   A configuration array containing information about the plugin instance.
     * @param string $plugin_id
     *   The plugin_id for the plugin instance.
     * @param mixed $plugin_definition
     *   The plugin implementation definition.
     */
    public function __construct(array $configuration, $plugin_id, $plugin_definition) {
        $configuration += [
            'include_source' => FALSE,
            'source_key' => 'source',
        ];
        parent::__construct($configuration, $plugin_id, $plugin_definition);
    }
    
    /**
     * {@inheritdoc}
     */
    public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
        $return = $source = [];
        if ($this->configuration['include_source']) {
            $key = $this->configuration['source_key'];
            $source[$key] = $row->getSource();
        }
        if (is_iterable($value)) {
            foreach ($value as $key => $new_value) {
                if (!is_array($new_value)) {
                    throw new MigrateException(sprintf("Input array should hold elements of type array, instead element was of type '%s'", gettype($new_value)));
                }
                $new_row = new Row($new_value + $source);
                try {
                    $migrate_executable->processRow($new_row, $this->configuration['process']);
                } catch (MigrateSkipRowException $e) {
                    continue;
                }
                $destination = $new_row->getDestination();
                if (array_key_exists('key', $this->configuration)) {
                    $key = $this->transformKey($key, $migrate_executable, $new_row);
                }
                // Do not save the result if the key is NULL. The configured process
                // pipeline used in transformKey() will return NULL if the key can not
                // be transformed.
                if ($key !== NULL) {
                    $return[$key] = $destination;
                }
            }
        }
        return $return;
    }
    
    /**
     * Runs the process pipeline for the key to determine its dynamic name.
     *
     * @param string|int $key
     *   The current key.
     * @param \Drupal\migrate\MigrateExecutableInterface $migrate_executable
     *   The migrate executable helper class.
     * @param \Drupal\migrate\Row $row
     *   The current row after processing.
     *
     * @return mixed
     *   The transformed key.
     */
    protected function transformKey($key, MigrateExecutableInterface $migrate_executable, Row $row) {
        $process = [
            'key' => $this->configuration['key'],
        ];
        $migrate_executable->processRow($row, $process, $key);
        return $row->getDestinationProperty('key');
    }
    
    /**
     * {@inheritdoc}
     */
    public function multiple() {
        return TRUE;
    }

}

Classes

Title Deprecated Summary
SubProcess Runs an array of arrays through its own process pipeline.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.