Hello,

Is there a way to get content_profile fields show up in this excellent module ?
I'm not sure that indications about Profile in advf-forum-user.tpl.php can apply for content_profile and I'd really like to do that.

Thank you advance (forum ahah… sorry).

Comments

michelle’s picture

Project: Advanced Forum » Content Profile
Component: Documentation » Miscellaneous

The $profile variable is for core profile. advf-author-pane.tpl.php has the $account variable which is the user object. So you need to load the content profile node from that and then you can get at the fields. This is out of the AF realm, so handing this off to content profile's queue.

Michelle

ethnovode’s picture

Thank you, I will try to do that but I don't know if I have the skills.

fago’s picture

Title: Content profile integration ? » add content profile docs for themer
Category: support » task

you can use content_profile_load(), e.g. $node = content_profile_load('profile', 4); where 4 is the uid.

Probably this and more needs to be documented somewhere for themers.

michelle’s picture

@fago:

Just an FYI, you can add variables to the author pane of advanced forum if you want. Just do this:

/**
 * Implementation of hook_preprocess_author_pane().
 */
function content_profile_preprocess_author_pane(&$variables) {
  $account = $variables['account'];
  $variables['author_node'] = content_profile_load('profile', $account->uid);
}

This would make a variable $author_node available in the author pane in AF. You can make available whatever you like this way.

If you put it in a file named content_profile.forum.inc it will get picked up automatically. Or you can just stick the function in the module. If you don't want to, that's fine. I might stick it into AF itself at some point. I'm just trying to get the contrib integration into the contrib modules themselves so I don't have to track down changes in other peoples' modules. :)

Michelle

ethnovode’s picture

I will learn how Drupal works because I'm lost. But thanks anyway for your help.

fago’s picture

I wonder if we should provide a reusable template preprocess function, that loads configurable content profiles or also the rendered node_view().

Any ideas how we could do that best?

michelle’s picture

Forgot about #4. That's out of date. I was actually going to add content profile support to author pane, but make it optional as it would be a performance killer on a large site. You can add it to content profile itself if you want but I had so much trouble getting maintainers to integrate that I just put all their code into my module instead. So it's up to you.

What I was going to do is load up the profile node and simplify all the cck fields / taxonomy on it into variables under the "profile_node" variable. So you'd end up with, say, $profile_node['gender'] to get at the "gender" field on the node.

I need to do this sometime today to make the location field available for a client so if you have any suggestion on how you'd like to do it, that would be nice so I can go in that direction.

Michelle

fago’s picture

$profile_node['gender'] is good idea!

To be sure to get all variables of a node into it, I think we should fire up all preprocess functions of a node ourself and let it generate the variables - we can get them from theme_get_registry().

ok, then there is the problem left that loading all variables for all profiles would be quite a performance penalty. We could use a lazy-loading object, but I think that's not possible with php4. So we could set the wanted profiles in $variables and then let the preprocess function read it - but that's quite inconvenient.

Perhaps best we write a simple class and do it set it as $variables['profile'];
Then support calls like $profile->get_vars($type)->$field or for your example $profile->get_vars('profile')->gender

So we could lazy-load (and cache) the variables of the node in the get_vars() method. So all variables are available, but only the really used ones are loaded. What do you think about that? :)

michelle’s picture

Doesn't the node_load already fire all the preprocesses?

I'm not sure what to do about the performance issue. My plan was a simple on/off in the author pane. Which means it's only useful for sites that can handle the load. Honestly, I don't know any way to make it better. If you have, say, 30 comments per page, that's potentially 31 users you're loading profile nodes for on a page. That's going to be nasty for performance no matter how you look at it. I went thru this on #336015: Function for retrieving a value from a field in a node but got no where.

I don't really know anything about this "lazy load". I have an idea of what it means but not how it would be implemented. If you have the skills to make this work without killing performance, feel free to take the lead here. I need something working today for a client so I'm just going to do a node_load but I won't commit it to author pane until we have a good solution.

Michelle

fago’s picture

>Doesn't the node_load already fire all the preprocesses?
No, just for loading, not for theming.

I had a look on this and implemented the lazy-loading stuff, but it's working only on node-level but not on field level as you suggested in the linked issue. I agree with KarenS that this won't get us much as the node get already cached when the author views it after submitting...

So I've added code to the module which automatically adds $content_profile to each template, where it can find an uid. If so it registers $content_profile for this uid, which can be used like I described already above:
echo $content_profile->get_vars('profile')->title;
or also
echo $content_profile->get_view('profile');

Have a look at http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/content_pro... to see what methods $content_profile support.

So this code makes sure that the nodes are only loaded, if they are actually used. But still all variables are easily accessible for themers.
Please test -> its committed to 6.x-1.x-dev.

I leave the issue open for now, as of course this all needs to be documented *puh*.

michelle’s picture

"I agree with KarenS that this won't get us much as the node get already cached when the author views it after submitting"

Huh? I'm not following you there. Are you saying every node on the entire site is cached forever when it's submitted? That doesn't make any sense. AFAIK, a node is cached on the first load. And since we'd be the ones loading it, that means 30+ node loads per page view. Which is back to site killing again.

