diff --git a/migrations/d7_field_collection.yml b/migrations/d7_field_collection.yml new file mode 100644 index 0000000..617f917 --- /dev/null +++ b/migrations/d7_field_collection.yml @@ -0,0 +1,17 @@ +id: d7_field_collection +label: Field Collections +migration_tags: + - Drupal 7 +deriver: Drupal\paragraphs\Plugin\migrate\D7FieldCollectionItemDeriver +source: + plugin: d7_field_collection_item +process: + type: bundle + +destination: + plugin: paragraphs +migration_dependencies: + required: + - d7_field_collection_type + optional: + - d7_field_instance diff --git a/migrations/d7_field_collection_revisions.yml b/migrations/d7_field_collection_revisions.yml new file mode 100644 index 0000000..99ccbce --- /dev/null +++ b/migrations/d7_field_collection_revisions.yml @@ -0,0 +1,24 @@ +id: d7_field_collection_revisions +label: Field Collection Revisions +migration_tags: + - Drupal 7 +deriver: Drupal\paragraphs\Plugin\migrate\D7FieldCollectionItemDeriver +source: + plugin: d7_field_collection_item_revision +process: + id: + - + plugin: migration_lookup + migration: d7_field_collection + source: item_id + - + plugin: extract + index: + - + 0 + type: bundle +destination: + plugin: paragraphs +migration_dependencies: + required: + - d7_field_collection \ No newline at end of file diff --git a/migrations/d7_paragraphs.yml b/migrations/d7_paragraphs.yml new file mode 100644 index 0000000..f0bd4bc --- /dev/null +++ b/migrations/d7_paragraphs.yml @@ -0,0 +1,16 @@ +id: d7_paragraphs +label: Paragraphs +migration_tags: + - Drupal 7 +deriver: Drupal\paragraphs\Plugin\migrate\D7ParagraphsItemDeriver +source: + plugin: d7_paragraphs_item +process: + type: bundle +destination: + plugin: paragraphs +migration_dependencies: + required: + - d7_paragraphs_type + optional: + - d7_field_instance diff --git a/migrations/d7_paragraphs_revisions.yml b/migrations/d7_paragraphs_revisions.yml new file mode 100644 index 0000000..5afbbad --- /dev/null +++ b/migrations/d7_paragraphs_revisions.yml @@ -0,0 +1,24 @@ +id: d7_paragraphs_revisions +label: Paragraphs Revisions +migration_tags: + - Drupal 7 +deriver: Drupal\paragraphs\Plugin\migrate\D7ParagraphsItemDeriver +source: + plugin: d7_paragraphs_item_revision +process: + id: + - + plugin: migration_lookup + migration: d7_paragraphs + source: item_id + - + plugin: extract + index: + - + 0 + type: bundle +destination: + plugin: paragraphs +migration_dependencies: + required: + - d7_paragraphs diff --git a/paragraphs.module b/paragraphs.module index 8b79738..3865328 100644 --- a/paragraphs.module +++ b/paragraphs.module @@ -8,6 +8,12 @@ use Drupal\Core\Url; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\field\FieldStorageConfigInterface; +use Drupal\field\Plugin\migrate\source\d7\Field; +use Drupal\field\Plugin\migrate\source\d7\FieldInstance; +use Drupal\field\Plugin\migrate\source\d7\FieldInstancePerViewMode; +use Drupal\field\Plugin\migrate\source\d7\FieldInstancePerFormDisplay; +use Drupal\field\Plugin\migrate\source\d7\ViewMode; +use Drupal\migrate_drupal\Plugin\migrate\FieldMigration; use Drupal\paragraphs\Entity\ParagraphsType; use Drupal\Core\Render\Element; @@ -440,3 +446,107 @@ function paragraphs_library_info_alter(&$libraries, $extension) { return $libraries; } + +/** + * Implements hook_migration_plugins_alter(). + * + * @todo refactor/rethink this when + * https://www.drupal.org/project/drupal/issues/2904765 is resolved + */ +function paragraphs_migration_plugins_alter(array &$migrations) { + foreach ($migrations as $key => &$migration) { + /** @var \Drupal\migrate\Plugin\MigrationPluginManager $migration_plugin_manager */ + $migration_plugin_manager = \Drupal::service('plugin.manager.migration'); + $migration_stub = $migration_plugin_manager->createStubMigration($migration); + /** @var \Drupal\migrate\Plugin\MigrateSourcePluginManager $source_plugin_manager */ + $source_plugin_manager = \Drupal::service('plugin.manager.migrate.source'); + $source = NULL; + $configuration = $migration['source']; + $source = $source_plugin_manager->createInstance($migration['source']['plugin'], $configuration, $migration_stub); + if ($source) { + if ((is_a($migration['class'], FieldMigration::class, TRUE))) { + + // Field storage. + if (is_a($source, Field::class)) { + _paragraphs_migration_entity_type_adjust($migration); + } + + // Field instance. + if (is_a($source, FieldInstance::class)) { + _paragraphs_migration_entity_type_adjust($migration); + _paragraphs_migration_bundle_adjust($migration); + $migration['migration_dependencies']['optional'][] = 'd7_field_collection_type'; + $migration['migration_dependencies']['optional'][] = 'd7_paragraphs_type'; + } + } + + // View Modes. + if (is_a($source, ViewMode::class)) { + _paragraphs_migration_entity_type_adjust($migration, 'targetEntityType'); + } + } + } +} + +/** + * Remove 'field_' prefix from field collection bundles. + * + * @param array $migration + * The migration configuration to process. + */ +function _paragraphs_migration_bundle_adjust(array &$migration) { + + if (!isset($migration['process']['bundle'])) { + $migration['process']['bundle'] = []; + } + + $bundle_process = $migration['process']['bundle']; + + // Try to play nice with other modules altering this, and don't replace + // it outright unless it's unchanged. + if (array_key_exists('plugin', $bundle_process)) { + $bundle_process = [$bundle_process]; + } + $bundle_process[] = [ + 'plugin' => 'paragraphs_process_on_value', + 'source_value' => 'entity_type', + 'expected_value' => 'field_collection_item', + 'process' => [ + 'plugin' => 'substr', + 'start' => 6, + ], + ]; + $migration['process']['bundle'] = $bundle_process; +} + +/** + * Map field_collection_item and 'paragraphs_item' fields to 'paragraph'. + * + * @param array $migration + * Thei migration to process. + * @param string $destination + * The process destination. + */ +function _paragraphs_migration_entity_type_adjust(array &$migration, $destination = 'entity_type') { + $entity_type_process = $migration['process'][$destination]; + + // Try to play with other modules altering this, and don't replace it + // outright unless it's unchanged. + if (!is_array($entity_type_process)) { + $entity_type_process = [ + [ + 'plugin' => 'get', + 'source' => 'entity_type', + ], + ]; + } + $entity_type_process[] = [ + 'plugin' => 'static_map', + 'map' => [ + 'field_collection_item' => 'paragraph', + 'paragraphs_item' => 'paragraph', + ], + 'bypass' => TRUE, + ]; + $migration['process'][$destination] = $entity_type_process; +} diff --git a/src/Plugin/migrate/D7FieldCollectionItemDeriver.php b/src/Plugin/migrate/D7FieldCollectionItemDeriver.php new file mode 100644 index 0000000..980c8f4 --- /dev/null +++ b/src/Plugin/migrate/D7FieldCollectionItemDeriver.php @@ -0,0 +1,167 @@ +basePluginId = $base_plugin_id; + $this->cckPluginManager = $cck_manager; + $this->fieldPluginManager = $field_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static( + $base_plugin_id, + $container->get('plugin.manager.migrate.cckfield'), + $container->get('plugin.manager.migrate.field') + ); + } + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinitions($base_plugin_definition) { + $types = static::getSourcePlugin('d7_field_collection_type'); + + try { + $types->checkRequirements(); + } + catch (RequirementsException $e) { + return $this->derivatives; + } + + $fields = []; + try { + $source_plugin = static::getSourcePlugin('d7_field_instance'); + $source_plugin->checkRequirements(); + + foreach ($source_plugin as $row) { + if ($row->getSourceProperty('entity_type') == 'field_collection_item') { + $fields[$row->getSourceProperty('bundle')][$row->getSourceProperty('field_name')] = $row->getSource(); + } + } + } + catch (RequirementsException $e) { + //no fields, no problem. we can keep going. + + } + + try { + foreach ($types as $row) { + /** @var \Drupal\migrate\Row $row */ + $values = $base_plugin_definition; + $fc_bundle = $row->getSourceProperty('field_name'); + $p_bundle = $row->getSourceProperty('bundle'); + $values['label'] = t('@label (@type)', [ + '@label' => $values['label'], + '@type' => $row->getSourceProperty('name'), + ]); + $values['source']['field_name'] = $fc_bundle; + $values['destination']['default_bundle'] = $p_bundle; + + /** @var \Drupal\migrate\Plugin\Migration $migration */ + $migration = \Drupal::service('plugin.manager.migration') + ->createStubMigration($values); + if (isset($fields[$fc_bundle])) { + + foreach ($fields[$fc_bundle] as $field_name => $info) { + $field_type = $info['type']; + try { + $plugin_id = $this->fieldPluginManager->getPluginIdFromFieldType($field_type, ['core' => 7], $migration); + if (!isset($this->fieldPluginCache[$field_type])) { + $this->fieldPluginCache[$field_type] = $this->fieldPluginManager->createInstance($plugin_id, ['core' => 7], $migration); + } + $this->fieldPluginCache[$field_type] + ->processFieldValues($migration, $field_name, $info); + } + catch (PluginNotFoundException $ex) { + try { + $plugin_id = $this->cckPluginManager->getPluginIdFromFieldType($field_type, ['core' => 7], $migration); + if (!isset($this->cckPluginCache[$field_type])) { + $this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($plugin_id, ['core' => 7], $migration); + } + $this->cckPluginCache[$field_type] + ->processCckFieldValues($migration, $field_name, $info); + } + catch (PluginNotFoundException $ex) { + $migration->setProcessOfProperty($field_name, $field_name); + } + } + } + } + $this->derivatives[$p_bundle] = $migration->getPluginDefinition(); + } + } + catch (DatabaseExceptionWrapper $e) { + // Once we begin iterating the source plugin it is possible that the + // source tables will not exist. This can happen when the + // MigrationPluginManager gathers up the migration definitions but we do + // not actually have a Drupal 7 source database. + } + return $this->derivatives; + } + +} diff --git a/src/Plugin/migrate/D7ParagraphsItemDeriver.php b/src/Plugin/migrate/D7ParagraphsItemDeriver.php new file mode 100644 index 0000000..62da913 --- /dev/null +++ b/src/Plugin/migrate/D7ParagraphsItemDeriver.php @@ -0,0 +1,164 @@ +basePluginId = $base_plugin_id; + $this->cckPluginManager = $cck_manager; + $this->fieldPluginManager = $field_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, $base_plugin_id) { + return new static( + $base_plugin_id, + $container->get('plugin.manager.migrate.cckfield'), + $container->get('plugin.manager.migrate.field') + ); + } + + /** + * {@inheritdoc} + */ + public function getDerivativeDefinitions($base_plugin_definition) { + + $types = static::getSourcePlugin('d7_paragraphs_type'); + try { + $types->checkRequirements(); + } + catch (RequirementsException $e) { + return $this->derivatives; + } + + $fields = []; + try { + $source_plugin = static::getSourcePlugin('d7_field_instance'); + $source_plugin->checkRequirements(); + + foreach ($source_plugin as $row) { + if ($row->getSourceProperty('entity_type') == 'paragraphs_item') { + $fields[$row->getSourceProperty('bundle')][$row->getSourceProperty('field_name')] = $row->getSource(); + } + } + } + catch (RequirementsException $e) { + + } + + try { + foreach ($types as $row) { + $values = $base_plugin_definition; + $bundle = $row->getSourceProperty('bundle'); + $values['label'] = t('@label (@type)', [ + '@label' => $values['label'], + '@type' => $row->getSourceProperty('name'), + ]); + $values['source']['bundle'] = $bundle; + $values['destination']['default_bundle'] = $bundle; + + /** @var \Drupal\migrate\Plugin\Migration $migration */ + $migration = \Drupal::service('plugin.manager.migration') + ->createStubMigration($values); + if (isset($fields[$bundle])) { + + foreach ($fields[$bundle] as $field_name => $info) { + $field_type = $info['type']; + try { + $plugin_id = $this->fieldPluginManager->getPluginIdFromFieldType($field_type, ['core' => 7], $migration); + if (!isset($this->fieldPluginCache[$field_type])) { + $this->fieldPluginCache[$field_type] = $this->fieldPluginManager->createInstance($plugin_id, ['core' => 7], $migration); + } + $this->fieldPluginCache[$field_type] + ->processFieldValues($migration, $field_name, $info); + } + catch (PluginNotFoundException $ex) { + try { + $plugin_id = $this->cckPluginManager->getPluginIdFromFieldType($field_type, ['core' => 7], $migration); + if (!isset($this->cckPluginCache[$field_type])) { + $this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($plugin_id, ['core' => 7], $migration); + } + $this->cckPluginCache[$field_type] + ->processCckFieldValues($migration, $field_name, $info); + } + catch (PluginNotFoundException $ex) { + $migration->setProcessOfProperty($field_name, $field_name); + } + } + } + } + $this->derivatives[$bundle] = $migration->getPluginDefinition(); + } + } + catch (DatabaseExceptionWrapper $e) { + // Once we begin iterating the source plugin it is possible that the + // source tables will not exist. This can happen when the + // MigrationPluginManager gathers up the migration definitions but we do + // not actually have a Drupal 7 source database. + } + return $this->derivatives; + } + +} diff --git a/src/Plugin/migrate/destination/Paragraphs.php b/src/Plugin/migrate/destination/Paragraphs.php new file mode 100644 index 0000000..b381b79 --- /dev/null +++ b/src/Plugin/migrate/destination/Paragraphs.php @@ -0,0 +1,75 @@ +getEntityTypeFromClass(Paragraph::class); + } + + /** + * {@inheritdoc} + */ + protected function getEntity(Row $row, array $oldDestinationIdValues) { + $item_id = $oldDestinationIdValues ? + array_shift($oldDestinationIdValues) : + $this->getEntityId($row); + $revision_id = $oldDestinationIdValues ? + array_pop($oldDestinationIdValues) : + $row->getDestinationProperty($this->getKey('revision')); + + // If a specific revision_id is supplied, update the revision. + /** @var \Drupal\Core\Entity\RevisionableInterface|\Drupal\Core\Entity\EntityInterface $entity */ + if (!empty($revision_id) && ($entity = $this->storage->loadRevision($revision_id))) { + $entity->setNewRevision(FALSE); + $entity = $this->updateEntity($entity, $row) ?: $entity; + } + // If there is no revision supplied, but there is an entity_id + // create a new revision. + elseif (!empty($item_id) && ($entity = $this->storage->load($item_id))) { + $entity->setNewRevision(TRUE); + $entity = $this->updateEntity($entity, $row) ?: $entity; + } + + // Otherwise, create a new (possibly stub) entity. + else { + // Attempt to ensure we always have a bundle. + if ($bundle = $this->getBundle($row)) { + $row->setDestinationProperty($this->getKey('bundle'), $bundle); + } + + // Stubs might need some required fields filled in. + if ($row->isStub()) { + $this->processStubRow($row); + } + $entity = $this->storage->create($row->getDestination()) + ->enforceIsNew(TRUE); + $entity->setNewRevision(TRUE); + } + $this->rollbackAction = MigrateIdMapInterface::ROLLBACK_DELETE; + return $entity; + } + +} diff --git a/src/Plugin/migrate/field/FieldCollection.php b/src/Plugin/migrate/field/FieldCollection.php new file mode 100644 index 0000000..d3983ed --- /dev/null +++ b/src/Plugin/migrate/field/FieldCollection.php @@ -0,0 +1,124 @@ + 'sub_process', + 'source' => $field_name, + 'process' => [ + 'target_id' => [ + [ + 'plugin' => 'migration_lookup', + 'migration' => 'd7_field_collection', + 'source' => 'value', + ], + [ + 'plugin' => 'extract', + 'index' => [0], + ], + ], + 'target_revision_id' => [ + [ + 'plugin' => 'migration_lookup', + 'migration' => [ + 'd7_field_collection_revisions', + 'd7_field_collection', + ], + 'source_ids' => [ + 'd7_field_collection_revisions' => ['revision_id'], + 'd7_field_collection' => ['value'], + ], + // D8.4 Does not like an empty source value, Even when using ids. + 'source' => 'value', + ], + [ + 'plugin' => 'extract', + 'index' => [1], + ], + ], + ], + ]; + $migration->setProcessOfProperty($field_name, $process); + } + + /** + * {@inheritdoc} + */ + public function processFieldFormatter(MigrationInterface $migration) { + $options_type[0]['map']['field_collection_view'] = 'entity_reference_revisions_entity_view'; + + $view_mode = [ + 'field_collection' => [ + 'plugin' => 'paragraphs_process_on_value', + 'source_value' => 'type', + 'expected_value' => 'field_collection', + 'process' => [ + 'plugin' => 'get', + 'source' => 'formatter/settings/view_mode', + ], + ], + ]; + + $migration->mergeProcessOfProperty('options/type', $options_type); + $migration->mergeProcessOfProperty('options/settings/view_mode', $view_mode); + } + + /** + * {@inheritdoc} + */ + public function getFieldWidgetMap() { + return ['field_collection_embed' => 'entity_reference_paragraphs'] + + parent::getFieldWidgetMap(); + } + + /** + * {@inheritdoc} + */ + public function processField(MigrationInterface $migration) { + $settings = [ + 'field_collection' => [ + 'plugin' => 'field_collection_field_settings', + ], + ]; + $migration->mergeProcessOfProperty('settings', $settings); + } + + /** + * {@inheritdoc} + */ + public function processFieldInstance(MigrationInterface $migration) { + $settings = [ + 'field_collection' => [ + 'plugin' => 'field_collection_field_instance_settings', + 'prefix' => 'field_', + ], + ]; + $migration->mergeProcessOfProperty('settings', $settings); + } + +} diff --git a/src/Plugin/migrate/field/Paragraphs.php b/src/Plugin/migrate/field/Paragraphs.php new file mode 100644 index 0000000..8c5950a --- /dev/null +++ b/src/Plugin/migrate/field/Paragraphs.php @@ -0,0 +1,179 @@ + 'sub_process', + 'source' => $field_name, + 'process' => [ + 'target_id' => [ + [ + 'plugin' => 'migration_lookup', + 'migration' => 'd7_paragraphs', + 'source' => 'value', + ], + [ + 'plugin' => 'extract', + 'index' => [0], + ], + ], + 'target_revision_id' => [ + [ + 'plugin' => 'migration_lookup', + 'migration' => [ + 'd7_paragraphs_revisions', + 'd7_paragraphs', + ], + 'source_ids' => [ + 'd7_paragraphs_revisions' => ['revision_id'], + 'd7_paragraphs' => ['value'], + ], + // D8.4 Does not like an empty source value, Even when using ids. + 'source' => 'value', + ], + [ + 'plugin' => 'extract', + 'index' => [1], + ], + ], + ], + ]; + $migration->setProcessOfProperty($field_name, $process); + } + + /** + * {@inheritdoc} + */ + public function processFieldWidget(MigrationInterface $migration) { + parent::processFieldWidget($migration); + $title = [ + 'paragraphs' => [ + 'plugin' => 'paragraphs_process_on_value', + 'source_value' => 'type', + 'expected_value' => 'paragraphs', + 'process' => [ + 'plugin' => 'get', + 'source' => 'settings/title', + ], + ], + ]; + $title_plural = [ + 'paragraphs' => [ + 'plugin' => 'paragraphs_process_on_value', + 'source_value' => 'type', + 'expected_value' => 'paragraphs', + 'process' => [ + 'plugin' => 'get', + 'source' => 'settings/title_multiple', + ], + ], + ]; + $edit_mode = [ + 'paragraphs' => [ + 'plugin' => 'paragraphs_process_on_value', + 'source_value' => 'type', + 'expected_value' => 'paragraphs', + 'process' => [ + 'plugin' => 'get', + 'source' => 'settings/default_edit_mode', + ], + ], + ]; + $add_mode = [ + 'paragraphs' => [ + 'plugin' => 'paragraphs_process_on_value', + 'source_value' => 'type', + 'expected_value' => 'paragraphs', + 'process' => [ + 'plugin' => 'get', + 'source' => 'settings/add_mode', + ], + ], + ]; + + $migration->mergeProcessOfProperty('options/settings/title', $title); + $migration->mergeProcessOfProperty('options/settings/title_plural', $title_plural); + $migration->mergeProcessOfProperty('options/settings/edit_mode', $edit_mode); + $migration->mergeProcessOfProperty('options/settings/add_mode', $add_mode); + } + + /** + * {@inheritdoc} + */ + public function processFieldFormatter(MigrationInterface $migration) { + $options_type[0]['map']['paragraphs_view'] = 'entity_reference_revisions_entity_view'; + $view_mode = [ + 'paragraphs' => [ + 'plugin' => 'paragraphs_process_on_value', + 'source_value' => 'type', + 'expected_value' => 'paragraphs', + 'process' => [ + 'plugin' => 'get', + 'source' => 'formatter/settings/view_mode', + ], + ], + ]; + $migration->mergeProcessOfProperty('options/type', $options_type); + $migration->mergeProcessOfProperty('options/settings/view_mode', $view_mode); + } + + /** + * {@inheritdoc} + */ + public function getFieldWidgetMap() { + return ['paragraphs_embed' => 'entity_reference_paragraphs'] + + parent::getFieldWidgetMap(); + } + + /** + * {@inheritdoc} + */ + public function processField(MigrationInterface $migration) { + + $settings = [ + 'paragraphs' => [ + 'plugin' => 'paragraphs_field_settings', + ], + ]; + $migration->mergeProcessOfProperty('settings', $settings); + } + + /** + * {@inheritdoc} + */ + public function processFieldInstance(MigrationInterface $migration) { + + $settings = [ + 'paragraphs' => [ + 'plugin' => 'paragraphs_field_instance_settings', + ], + ]; + $migration->mergeProcessOfProperty('settings', $settings); + } + +} diff --git a/src/Plugin/migrate/process/FieldCollectionFieldInstanceSettings.php b/src/Plugin/migrate/process/FieldCollectionFieldInstanceSettings.php new file mode 100644 index 0000000..be82e74 --- /dev/null +++ b/src/Plugin/migrate/process/FieldCollectionFieldInstanceSettings.php @@ -0,0 +1,61 @@ +getSourceProperty('type'); + + if ($type == 'field_collection') { + $bundles = $this->entityTypeBundleInfo->getBundleInfo('paragraph'); + + $target_bundle = $row->getSourceProperty('field_name'); + // Remove field_ prefix for new bundle. + $target_bundle = substr($target_bundle, static::FIELD_COLLECTION_PREFIX_LENGTH); + + if (!isset($bundles[$target_bundle])) { + throw new MigrateSkipRowException('No target paragraph bundle found for field_collection'); + } + + // Enable only this paragraph type for this field. + $value['handler_settings']['negate'] = 0; + $value['handler_settings']['target_bundles'] = [$target_bundle => $target_bundle]; + $value['handler_settings']['target_bundles_drag_drop'][$target_bundle] = [ + 'enabled' => TRUE, + 'weight' => -count($bundles), + ]; + unset($bundles[$target_bundle]); + + foreach ($bundles as $bundle_name => $bundle) { + $value['handler_settings']['target_bundles_drag_drop'][$bundle_name] = [ + 'enabled' => FALSE, + 'weight' => -count($bundles), + ]; + unset($bundles[$bundle_name]); + } + } + return $value; + } + +} diff --git a/src/Plugin/migrate/process/FieldCollectionFieldSettings.php b/src/Plugin/migrate/process/FieldCollectionFieldSettings.php new file mode 100644 index 0000000..e1c7cb0 --- /dev/null +++ b/src/Plugin/migrate/process/FieldCollectionFieldSettings.php @@ -0,0 +1,28 @@ +getSourceProperty('type') == 'field_collection') { + $value['target_type'] = 'paragraph'; + } + return $value; + } + +} diff --git a/src/Plugin/migrate/process/ParagraphsFieldInstanceSettings.php b/src/Plugin/migrate/process/ParagraphsFieldInstanceSettings.php new file mode 100644 index 0000000..b2b1ac4 --- /dev/null +++ b/src/Plugin/migrate/process/ParagraphsFieldInstanceSettings.php @@ -0,0 +1,86 @@ +getSourceProperty('type'); + + if ($type == 'paragraphs') { + $bundles = $this->entityTypeBundleInfo->getBundleInfo('paragraph'); + + if (!empty($value['allowed_bundles'])) { + + $target_bundles = array_filter($value['allowed_bundles'], function ($a) { + return $a != -1; + }); + if (!count($target_bundles)) { + + // No bundles are selected and therefore this field was set to allow + // all bundles in d7, but maybe we now have additional bundles + // from a field collection migration or pre-existing that shouldn't be + // included. + if (count($value['allowed_bundles']) == count($bundles)) { + + // We don't, so configure this one to allow all as well. + $value['handler_settings']['negate'] = 0; + $value['handler_settings']['target_bundles'] = []; + } + else { + + // Yes, new bundles. Don't allow the new ones to be selected + // in this field instance. + $value['handler_settings']['negate'] = 1; + $other_bundles = array_keys(array_diff_key($bundles, $value['allowed_bundles'])); + $value['handler_settings']['target_bundles'] = array_combine($other_bundles, $other_bundles); + } + } + else { + $value['handler_settings']['negate'] = 0; + $value['handler_settings']['target_bundles'] = $target_bundles; + } + unset($value['allowed_bundles']); + } + + if (!empty($value['bundle_weights'])) { + + // Copy the existing weights, and add any new bundles (either from + // a field collection migration happening now, or pre-existing on the + // site at the bottom. + foreach ($value['bundle_weights'] as $bundle_name => $weight) { + $value['handler_settings']['target_bundles_drag_drop'][$bundle_name] = [ + 'enabled' => array_key_exists($bundle_name, $value['handler_settings']['target_bundles']), + 'weight' => $weight, + ]; + } + $other_bundles = array_keys(array_diff_key($bundles, $value['bundle_weights'])); + $weight = max($value['bundle_weights']) + 1; + foreach ($other_bundles as $bundle_name) { + $value['handler_settings']['target_bundles_drag_drop'][$bundle_name] = [ + 'enabled' => array_key_exists($bundle_name, $value['handler_settings']['target_bundles']), + 'weight' => $weight, + ]; + } + unset($value['bundle_weights']); + } + } + return $value; + } + +} diff --git a/src/Plugin/migrate/process/ParagraphsFieldSettings.php b/src/Plugin/migrate/process/ParagraphsFieldSettings.php new file mode 100644 index 0000000..1569a13 --- /dev/null +++ b/src/Plugin/migrate/process/ParagraphsFieldSettings.php @@ -0,0 +1,28 @@ +getSourceProperty('type') == 'paragraphs') { + $value['target_type'] = 'paragraph'; + } + return $value; + } + +} diff --git a/src/Plugin/migrate/process/ParagraphsProcessOnValue.php b/src/Plugin/migrate/process/ParagraphsProcessOnValue.php new file mode 100644 index 0000000..ce875ab --- /dev/null +++ b/src/Plugin/migrate/process/ParagraphsProcessOnValue.php @@ -0,0 +1,83 @@ +configuration['source_value'])) { + throw new \InvalidArgumentException("Required argument 'source_value' not set for paragraphs_process_on_value plugin"); + } + if (empty($this->configuration['expected_value'])) { + throw new \InvalidArgumentException("Required argument 'expected_value' not set for paragraphs_process_on_value plugin"); + } + if (empty($this->configuration['process']) || !is_array($this->configuration['process'])) { + throw new \InvalidArgumentException("Required argument 'process' not set or invalid for paragraphs_process_on_value plugin"); + } + $source_value = $row->getSourceProperty($this->configuration['source_value']); + if (is_null($source_value)) { + throw new MigrateSkipRowException('Argument source_value is not valid for ProcessOnValue plugin'); + } + if ($source_value == $this->configuration['expected_value']) { + $process = $this->configuration['process']; + + if (array_key_exists('plugin', $process)) { + if (empty($process['source'])) { + $process['source'] = $destination_property; + } + } + else { + if (empty($process[0]['source'])) { + $process[0]['source'] = $destination_property; + } + } + $source = $row->getSource(); + $source[$destination_property] = $value; + $new_row = new Row($source, []); + $migrate_executable->processRow($new_row, [$destination_property => $process]); + return $new_row->getDestinationProperty($destination_property); + } + else { + return $value; + } + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return [ + 'source_value' => '', + 'expected_value' => '', + 'process' => [], + ] + parent::defaultConfiguration(); + } + +} diff --git a/src/Plugin/migrate/process/ProcessPluginBase.php b/src/Plugin/migrate/process/ProcessPluginBase.php new file mode 100644 index 0000000..172c6fe --- /dev/null +++ b/src/Plugin/migrate/process/ProcessPluginBase.php @@ -0,0 +1,72 @@ +entityTypeBundleInfo = $entity_type_bundle_info; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.bundle.info') + ); + } + + /** + * {@inheritdoc} + */ + public function getConfiguration() { + return $this->configuration; + } + + /** + * {@inheritdoc} + */ + public function setConfiguration(array $configuration) { + return NestedArray::mergeDeep($this->defaultConfiguration(), $configuration); + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return []; + } + + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + return []; + } + +} diff --git a/tests/src/Kernel/ParagraphsMigrationTest.php b/tests/src/Kernel/ParagraphsMigrationTest.php index 17c401c..109d96a 100644 --- a/tests/src/Kernel/ParagraphsMigrationTest.php +++ b/tests/src/Kernel/ParagraphsMigrationTest.php @@ -2,6 +2,13 @@ namespace Drupal\Tests\paragraphs\Kernel; +use Drupal\Core\Entity\Entity\EntityFormDisplay; +use Drupal\Core\Entity\Entity\EntityViewDisplay; +use Drupal\Core\Entity\Entity\EntityViewMode; +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; +use Drupal\migrate\Plugin\MigrationInterface; +use Drupal\node\Entity\Node; use Drupal\paragraphs\Entity\ParagraphsType; use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase; @@ -15,18 +22,34 @@ class ParagraphsMigrationTest extends MigrateDrupalTestBase { /** * {@inheritdoc} */ - public static $modules = ['paragraphs', 'user', 'system', 'field']; + public static $modules = [ + 'comment', + 'datetime', + 'datetime_range', + 'entity_reference_revisions', + 'field', + 'file', + 'image', + 'link', + 'menu_ui', + 'migrate_drupal', + 'node', + 'options', + 'paragraphs', + 'system', + 'taxonomy', + 'telephone', + 'text', + 'user', + ]; /** * {@inheritdoc} */ public function setUp() { parent::setUp(); - $this->loadFixture(__DIR__ . '/../../fixtures/drupal7.php'); - $this->executeMigration('d7_field_collection_type'); - $this->executeMigration('d7_paragraphs_type'); } /** @@ -44,12 +67,246 @@ class ParagraphsMigrationTest extends MigrateDrupalTestBase { } /** - * Test if the field collection type was brought over as a paragraph. + * Check if a field storage config entity was created for the paragraph. + * + * @param string $field_name + * The field to test for. + * @param string $field_type + * The expected field type. + */ + protected function assertParagraphEntityFieldExists($field_name, $field_type) { + $field_storage = FieldStorageConfig::loadByName('paragraph', $field_name); + $this->assertNotNull($field_storage); + $this->assertEquals($field_type, $field_storage->getType()); + } + + /** + * Check if a field storage entity was created for the paragraph fields. + * + * @param string $entity_type + * The entity type to check on. + * @param string $field_name + * The field name to check for. + */ + protected function assertParagraphFieldExists($entity_type, $field_name) { + $field_storage = FieldStorageConfig::loadByName($entity_type, $field_name); + $this->assertNotNull($field_storage); + $this->assertEquals('entity_reference_revisions', $field_storage->getType()); + $this->assertEquals('paragraph', $field_storage->getSetting('target_type')); + } + + /** + * Test if the given field instance was created. + */ + protected function assertFieldInstanceExists($entity_type, $bundle, $field_name, $field_type = 'entity_reference_revisions') { + $field = FieldConfig::loadByName($entity_type, $bundle, $field_name); + $this->assertNotNull($field); + $this->assertEquals($field_type, $field->getType()); + } + + /** + * Execute a migration's dependencies followed by the migration. + * + * @param string $plugin_id + * The migration id to execute. */ - public function testFieldCollectionTypeMigration() { + protected function executeMigrationWithDependencies($plugin_id) { + /** @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface $manager */ + $manager = $this->container->get('plugin.manager.migration'); + $migrations = $manager->createInstances($plugin_id); + foreach ($migrations as $migration) { + $this->executeMigrationDependencies($migration); + $this->executeMigration($migration); + } + } + + /** + * Find and execute a migration's dependencies. + * + * @param \Drupal\migrate\Plugin\MigrationInterface $migration + * The Migration from which to execute dependencies. + */ + protected function executeMigrationDependencies(MigrationInterface $migration) { + $dependencies = $migration->getMigrationDependencies(); + foreach ($dependencies['required'] as $dependency) { + $plugin = $this->getMigration($dependency); + if (!$plugin->allRowsProcessed()) { + $this->executeMigrationDependencies($plugin); + $this->executeMigration($plugin); + } + } + foreach ($dependencies['optional'] as $dependency) { + if ($plugin = $this->getMigration($dependency)) { + if (!$plugin->allRowsProcessed()) { + $this->executeMigrationDependencies($plugin); + $this->executeMigration($plugin); + } + } + } + } + + /** + * {@inheritdoc} + */ + protected function prepareMigration(MigrationInterface $migration) { + + // We want to run the revision migraiton without running all the node + // migrations. + if ($migration->id() == 'd7_node_revision:paragraphs_test') { + $migration->set('migration_dependencies', [ + 'required' => ['d7_node:paragraphs_test'], + 'optional' => [], + ]); + $migration->set('requirements', ['d7_node:paragraphs_test' => 'd7_node:paragraphs_test']); + + } + } + + /** + * Test if the paragraph/fc types were brought over as a paragraph. + */ + public function testParagraphsTypeMigration() { + $this->executeMigration('d7_field_collection_type'); + $this->executeMigration('d7_paragraphs_type'); + $this->assertParagraphBundleExists('field_collection_test', 'Field collection test'); $this->assertParagraphBundleExists('paragraph_bundle_one', 'Paragraph Bundle One'); $this->assertParagraphBundleExists('paragraph_bundle_two', 'Paragraph Bundle Two'); } + /** + * Test that the paragraph and field collection field storage was migrated. + */ + public function testParagraphsFieldMigration() { + $this->executeMigration('d7_field'); + + $this->assertParagraphEntityFieldExists('field_email', 'email'); + $this->assertParagraphEntityFieldExists('field_text', 'string'); + $this->assertParagraphEntityFieldExists('field_text_list', 'list_string'); + $this->assertParagraphEntityFieldExists('field_integer_list', 'list_integer'); + + $this->assertParagraphFieldExists('node', 'field_any_paragraph'); + $this->assertParagraphFieldExists('node', 'field_paragraph_one_only'); + $this->assertParagraphFieldExists('node', 'field_field_collection_test'); + } + + /** + * Test if the paragraph field instances were migrated. + */ + public function testParagrahsFieldInstanceMigration() { + + $this->executeMigrationWithDependencies('d7_field_instance'); + + $total_bundles = count(ParagraphsType::loadMultiple()); + + $bundles_from_field_collections = count($this->getMigration('d7_field_collection_type')->getSourcePlugin()); + + $this->assertFieldInstanceExists('node', 'paragraphs_test', 'field_field_collection_test'); + $field = FieldConfig::loadByName('node', 'paragraphs_test', 'field_field_collection_test'); + + $handler_settings = $field->getSetting('handler_settings'); + $this->assertEquals(0, $handler_settings['negate']); + $this->assertCount(1, $handler_settings['target_bundles']); + $this->assertEquals('field_collection_test', $handler_settings['target_bundles']['field_collection_test']); + $this->assertCount($total_bundles, $handler_settings['target_bundles_drag_drop']); + + $this->assertFieldInstanceExists('node', 'paragraphs_test', 'field_any_paragraph'); + $field = FieldConfig::loadByName('node', 'paragraphs_test', 'field_any_paragraph'); + $handler_settings = $field->getSetting('handler_settings'); + $this->assertEquals(1, $handler_settings['negate']); + $this->assertCount($bundles_from_field_collections, $handler_settings['target_bundles']); + $this->assertEquals('field_collection_test', $handler_settings['target_bundles']['field_collection_test']); + $this->assertCount($total_bundles, $handler_settings['target_bundles_drag_drop']); + + $this->assertFieldInstanceExists('node', 'paragraphs_test', 'field_paragraph_one_only'); + $field = FieldConfig::loadByName('node', 'paragraphs_test', 'field_paragraph_one_only'); + $handler_settings = $field->getSetting('handler_settings'); + $this->assertEquals(0, $handler_settings['negate']); + $this->assertCount(1, $handler_settings['target_bundles']); + $this->assertEquals('paragraph_bundle_one', $handler_settings['target_bundles']['paragraph_bundle_one']); + $this->assertCount($total_bundles, $handler_settings['target_bundles_drag_drop']); + + $this->assertFieldInstanceExists('paragraph', 'paragraph_bundle_one', 'field_text', 'string'); + $this->assertFieldInstanceExists('paragraph', 'paragraph_bundle_one', 'field_text_list', 'list_string'); + $this->assertFieldInstanceExists('paragraph', 'paragraph_bundle_two', 'field_text', 'string'); + $this->assertFieldInstanceExists('paragraph', 'paragraph_bundle_two', 'field_email', 'email'); + $this->assertFieldInstanceExists('paragraph', 'field_collection_test', 'field_text', 'string'); + $this->assertFieldInstanceExists('paragraph', 'field_collection_test', 'field_integer_list', 'list_integer'); + + } + + /** + * Test Paragraph widget Migration. + */ + public function testParagraphsWidgets() { + + $this->executeMigrationWithDependencies('d7_field_instance_widget_settings'); + + $formDisplay = EntityFormDisplay::load('node.paragraphs_test.default'); + $this->assertNotNull($formDisplay); + $field_any_paragraph = $formDisplay->getComponent('field_any_paragraph'); + $field_collection_test = $formDisplay->getComponent('field_field_collection_test'); + $field_paragraph_one_only = $formDisplay->getComponent('field_paragraph_one_only'); + $this->assertNotNull($field_any_paragraph); + $this->assertNotNull($field_collection_test); + $this->assertNotNull($field_paragraph_one_only); + $this->assertEquals('button', $field_any_paragraph['settings']['add_mode']); + $this->assertEquals('Any Paragraph', $field_any_paragraph['settings']['title']); + $this->assertEquals('Any Paragraphs', $field_any_paragraph['settings']['title_plural']); + $this->assertEquals('closed', $field_any_paragraph['settings']['edit_mode']); + } + + /** + * Test Paragraph Formatter Migration. + */ + public function testParagraphFormatters() { + + $this->executeMigrationWithDependencies('d7_field_formatter_settings'); + + $full = EntityViewMode::load('paragraph.full'); + $this->assertNotNull($full); + + $editor_preview = EntityViewMode::load('paragraph.paragraphs_editor_preview'); + $this->assertNotNull($editor_preview); + + $viewDisplay = EntityViewDisplay::load('node.paragraphs_test.default'); + $this->assertNotNull($viewDisplay); + $field_any_paragraph = $viewDisplay->getComponent('field_any_paragraph'); + $field_collection_test = $viewDisplay->getComponent('field_field_collection_test'); + $field_paragraph_one_only = $viewDisplay->getComponent('field_paragraph_one_only'); + $this->assertNotNull($field_any_paragraph); + $this->assertNotNull($field_collection_test); + $this->assertNull($field_paragraph_one_only); + $this->assertEquals('paragraphs_editor_preview', $field_any_paragraph['settings']['view_mode']); + } + + /** + * Test migrating the paragraph content. + */ + public function testParagraphContentMigration() { + $this->installEntitySchema('file'); + $this->installEntitySchema('node'); + $this->installEntitySchema('paragraph'); + $this->installEntitySchema('comment'); + $this->installSchema('comment', [ + 'comment_entity_statistics', + ]); + + $this->executeMigrationWithDependencies('d7_field_collection_revisions'); + $this->executeMigrationWithDependencies('d7_paragraphs_revisions'); + $this->executeMigrationWithDependencies('d7_node:paragraphs_test'); + + $this->prepareMigrations([ + 'd7_node:article' => [], + 'd7_node:forum' => [], + 'd7_node:test_content_type' => [], + ]); + + $this->executeMigration('d7_node_revision:paragraphs_test'); + + $node_8 = Node::load(8); + $this->assertEquals('Field Collection Text Data One UND', $node_8->field_field_collection_test->referencedEntities()[0]->field_text->value); + $this->assertEquals('Paragraph Field Two Bundle One Revision Two UND', $node_8->field_paragraph_one_only->referencedEntities()[0]->field_text->value); + } + } diff --git a/tests/src/Unit/migrate/FieldCollectionFieldSettingsTest.php b/tests/src/Unit/migrate/FieldCollectionFieldSettingsTest.php new file mode 100644 index 0000000..20248a1 --- /dev/null +++ b/tests/src/Unit/migrate/FieldCollectionFieldSettingsTest.php @@ -0,0 +1,61 @@ +plugin = new FieldCollectionFieldSettings([], 'field_collection_field_settings', []); + parent::setUp(); + + } + + /** + * Test setting target_type for paragraphs fields. + */ + public function testParagraphsFieldSettings() { + $this->row->expects($this->any()) + ->method('getSourceProperty') + ->with('type') + ->willReturn('field_collection'); + $value = $this->plugin->transform([], $this->migrateExecutable, $this->row, 'settings'); + $this->assertArrayEquals(['target_type' => 'paragraph'], $value); + } + + /** + * Test leaving target_type empty for non-field_collection fields. + */ + public function testNonParagraphFieldSettings() { + $this->row->expects($this->any()) + ->method('getSourceProperty') + ->with('type') + ->willReturn('something_else'); + $value = $this->plugin->transform([], $this->migrateExecutable, $this->row, 'settings'); + $this->assertEmpty($value); + } + + /** + * Test leaving target_type alone for other field types that may have set it. + */ + public function testTaxonomyParagraphFieldSettings() { + $this->row->expects($this->any()) + ->method('getSourceProperty') + ->with('type') + ->willReturn('taxonomy_term'); + $value = $this->plugin->transform(['target_type' => 'some_preset_vaue'], $this->migrateExecutable, $this->row, 'settings'); + $this->assertArrayEquals(['target_type' => 'some_preset_vaue'], $value); + } + +} diff --git a/tests/src/Unit/migrate/FieldCollectionsFieldInstanceSettingsTest.php b/tests/src/Unit/migrate/FieldCollectionsFieldInstanceSettingsTest.php new file mode 100644 index 0000000..1e9bcc8 --- /dev/null +++ b/tests/src/Unit/migrate/FieldCollectionsFieldInstanceSettingsTest.php @@ -0,0 +1,112 @@ +plugin = new FieldCollectionFieldInstanceSettings([], 'field_collection_field_instance_settings', [], $this->entityTypeBundleInfo); + + } + + /** + * Test settings for field_collection field instances. + * + * @param array $source + * The data source. + * @param array $expected + * The expected result. + * + * @dataProvider getData + */ + public function testFieldCollectionInstanceFieldSettings(array $source, array $expected) { + + $this->row->expects($this->any()) + ->method('getSourceProperty') + ->willReturnMap([ + ['type', 'field_collection'], + ['field_name', 'field_field_collection_bundle_one'], + ]); + $value = $this->plugin->transform($source, $this->migrateExecutable, $this->row, 'settings'); + + $this->assertArrayEquals($expected, $value); + } + + /** + * Test that unexpected bundles trigger an exception. + */ + public function testFieldCollectionBadBundle() { + $this->row->expects($this->any()) + ->method('getSourceProperty') + ->willReturnMap([ + ['type', 'field_collection'], + ['bundle', 'non_existent_bundle'], + ]); + $this->setExpectedException(MigrateSkipRowException::class, 'No target paragraph bundle found for field_collection'); + $this->plugin->transform([], $this->migrateExecutable, $this->row, 'settings'); + } + + /** + * Data provider for unit test. + * + * @return array + * The source data and expected data. + */ + public function getData() { + $data = [ + [ + 'source_data' => [], + 'expected_results' => [ + 'handler_settings' => [ + 'negate' => 0, + 'target_bundles' => [ + 'field_collection_bundle_one' => 'field_collection_bundle_one', + ], + 'target_bundles_drag_drop' => [ + 'field_collection_bundle_one' => [ + 'enabled' => TRUE, + 'weight' => -6, + ], + 'paragraph_bundle_one' => [ + 'enabled' => FALSE, + 'weight' => -5, + ], + 'paragraph_bundle_two' => [ + 'enabled' => FALSE, + 'weight' => -4, + ], + 'field_collection_bundle_two' => [ + 'enabled' => FALSE, + 'weight' => -3, + ], + 'prexisting_bundle_one' => [ + 'enabled' => FALSE, + 'weight' => -2, + ], + 'prexisting_bundle_two' => [ + 'enabled' => FALSE, + 'weight' => -1, + ], + ], + ], + ], + ], + ]; + return $data; + } + +} diff --git a/tests/src/Unit/migrate/ParagraphsFieldInstanceSettingsTest.php b/tests/src/Unit/migrate/ParagraphsFieldInstanceSettingsTest.php new file mode 100644 index 0000000..a543d7f --- /dev/null +++ b/tests/src/Unit/migrate/ParagraphsFieldInstanceSettingsTest.php @@ -0,0 +1,103 @@ +row->expects($this->any()) + ->method('getSourceProperty') + ->with('type') + ->willReturn('paragraphs'); + $this->plugin = new ParagraphsFieldInstanceSettings([], 'paragraphs_field_instance_settings', [], $this->entityTypeBundleInfo); + + } + + /** + * Test settings for paragraphs field instances. + * + * @param array $source + * The data source. + * @param array $expected + * The expected result. + * + * @dataProvider getData + */ + public function testParagraphsInstanceFieldSettings(array $source, array $expected) { + + $value = $this->plugin->transform($source, $this->migrateExecutable, $this->row, 'settings'); + + $this->assertArrayEquals($expected, $value); + } + + /** + * Data provider for unit test. + * + * @return array + * The source data and expected data. + */ + public function getData() { + $data = [ + [ + 'source_data' => [ + 'allowed_bundles' => [ + 'paragraph_bundle_one' => 'paragraph_bundle_one', + 'paragraph_bundle_two' => -1, + ], + 'bundle_weights' => [ + 'paragraph_bundle_one' => 1, + 'paragraph_bundle_two' => 2, + ], + ], + 'expected_results' => [ + 'handler_settings' => [ + 'negate' => 0, + 'target_bundles' => [ + 'paragraph_bundle_one' => 'paragraph_bundle_one', + ], + 'target_bundles_drag_drop' => [ + 'paragraph_bundle_one' => [ + 'enabled' => TRUE, + 'weight' => 1, + ], + 'paragraph_bundle_two' => [ + 'enabled' => FALSE, + 'weight' => 2, + ], + 'field_collection_bundle_one' => [ + 'enabled' => FALSE, + 'weight' => 3, + ], + 'field_collection_bundle_two' => [ + 'enabled' => FALSE, + 'weight' => 3, + ], + 'prexisting_bundle_one' => [ + 'enabled' => FALSE, + 'weight' => 3, + ], + 'prexisting_bundle_two' => [ + 'enabled' => FALSE, + 'weight' => 3, + ], + ], + ], + ], + ], + ]; + return $data; + } + +} diff --git a/tests/src/Unit/migrate/ParagraphsFieldSettingsTest.php b/tests/src/Unit/migrate/ParagraphsFieldSettingsTest.php new file mode 100644 index 0000000..2c8e84f --- /dev/null +++ b/tests/src/Unit/migrate/ParagraphsFieldSettingsTest.php @@ -0,0 +1,61 @@ +plugin = new ParagraphsFieldSettings([], 'paragraphs_field_settings', []); + parent::setUp(); + + } + + /** + * Test setting target_type for paragraphs fields. + */ + public function testParagraphsFieldSettings() { + $this->row->expects($this->any()) + ->method('getSourceProperty') + ->with('type') + ->willReturn('paragraphs'); + $value = $this->plugin->transform([], $this->migrateExecutable, $this->row, 'settings'); + $this->assertArrayEquals(['target_type' => 'paragraph'], $value); + } + + /** + * Test leaving target_type empty for non-paragraphs fields. + */ + public function testNonParagraphFieldSettings() { + $this->row->expects($this->any()) + ->method('getSourceProperty') + ->with('type') + ->willReturn('something_else'); + $value = $this->plugin->transform([], $this->migrateExecutable, $this->row, 'settings'); + $this->assertEmpty($value); + } + + /** + * Test leaving target_type alone for other field types that may have set it. + */ + public function testTaxonomyParagraphFieldSettings() { + $this->row->expects($this->any()) + ->method('getSourceProperty') + ->with('type') + ->willReturn('taxonomy_term'); + $value = $this->plugin->transform(['target_type' => 'some_preset_vaue'], $this->migrateExecutable, $this->row, 'settings'); + $this->assertArrayEquals(['target_type' => 'some_preset_vaue'], $value); + } + +} diff --git a/tests/src/Unit/migrate/ParagraphsProcessOnValueTest.php b/tests/src/Unit/migrate/ParagraphsProcessOnValueTest.php new file mode 100644 index 0000000..c016690 --- /dev/null +++ b/tests/src/Unit/migrate/ParagraphsProcessOnValueTest.php @@ -0,0 +1,96 @@ + 'test', + ]; + + /** + * {@inheritdoc} + */ + public function setup() { + parent::setup(); + $configuration = [ + 'source_value' => 'source', + 'expected_value' => 'expected', + 'process' => [ + 'plugin' => 'get', + 'source' => 'theValue', + ], + ]; + $this->plugin = new ParagraphsProcessOnValue($configuration, 'paragraphs_process_on_value', [], $this->entityTypeBundleInfo); + $this->row + ->expects($this->any()) + ->method('getSource') + ->willReturn([ + 'theValue' => 'Final Value', + 'source' => 'expected', + ]); + + } + + /** + * Test processing if conditions are met. + */ + public function testProcess() { + $migration = $this->getMigration(); + $get = new Get(['source' => 'theValue'], 'get', []); + $migration->expects($this->any()) + ->method('getProcessPlugins') + ->willReturn(['destination' => [$get]]); + + $this->row + ->expects($this->any()) + ->method('getSourceProperty') + ->with('source') + ->willReturn('expected'); + $event_dispatcher = $this->createMock(EventDispatcherInterface::class); + $message = $this->createMock(MigrateMessageInterface::class); + $migrate_executable = new MigrateExecutable($migration, $message, $event_dispatcher); + $value = $this->plugin->transform('Initial Value', $migrate_executable, $this->row, 'destination'); + $this->assertEquals('Final Value', $value); + + } + + /** + * Test not processing if conditions are not met. + */ + public function testSkip() { + $migration = $this->getMigration(); + $get = new Get(['source' => 'theValue'], 'get', []); + $migration->expects($this->any()) + ->method('getProcessPlugins') + ->willReturn(['destination' => [$get]]); + + $this->row + ->expects($this->any()) + ->method('getSourceProperty') + ->with('source') + ->willReturn('unexpected'); + $event_dispatcher = $this->createMock(EventDispatcherInterface::class); + $message = $this->createMock(MigrateMessageInterface::class); + $migrate_executable = new MigrateExecutable($migration, $message, $event_dispatcher); + $value = $this->plugin->transform('Initial Value', $migrate_executable, $this->row, 'destination'); + $this->assertEquals('Initial Value', $value); + + } + +} diff --git a/tests/src/Unit/migrate/ProcessTestCase.php b/tests/src/Unit/migrate/ProcessTestCase.php new file mode 100644 index 0000000..c2fe37d --- /dev/null +++ b/tests/src/Unit/migrate/ProcessTestCase.php @@ -0,0 +1,45 @@ +entityTypeBundleInfo = $this->getMockBuilder(EntityTypeBundleInfo::class) + ->disableOriginalConstructor() + ->getMock(); + $bundles = [ + 'paragraph_bundle_one' => [], + 'paragraph_bundle_two' => [], + 'field_collection_bundle_one' => [], + 'field_collection_bundle_two' => [], + 'prexisting_bundle_one' => [], + 'prexisting_bundle_two' => [], + ]; + $this->entityTypeBundleInfo + ->expects($this->any()) + ->method('getBundleInfo') + ->with('paragraph') + ->willReturn($bundles); + + } + +}