diff --git a/core/modules/field/src/Plugin/migrate/source/d7/FieldInstance.php b/core/modules/field/src/Plugin/migrate/source/d7/FieldInstance.php
index 42c628950d1f804214e74216d0ef4862a6e9c884..87853efb52c57a9e90214be59d9592c5531ed86b 100755
--- a/core/modules/field/src/Plugin/migrate/source/d7/FieldInstance.php
+++ b/core/modules/field/src/Plugin/migrate/source/d7/FieldInstance.php
@@ -28,7 +28,9 @@ public function query() {
       ->condition('fci.deleted', 0)
       ->condition('fc.active', 1)
       ->condition('fc.deleted', 0)
-      ->condition('fc.storage_active', 1);
+      ->condition('fc.storage_active', 1)
+      ->fields('fc', array('type'));
+
     $query->innerJoin('field_config', 'fc', 'fci.field_id = fc.id');
 
     // Optionally filter by entity type and bundle.
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/builder/d6/CckBuilder.php b/core/modules/migrate_drupal/src/Plugin/migrate/builder/CckBuilder.php
similarity index 59%
rename from core/modules/migrate_drupal/src/Plugin/migrate/builder/d6/CckBuilder.php
rename to core/modules/migrate_drupal/src/Plugin/migrate/builder/CckBuilder.php
index aa45439d29379ec45547c3327b2b27ea579eb8a7..50b1fcd6dd9b30284b666eccab3a1bef9afb815b 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/builder/d6/CckBuilder.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/builder/CckBuilder.php
@@ -2,12 +2,13 @@
 
 /**
  * @file
- * Contains \Drupal\migrate_drupal\Plugin\migrate\builder\d6\CckBuilder.
+ * Contains \Drupal\migrate_drupal\Plugin\migrate\builder\CckBuilder.
  */
 
-namespace Drupal\migrate_drupal\Plugin\migrate\builder\d6;
+namespace Drupal\migrate_drupal\Plugin\migrate\builder;
 
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\migrate\Entity\MigrationInterface;
 use Drupal\migrate\Plugin\migrate\builder\BuilderBase;
 use Drupal\migrate\Plugin\MigratePluginManager;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -24,6 +25,13 @@ abstract class CckBuilder extends BuilderBase implements ContainerFactoryPluginI
    */
   protected $cckPluginManager;
 
+  /**
+   * Already-instantiated cckfield plugins, keyed by ID.
+   *
+   * @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface[]
+   */
+  protected $cckPluginCache = [];
+
   /**
    * Constructs a CckBuilder.
    *
@@ -53,4 +61,22 @@ public static function create(ContainerInterface $container, array $configuratio
     );
   }
 
+  /**
+   * Gets a cckfield plugin instance.
+   *
+   * @param string $field_type
+   *   The field type (plugin ID).
+   * @param \Drupal\migrate\Entity\MigrationInterface|NULL $migration
+   *   The migration, if any.
+   *
+   * @return \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
+   *   The cckfield plugin instance.
+   */
+  protected function getCckPlugin($field_type, MigrationInterface $migration = NULL) {
+    if (empty($this->cckPluginCache[$field_type])) {
+      $this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($field_type, [], $migration);
+    }
+    return $this->cckPluginCache[$field_type];
+  }
+
 }
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/builder/d6/CckMigration.php b/core/modules/migrate_drupal/src/Plugin/migrate/builder/d6/CckMigration.php
index d63400c250989c95ff266479b90dd77f96385437..e870808a9cabf1b164d1c204d66017643388596e 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/builder/d6/CckMigration.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/builder/d6/CckMigration.php
@@ -8,6 +8,7 @@
 namespace Drupal\migrate_drupal\Plugin\migrate\builder\d6;
 
 use Drupal\migrate\Entity\Migration;
