Commit 485d7b7f authored by Damien McKenna's avatar Damien McKenna
Browse files

Issue #3045641 by DamienMcKenna, heddn, mikelutz: Migrations: Nodewords-D6 per-entity data.

parent ed42fc03
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ Metatag 8.x-1.x-dev, xxxx-xx-xx
#3113481 by thalles: Fix subclassing and stop overriding constructors in
  metatag_views\Plugin\views\display_extender\MetatagDisplayExtender.
By DamienMcKenna: Minor code readability tweak.
#3045641 by DamienMcKenna, heddn, mikelutz: Migrations: Nodewords-D6 per-entity
  data.


Metatag 8.x-1.11, 2019-12-20
+36 −17
Original line number Diff line number Diff line
@@ -237,40 +237,59 @@ type of meta tag, e.g. the generator meta tag uses the "content" attribute while
the link tag uses the "href" attribute.


Migration / Upgrade from Drupal 7
Migration / Upgrade from Drupal 6 or 7
--------------------------------------------------------------------------------
An upgrade path from Metatag on Drupal 7 is provided.
An upgrade path from Nodewords on Drupal 6 or Metatag on Drupal 7 is provided.

Two migration processes are supported:

 1. A guided migration using either the Migrate Drupal UI from core or the
    Migrate Upgrade [2] contributed module. This will automatically create a
    field named "field_metatag" and import any meta tag data that existed in D7.
    field named "field_metatag" and import any meta tag data that existed in
    Nodewords on D6 or Metatag on D7.

    This is set up in metatag_migration_plugins_alter() and then leverages code
    in metatag_migrate_prepare_row() and
    \Drupal\metatag\Plugin\migrate\process\d7\MetatagEntities to do the actual
    data migration.
    This migration configuration is all prepared in
    metatag_migration_plugins_alter(), the data is loaded onto the migrated
    entity in metatag_migrate_prepare_row(), and then the data is remapped in
    either \Drupal\metatag\Plugin\migrate\process\d6\NodewordsEntities or
    \Drupal\metatag\Plugin\migrate\process\d7\MetatagEntities depending upon
    what the source is.

 2. A custom migration using Migrate Plus [3] and possibly Migrate Tools [4].
    This will require manually creating the meta tag fields and assigning a
    custom process plugin as the source for its data. For example, if the name
    of the field is "field_meta_tags" the lines fron the "process" section of
    the migration yml file will look line the following:
    the migration yml file would need to look line the following:

.......................................
    For migrating from Nodewords on D6:
--------------------------------------------------------------------
process:
  field_metatag:
...
  field_meta_tags:
    plugin: d6_nodewords_entities
    source: pseudo_metatag_entities
...
--------------------------------------------------------------------

    For Migrating from Metatag on D7:
--------------------------------------------------------------------
process:
...
  field_meta_tags:
    plugin: d7_metatag_entities
    source: pseudo_d7_metatag_entities
.......................................
    source: pseudo_metatag_entities
...
--------------------------------------------------------------------

    The important items are the "plugin" and the "source" values, if these are
    not present the migration will not work as expected.

    The important items are the plugin "d7_metatag_entities" and the source
    value of "pseudo_d7_metatag_entities", if these are not present the
    migration will not work as expected.
    The data will then be loaded into the migrating entity using
    metatag_migrate_prepare_row().

    This is handled by metatag_migrate_prepare_row() and
    \Drupal\metatag\Plugin\migrate\process\d7\MetatagEntities.
    See also:
    * \Drupal\metatag\Plugin\migrate\process\d6\NodewordsEntities
    * \Drupal\metatag\Plugin\migrate\process\d7\MetatagEntities


DrupalConsole integration
+154 −73
Original line number Diff line number Diff line
@@ -8,9 +8,9 @@
use Drupal\Component\Plugin\Factory\DefaultFactory;
use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
@@ -19,10 +19,13 @@ use Drupal\migrate\Plugin\migrate\destination\EntityContentBase;
use Drupal\migrate\Plugin\MigrateSourceInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Row;
use Drupal\node\Plugin\migrate\source\d7\Node;
use Drupal\taxonomy\Plugin\migrate\source\d7\Term;
use Drupal\node\Plugin\migrate\source\d6\Node as Node6;
use Drupal\node\Plugin\migrate\source\d7\Node as Node7;
use Drupal\taxonomy\Plugin\migrate\source\d6\Term as Term6;
use Drupal\taxonomy\Plugin\migrate\source\d7\Term as Term7;
use Drupal\taxonomy\TermInterface;
use Drupal\user\Plugin\migrate\source\d7\User;
use Drupal\user\Plugin\migrate\source\d6\User as User6;
use Drupal\user\Plugin\migrate\source\d7\User as User7;

