PluginProbe
ActivityPub / 8.0.0
ActivityPub v8.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 / handler / class-create.php

class-create.php in ActivityPub 8.0.0, at includes/handler/class-create.php

178 lines 5.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Create handler file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Handler;
9
10 use Activitypub\Collection\Interactions;
11 use Activitypub\Collection\Posts;
12 use Activitypub\Tombstone;
13
14 use function Activitypub\get_activity_visibility;
15 use function Activitypub\is_activity_reply;
16 use function Activitypub\is_quote_activity;
17 use function Activitypub\is_self_ping;
18 use function Activitypub\object_id_to_comment;
19
20 /**
21 * Handle Create requests.
22 */
23 class Create {
24 /**
25 * Initialize the class, registering WordPress hooks.
26 */
27 public static function init() {
28 \add_action( 'activitypub_handled_inbox_create', array( self::class, 'handle_create' ), 10, 3 );
29 \add_filter( 'activitypub_validate_object', array( self::class, 'validate_object' ), 10, 3 );
30 \add_action( 'post_activitypub_add_to_outbox', array( self::class, 'maybe_unbury' ), 10, 2 );
31 }
32
33 /**
34 * Handles "Create" requests.
35 *
36 * @param array $activity The activity-object.
37 * @param int|int[] $user_ids The id(s) of the local blog-user(s).
38 * @param \Activitypub\Activity\Activity $activity_object Optional. The activity object. Default null.
39 */
40 public static function handle_create( $activity, $user_ids, $activity_object = null ) {
41 // Check for private and/or direct messages.
42 if ( ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE === get_activity_visibility( $activity ) ) {
43 $result = false;
44 } elseif ( is_activity_reply( $activity ) || is_quote_activity( $activity ) ) { // Check for replies and quotes.
45 $result = self::create_interaction( $activity, $user_ids, $activity_object );
46 } else { // Handle non-interaction objects.
47 $result = self::create_post( $activity, $user_ids, $activity_object );
48 }
49
50 if ( false === $result ) {
51 return;
52 }
53
54 $success = ! \is_wp_error( $result );
55
56 /**
57 * Fires after an ActivityPub Create activity has been handled.
58 *
59 * @param array $activity The ActivityPub activity data.
60 * @param int[] $user_ids The local user IDs.
61 * @param bool $success True on success, false otherwise.
62 * @param \WP_Comment|\WP_Post|\WP_Error $result The WP_Comment object of the created comment, or null if creation failed.
63 */
64 \do_action( 'activitypub_handled_create', $activity, (array) $user_ids, $success, $result );
65 }
66
67 /**
68 * Handle interactions like replies.
69 *
70 * @param array $activity The activity-object.
71 * @param int[] $user_ids The ids of the local blog-users.
72 * @param \Activitypub\Activity\Activity $activity_object Optional. The activity object. Default null.
73 *
74 * @return \WP_Comment|\WP_Error|false The created comment, WP_Error on failure, false if already exists or not processed.
75 */
76 public static function create_interaction( $activity, $user_ids, $activity_object = null ) {
77 $existing_comment = object_id_to_comment( $activity['object']['id'] );
78
79 // If comment exists, call update action.
80 if ( $existing_comment ) {
81 Update::handle_update( $activity, (array) $user_ids, $activity_object );
82
83 return false;
84 }
85
86 if ( is_self_ping( $activity['object']['id'] ) ) {
87 return false;
88 }
89
90 $result = Interactions::add_comment( $activity );
91
92 if ( ! $result || \is_wp_error( $result ) ) {
93 return $result;
94 }
95
96 return \get_comment( $result );
97 }
98
99 /**
100 * Handle non-interaction posts like posts.
101 *
102 * @param array $activity The activity-object.
103 * @param int[] $user_ids The ids of the local blog-users.
104 * @param \Activitypub\Activity\Activity $activity_object Optional. The activity object. Default null.
105 *
106 * @return \WP_Post|\WP_Error|false The post on success, WP_Error on failure, false if already exists.
107 */
108 public static function create_post( $activity, $user_ids, $activity_object = null ) {
109 if ( ! \get_option( 'activitypub_create_posts', false ) ) {
110 return false;
111 }
112
113 $existing_post = Posts::get_by_guid( $activity['object']['id'] );
114
115 // If post exists, call update action.
116 if ( $existing_post instanceof \WP_Post ) {
117 Update::handle_update( $activity, (array) $user_ids, $activity_object );
118
119 return false;
120 }
121
122 return Posts::add( $activity, $user_ids );
123 }
124
125 /**
126 * Validate the object.
127 *
128 * @param bool $valid The validation state.
129 * @param string $param The object parameter.
130 * @param \WP_REST_Request $request The request object.
131 *
132 * @return bool The validation state: true if valid, false if not.
133 */
134 public static function validate_object( $valid, $param, $request ) {
135 $activity = $request->get_json_params();
136
137 if ( empty( $activity['type'] ) ) {
138 return false;
139 }
140
141 if ( 'Create' !== $activity['type'] ) {
142 return $valid;
143 }
144
145 if ( ! isset( $activity['object'] ) || ! \is_array( $activity['object'] ) ) {
146 return false;
147 }
148
149 if ( ! isset( $activity['object']['id'], $activity['object']['content'] ) ) {
150 return false;
151 }
152
153 return $valid;
154 }
155
156 /**
157 * Remove a URL from the tombstone registry when a Create or Update activity is sent.
158 *
159 * This handles the case where a post was soft-deleted (visibility changed to local/private)
160 * and then later changed back to public. The Create/Update activity indicates the post is being
161 * re-federated, so we remove it from the tombstone registry.
162 *
163 * @param int $outbox_id The ID of the outbox activity.
164 * @param \Activitypub\Activity\Activity $activity The Activity object.
165 */
166 public static function maybe_unbury( $outbox_id, $activity ) {
167 if ( ! in_array( $activity->get_type(), array( 'Create', 'Update' ), true ) ) {
168 return;
169 }
170
171 $object = $activity->get_object();
172
173 if ( $object ) {
174 Tombstone::remove( $object->get_id(), $object->get_url() );
175 }
176 }
177 }
178