Not sure whether this request belongs here. However it would be great to provide an easy way to set up the several nodes of a user profile via tabs just like in the pageroute.module but without the edit.

Comments

fago’s picture

Hi!
That's currently only possible if you divide your profile into multiple nodes and use a pageroute for the user input process.

Then you get multiple nodes, and so multiple pages. So you can easily make links to all nodes and theme it as tabs.

Does this satisfy your needs?

aclight’s picture

This question relates to my question in the node family issues page (http://drupal.org/node/97354). I understand how to use pageroute to produce a logical order of editing the different nodes, but how do you pull up all related profile nodes unless you are at the top level node? I don't understand how you get the parent nodes of a child node.

aclight’s picture

Ok, fago just answered my above question on the node family issues board. I will post my code for doing profile tabs as soon as I get it working fully.

Axel_V’s picture

thanks. I'll move over to the tabbed menu discussion then.

Axel_V’s picture

Title: tabbed browsing for node profiles of a node family » code for tabbed browsing...

Hi Aclight. Trying to solve the tabbed browsing issue for user nodes myself but I'm not very experieced. I would very much appreciate to see your results once you've done with it. best, Axel

Axel_V’s picture

Hi Fago,

I've tried what you suggested. I had my profiles set up in multiple nodes already and I've now defined a page route for editing. That works more or less.

Now to the next step, displaying those user profiles, that is.
In my first version I had set up
- a view that lists specific users with names
- a nodefamiliy that contains the multiple profile nodes to be displayed together
- a modified node-usernode.tpl.php. that calls the parent and its children but listed from top to bottom

Now I want to display the multiple nodes via TABS instead and you said above:

So you can easily make links to all nodes and theme it as tabs.

Links to which nodes? Do you mean to the single pages of the pageroute? I know those URLs but that doesn't help, because the URLs only link to the respective profile page of the user who is logged in.

I'm a bit confused.

aclight’s picture

You need to link to the various nodes that make up your profile. If you have the following as your node family relationships:

usernode->content_type_a
usernode->conetnt_type_b

then you would want to link to both of those nodes (a and b) on your tabs.

I am working on doing this right now--I still have a few more bugs to work out, but it's almost working like I want. I'll post a howto of some form when I get them working--hopefully by the end of the weekend.

If you can't wait until I post a detailed howto, making the tabs themselves is easy--it's figuring out what tabs you need that's more difficult. Just do something like:

<div class="tabs">
<ul class="tabs secondary">
<li> Tab 1</li>
<li> Tab 2</li>
</ul>
</div>

Of course, you'll probably want the tab to link to the content type as well, so throw in a link in each li.

I'll post a follow up here when I put up a howto.

AC

Axel_V’s picture

Thanks for the advice, ac. I will wait though for your "how to"...
Axel

aclight’s picture

fago

Where should I put documentation for using tabs with node profiles? It seems to me that it would be a good idea for you to start a page in the documentation project and I could add a child under that. But if you would rather me do something else, let me know.

AC

fago’s picture

no, that's sound great. Just start a page for the nodeprofile modules in the handbook.
Don't hesitate to document as much as you like. Any contributions are welcome! :)

aclight’s picture

Component: Code » Documentation

I looked at the handbook and I didn't see a page for node profile. I don't have the knowledge or time to maintain the entire documentation entries for node profile, and since the handbook says that only the creator can edit a page (unless you have site administration privs), I was thinking that it would be best if you created a handbook page for node profile, and then I can add a child page detailing how to do the tabbed nodes. Is that possible?

AC

Axel_V’s picture

Hi AC. I don't want to be a pain but is there maybe the chance to post the tabbed browsing solution on this page for the time being or in a forum topic? As a soon as fago has managed to set up the handbook I guess it is not a huge problem to copy it there?! It would be an enormous help.
cheers, Axel

aclight’s picture

Ok.....this isn't totally polished, but will hopefully be at least somewhat useful. If anyone has suggestions on how to make it better or anything feel free to contribute.

I put the following code at the top of each template file for any nodeprofiles or usernode. So, in my case, that is node-usernode.tpl.php, node-content_user_profile.tpl.php, etc.)

Also, I haven't installed the most recent version of nodefamily yet (I'm still using the version that I created the patch for minimum status, from about a week ago). Therefore, this might not quite work or may return a slightly different result.

I haven't cleaned up the code, so there are still commented out debugging statements, etc.

<?php
<?php
  // status of node must be >= this value to be returned by the below calls.
  //  Use 0 to return all nodes or 1 to return only published nodes
 	$min_status = 1;
 	
  $parents = nodefamily_relation_load_parents($nid, $min_status);
//	msg_r("parents");
//	msg_r($parents);

  $children = nodefamily_relation_load($nid, $min_status);
//	msg_r("children");
//	msg_r($children);

 $siblings = nodefamily_relation_load_siblings($nid, $min_status);
//  msg_r("siblings");
//	msg_r($siblings);

?>
<?php // get all the content types so that the tabs can have the
			// readable name in the tab instead of the content_type
			// or automatically created node title   
   		$types  = node_get_types();
   		//$readable_type = $types['your_content_type'];
?> 	
  	<div class="content user_profile_content">
    <?php 
    // msg_r($node);
    
    // begin tab printing code
    // if there are any parent or child nodes for the current node, then make tabs
    // for those nodes and include the current node's tab between the parent
    // and child nodes.  If there are no parent or child nodes for the current
    // node, there is no need to print any tabs
		if (count($parents) + count($children) + count($siblings)) { ?>
			<div class="tabs">
			<ul class="tabs secondary">
			
			<?php
			// set minimum node status to create a tab for the node
			$min_status = 1;		// 1 = published
			
  		// print tabs for parents
   		if (count($parents)) {
        foreach ($parents as $parentnode) {
          if (node_access('view', $parentnode, $user->uid) && ($parentnode->status >= $min_status)) { ?>
   					<li><?php print l($types[$parentnode->type], 'node/'.$parentnode->nid) ?> </li> <?php
  	      }
        }
      }
      
      // print a tab for the current node
      ?>
      <li class="active"><?php print l($types[$node->type], 'node/'.$node->nid )?></li> <?php

  		
  		// print tabs for siblings of the current node
   		if (count($siblings)) {
   		  foreach ($siblings as $parent_of_sibling) {			// siblings of the same parent are returned within an array with index of parent node
          foreach ($parent_of_sibling as $siblingnode) {
            if (node_access('view', $siblingnode, $user->uid) && ($siblingnode->status >= $min_status)) { ?>
  					  <li><?php print l($types[$siblingnode->type], 'node/'.$siblingnode->nid) ?> </li>	<?php
  				  }
  				} 
        }
      } 
      	
  		// print tabs for children
   		if (count($children)) {
   		  foreach ($children as $childnode) {
          if (node_access('view', $childnode, $user->uid) && ($childnode->status >= $min_status)) { ?>
  					<li><?php print l($types[$childnode->type], 'node/'.$childnode->nid) ?> </li>	<?php
  				} 
        }
      } ?>
      </ul>
  		</div>
  		<?php
    }
		// end tab printing code ?>
?>

Let me know if you have any questions.

AC

Axel_V’s picture

Hi AC. Thanks a lot for that.

I've downloaded the latest nodefamily module

First: I think the first PHP opening tag <?php and the last end tag ?> should be deleted.

It works fine in so far as a tabbed version appears with the parent node upfront. However, if I click on one of the other tabs to the right, the respective node appears while the tabs disappear. Any ideas?

aclight’s picture

are you putting the entire block of code in the profile template file for EACH content type? If you are, try uncommenting some of the msg_r() statements to see if the function is finding the children nodes. I'm also not sure how many levels this function will dive down. I have only children of the main usernode, and it works for me, but I haven't tried the code if you have something like usernode->nodea->nodeb->nodec relationships. Though I would think that you should at least get the parent node and any siblings of any given node.

AC

Axel_V’s picture

StatusFileSize
new10.07 KB

Hi AC. Thanks for that hint. I have understood now that I need a tpl file for each of my content types that makes my usernode. I've got all the templates now and the tabs appear. However:

1. The tabs are there but strange things happen (see attached image). My parent is called Usernode. The children are Personal data and Contact data. Once I click one of the children, the other child appears twice.

2. I only know how to call the hole family and display the children as a list. I've got no clue how to call content of the node individually for each tpl. I tried a lot but my PhP skills are just to rudimentary. Maybe you can help.

thanks, xl

Axel_V’s picture

problem No 2 is solved. I just have to copy the code from node.tpl.php in the bottom of the respective_content_type_tpl.php
the strange duplicating tabs still appear.

Axel_V’s picture

Hi AC. The other problem is also solved. I really tend to post only when I think I've tried everything...In this case it was a problem with the nodefamily module.

There is one last think I can't solve: I've commented out the display of the parent node because I don't want to show the empty usernode. Now I've got the three children tabs. Whenever I click on one of them, the active tab jumps to the left. How can I achieve that the tabs stay where they are?

cheers, xl

aclight’s picture

The position of the tabs has to do with the order that the various nodefamily relation functions return the nodes, as well as the order in which the results of those functions are displayed (controlled by the code I gave you earlier that goes in the template files). I haven't looked too heavily into how to best do this, but there isn't an obvious way that I've seen to always keep the same order.

If what I said above isn't answering the right question, maybe you can provide another screenshot before and after you click on the tab to let me know exactly what your question is. I'm not sure I'm understanding your question correctly.

AC

Axel_V’s picture

StatusFileSize
new12.74 KB

Hi AC.
There are a few things actually. Please open the attached gif:

1. You can see what I described in my last post under 2. and 3.:
once I click on "Personal data" this tab 'jumps' to the left
same with "Contact data" and "Research Profile"

2. Usernode
I've commented out the section which prints the usernode because the usernode is empty. Therefore it does not appear in 2. and 3. However, when I click on a user's name to see his data it will bring me to a page like 1., including and starting with a usernode tab. That makes sense in respect to how the data are organized but is there a way not to display it?

3. Switching page names
Under 1. you see "Camille" which is the name of the user and obviously the title of the Usernode. I would actually prefer to have this usernode title on all of pages. Currently each tab calls its own content type title.

4. Changing names of content type title
This is a minor concern at the moment but I've recognized whenever a user edits one of the content types, the title changes, eg. from contact data to contact data 240 (see 3.)

Axel_V’s picture

In addition to my point 2: stupid me. I've obviously got a node-usernode.tpl.php which contains your tab code but is empty otherwise. However I would like not to display a page called usernode but go directly to the first child. How can I achieve that?

aclight’s picture

Ok, I can help you out a little with your questions, but not a lot.

1. This is because the code I posted orders tabs such that if the node currently being viewed is node x, the order of tabs will be:
all parents of node x; node x; all siblings of node x; all children of node x

