Skip to content

Commit 16143b3

Browse files
authored
Merge branch 'trunk' into add/reader
2 parents c945ce9 + 4f8a4fa commit 16143b3

File tree

12 files changed

+403
-34
lines changed

12 files changed

+403
-34
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: changed
3+
4+
Cache expensive operations in Post transformer to improve performance.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: changed
3+
4+
Use stable term_id-based IDs for Term transformer to ensure federation consistency.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: changed
3+
4+
Skip downloading video and audio attachments, embedding remote URLs directly to avoid storage limits.

includes/class-attachments.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,19 +483,33 @@ private static function save_attachment( $attachment_data, $post_id, $author_id
483483
/**
484484
* Save a file directly to uploads/activitypub/{type}/{id}/.
485485
*
486+
* For video and audio files, returns the remote URL directly without downloading
487+
* to avoid storage overhead for large media files.
488+
*
486489
* @param array $attachment_data The normalized attachment data.
487490
* @param int $object_id The post or comment ID to attach to.
488491
* @param string $object_type The object type ('post' or 'comment').
489492
*
490493
* @return array|\WP_Error {
491494
* Array of file data on success, WP_Error on failure.
492495
*
493-
* @type string $url Full URL to the saved file.
496+
* @type string $url Full URL to the saved file (or remote URL for video/audio).
494497
* @type string $mime_type MIME type of the file.
495498
* @type string $alt Alt text from attachment name field.
496499
* }
497500
*/
498501
private static function save_file( $attachment_data, $object_id, $object_type ) {
502+
$mime_type = $attachment_data['mediaType'] ?? '';
503+
504+
// Skip download for video and audio files - use remote URL directly.
505+
if ( str_starts_with( $mime_type, 'video/' ) || str_starts_with( $mime_type, 'audio/' ) ) {
506+
return array(
507+
'url' => $attachment_data['url'],
508+
'mime_type' => $attachment_data['mediaType'],
509+
'alt' => $attachment_data['name'] ?? '',
510+
);
511+
}
512+
499513
if ( ! \function_exists( 'download_url' ) ) {
500514
require_once ABSPATH . 'wp-admin/includes/file.php';
501515
}

includes/class-query.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,14 @@ public function get_queried_object() {
198198
}
199199
}
200200

201+
// Check Term by ID.
202+
if ( ! $queried_object ) {
203+
$term_id = \get_query_var( 'term_id' );
204+
if ( $term_id ) {
205+
$queried_object = \get_term( $term_id );
206+
}
207+
}
208+
201209
// Try to get Author by ID.
202210
if ( ! $queried_object ) {
203211
$url = $this->get_request_url();

includes/class-router.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,28 @@ public static function template_redirect() {
262262
\wp_safe_redirect( $actor->get_url(), 301 );
263263
exit;
264264
}
265+
266+
$term_id = \get_query_var( 'term_id', null );
267+
if ( $term_id ) {
268+
$term = \get_term( $term_id );
269+
270+
// Load a 404-page if `term_id` is set but not valid.
271+
if ( ! $term || \is_wp_error( $term ) ) {
272+
$wp_query->set_404();
273+
return;
274+
}
275+
276+
// Don't redirect for ActivityPub requests.
277+
if ( is_activitypub_request() ) {
278+
return;
279+
}
280+
281+
$term_link = \get_term_link( $term );
282+
if ( ! \is_wp_error( $term_link ) ) {
283+
\wp_safe_redirect( $term_link, 301 );
284+
exit;
285+
}
286+
}
265287
}
266288

267289
/**
@@ -280,6 +302,7 @@ public static function add_query_vars( $vars ) {
280302
$vars[] = 'type';
281303
$vars[] = 'c';
282304
$vars[] = 'p';
305+
$vars[] = 'term_id';
283306

284307
return $vars;
285308
}

includes/transformer/class-post.php

Lines changed: 105 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,48 @@ class Post extends Base {
4141
*/
4242
private $actor_object = null;
4343

44+
/**
45+
* The content.
46+
*
47+
* @var string|false False indicates not yet computed.
48+
*/
49+
private $content = false;
50+
51+
/**
52+
* The summary.
53+
*
54+
* @var string|null|false False indicates not yet computed.
55+
*/
56+
private $summary = false;
57+
58+
/**
59+
* The tags.
60+
*
61+
* @var array|false False indicates not yet computed.
62+
*/
63+
private $tags = false;
64+
65+
/**
66+
* The attachment.
67+
*
68+
* @var array|false False indicates not yet computed.
69+
*/
70+
private $attachment = false;
71+
72+
/**
73+
* The mentions.
74+
*
75+
* @var array|false False indicates not yet computed.
76+
*/
77+
private $mentions = false;
78+
79+
/**
80+
* The in_reply_to.
81+
*
82+
* @var string|array|null|false False indicates not yet computed.
83+
*/
84+
private $in_reply_to = false;
85+
4486
/**
4587
* Transforms the WP_Post object to an ActivityPub Object
4688
*
@@ -290,12 +332,18 @@ protected function get_icon() {
290332
* @return array The Attachments.
291333
*/
292334
protected function get_attachment() {
335+
if ( false !== $this->attachment ) {
336+
return $this->attachment;
337+
}
338+
293339
/*
294340
* Remove attachments from the Fediverse if a post was federated and then set back to draft.
295341
* Except in preview mode, where we want to show attachments.
296342
*/
297343
if ( ! $this->is_preview() && 'draft' === \get_post_status( $this->item ) ) {
298-
return array();
344+
$this->attachment = array();
345+
346+
return $this->attachment;
299347
}
300348

301349
$max_media = \get_post_meta( $this->item->ID, 'activitypub_max_image_attachments', true );
@@ -316,7 +364,9 @@ protected function get_attachment() {
316364
$max_media = (int) \apply_filters( 'activitypub_max_image_attachments', $max_media );
317365

318366
if ( 0 === $max_media ) {
319-
return array();
367+
$this->attachment = array();
368+
369+
return $this->attachment;
320370
}
321371

322372
$media = array(
@@ -363,7 +413,9 @@ protected function get_attachment() {
363413
*
364414
* @return array The filtered attachments.
365415
*/
366-
return \apply_filters( 'activitypub_attachments', $attachments, $this->item );
416+
$this->attachment = \apply_filters( 'activitypub_attachments', $attachments, $this->item );
417+
418+
return $this->attachment;
367419
}
368420

369421
/**
@@ -381,15 +433,8 @@ protected function get_type() {
381433
return \ucfirst( $post_format_setting );
382434
}
383435

384-
$has_title = \post_type_supports( $this->item->post_type, 'title' );
385-
$content = \wp_strip_all_tags( $this->item->post_content );
386-
387436
// Check if the post has a title.
388-
if (
389-
! $has_title ||
390-
! $this->item->post_title ||
391-
\strlen( $content ) <= ACTIVITYPUB_NOTE_LENGTH
392-
) {
437+
if ( ! \post_type_supports( $this->item->post_type, 'title' ) || ! $this->item->post_title ) {
393438
return 'Note';
394439
}
395440

@@ -430,6 +475,10 @@ public function get_audience() {
430475
* @return array The list of Tags.
431476
*/
432477
protected function get_tag() {
478+
if ( false !== $this->tags ) {
479+
return $this->tags;
480+
}
481+
433482
$tags = parent::get_tag();
434483

435484
$post_tags = \get_the_tags( $this->item->ID );
@@ -448,7 +497,9 @@ protected function get_tag() {
448497
}
449498
}
450499

451-
return \array_unique( $tags, SORT_REGULAR );
500+
$this->tags = \array_unique( $tags, SORT_REGULAR );
501+
502+
return $this->tags;
452503
}
453504

454505
/**
@@ -464,12 +515,20 @@ protected function get_summary() {
464515
return null;
465516
}
466517

518+
if ( false !== $this->summary ) {
519+
return $this->summary;
520+
}
521+
467522
// Remove Teaser from drafts.
468523
if ( ! $this->is_preview() && 'draft' === \get_post_status( $this->item ) ) {
469-
return \__( '(This post is being modified)', 'activitypub' );
524+
$this->summary = \__( '(This post is being modified)', 'activitypub' );
525+
526+
return $this->summary;
470527
}
471528

472-
return generate_post_summary( $this->item );
529+
$this->summary = generate_post_summary( $this->item );
530+
531+
return $this->summary;
473532
}
474533

475534
/**
@@ -506,9 +565,15 @@ protected function get_name() {
506565
* @return string The content.
507566
*/
508567
protected function get_content() {
568+
if ( false !== $this->content ) {
569+
return $this->content;
570+
}
571+
509572
// Remove Content from drafts.
510573
if ( ! $this->is_preview() && 'draft' === \get_post_status( $this->item ) ) {
511-
return \__( '(This post is being modified)', 'activitypub' );
574+
$this->content = \__( '(This post is being modified)', 'activitypub' );
575+
576+
return $this->content;
512577
}
513578

514579
global $post;
@@ -551,7 +616,9 @@ protected function get_content() {
551616
* @param string $content The transformed post content.
552617
* @param \WP_Post $post The post object being transformed.
553618
*/
554-
return \apply_filters( 'activitypub_the_content', $content, $post );
619+
$this->content = \apply_filters( 'activitypub_the_content', $content, $post );
620+
621+
return $this->content;
555622
}
556623

557624
/**
@@ -578,8 +645,13 @@ public function generate_reply_link( $block_content, $block ) {
578645
* @return string|array|null The in-reply-to URL of the post.
579646
*/
580647
protected function get_in_reply_to() {
648+
if ( false !== $this->in_reply_to ) {
649+
return $this->in_reply_to;
650+
}
651+
581652
if ( ! site_supports_blocks() ) {
582-
return null;
653+
$this->in_reply_to = null;
654+
return $this->in_reply_to;
583655
}
584656

585657
$reply_urls = array();
@@ -596,14 +668,20 @@ protected function get_in_reply_to() {
596668
}
597669

598670
if ( empty( $reply_urls ) ) {
599-
return null;
671+
$this->in_reply_to = null;
672+
673+
return $this->in_reply_to;
600674
}
601675

602676
if ( 1 === count( $reply_urls ) ) {
603-
return \current( $reply_urls );
677+
$this->in_reply_to = \current( $reply_urls );
678+
679+
return $this->in_reply_to;
604680
}
605681

606-
return \array_values( \array_unique( $reply_urls ) );
682+
$this->in_reply_to = \array_values( \array_unique( $reply_urls ) );
683+
684+
return $this->in_reply_to;
607685
}
608686

609687
/**
@@ -639,6 +717,10 @@ protected function get_updated() {
639717
* @return array The list of @-Mentions.
640718
*/
641719
protected function get_mentions() {
720+
if ( false !== $this->mentions ) {
721+
return $this->mentions;
722+
}
723+
642724
/**
643725
* Filter the mentions in the post content.
644726
*
@@ -648,12 +730,14 @@ protected function get_mentions() {
648730
*
649731
* @return array The filtered mentions.
650732
*/
651-
return apply_filters(
733+
$this->mentions = apply_filters(
652734
'activitypub_extract_mentions',
653735
array(),
654736
$this->item->post_content . ' ' . $this->item->post_excerpt,
655737
$this->item
656738
);
739+
740+
return $this->mentions;
657741
}
658742

659743
/**

includes/transformer/class-term.php

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,45 @@ public function to_object() {
2222
$base_object = new \Activitypub\Activity\Base_Object();
2323
$base_object->{'@context'} = 'https://www.w3.org/ns/activitystreams';
2424
$base_object->set_type( 'OrderedCollection' );
25-
$base_object->set_id( \get_term_link( $this->item ) );
25+
$base_object->set_id( $this->get_id() );
26+
$base_object->set_url( $this->get_url() );
2627

2728
return $base_object;
2829
}
2930

3031
/**
31-
* Get the OrderedCollection ID (term link).
32+
* Get the OrderedCollection ID.
3233
*
33-
* @return string The OrderedCollection ID (term link).
34+
* @return string The OrderedCollection ID.
3435
*/
3536
public function to_id() {
36-
return \get_term_link( $this->item );
37+
return $this->get_id();
38+
}
39+
40+
/**
41+
* Returns the stable ID of the Term.
42+
*
43+
* Uses term_id query parameter to ensure the ID remains stable
44+
* even if the term slug is changed.
45+
*
46+
* @return string The Term's stable ID.
47+
*/
48+
public function get_id() {
49+
return \add_query_arg( 'term_id', $this->item->term_id, \home_url( '/' ) );
50+
}
51+
52+
/**
53+
* Returns the URL of the Term.
54+
*
55+
* @return string The Term's URL (term link).
56+
*/
57+
public function get_url() {
58+
$term_link = \get_term_link( $this->item );
59+
60+
if ( \is_wp_error( $term_link ) ) {
61+
return '';
62+
}
63+
64+
return \esc_url( $term_link );
3765
}
3866
}

0 commit comments

Comments
 (0)