3 * StatusNet - the distributed open-source microblogging tool
4 * Copyright (C) 2010, StatusNet, Inc.
6 * Shows social activities in the output feed
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Affero General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Affero General Public License for more details.
20 * You should have received a copy of the GNU Affero General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 * @author Evan Prodromou <evan@status.net>
26 * @copyright 2010 StatusNet, Inc.
27 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
28 * @link http://status.net/
31 if (!defined('STATUSNET')) {
32 // This check helps protect against security problems;
33 // your code file can't be executed directly from the web.
38 * Activity plugin main class
42 * @author Evan Prodromou <evan@status.net>
43 * @copyright 2010 StatusNet, Inc.
44 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
45 * @link http://status.net/
47 class ActivityPlugin extends Plugin
49 const VERSION = '0.1';
50 const SOURCE = 'activity';
52 // Flags to switch off certain activity notices
53 public $StartFollowUser = true;
54 public $StopFollowUser = false;
55 public $JoinGroup = true;
56 public $LeaveGroup = false;
57 public $StartLike = false;
58 public $StopLike = false;
60 function onEndSubscribe($subscriber, $other)
62 // Only do this if config is enabled
63 if(!$this->StartFollowUser) return true;
64 $user = $subscriber->getUser();
66 $sub = Subscription::pkeyGet(array('subscriber' => $subscriber->id,
67 'subscribed' => $other->id));
68 // TRANS: Text for "started following" item in activity plugin.
69 // TRANS: %1$s is a profile URL, %2$s is a profile name,
70 // TRANS: %3$s is a profile URL, %4$s is a profile name.
71 $rendered = sprintf(_m('<a href="%1$s">%2$s</a> started following <a href="%3$s">%4$s</a>.'),
72 $subscriber->profileurl,
73 $subscriber->getBestName(),
75 $other->getBestName());
76 // TRANS: Text for "started following" item in activity plugin.
77 // TRANS: %1$s is a profile name, %2$s is a profile URL,
78 // TRANS: %3$s is a profile name, %4$s is a profile URL.
79 $content = sprintf(_m('%1$s (%2$s) started following %3$s (%4$s).'),
80 $subscriber->getBestName(),
81 $subscriber->profileurl,
82 $other->getBestName(),
85 $notice = Notice::saveNew($user->id,
87 ActivityPlugin::SOURCE,
88 array('rendered' => $rendered,
90 'replies' => array($other->getUri()),
91 'verb' => ActivityVerb::FOLLOW,
92 'object_type' => ActivityObject::PERSON,
98 function onEndUnsubscribe($subscriber, $other)
100 // Only do this if config is enabled
101 if(!$this->StopFollowUser) return true;
102 $user = $subscriber->getUser();
104 // TRANS: Text for "stopped following" item in activity plugin.
105 // TRANS: %1$s is a profile URL, %2$s is a profile name,
106 // TRANS: %3$s is a profile URL, %4$s is a profile name.
107 $rendered = sprintf(_m('<a href="%1$s">%2$s</a> stopped following <a href="%3$s">%4$s</a>.'),
108 $subscriber->profileurl,
109 $subscriber->getBestName(),
111 $other->getBestName());
112 // TRANS: Text for "stopped following" item in activity plugin.
113 // TRANS: %1$s is a profile name, %2$s is a profile URL,
114 // TRANS: %3$s is a profile name, %4$s is a profile URL.
115 $content = sprintf(_m('%1$s (%2$s) stopped following %3$s (%4$s).'),
116 $subscriber->getBestName(),
117 $subscriber->profileurl,
118 $other->getBestName(),
121 $uri = TagURI::mint('stop-following:%d:%d:%s',
124 common_date_iso8601(common_sql_now()));
126 $notice = Notice::saveNew($user->id,
128 ActivityPlugin::SOURCE,
129 array('rendered' => $rendered,
131 'replies' => array($other->getUri()),
133 'verb' => ActivityVerb::UNFOLLOW,
134 'object_type' => ActivityObject::PERSON));
139 function onEndFavorNotice($profile, $notice)
141 // Only do this if config is enabled
142 if(!$this->StartLike) return true;
144 $user = $profile->getUser();
148 $author = $notice->getProfile();
149 $fave = Fave::pkeyGet(array('user_id' => $user->id,
150 'notice_id' => $notice->id));
152 // TRANS: Text for "liked" item in activity plugin.
153 // TRANS: %1$s is a profile URL, %2$s is a profile name,
154 // TRANS: %3$s is a notice URL, %4$s is an author name.
155 $rendered = sprintf(_m('<a href="%1$s">%2$s</a> liked <a href="%3$s">%4$s\'s update</a>.'),
156 $profile->profileurl,
157 $profile->getBestName(),
159 $author->getBestName());
160 // TRANS: Text for "liked" item in activity plugin.
161 // TRANS: %1$s is a profile name, %2$s is a profile URL,
162 // TRANS: %3$s is an author name, %4$s is a notice URL.
163 $content = sprintf(_m('%1$s (%2$s) liked %3$s\'s status (%4$s).'),
164 $profile->getBestName(),
165 $profile->profileurl,
166 $author->getBestName(),
169 $notice = Notice::saveNew($user->id,
171 ActivityPlugin::SOURCE,
172 array('rendered' => $rendered,
174 'replies' => array($author->getUri()),
175 'uri' => $fave->getURI(),
176 'verb' => ActivityVerb::FAVORITE,
177 'object_type' => (($notice->verb == ActivityVerb::POST) ?
178 $notice->object_type : ActivityObject::ACTIVITY)));
183 function onEndDisfavorNotice($profile, $notice)
185 // Only do this if config is enabled
186 if(!$this->StopLike) return true;
187 $user = User::getKV('id', $profile->id);
190 $author = Profile::getKV('id', $notice->profile_id);
191 // TRANS: Text for "stopped liking" item in activity plugin.
192 // TRANS: %1$s is a profile URL, %2$s is a profile name,
193 // TRANS: %3$s is a notice URL, %4$s is an author name.
194 $rendered = sprintf(_m('<a href="%1$s">%2$s</a> stopped liking <a href="%3$s">%4$s\'s update</a>.'),
195 $profile->profileurl,
196 $profile->getBestName(),
198 $author->getBestName());
199 // TRANS: Text for "stopped liking" item in activity plugin.
200 // TRANS: %1$s is a profile name, %2$s is a profile URL,
201 // TRANS: %3$s is an author name, %4$s is a notice URL.
202 $content = sprintf(_m('%1$s (%2$s) stopped liking %3$s\'s status (%4$s).'),
203 $profile->getBestName(),
204 $profile->profileurl,
205 $author->getBestName(),
208 $uri = TagURI::mint('unlike:%d:%d:%s',
211 common_date_iso8601(common_sql_now()));
213 $notice = Notice::saveNew($user->id,
215 ActivityPlugin::SOURCE,
216 array('rendered' => $rendered,
218 'replies' => array($author->getUri()),
220 'verb' => ActivityVerb::UNFAVORITE,
221 'object_type' => (($notice->verb == ActivityVerb::POST) ?
222 $notice->object_type : ActivityObject::ACTIVITY)));
227 function onEndJoinGroup($group, $profile)
229 // Only do this if config is enabled
230 if(!$this->JoinGroup) return true;
232 $user = $profile->getUser();
238 // TRANS: Text for "joined group" item in activity plugin.
239 // TRANS: %1$s is a profile URL, %2$s is a profile name,
240 // TRANS: %3$s is a group URL, %4$s is a group name.
241 $rendered = sprintf(_m('<a href="%1$s">%2$s</a> joined the group <a href="%3$s">%4$s</a>.'),
242 $profile->profileurl,
243 $profile->getBestName(),
245 $group->getBestName());
246 // TRANS: Text for "joined group" item in activity plugin.
247 // TRANS: %1$s is a profile name, %2$s is a profile URL,
248 // TRANS: %3$s is a group name, %4$s is a group URL.
249 $content = sprintf(_m('%1$s (%2$s) joined the group %3$s (%4$s).'),
250 $profile->getBestName(),
251 $profile->profileurl,
252 $group->getBestName(),
255 $mem = Group_member::pkeyGet(array('group_id' => $group->id,
256 'profile_id' => $profile->id));
258 $notice = Notice::saveNew($user->id,
260 ActivityPlugin::SOURCE,
261 array('rendered' => $rendered,
263 'groups' => array($group->id),
264 'uri' => $mem->getURI(),
265 'verb' => ActivityVerb::JOIN,
266 'object_type' => ActivityObject::GROUP));
270 function onEndLeaveGroup($group, $profile)
272 // Only do this if config is enabled
273 if(!$this->LeaveGroup) return true;
275 $user = $profile->getUser();
281 // TRANS: Text for "left group" item in activity plugin.
282 // TRANS: %1$s is a profile URL, %2$s is a profile name,
283 // TRANS: %3$s is a group URL, %4$s is a group name.
284 $rendered = sprintf(_m('<a href="%1$s">%2$s</a> left the group <a href="%3$s">%4$s</a>.'),
285 $profile->profileurl,
286 $profile->getBestName(),
288 $group->getBestName());
289 // TRANS: Text for "left group" item in activity plugin.
290 // TRANS: %1$s is a profile name, %2$s is a profile URL,
291 // TRANS: %3$s is a group name, %4$s is a group URL.
292 $content = sprintf(_m('%1$s (%2$s) left the group %3$s (%4$s).'),
293 $profile->getBestName(),
294 $profile->profileurl,
295 $group->getBestName(),
298 $uri = TagURI::mint('leave:%d:%d:%s',
301 common_date_iso8601(common_sql_now()));
303 $notice = Notice::saveNew($user->id,
305 ActivityPlugin::SOURCE,
306 array('rendered' => $rendered,
308 'groups' => array($group->id),
310 'verb' => ActivityVerb::LEAVE,
311 'object_type' => ActivityObject::GROUP));
315 function onStartShowNoticeItem($nli)
317 $notice = $nli->notice;
321 switch ($notice->verb) {
322 case ActivityVerb::FAVORITE:
323 case ActivityVerb::UNFAVORITE:
324 $adapter = new SystemListItem($nli);
326 case ActivityVerb::JOIN:
327 $adapter = new JoinListItem($nli);
329 case ActivityVerb::LEAVE:
330 $adapter = new JoinListItem($nli);
332 case ActivityVerb::FOLLOW:
333 $adapter = new FollowListItem($nli);
335 case ActivityVerb::UNFOLLOW:
336 $adapter = new UnfollowListItem($nli);
340 if (!empty($adapter)) {
341 $adapter->showNotice();
342 $adapter->showNoticeAttachments();
343 $adapter->showNoticeInfo();
344 $adapter->showNoticeOptions();
351 function onEndNoticeAsActivity($notice, &$activity)
353 switch ($notice->verb) {
354 case ActivityVerb::FAVORITE:
355 $fave = Fave::getKV('uri', $notice->uri);
357 $notice = Notice::getKV('id', $fave->notice_id);
358 if (!empty($notice)) {
359 $cur = common_current_user();
360 $target = $notice->asActivity($cur);
361 if ($target->verb == ActivityVerb::POST) {
362 // "I like the thing you posted"
363 $activity->objects = $target->objects;
365 // "I like that you did whatever you did"
366 $activity->objects = array($target);
371 case ActivityVerb::UNFAVORITE:
372 // FIXME: do something here
374 case ActivityVerb::JOIN:
375 $mem = Group_member::getKV('uri', $notice->uri);
377 $group = $mem->getGroup();
378 $activity->objects = array(ActivityObject::fromGroup($group));
381 case ActivityVerb::LEAVE:
384 case ActivityVerb::FOLLOW:
385 $sub = Subscription::getKV('uri', $notice->uri);
387 $profile = Profile::getKV('id', $sub->subscribed);
388 if (!empty($profile)) {
389 $activity->objects = array(ActivityObject::fromProfile($profile));
393 case ActivityVerb::UNFOLLOW:
401 function onPluginVersion(&$versions)
403 $versions[] = array('name' => 'Activity',
404 'version' => self::VERSION,
405 'author' => 'Evan Prodromou',
406 'homepage' => 'http://status.net/wiki/Plugin:Activity',
408 // TRANS: Plugin description.
409 _m('Emits notices when social activities happen.'));