PluginProbe
ActivityPub / 7.8.0
ActivityPub v7.8.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 7.8.0, at includes/model/class-user.php

471 lines 10.3 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 Featured-API-Endpoint.
298 *
299 * @return string The Featured-Endpoint.
300 */
301 public function get_featured() {
302 return get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $this->get__id() ) );
303 }
304
305 /**
306 * Returns the Featured-Tags-API-Endpoint.
307 *
308 * @return string The Featured-Tags-Endpoint.
309 */
310 public function get_featured_tags() {
311 return get_rest_url_by_path( sprintf( 'actors/%d/collections/tags', $this->get__id() ) );
312 }
313
314 /**
315 * Returns the endpoints.
316 *
317 * @return string[]|null The endpoints.
318 */
319 public function get_endpoints() {
320 return array(
321 'sharedInbox' => get_rest_url_by_path( 'inbox' ),
322 );
323 }
324
325 /**
326 * Extend the User-Output with Attachments.
327 *
328 * @return array The extended User-Output.
329 */
330 public function get_attachment() {
331 $extra_fields = Extra_Fields::get_actor_fields( $this->_id );
332 return Extra_Fields::fields_to_attachments( $extra_fields );
333 }
334
335 /**
336 * Returns a user@domain type of identifier for the user.
337 *
338 * @return string The Webfinger-Identifier.
339 */
340 public function get_webfinger() {
341 return $this->get_preferred_username() . '@' . \wp_parse_url( \home_url(), \PHP_URL_HOST );
342 }
343
344 /**
345 * Returns the canonical URL.
346 *
347 * @return string The canonical URL.
348 */
349 public function get_canonical_url() {
350 return $this->get_url();
351 }
352
353 /**
354 * Returns the streams.
355 *
356 * @return null The streams.
357 */
358 public function get_streams() {
359 return null;
360 }
361
362 /**
363 * Returns the tag.
364 *
365 * @return array The tag.
366 */
367 public function get_tag() {
368 return array();
369 }
370
371 /**
372 * Returns the indexable state.
373 *
374 * @return bool Whether the user is indexable.
375 */
376 public function get_indexable() {
377 if ( is_blog_public() ) {
378 return true;
379 } else {
380 return false;
381 }
382 }
383
384 /**
385 * Update the username.
386 *
387 * @param string $value The new value.
388 * @return int|\WP_Error The updated user ID or \WP_Error on failure.
389 */
390 public function update_name( $value ) {
391 $userdata = array(
392 'ID' => $this->_id,
393 'display_name' => $value,
394 );
395 return \wp_update_user( $userdata );
396 }
397
398 /**
399 * Update the User description.
400 *
401 * @param string $value The new value.
402 * @return bool True if the attribute was updated, false otherwise.
403 */
404 public function update_summary( $value ) {
405 return \update_user_option( $this->_id, 'activitypub_description', $value );
406 }
407
408 /**
409 * Update the User icon.
410 *
411 * @param int $value The new value. Should be an attachment ID.
412 * @return bool True if the attribute was updated, false otherwise.
413 */
414 public function update_icon( $value ) {
415 if ( ! wp_attachment_is_image( $value ) ) {
416 return false;
417 }
418 return update_user_option( $this->_id, 'activitypub_icon', $value );
419 }
420
421 /**
422 * Update the User-Header-Image.
423 *
424 * @param int $value The new value. Should be an attachment ID.
425 * @return bool True if the attribute was updated, false otherwise.
426 */
427 public function update_header( $value ) {
428 if ( ! wp_attachment_is_image( $value ) ) {
429 return false;
430 }
431 return \update_user_option( $this->_id, 'activitypub_header_image', $value );
432 }
433
434 /**
435 * Returns the website hosts allowed to credit this blog.
436 *
437 * @return string[]|null The attribution domains or null if not found.
438 */
439 public function get_attribution_domains() {
440 return get_attribution_domains();
441 }
442
443 /**
444 * Returns the alsoKnownAs.
445 *
446 * @return string[] The alsoKnownAs.
447 */
448 public function get_also_known_as() {
449 $also_known_as = array(
450 \add_query_arg( 'author', $this->_id, \home_url( '/' ) ),
451 $this->get_url(),
452 $this->get_alternate_url(),
453 );
454
455 $also_known_as = array_merge( $also_known_as, \get_user_option( 'activitypub_also_known_as', $this->_id ) ?: array() );
456
457 return array_unique( $also_known_as );
458 }
459
460 /**
461 * Returns the movedTo.
462 *
463 * @return string The movedTo.
464 */
465 public function get_moved_to() {
466 $moved_to = \get_user_option( 'activitypub_moved_to', $this->_id );
467
468 return $moved_to && $moved_to !== $this->get_id() ? $moved_to : null;
469 }
470 }
471