I've given the code a quick look as I'm out of computer time right now... I have no clue what it's doing. How do I call this from my preprocess? Can you give me some basic docs?

Thanks,

Michelle

fago’s picture

@caching:
ah, we are talking about different things here. node_load() caches the loaded nodes for a page hit yes, cck caches all fields of a node in a cache table. so a node load let's cck pull it's cache, but yes there is still a query to the node table and all the hook stuff gets processed.
So if there would be field-level functions of cck to use, we could further improve it to support them - for now the improvements try just to save the number of node_loads and makes sure subsequent calls are cached.

@docs:
Just try this in any template, e.g. a node template, the page template or also the user profile template. It should work where it finds an uid, see content_profile_preprocess() for the uid detection code.
echo $content_profile->get_vars('profile')->title;

michelle’s picture

There is no $uid in author pane... There's an $account->uid. Will it find that?

I'll give it a whirl after the tarball generates this evening. I have to leave the house for a couple hours.

Michelle

fago’s picture

I've further improved the solution, so it's faster. The last solution was so generic that it was run for each template - resulting in a lot of unnecessary function calls, which dropped performance of my site about 2ms.
-> I've improved the solution to only work with some templates that actually have user information. I've added some templates which are supported out of the box, further custom templates can be added in the settings.php (needs documentation!)

-> see http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/content_pro... for the list of supported templates. If you can think of further templates which should be supported, please post them so we can add them to the default list.

I've already included author_pane, so it should keep working for it.

Perhaps we should also add a way one could easily deal with not existing profile nodes?

michelle’s picture

Just wanted to let you know I haven't forgotten about this. My son had minor surgery this morning so I haven't been at the computer much yet today. I'll take a look soon as I can.

Michelle

fago’s picture

oh, no problem

In the meantime I've improved it a bit. As echo $content_profile->get_vars('profile')->title; would generate a php notice if the profile is not available, I've changed the solution so

echo $content_profile->get_variables('profile') returns the usual array of variables, which are available in the node's template and echo $content_profile->get_variable('profile', 'title'); can be used else - so if there is no profile node it just returns FALSE and nothing is printed.

oh and all the best to your son!

fago’s picture

Status: Active » Fixed

I've just added some docs for this to README.txt. Please check them.

michelle’s picture

Thanks for your work on this, fago. I've been exhausted and going to bed early, which has cut into my computer time since I can only work when the kids are sleeping. I'm going to try and get to looking at this today.

Michelle

michelle’s picture

Finally got a chance to try this out. It works slick. For anyone reading this wondering exactly how to use it, here's an example:

  $town = $content_profile->get_variable('uprofile', 'field_town');
  $town = $town[0]['value'];
  print $town;

What about the performance question? I'm not really following what you're doing with the lazy loading and whatnot. Is this still going to kill sites if they have 30-50 comments on a page?

Thanks very much!

Michelle

fago’s picture

It's still loading the profile node for every user - if you request a field of the node.

@example:
I'm not used to theming but shouldn't it be:

  $town = $content_profile->get_variable('uprofile', 'field_town');
  print $town[0]['view'];

as 'value' is the raw user input, so you would create a XSS hole?

michelle’s picture

I'd have to look again, but I'm pretty sure "value" was the only thing in the array. I'll test it for script issues.

Michelle

michelle’s picture

Status: Fixed » Active

Ok, I double checked and the only thing available in the array "get_variable" returns is value. And that does, in fact, cause a sechole by using it. So we need your code to return "view" as well. Is that possible?

Thanks,

Michelle

michelle’s picture

Any more thoughts on this? It's a security hole as it stands. Do you have the input format available on your end to run it thru the proper one? Otherwise I guess people could just check plain it when they use it but that's not ideal. Forgetting to do that would open up a hole that people may not realize.

Thanks,

Michelle

fago’s picture

Status: Active » Fixed

sry for letting this lie so long. Yes, it's important to fix this, but it's not a security hole - as it doesn't say the value is checked. The other one is just missing.

Anyway, I had a look at this and fixed it. Now there is also the 'safe' value generated by CCK included (as well as all other stuff cck adds or might add in future). committed to 6.x-dev, please test!

So the above example should be

  $town = $content_profile->get_variable('uprofile', 'field_town');
  print $town[0]['safe'];
igorik’s picture

Hi

I am watching this interesting discuss. I heavy use various cck profile fields at a lot of places on my site, the most using is field sex (male/female) for better personalize, icons, etc.
I like the idea of $content_profile->get_variable in templates. It is probably the best what could be.

But there is a lot of places on my site except templates where I use need to find content of some field. In this case I have to use db_query to find uprofile node for $user->uid, then node_load of this node and finally use content_format for found value of required field.