The tab you click on jumps left (or to the middle) because the code is set to put the current tab to the left of sibling/children tabs. I guess you could change the tab code so that you first find the usernode of the user, and then find all children of the usernode, and display the tabs in that order. If you can't figure out how to do this, I might try this later today or tomorrow to see if it works. If you do get this to work how you want, let me know what the new code is. It looks like we're structuring our profiles in a very similar way.

2. I would also like to get rid of the display of the usernode, but I can't figure out a good way to do this. Let me explain. I have an override function in my template.php file that changes the link on any user's name from their user/uid page to node/usernode page. The code I use to do this is:

/**
* Catch the theme_profile_profile function, and redirect through the template api
*/
function phptemplate_user_profile($user, $fields = array()) {
  // Pass to phptemplate, including translating the parameters to an associative array. The element names are the names that the variables
  // will be assigned within your template.
  /* potential need for other code to extract field info */
  
  
  // redirect user to usernode page instead of standard drupal profile page
 	if (user_access('access user profiles')&& module_exist('usernode')) {
    $nid = usernode_get_node_id($user);
    $dest = drupal_get_destination();		// remember the original destination
    $output = drupal_goto('node/'. $nid, $dest);
  }

return _phptemplate_callback('user_profile', array('user' => $user, 'fields' => $fields));
  }

This function uses the usernode_get_node_id() function, which returns the nid of the usernode, and so that's the page that the user is directed to. Unfortunately a usernode is not a CCK node type, and therefore can't hold profile information on its own. I suppose you could use the function above but instead of redirecting to the usernode you could find the nid of the child node of a certain content type (assuming there is only 1 of that type) and then redirect the user to that page. I think that would get rid of the usernode tab. There might be a better way to do this, however. Fago may have some suggestions??

3. I haven't tried to do this yet, but it's on my list of things to do. I've looked into this a little bit and there wasn't an obvious solution. If you figure it out let me know how you did it--otherwise, I'll let you know if/when I figure it out.

4. are you using the auto_nodetitle module? If so, that's probably the reason. If not, I'm not sure.

I hope this helps
AC

Axel_V’s picture

Thanks a lot AC. I think I'll call it a day. Getting a bit dizzy after 15 hours in front of the screen. I'll have a closer look at your stuff tomorrow. You've been a huge help so far. I'm not sure if I can support you with the code but I try. But once we've sorted this out I'll be happy to do the documentation!
xl

aclight’s picture

Regarding coments #20 and #22 issue 3 (setting the displayed title for the page to be the user's name), here is something I wrote that seems to work fairly well. There may be a better way to do this, but I haven't come across one yet.

In your page.tpl.php file, add the following block of code after the html ..... line:

	
	// overrides the title (browser and displayed) of the node if the content type is one of those
	// used for profiles.  Checks for specific conetnt types need to be added here manually
	
	// set up default values of $head_title_override and $title_override
 	$head_title_override = $head_title;
 	$title_override = $title;	 	
	
	// first, check to see if this is a node.  If not, don't override the titles
	if ( arg(0) == 'node' && is_numeric(arg(1)) ) {
  	$node = node_load(arg(1)); 
  	if (is_object($node)) {
    	// get the readable names of node content types
    	$types  = node_get_types();

      // put any content types in this array for which you want to override the title
      $override_types = array('usernode', 'content_user_profile', 'content_secondary_user_profile');
   
      if (in_array($node->type, $override_types)) {
      	// override the title of this node
      	switch($node->type) {
      		case 'usernode':
      		case 'content_user_profile':
      		case 'content_secondary_user_profile':
      			$title_override = $node->name;
      			$head_title_override = $node->name.' | '.$types[$node->type];
      			break;
      	}
      }
	 	} 
	 }

Then, later on in the file, find the line:
<title><?php print $head_title ?></title>
and change it to read
<title><?php print $head_title_override ?></title>
Also find the line
<h1 class="title"><?php print $title ?></h1>
and change it to read
<h1 class="title"><?php print $title_override ?></h1>

This will cause the name of the user who created the node to be displayed as the title of the page, and the title in the browser bar will be the name and the readable name of the content type. Change those to suit your needs. Make sure to also add the content types of which you want to override the title to the array $override_types. If you want to have different behaviors depending on the content type, you can add additional cases to the switch() block.

Let me know if you have questions about this.
AC

aclight’s picture

Regarding comments #20 and #22, point 2, I've now got that working as well.
Use the code below to replace the code that I gave you earlier. Note that I think this will only work with the immediate children of the usernode. I don't believe that grandchildren will be displayed given just this code alone. Put this code in all of the template files for your different children node types of the usernode.

<?php
  // status of node must be >= this value to be returned by the below calls.
  //  Use 0 to return all nodes or 1 to return only published nodes
 	$min_status = 1;
 	
 	$user->uid = $node->uid;
 	$usernode_nid = usernode_get_node_id($user);
	$first_children = nodefamily_relation_load($usernode_nid, $min_status);

?>

<?php
		// get all the content types so that the tabs can have the
		// readable name in the tab instead of the content_type
		// or automatically created node title   
   	$types  = node_get_types();
