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
← All changes | includes/scheduler/class-post.php +18 -55 9.2.08.0.2 View file →
@@ -10,12 +10,12 @@
10 10 use Activitypub\Activity\Activity;
11 11 use Activitypub\Collection\Actors;
12 12
13 13 use function Activitypub\add_to_outbox;
14 +use function Activitypub\get_content_visibility;
14 15 use function Activitypub\get_post_id;
15 16 use function Activitypub\get_wp_object_state;
16 17 use function Activitypub\is_post_disabled;
17 -use function Activitypub\is_post_publicly_queryable;
18 18
19 19 /**
20 20 * Post scheduler class.
21 21 */
@@ -54,9 +54,9 @@
54 54 * @param bool $update Whether this is an existing post being updated.
55 55 * @param \WP_Post $post_before Post object before the update.
56 56 */
57 57 public static function triage( $post_id, $post, $update, $post_before ) {
58 - if ( \defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
58 + if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
59 59 return;
60 60 }
61 61
62 62 if ( is_post_disabled( $post ) ) {
@@ -63,12 +63,14 @@
63 63 return;
64 64 }
65 65
66 66 $object_status = get_wp_object_state( $post );
67 - $is_queryable = is_post_publicly_queryable( $post );
68 67
69 - // If the post is already soft-deleted and still non-public, do not create any more activities.
70 - if ( ACTIVITYPUB_OBJECT_STATE_DELETED === $object_status && ! $is_queryable ) {
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 + ) {
71 73 return;
72 74 }
73 75
74 76 // Bail on bulk edits, unless post author or post status changed.
@@ -75,10 +77,10 @@
75 77 if ( isset( $_REQUEST['bulk_edit'] ) && ( ! isset( $_REQUEST['post_author'] ) || -1 === (int) $_REQUEST['post_author'] ) && -1 === (int) $_REQUEST['_status'] ) { // phpcs:ignore WordPress
76 78 return;
77 79 }
78 80
79 - $new_status = \get_post_status( $post );
80 - $old_status = $post_before ? \get_post_status( $post_before ) : null;
81 + $new_status = get_post_status( $post );
82 + $old_status = $post_before ? get_post_status( $post_before ) : null;
81 83
82 84 switch ( $new_status ) {
83 85 case 'publish':
84 86 if ( $update ) {
@@ -87,38 +89,19 @@
87 89 $type = 'Create';
88 90 }
89 91 break;
90 92
91 - case 'future':
92 - /*
93 - * A (re-)scheduled post is not a deletion: it becomes public again
94 - * when it publishes, at which point the publish transition federates
95 - * it. Treating `future` as a soft delete would fan out a Delete that
96 - * remotely tombstones the object id — e.g. when a content edit reverts
97 - * a future-dated published post back to `future` — after which the
98 - * post can never re-federate. Emit nothing instead.
99 - */
100 - $type = false;
93 + case 'draft':
94 + case 'pending':
95 + $type = ( 'publish' === $old_status ) ? 'Update' : false;
101 96 break;
102 97
103 - case 'draft':
104 - case 'pending':
105 - case 'private':
106 98 case 'trash':
99 + $type = ACTIVITYPUB_OBJECT_STATE_FEDERATED === $object_status ? 'Delete' : false;
100 + break;
101 +
107 102 default:
108 - /*
109 - * Soft delete for federated posts (FEP-4f05).
110 - *
111 - * A previously-federated post transitioning to any non-public
112 - * status (built-in or custom) emits a Delete so federated
113 - * copies are torn down. Without this, draft/pending would
114 - * broadcast a placeholder Update, private/trash would silently
115 - * leave the federated copy stale, and a custom status would
116 - * fall through without notifying followers at all.
117 - */
118 - $type = ACTIVITYPUB_OBJECT_STATE_FEDERATED === $object_status && ! $is_queryable
119 - ? 'Delete'
120 - : false;
103 + $type = false;
121 104 }
122 105
123 106 // Do not send Activities if `$type` is not set or unknown.
124 107 if ( empty( $type ) ) {
@@ -124,35 +107,15 @@
124 107 if ( empty( $type ) ) {
125 108 return;
126 109 }
127 110
128 - /*
129 - * If the post was already federated and this is a Create, skip.
130 - * The outbox controller already added it to the outbox.
131 - */
132 - if ( ACTIVITYPUB_OBJECT_STATE_FEDERATED === $object_status && 'Create' === $type ) {
133 - return;
134 - }
135 -
136 111 // If the post was never federated before, it should be a Create activity.
137 112 if ( empty( $object_status ) && 'Update' === $type ) {
138 113 $type = 'Create';
139 114 }
140 115
141 - /*
142 - * Resurrection: a soft-deleted post that is back in a publicly
143 - * queryable state must emit Create, not Update. Remote followers
144 - * either dropped the original Create on the Delete fan-out (so
145 - * they need to learn about the post again) or had it cancelled
146 - * before fanning out (so the supersession logic invalidates the
147 - * pending Delete and Create is the correct re-introduction).
148 - */
149 - if ( ACTIVITYPUB_OBJECT_STATE_DELETED === $object_status && 'Update' === $type && $is_queryable ) {
150 - $type = 'Create';
151 - }
152 -
153 - // If the post was federated before but is now non-public, it should be a Delete activity.
154 - if ( ACTIVITYPUB_OBJECT_STATE_FEDERATED === $object_status && ! $is_queryable ) {
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 ) ) {
155 118 $type = 'Delete';
156 119 }
157 120
158 121 add_to_outbox( $post, $type, $post->post_author );