Merge 1.1.x into master
This commit is contained in:
commit
3fc1d245a1
@ -686,7 +686,7 @@ class Profile extends Managed_DataObject
|
|||||||
$profile = new Profile();
|
$profile = new Profile();
|
||||||
$tagged = array();
|
$tagged = array();
|
||||||
|
|
||||||
$cnt = $profile->query(sprintf($qry, $this->id, $this->id, $tag));
|
$cnt = $profile->query(sprintf($qry, $this->id, $this->id, $profile->escape($tag)));
|
||||||
|
|
||||||
while ($profile->fetch()) {
|
while ($profile->fetch()) {
|
||||||
$tagged[] = clone($profile);
|
$tagged[] = clone($profile);
|
||||||
|
@ -284,8 +284,11 @@ class Profile_tag extends Managed_DataObject
|
|||||||
'tag = "%s", tagger = "%s" ' .
|
'tag = "%s", tagger = "%s" ' .
|
||||||
'WHERE tag = "%s" ' .
|
'WHERE tag = "%s" ' .
|
||||||
'AND tagger = "%s"';
|
'AND tagger = "%s"';
|
||||||
$result = $tags->query(sprintf($qry, $new->tag, $new->tagger,
|
$result = $tags->query(sprintf($qry,
|
||||||
$orig->tag, $orig->tagger));
|
$tags->escape($new->tag),
|
||||||
|
$tags->escape($new->tagger),
|
||||||
|
$tags->escape($orig->tag),
|
||||||
|
$tags->escape($orig->tagger)));
|
||||||
|
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
common_log_db_error($tags, 'UPDATE', __FILE__);
|
common_log_db_error($tags, 'UPDATE', __FILE__);
|
||||||
@ -307,8 +310,8 @@ class Profile_tag extends Managed_DataObject
|
|||||||
$profile->query('SELECT profile.* ' .
|
$profile->query('SELECT profile.* ' .
|
||||||
'FROM profile JOIN profile_tag ' .
|
'FROM profile JOIN profile_tag ' .
|
||||||
'ON profile.id = profile_tag.tagged ' .
|
'ON profile.id = profile_tag.tagged ' .
|
||||||
'WHERE profile_tag.tagger = ' . $tagger . ' ' .
|
'WHERE profile_tag.tagger = ' . $profile->escape($tagger) . ' ' .
|
||||||
'AND profile_tag.tag = "' . $tag . '" ');
|
'AND profile_tag.tag = "' . $profile->escape($tag) . '" ');
|
||||||
$tagged = array();
|
$tagged = array();
|
||||||
while ($profile->fetch()) {
|
while ($profile->fetch()) {
|
||||||
$tagged[] = clone($profile);
|
$tagged[] = clone($profile);
|
||||||
|
@ -736,7 +736,7 @@ class User extends Managed_DataObject
|
|||||||
|
|
||||||
$profile = new Profile();
|
$profile = new Profile();
|
||||||
|
|
||||||
$cnt = $profile->query(sprintf($qry, $this->id, $tag));
|
$cnt = $profile->query(sprintf($qry, $this->id, $profile->escape($tag)));
|
||||||
|
|
||||||
return $profile;
|
return $profile;
|
||||||
}
|
}
|
||||||
@ -758,7 +758,7 @@ class User extends Managed_DataObject
|
|||||||
|
|
||||||
$profile = new Profile();
|
$profile = new Profile();
|
||||||
|
|
||||||
$profile->query(sprintf($qry, $this->id, $tag));
|
$profile->query(sprintf($qry, $this->id, $profile->escape($tag)));
|
||||||
|
|
||||||
return $profile;
|
return $profile;
|
||||||
}
|
}
|
||||||
|
@ -216,6 +216,10 @@ class oEmbedHelper
|
|||||||
{
|
{
|
||||||
$params['url'] = $url;
|
$params['url'] = $url;
|
||||||
$params['format'] = 'json';
|
$params['format'] = 'json';
|
||||||
|
$key=common_config('oembed','apikey');
|
||||||
|
if(isset($key)) {
|
||||||
|
$params['key'] = common_config('oembed','apikey');
|
||||||
|
}
|
||||||
$data = self::json($api, $params);
|
$data = self::json($api, $params);
|
||||||
return self::normalize($data);
|
return self::normalize($data);
|
||||||
}
|
}
|
||||||
|
@ -148,6 +148,9 @@ class BookmarkPlugin extends MicroAppPlugin
|
|||||||
|
|
||||||
switch ($cls)
|
switch ($cls)
|
||||||
{
|
{
|
||||||
|
case 'BookmarksAction':
|
||||||
|
case 'BookmarksrssAction':
|
||||||
|
case 'ApiTimelineBookmarksAction':
|
||||||
case 'ShowbookmarkAction':
|
case 'ShowbookmarkAction':
|
||||||
case 'NewbookmarkAction':
|
case 'NewbookmarkAction':
|
||||||
case 'BookmarkpopupAction':
|
case 'BookmarkpopupAction':
|
||||||
@ -180,6 +183,26 @@ class BookmarkPlugin extends MicroAppPlugin
|
|||||||
*/
|
*/
|
||||||
function onRouterInitialized($m)
|
function onRouterInitialized($m)
|
||||||
{
|
{
|
||||||
|
if (common_config('singleuser', 'enabled')) {
|
||||||
|
$nickname = User::singleUserNickname();
|
||||||
|
$m->connect('bookmarks',
|
||||||
|
array('action' => 'bookmarks', 'nickname' => $nickname));
|
||||||
|
$m->connect('bookmarks/rss',
|
||||||
|
array('action' => 'bookmarksrss', 'nickname' => $nickname));
|
||||||
|
} else {
|
||||||
|
$m->connect(':nickname/bookmarks',
|
||||||
|
array('action' => 'bookmarks'),
|
||||||
|
array('nickname' => Nickname::DISPLAY_FMT));
|
||||||
|
$m->connect(':nickname/bookmarks/rss',
|
||||||
|
array('action' => 'bookmarksrss'),
|
||||||
|
array('nickname' => Nickname::DISPLAY_FMT));
|
||||||
|
}
|
||||||
|
|
||||||
|
$m->connect('api/bookmarks/:id.:format',
|
||||||
|
array('action' => 'ApiTimelineBookmarks',
|
||||||
|
'id' => Nickname::INPUT_FMT,
|
||||||
|
'format' => '(xml|json|rss|atom|as)'));
|
||||||
|
|
||||||
$m->connect('main/bookmark/new',
|
$m->connect('main/bookmark/new',
|
||||||
array('action' => 'newbookmark'),
|
array('action' => 'newbookmark'),
|
||||||
array('id' => '[0-9]+'));
|
array('id' => '[0-9]+'));
|
||||||
@ -230,11 +253,13 @@ class BookmarkPlugin extends MicroAppPlugin
|
|||||||
{
|
{
|
||||||
$versions[] = array('name' => 'Bookmark',
|
$versions[] = array('name' => 'Bookmark',
|
||||||
'version' => self::VERSION,
|
'version' => self::VERSION,
|
||||||
'author' => 'Evan Prodromou',
|
'author' => 'Evan Prodromou, Stephane Berube, Jean Baptiste Favre',
|
||||||
'homepage' => 'http://status.net/wiki/Plugin:Bookmark',
|
'homepage' => 'http://status.net/wiki/Plugin:Bookmark',
|
||||||
'description' =>
|
'description' =>
|
||||||
// TRANS: Plugin description.
|
// TRANS: Plugin description.
|
||||||
_m('Simple extension for supporting bookmarks.'));
|
_m('Simple extension for supporting bookmarks. ') .
|
||||||
|
'BookmarkList feature has been developped by Stephane Berube. ' .
|
||||||
|
'Integration has been done by Jean Baptiste Favre.');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,6 +340,41 @@ class BookmarkPlugin extends MicroAppPlugin
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify the default menu to link to our custom action
|
||||||
|
*
|
||||||
|
* Using event handlers, it's possible to modify the default UI for pages
|
||||||
|
* almost without limit. In this method, we add a menu item to the default
|
||||||
|
* primary menu for the interface to link to our action.
|
||||||
|
*
|
||||||
|
* The Action class provides a rich set of events to hook, as well as output
|
||||||
|
* methods.
|
||||||
|
*
|
||||||
|
* @param Action $action The current action handler. Use this to
|
||||||
|
* do any output.
|
||||||
|
*
|
||||||
|
* @return boolean hook value; true means continue processing, false means stop.
|
||||||
|
*
|
||||||
|
* @see Action
|
||||||
|
*/
|
||||||
|
function onEndPersonalGroupNav($action)
|
||||||
|
{
|
||||||
|
$this->user = common_current_user();
|
||||||
|
|
||||||
|
if (!$this->user) {
|
||||||
|
// TRANS: Client error displayed when trying to display bookmarks for a non-existing user.
|
||||||
|
$this->clientError(_('No such user.'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$action->menuItem(common_local_url('bookmarks', array('nickname' => $this->user->nickname)),
|
||||||
|
// TRANS: Menu item in sample plugin.
|
||||||
|
_m('Bookmarks'),
|
||||||
|
// TRANS: Menu item title in sample plugin.
|
||||||
|
_m('A list of your bookmarks'), false, 'nav_timeline_bookmarks');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a remote bookmark (from Salmon or PuSH)
|
* Save a remote bookmark (from Salmon or PuSH)
|
||||||
*
|
*
|
||||||
|
268
plugins/Bookmark/apitimelinebookmarks.php
Normal file
268
plugins/Bookmark/apitimelinebookmarks.php
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Show a user's favorite 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 Zach Copley <zach@status.net>
|
||||||
|
* @copyright 2009-2010 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';
|
||||||
|
require_once 'bookmarksnoticestream.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the 20 most recent favorite notices for the authenticating user or user
|
||||||
|
* specified by the ID parameter in the requested format.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Craig Andrews <candrews@integralblue.com>
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @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 ApiTimelineBookmarksAction extends ApiBareAuthAction
|
||||||
|
{
|
||||||
|
var $notices = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take arguments for running
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST args
|
||||||
|
*
|
||||||
|
* @return boolean success flag
|
||||||
|
*/
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
$this->user = $this->getTargetUser($this->arg('id'));
|
||||||
|
|
||||||
|
if (empty($this->user)) {
|
||||||
|
// TRANS: Client error displayed when requesting most recent favourite notices by a user for a non-existing user.
|
||||||
|
$this->clientError(_('No such user.'), 404, $this->format);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->notices = $this->getNotices();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the request
|
||||||
|
*
|
||||||
|
* Just show the notices
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST data (unused)
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
$this->showTimeline();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the timeline of notices
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function showTimeline()
|
||||||
|
{
|
||||||
|
$profile = $this->user->getProfile();
|
||||||
|
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||||
|
|
||||||
|
$sitename = common_config('site', 'name');
|
||||||
|
$title = sprintf(
|
||||||
|
// TRANS: Title for timeline of most recent favourite notices by a user.
|
||||||
|
// TRANS: %1$s is the StatusNet sitename, %2$s is a user nickname.
|
||||||
|
_('%1$s / Bookmarks from %2$s'),
|
||||||
|
$sitename,
|
||||||
|
$this->user->nickname
|
||||||
|
);
|
||||||
|
|
||||||
|
$taguribase = TagURI::base();
|
||||||
|
$id = "tag:$taguribase:Bookmarks:" . $this->user->id;
|
||||||
|
|
||||||
|
$subtitle = sprintf(
|
||||||
|
// TRANS: Subtitle for timeline of most recent favourite notices by a user.
|
||||||
|
// TRANS: %1$s is the StatusNet sitename, %2$s is a user's full name,
|
||||||
|
// TRANS: %3$s is a user nickname.
|
||||||
|
_('%1$s updates bookmarked by %2$s / %3$s.'),
|
||||||
|
$sitename,
|
||||||
|
$profile->getBestName(),
|
||||||
|
$this->user->nickname
|
||||||
|
);
|
||||||
|
$logo = !empty($avatar)
|
||||||
|
? $avatar->displayUrl()
|
||||||
|
: Avatar::defaultImage(AVATAR_PROFILE_SIZE);
|
||||||
|
|
||||||
|
$link = common_local_url(
|
||||||
|
'bookmarks',
|
||||||
|
array('nickname' => $this->user->nickname)
|
||||||
|
);
|
||||||
|
|
||||||
|
$self = $this->getSelfUri();
|
||||||
|
|
||||||
|
switch($this->format) {
|
||||||
|
case 'xml':
|
||||||
|
$this->showXmlTimeline($this->notices);
|
||||||
|
break;
|
||||||
|
case 'rss':
|
||||||
|
$this->showRssTimeline(
|
||||||
|
$this->notices,
|
||||||
|
$title,
|
||||||
|
$link,
|
||||||
|
$subtitle,
|
||||||
|
null,
|
||||||
|
$logo,
|
||||||
|
$self
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'atom':
|
||||||
|
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||||
|
|
||||||
|
$atom = new AtomNoticeFeed($this->auth_user);
|
||||||
|
|
||||||
|
$atom->setId($id);
|
||||||
|
$atom->setTitle($title);
|
||||||
|
$atom->setSubtitle($subtitle);
|
||||||
|
$atom->setLogo($logo);
|
||||||
|
$atom->setUpdated('now');
|
||||||
|
|
||||||
|
$atom->addLink($link);
|
||||||
|
$atom->setSelfLink($self);
|
||||||
|
|
||||||
|
$atom->addEntryFromNotices($this->notices);
|
||||||
|
|
||||||
|
$this->raw($atom->getString());
|
||||||
|
break;
|
||||||
|
case 'json':
|
||||||
|
$this->showJsonTimeline($this->notices);
|
||||||
|
break;
|
||||||
|
case 'as':
|
||||||
|
header('Content-Type: ' . ActivityStreamJSONDocument::CONTENT_TYPE);
|
||||||
|
$doc = new ActivityStreamJSONDocument($this->auth_user);
|
||||||
|
$doc->setTitle($title);
|
||||||
|
$doc->addLink($link,'alternate', 'text/html');
|
||||||
|
$doc->addItemsFromNotices($this->notices);
|
||||||
|
$this->raw($doc->asString());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// TRANS: Client error displayed when coming across a non-supported API method.
|
||||||
|
$this->clientError(_('API method not found.'), $code = 404);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get notices
|
||||||
|
*
|
||||||
|
* @return array notices
|
||||||
|
*/
|
||||||
|
function getNotices()
|
||||||
|
{
|
||||||
|
$notices = array();
|
||||||
|
|
||||||
|
common_debug("since id = " . $this->since_id . " max id = " . $this->max_id);
|
||||||
|
|
||||||
|
$notice = new BookmarksNoticeStream($this->user->id, true);
|
||||||
|
$notice = $notice->getNotices(
|
||||||
|
($this->page-1) * $this->count,
|
||||||
|
$this->count,
|
||||||
|
$this->since_id,
|
||||||
|
$this->max_id
|
||||||
|
);
|
||||||
|
|
||||||
|
while ($notice->fetch()) {
|
||||||
|
$notices[] = clone($notice);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $notices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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, user 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_user_cache_hash($this->auth_user),
|
||||||
|
common_language(),
|
||||||
|
$this->user->id,
|
||||||
|
strtotime($this->notices[0]->created),
|
||||||
|
strtotime($this->notices[$last]->created))
|
||||||
|
)
|
||||||
|
. '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
233
plugins/Bookmark/bookmarks.php
Normal file
233
plugins/Bookmark/bookmarks.php
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Give a warm greeting to our friendly user
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* @category Bookmark
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||||
|
* @link http://status.net/
|
||||||
|
*
|
||||||
|
* StatusNet - the distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2009, StatusNet, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once 'bookmarksnoticestream.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List currently logged-in user's bookmakrs
|
||||||
|
*
|
||||||
|
* @category Bookmark
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Stephane Berube <chimo@chromic.org>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||||
|
* @link https://github.com/chimo/BookmarkList
|
||||||
|
*/
|
||||||
|
class BookmarksAction extends Action
|
||||||
|
{
|
||||||
|
var $user = null;
|
||||||
|
var $gc = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take arguments for running
|
||||||
|
*
|
||||||
|
* This method is called first, and it lets the action class get
|
||||||
|
* all its arguments and validate them. It's also the time
|
||||||
|
* to fetch any relevant data from the database.
|
||||||
|
*
|
||||||
|
* Action classes should run parent::prepare($args) as the first
|
||||||
|
* line of this method to make sure the default argument-processing
|
||||||
|
* happens.
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST args
|
||||||
|
*
|
||||||
|
* @return boolean success flag
|
||||||
|
*/
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
if (common_config('singleuser', 'enabled')) {
|
||||||
|
$nickname = User::singleUserNickname();
|
||||||
|
} else {
|
||||||
|
// PHP 5.4
|
||||||
|
// $nickname = $this->returnToArgs()[1]['nickname'];
|
||||||
|
|
||||||
|
// PHP < 5.4
|
||||||
|
$nickname = $this->returnToArgs();
|
||||||
|
$nickname = $nickname[1]['nickname'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->user = User::staticGet('nickname', $nickname);
|
||||||
|
|
||||||
|
if (!$this->user) {
|
||||||
|
// TRANS: Client error displayed when trying to display bookmarks for a non-existing user.
|
||||||
|
$this->clientError(_('No such user.'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||||
|
|
||||||
|
$stream = new BookmarksNoticeStream($this->user->id, true);
|
||||||
|
$this->notices = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE,
|
||||||
|
NOTICES_PER_PAGE + 1);
|
||||||
|
|
||||||
|
if($this->page > 1 && $this->notices->N == 0) {
|
||||||
|
throw new ClientException(_('No such page.'), 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle request
|
||||||
|
*
|
||||||
|
* This is the main method for handling a request. Note that
|
||||||
|
* most preparation should be done in the prepare() method;
|
||||||
|
* by the time handle() is called the action should be
|
||||||
|
* more or less ready to go.
|
||||||
|
*
|
||||||
|
* @param array $args $_REQUEST args; handled in prepare()
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
parent::handle($args);
|
||||||
|
$this->showPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Title of this page
|
||||||
|
*
|
||||||
|
* Override this method to show a custom title.
|
||||||
|
*
|
||||||
|
* @return string Title of the page
|
||||||
|
*/
|
||||||
|
function title()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (empty($this->user)) {
|
||||||
|
// TRANS: Page title for sample plugin.
|
||||||
|
return _m('Log in');
|
||||||
|
} else {
|
||||||
|
// TRANS: Page title for sample plugin. %s is a user nickname.
|
||||||
|
return sprintf(_m('%s\'s bookmarks'), $this->user->nickname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feeds for the <head> section
|
||||||
|
*
|
||||||
|
* @return array Feed objects to show
|
||||||
|
*/
|
||||||
|
function getFeeds()
|
||||||
|
{
|
||||||
|
return array(new Feed(Feed::JSON,
|
||||||
|
common_local_url('ApiTimelineBookmarks',
|
||||||
|
array(
|
||||||
|
'id' => $this->user->nickname,
|
||||||
|
'format' => 'as')),
|
||||||
|
// TRANS: Feed link text. %s is a username.
|
||||||
|
sprintf(_('Feed for favorites of %s (Activity Streams JSON)'),
|
||||||
|
$this->user->nickname)),
|
||||||
|
new Feed(Feed::RSS1,
|
||||||
|
common_local_url('bookmarksrss',
|
||||||
|
array('nickname' => $this->user->nickname)),
|
||||||
|
// TRANS: Feed link text. %s is a username.
|
||||||
|
sprintf(_('Feed for favorites of %s (RSS 1.0)'),
|
||||||
|
$this->user->nickname)),
|
||||||
|
new Feed(Feed::RSS2,
|
||||||
|
common_local_url('ApiTimelineBookmarks',
|
||||||
|
array(
|
||||||
|
'id' => $this->user->nickname,
|
||||||
|
'format' => 'rss')),
|
||||||
|
// TRANS: Feed link text. %s is a username.
|
||||||
|
sprintf(_('Feed for favorites of %s (RSS 2.0)'),
|
||||||
|
$this->user->nickname)),
|
||||||
|
new Feed(Feed::ATOM,
|
||||||
|
common_local_url('ApiTimelineBookmarks',
|
||||||
|
array(
|
||||||
|
'id' => $this->user->nickname,
|
||||||
|
'format' => 'atom')),
|
||||||
|
// TRANS: Feed link text. %s is a username.
|
||||||
|
sprintf(_('Feed for favorites of %s (Atom)'),
|
||||||
|
$this->user->nickname)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show content in the content area
|
||||||
|
*
|
||||||
|
* The default StatusNet page has a lot of decorations: menus,
|
||||||
|
* logos, tabs, all that jazz. This method is used to show
|
||||||
|
* content in the content area of the page; it's the main
|
||||||
|
* thing you want to overload.
|
||||||
|
*
|
||||||
|
* This method also demonstrates use of a plural localized string.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function showContent()
|
||||||
|
{
|
||||||
|
|
||||||
|
$nl = new NoticeList($this->notices, $this);
|
||||||
|
|
||||||
|
$cnt = $nl->show();
|
||||||
|
|
||||||
|
if ($cnt == 0) {
|
||||||
|
$this->showEmptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->pagination($this->page > 1,
|
||||||
|
$cnt > NOTICES_PER_PAGE,
|
||||||
|
$this->page, 'bookmarks',
|
||||||
|
array('nickname' => $this->user->nickname));
|
||||||
|
}
|
||||||
|
|
||||||
|
function showEmptyList() {
|
||||||
|
$message = sprintf(_('This is %1$s\'s bookmark stream, but %1$s hasn\'t bookmarked anything yet.'), $this->user->nickname) . ' ';
|
||||||
|
|
||||||
|
$this->elementStart('div', 'guide');
|
||||||
|
$this->raw(common_markup_to_html($message));
|
||||||
|
$this->elementEnd('div');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* Some actions only read from the database; others read and write.
|
||||||
|
* The simple database load-balancer built into StatusNet will
|
||||||
|
* direct read-only actions to database mirrors (if they are configured),
|
||||||
|
* and read-write actions to the master database.
|
||||||
|
*
|
||||||
|
* This defaults to false to avoid data integrity issues, but you
|
||||||
|
* should make sure to overload it for performance gains.
|
||||||
|
*
|
||||||
|
* @param array $args other arguments, if RO/RW status depends on them.
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
80
plugins/Bookmark/bookmarksnoticestream.php
Normal file
80
plugins/Bookmark/bookmarksnoticestream.php
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class RawBookmarksNoticeStream extends NoticeStream
|
||||||
|
{
|
||||||
|
protected $user_id;
|
||||||
|
protected $own;
|
||||||
|
|
||||||
|
function __construct($user_id, $own)
|
||||||
|
{
|
||||||
|
$this->user_id = $user_id;
|
||||||
|
$this->own = $own;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNoticeIds($offset, $limit, $since_id, $max_id)
|
||||||
|
{
|
||||||
|
$notice = new Notice();
|
||||||
|
$qry = null;
|
||||||
|
|
||||||
|
$qry = 'SELECT notice.* FROM notice ';
|
||||||
|
$qry .= 'INNER JOIN bookmark ON bookmark.uri = notice.uri ';
|
||||||
|
$qry .= 'WHERE bookmark.profile_id = ' . $this->user_id . ' ';
|
||||||
|
$qry .= 'AND notice.is_local != ' . Notice::GATEWAY . ' ';
|
||||||
|
|
||||||
|
if ($since_id != 0) {
|
||||||
|
$qry .= 'AND notice.id > ' . $since_id . ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($max_id != 0) {
|
||||||
|
$qry .= 'AND notice.id <= ' . $max_id . ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: we sort by bookmark time, not by notice time!
|
||||||
|
$qry .= 'ORDER BY created DESC ';
|
||||||
|
if (!is_null($offset)) {
|
||||||
|
$qry .= "LIMIT $limit OFFSET $offset";
|
||||||
|
}
|
||||||
|
|
||||||
|
$notice->query($qry);
|
||||||
|
$ids = array();
|
||||||
|
while ($notice->fetch()) {
|
||||||
|
$ids[] = $notice->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$notice->free();
|
||||||
|
unset($notice);
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notice stream for bookmarks
|
||||||
|
*
|
||||||
|
* @category Stream
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Stephane Berube <chimo@chromic.org>
|
||||||
|
* @copyright 2011 StatusNet, Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
class BookmarksNoticeStream extends ScopingNoticeStream
|
||||||
|
{
|
||||||
|
function __construct($user_id, $own, $profile = -1)
|
||||||
|
{
|
||||||
|
$stream = new RawBookmarksNoticeStream($user_id, $own);
|
||||||
|
|
||||||
|
if ($own) {
|
||||||
|
$key = 'bookmark:ids_by_user_own:'.$user_id;
|
||||||
|
} else {
|
||||||
|
$key = 'bookmark:ids_by_user:'.$user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_int($profile) && $profile == -1) {
|
||||||
|
$profile = Profile::current();
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::__construct(new CachingNoticeStream($stream, $key),
|
||||||
|
$profile);
|
||||||
|
}
|
||||||
|
}
|
137
plugins/Bookmark/bookmarksrss.php
Normal file
137
plugins/Bookmark/bookmarksrss.php
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* RSS feed for user bookmarks action class.
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* @category Action
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @author Robin Millette <millette@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||||
|
* @link http://status.net/
|
||||||
|
*
|
||||||
|
* StatusNet - the distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2008, 2009, StatusNet, Inc.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET') && !defined('LACONICA')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/lib/rssaction.php';
|
||||||
|
require_once 'bookmarksnoticestream.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSS feed for user bookmarks action class.
|
||||||
|
*
|
||||||
|
* Formatting of RSS handled by Rss10Action
|
||||||
|
*
|
||||||
|
* @category Action
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @author Robin Millette <millette@status.net>
|
||||||
|
* @author Zach Copley <zach@status.net>
|
||||||
|
* @author Stephane Berube <chimo@chromic.org> (modified 'favoritesrss.php' to show bookmarks instead)
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
class BookmarksrssAction extends Rss10Action
|
||||||
|
{
|
||||||
|
/** The user whose bookmarks to display */
|
||||||
|
|
||||||
|
var $user = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the user to display by supplied nickname
|
||||||
|
*
|
||||||
|
* @param array $args Arguments from $_REQUEST
|
||||||
|
*
|
||||||
|
* @return boolean success
|
||||||
|
*/
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
$nickname = $this->trimmed('nickname');
|
||||||
|
$this->user = User::staticGet('nickname', $nickname);
|
||||||
|
|
||||||
|
if (!$this->user) {
|
||||||
|
// TRANS: Client error displayed when trying to get the RSS feed with bookmarks of a user that does not exist.
|
||||||
|
$this->clientError(_('No such user.'));
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$this->notices = $this->getNotices($this->limit);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get notices
|
||||||
|
*
|
||||||
|
* @param integer $limit max number of notices to return
|
||||||
|
*
|
||||||
|
* @return array notices
|
||||||
|
*/
|
||||||
|
function getNotices($limit=0)
|
||||||
|
{
|
||||||
|
$user = $this->user;
|
||||||
|
|
||||||
|
$notice = new BookmarksNoticeStream($this->user->id, true);
|
||||||
|
$notice = $notice->getNotices(0, NOTICES_PER_PAGE);
|
||||||
|
|
||||||
|
$notices = array();
|
||||||
|
while ($notice->fetch()) {
|
||||||
|
$notices[] = clone($notice);
|
||||||
|
}
|
||||||
|
return $notices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get channel.
|
||||||
|
*
|
||||||
|
* @return array associative array on channel information
|
||||||
|
*/
|
||||||
|
function getChannel()
|
||||||
|
{
|
||||||
|
$user = $this->user;
|
||||||
|
$c = array('url' => common_local_url('bookmarksrss',
|
||||||
|
array('nickname' =>
|
||||||
|
$user->nickname)),
|
||||||
|
// TRANS: Title of RSS feed with bookmarks of a user.
|
||||||
|
// TRANS: %s is a user's nickname.
|
||||||
|
'title' => sprintf(_("%s's bookmarks"), $user->nickname),
|
||||||
|
'link' => common_local_url('bookmarks',
|
||||||
|
array('nickname' =>
|
||||||
|
$user->nickname)),
|
||||||
|
// TRANS: Desciption of RSS feed with bookmarks of a user.
|
||||||
|
// TRANS: %1$s is a user's nickname, %2$s is the name of the StatusNet site.
|
||||||
|
'description' => sprintf(_('Bookmarks posted by %1$s on %2$s!'),
|
||||||
|
$user->nickname, common_config('site', 'name')));
|
||||||
|
return $c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get image.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function getImage()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -31,6 +31,15 @@ class RemoteProfileAction extends ShowstreamAction
|
|||||||
$this->tag = $this->trimmed('tag');
|
$this->tag = $this->trimmed('tag');
|
||||||
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||||
common_set_returnto($this->selfUrl());
|
common_set_returnto($this->selfUrl());
|
||||||
|
|
||||||
|
$p = Profile::current();
|
||||||
|
if (empty($this->tag)) {
|
||||||
|
$stream = new ProfileNoticeStream($this->profile, $p);
|
||||||
|
} else {
|
||||||
|
$stream = new TaggedProfileNoticeStream($this->profile, $this->tag, $p);
|
||||||
|
}
|
||||||
|
$this->notice = $stream->getNotices(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +80,25 @@ class RemoteProfileAction extends ShowstreamAction
|
|||||||
// TRANS: Message on blocked remote profile page.
|
// TRANS: Message on blocked remote profile page.
|
||||||
$markdown = _m('Site moderators have silenced this profile, which prevents delivery of new messages to any users on this site.');
|
$markdown = _m('Site moderators have silenced this profile, which prevents delivery of new messages to any users on this site.');
|
||||||
$this->raw(common_markup_to_html($markdown));
|
$this->raw(common_markup_to_html($markdown));
|
||||||
|
}else{
|
||||||
|
|
||||||
|
$pnl = null;
|
||||||
|
if (Event::handle('ShowStreamNoticeList', array($this->notice, $this, &$pnl))) {
|
||||||
|
$pnl = new ProfileNoticeList($this->notice, $this);
|
||||||
|
}
|
||||||
|
$cnt = $pnl->show();
|
||||||
|
if (0 == $cnt) {
|
||||||
|
$this->showEmptyListMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
$args = array('id' => $this->profile->id);
|
||||||
|
if (!empty($this->tag))
|
||||||
|
{
|
||||||
|
$args['tag'] = $this->tag;
|
||||||
|
}
|
||||||
|
$this->pagination($this->page>1, $cnt>NOTICES_PER_PAGE, $this->page,
|
||||||
|
'remoteprofile', $args);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,14 +118,12 @@ class RemoteProfileAction extends ShowstreamAction
|
|||||||
|
|
||||||
function showLocalNav()
|
function showLocalNav()
|
||||||
{
|
{
|
||||||
$nav = new PublicGroupNav($this);
|
// skip
|
||||||
$nav->show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showSections()
|
function showSections()
|
||||||
{
|
{
|
||||||
ProfileAction::showSections();
|
// skip
|
||||||
// skip tag cloud
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showStatistics()
|
function showStatistics()
|
||||||
|
@ -204,6 +204,7 @@ class TwitterBridgePlugin extends Plugin
|
|||||||
return false;
|
return false;
|
||||||
case 'TwitterOAuthClient':
|
case 'TwitterOAuthClient':
|
||||||
case 'TwitterQueueHandler':
|
case 'TwitterQueueHandler':
|
||||||
|
case 'TweetInQueueHandler':
|
||||||
case 'TwitterImport':
|
case 'TwitterImport':
|
||||||
case 'JsonStreamReader':
|
case 'JsonStreamReader':
|
||||||
case 'TwitterStreamReader':
|
case 'TwitterStreamReader':
|
||||||
|
@ -136,7 +136,8 @@ class TwitterStatusFetcher extends ParallelizingDaemon
|
|||||||
// a new connection if there isn't one already
|
// a new connection if there isn't one already
|
||||||
$conn = &$flink->getDatabaseConnection();
|
$conn = &$flink->getDatabaseConnection();
|
||||||
|
|
||||||
$this->getTimeline($flink);
|
$this->getTimeline($flink, 'home_timeline');
|
||||||
|
$this->getTimeline($flink, 'mentions_timeline');
|
||||||
|
|
||||||
$flink->last_friendsync = common_sql_now();
|
$flink->last_friendsync = common_sql_now();
|
||||||
$flink->update();
|
$flink->update();
|
||||||
@ -149,65 +150,68 @@ class TwitterStatusFetcher extends ParallelizingDaemon
|
|||||||
unset($_DB_DATAOBJECT['CONNECTIONS']);
|
unset($_DB_DATAOBJECT['CONNECTIONS']);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTimeline($flink)
|
function getTimeline($flink, $timelineUri = 'home_timeline')
|
||||||
{
|
{
|
||||||
if (empty($flink)) {
|
if (empty($flink)) {
|
||||||
common_log(LOG_WARNING, $this->name() .
|
common_log(LOG_ERR, $this->name() .
|
||||||
" - Can't retrieve Foreign_link for foreign ID $fid");
|
" - Can't retrieve Foreign_link for foreign ID $fid");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
common_debug($this->name() . ' - Trying to get timeline for Twitter user ' .
|
common_log(LOG_DEBUG, $this->name() . ' - Trying to get ' . $timelineUri .
|
||||||
$flink->foreign_id);
|
' timeline for Twitter user ' . $flink->foreign_id);
|
||||||
|
|
||||||
$client = null;
|
$client = null;
|
||||||
|
|
||||||
if (TwitterOAuthClient::isPackedToken($flink->credentials)) {
|
if (TwitterOAuthClient::isPackedToken($flink->credentials)) {
|
||||||
$token = TwitterOAuthClient::unpackToken($flink->credentials);
|
$token = TwitterOAuthClient::unpackToken($flink->credentials);
|
||||||
$client = new TwitterOAuthClient($token->key, $token->secret);
|
$client = new TwitterOAuthClient($token->key, $token->secret);
|
||||||
common_debug($this->name() . ' - Grabbing friends timeline with OAuth.');
|
common_log(LOG_DEBUG, $this->name() . ' - Grabbing ' . $timelineUri . ' timeline with OAuth.');
|
||||||
} else {
|
} else {
|
||||||
common_debug("Skipping friends timeline for $flink->foreign_id since not OAuth.");
|
common_log(LOG_ERR, "Skipping " . $timelineUri . " timeline for " .
|
||||||
|
$flink->foreign_id . " since not OAuth.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$timeline = null;
|
$timeline = null;
|
||||||
|
|
||||||
$lastId = Twitter_synch_status::getLastId($flink->foreign_id, 'home_timeline');
|
$lastId = Twitter_synch_status::getLastId($flink->foreign_id, $timelineUri);
|
||||||
|
|
||||||
common_debug("Got lastId value '{$lastId}' for foreign id '{$flink->foreign_id}' and timeline 'home_timeline'");
|
common_log(LOG_DEBUG, "Got lastId value '" . $lastId . "' for foreign id '" .
|
||||||
|
$flink->foreign_id . "' and timeline '" . $timelineUri. "'");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$timeline = $client->statusesHomeTimeline($lastId);
|
$timeline = $client->statusesTimeline($lastId, $timelineUri);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
common_log(LOG_WARNING, $this->name() .
|
common_log(LOG_ERR, $this->name() .
|
||||||
' - Twitter client unable to get friends timeline for user ' .
|
' - Unable to get ' . $timelineUri . ' timeline for user ' . $flink->user_id .
|
||||||
$flink->user_id . ' - code: ' .
|
' - code: ' . $e->getCode() . 'msg: ' . $e->getMessage());
|
||||||
$e->getCode() . 'msg: ' . $e->getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($timeline)) {
|
if (empty($timeline)) {
|
||||||
common_log(LOG_WARNING, $this->name() . " - Empty timeline.");
|
common_log(LOG_WARNING, $this->name() . " - Empty '" . $timelineUri . "' timeline.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
common_debug(LOG_INFO, $this->name() . ' - Retrieved ' . sizeof($timeline) . ' statuses from Twitter.');
|
common_log(LOG_INFO, $this->name() .
|
||||||
|
' - Retrieved ' . sizeof($timeline) . ' statuses from ' . $timelineUri . ' timeline' .
|
||||||
$importer = new TwitterImport();
|
' - for user ' . $flink->user_id);
|
||||||
|
|
||||||
// Reverse to preserve order
|
|
||||||
|
|
||||||
foreach (array_reverse($timeline) as $status) {
|
|
||||||
$notice = $importer->importStatus($status);
|
|
||||||
|
|
||||||
if (!empty($notice)) {
|
|
||||||
Inbox::insertNotice($flink->user_id, $notice->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($timeline)) {
|
if (!empty($timeline)) {
|
||||||
|
$qm = QueueManager::get();
|
||||||
|
|
||||||
|
// Reverse to preserve order
|
||||||
|
foreach (array_reverse($timeline) as $status) {
|
||||||
|
$data = array(
|
||||||
|
'status' => $status,
|
||||||
|
'for_user' => $flink->foreign_id,
|
||||||
|
);
|
||||||
|
$qm->enqueue($data, 'tweetin');
|
||||||
|
}
|
||||||
|
|
||||||
$lastId = twitter_id($timeline[0]);
|
$lastId = twitter_id($timeline[0]);
|
||||||
Twitter_synch_status::setLastId($flink->foreign_id, 'home_timeline', $lastId);
|
Twitter_synch_status::setLastId($flink->foreign_id, $timelineUri, $lastId);
|
||||||
common_debug("Set lastId value '$lastId' for foreign id '{$flink->foreign_id}' and timeline 'home_timeline'");
|
common_debug("Set lastId value '$lastId' for foreign id '{$flink->foreign_id}' and timeline '" .
|
||||||
|
$timelineUri . "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Okay, record the time we synced with Twitter for posterity
|
// Okay, record the time we synced with Twitter for posterity
|
||||||
@ -233,5 +237,5 @@ if (have_option('d') || have_option('debug')) {
|
|||||||
$debug = true;
|
$debug = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$fetcher = new TwitterStatusFetcher($id, 60, 2, $debug);
|
$fetcher = new TwitterStatusFetcher($id, POLL_INTERVAL, MAXCHILDREN, $debug);
|
||||||
$fetcher->runOnce();
|
$fetcher->runOnce();
|
||||||
|
@ -51,10 +51,14 @@ class TweetInQueueHandler extends QueueHandler
|
|||||||
$importer = new TwitterImport();
|
$importer = new TwitterImport();
|
||||||
$notice = $importer->importStatus($status);
|
$notice = $importer->importStatus($status);
|
||||||
if ($notice) {
|
if ($notice) {
|
||||||
$flink = Foreign_link::getByForeignID(TWITTER_SERVICE, $receiver);
|
$flink = Foreign_link::getByForeignID($receiver, TWITTER_SERVICE);
|
||||||
if ($flink) {
|
if ($flink) {
|
||||||
|
common_log(LOG_DEBUG, "TweetInQueueHandler - Got flink so add notice ".
|
||||||
|
$notice->id." to inbox ".$flink->user_id);
|
||||||
// @fixme this should go through more regular channels?
|
// @fixme this should go through more regular channels?
|
||||||
Inbox::insertNotice($flink->user_id, $notice->id);
|
Inbox::insertNotice($flink->user_id, $notice->id);
|
||||||
|
}else {
|
||||||
|
common_log(LOG_DEBUG, "TweetInQueueHandler - No flink found for foreign user ".$receiver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,10 +339,7 @@ class TwitterImport
|
|||||||
{
|
{
|
||||||
global $config;
|
global $config;
|
||||||
|
|
||||||
$path_parts = pathinfo($twitter_user->profile_image_url);
|
$newname = 'Twitter_' . $twitter_user->id . '_' . basename($twitter_user->profile_image_url);
|
||||||
|
|
||||||
$newname = 'Twitter_' . $twitter_user->id . '_' .
|
|
||||||
$path_parts['basename'];
|
|
||||||
|
|
||||||
$oldname = $profile->getAvatar(48)->filename;
|
$oldname = $profile->getAvatar(48)->filename;
|
||||||
|
|
||||||
@ -370,15 +367,15 @@ class TwitterImport
|
|||||||
|
|
||||||
$path_parts = pathinfo($twitter_user->profile_image_url);
|
$path_parts = pathinfo($twitter_user->profile_image_url);
|
||||||
|
|
||||||
$img_root = substr($path_parts['basename'], 0, -11);
|
$ext = (isset($path_parts['extension']) ? '.'.$path_parts['extension'] : ''); // some lack extension
|
||||||
$ext = $path_parts['extension'];
|
$img_root = basename($path_parts['basename'], '_normal'.$ext); // cut off extension
|
||||||
$mediatype = $this->getMediatype($ext);
|
$mediatype = $this->getMediatype(substr($ext, 1));
|
||||||
|
|
||||||
foreach (array('mini', 'normal', 'bigger') as $size) {
|
foreach (array('mini', 'normal', 'bigger') as $size) {
|
||||||
$url = $path_parts['dirname'] . '/' .
|
$url = $path_parts['dirname'] . '/' .
|
||||||
$img_root . '_' . $size . ".$ext";
|
$img_root . '_' . $size . $ext;
|
||||||
$filename = 'Twitter_' . $twitter_user->id . '_' .
|
$filename = 'Twitter_' . $twitter_user->id . '_' .
|
||||||
$img_root . "_$size.$ext";
|
$img_root . '_' . $size . $ext;
|
||||||
|
|
||||||
$this->updateAvatar($profile->id, $size, $mediatype, $filename);
|
$this->updateAvatar($profile->id, $size, $mediatype, $filename);
|
||||||
$this->fetchAvatar($url, $filename);
|
$this->fetchAvatar($url, $filename);
|
||||||
@ -401,8 +398,9 @@ class TwitterImport
|
|||||||
$mediatype = null;
|
$mediatype = null;
|
||||||
|
|
||||||
switch (strtolower($ext)) {
|
switch (strtolower($ext)) {
|
||||||
|
case 'jpeg':
|
||||||
case 'jpg':
|
case 'jpg':
|
||||||
$mediatype = 'image/jpg';
|
$mediatype = 'image/jpeg';
|
||||||
break;
|
break;
|
||||||
case 'gif':
|
case 'gif':
|
||||||
$mediatype = 'image/gif';
|
$mediatype = 'image/gif';
|
||||||
@ -419,16 +417,15 @@ class TwitterImport
|
|||||||
global $config;
|
global $config;
|
||||||
|
|
||||||
$path_parts = pathinfo($user->profile_image_url);
|
$path_parts = pathinfo($user->profile_image_url);
|
||||||
$ext = $path_parts['extension'];
|
$ext = (isset($path_parts['extension']) ? '.'.$path_parts['extension'] : '');
|
||||||
$end = strlen('_normal' . $ext);
|
$img_root = basename($path_parts['basename'], '_normal'.$ext);
|
||||||
$img_root = substr($path_parts['basename'], 0, -($end+1));
|
$mediatype = $this->getMediatype(substr($ext, 1));
|
||||||
$mediatype = $this->getMediatype($ext);
|
|
||||||
|
|
||||||
foreach (array('mini', 'normal', 'bigger') as $size) {
|
foreach (array('mini', 'normal', 'bigger') as $size) {
|
||||||
$url = $path_parts['dirname'] . '/' .
|
$url = $path_parts['dirname'] . '/' .
|
||||||
$img_root . '_' . $size . ".$ext";
|
$img_root . '_' . $size . $ext;
|
||||||
$filename = 'Twitter_' . $user->id . '_' .
|
$filename = 'Twitter_' . $user->id . '_' .
|
||||||
$img_root . "_$size.$ext";
|
$img_root . '_' . $size . $ext;
|
||||||
|
|
||||||
if ($this->fetchAvatar($url, $filename)) {
|
if ($this->fetchAvatar($url, $filename)) {
|
||||||
$this->newAvatar($id, $size, $mediatype, $filename);
|
$this->newAvatar($id, $size, $mediatype, $filename);
|
||||||
|
@ -157,7 +157,7 @@ class TwitterOAuthClient extends OAuthClient
|
|||||||
*/
|
*/
|
||||||
function verifyCredentials()
|
function verifyCredentials()
|
||||||
{
|
{
|
||||||
$url = 'https://api.twitter.com/1/account/verify_credentials.json';
|
$url = 'https://api.twitter.com/1.1/account/verify_credentials.json';
|
||||||
$response = $this->oAuthGet($url);
|
$response = $this->oAuthGet($url);
|
||||||
$twitter_user = json_decode($response);
|
$twitter_user = json_decode($response);
|
||||||
return $twitter_user;
|
return $twitter_user;
|
||||||
@ -175,7 +175,7 @@ class TwitterOAuthClient extends OAuthClient
|
|||||||
*/
|
*/
|
||||||
function statusesUpdate($status, $params=array())
|
function statusesUpdate($status, $params=array())
|
||||||
{
|
{
|
||||||
$url = 'https://api.twitter.com/1/statuses/update.json';
|
$url = 'https://api.twitter.com/1.1/statuses/update.json';
|
||||||
if (is_numeric($params)) {
|
if (is_numeric($params)) {
|
||||||
$params = array('in_reply_to_status_id' => intval($params));
|
$params = array('in_reply_to_status_id' => intval($params));
|
||||||
}
|
}
|
||||||
@ -190,19 +190,21 @@ class TwitterOAuthClient extends OAuthClient
|
|||||||
/**
|
/**
|
||||||
* Calls Twitter's /statuses/home_timeline API method
|
* Calls Twitter's /statuses/home_timeline API method
|
||||||
*
|
*
|
||||||
* @param int $since_id show statuses after this id
|
* @param int $since_id show statuses after this id
|
||||||
* @param int $max_id show statuses before this id
|
* @param string $timelineUri timeline to poll statuses from
|
||||||
* @param int $cnt number of statuses to show
|
* @param int $max_id show statuses before this id
|
||||||
* @param int $page page number
|
* @param int $cnt number of statuses to show
|
||||||
|
* @param int $page page number
|
||||||
*
|
*
|
||||||
* @return mixed an array of statuses
|
* @return mixed an array of statuses
|
||||||
*/
|
*/
|
||||||
function statusesHomeTimeline($since_id = null, $max_id = null,
|
function statusesTimeline($since_id = null, $timelineUri = 'home_timeline',
|
||||||
$cnt = null, $page = null)
|
$max_id = null, $cnt = 200, $page = null)
|
||||||
{
|
{
|
||||||
$url = 'https://api.twitter.com/1/statuses/home_timeline.json';
|
$url = 'https://api.twitter.com/1.1/statuses/'.$timelineUri.'.json';
|
||||||
|
|
||||||
$params = array('include_entities' => 'true');
|
$params = array('include_entities' => 'true',
|
||||||
|
'include_rts' => 'true');
|
||||||
|
|
||||||
if (!empty($since_id)) {
|
if (!empty($since_id)) {
|
||||||
$params['since_id'] = $since_id;
|
$params['since_id'] = $since_id;
|
||||||
@ -235,7 +237,7 @@ class TwitterOAuthClient extends OAuthClient
|
|||||||
function statusesFriends($id = null, $user_id = null, $screen_name = null,
|
function statusesFriends($id = null, $user_id = null, $screen_name = null,
|
||||||
$page = null)
|
$page = null)
|
||||||
{
|
{
|
||||||
$url = "https://api.twitter.com/1/statuses/friends.json";
|
$url = "https://api.twitter.com/1.1/friends/list.json";
|
||||||
|
|
||||||
$params = array();
|
$params = array();
|
||||||
|
|
||||||
@ -273,7 +275,7 @@ class TwitterOAuthClient extends OAuthClient
|
|||||||
function friendsIds($id = null, $user_id = null, $screen_name = null,
|
function friendsIds($id = null, $user_id = null, $screen_name = null,
|
||||||
$page = null)
|
$page = null)
|
||||||
{
|
{
|
||||||
$url = "https://api.twitter.com/1/friends/ids.json";
|
$url = "https://api.twitter.com/1.1/friends/ids.json";
|
||||||
|
|
||||||
$params = array();
|
$params = array();
|
||||||
|
|
||||||
@ -308,7 +310,7 @@ class TwitterOAuthClient extends OAuthClient
|
|||||||
|
|
||||||
function statusesRetweet($id)
|
function statusesRetweet($id)
|
||||||
{
|
{
|
||||||
$url = "http://api.twitter.com/1/statuses/retweet/$id.json";
|
$url = "http://api.twitter.com/1.1/statuses/retweet/$id.json";
|
||||||
$response = $this->oAuthPost($url);
|
$response = $this->oAuthPost($url);
|
||||||
$status = json_decode($response);
|
$status = json_decode($response);
|
||||||
return $status;
|
return $status;
|
||||||
@ -324,8 +326,10 @@ class TwitterOAuthClient extends OAuthClient
|
|||||||
|
|
||||||
function favoritesCreate($id)
|
function favoritesCreate($id)
|
||||||
{
|
{
|
||||||
$url = "http://api.twitter.com/1/favorites/create/$id.json";
|
$url = "http://api.twitter.com/1.1/favorites/create.json";
|
||||||
$response = $this->oAuthPost($url);
|
$params=array();
|
||||||
|
$params['id'] = $id;
|
||||||
|
$response = $this->oAuthPost($url, $params);
|
||||||
$status = json_decode($response);
|
$status = json_decode($response);
|
||||||
return $status;
|
return $status;
|
||||||
}
|
}
|
||||||
@ -340,8 +344,10 @@ class TwitterOAuthClient extends OAuthClient
|
|||||||
|
|
||||||
function favoritesDestroy($id)
|
function favoritesDestroy($id)
|
||||||
{
|
{
|
||||||
$url = "http://api.twitter.com/1/favorites/destroy/$id.json";
|
$url = "http://api.twitter.com/1.1/favorites/destroy.json";
|
||||||
$response = $this->oAuthPost($url);
|
$params=array();
|
||||||
|
$params['id'] = $id;
|
||||||
|
$response = $this->oAuthPost($url,$params);
|
||||||
$status = json_decode($response);
|
$status = json_decode($response);
|
||||||
return $status;
|
return $status;
|
||||||
}
|
}
|
||||||
@ -356,7 +362,7 @@ class TwitterOAuthClient extends OAuthClient
|
|||||||
|
|
||||||
function statusesDestroy($id)
|
function statusesDestroy($id)
|
||||||
{
|
{
|
||||||
$url = "http://api.twitter.com/1/statuses/destroy/$id.json";
|
$url = "http://api.twitter.com/1.1/statuses/destroy/$id.json";
|
||||||
$response = $this->oAuthPost($url);
|
$response = $this->oAuthPost($url);
|
||||||
$status = json_decode($response);
|
$status = json_decode($response);
|
||||||
return $status;
|
return $status;
|
||||||
|
@ -433,6 +433,31 @@ class XmppPlugin extends ImPlugin
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add XMPP plugin daemon to the list of daemon to start
|
||||||
|
*
|
||||||
|
* @param array $daemons the list of daemons to run
|
||||||
|
*
|
||||||
|
* @return boolean hook return
|
||||||
|
*/
|
||||||
|
function onGetValidDaemons($daemons)
|
||||||
|
{
|
||||||
|
if( isset($this->server) &&
|
||||||
|
isset($this->port) &&
|
||||||
|
isset($this->user) &&
|
||||||
|
isset($this->password) ){
|
||||||
|
|
||||||
|
array_push(
|
||||||
|
$daemons,
|
||||||
|
INSTALLDIR
|
||||||
|
. '/scripts/imdaemon.php'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function onPluginVersion(&$versions)
|
function onPluginVersion(&$versions)
|
||||||
{
|
{
|
||||||
$versions[] = array('name' => 'XMPP',
|
$versions[] = array('name' => 'XMPP',
|
||||||
|
@ -39,8 +39,6 @@ $daemons = array();
|
|||||||
|
|
||||||
$daemons[] = INSTALLDIR.'/scripts/queuedaemon.php';
|
$daemons[] = INSTALLDIR.'/scripts/queuedaemon.php';
|
||||||
|
|
||||||
$daemons[] = INSTALLDIR.'/scripts/imdaemon.php';
|
|
||||||
|
|
||||||
if (Event::handle('GetValidDaemons', array(&$daemons))) {
|
if (Event::handle('GetValidDaemons', array(&$daemons))) {
|
||||||
foreach ($daemons as $daemon) {
|
foreach ($daemons as $daemon) {
|
||||||
print $daemon . ' ';
|
print $daemon . ' ';
|
||||||
|
@ -688,18 +688,22 @@ font-style:italic;
|
|||||||
display:none;
|
display:none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#remoteprofile .notice .entry-title, #remoteprofile .notice div.entry-content,
|
||||||
#showstream .notice .entry-title, #showstream .notice div.entry-content {
|
#showstream .notice .entry-title, #showstream .notice div.entry-content {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#remoteprofile .notice .entry-title,
|
||||||
#showstream .notice .entry-title {
|
#showstream .notice .entry-title {
|
||||||
min-height: 1px;
|
min-height: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#remoteprofile #content .notice .author,
|
||||||
#showstream #content .notice .author {
|
#showstream #content .notice .author {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#remoteprofile .notice,
|
||||||
#showstream .notice {
|
#showstream .notice {
|
||||||
min-height: 1em;
|
min-height: 1em;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user