add postaladdress support for the events calendar
Some checks failed
PHP Code Checker / PHP Code Checker (pull_request) Failing after 47s
PHPUnit / PHPUnit – PHP 7.4 (pull_request) Successful in 1m5s
PHPUnit / PHPUnit – PHP 8.0 (pull_request) Successful in 1m4s
PHPUnit / PHPUnit – PHP 8.1 (pull_request) Successful in 1m0s
PHPUnit / PHPUnit – PHP 8.2 (pull_request) Successful in 1m4s
PHPUnit / PHPUnit – PHP 8.3 (pull_request) Successful in 1m6s
PHPUnit / PHPUnit – PHP 8.4 (pull_request) Successful in 1m1s
Some checks failed
PHP Code Checker / PHP Code Checker (pull_request) Failing after 47s
PHPUnit / PHPUnit – PHP 7.4 (pull_request) Successful in 1m5s
PHPUnit / PHPUnit – PHP 8.0 (pull_request) Successful in 1m4s
PHPUnit / PHPUnit – PHP 8.1 (pull_request) Successful in 1m0s
PHPUnit / PHPUnit – PHP 8.2 (pull_request) Successful in 1m4s
PHPUnit / PHPUnit – PHP 8.3 (pull_request) Successful in 1m6s
PHPUnit / PHPUnit – PHP 8.4 (pull_request) Successful in 1m1s
and improve tests
This commit is contained in:
parent
ba9698f36d
commit
cb8c4eac5e
13 changed files with 534 additions and 32 deletions
|
@ -61,7 +61,7 @@
|
||||||
],
|
],
|
||||||
"test-debug": [
|
"test-debug": [
|
||||||
"@prepare-test",
|
"@prepare-test",
|
||||||
"@test-general"
|
"@test-the-events-calendar"
|
||||||
],
|
],
|
||||||
"test-vs-event-list": "phpunit --filter=vs_event_list",
|
"test-vs-event-list": "phpunit --filter=vs_event_list",
|
||||||
"test-the-events-calendar": "phpunit --filter=the_events_calendar",
|
"test-the-events-calendar": "phpunit --filter=the_events_calendar",
|
||||||
|
|
|
@ -56,7 +56,7 @@ abstract class Base {
|
||||||
$post_id = $this->save_event();
|
$post_id = $this->save_event();
|
||||||
|
|
||||||
if ( $post_id ) {
|
if ( $post_id ) {
|
||||||
update_post_meta( $post_id, '_event_bridge_for_activitypub_is_cached', true );
|
update_post_meta( $post_id, '_event_bridge_for_activitypub_is_remote_cached', true );
|
||||||
update_post_meta( $post_id, 'activitypub_content_visibility', constant( 'ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL' ) ?? '' );
|
update_post_meta( $post_id, 'activitypub_content_visibility', constant( 'ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL' ) ?? '' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier;
|
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier;
|
||||||
|
|
||||||
use DateTime;
|
use Tribe__Date_Utils;
|
||||||
|
|
||||||
use function Activitypub\sanitize_url;
|
use function Activitypub\sanitize_url;
|
||||||
|
|
||||||
|
@ -27,25 +27,47 @@ defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
class The_Events_Calendar extends Base {
|
class The_Events_Calendar extends Base {
|
||||||
/**
|
/**
|
||||||
* Get a list of Post IDs of events that have ended.
|
* Map an ActivityStreams Place to the Events Calendar venue.
|
||||||
*
|
*
|
||||||
* @param int $cache_retention_period Additional time buffer in seconds.
|
* @param array $location An ActivityPub location as an associative array.
|
||||||
* @return ?array
|
* @link https://www.w3.org/TR/activitystreams-vocabulary/#dfn-place
|
||||||
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function get_past_events( $cache_retention_period = 0 ): ?array {
|
private function get_venue_args( $location ) {
|
||||||
unset( $cache_retention_period );
|
$args = array(
|
||||||
|
'venue' => $location['name'],
|
||||||
|
'status' => 'publish',
|
||||||
|
);
|
||||||
|
|
||||||
$results = array();
|
if ( is_array( $location['address'] ) && isset( $location['address']['type'] ) && 'PostalAddress' === $location['address']['type'] ) {
|
||||||
|
$mapping = array(
|
||||||
|
'streetAddress' => 'address',
|
||||||
|
'postalCode' => 'zip',
|
||||||
|
'addressLocality' => 'city',
|
||||||
|
'addressState' => 'state',
|
||||||
|
'addressCountry' => 'country',
|
||||||
|
'url' => 'website',
|
||||||
|
);
|
||||||
|
|
||||||
return $results;
|
foreach ( $mapping as $postal_address_key => $venue_key ) {
|
||||||
|
if ( isset( $location['address'][ $postal_address_key ] ) ) {
|
||||||
|
$args[ $venue_key ] = $location['address'][ $postal_address_key ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif ( is_string( $location['address'] ) ) {
|
||||||
|
// Use the address field for a solely text address.
|
||||||
|
$args['address'] = $location['address'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $args;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add venue.
|
* Add venue.
|
||||||
*
|
*
|
||||||
* @param int $post_id The post ID.
|
* @return int|bool $post_id The venues post ID.
|
||||||
*/
|
*/
|
||||||
private function add_venue( $post_id ) {
|
private function add_venue() {
|
||||||
$location = $this->activitypub_event->get_location();
|
$location = $this->activitypub_event->get_location();
|
||||||
|
|
||||||
if ( ! $location ) {
|
if ( ! $location ) {
|
||||||
|
@ -60,6 +82,25 @@ class The_Events_Calendar extends Base {
|
||||||
if ( 'online' === $location['name'] ) {
|
if ( 'online' === $location['name'] ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$post_ids = tribe_events()->search( $location['name'] )->all();
|
||||||
|
|
||||||
|
$post_id = false;
|
||||||
|
|
||||||
|
if ( count( $post_ids ) ) {
|
||||||
|
$post_id = reset( $post_ids );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $post_id && get_post_meta( $post_id, '_event_bridge_for_activitypub_is_remote_cached' ) ) {
|
||||||
|
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();
|
||||||
|
if ( $post ) {
|
||||||
|
$post_id = $post->ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $post_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,6 +116,8 @@ class The_Events_Calendar extends Base {
|
||||||
|
|
||||||
$duration = $this->get_duration();
|
$duration = $this->get_duration();
|
||||||
|
|
||||||
|
$venue_id = $this->add_venue();
|
||||||
|
|
||||||
$args = array(
|
$args = array(
|
||||||
'title' => sanitize_text_field( $this->activitypub_event->get_name() ),
|
'title' => sanitize_text_field( $this->activitypub_event->get_name() ),
|
||||||
'content' => wp_kses_post( $this->activitypub_event->get_content() ),
|
'content' => wp_kses_post( $this->activitypub_event->get_content() ),
|
||||||
|
@ -84,6 +127,11 @@ class The_Events_Calendar extends Base {
|
||||||
'guid' => sanitize_url( $this->activitypub_event->get_id() ),
|
'guid' => sanitize_url( $this->activitypub_event->get_id() ),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ( $venue_id ) {
|
||||||
|
$args['venue'] = $venue_id;
|
||||||
|
$args['VenueID'] = $venue_id;
|
||||||
|
}
|
||||||
|
|
||||||
$tribe_event = new The_Events_Calendar_Event_Repository();
|
$tribe_event = new The_Events_Calendar_Event_Repository();
|
||||||
|
|
||||||
if ( $post_id ) {
|
if ( $post_id ) {
|
||||||
|
@ -99,8 +147,6 @@ class The_Events_Calendar extends Base {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->add_venue( $post->ID );
|
|
||||||
|
|
||||||
// Limit this as a safety measure.
|
// Limit this as a safety measure.
|
||||||
remove_filter( 'wp_revisions_to_keep', array( self::class, 'revisions_to_keep' ) );
|
remove_filter( 'wp_revisions_to_keep', array( self::class, 'revisions_to_keep' ) );
|
||||||
|
|
||||||
|
|
182
includes/activitypub/transmogrifier/class-vs-event-list.php
Normal file
182
includes/activitypub/transmogrifier/class-vs-event-list.php
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ActivityPub Transmogrifier for the VS Event List event plugin.
|
||||||
|
*
|
||||||
|
* Handles converting incoming external ActivityPub events to events of VS Event List.
|
||||||
|
*
|
||||||
|
* @link https://wordpress.org/plugins/very-simple-event-list/
|
||||||
|
* @package Event_Bridge_For_ActivityPub
|
||||||
|
* @since 1.0.0
|
||||||
|
* @license AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier;
|
||||||
|
|
||||||
|
use function Activitypub\sanitize_url;
|
||||||
|
|
||||||
|
// Exit if accessed directly.
|
||||||
|
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ActivityPub Transmogrifier for the VS Event List event plugin.
|
||||||
|
*
|
||||||
|
* Handles converting incoming external ActivityPub events to events of VS Event List.
|
||||||
|
*
|
||||||
|
* @link https://wordpress.org/plugins/very-simple-event-list/
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class VS_Event_List extends Base {
|
||||||
|
/**
|
||||||
|
* Get a list of Post IDs of events that have ended.
|
||||||
|
*
|
||||||
|
* @param int $cache_retention_period Additional time buffer in seconds.
|
||||||
|
* @return ?array
|
||||||
|
*/
|
||||||
|
public static function get_past_events( $cache_retention_period = 0 ): ?array {
|
||||||
|
unset( $cache_retention_period );
|
||||||
|
|
||||||
|
$results = array();
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map an ActivityStreams Place to the Events Calendar venue.
|
||||||
|
*
|
||||||
|
* @param array $location An ActivityPub location as an associative array.
|
||||||
|
* @link https://www.w3.org/TR/activitystreams-vocabulary/#dfn-place
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function get_venue_args( $location ) {
|
||||||
|
$args = array(
|
||||||
|
'venue' => $location['name'],
|
||||||
|
'status' => 'publish',
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( is_array( $location['address'] ) && isset( $location['address']['type'] ) && 'PostalAddress' === $location['address']['type'] ) {
|
||||||
|
$mapping = array(
|
||||||
|
'streetAddress' => 'address',
|
||||||
|
'postalCode' => 'zip',
|
||||||
|
'addressLocality' => 'city',
|
||||||
|
'addressState' => 'state',
|
||||||
|
'addressCountry' => 'country',
|
||||||
|
'url' => 'website',
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ( $mapping as $postal_address_key => $venue_key ) {
|
||||||
|
if ( isset( $location['address'][ $postal_address_key ] ) ) {
|
||||||
|
$args[ $venue_key ] = $location['address'][ $postal_address_key ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif ( is_string( $location['address'] ) ) {
|
||||||
|
// Use the address field for a solely text address.
|
||||||
|
$args['address'] = $location['address'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add venue.
|
||||||
|
*
|
||||||
|
* @return int|bool $post_id The venues post ID.
|
||||||
|
*/
|
||||||
|
private function add_venue() {
|
||||||
|
$location = $this->activitypub_event->get_location();
|
||||||
|
|
||||||
|
if ( ! $location ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! isset( $location['name'] ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback for Gancio instances.
|
||||||
|
if ( 'online' === $location['name'] ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$post_ids = tribe_events()->search( $location['name'] )->all();
|
||||||
|
|
||||||
|
$post_id = false;
|
||||||
|
|
||||||
|
if ( count( $post_ids ) ) {
|
||||||
|
$post_id = reset( $post_ids );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $post_id && get_post_meta( $post_id, '_event_bridge_for_activitypub_is_remote_cached' ) ) {
|
||||||
|
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();
|
||||||
|
if ( $post ) {
|
||||||
|
$post_id = $post->ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $post_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the ActivityPub event object as GatherPress Event.
|
||||||
|
*
|
||||||
|
* @return false|int
|
||||||
|
*/
|
||||||
|
public function save_event() {
|
||||||
|
// Limit this as a safety measure.
|
||||||
|
add_filter( 'wp_revisions_to_keep', array( self::class, 'revisions_to_keep' ) );
|
||||||
|
|
||||||
|
$post_id = $this->get_post_id_from_activitypub_id();
|
||||||
|
|
||||||
|
$duration = $this->get_duration();
|
||||||
|
|
||||||
|
$venue_id = $this->add_venue();
|
||||||
|
|
||||||
|
$args = array(
|
||||||
|
'title' => sanitize_text_field( $this->activitypub_event->get_name() ),
|
||||||
|
'content' => wp_kses_post( $this->activitypub_event->get_content() ),
|
||||||
|
'start_date' => gmdate( 'Y-m-d H:i:s', strtotime( $this->activitypub_event->get_start_time() ) ),
|
||||||
|
'duration' => $duration,
|
||||||
|
'status' => 'publish',
|
||||||
|
'guid' => sanitize_url( $this->activitypub_event->get_id() ),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( $venue_id ) {
|
||||||
|
$args['venue'] = $venue_id;
|
||||||
|
$args['VenueID'] = $venue_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tribe_event = new The_Events_Calendar_Event_Repository();
|
||||||
|
|
||||||
|
if ( $post_id ) {
|
||||||
|
$args['post_title'] = $args['title'];
|
||||||
|
$args['post_content'] = $args['content'];
|
||||||
|
// Update existing GatherPress event post.
|
||||||
|
$post = \Tribe__Events__API::updateEvent( $post_id, $args );
|
||||||
|
} else {
|
||||||
|
$post = $tribe_event->set_args( $args )->create();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! $post ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit this as a safety measure.
|
||||||
|
remove_filter( 'wp_revisions_to_keep', array( self::class, 'revisions_to_keep' ) );
|
||||||
|
|
||||||
|
return $post->ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the events duration in seconds.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function get_duration() {
|
||||||
|
$end_time = $this->activitypub_event->get_end_time();
|
||||||
|
if ( ! $end_time ) {
|
||||||
|
return 2 * HOUR_IN_SECONDS;
|
||||||
|
}
|
||||||
|
return abs( strtotime( $end_time ) - strtotime( $this->activitypub_event->get_start_time() ) );
|
||||||
|
}
|
||||||
|
}
|
|
@ -80,7 +80,7 @@ class Event_Sources {
|
||||||
}
|
}
|
||||||
\register_post_meta(
|
\register_post_meta(
|
||||||
$event_plugin_integration::get_post_type(),
|
$event_plugin_integration::get_post_type(),
|
||||||
'_event_bridge_for_activitypub_is_cached',
|
'_event_bridge_for_activitypub_is_remote_cached',
|
||||||
array(
|
array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'single' => false,
|
'single' => false,
|
||||||
|
@ -89,6 +89,21 @@ class Event_Sources {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$location_post_type = $event_plugin_integration::get_location_post_type();
|
||||||
|
if ( $location_post_type ) {
|
||||||
|
\register_post_meta(
|
||||||
|
$location_post_type,
|
||||||
|
'_event_bridge_for_activitypub_is_remote_cached',
|
||||||
|
array(
|
||||||
|
'type' => 'string',
|
||||||
|
'single' => false,
|
||||||
|
'sanitize_callback' => function ( $value ) {
|
||||||
|
return esc_sql( $value );
|
||||||
|
},
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +183,7 @@ class Event_Sources {
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function is_cached_external_event_post( $post ): bool {
|
public static function is_cached_external_event_post( $post ): bool {
|
||||||
if ( get_post_meta( $post->ID, '_event_bridge_for_activitypub_is_cached', true ) ) {
|
if ( get_post_meta( $post->ID, '_event_bridge_for_activitypub_is_remote_cached', true ) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,15 @@ abstract class Event_Plugin_Integration {
|
||||||
*/
|
*/
|
||||||
abstract public static function get_activitypub_event_transformer( $post ): ActivityPub_Event_Transformer;
|
abstract public static function get_activitypub_event_transformer( $post ): ActivityPub_Event_Transformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In case an event plugin used a custom post type for the locations/venues return it here.
|
||||||
|
*
|
||||||
|
* @return ?string
|
||||||
|
*/
|
||||||
|
public static function get_location_post_type() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the IDs of the admin pages of the plugin.
|
* Returns the IDs of the admin pages of the plugin.
|
||||||
*
|
*
|
||||||
|
|
|
@ -83,19 +83,19 @@ final class GatherPress extends Event_Plugin_Integration implements Feature_Even
|
||||||
/**
|
/**
|
||||||
* Get a list of Post IDs of events that have ended.
|
* Get a list of Post IDs of events that have ended.
|
||||||
*
|
*
|
||||||
* @param int $ended_before_time Filter: only get events that ended before that datetime as unix-time.
|
* @param int $ends_before_time Filter: only get events that ended before that datetime as unix-time.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function get_cached_remote_events( $ended_before_time ): array {
|
public static function get_cached_remote_events( $ends_before_time ): array {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
|
|
||||||
$ended_before_time_string = gmdate( 'Y-m-d H:i:s', $ended_before_time );
|
$ends_before_time_string = gmdate( 'Y-m-d H:i:s', $ends_before_time );
|
||||||
|
|
||||||
$results = $wpdb->get_col(
|
$results = $wpdb->get_col(
|
||||||
$wpdb->prepare(
|
$wpdb->prepare(
|
||||||
"SELECT post_id FROM {$wpdb->prefix}gatherpress_events WHERE datetime_end < %s",
|
"SELECT post_id FROM {$wpdb->prefix}gatherpress_events WHERE datetime_end < %s",
|
||||||
$ended_before_time_string
|
$ends_before_time_string
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ final class GatherPress extends Event_Plugin_Integration implements Feature_Even
|
||||||
if ( $post && 'gatherpress_event' === $post->post_type ) {
|
if ( $post && 'gatherpress_event' === $post->post_type ) {
|
||||||
// Add your custom logic here to decide whether to force the link.
|
// Add your custom logic here to decide whether to force the link.
|
||||||
// For example, force it only if a specific meta field exists.
|
// For example, force it only if a specific meta field exists.
|
||||||
if ( get_post_meta( $post->ID, '_event_bridge_for_activitypub_is_cached', true ) ) {
|
if ( get_post_meta( $post->ID, '_event_bridge_for_activitypub_is_remote_cached', true ) ) {
|
||||||
return true; // Force the online event link.
|
return true; // Force the online event link.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,15 @@ final class The_Events_Calendar extends Event_plugin_Integration implements Feat
|
||||||
return new The_Events_Calendar_Transformer( $post, self::get_event_category_taxonomy() );
|
return new The_Events_Calendar_Transformer( $post, self::get_event_category_taxonomy() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the location/venue post type used by tribe.
|
||||||
|
*
|
||||||
|
* @return ?string
|
||||||
|
*/
|
||||||
|
public static function get_location_post_type() {
|
||||||
|
return class_exists( '\Tribe__Events__Venue' ) ? \Tribe__Events__Venue::POSTTYPE : 'tribe_venue';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the IDs of the admin pages of the plugin.
|
* Returns the IDs of the admin pages of the plugin.
|
||||||
*
|
*
|
||||||
|
@ -88,11 +97,39 @@ final class The_Events_Calendar extends Event_plugin_Integration implements Feat
|
||||||
/**
|
/**
|
||||||
* Get a list of Post IDs of events that have ended.
|
* Get a list of Post IDs of events that have ended.
|
||||||
*
|
*
|
||||||
* @param int $ended_before_time Filter: only get events that ended before that datetime as unix-time.
|
* @param int $ends_before_time Filter to only get events that ended before that datetime as unix-time.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array<int>
|
||||||
*/
|
*/
|
||||||
public static function get_cached_remote_events( $ended_before_time ): array {
|
public static function get_cached_remote_events( $ends_before_time ): array {
|
||||||
return array();
|
add_filter(
|
||||||
|
'tribe_repository_events_apply_modifier_schema_entry',
|
||||||
|
array( self::class, 'add_is_activitypub_remote_cached_to_query' ),
|
||||||
|
10,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
$events = tribe_events()->where( 'ends_before', $ends_before_time )->get_ids();
|
||||||
|
|
||||||
|
remove_filter(
|
||||||
|
'tribe_repository_events_apply_modifier_schema_entry',
|
||||||
|
array( self::class, 'add_is_activitypub_remote_cached_to_query' )
|
||||||
|
);
|
||||||
|
|
||||||
|
return $events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only show remote cached ActivityPub events in Tribe query.
|
||||||
|
*
|
||||||
|
* @param array $schema_entry The current schema entry.
|
||||||
|
* @return array The modified schema entry.
|
||||||
|
*/
|
||||||
|
public static function add_is_activitypub_remote_cached_to_query( $schema_entry ) {
|
||||||
|
$schema_entry['meta_query']['is-remote-cached'] = array(
|
||||||
|
'key' => '_event_bridge_for_activitypub_is_remote_cached',
|
||||||
|
'compare' => 'EXISTS',
|
||||||
|
);
|
||||||
|
return $schema_entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,9 +36,9 @@ interface Feature_Event_Sources {
|
||||||
*
|
*
|
||||||
* Filters the events to include only those that ended before the specified timestamp.
|
* Filters the events to include only those that ended before the specified timestamp.
|
||||||
*
|
*
|
||||||
* @param int $ended_before_time Unix timestamp. Only events ending before this time will be included.
|
* @param int $ends_before_time Unix timestamp. Only events ending before this time will be included.
|
||||||
*
|
*
|
||||||
* @return int[] List of post IDs for events that match the criteria.
|
* @return int[] List of post IDs for events that match the criteria.
|
||||||
*/
|
*/
|
||||||
public static function get_cached_remote_events( $ended_before_time ): array;
|
public static function get_cached_remote_events( $ends_before_time ): array;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Class SampleTest
|
* Class file containing tests for the ActivityPub transformer of the WordPress plugin The Events Calendar.
|
||||||
*
|
*
|
||||||
* @package Event_Bridge_For_ActivityPub
|
* @package Event_Bridge_For_ActivityPub
|
||||||
*/
|
*/
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
namespace Event_Bridge_For_ActivityPup\Tests\ActivityPub\Transformer;
|
namespace Event_Bridge_For_ActivityPup\Tests\ActivityPub\Transformer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sample test case.
|
* Class containing tests for the ActivityPub transformer of the WordPress plugin The Events Calendar.
|
||||||
*/
|
*/
|
||||||
class Test_The_Events_Calendar extends \WP_UnitTestCase {
|
class Test_The_Events_Calendar extends \WP_UnitTestCase {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -132,8 +132,83 @@ class Test_The_Events_Calendar extends \WP_UnitTestCase {
|
||||||
$venue = $venues[0];
|
$venue = $venues[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// $this->assertEquals( $json['object']['location']['address'], $venue->address );
|
$this->assertEquals( $json['object']['location']['address'], $venue->address );
|
||||||
// $this->assertEquals( $json['object']['location']['name'], $venue->post_title );
|
$this->assertEquals( $json['object']['location']['name'], $venue->post_title );
|
||||||
|
|
||||||
|
\remove_filter( 'activitypub_defer_signature_verification', '__return_true' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test receiving event from followed actor.
|
||||||
|
*/
|
||||||
|
public function test_incoming_event_with_postal_address() {
|
||||||
|
\add_filter( 'activitypub_defer_signature_verification', '__return_true' );
|
||||||
|
|
||||||
|
$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 The Events Calendar',
|
||||||
|
'to' => 'https://www.w3.org/ns/activitystreams#Public',
|
||||||
|
'published' => '2020-01-01T00:00:00Z',
|
||||||
|
'location' => array(
|
||||||
|
'type' => 'Place',
|
||||||
|
'name' => 'Fediverse Concert Hall',
|
||||||
|
'address' => array(
|
||||||
|
'type' => 'PostalAddress',
|
||||||
|
'streetAddress' => 'FediStreet 13',
|
||||||
|
'postalCode' => '1337',
|
||||||
|
'addressLocality' => 'Feditown',
|
||||||
|
'addressState' => 'Fediverse State',
|
||||||
|
'addressCountry' => 'Fediverse World',
|
||||||
|
'url' => 'https://fedidevs.org/',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$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() );
|
||||||
|
|
||||||
|
// Check if post has been created.
|
||||||
|
$events = tribe_get_events();
|
||||||
|
|
||||||
|
$this->assertEquals( 1, count( $events ) );
|
||||||
|
|
||||||
|
// Initialize new GatherPress Event object.
|
||||||
|
$event = tribe_get_event( $events[0] );
|
||||||
|
|
||||||
|
$this->assertEquals( $json['object']['name'], $event->post_title );
|
||||||
|
$this->assertEquals( $json['object']['startTime'], $event->dates->start->format( 'Y-m-d\TH:i:s\Z' ) );
|
||||||
|
$this->assertEquals( $json['object']['endTime'], $event->dates->end->format( 'Y-m-d\TH:i:s\Z' ) );
|
||||||
|
|
||||||
|
$venues = $event->venues;
|
||||||
|
// Get first venue. We currently only support a single venue.
|
||||||
|
if ( $venues instanceof \Tribe\Events\Collections\Lazy_Post_Collection ) {
|
||||||
|
$venue = $venues->first();
|
||||||
|
} elseif ( empty( $this->wp_object->venues ) || ! empty( $this->wp_object->venues[0] ) ) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
$venue = $venues[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals( $json['object']['location']['name'], $venue->post_title );
|
||||||
|
$this->assertEquals( $json['object']['location']['address']['streetAddress'], $venue->address );
|
||||||
|
$this->assertEquals( $json['object']['location']['address']['postalCode'], $venue->zip );
|
||||||
|
$this->assertEquals( $json['object']['location']['address']['addressLocality'], $venue->city );
|
||||||
|
$this->assertEquals( $json['object']['location']['address']['addressState'], $venue->state );
|
||||||
|
$this->assertEquals( $json['object']['location']['address']['addressCountry'], $venue->country );
|
||||||
|
$this->assertEquals( $json['object']['location']['address']['url'], $venue->website );
|
||||||
|
|
||||||
\remove_filter( 'activitypub_defer_signature_verification', '__return_true' );
|
\remove_filter( 'activitypub_defer_signature_verification', '__return_true' );
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,7 +209,6 @@ class Test_Event_Sources extends \WP_UnitTestCase {
|
||||||
\remove_filter( 'activitypub_defer_signature_verification', '__return_true' );
|
\remove_filter( 'activitypub_defer_signature_verification', '__return_true' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test receiving event from actor we do not follow.
|
* Test receiving event from actor we do not follow.
|
||||||
*/
|
*/
|
||||||
|
|
139
tests/includes/integrations/class-test-the-events-calendar.php
Normal file
139
tests/includes/integrations/class-test-the-events-calendar.php
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Test file for the Transmogrifier (import of ActivityPub Event objects) of GatherPress.
|
||||||
|
*
|
||||||
|
* @package Event_Bridge_For_ActivityPub
|
||||||
|
* @since 1.0.0
|
||||||
|
* @license AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Event_Bridge_For_ActivityPub\Tests\Integrations;
|
||||||
|
|
||||||
|
use Event_Bridge_For_ActivityPup\Tests\ActivityPub\Transformer\Test_The_Events_Calendar as TRIBE_Transformer_Test;
|
||||||
|
use Event_Bridge_For_ActivityPub\Integrations\The_Events_Calendar;
|
||||||
|
|
||||||
|
use WP_REST_Request;
|
||||||
|
use WP_REST_Server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for the Transmogrifier (import of ActivityPub Event objects) of GatherPress.
|
||||||
|
*
|
||||||
|
* @coversDefaultClass \Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier\The_Events_Calendar
|
||||||
|
*/
|
||||||
|
class Test_The_Events_Calendar extends \WP_UnitTestCase {
|
||||||
|
const FOLLOWED_ACTOR = array(
|
||||||
|
'id' => '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 ( ! class_exists( '\Tribe__Events__Main' ) ) {
|
||||||
|
self::markTestSkipped( 'The Events Calendar 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\The_Events_Calendar::class
|
||||||
|
);
|
||||||
|
\update_option( 'activitypub_actor_mode', ACTIVITYPUB_BLOG_MODE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tear down the test.
|
||||||
|
*/
|
||||||
|
public function tear_down() {
|
||||||
|
\delete_option( 'permalink_structure' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 The Events Calendar',
|
||||||
|
'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() );
|
||||||
|
|
||||||
|
// Check if post has been created.
|
||||||
|
$events = tribe_get_events();
|
||||||
|
$this->assertEquals( 1, count( $events ) );
|
||||||
|
|
||||||
|
// Create a The Events Calendar Event without content.
|
||||||
|
$wp_object = tribe_events()
|
||||||
|
->set_args( TRIBE_Transformer_Test::MOCKUP_EVENTS['minimal_event'] )
|
||||||
|
->create();
|
||||||
|
|
||||||
|
$this->assertNotEquals( false, $wp_object );
|
||||||
|
// Check if we now have two tribe events.
|
||||||
|
$events = tribe_get_events();
|
||||||
|
$this->assertEquals( 2, count( $events ) );
|
||||||
|
|
||||||
|
$events = The_Events_Calendar::get_cached_remote_events( time() + MONTH_IN_SECONDS );
|
||||||
|
$this->assertEquals( 1, count( $events ) );
|
||||||
|
$this->assertEquals( $json['object']['id'], get_post( $events[0] )->guid );
|
||||||
|
|
||||||
|
$events = The_Events_Calendar::get_cached_remote_events( time() - WEEK_IN_SECONDS );
|
||||||
|
$this->assertEquals( 0, count( $events ) );
|
||||||
|
|
||||||
|
\remove_filter( 'activitypub_defer_signature_verification', '__return_true' );
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue