Skip to content

Commit 83d654b

Browse files
authored
Refactor mention detection to use Remote_Actors (#2602)
1 parent ec4fe89 commit 83d654b

File tree

4 files changed

+58
-57
lines changed

4 files changed

+58
-57
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+
Improve performance and reliability of @-mention detection.

includes/class-http.php

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -235,21 +235,10 @@ public static function get_remote_object( $url_or_object, $cached = true ) {
235235
);
236236
}
237237

238-
if ( is_wp_error( $url ) ) {
238+
if ( \is_wp_error( $url ) ) {
239239
return $url;
240240
}
241241

242-
$transient_key = self::generate_cache_key( $url );
243-
244-
// Only check the cache if needed.
245-
if ( $cached ) {
246-
$data = \get_transient( $transient_key );
247-
248-
if ( $data ) {
249-
return $data;
250-
}
251-
}
252-
253242
if ( ! \wp_http_validate_url( $url ) ) {
254243
return new \WP_Error(
255244
'activitypub_no_valid_object_url',
@@ -261,7 +250,7 @@ public static function get_remote_object( $url_or_object, $cached = true ) {
261250
);
262251
}
263252

264-
$response = self::get( $url );
253+
$response = self::get( $url, $cached );
265254

266255
if ( \is_wp_error( $response ) ) {
267256
return $response;
@@ -281,8 +270,6 @@ public static function get_remote_object( $url_or_object, $cached = true ) {
281270
);
282271
}
283272

284-
\set_transient( $transient_key, $data, WEEK_IN_SECONDS );
285-
286273
return $data;
287274
}
288275
}

includes/class-mention.php

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Activitypub;
99

10-
use WP_Error;
10+
use Activitypub\Collection\Remote_Actors;
1111

