| @@ -7,9 +7,8 @@ | ||
| 7 | 7 | |
| 8 | 8 | namespace Activitypub\Transformer; |
| 9 | 9 | |
| 10 | 10 | use Activitypub\Activity\Base_Object; |
| 11 | -use Activitypub\Blocks; | |
| 12 | 11 | use Activitypub\Collection\Actors; |
| 13 | 12 | use Activitypub\Collection\Interactions; |
| 14 | 13 | use Activitypub\Collection\Replies; |
| 15 | 14 | use Activitypub\Model\Blog; |
| @@ -20,8 +19,9 @@ | ||
| 20 | 19 | use function Activitypub\get_content_visibility; |
| 21 | 20 | use function Activitypub\get_content_warning; |
| 22 | 21 | use function Activitypub\get_enclosures; |
| 23 | 22 | use function Activitypub\get_rest_url_by_path; |
| 23 | +use function Activitypub\is_post_publicly_queryable; | |
| 24 | 24 | use function Activitypub\is_single_user; |
| 25 | 25 | use function Activitypub\site_supports_blocks; |
| 26 | 26 | |
| 27 | 27 | /** |
| @@ -89,8 +89,30 @@ | ||
| 89 | 89 | * |
| 90 | 90 | * @return \Activitypub\Activity\Base_Object The ActivityPub Object |
| 91 | 91 | */ |
| 92 | 92 | public function to_object() { |
| 93 | + /* | |
| 94 | + * A redacted (password-protected or non-public) post is, from the | |
| 95 | + * Fediverse's perspective, gone — the soft-delete path that reaches here | |
| 96 | + * emits a Delete. Represent it as a Tombstone: content-free by type, so | |
| 97 | + * no body-derived field (content, summary, tags, @-mentions, location, | |
| 98 | + * attachments…) can ever leak, even one added to the transformer later. | |
| 99 | + * | |
| 100 | + * Address the teardown to the public collection. A post only reaches the | |
| 101 | + * soft-delete path after being federated, and only public / quiet-public | |
| 102 | + * posts federate (private and local ones never do), so the original | |
| 103 | + * audience was always public — broadcasting the Delete tears the copy | |
| 104 | + * down everywhere it may exist. Private/direct activities are deleted via | |
| 105 | + * their own outbox path and keep their original (non-public) audience, so | |
| 106 | + * they are not affected by this. | |
| 107 | + */ | |
| 108 | + if ( $this->is_redacted() ) { | |
| 109 | + $tombstone = $this->to_tombstone(); | |
| 110 | + $tombstone->set_to( array( 'https://www.w3.org/ns/activitystreams#Public' ) ); | |
| 111 | + | |
| 112 | + return $tombstone; | |
| 113 | + } | |
| 114 | + | |
| 93 | 115 | $post = $this->item; |
| 94 | 116 | $object = parent::to_object(); |
| 95 | 117 | |
| 96 | 118 | $content_warning = get_content_warning( $post ); |
| @@ -112,8 +134,11 @@ | ||
| 112 | 134 | public function to_tombstone() { |
| 113 | 135 | $object = new Base_Object(); |
| 114 | 136 | $object->set_type( 'Tombstone' ); |
| 115 | 137 | $object->set_id( $this->get_id() ); |
| 138 | + // Preserve the permalink so the tombstone registry can resolve a request | |
| 139 | + // to it, even on sites whose ActivityPub ID is the post-ID URL (?p=123). | |
| 140 | + $object->set_url( $this->get_url() ); | |
| 116 | 141 | $object->set_former_type( $this->get_type() ); |
| 117 | 142 | $object->set_published( $this->get_published() ); |
| 118 | 143 | $object->set_updated( $this->get_updated() ); |
| 119 | 144 | |
| @@ -174,9 +199,9 @@ | ||
| 174 | 199 | } |
| 175 | 200 | |
| 176 | 201 | $user = Actors::get_by_id( $this->item->post_author ); |
| 177 | 202 | |
| 178 | - if ( $user && ! is_wp_error( $user ) ) { | |
| 203 | + if ( $user && ! \is_wp_error( $user ) ) { | |
| 179 | 204 | $this->actor_object = $user; |
| 180 | 205 | return $user; |
| 181 | 206 | } |
| 182 | 207 | |
| @@ -185,8 +210,22 @@ | ||
| 185 | 210 | |
| 186 | 211 | /** |
| 187 | 212 | * Returns the ID of the Post. |
| 188 | 213 | * |
| 214 | + * Posts past `activitypub_last_post_with_permalink_as_id` use the post-ID URL | |
| 215 | + * as their canonical ActivityPub ID — stable across slug changes. Posts at | |
| 216 | + * or below the threshold are *legacy* and use their permalink as the ID, | |
| 217 | + * which means a slug change effectively renames the federated object. | |
| 218 | + * | |
| 219 | + * Known limitation: a legacy post whose slug changes in the same save as | |
| 220 | + * a soft-delete transition (e.g. publish → draft + new post_name) will | |
| 221 | + * emit a Delete targeting the new permalink, while remote servers cached | |
| 222 | + * the original. The trash case mitigates this via the `wp_trash_post` | |
| 223 | + * hook caching the pre-transition URL in `_activitypub_canonical_url`, | |
| 224 | + * but draft / pending / private / password-applied transitions do not. | |
| 225 | + * If you maintain a site that pre-dates the ID migration, avoid editing | |
| 226 | + * the slug in the same save as the visibility change. | |
| 227 | + * | |
| 189 | 228 | * @return string The Posts ID. |
| 190 | 229 | */ |
| 191 | 230 | public function get_id() { |
| 192 | 231 | $last_legacy_id = (int) \get_option( 'activitypub_last_post_with_permalink_as_id', 0 ); |
| @@ -224,9 +263,9 @@ | ||
| 224 | 263 | $permalink = \get_permalink( $post ); |
| 225 | 264 | break; |
| 226 | 265 | } |
| 227 | 266 | |
| 228 | - return \esc_url( $permalink ); | |
| 267 | + return \esc_url_raw( $permalink ); | |
| 229 | 268 | } |
| 230 | 269 | |
| 231 | 270 | /** |
| 232 | 271 | * Returns the User-URL of the Author of the Post. |
| @@ -264,9 +303,9 @@ | ||
| 264 | 303 | * @param array|false $thumbnail The image URL, or false if no image is available. |
| 265 | 304 | * @param int $id The attachment ID. |
| 266 | 305 | * @param string $image_size The image size to retrieve. Set to 'large' by default. |
| 267 | 306 | */ |
| 268 | - $thumbnail = apply_filters( | |
| 307 | + $thumbnail = \apply_filters( | |
| 269 | 308 | 'activitypub_get_image', |
| 270 | 309 | $this->get_attachment_image_src( $id, $image_size ), |
| 271 | 310 | $id, |
| 272 | 311 | $image_size |
| @@ -279,9 +318,9 @@ | ||
| 279 | 318 | $mime_type = \get_post_mime_type( $id ); |
| 280 | 319 | |
| 281 | 320 | $image = array( |
| 282 | 321 | 'type' => 'Image', |
| 283 | - 'url' => \esc_url( $thumbnail[0] ), | |
| 322 | + 'url' => \esc_url_raw( $thumbnail[0] ), | |
| 284 | 323 | 'mediaType' => \esc_attr( $mime_type ), |
| 285 | 324 | ); |
| 286 | 325 | |
| 287 | 326 | $alt = \get_post_meta( $id, '_wp_attachment_image_alt', true ); |
| @@ -304,9 +343,9 @@ | ||
| 304 | 343 | if ( \has_post_thumbnail( $post_id ) ) { |
| 305 | 344 | $id = \get_post_thumbnail_id( $post_id ); |
| 306 | 345 | } else { |
| 307 | 346 | // Try site_logo, falling back to site_icon, first. |
| 308 | - $id = get_option( 'site_icon' ); | |
| 347 | + $id = \get_option( 'site_icon' ); | |
| 309 | 348 | } |
| 310 | 349 | |
| 311 | 350 | if ( ! $id ) { |
| 312 | 351 | return null; |
| @@ -320,9 +359,9 @@ | ||
| 320 | 359 | * @param array|false $thumbnail The image URL, or false if no image is available. |
| 321 | 360 | * @param int $id The attachment ID. |
| 322 | 361 | * @param string $image_size The image size to retrieve. Set to 'large' by default. |
| 323 | 362 | */ |
| 324 | - $thumbnail = apply_filters( | |
| 363 | + $thumbnail = \apply_filters( | |
| 325 | 364 | 'activitypub_get_image', |
| 326 | 365 | $this->get_attachment_image_src( $id, $image_size ), |
| 327 | 366 | $id, |
| 328 | 367 | $image_size |
| @@ -335,9 +374,9 @@ | ||
| 335 | 374 | $mime_type = \get_post_mime_type( $id ); |
| 336 | 375 | |
| 337 | 376 | $image = array( |
| 338 | 377 | 'type' => 'Image', |
| 339 | - 'url' => \esc_url( $thumbnail[0] ), | |
| 378 | + 'url' => \esc_url_raw( $thumbnail[0] ), | |
| 340 | 379 | 'mediaType' => \esc_attr( $mime_type ), |
| 341 | 380 | ); |
| 342 | 381 | |
| 343 | 382 | $alt = \get_post_meta( $id, '_wp_attachment_image_alt', true ); |
| @@ -357,21 +396,11 @@ | ||
| 357 | 396 | if ( false !== $this->attachment ) { |
| 358 | 397 | return $this->attachment; |
| 359 | 398 | } |
| 360 | 399 | |
| 361 | - /* | |
| 362 | - * Remove attachments from the Fediverse if a post was federated and then unpublished. | |
| 363 | - * Except in preview mode, where we want to show attachments. | |
| 364 | - */ | |
| 365 | - if ( ! $this->is_preview() && 'publish' !== \get_post_status( $this->item ) ) { | |
| 366 | - $this->attachment = array(); | |
| 367 | - | |
| 368 | - return $this->attachment; | |
| 369 | - } | |
| 370 | - | |
| 371 | 400 | $max_media = \get_post_meta( $this->item->ID, 'activitypub_max_image_attachments', true ); |
| 372 | 401 | |
| 373 | - if ( ! is_numeric( $max_media ) ) { | |
| 402 | + if ( ! \is_numeric( $max_media ) ) { | |
| 374 | 403 | $max_media = \get_option( 'activitypub_max_image_attachments', ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS ); |
| 375 | 404 | } |
| 376 | 405 | |
| 377 | 406 | /** |
| @@ -522,9 +551,9 @@ | ||
| 522 | 551 | } |
| 523 | 552 | |
| 524 | 553 | $tags[] = array( |
| 525 | 554 | 'type' => 'Hashtag', |
| 526 | - 'href' => \esc_url( \get_tag_link( $post_tag->term_id ) ), | |
| 555 | + 'href' => \esc_url_raw( \get_tag_link( $post_tag->term_id ) ), | |
| 527 | 556 | 'name' => esc_hashtag( $post_tag->name ), |
| 528 | 557 | ); |
| 529 | 558 | } |
| 530 | 559 | } |
| @@ -550,15 +579,8 @@ | ||
| 550 | 579 | if ( false !== $this->summary ) { |
| 551 | 580 | return $this->summary; |
| 552 | 581 | } |
| 553 | 582 | |
| 554 | - // Remove Teaser from unpublished posts. | |
| 555 | - if ( ! $this->is_preview() && 'publish' !== \get_post_status( $this->item ) ) { | |
| 556 | - $this->summary = \__( '(This post is being modified)', 'activitypub' ); | |
| 557 | - | |
| 558 | - return $this->summary; | |
| 559 | - } | |
| 560 | - | |
| 561 | 583 | $this->summary = generate_post_summary( $this->item ); |
| 562 | 584 | |
| 563 | 585 | return $this->summary; |
| 564 | 586 | } |
| @@ -600,15 +622,8 @@ | ||
| 600 | 622 | if ( false !== $this->content ) { |
| 601 | 623 | return $this->content; |
| 602 | 624 | } |
| 603 | 625 | |
| 604 | - // Remove Content from unpublished posts. | |
| 605 | - if ( ! $this->is_preview() && 'publish' !== \get_post_status( $this->item ) ) { | |
| 606 | - $this->content = \__( '(This post is being modified)', 'activitypub' ); | |
| 607 | - | |
| 608 | - return $this->content; | |
| 609 | - } | |
| 610 | - | |
| 611 | 626 | global $post; |
| 612 | 627 | |
| 613 | 628 | // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited |
| 614 | 629 | $post = $this->item; |
| @@ -623,9 +638,9 @@ | ||
| 623 | 638 | */ |
| 624 | 639 | \do_action( 'activitypub_before_get_content', $post ); |
| 625 | 640 | |
| 626 | 641 | // It seems that shortcodes are only applied to published posts. |
| 627 | - if ( is_preview() ) { | |
| 642 | + if ( \is_preview() ) { | |
| 628 | 643 | $post->post_status = 'publish'; |
| 629 | 644 | } |
| 630 | 645 | |
| 631 | 646 | // Register our shortcodes just in time. |
| @@ -649,24 +664,8 @@ | ||
| 649 | 664 | return $this->content; |
| 650 | 665 | } |
| 651 | 666 | |
| 652 | 667 | /** |
| 653 | - * Generate HTML @ link for reply block. | |
| 654 | - * | |
| 655 | - * @deprecated 7.4.0 Use {@see Blocks::generate_reply_link()}. | |
| 656 | - * | |
| 657 | - * @param string $block_content The block content. | |
| 658 | - * @param array $block The block data. | |
| 659 | - * | |
| 660 | - * @return string The HTML @ link. | |
| 661 | - */ | |
| 662 | - public function generate_reply_link( $block_content, $block ) { | |
| 663 | - _deprecated_function( __METHOD__, '7.4.0', 'Activitypub\Blocks::generate_reply_link' ); | |
| 664 | - | |
| 665 | - return Blocks::generate_reply_link( $block_content, $block ); | |
| 666 | - } | |
| 667 | - | |
| 668 | - /** | |
| 669 | 668 | * Returns the in-reply-to URL of the post. |
| 670 | 669 | * |
| 671 | 670 | * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-inreplyto |
| 672 | 671 | * |
| @@ -700,9 +699,9 @@ | ||
| 700 | 699 | |
| 701 | 700 | return $this->in_reply_to; |
| 702 | 701 | } |
| 703 | 702 | |
| 704 | - if ( 1 === count( $reply_urls ) ) { | |
| 703 | + if ( 1 === \count( $reply_urls ) ) { | |
| 705 | 704 | $this->in_reply_to = \current( $reply_urls ); |
| 706 | 705 | |
| 707 | 706 | return $this->in_reply_to; |
| 708 | 707 | } |
| @@ -759,10 +758,10 @@ | ||
| 759 | 758 | } |
| 760 | 759 | |
| 761 | 760 | // Both latitude and longitude are required for a valid location. |
| 762 | 761 | // Use is_numeric() instead of empty() since 0 is a valid coordinate (Equator/Prime Meridian). |
| 763 | - $has_latitude = isset( $meta['geo_latitude'][0] ) && is_numeric( $meta['geo_latitude'][0] ); | |
| 764 | - $has_longitude = isset( $meta['geo_longitude'][0] ) && is_numeric( $meta['geo_longitude'][0] ); | |
| 762 | + $has_latitude = isset( $meta['geo_latitude'][0] ) && \is_numeric( $meta['geo_latitude'][0] ); | |
| 763 | + $has_longitude = isset( $meta['geo_longitude'][0] ) && \is_numeric( $meta['geo_longitude'][0] ); | |
| 765 | 764 | |
| 766 | 765 | if ( ! $has_latitude || ! $has_longitude ) { |
| 767 | 766 | return null; |
| 768 | 767 | } |
| @@ -808,9 +807,9 @@ | ||
| 808 | 807 | * @param \WP_Post $post The post object. |
| 809 | 808 | * |
| 810 | 809 | * @return array The filtered mentions. |
| 811 | 810 | */ |
| 812 | - $this->mentions = apply_filters( | |
| 811 | + $this->mentions = \apply_filters( | |
| 813 | 812 | 'activitypub_extract_mentions', |
| 814 | 813 | array(), |
| 815 | 814 | $this->item->post_content . ' ' . $this->item->post_excerpt, |
| 816 | 815 | $this->item |
| @@ -819,38 +818,39 @@ | ||
| 819 | 818 | return $this->mentions; |
| 820 | 819 | } |
| 821 | 820 | |
| 822 | 821 | /** |
| 823 | - * Transform Embed blocks to block level link. | |
| 822 | + * Whether the post should be redacted from ActivityPub representations. | |
| 824 | 823 | * |
| 825 | - * Remote servers will simply drop iframe elements, rendering incomplete content. | |
| 824 | + * Redaction is fail-closed at a single boundary: `to_object()` returns a | |
| 825 | + * Tombstone instead of transforming the post, so no body-derived field | |
| 826 | + * (content, summary, name, preview, attachments, image/icon, tags, mentions, | |
| 827 | + * in-reply-to, location) is ever read — not even one added to the transformer | |
| 828 | + * later. This is the only caller of this gate. | |
| 826 | 829 | * |
| 827 | - * @deprecated 7.4.0 Use {@see Blocks::revert_embed_links()}. | |
| 830 | + * A post is redacted exactly when it is not publicly queryable — the same | |
| 831 | + * predicate the scheduler uses to decide a federated post should emit a | |
| 832 | + * Delete (`is_post_publicly_queryable()`), so the two never disagree. That | |
| 833 | + * covers non-public status, password protection, the `local`/`private` | |
| 834 | + * content-visibility meta, and a post type that no longer supports | |
| 835 | + * ActivityPub. The Fediverse Preview keeps working because | |
| 836 | + * `is_post_publicly_queryable()` itself treats a draft/pending/scheduled | |
| 837 | + * post as queryable during a `?preview=true` request from a user who can | |
| 838 | + * edit it. | |
| 828 | 839 | * |
| 829 | - * @see https://www.w3.org/TR/activitypub/#security-sanitizing-content | |
| 830 | - * @see https://www.w3.org/wiki/ActivityPub/Primer/HTML | |
| 840 | + * Note: we deliberately rely on `is_post_publicly_queryable()` rather than | |
| 841 | + * `post_password_required()`. Federation output is per-instance, never | |
| 842 | + * per-request, and `post_password_required()` returns false when a valid | |
| 843 | + * `wp-postpass` cookie is on the current request (e.g. an editor who unlocked | |
| 844 | + * the post), which would leak the protected body into an outbox snapshot. | |
| 831 | 845 | * |
| 832 | - * @param string $block_content The block content (html). | |
| 833 | - * @param object $block The block object. | |
| 834 | - * | |
| 835 | - * @return string A block level link | |
| 846 | + * @return boolean True if the post must be redacted, false otherwise. | |
| 836 | 847 | */ |
| 837 | - public function revert_embed_links( $block_content, $block ) { | |
| 838 | - _deprecated_function( __METHOD__, '7.4.0', 'Activitypub\Blocks::revert_embed_links' ); | |
| 839 | - | |
| 840 | - return Blocks::revert_embed_links( $block_content, $block ); | |
| 848 | + protected function is_redacted() { | |
| 849 | + return ! is_post_publicly_queryable( $this->item ); | |
| 841 | 850 | } |
| 842 | 851 | |
| 843 | 852 | /** |
| 844 | - * Check if the post is a preview. | |
| 845 | - * | |
| 846 | - * @return boolean True if the post is a preview, false otherwise. | |
| 847 | - */ | |
| 848 | - private function is_preview() { | |
| 849 | - return defined( 'ACTIVITYPUB_PREVIEW' ) && ACTIVITYPUB_PREVIEW; | |
| 850 | - } | |
| 851 | - | |
| 852 | - /** | |
| 853 | 853 | * Get enclosures for a post. |
| 854 | 854 | * |
| 855 | 855 | * @param array $media The media array grouped by type. |
| 856 | 856 | * |
| @@ -953,8 +953,53 @@ | ||
| 953 | 953 | ); |
| 954 | 954 | } |
| 955 | 955 | } |
| 956 | 956 | break; |
| 957 | + case 'core/media-text': | |
| 958 | + if ( ! empty( $block['attrs']['mediaId'] ) ) { | |
| 959 | + $media_id = $block['attrs']['mediaId']; | |
| 960 | + | |
| 961 | + // Media & Text holds either an image or a video; the default is image. | |
| 962 | + if ( 'video' === ( $block['attrs']['mediaType'] ?? 'image' ) ) { | |
| 963 | + $video = array( 'id' => $media_id ); | |
| 964 | + | |
| 965 | + // The poster is stored as an HTML attribute on the <video> tag, not in block attrs. | |
| 966 | + $processor = new \WP_HTML_Tag_Processor( $block['innerHTML'] ); | |
| 967 | + if ( $processor->next_tag( array( 'tag_name' => 'video' ) ) ) { | |
| 968 | + $poster = $processor->get_attribute( 'poster' ); | |
| 969 | + if ( ! empty( $poster ) ) { | |
| 970 | + $video['icon'] = \esc_url_raw( $poster ); | |
| 971 | + } | |
| 972 | + } | |
| 973 | + | |
| 974 | + $media['video'][] = $video; | |
| 975 | + } else { | |
| 976 | + $alt = ''; | |
| 977 | + $processor = new \WP_HTML_Tag_Processor( $block['innerHTML'] ); | |
| 978 | + if ( $processor->next_tag( array( 'tag_name' => 'img' ) ) ) { | |
| 979 | + $alt = $processor->get_attribute( 'alt' ) ?? ''; | |
| 980 | + } | |
| 981 | + | |
| 982 | + // Update alt in place if the image was already collected, so a | |
| 983 | + // duplicate ID does not get dropped (and its alt lost) later. | |
| 984 | + $found = false; | |
| 985 | + foreach ( $media['image'] as $i => $image ) { | |
| 986 | + if ( isset( $image['id'] ) && $image['id'] === $media_id ) { | |
| 987 | + $media['image'][ $i ]['alt'] = $alt; | |
| 988 | + $found = true; | |
| 989 | + break; | |
| 990 | + } | |
| 991 | + } | |
| 992 | + | |
| 993 | + if ( ! $found ) { | |
| 994 | + $media['image'][] = array( | |
| 995 | + 'id' => $media_id, | |
| 996 | + 'alt' => $alt, | |
| 997 | + ); | |
| 998 | + } | |
| 999 | + } | |
| 1000 | + } | |
| 1001 | + break; | |
| 957 | 1002 | case 'core/audio': |
| 958 | 1003 | if ( ! empty( $block['attrs']['id'] ) ) { |
| 959 | 1004 | $media['audio'][] = array( 'id' => $block['attrs']['id'] ); |
| 960 | 1005 | } |
| @@ -978,11 +1023,11 @@ | ||
| 978 | 1023 | break; |
| 979 | 1024 | case 'jetpack/slideshow': |
| 980 | 1025 | case 'jetpack/tiled-gallery': |
| 981 | 1026 | if ( ! empty( $block['attrs']['ids'] ) ) { |
| 982 | - $media['image'] = array_merge( | |
| 1027 | + $media['image'] = \array_merge( | |
| 983 | 1028 | $media['image'], |
| 984 | - array_map( | |
| 1029 | + \array_map( | |
| 985 | 1030 | static function ( $id ) { |
| 986 | 1031 | return array( 'id' => $id ); |
| 987 | 1032 | }, |
| 988 | 1033 | $block['attrs']['ids'] |
| @@ -1027,27 +1072,12 @@ | ||
| 1027 | 1072 | if ( ! empty( $media[ $type ] ) ) { |
| 1028 | 1073 | return $media[ $type ]; |
| 1029 | 1074 | } |
| 1030 | 1075 | |
| 1031 | - return array_filter( array_merge( ...array_values( $media ) ) ); | |
| 1076 | + return \array_filter( \array_merge( ...\array_values( $media ) ) ); | |
| 1032 | 1077 | } |
| 1033 | 1078 | |
| 1034 | 1079 | /** |
| 1035 | - * Converts a WordPress Attachment to an ActivityPub Attachment. | |
| 1036 | - * | |
| 1037 | - * @deprecated 7.2.0 Use {@see Base::transform_attachment()} instead. | |
| 1038 | - * | |
| 1039 | - * @param array $media The Attachment array. | |
| 1040 | - * | |
| 1041 | - * @return array The ActivityPub Attachment. | |
| 1042 | - */ | |
| 1043 | - public function wp_attachment_to_activity_attachment( $media ) { | |
| 1044 | - _deprecated_function( __METHOD__, '7.2.0', '\Activitypub\Transformer\Base::transform_attachment()' ); | |
| 1045 | - | |
| 1046 | - return parent::transform_attachment( $media ); | |
| 1047 | - } | |
| 1048 | - | |
| 1049 | - /** | |
| 1050 | 1080 | * Get the context of the post. |
| 1051 | 1081 | * |
| 1052 | 1082 | * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-context |
| 1053 | 1083 | * |
| @@ -1053,9 +1083,9 @@ | ||
| 1053 | 1083 | * |
| 1054 | 1084 | * @return string The context of the post. |
| 1055 | 1085 | */ |
| 1056 | 1086 | protected function get_context() { |
| 1057 | - return get_rest_url_by_path( sprintf( 'posts/%d/context', $this->item->ID ) ); | |
| 1087 | + return get_rest_url_by_path( \sprintf( 'posts/%d/context', $this->item->ID ) ); | |
| 1058 | 1088 | } |
| 1059 | 1089 | |
| 1060 | 1090 | /** |
| 1061 | 1091 | * Gets the template to use to generate the content of the activitypub item. |
| @@ -1100,9 +1130,9 @@ | ||
| 1100 | 1130 | * @param string $template The template string containing shortcodes. |
| 1101 | 1131 | * @param \WP_Post $item The WordPress post object being transformed. |
| 1102 | 1132 | * @param string $type ActivityStreams 2.0 Object-Type for the post. |
| 1103 | 1133 | */ |
| 1104 | - return apply_filters( 'activitypub_object_content_template', $template, $this->item, $type ); | |
| 1134 | + return \apply_filters( 'activitypub_object_content_template', $template, $this->item, $type ); | |
| 1105 | 1135 | } |
| 1106 | 1136 | |
| 1107 | 1137 | /** |
| 1108 | 1138 | * Get the replies Collection. |
| @@ -1119,9 +1149,9 @@ | ||
| 1119 | 1149 | * @return array The likes collection. |
| 1120 | 1150 | */ |
| 1121 | 1151 | public function get_likes() { |
| 1122 | 1152 | return array( |
| 1123 | - 'id' => get_rest_url_by_path( sprintf( 'posts/%d/likes', $this->item->ID ) ), | |
| 1153 | + 'id' => get_rest_url_by_path( \sprintf( 'posts/%d/likes', $this->item->ID ) ), | |
| 1124 | 1154 | 'type' => 'Collection', |
| 1125 | 1155 | 'totalItems' => Interactions::count_by_type( $this->item->ID, 'like' ), |
| 1126 | 1156 | ); |
| 1127 | 1157 | } |
| @@ -1132,9 +1162,9 @@ | ||
| 1132 | 1162 | * @return array The Shares collection. |
| 1133 | 1163 | */ |
| 1134 | 1164 | public function get_shares() { |
| 1135 | 1165 | return array( |
| 1136 | - 'id' => get_rest_url_by_path( sprintf( 'posts/%d/shares', $this->item->ID ) ), | |
| 1166 | + 'id' => get_rest_url_by_path( \sprintf( 'posts/%d/shares', $this->item->ID ) ), | |
| 1137 | 1167 | 'type' => 'Collection', |
| 1138 | 1168 | 'totalItems' => Interactions::count_by_type( $this->item->ID, 'repost' ) + Interactions::count_by_type( $this->item->ID, 'quote' ), |
| 1139 | 1169 | ); |
| 1140 | 1170 | } |
| @@ -1169,9 +1199,9 @@ | ||
| 1169 | 1199 | } |
| 1170 | 1200 | |
| 1171 | 1201 | switch ( $policy ) { |
| 1172 | 1202 | case ACTIVITYPUB_INTERACTION_POLICY_FOLLOWERS: |
| 1173 | - return array( 'automaticApproval' => get_rest_url_by_path( sprintf( 'actors/%d/followers', $this->item->post_author ) ) ); | |
| 1203 | + return array( 'automaticApproval' => get_rest_url_by_path( \sprintf( 'actors/%d/followers', $this->item->post_author ) ) ); | |
| 1174 | 1204 | |
| 1175 | 1205 | case ACTIVITYPUB_INTERACTION_POLICY_ME: |
| 1176 | 1206 | return array( 'automaticApproval' => $this->get_self_interaction_policy() ); |
| 1177 | 1207 | |