From f3a82e787c70e8cf749c79f22fe37ce6c9c9d4d3 Mon Sep 17 00:00:00 2001
From: Zach Copley <zach@status.net>
Date: Fri, 12 Feb 2010 19:00:35 -0800
Subject: [PATCH] Add OStatus PuSH hub and Salmon links back into user and
 group feeds

---
 actions/apitimelinegroup.php      | 14 ++++++-
 actions/apitimelineuser.php       | 14 ++++++-
 lib/api.php                       |  1 -
 lib/atom10feed.php                | 21 ++++++----
 lib/atomgroupnoticefeed.php       | 67 +++++++++++++++++++++++++++++++
 lib/atomnoticefeed.php            |  4 +-
 lib/atomusernoticefeed.php        | 66 ++++++++++++++++++++++++++++++
 plugins/OStatus/OStatusPlugin.php | 37 +++++++++--------
 8 files changed, 193 insertions(+), 31 deletions(-)
 create mode 100644 lib/atomgroupnoticefeed.php
 create mode 100644 lib/atomusernoticefeed.php

diff --git a/actions/apitimelinegroup.php b/actions/apitimelinegroup.php
index 45962fa76f..3c74e36b56 100644
--- a/actions/apitimelinegroup.php
+++ b/actions/apitimelinegroup.php
@@ -138,7 +138,19 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction
 
             try {
 
-                $atom = new AtomNoticeFeed();
+                // If this was called using an integer ID, i.e.: using the canonical
+                // URL for this group's feed, then pass the Group object into the feed, 
+                // so the OStatus plugin, and possibly other plugins, can access it. 
+                // Feels sorta hacky. -- Z
+
+                $atom = null;
+                $id = $this->arg('id');
+
+                if (strval(intval($id)) === strval($id)) {
+                    $atom = new AtomGroupNoticeFeed($this->group);
+                } else {
+                    $atom = new AtomGroupNoticeFeed();
+                }
 
                 $atom->setId($id);
                 $atom->setTitle($title);
diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php
index d20bb0d202..24752e45fd 100644
--- a/actions/apitimelineuser.php
+++ b/actions/apitimelineuser.php
@@ -148,7 +148,19 @@ class ApiTimelineUserAction extends ApiBareAuthAction
 
             header('Content-Type: application/atom+xml; charset=utf-8');
 
-            $atom = new AtomNoticeFeed();
+            // If this was called using an integer ID, i.e.: using the canonical
+            // URL for this user's feed, then pass the User object into the feed,
+            // so the OStatus plugin, and possibly other plugins, can access it.
+            // Feels sorta hacky. -- Z
+
+            $atom = null;
+            $id = $this->arg('id');
+
+            if (strval(intval($id)) === strval($id)) {
+                $atom = new AtomUserNoticeFeed($this->user);
+            } else {
+                $atom = new AtomUserNoticeFeed();
+            }
 
             $atom->setId($id);
             $atom->setTitle($title);
diff --git a/lib/api.php b/lib/api.php
index 494b595d17..22eef7436d 100644
--- a/lib/api.php
+++ b/lib/api.php
@@ -1154,7 +1154,6 @@ class ApiAction extends Action
         $this->elementStart('feed', array('xmlns' => 'http://www.w3.org/2005/Atom',
                                           'xml:lang' => 'en-US',
                                           'xmlns:thr' => 'http://purl.org/syndication/thread/1.0'));
-        Event::handle('StartApiAtom', array($this));
     }
 
     function endTwitterAtom()
diff --git a/lib/atom10feed.php b/lib/atom10feed.php
index 806a9684b7..14a3beb83e 100644
--- a/lib/atom10feed.php
+++ b/lib/atom10feed.php
@@ -175,6 +175,8 @@ class Atom10Feed extends XMLStringer
 
         $this->element('updated', null, $this->updated);
 
+        $this->renderAuthors();
+
         $this->renderLinks();
     }
 
@@ -221,17 +223,20 @@ class Atom10Feed extends XMLStringer
 
     function getString()
     {
-        $this->validate();
+        if (Event::handle('StartApiAtom', array($this))) {
 
-        $this->initFeed();
-        $this->renderAuthors();
+            $this->validate();
+            $this->initFeed();
 
-        if (!empty($this->subject)) {
-            $this->raw($this->subject);
-        }
+            if (!empty($this->subject)) {
+                $this->raw($this->subject);
+            }
+
+            $this->renderEntries();
+            $this->endFeed();
 
-        $this->renderEntries();
-        $this->endFeed();
+            Event::handle('EndApiAtom', array($this));
+        }
 
         return $this->xw->outputMemory();
     }
