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
activitypub / includes / activity / class-activity.php

class-activity.php in ActivityPub 9.2.1, at includes/activity/class-activity.php

318 lines 9.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Inspired by the PHP ActivityPub Library by @Landrok
4 *
5 * @link https://github.com/landrok/activitypub
6 *
7 * @package Activitypub
8 */
9
10 namespace Activitypub\Activity;
11
12 use Activitypub\Activity\Extended_Object\Event;
13 use Activitypub\Activity\Extended_Object\Place;
14
15 /**
16 * \Activitypub\Activity\Activity implements the common
17 * attributes of an Activity.
18 *
19 * @see https://www.w3.org/TR/activitystreams-core/#activities
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.
36 */
37 class Activity extends Base_Object {
38 const JSON_LD_CONTEXT = array(
39 'https://www.w3.org/ns/activitystreams',
40 array(
41 'toot' => 'http://joinmastodon.org/ns#',
42 'QuoteRequest' => 'toot:QuoteRequest',
43 'blurhash' => 'toot:blurhash',
44 'FeatureRequest' => 'https://w3id.org/fep/7aa9#FeatureRequest',
45 ),
46 );
47
48 /**
49 * The default types for Activities.
50 *
51 * @see https://www.w3.org/TR/activitystreams-vocabulary/#activity-types
52 *
53 * @var array
54 */
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 );
86
87 /**
88 * The type of the object.
89 *
90 * @var string
91 */
92 protected $type = 'Activity';
93
94 /**
95 * Describes the direct object of the activity.
96 * For instance, in the activity "John added a movie to his
97 * wishlist", the object of the activity is the movie added.
98 *
99 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object-term
100 *
101 * @var string|Base_Object|array|null
102 */
103 protected $object;
104
105 /**
106 * Describes one or more entities that either performed or are
107 * expected to perform the activity.
108 * Any single activity can have multiple actors.
109 * The actor MAY be specified using an indirect Link.
110 *
111 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-actor
112 *
113 * @var string|array
114 */
115 protected $actor;
116
117 /**
118 * The indirect object, or target, of the activity.
119 * The precise meaning of the target is largely dependent on the
120 * type of action being described but will often be the object of
121 * the English preposition "to".
122 * For instance, in the activity "John added a movie to his
123 * wishlist", the target of the activity is John's wishlist.
124 * An activity can have more than one target.
125 *
126 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-target
127 *
128 * @var string|array|null
129 */
130 protected $target;
131
132 /**
133 * Describes the result of the activity.
134 * For instance, if a particular action results in the creation of
135 * a new resource, the result property can be used to describe
136 * that new resource.
137 *
138 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-result
139 *
140 * @var string|Base_Object|null
141 */
142 protected $result;
143
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 /**
157 * An indirect object of the activity from which the
158 * activity is directed.
159 * The precise meaning of the origin is the object of the English
160 * preposition "from".
161 * For instance, in the activity "John moved an item to List B
162 * from List A", the origin of the activity is "List A".
163 *
164 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-origin
165 *
166 * @var string|array|null
167 */
168 protected $origin;
169
170 /**
171 * One or more objects used (or to be used) in the completion of an
172 * Activity.
173 *
174 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-instrument
175 *
176 * @var string|array|null
177 */
178 protected $instrument;
179
180 /**
181 * Set the object and copy Object properties to the Activity.
182 *
183 * Any to, bto, cc, bcc, and audience properties specified on the object
184 * MUST be copied over to the new "Create" activity by the server.
185 *
186 * @see https://www.w3.org/TR/activitypub/#object-without-create
187 *
188 * @param array|string|Base_Object|Activity|Actor|null $data Activity object.
189 */
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
202 $this->set( 'object', $object );
203 $this->pre_fill_activity_from_object();
204 }
205
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
216 return;
217 }
218
219 // Check if `$object` is an object and copy some properties otherwise do nothing.
220 if ( ! \is_object( $object ) ) {
221 return;
222 }
223
224 foreach ( array( 'to', 'bto', 'cc', 'bcc', 'audience' ) as $i ) {
225 $value = $object->get( $i );
226 if ( $value && ! $this->get( $i ) ) {
227 $this->set( $i, $value );
228 }
229 }
230
231 if ( $object->get_published() && ! $this->get_published() ) {
232 $this->set( 'published', $object->get_published() );
233 }
234
235 if ( $object->get_updated() && ! $this->get_updated() ) {
236 $this->set( 'updated', $object->get_updated() );
237 }
238
239 if ( $object->get_attributed_to() && ! $this->get_actor() ) {
240 $this->set( 'actor', $object->get_attributed_to() );
241 }
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
251 if ( $object->get_id() && ! $this->get_id() ) {
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 );
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;
316 }
317 }
318