diff options
author | Evan Prodromou <evan@controlyourself.ca> | 2009-03-12 11:56:23 -0400 |
---|---|---|
committer | Evan Prodromou <evan@controlyourself.ca> | 2009-03-12 11:56:23 -0400 |
commit | b3a0eea3b66e95becb6c4595ed71c7fe71ed6437 (patch) | |
tree | 76666150701f03205bfff77e7d034dfa724f8764 /actions | |
parent | 399669b1fb955d2d8c18098a7b551184d534a94c (diff) | |
parent | e185c0395a6cd250ccd7c8e385c54830be73f937 (diff) |
Merge branch '0.7.x' into 0.8.x
Conflicts:
classes/Notice.php
lib/action.php
lib/router.php
lib/twitter.php
Diffstat (limited to 'actions')
-rw-r--r-- | actions/all.php | 4 | ||||
-rw-r--r-- | actions/allrss.php | 5 | ||||
-rw-r--r-- | actions/api.php | 2 | ||||
-rw-r--r-- | actions/favorited.php | 2 | ||||
-rw-r--r-- | actions/finishopenidlogin.php | 3 | ||||
-rw-r--r-- | actions/finishremotesubscribe.php | 8 | ||||
-rw-r--r-- | actions/grouplogo.php | 2 | ||||
-rw-r--r-- | actions/joingroup.php | 2 | ||||
-rw-r--r-- | actions/leavegroup.php | 8 | ||||
-rw-r--r-- | actions/noticesearchrss.php | 3 | ||||
-rw-r--r-- | actions/peopletag.php | 2 | ||||
-rw-r--r-- | actions/postnotice.php | 2 | ||||
-rw-r--r-- | actions/publicrss.php | 5 | ||||
-rw-r--r-- | actions/remotesubscribe.php | 12 | ||||
-rw-r--r-- | actions/showgroup.php | 6 | ||||
-rw-r--r-- | actions/sup.php | 4 | ||||
-rw-r--r-- | actions/twitapidirect_messages.php | 24 | ||||
-rw-r--r-- | actions/twitapifavorites.php | 14 | ||||
-rw-r--r-- | actions/twitapisearchatom.php | 377 | ||||
-rw-r--r-- | actions/twitapisearchjson.php | 6 | ||||
-rw-r--r-- | actions/twitapistatuses.php | 62 | ||||
-rw-r--r-- | actions/twittersettings.php | 8 | ||||
-rw-r--r-- | actions/updateprofile.php | 20 | ||||
-rw-r--r-- | actions/userauthorization.php | 28 | ||||
-rw-r--r-- | actions/userrss.php | 1 |
25 files changed, 510 insertions, 100 deletions
diff --git a/actions/all.php b/actions/all.php index 08dcccbdd..8e67ec0f3 100644 --- a/actions/all.php +++ b/actions/all.php @@ -77,12 +77,12 @@ class AllAction extends Action sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)), new Feed(Feed::RSS2, common_local_url('api', array('apiaction' => 'statuses', - 'method' => 'friends', + 'method' => 'friends_timeline', 'argument' => $this->user->nickname.'.rss')), sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)), new Feed(Feed::ATOM, common_local_url('api', array('apiaction' => 'statuses', - 'method' => 'friends', + 'method' => 'friends_timeline', 'argument' => $this->user->nickname.'.atom')), sprintf(_('Feed for friends of %s (Atom)'), $this->user->nickname))); } diff --git a/actions/allrss.php b/actions/allrss.php index 0114c4396..45f3946a6 100644 --- a/actions/allrss.php +++ b/actions/allrss.php @@ -81,8 +81,9 @@ class AllrssAction extends Rss10Action */ function getNotices($limit=0) { - $user = $this->user; - $notice = $user->noticesWithFriends(0, $limit); + $user = $this->user; + $notice = $user->noticesWithFriends(0, $limit); + $notices = array(); while ($notice->fetch()) { $notices[] = clone($notice); diff --git a/actions/api.php b/actions/api.php index a27d24492..c18d551b6 100644 --- a/actions/api.php +++ b/actions/api.php @@ -127,7 +127,9 @@ class ApiAction extends Action 'laconica/wadl'); static $bareauth = array('statuses/user_timeline', + 'statuses/friends_timeline', 'statuses/friends', + 'statuses/replies', 'statuses/followers', 'favorites/favorites'); diff --git a/actions/favorited.php b/actions/favorited.php index 5082f4a4e..231b97897 100644 --- a/actions/favorited.php +++ b/actions/favorited.php @@ -178,7 +178,7 @@ class FavoritedAction extends Action $qry = 'SELECT notice.*, '. $weightexpr . ' as weight ' . 'FROM notice JOIN fave ON notice.id = fave.notice_id ' . - 'GROUP BY fave.notice_id ' . + 'GROUP BY id,profile_id,uri,content,rendered,url,created,notice.modified,reply_to,is_local,source ' . 'ORDER BY weight DESC'; $offset = ($this->page - 1) * NOTICES_PER_PAGE; diff --git a/actions/finishopenidlogin.php b/actions/finishopenidlogin.php index 6d92cb9aa..52d9be29c 100644 --- a/actions/finishopenidlogin.php +++ b/actions/finishopenidlogin.php @@ -62,9 +62,8 @@ class FinishopenidloginAction extends Action if ($this->error) { $this->element('div', array('class' => 'error'), $this->error); } else { - global $config; $this->element('div', 'instructions', - sprintf(_('This is the first time you\'ve logged into %s so we must connect your OpenID to a local account. You can either create a new account, or connect with your existing account, if you have one.'), $config['site']['name'])); + sprintf(_('This is the first time you\'ve logged into %s so we must connect your OpenID to a local account. You can either create a new account, or connect with your existing account, if you have one.'), common_config('site', 'name'))); } } diff --git a/actions/finishremotesubscribe.php b/actions/finishremotesubscribe.php index acfacbdc1..eaf57c2d8 100644 --- a/actions/finishremotesubscribe.php +++ b/actions/finishremotesubscribe.php @@ -136,16 +136,16 @@ class FinishremotesubscribeAction extends Action $profile->nickname = $nickname; $profile->profileurl = $profile_url; - if ($fullname) { + if (!is_null($fullname)) { $profile->fullname = $fullname; } - if ($homepage) { + if (!is_null($homepage)) { $profile->homepage = $homepage; } - if ($bio) { + if (!is_null($bio)) { $profile->bio = $bio; } - if ($location) { + if (!is_null($location)) { $profile->location = $location; } diff --git a/actions/grouplogo.php b/actions/grouplogo.php index 499db4ae8..fe6127da2 100644 --- a/actions/grouplogo.php +++ b/actions/grouplogo.php @@ -83,7 +83,7 @@ class GrouplogoAction extends Action if ($nickname_arg != $nickname) { $args = array('nickname' => $nickname); - common_redirect(common_local_url('editgroup', $args), 301); + common_redirect(common_local_url('grouplogo', $args), 301); return false; } diff --git a/actions/joingroup.php b/actions/joingroup.php index 1888ecdab..eeea4a37b 100644 --- a/actions/joingroup.php +++ b/actions/joingroup.php @@ -73,7 +73,7 @@ class JoingroupAction extends Action if ($nickname_arg != $nickname) { $args = array('nickname' => $nickname); - common_redirect(common_local_url('editgroup', $args), 301); + common_redirect(common_local_url('joingroup', $args), 301); return false; } diff --git a/actions/leavegroup.php b/actions/leavegroup.php index c7152e3c0..eb30d0e50 100644 --- a/actions/leavegroup.php +++ b/actions/leavegroup.php @@ -73,7 +73,7 @@ class LeavegroupAction extends Action if ($nickname_arg != $nickname) { $args = array('nickname' => $nickname); - common_redirect(common_local_url('editgroup', $args), 301); + common_redirect(common_local_url('leavegroup', $args), 301); return false; } @@ -96,12 +96,6 @@ class LeavegroupAction extends Action return false; } - if ($cur->isAdmin($this->group)) { - $this->clientError(_('You may not leave a group while you are its administrator.'), 403); - return false; - - } - return true; } diff --git a/actions/noticesearchrss.php b/actions/noticesearchrss.php index 7172977ee..0f98ed04b 100644 --- a/actions/noticesearchrss.php +++ b/actions/noticesearchrss.php @@ -82,10 +82,9 @@ class NoticesearchrssAction extends Rss10Action function getChannel() { - global $config; $q = $this->trimmed('q'); $c = array('url' => common_local_url('noticesearchrss', array('q' => $q)), - 'title' => $config['site']['name'] . sprintf(_(' Search Stream for "%s"'), $q), + 'title' => common_config('site', 'name') . sprintf(_(' Search Stream for "%s"'), $q), 'link' => common_local_url('noticesearch', array('q' => $q)), 'description' => sprintf(_('All updates matching search term "%s"'), $q)); return $c; diff --git a/actions/peopletag.php b/actions/peopletag.php index 6b1e34f1a..5add75485 100644 --- a/actions/peopletag.php +++ b/actions/peopletag.php @@ -119,7 +119,7 @@ class PeopletagAction extends Action 'FROM profile JOIN profile_tag ' . 'ON profile.id = profile_tag.tagger ' . 'WHERE profile_tag.tagger = profile_tag.tagged ' . - 'AND tag = "%s" ' . + "AND tag = '%s' " . 'ORDER BY profile_tag.modified DESC%s'; $profile->query(sprintf($qry, $this->tag, $lim)); diff --git a/actions/postnotice.php b/actions/postnotice.php index 0b4735296..c32d8ca94 100644 --- a/actions/postnotice.php +++ b/actions/postnotice.php @@ -79,7 +79,7 @@ class PostnoticeAction extends Action } $notice = Notice::staticGet('uri', $notice_uri); if (!$notice) { - $notice = Notice::saveNew($remote_profile->id, $content, 'omb', false, 0, $notice_uri); + $notice = Notice::saveNew($remote_profile->id, $content, 'omb', false, null, $notice_uri); if (is_string($notice)) { common_server_serror($notice, 500); return false; diff --git a/actions/publicrss.php b/actions/publicrss.php index c35877997..77e26e0f4 100644 --- a/actions/publicrss.php +++ b/actions/publicrss.php @@ -84,12 +84,11 @@ class PublicrssAction extends Rss10Action */ function getChannel() { - global $config; $c = array( 'url' => common_local_url('publicrss') - , 'title' => sprintf(_('%s Public Stream'), $config['site']['name']) + , 'title' => sprintf(_('%s Public Stream'), common_config('site', 'name')) , 'link' => common_local_url('public') - , 'description' => sprintf(_('All updates for %s'), $config['site']['name'])); + , 'description' => sprintf(_('All updates for %s'), common_config('site', 'name'))); return $c; } diff --git a/actions/remotesubscribe.php b/actions/remotesubscribe.php index 7ea7acd6d..af130f425 100644 --- a/actions/remotesubscribe.php +++ b/actions/remotesubscribe.php @@ -333,8 +333,6 @@ class RemotesubscribeAction extends Action function requestAuthorization($user, $omb, $token, $secret) { - global $config; # for license URL - $con = omb_oauth_consumer(); $tok = new OAuthToken($token, $secret); @@ -358,7 +356,7 @@ class RemotesubscribeAction extends Action $req->set_parameter('omb_listenee', $user->uri); $req->set_parameter('omb_listenee_profile', common_profile_url($user->nickname)); $req->set_parameter('omb_listenee_nickname', $user->nickname); - $req->set_parameter('omb_listenee_license', $config['license']['url']); + $req->set_parameter('omb_listenee_license', common_config('license', 'url')); $profile = $user->getProfile(); if (!$profile) { @@ -367,16 +365,16 @@ class RemotesubscribeAction extends Action return; } - if ($profile->fullname) { + if (!is_null($profile->fullname)) { $req->set_parameter('omb_listenee_fullname', $profile->fullname); } - if ($profile->homepage) { + if (!is_null($profile->homepage)) { $req->set_parameter('omb_listenee_homepage', $profile->homepage); } - if ($profile->bio) { + if (!is_null($profile->bio)) { $req->set_parameter('omb_listenee_bio', $profile->bio); } - if ($profile->location) { + if (!is_null($profile->location)) { $req->set_parameter('omb_listenee_location', $profile->location); } $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); diff --git a/actions/showgroup.php b/actions/showgroup.php index c20941a35..b6022840b 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -275,10 +275,8 @@ class ShowgroupAction extends Action $cur = common_current_user(); if ($cur) { if ($cur->isMember($this->group)) { - if (!$cur->isAdmin($this->group)) { - $lf = new LeaveForm($this, $this->group); - $lf->show(); - } + $lf = new LeaveForm($this, $this->group); + $lf->show(); } else { $jf = new JoinForm($this, $this->group); $jf->show(); diff --git a/actions/sup.php b/actions/sup.php index f4b1cda23..8ef9207fa 100644 --- a/actions/sup.php +++ b/actions/sup.php @@ -65,7 +65,9 @@ class SupAction extends Action $notice->query('SELECT profile_id, max(id) AS max_id ' . 'FROM notice ' . - 'WHERE created > (now() - ' . $seconds . ') ' . + ((common_config('db','type') == 'pgsql') ? + 'WHERE extract(epoch from created) > (extract(epoch from now()) - ' . $seconds . ') ' : + 'WHERE created > (now() - ' . $seconds . ') ' ) . 'GROUP BY profile_id'); $updates = array(); diff --git a/actions/twitapidirect_messages.php b/actions/twitapidirect_messages.php index db55e8cd0..7101db8df 100644 --- a/actions/twitapidirect_messages.php +++ b/actions/twitapidirect_messages.php @@ -38,7 +38,6 @@ class Twitapidirect_messagesAction extends TwitterapiAction function show_messages($args, $apidata, $type) { - $user = $apidata['user']; $count = $this->arg('count'); @@ -102,7 +101,17 @@ class Twitapidirect_messagesAction extends TwitterapiAction $this->show_rss_dmsgs($message, $title, $link, $subtitle); break; case 'atom': - $this->show_atom_dmsgs($message, $title, $link, $subtitle); + $selfuri = common_root_url() . 'api/direct_messages'; + $selfuri .= ($type == 'received') ? '.atom' : '/sent.atom'; + $taguribase = common_config('integration', 'taguri'); + + if ($type == 'sent') { + $id = "tag:$taguribase:SentDirectMessages:" . $user->id; + } else { + $id = "tag:$taguribase:DirectMessages:" . $user->id; + } + + $this->show_atom_dmsgs($message, $title, $link, $subtitle, $selfuri, $id); break; case 'json': $this->show_json_dmsgs($message); @@ -190,7 +199,7 @@ class Twitapidirect_messagesAction extends TwitterapiAction $this->init_document('xml'); $this->elementStart('direct-messages', array('type' => 'array')); - if (is_array($messages)) { + if (is_array($message)) { foreach ($message as $m) { $twitter_dm = $this->twitter_dmsg_array($m); $this->show_twitter_xml_dmsg($twitter_dm); @@ -261,16 +270,17 @@ class Twitapidirect_messagesAction extends TwitterapiAction } - function show_atom_dmsgs($message, $title, $link, $subtitle) + function show_atom_dmsgs($message, $title, $link, $subtitle, $selfuri, $id) { $this->init_document('atom'); $this->element('title', null, $title); - $siteserver = common_config('site', 'server'); - $this->element('id', null, "tag:$siteserver,2008:DirectMessage"); + $this->element('id', null, $id); $this->element('link', array('href' => $link, 'rel' => 'alternate', 'type' => 'text/html'), null); - $this->element('updated', null, common_date_iso8601(strftime('%c'))); + $this->element('link', array('href' => $selfuri, 'rel' => 'self', + 'type' => 'application/atom+xml'), null); + $this->element('updated', null, common_date_iso8601('now')); $this->element('subtitle', null, $subtitle); if (is_array($message)) { diff --git a/actions/twitapifavorites.php b/actions/twitapifavorites.php index 737b7229f..31dce341b 100644 --- a/actions/twitapifavorites.php +++ b/actions/twitapifavorites.php @@ -61,10 +61,9 @@ class TwitapifavoritesAction extends TwitterapiAction } $sitename = common_config('site', 'name'); - $siteserver = common_config('site', 'server'); - $title = sprintf(_('%s / Favorites from %s'), $sitename, $user->nickname); - $id = "tag:$siteserver:favorites:".$user->id; + $taguribase = common_config('integration', 'taguri'); + $id = "tag:$taguribase:Favorites:".$user->id; $link = common_local_url('favorites', array('nickname' => $user->nickname)); $subtitle = sprintf(_('%s updates favorited by %s / %s.'), $sitename, $profile->getBestName(), $user->nickname); @@ -76,7 +75,14 @@ class TwitapifavoritesAction extends TwitterapiAction $this->show_rss_timeline($notice, $title, $link, $subtitle); break; case 'atom': - $this->show_atom_timeline($notice, $title, $id, $link, $subtitle); + if (isset($apidata['api_arg'])) { + $selfuri = $selfuri = common_root_url() . + 'api/favorites/' . $apidata['api_arg'] . '.atom'; + } else { + $selfuri = $selfuri = common_root_url() . + 'api/favorites.atom'; + } + $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, null, $selfuri); break; case 'json': $this->show_json_timeline($notice); diff --git a/actions/twitapisearchatom.php b/actions/twitapisearchatom.php new file mode 100644 index 000000000..eb9ab5d8e --- /dev/null +++ b/actions/twitapisearchatom.php @@ -0,0 +1,377 @@ +<?php +/** + * Laconica, the distributed open-source microblogging tool + * + * Action for showing Twitter-like Atom search results + * + * 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 Search + * @package Laconica + * @author Zach Copley <zach@controlyourself.ca> + * @copyright 2008-2009 Control Yourself, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + */ + +if (!defined('LACONICA')) { + exit(1); +} + +require_once INSTALLDIR.'/lib/twitterapi.php'; + +/** + * Action for outputting search results in Twitter compatible Atom + * format. + * + * TODO: abstract Atom stuff into a ruseable base class like + * RSS10Action. + * + * @category Search + * @package Laconica + * @author Zach Copley <zach@controlyourself.ca> + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + * + * @see TwitterapiAction + */ + +class TwitapisearchatomAction extends TwitterapiAction +{ + + var $cnt; + var $query; + var $lang; + var $rpp; + var $page; + var $since_id; + var $geocode; + + /** + * Constructor + * + * Just wraps the Action constructor. + * + * @param string $output URI to output to, default = stdout + * @param boolean $indent Whether to indent output, default true + * + * @see Action::__construct + */ + + function __construct($output='php://output', $indent=true) + { + parent::__construct($output, $indent); + } + + /** + * Do we need to write to the database? + * + * @return boolean true + */ + + function isReadonly() + { + return true; + } + + /** + * Read arguments and initialize members + * + * @param array $args Arguments from $_REQUEST + * + * @return boolean success + * + */ + + function prepare($args) + { + parent::prepare($args); + + $this->query = $this->trimmed('q'); + $this->lang = $this->trimmed('lang'); + $this->rpp = $this->trimmed('rpp'); + + if (!$this->rpp) { + $this->rpp = 15; + } + + if ($this->rpp > 100) { + $this->rpp = 100; + } + + $this->page = $this->trimmed('page'); + + if (!$this->page) { + $this->page = 1; + } + + // TODO: Suppport since_id -- we need to tweak the backend + // Search classes to support it. + + $this->since_id = $this->trimmed('since_id'); + $this->geocode = $this->trimmed('geocode'); + + // TODO: Also, language and geocode + + return true; + } + + /** + * Handle a request + * + * @param array $args Arguments from $_REQUEST + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + $this->showAtom(); + } + + /** + * Get the notices to output as results. This also sets some class + * attrs so we can use them to calculate pagination, and output + * since_id and max_id. + * + * @return array an array of Notice objects sorted in reverse chron + */ + + function getNotices() + { + // TODO: Support search operators like from: and to:, boolean, etc. + + $notices = array(); + $notice = new Notice(); + + // lcase it for comparison + $q = strtolower($this->query); + + $search_engine = $notice->getSearchEngine('identica_notices'); + $search_engine->set_sort_mode('chron'); + $search_engine->limit(($this->page - 1) * $this->rpp, + $this->rpp + 1, true); + $search_engine->query($q); + $this->cnt = $notice->find(); + + $cnt = 0; + + while ($notice->fetch()) { + + ++$cnt; + + if (!$this->max_id) { + $this->max_id = $notice->id; + } + + if ($cnt > $this->rpp) { + break; + } + + $notices[] = clone($notice); + } + + return $notices; + } + + /** + * Output search results as an Atom feed + * + * @return void + */ + + function showAtom() + { + $notices = $this->getNotices(); + + $this->initAtom(); + $this->showFeed(); + + foreach ($notices as $n) { + $this->showEntry($n); + } + + $this->endAtom(); + } + + /** + * Show feed specific Atom elements + * + * @return void + */ + + function showFeed() + { + // TODO: A9 OpenSearch stuff like search.twitter.com? + + $server = common_config('site', 'server'); + $sitename = common_config('site', 'name'); + + // XXX: Use xmlns:laconica instead? + + $this->elementStart('feed', + array('xmlns' => 'http://www.w3.org/2005/Atom', + + // XXX: xmlns:twitter causes Atom validation to fail + // It's used for the source attr on notices + + 'xmlns:twitter' => 'http://api.twitter.com/', + 'xml:lang' => 'en-US')); // XXX Other locales ? + + $taguribase = common_config('integration', 'taguri'); + $this->element('id', null, "tag:$taguribase:search/$server"); + + $site_uri = common_path(false); + + $search_uri = $site_uri . 'api/search.atom?q=' . urlencode($this->query); + + if ($this->rpp != 15) { + $search_uri .= '&rpp=' . $this->rpp; + } + + // FIXME: this alternate link is not quite right because our + // web-based notice search doesn't support a rpp (responses per + // page) param yet + + $this->element('link', array('type' => 'text/html', + 'rel' => 'alternate', + 'href' => $site_uri . 'search/notice?q=' . + urlencode($this->query))); + + // self link + + $self_uri = $search_uri; + $self_uri .= ($this->page > 1) ? '&page=' . $this->page : ''; + + $this->element('link', array('type' => 'application/atom+xml', + 'rel' => 'self', + 'href' => $self_uri)); + + $this->element('title', null, "$this->query - $sitename Search"); + $this->element('updated', null, common_date_iso8601('now')); + + // XXX: The below "rel" links are not valid Atom, but it's what + // Twitter does... + + // refresh link + + $refresh_uri = $search_uri . "&since_id=" . $this->max_id; + + $this->element('link', array('type' => 'application/atom+xml', + 'rel' => 'refresh', + 'href' => $refresh_uri)); + + // pagination links + + if ($this->cnt > $this->rpp) { + + $next_uri = $search_uri . "&max_id=" . $this->max_id . + '&page=' . ($this->page + 1); + + $this->element('link', array('type' => 'application/atom+xml', + 'rel' => 'next', + 'href' => $next_uri)); + } + + if ($this->page > 1) { + + $previous_uri = $search_uri . "&max_id=" . $this->max_id . + '&page=' . ($this->page - 1); + + $this->element('link', array('type' => 'application/atom+xml', + 'rel' => 'previous', + 'href' => $previous_uri)); + } + + } + + /** + * Build an Atom entry similar to search.twitter.com's based on + * a given notice + * + * @param Notice $notice the notice to use + * + * @return void + */ + + function showEntry($notice) + { + $server = common_config('site', 'server'); + $profile = $notice->getProfile(); + $nurl = common_local_url('shownotice', array('notice' => $notice->id)); + + $this->elementStart('entry'); + + $taguribase = common_config('integration', 'taguri'); + + $this->element('id', null, "tag:$taguribase:$notice->id"); + $this->element('published', null, common_date_w3dtf($notice->created)); + $this->element('link', array('type' => 'text/html', + 'rel' => 'alternate', + 'href' => $nurl)); + $this->element('title', null, common_xml_safe_str(trim($notice->content))); + $this->element('content', array('type' => 'html'), $notice->rendered); + $this->element('updated', null, common_date_w3dtf($notice->created)); + $this->element('link', array('type' => 'image/png', + // XXX: Twitter uses rel="image" (not valid) + 'rel' => 'related', + 'href' => $profile->avatarUrl())); + + // TODO: Here is where we'd put in a link to an atom feed for threads + + $this->element("twitter:source", null, + htmlentities($this->source_link($notice->source))); + + $this->elementStart('author'); + + $name = $profile->nickname; + + if ($profile->fullname) { + $name .= ' (' . $profile->fullname . ')'; + } + + $this->element('name', null, $name); + $this->element('uri', null, common_profile_uri($profile)); + $this->elementEnd('author'); + + $this->elementEnd('entry'); + } + + /** + * Initialize the Atom output, send headers + * + * @return void + */ + + function initAtom() + { + header('Content-Type: application/atom+xml; charset=utf-8'); + $this->startXml(); + } + + /** + * End the Atom feed + * + * @return void + */ + + function endAtom() + { + $this->elementEnd('feed'); + } + +} diff --git a/actions/twitapisearchjson.php b/actions/twitapisearchjson.php index b50aa86b7..0f9f523a1 100644 --- a/actions/twitapisearchjson.php +++ b/actions/twitapisearchjson.php @@ -2,7 +2,7 @@ /** * Laconica, the distributed open-source microblogging tool * - * List of replies + * Action for showing Twitter-like JSON search results * * PHP version 5 * @@ -114,7 +114,7 @@ class TwitapisearchjsonAction extends TwitterapiAction function showResults() { - // TODO: Support search operators like from: and to: + // TODO: Support search operators like from: and to:, boolean, etc. $notice = new Notice(); @@ -137,7 +137,7 @@ class TwitapisearchjsonAction extends TwitterapiAction } /** - * This is a read-only action + * Do we need to write to the database? * * @return boolean true */ diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php index 216835026..323c4f1f8 100644 --- a/actions/twitapistatuses.php +++ b/actions/twitapistatuses.php @@ -29,10 +29,12 @@ class TwitapistatusesAction extends TwitterapiAction parent::handle($args); $sitename = common_config('site', 'name'); - $siteserver = common_config('site', 'server'); $title = sprintf(_("%s public timeline"), $sitename); - $id = "tag:$siteserver:Statuses"; + + $taguribase = common_config('integration', 'taguri'); + $id = "tag:$taguribase:PublicTimeline"; $link = common_root_url(); + $subtitle = sprintf(_("%s updates from everyone!"), $sitename); // Number of public statuses to return by default -- Twitter sends 20 @@ -70,7 +72,8 @@ class TwitapistatusesAction extends TwitterapiAction $this->show_rss_timeline($notice, $title, $link, $subtitle); break; case 'atom': - $this->show_atom_timeline($notice, $title, $id, $link, $subtitle); + $selfuri = common_root_url() . 'api/statuses/public_timeline.atom'; + $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, null, $selfuri); break; case 'json': $this->show_json_timeline($notice); @@ -114,17 +117,19 @@ class TwitapistatusesAction extends TwitterapiAction } $since = strtotime($this->arg('since')); - - $user = $this->get_user(null, $apidata); + $user = $this->get_user($apidata['api_arg'], $apidata); $this->auth_user = $user; - $profile = $user->getProfile(); + if (empty($user)) { + $this->clientError(_('No such user!'), 404, $apidata['content-type']); + return; + } + $profile = $user->getProfile(); $sitename = common_config('site', 'name'); - $siteserver = common_config('site', 'server'); - $title = sprintf(_("%s and friends"), $user->nickname); - $id = "tag:$siteserver:friends:" . $user->id; + $taguribase = common_config('integration', 'taguri'); + $id = "tag:$taguribase:FriendsTimeline:" . $user->id; $link = common_local_url('all', array('nickname' => $user->nickname)); $subtitle = sprintf(_('Updates from %1$s and friends on %2$s!'), $user->nickname, $sitename); @@ -138,7 +143,14 @@ class TwitapistatusesAction extends TwitterapiAction $this->show_rss_timeline($notice, $title, $link, $subtitle); break; case 'atom': - $this->show_atom_timeline($notice, $title, $id, $link, $subtitle); + if (isset($apidata['api_arg'])) { + $selfuri = $selfuri = common_root_url() . + 'api/statuses/friends_timeline/' . $apidata['api_arg'] . '.atom'; + } else { + $selfuri = $selfuri = common_root_url() . + 'api/statuses/friends_timeline.atom'; + } + $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, null, $selfuri); break; case 'json': $this->show_json_timeline($notice); @@ -194,10 +206,9 @@ class TwitapistatusesAction extends TwitterapiAction $since = strtotime($this->arg('since')); $sitename = common_config('site', 'name'); - $siteserver = common_config('site', 'server'); - $title = sprintf(_("%s timeline"), $user->nickname); - $id = "tag:$siteserver:user:".$user->id; + $taguribase = common_config('integration', 'taguri'); + $id = "tag:$taguribase:UserTimeline:".$user->id; $link = common_local_url('showstream', array('nickname' => $user->nickname)); $subtitle = sprintf(_('Updates from %1$s on %2$s!'), $user->nickname, $sitename); @@ -219,7 +230,14 @@ class TwitapistatusesAction extends TwitterapiAction $this->show_rss_timeline($notice, $title, $link, $subtitle, $suplink); break; case 'atom': - $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, $suplink); + if (isset($apidata['api_arg'])) { + $selfuri = $selfuri = common_root_url() . + 'api/statuses/user_timeline/' . $apidata['api_arg'] . '.atom'; + } else { + $selfuri = $selfuri = common_root_url() . + 'api/statuses/user_timeline.atom'; + } + $this->show_atom_timeline($notice, $title, $id, $link, $subtitle, $suplink, $selfuri); break; case 'json': $this->show_json_timeline($notice); @@ -337,15 +355,14 @@ class TwitapistatusesAction extends TwitterapiAction $since_id = $this->arg('since_id'); $before_id = $this->arg('before_id'); + $user = $this->get_user($apidata['api_arg'], $apidata); $this->auth_user = $apidata['user']; - $user = $this->auth_user; $profile = $user->getProfile(); $sitename = common_config('site', 'name'); - $siteserver = common_config('site', 'server'); - $title = sprintf(_('%1$s / Updates replying to %2$s'), $sitename, $user->nickname); - $id = "tag:$siteserver:replies:".$user->id; + $taguribase = common_config('integration', 'taguri'); + $id = "tag:$taguribase:Replies:".$user->id; $link = common_local_url('replies', array('nickname' => $user->nickname)); $subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'), $sitename, $user->nickname, $profile->getBestName()); @@ -383,7 +400,14 @@ class TwitapistatusesAction extends TwitterapiAction $this->show_rss_timeline($notices, $title, $link, $subtitle); break; case 'atom': - $this->show_atom_timeline($notices, $title, $id, $link, $subtitle); + if (isset($apidata['api_arg'])) { + $selfuri = $selfuri = common_root_url() . + 'api/statuses/replies/' . $apidata['api_arg'] . '.atom'; + } else { + $selfuri = $selfuri = common_root_url() . + 'api/statuses/replies.atom'; + } + $this->show_atom_timeline($notices, $title, $id, $link, $subtitle, null, $selfuri); break; case 'json': $this->show_json_timeline($notices); diff --git a/actions/twittersettings.php b/actions/twittersettings.php index a79859bbf..45725d3ff 100644 --- a/actions/twittersettings.php +++ b/actions/twittersettings.php @@ -186,12 +186,12 @@ class TwittersettingsAction extends ConnectSettingsAction $current_user = common_current_user(); - $qry = 'SELECT user.* ' . + $qry = 'SELECT "user".* ' . 'FROM subscription ' . - 'JOIN user ON subscription.subscribed = user.id ' . - 'JOIN foreign_link ON foreign_link.user_id = user.id ' . + 'JOIN "user" ON subscription.subscribed = "user".id ' . + 'JOIN foreign_link ON foreign_link.user_id = "user".id ' . 'WHERE subscriber = %d ' . - 'ORDER BY user.nickname'; + 'ORDER BY "user".nickname'; $user = new User(); diff --git a/actions/updateprofile.php b/actions/updateprofile.php index 4751a04ff..7dc52fda9 100644 --- a/actions/updateprofile.php +++ b/actions/updateprofile.php @@ -34,6 +34,8 @@ class UpdateprofileAction extends Action $server = omb_oauth_server(); list($consumer, $token) = $server->verify_request($req); if ($this->update_profile($req, $consumer, $token)) { + header('HTTP/1.1 200 OK'); + header('Content-type: text/plain'); print "omb_version=".OMB_VERSION_01; } } catch (OAuthException $e) { @@ -136,22 +138,24 @@ class UpdateprofileAction extends Action $orig_profile = clone($profile); - if ($nickname) { + /* Use values even if they are an empty string. Parsing an empty string in + updateProfile is the specified way of clearing a parameter in OMB. */ + if (!is_null($nickname)) { $profile->nickname = $nickname; } - if ($profile_url) { + if (!is_null($profile_url)) { $profile->profileurl = $profile_url; } - if ($fullname) { + if (!is_null($fullname)) { $profile->fullname = $fullname; } - if ($homepage) { + if (!is_null($homepage)) { $profile->homepage = $homepage; } - if ($bio) { + if (!is_null($bio)) { $profile->bio = $bio; } - if ($location) { + if (!is_null($location)) { $profile->location = $location; } @@ -173,10 +177,6 @@ class UpdateprofileAction extends Action return false; } } - header('HTTP/1.1 200 OK'); - header('Content-type: text/plain'); - print 'Updated profile'; - print "\n"; return true; } } diff --git a/actions/userauthorization.php b/actions/userauthorization.php index 0dc1841d4..6a76e3a4c 100644 --- a/actions/userauthorization.php +++ b/actions/userauthorization.php @@ -113,9 +113,9 @@ class UserauthorizationAction extends Action $this->element('a', array('href' => $profile, 'class' => 'external profile nickname'), $nickname); - if ($fullname) { + if (!is_null($fullname)) { $this->elementStart('div', 'fullname'); - if ($homepage) { + if (!is_null($homepage)) { $this->element('a', array('href' => $homepage), $fullname); } else { @@ -123,10 +123,10 @@ class UserauthorizationAction extends Action } $this->elementEnd('div'); } - if ($location) { + if (!is_null($location)) { $this->element('div', 'location', $location); } - if ($bio) { + if (!is_null($bio)) { $this->element('div', 'bio', $bio); } $this->elementStart('div', 'license'); @@ -179,16 +179,16 @@ class UserauthorizationAction extends Action $params['omb_listener_nickname'] = $user->nickname; $params['omb_listener_profile'] = common_local_url('showstream', array('nickname' => $user->nickname)); - if ($profile->fullname) { + if (!is_null($profile->fullname)) { $params['omb_listener_fullname'] = $profile->fullname; } - if ($profile->homepage) { + if (!is_null($profile->homepage)) { $params['omb_listener_homepage'] = $profile->homepage; } - if ($profile->bio) { + if (!is_null($profile->bio)) { $params['omb_listener_bio'] = $profile->bio; } - if ($profile->location) { + if (!is_null($profile->location)) { $params['omb_listener_location'] = $profile->location; } $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); @@ -197,7 +197,7 @@ class UserauthorizationAction extends Action } $parts = array(); foreach ($params as $k => $v) { - $parts[] = $k . '=' . OAuthUtil::urlencodeRFC3986($v); + $parts[] = $k . '=' . OAuthUtil::urlencode_rfc3986($v); } $query_string = implode('&', $parts); $parsed = parse_url($callback); @@ -267,16 +267,16 @@ class UserauthorizationAction extends Action $profile->nickname = $nickname; $profile->profileurl = $profile_url; - if ($fullname) { + if (!is_null($fullname)) { $profile->fullname = $fullname; } - if ($homepage) { + if (!is_null($homepage)) { $profile->homepage = $homepage; } - if ($bio) { + if (!is_null($bio)) { $profile->bio = $bio; } - if ($location) { + if (!is_null($location)) { $profile->location = $location; } @@ -409,7 +409,7 @@ class UserauthorizationAction extends Action 'omb_listenee_profile', 'omb_listenee_nickname', 'omb_listenee_license') as $param) { - if (!$req->get_parameter($param)) { + if (is_null($req->get_parameter($param))) { throw new OAuthException("Required parameter '$param' not found"); } } diff --git a/actions/userrss.php b/actions/userrss.php index a3e5a3aab..d3bf352d8 100644 --- a/actions/userrss.php +++ b/actions/userrss.php @@ -53,6 +53,7 @@ class UserrssAction extends Rss10Action $notice = $user->getNotices(0, ($limit == 0) ? NOTICES_PER_PAGE : $limit); + $notices = array(); while ($notice->fetch()) { $notices[] = clone($notice); } |