PluginProbe
ActivityPub / 5.3.1
ActivityPub v5.3.1
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-collections-controller.php

class-collections-controller.php in ActivityPub 5.3.1, at includes/rest/class-collections-controller.php

270 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Collections_Controller file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Rest;
9
10 use Activitypub\Activity\Base_Object;
11 use Activitypub\Collection\Actors;
12 use Activitypub\Model\Application;
13 use Activitypub\Model\Blog;
14 use Activitypub\Model\User;
15 use Activitypub\Transformer\Factory;
16
17 use function Activitypub\esc_hashtag;
18 use function Activitypub\is_single_user;
19 use function Activitypub\get_rest_url_by_path;
20
21 /**
22 * Collections_Controller class.
23 *
24 * @author Matthias Pfefferle
25 *
26 * @see https://docs.joinmastodon.org/spec/activitypub/#featured
27 * @see https://docs.joinmastodon.org/spec/activitypub/#featuredTags
28 * @see https://www.w3.org/TR/activitypub/#collections
29 */
30 class Collections_Controller extends Actors_Controller {
31 /**
32 * Register routes.
33 */
34 public function register_routes() {
35 \register_rest_route(
36 $this->namespace,
37 '/' . $this->rest_base . '/collections/(?P<type>[\w\-\.]+)',
38 array(
39 'args' => array(
40 'user_id' => array(
41 'description' => 'The user ID or username.',
42 'type' => 'string',
43 'required' => true,
44 ),
45 'type' => array(
46 'description' => 'The type of collection to query.',
47 'type' => 'string',
48 'enum' => array( 'tags', 'featured' ),
49 'required' => true,
50 ),
51 ),
52 array(
53 'methods' => \WP_REST_Server::READABLE,
54 'callback' => array( $this, 'get_items' ),
55 'permission_callback' => '__return_true',
56 ),
57 'schema' => array( $this, 'get_item_schema' ),
58 )
59 );
60 }
61
62 /**
63 * Retrieves a collection of featured tags.
64 *
65 * @param \WP_REST_Request $request The request object.
66 *
67 * @return \WP_REST_Response|\WP_Error Response object or WP_Error object.
68 */
69 public function get_items( $request ) {
70 $user_id = $request->get_param( 'user_id' );
71 $user = Actors::get_by_various( $user_id );
72
73 if ( \is_wp_error( $user ) ) {
74 return $user;
75 }
76
77 switch ( $request->get_param( 'type' ) ) {
78 case 'tags':
79 $response = $this->get_tags( $request, $user );
80 break;
81
82 case 'featured':
83 $response = $this->get_featured( $request, $user );
84 break;
85
86 default:
87 $response = new \WP_Error( 'rest_unknown_collection_type', 'Unknown collection type.', array( 'status' => 404 ) );
88 }
89
90 $response = \rest_ensure_response( $response );
91 $response->header( 'Content-Type', 'application/activity+json; charset=' . \get_option( 'blog_charset' ) );
92
93 return $response;
94 }
95
96 /**
97 * Retrieves a collection of featured tags.
98 *
99 * @param \WP_REST_Request $request The request object.
100 * @param User|Blog|Application $user Actor.
101 *
102 * @return array Collection of featured tags.
103 */
104 public function get_tags( $request, $user ) {
105 $tags = \get_terms(
106 array(
107 'taxonomy' => 'post_tag',
108 'orderby' => 'count',
109 'order' => 'DESC',
110 'number' => 4,
111 )
112 );
113
114 if ( \is_wp_error( $tags ) ) {
115 $tags = array();
116 }
117
118 $response = array(
119 '@context' => Base_Object::JSON_LD_CONTEXT,
120 'id' => get_rest_url_by_path( sprintf( 'actors/%d/collections/tags', $user->get__id() ) ),
121 'type' => 'Collection',
122 'totalItems' => \is_countable( $tags ) ? \count( $tags ) : 0,
123 'items' => array(),
124 );
125
126 foreach ( $tags as $tag ) {
127 $response['items'][] = array(
128 'type' => 'Hashtag',
129 'href' => \esc_url( \get_tag_link( $tag ) ),
130 'name' => esc_hashtag( $tag->name ),
131 );
132 }
133
134 return $response;
135 }
136
137 /**
138 * Retrieves a collection of featured posts.
139 *
140 * @param \WP_REST_Request $request The request object.
141 * @param User|Blog|Application $user Actor.
142 *
143 * @return array Collection of featured posts.
144 */
145 public function get_featured( $request, $user ) {
146 $posts = array();
147
148 if ( is_single_user() || Actors::BLOG_USER_ID !== $user->get__id() ) {
149 $sticky_posts = \get_option( 'sticky_posts' );
150
151 if ( $sticky_posts && is_array( $sticky_posts ) ) {
152 // Only show public posts.
153 $args = array(
154 'post__in' => $sticky_posts,
155 'ignore_sticky_posts' => 1,
156 'orderby' => 'date',
157 'order' => 'DESC',
158 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
159 'meta_query' => array(
160 array(
161 'key' => 'activitypub_content_visibility',
162 'compare' => 'NOT EXISTS',
163 ),
164 ),
165 );
166
167 if ( $user->get__id() > 0 ) {
168 $args['author'] = $user->get__id();
169 }
170
171 $posts = \get_posts( $args );
172 }
173 }
174
175 $response = array(
176 '@context' => Base_Object::JSON_LD_CONTEXT,
177 'id' => get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $request->get_param( 'user_id' ) ) ),
178 'type' => 'OrderedCollection',
179 'totalItems' => \is_countable( $posts ) ? \count( $posts ) : 0,
180 'orderedItems' => array(),
181 );
182
183 foreach ( $posts as $post ) {
184 $transformer = Factory::get_transformer( $post );
185
186 if ( \is_wp_error( $transformer ) ) {
187 continue;
188 }
189
190 $response['orderedItems'][] = $transformer->to_object()->to_array( false );
191 }
192
193 return $response;
194 }
195
196 /**
197 * Retrieves the schema for the Collections endpoint.
198 *
199 * @return array Schema data.
200 */
201 public function get_item_schema() {
202 if ( $this->schema ) {
203 return $this->add_additional_fields_schema( $this->schema );
204 }
205
206 $schema = array(
207 '$schema' => 'http://json-schema.org/draft-04/schema#',
208 'title' => 'featured',
209 'type' => 'object',
210 'properties' => array(
211 '@context' => array(
212 'type' => 'array',
213 'items' => array(
214 'type' => array( 'string', 'object' ),
215 ),
216 'required' => true,
217 ),
218 'id' => array(
219 'type' => 'string',
220 'format' => 'uri',
221 'required' => true,
222 ),
223 'type' => array(
224 'type' => 'string',
225 'enum' => array( 'Collection', 'OrderedCollection' ),
226 'required' => true,
227 ),
228 'totalItems' => array(
229 'type' => 'integer',
230 'required' => true,
231 ),
232 'oneOf' => array(
233 'orderedItems' => array(
234 'type' => 'array',
235 'items' => array(
236 'type' => 'object',
237 ),
238 ),
239 'items' => array(
240 'type' => 'array',
241 'items' => array(
242 'type' => 'object',
243 'properties' => array(
244 'type' => array(
245 'type' => 'string',
246 'enum' => array( 'Hashtag' ),
247 'required' => true,
248 ),
249 'href' => array(
250 'type' => 'string',
251 'format' => 'uri',
252 'required' => true,
253 ),
254 'name' => array(
255 'type' => 'string',
256 'required' => true,
257 ),
258 ),
259 ),
260 ),
261 ),
262 ),
263 );
264
265 $this->schema = $schema;
266
267 return $this->add_additional_fields_schema( $this->schema );
268 }
269 }
270