PluginProbe
ActivityPub / 8.0.2
ActivityPub v8.0.2
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.0.2, at includes/scheduler/class-post.php

224 lines 6.2 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 // If the post was never federated before, it should be a Create activity.
112 if ( empty( $object_status ) && 'Update' === $type ) {
113 $type = 'Create';
114 }
115
116 // If the post was federated before but is now local or private, it should be a Delete activity.
117 if ( ACTIVITYPUB_OBJECT_STATE_FEDERATED === $object_status && in_array( get_content_visibility( $post ), array( ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL, ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE ), true ) ) {
118 $type = 'Delete';
119 }
120
121 add_to_outbox( $post, $type, $post->post_author );
122 }
123
124 /**
125 * Schedules Activities for attachment transitions.
126 *
127 * @param int $post_id Attachment ID.
128 */
129 public static function transition_attachment_status( $post_id ) {
130 if ( \defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
131 return;
132 }
133
134 if ( ! \post_type_supports( 'attachment', 'activitypub' ) ) {
135 return;
136 }
137
138 if ( is_post_disabled( $post_id ) ) {
139 return;
140 }
141
142 $post = \get_post( $post_id );
143
144 if ( ! $post instanceof \WP_Post ) {
145 return;
146 }
147
148 switch ( \current_action() ) {
149 case 'add_attachment':
150 $type = 'Create';
151 break;
152 case 'edit_attachment':
153 $type = 'Update';
154 break;
155 case 'delete_attachment':
156 $type = 'Delete';
157 break;
158 default:
159 return;
160 }
161
162 add_to_outbox( $post, $type, $post->post_author );
163 }
164
165 /**
166 * Schedule an Add activity when a post is added to the featured collection.
167 *
168 * @param int $post_id The post ID.
169 */
170 public static function schedule_featured_add( $post_id ) {
171 self::schedule_featured_update( $post_id, 'Add' );
172 }
173
174 /**
175 * Schedule a Remove activity when a post is removed from the featured collection.
176 *
177 * @param int $post_id The post ID.
178 */
179 public static function schedule_featured_remove( $post_id ) {
180 self::schedule_featured_update( $post_id, 'Remove' );
181 }
182
183 /**
184 * Schedule an Add or Remove activity for the featured collection.
185 *
186 * When a post's sticky status changes, this sends an Add or Remove activity
187 * to notify followers about the change to the actor's featured collection.
188 *
189 * @see https://github.com/Automattic/wordpress-activitypub/issues/2795
190 *
191 * @param int $post_id The post ID.
192 * @param string $activity_type The activity type ('Add' or 'Remove').
193 */
194 private static function schedule_featured_update( $post_id, $activity_type ) {
195 if ( \defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
196 return;
197 }
198
199 $post = \get_post( $post_id );
200
201 if ( ! $post ) {
202 return;
203 }
204
205 if ( is_post_disabled( $post ) ) {
206 return;
207 }
208
209 $actor = Actors::get_by_id( $post->post_author );
210
211 if ( ! $actor || \is_wp_error( $actor ) ) {
212 return;
213 }
214
215 $activity = new Activity();
216 $activity->set_type( $activity_type );
217 $activity->set_actor( $actor->get_id() );
218 $activity->set_object( get_post_id( $post->ID ) );
219 $activity->set_target( $actor->get_featured() );
220
221 add_to_outbox( $activity, null, $post->post_author );
222 }
223 }
224