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/model/class-blog.php +100 -274 8.2.13.2.4 View file →
@@ -1,118 +1,113 @@
1 1 <?php
2 -/**
3 - * Blog model file.
4 - *
5 - * @package Activitypub
6 - */
2 +namespace Activitypub\Model;
7 3
8 -namespace Activitypub\Model;
4 +use WP_Query;
5 +use WP_Error;
9 6
7 +use Activitypub\Signature;
10 8 use Activitypub\Activity\Actor;
11 -use Activitypub\Collection\Actors;
9 +use Activitypub\Collection\Users;
12 10 use Activitypub\Collection\Extra_Fields;
13 11
14 12 use function Activitypub\esc_hashtag;
15 -use function Activitypub\get_attribution_domains;
13 +use function Activitypub\is_single_user;
14 +use function Activitypub\is_blog_public;
15 +use function Activitypub\is_user_disabled;
16 16 use function Activitypub\get_rest_url_by_path;
17 -use function Activitypub\is_blog_public;
18 -use function Activitypub\is_single_user;
19 17
20 -/**
21 - * Blog class.
22 - *
23 - * @method int get__id() Gets the internal user ID for the blog (always returns BLOG_USER_ID).
24 - */
25 18 class Blog extends Actor {
26 19 /**
20 + * The Featured-Posts.
21 + *
22 + * @see https://docs.joinmastodon.org/spec/activitypub/#featured
23 + *
24 + * @context {
25 + * "@id": "http://joinmastodon.org/ns#featured",
26 + * "@type": "@id"
27 + * }
28 + *
29 + * @var string
30 + */
31 + protected $featured;
32 +
33 + /**
34 + * Moderators endpoint.
35 + *
36 + * @see https://join-lemmy.org/docs/contributors/05-federation.html
37 + *
38 + * @var string
39 + */
40 + protected $moderators;
41 +
42 + /**
27 43 * The User-ID
28 44 *
29 45 * @var int
30 46 */
31 - protected $_id = Actors::BLOG_USER_ID; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
47 + protected $_id = Users::BLOG_USER_ID; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
32 48
33 49 /**
34 - * The generator of the object.
50 + * If the User is indexable.
35 51 *
36 - * @see https://www.w3.org/TR/activitypub/#generator
37 - * @see https://codeberg.org/fediverse/fep/src/branch/main/fep/844e/fep-844e.md#discovery-through-an-actor
52 + * @context http://joinmastodon.org/ns#indexable
38 53 *
39 - * @var array
54 + * @var boolean
40 55 */
41 - protected $generator = array(
42 - 'type' => 'Application',
43 - 'implements' => array(
44 - array(
45 - 'href' => 'https://datatracker.ietf.org/doc/html/rfc9421',
46 - 'name' => 'RFC-9421: HTTP Message Signatures',
47 - ),
48 - ),
49 - );
56 + protected $indexable;
50 57
51 58 /**
52 - * Constructor.
59 + * The WebFinger Resource.
60 + *
61 + * @var string<url>
53 62 */
54 - public function __construct() {
55 - /**
56 - * Fires when a model actor is constructed.
57 - *
58 - * @param Blog $this The Blog model.
59 - */
60 - \do_action( 'activitypub_construct_model_actor', $this );
61 - }
63 + protected $webfinger;
62 64
63 65 /**
64 - * Whether the User manually approves followers.
66 + * If the User is discoverable.
65 67 *
66 - * @return false
68 + * @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
69 + *
70 + * @context http://joinmastodon.org/ns#discoverable
71 + *
72 + * @var boolean
67 73 */
74 + protected $discoverable;
75 +
76 + /**
77 + * Restrict posting to mods
78 + *
79 + * @see https://join-lemmy.org/docs/contributors/05-federation.html
80 + *
81 + * @var boolean
82 + */
83 + protected $posting_restricted_to_mods;
84 +
68 85 public function get_manually_approves_followers() {
69 86 return false;
70 87 }
71 88
72 - /**
73 - * Whether the User is discoverable.
74 - *
75 - * @return boolean
76 - */
77 89 public function get_discoverable() {
78 90 return true;
79 91 }
80 92
81 93 /**
82 - * Get the User ID.
94 + * Get the User-ID.
83 95 *
84 - * @return string The User ID.
96 + * @return string The User-ID.
85 97 */
86 98 public function get_id() {
87 - $id = parent::get_id();
88 -
89 - if ( $id ) {
90 - return $id;
91 - }
92 -
93 - $permalink = \get_option( 'activitypub_use_permalink_as_id_for_blog', false );
94 -
95 - if ( $permalink ) {
96 - return \esc_url( \home_url( '/@' . $this->get_preferred_username() ) );
97 - }
98 -
99 - return \add_query_arg( 'author', $this->_id, \home_url( '/' ) );
99 + return $this->get_url();
100 100 }
101 101
102 102 /**
103 103 * Get the type of the object.
104 104 *
105 - * If relay mode is enabled, return "Service".
106 - * If the Blog is in "single user" mode, return "Person" instead of "Group".
105 + * If the Blog is in "single user" mode, return "Person" insted of "Group".
107 106 *
108 107 * @return string The type of the object.
109 108 */
110 109 public function get_type() {
111 - if ( \get_option( 'activitypub_relay_mode', false ) ) {
112 - return 'Service';
113 - }
114 -
115 110 if ( is_single_user() ) {
116 111 return 'Person';
117 112 } else {
118 113 return 'Group';
@@ -119,11 +114,11 @@
119 114 }
120 115 }
121 116
122 117 /**
123 - * Get the Username.
118 + * Get the User-Name.
124 119 *
125 - * @return string The Username.
120 + * @return string The User-Name.
126 121 */
127 122 public function get_name() {
128 123 return \wp_strip_all_tags(
129 124 \html_entity_decode(
@@ -134,11 +129,11 @@
134 129 );
135 130 }
136 131
137 132 /**
138 - * Get the User description.
133 + * Get the User-Description.
139 134 *
140 - * @return string The User description.
135 + * @return string The User-Description.
141 136 */
142 137 public function get_summary() {
143 138 $summary = \get_option( 'activitypub_blog_description', null );
144 139
@@ -154,14 +149,14 @@
154 149 );
155 150 }
156 151
157 152 /**
158 - * Get the User url.
153 + * Get the User-Url.
159 154 *
160 - * @return string The User url.
155 + * @return string The User-Url.
161 156 */
162 157 public function get_url() {
163 - return \get_bloginfo( 'url' );
158 + return \esc_url( \trailingslashit( get_home_url() ) . '@' . $this->get_preferred_username() );
164 159 }
165 160
166 161 /**
167 162 * Get blog's homepage URL.
@@ -177,28 +172,24 @@
177 172 *
178 173 * @return string The auto-generated Username.
179 174 */
180 175 public static function get_default_username() {
181 - // Check if domain host has a subdomain.
176 + // check if domain host has a subdomain
182 177 $host = \wp_parse_url( \get_home_url(), \PHP_URL_HOST );
183 178 $host = \preg_replace( '/^www\./i', '', $host );
184 179
185 180 /**
186 - * Filters the default blog username.
181 + * Filter the default blog username.
187 182 *
188 - * This filter allows developers to modify the default username that is
189 - * generated for the blog, which by default is the site's host name
190 - * without the 'www.' prefix.
191 - *
192 - * @param string $host The default username (site's host name).
183 + * @param string $host The default username.
193 184 */
194 185 return apply_filters( 'activitypub_default_blog_username', $host );
195 186 }
196 187
197 188 /**
198 - * Get the preferred Username.
189 + * Get the preferred User-Name.
199 190 *
200 - * @return string The Username.
191 + * @return string The User-Name.
201 192 */
202 193 public function get_preferred_username() {
203 194 $username = \get_option( 'activitypub_blog_identifier' );
204 195
@@ -209,17 +200,17 @@
209 200 return self::get_default_username();
210 201 }
211 202
212 203 /**
213 - * Get the User icon.
204 + * Get the User-Icon.
214 205 *
215 - * @return string[] The User icon.
206 + * @return array The User-Icon.
216 207 */
217 208 public function get_icon() {
218 - // Try site_logo, falling back to site_icon, first.
209 + // try site icon first
219 210 $icon_id = get_option( 'site_icon' );
220 211
221 - // Try custom logo second.
212 + // try custom logo second
222 213 if ( ! $icon_id ) {
223 214 $icon_id = get_theme_mod( 'custom_logo' );
224 215 }
225 216
@@ -232,9 +223,9 @@
232 223 }
233 224 }
234 225
235 226 if ( ! $icon_url ) {
236 - // Fallback to default icon.
227 + // fallback to default icon
237 228 $icon_url = plugins_url( '/assets/img/wp-logo.png', ACTIVITYPUB_PLUGIN_FILE );
238 229 }
239 230
240 231 return array(
@@ -245,9 +236,9 @@
245 236
246 237 /**
247 238 * Get the User-Header-Image.
248 239 *
249 - * @return string[]|null The User-Header-Image.
240 + * @return array|null The User-Header-Image.
250 241 */
251 242 public function get_image() {
252 243 $header_image = get_option( 'activitypub_header_image' );
253 244 $image_url = null;
@@ -269,68 +260,30 @@
269 260
270 261 return null;
271 262 }
272 263
273 - /**
274 - * Get the published date.
275 - *
276 - * @return string The published date.
277 - */
278 264 public function get_published() {
279 - $published = \get_option( 'activitypub_blog_published' );
280 -
281 - if ( $published ) {
282 - return $published;
283 - }
284 -
285 - // Backfill from the first federated post.
286 - $first_federated = new \WP_Query(
265 + $first_post = new WP_Query(
287 266 array(
288 - 'orderby' => 'date',
289 - 'order' => 'ASC',
290 - 'posts_per_page' => 1,
291 - 'post_status' => 'publish',
292 - 'no_found_rows' => true,
293 - 'ignore_sticky_posts' => true,
294 - 'update_post_meta_cache' => false,
295 - 'update_post_term_cache' => false,
296 - // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
297 - 'meta_query' => array(
298 - array(
299 - 'key' => 'activitypub_status',
300 - 'compare' => 'EXISTS',
301 - ),
302 - ),
267 + 'orderby' => 'date',
268 + 'order' => 'ASC',
269 + 'number' => 1,
303 270 )
304 271 );
305 272
306 - if ( ! empty( $first_federated->posts[0] ) ) {
307 - $time = \strtotime( $first_federated->posts[0]->post_date_gmt );
273 + if ( ! empty( $first_post->posts[0] ) ) {
274 + $time = \strtotime( $first_post->posts[0]->post_date_gmt );
308 275 } else {
309 276 $time = \time();
310 277 }
311 278
312 - $published = \gmdate( ACTIVITYPUB_DATE_TIME_RFC3339, $time );
313 -
314 - \update_option( 'activitypub_blog_published', $published, false );
315 -
316 - return $published;
279 + return \gmdate( 'Y-m-d\TH:i:s\Z', $time );
317 280 }
318 281
319 - /**
320 - * Get the canonical URL.
321 - *
322 - * @return string|null The canonical URL.
323 - */
324 282 public function get_canonical_url() {
325 283 return \home_url();
326 284 }
327 285
328 - /**
329 - * Get the Moderators endpoint.
330 - *
331 - * @return string|null The Moderators endpoint.
332 - */
333 286 public function get_moderators() {
334 287 if ( is_single_user() || 'Group' !== $this->get_type() ) {
335 288 return null;
336 289 }
@@ -337,13 +290,8 @@
337 290
338 291 return get_rest_url_by_path( 'collections/moderators' );
339 292 }
340 293
341 - /**
342 - * Get attributedTo value.
343 - *
344 - * @return string|null The attributedTo value.
345 - */
346 294 public function get_attributed_to() {
347 295 if ( is_single_user() || 'Group' !== $this->get_type() ) {
348 296 return null;
349 297 }
@@ -350,26 +298,16 @@
350 298
351 299 return get_rest_url_by_path( 'collections/moderators' );
352 300 }
353 301
354 - /**
355 - * Get the public key information.
356 - *
357 - * @return string[] The public key.
358 - */
359 302 public function get_public_key() {
360 303 return array(
361 - 'id' => $this->get_id() . '#main-key',
362 - 'owner' => $this->get_id(),
363 - 'publicKeyPem' => Actors::get_public_key( $this->get__id() ),
304 + 'id' => $this->get_id() . '#main-key',
305 + 'owner' => $this->get_id(),
306 + 'publicKeyPem' => Signature::get_public_key_for( $this->get__id() ),
364 307 );
365 308 }
366 309
367 - /**
368 - * Returns whether posting is restricted to mods.
369 - *
370 - * @return bool|null True if posting is restricted to mods, null if not applicable.
371 - */
372 310 public function get_posting_restricted_to_mods() {
373 311 if ( 'Group' === $this->get_type() ) {
374 312 return true;
375 313 }
@@ -412,22 +350,18 @@
412 350 public function get_following() {
413 351 return get_rest_url_by_path( sprintf( 'actors/%d/following', $this->get__id() ) );
414 352 }
415 353
416 - /**
417 - * Returns endpoints.
418 - *
419 - * @return string[]|null The endpoints.
420 - */
421 354 public function get_endpoints() {
422 - return array(
423 - 'sharedInbox' => get_rest_url_by_path( 'inbox' ),
424 - 'oauthAuthorizationEndpoint' => get_rest_url_by_path( 'oauth/authorize' ),
425 - 'oauthTokenEndpoint' => get_rest_url_by_path( 'oauth/token' ),
426 - 'oauthRegistrationEndpoint' => get_rest_url_by_path( 'oauth/clients' ),
427 - 'proxyUrl' => get_rest_url_by_path( 'proxy' ),
428 - 'proxyEventStream' => get_rest_url_by_path( 'proxy/stream' ),
429 - );
355 + $endpoints = null;
356 +
357 + if ( ACTIVITYPUB_SHARED_INBOX_FEATURE ) {
358 + $endpoints = array(
359 + 'sharedInbox' => get_rest_url_by_path( 'inbox' ),
360 + );
361 + }
362 +
363 + return $endpoints;
430 364 }
431 365
432 366 /**
433 367 * Returns a user@domain type of identifier for the user.
@@ -438,19 +372,8 @@
438 372 return $this->get_preferred_username() . '@' . \wp_parse_url( \home_url(), \PHP_URL_HOST );
439 373 }
440 374
441 375 /**
442 - * Returns the Liked API endpoint.
443 - *
444 - * @since 8.1.0
445 - *
446 - * @return string The Liked endpoint.
447 - */
448 - public function get_liked() {
449 - return get_rest_url_by_path( sprintf( 'actors/%d/liked', $this->get__id() ) );
450 - }
451 -
452 - /**
453 376 * Returns the Featured-API-Endpoint.
454 377 *
455 378 * @return string The Featured-Endpoint.
456 379 */
@@ -457,22 +380,8 @@
457 380 public function get_featured() {
458 381 return get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $this->get__id() ) );
459 382 }
460 383
461 - /**
462 - * Returns the Featured-Tags-API-Endpoint.
463 - *
464 - * @return string The Featured-Tags-Endpoint.
465 - */
466 - public function get_featured_tags() {
467 - return get_rest_url_by_path( sprintf( 'actors/%d/collections/tags', $this->get__id() ) );
468 - }
469 -
470 - /**
471 - * Returns whether the site is indexable.
472 - *
473 - * @return bool Whether the site is indexable.
474 - */
475 384 public function get_indexable() {
476 385 if ( is_blog_public() ) {
477 386 return true;
478 387 } else {
@@ -480,59 +389,13 @@
480 389 }
481 390 }
482 391
483 392 /**
484 - * Update the Username.
393 + * Get the User-Hashtags.
485 394 *
486 - * @param mixed $value The new value.
487 - * @return bool True if the attribute was updated, false otherwise.
488 - */
489 - public function update_name( $value ) {
490 - return \update_option( 'blogname', $value );
491 - }
492 -
493 - /**
494 - * Update the User description.
495 - *
496 - * @param mixed $value The new value.
497 - * @return bool True if the attribute was updated, false otherwise.
498 - */
499 - public function update_summary( $value ) {
500 - return \update_option( 'blogdescription', $value );
501 - }
502 -
503 - /**
504 - * Update the User icon.
505 - *
506 - * @param mixed $value The new value.
507 - * @return bool True if the attribute was updated, false otherwise.
508 - */
509 - public function update_icon( $value ) {
510 - if ( ! wp_attachment_is_image( $value ) ) {
511 - return false;
512 - }
513 - return \update_option( 'site_icon', $value );
514 - }
515 -
516 - /**
517 - * Update the User-Header-Image.
518 - *
519 - * @param mixed $value The new value.
520 - * @return bool True if the attribute was updated, false otherwise.
521 - */
522 - public function update_header( $value ) {
523 - if ( ! wp_attachment_is_image( $value ) ) {
524 - return false;
525 - }
526 - return \update_option( 'activitypub_header_image', $value );
527 - }
528 -
529 - /**
530 - * Get the User - Hashtags.
531 - *
532 395 * @see https://docs.joinmastodon.org/spec/activitypub/#Hashtag
533 396 *
534 - * @return string[] The User - Hashtags.
397 + * @return array The User-Hashtags.
535 398 */
536 399 public function get_tag() {
537 400 $hashtags = array();
538 401
@@ -562,43 +425,6 @@
562 425 */
563 426 public function get_attachment() {
564 427 $extra_fields = Extra_Fields::get_actor_fields( $this->_id );
565 428 return Extra_Fields::fields_to_attachments( $extra_fields );
566 - }
567 -
568 - /**
569 - * Returns the website hosts allowed to credit this blog.
570 - *
571 - * @return string[]|null The attribution domains or null if not found.
572 - */
573 - public function get_attribution_domains() {
574 - return get_attribution_domains();
575 - }
576 -
577 - /**
578 - * Returns the alsoKnownAs.
579 - *
580 - * @return string[] The alsoKnownAs.
581 - */
582 - public function get_also_known_as() {
583 - $also_known_as = array(
584 - \add_query_arg( 'author', $this->_id, \home_url( '/' ) ),
585 - $this->get_url(),
586 - $this->get_alternate_url(),
587 - );
588 -
589 - $also_known_as = array_merge( $also_known_as, \get_option( 'activitypub_blog_user_also_known_as', array() ) );
590 -
591 - return array_unique( $also_known_as );
592 - }
593 -
594 - /**
595 - * Returns the movedTo.
596 - *
597 - * @return string The movedTo.
598 - */
599 - public function get_moved_to() {
600 - $moved_to = \get_option( 'activitypub_blog_user_moved_to' );
601 -
602 - return $moved_to && $moved_to !== $this->get_id() ? $moved_to : null;
603 429 }
604 430 }