]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
New individual actions for dealing with groups via API
authorZach Copley <zach@status.net>
Thu, 8 Oct 2009 00:20:08 +0000 (17:20 -0700)
committerZach Copley <zach@status.net>
Thu, 8 Oct 2009 00:20:08 +0000 (17:20 -0700)
actions/apigroupismember.php [new file with mode: 0644]
actions/apigroupjoin.php [new file with mode: 0644]
actions/apigroupleave.php [new file with mode: 0644]
actions/apigrouplist.php [new file with mode: 0644]
actions/apigrouplistall.php [new file with mode: 0644]
actions/apigroupmembership.php [new file with mode: 0644]
actions/apigroupshow.php [new file with mode: 0644]
actions/twitapigroups.php [deleted file]
lib/router.php
lib/twitterapi.php

diff --git a/actions/apigroupismember.php b/actions/apigroupismember.php
new file mode 100644 (file)
index 0000000..facc581
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Check to see whether a user a member of a group
+ *
+ * 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  API
+ * @package   StatusNet
+ * @author    Zach Copley <zach@status.net>
+ * @copyright 2009 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);
+}
+
+require_once INSTALLDIR . '/lib/apibareauth.php';
+
+/**
+ * Returns whether a user is a member of a specified group.
+ *
+ * @category API
+ * @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 ApiGroupIsMemberAction extends ApiBareAuthAction
+{
+    var $format  = null;
+    var $user    = null;
+    var $group   = null;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     *
+     */
+
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        if ($this->requiresAuth()) {
+            if ($this->checkBasicAuthUser() == false) {
+                return;
+            }
+        }
+
+        $this->user   = $this->getTargetUser(null);
+        $this->group  = $this->getTargetGroup(null);
+        $this->format = $this->arg('format');
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Save the new message
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+
+    function handle($args)
+    {
+        parent::handle($args);
+
+        if (empty($this->user)) {
+            $this->clientError(_('No such user!'), 404, $this->format);
+            return;
+        }
+
+        if (empty($this->group)) {
+            $this->clientError('Group not found!', 404, $this->format);
+            return false;
+        }
+
+        $is_member = $this->user->isMember($this->group);
+
+        switch($this->format) {
+        case 'xml':
+            $this->init_document('xml');
+            $this->element('is_member', null, $is_member);
+            $this->end_document('xml');
+            break;
+        case 'json':
+            $this->init_document('json');
+            $this->show_json_objects(array('is_member' => $is_member));
+            $this->end_document('json');
+            break;
+        default:
+            $this->clientError(
+                _('API method not found!'),
+                400,
+                $this->format
+            );
+            break;
+        }
+    }
+
+}
diff --git a/actions/apigroupjoin.php b/actions/apigroupjoin.php
new file mode 100644 (file)
index 0000000..c00d594
--- /dev/null
@@ -0,0 +1,167 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Join a group via the API
+ *
+ * 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  API
+ * @package   StatusNet
+ * @author    Zach Copley <zach@status.net>
+ * @copyright 2009 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);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Joins the authenticated user to the group speicified by ID
+ *
+ * @category API
+ * @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 ApiGroupJoinAction extends ApiAuthAction
+{
+    var $format  = null;
+    var $user    = null;
+    var $group   = null;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     *
+     */
+
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        if ($this->requiresAuth()) {
+            if ($this->checkBasicAuthUser() == false) {
+                return;
+            }
+        }
+
+        $this->user  = $this->auth_user;
+        $this->group = $this->getTargetGroup($this->arg('id'));
+
+        $this->format = $this->arg('format');
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Save the new message
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+
+    function handle($args)
+    {
+        parent::handle($args);
+
+        if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+            $this->clientError(
+                _('This method requires a POST.'),
+                400,
+                $this->format
+            );
+            return;
+        }
+
+        if (empty($this->user)) {
+            $this->clientError(_('No such user!'), 404, $this->format);
+            return;
+        }
+
+        if (empty($this->group)) {
+            $this->clientError('Group not found!', 404, $this->format);
+            return false;
+        }
+
+        if ($this->user->isMember($this->group)) {
+            $this->clientError(
+                _('You are already a member of that group.'),
+                403,
+                $this->format
+            );
+            return;
+        }
+
+        if (Group_block::isBlocked($this->group, $this->user->getProfile())) {
+            $this->clientError(
+                _('You have been blocked from that group by the admin.'),
+                403,
+                $this->format
+            );
+            return;
+        }
+
+        $member = new Group_member();
+
+        $member->group_id   = $this->group->id;
+        $member->profile_id = $this->user->id;
+        $member->created    = common_sql_now();
+
+        $result = $member->insert();
+
+        if (!$result) {
+            common_log_db_error($member, 'INSERT', __FILE__);
+            $this->serverError(
+                sprintf(
+                    _('Could not join user %s to group %s.'),
+                    $this->user->nickname,
+                    $this->group->nickname
+                )
+            );
+            return;
+        }
+
+        switch($this->format) {
+        case 'xml':
+            $this->show_single_xml_group($this->group);
+            break;
+        case 'json':
+            $this->show_single_json_group($this->group);
+            break;
+        default:
+            $this->clientError(
+                _('API method not found!'),
+                404,
+                $this->format
+            );
+            break;
+        }
+    }
+
+}
diff --git a/actions/apigroupleave.php b/actions/apigroupleave.php
new file mode 100644 (file)
index 0000000..568b04b
--- /dev/null
@@ -0,0 +1,153 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Leave a group via the API
+ *
+ * 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  API
+ * @package   StatusNet
+ * @author    Zach Copley <zach@status.net>
+ * @copyright 2009 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);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Removes the authenticated user from the group specified by ID
+ *
+ * @category API
+ * @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 ApiGroupLeaveAction extends ApiAuthAction
+{
+    var $format  = null;
+    var $user    = null;
+    var $group   = null;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     *
+     */
+
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        if ($this->requiresAuth()) {
+            if ($this->checkBasicAuthUser() == false) {
+                return;
+            }
+        }
+
+        $this->user  = $this->auth_user;
+        $this->group = $this->getTargetGroup($this->arg('id'));
+
+        $this->format = $this->arg('format');
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Save the new message
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+
+    function handle($args)
+    {
+        parent::handle($args);
+
+        if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+            $this->clientError(
+                _('This method requires a POST.'),
+                400,
+                $this->format
+            );
+            return;
+        }
+
+        if (empty($this->user)) {
+            $this->clientError(_('No such user!'), 404, $this->format);
+            return;
+        }
+
+        if (empty($this->group)) {
+            $this->clientError('Group not found!', 404, $this->format);
+            return false;
+        }
+
+        $member = new Group_member();
+
+        $member->group_id   = $this->group->id;
+        $member->profile_id = $this->auth->id;
+
+        if (!$member->find(true)) {
+            $this->serverError(_('You are not a member of this group.'));
+            return;
+        }
+
+        $result = $member->delete();
+
+        if (!$result) {
+            common_log_db_error($member, 'INSERT', __FILE__);
+            $this->serverError(
+                sprintf(
+                    _('Could not remove user %s to group %s.'),
+                    $this->user->nickname, 
+                    $this->$group->nickname
+                )
+            );
+            return;
+        }
+       
+        switch($this->format) {
+        case 'xml':
+            $this->show_single_xml_group($this->group);
+            break;
+        case 'json':
+            $this->show_single_json_group($this->group);
+            break;
+        default:
+            $this->clientError(
+                _('API method not found!'),
+                404,
+                $this->format
+            );
+            break;
+        }
+    }
+
+}
diff --git a/actions/apigrouplist.php b/actions/apigrouplist.php
new file mode 100644 (file)
index 0000000..84b7fc1
--- /dev/null
@@ -0,0 +1,237 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Check to see whether a user a member of a group
+ *
+ * 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  API
+ * @package   StatusNet
+ * @author    Zach Copley <zach@status.net>
+ * @copyright 2009 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);
+}
+
+require_once INSTALLDIR . '/lib/apibareauth.php';
+
+/**
+ * Returns whether a user is a member of a specified group.
+ *
+ * @category API
+ * @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 ApiGroupListAction extends ApiBareAuthAction
+{
+    var $format   = null;
+    var $user     = null;
+    var $page     = null;
+    var $count    = null;
+    var $max_id   = null;
+    var $since_id = null;
+    var $since    = null;
+    var $groups   = null;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     *
+     */
+
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        if ($this->requiresAuth()) {
+            if ($this->checkBasicAuthUser() == false) {
+                return;
+            }
+        }
+
+        $this->page     = (int)$this->arg('page', 1);
+        $this->count    = (int)$this->arg('count', 20);
+        $this->max_id   = (int)$this->arg('max_id', 0);
+        $this->since_id = (int)$this->arg('since_id', 0);
+        $this->since    = $this->arg('since');
+        
+        $this->user   = $this->getTargetUser($id);
+        $this->format = $this->arg('format');
+        $this->groups = $this->getGroups();
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Show the user's groups
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+
+    function handle($args)
+    {
+        parent::handle($args);
+
+        if (empty($this->user)) {
+            $this->clientError(_('No such user!'), 404, $this->format);
+            return;
+        }
+
+        $sitename   = common_config('site', 'name');
+        $title      = sprintf(_("%s's groups"), $this->user->nickname);
+        $taguribase = common_config('integration', 'taguri');
+        $id         = "tag:$taguribase:Groups";
+        $link       = common_local_url(
+            'usergroups',
+            array('nickname' => $this->user->nickname)
+        );
+        $subtitle   = sprintf(
+            _("Groups %s is a member of on %s."),
+            $this->user->nickname,
+            $sitename
+        );
+
+        switch($this->format) {
+        case 'xml':
+            $this->show_xml_groups($this->groups);
+            break;
+        case 'rss':
+            $this->show_rss_groups($this->groups, $title, $link, $subtitle);
+            break;
+        case 'atom':
+            $selfuri = common_root_url() . 'api/statusnet/groups/list/' .
+                $this->user->id . '.atom';
+            $this->show_atom_groups(
+                $this->groups,
+                $title,
+                $id,
+                $link,
+                $subtitle,
+                $selfuri
+            );
+            break;
+        case 'json':
+            $this->show_json_groups($this->groups);
+            break;
+        default:
+            $this->clientError(
+                _('API method not found!'),
+                404,
+                $this->format
+            );
+            break;
+        }
+
+    }
+
+    /**
+     * Get groups
+     *
+     * @return array groups
+     */
+
+    function getGroups()
+    {
+        $groups = array();
+
+        $group = $this->user->getGroups(
+            ($this->page - 1) * $this->count,
+            $this->count,
+            $this->since_id,
+            $this->max_id,
+            $this->since
+        );
+
+        while ($group->fetch()) {
+            $groups[] = clone($group);
+        }
+
+        return $groups;
+    }
+
+    /**
+     * Is this action read only?
+     *
+     * @param array $args other arguments
+     *
+     * @return boolean true
+     */
+
+    function isReadOnly($args)
+    {
+        return true;
+    }
+
+    /**
+     * When was this feed last modified?
+     *
+     * @return string datestamp of the latest group the user has joined
+     */
+
+    function lastModified()
+    {
+        if (!empty($this->groups) && (count($this->groups) > 0)) {
+            return strtotime($this->groups[0]->created);
+        }
+
+        return null;
+    }
+
+    /**
+     * An entity tag for this list of groups
+     *
+     * Returns an Etag based on the action name, language, user ID and
+     * timestamps of the first and last group the user has joined
+     *
+     * @return string etag
+     */
+
+    function etag()
+    {
+        if (!empty($this->groups) && (count($this->groups) > 0)) {
+
+            $last = count($this->groups) - 1;
+
+            return '"' . implode(
+                ':',
+                array($this->arg('action'),
+                      common_language(),
+                      $this->user->id,
+                      strtotime($this->groups[0]->created),
+                      strtotime($this->groups[$last]->created))
+            )
+            . '"';
+        }
+
+        return null;
+    }
+
+}
diff --git a/actions/apigrouplistall.php b/actions/apigrouplistall.php
new file mode 100644 (file)
index 0000000..b1964d8
--- /dev/null
@@ -0,0 +1,215 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show the newest groups
+ *
+ * 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  API
+ * @package   StatusNet
+ * @author    Zach Copley <zach@status.net>
+ * @copyright 2009 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);
+}
+
+require_once INSTALLDIR . '/lib/twitterapi.php';
+
+/**
+ * Returns of the lastest 20 groups for the site
+ *
+ * @category API
+ * @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 ApiGroupListAllAction extends TwitterApiAction
+{
+    var $format   = null;
+    var $page     = null;
+    var $count    = null;
+    var $max_id   = null;
+    var $since_id = null;
+    var $since    = null;
+    var $groups   = null;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     *
+     */
+
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        $this->page     = (int)$this->arg('page', 1);
+        $this->count    = (int)$this->arg('count', 20);
+        $this->max_id   = (int)$this->arg('max_id', 0);
+        $this->since_id = (int)$this->arg('since_id', 0);
+        $this->since    = $this->arg('since');
+
+        $this->user   = $this->getTargetUser($id);
+        $this->format = $this->arg('format');
+        $this->groups = $this->getGroups();
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Show the user's groups
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+
+    function handle($args)
+    {
+        parent::handle($args);
+
+        $sitename   = common_config('site', 'name');
+        $title      = sprintf(_("%s groups"), $sitename);
+        $taguribase = common_config('integration', 'taguri');
+        $id         = "tag:$taguribase:Groups";
+        $link       = common_local_url('groups');
+        $subtitle   = sprintf(_("groups on %s"), $sitename);
+
+        switch($this->format) {
+        case 'xml':
+            $this->show_xml_groups($this->groups);
+            break;
+        case 'rss':
+            $this->show_rss_groups($this->groups, $title, $link, $subtitle);
+            break;
+        case 'atom':
+            $selfuri = common_root_url() .
+                'api/statusnet/groups/list_all.atom';
+            $this->show_atom_groups(
+                $this->groups,
+                $title,
+                $id,
+                $link,
+                $subtitle,
+                $selfuri
+            );
+            break;
+        case 'json':
+            $this->show_json_groups($this->groups);
+            break;
+        default:
+            $this->clientError(
+                _('API method not found!'),
+                404,
+                $this->format
+            );
+            break;
+        }
+
+    }
+
+    /**
+     * Get groups
+     *
+     * @return array groups
+     */
+
+    function getGroups()
+    {
+        $groups = array();
+
+        // XXX: Use the $page, $count, $max_id, $since_id, and $since parameters
+
+        $group = new User_group();
+        $group->orderBy('created DESC');
+        $group->find();
+
+        while ($group->fetch()) {
+            $groups[] = clone($group);
+        }
+
+        return $groups;
+    }
+
+    /**
+     * Is this action read only?
+     *
+     * @param array $args other arguments
+     *
+     * @return boolean true
+     */
+
+    function isReadOnly($args)
+    {
+        return true;
+    }
+
+    /**
+     * When was this feed last modified?
+     *
+     * @return string datestamp of the site's latest group
+     */
+
+    function lastModified()
+    {
+        if (!empty($this->groups) && (count($this->groups) > 0)) {
+            return strtotime($this->groups[0]->created);
+        }
+
+        return null;
+    }
+
+    /**
+     * An entity tag for this list of groups
+     *
+     * Returns an Etag based on the action name, language, and
+     * timestamps of the first and last group the user has joined
+     *
+     * @return string etag
+     */
+
+    function etag()
+    {
+        if (!empty($this->groups) && (count($this->groups) > 0)) {
+
+            $last = count($this->groups) - 1;
+
+            return '"' . implode(
+                ':',
+                array($this->arg('action'),
+                      common_language(),
+                      strtotime($this->groups[0]->created),
+                      strtotime($this->groups[$last]->created))
+            )
+            . '"';
+        }
+
+        return null;
+    }
+
+}
diff --git a/actions/apigroupmembership.php b/actions/apigroupmembership.php
new file mode 100644 (file)
index 0000000..0cd3ed2
--- /dev/null
@@ -0,0 +1,200 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * List a group's members
+ *
+ * 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  API
+ * @package   StatusNet
+ * @author    Zach Copley <zach@status.net>
+ * @copyright 2009 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);
+}
+
+require_once INSTALLDIR . '/lib/twitterapi.php';
+
+/**
+ * List 20 newest members of the group specified by name or ID. 
+ *
+ * @category API
+ * @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 ApiGroupMembershipAction extends TwitterApiAction
+{
+    var $format   = null;
+    var $page     = null;
+    var $count    = null;
+    var $max_id   = null;
+    var $since_id = null;
+    var $since    = null;
+    var $group    = null;
+    var $profiles = null;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     *
+     */
+
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        $this->page     = (int)$this->arg('page', 1);
+        $this->count    = (int)$this->arg('count', 20);
+        $this->max_id   = (int)$this->arg('max_id', 0);
+        $this->since_id = (int)$this->arg('since_id', 0);
+        $this->since    = $this->arg('since');
+
+        $this->format = $this->arg('format');
+        $this->group  = $this->getTargetGroup($this->arg('id'));
+
+        $this->profiles = $this->getProfiles();
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Show the members of the group
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+
+    function handle($args)
+    {
+        parent::handle($args);
+
+        // XXX: RSS and Atom
+
+        switch($this->format) {
+        case 'xml':
+            $this->show_twitter_xml_users($this->profiles);
+            break;
+        case 'json':
+            $this->show_json_users($this->profiles);
+            break;
+        default:
+            $this->clientError(
+                _('API method not found!'),
+                404,
+                $this->format
+            );
+            break;
+        }
+    }
+
+    /**
+     * Fetch the members of a group
+     *
+     * @return array $profiles list of profiles 
+     */
+
+    function getProfiles()
+    {
+        $profiles = array();
+
+        $profile = $this->group->getMembers(
+            ($this->page - 1) * $this->count,
+            $this->count, 
+            $this->since_id, 
+            $this->max_id, 
+            $this->since
+        );
+
+        while ($profile->fetch()) {
+            $profiles[] = clone($profile);
+        }
+
+        return $profiles;
+    }
+
+    /**
+     * Is this action read only?
+     *
+     * @param array $args other arguments
+     *
+     * @return boolean true
+     */
+
+    function isReadOnly($args)
+    {
+        return true;
+    }
+
+    /**
+     * When was this list of profiles last modified?
+     *
+     * @return string datestamp of the lastest profile in the group
+     */
+
+    function lastModified()
+    {
+        if (!empty($this->profiles) && (count($this->profiles) > 0)) {
+            return strtotime($this->profiles[0]->created);
+        }
+
+        return null;
+    }
+
+    /**
+     * An entity tag for this list of groups
+     *
+     * Returns an Etag based on the action name, language
+     * the group id, and timestamps of the first and last 
+     * user who has joined the group
+     *
+     * @return string etag
+     */
+
+    function etag()
+    {
+        if (!empty($this->profiles) && (count($this->profiles) > 0)) {
+
+            $last = count($this->profiles) - 1;
+
+            return '"' . implode(
+                ':',
+                array($this->arg('action'),
+                      common_language(),
+                      $this->group->id,
+                      strtotime($this->profiles[0]->created),
+                      strtotime($this->profiles[$last]->created))
+            )
+            . '"';
+        }
+
+        return null;
+    }
+
+}
diff --git a/actions/apigroupshow.php b/actions/apigroupshow.php
new file mode 100644 (file)
index 0000000..733c9cc
--- /dev/null
@@ -0,0 +1,148 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show information about a group
+ *
+ * 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  API
+ * @package   StatusNet
+ * @author    Zach Copley <zach@status.net>
+ * @copyright 2009 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);
+}
+
+require_once INSTALLDIR.'/lib/twitterapi.php';
+
+/**
+ * Outputs detailed information about the group specified by ID
+ *
+ * @category API
+ * @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 ApiGroupShowAction extends TwitterApiAction
+{
+    var $format = null;
+    var $group = null;
+
+    /**
+     * Take arguments for running
+     *
+     * @param array $args $_REQUEST args
+     *
+     * @return boolean success flag
+     *
+     */
+
+    function prepare($args)
+    {
+        parent::prepare($args);
+
+        $this->format = $this->arg('format');
+        $this->group = $this->getTargetGroup($this->arg('id'));
+
+        return true;
+    }
+
+    /**
+     * Handle the request
+     *
+     * Check the format and show the user info
+     *
+     * @param array $args $_REQUEST data (unused)
+     *
+     * @return void
+     */
+
+    function handle($args)
+    {
+        parent::handle($args);
+
+        if (empty($this->group)) {
+            $this->clientError(
+                'Group not found!',
+                404,
+                $this->format
+            );
+            return;
+        }
+
+        switch($this->format) {
+        case 'xml':
+            $this->show_single_xml_group($this->group);
+            break;
+        case 'json':
+            $this->show_single_json_group($this->group);
+            break;
+        default:
+            $this->clientError(_('API method not found!'), 404, $this->format);
+            break;
+        }
+
+    }
+
+    /**
+     * When was this group last modified?
+     *
+     * @return string datestamp of the latest notice in the stream
+     */
+
+    function lastModified()
+    {
+        if (!empty($this->group)) {
+            return strtotime($this->group->modified);
+        }
+
+        return null;
+    }
+
+    /**
+     * An entity tag for this group
+     *
+     * Returns an Etag based on the action name, language, and
+     * timestamps of the notice
+     *
+     * @return string etag
+     */
+
+    function etag()
+    {
+        if (!empty($this->group)) {
+
+            return '"' . implode(
+                ':',
+                array($this->arg('action'),
+                      common_language(),
+                      $this->group->id,
+                      strtotime($this->group->modified))
+            )
+            . '"';
+        }
+
+        return null;
+    }
+
+}
diff --git a/actions/twitapigroups.php b/actions/twitapigroups.php
deleted file mode 100644 (file)
index 493144e..0000000
+++ /dev/null
@@ -1,453 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * StatusNet extensions to the Twitter-like API for groups
- *
- * 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  Twitter
- * @package   StatusNet
- * @author    Craig Andrews <candrews@integralblue.com>
- * @author    Zach Copley <zach@status.net>
- * @copyright 2009 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') && !defined('LACONICA')) {
-    exit(1);
-}
-
-require_once INSTALLDIR.'/lib/twitterapi.php';
-
-/**
- * Group-specific API methods
- *
- * This class handles StatusNet group API methods.
- *
- * @category  Twitter
- * @package   StatusNet
- * @author    Craig Andrews <candrews@integralblue.com>
- * @author    Zach Copley <zach@status.net>
- * @copyright 2009 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/
- */
-
- class TwitapigroupsAction extends TwitterapiAction
- {
-
-     function list_groups($args, $apidata)
-     {
-         parent::handle($args);
-         
-         common_debug("in groups api action");
-         
-         $this->auth_user = $apidata['user'];
-         $user = $this->get_user($apidata['api_arg'], $apidata);
-
-         if (empty($user)) {
-             $this->clientError('Not Found', 404, $apidata['content-type']);
-             return;
-         }
-
-         $page     = (int)$this->arg('page', 1);
-         $count    = (int)$this->arg('count', 20);
-         $max_id   = (int)$this->arg('max_id', 0);
-         $since_id = (int)$this->arg('since_id', 0);
-         $since    = $this->arg('since');
-         $group = $user->getGroups(($page-1)*$count,
-             $count, $since_id, $max_id, $since);
-
-         $sitename   = common_config('site', 'name');
-         $title      = sprintf(_("%s's groups"), $user->nickname);
-         $taguribase = common_config('integration', 'taguri');
-         $id         = "tag:$taguribase:Groups";
-         $link       = common_root_url();
-         $subtitle   = sprintf(_("groups %s is a member of on %s"), $user->nickname, $sitename);
-
-         switch($apidata['content-type']) {
-         case 'xml':
-             $this->show_xml_groups($group);
-             break;
-         case 'rss':
-             $this->show_rss_groups($group, $title, $link, $subtitle);
-             break;
-         case 'atom':
-             $selfuri = common_root_url() . 'api/statusnet/groups/list/' . $user->id . '.atom';
-             $this->show_atom_groups($group, $title, $id, $link,
-                 $subtitle, $selfuri);
-             break;
-         case 'json':
-             $this->show_json_groups($group);
-             break;
-         default:
-             $this->clientError(_('API method not found!'), $code = 404);
-             break;
-         }
-     }
-
-     function list_all($args, $apidata)
-     {
-         parent::handle($args);
-         
-         common_debug("in groups api action");
-         
-         $page     = (int)$this->arg('page', 1);
-         $count    = (int)$this->arg('count', 20);
-         $max_id   = (int)$this->arg('max_id', 0);
-         $since_id = (int)$this->arg('since_id', 0);
-         $since    = $this->arg('since');
-
-         /*     TODO:
-         Use the $page, $count, $max_id, $since_id, and $since parameters
-         */
-         $group = new User_group();
-         $group->orderBy('created DESC');
-         $group->find();
-
-         $sitename   = common_config('site', 'name');
-         $title      = sprintf(_("%s groups"), $sitename);
-         $taguribase = common_config('integration', 'taguri');
-         $id         = "tag:$taguribase:Groups";
-         $link       = common_root_url();
-         $subtitle   = sprintf(_("groups on %s"), $sitename);
-
-         switch($apidata['content-type']) {
-         case 'xml':
-             $this->show_xml_groups($group);
-             break;
-         case 'rss':
-             $this->show_rss_groups($group, $title, $link, $subtitle);
-             break;
-         case 'atom':
-             $selfuri = common_root_url() . 'api/statusnet/groups/list_all.atom';
-             $this->show_atom_groups($group, $title, $id, $link,
-                 $subtitle, $selfuri);
-             break;
-         case 'json':
-             $this->show_json_groups($group);
-             break;
-         default:
-             $this->clientError(_('API method not found!'), $code = 404);
-             break;
-         }
-     }
-
-     function show($args, $apidata)
-     {
-         parent::handle($args);
-
-         common_debug("in groups api action");
-
-         $this->auth_user = $apidata['user'];
-         $group = $this->get_group($apidata['api_arg'], $apidata);
-
-         if (empty($group)) {
-             $this->clientError('Not Found', 404, $apidata['content-type']);
-             return;
-         }
-
-         switch($apidata['content-type']) {
-          case 'xml':
-             $this->show_single_xml_group($group);
-             break;
-          case 'json':
-             $this->show_single_json_group($group);
-             break;
-          default:
-             $this->clientError(_('API method not found!'), $code = 404);
-         }
-     }
-
-     function timeline($args, $apidata)
-     {
-         parent::handle($args);
-
-         common_debug("in groups api action");
-
-         $this->auth_user = $apidata['user'];
-         $group = $this->get_group($apidata['api_arg'], $apidata);
-
-         if (empty($group)) {
-             $this->clientError('Not Found', 404, $apidata['content-type']);
-             return;
-         }
-
-         $sitename   = common_config('site', 'name');
-         $title      = sprintf(_("%s timeline"), $group->nickname);
-         $taguribase = common_config('integration', 'taguri');
-         $id         = "tag:$taguribase:GroupTimeline:".$group->id;
-         $link       = common_local_url('showgroup',
-             array('nickname' => $group->nickname));
-         $subtitle   = sprintf(_('Updates from %1$s on %2$s!'),
-             $group->nickname, $sitename);
-
-         $page     = (int)$this->arg('page', 1);
-         $count    = (int)$this->arg('count', 20);
-         $max_id   = (int)$this->arg('max_id', 0);
-         $since_id = (int)$this->arg('since_id', 0);
-         $since    = $this->arg('since');
-
-         $notice = $group->getNotices(($page-1)*$count,
-             $count, $since_id, $max_id, $since);
-
-         switch($apidata['content-type']) {
-          case 'xml':
-             $this->show_xml_timeline($notice);
-             break;
-          case 'rss':
-             $this->show_rss_timeline($notice, $title, $link, $subtitle);
-             break;
-          case 'atom':
-             if (isset($apidata['api_arg'])) {
-                 $selfuri = common_root_url() .
-                     'api/statusnet/groups/timeline/' .
-                         $apidata['api_arg'] . '.atom';
-             } else {
-                 $selfuri = common_root_url() .
-                  'api/statusnet/groups/timeline.atom';
-             }
-             $this->show_atom_timeline($notice, $title, $id, $link,
-                 $subtitle, null, $selfuri);
-             break;
-          case 'json':
-             $this->show_json_timeline($notice);
-             break;
-          default:
-             $this->clientError(_('API method not found!'), $code = 404);
-         }
-     }
-
-     function membership($args, $apidata)
-     {
-         parent::handle($args);
-
-         common_debug("in groups api action");
-
-         $this->auth_user = $apidata['user'];
-         $group = $this->get_group($apidata['api_arg'], $apidata);
-         
-         if (empty($group)) {
-             $this->clientError('Not Found', 404, $apidata['content-type']);
-             return;
-         }
-
-         $sitename   = common_config('site', 'name');
-         $title      = sprintf(_("Members of %s group"), $group->nickname);
-         $taguribase = common_config('integration', 'taguri');
-         $id         = "tag:$taguribase:GroupMembership:".$group->id;
-         $link       = common_local_url('showgroup',
-             array('nickname' => $group->nickname));
-         $subtitle   = sprintf(_('Members of %1$s on %2$s'),
-             $group->nickname, $sitename);
-
-         $page     = (int)$this->arg('page', 1);
-         $count    = (int)$this->arg('count', 20);
-         $max_id   = (int)$this->arg('max_id', 0);
-         $since_id = (int)$this->arg('since_id', 0);
-         $since    = $this->arg('since');
-
-         $member = $group->getMembers(($page-1)*$count,
-             $count, $since_id, $max_id, $since);
-
-         switch($apidata['content-type']) {
-          case 'xml':
-             $this->show_twitter_xml_users($member);
-             break;
-          //TODO implement the RSS and ATOM content types
-          /*case 'rss':
-             $this->show_rss_users($member, $title, $link, $subtitle);
-             break;*/
-          /*case 'atom':
-             if (isset($apidata['api_arg'])) {
-                 $selfuri = common_root_url() .
-                     'api/statusnet/groups/membership/' .
-                         $apidata['api_arg'] . '.atom';
-             } else {
-                 $selfuri = common_root_url() .
-                  'api/statusnet/groups/membership.atom';
-             }
-             $this->show_atom_users($member, $title, $id, $link,
-                 $subtitle, null, $selfuri);
-             break;*/
-          case 'json':
-             $this->show_json_users($member);
-             break;
-          default:
-             $this->clientError(_('API method not found!'), $code = 404);
-         }
-     }
-
-     function join($args, $apidata)
-     {
-         parent::handle($args);
-
-         common_debug("in groups api action");
-
-         $this->auth_user = $apidata['user'];
-         $group = $this->get_group($apidata['api_arg'], $apidata);
-
-         if (empty($group)) {
-             $this->clientError('Not Found', 404, $apidata['content-type']);
-             return false;
-         }
-
-         if($this->auth_user->isMember($group)){
-            $this->clientError(_('You are already a member of that group'), $code = 403);
-            return false;
-         }
-
-         if (Group_block::isBlocked($group, $this->auth_user->getProfile())) {
-            $this->clientError(_('You have been blocked from that group by the admin.'), 403);
-            return false;
-         }
-
-         $member = new Group_member();
-
-         $member->group_id   = $group->id;
-         $member->profile_id = $this->auth_user->id;
-         $member->created    = common_sql_now();
-
-         $result = $member->insert();
-
-         if (!$result) {
-            common_log_db_error($member, 'INSERT', __FILE__);
-            $this->serverError(sprintf(_('Could not join user %s to group %s'),
-                                       $this->auth_user->nickname, $group->nickname));
-         }
-
-         switch($apidata['content-type']) {
-          case 'xml':
-             $this->show_single_xml_group($group);
-             break;
-          case 'json':
-             $this->show_single_json_group($group);
-             break;
-          default:
-             $this->clientError(_('API method not found!'), $code = 404);
-         }
-     }
-
-     function leave($args, $apidata)
-     {
-         parent::handle($args);
-
-         common_debug("in groups api action");
-
-         $this->auth_user = $apidata['user'];
-         $group = $this->get_group($apidata['api_arg'], $apidata);
-
-         if (empty($group)) {
-             $this->clientError('Not Found', 404, $apidata['content-type']);
-             return false;
-         }
-
-         if(! $this->auth_user->isMember($group)){
-            $this->clientError(_('You are not a member of that group'), $code = 403);
-            return false;
-         }
-
-         $member = new Group_member();
-
-         $member->group_id   = $group->id;
-         $member->profile_id = $this->auth_user->id;
-
-         if (!$member->find(true)) {
-            $this->serverError(_('Could not find membership record.'));
-            return;
-         }
-
-         $result = $member->delete();
-
-         if (!$result) {
-            common_log_db_error($member, 'INSERT', __FILE__);
-            $this->serverError(sprintf(_('Could not remove user %s to group %s'),
-                                       $this->auth_user->nickname, $group->nickname));
-         }
-
-         switch($apidata['content-type']) {
-          case 'xml':
-             $this->show_single_xml_group($group);
-             break;
-          case 'json':
-             $this->show_single_json_group($group);
-             break;
-          default:
-             $this->clientError(_('API method not found!'), $code = 404);
-         }
-     }
-
-     function is_member($args, $apidata)
-     {
-         parent::handle($args);
-
-         common_debug("in groups api action");
-
-         $this->auth_user = $apidata['user'];
-         $group = User_group::staticGet($args['group_id']);
-         if(! $group){
-            $this->clientError(_('Group not found'), $code = 500);
-         }
-         $user = User::staticGet('id', $args['user_id']);
-         if(! $user){
-            $this->clientError(_('User not found'), $code = 500);
-         }
-         
-         $is_member=$user->isMember($group);
-
-         switch($apidata['content-type']) {
-          case 'xml':
-             $this->init_document('xml');
-             $this->element('is_member', null, $is_member);
-             $this->end_document('xml');
-             break;
-          case 'json':
-             $this->init_document('json');
-             $this->show_json_objects(array('is_member'=>$is_member));
-             $this->end_document('json');
-             break;
-          default:
-             $this->clientError(_('API method not found!'), $code = 404);
-         }
-     }
-
-     function create($args, $apidata)
-     {
-        die("todo");
-     }
-
-     function update($args, $apidata)
-     {
-        die("todo");
-     }
-
-     function update_group_logo($args, $apidata)
-     {
-        die("todo");
-     }
-
-     function destroy($args, $apidata)
-     {
-        die("todo");
-     }
-
-     function tag($args, $apidata)
-     {
-        die("todo");
-     }
-}
index dbe2be0bb41ff01ffab8771a52a1c6180b2c6131..1ea5885dac7c87be02461bb9e7d19cb5d94ba674 100644 (file)
@@ -507,27 +507,58 @@ class Router
                           'id' => '[a-zA-Z0-9]+',
                           'format' => '(xmljson|rss|atom)'));
 
