wip draft of composed human readable summary using vs events list
Some checks failed
PHP Code Checker / PHP Code Checker (pull_request) Failing after 36s
PHPUnit / PHPUnit – PHP 8.1 (pull_request) Failing after 55s
PHPUnit / PHPUnit – PHP 8.2 (pull_request) Failing after 53s
PHPUnit / PHPUnit – PHP 8.3 (pull_request) Failing after 50s

This commit is contained in:
André Menrath 2024-09-25 13:59:31 +02:00
parent e8574d26ac
commit ac99300949
3 changed files with 202 additions and 30 deletions

View file

@ -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 = '<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;
}
/**
* Generic function that converts an WP-Event object to an ActivityPub-Event object.
*

View file

@ -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;
}
}
}

View 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.
),
);