diff --git a/lib/atomgroupnoticefeed.php b/lib/atomgroupnoticefeed.php
new file mode 100644
index 0000000000..52ee4c7d6e
--- /dev/null
+++ b/lib/atomgroupnoticefeed.php
@@ -0,0 +1,67 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Class for building an in-memory Atom feed for a particular group's
+ * timeline.
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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/>.
+ *
+ * @category  Feed
+ * @package   StatusNet
+ * @author    Zach Copley <zach@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET'))
+{
+    exit(1);
+}
+
+/**
+ * Class for group notice feeds.  May contains a reference to the group.
+ *
+ * @category Feed
+ * @package  StatusNet
+ * @author   Zach Copley <zach@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+class AtomGroupNoticeFeed extends AtomNoticeFeed
+{
+    private $group;
+
+    /**
+     * Constructor
+     *
+     * @param Group   $group   the group for the feed (optional)
+     * @param boolean $indent  flag to turn indenting on or off
+     *
+     * @return void
+     */
+    function __construct($group = null, $indent = true) {
+        parent::__construct($indent);
+        $this->group = $group;
+    }
+
+    function getGroup()
+    {
+        return $this->group;
+    }
+
+}
diff --git a/lib/atomnoticefeed.php b/lib/atomnoticefeed.php
index 34ed44b2ed..b7a60bde6e 100644
--- a/lib/atomnoticefeed.php
+++ b/lib/atomnoticefeed.php
@@ -2,7 +2,7 @@
 /**
  * StatusNet, the distributed open-source microblogging tool
  *
- * Class for building and Atom feed from a collection of notices
+ * Class for building an Atom feed from a collection of notices
  *
  * PHP version 5
  *
@@ -101,3 +101,5 @@ class AtomNoticeFeed extends Atom10Feed
     }
 
 }
+
+
diff --git a/lib/atomusernoticefeed.php b/lib/atomusernoticefeed.php
new file mode 100644
index 0000000000..9f224325c6
--- /dev/null
+++ b/lib/atomusernoticefeed.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Class for building an in-memory Atom feed for a particular user's
+ * timeline.
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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/>.
+ *
+ * @category  Feed
+ * @package   StatusNet
+ * @author    Zach Copley <zach@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET'))
+{
+    exit(1);
+}
+
+/**
+ * Class for user notice feeds.  May contain a reference to the user.
+ *
+ * @category Feed
+ * @package  StatusNet
+ * @author   Zach Copley <zach@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+class AtomUserNoticeFeed extends AtomNoticeFeed
+{
+    private $user;
+
+    /**
+     * Constructor
+     *
+     * @param User    $user    the user for the feed (optional)
+     * @param boolean $indent  flag to turn indenting on or off
+     *
+     * @return void
+     */
+    function __construct($user = null, $indent = true) {
+        parent::__construct($indent);
+        $this->user = $user;
+    }
+
+    function getUser()
+    {
+        return $this->user;
+    }
+}
diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php
index 8444c3d73d..bf7dde2967 100644
--- a/plugins/OStatus/OStatusPlugin.php
+++ b/plugins/OStatus/OStatusPlugin.php
@@ -63,9 +63,9 @@ class OStatusPlugin extends Plugin
         $m->connect('main/ostatus?nickname=:nickname',
                   array('action' => 'ostatusinit'), array('nickname' => '[A-Za-z0-9_-]+'));
         $m->connect('main/ostatussub',
-                    array('action' => 'ostatussub'));          
+                    array('action' => 'ostatussub'));
         $m->connect('main/ostatussub',
-                    array('action' => 'ostatussub'), array('feed' => '[A-Za-z0-9\.\/\:]+'));          
+                    array('action' => 'ostatussub'), array('feed' => '[A-Za-z0-9\.\/\:]+'));
 
         // PuSH actions
         $m->connect('main/push/hub', array('action' => 'pushhub'));
@@ -112,35 +112,34 @@ class OStatusPlugin extends Plugin
      * Set up a PuSH hub link to our internal link for canonical timeline
      * Atom feeds for users and groups.
      */
-    function onStartApiAtom(Action $action)
+    function onStartApiAtom(AtomNoticeFeed $feed)
     {
-        if ($action instanceof ApiTimelineUserAction) {
+        $id = null;
+
+        if ($feed instanceof AtomUserNoticeFeed) {
             $salmonAction = 'salmon';
-        } else if ($action instanceof ApiTimelineGroupAction) {
+            $id = $feed->getUser()->id;
+        } else if ($feed instanceof AtomGroupNoticeFeed) {
             $salmonAction = 'salmongroup';
+            $id = $feed->getGroup()->id;
         } else {
             return;
         }
 
-        $id = $action->arg('id');
-        if (strval(intval($id)) === strval($id)) {
-            // Canonical form of id in URL? These are used for OStatus syndication.
-
+       if (!empty($id)) {
             $hub = common_config('ostatus', 'hub');
             if (empty($hub)) {
                 // Updates will be handled through our internal PuSH hub.
                 $hub = common_local_url('pushhub');
             }
-            $action->element('link', array('rel' => 'hub',
-                                           'href' => $hub));
+            $feed->addLink($hub, array('rel' => 'hub'));
 
             // Also, we'll add in the salmon link
             $salmon = common_local_url($salmonAction, array('id' => $id));
-            $action->element('link', array('rel' => 'salmon',
-                                           'href' => $salmon));
+            $feed->addLink($salmon, array('rel' => 'salmon'));
         }
     }
-    
+
     /**
      * Add the feed settings page to the Connect Settings menu
      *
@@ -201,7 +200,7 @@ class OStatusPlugin extends Plugin
             $output->element('a', array('href' => $url,
                                         'class' => 'entity_remote_subscribe'),
                                 _m('OStatus'));
-            
+
             $output->elementEnd('li');
         }
     }
@@ -221,25 +220,25 @@ class OStatusPlugin extends Plugin
                 $w = new Webfinger;
 
                 $endpoint_uri = '';
-                
+
                 $result = $w->lookup($webfinger);
                 if (empty($result)) {
                     continue;
                 }
-                
+
                 foreach ($result->links as $link) {
                     if ($link['rel'] == 'salmon') {
                         $endpoint_uri = $link['href'];
                     }
                 }
-                
+
                 if (empty($endpoint_uri)) {
                     continue;
                 }
 
                 $xml = '<?xml version="1.0" encoding="UTF-8" ?>';
                 $xml .= $notice->asAtomEntry();
-               
+
                 $salmon = new Salmon();
                 $salmon->post($endpoint_uri, $xml);
             }
-- 
2.39.5