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 / outbox / class-update.php

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

115 lines 2.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Outbox Update handler file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Handler\Outbox;
9
10 use Activitypub\Collection\Posts;
11 use Activitypub\Collection\Remote_Posts;
12
13 use function Activitypub\is_activity_public;
14
15 /**
16 * Handle outgoing Update activities (C2S).
17 */
18 class Update {
19 /**
20 * Initialize the class, registering WordPress hooks.
21 */
22 public static function init() {
23 \add_filter( 'activitypub_outbox_update', array( self::class, 'handle_update' ), 10, 3 );
24 }
25
26 /**
27 * Handle outgoing "Update" activities from local actors.
28 *
29 * Updates a WordPress post from the ActivityPub object. The post scheduler
30 * will add it to the outbox and federate it.
31 *
32 * @param array $activity The activity data.
33 * @param int $user_id The local user ID.
34 * @param string|null $visibility Content visibility.
35 *
36 * @return \WP_Post|\WP_Error|false The updated post on success, WP_Error on failure, false if not handled.
37 */
38 public static function handle_update( $activity, $user_id = null, $visibility = null ) {
39 // Skip private/direct activities.
40 if ( ! is_activity_public( $activity ) ) {
41 return false;
42 }
43
44 $object = $activity['object'] ?? array();
45
46 if ( ! \is_array( $object ) ) {
47 return false;
48 }
49
50 $type = $object['type'] ?? '';
51
52 // Only handle Note and Article types.
53 if ( ! \in_array( $type, array( 'Note', 'Article' ), true ) ) {
54 return false;
55 }
56
57 $object_id = $object['id'] ?? '';
58
59 if ( empty( $object_id ) ) {
60 return false;
61 }
62
63 /*
64 * Find the post by its ActivityPub ID.
65 * First try to find a local post by permalink.
66 */
67 $post_id = \url_to_postid( $object_id );
68 $post = $post_id ? \get_post( $post_id ) : null;
69
70 // Fall back to Posts collection for remote posts (ap_post type).
71 if ( ! $post instanceof \WP_Post ) {
72 $post = Remote_Posts::get_by_guid( $object_id );
73 }
74
75 if ( ! $post instanceof \WP_Post ) {
76 return false;
77 }
78
79 /*
80 * Verify the user owns this post.
81 * The blog actor ($user_id === 0) can update any post since it
82 * represents the site itself.
83 */
84 if ( (int) $post->post_author !== $user_id && $user_id > 0 ) {
85 return false;
86 }
87
88 // Verify the user has permission to edit this post.
89 if ( $user_id > 0 && ! \user_can( $user_id, 'edit_post', $post->ID ) ) {
90 return new \WP_Error(
91 'activitypub_forbidden',
92 \__( 'You do not have permission to edit this post.', 'activitypub' ),
93 array( 'status' => 403 )
94 );
95 }
96
97 $post = Posts::update( $post, $activity, $visibility );
98
99 if ( \is_wp_error( $post ) ) {
100 return $post;
101 }
102
103 /**
104 * Fires after a post has been updated from an outgoing Update activity.
105 *
106 * @param int $post_id The updated post ID.
107 * @param array $activity The activity data.
108 * @param int $user_id The user ID.
109 */
110 \do_action( 'activitypub_outbox_updated_post', $post->ID, $activity, $user_id );
111
112 return $post;
113 }
114 }
115