OpenSocial is useful for websites to start hosting social applications. Apache Shindig is an OpenSocial container and helps you to start hosting these apps on your website.
OpenSocial is not just about gadgets and widgets for your Website. With it, your website can be a container or can store persistent data and publish notices/alerts called activities.
OpenSocial has vast verity of uses including social mashups, social websites and applications, gadgets/application creation, CMS and social network integration and any PHP website integration with social network/ features.
In this tutorial we will explore more about PHP Website integration with social features of OpenSocial platform. To understand a basic communication structure between OpenSocial and existing website, please refer the figure below:
As shown in the figure above, you can integrate your website server and shindig server with a common database. For example: Application like giving virtual gift to your friends requires accessing your friends list from the database (the same database interacts with your website’s database components and PHP API component in shindig). Functionality of virtual gifts from shindig server, and application will be shown on your website’s application page under presentation layer.
I assume that you already have a social network, that’s to say, a site with registered users and a notion of “friends”. Your site also has a notion of an “activity stream” that lists actions that the friends of a given user have taken recently. If you don’t have the above things, you can still use OpenSocial but the use will be limited to gadgets that use less user data for Ex: you can still use Horoscope like gadgets in your website, you will only need date of birth of the signed user. To make integration of social features with any application, follow below steps;
- Download PHP Apache Shindig and install
- You need to implement some basic classes: PersonService, AppDataService, ActivityService etc.
- An HTML and PHP file to connect with container and render the gadget
- Function to request social data
- OpenSocial Gadget
Download and Install
Apache Shindig is a container for hosting social application consisting of four parts:
- Gadget Container JavaScript: core JavaScript foundation for general gadget functionality (read more about gadget functionality). This JavaScript manages security, communication, UI layout, and feature extensions, such as the OpenSocial API.
- Gadget Rendering Server: used to render the gadget XML into JavaScript and HTML for the container to expose via the container JavaScript.
- OpenSocial Container JavaScript: JavaScript environment that sits on top of the Gadget Container JavaScript and provides OpenSocial specific functionality (profiles, friends, activities, datastore).
- OpenSocial Data Server: an implementation of the server interface to container-specific information, including the OpenSocial REST APIs, with clear extension points so others can connect it to their own backends.
The link to download Shindig is http://shindig.apache.org/download/index.html.
Building and running instructions can be found at http://shindig.apache.org/developers/php/build.html.
Implement Classes
In PHP, theses class files are located in the src/social/spi directory. You need to implement the following Shindig class services to connect your own database.
- PersonService
- ActivityService
- AppDataService
For example: if we implement ActivityService class in src/social/spi/ActivityService.php, then a sample code for implementing the function createActivity could be:
public function createActivity($userId, $groupId, $appId, $fields, $activity, SecurityToken $token)
{
$person_id = $userId->getUserId($token);
$title=$activity['title'];
if($body==NULL){
$body=$activity['body'];
}
$activity['body']=$body;
$query="insert into activity_streams (activity_streams_id,user_id,title) values ('', $person_id,'$title')";
mysql_query($query);
$query="select activity_streams_id from activity_streams where user_id=$person_id";
$stream1=array();
$stream_id=mysql_query($query);
while (@$row=mysql_fetch_array($stream_id) ){
$stream1[]=$row[0];
}
$stream=mysql_query("SELECT distinct(stream_id) FROM activities where stream_id not in( 'select activity_streams_id from activity_streams where user_id=$person_id')");
$stream2=array();
while (@$row1=mysql_fetch_array($stream) ){
$stream2[]=$row1[0];
}
$stream3=array();
$stream3=array_diff($stream1,$stream2);
foreach($stream3 as $key =>$value){
$time=strtotime("now");
$posted_time=gmdate("Y-m-d H:i:s",time());
mysql_query("insert into activities (activities_id,title,body,stream_id,posted_time) values ('','$title', '$body',$value,'$posted_time')");
}
return new ResponseItem(null, null, array());
}
The above code is just a sample and you can create your own activities function, the activities are like updates of your friends etc.
HTML Page
The HTML page will be Apache Shindig sample container. OpenSocial apps can define multiple views to generate UI appropriate for the context in which the app is being shown. For example, you can define a profile view to be shown when the app is rendered on a user’s profile. The other common view on a typical social network is the canvas view, which is used to render a full page view of the app.
Note: For the simplicity, I am including the database connection and other functions in the same file but with your existing website you might have database connection and functions layer separate so please keep your OOPs model the same.
The HTML and PHP file sample is:
<?php
include("{your database connection file");
include("your database functions file"); //this can add or remove the gadgets links in to the database
require_once("configuration file in which you make connection with Shindig"); //Please find code below for this file
{Identify Viewer and Owner id} //It depends on the gadget functionality if you need it or not
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Google</title>
<link href="style/GoogleClasses.css" rel="stylesheet" type="text/css" />
<?php
{include js files for the shindig}
{Include functions to request social data, which is explained in next heading}
</head>
<body class="ContentCanvas">
//The below form is to choose one gadget out of various gadget options and render them in profile mode
<form name="profileViewGadgetForm" onsubmit="return false;">
<select id="selectGadget" onChange="handleGadgetInMode('profile');">
<option value="">-------select------</option>
<?php
//Fetch various gadget list from database to show options in drop-down box
$result = gadgetList();
while($row2=mysql_fetch_array($result)){
//$value = explode("/",$row['name']);
//$size = count($value);
$gadName=$row2[1];
$gadUrl=$row2[2];
echo '<option value="'.$gadUrl.'">'.$gadName.'</option>';
}
}
?>
</select>
</form>
//the gadget will render in below mentions Div
<div class="profileView">
<div id="gadget-profile-chrome" class="gadgets-gadget-chrome"></div>
</div>
</body>
</html>
Function to call social data
Now we will include the main JavaScript files which are essential for the Shindig code rendering into the browser. Please check the functions in below file. If you want to change the way the gadget looks in your browser then it’s the file to work on. Again it depends on what you want to include or how creative you can be in terms of look and feel.
<script type="text/javascript">
var gServerBaseURL = '';
var gProfileGadget = null;
var gCanvasGadget = null;
var gChromeIds = [ "gadget-profile-chrome", "gadget-canvas-chrome" ];
var gOwnerId = <?php echo $ownerid; ?>;
var gViewerId = <?php echo $viewerid; ?>;
getUpdate('@friends');
function generateSecureToken( gadget, mode ) {
// TODO: Use a less silly mechanism of mapping a gadget URL to an appid
var appId = 0;
var appIdGeneratorUrl = gadget.specUrl + "?mode=" + mode;
for (var i = 0; i < appIdGeneratorUrl.length; i++) {
appId += appIdGeneratorUrl.charCodeAt(i);
}
var fields = [gOwnerId, gViewerId, appId, "shindig", gadget.specUrl, "0"];
for (var i = 0; i < fields.length; i++) {
// escape each field individually, for metachars in URL
fields[i] = escape(fields[i]);
}
return fields.join(":");
}
</script>
<script type="text/javascript">
function handleNewProfileGadget( gadgetUrl ) {
gProfileGadget = gadgets.container.createGadget( {'specUrl': gadgetUrl} );
gProfileGadget.setServerBase('<?php echo $gadgetServer; ?>');
gProfileGadget.width=170;
gadgets.container.addGadget( gProfileGadget );
gadgets.container.layoutManager.setGadgetChromeIds( gChromeIds );
}
function handleNewCanvasGadget( gadgetUrl ) {
gCanvasGadget = gadgets.container.createGadget( {'specUrl': gadgetUrl} );
gCanvasGadget.setServerBase('<?php echo $gadgetServer; ?>');
gCanvasGadget.width=430;
gCanvasGadget.height=400;
gadgets.container.addGadget( gCanvasGadget );
gadgets.container.layoutManager.setGadgetChromeIds( gChromeIds );
}
function View(){
handleGadgetInMode('canvas');
}
function confirmDelete()
{
return confirm("Are you sure you wish to delete this gadget?");
}
function handleGadgetInMode( mode ) {
var currGadget = null;
if (document.forms[ "profileViewGadgetForm" ].elements[ "selectGadget" ].selectedIndex == -1) {
//nothing has been selected yet!
return ;
}
var gadgetUrl = gServerBaseURL + document.forms[ "profileViewGadgetForm" ].elements[ "selectGadget" ].value;
gadgets.DemoAppGadget.prototype.gadget_url = gadgetUrl; //document.forms[ "profileViewGadgetForm" ].elements[ "selectGadget" ].value;
gadgets.DemoAppGadget.prototype.user="<?php if($ownerid==$viewerid) echo "viewer"; ?>";
if( mode == "profile" ) {
gadgets.DemoAppGadget.prototype.viewMode = 1;
if( gProfileGadget === null ) handleNewProfileGadget( gadgetUrl );
currGadget = gProfileGadget;
} else if( mode == "canvas" ) {
gadgets.DemoAppGadget.prototype.viewMode = 0;
if( gCanvasGadget === null ) handleNewCanvasGadget( gadgetUrl );
currGadget = gCanvasGadget;
var profileDetailsDiv=document.getElementById("profileDetails");
profileDetailsDiv.style.display = "none";
}
currGadget.specUrl = gadgetUrl;
currGadget.secureToken = escape(generateSecureToken( currGadget, mode ));
gadgets.container.setView( mode );
gadgets.container.renderGadget( currGadget );
}
function initProfileGadget( ) {
handleGadgetInMode("profile");
}
gadgets.util.registerOnLoadHandler(initProfileGadget);
</script>
We will explore more about the gadgets in an upcoming tutorial so be on the lookout.