From 6dd511e4b0cda4b11f8e281ed74f85f5c0c771d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Thu, 12 Dec 2024 23:24:36 +0100 Subject: [PATCH 1/2] Improving detection of active event plugins: use caching and don't use WordPress internal constant WP_PLUGINS_DIR (#87) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-on: https://code.event-federation.eu/Event-Federation/wordpress-event-bridge-for-activitypub/pulls/87 Co-authored-by: André Menrath Co-committed-by: André Menrath --- CHANGELOG.md | 2 +- README.md | 2 +- event-bridge-for-activitypub.php | 2 +- .../class-event-plugin-admin-notices.php | 12 ++++- includes/admin/class-health-check.php | 6 ++- includes/admin/class-settings-page.php | 3 ++ includes/class-setup.php | 50 +++++++++++++++---- .../integrations/class-event-organiser.php | 2 +- includes/integrations/class-event-plugin.php | 10 ++-- includes/integrations/class-eventin.php | 2 +- includes/integrations/class-eventprime.php | 7 ++- .../integrations/class-events-manager.php | 2 +- includes/integrations/class-gatherpress.php | 2 +- .../class-modern-events-calendar-lite.php | 2 +- .../class-the-events-calendar.php | 2 +- includes/integrations/class-vs-event-list.php | 2 +- .../integrations/class-wp-event-manager.php | 2 +- phpcs.xml | 1 - readme.txt | 2 +- templates/settings.php | 4 +- 20 files changed, 80 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 870d722..d7e4577 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index f61876b..30f63c1 100644 --- a/README.md +++ b/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 diff --git a/event-bridge-for-activitypub.php b/event-bridge-for-activitypub.php index 4bb34cf..ec9cfad 100644 --- a/event-bridge-for-activitypub.php +++ b/event-bridge-for-activitypub.php @@ -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.1 + * Version: 0.3.2 * Author: André Menrath * Author URI: https://graz.social/@linos * Text Domain: event-bridge-for-activitypub diff --git a/includes/admin/class-event-plugin-admin-notices.php b/includes/admin/class-event-plugin-admin-notices.php index 823472e..cb4af54 100644 --- a/includes/admin/class-event-plugin-admin-notices.php +++ b/includes/admin/class-event-plugin-admin-notices.php @@ -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( diff --git a/includes/admin/class-health-check.php b/includes/admin/class-health-check.php index 61faa18..45d4ea0 100644 --- a/includes/admin/class-health-check.php +++ b/includes/admin/class-health-check.php @@ -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'; diff --git a/includes/admin/class-settings-page.php b/includes/admin/class-settings-page.php index 3a3903f..e901064 100644 --- a/includes/admin/class-settings-page.php +++ b/includes/admin/class-settings-page.php @@ -97,6 +97,9 @@ class Settings_Page { $tab = sanitize_key( $_GET['tab'] ); } + // Fallback to always re-scan active event plugins, when user visits admin area of this plugin. + Setup::get_instance()->redetect_active_event_plugins(); + switch ( $tab ) { case 'settings': $plugin_setup = Setup::get_instance(); diff --git a/includes/class-setup.php b/includes/class-setup.php index ce6afc4..f75721f 100644 --- a/includes/class-setup.php +++ b/includes/class-setup.php @@ -67,9 +67,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' ) ); } /** @@ -106,8 +105,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'; } /** @@ -136,23 +134,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; } @@ -165,9 +187,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' ) ); @@ -303,6 +330,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 ) ); diff --git a/includes/integrations/class-event-organiser.php b/includes/integrations/class-event-organiser.php index 9278f43..0fbd190 100644 --- a/includes/integrations/class-event-organiser.php +++ b/includes/integrations/class-event-organiser.php @@ -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'; } diff --git a/includes/integrations/class-event-plugin.php b/includes/integrations/class-event-plugin.php index 56d020a..c5e7c40 100644 --- a/includes/integrations/class-event-plugin.php +++ b/includes/integrations/class-event-plugin.php @@ -24,11 +24,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. @@ -57,9 +57,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 ''; } diff --git a/includes/integrations/class-eventin.php b/includes/integrations/class-eventin.php index 6ce88a6..364a2a8 100644 --- a/includes/integrations/class-eventin.php +++ b/includes/integrations/class-eventin.php @@ -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'; } diff --git a/includes/integrations/class-eventprime.php b/includes/integrations/class-eventprime.php index af78347..a50f7ff 100644 --- a/includes/integrations/class-eventprime.php +++ b/includes/integrations/class-eventprime.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' ); diff --git a/includes/integrations/class-events-manager.php b/includes/integrations/class-events-manager.php index 2f22620..9208126 100644 --- a/includes/integrations/class-events-manager.php +++ b/includes/integrations/class-events-manager.php @@ -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'; } diff --git a/includes/integrations/class-gatherpress.php b/includes/integrations/class-gatherpress.php index 57cd222..f68fbbc 100644 --- a/includes/integrations/class-gatherpress.php +++ b/includes/integrations/class-gatherpress.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'; } diff --git a/includes/integrations/class-modern-events-calendar-lite.php b/includes/integrations/class-modern-events-calendar-lite.php index 02329ae..95bfef7 100644 --- a/includes/integrations/class-modern-events-calendar-lite.php +++ b/includes/integrations/class-modern-events-calendar-lite.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'; } diff --git a/includes/integrations/class-the-events-calendar.php b/includes/integrations/class-the-events-calendar.php index 42d295e..6f6e17b 100644 --- a/includes/integrations/class-the-events-calendar.php +++ b/includes/integrations/class-the-events-calendar.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'; } diff --git a/includes/integrations/class-vs-event-list.php b/includes/integrations/class-vs-event-list.php index 6ce4ba6..dc2747d 100644 --- a/includes/integrations/class-vs-event-list.php +++ b/includes/integrations/class-vs-event-list.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'; } diff --git a/includes/integrations/class-wp-event-manager.php b/includes/integrations/class-wp-event-manager.php index 18c217d..2adc473 100644 --- a/includes/integrations/class-wp-event-manager.php +++ b/includes/integrations/class-wp-event-manager.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'; } diff --git a/phpcs.xml b/phpcs.xml index 7839664..7d2da1f 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -109,7 +109,6 @@ - diff --git a/readme.txt b/readme.txt index 3386f69..eb89bf1 100644 --- a/readme.txt +++ b/readme.txt @@ -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 diff --git a/templates/settings.php b/templates/settings.php index 2c9c077..9623eca 100644 --- a/templates/settings.php +++ b/templates/settings.php @@ -48,7 +48,7 @@ $current_category_mapping = \get_option( 'event_bridge_for_activitypub_ev

- +
[ap_start_time]
From 16b3c1402ea927d5e5ea29adbb2c0e1f4dd44e61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Thu, 12 Dec 2024 23:35:00 +0100 Subject: [PATCH 2/2] Bump version to 0.3.2 --- README.md | 10 ++-------- readme.txt | 4 ++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 30f63c1..83c871f 100644 --- a/README.md +++ b/README.md @@ -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/ diff --git a/readme.txt b/readme.txt index eb89bf1..35b33d0 100644 --- a/readme.txt +++ b/readme.txt @@ -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/