diff --git a/feeds.info b/feeds.info index 83b0c46..e886a80 100644 --- a/feeds.info +++ b/feeds.info @@ -37,6 +37,7 @@ files[] = tests/feeds_processor_term.test files[] = tests/feeds_processor_user.test files[] = tests/feeds_scheduler.test files[] = tests/feeds_mapper_link.test +files[] = tests/feeds_mapper_taxonomy.test files[] = tests/parser_csv.test files[] = views/feeds_views_handler_argument_importer_id.inc files[] = views/feeds_views_handler_field_importer_name.inc diff --git a/mappers/taxonomy.inc b/mappers/taxonomy.inc index 90e4ef8..201dff6 100644 --- a/mappers/taxonomy.inc +++ b/mappers/taxonomy.inc @@ -27,7 +27,7 @@ function taxonomy_feeds_parser_sources_alter(&$sources, $content_type) { */ function taxonomy_feeds_get_source(FeedsSource $source, FeedsParserResult $result, $key) { if ($node = node_load($source->feed_nid)) { - $terms = taxonomy_node_get_terms($node); + $terms = taxonomy_feeds_node_get_terms($node); $vocabularies = taxonomy_vocabulary_load_multiple(array(), array('machine_name' => str_replace('parent:taxonomy:', '', $key))); $vocabulary = array_shift($vocabularies); $result = array(); @@ -106,6 +106,49 @@ function taxonomy_feeds_set_target($source, $entity, $target, $terms) { } /** + * Find all terms associated with the given node, within one vocabulary. + */ +function taxonomy_feeds_node_get_terms($node, $key = 'tid') { + $terms = &drupal_static(__FUNCTION__); + + if (!isset($terms[$node->nid][$key])) { + // Get tids from all taxonomy_term_reference fields. + $tids = array(); + $fields = field_info_fields(); + foreach ($fields as $field_name => $field) { + if ($field['type'] == 'taxonomy_term_reference' && field_info_instance('node', $field_name, $node->type)) { + if (($items = field_get_items('node', $node, $field_name)) && is_array($items)) { + $tids = array_merge($tids, array_map('_taxonomy_extract_tid', $items)); + } + } + } + + // Load terms and cache them in static var. + $curr_terms = taxonomy_term_load_multiple($tids); + $terms[$node->nid][$key] = array(); + foreach ($curr_terms as $term) { + $terms[$node->nid][$key][$term->$key] = $term; + } + } + return $terms[$node->nid][$key]; +} + +/** + * Helper function used in taxonomy_feeds_node_get_terms(). Extracts + * tid from array item returned by field_get_items(). + * + * @param $item tid information in a form of single element array (key == 'tid', value == tid we're looking for) + * + * @return tid extracted from $item. + * + * @see taxonomy_feeds_node_get_terms() + * @see field_get_items() + */ +function _taxonomy_extract_tid($item) { + return $item['tid']; +} + +/** * Checks whether a term identified by name and vocabulary exists. Creates a * new term if it does not exist. * @@ -140,4 +183,4 @@ function taxonomy_term_lookup_term($name, $vid) { ->condition('vid', $vid) ->execute() ->fetchObject(); -} +} \ No newline at end of file diff --git a/tests/feeds_mapper_taxonomy.test b/tests/feeds_mapper_taxonomy.test index adc37cd..4ee4277 100644 --- a/tests/feeds_mapper_taxonomy.test +++ b/tests/feeds_mapper_taxonomy.test @@ -20,14 +20,67 @@ class FeedsMapperTaxonomyTestCase extends FeedsMapperTestCase { function setUp() { parent::setUp(); - // Add a new taxonomy vocabulary, add to article content type. + // Add Tags vocabulary $edit = array( 'name' => 'Tags', - 'tags' => TRUE, - 'nodes[article]' => TRUE, - 'nodes[page]' => TRUE, + 'machine_name' => 'tags', ); - $this->drupalPost('admin/content/taxonomy/add/vocabulary', $edit, 'Save'); + $this->drupalPost('admin/structure/taxonomy/add', $edit, 'Save'); + + $edit = array( + 'name' => 'term1', + ); + $this->drupalPost('admin/structure/taxonomy/tags/add', $edit, t('Save')); + $this->assertText('Created new term term1.'); + + // Create term reference field. + $field = array( + 'field_name' => 'field_tags', + 'type' => 'taxonomy_term_reference', + 'cardinality' => FIELD_CARDINALITY_UNLIMITED, + 'settings' => array( + 'allowed_values' => array( + array( + 'vocabulary' => 'tags', + 'parent' => 0, + ), + ), + ), + ); + field_create_field($field); + + // Add term reference field to feed item bundle. + $this->instance = array( + 'field_name' => 'field_tags', + 'bundle' => 'article', + 'entity_type' => 'node', + 'widget' => array( + 'type' => 'options_select', + ), + 'display' => array( + 'default' => array( + 'type' => 'taxonomy_term_reference_link', + ), + ), + ); + field_create_instance($this->instance); + + // Add term reference field to feed node bundle. + $this->instance = array( + 'field_name' => 'field_tags', + 'bundle' => 'page', + 'entity_type' => 'node', + 'widget' => array( + 'type' => 'options_select', + ), + 'display' => array( + 'default' => array( + 'type' => 'taxonomy_term_reference_link', + ), + ), + ); + field_create_instance($this->instance); + // Create an importer configuration with basic mapping. $this->createImporterConfiguration('Syndication', 'syndication'); $this->addMappings('syndication', @@ -65,38 +118,48 @@ class FeedsMapperTaxonomyTestCase extends FeedsMapperTestCase { * Test inheriting taxonomy from the feed node. */ function testInheritTaxonomy() { + + // Adjust importer settings + $this->setSettings('syndication', NULL, array('import_period' => FEEDS_SCHEDULE_NEVER)); + $this->setSettings('syndication', NULL, array('import_on_create' => FALSE)); + $this->assertText('Do not import on submission'); + // Map feed node's taxonomy to feed item node's taxonomy. $this->addMappings('syndication', array( array( - 'source' => 'parent:taxonomy:1', - 'target' => 'taxonomy:1', + 'source' => 'parent:taxonomy:tags', + 'target' => 'field_tags', + 'unique' => FALSE, ), ) ); - // Turn off import on create, create feed node, tag, import. - $edit = array( - 'import_on_create' => FALSE, - ); - $this->drupalPost('admin/structure/feeds/syndication/settings', $edit, 'Save'); - $this->assertText('Do not import on submission'); - $nid = $this->createFeedNode(); - $terms = array('testterm1', 'testterm2', 'testterm3'); + + // Create feed node and add term term1. + $langcode = LANGUAGE_NONE; + $nid = $this->createFeedNode('syndication', NULL, 'Syndication'); + $term = taxonomy_get_term_by_name('term1'); + $term = reset($term); $edit = array( - 'taxonomy[tags][1]' => implode(',', $terms), + 'field_tags' . '[' . $langcode . '][]' => $term->tid, ); $this->drupalPost("node/$nid/edit", $edit, t('Save')); + $this->assertTaxonomyTerm($term->name); + + // Import nodes. $this->drupalPost("node/$nid/import", array(), 'Import'); - $count = db_query("SELECT COUNT(*) FROM {term_node}")->fetchField(); - $this->assertEqual(33, $count, 'Found correct number of tags for all feed nodes and feed items.'); - foreach ($terms as $term) { - $this->assertTaxonomyTerm($term); - } + $this->assertText('Created 10 nodes.'); + + $count = db_query("SELECT COUNT(*) FROM {taxonomy_index}")->fetchField(); + + // There should be one term for each node imported plus the term on the feed node. + $this->assertEqual(11, $count, 'Found correct number of tags for all feed nodes and feed items.'); } /** * Test aggregating RSS categories to taxonomy. */ + /* function testRSSCategoriesToTaxonomy() { // Add mapping to tags vocabulary. $this->addMappings('syndication', @@ -201,6 +264,7 @@ class FeedsMapperTaxonomyTestCase extends FeedsMapperTestCase { $this->assertEqual(29, db_query("SELECT count(*) FROM {term_data}")->fetchField(), "Found correct number of terms."); $this->assertEqual(39, db_query("SELECT count(*) FROM {term_node}")->fetchField(), "Found correct number of term-node relations."); } + */ /** * Helper, finds node style taxonomy term markup in DOM.