/**
 * Implements hook_help().
@@ -650,24 +653,25 @@ function metatag_generate_entity_metatags($entity) {
 * Implements hook_migrate_prepare_row().
 */
function metatag_migrate_prepare_row(Row $row, MigrateSourceInterface $source, MigrationInterface $migration) {
  // If there's no 'metatag' table in the source, there's no point in
  // continuing.
  if (!method_exists($source, 'getDatabase')
      || !$source->getDatabase()->schema()->tableExists('metatag')) {
  // Don't bother if there source doesn't allow the getDatabase() method.
  if (!method_exists($source, 'getDatabase')) {
    return;
  }

  // Work out what sort of migration to do.
  // Metatag-D7.
  if ($source->getDatabase()->schema()->tableExists('metatag')) {
    // @todo Write a more general version rather than hard-coded.
    // Support a know subset of D7 sources.
  if (is_a($source, Node::class)) {
    if (is_a($source, Node7::class)) {
      // E.g. d7_node, d7_node_revision.
      $source_type = 'node';
    }
  elseif (is_a($source, Term::class)) {
    elseif (is_a($source, Term7::class)) {
      // E.g. d7_taxonomy_term.
      $source_type = 'taxonomy';
    }
  elseif (is_a($source, User::class)) {
    elseif (is_a($source, User7::class)) {
      // E.g. d7_user.
      $source_type = 'user';
    }
@@ -716,7 +720,78 @@ function metatag_migrate_prepare_row(Row $row, MigrateSourceInterface $source, M
        $value = array_pop($value);
      }

    $row->setSourceProperty('pseudo_d7_metatag_entities', $value);
      $row->setSourceProperty('pseudo_metatag_entities', $value);
    }
  }

  // Nodewords-D6.
  elseif ($source->getDatabase()->schema()->tableExists('nodewords')) {
    // @todo Write a more general version rather than hard-coded.
    // Support a know subset of D6 sources.
    if (is_a($source, Node6::class)) {
      // E.g. d6_node, d6_node_revision.
      $source_type = 'node';
    }
    elseif (is_a($source, Term6::class)) {
      // E.g. d6_taxonomy_term.
      $source_type = 'taxonomy_term';
    }
    elseif (is_a($source, User6::class)) {
      // E.g. d6_user.
      $source_type = 'user';
    }
    else {
      // Not supported now, nothing to do.
      return;
    }

    if ($migration->getDestinationPlugin() instanceof EntityContentBase) {
      $nodeword_type = $entity_id = NULL;

      // @todo Write a more general version rather than a switch statement.
      switch ($source_type) {
        case 'node':
          // define('NODEWORDS_TYPE_NODE',       5);
          $nodeword_type = 5;
          $entity_id = $row->getSourceProperty('nid');
          break;

        case 'taxonomy_term':
          // define('NODEWORDS_TYPE_TERM',       6);
          $nodeword_type = 6;
          $entity_id = $row->getSourceProperty('tid');
          break;

        case 'user':
          // define('NODEWORDS_TYPE_USER',       8);
          $nodeword_type = 8;
          $entity_id = $row->getSourceProperty('uid');
          break;
      }
      // @todo
      // define('NODEWORDS_TYPE_BLOG',       13);
      // define('NODEWORDS_TYPE_DEFAULT',    1);
      // define('NODEWORDS_TYPE_ERRORPAGE',  2);
      // define('NODEWORDS_TYPE_FORUM',      12);
      // define('NODEWORDS_TYPE_FRONTPAGE',  3);
      // define('NODEWORDS_TYPE_NONE',       0);
      // define('NODEWORDS_TYPE_OFFLINE',    11);
      // define('NODEWORDS_TYPE_PAGE',       10);
      // define('NODEWORDS_TYPE_PAGER',      4);
      // define('NODEWORDS_TYPE_TRACKER',    7);
      // define('NODEWORDS_TYPE_VOCABULARY', 9);

      /** @var \Drupal\migrate\Plugin\migrate\source\SqlBase $source */
      /** @var \Drupal\Core\Database\Query\SelectInterface $query */
      $query = $source->getDatabase()->select('nodewords', 'nw')
        ->fields('nw', ['name', 'content'])
        ->condition('type', $nodeword_type)
        ->condition('id', $entity_id)
        ->orderBy('nw.name');
      $value = $query->execute()->fetchAllKeyed();

      $row->setSourceProperty('pseudo_metatag_entities',  $value);
    }
  }
}

@@ -738,20 +813,26 @@ function metatag_migration_plugins_alter(array &$definitions) {
  foreach ($definitions as &$definition) {
    // Only certain migrate plugins are supported.
    if (_metatag_is_migration_plugin_supported($definition)) {
      // Metatag-D7's data is handled via a custom process plugin that does
      // the data conversion.
      // There are different field and process plugins for D6 and D7 too.
      if (in_array('Drupal 6', $definition['migration_tags'], TRUE)) {
        $definition['process']['field_metatag'] = [
          'plugin' => 'd6_nodewords_entities',
          'source' => 'pseudo_metatag_entities',
        ];
        $definition['migration_dependencies']['optional'][] = 'd6_nodewords_field';
        $definition['migration_dependencies']['optional'][] = 'd6_nodewords_field_instance';
      }
      if (in_array('Drupal 7', $definition['migration_tags'], TRUE)) {
        $definition['process']['field_metatag'] = [
          'plugin' => 'd7_metatag_entities',
        'source' => 'pseudo_d7_metatag_entities',
          'source' => 'pseudo_metatag_entities',
        ];

      // List dependencies here so that they are processed first, otherwise
      // the destination field won't be available for the data to go into.
        $definition['migration_dependencies']['optional'][] = 'd7_metatag_field';
        $definition['migration_dependencies']['optional'][] = 'd7_metatag_field_instance';
      }
    }
  }
}

/**
 * Check if a given migrate plugin should have Metatag's logic added.
@@ -770,7 +851,7 @@ function _metatag_is_migration_plugin_supported(array $definition) {
  // will catch standard core migrations but allow skipping this log for custom
  // migrations that do not have this tag.
  if (!empty($definition['migration_tags'])) {
    if (!in_array('Drupal 7', $definition['migration_tags'])) {
    if (!array_intersect(['Drupal 6', 'Drupal 7'], $definition['migration_tags'])) {
      return FALSE;
    }
  }
@@ -820,7 +901,7 @@ function _metatag_is_migration_plugin_supported(array $definition) {
  $plugin_definition = \Drupal::service('plugin.manager.migrate.destination')
    ->getDefinition($definition['destination']['plugin']);
  $destination_plugin = DefaultFactory::getPluginClass($definition['destination']['plugin'], $plugin_definition);
  if (!is_subclass_of($destination_plugin, EntityContentBase::class) && $destination_plugin != EntityContentBase::class) {
  if (!is_subclass_of($destination_plugin, EntityContentBase::class) && $destination_plugin !== EntityContentBase::class) {
    return FALSE;
  }

+25 −0
Original line number Diff line number Diff line
# A default migration mapping for Metatag-D6 base fields.
#
# @see Drupal\metatag\Plugin\migrate\source\d6\NodewordsField

id: d6_nodewords_field
label: Nodewords field
migration_tags:
  - Drupal 6
source:
  plugin: d6_nodewords_field
  source_module: metatag
  ignore_map: true
  constants:
    field_name: field_metatag
    langcode: und
    type: metatag
    status: true
process:
  entity_type: entity_type
  field_name: 'constants/field_name'
  langcode: 'constants/langcode'
  status: 'constants/status'
  type: 'constants/type'
destination:
  plugin: entity:field_storage_config
+32 −0
Original line number Diff line number Diff line
# A default migration mapping for Metatag-D6 field instances.
#
# @see Drupal\metatag\Plugin\migrate\source\d6\NodewordsFieldInstance

id: d6_nodewords_field_instance
label: Metatag field instance
migration_tags:
  - Drupal 6
source:
  plugin: d6_nodewords_field_instance
  source_module: metatag
  ignore_map: true
  constants:
    field_name: field_metatag
    label: Meta tags
process:
  bundle: bundle
  entity_type: entity_type
  field_name: 'constants/field_name'
  label: 'constants/label'
destination:
  plugin: entity:field_config
migration_dependencies:
  required:
    # The base field migration is required before this migration can run.
    - d6_nodewords_field

    # @todo Is this accurate? Does it really need the vocabulary migration, or
    # is it more precautionary, that it *might* be needed so it might as well be
    # executed first?
    - d6_node_type
    - d6_taxonomy_vocabulary
Loading