?>
  	<div class="content user_profile_content">
    <?php 
    // msg_r($node);
    
    // begin tab printing code
    // if there are any child nodes for the current node, then make tabs
    // for those nodes 
		if (count($first_children)) { ?>
			<div class="tabs">
			<ul class="tabs secondary">
			
			<?php
			// set minimum node status to create a tab for the node
			$min_status = 1;		// 1 = published
			
  		// print tabs for parents
   		if (count($first_children)) {
        foreach ($first_children as $childnode) {
          if (node_access('view', $childnode, $user->uid) && ($childnode->status >= $min_status)) { 
          	if ($childnode->nid == $node->nid) {
          		// show that this is the active node ?>
          		<li class="active"><?php print l($types[$childnode->type], 'node/'.$childnode->nid )?></li>
          		
          	<?php	
          	} else {
          		// this is not the active node ?>
   					<li><?php print l($types[$childnode->type], 'node/'.$childnode->nid) ?> </li> <?php
   					}
  	      }
        }
      }
     }
     ?>
    </ul>
  	</div>

I'm still working on tweaking the code that goes into the template.php file that links to the content type that you want to be your user profile, instead of the usernode. I'll post that code when I get it working right.

I hope this helps

AC

Axel_V’s picture

Hi AC,
If you would be here now you would see a very, very happy man. Thank you so much! This is exactly what I need. I wished my skills would be sufficient to support you. As mentioned before: once everything is done I'd be happy to pull this all together for the documentation if you want me to. Given the case that fago has set up a Handbook section for the nodefamily module til then.
xl

Axel_V’s picture

something else has now appeared: I want to have one tab that gives a list of documents uploaded by the chosen user. The documents are of one content type called student_document. I know how to call a list of these documents. The problems is though that the code currently produces a tab for each node of a content type. If I have 10 nodes of the type student_document I get 10 tabs, each containing the same list with all 10 documents. The possible solutions I can think about at the moment:
- having an additional content type that is distributed to all users once and that contains a list of the content type student_document (the user nodes does this currently. So it might use it anyway)
- an addition in the code that says something like: for the content type "student document" only print one tab
- an addition in the code that prints exactly one tab for each content type

Unfortunately I don't know how to solve this. I'll give it a try though. But maybe you've got a quick fix.

aclight’s picture

Since you don't want to display the usernode, I think I would go with displaying the usernode but changing the usernode template file to display a list of your files instead of what it might normally display. If you use the following code in place of previous versions in your template files for the various content types, I think you'll have what you want.

<?php
  // status of node must be >= this value to be returned by the below calls.
  //  Use 0 to return all nodes or 1 to return only published nodes
 	$min_status = 1;
 	
 	$user->uid = $node->uid;
 	$usernode_nid = usernode_get_node_id($user);
	$first_children = nodefamily_relation_load($usernode_nid, $min_status);

?>

<?php
		// get all the content types so that the tabs can have the
		// readable name in the tab instead of the content_type
		// or automatically created node title   
   	$types  = node_get_types();
?>
  	<div class="content user_profile_content">
    <?php 
    // msg_r($node);
    
    // begin tab printing code
    // if there are any parent or child nodes for the current node, then make tabs
    // for those nodes and include the current node's tab between the parent
    // and child nodes.  If there are no parent or child nodes for the current
    // node, there is no need to print any tabs
		if (count($first_children)) { ?>
			<div class="tabs">
			<ul class="tabs secondary">
			
			<?php
			// set minimum node status to create a tab for the node
			$min_status = 1;		// 1 = published
			
  		// print tabs for parents
   		if (count($first_children)) {
        foreach ($first_children as $childnode) {
          if (node_access('view', $childnode, $user->uid) && ($childnode->status >= $min_status)) { 
          	if ($childnode->nid == $node->nid) {
          		// show that this is the active node ?>
          		<li class="active"><?php print l($types[$childnode->type], 'node/'.$childnode->nid )?></li>
          		
          	<?php	
          	} else {
          		// this is not the active node ?>
   					<li><?php print l($types[$childnode->type], 'node/'.$childnode->nid) ?> </li> <?php
   					}
  	      }
        }
      }
      
      // load the usernode
      $usernode = node_load(array('nid' => $usernode_nid));
      
      // print usernode tab which could be used to hold a list of files, for example
      if (node_access('view', $usernode, $user->uid) && ($usernode->status >= $min_status)) { 
      	if ($usernode->nid == $node->nid) {
      		// show that this is the active node ?>
      		<li class="active"><?php print l('Tab Title', 'node/'.$usernode->nid )?></li>
      		
      	<?php	
      	} else {
      		// this is not the active node ?>
				<li><?php print l('Tab Title', 'node/'.$usernode->nid) ?> </li> <?php
				}
      }
      
     }
     ?>
  </ul>
  </div>

Replace 'Tab Title' with the name you want to be displayed for the tab.

Does that accomplish what you want it to?

AC

Axel_V’s picture

Hi AC. Works like a treat. Just one last thing: The document tab that I've now created via the usernode shows on the outer right side which is perfect. However, as it is actually a usernode in disguise and thus the parent of the other tabs, it is always the first tab that is displayed. Is there a chance to avoid that? Ideally I would l like to start with the first tab on the left side, the first child that is. I can live with the status quo for the moment. I've got more than I've expected anyway. But if there is a quick fix please tell me.
Thank you very much,
xl

aclight’s picture

I'm afraid I don't understand what your problem is. Can you post a screenshot?

AC

Axel_V’s picture

StatusFileSize
new14.07 KB

Hi AC. If you open the image:
1 is what I would like to see as the first screen when I click on the name Stanza in my user list
2 is what I get.
This is because "Documents" is my usernode in disguise and if you click on Stanza it will automatically go to the usernode, the parent node that is. Is there a way around this?