1212
/**
1313
* ActivityPub Mention Class.
@@ -65,27 +65,22 @@ public static function the_content( $the_content ) {
6565
* @return string The final string.
6666
*/
6767
public static function replace_with_links( $result ) {
68-
$metadata = get_remote_metadata_by_actor( $result[0] );
69-
70-
if (
71-
! empty( $metadata ) &&
72-
! is_wp_error( $metadata ) &&
73-
( ! empty( $metadata['id'] ) || ! empty( $metadata['url'] ) )
74-
) {
75-
$username = ltrim( $result[0], '@' );
76-
if ( ! empty( $metadata['name'] ) ) {
77-
$username = $metadata['name'];
78-
}
79-
if ( ! empty( $metadata['preferredUsername'] ) ) {
80-
$username = $metadata['preferredUsername'];
81-
}
68+
$post = Remote_Actors::fetch_by_acct( $result[0] );
8269

83-
$url = isset( $metadata['url'] ) ? object_to_uri( $metadata['url'] ) : object_to_uri( $metadata['id'] );
70+
if ( \is_wp_error( $post ) ) {
71+
return $result[0];
72+
}
8473

85-
return \sprintf( '<a rel="mention" class="u-url mention" href="%1$s">@%2$s</a>', esc_url( $url ), esc_html( $username ) );
74+
$actor = Remote_Actors::get_actor( $post );
75+
76+
if ( \is_wp_error( $actor ) ) {
77+
return $result[0];
8678
}
8779

88-
return $result[0];
80+
$username = $actor->get_preferred_username() ?: $actor->get_name() ?: Sanitize::webfinger( $result[0] );
81+
$url = object_to_uri( $actor->get_url() ?: $actor->get_id() );
82+
83+
return \sprintf( '<a rel="mention" class="u-url mention" href="%1$s">@%2$s</a>', esc_url( $url ), esc_html( $username ) );
8984
}
9085

9186
/**
@@ -114,7 +109,7 @@ public static function get_inboxes( $mentioned ) {
114109
*
115110
* @param string $actor The Actor URL.
116111
*
117-
* @return string|WP_Error The Inbox-URL or WP_Error if not found.
112+
* @return string|\WP_Error The Inbox-URL or WP_Error if not found.
118113
*/
119114
public static function get_inbox_by_mentioned_actor( $actor ) {
120115
$metadata = get_remote_metadata_by_actor( $actor );
@@ -131,7 +126,7 @@ public static function get_inbox_by_mentioned_actor( $actor ) {
131126
return $metadata['inbox'];
132127
}
133128

134-
return new WP_Error( 'activitypub_no_inbox', \__( 'No "Inbox" found', 'activitypub' ), $metadata );
129+
return new \WP_Error( 'activitypub_no_inbox', \__( 'No "Inbox" found', 'activitypub' ), $metadata );
135130
}
136131

137132
/**

tests/phpunit/tests/includes/class-test-mention.php

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,13 @@ class Test_Mention extends \WP_UnitTestCase {
2525
*/
2626
public static $actors = array(
2727
'[email protected]' => array(
28-
'id' => 'https://example.org/users/username',
29-
'url' => 'https://example.org/users/username',
30-
'name' => 'username',
28+
'@context' => 'https://www.w3.org/ns/activitystreams',
29+
'id' => 'https://example.org/users/username',
30+
'type' => 'Person',
31+
'url' => 'https://example.org/users/username',
32+
'name' => 'username',
33+
'preferredUsername' => 'username',
34+
'inbox' => 'https://example.org/users/username/inbox',
3135
),
3236
);
3337

@@ -36,7 +40,6 @@ class Test_Mention extends \WP_UnitTestCase {
3640
*/
3741
public function set_up() {
3842
parent::set_up();
39-
add_filter( 'pre_get_remote_metadata_by_actor', array( get_called_class(), 'pre_get_remote_metadata_by_actor' ), 10, 2 );
4043
add_filter( 'pre_http_request', array( $this, 'pre_http_request' ), 10, 3 );
4144
add_filter( 'activitypub_pre_http_get_remote_object', array( $this, 'activitypub_pre_http_get_remote_object' ), 10, 2 );
4245
}
@@ -45,7 +48,6 @@ public function set_up() {
4548
* Tear down the test case.
4649
*/
4750
public function tear_down() {
48-
remove_filter( 'pre_get_remote_metadata_by_actor', array( get_called_class(), 'pre_get_remote_metadata_by_actor' ) );
4951
remove_filter( 'pre_http_request', array( $this, 'pre_http_request' ) );
5052
remove_filter( 'activitypub_pre_http_get_remote_object', array( $this, 'activitypub_pre_http_get_remote_object' ) );
5153
parent::tear_down();
@@ -103,6 +105,26 @@ public function the_content_provider() {
103105
* @return array|false|\WP_Error
104106
*/
105107
public function pre_http_request( $response, $parsed_args, $url ) {
108+
// Mock webfinger for test actors.
109+
if ( 'https://example.org/.well-known/webfinger?resource=acct%3Ausername%40example.org' === $url ) {
110+
return array(
111+
'headers' => array( 'content-type' => 'application/jrd+json' ),
112+
'body' => wp_json_encode(
113+
array(
114+
'subject' => 'acct:[email protected]',
115+
'links' => array(
116+
array(
117+
'rel' => 'self',
118+
'type' => 'application/activity+json',
119+
'href' => 'https://example.org/users/username',
120+
),
121+
),
122+
)
123+
),
124+
'response' => array( 'code' => 200 ),
125+
);
126+
}
127+
106128
// Mock responses for remote users.
107129
if ( 'https://notiz.blog/.well-known/webfinger?resource=acct%3Apfefferle%40notiz.blog' === $url ) {
108130
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
@@ -137,6 +159,16 @@ public function pre_http_request( $response, $parsed_args, $url ) {
137159
public function activitypub_pre_http_get_remote_object( $pre, $url_or_object ) {
138160
$url = object_to_uri( $url_or_object );
139161

162+
// Check if this is a URL from our test actors.
163+
foreach ( self::$actors as $actor_data ) {
164+
if ( isset( $actor_data['id'] ) && $actor_data['id'] === $url ) {
165+
return $actor_data;
166+
}
167+
if ( isset( $actor_data['url'] ) && $actor_data['url'] === $url ) {
168+
return $actor_data;
169+
}
170+
}
171+
140172
// Return parsed object data for ActivityPub actors.
141173
if ( 'https://notiz.blog/author/matthias-pfefferle/' === $url ) {
142174
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
@@ -152,21 +184,4 @@ public function activitypub_pre_http_get_remote_object( $pre, $url_or_object ) {
152184

153185
return $pre;
154186
}
155-
156-
/**
157-
* Filters remote metadata by actor.
158-
*
159-
* @param array|string $pre The pre-filtered value.
160-
* @param string $actor The actor.
161-
* @return array|string
162-
*/
163-
public static function pre_get_remote_metadata_by_actor( $pre, $actor ) {
164-
$actor = ltrim( $actor, '@' );
165-
166-
if ( isset( self::$actors[ $actor ] ) ) {
167-
return self::$actors[ $actor ];
168-
}
169-
170-
return $pre;
171-
}
172187
}

0 commit comments

Comments
 (0)