--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show, update or delete a list.
+ *
+ * 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 Shashi Gowda <connect2shashi@gmail.com>
+ * @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';
+
+class ApiListAction extends ApiBareAuthAction
+{
+ /**
+ * The list in question in the current request
+ */
+
+ var $list = null;
+
+ /**
+ * Is this an update request?
+ */
+
+ var $update = false;
+
+ /**
+ * Is this a delete request?
+ */
+
+ var $delete = false;
+
+ /**
+ * Set the flags for handling the request. Show list if this is a GET
+ * request, update it if it is POST, delete list if method is DELETE
+ * or if method is POST and an argument _method is set to DELETE. Act
+ * like we don't know if the current user has no access to the list.
+ *
+ * Takes parameters:
+ * - user: the user id or nickname
+ * - id: the id of the tag or the tag itself
+ *
+ * @return boolean success flag
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->delete = ($_SERVER['REQUEST_METHOD'] == 'DELETE' ||
+ ($this->trimmed('_method') == 'DELETE' &&
+ $_SERVER['REQUEST_METHOD'] == 'POST'));
+
+ // update list if method is POST or PUT and $this->delete is not true
+ $this->update = (!$this->delete &&
+ in_array($_SERVER['REQUEST_METHOD'], array('POST', 'PUT')));
+
+ $this->user = $this->getTargetUser($this->arg('user'));
+ $this->list = $this->getTargetList($this->arg('user'), $this->arg('id'));
+
+ if (empty($this->list)) {
+ $this->clientError(_('Not found'), 404, $this->format);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * @return boolean success flag
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if($this->delete) {
+ $this->handleDelete();
+ return true;
+ }
+
+ if($this->update) {
+ $this->handlePut();
+ return true;
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->showSingleXmlList($this->list);
+ break;
+ case 'json':
+ $this->showSingleJsonList($this->list);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+
+ /**
+ * require authentication if it is a write action or user is ambiguous
+ *
+ */
+
+ function requiresAuth()
+ {
+ return parent::requiresAuth() ||
+ $this->create || $this->delete;
+ }
+
+ /**
+ * Update a list
+ *
+ * @return boolean success
+ */
+
+ function handlePut()
+ {
+ if($this->auth_user->id != $this->list->tagger) {
+ $this->clientError(
+ _('You can not update lists that don\'t belong to you.'),
+ 401,
+ $this->format
+ );
+ }
+
+ $new_list = clone($this->list);
+ $new_list->tag = common_canonical_tag($this->arg('name'));
+ $new_list->description = common_canonical_tag($this->arg('description'));
+ $new_list->private = ($this->arg('mode') === 'private') ? true : false;
+
+ $result = $new_list->update($this->list);
+
+ if(!$result) {
+ $this->clientError(
+ _('An error occured.'),
+ 503,
+ $this->format
+ );
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->showSingleXmlList($new_list);
+ break;
+ case 'json':
+ $this->showSingleJsonList($new_list);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+
+ /**
+ * Delete a list
+ *
+ * @return boolean success
+ */
+
+ function handleDelete()
+ {
+ if($this->auth_user->id != $this->list->tagger) {
+ $this->clientError(
+ _('You can not delete lists that don\'t belong to you.'),
+ 401,
+ $this->format
+ );
+ }
+
+ $record = clone($this->list);
+ $this->list->delete();
+
+ switch($this->format) {
+ case 'xml':
+ $this->showSingleXmlList($record);
+ break;
+ case 'json':
+ $this->showSingleJsonList($record);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+
+ /**
+ * Indicate that this resource is not read-only.
+ *
+ * @return boolean is_read-only=false
+ */
+
+ function isReadOnly($args)
+ {
+ return false;
+ }
+
+ /**
+ * When was the list (people tag) last updated?
+ *
+ * @return String time_last_modified
+ */
+
+ function lastModified()
+ {
+ if(!empty($this->list)) {
+ return strtotime($this->list->modified);
+ }
+ return null;
+ }
+
+ /**
+ * An entity tag for this list
+ *
+ * Returns an Etag based on the action name, language, user ID and
+ * timestamps of the first and last list the user has joined
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->list)) {
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->user->id,
+ strtotime($this->list->created),
+ strtotime($this->list->modified))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * API method to check if a user belongs to a list.
+ *
+ * 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 Shashi Gowda <connect2shashi@gmail.com>
+ * @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';
+
+/**
+ * Action handler for Twitter list_memeber methods
+ *
+ * @category API
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ * @see ApiBareAuthAction
+ */
+
+class ApiListMemberAction extends ApiBareAuthAction
+{
+ /**
+ * Set the flags for handling the request. Show the profile if this
+ * is a GET request AND the profile is a member of the list, add a member
+ * if it is a POST, remove the profile from the list if method is DELETE
+ * or if method is POST and an argument _method is set to DELETE. Act
+ * like we don't know if the current user has no access to the list.
+ *
+ * Takes parameters:
+ * - user: the user id or nickname
+ * - list_id: the id of the tag or the tag itself
+ * - id: the id of the member being looked for/added/removed
+ *
+ * @return boolean success flag
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->getTargetUser($this->arg('id'));
+ $this->list = $this->getTargetList($this->arg('user'), $this->arg('list_id'));
+
+ if (empty($this->list)) {
+ $this->clientError(_('Not found'), 404, $this->format);
+ return false;
+ }
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user'), 404, $this->format);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * @return boolean success flag
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ $arr = array('tagger' => $this->list->tagger,
+ 'tag' => $this->list->tag,
+ 'tagged' => $this->user->id);
+ $ptag = Profile_tag::pkeyGet($arr);
+
+ if(empty($ptag)) {
+ $this->clientError(
+ _('The specified user is not a member of this list'),
+ 400,
+ $this->format
+ );
+ }
+
+ $user = $this->twitterUserArray($this->user->getProfile(), true);
+
+ switch($this->format) {
+ case 'xml':
+ $this->showTwitterXmlUser($user, 'user', true);
+ break;
+ case 'json':
+ $this->showSingleJsonUser($user);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ return true;
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * List/add/remove list 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 Shashi Gowda <connect2shashi@gmail.com>
+ * @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/apilistusers.php';
+
+class ApiListMembersAction extends ApiListUsersAction
+{
+ /**
+ * Add a user to a list (tag someone)
+ *
+ * @return boolean success
+ */
+
+ function handlePost()
+ {
+ if($this->auth_user->id != $this->list->tagger) {
+ $this->clientError(
+ _('You aren\'t allowed to add members to this list'),
+ 401,
+ $this->format
+ );
+ return false;
+ }
+
+ if($this->user === false) {
+ $this->clientError(
+ _('You must specify a member'),
+ 400,
+ $this->format
+ );
+ return false;
+ }
+
+ $result = Profile_tag::setTag($this->auth_user->id,
+ $this->user->id, $this->list->tag);
+
+ if(empty($result)) {
+ $this->clientError(
+ _('An error occured.'),
+ 500,
+ $this->format
+ );
+ return false;
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->showSingleXmlList($this->list);
+ break;
+ case 'json':
+ $this->showSingleJsonList($this->list);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ return false;
+ break;
+ }
+ }
+
+ /**
+ * Remove a user from a list (untag someone)
+ *
+ * @return boolean success
+ */
+
+ function handleDelete()
+ {
+ if($this->auth_user->id != $this->list->tagger) {
+ $this->clientError(
+ _('You aren\'t allowed to remove members from this list'),
+ 401,
+ $this->format
+ );
+ return false;
+ }
+
+ if($this->user === false) {
+ $this->clientError(
+ _('You must specify a member'),
+ 400,
+ $this->format
+ );
+ return false;
+ }
+
+ $args = array('tagger' => $this->auth_user->id,
+ 'tagged' => $this->user->id,
+ 'tag' => $this->list->tag);
+ $ptag = Profile_tag::pkeyGet($args);
+
+ if(empty($ptag)) {
+ $this->clientError(
+ _('The user you are trying to remove from the list is not a member'),
+ 400,
+ $this->format
+ );
+ return false;
+ }
+
+ $result = $ptag->delete();
+
+ if(empty($result)) {
+ $this->clientError(
+ _('An error occured.'),
+ 500,
+ $this->format
+ );
+ return false;
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->showSingleXmlList($this->list);
+ break;
+ case 'json':
+ $this->showSingleJsonList($this->list);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ return false;
+ break;
+ }
+ return true;
+ }
+
+ /**
+ * List the members of a list (people tagged)
+ */
+
+ function getUsers()
+ {
+ $fn = array($this->list, 'getTagged');
+ list($this->users, $this->next_cursor, $this->prev_cursor) =
+ Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Get a list of lists a user belongs to. (people tags for a user)
+ *
+ * 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 Shashi Gowda <connect2shashi@gmail.com>
+ * @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';
+
+/**
+ * Action handler for API method to list lists a user belongs to.
+ * (people tags for a user)
+ *
+ * @category API
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ * @see ApiBareAuthAction
+ */
+
+class ApiListMembershipsAction extends ApiBareAuthAction
+{
+ var $lists = array();
+ var $cursor = -1;
+ var $next_cursor = 0;
+ var $prev_cursor = 0;
+
+ /**
+ * Prepare for running the action
+ * Take arguments for running:s
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->cursor = (int) $this->arg('cursor', -1);
+ $this->user = $this->getTargetUser($this->arg('user'));
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user.'), 404, $this->format);
+ return;
+ }
+
+ $this->getLists();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Show the lists
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlLists($this->lists, $this->next_cursor, $this->prev_cursor);
+ break;
+ case 'json':
+ $this->showJsonLists($this->lists, $this->next_cursor, $this->prev_cursor);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 400,
+ $this->format
+ );
+ break;
+ }
+ }
+
+ /**
+ * Return true if read only.
+ *
+ * MAY override
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean is read only action?
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function getLists()
+ {
+ $profile = $this->user->getProfile();
+ $fn = array($profile, 'getOtherTags');
+
+ # 20 lists
+ list($this->lists, $this->next_cursor, $this->prev_cursor) =
+ Profile_list::getAtCursor($fn, array($this->auth_user), $this->cursor, 20);
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * List existing lists or create a new list.
+ *
+ * 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 Shashi Gowda <connect2shashi@gmail.com>
+ * @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';
+
+/**
+ * Action handler for Twitter list_memeber methods
+ *
+ * @category API
+ * @package StatusNet
+ * @author Shashi Gowda <connect2shashi@gmail.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ * @see ApiBareAuthAction
+ */
+
+class ApiListsAction extends ApiBareAuthAction
+{
+ var $lists = null;
+ var $cursor = 0;
+ var $next_cursor = 0;
+ var $prev_cursor = 0;
+ var $create = false;
+
+ /**
+ * Set the flags for handling the request. List lists created by user if this
+ * is a GET request, create a new list if it is a POST request.
+ *
+ * Takes parameters:
+ * - user: the user id or nickname
+ * Parameters for POST request
+ * - name: name of the new list (the people tag itself)
+ * - mode: (optional) mode for the new list private/public
+ * - description: (optional) description for the list
+ *
+ * @return boolean success flag
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->create = ($_SERVER['REQUEST_METHOD'] == 'POST');
+
+ if (!$this->create) {
+
+ $this->user = $this->getTargetUser($this->arg('user'));
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user.'), 404, $this->format);
+ return false;
+ }
+ $this->getLists();
+ }
+
+ return true;
+ }
+
+ /**
+ * require authentication if it is a write action or user is ambiguous
+ *
+ */
+
+ function requiresAuth()
+ {
+ return parent::requiresAuth() ||
+ $this->create || $this->delete;
+ }
+
+ /**
+ * Handle request:
+ * Show the lists the user has created if the request method is GET
+ * Create a new list by diferring to handlePost() if it is POST.
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if($this->create) {
+ return $this->handlePost();
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlLists($this->lists, $this->next_cursor, $this->prev_cursor);
+ break;
+ case 'json':
+ $this->showJsonLists($this->lists, $this->next_cursor, $this->prev_cursor);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+
+ /**
+ * Create a new list
+ *
+ * @return boolean success
+ */
+
+ function handlePost()
+ {
+ $name=$this->arg('name');
+ if(empty($name)) {
+ // mimick twitter
+ print _("A list's name can't be blank.");
+ exit(1);
+ }
+
+ // twitter creates a new list by appending a number to the end
+ // if the list by the given name already exists
+ // it makes more sense to return the existing list instead
+
+ $private = null;
+ if ($this->arg('mode') === 'public') {
+ $private = false;
+ } else if ($this->arg('mode') === 'private') {
+ $private = true;
+ }
+
+ $list = Profile_list::ensureTag($this->auth_user->id,
+ $this->arg('name'),
+ $this->arg('description'),
+ $private);
+ if (empty($list)) {
+ return false;
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->showSingleXmlList($list);
+ break;
+ case 'json':
+ $this->showSingleJsonList($list);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ return true;
+ }
+
+ /**
+ * Get lists
+ */
+
+ function getLists()
+ {
+ $cursor = (int) $this->arg('cursor', -1);
+
+ // twitter fixes count at 20
+ // there is no argument named count
+ $count = 20;
+ $profile = $this->user->getProfile();
+ $fn = array($profile, 'getOwnedTags');
+
+ list($this->lists,
+ $this->next_cursor,
+ $this->prev_cursor) = Profile_list::getAtCursor($fn, array($this->auth_user), $cursor, $count);
+ }
+
+ function isReadOnly($args)
+ {
+ return false;
+ }
+
+ function lastModified()
+ {
+ if (!$this->create && !empty($this->lists) && (count($this->lists) > 0)) {
+ return strtotime($this->lists[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this list of lists
+ *
+ * Returns an Etag based on the action name, language, user ID and
+ * timestamps of the first and last list the user has joined
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!$this->create && !empty($this->lists) && (count($this->lists) > 0)) {
+
+ $last = count($this->lists) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->user->id,
+ strtotime($this->lists[0]->created),
+ strtotime($this->lists[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Check if a user is subscribed to a list
+ *
+ * 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
+ * @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';
+
+class ApiListSubscriberAction extends ApiBareAuthAction
+{
+ var $list = null;
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->getTargetUser($this->arg('id'));
+ $this->list = $this->getTargetList($this->arg('user'), $this->arg('list_id'));
+
+ if (empty($this->list)) {
+ $this->clientError(_('Not found'), 404, $this->format);
+ return false;
+ }
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user'), 404, $this->format);
+ return false;
+ }
+ return true;
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ $arr = array('profile_tag_id' => $this->list->id,
+ 'profile_id' => $this->user->id);
+ $sub = Profile_tag_subscription::pkeyGet($arr);
+
+ if(empty($sub)) {
+ $this->clientError(
+ _('The specified user is not a subscriber of this list'),
+ 400,
+ $this->format
+ );
+ }
+
+ $user = $this->twitterUserArray($this->user->getProfile(), true);
+
+ switch($this->format) {
+ case 'xml':
+ $this->showTwitterXmlUser($user, 'user', true);
+ break;
+ case 'json':
+ $this->showSingleJsonUser($user);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show/add/remove list subscribers.
+ *
+ * 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
+ * @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/apilistusers.php';
+
+class ApiListSubscribersAction extends ApiListUsersAction
+{
+ /**
+ * Subscribe to list
+ *
+ * @return boolean success
+ */
+
+ function handlePost()
+ {
+ $result = Profile_tag_subscription::add($this->list,
+ $this->auth_user);
+
+ if(empty($result)) {
+ $this->clientError(
+ _('An error occured.'),
+ 500,
+ $this->format
+ );
+ return false;
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->showSingleXmlList($this->list);
+ break;
+ case 'json':
+ $this->showSingleJsonList($this->list);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ return false;
+ break;
+ }
+ }
+
+ function handleDelete()
+ {
+ $args = array('profile_tag_id' => $this->list->id,
+ 'profile_id' => $this->auth_user->id);
+ $ptag = Profile_tag_subscription::pkeyGet($args);
+
+ if(empty($ptag)) {
+ $this->clientError(
+ _('You are not subscribed to this list'),
+ 400,
+ $this->format
+ );
+ return false;
+ }
+
+ Profile_tag_subscription::remove($this->list, $this->auth_user);
+
+ if(empty($result)) {
+ $this->clientError(
+ _('An error occured.'),
+ 500,
+ $this->format
+ );
+ return false;
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->showSingleXmlList($this->list);
+ break;
+ case 'json':
+ $this->showSingleJsonList($this->list);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ return false;
+ break;
+ }
+ return true;
+ }
+
+ function getUsers()
+ {
+ $fn = array($this->list, 'getSubscribers');
+ list($this->users, $this->next_cursor, $this->prev_cursor) =
+ Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Get a list of lists a user is subscribed to.
+ *
+ * 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
+ * @copyright 2009 StatusNet, Inc.
+ * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
+ * @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';
+
+class ApiListSubscriptionsAction extends ApiBareAuthAction
+{
+ var $lists = array();
+ var $cursor = -1;
+ var $next_cursor = 0;
+ var $prev_cursor = 0;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->cursor = (int) $this->arg('cursor', -1);
+ $this->user = $this->getTargetUser($this->arg('user'));
+ $this->getLists();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Show the lists
+ *
+ * @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;
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlLists($this->lists, $this->next_cursor, $this->prev_cursor);
+ break;
+ case 'json':
+ $this->showJsonLists($this->lists, $this->next_cursor, $this->prev_cursor);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 400,
+ $this->format
+ );
+ break;
+ }
+ }
+
+ /**
+ * Return true if read only.
+ *
+ * MAY override
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean is read only action?
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function getLists()
+ {
+ if(empty($this->user)) {
+ return;
+ }
+
+ $profile = $this->user->getProfile();
+ $fn = array($profile, 'getTagSubscriptions');
+ # 20 lists
+ list($this->lists, $this->next_cursor, $this->prev_cursor) =
+ Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a list's notices
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
+ * @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/apiprivateauth.php';
+require_once INSTALLDIR . '/lib/atomlistnoticefeed.php';
+
+/**
+ * Returns the most recent notices (default 20) posted to the list specified by ID
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @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 ApiTimelineListAction extends ApiPrivateAuthAction
+{
+
+ var $list = null;
+ var $notices = array();
+ var $next_cursor = 0;
+ var $prev_cursor = 0;
+ var $cursor = -1;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->cursor = (int) $this->arg('cursor', -1);
+ $this->list = $this->getTargetList($this->arg('user'), $this->arg('id'));
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Just show the notices
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (empty($this->list)) {
+ $this->clientError(_('List not found.'), 404, $this->format);
+ return false;
+ }
+
+ $this->getNotices();
+ $this->showTimeline();
+ }
+
+ /**
+ * Show the timeline of notices
+ *
+ * @return void
+ */
+
+ function showTimeline()
+ {
+ // We'll pull common formatting out of this for other formats
+ $atom = new AtomListNoticeFeed($this->list, $this->auth_user);
+
+ $self = $this->getSelfUri();
+
+ switch($this->format) {
+ case 'xml':
+ $this->initDocument('xml');
+ $this->elementStart('statuses_list',
+ array('xmlns:statusnet' => 'http://status.net/schema/api/1/'));
+ $this->elementStart('statuses', array('type' => 'array'));
+
+ foreach ($this->notices as $n) {
+ $twitter_status = $this->twitterStatusArray($n);
+ $this->showTwitterXmlStatus($twitter_status);
+ }
+
+ $this->elementEnd('statuses');
+ $this->element('next_cursor', null, $this->next_cursor);
+ $this->element('previous_cursor', null, $this->prev_cursor);
+ $this->elementEnd('statuses_list');
+ $this->endDocument('xml');
+ break;
+ case 'rss':
+ $this->showRssTimeline(
+ $this->notices,
+ $atom->title,
+ $this->list->getUri(),
+ $atom->subtitle,
+ null,
+ $atom->logo,
+ $self
+ );
+ break;
+ case 'atom':
+
+ header('Content-Type: application/atom+xml; charset=utf-8');
+
+ try {
+ $atom->setId($self);
+ $atom->setSelfLink($self);
+ $atom->addEntryFromNotices($this->notices);
+ $this->raw($atom->getString());
+ } catch (Atom10FeedException $e) {
+ $this->serverError(
+ 'Could not generate feed for list - ' . $e->getMessage()
+ );
+ return;
+ }
+
+ break;
+ case 'json':
+ $this->initDocument('json');
+
+ $statuses = array();
+ foreach ($this->notices as $n) {
+ $twitter_status = $this->twitterStatusArray($n);
+ array_push($statuses, $twitter_status);
+ }
+
+ $statuses_list = array('statuses' => $statuses,
+ 'next_cursor' => $this->next_cusror,
+ 'next_cursor_str' => strval($this->next_cusror),
+ 'previous_cursor' => $this->prev_cusror,
+ 'previous_cursor_str' => strval($this->prev_cusror)
+ );
+ $this->showJsonObjects($statuses_list);
+
+ $this->initDocument('json');
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+
+ /**
+ * Get notices
+ *
+ * @return array notices
+ */
+
+ function getNotices()
+ {
+ $fn = array($this->list, 'getNotices');
+ list($this->notices, $this->next_cursor, $this->prev_cursor) =
+ Profile_list::getAtCursor($fn, array(), $this->cursor, 20);
+ if (!$this->notices) {
+ $this->notices = array();
+ }
+ }
+
+ /**
+ * 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 notice in the stream
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+ return strtotime($this->notices[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this stream
+ *
+ * Returns an Etag based on the action name, language, list ID and
+ * timestamps of the first and last notice in the timeline
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+
+ $last = count($this->notices) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->list->id,
+ strtotime($this->notices[0]->created),
+ strtotime($this->notices[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
const BOOKMARK = 'http://activitystrea.ms/schema/1.0/bookmark';
const PERSON = 'http://activitystrea.ms/schema/1.0/person';
const GROUP = 'http://activitystrea.ms/schema/1.0/group';
+ const _LIST = 'http://activitystrea.ms/schema/1.0/list'; // LIST is reserved
const PLACE = 'http://activitystrea.ms/schema/1.0/place';
const COMMENT = 'http://activitystrea.ms/schema/1.0/comment';
// ^^^^^^^^^^ tea!
public $title;
public $summary;
public $content;
+ public $owner;
public $link;
public $source;
public $avatarLinks = array();
Activity::MEDIA
);
}
+ if ($this->type == self::_LIST) {
+ $owner = ActivityUtils::child($this->element, Activity::AUTHOR, Activity::SPEC);
+ $this->owner = new ActivityObject($owner);
+ }
}
private function _fromAuthor($element)
AVATAR_MINI_SIZE);
$object->poco = PoCo::fromGroup($group);
-
- Event::handle('EndActivityObjectFromGroup', array($group, &$object));
+ Event::handle('EndActivityObjectFromGroup', array($group, &$object));
}
return $object;
}
+ static function fromPeopletag($ptag)
+ {
+ $object = new ActivityObject();
+ if (Event::handle('StartActivityObjectFromPeopletag', array($ptag, &$object))) {
+ $object->type = ActivityObject::_LIST;
+
+ $object->id = $ptag->getUri();
+ $object->title = $ptag->tag;
+ $object->summary = $ptag->description;
+ $object->link = $ptag->homeUrl();
+ $object->owner = Profile::staticGet('id', $ptag->tagger);
+ $object->poco = PoCo::fromProfile($object->owner);
+ Event::handle('EndActivityObjectFromPeopletag', array($ptag, &$object));
+ }
+ return $object;
+ }
+
function outputTo($xo, $tag='activity:object')
{
if (!empty($tag)) {
}
}
+ if(!empty($this->owner)) {
+ $owner = $this->owner->asActivityNoun(self::AUTHOR);
+ $xo->raw($owner);
+ }
+
if (!empty($this->geopoint)) {
$xo->element(
'georss:point',
const UNFAVORITE = 'http://ostatus.org/schema/1.0/unfavorite';
const UNFOLLOW = 'http://ostatus.org/schema/1.0/unfollow';
const LEAVE = 'http://ostatus.org/schema/1.0/leave';
+ const UNTAG = 'http://ostatus.org/schema/1.0/untag';
// For simple profile-update pings; no content to share.
const UPDATE_PROFILE = 'http://ostatus.org/schema/1.0/update-profile';
return $entry;
}
+ function twitterListArray($list)
+ {
+ $profile = Profile::staticGet('id', $list->tagger);
+
+ $twitter_list = array();
+ $twitter_list['id'] = $list->id;
+ $twitter_list['name'] = $list->tag;
+ $twitter_list['full_name'] = '@'.$profile->nickname.'/'.$list->tag;;
+ $twitter_list['slug'] = $list->tag;
+ $twitter_list['description'] = $list->description;
+ $twitter_list['subscriber_count'] = $list->subscriberCount();
+ $twitter_list['member_count'] = $list->taggedCount();
+ $twitter_list['uri'] = $list->getUri();
+
+ if (isset($this->auth_user)) {
+ $twitter_list['following'] = $list->hasSubscriber($this->auth_user);
+ } else {
+ $twitter_list['following'] = false;
+ }
+
+ $twitter_list['mode'] = ($list->private) ? 'private' : 'public';
+ $twitter_list['user'] = $this->twitterUserArray($profile, false);
+
+ return $twitter_list;
+ }
+
function twitterRssEntryArray($notice)
{
$entry = array();
$this->elementEnd('group');
}
+ function showTwitterXmlList($twitter_list)
+ {
+ $this->elementStart('list');
+ foreach($twitter_list as $element => $value) {
+ if($element == 'user') {
+ $this->showTwitterXmlUser($value, 'user');
+ }
+ else {
+ $this->element($element, null, $value);
+ }
+ }
+ $this->elementEnd('list');
+ }
+
function showTwitterXmlUser($twitter_user, $role='user', $namespaces=false)
{
$attrs = array();
$this->endDocument('xml');
}
+ function showXmlLists($list, $next_cursor=0, $prev_cursor=0)
+ {
+
+ $this->initDocument('xml');
+ $this->elementStart('lists_list');
+ $this->elementStart('lists', array('type' => 'array'));
+
+ if (is_array($list)) {
+ foreach ($list as $l) {
+ $twitter_list = $this->twitterListArray($l);
+ $this->showTwitterXmlList($twitter_list);
+ }
+ } else {
+ while ($list->fetch()) {
+ $twitter_list = $this->twitterListArray($list);
+ $this->showTwitterXmlList($twitter_list);
+ }
+ }
+
+ $this->elementEnd('lists');
+
+ $this->element('next_cursor', null, $next_cursor);
+ $this->element('previous_cursor', null, $prev_cursor);
+
+ $this->elementEnd('lists_list');
+ $this->endDocument('xml');
+ }
+
+ function showJsonLists($list, $next_cursor=0, $prev_cursor=0)
+ {
+ $this->initDocument('json');
+
+ $lists = array();
+
+ if (is_array($list)) {
+ foreach ($list as $l) {
+ $twitter_list = $this->twitterListArray($l);
+ array_push($lists, $twitter_list);
+ }
+ } else {
+ while ($list->fetch()) {
+ $twitter_list = $this->twitterListArray($list);
+ array_push($lists, $twitter_list);
+ }
+ }
+
+ $lists_list = array(
+ 'lists' => $lists,
+ 'next_cursor' => $next_cursor,
+ 'next_cursor_str' => strval($next_cursor),
+ 'previous_cursor' => $prev_cursor,
+ 'previous_cursor_str' => strval($prev_cursor)
+ );
+
+ $this->showJsonObjects($lists_list);
+
+ $this->endDocument('json');
+ }
+
function showTwitterXmlUsers($user)
{
$this->initDocument('xml');
$this->endDocument('xml');
}
+ function showSingleJsonList($list)
+ {
+ $this->initDocument('json');
+ $twitter_list = $this->twitterListArray($list);
+ $this->showJsonObjects($twitter_list);
+ $this->endDocument('json');
+ }
+
+ function showSingleXmlList($list)
+ {
+ $this->initDocument('xml');
+ $twitter_list = $this->twitterListArray($list);
+ $this->showTwitterXmlList($twitter_list);
+ $this->endDocument('xml');
+ }
+
function dateTwitter($dt)
{
$dateStr = date('d F Y H:i:s', strtotime($dt));
}
}
+ function getTargetList($user=null, $id=null)
+ {
+ $tagger = $this->getTargetUser($user);
+ $list = null;
+
+ if (empty($id)) {
+ $id = $this->arg('id');
+ }
+
+ if($id) {
+ if (is_numeric($id)) {
+ $list = Profile_list::staticGet('id', $id);
+
+ // only if the list with the id belongs to the tagger
+ if(empty($list) || $list->tagger != $tagger->id) {
+ $list = null;
+ }
+ }
+ if (empty($list)) {
+ $tag = common_canonical_tag($id);
+ $list = Profile_list::getByTaggerAndTag($tagger->id, $tag);
+ }
+
+ if (!empty($list) && $list->private) {
+ if ($this->auth_user->id == $list->tagger) {
+ return $list;
+ }
+ } else {
+ return $list;
+ }
+ }
+ return null;
+ }
+
/**
* Returns query argument or default value if not found. Certain
* parameters used throughout the API are lightly scrubbed and
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Base class for list members and list subscribers 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
+ * @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';
+
+class ApiListUsersAction extends ApiBareAuthAction
+{
+ var $list = null;
+ var $user = false;
+ var $create = false;
+ var $delete = false;
+ var $cursor = -1;
+ var $next_cursor = 0;
+ var $prev_cursor = 0;
+ var $users = null;
+
+ function prepare($args)
+ {
+ // delete list member if method is DELETE or if method is POST and an argument
+ // _method is set to DELETE
+ $this->delete = ($_SERVER['REQUEST_METHOD'] == 'DELETE' ||
+ ($this->trimmed('_method') == 'DELETE' &&
+ $_SERVER['REQUEST_METHOD'] == 'POST'));
+
+ // add member if method is POST
+ $this->create = (!$this->delete &&
+ $_SERVER['REQUEST_METHOD'] == 'POST');
+
+ if($this->arg('id')) {
+ $this->user = $this->getTargetUser($this->arg('id'));
+ }
+
+ parent::prepare($args);
+
+ $this->list = $this->getTargetList($this->arg('user'), $this->arg('list_id'));
+
+ if (empty($this->list)) {
+ $this->clientError(_('Not found'), 404, $this->format);
+ return false;
+ }
+
+ if(!$this->create && !$this->delete) {
+ $this->getUsers();
+ }
+ return true;
+ }
+
+ function requiresAuth()
+ {
+ return parent::requiresAuth() ||
+ $this->create || $this->delete;
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if($this->delete) {
+ return $this->handleDelete();
+ }
+
+ if($this->create) {
+ return $this->handlePost();
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->initDocument('xml');
+ $this->elementStart('users_list', array('xmlns:statusnet' =>
+ 'http://status.net/schema/api/1/'));
+ $this->elementStart('users', array('type' => 'array'));
+
+ if (is_array($this->users)) {
+ foreach ($this->users as $u) {
+ $twitter_user = $this->twitterUserArray($u, true);
+ $this->showTwitterXmlUser($twitter_user);
+ }
+ } else {
+ while ($this->users->fetch()) {
+ $twitter_user = $this->twitterUserArray($this->users, true);
+ $this->showTwitterXmlUser($twitter_user);
+ }
+ }
+
+ $this->elementEnd('users');
+ $this->element('next_cursor', null, $this->next_cursor);
+ $this->element('previous_cursor', null, $this->prev_cursor);
+ $this->elementEnd('users_list');
+ break;
+ case 'json':
+ $this->initDocument('json');
+
+ $users = array();
+
+ if (is_array($this->users)) {
+ foreach ($this->users as $u) {
+ $twitter_user = $this->twitterUserArray($u, true);
+ array_push($users, $twitter_user);
+ }
+ } else {
+ while ($this->users->fetch()) {
+ $twitter_user = $this->twitterUserArray($this->users, true);
+ array_push($users, $twitter_user);
+ }
+ }
+
+ $users_list = array('users' => $users,
+ 'next_cursor' => $this->next_cursor,
+ 'next_cursor_str' => strval($this->next_cursor),
+ 'previous_cursor' => $this->prev_cursor,
+ 'previous_cursor_str' => strval($this->prev_cursor));
+
+ $this->showJsonObjects($users_list);
+
+ $this->endDocument('json');
+ break;
+ default:
+ $this->clientError(
+ _('API method not found.'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+
+ function handlePost()
+ {
+ }
+
+ function handleDelete()
+ {
+ }
+
+ function getUsers()
+ {
+ }
+
+ function isReadOnly($args)
+ {
+ return false;
+ }
+
+ function lastModified()
+ {
+ if(!empty($this->list)) {
+ return strtotime($this->list->modified);
+ }
+ return null;
+ }
+
+ /**
+ * An entity tag for this list
+ *
+ * Returns an Etag based on the action name, language, user ID and
+ * timestamps of the first and last list the user has joined
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->list)) {
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->list->id,
+ strtotime($this->list->created),
+ strtotime($this->list->modified))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Class for building an in-memory Atom feed for a particular list'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 list notice feeds. May contain a reference to the list.
+ *
+ * @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 AtomListNoticeFeed extends AtomNoticeFeed
+{
+ private $list;
+ private $tagger;
+
+ /**
+ * Constructor
+ *
+ * @param List $list the list for the feed
+ * @param User $cur the current authenticated user, if any
+ * @param boolean $indent flag to turn indenting on or off
+ *
+ * @return void
+ */
+ function __construct($list, $cur = null, $indent = true) {
+ parent::__construct($cur, $indent);
+ $this->list = $list;
+ $this->tagger = Profile::staticGet('id', $list->tagger);
+
+ // TRANS: Title in atom list notice feed. %s is a list name.
+ $title = sprintf(_("Timeline for people tagged #%s by %s"), $list->tag, $this->tagger->nickname);
+ $this->setTitle($title);
+
+ $sitename = common_config('site', 'name');
+ $subtitle = sprintf(
+ // TRANS: Message is used as a subtitle in atom list notice feed.
+ // TRANS: %1$s is a list name, %2$s is a site name.
+ _('Updates from %1$s\'s %2$s people tag on %3$s!'),
+ $this->tagger->nickname,
+ $list->tag,
+ $sitename
+ );
+ $this->setSubtitle($subtitle);
+
+ $avatar = $this->tagger->avatarUrl(AVATAR_PROFILE_SIZE);
+ $this->setLogo($avatar);
+
+ $this->setUpdated('now');
+
+ $self = common_local_url('ApiTimelineList',
+ array('user' => $this->tagger->nickname,
+ 'id' => $list->tag,
+ 'format' => 'atom'));
+ $this->setId($self);
+ $this->setSelfLink($self);
+
+ // FIXME: Stop using activity:subject?
+ $ao = ActivityObject::fromPeopletag($this->list);
+
+ $this->addAuthorRaw($ao->asString('author').
+ $ao->asString('activity:subject'));
+
+ $this->addLink($this->list->getUri());
+ }
+
+ function getList()
+ {
+ return $this->list;
+ }
+
+}
'id' => '[a-zA-Z0-9]+',
'format' => '(xml|json)'));
+ // Lists (people tags)
+
+ $m->connect('api/lists/memberships.:format',
+ array('action' => 'ApiListMemberships',
+ 'format' => '(xml|json)'));
+
+ $m->connect('api/:user/lists/memberships.:format',
+ array('action' => 'ApiListMemberships',
+ 'user' => '[a-zA-Z0-9]+',
+ 'format' => '(xml|json)'));
+
+ $m->connect('api/lists/subscriptions.:format',
+ array('action' => 'ApiListSubscriptions',
+ 'format' => '(xml|json)'));
+
+ $m->connect('api/:user/lists/subscriptions.:format',
+ array('action' => 'ApiListSubscriptions',
+ 'user' => '[a-zA-Z0-9]+',
+ 'format' => '(xml|json)'));
+ $m->connect('api/lists.:format',
+ array('action' => 'ApiLists',
+ 'format' => '(xml|json)'));
+
+ $m->connect('api/:user/lists.:format',
+ array('action' => 'ApiLists',
+ 'user' => '[a-zA-Z0-9]+',
+ 'format' => '(xml|json)'));
+
+ $m->connect('api/:user/lists/:id.:format',
+ array('action' => 'ApiList',
+ 'user' => '[a-zA-Z0-9]+',
+ 'id' => '[a-zA-Z0-9]+',
+ 'format' => '(xml|json)'));
+
+ $m->connect('api/:user/lists/:id/statuses.:format',
+ array('action' => 'ApiTimelineList',
+ 'user' => '[a-zA-Z0-9]+',
+ 'id' => '[a-zA-Z0-9]+',
+ 'format' => '(xml|json|rss|atom)'));
+
+ $m->connect('api/:user/:list_id/members.:format',
+ array('action' => 'ApiListMembers',
+ 'user' => '[a-zA-Z0-9]+',
+ 'list_id' => '[a-zA-Z0-9]+',
+ 'format' => '(xml|json)'));
+
+ $m->connect('api/:user/:list_id/subscribers.:format',
+ array('action' => 'ApiListSubscribers',
+ 'user' => '[a-zA-Z0-9]+',
+ 'list_id' => '[a-zA-Z0-9]+',
+ 'format' => '(xml|json)'));
+
+ $m->connect('api/:user/:list_id/members/:id.:format',
+ array('action' => 'ApiListMember',
+ 'user' => '[a-zA-Z0-9]+',
+ 'list_id' => '[a-zA-Z0-9]+',
+ 'id' => '[a-zA-Z0-9]+',
+ 'format' => '(xml|json)'));
+
+ $m->connect('api/:user/:list_id/subscribers/:id.:format',
+ array('action' => 'ApiListSubscriber',
+ 'user' => '[a-zA-Z0-9]+',
+ 'list_id' => '[a-zA-Z0-9]+',
+ 'id' => '[a-zA-Z0-9]+',
+ 'format' => '(xml|json)'));
+
// Tags
$m->connect('api/statusnet/tags/timeline/:tag.:format',
array('action' => 'ApiTimelineTag',