Skip to content

Commit 22c8d1e

Browse files
authored
Outbox: Add settings for Outbox retention (#1325)
* Outbox: Add settings for Outbox retention * Update description with definition * Add unit tests for retention option * Add changelog * Register new setting
1 parent a43b78e commit 22c8d1e

File tree

8 files changed

+105
-4
lines changed

8 files changed

+105
-4
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
* Setting to adjust the number of days Outbox items are kept before being purged.
13+
14+
### Fixed
15+
16+
* The Outbox purging routine no longer is limited to deleting 5 items at a time.
1217
* Undo API for Outbox items.
1318

1419
## [5.2.0] - 2025-02-13

includes/class-activitypub.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ public static function uninstall() {
111111
delete_option( 'activitypub_max_image_attachments' );
112112
delete_option( 'activitypub_migration_lock' );
113113
delete_option( 'activitypub_object_type' );
114+
delete_option( 'activitypub_outbox_purge_days' );
114115
delete_option( 'activitypub_support_post_types' );
115116
delete_option( 'activitypub_use_hashtags' );
116117
delete_option( 'activitypub_use_opengraph' );

includes/class-scheduler.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,15 @@ public static function init() {
3131
\add_action( 'activitypub_update_followers', array( self::class, 'update_followers' ) );
3232
\add_action( 'activitypub_cleanup_followers', array( self::class, 'cleanup_followers' ) );
3333

34+
// Event callbacks.
3435
\add_action( 'activitypub_async_batch', array( self::class, 'async_batch' ), 10, 99 );
3536
\add_action( 'activitypub_reprocess_outbox', array( self::class, 'reprocess_outbox' ) );
3637
\add_action( 'activitypub_outbox_purge', array( self::class, 'purge_outbox' ) );
3738

3839
\add_action( 'post_activitypub_add_to_outbox', array( self::class, 'schedule_outbox_activity_for_federation' ) );
3940
\add_action( 'post_activitypub_add_to_outbox', array( self::class, 'schedule_announce_activity' ), 10, 4 );
41+
42+
\add_action( 'update_option_activitypub_outbox_purge_days', array( self::class, 'handle_outbox_purge_days_update' ), 10, 2 );
4043
}
4144

4245
/**
@@ -214,7 +217,7 @@ public static function purge_outbox() {
214217
return;
215218
}
216219

217-
$days = 180; // TODO: Replace with a setting.
220+
$days = (int) get_option( 'activitypub_outbox_purge_days', 180 );
218221
$timezone = new \DateTimeZone( 'UTC' );
219222
$date = new \DateTime( 'now', $timezone );
220223

@@ -225,6 +228,7 @@ public static function purge_outbox() {
225228
'post_type' => Outbox::POST_TYPE,
226229
'post_status' => 'any',
227230
'fields' => 'ids',
231+
'numberposts' => -1,
228232
'date_query' => array(
229233
array(
230234
'before' => $date->format( 'Y-m-d' ),
@@ -238,6 +242,20 @@ public static function purge_outbox() {
238242
}
239243
}
240244

245+
/**
246+
* Update schedules when outbox purge days settings change.
247+
*
248+
* @param int $old_value The old value.
249+
* @param int $value The new value.
250+
*/
251+
public static function handle_outbox_purge_days_update( $old_value, $value ) {
252+
if ( 0 === (int) $value ) {
253+
wp_clear_scheduled_hook( 'activitypub_outbox_purge' );
254+
} elseif ( ! wp_next_scheduled( 'activitypub_outbox_purge' ) ) {
255+
wp_schedule_event( time(), 'daily', 'activitypub_outbox_purge' );
256+
}
257+
}
258+
241259
/**
242260
* Asynchronously runs batch processing routines.
243261
*

includes/help.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@
6969
'<p>' . \__( 'For more information please visit <a href="https://webfinger.net/" target="_blank">webfinger.net</a>', 'activitypub' ) . '</p>' .
7070
'<p><h2>' . \__( 'NodeInfo', 'activitypub' ) . '</h2></p>' .
7171
'<p>' . \__( 'NodeInfo is an effort to create a standardized way of exposing metadata about a server running one of the distributed social networks. The two key goals are being able to get better insights into the user base of distributed social networking and the ability to build tools that allow users to choose the best fitting software and server for their needs.', 'activitypub' ) . '</p>' .
72-
'<p>' . \__( 'For more information please visit <a href="http://nodeinfo.diaspora.software/" target="_blank">nodeinfo.diaspora.software</a>', 'activitypub' ) . '</p>',
72+
'<p>' . \__( 'For more information please visit <a href="http://nodeinfo.diaspora.software/" target="_blank">nodeinfo.diaspora.software</a>', 'activitypub' ) . '</p>' .
73+
'<p><h2>' . \__( 'Outbox', 'activitypub' ) . '</h2></p>' .
74+
'<p>' . \__( 'An "Outbox" is a virtual location on a user&#8217;s profile where all the activities (posts, likes, replies) they publish are stored, acting as a feed that other users can access to see their publicly shared content; it&#8217;s essentially how a user "sends" information to others on a decentralized social network following the ActivityPub standard.', 'activitypub' ) . '</p>',
7375
)
7476
);
7577

includes/wp-admin/class-settings-fields.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,15 @@ public static function register_settings_fields() {
125125
'activitypub_general'
126126
);
127127

128+
add_settings_field(
129+
'activitypub_outbox_purge_days',
130+
__( 'Outbox Retention Period', 'activitypub' ),
131+
array( self::class, 'render_outbox_purge_days_field' ),
132+
'activitypub_settings',
133+
'activitypub_general',
134+
array( 'label_for' => 'activitypub_outbox_purge_days' )
135+
);
136+
128137
if ( ! defined( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) ) {
129138
add_settings_section(
130139
'activitypub_security',
@@ -255,7 +264,7 @@ public static function render_custom_post_content_field() {
255264
public static function render_max_image_attachments_field() {
256265
$value = get_option( 'activitypub_max_image_attachments', ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS );
257266
?>
258-
<input id="activitypub_max_image_attachments" value="<?php echo esc_attr( $value ); ?>" name="activitypub_max_image_attachments" type="number" min="0" />
267+
<input id="activitypub_max_image_attachments" value="<?php echo esc_attr( $value ); ?>" name="activitypub_max_image_attachments" type="number" min="0" class="small-text" />
259268
<p class="description">
260269
<?php
261270
echo wp_kses(
@@ -361,6 +370,26 @@ public static function render_blocklist_field() {
361370
<?php
362371
}
363372

373+
/**
374+
* Render outbox purge days field.
375+
*/
376+
public static function render_outbox_purge_days_field() {
377+
$value = get_option( 'activitypub_outbox_purge_days', 180 );
378+
echo '<input type="number" id="activitypub_outbox_purge_days" name="activitypub_outbox_purge_days" value="' . esc_attr( $value ) . '" class="small-text" min="0" max="365" />';
379+
echo '<p class="description">' . wp_kses(
380+
sprintf(
381+
// translators: 1: Definition of Outbox; 2: Default value (180).
382+
__( 'Maximum number of days to keep items in the <abbr title="%1$s">Outbox</abbr>. A lower value might be better for sites with lots of activity to maintain site performance. Default: <code>%2$s</code>', 'activitypub' ),
383+
esc_attr__( 'A virtual location on a user&#8217;s profile where all the activities (posts, likes, replies) they publish are stored, acting as a feed that other users can access to see their publicly shared content', 'activitypub' ),
384+
esc_html( 180 )
385+
),
386+
array(
387+
'abbr' => array( 'title' => array() ),
388+
'code' => array(),
389+
)
390+
) . '</p>';
391+
}
392+
364393
/**
365394
* Render use hashtags field.
366395
*/

includes/wp-admin/class-settings.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ public static function register_settings() {
6363
)
6464
);
6565

66+
\register_setting(
67+
'activitypub',
68+
'activitypub_outbox_purge_days',
69+
array(
70+
'type' => 'integer',
71+
'description' => \__( 'Number of days to keep items in the Outbox.', 'activitypub' ),
72+
'default' => 180,
73+
)
74+
);
75+
6676
\register_setting(
6777
'activitypub',
6878
'activitypub_object_type',

readme.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ For reasons of data protection, it is not possible to see the followers of other
132132
= Unreleased =
133133

134134
* Added: Undo API for Outbox items.
135+
* Added: Setting to adjust the number of days Outbox items are kept before being purged.
136+
* Fixed: The Outbox purging routine no longer is limited to deleting 5 items at a time.
135137

136138
= 5.2.0 =
137139

tests/includes/class-test-scheduler.php

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Test_Scheduler extends WP_UnitTestCase {
2828
/**
2929
* Create fake data before tests run.
3030
*
31-
* @param WP_UnitTest_Factory $factory Helper that creates fake data.
31+
* @param \WP_UnitTest_Factory $factory Helper that creates fake data.
3232
*/
3333
public static function wpSetUpBeforeClass( $factory ) {
3434
self::$user_id = $factory->user->create(
@@ -248,4 +248,38 @@ public function test_purge_outbox_20_or_fewer_posts() {
248248
// Assert that no posts were deleted.
249249
$this->assertEquals( 20, wp_count_posts( Outbox::POST_TYPE )->publish );
250250
}
251+
252+
/**
253+
* Test purge_outbox method with changing activitypub_outbox_purge_days option.
254+
*
255+
* @covers ::purge_outbox
256+
*/
257+
public function test_purge_outbox_with_different_purge_days() {
258+
// Create posts older than initial_days.
259+
self::factory()->post->create_many(
260+
25,
261+
array(
262+
'post_type' => Outbox::POST_TYPE,
263+
'post_date' => gmdate( 'Y-m-d H:i:s', strtotime( '-4 months' ) ),
264+
'post_status' => 'publish',
265+
)
266+
);
267+
268+
// Run purge_outbox with initial_days.
269+
Scheduler::purge_outbox();
270+
wp_cache_delete( _count_posts_cache_key( Outbox::POST_TYPE ), 'counts' );
271+
272+
// Verify posts are not deleted.
273+
$this->assertEquals( 25, wp_count_posts( Outbox::POST_TYPE )->publish );
274+
275+
// Change the purge days option.
276+
update_option( 'activitypub_outbox_purge_days', 90 );
277+
278+
// Run purge_outbox with changed_days.
279+
Scheduler::purge_outbox();
280+
wp_cache_delete( _count_posts_cache_key( Outbox::POST_TYPE ), 'counts' );
281+
282+
// Verify posts are deleted.
283+
$this->assertEquals( 0, wp_count_posts( Outbox::POST_TYPE )->publish );
284+
}
251285
}

0 commit comments

Comments
 (0)