WIP: Add Event Sources Logic (ActivityPub follows) #86
20 changed files with 84 additions and 48 deletions
|
@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
* Add custom summary via shortcodes
|
||||
|
||||
## [0.3.1] - 2024-11-16
|
||||
## [0.3.2] - 2024-12-12
|
||||
|
||||
* Initial release on WordPress.org
|
||||
|
||||
|
|
12
README.md
12
README.md
|
@ -3,7 +3,7 @@
|
|||
**Tags:** events, fediverse, activitypub, calendar
|
||||
**Requires at least:** 6.5
|
||||
**Tested up to:** 6.7
|
||||
**Stable tag:** 0.3.1
|
||||
**Stable tag:** 0.3.2
|
||||
**Requires PHP:** 7.4
|
||||
**License:** AGPL-3.0-or-later
|
||||
**License URI:** https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
@ -44,7 +44,7 @@ The Event Federation plugin ensures that users from those platforms are provided
|
|||
|
||||
**ActivityPub-Enabled Event Sharing:** Your WordPress events are now compatible with the Fediverse, using the ActivityStreams format. This means your events can be easily discovered and followed by users on platforms like Mastodon and other ActivityPub-compatible services.
|
||||
|
||||
**Automatic Event Summaries:** When your event is shared on the Fediverse, platforms like Mastodon that don't fully support events will display a brief HTML summary of key details — such as the event's title, start time, and location. This ensures that even if someone can't view the full event on their platform, they still get the important info at a glance, with a link to your WordPress event page.
|
||||
**Automatic Event Summaries:** When your event is shared on the Fediverse, platforms like Mastodon that don't fully support events will display a brief HTML summary of key details — such as the event's title, start time, and location. This ensures that even if someone can't view the full event on their platform, they still get the important info at a glance, with a link to your WordPress event page. Advanced users can create custom summaries via a set of shortcodes.
|
||||
|
||||
**Improved Event Discoverability:** Your custom event categories are mapped to a set of default categories used in the Fediverse, helping your events reach a wider audience. This improves the chances that users searching for similar events on other platforms will find yours.
|
||||
|
||||
|
@ -102,13 +102,7 @@ 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 ###
|
||||
### [0.3.2] 2024-12-12 ###
|
||||
|
||||
* Initial release on https://wordpress.org/
|
||||
|
||||
|
|
|
@ -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.3
|
||||
* Version: 0.3.2
|
||||
* Author: André Menrath
|
||||
* Author URI: https://graz.social/@linos
|
||||
* Text Domain: event-bridge-for-activitypub
|
||||
|
|
|
@ -69,7 +69,15 @@ class Event_Plugin_Admin_Notices {
|
|||
* @return void
|
||||
*/
|
||||
private function do_admin_notice_post_type_not_activitypub_enabled(): void {
|
||||
$event_plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $this->event_plugin::get_plugin_file() );
|
||||
$all_plugins = get_plugins();
|
||||
$event_plugin_file = $this->event_plugin::get_relative_plugin_file();
|
||||
if ( isset( $all_plugins[ $event_plugin_file ]['Name'] ) ) {
|
||||
$event_plugin_name = $all_plugins[ $event_plugin_file ]['Name'];
|
||||
} elseif ( isset( get_mu_plugins()[ $event_plugin_file ]['Name'] ) ) {
|
||||
$event_plugin_name = get_mu_plugins()[ $event_plugin_file ]['Name'];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
$activitypub_plugin_data = get_plugin_data( ACTIVITYPUB_PLUGIN_FILE );
|
||||
$notice = sprintf(
|
||||
/* translators: 1: the name of the event plugin a admin notice is shown. 2: The name of the ActivityPub plugin. */
|
||||
|
@ -79,7 +87,7 @@ class Event_Plugin_Admin_Notices {
|
|||
'event-bridge-for-activitypub'
|
||||
),
|
||||
esc_html( $activitypub_plugin_data['Name'] ),
|
||||
esc_html( $event_plugin_data['Name'] ),
|
||||
esc_html( $event_plugin_name ),
|
||||
admin_url( 'options-general.php?page=activitypub&tab=settings' )
|
||||
);
|
||||
$allowed_html = array(
|
||||
|
|
|
@ -114,7 +114,9 @@ class Health_Check {
|
|||
*/
|
||||
public static function get_most_recent_event_posts( $event_post_type = null, $number_of_posts = 5 ) {
|
||||
if ( ! $event_post_type ) {
|
||||
$event_post_type = Setup::get_instance()->get_active_event_plugins()[0]->get_post_type();
|
||||
$active_event_plugins = Setup::get_instance()->get_active_event_plugins();
|
||||
$active_event_plugin = reset( $active_event_plugins );
|
||||
$event_post_type = $active_event_plugin->get_post_type();
|
||||
}
|
||||
|
||||
$args = array(
|
||||
|
@ -148,7 +150,7 @@ class Health_Check {
|
|||
$active_event_plugins = Setup::get_instance()->get_active_event_plugins();
|
||||
$info = array();
|
||||
foreach ( $active_event_plugins as $active_event_plugin ) {
|
||||
$event_plugin_file = $active_event_plugin->get_plugin_file();
|
||||
$event_plugin_file = $active_event_plugin->get_relative_plugin_file();
|
||||
$event_plugin_data = \get_plugin_data( $event_plugin_file );
|
||||
$event_plugin_name = isset( $event_plugin_data['Plugin Name'] ) ? $event_plugin_data['Plugin Name'] : 'Name not found';
|
||||
$event_plugin_version = isset( $event_plugin_version['Plugin Version'] ) ? $event_plugin_version['Plugin Version'] : 'Version not found';
|
||||
|
|
|
@ -162,7 +162,9 @@ class Settings_Page {
|
|||
$tab = sanitize_key( $_GET['tab'] );
|
||||
}
|
||||
|
||||
$plugin_setup = Setup::get_instance();
|
||||
// Fallback to always re-scan active event plugins, when user visits admin area of this plugin.
|
||||
$plugin_setup = Setup::get_instance();
|
||||
$plugin_setup->redetect_active_event_plugins();
|
||||
$event_plugins = $plugin_setup->get_active_event_plugins();
|
||||
|
||||
switch ( $tab ) {
|
||||
|
|
|
@ -70,9 +70,8 @@ class Setup {
|
|||
// deactivate_plugins( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE );
|
||||
// return;
|
||||
// }.
|
||||
$this->active_event_plugins = self::detect_active_event_plugins();
|
||||
$this->activitypub_plugin_version = self::get_activitypub_plugin_version();
|
||||
$this->setup_hooks();
|
||||
add_action( 'plugins_loaded', array( $this, 'setup_hooks' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,8 +108,7 @@ class Setup {
|
|||
if ( defined( 'ACTIVITYPUB_PLUGIN_VERSION' ) ) {
|
||||
return constant( 'ACTIVITYPUB_PLUGIN_VERSION' );
|
||||
}
|
||||
$version = get_file_data( WP_PLUGIN_DIR . '/activitypub/activitypub.php', array( 'Version' ) )[0];
|
||||
return $version ?? '0.0.0';
|
||||
return '0.0.0';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,23 +137,47 @@ class Setup {
|
|||
'\Event_Bridge_For_ActivityPub\Integrations\Event_Organiser',
|
||||
);
|
||||
|
||||
/**
|
||||
* Force the re-scan for active event plugins without using the cached transient.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function redetect_active_event_plugins(): void {
|
||||
delete_transient( 'event_bridge_for_activitypub_active_event_plugins' );
|
||||
$this->detect_active_event_plugins();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that checks for supported activated event plugins.
|
||||
*
|
||||
* @return array List of supported event plugins as keys from the SUPPORTED_EVENT_PLUGINS const.
|
||||
*/
|
||||
public static function detect_active_event_plugins(): array {
|
||||
$active_event_plugins = array();
|
||||
public function detect_active_event_plugins(): array {
|
||||
$active_event_plugins = get_transient( 'event_bridge_for_activitypub_active_event_plugins' );
|
||||
|
||||
if ( $active_event_plugins ) {
|
||||
$this->active_event_plugins = $active_event_plugins;
|
||||
return $active_event_plugins;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'get_plugins' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
$all_plugins = array_merge( get_plugins(), get_mu_plugins() );
|
||||
|
||||
$active_event_plugins = array();
|
||||
foreach ( self::EVENT_PLUGIN_CLASSES as $event_plugin_class ) {
|
||||
if ( ! class_exists( $event_plugin_class ) || ! method_exists( $event_plugin_class, 'get_plugin_file' ) ) {
|
||||
$event_plugin_file = call_user_func( array( $event_plugin_class, 'get_relative_plugin_file' ) );
|
||||
if ( ! $event_plugin_file ) {
|
||||
continue;
|
||||
}
|
||||
$event_plugin_file = call_user_func( array( $event_plugin_class, 'get_plugin_file' ) );
|
||||
if ( \is_plugin_active( $event_plugin_file ) ) {
|
||||
$active_event_plugins[] = new $event_plugin_class();
|
||||
if ( array_key_exists( $event_plugin_file, $all_plugins ) && \is_plugin_active( $event_plugin_file ) ) {
|
||||
$active_event_plugins[ $event_plugin_file ] = new $event_plugin_class();
|
||||
}
|
||||
}
|
||||
set_transient( 'event_bridge_for_activitypub_active_event_plugins', $active_event_plugins );
|
||||
$this->active_event_plugins = $active_event_plugins;
|
||||
return $active_event_plugins;
|
||||
}
|
||||
|
||||
|
@ -187,9 +209,14 @@ class Setup {
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setup_hooks(): void {
|
||||
public function setup_hooks(): void {
|
||||
$this->detect_active_event_plugins();
|
||||
|
||||
register_activation_hook( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE, array( $this, 'activate' ) );
|
||||
|
||||
add_action( 'activated_plugin', array( $this, 'redetect_active_event_plugins' ) );
|
||||
add_action( 'deactivated_plugin', array( $this, 'redetect_active_event_plugins' ) );
|
||||
|
||||
add_action( 'admin_init', array( $this, 'do_admin_notices' ) );
|
||||
add_action( 'admin_init', array( Settings::class, 'register_settings' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_styles' ) );
|
||||
|
@ -332,6 +359,7 @@ class Setup {
|
|||
* @return void
|
||||
*/
|
||||
public function activate(): void {
|
||||
$this->redetect_active_event_plugins();
|
||||
// Don't allow plugin activation, when the ActivityPub plugin is not activated yet.
|
||||
if ( ! $this->activitypub_plugin_is_active ) {
|
||||
deactivate_plugins( plugin_basename( EVENT_BRIDGE_FOR_ACTIVITYPUB_PLUGIN_FILE ) );
|
||||
|
|
|
@ -27,7 +27,7 @@ final class Event_Organiser extends Event_Plugin {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_plugin_file(): string {
|
||||
public static function get_relative_plugin_file(): string {
|
||||
return 'event-organiser/event-organiser.php';
|
||||
}
|
||||
|
||||
|
|
|
@ -25,11 +25,11 @@ defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
|||
*/
|
||||
abstract class Event_Plugin {
|
||||
/**
|
||||
* Returns the full plugin file.
|
||||
* Returns the plugin file relative to the plugins dir.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public static function get_plugin_file(): string;
|
||||
abstract public static function get_relative_plugin_file(): string;
|
||||
|
||||
/**
|
||||
* Returns the event post type of the plugin.
|
||||
|
@ -67,9 +67,9 @@ abstract class Event_Plugin {
|
|||
* Get the plugins name from the main plugin-file's top-level-file-comment.
|
||||
*/
|
||||
final public static function get_plugin_name(): string {
|
||||
$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . static::get_plugin_file() );
|
||||
if ( isset( $plugin_data['Name'] ) ) {
|
||||
return $plugin_data['Name'];
|
||||
$all_plugins = array_merge( get_plugins(), get_mu_plugins() );
|
||||
if ( isset( $all_plugins[ static::get_relative_plugin_file() ]['Name'] ) ) {
|
||||
return $all_plugins[ static::get_relative_plugin_file() ]['Name'];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ final class Eventin extends Event_plugin {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_plugin_file(): string {
|
||||
public static function get_relative_plugin_file(): string {
|
||||
return 'wp-event-solution/eventin.php';
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ final class EventPrime extends Event_Plugin {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_plugin_file(): string {
|
||||
public static function get_relative_plugin_file(): string {
|
||||
return 'eventprime-event-calendar-management/event-prime.php';
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,9 @@ final class EventPrime extends Event_Plugin {
|
|||
|
||||
/**
|
||||
* Determine whether the current request is an EventPrime ActivityPub request.
|
||||
*
|
||||
* Forked from https://github.com/Automattic/wordpress-activitypub/blob/trunk/includes/functions.php
|
||||
* the function is_activitypub_request.
|
||||
*/
|
||||
private static function is_eventprime_activitypub_request() {
|
||||
global $wp_query;
|
||||
|
@ -192,7 +195,7 @@ final class EventPrime extends Event_Plugin {
|
|||
* @see https://www.w3.org/wiki/SocialCG/ActivityPub/Primer/Authentication_Authorization#Authorized_fetch
|
||||
* @see https://swicg.github.io/activitypub-http-signature/#authorized-fetch
|
||||
*/
|
||||
if ( $activitypub_template && ACTIVITYPUB_AUTHORIZED_FETCH ) {
|
||||
if ( $activitypub_template && defined( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) && constant( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) ) {
|
||||
$verification = Signature::verify_http_signature( $_SERVER );
|
||||
if ( \is_wp_error( $verification ) ) {
|
||||
header( 'HTTP/1.1 401 Unauthorized' );
|
||||
|
|
|
@ -27,7 +27,7 @@ final class Events_Manager extends Event_Plugin {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_plugin_file(): string {
|
||||
public static function get_relative_plugin_file(): string {
|
||||
return 'events-manager/events-manager.php';
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ final class GatherPress extends Event_Plugin {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_plugin_file(): string {
|
||||
public static function get_relative_plugin_file(): string {
|
||||
return 'gatherpress/gatherpress.php';
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ final class Modern_Events_Calendar_Lite extends Event_plugin {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_plugin_file(): string {
|
||||
public static function get_relative_plugin_file(): string {
|
||||
return 'modern-events-calendar-lite/modern-events-calendar-lite.php';
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ final class The_Events_Calendar extends Event_plugin {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_plugin_file(): string {
|
||||
public static function get_relative_plugin_file(): string {
|
||||
return 'the-events-calendar/the-events-calendar.php';
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ final class VS_Event_List extends Event_Plugin {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_plugin_file(): string {
|
||||
public static function get_relative_plugin_file(): string {
|
||||
return 'very-simple-event-list/vsel.php';
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ final class WP_Event_Manager extends Event_Plugin {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_plugin_file(): string {
|
||||
public static function get_relative_plugin_file(): string {
|
||||
return 'wp-event-manager/wp-event-manager.php';
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,6 @@
|
|||
<properties>
|
||||
<property name="text_domain" type="array">
|
||||
<element value="event-bridge-for-activitypub"/>
|
||||
<element value="activitypub"/>
|
||||
</property>
|
||||
</properties>
|
||||
</rule>
|
||||
|
|
|
@ -3,7 +3,7 @@ Contributors: andremenrath
|
|||
Tags: events, fediverse, activitypub, calendar
|
||||
Requires at least: 6.5
|
||||
Tested up to: 6.7
|
||||
Stable tag: 0.3.1
|
||||
Stable tag: 0.3.2
|
||||
Requires PHP: 7.4
|
||||
License: AGPL-3.0-or-later
|
||||
License URI: https://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
@ -38,7 +38,7 @@ The Event Federation plugin ensures that users from those platforms are provided
|
|||
|
||||
**ActivityPub-Enabled Event Sharing:** Your WordPress events are now compatible with the Fediverse, using the ActivityStreams format. This means your events can be easily discovered and followed by users on platforms like Mastodon and other ActivityPub-compatible services.
|
||||
|
||||
**Automatic Event Summaries:** When your event is shared on the Fediverse, platforms like Mastodon that don't fully support events will display a brief HTML summary of key details — such as the event's title, start time, and location. This ensures that even if someone can't view the full event on their platform, they still get the important info at a glance, with a link to your WordPress event page.
|
||||
**Automatic Event Summaries:** When your event is shared on the Fediverse, platforms like Mastodon that don't fully support events will display a brief HTML summary of key details — such as the event's title, start time, and location. This ensures that even if someone can't view the full event on their platform, they still get the important info at a glance, with a link to your WordPress event page. Advanced users can create custom summaries via a set of shortcodes.
|
||||
|
||||
**Improved Event Discoverability:** Your custom event categories are mapped to a set of default categories used in the Fediverse, helping your events reach a wider audience. This improves the chances that users searching for similar events on other platforms will find yours.
|
||||
|
||||
|
@ -96,6 +96,6 @@ We're always interested in your feedback. Feel free to reach out to us via [E-Ma
|
|||
|
||||
== Changelog ==
|
||||
|
||||
= [0.3.1] 2024-12-05 =
|
||||
= [0.3.2] 2024-12-12 =
|
||||
|
||||
* Initial release on https://wordpress.org/
|
||||
|
|
|
@ -58,7 +58,7 @@ $current_category_mapping = \get_option( 'event_bridge_for_activitypub_ev
|
|||
<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' ); ?>
|
||||
<?php \esc_html_e( 'Automatic (default)', 'event-bridge-for-activitypub' ); ?>
|
||||
-
|
||||
<span class="description">
|
||||
<?php \esc_html_e( 'Let the plugin compose a summary for you. ', 'event-bridge-for-activitypub' ); ?>
|
||||
|
@ -78,7 +78,7 @@ $current_category_mapping = \get_option( 'event_bridge_for_activitypub_ev
|
|||
<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>
|
||||
<summary><?php esc_html_e( 'See a list Template Tags available for the summary.', 'event-bridge-for-activitypub' ); ?></summary>
|
||||
<div class="description">
|
||||
<dl>
|
||||
<dt><code>[ap_start_time]</code><dt>
|
||||
|
|
Loading…
Reference in a new issue