Skip to content

Commit 04e0c36

Browse files
authored
Fix logic errors in Move handler (#2362)
1 parent 8f0c9e2 commit 04e0c36

File tree

3 files changed

+95
-14
lines changed

3 files changed

+95
-14
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: fixed
3+
4+
Fix logic errors in Move handler: remove redundant assignment and fix variable name collision.

includes/handler/class-move.php

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,8 @@ public static function handle_move( $activity, $user_id ) {
5757
$result = null;
5858
$success = false;
5959

60-
/*
61-
* If the new target is followed, but the origin is not,
62-
* everything is fine, so we can return.
63-
*/
64-
if ( ! \is_wp_error( $target_object ) && \is_wp_error( $origin_object ) ) {
65-
$success = false;
66-
} elseif ( \is_wp_error( $target_object ) && ! \is_wp_error( $origin_object ) ) {
60+
// If the origin is followed but the target is not, update the origin to point to the target.
61+
if ( \is_wp_error( $target_object ) && ! \is_wp_error( $origin_object ) ) {
6762
global $wpdb;
6863
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
6964
$wpdb->update(
@@ -77,15 +72,18 @@ public static function handle_move( $activity, $user_id ) {
7772

7873
$success = true;
7974
$result = Remote_Actors::upsert( $target_json );
80-
} elseif ( ! \is_wp_error( $target_object ) && ! \is_wp_error( $origin_object ) ) {
75+
}
76+
77+
// If both the target and origin are followed, merge them.
78+
if ( ! \is_wp_error( $target_object ) && ! \is_wp_error( $origin_object ) ) {
8179
$origin_users = \get_post_meta( $origin_object->ID, Followers::FOLLOWER_META_KEY, false );
8280
$target_users = \get_post_meta( $target_object->ID, Followers::FOLLOWER_META_KEY, false );
8381

8482
// Get all user ids from $origin_users that are not in $target_users.
8583
$users = \array_diff( $origin_users, $target_users );
8684

87-
foreach ( $users as $user_id ) {
88-
\add_post_meta( $target_object->ID, Followers::FOLLOWER_META_KEY, $user_id );
85+
foreach ( $users as $follower_user_id ) {
86+
\add_post_meta( $target_object->ID, Followers::FOLLOWER_META_KEY, $follower_user_id );
8987
}
9088

9189
$success = true;

tests/phpunit/tests/includes/handler/class-test-move.php

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ class Test_Move extends \WP_UnitTestCase {
3333
private $user_id_2;
3434

3535
/**
36-
* Setup the test.
36+
* Set up the test.
3737
*/
3838
public function setUp(): void {
3939
parent::setUp();
40-
$this->user_id = $this->factory->user->create();
41-
$this->user_id_2 = $this->factory->user->create();
40+
$this->user_id = self::factory()->user->create();
41+
$this->user_id_2 = self::factory()->user->create();
4242
}
4343

4444
/**
@@ -125,7 +125,7 @@ public function test_handle_move_with_target_and_origin() {
125125

126126
\wp_delete_post( $updated_follower->ID );
127127

128-
\remove_filter( 'pre_http_request', $filter, 10 );
128+
\remove_filter( 'pre_http_request', $filter );
129129
}
130130

131131
/**
@@ -232,6 +232,85 @@ public function test_handle_move_without_target_or_origin() {
232232
$test_follower->delete();
233233
}
234234

235+
/**
236+
* Test the handle_move method when target exists but origin does not.
237+
*
238+
* This tests the scenario where the new profile is already followed,
239+
* but the old profile is not. In this case, no action should be taken.
240+
*/
241+
public function test_handle_move_with_existing_target_but_missing_origin() {
242+
$target = 'https://example.com/new-profile';
243+
$origin = 'https://example.com/old-profile';
244+
245+
// Create only the target follower, not the origin.
246+
$target_follower = new Actor();
247+
$target_follower->set_inbox( 'https://example.com/new-profile/inbox' );
248+
$target_follower->set_type( 'Person' );
249+
$target_follower->set_id( $target );
250+
$target_follower->set_url( $target );
251+
$target_id = Remote_Actors::upsert( $target_follower );
252+
253+
// Add user ID to target.
254+
\add_post_meta( $target_id, Followers::FOLLOWER_META_KEY, $this->user_id );
255+
256+
$filter = function ( $preempt, $args, $url ) use ( $target, $origin ) {
257+
if ( $url === $target ) {
258+
return array(
259+
'body' => \wp_json_encode(
260+
array(
261+
'type' => 'Person',
262+
'id' => $target,
263+
'url' => $target,
264+
'name' => 'New Profile',
265+
'inbox' => 'https://example.com/new-profile/inbox',
266+
'also_known_as' => array( $origin ),
267+
)
268+
),
269+
'response' => array( 'code' => 200 ),
270+
);
271+
}
272+
if ( $url === $origin ) {
273+
return array(
274+
'body' => \wp_json_encode(
275+
array(
276+
'type' => 'Person',
277+
'id' => $origin,
278+
'url' => $origin,
279+
'name' => 'Old Profile',
280+
'inbox' => 'https://example.com/old-profile/inbox',
281+
'movedTo' => $target,
282+
)
283+
),
284+
'response' => array( 'code' => 200 ),
285+
);
286+
}
287+
return $preempt;
288+
};
289+
290+
// Mock the HTTP request.
291+
\add_filter( 'pre_http_request', $filter, 10, 3 );
292+
293+
$activity = array(
294+
'type' => 'Move',
295+
'actor' => $origin,
296+
'object' => $target,
297+
);
298+
299+
Move::handle_move( $activity, 1 );
300+
301+
// Verify that the target still exists with the same followers.
302+
$target_users = \get_post_meta( $target_id, Followers::FOLLOWER_META_KEY, false );
303+
$this->assertContains( (string) $this->user_id, $target_users );
304+
$this->assertCount( 1, $target_users );
305+
306+
// Verify that no origin follower was created.
307+
$this->assertWPError( Remote_Actors::get_by_uri( $origin ) );
308+
309+
// Cleanup.
310+
\wp_delete_post( $target_id );
311+
\remove_filter( 'pre_http_request', $filter );
312+
}
313+
235314
/**
236315
* Test the handle_move method with an existing target and origin.
237316
*/

0 commit comments

Comments
 (0)