Stream API v2

NOTE: API examples below apply to version 2.8 and above. To read the full Activity Stream API for older versions, click here

Overview

Since JomSocial 2.8 onwards, we bring the massive change in how activity streams are handled and introduce a set of new rules to follow which will allow more freedom for third party developers to easier customize every individual's activity stream item;
JomSocial 2.8+ streams are NOT backward compatible with JomSocial 2.6 and bellow, however, some legacy support for old activity stream exist in JomSocial 2.8 and above. This does not necessarily mean your old activity will work though.
You can still use the old API to create the activity streams, but you can't use the {multiple}...{/multiple} tags anymore as they are completely removed and will cause activity streams to break. (It will be created, but will not be shown on Front End, or it will be shown with {multiple} tags).

Storing & Displaying

Unlike JomSocial 2.6 and bellow, where third party activity streams were created by JomSocial APIv1 and later displayed "as they are" directly from the database, in Stream API v2 we first store the activity stream in the database and then manipulate the database data with the community-type plugin

Storing

Storing the data is pretty much straight forward task and is exactly the same as in V1 with use of CActivityStream::add API
We will provide just a basic example here

$act            = new stdClass();
$act->cmd 	= 'example.task';
$act->actor 	= $my->id;
$act->target 	= 0;
$act->title 	= 'string';
$act->content 	= 'Your activity content';
// Pay close attention on this
$act->app 	= 'example.action';
$act->access  = 10; // 10 = Public; 20 = Site members; 30 = Friends Only; 40 = Only Me
$act->cid       = 0;
 
CFactory::load('libraries', 'activities');
$act->comment_type  = $command;
$act->comment_id    = CActivities::COMMENT_SELF;
 
$act->like_type     = $command;
$act->like_id     = CActivities::LIKE_SELF;
 
CActivityStream::add($act);


Lets decompose this very basic activity stream item addition

  • $act = new stdClass(); - We want to create an activity stream object, and assign data to it, without having to formally define a class.
  • $act->cmd = 'example.task'; - An unique custom command for your activity used for likes and comments. You can set this to any value but the best practice is to name it like pluginname.task
    • pluginname will be explained later. It will be the name of plugin we will create through this tutorial
    • task is simply a command that will help you to easier distinguish the different activities. For example, if you want to integrate the forum component, you can replace the word task with newpost or newthread but whitespace is not allowed
  • $act->actor = $my->id; - Actor is the person who carry out the action
  • $act->target = 0; - (Optional) A target is a user who's object is being manipulated by actor. Leave it to 0 if your activity wont have the target
  • $act->title = 'string'; - Since 2.8 title have different purpose. In 2.6 and bellow, title was used as an activity stream item title. Since 2.8 we are using it as an title above attachment. We will come to attachments later in this article.
  • $act->content = 'Your activity content'; - This will be the activity content
  • $act->app = 'example.action'; - This is the most important part of the API. You are absolutely required to define the app name exactly as your plugin will be named, which in this tutorial is example
    • example - is the name of the plugin we are about to create
    • action - is simply a name of the carried action within the plugin
  • $command - In this case is simply a short string that uniquely identify your particular stream type. If your plugin is called 'mypplugin', your comment_type and like_type can be called 'myplugin.myaction' .
  • CActivityStream::add($act); - And finally, this will store the activity stream object.

Displaying

This is where all the fun with activity stream items begin, but as stated earlier, you will need to create the community plugin.
If you dont know how to create a community plugin yet, please follow this guide
Before you start creating your plugin, ensure that your component properly store the activity stream into database. For this tutorial, i have added one row manually, but you will really want to check if your component adds it automatically.

Dbrow.png

As shown in the image above, this row doesn't really have any data, except the actor id and app name which for the very basic activity stream item is enough.
Through this documentation article, we will extend the activity item massively, but lets start creating our first activity stream plugin.
Exactly as required for creating community plugin we will first declare a class with the format, plgCommunity[Plugin name] which will extend CApplications class.
Within the plugin, we will now use onCommunityStreamRender() event which is available from JomSocial 2.8 onwards

