PluginProbe
ActivityPub / 4.0.2
ActivityPub v4.0.2
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 / rest / class-collection.php

class-collection.php in ActivityPub 4.0.2, at includes/rest/class-collection.php

308 lines 7.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Collections REST-Class file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Rest;
9
10 use WP_Error;
11 use WP_REST_Server;
12 use WP_REST_Response;
13 use Activitypub\Activity\Actor;
14 use Activitypub\Collection\Replies;
15 use Activitypub\Transformer\Factory;
16 use Activitypub\Activity\Base_Object;
17 use Activitypub\Collection\Users as User_Collection;
18
19 use function Activitypub\esc_hashtag;
20 use function Activitypub\is_single_user;
21 use function Activitypub\get_rest_url_by_path;
22
23 /**
24 * ActivityPub Collections REST-Class.
25 *
26 * @author Matthias Pfefferle
27 *
28 * @see https://docs.joinmastodon.org/spec/activitypub/#featured
29 * @see https://docs.joinmastodon.org/spec/activitypub/#featuredTags
30 */
31 class Collection {
32 /**
33 * Initialize the class, registering WordPress hooks.
34 */
35 public static function init() {
36 self::register_routes();
37 }
38
39 /**
40 * Register routes.
41 */
42 public static function register_routes() {
43 \register_rest_route(
44 ACTIVITYPUB_REST_NAMESPACE,
45 '/(users|actors)/(?P<user_id>[\w\-\.]+)/collections/tags',
46 array(
47 array(
48 'methods' => WP_REST_Server::READABLE,
49 'callback' => array( self::class, 'tags_get' ),
50 'permission_callback' => '__return_true',
51 ),
52 )
53 );
54
55 \register_rest_route(
56 ACTIVITYPUB_REST_NAMESPACE,
57 '/(users|actors)/(?P<user_id>[\w\-\.]+)/collections/featured',
58 array(
59 array(
60 'methods' => WP_REST_Server::READABLE,
61 'callback' => array( self::class, 'featured_get' ),
62 'permission_callback' => '__return_true',
63 ),
64 )
65 );
66
67 \register_rest_route(
68 ACTIVITYPUB_REST_NAMESPACE,
69 '/collections/moderators',
70 array(
71 array(
72 'methods' => WP_REST_Server::READABLE,
73 'callback' => array( self::class, 'moderators_get' ),
74 'permission_callback' => '__return_true',
75 ),
76 )
77 );
78
79 \register_rest_route(
80 ACTIVITYPUB_REST_NAMESPACE,
81 '/(?P<type>[\w\-\.]+)s/(?P<id>[\w\-\.]+)/replies',
82 array(
83 array(
84 'methods' => WP_REST_Server::READABLE,
85 'callback' => array( self::class, 'replies_get' ),
86 'args' => self::request_parameters_for_replies(),
87 'permission_callback' => '__return_true',
88 ),
89 )
90 );
91 }
92
93 /**
94 * The endpoint for replies collections.
95 *
96 * @param \WP_REST_Request $request The request object.
97 *
98 * @return WP_REST_Response|\WP_Error The response object or WP_Error.
99 */
100 public static function replies_get( $request ) {
101 $type = $request->get_param( 'type' );
102 $id = (int) $request->get_param( 'id' );
103
104 // Get the WordPress object of that "owns" the requested replies.
105 switch ( $type ) {
106 case 'comment':
107 $wp_object = \get_comment( $id );
108 break;
109 case 'post':
110 default:
111 $wp_object = \get_post( $id );
112 break;
113 }
114
115 if ( ! isset( $wp_object ) || is_wp_error( $wp_object ) ) {
116 return new WP_Error(
117 'activitypub_replies_collection_does_not_exist',
118 \sprintf(
119 // translators: %s: The type (post, comment, etc.) for which no replies collection exists.
120 \__( 'No reply collection exists for the type %s.', 'activitypub' ),
121 $type
122 )
123 );
124 }
125
126 $page = (int) $request->get_param( 'page' );
127
128 // If the request parameter page is present get the CollectionPage otherwise the replies collection.
129 if ( isset( $page ) ) {
130 $response = Replies::get_collection_page( $wp_object, $page );
131 } else {
132 $response = Replies::get_collection( $wp_object );
133 }
134
135 if ( is_wp_error( $response ) ) {
136 return $response;
137 }
138
139 // Add ActivityPub Context.
140 $response = array_merge(
141 array( '@context' => Base_Object::JSON_LD_CONTEXT ),
142 $response
143 );
144
145 return new WP_REST_Response( $response, 200 );
146 }
147
148 /**
149 * The Featured Tags endpoint
150 *
151 * @param \WP_REST_Request $request The request object.
152 *
153 * @return WP_REST_Response|\WP_Error The response object or WP_Error.
154 */
155 public static function tags_get( $request ) {
156 $user_id = $request->get_param( 'user_id' );
157 $user = User_Collection::get_by_various( $user_id );
158
159 if ( is_wp_error( $user ) ) {
160 return $user;
161 }
162
163 $number = 4;
164
165 $tags = \get_terms(
166 array(
167 'taxonomy' => 'post_tag',
168 'orderby' => 'count',
169 'order' => 'DESC',
170 'number' => $number,
171 )
172 );
173
174 if ( is_wp_error( $tags ) ) {
175 $tags = array();
176 }
177
178 $response = array(
179 '@context' => Base_Object::JSON_LD_CONTEXT,
180 'id' => get_rest_url_by_path( sprintf( 'actors/%d/collections/tags', $user->get__id() ) ),
181 'type' => 'Collection',
182 'totalItems' => is_countable( $tags ) ? count( $tags ) : 0,
183 'items' => array(),
184 );
185
186 foreach ( $tags as $tag ) {
187 $response['items'][] = array(
188 'type' => 'Hashtag',
189 'href' => \esc_url( \get_tag_link( $tag ) ),
190 'name' => esc_hashtag( $tag->name ),
191 );
192 }
193
194 $rest_response = new WP_REST_Response( $response, 200 );
195 $rest_response->header( 'Content-Type', 'application/activity+json; charset=' . get_option( 'blog_charset' ) );
196
197 return $rest_response;
198 }
199
200 /**
201 * Featured posts endpoint
202 *
203 * @param \WP_REST_Request $request The request object.
204 *
205 * @return WP_REST_Response|\WP_Error The response object or WP_Error.
206 */
207 public static function featured_get( $request ) {
208 $user_id = $request->get_param( 'user_id' );
209 $user = User_Collection::get_by_various( $user_id );
210
211 if ( is_wp_error( $user ) ) {
212 return $user;
213 }
214
215 $sticky_posts = \get_option( 'sticky_posts' );
216
217 if ( ! is_single_user() && User_Collection::BLOG_USER_ID === $user->get__id() ) {
218 $posts = array();
219 } elseif ( $sticky_posts && is_array( $sticky_posts ) ) {
220 $args = array(
221 'post__in' => $sticky_posts,
222 'ignore_sticky_posts' => 1,
223 'orderby' => 'date',
224 'order' => 'DESC',
225 );
226
227 if ( $user->get__id() > 0 ) {
228 $args['author'] = $user->get__id();
229 }
230
231 $posts = \get_posts( $args );
232 } else {
233 $posts = array();
234 }
235
236 $response = array(
237 '@context' => Base_Object::JSON_LD_CONTEXT,
238 'id' => get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $user_id ) ),
239 'type' => 'OrderedCollection',
240 'totalItems' => is_countable( $posts ) ? count( $posts ) : 0,
241 'orderedItems' => array(),
242 );
243
244 foreach ( $posts as $post ) {
245 $transformer = Factory::get_transformer( $post );
246
247 if ( \is_wp_error( $transformer ) ) {
248 continue;
249 }
250
251 $response['orderedItems'][] = $transformer->to_object()->to_array( false );
252 }
253
254 $rest_response = new WP_REST_Response( $response, 200 );
255 $rest_response->header( 'Content-Type', 'application/activity+json; charset=' . get_option( 'blog_charset' ) );
256
257 return $rest_response;
258 }
259
260 /**
261 * Moderators endpoint.
262 *
263 * @return WP_REST_Response The response object.
264 */
265 public static function moderators_get() {
266 $response = array(
267 '@context' => Actor::JSON_LD_CONTEXT,
268 'id' => get_rest_url_by_path( 'collections/moderators' ),
269 'type' => 'OrderedCollection',
270 'orderedItems' => array(),
271 );
272
273 $users = User_Collection::get_collection();
274
275 foreach ( $users as $user ) {
276 $response['orderedItems'][] = $user->get_id();
277 }
278
279 $rest_response = new WP_REST_Response( $response, 200 );
280 $rest_response->header( 'Content-Type', 'application/activity+json; charset=' . get_option( 'blog_charset' ) );
281
282 return $rest_response;
283 }
284
285 /**
286 * The supported parameters.
287 *
288 * @return array list of parameters.
289 */
290 public static function request_parameters_for_replies() {
291 $params = array();
292
293 $params['type'] = array(
294 'required' => true,
295 'type' => 'string',
296 'enum' => array( 'post', 'comment' ),
297 );
298
299 $params['id'] = array(
300 'required' => true,
301 'type' => 'string',
302 'sanitize_callback' => 'sanitize_text_field',
303 );
304
305 return $params;
306 }
307 }
308