Compare commits

...

13 commits

Author SHA1 Message Date
2257e86f0f Merge branch 'format_summary'
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 35s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 59s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 1m3s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 56s
2024-09-28 16:38:29 +02:00
11bf3a2048 add node_modules to gitignore
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 36s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 1m5s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 59s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 1m0s
2024-09-28 16:18:00 +02:00
6f744b9e14 Cleanup top of PHP files (#40)
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 32s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 57s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 58s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 1m5s
- sorting use statements
- always check for `ABSPATH` after namespace

Reviewed-on: #40
Co-authored-by: André Menrath <andre.menrath@posteo.de>
Co-committed-by: André Menrath <andre.menrath@posteo.de>
2024-09-28 13:14:10 +02:00
c599384006 improve readme text
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 33s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 58s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 54s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 57s
2024-09-28 11:51:43 +02:00
f92c5853ad First draft of a proper Readme (targeting WordPress.org) (#39)
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 33s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 56s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 1m0s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 56s
Reviewed-on: #39
Co-authored-by: André Menrath <andre.menrath@posteo.de>
Co-committed-by: André Menrath <andre.menrath@posteo.de>
2024-09-28 11:45:47 +02:00
19457a9f19 The Events Calendar: add categories to ActivityStreams tag (#37)
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 36s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 56s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 55s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 54s
Reviewed-on: #37
Co-authored-by: André Menrath <andre.menrath@posteo.de>
Co-committed-by: André Menrath <andre.menrath@posteo.de>
2024-09-27 23:20:30 +02:00
7ab51b104e Fix location for tribe (#36)
All checks were successful
PHP Code Checker / PHP Code Checker (push) Successful in 35s
PHPUnit / PHPUnit – PHP 8.1 (push) Successful in 59s
PHPUnit / PHPUnit – PHP 8.2 (push) Successful in 1m0s
PHPUnit / PHPUnit – PHP 8.3 (push) Successful in 57s
Updates did not work. Always use the tribe_event instead of the wp_object where ever possible!

Reviewed-on: #36
Co-authored-by: André Menrath <andre.menrath@posteo.de>
Co-committed-by: André Menrath <andre.menrath@posteo.de>
2024-09-27 18:04:29 +02:00
3dbd3e21ee phpdocs, phpcs
All checks were successful
PHP Code Checker / PHP Code Checker (pull_request) Successful in 39s
PHPUnit / PHPUnit – PHP 8.1 (pull_request) Successful in 1m10s
PHPUnit / PHPUnit – PHP 8.2 (pull_request) Successful in 1m9s
PHPUnit / PHPUnit – PHP 8.3 (pull_request) Successful in 1m4s
2024-09-26 15:51:23 +02:00
20f0ea2823 add filter to never include permalink in summary
Some checks failed
PHP Code Checker / PHP Code Checker (pull_request) Failing after 48s
PHPUnit / PHPUnit – PHP 8.1 (pull_request) Successful in 1m10s
PHPUnit / PHPUnit – PHP 8.2 (pull_request) Successful in 1m17s
PHPUnit / PHPUnit – PHP 8.3 (pull_request) Successful in 1m4s
2024-09-26 15:44:22 +02:00
c13230ac6f fix more function return types in transformers
All checks were successful
PHP Code Checker / PHP Code Checker (pull_request) Successful in 33s
PHPUnit / PHPUnit – PHP 8.1 (pull_request) Successful in 1m3s
PHPUnit / PHPUnit – PHP 8.2 (pull_request) Successful in 57s
PHPUnit / PHPUnit – PHP 8.3 (pull_request) Successful in 52s
2024-09-25 14:30:37 +02:00
4d4328f3fd add missing phpdoc
Some checks failed
PHP Code Checker / PHP Code Checker (pull_request) Successful in 34s
PHPUnit / PHPUnit – PHP 8.1 (pull_request) Failing after 57s
PHPUnit / PHPUnit – PHP 8.2 (pull_request) Failing after 58s
PHPUnit / PHPUnit – PHP 8.3 (pull_request) Failing after 50s
2024-09-25 14:25:27 +02:00
35bd198f47 fix return types of transformer functions
Some checks failed
PHP Code Checker / PHP Code Checker (pull_request) Failing after 36s
PHPUnit / PHPUnit – PHP 8.2 (pull_request) Has been cancelled
PHPUnit / PHPUnit – PHP 8.3 (pull_request) Has been cancelled
PHPUnit / PHPUnit – PHP 8.1 (pull_request) Has been cancelled
2024-09-25 14:24:30 +02:00
ac99300949 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
2024-09-25 13:59:31 +02:00
17 changed files with 426 additions and 135 deletions

3
.gitignore vendored
View file

@ -1,3 +1,4 @@
vendor
vendor/
composer.lock
.phpunit.result.cache
node_modules/

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View file

@ -1,26 +1,92 @@
This is a WordPress plugin improves the Fediverse integration of Events via the [WordPress ActivityPub plugin](https://wordpress.org/plugins/activitypub/).
# ActivityPub Event Extensions
> **_NOTE:_** This is still pre-alpha. It is not more than a skeleton/playground. Things change rapidly. Please contact us, instead of trying it out yourself at this time.
Contributors: andremenrath
Tags: events, fediverse, activitypub,, calendar
Requires at least: 6.5
Tested up to: 6.6
Stable tag: 0.1.0
Requires PHP: 8.1
License: AGPL-3.0-or-later
License URI: https://www.gnu.org/licenses/agpl-3.0.html
For more information checkout our website https://event-federation.eu/. You can follow updates via [RSS](https://event-federation.eu/feed/) or ActivityPub: [@blog@event-federation.eu](https://event-federation.eu/blog/).
Integrating popular event plugins with the ActivityPub plugin.
## Goals
* Proper ActivityPub (JSON-LD) representation of events within WordPress
* Improving the setup and configuration workflow of ActivityPub
* Researching/Implementing federated RSVP/attendee management
![](.wordpress-org/banner-1544x500.jpg)
## Supported Event Plugins
## Description
### Events plugin that will be supported at first:
Make your events more discoverable, expand your reach effortlessly while being independent of other (commercial) platforms, and part of the growing decentralized web.
With the ActivityPub Event Extensions Plugin for WordPress, your events can be automatically aggregated and displayed across decentralized platforms like [Mastodon](https://joinmastodon.org) or [Gancio](https://gancio.org), without any extra work.
Forget the hassle of managing multiple social media accounts just to keep your audience informed.
This plugin is not an event managing plugin but an add-on to popular event plugins. It extends their functionality to fully support the [ActivityPub plugin](https://wordpress.org/plugins/activitypub/).
With the ActivityPub plugin people can follow your website directly and engage with your events just as they would on social media - liking, boosting and even commenting if you enable it.
You retain full ownership of your content. By integrating into your existing setup, it ensures no extra work is needed while enhancing your events' visibility across the Fediverse.
### How It Works
With the Event Federation Plugin for WordPress, sharing your events is effortless and automatic!
Once you create an event on your WordPress site, it is seamlessly shared across the decentralized web using the ActivityPub protocol.
<p align="center">
<img src="./.wordpress-org/event-activitypub-publishing.gif" alt="Logo" width="250" />
</p>
Your events can be automatically delivered to platforms that fully support events, such as [Mobilizon](https://joinmobilizon.org/), [Gancio](https://gancio.org), [Friendica](https://friendi.ca), [Hubzilla](https://hubzilla.org), and [Pleroma](https://pleroma.social/).
These platforms create public event calendars by pulling in events from various sources, including your website. Any updates you make to your events are synced across these platforms—so you only need to manage your events on your own site, with no extra work required.
<p align="center">
<img src="./.wordpress-org/decentralized-event-calenders.gif" alt="Logo" width="250" />
</p>
Even platforms that dont yet fully support events, like [Mastodon](https://joinmastodon.org), will still receive a detailed, well-composed summary of your event.
The Event Federation Plugin ensures that users from those platforms are provided with all important information about an event.
## Installation
This plugin depends on the [ActivityPub plugin](https://wordpress.org/plugins/activitypub/). Additionally, you need to use one of the supported Event Plugins. See below.
### Supported Event Plugins
* [The Events Calendar](https://de.wordpress.org/plugins/the-events-calendar/)
* [VS Event List](https://de.wordpress.org/plugins/very-simple-event-list/)
* [Events Manager](https://de.wordpress.org/plugins/events-manager/)
* [GatherPress](https://github.com/GatherPress/gatherpress)
### Later:
- [All in One Events Calendar](https://de.wordpress.org/plugins/all-in-one-event-calendar/)
- TBA
## Configuration
### Your event plugin:
- [**Contact us**](https://event-federation.eu/contact/), if you want to see your event plugin on the list.
If youre new to the [ActivityPub plugin](https://wordpress.org/plugins/activitypub/), its recommended to spend a few minutes reading through its documentation to familiarize yourself with its setup and functionality.
## Frequently Asked Questions
### Do I need to install another event plugin to use the Event Federation Plugin?
Yes, this plugin works needs a supported event plugin such as The Events Calendar, VS Event List, or Events Manager to manage your events. It just fills the missing gap between event plugins and the [ActivityPub plugin](https://wordpress.org/plugins/activitypub/).
### What platforms can follow my events?
Your events can be followed on platforms that support ActivityPub like [Mobilizon](https://joinmobilizon.org/), [Gancio](https://gancio.org), [Friendica](https://friendi.ca), [Hubzilla](https://hubzilla.org), and [Pleroma](https://pleroma.social/). Even other applications like [Mastodon](https://joinmastodon.org), which dont fully support events yet, will display a all important information about the events.
### How much extra work is required to maintain my events across the decentralized Web?
None! Once the plugin is set up, your events are automatically sent to all connected platforms or account that follow you (your Website). Any updates you make to your events are synced without additional effort.
### Can I still use social media to promote my events?
Yes, you can still use traditional social media if you wish. However, this plugin helps reduce reliance on commercial platforms by connecting your events to the decentralized Fediverse.
### Will this plugin work if I don't use the ActivityPub plugin?
No, the Event Federation Plugin depends on the ActivityPub plugin to deliver your events across decentralized platforms, so it's essential to have it installed and configured.
### My event plugin is not supported, what can I do?
If you know about coding have a look at the documentation of how to add your plugin or open an [issue](https://code.event-federation.eu/Event-Federation/wordpress-activitypub-event-extensions/issues), if we can spare some free hours we might add it.
### What if I experience problems?
We're always interested in your feedback. Feel free to reach out to us via [E-Mail](https://event-federation.eu/contact/) or create an [issue](https://code.event-federation.eu/Event-Federation/wordpress-activitypub-event-extensions/issues).
## Changelog
### [0.1.0] 2024-10-01
* Initial alpha release on WordPress.org

View file

@ -13,7 +13,7 @@
*
* Requires at least ActivityPub plugin with version >= 3.2.2. ActivityPub plugin tested up to: 3.2.2.
*
* @package activitypub-event-extensions
* @package Activitypub_Event_Extensions
* @license AGPL-3.0-or-later
*/

View file

@ -8,10 +8,13 @@
namespace Activitypub_Event_Extensions\Activitypub\Transformer;
use Activitypub\Activity\Extended_Object\Event as Event_Object;
use Activitypub\Transformer\Post;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
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;
use DateTime;
/**
* Base transformer for WordPress event post types to ActivityPub events.
@ -19,7 +22,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 +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.
*

View file

@ -8,17 +8,17 @@
namespace Activitypub_Event_Extensions\Activitypub\Transformer;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use Activitypub\Activity\Extended_Object\Event;
use Activitypub\Activity\Extended_Object\Place;
use Activitypub_Event_Extensions\Activitypub\Transformer\Event as Event_Transformer;
use DateTime;
use DateTimeZone;
use EM_Event;
use Activitypub\Activity\Extended_Object\Event;
use Activitypub\Activity\Extended_Object\Place;
use function Activitypub\esc_hashtag;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
use function Activitypub\esc_hashtag;
/**
* ActivityPub Transformer for events from the WordPress plugin 'Events Manager'
@ -89,7 +89,7 @@ final class Events_Manager extends Event_Transformer {
*
* @return array The Place.
*/
public function get_location() {
public function get_location(): ?Place {
if ( 'url' === $this->em_event->event_location_type ) {
return null;
}
@ -125,14 +125,14 @@ final class Events_Manager extends Event_Transformer {
/**
* Get the end time from the events metadata.
*/
public function get_end_time() {
public function get_end_time(): ?string {
return null;
}
/**
* 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;
$time_string = $this->em_event->event_start_time;
$timezone_string = $this->em_event->event_timezone;
@ -181,7 +181,7 @@ final class Events_Manager extends Event_Transformer {
/**
* Hardcoded function for generating a summary.
*/
public function get_summary() {
public function get_summary(): ?string {
if ( $this->em_event->post_excerpt ) {
$excerpt = $this->em_event->post_excerpt;
} else {

View file

@ -8,18 +8,15 @@
namespace Activitypub_Event_Extensions\Activitypub\Transformer;
use Activitypub_Event_Extensions\Activitypub\Transformer\Event;
use Activitypub\Model\Blog;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use Activitypub\Activity\Extended_Object\Event as Event_Object;
use Activitypub\Activity\Extended_Object\Place;
use Activitypub\Model\Blog;
use Activitypub_Event_Extensions\Activitypub\Transformer\Event;
use GatherPress\Core\Event as GatherPress_Event;
use function Activitypub\get_rest_url_by_path;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* ActivityPub Transformer for VS Event
*
@ -81,7 +78,7 @@ final class GatherPress extends Event {
*
* @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'];
if ( $address ) {
$place = new Place();
@ -97,14 +94,14 @@ final class GatherPress extends Event {
/**
* 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' );
}
/**
* 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' );
}

View file

@ -8,16 +8,16 @@
namespace Activitypub_Event_Extensions\Activitypub\Transformer;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use Activitypub_Event_Extensions\Activitypub\Transformer\Event;
use Activitypub\Activity\Extended_Object\Place;
use Activitypub\Activity\Extended_Object\Event as Event_Object;
use WP_Error;
use Activitypub\Activity\Extended_Object\Place;
use Activitypub_Event_Extensions\Activitypub\Transformer\Event;
use WP_Post;
use function Activitypub\esc_hashtag;
/**
* ActivityPub Tribe Transformer
*
@ -47,24 +47,36 @@ final class The_Events_Calendar extends Event {
}
/**
* Get tribe category of wp_post
* Get the tags, including also the set categories from The Events Calendar.
*
* @return string|null tribe category if it exists
* @return ?array The array if tags,
*/
public function get_tribe_category() {
$categories = tribe_get_event_cat_slugs( $this->wp_object->ID );
if ( count( $categories ) === 0 ) {
return null;
public function get_tag(): ?array {
$tags = array();
$category_ids = tribe_get_event_cat_ids();
if ( $category_ids ) {
foreach ( $category_ids as $category_id ) {
$term = \get_term( $category_id );
$tag = array(
'type' => 'Hashtag',
'href' => \esc_url( \get_term_link( $term ) ),
'name' => esc_hashtag( $term->name ),
);
$tags[] = $tag;
}
}
$tags[] = parent::get_tag();
return $categories[0];
return $tags;
}
/**
* Get the end time from the event object.
*/
protected function get_end_time() {
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() );
return \gmdate( 'Y-m-d\TH:i:s\Z', $date->getTimestamp() );
}
@ -72,7 +84,7 @@ final class The_Events_Calendar extends Event {
/**
* 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() );
return \gmdate( 'Y-m-d\TH:i:s\Z', $date->getTimestamp() );
}
@ -83,20 +95,16 @@ final class The_Events_Calendar extends Event {
* @return string status of the event
*/
public function get_tribe_status() {
if ( 'canceled' === $this->tribe_event->event_status ) {
return 'CANCELLED';
}
if ( 'postponed' === $this->tribe_event->event_status ) {
return 'CANCELLED'; // This will be reflected in the cancelled reason.
}
if ( '' === $this->tribe_event->event_status ) {
return 'CONFIRMED';
}
return new WP_Error( 'invalid event_status value', __( 'invalid event_status', 'activitypub' ), array( 'status' => 404 ) );
return 'CONFIRMED';
}
/**
* Check if the comments are enabled for the current event.
*/
@ -119,7 +127,6 @@ final class The_Events_Calendar extends Event {
* @return string The content.
*/
protected function get_content() {
$content = parent::get_content();
// /BeforeFirstRelease:
// * remove link at the end of the content.
@ -136,7 +143,7 @@ final class The_Events_Calendar extends Event {
*/
public function get_location(): Place|null {
// Get short handle for the venues.
$venues = $this->wp_object->venues;
$venues = $this->tribe_event->venues;
// Get first venue. We currently only support a single venue.
if ( $venues instanceof \Tribe\Events\Collections\Lazy_Post_Collection ) {
@ -181,6 +188,8 @@ final class The_Events_Calendar extends Event {
$location = new Place();
if ( count( $address ) > 1 ) {
$location->set_address( $address );
} else {
$location->set_address( $venue->post_title );
}
$location->set_id( $venue->permalink );
$location->set_name( $venue->post_title );

View file

@ -8,16 +8,12 @@
namespace Activitypub_Event_Extensions\Activitypub\Transformer;
use Activitypub_Event_Extensions\Activitypub\Transformer\Event as Event_Transformer;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
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.
}
use Activitypub_Event_Extensions\Activitypub\Transformer\Event as Event_Transformer;
/**
* ActivityPub Transformer for VS Event.
@ -34,17 +30,6 @@ final class VS_Event_List extends Event_Transformer {
*/
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.
*
@ -71,6 +56,9 @@ final class VS_Event_List extends Event_Transformer {
return null;
}
$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;
}
@ -79,7 +67,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 );
}
/**
@ -118,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
* ActivityPub object type 'Event' is not supported, e.g. in Mastodon.
*
* @return string $summary The custom event summary.
* @return ?string
*/
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 );
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 {
$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;
}
}

View file

@ -11,6 +11,9 @@
namespace Activitypub_Event_Extensions\Admin;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use Activitypub_Event_Extensions\Plugins\Event_Plugin;
/**

View file

@ -11,6 +11,9 @@
namespace Activitypub_Event_Extensions\Admin;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
/**
* Class responsible for general admin notices.
*

View file

@ -11,12 +11,12 @@
namespace Activitypub_Event_Extensions\Admin;
use Activitypub_Event_Extensions\Setup;
use Activitypub_Event_Extensions\Plugins\Event_Plugin;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use Activitypub_Event_Extensions\Plugins\Event_Plugin;
use Activitypub_Event_Extensions\Setup;
/**
* Class responsible for the ActivityPub Event Extension related Settings.
*

View file

@ -11,11 +11,11 @@
namespace Activitypub_Event_Extensions;
use Activitypub\Activity\Extended_Object\Event;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use Activitypub\Activity\Extended_Object\Event;
/**
* Class responsible for the ActivityPui Event Extension related Settings.
*

View file

@ -12,14 +12,14 @@
namespace Activitypub_Event_Extensions;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
use Activitypub_Event_Extensions\Admin\Event_Plugin_Admin_Notices;
use Activitypub_Event_Extensions\Admin\General_Admin_Notices;
use Activitypub_Event_Extensions\Admin\Settings_Page;
use Activitypub_Event_Extensions\Plugins\Event_Plugin;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
require_once ABSPATH . 'wp-admin/includes/plugin.php';
/**

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

View file

@ -1,53 +1,82 @@
=== ActivityPub Event Extensions ===
Contributors: menrath
Tags: events, fediverse, activitypub, activitystreams
Requires at least: 5.5
Tested up to: 6.4
Stable tag: 1.0.0
Requires PHP: 7.4
Contributors: andremenrath
Tags: events, fediverse, activitypub, activitystreams, calendar
Requires at least: 6.5
Tested up to: 6.6
Stable tag: 0.1.0
Requires PHP: 8.1
License: AGPL-3.0-or-later
License URI: https://www.gnu.org/licenses/agpl-3.0.html
The ActivityPub Event Extensions
Integrating popular event plugins with the ActivityPub plugin.
== Description ==
With this event others can automatically aggregate and display events published on your website!
Additionally, people who do not want to miss on of your events will not have to follow a social-media account of yours that you maintain on the website of another party (and thereby you push the people to use these platforms), but could just follow your website directly.
Following like in social media, including all features you know like boosting, liking or commenting.
And the best: as you already publish events on your website, this means no extra work for you.
In the long term it actually might lead to less work and you help to provide a momentum to become independent of commercial platforms like Facebook and co.
For more details read our detailed project description.
Make your events more discoverable, expand your reach effortlessly while being independent of other (commercial) platforms, and part of the growing decentralized web.
With the ActivityPub Event Extensions Plugin for WordPress, your events can be automatically aggregated and displayed across decentralized platforms like [Mastodon](https://joinmastodon.org) or [Gancio](https://gancio.org), without any extra work.
Forget the hassle of managing multiple social media accounts just to keep your audience informed.
This plugin is not an event managing plugin but an add-on to popular event plugins. It extends their functionality to fully support the [ActivityPub plugin](https://wordpress.org/plugins/activitypub/).
With the ActivityPub plugin people can follow your website directly and engage with your events just as they would on social media - liking, boosting and even commenting if you enable it.
You retain full ownership of your content. By integrating into your existing setup, it ensures no extra work is needed while enhancing your events' visibility across the Fediverse.
= How It Works =
With the Event Federation Plugin for WordPress, sharing your events is effortless and automatic!
Once you create an event on your WordPress site, it is seamlessly shared across the decentralized web using the ActivityPub protocol.
![](./.wordpress-org/event-activitypub-publishing.gif)
Your events can be automatically delivered to platforms that fully support events, such as [Mobilizon](https://joinmobilizon.org/), [Gancio](https://gancio.org), [Friendica](https://friendi.ca), [Hubzilla](https://hubzilla.org), and [Pleroma](https://pleroma.social/).
These platforms create public event calendars by pulling in events from various sources, including your website. Any updates you make to your events are synced across these platforms—so you only need to manage your events on your own site, with no extra work required.
![](./.wordpress-org/decentralized-event-calenders.gif)
== Installation ==
This plugin depends on the ActivityPub plugin. Furthermore you need to use one of the supported Event Plugins. See below.
This plugin depends on the [ActivityPub plugin](https://wordpress.org/plugins/activitypub/). Additionally, you need to use one of the supported Event Plugins.
== Supported Event Plugins ==
= Supported Event Plugins =
* [The Events Calendar](https://de.wordpress.org/plugins/the-events-calendar/)
* [VS Event List](https://de.wordpress.org/plugins/very-simple-event-list/)
* [Events Manager](https://de.wordpress.org/plugins/events-manager/)
* [GatherPress](https://github.com/GatherPress/gatherpress)
== Configuration ==
At first be sure to spend some minutes reading the Documentation of the ActivityPub plugin](https://wordpress.org/plugins/activitypub/), in case you have not used it before.
TODO
If youre new to the [ActivityPub plugin](https://wordpress.org/plugins/activitypub/), its recommended to spend a few minutes reading through its documentation to familiarize yourself with its setup and functionality.
== Frequently Asked Questions ==
= Do I need to install another event plugin to use the Event Federation Plugin? =
Yes, this plugin works as an add-on and requires both the ActivityPub plugin a supported event plugin such as The Events Calendar, VS Event List, or Events Manager to manage your events.
= What platforms can follow my events? =
Your events can be followed on platforms that support ActivityPub like [Mobilizon](https://joinmobilizon.org/), [Gancio](https://gancio.org), [Friendica](https://friendi.ca), [Hubzilla](https://hubzilla.org), and [Pleroma](https://pleroma.social/). Even other applications like [Mastodon](https://joinmastodon.org), which dont fully support events yet, will display a all important information about the events.
= How much extra work is required to maintain my events across the decentralized Web? =
None! Once the plugin is set up, your events are automatically sent to all connected platforms or account that follow you (your Website). Any updates you make to your events are synced without additional effort.
= Can I still use social media to promote my events? =
Yes, you can still use traditional social media if you wish. However, this plugin helps reduce reliance on commercial platforms by connecting your events to the decentralized Fediverse.
= Will this plugin work if I don't use the ActivityPub plugin? =
No, the Event Federation Plugin depends on the [ActivityPub plugin](https://wordpress.org/plugins/activitypub/) to deliver your events across decentralized platforms, so it's essential to have it installed and configured.
= My event plugin is not supported, what can I do? =
If you know about coding have a look at the documentation of how to add your plugin or open an [issue](https://code.event-federation.eu/Event-Federation/wordpress-activitypub-event-extensions/issues), if we can spare some free hours we might add it.
= What if I experience problems? =
We're always interested in your feedback. Feel free to reach out to us via E-Mail or create an [issue](https://code.event-federation.eu/Event-Federation/wordpress-activitypub-event-extensions/issues).
We're always interested in your feedback. Feel free to reach out to us via [E-Mail](https://event-federation.eu/contact/) or create an [issue](https://code.event-federation.eu/Event-Federation/wordpress-activitypub-event-extensions/issues).
== Changelog ==
= [1.0.0] 2024-09-01 =
= [0.1.0] 2024-09-01 =
* Initial release
* Initial alpha release on WordPress.org