-        $m->connect('api/statusnet/groups/list/:argument',
-                    array('action' => 'api',
-                          'method' => 'list_groups',
-                          'apiaction' => 'groups'));
+        $m->connect('api/statusnet/groups/show.:format',
+                    array('action' => 'ApiGroupShow',
+                    'format' => '(xml|json)'));
 
-        foreach (array('xml', 'json', 'rss', 'atom') as $e) {
-            $m->connect('api/statusnet/groups/list.' . $e,
-                    array('action' => 'api',
-                          'method' => 'list_groups.' . $e,
-                          'apiaction' => 'groups'));
-        }
+        $m->connect('api/statusnet/groups/show/:id.:format',
+                    array('action' => 'ApiGroupShow',
+                          'id' => '[a-zA-Z0-9]+',
+                          'format' => '(xml|json)'));
 
-        $m->connect('api/statusnet/groups/:method',
-                    array('action' => 'api',
-                          'apiaction' => 'statuses'),
-                    array('method' => '(list_all|)(\.(atom|rss|xml|json))?'));
+        $m->connect('api/statusnet/groups/join.:format',
+                    array('action' => 'ApiGroupJoin',
+                          'id' => '[a-zA-Z0-9]+',
+                          'format' => '(xml|json)'));
 
-        $m->connect('api/statusnet/groups/:method',
-                    array('action' => 'api',
-                          'apiaction' => 'groups'));
+        $m->connect('api/statusnet/groups/join/:id.:format',
+                    array('action' => 'ApiGroupJoin',
+                    'format' => '(xml|json)'));
+
+        $m->connect('api/statusnet/groups/leave.:format',
+                    array('action' => 'ApiGroupLeave',
+                          'id' => '[a-zA-Z0-9]+',
+                          'format' => '(xml|json)'));
 
