Go Back   vb.org Archive > vBulletin Article Depository > Read An Article > vBulletin 3 Articles
[How-to] Decode custom user profile bitfield
joelabq
Join Date: Oct 2005
Posts: 15

 

Show Printable Version Email this Page Subscription
joelabq joelabq is offline 01-03-2006, 10:00 PM

This How to _should_ help someone setup custom profile fields that use multiple selections decode the bitfields for display (or other) purposes.

If you see anything wrong with how I did this, please let me know, likewise if you have suggestions on how to improve it. I'm just putting this out there because no one else has, and I've had a few people ask about it.

Let?s assume you are using Field7, and you have three settings you defined as multi-select checkbox (Yes, No, and Maybe). You can add more fields if you wish to test more.

1.Run a query to extract the data from the database for that profile field? These are all the settings for this field as defined in your custom profile field manager in the AdminCP. The following code will extract the settings you defined?in this case, ?Yes?, ?No?, and ?Maybe?.

Code:
	$custom_field_qry = $db->query_read("SELECT data from ". TABLE_PREFIX."profilefield where profilefieldid = '7' ");
	$custom_field_ary = $db->fetch_array($custom_field_qry);
2. If you are using any of the following field types in the custom field manager ? ?select?, ?radio?, ?checkbox?, ?select_multiple? the data is stored serialized, see php.net?s manual for serialize and unserialize to understand the meaning of the function if you do not already understand it. In this case, we used ?multi-select checkbox?, so we unserialize the data:

Code:
	$my_custom_data = unserialize($custom_field_ary['data']);
This will load the array structure stored in the ?data? field of the database into $my_custom_data

