From b5b5184c885e74d9532409a5962f851c4baf41c4 Mon Sep 17 00:00:00 2001
From: Brion Vibber <brion@pobox.com>
Date: Thu, 25 Feb 2010 13:02:08 -0800
Subject: [PATCH 1/2] OStatus: fix remote groups to work with new
 user_groups/local_groups split. - fix <activity:subject> generation so we get
 the profile info (what's available so far) - use id instead of nickname for
 group join/leave forms so we can join/leave remote groups   while the rest of
 the groups UI remains limited to local groups   (plugins are responsible for
 making sure remote notifications and permission checks are done) - fix remote
 notification when joining group through OStatus's remote subscribe form

---
 actions/joingroup.php                       | 41 +++++++++++----------
 actions/leavegroup.php                      | 41 +++++++++++----------
 classes/User_group.php                      |  2 +-
 lib/activity.php                            |  7 +++-
 lib/joinform.php                            |  2 +-
 lib/leaveform.php                           |  2 +-
 lib/router.php                              |  3 ++
 plugins/OStatus/actions/ostatussub.php      | 14 +++++--
 plugins/OStatus/classes/Ostatus_profile.php | 26 +++++++------
 9 files changed, 81 insertions(+), 57 deletions(-)

diff --git a/actions/joingroup.php b/actions/joingroup.php
index ba642f7129..f87e5dae29 100644
--- a/actions/joingroup.php
+++ b/actions/joingroup.php
@@ -62,30 +62,33 @@ class JoingroupAction extends Action
         }
 
         $nickname_arg = $this->trimmed('nickname');
