PluginProbe
ActivityPub / 7.7.0
ActivityPub v7.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/class-post-types.php +26 -451 9.2.07.7.0 View file →
@@ -9,16 +9,12 @@
9 9
10 10 use Activitypub\Activity\Activity;
11 11 use Activitypub\Collection\Extra_Fields;
12 12 use Activitypub\Collection\Followers;
13 -use Activitypub\Collection\Following;
14 13 use Activitypub\Collection\Inbox;
15 14 use Activitypub\Collection\Outbox;
15 +use Activitypub\Collection\Posts;
16 16 use Activitypub\Collection\Remote_Actors;
17 -use Activitypub\Collection\Remote_Posts;
18 -use Activitypub\OAuth\Client;
19 -use Activitypub\OAuth\Scope;
20 -use Activitypub\OAuth\Token;
21 17
22 18 /**
23 19 * Post Types class.
24 20 */
@@ -32,19 +28,11 @@
32 28 \add_action( 'init', array( self::class, 'register_outbox_post_type' ), 11 );
33 29 \add_action( 'init', array( self::class, 'register_post_post_type' ), 11 );
34 30 \add_action( 'init', array( self::class, 'register_extra_fields_post_types' ), 11 );
35 31 \add_action( 'init', array( self::class, 'register_activitypub_post_meta' ), 11 );
36 - \add_action( 'init', array( self::class, 'register_oauth_post_types' ), 11 );
37 - \add_action( 'init', array( self::class, 'register_tombstone_post_type' ), 11 );
38 32
39 33 \add_action( 'rest_api_init', array( self::class, 'register_ap_actor_rest_field' ) );
40 - \add_action( 'rest_api_init', array( self::class, 'register_ap_post_actor_rest_field' ) );
41 - \add_action( 'rest_api_init', array( self::class, 'register_ap_post_rest_params' ) );
42 34
43 - \add_filter( 'rest_ap_post_query', array( self::class, 'filter_ap_post_by_user' ), 10, 2 );
44 - \add_filter( 'rest_ap_object_type_query', array( self::class, 'filter_object_type_by_user' ), 10, 2 );
45 - \add_filter( 'rest_ap_object_type_collection_params', array( self::class, 'register_object_type_user_param' ) );
46 -
47 35 \add_filter( 'activitypub_get_actor_extra_fields', array( Extra_Fields::class, 'default_actor_extra_fields' ), 10, 2 );
48 36
49 37 \add_filter( 'add_post_metadata', array( self::class, 'prevent_empty_post_meta' ), 10, 4 );
50 38 \add_filter( 'update_post_metadata', array( self::class, 'prevent_empty_post_meta' ), 10, 4 );
@@ -72,9 +60,9 @@
72 60 'rewrite' => false,
73 61 'query_var' => false,
74 62 'delete_with_user' => false,
75 63 'can_export' => true,
76 - 'supports' => array( 'custom-fields' ),
64 + 'supports' => array(),
77 65 )
78 66 );
79 67
80 68 // Register meta for Remote Actors post type.
@@ -103,9 +91,8 @@
103 91 Followers::FOLLOWER_META_KEY,
104 92 array(
105 93 'type' => 'string',
106 94 'single' => false,
107 - 'show_in_rest' => true,
108 95 'sanitize_callback' => 'sanitize_text_field',
109 96 )
110 97 );
111 98 }
@@ -155,9 +142,9 @@
155 142 'type' => 'string',
156 143 'description' => 'The type of the activity',
157 144 'single' => true,
158 145 'show_in_rest' => true,
159 - 'sanitize_callback' => static function ( $value ) {
146 + 'sanitize_callback' => function ( $value ) {
160 147 $schema = array(
161 148 'type' => 'string',
162 149 'enum' => Activity::TYPES,
163 150 'default' => 'Create',
@@ -189,9 +176,9 @@
189 176 array(
190 177 'type' => 'string',
191 178 'single' => true,
192 179 'show_in_rest' => true,
193 - 'sanitize_callback' => static function ( $value ) {
180 + 'sanitize_callback' => function ( $value ) {
194 181 $schema = array(
195 182 'type' => 'string',
196 183 'enum' => array( ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC, ACTIVITYPUB_CONTENT_VISIBILITY_QUIET_PUBLIC, ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE, ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL ),
197 184 'default' => ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC,
@@ -258,9 +245,9 @@
258 245 'type' => 'string',
259 246 'description' => 'The type of the activity',
260 247 'single' => true,
261 248 'show_in_rest' => true,
262 - 'sanitize_callback' => static function ( $value ) {
249 + 'sanitize_callback' => function ( $value ) {
263 250 $schema = array(
264 251 'type' => 'string',
265 252 'enum' => Activity::TYPES,
266 253 'default' => 'Announce',
@@ -281,9 +268,9 @@
281 268 array(
282 269 'type' => 'string',
283 270 'single' => true,
284 271 'show_in_rest' => true,
285 - 'sanitize_callback' => static function ( $value ) {
272 + 'sanitize_callback' => function ( $value ) {
286 273 $schema = array(
287 274 'type' => 'string',
288 275 'enum' => array( 'application', 'blog', 'user' ),
289 276 'default' => 'user',
@@ -327,9 +314,9 @@
327 314 array(
328 315 'type' => 'string',
329 316 'single' => true,
330 317 'show_in_rest' => true,
331 - 'sanitize_callback' => static function ( $value ) {
318 + 'sanitize_callback' => function ( $value ) {
332 319 $schema = array(
333 320 'type' => 'string',
334 321 'enum' => array( ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC, ACTIVITYPUB_CONTENT_VISIBILITY_QUIET_PUBLIC, ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE, ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL ),
335 322 'default' => ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC,
@@ -349,9 +336,9 @@
349 336 * Register the Post post type.
350 337 */
351 338 public static function register_post_post_type() {
352 339 \register_post_type(
353 - Remote_Posts::POST_TYPE,
340 + Posts::POST_TYPE,
354 341 array(
355 342 'labels' => array(
356 343 'name' => \_x( 'Posts', 'post_type plural name', 'activitypub' ),
357 344 'singular_name' => \_x( 'Post', 'post_type single name', 'activitypub' ),
@@ -356,13 +343,13 @@
356 343 'name' => \_x( 'Posts', 'post_type plural name', 'activitypub' ),
357 344 'singular_name' => \_x( 'Post', 'post_type single name', 'activitypub' ),
358 345 ),
359 346 'capabilities' => array(
360 - 'activitypub' => true,
347 + 'create_posts' => false,
361 348 ),
362 349 'map_meta_cap' => true,
363 350 'public' => false,
364 - 'show_in_rest' => true,
351 + 'show_in_rest' => false,
365 352 'rewrite' => false,
366 353 'query_var' => false,
367 354 'supports' => array( 'title', 'editor', 'author', 'custom-fields', 'excerpt', 'comments' ),
368 355 'delete_with_user' => true,
@@ -373,9 +360,9 @@
373 360 );
374 361
375 362 \register_taxonomy(
376 363 'ap_tag',
377 - array( Remote_Posts::POST_TYPE ),
364 + array( Posts::POST_TYPE ),
378 365 array(
379 366 'public' => false,
380 367 'query_var' => true,
381 368 'show_in_rest' => true,
@@ -383,9 +370,9 @@
383 370 );
384 371
385 372 \register_taxonomy(
386 373 'ap_object_type',
387 - array( Remote_Posts::POST_TYPE ),
374 + array( Posts::POST_TYPE ),
388 375 array(
389 376 'public' => false,
390 377 'query_var' => true,
391 378 'show_in_rest' => true,
@@ -392,9 +379,9 @@
392 379 )
393 380 );
394 381
395 382 \register_post_meta(
396 - Remote_Posts::POST_TYPE,
383 + Posts::POST_TYPE,
397 384 '_activitypub_remote_actor_id',
398 385 array(
399 386 'type' => 'integer',
400 387 'single' => true,
@@ -403,9 +390,9 @@
403 390 )
404 391 );
405 392
406 393 \register_post_meta(
407 - Remote_Posts::POST_TYPE,
394 + Posts::POST_TYPE,
408 395 '_activitypub_user_id',
409 396 array(
410 397 'type' => 'integer',
411 398 'single' => true,
@@ -443,9 +430,8 @@
443 430 'map_meta_cap' => true,
444 431 'show_ui' => true,
445 432 'supports' => array( 'title', 'editor', 'page-attributes', 'author' ),
446 433 'capabilities' => array(
447 - 'create_posts' => 'activitypub', // Require activitypub capability to create extra fields.
448 434 'edit_others_posts' => 'do_not_allow', // Disallow editing others' Extra Fields (only own ones).
449 435 ),
450 436 );
451 437
@@ -450,10 +436,9 @@
450 436 );
451 437
452 438 \register_post_type( Extra_Fields::USER_POST_TYPE, $extra_field_args );
453 439
454 - // Blog Extra Fields require manage_options capability.
455 - $extra_field_args['capabilities'] = array( 'create_posts' => 'manage_options' );
440 + unset( $extra_field_args['capabilities'] ); // Allow editing the Blog's Extra Fields.
456 441 \register_post_type( Extra_Fields::BLOG_POST_TYPE, $extra_field_args );
457 442
458 443 /**
459 444 * Fires after ActivityPub custom post types have been registered.
@@ -461,143 +446,8 @@
461 446 \do_action( 'activitypub_after_register_post_type' );
462 447 }
463 448
464 449 /**
465 - * Register OAuth 2.0 post types for C2S support.
466 - *
467 - * Registers post type for OAuth clients.
468 - * Note: Tokens are stored in user meta and authorization codes in transients.
469 - */
470 - public static function register_oauth_post_types() {
471 - // OAuth Clients post type.
472 - \register_post_type(
473 - Client::POST_TYPE,
474 - array(
475 - 'labels' => array(
476 - 'name' => \_x( 'OAuth Clients', 'post_type plural name', 'activitypub' ),
477 - 'singular_name' => \_x( 'OAuth Client', 'post_type single name', 'activitypub' ),
478 - ),
479 - 'public' => false,
480 - 'show_in_rest' => false,
481 - 'hierarchical' => false,
482 - 'rewrite' => false,
483 - 'query_var' => false,
484 - 'delete_with_user' => false,
485 - 'can_export' => true,
486 - 'supports' => array( 'title', 'editor', 'custom-fields' ),
487 - 'exclude_from_search' => true,
488 - )
489 - );
490 -
491 - // OAuth Client meta.
492 - \register_post_meta(
493 - Client::POST_TYPE,
494 - '_activitypub_client_id',
495 - array(
496 - 'type' => 'string',
497 - 'single' => true,
498 - 'description' => 'Unique OAuth client identifier (UUID).',
499 - 'sanitize_callback' => 'sanitize_text_field',
500 - )
501 - );
502 -
503 - \register_post_meta(
504 - Client::POST_TYPE,
505 - '_activitypub_client_secret_hash',
506 - array(
507 - 'type' => 'string',
508 - 'single' => true,
509 - 'description' => 'SHA-256 hash of the client secret (null for public clients).',
510 - 'sanitize_callback' => 'sanitize_text_field',
511 - )
512 - );
513 -
514 - \register_post_meta(
515 - Client::POST_TYPE,
516 - '_activitypub_redirect_uris',
517 - array(
518 - 'type' => 'array',
519 - 'single' => true,
520 - 'description' => 'Allowed redirect URIs for this client.',
521 - 'sanitize_callback' => static function ( $value ) {
522 - if ( ! \is_array( $value ) ) {
523 - return array();
524 - }
525 - return \array_map( array( Sanitize::class, 'redirect_uri' ), $value );
526 - },
527 - )
528 - );
529 -
530 - \register_post_meta(
531 - Client::POST_TYPE,
532 - '_activitypub_allowed_scopes',
533 - array(
534 - 'type' => 'array',
535 - 'single' => true,
536 - 'description' => 'Allowed OAuth scopes for this client.',
537 - 'sanitize_callback' => array( Scope::class, 'sanitize' ),
538 - )
539 - );
540 -
541 - \register_post_meta(
542 - Client::POST_TYPE,
543 - '_activitypub_is_public',
544 - array(
545 - 'type' => 'boolean',
546 - 'single' => true,
547 - 'description' => 'Whether this is a public client (PKCE-only, no secret).',
548 - 'sanitize_callback' => 'rest_sanitize_boolean',
549 - 'default' => true,
550 - )
551 - );
552 -
553 - \register_post_meta(
554 - Client::POST_TYPE,
555 - Token::USER_META_KEY,
556 - array(
557 - 'type' => 'integer',
558 - 'single' => false,
559 - 'description' => 'User IDs that have active tokens for this client.',
560 - 'sanitize_callback' => 'absint',
561 - )
562 - );
563 - }
564 -
565 - /**
566 - * Register the ap_tombstone post type.
567 - *
568 - * Stores local tombstone URLs out of the autoloaded options row.
569 - * The post type is fully internal — never queried publicly, never shown in UI.
570 - *
571 - * @since 8.3.0
572 - */
573 - public static function register_tombstone_post_type() {
574 - \register_post_type(
575 - Tombstone::POST_TYPE,
576 - array(
577 - 'labels' => array(
578 - 'name' => \_x( 'Tombstones', 'post_type plural name', 'activitypub' ),
579 - 'singular_name' => \_x( 'Tombstone', 'post_type single name', 'activitypub' ),
580 - ),
581 - 'public' => false,
582 - 'publicly_queryable' => false,
583 - 'show_ui' => false,
584 - 'show_in_menu' => false,
585 - 'show_in_nav_menus' => false,
586 - 'show_in_admin_bar' => false,
587 - 'show_in_rest' => false,
588 - 'exclude_from_search' => true,
589 - 'has_archive' => false,
590 - 'rewrite' => false,
591 - 'query_var' => false,
592 - 'can_export' => false,
593 - 'delete_with_user' => false,
594 - 'supports' => array(),
595 - )
596 - );
597 - }
598 -
599 - /**
600 450 * Register post meta for ActivityPub supported post types.
601 451 */
602 452 public static function register_activitypub_post_meta() {
603 453 $ap_post_types = \get_post_types_by_support( 'activitypub' );
@@ -619,9 +469,9 @@
619 469 array(
620 470 'type' => 'string',
621 471 'single' => true,
622 472 'show_in_rest' => true,
623 - 'sanitize_callback' => static function ( $value ) {
473 + 'sanitize_callback' => function ( $value ) {
624 474 $schema = array(
625 475 'type' => 'string',
626 476 'enum' => array( ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC, ACTIVITYPUB_CONTENT_VISIBILITY_QUIET_PUBLIC, ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE, ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL ),
627 477 'default' => ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC,
@@ -654,10 +504,9 @@
654 504 array(
655 505 'type' => 'string',
656 506 'single' => true,
657 507 'show_in_rest' => true,
658 - 'default' => \get_option( 'activitypub_default_quote_policy', ACTIVITYPUB_INTERACTION_POLICY_ANYONE ),
659 - 'sanitize_callback' => static function ( $value ) {
508 + 'sanitize_callback' => function ( $value ) {
660 509 $schema = array(
661 510 'type' => 'string',
662 511 'enum' => array( ACTIVITYPUB_INTERACTION_POLICY_ANYONE, ACTIVITYPUB_INTERACTION_POLICY_FOLLOWERS, ACTIVITYPUB_INTERACTION_POLICY_ME ),
663 512 'default' => ACTIVITYPUB_INTERACTION_POLICY_ANYONE,
@@ -678,23 +527,13 @@
678 527 array(
679 528 'type' => 'string',
680 529 'single' => true,
681 530 'show_in_rest' => true,
682 - 'sanitize_callback' => static function ( $value ) {
683 - // Allow empty values to pass through without setting a default.
684 - if ( empty( $value ) ) {
685 - return '';
686 - }
687 -
531 + 'sanitize_callback' => function ( $value ) {
688 532 $schema = array(
689 533 'type' => 'string',
690 - 'enum' => array(
691 - ACTIVITYPUB_OBJECT_STATE_PENDING,
692 - ACTIVITYPUB_OBJECT_STATE_FEDERATED,
693 - ACTIVITYPUB_OBJECT_STATE_FAILED,
694 - ACTIVITYPUB_OBJECT_STATE_DELETED,
695 - ),
696 - 'default' => '',
534 + 'enum' => array( 'pending', 'federated', 'failed' ),
535 + 'default' => 'pending',
697 536 );
698 537
699 538 if ( \is_wp_error( \rest_validate_enum( $value, $schema, '' ) ) ) {
700 539 return $schema['default'];
@@ -720,9 +559,9 @@
720 559 *
721 560 * @param array $response Prepared response array.
722 561 * @return string The raw post content.
723 562 */
724 - 'get_callback' => static function ( $response ) {
563 + 'get_callback' => function ( $response ) {
725 564 return \get_post_field( 'post_content', $response['id'] );
726 565 },
727 566 'schema' => array(
728 567 'description' => 'Raw ActivityPub JSON data without WordPress content filtering',
@@ -730,276 +569,11 @@
730 569 'context' => array( 'view', 'edit' ),
731 570 ),
732 571 )
733 572 );
734 -
735 - // Add formatted actor data field.
736 - \register_rest_field(
737 - Remote_Actors::POST_TYPE,
738 - 'actor_info',
739 - array(
740 - 'get_callback' => function ( $response ) {
741 - $actor = Remote_Actors::get_actor( $response['id'] );
742 - if ( \is_wp_error( $actor ) ) {
743 - return null;
744 - }
745 - return array(
746 - 'username' => $actor->get_preferred_username(),
747 - 'name' => $actor->get_name() ?? $actor->get_preferred_username(),
748 - 'icon' => \sanitize_url( object_to_uri( $actor->get_icon() ) ?? '' ),
749 - 'url' => \sanitize_url( object_to_uri( $actor->get_url() ?? $actor->get_id() ) ?? '' ),
750 - 'webfinger' => Remote_Actors::get_acct( $response['id'] ),
751 - 'identifier' => $actor->get_id(),
752 - );
753 - },
754 - 'schema' => array(
755 - 'description' => 'Parsed ActivityPub actor information',
756 - 'type' => 'object',
757 - 'context' => array( 'view', 'edit' ),
758 - ),
759 - )
760 - );
761 -
762 - // Add follow status field.
763 - \register_rest_field(
764 - Remote_Actors::POST_TYPE,
765 - 'follow_status',
766 - array(
767 - 'get_callback' => function ( $response ) {
768 - $current_user_id = \get_current_user_id();
769 - if ( ! $current_user_id ) {
770 - return array( 'follows_back' => false );
771 - }
772 - return array(
773 - 'follows_back' => Following::check_status( $current_user_id, $response['id'] ),
774 - );
775 - },
776 - 'schema' => array(
777 - 'description' => 'Follow relationship status',
778 - 'type' => 'object',
779 - 'context' => array( 'view', 'edit' ),
780 - ),
781 - )
782 - );
783 -
784 - // Add custom query parameter for filtering by follower relationships.
785 - \add_filter( 'rest_ap_actor_query', array( self::class, 'filter_ap_actor_query_by_follower' ), 10, 2 );
786 573 }
787 574
788 575 /**
789 - * Filter WP_Query args to support follower_of parameter.
790 - *
791 - * @param array $args Array of arguments for WP_Query.
792 - * @param \WP_REST_Request $request The REST API request.
793 - * @return array Modified query arguments.
794 - */
795 - public static function filter_ap_actor_query_by_follower( $args, $request ) {
796 - if ( ! empty( $request['follower_of'] ) ) {
797 - // Add meta_query to filter by _activitypub_following.
798 - if ( ! isset( $args['meta_query'] ) ) {
799 - $args['meta_query'] = array(); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
800 - }
801 -
802 - $args['meta_query'][] = array(
803 - 'key' => Followers::FOLLOWER_META_KEY,
804 - 'value' => $request['follower_of'],
805 - );
806 - }
807 -
808 - return $args;
809 - }
810 -
811 - /**
812 - * Register a REST field for the ap_post post type to embed remote actor data.
813 - */
814 - public static function register_ap_post_actor_rest_field() {
815 - \register_rest_field(
816 - Remote_Posts::POST_TYPE,
817 - 'actor_info',
818 - array(
819 - /**
820 - * Get the remote actor data for an ap_post.
821 - *
822 - * @param array $response Prepared response array.
823 - * @return array|null The actor data or null if not found.
824 - */
825 - 'get_callback' => function ( $response ) {
826 - $id = \get_post_meta( $response['id'], '_activitypub_remote_actor_id', true );
827 - $actor = Remote_Actors::get_actor( $id );
828 -
829 - if ( \is_wp_error( $actor ) ) {
830 - return null;
831 - }
832 -
833 - return array(
834 - 'username' => $actor->get_preferred_username(),
835 - 'name' => $actor->get_name() ?? $actor->get_preferred_username(),
836 - 'icon' => \sanitize_url( object_to_uri( $actor->get_icon() ) ?? '' ),
837 - 'url' => \sanitize_url( object_to_uri( $actor->get_url() ?? $actor->get_id() ) ?? '' ),
838 - 'webfinger' => Remote_Actors::get_acct( $id ),
839 - 'identifier' => $actor->get_id(),
840 - );
841 - },
842 - 'schema' => array(
843 - 'description' => 'Remote actor data',
844 - 'type' => 'object',
845 - 'context' => array( 'view', 'edit' ),
846 - ),
847 - )
848 - );
849 - }
850 -
851 - /**
852 - * Register custom REST API parameters for ap_post endpoint.
853 - */
854 - public static function register_ap_post_rest_params() {
855 - \add_filter(
856 - 'rest_' . Remote_Posts::POST_TYPE . '_collection_params',
857 - function ( $params ) {
858 - $params['user_id'] = array(
859 - 'description' => \__( 'Filter posts by user ID (0 for site/blog actor).', 'activitypub' ),
860 - 'type' => 'integer',
861 - 'sanitize_callback' => 'absint',
862 - );
863 -
864 - $params['ap_object_type'] = array(
865 - 'description' => 'Filter posts by ActivityPub object type.',
866 - 'type' => 'array',
867 - 'items' => array(
868 - 'type' => 'integer',
869 - 'minimum' => 0,
870 - ),
871 - );
872 -
873 - $params['ap_tag'] = array(
874 - 'description' => 'Filter posts by ActivityPub tag (term IDs).',
875 - 'type' => 'array',
876 - 'items' => array(
877 - 'type' => 'integer',
878 - 'minimum' => 0,
879 - ),
880 - );
881 -
882 - return $params;
883 - }
884 - );
885 - }
886 -
887 - /**
888 - * Filter ap_post REST query to only show posts for the current user.
889 - *
890 - * @param array $args Query arguments.
891 - * @param \WP_REST_Request $request The REST API request.
892 - *
893 - * @return array Modified query arguments.
894 - */
895 - public static function filter_ap_post_by_user( $args, $request ) {
896 - $ap_tag = $request->get_param( 'ap_tag' );
897 - if ( ! empty( $ap_tag ) ) {
898 - if ( ! isset( $args['tax_query'] ) ) {
899 - $args['tax_query'] = array(); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
900 - }
901 -
902 - $args['tax_query'][] = array(
903 - 'taxonomy' => 'ap_tag',
904 - 'field' => 'term_id',
905 - 'terms' => $ap_tag,
906 - );
907 -
908 - return $args;
909 - }
910 -
911 - // Filter by user_id (defaults to current user, use 0 for site/blog actor).
912 - $user_id = isset( $request['user_id'] ) ? (int) $request['user_id'] : \get_current_user_id();
913 -
914 - if ( ! isset( $args['meta_query'] ) ) {
915 - $args['meta_query'] = array(); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
916 - }
917 -
918 - $args['meta_query'][] = array(
919 - 'key' => '_activitypub_user_id',
920 - 'value' => $user_id,
921 - 'compare' => '=',
922 - );
923 -
924 - // Filter by object type if provided.
925 - if ( ! empty( $request['ap_object_type'] ) ) {
926 - if ( ! isset( $args['tax_query'] ) ) {
927 - $args['tax_query'] = array(); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
928 - }
929 -
930 - $args['tax_query'][] = array(
931 - 'taxonomy' => 'ap_object_type',
932 - 'field' => 'term_id',
933 - 'terms' => $request['ap_object_type'],
934 - );
935 - }
936 -
937 - return $args;
938 - }
939 -
940 - /**
941 - * Register user_id parameter for ap_object_type taxonomy REST API.
942 - *
943 - * @param array $params Existing collection parameters.
944 - *
945 - * @return array Modified collection parameters.
946 - */
947 - public static function register_object_type_user_param( $params ) {
948 - $params['user_id'] = array(
949 - 'description' => \__( 'Filter terms to those with posts from this user ID.', 'activitypub' ),
950 - 'type' => 'integer',
951 - 'sanitize_callback' => 'absint',
952 - );
953 -
954 - return $params;
955 - }
956 -
957 - /**
958 - * Filter ap_object_type REST query to only return terms that have posts for the given user.
959 - *
960 - * Uses a direct SQL query to efficiently get term IDs without loading all post IDs.
961 - *
962 - * @param array $args Query arguments.
963 - * @param \WP_REST_Request $request The REST API request.
964 - *
965 - * @return array Modified query arguments.
966 - */
967 - public static function filter_object_type_by_user( $args, $request ) {
968 - $user_id = $request->get_param( 'user_id' );
969 - if ( null === $user_id ) {
970 - return $args;
971 - }
972 -
973 - global $wpdb;
974 -
975 - // Get term IDs that have at least one ap_post for this user.
976 - $term_ids = $wpdb->get_col( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
977 - $wpdb->prepare(
978 - "SELECT DISTINCT tt.term_id
979 - FROM {$wpdb->term_taxonomy} tt
980 - INNER JOIN {$wpdb->term_relationships} tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
981 - INNER JOIN {$wpdb->posts} p ON tr.object_id = p.ID
982 - INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
983 - WHERE tt.taxonomy = 'ap_object_type'
984 - AND p.post_type = 'ap_post'
985 - AND pm.meta_key = '_activitypub_user_id'
986 - AND pm.meta_value = %s",
987 - $user_id
988 - )
989 - );
990 -
991 - if ( empty( $term_ids ) ) {
992 - // Force empty result.
993 - $term_ids = array( 0 );
994 - }
995 -
996 - $args['include'] = \array_map( 'intval', $term_ids );
997 -
998 - return $args;
999 - }
1000 -
1001 - /**
1002 576 * Prevent empty or default meta values.
1003 577 *
1004 578 * @param null|bool $check Whether to allow updating metadata for the given type.
1005 579 * @param int $object_id ID of the object metadata is for.
@@ -1007,15 +581,16 @@
1007 581 * @param mixed $meta_value Metadata value. Must be serializable if non-scalar.
1008 582 */
1009 583 public static function prevent_empty_post_meta( $check, $object_id, $meta_key, $meta_value ) {
1010 584 $post_metas = array(
1011 - 'activitypub_content_visibility' => '',
1012 - 'activitypub_content_warning' => '',
1013 - 'activitypub_max_image_attachments' => (string) \get_option( 'activitypub_max_image_attachments', ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS ),
585 + 'activitypub_content_visibility' => '',
586 + 'activitypub_content_warning' => '',
587 + 'activitypub_interaction_policy_quote' => ACTIVITYPUB_INTERACTION_POLICY_ANYONE,
588 + 'activitypub_max_image_attachments' => (string) \get_option( 'activitypub_max_image_attachments', ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS ),
1014 589 );
1015 590
1016 591 if ( isset( $post_metas[ $meta_key ] ) && $post_metas[ $meta_key ] === (string) $meta_value ) {
1017 - if ( 'update_post_metadata' === \current_action() ) {
592 + if ( 'update_post_metadata' === current_action() ) {
1018 593 \delete_post_meta( $object_id, $meta_key );
1019 594 }
1020 595
1021 596 $check = true;