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
← All changes | includes/model/class-user.php +199 -91 2.0.05.3.1 View file →
@@ -1,16 +1,28 @@
1 1 <?php
2 +/**
3 + * User model file.
4 + *
5 + * @package Activitypub
6 + */
7 +
2 8 namespace Activitypub\Model;
3 9
4 -use WP_Query;
5 10 use WP_Error;
6 11 use Activitypub\Signature;
7 -use Activitypub\Collection\Users;
8 12 use Activitypub\Activity\Actor;
13 +use Activitypub\Collection\Extra_Fields;
9 14
15 +use function Activitypub\is_blog_public;
10 16 use function Activitypub\is_user_disabled;
11 17 use function Activitypub\get_rest_url_by_path;
18 +use function Activitypub\get_attribution_domains;
12 19
20 +/**
21 + * User class.
22 + *
23 + * @method int get__id() Gets the WordPress user ID.
24 + */
13 25 class User extends Actor {
14 26 /**
15 27 * The local User-ID (WP_User).
16 28 *
@@ -22,60 +34,60 @@
22 34 * The Featured-Posts.
23 35 *
24 36 * @see https://docs.joinmastodon.org/spec/activitypub/#featured
25 37 *
38 + * @context {
39 + * "@id": "http://joinmastodon.org/ns#featured",
40 + * "@type": "@id"
41 + * }
42 + *
26 43 * @var string
27 44 */
28 45 protected $featured;
29 46
30 47 /**
31 - * Moderators endpoint.
48 + * Whether the User is discoverable.
32 49 *
33 - * @see https://join-lemmy.org/docs/contributors/05-federation.html
50 + * @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
34 51 *
35 - * @var string
36 - */
37 - protected $moderators;
38 -
39 - /**
40 - * The User-Type
52 + * @context http://joinmastodon.org/ns#discoverable
41 53 *
42 - * @var string
54 + * @var boolean
43 55 */
44 - protected $type = 'Person';
56 + protected $discoverable = true;
45 57
46 58 /**
47 - * If the User is discoverable.
59 + * Whether the User is indexable.
48 60 *
49 - * @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
61 + * @context http://joinmastodon.org/ns#indexable
50 62 *
51 63 * @var boolean
52 64 */
53 - protected $discoverable = true;
65 + protected $indexable;
54 66
55 67 /**
56 - * If the User is indexable.
68 + * The WebFinger Resource.
57 69 *
58 - * @var boolean
70 + * @var string
59 71 */
60 - protected $indexable;
72 + protected $webfinger;
61 73
62 74 /**
63 - * The WebFinger Resource.
75 + * The type of the object.
64 76 *
65 - * @var string<url>
77 + * @return string The type of the object.
66 78 */
67 - protected $webfinger;
79 + public function get_type() {
80 + return 'Person';
81 + }
68 82
69 83 /**
70 - * Restrict posting to mods
84 + * Generate a User object from a WP_User.
71 85 *
72 - * @see https://join-lemmy.org/docs/contributors/05-federation.html
86 + * @param int $user_id The user ID.
73 87 *
74 - * @var boolean
88 + * @return WP_Error|User The User object or WP_Error if user not found.
75 89 */
76 - protected $posting_restricted_to_mods = null;
77 -
78 90 public static function from_wp_user( $user_id ) {
79 91 if ( is_user_disabled( $user_id ) ) {
80 92 return new WP_Error(
81 93 'activitypub_user_not_found',
@@ -83,9 +95,9 @@
83 95 array( 'status' => 404 )
84 96 );
85 97 }
86 98
87 - $object = new static();
99 + $object = new static();
88 100 $object->_id = $user_id;
89 101
90 102 return $object;
91 103 }
@@ -90,32 +102,38 @@
90 102 return $object;
91 103 }
92 104
93 105 /**
94 - * Get the User-ID.
106 + * Get the user ID.
95 107 *
96 - * @return string The User-ID.
108 + * @return string The user ID.
97 109 */
98 110 public function get_id() {
99 - return $this->get_url();
111 + $permalink = \get_user_option( 'activitypub_use_permalink_as_id', $this->_id );
112 +
113 + if ( '1' === $permalink ) {
114 + return $this->get_url();
115 + }
116 +
117 + return \add_query_arg( 'author', $this->_id, \trailingslashit( \home_url() ) );
100 118 }
101 119
102 120 /**
103 - * Get the User-Name.
121 + * Get the Username.
104 122 *
105 - * @return string The User-Name.
123 + * @return string The Username.
106 124 */
107 125 public function get_name() {
108 - return \esc_attr( \get_the_author_meta( 'display_name', $this->_id ) );
126 + return \get_the_author_meta( 'display_name', $this->_id );
109 127 }
110 128
111 129 /**
112 - * Get the User-Description.
130 + * Get the User description.
113 131 *
114 - * @return string The User-Description.
132 + * @return string The User description.
115 133 */
116 134 public function get_summary() {
117 - $description = get_user_meta( $this->_id, 'activitypub_user_description', true );
135 + $description = get_user_option( 'activitypub_description', $this->_id );
118 136 if ( empty( $description ) ) {
119 137 $description = get_user_meta( $this->_id, 'description', true );
120 138 }
121 139 return \wpautop( \wp_kses( $description, 'default' ) );
@@ -121,11 +139,11 @@
121 139 return \wpautop( \wp_kses( $description, 'default' ) );
122 140 }
123 141
124 142 /**
125 - * Get the User-Url.
143 + * Get the User url.
126 144 *
127 - * @return string The User-Url.
145 + * @return string The User url.
128 146 */
129 147 public function get_url() {
130 148 return \esc_url( \get_author_posts_url( $this->_id ) );
131 149 }
@@ -130,21 +148,39 @@
130 148 return \esc_url( \get_author_posts_url( $this->_id ) );
131 149 }
132 150
133 151 /**
134 - * Returns the User-URL with @-Prefix for the username.
152 + * Returns the User URL with @-Prefix for the username.
135 153 *
136 - * @return string The User-URL with @-Prefix for the username.
154 + * @return string The User URL with @-Prefix for the username.
137 155 */
138 156 public function get_alternate_url() {
139 157 return \esc_url( \trailingslashit( get_home_url() ) . '@' . $this->get_preferred_username() );
140 158 }
141 159
160 + /**
161 + * Get the preferred username.
162 + *
163 + * @return string The preferred username.
164 + */
142 165 public function get_preferred_username() {
143 - return \esc_attr( \get_the_author_meta( 'login', $this->_id ) );
166 + return \get_the_author_meta( 'login', $this->_id );
144 167 }
145 168
169 + /**
170 + * Get the User icon.
171 + *
172 + * @return array The User icon.
173 + */
146 174 public function get_icon() {
175 + $icon = \get_user_option( 'activitypub_icon', $this->_id );
176 + if ( wp_attachment_is_image( $icon ) ) {
177 + return array(
178 + 'type' => 'Image',
179 + 'url' => esc_url( wp_get_attachment_url( $icon ) ),
180 + );
181 + }
182 +
147 183 $icon = \esc_url(
148 184 \get_avatar_url(
149 185 $this->_id,
150 186 array( 'size' => 120 )
@@ -156,14 +192,29 @@
156 192 'url' => $icon,
157 193 );
158 194 }
159 195
196 + /**
197 + * Returns the header image.
198 + *
199 + * @return array|null The header image.
200 + */
160 201 public function get_image() {
161 - if ( \has_header_image() ) {
162 - $image = \esc_url( \get_header_image() );
202 + $header_image = get_user_option( 'activitypub_header_image', $this->_id );
203 + $image_url = null;
204 +
205 + if ( ! $header_image && \has_header_image() ) {
206 + $image_url = \get_header_image();
207 + }
208 +
209 + if ( $header_image ) {
210 + $image_url = \wp_get_attachment_url( $header_image );
211 + }
212 +
213 + if ( $image_url ) {
163 214 return array(
164 215 'type' => 'Image',
165 - 'url' => $image,
216 + 'url' => esc_url( $image_url ),
166 217 );
167 218 }
168 219
169 220 return null;
@@ -168,16 +219,26 @@
168 219
169 220 return null;
170 221 }
171 222
223 + /**
224 + * Returns the date the user was created.
225 + *
226 + * @return false|string The date the user was created.
227 + */
172 228 public function get_published() {
173 229 return \gmdate( 'Y-m-d\TH:i:s\Z', \strtotime( \get_the_author_meta( 'registered', $this->_id ) ) );
174 230 }
175 231
232 + /**
233 + * Returns the public key.
234 + *
235 + * @return array The public key.
236 + */
176 237 public function get_public_key() {
177 238 return array(
178 - 'id' => $this->get_id() . '#main-key',
179 - 'owner' => $this->get_id(),
239 + 'id' => $this->get_id() . '#main-key',
240 + 'owner' => $this->get_id(),
180 241 'publicKeyPem' => Signature::get_public_key_for( $this->get__id() ),
181 242 );
182 243 }
183 244
@@ -186,9 +247,9 @@
186 247 *
187 248 * @return string The Inbox-Endpoint.
188 249 */
189 250 public function get_inbox() {
190 - return get_rest_url_by_path( sprintf( 'users/%d/inbox', $this->get__id() ) );
251 + return get_rest_url_by_path( sprintf( 'actors/%d/inbox', $this->get__id() ) );
191 252 }
192 253
193 254 /**
194 255 * Returns the Outbox-API-Endpoint.
@@ -195,9 +256,9 @@
195 256 *
196 257 * @return string The Outbox-Endpoint.
197 258 */
198 259 public function get_outbox() {
199 - return get_rest_url_by_path( sprintf( 'users/%d/outbox', $this->get__id() ) );
260 + return get_rest_url_by_path( sprintf( 'actors/%d/outbox', $this->get__id() ) );
200 261 }
201 262
202 263 /**
203 264 * Returns the Followers-API-Endpoint.
@@ -204,9 +265,9 @@
204 265 *
205 266 * @return string The Followers-Endpoint.
206 267 */
207 268 public function get_followers() {
208 - return get_rest_url_by_path( sprintf( 'users/%d/followers', $this->get__id() ) );
269 + return get_rest_url_by_path( sprintf( 'actors/%d/followers', $this->get__id() ) );
209 270 }
210 271
211 272 /**
212 273 * Returns the Following-API-Endpoint.
@@ -213,9 +274,9 @@
213 274 *
214 275 * @return string The Following-Endpoint.
215 276 */
216 277 public function get_following() {
217 - return get_rest_url_by_path( sprintf( 'users/%d/following', $this->get__id() ) );
278 + return get_rest_url_by_path( sprintf( 'actors/%d/following', $this->get__id() ) );
218 279 }
219 280
220 281 /**
221 282 * Returns the Featured-API-Endpoint.
@@ -222,11 +283,16 @@
222 283 *
223 284 * @return string The Featured-Endpoint.
224 285 */
225 286 public function get_featured() {
226 - return get_rest_url_by_path( sprintf( 'users/%d/collections/featured', $this->get__id() ) );
287 + return get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $this->get__id() ) );
227 288 }
228 289
290 + /**
291 + * Returns the endpoints.
292 + *
293 + * @return array|null The endpoints.
294 + */
229 295 public function get_endpoints() {
230 296 $endpoints = null;
231 297
232 298 if ( ACTIVITYPUB_SHARED_INBOX_FEATURE ) {
@@ -243,43 +309,10 @@
243 309 *
244 310 * @return array The extended User-Output.
245 311 */
246 312 public function get_attachment() {
247 - $array = array();
248 -
249 - $array[] = array(
250 - 'type' => 'PropertyValue',
251 - 'name' => \__( 'Blog', 'activitypub' ),
252 - 'value' => \html_entity_decode(
253 - '<a rel="me" title="' . \esc_attr( \home_url( '/' ) ) . '" target="_blank" href="' . \home_url( '/' ) . '">' . \wp_parse_url( \home_url( '/' ), \PHP_URL_HOST ) . '</a>',
254 - \ENT_QUOTES,
255 - 'UTF-8'
256 - ),
257 - );
258 -
259 - $array[] = array(
260 - 'type' => 'PropertyValue',
261 - 'name' => \__( 'Profile', 'activitypub' ),
262 - 'value' => \html_entity_decode(
263 - '<a rel="me" title="' . \esc_attr( \get_author_posts_url( $this->get__id() ) ) . '" target="_blank" href="' . \get_author_posts_url( $this->get__id() ) . '">' . \wp_parse_url( \get_author_posts_url( $this->get__id() ), \PHP_URL_HOST ) . '</a>',
264 - \ENT_QUOTES,
265 - 'UTF-8'
266 - ),
267 - );
268 -
269 - if ( \get_the_author_meta( 'user_url', $this->get__id() ) ) {
270 - $array[] = array(
271 - 'type' => 'PropertyValue',
272 - 'name' => \__( 'Website', 'activitypub' ),
273 - 'value' => \html_entity_decode(
274 - '<a rel="me" title="' . \esc_attr( \get_the_author_meta( 'user_url', $this->get__id() ) ) . '" target="_blank" href="' . \get_the_author_meta( 'user_url', $this->get__id() ) . '">' . \wp_parse_url( \get_the_author_meta( 'user_url', $this->get__id() ), \PHP_URL_HOST ) . '</a>',
275 - \ENT_QUOTES,
276 - 'UTF-8'
277 - ),
278 - );
279 - }
280 -
281 - return $array;
313 + $extra_fields = Extra_Fields::get_actor_fields( $this->_id );
314 + return Extra_Fields::fields_to_attachments( $extra_fields );
282 315 }
283 316
284 317 /**
285 318 * Returns a user@domain type of identifier for the user.
@@ -289,28 +322,103 @@
289 322 public function get_webfinger() {
290 323 return $this->get_preferred_username() . '@' . \wp_parse_url( \home_url(), \PHP_URL_HOST );
291 324 }
292 325
293 - public function get_resource() {
294 - return $this->get_webfinger();
295 - }
296 -
326 + /**
327 + * Returns the canonical URL.
328 + *
329 + * @return string The canonical URL.
330 + */
297 331 public function get_canonical_url() {
298 332 return $this->get_url();
299 333 }
300 334
335 + /**
336 + * Returns the streams.
337 + *
338 + * @return null The streams.
339 + */
301 340 public function get_streams() {
302 341 return null;
303 342 }
304 343
344 + /**
345 + * Returns the tag.
346 + *
347 + * @return array The tag.
348 + */
305 349 public function get_tag() {
306 350 return array();
307 351 }
308 352
353 + /**
354 + * Returns the indexable state.
355 + *
356 + * @return bool Whether the user is indexable.
357 + */
309 358 public function get_indexable() {
310 - if ( \get_option( 'blog_public', 1 ) ) {
359 + if ( is_blog_public() ) {
311 360 return true;
312 361 } else {
313 362 return false;
314 363 }
364 + }
365 +
366 + /**
367 + * Update the username.
368 + *
369 + * @param string $value The new value.
370 + * @return int|WP_Error The updated user ID or WP_Error on failure.
371 + */
372 + public function update_name( $value ) {
373 + $userdata = array(
374 + 'ID' => $this->_id,
375 + 'display_name' => $value,
376 + );
377 + return \wp_update_user( $userdata );
378 + }
379 +
380 + /**
381 + * Update the User description.
382 + *
383 + * @param string $value The new value.
384 + * @return bool True if the attribute was updated, false otherwise.
385 + */
386 + public function update_summary( $value ) {
387 + return \update_user_option( $this->_id, 'activitypub_description', $value );
388 + }
389 +
390 + /**
391 + * Update the User icon.
392 + *
393 + * @param int $value The new value. Should be an attachment ID.
394 + * @return bool True if the attribute was updated, false otherwise.
395 + */
396 + public function update_icon( $value ) {
397 + if ( ! wp_attachment_is_image( $value ) ) {
398 + return false;
399 + }
400 + return update_user_option( $this->_id, 'activitypub_icon', $value );
401 + }
402 +
403 + /**
404 + * Update the User-Header-Image.
405 + *
406 + * @param int $value The new value. Should be an attachment ID.
407 + * @return bool True if the attribute was updated, false otherwise.
408 + */
409 + public function update_header( $value ) {
410 + if ( ! wp_attachment_is_image( $value ) ) {
411 + return false;
412 + }
413 + return \update_user_option( $this->_id, 'activitypub_header_image', $value );
414 + }
415 +
416 + /**
417 + * Returns the website hosts allowed to credit this blog.
418 + *
419 + * @return array|null The attribution domains or null if not found.
420 + */
421 + public function get_attribution_domains() {
422 + return get_attribution_domains();
315 423 }
316 424 }