Commit cd4b23aa authored by Luke Fitzgerald's avatar Luke Fitzgerald

Merge branch '1.0.x' into msn-plugin

parents 43db20ca 558bfb8c
......@@ -1115,3 +1115,27 @@ StartGroupProfileElements: Start showing stuff about the group on its profile pa
EndGroupProfileElements: Start showing stuff about the group on its profile page
- $action: action being executed (for output and params)
- $group: group for the page
StartActivityObjectOutputAtom: Called at start of Atom XML output generation for ActivityObject chunks, just inside the <activity:object>. Cancel the event to take over its output completely (you're responsible for calling the matching End event if so)
- $obj: ActivityObject
- $out: XMLOutputter to append custom output
EndActivityObjectOutputAtom: Called at end of Atom XML output generation for ActivityObject chunks, just inside the </activity:object>
- $obj: ActivityObject
- $out: XMLOutputter to append custom output
StartActivityObjectOutputJson: Called at start of JSON output generation for ActivityObject chunks: the array has not yet been filled out. Cancel the event to take over its output completely (you're responsible for calling the matching End event if so)
- $obj ActivityObject
- &$out: array to be serialized; you're free to modify it
EndActivityObjectOutputJson: Called at end of JSON output generation for ActivityObject chunks: the array has not yet been filled out.
- $obj ActivityObject
- &$out: array to be serialized; you're free to modify it
StartNoticeWhoGets: Called at start of inbox delivery prep; plugins can schedule notices to go to particular profiles that would otherwise not have reached them. Canceling will take over the entire addressing operation. Be aware that output can be cached or used several times, so should remain idempotent.
- $notice Notice
- &$ni: in/out array mapping profile IDs to constants: NOTICE_INBOX_SOURCE_SUB etc
EndNoticeWhoGets: Called at end of inbox delivery prep; plugins can filter out profiles from receiving inbox delivery here. Be aware that output can be cached or used several times, so should remain idempotent.
- $notice Notice
- &$ni: in/out array mapping profile IDs to constants: NOTICE_INBOX_SOURCE_SUB etc
......@@ -100,7 +100,7 @@ class ApiGroupListAction extends ApiBareAuthAction
);
$subtitle = sprintf(
// TRANS: Used as subtitle in check for group membership. %1$s is a user name, %2$s is the site name.
// TRANS: Used as subtitle in check for group membership. %1$s is the site name, %2$s is a user name.
_('%1$s groups %2$s is a member of.'),
$sitename,
$this->user->nickname
......
......@@ -322,8 +322,11 @@ class ApiTimelineUserAction extends ApiBareAuthAction
$this->clientError(_('Atom post must not be empty.'));
}
$dom = DOMDocument::loadXML($xml);
if (!$dom) {
$old = error_reporting(error_reporting() & ~(E_WARNING | E_NOTICE));
$dom = new DOMDocument();
$ok = $dom->loadXML($xml);
error_reporting($old);
if (!$ok) {
// TRANS: Client error displayed attempting to post an API that is not well-formed XML.
$this->clientError(_('Atom post must be well-formed XML.'));
}
......
......@@ -301,4 +301,8 @@ class LoginAction extends Action
function showNoticeForm()
{
}
function showProfileBlock()
{
}
}
......@@ -138,11 +138,14 @@ class NoticesearchAction extends SearchAction
$this->elementEnd('div');
return;
}
$terms = preg_split('/[\s,]+/', $q);
$nl = new SearchNoticeList($notice, $this, $terms);
$cnt = $nl->show();
$this->pagination($page > 1, $cnt > NOTICES_PER_PAGE,
$page, 'noticesearch', array('q' => $q));
if (Event::handle('StartNoticeSearchShowResults', array($this, $q, $notice))) {
$terms = preg_split('/[\s,]+/', $q);
$nl = new SearchNoticeList($notice, $this, $terms);
$cnt = $nl->show();
$this->pagination($page > 1, $cnt > NOTICES_PER_PAGE,
$page, 'noticesearch', array('q' => $q));
Event::handle('EndNoticeSearchShowResults', array($this, $q, $notice));
}
}
function showScripts()
......
......@@ -610,4 +610,8 @@ class RegisterAction extends Action
function showNoticeForm()
{
}
function showProfileBlock()
{
}
}
......@@ -180,8 +180,6 @@ class ShowgroupAction extends GroupDesignAction
*/
function showContent()
{
$this->showGroupProfile();
$this->showGroupActions();
$this->showGroupNotices();
}
......@@ -205,121 +203,6 @@ class ShowgroupAction extends GroupDesignAction
array('nickname' => $this->group->nickname));
}
/**
* Show the group profile
*
* Information about the group
*
* @return void
*/
function showGroupProfile()
{
$this->elementStart('div', array('id' => 'i',
'class' => 'entity_profile vcard author'));
$logo = ($this->group->homepage_logo) ?
$this->group->homepage_logo : User_group::defaultLogo(AVATAR_PROFILE_SIZE);
$this->element('img', array('src' => $logo,
'class' => 'photo avatar entity_depiction',
'width' => AVATAR_PROFILE_SIZE,
'height' => AVATAR_PROFILE_SIZE,
'alt' => $this->group->nickname));
$hasFN = ($this->group->fullname) ? 'entity_nickname nickname url uid' :
'entity_nickname fn org nickname url uid';
$this->element('a', array('href' => $this->group->homeUrl(),
'rel' => 'me', 'class' => $hasFN),
$this->group->nickname);
if ($this->group->fullname) {
$this->element('div', 'entity_fn fn org', $this->group->fullname);
}
if ($this->group->location) {
$this->element('div', 'entity_location label', $this->group->location);
}
if ($this->group->homepage) {
$this->element('a', array('href' => $this->group->homepage,
'rel' => 'me',
'class' => 'url entity_url'),
$this->group->homepage);
}
if ($this->group->description) {
$this->element('div', 'note entity_note', $this->group->description);
}
if (common_config('group', 'maxaliases') > 0) {
$aliases = $this->group->getAliases();
if (!empty($aliases)) {
$this->element('div',
'aliases entity_aliases',
implode(' ', $aliases));
}
if ($this->group->description) {
$this->elementStart('dl', 'entity_note');
// TRANS: Label for group description or group note (dt). Text hidden by default.
$this->element('dt', null, _('Note'));
$this->element('dd', 'note', $this->group->description);
$this->elementEnd('dl');
}
if (common_config('group', 'maxaliases') > 0) {
$aliases = $this->group->getAliases();
if (!empty($aliases)) {
$this->elementStart('dl', 'entity_aliases');
// TRANS: Label for group aliases (dt). Text hidden by default.
$this->element('dt', null, _('Aliases'));
$this->element('dd', 'aliases', implode(' ', $aliases));
$this->elementEnd('dl');
}
}
Event::handle('EndGroupProfileElements', array($this, $this->group));
}
$this->elementEnd('div');
}
function showGroupActions()
{
$cur = common_current_user();
$this->elementStart('div', 'entity_actions');
// TRANS: Group actions header (h2). Text hidden by default.
$this->element('h2', null, _('Group actions'));
$this->elementStart('ul');
if (Event::handle('StartGroupActionsList', array($this, $this->group))) {
$this->elementStart('li', 'entity_subscribe');
if (Event::handle('StartGroupSubscribe', array($this, $this->group))) {
if ($cur) {
if ($cur->isMember($this->group)) {
$lf = new LeaveForm($this, $this->group);
$lf->show();
} else if (!Group_block::isBlocked($this->group, $cur->getProfile())) {
$jf = new JoinForm($this, $this->group);
$jf->show();
}
}
Event::handle('EndGroupSubscribe', array($this, $this->group));
}
$this->elementEnd('li');
if ($cur && $cur->hasRight(Right::DELETEGROUP)) {
$this->elementStart('li', 'entity_delete');
$df = new DeleteGroupForm($this, $this->group);
$df->show();
$this->elementEnd('li');
}
Event::handle('EndGroupActionsList', array($this, $this->group));
}
$this->elementEnd('ul');
$this->elementEnd('div');
}
/**
* Get a list of the feeds for this page
*
......@@ -440,7 +323,7 @@ class ShowgroupAction extends GroupDesignAction
// TRANS: Header for group statistics on a group page (h2).
$this->element('h2', null, _('Statistics'));
$this->elementEnd('dl');
$this->elementStart('dl');
$this->element('dt', null, _m('LABEL','Created'));
$this->element('dd', 'entity_created', date('j M Y',
strtotime($this->group->created)));
......
......@@ -78,6 +78,9 @@ class ShownoticeAction extends OwnerDesignAction
function prepare($args)
{
parent::prepare($args);
if ($this->boolean('ajax')) {
StatusNet::setApi(true);
}
$id = $this->arg('notice');
......@@ -188,22 +191,26 @@ class ShownoticeAction extends OwnerDesignAction
{
parent::handle($args);
if ($this->notice->is_local == Notice::REMOTE_OMB) {
if (!empty($this->notice->url)) {
$target = $this->notice->url;
} else if (!empty($this->notice->uri) && preg_match('/^https?:/', $this->notice->uri)) {
// Old OMB posts saved the remote URL only into the URI field.
$target = $this->notice->uri;
} else {
// Shouldn't happen.
$target = false;
}
if ($target && $target != $this->selfUrl()) {
common_redirect($target, 301);
return false;
if ($this->boolean('ajax')) {
$this->showAjax();
} else {
if ($this->notice->is_local == Notice::REMOTE_OMB) {
if (!empty($this->notice->url)) {
$target = $this->notice->url;
} else if (!empty($this->notice->uri) && preg_match('/^https?:/', $this->notice->uri)) {
// Old OMB posts saved the remote URL only into the URI field.
$target = $this->notice->uri;
} else {
// Shouldn't happen.
$target = false;
}
if ($target && $target != $this->selfUrl()) {
common_redirect($target, 301);
return false;
}
}
$this->showPage();
}
$this->showPage();
}
/**
......@@ -232,6 +239,21 @@ class ShownoticeAction extends OwnerDesignAction
$this->elementEnd('ol');
}
function showAjax()
{
header('Content-Type: text/xml;charset=utf-8');
$this->xw->startDocument('1.0', 'UTF-8');
$this->elementStart('html');
$this->elementStart('head');
$this->element('title', null, _('Notice'));
$this->elementEnd('head');
$this->elementStart('body');
$nli = new NoticeListItem($this->notice, $this);
$nli->show();
$this->elementEnd('body');
$this->elementEnd('html');
}
/**
* Don't show page notice
*
......
......@@ -33,7 +33,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
}
require_once INSTALLDIR.'/lib/personalgroupnav.php';
require_once INSTALLDIR.'/lib/userprofile.php';
require_once INSTALLDIR.'/lib/noticelist.php';
require_once INSTALLDIR.'/lib/profileminilist.php';
require_once INSTALLDIR.'/lib/groupminilist.php';
......@@ -100,7 +99,6 @@ class ShowstreamAction extends ProfileAction
function showContent()
{
$this->showProfile();
$this->showNotices();
}
......@@ -110,6 +108,12 @@ class ShowstreamAction extends ProfileAction
$nav->show();
}
function showProfileBlock()
{
$block = new AccountProfileBlock($this, $this->profile);
$block->show();
}
function showPageNoticeBlock()
{
return;
......@@ -193,12 +197,6 @@ class ShowstreamAction extends ProfileAction
'href' => $rsd));
}
function showProfile()
{
$profile = new UserProfile($this, $this->user, $this->profile);
$profile->show();
}
function showEmptyListMessage()
{
// TRANS: First sentence of empty list message for a stream. $1%s is a user nickname.
......@@ -281,6 +279,18 @@ class ShowstreamAction extends ProfileAction
// We don't show the author for a profile, since we already know who it is!
/**
* Slightly modified from standard list; the author & avatar are hidden
* in CSS. We used to remove them here too, but as it turns out that
* confuses the inline reply code... and we hide them in CSS anyway
* since realtime updates come through in original form.
*
* Remaining customization right now is for the repeat marker, where
* it'll list who the original poster was instead of who did the repeat
* (since the repeater is you, and the repeatee isn't shown!)
* This will remain inconsistent if realtime updates come through,
* since those'll get rendered as a regular NoticeListItem.
*/
class ProfileNoticeList extends NoticeList
{
function newListItem($notice)
......@@ -291,11 +301,6 @@ class ProfileNoticeList extends NoticeList
class ProfileNoticeListItem extends DoFollowListItem
{
function showAuthor()
{
return;
}
/**
* show a link to the author of repeat
*
......
......@@ -409,7 +409,7 @@ class SmssettingsAction extends SettingsAction
if (!$result) {
common_log_db_error($confirm, 'DELETE', __FILE__);
// TRANS: Server error thrown on database error canceling SMS phone number confirmation.
$this->serverError(_('Could not delete email confirmation.'));
$this->serverError(_('Could not delete SMS confirmation.'));
return;
}
......
......@@ -21,6 +21,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once(INSTALLDIR.'/lib/settingsaction.php');
// @todo FIXME: documentation missing.
class TagotherAction extends Action
{
var $profile = null;
......@@ -127,10 +128,10 @@ class TagotherAction extends Action
$this->elementStart('li');
$this->input('tags', _('Tags'),
($this->arg('tags')) ? $this->arg('tags') : implode(' ', Profile_tag::getTags($user->id, $this->profile->id)),
_('Tags for this user (letters, numbers, -, ., and _), comma- or space- separated'));
_('Tags for this user (letters, numbers, -, ., and _), separated by commas or spaces.'));
$this->elementEnd('li');
$this->elementEnd('ul');
$this->submit('save', _('Save'));
$this->submit('save', _m('BUTTON','Save'));
$this->elementEnd('fieldset');
$this->elementEnd('form');
}
......@@ -154,7 +155,9 @@ class TagotherAction extends Action
foreach ($tags as $tag) {
if (!common_valid_profile_tag($tag)) {
$this->showForm(sprintf(_('Invalid tag: "%s"'), $tag));
// TRANS: Form validation error when entering an invalid tag.
// TRANS: %s is the invalid tag.
$this->showForm(sprintf(_('Invalid tag: "%s".'), $tag));
return;
}
}
......@@ -217,4 +220,3 @@ class TagotherAction extends Action
}
}
}
......@@ -168,4 +168,10 @@ class UsergroupsAction extends OwnerDesignAction
$this->raw(common_markup_to_html($message));
$this->elementEnd('div');
}
function showProfileBlock()
{
$block = new AccountProfileBlock($this, $this->profile);
$block->show();
}
}
......@@ -812,41 +812,48 @@ class Notice extends Memcached_DataObject
$ni = array();
foreach ($users as $id) {
$ni[$id] = NOTICE_INBOX_SOURCE_SUB;
}
// Give plugins a chance to add folks in at start...
if (Event::handle('StartNoticeWhoGets', array($this, &$ni))) {
foreach ($groups as $group) {
$users = $group->getUserMembers();
foreach ($users as $id) {
if (!array_key_exists($id, $ni)) {
$ni[$id] = NOTICE_INBOX_SOURCE_GROUP;
$ni[$id] = NOTICE_INBOX_SOURCE_SUB;
}
foreach ($groups as $group) {
$users = $group->getUserMembers();
foreach ($users as $id) {
if (!array_key_exists($id, $ni)) {
$ni[$id] = NOTICE_INBOX_SOURCE_GROUP;
}
}
}
}
foreach ($recipients as $recipient) {
if (!array_key_exists($recipient, $ni)) {
$ni[$recipient] = NOTICE_INBOX_SOURCE_REPLY;
foreach ($recipients as $recipient) {
if (!array_key_exists($recipient, $ni)) {
$ni[$recipient] = NOTICE_INBOX_SOURCE_REPLY;
}
}
}
// Exclude any deleted, non-local, or blocking recipients.
$profile = $this->getProfile();
$originalProfile = null;
if ($this->repeat_of) {
// Check blocks against the original notice's poster as well.
$original = Notice::staticGet('id', $this->repeat_of);
if ($original) {
$originalProfile = $original->getProfile();
// Exclude any deleted, non-local, or blocking recipients.
$profile = $this->getProfile();
$originalProfile = null;
if ($this->repeat_of) {
// Check blocks against the original notice's poster as well.
$original = Notice::staticGet('id', $this->repeat_of);
if ($original) {
$originalProfile = $original->getProfile();
}
}
}
foreach ($ni as $id => $source) {
$user = User::staticGet('id', $id);
if (empty($user) || $user->hasBlocked($profile) ||
($originalProfile && $user->hasBlocked($originalProfile))) {
unset($ni[$id]);
foreach ($ni as $id => $source) {
$user = User::staticGet('id', $id);
if (empty($user) || $user->hasBlocked($profile) ||
($originalProfile && $user->hasBlocked($originalProfile))) {
unset($ni[$id]);
}
}
// Give plugins a chance to filter out...
Event::handle('EndNoticeWhoGets', array($this, &$ni));
}
if (!empty($c)) {
......@@ -1999,6 +2006,11 @@ class Notice extends Memcached_DataObject
$this->is_local == Notice::LOCAL_NONPUBLIC);
}
/**
* Get the list of hash tags saved with this notice.
*
* @return array of strings
*/
public function getTags()
{
$tags = array();
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
/* Afrikaans initialisation for the jQuery UI date picker plugin. */
/* Written by Renier Pretorius. *