PluginProbe
ActivityPub / trunk
ActivityPub vtrunk
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-update.php

class-update.php in ActivityPub trunk, at includes/handler/class-update.php

180 lines 5.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Update handler file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Handler;
9
10 use Activitypub\Collection\Interactions;
11 use Activitypub\Collection\Remote_Actors;
12 use Activitypub\Collection\Remote_Posts;
13 use Activitypub\Http;
14
15 use function Activitypub\is_activity_reply;
16 use function Activitypub\object_to_uri;
17
18 /**
19 * Handle Update requests.
20 */
21 class Update {
22 /**
23 * Initialize the class, registering WordPress hooks.
24 */
25 public static function init() {
26 \add_action( 'activitypub_handled_inbox_update', array( self::class, 'handle_update' ), 10, 3 );
27 }
28
29 /**
30 * Handle "Update" requests.
31 *
32 * @param array $activity The Activity object.
33 * @param int[] $user_ids Local recipient user IDs (followers and addressed local actors); may be empty.
34 * @param \Activitypub\Activity\Activity $activity_object The activity object. Default null.
35 */
36 public static function handle_update( $activity, $user_ids, $activity_object ) {
37 $object_type = $activity['object']['type'] ?? '';
38
39 switch ( $object_type ) {
40 /*
41 * Actor Types.
42 *
43 * @see https://www.w3.org/TR/activitystreams-vocabulary/#actor-types
44 */
45 case 'Person':
46 case 'Group':
47 case 'Organization':
48 case 'Service':
49 case 'Application':
50 self::update_actor( $activity, $user_ids );
51 break;
52
53 /*
54 * Object and Link Types.
55 *
56 * @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types
57 */
58 case 'Note':
59 case 'Article':
60 case 'Image':
61 case 'Audio':
62 case 'Video':
63 case 'Event':
64 case 'Document':
65 self::update_object( $activity, $user_ids, $activity_object );
66 break;
67
68 /*
69 * Minimal Activity.
70 *
71 * @see https://www.w3.org/TR/activitystreams-core/#example-1
72 */
73 default:
74 break;
75 }
76 }
77
78 /**
79 * Update an Object.
80 *
81 * @param array $activity The Activity object.
82 * @param int[]|null $user_ids Local recipient user IDs (followers and addressed local actors); may be empty.
83 * @param \Activitypub\Activity\Activity $activity_object The activity object. Default null.
84 */
85 public static function update_object( $activity, $user_ids, $activity_object ) {
86 $result = new \WP_Error( 'activitypub_update_failed', 'Update failed' );
87 $updated = true;
88
89 // Check for private and/or direct messages.
90 if ( is_activity_reply( $activity ) ) {
91 $comment_data = Interactions::update_comment( $activity );
92
93 if ( false === $comment_data ) {
94 $updated = false;
95 } elseif ( \is_wp_error( $comment_data ) ) {
96 // Handled but rejected (e.g. a foreign actor): keep the failure so the
97 // success flag stays false and the Create fallback is not triggered.
98 $result = $comment_data;
99 } elseif ( ! empty( $comment_data['comment_ID'] ) ) {
100 $result = \get_comment( $comment_data['comment_ID'] );
101 }
102 } elseif ( \get_option( 'activitypub_create_posts', false ) ) {
103 $result = Remote_Posts::update( $activity, $user_ids );
104
105 if ( \is_wp_error( $result ) && 'activitypub_post_not_found' === $result->get_error_code() ) {
106 $updated = false;
107 }
108 }
109
110 // There is no object to update, try to trigger create instead.
111 if ( ! $updated ) {
112 return Create::handle_create( $activity, $user_ids, $activity_object );
113 }
114
115 $success = ( $result && ! \is_wp_error( $result ) );
116
117 /**
118 * Fires after an ActivityPub Update activity has been handled.
119 *
120 * @param array $activity The ActivityPub activity data.
121 * @param int[]|null $user_ids The local user IDs.
122 * @param bool $success True on success, false otherwise.
123 * @param \WP_Comment|\WP_Post|\WP_Error $result The updated post, comment, or error.
124 */
125 \do_action( 'activitypub_handled_update', $activity, (array) $user_ids, $success, $result );
126 }
127
128 /**
129 * Update an Actor.
130 *
131 * @param array $activity The Activity object.
132 * @param int[]|null $user_ids Local recipient user IDs (followers and addressed local actors); may be empty.
133 */
134 public static function update_actor( $activity, $user_ids ) {
135 /*
136 * Prefer the actor data embedded in the activity object, as it contains
137 * the fresh data sent by the remote server.
138 */
139 $actor = $activity['object'] ?? null;
140
141 /*
142 * The object may be a string IRI instead of an embedded object,
143 * in which case we need to fetch the actor data remotely.
144 * We use Http::get_remote_object() directly instead of
145 * get_remote_metadata_by_actor() because the latter returns the
146 * stale locally cached copy via fetch_by_uri().
147 */
148 if ( ! \is_array( $actor ) || ! isset( $actor['id'] ) ) {
149 $object = Http::get_remote_object( $activity['actor'], false );
150
151 if ( ! \is_wp_error( $object ) && \is_array( $object ) ) {
152 $actor = $object;
153 }
154 }
155
156 /*
157 * An actor may only update itself. Bind the updated object to the activity
158 * actor (the same constraint the Delete handler enforces) so a remote server
159 * cannot overwrite another host's cached actor by sending an Update whose
160 * object.id points at a victim actor.
161 */
162 if ( \is_array( $actor ) && isset( $actor['id'] ) && object_to_uri( $actor ) === object_to_uri( $activity['actor'] ) ) {
163 $state = Remote_Actors::upsert( $actor );
164 } else {
165 $state = new \WP_Error( 'activitypub_update_failed', \__( 'Update failed: missing, invalid, or unauthorized actor object in Update activity.', 'activitypub' ) );
166 $actor = array();
167 }
168
169 /**
170 * Fires after an ActivityPub Update activity has been handled.
171 *
172 * @param array $activity The ActivityPub activity data.
173 * @param int[] $user_ids The local user IDs.
174 * @param int|\WP_Error $state Actor post ID on success, WP_Error on failure.
175 * @param array $actor Remote actor meta data.
176 */
177 \do_action( 'activitypub_handled_update', $activity, (array) $user_ids, $state, $actor );
178 }
179 }
180