PluginProbe
ActivityPub / 9.2.1
ActivityPub v9.2.1
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
← All changes | includes/activity/class-activity.php +184 -90 1.2.09.2.1 View file →
@@ -2,13 +2,16 @@
2 2 /**
3 3 * Inspired by the PHP ActivityPub Library by @Landrok
4 4 *
5 5 * @link https://github.com/landrok/activitypub
6 + *
7 + * @package Activitypub
6 8 */
7 9
8 10 namespace Activitypub\Activity;
9 11
10 -use Activitypub\Activity\Base_Object;
12 +use Activitypub\Activity\Extended_Object\Event;
13 +use Activitypub\Activity\Extended_Object\Place;
11 14
12 15 /**
13 16 * \Activitypub\Activity\Activity implements the common
14 17 * attributes of an Activity.
@@ -14,81 +17,82 @@
14 17 * attributes of an Activity.
15 18 *
16 19 * @see https://www.w3.org/TR/activitystreams-core/#activities
17 20 * @see https://www.w3.org/TR/activitystreams-core/#intransitiveactivities
21 + *
22 + * @method string|array get_actor() Gets one or more entities that performed or are expected to perform the activity.
23 + * @method string|array|null get_instrument() Gets one or more objects used in the completion of an Activity.
24 + * @method Base_Object|string|array|null get_object() Gets the direct object of the activity.
25 + * @method string|string[]|null get_origin() Gets the origin property of the activity.
26 + * @method array|null get_replies() Gets the collection of responses to this activity.
27 + * @method string|null get_result() Gets the result property of the activity.
28 + * @method string|string[]|null get_target() Gets the target property of the activity.
29 + *
30 + * @method Activity set_actor( string|array $actor ) Sets one or more entities that performed the activity.
31 + * @method Activity set_instrument( string|array $instrument ) Sets one or more objects used in the completion of an Activity.
32 + * @method Activity set_origin( string|array|null $origin ) Sets the origin property of the activity.
33 + * @method Activity set_replies( array $replies ) Sets the collection of responses to this activity.
34 + * @method Activity set_result( string|null $result ) Sets the result property of the activity.
35 + * @method Activity set_target( string|array|null $target ) Sets the target property of the activity.
18 36 */
19 37 class Activity extends Base_Object {
20 - const CONTEXT = array(
38 + const JSON_LD_CONTEXT = array(
21 39 'https://www.w3.org/ns/activitystreams',
22 - 'https://w3id.org/security/v1',
23 40 array(
24 - 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
25 - 'PropertyValue' => 'schema:PropertyValue',
26 - 'schema' => 'http://schema.org#',
27 - 'pt' => 'https://joinpeertube.org/ns#',
28 - 'toot' => 'http://joinmastodon.org/ns#',
29 - 'webfinger' => 'https://webfinger.net/#',
30 - 'litepub' => 'http://litepub.social/ns#',
31 - 'lemmy' => 'https://join-lemmy.org/ns#',
32 - 'value' => 'schema:value',
33 - 'Hashtag' => 'as:Hashtag',
34 - 'featured' => array(
35 - '@id' => 'toot:featured',
36 - '@type' => '@id',
37 - ),
38 - 'featuredTags' => array(
39 - '@id' => 'toot:featuredTags',
40 - '@type' => '@id',
41 - ),
42 - 'alsoKnownAs' => array(
43 - '@id' => 'as:alsoKnownAs',
44 - '@type' => '@id',
45 - ),
46 - 'moderators' => array(
47 - '@id' => 'lemmy:moderators',
48 - '@type' => '@id',
49 - ),
50 - 'postingRestrictedToMods' => 'lemmy:postingRestrictedToMods',
51 - 'discoverable' => 'toot:discoverable',
52 - 'indexable' => 'toot:indexable',
53 - 'sensitive' => 'as:sensitive',
54 - 'resource' => 'webfinger:resource',
41 + 'toot' => 'http://joinmastodon.org/ns#',
42 + 'QuoteRequest' => 'toot:QuoteRequest',
43 + 'blurhash' => 'toot:blurhash',
44 + 'FeatureRequest' => 'https://w3id.org/fep/7aa9#FeatureRequest',
55 45 ),
56 46 );
57 47
58 48 /**
59 - * The object's unique global identifier
49 + * The default types for Activities.
60 50 *
61 - * @see https://www.w3.org/TR/activitypub/#obj-id
51 + * @see https://www.w3.org/TR/activitystreams-vocabulary/#activity-types
62 52 *
63 - * @var string
53 + * @var array
64 54 */
65 - protected $id;
55 + const TYPES = array(
56 + 'Accept',
57 + 'Add',
58 + 'Announce',
59 + 'Arrive',
60 + 'Block',
61 + 'Create',
62 + 'Delete',
63 + 'Dislike',
64 + 'Follow',
65 + 'Flag',
66 + 'Ignore',
67 + 'Invite',
68 + 'Join',
69 + 'Leave',
70 + 'Like',
71 + 'Listen',
72 + 'Move',
73 + 'Offer',
74 + 'QuoteRequest', // @see https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md
75 + 'FeatureRequest', // @see https://w3id.org/fep/7aa9 (FEP-7aa9 draft)
76 + 'Read',
77 + 'Reject',
78 + 'Remove',
79 + 'TentativeAccept',
80 + 'TentativeReject',
81 + 'Travel',
82 + 'Undo',
83 + 'Update',
84 + 'View',
85 + );
66 86
67 87 /**
88 + * The type of the object.
89 + *
68 90 * @var string
69 91 */
70 92 protected $type = 'Activity';
71 93
72 94 /**
73 - * The context within which the object exists or an activity was
74 - * performed.
75 - * The notion of "context" used is intentionally vague.
76 - * The intended function is to serve as a means of grouping objects
77 - * and activities that share a common originating context or
78 - * purpose. An example could be all activities relating to a common
79 - * project or event.
80 - *
81 - * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-context
82 - *
83 - * @var string
84 - * | ObjectType
85 - * | Link
86 - * | null
87 - */
88 - protected $context = self::CONTEXT;
89 -
90 - /**
91 95 * Describes the direct object of the activity.
92 96 * For instance, in the activity "John added a movie to his
93 97 * wishlist", the object of the activity is the movie added.
94 98 *
@@ -93,12 +97,9 @@
93 97 * wishlist", the object of the activity is the movie added.
94 98 *
95 99 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object-term
96 100 *
97 - * @var string
98 - * | Base_Objectr
99 - * | Link
100 - * | null
101 + * @var string|Base_Object|array|null
101 102 */
102 103 protected $object;
103 104
104 105 /**
@@ -108,13 +109,9 @@
108 109 * The actor MAY be specified using an indirect Link.
109 110 *
110 111 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-actor
111 112 *
112 - * @var string
113 - * | \ActivityPhp\Type\Extended\AbstractActor
114 - * | array<Actor>
115 - * | array<Link>
116 - * | Link
113 + * @var string|array
117 114 */
118 115 protected $actor;
119 116
120 117 /**
@@ -127,13 +124,9 @@
127 124 * An activity can have more than one target.
128 125 *
129 126 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-target
130 127 *
131 - * @var string
132 - * | ObjectType
133 - * | array<ObjectType>
134 - * | Link
135 - * | array<Link>
128 + * @var string|array|null
136 129 */
137 130 protected $target;
138 131
139 132 /**
@@ -143,16 +136,25 @@
143 136 * that new resource.
144 137 *
145 138 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-result
146 139 *
147 - * @var string
148 - * | ObjectType
149 - * | Link
150 - * | null
140 + * @var string|Base_Object|null
151 141 */
152 142 protected $result;
153 143
154 144 /**
145 + * Identifies a Collection containing objects considered to be responses
146 + * to this object.
147 + * WordPress has a strong core system of approving replies. We only include
148 + * approved replies here.
149 + *
150 + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-replies
151 + *
152 + * @var array|null
153 + */
154 + protected $replies;
155 +
156 + /**
155 157 * An indirect object of the activity from which the
156 158 * activity is directed.
157 159 * The precise meaning of the origin is the object of the English
158 160 * preposition "from".
@@ -160,12 +162,9 @@
160 162 * from List A", the origin of the activity is "List A".
161 163 *
162 164 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-origin
163 165 *
164 - * @var string
165 - * | ObjectType
166 - * | Link
167 - * | null
166 + * @var string|array|null
168 167 */
169 168 protected $origin;
170 169
171 170 /**
@@ -173,12 +172,9 @@
173 172 * Activity.
174 173 *
175 174 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-instrument
176 175 *
177 - * @var string
178 - * | ObjectType
179 - * | Link
180 - * | null
176 + * @var string|array|null
181 177 */
182 178 protected $instrument;
183 179
184 180 /**
@@ -184,25 +180,53 @@
184 180 /**
185 181 * Set the object and copy Object properties to the Activity.
186 182 *
187 183 * Any to, bto, cc, bcc, and audience properties specified on the object
188 - * MUST be copied over to the new Create activity by the server.
184 + * MUST be copied over to the new "Create" activity by the server.
189 185 *
190 186 * @see https://www.w3.org/TR/activitypub/#object-without-create
191 187 *
192 - * @param string|Base_Objectr|Link|null $object
193 - *
194 - * @return void
188 + * @param array|string|Base_Object|Activity|Actor|null $data Activity object.
195 189 */
196 - public function set_object( $object ) {
190 + public function set_object( $data ) {
191 + $object = $data;
192 +
193 + // Convert array to appropriate object type.
194 + if ( \is_array( $data ) ) {
195 + if ( \array_is_list( $data ) ) {
196 + $object = \array_map( array( $this, 'maybe_convert_to_object' ), $data );
197 + } else {
198 + $object = $this->maybe_convert_to_object( $data );
199 + }
200 + }
201 +
197 202 $this->set( 'object', $object );
203 + $this->pre_fill_activity_from_object();
204 + }
198 205
199 - if ( ! is_object( $object ) ) {
206 + /**
207 + * Fills the Activity with the specified activity object.
208 + */
209 + public function pre_fill_activity_from_object() {
210 + $object = $this->get_object();
211 +
212 + // Check if `$object` is a URL and use it to generate an ID then.
213 + if ( \is_string( $object ) && \filter_var( $object, FILTER_VALIDATE_URL ) && ! $this->get_id() ) {
214 + $this->set( 'id', $object . '#activity-' . \strtolower( $this->get_type() ) . '-' . \time() );
215 +
200 216 return;
201 217 }
202 218
219 + // Check if `$object` is an object and copy some properties otherwise do nothing.
220 + if ( ! \is_object( $object ) ) {
221 + return;
222 + }
223 +
203 224 foreach ( array( 'to', 'bto', 'cc', 'bcc', 'audience' ) as $i ) {
204 - $this->set( $i, $object->get( $i ) );
225 + $value = $object->get( $i );
226 + if ( $value && ! $this->get( $i ) ) {
227 + $this->set( $i, $value );
228 + }
205 229 }
206 230
207 231 if ( $object->get_published() && ! $this->get_published() ) {
208 232 $this->set( 'published', $object->get_published() );
@@ -215,9 +239,79 @@
215 239 if ( $object->get_attributed_to() && ! $this->get_actor() ) {
216 240 $this->set( 'actor', $object->get_attributed_to() );
217 241 }
218 242
243 + if ( $this->get_type() !== 'Announce' && $object->get_in_reply_to() && ! $this->get_in_reply_to() ) {
244 + $this->set( 'in_reply_to', $object->get_in_reply_to() );
245 + }
246 +
247 + if ( $object->get_interaction_policy() && ! $this->get_interaction_policy() ) {
248 + $this->set( 'interaction_policy', $object->get_interaction_policy() );
249 + }
250 +
219 251 if ( $object->get_id() && ! $this->get_id() ) {
220 - $this->set( 'id', $object->get_id() . '#activity' );
252 + $id = \strtok( $object->get_id(), '#' );
253 + if ( $object->get_updated() ) {
254 + $updated = $object->get_updated();
255 + } elseif ( $object->get_published() ) {
256 + $updated = $object->get_published();
257 + } else {
258 + $updated = \time();
259 + }
260 + $this->set( 'id', $id . '#activity-' . \strtolower( $this->get_type() ) . '-' . $updated );
221 261 }
262 + }
263 +
264 + /**
265 + * The context of an Activity is usually just the context of the object it contains.
266 + *
267 + * @return array $context A compacted JSON-LD context.
268 + */
269 + public function get_json_ld_context() {
270 + if ( \is_object( $this->object ) ) {
271 + $class = \get_class( $this->object );
272 + if ( $class && $class::JSON_LD_CONTEXT ) {
273 + // Without php 5.6 support this could be just: 'return $this->object::JSON_LD_CONTEXT;'.
274 + return $class::JSON_LD_CONTEXT;
275 + }
276 + }
277 +
278 + return static::JSON_LD_CONTEXT;
279 + }
280 +
281 + /**
282 + * Convert data to the appropriate object type if it has an ActivityPub type.
283 + *
284 + * @param array|string|Base_Object|Activity|Actor|null $data The data to convert.
285 + *
286 + * @return Activity|Actor|Base_Object|Generic_Object|string|\WP_Error|null The converted object or original data.
287 + */
288 + private function maybe_convert_to_object( $data ) {
289 + if ( ! \is_array( $data ) ) {
290 + return $data;
291 + }
292 +
293 + $type = $data['type'] ?? null;
294 +
295 + if ( \in_array( $type, self::TYPES, true ) ) {
296 + $object = self::init_from_array( $data );
297 + } elseif ( \in_array( $type, Actor::TYPES, true ) ) {
298 + $object = Actor::init_from_array( $data );
299 + } elseif ( \in_array( $type, Base_Object::TYPES, true ) ) {
300 + switch ( $type ) {
301 + case 'Event':
302 + $object = Event::init_from_array( $data );
303 + break;
304 + case 'Place':
305 + $object = Place::init_from_array( $data );
306 + break;
307 + default:
308 + $object = Base_Object::init_from_array( $data );
309 + break;
310 + }
311 + } else {
312 + $object = Generic_Object::init_from_array( $data );
313 + }
314 +
315 + return $object;
222 316 }
223 317 }