Commit 1b7d1d9a authored by Samantha Doherty's avatar Samantha Doherty

Merge branch '1.0.x' of gitorious.org:statusnet/mainline into 1.0.x

parents 23e5f25d 5d557a26
......@@ -4,7 +4,7 @@
* Copyright (C) 2011, StatusNet, Inc.
*
* Show a stream of notices in a particular conversation
*
*
* PHP version 5
*
* 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
* @link http://status.net/
*/
class ApiconversationAction extends ApiAuthAction
{
protected $conversation = null;
protected $notices = null;
protected $conversation = null;
protected $notices = null;
/**
* For initializing members of the class.
*
......@@ -59,35 +58,36 @@ class ApiconversationAction extends ApiAuthAction
*
* @return boolean true
*/
function prepare($argarray)
{
parent::prepare($argarray);
$convId = $this->trimmed('id');
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);
if (empty($this->conversation)) {
throw new ClientException(sprintf(_m('No conversation with id %d'), $convId),
404);
// TRANS: Client exception thrown when referring to a non-existing conversation ID (%d).
throw new ClientException(sprintf(_('No conversation with ID %d.'), $convId),
404);
}
$profile = Profile::current();
$stream = new ConversationNoticeStream($convId, $profile);
$notice = $stream->getNotices(($this->page-1) * $this->count,
$this->count,
$this->since_id,
$this->max_id);
$this->notices = $notice->fetchAll();
return true;
}
......@@ -98,17 +98,16 @@ class ApiconversationAction extends ApiAuthAction
*
* @return void
*/
function handle($argarray=null)
{
$sitename = common_config('site', 'name');
// 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));
$link = common_local_url('conversation', array('id' => $this->conversation->id));
$self = $id;
switch($this->format) {
case 'xml':
$this->showXmlTimeline($this->notices);
......@@ -168,7 +167,6 @@ class ApiconversationAction extends ApiAuthAction
*
* @return boolean is read only action?
*/
function isReadOnly($args)
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
......@@ -202,7 +200,6 @@ class ApiconversationAction extends ApiAuthAction
*
* @return string etag http header
*/
function etag()
{
if (!empty($this->notices) && (count($this->notices) > 0)) {
......@@ -220,7 +217,7 @@ class ApiconversationAction extends ApiAuthAction
)
. '"';
}
return null;
}
......@@ -229,7 +226,6 @@ class ApiconversationAction extends ApiAuthAction
*
* @return boolean true if delete, else false
*/
function requiresAuth()
{
if ($_SERVER['REQUEST_METHOD'] == 'GET' ||
......@@ -239,4 +235,4 @@ class ApiconversationAction extends ApiAuthAction
return true;
}
}
}
\ No newline at end of file
}
......@@ -63,156 +63,158 @@ class Memcached_DataObject extends Safe_DataObject
}
return $i;
}
/**
* Get multiple items from the database by key
*
*
* @param string $cls Class to fetch
* @param string $keyCol name of column for key
* @param array $keyVals key values to fetch
* @param boolean $skipNulls return only non-null results?
*
*
* @return array Array of objects, in order
*/
function multiGet($cls, $keyCol, $keyVals, $skipNulls=true)
{
$result = self::pivotGet($cls, $keyCol, $keyVals);
$values = array_values($result);
if ($skipNulls) {
$tmp = array();
foreach ($values as $value) {
if (!empty($value)) {
$tmp[] = $value;
}
}
$values = $tmp;
}
return new ArrayWrapper($values);
}
$result = self::pivotGet($cls, $keyCol, $keyVals);
$values = array_values($result);
if ($skipNulls) {
$tmp = array();
foreach ($values as $value) {
if (!empty($value)) {
$tmp[] = $value;
}
}
$values = $tmp;
}
return new ArrayWrapper($values);
}
/**
* Get multiple items from the database by key
*
*
* @param string $cls Class to fetch
* @param string $keyCol name of column for key
* @param array $keyVals key values to fetch
* @param boolean $otherCols Other columns to hold fixed
*
*
* @return array Array mapping $keyVals to objects, or null if not found
*/
static function pivotGet($cls, $keyCol, $keyVals, $otherCols = array())
{
$result = array_fill_keys($keyVals, null);
$toFetch = array();
foreach ($keyVals as $keyVal) {
$kv = array_merge($otherCols, array($keyCol => $keyVal));
$i = self::multicache($cls, $kv);
if ($i !== false) {
$result[$keyVal] = $i;
} else if (!empty($keyVal)) {
$toFetch[] = $keyVal;
}
}
if (count($toFetch) > 0) {
$result = array_fill_keys($keyVals, null);
$toFetch = array();
foreach ($keyVals as $keyVal) {
$kv = array_merge($otherCols, array($keyCol => $keyVal));
$i = self::multicache($cls, $kv);
if ($i !== false) {
$result[$keyVal] = $i;
} else if (!empty($keyVal)) {
$toFetch[] = $keyVal;
}
}
if (count($toFetch) > 0) {
$i = DB_DataObject::factory($cls);
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) {
$i->$otherKeyCol = $otherKeyVal;
}
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
if ($i->find()) {
while ($i->fetch()) {
$copy = clone($i);
$copy->encache();
$result[$i->$keyCol] = $copy;
}
}
// Save state of DB misses
foreach ($toFetch as $keyVal) {
if (empty($result[$keyVal])) {
$kv = array_merge($otherCols, array($keyCol => $keyVal));
// save the fact that no such row exists
$c = self::memcache();
if (!empty($c)) {
$ck = self::multicacheKey($cls, $kv);
$c->set($ck, null);
}
}
}
}
return $result;
}
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
if ($i->find()) {
while ($i->fetch()) {
$copy = clone($i);
$copy->encache();
$result[$i->$keyCol] = $copy;
}
}
// Save state of DB misses
foreach ($toFetch as $keyVal) {
if (empty($result[$keyVal])) {
$kv = array_merge($otherCols, array($keyCol => $keyVal));
// save the fact that no such row exists
$c = self::memcache();
if (!empty($c)) {
$ck = self::multicacheKey($cls, $kv);
$c->set($ck, null);
}
}
}
}
return $result;
}
function listGet($cls, $keyCol, $keyVals)
{
$result = array_fill_keys($keyVals, array());
$toFetch = array();
foreach ($keyVals as $keyVal) {
$l = self::cacheGet(sprintf("%s:list:%s:%s", $cls, $keyCol, $keyVal));
if ($l !== false) {
$result[$keyVal] = $l;
} else {
$toFetch[] = $keyVal;
}
}
$result = array_fill_keys($keyVals, array());
$toFetch = array();
foreach ($keyVals as $keyVal) {
$l = self::cacheGet(sprintf("%s:list:%s:%s", $cls, $keyCol, $keyVal));
if ($l !== false) {
$result[$keyVal] = $l;
} else {
$toFetch[] = $keyVal;
}
}
if (count($toFetch) > 0) {
$i = DB_DataObject::factory($cls);
if (empty($i)) {
throw new Exception(_('Cannot instantiate class ' . $cls));
}
$i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
if ($i->find()) {
while ($i->fetch()) {
$copy = clone($i);
$copy->encache();
$result[$i->$keyCol][] = $copy;
}
}
foreach ($toFetch as $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';
}
}
$i = DB_DataObject::factory($cls);
if (empty($i)) {
// 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()) {
while ($i->fetch()) {
$copy = clone($i);
$copy->encache();
$result[$i->$keyCol][] = $copy;
}
}
foreach ($toFetch as $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';
}
}
/**
* @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)
{
......@@ -225,13 +227,13 @@ class Memcached_DataObject extends Safe_DataObject
return false;
}
foreach ($kv as $k => $v) {
if (is_null($v)) {
// XXX: possible SQL injection...? Don't
// pass keys from the browser, eh.
$i->whereAdd("$k is null");
} else {
$i->$k = $v;
}
if (is_null($v)) {
// XXX: possible SQL injection...? Don't
// pass keys from the browser, eh.
$i->whereAdd("$k is null");
} else {
$i->$k = $v;
}
}
if ($i->find(true)) {
$i->encache();
......@@ -562,7 +564,7 @@ class Memcached_DataObject extends Safe_DataObject
continue;
}
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;
break;
......@@ -705,7 +707,7 @@ class Memcached_DataObject extends Safe_DataObject
if (!$dsn) {
// 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;
......
......@@ -84,8 +84,10 @@ class GroupsNav extends MoreMenu
function seeAllItem() {
return array('usergroups',
array('nickname' => $this->user->nickname),
// TRANS: Link description for seeing all groups.
_('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';
}
function getItems()
{
$items = array();
while ($this->lists->fetch()) {
$mode = $this->lists->private ? 'private' : 'public';
$items[] = array('showprofiletag',
......@@ -84,7 +84,9 @@ class ListsNav extends MoreMenu
{
return array('peopletagsbyuser',
array('nickname' => $this->profile->nickname),
// TRANS: Link description for seeing all lists.
_('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.
*
* A menu with a More... button to show more elements
*
*
* PHP version 5
*
* 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
* @link http://status.net/
*/
class MoreMenu extends Menu
{
const SOFT_MAX = 5;
const HARD_MAX = 15;
/**
* Show a menu with a limited number of elements
*
......@@ -57,7 +56,6 @@ class MoreMenu extends Menu
*
* @return
*/
function show()
{
$items = $this->getItems();
......@@ -72,7 +70,6 @@ class MoreMenu extends Menu
}
if (Event::handle('StartNav', array($this, &$tag, &$items))) {
$this->out->elementStart('ul', $attrs);
$total = count($items);
......@@ -89,10 +86,10 @@ class MoreMenu extends Menu
}
if ($total > self::SOFT_MAX + 1) {
$this->out->elementStart('li', array('class' => 'more_link'));
$this->out->element('a', array('href' => '#',
'onclick' => 'SN.U.showMoreMenuItems("'.$menuID.'"); return false;'),
// TRANS: Link description to show more items in a list.
_('More ▼'));
$this->out->elementEnd('li');
......@@ -112,7 +109,7 @@ class MoreMenu extends Menu
}
}
}
$this->out->elementEnd('ul');
Event::handle('EndNav', array($this, $tag, $items));
......@@ -123,5 +120,4 @@ class MoreMenu extends Menu
{
return null;
}
}
......@@ -120,13 +120,15 @@ class BlogPlugin extends MicroAppPlugin
'author' => 'Evan Prodromou',
'homepage' => 'http://status.net/wiki/Plugin:Blog',
'rawdescription' =>
// TRANS: Plugin description.
_m('Let users write and share long-form texts.'));
return true;
}
function appTitle()
{
return _m('Blog');
// TRANS: Blog application title.
return _m('TITLE','Blog');
}
function tag()
......@@ -149,7 +151,7 @@ class BlogPlugin extends MicroAppPlugin
$entryObj = $activity->objects[0];
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.'));
}
......@@ -175,7 +177,8 @@ class BlogPlugin extends MicroAppPlugin
$entry = Blog_entry::fromNotice($notice);
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));
}
......@@ -204,7 +207,7 @@ class BlogPlugin extends MicroAppPlugin
if ($notice->object_type == Blog_entry::TYPE) {
return new BlogEntryListItem($nli);
}
return null;
}
......
......@@ -44,7 +44,6 @@ if (!defined('STATUSNET')) {
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class BlogEntryForm extends Form
{
/**
......@@ -96,13 +95,13 @@ class BlogEntryForm extends Form
_m('Title of the blog entry.'),
'title');
$this->unli();
$this->li();
$this->out->textarea('blog-entry-content',
// TRANS: Field label on event form.
// TRANS: Field label on blog entry form.
_m('LABEL','Text'),
null,
// TRANS: Field title on event form.
// TRANS: Field title on blog entry form.
_m('Text of the blog entry.'),
'content');
$this->unli();
......@@ -124,8 +123,8 @@ class BlogEntryForm extends Form
*/
function formActions()
{
// TRANS: Button text to save an event..
$this->out->submit('blog-entry-submit',
// TRANS: Button text to save a blog entry.
_m('BUTTON', 'Save'),
'submit',
'submit');
......
......@@ -4,7 +4,7 @@
* Copyright (C) 2011, StatusNet, Inc.
*
* Show a blog entry
*
*
* PHP version 5
*
* 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
* @link http://status.net/
*/
class ShowblogentryAction extends ShownoticeAction
{
protected $id;
protected $entry;
function getNotice()
{
$this->id = $this->trimmed('id');
......@@ -81,6 +80,7 @@ class ShowblogentryAction extends ShownoticeAction
function title()
{
// XXX: check for double-encoding
// TRANS: Title for a blog entry without a title.
return (empty($this->entry->title)) ? _m('Untitled') : $this->entry->title;
}
}
......@@ -78,14 +78,14 @@ class NewrsvpAction extends Action
$eventId = $this->trimmed('event');
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.'));
}
$this->event = Happening::staticGet('id', $eventId);
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.'));
}
......
......@@ -32,7 +32,6 @@ if (!defined('STATUSNET')) {
* Callback handler to populate end time dropdown
*/
class TimelistAction extends Action {
private $start;
private $duration;
......@@ -63,13 +62,14 @@ class TimelistAction extends Action {
if (!common_logged_in()) {
// 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;
}