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(Profile $profile, Profile $other)
62 // Only do this if config is enabled
63 if(!$this->StartFollowUser) return true;
65 if (!$profile->isLocal()) {
66 // can't do anything with remote user anyway
70 $sub = Subscription::pkeyGet(array('subscriber' => $profile->id,
71 'subscribed' => $other->id));
72 // TRANS: Text for "started following" item in activity plugin.
73 // TRANS: %1$s is a profile URL, %2$s is a profile name,
74 // TRANS: %3$s is a profile URL, %4$s is a profile name.
75 $rendered = sprintf(_m('<a href="%1$s">%2$s</a> started following <a href="%3$s">%4$s</a>.'),
77 $profile->getBestName(),
79 $other->getBestName());
80 // TRANS: Text for "started following" item in activity plugin.
81 // TRANS: %1$s is a profile name, %2$s is a profile URL,
82 // TRANS: %3$s is a profile name, %4$s is a profile URL.
83 $content = sprintf(_m('%1$s (%2$s) started following %3$s (%4$s).'),
84 $profile->getBestName(),
86 $other->getBestName(),
89 $notice = Notice::saveNew($profile->id,
91 ActivityPlugin::SOURCE,
92 array('rendered' => $rendered,
94 'replies' => array($other->getUri()),
95 'verb' => ActivityVerb::FOLLOW,
96 'object_type' => ActivityObject::PERSON,
101 function onEndUnsubscribe(Profile $profile, Profile $other)
103 // Only do this if config is enabled
104 if(!$this->StopFollowUser) return true;
106 if (!$profile->isLocal()) {
110 // TRANS: Text for "stopped following" item in activity plugin.
111 // TRANS: %1$s is a profile URL, %2$s is a profile name,
112 // TRANS: %3$s is a profile URL, %4$s is a profile name.
113 $rendered = sprintf(_m('<a href="%1$s">%2$s</a> stopped following <a href="%3$s">%4$s</a>.'),
114 $profile->profileurl,
115 $profile->getBestName(),
117 $other->getBestName());
118 // TRANS: Text for "stopped following" item in activity plugin.
119 // TRANS: %1$s is a profile name, %2$s is a profile URL,
120 // TRANS: %3$s is a profile name, %4$s is a profile URL.
121 $content = sprintf(_m('%1$s (%2$s) stopped following %3$s (%4$s).'),
122 $profile->getBestName(),
123 $profile->profileurl,
124 $other->getBestName(),
127 $uri = TagURI::mint('stop-following:%d:%d:%s',
130 common_date_iso8601(common_sql_now()));
132 $notice = Notice::saveNew($profile->id,
134 ActivityPlugin::SOURCE,
135 array('rendered' => $rendered,
137 'replies' => array($other->getUri()),
139 'verb' => ActivityVerb::UNFOLLOW,
140 'object_type' => ActivityObject::PERSON));
145 function onEndFavorNotice($profile, $notice)
147 // Only do this if config is enabled
148 if(!$this->StartLike) return true;
150 if (!$profile->isLocal()) {
154 $author = $notice->getProfile();
155 $fave = Fave::pkeyGet(array('user_id' => $profile->id,
156 'notice_id' => $notice->id));
158 // TRANS: Text for "liked" item in activity plugin.
159 // TRANS: %1$s is a profile URL, %2$s is a profile name,
160 // TRANS: %3$s is a notice URL, %4$s is an author name.
161 $rendered = sprintf(_m('<a href="%1$s">%2$s</a> liked <a href="%3$s">%4$s\'s update</a>.'),
162 $profile->profileurl,
163 $profile->getBestName(),
165 $author->getBestName());
166 // TRANS: Text for "liked" item in activity plugin.
167 // TRANS: %1$s is a profile name, %2$s is a profile URL,
168 // TRANS: %3$s is an author name, %4$s is a notice URL.
169 $content = sprintf(_m('%1$s (%2$s) liked %3$s\'s status (%4$s).'),
170 $profile->getBestName(),
171 $profile->profileurl,
172 $author->getBestName(),
175 $notice = Notice::saveNew($profile->id,
177 ActivityPlugin::SOURCE,
178 array('rendered' => $rendered,
180 'replies' => array($author->getUri()),
181 'uri' => $fave->getURI(),
182 'verb' => ActivityVerb::FAVORITE,
183 'object_type' => (($notice->verb == ActivityVerb::POST) ?
184 $notice->object_type : ActivityObject::ACTIVITY)));
189 function onEndDisfavorNotice($profile, $notice)
191 // Only do this if config is enabled
192 if(!$this->StopLike) return true;
194 if (!$profile->isLocal()) {
198 $author = Profile::getKV('id', $notice->profile_id);
199 // TRANS: Text for "stopped liking" item in activity plugin.
200 // TRANS: %1$s is a profile URL, %2$s is a profile name,
201 // TRANS: %3$s is a notice URL, %4$s is an author name.
202 $rendered = sprintf(_m('<a href="%1$s">%2$s</a> stopped liking <a href="%3$s">%4$s\'s update</a>.'),
203 $profile->profileurl,
204 $profile->getBestName(),
206 $author->getBestName());
207 // TRANS: Text for "stopped liking" item in activity plugin.
208 // TRANS: %1$s is a profile name, %2$s is a profile URL,
209 // TRANS: %3$s is an author name, %4$s is a notice URL.
210 $content = sprintf(_m('%1$s (%2$s) stopped liking %3$s\'s status (%4$s).'),
211 $profile->getBestName(),
212 $profile->profileurl,
213 $author->getBestName(),
216 $uri = TagURI::mint('unlike:%d:%d:%s',
219 common_date_iso8601(common_sql_now()));
221 $notice = Notice::saveNew($profile->id,
223 ActivityPlugin::SOURCE,
224 array('rendered' => $rendered,
226 'replies' => array($author->getUri()),
228 'verb' => ActivityVerb::UNFAVORITE,
229 'object_type' => (($notice->verb == ActivityVerb::POST) ?
230 $notice->object_type : ActivityObject::ACTIVITY)));
235 function onEndJoinGroup($group, $profile)
237 // Only do this if config is enabled
238 if(!$this->JoinGroup) return true;
240 if (!$profile->isLocal()) {
244 // TRANS: Text for "joined group" item in activity plugin.
245 // TRANS: %1$s is a profile URL, %2$s is a profile name,
246 // TRANS: %3$s is a group URL, %4$s is a group name.
247 $rendered = sprintf(_m('<a href="%1$s">%2$s</a> joined the group <a href="%3$s">%4$s</a>.'),
248 $profile->profileurl,
249 $profile->getBestName(),
251 $group->getBestName());
252 // TRANS: Text for "joined group" item in activity plugin.
253 // TRANS: %1$s is a profile name, %2$s is a profile URL,
254 // TRANS: %3$s is a group name, %4$s is a group URL.
255 $content = sprintf(_m('%1$s (%2$s) joined the group %3$s (%4$s).'),
256 $profile->getBestName(),
257 $profile->profileurl,
258 $group->getBestName(),
261 $mem = Group_member::pkeyGet(array('group_id' => $group->id,
262 'profile_id' => $profile->id));
264 $notice = Notice::saveNew($profile->id,
266 ActivityPlugin::SOURCE,
267 array('rendered' => $rendered,
269 'groups' => array($group->id),
270 'uri' => $mem->getURI(),
271 'verb' => ActivityVerb::JOIN,
272 'object_type' => ActivityObject::GROUP));
276 function onEndLeaveGroup($group, $profile)
278 // Only do this if config is enabled
279 if(!$this->LeaveGroup) return true;
281 if (!$profile->isLocal()) {
285 // TRANS: Text for "left group" item in activity plugin.
286 // TRANS: %1$s is a profile URL, %2$s is a profile name,
287 // TRANS: %3$s is a group URL, %4$s is a group name.
288 $rendered = sprintf(_m('<a href="%1$s">%2$s</a> left the group <a href="%3$s">%4$s</a>.'),
289 $profile->profileurl,
290 $profile->getBestName(),
292 $group->getBestName());
293 // TRANS: Text for "left group" item in activity plugin.
294 // TRANS: %1$s is a profile name, %2$s is a profile URL,
295 // TRANS: %3$s is a group name, %4$s is a group URL.
296 $content = sprintf(_m('%1$s (%2$s) left the group %3$s (%4$s).'),
297 $profile->getBestName(),
298 $profile->profileurl,
299 $group->getBestName(),
302 $uri = TagURI::mint('leave:%d:%d:%s',
305 common_date_iso8601(common_sql_now()));
307 $notice = Notice::saveNew($profile->id,
309 ActivityPlugin::SOURCE,
310 array('rendered' => $rendered,
312 'groups' => array($group->id),
314 'verb' => ActivityVerb::LEAVE,
315 'object_type' => ActivityObject::GROUP));
319 function onStartShowNoticeItem($nli)
321 $notice = $nli->notice;
325 switch ($notice->verb) {
326 case ActivityVerb::FAVORITE:
327 case ActivityVerb::UNFAVORITE:
328 $adapter = new SystemListItem($nli);
330 case ActivityVerb::JOIN:
331 $adapter = new JoinListItem($nli);
333 case ActivityVerb::LEAVE:
334 $adapter = new JoinListItem($nli);
336 case ActivityVerb::FOLLOW:
337 $adapter = new FollowListItem($nli);
339 case ActivityVerb::UNFOLLOW:
340 $adapter = new UnfollowListItem($nli);
344 if (!empty($adapter)) {
345 $adapter->showNotice();
346 $adapter->showNoticeAttachments();
347 $adapter->showNoticeInfo();
348 $adapter->showNoticeOptions();
355 function onEndNoticeAsActivity($notice, &$activity)
357 switch ($notice->verb) {
358 case ActivityVerb::FAVORITE:
359 $fave = Fave::getKV('uri', $notice->uri);
361 $notice = Notice::getKV('id', $fave->notice_id);
362 if (!empty($notice)) {
363 $cur = common_current_user();
364 $target = $notice->asActivity($cur);
365 if ($target->verb == ActivityVerb::POST) {
366 // "I like the thing you posted"
367 $activity->objects = $target->objects;
369 // "I like that you did whatever you did"
370 $activity->objects = array($target);
375 case ActivityVerb::UNFAVORITE:
376 // FIXME: do something here
378 case ActivityVerb::JOIN:
379 $mem = Group_member::getKV('uri', $notice->uri);
381 $group = $mem->getGroup();
382 $activity->objects = array(ActivityObject::fromGroup($group));
385 case ActivityVerb::LEAVE:
388 case ActivityVerb::FOLLOW:
389 $sub = Subscription::getKV('uri', $notice->uri);
391 $profile = Profile::getKV('id', $sub->subscribed);
392 if (!empty($profile)) {
393 $activity->objects = array(ActivityObject::fromProfile($profile));
397 case ActivityVerb::UNFOLLOW:
405 function onPluginVersion(&$versions)
407 $versions[] = array('name' => 'Activity',
408 'version' => self::VERSION,
409 'author' => 'Evan Prodromou',
410 'homepage' => 'http://status.net/wiki/Plugin:Activity',
412 // TRANS: Plugin description.
413 _m('Emits notices when social activities happen.'));