Skip to content

Conversation

@obenland
Copy link
Member

Follow-up to #2314

Addresses #2314 (comment)

Proposed changes:

  • Adds a new activitypub_store_attachments_locally filter that allows users and plugins to disable local storage of attachments from incoming ActivityPub posts
  • This addresses the feedback about providing an option for users with limited webspace who may prefer not to download and store remote images locally

Other information:

  • Have you written new tests for your changes, if applicable?

Testing instructions:

Default behavior (no change):

  1. Ensure the plugin is active
  2. Receive an ActivityPub post with attachments
  3. Verify attachments are downloaded and stored locally in wp-content/uploads/activitypub/ap_posts/{post_id}/

Disabled storage:

  1. Add this code to your theme's functions.php:
add_filter( 'activitypub_store_attachments_locally', '__return_false' );
  1. Receive an ActivityPub post with attachments
  2. Verify that attachments are NOT downloaded or stored locally

Changelog entry

Introduces the `activitypub_store_attachments_locally` filter to allow
users and plugins to disable local storage of attachments from incoming
ActivityPub posts. This addresses feedback about providing an option for
users with limited webspace who may prefer not to store remote images
locally.

The filter is applied in both the add() and update() methods of the
Posts collection class, with full documentation on the first instance
and a reference comment on the second instance following WordPress
conventions.
Copilot AI review requested due to automatic review settings October 29, 2025 16:51
@obenland obenland self-assigned this Oct 29, 2025
@obenland obenland requested a review from pfefferle October 29, 2025 16:51
@obenland obenland added the Skip Changelog Disables the "Changelog Updated" action for PRs where changelog entries are not necessary. label Oct 29, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a new filter activitypub_store_attachments_locally that allows plugins or users to disable local storage of attachments from incoming ActivityPub posts, which can be useful for users with limited webspace.

  • Introduces filter hook to control whether attachments should be stored locally
  • Applies the filter in both the add() and update() methods of the Posts collection class
  • Maintains backward compatibility by defaulting to true (store locally)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


if ( $store_locally ) {
Attachments::delete_ap_posts_directory( $post_id );
Attachments::import_post_files( $activity['object']['attachment'], $post_id );
Copy link

Copilot AI Oct 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When $store_locally is false, the existing attachments directory is not deleted, which could lead to orphaned files if a post previously had local attachments enabled and is now being updated with the filter returning false. Consider deleting the existing attachments directory before the conditional check, or add an else clause to handle cleanup when the filter is disabled.

Suggested change
Attachments::import_post_files( $activity['object']['attachment'], $post_id );
Attachments::import_post_files( $activity['object']['attachment'], $post_id );
} else {
Attachments::delete_ap_posts_directory( $post_id );

Copilot uses AI. Check for mistakes.

This comment was marked as off-topic.

@Jiwoon-Kim

This comment was marked as off-topic.

obenland and others added 3 commits October 29, 2025 13:30
Refactors the attachment storage logic:
- Extracts filter logic into a reusable maybe_import_attachments() method
- Always deletes existing attachments on update before re-importing
- This ensures the filter return value is respected even if it changed
  since the post was first added

This addresses feedback that the filter value might change between
add and update operations, so we should always clean up and re-evaluate
whether to store attachments locally.
@pfefferle
Copy link
Member

That is not exactly what I had in mind 🤔

I will try to provide an example later today.

@Jiwoon-Kim
Copy link
Contributor

Jiwoon-Kim commented Oct 30, 2025

https://wordpress.org/plugins/regenerate-thumbnails/

Using a plugin like Regenerate Thumbnails can pose a significant risk when dealing with a large number of image files. In other words, in the case of Fediverse, performing bulk synchronization of images could be very dangerous.

My suggestion is also based on the assumption of using the mediaLib endpoint(+FMO). By specifying the file size in advance, each instance can predictively generate the image itself.

Additionally, retrieving and synchronizing the file URL of remote image objects also becomes easier.


Inspired by FileBird, I think that using an S2S Media Library endpoint could make it possible not only to query collections or individual image objects, but even to transfer them in bulk as a compressed archive.

@Jiwoon-Kim
Copy link
Contributor

Jiwoon-Kim commented Nov 2, 2025

The most painful idea I'm dealing with right now is that,
to implement a Proxy Post system, I would need to insert an actor_id mapping layer between the wp_users table and the author field.

However, once author is decoupled from wp_users,
the entire core structure and countless plugin/function dependencies will inevitably break.

I'm trying to design a blog actor model that allows multiple intermediaries (proxies or agents) to exist between the author and the post,
but the architectural complexity is skyrocketing to an unbearable level...

#2322 (comment)

As you know, when enabling Multisite in WordPress, additional tables related to blog_id and site_id are created.

Neither Mastodon nor Misskey supported ActivityPub from the beginning — their architectures had to be restructured to accommodate federation.

So why do you think WordPress could achieve full federation without any core modification?

In my opinion, a more proper and sustainable approach would be to first handle core extensions and housekeeping through a canonical plugin, and only then build the ActivityPub layer on top of that foundation.

@obenland
Copy link
Member Author

obenland commented Nov 6, 2025

That is not exactly what I had in mind 🤔 I will try to provide an example later today.

@pfefferle Have you had a chance to give this another thought?

@obenland obenland merged commit f06ad51 into trunk Nov 6, 2025
12 checks passed
@obenland obenland deleted the add/attachment-storage-filter branch November 6, 2025 07:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Collections Skip Changelog Disables the "Changelog Updated" action for PRs where changelog entries are not necessary.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants