0

I have 40/1040 source product_id's I need to ignore in one migration, so that I can put them in their own separate migration. I can exclude and include them in the yaml files, but it's a bit ugly and I would rather do so in the custom source plugin because doing this in the yaml is not performant as they are all queried in both.

I can exclude the 40 from their own yaml this way:

process:
  variation_id:
    -
      plugin: skip_on_value
      source: product_id
      method: row
      value:
        - 1
        - 2
        - all the way to 40

I can include only the 40 in another yaml this way:

process:
  variation_id:
    -
      plugin: skip_on_value
      not_equals: true
      source: product_id
      method: row
      value:
        - 1
        - 2
        - all the way to 40

But I would rather set a string of product_id's to include/exclude (I'm guessing in the public function query()??) because when I run the smaller migration (the 40) there is no need to query and ignore the other 1000 variations.

I created a copy of the source plugin so that I could use a distinct plugin for each of the 2 migrations. Here is the plugin that I am currently using for both:

use CommerceGuys\Intl\Currency\CurrencyRepository;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;

/**
 * Gets Commerce 1 commerce_product data from database.
 *
 * @MigrateSource(
 *   id = "commerce1_product_bundle",
 *   source_module = "commerce_product"
 * )
 */
class CommerceProduct extends FieldableEntity {

  /**
   * {@inheritdoc}
   */
  public function fields() {
    return [
      'product_id' => t('Product variation ID'),
      'sku' => t('SKU'),
      'title' => t('Title'),
      'type' => t('Type'),
      'language' => t('Language'),
      'status' => t('Status'),
      'created' => t('Created'),
      'changed' => t('Changes'),
      'data' => t('Data'),
      'commerce_price' => t('Price with amount, currency_code and fraction_digits'),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getIds() {
    $ids['product_id']['type'] = 'integer';
    $ids['product_id']['alias'] = 'p';
    return $ids;
  }

  /**
   * {@inheritdoc}
   */
  public function query() {
    $query = $this->select('commerce_product', 'p')->fields('p');
    if (isset($this->configuration['product_variation_type'])) {
      $query->condition('p.type', $this->configuration['product_variation_type']);
    }
    return $query;
  }

  /**
   * {@inheritdoc}
   */
  public function prepareRow(Row $row) {
    $product_id = $row->getSourceProperty('product_id');
    $revision_id = $row->getSourceProperty('revision_id');
    foreach (array_keys($this->getFields('commerce_product', $row->getSourceProperty('type'))) as $field) {
      $row->setSourceProperty($field, $this->getFieldValues('commerce_product', $field, $product_id, $revision_id));
    }

So I'm asking how to exclude an array of 40 product_id's in one plugin, and then only include an array of 40 product_id's in the other plugin.

Should I do this in the public function getIds(), the public function query(), or the public function prepareRow(Row $row)?

My guess would be in the public function query() But I would like to know the best way, and why.

1

1 Answer 1

1

This was quite easy by adding a $query->condition() to public function query() using IN and NOT IN in dynamic queries

This worked to exclude certain id's:

$products = [1, 2, 3,];
$query->condition('product_id', $products, 'NOT IN');

This worked to include only certain id's:

$products = [1, 2, 3,];
$query->condition('product_id', $products, 'IN');

I was then able to clean up the yamls, and only query the stuff I wanted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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