From d0ac307e0b952dda08f402c30a6e6edc2cd8b7cd Mon Sep 17 00:00:00 2001
From: MegaChriz <megachriz@hotmail.com>
Date: Fri, 30 Oct 2015 20:39:37 +0100
Subject: [PATCH] Issue #2556461 by MegaChriz: Fixed importing two hierarchical
 vocabularies with overlapping id's.

---
 plugins/FeedsTermProcessor.inc  |  14 +-
 tests/feeds/terms.csv           |   3 +
 tests/feeds_processor_term.test | 228 ++++++++++++++++++++++++++++++++
 3 files changed, 243 insertions(+), 2 deletions(-)
 create mode 100644 tests/feeds/terms.csv

diff --git a/plugins/FeedsTermProcessor.inc b/plugins/FeedsTermProcessor.inc
index f69819f3..c600b978 100644
--- a/plugins/FeedsTermProcessor.inc
+++ b/plugins/FeedsTermProcessor.inc
@@ -112,11 +112,21 @@ class FeedsTermProcessor extends FeedsProcessor {
 
       case 'parentguid':
         // value is parent_guid field value
+        $parent_tid = 0;
         $query = db_select('feeds_item')
           ->fields('feeds_item', array('entity_id'))
           ->condition('entity_type', $this->entityType());
-        $parent_tid = $query->condition('guid', $value)->execute()->fetchField();
-        $target_term->parent[] = ($parent_tid) ? $parent_tid : 0;
+        $term_ids = array_keys($query->condition('guid', $value)->execute()->fetchAllAssoc('entity_id'));
+        if (!empty($term_ids)) {
+          $terms = entity_load($this->entityType(), $term_ids);
+          foreach ($terms as $term) {
+            if ($term->vid == $target_term->vid) {
+              $parent_tid = $term->tid;
+              break;
+            }
+          }
+        }
+        $target_term->parent[] = $parent_tid;
         break;
 
       case 'weight':
diff --git a/tests/feeds/terms.csv b/tests/feeds/terms.csv
new file mode 100644
index 00000000..31fad597
--- /dev/null
+++ b/tests/feeds/terms.csv
@@ -0,0 +1,3 @@
+guid,name,parent,parentguid
+1,Europe,,
+2,Belgium,Europe,1
\ No newline at end of file
diff --git a/tests/feeds_processor_term.test b/tests/feeds_processor_term.test
index 3e9c5cd0..9af79aca 100644
--- a/tests/feeds_processor_term.test
+++ b/tests/feeds_processor_term.test
@@ -120,4 +120,232 @@ class FeedsCSVtoTermsTest extends FeedsWebTestCase {
     $this->assertText(t('No vocabulary defined for Taxonomy Term processor.'));
   }
 
+  /**
+   * Tests that terms mapped to their parent by GUID are from the same vocabulary.
+   */
+  public function testParentTargetByGUID() {
+    // Create an other vocabulary.
+    $vocabulary1 = 'addams';
+    $vocabulary2 = strtolower($this->randomName());
+    $edit = array(
+      'name' => $this->randomString(),
+      'machine_name' => $vocabulary2,
+    );
+    $this->drupalPost('admin/structure/taxonomy/add', $edit, t('Save'));
+
+    // Add mappings for the first importer.
+    $this->addMappings('term_import',
+      array(
+        0 => array(
+          'source' => 'guid',
+          'target' => 'guid',
+          'unique' => TRUE,
+        ),
+        1 => array(
+          'source' => 'name',
+          'target' => 'name',
+        ),
+        2 => array(
+          'source' => 'parentguid',
+          'target' => 'parentguid',
+        ),
+      )
+    );
+
+    // Create a second importer.
+    $this->createImporterConfiguration('Term import 2', 'term_import2');
+    $this->setSettings('term_import2', NULL, array('content_type' => ''));
+
+    // Set and configure plugins and mappings.
+    $this->setPlugin('term_import2', 'FeedsFileFetcher');
+    $this->setPlugin('term_import2', 'FeedsCSVParser');
+    $this->setPlugin('term_import2', 'FeedsTermProcessor');
+    $this->setSettings('term_import2', 'FeedsTermProcessor', array('bundle' => $vocabulary2));
+
+    // Add mappings for the second importer.
+    $this->addMappings('term_import2',
+      array(
+        0 => array(
+          'source' => 'guid',
+          'target' => 'guid',
+          'unique' => TRUE,
+        ),
+        1 => array(
+          'source' => 'name',
+          'target' => 'name',
+        ),
+        2 => array(
+          'source' => 'parentguid',
+          'target' => 'parentguid',
+        ),
+      )
+    );
+
+    $values = array(
+      1 => 'Europe',
+      2 => 'Belgium',
+    );
+
+    // Import file using the first importer.
+    $this->importFile('term_import', $this->absolutePath() . '/tests/feeds/terms.csv');
+    $this->assertText('Created 2 terms.');
+
+    // Assert that two terms were created in the first vocabulary.
+    $terms = entity_load('taxonomy_term', array_keys($values));
+    foreach ($terms as $tid => $term) {
+      $this->assertEqual($values[$tid], $term->name);
+      $this->assertEqual($vocabulary1, $term->vocabulary_machine_name);
+    }
+    // Assert that the second term's parent is the first term.
+    $parents = taxonomy_get_parents($terms[2]->tid);
+    $message = format_string('The term @term is correctly linked to its parent.', array('@term' => $terms[2]->name));
+    if (!empty($parents)) {
+      $parent = current($parents);
+      $this->assertEqual(1, $parent->tid, $message);
+    }
+    else {
+      $this->fail($message);
+    }
+
+    $values = array(
+      3 => 'Europe',
+      4 => 'Belgium',
+    );
+
+    // Now import the file using the second importer.
+    $this->importFile('term_import2', $this->absolutePath() . '/tests/feeds/terms.csv');
+    $this->assertText('Created 2 terms.');
+
+    // Assert that two terms were created in the second vocabulary.
+    $terms = entity_load('taxonomy_term', array_keys($values));
+    foreach ($terms as $tid => $term) {
+      $this->assertEqual($values[$tid], $term->name);
+      $this->assertEqual($vocabulary2, $term->vocabulary_machine_name);
+    }
+    // Assert that the second term's parent is the first term.
+    $parents = taxonomy_get_parents($terms[4]->tid);
+    $message = format_string('The term @term is correctly linked to its parent.', array('@term' => $terms[4]->name));
+    if (!empty($parents)) {
+      $parent = current($parents);
+      $this->assertEqual(3, $parent->tid, $message);
+    }
+    else {
+      $this->fail($message);
+    }
+  }
+
+  /**
+   * Tests that terms mapped to their parent by GUID are from the same vocabulary.
+   */
+  public function testParentTargetByName() {
+    // Create an other vocabulary.
+    $vocabulary1 = 'addams';
+    $vocabulary2 = strtolower($this->randomName());
+    $edit = array(
+      'name' => $this->randomString(),
+      'machine_name' => $vocabulary2,
+    );
+    $this->drupalPost('admin/structure/taxonomy/add', $edit, t('Save'));
+
+    // Add mappings for the first importer.
+    $this->addMappings('term_import',
+      array(
+        0 => array(
+          'source' => 'guid',
+          'target' => 'guid',
+          'unique' => TRUE,
+        ),
+        1 => array(
+          'source' => 'name',
+          'target' => 'name',
+        ),
+        2 => array(
+          'source' => 'parent',
+          'target' => 'parent',
+        ),
+      )
+    );
+
+    // Create a second importer.
+    $this->createImporterConfiguration('Term import 2', 'term_import2');
+    $this->setSettings('term_import2', NULL, array('content_type' => ''));
+
+    // Set and configure plugins and mappings.
+    $this->setPlugin('term_import2', 'FeedsFileFetcher');
+    $this->setPlugin('term_import2', 'FeedsCSVParser');
+    $this->setPlugin('term_import2', 'FeedsTermProcessor');
+    $this->setSettings('term_import2', 'FeedsTermProcessor', array('bundle' => $vocabulary2));
+
+    // Add mappings for the second importer.
+    $this->addMappings('term_import2',
+      array(
+        0 => array(
+          'source' => 'guid',
+          'target' => 'guid',
+          'unique' => TRUE,
+        ),
+        1 => array(
+          'source' => 'name',
+          'target' => 'name',
+        ),
+        2 => array(
+          'source' => 'parent',
+          'target' => 'parent',
+        ),
+      )
+    );
+
+    $values = array(
+      1 => 'Europe',
+      2 => 'Belgium',
+    );
+
+    // Import file using the first importer.
+    $this->importFile('term_import', $this->absolutePath() . '/tests/feeds/terms.csv');
+    $this->assertText('Created 2 terms.');
+
+    // Assert that two terms were created in the first vocabulary.
+    $terms = entity_load('taxonomy_term', array_keys($values));
+    foreach ($terms as $tid => $term) {
+      $this->assertEqual($values[$tid], $term->name);
+      $this->assertEqual($vocabulary1, $term->vocabulary_machine_name);
+    }
+    // Assert that the second term's parent is the first term.
+    $parents = taxonomy_get_parents($terms[2]->tid);
+    $message = format_string('The term @term is correctly linked to its parent.', array('@term' => $terms[2]->name));
+    if (!empty($parents)) {
+      $parent = current($parents);
+      $this->assertEqual(1, $parent->tid, $message);
+    }
+    else {
+      $this->fail($message);
+    }
+
+    $values = array(
+      3 => 'Europe',
+      4 => 'Belgium',
+    );
+
+    // Now import the file using the second importer.
+    $this->importFile('term_import2', $this->absolutePath() . '/tests/feeds/terms.csv');
+    $this->assertText('Created 2 terms.');
+
+    // Assert that two terms were created in the second vocabulary.
+    $terms = entity_load('taxonomy_term', array_keys($values));
+    foreach ($terms as $tid => $term) {
+      $this->assertEqual($values[$tid], $term->name);
+      $this->assertEqual($vocabulary2, $term->vocabulary_machine_name);
+    }
+    // Assert that the second term's parent is the first term.
+    $parents = taxonomy_get_parents($terms[4]->tid);
+    $message = format_string('The term @term is correctly linked to its parent.', array('@term' => $terms[4]->name));
+    if (!empty($parents)) {
+      $parent = current($parents);
+      $this->assertEqual(3, $parent->tid, $message);
+    }
+    else {
+      $this->fail($message);
+    }
+  }
+
 }
-- 
GitLab