]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Merge branch '0.9.x' into activityexport
authorEvan Prodromou <evan@status.net>
Thu, 16 Sep 2010 03:31:20 +0000 (23:31 -0400)
committerEvan Prodromou <evan@status.net>
Thu, 16 Sep 2010 03:31:20 +0000 (23:31 -0400)
classes/Fave.php
classes/Group_member.php
classes/Notice.php
classes/Subscription.php
lib/activity.php
lib/activitycontext.php
lib/atomusernoticefeed.php
lib/useractivitystream.php [new file with mode: 0644]
plugins/OStatus/OStatusPlugin.php
scripts/backupuser.php [new file with mode: 0644]

index ed4f56aeef0405b957534495aea326875bca4d9f..f21f1b5297613019a3efc2cc59072d1e2387ee1d 100644 (file)
@@ -129,4 +129,29 @@ class Fave extends Memcached_DataObject
 
         return $ids;
     }
+
+    function asActivity()
+    {
+        $notice  = Notice::staticGet('id', $this->notice_id);
+        $profile = Profile::staticGet('id', $this->user_id);
+
+        $act = new Activity();
+
+        $act->verb = ActivityVerb::FAVORITE;
+        $act->id   = TagURI::mint('favor:%d:%d:%s',
+                                  $profile->id,
+                                  $notice->id,
+                                  common_date_iso8601($this->modified));
+
+        $act->time    = strtotime($this->modified);
+        $act->title   = _("Favor");
+        $act->content = sprintf(_("%s marked notice %s as a favorite."),
+                               $profile->getBestName(),
+                               $notice->uri);
+
+        $act->actor     = ActivityObject::fromProfile($profile);
+        $act->objects[] = ActivityObject::fromNotice($notice);
+
+        return $act;
+    }
 }
index 2239461beb5e08b3b4253e0f76b3c472159d8b73..939a9cde76e8cf3049fc484a0e97db48473bcd7b 100644 (file)
@@ -65,4 +65,54 @@ class Group_member extends Memcached_DataObject
 
         return true;
     }
+
+    function getMember()
+    {
+        $member = Profile::staticGet('id', $this->profile_id);
+
+        if (empty($member)) {
+            throw new Exception("Profile ID {$this->profile_id} invalid.");
+        }
+
+        return $member;
+    }
+
+    function getGroup()
+    {
+        $group  = User_group::staticGet('id', $this->group_id);
+
+        if (empty($group)) {
+            throw new Exception("Group ID {$this->group_id} invalid.");
+        }
+
+        return $group;
+    }
+
+    function asActivity()
+    {
+        $member = $this->getMember();
+        $group  = $this->getGroup();
+
+        $act = new Activity();
+
+        $act->id = TagURI::mint('join:%d:%d:%s',
+                                $member->id,
+                                $group->id,
+                                common_date_iso8601($this->created));
+
+        $act->actor     = ActivityObject::fromProfile($member);
+        $act->verb      = ActivityVerb::JOIN;
+        $act->objects[] = ActivityObject::fromGroup($group);
+
+        $act->time  = strtotime($this->created);
+        $act->title = _("Join");
+
+        // TRANS: Success message for subscribe to group attempt through OStatus.
+        // TRANS: %1$s is the member name, %2$s is the subscribed group's name.
+        $act->content = sprintf(_('%1$s has joined group %2$s.'),
+                                $member->getBestName(),
+                                $group->getBestName());
+
+        return $act;
+    }
 }
index f1b012465b39cbd2c0766ffe8b211802d4d964b0..0539ca3b1d14215503e0ecf6036ed53cbeefe264 100644 (file)
@@ -1212,6 +1212,64 @@ class Notice extends Memcached_DataObject
         return $groups;
     }
 