+        $m->connect('api/statusnet/groups/leave/:id.:format',
+                    array('action' => 'ApiGroupLeave',
+                          'format' => '(xml|json)'));
+
+        $m->connect('api/statusnet/groups/is_member.:format',
+                    array('action' => 'ApiGroupIsMember',
+                          'format' => '(xml|json)'));
+
+        $m->connect('api/statusnet/groups/list.:format',
+                    array('action' => 'ApiGroupList',
+                          'format' => '(xml|json|rss|atom)'));
+
+        $m->connect('api/statusnet/groups/list/:id.:format',
+                    array('action' => 'ApiGroupList',
+                          'id' => '[a-zA-Z0-9]+',
+                          'format' => '(xml|json|rss|atom)'));
+
+        $m->connect('api/statusnet/groups/list_all.:format',
+                    array('action' => 'ApiGroupListAll',
+                          'format' => '(xml|json|rss|atom)'));
+
+        $m->connect('api/statusnet/groups/membership.:format',
+                    array('action' => 'ApiGroupMembership',
+                         'format' => '(xml|json)'));
+
+        $m->connect('api/statusnet/groups/membership/:id.:format',
+                     array('action' => 'ApiGroupMembership',
+                           'id' => '[a-zA-Z0-9]+',
+                           'format' => '(xml|json)'));
         // Tags
         $m->connect('api/statusnet/tags/timeline/:tag.:format',
                     array('action' => 'ApiTimelineTag',
index 5cd88628bb86d90b059e17fc1ad5ca4b6cfa7c3e..e5904cc85884670506fc3b677a71f1c4ce57d2f8 100644 (file)
@@ -829,9 +829,9 @@ class TwitterapiAction extends Action
         $this->elementStart('users', array('type' => 'array'));
 
         if (is_array($user)) {
-            foreach ($group as $g) {
-                $twitter_user = $this->twitter_user_array($g);
-                $this->show_twitter_xml_user($twitter_user,'user');
+            foreach ($user as $u) {
+                $twitter_user = $this->twitter_user_array($u);
+                $this->show_twitter_xml_user($twitter_user);
             }
         } else {
             while ($user->fetch()) {
@@ -1145,7 +1145,6 @@ class TwitterapiAction extends Action
     function getTargetGroup($id)
     {
         if (empty($id)) {
-
             if (is_numeric($this->arg('id'))) {
                 return User_group::staticGet($this->arg('id'));
             } else if ($this->arg('id')) {