cheers, xl

aclight’s picture

Ok, I see what you mean. That should be easy to fix.

Add (or edit) the following function to your theme's template.php file (assuming you are using a phptemplate based theme, which it looks like you are).

/**
* Catch the theme_profile_profile function, and redirect through the template api
*/
function phptemplate_user_profile($user, $fields = array()) {
  // Pass to phptemplate, including translating the parameters to an associative array. The element names are the names that the variables
  // will be assigned within your template.
  /* potential need for other code to extract field info */
  
  
  // redirect user to usernode page instead of standard drupal profile page
 	if (user_access('access user profiles')&& module_exist('usernode')) {
    $nid = usernode_get_node_id($user);
    if (module_exist('nodefamily') && $nid) {
    	$min_status = 1;
    	$usernode_children = nodefamily_relation_load($nid, $min_status);
    	if (count($usernode_children)) {
        foreach ($usernode_children as $childnode) {
          if (node_access('view', $childnode, $user->uid) && ($childnode->status >= $min_status)) { 
          	if ($childnode->type = 'content_user_profile') {
    					$dest = drupal_get_destination();		// remember the original destination
    					$output = drupal_goto('node/'. $childnode->nid, $dest);
    					return _phptemplate_callback('user_profile', array('user' => $user, 'fields' => $fields));
          	}
          }
        }
      }
    }
    $dest = drupal_get_destination();		// remember the original destination
    $output = drupal_goto('node/'. $nid, $dest);
  }

return _phptemplate_callback('user_profile', array('user' => $user, 'fields' => $fields));
}

Replace content_user_profile with the content type which you want links of users' names to point to.
Doing the above will redirect users from the real profile page for a user to your usernode/nodeprofile based page.

If you instead want the link of every user to point directly to their usernode/nodeprofile based page, you will also need to add/edit this function in your template.php file for the theme.

/**
 * Catch the theme_username function and link to the usernode instead of linking to the userpage
 */

function phptemplate_username(&$object) {

  if ($object->uid && $object->name) {
   	
  	// display the user's real name.  First, we want to see if the user has a nickname
  	// stored, and if so we use that as the first name.  Then, we add the last name
  	// and display the name
  	
  	// name lookup
		
  	$user->uid = $object->uid;

		get_real_name($user);
		if (isset($user->name)) {
			$object->name = $user->name;
		}
  	// end name lookup
   	
    // Shorten the name when it is too long or it will break many tables.
    if (drupal_strlen($object->name) > 20) {
      $name = drupal_substr($object->name, 0, 15) .'...';
    }
    else {
      $name = $object->name;
    }
	$output = check_plain($name);

    //if (user_access('access user profiles') && module_exist('usernode')) {
 		if (user_access('access user profiles')&& module_exist('usernode')) {			// dont make a link for anonymous users since they can't access the profile anyway
      $nid = usernode_get_node_id($object);
      // set default value of $output
			$output = l($name, 'node/'. $nid, array('title' => t('View user details.')));
			if (module_exist('nodefamily') && $nid) {
      	$min_status = 1;
      	$usernode_children = nodefamily_relation_load($nid, $min_status);
      	if (count($usernode_children)) {
          foreach ($usernode_children as $childnode) {
            if (node_access('view', $childnode, $user->uid) && ($childnode->status >= $min_status)) { 
            	if ($childnode->type = 'content_user_profile') {
      					$output = l($name, 'node/'. $childnode->nid, array('title' => t('View user details.')));
            	}
            }
          }
        }
    	}
     // $output = l($name, 'node/'. $nid, array('title' => t('View user details.')));
    }
    else {
      $output = check_plain($name);
    }
  }
  else if ($object->name) {
    // Sometimes modules display content composed by people who are
    // not registered members of the site (e.g. mailing list or news
    // aggregator modules). This clause enables modules to display
    // the true author of the content.
    if ($object->homepage) {
      $output = l($object->name, $object->homepage);
    }
    else {
      $output = check_plain($object->name);
    }

    $output .= ' ('. t('not verified') .')';
  }
  else {
    $output = variable_get('anonymous', 'Anonymous');
  }

  return $output;
}

Once again, change content_user_profile to whatever you are using. You might also need to change the code a little if you are allowing anonymous users to view user profiles.

This function is called by the one above, and you may need to modify the call or the function or just get rid of it completely, depending on your setup. It also goes in the template.php file.

/**
 * get the real name of a user based on their id
 */

function get_real_name(&$object) {
	if (isset($object->uid)) {
		$user->uid = $object->uid;
		profile_load_profile($user);
  	$user_name_string = "";
  	if (!empty($user->profile_nickname)) {
  		$user_name_string = $user_name_string.$user->profile_nickname." ";
  	} elseif (!empty($user->profile_fn)) {		// first name
  		$user_name_string = $user_name_string.$user->profile_fn." ";
  	}
  	if (!empty($user->profile_ln)) {		// last name
    	$user_name_string = $user_name_string.$user->profile_ln;
  	}
  	if (!empty($user_name_string)) {
  		$user->name = $user_name_string;
  		$object->name = $user_name_string;
  	}
	}
}

I think this should take care of your problem--let me know if you have questions.

AC

Axel_V’s picture

StatusFileSize
new5.29 KB

thanks a lot AC. I've tried it and got several questions.

1. Between the two big junks of code you write:

