PluginProbe
ActivityPub / 3.2.4
ActivityPub v3.2.4
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-base-object.php +311 -273 9.2.23.2.4 View file →
@@ -2,16 +2,19 @@
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
8 6 */
9 7
10 8 namespace Activitypub\Activity;
11 9
12 -use Activitypub\Activity\Extended_Object\Place;
10 +use WP_Error;
11 +use ReflectionClass;
12 +use DateTime;
13 13
14 +use function Activitypub\camel_to_snake_case;
15 +use function Activitypub\snake_to_camel_case;
16 +
14 17 /**
15 18 * Base_Object is an implementation of one of the
16 19 * Activity Streams Core Types.
17 20 *
@@ -21,178 +24,27 @@
21 24 * Note: Object is a reserved keyword in PHP. It has been suffixed with
22 25 * 'Base_' for this reason.
23 26 *
24 27 * @see https://www.w3.org/TR/activitystreams-core/#object
25 - *
26 - * @method array|string|null get_attachment() Gets the attachment property of the object.
27 - * @method array|string|null get_attributed_to() Gets the entity attributed as the original author.
28 - * @method string|null get_audience() Gets the total population of entities for which the object can be considered relevant.
29 - * @method string[]|string|null get_bcc() Gets the private secondary audience of the object.
30 - * @method string[]|string|null get_bto() Gets the private primary audience of the object.
31 - * @method string[]|string|null get_cc() Gets the secondary recipients of the object.
32 - * @method string|null get_content() Gets the content property of the object.
33 - * @method string[]|null get_content_map() Gets the content map property of the object.
34 - * @method string|null get_context() Gets the context within which the object exists.
35 - * @method array|null get_dcterms() Gets the Dublin Core terms property of the object.
36 - * @method string|null get_duration() Gets the duration property of time-bound resources.
37 - * @method string|null get_end_time() Gets the date and time describing the ending time of the object.
38 - * @method string|null get_generator() Gets the entity that generated the object.
39 - * @method string[]|null get_icon() Gets the icon property of the object.
40 - * @method string|null get_id() Gets the object's unique global identifier.
41 - * @method string[]|null get_image() Gets the image property of the object.
42 - * @method string[]|string|null get_in_reply_to() Gets the objects this object is in reply to.
43 - * @method array|null get_interaction_policy() Gets the interaction policy property of the object.
44 - * @method array|null get_likes() Gets the collection of likes for this object.
45 - * @method array|string|null|Place get_location() Gets the physical or logical locations associated with the object.
46 - * @method string|null get_media_type() Gets the MIME media type of the content property.
47 - * @method string|null get_name() Gets the natural language name of the object.
48 - * @method string[]|null get_name_map() Gets the name map property of the object.
49 - * @method string|null get_preview() Gets the entity that provides a preview of this object.
50 - * @method string|null get_published() Gets the date and time the object was published in ISO 8601 format.
51 - * @method string|null get_quote() Gets the quote property of the object (FEP-044f).
52 - * @method string|null get_quote_url() Gets the quoteUrl property of the object.
53 - * @method string|null get_quote_uri() Gets the quoteUri property of the object.
54 - * @method string|null get__misskey_quote() Gets the _misskey_quote property of the object.
55 - * @method string|array|null get_replies() Gets the collection of responses to this object.
56 - * @method bool|null get_sensitive() Gets the sensitive property of the object.
57 - * @method array|null get_shares() Gets the collection of shares for this object.
58 - * @method array|null get_source() Gets the source property indicating content markup derivation.
59 - * @method string|null get_start_time() Gets the date and time describing the starting time of the object.
60 - * @method string|null get_summary() Gets the natural language summary of the object.
61 - * @method string[]|null get_summary_map() Gets the summary map property of the object.
62 - * @method array[]|null get_tag() Gets the tag property of the object.
63 - * @method string[]|string|null get_to() Gets the primary recipients of the object.
64 - * @method string get_type() Gets the type of the object.
65 - * @method string|null get_updated() Gets the date and time the object was updated in ISO 8601 format.
66 - * @method string|null get_url() Gets the URL of the object.
67 - * @method string|null get_former_type() Gets the former type of a Tombstone object.
68 - * @method string|null get_deleted() Gets the date and time the object was deleted in ISO 8601 format.
69 - *
70 - * @method string|string[] add_cc( string|array $cc ) Adds one or more entities to the secondary audience of the object.
71 - * @method string|string[] add_to( string|array $to ) Adds one or more entities to the primary audience of the object.
72 - *
73 - * @method Base_Object set_attachment( array $attachment ) Sets the attachment property of the object.
74 - * @method Base_Object set_attributed_to( string $attributed_to ) Sets the entity attributed as the original author.
75 - * @method Base_Object set_audience( string $audience ) Sets the total population of entities for which the object can be considered relevant.
76 - * @method Base_Object set_bcc( array|string $bcc ) Sets the private secondary audience of the object.
77 - * @method Base_Object set_bto( array|string $bto ) Sets the private primary audience of the object.
78 - * @method Base_Object set_cc( array|string $cc ) Sets the secondary recipients of the object.
79 - * @method Base_Object set_content( string $content ) Sets the content property of the object.
80 - * @method Base_Object set_content_map( array $content_map ) Sets the content property of the object.
81 - * @method Base_Object set_context( string $context ) Sets the context within which the object exists.
82 - * @method Base_Object set_dcterms( array $dcterms ) Sets the Dublin Core terms property of the object.
83 - * @method Base_Object set_duration( string $duration ) Sets the duration property of time-bound resources.
84 - * @method Base_Object set_end_time( string $end_time ) Sets the date and time describing the ending time of the object.
85 - * @method Base_Object set_generator( string $generator ) Sets the entity that generated the object.
86 - * @method Base_Object set_icon( array $icon ) Sets the icon property of the object.
87 - * @method Base_Object set_id( string $id ) Sets the object's unique global identifier.
88 - * @method Base_Object set_image( array $image ) Sets the image property of the object.
89 - * @method Base_Object set_in_reply_to( string|string[] $in_reply_to ) Sets the is in reply to property of the object.
90 - * @method Base_Object set_interaction_policy( array|null $policy ) Sets the interaction policy property of the object.
91 - * @method Base_Object set_likes( array $likes ) Sets the collection of likes for this object.
92 - * @method Base_Object set_location( array|string|Place $location ) Sets the physical or logical locations associated with the object.
93 - * @method Base_Object set_media_type( string $media_type ) Sets the MIME media type of the content property.
94 - * @method Base_Object set_name( string $name ) Sets the natural language name of the object.
95 - * @method Base_Object set_name_map( array|null $name_map ) Sets the name map property of the object.
96 - * @method Base_Object set_preview( string $preview ) Sets the entity that provides a preview of this object.
97 - * @method Base_Object set_published( string|null $published ) Sets the date and time the object was published in ISO 8601 format.
98 - * @method Base_Object set_quote( string $quote ) Sets the quote property of the object (FEP-044f).
99 - * @method Base_Object set_quote_url( string $quote_url ) Sets the quoteUrl property of the object.
100 - * @method Base_Object set_quote_uri( string $quote_uri ) Sets the quoteUri property of the object.
101 - * @method Base_Object set__misskey_quote( mixed $misskey_quote ) Sets the _misskey_quote property of the object.
102 - * @method Base_Object set_replies( string|array $replies ) Sets the collection of responses to this object.
103 - * @method Base_Object set_sensitive( bool|null $sensitive ) Sets the sensitive property of the object.
104 - * @method Base_Object set_shares( array $shares ) Sets the collection of shares for this object.
105 - * @method Base_Object set_source( array $source ) Sets the source property indicating content markup derivation.
106 - * @method Base_Object set_start_time( string $start_time ) Sets the date and time describing the starting time of the object.
107 - * @method Base_Object set_summary( string $summary ) Sets the natural language summary of the object.
108 - * @method Base_Object set_summary_map( array|null $summary_map ) Sets the summary property of the object.
109 - * @method Base_Object set_tag( array|null $tag ) Sets the tag property of the object.
110 - * @method Base_Object set_to( string|string[] $to ) Sets the primary recipients of the object.
111 - * @method Base_Object set_type( string $type ) Sets the type of the object.
112 - * @method Base_Object set_updated( string $updated ) Sets the date and time the object was updated in ISO 8601 format.
113 - * @method Base_Object set_url( string $url ) Sets the URL of the object.
114 - * @method Base_Object set_former_type( string $former_type ) Sets the former type of a Tombstone object.
115 - * @method Base_Object set_deleted( string $deleted ) Sets the date and time the object was deleted in ISO 8601 format.
116 28 */
117 -class Base_Object extends Generic_Object {
118 - /**
119 - * The JSON-LD context for the object.
120 - *
121 - * @var array
122 - */
29 +class Base_Object {
123 30 const JSON_LD_CONTEXT = array(
124 31 'https://www.w3.org/ns/activitystreams',
125 32 array(
126 - 'Hashtag' => 'as:Hashtag',
127 - 'sensitive' => 'as:sensitive',
128 - 'dcterms' => 'http://purl.org/dc/terms/',
129 - 'gts' => 'https://gotosocial.org/ns#',
130 - 'schema' => 'http://schema.org/',
131 - 'exifData' => 'schema:exifData',
132 - 'PropertyValue' => 'schema:PropertyValue',
133 - 'interactionPolicy' => array(
134 - '@id' => 'gts:interactionPolicy',
135 - '@type' => '@id',
136 - ),
137 - 'canQuote' => array(
138 - '@id' => 'gts:canQuote',
139 - '@type' => '@id',
140 - ),
141 - 'canReply' => array(
142 - '@id' => 'gts:canReply',
143 - '@type' => '@id',
144 - ),
145 - 'canLike' => array(
146 - '@id' => 'gts:canLike',
147 - '@type' => '@id',
148 - ),
149 - 'canAnnounce' => array(
150 - '@id' => 'gts:canAnnounce',
151 - '@type' => '@id',
152 - ),
153 - 'automaticApproval' => array(
154 - '@id' => 'gts:automaticApproval',
155 - '@type' => '@id',
156 - ),
157 - 'manualApproval' => array(
158 - '@id' => 'gts:manualApproval',
159 - '@type' => '@id',
160 - ),
161 - 'always' => array(
162 - '@id' => 'gts:always',
163 - '@type' => '@id',
164 - ),
165 - 'toot' => 'http://joinmastodon.org/ns#',
166 - 'blurhash' => 'toot:blurhash',
33 + 'Hashtag' => 'as:Hashtag',
167 34 ),
168 35 );
169 36
170 37 /**
171 - * The default types for Objects.
38 + * The object's unique global identifier
172 39 *
173 - * @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types
40 + * @see https://www.w3.org/TR/activitypub/#obj-id
174 41 *
175 - * @var array
42 + * @var string
176 43 */
177 - const TYPES = array(
178 - 'Article',
179 - 'Audio',
180 - 'Document',
181 - 'Event',
182 - 'Image',
183 - 'Note',
184 - 'Page',
185 - 'Place',
186 - 'Profile',
187 - 'Relationship',
188 - 'Tombstone',
189 - 'Video',
190 - );
44 + protected $id;
191 45
192 46 /**
193 - * The type of the object.
194 - *
195 47 * @var string
196 48 */
197 49 protected $type = 'Object';
198 50
@@ -203,9 +55,14 @@
203 55 * similar to attachments in email.
204 56 *
205 57 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-attachment
206 58 *
207 - * @var string|null
59 + * @var string
60 + * | ObjectType
61 + * | Link
62 + * | array<ObjectType>
63 + * | array<Link>
64 + * | null
208 65 */
209 66 protected $attachment;
210 67
211 68 /**
@@ -214,19 +71,29 @@
214 71 * object might be attributed to the completion of another activity.
215 72 *
216 73 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-attributedto
217 74 *
218 - * @var string|null
75 + * @var string
76 + * | ObjectType
77 + * | Link
78 + * | array<ObjectType>
79 + * | array<Link>
80 + * | null
219 81 */
220 82 protected $attributed_to;
221 83
222 84 /**
223 85 * One or more entities that represent the total population of
224 - * entities for which the object can be considered to be relevant.
86 + * entities for which the object can considered to be relevant.
225 87 *
226 88 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-audience
227 89 *
228 - * @var string|null
90 + * @var string
91 + * | ObjectType
92 + * | Link
93 + * | array<ObjectType>
94 + * | array<Link>
95 + * | null
229 96 */
230 97 protected $audience;
231 98
232 99 /**
@@ -254,9 +121,12 @@
254 121 * project or event.
255 122 *
256 123 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-context
257 124 *
258 - * @var string|null
125 + * @var string
126 + * | ObjectType
127 + * | Link
128 + * | null
259 129 */
260 130 protected $context;
261 131
262 132 /**
@@ -269,27 +139,8 @@
269 139 */
270 140 protected $content_map;
271 141
272 142 /**
273 - * The date and time at which the object was deleted.
274 - *
275 - * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-deleted
276 - *
277 - * @var string|null
278 - */
279 - protected $deleted;
280 -
281 - /**
282 - * The former type of the object. Used in Tombstone objects to
283 - * indicate the type of the object prior to deletion.
284 - *
285 - * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-formertype
286 - *
287 - * @var string|null
288 - */
289 - protected $former_type;
290 -
291 - /**
292 143 * A simple, human-readable, plain-text name for the object.
293 144 * HTML markup MUST NOT be included.
294 145 *
295 146 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-name
@@ -334,9 +185,14 @@
334 185 * at a small size.
335 186 *
336 187 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-icon
337 188 *
338 - * @var string|array|null
189 + * @var string
190 + * | Image
191 + * | Link
192 + * | array<Image>
193 + * | array<Link>
194 + * | null
339 195 */
340 196 protected $icon;
341 197
342 198 /**
@@ -345,9 +201,14 @@
345 201 * or display size limitations assumed.
346 202 *
347 203 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-image-term
348 204 *
349 - * @var string|array|null
205 + * @var string
206 + * | Image
207 + * | Link
208 + * | array<Image>
209 + * | array<Link>
210 + * | null
350 211 */
351 212 protected $image;
352 213
353 214 /**
@@ -355,9 +216,14 @@
355 216 * response.
356 217 *
357 218 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-inreplyto
358 219 *
359 - * @var string|null
220 + * @var string
221 + * | ObjectType
222 + * | Link
223 + * | array<ObjectType>
224 + * | array<Link>
225 + * | null
360 226 */
361 227 protected $in_reply_to;
362 228
363 229 /**
@@ -365,9 +231,14 @@
365 231 * object.
366 232 *
367 233 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-location
368 234 *
369 - * @var string|null|Place
235 + * @var string
236 + * | ObjectType
237 + * | Link
238 + * | array<ObjectType>
239 + * | array<Link>
240 + * | null
370 241 */
371 242 protected $location;
372 243
373 244 /**
@@ -374,9 +245,12 @@
374 245 * An entity that provides a preview of this object.
375 246 *
376 247 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-preview
377 248 *
378 - * @var string|null
249 + * @var string
250 + * | ObjectType
251 + * | Link
252 + * | null
379 253 */
380 254 protected $preview;
381 255
382 256 /**
@@ -406,9 +280,12 @@
406 280 * Multiple language tagged summaries MAY be provided.
407 281 *
408 282 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-summary
409 283 *
410 - * @var string|null
284 + * @var string
285 + * | ObjectType
286 + * | Link
287 + * | null
411 288 */
412 289 protected $summary;
413 290
414 291 /**
@@ -416,9 +293,9 @@
416 293 * values.
417 294 *
418 295 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-summary
419 296 *
420 - * @var string[]|null
297 + * @var array<string>|null
421 298 */
422 299 protected $summary_map;
423 300
424 301 /**
@@ -429,9 +306,14 @@
429 306 * associated by reference.
430 307 *
431 308 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tag
432 309 *
433 - * @var string|null
310 + * @var string
311 + * | ObjectType
312 + * | Link
313 + * | array<ObjectType>
314 + * | array<Link>
315 + * | null
434 316 */
435 317 protected $tag;
436 318
437 319 /**
@@ -445,9 +327,13 @@
445 327
446 328 /**
447 329 * One or more links to representations of the object.
448 330 *
449 - * @var string|null
331 + * @var string
332 + * | array<string>
333 + * | Link
334 + * | array<Link>
335 + * | null
450 336 */
451 337 protected $url;
452 338
453 339 /**
@@ -455,9 +341,14 @@
455 341 * of an Object
456 342 *
457 343 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-to
458 344 *
459 - * @var string|array|null
345 + * @var string
346 + * | ObjectType
347 + * | Link
348 + * | array<ObjectType>
349 + * | array<Link>
350 + * | null
460 351 */
461 352 protected $to;
462 353
463 354 /**
@@ -465,9 +356,14 @@
465 356 * Object.
466 357 *
467 358 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-bto
468 359 *
469 - * @var string|array|null
360 + * @var string
361 + * | ObjectType
362 + * | Link
363 + * | array<ObjectType>
364 + * | array<Link>
365 + * | null
470 366 */
471 367 protected $bto;
472 368
473 369 /**
@@ -475,9 +371,14 @@
475 371 * Object.
476 372 *
477 373 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-cc
478 374 *
479 - * @var string|array|null
375 + * @var string
376 + * | ObjectType
377 + * | Link
378 + * | array<ObjectType>
379 + * | array<Link>
380 + * | null
480 381 */
481 382 protected $cc;
482 383
483 384 /**
@@ -485,9 +386,14 @@
485 386 * audience of this Object.
486 387 *
487 388 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-bcc
488 389 *
489 - * @var string|array|null
390 + * @var string
391 + * | ObjectType
392 + * | Link
393 + * | array<ObjectType>
394 + * | array<Link>
395 + * | null
490 396 */
491 397 protected $bcc;
492 398
493 399 /**
@@ -502,11 +408,11 @@
502 408 protected $media_type;
503 409
504 410 /**
505 411 * When the object describes a time-bound resource, such as an audio
506 - * or video, a meeting, etc., the duration property indicates the
412 + * or video, a meeting, etc, the duration property indicates the
507 413 * object's approximate duration.
508 - * The value MUST be expressed as a xsd:duration as defined by
414 + * The value MUST be expressed as an xsd:duration as defined by
509 415 * xmlschema11-2, section 3.3.6 (e.g. a period of 5 seconds is
510 416 * represented as "PT5S").
511 417 *
512 418 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-duration
@@ -521,9 +427,9 @@
521 427 * future editing by clients.
522 428 *
523 429 * @see https://www.w3.org/TR/activitypub/#source-property
524 430 *
525 - * @var array|null
431 + * @var ObjectType
526 432 */
527 433 protected $source;
528 434
529 435 /**
@@ -531,146 +437,278 @@
531 437 * this object.
532 438 *
533 439 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-replies
534 440 *
535 - * @var string|array|null
441 + * @var string
442 + * | Collection
443 + * | Link
444 + * | null
536 445 */
537 446 protected $replies;
538 447
539 448 /**
540 - * A Collection containing objects considered to be likes for
541 - * this object.
449 + * Magic function to implement getter and setter
542 450 *
543 - * @see https://www.w3.org/TR/activitypub/#likes
451 + * @param string $method The method name.
452 + * @param string $params The method params.
544 453 *
545 - * @var array|null
454 + * @return void
546 455 */
547 - protected $likes;
456 + public function __call( $method, $params ) {
457 + $var = \strtolower( \substr( $method, 4 ) );
548 458
459 + if ( \strncasecmp( $method, 'get', 3 ) === 0 ) {
460 + if ( ! $this->has( $var ) ) {
461 + return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) );
462 + }
463 +
464 + return $this->$var;
465 + }
466 +
467 + if ( \strncasecmp( $method, 'set', 3 ) === 0 ) {
468 + return $this->set( $var, $params[0] );
469 + }
470 +
471 + if ( \strncasecmp( $method, 'add', 3 ) === 0 ) {
472 + $this->add( $var, $params[0] );
473 + }
474 + }
475 +
549 476 /**
550 - * A Collection containing objects considered to be shares for
551 - * this object.
477 + * Magic function, to transform the object to string.
552 478 *
553 - * @see https://www.w3.org/TR/activitypub/#shares
479 + * @return string The object id.
480 + */
481 + public function __toString() {
482 + return $this->to_string();
483 + }
484 +
485 + /**
486 + * Function to transform the object to string.
554 487 *
555 - * @var array|null
488 + * @return string The object id.
556 489 */
557 - protected $shares;
490 + public function to_string() {
491 + return $this->get_id();
492 + }
558 493
559 494 /**
560 - * Used to mark an object as containing sensitive content.
561 - * Mastodon displays a content warning, requiring users to click
562 - * through to view the content.
495 + * Generic getter.
563 496 *
564 - * @see https://docs.joinmastodon.org/spec/activitypub/#sensitive
497 + * @param string $key The key to get.
565 498 *
566 - * @var boolean|null
499 + * @return mixed The value.
567 500 */
568 - protected $sensitive;
501 + public function get( $key ) {
502 + if ( ! $this->has( $key ) ) {
503 + return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) );
504 + }
569 505
506 + return call_user_func( array( $this, 'get_' . $key ) );
507 + }
508 +
570 509 /**
571 - * The dcterms namespace.
510 + * Check if the object has a key
572 511 *
573 - * @see https://codeberg.org/fediverse/fep/src/branch/main/fep/b2b8/fep-b2b8.md#sensitive
574 - * @see https://www.dublincore.org/specifications/dublin-core/dcmi-terms/
512 + * @param string $key The key to check.
575 513 *
576 - * @var array|null
514 + * @return boolean True if the object has the key.
577 515 */
578 - protected $dcterms;
516 + public function has( $key ) {
517 + return property_exists( $this, $key );
518 + }
579 519
580 520 /**
581 - * Interaction policy is an attempt to limit the harmful effects of unwanted replies and
582 - * other interactions on a user's posts (e.g., "reply guys").
521 + * Generic setter.
583 522 *
584 - * It is also used by Mastodon to limit the ability to quote posts.
523 + * @param string $key The key to set.
524 + * @param string $value The value to set.
585 525 *
586 - * @see https://docs.gotosocial.org/en/latest/federation/interaction_policy/
587 - * @see https://blog.joinmastodon.org/2025/09/introducing-quote-posts/
588 - *
589 - * @var array|null
526 + * @return mixed The value.
590 527 */
591 - protected $interaction_policy;
528 + public function set( $key, $value ) {
529 + if ( ! $this->has( $key ) ) {
530 + return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) );
531 + }
592 532
533 + $this->$key = $value;
534 +
535 + return $this;
536 + }
537 +
593 538 /**
594 - * Fediverse Enhancement Proposal 044f: Quote Property
539 + * Generic adder.
595 540 *
596 - * @see https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md
597 - * @see https://w3id.org/fep/044f#quote
541 + * @param string $key The key to set.
542 + * @param mixed $value The value to add.
598 543 *
599 - * @var string|null
544 + * @return mixed The value.
600 545 */
601 - protected $quote;
546 + public function add( $key, $value ) {
547 + if ( ! $this->has( $key ) ) {
548 + return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) );
549 + }
602 550
551 + if ( ! isset( $this->$key ) ) {
552 + $this->$key = array();
553 + }
554 +
555 + $attributes = $this->$key;
556 + $attributes[] = $value;
557 +
558 + $this->$key = $attributes;
559 +
560 + return $this->$key;
561 + }
562 +
603 563 /**
604 - * ActivityStreams quoteUrl property.
564 + * Convert JSON input to an array.
605 565 *
606 - * @see https://www.w3.org/ns/activitystreams#quoteUrl
566 + * @return string The JSON string.
607 567 *
608 - * @var string|null
568 + * @return \Activitypub\Activity\Base_Object An Object built from the JSON string.
609 569 */
610 - protected $quote_url;
570 + public static function init_from_json( $json ) {
571 + $array = \json_decode( $json, true );
611 572
573 + if ( ! is_array( $array ) ) {
574 + $array = array();
575 + }
576 +
577 + return self::init_from_array( $array );
578 + }
579 +
612 580 /**
613 - * Fedibird-specific quoteUri property.
581 + * Convert JSON input to an array.
614 582 *
615 - * @see https://fedibird.com/ns#quoteUri
583 + * @return string The object array.
616 584 *
617 - * @var string|null
585 + * @return \Activitypub\Activity\Base_Object An Object built from the JSON string.
618 586 */
619 - protected $quote_uri;
587 + public static function init_from_array( $array ) {
588 + if ( ! is_array( $array ) ) {
589 + return new WP_Error( 'invalid_array', __( 'Invalid array', 'activitypub' ), array( 'status' => 404 ) );
590 + }
620 591
592 + $object = new static();
593 +
594 + foreach ( $array as $key => $value ) {
595 + $key = camel_to_snake_case( $key );
596 + call_user_func( array( $object, 'set_' . $key ), $value );
597 + }
598 +
599 + return $object;
600 + }
601 +
621 602 /**
622 - * Misskey-specific quote property.
603 + * Convert JSON input to an array and pre-fill the object.
623 604 *
624 - * @see https://misskey-hub.net/ns/#_misskey_quote
605 + * @param string $json The JSON string.
606 + */
607 + public function from_json( $json ) {
608 + $array = \json_decode( $json, true );
609 +
610 + $this->from_array( $array );
611 + }
612 +
613 + /**
614 + * Convert JSON input to an array and pre-fill the object.
625 615 *
626 - * @var string|null
616 + * @param array $array The array.
627 617 */
628 - protected $_misskey_quote; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
618 + public function from_array( $array ) {
619 + foreach ( $array as $key => $value ) {
620 + if ( $value ) {
621 + $key = camel_to_snake_case( $key );
622 + call_user_func( array( $this, 'set_' . $key ), $value );
623 + }
624 + }
625 + }
629 626
630 627 /**
631 - * Generic getter.
628 + * Convert Object to an array.
632 629 *
633 - * @param string $key The key to get.
630 + * It tries to get the object attributes if they exist
631 + * and falls back to the getters. Empty values are ignored.
634 632 *
635 - * @return mixed The value.
633 + * @param bool $include_json_ld_context Whether to include the JSON-LD context. Default true.
634 + *
635 + * @return array An array built from the Object.
636 636 */
637 - public function get( $key ) {
638 - if ( ! $this->has( $key ) ) {
639 - return new \WP_Error( 'invalid_key', \__( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) );
637 + public function to_array( $include_json_ld_context = true ) {
638 + $array = array();
639 + $vars = get_object_vars( $this );
640 +
641 + foreach ( $vars as $key => $value ) {
642 + // ignotre all _prefixed keys.
643 + if ( '_' === substr( $key, 0, 1 ) ) {
644 + continue;
645 + }
646 +
647 + // if value is empty, try to get it from a getter.
648 + if ( ! $value ) {
649 + $value = call_user_func( array( $this, 'get_' . $key ) );
650 + }
651 +
652 + if ( is_object( $value ) ) {
653 + $value = $value->to_array( false );
654 + }
655 +
656 + // if value is still empty, ignore it for the array and continue.
657 + if ( isset( $value ) ) {
658 + $array[ snake_to_camel_case( $key ) ] = $value;
659 + }
640 660 }
641 661
642 - return parent::get( $key );
662 + if ( $include_json_ld_context ) {
663 + // Get JsonLD context and move it to '@context' at the top.
664 + $array = array_merge( array( '@context' => $this->get_json_ld_context() ), $array );
665 + }
666 +
667 + $class = new ReflectionClass( $this );
668 + $class = strtolower( $class->getShortName() );
669 +
670 + $array = \apply_filters( 'activitypub_activity_object_array', $array, $class, $this->id, $this );
671 + $array = \apply_filters( "activitypub_activity_{$class}_object_array", $array, $this->id, $this );
672 +
673 + return $array;
643 674 }
644 675
645 676 /**
646 - * Generic setter.
677 + * Convert Object to JSON.
647 678 *
648 - * @param string $key The key to set.
649 - * @param string $value The value to set.
679 + * @param bool $include_json_ld_context Whether to include the JSON-LD context. Default true.
650 680 *
651 - * @return mixed The value.
681 + * @return string The JSON string.
652 682 */
653 - public function set( $key, $value ) {
654 - if ( ! $this->has( $key ) ) {
655 - return new \WP_Error( 'invalid_key', \__( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) );
656 - }
683 + public function to_json( $include_json_ld_context = true ) {
684 + $array = $this->to_array( $include_json_ld_context );
685 + $options = \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT;
657 686
658 - return parent::set( $key, $value );
687 + /*
688 + * Options to be passed to json_encode()
689 + *
690 + * @param int $options The current options flags
691 + */
692 + $options = \apply_filters( 'activitypub_json_encode_options', $options );
693 +
694 + return \wp_json_encode( $array, $options );
659 695 }
660 696
661 697 /**
662 - * Generic adder.
698 + * Returns the keys of the object vars.
663 699 *
664 - * @param string $key The key to set.
665 - * @param mixed $value The value to add.
700 + * @return array The keys of the object vars.
701 + */
702 + public function get_object_var_keys() {
703 + return \array_keys( \get_object_vars( $this ) );
704 + }
705 +
706 + /**
707 + * Returns the JSON-LD context of this object.
666 708 *
667 - * @return mixed The value.
709 + * @return array $context A compacted JSON-LD context for the ActivityPub object.
668 710 */
669 - public function add( $key, $value ) {
670 - if ( ! $this->has( $key ) ) {
671 - return new \WP_Error( 'invalid_key', \__( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) );
672 - }
673 -
674 - return parent::add( $key, $value );
711 + public function get_json_ld_context() {
712 + return static::JSON_LD_CONTEXT;
675 713 }
676 714 }