From d7cfcee71b61302d573709a04ea1f8a2c2638bc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Mon, 23 Dec 2024 11:49:18 +0100 Subject: [PATCH] fix gatherpress getting remote past events --- composer.json | 2 +- docker-compose.yml | 2 + .../class-the-events-calendar.php | 2 +- .../transmogrifier/class-vs-event-list.php | 2 +- includes/integrations/class-gatherpress.php | 23 ++- .../transformer/class-test-gatherpress.php | 9 +- .../transmogrifier/class-test-gatherpress.php | 7 + .../integrations/class-test-gatherpress.php | 154 ++++++++++++++++++ 8 files changed, 192 insertions(+), 9 deletions(-) create mode 100644 tests/includes/integrations/class-test-gatherpress.php diff --git a/composer.json b/composer.json index 09cd0ed..06122c9 100644 --- a/composer.json +++ b/composer.json @@ -61,7 +61,7 @@ ], "test-debug": [ "@prepare-test", - "@test-the-events-calendar" + "@test-gatherpress" ], "test-vs-event-list": "phpunit --filter=vs_event_list", "test-the-events-calendar": "phpunit --filter=the_events_calendar", diff --git a/docker-compose.yml b/docker-compose.yml index c95f996..cab44cb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,6 +33,8 @@ services: interval: 1s timeout: 5s retries: 10 + ports: + - "3306:3306" test-php: build: diff --git a/includes/activitypub/transmogrifier/class-the-events-calendar.php b/includes/activitypub/transmogrifier/class-the-events-calendar.php index 559dfb8..2c12d68 100644 --- a/includes/activitypub/transmogrifier/class-the-events-calendar.php +++ b/includes/activitypub/transmogrifier/class-the-events-calendar.php @@ -91,7 +91,7 @@ class The_Events_Calendar extends Base { $post_id = reset( $post_ids ); } - if ( $post_id && get_post_meta( $post_id, '_event_bridge_for_activitypub_is_remote_cached' ) ) { + if ( $post_id && get_post_meta( $post_id, '_event_bridge_for_activitypub_is_remote_cached', true ) ) { tribe_venues()->where( 'id', $post_id )->set_args( $this->get_venue_args( $location ) )->save()[0]; } else { $post = tribe_venues()->set_args( $this->get_venue_args( $location ) )->create(); diff --git a/includes/activitypub/transmogrifier/class-vs-event-list.php b/includes/activitypub/transmogrifier/class-vs-event-list.php index 31d33ac..f1731d5 100644 --- a/includes/activitypub/transmogrifier/class-vs-event-list.php +++ b/includes/activitypub/transmogrifier/class-vs-event-list.php @@ -105,7 +105,7 @@ class VS_Event_List extends Base { $post_id = reset( $post_ids ); } - if ( $post_id && get_post_meta( $post_id, '_event_bridge_for_activitypub_is_remote_cached' ) ) { + if ( $post_id && get_post_meta( $post_id, '_event_bridge_for_activitypub_is_remote_cached', true ) ) { tribe_venues()->where( 'id', $post_id )->set_args( $this->get_venue_args( $location ) )->save()[0]; } else { $post = tribe_venues()->set_args( $this->get_venue_args( $location ) )->create(); diff --git a/includes/integrations/class-gatherpress.php b/includes/integrations/class-gatherpress.php index 3b07487..3a5c5ed 100644 --- a/includes/integrations/class-gatherpress.php +++ b/includes/integrations/class-gatherpress.php @@ -92,18 +92,31 @@ final class GatherPress extends Event_Plugin_Integration implements Feature_Even $ends_before_time_string = gmdate( 'Y-m-d H:i:s', $ends_before_time ); - $results = $wpdb->get_col( + $results = $wpdb->get_results( $wpdb->prepare( - "SELECT post_id FROM {$wpdb->prefix}gatherpress_events WHERE datetime_end < %s", + "SELECT DISTINCT {$wpdb->prefix}posts.ID + FROM {$wpdb->prefix}posts + LEFT JOIN {$wpdb->prefix}gatherpress_events + ON {$wpdb->prefix}posts.ID = {$wpdb->prefix}gatherpress_events.post_id + LEFT JOIN {$wpdb->prefix}postmeta + ON {$wpdb->prefix}posts.ID = {$wpdb->prefix}postmeta.post_id + WHERE {$wpdb->prefix}posts.post_type = 'gatherpress_event' + AND {$wpdb->prefix}posts.post_status = 'publish' + AND {$wpdb->prefix}gatherpress_events.datetime_end_gmt <= %s + AND {$wpdb->prefix}postmeta.meta_key = '_event_bridge_for_activitypub_is_remote_cached' + ", $ends_before_time_string - ) + ), + ARRAY_N ); - return $results; + $post_ids = array_column( $results, 0 ); + + return $post_ids; } /** - * Init function. + * Init function: force displaying online event link for federated events. */ public static function init() { \add_filter( diff --git a/tests/includes/activitypub/transformer/class-test-gatherpress.php b/tests/includes/activitypub/transformer/class-test-gatherpress.php index b7d0a8f..e463e12 100644 --- a/tests/includes/activitypub/transformer/class-test-gatherpress.php +++ b/tests/includes/activitypub/transformer/class-test-gatherpress.php @@ -32,6 +32,13 @@ class Test_GatherPress extends \WP_UnitTestCase { _delete_all_posts(); } + /** + * Tear down the test. + */ + public function tear_down() { + _delete_all_posts(); + } + /** * Test that the right transformer gets applied. */ @@ -48,7 +55,7 @@ class Test_GatherPress extends \WP_UnitTestCase { // Mock GatherPress Event. $post_id = wp_insert_post( array( - 'post_title' => 'Unit Test Event', + 'post_title' => 'Test Event for transformer class.', 'post_type' => 'gatherpress_event', 'post_content' => 'Unit Test description.', 'post_status' => 'publish', diff --git a/tests/includes/activitypub/transmogrifier/class-test-gatherpress.php b/tests/includes/activitypub/transmogrifier/class-test-gatherpress.php index 59fdc36..3ae578c 100644 --- a/tests/includes/activitypub/transmogrifier/class-test-gatherpress.php +++ b/tests/includes/activitypub/transmogrifier/class-test-gatherpress.php @@ -81,6 +81,13 @@ class Test_GatherPress extends \WP_UnitTestCase { \update_option( 'activitypub_actor_mode', ACTIVITYPUB_BLOG_MODE ); } + /** + * Purge gatherpress custom events table. + */ + public static function delete_all_gatherpress_events() { + global $wpdb; + } + /** * Tear down the test. */ diff --git a/tests/includes/integrations/class-test-gatherpress.php b/tests/includes/integrations/class-test-gatherpress.php new file mode 100644 index 0000000..8b2ba1f --- /dev/null +++ b/tests/includes/integrations/class-test-gatherpress.php @@ -0,0 +1,154 @@ + 'https://remote.example/@organizer', + 'type' => 'Person', + 'inbox' => 'https://remote.example/@organizer/inbox', + 'outbox' => 'https://remote.example/@organizer/outbox', + 'name' => 'The Organizer', + 'summary' => 'Just a random organizer of events in the Fediverse', + ); + + /** + * REST Server. + * + * @var WP_REST_Server + */ + protected $server; + + /** + * Set up the test. + */ + public function set_up() { + if ( ! defined( 'GATHERPRESS_CORE_FILE' ) ) { + self::markTestSkipped( 'GatherPress plugin is not active.' ); + } + + \add_option( 'permalink_structure', '/%postname%/' ); + + global $wp_rest_server; + $wp_rest_server = new WP_REST_Server(); + $this->server = $wp_rest_server; + + do_action( 'rest_api_init' ); + + \Activitypub\Rest\Server::add_hooks(); + + // Make sure that ActivityPub support is enabled for The Events Calendar. + $aec = \Event_Bridge_For_ActivityPub\Setup::get_instance(); + $aec->activate_activitypub_support_for_active_event_plugins(); + + // Add event source (ActivityPub follower). + _delete_all_posts(); + \Event_Bridge_For_ActivityPub\ActivityPub\Model\Event_Source::init_from_array( self::FOLLOWED_ACTOR )->save(); + + \update_option( 'event_bridge_for_activitypub_event_sources_active', true ); + \update_option( + 'event_bridge_for_activitypub_integration_used_for_event_sources_feature', + \Event_Bridge_For_ActivityPub\Integrations\GatherPress::class + ); + \update_option( 'activitypub_actor_mode', ACTIVITYPUB_BLOG_MODE ); + } + + /** + * Tear down the test. + */ + public function tear_down() { + \delete_option( 'permalink_structure' ); + } + + public static function get_all_posts() { + global $wpdb; + + return $wpdb->get_results( "SELECT ID, post_type from {$wpdb->posts}", ARRAY_A ); + } + + /** + * Test receiving event from followed actor. + */ + public function test_getting_past_remote_events() { + \add_filter( 'activitypub_defer_signature_verification', '__return_true' ); + + // Receive an federated event. + $json = array( + 'id' => 'https://remote.example/@organizer/events/new-year-party#create', + 'type' => 'Create', + 'actor' => 'https://remote.example/@organizer', + 'object' => array( + 'id' => 'https://remote.example/@organizer/events/new-year-party', + 'type' => 'Event', + 'startTime' => \gmdate( 'Y-m-d\TH:i:s\Z', time() + WEEK_IN_SECONDS ), + 'endTime' => \gmdate( 'Y-m-d\TH:i:s\Z', time() + WEEK_IN_SECONDS + HOUR_IN_SECONDS ), + 'name' => 'Fediverse Party for GatherPress', + 'to' => 'https://www.w3.org/ns/activitystreams#Public', + 'published' => '2020-01-01T00:00:00Z', + 'location' => array( + 'type' => 'Place', + 'name' => 'Fediverse Concert Hall', + 'address' => 'Fedistreet 13, Feditown 1337', + ), + ), + ); + + $request = new WP_REST_Request( 'POST', '/activitypub/1.0/users/0/inbox' ); + $request->set_header( 'Content-Type', 'application/activity+json' ); + $request->set_body( \wp_json_encode( $json ) ); + + // Dispatch the request. + $response = \rest_do_request( $request ); + $this->assertEquals( 202, $response->get_status() ); + + // Mock local GatherPress Event. + $post_id = wp_insert_post( + array( + 'post_title' => 'Locally created GatherPress event', + 'post_type' => 'gatherpress_event', + 'post_content' => 'Unit Test description.', + 'post_status' => 'publish', + ) + ); + $event = new \GatherPress\Core\Event( $post_id ); + $params = array( + 'datetime_start' => '+10 days 15:00:00', + 'datetime_end' => '+10 days 16:00:00', + 'timezone' => \wp_timezone_string(), + ); + $event->save_datetimes( $params ); + + $this->assertNotEquals( false, $post_id ); + + // Check if we now have two tribe events. + + $query = \GatherPress\Core\Event_Query::get_instance(); + $query->get_past_events(); + + $events = GatherPress::get_cached_remote_events( time() + MONTH_IN_SECONDS ); + $this->assertEquals( 1, count( $events ) ); + $this->assertEquals( $json['object']['id'], get_post( $events[0] )->guid ); + + $events = GatherPress::get_cached_remote_events( time() - WEEK_IN_SECONDS ); + $this->assertEquals( 0, count( $events ) ); + + \remove_filter( 'activitypub_defer_signature_verification', '__return_true' ); + } +}