PluginProbe
ActivityPub / 4.7.1
ActivityPub v4.7.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 / model / class-blog.php

class-blog.php in ActivityPub 4.7.1, at includes/model/class-blog.php

554 lines 11.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Blog model file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Model;
9
10 use WP_Query;
11
12 use Activitypub\Signature;
13 use Activitypub\Activity\Actor;
14 use Activitypub\Collection\Actors;
15 use Activitypub\Collection\Extra_Fields;
16
17 use function Activitypub\esc_hashtag;
18 use function Activitypub\is_single_user;
19 use function Activitypub\is_blog_public;
20 use function Activitypub\get_rest_url_by_path;
21 use function Activitypub\get_attribution_domains;
22
23 /**
24 * Blog class.
25 */
26 class Blog extends Actor {
27 /**
28 * The Featured-Posts.
29 *
30 * @see https://docs.joinmastodon.org/spec/activitypub/#featured
31 *
32 * @context {
33 * "@id": "http://joinmastodon.org/ns#featured",
34 * "@type": "@id"
35 * }
36 *
37 * @var string
38 */
39 protected $featured;
40
41 /**
42 * Moderators endpoint.
43 *
44 * @see https://join-lemmy.org/docs/contributors/05-federation.html
45 *
46 * @var string
47 */
48 protected $moderators;
49
50 /**
51 * The User-ID
52 *
53 * @var int
54 */
55 protected $_id = Actors::BLOG_USER_ID; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
56
57 /**
58 * If the User is indexable.
59 *
60 * @context http://joinmastodon.org/ns#indexable
61 *
62 * @var boolean
63 */
64 protected $indexable;
65
66 /**
67 * The WebFinger Resource.
68 *
69 * @var string
70 */
71 protected $webfinger;
72
73 /**
74 * Whether the User is discoverable.
75 *
76 * @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
77 *
78 * @context http://joinmastodon.org/ns#discoverable
79 *
80 * @var boolean
81 */
82 protected $discoverable;
83
84 /**
85 * Restrict posting to mods.
86 *
87 * @see https://join-lemmy.org/docs/contributors/05-federation.html
88 *
89 * @var boolean
90 */
91 protected $posting_restricted_to_mods;
92
93 /**
94 * Whether the User manually approves followers.
95 *
96 * @return false
97 */
98 public function get_manually_approves_followers() {
99 return false;
100 }
101
102 /**
103 * Whether the User is discoverable.
104 *
105 * @return boolean
106 */
107 public function get_discoverable() {
108 return true;
109 }
110
111 /**
112 * Get the User ID.
113 *
114 * @return string The User ID.
115 */
116 public function get_id() {
117 $permalink = \get_option( 'activitypub_use_permalink_as_id_for_blog', false );
118
119 if ( $permalink ) {
120 return $this->get_url();
121 }
122
123 return \add_query_arg( 'author', $this->_id, \trailingslashit( \home_url() ) );
124 }
125
126 /**
127 * Get the type of the object.
128 *
129 * If the Blog is in "single user" mode, return "Person" insted of "Group".
130 *
131 * @return string The type of the object.
132 */
133 public function get_type() {
134 if ( is_single_user() ) {
135 return 'Person';
136 } else {
137 return 'Group';
138 }
139 }
140
141 /**
142 * Get the Username.
143 *
144 * @return string The Username.
145 */
146 public function get_name() {
147 return \wp_strip_all_tags(
148 \html_entity_decode(
149 \get_bloginfo( 'name' ),
150 \ENT_QUOTES,
151 'UTF-8'
152 )
153 );
154 }
155
156 /**
157 * Get the User description.
158 *
159 * @return string The User description.
160 */
161 public function get_summary() {
162 $summary = \get_option( 'activitypub_blog_description', null );
163
164 if ( ! $summary ) {
165 $summary = \get_bloginfo( 'description' );
166 }
167
168 return \wpautop(
169 \wp_kses(
170 $summary,
171 'default'
172 )
173 );
174 }
175
176 /**
177 * Get the User url.
178 *
179 * @return string The User url.
180 */
181 public function get_url() {
182 return \esc_url( \trailingslashit( get_home_url() ) . '@' . $this->get_preferred_username() );
183 }
184
185 /**
186 * Get blog's homepage URL.
187 *
188 * @return string The User-Url.
189 */
190 public function get_alternate_url() {
191 return \esc_url( \trailingslashit( get_home_url() ) );
192 }
193
194 /**
195 * Generate a default Username.
196 *
197 * @return string The auto-generated Username.
198 */
199 public static function get_default_username() {
200 // Check if domain host has a subdomain.
201 $host = \wp_parse_url( \get_home_url(), \PHP_URL_HOST );
202 $host = \preg_replace( '/^www\./i', '', $host );
203
204 /**
205 * Filters the default blog username.
206 *
207 * This filter allows developers to modify the default username that is
208 * generated for the blog, which by default is the site's host name
209 * without the 'www.' prefix.
210 *
211 * @param string $host The default username (site's host name).
212 */
213 return apply_filters( 'activitypub_default_blog_username', $host );
214 }
215
216 /**
217 * Get the preferred Username.
218 *
219 * @return string The Username.
220 */
221 public function get_preferred_username() {
222 $username = \get_option( 'activitypub_blog_identifier' );
223
224 if ( $username ) {
225 return $username;
226 }
227
228 return self::get_default_username();
229 }
230
231 /**
232 * Get the User icon.
233 *
234 * @return array The User icon.
235 */
236 public function get_icon() {
237 // Try site_logo, falling back to site_icon, first.
238 $icon_id = get_option( 'site_icon' );
239
240 // Try custom logo second.
241 if ( ! $icon_id ) {
242 $icon_id = get_theme_mod( 'custom_logo' );
243 }
244
245 $icon_url = false;
246
247 if ( $icon_id ) {
248 $icon = wp_get_attachment_image_src( $icon_id, 'full' );
249 if ( $icon ) {
250 $icon_url = $icon[0];
251 }
252 }
253
254 if ( ! $icon_url ) {
255 // Fallback to default icon.
256 $icon_url = plugins_url( '/assets/img/wp-logo.png', ACTIVITYPUB_PLUGIN_FILE );
257 }
258
259 return array(
260 'type' => 'Image',
261 'url' => esc_url( $icon_url ),
262 );
263 }
264
265 /**
266 * Get the User-Header-Image.
267 *
268 * @return array|null The User-Header-Image.
269 */
270 public function get_image() {
271 $header_image = get_option( 'activitypub_header_image' );
272 $image_url = null;
273
274 if ( $header_image ) {
275 $image_url = \wp_get_attachment_url( $header_image );
276 }
277
278 if ( ! $image_url && \has_header_image() ) {
279 $image_url = \get_header_image();
280 }
281
282 if ( $image_url ) {
283 return array(
284 'type' => 'Image',
285 'url' => esc_url( $image_url ),
286 );
287 }
288
289 return null;
290 }
291
292 /**
293 * Get the published date.
294 *
295 * @return string The published date.
296 */
297 public function get_published() {
298 $first_post = new WP_Query(
299 array(
300 'orderby' => 'date',
301 'order' => 'ASC',
302 'number' => 1,
303 )
304 );
305
306 if ( ! empty( $first_post->posts[0] ) ) {
307 $time = \strtotime( $first_post->posts[0]->post_date_gmt );
308 } else {
309 $time = \time();
310 }
311
312 return \gmdate( 'Y-m-d\TH:i:s\Z', $time );
313 }
314
315 /**
316 * Get the canonical URL.
317 *
318 * @return string|null The canonical URL.
319 */
320 public function get_canonical_url() {
321 return \home_url();
322 }
323
324 /**
325 * Get the Moderators endpoint.
326 *
327 * @return string|null The Moderators endpoint.
328 */
329 public function get_moderators() {
330 if ( is_single_user() || 'Group' !== $this->get_type() ) {
331 return null;
332 }
333
334 return get_rest_url_by_path( 'collections/moderators' );
335 }
336
337 /**
338 * Get attributedTo value.
339 *
340 * @return string|null The attributedTo value.
341 */
342 public function get_attributed_to() {
343 if ( is_single_user() || 'Group' !== $this->get_type() ) {
344 return null;
345 }
346
347 return get_rest_url_by_path( 'collections/moderators' );
348 }
349
350 /**
351 * Get the public key information.
352 *
353 * @return array The public key.
354 */
355 public function get_public_key() {
356 return array(
357 'id' => $this->get_id() . '#main-key',
358 'owner' => $this->get_id(),
359 'publicKeyPem' => Signature::get_public_key_for( $this->get__id() ),
360 );
361 }
362
363 /**
364 * Returns whether posting is restricted to mods.
365 *
366 * @return bool|null True if posting is restricted to mods, null if not applicable.
367 */
368 public function get_posting_restricted_to_mods() {
369 if ( 'Group' === $this->get_type() ) {
370 return true;
371 }
372
373 return null;
374 }
375
376 /**
377 * Returns the Inbox-API-Endpoint.
378 *
379 * @return string The Inbox-Endpoint.
380 */
381 public function get_inbox() {
382 return get_rest_url_by_path( sprintf( 'actors/%d/inbox', $this->get__id() ) );
383 }
384
385 /**
386 * Returns the Outbox-API-Endpoint.
387 *
388 * @return string The Outbox-Endpoint.
389 */
390 public function get_outbox() {
391 return get_rest_url_by_path( sprintf( 'actors/%d/outbox', $this->get__id() ) );
392 }
393
394 /**
395 * Returns the Followers-API-Endpoint.
396 *
397 * @return string The Followers-Endpoint.
398 */
399 public function get_followers() {
400 return get_rest_url_by_path( sprintf( 'actors/%d/followers', $this->get__id() ) );
401 }
402
403 /**
404 * Returns the Following-API-Endpoint.
405 *
406 * @return string The Following-Endpoint.
407 */
408 public function get_following() {
409 return get_rest_url_by_path( sprintf( 'actors/%d/following', $this->get__id() ) );
410 }
411
412 /**
413 * Returns endpoints.
414 *
415 * @return array|null The endpoints.
416 */
417 public function get_endpoints() {
418 $endpoints = null;
419
420 if ( ACTIVITYPUB_SHARED_INBOX_FEATURE ) {
421 $endpoints = array(
422 'sharedInbox' => get_rest_url_by_path( 'inbox' ),
423 );
424 }
425
426 return $endpoints;
427 }
428
429 /**
430 * Returns a user@domain type of identifier for the user.
431 *
432 * @return string The Webfinger-Identifier.
433 */
434 public function get_webfinger() {
435 return $this->get_preferred_username() . '@' . \wp_parse_url( \home_url(), \PHP_URL_HOST );
436 }
437
438 /**
439 * Returns the Featured-API-Endpoint.
440 *
441 * @return string The Featured-Endpoint.
442 */
443 public function get_featured() {
444 return get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $this->get__id() ) );
445 }
446
447 /**
448 * Returns whether the site is indexable.
449 *
450 * @return bool Whether the site is indexable.
451 */
452 public function get_indexable() {
453 if ( is_blog_public() ) {
454 return true;
455 } else {
456 return false;
457 }
458 }
459
460 /**
461 * Update the Username.
462 *
463 * @param mixed $value The new value.
464 * @return bool True if the attribute was updated, false otherwise.
465 */
466 public function update_name( $value ) {
467 return \update_option( 'blogname', $value );
468 }
469
470 /**
471 * Update the User description.
472 *
473 * @param mixed $value The new value.
474 * @return bool True if the attribute was updated, false otherwise.
475 */
476 public function update_summary( $value ) {
477 return \update_option( 'blogdescription', $value );
478 }
479
480 /**
481 * Update the User icon.
482 *
483 * @param mixed $value The new value.
484 * @return bool True if the attribute was updated, false otherwise.
485 */
486 public function update_icon( $value ) {
487 if ( ! wp_attachment_is_image( $value ) ) {
488 return false;
489 }
490 return \update_option( 'site_icon', $value );
491 }
492
493 /**
494 * Update the User-Header-Image.
495 *
496 * @param mixed $value The new value.
497 * @return bool True if the attribute was updated, false otherwise.
498 */
499 public function update_header( $value ) {
500 if ( ! wp_attachment_is_image( $value ) ) {
501 return false;
502 }
503 return \update_option( 'activitypub_header_image', $value );
504 }
505
506 /**
507 * Get the User - Hashtags.
508 *
509 * @see https://docs.joinmastodon.org/spec/activitypub/#Hashtag
510 *
511 * @return array The User - Hashtags.
512 */
513 public function get_tag() {
514 $hashtags = array();
515
516 $args = array(
517 'orderby' => 'count',
518 'order' => 'DESC',
519 'number' => 10,
520 );
521
522 $tags = get_tags( $args );
523
524 foreach ( $tags as $tag ) {
525 $hashtags[] = array(
526 'type' => 'Hashtag',
527 'href' => \get_tag_link( $tag->term_id ),
528 'name' => esc_hashtag( $tag->name ),
529 );
530 }
531
532 return $hashtags;
533 }
534
535 /**
536 * Extend the User-Output with Attachments.
537 *
538 * @return array The extended User-Output.
539 */
540 public function get_attachment() {
541 $extra_fields = Extra_Fields::get_actor_fields( $this->_id );
542 return Extra_Fields::fields_to_attachments( $extra_fields );
543 }
544
545 /**
546 * Returns the website hosts allowed to credit this blog.
547 *
548 * @return array|null The attribution domains or null if not found.
549 */
550 public function get_attribution_domains() {
551 return get_attribution_domains();
552 }
553 }
554