PluginProbe
ActivityPub / 1.0.0
ActivityPub v1.0.0
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.0, at includes/class-activitypub.php

326 lines 7.7 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 ( ! \class_exists( 'Webfinger' ) ) {
231 \add_rewrite_rule(
232 '^.well-known/webfinger',
233 'index.php?rest_route=/' . ACTIVITYPUB_REST_NAMESPACE . '/webfinger',
234 'top'
235 );
236 }
237
238 if ( ! \class_exists( 'Nodeinfo_Endpoint' ) && true === (bool) \get_option( 'blog_public', 1 ) ) {
239 \add_rewrite_rule(
240 '^.well-known/nodeinfo',
241 'index.php?rest_route=/' . ACTIVITYPUB_REST_NAMESPACE . '/nodeinfo/discovery',
242 'top'
243 );
244 \add_rewrite_rule(
245 '^.well-known/x-nodeinfo2',
246 'index.php?rest_route=/' . ACTIVITYPUB_REST_NAMESPACE . '/nodeinfo2',
247 'top'
248 );
249 }
250
251 \add_rewrite_rule(
252 '^@([\w\-\.]+)',
253 'index.php?rest_route=/' . ACTIVITYPUB_REST_NAMESPACE . '/users/$matches[1]',
254 'top'
255 );
256
257 \add_rewrite_endpoint( 'activitypub', EP_AUTHORS | EP_PERMALINK | EP_PAGES );
258 }
259
260 /**
261 * Flush rewrite rules;
262 */
263 public static function flush_rewrite_rules() {
264 self::add_rewrite_rules();
265 \flush_rewrite_rules();
266 }
267
268 /**
269 * Theme compatibility stuff
270 *
271 * @return void
272 */
273 public static function theme_compat() {
274 $site_icon = get_theme_support( 'custom-logo' );
275
276 if ( ! $site_icon ) {
277 // custom logo support
278 add_theme_support(
279 'custom-logo',
280 array(
281 'height' => 80,
282 'width' => 80,
283 )
284 );
285 }
286
287 $custom_header = get_theme_support( 'custom-header' );
288
289 if ( ! $custom_header ) {
290 // This theme supports a custom header
291 $custom_header_args = array(
292 'width' => 1250,
293 'height' => 600,
294 'header-text' => true,
295 );
296 add_theme_support( 'custom-header', $custom_header_args );
297 }
298 }
299
300 /**
301 * Display plugin upgrade notice to users
302 *
303 * @param array $data The plugin data
304 *
305 * @return void
306 */
307 public static function plugin_update_message( $data ) {
308 if ( ! isset( $data['upgrade_notice'] ) ) {
309 return;
310 }
311
312 printf(
313 '<div class="update-message">%s</div>',
314 wp_kses(
315 wpautop( $data['upgrade_notice '] ),
316 array(
317 'p' => array(),
318 'a' => array( 'href', 'title' ),
319 'strong' => array(),
320 'em' => array(),
321 )
322 )
323 );
324 }
325 }
326