Comments, likes, and dislikes The functionality behind adding comments, likes, and dislikes is very similar to the work we did in Chapter 5 in developing the statuses on a user's profile
Trang 1'stream-' $data['ID'], 'stream/types/'
$data['type_reference'] '-fromself.tpl.php', $datatags );
}
elseif( $data['poster'] == $data['profile'] )
{
$this->registry->getObject('template')->addTemplateBit(
'stream-' $data['ID'], 'stream/types/'
$data['type_reference'] '-user.tpl.php', $datatags );
}
else
{
// network updates
$this->registry->getObject('template')->addTemplateBit(
'stream-' $data['ID'], 'stream/types/'
$data['type_reference'] '.tpl.php', $datatags );
}
}
}
else
{
If there were no updates, we display the none template
$this->registry->getObject('template')->buildFromTemplates(
'header.tpl.php', 'stream/none.tpl.php', 'footer.tpl.php');
}
}
So, if we had our templates in place at this stage, bringing all of this together,
adding the controller to our database, and viewing /stream what would we see?
Trang 2This is the basics of our status stream We can now look at adding comments, likes,
and dislikes to the stream
Comments, likes, and dislikes
The functionality behind adding comments, likes, and dislikes is very similar to the
work we did in Chapter 5 in developing the statuses on a user's profile
The concept to adding these to the stream is fairly straightforward Firstly, we
create an empty array of comments / likes / dislikes for each status This way,
if a post has no comments, likes, or dislikes, then by caching the empty array and
sending it to the template, we don't see a blank list where comments should be
If there are comments, they are added to the empty array (making it non-empty),
cached, and sent to the template
Although the method is the same for the three aspects, comments require one
database query, whereas likes and dislikes combined require another, so let's
add in support one at a time
Comments
Take the status IDs we retrieved earlier, and create empty arrays for each of them
$status_ids = implode( ',', $IDs );
$start = array();
foreach( $IDs as $id )
{
$start[ $id ] = array();
}
Copy our new array of empty arrays to be used for comments
// comments
$comments = $start;
Query the database for comments
$sql = "SELECT p.name as commenter, c.profile_post, c.comment FROM
profile p, comments c WHERE p.user_id=c.creator AND c.approved=1
AND c.profile_post IN ({$status_ids})";
$this->registry->getObject('db')->executeQuery( $sql );
if( $this->registry->getObject('db')->numRows() > 0 )
{
Trang 3If there are comments, iterate through them and add them to the appropriate bucket
(or array) for the status it relates to
while( $comment = $this->registry->getObject('db')->getRows() )
{
$comments[ $comment['profile_post'] ][] = $comment;
}
}
For each of the comments arrays, we cache the data and send them to the
template engine
foreach( $comments as $status => $comments )
{
$cache = $this->registry->getObject('db')->cacheData( $comments );
$this->registry->getObject('template')->getPage()->addTag(
'comments-' $status, array( 'DATA', $cache ) );
}
Likes and dislikes
Likes and dislikes are stored in the same table So we query it, and depending
on the result, put the result in a different array
$likes = $start;
$dislikes = $start;
$sql = "SELECT i.status, p.name as iker, i.iker as iker_id, i.type as
type FROM profile p, ikes i WHERE p.user_id=i.iker AND i.status IN
({$status_ids}) ";
$this->registry->getObject('db')->executeQuery( $sql );
if( $this->registry->getObject('db')->numRows() > 0 )
{
while( $ike = $this->registry->getObject('db')->getRows() )
{
if( $ike['type'] == 'likes' )
{
$likes[ $ike['status'] ][] = $ike;
}
else
{
$dislikes[ $ike['status'] ][] = $ike;
}
}
}
foreach( $likes as $status => $likeslist )
{
Trang 4$cache = $this->registry->getObject('db')->cacheData( $likeslist );
$this->registry->getObject('template')->getPage()->addTag( 'likes-'
$status, array( 'DATA', $cache ) );
}
foreach( $dislikes as $status => $dislikeslist )
{
$cache = $this->registry->getObject('db')->cacheData(
$dislikeslist );
$this->registry->getObject('template')->getPage()->addTag(
'dislikes-' $status, array( 'DATA', $cache ) );
}
Views
Now we need our template files to provide us with the view
Main template
The main template contains an outer template loop, which is populated based on
the cached status IDs Once this is populated, we have a unique template tag for
each status, ready for the status template to be inserted It also generates three
inner loops—one for comments, one for likes, and one for dislikes
<div id="main">
<div id="rightside">
</div>
<div id="content">
<h1>Updates in your network</h1>
<! START stream >
{stream-{status_id}}
<! START comments-{status_id} >
<p> {comment} by {commenter}</p>
<! END comments-{status_id} >
<! START likes-{status_id} >
<p>{iker} likes this</p>
<! END likes-{status_id} >
<! START dislikes-{status_id} >
<p>{iker} dislikes this</p>
<! END dislikes-{status_id} >
<! END stream >
</div>
Trang 5Status type templates
For each status type (we have only one at the moment) we need a template for each
context (user's own status, user posting on someone else's profile, someone posting
on a user's profile, and two users in a contact's network posting on their profile)
These templates are stored in the views/default/templates/stream/types folder
Below is the template used when showing the status the logged-in user posted on the
profile of another user:
<p>You posted on {statusprofile_name}'s profile: {statusupdate}</p>
<p class="postedtime">Posted {statusfriendly_time}</p>
In action
Now that we have the model, controller, and views in place, all that leaves us
to do is create a controller record in the database for stream, and visit /stream
as a logged-in user
Room for improvement
We have developed a powerful status stream in this chapter, but as with anything
there is always room for improvement Let's discuss how this might be improved
and extended
Trang 6Firstly, there is some overlap in terms of logic and queries with the user's profile
and the status' delegator within the profile It may be possible for us to centralize
this functionality and use it in both these instances, perhaps generating a stream
for a profile or generating a stream for a network, depending on methods called
in the object
Secondly, we are doing a few small queries in the controller This is generally best
avoided, and instead models should be used to generate the comments, likes, and
dislikes We could create models for these, which this and the user's profile could
make use of
Plural names are currently hardcoded within the templates So if Bill posts on Ben's
profile, the text is generated by adding 's to the user's name Some names may only
require an apostrophe, so we could look at making this more dynamic
The final obvious area for improvement is the data it pulls in; it currently pulls in
the 20 most recent updates, taking an offset into account We may wish to detect
more recent updates since then, so a user could load in (perhaps through AJAX)
more recent status updates that have occurred while they have been viewing the
stream page
A system stream for administrators
While not as straightforward, as these events won't be centrally stored, we could
also create a stream of system events for the administrator These could include:
• Logins / logouts / signups
• Statuses
• Relationship formations
• When passwords are sent
• When e-mails are sent via the site, and so on
This isn't an essential feature, but could be a nice feature to have depending on
the size of the network and the size of the administrative team running the site
Trang 7In this chapter we have taken the statuses that users were able to update and post
thanks to our work in Chapter 5 and created a stream of these statuses that the user
can see, based on the activity and contacts within their network on Dino Space
This includes:
• Status updates
• Posting on other user's profiles
• Comments relating to these updates
• Likes / dislikes related to these updates
We've also looked at potential ways to improve and enhance this feature, as well
as what we might wish to consider adding for administrators to see an overview
of the system
With all of this now in place, let's move on to supporting new types of media on
the site, with images, videos, and links being posted onto the profiles of our users!
Trang 8Public and Private Messages
On Dino Space, we have a new status stream for our users to display the activity
happening in their network One of the things included in the stream was postings
on other users' wall posts, something which our database supports, but at the
moment, our site doesn't!
In this chapter, you will learn:
• How to allow users to post messages on each other's profiles
• How to allow users to post private messages to each other
Most social networking sites support two types of messages: public and private
messages Private messages are generally sent in a similar fashion to e-mails, and
public messages being posted on user's profiles for other users to see
Let's get started with extending our profiles and the status stream!
Public messages
Our status stream from Chapter 6 fully supports public messages and streaming
them to the Dino Space members What we don't yet have, however, is support
for users to post messages on the profiles of other users, so, let's add that in now
Controller
A user should only be able to post a message on another user's profile if they
are connected The post message form should only be displayed if the users are
connected Similarly, a public message post should only be processed if the two
users are connected The controller also needs to display messages that have
been posted on a user's profile too
Trang 9Displaying profile messages
If we look at our Profilestatusescontroller (controllers/profile/
profilestatusescontroller.php), in the listRecentStatuses method,
we have our query for listing recent profile statuses:
$sql = "SELECT t.type_reference, t.type_name, s.*, p.name as
poster_name FROM statuses s, status_types t, profile p
WHERE t.ID=s.type AND p.user_id=s.poster AND p.user_id={$user}
ORDER BY s.ID DESC LIMIT 20";
At the moment, this query pulls in any posts on a user's profile by the user whose
profile it is If that user has made a post on someone else's profile, the message
instead shows on the user's own profile, which we don't want
We need to change this to pull in the profiles table twice, once for the user who
made the post, and again for the user whose profile is being viewed We will also
want to only pull in posts made on the user's profile, and not posts made by the user
on another user's profile (though this is something we can expand on in the future,
perhaps to indicate that a user has made a post on the profile of another user)
The following query should meet our requirements nicely:
$sql = "SELECT t.type_reference, t.type_name, s.*, pa.name as
poster_name FROM statuses s, status_types t, profile p,
profile pa WHERE t.ID=s.type AND p.user_id=s.profile
AND pa.user_id=s.poster AND p.user_id={$user}
ORDER BY s.ID DESC LIMIT 20";
Now, if we view a user's profile, we see their own status updates, and messages
posted on their profile by other users, as shown in the following screenshot:
Trang 10Displaying the post message box
The listRecentStatuses method we were just editing is the method we need to
edit to display the post message box This box should only be displayed if the user is
logged in, and is connected to the user If the user is viewing their own profile, then
they should see a box to update their own status:
// post status / public message box
if( $this->registry->getObject('authenticate')->isLoggedIn() == true )
{
$loggedInUser = $this->registry->getObject('authenticate')-
>getUser()->getUserID();
If the logged in user is viewing their own profile, then we add the update template
to the view, so they can update their status:
if( $loggedInUser == $user )
{
$this->registry->getObject('template')->addTemplateBit( 'status_
update', 'profile/statuses/update.tpl.php' );
}
else
{
If the user isn't viewing their own profile, but is logged in, we get any connections
the user has:
require_once( FRAMEWORK_PATH 'models/relationships.php' );
$relationships = new Relationships( $this->registry );
$connections = $relationships->getNetwork( $user, false );
if( in_array( $loggedInUser, $connections ) )
{
If the user is connected to the user whose profile they are viewing, then we allow
them to post a message on the users profile with the post template:
$this->registry->getObject('template')->addTemplateBit(
'status_update', 'profile/statuses/post.tpl.php' );
}
else
{