Problem/Motivation

I create a cck type with a field-collection field, the collection field contains a taxonomy term.

When I open the taxonomy term, no node is displayed, this message is displayed :There is currently no content classified with this term.

Comments

craigmc’s picture

Subscribing-- also seeing this behavior.

Content Type:
my_node_type
has an unlimited field-collection: my_field_collection

My_field_collection has a taxonomy term reference: my_term_ref

I create a new my_node_type and set a value for my_field_collection of Taxonomy_Term_1

When I go to the taxonomy/term page for Taxonomy_Term_!, I get "There is currently no content classified with this term".

odegard’s picture

I've just starting looking into this module so my advice/understanding might be way off.

My impression is that this module works sortof like a node reference, but referencing a collection of fields, not a node per se. In D7, content types are nothing BUT a collection of fields, so perhaps this module could, instead of defining it's own "content type" aka collection of fields, use an existing content type as fieldable entity in the main content type...?

ANYWAY, to solve your particular problem, I think you'd have to make your own tax/term views. Make a page taking term as argument. Then add the field collection as a reference, then pass the argument to the term in the collection...

You should think of the term ref field inside the field collection as a term field for that particular field collection instance, not automatically belonging to the node where the field collection is added!

I hope that made some sense.

This is a module with very high potential!

hbellahc’s picture

Hello

When you say : Then add the field collection as a reference

What it means please ?

Thanks in advance

odegard’s picture

Sorry, I meant "relation". In views, click on advanced, relations and add the field name for the collectible field. This will "open up" the terms belonging to the collectible fields field in the content type.

Not sure exactly how to proceed from here. I would probably use the page manager in ctools to get the term in the url as a context and passing it to the view like that.

Jessica A’s picture

subscribing

Tony Finlay’s picture

I've managed to get this working using views, if anyone wants to know how let me know here and I will write a tutorial, I am following this issue so will check regularly.

Jessica A’s picture

If you could write a tutorial on how to accomplish this in views, that would be greatly appreciated!!

blenny’s picture

This is because there is no content tagged with the term, therefore no content will be displayed on the term page. But i'm somewhat confused about what you're trying to do.

craigmc’s picture

all, the issue is that the taxonomy term relations from the field collection are not inherited back to the node that contains the field collection. Maybe this is by design, but I would imagine that if a given field collection (entity) were tagged with a given term, you would see something appear on the taxonomy/term page-- at least the field collection, if not the node that refers to it.

Take the analogy of a node reference. If the referenced node is tagged with a specific term, then the referenced node will appear in the /taxonomy/term page for that term. One would expect similar behavior from the referenced entity.

Ideally, since this module logically functions like the Multigroup CCK module from 6.x-3.x, we'd expect that if there are terms applied in the multigroup/field-collection, that they would apply to the containing node, hence why this issue is posted.

As for ways to solve this using Views, etc. Thanks for the offer. That may well be a work-around to achieve the desired result, but to my understanding of taxonomy, we at least should get the field-collection entity at taxonomy/term, if not the node itself. (Ideally the node itself).

aendra’s picture

Any updates on this? Or even better, any idea how to find a host-entity's NID given a particular taxonomy term attached within a field collection, whether as code or via Views?

I'm using field collection to do advanced author meta data and multiple authors, and am trying to create a page for each author showing which articles they've contributed to. Any help?

Thanks!

Tony Finlay’s picture

This module now has a 7 dev release; http://drupal.org/project/taxonomy_image. I haven't tried it yet but it seems to have the functionality I was originally looking for.

Hopefully it's of some use to the others in here

aendra’s picture

If it helps, I figured the easiest way to accomplish this was by accessing the SQL tables directly, and unhooking the taxonomy links associated with the vocabulary in question. Example below to list articles when taxonomy field named "field_byline_author" is within a field collection named "field_bylines".

<?php
/**
* @file
* Lists contributors by an author.
*
* Looks through field_collections and compiles a list of articles by author. URL style is site.com/author/Aendrew%20Rininsland
* 
*/


/**
* Implementation of hook_menu().
*/

function author_listing_menu (){
	$items = array();
	$items['author/%'] = array(
		'page callback' => 'author_listing_view',
		'page arguments' => array(1),
		'title callback' => 'author_listing_page_title',
		'title arguments' => array(1),		
		'access callback' => TRUE,
	);
	
	return $items;
}

function author_listing_page_title ($contributor) {
	return $contributor;
}

function author_listing_view ($author = NULL) {
	$tids = taxonomy_get_term_by_name($author, 'authors'); 
	
	$stories = author_listing_get_stories(current($tids)->tid);
	
	$element = 0;
	if (!empty($stories)){ 
		$output .= '<h3>Stories</h3>';
		foreach($stories as $story) {
			$output .= $story;
		}
	}
	
	$output .= theme('pager', array('element' => $element));
	return $output;
}

function author_listing_get_stories($tid) { //This is where all the real work is done
	$query = db_select('field_data_field_byline_author', 't'); //first, select the table containing information on the taxonomy field.
	$query->condition('field_byline_author_tid', $tid); //filter by term id
	$query->addField('t', 'entity_id'); //keep field entity_id -- this is used to get the node id from the field collection table
	$entities = $query->execute()->fetchCol();
	foreach ($entities as $entity) { 
		$query = db_select('field_data_field_bylines', 'b');    //field_bylines is my field collection
		$query->condition('field_bylines_value', $entity);    //the entity_id from the previous table translates to field_bylines_value
		$query->addField('b', 'entity_id');                            //entity_id here translates to the node id
		$stories[] = $query->execute()->fetchField();         //return as an array of nids. 
	}
	$query = db_select('node', 'n');     //I was just wanting links and titles; you can also just node_load_multiple($stories) instead
	$query->addField('n', 'title');
	$query->addField('n', 'nid');
	$query->addField('n', 'created');
	$query->condition('nid', $stories);
	$query->condition('status', 1);
	$query->orderBy('created', 'desc');
	$query = $query->extend('PagerDefault')->limit(10);
	$results = $query->execute()->fetchAll();
	foreach ($results as $result) { 
		$links[] = '<h5><a href="/node/' . $result->nid . '">' . $result->title . '</a> -- <em>' . date('F j, Y', $result->created) . '</em></h5>';
	}
	return $links; //return to function author_listing_view();
}

