PluginProbe
ActivityPub / 5.7.0
ActivityPub v5.7.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
← All changes | includes/model/class-user.php +57 -125 9.2.05.7.0 View file →
@@ -7,14 +7,15 @@
7 7
8 8 namespace Activitypub\Model;
9 9
10 10 use Activitypub\Activity\Actor;
11 -use Activitypub\Collection\Actors;
12 11 use Activitypub\Collection\Extra_Fields;
12 +use Activitypub\Http;
13 +use Activitypub\Signature;
13 14
15 +use function Activitypub\is_blog_public;
16 +use function Activitypub\get_rest_url_by_path;
14 17 use function Activitypub\get_attribution_domains;
15 -use function Activitypub\get_rest_url_by_path;
16 -use function Activitypub\is_blog_public;
17 18 use function Activitypub\user_can_activitypub;
18 19
19 20 /**
20 21 * User class.
@@ -29,8 +30,22 @@
29 30 */
30 31 protected $_id; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
31 32
32 33 /**
34 + * The Featured-Posts.
35 + *
36 + * @see https://docs.joinmastodon.org/spec/activitypub/#featured
37 + *
38 + * @context {
39 + * "@id": "http://joinmastodon.org/ns#featured",
40 + * "@type": "@id"
41 + * }
42 + *
43 + * @var string
44 + */
45 + protected $featured;
46 +
47 + /**
33 48 * Whether the User is discoverable.
34 49 *
35 50 * @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
36 51 *
@@ -40,26 +55,24 @@
40 55 */
41 56 protected $discoverable = true;
42 57
43 58 /**
44 - * The generator of the object.
59 + * Whether the User is indexable.
45 60 *
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
61 + * @context http://joinmastodon.org/ns#indexable
48 62 *
49 - * @var array
63 + * @var boolean
50 64 */
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 - );
65 + protected $indexable;
60 66
61 67 /**
68 + * The WebFinger Resource.
69 + *
70 + * @var string
71 + */
72 + protected $webfinger;
73 +
74 + /**
62 75 * Constructor.
63 76 *
64 77 * @param int $user_id Optional. The WordPress user ID. Default null.
65 78 */
@@ -121,9 +134,9 @@
121 134 if ( '1' === $permalink ) {
122 135 return $this->get_url();
123 136 }
124 137
125 - return \add_query_arg( 'author', $this->_id, \home_url( '/' ) );
138 + return \add_query_arg( 'author', $this->_id, \trailingslashit( \home_url() ) );
126 139 }
127 140
128 141 /**
129 142 * Get the Username.
@@ -139,11 +152,11 @@
139 152 *
140 153 * @return string The User description.
141 154 */
142 155 public function get_summary() {
143 - $description = \get_user_option( 'activitypub_description', $this->_id );
156 + $description = get_user_option( 'activitypub_description', $this->_id );
144 157 if ( empty( $description ) ) {
145 - $description = \get_user_meta( $this->_id, 'description', true );
158 + $description = get_user_meta( $this->_id, 'description', true );
146 159 }
147 160 return \wpautop( \wp_kses( $description, 'default' ) );
148 161 }
149 162
@@ -152,9 +165,9 @@
152 165 *
153 166 * @return string The User url.
154 167 */
155 168 public function get_url() {
156 - return \esc_url_raw( \get_author_posts_url( $this->_id ) );
169 + return \esc_url( \get_author_posts_url( $this->_id ) );
157 170 }
158 171
159 172 /**
160 173 * Returns the User URL with @-Prefix for the username.
@@ -161,9 +174,9 @@
161 174 *
162 175 * @return string The User URL with @-Prefix for the username.
163 176 */
164 177 public function get_alternate_url() {
165 - return \esc_url_raw( \trailingslashit( \get_home_url() ) . '@' . $this->get_preferred_username() );
178 + return \esc_url( \trailingslashit( get_home_url() ) . '@' . $this->get_preferred_username() );
166 179 }
167 180
168 181 /**
169 182 * Get the preferred username.
@@ -170,16 +183,9 @@
170 183 *
171 184 * @return string The preferred username.
172 185 */
173 186 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;
187 + return \get_the_author_meta( 'login', $this->_id );
182 188 }
183 189
184 190 /**
185 191 * Get the User icon.
@@ -187,16 +193,16 @@
187 193 * @return string[] The User icon.
188 194 */
189 195 public function get_icon() {
190 196 $icon = \get_user_option( 'activitypub_icon', $this->_id );
191 - if ( false !== $icon && \wp_attachment_is_image( $icon ) ) {
197 + if ( false !== $icon && wp_attachment_is_image( $icon ) ) {
192 198 return array(
193 199 'type' => 'Image',
194 - 'url' => \esc_url_raw( \wp_get_attachment_url( $icon ) ),
200 + 'url' => esc_url( wp_get_attachment_url( $icon ) ),
195 201 );
196 202 }
197 203
198 - $icon = \esc_url_raw(
204 + $icon = \esc_url(
199 205 \get_avatar_url(
200 206 $this->_id,
201 207 array( 'size' => 120 )
202 208 )
@@ -213,9 +219,9 @@
213 219 *
214 220 * @return string[]|null The header image.
215 221 */
216 222 public function get_image() {
217 - $header_image = \get_user_option( 'activitypub_header_image', $this->_id );
223 + $header_image = get_user_option( 'activitypub_header_image', $this->_id );
218 224 $image_url = null;
219 225
220 226 if ( ! $header_image && \has_header_image() ) {
221 227 $image_url = \get_header_image();
@@ -227,9 +233,9 @@
227 233
228 234 if ( $image_url ) {
229 235 return array(
230 236 'type' => 'Image',
231 - 'url' => \esc_url_raw( $image_url ),
237 + 'url' => esc_url( $image_url ),
232 238 );
233 239 }
234 240
235 241 return null;
@@ -252,9 +258,9 @@
252 258 public function get_public_key() {
253 259 return array(
254 260 'id' => $this->get_id() . '#main-key',
255 261 'owner' => $this->get_id(),
256 - 'publicKeyPem' => Actors::get_public_key( $this->get__id() ),
262 + 'publicKeyPem' => Signature::get_public_key_for( $this->get__id() ),
257 263 );
258 264 }
259 265
260 266 /**
@@ -262,9 +268,9 @@
262 268 *
263 269 * @return string The Inbox-Endpoint.
264 270 */
265 271 public function get_inbox() {
266 - return get_rest_url_by_path( \sprintf( 'actors/%d/inbox', $this->get__id() ) );
272 + return get_rest_url_by_path( sprintf( 'actors/%d/inbox', $this->get__id() ) );
267 273 }
268 274
269 275 /**
270 276 * Returns the Outbox-API-Endpoint.
@@ -271,9 +277,9 @@
271 277 *
272 278 * @return string The Outbox-Endpoint.
273 279 */
274 280 public function get_outbox() {
275 - return get_rest_url_by_path( \sprintf( 'actors/%d/outbox', $this->get__id() ) );
281 + return get_rest_url_by_path( sprintf( 'actors/%d/outbox', $this->get__id() ) );
276 282 }
277 283
278 284 /**
279 285 * Returns the Followers-API-Endpoint.
@@ -280,9 +286,9 @@
280 286 *
281 287 * @return string The Followers-Endpoint.
282 288 */
283 289 public function get_followers() {
284 - return get_rest_url_by_path( \sprintf( 'actors/%d/followers', $this->get__id() ) );
290 + return get_rest_url_by_path( sprintf( 'actors/%d/followers', $this->get__id() ) );
285 291 }
286 292
287 293 /**
288 294 * Returns the Following-API-Endpoint.
@@ -289,61 +295,32 @@
289 295 *
290 296 * @return string The Following-Endpoint.
291 297 */
292 298 public function get_following() {
293 - return get_rest_url_by_path( \sprintf( 'actors/%d/following', $this->get__id() ) );
299 + return get_rest_url_by_path( sprintf( 'actors/%d/following', $this->get__id() ) );
294 300 }
295 301
296 302 /**
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 303 * Returns the Featured-API-Endpoint.
309 304 *
310 305 * @return string The Featured-Endpoint.
311 306 */
312 307 public function get_featured() {
313 - return get_rest_url_by_path( \sprintf( 'actors/%d/collections/featured', $this->get__id() ) );
308 + return get_rest_url_by_path( sprintf( 'actors/%d/collections/featured', $this->get__id() ) );
314 309 }
315 310
316 311 /**
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 312 * Returns the endpoints.
327 313 *
328 314 * @return string[]|null The endpoints.
329 315 */
330 316 public function get_endpoints() {
331 - $endpoints = 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 - );
317 + $endpoints = null;
339 318
340 - if ( \get_option( 'activitypub_api', false ) ) {
341 - /*
342 - * RFC 6570 template. add_query_arg() picks the ?/& separator (plain permalinks already
343 - * carry a query string) and does not encode values, so the {q} placeholder stays intact.
344 - */
345 - $endpoints['actorAutocomplete'] = \add_query_arg( 'q', '{q}', get_rest_url_by_path( 'actors/autocomplete' ) );
319 + if ( \get_option( 'activitypub_shared_inbox' ) ) {
320 + $endpoints = array(
321 + 'sharedInbox' => get_rest_url_by_path( 'inbox' ),
322 + );
346 323 }
347 324
348 325 return $endpoints;
349 326 }
@@ -437,12 +414,12 @@
437 414 * @param int $value The new value. Should be an attachment ID.
438 415 * @return bool True if the attribute was updated, false otherwise.
439 416 */
440 417 public function update_icon( $value ) {
441 - if ( ! \wp_attachment_is_image( $value ) ) {
418 + if ( ! wp_attachment_is_image( $value ) ) {
442 419 return false;
443 420 }
444 - return \update_user_option( $this->_id, 'activitypub_icon', $value );
421 + return update_user_option( $this->_id, 'activitypub_icon', $value );
445 422 }
446 423
447 424 /**
448 425 * Update the User-Header-Image.
@@ -450,9 +427,9 @@
450 427 * @param int $value The new value. Should be an attachment ID.
451 428 * @return bool True if the attribute was updated, false otherwise.
452 429 */
453 430 public function update_header( $value ) {
454 - if ( ! \wp_attachment_is_image( $value ) ) {
431 + if ( ! wp_attachment_is_image( $value ) ) {
455 432 return false;
456 433 }
457 434 return \update_user_option( $this->_id, 'activitypub_header_image', $value );
458 435 }
@@ -477,11 +454,12 @@
477 454 $this->get_url(),
478 455 $this->get_alternate_url(),
479 456 );
480 457
481 - $also_known_as = \array_merge( $also_known_as, \get_user_option( 'activitypub_also_known_as', $this->_id ) ?: array() );
458 + // phpcs:ignore Universal.Operators.DisallowShortTernary.Found
459 + $also_known_as = array_merge( $also_known_as, \get_user_option( 'activitypub_also_known_as', $this->_id ) ?: array() );
482 460
483 - return \array_unique( $also_known_as );
461 + return array_unique( $also_known_as );
484 462 }
485 463
486 464 /**
487 465 * Returns the movedTo.
@@ -491,52 +469,6 @@
491 469 public function get_moved_to() {
492 470 $moved_to = \get_user_option( 'activitypub_moved_to', $this->_id );
493 471
494 472 return $moved_to && $moved_to !== $this->get_id() ? $moved_to : null;
495 - }
496 -
497 - /**
498 - * Get the actor-level interaction policy.
499 - *
500 - * Overrides the magic property accessor on Base_Object so that we always
501 - * compute the policy from the current site setting rather than returning a
502 - * cached property value. Currently only emits `canFeature` (FEP-7aa9).
503 - * Driven by the site option `activitypub_default_feature_policy` and
504 - * defaults to denying all featured-collection requests, in line with
505 - * FEP-7aa9's "absence of policy = no consent" rule.
506 - *
507 - * @see https://w3id.org/fep/7aa9
508 - *
509 - * @since 9.0.0
510 - *
511 - * @return array
512 - */
513 - public function get_interaction_policy() {
514 - $policy = array( 'canFeature' => $this->build_can_feature_policy() );
515 -
516 - // Merge with an explicitly set interaction policy, if any.
517 - if ( $this->interaction_policy ) {
518 - $policy = \array_merge( (array) $this->interaction_policy, $policy );
519 - }
520 -
521 - return $policy;
522 - }
523 -
524 - /**
525 - * Build the `canFeature` policy array from the site option.
526 - *
527 - * @return array
528 - */
529 - protected function build_can_feature_policy() {
530 - $policy = \get_option( 'activitypub_default_feature_policy', ACTIVITYPUB_INTERACTION_POLICY_ME );
531 -
532 - switch ( $policy ) {
533 - case ACTIVITYPUB_INTERACTION_POLICY_ANYONE:
534 - return array( 'automaticApproval' => array( 'https://www.w3.org/ns/activitystreams#Public' ) );
535 - case ACTIVITYPUB_INTERACTION_POLICY_FOLLOWERS:
536 - return array( 'automaticApproval' => array( $this->get_followers() ) );
537 - case ACTIVITYPUB_INTERACTION_POLICY_ME:
538 - default:
539 - return array( 'automaticApproval' => array( $this->get_id() ) );
540 - }
541 473 }
542 474 }