Doing the above will redirect users from the real profile page for a user to your usernode/nodeprofile based page.
If you instead want the link of every user to point directly to their usernode/nodeprofile based page, you will also need to add/edit this function in your template.php file for the theme.

I do not really understand the difference between the two.

2. I tried the following:
- I had an older phptemplate_username function and I exchanged it for yours.
- I commented out the 'name lookup' becaue it caused trouble in connection with calling the get_real_name function.
- I changed the node type to 'content_personal_data'.
What I get then is what you see in the attached image. 'Documents' on the right side is my usernode in disguise. Your code seems to work in the sense that clicking on a user name doesn't any longer lead to documents(=usernode). However, it seems not to find the node I've redirected to and as a consequence it chooses the one next to the usernode. ('Research profile' in my example).
I've also tried to redirect to the other node type 'content_contact_data' with the same result
I then added your phptemplate_user_profile function with the correct node name but still I get the same result

3. Nodeprofile
You talk about nodeprofiles. I have the module installed and I know that I can switch individual content types to be nodeprofiles. I don't really understand what it does though. It seems that whole nodefamily thing works without it. But to make sure that this isn't the issue I switched the content type 'content_personal_data' that I want to redirect to into a nodeprofile. The result wasn't different though. Do all of the nodefamily content types have to be nodeprofiles?

any ideas? thanks, xl

Axel_V’s picture

My confusion around the nodeprofile has been resolved (point 3). I understand now that marking a content type as a nodeprofile automatically establishes a child relationship with the the usernode (=parent) which automatically shows in the nodefamily settings. However, point 1 and specifically point 2 are still unresolved. Any hints would be very much appreciated.
xl

aclight’s picture

regarding comment #33:

point 1: When you use the function phptemplate_username() to provide a link to the user's nodeprofile instead of true user profile, that works in most places. However, I found that there were still some links that remained to the user profile (maybe because the theme function wasn't being called in those places). Since my goal was to completely eliminate access of users to their own user profile, I didn't want people to end up being able to directly view or edit their user profile, so I also added the code in phptemplate_user_profile() that redirects the user to their nodeprofile if they happen to get to their user profile. In some cases (especially while in development) it is convenient to not redirect from the user profile to the nodeprofile, and so you may want to comment out that section (or not use it at all, if you want it to be possible for users to see their user profile). I'm using LDAP authentication on my system, so I have no need for users to be able to change their passwords, for example, and I've written functions in other places that allow for synchronization of certain fields of a nodeprofile to the actual user profile fields.

point 2:
These three lines in my phptemplate_username() function determine the actual link that is used when a user's name is clicked on:

            	if ($childnode->type = 'content_user_profile') {
      					$output = l($name, 'node/'. $childnode->nid, array('title' => t('View user details.')));
            	}

If you have replaced 'content_user_profile' with 'content_personal_data' it should work unless for some reason that statement never evaluates to true, in which case I guess I'm not quite sure what would happen, but I don't think you would get a link at all. Try putting in some debugging statements around that area to see if the value of the various variables matches what you expect. Also, you could post your code for that function and I'll look at it to make sure you edited it right. Other than that, I'm not sure what's going on.

AC

Axel_V’s picture

Thanks a lot AC for the detailed description (point 1). I do understand now. As for point 2: I've changed a few things and came to the conclusion that it is better to do my filelist in a new content type rather than on the usernode. Therefore I' would prefer a solution that doesn't show the usernode at all. You've mentioned that this was the way you were going for your site anyway. I wonder wether you have already solved that issue and whether I might ask you another time for your precious help?
BTW: is there a way to show the user/atavar image in one of the node profiles? The usal 'print $user->picture' only works in connection with the usernode
cheers, xl

Axel_V’s picture

Hi AC. Don't bother for the moment. I have to rethink...

Axel_V’s picture

... I have rethought. And I stick to what I've posted in #36. So if there is a chance you can help me that would be fantastic.
cheers, xl

Axel_V’s picture

stupid me again. It is very easy to get rid of the usernode tab. I just commented out the element that loads the usernode. Again: Thank you very, very much for your help, AC! That was amazing. And if you come across an easy solution for getting the user image or other elements of the user page into the node profiles it would be great if you could let me know. Thanks again!
xl

aclight’s picture

To print the user's picture from their usernode, I use the following bit of code in my usernode template file:

<?php 
// print users picture by calling theme function to print picture
if (function_exists('phptemplate_user_picture')) {
	print phptemplate_user_picture($user);
} else {
	print theme_user_picture($user);
}
?>

That code calls phptemplate_user_picture() if it exists. I don't see why this wouldn't work from any other nodeprofile template file.

function phptemplate_user_picture(&$account) {
  if (variable_get('user_pictures', 0)) {
     if ($account->picture && file_exists($account->picture)) {
        $picture = file_create_url($account->picture);
      }
      else if (variable_get('user_picture_default', '')) {
        $picture = variable_get('user_picture_default', '');
      }
  
      if (isset($picture)) {
        $alt = t('%user\'s picture', array('%user' => $account->name ? $account->name : variable_get('anonymous', 'Anonymous')));
        $picture = theme('image', $picture, $alt, $alt, '', false);
 
        if (!empty($account->uid) && user_access('access user profiles') && module_exist('usernode')) {
          $nid = usernode_get_node_id($account);		// node id of the user's usernode
          $picture = l($picture, "node/$nid", array('title' => 'View user details.'), NULL, NULL, FALSE, TRUE);
        }
        return "<div class=\"picture\">$picture</div>";
      }
    }
  
} 

