Add transmogrifier and tests for vs event list
All checks were successful
PHP Code Checker / PHP Code Checker (pull_request) Successful in 48s
PHPUnit / PHPUnit – PHP 7.4 (pull_request) Successful in 1m4s
PHPUnit / PHPUnit – PHP 8.0 (pull_request) Successful in 1m6s
PHPUnit / PHPUnit – PHP 8.1 (pull_request) Successful in 1m2s
PHPUnit / PHPUnit – PHP 8.2 (pull_request) Successful in 1m6s
PHPUnit / PHPUnit – PHP 8.3 (pull_request) Successful in 1m6s
PHPUnit / PHPUnit – PHP 8.4 (pull_request) Successful in 1m5s
All checks were successful
PHP Code Checker / PHP Code Checker (pull_request) Successful in 48s
PHPUnit / PHPUnit – PHP 7.4 (pull_request) Successful in 1m4s
PHPUnit / PHPUnit – PHP 8.0 (pull_request) Successful in 1m6s
PHPUnit / PHPUnit – PHP 8.1 (pull_request) Successful in 1m2s
PHPUnit / PHPUnit – PHP 8.2 (pull_request) Successful in 1m6s
PHPUnit / PHPUnit – PHP 8.3 (pull_request) Successful in 1m6s
PHPUnit / PHPUnit – PHP 8.4 (pull_request) Successful in 1m5s
This commit is contained in:
parent
460b223920
commit
633a5332d1
16 changed files with 455 additions and 119 deletions
|
@ -61,7 +61,7 @@
|
||||||
],
|
],
|
||||||
"test-debug": [
|
"test-debug": [
|
||||||
"@prepare-test",
|
"@prepare-test",
|
||||||
"@test-gatherpress"
|
"@test-vs-event-list"
|
||||||
],
|
],
|
||||||
"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",
|
||||||
|
|
|
@ -53,7 +53,6 @@ class Event_Sources {
|
||||||
*/
|
*/
|
||||||
public static function init() {
|
public static function init() {
|
||||||
self::register_post_type();
|
self::register_post_type();
|
||||||
\add_filter( 'allowed_redirect_hosts', array( self::class, 'add_event_sources_hosts_to_allowed_redirect_hosts' ) );
|
|
||||||
\add_action( 'event_bridge_for_activitypub_follow', array( self::class, 'activitypub_follow_actor' ), 10, 1 );
|
\add_action( 'event_bridge_for_activitypub_follow', array( self::class, 'activitypub_follow_actor' ), 10, 1 );
|
||||||
\add_action( 'event_bridge_for_activitypub_unfollow', array( self::class, 'activitypub_unfollow_actor' ), 10, 1 );
|
\add_action( 'event_bridge_for_activitypub_unfollow', array( self::class, 'activitypub_unfollow_actor' ), 10, 1 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,13 @@ class Event_Source extends Actor {
|
||||||
return $icon;
|
return $icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the Post-IDs of all events cached by this event source.
|
||||||
|
*/
|
||||||
|
public static function get_cached_events(): array {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the WordPress post which stores the Event Source by the ActivityPub actor id of the event source.
|
* Get the WordPress post which stores the Event Source by the ActivityPub actor id of the event source.
|
||||||
*
|
*
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier;
|
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier;
|
||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
|
use Event_Bridge_For_ActivityPub\Integrations\GatherPress as IntegrationsGatherPress;
|
||||||
|
|
||||||
use function Activitypub\sanitize_url;
|
use function Activitypub\sanitize_url;
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ class GatherPress extends Base {
|
||||||
|
|
||||||
// Add the tags as terms to the post.
|
// Add the tags as terms to the post.
|
||||||
if ( ! empty( $tag_names ) ) {
|
if ( ! empty( $tag_names ) ) {
|
||||||
wp_set_object_terms( $post_id, $tag_names, 'gatherpress_topic', true );
|
wp_set_object_terms( $post_id, $tag_names, IntegrationsGatherPress::get_event_category_taxonomy(), true );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier;
|
namespace Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier;
|
||||||
|
|
||||||
|
use Event_Bridge_For_ActivityPub\Integrations\VS_Event_List as IntegrationsVS_Event_List;
|
||||||
|
|
||||||
use function Activitypub\sanitize_url;
|
use function Activitypub\sanitize_url;
|
||||||
|
|
||||||
// Exit if accessed directly.
|
// Exit if accessed directly.
|
||||||
|
@ -27,94 +29,67 @@ defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
class VS_Event_List extends Base {
|
class VS_Event_List extends Base {
|
||||||
/**
|
/**
|
||||||
* Get a list of Post IDs of events that have ended.
|
* Extract location and address as string.
|
||||||
*
|
*
|
||||||
* @param int $cache_retention_period Additional time buffer in seconds.
|
* @param ?array $location The ActivitySTreams location as an associative array.
|
||||||
* @return ?array
|
* @return string The location and address formatted as a single string.
|
||||||
*/
|
*/
|
||||||
public static function get_past_events( $cache_retention_period = 0 ): ?array {
|
private function get_location_as_string( $location ): string {
|
||||||
unset( $cache_retention_period );
|
$location_string = '';
|
||||||
|
|
||||||
$results = array();
|
// Return empty string when location is not an associative array.
|
||||||
|
if ( is_null( $location ) || ! is_array( $location ) ) {
|
||||||
|
return $location_string;
|
||||||
|
}
|
||||||
|
|
||||||
return $results;
|
if ( ! isset( $location['type'] ) || 'Place' !== $location['type'] ) {
|
||||||
|
return $location_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add name of the location.
|
||||||
|
if ( isset( $location['name'] ) ) {
|
||||||
|
$location_string .= $location['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add delimiter between name and address if both are set.
|
||||||
|
if ( isset( $location['name'] ) && isset( $location['address'] ) ) {
|
||||||
|
$location_string .= ' – ';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add address.
|
||||||
|
if ( isset( $location['address'] ) ) {
|
||||||
|
$location_string .= $this->address_to_string( $location['address'] );
|
||||||
|
}
|
||||||
|
return $location_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map an ActivityStreams Place to the Events Calendar venue.
|
* Add tags to post.
|
||||||
*
|
*
|
||||||
* @param array $location An ActivityPub location as an associative array.
|
* @param int $post_id The post ID.
|
||||||
* @link https://www.w3.org/TR/activitystreams-vocabulary/#dfn-place
|
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
private function get_venue_args( $location ) {
|
private function add_tags_to_post( $post_id ) {
|
||||||
$args = array(
|
$tags_array = $this->activitypub_event->get_tag();
|
||||||
'venue' => $location['name'],
|
|
||||||
'status' => 'publish',
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( is_array( $location['address'] ) && isset( $location['address']['type'] ) && 'PostalAddress' === $location['address']['type'] ) {
|
// Ensure the input is valid.
|
||||||
$mapping = array(
|
if ( empty( $tags_array ) || ! is_array( $tags_array ) || ! $post_id ) {
|
||||||
'streetAddress' => 'address',
|
return false;
|
||||||
'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;
|
// Extract and process tag names.
|
||||||
}
|
$tag_names = array();
|
||||||
|
foreach ( $tags_array as $tag ) {
|
||||||
/**
|
if ( isset( $tag['name'] ) && 'Hashtag' === $tag['type'] ) {
|
||||||
* Add venue.
|
$tag_names[] = ltrim( $tag['name'], '#' ); // Remove the '#' from the name.
|
||||||
*
|
|
||||||
* @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', 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();
|
|
||||||
if ( $post ) {
|
|
||||||
$post_id = $post->ID;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $post_id;
|
// Add the tags as terms to the post.
|
||||||
|
if ( ! empty( $tag_names ) ) {
|
||||||
|
wp_set_object_terms( $post_id, $tag_names, IntegrationsVS_Event_List::get_event_category_taxonomy(), true );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,59 +99,62 @@ class VS_Event_List extends Base {
|
||||||
*/
|
*/
|
||||||
public function save_event() {
|
public function save_event() {
|
||||||
// Limit this as a safety measure.
|
// Limit this as a safety measure.
|
||||||
add_filter( 'wp_revisions_to_keep', array( self::class, 'revisions_to_keep' ) );
|
\add_filter( 'wp_revisions_to_keep', array( self::class, 'revisions_to_keep' ) );
|
||||||
|
|
||||||
$post_id = $this->get_post_id_from_activitypub_id();
|
$post_id = $this->get_post_id_from_activitypub_id();
|
||||||
|
|
||||||
$duration = $this->get_duration();
|
|
||||||
|
|
||||||
$venue_id = $this->add_venue();
|
|
||||||
|
|
||||||
$args = array(
|
$args = array(
|
||||||
'title' => sanitize_text_field( $this->activitypub_event->get_name() ),
|
'post_title' => \sanitize_text_field( $this->activitypub_event->get_name() ),
|
||||||
'content' => wp_kses_post( $this->activitypub_event->get_content() ),
|
'post_type' => \Event_Bridge_For_ActivityPub\Integrations\VS_Event_List::get_post_type(),
|
||||||
'start_date' => gmdate( 'Y-m-d H:i:s', strtotime( $this->activitypub_event->get_start_time() ) ),
|
'post_content' => \wp_kses_post( $this->activitypub_event->get_content() ?? '' ),
|
||||||
'duration' => $duration,
|
'post_excerpt' => \wp_kses_post( $this->activitypub_event->get_summary() ?? '' ),
|
||||||
'status' => 'publish',
|
'post_status' => 'publish',
|
||||||
'guid' => sanitize_url( $this->activitypub_event->get_id() ),
|
'guid' => \sanitize_url( $this->activitypub_event->get_id() ),
|
||||||
|
'meta_input' => array(
|
||||||
|
'event-start-date' => \strtotime( $this->activitypub_event->get_start_time() ),
|
||||||
|
'event-link' => \sanitize_url( $this->activitypub_event->get_url() ),
|
||||||
|
'event-link-label' => \sanitize_text_field( __( 'Original Website', 'event-bridge-for-activitypub' ) ),
|
||||||
|
'event-link-target' => 'yes', // Open in new window.
|
||||||
|
'event-link-title' => 'no', // Whether to redirect event title to original source.
|
||||||
|
'event-link-image' => 'no', // Whether to redirect events featured image to original source.
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $venue_id ) {
|
// Add end time.
|
||||||
$args['venue'] = $venue_id;
|
$end_time = $this->activitypub_event->get_end_time();
|
||||||
$args['VenueID'] = $venue_id;
|
if ( $end_time ) {
|
||||||
|
$args['meta_input']['event-date'] = \strtotime( $end_time );
|
||||||
}
|
}
|
||||||
|
|
||||||
$tribe_event = new The_Events_Calendar_Event_Repository();
|
// Maybe add location.
|
||||||
|
$location = $this->get_location_as_string( $this->activitypub_event->get_location() );
|
||||||
|
if ( $location ) {
|
||||||
|
$args['meta_input']['event-location'] = $location;
|
||||||
|
}
|
||||||
|
|
||||||
if ( $post_id ) {
|
if ( $post_id ) {
|
||||||
$args['post_title'] = $args['title'];
|
// Update existing event post.
|
||||||
$args['post_content'] = $args['content'];
|
$args['ID'] = $post_id;
|
||||||
// Update existing GatherPress event post.
|
$post_id = \wp_update_post( $args );
|
||||||
$post = \Tribe__Events__API::updateEvent( $post_id, $args );
|
|
||||||
} else {
|
} else {
|
||||||
$post = $tribe_event->set_args( $args )->create();
|
// Insert new event post.
|
||||||
|
$post_id = \wp_insert_post( $args );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! $post ) {
|
if ( ! $post_id || \is_wp_error( $post_id ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Insert featured image.
|
||||||
|
$image = $this->get_featured_image();
|
||||||
|
self::set_featured_image_with_alt( $post_id, $image['url'], $image['alt'] );
|
||||||
|
|
||||||
|
// Add hashtags.
|
||||||
|
$this->add_tags_to_post( $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' ) );
|
||||||
|
|
||||||
return $post->ID;
|
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() ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,9 @@ class Event_Sources {
|
||||||
// Register the Event Sources Collection which takes care of managing the event sources.
|
// Register the Event Sources Collection which takes care of managing the event sources.
|
||||||
\add_action( 'init', array( Event_Sources_Collection::class, 'init' ) );
|
\add_action( 'init', array( Event_Sources_Collection::class, 'init' ) );
|
||||||
|
|
||||||
|
// Allow wp_safe_redirect to all followed event sources hosts.
|
||||||
|
\add_filter( 'allowed_redirect_hosts', array( self::class, 'add_event_sources_hosts_to_allowed_redirect_hosts' ) );
|
||||||
|
|
||||||
// Register handlers for incoming activities to the ActivityPub plugin, e.g. incoming `Event` objects.
|
// Register handlers for incoming activities to the ActivityPub plugin, e.g. incoming `Event` objects.
|
||||||
\add_action( 'activitypub_register_handlers', array( Handler::class, 'register_handlers' ) );
|
\add_action( 'activitypub_register_handlers', array( Handler::class, 'register_handlers' ) );
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ class Settings {
|
||||||
'event-bridge-for-activitypub',
|
'event-bridge-for-activitypub',
|
||||||
'event_bridge_for_activitypub_integration_used_for_event_sources_feature',
|
'event_bridge_for_activitypub_integration_used_for_event_sources_feature',
|
||||||
array(
|
array(
|
||||||
'type' => 'array',
|
'type' => 'string',
|
||||||
'description' => \__( 'Define which plugin/integration is used for the event sources feature', 'event-bridge-for-activitypub' ),
|
'description' => \__( 'Define which plugin/integration is used for the event sources feature', 'event-bridge-for-activitypub' ),
|
||||||
'default' => array(),
|
'default' => array(),
|
||||||
'sanitize_callback' => array( self::class, 'sanitize_event_plugin_integration_used_for_event_sources' ),
|
'sanitize_callback' => array( self::class, 'sanitize_event_plugin_integration_used_for_event_sources' ),
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
namespace Event_Bridge_For_ActivityPub\Integrations;
|
namespace Event_Bridge_For_ActivityPub\Integrations;
|
||||||
|
|
||||||
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\VS_Event_List as VS_Event_List_Transformer;
|
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\VS_Event_List as VS_Event_List_Transformer;
|
||||||
|
use Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier\VS_Event_List as VS_Event_List_Transmogrifier;
|
||||||
|
use WP_Query;
|
||||||
|
|
||||||
// Exit if accessed directly.
|
// Exit if accessed directly.
|
||||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||||
|
@ -25,7 +27,7 @@ defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
final class VS_Event_List extends Event_Plugin_Integration {
|
final class VS_Event_List extends Event_Plugin_Integration implements Feature_Event_Sources {
|
||||||
/**
|
/**
|
||||||
* Returns the full plugin file.
|
* Returns the full plugin file.
|
||||||
*
|
*
|
||||||
|
@ -71,4 +73,45 @@ final class VS_Event_List extends Event_Plugin_Integration {
|
||||||
public static function get_activitypub_event_transformer( $post ): VS_Event_List_Transformer {
|
public static function get_activitypub_event_transformer( $post ): VS_Event_List_Transformer {
|
||||||
return new VS_Event_List_Transformer( $post, self::get_event_category_taxonomy() );
|
return new VS_Event_List_Transformer( $post, self::get_event_category_taxonomy() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Transmogrifier for The_Events_Calendar.
|
||||||
|
*/
|
||||||
|
public static function get_transmogrifier(): VS_Event_List_Transmogrifier {
|
||||||
|
return new VS_Event_List_Transmogrifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of Post IDs of events that have ended.
|
||||||
|
*
|
||||||
|
* @param int $ends_before_time Filter to only get events that ended before that datetime as unix-time.
|
||||||
|
*
|
||||||
|
* @return array<int>
|
||||||
|
*/
|
||||||
|
public static function get_cached_remote_events( $ends_before_time ): array {
|
||||||
|
$args = array(
|
||||||
|
'post_type' => 'event',
|
||||||
|
'posts_per_page' => -1,
|
||||||
|
'fields' => 'ids',
|
||||||
|
'meta_query' => array(
|
||||||
|
'relation' => 'AND',
|
||||||
|
array(
|
||||||
|
'key' => '_event_bridge_for_activitypub_is_remote_cached',
|
||||||
|
'compare' => 'EXISTS',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'key' => 'event-date',
|
||||||
|
'value' => $ends_before_time,
|
||||||
|
'type' => 'NUMERIC',
|
||||||
|
'compare' => '<',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$query = new WP_Query( $args );
|
||||||
|
|
||||||
|
$post_ids = $query->posts;
|
||||||
|
|
||||||
|
return $post_ids;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ $current_category_mapping = \get_option( 'event_bridge_for_activitypub_ev
|
||||||
>
|
>
|
||||||
<?php
|
<?php
|
||||||
foreach ( $event_plugins_supporting_event_sources as $event_plugin_class_name => $event_plugin_name ) {
|
foreach ( $event_plugins_supporting_event_sources as $event_plugin_class_name => $event_plugin_name ) {
|
||||||
echo '<option value="' . esc_attr( $event_plugin_class_name ) . '" ' . selected( $event_plugin_class_name, $event_plugin, true ) . '>' . esc_attr( $event_plugin_name ) . '</option>';
|
echo '<option value="' . esc_attr( $event_plugin_class_name ) . '" ' . selected( $event_plugin_class_name, get_option( 'event_bridge_for_activitypub_integration_used_for_event_sources_feature', $event_plugin ), true ) . '>' . esc_attr( $event_plugin_name ) . '</option>';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</select>
|
</select>
|
||||||
|
|
|
@ -48,10 +48,11 @@ WP_Filesystem();
|
||||||
<?php
|
<?php
|
||||||
if ( ! $activitypub_plugin_is_active ) {
|
if ( ! $activitypub_plugin_is_active ) {
|
||||||
$notice = General_Admin_Notices::get_admin_notice_activitypub_plugin_not_enabled();
|
$notice = General_Admin_Notices::get_admin_notice_activitypub_plugin_not_enabled();
|
||||||
|
echo '<p>⚠' . \wp_kses( $notice, General_Admin_Notices::ALLOWED_HTML ) . '</p>';
|
||||||
} elseif ( empty( $active_event_plugins ) ) {
|
} elseif ( empty( $active_event_plugins ) ) {
|
||||||
$notice = General_Admin_Notices::get_admin_notice_no_supported_event_plugin_active();
|
$notice = General_Admin_Notices::get_admin_notice_no_supported_event_plugin_active();
|
||||||
|
echo '<p>⚠' . \wp_kses( $notice, General_Admin_Notices::ALLOWED_HTML ) . '</p>';
|
||||||
}
|
}
|
||||||
echo '<p>⚠' . \wp_kses( $notice, General_Admin_Notices::ALLOWED_HTML ) . '</p>';
|
|
||||||
?>
|
?>
|
||||||
<?php foreach ( $active_event_plugins as $active_event_plugin ) { ?>
|
<?php foreach ( $active_event_plugins as $active_event_plugin ) { ?>
|
||||||
<h3><?php echo esc_html( $active_event_plugin->get_plugin_name() ); ?>:</h3>
|
<h3><?php echo esc_html( $active_event_plugin->get_plugin_name() ); ?>:</h3>
|
||||||
|
|
|
@ -81,6 +81,12 @@ function _manually_load_plugin() {
|
||||||
break;
|
break;
|
||||||
case 'vs_event_list':
|
case 'vs_event_list':
|
||||||
$plugin_file = 'very-simple-event-list/vsel.php';
|
$plugin_file = 'very-simple-event-list/vsel.php';
|
||||||
|
\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\VS_Event_List::class
|
||||||
|
);
|
||||||
|
\update_option( 'activitypub_actor_mode', ACTIVITYPUB_BLOG_MODE );
|
||||||
break;
|
break;
|
||||||
case 'events_manager':
|
case 'events_manager':
|
||||||
$plugin_file = 'events-manager/events-manager.php';
|
$plugin_file = 'events-manager/events-manager.php';
|
||||||
|
|
|
@ -113,7 +113,7 @@ class Test_GatherPress extends \WP_UnitTestCase {
|
||||||
'endTime' => \gmdate( 'Y-m-d\TH:i:s\Z', time() + WEEK_IN_SECONDS + HOUR_IN_SECONDS ),
|
'endTime' => \gmdate( 'Y-m-d\TH:i:s\Z', time() + WEEK_IN_SECONDS + HOUR_IN_SECONDS ),
|
||||||
'name' => 'Fediverse Party',
|
'name' => 'Fediverse Party',
|
||||||
'to' => 'https://www.w3.org/ns/activitystreams#Public',
|
'to' => 'https://www.w3.org/ns/activitystreams#Public',
|
||||||
'published' => '2020-01-01T00:00:00Z',
|
'published' => \gmdate( 'Y-m-d\TH:i:s\Z', time() ),
|
||||||
'location' => array(
|
'location' => array(
|
||||||
'type' => 'Place',
|
'type' => 'Place',
|
||||||
'name' => 'Fediverse Concert Hall',
|
'name' => 'Fediverse Concert Hall',
|
||||||
|
|
|
@ -93,7 +93,7 @@ class Test_The_Events_Calendar extends \WP_UnitTestCase {
|
||||||
'endTime' => \gmdate( 'Y-m-d\TH:i:s\Z', time() + WEEK_IN_SECONDS + HOUR_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',
|
'name' => 'Fediverse Party for The Events Calendar',
|
||||||
'to' => 'https://www.w3.org/ns/activitystreams#Public',
|
'to' => 'https://www.w3.org/ns/activitystreams#Public',
|
||||||
'published' => '2020-01-01T00:00:00Z',
|
'published' => \gmdate( 'Y-m-d\TH:i:s\Z', time() ),
|
||||||
'location' => array(
|
'location' => array(
|
||||||
'type' => 'Place',
|
'type' => 'Place',
|
||||||
'name' => 'Fediverse Concert Hall',
|
'name' => 'Fediverse Concert Hall',
|
||||||
|
@ -155,7 +155,7 @@ class Test_The_Events_Calendar extends \WP_UnitTestCase {
|
||||||
'endTime' => \gmdate( 'Y-m-d\TH:i:s\Z', time() + WEEK_IN_SECONDS + HOUR_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',
|
'name' => 'Fediverse Party for The Events Calendar',
|
||||||
'to' => 'https://www.w3.org/ns/activitystreams#Public',
|
'to' => 'https://www.w3.org/ns/activitystreams#Public',
|
||||||
'published' => '2020-01-01T00:00:00Z',
|
'published' => \gmdate( 'Y-m-d\TH:i:s\Z', time() ),
|
||||||
'location' => array(
|
'location' => array(
|
||||||
'type' => 'Place',
|
'type' => 'Place',
|
||||||
'name' => 'Fediverse Concert Hall',
|
'name' => 'Fediverse Concert Hall',
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Test file for the Transmogrifier (import of ActivityPub Event objects) in VS Event List.
|
||||||
|
*
|
||||||
|
* @package Event_Bridge_For_ActivityPub
|
||||||
|
* @since 1.0.0
|
||||||
|
* @license AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Event_Bridge_For_ActivityPub\Tests\ActivityPub\Transmogrifier;
|
||||||
|
|
||||||
|
use Event_Bridge_For_ActivityPub\ActivityPub\Model\Event_Source;
|
||||||
|
use Event_Bridge_For_ActivityPub\ActivityPub\Transformer\VS_Event_List as TransformerVS_Event_List;
|
||||||
|
use Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier\VS_Event_List;
|
||||||
|
use Event_Bridge_For_ActivityPub\Integrations\VS_Event_List as IntegrationsVS_Event_List;
|
||||||
|
use WP_REST_Request;
|
||||||
|
use WP_REST_Server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for the Transmogrifier (import of ActivityPub Event objects) in VS Event List.
|
||||||
|
*
|
||||||
|
* @coversDefaultClass \Event_Bridge_For_ActivityPub\ActivityPub\Transmogrifier\VS_Event_List
|
||||||
|
*/
|
||||||
|
class Test_VS_Event_List 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 ( ! function_exists( 'vsel_custom_post_type' ) ) {
|
||||||
|
self::markTestSkipped( 'VS Event List 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\VS_Event_List::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_incoming_event() {
|
||||||
|
\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 Test Event',
|
||||||
|
'to' => 'https://www.w3.org/ns/activitystreams#Public',
|
||||||
|
'published' => \gmdate( 'Y-m-d\TH:i:s\Z', time() ),
|
||||||
|
'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() );
|
||||||
|
|
||||||
|
$events = get_posts( array( 'post_type' => IntegrationsVS_Event_List::get_post_type() ) );
|
||||||
|
|
||||||
|
$this->assertCount( 1, $events );
|
||||||
|
$event = $events[0];
|
||||||
|
|
||||||
|
$this->assertEquals( $json['object']['name'], $event->post_title );
|
||||||
|
$this->assertEquals( $json['object']['startTime'], \gmdate( 'Y-m-d\TH:i:s\Z', get_post_meta( $event->ID, 'event-start-date', true ) ) );
|
||||||
|
$this->assertEquals( $json['object']['endTime'], \gmdate( 'Y-m-d\TH:i:s\Z', get_post_meta( $event->ID, 'event-date', true ) ) );
|
||||||
|
$this->assertStringStartsWith( $json['object']['location']['name'], get_post_meta( $event->ID, 'event-location', true ) );
|
||||||
|
\remove_filter( 'activitypub_defer_signature_verification', '__return_true' );
|
||||||
|
}
|
||||||
|
}
|
171
tests/includes/integrations/class-test-vs-event-list.php
Normal file
171
tests/includes/integrations/class-test-vs-event-list.php
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
<?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_ActivityPub\Integrations\VS_Event_List;
|
||||||
|
|
||||||
|
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_VS_Event_List 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 ( ! function_exists( 'vsel_custom_post_type' ) ) {
|
||||||
|
self::markTestSkipped( 'VS Event List 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\VS_Event_List::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' );
|
||||||
|
|
||||||
|
// Federated event 1: starts in one week.
|
||||||
|
$event_in_one_week = array(
|
||||||
|
'id' => 'https://remote.example/@organizer/events/in-one-week#create',
|
||||||
|
'type' => 'Create',
|
||||||
|
'actor' => 'https://remote.example/@organizer',
|
||||||
|
'object' => array(
|
||||||
|
'id' => 'https://remote.example/@organizer/events/in-one-week',
|
||||||
|
'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' => 'Remote Event in One Week',
|
||||||
|
'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',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Federated event 1: starts in two months.
|
||||||
|
$event_in_two_months = array(
|
||||||
|
'id' => 'https://remote.example/@organizer/events/in-two-months#create',
|
||||||
|
'type' => 'Create',
|
||||||
|
'actor' => 'https://remote.example/@organizer',
|
||||||
|
'object' => array(
|
||||||
|
'id' => 'https://remote.example/@organizer/events/in-two-months',
|
||||||
|
'type' => 'Event',
|
||||||
|
'startTime' => \gmdate( 'Y-m-d\TH:i:s\Z', time() + 2 * MONTH_IN_SECONDS ),
|
||||||
|
'endTime' => \gmdate( 'Y-m-d\TH:i:s\Z', time() + 2 * MONTH_IN_SECONDS + HOUR_IN_SECONDS ),
|
||||||
|
'name' => 'Remote Event in Two Months',
|
||||||
|
'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' );
|
||||||
|
|
||||||
|
// Receive both events.
|
||||||
|
$request->set_body( \wp_json_encode( $event_in_one_week ) );
|
||||||
|
$response = \rest_do_request( $request );
|
||||||
|
$this->assertEquals( 202, $response->get_status() );
|
||||||
|
$request->set_body( \wp_json_encode( $event_in_two_months ) );
|
||||||
|
$response = \rest_do_request( $request );
|
||||||
|
$this->assertEquals( 202, $response->get_status() );
|
||||||
|
|
||||||
|
// Create a local event in VS Event List.
|
||||||
|
$post_id = \wp_insert_post(
|
||||||
|
array(
|
||||||
|
'post_title' => 'VSEL Local Test Event',
|
||||||
|
'post_status' => 'publish',
|
||||||
|
'post_type' => 'event',
|
||||||
|
'meta_input' => array(
|
||||||
|
'event-start-date' => \strtotime( '+10 days 15:00:00' ),
|
||||||
|
'event-date' => \strtotime( '+10 days 16:00:00' ),
|
||||||
|
'event-link' => 'https://event-federation.eu/vsel-test-event',
|
||||||
|
'event-link-label' => 'Website',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertNotEquals( false, $post_id );
|
||||||
|
|
||||||
|
// Only one event should show up in the remote events query.
|
||||||
|
$events = VS_Event_List::get_cached_remote_events( time() + MONTH_IN_SECONDS );
|
||||||
|
$this->assertEquals( 1, count( $events ) );
|
||||||
|
$this->assertEquals( $event_in_one_week['object']['id'], get_post( $events[0] )->guid );
|
||||||
|
|
||||||
|
// Include the even in two months in the time_span.
|
||||||
|
$events = VS_Event_List::get_cached_remote_events( time() + 3 * MONTH_IN_SECONDS );
|
||||||
|
$this->assertEquals( 2, count( $events ) );
|
||||||
|
|
||||||
|
// All events are in the future, so no events should be in past.
|
||||||
|
$events = VS_Event_List::get_cached_remote_events( time() );
|
||||||
|
$this->assertEquals( 0, count( $events ) );
|
||||||
|
|
||||||
|
\remove_filter( 'activitypub_defer_signature_verification', '__return_true' );
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue