diff --git a/includes/activitypub/transformer/class-event.php b/includes/activitypub/transformer/class-event.php
index 4dc96e1..33a36d0 100644
--- a/includes/activitypub/transformer/class-event.php
+++ b/includes/activitypub/transformer/class-event.php
@@ -8,10 +8,12 @@
namespace Activitypub_Event_Extensions\Activitypub\Transformer;
-use Activitypub\Activity\Extended_Object\Event as Event_Object;
-use Activitypub\Transformer\Post;
+use DateTime;
-use function Activitypub\get_rest_url_by_path;
+use Activitypub\Activity\Extended_Object\Event as Event_Object;
+use Activitypub\Activity\Extended_Object\Place;
+
+use Activitypub\Transformer\Post;
/**
* Base transformer for WordPress event post types to ActivityPub events.
@@ -19,7 +21,7 @@ use function Activitypub\get_rest_url_by_path;
* Everything that transforming several WordPress post types that represent events
* have in common, as well as sane defaults for events should be defined here.
*/
-class Event extends Post {
+abstract class Event extends Post {
/**
* The WordPress event taxonomy.
@@ -118,6 +120,141 @@ class Event extends Post {
}
}
+ /**
+ * Retrieves the excerpt text (may be HTML). Used for constructing the summary.
+ *
+ * @return ?string
+ */
+ protected function extract_excerpt(): ?string {
+ if ( $this->wp_object->excerpt ) {
+ return $this->wp_object->post_excerpt;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get the start time.
+ *
+ * This is mandatory and must be implemented in the final event transformer class.
+ */
+ abstract protected 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 {
+ return null;
+ }
+
+ /**
+ * Get a default for the location.
+ *
+ * This should be overridden in the actual event transformer.
+ */
+ protected function get_location(): ?Place {
+ return null;
+ }
+
+ /**
+ * Compose a human readable formatted start time.
+ */
+ protected function format_time( $is_start_time = true ) {
+ $time = $is_start_time ? $this->get_start_time() : $this->get_end_time();
+ if ( is_null( $time ) ) {
+ return '';
+ }
+ $start_datetime = new DateTime( $time );
+ $start_timestamp = $start_datetime->getTimestamp();
+ $datetime_format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
+ return wp_date( $datetime_format, $start_timestamp );
+ }
+
+ /**
+ * Format a human readable address.
+ */
+ protected function format_address(): string {
+ $location = $this->get_location();
+ if ( is_null( $location ) ) {
+ return '';
+ }
+ $address = $location->get_address();
+ if ( ! $address ) {
+ return $location->get_name();
+ }
+ if ( is_string( $address ) ) {
+ return $address;
+ }
+ if ( ! is_array( $address ) ) {
+ return '';
+ }
+ return isset( $address['locality'] ) ? $address['locality'] : '';
+ }
+
+ /**
+ * Format the category using the translation.
+ */
+ protected function format_category(): string {
+ require_once ACTIVITYPUB_EVENT_EXTENSIONS_PLUGIN_DIR . '/includes/event-categories.php';
+ $category = $this->get_category();
+ if ( array_key_exists( $category, ACTIVITYPUB_EVENT_EXTENSIONS_EVENT_CATEGORIES ) ) {
+ return ACTIVITYPUB_EVENT_EXTENSIONS_EVENT_CATEGORIES[ $category ];
+ } else {
+ return ACTIVITYPUB_EVENT_EXTENSIONS_EVENT_CATEGORIES['MEETING'];
+ }
+ }
+
+ /**
+ * Create a custom summary.
+ *
+ * It contains also the most important meta-information. The summary is often used when the
+ * ActivityPub object type 'Event' is not supported, e.g. in Mastodon.
+ *
+ * @return string $summary The custom event summary.
+ */
+ public function get_summary(): ?string {
+ $excerpt = $this->extract_excerpt();
+ // BeforeFirstRelease: decide whether this should be a admin setting.
+ $fallback_to_content = true;
+ if ( is_null( $excerpt ) && $fallback_to_content ) {
+ $excerpt = $this->get_content();
+ }
+ $category = $this->format_category();
+ $start_time = $this->format_time();
+ $end_time = $this->format_time( false );
+ $address = $this->format_address();
+
+ $formatted_items = array();
+ if ( ! empty( $category ) ) {
+ $formatted_items[] = "š·ļø $category";
+ }
+
+ if ( ! empty( $start_time ) ) {
+ $formatted_items[] = "šļø . {$start_time}";
+ }
+
+ if ( ! empty( $end_time ) ) {
+ $formatted_items[] = "ā³ . {$end_time}";
+ }
+
+ if ( ! empty( $address ) ) {
+ $formatted_items[] = "š {$address}";
+ }
+ // Compose the summary based on the number of meta items.
+ if ( count( $formatted_items ) > 1 ) {
+ $summary = '
- ' . implode( '
- ', $formatted_items ) . '
';
+ } elseif ( 1 === count( $formatted_items ) ) {
+ $summary = $formatted_items[0]; // Just the one item without - .
+ } else {
+ $summary = ''; // No items, so no output.
+ }
+
+ $summary .= $excerpt;
+ return $summary;
+ }
+
/**
* Generic function that converts an WP-Event object to an ActivityPub-Event object.
*
diff --git a/includes/activitypub/transformer/class-vs-event-list.php b/includes/activitypub/transformer/class-vs-event-list.php
index f6f9b61..81d36e8 100644
--- a/includes/activitypub/transformer/class-vs-event-list.php
+++ b/includes/activitypub/transformer/class-vs-event-list.php
@@ -12,9 +12,6 @@ use Activitypub_Event_Extensions\Activitypub\Transformer\Event as Event_Transfor
use Activitypub\Activity\Extended_Object\Event;
use Activitypub\Activity\Extended_Object\Place;
-use WP_Error;
-use function Activitypub\get_rest_url_by_path;
-
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
@@ -79,7 +76,7 @@ final class VS_Event_List extends Event_Transformer {
*/
protected function get_start_time(): string {
$start_time = get_post_meta( $this->wp_object->ID, 'event-start-date', true );
- return $start_time ? \gmdate( 'Y-m-d\TH:i:s\Z', $start_time ) : null;
+ return \gmdate( 'Y-m-d\TH:i:s\Z', $start_time );
}
/**
@@ -117,28 +114,19 @@ final class VS_Event_List extends Event_Transformer {
return $attachments;
}
- /**
- * Create a custom summary.
- *
- * It contains also the most important meta-information. The summary is often used when the
- * ActivityPub object type 'Event' is not supported, e.g. in Mastodon.
- *
- * @return string $summary The custom event summary.
- */
- public function get_summary(): ?string {
- if ( $this->wp_object->excerpt ) {
- $excerpt = $this->wp_object->post_excerpt;
- } elseif ( get_post_meta( $this->wp_object->ID, 'event-summary', true ) ) {
- $excerpt = get_post_meta( $this->wp_object->ID, 'event-summary', true );
- } else {
- $excerpt = $this->get_content();
- }
- $address = get_post_meta( $this->wp_object->ID, 'event-location', true );
- $start_time = get_post_meta( $this->wp_object->ID, 'event-start-date', true );
- $datetime_format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
- $start_time_string = wp_date( $datetime_format, $start_time );
- $summary = "š {$address}\nš
{$start_time_string}\n\n{$excerpt}";
- return $summary;
+ /**
+ * Retrieves the excerpt text (may be HTML). Used for constructing the summary.
+ *
+ * @return ?string
+ */
+ protected function get_excerpt(): ?string {
+ if ( get_post_meta( $this->wp_object->ID, 'event-summary', true ) ) {
+ return get_post_meta( $this->wp_object->ID, 'event-summary', true );
+ } elseif ( $this->wp_object->excerpt ) {
+ return $this->wp_object->post_excerpt;
+ } else {
+ return null;
+ }
}
}
diff --git a/includes/event-categories.php b/includes/event-categories.php
new file mode 100644
index 0000000..a867167
--- /dev/null
+++ b/includes/event-categories.php
@@ -0,0 +1,47 @@
+ __( 'Arts', 'activitypub-event-extensions' ),
+ 'BOOK_CLUBS' => __( 'Book clubs', 'activitypub-event-extensions' ),
+ 'BUSINESS' => __( 'Business', 'activitypub-event-extensions' ),
+ 'CAUSES' => __( 'Causes', 'activitypub-event-extensions' ),
+ 'COMEDY' => __( 'Comedy', 'activitypub-event-extensions' ),
+ 'CRAFTS' => __( 'Crafts', 'activitypub-event-extensions' ),
+ 'FOOD_DRINK' => __( 'Food & Drink', 'activitypub-event-extensions' ),
+ 'HEALTH' => __( 'Health', 'activitypub-event-extensions' ),
+ 'MUSIC' => __( 'Music', 'activitypub-event-extensions' ),
+ 'AUTO_BOAT_AIR' => __( 'Auto, boat and air', 'activitypub-event-extensions' ),
+ 'COMMUNITY' => __( 'Community', 'activitypub-event-extensions' ),
+ 'FAMILY_EDUCATION' => __( 'Family & Education', 'activitypub-event-extensions' ),
+ 'FASHION_BEAUTY' => __( 'Fashion & Beauty', 'activitypub-event-extensions' ),
+ 'FILM_MEDIA' => __( 'Film & Media', 'activitypub-event-extensions' ),
+ 'GAMES' => __( 'Games', 'activitypub-event-extensions' ),
+ 'LANGUAGE_CULTURE' => __( 'Language & Culture', 'activitypub-event-extensions' ),
+ 'LEARNING' => __( 'Learning', 'activitypub-event-extensions' ),
+ 'LGBTQ' => __( 'LGBTQ', 'activitypub-event-extensions' ),
+ 'MOVEMENTS_POLITICS' => __( 'Movements and politics', 'activitypub-event-extensions' ),
+ 'NETWORKING' => __( 'Networking', 'activitypub-event-extensions' ),
+ 'PARTY' => __( 'Party', 'activitypub-event-extensions' ),
+ 'PERFORMING_VISUAL_ARTS' => __( 'Performing & Visual Arts', 'activitypub-event-extensions' ),
+ 'PETS' => __( 'Pets', 'activitypub-event-extensions' ),
+ 'PHOTOGRAPHY' => __( 'Photography', 'activitypub-event-extensions' ),
+ 'OUTDOORS_ADVENTURE' => __( 'Outdoors & Adventure', 'activitypub-event-extensions' ),
+ 'SPIRITUALITY_RELIGION_BELIEFS' => __( 'Spirituality, Religion & Beliefs', 'activitypub-event-extensions' ),
+ 'SCIENCE_TECH' => __( 'Science & Tech', 'activitypub-event-extensions' ),
+ 'SPORTS' => __( 'Sports', 'activitypub-event-extensions' ),
+ 'THEATRE' => __( 'Theatre', 'activitypub-event-extensions' ),
+ 'MEETING' => __( 'Meeting', 'activitypub-event-extensions' ), // Default value in federation.
+ 'DEFAULT' => __( 'Default', 'activitypub-event-extensions' ), // Internal default for overrides.
+ ),
+);