class plgCommunityExample extends CApplications
{
	public function onCommunityStreamRender($act)
	{
    	$actor = CFactory::getUser($act->actor);
 
    	$stream    = new stdClass();
    	$stream->actor  = $actor;
    	$stream->headline = 'Headline';
    	$stream->message = 'Message';
    	return $stream;
	}
}


As you can see, we now have a very basic activity stream plugin which will display all activities created by $act->app = example.action app
When plugin is enabled, the stream will be shown like this
Activity1.png
If you disable the plugin now, the content of it will disappear

Headline, Actor & Target

Examples above described how to get going with the very basic activity stream plugin. We now want to extend the functionality of the plugin and add the username to it as well as changing the headline
We will modify our code to look like this

class plgCommunityExample extends CApplications
{
	public function onCommunityStreamRender($act)
	{
    	JPlugin::loadLanguage ( 'plg_example', JPATH_ADMINISTRATOR ); // only use if theres any language file
    	$actor = CFactory::getUser($act->actor);
    	$actorLink = '<a class="cStream-Author" href="' .CUrlHelper::userLink($actor->id).'">'.$actor->getDisplayName().'</a>';
 
    	$stream    = new stdClass();
    	$stream->actor  = $actor;
    	$stream->headline = JText::sprintf('PLG_EXAMPLE_ACTIVITY_HEADLINE', $actorLink );
    	$stream->message = 'Message';
 
    	return $stream;
	}
}


At this stage, we added the language for our plugin as we want to play nice and harness the power of V2 API to make activity streams multilingual - something we couldn't do with previous API
Our new language file will simply have one line in it

PLG_EXAMPLE_ACTIVITY_HEADLINE="%1$s made some action in my component"


And our activity stream now look like this.
Activity2.png
See how it starts to shape up and builds nicely. lets add the target to the mix.
First, we need to make sure that target id is properly stored in the database. We explained storing the data at the beginning of this article so we will assume you already have the proper id in "target" column
Your plugin php file should now look like this

class plgCommunityExample extends CApplications
{
	public function onCommunityStreamRender($act)
	{
    	JPlugin::loadLanguage ( 'plg_example', JPATH_ADMINISTRATOR ); // only use if theres any language file
    	$actor = CFactory::getUser($act->actor);
    	$actorLink = '<a class="cStream-Author" href="' .CUrlHelper::userLink($actor->id).'">'.$actor->getDisplayName().'</a>';
	$target = CFactory::getUser($act->target);
	$targetLink = '<a class="cStream-Author" href="' .CUrlHelper::userLink($target->id).'">'.$target->getDisplayName().'</a>';
 
    	$stream    = new stdClass();
    	$stream->actor  = $actor;
    	$stream->headline = JText::sprintf('PLG_EXAMPLE_ACTIVITY_HEADLINE', $actorLink, $targetLink );
    	$stream->message = 'Message';
 
    	return $stream;
	}
}


And the language file is changed to, otherwise, to few arguments error will be displayed

PLG_EXAMPLE_ACTIVITY_HEADLINE="%1$s suggest %2$s to like cats"


And finally, our activity stream now looks like this
Activity3.png

Activity Content

We now know how to deal with the activity headline which basically replaced the $act->title allowing for multilingual functionality of activity stream item
Lets move on to the activity content.

* Again, we will assume you have a title and content data properly stored in the database

Lets just replace the boring and dull

$stream->message = 'Message';


Withe the title or content we stored previously

$stream->message = $act->title;
// You can also use
// $stream->message = $act->content;


Depending what you set as the activity title or the content, the stream item will now look like this
Activity4.png

Attachments

Simple activity content stored with $act->content is nice, and experienced devs already came up with some beautiful contents for their activities, but JomSocial 2.8 offers you way better possibility to present your content using attachments. Attachment is basically the array of data displayed in the activity content area. Lets see how this works
In a $stream->message we will revert from title to content as you can't use the title data in addition to attachments array