do you think it will be better in this case to build own module, which on ( hook_user (load), and when user's uprofile node is changed), adds wanted cck field values into $user (e.g. user sex, user image_field path, user town, user age)
or could be better to do everywhere some templates ( user-picture.tpl.php, various own blocks, pages, my modules, etc) where then I can use your $content_profile->get_variable ?

I am thinking with focus on performance. Content what I am thinking to add into $user is not big, some paths, word 'male' or 'female', name of city and age. This is enoug for me.

Could you someone of you (or you both :) tell me please your opinon about it? Many thanks for it, I think it can be useful information for other themers using content_profile too and I feel that it is relevant to this discussion (but I can to add as a separate support request too if you wish).

thanks a lot
Igorik
http://www.somvprahe.sk

fago’s picture

I'd suggest to also $content_profile, you can create your own one by doing

$content_profile = new content_profile_theme_variables($uid);

To further increase performance I think it would make sense to have a look at the issue for loading single CCK fields mentioned by Michelle and once there is a CCK API function for that, make it possible to use that with $content_profile.

michelle’s picture

Adding selected fields to the user is something I thought of but I don't know if it belongs in content profile. That would require another UI for selecting the fields plus all the code to manage updates and keep them in sync. Possibly a submodule? I hate to bloat content profile itself with too many things.

It's a bit academic, though, unless someone wants to write it as I don't have the time. ;)

Michelle

fago’s picture

>code to manage updates and keep them in sync

I don't think it makes sense to store the same information again - as it would be required to load it nevertheless. Instead we could store the NIDs of the users profiles, make $content_profile work with that too and populate $user->content_profile.

michelle’s picture

@#28: The whole point of it would be to avoid the node load. Storing the nid doesn't solve that. The problem is that, while most of the profile node information is only needed on the profile page, there are a few things, usually real name and location, that people want to display all over the place. And doing a node load to get that information is expensive, especially if you are doing it 50 times on one page. An alternate is to use core profile for those fields but then you have the hassle of the profile editing being split into two different forms.

Michelle

igorik’s picture

Hi

is it possible to use that not only in themes?

I tried to use it for user uid = 19 in my chat module in one of my function (for list of users - I want to add some their profile fields into their chat bubble details)
but I got only

content_profile_theme_variables Object ( [uid] => 19 [_cache] => Array ( ) )

thanks
Igorik

igorik’s picture

Hi

I agree with Michelle, the point is avoid the node load (and use db_query needed for finding user profile node before node_load is used)

That was the point for me when I thought that I will add the most using profile fields into $user.

No new db_rows is needed, field content is added on events: on hook_user (load) - creating user object and if his profile node is updated. I could be done by one small module. It takes some data from content profile and put it into $user.

I have no idea how to use it together with content_format but without node_load. maybe some layer to take it directly from db together with using content_format...? I am not sure about it.

It is important especially for no-english languages . In my language (slovak) there are a lot changes in words/verbs depends if it is about woman or man. This is why I need to use "sex field" so often. For various senteces, not only for icons, images, etc. Everywhere, in blocks, themes, modules.

igorik’s picture

I did a small module which on hook_user - case $op : 'load' adding some datas from content profile to $user.
but when I use node_load inside, it will do massive overload on the frontpage and stop my test site.
So I am not sure if it is the right way

This was my code:

 
function userfield_user($op, &$edit, &$account, $category = NULL) {
  switch($op) {
    case 'load' :
        $account->userfield_profile_data = _userfield_fetch_profile_data($account->uid);        
  }
} 
 

function _userfield_fetch_profile_data($uid) {
  $sql = "
  SELECT n.nid, n.uid FROM node n WHERE (
  n.type = 'uprofile' AND $uid = n.uid)";
  $result = db_query($sql);
  $row = db_fetch_object($result);
  $node_loaded = node_load($row->nid);
  
  $sex = content_format('field_profil_pohlavie_2', $node_loaded->field_profil_pohlavie_2[0], 'default', $node_loaded);
  $forename = content_format('field_profil_krstne_meno', $node_loaded->field_profil_krstne_meno[0], 'default', $node_loaded);
  $age = content_format('field_computed_vek', $node_loaded->field_computed_vek[0], 'default', $node_loaded);
  $from = content_format('field_profil_z_ktoreho_mesta', $node_loaded->field_profil_z_ktoreho_mesta[0], 'default', $node_loaded);      
  return array($sex, $forename, $age, $from);
}
fago’s picture

yes, I see the point with node_load(). But anyway to retrieve the data you need the node id - my suggestion in #28 was to "presave" that. Then add field-level-loading support to $content_profile / CCK and we are done.

Anyway, I think we should open a new issue for further improving this.

@igorik #31: Yes it's working everywhere and it's looking fine. You just need to call the methods on this object as documented in the readme.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

joostvdl’s picture

Status: Closed (fixed) » Active

It seems that it only works on the My Account page

I have add the following code to the node.tpl.php file:

        <?php
        	echo $content_profile->get_variable('memberprofile_company', 'title');
        ?>

But it does not give any results but only on the My Account page

joostvdl’s picture

2nd problem i see is that when I try to get the field content I get an array back

        <?php
            echo $content_profile->get_variable('memberprofile_company', 'field_member_companyname');
        ?>

Gives:

Array
fago’s picture

Status: Active » Closed (fixed)

Please don't reopen this issue, but create new ones. Get variable is supposed to get the variable, which might be an array.