3. Now we need to match the values from $my_custom_data to the values in $custom_user_data. The ?odd? thing here is we are matching binary data in custom_user_data, represented in a decimal number, to the real field in $my_custom_data, and set the values in $show[testbit] so we can display them in a template like forumhome. You may choose how you want to do this, of coarse (refer to the operator reference to understand how ?&? works at http://us2.php.net/manual/en/language.operators.php):
Code:
foreach($my_custom_data AS $key => $val) 
{ 
  if ($vbulletin->userinfo[field7] & pow(2,$key)) 
  { 
       $show[testbit] .= $val." ";
  }

}

So for our example, edit the forumhome template, and add ?Testing: $show[testbit]? right below $navbar like shown below:

Code:
$stylevar[htmldoctype]
<html dir="$stylevar[textdirection]" lang="$stylevar[languagecode]">
<head>
	<!-- no cache headers -->
	<meta http-equiv="Pragma" content="no-cache" />
	<meta http-equiv="Expires" content="-1" />
	<meta http-equiv="Cache-Control" content="no-cache" />
	<!-- end no cache headers -->
	$headinclude
	<title><phrase 1="$vboptions[bbtitle]">$vbphrase[x_powered_by_vbulletin]</phrase></title>
</head>
<body>
$header
$navbar
Testing: $show[testbit]

<!-- main -->
Now go into the plugin manage, and add a plugin at ?forumhome_start?, copy this code (as explained above):

Code:
$custom_field_qry = $db->query_read("SELECT data from ". TABLE_PREFIX."profilefield where profilefieldid = '7' ");
$custom_field_ary = $db->fetch_array($custom_field_qry);

$my_custom_data = unserialize($custom_field_ary['data']);

foreach($my_custom_data AS $key => $val) 
{ 
  if ($vbulletin->userinfo[field7] & pow(2,$key)) 
  { 
       $show[testbit] .= $val." ";
  }

}
Make sure the plugin is activated, and save it.

Now load up your UserCP, check mark whatever boxes you like, and then load up your main forumhome homepage. It should show you all the options you select (and only those options) delimited by a space.
Reply With Quote
  #2  
Old 01-04-2006, 09:34 PM
Antivirus's Avatar
Antivirus Antivirus is offline
 
Join Date: Sep 2004
Location: Black Lagoon
Posts: 1,090
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Joel, that works really nicely for FORUMHOME, but I am trying to get it to work in the MEMBERINFO template and using hook location member_complete and it's returning my profile's data, not the member who's profile i am viewing...

Thanks!
Reply With Quote
  #3  
Old 01-04-2006, 10:22 PM
joelabq joelabq is offline
 
Join Date: Oct 2005
Posts: 15
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Quote:
Originally Posted by Antivirus
Joel, that works really nicely for FORUMHOME, but I am trying to get it to work in the MEMBERINFO template and using hook location member_complete and it's returning my profile's data, not the member who's profile i am viewing...

Thanks!
The line that has this:
Code:
 if ($vbulletin->userinfo[field7] & pow(2,$key))
Is what you need to modify. The var $vbulletin->userinfo[field7] is only the current logged in user's information.

What you need to do is query for that users profile fieldX values.

In memberinfo, only hidden field aren't already decoded... So I'm not sure what you want to do exactly, but you could make sure they are not hidden and vB already will display the correct values for that user in their profile.

If you really need this in member info, you could add a query using a plugin at member_customfields, something to this effect:

Code:
$my_qry = $db->query_read("select userfield.field7 where " . TABLE_PREFIX ." userfield as userfield where userfield.userid = " . $userinfo['userid'].";" );
Then pull that data out in a variable, and put that in place of the code above where $vbulletin->userinfo[field7] is used... Like so:

Code:
$my_profilefield_data = $db->fetch_array($my_qry);
if ($my_profilefield_data[field7] & pow(2,$key))
{
  ....
}
Hope that helps.

Joel
Reply With Quote
  #4  
Old 01-05-2006, 04:31 PM
Antivirus's Avatar
Antivirus Antivirus is offline
 
Join Date: Sep 2004
Location: Black Lagoon
Posts: 1,090
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

It took me a couple hours to figure it out due to process of elimination and with your help above as well- but the following works for me:

Create a plugin using hook location member_complete with following code:

Code:
$custom_field_qry = $db->query_read("SELECT data from ". TABLE_PREFIX."profilefield where profilefieldid = '26' ");
$custom_field_ary = $db->fetch_array($custom_field_qry);
$my_custom_data = unserialize($custom_field_ary['data']);
foreach($my_custom_data AS $key => $val) 
{ 
if ($userinfo[field26] & pow(2,$key)) 
{ 
	 $show[testbit] .= $val.", ";
}
}
and include $show[testbit] in the template...

BUT...

It does however add 1 additional query to the page. I don't understand why it needs to run another query at all, since the correct serialized data is already in $userinfo[field26] to begin with, but it does now work at the least.

I was attempting to unserialize the data and match it up without having to run the additional query above. I tried the following, but I am still a beginner with php and it wasn't working properly.

Code:
$my_custom_data = unserialize($userinfo['field26']);
foreach($my_custom_data AS $key => $val) 
{ 
if ($userinfo[field26] & pow(2,$key)) 
{ 
	 $show[testbit] .= $val.", ";
}
}
Reply With Quote
  #5  
Old 01-05-2006, 06:48 PM
vietkieu_cz vietkieu_cz is offline
 
Join Date: Dec 2005
Posts: 120
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Some screenshot please?
Reply With Quote
  #6  
Old 01-05-2006, 06:49 PM
joelabq joelabq is offline
 
Join Date: Oct 2005
Posts: 15
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

You have to run the query because field26 in the user info does not contain the actual data, just the bitfield data. All you get in the bitfield is 1's and 0's. Basically you have to match the real array with $userinfo[field26].

To visualize may be easier... imagine your array with "Yes", "No" and "Maybe" values (in that order in your custom field manager), which is contained NOT in userinfo[$field26] but in $my_custom_data as outlined above. $my_custom_data looks like this:

$my_custom_data[0] = "Yes"
$my_custom_data[1] = "No"
$my_custom_data[2] = "Maybe"

Now, $userinfo[field26] looks like this when "Yes" is set (in binary):
001 (or simply "1", but the leading zero's may help you visualize here)

So when you compare the fields with " if ($userinfo[field26] & pow(2,$key)" you are essentially doing this:

$my_custom_data[0] = "Yes" 1 (YES, user has it)
$my_custom_data[1] = "No" 0 (No, User doesnt have it set)
$my_custom_data[2] = "Maybe" 0 (No, User doesnt have it set)

Now, imagine Yes and Maybe are set for this user. $userinfo[field26] will be set to "5" in decimal, and when converted to binary is "101"... ON, OFF, ON... so lets compare it to $my_custom_data:

$my_custom_data[0] = "Yes" 1 (YES, user has it)
$my_custom_data[1] = "No" 0 (No, User doesnt have it set)
$my_custom_data[2] = "Maybe" 1 (YES, user has it)

Likewise, the code you posted:

Code:
$my_custom_data = unserialize($userinfo['field26']);
foreach($my_custom_data AS $key => $val) 
{ 
if ($userinfo[field26] & pow(2,$key)) 
{ 
	 $show[testbit] .= $val.", ";
}
}
...Will not work, because the data that is in $userinfo[field26] is NOT the serialized data, it only hold the binary representation to what is set when compared to the real serialized data. Therefore, you MUST run a query, unless vB already has pulled the data.

In your case, around line 560 in member.php

Code:
$customfields = '';
while ($profilefield = $db->fetch_array($profilefields))
{
	exec_switch_bg();
	$profilefieldname = "field$profilefield[profilefieldid]";
	if ($profilefield['type'] == 'checkbox' OR $profilefield['type'] == 'select_multiple')
	{
		$data = unserialize($profilefield['data']);
		foreach ($data AS $key => $val)
		{
			if ($userinfo["$profilefieldname"] & pow(2, $key))
			{
				$profilefield['value'] .= iif($profilefield['value'], ', ') . $val;
			}
		}
	}
...Which means, you could use the already queried $userinfo["$profilefieldname"], but ONLY if it's not hidden. I take it your data is hidden, therefore you could either unhide and create some template conditionals, or you add this query.

Hope this helps.

Joel

Quote:
Originally Posted by vietkieu_cz
Some screenshot please?
What?
Reply With Quote
  #7  
Old 01-05-2006, 07:17 PM
Antivirus's Avatar
Antivirus Antivirus is offline
 
Join Date: Sep 2004
Location: Black Lagoon
Posts: 1,090
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

that helps me understand the bitfields more, thanks Joel, you have been a tremendous help!
Reply With Quote
  #8  
Old 01-05-2006, 08:28 PM
joelabq joelabq is offline
 
Join Date: Oct 2005
Posts: 15
Благодарил(а): 0 раз(а)
Поблагодарили: 0 раз(а) в 0 сообщениях
Default

Glad I could help.

Joel
Reply With Quote
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 03:21 PM.


Powered by vBulletin® Version 3.8.12 by vBS
Copyright ©2000 - 2024, vBulletin Solutions Inc.
X vBulletin 3.8.12 by vBS Debug Information
  • Page Generation 0.04461 seconds
  • Memory Usage 2,277KB
  • Queries Executed 21 (?)
More Information
Template Usage:
  • (1)SHOWTHREAD
  • (1)ad_footer_end
  • (1)ad_footer_start
  • (1)ad_header_end
  • (1)ad_header_logo
  • (1)ad_navbar_below
  • (1)ad_showthread_beforeqr
  • (12)bbcode_code
  • (2)bbcode_quote
  • (1)footer
  • (1)forumjump
  • (1)forumrules
  • (1)gobutton
  • (1)header
  • (1)headinclude
  • (1)modsystem_article
  • (1)navbar
  • (4)navbar_link
  • (120)option
  • (8)post_thanks_box
  • (8)post_thanks_button
  • (1)post_thanks_javascript
  • (1)post_thanks_navbar_search
  • (8)post_thanks_postbit_info
  • (7)postbit
  • (8)postbit_onlinestatus
  • (8)postbit_wrapper
  • (1)spacer_close
  • (1)spacer_open
  • (1)tagbit_wrapper 

Phrase Groups Available:
  • global
  • inlinemod
  • postbit
  • posting
  • reputationlevel
  • showthread
Included Files:
  • ./showthread.php
  • ./global.php
  • ./includes/init.php
  • ./includes/class_core.php
  • ./includes/config.php
  • ./includes/functions.php
  • ./includes/class_hook.php
  • ./includes/modsystem_functions.php
  • ./includes/functions_bigthree.php
  • ./includes/class_postbit.php
  • ./includes/class_bbcode.php
  • ./includes/functions_reputation.php
  • ./includes/functions_post_thanks.php 

Hooks Called:
  • init_startup
  • init_startup_session_setup_start
  • init_startup_session_setup_complete
  • cache_permissions
  • fetch_threadinfo_query
  • fetch_threadinfo
  • fetch_foruminfo
  • style_fetch
  • cache_templates
  • global_start
  • parse_templates
  • global_setup_complete
  • showthread_start
  • showthread_getinfo
  • forumjump
  • showthread_post_start
  • showthread_query_postids
  • showthread_query
  • bbcode_fetch_tags
  • bbcode_create
  • showthread_postbit_create
  • postbit_factory
  • postbit_display_start
  • post_thanks_function_post_thanks_off_start
  • post_thanks_function_post_thanks_off_end
  • post_thanks_function_fetch_thanks_start
  • post_thanks_function_fetch_thanks_end
  • post_thanks_function_thanked_already_start
  • post_thanks_function_thanked_already_end
  • fetch_musername
  • postbit_imicons
  • bbcode_parse_start
  • bbcode_parse_complete_precache
  • bbcode_parse_complete
  • postbit_display_complete
  • post_thanks_function_can_thank_this_post_start
  • tag_fetchbit_complete
  • forumrules
  • navbits
  • navbits_complete
  • showthread_complete