/**
 * Implementation of hook_entity_info_alter().
 *
 * Change non-functional taxonomy terms to point to this module. Via: erikwebb.net/blog/changing-url-all-taxonomy-terms
 */
function author_listing_entity_info_alter(&$entity_info) {
  $entity_info['taxonomy_term']['uri callback'] = 'author_listing_taxonomy_term_uri';
}


function author_listing_taxonomy_term_uri($term) {
  if ('authors' == $term->vocabulary_machine_name) { //taxonomy vocabulary is named "authors". Replace with whatever you called yours.
    return array(
      'path' => 'author/' . htmlentities($term->name),
    );
  }
  else { // don't do anything to all other vocabularies
    return array(
      'path' => 'taxonomy/term/' . $term->tid,
    );
  }
}
?>

Hope this helps someone -- I was scratching my head pretty furiously for awhile about how to manage this.

aendra’s picture

So, that moment when you spend several hours coding something, before realizing you actually *can* do what you're wanting to do in Views, in under ten minutes?

Using the example above (unlimited value field collection named "field_bylines" containing a taxonomy field "field_author" and text field "field_position"), you can accomplish pretty much the exact same thing by creating the following view:

1. Create a view, call it whatever you want. Make path something like "author/%"
2. Click Advanced, Add a Relationship. Choose your field collection; in this case, "Content: Bylines"
3. Add a Contextual Filter. This will be the taxonomy field (I.e., "field_author"), should appear named something like: "(field collection item from field_bylines) Field collection item: Author". Tell it not to display anything when filter value is not in the URL.

Tah-dah. Should work. If you want your field collection listed in the results instead of the default user creating the content:

4. Under Format, click "Content". Change to "Fields".
5. Under Fields, Click Add and select "Content: Bylines". Change formatter to "Fields Only" and uncheck "Create a label". (Last two are my preference to tidy UI up)

Note that you'll have to supply the author's term id to the view instead of the term name (I've never figured how to supply a term name as an argument as opposed to a tid...).

kalman.hosszu’s picture

Version: 7.x-1.0-beta2 » 7.x-1.x-dev
Component: User interface » Code
Priority: Normal » Major

I set the issue's properties.

tim.plunkett’s picture

Category: bug » feature
Priority: Major » Normal
Status: Active » Closed (duplicate)
Frippuz’s picture

Actually, I don't think doing this by code isn't a bad idea - if you want to support several fields at once.
The web I'm working on has 30+ fields with different vocabularies, and it wouldn't be feasible to add a view for each field.

I've made something similar split into two parts; one coded, and a quite simple view.

Part 1:2 - function to get the nids

Function to get the nids I want to get information from:

function my_module_get_termnids() {
  $path = request_path();
  $path = drupal_lookup_path('source', $path);
    
  if($path != ''){

    // Find out the tid from the URL
    $pos = strripos($path, '/');
    $tid = substr($path, $pos+1);
    $term = taxonomy_term_load($tid);
     
    $nids = cache_get('termnids:' . $tid);
    if($nids === FALSE) {

      $nids = array();
      // Get all fields using the vocabulary in question
      $fields = field_info_fields();
      foreach ($fields as $field) {
        if ($field['module'] == 'taxonomy' && $field['settings']['allowed_values'][0]['vocabulary'] == $term->vocabulary_machine_name){

          // Construct an array of nids using the field
          $result = db_query("SELECT entity_type, bundle, entity_id FROM " . 'field_data_' . $field['field_name'] . ' WHERE ' . $field['field_name'] .'_tid=:tid', array('tid'=>$tid) );
          foreach($result as $index => $row) {
            if($row->bundle == 'node') {
              $nids[$row->entity_id] = $row->entity_id;
            }
            else {
              $collection = entity_load('field_collection_item', array($row->entity_id));
              $collection = array_pop($collection);

              $inner = db_query("SELECT entity_type, entity_id FROM " . 'field_data_' . $collection->field_name . ' WHERE ' . $collection->field_name . '_value =:value', array('value' => $row->entity_id));
              foreach($inner as $idx => $col) {
                if($col->entity_type == 'node') {
                  $nids[$col->entity_id] = $col->entity_id;
                }
              }
            }
          }

          cache_set('termnids:' . $tid, $nids);
        }
      }
    }
    else{
      $nids = $nids->data;
    }
    return $nids;
  }

I guess I need to to something about those queries to make them secure, but the function works.
Due to the fact the function is pretty heavy, it also incorporates simple caching. I've added a clear cache in a hook_node_insert() function, but I think I need to rethink that when it clears the cache a bit too often.

cache_clear_all('termnids:', 'cache', true);

Part 2:2 - Views
To use this, I've created a view with a contextual filter in views. It's a nid filter set as a default PHP value :

return implode(',' ,my_module_get_termnids());

The filter is also set to allow multiple values.

The rest of the view is pretty straight forward. I'm using a panel display with a few fields and a exposed filter to handle the results. The panel is then placed into a custom page. I guess a views page would work as well.

I hope this can be of use to someone else.