PluginProbe
ActivityPub / 8.2.0
ActivityPub v8.2.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 / scheduler / class-post.php

class-post.php in ActivityPub 8.2.0, at includes/scheduler/class-post.php

232 lines 6.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Post scheduler class file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\Scheduler;
9
10 use Activitypub\Activity\Activity;
11 use Activitypub\Collection\Actors;
12
13 use function Activitypub\add_to_outbox;
14 use function Activitypub\get_content_visibility;
15 use function Activitypub\get_post_id;
16 use function Activitypub\get_wp_object_state;
17 use function Activitypub\is_post_disabled;
18
19 /**
20 * Post scheduler class.
21 */
22 class Post {
23 /**
24 * Initialize the class, registering WordPress hooks.
25 */
26 public static function init() {
27 // Post transitions.
28 \add_action( 'wp_after_insert_post', array( self::class, 'triage' ), 33, 4 );
29
30 // Attachment transitions.
31 \add_action( 'add_attachment', array( self::class, 'transition_attachment_status' ) );
32 \add_action( 'edit_attachment', array( self::class, 'transition_attachment_status' ) );
33 \add_action( 'delete_attachment', array( self::class, 'transition_attachment_status' ) );
34
35 /*
36 * Sticky post transitions (featured collection).
37 *
38 * Note: These hooks run in addition to the legacy sticky hooks in
39 * Actor scheduler, which send an Update activity when a post becomes
40 * sticky or is unstuck. This means a sticky/unsticky event will cause both:
41 * - an Add/Remove activity for the Actor's featured collection (below), and
42 * - an Update activity (from Actor scheduler).
43 * The Update activity is kept for backwards compatibility.
44 */
45 \add_action( 'post_stuck', array( self::class, 'schedule_featured_add' ) );
46 \add_action( 'post_unstuck', array( self::class, 'schedule_featured_remove' ) );
47 }
48
49 /**
50 * Triage post transitions and determine the appropriate Activity type.
51 *
52 * @param int $post_id Post ID.
53 * @param \WP_Post $post Post object.
54 * @param bool $update Whether this is an existing post being updated.
55 * @param \WP_Post $post_before Post object before the update.
56 */
57 public static function triage( $post_id, $post, $update, $post_before ) {
58 if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
59 return;
60 }
61
62 if ( is_post_disabled( $post ) ) {
63 return;
64 }
65
66 $object_status = get_wp_object_state( $post );
67
68 // If the post is already soft-deleted, do not create any more activities.
69 if (
70 ACTIVITYPUB_OBJECT_STATE_DELETED === $object_status &&
71 in_array( get_content_visibility( $post ), array( ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL, ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE ), true )
72 ) {
73 return;
74 }
75
76 // Bail on bulk edits, unless post author or post status changed.
77 if ( isset( $_REQUEST['bulk_edit'] ) && ( ! isset( $_REQUEST['post_author'] ) || -1 === (int) $_REQUEST['post_author'] ) && -1 === (int) $_REQUEST['_status'] ) { // phpcs:ignore WordPress
78 return;
79 }
80
81 $new_status = get_post_status( $post );
82 $old_status = $post_before ? get_post_status( $post_before ) : null;
83
84 switch ( $new_status ) {
85 case 'publish':
86 if ( $update ) {
87 $type = ( 'publish' === $old_status ) ? 'Update' : 'Create';
88 } else {
89 $type = 'Create';
90 }
91 break;
92
93 case 'draft':
94 case 'pending':
95 $type = ( 'publish' === $old_status ) ? 'Update' : false;
96 break;
97
98 case 'trash':
99 $type = ACTIVITYPUB_OBJECT_STATE_FEDERATED === $object_status ? 'Delete' : false;
100 break;
101
102 default:
103 $type = false;
104 }
105
106 // Do not send Activities if `$type` is not set or unknown.
107 if ( empty( $type ) ) {
108 return;
109 }
110
111 /*
112 * If the post was already federated and this is a Create, skip.
113 * The outbox controller already added it to the outbox.
114 */
115 if ( ACTIVITYPUB_OBJECT_STATE_FEDERATED === $object_status && 'Create' === $type ) {
116 return;
117 }
118
119 // If the post was never federated before, it should be a Create activity.
120 if ( empty( $object_status ) && 'Update' === $type ) {
121 $type = 'Create';
122 }
123
124 // If the post was federated before but is now local or private, it should be a Delete activity.
125 if ( ACTIVITYPUB_OBJECT_STATE_FEDERATED === $object_status && in_array( get_content_visibility( $post ), array( ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL, ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE ), true ) ) {
126 $type = 'Delete';
127 }
128
129 add_to_outbox( $post, $type, $post->post_author );
130 }
131
132 /**
133 * Schedules Activities for attachment transitions.
134 *
135 * @param int $post_id Attachment ID.
136 */
137 public static function transition_attachment_status( $post_id ) {
138 if ( \defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
139 return;
140 }
141
142 if ( ! \post_type_supports( 'attachment', 'activitypub' ) ) {
143 return;
144 }
145
146 if ( is_post_disabled( $post_id ) ) {
147 return;
148 }
149
150 $post = \get_post( $post_id );
151
152 if ( ! $post instanceof \WP_Post ) {
153 return;
154 }
155
156 switch ( \current_action() ) {
157 case 'add_attachment':
158 $type = 'Create';
159 break;
160 case 'edit_attachment':
161 $type = 'Update';
162 break;
163 case 'delete_attachment':
164 $type = 'Delete';
165 break;
166 default:
167 return;
168 }
169
170 add_to_outbox( $post, $type, $post->post_author );
171 }
172
173 /**
174 * Schedule an Add activity when a post is added to the featured collection.
175 *
176 * @param int $post_id The post ID.
177 */
178 public static function schedule_featured_add( $post_id ) {
179 self::schedule_featured_update( $post_id, 'Add' );
180 }
181
182 /**
183 * Schedule a Remove activity when a post is removed from the featured collection.
184 *
185 * @param int $post_id The post ID.
186 */
187 public static function schedule_featured_remove( $post_id ) {
188 self::schedule_featured_update( $post_id, 'Remove' );
189 }
190
191 /**
192 * Schedule an Add or Remove activity for the featured collection.
193 *
194 * When a post's sticky status changes, this sends an Add or Remove activity
195 * to notify followers about the change to the actor's featured collection.
196 *
197 * @see https://github.com/Automattic/wordpress-activitypub/issues/2795
198 *
199 * @param int $post_id The post ID.
200 * @param string $activity_type The activity type ('Add' or 'Remove').
201 */
202 private static function schedule_featured_update( $post_id, $activity_type ) {
203 if ( \defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
204 return;
205 }
206
207 $post = \get_post( $post_id );
208
209 if ( ! $post ) {
210 return;
211 }
212
213 if ( is_post_disabled( $post ) ) {
214 return;
215 }
216
217 $actor = Actors::get_by_id( $post->post_author );
218
219 if ( ! $actor || \is_wp_error( $actor ) ) {
220 return;
221 }
222
223 $activity = new Activity();
224 $activity->set_type( $activity_type );
225 $activity->set_actor( $actor->get_id() );
226 $activity->set_object( get_post_id( $post->ID ) );
227 $activity->set_target( $actor->get_featured() );
228
229 add_to_outbox( $activity, null, $post->post_author );
230 }
231 }
232