PluginProbe
ActivityPub / 1.0.3
ActivityPub v1.0.3
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-activitypub.php

class-activitypub.php in ActivityPub 1.0.3, at includes/class-activitypub.php

332 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Activitypub;
3
4 use Activitypub\Signature;
5 use Activitypub\Collection\Users;
6
7 /**
8 * ActivityPub Class
9 *
10 * @author Matthias Pfefferle
11 */
12 class Activitypub {
13 /**
14 * Initialize the class, registering WordPress hooks.
15 */
16 public static function init() {
17 \add_filter( 'template_include', array( self::class, 'render_json_template' ), 99 );
18 \add_filter( 'query_vars', array( self::class, 'add_query_vars' ) );
19 \add_filter( 'pre_get_avatar_data', array( self::class, 'pre_get_avatar_data' ), 11, 2 );
20 \add_filter( 'get_comment_link', array( self::class, 'remote_comment_link' ), 11, 3 );
21
22 // Add support for ActivityPub to custom post types
23 $post_types = \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) ) ? \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) ) : array();
24
25 foreach ( $post_types as $post_type ) {
26 \add_post_type_support( $post_type, 'activitypub' );
27 }
28
29 \add_action( 'wp_trash_post', array( self::class, 'trash_post' ), 1 );
30 \add_action( 'untrash_post', array( self::class, 'untrash_post' ), 1 );
31
32 \add_action( 'init', array( self::class, 'add_rewrite_rules' ), 11 );
33
34 \add_action( 'after_setup_theme', array( self::class, 'theme_compat' ), 99 );
35
36 \add_action( 'in_plugin_update_message-' . ACTIVITYPUB_PLUGIN_BASENAME, array( self::class, 'plugin_update_message' ) );
37 }
38
39 /**
40 * Activation Hook
41 *
42 * @return void
43 */
44 public static function activate() {
45 self::flush_rewrite_rules();
46
47 Scheduler::register_schedules();
48 }
49
50 /**
51 * Deactivation Hook
52 *
53 * @return void
54 */
55 public static function deactivate() {
56 self::flush_rewrite_rules();
57
58 Scheduler::deregister_schedules();
59 }
60
61 /**
62 * Uninstall Hook
63 *
64 * @return void
65 */
66 public static function uninstall() {
67 Scheduler::deregister_schedules();
68 }
69
70 /**
71 * Return a AS2 JSON version of an author, post or page.
72 *
73 * @param string $template The path to the template object.
74 *
75 * @return string The new path to the JSON template.
76 */
77 public static function render_json_template( $template ) {
78 if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
79 return $template;
80 }
81
82 if ( ! is_activitypub_request() ) {
83 return $template;
84 }
85
86 $json_template = false;
87
88 // check if user can publish posts
89 if ( \is_author() && is_wp_error( Users::get_by_id( \get_the_author_meta( 'ID' ) ) ) ) {
90 return $template;
91 }
92
93 if ( \is_author() ) {
94 $json_template = ACTIVITYPUB_PLUGIN_DIR . '/templates/author-json.php';
95 } elseif ( \is_singular() ) {
96 $json_template = ACTIVITYPUB_PLUGIN_DIR . '/templates/post-json.php';
97 } elseif ( \is_home() ) {
98 $json_template = ACTIVITYPUB_PLUGIN_DIR . '/templates/blog-json.php';
99 }
100
101 if ( ACTIVITYPUB_AUTHORIZED_FETCH ) {
102 $verification = Signature::verify_http_signature( $_SERVER );
103 if ( \is_wp_error( $verification ) ) {
104 // fallback as template_loader can't return http headers
105 return $template;
106 }
107 }
108
109 return $json_template;
110 }
111
112 /**
113 * Add the 'activitypub' query variable so WordPress won't mangle it.
114 */
115 public static function add_query_vars( $vars ) {
116 $vars[] = 'activitypub';
117
118 return $vars;
119 }
120
121 /**
122 * Replaces the default avatar.
123 *
124 * @param array $args Arguments passed to get_avatar_data(), after processing.
125 * @param int|string|object $id_or_email A user ID, email address, or comment object.
126 *
127 * @return array $args
128 */
129 public static function pre_get_avatar_data( $args, $id_or_email ) {
130 if (
131 ! $id_or_email instanceof \WP_Comment ||
132 ! isset( $id_or_email->comment_type ) ||
133 $id_or_email->user_id
134 ) {
135 return $args;
136 }
137
138 $allowed_comment_types = \apply_filters( 'get_avatar_comment_types', array( 'comment' ) );
139 if (
140 ! empty( $id_or_email->comment_type ) &&
141 ! \in_array(
142 $id_or_email->comment_type,
143 (array) $allowed_comment_types,
144 true
145 )
146 ) {
147 $args['url'] = false;
148 /** This filter is documented in wp-includes/link-template.php */
149 return \apply_filters( 'get_avatar_data', $args, $id_or_email );
150 }
151
152 // Check if comment has an avatar.
153 $avatar = self::get_avatar_url( $id_or_email->comment_ID );
154
155 if ( $avatar ) {
156 if ( ! isset( $args['class'] ) || ! \is_array( $args['class'] ) ) {
157 $args['class'] = array( 'u-photo' );
158 } else {
159 $args['class'][] = 'u-photo';
160 $args['class'] = \array_unique( $args['class'] );
161 }
162 $args['url'] = $avatar;
163 $args['class'][] = 'avatar-activitypub';
164 }
165
166 return $args;
167 }
168
169 /**
170 * Function to retrieve Avatar URL if stored in meta.
171 *
172 * @param int|WP_Comment $comment
173 *
174 * @return string $url
175 */
176 public static function get_avatar_url( $comment ) {
177 if ( \is_numeric( $comment ) ) {
178 $comment = \get_comment( $comment );
179 }
180 return \get_comment_meta( $comment->comment_ID, 'avatar_url', true );
181 }
182
183 /**
184 * Link remote comments to source url.
185 *
186 * @param string $comment_link
187 * @param object|WP_Comment $comment
188 *
189 * @return string $url
190 */
191 public static function remote_comment_link( $comment_link, $comment ) {
192 $remote_comment_link = get_comment_meta( $comment->comment_ID, 'source_url', true );
193 if ( $remote_comment_link ) {
194 $comment_link = esc_url( $remote_comment_link );
195 }
196 return $comment_link;
197 }
198
199 /**
200 * Store permalink in meta, to send delete Activity.
201 *
202 * @param string $post_id The Post ID.
203 *
204 * @return void
205 */
206 public static function trash_post( $post_id ) {
207 \add_post_meta(
208 $post_id,
209 'activitypub_canonical_url',
210 \get_permalink( $post_id ),
211 true
212 );
213 }
214
215 /**
216 * Delete permalink from meta
217 *
218 * @param string $post_id The Post ID
219 *
220 * @return void
221 */
222 public static function untrash_post( $post_id ) {
223 \delete_post_meta( $post_id, 'activitypub_canonical_url' );
224 }
225
226 /**
227 * Add rewrite rules
228 */
229 public static function add_rewrite_rules() {
230 // If another system needs to take precedence over the ActivityPub rewrite rules,
231 // they can define their own and will manually call the appropriate functions as required.
232 if ( ACTIVITYPUB_DISABLE_REWRITES ) {
233 return;
234 }
235
236 if ( ! \class_exists( 'Webfinger' ) ) {
237 \add_rewrite_rule(
238 '^.well-known/webfinger',
239 'index.php?rest_route=/' . ACTIVITYPUB_REST_NAMESPACE . '/webfinger',
240 'top'
241 );
242 }
243
244 if ( ! \class_exists( 'Nodeinfo_Endpoint' ) && true === (bool) \get_option( 'blog_public', 1 ) ) {
245 \add_rewrite_rule(
246 '^.well-known/nodeinfo',
247 'index.php?rest_route=/' . ACTIVITYPUB_REST_NAMESPACE . '/nodeinfo/discovery',
248 'top'
249 );
250 \add_rewrite_rule(
251 '^.well-known/x-nodeinfo2',
252 'index.php?rest_route=/' . ACTIVITYPUB_REST_NAMESPACE . '/nodeinfo2',
253 'top'
254 );
255 }
256
257 \add_rewrite_rule(
258 '^@([\w\-\.]+)',
259 'index.php?rest_route=/' . ACTIVITYPUB_REST_NAMESPACE . '/users/$matches[1]',
260 'top'
261 );
262
263 \add_rewrite_endpoint( 'activitypub', EP_AUTHORS | EP_PERMALINK | EP_PAGES );
264 }
265
266 /**
267 * Flush rewrite rules;
268 */
269 public static function flush_rewrite_rules() {
270 self::add_rewrite_rules();
271 \flush_rewrite_rules();
272 }
273
274 /**
275 * Theme compatibility stuff
276 *
277 * @return void
278 */
279 public static function theme_compat() {
280 $site_icon = get_theme_support( 'custom-logo' );
281
282 if ( ! $site_icon ) {
283 // custom logo support
284 add_theme_support(
285 'custom-logo',
286 array(
287 'height' => 80,
288 'width' => 80,
289 )
290 );
291 }
292
293 $custom_header = get_theme_support( 'custom-header' );
294
295 if ( ! $custom_header ) {
296 // This theme supports a custom header
297 $custom_header_args = array(
298 'width' => 1250,
299 'height' => 600,
300 'header-text' => true,
301 );
302 add_theme_support( 'custom-header', $custom_header_args );
303 }
304 }
305
306 /**
307 * Display plugin upgrade notice to users
308 *
309 * @param array $data The plugin data
310 *
311 * @return void
312 */
313 public static function plugin_update_message( $data ) {
314 if ( ! isset( $data['upgrade_notice'] ) ) {
315 return;
316 }
317
318 printf(
319 '<div class="update-message">%s</div>',
320 wp_kses(
321 wpautop( $data['upgrade_notice '] ),
322 array(
323 'p' => array(),
324 'a' => array( 'href', 'title' ),
325 'strong' => array(),
326 'em' => array(),
327 )
328 )
329 );
330 }
331 }
332