@@ -22,12 +22,29 @@ class Dispatcher {
2222 /**
2323 * Batch size.
2424 *
25- * @deprecated unreleased {@see Activitypub\ Dispatcher::get_batch_size()}
25+ * @deprecated unreleased Use {@see Dispatcher::get_batch_size()}.
2626 *
2727 * @var int
2828 */
2929 public static $ batch_size = ACTIVITYPUB_OUTBOX_PROCESSING_BATCH_SIZE ;
3030
31+ /**
32+ * Initialize the class, registering WordPress hooks.
33+ */
34+ public static function init () {
35+ \add_action ( 'activitypub_process_outbox ' , array ( self ::class, 'process_outbox ' ) );
36+
37+ \add_action ( 'post_activitypub_add_to_outbox ' , array ( self ::class, 'send_immediate_accept ' ), 10 , 2 );
38+
39+ // Default filters to add Inboxes to sent to.
40+ \add_filter ( 'activitypub_additional_inboxes ' , array ( self ::class, 'add_inboxes_by_mentioned_actors ' ), 10 , 3 );
41+ \add_filter ( 'activitypub_additional_inboxes ' , array ( self ::class, 'add_inboxes_of_replied_urls ' ), 10 , 3 );
42+ \add_filter ( 'activitypub_additional_inboxes ' , array ( self ::class, 'add_inboxes_of_relays ' ), 10 , 3 );
43+
44+ Scheduler::register_async_batch_callback ( 'activitypub_send_activity ' , array ( self ::class, 'send_to_followers ' ) );
45+ Scheduler::register_async_batch_callback ( 'activitypub_retry_activity ' , array ( self ::class, 'retry_send_to_followers ' ) );
46+ }
47+
3148 /**
3249 * Get the batch size for processing outbox items.
3350 *
@@ -90,23 +107,6 @@ public static function get_retry_error_codes() {
90107 return apply_filters ( 'activitypub_dispatcher_retry_error_codes ' , array ( 408 , 429 , 500 , 502 , 503 , 504 ) );
91108 }
92109
93- /**
94- * Initialize the class, registering WordPress hooks.
95- */
96- public static function init () {
97- \add_action ( 'activitypub_process_outbox ' , array ( self ::class, 'process_outbox ' ) );
98-
99- \add_action ( 'post_activitypub_add_to_outbox ' , array ( self ::class, 'send_immediate_accept ' ), 10 , 2 );
100-
101- // Default filters to add Inboxes to sent to.
102- \add_filter ( 'activitypub_additional_inboxes ' , array ( self ::class, 'add_inboxes_by_mentioned_actors ' ), 10 , 3 );
103- \add_filter ( 'activitypub_additional_inboxes ' , array ( self ::class, 'add_inboxes_of_replied_urls ' ), 10 , 3 );
104- \add_filter ( 'activitypub_additional_inboxes ' , array ( self ::class, 'add_inboxes_of_relays ' ), 10 , 3 );
105-
106- Scheduler::register_async_batch_callback ( 'activitypub_send_activity ' , array ( self ::class, 'send_to_followers ' ) );
107- Scheduler::register_async_batch_callback ( 'activitypub_retry_activity ' , array ( self ::class, 'retry_send_to_followers ' ) );
108- }
109-
110110 /**
111111 * Process the outbox.
112112 *
@@ -253,16 +253,21 @@ private static function send_to_inboxes( $inboxes, $outbox_item_id ) {
253253 \do_action ( 'activitypub_pre_send_to_inboxes ' , $ json , $ inboxes , $ outbox_item_id );
254254
255255 foreach ( $ inboxes as $ inbox ) {
256- $ result = safe_remote_post ( $ inbox , $ json , $ outbox_item ->post_author );
256+ // Handle local inboxes via internal REST API, remote via HTTP.
257+ if ( is_same_domain ( $ inbox ) ) {
258+ $ result = self ::send_to_local_inbox ( $ inbox , $ json );
259+ } else {
260+ $ result = safe_remote_post ( $ inbox , $ json , $ outbox_item ->post_author );
261+ }
257262
258- if ( is_wp_error ( $ result ) && in_array ( $ result ->get_error_code (), self ::get_retry_error_codes (), true ) ) {
263+ if ( \ is_wp_error ( $ result ) && in_array ( $ result ->get_error_code (), self ::get_retry_error_codes (), true ) ) {
259264 $ retries [] = $ inbox ;
260265 }
261266
262267 /**
263268 * Fires after an Activity has been sent to an inbox.
264269 *
265- * @param array $result The result of the remote post request.
270+ * @param array $result The result of the internal or remote post request.
266271 * @param string $inbox The inbox URL.
267272 * @param string $json The ActivityPub Activity JSON.
268273 * @param int $actor_id The actor ID.
@@ -274,6 +279,41 @@ private static function send_to_inboxes( $inboxes, $outbox_item_id ) {
274279 return $ retries ;
275280 }
276281
282+ /**
283+ * Send an activity to a local inbox via internal REST API request.
284+ *
285+ * @param string $inbox_url The local inbox URL.
286+ * @param string $json The ActivityPub Activity JSON.
287+ * @return array|\WP_Error The result in the format of a remote post response, or WP_Error on failure.
288+ */
289+ private static function send_to_local_inbox ( $ inbox_url , $ json ) {
290+ // Parse the inbox URL to extract the REST route.
291+ $ path = \wp_parse_url ( $ inbox_url , PHP_URL_PATH ) ?? '' ;
292+ $ rest_route = \preg_replace ( '#^/ ' . preg_quote ( \rest_get_url_prefix (), '# ' ) . '# ' , '' , $ path );
293+
294+ // Create a REST request.
295+ $ request = new \WP_REST_Request ( 'POST ' , $ rest_route );
296+ $ request ->set_header ( 'Content-Type ' , 'application/activity+json ' );
297+ $ request ->set_body ( $ json );
298+ $ request ->get_json_params ();
299+
300+ \add_filter ( 'activitypub_defer_signature_verification ' , '__return_true ' );
301+ $ response = \rest_do_request ( $ request );
302+ \remove_filter ( 'activitypub_defer_signature_verification ' , '__return_true ' );
303+
304+ // Return result in format similar to remote post response.
305+ if ( $ response ->is_error () ) {
306+ return $ response ->as_error ();
307+ }
308+
309+ return array (
310+ 'response ' => array (
311+ 'code ' => $ response ->get_status (),
312+ ),
313+ 'body ' => \wp_json_encode ( $ response ->get_data () ),
314+ );
315+ }
316+
277317 /**
278318 * Schedule a retry.
279319 *
@@ -335,13 +375,8 @@ public static function add_inboxes_by_mentioned_actors( $inboxes, $actor_id, $ac
335375
336376 $ audience = array_merge ( $ cc , $ to );
337377
338- // Remove "public placeholder" and "same domain" from the audience.
339- $ audience = array_filter (
340- $ audience ,
341- function ( $ actor ) {
342- return 'https://www.w3.org/ns/activitystreams#Public ' !== $ actor && ! is_same_domain ( $ actor );
343- }
344- );
378+ // Remove "public placeholder" from the audience.
379+ $ audience = array_diff ( $ audience , array ( 'https://www.w3.org/ns/activitystreams#Public ' ) );
345380
346381 if ( $ audience ) {
347382 $ mentioned_inboxes = Mention::get_inboxes ( $ audience );
0 commit comments