PluginProbe
ActivityPub / 7.8.4
ActivityPub v7.8.4
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 / integration / class-wp-rest-cache.php

class-wp-rest-cache.php in ActivityPub 7.8.4, at integration/class-wp-rest-cache.php

149 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WP REST Cache integration file.
4 *
5 * This file contains code for caching ActivityPub REST requests.
6 *
7 * Copyright (C) 2025 Epiphyt
8 * Original code: https://epiph.yt/en/blog/2025/accidental-ddos-through-activitypub-plugin/
9 *
10 * Portions of this code are adapted from GPL v2 licensed code.
11 * As such, you may also redistribute and/or modify those portions under the terms of
12 * the GNU General Public License as published by the Free Software Foundation.
13 *
14 * https://www.gnu.org/licenses/gpl-2.0.html
15 *
16 * @package Activitypub
17 */
18
19 namespace Activitypub\Integration;
20
21 use Activitypub\Collection\Outbox;
22 use Activitypub\Comment;
23 use WP_Rest_Cache_Plugin\Includes\Caching\Caching;
24
25 /**
26 * Compatibility with the WP REST Cache plugin.
27 *
28 * @see https://wordpress.org/plugins/wp-rest-cache/
29 */
30 class WP_Rest_Cache {
31 /**
32 * Initialize the class, registering WordPress hooks.
33 */
34 public static function init() {
35 \add_filter( 'wp_rest_cache/allowed_endpoints', array( self::class, 'add_activitypub_endpoints' ) );
36 \add_filter( 'wp_rest_cache/determine_object_type', array( self::class, 'set_object_type' ), 10, 4 );
37 \add_filter( 'wp_rest_cache/is_single_item', array( self::class, 'set_is_single_item' ), 10, 3 );
38 \add_action( 'transition_post_status', array( self::class, 'transition_post_status' ), 10, 3 );
39 \add_action( 'transition_comment_status', array( self::class, 'transition_comment_status' ), 10, 3 );
40 }
41
42 /**
43 * Add ActivityPub endpoints to the list of allowed endpoints.
44 *
45 * @param array $endpoints List of allowed endpoints.
46 *
47 * @return array Filtered list of allowed endpoints.
48 */
49 public static function add_activitypub_endpoints( $endpoints ) {
50 $endpoints[ ACTIVITYPUB_REST_NAMESPACE ] = array( 'actors', 'collections', 'comments', 'interactions', 'nodeinfo', 'posts', 'users' );
51
52 return $endpoints;
53 }
54
55 /**
56 * Set whether the cache represents a single item.
57 *
58 * Always return false for ActivityPub endpoints, since cache entries cannot be flushed otherwise.
59 *
60 * @param bool $is_single Whether the current cache represents a single item.
61 * @param mixed $data Data to cache.
62 * @param string $uri Request URI.
63 *
64 * @return bool Whether the cache represents a single item.
65 */
66 public static function set_is_single_item( $is_single, $data, $uri ) {
67 if ( self::is_activitypub_endpoint( $uri ) ) {
68 return false;
69 }
70
71 return $is_single;
72 }
73
74 /**
75 * Set object type for ActivityPub.
76 *
77 * @param string $object_type Object type.
78 * @param string $cache_key Object key.
79 * @param mixed $data Data to cache.
80 * @param string $uri Request URI.
81 *
82 * @return string Updated object type.
83 */
84 public static function set_object_type( $object_type, $cache_key, $data, $uri ) {
85 if ( self::is_activitypub_endpoint( $uri ) ) {
86 return 'ActivityPub';
87 }
88
89 return $object_type;
90 }
91
92 /**
93 * Reset cache by transition post status.
94 *
95 * @param string $new_status New post status.
96 * @param string $old_status Old post status.
97 * @param \WP_Post $post Post object.
98 */
99 public static function transition_post_status( $new_status, $old_status, $post ) {
100 if ( 'publish' !== $new_status && 'publish' !== $old_status ) {
101 return;
102 }
103
104 $post_types = \get_option( 'activitypub_support_post_types', array() );
105 $post_types[] = Outbox::POST_TYPE;
106
107 if ( ! \in_array( $post->post_type, $post_types, true ) ) {
108 return;
109 }
110
111 Caching::get_instance()->delete_object_type_caches( 'ActivityPub' );
112 }
113
114 /**
115 * Reset cache by transition comment status.
116 *
117 * @param string $new_status The new comment status.
118 * @param string $old_status The old comment status.
119 * @param \WP_Comment $comment Comment object.
120 */
121 public static function transition_comment_status( $new_status, $old_status, $comment ) {
122 if ( 'approved' !== $new_status && 'approved' !== $old_status ) {
123 return;
124 }
125
126 $comment_types = Comment::get_comment_type_slugs();
127 $comment_types[] = 'comment';
128
129 if ( ! \in_array( $comment->comment_type ?: 'comment', $comment_types, true ) ) {
130 return;
131 }
132
133 Caching::get_instance()->delete_object_type_caches( 'ActivityPub' );
134 }
135
136 /**
137 * Test, whether the current endpoint is an ActivityPub endpoint.
138 *
139 * @param string $uri URI to test.
140 *
141 * @return bool Whether the current endpoint is an ActivityPub endpoint.
142 */
143 private static function is_activitypub_endpoint( $uri ) {
144 $search = '/' . ACTIVITYPUB_REST_NAMESPACE . '/';
145
146 return \str_contains( $uri, $search ) || \str_contains( $uri, 'rest_route=' . \rawurlencode( $search ) );
147 }
148 }
149