diff --git a/activitypub-event-bridge.php b/activitypub-event-bridge.php index 961af39..0276072 100644 --- a/activitypub-event-bridge.php +++ b/activitypub-event-bridge.php @@ -3,7 +3,7 @@ * Plugin Name: ActivityPub Event Bridge * Description: Integrating popular event plugins with the ActivityPub plugin. * Plugin URI: https://event-federation.eu/ - * Version: 0.2.1 + * Version: 0.2.1.4 * Author: André Menrath * Author URI: https://graz.social/@linos * Text Domain: activitypub-event-bridge @@ -27,6 +27,8 @@ define( 'ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); define( 'ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_VERSION', current( get_file_data( __FILE__, array( 'Version' ), 'plugin' ) ) ); define( 'ACTIVITYPUB_EVENT_BRIDGE_DOMAIN', 'activitypub-event-bridge' ); define( 'ACTIVITYPUB_EVENT_BRIDGE_ACTIVITYPUB_PLUGIN_MIN_VERSION', '3.2.2' ); +define( 'ACTIVITYPUB_EVENT_BRIDGE_CUSTOM_SUMMARY', "\n[ap_hashcats][ap_hashtags]" ); +define( 'ACTIVITYPUB_EVENT_BRIDGE_DEFAULT_SUMMARY_TYPE', 'preset' ); // Include and register the autoloader class for automatic loading of plugin classes. require_once ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_DIR . '/includes/class-autoloader.php'; diff --git a/assets/css/activitypub-event-bridge-admin.css b/assets/css/activitypub-event-bridge-admin.css index c89ec6e..043082f 100644 --- a/assets/css/activitypub-event-bridge-admin.css +++ b/assets/css/activitypub-event-bridge-admin.css @@ -177,3 +177,7 @@ code.activitypub-event-bridge-settings-example-url { overflow-x: auto; word-break: break-all; } + +#activitypub_summary_type_custom-details { + display: none; +} diff --git a/assets/js/activitypub-event-bridge-admin.js b/assets/js/activitypub-event-bridge-admin.js index bf00a1c..4716ec8 100644 --- a/assets/js/activitypub-event-bridge-admin.js +++ b/assets/js/activitypub-event-bridge-admin.js @@ -11,4 +11,23 @@ jQuery( function( $ ) { $( '#' + $( this ).attr( 'aria-controls' ) ).attr( 'hidden', false ); } } ); + + // Function to toggle visibility of custom details based on selected radio button. + function toggleCustomDetailsForSummary() { + if ($("#activitypub_summary_type_custom").is(':checked')) { + $("#activitypub_summary_type_custom-details").show(); + } else { + $("#activitypub_summary_type_custom-details").hide(); + } + } + + // Run the toggle function on page load. + $(document).ready(function() { + toggleCustomDetailsForSummary(); // Set the correct state on load. + + // Listen for changes on the radio buttons + $("input[name=activitypub_summary_type]").change(function() { + toggleCustomDetailsForSummary(); // Update visibility on change. + }); + }); } ); diff --git a/includes/activitypub/transformer/class-event.php b/includes/activitypub/transformer/class-event.php index babf2b9..6d742cd 100644 --- a/includes/activitypub/transformer/class-event.php +++ b/includes/activitypub/transformer/class-event.php @@ -14,6 +14,8 @@ defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore use Activitypub\Activity\Extended_Object\Event as Event_Object; use Activitypub\Activity\Extended_Object\Place; use Activitypub\Transformer\Post; +use ActivityPub_Event_Bridge\Event_Shortcodes; + use DateTime; /** @@ -148,14 +150,14 @@ abstract class Event extends Post { * * This is mandatory and must be implemented in the final event transformer class. */ - abstract protected function get_start_time(): string; + abstract public function get_start_time(): string; /** * Get the end time. * * This is not mandatory and therefore just return null by default. */ - protected function get_end_time(): ?string { + public function get_end_time(): ?string { return null; } @@ -164,14 +166,14 @@ abstract class Event extends Post { * * This should be overridden in the actual event transformer. */ - protected function get_location(): ?Place { + public function get_location(): ?Place { return null; } /** * Default value for the event status. */ - protected function get_status(): ?string { + public function get_status(): ?string { return 'CONFIRMED'; } @@ -255,6 +257,44 @@ abstract class Event extends Post { return ''; } + + + /** + * Get the summary. + */ + public function get_summary(): ?string { + if ( 'preset' === get_option( 'activitypub_summary_type', 'preset' ) ) { + return $this->get_preset_summary(); + } + + // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited + $post = $this->wp_object; + $summary = $this->get_event_summary_template(); + + // It seems that shortcodes are only applied to published posts. + if ( is_preview() ) { + $post->post_status = 'publish'; + } + + // Register our shortcodes just in time. + Event_Shortcodes::register(); + // Fill in the shortcodes. + \setup_postdata( $post ); + $summary = \do_shortcode( $summary ); + \wp_reset_postdata(); + + $summary = \wpautop( $summary ); + $summary = \preg_replace( '/[\n\r\t]/', '', $summary ); + $summary = \trim( $summary ); + + $summary = \apply_filters( 'activitypub_event_bridge_the_summary', $summary, $post ); + + // Don't need these anymore, should never appear in a post. + Event_Shortcodes::unregister(); + + return $summary; + } + /** * Create a custom summary. * @@ -263,7 +303,7 @@ abstract class Event extends Post { * * @return string $summary The custom event summary. */ - public function get_summary(): ?string { + public function get_preset_summary(): ?string { add_filter( 'activitypub_object_content_template', array( self::class, 'remove_ap_permalink_from_template' ), 2, 2 ); $excerpt = $this->retrieve_excerpt(); // BeforeFirstRelease: decide whether this should be a admin setting. @@ -308,6 +348,18 @@ abstract class Event extends Post { return $summary; } + /** + * Gets the template to use to generate the summary of the ActivityStreams representation of an event post. + * + * @return string The Template. + */ + protected function get_event_summary_template() { + $summary = \get_option( 'activitypub_event_bridge_custom_summary', ACTIVITYPUB_EVENT_BRIDGE_CUSTOM_SUMMARY ); + $template = $summary ?? ACTIVITYPUB_EVENT_BRIDGE_CUSTOM_SUMMARY; + + return apply_filters( 'activitypub_event_bridge_summary_template', $template, $this->wp_object ); + } + /** * By default set the timezone of the WordPress site. * diff --git a/includes/activitypub/transformer/class-the-events-calendar.php b/includes/activitypub/transformer/class-the-events-calendar.php index f50fa29..80ac52e 100644 --- a/includes/activitypub/transformer/class-the-events-calendar.php +++ b/includes/activitypub/transformer/class-the-events-calendar.php @@ -72,7 +72,7 @@ final class The_Events_Calendar extends Event { /** * Get the end time from the event object. */ - protected function get_end_time(): ?string { + public function get_end_time(): ?string { if ( empty( $this->tribe_event->end_date ) ) { return null; } @@ -83,7 +83,7 @@ final class The_Events_Calendar extends Event { /** * Get the end time from the event object. */ - protected function get_start_time(): string { + public function get_start_time(): string { $date = date_create( $this->tribe_event->start_date, wp_timezone() ); return \gmdate( 'Y-m-d\TH:i:s\Z', $date->getTimestamp() ); } diff --git a/includes/class-event-shortcodes.php b/includes/class-event-shortcodes.php new file mode 100644 index 0000000..611150f --- /dev/null +++ b/includes/class-event-shortcodes.php @@ -0,0 +1,253 @@ +getTimestamp(); + $datetime_format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' ); + return wp_date( $datetime_format, $start_timestamp ); + } + + /** + * Generates output for the 'apeb_start_time' shortcode. + * + * @param ?array $atts The shortcodes attributes. + * + * @return string The formatted start date and time of the event. + */ + public static function start_time( $atts ) { + $transformer = self::get_transformer(); + + if ( ! $transformer ) { + return ''; + } + + $args = shortcode_atts( + array( + 'icon' => 'true', + 'title' => 'true', + ), + $atts, + 'ap_start_time' + ); + + $args['icon'] = filter_var( $args['icon'], FILTER_VALIDATE_BOOLEAN ); + $args['title'] = filter_var( $args['title'], FILTER_VALIDATE_BOOLEAN ); + + $start_timestamp = $transformer->get_start_time(); + + if ( ! $start_timestamp ) { + return ''; + } + + $start_time = array(); + + if ( $args['icon'] ) { + $start_time[] = '🗓️'; + } + + if ( $args['title'] ) { + $start_time[] = __( 'Start', 'activitypub-event-bridge' ) . ':'; + } + + $start_time[] = self::format_time( $start_timestamp ); + + $start_time = implode( ' ', $start_time ); + + return $start_time; + } + + /** + * Generates output for the 'apeb_end_time' shortcode. + * + * @param ?array $atts The shortcodes attributes. + * + * @return string The formatted end date and time of the event. + */ + public static function end_time( $atts ) { + $transformer = self::get_transformer(); + + if ( ! $transformer ) { + return ''; + } + + $args = shortcode_atts( + array( + 'icon' => 'true', + 'title' => 'true', + ), + $atts, + 'ap_end_time' + ); + + $args['icon'] = filter_var( $args['icon'], FILTER_VALIDATE_BOOLEAN ); + $args['title'] = filter_var( $args['title'], FILTER_VALIDATE_BOOLEAN ); + + $end_timestamp = $transformer->get_end_time(); + + if ( ! $end_timestamp ) { + return ''; + } + + $end_time = array(); + + if ( $args['icon'] ) { + $end_time[] = '⏳'; + } + + if ( $args['title'] ) { + $end_time[] = __( 'End', 'activitypub-event-bridge' ) . ':'; + } + + $end_time[] = self::format_time( $end_timestamp ); + + $end_time = implode( ' ', $end_time ); + + return $end_time; + } + + /** + * Generates output for the 'apeb_location shortcode. + * + * @param ?array $atts The shortcodes attributes. + * + * @return string The formatted location/address of the event. + */ + public static function location( $atts ) { + $transformer = self::get_transformer(); + + if ( ! $transformer ) { + return ''; + } + + $args = shortcode_atts( + array( + 'icon' => 'true', + 'title' => 'true', + 'country' => 'true', + 'zip' => 'true', + 'city' => 'true', + 'street' => 'true', + 'name' => 'true', + ), + $atts, + 'ap_location' + ); + + foreach ( $args as $arg => $value ) { + $args[ $arg ] = filter_var( $value, FILTER_VALIDATE_BOOLEAN ); + } + + $location = $transformer->get_location(); + + if ( ! $location ) { + return ''; + } + + $output = array(); + + if ( $args['icon'] ) { + $output[] = '📍'; + } + + if ( $args['title'] ) { + $output[] = __( 'Location', 'activitypub-event-bridge' ) . ':'; + } + + $address = $location->get_address(); + + if ( $address ) { + if ( is_string( $address ) ) { + $output[] = $address; + } + if ( is_array( $address ) ) { + if ( $args['name'] && array_key_exists( 'name', $address ) ) { + $output[] = $address['name'] . ','; + } + if ( $args['street'] && array_key_exists( 'streetAddress', $address ) ) { + $output[] = $address['streetAddress'] . ','; + } + if ( $args['zip'] && array_key_exists( 'postalCode', $address ) ) { + $output[] = $address['postalCode']; + } + if ( $args['city'] && array_key_exists( 'addressLocality', $address ) ) { + $output[] = $address['addressLocality'] . ','; + } + if ( $args['country'] && array_key_exists( 'addressCountry', $address ) ) { + $output[] = $address['addressCountry']; + } + } + } + + $output = implode( ' ', $output ); + + return $output; + } +} diff --git a/includes/class-settings.php b/includes/class-settings.php index 6cd7d2e..da1467d 100644 --- a/includes/class-settings.php +++ b/includes/class-settings.php @@ -71,6 +71,28 @@ class Settings { 'default' => 1, ) ); + + \register_setting( + 'activitypub-event-bridge', + 'activitypub_summary_type', + array( + 'type' => 'string', + 'description' => \__( 'Summary type to use for ActivityStreams', 'activitypub-event-bridge' ), + 'show_in_rest' => true, + 'default' => 'preset', + ) + ); + + \register_setting( + 'activitypub-event-bridge', + 'activitypub_event_bridge_custom_summary', + array( + 'type' => 'string', + 'description' => \__( 'Define your own custom summary template for events', 'activitypub-event-bridge' ), + 'show_in_rest' => true, + 'default' => ACTIVITYPUB_EVENT_BRIDGE_CUSTOM_SUMMARY, + ) + ); } /** diff --git a/templates/settings.php b/templates/settings.php index 309590f..e9390d1 100644 --- a/templates/settings.php +++ b/templates/settings.php @@ -42,6 +42,52 @@ $current_category_mapping = \get_option( 'activitypub_event_bridge_event_
+
+

+

+

+ +

+

+ +

+
+ +
+ +
+
+
[ap_start_time]
+
+
[ap_end_time]
+
+
[ap_location]
+
+
[ap_hashtags]
+
+
[ap_excerpt]
+
+
[ap_content]
+
+
+
+
+
+