AC

Axel_V’s picture

Hi AC,
I tried everything (nearly I guess) but I still can't call the image from a different node nor can I point to an individual node as the default active tab (my post #33, point 2). Everything else runs absolut smoothly. Here is the code of my template.php:

<?php
function phptemplate_user_picture(&$account) {
  if (variable_get('user_pictures', 0)) {
     if ($account->picture && file_exists($account->picture)) {
        $picture = file_create_url($account->picture);
      }
      else if (variable_get('user_picture_default', '')) {
        $picture = variable_get('user_picture_default', '');
      }
 
      if (isset($picture)) {
        $alt = t('%user\'s picture', array('%user' => $account->name ? $account->name : variable_get('anonymous', 'Anonymous')));
        $picture = theme('image', $picture, $alt, $alt, '', false);
 
        if (!empty($account->uid) && user_access('access user profiles') && module_exist('usernode')) {
          $nid = usernode_get_node_id($account);        // node id of the user's usernode
          $picture = l($picture, "node/$nid", array('title' => 'View user details.'), NULL, NULL, FALSE, TRUE);
        }
        return "<div class=\"picture\">$picture</div>";
      }
    }
 
} 
?>
<?php
/**
 * Catch the theme_username function and link to the usernode instead of linking to the userpage
 */

function phptemplate_username(&$object) {

  if ($object->uid && $object->name) {
       
      // display the user's real name.  First, we want to see if the user has a nickname
      // stored, and if so we use that as the first name.  Then, we add the last name
      // and display the name
     
      // name lookup
       
    //  don't need the following at the moment:
	/*$user->uid = $object->uid;

        get_real_name($user);
        if (isset($user->name)) {
            $object->name = $user->name;
        }
		
	*/
      // end name lookup
       
    // Shorten the name when it is too long or it will break many tables.
    if (drupal_strlen($object->name) > 20) {
      $name = drupal_substr($object->name, 0, 15) .'...';
    }
    else {
      $name = $object->name;
    }
    $output = check_plain($name);

    //if (user_access('access user profiles') && module_exist('usernode')) {
         if (user_access('access user profiles')&& module_exist('usernode')) {           
		  // dont make a link for anonymous users since they can't access the profile anyway
      $nid = usernode_get_node_id($object);
      // set default value of $output
            $output = l($name, 'node/'. $nid, array('title' => t('View user details.')));
            if (module_exist('nodefamily') && $nid) {
          $min_status = 1;
          $usernode_children = nodefamily_relation_load($nid, $min_status);
          if (count($usernode_children)) {
          foreach ($usernode_children as $childnode) {
            if (node_access('view', $childnode, $user->uid) && ($childnode->status >= $min_status)) { 
                if ($childnode->type = 'content_personal_data') {

                          $output = l($name, 'node/'. $childnode->nid, array('title' => t('View user details.')));
                }
            }
          }
        }
        }
	
    }
    else {
      $output = check_plain($name);
    }
  }
  else if ($object->name) {
    // Sometimes modules display content composed by people who are
    // not registered members of the site (e.g. mailing list or news
    // aggregator modules). This clause enables modules to display
    // the true author of the content.
    if ($object->homepage) {
      $output = l($object->name, $object->homepage);
    }
    else {
      $output = check_plain($object->name);
    }

    $output .= ' ('. t('not verified') .')';
  }
  else {
    $output = variable_get('anonymous', 'Anonymous');
  }

  return $output;
}
?>

and here the code for the node that should be the active tab and should contain the image (node-content_personal_data.tpl.php) BTW: I tried the other nodes I have as well.

<?php
  // status of node must be >= this value to be returned by the below calls.
  //  Use 0 to return all nodes or 1 to return only published nodes
     $min_status = 1;
     
     $user->uid = $node->uid;
     $usernode_nid = usernode_get_node_id($user);
    $first_children = nodefamily_relation_load($usernode_nid, $min_status);

?>

<?php
        // get all the content types so that the tabs can have the
        // readable name in the tab instead of the content_type
        // or automatically created node title   
       $types  = node_get_types();
?>
<div class="content user_profile_content">

<?php 
    // msg_r($node);
   
    // begin tab printing code
    // if there are any parent or child nodes for the current node, then make tabs
    // for those nodes and include the current node's tab between the parent
    // and child nodes.  If there are no parent or child nodes for the current
    // node, there is no need to print any tabs
        if (count($first_children)) { ?>
<div class="tabs">
<ul class="tabs primary">
<?php
            // set minimum node status to create a tab for the node
            $min_status = 1;        // 1 = published
           
          // print tabs for parents
           if (count($first_children)) {
        foreach ($first_children as $childnode) {
          if (node_access('view', $childnode, $user->uid) && ($childnode->status >= $min_status)) { 
              if ($childnode->nid == $node->nid) {
                  // show that this is the active node ?>
<li class="active"><?php print l($types[$childnode->type], 'node/'.$childnode->nid )?></li>

<?php   
              } else {
                  // this is not the active node ?>
<li><?php print l($types[$childnode->type], 'node/'.$childnode->nid) ?> </li> <?php
                       }
            }
        }
      }
     }
     ?>
</ul>
</div>	

  <div class="node">
  <?php if ($sticky) { print " sticky"; } ?><?php if (!$status) { print " node-unpublished"; } ?>
    <?php if ($picture) {
      print $picture;
    }?>			
    <?php if ($page == 0) { ?><h2 class="title"><a href="<?php print $node_url?>"><?php print $title?></a></h2><?php }; ?>
    <span class="submitted"><?php print $submitted?></span>
    <span class="taxonomy"><?php print $terms?></span>
