PluginProbe
ActivityPub / 1.0.0
ActivityPub v1.0.0
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 +281 -285 8.3.01.0.0 View file →
@@ -2,16 +2,18 @@
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;
13 12
13 +use function Activitypub\camel_to_snake_case;
14 +use function Activitypub\snake_to_camel_case;
15 +
14 16 /**
15 17 * Base_Object is an implementation of one of the
16 18 * Activity Streams Core Types.
17 19 *
@@ -21,176 +23,20 @@
21 23 * Note: Object is a reserved keyword in PHP. It has been suffixed with
22 24 * 'Base_' for this reason.
23 25 *
24 26 * @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 27 */
117 -class Base_Object extends Generic_Object {
28 +class Base_Object {
118 29 /**
119 - * The JSON-LD context for the object.
30 + * The object's unique global identifier
120 31 *
121 - * @var array
122 - */
123 - const JSON_LD_CONTEXT = array(
124 - 'https://www.w3.org/ns/activitystreams',
125 - 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 - ),
166 - );
167 -
168 - /**
169 - * The default types for Objects.
32 + * @see https://www.w3.org/TR/activitypub/#obj-id
170 33 *
171 - * @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types
172 - *
173 - * @var array
34 + * @var string
174 35 */
175 - const TYPES = array(
176 - 'Article',
177 - 'Audio',
178 - 'Document',
179 - 'Event',
180 - 'Image',
181 - 'Note',
182 - 'Page',
183 - 'Place',
184 - 'Profile',
185 - 'Relationship',
186 - 'Tombstone',
187 - 'Video',
188 - );
36 + protected $id;
189 37
190 38 /**
191 - * The type of the object.
192 - *
193 39 * @var string
194 40 */
195 41 protected $type = 'Object';
196 42
@@ -201,9 +47,14 @@
201 47 * similar to attachments in email.
202 48 *
203 49 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-attachment
204 50 *
205 - * @var string|null
51 + * @var string
52 + * | ObjectType
53 + * | Link
54 + * | array<ObjectType>
55 + * | array<Link>
56 + * | null
206 57 */
207 58 protected $attachment;
208 59
209 60 /**
@@ -212,19 +63,29 @@
212 63 * object might be attributed to the completion of another activity.
213 64 *
214 65 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-attributedto
215 66 *
216 - * @var string|null
67 + * @var string
68 + * | ObjectType
69 + * | Link
70 + * | array<ObjectType>
71 + * | array<Link>
72 + * | null
217 73 */
218 74 protected $attributed_to;
219 75
220 76 /**
221 77 * One or more entities that represent the total population of
222 - * entities for which the object can be considered to be relevant.
78 + * entities for which the object can considered to be relevant.
223 79 *
224 80 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-audience
225 81 *
226 - * @var string|null
82 + * @var string
83 + * | ObjectType
84 + * | Link
85 + * | array<ObjectType>
86 + * | array<Link>
87 + * | null
227 88 */
228 89 protected $audience;
229 90
230 91 /**
@@ -252,9 +113,12 @@
252 113 * project or event.
253 114 *
254 115 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-context
255 116 *
256 - * @var string|null
117 + * @var string
118 + * | ObjectType
119 + * | Link
120 + * | null
257 121 */
258 122 protected $context;
259 123
260 124 /**
@@ -267,27 +131,8 @@
267 131 */
268 132 protected $content_map;
269 133
270 134 /**
271 - * The date and time at which the object was deleted.
272 - *
273 - * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-deleted
274 - *
275 - * @var string|null
276 - */
277 - protected $deleted;
278 -
279 - /**
280 - * The former type of the object. Used in Tombstone objects to
281 - * indicate the type of the object prior to deletion.
282 - *
283 - * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-formertype
284 - *
285 - * @var string|null
286 - */
287 - protected $former_type;
288 -
289 - /**
290 135 * A simple, human-readable, plain-text name for the object.
291 136 * HTML markup MUST NOT be included.
292 137 *
293 138 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-name
@@ -332,9 +177,14 @@
332 177 * at a small size.
333 178 *
334 179 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-icon
335 180 *
336 - * @var string|array|null
181 + * @var string
182 + * | Image
183 + * | Link
184 + * | array<Image>
185 + * | array<Link>
186 + * | null
337 187 */
338 188 protected $icon;
339 189
340 190 /**
@@ -343,9 +193,14 @@
343 193 * or display size limitations assumed.
344 194 *
345 195 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-image-term
346 196 *
347 - * @var string|array|null
197 + * @var string
198 + * | Image
199 + * | Link
200 + * | array<Image>
201 + * | array<Link>
202 + * | null
348 203 */
349 204 protected $image;
350 205
351 206 /**
@@ -353,9 +208,14 @@
353 208 * response.
354 209 *
355 210 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-inreplyto
356 211 *
357 - * @var string|null
212 + * @var string
213 + * | ObjectType
214 + * | Link
215 + * | array<ObjectType>
216 + * | array<Link>
217 + * | null
358 218 */
359 219 protected $in_reply_to;
360 220
361 221 /**
@@ -363,9 +223,14 @@
363 223 * object.
364 224 *
365 225 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-location
366 226 *
367 - * @var string|null|Place
227 + * @var string
228 + * | ObjectType
229 + * | Link
230 + * | array<ObjectType>
231 + * | array<Link>
232 + * | null
368 233 */
369 234 protected $location;
370 235
371 236 /**
@@ -372,9 +237,12 @@
372 237 * An entity that provides a preview of this object.
373 238 *
374 239 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-preview
375 240 *
376 - * @var string|null
241 + * @var string
242 + * | ObjectType
243 + * | Link
244 + * | null
377 245 */
378 246 protected $preview;
379 247
380 248 /**
@@ -386,8 +254,21 @@
386 254 */
387 255 protected $published;
388 256
389 257 /**
258 + * A Collection containing objects considered to be responses to
259 + * this object.
260 + *
261 + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-replies
262 + *
263 + * @var string
264 + * | Collection
265 + * | Link
266 + * | null
267 + */
268 + protected $replies;
269 +
270 + /**
390 271 * The date and time describing the actual or expected starting time
391 272 * of the object.
392 273 * When used with an Activity object, for instance, the startTime
393 274 * property specifies the moment the activity began
@@ -404,9 +285,12 @@
404 285 * Multiple language tagged summaries MAY be provided.
405 286 *
406 287 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-summary
407 288 *
408 - * @var string|null
289 + * @var string
290 + * | ObjectType
291 + * | Link
292 + * | null
409 293 */
410 294 protected $summary;
411 295
412 296 /**
@@ -414,9 +298,9 @@
414 298 * values.
415 299 *
416 300 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-summary
417 301 *
418 - * @var string[]|null
302 + * @var array<string>|null
419 303 */
420 304 protected $summary_map;
421 305
422 306 /**
@@ -427,9 +311,14 @@
427 311 * associated by reference.
428 312 *
429 313 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tag
430 314 *
431 - * @var string|null
315 + * @var string
316 + * | ObjectType
317 + * | Link
318 + * | array<ObjectType>
319 + * | array<Link>
320 + * | null
432 321 */
433 322 protected $tag;
434 323
435 324 /**
@@ -443,9 +332,13 @@
443 332
444 333 /**
445 334 * One or more links to representations of the object.
446 335 *
447 - * @var string|null
336 + * @var string
337 + * | array<string>
338 + * | Link
339 + * | array<Link>
340 + * | null
448 341 */
449 342 protected $url;
450 343
451 344 /**
@@ -453,9 +346,14 @@
453 346 * of an Object
454 347 *
455 348 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-to
456 349 *
457 - * @var string|array|null
350 + * @var string
351 + * | ObjectType
352 + * | Link
353 + * | array<ObjectType>
354 + * | array<Link>
355 + * | null
458 356 */
459 357 protected $to;
460 358
461 359 /**
@@ -463,9 +361,14 @@
463 361 * Object.
464 362 *
465 363 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-bto
466 364 *
467 - * @var string|array|null
365 + * @var string
366 + * | ObjectType
367 + * | Link
368 + * | array<ObjectType>
369 + * | array<Link>
370 + * | null
468 371 */
469 372 protected $bto;
470 373
471 374 /**
@@ -473,9 +376,14 @@
473 376 * Object.
474 377 *
475 378 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-cc
476 379 *
477 - * @var string|array|null
380 + * @var string
381 + * | ObjectType
382 + * | Link
383 + * | array<ObjectType>
384 + * | array<Link>
385 + * | null
478 386 */
479 387 protected $cc;
480 388
481 389 /**
@@ -483,9 +391,14 @@
483 391 * audience of this Object.
484 392 *
485 393 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-bcc
486 394 *
487 - * @var string|array|null
395 + * @var string
396 + * | ObjectType
397 + * | Link
398 + * | array<ObjectType>
399 + * | array<Link>
400 + * | null
488 401 */
489 402 protected $bcc;
490 403
491 404 /**
@@ -500,11 +413,11 @@
500 413 protected $media_type;
501 414
502 415 /**
503 416 * When the object describes a time-bound resource, such as an audio
504 - * or video, a meeting, etc., the duration property indicates the
417 + * or video, a meeting, etc, the duration property indicates the
505 418 * object's approximate duration.
506 - * The value MUST be expressed as a xsd:duration as defined by
419 + * The value MUST be expressed as an xsd:duration as defined by
507 420 * xmlschema11-2, section 3.3.6 (e.g. a period of 5 seconds is
508 421 * represented as "PT5S").
509 422 *
510 423 * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-duration
@@ -519,156 +432,239 @@
519 432 * future editing by clients.
520 433 *
521 434 * @see https://www.w3.org/TR/activitypub/#source-property
522 435 *
523 - * @var array|null
436 + * @var ObjectType
524 437 */
525 438 protected $source;
526 439
527 440 /**
528 - * A Collection containing objects considered to be responses to
529 - * this object.
441 + * Magic function to implement getter and setter
530 442 *
531 - * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-replies
443 + * @param string $method The method name.
444 + * @param string $params The method params.
532 445 *
533 - * @var string|array|null
446 + * @return void
534 447 */
535 - protected $replies;
448 + public function __call( $method, $params ) {
449 + $var = \strtolower( \substr( $method, 4 ) );
536 450
451 + if ( \strncasecmp( $method, 'get', 3 ) === 0 ) {
452 + if ( ! $this->has( $var ) ) {
453 + return new WP_Error( 'invalid_key', 'Invalid key' );
454 + }
455 +
456 + return $this->$var;
457 + }
458 +
459 + if ( \strncasecmp( $method, 'set', 3 ) === 0 ) {
460 + $this->set( $var, $params[0] );
461 + }
462 +
463 + if ( \strncasecmp( $method, 'add', 3 ) === 0 ) {
464 + $this->add( $var, $params[0] );
465 + }
466 + }
467 +
537 468 /**
538 - * A Collection containing objects considered to be likes for
539 - * this object.
469 + * Magic function, to transform the object to string.
540 470 *
541 - * @see https://www.w3.org/TR/activitypub/#likes
542 - *
543 - * @var array|null
471 + * @return string The object id.
544 472 */
545 - protected $likes;
473 + public function __toString() {
474 + return $this->to_string();
475 + }
546 476
547 477 /**
548 - * A Collection containing objects considered to be shares for
549 - * this object.
478 + * Function to transform the object to string.
550 479 *
551 - * @see https://www.w3.org/TR/activitypub/#shares
552 - *
553 - * @var array|null
480 + * @return string The object id.
554 481 */
555 - protected $shares;
482 + public function to_string() {
483 + return $this->get_id();
484 + }
556 485
557 486 /**
558 - * Used to mark an object as containing sensitive content.
559 - * Mastodon displays a content warning, requiring users to click
560 - * through to view the content.
487 + * Generic getter.
561 488 *
562 - * @see https://docs.joinmastodon.org/spec/activitypub/#sensitive
489 + * @param string $key The key to get.
563 490 *
564 - * @var boolean|null
491 + * @return mixed The value.
565 492 */
566 - protected $sensitive;
493 + public function get( $key ) {
494 + if ( ! $this->has( $key ) ) {
495 + return new WP_Error( 'invalid_key', 'Invalid key' );
496 + }
567 497
498 + return call_user_func( array( $this, 'get_' . $key ) );
499 + }
500 +
568 501 /**
569 - * The dcterms namespace.
502 + * Check if the object has a key
570 503 *
571 - * @see https://codeberg.org/fediverse/fep/src/branch/main/fep/b2b8/fep-b2b8.md#sensitive
572 - * @see https://www.dublincore.org/specifications/dublin-core/dcmi-terms/
504 + * @param string $key The key to check.
573 505 *
574 - * @var array|null
506 + * @return boolean True if the object has the key.
575 507 */
576 - protected $dcterms;
508 + public function has( $key ) {
509 + return property_exists( $this, $key );
510 + }
577 511
578 512 /**
579 - * Interaction policy is an attempt to limit the harmful effects of unwanted replies and
580 - * other interactions on a user's posts (e.g., "reply guys").
513 + * Generic setter.
581 514 *
582 - * It is also used by Mastodon to limit the ability to quote posts.
515 + * @param string $key The key to set.
516 + * @param string $value The value to set.
583 517 *
584 - * @see https://docs.gotosocial.org/en/latest/federation/interaction_policy/
585 - * @see https://blog.joinmastodon.org/2025/09/introducing-quote-posts/
586 - *
587 - * @var array|null
518 + * @return mixed The value.
588 519 */
589 - protected $interaction_policy;
520 + public function set( $key, $value ) {
521 + if ( ! $this->has( $key ) ) {
522 + return new WP_Error( 'invalid_key', 'Invalid key' );
523 + }
590 524
525 + $this->$key = $value;
526 +
527 + return $this->$key;
528 + }
529 +
591 530 /**
592 - * Fediverse Enhancement Proposal 044f: Quote Property
531 + * Generic adder.
593 532 *
594 - * @see https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md
595 - * @see https://w3id.org/fep/044f#quote
533 + * @param string $key The key to set.
534 + * @param mixed $value The value to add.
596 535 *
597 - * @var string|null
536 + * @return mixed The value.
598 537 */
599 - protected $quote;
538 + public function add( $key, $value ) {
539 + if ( ! $this->has( $key ) ) {
540 + return new WP_Error( 'invalid_key', 'Invalid key' );
541 + }
600 542
543 + if ( ! isset( $this->$key ) ) {
544 + $this->$key = array();
545 + }
546 +
547 + $attributes = $this->$key;
548 + $attributes[] = $value;
549 +
550 + $this->$key = $attributes;
551 +
552 + return $this->$key;
553 + }
554 +
601 555 /**
602 - * ActivityStreams quoteUrl property.
556 + * Convert JSON input to an array.
603 557 *
604 - * @see https://www.w3.org/ns/activitystreams#quoteUrl
558 + * @return string The JSON string.
605 559 *
606 - * @var string|null
560 + * @return \Activitypub\Activity\Base_Object An Object built from the JSON string.
607 561 */
608 - protected $quote_url;
562 + public static function init_from_json( $json ) {
563 + $array = \json_decode( $json, true );
609 564
565 + return self::init_from_array( $array );
566 + }
567 +
610 568 /**
611 - * Fedibird-specific quoteUri property.
569 + * Convert JSON input to an array.
612 570 *
613 - * @see https://fedibird.com/ns#quoteUri
571 + * @return string The object array.
614 572 *
615 - * @var string|null
573 + * @return \Activitypub\Activity\Base_Object An Object built from the JSON string.
616 574 */
617 - protected $quote_uri;
575 + public static function init_from_array( $array ) {
576 + $object = new static();
618 577
578 + foreach ( $array as $key => $value ) {
579 + $key = camel_to_snake_case( $key );
580 + $object->set( $key, $value );
581 + }
582 +
583 + return $object;
584 + }
585 +
619 586 /**
620 - * Misskey-specific quote property.
587 + * Convert JSON input to an array and pre-fill the object.
621 588 *
622 - * @see https://misskey-hub.net/ns/#_misskey_quote
623 - *
624 - * @var string|null
589 + * @param string $json The JSON string.
625 590 */
626 - protected $_misskey_quote; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
591 + public function from_json( $json ) {
592 + $array = \json_decode( $json, true );
627 593
594 + $this->from_array( $array );
595 + }
596 +
628 597 /**
629 - * Generic getter.
598 + * Convert JSON input to an array and pre-fill the object.
630 599 *
631 - * @param string $key The key to get.
632 - *
633 - * @return mixed The value.
600 + * @param array $array The array.
634 601 */
635 - public function get( $key ) {
636 - if ( ! $this->has( $key ) ) {
637 - return new \WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) );
602 + public function from_array( $array ) {
603 + foreach ( $array as $key => $value ) {
604 + if ( $value ) {
605 + $key = camel_to_snake_case( $key );
606 + $this->set( $key, $value );
607 + }
638 608 }
639 -
640 - return parent::get( $key );
641 609 }
642 610
643 611 /**
644 - * Generic setter.
612 + * Convert Object to an array.
645 613 *
646 - * @param string $key The key to set.
647 - * @param string $value The value to set.
614 + * It tries to get the object attributes if they exist
615 + * and falls back to the getters. Empty values are ignored.
648 616 *
649 - * @return mixed The value.
617 + * @return array An array built from the Object.
650 618 */
651 - public function set( $key, $value ) {
652 - if ( ! $this->has( $key ) ) {
653 - return new \WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) );
619 + public function to_array() {
620 + $array = array();
621 + $vars = get_object_vars( $this );
622 +
623 + foreach ( $vars as $key => $value ) {
624 + // ignotre all _prefixed keys.
625 + if ( '_' === substr( $key, 0, 1 ) ) {
626 + continue;
627 + }
628 +
629 + // if value is empty, try to get it from a getter.
630 + if ( ! $value ) {
631 + $value = call_user_func( array( $this, 'get_' . $key ) );
632 + }
633 +
634 + if ( is_object( $value ) ) {
635 + $value = $value->to_array();
636 + }
637 +
638 + // if value is still empty, ignore it for the array and continue.
639 + if ( $value ) {
640 + $array[ snake_to_camel_case( $key ) ] = $value;
641 + }
654 642 }
655 643
656 - return parent::set( $key, $value );
644 + // replace 'context' key with '@context' and move it to the top.
645 + if ( array_key_exists( 'context', $array ) ) {
646 + $context = $array['context'];
647 + unset( $array['context'] );
648 + $array = array_merge( array( '@context' => $context ), $array );
649 + }
650 +
651 + $class = new ReflectionClass( $this );
652 + $class = strtolower( $class->getShortName() );
653 +
654 + $array = \apply_filters( 'activitypub_activity_object_array', $array, $class, $this->id, $this );
655 + $array = \apply_filters( "activitypub_activity_{$class}_object_array", $array, $this->id, $this );
656 +
657 + return $array;
657 658 }
658 659
659 660 /**
660 - * Generic adder.
661 + * Convert Object to JSON.
661 662 *
662 - * @param string $key The key to set.
663 - * @param mixed $value The value to add.
664 - *
665 - * @return mixed The value.
663 + * @return string The JSON string.
666 664 */
667 - public function add( $key, $value ) {
668 - if ( ! $this->has( $key ) ) {
669 - return new \WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) );
670 - }
665 + public function to_json() {
666 + $array = $this->to_array();
671 667
672 - return parent::add( $key, $value );
668 + return \wp_json_encode( $array, \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT );
673 669 }
674 670 }