Skip to:
Content
Pages
Categories
Search
Top
Bottom

Re: bpContents 1.0 Alpha 1 – Member, Group and Blog Tagging for BuddyPress


Burt Adsit
Participant

@burtadsit

I said I wasn’t going to document the code yet. I will tell you how it works though. :)

bpc allows any type of content to be organized into a hierarchy. Think of it as a virtual file system implemented with SQL tables and relationships. Each path in the tree can have it’s own set of tags and content items.

bpc 1.0a1 creates a tree consisting of member, group and blog tags.

root

— user

— group

— blog

That’s the tree for bpc 1.0a1. All content, tags or items, are children of the tag ‘root’. Root is invisible to everyone and it’s the only thing allowed at it’s level. All other content is organized as children of ‘root’.

Below root are the tags ‘user’, ‘group’ and ‘blog’. These tags are invisible to the end users also. When a bp member tags their profile they create other tags that are forced to be children of ‘user’.

root

— user

—- cats

—- dogs

—- fish

These tags form the member tag cloud. That cloud template tag looks in the path ‘root/user’ and displays everything it finds there. I’m just going to stop saying ‘root/user’ and use ‘/user’. The root is implied by the first slash. Just like a file system.

What actually happens further is that an content item representing the user who created the tags ‘cats’, ‘dogs’ and ‘fish’ tags is put in each tag. We wind up with this:

root

— user

—- cats


item (burt)

—- dogs


item (burt)

—- fish


item (burt)

These ‘items’ are content neutral representations of any type of content. In the case of items in /user, all items are derived from the bp user that created the tag. In the case of this tree some people want to be tagged differently and some the same:

root

— user

—- cats


item (burt)


item (john)


item (jeff)

—- dogs


item (burt)


item (john)

—- fish


item (burt)

—- giraffes


item (jeff)

—- bears


item (john)

When a user creates their own set of individual tags bpc inserts an item for them into an existing tag or creates a new one.

So we’ve got a tag cloud now. In bpc the links in the tag cloud launch the content specific bp directory. A member tag cloud launches the member directory with a query param like /members?tags=cats

The member directory has been modified by extending the normal template class that bp uses to pay attention to those $_GET vars if they exist in the url.

The directory parses the $_GET query vars and determines what tag the user clicked on. In this case the tag was ‘cats’. The directory template class then gets all the items in the path /user/cats. These things it gets back from bpc are not the actual user records we need to display in the directory, they are instances of the class OCI_Item. That neutral representation of the original content.

We get neutral representations of original content from classes that understand the original content types. They know where they came from and how to convert them to OCI_Items. Each content type that wants to store info in bpc has to have one of these conversion classes. In the case of bp members the class is called OCI_Item_User and it is a derived class of OCI_Item.

It’s defined like: OCI_Item_User extends OCI_Item. You’ll see it in the oci-classes.php file. There’s three like that in there. One each for users, groups and blogs. The purpose of these classes is to convert source content into item format and when the time comes, take the item information and get() the original item back.

This is the template class for the member directory:

class OCI_BP_Core_Members_Template extends BP_Core_Members_template.

When this class is fired up by the user clicking on a tag in the member tag cloud, the directory is launched. The template is run and in the constructor for OCI_BP_Core_Members_Template, it does a bunch of stuff and gets to the following chunk of code (lines 170-188 in oci-classes.php):

} else if (isset($_GET[$bp->contents->slug])) {

if (!$path)
return;

$tag = $path . '/' . $_GET[$bp->contents->slug];

$container = new OCI_Container('path=' . $tag);
$items = $container->get_items();
foreach ($items as $item){
$tmp->user_id = $item->item_id;
$users['users'][] = $tmp;
unset($tmp);
}

$users['total'] = count($users['users']);
$this->members = $users;
} else {

If there are any query vars such as /members/?tags=cats then instantiate an OCI_Container for the path ‘/user/cats’ and get all the items in that tag.

When the OCI_Item_User creates each member item in a tag it stores the user id in the var $this->item_id. The group version and the blog versions of that class store the group or blog ids in that spot when they create items.

I took a look at the the bp template class and figured out that it needs an array of the format: array(‘users’ => $users, ‘total’ => $count) to operate properly so that’s what gets built for it in that chunk of code.

Group and Blog templates use a similar thing. So we just pull out the user ids stored in each item and create an array that bp’s template class is happy with.

All I had to do to modify the the directories was create a new bp_has_whatever() tempate tag and override the constructor for each template class that bp uses.

Now we’ve got some modified php templates, classes and a replacement has_whatever() template tag function. It’s a good thing that Andy is filter and action happy because the only other thing to do was to create a filter that tells bp to use our new directories instead of the standard ones.

// changes the default members dir to this one
function oci_filter_template_directory_members(){
return ('oci-contents/directories/members/index');
}
add_filter('bp_core_template_directory_members', oci_filter_template_directory_members');

That function lives in oci-templatetags.php. There’s one for each of the directory types being hijacked.

Skip to toolbar