<?php 
// print users picture by calling theme function to print picture
if (function_exists('phptemplate_user_picture')) {
    print phptemplate_user_picture($user);
} else {
    print theme_user_picture($user);
}
?>
    <div class="content"><?php print $content?></div>
    <?php if ($links) { ?><div class="links">&raquo; <?php print $links?></div><?php }; ?>
  </div>

any ideas? Your help would be very much appreciated.
cheers, xl

aclight’s picture

It's not obvious to me why you're having the problems you're having, but if I were in your situation I would try to insert some debugging statements at various places to see what's happening.

First of all, I like to use these two axillary functions which print objects and arrays in a way that makes them fairly easy to read. The code is originally from the LDAP integration module, in the libdebug.php file. I think they should work if you just put these two functions in your template.php file, though I'm not positive. The functions are:


function msg($string) {
  drupal_set_message("<pre style=\"border: 0; margin: 0; padding: 0;\">$string</pre>");
}

function msg_r($object) {
  msg(print_r($object, true));
}

Now that you've done that, go into your template file, and find this section of code below and add in the debug statements as so:

// print users picture by calling theme function to print picture
if (function_exists('phptemplate_user_picture')) {
  msg_r('function exists'); 
  print phptemplate_user_picture($user);
} else {
  msg_r('no function');
  print theme_user_picture($user);
}

Then view that content type and see what is printed towards the top of the page. If you see 'function exists' then you know what part of the if statement is evaluating to true. If that's the case, go to your phptemplate_user_picture() function and try to add some debugging statements. You might try something like this below:

function phptemplate_user_picture(&$account) {
  if (variable_get('user_pictures', 0)) {
msg_r('1');
     if ($account->picture && file_exists($account->picture)) {
msg_r('2');
        $picture = file_create_url($account->picture);
      }
      else if (variable_get('user_picture_default', '')) {
msg_r('3'); 
       $picture = variable_get('user_picture_default', '');
      }
 
      if (isset($picture)) {
msg_r('4'); 
       $alt = t('%user\'s picture', array('%user' => $account->name ? $account->name : variable_get('anonymous', 'Anonymous')));
        $picture = theme('image', $picture, $alt, $alt, '', false);
 
        if (!empty($account->uid) && user_access('access user profiles') && module_exist('usernode')) {
msg_r('5'); 
         $nid = usernode_get_node_id($account);        // node id of the user's usernode
          $picture = l($picture, "node/$nid", array('title' => 'View user details.'), NULL, NULL, FALSE, TRUE);
        }
        return "<div class=\"picture\">$picture</div>";
      }
    }
 
} 

Then load the page again and see what prints. Depending on what numbers print, you should be able to figure out which parts of this code are being evaluated. You should see the numbers 1, 2, 4, and 5 printed out if the user has a valid picture. You can also use debugging statements like msg_r($picture);, msg_r($user);, msg_r($node);, etc. to print out the actual contents of variables, arrays, and objects.

Play around with this some and try to figure out where the problem is. Like I said, this code works on my system, and though I'm not claiming that the code is perfect or that there are not errors, it's hard for me to figure out what's going wrong for you since you're using pretty much the same code and it's not working.

AC

Axel_V’s picture

Hi AC. Thanks a lot.

I've applied your debug statements with the following result:
- when I go to "my account" where I can see my image I do get the expected result: "1, 2, 4, 5."
- With the respective content type which should display the image it says "function exists" and "1."
I don't know what to make out of this. Any ideas?

I don't know if this is related but I played around with your earlier posts and realised that your function phptemplate_user_profile (post #32, top) brings the wished result in that respect that it always jumps to the active node that I've defined in the function. As I've mentioned before this doesn't work with the function phptemplate_username (post #32, bottom). As I want my users to access their accounts I will have to use the _username function.

Could it be that the problem lies somewhere in the _username function?

cheers, xl

liquidcms’s picture

don't want to spoil this excellent thread.. but what I am trying to do seems like it must be VERY close to this.

basically I am trying to make a user profile page.

this page has various collections of info specific to the user that, so far, have all been created as tabbed views.

at the top of the page I also have a block which is a themed view of a usernode (basically I just grab the uid and then pull in everything else I need in the tpl file for the block).

I have gotten quite a ways down this path and just realized I don't have a solid plan to include a method the user to edit his "profile" info as part of this user page. And, by profile info I mean the user info (username, email, password) AND his various usernodes.
unlike the results from this thread I don't really ever need to "view" my user info (anything public is pulled into the block at top of the page); so rather than "view" versions I ONLY need the edit pages.

so not sure if this is making sense.. but I'll summarize.

- top of the page has a view block with collection of user info

- under this is a set of primary tabs (views) such as "member/$arg/my_favorites", "member/$arg/my_reviews", etc.

so what I need to add is:

- another primary tab along side those above called profile (or in similar vain as above: "member/$arg/profile".

and, under "profile" tab I would have secondary tabs for the edit forms for my various usernodes as well as my "account settings".

Hopefully this makes sense.

Does this seem possible? Does it seem like this is similar to the techniques in this thread?

I'll start looking deeper into the methods here in a few hours.. but hopefully someone can suggest if this at least seems feasible.

thanks,

Peter Lindstrom
LiquidCMS - Content Management Solution Experts