| @@ -15,9 +15,8 @@ | ||
| 15 | 15 | use function Activitypub\get_attribution_domains; |
| 16 | 16 | use function Activitypub\get_rest_url_by_path; |
| 17 | 17 | use function Activitypub\is_blog_public; |
| 18 | 18 | use function Activitypub\is_single_user; |
| 19 | -use function Activitypub\site_icon; | |
| 20 | 19 | |
| 21 | 20 | /** |
| 22 | 21 | * Blog class. |
| 23 | 22 | * |
| @@ -93,9 +92,9 @@ | ||
| 93 | 92 | |
| 94 | 93 | $permalink = \get_option( 'activitypub_use_permalink_as_id_for_blog', false ); |
| 95 | 94 | |
| 96 | 95 | if ( $permalink ) { |
| 97 | - return \esc_url_raw( \home_url( '/@' . $this->get_preferred_username() ) ); | |
| 96 | + return \esc_url( \trailingslashit( get_home_url() ) . '@' . $this->get_preferred_username() ); | |
| 98 | 97 | } |
| 99 | 98 | |
| 100 | 99 | return \add_query_arg( 'author', $this->_id, \home_url( '/' ) ); |
| 101 | 100 | } |
| @@ -102,18 +101,13 @@ | ||
| 102 | 101 | |
| 103 | 102 | /** |
| 104 | 103 | * Get the type of the object. |
| 105 | 104 | * |
| 106 | - * If relay mode is enabled, return "Service". | |
| 107 | 105 | * If the Blog is in "single user" mode, return "Person" instead of "Group". |
| 108 | 106 | * |
| 109 | 107 | * @return string The type of the object. |
| 110 | 108 | */ |
| 111 | 109 | public function get_type() { |
| 112 | - if ( \get_option( 'activitypub_relay_mode', false ) ) { | |
| 113 | - return 'Service'; | |
| 114 | - } | |
| 115 | - | |
| 116 | 110 | if ( is_single_user() ) { |
| 117 | 111 | return 'Person'; |
| 118 | 112 | } else { |
| 119 | 113 | return 'Group'; |
| @@ -169,9 +163,9 @@ | ||
| 169 | 163 | * |
| 170 | 164 | * @return string The User-Url. |
| 171 | 165 | */ |
| 172 | 166 | public function get_alternate_url() { |
| 173 | - return \esc_url_raw( \trailingslashit( \get_home_url() ) ); | |
| 167 | + return \esc_url( \trailingslashit( get_home_url() ) ); | |
| 174 | 168 | } |
| 175 | 169 | |
| 176 | 170 | /** |
| 177 | 171 | * Generate a default Username. |
| @@ -191,9 +185,9 @@ | ||
| 191 | 185 | * without the 'www.' prefix. |
| 192 | 186 | * |
| 193 | 187 | * @param string $host The default username (site's host name). |
| 194 | 188 | */ |
| 195 | - return \apply_filters( 'activitypub_default_blog_username', $host ); | |
| 189 | + return apply_filters( 'activitypub_default_blog_username', $host ); | |
| 196 | 190 | } |
| 197 | 191 | |
| 198 | 192 | /** |
| 199 | 193 | * Get the preferred Username. |
| @@ -215,9 +209,34 @@ | ||
| 215 | 209 | * |
| 216 | 210 | * @return string[] The User icon. |
| 217 | 211 | */ |
| 218 | 212 | public function get_icon() { |
| 219 | - return site_icon(); | |
| 213 | + // Try site_logo, falling back to site_icon, first. | |
| 214 | + $icon_id = get_option( 'site_icon' ); | |
| 215 | + | |
| 216 | + // Try custom logo second. | |
| 217 | + if ( ! $icon_id ) { | |
| 218 | + $icon_id = get_theme_mod( 'custom_logo' ); | |
| 219 | + } | |
| 220 | + | |
| 221 | + $icon_url = false; | |
| 222 | + | |
| 223 | + if ( $icon_id ) { | |
| 224 | + $icon = wp_get_attachment_image_src( $icon_id, 'full' ); | |
| 225 | + if ( $icon ) { | |
| 226 | + $icon_url = $icon[0]; | |
| 227 | + } | |
| 228 | + } | |
| 229 | + | |
| 230 | + if ( ! $icon_url ) { | |
| 231 | + // Fallback to default icon. | |
| 232 | + $icon_url = plugins_url( '/assets/img/wp-logo.png', ACTIVITYPUB_PLUGIN_FILE ); | |
| 233 | + } | |
| 234 | + | |
| 235 | + return array( | |
| 236 | + 'type' => 'Image', | |
| 237 | + 'url' => esc_url( $icon_url ), | |
| 238 | + ); | |
| 220 | 239 | } |
| 221 | 240 | |
| 222 | 241 | /** |
| 223 | 242 | * Get the User-Header-Image. |
| @@ -224,9 +243,9 @@ | ||
| 224 | 243 | * |
| 225 | 244 | * @return string[]|null The User-Header-Image. |
| 226 | 245 | */ |
| 227 | 246 | public function get_image() { |
| 228 | - $header_image = \get_option( 'activitypub_header_image' ); | |
| 247 | + $header_image = get_option( 'activitypub_header_image' ); | |
| 229 | 248 | $image_url = null; |
| 230 | 249 | |
| 231 | 250 | if ( $header_image ) { |
| 232 | 251 | $image_url = \wp_get_attachment_url( $header_image ); |
| @@ -238,9 +257,9 @@ | ||
| 238 | 257 | |
| 239 | 258 | if ( $image_url ) { |
| 240 | 259 | return array( |
| 241 | 260 | 'type' => 'Image', |
| 242 | - 'url' => \esc_url_raw( $image_url ), | |
| 261 | + 'url' => esc_url( $image_url ), | |
| 243 | 262 | ); |
| 244 | 263 | } |
| 245 | 264 | |
| 246 | 265 | return null; |
| @@ -251,46 +270,23 @@ | ||
| 251 | 270 | * |
| 252 | 271 | * @return string The published date. |
| 253 | 272 | */ |
| 254 | 273 | public function get_published() { |
| 255 | - $published = \get_option( 'activitypub_blog_published' ); | |
| 256 | - | |
| 257 | - if ( $published ) { | |
| 258 | - return $published; | |
| 259 | - } | |
| 260 | - | |
| 261 | - // Backfill from the first federated post. | |
| 262 | - $first_federated = new \WP_Query( | |
| 274 | + $first_post = new \WP_Query( | |
| 263 | 275 | array( |
| 264 | - 'orderby' => 'date', | |
| 265 | - 'order' => 'ASC', | |
| 266 | - 'posts_per_page' => 1, | |
| 267 | - 'post_status' => 'publish', | |
| 268 | - 'no_found_rows' => true, | |
| 269 | - 'ignore_sticky_posts' => true, | |
| 270 | - 'update_post_meta_cache' => false, | |
| 271 | - 'update_post_term_cache' => false, | |
| 272 | - // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query | |
| 273 | - 'meta_query' => array( | |
| 274 | - array( | |
| 275 | - 'key' => 'activitypub_status', | |
| 276 | - 'compare' => 'EXISTS', | |
| 277 | - ), | |
| 278 | - ), | |
| 276 | + 'orderby' => 'date', | |
| 277 | + 'order' => 'ASC', | |
| 278 | + 'number' => 1, | |
| 279 | 279 | ) |
| 280 | 280 | ); |
| 281 | 281 | |
| 282 | - if ( ! empty( $first_federated->posts[0] ) ) { | |
| 283 | - $time = \strtotime( $first_federated->posts[0]->post_date_gmt ); | |
| 282 | + if ( ! empty( $first_post->posts[0] ) ) { | |
| 283 | + $time = \strtotime( $first_post->posts[0]->post_date_gmt ); | |
| 284 | 284 | } else { |
| 285 | 285 | $time = \time(); |
| 286 | 286 | } |
| 287 | 287 | |
| 288 | - $published = \gmdate( ACTIVITYPUB_DATE_TIME_RFC3339, $time ); | |
| 289 | - | |
| 290 | - \update_option( 'activitypub_blog_published', $published, false ); | |
| 291 | - | |
| 292 | - return $published; | |
| 288 | + return \gmdate( ACTIVITYPUB_DATE_TIME_RFC3339, $time ); | |
| 293 | 289 | } |
| 294 | 290 | |
| 295 | 291 | /** |
| 296 | 292 | * Get the canonical URL. |
| @@ -358,9 +354,9 @@ | ||
| 358 | 354 | * |
| 359 | 355 | * @return string The Inbox-Endpoint. |
| 360 | 356 | */ |
| 361 | 357 | public function get_inbox() { |
| 362 | - return get_rest_url_by_path( \sprintf( 'actors/%d/inbox', $this->get__id() ) ); | |
| 358 | + return get_rest_url_by_path( sprintf( 'actors/%d/inbox', $this->get__id() ) ); | |
| 363 | 359 | } |
| 364 | 360 | |
| 365 | 361 | /** |
| 366 | 362 | * Returns the Outbox-API-Endpoint. |
| @@ -367,9 +363,9 @@ | ||
| 367 | 363 | * |
| 368 | 364 | * @return string The Outbox-Endpoint. |
| 369 | 365 | */ |
| 370 | 366 | public function get_outbox() { |
| 371 | - return get_rest_url_by_path( \sprintf( 'actors/%d/outbox', $this->get__id() ) ); | |
| 367 | + return get_rest_url_by_path( sprintf( 'actors/%d/outbox', $this->get__id() ) ); | |
| 372 | 368 | } |
| 373 | 369 | |
| 374 | 370 | /** |
| 375 | 371 | * Returns the Followers-API-Endpoint. |
| @@ -376,9 +372,9 @@ | ||
| 376 | 372 | * |
| 377 | 373 | * @return string The Followers-Endpoint. |
| 378 | 374 | */ |
| 379 | 375 | public function get_followers() { |
| 380 | - return get_rest_url_by_path( \sprintf( 'actors/%d/followers', $this->get__id() ) ); | |
| 376 | + return get_rest_url_by_path( sprintf( 'actors/%d/followers', $this->get__id() ) ); | |
| 381 | 377 | } |
| 382 | 378 | |
| 383 | 379 | /** |
| 384 | 380 | * Returns the Following-API-Endpoint. |
| @@ -385,9 +381,9 @@ | ||
| 385 | 381 | * |
| 386 | 382 | * @return string The Following-Endpoint. |
| 387 | 383 | */ |
| 388 | 384 | public function get_following() { |
| 389 | - return get_rest_url_by_path( \sprintf( 'actors/%d/following', $this->get__id() ) ); | |
| 385 | + return get_rest_url_by_path( sprintf( 'actors/%d/following', $this->get__id() ) ); | |
| 390 | 386 | } |
| 391 | 387 | |
| 392 | 388 | /** |
| 393 | 389 | * Returns endpoints. |
| @@ -394,26 +390,11 @@ | ||
| 394 | 390 | * |
| 395 | 391 | * @return string[]|null The endpoints. |
| 396 | 392 | */ |
| 397 | 393 | public function get_endpoints() { |
| 398 | - $endpoints = array( | |
| 399 | - 'sharedInbox' => get_rest_url_by_path( 'inbox' ), | |
| 400 | - 'oauthAuthorizationEndpoint' => get_rest_url_by_path( 'oauth/authorize' ), | |
| 401 | - 'oauthTokenEndpoint' => get_rest_url_by_path( 'oauth/token' ), | |
| 402 | - 'oauthRegistrationEndpoint' => get_rest_url_by_path( 'oauth/clients' ), | |
| 403 | - 'proxyUrl' => get_rest_url_by_path( 'proxy' ), | |
| 404 | - 'proxyEventStream' => get_rest_url_by_path( 'proxy/stream' ), | |
| 394 | + return array( | |
| 395 | + 'sharedInbox' => get_rest_url_by_path( 'inbox' ), | |
| 405 | 396 | ); |
| 406 | - | |
| 407 | - if ( \get_option( 'activitypub_api', false ) ) { | |
| 408 | - /* | |
| 409 | - * RFC 6570 template. add_query_arg() picks the ?/& separator (plain permalinks already | |
| 410 | - * carry a query string) and does not encode values, so the {q} placeholder stays intact. | |
| 411 | - */ | |
| 412 | - $endpoints['actorAutocomplete'] = \add_query_arg( 'q', '{q}', get_rest_url_by_path( 'actors/autocomplete' ) ); | |
| 413 | - } | |
| 414 | - | |
| 415 | - return $endpoints; | |
| 416 | 397 | } |
| 417 | 398 | |
| 418 | 399 | /** |
| 419 | 400 | * Returns a user@domain type of identifier for the user. |
| @@ -424,25 +405,14 @@ | ||
| 424 | 405 | return $this->get_preferred_username() . '@' . \wp_parse_url( \home_url(), \PHP_URL_HOST ); |
| 425 | 406 | } |
| 426 | 407 | |
| 427 | 408 | /** |
| 428 | - * Returns the Liked API endpoint. | |
| 429 | - * | |
| 430 | - * @since 8.1.0 | |
| 431 | - * | |
| 432 | - * @return string The Liked endpoint. | |
| 433 | - */ | |
| 434 | - public function get_liked() { | |
| 435 | - return get_rest_url_by_path( \sprintf( 'actors/%d/liked', $this->get__id() ) ); | |
| 436 | - } | |
| 437 | - | |
| 438 | - /** | |
| 439 | 409 | * Returns the Featured-API-Endpoint. |
| 440 | 410 | * |
| 441 | 411 | * @return string The Featured-Endpoint. |
| 442 | 412 | */ |
| 443 | 413 | public function get_featured() { |
| 444 | - return get_rest_url_by_path( \sprintf( 'actors/%d/collections/featured', $this->get__id() ) ); | |
| 414 | + return get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $this->get__id() ) ); | |
| 445 | 415 | } |
| 446 | 416 | |
| 447 | 417 | /** |
| 448 | 418 | * Returns the Featured-Tags-API-Endpoint. |
| @@ -449,9 +419,9 @@ | ||
| 449 | 419 | * |
| 450 | 420 | * @return string The Featured-Tags-Endpoint. |
| 451 | 421 | */ |
| 452 | 422 | public function get_featured_tags() { |
| 453 | - return get_rest_url_by_path( \sprintf( 'actors/%d/collections/tags', $this->get__id() ) ); | |
| 423 | + return get_rest_url_by_path( sprintf( 'actors/%d/collections/tags', $this->get__id() ) ); | |
| 454 | 424 | } |
| 455 | 425 | |
| 456 | 426 | /** |
| 457 | 427 | * Returns whether the site is indexable. |
| @@ -492,9 +462,9 @@ | ||
| 492 | 462 | * @param mixed $value The new value. |
| 493 | 463 | * @return bool True if the attribute was updated, false otherwise. |
| 494 | 464 | */ |
| 495 | 465 | public function update_icon( $value ) { |
| 496 | - if ( ! \wp_attachment_is_image( $value ) ) { | |
| 466 | + if ( ! wp_attachment_is_image( $value ) ) { | |
| 497 | 467 | return false; |
| 498 | 468 | } |
| 499 | 469 | return \update_option( 'site_icon', $value ); |
| 500 | 470 | } |
| @@ -505,9 +475,9 @@ | ||
| 505 | 475 | * @param mixed $value The new value. |
| 506 | 476 | * @return bool True if the attribute was updated, false otherwise. |
| 507 | 477 | */ |
| 508 | 478 | public function update_header( $value ) { |
| 509 | - if ( ! \wp_attachment_is_image( $value ) ) { | |
| 479 | + if ( ! wp_attachment_is_image( $value ) ) { | |
| 510 | 480 | return false; |
| 511 | 481 | } |
| 512 | 482 | return \update_option( 'activitypub_header_image', $value ); |
| 513 | 483 | } |
| @@ -527,9 +497,9 @@ | ||
| 527 | 497 | 'order' => 'DESC', |
| 528 | 498 | 'number' => 10, |
| 529 | 499 | ); |
| 530 | 500 | |
| 531 | - $tags = \get_tags( $args ); | |
| 501 | + $tags = get_tags( $args ); | |
| 532 | 502 | |
| 533 | 503 | foreach ( $tags as $tag ) { |
| 534 | 504 | $hashtags[] = array( |
| 535 | 505 | 'type' => 'Hashtag', |
| @@ -571,11 +541,11 @@ | ||
| 571 | 541 | $this->get_url(), |
| 572 | 542 | $this->get_alternate_url(), |
| 573 | 543 | ); |
| 574 | 544 | |
| 575 | - $also_known_as = \array_merge( $also_known_as, \get_option( 'activitypub_blog_user_also_known_as', array() ) ); | |
| 545 | + $also_known_as = array_merge( $also_known_as, \get_option( 'activitypub_blog_user_also_known_as', array() ) ); | |
| 576 | 546 | |
| 577 | - return \array_unique( $also_known_as ); | |
| 547 | + return array_unique( $also_known_as ); | |
| 578 | 548 | } |
| 579 | 549 | |
| 580 | 550 | /** |
| 581 | 551 | * Returns the movedTo. |
| @@ -585,52 +555,6 @@ | ||
| 585 | 555 | public function get_moved_to() { |
| 586 | 556 | $moved_to = \get_option( 'activitypub_blog_user_moved_to' ); |
| 587 | 557 | |
| 588 | 558 | return $moved_to && $moved_to !== $this->get_id() ? $moved_to : null; |
| 589 | - } | |
| 590 | - | |
| 591 | - /** | |
| 592 | - * Get the actor-level interaction policy. | |
| 593 | - * | |
| 594 | - * Overrides the magic property accessor on Base_Object so that we always | |
| 595 | - * compute the policy from the current site setting rather than returning a | |
| 596 | - * cached property value. Currently only emits `canFeature` (FEP-7aa9). | |
| 597 | - * Driven by the site option `activitypub_default_feature_policy` and | |
| 598 | - * defaults to denying all featured-collection requests, in line with | |
| 599 | - * FEP-7aa9's "absence of policy = no consent" rule. | |
| 600 | - * | |
| 601 | - * @see https://w3id.org/fep/7aa9 | |
| 602 | - * | |
| 603 | - * @since 9.0.0 | |
| 604 | - * | |
| 605 | - * @return array | |
| 606 | - */ | |
| 607 | - public function get_interaction_policy() { | |
| 608 | - $policy = array( 'canFeature' => $this->build_can_feature_policy() ); | |
| 609 | - | |
| 610 | - // Merge with an explicitly set interaction policy, if any. | |
| 611 | - if ( $this->interaction_policy ) { | |
| 612 | - $policy = \array_merge( (array) $this->interaction_policy, $policy ); | |
| 613 | - } | |
| 614 | - | |
| 615 | - return $policy; | |
| 616 | - } | |
| 617 | - | |
| 618 | - /** | |
| 619 | - * Build the `canFeature` policy array from the site option. | |
| 620 | - * | |
| 621 | - * @return array | |
| 622 | - */ | |
| 623 | - protected function build_can_feature_policy() { | |
| 624 | - $policy = \get_option( 'activitypub_default_feature_policy', ACTIVITYPUB_INTERACTION_POLICY_ME ); | |
| 625 | - | |
| 626 | - switch ( $policy ) { | |
| 627 | - case ACTIVITYPUB_INTERACTION_POLICY_ANYONE: | |
| 628 | - return array( 'automaticApproval' => array( 'https://www.w3.org/ns/activitystreams#Public' ) ); | |
| 629 | - case ACTIVITYPUB_INTERACTION_POLICY_FOLLOWERS: | |
| 630 | - return array( 'automaticApproval' => array( $this->get_followers() ) ); | |
| 631 | - case ACTIVITYPUB_INTERACTION_POLICY_ME: | |
| 632 | - default: | |
| 633 | - return array( 'automaticApproval' => array( $this->get_id() ) ); | |
| 634 | - } | |
| 635 | 559 | } |
| 636 | 560 | } |