+    function asActivity()
+    {
+        $profile = $this->getProfile();
+
+        $act = new Activity();
+
+        $act->actor     = ActivityObject::fromProfile($profile);
+        $act->verb      = ActivityVerb::POST;
+        $act->objects[] = ActivityObject::fromNotice($this);
+
+        $act->time    = strtotime($this->created);
+        $act->link    = $this->bestUrl();
+
+        $act->content = common_xml_safe_str($this->rendered);
+        $act->id      = $this->uri;
+        $act->title   = common_xml_safe_str($this->content);
+
+        $ctx = new ActivityContext();
+
+        if (!empty($this->reply_to)) {
+            $reply = Notice::staticGet('id', $this->reply_to);
+            if (!empty($reply)) {
+                $ctx->replyToID  = $reply->uri;
+                $ctx->replyToUrl = $reply->bestUrl();
+            }
+        }
+
+        $ctx->location = $this->getLocation();
+
+        $conv = null;
+
+        if (!empty($this->conversation)) {
+            $conv = Conversation::staticGet('id', $this->conversation);
+            if (!empty($conv)) {
+                $ctx->conversation = $conv->uri;
+            }
+        }
+
+        $reply_ids = $this->getReplies();
+
+        foreach ($reply_ids as $id) {
+            $profile = Profile::staticGet('id', $id);
+            if (!empty($profile)) {
+                $ctx->attention[] = $profile->uri;
+            }
+        }
+
+        $groups = $this->getGroups();
+
+        foreach ($groups as $group) {
+            $ctx->attention[] = $group->uri;
+        }
+
+        $act->context = $ctx;
+
+        return $act;
+    }
+
     // This has gotten way too long. Needs to be sliced up into functional bits
     // or ideally exported to a utility class.
 
index 0225ed4df97b9282bc8b5efd6d2175f8e216e8f2..1287499fadc1d8be090978076eaccb565cdf84dc 100644 (file)
@@ -235,4 +235,30 @@ class Subscription extends Memcached_DataObject
                                            'subscribed' => $other->id));
         return (empty($sub)) ? false : true;
     }
+
+    function asActivity()
+    {
+        $subscriber = Profile::staticGet('id', $this->subscriber);
+        $subscribed = Profile::staticGet('id', $this->subscribed);
+
+        $act = new Activity();
+
+        $act->verb = ActivityVerb::FOLLOW;
+
+        $act->id   = TagURI::mint('follow:%d:%d:%s',
+                                  $subscriber->id,
+                                  $subscribed->id,
+                                  common_date_iso8601($this->created));
+
+        $act->time    = strtotime($this->created);
+        $act->title   = _("Follow");
+        $act->content = sprintf(_("%s is now following %s."),
+                               $subscriber->getBestName(),
+                               $subscribed->getBestName());
+
+        $act->actor     = ActivityObject::fromProfile($subscriber);
+        $act->objects[] = ActivityObject::fromProfile($subscribed);
+
+        return $act;
+    }
 }
index 09a4daee828192e1827c0a31e4e4b2756db28322..f19f10e34dabfd647478d198ea2077c1ba3aaefe 100644 (file)
@@ -319,7 +319,7 @@ class Activity
         return null;
     }
 
