Add options for summary #80
17 changed files with 581 additions and 42 deletions
|
@ -75,6 +75,11 @@ jobs:
|
|||
if: steps.cache-wordpress.outputs.cache-hit != 'false'
|
||||
run: bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 ${{ matrix.wordpress-version }} false true true true
|
||||
|
||||
- name: Run General Tests
|
||||
run: cd /workspace/Event-Federation/wordpress-event-bridge-for-activitypub/ && ./vendor/bin/phpunit --filter=event_bridge_for_activitypub
|
||||
env:
|
||||
PHP_VERSION: ${{ matrix.php-version }}
|
||||
|
||||
- name: Run Integration tests for The Events Calendar
|
||||
run: cd /workspace/Event-Federation/wordpress-event-bridge-for-activitypub/ && ./vendor/bin/phpunit --filter=the_events_calendar
|
||||
env:
|
||||
|
|
|
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
* Add custom summary via shortcodes
|
||||
|
||||
## [0.3.1] - 2024-11-16
|
||||
|
||||
* Initial release on WordPress.org
|
||||
|
|
|
@ -102,6 +102,12 @@ We're always interested in your feedback. Feel free to reach out to us via [E-Ma
|
|||
|
||||
## Changelog ##
|
||||
|
||||
### Unreleased
|
||||
|
||||
#### Added
|
||||
|
||||
* Add custom summary via shortcodes
|
||||
|
||||
### [0.3.1] 2024-12-05 ###
|
||||
|
||||
* Initial release on https://wordpress.org/
|
||||
|
|
|
@ -177,3 +177,11 @@ code.event-bridge-for-activitypub-settings-example-url {
|
|||
overflow-x: auto;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
#event_bridge_for_activitypub_summary_type_custom-details {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#event_bridge_for_activitypub_summary_type_custom-details > details {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
|
|
@ -11,4 +11,24 @@ jQuery( function( $ ) {
|
|||
$( '#' + $( this ).attr( 'aria-controls' ) ).attr( 'hidden', false );
|
||||
}
|
||||
} );
|
||||
|
||||
// Function to toggle visibility of custom details based on selected radio button.
|
||||
function toggleCustomDetailsForSummary() {
|
||||
if ($("#event_bridge_for_activitypub_summary_type_custom").is(':checked')) {
|
||||
$("#event_bridge_for_activitypub_summary_type_custom-details").show();
|
||||
} else {
|
||||
$("#event_bridge_for_activitypub_summary_type_custom-details").hide();
|
||||
}
|
||||
}
|
||||
|
||||
// Run the toggle function on page load.
|
||||
$(document).ready(function() {
|
||||
window.console.log("test");
|
||||
toggleCustomDetailsForSummary(); // Set the correct state on load.
|
||||
|
||||
// Listen for changes on the radio buttons
|
||||
$("input[name=event_bridge_for_activitypub_summary_type]").change(function() {
|
||||
toggleCustomDetailsForSummary(); // Update visibility on change.
|
||||
});
|
||||
});
|
||||
} );
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
],
|
||||
"test-debug": [
|
||||
"@prepare-test",
|
||||
"@test-event-organiser"
|
||||
"@test-event-bridge-for-activitypub-shortcodes"
|
||||
],
|
||||
"test-vs-event-list": "phpunit --filter=vs_event_list",
|
||||
"test-the-events-calendar": "phpunit --filter=the_events_calendar",
|
||||
|
@ -71,6 +71,7 @@
|
|||
"test-modern-events-calendar-lite": "phpunit --filter=modern_events_calendar_lite",
|
||||
"test-eventprime": "phpunit --filter=eventprime",
|
||||
"test-event-organiser": "phpunit --filter=event_organiser",
|
||||
"test-event-bridge-for-activitypub-shortcodes": "phpunit --filter=event_bridge_for_activitypub_shortcodes",
|
||||
"test-all": "phpunit"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Plugin Name: Event Bridge for ActivityPub
|
||||
* Description: Integrating popular event plugins with the ActivityPub plugin.
|
||||
* Plugin URI: https://event-federation.eu/
|
||||
* Version: 0.3.1
|
||||
* Version: 0.3.1.1
|
||||
* Author: André Menrath
|
||||
* Author URI: https://graz.social/@linos
|
||||
* Text Domain: event-bridge-for-activitypub
|
||||
|
@ -27,6 +27,8 @@ define( 'EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
|
|||
define( 'EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_VERSION', current( get_file_data( __FILE__, array( 'Version' ), 'plugin' ) ) );
|
||||
define( 'EVENT_BRIDGE_FOR_ACTIVITYPUB_DOMAIN', 'event-bridge-for-activitypub' );
|
||||
define( 'EVENT_BRIDGE_FOR_ACTIVITYPUB_ACTIVITYPUB_PLUGIN_MIN_VERSION', '3.2.2' );
|
||||
define( 'EVENT_BRIDGE_FOR_ACTIVITYPUB_CUSTOM_SUMMARY', "<ul>\n <li>[ap_start_time]</li>\n <li>[ap_end_time]</li>\n <li>[ap_location]</li>\n</ul>\n[ap_hashcats] [ap_hashtags]" );
|
||||
define( 'EVENT_BRIDGE_FOR_ACTIVITYPUB_DEFAULT_SUMMARY_TYPE', 'preset' );
|
||||
|
||||
// Include and register the autoloader class for automatic loading of plugin classes.
|
||||
require_once EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_DIR . '/includes/class-autoloader.php';
|
||||
|
|
|
@ -44,21 +44,21 @@ final class Event_Organiser extends Event {
|
|||
/**
|
||||
* Get the end time from the event object.
|
||||
*/
|
||||
protected function get_end_time(): ?string {
|
||||
public function get_end_time(): ?string {
|
||||
return eo_get_the_end( 'Y-m-d\TH:i:s\Z', $this->wp_object->ID, $this->wp_object->occurrence_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end time from the event object.
|
||||
*/
|
||||
protected function get_start_time(): string {
|
||||
public function get_start_time(): string {
|
||||
return eo_get_the_start( 'Y-m-d\TH:i:s\Z', $this->wp_object->ID, $this->wp_object->occurrence_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get location from the event object.
|
||||
*/
|
||||
protected function get_location(): ?Place {
|
||||
public function get_location(): ?Place {
|
||||
$venue_id = eo_get_venue( $this->wp_object->ID );
|
||||
|
||||
if ( ! $venue_id ) {
|
||||
|
|
|
@ -13,7 +13,9 @@ defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
|||
|
||||
use Activitypub\Activity\Extended_Object\Event as Event_Object;
|
||||
use Activitypub\Activity\Extended_Object\Place;
|
||||
use Activitypub\Shortcodes;
|
||||
use Activitypub\Transformer\Post;
|
||||
|
||||
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';
|
||||
}
|
||||
|
||||
|
@ -194,7 +196,7 @@ abstract class Event extends Post {
|
|||
*
|
||||
* @param ?string $time The time which needs to be formatted.
|
||||
*/
|
||||
private static function format_time( $time ) {
|
||||
protected static function format_time( $time ) {
|
||||
if ( is_null( $time ) ) {
|
||||
return '';
|
||||
}
|
||||
|
@ -205,24 +207,160 @@ abstract class Event extends Post {
|
|||
}
|
||||
|
||||
/**
|
||||
* Format a human readable address.
|
||||
* Generates output for the 'ap_start_time' shortcode.
|
||||
*
|
||||
* @param ?array $atts The shortcode's attributes.
|
||||
* @return string The formatted start date and time of the event.
|
||||
*/
|
||||
protected function format_address(): string {
|
||||
public function shortcode_start_time( $atts ) {
|
||||
$start_timestamp = $this->get_start_time();
|
||||
return $this->generate_time_output( $start_timestamp, $atts, '🗓️', __( 'Start', 'event-bridge-for-activitypub' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates output for the 'ap_end_time' shortcode.
|
||||
*
|
||||
* @param ?array $atts The shortcode's attributes.
|
||||
* @return string The formatted end date and time of the event.
|
||||
*/
|
||||
public function shortcode_end_time( $atts ) {
|
||||
$end_timestamp = $this->get_end_time();
|
||||
return $this->generate_time_output( $end_timestamp, $atts, '⏳', __( 'End', 'event-bridge-for-activitypub' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the formatted time output for a shortcode.
|
||||
*
|
||||
* @param int|null $timestamp The timestamp for the event time.
|
||||
* @param array $atts The shortcode attributes.
|
||||
* @param string $icon The icon to display.
|
||||
* @param string $label The label to display (e.g., 'Start', 'End').
|
||||
* @return string The formatted date and time, or an empty string if the timestamp is invalid.
|
||||
*/
|
||||
private function generate_time_output( $timestamp, $atts, $icon, $label ) {
|
||||
if ( ! $timestamp ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$args = shortcode_atts(
|
||||
array(
|
||||
'icon' => 'true',
|
||||
'label' => 'true',
|
||||
),
|
||||
$atts
|
||||
);
|
||||
|
||||
$args['icon'] = filter_var( $args['icon'], FILTER_VALIDATE_BOOLEAN );
|
||||
$args['label'] = filter_var( $args['label'], FILTER_VALIDATE_BOOLEAN );
|
||||
|
||||
$output = array();
|
||||
|
||||
if ( $args['icon'] ) {
|
||||
$output[] = $icon;
|
||||
}
|
||||
|
||||
if ( $args['label'] ) {
|
||||
$output[] = $label . ':';
|
||||
}
|
||||
|
||||
$output[] = self::format_time( $timestamp );
|
||||
|
||||
return implode( ' ', $output );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates output for the 'ap_location' shortcode.
|
||||
*
|
||||
* @param ?array $atts The shortcode's attributes.
|
||||
* @return string The formatted location/address of the event.
|
||||
*/
|
||||
public function shortcode_location( $atts ) {
|
||||
$args = shortcode_atts(
|
||||
array(
|
||||
'icon' => 'true',
|
||||
'label' => 'true',
|
||||
'country' => 'true',
|
||||
'zip' => 'true',
|
||||
'city' => 'true',
|
||||
'street' => 'true',
|
||||
'name' => 'true',
|
||||
),
|
||||
$atts,
|
||||
'ap_location'
|
||||
);
|
||||
|
||||
// Convert attributes to booleans.
|
||||
$args = array_map(
|
||||
function ( $value ) {
|
||||
return filter_var( $value, FILTER_VALIDATE_BOOLEAN );
|
||||
},
|
||||
$args
|
||||
);
|
||||
|
||||
$location = $this->get_location();
|
||||
if ( is_null( $location ) ) {
|
||||
if ( ! $location ) {
|
||||
return '';
|
||||
}
|
||||
$address = $location->get_address();
|
||||
if ( ! $address ) {
|
||||
return $location->get_name();
|
||||
|
||||
$output = array();
|
||||
if ( $args['icon'] ) {
|
||||
$output[] = '📍';
|
||||
}
|
||||
if ( $args['label'] ) {
|
||||
$output[] = esc_html__( 'Location', 'event-bridge-for-activitypub' ) . ':';
|
||||
}
|
||||
|
||||
$output[] = self::format_address( $location->get_address(), $args );
|
||||
|
||||
// Join output array into a single string with spaces and return.
|
||||
return implode( ' ', array_filter( $output ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the address based on provided arguments.
|
||||
*
|
||||
* @param mixed $address The address data, either as a string or an array.
|
||||
* @param array $args The arguments for which components to include.
|
||||
* @return string The formatted address.
|
||||
*/
|
||||
protected static function format_address( $address, $args = null ) {
|
||||
if ( is_string( $address ) ) {
|
||||
return $address;
|
||||
return esc_html( $address );
|
||||
}
|
||||
if ( ! is_array( $address ) ) {
|
||||
return '';
|
||||
|
||||
if ( is_null( $args ) ) {
|
||||
$args = array(
|
||||
'icon' => 'true',
|
||||
'title' => 'true',
|
||||
'country' => 'true',
|
||||
'zip' => 'true',
|
||||
'city' => 'true',
|
||||
'street' => 'true',
|
||||
'name' => 'true',
|
||||
);
|
||||
}
|
||||
return isset( $address['locality'] ) ? $address['locality'] : '';
|
||||
|
||||
if ( is_array( $address ) ) {
|
||||
$address_parts = array();
|
||||
|
||||
$components = array(
|
||||
'name' => 'name',
|
||||
'street' => 'streetAddress',
|
||||
'zip' => 'postalCode',
|
||||
'city' => 'addressLocality',
|
||||
'country' => 'addressCountry',
|
||||
);
|
||||
|
||||
foreach ( $components as $arg_key => $address_key ) {
|
||||
if ( $args[ $arg_key ] && ! empty( $address[ $address_key ] ) ) {
|
||||
$address_parts[] = esc_html( $address[ $address_key ] );
|
||||
}
|
||||
}
|
||||
|
||||
return implode( ', ', $address_parts );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -255,6 +393,68 @@ abstract class Event extends Post {
|
|||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the shortcodes.
|
||||
*/
|
||||
public function register_shortcodes() {
|
||||
foreach ( get_class_methods( self::class ) as $function ) {
|
||||
if ( 'shortcode_' === substr( $function, 0, 10 ) ) {
|
||||
add_shortcode( 'ap_' . substr( $function, 10, strlen( $function ) ), array( $this, $function ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the shortcodes.
|
||||
*/
|
||||
public function unregister_shortcodes() {
|
||||
foreach ( get_class_methods( self::class ) as $function ) {
|
||||
if ( 'shortcode_' === substr( $function, 0, 10 ) ) {
|
||||
remove_shortcode( 'ap_' . substr( $function, 10, strlen( $function ) ), array( $this, $function ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the summary.
|
||||
*/
|
||||
public function get_summary(): ?string {
|
||||
if ( 'preset' === get_option( 'event_bridge_for_activitypub_summary_type', 'preset' ) ) {
|
||||
return $this->format_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.
|
||||
|
||||
Shortcodes::register();
|
||||
$this->register_shortcodes();
|
||||
|
||||
// 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( 'event_bridge_for_activitypub_the_summary', $summary, $post );
|
||||
|
||||
// Unregister the shortcodes.
|
||||
Shortcodes::unregister();
|
||||
$this->unregister_shortcodes();
|
||||
|
||||
return $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a custom summary.
|
||||
*
|
||||
|
@ -263,7 +463,7 @@ abstract class Event extends Post {
|
|||
*
|
||||
* @return string $summary The custom event summary.
|
||||
*/
|
||||
public function get_summary(): ?string {
|
||||
public function format_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.
|
||||
|
@ -274,9 +474,13 @@ abstract class Event extends Post {
|
|||
remove_filter( 'activitypub_object_content_template', array( self::class, 'remove_ap_permalink_from_template' ) );
|
||||
|
||||
$category = $this->format_categories();
|
||||
$start_time = $this->format_start_time();
|
||||
$end_time = $this->format_end_time();
|
||||
$address = $this->format_address();
|
||||
$start_time = $this->get_start_time();
|
||||
$end_time = $this->get_end_time();
|
||||
$address = $this->format_address( $this->get_location() );
|
||||
$time_atts = array(
|
||||
'icon' => true,
|
||||
'label' => true,
|
||||
);
|
||||
|
||||
$formatted_items = array();
|
||||
if ( ! empty( $category ) ) {
|
||||
|
@ -284,11 +488,11 @@ abstract class Event extends Post {
|
|||
}
|
||||
|
||||
if ( ! empty( $start_time ) ) {
|
||||
$formatted_items[] = '🗓️ ' . __( 'Start', 'event-bridge-for-activitypub' ) . ': ' . $start_time;
|
||||
$formatted_items[] = $this->generate_time_output( $start_time, $time_atts, '🗓️', __( 'Start', 'event-bridge-for-activitypub' ) );
|
||||
}
|
||||
|
||||
if ( ! empty( $end_time ) ) {
|
||||
$formatted_items[] = '⏳ ' . __( 'End', 'event-bridge-for-activitypub' ) . ': ' . $end_time;
|
||||
$formatted_items[] = $this->generate_time_output( $end_time, $time_atts, '⏳', __( 'End', 'event-bridge-for-activitypub' ) );
|
||||
}
|
||||
|
||||
if ( ! empty( $address ) ) {
|
||||
|
@ -308,6 +512,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( 'event_bridge_for_activitypub_custom_summary', EVENT_BRIDGE_FOR_ACTIVITYPUB_CUSTOM_SUMMARY );
|
||||
$template = $summary ?? EVENT_BRIDGE_FOR_ACTIVITYPUB_CUSTOM_SUMMARY;
|
||||
|
||||
return apply_filters( 'event_bridge_for_activitypub_summary_template', $template, $this->wp_object );
|
||||
}
|
||||
|
||||
/**
|
||||
* By default set the timezone of the WordPress site.
|
||||
*
|
||||
|
|
|
@ -23,7 +23,7 @@ final class EventPrime extends Event {
|
|||
/**
|
||||
* Get the end time from the event object.
|
||||
*/
|
||||
protected function get_end_time(): ?string {
|
||||
public function get_end_time(): ?string {
|
||||
$timestamp = get_post_meta( $this->wp_object->ID, 'em_end_date', true );
|
||||
if ( $timestamp ) {
|
||||
return \gmdate( 'Y-m-d\TH:i:s\Z', $timestamp );
|
||||
|
@ -35,7 +35,7 @@ final class EventPrime extends Event {
|
|||
/**
|
||||
* Get the end time from the event object.
|
||||
*/
|
||||
protected function get_start_time(): string {
|
||||
public function get_start_time(): string {
|
||||
$timestamp = get_post_meta( $this->wp_object->ID, 'em_start_date', true );
|
||||
if ( $timestamp ) {
|
||||
return \gmdate( 'Y-m-d\TH:i:s\Z', $timestamp );
|
||||
|
@ -47,7 +47,7 @@ final class EventPrime extends Event {
|
|||
/**
|
||||
* Get location from the event object.
|
||||
*/
|
||||
protected function get_location(): ?Place {
|
||||
public function get_location(): ?Place {
|
||||
$venue_term_id = get_post_meta( $this->wp_object->ID, 'em_venue', true );
|
||||
if ( ! $venue_term_id ) {
|
||||
return null;
|
||||
|
|
|
@ -73,14 +73,14 @@ final class GatherPress extends Event {
|
|||
/**
|
||||
* Get the end time from the event object.
|
||||
*/
|
||||
protected function get_end_time(): ?string {
|
||||
public function get_end_time(): ?string {
|
||||
return $this->gp_event->get_datetime_end( 'Y-m-d\TH:i:s\Z' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end time from the event object.
|
||||
*/
|
||||
protected function get_start_time(): string {
|
||||
public function get_start_time(): string {
|
||||
return $this->gp_event->get_datetime_start( 'Y-m-d\TH:i:s\Z' );
|
||||
}
|
||||
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ final class VS_Event_List extends Event_Transformer {
|
|||
/**
|
||||
* Get the end time from the events metadata.
|
||||
*/
|
||||
protected function get_end_time(): ?string {
|
||||
public function get_end_time(): ?string {
|
||||
if ( 'yes' === get_post_meta( $this->wp_object->ID, 'event-hide-end-time', true ) ) {
|
||||
return null;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ final class VS_Event_List extends Event_Transformer {
|
|||
/**
|
||||
* Get the end time from the events metadata.
|
||||
*/
|
||||
protected function get_start_time(): string {
|
||||
public function get_start_time(): string {
|
||||
$start_time = get_post_meta( $this->wp_object->ID, 'event-start-date', true );
|
||||
return \gmdate( 'Y-m-d\TH:i:s\Z', $start_time );
|
||||
}
|
||||
|
|
|
@ -71,6 +71,28 @@ class Settings {
|
|||
'default' => 1,
|
||||
)
|
||||
);
|
||||
|
||||
\register_setting(
|
||||
'event-bridge-for-activitypub',
|
||||
'event_bridge_for_activitypub_summary_type',
|
||||
array(
|
||||
'type' => 'string',
|
||||
'description' => \__( 'Summary type to use for ActivityStreams', 'event-bridge-for-activitypub' ),
|
||||
'show_in_rest' => true,
|
||||
'default' => 'preset',
|
||||
)
|
||||
);
|
||||
|
||||
\register_setting(
|
||||
'event-bridge-for-activitypub',
|
||||
'event_bridge_for_activitypub_custom_summary',
|
||||
array(
|
||||
'type' => 'string',
|
||||
'description' => \__( 'Define your own custom summary template for events', 'event-bridge-for-activitypub' ),
|
||||
'show_in_rest' => true,
|
||||
'default' => EVENT_BRIDGE_FOR_ACTIVITYPUB_CUSTOM_SUMMARY,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -42,6 +42,52 @@ $current_category_mapping = \get_option( 'event_bridge_for_activitypub_ev
|
|||
<div class="event-bridge-for-activitypub-settings event-bridge-for-activitypub-settings-page hide-if-no-js">
|
||||
<form method="post" action="options.php">
|
||||
<?php \settings_fields( 'event-bridge-for-activitypub' ); ?>
|
||||
<div class="box">
|
||||
<h2> <?php esc_html_e( 'Event Summary Text', 'event-bridge-for-activitypub' ); ?> </h2>
|
||||
<p><?php esc_html_e( 'Many Fediverse applications (e.g., Mastodon) don\'t fully support events, instead they will show a summary text along with the events title and the URL to your Website.', 'event-bridge-for-activitypub' ); ?></p>
|
||||
<p>
|
||||
<label for="event_bridge_for_activitypub_summary_type_preset">
|
||||
<input type="radio" name="event_bridge_for_activitypub_summary_type" id="event_bridge_for_activitypub_summary_type_preset" value="preset" <?php echo \checked( 'preset', \get_option( 'event_bridge_for_activitypub_summary_type', EVENT_BRIDGE_FOR_ACTIVITYPUB_DEFAULT_SUMMARY_TYPE ) ); ?> />
|
||||
<?php \esc_html_e( 'Automatic (default)', 'activitypub' ); ?>
|
||||
-
|
||||
<span class="description">
|
||||
<?php \esc_html_e( 'Let the plugin compose a summary for you. ', 'event-bridge-for-activitypub' ); ?>
|
||||
</span>
|
||||
</label>
|
||||
</p>
|
||||
<p>
|
||||
<label for="event_bridge_for_activitypub_summary_type_custom">
|
||||
<input type="radio" name="event_bridge_for_activitypub_summary_type" id="event_bridge_for_activitypub_summary_type_custom" value="custom" <?php echo \checked( 'custom', \get_option( 'event_bridge_for_activitypub_summary_type', EVENT_BRIDGE_FOR_ACTIVITYPUB_DEFAULT_SUMMARY_TYPE ) ); ?> />
|
||||
<?php \esc_html_e( 'Custom', 'event-bridge-for-activitypub' ); ?>
|
||||
-
|
||||
<span class="description">
|
||||
<?php \esc_html_e( 'For advanced users: compose your custom summary via shortcodes.', 'event-bridge-for-activitypub' ); ?>
|
||||
</span>
|
||||
</label>
|
||||
</p>
|
||||
<div id="event_bridge_for_activitypub_summary_type_custom-details">
|
||||
<textarea name="event_bridge_for_activitypub_custom_summary" id="event_bridge_for_activitypub_custom_summary" rows="10" cols="50" class="large-text" placeholder="<?php echo wp_kses( EVENT_BRIDGE_FOR_ACTIVITYPUB_CUSTOM_SUMMARY, 'post' ); ?>"><?php echo esc_textarea( wp_kses( \get_option( 'event_bridge_for_activitypub_custom_summary', EVENT_BRIDGE_FOR_ACTIVITYPUB_CUSTOM_SUMMARY ), 'post' ) ); ?></textarea>
|
||||
<details>
|
||||
<summary><?php esc_html_e( 'See a list Template Tags available for the summary.', 'activitypub' ); ?></summary>
|
||||
<div class="description">
|
||||
<dl>
|
||||
<dt><code>[ap_start_time]</code><dt>
|
||||
<dd><?php \esc_html_e( 'The events title.', 'event-bridge-for-activitypub' ); ?></dd>
|
||||
<dt><code>[ap_end_time]</code><dt>
|
||||
<dd><?php \esc_html_e( 'The events content.', 'event-bridge-for-activitypub' ); ?></dd>
|
||||
<dt><code>[ap_location]</code><dt>
|
||||
<dd><?php \esc_html_e( 'The events location.', 'event-bridge-for-activitypub' ); ?></dd>
|
||||
<dt><code>[ap_hashtags]</code><dt>
|
||||
<dd><?php \esc_html_e( 'The events tags as hashtags.', 'event-bridge-for-activitypub' ); ?></dd>
|
||||
<dt><code>[ap_excerpt]</code><dt>
|
||||
<dd><?php \esc_html_e( 'The events excerpt (may be truncated).', 'event-bridge-for-activitypub' ); ?></dd>
|
||||
<dt><code>[ap_content]</code><dt>
|
||||
<dd><?php \esc_html_e( 'The events description.', 'event-bridge-for-activitypub' ); ?></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h2> <?php esc_html_e( 'ActivityPub Event Category', 'event-bridge-for-activitypub' ); ?> </h2>
|
||||
|
|
|
@ -25,6 +25,21 @@ if ( ! file_exists( "{$_tests_dir}/includes/functions.php" ) ) {
|
|||
// Give access to tests_add_filter() function.
|
||||
require_once "{$_tests_dir}/includes/functions.php";
|
||||
|
||||
/**
|
||||
* Function to manually load an event plugin.
|
||||
*
|
||||
* @param string $plugin_file The main plugin file of the event plugin.
|
||||
*/
|
||||
function _manually_load_event_plugin( $plugin_file ) {
|
||||
$plugin_dir = ABSPATH . '/wp-content/plugins/';
|
||||
require_once $plugin_dir . $plugin_file;
|
||||
update_option( 'purchase_history_table_structure_migration_done', true );
|
||||
$current = get_option( 'active_plugins', array() );
|
||||
$current[] = $plugin_file;
|
||||
sort( $current );
|
||||
update_option( 'active_plugins', $current );
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually load the plugin being tested and its integrations.
|
||||
*/
|
||||
|
@ -80,13 +95,12 @@ function _manually_load_plugin() {
|
|||
}
|
||||
|
||||
if ( $plugin_file ) {
|
||||
// Manually load the event plugin.
|
||||
require_once $plugin_dir . $plugin_file;
|
||||
update_option( 'purchase_history_table_structure_migration_done', true );
|
||||
$current = get_option( 'active_plugins', array() );
|
||||
$current[] = $plugin_file;
|
||||
sort( $current );
|
||||
update_option( 'active_plugins', $current );
|
||||
_manually_load_event_plugin( $plugin_file );
|
||||
} else {
|
||||
// For all other tests we mainly use the Events Calendar as a reference.
|
||||
_manually_load_event_plugin( 'the-events-calendar/the-events-calendar.php' );
|
||||
_manually_load_event_plugin( 'very-simple-event-list/vsel.php' );
|
||||
|
||||
}
|
||||
|
||||
// Hot fix that allows using Events Manager within unit tests, because the em_init() is later not run as admin.
|
||||
|
|
193
tests/test-class-activitypub-event-bridge-shortcodes.php
Normal file
193
tests/test-class-activitypub-event-bridge-shortcodes.php
Normal file
|
@ -0,0 +1,193 @@
|
|||
<?php
|
||||
/**
|
||||
* Test file for Activitypub Shortcodes.
|
||||
*
|
||||
* @package Event_Bridge_For_ActivityPub
|
||||
* @license AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
use Activitypub\Shortcodes;
|
||||
|
||||
/**
|
||||
* Test class for Activitypub Shortcodes.
|
||||
*
|
||||
* @coversDefaultClass \Activitypub\Shortcodes
|
||||
*/
|
||||
class Test_Activitypub_Event_Bridge_Shortcodes extends WP_UnitTestCase {
|
||||
/**
|
||||
* Override the setup function, so that tests don't run if the Events Calendar is not active.
|
||||
*/
|
||||
public function set_up() {
|
||||
parent::set_up();
|
||||
|
||||
if ( ! class_exists( '\Tribe__Events__Main' ) ) {
|
||||
self::markTestSkipped( 'The Events Calendar plugin is needed to test Event Shortcodes' );
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
// Delete all posts afterwards.
|
||||
_delete_all_posts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the shortcode for rendering the events start time.
|
||||
*/
|
||||
public function test_start_time() {
|
||||
// Create a The Events Calendar Event without content.
|
||||
$wp_object = tribe_events()
|
||||
->set_args( Test_The_Events_Calendar::MOCKUP_EVENTS['minimal_event'] )
|
||||
->create();
|
||||
|
||||
// Call the transformer Factory.
|
||||
$transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object );
|
||||
|
||||
if ( ! $transformer instanceof \Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$transformer->register_shortcodes();
|
||||
|
||||
$summary = '[ap_start_time]';
|
||||
$summary = do_shortcode( $summary );
|
||||
$this->assertEquals( '🗓️ Start: December 1, 2024 3:00 pm', $summary );
|
||||
|
||||
$summary = '[ap_start_time icon="false"]';
|
||||
$summary = do_shortcode( $summary );
|
||||
$this->assertEquals( 'Start: December 1, 2024 3:00 pm', $summary );
|
||||
|
||||
$summary = '[ap_start_time icon="false" label="false"]';
|
||||
$summary = do_shortcode( $summary );
|
||||
$this->assertEquals( 'December 1, 2024 3:00 pm', $summary );
|
||||
|
||||
$transformer->unregister_shortcodes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the shortcode for rendering the events end time.
|
||||
*/
|
||||
public function test_end_time() {
|
||||
// Create a The Events Calendar Event without content.
|
||||
$wp_object = tribe_events()
|
||||
->set_args( Test_The_Events_Calendar::MOCKUP_EVENTS['minimal_event'] )
|
||||
->create();
|
||||
|
||||
// Call the transformer Factory.
|
||||
$transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object );
|
||||
|
||||
if ( ! $transformer instanceof \Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$transformer->register_shortcodes();
|
||||
|
||||
$summary = '[ap_end_time]';
|
||||
$summary = do_shortcode( $summary );
|
||||
$this->assertEquals( '⏳ End: December 1, 2024 4:00 pm', $summary );
|
||||
|
||||
$summary = '[ap_end_time icon="false"]';
|
||||
$summary = do_shortcode( $summary );
|
||||
$this->assertEquals( 'End: December 1, 2024 4:00 pm', $summary );
|
||||
|
||||
$summary = '[ap_end_time icon="false" label="false"]';
|
||||
$summary = do_shortcode( $summary );
|
||||
$this->assertEquals( 'December 1, 2024 4:00 pm', $summary );
|
||||
|
||||
$transformer->unregister_shortcodes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the shortcode for rendering the events location when no location is set.
|
||||
*/
|
||||
public function test_location_when_no_location_is_set() {
|
||||
// Create a The Events Calendar Event without content.
|
||||
$wp_object = tribe_events()
|
||||
->set_args( Test_The_Events_Calendar::MOCKUP_EVENTS['minimal_event'] )
|
||||
->create();
|
||||
|
||||
// Call the transformer Factory.
|
||||
$transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object );
|
||||
|
||||
if ( ! $transformer instanceof \Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$transformer->register_shortcodes();
|
||||
|
||||
$summary = '[ap_location]';
|
||||
$summary = do_shortcode( $summary );
|
||||
$this->assertEquals( '', $summary );
|
||||
|
||||
$transformer->unregister_shortcodes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the shortcode for rendering the events location when location is set.
|
||||
*/
|
||||
public function test_location_when_location_is_set() {
|
||||
// Create Venue.
|
||||
$venue = tribe_venues()->set_args( Test_The_Events_Calendar::MOCKUP_VENUS['minimal_venue'] )->create();
|
||||
// Create a The Events Calendar Event.
|
||||
$wp_object = tribe_events()
|
||||
->set_args( Test_The_Events_Calendar::MOCKUP_EVENTS['complex_event'] )
|
||||
->set( 'venue', $venue->ID )
|
||||
->create();
|
||||
|
||||
// Call the transformer Factory.
|
||||
$transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object );
|
||||
|
||||
if ( ! $transformer instanceof \Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$transformer->register_shortcodes();
|
||||
|
||||
$summary = '[ap_location]';
|
||||
$summary = do_shortcode( $summary );
|
||||
$this->assertEquals( '📍 Location: Minimal Venue', $summary );
|
||||
|
||||
$summary = '[ap_location icon="false"]';
|
||||
$summary = do_shortcode( $summary );
|
||||
$this->assertEquals( 'Location: Minimal Venue', $summary );
|
||||
|
||||
$summary = '[ap_location icon="false" label="false"]';
|
||||
$summary = do_shortcode( $summary );
|
||||
$this->assertEquals( 'Minimal Venue', $summary );
|
||||
|
||||
$transformer->unregister_shortcodes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the shortcode for rendering the events location when location with detailed address is set.
|
||||
*/
|
||||
public function test_location_when_detailed_location_is_set() {
|
||||
// Create Venue.
|
||||
$venue = tribe_venues()->set_args( Test_The_Events_Calendar::MOCKUP_VENUS['complex_venue'] )->create();
|
||||
// Create a The Events Calendar Event.
|
||||
$wp_object = tribe_events()
|
||||
->set_args( Test_The_Events_Calendar::MOCKUP_EVENTS['complex_event'] )
|
||||
->set( 'venue', $venue->ID )
|
||||
->create();
|
||||
|
||||
// Call the transformer Factory.
|
||||
$transformer = \Activitypub\Transformer\Factory::get_transformer( $wp_object );
|
||||
|
||||
if ( ! $transformer instanceof \Event_Bridge_For_ActivityPub\Activitypub\Transformer\Event ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$transformer->register_shortcodes();
|
||||
|
||||
$summary = '[ap_location]';
|
||||
$summary = do_shortcode( $summary );
|
||||
$this->assertEquals( '📍 Location: Complex Venue, Venue address, Venue zip, Venue city, Venue country', $summary );
|
||||
|
||||
$summary = '[ap_location country="false"]';
|
||||
$summary = do_shortcode( $summary );
|
||||
$this->assertEquals( '📍 Location: Complex Venue, Venue address, Venue zip, Venue city', $summary );
|
||||
|
||||
$transformer->unregister_shortcodes();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue