diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php index 0057693068..9696ea3615 100644 --- a/actions/apitimelineuser.php +++ b/actions/apitimelineuser.php @@ -420,9 +420,9 @@ class ApiTimelineUserAction extends ApiBareAuthAction // 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); diff --git a/classes/Message.php b/classes/Message.php index c5aefcc4e8..211284ecec 100644 --- a/classes/Message.php +++ b/classes/Message.php @@ -198,8 +198,7 @@ class Message extends Managed_DataObject throw new Exception(sprintf("Receiver profile not found: %d", $this->to_profile)); } - $ctx->attention[] = $rprofile->getUri(); - $ctx->attentionType[$rprofile->getUri()] = ActivityObject::PERSON; + $ctx->attention[$rprofile->getUri()] = ActivityObject::PERSON; $act->context = $ctx; diff --git a/classes/Notice.php b/classes/Notice.php index d3c56bac54..df05ce4650 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -1577,27 +1577,23 @@ class Notice extends Managed_DataObject foreach ($reply_ids as $id) { $rprofile = Profile::getKV('id', $id); if ($rprofile instanceof Profile) { - $ctx->attention[] = $rprofile->getUri(); - $ctx->attentionType[$rprofile->getUri()] = ActivityObject::PERSON; + $ctx->attention[$rprofile->getUri()] = ActivityObject::PERSON; } } $groups = $this->getGroups(); foreach ($groups as $group) { - $ctx->attention[] = $group->getUri(); - $ctx->attentionType[$group->getUri()] = ActivityObject::GROUP; + $ctx->attention[$group->getUri()] = ActivityObject::GROUP; } switch ($this->scope) { case Notice::PUBLIC_SCOPE: - $ctx->attention[] = "http://activityschema.org/collection/public"; - $ctx->attentionType["http://activityschema.org/collection/public"] = ActivityObject::COLLECTION; + $ctx->attention[ActivityContext::ATTN_PUBLIC] = ActivityObject::COLLECTION; break; case Notice::FOLLOWER_SCOPE: $surl = common_local_url("subscribers", array('nickname' => $profile->nickname)); - $ctx->attention[] = $surl; - $ctx->attentionType[$surl] = ActivityObject::COLLECTION; + $ctx->attention[$surl] = ActivityObject::COLLECTION; break; } diff --git a/lib/activity.php b/lib/activity.php index eaa7cf1c2d..8be37c5681 100644 --- a/lib/activity.php +++ b/lib/activity.php @@ -626,8 +626,9 @@ class Activity 'href' => $this->context->conversation)); } - foreach ($this->context->attention as $attnURI) { + foreach ($this->context->attention as $attnURI=>$type) { $xs->element('link', array('rel' => ActivityContext::MENTIONED, + ActivityContext::OBJECTTYPE => $type, // FIXME: undocumented 'href' => $attnURI)); } diff --git a/lib/activitycontext.php b/lib/activitycontext.php index 371eab3e64..cebd72ea90 100644 --- a/lib/activitycontext.php +++ b/lib/activitycontext.php @@ -37,8 +37,7 @@ class ActivityContext public $replyToID; public $replyToUrl; public $location; - public $attention = array(); - public $attentionType = array(); + public $attention = array(); // 'uri' => 'type' public $conversation; public $scope; @@ -46,15 +45,18 @@ class ActivityContext const GEORSS = 'http://www.georss.org/georss'; const OSTATUS = 'http://ostatus.org/schema/1.0'; - const INREPLYTO = 'in-reply-to'; - const REF = 'ref'; - const HREF = 'href'; + const INREPLYTO = 'in-reply-to'; + const REF = 'ref'; + const HREF = 'href'; + const OBJECTTYPE = 'ostatus:object-type'; // FIXME: Undocumented! const POINT = 'point'; const MENTIONED = 'mentioned'; const CONVERSATION = 'ostatus:conversation'; + const ATTN_PUBLIC = 'http://activityschema.org/collection/public'; + function __construct($element = null) { if (empty($element)) { @@ -76,17 +78,15 @@ class ActivityContext $links = $element->getElementsByTagNameNS(ActivityUtils::ATOM, ActivityUtils::LINK); - $attention = array(); for ($i = 0; $i < $links->length; $i++) { $link = $links->item($i); - $linkRel = $link->getAttribute(ActivityUtils::REL); - - if ($linkRel == self::MENTIONED) { - $attention[] = $link->getAttribute(self::HREF); + $linkRel = $link->getAttribute(ActivityUtils::REL); + $linkHref = $link->getAttribute(self::HREF); + if ($linkRel == self::MENTIONED && $linkHref !== '') { + $this->attention[$linkHref] = $link->getAttribute(ActivityContext::OBJECTTYPE); } } - $this->attention = array_unique($attention); } /** @@ -159,15 +159,10 @@ class ActivityContext { $tos = array(); - foreach ($this->attention as $attnUrl) { - if (array_key_exists($attnUrl, $this->attentionType)) { - $type = ActivityObject::canonicalType($this->attentionType[$attnUrl]); - } else { - $type = ActivityObject::canonicalType(ActivityObject::PERSON); - } + foreach ($this->attention as $attnUrl => $attnType) { $to = array( - 'objectType' => $type, - 'id' => $attnUrl + 'objectType' => $attnType, // can be empty + 'id' => $attnUrl, ); $tos[] = $to; } diff --git a/lib/activityimporter.php b/lib/activityimporter.php index c2bdc447b5..1c34b64d35 100644 --- a/lib/activityimporter.php +++ b/lib/activityimporter.php @@ -290,19 +290,19 @@ class ActivityImporter extends QueueHandler return $saved; } - function filterAttention($attn) + protected function filterAttention(array $attn) { - $groups = array(); - $replies = array(); + $groups = array(); // TODO: context->attention + $replies = array(); // TODO: context->attention - foreach (array_unique($attn) as $recipient) { + foreach ($attn as $recipient=>$type) { // Is the recipient a local user? $user = User::getKV('uri', $recipient); - if ($user) { - // @fixme sender verification, spam etc? + if ($user instanceof User) { + // TODO: @fixme sender verification, spam etc? $replies[] = $recipient; continue; } @@ -319,7 +319,7 @@ class ActivityImporter extends QueueHandler } // 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); $id = OStatusPlugin::localGroupFromUrl($recipient); diff --git a/lib/microappplugin.php b/lib/microappplugin.php index 30542ffa73..3ed9a76e95 100644 --- a/lib/microappplugin.php +++ b/lib/microappplugin.php @@ -390,10 +390,10 @@ abstract class MicroAppPlugin extends Plugin if ($target instanceof User_group) { $uri = $target->getUri(); - if (!in_array($uri, $activity->context->attention)) { + if (!array_key_exists($uri, $activity->context->attention)) { // @todo FIXME: please document (i18n). // 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) { $uri = $target->uri; @@ -402,7 +402,7 @@ abstract class MicroAppPlugin extends Plugin $original = Notice::getKV('uri', $activity->context->replyToID); } - if (!in_array($uri, $activity->context->attention) && + if (!array_key_exists($uri, $activity->context->attention) && (empty($original) || $original->profile_id != $target->id)) { // @todo FIXME: Please document (i18n). diff --git a/plugins/Bookmark/BookmarkPlugin.php b/plugins/Bookmark/BookmarkPlugin.php index 6dacdb085e..6461227f98 100644 --- a/plugins/Bookmark/BookmarkPlugin.php +++ b/plugins/Bookmark/BookmarkPlugin.php @@ -450,19 +450,19 @@ class BookmarkPlugin extends MicroAppPlugin } } - $replies = $activity->context->attention; - $options['groups'] = array(); - $options['replies'] = array(); + $options['replies'] = array(); // TODO: context->attention - foreach ($replies as $replyURI) { - $other = Profile::fromURI($replyURI); - if (!empty($other)) { - $options['replies'][] = $replyURI; + foreach ($activity->context->attention as $attnUrl=>$type) { + $other = Profile::fromURI($attnUrl); + if ($other instanceof Profile) { + $options['replies'][] = $attnUrl; } else { - $group = User_group::getKV('uri', $replyURI); - if (!empty($group)) { - $options['groups'][] = $replyURI; + // Maybe we can get rid of this since every User_group got a Profile? + // TODO: Make sure the above replies get sorted properly for groups (or handled afterwards) + $group = User_group::getKV('uri', $attnUrl); + if ($group instanceof User_group) { + $options['groups'][] = $attnUrl; } } } diff --git a/plugins/OStatus/actions/groupsalmon.php b/plugins/OStatus/actions/groupsalmon.php index 14e66f5ca0..c8b2a73b68 100644 --- a/plugins/OStatus/actions/groupsalmon.php +++ b/plugins/OStatus/actions/groupsalmon.php @@ -78,14 +78,13 @@ class GroupsalmonAction extends SalmonAction } // Notice must be to the attention of this group - $context = $this->activity->context; - - if (empty($context->attention)) { + if (empty($this->activity->context->attention)) { // TRANS: Client exception. throw new ClientException("Not to the attention of anyone."); } else { $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. throw new ClientException("Not to the attention of this group."); } diff --git a/plugins/OStatus/actions/usersalmon.php b/plugins/OStatus/actions/usersalmon.php index ed2c7b3d5f..296fd6c6c7 100644 --- a/plugins/OStatus/actions/usersalmon.php +++ b/plugins/OStatus/actions/usersalmon.php @@ -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.')); } } else if (!empty($context->attention)) { - if (!in_array($this->user->uri, $context->attention) && - !in_array(common_profile_url($this->user->nickname), $context->attention)) { - common_log(LOG_ERR, "{$this->user->uri} not in attention list (".implode(',', $context->attention).")"); + if (!array_key_exists($this->user->uri, $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(',', array_keys($context->attention)).')'); // TRANS: Client exception. throw new ClientException(_m('To the attention of user(s), not including this one.')); } diff --git a/plugins/OStatus/classes/Ostatus_profile.php b/plugins/OStatus/classes/Ostatus_profile.php index 0edb45f825..1e49323653 100644 --- a/plugins/OStatus/classes/Ostatus_profile.php +++ b/plugins/OStatus/classes/Ostatus_profile.php @@ -656,10 +656,9 @@ class Ostatus_profile extends Managed_DataObject } if ($activity->context) { - // Any individual or group attn: targets? - $replies = $activity->context->attention; - $options['groups'] = $this->filterReplies($oprofile, $replies); - $options['replies'] = $replies; + // TODO: context->attention + list($options['groups'], $options['replies']) + = $this->filterReplies($oprofile, $activity->context->attention); // Maintain direct reply associations // @todo FIXME: What about conversation ID? @@ -826,10 +825,9 @@ class Ostatus_profile extends Managed_DataObject } if ($activity->context) { - // Any individual or group attn: targets? - $replies = $activity->context->attention; - $options['groups'] = $this->filterReplies($oprofile, $replies); - $options['replies'] = $replies; + // TODO: context->attention + list($options['groups'], $options['replies']) + = $this->filterReplies($oprofile, $activity->context->attention); // Maintain direct reply associations // @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 * @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(); $replies = array(); - foreach (array_unique($attention_uris) as $recipient) { + foreach ($attention as $recipient=>$type) { // Is the recipient a local user? $user = User::getKV('uri', $recipient); - if ($user) { + if ($user instanceof User) { // @todo FIXME: Sender verification, spam etc? $replies[] = $recipient; continue; } // Is the recipient a local group? - // $group = User_group::getKV('uri', $recipient); + // TODO: $group = User_group::getKV('uri', $recipient); $id = OStatusPlugin::localGroupFromUrl($recipient); if ($id) { $group = User_group::getKV('id', $id); - if ($group) { + if ($group instanceof User_group) { // Deliver to all members of this local group if allowed. $profile = $sender->localProfile(); 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 group recipients: " . implode(', ', $groups)); - return $groups; + return array($groups, $replies); } /** diff --git a/tests/ActivityParseTests.php b/tests/ActivityParseTests.php index 71b90aadb6..27b751b75e 100644 --- a/tests/ActivityParseTests.php +++ b/tests/ActivityParseTests.php @@ -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->replyToUrl); $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->assertEquals($act->objects[0]->content,