Merge branch 'format_summary'
This commit is contained in:
commit
2257e86f0f
6 changed files with 230 additions and 42 deletions
|
@ -12,7 +12,9 @@ namespace Activitypub_Event_Extensions\Activitypub\Transformer;
|
||||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||||
|
|
||||||
use Activitypub\Activity\Extended_Object\Event as Event_Object;
|
use Activitypub\Activity\Extended_Object\Event as Event_Object;
|
||||||
|
use Activitypub\Activity\Extended_Object\Place;
|
||||||
use Activitypub\Transformer\Post;
|
use Activitypub\Transformer\Post;
|
||||||
|
use DateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base transformer for WordPress event post types to ActivityPub events.
|
* Base transformer for WordPress event post types to ActivityPub events.
|
||||||
|
@ -20,7 +22,7 @@ use Activitypub\Transformer\Post;
|
||||||
* Everything that transforming several WordPress post types that represent events
|
* Everything that transforming several WordPress post types that represent events
|
||||||
* have in common, as well as sane defaults for events should be defined here.
|
* 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.
|
* The WordPress event taxonomy.
|
||||||
|
@ -119,6 +121,161 @@ 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.
|
||||||
|
*
|
||||||
|
* @param bool $is_start_time Whether format the events start or end 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 {
|
||||||
|
add_filter( 'activitypub_object_content_template', array( self::class, 'remove_ap_permalink_from_template' ), 2 );
|
||||||
|
$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();
|
||||||
|
}
|
||||||
|
remove_filter( 'activitypub_object_content_template', array( self::class, 'remove_ap_permalink_from_template' ) );
|
||||||
|
|
||||||
|
$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 = '<ul><li>' . implode( '</li><li>', $formatted_items ) . '</li></ul>';
|
||||||
|
} elseif ( 1 === count( $formatted_items ) ) {
|
||||||
|
$summary = $formatted_items[0]; // Just the one item without <ul><li>.
|
||||||
|
} else {
|
||||||
|
$summary = ''; // No items, so no output.
|
||||||
|
}
|
||||||
|
|
||||||
|
$summary .= $excerpt;
|
||||||
|
return $summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the permalink shortcode from a WordPress template.
|
||||||
|
*
|
||||||
|
* This used for the summary template, because the summary usually gets,
|
||||||
|
* used when converting a object, where the URL is usually appended anyway.
|
||||||
|
*
|
||||||
|
* @param string $template The template string.
|
||||||
|
*/
|
||||||
|
public static function remove_ap_permalink_from_template( $template ) {
|
||||||
|
$template = str_replace( '[ap_permalink]', '', $template );
|
||||||
|
$template = str_replace( '[ap_permalink type="html"]', '', $template );
|
||||||
|
|
||||||
|
return $template;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic function that converts an WP-Event object to an ActivityPub-Event object.
|
* Generic function that converts an WP-Event object to an ActivityPub-Event object.
|
||||||
*
|
*
|
||||||
|
|
|
@ -89,7 +89,7 @@ final class Events_Manager extends Event_Transformer {
|
||||||
*
|
*
|
||||||
* @return array The Place.
|
* @return array The Place.
|
||||||
*/
|
*/
|
||||||
public function get_location() {
|
public function get_location(): ?Place {
|
||||||
if ( 'url' === $this->em_event->event_location_type ) {
|
if ( 'url' === $this->em_event->event_location_type ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -125,14 +125,14 @@ final class Events_Manager extends Event_Transformer {
|
||||||
/**
|
/**
|
||||||
* Get the end time from the events metadata.
|
* Get the end time from the events metadata.
|
||||||
*/
|
*/
|
||||||
public function get_end_time() {
|
public function get_end_time(): ?string {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the end time from the events metadata.
|
* Get the end time from the events metadata.
|
||||||
*/
|
*/
|
||||||
public function get_start_time() {
|
public function get_start_time(): string {
|
||||||
$date_string = $this->em_event->event_start_date;
|
$date_string = $this->em_event->event_start_date;
|
||||||
$time_string = $this->em_event->event_start_time;
|
$time_string = $this->em_event->event_start_time;
|
||||||
$timezone_string = $this->em_event->event_timezone;
|
$timezone_string = $this->em_event->event_timezone;
|
||||||
|
@ -181,7 +181,7 @@ final class Events_Manager extends Event_Transformer {
|
||||||
/**
|
/**
|
||||||
* Hardcoded function for generating a summary.
|
* Hardcoded function for generating a summary.
|
||||||
*/
|
*/
|
||||||
public function get_summary() {
|
public function get_summary(): ?string {
|
||||||
if ( $this->em_event->post_excerpt ) {
|
if ( $this->em_event->post_excerpt ) {
|
||||||
$excerpt = $this->em_event->post_excerpt;
|
$excerpt = $this->em_event->post_excerpt;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -78,7 +78,7 @@ final class GatherPress extends Event {
|
||||||
*
|
*
|
||||||
* @return Place|null The place objector null if not place set.
|
* @return Place|null The place objector null if not place set.
|
||||||
*/
|
*/
|
||||||
public function get_location(): Place|null {
|
public function get_location(): ?Place {
|
||||||
$address = $this->gp_venue['full_address'];
|
$address = $this->gp_venue['full_address'];
|
||||||
if ( $address ) {
|
if ( $address ) {
|
||||||
$place = new Place();
|
$place = new Place();
|
||||||
|
@ -94,14 +94,14 @@ final class GatherPress extends Event {
|
||||||
/**
|
/**
|
||||||
* Get the end time from the event object.
|
* Get the end time from the event object.
|
||||||
*/
|
*/
|
||||||
protected function get_end_time() {
|
protected function get_end_time(): ?string {
|
||||||
return $this->gp_event->get_datetime_end( 'Y-m-d\TH:i:s\Z' );
|
return $this->gp_event->get_datetime_end( 'Y-m-d\TH:i:s\Z' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the end time from the event object.
|
* Get the end time from the event object.
|
||||||
*/
|
*/
|
||||||
protected function get_start_time() {
|
protected function get_start_time(): string {
|
||||||
return $this->gp_event->get_datetime_start( 'Y-m-d\TH:i:s\Z' );
|
return $this->gp_event->get_datetime_start( 'Y-m-d\TH:i:s\Z' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,10 @@ namespace Activitypub_Event_Extensions\Activitypub\Transformer;
|
||||||
// Exit if accessed directly.
|
// Exit if accessed directly.
|
||||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||||
|
|
||||||
use WP_Post;
|
|
||||||
|
|
||||||
use Activitypub\Activity\Extended_Object\Event as Event_Object;
|
use Activitypub\Activity\Extended_Object\Event as Event_Object;
|
||||||
use Activitypub\Activity\Extended_Object\Place;
|
use Activitypub\Activity\Extended_Object\Place;
|
||||||
use Activitypub_Event_Extensions\Activitypub\Transformer\Event;
|
use Activitypub_Event_Extensions\Activitypub\Transformer\Event;
|
||||||
|
use WP_Post;
|
||||||
|
|
||||||
use function Activitypub\esc_hashtag;
|
use function Activitypub\esc_hashtag;
|
||||||
|
|
||||||
|
@ -74,7 +73,10 @@ final class The_Events_Calendar extends Event {
|
||||||
/**
|
/**
|
||||||
* Get the end time from the event object.
|
* Get the end time from the event object.
|
||||||
*/
|
*/
|
||||||
protected function get_end_time(): string {
|
protected function get_end_time(): ?string {
|
||||||
|
if ( empty( $this->tribe_event->end_date ) ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
$date = date_create( $this->tribe_event->end_date, wp_timezone() );
|
$date = date_create( $this->tribe_event->end_date, wp_timezone() );
|
||||||
return \gmdate( 'Y-m-d\TH:i:s\Z', $date->getTimestamp() );
|
return \gmdate( 'Y-m-d\TH:i:s\Z', $date->getTimestamp() );
|
||||||
}
|
}
|
||||||
|
@ -82,7 +84,7 @@ final class The_Events_Calendar extends Event {
|
||||||
/**
|
/**
|
||||||
* Get the end time from the event object.
|
* Get the end time from the event object.
|
||||||
*/
|
*/
|
||||||
protected function get_start_time() {
|
protected function get_start_time(): string {
|
||||||
$date = date_create( $this->tribe_event->start_date, wp_timezone() );
|
$date = date_create( $this->tribe_event->start_date, wp_timezone() );
|
||||||
return \gmdate( 'Y-m-d\TH:i:s\Z', $date->getTimestamp() );
|
return \gmdate( 'Y-m-d\TH:i:s\Z', $date->getTimestamp() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,17 +30,6 @@ final class VS_Event_List extends Event_Transformer {
|
||||||
*/
|
*/
|
||||||
protected $ap_object;
|
protected $ap_object;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the ActivityStreams 2.0 Object-Type for an Event.
|
|
||||||
*
|
|
||||||
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-event
|
|
||||||
* @since 1.0.0
|
|
||||||
* @return string The Event Object-Type.
|
|
||||||
*/
|
|
||||||
protected function get_type(): string {
|
|
||||||
return 'Event';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the event location.
|
* Get the event location.
|
||||||
*
|
*
|
||||||
|
@ -67,6 +56,9 @@ final class VS_Event_List extends Event_Transformer {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$end_time = get_post_meta( $this->wp_object->ID, 'event-date', true );
|
$end_time = get_post_meta( $this->wp_object->ID, 'event-date', true );
|
||||||
|
if ( is_null( $end_time ) || empty( $end_time ) || 'no' === $end_time ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return $end_time ? \gmdate( 'Y-m-d\TH:i:s\Z', $end_time ) : null;
|
return $end_time ? \gmdate( 'Y-m-d\TH:i:s\Z', $end_time ) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +67,7 @@ final class VS_Event_List extends Event_Transformer {
|
||||||
*/
|
*/
|
||||||
protected function get_start_time(): string {
|
protected function get_start_time(): string {
|
||||||
$start_time = get_post_meta( $this->wp_object->ID, 'event-start-date', true );
|
$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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,27 +106,17 @@ final class VS_Event_List extends Event_Transformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a custom summary.
|
* Retrieves the excerpt text (may be HTML). Used for constructing the summary.
|
||||||
*
|
*
|
||||||
* It contains also the most important meta-information. The summary is often used when the
|
* @return ?string
|
||||||
* ActivityPub object type 'Event' is not supported, e.g. in Mastodon.
|
|
||||||
*
|
|
||||||
* @return string $summary The custom event summary.
|
|
||||||
*/
|
*/
|
||||||
public function get_summary(): ?string {
|
protected function get_excerpt(): ?string {
|
||||||
if ( $this->wp_object->excerpt ) {
|
if ( get_post_meta( $this->wp_object->ID, 'event-summary', true ) ) {
|
||||||
$excerpt = $this->wp_object->post_excerpt;
|
return get_post_meta( $this->wp_object->ID, 'event-summary', true );
|
||||||
} elseif ( get_post_meta( $this->wp_object->ID, 'event-summary', true ) ) {
|
} elseif ( $this->wp_object->excerpt ) {
|
||||||
$excerpt = get_post_meta( $this->wp_object->ID, 'event-summary', true );
|
return $this->wp_object->post_excerpt;
|
||||||
} else {
|
} else {
|
||||||
$excerpt = $this->get_content();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
47
includes/event-categories.php
Normal file
47
includes/event-categories.php
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* File responsible for defining the event category strings.
|
||||||
|
*
|
||||||
|
* @package Activitypub_Event_Extensions
|
||||||
|
* @since 1.0.0
|
||||||
|
* @license AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Activitypub_Event_Extensions;
|
||||||
|
|
||||||
|
define(
|
||||||
|
'ACTIVITYPUB_EVENT_EXTENSIONS_EVENT_CATEGORIES',
|
||||||
|
array(
|
||||||
|
'ARTS' => __( '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.
|
||||||
|
),
|
||||||
|
);
|
Loading…
Reference in a new issue