PluginProbe
ActivityPub / trunk
ActivityPub vtrunk
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
activitypub / includes / class-search.php

class-search.php in ActivityPub trunk, at includes/class-search.php

144 lines 3.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ActivityPub Search Enhancement Class
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub;
9
10 use Activitypub\Collection\Interactions;
11
12 /**
13 * ActivityPub Search Enhancement Class
14 *
15 * This class enhances WordPress search functionality to detect URLs in search queries
16 * and attempt to import ActivityPub objects if found, otherwise falls back to classic search.
17 */
18 class Search {
19
20 /**
21 * Initialize the search enhancement.
22 */
23 public static function init() {
24 \add_filter( 'pre_get_posts', array( self::class, 'enhance_public_search' ) );
25 \add_action( 'load-edit-comments.php', array( self::class, 'enhance_admin_comment_search' ) );
26 }
27
28 /**
29 * Enhance public search functionality to check for URLs and ActivityPub objects.
30 *
31 * @param \WP_Query $query The WP_Query instance.
32 * @return \WP_Query The modified query.
33 */
34 public static function enhance_public_search( $query ) {
35 // Check user capabilities.
36 if ( ! \current_user_can( 'activitypub' ) ) {
37 return $query;
38 }
39
40 // Only enhance main search queries on frontend.
41 if ( ! $query->is_main_query() || ! $query->is_search() || \is_admin() ) {
42 return $query;
43 }
44
45 $search_term = $query->get( 's' );
46 if ( empty( $search_term ) ) {
47 return $query;
48 }
49
50 // Check if search term is a URL.
51 if ( ! \wp_http_validate_url( $search_term ) ) {
52 return $query;
53 }
54
55 // Try to import ActivityPub object.
56 $imported = self::try_import_activitypub_object( $search_term );
57
58 if ( $imported ) {
59 // Ensure the imported comment is approved/published.
60 \wp_set_comment_status( $imported, 'approve' );
61 $comment_link = \get_comment_link( $imported );
62 $validated_link = \wp_validate_redirect( $comment_link, \home_url() );
63 if ( $validated_link ) {
64 \wp_safe_redirect( $validated_link );
65 exit;
66 }
67 }
68
69 // Fall back to classic search if import failed or no redirect.
70 return $query;
71 }
72
73 /**
74 * Handle admin comment search to check for URLs and ActivityPub objects.
75 * Runs on admin_init to avoid infinite loops.
76 */
77 public static function enhance_admin_comment_search() {
78 // Check user capabilities.
79 if ( ! \current_user_can( 'activitypub' ) ) {
80 return;
81 }
82
83 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
84 $search_term = isset( $_GET['s'] ) ? \sanitize_text_field( \wp_unslash( $_GET['s'] ) ) : '';
85 if ( empty( $search_term ) ) {
86 return;
87 }
88
89 // Check if search term is a URL.
90 if ( ! \wp_http_validate_url( $search_term ) ) {
91 return;
92 }
93
94 // Try to import ActivityPub object.
95 $imported = self::try_import_activitypub_object( $search_term );
96
97 if ( $imported ) {
98 // Ensure the imported comment is approved/published.
99 \wp_set_comment_status( $imported, 'approve' );
100 $comment_link = \get_comment_link( $imported );
101 $validated_link = \wp_validate_redirect( $comment_link, \home_url() );
102 if ( $validated_link ) {
103 \wp_safe_redirect( $validated_link );
104 exit;
105 }
106 }
107 }
108
109 /**
110 * Try to import an ActivityPub reply from a URL.
111 *
112 * @param string $url The URL to check and import.
113 *
114 * @return int|false The imported comment ID or false on failure.
115 */
116 private static function try_import_activitypub_object( $url ) {
117 // Check if it's already imported.
118 $existing = Comment::url_to_commentid( $url );
119 if ( $existing ) {
120 return $existing;
121 }
122
123 // Try to fetch as ActivityPub object.
124 $object = Http::get_remote_object( $url );
125 if ( \is_wp_error( $object ) ) {
126 return false;
127 }
128
129 // Check if it's a reply (has inReplyTo).
130 if ( empty( $object['inReplyTo'] ) ) {
131 return false;
132 }
133
134 $activity = array(
135 'type' => 'Create',
136 'actor' => $object['attributedTo'],
137 'object' => $object,
138 );
139
140 // Import the reply as a comment.
141 return Interactions::add_comment( $activity );
142 }
143 }
144