+use Drupal\migrate_drupal\Plugin\migrate\builder\CckBuilder;
 
 /**
  * @PluginID("d6_cck_migration")
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d6/System.php b/core/modules/migrate_drupal/src/Tests/Table/d6/System.php
index d0d9d9b78fa9a87d2d7cb26496d6448e7c4f5d21..f6400ccb6c310392aa3746d5e00e426a3cca39ff 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d6/System.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d6/System.php
@@ -759,6 +759,28 @@ public function load() {
       'schema_version' => '-1',
       'weight' => '0',
       'info' => 'a:10:{s:4:"name";s:14:"FileField Meta";s:11:"description";s:48:"Add metadata gathering and storage to FileField.";s:12:"dependencies";a:2:{i:0;s:9:"filefield";i:1;s:6:"getid3";}s:7:"package";s:3:"CCK";s:4:"core";s:3:"6.x";s:3:"php";s:3:"5.0";s:7:"version";s:8:"6.x-3.11";s:7:"project";s:9:"filefield";s:9:"datestamp";s:10:"1365968724";s:10:"dependents";a:0:{}}',
+    ))->values(array(
+      'filename' => 'sites/all/modules/imageapi/imageapi.module',
+      'name' => 'imageapi',
+      'type' => 'module',
+      'owner' => '',
+      'status' => '1',
+      'throttle' => '0',
+      'bootstrap' => '0',
+      'schema_version' => '0',
+      'weight' => '0',
+      'info' => 'a:10:{s:4:"name";s:8:"ImageAPI";s:11:"description";s:38:"ImageAPI supporting multiple toolkits.";s:7:"package";s:10:"ImageCache";s:4:"core";s:3:"6.x";s:3:"php";s:3:"5.1";s:7:"version";s:8:"6.x-1.10";s:7:"project";s:8:"imageapi";s:9:"datestamp";s:10:"1305563215";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}}',
+    ))->values(array(
+      'filename' => 'sites/all/modules/imagecache/imagecache.module',
+      'name' => 'imagecache',
+      'type' => 'module',
+      'owner' => '',
+      'status' => '1',
+      'throttle' => '0',
+      'bootstrap' => '0',
+      'schema_version' => '6001',
+      'weight' => '0',
+      'info' => 'a:10:{s:4:"name";s:8:"ImageAPI";s:11:"description";s:38:"ImageAPI supporting multiple toolkits.";s:7:"package";s:10:"ImageCache";s:4:"core";s:3:"6.x";s:3:"php";s:3:"5.1";s:7:"version";s:8:"6.x-1.10";s:7:"project";s:8:"imageapi";s:9:"datestamp";s:10:"1305563215";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}}',
     ))->values(array(
       'filename' => 'sites/all/modules/imagefield/imagefield.module',
       'name' => 'imagefield',
@@ -847,28 +869,6 @@ public function load() {
       'schema_version' => '-1',
       'weight' => '0',
       'info' => 'a:10:{s:4:"name";s:8:"Views UI";s:11:"description";s:93:"Administrative interface to views. Without this module, you cannot create or edit your views.";s:7:"package";s:5:"Views";s:4:"core";s:3:"6.x";s:12:"dependencies";a:1:{i:0;s:5:"views";}s:7:"version";s:7:"6.x-3.0";s:7:"project";s:5:"views";s:9:"datestamp";s:10:"1325638545";s:10:"dependents";a:0:{}s:3:"php";s:5:"4.3.5";}',
-    ))->values(array(
-      'filename' => 'sites/all/modules/imageapi/imageapi.module',
-      'name' => 'imageapi',
-      'type' => 'module',
-      'owner' => '',
-      'status' => '1',
-      'throttle' => '0',
-      'bootstrap' => '0',
-      'schema_version' => '0',
-      'weight' => '0',
-      'info' => 'a:10:{s:4:"name";s:8:"ImageAPI";s:11:"description";s:38:"ImageAPI supporting multiple toolkits.";s:7:"package";s:10:"ImageCache";s:4:"core";s:3:"6.x";s:3:"php";s:3:"5.1";s:7:"version";s:8:"6.x-1.10";s:7:"project";s:8:"imageapi";s:9:"datestamp";s:10:"1305563215";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}}',
-    ))->values(array(
-      'filename' => 'sites/all/modules/imagecache/imagecache.module',
-      'name' => 'imagecache',
-      'type' => 'module',
-      'owner' => '',
-      'status' => '1',
-      'throttle' => '0',
-      'bootstrap' => '0',
-      'schema_version' => '6001',
-      'weight' => '0',
-      'info' => 'a:10:{s:4:"name";s:8:"ImageAPI";s:11:"description";s:38:"ImageAPI supporting multiple toolkits.";s:7:"package";s:10:"ImageCache";s:4:"core";s:3:"6.x";s:3:"php";s:3:"5.1";s:7:"version";s:8:"6.x-1.10";s:7:"project";s:8:"imageapi";s:9:"datestamp";s:10:"1305563215";s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}}',
     ))->values(array(
       'filename' => 'themes/bluemarine/bluemarine.info',
       'name' => 'bluemarine',
@@ -939,4 +939,4 @@ public function load() {
   }
 
 }
-#f7d26efda87933cbe199c1f232d329b2
+#67a0176adb132bf6a171a703fa411e49
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d7/FieldDataBody.php b/core/modules/migrate_drupal/src/Tests/Table/d7/FieldDataBody.php
index 301d9d61656e017b0773ce7c6e8b66aa69f5ccea..750bfc78658d8ad572431322f96ec5da3893ae8f 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d7/FieldDataBody.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d7/FieldDataBody.php
@@ -101,8 +101,19 @@ public function load() {
       'body_summary',
       'body_format',
     ))
-    ->execute();
+    ->values(array(
+      'entity_type' => 'node',
+      'bundle' => 'article',
+      'deleted' => '0',
+      'entity_id' => '2',
+      'revision_id' => '2',
+      'language' => 'und',
+      'delta' => '0',
+      'body_value' => "...is that it's the absolute best show ever. Trust me, I would know.",
+      'body_summary' => '',
+      'body_format' => 'filtered_html',
+    ))->execute();
   }
 
 }
-#58f5b8a4637fcf4163189ea05cf087f7
+#7fc3d3e12c126c8ef003d5f5ef2b8837
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d7/FieldDataFieldTags.php b/core/modules/migrate_drupal/src/Tests/Table/d7/FieldDataFieldTags.php
index 7b55a6fc6a0cae599e5970a2410b5d5b49938939..c65f7614c57fdd0eec4356a9c32ae6d78197fed4 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d7/FieldDataFieldTags.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d7/FieldDataFieldTags.php
@@ -90,8 +90,35 @@ public function load() {
       'delta',
       'field_tags_tid',
     ))
-    ->execute();
+    ->values(array(
+      'entity_type' => 'node',
+      'bundle' => 'article',
+      'deleted' => '0',
+      'entity_id' => '2',
+      'revision_id' => '2',
+      'language' => 'und',
+      'delta' => '0',
+      'field_tags_tid' => '9',
+    ))->values(array(
+      'entity_type' => 'node',
+      'bundle' => 'article',
+      'deleted' => '0',
+      'entity_id' => '2',
+      'revision_id' => '2',
+      'language' => 'und',
+      'delta' => '1',
+      'field_tags_tid' => '14',
+    ))->values(array(
+      'entity_type' => 'node',
+      'bundle' => 'article',
+      'deleted' => '0',
+      'entity_id' => '2',
+      'revision_id' => '2',
+      'language' => 'und',
+      'delta' => '2',
+      'field_tags_tid' => '17',
+    ))->execute();
   }
 
 }
-#9e0f85739f8ae8d2c27054edb43f388d
+#b72078545dd0cae56f1c0b4698d064ad
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d7/FieldRevisionBody.php b/core/modules/migrate_drupal/src/Tests/Table/d7/FieldRevisionBody.php
index c6c343bc6573eb09dc1279f0f9728fe3aa890096..82edd649fa6543c14b064d099e1704d151b86580 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d7/FieldRevisionBody.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d7/FieldRevisionBody.php
@@ -102,8 +102,19 @@ public function load() {
       'body_summary',
       'body_format',
     ))
-    ->execute();
+    ->values(array(
+      'entity_type' => 'node',
+      'bundle' => 'article',
+      'deleted' => '0',
+      'entity_id' => '2',
+      'revision_id' => '2',
+      'language' => 'und',
+      'delta' => '0',
+      'body_value' => "...is that it's the absolute best show ever. Trust me, I would know.",
+      'body_summary' => '',
+      'body_format' => 'filtered_html',
+    ))->execute();
   }
 
 }
-#088085ffa6940ff7b87442b920d39de3
+#eb2f8f6fd180db91769e5e2a6d5ff950
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d7/FieldRevisionFieldTags.php b/core/modules/migrate_drupal/src/Tests/Table/d7/FieldRevisionFieldTags.php
index efc5a19e796711dd434b760d7478617b87edf80c..c879ee57ecf9655832dc6641245b0aa749199189 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d7/FieldRevisionFieldTags.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d7/FieldRevisionFieldTags.php
@@ -91,8 +91,35 @@ public function load() {
       'delta',
       'field_tags_tid',
     ))
-    ->execute();
+    ->values(array(
+      'entity_type' => 'node',
+      'bundle' => 'article',
+      'deleted' => '0',
+      'entity_id' => '2',
+      'revision_id' => '2',
+      'language' => 'und',
+      'delta' => '0',
+      'field_tags_tid' => '9',
+    ))->values(array(
+      'entity_type' => 'node',
+      'bundle' => 'article',
+      'deleted' => '0',
+      'entity_id' => '2',
+      'revision_id' => '2',
+      'language' => 'und',
+      'delta' => '1',
+      'field_tags_tid' => '14',
+    ))->values(array(
+      'entity_type' => 'node',
+      'bundle' => 'article',
+      'deleted' => '0',
+      'entity_id' => '2',
+      'revision_id' => '2',
+      'language' => 'und',
+      'delta' => '2',
+      'field_tags_tid' => '17',
+    ))->execute();
   }
 
 }
-#16ce847952ff261838323685dcf2dbc3
+#3e8379dcd102dc753b93a396fa3e553c
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d7/Node.php b/core/modules/migrate_drupal/src/Tests/Table/d7/Node.php
index 306475402fd4b608a1810a1ffd82de98436e39f1..544fcba791551efdd5d9a27d4343d3a748ef7cf7 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d7/Node.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d7/Node.php
@@ -144,8 +144,23 @@ public function load() {
       'sticky' => '0',
       'tnid' => '0',
       'translate' => '0',
+    ))->values(array(
+      'nid' => '2',
+      'vid' => '2',
+      'type' => 'article',
+      'language' => 'en',
+      'title' => 'The thing about Deep Space 9',
+      'uid' => '2',
+      'status' => '1',
+      'created' => '1441306772',
+      'changed' => '1441306832',
+      'comment' => '2',
+      'promote' => '1',
+      'sticky' => '0',
+      'tnid' => '0',
+      'translate' => '0',
     ))->execute();
   }
 
 }
-#06cbcf4df265ff717f83f472c22fdbcf
+#c0239fe20ab594399f7d89ece5d1705f
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d7/NodeRevision.php b/core/modules/migrate_drupal/src/Tests/Table/d7/NodeRevision.php
index d709a8be513bdd53caad77a0b09d523799c2971a..6b1426c5573947b97854c94ab3a59f7b40797b04 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d7/NodeRevision.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d7/NodeRevision.php
@@ -111,8 +111,19 @@ public function load() {
       'comment' => '2',
       'promote' => '1',
       'sticky' => '0',
+    ))->values(array(
+      'nid' => '2',
+      'vid' => '2',
+      'uid' => '1',
+      'title' => 'The thing about Deep Space 9',
+      'log' => '',
+      'timestamp' => '1441306832',
+      'status' => '1',
+      'comment' => '2',
+      'promote' => '1',
+      'sticky' => '0',
     ))->execute();
   }
 
 }
-#e202cc75a51afc39cabf52cbf0a0f9e2
+#e111edf15130b7307ccaffac6f8f9b6f
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d7/TaxonomyIndex.php b/core/modules/migrate_drupal/src/Tests/Table/d7/TaxonomyIndex.php
index aafd3102db171efce275e0c4187e954837a69dc0..4a87d4ca5d7ecfd6db164cbd3a39aac79017c16c 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d7/TaxonomyIndex.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d7/TaxonomyIndex.php
@@ -62,8 +62,23 @@ public function load() {
       'tid' => '4',
       'sticky' => '0',
       'created' => '1421727515',
+    ))->values(array(
+      'nid' => '2',
+      'tid' => '9',
+      'sticky' => '0',
+      'created' => '1441306772',
+    ))->values(array(
+      'nid' => '2',
+      'tid' => '14',
+      'sticky' => '0',
+      'created' => '1441306772',
+    ))->values(array(
+      'nid' => '2',
+      'tid' => '17',
+      'sticky' => '0',
+      'created' => '1441306772',
     ))->execute();
   }
 
 }
-#8204d7c1b294ccb506b5106f410bfa37
+#c5beb19e23b4c7867ff9ea86a4d5b3ac
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d7/TaxonomyTermData.php b/core/modules/migrate_drupal/src/Tests/Table/d7/TaxonomyTermData.php
index 9a5d722316787c1a3f8ece5e02a84fb1a7f17845..3b1dc7f7bbc6fea2ce19b9cc25a4c90e9c942110 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d7/TaxonomyTermData.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d7/TaxonomyTermData.php
@@ -127,8 +127,78 @@ public function load() {
       'description' => '',
       'format' => NULL,
       'weight' => '0',
+    ))->values(array(
+      'tid' => '9',
+      'vid' => '1',
+      'name' => 'Benjamin Sisko',
+      'description' => 'Portrayed by Avery Brooks',
+      'format' => 'filtered_html',
+      'weight' => '0',
+    ))->values(array(
+      'tid' => '10',
+      'vid' => '1',
+      'name' => 'Kira Nerys',
+      'description' => 'Portrayed by Nana Visitor',
+      'format' => 'filtered_html',
+      'weight' => '0',
+    ))->values(array(
+      'tid' => '11',
+      'vid' => '1',
+      'name' => 'Dax',
+      'description' => 'Portrayed by Terry Farrell',
+      'format' => 'filtered_html',
+      'weight' => '0',
+    ))->values(array(
+      'tid' => '12',
+      'vid' => '1',
+      'name' => 'Jake Sisko',
+      'description' => 'Portrayed by Cirroc Lofton',
+      'format' => 'filtered_html',
+      'weight' => '0',
+    ))->values(array(
+      'tid' => '13',
+      'vid' => '1',
+      'name' => 'Gul Dukat',
+      'description' => 'Portrayed by Marc Alaimo',
+      'format' => 'filtered_html',
+      'weight' => '0',
+    ))->values(array(
+      'tid' => '14',
+      'vid' => '1',
+      'name' => 'Odo',
+      'description' => 'Portrayed by Rene Auberjonois',
+      'format' => 'filtered_html',
+      'weight' => '0',
+    ))->values(array(
+      'tid' => '15',
+      'vid' => '1',
+      'name' => 'Worf',
+      'description' => 'Portrayed by Michael Dorn',
+      'format' => 'filtered_html',
+      'weight' => '0',
+    ))->values(array(
+      'tid' => '16',
+      'vid' => '1',
+      'name' => "Miles O'Brien",
+      'description' => 'Portrayed by Colm Meaney',
+      'format' => 'filtered_html',
+      'weight' => '0',
+    ))->values(array(
+      'tid' => '17',
+      'vid' => '1',
+      'name' => 'Quark',
+      'description' => 'Portrayed by Armin Shimerman',
+      'format' => 'filtered_html',
+      'weight' => '0',
+    ))->values(array(
+      'tid' => '18',
+      'vid' => '1',
+      'name' => 'Elim Garak',
+      'description' => 'Portrayed by Andrew Robinson',
+      'format' => 'filtered_html',
+      'weight' => '0',
     ))->execute();
   }
 
 }
-#77a4e5089be7384cbdf2b8c42efc2707
+#96a4d71a6a8cfeef1c1b40e49ae22f16
diff --git a/core/modules/migrate_drupal/src/Tests/Table/d7/TaxonomyTermHierarchy.php b/core/modules/migrate_drupal/src/Tests/Table/d7/TaxonomyTermHierarchy.php
index 9afd709ac3b97f0418542d57a502a781e54a3764..ae691a07099e5f51a6165543972d0e89ffc37454 100644
--- a/core/modules/migrate_drupal/src/Tests/Table/d7/TaxonomyTermHierarchy.php
+++ b/core/modules/migrate_drupal/src/Tests/Table/d7/TaxonomyTermHierarchy.php
@@ -62,6 +62,36 @@ public function load() {
     ))->values(array(
       'tid' => '6',
       'parent' => '0',
+    ))->values(array(
+      'tid' => '9',
+      'parent' => '0',
+    ))->values(array(
+      'tid' => '10',
+      'parent' => '0',
+    ))->values(array(
+      'tid' => '11',
+      'parent' => '0',
+    ))->values(array(
+      'tid' => '12',
+      'parent' => '0',
+    ))->values(array(
+      'tid' => '13',
+      'parent' => '0',
+    ))->values(array(
+      'tid' => '14',
+      'parent' => '0',
+    ))->values(array(
+      'tid' => '15',
+      'parent' => '0',
+    ))->values(array(
+      'tid' => '16',
+      'parent' => '0',
+    ))->values(array(
+      'tid' => '17',
+      'parent' => '0',
+    ))->values(array(
+      'tid' => '18',
+      'parent' => '0',
     ))->values(array(
       'tid' => '4',
       'parent' => '3',
@@ -75,4 +105,4 @@ public function load() {
   }
 
 }
-#ea3220ca740097f9251ba194e9bd736d
+#d93023562f8865e1410e3299511294d7
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6Test.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6Test.php
index 6c9c007cc51106ba15535ead022e2c76c63428e4..c8a86f64663d5385562901137772a1c71541c63d 100644
--- a/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6Test.php
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateDrupal6Test.php
@@ -124,7 +124,7 @@ class MigrateDrupal6Test extends MigrateFullDrupalTestBase {
     'd6_system_performance',
     'd6_system_rss',
     'd6_system_site',
-    'd6_taxonomy_settings',
+    'taxonomy_settings',
     'd6_taxonomy_term',
     'd6_taxonomy_vocabulary',
     'd6_term_node_revision:*',
diff --git a/core/modules/node/src/Plugin/migrate/builder/d6/Node.php b/core/modules/node/src/Plugin/migrate/builder/d6/Node.php
index ac08be1c844d6d30e4ac9e2a9e6a9ad89a45c8fa..4eaba230946198ef7d5b6205099a6fecf03a679e 100644
--- a/core/modules/node/src/Plugin/migrate/builder/d6/Node.php
+++ b/core/modules/node/src/Plugin/migrate/builder/d6/Node.php
@@ -8,45 +8,26 @@
 namespace Drupal\node\Plugin\migrate\builder\d6;
 
 use Drupal\migrate\Entity\Migration;
-use Drupal\migrate\Entity\MigrationInterface;
-use Drupal\migrate_drupal\Plugin\migrate\builder\d6\CckBuilder;
+use Drupal\migrate_drupal\Plugin\migrate\builder\CckBuilder;
 
 /**
  * @PluginID("d6_node")
  */
 class Node extends CckBuilder {
 
-  /**
-   * Already-instantiated cckfield plugins, keyed by ID.
-   *
-   * @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface[]
-   */
-  protected $cckPluginCache = [];
-
-  /**
-   * Gets a cckfield plugin instance.
-   *
-   * @param string $field_type
-   *   The field type (plugin ID).
-   * @param \Drupal\migrate\Entity\MigrationInterface|NULL $migration
-   *   The migration, if any.
-   *
-   * @return \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface
-   *   The cckfield plugin instance.
-   */
-  protected function getCckPlugin($field_type, MigrationInterface $migration = NULL) {
-    if (empty($this->cckPluginCache[$field_type])) {
-      $this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($field_type, [], $migration);
-    }
-    return $this->cckPluginCache[$field_type];
-  }
-
   /**
    * {@inheritdoc}
    */
   public function buildMigrations(array $template) {
     $migrations = [];
 
+    // Read all CCK field instance definitions in the source database.
+    $fields = array();
+    foreach ($this->getSourcePlugin('d6_field_instance', $template['source']) as $field) {
+      $info = $field->getSource();
+      $fields[$info['type_name']][$info['field_name']] = $info;
+    }
+
     foreach ($this->getSourcePlugin('d6_node_type', $template['source']) as $row) {
       $node_type = $row->getSourceProperty('type');
       $values = $template;
@@ -56,16 +37,15 @@ public function buildMigrations(array $template) {
       $values['source']['node_type'] = $node_type;
       $migration = Migration::create($values);
 
-      $fields = $this->getSourcePlugin('d6_field_instance', ['node_type' => $node_type] + $template['source']);
-      foreach ($fields as $field) {
-        $data = $field->getSource();
-
-        if ($this->cckPluginManager->hasDefinition($data['type'])) {
-          $this->getCckPlugin($data['type'])
-            ->processCckFieldValues($migration, $data['field_name'], $data);
-        }
-        else {
-          $migration->setProcessOfProperty($data['field_name'], $data['field_name']);
+      if (isset($fields[$node_type])) {
+        foreach ($fields[$node_type] as $field => $info) {
+          if ($this->cckPluginManager->hasDefinition($info['type'])) {
+            $this->getCckPlugin($info['type'])
+              ->processCckFieldValues($migration, $field, $info);
+          }
+          else {
+            $migration->setProcessOfProperty($field, $field);
+          }
         }
       }
 
diff --git a/core/modules/node/src/Plugin/migrate/builder/d7/Node.php b/core/modules/node/src/Plugin/migrate/builder/d7/Node.php
index 8b1dda35083f0ec8ba723e361be3ccc04cfc0f36..44b124ce8981c3da3cd276547d1d3ca9d90394cc 100644
--- a/core/modules/node/src/Plugin/migrate/builder/d7/Node.php
+++ b/core/modules/node/src/Plugin/migrate/builder/d7/Node.php
@@ -8,12 +8,12 @@
 namespace Drupal\node\Plugin\migrate\builder\d7;
 
 use Drupal\migrate\Entity\Migration;
-use Drupal\migrate\Plugin\migrate\builder\BuilderBase;
+use Drupal\migrate_drupal\Plugin\migrate\builder\CckBuilder;
 
 /**
  * @PluginID("d7_node")
  */
-class Node extends BuilderBase {
+class Node extends CckBuilder {
 
   /**
    * {@inheritdoc}
@@ -21,12 +21,11 @@ class Node extends BuilderBase {
   public function buildMigrations(array $template) {
     $migrations = [];
 
-    $fields = [];
+    // Read all field instance definitions in the source database.
+    $fields = array();
     foreach ($this->getSourcePlugin('d7_field_instance', $template['source']) as $field) {
-      $entity_type = $field->getSourceProperty('entity_type');
-      $bundle = $field->getSourceProperty('bundle');
-      $field_name = $field->getSourceProperty('field_name');
-      $fields[$entity_type][$bundle][$field_name] = $field->getSource();
+      $info = $field->getSource();
+      $fields[$info['entity_type']][$info['bundle']][$info['field_name']] = $info;
     }
 
     foreach ($this->getSourcePlugin('d7_node_type', $template['source']) as $node_type) {
@@ -38,8 +37,14 @@ public function buildMigrations(array $template) {
       $migration = Migration::create($values);
 
       if (isset($fields['node'][$bundle])) {
-        foreach (array_keys($fields['node'][$bundle]) as $field) {
-          $migration->setProcessOfProperty($field, $field);
+        foreach ($fields['node'][$bundle] as $field => $data) {
+          if ($this->cckPluginManager->hasDefinition($data['type'])) {
+            $this->getCckPlugin($data['type'])
+              ->processCckFieldValues($migration, $field, $data);
+          }
+          else {
+            $migration->setProcessOfProperty($field, $field);
+          }
         }
       }
 
diff --git a/core/modules/taxonomy/migration_templates/d6_taxonomy_term.yml b/core/modules/taxonomy/migration_templates/d6_taxonomy_term.yml
index 546f95fbe924861355c4f9a2f48f38e36054e8cd..39078f9d25aa11f01ad3f628fb5298a45d19ee06 100644
--- a/core/modules/taxonomy/migration_templates/d6_taxonomy_term.yml
+++ b/core/modules/taxonomy/migration_templates/d6_taxonomy_term.yml
@@ -3,7 +3,7 @@ label: Drupal 6 taxonomy terms
 migration_tags:
   - Drupal 6
 source:
-  plugin: d6_taxonomy_term
+  plugin: taxonomy_term
 process:
   tid: tid
   vid:
@@ -14,13 +14,9 @@ process:
   description: description
   weight: weight
   parent:
-    -
-      plugin: skip_on_empty
-      method: process
-      source: parent
-    -
-      plugin: migration
-      migration: d6_taxonomy_term
+    plugin: migration
+    migration: d6_taxonomy_term
+    source: parent
   changed: timestamp
 destination:
   plugin: entity:taxonomy_term
diff --git a/core/modules/taxonomy/migration_templates/d6_term_node.yml b/core/modules/taxonomy/migration_templates/d6_term_node.yml
index ee7f8300e6e19fd266792954d3c888c3209c5895..024548dfaecb8f57cfb774186a828bcc3ca952aa 100644
--- a/core/modules/taxonomy/migration_templates/d6_term_node.yml
+++ b/core/modules/taxonomy/migration_templates/d6_term_node.yml
@@ -4,17 +4,12 @@ migration_tags:
   - Drupal 6
 builder:
   plugin: d6_term_node
-load:
-  plugin: d6_term_node
-
 source:
   plugin: d6_term_node
-
 process:
   nid: nid
   type: type
-  # The actual field name is dynamic and will be added by the load plugin.
-
+  # The actual field name is dynamic and will be added by the builder.
 destination:
   plugin: entity:node
 migration_dependencies:
diff --git a/core/modules/taxonomy/migration_templates/d6_term_node_revision.yml b/core/modules/taxonomy/migration_templates/d6_term_node_revision.yml
index d904d41844da0ebdd5e690a1f0dc9fc417043d18..ae3dffc32ecca3c1a1695a8fbb3314dc2eac1d2c 100644
--- a/core/modules/taxonomy/migration_templates/d6_term_node_revision.yml
+++ b/core/modules/taxonomy/migration_templates/d6_term_node_revision.yml
@@ -4,18 +4,12 @@ migration_tags:
   - Drupal 6
 builder:
   plugin: d6_term_node
-load:
-  plugin: d6_term_node
-  bundle_migration: d6_vocabulary_field
-
 source:
   plugin: d6_term_node_revision
-
 process:
   vid: vid
   type: type
-  # The actual field name is dynamic and will be added by the load plugin.
-
+  # The actual field name is dynamic and will be added by the builder.
 destination:
   plugin: entity_revision:node
 migration_dependencies:
diff --git a/core/modules/taxonomy/migration_templates/d6_vocabulary_entity_display.yml b/core/modules/taxonomy/migration_templates/d6_vocabulary_entity_display.yml
index 9295acd92996a5941fb7470d25ba58870a24498d..eee7474b02c30371bb74c867d2ed626a0ad71ea2 100644
--- a/core/modules/taxonomy/migration_templates/d6_vocabulary_entity_display.yml
+++ b/core/modules/taxonomy/migration_templates/d6_vocabulary_entity_display.yml
@@ -11,7 +11,6 @@ source:
       label: hidden
       type: entity_reference_label
       weight: 20
-
 process:
   entity_type: 'constants/entity_type'
   view_mode: 'constants/view_mode'
diff --git a/core/modules/taxonomy/migration_templates/d7_taxonomy_term.yml b/core/modules/taxonomy/migration_templates/d7_taxonomy_term.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5ef8b9e68a81237d47e85698e749ad9aa6ba6bb3
--- /dev/null
+++ b/core/modules/taxonomy/migration_templates/d7_taxonomy_term.yml
@@ -0,0 +1,25 @@
+id: d7_taxonomy_term
+label: Drupal 7 taxonomy terms
+migration_tags:
+  - Drupal 7
+source:
+  plugin: taxonomy_term
+process:
+  tid: tid
+  vid:
+    plugin: migration
+    migration: d7_taxonomy_vocabulary
+    source: vid
+  name: name
+  description: description
+  weight: weight
+  parent:
+    plugin: migration
+    migration: d7_taxonomy_term
+    source: parent
+  changed: timestamp
+destination:
+  plugin: entity:taxonomy_term
+migration_dependencies:
+  required:
+    - d7_taxonomy_vocabulary
diff --git a/core/modules/taxonomy/migration_templates/d7_taxonomy_vocabulary.yml b/core/modules/taxonomy/migration_templates/d7_taxonomy_vocabulary.yml
new file mode 100644
index 0000000000000000000000000000000000000000..946c79941d7a0ce81c8861991d3dbbf98a290620
--- /dev/null
+++ b/core/modules/taxonomy/migration_templates/d7_taxonomy_vocabulary.yml
@@ -0,0 +1,15 @@
+id: d7_taxonomy_vocabulary
+label: Drupal 7 taxonomy vocabularies
+migration_tags:
+  - Drupal 7
+source:
+  plugin: d7_taxonomy_vocabulary
+process:
+  vid: machine_name
+  label: name
+  name: name
+  description: description
+  hierarchy: hierarchy
+  weight: weight
+destination:
+  plugin: entity:taxonomy_vocabulary
diff --git a/core/modules/taxonomy/migration_templates/d6_taxonomy_settings.yml b/core/modules/taxonomy/migration_templates/taxonomy_settings.yml
similarity index 79%
rename from core/modules/taxonomy/migration_templates/d6_taxonomy_settings.yml
rename to core/modules/taxonomy/migration_templates/taxonomy_settings.yml
index 3fe9e1fd90c5a76292485237f91c53ffec086e50..b50657d961f8d8cf33905debab79e317e3cbd6c7 100644
--- a/core/modules/taxonomy/migration_templates/d6_taxonomy_settings.yml
+++ b/core/modules/taxonomy/migration_templates/taxonomy_settings.yml
@@ -1,7 +1,8 @@
-id: d6_taxonomy_settings
-label: Drupal 6 taxonomy configuration
+id: taxonomy_settings
+label: Drupal 6 and 7 taxonomy configuration
 migration_tags:
   - Drupal 6
+  - Drupal 7
 source:
   plugin: variable
   variables:
diff --git a/core/modules/taxonomy/src/Plugin/migrate/cckfield/TaxonomyTermReference.php b/core/modules/taxonomy/src/Plugin/migrate/cckfield/TaxonomyTermReference.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ce428e05c6e60ef64a75a29c25052ae06bf1cb9
--- /dev/null
+++ b/core/modules/taxonomy/src/Plugin/migrate/cckfield/TaxonomyTermReference.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\taxonomy\Plugin\migrate\cckfield\TaxonomyTermReference.
+ */
+
+namespace Drupal\taxonomy\Plugin\migrate\cckfield;
+
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate_drupal\Plugin\migrate\cckfield\CckFieldPluginBase;
+
+/**
+ * @PluginID("taxonomy_term_reference")
+ */
+class TaxonomyTermReference extends CckFieldPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldFormatterMap() {
+    return array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function processCckFieldValues(MigrationInterface $migration, $field_name, $data) {
+    $process = array(
+      'plugin' => 'iterator',
+      'source' => $field_name,
+      'process' => array(
+        'target_id' => 'tid',
+      ),
+    );
+    $migration->setProcessOfProperty($field_name, $process);
+  }
+
+}
diff --git a/core/modules/taxonomy/src/Plugin/migrate/source/d6/Term.php b/core/modules/taxonomy/src/Plugin/migrate/source/Term.php
similarity index 58%
rename from core/modules/taxonomy/src/Plugin/migrate/source/d6/Term.php
rename to core/modules/taxonomy/src/Plugin/migrate/source/Term.php
index 841faca09a6f0042bcfcc3fcb726ae0bf849d39e..ff4507d0c3e48d666dc853cf10a43ebb1c2e69ea 100644
--- a/core/modules/taxonomy/src/Plugin/migrate/source/d6/Term.php
+++ b/core/modules/taxonomy/src/Plugin/migrate/source/Term.php
@@ -2,41 +2,62 @@
 
 /**
  * @file
- * Contains \Drupal\taxonomy\Plugin\migrate\source\d6\Term.
+ * Contains \Drupal\taxonomy\Plugin\migrate\source\Term.
  */
 
-namespace Drupal\taxonomy\Plugin\migrate\source\d6;
+namespace Drupal\taxonomy\Plugin\migrate\source;
 
 use Drupal\migrate\Row;
 use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
 
 /**
- * Drupal 6 taxonomy terms source from database.
+ * Taxonomy term source from database.
  *
  * @todo Support term_relation, term_synonym table if possible.
  *
  * @MigrateSource(
- *   id = "d6_taxonomy_term",
+ *   id = "taxonomy_term",
  *   source_provider = "taxonomy"
  * )
  */
 class Term extends DrupalSqlBase {
 
+  /**
+   * Name of the term data table.
+   *
+   * @var string
+   */
+  protected $termDataTable;
+
+  /**
+   * Name of the term hierarchy table.
+   *
+   * @var string
+   */
+  protected $termHierarchyTable;
+
   /**
    * {@inheritdoc}
    */
   public function query() {
-    // Note the explode - this supports the (admittedly unusual) case of
-    // consolidating multiple vocabularies into one.
-    $query = $this->select('term_data', 'td')
-      ->fields('td', array('tid', 'vid', 'name', 'description', 'weight'))
-    // This works, but we cannot test that, because there is no support for
-    // distinct() in FakeSelect, yet.
+    if ($this->getModuleSchemaVersion('taxonomy') >= 7000) {
+      $this->termDataTable = 'taxonomy_term_data';
+      $this->termHierarchyTable = 'taxonomy_term_hierarchy';
+    }
+    else {
+      $this->termDataTable = 'term_data';
+      $this->termHierarchyTable = 'term_hierarchy';
+    }
+
+    $query = $this->select($this->termDataTable, 'td')
+      ->fields('td')
       ->distinct()
       ->orderBy('tid');
+
     if (isset($this->configuration['vocabulary'])) {
       $query->condition('vid', $this->configuration['vocabulary'], 'IN');
     }
+
     return $query;
   }
 
@@ -44,7 +65,7 @@ public function query() {
    * {@inheritdoc}
    */
   public function fields() {
-    return array(
+    $fields = array(
       'tid' => $this->t('The term ID.'),
       'vid' => $this->t('Existing term VID'),
       'name' => $this->t('The name of the term.'),
@@ -52,6 +73,10 @@ public function fields() {
       'weight' => $this->t('Weight'),
       'parent' => $this->t("The Drupal term IDs of the term's parents."),
     );
+    if ($this->getModuleSchemaVersion('taxonomy') >= 7000) {
+      $fields['format'] = $this->t('Format of the term description.');
+    }
+    return $fields;
   }
 
   /**
@@ -59,12 +84,13 @@ public function fields() {
    */
   public function prepareRow(Row $row) {
     // Find parents for this row.
-    $parents = $this->select('term_hierarchy', 'th')
+    $parents = $this->select($this->termHierarchyTable, 'th')
       ->fields('th', array('parent', 'tid'))
       ->condition('tid', $row->getSourceProperty('tid'))
       ->execute()
       ->fetchCol();
     $row->setSourceProperty('parent', $parents);
+
     return parent::prepareRow($row);
   }
 
diff --git a/core/modules/taxonomy/src/Plugin/migrate/source/d6/Vocabulary.php b/core/modules/taxonomy/src/Plugin/migrate/source/d6/Vocabulary.php
index 2ed3c003352a77b66ceaa574fa7fe4a61d8abb83..d2d3f19853a16d191de572a4643bf84e1171b6c8 100644
--- a/core/modules/taxonomy/src/Plugin/migrate/source/d6/Vocabulary.php
+++ b/core/modules/taxonomy/src/Plugin/migrate/source/d6/Vocabulary.php
@@ -8,6 +8,7 @@
 namespace Drupal\taxonomy\Plugin\migrate\source\d6;
 
 use Drupal\migrate\Row;
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
 
 /**
  * Drupal 6 vocabularies source from database.
@@ -17,7 +18,48 @@
  *   source_provider = "taxonomy"
  * )
  */
-class Vocabulary extends VocabularyBase {
+class Vocabulary extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('vocabulary', 'v')
+      ->fields('v', array(
+        'vid',
+        'name',
+        'description',
+        'help',
+        'relations',
+        'hierarchy',
+        'multiple',
+        'required',
+        'tags',
+        'module',
+        'weight',
+      ));
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'vid' => $this->t('The vocabulary ID.'),
+      'name' => $this->t('The name of the vocabulary.'),
+      'description' => $this->t('The description of the vocabulary.'),
+      'help' => $this->t('Help text to display for the vocabulary.'),
+      'relations' => $this->t('Whether or not related terms are enabled within the vocabulary. (0 = disabled, 1 = enabled)'),
+      'hierarchy' => $this->t('The type of hierarchy allowed within the vocabulary. (0 = disabled, 1 = single, 2 = multiple)'),
+      'multiple' => $this->t('Whether or not multiple terms from this vocabulary may be assigned to a node. (0 = disabled, 1 = enabled)'),
+      'required' => $this->t('Whether or not terms are required for nodes using this vocabulary. (0 = disabled, 1 = enabled)'),
+      'tags' => $this->t('Whether or not free tagging is enabled for the vocabulary. (0 = disabled, 1 = enabled)'),
+      'weight' => $this->t('The weight of the vocabulary in relation to other vocabularies.'),
+      'parents' => $this->t("The Drupal term IDs of the term's parents."),
+      'node_types' => $this->t('The names of the node types the vocabulary may be used with.'),
+    );
+  }
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyBase.php b/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyBase.php
deleted file mode 100644
index ce132d0ef2c3ccd8090e1992d81c6488ba402380..0000000000000000000000000000000000000000
--- a/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyBase.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\taxonomy\Plugin\migrate\source\d6\VocabularyBase.
- */
-
-namespace Drupal\taxonomy\Plugin\migrate\source\d6;
-
-use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
-
-/**
- * Drupal 6 vocabularies source base.
- */
-abstract class VocabularyBase extends DrupalSqlBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function query() {
-    $query = $this->select('vocabulary', 'v')
-      ->fields('v', array(
-        'vid',
-        'name',
-        'description',
-        'help',
-        'relations',
-        'hierarchy',
-        'multiple',
-        'required',
-        'tags',
-        'module',
-        'weight',
-      ));
-    return $query;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function fields() {
-    return array(
-      'vid' => $this->t('The vocabulary ID.'),
-      'name' => $this->t('The name of the vocabulary.'),
-      'description' => $this->t('The description of the vocabulary.'),
-      'help' => $this->t('Help text to display for the vocabulary.'),
-      'relations' => $this->t('Whether or not related terms are enabled within the vocabulary. (0 = disabled, 1 = enabled)'),
-      'hierarchy' => $this->t('The type of hierarchy allowed within the vocabulary. (0 = disabled, 1 = single, 2 = multiple)'),
-      'multiple' => $this->t('Whether or not multiple terms from this vocabulary may be assigned to a node. (0 = disabled, 1 = enabled)'),
-      'required' => $this->t('Whether or not terms are required for nodes using this vocabulary. (0 = disabled, 1 = enabled)'),
-      'tags' => $this->t('Whether or not free tagging is enabled for the vocabulary. (0 = disabled, 1 = enabled)'),
-      'weight' => $this->t('The weight of the vocabulary in relation to other vocabularies.'),
-      'parents' => $this->t("The Drupal term IDs of the term's parents."),
-      'node_types' => $this->t('The names of the node types the vocabulary may be used with.'),
-    );
-  }
-
-}
diff --git a/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyPerType.php b/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyPerType.php
index 3f0083db9b588a75e0e54474d114fae4839143c0..3dee6fc76e43acfecd56ffa2e0c6a435e3a2eb65 100644
--- a/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyPerType.php
+++ b/core/modules/taxonomy/src/Plugin/migrate/source/d6/VocabularyPerType.php
@@ -22,10 +22,8 @@ class VocabularyPerType extends Vocabulary {
    */
   public function query() {
     $query = parent::query();
-    $query->fields('nt', array(
-        'type',
-      ));
     $query->join('vocabulary_node_types', 'nt', 'v.vid = nt.vid');
+    $query->fields('nt', array('type'));
     return $query;
   }
 
diff --git a/core/modules/taxonomy/src/Plugin/migrate/source/d7/Vocabulary.php b/core/modules/taxonomy/src/Plugin/migrate/source/d7/Vocabulary.php
new file mode 100644
index 0000000000000000000000000000000000000000..368c81976d21c4e7a82e92c68b6753fe2600e59a
--- /dev/null
+++ b/core/modules/taxonomy/src/Plugin/migrate/source/d7/Vocabulary.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\taxonomy\Plugin\migrate\source\d7\Vocabulary.
+ */
+
+namespace Drupal\taxonomy\Plugin\migrate\source\d7;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 7 vocabularies source from database.
+ *
+ * @MigrateSource(
+ *   id = "d7_taxonomy_vocabulary",
+ *   source_provider = "taxonomy"
+ * )
+ */
+class Vocabulary extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('taxonomy_vocabulary', 'v')
+      ->fields('v', array(
+        'vid',
+        'name',
+        'description',
+        'hierarchy',
+        'module',
+        'weight',
+        'machine_name',
+      ));
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'vid' => $this->t('The vocabulary ID.'),
+      'name' => $this->t('The name of the vocabulary.'),
+      'description' => $this->t('The description of the vocabulary.'),
+      'hierarchy' => $this->t('The type of hierarchy allowed within the vocabulary. (0 = disabled, 1 = single, 2 = multiple)'),
+      'module' => $this->t('Module responsible for the vocabulary.'),
+      'weight' => $this->t('The weight of the vocabulary in relation to other vocabularies.'),
+      'machine_name' => $this->t('Unique achine name of the vocabulary.')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['vid']['type'] = 'integer';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/taxonomy/src/Tests/Migrate/d6/MigrateTaxonomyConfigsTest.php b/core/modules/taxonomy/src/Tests/Migrate/MigrateTaxonomyConfigsTest.php
similarity index 84%
rename from core/modules/taxonomy/src/Tests/Migrate/d6/MigrateTaxonomyConfigsTest.php
rename to core/modules/taxonomy/src/Tests/Migrate/MigrateTaxonomyConfigsTest.php
index d2122752949c2568df478a2e27c3a7b88914e7d4..699ea9344962adbd5c880f7c0949dd823453a6e0 100644
--- a/core/modules/taxonomy/src/Tests/Migrate/d6/MigrateTaxonomyConfigsTest.php
+++ b/core/modules/taxonomy/src/Tests/Migrate/MigrateTaxonomyConfigsTest.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Contains \Drupal\taxonomy\Tests\Migrate\d6\MigrateTaxonomyConfigsTest.
+ * Contains \Drupal\taxonomy\Tests\Migrate\MigrateTaxonomyConfigsTest.
  */
 
-namespace Drupal\taxonomy\Tests\Migrate\d6;
+namespace Drupal\taxonomy\Tests\Migrate;
 
 use Drupal\config\Tests\SchemaCheckTestTrait;
 use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
@@ -31,7 +31,7 @@ class MigrateTaxonomyConfigsTest extends MigrateDrupal6TestBase {
    */
   protected function setUp() {
     parent::setUp();
-    $this->executeMigration('d6_taxonomy_settings');
+    $this->executeMigration('taxonomy_settings');
   }
 
   /**
diff --git a/core/modules/taxonomy/src/Tests/Migrate/d7/MigrateNodeTaxonomyTest.php b/core/modules/taxonomy/src/Tests/Migrate/d7/MigrateNodeTaxonomyTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..32b82d258f6b14ec599b4c302c64f3af060f8730
--- /dev/null
+++ b/core/modules/taxonomy/src/Tests/Migrate/d7/MigrateNodeTaxonomyTest.php
@@ -0,0 +1,83 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\taxonomy\Tests\Migrate\d7\MigrateNodeTaxonomyTest.
+ */
+
+namespace Drupal\taxonomy\Tests\Migrate\d7;
+
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\field\FieldStorageConfigInterface;
+use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
+use Drupal\node\Entity\Node;
+use Drupal\node\NodeInterface;
+
+/**
+ * @group taxonomy
+ */
+class MigrateNodeTaxonomyTest extends MigrateDrupal7TestBase {
+
+  public static $modules = array(
+    'datetime',
+    'entity_reference',
+    'field',
+    'filter',
+    'image',
+    'link',
+    'node',
+    'taxonomy',
+    'telephone',
+    'text',
+  );
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->installEntitySchema('node');
+    $this->installEntitySchema('taxonomy_term');
+    $this->installConfig(static::$modules);
+    $this->installSchema('node', ['node_access']);
+    $this->installSchema('system', ['sequences']);
+
+    $this->executeMigration('d7_node_type');
+
+    FieldStorageConfig::create(array(
+      'type' => 'entity_reference',
+      'field_name' => 'field_tags',
+      'entity_type' => 'node',
+      'settings' => array(
+        'target_type' => 'taxonomy_term',
+      ),
+      'cardinality' => FieldStorageConfigInterface::CARDINALITY_UNLIMITED,
+    ))->save();
+
+    FieldConfig::create(array(
+      'entity_type' => 'node',
+      'field_name' => 'field_tags',
+      'bundle' => 'article',
+    ))->save();
+
+    $this->executeMigration('d7_taxonomy_vocabulary');
+    $this->executeMigration('d7_taxonomy_term');
+    $this->executeMigration('d7_user_role');
+    $this->executeMigration('d7_user');
+    $this->executeMigration('d7_node__article');
+  }
+
+  /**
+   * Test node migration from Drupal 7 to 8.
+   */
+  public function testMigration() {
+    $node = Node::load(2);
+    $this->assertTrue($node instanceof NodeInterface);
+    $this->assertEqual(9, $node->field_tags[0]->target_id);
+    $this->assertEqual(14, $node->field_tags[1]->target_id);
+    $this->assertEqual(17, $node->field_tags[2]->target_id);
+  }
+
+}
diff --git a/core/modules/taxonomy/src/Tests/Migrate/d7/MigrateTaxonomyTermTest.php b/core/modules/taxonomy/src/Tests/Migrate/d7/MigrateTaxonomyTermTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..6c016978e5a56cb00210a953c970393adb37a5a4
--- /dev/null
+++ b/core/modules/taxonomy/src/Tests/Migrate/d7/MigrateTaxonomyTermTest.php
@@ -0,0 +1,87 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\taxonomy\Tests\Migrate\d7\MigrateTaxonomyTermTest.
+ */
+
+namespace Drupal\taxonomy\Tests\Migrate\d7;
+
+use Drupal\taxonomy\Entity\Term;
+use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
+use Drupal\taxonomy\TermInterface;
+
+/**
+ * Upgrade taxonomy terms.
+ *
+ * @group taxonomy
+ */
+class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase {
+
+  static $modules = array('taxonomy', 'text');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->installEntitySchema('taxonomy_term');
+    $this->executeMigration('d7_taxonomy_vocabulary');
+    $this->executeMigration('d7_taxonomy_term');
+  }
+
+  /**
+   * Validate a migrated term contains the expected values.
+   *
+   * @param $id
+   *   Entity ID to load and check.
+   * @param $expected_label
+   *   The label the migrated entity should have.
+   * @param $expected_vid
+   *   The parent vocabulary the migrated entity should have.
+   * @param string $expected_description
+   *   The description the migrated entity should have.
+   * @param int $expected_weight
+   *   The weight the migrated entity should have.
+   * @param array $expected_parents
+   *   The parent terms the migrated entity should have.
+   */
+  protected function assertEntity($id, $expected_label, $expected_vid, $expected_description = '', $expected_weight = 0, $expected_parents = []) {
+    /** @var \Drupal\taxonomy\TermInterface $entity */
+    $entity = Term::load($id);
+    $this->assertTrue($entity instanceof TermInterface);
+    $this->assertIdentical($expected_label, $entity->label());
+    $this->assertIdentical($expected_vid, $entity->getVocabularyId());
+    $this->assertEqual($expected_description, $entity->getDescription());
+    $this->assertEqual($expected_weight, $entity->getWeight());
+    $this->assertIdentical($expected_parents, $this->getParentIDs($id));
+  }
+
+  /**
+   * Tests the Drupal 7 taxonomy term to Drupal 8 migration.
+   */
+  public function testTaxonomyTerms() {
+    $this->assertEntity(1, 'General discussion', 'forums', '', 2);
+    $this->assertEntity(2, 'Term1', 'test_vocabulary', 'The first term.');
+    $this->assertEntity(3, 'Term2', 'test_vocabulary', 'The second term.');
+    $this->assertEntity(4, 'Term3', 'test_vocabulary', 'The third term.', 0, [3]);
+    $this->assertEntity(5, 'Custom Forum', 'forums', 'Where the cool kids are.', 3);
+    $this->assertEntity(6, 'Games', 'forums', '', 4);
+    $this->assertEntity(7, 'Minecraft', 'forums', '', 1, [6]);
+    $this->assertEntity(8, 'Half Life 3', 'forums', '', 0, [6]);
+  }
+
+  /**
+   * Retrieves the parent term IDs for a given term.
+   *
+   * @param $tid
+   *   ID of the term to check.
+   *
+   * @return array
+   *   List of parent term IDs.
+   */
+  protected function getParentIDs($tid) {
+    return array_keys(\Drupal::entityManager()->getStorage('taxonomy_term')->loadParents($tid));
+  }
+
+}
diff --git a/core/modules/taxonomy/src/Tests/Migrate/d7/MigrateTaxonomyVocabularyTest.php b/core/modules/taxonomy/src/Tests/Migrate/d7/MigrateTaxonomyVocabularyTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e53f827f53a6a45d5e567434dc506fcb0a2b997d
--- /dev/null
+++ b/core/modules/taxonomy/src/Tests/Migrate/d7/MigrateTaxonomyVocabularyTest.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\taxonomy\Tests\Migrate\d7\MigrateTaxonomyVocabularyTest.
+ */
+
+namespace Drupal\taxonomy\Tests\Migrate\d7;
+
+use Drupal\taxonomy\Entity\Vocabulary;
+use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
+use Drupal\taxonomy\VocabularyInterface;
+
+/**
+ * Migrate taxonomy vocabularies to taxonomy.vocabulary.*.yml.
+ *
+ * @group taxonomy
+ */
+class MigrateTaxonomyVocabularyTest extends MigrateDrupal7TestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('taxonomy');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->executeMigration('d7_taxonomy_vocabulary');
+  }
+
+  /**
+   * Validate a migrated vocabulary contains the expected values.
+   *
+   * @param $id
+   *   Entity ID to load and check.
+   * @param $expected_label
+   *   The label the migrated entity should have.
+   * @param $expected_description
+   *   The description the migrated entity should have.
+   * @param $expected_hierarchy
+   *   The hierarchy setting the migrated entity should have.
+   * @param $expected_weight
+   *   The weight the migrated entity should have.
+   */
+  protected function assertEntity($id, $expected_label, $expected_description, $expected_hierarchy, $expected_weight) {
+    /** @var \Drupal\taxonomy\VocabularyInterface $entity */
+    $entity = Vocabulary::load($id);
+    $this->assertTrue($entity instanceof VocabularyInterface);
+    $this->assertIdentical($expected_label, $entity->label());
+    $this->assertIdentical($expected_description, $entity->getDescription());
+    $this->assertIdentical($expected_hierarchy, $entity->getHierarchy());
+    $this->assertIdentical($expected_weight, $entity->get('weight'));
+  }
+
+  /**
+   * Tests the Drupal 7 taxonomy vocabularies to Drupal 8 migration.
+   */
+  public function testTaxonomyVocabulary() {
+    $this->assertEntity('tags', 'Tags', 'Use tags to group articles on similar topics into categories.', TAXONOMY_HIERARCHY_DISABLED, 0);
+    $this->assertEntity('forums', 'Forums', 'Forum navigation vocabulary', TAXONOMY_HIERARCHY_SINGLE, -10);
+    $this->assertEntity('test_vocabulary', 'Test Vocabulary', 'This is the vocabulary description', TAXONOMY_HIERARCHY_SINGLE, 0);
+  }
+
+}
diff --git a/core/modules/taxonomy/tests/src/Unit/Migrate/d6/TermSourceWithVocabularyFilterTest.php b/core/modules/taxonomy/tests/src/Unit/Migrate/TermSourceWithVocabularyFilterTest.php
similarity index 71%
rename from core/modules/taxonomy/tests/src/Unit/Migrate/d6/TermSourceWithVocabularyFilterTest.php
rename to core/modules/taxonomy/tests/src/Unit/Migrate/TermSourceWithVocabularyFilterTest.php
index 38a026f66752eb80e2a8681262824ad4a1f83826..6038a3e36682de4e971f2c899b84706e8051de43 100644
--- a/core/modules/taxonomy/tests/src/Unit/Migrate/d6/TermSourceWithVocabularyFilterTest.php
+++ b/core/modules/taxonomy/tests/src/Unit/Migrate/TermSourceWithVocabularyFilterTest.php
@@ -2,13 +2,13 @@
 
 /**
  * @file
- * Contains \Drupal\Tests\taxonomy\Unit\Migrate\d6\TermSourceWithVocabularyFilterTest.
+ * Contains \Drupal\Tests\taxonomy\Unit\Migrate\TermSourceWithVocabularyFilterTest.
  */
 
-namespace Drupal\Tests\taxonomy\Unit\Migrate\d6;
+namespace Drupal\Tests\taxonomy\Unit\Migrate;
 
 /**
- * Tests the Drupal 6 taxonomy term source with vocabulary filter.
+ * Tests the taxonomy term source with vocabulary filter.
  *
  * @group taxonomy
  */
diff --git a/core/modules/taxonomy/tests/src/Unit/Migrate/TermTest.php b/core/modules/taxonomy/tests/src/Unit/Migrate/TermTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e17c963c2e4b9d02a3cdda3e8c2efbfa10e36200
--- /dev/null
+++ b/core/modules/taxonomy/tests/src/Unit/Migrate/TermTest.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\taxonomy\Unit\Migrate\TermTest.
+ */
+
+namespace Drupal\Tests\taxonomy\Unit\Migrate;
+
+/**
+ * Tests taxonomy term source plugin.
+ *
+ * @group taxonomy
+ */
+class TermTest extends TermTestBase {
+
+}
diff --git a/core/modules/taxonomy/tests/src/Unit/Migrate/d6/TermTestBase.php b/core/modules/taxonomy/tests/src/Unit/Migrate/TermTestBase.php
similarity index 91%
rename from core/modules/taxonomy/tests/src/Unit/Migrate/d6/TermTestBase.php
rename to core/modules/taxonomy/tests/src/Unit/Migrate/TermTestBase.php
index e8d164be227053818a8fd69447b00689d6148f1f..f8142f55a7f8cff7ab46e18791151219045ed7f0 100644
--- a/core/modules/taxonomy/tests/src/Unit/Migrate/d6/TermTestBase.php
+++ b/core/modules/taxonomy/tests/src/Unit/Migrate/TermTestBase.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Contains \Drupal\Tests\taxonomy\Unit\Migrate\d6\TermTestBase.
+ * Contains \Drupal\Tests\taxonomy\Unit\Migrate\TermTestBase.
  */
 
-namespace Drupal\Tests\taxonomy\Unit\Migrate\d6;
+namespace Drupal\Tests\taxonomy\Unit\Migrate;
 
 use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
 
@@ -14,7 +14,7 @@
  */
 abstract class TermTestBase extends MigrateSqlSourceTestCase {
 
-  const PLUGIN_CLASS = 'Drupal\taxonomy\Plugin\migrate\source\d6\Term';
+  const PLUGIN_CLASS = 'Drupal\taxonomy\Plugin\migrate\source\Term';
 
   protected $migrationConfiguration = array(
     'id' => 'test',
diff --git a/core/modules/taxonomy/tests/src/Unit/Migrate/d6/TermTest.php b/core/modules/taxonomy/tests/src/Unit/Migrate/d6/TermTest.php
deleted file mode 100644
index 22a83129adff6d576c04f7795021cf9362c35e9e..0000000000000000000000000000000000000000
--- a/core/modules/taxonomy/tests/src/Unit/Migrate/d6/TermTest.php
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\taxonomy\Unit\Migrate\d6\TermTest.
- */
-
-namespace Drupal\Tests\taxonomy\Unit\Migrate\d6;
-
-/**
- * Tests D6 taxonomy term source plugin.
- *
- * @group taxonomy
- */
-class TermTest extends TermTestBase {
-
-}
diff --git a/core/modules/taxonomy/tests/src/Unit/Migrate/d6/VocabularyTest.php b/core/modules/taxonomy/tests/src/Unit/Migrate/d6/VocabularyTest.php
index d2a87c9f5711667237ff3872c53e377b5738bc3e..60362d73c89ce449847617f093b2d646e16425d8 100644
--- a/core/modules/taxonomy/tests/src/Unit/Migrate/d6/VocabularyTest.php
+++ b/core/modules/taxonomy/tests/src/Unit/Migrate/d6/VocabularyTest.php
@@ -18,9 +18,7 @@ class VocabularyTest extends MigrateSqlSourceTestCase {
 
   const PLUGIN_CLASS = 'Drupal\taxonomy\Plugin\migrate\source\d6\Vocabulary';
 
-  // The fake Migration configuration entity.
   protected $migrationConfiguration = [
-    // The ID of the entity, can be any string.
     'id' => 'test',
     'source' => [
       'plugin' => 'd6_vocabulary',
diff --git a/core/modules/taxonomy/tests/src/Unit/Migrate/d7/VocabularyTest.php b/core/modules/taxonomy/tests/src/Unit/Migrate/d7/VocabularyTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3698090888b92e23d6dfcca6736c6cafcae9b43f
--- /dev/null
+++ b/core/modules/taxonomy/tests/src/Unit/Migrate/d7/VocabularyTest.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\taxonomy\Unit\Migrate\d7\VocabularyTest.
+ */
+
+namespace Drupal\Tests\taxonomy\Unit\Migrate\d7;
+
+use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
+
+/**
+ * Tests D7 vocabulary source plugin.
+ *
+ * @group taxonomy
+ */
+class VocabularyTest extends MigrateSqlSourceTestCase {
+
+  const PLUGIN_CLASS = 'Drupal\taxonomy\Plugin\migrate\source\d7\Vocabulary';
+
+  protected $migrationConfiguration = [
+    'id' => 'test',
+    'source' => [
+      'plugin' => 'd7_vocabulary',
+    ],
+  ];
+
+  protected $expectedResults = [
+    [
+      'vid' => 1,
+      'name' => 'Tags',
+      'description' => 'Tags description.',
+      'hierarchy' => 0,
+      'module' => 'taxonomy',
+      'weight' => 0,
+      'machine_name' => 'tags',
+    ],
+    [
+      'vid' => 2,
+      'name' => 'Categories',
+      'description' => 'Categories description.',
+      'hierarchy' => 1,
+      'module' => 'taxonomy',
+      'weight' => 0,
+      'machine_name' => 'categories',
+    ],
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->databaseContents['taxonomy_vocabulary'] = $this->expectedResults;
+    parent::setUp();
+  }
+
+}