Reworked the ActivityContext->attention structure

Removing Evan's obscure attentionType solution and directly using the attention array
This commit is contained in:
Mikael Nordfeldth 2013-10-28 22:21:14 +01:00
parent f99c4b7f07
commit 23a6b4595f
12 changed files with 63 additions and 76 deletions

View File

@ -420,9 +420,9 @@ class ApiTimelineUserAction extends ApiBareAuthAction
// Check for optional attributes... // Check for optional attributes...
if (!empty($activity->context)) { if ($activity->context instanceof ActivityContext) {
foreach ($activity->context->attention as $uri) { foreach ($activity->context->attention as $uri=>$type) {
$profile = Profile::fromURI($uri); $profile = Profile::fromURI($uri);

View File

@ -198,8 +198,7 @@ class Message extends Managed_DataObject
throw new Exception(sprintf("Receiver profile not found: %d", $this->to_profile)); throw new Exception(sprintf("Receiver profile not found: %d", $this->to_profile));
} }
$ctx->attention[] = $rprofile->getUri(); $ctx->attention[$rprofile->getUri()] = ActivityObject::PERSON;
$ctx->attentionType[$rprofile->getUri()] = ActivityObject::PERSON;
$act->context = $ctx; $act->context = $ctx;

View File

@ -1577,27 +1577,23 @@ class Notice extends Managed_DataObject
foreach ($reply_ids as $id) { foreach ($reply_ids as $id) {
$rprofile = Profile::getKV('id', $id); $rprofile = Profile::getKV('id', $id);
if ($rprofile instanceof Profile) { if ($rprofile instanceof Profile) {
$ctx->attention[] = $rprofile->getUri(); $ctx->attention[$rprofile->getUri()] = ActivityObject::PERSON;
$ctx->attentionType[$rprofile->getUri()] = ActivityObject::PERSON;
} }
} }
$groups = $this->getGroups(); $groups = $this->getGroups();
foreach ($groups as $group) { foreach ($groups as $group) {
$ctx->attention[] = $group->getUri(); $ctx->attention[$group->getUri()] = ActivityObject::GROUP;
$ctx->attentionType[$group->getUri()] = ActivityObject::GROUP;
} }
switch ($this->scope) { switch ($this->scope) {
case Notice::PUBLIC_SCOPE: case Notice::PUBLIC_SCOPE:
$ctx->attention[] = "http://activityschema.org/collection/public"; $ctx->attention[ActivityContext::ATTN_PUBLIC] = ActivityObject::COLLECTION;
$ctx->attentionType["http://activityschema.org/collection/public"] = ActivityObject::COLLECTION;
break; break;
case Notice::FOLLOWER_SCOPE: case Notice::FOLLOWER_SCOPE:
$surl = common_local_url("subscribers", array('nickname' => $profile->nickname)); $surl = common_local_url("subscribers", array('nickname' => $profile->nickname));
$ctx->attention[] = $surl; $ctx->attention[$surl] = ActivityObject::COLLECTION;
$ctx->attentionType[$surl] = ActivityObject::COLLECTION;
break; break;
} }

View File

@ -626,8 +626,9 @@ class Activity
'href' => $this->context->conversation)); 'href' => $this->context->conversation));
} }
foreach ($this->context->attention as $attnURI) { foreach ($this->context->attention as $attnURI=>$type) {
$xs->element('link', array('rel' => ActivityContext::MENTIONED, $xs->element('link', array('rel' => ActivityContext::MENTIONED,
ActivityContext::OBJECTTYPE => $type, // FIXME: undocumented
'href' => $attnURI)); 'href' => $attnURI));
} }

View File

@ -37,8 +37,7 @@ class ActivityContext
public $replyToID; public $replyToID;
public $replyToUrl; public $replyToUrl;
public $location; public $location;
public $attention = array(); public $attention = array(); // 'uri' => 'type'
public $attentionType = array();
public $conversation; public $conversation;
public $scope; public $scope;
@ -46,15 +45,18 @@ class ActivityContext
const GEORSS = 'http://www.georss.org/georss'; const GEORSS = 'http://www.georss.org/georss';
const OSTATUS = 'http://ostatus.org/schema/1.0'; const OSTATUS = 'http://ostatus.org/schema/1.0';
const INREPLYTO = 'in-reply-to'; const INREPLYTO = 'in-reply-to';
const REF = 'ref'; const REF = 'ref';
const HREF = 'href'; const HREF = 'href';
const OBJECTTYPE = 'ostatus:object-type'; // FIXME: Undocumented!
const POINT = 'point'; const POINT = 'point';
const MENTIONED = 'mentioned'; const MENTIONED = 'mentioned';
const CONVERSATION = 'ostatus:conversation'; const CONVERSATION = 'ostatus:conversation';
const ATTN_PUBLIC = 'http://activityschema.org/collection/public';
function __construct($element = null) function __construct($element = null)
{ {
if (empty($element)) { if (empty($element)) {
@ -76,17 +78,15 @@ class ActivityContext
$links = $element->getElementsByTagNameNS(ActivityUtils::ATOM, ActivityUtils::LINK); $links = $element->getElementsByTagNameNS(ActivityUtils::ATOM, ActivityUtils::LINK);
$attention = array();
for ($i = 0; $i < $links->length; $i++) { for ($i = 0; $i < $links->length; $i++) {
$link = $links->item($i); $link = $links->item($i);
$linkRel = $link->getAttribute(ActivityUtils::REL); $linkRel = $link->getAttribute(ActivityUtils::REL);
$linkHref = $link->getAttribute(self::HREF);
if ($linkRel == self::MENTIONED) { if ($linkRel == self::MENTIONED && $linkHref !== '') {
$attention[] = $link->getAttribute(self::HREF); $this->attention[$linkHref] = $link->getAttribute(ActivityContext::OBJECTTYPE);
} }
} }
$this->attention = array_unique($attention);
} }
/** /**
@ -159,15 +159,10 @@ class ActivityContext
{ {
$tos = array(); $tos = array();
foreach ($this->attention as $attnUrl) { foreach ($this->attention as $attnUrl => $attnType) {
if (array_key_exists($attnUrl, $this->attentionType)) {
$type = ActivityObject::canonicalType($this->attentionType[$attnUrl]);
} else {
$type = ActivityObject::canonicalType(ActivityObject::PERSON);
}
$to = array( $to = array(
'objectType' => $type, 'objectType' => $attnType, // can be empty
'id' => $attnUrl 'id' => $attnUrl,
); );
$tos[] = $to; $tos[] = $to;
} }

View File

@ -290,19 +290,19 @@ class ActivityImporter extends QueueHandler
return $saved; return $saved;
} }
function filterAttention($attn) protected function filterAttention(array $attn)
{ {
$groups = array(); $groups = array(); // TODO: context->attention
$replies = array(); $replies = array(); // TODO: context->attention
foreach (array_unique($attn) as $recipient) { foreach ($attn as $recipient=>$type) {
// Is the recipient a local user? // Is the recipient a local user?
$user = User::getKV('uri', $recipient); $user = User::getKV('uri', $recipient);
if ($user) { if ($user instanceof User) {
// @fixme sender verification, spam etc? // TODO: @fixme sender verification, spam etc?
$replies[] = $recipient; $replies[] = $recipient;
continue; continue;
} }
@ -319,7 +319,7 @@ class ActivityImporter extends QueueHandler
} }
// Is the recipient a local group? // Is the recipient a local group?
// @fixme uri on user_group isn't reliable yet // TODO: @fixme uri on user_group isn't reliable yet
// $group = User_group::getKV('uri', $recipient); // $group = User_group::getKV('uri', $recipient);
$id = OStatusPlugin::localGroupFromUrl($recipient); $id = OStatusPlugin::localGroupFromUrl($recipient);

View File

@ -390,10 +390,10 @@ abstract class MicroAppPlugin extends Plugin
if ($target instanceof User_group) { if ($target instanceof User_group) {
$uri = $target->getUri(); $uri = $target->getUri();
if (!in_array($uri, $activity->context->attention)) { if (!array_key_exists($uri, $activity->context->attention)) {
// @todo FIXME: please document (i18n). // @todo FIXME: please document (i18n).
// TRANS: Client exception thrown when ... // TRANS: Client exception thrown when ...
throw new ClientException(_('Bookmark not posted to this group.')); throw new ClientException(_('Object not posted to this group.'));
} }
} else if ($target instanceof User) { } else if ($target instanceof User) {
$uri = $target->uri; $uri = $target->uri;
@ -402,7 +402,7 @@ abstract class MicroAppPlugin extends Plugin
$original = Notice::getKV('uri', $original = Notice::getKV('uri',
$activity->context->replyToID); $activity->context->replyToID);
} }
if (!in_array($uri, $activity->context->attention) && if (!array_key_exists($uri, $activity->context->attention) &&
(empty($original) || (empty($original) ||
$original->profile_id != $target->id)) { $original->profile_id != $target->id)) {
// @todo FIXME: Please document (i18n). // @todo FIXME: Please document (i18n).

View File

@ -450,19 +450,19 @@ class BookmarkPlugin extends MicroAppPlugin
} }
} }
$replies = $activity->context->attention;
$options['groups'] = array(); $options['groups'] = array();
$options['replies'] = array(); $options['replies'] = array(); // TODO: context->attention
foreach ($replies as $replyURI) { foreach ($activity->context->attention as $attnUrl=>$type) {
$other = Profile::fromURI($replyURI); $other = Profile::fromURI($attnUrl);
if (!empty($other)) { if ($other instanceof Profile) {
$options['replies'][] = $replyURI; $options['replies'][] = $attnUrl;
} else { } else {
$group = User_group::getKV('uri', $replyURI); // Maybe we can get rid of this since every User_group got a Profile?
if (!empty($group)) { // TODO: Make sure the above replies get sorted properly for groups (or handled afterwards)
$options['groups'][] = $replyURI; $group = User_group::getKV('uri', $attnUrl);
if ($group instanceof User_group) {
$options['groups'][] = $attnUrl;
} }
} }
} }

View File

@ -78,14 +78,13 @@ class GroupsalmonAction extends SalmonAction
} }
// Notice must be to the attention of this group // Notice must be to the attention of this group
$context = $this->activity->context; if (empty($this->activity->context->attention)) {
if (empty($context->attention)) {
// TRANS: Client exception. // TRANS: Client exception.
throw new ClientException("Not to the attention of anyone."); throw new ClientException("Not to the attention of anyone.");
} else { } else {
$uri = common_local_url('groupbyid', array('id' => $this->group->id)); $uri = common_local_url('groupbyid', array('id' => $this->group->id));
if (!in_array($uri, $context->attention)) {
if (!array_key_exists($uri, $this->activity->context->attention)) {
// TRANS: Client exception. // TRANS: Client exception.
throw new ClientException("Not to the attention of this group."); throw new ClientException("Not to the attention of this group.");
} }

View File

@ -91,9 +91,9 @@ class UsersalmonAction extends SalmonAction
throw new ClientException(_m('In reply to a notice not by this user and not mentioning this user.')); throw new ClientException(_m('In reply to a notice not by this user and not mentioning this user.'));
} }
} else if (!empty($context->attention)) { } else if (!empty($context->attention)) {
if (!in_array($this->user->uri, $context->attention) && if (!array_key_exists($this->user->uri, $context->attention) &&
!in_array(common_profile_url($this->user->nickname), $context->attention)) { !array_key_exists(common_profile_url($this->user->nickname), $context->attention)) {
common_log(LOG_ERR, "{$this->user->uri} not in attention list (".implode(',', $context->attention).")"); common_log(LOG_ERR, "{$this->user->uri} not in attention list (".implode(',', array_keys($context->attention)).')');
// TRANS: Client exception. // TRANS: Client exception.
throw new ClientException(_m('To the attention of user(s), not including this one.')); throw new ClientException(_m('To the attention of user(s), not including this one.'));
} }

View File

@ -656,10 +656,9 @@ class Ostatus_profile extends Managed_DataObject
} }
if ($activity->context) { if ($activity->context) {
// Any individual or group attn: targets? // TODO: context->attention
$replies = $activity->context->attention; list($options['groups'], $options['replies'])
$options['groups'] = $this->filterReplies($oprofile, $replies); = $this->filterReplies($oprofile, $activity->context->attention);
$options['replies'] = $replies;
// Maintain direct reply associations // Maintain direct reply associations
// @todo FIXME: What about conversation ID? // @todo FIXME: What about conversation ID?
@ -826,10 +825,9 @@ class Ostatus_profile extends Managed_DataObject
} }
if ($activity->context) { if ($activity->context) {
// Any individual or group attn: targets? // TODO: context->attention
$replies = $activity->context->attention; list($options['groups'], $options['replies'])
$options['groups'] = $this->filterReplies($oprofile, $replies); = $this->filterReplies($oprofile, $activity->context->attention);
$options['replies'] = $replies;
// Maintain direct reply associations // Maintain direct reply associations
// @todo FIXME: What about conversation ID? // @todo FIXME: What about conversation ID?
@ -908,26 +906,26 @@ class Ostatus_profile extends Managed_DataObject
* @param array in/out &$attention_uris set of URIs, will be pruned on output * @param array in/out &$attention_uris set of URIs, will be pruned on output
* @return array of group IDs * @return array of group IDs
*/ */
protected function filterReplies($sender, &$attention_uris) protected function filterReplies($sender, array $attention)
{ {
common_log(LOG_DEBUG, "Original reply recipients: " . implode(', ', $attention_uris)); common_log(LOG_DEBUG, "Original reply recipients: " . implode(', ', $attention));
$groups = array(); $groups = array();
$replies = array(); $replies = array();
foreach (array_unique($attention_uris) as $recipient) { foreach ($attention as $recipient=>$type) {
// Is the recipient a local user? // Is the recipient a local user?
$user = User::getKV('uri', $recipient); $user = User::getKV('uri', $recipient);
if ($user) { if ($user instanceof User) {
// @todo FIXME: Sender verification, spam etc? // @todo FIXME: Sender verification, spam etc?
$replies[] = $recipient; $replies[] = $recipient;
continue; continue;
} }
// Is the recipient a local group? // Is the recipient a local group?
// $group = User_group::getKV('uri', $recipient); // TODO: $group = User_group::getKV('uri', $recipient);
$id = OStatusPlugin::localGroupFromUrl($recipient); $id = OStatusPlugin::localGroupFromUrl($recipient);
if ($id) { if ($id) {
$group = User_group::getKV('id', $id); $group = User_group::getKV('id', $id);
if ($group) { if ($group instanceof User_group) {
// Deliver to all members of this local group if allowed. // Deliver to all members of this local group if allowed.
$profile = $sender->localProfile(); $profile = $sender->localProfile();
if ($profile->isMember($group)) { if ($profile->isMember($group)) {
@ -959,10 +957,9 @@ class Ostatus_profile extends Managed_DataObject
} }
} }
$attention_uris = $replies;
common_log(LOG_DEBUG, "Local reply recipients: " . implode(', ', $replies)); common_log(LOG_DEBUG, "Local reply recipients: " . implode(', ', $replies));
common_log(LOG_DEBUG, "Local group recipients: " . implode(', ', $groups)); common_log(LOG_DEBUG, "Local group recipients: " . implode(', ', $groups));
return $groups; return array($groups, $replies);
} }
/** /**

View File

@ -101,7 +101,7 @@ class ActivityParseTests extends PHPUnit_Framework_TestCase
$this->assertEquals('http://example.net/notice/12', $act->context->replyToID); $this->assertEquals('http://example.net/notice/12', $act->context->replyToID);
$this->assertEquals('http://example.net/notice/12', $act->context->replyToUrl); $this->assertEquals('http://example.net/notice/12', $act->context->replyToUrl);
$this->assertEquals('http://example.net/conversation/11', $act->context->conversation); $this->assertEquals('http://example.net/conversation/11', $act->context->conversation);
$this->assertEquals(array('http://example.net/user/1'), $act->context->attention); $this->assertEquals(array('http://example.net/user/1'), array_keys($act->context->attention));
$this->assertFalse(empty($act->objects[0])); $this->assertFalse(empty($act->objects[0]));
$this->assertEquals($act->objects[0]->content, $this->assertEquals($act->objects[0]->content,