-        $nickname = common_canonical_nickname($nickname_arg);
+        $id = intval($this->arg('id'));
+        if ($id) {
+            $this->group = User_group::staticGet('id', $id);
+        } else if ($nickname_arg) {
+            $nickname = common_canonical_nickname($nickname_arg);
 
-        // Permanent redirect on non-canonical nickname
+            // Permanent redirect on non-canonical nickname
 
-        if ($nickname_arg != $nickname) {
-            $args = array('nickname' => $nickname);
-            common_redirect(common_local_url('joingroup', $args), 301);
+            if ($nickname_arg != $nickname) {
+                $args = array('nickname' => $nickname);
+                common_redirect(common_local_url('leavegroup', $args), 301);
+                return false;
+            }
+
+            $local = Local_group::staticGet('nickname', $nickname);
+
+            if (!$local) {
+                $this->clientError(_('No such group.'), 404);
+                return false;
+            }
+
+            $this->group = User_group::staticGet('id', $local->group_id);
+        } else {
+            $this->clientError(_('No nickname or ID.'), 404);
             return false;
         }
 
-        if (!$nickname) {
-            $this->clientError(_('No nickname.'), 404);
-            return false;
-        }
-
-        $local = Local_group::staticGet('nickname', $nickname);
-
-        if (!$local) {
-            $this->clientError(_('No such group.'), 404);
-            return false;
-        }
-
-        $this->group = User_group::staticGet('id', $local->group_id);
-
         if (!$this->group) {
             $this->clientError(_('No such group.'), 404);
             return false;
diff --git a/actions/leavegroup.php b/actions/leavegroup.php
index 222d4c1b43..329b5aafe1 100644
--- a/actions/leavegroup.php
+++ b/actions/leavegroup.php
@@ -62,30 +62,33 @@ class LeavegroupAction extends Action
         }
 
         $nickname_arg = $this->trimmed('nickname');
-        $nickname = common_canonical_nickname($nickname_arg);
+        $id = intval($this->arg('id'));
+        if ($id) {
+            $this->group = User_group::staticGet('id', $id);
+        } else if ($nickname_arg) {
+            $nickname = common_canonical_nickname($nickname_arg);
 
-        // Permanent redirect on non-canonical nickname
+            // Permanent redirect on non-canonical nickname
 
-        if ($nickname_arg != $nickname) {
-            $args = array('nickname' => $nickname);
-            common_redirect(common_local_url('leavegroup', $args), 301);
+            if ($nickname_arg != $nickname) {
+                $args = array('nickname' => $nickname);
+                common_redirect(common_local_url('leavegroup', $args), 301);
+                return false;
+            }
+
+            $local = Local_group::staticGet('nickname', $nickname);
+
+            if (!$local) {
+                $this->clientError(_('No such group.'), 404);
+                return false;
+            }
+
+            $this->group = User_group::staticGet('id', $local->group_id);
+        } else {
+            $this->clientError(_('No nickname or ID.'), 404);
             return false;
         }
 
-        if (!$nickname) {
-            $this->clientError(_('No nickname.'), 404);
-            return false;
-        }
-
-        $local = Local_group::staticGet('nickname', $nickname);
-
-        if (!$local) {
-            $this->clientError(_('No such group.'), 404);
-            return false;
-        }
-
-        $this->group = User_group::staticGet('id', $local->group_id);
-
         if (!$this->group) {
             $this->clientError(_('No such group.'), 404);
             return false;
diff --git a/classes/User_group.php b/classes/User_group.php
index f24bef7647..2a58d88959 100644
--- a/classes/User_group.php
+++ b/classes/User_group.php
@@ -404,7 +404,7 @@ class User_group extends Memcached_DataObject
         $xs = new XMLStringer(true);
 
         $xs->elementStart('activity:subject');
-        $xs->element('activity:object', null, 'http://activitystrea.ms/schema/1.0/group');
+        $xs->element('activity:object-type', null, 'http://activitystrea.ms/schema/1.0/group');
         $xs->element('id', null, $this->permalink());
         $xs->element('title', null, $this->getBestName());
         $xs->element(
diff --git a/lib/activity.php b/lib/activity.php
index e592aad6ff..4e7ff5336e 100644
--- a/lib/activity.php
+++ b/lib/activity.php
@@ -610,7 +610,10 @@ class ActivityObject
         $object->id     = $profile->getUri();
         $object->title  = $profile->getBestName();
         $object->link   = $profile->profileurl;
-        $object->avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
+        $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
+        if ($avatar) {
+            $object->avatar = $avatar->displayUrl();
+        }
 
         if (isset($profile->lat) && isset($profile->lon)) {
             $object->geopoint = (float)$profile->lat . ' ' . (float)$profile->lon;
@@ -664,7 +667,7 @@ class ActivityObject
                     'rel'  => 'avatar',
                     'href' => empty($this->avatar)
                     ? Avatar::defaultImage(AVATAR_PROFILE_SIZE)
-                    : $this->avatar->displayUrl()
+                    : $this->avatar
                 ),
                 null
             );
diff --git a/lib/joinform.php b/lib/joinform.php
index aefb553aac..aa8bc20e24 100644
--- a/lib/joinform.php
+++ b/lib/joinform.php
@@ -100,7 +100,7 @@ class JoinForm extends Form
     function action()
     {
         return common_local_url('joingroup',
-                                array('nickname' => $this->group->nickname));
+                                array('id' => $this->group->id));
     }
 
     /**
diff --git a/lib/leaveform.php b/lib/leaveform.php
index e63d96ee80..5469b5704c 100644
--- a/lib/leaveform.php
+++ b/lib/leaveform.php
@@ -100,7 +100,7 @@ class LeaveForm extends Form
     function action()
     {
         return common_local_url('leavegroup',
-                                array('nickname' => $this->group->nickname));
+                                array('id' => $this->group->id));
     }
 
     /**
diff --git a/lib/router.php b/lib/router.php
index 987d0152e4..0e15d83b9a 100644
--- a/lib/router.php
+++ b/lib/router.php
@@ -247,6 +247,9 @@ class Router
                 $m->connect('group/:nickname/'.$v,
                             array('action' => $v.'group'),
                             array('nickname' => '[a-zA-Z0-9]+'));
+                $m->connect('group/:id/id/'.$v,
+                            array('action' => $v.'group'),
+                            array('id' => '[0-9]+'));
             }
 
             foreach (array('members', 'logo', 'rss', 'designsettings') as $n) {
diff --git a/plugins/OStatus/actions/ostatussub.php b/plugins/OStatus/actions/ostatussub.php
index 12832cdcfb..aae22f868a 100644
--- a/plugins/OStatus/actions/ostatussub.php
+++ b/plugins/OStatus/actions/ostatussub.php
@@ -333,10 +333,18 @@ class OStatusSubAction extends Action
             $group = $this->oprofile->localGroup();
             if ($user->isMember($group)) {
                 $this->showForm(_m('Already a member!'));
-            } elseif (Group_member::join($this->oprofile->group_id, $user->id)) {
-                $this->successGroup();
+                return;
+            }
+            if (Event::handle('StartJoinGroup', array($group, $user))) {
+                $ok = Group_member::join($this->oprofile->group_id, $user->id);
+                if ($ok) {
+                    Event::handle('EndJoinGroup', array($group, $user));
+                    $this->successGroup();
+                } else {
+                    $this->showForm(_m('Remote group join failed!'));
+                }
             } else {
-                $this->showForm(_m('Remote group join failed!'));
+                $this->showForm(_m('Remote group join aborted!'));
             }
         } else {
             $local = $this->oprofile->localProfile();
diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php
index d66939399a..f230170776 100644
--- a/plugins/OStatus/classes/Ostatus_profile.php
+++ b/plugins/OStatus/classes/Ostatus_profile.php
@@ -162,7 +162,7 @@ class Ostatus_profile extends Memcached_DataObject
                              'jpg' => 'image/jpeg',
                              'jpeg' => 'image/jpeg',
                              'gif' => 'image/gif');
-                $extension = pathinfo(parse_url($avatarHref, PHP_URL_PATH), PATHINFO_EXTENSION);
+                $extension = pathinfo(parse_url($object->avatar, PHP_URL_PATH), PATHINFO_EXTENSION);
                 if (isset($map[$extension])) {
                     // @fixme this ain't used/saved yet
                     $object->avatarType = $map[$extension];
@@ -332,6 +332,9 @@ class Ostatus_profile extends Memcached_DataObject
      */
     public function unsubscribe() {
         $feedsub = FeedSub::staticGet('uri', $this->feeduri);
+        if (!$feedsub) {
+            return true;
+        }
         if ($feedsub->sub_state == 'active') {
             return $feedsub->unsubscribe();
         } else if ($feedsub->sub_state == '' || $feedsub->sub_state == 'inactive' || $feedsub->sub_state == 'unsubscribe') {
@@ -356,7 +359,7 @@ class Ostatus_profile extends Memcached_DataObject
             $count = $this->localProfile()->subscriberCount();
         }
         if ($count == 0) {
-            common_log(LOG_INFO, "Unsubscribing from now-unused remote feed $oprofile->feeduri");
+            common_log(LOG_INFO, "Unsubscribing from now-unused remote feed $this->feeduri");
             $this->unsubscribe();
             return true;
         } else {
@@ -1095,8 +1098,8 @@ class Ostatus_profile extends Memcached_DataObject
 
         if ($object->type == ActivityObject::PERSON) {
             $profile = new Profile();
+            $profile->created = common_sql_now();
             self::updateProfile($profile, $object, $hints);
-            $profile->created  = common_sql_now();
 
             $oprofile->profile_id = $profile->insert();
             if (!$oprofile->profile_id) {
@@ -1104,6 +1107,7 @@ class Ostatus_profile extends Memcached_DataObject
             }
         } else {
             $group = new User_group();
+            $group->uri = $homeuri;
             $group->created = common_sql_now();
             self::updateGroup($group, $object, $hints);
 
@@ -1183,19 +1187,19 @@ class Ostatus_profile extends Memcached_DataObject
     {
         $orig = clone($group);
 
-        // @fixme need to make nick unique etc *hack hack*
         $group->nickname = self::getActivityObjectNickname($object, $hints);
         $group->fullname = $object->title;
 
-        // @fixme no canonical profileurl; using homepage instead for now
-        $group->homepage = $object->id;
+        if (!empty($object->link)) {
+            $group->mainpage = $object->link;
+        } else if (array_key_exists('profileurl', $hints)) {
+            $group->mainpage = $hints['profileurl'];
+        }
 
-        // @fixme homepage
-        // @fixme bio
-        // @fixme tags/categories
-        // @fixme location?
         // @todo tags from categories
-        // @todo lat/lon/location?
+        $group->description = self::getActivityObjectBio($object, $hints);
+        $group->location = self::getActivityObjectLocation($object, $hints);
+        $group->homepage = self::getActivityObjectHomepage($object, $hints);
 
         if ($group->id) {
             common_log(LOG_DEBUG, "Updating OStatus group $group->id from remote info $object->id: " . var_export($object, true) . var_export($hints, true));

From 8278eca7ffe5d8c3e05fead042754640b8169411 Mon Sep 17 00:00:00 2001
From: Brion Vibber <brion@pobox.com>
Date: Thu, 25 Feb 2010 21:15:20 +0000
Subject: [PATCH 2/2] Not sure how this ended up in wrong-cased dir...

---
 {DB => db}/local_group.sql | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename {DB => db}/local_group.sql (100%)

diff --git a/DB/local_group.sql b/db/local_group.sql
similarity index 100%
rename from DB/local_group.sql
rename to db/local_group.sql