Merge branch '1.0.x' of gitorious.org:statusnet/mainline into 1.0.x
This commit is contained in:
commit
1b7d1d9a4a
@ -4,7 +4,7 @@
|
|||||||
* Copyright (C) 2011, StatusNet, Inc.
|
* Copyright (C) 2011, StatusNet, Inc.
|
||||||
*
|
*
|
||||||
* Show a stream of notices in a particular conversation
|
* Show a stream of notices in a particular conversation
|
||||||
*
|
*
|
||||||
* PHP version 5
|
* PHP version 5
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -46,12 +46,11 @@ require_once INSTALLDIR . '/lib/apiauth.php';
|
|||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||||
* @link http://status.net/
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ApiconversationAction extends ApiAuthAction
|
class ApiconversationAction extends ApiAuthAction
|
||||||
{
|
{
|
||||||
protected $conversation = null;
|
protected $conversation = null;
|
||||||
protected $notices = null;
|
protected $notices = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For initializing members of the class.
|
* For initializing members of the class.
|
||||||
*
|
*
|
||||||
@ -59,35 +58,36 @@ class ApiconversationAction extends ApiAuthAction
|
|||||||
*
|
*
|
||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function prepare($argarray)
|
function prepare($argarray)
|
||||||
{
|
{
|
||||||
parent::prepare($argarray);
|
parent::prepare($argarray);
|
||||||
|
|
||||||
$convId = $this->trimmed('id');
|
$convId = $this->trimmed('id');
|
||||||
|
|
||||||
if (empty($convId)) {
|
if (empty($convId)) {
|
||||||
throw new ClientException(_m('no conversation id'));
|
// TRANS: Client exception thrown when no conversation ID is given.
|
||||||
|
throw new ClientException(_('No conversation ID.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->conversation = Conversation::staticGet('id', $convId);
|
$this->conversation = Conversation::staticGet('id', $convId);
|
||||||
|
|
||||||
if (empty($this->conversation)) {
|
if (empty($this->conversation)) {
|
||||||
throw new ClientException(sprintf(_m('No conversation with id %d'), $convId),
|
// TRANS: Client exception thrown when referring to a non-existing conversation ID (%d).
|
||||||
404);
|
throw new ClientException(sprintf(_('No conversation with ID %d.'), $convId),
|
||||||
|
404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$profile = Profile::current();
|
$profile = Profile::current();
|
||||||
|
|
||||||
$stream = new ConversationNoticeStream($convId, $profile);
|
$stream = new ConversationNoticeStream($convId, $profile);
|
||||||
|
|
||||||
$notice = $stream->getNotices(($this->page-1) * $this->count,
|
$notice = $stream->getNotices(($this->page-1) * $this->count,
|
||||||
$this->count,
|
$this->count,
|
||||||
$this->since_id,
|
$this->since_id,
|
||||||
$this->max_id);
|
$this->max_id);
|
||||||
|
|
||||||
$this->notices = $notice->fetchAll();
|
$this->notices = $notice->fetchAll();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,17 +98,16 @@ class ApiconversationAction extends ApiAuthAction
|
|||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function handle($argarray=null)
|
function handle($argarray=null)
|
||||||
{
|
{
|
||||||
$sitename = common_config('site', 'name');
|
$sitename = common_config('site', 'name');
|
||||||
// TRANS: Timeline title for user and friends. %s is a user nickname.
|
// TRANS: Timeline title for user and friends. %s is a user nickname.
|
||||||
$title = _("Conversation");
|
$title = _m('TITLE', 'Conversation');
|
||||||
$id = common_local_url('apiconversation', array('id' => $this->conversation->id, 'format' => $this->format));
|
$id = common_local_url('apiconversation', array('id' => $this->conversation->id, 'format' => $this->format));
|
||||||
$link = common_local_url('conversation', array('id' => $this->conversation->id));
|
$link = common_local_url('conversation', array('id' => $this->conversation->id));
|
||||||
|
|
||||||
$self = $id;
|
$self = $id;
|
||||||
|
|
||||||
switch($this->format) {
|
switch($this->format) {
|
||||||
case 'xml':
|
case 'xml':
|
||||||
$this->showXmlTimeline($this->notices);
|
$this->showXmlTimeline($this->notices);
|
||||||
@ -168,7 +167,6 @@ class ApiconversationAction extends ApiAuthAction
|
|||||||
*
|
*
|
||||||
* @return boolean is read only action?
|
* @return boolean is read only action?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function isReadOnly($args)
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
|
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
|
||||||
@ -202,7 +200,6 @@ class ApiconversationAction extends ApiAuthAction
|
|||||||
*
|
*
|
||||||
* @return string etag http header
|
* @return string etag http header
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function etag()
|
function etag()
|
||||||
{
|
{
|
||||||
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
if (!empty($this->notices) && (count($this->notices) > 0)) {
|
||||||
@ -220,7 +217,7 @@ class ApiconversationAction extends ApiAuthAction
|
|||||||
)
|
)
|
||||||
. '"';
|
. '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +226,6 @@ class ApiconversationAction extends ApiAuthAction
|
|||||||
*
|
*
|
||||||
* @return boolean true if delete, else false
|
* @return boolean true if delete, else false
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function requiresAuth()
|
function requiresAuth()
|
||||||
{
|
{
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
|
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
|
||||||
@ -239,4 +235,4 @@ class ApiconversationAction extends ApiAuthAction
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,156 +63,158 @@ class Memcached_DataObject extends Safe_DataObject
|
|||||||
}
|
}
|
||||||
return $i;
|
return $i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get multiple items from the database by key
|
* Get multiple items from the database by key
|
||||||
*
|
*
|
||||||
* @param string $cls Class to fetch
|
* @param string $cls Class to fetch
|
||||||
* @param string $keyCol name of column for key
|
* @param string $keyCol name of column for key
|
||||||
* @param array $keyVals key values to fetch
|
* @param array $keyVals key values to fetch
|
||||||
* @param boolean $skipNulls return only non-null results?
|
* @param boolean $skipNulls return only non-null results?
|
||||||
*
|
*
|
||||||
* @return array Array of objects, in order
|
* @return array Array of objects, in order
|
||||||
*/
|
*/
|
||||||
function multiGet($cls, $keyCol, $keyVals, $skipNulls=true)
|
function multiGet($cls, $keyCol, $keyVals, $skipNulls=true)
|
||||||
{
|
{
|
||||||
$result = self::pivotGet($cls, $keyCol, $keyVals);
|
$result = self::pivotGet($cls, $keyCol, $keyVals);
|
||||||
|
|
||||||
$values = array_values($result);
|
$values = array_values($result);
|
||||||
|
|
||||||
if ($skipNulls) {
|
if ($skipNulls) {
|
||||||
$tmp = array();
|
$tmp = array();
|
||||||
foreach ($values as $value) {
|
foreach ($values as $value) {
|
||||||
if (!empty($value)) {
|
if (!empty($value)) {
|
||||||
$tmp[] = $value;
|
$tmp[] = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$values = $tmp;
|
$values = $tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ArrayWrapper($values);
|
return new ArrayWrapper($values);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get multiple items from the database by key
|
* Get multiple items from the database by key
|
||||||
*
|
*
|
||||||
* @param string $cls Class to fetch
|
* @param string $cls Class to fetch
|
||||||
* @param string $keyCol name of column for key
|
* @param string $keyCol name of column for key
|
||||||
* @param array $keyVals key values to fetch
|
* @param array $keyVals key values to fetch
|
||||||
* @param boolean $otherCols Other columns to hold fixed
|
* @param boolean $otherCols Other columns to hold fixed
|
||||||
*
|
*
|
||||||
* @return array Array mapping $keyVals to objects, or null if not found
|
* @return array Array mapping $keyVals to objects, or null if not found
|
||||||
*/
|
*/
|
||||||
static function pivotGet($cls, $keyCol, $keyVals, $otherCols = array())
|
static function pivotGet($cls, $keyCol, $keyVals, $otherCols = array())
|
||||||
{
|
{
|
||||||
$result = array_fill_keys($keyVals, null);
|
$result = array_fill_keys($keyVals, null);
|
||||||
|
|
||||||
$toFetch = array();
|
$toFetch = array();
|
||||||
|
|
||||||
foreach ($keyVals as $keyVal) {
|
foreach ($keyVals as $keyVal) {
|
||||||
|
|
||||||
$kv = array_merge($otherCols, array($keyCol => $keyVal));
|
$kv = array_merge($otherCols, array($keyCol => $keyVal));
|
||||||
|
|
||||||
$i = self::multicache($cls, $kv);
|
$i = self::multicache($cls, $kv);
|
||||||
|
|
||||||
if ($i !== false) {
|
if ($i !== false) {
|
||||||
$result[$keyVal] = $i;
|
$result[$keyVal] = $i;
|
||||||
} else if (!empty($keyVal)) {
|
} else if (!empty($keyVal)) {
|
||||||
$toFetch[] = $keyVal;
|
$toFetch[] = $keyVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($toFetch) > 0) {
|
if (count($toFetch) > 0) {
|
||||||
$i = DB_DataObject::factory($cls);
|
$i = DB_DataObject::factory($cls);
|
||||||
if (empty($i)) {
|
if (empty($i)) {
|
||||||
throw new Exception(_('Cannot instantiate class ' . $cls));
|
// TRANS: Exception thrown when a class (%s) could not be instantiated.
|
||||||
|
throw new Exception(sprintf(_('Cannot instantiate class %s.'),$cls));
|
||||||
}
|
}
|
||||||
foreach ($otherCols as $otherKeyCol => $otherKeyVal) {
|
foreach ($otherCols as $otherKeyCol => $otherKeyVal) {
|
||||||
$i->$otherKeyCol = $otherKeyVal;
|
$i->$otherKeyCol = $otherKeyVal;
|
||||||
}
|
}
|
||||||
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
|
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
|
||||||
if ($i->find()) {
|
if ($i->find()) {
|
||||||
while ($i->fetch()) {
|
while ($i->fetch()) {
|
||||||
$copy = clone($i);
|
$copy = clone($i);
|
||||||
$copy->encache();
|
$copy->encache();
|
||||||
$result[$i->$keyCol] = $copy;
|
$result[$i->$keyCol] = $copy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save state of DB misses
|
// Save state of DB misses
|
||||||
|
|
||||||
foreach ($toFetch as $keyVal) {
|
foreach ($toFetch as $keyVal) {
|
||||||
if (empty($result[$keyVal])) {
|
if (empty($result[$keyVal])) {
|
||||||
$kv = array_merge($otherCols, array($keyCol => $keyVal));
|
$kv = array_merge($otherCols, array($keyCol => $keyVal));
|
||||||
// save the fact that no such row exists
|
// save the fact that no such row exists
|
||||||
$c = self::memcache();
|
$c = self::memcache();
|
||||||
if (!empty($c)) {
|
if (!empty($c)) {
|
||||||
$ck = self::multicacheKey($cls, $kv);
|
$ck = self::multicacheKey($cls, $kv);
|
||||||
$c->set($ck, null);
|
$c->set($ck, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function listGet($cls, $keyCol, $keyVals)
|
function listGet($cls, $keyCol, $keyVals)
|
||||||
{
|
{
|
||||||
$result = array_fill_keys($keyVals, array());
|
$result = array_fill_keys($keyVals, array());
|
||||||
|
|
||||||
$toFetch = array();
|
$toFetch = array();
|
||||||
|
|
||||||
foreach ($keyVals as $keyVal) {
|
foreach ($keyVals as $keyVal) {
|
||||||
$l = self::cacheGet(sprintf("%s:list:%s:%s", $cls, $keyCol, $keyVal));
|
$l = self::cacheGet(sprintf("%s:list:%s:%s", $cls, $keyCol, $keyVal));
|
||||||
if ($l !== false) {
|
if ($l !== false) {
|
||||||
$result[$keyVal] = $l;
|
$result[$keyVal] = $l;
|
||||||
} else {
|
} else {
|
||||||
$toFetch[] = $keyVal;
|
$toFetch[] = $keyVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($toFetch) > 0) {
|
if (count($toFetch) > 0) {
|
||||||
$i = DB_DataObject::factory($cls);
|
$i = DB_DataObject::factory($cls);
|
||||||
if (empty($i)) {
|
if (empty($i)) {
|
||||||
throw new Exception(_('Cannot instantiate class ' . $cls));
|
// TRANS: Exception thrown when a class (%s) could not be instantiated.
|
||||||
}
|
throw new Exception(sprintf(_('Cannot instantiate class %s.'),$cls));
|
||||||
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
|
}
|
||||||
if ($i->find()) {
|
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
|
||||||
while ($i->fetch()) {
|
if ($i->find()) {
|
||||||
$copy = clone($i);
|
while ($i->fetch()) {
|
||||||
$copy->encache();
|
$copy = clone($i);
|
||||||
$result[$i->$keyCol][] = $copy;
|
$copy->encache();
|
||||||
}
|
$result[$i->$keyCol][] = $copy;
|
||||||
}
|
}
|
||||||
foreach ($toFetch as $keyVal)
|
}
|
||||||
{
|
foreach ($toFetch as $keyVal)
|
||||||
self::cacheSet(sprintf("%s:list:%s:%s", $cls, $keyCol, $keyVal),
|
{
|
||||||
$result[$keyVal]);
|
self::cacheSet(sprintf("%s:list:%s:%s", $cls, $keyCol, $keyVal),
|
||||||
}
|
$result[$keyVal]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function columnType($columnName)
|
||||||
|
{
|
||||||
|
$keys = $this->table();
|
||||||
|
if (!array_key_exists($columnName, $keys)) {
|
||||||
|
throw new Exception('Unknown key column ' . $columnName . ' in ' . join(',', array_keys($keys)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$def = $keys[$columnName];
|
||||||
|
|
||||||
|
if ($def & DB_DATAOBJECT_INT) {
|
||||||
|
return 'integer';
|
||||||
|
} else {
|
||||||
|
return 'string';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function columnType($columnName)
|
|
||||||
{
|
|
||||||
$keys = $this->table();
|
|
||||||
if (!array_key_exists($columnName, $keys)) {
|
|
||||||
throw new Exception('Unknown key column ' . $columnName . ' in ' . join(',', array_keys($keys)));
|
|
||||||
}
|
|
||||||
|
|
||||||
$def = $keys[$columnName];
|
|
||||||
|
|
||||||
if ($def & DB_DATAOBJECT_INT) {
|
|
||||||
return 'integer';
|
|
||||||
} else {
|
|
||||||
return 'string';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fixme Should this return false on lookup fail to match staticGet?
|
* @todo FIXME: Should this return false on lookup fail to match staticGet?
|
||||||
*/
|
*/
|
||||||
function pkeyGet($cls, $kv)
|
function pkeyGet($cls, $kv)
|
||||||
{
|
{
|
||||||
@ -225,13 +227,13 @@ class Memcached_DataObject extends Safe_DataObject
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
foreach ($kv as $k => $v) {
|
foreach ($kv as $k => $v) {
|
||||||
if (is_null($v)) {
|
if (is_null($v)) {
|
||||||
// XXX: possible SQL injection...? Don't
|
// XXX: possible SQL injection...? Don't
|
||||||
// pass keys from the browser, eh.
|
// pass keys from the browser, eh.
|
||||||
$i->whereAdd("$k is null");
|
$i->whereAdd("$k is null");
|
||||||
} else {
|
} else {
|
||||||
$i->$k = $v;
|
$i->$k = $v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($i->find(true)) {
|
if ($i->find(true)) {
|
||||||
$i->encache();
|
$i->encache();
|
||||||
@ -562,7 +564,7 @@ class Memcached_DataObject extends Safe_DataObject
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (in_array($func, $ignoreStatic)) {
|
if (in_array($func, $ignoreStatic)) {
|
||||||
continue; // @fixme this shouldn't be needed?
|
continue; // @todo FIXME: This shouldn't be needed?
|
||||||
}
|
}
|
||||||
$here = get_class($frame['object']) . '->' . $func;
|
$here = get_class($frame['object']) . '->' . $func;
|
||||||
break;
|
break;
|
||||||
@ -705,7 +707,7 @@ class Memcached_DataObject extends Safe_DataObject
|
|||||||
|
|
||||||
if (!$dsn) {
|
if (!$dsn) {
|
||||||
// TRANS: Exception thrown when database name or Data Source Name could not be found.
|
// TRANS: Exception thrown when database name or Data Source Name could not be found.
|
||||||
throw new Exception(_("No database name or DSN found anywhere."));
|
throw new Exception(_('No database name or DSN found anywhere.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $dsn;
|
return $dsn;
|
||||||
|
@ -84,8 +84,10 @@ class GroupsNav extends MoreMenu
|
|||||||
function seeAllItem() {
|
function seeAllItem() {
|
||||||
return array('usergroups',
|
return array('usergroups',
|
||||||
array('nickname' => $this->user->nickname),
|
array('nickname' => $this->user->nickname),
|
||||||
|
// TRANS: Link description for seeing all groups.
|
||||||
_('See all'),
|
_('See all'),
|
||||||
_('See all groups you belong to'));
|
// TRANS: Link title for seeing all groups.
|
||||||
|
_('See all groups you belong to.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -58,11 +58,11 @@ class ListsNav extends MoreMenu
|
|||||||
{
|
{
|
||||||
return 'lists';
|
return 'lists';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getItems()
|
function getItems()
|
||||||
{
|
{
|
||||||
$items = array();
|
$items = array();
|
||||||
|
|
||||||
while ($this->lists->fetch()) {
|
while ($this->lists->fetch()) {
|
||||||
$mode = $this->lists->private ? 'private' : 'public';
|
$mode = $this->lists->private ? 'private' : 'public';
|
||||||
$items[] = array('showprofiletag',
|
$items[] = array('showprofiletag',
|
||||||
@ -84,7 +84,9 @@ class ListsNav extends MoreMenu
|
|||||||
{
|
{
|
||||||
return array('peopletagsbyuser',
|
return array('peopletagsbyuser',
|
||||||
array('nickname' => $this->profile->nickname),
|
array('nickname' => $this->profile->nickname),
|
||||||
|
// TRANS: Link description for seeing all lists.
|
||||||
_('See all'),
|
_('See all'),
|
||||||
_('See all lists you have created'));
|
// TRANS: Link title for seeing all lists.
|
||||||
|
_('See all lists you have created.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Copyright (C) 2011, StatusNet, Inc.
|
* Copyright (C) 2011, StatusNet, Inc.
|
||||||
*
|
*
|
||||||
* A menu with a More... button to show more elements
|
* A menu with a More... button to show more elements
|
||||||
*
|
*
|
||||||
* PHP version 5
|
* PHP version 5
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -44,12 +44,11 @@ if (!defined('STATUSNET')) {
|
|||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||||
* @link http://status.net/
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class MoreMenu extends Menu
|
class MoreMenu extends Menu
|
||||||
{
|
{
|
||||||
const SOFT_MAX = 5;
|
const SOFT_MAX = 5;
|
||||||
const HARD_MAX = 15;
|
const HARD_MAX = 15;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a menu with a limited number of elements
|
* Show a menu with a limited number of elements
|
||||||
*
|
*
|
||||||
@ -57,7 +56,6 @@ class MoreMenu extends Menu
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function show()
|
function show()
|
||||||
{
|
{
|
||||||
$items = $this->getItems();
|
$items = $this->getItems();
|
||||||
@ -72,7 +70,6 @@ class MoreMenu extends Menu
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Event::handle('StartNav', array($this, &$tag, &$items))) {
|
if (Event::handle('StartNav', array($this, &$tag, &$items))) {
|
||||||
|
|
||||||
$this->out->elementStart('ul', $attrs);
|
$this->out->elementStart('ul', $attrs);
|
||||||
|
|
||||||
$total = count($items);
|
$total = count($items);
|
||||||
@ -89,10 +86,10 @@ class MoreMenu extends Menu
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($total > self::SOFT_MAX + 1) {
|
if ($total > self::SOFT_MAX + 1) {
|
||||||
|
|
||||||
$this->out->elementStart('li', array('class' => 'more_link'));
|
$this->out->elementStart('li', array('class' => 'more_link'));
|
||||||
$this->out->element('a', array('href' => '#',
|
$this->out->element('a', array('href' => '#',
|
||||||
'onclick' => 'SN.U.showMoreMenuItems("'.$menuID.'"); return false;'),
|
'onclick' => 'SN.U.showMoreMenuItems("'.$menuID.'"); return false;'),
|
||||||
|
// TRANS: Link description to show more items in a list.
|
||||||
_('More ▼'));
|
_('More ▼'));
|
||||||
$this->out->elementEnd('li');
|
$this->out->elementEnd('li');
|
||||||
|
|
||||||
@ -112,7 +109,7 @@ class MoreMenu extends Menu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->out->elementEnd('ul');
|
$this->out->elementEnd('ul');
|
||||||
|
|
||||||
Event::handle('EndNav', array($this, $tag, $items));
|
Event::handle('EndNav', array($this, $tag, $items));
|
||||||
@ -123,5 +120,4 @@ class MoreMenu extends Menu
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -120,13 +120,15 @@ class BlogPlugin extends MicroAppPlugin
|
|||||||
'author' => 'Evan Prodromou',
|
'author' => 'Evan Prodromou',
|
||||||
'homepage' => 'http://status.net/wiki/Plugin:Blog',
|
'homepage' => 'http://status.net/wiki/Plugin:Blog',
|
||||||
'rawdescription' =>
|
'rawdescription' =>
|
||||||
|
// TRANS: Plugin description.
|
||||||
_m('Let users write and share long-form texts.'));
|
_m('Let users write and share long-form texts.'));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function appTitle()
|
function appTitle()
|
||||||
{
|
{
|
||||||
return _m('Blog');
|
// TRANS: Blog application title.
|
||||||
|
return _m('TITLE','Blog');
|
||||||
}
|
}
|
||||||
|
|
||||||
function tag()
|
function tag()
|
||||||
@ -149,7 +151,7 @@ class BlogPlugin extends MicroAppPlugin
|
|||||||
$entryObj = $activity->objects[0];
|
$entryObj = $activity->objects[0];
|
||||||
|
|
||||||
if ($entryObj->type != Blog_entry::TYPE) {
|
if ($entryObj->type != Blog_entry::TYPE) {
|
||||||
// TRANS: Exception thrown when blog plugin comes across a non-event type object.
|
// TRANS: Exception thrown when blog plugin comes across a non-blog entry type object.
|
||||||
throw new ClientException(_m('Wrong type for object.'));
|
throw new ClientException(_m('Wrong type for object.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +177,8 @@ class BlogPlugin extends MicroAppPlugin
|
|||||||
$entry = Blog_entry::fromNotice($notice);
|
$entry = Blog_entry::fromNotice($notice);
|
||||||
|
|
||||||
if (empty($entry)) {
|
if (empty($entry)) {
|
||||||
throw new ClientException(sprintf(_('No blog entry for notice %s'),
|
// TRANS: Exception thrown when requesting a non-existing blog entry for notice.
|
||||||
|
throw new ClientException(sprintf(_m('No blog entry for notice %s.'),
|
||||||
$notice->id));
|
$notice->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +207,7 @@ class BlogPlugin extends MicroAppPlugin
|
|||||||
if ($notice->object_type == Blog_entry::TYPE) {
|
if ($notice->object_type == Blog_entry::TYPE) {
|
||||||
return new BlogEntryListItem($nli);
|
return new BlogEntryListItem($nli);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,6 @@ if (!defined('STATUSNET')) {
|
|||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||||
* @link http://status.net/
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class BlogEntryForm extends Form
|
class BlogEntryForm extends Form
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -96,13 +95,13 @@ class BlogEntryForm extends Form
|
|||||||
_m('Title of the blog entry.'),
|
_m('Title of the blog entry.'),
|
||||||
'title');
|
'title');
|
||||||
$this->unli();
|
$this->unli();
|
||||||
|
|
||||||
$this->li();
|
$this->li();
|
||||||
$this->out->textarea('blog-entry-content',
|
$this->out->textarea('blog-entry-content',
|
||||||
// TRANS: Field label on event form.
|
// TRANS: Field label on blog entry form.
|
||||||
_m('LABEL','Text'),
|
_m('LABEL','Text'),
|
||||||
null,
|
null,
|
||||||
// TRANS: Field title on event form.
|
// TRANS: Field title on blog entry form.
|
||||||
_m('Text of the blog entry.'),
|
_m('Text of the blog entry.'),
|
||||||
'content');
|
'content');
|
||||||
$this->unli();
|
$this->unli();
|
||||||
@ -124,8 +123,8 @@ class BlogEntryForm extends Form
|
|||||||
*/
|
*/
|
||||||
function formActions()
|
function formActions()
|
||||||
{
|
{
|
||||||
// TRANS: Button text to save an event..
|
|
||||||
$this->out->submit('blog-entry-submit',
|
$this->out->submit('blog-entry-submit',
|
||||||
|
// TRANS: Button text to save a blog entry.
|
||||||
_m('BUTTON', 'Save'),
|
_m('BUTTON', 'Save'),
|
||||||
'submit',
|
'submit',
|
||||||
'submit');
|
'submit');
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Copyright (C) 2011, StatusNet, Inc.
|
* Copyright (C) 2011, StatusNet, Inc.
|
||||||
*
|
*
|
||||||
* Show a blog entry
|
* Show a blog entry
|
||||||
*
|
*
|
||||||
* PHP version 5
|
* PHP version 5
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -44,12 +44,11 @@ if (!defined('STATUSNET')) {
|
|||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||||
* @link http://status.net/
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ShowblogentryAction extends ShownoticeAction
|
class ShowblogentryAction extends ShownoticeAction
|
||||||
{
|
{
|
||||||
protected $id;
|
protected $id;
|
||||||
protected $entry;
|
protected $entry;
|
||||||
|
|
||||||
function getNotice()
|
function getNotice()
|
||||||
{
|
{
|
||||||
$this->id = $this->trimmed('id');
|
$this->id = $this->trimmed('id');
|
||||||
@ -81,6 +80,7 @@ class ShowblogentryAction extends ShownoticeAction
|
|||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
// XXX: check for double-encoding
|
// XXX: check for double-encoding
|
||||||
|
// TRANS: Title for a blog entry without a title.
|
||||||
return (empty($this->entry->title)) ? _m('Untitled') : $this->entry->title;
|
return (empty($this->entry->title)) ? _m('Untitled') : $this->entry->title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,14 +78,14 @@ class NewrsvpAction extends Action
|
|||||||
$eventId = $this->trimmed('event');
|
$eventId = $this->trimmed('event');
|
||||||
|
|
||||||
if (empty($eventId)) {
|
if (empty($eventId)) {
|
||||||
// TRANS: Client exception thrown when requesting a non-exsting event.
|
// TRANS: Client exception thrown when referring to a non-existing event.
|
||||||
throw new ClientException(_m('No such event.'));
|
throw new ClientException(_m('No such event.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->event = Happening::staticGet('id', $eventId);
|
$this->event = Happening::staticGet('id', $eventId);
|
||||||
|
|
||||||
if (empty($this->event)) {
|
if (empty($this->event)) {
|
||||||
// TRANS: Client exception thrown when requesting a non-exsting event.
|
// TRANS: Client exception thrown when referring to a non-existing event.
|
||||||
throw new ClientException(_m('No such event.'));
|
throw new ClientException(_m('No such event.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ if (!defined('STATUSNET')) {
|
|||||||
* Callback handler to populate end time dropdown
|
* Callback handler to populate end time dropdown
|
||||||
*/
|
*/
|
||||||
class TimelistAction extends Action {
|
class TimelistAction extends Action {
|
||||||
|
|
||||||
private $start;
|
private $start;
|
||||||
private $duration;
|
private $duration;
|
||||||
|
|
||||||
@ -63,13 +62,14 @@ class TimelistAction extends Action {
|
|||||||
|
|
||||||
if (!common_logged_in()) {
|
if (!common_logged_in()) {
|
||||||
// TRANS: Error message displayed when trying to perform an action that requires a logged in user.
|
// TRANS: Error message displayed when trying to perform an action that requires a logged in user.
|
||||||
$this->clientError(_('Not logged in.'));
|
$this->clientError(_m('Not logged in.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($this->start)) {
|
if (!empty($this->start)) {
|
||||||
$times = EventTimeList::getTimes($this->start, $this->duration);
|
$times = EventTimeList::getTimes($this->start, $this->duration);
|
||||||
} else {
|
} else {
|
||||||
|
// TRANS: Client error when submitting a form with unexpected information.
|
||||||
$this->clientError(_m('Unexpected form submission.'));
|
$this->clientError(_m('Unexpected form submission.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -78,6 +78,7 @@ class TimelistAction extends Action {
|
|||||||
header('Content-Type: application/json; charset=utf-8');
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
print json_encode($times);
|
print json_encode($times);
|
||||||
} else {
|
} else {
|
||||||
|
// TRANS: Client error displayed when using an action in a non-AJAX way.
|
||||||
$this->clientError(_m('This action is AJAX only.'));
|
$this->clientError(_m('This action is AJAX only.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,16 +228,14 @@ class OMBPlugin extends Plugin
|
|||||||
$omb01 = Remote_profile::staticGet('id', $other_id);
|
$omb01 = Remote_profile::staticGet('id', $other_id);
|
||||||
|
|
||||||
if (!empty($omb01)) {
|
if (!empty($omb01)) {
|
||||||
// TRANS: Client error displayed trying to subscribe to an OMB 0.1 remote profile.
|
|
||||||
throw new ClientException(
|
throw new ClientException(
|
||||||
_m(
|
// TRANS: Client error displayed trying to subscribe to an OMB 0.1 remote profile.
|
||||||
'You cannot subscribe to an OMB 0.1 '
|
_m('You cannot subscribe to an OMB 0.1 '
|
||||||
. 'remote profile with this action.'
|
. 'remote profile with this action.'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -257,10 +255,9 @@ class OMBPlugin extends Plugin
|
|||||||
$omb01 = Remote_profile::staticGet('id', $tagged_profile->id);
|
$omb01 = Remote_profile::staticGet('id', $tagged_profile->id);
|
||||||
|
|
||||||
if (!empty($omb01)) {
|
if (!empty($omb01)) {
|
||||||
// TRANS: Client error displayed when trying to add an OMB 0.1 remote profile to a list.
|
|
||||||
$this->clientError(
|
$this->clientError(
|
||||||
_m(
|
// TRANS: Client error displayed when trying to add an OMB 0.1 remote profile to a list.
|
||||||
'You cannot list an OMB 0.1 '
|
_m('You cannot list an OMB 0.1 '
|
||||||
.'remote profile with this action.')
|
.'remote profile with this action.')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -282,10 +279,9 @@ class OMBPlugin extends Plugin
|
|||||||
$omb01 = Remote_profile::staticGet('id', $ptag->tagged);
|
$omb01 = Remote_profile::staticGet('id', $ptag->tagged);
|
||||||
|
|
||||||
if (!empty($omb01)) {
|
if (!empty($omb01)) {
|
||||||
// TRANS: Client error displayed when trying to (un)list an OMB 0.1 remote profile.
|
|
||||||
$this->clientError(
|
$this->clientError(
|
||||||
_m(
|
// TRANS: Client error displayed when trying to (un)list an OMB 0.1 remote profile.
|
||||||
'You cannot (un)list an OMB 0.1 '
|
_m('You cannot (un)list an OMB 0.1 '
|
||||||
. 'remote profile with this action.')
|
. 'remote profile with this action.')
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
@ -317,8 +313,8 @@ class OMBPlugin extends Plugin
|
|||||||
|
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
common_log_db_error($token, 'DELETE', __FILE__);
|
common_log_db_error($token, 'DELETE', __FILE__);
|
||||||
// TRANS: Exception thrown when the OMB token for a subscription could not deleted on the server.
|
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
|
// TRANS: Exception thrown when the OMB token for a subscription could not deleted on the server.
|
||||||
_m('Could not delete subscription OMB token.')
|
_m('Could not delete subscription OMB token.')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -394,12 +390,10 @@ class OMBPlugin extends Plugin
|
|||||||
'version' => STATUSNET_VERSION,
|
'version' => STATUSNET_VERSION,
|
||||||
'author' => 'Zach Copley',
|
'author' => 'Zach Copley',
|
||||||
'homepage' => 'http://status.net/wiki/Plugin:Sample',
|
'homepage' => 'http://status.net/wiki/Plugin:Sample',
|
||||||
'rawdescription' =>
|
|
||||||
// TRANS: Plugin description.
|
// TRANS: Plugin description.
|
||||||
_m('A sample plugin to show basics of development for new hackers.')
|
'rawdescription' => _m('A sample plugin to show basics of development for new hackers.')
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,4 +28,3 @@ Note: once you have a sizable number of users, sending OMB messages whenever
|
|||||||
someone posts a message can really slow down your site; it may cause posting
|
someone posts a message can really slow down your site; it may cause posting
|
||||||
to timeout. You may wish to enable queuing and handle OMB communication
|
to timeout. You may wish to enable queuing and handle OMB communication
|
||||||
offline. See the "queues and daemons" section of the main StatusNet README.
|
offline. See the "queues and daemons" section of the main StatusNet README.
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ if (!defined('STATUSNET')) {
|
|||||||
* @package OStatusPlugin
|
* @package OStatusPlugin
|
||||||
* @maintainer Brion Vibber <brion@status.net>
|
* @maintainer Brion Vibber <brion@status.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Ostatus_profile extends Managed_DataObject
|
class Ostatus_profile extends Managed_DataObject
|
||||||
{
|
{
|
||||||
public $__table = 'ostatus_profile';
|
public $__table = 'ostatus_profile';
|
||||||
@ -141,7 +140,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
*
|
*
|
||||||
* Assumes that 'activity' namespace has been previously defined.
|
* Assumes that 'activity' namespace has been previously defined.
|
||||||
*
|
*
|
||||||
* @fixme replace with wrappers on asActivityObject when it's got everything.
|
* @todo FIXME: Replace with wrappers on asActivityObject when it's got everything.
|
||||||
*
|
*
|
||||||
* @param string $element one of 'actor', 'subject', 'object', 'target'
|
* @param string $element one of 'actor', 'subject', 'object', 'target'
|
||||||
* @return string
|
* @return string
|
||||||
@ -301,7 +300,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
$actor->getURI(),
|
$actor->getURI(),
|
||||||
common_date_iso8601(time()));
|
common_date_iso8601(time()));
|
||||||
|
|
||||||
// @fixme consolidate all these NS settings somewhere
|
// @todo FIXME: Consolidate all these NS settings somewhere.
|
||||||
$attributes = array('xmlns' => Activity::ATOM,
|
$attributes = array('xmlns' => Activity::ATOM,
|
||||||
'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/',
|
'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/',
|
||||||
'xmlns:thr' => 'http://purl.org/syndication/thread/1.0',
|
'xmlns:thr' => 'http://purl.org/syndication/thread/1.0',
|
||||||
@ -414,7 +413,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
|
|
||||||
if ($feed->localName == 'feed' && $feed->namespaceURI == Activity::ATOM) {
|
if ($feed->localName == 'feed' && $feed->namespaceURI == Activity::ATOM) {
|
||||||
$this->processAtomFeed($feed, $source);
|
$this->processAtomFeed($feed, $source);
|
||||||
} else if ($feed->localName == 'rss') { // @fixme check namespace
|
} else if ($feed->localName == 'rss') { // @todo FIXME: Check namespace.
|
||||||
$this->processRssFeed($feed, $source);
|
$this->processRssFeed($feed, $source);
|
||||||
} else {
|
} else {
|
||||||
// TRANS: Exception.
|
// TRANS: Exception.
|
||||||
@ -466,7 +465,6 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
*
|
*
|
||||||
* @return Notice Notice representing the new (or existing) activity
|
* @return Notice Notice representing the new (or existing) activity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public function processEntry($entry, $feed, $source)
|
public function processEntry($entry, $feed, $source)
|
||||||
{
|
{
|
||||||
$activity = new Activity($entry, $feed);
|
$activity = new Activity($entry, $feed);
|
||||||
@ -509,7 +507,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
Event::handle('EndHandleFeedEntry', array($activity));
|
Event::handle('EndHandleFeedEntry', array($activity));
|
||||||
Event::handle('EndHandleFeedEntryWithProfile', array($activity, $this, $notice));
|
Event::handle('EndHandleFeedEntryWithProfile', array($activity, $this, $notice));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $notice;
|
return $notice;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,13 +523,15 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (count($activity->objects) != 1) {
|
if (count($activity->objects) != 1) {
|
||||||
throw new ClientException(_m("Can only handle share activities with exactly one object."));
|
// TRANS: Client exception thrown when trying to share multiple activities at once.
|
||||||
|
throw new ClientException(_m('Can only handle share activities with exactly one object.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$shared = $activity->objects[0];
|
$shared = $activity->objects[0];
|
||||||
|
|
||||||
if (!($shared instanceof Activity)) {
|
if (!($shared instanceof Activity)) {
|
||||||
throw new ClientException(_m("Can only handle shared activities."));
|
// TRANS: Client exception thrown when trying to share a non-activity object.
|
||||||
|
throw new ClientException(_m('Can only handle shared activities.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$other = Ostatus_profile::ensureActivityObjectProfile($shared->actor);
|
$other = Ostatus_profile::ensureActivityObjectProfile($shared->actor);
|
||||||
@ -539,10 +539,12 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
// Save the item (or check for a dupe)
|
// Save the item (or check for a dupe)
|
||||||
|
|
||||||
$sharedNotice = $other->processActivity($shared, $method);
|
$sharedNotice = $other->processActivity($shared, $method);
|
||||||
|
|
||||||
if (empty($sharedNotice)) {
|
if (empty($sharedNotice)) {
|
||||||
$sharedId = ($shared->id) ? $shared->id : $shared->objects[0]->id;
|
$sharedId = ($shared->id) ? $shared->id : $shared->objects[0]->id;
|
||||||
throw new ClientException(sprintf(_m("Failed to save activity %s."),
|
// TRANS: Client exception thrown when saving an activity share fails.
|
||||||
|
// TRANS: %s is a share ID.
|
||||||
|
throw new ClientException(sprintf(_m('Failed to save activity %s.'),
|
||||||
$sharedId));
|
$sharedId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,7 +580,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
} else if (!empty($activity->title)) {
|
} else if (!empty($activity->title)) {
|
||||||
$sourceContent = $activity->title;
|
$sourceContent = $activity->title;
|
||||||
} else {
|
} else {
|
||||||
// @fixme fetch from $sourceUrl?
|
// @todo FIXME: Fetch from $sourceUrl?
|
||||||
// TRANS: Client exception. %s is a source URI.
|
// TRANS: Client exception. %s is a source URI.
|
||||||
throw new ClientException(sprintf(_m('No content for notice %s.'),$sourceUri));
|
throw new ClientException(sprintf(_m('No content for notice %s.'),$sourceUri));
|
||||||
}
|
}
|
||||||
@ -652,7 +654,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
$options['replies'] = $replies;
|
$options['replies'] = $replies;
|
||||||
|
|
||||||
// Maintain direct reply associations
|
// Maintain direct reply associations
|
||||||
// @fixme what about conversation ID?
|
// @todo FIXME: What about conversation ID?
|
||||||
if (!empty($activity->context->replyToID)) {
|
if (!empty($activity->context->replyToID)) {
|
||||||
$orig = Notice::staticGet('uri',
|
$orig = Notice::staticGet('uri',
|
||||||
$activity->context->replyToID);
|
$activity->context->replyToID);
|
||||||
@ -688,7 +690,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
|
|
||||||
// Atom enclosures -> attachment URLs
|
// Atom enclosures -> attachment URLs
|
||||||
foreach ($activity->enclosures as $href) {
|
foreach ($activity->enclosures as $href) {
|
||||||
// @fixme save these locally or....?
|
// @todo FIXME: Save these locally or....?
|
||||||
$options['urls'][] = $href;
|
$options['urls'][] = $href;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,7 +707,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
* @param Activity $activity
|
* @param Activity $activity
|
||||||
* @param string $method 'push' or 'salmon'
|
* @param string $method 'push' or 'salmon'
|
||||||
* @return mixed saved Notice or false
|
* @return mixed saved Notice or false
|
||||||
* @fixme break up this function, it's getting nasty long
|
* @todo FIXME: Break up this function, it's getting nasty long
|
||||||
*/
|
*/
|
||||||
public function processPost($activity, $method)
|
public function processPost($activity, $method)
|
||||||
{
|
{
|
||||||
@ -750,7 +752,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
} else if (!empty($note->title)) {
|
} else if (!empty($note->title)) {
|
||||||
$sourceContent = $note->title;
|
$sourceContent = $note->title;
|
||||||
} else {
|
} else {
|
||||||
// @fixme fetch from $sourceUrl?
|
// @todo FIXME: Fetch from $sourceUrl?
|
||||||
// TRANS: Client exception. %s is a source URI.
|
// TRANS: Client exception. %s is a source URI.
|
||||||
throw new ClientException(sprintf(_m('No content for notice %s.'),$sourceUri));
|
throw new ClientException(sprintf(_m('No content for notice %s.'),$sourceUri));
|
||||||
}
|
}
|
||||||
@ -822,7 +824,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
$options['replies'] = $replies;
|
$options['replies'] = $replies;
|
||||||
|
|
||||||
// Maintain direct reply associations
|
// Maintain direct reply associations
|
||||||
// @fixme what about conversation ID?
|
// @todo FIXME: What about conversation ID?
|
||||||
if (!empty($activity->context->replyToID)) {
|
if (!empty($activity->context->replyToID)) {
|
||||||
$orig = Notice::staticGet('uri',
|
$orig = Notice::staticGet('uri',
|
||||||
$activity->context->replyToID);
|
$activity->context->replyToID);
|
||||||
@ -858,7 +860,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
|
|
||||||
// Atom enclosures -> attachment URLs
|
// Atom enclosures -> attachment URLs
|
||||||
foreach ($activity->enclosures as $href) {
|
foreach ($activity->enclosures as $href) {
|
||||||
// @fixme save these locally or....?
|
// @todo FIXME: Save these locally or....?
|
||||||
$options['urls'][] = $href;
|
$options['urls'][] = $href;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -907,7 +909,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
// Is the recipient a local user?
|
// Is the recipient a local user?
|
||||||
$user = User::staticGet('uri', $recipient);
|
$user = User::staticGet('uri', $recipient);
|
||||||
if ($user) {
|
if ($user) {
|
||||||
// @fixme sender verification, spam etc?
|
// @todo FIXME: Sender verification, spam etc?
|
||||||
$replies[] = $recipient;
|
$replies[] = $recipient;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -936,7 +938,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
$oprofile = Ostatus_profile::ensureProfileURI($recipient);
|
$oprofile = Ostatus_profile::ensureProfileURI($recipient);
|
||||||
if ($oprofile->isGroup()) {
|
if ($oprofile->isGroup()) {
|
||||||
// Deliver to local members of this remote group.
|
// Deliver to local members of this remote group.
|
||||||
// @fixme sender verification?
|
// @todo FIXME: Sender verification?
|
||||||
$groups[] = $oprofile->group_id;
|
$groups[] = $oprofile->group_id;
|
||||||
} else {
|
} else {
|
||||||
// may be canonicalized or something
|
// may be canonicalized or something
|
||||||
@ -1129,7 +1131,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
*
|
*
|
||||||
* @param DOMElement $feedEl root element of a loaded Atom feed
|
* @param DOMElement $feedEl root element of a loaded Atom feed
|
||||||
* @param array $hints additional discovery information passed from higher levels
|
* @param array $hints additional discovery information passed from higher levels
|
||||||
* @fixme should this be marked public?
|
* @todo FIXME: Should this be marked public?
|
||||||
* @return Ostatus_profile
|
* @return Ostatus_profile
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@ -1155,7 +1157,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
*
|
*
|
||||||
* @param DOMElement $feedEl root element of a loaded RSS feed
|
* @param DOMElement $feedEl root element of a loaded RSS feed
|
||||||
* @param array $hints additional discovery information passed from higher levels
|
* @param array $hints additional discovery information passed from higher levels
|
||||||
* @fixme should this be marked public?
|
* @todo FIXME: Should this be marked public?
|
||||||
* @return Ostatus_profile
|
* @return Ostatus_profile
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@ -1181,7 +1183,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @fixme we should check whether this feed has elements
|
// @todo FIXME: We should check whether this feed has elements
|
||||||
// with different <author> or <dc:creator> elements, and... I dunno.
|
// with different <author> or <dc:creator> elements, and... I dunno.
|
||||||
// Do something about that.
|
// Do something about that.
|
||||||
|
|
||||||
@ -1219,7 +1221,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
$this->uri));
|
$this->uri));
|
||||||
}
|
}
|
||||||
|
|
||||||
// @fixme this should be better encapsulated
|
// @todo FIXME: This should be better encapsulated
|
||||||
// ripped from oauthstore.php (for old OMB client)
|
// ripped from oauthstore.php (for old OMB client)
|
||||||
$temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
|
$temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
|
||||||
try {
|
try {
|
||||||
@ -1233,7 +1235,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
} else {
|
} else {
|
||||||
$id = $this->profile_id;
|
$id = $this->profile_id;
|
||||||
}
|
}
|
||||||
// @fixme should we be using different ids?
|
// @todo FIXME: Should we be using different ids?
|
||||||
$imagefile = new ImageFile($id, $temp_filename);
|
$imagefile = new ImageFile($id, $temp_filename);
|
||||||
$filename = Avatar::filename($id,
|
$filename = Avatar::filename($id,
|
||||||
image_type_to_extension($imagefile->type),
|
image_type_to_extension($imagefile->type),
|
||||||
@ -1244,7 +1246,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
unlink($temp_filename);
|
unlink($temp_filename);
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
// @fixme hardcoded chmod is lame, but seems to be necessary to
|
// @todo FIXME: Hardcoded chmod is lame, but seems to be necessary to
|
||||||
// keep from accidentally saving images from command-line (queues)
|
// keep from accidentally saving images from command-line (queues)
|
||||||
// that can't be read from web server, which causes hard-to-notice
|
// that can't be read from web server, which causes hard-to-notice
|
||||||
// problems later on:
|
// problems later on:
|
||||||
@ -1253,7 +1255,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
chmod(Avatar::path($filename), 0644);
|
chmod(Avatar::path($filename), 0644);
|
||||||
|
|
||||||
$profile = $this->localProfile();
|
$profile = $this->localProfile();
|
||||||
|
|
||||||
if (!empty($profile)) {
|
if (!empty($profile)) {
|
||||||
$profile->setOriginal($filename);
|
$profile->setOriginal($filename);
|
||||||
}
|
}
|
||||||
@ -1426,7 +1428,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fixme validate stuff somewhere
|
* @todo FIXME: Validate stuff somewhere.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1519,7 +1521,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
|
|
||||||
$oprofile->profile_id = $profile->insert();
|
$oprofile->profile_id = $profile->insert();
|
||||||
if (!$oprofile->profile_id) {
|
if (!$oprofile->profile_id) {
|
||||||
// TRANS: Server exception.
|
// TRANS: Server exception.
|
||||||
throw new ServerException(_m('Cannot save local profile.'));
|
throw new ServerException(_m('Cannot save local profile.'));
|
||||||
}
|
}
|
||||||
} else if ($object->type == ActivityObject::GROUP) {
|
} else if ($object->type == ActivityObject::GROUP) {
|
||||||
@ -1652,7 +1654,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @fixme tags/categories
|
// @todo FIXME: tags/categories
|
||||||
// @todo tags from categories
|
// @todo tags from categories
|
||||||
|
|
||||||
if ($profile->id) {
|
if ($profile->id) {
|
||||||
@ -1887,7 +1889,7 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
$xrd = $disco->lookup($addr);
|
$xrd = $disco->lookup($addr);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
// Save negative cache entry so we don't waste time looking it up again.
|
// Save negative cache entry so we don't waste time looking it up again.
|
||||||
// @fixme distinguish temporary failures?
|
// @todo FIXME: Distinguish temporary failures?
|
||||||
self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), null);
|
self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), null);
|
||||||
// TRANS: Exception.
|
// TRANS: Exception.
|
||||||
throw new Exception(_m('Not a valid webfinger address.'));
|
throw new Exception(_m('Not a valid webfinger address.'));
|
||||||
@ -1930,14 +1932,14 @@ class Ostatus_profile extends Managed_DataObject
|
|||||||
return $oprofile;
|
return $oprofile;
|
||||||
} catch (OStatusShadowException $e) {
|
} catch (OStatusShadowException $e) {
|
||||||
// We've ended up with a remote reference to a local user or group.
|
// We've ended up with a remote reference to a local user or group.
|
||||||
// @fixme ideally we should be able to say who it was so we can
|
// @todo FIXME: Ideally we should be able to say who it was so we can
|
||||||
// go back and refer to it the regular way
|
// go back and refer to it the regular way
|
||||||
throw $e;
|
throw $e;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
common_log(LOG_WARNING, "Failed creating profile from profile URL '$profileUrl': " . $e->getMessage());
|
common_log(LOG_WARNING, "Failed creating profile from profile URL '$profileUrl': " . $e->getMessage());
|
||||||
// keep looking
|
// keep looking
|
||||||
//
|
//
|
||||||
// @fixme this means an error discovering from profile page
|
// @todo FIXME: This means an error discovering from profile page
|
||||||
// may give us a corrupt entry using the webfinger URI, which
|
// may give us a corrupt entry using the webfinger URI, which
|
||||||
// will obscure the correct page-keyed profile later on.
|
// will obscure the correct page-keyed profile later on.
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,6 @@ class RealtimePlugin extends Plugin
|
|||||||
* When it's time to initialize the plugin, calculate and
|
* When it's time to initialize the plugin, calculate and
|
||||||
* pass the URLs we need.
|
* pass the URLs we need.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function onInitializePlugin()
|
function onInitializePlugin()
|
||||||
{
|
{
|
||||||
// FIXME: need to find a better way to pass this pattern in
|
// FIXME: need to find a better way to pass this pattern in
|
||||||
@ -59,14 +58,14 @@ class RealtimePlugin extends Plugin
|
|||||||
array('notice' => '0000000000'));
|
array('notice' => '0000000000'));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCheckSchema()
|
function onCheckSchema()
|
||||||
{
|
{
|
||||||
$schema = Schema::get();
|
$schema = Schema::get();
|
||||||
$schema->ensureTable('realtime_channel', Realtime_channel::schemaDef());
|
$schema->ensureTable('realtime_channel', Realtime_channel::schemaDef());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAutoload($cls)
|
function onAutoload($cls)
|
||||||
{
|
{
|
||||||
$dir = dirname(__FILE__);
|
$dir = dirname(__FILE__);
|
||||||
@ -238,31 +237,31 @@ class RealtimePlugin extends Plugin
|
|||||||
$json = $this->noticeAsJson($notice);
|
$json = $this->noticeAsJson($notice);
|
||||||
|
|
||||||
$this->_connect();
|
$this->_connect();
|
||||||
|
|
||||||
// XXX: We should probably fan-out here and do a
|
// XXX: We should probably fan-out here and do a
|
||||||
// new queue item for each path
|
// new queue item for each path
|
||||||
|
|
||||||
foreach ($paths as $path) {
|
foreach ($paths as $path) {
|
||||||
|
|
||||||
list($action, $arg1, $arg2) = $path;
|
list($action, $arg1, $arg2) = $path;
|
||||||
|
|
||||||
$channels = Realtime_channel::getAllChannels($action, $arg1, $arg2);
|
$channels = Realtime_channel::getAllChannels($action, $arg1, $arg2);
|
||||||
|
|
||||||
foreach ($channels as $channel) {
|
foreach ($channels as $channel) {
|
||||||
|
|
||||||
// XXX: We should probably fan-out here and do a
|
// XXX: We should probably fan-out here and do a
|
||||||
// new queue item for each user/path combo
|
// new queue item for each user/path combo
|
||||||
|
|
||||||
if (is_null($channel->user_id)) {
|
if (is_null($channel->user_id)) {
|
||||||
$profile = null;
|
$profile = null;
|
||||||
} else {
|
} else {
|
||||||
$profile = Profile::staticGet('id', $channel->user_id);
|
$profile = Profile::staticGet('id', $channel->user_id);
|
||||||
}
|
}
|
||||||
if ($notice->inScope($profile)) {
|
if ($notice->inScope($profile)) {
|
||||||
$timeline = $this->_pathToChannel(array($channel->channel_key));
|
$timeline = $this->_pathToChannel(array($channel->channel_key));
|
||||||
$this->_publish($timeline, $json);
|
$this->_publish($timeline, $json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_disconnect();
|
$this->_disconnect();
|
||||||
@ -367,9 +366,8 @@ class RealtimePlugin extends Plugin
|
|||||||
$convurl = $conv->uri;
|
$convurl = $conv->uri;
|
||||||
|
|
||||||
if(empty($convurl)) {
|
if(empty($convurl)) {
|
||||||
$msg = sprintf(
|
$msg = sprintf( "Could not find Conversation ID %d to make 'in context'"
|
||||||
"Couldn't find Conversation ID %d to make 'in context'"
|
. "link for Notice ID %d.",
|
||||||
. "link for Notice ID %d",
|
|
||||||
$notice->conversation,
|
$notice->conversation,
|
||||||
$notice->id
|
$notice->id
|
||||||
);
|
);
|
||||||
@ -455,26 +453,26 @@ class RealtimePlugin extends Plugin
|
|||||||
function _getChannel($action)
|
function _getChannel($action)
|
||||||
{
|
{
|
||||||
$timeline = null;
|
$timeline = null;
|
||||||
$arg1 = null;
|
$arg1 = null;
|
||||||
$arg2 = null;
|
$arg2 = null;
|
||||||
|
|
||||||
$action_name = $action->trimmed('action');
|
$action_name = $action->trimmed('action');
|
||||||
|
|
||||||
// FIXME: lists
|
// FIXME: lists
|
||||||
// FIXME: search (!)
|
// FIXME: search (!)
|
||||||
// FIXME: profile + tag
|
// FIXME: profile + tag
|
||||||
|
|
||||||
switch ($action_name) {
|
switch ($action_name) {
|
||||||
case 'public':
|
case 'public':
|
||||||
// no arguments
|
// no arguments
|
||||||
break;
|
break;
|
||||||
case 'tag':
|
case 'tag':
|
||||||
$tag = $action->trimmed('tag');
|
$tag = $action->trimmed('tag');
|
||||||
if (empty($tag)) {
|
if (empty($tag)) {
|
||||||
$arg1 = $tag;
|
$arg1 = $tag;
|
||||||
} else {
|
} else {
|
||||||
$this->log(LOG_NOTICE, "Unexpected 'tag' action without tag argument");
|
$this->log(LOG_NOTICE, "Unexpected 'tag' action without tag argument");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'showstream':
|
case 'showstream':
|
||||||
@ -485,29 +483,29 @@ class RealtimePlugin extends Plugin
|
|||||||
if (!empty($nickname)) {
|
if (!empty($nickname)) {
|
||||||
$arg1 = $nickname;
|
$arg1 = $nickname;
|
||||||
} else {
|
} else {
|
||||||
$this->log(LOG_NOTICE, "Unexpected $action_name action without nickname argument.");
|
$this->log(LOG_NOTICE, "Unexpected $action_name action without nickname argument.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = common_current_user();
|
$user = common_current_user();
|
||||||
|
|
||||||
$user_id = (!empty($user)) ? $user->id : null;
|
$user_id = (!empty($user)) ? $user->id : null;
|
||||||
|
|
||||||
$channel = Realtime_channel::getChannel($user_id,
|
$channel = Realtime_channel::getChannel($user_id,
|
||||||
$action_name,
|
$action_name,
|
||||||
$arg1,
|
$arg1,
|
||||||
$arg2);
|
$arg2);
|
||||||
|
|
||||||
return $channel;
|
return $channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onStartReadWriteTables(&$alwaysRW, &$rwdb)
|
function onStartReadWriteTables(&$alwaysRW, &$rwdb)
|
||||||
{
|
{
|
||||||
$alwaysRW[] = 'realtime_channel';
|
$alwaysRW[] = 'realtime_channel';
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Copyright (C) 2011, StatusNet, Inc.
|
* Copyright (C) 2011, StatusNet, Inc.
|
||||||
*
|
*
|
||||||
* A channel for real-time browser data
|
* A channel for real-time browser data
|
||||||
*
|
*
|
||||||
* PHP version 5
|
* PHP version 5
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -34,7 +34,7 @@ if (!defined('STATUSNET')) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A channel for real-time browser data
|
* A channel for real-time browser data
|
||||||
*
|
*
|
||||||
* For each user currently browsing the site, we want to know which page they're on
|
* For each user currently browsing the site, we want to know which page they're on
|
||||||
* so we can send real-time updates to their browser.
|
* so we can send real-time updates to their browser.
|
||||||
*
|
*
|
||||||
@ -46,20 +46,19 @@ if (!defined('STATUSNET')) {
|
|||||||
*
|
*
|
||||||
* @see DB_DataObject
|
* @see DB_DataObject
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Realtime_channel extends Managed_DataObject
|
class Realtime_channel extends Managed_DataObject
|
||||||
{
|
{
|
||||||
const TIMEOUT = 1800; // 30 minutes
|
const TIMEOUT = 1800; // 30 minutes
|
||||||
|
|
||||||
public $__table = 'realtime_channel'; // table name
|
public $__table = 'realtime_channel'; // table name
|
||||||
|
|
||||||
public $user_id; // int -> user.id, can be null
|
public $user_id; // int -> user.id, can be null
|
||||||
public $action; // string
|
public $action; // string
|
||||||
public $arg1; // argument
|
public $arg1; // argument
|
||||||
public $arg2; // argument, usually null
|
public $arg2; // argument, usually null
|
||||||
public $channel_key; // 128-bit shared secret key
|
public $channel_key; // 128-bit shared secret key
|
||||||
public $audience; // listener count
|
public $audience; // listener count
|
||||||
public $created; // created date
|
public $created; // created date
|
||||||
public $modified; // modified date
|
public $modified; // modified date
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,7 +70,6 @@ class Realtime_channel extends Managed_DataObject
|
|||||||
* @param mixed $v Value to lookup
|
* @param mixed $v Value to lookup
|
||||||
*
|
*
|
||||||
* @return Realtime_channel object found, or null for no hits
|
* @return Realtime_channel object found, or null for no hits
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
function staticGet($k, $v=null)
|
function staticGet($k, $v=null)
|
||||||
{
|
{
|
||||||
@ -84,7 +82,6 @@ class Realtime_channel extends Managed_DataObject
|
|||||||
* @param array $kv array of key-value mappings
|
* @param array $kv array of key-value mappings
|
||||||
*
|
*
|
||||||
* @return Realtime_channel object found, or null for no hits
|
* @return Realtime_channel object found, or null for no hits
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
function pkeyGet($kv)
|
function pkeyGet($kv)
|
||||||
{
|
{
|
||||||
@ -100,34 +97,34 @@ class Realtime_channel extends Managed_DataObject
|
|||||||
'description' => 'A channel of realtime notice data',
|
'description' => 'A channel of realtime notice data',
|
||||||
'fields' => array(
|
'fields' => array(
|
||||||
'user_id' => array('type' => 'int',
|
'user_id' => array('type' => 'int',
|
||||||
'not null' => false,
|
'not null' => false,
|
||||||
'description' => 'user viewing page; can be null'),
|
'description' => 'user viewing page; can be null'),
|
||||||
'action' => array('type' => 'varchar',
|
'action' => array('type' => 'varchar',
|
||||||
'length' => 255,
|
'length' => 255,
|
||||||
'not null' => true,
|
'not null' => true,
|
||||||
'description' => 'page being viewed'),
|
'description' => 'page being viewed'),
|
||||||
'arg1' => array('type' => 'varchar',
|
'arg1' => array('type' => 'varchar',
|
||||||
'length' => 255,
|
'length' => 255,
|
||||||
'not null' => false,
|
'not null' => false,
|
||||||
'description' => 'page argument, like username or tag'),
|
'description' => 'page argument, like username or tag'),
|
||||||
'arg2' => array('type' => 'varchar',
|
'arg2' => array('type' => 'varchar',
|
||||||
'length' => 255,
|
'length' => 255,
|
||||||
'not null' => false,
|
'not null' => false,
|
||||||
'description' => 'second page argument, like tag for showstream'),
|
'description' => 'second page argument, like tag for showstream'),
|
||||||
'channel_key' => array('type' => 'varchar',
|
'channel_key' => array('type' => 'varchar',
|
||||||
'length' => 32,
|
'length' => 32,
|
||||||
'not null' => true,
|
'not null' => true,
|
||||||
'description' => 'shared secret key for this channel'),
|
'description' => 'shared secret key for this channel'),
|
||||||
'audience' => array('type' => 'integer',
|
'audience' => array('type' => 'integer',
|
||||||
'not null' => true,
|
'not null' => true,
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'description' => 'reference count'),
|
'description' => 'reference count'),
|
||||||
'created' => array('type' => 'datetime',
|
'created' => array('type' => 'datetime',
|
||||||
'not null' => true,
|
'not null' => true,
|
||||||
'description' => 'date this record was created'),
|
'description' => 'date this record was created'),
|
||||||
'modified' => array('type' => 'datetime',
|
'modified' => array('type' => 'datetime',
|
||||||
'not null' => true,
|
'not null' => true,
|
||||||
'description' => 'date this record was modified'),
|
'description' => 'date this record was modified'),
|
||||||
),
|
),
|
||||||
'primary key' => array('channel_key'),
|
'primary key' => array('channel_key'),
|
||||||
'unique keys' => array('realtime_channel_user_page_idx' => array('user_id', 'action', 'arg1', 'arg2')),
|
'unique keys' => array('realtime_channel_user_page_idx' => array('user_id', 'action', 'arg1', 'arg2')),
|
||||||
@ -140,107 +137,107 @@ class Realtime_channel extends Managed_DataObject
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function saveNew($user_id, $action, $arg1, $arg2)
|
static function saveNew($user_id, $action, $arg1, $arg2)
|
||||||
{
|
{
|
||||||
$channel = new Realtime_channel();
|
$channel = new Realtime_channel();
|
||||||
|
|
||||||
$channel->user_id = $user_id;
|
$channel->user_id = $user_id;
|
||||||
$channel->action = $action;
|
$channel->action = $action;
|
||||||
$channel->arg1 = $arg1;
|
$channel->arg1 = $arg1;
|
||||||
$channel->arg2 = $arg2;
|
$channel->arg2 = $arg2;
|
||||||
$channel->audience = 1;
|
$channel->audience = 1;
|
||||||
|
|
||||||
$channel->channel_key = common_good_rand(16); // 128-bit key, 32 hex chars
|
$channel->channel_key = common_good_rand(16); // 128-bit key, 32 hex chars
|
||||||
|
|
||||||
$channel->created = common_sql_now();
|
$channel->created = common_sql_now();
|
||||||
$channel->modified = $channel->created;
|
$channel->modified = $channel->created;
|
||||||
|
|
||||||
$channel->insert();
|
$channel->insert();
|
||||||
|
|
||||||
return $channel;
|
return $channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function getChannel($user_id, $action, $arg1, $arg2)
|
static function getChannel($user_id, $action, $arg1, $arg2)
|
||||||
{
|
{
|
||||||
$channel = self::fetchChannel($user_id, $action, $arg1, $arg2);
|
$channel = self::fetchChannel($user_id, $action, $arg1, $arg2);
|
||||||
|
|
||||||
// Ignore (and delete!) old channels
|
// Ignore (and delete!) old channels
|
||||||
|
|
||||||
if (!empty($channel)) {
|
if (!empty($channel)) {
|
||||||
$modTime = strtotime($channel->modified);
|
$modTime = strtotime($channel->modified);
|
||||||
if ((time() - $modTime) > self::TIMEOUT) {
|
if ((time() - $modTime) > self::TIMEOUT) {
|
||||||
$channel->delete();
|
$channel->delete();
|
||||||
$channel = null;
|
$channel = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($channel)) {
|
if (empty($channel)) {
|
||||||
$channel = self::saveNew($user_id, $action, $arg1, $arg2);
|
$channel = self::saveNew($user_id, $action, $arg1, $arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $channel;
|
return $channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function getAllChannels($action, $arg1, $arg2)
|
static function getAllChannels($action, $arg1, $arg2)
|
||||||
{
|
{
|
||||||
$channel = new Realtime_channel();
|
$channel = new Realtime_channel();
|
||||||
|
|
||||||
$channel->action = $action;
|
$channel->action = $action;
|
||||||
|
|
||||||
if (is_null($arg1)) {
|
if (is_null($arg1)) {
|
||||||
$channel->whereAdd('arg1 is null');
|
$channel->whereAdd('arg1 is null');
|
||||||
} else {
|
} else {
|
||||||
$channel->arg1 = $arg1;
|
$channel->arg1 = $arg1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_null($arg2)) {
|
if (is_null($arg2)) {
|
||||||
$channel->whereAdd('arg2 is null');
|
$channel->whereAdd('arg2 is null');
|
||||||
} else {
|
} else {
|
||||||
$channel->arg2 = $arg2;
|
$channel->arg2 = $arg2;
|
||||||
}
|
}
|
||||||
|
|
||||||
$channel->whereAdd('modified > "' . common_sql_date(time() - self::TIMEOUT) . '"');
|
$channel->whereAdd('modified > "' . common_sql_date(time() - self::TIMEOUT) . '"');
|
||||||
|
|
||||||
$channels = array();
|
$channels = array();
|
||||||
|
|
||||||
if ($channel->find()) {
|
if ($channel->find()) {
|
||||||
$channels = $channel->fetchAll();
|
$channels = $channel->fetchAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $channels;
|
return $channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function fetchChannel($user_id, $action, $arg1, $arg2)
|
static function fetchChannel($user_id, $action, $arg1, $arg2)
|
||||||
{
|
{
|
||||||
$channel = new Realtime_channel();
|
$channel = new Realtime_channel();
|
||||||
|
|
||||||
if (is_null($user_id)) {
|
if (is_null($user_id)) {
|
||||||
$channel->whereAdd('user_id is null');
|
$channel->whereAdd('user_id is null');
|
||||||
} else {
|
} else {
|
||||||
$channel->user_id = $user_id;
|
$channel->user_id = $user_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
$channel->action = $action;
|
$channel->action = $action;
|
||||||
|
|
||||||
if (is_null($arg1)) {
|
if (is_null($arg1)) {
|
||||||
$channel->whereAdd('arg1 is null');
|
$channel->whereAdd('arg1 is null');
|
||||||
} else {
|
} else {
|
||||||
$channel->arg1 = $arg1;
|
$channel->arg1 = $arg1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_null($arg2)) {
|
if (is_null($arg2)) {
|
||||||
$channel->whereAdd('arg2 is null');
|
$channel->whereAdd('arg2 is null');
|
||||||
} else {
|
} else {
|
||||||
$channel->arg2 = $arg2;
|
$channel->arg2 = $arg2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($channel->find(true)) {
|
if ($channel->find(true)) {
|
||||||
$channel->increment();
|
$channel->increment();
|
||||||
return $channel;
|
return $channel;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function increment()
|
function increment()
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Copyright (C) 2011, StatusNet, Inc.
|
* Copyright (C) 2011, StatusNet, Inc.
|
||||||
*
|
*
|
||||||
* action to close a channel
|
* action to close a channel
|
||||||
*
|
*
|
||||||
* PHP version 5
|
* PHP version 5
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -44,7 +44,6 @@ if (!defined('STATUSNET')) {
|
|||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||||
* @link http://status.net/
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ClosechannelAction extends Action
|
class ClosechannelAction extends Action
|
||||||
{
|
{
|
||||||
protected $channelKey = null;
|
protected $channelKey = null;
|
||||||
@ -57,24 +56,26 @@ class ClosechannelAction extends Action
|
|||||||
*
|
*
|
||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function prepare($argarray)
|
function prepare($argarray)
|
||||||
{
|
{
|
||||||
parent::prepare($argarray);
|
parent::prepare($argarray);
|
||||||
|
|
||||||
if (!$this->isPost()) {
|
if (!$this->isPost()) {
|
||||||
|
// TRANS: Client exception. Do not translate POST.
|
||||||
throw new ClientException(_m('You have to POST it.'));
|
throw new ClientException(_m('You have to POST it.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->channelKey = $this->trimmed('channelkey');
|
$this->channelKey = $this->trimmed('channelkey');
|
||||||
|
|
||||||
if (empty($this->channelKey)) {
|
if (empty($this->channelKey)) {
|
||||||
|
// TRANS: Client exception thrown when the channel key argument is missing.
|
||||||
throw new ClientException(_m('No channel key argument.'));
|
throw new ClientException(_m('No channel key argument.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->channel = Realtime_channel::staticGet('channel_key', $this->channelKey);
|
$this->channel = Realtime_channel::staticGet('channel_key', $this->channelKey);
|
||||||
|
|
||||||
if (empty($this->channel)) {
|
if (empty($this->channel)) {
|
||||||
|
// TRANS: Client exception thrown when referring to a non-existing channel.
|
||||||
throw new ClientException(_m('No such channel.'));
|
throw new ClientException(_m('No such channel.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +89,6 @@ class ClosechannelAction extends Action
|
|||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function handle($argarray=null)
|
function handle($argarray=null)
|
||||||
{
|
{
|
||||||
$this->channel->decrement();
|
$this->channel->decrement();
|
||||||
@ -107,7 +107,6 @@ class ClosechannelAction extends Action
|
|||||||
*
|
*
|
||||||
* @return boolean is read only action?
|
* @return boolean is read only action?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function isReadOnly($args)
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -44,7 +44,6 @@ if (!defined('STATUSNET')) {
|
|||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
|
||||||
* @link http://status.net/
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class KeepalivechannelAction extends Action
|
class KeepalivechannelAction extends Action
|
||||||
{
|
{
|
||||||
protected $channelKey = null;
|
protected $channelKey = null;
|
||||||
@ -57,24 +56,26 @@ class KeepalivechannelAction extends Action
|
|||||||
*
|
*
|
||||||
* @return boolean true
|
* @return boolean true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function prepare($argarray)
|
function prepare($argarray)
|
||||||
{
|
{
|
||||||
parent::prepare($argarray);
|
parent::prepare($argarray);
|
||||||
|
|
||||||
if (!$this->isPost()) {
|
if (!$this->isPost()) {
|
||||||
|
// TRANS: Client exception. Do not translate POST.
|
||||||
throw new ClientException(_m('You have to POST it.'));
|
throw new ClientException(_m('You have to POST it.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->channelKey = $this->trimmed('channelkey');
|
$this->channelKey = $this->trimmed('channelkey');
|
||||||
|
|
||||||
if (empty($this->channelKey)) {
|
if (empty($this->channelKey)) {
|
||||||
|
// TRANS: Client exception thrown when the channel key argument is missing.
|
||||||
throw new ClientException(_m('No channel key argument.'));
|
throw new ClientException(_m('No channel key argument.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->channel = Realtime_channel::staticGet('channel_key', $this->channelKey);
|
$this->channel = Realtime_channel::staticGet('channel_key', $this->channelKey);
|
||||||
|
|
||||||
if (empty($this->channel)) {
|
if (empty($this->channel)) {
|
||||||
|
// TRANS: Client exception thrown when referring to a non-existing channel.
|
||||||
throw new ClientException(_m('No such channel.'));
|
throw new ClientException(_m('No such channel.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +89,6 @@ class KeepalivechannelAction extends Action
|
|||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function handle($argarray=null)
|
function handle($argarray=null)
|
||||||
{
|
{
|
||||||
$this->channel->touch();
|
$this->channel->touch();
|
||||||
@ -107,7 +107,6 @@ class KeepalivechannelAction extends Action
|
|||||||
*
|
*
|
||||||
* @return boolean is read only action?
|
* @return boolean is read only action?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function isReadOnly($args)
|
function isReadOnly($args)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -412,7 +412,7 @@ RealtimeUpdate = {
|
|||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: RealtimeUpdate._keepaliveurl});
|
url: RealtimeUpdate._keepaliveurl});
|
||||||
|
|
||||||
}, 15 * 60 * 1000 ); // every 15 min; timeout in 30 min
|
}, 15 * 60 * 1000 ); // every 15 min; timeout in 30 min
|
||||||
|
|
||||||
RealtimeUpdate.initPlayPause();
|
RealtimeUpdate.initPlayPause();
|
||||||
|
Loading…
Reference in New Issue
Block a user