PluginProbe
ActivityPub / 9.0.0
ActivityPub v9.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 / model / class-user.php

class-user.php in ActivityPub 9.0.0, at includes/model/class-user.php

487 lines 10.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * User model file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Model;
9
10 use Activitypub\Activity\Actor;
11 use Activitypub\Collection\Actors;
12 use Activitypub\Collection\Extra_Fields;
13
14 use function Activitypub\get_attribution_domains;
15 use function Activitypub\get_rest_url_by_path;
16 use function Activitypub\is_blog_public;
17 use function Activitypub\user_can_activitypub;
18
19 /**
20 * User class.
21 *
22 * @method int get__id() Gets the WordPress user ID.
23 */
24 class User extends Actor {
25 /**
26 * The local User-ID (WP_User).
27 *
28 * @var int
29 */
30 protected $_id; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
31
32 /**
33 * Whether the User is discoverable.
34 *
35 * @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
36 *
37 * @context http://joinmastodon.org/ns#discoverable
38 *
39 * @var boolean
40 */
41 protected $discoverable = true;
42
43 /**
44 * The generator of the object.
45 *
46 * @see https://www.w3.org/TR/activitypub/#generator
47 * @see https://codeberg.org/fediverse/fep/src/branch/main/fep/844e/fep-844e.md#discovery-through-an-actor
48 *
49 * @var array
50 */
51 protected $generator = array(
52 'type' => 'Application',
53 'implements' => array(
54 array(
55 'href' => 'https://datatracker.ietf.org/doc/html/rfc9421',
56 'name' => 'RFC-9421: HTTP Message Signatures',
57 ),
58 ),
59 );
60
61 /**
62 * Constructor.
63 *
64 * @param int $user_id Optional. The WordPress user ID. Default null.
65 */
66 public function __construct( $user_id = null ) {
67 if ( $user_id ) {
68 $this->_id = $user_id;
69
70 /**
71 * Fires when a model actor is constructed.
72 *
73 * @param User $this The User object.
74 */
75 \do_action( 'activitypub_construct_model_actor', $this );
76 }
77 }
78
79 /**
80 * The type of the object.
81 *
82 * @return string The type of the object.
83 */
84 public function get_type() {
85 return 'Person';
86 }
87
88 /**
89 * Generate a User object from a WP_User.
90 *
91 * @param int $user_id The user ID.
92 *
93 * @return \WP_Error|User The User object or \WP_Error if user not found.
94 */
95 public static function from_wp_user( $user_id ) {
96 if ( ! user_can_activitypub( $user_id ) ) {
97 return new \WP_Error(
98 'activitypub_user_not_found',
99 \__( 'User not found', 'activitypub' ),
100 array( 'status' => 404 )
101 );
102 }
103
104 return new static( $user_id );
105 }
106
107 /**
108 * Get the user ID.
109 *
110 * @return string The user ID.
111 */
112 public function get_id() {
113 $id = parent::get_id();
114
115 if ( $id ) {
116 return $id;
117 }
118
119 $permalink = \get_user_option( 'activitypub_use_permalink_as_id', $this->_id );
120
121 if ( '1' === $permalink ) {
122 return $this->get_url();
123 }
124
125 return \add_query_arg( 'author', $this->_id, \home_url( '/' ) );
126 }
127
128 /**
129 * Get the Username.
130 *
131 * @return string The Username.
132 */
133 public function get_name() {
134 return \get_the_author_meta( 'display_name', $this->_id );
135 }
136
137 /**
138 * Get the User description.
139 *
140 * @return string The User description.
141 */
142 public function get_summary() {
143 $description = get_user_option( 'activitypub_description', $this->_id );
144 if ( empty( $description ) ) {
145 $description = get_user_meta( $this->_id, 'description', true );
146 }
147 return \wpautop( \wp_kses( $description, 'default' ) );
148 }
149
150 /**
151 * Get the User url.
152 *
153 * @return string The User url.
154 */
155 public function get_url() {
156 return \esc_url( \get_author_posts_url( $this->_id ) );
157 }
158
159 /**
160 * Returns the User URL with @-Prefix for the username.
161 *
162 * @return string The User URL with @-Prefix for the username.
163 */
164 public function get_alternate_url() {
165 return \esc_url( \trailingslashit( get_home_url() ) . '@' . $this->get_preferred_username() );
166 }
167
168 /**
169 * Get the preferred username.
170 *
171 * @return string The preferred username.
172 */
173 public function get_preferred_username() {
174 $login = \get_the_author_meta( 'login', $this->_id );
175
176 // Handle cases where login is an email address (e.g., from Site Kit Google login).
177 if ( \filter_var( $login, FILTER_VALIDATE_EMAIL ) ) {
178 $login = \get_the_author_meta( 'user_nicename', $this->_id );
179 }
180
181 return $login;
182 }
183
184 /**
185 * Get the User icon.
186 *
187 * @return string[] The User icon.
188 */
189 public function get_icon() {
190 $icon = \get_user_option( 'activitypub_icon', $this->_id );
191 if ( false !== $icon && wp_attachment_is_image( $icon ) ) {
192 return array(
193 'type' => 'Image',
194 'url' => esc_url( wp_get_attachment_url( $icon ) ),
195 );
196 }
197
198 $icon = \esc_url(
199 \get_avatar_url(
200 $this->_id,
201 array( 'size' => 120 )
202 )
203 );
204
205 return array(
206 'type' => 'Image',
207 'url' => $icon,
208 );
209 }
210
211 /**
212 * Returns the header image.
213 *
214 * @return string[]|null The header image.
215 */
216 public function get_image() {
217 $header_image = get_user_option( 'activitypub_header_image', $this->_id );
218 $image_url = null;
219
220 if ( ! $header_image && \has_header_image() ) {
221 $image_url = \get_header_image();
222 }
223
224 if ( $header_image ) {
225 $image_url = \wp_get_attachment_url( $header_image );
226 }
227
228 if ( $image_url ) {
229 return array(
230 'type' => 'Image',
231 'url' => esc_url( $image_url ),
232 );
233 }
234
235 return null;
236 }
237
238 /**
239 * Returns the date the user was created.
240 *
241 * @return false|string The date the user was created.
242 */
243 public function get_published() {
244 return \gmdate( ACTIVITYPUB_DATE_TIME_RFC3339, \strtotime( \get_the_author_meta( 'registered', $this->_id ) ) );
245 }
246
247 /**
248 * Returns the public key.
249 *
250 * @return string[] The public key.
251 */
252 public function get_public_key() {
253 return array(
254 'id' => $this->get_id() . '#main-key',
255 'owner' => $this->get_id(),
256 'publicKeyPem' => Actors::get_public_key( $this->get__id() ),
257 );
258 }
259
260 /**
261 * Returns the Inbox-API-Endpoint.
262 *
263 * @return string The Inbox-Endpoint.
264 */
265 public function get_inbox() {
266 return get_rest_url_by_path( sprintf( 'actors/%d/inbox', $this->get__id() ) );
267 }
268
269 /**
270 * Returns the Outbox-API-Endpoint.
271 *
272 * @return string The Outbox-Endpoint.
273 */
274 public function get_outbox() {
275 return get_rest_url_by_path( sprintf( 'actors/%d/outbox', $this->get__id() ) );
276 }
277
278 /**
279 * Returns the Followers-API-Endpoint.
280 *
281 * @return string The Followers-Endpoint.
282 */
283 public function get_followers() {
284 return get_rest_url_by_path( sprintf( 'actors/%d/followers', $this->get__id() ) );
285 }
286
287 /**
288 * Returns the Following-API-Endpoint.
289 *
290 * @return string The Following-Endpoint.
291 */
292 public function get_following() {
293 return get_rest_url_by_path( sprintf( 'actors/%d/following', $this->get__id() ) );
294 }
295
296 /**
297 * Returns the Liked API endpoint.
298 *
299 * @since 8.1.0
300 *
301 * @return string The Liked endpoint.
302 */
303 public function get_liked() {
304 return get_rest_url_by_path( sprintf( 'actors/%d/liked', $this->get__id() ) );
305 }
306
307 /**
308 * Returns the Featured-API-Endpoint.
309 *
310 * @return string The Featured-Endpoint.
311 */
312 public function get_featured() {
313 return get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $this->get__id() ) );
314 }
315
316 /**
317 * Returns the Featured-Tags-API-Endpoint.
318 *
319 * @return string The Featured-Tags-Endpoint.
320 */
321 public function get_featured_tags() {
322 return get_rest_url_by_path( sprintf( 'actors/%d/collections/tags', $this->get__id() ) );
323 }
324
325 /**
326 * Returns the endpoints.
327 *
328 * @return string[]|null The endpoints.
329 */
330 public function get_endpoints() {
331 return array(
332 'sharedInbox' => get_rest_url_by_path( 'inbox' ),
333 'oauthAuthorizationEndpoint' => get_rest_url_by_path( 'oauth/authorize' ),
334 'oauthTokenEndpoint' => get_rest_url_by_path( 'oauth/token' ),
335 'oauthRegistrationEndpoint' => get_rest_url_by_path( 'oauth/clients' ),
336 'proxyUrl' => get_rest_url_by_path( 'proxy' ),
337 'proxyEventStream' => get_rest_url_by_path( 'proxy/stream' ),
338 );
339 }
340
341 /**
342 * Extend the User-Output with Attachments.
343 *
344 * @return array The extended User-Output.
345 */
346 public function get_attachment() {
347 $extra_fields = Extra_Fields::get_actor_fields( $this->_id );
348 return Extra_Fields::fields_to_attachments( $extra_fields );
349 }
350
351 /**
352 * Returns a user@domain type of identifier for the user.
353 *
354 * @return string The Webfinger-Identifier.
355 */
356 public function get_webfinger() {
357 return $this->get_preferred_username() . '@' . \wp_parse_url( \home_url(), \PHP_URL_HOST );
358 }
359
360 /**
361 * Returns the canonical URL.
362 *
363 * @return string The canonical URL.
364 */
365 public function get_canonical_url() {
366 return $this->get_url();
367 }
368
369 /**
370 * Returns the streams.
371 *
372 * @return null The streams.
373 */
374 public function get_streams() {
375 return null;
376 }
377
378 /**
379 * Returns the tag.
380 *
381 * @return array The tag.
382 */
383 public function get_tag() {
384 return array();
385 }
386
387 /**
388 * Returns the indexable state.
389 *
390 * @return bool Whether the user is indexable.
391 */
392 public function get_indexable() {
393 if ( is_blog_public() ) {
394 return true;
395 } else {
396 return false;
397 }
398 }
399
400 /**
401 * Update the username.
402 *
403 * @param string $value The new value.
404 * @return int|\WP_Error The updated user ID or \WP_Error on failure.
405 */
406 public function update_name( $value ) {
407 $userdata = array(
408 'ID' => $this->_id,
409 'display_name' => $value,
410 );
411 return \wp_update_user( $userdata );
412 }
413
414 /**
415 * Update the User description.
416 *
417 * @param string $value The new value.
418 * @return bool True if the attribute was updated, false otherwise.
419 */
420 public function update_summary( $value ) {
421 return \update_user_option( $this->_id, 'activitypub_description', $value );
422 }
423
424 /**
425 * Update the User icon.
426 *
427 * @param int $value The new value. Should be an attachment ID.
428 * @return bool True if the attribute was updated, false otherwise.
429 */
430 public function update_icon( $value ) {
431 if ( ! wp_attachment_is_image( $value ) ) {
432 return false;
433 }
434 return update_user_option( $this->_id, 'activitypub_icon', $value );
435 }
436
437 /**
438 * Update the User-Header-Image.
439 *
440 * @param int $value The new value. Should be an attachment ID.
441 * @return bool True if the attribute was updated, false otherwise.
442 */
443 public function update_header( $value ) {
444 if ( ! wp_attachment_is_image( $value ) ) {
445 return false;
446 }
447 return \update_user_option( $this->_id, 'activitypub_header_image', $value );
448 }
449
450 /**
451 * Returns the website hosts allowed to credit this blog.
452 *
453 * @return string[]|null The attribution domains or null if not found.
454 */
455 public function get_attribution_domains() {
456 return get_attribution_domains();
457 }
458
459 /**
460 * Returns the alsoKnownAs.
461 *
462 * @return string[] The alsoKnownAs.
463 */
464 public function get_also_known_as() {
465 $also_known_as = array(
466 \add_query_arg( 'author', $this->_id, \home_url( '/' ) ),
467 $this->get_url(),
468 $this->get_alternate_url(),
469 );
470
471 $also_known_as = array_merge( $also_known_as, \get_user_option( 'activitypub_also_known_as', $this->_id ) ?: array() );
472
473 return array_unique( $also_known_as );
474 }
475
476 /**
477 * Returns the movedTo.
478 *
479 * @return string The movedTo.
480 */
481 public function get_moved_to() {
482 $moved_to = \get_user_option( 'activitypub_moved_to', $this->_id );
483
484 return $moved_to && $moved_to !== $this->get_id() ? $moved_to : null;
485 }
486 }
487