-    function asString($namespace=false)
+    function asString($namespace=false, $author=true)
     {
         $xs = new XMLStringer(true);
 
@@ -338,7 +338,7 @@ class Activity
 
         $xs->element('id', null, $this->id);
         $xs->element('title', null, $this->title);
-        $xs->element('published', null, common_date_iso8601($this->time));
+        $xs->element('published', null, self::iso8601Date($this->time));
         $xs->element('content', array('type' => 'html'), $this->content);
 
         if (!empty($this->summary)) {
@@ -353,13 +353,15 @@ class Activity
 
         // XXX: add context
 
-        $xs->elementStart('author');
-        $xs->element('uri', array(), $this->actor->id);
-        if ($this->actor->title) {
-            $xs->element('name', array(), $this->actor->title);
+        if ($author) {
+            $xs->elementStart('author');
+            $xs->element('uri', array(), $this->actor->id);
+            if ($this->actor->title) {
+                $xs->element('name', array(), $this->actor->title);
+            }
+            $xs->elementEnd('author');
+            $xs->raw($this->actor->asString('activity:actor'));
         }
-        $xs->elementEnd('author');
-        $xs->raw($this->actor->asString('activity:actor'));
 
         $xs->element('activity:verb', null, $this->verb);
 
@@ -386,4 +388,12 @@ class Activity
     {
         return ActivityUtils::child($element, $tag, $namespace);
     }
+
+    static function iso8601Date($tm)
+    {
+        $dateStr = date('d F Y H:i:s', $tm);
+        $d = new DateTime($dateStr, new DateTimeZone('UTC'));
+        $d->setTimezone(new DateTimeZone(common_timezone()));
+        return $d->format('c');
+    }
 }
index cc02a0195582ef010f4bfdae01050d5055fcb373..ff3bc9411d53baeaa48b9b8d007769382bafef44 100644 (file)
@@ -54,8 +54,12 @@ class ActivityContext
     const MENTIONED    = 'mentioned';
     const CONVERSATION = 'ostatus:conversation';
 
-    function __construct($element)
+    function __construct($element = null)
     {
+        if (empty($element)) {
+            return;
+        }
+
         $replyToEl = ActivityUtils::child($element, self::INREPLYTO, self::THR);
 
         if (!empty($replyToEl)) {
index 785db4915b9c405be2cee021b4b1378360947ae0..34a18701754a505cf0a3002c36502a112f556134 100644 (file)
@@ -44,7 +44,7 @@ if (!defined('STATUSNET'))
  */
 class AtomUserNoticeFeed extends AtomNoticeFeed
 {
-    private $user;
+    protected $user;
 
     /**
      * Constructor
@@ -90,7 +90,7 @@ class AtomUserNoticeFeed extends AtomNoticeFeed
                 array('nickname' => $user->nickname)
             )
         );
-        
+
         $self = common_local_url('ApiTimelineUser',
                                  array('id' => $user->id,
                                        'format' => 'atom'));
diff --git a/lib/useractivitystream.php b/lib/useractivitystream.php
new file mode 100644 (file)
index 0000000..0fc315e
--- /dev/null
@@ -0,0 +1,151 @@
+<?php
+/*
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010 StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Class for activity streams
+ *
+ * Includes faves, notices, and subscriptions.
+ *
+ * We extend atomusernoticefeed since it does some nice setup for us.
+ *
+ */
+
+class UserActivityStream extends AtomUserNoticeFeed
+{
+    function __construct($user, $indent = true)
+    {
+        parent::__construct($user, null, $indent);
+
+        $subscriptions = $this->getSubscriptions();
+        $subscribers   = $this->getSubscribers();
+        $groups        = $this->getGroups();
+        $faves         = $this->getFaves();
+        $notices       = $this->getNotices();
+
+        $objs = array_merge($subscriptions, $subscribers, $groups, $faves, $notices);
+
+        // Sort by create date
+
+        usort($objs, 'UserActivityStream::compareObject');
+
+        foreach ($objs as $obj) {
+            $act = $obj->asActivity();
+            // Only show the author sub-element if it's different from default user
+            $str = $act->asString(false, ($act->actor->id != $this->user->uri));
+            $this->addEntryRaw($str);
+        }
+    }
+
+    function compareObject($a, $b)
+    {
+        $ac = strtotime((empty($a->created)) ? $a->modified : $a->created);
+        $bc = strtotime((empty($b->created)) ? $b->modified : $b->created);
+
+        return (($ac == $bc) ? 0 : (($ac < $bc) ? 1 : -1));
+    }
+
+    function getSubscriptions()
+    {
+        $subs = array();
+
+        $sub = new Subscription();
+
+        $sub->subscriber = $this->user->id;
+
+        if ($sub->find()) {
+            while ($sub->fetch()) {
+                if ($sub->subscribed != $this->user->id) {
+                    $subs[] = clone($sub);
+                }
+            }
+        }
+
+        return $subs;
+    }
+
+    function getSubscribers()
+    {
+        $subs = array();
+
+        $sub = new Subscription();
+
+        $sub->subscribed = $this->user->id;
+
+        if ($sub->find()) {
+            while ($sub->fetch()) {
+                if ($sub->subscriber != $this->user->id) {
+                    $subs[] = clone($sub);
+                }
+            }
+        }
+
+        return $subs;
+    }
+
+    function getFaves()
+    {
+        $faves = array();
+
+        $fave = new Fave();
+
+        $fave->user_id = $this->user->id;
+
+        if ($fave->find()) {
+            while ($fave->fetch()) {
+                $faves[] = clone($fave);
+            }
+        }
+
+        return $faves;
+    }
+
+    function getNotices()
+    {
+        $notices = array();
+
+        $notice = new Notice();
+
+        $notice->profile_id = $this->user->id;
+
+        if ($notice->find()) {
+            while ($notice->fetch()) {
+                $notices[] = clone($notice);
+            }
+        }
+
+        return $notices;
+    }
+
+    function getGroups()
+    {
+        $groups = array();
+
+        $gm = new Group_member();
+
+        $gm->profile_id = $this->user->id;
+
+        if ($gm->find()) {
+            while ($gm->fetch()) {
+                $groups[] = clone($gm);
+            }
+        }
+
+        return $groups;
+    }
+}
index 77bc9872b401827057bc6b5c92fc118ead2b4fb1..98f18f83380cc7d1b54be805ad60c6ed363827d0 100644 (file)
@@ -553,25 +553,10 @@ class OStatusPlugin extends Plugin
             return true;
         }
 
-        $act = new Activity();
-
-        $act->verb = ActivityVerb::FOLLOW;
+        $sub = Subscription::pkeyGet(array('subscriber' => $subscriber->id,
+                                           'subscribed' => $other->id));
 
-        $act->id   = TagURI::mint('follow:%d:%d:%s',
-                                  $subscriber->id,
-                                  $other->id,
-                                  common_date_iso8601(time()));
-
-        $act->time    = time();
-        $act->title   = _("Follow");
-        // TRANS: Success message for subscribe to user attempt through OStatus.
-        // TRANS: %1$s is the subscriber name, %2$s is the subscribed user's name.
-        $act->content = sprintf(_("%1$s is now following %2$s."),
-                               $subscriber->getBestName(),
-                               $other->getBestName());
-
-        $act->actor   = ActivityObject::fromProfile($subscriber);
-        $act->object  = ActivityObject::fromProfile($other);
+        $act = $sub->asActivity();
 
         $oprofile->notifyActivity($act, $subscriber);
 
@@ -647,6 +632,9 @@ class OStatusPlugin extends Plugin
                 throw new Exception(_m('Could not set up remote group membership.'));
             }
 
+            // NOTE: we don't use Group_member::asActivity() since that record
+            // has not yet been created.
+
             $member = Profile::staticGet($user->id);
 
             $act = new Activity();
@@ -744,24 +732,15 @@ class OStatusPlugin extends Plugin
             return true;
         }
 
-        $act = new Activity();
-
-        $act->verb = ActivityVerb::FAVORITE;
-        $act->id   = TagURI::mint('favor:%d:%d:%s',
-                                  $profile->id,
-                                  $notice->id,
-                                  common_date_iso8601(time()));
+        $fav = Fave::pkeyGet(array('user_id' => $user->id,
+                                   'notice_id' => $notice->id));
 
-        $act->time    = time();
-        $act->title   = _("Favor");
-        // TRANS: Success message for adding a favorite notice through OStatus.
-        // TRANS: %1$s is the favoring user's name, %2$s is URI to the favored notice.
-        $act->content = sprintf(_("%1$s marked notice %2$s as a favorite."),
-                               $profile->getBestName(),
-                               $notice->uri);
+        if (empty($fav)) {
+            // That's weird.
+            return true;
+        }
 
-        $act->actor   = ActivityObject::fromProfile($profile);
-        $act->object  = ActivityObject::fromNotice($notice);
+        $act = $fav->asActivity();
 
         $oprofile->notifyActivity($act, $profile);
 
diff --git a/scripts/backupuser.php b/scripts/backupuser.php
new file mode 100644 (file)
index 0000000..56a5481
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+/*
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010 StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
+
+$shortoptions = 'i:n:f:';
+$longoptions = array('id=', 'nickname=', 'file=');
+
+$helptext = <<<END_OF_EXPORTACTIVITYSTREAM_HELP
+exportactivitystream.php [options]
+Export a StatusNet user history to a file
+
+  -i --id       ID of user to export
+  -n --nickname nickname of the user to export
+  -f --file     file to export to (default STDOUT)
+
+END_OF_EXPORTACTIVITYSTREAM_HELP;
+
+require_once INSTALLDIR.'/scripts/commandline.inc';
+
+function getUser()
+{
+    $user = null;
+
+    if (have_option('i', 'id')) {
+        $id = get_option_value('i', 'id');
+        $user = User::staticGet('id', $id);
+        if (empty($user)) {
+            throw new Exception("Can't find user with id '$id'.");
+        }
+    } else if (have_option('n', 'nickname')) {
+        $nickname = get_option_value('n', 'nickname');
+        $user = User::staticGet('nickname', $nickname);
+        if (empty($user)) {
+            throw new Exception("Can't find user with nickname '$nickname'");
+        }
+    } else {
+        show_help();
+        exit(1);
+    }
+
+    return $user;
+}
+
+try {
+    $user = getUser();
+    $actstr = new UserActivityStream($user);
+    print $actstr->getString();
+} catch (Exception $e) {
+    print $e->getMessage()."\n";
+    exit(1);
+}