class plgCommunityExample extends CApplications
{
	public function onCommunityStreamRender($act)
	{
    	JPlugin::loadLanguage ( 'plg_example', JPATH_ADMINISTRATOR ); // only use if theres any language file
    	$actor = CFactory::getUser($act->actor);
    	$actorLink = '<a class="cStream-Author" href="' .CUrlHelper::userLink($actor->id).'">'.$actor->getDisplayName().'</a>';
		$target = CFactory::getUser($act->target);
		$targetLink = '<a class="cStream-Author" href="' .CUrlHelper::userLink($target->id).'">'.$target->getDisplayName().'</a>';
 
    	$stream    = new stdClass();
    	$stream->actor  = $actor;
    	$stream->headline = JText::sprintf('PLG_EXAMPLE_ACTIVITY_HEADLINE', $actorLink, $targetLink );
    	$stream->message = $act->content;
	// If you want to use attachments, you CAN'T use
	// $stream->message = $act->title;
 
    	$stream->attachments = array();
    		$attachment = new stdClass();
    		$attachment->type = 'album';
    	$stream->attachments[] = $attachment;
 
    	return $stream;
	}
}


And lets see how it looks
Activity5.png
WoW?! It certainly is, but there is more.
We provided four (4) types of attachments you can use. They are

  1. media
  2. album
  3. video
  4. quote

However, we will leave those to your imagination :)
If you want to find out more about attachments, browse these files for examples

  • ROOT/components/com_community/templates/default/
    • activities.groups.bulletin.php
    • activities.videos.php

Changing the favicon

Next we need to take care of is adding the unique favicon to our stream items.
In new stream, this is done through CSS so we need to create a new CSS file for our plugin. Lets call it simply, style.css. We need to call it by adding

//Atach stylesheet
$document 	= JFactory::getDocument();
$css		= JURI::base() . 'plugins/community/example/style.css';
$document->addStyleSheet($css);


into our plugin, so at the end, it will look like this

class plgCommunityExample extends CApplications
{
	public function onCommunityStreamRender($act)
	{
	//Atach stylesheet
	$document 	= JFactory::getDocument();
	$css		= JURI::base() . 'plugins/community/example/style.css';
	$document->addStyleSheet($css);
 
    	JPlugin::loadLanguage ( 'plg_example', JPATH_ADMINISTRATOR ); // only use if theres any language file
    	$actor = CFactory::getUser($act->actor);
    	$actorLink = '<a class="cStream-Author" href="' .CUrlHelper::userLink($actor->id).'">'.$actor->getDisplayName().'</a>';
	$target = CFactory::getUser($act->target);
	$targetLink = '<a class="cStream-Author" href="' .CUrlHelper::userLink($target->id).'">'.$target->getDisplayName().'</a>';
 
    	$stream    = new stdClass();
    	$stream->actor  = $actor;
    	$stream->headline = JText::sprintf('PLG_EXAMPLE_ACTIVITY_HEADLINE', $actorLink, $targetLink );
    	$stream->message = $act->content;
	// If you want to use attachments, you CAN'T use
	// $stream->message = $act->title;
 
    	$stream->attachments = array();
    		$attachment = new stdClass();
    		$attachment->type = 'album';
    	$stream->attachments[] = $attachment;
 
    	return $stream;
	}
}


Using Your Own Favicon Image

If you want to use your own favicon image, in the style.css file of the plugin you will have to define it with a class name ..com-icon-example

Using JomSocial Favicons

You can also use one of the available favicons from jomsocial sprites-icons.png
This file is located in the images folder of JomSocial default template.
To use it, simply add this into style.css file.

#community-wrap .com-icon-example {
background-position:0 -440px;
}


Favicon.png
Hint: A very basic css knowledge implies that you can change the value of background-position property to change the sprite image you want to use